forked from Imagelibrary/rtems
2009-08-21 Roxana Leontie <roxana.leontie@gmail.com>
* bsp_howto/framebuffer.t: Updated the frame buffer documentation.
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
2009-08-21 Roxana Leontie <roxana.leontie@gmail.com>
|
||||
|
||||
* bsp_howto/framebuffer.t: Updated the frame buffer documentation.
|
||||
|
||||
2009-08-05 Joel Sherrill <joel.sherrill@OARcorp.com>
|
||||
|
||||
* user/conf.t: Add configuration of posix message queue file
|
||||
|
||||
@@ -8,33 +8,50 @@
|
||||
|
||||
@chapter Frame Buffer Driver
|
||||
|
||||
In this chapter, we present the basic functionality implemented by a
|
||||
frame buffer driver: @code{frame_buffer_initialize()}, @code{frame_buffer_open()},
|
||||
@code{frame_buffer_close()}, @code{frame_buffer_read()}, @code{frame_buffer_write()}
|
||||
and @code{frame_buffer_control()}.
|
||||
|
||||
@section Introduction
|
||||
|
||||
The purpose of the frame buffer driver is to provide an abstraction for the
|
||||
The purpose of the frame buffer driver is to provide an abstraction for
|
||||
graphics hardware.
|
||||
By using the frame buffer interface the application can access the graphics
|
||||
without knowing anything about the low-level communication.
|
||||
By using the frame buffer interface, an application can display graphics
|
||||
without knowing anything about the low-level details of interfacing to a
|
||||
particular graphics adapter. The parameters governing the mapping of
|
||||
memory to displayed pixels (planar or linear, bit depth, etc) is still
|
||||
implementation-specific, but device-independent methods are provided to
|
||||
determine and potentially modify these parameters.
|
||||
|
||||
The frame buffer driver is usually located in the @code{console} directory
|
||||
of the BSP and registered by the name @b{/dev/fb}
|
||||
The frame buffer driver is commonly located in the @code{console}
|
||||
directory of the BSP and registered by the name @b{/dev/fb0}.
|
||||
Additional frame buffers (if available) are named @b{/dev/fb1},
|
||||
@b{/dev/fb2}, etc.
|
||||
|
||||
@section Driver Functioning Overview
|
||||
To work with the frame buffer, the following operation sequence is used:
|
||||
@code{open()}, @code{ioctls()} to get the frame buffer info, @code{read()} and/or
|
||||
@code{write()}, and @code{close()}.
|
||||
|
||||
@section Driver Function Overview
|
||||
|
||||
@subsection Initialization
|
||||
|
||||
The driver initialization is called once during the RTEMS initialization
|
||||
process and returns RTEMS_SUCCESSFUL when the device driver is successfully
|
||||
initialized
|
||||
initialized. During the initialization, a name is assigned to the frame
|
||||
buffer device. If the graphics hardware supports console text output,
|
||||
as is the case with the pc386 VGA hardware, initialization into graphics
|
||||
mode may be deferred until the device is @code{open()}ed.
|
||||
|
||||
The @code{frame_buffer_initialize} function may look like this:
|
||||
The @code{frame_buffer_initialize()} function may look like this:
|
||||
|
||||
@example
|
||||
@group
|
||||
rtems_device_driver frame_buffer_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
void *arg)
|
||||
@{
|
||||
rtems_status_code status;
|
||||
|
||||
@@ -43,12 +60,17 @@ rtems_device_driver frame_buffer_initialize(
|
||||
/*
|
||||
* Register the device
|
||||
*/
|
||||
status = rtems_io_register_name ("/dev/fb", major, 0);
|
||||
status = rtems_io_register_name("/dev/fb0", major, 0);
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
@{
|
||||
@{
|
||||
printk("Error registering frame buffer device!\n");
|
||||
rtems_fatal_error_occurred( status );
|
||||
@}
|
||||
@}
|
||||
|
||||
/*
|
||||
* graphics hardware initialization goes here for non-console
|
||||
* devices
|
||||
*/
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@}
|
||||
@@ -57,40 +79,16 @@ rtems_device_driver frame_buffer_initialize(
|
||||
|
||||
@subsection Opening the Frame Buffer Device
|
||||
|
||||
The @code{frame_buffer_open} function is called whenever a frame buffer device is opened.
|
||||
The device registered as @code{"/dev/fb"} (@code{FRAMEBUFFER_DEVICE_NAME}) is
|
||||
opened automatically during RTEMS initialization. For instance, if the frame buffer is
|
||||
registered as "/dev/fb", the @code{frame_buffer_open} entry point will be called as the
|
||||
result of an @code{open("/dev/fb", mode)} in the application.
|
||||
The @code{frame_buffer_open()} function is called whenever a frame buffer device is opened.
|
||||
If the frame buffer is registered as "/dev/fb0", the @code{frame_buffer_open} entry point
|
||||
will be called as the result of an @code{open("/dev/fb0", mode)} in the application.
|
||||
|
||||
The @code{frame_buffer_open} function returns RTEMS_SUCCESSFUL when the device driver
|
||||
is successfully opened:
|
||||
Thread safety of the frame buffer driver is implementation-dependent.
|
||||
The VGA driver shown below uses a mutex to prevent multiple open()
|
||||
operations of the frame buffer device.
|
||||
|
||||
@example
|
||||
@group
|
||||
rtems_device_driver frame_buffer_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
@{
|
||||
ega_hwinit();
|
||||
printk( "frame buffer open called.\n" );
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@}
|
||||
@end group
|
||||
@end example
|
||||
|
||||
The @code{ega_hwinit()} which takes care of the hardware initialization.
|
||||
|
||||
@subsection Closing the Frame Buffer Device
|
||||
|
||||
The @code{frame_buffer_close} is invoked when the serial device is to be closed.
|
||||
This entry point corresponds to the device driver close entry point.
|
||||
|
||||
The @code{frame_buffer_close} function freeing up the hardware resources.
|
||||
Returns RTEMS_SUCCESSFUL when the device driver is successfully closed:
|
||||
The @code{frame_buffer_open()} function returns RTEMS_SUCCESSFUL when the device driver
|
||||
is successfully opened, and RTEMS_UNSATISFIED if the device is already open:
|
||||
|
||||
@example
|
||||
@group
|
||||
@@ -100,9 +98,47 @@ rtems_device_driver frame_buffer_close(
|
||||
void *arg
|
||||
)
|
||||
@{
|
||||
if (pthread_mutex_unlock(&mutex) == 0)@{
|
||||
/* restore previous state. for VGA this means return to text mode.
|
||||
* leave out if graphics hardware has been initialized in
|
||||
* frame_buffer_initialize() */
|
||||
ega_hwterm();
|
||||
printk( "FBVGA close called.\n" );
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@}
|
||||
|
||||
return RTEMS_UNSATISFIED;
|
||||
@}
|
||||
@end group
|
||||
@end example
|
||||
|
||||
In the previous example, the function @code{ega_hwinit()} takes care of
|
||||
hardware-specific initialization.
|
||||
|
||||
@subsection Closing the Frame Buffer Device
|
||||
|
||||
The @code{frame_buffer_close()} is invoked when the frame buffer device
|
||||
is closed. It frees up any resources allocated in
|
||||
@code{frame_buffer_open()}, and should restore previous hardware state.
|
||||
The entry point corresponds to the device driver close entry point.
|
||||
|
||||
Returns RTEMS_SUCCESSFUL when the device driver is successfully closed:
|
||||
|
||||
@example
|
||||
@group
|
||||
rtems_device_driver frame_buffer_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg)
|
||||
@{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
/* TODO check mutex return value, RTEMS_UNSATISFIED if it failed. we
|
||||
* don't want to unconditionally call ega_hwterm()... */
|
||||
/* restore previous state. for VGA this means return to text mode.
|
||||
* leave out if graphics hardware has been initialized in
|
||||
* frame_buffer_initialize() */
|
||||
ega_hwterm();
|
||||
printk( "frame buffer close called.\n" );
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@}
|
||||
|
||||
@@ -112,7 +148,11 @@ rtems_device_driver frame_buffer_close(
|
||||
|
||||
@subsection Reading from the Frame Buffer Device
|
||||
|
||||
The @code{frame_buffer_read} is invoked when the serial device is to be read from.
|
||||
The @code{frame_buffer_read()} is invoked from a @code{read()} operation
|
||||
on the frame buffer device.
|
||||
Read functions should allow normal and partial reading at the end of frame buffer memory,
|
||||
returning RTEMS_UNSATISFIED if trying to read beyond the frame buffer
|
||||
memory or a negative number of bytes.
|
||||
This method returns RTEMS_SUCCESSFUL when the device is successfully read from:
|
||||
|
||||
@example
|
||||
@@ -123,17 +163,40 @@ rtems_device_driver frame_buffer_read(
|
||||
void *arg
|
||||
)
|
||||
@{
|
||||
/*TBD*/
|
||||
return RTEMS_SUCCESSFUL;
|
||||
/*printk( "FBVGA read called.\n" );*/
|
||||
rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
|
||||
if ( (rw_args->offset >= fb_fix.smem_len) || (rw_args->count < 0) )@{
|
||||
return RTEMS_UNSATISFIED;
|
||||
@}
|
||||
else
|
||||
@{
|
||||
/*partial reading*/
|
||||
if ( (rw_args->offset + rw_args->count) > fb_fix.smem_len )@{
|
||||
rw_args->count = fb_fix.smem_len - rw_args->offset;
|
||||
memcpy(rw_args->buffer, (const void *) (rw_args->offset + fb_fix.smem_start), rw_args->count);
|
||||
rw_args->bytes_moved = rw_args->count;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@}
|
||||
/*best reading case*/
|
||||
else@{
|
||||
memcpy(rw_args->buffer, (const void *) (rw_args->offset + fb_fix.smem_start), rw_args->count);
|
||||
rw_args->bytes_moved = rw_args->count;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@}
|
||||
@}
|
||||
@}
|
||||
@end group
|
||||
@end example
|
||||
|
||||
@subsection Writing to the Frame Buffer Device
|
||||
|
||||
The @code{frame_buffer_write} is invoked when the serial device is to be written to.
|
||||
This entry point corresponds to the device driver write entry point.
|
||||
The @code{frame_buffer_write()} is invoked from a @code{write()}
|
||||
operation on the frame buffer device.
|
||||
The frame buffer write function is similar to the read function, and
|
||||
should handle similar cases involving partial writes.
|
||||
|
||||
This method returns RTEMS_SUCCESSFUL when the device is successfully
|
||||
written to:
|
||||
|
||||
@example
|
||||
@group
|
||||
@@ -143,19 +206,46 @@ rtems_device_driver frame_buffer_write(
|
||||
void *arg
|
||||
)
|
||||
@{
|
||||
/*TBD*/
|
||||
return RTEMS_SUCCESSFUL;
|
||||
/*printk( "FBVGA write called.\n" );*/
|
||||
rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
|
||||
if ( (rw_args->offset >= fb_fix.smem_len) || (rw_args->count < 0) )@{
|
||||
return RTEMS_UNSATISFIED;
|
||||
@}
|
||||
else
|
||||
@{
|
||||
/*partial writing*/
|
||||
if ( (rw_args->offset + rw_args->count) > fb_fix.smem_len )@{
|
||||
rw_args->count = fb_fix.smem_len - rw_args->offset;
|
||||
memcpy( (void *) (rw_args->offset + fb_fix.smem_start), rw_args->buffer, rw_args->count);
|
||||
rw_args->bytes_moved = rw_args->count;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@}
|
||||
/* best writing case*/
|
||||
else@{
|
||||
memcpy( (void *) (rw_args->offset + fb_fix.smem_start), rw_args->buffer, rw_args->count);
|
||||
rw_args->bytes_moved = rw_args->count;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@}
|
||||
@}
|
||||
@}
|
||||
@end group
|
||||
@end example
|
||||
|
||||
|
||||
@section Frame Buffer IO Control
|
||||
@subsection Frame Buffer IO Control
|
||||
|
||||
The frame buffer driver allows several ioctls partial compatible with the linux ones
|
||||
The frame buffer driver allows several ioctls, partially compatible with
|
||||
the Linux kernel,
|
||||
to obtain information about the hardware.
|
||||
Basically `ioctl' commands call `console_control' with the
|
||||
serial line configuration wich handeles all the services on the interface.
|
||||
|
||||
All @code{ioctl()} operations on the frame buffer device invoke
|
||||
@code{frame_buffer_control()}.
|
||||
|
||||
Ioctls supported:
|
||||
@itemize @bullet
|
||||
@item ioctls to get the frame buffer screen info (fixed and variable).
|
||||
@item ioctl to set and get palette.
|
||||
@end itemize
|
||||
|
||||
@example
|
||||
@group
|
||||
@@ -171,19 +261,20 @@ rtems_device_driver frame_buffer_control(
|
||||
|
||||
switch( args->command ) @{
|
||||
case FBIOGET_FSCREENINFO:
|
||||
args->ioctl_return = get_fix_screen_info( args->buffer );
|
||||
args->ioctl_return = get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer );
|
||||
break;
|
||||
case FBIOGET_VSCREENINFO:
|
||||
args->ioctl_return = get_var_screen_info( args->buffer );
|
||||
args->ioctl_return = get_var_screen_info( ( struct fb_var_screeninfo * ) args->buffer );
|
||||
break;
|
||||
case FBIOPUT_VSCREENINFO:
|
||||
/* not implemented yet*/
|
||||
break;
|
||||
args->ioctl_return = -1;
|
||||
return RTEMS_UNSATISFIED;
|
||||
case FBIOGETCMAP:
|
||||
args->ioctl_return = get_palette( args->buffer );
|
||||
args->ioctl_return = get_palette( ( struct fb_cmap * ) args->buffer );
|
||||
break;
|
||||
case FBIOPUTCMAP:
|
||||
args->ioctl_return = set_palette( args->buffer );
|
||||
args->ioctl_return = set_palette( ( struct fb_cmap * ) args->buffer );
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -195,5 +286,5 @@ rtems_device_driver frame_buffer_control(
|
||||
@end group
|
||||
@end example
|
||||
|
||||
Look into @code{rtems/fb.h} for more information on what ioctls exist and on
|
||||
which data structures they work.
|
||||
See @code{rtems/fb.h} for more information on the list of ioctls and
|
||||
data structures they work with.
|
||||
|
||||
Reference in New Issue
Block a user