Subject: RFC: framebuffer device support in NetBSD - v0.05
To: None <tech-kern@netbsd.org>
From: Reinoud Zandijk <reinoud@netbsd.org>
List: tech-kern
Date: 09/25/2002 23:24:58
--envbJBWh7q8WU6mo
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hiya folks,

as promised an updated version of my proposal for a framebuffer device for 
NetBSD. I've tried to incorporate as much feedback as i could but tried to 
not work it all out in detail yet.

Feel free to react :) only please read it first before aiming !

Cheers,
Reinoud



--envbJBWh7q8WU6mo
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=framebuffer-proposal-netbsd


		Framebuffer-device proposal for NetBSD/*
		----------------------------------------
		
Reinoud Zandijk (reinoud@netbsd.org)
24 September 2002
version 0.05 - second draft, unfinished


Abstract:

Proposal for the implementation of a framebuffer device under all NetBSD
architectures capable of displaying graphics presenting a machine and
architecture indepenent access to one or more framebuffer devices as an
_extension_ to the current wscons infrastructure including hardware
accelerations where possible.

The programmers interface for userland-applications could be modelled to
resemble the framebuffer device as currently implemented in Linux 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 either neglected or treated by
the kernel as text console devices.

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 too and
provide *proprietary* interfaces towards their associated 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.

Allthough allmost cursing on these lists, there is a notorius exeption on this
`rule' that is the Linux framebuffer device. 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.

Other alternatives to learn from are propably the now allmost dead KGI project
that didnt get a `go' from Linus. This project has some good ideas but is
effectively `dead' considering the extreme few activities going on.

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 attempts were made in the KGI project to abstract
the acceleration as much as possilbe. It could be given some thought
nevertheless in the overall design. Rumers are that a FreeBSD port is being
worked on too.



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

This proposal consist of an extension on the current wscons structure and not
as an replacement. The current wscons structure allows for tty abstraction,
keyboard abstraction and display abstraction. This last part, the display
abstraction is very under-developed though and has no information about for
example byte encoding, bit depths per channel, line interleave etc.

At the minimum, it is nessisary to extend the current WSDISPLAYIO_GINFO ioctl
framework to a much more detailed ioctl. Choice is between either suporting
several small set and get ioctl's or to provide an ioctl interface that allows
parameters to be retrieved and updated.

The second strategy could be to provide the requested information into at
least two seperate chunks : the fixed information and the variable screen
information. Thus creating WSDISPLAYIO_GINFO_SCREEN_FIXED,
WSDISPLAYIO_GINFO_SCREEN_VARIABLE and WSDISPLAY_SINFO_VARIABLE ioctls.

If a card supports 2D accelleration functions these can be accessed using a
virtualised acceleration engine that translates the commands to register
values specific to the graphic card. For accelerated functions the writev(2)
system can be used to ensure block based commands to be written either in
single issues or in a sequence. If a card doesn't support 2D acceleration
functions the framebuffer driver can still emulate them at a speed cost but
tailored to the system.

Drivers for the various dedicated framebuffer based architectures like the DEC
Pmax, the Acorn32 and the Sun sparcs framebuffers allready exist and are
in-kernel allready. These framebuffer drivers can be used as prototype systems
to develop the API.

The implementation for PCI graphic card devices and such ought not to be a
huge problem. Example code to identify, configure an query these can be found
in the current XF86 drivers and in the KGI project. 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.

A small survey in KGI turns out that most cards are mostly build out of
different combinations of just a few standard chips with possibly different
offsets. These can be parameterised in a detection list of `known' graphic
cards and their features. Using the table in this way we can thus detect and
support lots of graphic cards while only needing support for a limited set of
chips.



References :

Linux 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

The KGI project curently residing at http://kgi.sourceforge.com



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.

Pedro Giffuni <giffunip@yahoo.com> for pointing me out to KGI :-D



-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-

Appendix A : 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!



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 */
};



-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-o-


--envbJBWh7q8WU6mo--