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>
|
2009-08-05 Joel Sherrill <joel.sherrill@OARcorp.com>
|
||||||
|
|
||||||
* user/conf.t: Add configuration of posix message queue file
|
* user/conf.t: Add configuration of posix message queue file
|
||||||
|
|||||||
@@ -8,33 +8,50 @@
|
|||||||
|
|
||||||
@chapter Frame Buffer Driver
|
@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
|
@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.
|
graphics hardware.
|
||||||
By using the frame buffer interface the application can access the graphics
|
By using the frame buffer interface, an application can display graphics
|
||||||
without knowing anything about the low-level communication.
|
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
|
The frame buffer driver is commonly located in the @code{console}
|
||||||
of the BSP and registered by the name @b{/dev/fb}
|
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
|
@subsection Initialization
|
||||||
|
|
||||||
The driver initialization is called once during the RTEMS initialization
|
The driver initialization is called once during the RTEMS initialization
|
||||||
process and returns RTEMS_SUCCESSFUL when the device driver is successfully
|
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
|
@example
|
||||||
@group
|
@group
|
||||||
rtems_device_driver frame_buffer_initialize(
|
rtems_device_driver frame_buffer_initialize(
|
||||||
rtems_device_major_number major,
|
rtems_device_major_number major,
|
||||||
rtems_device_minor_number minor,
|
rtems_device_minor_number minor,
|
||||||
void *arg
|
void *arg)
|
||||||
)
|
|
||||||
@{
|
@{
|
||||||
rtems_status_code status;
|
rtems_status_code status;
|
||||||
|
|
||||||
@@ -43,12 +60,17 @@ rtems_device_driver frame_buffer_initialize(
|
|||||||
/*
|
/*
|
||||||
* Register the device
|
* 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)
|
if (status != RTEMS_SUCCESSFUL)
|
||||||
@{
|
@{
|
||||||
printk("Error registering frame buffer device!\n");
|
printk("Error registering frame buffer device!\n");
|
||||||
rtems_fatal_error_occurred( status );
|
rtems_fatal_error_occurred( status );
|
||||||
@}
|
@}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* graphics hardware initialization goes here for non-console
|
||||||
|
* devices
|
||||||
|
*/
|
||||||
|
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
@}
|
@}
|
||||||
@@ -57,40 +79,16 @@ rtems_device_driver frame_buffer_initialize(
|
|||||||
|
|
||||||
@subsection Opening the Frame Buffer Device
|
@subsection Opening the Frame Buffer Device
|
||||||
|
|
||||||
The @code{frame_buffer_open} function is called whenever a frame buffer device is opened.
|
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
|
If the frame buffer is registered as "/dev/fb0", the @code{frame_buffer_open} entry point
|
||||||
opened automatically during RTEMS initialization. For instance, if the frame buffer is
|
will be called as the result of an @code{open("/dev/fb0", mode)} in the application.
|
||||||
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 returns RTEMS_SUCCESSFUL when the device driver
|
Thread safety of the frame buffer driver is implementation-dependent.
|
||||||
is successfully opened:
|
The VGA driver shown below uses a mutex to prevent multiple open()
|
||||||
|
operations of the frame buffer device.
|
||||||
|
|
||||||
@example
|
The @code{frame_buffer_open()} function returns RTEMS_SUCCESSFUL when the device driver
|
||||||
@group
|
is successfully opened, and RTEMS_UNSATISFIED if the device is already open:
|
||||||
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:
|
|
||||||
|
|
||||||
@example
|
@example
|
||||||
@group
|
@group
|
||||||
@@ -100,9 +98,47 @@ rtems_device_driver frame_buffer_close(
|
|||||||
void *arg
|
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();
|
ega_hwterm();
|
||||||
printk( "frame buffer close called.\n" );
|
printk( "frame buffer close called.\n" );
|
||||||
|
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
@}
|
@}
|
||||||
|
|
||||||
@@ -112,7 +148,11 @@ rtems_device_driver frame_buffer_close(
|
|||||||
|
|
||||||
@subsection Reading from the Frame Buffer Device
|
@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:
|
This method returns RTEMS_SUCCESSFUL when the device is successfully read from:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
@@ -123,17 +163,40 @@ rtems_device_driver frame_buffer_read(
|
|||||||
void *arg
|
void *arg
|
||||||
)
|
)
|
||||||
@{
|
@{
|
||||||
/*TBD*/
|
/*printk( "FBVGA read called.\n" );*/
|
||||||
return RTEMS_SUCCESSFUL;
|
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 group
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@subsection Writing to the Frame Buffer Device
|
@subsection Writing to the Frame Buffer Device
|
||||||
|
|
||||||
The @code{frame_buffer_write} is invoked when the serial device is to be written to.
|
The @code{frame_buffer_write()} is invoked from a @code{write()}
|
||||||
This entry point corresponds to the device driver write entry point.
|
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
|
@example
|
||||||
@group
|
@group
|
||||||
@@ -143,19 +206,46 @@ rtems_device_driver frame_buffer_write(
|
|||||||
void *arg
|
void *arg
|
||||||
)
|
)
|
||||||
@{
|
@{
|
||||||
/*TBD*/
|
/*printk( "FBVGA write called.\n" );*/
|
||||||
return RTEMS_SUCCESSFUL;
|
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 group
|
||||||
@end example
|
@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.
|
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
|
@example
|
||||||
@group
|
@group
|
||||||
@@ -171,19 +261,20 @@ rtems_device_driver frame_buffer_control(
|
|||||||
|
|
||||||
switch( args->command ) @{
|
switch( args->command ) @{
|
||||||
case FBIOGET_FSCREENINFO:
|
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;
|
break;
|
||||||
case FBIOGET_VSCREENINFO:
|
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;
|
break;
|
||||||
case FBIOPUT_VSCREENINFO:
|
case FBIOPUT_VSCREENINFO:
|
||||||
/* not implemented yet*/
|
/* not implemented yet*/
|
||||||
break;
|
args->ioctl_return = -1;
|
||||||
|
return RTEMS_UNSATISFIED;
|
||||||
case FBIOGETCMAP:
|
case FBIOGETCMAP:
|
||||||
args->ioctl_return = get_palette( args->buffer );
|
args->ioctl_return = get_palette( ( struct fb_cmap * ) args->buffer );
|
||||||
break;
|
break;
|
||||||
case FBIOPUTCMAP:
|
case FBIOPUTCMAP:
|
||||||
args->ioctl_return = set_palette( args->buffer );
|
args->ioctl_return = set_palette( ( struct fb_cmap * ) args->buffer );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -195,5 +286,5 @@ rtems_device_driver frame_buffer_control(
|
|||||||
@end group
|
@end group
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
Look into @code{rtems/fb.h} for more information on what ioctls exist and on
|
See @code{rtems/fb.h} for more information on the list of ioctls and
|
||||||
which data structures they work.
|
data structures they work with.
|
||||||
|
|||||||
Reference in New Issue
Block a user