Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:41

0001 /*
0002  * Copyright (c) 2000 - Rosimildo da Silva ( rdasilva@connecttel.com )
0003  *
0004  * MODULE DESCRIPTION:
0005  * This module implements FB driver for "Bare VGA". It uses the
0006  * routines for "bare hardware" found in vgainit.c.
0007  *
0008  */
0009 
0010 #include <stdlib.h>
0011 #include <stdio.h>
0012 #include <errno.h>
0013 #include <sys/types.h>
0014 #include <pthread.h>
0015 
0016 #include <bsp.h>
0017 #include <bsp/irq.h>
0018 #include <rtems/libio.h>
0019 
0020 #include <rtems/fb.h>
0021 #include <rtems/framebuffer.h>
0022 
0023 #include <rtems/score/atomic.h>
0024 
0025 /* these routines are defined in vgainit.c.*/
0026 extern void ega_hwinit( void );
0027 extern void ega_hwterm( void );
0028 
0029 /* flag to limit driver to protect against multiple opens */
0030 static Atomic_Flag driver_mutex;
0031 
0032 /* screen information for the VGA driver */
0033 static struct fb_var_screeninfo fb_var =
0034 {
0035   .xres                = 640,
0036   .yres                = 480,
0037   .bits_per_pixel      = 4
0038 };
0039 
0040 static struct fb_fix_screeninfo fb_fix =
0041 {
0042   .smem_start          = (volatile char *)0xA0000,     /* buffer pointer    */
0043   .smem_len            = 0x10000,                      /* buffer size       */
0044   .type                = FB_TYPE_VGA_PLANES,           /* type of dsplay    */
0045   .visual              = FB_VISUAL_PSEUDOCOLOR,        /* color scheme used */
0046   .line_length         = 80                            /* chars per line    */
0047 };
0048 
0049 
0050 static uint16_t red16[] = {
0051    0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa,
0052    0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff
0053 };
0054 static uint16_t green16[] = {
0055    0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa,
0056    0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff
0057 };
0058 static uint16_t blue16[] = {
0059    0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa,
0060    0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff
0061 };
0062 
0063 /* Functionality to support multiple VGA frame buffers can be added easily,
0064  * but is not supported at this moment because there is no need for two or
0065  * more "classic" VGA adapters.  Multiple frame buffer drivers may be
0066  * implemented and If we had implement it they would be named as "/dev/fb0",
0067  * "/dev/fb1", "/dev/fb2" and so on.
0068  */
0069 /*
0070  * fbvga device driver INITIALIZE entry point.
0071  */
0072 rtems_device_driver frame_buffer_initialize(
0073   rtems_device_major_number  major,
0074   rtems_device_minor_number  minor,
0075   void                      *arg
0076 )
0077 {
0078   rtems_status_code status;
0079 
0080   printk( "FBVGA -- driver initializing..\n" );
0081 
0082   /*
0083    * Register the device
0084    */
0085   status = rtems_io_register_name (FRAMEBUFFER_DEVICE_0_NAME, major, 0);
0086   if (status != RTEMS_SUCCESSFUL) {
0087     printk("Error registering " FRAMEBUFFER_DEVICE_0_NAME
0088            " FBVGA framebuffer device!\n");
0089     rtems_fatal_error_occurred( status );
0090   }
0091 
0092   _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
0093 
0094   return RTEMS_SUCCESSFUL;
0095 }
0096 
0097 /*
0098  * fbvga device driver OPEN entry point
0099  */
0100 rtems_device_driver frame_buffer_open(
0101   rtems_device_major_number  major,
0102   rtems_device_minor_number  minor,
0103   void                      *arg
0104 )
0105 {
0106   if (_Atomic_Flag_test_and_set(&driver_mutex, ATOMIC_ORDER_ACQUIRE) != 0 ) {
0107       /* restore previous state.  for VGA this means return to text mode.
0108        * leave out if graphics hardware has been initialized in
0109        * frame_buffer_initialize()
0110        */
0111       ega_hwinit();
0112       printk( "FBVGA open called.\n" );
0113       return RTEMS_SUCCESSFUL;
0114   }
0115 
0116   return RTEMS_UNSATISFIED;
0117 }
0118 
0119 /*
0120  * fbvga device driver CLOSE entry point
0121  */
0122 rtems_device_driver frame_buffer_close(
0123   rtems_device_major_number  major,
0124   rtems_device_minor_number  minor,
0125   void                      *arg
0126 )
0127 {
0128   _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
0129   /* restore previous state.  for VGA this means return to text mode.
0130    * leave out if graphics hardware has been initialized in
0131    * frame_buffer_initialize() */
0132   ega_hwterm();
0133   printk( "FBVGA close called.\n" );
0134   return RTEMS_SUCCESSFUL;
0135 
0136 /*
0137  * fbvga device driver READ entry point.
0138  */
0139 rtems_device_driver frame_buffer_read(
0140   rtems_device_major_number  major,
0141   rtems_device_minor_number  minor,
0142   void                      *arg
0143 )
0144 {
0145   rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
0146   rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
0147   memcpy(rw_args->buffer, (const void *) (fb_fix.smem_start + rw_args->offset), rw_args->bytes_moved);
0148   return RTEMS_SUCCESSFUL;
0149 }
0150 
0151 /*
0152  * frame_buffer device driver WRITE entry point.
0153  */
0154 rtems_device_driver frame_buffer_write(
0155   rtems_device_major_number  major,
0156   rtems_device_minor_number  minor,
0157   void                      *arg
0158 )
0159 {
0160   rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
0161   rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
0162   memcpy( (void *) (fb_fix.smem_start + rw_args->offset), rw_args->buffer, rw_args->bytes_moved);
0163   return RTEMS_SUCCESSFUL;
0164 }
0165 
0166 static int get_fix_screen_info( struct fb_fix_screeninfo *info )
0167 {
0168   *info = fb_fix;
0169   return 0;
0170 }
0171 
0172 static int get_var_screen_info( struct fb_var_screeninfo *info )
0173 {
0174   *info =  fb_var;
0175   return 0;
0176 }
0177 
0178 static int get_palette( struct fb_cmap *cmap )
0179 {
0180   uint32_t i;
0181 
0182   if ( cmap->start + cmap->len >= 16 )
0183     return 1;
0184 
0185   for( i = 0; i < cmap->len; i++ ) {
0186     cmap->red[ cmap->start + i ]   = red16[ cmap->start + i ];
0187     cmap->green[ cmap->start + i ] = green16[ cmap->start + i ];
0188     cmap->blue[ cmap->start + i ]  = blue16[ cmap->start + i ];
0189   }
0190   return 0;
0191 }
0192 
0193 static int set_palette( struct fb_cmap *cmap )
0194 {
0195   uint32_t i;
0196 
0197   if ( cmap->start + cmap->len >= 16 )
0198     return 1;
0199 
0200   for( i = 0; i < cmap->len; i++ ) {
0201     red16[ cmap->start + i ] = cmap->red[ cmap->start + i ];
0202     green16[ cmap->start + i ] = cmap->green[ cmap->start + i ];
0203     blue16[ cmap->start + i ] = cmap->blue[ cmap->start + i ];
0204   }
0205   return 0;
0206 }
0207 
0208 /*
0209  * IOCTL entry point -- This method is called to carry
0210  * all services of this interface.
0211  */
0212 rtems_device_driver frame_buffer_control(
0213   rtems_device_major_number  major,
0214   rtems_device_minor_number  minor,
0215   void                      *arg
0216 )
0217 {
0218   rtems_libio_ioctl_args_t *args = arg;
0219 
0220   printk( "FBVGA ioctl called, cmd=%x\n", args->command  );
0221 
0222   switch( args->command ) {
0223     case FBIOGET_FSCREENINFO:
0224       args->ioctl_return =  get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer );
0225       break;
0226     case FBIOGET_VSCREENINFO:
0227       args->ioctl_return =  get_var_screen_info( ( struct fb_var_screeninfo * ) args->buffer );
0228       break;
0229     case FBIOPUT_VSCREENINFO:
0230       /* not implemented yet*/
0231       args->ioctl_return = -1;
0232       return RTEMS_UNSATISFIED;
0233     case FBIOGETCMAP:
0234       args->ioctl_return =  get_palette( ( struct fb_cmap * ) args->buffer );
0235       break;
0236     case FBIOPUTCMAP:
0237       args->ioctl_return =  set_palette( ( struct fb_cmap * ) args->buffer );
0238       break;
0239 
0240     default:
0241      args->ioctl_return = 0;
0242      break;
0243   }
0244   return RTEMS_SUCCESSFUL;
0245 }