This is the mail archive of the ecos-patches@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

framebuffer contribution


This patch is a contribution of eCosCentric's generic framebuffer
support. The original driving force behind this code was to facilitate
porting of Swell Software's PEG and C/PEG libraries. However the code
is general-purpose and should be readily usable for porting other
higher-level graphics libraries, or for use directly by application
code.

The current code is incomplete in various ways. It only supports
displays with depths of 8 bits/pixel, 16bpp or 32bpp. The design also
allows for 1bpp, 2bpp and 4bpp displays but there is no implementation
yet for these. An important optimization for double-buffered displays,
bounding boxes, is still missing. However, within these limitations,
the code has already proved valuable.

A reference device driver will follow soon.

Bart

Index: ChangeLog
===================================================================
RCS file: ChangeLog
diff -N ChangeLog
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ChangeLog	7 Oct 2008 10:02:55 -0000
@@ -0,0 +1,68 @@
+2008-10-06 Bart Veer  <bartv@ecoscentric.com>
+
+	* src/gen_framebufs.tcl, cdl/framebuf.cdl, tests/*: add some
+	examples/testcases.
+
+2007-10-11  Bart Veer  <bartv@ecoscentric.com>
+
+	* include/framebuf.h: fix 555 true colour manipulation macros.
+
+2006-04-05  John Dallaway  <jld@ecoscentric.com>
+
+	* cdl/framebuf.cdl: Add reference to package documentation.
+
+2005-11-21  Bart Veer  <bartv@ecoscentric.com>
+
+	* include/framebuf.h, src/framebuf.c: fix aliasing of the
+	make/break colour functions, needed with more recent compilers.
+
+	* doc/framebuf.sgml: fix blanking support typo
+
+	* cdl/framebuf.cdl: run gen_framebufs.tcl slightly later
+	in the build process in case other packages create framebuf header
+	files at build-time.
+
+	* src/gen_framebufs.tcl: fix typo in diagnostic.
+
+	* src/framebuf.c (cyg_fb_synch), include/framebuf.h
+	(CYG_FB_FRAMEBUFFER): fix double buffer support.
+
+2005-06-20  John Dallaway  <jld@ecoscentric.com>
+
+	* doc/framebuf.sgml: Fix typographical errors.
+
+2005-03-29  Bart Veer  <bartv@ecoscentric.com>
+
+	* Generic framebuffer package created
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
Index: cdl/framebuf.cdl
===================================================================
RCS file: cdl/framebuf.cdl
diff -N cdl/framebuf.cdl
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ cdl/framebuf.cdl	7 Oct 2008 10:02:55 -0000
@@ -0,0 +1,232 @@
+# ====================================================================
+#
+#      framebuf.cdl
+#
+#      Generic framebuffer package configuration data
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+# -------------------------------------------
+# This file is part of eCos, the Embedded Configurable Operating System.
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# eCos is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 or (at your option) any later version.
+#
+# eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with eCos; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+#
+# As a special exception, if other files instantiate templates or use macros
+# or inline functions from this file, or you compile this file and link it
+# with other works to produce a work based on this file, this file does not
+# by itself cause the resulting work to be covered by the GNU General Public
+# License. However the source code for this file must still be made available
+# in accordance with section (3) of the GNU General Public License.
+#
+# This exception does not invalidate any other reasons why a work based on
+# this file might be covered by the GNU General Public License.
+# -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):     bartv
+# Date:          2005-03-29
+#
+#####DESCRIPTIONEND####
+#========================================================================
+
+cdl_package CYGPKG_IO_FRAMEBUF {
+    display		"Framebuffer support"
+    doc         ref/io-framebuf.html
+    requires	CYGPKG_INFRA CYGPKG_HAL CYGPKG_ERROR
+    include_dir	cyg/io
+    compile		framebuf.c linear.c palette.c
+
+    # A custom build step to generate a single header with details of all
+    # the framebuffers for this target. The dependency on <pkgconf/system.h>
+    # copes with the case of a framebuffer device driver package being removed
+    make -priority 2 {
+        $(PREFIX)/include/cyg/io/framebufs/framebufs.h : $(REPOSITORY)/$(PACKAGE)/src/gen_framebufs.tcl \
+            $(PREFIX)/include/pkgconf/system.h \
+            $(subst $(PREFIX)/include/cyg/io/framebufs/framebufs.h,,$(wildcard $(PREFIX)/include/cyg/io/framebufs/*.h*))
+        sh $< $(dir $@)
+    }
+    
+    description "
+        The generic framebuffer package provides an API for accessing
+        one or more framebuffers, plus support for appropriate device
+        drivers."
+
+    cdl_interface CYGINT_IO_FRAMEBUF_DEVICES {
+        display		"Number of available framebuffer devices"
+        flavor		data
+        description "
+            This interface specifies the number of framebuffer devices
+            supported by device driver(s) on this platform."
+    }
+
+    cdl_option CYGDAT_IO_FRAMEBUF_DEVICES {
+        display		"Names of available framebuffer devices"
+        default_value	{ "" }
+        flavor		data
+        description "
+            This option provides a list of the framebuffer devices available
+            on the current platform. It is controlled by the appropriate
+            device driver(s) and should not be edited by users."
+    }
+
+    cdl_option CYGDAT_IO_FRAMEBUF_TEST_DEVICE {
+        display         "Framebuffer device to use for testing"
+        active_if       CYGINT_IO_FRAMEBUF_DEVICES
+        flavor          booldata
+        default_value   0
+        requires        { is_substr(CYGDAT_IO_FRAMEBUF_DEVICES, " " . CYGDAT_IO_FRAMEBUF_TEST_DEVICE . " ") }
+        description "
+            This option determines the framebuffer device to be used for running
+          the testcases. By default the build system will automatically select
+          the first entry in CYGDAT_IO_FRAMEBUF_DEVICES, which will be the
+          only entry if there is only framebuffer device in the system."
+    }
+    
+    cdl_component CYGPKG_IO_FRAMEBUF_FUNCTIONALITY {
+        display		"Functionality supported by the platform's framebuffer(s)"
+        flavor 		none
+        description "
+            This component holds details of the functionality provided by the
+            framebuffer device driver(s) for the current platform."
+
+        cdl_interface CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_32BPP {
+            display	"32bpp pixel support required"
+            flavor	booldata
+            description "
+                This interface will be implemented if any of the framebuffer
+                device drivers for the current platform provides a 32 bits
+                per pixel display. This constrains the cyg_colour data type
+                to be at least 32 bits."
+        }
+        
+        cdl_interface CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR {
+            display	"Framebuffer supports true colour mode"
+            flavor	booldata
+            define	CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOR
+            description "
+                This interface will be implemented if any of the framebuffer
+                device drivers for the current platform support true colour
+                operation. In other words the contents of the framebuffer
+                defines the colours directly and there is no indirection via
+                a palette."
+        }
+
+        cdl_interface CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE {
+            display	"Framebuffer uses a palette for colours"
+            flavor	booldata
+            description "
+                This interface will be implemented if any of the framebuffer
+                device drivers for the current platform use a palette. In
+                other words the contents of the framebuffer's memory do not
+                represent colours directly, but instead are treated as indices
+                into a separate table known as the palette."
+        }
+        
+        cdl_interface CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE {
+            display	"Framebuffer uses a writeable palette for colours"
+            flavor	booldata
+            description "
+                This interface will be implemented if any of the framebuffer
+                device drivers for the current platform use a palette, and this
+                palette can be modified at run-time. In other words the contents
+                of the framebuffer's memory do not represent colours directly,
+                but instead are treated as indices into a separate table known
+                as the palette."
+        }
+        
+        cdl_interface CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT {
+            display	"Framebuffer provides viewport support"
+            flavor	booldata
+            description "
+              This interface will be implemented if any of the framebuffer
+              device drivers for the current platform provide viewport support.
+              In other words only a subset of the framebuffer, the viewport,
+              is actually visible on the display and application code can move
+              this viewport."
+        }
+
+        cdl_interface CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER {
+            display	"Framebuffer provides double buffering support"
+            flavor	booldata
+            description "
+              This interface will be implemented if any of the framebuffer
+              device drivers for the current platform provide support for
+              double buffering. In other words the framebuffer memory that
+              is updated by graphics operations is not what actually gets
+              displayed. Instead there is a separate hidden area of memory
+              used for the display, and when drawing is complete a flush
+              operation is needed to move the framebuffer contents to that
+              hidden area. This makes it possible to update the display more
+              smoothly, at the cost of potentially expensive memory copy
+              operations."
+        }
+    }
+
+    cdl_option CYGFUN_IO_FRAMEBUF_INSTALL_DEFAULT_PALETTE {
+        display		"Framebuffers should install a default palette"
+        flavor		bool
+        default_value	1
+        active_if	CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE
+        description "
+          Framebuffer devices which involve a writeable palette may set this
+          to a default palette when activated by cyg_fb_on() or equivalent
+          functionality. This is useful when the application will access the
+          framebuffer directly. It is less useful if a higher-level graphics
+          library is in use because typically that will install its own
+          palette, and typically there is a code/data overhead of approximately 1K."
+    }
+    
+    cdl_component CYGPKG_IO_FRAMEBUF_OPTIONS {
+        display "Framebuffer build options"
+        flavor  none
+        description   "
+	    Package specific build options including control over
+	    compiler flags used only in building the generic frame
+            buffer package, and details of which tests are built."
+
+        cdl_option CYGPKG_IO_FRAMEBUF_CFLAGS_ADD {
+            display "Additional compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building the generic framebuffer package. These flags
+                are used in addition to the set of global flags."
+        }
+
+        cdl_option CYGPKG_IO_FRAMEBUF_CFLAGS_REMOVE {
+            display "Suppressed compiler flags"
+            flavor  data
+            no_define
+            default_value { "" }
+            description   "
+                This option modifies the set of compiler flags for
+                building the generic framebuffer package. These flags
+                are removed from the set of global flags if present."
+        }
+
+        cdl_option CYGPKG_IO_FRAMEBUF_TESTS {
+            display	    "Framebuffer tests"
+            active_if   CYGINT_IO_FRAMEBUF_DEVICES
+            flavor 	    booldata
+            calculated  { "tests/fb tests/fbmacro" }
+            description "
+                This option specifies the set of tests for the framebuffer package"
+        }
+    }
+}
Index: doc/framebuf.sgml
===================================================================
RCS file: doc/framebuf.sgml
diff -N doc/framebuf.sgml
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ doc/framebuf.sgml	7 Oct 2008 10:03:01 -0000
@@ -0,0 +1,2914 @@
+<!-- DOCTYPE part  PUBLIC "-//OASIS//DTD DocBook V3.1//EN" -->
+
+<!-- {{{ Banner                         -->
+
+<!-- =============================================================== -->
+<!--                                                                 -->
+<!--     framebuf.sgml                                               -->
+<!--                                                                 -->
+<!--     Generic framebuffer documentation.                          -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+<!-- ####COPYRIGHTBEGIN####                                          -->
+<!--                                                                 -->
+<!-- =============================================================== -->
+<!-- Copyright (C) 2008 Free Software Foundation, Inc.               -->
+<!-- This material may be distributed only subject to the terms      -->
+<!-- and conditions set forth in the Open Publication License, v1.0  -->
+<!-- or later (the latest version is presently available at          -->
+<!-- http://www.opencontent.org/openpub/)                            -->
+<!-- Distribution of the work or derivative of the work in any       -->
+<!-- standard (paper) book form is prohibited unless prior           -->
+<!-- permission obtained from the copyright holder                   -->
+<!-- =============================================================== -->
+<!--                                                                 -->      
+<!-- ####COPYRIGHTEND####                                            -->
+<!-- =============================================================== -->
+<!-- #####DESCRIPTIONBEGIN####                                       -->
+<!--                                                                 -->
+<!-- Author(s):   bartv                                              -->
+<!-- Date:        2005/03/29                                         -->
+<!--                                                                 -->
+<!-- ####DESCRIPTIONEND####                                          -->
+<!-- =============================================================== -->
+
+<!-- }}} -->
+
+<part id="io-framebuf"><title>Framebuffer Support</title>
+
+<!-- {{{ Overview                       -->
+
+<refentry id="framebuf">
+  <refmeta>
+    <refentrytitle>Overview</refentrytitle>
+  </refmeta>
+  <refnamediv>
+    <refname>Overview</refname>
+    <refpurpose>eCos Support for Framebuffer Devices</refpurpose>
+  </refnamediv>
+
+  <refsect1 id="framebuf-description">
+    <title>Description</title>
+    <para>
+Framebuffer devices are the most common way for a computer system to
+display graphical output to users. There are immense variations in the
+implementations of such devices. <varname>CYGPKG_IO_FRAMEBUF</varname>
+provides an abstraction layer for use by application code and other
+packages. It defines an API for manipulating framebuffers, mapping
+this API on to functionality provided by the appropriate device
+driver. It also defines the interface which such device drivers should
+implement. For simple hardware it provides default implementations of
+much of this interface, greatly reducing the effort needed to write a
+device driver.
+    </para>
+    <para>
+This package does not constitute a graphics library. It does not
+implement functionality like drawing text or arbitrary lines, let
+alone any kind of windowing system. Instead it operates at the lower
+level of individual pixels and blocks of pixels, in addition to
+control operations such as hardware initialization. Some applications
+may use the framebuffer API directly. Others will instead use a
+higher-level graphics library, and it is that library which uses the
+framebuffer API.
+    </para>
+    <para>
+It is assumed that users are already familiar with the fundamentals of
+computer graphics, and no attempt is made here to explain terms like
+display depth, palette or pixel.
+    </para>
+    <note>
+      <para>
+This package is work-in-progress. The support for 1bpp, 2bpp and 4bpp
+display depths is incomplete. For double-buffered displays the code
+does not yet maintain a bounding box of the updated parts of the
+display. The package has also been designed to allow for
+<link linkend="framebuf-porting-expansion">expansion</link> with new
+functionality.
+      </para>
+    </note>
+  </refsect1>
+
+  <refsect1 id="framebuf-configuration">
+    <title>Configuration</title>
+    <para>
+<varname>CYGPKG_IO_FRAMEBUF</varname> only contains
+hardware-independent code. It should be complemented by one or more
+framebuffer device drivers appropriate for the target platform. These
+drivers may be specific to the platform, or they may be more generic
+with platform-specific details such as the framebuffer memory base
+address provided by the platform HAL. When creating a configuration
+for a given target the device driver(s) will always be included
+automatically (assuming one has been written or ported). However by
+default this driver will be inactive and will not get built, so does
+not add any unnecessary size overhead for applications which do not
+require graphics. To activate the device driver
+<varname>CYGPKG_IO_FRAMEBUF</varname> must be added explicitly to the
+configuration, for example using
+<command>ecosconfig&nbsp;add&nbsp;framebuf</command>. After this the
+full framebuffer API will be available to other packages and to
+application code.
+    </para>
+    <para>
+This package contains very few configuration options. Instead it is
+left to device drivers or higher-level code to provide appropriate
+configurability. One option,
+<varname>CYGFUN_IO_FRAMEBUF_INSTALL_DEFAULT_PALETTE</varname>, relates
+to the initialization of <link
+linkend="framebuf-colour-palette">paletted displays</link>.
+    </para>
+    <para>
+There are a number of calculated and inferred configuration options
+and a number of interfaces. These provide information such as whether
+or not there is a backlight. The most important one is
+<varname>CYGDAT_IO_FRAMEBUF_DEVICES</varname>, which holds a list of
+framebuffer identifiers for use with the <link
+linkend="framebuf-api">macro-based API</link>. If there is a single
+framebuffer device driver which supports one display in either
+landscape or portrait mode, the configuration option may hold a value
+like <literal> 240x320x8 320x240x8r90</literal>.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-api">
+    <title>Application Programmer Interfaces</title>
+    <para>
+Framebuffer devices require a difficult choice between flexibility and
+performance. On the one hand the API should be able to support
+multiple devices driving separate displays, or a single device
+operating in different modes at different times. On the other hand
+graphics tends to involve very large amounts of I/O: even something as
+simple as drawing a background image can involve setting many
+thousands of pixels. Efficiency requires avoiding all possible
+overheads including function calls. Instead the API should make
+extensive use of macros or inline functions. Ideally details of the
+framebuffer device such as the stride would be known constants at
+compile-time, giving the compiler as much opportunity as possible to
+optimize the code. Clearly this is difficult if multiple framebuffer
+devices are in use or if the device mode may get changed at run-time.
+    </para>
+    <para>
+To meet the conflicting requirements the generic framebuffer package
+provides two APIs: a fast macro API which requires selecting a single
+framebuffer device at compile or configure time; and a slower function
+API without this limitation. The two are very similar, for example:
+    </para>
+    <programlisting width=72>
+#include &lt;cyg/io/framebuf.h&gt;
+
+void
+clear_screen(cyg_fb* fb, cyg_fb_colour colour)
+{
+    cyg_fb_fill_block(fb, 0, 0,
+                      fb->fb_width, fb->fb_height,
+                      colour);
+}
+    </programlisting>
+    <para>
+or the equivalent macro version:
+    </para>
+<programlisting width=72>
+#include &lt;cyg/io/framebuf.h&gt;
+
+#define FRAMEBUF 240x320x8
+
+void
+clear_screen(cyg_fb_colour colour)
+{
+    CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
+                      CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
+                      colour);
+}
+    </programlisting>
+    <para>
+The function-based API works in terms of
+<structname>cyg_fb</structname> structures, containing all the
+information needed to manipulate the device. Each framebuffer device
+driver will export one or more of these structures, for example
+<varname>cyg_alaia_fb_240x320x8</varname>, and the driver
+documentation should list the variable names. The macro API works in
+terms of identifiers such as <literal>240x320x8</literal>, and by a
+series of substitutions the main macro gets expanded to the
+appropriate device-specific code, usually inline. Again the device
+driver documentation should list the supported identifiers. In
+addition the configuration option
+<varname>CYGDAT_IO_FRAMEBUF_DEVICES</varname> will contain the full
+list. By convention the identifier will be specified by a
+<literal>#define</literal>'d symbol such as
+<varname>FRAMEBUF</varname>, or in the case of graphics libraries by a
+configuration option.
+    </para>
+    <para>
+If a platform has multiple framebuffer devices connected to different
+displays then there will be separate <structname>cyg_fb</structname>
+structures and macro identifiers for each one. In addition some
+devices can operate in multiple modes. For example a PC VGA card can
+operate in a monochome 640x480 mode, an 8bpp 320x200 mode, and many
+other modes, but only one of these can be active at a time. The
+different modes are also represented by different
+<structname>cyg_fb</structname> structures and identifiers,
+effectively treating the modes as separate devices. It is the
+responsibility of higher-level code to ensure that only one mode is in
+use at a time.
+    </para>
+    <para>
+It is possible to use the macro API with more than one device,
+basically by compiling the code twice with different values of
+<varname>FRAMEBUF</varname>, taking appropriate care to avoid
+identifier name clashes. This gives the higher performance of the
+macros at the cost of increased code size.
+    </para>
+    <para>
+All of the framebuffer API, including exports of the device-specific
+<structname>cyg_fb</structname> structures, is available through a
+single header file <filename>&lt;cyg/io/framebuf.h&gt;</filename>. The
+API follows a number of conventions. Coordinates (0,0) correspond to
+the top-left corner of the display. All functions and macros which
+take a pair of coordinates have x first, y second. For block
+operations these coordinates are followed by width, then height.
+Coordinates and dimensions use <type>cyg_ucount16</type> variables,
+which for any processor should be the most efficient unsigned data
+type with at least 16 bits - usually plain unsigned integers. Colours
+are identified by <type>cyg_fb_colour</type> variables, again usually
+unsigned integers.
+    </para>
+    <para>
+To allow for the different variants of the English language, the API
+allows for a number of alternate spellings. Colour and color can be
+used interchangeably, so there are data types
+<type>cyg_fb_colour</type> and <type>cyg_fb_color</type>, and
+functions <function>cyg_fb_make_colour</function> and
+<function>cyg_fb_make_color</function>. Similarly gray is accepted as
+a variant of grey so the predefined colours
+<literal>CYG_FB_DEFAULT_PALETTE_LIGHTGREY</literal> and
+<literal>CYG_FB_DEFAULT_PALETTE_LIGHTGRAY</literal> are equivalent.
+    </para>
+    <para>
+The API is split into the following categories:
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term><link linkend="framebuf-parameters">parameters</link></term>
+        <listitem><para>
+getting information about a given framebuffer device such as width,
+height and depth. Colours management is complicated so has its own
+<link linkend="framebuf-colour">category</link>.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><link linkend="framebuf-control">control</link></term>
+        <listitem><para>
+operations such as switching the display on and off, and more
+device-specific ones such as manipulating the backlight.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><link linkend="framebuf-colour">colours</link></term>
+        <listitem><para>
+determining the colour format (monochrome, paletted, &hellip),
+manipulating the palette, or constructing true colours.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><link linkend="framebuf-drawing">drawing</link></term>
+        <listitem><para>
+primitives for manipulating pixels and blocks of pixels.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><link linkend="framebuf-iterating">iteration</link></term>
+        <listitem><para>
+efficiently iterating over blocks of pixels.
+        </para></listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1 id="framebuf-threads">
+    <title>Thread Safety</title>
+    <para>
+The framebuffer API never performs any locking so is not thread-safe.
+Instead it assumes that higher-level code such as a graphics library
+performs any locking that may be needed. Adding a mutex lock and
+unlock around every drawing primitive, including pixel writes, would
+be prohibitively expensive.
+    </para>
+    <para>
+It is also assumed that the framebuffer will only be updated from
+thread context. With most hardware it will also be possible to access
+a framebuffer from DSR or ISR context, but this should be avoided in
+portable code.
+    </para>
+  </refsect1>
+
+</refentry>
+
+<!-- }}} -->
+<!-- {{{ Framebuffer parameters         -->
+
+<refentry id="framebuf-parameters">
+  <refmeta>
+    <refentrytitle>Framebuffer Parameters</refentrytitle>
+  </refmeta>
+  <refnamediv>
+    <refname>Parameters</refname>
+    <refpurpose>determining framebuffer capabilities</refpurpose>
+  </refnamediv>
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>
+#include &lt;cyg/io/framebuf.h&gt;
+
+typedef struct cyg_fb {
+    cyg_ucount16    fb_depth;
+    cyg_ucount16    fb_format;
+    cyg_ucount16    fb_width;
+    cyg_ucount16    fb_height;
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT
+    cyg_ucount16    fb_viewport_width;
+    cyg_ucount16    fb_viewport_height;
+#endif
+    void*           fb_base;
+    cyg_ucount16    fb_stride;
+    cyg_uint32      fb_flags0;
+    &hellip;    
+} cyg_fb;
+      </funcsynopsisinfo>
+      <funcprototype>
+        <funcdef>cyg_fb* <function>CYG_FB_STRUCT</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_ucount16 <function>CYG_FB_DEPTH</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_ucount16 <function>CYG_FB_FORMAT</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_ucount16 <function>CYG_FB_WIDTH</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_ucount16 <function>CYG_FB_HEIGHT</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_ucount16 <function>CYG_FB_VIEWPORT_WIDTH</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_ucount16 <function>CYG_FB_VIEWPORT_HEIGHT</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void* <function>CYG_FB_BASE</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_ucount16 <function>CYG_FB_STRIDE</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_uint32 <function>CYG_FB_FLAGS0</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1 id="framebuf-parameters-description">
+    <title>Description</title>
+    <para>
+When developing an application for a specific platform the various
+framebuffer parameters such as width and height are known, and the
+code can be written accordingly. However when writing code that should
+work on many platforms with different framebuffer devices, for example
+a graphics library, the code must be able to get these parameters and
+adapt.
+    </para>
+    <para>
+Code using the function API can extract the parameters from the
+<structname>cyg_fb</structname> structures at run-time. The macro API
+provides dedicated macros for each parameter. These do not follow the
+usual eCos convention where the result is provided via an extra
+argument. Instead the result is returned as normal, and is guaranteed
+to be a compile-time constant. This allows code like the following:
+    </para>
+    <programlisting width=72>
+#if CYG_FB_DEPTH(FRAMEBUF) &lt; 8
+    &hellip;
+#else
+    &hellip;
+#endif
+    </programlisting>
+    <para>
+or alternatively:
+    </para>
+    <programlisting width=72>
+    if (CYG_FB_DEPTH(FRAMEBUF) < 8) {
+        &hellip;
+    } else {
+        &hellip;
+    }
+    </programlisting>
+    <para>
+or:
+    </para>
+    <programlisting width=72>
+    switch (CYG_FB_DEPTH(FRAMEBUF)) {
+        case  1 : &hellip; break;
+        case  2 : &hellip; break;
+        case  4 : &hellip; break;
+        case  8 : &hellip; break;
+        case 16 : &hellip; break;
+        case 32 : &hellip; break;
+    }
+    </programlisting>
+    <para>
+In terms of the code actually generated by the compiler these
+approaches have much the same effect. The macros expand to a
+compile-time constant so unnecessary code can be easily eliminated.
+    </para>
+    <para>
+The available parameters are as follows:
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term>depth</term>
+        <listitem><para>
+The number of bits per pixel or bpp. The common depths are 1, 2, 4, 8,
+16 and 32. 
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>format</term>
+        <listitem><para>
+How the pixel values are mapped on to visible <link
+linkend="framebuf-colour">colours</link>, for example true colour
+or paletted or greyscale.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>width</term>
+        <term>height</term>
+        <listitem><para>
+The number of framebuffer pixels horizontally and vertically.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>viewport width</term>
+        <term>viewport height</term>
+        <listitem><para>
+With some devices the framebuffer height and/or width are greater than
+what the display can actually show. The display is said to offer a
+viewport into the larger framebuffer. The number of visible pixels is
+determined from the viewport width and height. The position of the
+viewport is controlled via an <link
+linkend="framebuf-control-ioctl-viewport"><function>ioctl</function></link>.
+Within a <structname>cyg_fb</structname> structure these fields are
+only present if
+<varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT</varname>
+is defined, to avoid wasting data space on fields that are unnecessary
+for the current platform. For the macro API the viewport macros should only be used
+if <literal>CYG_FB_FLAGS0_VIEWPORT</literal> is set for the framebuffer:
+        </para>
+        <programlisting width=72>
+#if (CYG_FB_FLAGS0(FRAMEBUF) &amp; CYG_FB_FLAGS0_VIEWPORT)
+    &hellip;
+#endif
+        </programlisting></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>base</term>
+        <term>stride</term>
+        <listitem><para>
+For <link linkend="framebuf-parameters-linear">linear</link>
+framebuffers these parameters provide the information needed to access
+framebuffer memory. The stride is in bytes.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>flags0</term>
+        <listitem><para>
+This gives further information about the hardware capabilities.
+Some of this overlaps with other parameters, especially when it comes
+to colour, because it is often easier to test for a single flag than
+for a range of colour modes. The current flags are:
+        </para>
+        <variablelist>
+          <varlistentry>
+            <term><literal>CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER</literal></term>
+            <listitem><para>
+Framebuffer memory is organized in a conventional fashion and can be
+<link linkend="framebuf-parameters-linear">accessed</link> directly by
+higher-level code using the base and stride parameters.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>CYG_FB_FLAGS0_LE</literal></term>
+            <listitem><para>
+This flag is only relevant for 1bpp, 2bpp and 4bpp devices and
+controls how the pixels are organized within each byte. If the flag is
+set then the layout is little-endian: for a 1bpp device pixel (0,0)
+occupies bit 0 of the first byte of framebuffer memory. The more
+common layout is big-endian where pixel (0,0) occupies bit 7 of the
+first byte.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>CYG_FB_FLAGS0_TRUE_COLOUR</literal></term>
+            <listitem><para>
+The framebuffer uses a true colour format where the value of each
+pixel directly encodes the red, green and blue intensities. This is
+common for 16bpp and 32bpp devices, and is occasionally used for 8bpp
+devices. 
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>CYG_FB_FLAGS0_PALETTE</literal></term>
+            <listitem><para>
+The framebuffer uses a palette. A pixel value does not directly encode
+the colours, but instead acts as an index into a separate table of
+colour values. That table may be read-only or read-write. Paletted
+displays are common for 8bpp and some 4bpp displays.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>CYG_FB_FLAGS0_WRITEABLE_PALETTE</literal></term>
+            <listitem><para>
+The palette is read-write.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>CYG_FB_FLAGS0_DELAYED_PALETTE_UPDATE</literal></term>
+            <listitem><para>
+Palette updates can be synchronized to a vertical blank, in other
+words a brief time period when the display is not being updated,
+by using <literal>CYG_FB_UPDATE_VERTICAL_RETRACE</literal> as the last
+argument to <function>cyg_fb_write_palette</function> or
+<function>CYG_FB_WRITE_PALETTE</function>. With some hardware updating
+the palette in the middle of a screen update may result in visual noise.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>CYG_FB_FLAGS0_VIEWPORT</literal></term>
+            <listitem><para>
+The framebuffer contains more pixels than can be shown on the display.
+Instead the display provides a viewport into the framebuffer. An
+<link linkend="framebuf-control-ioctl-viewport"><function>ioctl</function></link>
+can be used to move the viewport.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>CYG_FB_FLAGS0_DOUBLE_BUFFER</literal></term>
+            <listitem><para>
+The display does not show the current contents of the framebuffer, so
+the results of drawing into the framebuffer are not immediately
+visible. Instead higher-level code needs to perform an explicit 
+<link linkend="framebuf-drawing-synch">synch</link> operation to
+update the display.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>CYG_FB_FLAGS0_PAGE_FLIPPING</literal></term>
+            <listitem><para>
+The hardware supports two or more pages, each of width*height pixels,
+only one of which is visible on the display. This allows higher-level
+code to update one page without disturbing what is currently visible.
+An <link
+linkend="framebuf-control-ioctl-pageflip"><function>ioctl</function></link>
+is used to switch the visible page.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>CYG_FB_FLAGS0_BLANK</literal></term>
+            <listitem><para>
+The display can be <link linkend="framebuf-control-ioctl-blank">blanked</link>
+without affecting the framebuffer contents or settings.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>CYG_FB_FLAGS0_BACKLIGHT</literal></term>
+            <listitem><para>
+There is a backlight which can be <link
+linkend="framebuf-control-ioctl-backlight">switched</link> 
+on or off. Some hardware provides finer-grained control over the
+backlight intensity.
+            </para></listitem>
+          </varlistentry>
+          <varlistentry>
+            <term><literal>CYG_FB_FLAGS0_MUST_BE_ON</literal></term>
+            <listitem><para>
+Often it is desirable to perform some initialization such as clearing
+the screen or setting the palette before the display is <link
+linkend="framebuf-control-onoff">switched on</link>, to avoid visual
+noise. However not all hardware allows this. If this flag is set then
+it is possible to access framebuffer memory and the palette before the
+<function>cyg_fb_on</function> or <function>CYG_FB_ON</function>
+operation. It may also be possible to perform some other operations
+such as activating the backlight, but that is implementation-defined.
+            </para></listitem>
+          </varlistentry>
+        </variablelist>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+    <para>
+To allow for future expansion there are also flags1, flags2, and
+flags3 fields. These may get used for encoding additional
+<function>ioctl</function> functionality, support for hardware
+acceleration, and similar features.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-parameters-linear">
+    <title>Linear Framebuffers</title>
+    <para>
+There are drawing primitives for writing and reading individual
+pixels. However these involve a certain amount of arithmetic each time
+to get from a position to an address within the frame buffer, plus
+function call overhead if the function API is used, and this will slow
+down graphics operations.
+    </para>
+    <para>
+When the framebuffer device is known at compile-time and the macro API
+is used then there are additional macros specifically for <link
+linkend="framebuf-iterating">iterating</link> over parts of the frame
+buffer. These should prove very efficient for many graphics
+operations. However if the device is selected at run-time then the
+macros are not appropriate and code may want to manipulate framebuffer
+memory directly. This is possible if two conditions are satisfied:
+    </para>
+    <orderedlist>
+      <listitem><para>
+The <literal>CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER</literal> flag must be
+set. Otherwise framebuffer memory is either not directly accessible or
+has a non-linear layout.
+      </para></listitem>
+      <listitem><para>
+The <literal>CYG_FB_FLAGS0_DOUBLE_BUFFER</literal> flag must be clear.
+An efficient double buffer synch operation requires knowing what part
+of the framebuffer have been updated, and the various drawing
+primitives will keep track of this. If higher-level code then starts
+manipulating the framebuffer directly the synch operation may perform
+only a partial update.
+      </para></listitem>
+    </orderedlist>
+    <para>
+The base, stride, depth, width and height parameters, plus the
+<literal>CYG_FB_FLAGS0_LE</literal> flag for 1bpp, 2bpp and 4bpp
+devices, provide all the information needed to access framebuffer
+memory. A linear framebuffer has pixel (0,0) at the base address.
+Incrementing y means adding stride bytes to the pointer.
+    </para>
+    <para>
+The base and stride parameters may be set even if
+<literal>CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER</literal> is clear. This can
+be useful if for example the display is rotated in software from
+landscape to portrait mode. However the meaning of these parameters
+for non-linear framebuffers is implementation-defined.
+    </para>
+  </refsect1>
+</refentry>
+
+<!-- }}} -->
+<!-- {{{ Control Operations             -->
+
+<refentry id="framebuf-control">
+  <refmeta>
+    <refentrytitle>Framebuffer Control Operations</refentrytitle>
+  </refmeta>
+  <refnamediv>
+    <refname>Control Operations</refname>
+    <refpurpose>managing a framebuffer</refpurpose>
+  </refnamediv>
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>
+#include &lt;cyg/io/framebuf.h&gt;
+      </funcsynopsisinfo>
+      <funcprototype>
+        <funcdef>int <function>cyg_fb_on</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>cyg_fb_off</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>cyg_fb_ioctl</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+        <paramdef>cyg_uint16 <parameter>key</parameter></paramdef>
+        <paramdef>void* <parameter>data</parameter></paramdef>
+        <paramdef>size_t* <parameter>len</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>CYG_FB_ON</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>CYG_FB_OFF</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>int <function>CYG_FB_IOCTL</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_uint16 <parameter>key</parameter></paramdef>
+        <paramdef>void* <parameter>data</parameter></paramdef>
+        <paramdef>size_t* <parameter>len</parameter></paramdef>
+      </funcprototype> 
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1 id="framebuf-control-description">
+    <title>Description</title>
+    <para>
+The main operations on a framebuffer are drawing and colour
+management. However on most hardware it is also necessary to switch
+the display <link linkend="framebuf-control-onoff">on</link> before the
+user can see anything, and application code should be able to control
+when this happens. There are also miscellaneous operations such as
+manipulating the backlight or moving the viewpoint. These do not
+warrant dedicated functions, especially since the functionality will
+only be available on some hardware, so an <link
+linkend="framebuf-control-ioctl"><function>ioctl</function></link>
+interface is used.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-control-onoff">
+    <title>Switching the Display On or Off</title>
+    <para>
+With most hardware nothing will be visible until there is a call to
+<function>cyg_fb_on</function> or an invocation of the
+<function>CYG_FB_ON</function> macro. This will initialize the
+framebuffer control circuitry, start sending the data signals to the
+display unit, and switch on the display if necessary. The exact
+initialization semantics are left to the framebuffer device driver. In
+some cases the hardware may already be partially or fully initialized
+by a static constructor or by boot code that ran before eCos.
+    </para>
+    <para>
+There are some circumstances in which initialization can fail, and
+this is indicated by a POSIX error code such as
+<literal>ENODEV</literal>. An example would be plug and play hardware
+where the framebuffer device is not detected at run-time. Another
+example is hardware which can operate in several modes, with separate
+<structname>cyg_fb</structname> structures for each mode, if the
+hardware is already in use for a different mode. A return value of 0
+indicates success.
+    </para>
+    <para>
+Some but not all hardware allows the framebuffer memory and, if
+present, the palette to be manipulated before the device is switched
+on. That way the user does not see random noise on the screen during
+system startup. The flag <literal>CYG_FB_FLAGS0_MUST_BE_ON</literal>
+should be checked:
+    </para>
+    <programlisting width=72>
+static void
+init_screen(cyg_fb_colour background)
+{
+    int result;
+
+#if (! (CYG_FB_FLAGS0(FRAMEBUF) &amp; CYG_FB_FLAGS0_MUST_BE_ON))
+    CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
+                      CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
+                      background);
+#endif
+
+    result = CYG_FB_ON(FRAMEBUF);
+    if (0 != result) {
+        &lt;handle unusual error condition&gt;
+    }
+
+#if (CYG_FB_FLAGS0(FRAMEBUF) &amp; CYG_FB_FLAGS0_MUST_BE_ON)
+    CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
+                      CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
+                      background);
+#endif
+}
+    </programlisting>
+    <para>
+Obviously if the application has already manipulated framebuffer
+memory or the palette but then the <function>cyg_fb_on</function>
+operation fails, the system is left in an undefined state.
+    </para>
+    <para>
+It is also possible to switch a framebuffer device off, using the
+function <function>cyg_fb_off</function> or the macro
+<function>CYG_FB_OFF</function>, although this functionality is rarely
+used in embedded systems. The exact semantics of switching a device
+off are implementation-defined, but typically it involves shutting
+down the display, stopping the data signals to the display, and
+halting the control circuitry. The framebuffer memory and the palette
+are left in an undefined state, and application code should assume
+that both need full reinitializing when the device is switched back
+on. Some hardware may also provide a <link
+linkend="framebuf-control-ioctl-blank">blank</link> operation which
+typically just manipulates the display, not the whole framebuffer
+device. Normally <function>cyg_fb_on</function> returns 0. The API
+allows for a POSIX error code as with <function>cyg_fb_on</function>,
+but switching a device off is not an operation that is likely to fail.
+    </para>
+    <para>
+If a framebuffer device can operate in several modes, represented by
+several <structname>cyg_fb</structname> structures and macro
+identifiers, then switching modes requires turning the current device
+off before turning the next one one.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-control-ioctl">
+    <title>Miscellaneous Control Operations</title>
+    <para>
+Some hardware functionality such as an LCD panel backlight is common
+but not universal. Supporting these does not warrant dedicated
+functions. Instead a catch-all <function>ioctl</function> interface is
+provided, with the arguments just passed straight to the device
+driver. This approach also allows for future expansion and for
+device-specific operations. <function>cyg_fb_ioctl</function> and
+<function>CYG_FB_IOCTL</function> take four arguments: a
+<structname>cyg_fb</structname> structure or framebuffer identifier; a
+key that specifies the operation to be performed; an arbitrary
+pointer, which should usually be a pointer to a data structure
+specific to the key; and a length field. Key values from 0 to 0x7fff
+are generic. Key values from 0x8000 onwards are reserved for the
+individual framebuffer device drivers, for device-specific
+functionality. The length field should be set to the size of the data
+structure, and may get updated by the device driver.
+    </para>
+    <para>
+With most ioctl operations the device can indicate whether or not it
+supports the functionality by one of the flags, for example:
+    </para>
+    <programlisting width=72>
+void
+backlight_off(cyg_fb* fb)
+{
+    if (fb->fb_flags0 &amp; CYG_FB_FLAGS0_BACKLIGHT) {
+        cyg_fb_ioctl_backlight  new_setting;
+        size_t                  len = sizeof(cyg_fb_ioctl_backlight);
+        int                     result;
+
+        new_setting.fbbl_current = 0;
+        result = cyg_fb_ioctl(fb, CYG_FB_IOCTL_BACKLIGHT_SET,
+                              &amp;new_setting, &amp;len);
+        if (0 != result) {
+            &hellip;
+        }
+    }
+}
+    </programlisting>
+    <para>
+The operation returns zero for success or a POSIX error code on
+failure, for example <literal>ENOSYS</literal> if the device driver
+does not implement the requested functionality.
+    </para>
+
+    <refsect2 id="framebuf-control-ioctl-viewport">
+      <title>Viewport</title>
+      <programlisting width=72>
+# define CYG_FB_IOCTL_VIEWPORT_GET_POSITION     0x0100
+# define CYG_FB_IOCTL_VIEWPORT_SET_POSITION     0x0101
+
+typedef struct cyg_fb_ioctl_viewport {
+    cyg_ucount16    fbvp_x;     // position of top-left corner of the viewport within
+    cyg_ucount16    fbvp_y;     // the framebuffer
+    cyg_ucount16    fbvp_when;  // set-only, now or vert retrace
+} cyg_fb_ioctl_viewport;
+      </programlisting>
+      <para>
+On some targets the framebuffer device has a higher resolution than
+the display. Only a subset of the pixels, the viewport, is currently
+visible. Application code can exploit this functionality to achieve
+certain effects, for example smooth scrolling. Framebuffers which
+support this functionality will have the
+<literal>CYG_FB_FLAGS0_VIEWPORT</literal> flag set. The viewport
+dimensions are available as additional <link
+linkend="framebuf-parameters">parameters</link> to the normal
+framebuffer width and height.
+      </para>
+      <para>
+The current position of the viewport can be obtained using an
+<literal>CYG_FB_IOCTL_VIEWPORT_GET_POSITION</literal> ioctl operation.
+The data argument should be a pointer to a
+<structname>cyg_fb_ioctl_viewport</structname> structure. On return
+the <structfield>fbvp_x</structfield> and
+<structfield>fbvp_y</structfield> fields will be filled in. To move
+the viewport use <literal>CYG_FB_IOCTL_VIEWPORT_SET_POSITION</literal>
+with <structfield>fbvp_x</structfield> and
+<structfield>fbvp_y</structfield> set to the top left corner of the
+new viewport within the framebuffer, and
+<structfield>fbvp_when</structfield> set to either
+<literal>CYG_FB_UPDATE_NOW</literal> or
+<literal>CYG_FB_UPDATE_VERTICAL_RETRACE</literal>. If the device
+driver cannot easily synchronize to a vertical retrace period then
+this last field is ignored.
+      </para>
+      <programlisting width=72>
+void
+move_viewport(cyg_fb* fb, int dx, int dy)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT
+    cyg_fb_ioctl_viewport viewport;
+    int len = sizeof(cyg_fb_ioctl_viewport);
+    int result;
+
+    result = cyg_fb_ioctl(fb, CYG_FB_IOCTL_VIEWPORT_GET_POSITION,
+                        &amp;viewport, &amp;len);
+    if (result != 0) {
+        &hellip;
+    }
+    if (((int)viewport.fbvp_x + dx) &lt; 0) {
+        viewport.fbvp_x = 0;
+    } else if ((viewport.fbvp_x + dx + fb-&gt;fb_viewport_width) &gt; fb-&gt;fb_width) {
+        viewport.fbvp_x = fb-&gt;fb_width - fb-&gt;fb_viewport_width;
+    } else {
+        viewport.fbvp_x += dx;
+    }
+    if (((int)viewport.fbvp_y + dy) &lt; 0) {
+        viewport.fbvp_y = 0;
+    } else if ((viewport.fbvp_y + dy + fb-&gt;fb_viewport_height) &gt; fb-&gt;fb_height) {
+        viewport.fbvp_y = fb-&gt;fb_height - fb-&gt;fb_viewport_height;
+    } else {
+        viewport.fbvp_y += dy;
+    }
+    result = cyg_fb_ioctl(fb, CYG_FB_IOCTL_VIEWPORT_SET_POSITION,
+                          &amp;viewport, &amp;len);
+    if (result != 0) {
+        &hellip;
+    }
+#else
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_UNUSED_PARAM(int, dx);
+    CYG_UNUSED_PARAM(int, dy);
+#endif
+}
+      </programlisting>
+      <para>
+If an attempt is made to move the viewport beyond the boundaries of
+the framebuffer then the resulting behaviour is undefined. Some
+hardware may behave reasonably, wrapping around as appropriate, but
+portable code cannot assume this. The above code fragment is careful
+to clip the viewport to the framebuffer dimensions.
+      </para>
+    </refsect2>
+
+    <refsect2 id="framebuf-control-ioctl-pageflip">
+      <title>Page Flipping</title>
+      <programlisting width=72>
+# define CYG_FB_IOCTL_PAGE_FLIPPING_GET_PAGES   0x0200
+# define CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES   0x0201
+
+typedef struct cyg_fb_ioctl_page_flip {
+    cyg_uint32      fbpf_number_pages;
+    cyg_uint32      fbpf_visible_page;
+    cyg_uint32      fbpf_drawable_page;
+    cyg_ucount16    fbpf_when;  // set-only, now or vert retrace
+} cyg_fb_ioctl_page_flip;
+      </programlisting>
+      <para>
+On some targets the framebuffer has enough memory for several pages,
+only one of which is visible at a time. This allows the application
+to draw into one page while displaying another. Once drawing is
+complete the display is flipped to the newly drawn page, and the
+previously displayed page is now available for updating. This
+technique is used for smooth animation, especially in games. The flag
+<literal>CYG_FB_FLAGS0_PAGE_FLIPPING</literal> indicates support for
+this functionality.
+      </para>
+      <para>
+<literal>CYG_FB_IOCTL_PAGE_FLIPPING_GET_PAGES</literal> can be used to
+get the current settings of the page flipping support. The data
+argument should be a pointer to a
+<structname>cyg_fb_ioctl_page_flip</structname> structure. The
+resulting <structfield>fbpf_number_pages</structfield> field indicates
+the total number of pages available: 2 is common, but more pages are
+possible. <structfield>fbpf_visible_page</structfield> gives the page
+that is currently visible to the user, and will be between 0 and
+(<structfield>fbpf_number_pages</structfield>&nbsp;-&nbsp;1).
+Similarly <structfield>fbpf_drawable_page</structfield> gives the page
+that is currently visible. It is implementation-defined whether or not
+the visible and drawable page can be the same one.
+      </para>
+      <para>
+<literal>CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES</literal> can be used to
+change the visible and drawable page. The
+<structfield>fbpf_number_pages</structfield> field is ignored.
+<structfield>fbpf_visible_page</structfield> and
+<structfield>fbpf_drawable_page</structfield> give the new settings.
+<structfield>fbpf_when</structfield> should be one of
+<literal>CYG_FB_UPDATE_NOW</literal> or
+<literal>CYG_FB_UPDATE_VERTICAL_RETRACE</literal>, but may be ignored
+by some device drivers.
+      </para>
+      <programlisting width=72>
+#if !(CYG_FB_FLAGS0(FRAMEBUF) &amp; CYG_FB_FLAGS0_PAGE_FLIPPING)
+# error Current framebuffer device does not support page flipping
+#endif
+
+static cyg_uint32 current_visible = 0;
+
+static void
+page_flip_init(cyg_fb_colour background)
+{
+    cyg_fb_ioctl_page_flip flip;
+    size_t len = sizeof(cyg_fb_ioctl_page_flip);
+
+    flip.fbpf_visible_page  = current_visible;
+    flip.fbpf_drawable_page = 1 - current_visible;
+    flip.fbpf_when          = CYG_FB_UPDATE_NOW;
+    CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES,
+                 &amp;flip, &amp;len);
+    CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
+                      CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
+                      background);
+    flip.fbpf_visible_page  = 1 - current_visible;
+    flip.fbpf_drawable_page = current_visible;
+    CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES,
+                 &amp;flip, &amp;len);
+    CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
+                      CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
+                      background);
+    current_visible = 1 - current_visible;
+}
+
+static void
+page_flip_toggle(void)
+{
+    cyg_fb_ioctl_page_flip flip;
+    size_t len = sizeof(cyg_fb_ioctl_page_flip);
+
+    flip.fbpf_visible_page  = 1 - current_visible;
+    flip.fbpf_drawable_page = current_visible;
+    CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES,
+                 &amp;flip, &amp;len);
+    current_visible = 1 - current_visible;
+}
+      </programlisting>
+      <para>
+A page flip typically just changes a couple of pointers within the
+hardware and device driver. No attempt is made to synchronize the
+contents of the pages, that is left to higher-level code.
+      </para>
+    </refsect2>
+
+    <refsect2 id="framebuf-control-ioctl-blank">
+      <title>Blanking the Screen</title>
+      <programlisting width=72>
+# define CYG_FB_IOCTL_BLANK_GET                 0x0300
+# define CYG_FB_IOCTL_BLANK_SET                 0x0301
+
+typedef struct cyg_fb_ioctl_blank {
+    cyg_bool        fbbl_on;
+} cyg_fb_ioctl_blank;
+      </programlisting>
+      <para>
+Some hardware allows the display to be switched off or blanked without
+shutting down the entire framebuffer device, greatly reducing power
+consumption. The current blanking state can be obtained using
+<literal>CYG_FB_IOCTL_BLANK_GET</literal> and the state can be updated
+using <literal>CYG_FB_IOCTL_BLANK_SET</literal>. The data argument
+should be a pointer to a <structname>cyg_fb_ioctl_blank</structname>
+structure. Support for this functionality is indicated by the
+<literal>CYG_FB_FLAGS0_BLANK</literal> flag.
+      </para>
+      <programlisting width=72>
+static cyg_bool
+display_blanked(cyg_fb_* fb)
+{
+    cyg_fb_ioctl_blank blank;
+    size_t len = sizeof(cyg_fb_ioctl_blank);
+    
+    if (! (fb->fb_flags0 &amp; CYG_FB_FLAGS0_BLANK)) {
+        return false;
+    }
+    (void) cyg_fb_ioctl(fb, CYG_FB_IOCTL_BLANK_GET, &amp;blank, &amp;len);
+    return !blank.fbbl_on;
+}
+      </programlisting>
+    </refsect2>
+
+    <refsect2 id="framebuf-control-ioctl-backlight">
+      <title>Controlling the Backlight</title>
+      <programlisting width=72>
+# define CYG_FB_IOCTL_BACKLIGHT_GET             0x0400
+# define CYG_FB_IOCTL_BACKLIGHT_SET             0x0401
+
+typedef struct cyg_fb_ioctl_backlight {
+    cyg_ucount32    fbbl_current;
+    cyg_ucount32    fbbl_max;
+} cyg_fb_ioctl_backlight;
+      </programlisting>
+      <para>
+Many LCD panels provide some sort of backlight, making the display
+easier to read at the cost of increased power consumption. Support for
+this is indicated by the <literal>CYG_FB_FLAGS0_BACKLIGHT</literal>
+flag. <literal>CYG_FB_IOCTL_BACKLIGHT_GET</literal> can be used to get
+both the current setting and the maximum value. If the maximum is 1
+then the backlight can only be switched on or off. Otherwise it is
+possible to control the intensity.
+      </para>
+      <programlisting width=72>
+static void
+set_backlight_50_percent(void)
+{
+#if (CYG_FB_FLAGS0(FRAMEBUF) & CYG_FB_FLAGS0_BACKLIGHT)
+    cyg_fb_ioctl_backlight backlight;
+    size_t len = sizeof(cyg_fb_ioctl_backlight);
+
+    CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_BACKLIGHT_GET, &amp;backlight, &amp;len);
+    backlight.fbbl_current = (backlight.fbbl_max + 1) >> 1;    
+    CYG_FB_IOCTL(FRAMEBUF, CYG_FB_IOCTL_BACKLIGHT_SET, &amp;backlight, &amp;len);
+#endif
+}
+      </programlisting>
+    </refsect2>
+  </refsect1>
+
+</refentry>
+
+<!-- }}} -->
+<!-- {{{ Colour Management              -->
+
+<refentry id="framebuf-colour">
+  <refmeta>
+    <refentrytitle>Framebuffer Colours</refentrytitle>
+  </refmeta>
+  <refnamediv>
+    <refname>Colours</refname>
+    <refpurpose>formats and palette management</refpurpose>
+  </refnamediv>
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>
+#include &lt;cyg/io/framebuf.h&gt;
+
+typedef struct cyg_fb {
+    cyg_ucount16    fb_depth;
+    cyg_ucount16    fb_format;
+    cyg_uint32      fb_flags0;
+    &hellip;    
+} cyg_fb;
+
+extern const cyg_uint8  cyg_fb_palette_ega[16 * 3];
+extern const cyg_uint8  cyg_fb_palette_vga[256 * 3];
+
+#define CYG_FB_DEFAULT_PALETTE_BLACK        0x00
+#define CYG_FB_DEFAULT_PALETTE_BLUE         0x01
+#define CYG_FB_DEFAULT_PALETTE_GREEN        0x02
+#define CYG_FB_DEFAULT_PALETTE_CYAN         0x03
+#define CYG_FB_DEFAULT_PALETTE_RED          0x04
+#define CYG_FB_DEFAULT_PALETTE_MAGENTA      0x05
+#define CYG_FB_DEFAULT_PALETTE_BROWN        0x06
+#define CYG_FB_DEFAULT_PALETTE_LIGHTGREY    0x07
+#define CYG_FB_DEFAULT_PALETTE_LIGHTGRAY    0x07
+#define CYG_FB_DEFAULT_PALETTE_DARKGREY     0x08
+#define CYG_FB_DEFAULT_PALETTE_DARKGRAY     0x08
+#define CYG_FB_DEFAULT_PALETTE_LIGHTBLUE    0x09
+#define CYG_FB_DEFAULT_PALETTE_LIGHTGREEN   0x0A
+#define CYG_FB_DEFAULT_PALETTE_LIGHTCYAN    0x0B
+#define CYG_FB_DEFAULT_PALETTE_LIGHTRED     0x0C
+#define CYG_FB_DEFAULT_PALETTE_LIGHTMAGENTA 0x0D
+#define CYG_FB_DEFAULT_PALETTE_YELLOW       0x0E
+#define CYG_FB_DEFAULT_PALETTE_WHITE        0x0F
+      </funcsynopsisinfo>
+      <funcprototype>
+        <funcdef>cyg_ucount16 <function>CYG_FB_FORMAT</function></funcdef>
+        <paramdef><parameter>framebuf</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>cyg_fb_read_palette</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fb</parameter></paramdef>
+        <paramdef>cyg_ucount32 <parameter>first</parameter></paramdef>
+        <paramdef>cyg_ucount32 <parameter>count</parameter></paramdef>
+        <paramdef>void* <parameter>data</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>cyg_fb_write_palette</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fb</parameter></paramdef>
+        <paramdef>cyg_ucount32 <parameter>first</parameter></paramdef>
+        <paramdef>cyg_ucount32 <parameter>count</parameter></paramdef>
+        <paramdef>const void* <parameter>data</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>when</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_fb_colour <function>cyg_fb_make_colour</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fb</parameter></paramdef>
+        <paramdef>cyg_ucount8 <parameter>r</parameter></paramdef>
+        <paramdef>cyg_ucount8 <parameter>g</parameter></paramdef>
+        <paramdef>cyg_ucount8 <parameter>b</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>cyg_fb_break_colour</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fb</parameter></paramdef>
+        <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+        <paramdef>cyg_ucount8* <parameter>r</parameter></paramdef>
+        <paramdef>cyg_ucount8* <parameter>g</parameter></paramdef>
+        <paramdef>cyg_ucount8* <parameter>b</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_READ_PALETTE</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount32 <parameter>first</parameter></paramdef>
+        <paramdef>cyg_ucount32 <parameter>count</parameter></paramdef>
+        <paramdef>void* <parameter>data</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_WRITE_PALETTE</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount32 <parameter>first</parameter></paramdef>
+        <paramdef>cyg_ucount32 <parameter>count</parameter></paramdef>
+        <paramdef>const void* <parameter>data</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>when</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_fb_colour <function>CYG_FB_MAKE_COLOUR</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount8 <parameter>r</parameter></paramdef>
+        <paramdef>cyg_ucount8 <parameter>g</parameter></paramdef>
+        <paramdef>cyg_ucount8 <parameter>b</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_BREAK_COLOUR</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+        <paramdef>cyg_ucount8* <parameter>r</parameter></paramdef>
+        <paramdef>cyg_ucount8* <parameter>g</parameter></paramdef>
+        <paramdef>cyg_ucount8* <parameter>b</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1 id="framebuf-colour-description">
+    <title>Description</title>
+    <para>
+Managing colours can be one of the most difficult aspects of writing
+graphics code, especially if that code is intended to be portable to
+many different platforms. Displays can vary from 1bpp monochrome, via
+2bpp and 4bpp greyscale, through 4bpp and 8bpp paletted, and up to
+16bpp and 32bpp true colour - and those are just the more common
+scenarios. The various <link linkend="framebuf-drawing">drawing
+primitives</link> like <function>cyg_fb_write_pixel</function> work in
+terms of <type>cyg_fb_colour</type> values, usually an unsigned
+integer. Exactly how the hardware interprets a
+<type>cyg_fb_colour</type> depends on the format.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-colour-formats">
+    <title>Colour Formats</title>
+    <para>
+There are a number of ways of finding out how these values will be
+interpreted by the hardware:
+    </para>
+    <orderedlist>
+      <listitem><para>
+The <literal>CYG_FB_FLAGS0_TRUE_COLOUR</literal> flag is set for all
+true colour displays. The format parameter can be examined for more
+details but this is not usually necessary. Instead code can use
+<link
+linkend="framebuf-colour-true"><function>cyg_fb_make_colour</function></link>
+or <link
+linkend="framebuf-colour-true"><function>CYG_FB_MAKE_COLOUR</function></link>
+to construct a <type>cyg_fb_colour</type> value from red, green and
+blue components.
+      </para></listitem>
+      <listitem><para>
+If the <literal>CYG_FB_FLAGS0_WRITEABLE_PALETTE</literal> flag is set
+then a <type>cyg_fb_colour</type> value is an index into a lookup
+table known as the palette, and this table contains red, green and
+blue components. The size of the palette is determined by the display
+depth, so 16 entries for a 4bpp display and 256 entries for an 8bpp
+display. Application code or a graphics library can <link
+linkend="framebuf-colour-palette">install</link> its own palette so
+can control exactly what colour each <type>cyg_fb_colour</type> value
+corresponds to. Alternatively there is support for installing a
+default palette.
+      </para></listitem>
+      <listitem><para>
+If <literal>CYG_FB_FLAGS0_PALETTE</literal> is set but
+<literal>CYG_FB_FLAGS0_WRITEABLE_PALETTE</literal> is clear then the
+hardware uses a fixed palette. There is no easy way for portable
+software to handle this case. The palette can be read at run-time,
+allowing the application's desired colours to be mapped to whichever
+palette entry provides the best match. However normally it will be
+necessary to write code specifically for the fixed palette.
+      </para></listitem>
+      <listitem><para>
+Otherwise the display is monochrome or greyscale, depending on the
+depth. There are still variations, for example on a monochrome display
+colour 0 can be either white or black.
+      </para></listitem>
+    </orderedlist>
+    <para>
+As an alternative or to provide additional information, the exact
+colour format is provided by the <structfield>fb_format</structfield>
+field of the <structname>cyg_fb</structname> structure or by the
+<function>CYG_FB_FORMAT</function> macro. It can be one of the
+following (more entries may be added in future):
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_1BPP_MONO_0_BLACK</literal></term>
+        <listitem><para>
+simple 1bpp monochrome display, with 0 as black or the darker of the
+two colours, and 1 as white or the ligher colour.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_1BPP_MONO_0_WHITE</literal></term>
+        <listitem><para>
+simple 1bpp monochrome display, with 0 as white or the lighter of the
+two colours, and 1 as black or the darker colour.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_1BPP_PAL888</literal></term>
+        <listitem><para>
+a 1bpp display which cannot easily be described as monochrome. This is
+unusual and not readily supported by portable code. It can happen if
+the framebuffer normally runs at a higher depth, for example 4bpp or
+8bpp paletted, but is run at only 1bpp to save memory. Hence only two
+of the palette entries are used, but can be set to arbitrary colours.
+The palette may be read-only or read-write.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_2BPP_GREYSCALE_0_BLACK</literal></term>
+        <listitem><para>
+a 2bpp display offering four shades of grey, with 0 as black or the
+darkest of the four shades, and 3 as white or the lightest.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_2BPP_GREYSCALE_0_WHITE</literal></term>
+        <listitem><para>
+a 2bpp display offering four shades of grey, with 0 as white or the
+lightest of the four shades, and 3 as black or the darkest.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_2BPP_PAL888</literal></term>
+        <listitem><para>
+a 2bpp display which cannot easily be described as greyscale, for
+example providing black, red, blue and white as the four colours.
+This is unusual and not readily supported by portable code. It can
+happen if the framebuffer normally runs at a higher depth, for example
+4bpp or 8bpp paletted, but is run at only 2bpp to save memory. Hence
+only four of the palette entries are used, but can be set to arbitrary
+colours. The palette may be read-only or read-write.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_4BPP_GREYSCALE_0_BLACK</literal></term>
+        <listitem><para>
+a 4bpp display offering sixteen shades of grey, with 0 as black or the
+darkest of the 16 shades, and 15 as white or the lighest.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_4BPP_GREYSCALE_0_WHITE</literal></term>
+        <listitem><para>
+a 4bpp display offering sixteen shades of grey, with 0 as white or the
+lightest of the 16 shades, and 15 as black or the darkest.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_4BPP_PAL888</literal></term>
+        <listitem><para>
+a 4bpp paletted display, allowing for 16 different colours on screen
+at the same time. The palette may be read-only or read-write.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_8BPP_PAL888</literal></term>
+        <listitem><para>
+an 8bpp paletted display, allowing for 256 different colours on screen
+at the same time. The palette may be read-only or read-write.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_8BPP_TRUE_332</literal></term>
+        <listitem><para>
+an 8bpp true colour display. Bits 0 and 1 of each pixel value control
+four levels of blue intensity, bits 2 to 4 control eight levels of
+green, and bits 5 to 7 control eight levels of red.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_16BPP_TRUE_565</literal></term>
+        <listitem><para>
+a 16bpp true colour display. Bits 0 to 4 of each pixel value control
+the blue intensity, bits 5 to 10 the green intensity, and bits 11 to
+15 the red intensity.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_16BPP_TRUE_555</literal></term>
+        <listitem><para>
+a 16bpp true colour display, with the top bit unused. Bits 0 to 4 of
+each pixel value control the blue intensity, bits 5 to 9 the green
+intensity, and bits 10 to 14 the red intensity.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><literal>CYG_FB_FORMAT_32BPP_TRUE_0888</literal></term>
+        <listitem><para>
+a 32bpp true colour display, with the top byte unused. Bits 0 to 7 of
+each pixel value control the blue intensity, bits 8 to 15 the green
+intensity, and bits 16 to 23 the red intensity.
+        </para></listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1 id="framebuf-colour-palette">
+    <title>Paletted Displays</title>
+    <para>
+Palettes are the common way of implementing low-end colour displays.
+There are two variants. A read-only palette provides a fixed set of
+colours and it is up to application code to use these colours
+appropriately. A read-write palette allows the application to select
+its own set of colours. Displays providing a read-write palette will
+have the <literal>CYG_FB_FLAGS0_WRITEABLE_PALETTE</literal> flag set
+in addition to <literal>CYG_FB_FLAGS0_PALETTE</literal>.
+    </para>
+    <para>
+Even if application code can install its own palette, many
+applications do not exploit this functionality and instead stick with
+a default. There are two standard palettes: the 16-entry PC EGA for
+4bpp displays; and the 256-entry PC VGA, a superset of the EGA one,
+for 8bpp displays. This package provides the data for both, in the
+form of arrays <varname>cyg_fb_palette_ega</varname> and
+<varname>cyg_fb_palette_vga</varname>, and 16
+<literal>#define</literal>'s such as
+<varname>CYG_FB_DEFAULT_PALETTE_BLACK</varname> for the EGA colours
+and the first 16 VGA colours. By default device drivers for read-write
+paletted displays will install the appropriate default palette, but
+this can be suppressed using configuration option
+<varname>CYGFUN_IO_FRAMEBUF_INSTALL_DEFAULT_PALETTE</varname>. If a
+custom palette will be used then installing the default palette
+involves wasting 48 or 768 bytes of memory.
+    </para>
+    <para>
+It should be emphasized that displays vary widely. A colour such
+as <varname>CYG_FB_DEFAULT_PALETTE_YELLOW</varname> may appear rather
+differently on two different displays, although it should always be
+recognizable as yellow. Developers may wish to fine-tune the palette
+for specific hardware.
+    </para>
+    <para>
+The current palette can be retrieved using
+<function>cyg_fb_read_palette</function> or
+<function>CYG_FB_READ_PALETTE</function>. The
+<parameter>first</parameter> and <parameter>count</parameter>
+arguments control which palette entries should be retrieved. For
+example, to retrieve just palette entry 12
+<parameter>first</parameter> should be set to 12 and
+<parameter>count</parameter> should be set to 1. To retrieve all 256
+entries for an 8bpp display, <parameter>first</parameter> should be
+set to 0 and <parameter>count</parameter> should be set to 256. The
+<parameter>data</parameter> argument should point at an array of
+bytes, allowing three bytes for every entry. Byte 0 will contain the red
+intensity for the first entry, byte 1 green and byte 2 blue.
+    </para>
+    <para>
+For read-write palettes the palette can be updated using
+<function>cyg_fb_write_palette</function> or
+<function>CYG_FB_WRITE_PALETTE</function>. The
+<parameter>first</parameter> and <parameter>count</parameter> arguments
+are the same as for <function>cyg_fb_read_palette</function>, and the
+<parameter>data</parameter> argument should point at a suitable byte
+array packed in the same way. The <parameter>when</parameter> argument
+should be one of <literal>CYG_FB_UPDATE_NOW</literal> or
+<literal>CYG_FB_UPDATE_VERTICAL_RETRACE</literal>. With some displays
+updating the palette in the middle of an update may result in visual
+noise, so synchronizing to the vertical retrace avoids this. However
+not all device drivers will support this.
+    </para>
+    <para>
+There is an assumption that palette entries use 8 bits for each of the
+red, green and blue colour intensities. This is not always the case,
+but the device drivers will perform appropriate adjustments. Some
+hardware may use only 6 bits per colour, and the device driver will
+ignore the bottom two bits of the supplied intensity values.
+Occasionally hardware may use more than 8 bits, in which case the
+supplied 8 bits are shifted left appropriately and zero-padded. Device
+drivers for such hardware may also provide device-specific routines to
+manipulate the palette in a non-portable fashion.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-colour-true">
+    <title>True Colour displays</title>
+    <para>
+True colour displays are often easier to manage than paletted
+displays. However this comes at the cost of extra memory. A 16bpp true
+colour display requires twice as much memory as an 8bpp paletted
+display, yet can offer only 32 or 64 levels of intensity for each
+colour as opposed to the 256 levels provided by a palette. It also
+requires twice as much video memory bandwidth to send all the pixel
+data to the display for every refresh, which may impact the
+performance of the rest of the system. A 32bpp true colour display
+offers the same colour intensities but requires four times the memory
+and four times the bandwidth.
+    </para>
+    <para>
+There are two ways of determining a <type>cyg_fb_colour</type> pixel
+value for a given colour. The first is to decode the colour format,
+for example <literal>CYG_FB_FORMAT_16BPP_TRUE_565</literal>, and
+perform the appropriate arithmetic. The second is to use the supplied
+<function>cyg_fb_make_colour</function> or
+<function>CYG_FB_MAKE_COLOUR</function> primitives. These take 8-bit
+intensity levels for red, green and blue, and return the corresponding
+<type>cyg_fb_colour</type>. When using the macro interface the
+arithmetic happens at compile-time, for example:
+    </para>
+    <programlisting width=72>
+#define BLACK        CYG_FB_MAKE_COLOUR(FRAMEBUF,   0,   0,   0)
+#define WHITE        CYG_FB_MAKE_COLOUR(FRAMEBUF, 255, 255, 255)
+#define RED          CYG_FB_MAKE_COLOUR(FRAMEBUF, 255,   0,   0)
+#define GREEN        CYG_FB_MAKE_COLOUR(FRAMEBUF,   0, 255,   0)
+#define BLUE         CYG_FB_MAKE_COLOUR(FRAMEBUF,   0,   0, 255)
+#define YELLOW       CYG_FB_MAKE_COLOUR(FRAMEBUF, 255, 255,  80)
+    </programlisting>
+    <para>
+Displays vary widely so the numbers may need to be adjusted to give
+the exact desired colours.
+    </para>
+    <para>
+For symmetry there are also <function>cyg_fb_break_colour</function>
+and <function>CYG_FB_BREAK_COLOUR</function> primitives. These take a
+<type>cyg_fb_colour</type> value and decompose it into its red, green
+and blue components.
+    </para>
+  </refsect1>
+
+</refentry>
+
+<!-- }}} -->
+<!-- {{{ Drawing primitives             -->
+
+<refentry id="framebuf-drawing">
+  <refmeta>
+    <refentrytitle>Framebuffer Drawing Primitives</refentrytitle>
+  </refmeta>
+  <refnamediv>
+    <refname>Drawing Primitives</refname>
+    <refpurpose>updating the display</refpurpose>
+  </refnamediv>
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>
+#include &lt;cyg/io/framebuf.h&gt;
+      </funcsynopsisinfo>
+      <funcprototype>
+        <funcdef>void <function>cyg_fb_write_pixel</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_fb_colour <function>cyg_fb_read_pixel</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>cyg_fb_write_hline</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>len</parameter></paramdef>
+        <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>cyg_fb_write_vline</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>len</parameter></paramdef>
+        <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>cyg_fb_fill_block</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+        <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>cyg_fb_write_block</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+        <paramdef>const void* <parameter>data</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>offset</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>stride</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>cyg_fb_read_block</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+        <paramdef>void* <parameter>data</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>offset</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>stride</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>cyg_fb_move_block</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>new_x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>new_y</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>cyg_fb_synch</function></funcdef>
+        <paramdef>cyg_fb* <parameter>fbdev</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>when</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_WRITE_PIXEL</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_fb_colour <function>CYG_FB_READ_PIXEL</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_WRITE_HLINE</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>len</parameter></paramdef>
+        <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_WRITE_VLINE</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>len</parameter></paramdef>
+        <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_FILL_BLOCK</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+        <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_WRITE_BLOCK</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+        <paramdef>const void* <parameter>data</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>offset</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>stride</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_READ_BLOCK</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+        <paramdef>void* <parameter>data</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>offset</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>stride</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_MOVE_BLOCK</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>new_x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>new_y</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_SYNCH</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>when</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1 id="framebuf-drawing-description">
+    <title>Description</title>
+    <para>
+The eCos framebuffer infrastructure defines a small number of drawing
+primitives. These are not intended to provide full graphical
+functionality like multiple windows, drawing text in arbitrary fonts,
+or anything like that. Instead they provide building blocks for
+higher-level graphical toolkits. The available primitives are:
+    </para>
+    <orderedlist>
+      <listitem><para>
+Manipulating individual pixels.
+      </para></listitem>
+      <listitem><para>
+Drawing horizontal and vertical lines.
+      </para></listitem>
+      <listitem><para>
+Block fills.
+      </para></listitem>
+      <listitem><para>
+Moving blocks between the framebuffer and main memory.
+      </para></listitem>
+      <listitem><para>
+Moving blocks within the framebuffer.
+      </para></listitem>
+      <listitem><para>
+For double-buffered devices, synchronizing the framebuffer contents
+with the actual display.
+      </para></listitem>
+    </orderedlist>
+    <para>
+There are two versions for each primitive: a macro and a function. The
+macro can be used if the desired framebuffer device is known at
+compile-time. Its first argument should be a framebuffer identifier,
+for example <literal>320x240x16</literal>, and must be one of the
+entries in the configuration option
+<varname>CYGDAT_IO_FRAMEBUF_DEVICES</varname>. In the examples below
+it is assumed that <varname>FRAMEBUF</varname> has been
+<literal>#define</literal>'d to a suitable identifier. The function
+can be used if the desired framebuffer device is selected at
+run-time. Its first argument should be a pointer to the appropriate
+<structname>cyg_fb</structname> structure.
+    </para>
+    <para>
+The pixel, line, and block fill primitives take a
+<type>cyg_fb_colour</type> argument. For details of colour handling
+see <xref linkend="framebuf-colour">. This argument should have no
+more bits set than are appropriate for the display depth. For example
+on a 4bpp only the bottom four bits of the colour may be set,
+otherwise the behaviour is undefined.
+    </para>
+    <para>
+None of the primitives will perform any run-time error checking,
+except possibly for some assertions in a debug build. If higher-level
+code provides invalid arguments, for example trying to write a block
+which extends past the right hand side of the screen, then the
+system's behaviour is undefined. It is the responsibility of
+higher-level code to perform clipping to the screen boundaries.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-drawing-pixels">
+    <title>Manipulating Individual Pixels</title>
+    <para>
+The primitives for manipulating individual pixels are very simple: a
+pixel can be written or read back. The following example shows one way
+of drawing a diagonal line:
+    </para>
+    <programlisting width=72>
+void
+draw_diagonal(cyg_fb* fb,
+              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len,
+              cyg_fb_colour colour)
+{
+    while ( len-- ) {
+        cyg_fb_write_pixel(fb, x++, y++, colour);
+    }
+}
+    </programlisting>
+    <para>
+The next example shows how to draw a horizontal XOR line on a 1bpp
+display.
+    </para>
+    <programlisting width=72>
+void
+draw_horz_xor(cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len)
+{
+    cyg_fb_colour colour;
+    while ( len--) {
+        colour = CYG_FB_READ_PIXEL(FRAMEBUF, x, y);
+        CYG_FB_WRITE_PIXEL(FRAMEBUF, x++, y, colour ^ 0x01);
+    }
+}
+    </programlisting>
+    <para>
+The pixel macros should normally be avoided. Determining the correct
+location within framebuffer memory corresponding to a set of
+coordinates for each pixel is a comparatively expensive operation.
+Instead there is direct support for <link
+linkend="framebuf-iterating">iterating</link> over parts of the
+display, avoiding unnecessary overheads.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-drawing-lines">
+    <title>Drawing Simple Lines</title>
+    <para>
+Higher-level graphics code often needs to draw single-pixel horizontal
+and vertical lines. If the application involves multiple windows then
+these will usually have thin borders around them. Widgets such as
+buttons and scrollbars also often have thin borders. 
+    </para>
+    <para>
+<function>cyg_fb_draw_hline</function> and
+<function>CYG_FB_DRAW_HLINE</function> draw a horizontal line of the
+specified <parameter>colour</parameter>, starting at the
+<parameter>x</parameter> and <parameter>y</parameter> coordinates and
+extending to the right (increasing x) for a total of
+<parameter>len</parameter> pixels. A 50 pixel line starting at
+(100,100) will end at (149,100).
+    </para>
+    <para>
+<function>cyg_fb_draw_vline</function> and
+<function>CYG_FB_DRAW_VLINE</function> take the same arguments, but
+the line extends down (increasing y).
+    </para>
+    <para>
+These primitives do not directly support drawing lines more than one
+pixel thick, but <link linkend="framebuf-drawing-fill">block
+fills</link> can be used to achieve those. There is no generic support
+for drawing arbitrary lines, instead that is left to higher-level
+graphics toolkits.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-drawing-fill">
+    <title>Block Fills</title>
+    <para>
+Filling a rectangular part of the screen with a solid colour is
+another common requirement for higher-level code. The simplest example
+is during initialization, to set the display's whole background to a
+known value. Block fills are also often used when creating new windows
+or drawing the bulk of a simple button or scrollbar widget.
+<function>cyg_fb_fill_block</function> and
+<function>CYG_FB_FILL_BLOCK</function> provide this functionality.
+    </para>
+    <para>
+The <parameter>x</parameter> and <parameter>y</parameter> arguments
+specify the top-left corner of the block to be filled. The
+<parameter>width</parameter> and <parameter>height</parameter>
+arguments specify the number of pixels affected, a total of
+<literal>width&nbsp;*&nbsp;height</literal>. The following example
+illustrates part of the process for initializing a framebuffer,
+assumed here to have a writeable palette with default settings.
+    </para>
+    <programlisting width=72>
+int
+display_init(void)
+{
+    int result = CYG_FB_ON(FRAMEBUF);
+    if ( result ) {
+        return result;
+    }
+    CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
+                      CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
+                      CYG_FB_DEFAULT_PALETTE_WHITE);
+    &hellip;
+}
+    </programlisting>
+  </refsect1>
+
+  <refsect1 id="framebuf-drawing-block-transfers">
+    <title>Copying Blocks between the Framebuffer and Main Memory</title>
+    <para>
+The block transfer primitives serve two main purposes: drawing images.
+and saving parts of the current display to be restored later. For
+simple linear framebuffers the primitives just implement copy
+operations, with no data conversion of any sort. For non-linear ones
+the primitives act as if the framebuffer memory was linear. For
+example, consider a 2bpp display where the two bits for a single pixel
+are split over two separate bytes in framebuffer memory, or two
+planes. For a block write operation the source data should still be
+organized with four full pixels per byte, as for a linear framebuffer
+of the same depth. and the block write primitive will distribute the
+bits over the framebuffer memory as required. Similarly a block read
+will combine the appropriate bits from different locations in
+framebuffer memory and the resulting memory block will have four full
+pixels per byte.
+    </para>
+    <para>
+Because the block transfer primitives perform no data conversion, if
+they are to be used for rendering images then those images should be
+pre-formatted appropriately for the framebuffer device. For small
+images this would normally happen on the host-side as part of the
+application build process. For larger images it will usually be better
+to store them in a compressed format and decompress them at run-time,
+trading off memory for cpu cycles.
+    </para>
+    <para>
+The <parameter>x</parameter> and <parameter>y</parameter> arguments
+specify the top-left corner of the block to be transferred, and the
+<parameter>width</parameter> and <parameter>height</parameter>
+arguments determine the size. The <parameter>data</parameter>,
+<parameter>offset</parameter> and <parameter>stride</parameter>
+arguments determine the location and layout of the block in main
+memory:
+    </para>
+    <variablelist>
+      <varlistentry>
+        <term><parameter>data</parameter></term>
+        <listitem><para>
+The source or destination for the transfer. For 1bpp, 2bpp and 4bpp
+devices the data will be packed in accordance with the framebuffer
+device's endianness as per the <literal>CYG_FB_FLAGS0_LE</literal>
+flag. Each row starts in a new byte so there may be some padding on
+the right. For 16bpp and 32bpp the data should be aligned to the
+appropriate boundary.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><parameter>offset</parameter></term>
+        <listitem><para>
+Sometimes only part of an image should be written to the screen. A
+vertical offset can be achieved simply by adjusting
+<parameter>data</parameter> to point at the appropriate row within the
+image instead of the top row. For 8bpp, 16bpp and 32bpp displays
+an additional horizontal offset can also be achieved by adjusting
+<parameter>data</parameter>. However for 1bpp, 2bpp and 4bpp displays
+the starting position within the image may be in the middle of a byte.
+Hence the horizontal pixel offset can instead be specified with the
+<parameter>offset</parameter> argument.
+        </para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><parameter>stride</parameter></term>
+        <listitem><para>
+This indicates the number of bytes between rows. Usually it will be
+related to the <parameter>width</parameter>, but there are exceptions
+such as when drawing only part of an image.
+        </para></listitem>
+      </varlistentry>
+    </variablelist>
+    <para>
+The following example fills a 4bpp display with an image held in
+memory and already in the right format. If the image is smaller than
+the display it will be centered. If the image is larger then the
+center portion will fill the entire display.
+    </para>
+    <programlisting width=72>
+void
+draw_image(const void* data, int width, int height)
+{
+    cyg_ucount16 stride;
+    cyg_ucount16 x, y, offset;
+
+#if (4 != CYG_FB_DEPTH(FRAMEBUF))
+# error This code assumes a 4bpp display
+#endif
+
+    stride = (width + 1) &gt;&gt; 1;  // 4bpp to byte stride
+
+    if (width &lt; CYG_FB_WIDTH(FRAMEBUF)) {
+        x      = (CYG_FB_WIDTH(FRAMEBUF) - width) &gt;&gt; 1;
+        offset = 0;
+    } else {
+        x      = 0;
+        offset = (width - CYG_FB_WIDTH(FRAMEBUF)) &gt;&gt; 1;
+        width  = CYG_FB_WIDTH(FRAMEBUF);
+    }
+    if (height &lt; CYG_FB_HEIGHT(FRAMEBUF)) {
+        y      = (CYG_FB_HEIGHT(FRAMEBUF) - height) &gt;&gt; 1;
+    } else {
+        y      = 0;
+        data   = (const void*)((const cyg_uint8*)data +
+                 (stride * ((height - CYG_FB_HEIGHT(FRAMEBUF)) &gt;&gt; 1));
+        height = CYG_FB_HEIGHT(FRAMEBUF);
+    }
+    CYG_FB_WRITE_BLOCK(FRAMEBUF, x, y, width, height, data, offset, stride);
+}
+    </programlisting>
+  </refsect1>
+
+  <refsect1 id="framebuf-drawing-block-moves">
+    <title>Moving Blocks with the Framebuffer</title>
+    <para>
+Sometimes it is necessary to move a block of data around the screen,
+especially when using a higher-level graphics toolkit that supports
+multiple windows. Block moves can be implemented by a read into main
+memory followed by a write block, but this is expensive and imposes an
+additional memory requirement. Instead the framebuffer infrastructure
+provides a generic block move primitive. It will handle all cases
+where the source and destination positions overlap. The
+<parameter>x</parameter> and <parameter>y</parameter> arguments
+specify the top-left corner of the block to be moved, and
+<parameter>width</parameter> and <parameter>height</parameter>
+determine the block size. <parameter>new_x</parameter> and
+<parameter>new_y</parameter> specify the destination. The source data
+will remain unchanged except in areas where it overlaps the destination.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-drawing-synch">
+    <title>Synchronizing Double-Buffered Displays</title>
+    <para>
+Some framebuffer devices are double-buffered: the framebuffer memory
+that gets manipulated by the drawing primitives is separate from what
+is actually displayed, and a synch operation is needed to update the
+display. In some cases this may be because the actual display memory
+is not directly accessible by the processor, for example it may
+instead be attached via an SPI bus. Instead drawing happens in a
+buffer in main memory, and then this gets transferred over the SPI bus
+to the actual display hardware during a synch. In other cases it may
+be a software artefact. Some drawing operations, especially ones
+involving complex curves, can take a very long time and it may be
+considered undesirable to have the user see this happening a few
+pixels at a time. Instead the drawing happens in a separate buffer in
+main memory and then a double buffer synch just involves a block move
+to framebuffer memory. Typically that block move is much faster than
+the drawing operation. Obviously there is a cost: an extra area of
+memory, and the synch operation itself can consume many cycles and
+much of the available memory bandwidth.
+    </para>
+    <para>
+It is the responsibility of the framebuffer device driver to provide
+the extra main memory. As far as higher-level code is concerned the
+only difference between an ordinary and a double-buffered display is
+that with the latter changes do not become visible until a synch
+operation has been performed. The framebuffer infrastructure provides
+support for a bounding box, keeping track of what has been updated
+since the last synch. This means only the updated part of the screen
+has to be transferred to the display hardware.
+    </para>
+    <para>
+The synch primitives take two arguments. The first identifies the
+framebuffer device. The second should be one of
+<literal>CYG_FB_UPDATE_NOW</literal> for an immediate update, or
+<literal>CYG_FB_UPDATE_VERTICAL_RETRACE</literal>. Some display
+hardware involves a lengthy vertical retrace period every 10-20
+milliseconds during which nothing gets drawn to the screen, and
+performing the synch during this time means that the end user is
+unaware of the operation (assuming the synch can be completed in the
+time available). When the hardware supports it, specifying
+<literal>CYG_FB_UPDATE_VERTICAL_RETRACE</literal> means that the synch
+operation will block until the next vertical retrace takes place and
+then perform the update. This may be an expensive operation, for
+example it may involve polling a bit in a register. In a
+multi-threaded environment it may also be unreliable because the
+thread performing the synch may get interrupted or rescheduled in the
+middle of the operation. When the hardware does not involve vertical
+retraces, or when there is no easy way to detect them, the second
+argument to the synch operation will just be ignored and the update
+will always happen immediately.
+    </para>
+    <para>
+It is up to higher level code to determine when a synch operation is
+appropriate. One approach for typical event-driven code is to perform
+the synch at the start of the event loop, just before waiting for an
+input or timer event. This may not be optimal. For example if there
+two small updates to opposite corners of the screen then it would be
+better to make two synch calls with small bounding boxes, rather than
+a single synch call with a a large bounding box that requires most of
+the framebuffer memory to be updated.
+    </para>
+    <para>
+Leaving out the synch operations leads to portability problems. On
+hardware which does not involve double-buffering the synch operation
+is a no-op, usually eliminated at compile-time, so invoking synch does
+not add any code size or cpu cycle overhead. On double-buffered
+hardware, leaving out the synch means the user cannot see what has
+been drawn into the framebuffer.
+    </para>
+  </refsect1>
+  
+</refentry>
+
+<!-- }}} -->
+<!-- {{{ Iteration                      -->
+
+<refentry id="framebuf-iterating">
+  <refmeta>
+    <refentrytitle>Framebuffer Pixel Manipulation</refentrytitle>
+  </refmeta>
+  <refnamediv>
+    <refname>Pixel Manipulation</refname>
+    <refpurpose>iterating over the display</refpurpose>
+  </refnamediv>
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>
+#include &lt;cyg/io/framebuf.h&gt;
+      </funcsynopsisinfo>
+      <funcprototype>
+        <funcdef><function>CYG_FB_PIXEL0_VAR</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_PIXEL0_SET</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_PIXEL0_GET</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_PIXEL0_ADDX</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>incr</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_PIXEL0_ADDY</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>incr</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_PIXEL0_WRITE</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_fb_colour <parameter>colour</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>cyg_fb_colour <function>CYG_FB_PIXEL0_READ</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_PIXEL0_FLUSHABS</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x0</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y0</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>width</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>height</parameter></paramdef>
+      </funcprototype>
+      <funcprototype>
+        <funcdef>void <function>CYG_FB_PIXEL0_FLUSHREL</function></funcdef>
+        <paramdef><parameter>FRAMEBUF</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>x0</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>y0</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>dx</parameter></paramdef>
+        <paramdef>cyg_ucount16 <parameter>dy</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1 id="framebuf-iteration-description">
+    <title>Description</title>
+    <para>
+A common requirement for graphics code is to iterate over parts of the
+framebuffer. Drawing text typically involves iterating over a block
+of pixels for each character, say 8 by 8, setting each pixel to either
+a foreground or background colour. Drawing arbitrary lines typically
+involves moving to the start position and then adjusting the x and y
+coordinates until the end position is reached, setting a single pixel
+each time around the loop. Drawing images which are not in the frame
+buffer's native format typically involves iterating over a block of
+pixels, from top to bottom and left to right, setting pixels as the
+image is decoded.
+    </para>
+    <para>
+Functionality like this can be implemented in several ways. One
+approach is to use the pixel write primitive. Typically this involves
+some arithmetic to get from the x and y coordinates to a location
+within framebuffer memory so it is fairly expensive compared with a
+loop which just increments a pointer. Another approach is to write the
+data first to a separate buffer in memory and then use a block write
+primitive to move it to the framebuffer, but again this involves
+overhead. The eCos framebuffer support provides a third approach: a
+set of macros specifically for iterating over the frame buffer.
+Depending on the operation being performed and the details of the
+framebuffer implementation, these macros may be optimal or
+near-optimal. Obviously there are limitations. Most importantly the
+framebuffer device must be known at compile-time: the compiler can do
+a better job optimizing the code if information such as the frame
+buffer width are constant. Also each iteration must be performed
+within a single variable scope: it is not possible to do some of the
+iteration in one function, some in another.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-iteration-macros">
+    <title>The Pixel Macros</title>
+    <para>
+All the pixel macros take a framebuffer identifier as their first
+argument. This is the same identifier that can be used with the other
+macros like <function>CYG_FB_WRITE_HLINE</function> and
+<function>CYG_FB_ON</function>, one of the entries in the
+configuration option <varname>CYGDAT_IO_FRAMEBUF_DEVICES</varname>.
+Using an invalid identifier will result in numerous compile-time error
+messages which may bear little resemblance to the original code. In
+the examples below it is assumed that <varname>FRAMEBUF</varname> has
+been <literal>#define</literal>'d to a suitable identifier.
+    </para>
+    <para>
+Typical use of the pixel macros will look like this:
+    </para>
+<programlisting width=72>
+    CYG_FB_PIXEL0_VAR(FRAMEBUF);
+    &hellip;
+    CYG_FB_PIXEL0_FLUSHABS(FRAMEBUF, x, y, width, height);
+</programlisting>
+    <para>
+The <literal>VAR</literal> macro will define one or more local
+variables to keep track of the current pixel position, as appropriate
+to the framebuffer device. The other pixel macros will then use these
+variables. For a simple 8bpp linear framebuffer there will be just a
+byte pointer. For a 1bpp display there may be several variables: a
+byte pointer, a bit index within that byte, and possibly a cached
+byte; using a cached value means that the framebuffer may only get
+read and written once for every 8 pixels, and the compiler may well
+allocate a register for the cached value; on some platforms
+framebuffer access will bypass the processor's main cache, so reading
+from or writing to framebuffer memory will be slow; reducing the
+number of framebuffer accesses may greatly improve performance.
+    </para>
+    <para>
+Because the <literal>VAR</literal> macro defines one or more local
+variables it is normally placed at the start of a function or block,
+alongside other local variable definitions.
+    </para>
+    <para>
+One the iteration has been completed there should be a
+<function>FLUSHABS</function> or <function>FLUSHREL</function> macro.
+This serves two purposes. First, if the local variables involve a
+dirty cached value or similar state then this will be written back.
+Second, for double-buffered displays the macro sets a bounding box for
+the part of the screen that has been updated. This allows the double
+buffer synch operation to update only the part of the display that has
+been modified, without having to keep track of the current bounding
+box for every updated pixel. For <literal>FLUSHABS</literal> the
+<parameter>x0</parameter> and <parameter>y0</parameter> arguments
+specify the top-left corner of the bounding box, which extends for
+<parameter>width</parameter> by <parameter>height</parameter> pixels.
+For <literal>FLUSHREL</literal> <parameter>x0</parameter> and
+<parameter>y0</parameter> still specify the top-left corner, but the
+bottom-right corner is now determined from the current pixel position
+offset by <parameter>dx</parameter> and <parameter>dy</parameter>.
+More specifically, <parameter>dx</parameter> should move the current
+horizontal position one pixel to the right of the right-most pixel
+modified, such that
+<literal>(x&nbsp;+&nbsp;dx)&nbsp;-&nbsp;x0</literal> gives the width
+of the bounding box. Similarly <parameter>dy</parameter> should move
+the current vertical position one pixel below the bottom-most pixel
+modified. In typical code the current pixel position will already
+correspond in part or in whole to the bounding box corner, as a
+consequence of iterating over the block of memory.
+    </para>
+    <para>
+If a pixel variable has been used only for reading framebuffer memory,
+not for modifying it, then it should still be flushed. A
+<literal>FLUSHABS</literal> with a width and height of 0 can be used
+to indicate that the bounding box is empty. If it is known that the
+framebuffer device being used does not support double-buffering then
+again it is possible to specify an empty bounding box. Otherwise
+portable code should specify a correct bounding box. If the
+framebuffer device that ends up being used does not support double
+buffering then the relevant macro arguments are eliminated at
+compile-time and do not result in any unnecessary code. In addition if
+there is no cached value or other state then the whole flush operation
+will be a no-op and no code will be generated.
+    </para>
+    <para>
+Failure to perform the flush may result in strange drawing artefacts
+on some displays which can be very hard to debug. A
+<function>FLUSHABS</function> or <function>FLUSHREL</function> macro
+only needs to be invoked once, at the end of the iteration.
+    </para>
+    <para>
+The <literal>SET</literal> macro sets the current position within the
+framebuffer. It can be used many times within an iteration. However
+it tends to be somewhat more expensive than <literal>ADDX</literal> or
+<literal>ADDY</literal>, so usually <literal>SET</literal> is only
+executed once at the start of an iteration.
+    </para>
+<programlisting width=72>
+    CYG_FB_PIXEL0_VAR(FRAMEBUF);
+    CYG_FB_PIXEL0_SET(FRAMEBUF, x, y);
+    &hellip;
+    CYG_FB_PIXEL0_FLUSHREL(FRAMEBUF, x, y, 0, 0);
+</programlisting>
+    <para>
+The <literal>GET</literal> macro retrieves the x and y coordinates
+corresponding to the current position. It is provided mainly for
+symmetry, but can prove useful for debugging.
+    </para>
+<programlisting width=72>
+    CYG_FB_PIXEL0_VAR(FRAMEBUF);
+    CYG_FB_PIXEL0_SET(FRAMEBUF, x, y);
+    &hellip;
+#ifdef DEBUG
+    CYG_FB_PIXEL0_GET(FRAMEBUF, new_x, new_y);
+    diag_printf("Halfway through: x now %d, y now %d\n", new_x, new_y);
+#endif
+    &hellip;
+    CYG_FB_PIXEL0_FLUSHREL(FRAMEBUF, x, y, 0, 0);
+</programlisting>
+    <para>
+The <literal>ADDX</literal> and <literal>ADDY</literal> macros adjust
+the current position. The most common increments are 1 and -1, moving
+to the next or previous pixel horizontally or vertically, but any
+increment can be used.
+    </para>
+<programlisting width=72>
+    CYG_FB_PIXEL0_VAR(FRAMEBUF);
+    CYG_FB_PIXEL0_SET(FRAMEBUF, x, y);
+    for (rows = height; rows; rows--) {
+        for (columns = width; columns; columns--) {
+            &lt;perform operation&gt;
+            CYG_FB_PIXEL0_ADDX(FRAMEBUF, 1);
+        }
+        CYG_FB_PIXEL0_ADDX(FRAMEBUF, -1 * width);
+        CYG_FB_PIXEL0_ADDY(FRAMEBUF, 1);
+    }
+    CYG_FB_PIXEL0_FLUSHREL(FRAMEBUF, x, y, width, 0);
+</programlisting>
+    <para>
+Here the current position is moved one pixel to the right each time
+around the inner loop. In the outer loop the position is first moved
+back to the start of the current row, then moved one pixel down.
+For the final flush the current x position is off by
+<literal>width</literal>, but the current y position is already correct.
+    </para>
+    <para>
+The final two macros <literal>READ</literal> and
+<literal>WRITE</literal> can be used to examine or update the current
+pixel value.
+    </para>
+<programlisting width=72>
+    CYG_FB_PIXEL0_VAR(FRAMEBUF);
+    CYG_FB_PIXEL0_SET(FRAMEBUF, x, y);
+    for (rows = height; rows; rows--) {
+        for (columns = width; columns; columns--) {
+            cyg_fb_colour colour = CYG_FB_PIXEL0_READ(FRAMEBUF);
+            if (colour == colour_to_replace) {
+                CYG_FB_PIXEL0_WRITE(FRAMEBUF, replacement);
+            }
+            CYG_FB_PIXEL0_ADDX(FRAMEBUF, 1);
+        }
+        CYG_FB_PIXEL0_ADDX(FRAMEBUF, -1 * width);
+        CYG_FB_PIXEL0_ADDY(FRAMEBUF, 1);
+    }
+    CYG_FB_PIXEL0_FLUSHREL(FRAMEBUF, x, y, width, 0);
+</programlisting>
+  </refsect1>
+
+  <refsect1 id="framebuf-iteration-other">
+    <title>Concurrent Iterations</title>
+    <para>
+Although uncommon, in some cases application code may need to iterate
+over two or more blocks. An example might be an advanced block move
+where each copied pixel requires some processing. To support this
+there are <literal>PIXEL1</literal>, <literal>PIXEL2</literal> and
+<literal>PIXEL3</literal> variants of all the
+<literal>PIXEL0</literal> macros. For example:
+    </para>
+<programlisting width=72>
+    CYG_FB_PIXEL0_VAR(FRAMEBUF);
+    CYG_FB_PIXEL1_VAR(FRAMEBUF);
+
+    CYG_FB_PIXEL0_SET(FRAMEBUF, dest_x, dest_y_);
+    CYG_FB_PIXEL1_SET(FRAMEBUF, source_x, source_y);
+    for (rows = height; rows; rows--) {
+        for (columns = width; columns; columns--) {
+            colour = CYG_FB_PIXEL1_READ(FRAMEBUF);
+            &lt;do some processing on colour&gt;
+            CYG_FB_PIXEL0_WRITE(FRAMEBUF, colour);
+            CYG_FB_PIXEL0_ADDX(FRAMEBUF, 1);
+            CYG_FB_PIXEL1_ADDX(FRAMEBUF, 1);
+        }
+        CYG_FB_PIXEL0_ADDX(FRAMEBUF, -100);
+        CYG_FB_PIXEL0_ADDY(FRAMEBUF, 1);
+        CYG_FB_PIXEL1_ADDX(FRAMEBUF, -100);
+        CYG_FB_PIXEL1_ADDY(FRAMEBUF, 1);
+    }
+
+    CYG_FB_PIXEL0_FLUSHABS(FRAMEBUF, source_x, source_y, width, height);
+    CYG_FB_PIXEL1_FLUSHABS(FRAMEBUF, 0, 0, 0, 0);  // Only used for reading
+</programlisting>
+    <para>
+The <literal>PIXEL0</literal>, <literal>PIXEL1</literal>,
+<literal>PIXEL2</literal> and <literal>PIXEL3</literal> macros all use
+different local variables so there are no conflicts. The variable
+names also depend on the framebuffer device. If the target has two
+displays and two active framebuffer devices then the pixel macros can
+be used with the two devices without conflict:
+    </para>
+<programlisting width=72>
+    CYG_FB_PIXEL0_VAR(FRAMEBUF0);
+    CYG_FB_PIXEL0_VAR(FRAMEBUF1);
+    &hellip;
+</programlisting>  
+  </refsect1>
+
+</refentry>
+
+<!-- }}} -->
+<!-- {{{ Porting                        -->
+
+<refentry id="framebuf-porting">
+  <refmeta>
+    <refentrytitle>Writing a Framebuffer Device Driver</refentrytitle>
+  </refmeta>
+  <refnamediv>
+    <refname>Porting</refname>
+    <refpurpose>writing a new framebuffer device driver</refpurpose>
+  </refnamediv>
+
+  <refsect1 id="framebuf-porting-description">
+    <title>Description</title>
+    <para>
+As with most device drivers, the easiest way to write a new
+framebuffer package is to start with an existing one. Suitable ones
+include the PC VGA mode13 driver, an 8bpp paletted display, and the
+ARM iPAQ driver, a 16bpp true colour display. This document only
+outlines the process.
+    </para>
+    <para>
+Before writing any code it is necessary to decide how many framebuffer
+devices should be provided by the device driver. Each such device
+requires a <structname>cyg_fb</structname> structure and appropriate
+functions, and an identifier for use with the macro API plus
+associated macros. There are no hard rules here. Some device drivers
+may support just a single device, others may support many devices
+which drive the hardware in different modes or orientations. Optional
+functionality such as viewports and page flipping may be supported by
+having different <structname>cyg_fb</structname> devices, or by a
+number of configuration options which affect a single
+<structname>cyg_fb</structname> device. Usually providing multiple
+<structname>cyg_fb</structname> structures is harmless because the
+unused ones will get eliminated at link-time.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-porting-configuration">
+    <title>Configuration</title>
+    <para>
+The CDL for a framebuffer package is usually straightforward. A
+framebuffer package should be a hardware package and reside in the
+<filename class="directory">devs/framebuf</filename> hierarchy,
+further organized by architecture. Generic framebuffer packages, if
+any, can go into a <filename class="directory">generic</filename>
+subdirectory, and will normally rely on the platform HAL to provide
+some platform-specific information such as base addresses. The package
+should be part of the target definition and hence loaded
+automatically, but should be
+<literal>active_if&nbsp;CYGPKG_IO_FRAMEBUF</literal> so that the
+driver only gets built if the generic framebuffer support is
+explicitly added to the configuration.
+    </para>
+    <para>
+The configuration option <varname>CYGDAT_IO_FRAMEBUF_DEVICES</varname>
+should hold all the valid identifiers which can be used as the first
+argument for the macro API. This helps application developers to
+select the appropriate identifier, and allows higher-level graphics
+library packages to check that they have been configured correctly.
+This is achieved using something like the following, where
+<literal>mode13_320x200x8</literal> is a valid identifier for the PC
+VGA driver:
+    </para>
+    <programlisting width=72>
+  requires { is_substr(CYGDAT_IO_FRAMEBUF_DEVICES, " mode13_320x200x8 ") }
+    </programlisting>
+    <para>
+The spaces ensure that the CDL inference engine keeps the identifiers
+separate.
+    </para>
+    <para>
+<varname>CYGPKG_IO_FRAMEBUF</varname> contains a number of interfaces
+which should be implemented by individual device drivers when
+appropriate. This is used to eliminate some code or data structure
+fields at compile-time, keeping down memory requirements. The
+interfaces are
+<varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_32BPP</varname>,
+<varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR</varname>,
+<varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE</varname>,
+<varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE</varname>,
+<varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER</varname>,
+and <varname>CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT</varname>.
+For example if a device driver provides a true colour display but
+fails to implement the relevant interface then functions like
+<function>cyg_fb_make_colour</function> will be no-ops.
+    </para>
+    <para>
+Device drivers for paletted displays should observe the generic
+configuration option
+<varname>CYGFUN_IO_FRAMEBUF_INSTALL_DEFAULT_PALETTE</varname> and
+install either <varname>cyg_fb_palette_ega</varname> or
+<varname>cyg_fb_palette_vga</varname> as part of their
+<function>cyg_fb_on</function> implementation.
+    </para>
+  </refsect1>
+
+  <refsect1 id="framebuf-porting-header">
+    <title>Exported Header File(s)</title>
+    <para>
+Each framebuffer device driver should export one or more header files
+to <filename class="directory">cyg/io/framebufs</filename>. A custom
+build step in <varname>CYGPKG_IO_FRAMEBUF</varname> ensures that
+application code can just <literal>#include</literal> <filename
+class="headerfile">cyg/io/framebuf.h</filename> and this will
+automatically include the device-specific headers. Drivers may export
+one header per <structname>cyg_fb</structname> device or a single
+header for all devices, without affecting any code outside the device
+driver.
+    </para>
+    <para>
+Each exported header serves two purposes. First it defines the
+<link linkend="framebuf-parameters">parameters</link>, <link
+linkend="framebuf-drawing">drawing primitive</link> macros, and
+<link linkend="framebuf-iterating">iteration</link> macros for each
+device. Second it declares the <structname>cyg_fb</structname>
+structure.
+    </para>
+    <refsect2 id="framebuf-porting-header-parameters">
+      <title>Parameters</title>
+      <para>
+The parameter section should resemble the following:
+      </para>
+      <programlisting width=72>
+#define CYG_FB_320x240x16_STRUCT            cyg_ipaq_fb_320x240x16
+#define CYG_FB_320x240x16_DEPTH             16
+#define CYG_FB_320x240x16_FORMAT            CYG_FB_FORMAT_16BPP_TRUE_565
+#define CYG_FB_320x240x16_WIDTH             320
+#define CYG_FB_320x240x16_HEIGHT            240
+#define CYG_FB_320x240x16_VIEWPORT_WIDTH    320
+#define CYG_FB_320x240x16_VIEWPORT_HEIGHT   240
+#define CYG_FB_320x240x16_FLAGS0            (CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER | \
+                                             CYG_FB_FLAGS0_TRUE_COLOUR        | \
+                                             CYG_FB_FLAGS0_BLANK              | \
+                                             CYG_FB_FLAGS0_BACKLIGHT)
+#define CYG_FB_320x240x16_FLAGS1            0
+#define CYG_FB_320x240x16_FLAGS2            0
+#define CYG_FB_320x240x16_FLAGS3            0
+#define CYG_FB_320x240x16_BASE              ((void*)0x01FC0020)
+#define CYG_FB_320x240x16_STRIDE            640
+      </programlisting>
+      <para>
+Here <literal>320x240x16</literal> is the framebuffer identifier for
+use with the macro API. Application code like:
+      </para>
+      <programlisting width=72>
+#define FRAMEBUF 320x240x16
+cyg_ucount16 width = CYG_FB_WIDTH(FRAMEBUF);
+      </programlisting>
+      <para>
+will end up using the <varname>CYG_FB_320x240x16_WIDTH</varname>
+definition. To allow for efficient portable code all parameters must
+be compile-time constants. If the hardware may allow some of the
+parameters to be varied, for example different resolutions, then this
+should be handled either by defining separate devices for each
+resolution or by configuration options.
+      </para>
+      <para>
+The viewport width and height should always be defined. If the device
+driver does not support a viewport then these will be the same as the
+standard width and height.
+      </para>
+      <para>
+To allow for future expansion there are <literal>FLAGS1</literal>,
+<literal>FLAGS2</literal> and <literal>FLAGS3</literal> parameters. No
+flags are defined for these at present, but device drivers should
+still define the parameters.
+      </para>
+      </refsect2>
+
+      <refsect2 id="framebuf-porting-header-drawing">
+        <title>Drawing Primitives</title>
+        <para>
+For each device the exported header file should define macros for the
+drawing primitives, using the same naming convention as for
+parameters. In the case of true colour displays there should also be
+macros for the make-colour and break-colour primitives:
+        </para>
+        <programlisting width=72>
+#define CYG_FB_320x240x16_WRITE_PIXEL(_x_, _y_, _colour_) &hellip;
+#define CYG_FB_320x240x16_READ_PIXEL(_x_, _y_) &hellip;
+#define CYG_FB_320x240x16_WRITE_HLINE(_x_, _y_, _len_, _colour_) &hellip;
+#define CYG_FB_320x240x16_WRITE_VLINE(_x_, _y_, _len_, _colour_) &hellip;
+#define CYG_FB_320x240x16_FILL_BLOCK(_x_, _y_, _w_, _h_, _colour_) &hellip;
+#define CYG_FB_320x240x16_WRITE_BLOCK(_x_, _y_, _w_, _h_, _data_, _off_, _s_) &hellip;
+#define CYG_FB_320x240x16_READ_BLOCK(_x_, _y_, _w_, _h_, _data_, _off_, _s_) &hellip;
+#define CYG_FB_320x240x16_MOVE_BLOCK(_x_, _y_, _w_, _h_, _new_x_, _new_y_) &hellip;
+#define CYG_FB_320x240x16_MAKE_COLOUR(_r_, _g_, _b_) &hellip;
+#define CYG_FB_320x240x16_BREAK_COLOUR(_colour_, _r_, _g_, _b_) &hellip;
+        </programlisting>
+        <para>
+For typical linear framebuffers there are default implementations of
+all of these primitives in the generic framebuffer package, held in
+the exported header <filename
+class="headerfile">cyg/io/framebuf.inl</filename>. Hence the
+definitions will typically look something like:
+        </para>
+        <programlisting width=72>
+#include &lt;cyg/io/framebuf.inl&gt;
+&hellip;
+#define CYG_FB_320x240x16_WRITE_PIXEL(_x_, _y_, _colour_)      \
+    CYG_MACRO_START                                            \
+    cyg_fb_linear_write_pixel_16_inl(CYG_FB_320x240x16_BASE,   \
+                                     CYG_FB_320x240x16_STRIDE, \
+                                     _x_, _y_, _colour_);      \
+    CYG_MACRO_END
+#define CYG_FB_320x240x16_READ_PIXEL(_x_, _y_)                   \
+    ({ cyg_fb_linear_read_pixel_16_inl(CYG_FB_320x240x16_BASE,   \
+                                       CYG_FB_320x240x16_STRIDE, \
+                                       _x_, _y_); })
+&hellip;
+        </programlisting>
+        <para>
+All of the drawing primitives have variants for the common display
+depths and layouts: 1le, 1be, 2le, 2be, 4le, 4be, 8, 16 and 32. The
+inlines take the framebuffer memory base address as the first
+argument, and the stride in bytes as the second. Similarly there are
+default definitions of the true colour primitives for
+<literal>8BPP_TRUE_332</literal>, <literal>16BPP_TRUE_565</literal>,
+<literal>16BPP_TRUE_555</literal>, and <literal>32BPP_TRUE_0888</literal>:
+        </para>
+        <programlisting width=72>
+#define CYG_FB_320x240x16_MAKE_COLOUR(_r_, _g_, _b_)             \
+    ({  CYG_FB_MAKE_COLOUR_16BPP_TRUE_565(_r_, _g_, _b_); })
+#define CYG_FB_320x240x16_BREAK_COLOUR(_colour_, _r_, _g_, _b_)  \
+    CYG_MACRO_START                                              \
+    CYG_FB_BREAK_COLOUR_16BPP_TRUE_565(_colour_, _r_, _g_, _b_); \
+    CYG_MACRO_END
+        </programlisting>
+        <para>
+If the hardware does not implement a linear framebuffer then obviously
+writing the device driver will be significantly more work. The macros
+will have to perform the operations themselves instead of relying on
+generic implementations. The required functionality should be obvious,
+and the generic implementations can still be consulted as a reference.
+For complicated hardware it may be appropriate to map the macros onto
+function calls, rather than try to implement everything inline.
+        </para>
+        <note><para> At the time of writing the support for linear
+framebuffers is incomplete. Only 8bpp, 16bpp and 32bpp depths have
+full support. There may also be future extensions, for example
+<literal>r90</literal>, <literal>r180</literal> and
+<literal>r270</literal> variants to support rotation in software, and
+<literal>db</literal> variants to support double-buffered displays.
+         </para></note>
+      </refsect2>
+
+      <refsect2 id="framebuf-porting-header-iterating">
+        <title>Iteration Macros</title>
+        <para>
+In addition to the drawing primitives the exported header file should
+define iteration macros:
+        </para>
+        <programlisting width=72>
+#define CYG_FB_320x240x16_PIXELx_VAR(  _fb_, _id_) &hellip;
+#define CYG_FB_320x240x16_PIXELx_SET(  _fb_, _id_, _x_, _y_) &hellip;
+#define CYG_FB_320x240x16_PIXELx_GET(  _fb_, _id_, _x_, _y_) &hellip;
+#define CYG_FB_320x240x16_PIXELx_ADDX( _fb_, _id_, _incr_) &hellip;
+#define CYG_FB_320x240x16_PIXELx_ADDY( _fb_, _id_, _incr_) &hellip;
+#define CYG_FB_320x240x16_PIXELx_WRITE(_fb_, _id_, _colour_) &hellip;
+#define CYG_FB_320x240x16_PIXELx_READ( _fb_, _id_)&hellip;
+#define CYG_FB_320x240x16_PIXELx_FLUSHABS( _fb_, _id_, _x0_, _y0_, _w_, _h_) &hellip;
+#define CYG_FB_320x240x16_PIXELx_FLUSHREL( _fb_, _id_, _x0_, _y0_, _dx_, _dy_) &hellip;
+        </programlisting>
+        <para>
+The <parameter>_fb_</parameter> argument will be the identifier, in
+this case <literal>320x240x16</literal>, and the
+<parameter>_id_</parameter> will be a small number, 0 for a
+<literal>PIXEL0</literal> iteration, 1 for <literal>PIXEL1</literal>,
+and so on. Together these two should allow unique local variable names
+to be constructed. Again there are default definitions of the macros
+in <filename class="headerfile">cyg/io/framebuf.inl</filename> for
+linear framebuffers:
+        </para>
+        <programlisting width=72>
+#define CYG_FB_320x240x16_PIXELx_VAR(  _fb_, _id_) \
+    CYG_FB_PIXELx_VAR_16(  _fb_, _id_)
+#define CYG_FB_320x240x16_PIXELx_SET(  _fb_, _id_, _x_, _y_)    \
+    CYG_MACRO_START                                             \
+    CYG_FB_PIXELx_SET_16( _fb_, _id_,                           \
+                          CYG_FB_320x240x16_BASE,               \
+                          320, _x_, _y_);                       \
+    CYG_MACRO_END
+        </programlisting>
+        <para>
+The linear <literal>SET</literal> and <literal>GET</literal> macros
+take base and stride information. The <literal>ADDX</literal> and
+<literal>ADDY</literal> macros only need the stride. By convention
+most of the macros are wrapped in
+<literal>CYG_MACRO_START</literal>/<literal>CYG_MACRO_END</literal> or
+<literal>({</literal>/<literal>})</literal> pairs, allowing debug code
+to be inserted if necessary. However the <literal>_VAR</literal> macro
+must not be wrapped in this way: its purpose is to define one or more
+local variables; wrapping the macro would declare the variables in a
+new scope, inaccessible to the other macros.
+        </para>
+        <para>
+Again for non-linear framebuffers it will be necessary to implement
+these macros fully rather than rely on generic implementations, but
+the generic versions can be consulted as a reference.
+        </para>
+      </refsect2>
+
+      <refsect2 id="framebuf-porting-header-fb">
+        <title>The <structname>cyg_fb</structname> declaration</title>
+        <para>
+Finally there should be an export of the
+<structname>cyg_fb</structname> structure or structures. Typically
+this uses the <literal>_STRUCT</literal> parameter, reducing the
+possibility of an accidental mismatch between the macro and function APIs:
+        </para>
+        <programlisting width=72>
+extern cyg_fb   CYG_FB_320x240x16_STRUCT;
+        </programlisting>
+      </refsect2>
+
+</refsect1>
+
+  <refsect1 id="framebuf-porting-source">
+    <title>Driver-Specific Source Code</title>
+    <para>
+Exporting parameters and macros in a header file is not enough. It is
+also necessary to actually define the <structname>cyg_fb</structname>
+structure or structures, and to provide hardware-specific versions of
+the control operations. For non-linear framebuffers it will also be
+necessary to provide the drawing functions. There is a utility macro
+<function>CYG_FB_FRAMEBUFFER</function> for instantiating a
+<structname>cyg_fb</structname> structure. Drivers may ignore this
+macro and do the work themselves, but at an increased risk of
+compatibility problems with future versions of the generic code.
+    </para>
+    <programlisting width=72>
+CYG_FB_FRAMEBUFFER(CYG_FB_320x240x16_STRUCT,
+                   CYG_FB_320x240x16_DEPTH,
+                   CYG_FB_320x240x16_FORMAT,
+                   CYG_FB_320x240x16_WIDTH,
+                   CYG_FB_320x240x16_HEIGHT,
+                   CYG_FB_320x240x16_VIEWPORT_WIDTH,
+                   CYG_FB_320x240x16_VIEWPORT_HEIGHT,
+                   CYG_FB_320x240x16_BASE,
+                   CYG_FB_320x240x16_STRIDE,
+                   CYG_FB_320x240x16_FLAGS0,
+                   CYG_FB_320x240x16_FLAGS1,
+                   CYG_FB_320x240x16_FLAGS2,
+                   CYG_FB_320x240x16_FLAGS3,
+                   0, 0, 0, 0,   // fb_driver0 -> fb_driver3
+                   &amp;cyg_ipaq_fb_on,
+                   &amp;cyg_ipaq_fb_off,
+                   &amp;cyg_ipaq_fb_ioctl,
+                   &amp;cyg_fb_nop_synch,
+                   &amp;cyg_fb_nop_read_palette,
+                   &amp;cyg_fb_nop_write_palette,
+                   &amp;cyg_fb_dev_make_colour_16bpp_true_565,
+                   &amp;cyg_fb_dev_break_colour_16bpp_true_565,
+                   &amp;cyg_fb_linear_write_pixel_16,
+                   &amp;cyg_fb_linear_read_pixel_16,
+                   &amp;cyg_fb_linear_write_hline_16,
+                   &amp;cyg_fb_linear_write_vline_16,
+                   &amp;cyg_fb_linear_fill_block_16,
+                   &amp;cyg_fb_linear_write_block_16,
+                   &amp;cyg_fb_linear_read_block_16,
+                   &amp;cyg_fb_linear_move_block_16,
+                   0, 0, 0, 0 // fb_spare0 -> fb_spare3
+);
+    </programlisting>
+    <para>
+The first 13 arguments to the macro correspond to the device
+parameters. The next four are arbitrary <type>CYG_ADDRWORD</type>
+values for use by the device driver. Typically these are used to share
+on/off/ioctl functions between multiple
+<structname>cyg_fb</structname> structure. They are followed by
+function pointers: on/off/ioctl control; double buffer synch; palette
+management; true colour support; and the drawing primitives.
+<literal>nop</literal> versions of the on, off, ioctl, synch, palette
+management and true colour functions are provided by the generic
+framebuffer package, and often these arguments to the
+<function>CYG_FB_FRAMEBUFFER</function> macro will be discarded
+at compile-time because the relevant CDL interface is not implemented.
+The final four arguments are currently unused and should be 0. They
+are intended for future expansion, with a value of 0 indicating that a
+device driver does not implement non-core functionality.
+    </para>
+    <para>
+As with the macros there are default implementations of the true
+colour primitives for <literal>8bpp_true_332</literal>,
+<literal>16bpp_true_565</literal>, <literal>16bpp_true_555</literal>
+and <literal>32bpp_true_0888</literal>. There are also default
+implementations of the drawing primitives for linear framebuffers,
+with variants for the common display depths and layouts. Obviously
+non-linear framebuffers will need rather more work.
+    </para>
+    <para>
+Typically a true colour or grey scale framebuffer device driver will
+have to implement just three hardware-specific functions:
+    </para>
+    <programlisting width=72>
+int
+cyg_ipaq_fb_on(cyg_fb* fb)
+{
+    &hellip;
+}
+
+int
+cyg_ipaq_fb_off(cyg_fb* fb)
+{
+    &hellip;
+}
+
+int
+cyg_ipaq_fb_ioctl(cyg_fb* fb, cyg_ucount16 key, void* data, size_t* len)
+{
+    int result;
+
+    switch(key) {
+        case CYG_FB_IOCTL_BLANK_GET: &hellip;
+        &hellip;
+        default: result = ENOSYS; break;
+    }
+    return result;
+}
+    </programlisting>
+    <para>
+These control operations are entirely hardware-specific and cannot be
+implemented by generic code. Paletted displays will need two more
+functions, again hardware-specific:
+    </para>
+    <programlisting width=72>
+void
+cyg_pcvga_fb_read_palette(cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 len,
+                          void* data)
+{
+    &hellip;
+}
+
+void
+cyg_pcvga_fb_write_palette(cyg_fb* fb, cyg_ucount32 first,  cyg_ucount32 len,
+                           const void* data, cyg_ucount16 when)
+{
+    &hellip;
+}
+    </programlisting>
+  </refsect1>
+
+  <refsect1 id="framebuf-porting-expansion">
+    <title>Future Expansion</title>
+    <para>
+As has been mentioned before framebuffer hardware varies widely. The
+design of a generic framebuffer API requires complicated trade-offs
+between efficiency, ease of use, ease of porting, and still supporting
+a very wide range of hardware. To some extent this requires a lowest
+common denominator approach, but the design allows for some future
+expansion and optional support for more advanced features like
+hardware acceleration.
+    </para>
+    <para>
+The most obvious route for expansion is the <function>ioctl</function>
+interface. Device drivers can define their own keys, values
+<literal>0x8000</literal> and higher, for any operation. Alternatively
+a device driver does not have to implement just the interface provided
+by the generic framebuffer package: additional functions and macros
+can be exported as required.
+    </para>
+    <para>
+Currently there are only a small number of <function>ioctl</function>
+operations. Additional ones may get added in future, for example to
+support a hardware mouse cursor, but only in cases where the
+functionality is likely to be provided by a significant number of
+framebuffer devices. Adding new generic functionality adds to the
+maintenance overhead of both code and documentation. When a new
+generic <function>ioctl</function> operation is added there will
+usually also be one or more new flags, so that device drivers can
+indicate they support the functionality. At the time of writing only
+12 of the 32 <literal>FLAGS0</literal> flags are used, and a further
+96 are available in <literal>FLAGS1</literal>,
+<literal>FLAGS2</literal> and <literal>FLAGS3</literal>.
+    </para>
+    <para>
+Another route for future expansion is the four spare arguments to the
+<function>CYG_FB_FRAMEBUFFER</function> macro. As an example of how
+these may get used in future, consider support for 3d hardware
+acceleration. One of the spare fields would become another table of
+function pointers to the various accelerators, or possibly a
+structure. A <literal>FLAGS0</literal> flag would indicate that the
+device driver implements such functionality.
+    </para>
+    <para>
+Other forms of expansion such as defining a new standard drawing
+primitive would be more difficult, since this would normally involve
+changing the <function>CYG_FB_FRAMEBUFFER</function> macro. Such
+expansion should not be necessary because the existing primitives
+provide all reasonable core functionality. Instead other packages such
+as graphics libraries can work on top of the existing primitives.
+    </para>
+  </refsect1>
+
+</refentry>
+
+<!-- }}} -->
+
+</part>
Index: include/framebuf.h
===================================================================
RCS file: include/framebuf.h
diff -N include/framebuf.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ include/framebuf.h	7 Oct 2008 10:03:04 -0000
@@ -0,0 +1,1024 @@
+#ifndef CYGONCE_IO_FRAMEBUF_H
+#define CYGONCE_IO_FRAMEBUF_H
+
+//=============================================================================
+//
+//      framebuf.h
+//
+//      Generic API for accessing framebuffers
+//
+//=============================================================================
+//###ECOSGPLCOPYRIGHTBEGIN####
+//-------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//####DESCRIPTIONBEGIN####
+//
+// Author(s): 	bartv
+// Date:	    2005-03-29
+//####DESCRIPTIONEND####
+//=============================================================================
+
+#include <pkgconf/infra.h>
+#include <pkgconf/io_framebuf.h>
+#include <cyg/infra/cyg_type.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ----------------------------------------------------------------------------
+// The colour data type. For now this is a cyg_ucount32. On 16-bit targets
+// where the display depth is less than 32bpp a cyg_ucount16 would suffice
+// and be more efficient. A separate cyg_fb_colour type is used to allow this
+// change to be made in future.
+typedef cyg_ucount32    cyg_fb_colour;
+typedef cyg_fb_colour   cyg_fb_color;
+   
+// ----------------------------------------------------------------------------
+// Each framebuffer device exports one of these structures
+typedef struct cyg_fb {
+#ifdef CYGPKG_INFRA_DEBUG
+    cyg_ucount32    fb_magic;
+#endif    
+    cyg_ucount16    fb_depth;   // 1, 2, 4, 8, 16, or 32 bits per pixel
+    cyg_ucount16    fb_format;  // detailed format, e.g. 8-bit paletted, or 32-bit 0888
+    cyg_ucount16    fb_width;   // of the framebuffer, not the viewport
+    cyg_ucount16    fb_height;
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT
+    cyg_ucount16    fb_viewport_width;
+    cyg_ucount16    fb_viewport_height;
+#endif
+    void*           fb_base;    // Base address of the framebuffer, or 0 if not directly accessible
+    cyg_ucount16    fb_stride;  // number of bytes per line
+    cyg_uint32      fb_flags0;
+    cyg_uint32      fb_flags1;
+    cyg_uint32      fb_flags2;
+    cyg_uint32      fb_flags3;
+
+    CYG_ADDRWORD    fb_driver0; // Driver private fields
+    CYG_ADDRWORD    fb_driver1;
+    CYG_ADDRWORD    fb_driver2;
+    CYG_ADDRWORD    fb_driver3;
+    
+    int             (*fb_on_fn)(struct cyg_fb*);
+    int             (*fb_off_fn)(struct cyg_fb*);
+    int             (*fb_ioctl_fn)(      struct cyg_fb*, cyg_ucount16, void*,        size_t*);
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER    
+    void            (*fb_synch_fn)(      struct cyg_fb*, cyg_ucount16);
+#endif
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE
+    void            (*fb_read_palette_fn)(struct cyg_fb*, cyg_ucount32, cyg_ucount32, void*);
+#endif
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE
+    void            (*fb_write_palette_fn)(struct cyg_fb*, cyg_ucount32, cyg_ucount32, const void*, cyg_ucount16);
+#endif
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+    cyg_fb_colour   (*fb_make_colour_fn)(struct cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+    void            (*fb_break_colour_fn)(struct cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+#endif    
+    
+    void            (*fb_write_pixel_fn)(struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_fb_colour);
+    cyg_fb_colour   (*fb_read_pixel_fn)( struct cyg_fb*, cyg_ucount16, cyg_ucount16);
+    void            (*fb_write_hline_fn)(struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_fb_colour);
+    void            (*fb_write_vline_fn)(struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_fb_colour);
+    void            (*fb_fill_block_fn)( struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_fb_colour);
+    void            (*fb_write_block_fn)(struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_ucount16, const void*, cyg_ucount16, cyg_ucount16);
+    void            (*fb_read_block_fn)( struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_ucount16, void*, cyg_ucount16, cyg_ucount16);
+    void            (*fb_move_block_fn)( struct cyg_fb*, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_ucount16, cyg_ucount16);
+} cyg_fb;
+
+// A magic number used to validate an fb pointer
+#define CYG_FB_MAGIC    0xC201e147    
+
+// The various supported colour formats. A 16-bit value.
+#define CYG_FB_FORMAT_1BPP_MONO_0_BLACK         0x0000
+#define CYG_FB_FORMAT_1BPP_MONO_0_WHITE         0x0001
+#define CYG_FB_FORMAT_1BPP_PAL888               0x0002
+
+#define CYG_FB_FORMAT_2BPP_GREYSCALE_0_BLACK    0x0100
+#define CYG_FB_FORMAT_2BPP_GRAYSCALE_0_BLACK    0x0100
+#define CYG_FB_FORMAT_2BPP_GREYSCALE_0_WHITE    0x0101
+#define CYG_FB_FORMAT_2BPP_GRAYSCALE_0_WHITE    0x0101
+#define CYG_FB_FORMAT_2BPP_PAL888               0x0102
+
+#define CYG_FB_FORMAT_4BPP_GREYSCALE_0_BLACK    0x0200
+#define CYG_FB_FORMAT_4BPP_GRAYSCALE_0_BLACK    0x0200
+#define CYG_FB_FORMAT_4BPP_GREYSCALE_0_WHITE    0x0201
+#define CYG_FB_FORMAT_4BPP_GRAYSCALE_0_WHITE    0x0202
+#define CYG_FB_FORMAT_4BPP_PAL888               0x0203
+
+#define CYG_FB_FORMAT_8BPP_PAL888               0x0300
+#define CYG_FB_FORMAT_8BPP_TRUE_332             0x0301
+    
+#define CYG_FB_FORMAT_16BPP_TRUE_565            0x0400
+#define CYG_FB_FORMAT_16BPP_TRUE_555            0x0401
+
+#define CYG_FB_FORMAT_32BPP_TRUE_0888           0x0500
+    
+// Flags indicating exactly what the device driver can support.
+// Each fb structure has four flags fields for a maximum of
+// 128 flags, allowing for future expansion at a relatively
+// low cost.
+    
+// The framebuffer memory is directly accessible and organized in a
+// conventional fashion, i.e. increasing x means the addresses
+// increase by 1 bit/nibble/byte/short/int as appropriate, and
+// increasing y means adding n bytes/shorts/ints
+#define CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER        (0x01 <<  0)
+// Only relevant for 1bpp, 2bpp and 4bpp displays. Little-endian
+// means that pixel (0,0) occupies bit 0 of framebuffer byte 0.
+// 0. Big-endian means that pixel(0,0) occupies bit 7.
+#define CYG_FB_FLAGS0_LE                        (0x01 <<  1)
+
+#define CYG_FB_FLAGS0_TRUE_COLOUR               (0x01 <<  8)    
+#define CYG_FB_FLAGS0_TRUE_COLOR                (0x01 <<  8)    
+#define CYG_FB_FLAGS0_PALETTE                   (0x01 <<  9)
+#define CYG_FB_FLAGS0_WRITEABLE_PALETTE         (0x01 << 10)
+    
+#define CYG_FB_FLAGS0_DELAYED_PALETTE_UPDATE    (0x01 << 16)
+#define CYG_FB_FLAGS0_VIEWPORT                  (0x01 << 17)
+#define CYG_FB_FLAGS0_DOUBLE_BUFFER             (0x01 << 18)
+#define CYG_FB_FLAGS0_PAGE_FLIPPING             (0x01 << 19)
+#define CYG_FB_FLAGS0_BLANK                     (0x01 << 20)
+#define CYG_FB_FLAGS0_BACKLIGHT                 (0x01 << 21)
+#define CYG_FB_FLAGS0_MUST_BE_ON                (0x01 << 22)
+    
+// Some operations including updating the palette, double-buffer
+// synch, page flipping and moving the viewport take an argument
+// to specify when the operation should happen. Driver support
+// for this is optional.    
+#define CYG_FB_UPDATE_NOW                       0x0000
+#define CYG_FB_UPDATE_VERTICAL_RETRACE          0x0001
+
+// ----------------------------------------------------------------------------
+// Macro to define a framebuffer. A couple of auxiliary macros are used
+// for the conditional fields.
+#ifdef CYGPKG_INFRA_DEBUG    
+# define CYG_FB_FRAMEBUFFER_DEBUG   \
+      .fb_magic   = CYG_FB_MAGIC,
+#else
+# define CYG_FB_FRAMEBUFFER_DEBUG
+#endif    
+
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT    
+# define CYG_FB_FRAMEBUFFER_VIEWPORT(_width_, _height_) \
+    .fb_viewport_width  = _width_,                      \
+    .fb_viewport_height = _height_,
+#else
+# define CYG_FB_FRAMEBUFFER_VIEWPORT(_width_, _height_)
+#endif
+
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER
+# define CYG_FB_FRAMEBUFFER_SYNCH_FN(_fn_)              \
+    .fb_synch_fn = _fn_,
+#else
+# define CYG_FB_FRAMEBUFFER_SYNCH_FN(_fn_)
+#endif
+    
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE
+# define CYG_FB_FRAMEBUFFER_READ_PALETTE_FN(_fn_)       \
+    .fb_read_palette_fn     = _fn_,
+#else
+# define CYG_FB_FRAMEBUFFER_READ_PALETTE_FN(_fn_)
+#endif
+
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE
+# define CYG_FB_FRAMEBUFFER_WRITE_PALETTE_FN(_fn_)      \
+    .fb_write_palette_fn     = _fn_,
+#else
+# define CYG_FB_FRAMEBUFFER_WRITE_PALETTE_FN(_fn_)
+#endif
+
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+# define CYG_FB_FRAMEBUFFER_MAKE_COLOUR_FN(_fn_) \
+    .fb_make_colour_fn      = _fn_,
+# define CYG_FB_FRAMEBUFFER_BREAK_COLOUR_FN(_fn_) \
+    .fb_break_colour_fn     = _fn_,
+#else
+# define CYG_FB_FRAMEBUFFER_MAKE_COLOUR_FN(_fn_)
+# define CYG_FB_FRAMEBUFFER_BREAK_COLOUR_FN(_fn_)
+#endif
+    
+#define CYG_FB_FRAMEBUFFER(_name_, _depth_, _format_,                                               \
+                           _width_, _height_, _viewport_width_, _viewport_height_,                  \
+                           _base_, _stride_,                                                        \
+                           _flags0_, _flags1_, _flags2_, _flags3_,                                  \
+                           _driver0_, _driver1_, _driver2_, _driver3_,                              \
+                           _on_fn_, _off_fn_, _ioctl_fn_, _synch_fn_,                               \
+                           _read_palette_fn_, _write_palette_fn_,                                   \
+                           _make_colour_fn_, _break_colour_fn_,                                     \
+                           _write_pixel_fn_, _read_pixel_fn_, _write_hline_fn_, _write_vline_fn_,   \
+                           _fill_block_fn_, _write_block_fn_, _read_block_fn_, _move_block_fn_,     \
+                           _spare0_, _spare1_, _spare2_, _spare3_ )                                 \
+struct cyg_fb _name_ = {                                                \
+    CYG_FB_FRAMEBUFFER_DEBUG                                            \
+    .fb_depth           = _depth_,                                      \
+    .fb_format          = _format_,                                     \
+    .fb_width           = _width_,                                      \
+    .fb_height          = _height_,                                     \
+    CYG_FB_FRAMEBUFFER_VIEWPORT(_viewport_width_, _viewport_height_)    \
+    .fb_stride          = _stride_,                                     \
+    .fb_base            = _base_,                                       \
+    .fb_flags0          = _flags0_,                                     \
+    .fb_flags1          = _flags1_,                                     \
+    .fb_flags2          = _flags2_,                                     \
+    .fb_flags3          = _flags3_,                                     \
+    .fb_driver0         = _driver0_,                                    \
+    .fb_driver1         = _driver1_,                                    \
+    .fb_driver2         = _driver2_,                                    \
+    .fb_driver3         = _driver3_,                                    \
+    .fb_on_fn           = _on_fn_,                                      \
+    .fb_off_fn          = _off_fn_,                                     \
+    .fb_ioctl_fn        = _ioctl_fn_,                                   \
+    CYG_FB_FRAMEBUFFER_SYNCH_FN(_synch_fn_)                             \
+    CYG_FB_FRAMEBUFFER_READ_PALETTE_FN(_read_palette_fn_)               \
+    CYG_FB_FRAMEBUFFER_WRITE_PALETTE_FN(_write_palette_fn_)             \
+    CYG_FB_FRAMEBUFFER_MAKE_COLOUR_FN(_make_colour_fn_)                 \
+    CYG_FB_FRAMEBUFFER_BREAK_COLOUR_FN(_break_colour_fn_)               \
+    .fb_write_pixel_fn  = _write_pixel_fn_,                             \
+    .fb_read_pixel_fn   = _read_pixel_fn_,                              \
+    .fb_write_hline_fn  = _write_hline_fn_,                             \
+    .fb_write_vline_fn  = _write_vline_fn_,                             \
+    .fb_fill_block_fn   = _fill_block_fn_,                              \
+    .fb_write_block_fn  = _write_block_fn_,                             \
+    .fb_read_block_fn   = _read_block_fn_,                              \
+    .fb_move_block_fn   = _move_block_fn_                               \
+}
+
+ 
+// ----------------------------------------------------------------------------
+// ioctl() operations: these are defined by a 16-bit key. The top byte
+// gives a category, with values of 0x8000 onwards reserved for use by
+// individual device drivers. The bottom byte defines the actual
+// operation. This gives 128 generic ioctl categories.
+
+# define CYG_FB_IOCTL_VIEWPORT_GET_POSITION     0x0100
+# define CYG_FB_IOCTL_VIEWPORT_SET_POSITION     0x0101
+
+typedef struct cyg_fb_ioctl_viewport {
+    cyg_ucount16    fbvp_x;     // position of top-left corner of the viewport within
+    cyg_ucount16    fbvp_y;     // the framebuffer
+    cyg_ucount16    fbvp_when;  // set-only, now or vert retrace
+} cyg_fb_ioctl_viewport;
+
+# define CYG_FB_IOCTL_PAGE_FLIPPING_GET_PAGES   0x0200
+# define CYG_FB_IOCTL_PAGE_FLIPPING_SET_PAGES   0x0201
+
+typedef struct cyg_fb_ioctl_page_flip {
+    cyg_uint32      fbpf_number_pages;
+    cyg_uint32      fbpf_visible_page;
+    cyg_uint32      fbpf_drawable_page;
+    cyg_ucount16    fbpf_when;  // set-only, now or vert retrace
+} cyg_fb_ioctl_page_flip;
+
+# define CYG_FB_IOCTL_BLANK_GET                 0x0300
+# define CYG_FB_IOCTL_BLANK_SET                 0x0301
+
+typedef struct cyg_fb_ioctl_blank {
+    cyg_bool        fbbl_on;
+} cyg_fb_ioctl_blank;
+
+# define CYG_FB_IOCTL_BACKLIGHT_GET             0x0400
+# define CYG_FB_IOCTL_BACKLIGHT_SET             0x0401
+
+typedef struct cyg_fb_ioctl_backlight {
+    cyg_ucount32    fbbl_current;
+    cyg_ucount32    fbbl_max;
+} cyg_fb_ioctl_backlight;
+
+// ----------------------------------------------------------------------------
+// The functional API. This can be implemented either by inlines or by
+// explicit functions, the latter allowing extra assertions.
+
+#if defined(CYGPKG_INFRA_DEBUG) || defined(__CYG_FB_IN_FRAMEBUF_C)
+
+extern int              cyg_fb_on(cyg_fb*);
+extern int              cyg_fb_off(cyg_fb*);
+extern void             cyg_fb_write_pixel( cyg_fb*,
+                                            cyg_ucount16 /* x */,       cyg_ucount16 /* y */,
+                                            cyg_fb_colour);
+extern cyg_fb_colour    cyg_fb_read_pixel(  cyg_fb*,
+                                            cyg_ucount16 /* x */,       cyg_ucount16 /* y */);
+extern void             cyg_fb_write_hline( cyg_fb*,
+                                            cyg_ucount16 /* x */,       cyg_ucount16 /* y */,
+                                            cyg_ucount16 /* len */,
+                                            cyg_fb_colour);
+extern void             cyg_fb_write_vline( cyg_fb*,
+                                            cyg_ucount16 /* x */,       cyg_ucount16 /* y */,
+                                            cyg_ucount16 /* len */,
+                                            cyg_fb_colour);
+extern void             cyg_fb_fill_block(  cyg_fb*,
+                                            cyg_ucount16 /* x */,       cyg_ucount16 /* y */,
+                                            cyg_ucount16 /* width */,   cyg_ucount16 /* height */,
+                                            cyg_fb_colour);
+extern void             cyg_fb_write_block( cyg_fb*,
+                                            cyg_ucount16 /* x */,       cyg_ucount16 /* y */,
+                                            cyg_ucount16 /* width */,   cyg_ucount16 /* height */,
+                                            const void*  /* source */,
+                                            cyg_ucount16 /* offset */,  cyg_ucount16 /* source stride */);
+extern void             cyg_fb_read_block(  cyg_fb*,
+                                            cyg_ucount16 /* x */,       cyg_ucount16 /* y */,
+                                            cyg_ucount16 /* width */,   cyg_ucount16 /* height */,
+                                            void*        /* dest */,
+                                            cyg_ucount16 /* offset */,  cyg_ucount16 /* source stride */);
+extern void             cyg_fb_move_block(  cyg_fb*,
+                                            cyg_ucount16 /* x */,       cyg_ucount16 /* y */,
+                                            cyg_ucount16 /* width */,   cyg_ucount16 /* height */,
+                                            cyg_ucount16 /* new_x */,   cyg_ucount16 /* new_y */);
+extern int              cyg_fb_ioctl(       cyg_fb*,
+                                            cyg_uint16  /* key */,
+                                            void*       /* data */,
+                                            size_t*     /* len */);
+
+extern void             cyg_fb_synch(       cyg_fb*,
+                                            cyg_ucount16 /* when */);
+    
+extern void             cyg_fb_write_palette(   cyg_fb*,
+                                                cyg_ucount32    /* first  */,
+                                                cyg_ucount32    /* count  */,
+                                                const void*     /* source */,
+                                                cyg_ucount16    /* when   */);
+extern void             cyg_fb_read_palette(    cyg_fb*,
+                                                cyg_ucount32    /* first */,
+                                                cyg_ucount32    /* count */,
+                                                void*           /* dest  */);
+
+extern cyg_fb_colour    cyg_fb_make_colour(     cyg_fb*,
+                                               cyg_ucount8 /* r */, cyg_ucount8 /* g */, cyg_ucount8 /* b */);
+
+extern void             cyg_fb_break_colour(    cyg_fb*,
+                                                cyg_fb_colour,
+                                                cyg_ucount8* /* r */, cyg_ucount8* /* g */, cyg_ucount8* /* b */);
+
+#else
+
+extern __inline__ int
+cyg_fb_on(cyg_fb* _fb_)
+{
+    return (*(_fb_->fb_on_fn))(_fb_);
+}
+
+extern __inline__ int
+cyg_fb_off(cyg_fb* _fb_)
+{
+    return (*(_fb_->fb_off_fn))(_fb_);
+}
+
+extern __inline__ void
+cyg_fb_write_pixel(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_count32 _colour_)
+{
+    (*(_fb_->fb_write_pixel_fn))(_fb_, _x_, _y_, _colour_);
+}
+
+extern __inline__ cyg_fb_colour
+cyg_fb_read_pixel(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_)
+{
+    return (*(_fb_->fb_read_pixel_fn))(_fb_, _x_, _y_);
+}
+
+extern __inline__ void
+cyg_fb_write_hline(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_)
+{
+    (*(_fb_->fb_write_hline_fn))(_fb_, _x_, _y_, _len_, _colour_);
+}
+
+extern __inline__ void
+cyg_fb_write_vline(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_)
+{
+    (*(_fb_->fb_write_vline_fn))(_fb_, _x_, _y_, _len_, _colour_);
+}
+
+extern __inline__ void
+cyg_fb_fill_block(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_, cyg_fb_colour _colour_)
+{
+    (*(_fb_->fb_fill_block_fn))(_fb_, _x_, _y_, _width_, _height_, _colour_);
+}
+
+extern __inline__ void
+cyg_fb_write_block(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                   const void* _source_, cyg_ucount16 _offset_, cyg_ucount16 _stride_)
+{
+    (*(_fb_->fb_write_block_fn))(_fb_, _x_, _y_, _width_, _height_, _source_, _offset_, _stride_);
+}
+
+extern __inline__ void
+cyg_fb_read_block(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                  void* _dest_, cyg_ucount16 _offset_, cyg_ucount16 _stride_)
+{
+    (*((_fb_)->fb_read_block_fn))(_fb_, _x_, _y_, _width_, _height_, _dest_, _offset_, _stride_);
+}
+
+extern __inline__ void
+cyg_fb_move_block(cyg_fb* _fb_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_, cyg_ucount16 _newx_, cyg_ucount16 _newy_)
+{
+    (*(_fb_->fb_move_block_fn))(_fb_, _x_, _y_, _width_, _height_, _newx_, _newy_);
+}
+
+extern __inline__ int
+cyg_fb_ioctl(cyg_fb* _fb_, cyg_uint16  _key_, void* _data_, size_t* _len_)
+{
+    int result = (*(_fb_->fb_ioctl_fn))(_fb_, _key_, _data_, _len_);
+    return result;
+}
+
+extern __inline__ void
+cyg_fb_synch(cyg_fb* _fb_, cyg_ucount16 _when_)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER    
+    (*(_fb_->fb_synch_fn))(_fb_, _when_);
+#else
+    // Synch is a no-op
+#endif    
+}
+
+extern __inline__ void
+cyg_fb_read_palette(cyg_fb* _fb_, cyg_ucount32 _first_, cyg_ucount32 _count_, void* _dest_)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE
+    (*(_fb_->fb_read_palette_fn))(_fb_, _first_, _count_, _dest_);
+#else
+    CYG_UNUSED_PARAM(cyg_fb*, _fb_);
+    CYG_UNUSED_PARAM(cyg_ucount32, _first_);
+    CYG_UNUSED_PARAM(cyg_ucount32, _count_);
+    CYG_UNUSED_PARAM(void*, _dest_);
+#endif
+}
+
+extern __inline__ void
+cyg_fb_write_palette(cyg_fb* _fb_, cyg_ucount32 _first_, cyg_ucount32 _count_, const void* _dest_, cyg_ucount16 _when_)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE
+    (*(_fb_->fb_write_palette_fn))(_fb_, _first_, _count_, _dest_, _when_);
+#else
+    CYG_UNUSED_PARAM(cyg_fb*, _fb_);
+    CYG_UNUSED_PARAM(cyg_ucount32, _first_);
+    CYG_UNUSED_PARAM(cyg_ucount32, _count_);
+    CYG_UNUSED_PARAM(const void*, _dest_);
+    CYG_UNUSED_PARAM(cyg_ucount16, _when_);
+#endif
+}
+
+extern __inline__ cyg_fb_colour
+cyg_fb_make_colour(cyg_fb* _fb_, cyg_ucount8 _r_, cyg_ucount8 _g_, cyg_ucount8 _b_)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+    return (*(_fb_->fb_make_colour_fn))(_fb_, _r_, _g_, _b_);
+#else
+    CYG_UNUSED_PARAM(cyg_fb*, _fb_);
+    CYG_UNUSED_PARAM(cyg_ucount8, _r_);
+    CYG_UNUSED_PARAM(cyg_ucount8, _g_);
+    CYG_UNUSED_PARAM(cyg_ucount8, _b_);
+    return 0;
+#endif    
+}
+
+extern __inline__ void
+cyg_fb_break_colour(cyg_fb* _fb_, cyg_fb_colour _colour_, cyg_ucount8* _r_, cyg_ucount8* _g_, cyg_ucount8* _b_)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+    (*(_fb_->fb_break_colour_fn))(_fb_, _colour_, _r_, _g_, _b_);
+#else
+    CYG_UNUSED_PARAM(cyg_fb*, _fb_);
+    CYG_UNUSED_PARAM(cyg_fb_colour, _colour_);
+    CYG_UNUSED_PARAM(cyg_ucount8*, _r_);
+    CYG_UNUSED_PARAM(cyg_ucount8*, _g_);
+    CYG_UNUSED_PARAM(cyg_ucount8*, _b_);
+#endif    
+}
+
+#endif  // defined(CYGPKG_INFRA_DEBUG) || defined(__CYG_FB_IN_FRAMEBUF_C)
+
+// ----------------------------------------------------------------------------
+// The MACRO API
+#define CYG_FB__AUX(_fb_, _field_)          CYG_FB_ ## _fb_ ## _field_
+
+#define CYG_FB_STRUCT(_fb_)                 CYG_FB__AUX(_fb_, _STRUCT)
+#define CYG_FB_DEPTH(_fb_)                  CYG_FB__AUX(_fb_, _DEPTH)
+#define CYG_FB_FORMAT(_fb_)                 CYG_FB__AUX(_fb_, _FORMAT)
+#define CYG_FB_WIDTH(_fb_)                  CYG_FB__AUX(_fb_, _WIDTH)
+#define CYG_FB_HEIGHT(_fb_)                 CYG_FB__AUX(_fb_, _HEIGHT)
+#define CYG_FB_VIEWPORT_WIDTH(_fb_)         CYG_FB__AUX(_fb_, _VIEWPORT_WIDTH)
+#define CYG_FB_VIEWPORT_HEIGHT(_fb_)        CYG_FB__AUX(_fb_, _VIEWPORT_HEIGHT)
+#define CYG_FB_STRIDE(_fb_)                 CYG_FB__AUX(_fb_, _STRIDE)
+#define CYG_FB_BASE(_fb_)                   CYG_FB__AUX(_fb_, _BASE)
+#define CYG_FB_FLAGS0(_fb_)                 CYG_FB__AUX(_fb_, _FLAGS0)
+#define CYG_FB_FLAGS1(_fb_)                 CYG_FB__AUX(_fb_, _FLAGS1)
+#define CYG_FB_FLAGS2(_fb_)                 CYG_FB__AUX(_fb_, _FLAGS2)
+#define CYG_FB_FLAGS3(_fb_)                 CYG_FB__AUX(_fb_, _FLAGS3)
+
+#define CYG_FB_PIXELx_VAR(  _fb_, _id_)                                     CYG_FB__AUX(_fb_, _PIXELx_VAR)(   _fb_, _id_)
+#define CYG_FB_PIXELx_SET(  _fb_, _id_, _x_, _y_)                           CYG_FB__AUX(_fb_, _PIXELx_SET)(   _fb_, _id_, _x_, _y_)
+#define CYG_FB_PIXELx_GET(  _fb_, _id_, _x_, _y_)                           CYG_FB__AUX(_fb_, _PIXELx_GET)(   _fb_, _id_, _x_, _y_)
+#define CYG_FB_PIXELx_ADDX( _fb_, _id_, _incr_)                             CYG_FB__AUX(_fb_, _PIXELx_ADDX)(  _fb_, _id_, _incr_)
+#define CYG_FB_PIXELx_ADDY( _fb_, _id_, _incr_)                             CYG_FB__AUX(_fb_, _PIXELx_ADDY)(  _fb_, _id_, _incr_)
+#define CYG_FB_PIXELx_WRITE(_fb_, _id_, _colour_)                           CYG_FB__AUX(_fb_, _PIXELx_WRITE)( _fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READ( _fb_, _id_)                                     CYG_FB__AUX(_fb_, _PIXELx_READ)(  _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS(_fb_, _id_, _x0_, _y0_, _width_, _height_)   CYG_FB__AUX(_fb_, _PIXELx_FLUSHABS)( _fb_, _id_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL(_fb_, _id_, _x0_, _y0_, _dx_, _dy_)          CYG_FB__AUX(_fb_, _PIXELx_FLUSHREL)( _fb_, _id_, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXEL0_VAR(  _fb_)                                       CYG_FB_PIXELx_VAR(  _fb_, 0)
+#define CYG_FB_PIXEL0_SET(  _fb_, _x_, _y_)                             CYG_FB_PIXELx_SET(  _fb_, 0, _x_, _y_)
+#define CYG_FB_PIXEL0_GET(  _fb_, _x_, _y_)                             CYG_FB_PIXELx_GET(  _fb_, 0, _x_, _y_)
+#define CYG_FB_PIXEL0_ADDX( _fb_, _incr_)                               CYG_FB_PIXELx_ADDX( _fb_, 0, _incr_)
+#define CYG_FB_PIXEL0_ADDY( _fb_, _incr_)                               CYG_FB_PIXELx_ADDY( _fb_, 0, _incr_)
+#define CYG_FB_PIXEL0_WRITE(_fb_, _colour_)                             CYG_FB_PIXELx_WRITE(_fb_, 0, _colour_)
+#define CYG_FB_PIXEL0_READ( _fb_)                                       CYG_FB_PIXELx_READ( _fb_, 0)
+#define CYG_FB_PIXEL0_FLUSHABS( _fb_, _x0_, _y0_, _width_, _height_)    CYG_FB_PIXELx_FLUSHABS( _fb_, 0, _x0_, _y0_, _width_, _height_)
+#define CYG_FB_PIXEL0_FLUSHREL( _fb_, _x0_, _y0_, _dx_, _dy_)           CYG_FB_PIXELx_FLUSHREL( _fb_, 0, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXEL1_VAR(  _fb_)                                       CYG_FB_PIXELx_VAR(  _fb_, 1)
+#define CYG_FB_PIXEL1_SET(  _fb_, _x_, _y_)                             CYG_FB_PIXELx_SET(  _fb_, 1, _x_, _y_)
+#define CYG_FB_PIXEL1_GET(  _fb_, _x_, _y_)                             CYG_FB_PIXELx_GET(  _fb_, 1, _x_, _y_)
+#define CYG_FB_PIXEL1_ADDX( _fb_, _incr_)                               CYG_FB_PIXELx_ADDX( _fb_, 1, _incr_)
+#define CYG_FB_PIXEL1_ADDY( _fb_, _incr_)                               CYG_FB_PIXELx_ADDY( _fb_, 1, _incr_)
+#define CYG_FB_PIXEL1_WRITE(_fb_, _colour_)                             CYG_FB_PIXELx_WRITE(_fb_, 1, _colour_)
+#define CYG_FB_PIXEL1_READ( _fb_)                                       CYG_FB_PIXELx_READ( _fb_, 1)
+#define CYG_FB_PIXEL1_FLUSHABS( _fb_, _x0_, _y0_, _width_, _height_)    CYG_FB_PIXELx_FLUSHABS( _fb_, 1, _x0_, _y0_, _width_, _height_)
+#define CYG_FB_PIXEL1_FLUSHREL( _fb_, _x0_, _y0_, _dx_, _dy_)           CYG_FB_PIXELx_FLUSHREL( _fb_, 1, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXEL2_VAR(  _fb_)                                       CYG_FB_PIXELx_VAR(  _fb_, 2)
+#define CYG_FB_PIXEL2_SET(  _fb_, _x_, _y_)                             CYG_FB_PIXELx_SET(  _fb_, 2, _x_, _y_)
+#define CYG_FB_PIXEL2_GET(  _fb_, _x_, _y_)                             CYG_FB_PIXELx_GET(  _fb_, 2, _x_, _y_)
+#define CYG_FB_PIXEL2_ADDX( _fb_, _incr_)                               CYG_FB_PIXELx_ADDX( _fb_, 2, _incr_)
+#define CYG_FB_PIXEL2_ADDY( _fb_, _incr_)                               CYG_FB_PIXELx_ADDY( _fb_, 2, _incr_)
+#define CYG_FB_PIXEL2_WRITE(_fb_, _colour_)                             CYG_FB_PIXELx_WRITE(_fb_, 2, _colour_)
+#define CYG_FB_PIXEL2_READ( _fb_)                                       CYG_FB_PIXELx_READ( _fb_, 2)
+#define CYG_FB_PIXEL2_FLUSHABS( _fb_, _x0_, _y0_, _width_, _height_)    CYG_FB_PIXELx_FLUSHABS( _fb_, 2, _x0_, _y0_, _width_, _height_)
+#define CYG_FB_PIXEL2_FLUSHREL( _fb_, _x0_, _y0_, _dx_, _dy_)           CYG_FB_PIXELx_FLUSHREL( _fb_, 2, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXEL3_VAR(  _fb_)                                       CYG_FB_PIXELx_VAR(  _fb_, 3)
+#define CYG_FB_PIXEL3_SET(  _fb_, _x_, _y_)                             CYG_FB_PIXELx_SET(  _fb_, 3, _x_, _y_)
+#define CYG_FB_PIXEL3_GET(  _fb_, _x_, _y_)                             CYG_FB_PIXELx_GET(  _fb_, 3, _x_, _y_)
+#define CYG_FB_PIXEL3_ADDX( _fb_, _incr_)                               CYG_FB_PIXELx_ADDX( _fb_, 3, _incr_)
+#define CYG_FB_PIXEL3_ADDY( _fb_, _incr_)                               CYG_FB_PIXELx_ADDY( _fb_, 3, _incr_)
+#define CYG_FB_PIXEL3_WRITE(_fb_, _colour_)                             CYG_FB_PIXELx_WRITE(_fb_, 3, _colour_)
+#define CYG_FB_PIXEL3_READ( _fb_)                                       CYG_FB_PIXELx_READ( _fb_, 3)
+#define CYG_FB_PIXEL3_FLUSHABS( _fb_, _x0_, _y0_, _width_, _height_)    CYG_FB_PIXELx_FLUSHABS( _fb_, 3, _x0_, _y0_, _width_, _height_)
+#define CYG_FB_PIXEL3_FLUSHREL( _fb_, _x0_, _y0_, _dx_, _dy_)           CYG_FB_PIXELx_FLUSHREL( _fb_, 3, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_ON(_fb_)                             ({ cyg_fb_on(& CYG_FB_STRUCT(_fb_)); })
+#define CYG_FB_OFF(_fb_)                            ({ cyg_fb_off(& CYG_FB_STRUCT(_fb_)); })
+#define CYG_FB_IOCTL(_fb_, _key_, _data_, _len_)    ({ cyg_fb_ioctl(& CYG_FB_STRUCT(_fb_), _key_, _data_, _len_); })
+#define CYG_FB_SYNCH(_fb_, _when_)                                                      \
+    CYG_MACRO_START                                                                     \
+    cyg_fb_synch(& CYG_FB_STRUCT(_fb_), _when_);                                        \
+    CYG_MACRO_END
+#define CYG_FB_WRITE_PALETTE(_fb_, _first_, _count_, _data_, _when_)                    \
+    CYG_MACRO_START                                                                     \
+    cyg_fb_write_palette(& CYG_FB_STRUCT(_fb_), _first_, _count_, _data_, _when_);      \
+    CYG_MACRO_END
+#define CYG_FB_READ_PALETTE(_fb_, _first_, _count_, _data_)                             \
+    CYG_MACRO_START                                                                     \
+    cyg_fb_read_palette(& CYG_FB_STRUCT(_fb_), _first_, _count_, _data_);               \
+    CYG_MACRO_END
+
+#define CYG_FB_WRITE_PIXEL(_fb_, _x_, _y_, _colour_)                                        \
+    CYG_FB__AUX(_fb_, _WRITE_PIXEL)(_x_, _y_, _colour_)
+#define CYG_FB_READ_PIXEL(_fb_, _x_, _y_)                                                   \
+    CYG_FB__AUX(_fb_, _READ_PIXEL)(_x_, _y_)
+#define CYG_FB_WRITE_HLINE(_fb_, _x_, _y_, _len_, _colour_)                                 \
+    CYG_FB__AUX(_fb_, _WRITE_HLINE)(_x_, _y_, _len_, _colour_)
+#define CYG_FB_WRITE_VLINE(_fb_, _x_, _y_, _len_, _colour_)                                 \
+    CYG_FB__AUX(_fb_, _WRITE_VLINE)(_x_, _y_, _len_, _colour_)
+#define CYG_FB_FILL_BLOCK(_fb_, _x_, _y_, _width_, _height_, _colour_)                      \
+    CYG_FB__AUX(_fb_, _FILL_BLOCK)(_x_, _y_, _width_, _height_, _colour_)
+#define CYG_FB_WRITE_BLOCK(_fb_, _x_, _y_, _width_, _height_, _data_, _offset_, _stride_)   \
+    CYG_FB__AUX(_fb_, _WRITE_BLOCK)(_x_, _y_, _width_, _height_, _data_, _offset_, _stride_)
+#define CYG_FB_READ_BLOCK(_fb_, _x_, _y_, _width_, _height_, _data_, _offset_, _stride_)    \
+    CYG_FB__AUX(_fb_, _READ_BLOCK)(_x_, _y_, _width_, _height_, _data_, _offset_, _stride_)
+#define CYG_FB_MOVE_BLOCK(_fb_, _x_, _y_, _width_, _height_, _new_x_, _new_y_)              \
+    CYG_FB__AUX(_fb_, _MOVE_BLOCK)(_x_, _y_, _width_, _height_, _new_x_, _new_y_)
+#define CYG_FB_MAKE_COLOUR(_fb_, _r_, _g_, _b_)                                             \
+    CYG_FB__AUX(_fb_, _MAKE_COLOUR)(_r_, _g_, _b_)
+#define CYG_FB_MAKE_COLOR(_fb_, _r_, _g_, _b_)                                              \
+    CYG_FB__AUX(_fb_, _MAKE_COLOUR)(_r_, _g_, _b_)
+#define CYG_FB_BREAK_COLOUR(_fb_, _colour_, _r_, _g_, _b_)                                  \
+    CYG_FB__AUX(_fb_, _BREAK_COLOUR)(_colour_, _r_, _g_, _b_)
+#define CYG_FB_BREAK_COLOR(_fb_, _colour_, _r_, _g_, _b_)                                   \
+    CYG_FB__AUX(_fb_, _BREAK_COLOUR)(_colour_, _r_, _g_, _b_)
+
+// ----------------------------------------------------------------------------
+// Default implementations of some of the per-device functions for linear
+// framebuffers. Control operations like initialization are always
+// device-specific and cannot be implemented by the generic package.
+
+extern void cyg_fb_linear_write_pixel_1LE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_1BE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_2LE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_2BE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_4LE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_4BE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_8(   cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_16(  cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_pixel_32(  cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_fb_colour);
+
+extern cyg_fb_colour   cyg_fb_linear_read_pixel_1LE(  cyg_fb*,
+                                                      cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour   cyg_fb_linear_read_pixel_1BE(  cyg_fb*,
+                                                      cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour   cyg_fb_linear_read_pixel_2LE(  cyg_fb*,
+                                                      cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour   cyg_fb_linear_read_pixel_2BE(  cyg_fb*,
+                                                      cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour   cyg_fb_linear_read_pixel_4LE(  cyg_fb*,
+                                                      cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour   cyg_fb_linear_read_pixel_4BE(  cyg_fb*,
+                                                      cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour   cyg_fb_linear_read_pixel_8(    cyg_fb*,
+                                                      cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour   cyg_fb_linear_read_pixel_16(   cyg_fb*,
+                                                      cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+extern cyg_fb_colour   cyg_fb_linear_read_pixel_32(   cyg_fb*,
+                                                      cyg_ucount16 /* x */, cyg_ucount16 /* y */);
+
+extern void cyg_fb_linear_write_hline_1LE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_1BE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_2LE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_2BE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_4LE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_4BE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_8(   cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_16(  cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_hline_32(  cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+
+extern void cyg_fb_linear_write_vline_1LE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_1BE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_2LE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_2BE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_4LE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_4BE( cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_8(   cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_16(  cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+extern void cyg_fb_linear_write_vline_32(  cyg_fb*,
+                                           cyg_ucount16 /* x */,   cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* len */,
+                                           cyg_fb_colour);
+
+extern void cyg_fb_linear_fill_block_1LE( cyg_fb*,
+                                          cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                          cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                          cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_1BE( cyg_fb*,
+                                          cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                          cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                          cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_2LE( cyg_fb*,
+                                          cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                          cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                          cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_2BE( cyg_fb*,
+                                          cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                          cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                          cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_4LE( cyg_fb*,
+                                          cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                          cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                          cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_4BE( cyg_fb*,
+                                          cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                          cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                          cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_8(   cyg_fb*,
+                                          cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                          cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                          cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_16(  cyg_fb*,
+                                          cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                          cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                          cyg_fb_colour);
+extern void cyg_fb_linear_fill_block_32(  cyg_fb*,
+                                          cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                          cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                          cyg_fb_colour);
+
+extern void cyg_fb_linear_write_block_1LE( cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           const void*  /* source */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_1BE( cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           const void*  /* source */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_2LE( cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           const void*  /* source */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /* stride */);
+                                           
+extern void cyg_fb_linear_write_block_2BE( cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           const void*  /* source */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_4LE( cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           const void*  /* source */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_4BE( cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           const void*  /* source */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_8(   cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           const void*  /* source */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_16(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           const void*  /* source */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /* stride */);
+extern void cyg_fb_linear_write_block_32(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           const void*  /* source */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /* stride */);
+
+extern void cyg_fb_linear_read_block_1LE(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           void*        /* dest */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /*  stride */);
+extern void cyg_fb_linear_read_block_1BE(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           void* /* dest */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /*  stride */);
+extern void cyg_fb_linear_read_block_2LE(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           void* /* dest */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /*  stride */);
+extern void cyg_fb_linear_read_block_2BE(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           void* /* dest */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /*  stride */);
+extern void cyg_fb_linear_read_block_4LE(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           void* /* dest */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /*  stride */);
+extern void cyg_fb_linear_read_block_4BE(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           void* /* dest */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /*  stride */);
+extern void cyg_fb_linear_read_block_8(    cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           void* /* dest */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /*  stride */);
+extern void cyg_fb_linear_read_block_16(   cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           void* /* dest */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /*  stride */);
+extern void cyg_fb_linear_read_block_32(   cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           void* /* dest */,
+                                           cyg_ucount16 /* offset */,   cyg_ucount16 /*  stride */);
+
+extern void cyg_fb_linear_move_block_1LE(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           cyg_ucount16 /* new_x */,    cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_1BE(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           cyg_ucount16 /* new_x */,    cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_2LE(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           cyg_ucount16 /* new_x */,    cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_2BE(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           cyg_ucount16 /* new_x */,    cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_4LE(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           cyg_ucount16 /* new_x */,    cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_4BE(  cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           cyg_ucount16 /* new_x */,    cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_8(    cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           cyg_ucount16 /* new_x */,    cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_16(   cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           cyg_ucount16 /* new_x */,    cyg_ucount16 /* new_y */);
+extern void cyg_fb_linear_move_block_32(   cyg_fb*,
+                                           cyg_ucount16 /* x */,        cyg_ucount16 /* y */,
+                                           cyg_ucount16 /* width */,    cyg_ucount16 /* height */,
+                                           cyg_ucount16 /* new_x */,    cyg_ucount16 /* new_y */);
+
+// ----------------------------------------------------------------------------
+// Dummy implementations of various device functions
+
+extern int              cyg_fb_nop_on(cyg_fb*);
+extern int              cyg_fb_nop_off(cyg_fb*);
+extern int              cyg_fb_nop_ioctl(cyg_fb*, cyg_uint16, void*, size_t*);
+extern void             cyg_fb_nop_synch(cyg_fb*, cyg_ucount16);
+extern void             cyg_fb_nop_write_palette(cyg_fb*, cyg_ucount32, cyg_ucount32, const void*, cyg_ucount16);
+extern void             cyg_fb_nop_read_palette( cyg_fb*, cyg_ucount32, cyg_ucount32, void*);
+extern cyg_fb_colour    cyg_fb_nop_make_colour(cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+extern cyg_fb_colour    cyg_fb_nop_make_color(cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+extern void             cyg_fb_nop_break_colour(cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+extern void             cyg_fb_nop_break_color(cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+
+// ----------------------------------------------------------------------------
+// Standard palettes. The generic framebuffer package provides EGA and VGA
+// palettes.
+extern const cyg_uint8  cyg_fb_palette_ega[16 * 3];
+extern const cyg_uint8  cyg_fb_palette_vga[256 * 3];
+
+#define CYG_FB_DEFAULT_PALETTE_BLACK        0x00
+#define CYG_FB_DEFAULT_PALETTE_BLUE         0x01
+#define CYG_FB_DEFAULT_PALETTE_GREEN        0x02
+#define CYG_FB_DEFAULT_PALETTE_CYAN         0x03
+#define CYG_FB_DEFAULT_PALETTE_RED          0x04
+#define CYG_FB_DEFAULT_PALETTE_MAGENTA      0x05
+#define CYG_FB_DEFAULT_PALETTE_BROWN        0x06
+#define CYG_FB_DEFAULT_PALETTE_LIGHTGREY    0x07
+#define CYG_FB_DEFAULT_PALETTE_LIGHTGRAY    0x07
+#define CYG_FB_DEFAULT_PALETTE_DARKGREY     0x08
+#define CYG_FB_DEFAULT_PALETTE_DARKGRAY     0x08
+#define CYG_FB_DEFAULT_PALETTE_LIGHTBLUE    0x09
+#define CYG_FB_DEFAULT_PALETTE_LIGHTGREEN   0x0A
+#define CYG_FB_DEFAULT_PALETTE_LIGHTCYAN    0x0B
+#define CYG_FB_DEFAULT_PALETTE_LIGHTRED     0x0C
+#define CYG_FB_DEFAULT_PALETTE_LIGHTMAGENTA 0x0D
+#define CYG_FB_DEFAULT_PALETTE_YELLOW       0x0E
+#define CYG_FB_DEFAULT_PALETTE_WHITE        0x0F
+
+// ----------------------------------------------------------------------------
+// Support for some common true colour modes
+#define CYG_FB_MAKE_COLOUR_8BPP_TRUE_332(_r_, _g_, _b_)                                             \
+    ({  cyg_fb_colour _colour_;                                                                     \
+        _colour_ = ((((_r_) & 0x00E0) >> 0) | (((_g_) & 0x00E0) >> 3) | (((_b_) & 0x00C0) >> 6));   \
+        _colour_; })
+
+#define CYG_FB_BREAK_COLOUR_8BPP_TRUE_332(_colour_, _r_, _g_, _b_ )                                 \
+    CYG_MACRO_START                                                                                 \
+    *(_r_) = ((_colour_) << 0) & 0x00E0;                                                            \
+    *(_g_) = ((_colour_) << 3) & 0x00E0;                                                            \
+    *(_g_) = ((_colour_) << 6) & 0x00C0;                                                            \
+    CYG_MACRO_END
+
+#define CYG_FB_MAKE_COLOUR_16BPP_TRUE_565(_r_, _g_, _b_)                                            \
+    ({ ((((_r_) & 0x00F8) << 8) | (((_g_) & 0x00FC) << 3) | (((_b_) & 0x00F8) >> 3)); })
+
+#define CYG_FB_BREAK_COLOUR_16BPP_TRUE_565(_colour_, _r_, _g_, _b_)                                 \
+    CYG_MACRO_START                                                                                 \
+    *(_r_) = ((_colour_) >> 8) & 0x00F8;                                                            \
+    *(_g_) = ((_colour_) >> 3) & 0x00FC;                                                            \
+    *(_b_) = ((_colour_) << 3) & 0x00F8;                                                            \
+    CYG_MACRO_END
+
+#define CYG_FB_MAKE_COLOUR_16BPP_TRUE_555(_r_, _g_, _b_)                                            \
+    ({ ((((_r_) & 0x00F8) << 7) | (((_g_) & 0x00F8) << 2) | (((_b_) & 0x00F8) >> 3)); })
+
+#define CYG_FB_BREAK_COLOUR_16BPP_TRUE_555(_colour_, _r_, _g_, _b_)                             \
+    CYG_MACRO_START                                                                             \
+    *(_r_) = ((_colour_) >> 7) & 0x00F8;                                                        \
+    *(_g_) = ((_colour_) >> 2) & 0x00F8;                                                        \
+    *(_b_) = ((_colour_) << 3) & 0x00F8;                                                        \
+    CYG_MACRO_END
+
+#define CYG_FB_MAKE_COLOUR_32BPP_TRUE_0888(_r_, _g_, _b_)                                       \
+    ({ (((_r_) << 16) | ((_g_) << 8) | (_b_)); })
+
+#define CYG_FB_BREAK_COLOUR_32BPP_TRUE_0888(_colour_, _r_, _g_, _b_)                            \
+    CYG_MACRO_START                                                                             \
+    *(_r_) = ((_colour_) >> 16) & 0x00FF;                                                       \
+    *(_g_) = ((_colour_) >>  8) & 0x00FF;                                                       \
+    *(_b_) = ((_colour_)      ) & 0x00FF;                                                       \
+    CYG_MACRO_END
+
+extern cyg_fb_colour    cyg_fb_dev_make_colour_8bpp_true_332(cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+extern void             cyg_fb_dev_break_colour_8bpp_true_332(cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+extern cyg_fb_colour    cyg_fb_dev_make_colour_16bpp_true_565(cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+extern void             cyg_fb_dev_break_colour_16bpp_true_565(cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+extern cyg_fb_colour    cyg_fb_dev_make_colour_16bpp_true_555(cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+extern void             cyg_fb_dev_break_colour_16bpp_true_555(cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+extern cyg_fb_colour    cyg_fb_dev_make_colour_32bpp_true_0888(cyg_fb*, cyg_ucount8, cyg_ucount8, cyg_ucount8);
+extern void             cyg_fb_dev_break_colour_32bpp_true_0888(cyg_fb*, cyg_fb_colour, cyg_ucount8*, cyg_ucount8*, cyg_ucount8*);
+
+// ----------------------------------------------------------------------------
+// A custom build step combines all the header files from the various
+// framebuffer devices (usually just one) into a single header. This
+// makes it easier for portable higher-level code to work with
+// whatever devices happen to be available.
+#include <cyg/io/framebufs/framebufs.h>
+
+//-----------------------------------------------------------------------------
+#ifdef __cplusplus
+}   /* extern "C" */
+#endif
+
+#endif // ifndef CYGONCE_IO_FRAMEBUF_H
+// End of framebuf.h
Index: include/framebuf.inl
===================================================================
RCS file: include/framebuf.inl
diff -N include/framebuf.inl
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ include/framebuf.inl	7 Oct 2008 10:03:08 -0000
@@ -0,0 +1,958 @@
+#include <cyg/infra/diag.h>
+#ifndef CYGONCE_IO_FRAMEBUF_INL
+#define CYGONCE_IO_FRAMEBUF_INL
+
+//=============================================================================
+//
+//      framebuf.inl
+//
+//      Inline functions for manipulating linear framebuffers
+//
+//=============================================================================
+//###ECOSGPLCOPYRIGHTBEGIN####
+//-------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//=============================================================================
+//####DESCRIPTIONBEGIN####
+//
+// Author(s):   bartv
+// Date:        2005-03-29
+//####DESCRIPTIONEND####
+//=============================================================================
+
+// There are numerous ways of implementing the functions in this file.
+// For example for depths >= 8 many operations can be performed using
+// memset()/memcpy()/memmove(), or
+// __builtin_memset()/__builtin_memcpy()/ memmove(), or by explicit
+// direct accesses to framebuffer memory. The first of these can be
+// discarded because the builtins are never worse than explicit
+// function calls. The choice between the builtins and direct accesses
+// is not so clear. On the one hand the library functions may well
+// involve architecture-specific optimizations. On the other hand
+// function calls are not free. This decision really needs to be taken
+// on a per-architecture basis after careful measurements.
+//
+// A similar question arises regarding the handling of row numbers.
+// One implementation involves multiplying by the width. Another
+// involves keeping a table of pointers to the start of each row,
+// avoiding a multiplication but adding a memory access. Again the
+// trade off is not immediately obvious.
+//
+// For direct accesses the bus width is an issue. Typically the frame
+// buffer will not be cached so the framebuffer memory accesses will
+// account for much of the inner loop. For now 32-bit accesses are
+// preferred. If the target has h/w support for 64-bit accesses that
+// would improve performance, at the cost of extra code to handle
+// alignments. If the video device is accessed via a 16-bit bus then
+// it is assumed that the h/w will fix up 32->16 bit accesses faster
+// than any s/w workaround.
+//
+// For now the code prefers builtins and multiplies.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ----------------------------------------------------------------------------
+// Macro definitions for the pixel manipulation.
+// Little-endian means pixel 0 occupies bit 0 within a byte
+// Big-endian means pixel 0 occupies bit 7
+#define CYG_FB_PIXELx_VARx_1LE(  _fb_, _id_)
+#define CYG_FB_PIXELx_SETx_1LE(  _fb_, _id_, _fbaddr_, _stride_, _x_, _y_)
+#define CYG_FB_PIXELx_GETx_1LE(  _fb_, _id_, _fbaddr_, _stride_, _x_ ,_y_)
+#define CYG_FB_PIXELx_ADDx_1LE(  _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_ADDx_1LE(  _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_WRITEx_1LE(_fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READx_1LE( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS_1LE(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL_1LE(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXELx_VARx_1BE(  _fb_, _id_)
+#define CYG_FB_PIXELx_SETx_1BE(  _fb_, _id_, _fbaddr_, _stride_, _x_, _y_)
+#define CYG_FB_PIXELx_GETx_1BE(  _fb_, _id_, _fbaddr_, _stride_, _x_ ,_y_)
+#define CYG_FB_PIXELx_ADDXx_1BE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_ADDYx_1BE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_WRITEx_1BE(_fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READx_1BE( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS_1BE(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL_1BE(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXELx_VARx_2LE(  _fb_, _id_, _which_)
+#define CYG_FB_PIXELx_SETx_2LE(  _fb_, _id_, _fbaddr_, _stride_, _x_, _y_)
+#define CYG_FB_PIXELx_GETx_2LE(  _fb_, _id_, _fbaddr_, _stride_, _x_ ,_y_)
+#define CYG_FB_PIXELx_ADDx_2LE(  _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_ADDx_2LE(  _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_WRITEx_2LE(_fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READx_2LE( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS_2LE(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL_2LE(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXELx_VARx_2BE(  _fb_, _id_)
+#define CYG_FB_PIXELx_SETx_2BE(  _fb_, _id_, _fbaddr_, _stride_, _x_, _y_)
+#define CYG_FB_PIXELx_GETx_2BE(  _fb_, _id_, _fbaddr_, _stride_, _x_ ,_y_)
+#define CYG_FB_PIXELx_ADDXx_2BE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_ADDYx_2BE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_WRITEx_2BE(_fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READx_2BE( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS_2BE(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL_2BE(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXELx_VARx_4LE(  _fb_, _id_, _which_)
+#define CYG_FB_PIXELx_SETx_4LE(  _fb_, _id_, _fbaddr_, _stride_, _x_, _y_)
+#define CYG_FB_PIXELx_GETx_4LE(  _fb_, _id_, _fbaddr_, _stride_, _x_ ,_y_)
+#define CYG_FB_PIXELx_ADDx_4LE(  _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_ADDx_4LE(  _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_WRITEx_4LE(_fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READx_4LE( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS_4LE(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL_4LE(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)
+
+#define CYG_FB_PIXELx_VARx_4BE(  _fb_, _id_)
+#define CYG_FB_PIXELx_SETx_4BE(  _fb_, _id_, _fbaddr_, _stride_, _x_, _y_)
+#define CYG_FB_PIXELx_GETx_4BE(  _fb_, _id_, _fbaddr_, _stride_, _x_ ,_y_)
+#define CYG_FB_PIXELx_ADDXx_4BE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_ADDYx_4BE( _fb_, _id_, _stride_, _incr_)
+#define CYG_FB_PIXELx_WRITEx_4BE(_fb_, _id_, _colour_)
+#define CYG_FB_PIXELx_READx_4BE( _fb_, _id_)
+#define CYG_FB_PIXELx_FLUSHABS_4BE(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)
+#define CYG_FB_PIXELx_FLUSHREL_4BE(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)
+
+
+// ----------------------------------------------------------------------------
+#define CYG_FB_PIXELx_VAR_8(_fb_, _which_)    cyg_uint8*  _cyg_fb_pixelpos8_ ## _fb_ ## _which_
+#define CYG_FB_PIXELx_SET_8(_fb_, _which_, _fbaddr_, _stride_, _x_, _y_)            \
+    CYG_MACRO_START                                                                 \
+    _cyg_fb_pixelpos8_ ## _fb_ ## _which_  = (cyg_uint8*)_fbaddr_;                  \
+    _cyg_fb_pixelpos8_ ## _fb_ ## _which_ += ((_stride_) * (_y_));                  \
+    _cyg_fb_pixelpos8_ ## _fb_ ## _which_ += (_x_);                                 \
+    CYG_MACRO_END
+
+#define CYG_FB_PIXELx_GET_8(_fb_, _which_, _fbaddr_, _stride_, _x_ ,_y_)            \
+    CYG_MACRO_START                                                                 \
+    cyg_uint32 _offset_;                                                            \
+    _offset_ = (_cyg_fb_pixelpos8_ ## _fb_ ## _which_) - (cyg_uint8*)(_fbaddr_);    \
+    _y_ = _offset_ / (_stride_);                                                    \
+    _x_ = _offset_ % (_stride_);                                                    \
+    CYG_MACRO_END
+    
+#define CYG_FB_PIXELx_ADDX_8(_fb_, _which_, _stride_, _incr_)                       \
+    CYG_MACRO_START                                                                 \
+    _cyg_fb_pixelpos8_ ## _fb_ ## _which_ += (_incr_);                              \
+    CYG_MACRO_END
+                                      
+#define CYG_FB_PIXELx_ADDY_8(_fb_, _which_, _stride_, _incr_)                       \
+    CYG_MACRO_START                                                                 \
+    _cyg_fb_pixelpos8_ ## _fb_ ## _which_ += ((_incr_) * (_stride_));               \
+    CYG_MACRO_END
+                                      
+#define CYG_FB_PIXELx_WRITE_8(_fb_, _which_, _colour_)                              \
+    CYG_MACRO_START                                                                 \
+    * _cyg_fb_pixelpos8_ ## _fb_ ## _which_ = (_colour_);                           \
+    CYG_MACRO_END
+                                      
+#define CYG_FB_PIXELx_READ_8(_fb_, _which_) ({ * _cyg_fb_pixelpos8_ ## _fb_ ## _which_; })
+
+#define CYG_FB_PIXELx_FLUSHABS_8(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)             \
+    CYG_MACRO_START                                                                 \
+    CYG_MACRO_END
+    
+#define CYG_FB_PIXELx_FLUSHREL_8(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)             \
+    CYG_MACRO_START                                                                 \
+    CYG_MACRO_END
+    
+// ----------------------------------------------------------------------------
+#define CYG_FB_PIXELx_VAR_16(_fb_, _which_)    cyg_uint16*  _cyg_fb_pixelpos16_ ## _fb_ ## _which_
+#define CYG_FB_PIXELx_SET_16(_fb_, _which_, _fbaddr_, _stride8_, _x_, _y_)                                              \
+    CYG_MACRO_START                                                                                                     \
+    _cyg_fb_pixelpos16_ ## _fb_ ## _which_  = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + ((_stride8_) * (_y_)))) + (_x_);  \
+    CYG_MACRO_END
+
+#define CYG_FB_PIXELx_GET_16(_fb_, _which_, _fbaddr_, _stride8_, _x_ ,_y_)          \
+    CYG_MACRO_START                                                                 \
+    cyg_ucount16 _stride_ = (_stride8_) >> 1;                                       \
+    cyg_uint32   _offset_;                                                          \
+    _offset_ = (_cyg_fb_pixelpos16_ ## _fb_ ## _which_) - (cyg_uint16*)(_fbaddr_);  \
+    _y_ = _offset_ / (_stride_);                                                    \
+    _x_ = _offset_ % (_stride_);                                                    \
+    CYG_MACRO_END
+    
+#define CYG_FB_PIXELx_ADDX_16(_fb_, _which_, _stride8_, _incr_)                     \
+    CYG_MACRO_START                                                                 \
+    _cyg_fb_pixelpos16_ ## _fb_ ## _which_ += (_incr_);                             \
+    CYG_MACRO_END
+                                      
+#define CYG_FB_PIXELx_ADDY_16(_fb_, _which_, _stride8_, _incr_)                     \
+    CYG_MACRO_START                                                                 \
+    _cyg_fb_pixelpos16_ ## _fb_ ## _which_ += ((_incr_) * ((_stride8_) >> 1));      \
+    CYG_MACRO_END
+                                      
+#define CYG_FB_PIXELx_WRITE_16(_fb_, _which_, _colour_)                             \
+    CYG_MACRO_START                                                                 \
+    * _cyg_fb_pixelpos16_ ## _fb_ ## _which_ = (_colour_);                          \
+    CYG_MACRO_END
+                                      
+#define CYG_FB_PIXELx_READ_16(_fb_, _which_)                                        \
+    ({ * _cyg_fb_pixelpos16_ ## _fb_ ## _which_; })
+
+#define CYG_FB_PIXELx_FLUSHABS_16(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)            \
+    CYG_MACRO_START                                                                 \
+    CYG_MACRO_END
+    
+#define CYG_FB_PIXELx_FLUSHREL_16(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)            \
+    CYG_MACRO_START                                                                 \
+    CYG_MACRO_END
+    
+// ----------------------------------------------------------------------------
+#define CYG_FB_PIXELx_VAR_32(_fb_, _which_)    cyg_uint32*  _cyg_fb_pixelpos32_ ## _fb_ ## _which_
+#define CYG_FB_PIXELx_SET_32(_fb_, _which_, _fbaddr_, _stride8_, _x_, _y_)                                              \
+    CYG_MACRO_START                                                                                                     \
+    _cyg_fb_pixelpos32_ ## _fb_ ## _which_  = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + ((_stride8_) * (_y_)))) + (_x_);  \
+    CYG_MACRO_END
+
+#define CYG_FB_PIXELx_GET_32(_fb_, _which_, _fbaddr_, _stride8_, _x_ ,_y_)          \
+    CYG_MACRO_START                                                                 \
+    cyg_ucount16 _stride_ = (_stride8_) >> 2;                                       \
+    cyg_uint32   _offset_;                                                          \
+    _offset_ = (_cyg_fb_pixelpos32_ ## _fb_ ## _which_) - (cyg_uint32*)(_fbaddr_);  \
+    _y_ = _offset_ / (_stride_);                                                    \
+    _x_ = _offset_ % (_stride_);                                                    \
+    CYG_MACRO_END
+    
+#define CYG_FB_PIXELx_ADDX_32(_fb_, _which_, _stride8_, _incr_)                     \
+    CYG_MACRO_START                                                                 \
+    _cyg_fb_pixelpos32_ ## _fb_ ## _which_ += (_incr_);                             \
+    CYG_MACRO_END
+                                      
+#define CYG_FB_PIXELx_ADDY_32(_fb_, _which_, _stride8_, _incr_)                     \
+    CYG_MACRO_START                                                                 \
+    _cyg_fb_pixelpos32_ ## _fb_ ## _which_ += ((_incr_) * ((_stride8_) >> 2));      \
+    CYG_MACRO_END
+                                      
+#define CYG_FB_PIXELx_WRITE_32(_fb_, _which_, _colour_)                             \
+    CYG_MACRO_START                                                                 \
+    * _cyg_fb_pixelpos32_ ## _fb_ ## _which_ = (_colour_);                          \
+    CYG_MACRO_END
+                                      
+#define CYG_FB_PIXELx_READ_32(_fb_, _which_) ({ * _cyg_fb_pixelpos32_ ## _fb_ ## _which_; })
+
+#define CYG_FB_PIXELx_FLUSHABS_32(_fb_, _which_, _x0_, _y0_, _x1_, _y1_)            \
+    CYG_MACRO_START                                                                 \
+    CYG_MACRO_END
+    
+#define CYG_FB_PIXELx_FLUSHREL_32(_fb_, _which_, _x0_, _y0_, _dx_, _dy_)            \
+    CYG_MACRO_START                                                                 \
+    CYG_MACRO_END
+    
+// ----------------------------------------------------------------------------
+// Some of the functions could be speeded up by using 32-bit accesses
+// instead of byte accesses, but that would introduce another endianness
+// complication.    
+    
+// The always_inline attribute must be a applied to a declaration, not a
+// definition, so combine the two via a single macro.
+#define CYG_FB_LINEAR_INLINE_FN(_type_, _name_, _args_)                     \
+static __inline__ _type_ _name_ _args_ __attribute__((__always_inline__));  \
+static __inline__ _type_ _name_ _args_
+    
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_pixel_1LE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 3);
+    cyg_uint8   _mask_  = 0x0001 << (_x_ & 0x07);
+    if (_colour_) {
+        *_ptr8_ |= _mask_;
+    } else {
+        *_ptr8_ &= ~_mask_;
+    }
+}
+                     
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_pixel_1BE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 3);
+    cyg_uint8   _mask_  = 0x0080 >> (_x_ & 0x07);
+    if (_colour_) {
+        *_ptr8_ |= _mask_;
+    } else {
+        *_ptr8_ &= ~_mask_;
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+                        cyg_fb_linear_read_pixel_1LE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 3);
+    cyg_uint8   _mask_  = 0x0001 << (_x_ & 0x07);
+    return (*_ptr8_ & _mask_) ? 1 : 0;
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+                        cyg_fb_linear_read_pixel_1BE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 3);
+    cyg_uint8   _mask_  = 0x0080 >> (_x_ & 0x07);
+    return (*_ptr8_ & _mask_) ? 1 : 0;
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_vline_1LE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 3);
+    cyg_uint8   _mask_  = 0x0001 << (_x_ & 0x07);
+    if (_colour_) {
+        for ( ; _len_; _len_--) {
+            *_ptr8_ |= _mask_;
+            _ptr8_  += _stride_;
+        }
+    } else {
+        _mask_  = ~_mask_;
+        for ( ; _len_; _len_--) {
+            *_ptr8_ &= _mask_;
+            _ptr8_  += _stride_;
+        }
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_vline_1BE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 3);
+    cyg_uint8   _mask_  = 0x0080 >> (_x_ & 0x07);
+    if (_colour_) {
+        for ( ; _len_; _len_--) {
+            *_ptr8_ |= _mask_;
+            _ptr8_  += _stride_;
+        }
+    } else {
+        _mask_  = ~_mask_;
+        for ( ; _len_; _len_--) {
+            *_ptr8_ &= _mask_;
+            _ptr8_  += _stride_;
+        }
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_pixel_2LE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+    cyg_uint8   _shift_ = (_x_ & 0x03) << 1;
+
+    *_ptr8_ = (*_ptr8_ & ~(0x03 << _shift_)) | (_colour_ << _shift_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_pixel_2BE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+    cyg_uint8   _shift_ = 6 - ((_x_ & 0x03) << 1);
+
+    *_ptr8_ = (*_ptr8_ & ~(0x03 << _shift_)) | (_colour_ << _shift_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+                        cyg_fb_linear_read_pixel_2LE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+    cyg_uint8   _shift_ = (_x_ & 0x03) << 1;
+
+    return (*_ptr8_ >> _shift_) & 0x03;
+}
+                     
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+                        cyg_fb_linear_read_pixel_2BE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+    cyg_uint8   _shift_ = 6 - ((_x_ & 0x03) << 1);
+
+    return (*_ptr8_ >> _shift_) & 0x03;
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_vline_2LE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+    cyg_uint8   _shift_ = (_x_ & 0x03) << 1;
+    cyg_uint8   _mask_  = ~(0x03 << _shift_);
+    _colour_    <<= _shift_;
+
+    for ( ; _len_; _len_--) {
+        *_ptr8_  = (*_ptr8_ & _mask_) | _colour_;
+        _ptr8_  += _stride_;
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_vline_2BE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+    cyg_uint8   _shift_ = 6 - ((_x_ & 0x03) << 1);
+    cyg_uint8   _mask_  = ~(0x03 << _shift_);
+    _colour_    <<= _shift_;
+
+    for ( ; _len_; _len_--) {
+        *_ptr8_  = (*_ptr8_ & _mask_) | _colour_;
+        _ptr8_  += _stride_;
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_pixel_4LE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 1);
+    if (_x_ & 0x01) {
+        *_ptr8_ = (*_ptr8_ & 0x000F) | (_colour_ << 4);
+    } else {
+        *_ptr8_ = (*_ptr8_ & 0x00F0) | _colour_;
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_pixel_4BE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 1);
+    if (_x_ & 0x01) {
+        *_ptr8_ = (*_ptr8_ & 0x00F0) | _colour_;
+    } else {
+        *_ptr8_ = (*_ptr8_ & 0x000F) | (_colour_ << 4);
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+                        cyg_fb_linear_read_pixel_4LE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 1);
+    if (_x_ & 0x01) {
+        return (*_ptr8_ >> 4) & 0x000F;
+    } else {
+        return *_ptr8_ & 0x000F;
+    }
+}
+                     
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+                        cyg_fb_linear_read_pixel_4BE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 1);
+    if (_x_ & 0x01) {
+        return *_ptr8_ & 0x000F;
+    } else {
+        return (*_ptr8_ >> 4) & 0x000F;
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_vline_4LE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+    if (_x_ & 0x01) {
+        _colour_ <<= 4;
+        for ( ; _len_; _len_--) {
+            *_ptr8_  = (*_ptr8_ & 0x000F) | _colour_;
+            _ptr8_  += _stride_;
+        }
+    } else {
+        for ( ; _len_; _len_--) {
+            *_ptr8_ = (*_ptr8_ & 0x00F0) | _colour_;
+        }
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_vline_4BE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + (_x_ >> 2);
+    if (_x_ & 0x01) {
+        for ( ; _len_; _len_--) {
+            *_ptr8_ = (*_ptr8_ & 0x00F0) | _colour_;
+        }
+    } else {
+        _colour_ <<= 4;
+        for ( ; _len_; _len_--) {
+            *_ptr8_  = (*_ptr8_ & 0x000F) | _colour_;
+            _ptr8_  += _stride_;
+        }
+    }
+}
+
+// ----------------------------------------------------------------------------
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_pixel_8_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+    *_ptr8_ = _colour_;
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+                        cyg_fb_linear_read_pixel_8_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+    cyg_uint8*  _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+    return *_ptr8_;
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_hline_8_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+    __builtin_memset(_ptr8_, _colour_, _len_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_vline_8_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+    for ( ; _len_; _len_--) {
+        *_ptr8_  = _colour_;
+        _ptr8_  += _stride_;
+    }    
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_fill_block_8_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_, cyg_fb_colour _colour_))
+{
+    cyg_uint8*  _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+    for ( ; _height_; _height_--) {
+        __builtin_memset(_ptr8_, _colour_, _width_);
+        _ptr8_ += _stride_;
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_block_8_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         const void* _source_,
+                         cyg_ucount16 _offset_, cyg_ucount16 _source_stride_))
+{
+    cyg_uint8*  _ptr8_ = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+    cyg_uint8*  _src8_ = ((cyg_uint8*) _source_) + _offset_;
+    
+    for ( ; _height_; _height_--) {
+        __builtin_memcpy(_ptr8_, _src8_, _width_);
+        _ptr8_  += _stride_;
+        _src8_  += _source_stride_;
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_read_block_8_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         void* _dest_,
+                         cyg_ucount16 _offset_, cyg_ucount16 _dest_stride_))
+{
+    cyg_uint8*  _ptr8_  = ((cyg_uint8*)_fbaddr_) + (_stride_ * _y_) + _x_;
+    cyg_uint8*  _dst8_  = ((cyg_uint8*)_dest_) + _offset_;
+    
+    for ( ; _height_; _height_--) {
+        __builtin_memcpy(_dst8_, _ptr8_, _width_);
+        _ptr8_  += _stride_;
+        _dst8_  += _dest_stride_;
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_pixel_16_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+    cyg_uint16* _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    *_ptr16_ = _colour_;
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+                        cyg_fb_linear_read_pixel_16_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+    cyg_uint16* _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    return *_ptr16_;
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_hline_16_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+    cyg_uint16* _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    cyg_uint32* _ptr32_;
+    cyg_bool    _right_;
+
+    if (_x_ & 0x01) {
+        *_ptr16_++ = _colour_;
+        _len_      -= 1;
+    }
+    _ptr32_   = (cyg_uint32*) _ptr16_;
+    _colour_ |= (_colour_ << 16);
+    _right_   = (_len_ & 0x01);
+    for ( _len_ >>= 1; _len_; _len_--) {
+        *_ptr32_++ = _colour_;
+    }
+    if (_right_) {
+        *((cyg_uint16*)_ptr32_) = _colour_;
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_vline_16_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+    cyg_uint16* _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    for ( ; _len_; _len_--) {
+        *_ptr16_     = _colour_;
+        _ptr16_      = (cyg_uint16*)(((cyg_uint8*)_ptr16_) + _stride8_);
+    }    
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_fill_block_16_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_, cyg_fb_colour _colour_))
+{
+    cyg_bool        _left_, _right_;
+    cyg_uint16*     _ptr16_;
+    cyg_uint32*     _ptr32_;
+    cyg_ucount16    _stride32_;
+
+    _ptr16_       = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    _left_ = (_x_ & 0x01);
+    if (_left_) {
+        _width_  -= 1;
+    }
+    _right_       = (_width_ & 0x01);
+
+    if (_left_) {
+        _ptr32_ = (cyg_uint32*) &(_ptr16_[1]);
+        for (_y_ = _height_; _y_; _y_--) {
+            *_ptr16_    = _colour_;
+            _ptr16_     = (cyg_uint16*)(((cyg_uint8*)_ptr16_) + _stride8_);
+        }
+    } else {
+        _ptr32_ = (cyg_uint32*) _ptr16_;
+    }
+    _width_     >>= 1;
+    _stride32_    = _stride8_ - (_width_ << 2);
+    _colour_     |= (_colour_ << 16);
+    _ptr16_       = (cyg_uint16*) &(_ptr32_[_width_]);
+    
+    for ( _y_ = _height_; _y_; _y_--) {
+        for ( _x_ = _width_; _x_; _x_--) {
+            *_ptr32_++ = _colour_;
+        }
+        _ptr32_ = (cyg_uint32*)(((cyg_uint8*)_ptr32_) + _stride32_);
+    }
+    if (_right_) {
+        for (_y_ = _height_; _y_; _y_--) {
+            *_ptr16_    = _colour_;
+            _ptr16_     = (cyg_uint16*)(((cyg_uint8*)_ptr16_) + _stride8_);
+        }
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_block_16_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         const void* _source_,
+                         cyg_ucount16 _offset_, cyg_ucount16 _source_stride8_))
+{
+    cyg_uint16* _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    cyg_uint16* _src16_ = ((cyg_uint16*) _source_) + _offset_;
+
+    _width_ <<= 1;
+    for ( ; _height_; _height_--) {
+        __builtin_memcpy(_ptr16_, _src16_, _width_);
+        _ptr16_ = (cyg_uint16*)(((cyg_uint8*)_ptr16_) + _stride8_);
+        _src16_ = (cyg_uint16*)(((cyg_uint8*)_src16_) + _source_stride8_);
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_read_block_16_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         void* _dest_,
+                         cyg_ucount16 _offset_, cyg_ucount16 _dest_stride8_))
+{
+    cyg_uint16* _ptr16_ = ((cyg_uint16*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    cyg_uint16* _dst16_ = ((cyg_uint16*)_dest_) + _offset_;
+
+    _width_ <<= 1;
+    for ( ; _height_; _height_--) {
+        __builtin_memcpy(_dst16_, _ptr16_, _width_);
+        _ptr16_ = (cyg_uint16*)(((cyg_uint8*)_ptr16_) + _stride8_);
+        _dst16_ = (cyg_uint16*)(((cyg_uint8*)_dst16_) + _dest_stride8_);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_pixel_32_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_fb_colour _colour_))
+{
+    cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    *_ptr32_ = _colour_;
+}
+
+CYG_FB_LINEAR_INLINE_FN(cyg_fb_colour,
+                        cyg_fb_linear_read_pixel_32_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_))
+{
+    cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    return *_ptr32_;
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_hline_32_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+    cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    while (_len_--) {
+        *_ptr32_++ = _colour_;
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_vline_32_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_, cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _len_, cyg_fb_colour _colour_))
+{
+    cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    while (_len_--) {
+        *_ptr32_    = _colour_;
+        _ptr32_     = (cyg_uint32*)(((cyg_uint8*)_ptr32_) + _stride8_);
+    }    
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_fill_block_32_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_, cyg_fb_colour _colour_))
+{
+    cyg_uint32*     _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    cyg_ucount16    _len_;
+    
+    _stride8_   -= (_width_ << 2);
+    for ( ; _height_; _height_--) {
+        for (_len_ = _width_; _len_; _len_--) {
+            *_ptr32_++ = _colour_;
+        }
+        _ptr32_ = (cyg_uint32*)(((cyg_uint8*)_ptr32_) + _stride8_);
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_write_block_32_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         const void* _source_,
+                         cyg_ucount16 _offset_, cyg_ucount16 _source_stride8_))
+{
+    cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    cyg_uint32* _src32_ = ((cyg_uint32*) _source_) + _offset_;
+
+    _width_ <<= 2;
+    for ( ; _height_; _height_--) {
+        __builtin_memcpy(_ptr32_, _src32_, _width_);
+        _ptr32_ = (cyg_uint32*)(((cyg_uint8*)_ptr32_) + _stride8_);
+        _src32_ = (cyg_uint32*)(((cyg_uint8*)_src32_) + _source_stride8_);
+    }
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_read_block_32_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride8_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         void* _dest_,
+                         cyg_ucount16 _offset_, cyg_ucount16 _dest_stride8_))
+{
+    cyg_uint32* _ptr32_ = ((cyg_uint32*)(((cyg_uint8*)_fbaddr_) + (_stride8_ * _y_))) + _x_;
+    cyg_uint32* _dst32_  = ((cyg_uint32*)_dest_) + _offset_;
+
+    _width_ <<= 2;
+    for ( ; _height_; _height_--) {
+        __builtin_memcpy(_dst32_, _ptr32_, _width_);
+        _ptr32_ = (cyg_uint32*)(((cyg_uint8*)_ptr32_) + _stride8_);
+        _dst32_ = (cyg_uint32*)(((cyg_uint8*)_dst32_) + _dest_stride8_);
+    }
+}
+
+// ----------------------------------------------------------------------------
+// The actual move block functions are not inlined, but it is convenient to
+// have dummy _inl functions anyway.
+
+extern void cyg_fb_linear_move_block_1LE_impl(void*, cyg_ucount16 /* stride */,
+                                              cyg_ucount16, cyg_ucount16,
+                                              cyg_ucount16, cyg_ucount16,
+                                              cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_1BE_impl(void*, cyg_ucount16 /* stride */,
+                                              cyg_ucount16, cyg_ucount16,
+                                              cyg_ucount16, cyg_ucount16,
+                                              cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_2LE_impl(void*, cyg_ucount16 /* stride */,
+                                              cyg_ucount16, cyg_ucount16,
+                                              cyg_ucount16, cyg_ucount16,
+                                              cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_2BE_impl(void*, cyg_ucount16 /* stride */,
+                                              cyg_ucount16, cyg_ucount16,
+                                              cyg_ucount16, cyg_ucount16,
+                                              cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_4LE_impl(void*, cyg_ucount16 /* stride */,
+                                              cyg_ucount16, cyg_ucount16,
+                                              cyg_ucount16, cyg_ucount16,
+                                              cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_4BE_impl(void*, cyg_ucount16 /* stride */,
+                                              cyg_ucount16, cyg_ucount16,
+                                              cyg_ucount16, cyg_ucount16,
+                                              cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_8_impl(void*, cyg_ucount16 /* stride */,
+                                            cyg_ucount16, cyg_ucount16,
+                                            cyg_ucount16, cyg_ucount16,
+                                            cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_16_impl(void*, cyg_ucount16 /* stride */,
+                                             cyg_ucount16, cyg_ucount16,
+                                             cyg_ucount16, cyg_ucount16,
+                                             cyg_ucount16, cyg_ucount16);
+extern void cyg_fb_linear_move_block_32_impl(void*, cyg_ucount16 /* stride */,
+                                             cyg_ucount16, cyg_ucount16,
+                                             cyg_ucount16, cyg_ucount16,
+                                             cyg_ucount16, cyg_ucount16);
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_move_block_1LE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+    cyg_fb_linear_move_block_1LE_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_move_block_1BE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+    cyg_fb_linear_move_block_1BE_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_move_block_2LE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+    cyg_fb_linear_move_block_2LE_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_move_block_2BE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+    cyg_fb_linear_move_block_2BE_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_move_block_4LE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+    cyg_fb_linear_move_block_4LE_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_move_block_4BE_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+    cyg_fb_linear_move_block_4BE_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_move_block_8_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+    cyg_fb_linear_move_block_8_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_move_block_16_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+    cyg_fb_linear_move_block_16_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+CYG_FB_LINEAR_INLINE_FN(void,
+                        cyg_fb_linear_move_block_32_inl,
+                        (void* _fbaddr_, cyg_ucount16 _stride_,
+                         cyg_ucount16 _x_, cyg_ucount16 _y_, cyg_ucount16 _width_, cyg_ucount16 _height_,
+                         cyg_ucount16 _new_x_, cyg_ucount16 _new_y_))
+{
+    cyg_fb_linear_move_block_32_impl(_fbaddr_, _stride_, _x_, _y_, _width_, _height_, _new_x_, _new_y_);
+}
+
+#ifdef __cplusplus
+}   /* extern "C" */
+#endif
+
+#endif // ifndef CYGONCE_IO_FRAMEBUF_H
+// End of framebuf.h
Index: src/framebuf.c
===================================================================
RCS file: src/framebuf.c
diff -N src/framebuf.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/framebuf.c	7 Oct 2008 10:03:09 -0000
@@ -0,0 +1,492 @@
+//==========================================================================
+//
+//      framebuf.c
+//
+//      Generic API for accessing framebuffers
+//
+//==========================================================================
+//###ECOSGPLCOPYRIGHTBEGIN####
+//-------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//###DESCRIPTIONBEGIN####
+//
+// Author(s):     bartv
+// Date:          2005-03-29
+//
+//###DESCRIPTIONEND####
+//========================================================================
+
+#define __CYG_FB_IN_FRAMEBUF_C  1
+#include <cyg/io/framebuf.h>
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/cyg_ass.h>
+#include <errno.h>
+
+// Implementations of the framebuffer functions. Production code
+// normally uses extern inline versions of these, defined in
+// framebuf.h. However real functions are supplied here in case
+// higher-level code chooses to take the address of a function for
+// some reason. Also when building for debugging (CYGPKG_INFRA_DEBUG)
+// the inline functions are suppressed and the real functions here
+// contain lots of useful assertions.
+
+int
+cyg_fb_on(cyg_fb* fb)
+{
+    int result;
+    
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_on_fn);
+    CYG_CHECK_FUNC_PTRC(fb->fb_off_fn);
+    CYG_CHECK_FUNC_PTRC(fb->fb_write_pixel_fn);
+    CYG_CHECK_FUNC_PTRC(fb->fb_read_pixel_fn);
+    CYG_CHECK_FUNC_PTRC(fb->fb_write_hline_fn);
+    CYG_CHECK_FUNC_PTRC(fb->fb_write_vline_fn);
+    CYG_CHECK_FUNC_PTRC(fb->fb_fill_block_fn);
+    CYG_CHECK_FUNC_PTRC(fb->fb_write_block_fn);
+    CYG_CHECK_FUNC_PTRC(fb->fb_read_block_fn);
+    CYG_CHECK_FUNC_PTRC(fb->fb_move_block_fn);
+
+    result = (*(fb->fb_on_fn))(fb);
+    return result;
+}
+
+int
+cyg_fb_off(cyg_fb* fb)
+{
+    int result;
+    
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_off_fn);
+    
+    result = (*(fb->fb_off_fn))(fb);
+    return result;
+}
+
+void
+cyg_fb_write_pixel(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_write_pixel_fn);
+
+    CYG_PRECONDITIONC(x < fb->fb_width);
+    CYG_PRECONDITIONC(y < fb->fb_height);
+    CYG_PRECONDITIONC((colour <=     1)  || (fb->fb_depth >  1));
+    CYG_PRECONDITIONC((colour <=     3)  || (fb->fb_depth >  2));
+    CYG_PRECONDITIONC((colour <=    15)  || (fb->fb_depth >  4));
+    CYG_PRECONDITIONC((colour <=   255)  || (fb->fb_depth >  8));
+    CYG_PRECONDITIONC((colour <= 65535)  || (fb->fb_depth >  16));
+    
+    (*(fb->fb_write_pixel_fn))(fb, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_read_pixel(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y)
+{
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_read_pixel_fn);
+    
+    CYG_PRECONDITIONC(x < fb->fb_width);
+    CYG_PRECONDITIONC(y < fb->fb_height);
+    
+    return (*(fb->fb_read_pixel_fn))(fb, x, y);
+}
+
+void
+cyg_fb_write_hline(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_write_hline_fn);
+
+    CYG_PRECONDITIONC(x < fb->fb_width);
+    CYG_PRECONDITIONC(y < fb->fb_height);
+    CYG_PRECONDITIONC((x + len) <= fb->fb_width);
+    CYG_PRECONDITIONC((colour <=     1)  || (fb->fb_depth >  1));
+    CYG_PRECONDITIONC((colour <=     3)  || (fb->fb_depth >  2));
+    CYG_PRECONDITIONC((colour <=    15)  || (fb->fb_depth >  4));
+    CYG_PRECONDITIONC((colour <=   255)  || (fb->fb_depth >  8));
+    CYG_PRECONDITIONC((colour <= 65535)  || (fb->fb_depth >  16));
+    
+    (*(fb->fb_write_hline_fn))(fb, x, y, len, colour);
+}
+
+void
+cyg_fb_write_vline(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_write_vline_fn);
+
+    CYG_PRECONDITIONC(x < fb->fb_width);
+    CYG_PRECONDITIONC(y < fb->fb_height);
+    CYG_PRECONDITIONC((y + len) <= fb->fb_height);
+    CYG_PRECONDITIONC((colour <=     1)  || (fb->fb_depth >  1));
+    CYG_PRECONDITIONC((colour <=     3)  || (fb->fb_depth >  2));
+    CYG_PRECONDITIONC((colour <=    15)  || (fb->fb_depth >  4));
+    CYG_PRECONDITIONC((colour <=   255)  || (fb->fb_depth >  8));
+    CYG_PRECONDITIONC((colour <= 65535)  || (fb->fb_depth >  16));
+
+    (*(fb->fb_write_vline_fn))(fb, x, y, len, colour);
+}
+
+void
+cyg_fb_fill_block(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_fill_block_fn);
+
+    CYG_PRECONDITIONC(x < fb->fb_width);
+    CYG_PRECONDITIONC(y < fb->fb_height);
+    CYG_PRECONDITIONC((x + width) <= fb->fb_width);
+    CYG_PRECONDITIONC((y + height) <= fb->fb_height);
+    CYG_PRECONDITIONC((colour <=     1)  || (fb->fb_depth >  1));
+    CYG_PRECONDITIONC((colour <=     3)  || (fb->fb_depth >  2));
+    CYG_PRECONDITIONC((colour <=    15)  || (fb->fb_depth >  4));
+    CYG_PRECONDITIONC((colour <=   255)  || (fb->fb_depth >  8));
+    CYG_PRECONDITIONC((colour <= 65535)  || (fb->fb_depth >  16));
+
+    (*(fb->fb_fill_block_fn))(fb, x, y, width, height, colour);
+}
+
+void
+cyg_fb_write_block(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                   const void* source, cyg_ucount16 offset, cyg_ucount16 stride)
+{
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_write_block_fn);
+    
+    CYG_CHECK_DATA_PTRC(source);
+    CYG_PRECONDITIONC(x < fb->fb_width);
+    CYG_PRECONDITIONC(y < fb->fb_height);
+    CYG_PRECONDITIONC((x + width) <= fb->fb_width);
+    CYG_PRECONDITIONC((y + height) <= fb->fb_height);
+
+    (*(fb->fb_write_block_fn))(fb, x, y, width, height, source, offset, stride);
+}
+
+void
+cyg_fb_read_block(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                  void* dest, cyg_ucount16 offset, cyg_ucount16 stride)
+{
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_read_block_fn);
+
+    CYG_CHECK_DATA_PTRC(dest);
+    CYG_PRECONDITIONC(x < fb->fb_width);
+    CYG_PRECONDITIONC(y < fb->fb_height);
+    CYG_PRECONDITIONC((x + width) <= fb->fb_width);
+    CYG_PRECONDITIONC((y + height) <= fb->fb_height);
+    
+    (*(fb->fb_read_block_fn))(fb, x, y, width, height, dest, offset, stride);
+}
+
+void
+cyg_fb_move_block(cyg_fb* fb, cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_move_block_fn);
+
+    CYG_PRECONDITIONC(x != new_x);
+    CYG_PRECONDITIONC(y != new_y);
+    CYG_PRECONDITIONC(x < fb->fb_width);
+    CYG_PRECONDITIONC(y < fb->fb_height);
+    CYG_PRECONDITIONC((x + width) <= fb->fb_width);
+    CYG_PRECONDITIONC((y + height) <= fb->fb_height);
+    CYG_PRECONDITIONC(new_x < fb->fb_width);
+    CYG_PRECONDITIONC(new_y < fb->fb_height);
+    CYG_PRECONDITIONC((new_x + width) <= fb->fb_width);
+    CYG_PRECONDITIONC((new_y + height) <= fb->fb_height);
+
+    (*(fb->fb_move_block_fn))(fb, x, y, width, height, new_x, new_y);
+}
+
+int
+cyg_fb_ioctl(cyg_fb* fb, cyg_uint16 key, void* data, size_t* len)
+{
+    int result;
+                 
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_ioctl_fn);
+
+    result = (*(fb->fb_ioctl_fn))(fb, key, data, len);
+    return result;
+}
+
+void
+cyg_fb_synch(cyg_fb* fb, cyg_ucount16 when)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_DOUBLE_BUFFER    
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_move_block_fn);
+    (*(fb->fb_synch_fn))(fb, when);
+#else
+    // Synch is a no-op
+#endif    
+}
+
+void
+cyg_fb_read_palette(cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 count, void* dest)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_PALETTE
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_read_palette_fn);
+    CYG_CHECK_DATA_PTRC(dest);
+
+    CYG_PRECONDITIONC( (first < 16)             || (fb->fb_depth > 4));
+    CYG_PRECONDITIONC(((first + count) < 16)    || (fb->fb_depth > 4));
+    CYG_PRECONDITIONC( (first < 256)            || (fb->fb_depth > 8));
+    CYG_PRECONDITIONC(((first + count) <= 256)  || (fb->fb_depth > 8));
+    
+    (*(fb->fb_read_palette_fn))(fb, first, count, dest);
+#else
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_UNUSED_PARAM(cyg_ucount32, first);
+    CYG_UNUSED_PARAM(cyg_ucount32, count);
+    CYG_UNUSED_PARAM(void*, dest);
+#endif
+}
+
+void
+cyg_fb_write_palette(cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 count, const void* source, cyg_ucount16 when)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_WRITEABLE_PALETTE
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_write_palette_fn);
+    CYG_CHECK_DATA_PTRC(source);
+    
+    CYG_PRECONDITIONC( (first < 16)             || (fb->fb_depth > 4));
+    CYG_PRECONDITIONC(((first + count) < 16)    || (fb->fb_depth > 4));
+    CYG_PRECONDITIONC( (first < 256)            || (fb->fb_depth > 8));
+    CYG_PRECONDITIONC(((first + count) <= 256)  || (fb->fb_depth > 8));
+
+    (*(fb->fb_write_palette_fn))(fb, first, count, source, when);
+#else
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_UNUSED_PARAM(cyg_ucount32, first);
+    CYG_UNUSED_PARAM(cyg_ucount32, count);
+    CYG_UNUSED_PARAM(const void*, source);
+    CYG_UNUSED_PARAM(cyg_ucount16, when);
+#endif
+}
+
+cyg_fb_colour
+cyg_fb_make_colour(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_make_colour_fn);
+    CYG_PRECONDITIONC((r <= 0x00FF) && (g <= 0x00FF) && (b <= 0x00FF));
+
+    return (*(fb->fb_make_colour_fn))(fb, r, g, b);
+#else
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_UNUSED_PARAM(cyg_ucount8, r);
+    CYG_UNUSED_PARAM(cyg_ucount8, g);
+    CYG_UNUSED_PARAM(cyg_ucount8, b);
+    return 0;
+#endif
+}
+
+void
+cyg_fb_break_colour(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+{
+#ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_TRUE_COLOUR
+    CYG_CHECK_DATA_PTRC(fb);
+    CYG_PRECONDITIONC(CYG_FB_MAGIC == fb->fb_magic);
+    CYG_CHECK_FUNC_PTRC(fb->fb_break_colour_fn);
+    CYG_CHECK_DATA_PTRC(r);
+    CYG_CHECK_DATA_PTRC(g);
+    CYG_CHECK_DATA_PTRC(b);
+
+    (*(fb->fb_break_colour_fn))(fb, colour, r, g, b);
+#else
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_UNUSED_PARAM(cyg_fb_colour, colour);
+    CYG_UNUSED_PARAM(cyg_ucount8*, r);
+    CYG_UNUSED_PARAM(cyg_ucount8*, g);
+    CYG_UNUSED_PARAM(cyg_ucount8*, b);
+#endif
+}
+
+// ----------------------------------------------------------------------------
+// Dummy functions for use by device drivers when instantiating a cyg_fb
+// structure
+
+int
+cyg_fb_nop_on(cyg_fb* fb)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    return 0;
+}
+
+int
+cyg_fb_nop_off(cyg_fb* fb)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    return 0;
+}
+
+int
+cyg_fb_nop_ioctl(cyg_fb* fb, cyg_uint16 key, void* data, size_t* len)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_UNUSED_PARAM(cyg_uint16, key);
+    CYG_UNUSED_PARAM(void*, data);
+    CYG_UNUSED_PARAM(size_t*, len);
+    return ENOSYS;
+}
+
+void
+cyg_fb_nop_synch(cyg_fb* fb, cyg_ucount16 when)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_UNUSED_PARAM(cyg_ucount16, when);
+}
+
+void
+cyg_fb_nop_write_palette(cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 count, const void* source, cyg_ucount16 when)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_UNUSED_PARAM(cyg_ucount32, first);
+    CYG_UNUSED_PARAM(cyg_ucount32, count);
+    CYG_UNUSED_PARAM(const void*, source);
+    CYG_UNUSED_PARAM(cyg_ucount16, when);
+}
+
+void
+cyg_fb_nop_read_palette(cyg_fb* fb, cyg_ucount32 first, cyg_ucount32 count, void* dest)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_UNUSED_PARAM(cyg_ucount32, first);
+    CYG_UNUSED_PARAM(cyg_ucount32, count);
+    CYG_UNUSED_PARAM(void*, dest);
+}
+
+cyg_fb_colour
+cyg_fb_nop_make_colour(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_UNUSED_PARAM(cyg_ucount8, r);
+    CYG_UNUSED_PARAM(cyg_ucount8, g);
+    CYG_UNUSED_PARAM(cyg_ucount8, b);
+    return 0;
+}
+
+cyg_fb_colour
+cyg_fb_nop_make_color(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+    __attribute__((alias("cyg_fb_nop_make_colour")));
+
+void
+cyg_fb_nop_break_colour(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_UNUSED_PARAM(cyg_fb_colour, colour);
+    CYG_UNUSED_PARAM(cyg_ucount8*, r);
+    CYG_UNUSED_PARAM(cyg_ucount8*, g);
+    CYG_UNUSED_PARAM(cyg_ucount8*, b);
+}
+
+void
+cyg_fb_nop_break_color(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+    __attribute__((alias("cyg_fb_nop_break_colour")));
+    
+// ----------------------------------------------------------------------------
+// Utility functions for common true colour modes
+
+cyg_fb_colour
+cyg_fb_dev_make_colour_8bpp_true_332(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    return CYG_FB_MAKE_COLOUR_8BPP_TRUE_332(r, g, b);
+}
+
+void
+cyg_fb_dev_break_colour_8bpp_true_332(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_FB_BREAK_COLOUR_8BPP_TRUE_332(colour, r, g, b);
+}
+
+cyg_fb_colour
+cyg_fb_dev_make_colour_16bpp_true_565(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    return CYG_FB_MAKE_COLOUR_16BPP_TRUE_565(r, g, b);
+}
+
+void
+cyg_fb_dev_break_colour_16bpp_true_565(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_FB_BREAK_COLOUR_16BPP_TRUE_565(colour, r, g, b);
+}
+
+cyg_fb_colour
+cyg_fb_dev_make_colour_16bpp_true_555(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    return CYG_FB_MAKE_COLOUR_16BPP_TRUE_555(r, g, b);
+}
+
+void
+cyg_fb_dev_break_colour_16bpp_true_555(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_FB_BREAK_COLOUR_16BPP_TRUE_555(colour, r, g, b);
+}
+
+cyg_fb_colour
+cyg_fb_dev_make_colour_32bpp_true_0888(cyg_fb* fb, cyg_ucount8 r, cyg_ucount8 g, cyg_ucount8 b)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    return CYG_FB_MAKE_COLOUR_32BPP_TRUE_0888(r, g, b);
+}
+
+void
+cyg_fb_dev_break_colour_32bpp_true_0888(cyg_fb* fb, cyg_fb_colour colour, cyg_ucount8* r, cyg_ucount8* g, cyg_ucount8* b)
+{
+    CYG_UNUSED_PARAM(cyg_fb*, fb);
+    CYG_FB_BREAK_COLOUR_32BPP_TRUE_0888(colour, r, g, b);
+}
+
Index: src/gen_framebufs.tcl
===================================================================
RCS file: src/gen_framebufs.tcl
diff -N src/gen_framebufs.tcl
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/gen_framebufs.tcl	7 Oct 2008 10:03:09 -0000
@@ -0,0 +1,130 @@
+#!/bin/bash
+# restart using a Tcl shell \
+    exec sh -c 'for tclshell in tclsh tclsh83 cygtclsh80 ; do \
+    ( echo | $tclshell ) 2> /dev/null && exec $tclshell "`( cygpath -w \"$0\" ) 2> /dev/null || echo $0`" "$@" ; \
+    done ; \
+    echo "gen_framebufs.tcl: cannot find Tcl shell" ; exit 1' "$0" "$@"
+
+#===============================================================================
+#
+#    gen_framebufs.tcl
+#
+#    Amalgamate the various framebuffers available on a given platform
+#
+#===============================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+# -------------------------------------------
+# This file is part of eCos, the Embedded Configurable Operating System.
+# Copyright (C) 2008 Free Software Foundation, Inc.
+#
+# eCos is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 or (at your option) any later version.
+#
+# eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with eCos; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+#
+# As a special exception, if other files instantiate templates or use macros
+# or inline functions from this file, or you compile this file and link it
+# with other works to produce a work based on this file, this file does not
+# by itself cause the resulting work to be covered by the GNU General Public
+# License. However the source code for this file must still be made available
+# in accordance with section (3) of the GNU General Public License.
+#
+# This exception does not invalidate any other reasons why a work based on
+# this file might be covered by the GNU General Public License.
+# -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+#===============================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s):	bartv
+# Date:		2005-03-29
+#
+# This script is invoked via a custom make rule to generate a file
+# <cyg/io/framebufs/framebufs.h>
+#
+#####DESCRIPTIONEND####
+#===============================================================================
+
+proc do_it { dir } {
+
+    # dir should be set to <prefix>/install/include/cyg/io/framebufs
+    if { ! [file exists $dir] } {
+        file mkdir $dir
+    }
+    if { ! [file isdirectory $dir] } {
+        puts stderr "gen_framebufs.tcl: strange build tree, $dir should be a directory"
+        exit 1
+    }
+    
+    set	framebufs_file 	[file join $dir "framebufs.h"]
+    set	current_data	""
+    if { [file exists $framebufs_file] } {
+        set fd [open $framebufs_file "r"]
+        set current_data [read $fd]
+        close $fd
+    }
+
+    set headers	[lsort [glob -nocomplain  [file join $dir "*.h*"]]]
+
+    set new_data \
+        "\#ifndef CYGONCE_IO_FRAMEBUFS_FRAMEBUFS_H
+# define CYGONCE_IO_FRAMEBUFS_FRAMEBUFS_H
+
+/* This is a generated file - do not edit! 			*/
+/* <cyg/io/framebufs/framebufs.h> should not be #include'd 	*/
+/* directly, instead use <cyg/io/framebuf.h>			*/
+"
+
+    foreach header $headers {
+        set header [file tail $header]
+        if { [string equal "framebufs.h" $header] } {
+            continue
+        }
+        append new_data "#include <cyg/io/framebufs/[set header]>\n"
+    }
+
+    # Next, work out the default test device. We need to read pkgconf/io_framebuf.h,
+    # look for CYGDAT_IO_FRAMEBUF_DEVICES, and extract the first entry.
+    set pkgconf_file [file join $dir "../../../pkgconf/io_framebuf.h"]
+    if { ! [file exists $pkgconf_file] || ! [file readable $pkgconf_file] } {
+        puts stderr "gen_framebufs.tcl: strange build tree, no access to $pkgconf_file"
+        exit 1
+    }
+    set fd [open $pkgconf_file "r"]
+    while { ! [eof $fd] } {
+        set line [gets $fd]
+        if { [regexp {^#define\s*CYGDAT_IO_FRAMEBUF_DEVICES\s*(\S*)\s+.*$} $line junk fb] } {
+            append new_data "#define CYGDAT_IO_FRAMEBUF_DEFAULT_TEST_DEVICE $fb\n"
+            break
+        }
+    }
+
+    # Close the #ifndef CYGONCE_
+    append new_data "#endif\n"
+
+    if { ! [string equal $current_data $new_data] } {
+        set fd [open $framebufs_file "w"]
+        puts -nonewline $fd $new_data
+        close $fd
+    }
+}
+
+if { 0 == $::argc } {
+    puts stderr "gen_framebufs.tcl: missing argument for install directory"
+    exit 1
+}
+
+if { [catch { do_it [lindex $::argv 0] } msg] } {
+    puts stderr "gen_framebufs.tcl: internal error"
+    puts stderr "    $msg"
+    exit 1
+}
+exit 0
Index: src/linear.c
===================================================================
RCS file: src/linear.c
diff -N src/linear.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/linear.c	7 Oct 2008 10:03:09 -0000
@@ -0,0 +1,807 @@
+//==========================================================================
+//
+//      linear.c
+//
+//      Generic implementations of some of the driver functions for linear
+//      framebuffers.
+//
+//==========================================================================
+//###ECOSGPLCOPYRIGHTBEGIN####
+//-------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//###DESCRIPTIONBEGIN####
+//
+// Author(s):     bartv
+// Date:          2005-03-29
+//
+//###DESCRIPTIONEND####
+//========================================================================
+
+#include <cyg/infra/cyg_type.h>
+#include <cyg/io/framebuf.h>
+
+// The real implementations for most of the functions are actually
+// inlines held in framebuf.inl. That allows the implementation to be
+// shared between the functions and the macros.
+#include <cyg/io/framebuf.inl>
+
+// ----------------------------------------------------------------------------
+void
+cyg_fb_linear_write_pixel_1LE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_pixel_1LE_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_1LE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y)
+{
+    return cyg_fb_linear_read_pixel_1LE_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_1LE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_vline_1LE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_vline_1LE_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_1LE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_block_1LE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                              const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+}
+
+void
+cyg_fb_linear_read_block_1LE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+}
+
+void
+cyg_fb_linear_move_block_1LE_impl(void* fbaddr, cyg_ucount16 stride,
+                                  cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                                  cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+}
+
+void
+cyg_fb_linear_move_block_1LE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    cyg_fb_linear_move_block_1LE_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+void
+cyg_fb_linear_write_pixel_1BE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_pixel_1BE_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_1BE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y)
+{
+    return cyg_fb_linear_read_pixel_1BE_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_1BE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_vline_1BE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_vline_1BE_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_1BE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_block_1BE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                              const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+}
+
+void
+cyg_fb_linear_read_block_1BE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+}
+
+void
+cyg_fb_linear_move_block_1BE_impl(void* fbaddr, cyg_ucount16 stride,
+                                  cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                                  cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+}
+
+void
+cyg_fb_linear_move_block_1BE(cyg_fb* fb,
+                          cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                          cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    cyg_fb_linear_move_block_1LE_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+
+void
+cyg_fb_linear_write_pixel_2LE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_pixel_2LE_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_2LE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y)
+{
+    return cyg_fb_linear_read_pixel_2LE_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_2LE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_vline_2LE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_vline_2LE_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_2LE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_block_2LE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                              const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+}
+
+void
+cyg_fb_linear_read_block_2LE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+}
+
+void
+cyg_fb_linear_move_block_2LE_impl(void* fbaddr, cyg_ucount16 stride,
+                                  cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                                  cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+}
+
+void
+cyg_fb_linear_move_block_2LE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    cyg_fb_linear_move_block_2LE_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+
+void
+cyg_fb_linear_write_pixel_2BE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_pixel_2BE_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_2BE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y)
+{
+    return cyg_fb_linear_read_pixel_2BE_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_2BE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_vline_2BE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_vline_2BE_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_2BE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_block_2BE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                              const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+}
+
+void
+cyg_fb_linear_read_block_2BE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+}
+
+void
+cyg_fb_linear_move_block_2BE_impl(void* fbaddr, cyg_ucount16 stride,
+                                  cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                                  cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+}
+
+void
+cyg_fb_linear_move_block_2BE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    cyg_fb_linear_move_block_2BE_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+    
+// ----------------------------------------------------------------------------
+void
+cyg_fb_linear_write_pixel_4LE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_pixel_4LE_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_4LE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y)
+{
+    return cyg_fb_linear_read_pixel_4LE_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_4LE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_vline_4LE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_vline_4LE_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_4LE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_block_4LE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                              const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+}
+
+void
+cyg_fb_linear_read_block_4LE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+}
+
+void
+cyg_fb_linear_move_block_4LE_impl(void* fbaddr, cyg_ucount16 stride,
+                                  cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                                  cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+}
+
+void
+cyg_fb_linear_move_block_4LE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    cyg_fb_linear_move_block_4LE_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+void
+cyg_fb_linear_write_pixel_4BE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_pixel_4BE_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_4BE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y)
+{
+    return cyg_fb_linear_read_pixel_4BE_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_4BE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_vline_4BE_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_write_vline_4BE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_fill_block_4BE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+}
+
+void
+cyg_fb_linear_write_block_4BE(cyg_fb* fb,
+                              cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                              const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+}
+
+void
+cyg_fb_linear_read_block_4BE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+}
+
+void
+cyg_fb_linear_move_block_4BE_impl(void* fbaddr, cyg_ucount16 stride,
+                                  cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                                  cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+}
+
+void
+cyg_fb_linear_move_block_4BE(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    cyg_fb_linear_move_block_4BE_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+
+void
+cyg_fb_linear_write_pixel_8(cyg_fb* fb,
+                            cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_pixel_8_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_8(cyg_fb* fb,
+                           cyg_ucount16 x, cyg_ucount16 y)
+{
+    return cyg_fb_linear_read_pixel_8_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_8(cyg_fb* fb,
+                            cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_hline_8_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_write_vline_8(cyg_fb* fb,
+                            cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_vline_8_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_8(cyg_fb* fb,
+                           cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+    cyg_fb_linear_fill_block_8_inl(fb->fb_base, fb->fb_stride, x, y, width, height, colour);
+}
+
+void
+cyg_fb_linear_write_block_8(cyg_fb* fb,
+                            cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                            const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+    cyg_fb_linear_write_block_8_inl(fb->fb_base, fb->fb_stride, x, y, width, height, source, offset, source_stride);
+}
+
+void
+cyg_fb_linear_read_block_8(cyg_fb* fb,
+                           cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                           void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+    cyg_fb_linear_read_block_8_inl(fb->fb_base, fb->fb_stride, x, y, width, height, dest, offset, dest_stride);
+}
+
+void
+cyg_fb_linear_move_block_8_impl(void* fbaddr, cyg_ucount16 stride,
+                                cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                                cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    cyg_uint8*  source;
+    cyg_uint8*  dest;
+    int         i;
+    
+    source  = ((cyg_uint8*)fbaddr) + (    y * stride) +     x;
+    dest    = ((cyg_uint8*)fbaddr) + (new_y * stride) + new_x;
+    
+    if ((new_y < y)             ||  // Possible overlapping blocks but no conflict
+        (new_y > (y + height))  ||  // No overlap
+        ((new_x + width) < x)   ||  // No overlap
+        (new_x > (x + width))) {    // No overlap
+        
+        for ( ; height; height--) {
+            __builtin_memcpy(dest, source, width);
+            source  += stride;
+            dest    += stride;
+        }
+        return;
+    }
+
+    // There is an overlap. Can we do a safe bottom-to-top lot of memcpy()'s ?
+    if (new_y > y) {
+        source += (height * stride);
+        dest   += (height * stride);
+        
+        for ( ; height; height--) {
+            __builtin_memcpy(dest, source, width);
+            source  -= stride;
+            dest    -= stride;
+        }
+        return;
+    }
+
+    // We must have (y == new_y) and an overlap, i.e. a short
+    // horizontal move. We could use memmove() but the default
+    // implementation is no better than what we can do here.
+    if (new_x < x) {
+        stride -= width;
+        for ( ; height; height--) {
+            for ( i = width; i ; i--) {
+                *dest++ = *source++;
+            }
+            source  += stride;
+            dest    += stride;
+        }
+    } else if (new_x > x) {
+        source  += width;
+        dest    += width;
+        stride  += width;
+        for ( ; height; height--) {
+            for ( i = width; i; i--) {
+                *--dest = *--source;
+            }
+            source  += stride;
+            dest    += stride;
+        }
+    }
+}
+
+void
+cyg_fb_linear_move_block_8(cyg_fb* fb,
+                           cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                           cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    cyg_fb_linear_move_block_8_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+void
+cyg_fb_linear_write_pixel_16(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_pixel_16_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_16(cyg_fb* fb,
+                            cyg_ucount16 x, cyg_ucount16 y)
+{
+    return cyg_fb_linear_read_pixel_16_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_16(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_hline_16_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_write_vline_16(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_vline_16_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_16(cyg_fb* fb,
+                            cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+    cyg_fb_linear_fill_block_16_inl(fb->fb_base, fb->fb_stride, x, y, width, height, colour);
+}
+
+void
+cyg_fb_linear_write_block_16(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+    cyg_fb_linear_write_block_16_inl(fb->fb_base, fb->fb_stride, x, y, width, height, source, offset, source_stride);
+}
+
+void
+cyg_fb_linear_read_block_16(cyg_fb* fb,
+                            cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                            void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+    cyg_fb_linear_read_block_16_inl(fb->fb_base, fb->fb_stride, x, y, width, height, dest, offset, dest_stride);
+}
+
+void
+cyg_fb_linear_move_block_16_impl(void* fbaddr, cyg_ucount16 stride8,
+                                  cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                                  cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    cyg_uint16* source;
+    cyg_uint16* dest;
+    int         i;
+    
+    source  = ((cyg_uint16*)(((cyg_uint8*)fbaddr) + (    y * stride8))) + x;
+    dest    = ((cyg_uint16*)(((cyg_uint8*)fbaddr) + (new_y * stride8))) + new_x;
+    
+    if ((new_y < y)             ||  // Possible overlapping blocks but no conflict
+        (new_y > (y + height))  ||  // No overlap
+        ((new_x + width) < x)   ||  // No overlap
+        (new_x > (x + width))) {    // No overlap
+        
+        width <<= 1;
+        for ( ; height; height--) {
+            __builtin_memcpy(dest, source, width);
+            source  = (cyg_uint16*)(((cyg_uint8*)source) + stride8);
+            dest    = (cyg_uint16*)(((cyg_uint8*)source) + stride8);
+        }
+        return;
+    }
+
+    // There is an overlap. Can we do a safe bottom-to-top lot of memcpy()'s ?
+    if (new_y > y) {
+        source = (cyg_uint16*)(((cyg_uint8*)source) + (height * stride8));
+        dest   = (cyg_uint16*)(((cyg_uint8*)dest)   + (height * stride8));
+        width <<= 1;
+        for ( ; height; height--) {
+            __builtin_memcpy(dest, source, width);
+            source   = (cyg_uint16*)(((cyg_uint8*)source) - stride8);
+            dest     = (cyg_uint16*)(((cyg_uint8*)dest) - stride8);
+        }
+        return;
+    }
+
+    // We must have (y == new_y) and an overlap, i.e. a short
+    // horizontal move. We could use memmove() but the default
+    // implementation is no better than what we can do here.
+    if (new_x < x) {
+        stride8 -= (width << 1);
+        for ( ; height; height--) {
+            for ( i = width; i ; i--) {
+                *dest++ = *source++;
+            }
+            source  = (cyg_uint16*)(((cyg_uint8*)source) + stride8);
+            dest    = (cyg_uint16*)(((cyg_uint8*)dest) + stride8);
+        }
+    } else if (new_x > x) {
+        source  += width;
+        dest    += width;
+        stride8 += (width << 1);
+        for ( ; height; height--) {
+            for ( i = width; i ; i--) {
+                *--dest = *--source;
+            }
+            source  = (cyg_uint16*)(((cyg_uint8*)source) + stride8);
+            dest    = (cyg_uint16*)(((cyg_uint8*)dest) + stride8);
+        }
+    }
+}
+
+void
+cyg_fb_linear_move_block_16(cyg_fb* fb,
+                            cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                            cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    cyg_fb_linear_move_block_16_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
+
+// ----------------------------------------------------------------------------
+void
+cyg_fb_linear_write_pixel_32(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_pixel_32_inl(fb->fb_base, fb->fb_stride, x, y, colour);
+}
+
+cyg_fb_colour
+cyg_fb_linear_read_pixel_32(cyg_fb* fb,
+                            cyg_ucount16 x, cyg_ucount16 y)
+{
+    return cyg_fb_linear_read_pixel_32_inl(fb->fb_base, fb->fb_stride, x, y);
+}
+
+void
+cyg_fb_linear_write_hline_32(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_hline_32_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_write_vline_32(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
+{
+    cyg_fb_linear_write_vline_32_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
+}
+
+void
+cyg_fb_linear_fill_block_32(cyg_fb* fb,
+                            cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height, cyg_fb_colour colour)
+{
+    cyg_fb_linear_fill_block_32_inl(fb->fb_base, fb->fb_stride, x, y, width, height, colour);
+}
+
+void
+cyg_fb_linear_write_block_32(cyg_fb* fb,
+                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                             const void* source, cyg_ucount16 offset, cyg_ucount16 source_stride)
+{
+    cyg_fb_linear_write_block_32_inl(fb->fb_base, fb->fb_stride, x, y, width, height, source, offset, source_stride);
+}
+
+void
+cyg_fb_linear_read_block_32(cyg_fb* fb,
+                            cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                            void* dest, cyg_ucount16 offset, cyg_ucount16 dest_stride)
+{
+    cyg_fb_linear_read_block_32_inl(fb->fb_base, fb->fb_stride, x, y, width, height, dest, offset, dest_stride);
+}
+
+void
+cyg_fb_linear_move_block_32_impl(void* fbaddr, cyg_ucount16 stride8,
+                                  cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                                  cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    cyg_uint32* source;
+    cyg_uint32* dest;
+    int         i;
+    
+    source  = ((cyg_uint32*)(((cyg_uint8*)fbaddr) + (    y * stride8))) + x;
+    dest    = ((cyg_uint32*)(((cyg_uint8*)fbaddr) + (new_y * stride8))) + new_x;
+    
+    if ((new_y < y)             ||  // Possible overlapping blocks but no conflict
+        (new_y > (y + height))  ||  // No overlap
+        ((new_x + width) < x)   ||  // No overlap
+        (new_x > (x + width))) {    // No overlap
+        
+        width <<= 2;
+        for ( ; height; height--) {
+            __builtin_memcpy(dest, source, width);
+            source  = (cyg_uint32*)(((cyg_uint8*)source) + stride8);
+            dest    = (cyg_uint32*)(((cyg_uint8*)source) + stride8);
+        }
+        return;
+    }
+
+    // There is an overlap. Can we do a safe bottom-to-top lot of memcpy()'s ?
+    if (new_y > y) {
+        source  = (cyg_uint32*)(((cyg_uint8*)source) + (height * stride8));
+        dest    = (cyg_uint32*)(((cyg_uint8*)dest)   + (height * stride8));
+        width <<= 2;
+        for ( ; height; height--) {
+            __builtin_memcpy(dest, source, width);
+            source   = (cyg_uint32*)(((cyg_uint8*)source) - stride8);
+            dest     = (cyg_uint32*)(((cyg_uint8*)dest) - stride8);
+        }
+        return;
+    }
+
+    // We must have (y == new_y) and an overlap, i.e. a short
+    // horizontal move. We could use memmove() but the default
+    // implementation is no better than what we can do here.
+    if (new_x < x) {
+        stride8 -= (width << 2);
+        for ( ; height; height--) {
+            for ( i = width; i ; i--) {
+                *dest++ = *source++;
+            }
+            source  = (cyg_uint32*)(((cyg_uint8*)source) + stride8);
+            dest    = (cyg_uint32*)(((cyg_uint8*)dest) + stride8);
+        }
+    } else if (new_x > x) {
+        source  += width;
+        dest    += width;
+        stride8 += (width << 2);
+        for ( ; height; height--) {
+            for ( i = width; i ; i--) {
+                *--dest = *--source;
+            }
+            source  = (cyg_uint32*)(((cyg_uint8*)source) + stride8);
+            dest    = (cyg_uint32*)(((cyg_uint8*)dest) + stride8);
+        }
+    }
+}
+
+void
+cyg_fb_linear_move_block_32(cyg_fb* fb,
+                            cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 width, cyg_ucount16 height,
+                            cyg_ucount16 new_x, cyg_ucount16 new_y)
+{
+    cyg_fb_linear_move_block_32_inl(fb->fb_base, fb->fb_stride, x, y, width, height, new_x, new_y);
+}
Index: src/palette.c
===================================================================
RCS file: src/palette.c
diff -N src/palette.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/palette.c	7 Oct 2008 10:03:09 -0000
@@ -0,0 +1,327 @@
+//==========================================================================
+//
+//      palette.c
+//
+//      Provide default palettes
+//
+//==========================================================================
+//###ECOSGPLCOPYRIGHTBEGIN####
+//-------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//###DESCRIPTIONBEGIN####
+//
+// Author(s):     bartv
+// Date:          2005-03-29
+//
+//###DESCRIPTIONEND####
+//========================================================================
+
+#include <cyg/io/framebuf.h>
+
+// These figures were taken from a real VGA card. The VGA palette
+// registers only use six bits so the values were shifted by two,
+// then 0xFC was converted to 0xFF to get maximum brightness.
+
+const cyg_uint8 cyg_fb_palette_ega[16 * 3] = {
+    0x00, 0x00, 0x00,       // 0    black
+    0x00, 0x00, 0xa8,       // 1    blue
+    0x00, 0xa8, 0x00,       // 2    green
+    0x00, 0xa8, 0xa8,       // 3    cyan
+    0xa8, 0x00, 0x00,       // 4    red
+    0xa8, 0x00, 0xa8,       // 5    magenta
+    0xa8, 0x54, 0x00,       // 6    brown
+    0xa8, 0xa8, 0xa8,       // 7    light grey
+    0x54, 0x54, 0x54,       // 8    dark grey
+    0x54, 0x54, 0xff,       // 9    light blue
+    0x54, 0xff, 0x54,       // 10   light green
+    0x54, 0xff, 0xff,       // 11   light cyan
+    0xff, 0x54, 0x54,       // 12   light red
+    0xff, 0x54, 0xff,       // 13   light magenta
+    0xff, 0xff, 0x54,       // 14   yellow
+    0xff, 0xff, 0xff        // 15   white
+};
+
+const cyg_uint8 cyg_fb_palette_vga[256 * 3] = {
+    0x00, 0x00, 0x00,       // 0    black
+    0x00, 0x00, 0xa8,       // 1    blue
+    0x00, 0xa8, 0x00,       // 2    green
+    0x00, 0xa8, 0xa8,       // 3    cyan
+    0xa8, 0x00, 0x00,       // 4    red
+    0xa8, 0x00, 0xa8,       // 5    magenta
+    0xa8, 0x54, 0x00,       // 6    brown
+    0xa8, 0xa8, 0xa8,       // 7    light grey
+    0x54, 0x54, 0x54,       // 8    dark grey
+    0x54, 0x54, 0xff,       // 9    light blue
+    0x54, 0xff, 0x54,       // 10   light green
+    0x54, 0xff, 0xff,       // 11   light cyan
+    0xff, 0x54, 0x54,       // 12   light red
+    0xff, 0x54, 0xff,       // 13   light magenta
+    0xff, 0xff, 0x54,       // 14   yellow
+    0xff, 0xff, 0xff,       // 15   white
+    0x00, 0x00, 0x00,       // 16
+    0x14, 0x14, 0x14,       // 17
+    0x20, 0x20, 0x20,       // 18
+    0x2c, 0x2c, 0x2c,       // 19
+    0x38, 0x38, 0x38,       // 20
+    0x44, 0x44, 0x44,       // 21
+    0x50, 0x50, 0x50,       // 22
+    0x60, 0x60, 0x60,       // 23
+    0x70, 0x70, 0x70,       // 24
+    0x80, 0x80, 0x80,       // 25
+    0x90, 0x90, 0x90,       // 26
+    0xa0, 0xa0, 0xa0,       // 27
+    0xb4, 0xb4, 0xb4,       // 28
+    0xc8, 0xc8, 0xc8,       // 29
+    0xe0, 0xe0, 0xe0,       // 30
+    0xff, 0xff, 0xff,       // 31
+    0x00, 0x00, 0xff,       // 32
+    0x40, 0x00, 0xff,       // 33
+    0x7c, 0x00, 0xff,       // 34
+    0xbc, 0x00, 0xff,       // 35
+    0xff, 0x00, 0xff,       // 36
+    0xff, 0x00, 0xbc,       // 37
+    0xff, 0x00, 0x7c,       // 38
+    0xff, 0x00, 0x40,       // 39
+    0xff, 0x00, 0x00,       // 40
+    0xff, 0x40, 0x00,       // 41
+    0xff, 0x7c, 0x00,       // 42
+    0xff, 0xbc, 0x00,       // 43
+    0xff, 0xff, 0x00,       // 44
+    0xbc, 0xff, 0x00,       // 45
+    0x7c, 0xff, 0x00,       // 46
+    0x40, 0xff, 0x00,       // 47
+    0x00, 0xff, 0x00,       // 48
+    0x00, 0xff, 0x40,       // 49
+    0x00, 0xff, 0x7c,       // 50
+    0x00, 0xff, 0xbc,       // 51
+    0x00, 0xff, 0xff,       // 52
+    0x00, 0xbc, 0xff,       // 53
+    0x00, 0x7c, 0xff,       // 54
+    0x00, 0x40, 0xff,       // 55
+    0x7c, 0x7c, 0xff,       // 56
+    0x9c, 0x7c, 0xff,       // 57
+    0xbc, 0x7c, 0xff,       // 58
+    0xdc, 0x7c, 0xff,       // 59
+    0xff, 0x7c, 0xff,       // 60
+    0xff, 0x7c, 0xdc,       // 61
+    0xff, 0x7c, 0xbc,       // 62
+    0xff, 0x7c, 0x9c,       // 63
+    0xff, 0x7c, 0x7c,       // 64
+    0xff, 0x9c, 0x7c,       // 65
+    0xff, 0xbc, 0x7c,       // 66
+    0xff, 0xdc, 0x7c,       // 67
+    0xff, 0xff, 0x7c,       // 68
+    0xdc, 0xff, 0x7c,       // 69
+    0xbc, 0xff, 0x7c,       // 70
+    0x9c, 0xff, 0x7c,       // 71
+    0x7c, 0xff, 0x7c,       // 72
+    0x7c, 0xff, 0x9c,       // 73
+    0x7c, 0xff, 0xbc,       // 74
+    0x7c, 0xff, 0xdc,       // 75
+    0x7c, 0xff, 0xff,       // 76
+    0x7c, 0xdc, 0xff,       // 77
+    0x7c, 0xbc, 0xff,       // 78
+    0x7c, 0x9c, 0xff,       // 79
+    0xb4, 0xb4, 0xff,       // 80
+    0xc4, 0xb4, 0xff,       // 81
+    0xd8, 0xb4, 0xff,       // 82
+    0xe8, 0xb4, 0xff,       // 83
+    0xff, 0xb4, 0xff,       // 84
+    0xff, 0xb4, 0xe8,       // 85
+    0xff, 0xb4, 0xd8,       // 86
+    0xff, 0xb4, 0xc4,       // 87
+    0xff, 0xb4, 0xb4,       // 88
+    0xff, 0xc4, 0xb4,       // 89
+    0xff, 0xd8, 0xb4,       // 90
+    0xff, 0xe8, 0xb4,       // 91
+    0xff, 0xff, 0xb4,       // 92
+    0xe8, 0xff, 0xb4,       // 93
+    0xd8, 0xff, 0xb4,       // 94
+    0xc4, 0xff, 0xb4,       // 95
+    0xb4, 0xff, 0xb4,       // 96
+    0xb4, 0xff, 0xc4,       // 97
+    0xb4, 0xff, 0xd8,       // 98
+    0xb4, 0xff, 0xe8,       // 99
+    0xb4, 0xff, 0xff,       // 100
+    0xb4, 0xe8, 0xff,       // 101
+    0xb4, 0xd8, 0xff,       // 102
+    0xb4, 0xc4, 0xff,       // 103
+    0x00, 0x00, 0x70,       // 104
+    0x1c, 0x00, 0x70,       // 105
+    0x38, 0x00, 0x70,       // 106
+    0x54, 0x00, 0x70,       // 107
+    0x70, 0x00, 0x70,       // 108
+    0x70, 0x00, 0x54,       // 109
+    0x70, 0x00, 0x38,       // 110
+    0x70, 0x00, 0x1c,       // 111
+    0x70, 0x00, 0x00,       // 112
+    0x70, 0x1c, 0x00,       // 113
+    0x70, 0x38, 0x00,       // 114
+    0x70, 0x54, 0x00,       // 115
+    0x70, 0x70, 0x00,       // 116
+    0x54, 0x70, 0x00,       // 117
+    0x38, 0x70, 0x00,       // 118
+    0x1c, 0x70, 0x00,       // 119
+    0x00, 0x70, 0x00,       // 120
+    0x00, 0x70, 0x1c,       // 121
+    0x00, 0x70, 0x38,       // 122
+    0x00, 0x70, 0x54,       // 123
+    0x00, 0x70, 0x70,       // 124
+    0x00, 0x54, 0x70,       // 125
+    0x00, 0x38, 0x70,       // 126
+    0x00, 0x1c, 0x70,       // 127
+    0x38, 0x38, 0x70,       // 128
+    0x44, 0x38, 0x70,       // 129
+    0x54, 0x38, 0x70,       // 130
+    0x60, 0x38, 0x70,       // 131
+    0x70, 0x38, 0x70,       // 132
+    0x70, 0x38, 0x60,       // 133
+    0x70, 0x38, 0x54,       // 134
+    0x70, 0x38, 0x44,       // 135
+    0x70, 0x38, 0x38,       // 136
+    0x70, 0x44, 0x38,       // 137
+    0x70, 0x54, 0x38,       // 138
+    0x70, 0x60, 0x38,       // 139
+    0x70, 0x70, 0x38,       // 140
+    0x60, 0x70, 0x38,       // 141
+    0x54, 0x70, 0x38,       // 142
+    0x44, 0x70, 0x38,       // 143
+    0x38, 0x70, 0x38,       // 144
+    0x38, 0x70, 0x44,       // 145
+    0x38, 0x70, 0x54,       // 146
+    0x38, 0x70, 0x60,       // 147
+    0x38, 0x70, 0x70,       // 148
+    0x38, 0x60, 0x70,       // 149
+    0x38, 0x54, 0x70,       // 150
+    0x38, 0x44, 0x70,       // 151
+    0x50, 0x50, 0x70,       // 152
+    0x58, 0x50, 0x70,       // 153
+    0x60, 0x50, 0x70,       // 154
+    0x68, 0x50, 0x70,       // 155
+    0x70, 0x50, 0x70,       // 156
+    0x70, 0x50, 0x68,       // 157
+    0x70, 0x50, 0x60,       // 158
+    0x70, 0x50, 0x58,       // 159
+    0x70, 0x50, 0x50,       // 160
+    0x70, 0x58, 0x50,       // 161
+    0x70, 0x60, 0x50,       // 162
+    0x70, 0x68, 0x50,       // 163
+    0x70, 0x70, 0x50,       // 164
+    0x68, 0x70, 0x50,       // 165
+    0x60, 0x70, 0x50,       // 166
+    0x58, 0x70, 0x50,       // 167
+    0x50, 0x70, 0x50,       // 168
+    0x50, 0x70, 0x58,       // 169
+    0x50, 0x70, 0x60,       // 170
+    0x50, 0x70, 0x68,       // 171
+    0x50, 0x70, 0x70,       // 172
+    0x50, 0x68, 0x70,       // 173
+    0x50, 0x60, 0x70,       // 174
+    0x50, 0x58, 0x70,       // 175
+    0x00, 0x00, 0x40,       // 176
+    0x10, 0x00, 0x40,       // 177
+    0x20, 0x00, 0x40,       // 178
+    0x30, 0x00, 0x40,       // 179
+    0x40, 0x00, 0x40,       // 180
+    0x40, 0x00, 0x30,       // 181
+    0x40, 0x00, 0x20,       // 182
+    0x40, 0x00, 0x10,       // 183
+    0x40, 0x00, 0x00,       // 184
+    0x40, 0x10, 0x00,       // 185
+    0x40, 0x20, 0x00,       // 186
+    0x40, 0x30, 0x00,       // 187
+    0x40, 0x40, 0x00,       // 188
+    0x30, 0x40, 0x00,       // 189
+    0x20, 0x40, 0x00,       // 190
+    0x10, 0x40, 0x00,       // 191
+    0x00, 0x40, 0x00,       // 192
+    0x00, 0x40, 0x10,       // 193
+    0x00, 0x40, 0x20,       // 194
+    0x00, 0x40, 0x30,       // 195
+    0x00, 0x40, 0x40,       // 196
+    0x00, 0x30, 0x40,       // 197
+    0x00, 0x20, 0x40,       // 198
+    0x00, 0x10, 0x40,       // 199
+    0x20, 0x20, 0x40,       // 200
+    0x28, 0x20, 0x40,       // 201
+    0x30, 0x20, 0x40,       // 202
+    0x38, 0x20, 0x40,       // 203
+    0x40, 0x20, 0x40,       // 204
+    0x40, 0x20, 0x38,       // 205
+    0x40, 0x20, 0x30,       // 206
+    0x40, 0x20, 0x28,       // 207
+    0x40, 0x20, 0x20,       // 208
+    0x40, 0x28, 0x20,       // 209
+    0x40, 0x30, 0x20,       // 210
+    0x40, 0x38, 0x20,       // 211
+    0x40, 0x40, 0x20,       // 212
+    0x38, 0x40, 0x20,       // 213
+    0x30, 0x40, 0x20,       // 214
+    0x28, 0x40, 0x20,       // 215
+    0x20, 0x40, 0x20,       // 216
+    0x20, 0x40, 0x28,       // 217
+    0x20, 0x40, 0x30,       // 218
+    0x20, 0x40, 0x38,       // 219
+    0x20, 0x40, 0x40,       // 220
+    0x20, 0x38, 0x40,       // 221
+    0x20, 0x30, 0x40,       // 222
+    0x20, 0x28, 0x40,       // 223
+    0x2c, 0x2c, 0x40,       // 224
+    0x30, 0x2c, 0x40,       // 225
+    0x34, 0x2c, 0x40,       // 226
+    0x3c, 0x2c, 0x40,       // 227
+    0x40, 0x2c, 0x40,       // 228
+    0x40, 0x2c, 0x3c,       // 229
+    0x40, 0x2c, 0x34,       // 230
+    0x40, 0x2c, 0x30,       // 231
+    0x40, 0x2c, 0x2c,       // 232
+    0x40, 0x30, 0x2c,       // 233
+    0x40, 0x34, 0x2c,       // 234
+    0x40, 0x3c, 0x2c,       // 235
+    0x40, 0x40, 0x2c,       // 236
+    0x3c, 0x40, 0x2c,       // 237
+    0x34, 0x40, 0x2c,       // 238
+    0x30, 0x40, 0x2c,       // 239
+    0x2c, 0x40, 0x2c,       // 240
+    0x2c, 0x40, 0x30,       // 241
+    0x2c, 0x40, 0x34,       // 242
+    0x2c, 0x40, 0x3c,       // 243
+    0x2c, 0x40, 0x40,       // 244
+    0x2c, 0x3c, 0x40,       // 245
+    0x2c, 0x34, 0x40,       // 246
+    0x2c, 0x30, 0x40,       // 247
+    0x00, 0x00, 0x00,       // 248
+    0x00, 0x00, 0x00,       // 249
+    0x00, 0x00, 0x00,       // 250
+    0x00, 0x00, 0x00,       // 251
+    0x00, 0x00, 0x00,       // 252
+    0x00, 0x00, 0x00,       // 253
+    0x00, 0x00, 0x00,       // 254
+    0x00, 0x00, 0x00        // 255
+};
Index: tests/fb.c
===================================================================
RCS file: tests/fb.c
diff -N tests/fb.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/fb.c	7 Oct 2008 10:03:09 -0000
@@ -0,0 +1,226 @@
+//==========================================================================
+//
+//      fb.c
+//
+//      Framebuffer testcase
+//
+//==========================================================================
+//###ECOSGPLCOPYRIGHTBEGIN####
+//-------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//###DESCRIPTIONBEGIN####
+//
+// Author(s):     bartv
+// Date:          2008-10-06
+//
+//###DESCRIPTIONEND####
+//========================================================================
+
+#include <pkgconf/system.h>
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/testcase.h>
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_intr.h>
+#include <pkgconf/io_framebuf.h>
+#include <cyg/io/framebuf.h>
+
+#if defined(CYGDAT_IO_FRAMEBUF_TEST_DEVICE)
+# define FB         CYGDAT_IO_FRAMEBUF_TEST_DEVICE
+#elif defined(CYGDAT_IO_FRAMEBUF_DEFAULT_TEST_DEVICE)
+# define FB         CYGDAT_IO_FRAMEBUF_DEFAULT_TEST_DEVICE
+#else
+# define NA_MSG "No framebuffer test device selected"
+#endif
+
+#ifndef NA_MSG
+# if (CYG_FB_DEPTH(FB) < 4)
+#  define NA_MSG    "Testcase requires a display depth of at least 4 bits/pixel"
+# else
+#  define FRAMEBUF  CYG_FB_STRUCT(FB)
+# endif
+#endif
+
+#ifdef NA_MSG
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA(NA_MSG);
+}
+#else
+
+#define STRING1(_a_) # _a_
+#define STRING(_a_) STRING1(_a_)
+
+// A simple bitmap. Black on the outside, then blue,
+// then green, and a red centre.
+static cyg_uint8    bitmap8[8][8] = {
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static cyg_uint16   bitmap16[8][8] = {
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static cyg_uint32   bitmap32[8][8] = {
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+// The colours used by this test code. Default to the standard palette
+// but if running on a true colour display then adjust.
+static cyg_ucount32 colours[16]  = {
+    CYG_FB_DEFAULT_PALETTE_BLACK,
+    CYG_FB_DEFAULT_PALETTE_BLUE,
+    CYG_FB_DEFAULT_PALETTE_GREEN,
+    CYG_FB_DEFAULT_PALETTE_CYAN,
+    CYG_FB_DEFAULT_PALETTE_RED,
+    CYG_FB_DEFAULT_PALETTE_MAGENTA,
+    CYG_FB_DEFAULT_PALETTE_BROWN,
+    CYG_FB_DEFAULT_PALETTE_LIGHTGREY,
+    CYG_FB_DEFAULT_PALETTE_DARKGREY,
+    CYG_FB_DEFAULT_PALETTE_LIGHTBLUE,
+    CYG_FB_DEFAULT_PALETTE_LIGHTGREEN,
+    CYG_FB_DEFAULT_PALETTE_LIGHTCYAN,
+    CYG_FB_DEFAULT_PALETTE_LIGHTRED,
+    CYG_FB_DEFAULT_PALETTE_LIGHTMAGENTA,
+    CYG_FB_DEFAULT_PALETTE_YELLOW,
+    CYG_FB_DEFAULT_PALETTE_WHITE
+};
+
+#define BLACK        colours[0x00]
+#define BLUE         colours[0x01]
+#define GREEN        colours[0x02]
+#define CYAN         colours[0x03]
+#define RED          colours[0x04]
+#define MAGENTA      colours[0x05]
+#define BROWN        colours[0x06]
+#define LIGHTGREY    colours[0x07]
+#define DARKGREY     colours[0x08]
+#define LIGHTBLUE    colours[0x09]
+#define LIGHTGREEN   colours[0x0A]
+#define LIGHTCYAN    colours[0x0B]
+#define LIGHTRED     colours[0x0C]
+#define LIGHTMAGENTA colours[0x0D]
+#define YELLOW       colours[0x0E]
+#define WHITE        colours[0x0F]
+
+static void
+reset_colours_to_true(void)
+{
+    int i, j;
+    for (i = 0; i < 16; i++) {
+        colours[i]  = cyg_fb_make_colour(&FRAMEBUF,
+                                         cyg_fb_palette_vga[i + i + i], cyg_fb_palette_vga[i + i + i + 1],cyg_fb_palette_vga[i + i + i + 2]);
+    }
+    for (i = 0; i < 8; i++) {
+        for (j = 0; j < 8; j++) {
+            bitmap16[i][j]  = colours[bitmap16[i][j]];
+            bitmap32[i][j]  = colours[bitmap32[i][j]];
+        }
+    }
+}
+
+void
+cyg_start(void)
+{
+    int             i;
+    cyg_ucount16    block_width;
+    
+    CYG_TEST_INIT();
+    diag_printf("Frame buffer %s\n", STRING(FRAMEBUF));
+    diag_printf("Depth %d, width %d, height %d\n", FRAMEBUF.fb_depth, FRAMEBUF.fb_width, FRAMEBUF.fb_height);
+    cyg_fb_on(&FRAMEBUF);
+
+    if (FRAMEBUF.fb_flags0 & CYG_FB_FLAGS0_TRUE_COLOUR) {
+        reset_colours_to_true();
+    }
+
+    // A white background
+    cyg_fb_fill_block(&FRAMEBUF, 0, 0, FRAMEBUF.fb_width, FRAMEBUF.fb_height, WHITE);
+    // A black block in the middle, 25 pixels in.
+    cyg_fb_fill_block(&FRAMEBUF, 25, 25, FRAMEBUF.fb_width - 50, FRAMEBUF.fb_height - 50, BLACK);
+
+    // Four diagonal lines in the corners. Red in the top left, blue in the top right,
+    // green in the bottom left, and yellow in the bottom right.
+    for (i = 0; i < 25; i++) {
+        cyg_fb_write_pixel(&FRAMEBUF, i,                           i,                            RED);
+        cyg_fb_write_pixel(&FRAMEBUF, (FRAMEBUF.fb_width - 1) - i, i,                            BLUE);
+        cyg_fb_write_pixel(&FRAMEBUF, i,                           (FRAMEBUF.fb_height - 1) - i, GREEN);
+        cyg_fb_write_pixel(&FRAMEBUF, (FRAMEBUF.fb_width - 1) - i, (FRAMEBUF.fb_height - 1) - i, YELLOW);
+    }
+
+    // Horizontal and vertical lines. Cyan at the top, magenta on the bottom,
+    // brown on the left, lightgrey on the right.
+    cyg_fb_write_hline(&FRAMEBUF, 25, 12, FRAMEBUF.fb_width - 50, CYAN);
+    cyg_fb_write_hline(&FRAMEBUF, 25, FRAMEBUF.fb_height - 12, FRAMEBUF.fb_width - 50, MAGENTA);
+    cyg_fb_write_vline(&FRAMEBUF, 12, 25, FRAMEBUF.fb_height - 50, BROWN);
+    cyg_fb_write_vline(&FRAMEBUF, FRAMEBUF.fb_width - 12, 25, FRAMEBUF.fb_height - 50, LIGHTGREY);
+
+    // Display a simple bitmap on the left, halfway down.
+    if (8 == FRAMEBUF.fb_depth) {
+        cyg_fb_write_block(&FRAMEBUF, 0, FRAMEBUF.fb_height / 2, 8, 8, bitmap8, 0, 8);
+    } else if (16 == FRAMEBUF.fb_depth) {
+        cyg_fb_write_block(&FRAMEBUF, 0, FRAMEBUF.fb_height / 2, 8, 8, bitmap16, 0, 8);
+    } else if (32 == FRAMEBUF.fb_depth) {
+        cyg_fb_write_block(&FRAMEBUF, 0, FRAMEBUF.fb_height / 2, 8, 8, bitmap32, 0, 8);
+    }
+
+    // And 14 vertical stripes, from blue to yellow, in the centre of the box.
+    block_width     = (FRAMEBUF.fb_width - 100) / 14;
+    for (i = 1; i <= 14; i++) {
+        cyg_fb_fill_block(&FRAMEBUF, 50 + ((i - 1) * block_width), 50, block_width, FRAMEBUF.fb_height - 100, colours[i]);
+    }
+
+    cyg_fb_synch(&FRAMEBUF, CYG_FB_UPDATE_NOW);
+    
+    CYG_TEST_EXIT("Done");
+}
+#endif  // NA_MSG
Index: tests/fbmacro.c
===================================================================
RCS file: tests/fbmacro.c
diff -N tests/fbmacro.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/fbmacro.c	7 Oct 2008 10:03:09 -0000
@@ -0,0 +1,284 @@
+//==========================================================================
+//
+//      fbmacro.c
+//
+//      Framebuffer testcase
+//
+//==========================================================================
+//###ECOSGPLCOPYRIGHTBEGIN####
+//-------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 2008 Free Software Foundation, Inc.
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//###DESCRIPTIONBEGIN####
+//
+// Author(s):     bartv
+// Date:          2008-10-06
+//
+//###DESCRIPTIONEND####
+//========================================================================
+
+#include <pkgconf/system.h>
+#include <cyg/infra/cyg_type.h>
+#include <cyg/infra/testcase.h>
+#include <cyg/infra/diag.h>
+#include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_intr.h>
+#include <pkgconf/io_framebuf.h>
+#include <cyg/io/framebuf.h>
+
+#if defined(CYGDAT_IO_FRAMEBUF_TEST_DEVICE)
+# define FRAMEBUF   CYGDAT_IO_FRAMEBUF_TEST_DEVICE
+#elif defined(CYGDAT_IO_FRAMEBUF_DEFAULT_TEST_DEVICE)
+# define FRAMEBUF   CYGDAT_IO_FRAMEBUF_DEFAULT_TEST_DEVICE
+#else
+# define NA_MSG "No framebuffer test device selected"
+#endif
+
+#ifndef NA_MSG
+# if (CYG_FB_DEPTH(FRAMEBUF) < 4)
+#  define NA_MSG    "Testcase requires a display depth of at least 4 bits/pixel"
+# endif
+#endif
+
+#ifdef NA_MSG
+void
+cyg_start(void)
+{
+    CYG_TEST_INIT();
+    CYG_TEST_NA(NA_MSG);
+}
+#else
+
+#define STRING1(_a_) # _a_
+#define STRING(_a_) STRING1(_a_)
+
+// A simple bitmap. Black on the outside, then blue,
+// then green, and a red centre.
+static cyg_uint8    bitmap8[8][8] = {
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static cyg_uint16   bitmap16[8][8] = {
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+static cyg_uint32   bitmap32[8][8] = {
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+    { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00 },
+    { 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+};
+
+// The colours used by this test code. Default to the standard palette
+// but if running on a true colour display then adjust.
+static cyg_ucount32 colours[16]  = {
+    CYG_FB_DEFAULT_PALETTE_BLACK,
+    CYG_FB_DEFAULT_PALETTE_BLUE,
+    CYG_FB_DEFAULT_PALETTE_GREEN,
+    CYG_FB_DEFAULT_PALETTE_CYAN,
+    CYG_FB_DEFAULT_PALETTE_RED,
+    CYG_FB_DEFAULT_PALETTE_MAGENTA,
+    CYG_FB_DEFAULT_PALETTE_BROWN,
+    CYG_FB_DEFAULT_PALETTE_LIGHTGREY,
+    CYG_FB_DEFAULT_PALETTE_DARKGREY,
+    CYG_FB_DEFAULT_PALETTE_LIGHTBLUE,
+    CYG_FB_DEFAULT_PALETTE_LIGHTGREEN,
+    CYG_FB_DEFAULT_PALETTE_LIGHTCYAN,
+    CYG_FB_DEFAULT_PALETTE_LIGHTRED,
+    CYG_FB_DEFAULT_PALETTE_LIGHTMAGENTA,
+    CYG_FB_DEFAULT_PALETTE_YELLOW,
+    CYG_FB_DEFAULT_PALETTE_WHITE
+};
+
+#define BLACK        colours[0x00]
+#define BLUE         colours[0x01]
+#define GREEN        colours[0x02]
+#define CYAN         colours[0x03]
+#define RED          colours[0x04]
+#define MAGENTA      colours[0x05]
+#define BROWN        colours[0x06]
+#define LIGHTGREY    colours[0x07]
+#define DARKGREY     colours[0x08]
+#define LIGHTBLUE    colours[0x09]
+#define LIGHTGREEN   colours[0x0A]
+#define LIGHTCYAN    colours[0x0B]
+#define LIGHTRED     colours[0x0C]
+#define LIGHTMAGENTA colours[0x0D]
+#define YELLOW       colours[0x0E]
+#define WHITE        colours[0x0F]
+
+static void
+reset_colours_to_true(void)
+{
+#if (CYG_FB_FLAGS0_TRUE_COLOUR & CYG_FB_FLAGS0(FRAMEBUF))    
+    int i, j;
+    
+    for (i = 0; i < 16; i++) {
+        colours[i] = CYG_FB_MAKE_COLOUR(FRAMEBUF,
+                                        cyg_fb_palette_vga[i + i + i], cyg_fb_palette_vga[i + i + i + 1],cyg_fb_palette_vga[i + i + i + 2]);
+    }
+    for (i = 0; i < 8; i++) {
+        for (j = 0; j < 8; j++) {
+            bitmap16[i][j]  = colours[bitmap16[i][j]];
+            bitmap32[i][j]  = colours[bitmap32[i][j]];
+        }
+    }
+#endif    
+}
+
+void
+cyg_start(void)
+{
+    int             i, j;
+    int             x = 0, y = 0;
+    int             result;
+    cyg_ucount16    block_width;
+    
+    CYG_FB_PIXEL0_VAR(FRAMEBUF);
+    CYG_FB_PIXEL1_VAR(FRAMEBUF);
+    
+#define DEPTH   CYG_FB_DEPTH(FRAMEBUF)
+#define WIDTH   CYG_FB_WIDTH(FRAMEBUF)
+#define HEIGHT  CYG_FB_HEIGHT(FRAMEBUF)    
+    
+    CYG_TEST_INIT();
+
+    diag_printf("Frame buffer %s\n", STRING(FRAMEBUF));
+    diag_printf("Depth %d, width %d, height %d\n", DEPTH, WIDTH, HEIGHT);
+    
+    result = CYG_FB_ON(FRAMEBUF);
+
+    if (CYG_FB_FLAGS0(FRAMEBUF) & CYG_FB_FLAGS0_TRUE_COLOUR) {
+        reset_colours_to_true();
+    }
+    
+    // A white background
+    CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0, WIDTH, HEIGHT, WHITE);
+    // A black block in the middle, 25 pixels in.
+    CYG_FB_FILL_BLOCK(FRAMEBUF, 32, 32, WIDTH - 64, HEIGHT - 64, BLACK);
+
+    // Four diagonal lines in the corners. Red in the top left, blue in the top right,
+    // green in the bottom left, and yellow in the bottom right.
+    for (i = 0; i < 32; i++) {
+        CYG_FB_WRITE_PIXEL(FRAMEBUF, i,               i,                RED);
+        CYG_FB_WRITE_PIXEL(FRAMEBUF, (WIDTH - 1) - i, i,                BLUE);
+        CYG_FB_WRITE_PIXEL(FRAMEBUF, i,               (HEIGHT - 1) - i, GREEN);
+        CYG_FB_WRITE_PIXEL(FRAMEBUF, (WIDTH - 1) - i, (HEIGHT - 1) - i, YELLOW);
+    }
+
+    // Horizontal and vertical lines. Cyan at the top, magenta on the bottom,
+    // brown on the left, lightgrey on the right.
+    CYG_FB_WRITE_HLINE(FRAMEBUF, 32,         16,            WIDTH - 64, CYAN);
+    CYG_FB_WRITE_HLINE(FRAMEBUF, 32,         HEIGHT - 16,   WIDTH - 64, MAGENTA);
+    CYG_FB_WRITE_VLINE(FRAMEBUF, 16,         32,            HEIGHT - 64, BROWN);
+    CYG_FB_WRITE_VLINE(FRAMEBUF, WIDTH - 16, 32,            HEIGHT - 64, LIGHTGREY);
+
+    // Top left, diagonal lines away from 0,0 with increasing spacing horizontally
+    for (i = 0; i < 16; i++) {
+        CYG_FB_PIXEL0_SET(FRAMEBUF, i + 16, i);
+        for (j = 0; j < 16; j++) {
+            CYG_FB_PIXEL0_WRITE(FRAMEBUF, colours[i]);
+            CYG_FB_PIXEL0_ADDX(FRAMEBUF, j);
+        }
+    }
+
+    // Top right, diagonal lines away from the corner, with increasing spacing horizontally
+    for (i = 0; i < 16; i++) {
+        CYG_FB_PIXEL0_SET(FRAMEBUF, WIDTH - (i + 16), i);
+        for (j = 0; j < 16; j++) {
+            CYG_FB_PIXEL0_WRITE(FRAMEBUF, colours[i]);
+            CYG_FB_PIXEL0_ADDX(FRAMEBUF, -1 * j);
+        }
+    }
+
+    // Top left, diagonal lines away from the corner, with increasing spacing vertically
+    for (i = 0; i < 16; i++) {
+        CYG_FB_PIXEL0_SET(FRAMEBUF, i, i + 16);
+        for (j = 0; j < 16; j++) {
+            CYG_FB_PIXEL0_WRITE(FRAMEBUF, colours[i]);
+            CYG_FB_PIXEL0_ADDY(FRAMEBUF, j);
+        }
+    }
+    // Bottom left, diagonal lines away from the corner, with increasing spacing vertically
+    for (i = 0; i < 16; i++) {
+        CYG_FB_PIXEL0_SET(FRAMEBUF, i, HEIGHT - (i + 16));
+        for (j = 0; j < 16; j++) {
+            CYG_FB_PIXEL0_WRITE(FRAMEBUF, colours[i]);
+            CYG_FB_PIXEL0_ADDY(FRAMEBUF, -1 * j);
+        }
+    }
+
+    // Thin vertical bars in the top-middle of the screen, between the hline and the box.
+    // Starting in the center and moving out with increasing spacing.
+    for (j = 0; j < 8; j++) {
+        CYG_FB_PIXEL0_SET(FRAMEBUF, (WIDTH / 2) - 2, 20 + j);
+        CYG_FB_PIXEL0_GET(FRAMEBUF, x, y);
+        CYG_FB_PIXEL1_SET(FRAMEBUF, x + 3, y);
+        for (i = 0; i < 16; i++) {
+            CYG_FB_PIXEL0_ADDX(FRAMEBUF, -1 * i);
+            CYG_FB_PIXEL1_ADDX(FRAMEBUF, i);
+            CYG_FB_PIXEL0_WRITE(FRAMEBUF, colours[i]);
+            CYG_FB_PIXEL1_WRITE(FRAMEBUF, colours[i]);
+        }
+    }
+    
+    
+    if (8 == DEPTH) {
+        CYG_FB_WRITE_BLOCK(FRAMEBUF, 0, HEIGHT / 2, 8, 8, bitmap8, 0, 8);
+    } else if (16 == DEPTH) {
+        CYG_FB_WRITE_BLOCK(FRAMEBUF, 0, HEIGHT / 2, 8, 8, bitmap16, 0, 8);
+    } else if (32 == DEPTH) {
+        CYG_FB_WRITE_BLOCK(FRAMEBUF, 0, HEIGHT / 2, 8, 8, bitmap32, 0, 8);
+    }
+
+    block_width     = (WIDTH - 100) / 14;
+    for (i = 1; i <= 14; i++) {
+        CYG_FB_FILL_BLOCK(FRAMEBUF, 50 + ((i - 1) * block_width), 50, block_width, HEIGHT - 100, colours[i]);
+    }
+
+    CYG_TEST_EXIT("Done");
+}
+#endif  // NA_MSG


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]