Subject: RFC: framebuffer device support in NetBSD
To: None <tech-x11@netbsd.org>
From: Reinoud Zandijk <reinoud@netbsd.org>
List: tech-x11
Date: 09/13/2002 02:18:40
Hiya folks,

hereunder you'll find a first draft for framebuffer device support in 
NetBSD profiled along the Linux framebuffer device. See it as a first step 
on the road and a plea....

Cheers,
Reinoud

P.S. since i am not subscribed to tech-kern and tech-x11, please also CC 
me.


		Framebuffer-device proposal for NetBSD/*
		----------------------------------------
		
Reinoud Zandijk (reinoud@netbsd.org)
12 September 2002
version 0.01 - first draft, unfinished


Abstract:

Proposal for the implementation of a /dev/fb device under all NetBSD
architectures capable of displaying graphics for a machine and architecture
indepenent access to one or more framebuffer devices including support for
hardware accelerations where possible. The interface to this device from
userland can be modelled as much as posible to the framebuffer devices as
currently found in the Linux operating system if desired for compatibility
reasons or in a more generic way when proven nessisary.



Introduction:

Framebuffers in *BSD operating systems are treated very differently from other
devices like disc controllers, PCI bridge controllers and network cards. Where
all kinds of network cards get their own associated driver, graphic cards in
contrast, especially PCI/ISA devices, generally are only set up by the
computers BIOS or similar part and further neglected. Non PCI/ISA framebuffers
like the pmax's framebuffer or the Acorn's VIDC framebuffer are set up in the
kernel and used for console display only and provide proprietary interfaces
towards the X windowing sytem.

The reason for this neglect of framebuffers is propably that framebuffer
devices are considered to be strange critters and are to be dealt with with
the X windowing system alone.  Sure the X windowing system has brought a
defacto standard for getting graphic content on a display but its mere
presence also prohibited initiatives towards more generic graphic framebuffer
devicedriver development.

A notorius exeption on this `rule' is the Linux framebuffer device that
propably evolved from the svga-lib experiment. This Linux framebuffer device
allows a program to not only mmap() the framebuffer but also allows the
program to configure the display to be in a specified colour depth, screensize
etc. all independent of the graphic card present.

One of the sucesses of M$ Windows lately has been the device independent
drivers for graphic cards and 3D acceleration wich used to be notorious
problems on PC architectures. Now 3D acceleration is propably a bit out of
scope of this proposal but it could be given some thought nevertheless.

In the following sections i'll first describe the current status of the Linux
framebuffer device, its implementation and limits followed by a summation of
various framebuffer like devices allready found in NetBSD and their
implementation and concluding with my proposal for a satisfactory BSD
solution, its implementation and its merits/problems.



Linux framebuffer device:

The Linux framebuffer device is a device that is accesible to userland trough
character devices in /dev and behaves just like `normal' memory memory devices
like a ramdisc or kmem. Typically it allows to manipulate multiple
framebuffers on one machine by encoding them into the minor device number. The
devices are typically named /dev/fb0, /dev/fb1 etc. The simplest way to make a
screendump is f.e. is `cp /dev/fb0 myscreendump.raw'.

The Linux framebuffer device also implements various ioctl() calls by which
lots of information about the hardware can be queried or set. Information like
screenorganisation (packed pickel, bitdepth, rgb or bgr, bitfield
organisation, endian etc), screen geometry, colourmap organisation etc etc.
The requested information can also be changed and written back using the
ioctl() calls and the driver responsable will try to match the screen as close
as possible or return EINVAL otherwise.

Video modes can be changed from the commandline using a `fbset' utility which
reads a configurationfile stored in the `/etc/fb.modes' file. This file can be
architecture dependent if nessisary.

Since userland programs using the framebuffer device like f.e. `direct-GTK'
work on the raw framebuffer directly, they offcource have to support the
various display organisations in order to display comprehensable images.

There is allready a X server capable of driving the Linux framebuffer device,
called XF86_FBDev and is included in the standard XFree86 release from version
3.2.

In Linux 2.4 drivers for the following graphic cards are allready included :
	- ATI Rage 128 based devices
	- Cirrus Logic chipsets (SD64, Piccolo, Spectrum, Alpine (GD-543x/4x),
	  Picasso4 (GD-5446), GD-5480, Laguna (GD-546x)
	- Matrox devices (with some acceleration and heaps of features)
	- Graphic framebuffer for the SA-1100 as found in many portable
	  devices.
	- TGA drivers (DECChip 21030)
	- Generic VESA for VESA BIOS 2.0 or later.
	- nVidia cards (Linux 2.5 and newer?)
	- ....

Communcation to userland is done using the following structures :
	- struct fb_fix_screeninfo
		Device indendent unchangeable information about the
		framebuffer device itself and a specific video mode. This can
		be obtained using the FBIOGET_FSCREENINFO ioctl.
	- struct fb_var_screeninfo
		Device independent changeable information obtained by
		FBIOGET_VSCREENINFO ioctl and written by FBIOPUT_VSCREENINFO.
		Panning can be done seperately by calling the FBIOPAN_DISPLAY
		ioctl.
	- struct fb_cmap
		Device independent colourmap information that can be read
		using the FBIOGETCMAP anbd FBIOPUTCMAP ioctls.
	- struct { fb_fix_cursorinfo, fb_var_cursorinfo, fb_cursorstate } :
		Preliminary interface for hardware cursor support in Lin. 2.5.

The visuals used by the Linux framebuffer device API are related to the X
visuals in that there is support for Monochrome, Pseudocolour, True color,
Direct colour and grayscale classes.

In the Linux drivers there are allready accelerated functions implemented but
not exported by a ioctl yet. The framebuffer cardtype is exported though as is
the memory mapped I/O address so applications can effectively accelerate when
they have the knowledge of the card. So accelerated X servers can even be
build on top of it too!



Proposal for framebuffer device support in NetBSD (or *BSD in general) :

My initial proposal is to follow the Linux interface as much as possible since
it looks pretty sane for now. Ofcource the ioctl() number is bound to be
different under NetBSD but as long as the ioctl() names are the same
compilation time compatibility shouldn't be a problem.

The implementation ought not to be a huge problem allthough the actual drivers
as found in the Linux kernel are propably GPL'd and very Linux bound. They
propably have to be rewritten but since most of the `research' is allready
done it ought to be straitforward to acomplish.

Inside the kernel these framebuffer drivers can also be used for the graphic
wscons project currently underway. The implemented acceleration functions can
then also be used for faster wscons scrolling on these terminals.



References :

Framebuffer HOWTO written by Alex Buell <alex.buell@tahallah.clara.co.uk>
found at http://www.ibiblio.org/pub/Linux/docs/HOWTO/other-formats/html_single/Framebuffer-HOWTO.html

Framebuffer defines in <linux/fb.h>.



Acknowledgements/Credits :

Geert Uytterhoeven <geert@linux-m68k.org>, Roman Hodek and Martin Schaller for
the document about the Linux framebuffer device.

Martin Schaller for the Linux framebuffer device abstraction design.



Apendix containing some definitions from <linux/fb.h> (by Martin Schaller) :

struct fb_fix_screeninfo {
        char id[16];                    /* identification string eg "TT Builtin" */
        unsigned long smem_start;       /* Start of frame buffer mem */ 
                                        /* (physical address) */
        __u32 smem_len;                 /* Length of frame buffer mem */  
        __u32 type;                     /* see FB_TYPE_*                */
        __u32 type_aux;                 /* Interleave for interleaved Planes */
        __u32 visual;                   /* see FB_VISUAL_*              */
        __u16 xpanstep;                 /* zero if no hardware panning  */ 
        __u16 ypanstep;                 /* zero if no hardware panning  */ 
        __u16 ywrapstep;                /* zero if no hardware ywrap    */
        __u32 line_length;              /* length of a line in bytes    */
        unsigned long mmio_start;       /* Start of Memory Mapped I/O   */
                                        /* (physical address) */
        __u32 mmio_len;                 /* Length of Memory Mapped I/O  */
        __u32 accel;                    /* Type of acceleration available */
        __u16 reserved[3];              /* Reserved for future compatibility */
};

struct fb_bitfield {
        __u32 offset;                   /* beginning of bitfield        */ 
        __u32 length;                   /* length of bitfield           */
        __u32 msb_right;                /* != 0 : Most significant bit is */
                                        /* right */
};      

struct fb_var_screeninfo {              
        __u32 xres;                     /* visible resolution           */  
        __u32 yres;
        __u32 xres_virtual;             /* virtual resolution           */
        __u32 yres_virtual;
        __u32 xoffset;                  /* offset from virtual to visible */ 
        __u32 yoffset;                  /* resolution                   */
 
        __u32 bits_per_pixel;           /* guess what                   */
        __u32 grayscale;                /* != 0 Graylevels instead of colors */
   
        struct fb_bitfield red;         /* bitfield in fb mem if true color, */
        struct fb_bitfield green;       /* else only length is significant */
        struct fb_bitfield blue;        
        struct fb_bitfield transp;      /* transparency                 */  
                                        
        __u32 nonstd;                   /* != 0 Non standard pixel format */

        __u32 activate;                 /* see FB_ACTIVATE_*            */

        __u32 height;                   /* height of picture in mm    */
        __u32 width;                    /* width of picture in mm     */   

        __u32 accel_flags;              /* acceleration flags (hints)   */
                                        
        /* Timing: All values in pixclocks, except pixclock (of course) */
        __u32 pixclock;                 /* pixel clock in ps (pico seconds) */
        __u32 left_margin;              /* time from sync to picture    */
        __u32 right_margin;             /* time from picture to sync    */
        __u32 upper_margin;             /* time from sync to picture    */
        __u32 lower_margin;
        __u32 hsync_len;                /* length of horizontal sync    */
        __u32 vsync_len;                /* length of vertical sync      */
        __u32 sync;                     /* see FB_SYNC_*                */
        __u32 vmode;                    /* see FB_VMODE_*               */
        __u32 reserved[6];              /* Reserved for future compatibility */
};

struct fb_cmap {
        __u32 start;                    /* First entry  */
        __u32 len;                      /* Number of entries */
        __u16 *red;                     /* Red values   */
        __u16 *green;
        __u16 *blue;
        __u16 *transp;                  /* transparency, can be NULL */
};

----------------- end -------------------------