[3cbb63a] | 1 | /* |
---|
[c6fda81] | 2 | * Copyright (c) 2000 - Rosimildo da Silva ( rdasilva@connecttel.com ) |
---|
| 3 | * |
---|
| 4 | * MODULE DESCRIPTION: |
---|
[573e3b2] | 5 | * This module implements FB driver for "Bare VGA". It uses the |
---|
| 6 | * routines for "bare hardware" found in vgainit.c. |
---|
[c6fda81] | 7 | * |
---|
| 8 | */ |
---|
[3cbb63a] | 9 | |
---|
| 10 | #include <stdlib.h> |
---|
| 11 | #include <stdio.h> |
---|
| 12 | #include <errno.h> |
---|
| 13 | #include <sys/types.h> |
---|
[573e3b2] | 14 | #include <pthread.h> |
---|
[3cbb63a] | 15 | |
---|
| 16 | #include <bsp.h> |
---|
[6daada6] | 17 | #include <bsp/irq.h> |
---|
[3cbb63a] | 18 | #include <rtems/libio.h> |
---|
| 19 | |
---|
[71abba7] | 20 | #include <rtems/fb.h> |
---|
[61af4b0b] | 21 | #include <rtems/framebuffer.h> |
---|
[3cbb63a] | 22 | |
---|
[573e3b2] | 23 | /* these routines are defined in vgainit.c.*/ |
---|
[3cbb63a] | 24 | extern void ega_hwinit( void ); |
---|
| 25 | extern void ega_hwterm( void ); |
---|
| 26 | |
---|
[573e3b2] | 27 | /* mutex attribure */ |
---|
| 28 | pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; |
---|
| 29 | |
---|
[3cbb63a] | 30 | /* screen information for the VGA driver */ |
---|
[cd62f7a] | 31 | static struct fb_var_screeninfo fb_var = |
---|
[3cbb63a] | 32 | { |
---|
[83987a5] | 33 | .xres = 640, |
---|
| 34 | .yres = 480, |
---|
| 35 | .bits_per_pixel = 4 |
---|
[cd62f7a] | 36 | }; |
---|
| 37 | |
---|
| 38 | static struct fb_fix_screeninfo fb_fix = |
---|
| 39 | { |
---|
[83987a5] | 40 | .smem_start = (volatile char *)0xA0000, /* buffer pointer */ |
---|
| 41 | .smem_len = 0x10000, /* buffer size */ |
---|
| 42 | .type = FB_TYPE_VGA_PLANES, /* type of dsplay */ |
---|
| 43 | .visual = FB_VISUAL_PSEUDOCOLOR, /* color scheme used */ |
---|
| 44 | .line_length = 80 /* chars per line */ |
---|
[3cbb63a] | 45 | }; |
---|
| 46 | |
---|
[573e3b2] | 47 | |
---|
[40d5b64b] | 48 | static uint16_t red16[] = { |
---|
[83987a5] | 49 | 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa, |
---|
| 50 | 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff |
---|
[3cbb63a] | 51 | }; |
---|
[40d5b64b] | 52 | static uint16_t green16[] = { |
---|
[83987a5] | 53 | 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa, |
---|
| 54 | 0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff |
---|
[3cbb63a] | 55 | }; |
---|
[40d5b64b] | 56 | static uint16_t blue16[] = { |
---|
[83987a5] | 57 | 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, |
---|
| 58 | 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff |
---|
[3cbb63a] | 59 | }; |
---|
| 60 | |
---|
[573e3b2] | 61 | /* Functionality to support multiple VGA frame buffers can be added easily, |
---|
| 62 | * but is not supported at this moment because there is no need for two or |
---|
| 63 | * more "classic" VGA adapters. Multiple frame buffer drivers may be |
---|
| 64 | * implemented and If we had implement it they would be named as "/dev/fb0", |
---|
| 65 | * "/dev/fb1", "/dev/fb2" and so on. |
---|
| 66 | */ |
---|
[3cbb63a] | 67 | /* |
---|
| 68 | * fbvga device driver INITIALIZE entry point. |
---|
| 69 | */ |
---|
[83987a5] | 70 | rtems_device_driver frame_buffer_initialize( |
---|
| 71 | rtems_device_major_number major, |
---|
| 72 | rtems_device_minor_number minor, |
---|
| 73 | void *arg |
---|
| 74 | ) |
---|
[3cbb63a] | 75 | { |
---|
[83987a5] | 76 | rtems_status_code status; |
---|
[3cbb63a] | 77 | |
---|
| 78 | printk( "FBVGA -- driver initializing..\n" ); |
---|
[83987a5] | 79 | |
---|
[3cbb63a] | 80 | /* |
---|
| 81 | * Register the device |
---|
| 82 | */ |
---|
[311ba73] | 83 | status = rtems_io_register_name (FRAMEBUFFER_DEVICE_0_NAME, major, 0); |
---|
[83987a5] | 84 | if (status != RTEMS_SUCCESSFUL) { |
---|
[311ba73] | 85 | printk("Error registering " FRAMEBUFFER_DEVICE_0_NAME |
---|
| 86 | " FBVGA framebuffer device!\n"); |
---|
[83987a5] | 87 | rtems_fatal_error_occurred( status ); |
---|
[3cbb63a] | 88 | } |
---|
[359e537] | 89 | |
---|
[3cbb63a] | 90 | return RTEMS_SUCCESSFUL; |
---|
| 91 | } |
---|
| 92 | |
---|
| 93 | /* |
---|
| 94 | * fbvga device driver OPEN entry point |
---|
| 95 | */ |
---|
[83987a5] | 96 | rtems_device_driver frame_buffer_open( |
---|
| 97 | rtems_device_major_number major, |
---|
| 98 | rtems_device_minor_number minor, |
---|
| 99 | void *arg |
---|
| 100 | ) |
---|
[3cbb63a] | 101 | { |
---|
[573e3b2] | 102 | if (pthread_mutex_trylock(&mutex)== 0){ |
---|
| 103 | /* restore previous state. for VGA this means return to text mode. |
---|
| 104 | * leave out if graphics hardware has been initialized in |
---|
[359e537] | 105 | * frame_buffer_initialize() |
---|
[573e3b2] | 106 | */ |
---|
| 107 | ega_hwinit(); |
---|
[359e537] | 108 | printk( "FBVGA open called.\n" ); |
---|
[573e3b2] | 109 | return RTEMS_SUCCESSFUL; |
---|
| 110 | } |
---|
[359e537] | 111 | |
---|
[573e3b2] | 112 | return RTEMS_UNSATISFIED; |
---|
[3cbb63a] | 113 | } |
---|
| 114 | |
---|
| 115 | /* |
---|
| 116 | * fbvga device driver CLOSE entry point |
---|
| 117 | */ |
---|
[83987a5] | 118 | rtems_device_driver frame_buffer_close( |
---|
| 119 | rtems_device_major_number major, |
---|
| 120 | rtems_device_minor_number minor, |
---|
| 121 | void *arg |
---|
| 122 | ) |
---|
[3cbb63a] | 123 | { |
---|
[573e3b2] | 124 | if (pthread_mutex_unlock(&mutex) == 0){ |
---|
| 125 | /* restore previous state. for VGA this means return to text mode. |
---|
| 126 | * leave out if graphics hardware has been initialized in |
---|
| 127 | * frame_buffer_initialize() */ |
---|
| 128 | ega_hwterm(); |
---|
| 129 | printk( "FBVGA close called.\n" ); |
---|
| 130 | return RTEMS_SUCCESSFUL; |
---|
| 131 | } |
---|
[83987a5] | 132 | |
---|
[573e3b2] | 133 | return RTEMS_UNSATISFIED; |
---|
[3cbb63a] | 134 | } |
---|
| 135 | |
---|
| 136 | /* |
---|
| 137 | * fbvga device driver READ entry point. |
---|
| 138 | */ |
---|
[83987a5] | 139 | rtems_device_driver frame_buffer_read( |
---|
| 140 | rtems_device_major_number major, |
---|
| 141 | rtems_device_minor_number minor, |
---|
| 142 | void *arg |
---|
| 143 | ) |
---|
[3cbb63a] | 144 | { |
---|
| 145 | rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg; |
---|
[b8dfc88] | 146 | rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count; |
---|
| 147 | memcpy(rw_args->buffer, (const void *) (fb_fix.smem_start + rw_args->offset), rw_args->bytes_moved); |
---|
[359e537] | 148 | return RTEMS_SUCCESSFUL; |
---|
[3cbb63a] | 149 | } |
---|
[6128a4a] | 150 | |
---|
[3cbb63a] | 151 | /* |
---|
[83987a5] | 152 | * frame_buffer device driver WRITE entry point. |
---|
[3cbb63a] | 153 | */ |
---|
[83987a5] | 154 | rtems_device_driver frame_buffer_write( |
---|
| 155 | rtems_device_major_number major, |
---|
| 156 | rtems_device_minor_number minor, |
---|
| 157 | void *arg |
---|
| 158 | ) |
---|
[3cbb63a] | 159 | { |
---|
| 160 | rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg; |
---|
[b8dfc88] | 161 | rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count; |
---|
| 162 | memcpy( (void *) (fb_fix.smem_start + rw_args->offset), rw_args->buffer, rw_args->bytes_moved); |
---|
[359e537] | 163 | return RTEMS_SUCCESSFUL; |
---|
[3cbb63a] | 164 | } |
---|
| 165 | |
---|
[cd62f7a] | 166 | static int get_fix_screen_info( struct fb_fix_screeninfo *info ) |
---|
[3cbb63a] | 167 | { |
---|
[cd62f7a] | 168 | *info = fb_fix; |
---|
| 169 | return 0; |
---|
| 170 | } |
---|
| 171 | |
---|
| 172 | static int get_var_screen_info( struct fb_var_screeninfo *info ) |
---|
| 173 | { |
---|
[573e3b2] | 174 | *info = fb_var; |
---|
[3cbb63a] | 175 | return 0; |
---|
| 176 | } |
---|
| 177 | |
---|
| 178 | static int get_palette( struct fb_cmap *cmap ) |
---|
| 179 | { |
---|
[40d5b64b] | 180 | uint32_t i; |
---|
[3cbb63a] | 181 | |
---|
[83987a5] | 182 | if ( cmap->start + cmap->len >= 16 ) |
---|
| 183 | return 1; |
---|
[3cbb63a] | 184 | |
---|
[83987a5] | 185 | for( i = 0; i < cmap->len; i++ ) { |
---|
[3cbb63a] | 186 | cmap->red[ cmap->start + i ] = red16[ cmap->start + i ]; |
---|
| 187 | cmap->green[ cmap->start + i ] = green16[ cmap->start + i ]; |
---|
| 188 | cmap->blue[ cmap->start + i ] = blue16[ cmap->start + i ]; |
---|
| 189 | } |
---|
| 190 | return 0; |
---|
| 191 | } |
---|
| 192 | |
---|
| 193 | static int set_palette( struct fb_cmap *cmap ) |
---|
| 194 | { |
---|
[40d5b64b] | 195 | uint32_t i; |
---|
[3cbb63a] | 196 | |
---|
[83987a5] | 197 | if ( cmap->start + cmap->len >= 16 ) |
---|
| 198 | return 1; |
---|
[3cbb63a] | 199 | |
---|
[83987a5] | 200 | for( i = 0; i < cmap->len; i++ ) { |
---|
[3cbb63a] | 201 | red16[ cmap->start + i ] = cmap->red[ cmap->start + i ]; |
---|
| 202 | green16[ cmap->start + i ] = cmap->green[ cmap->start + i ]; |
---|
| 203 | blue16[ cmap->start + i ] = cmap->blue[ cmap->start + i ]; |
---|
| 204 | } |
---|
| 205 | return 0; |
---|
| 206 | } |
---|
| 207 | |
---|
| 208 | /* |
---|
| 209 | * IOCTL entry point -- This method is called to carry |
---|
| 210 | * all services of this interface. |
---|
| 211 | */ |
---|
[83987a5] | 212 | rtems_device_driver frame_buffer_control( |
---|
| 213 | rtems_device_major_number major, |
---|
| 214 | rtems_device_minor_number minor, |
---|
| 215 | void *arg |
---|
[3cbb63a] | 216 | ) |
---|
[6128a4a] | 217 | { |
---|
[83987a5] | 218 | rtems_libio_ioctl_args_t *args = arg; |
---|
| 219 | |
---|
| 220 | printk( "FBVGA ioctl called, cmd=%x\n", args->command ); |
---|
| 221 | |
---|
| 222 | switch( args->command ) { |
---|
| 223 | case FBIOGET_FSCREENINFO: |
---|
[573e3b2] | 224 | args->ioctl_return = get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer ); |
---|
[cd62f7a] | 225 | break; |
---|
[83987a5] | 226 | case FBIOGET_VSCREENINFO: |
---|
[573e3b2] | 227 | args->ioctl_return = get_var_screen_info( ( struct fb_var_screeninfo * ) args->buffer ); |
---|
[cd62f7a] | 228 | break; |
---|
[83987a5] | 229 | case FBIOPUT_VSCREENINFO: |
---|
[cd62f7a] | 230 | /* not implemented yet*/ |
---|
[573e3b2] | 231 | args->ioctl_return = -1; |
---|
| 232 | return RTEMS_UNSATISFIED; |
---|
[83987a5] | 233 | case FBIOGETCMAP: |
---|
[573e3b2] | 234 | args->ioctl_return = get_palette( ( struct fb_cmap * ) args->buffer ); |
---|
[3cbb63a] | 235 | break; |
---|
[83987a5] | 236 | case FBIOPUTCMAP: |
---|
[573e3b2] | 237 | args->ioctl_return = set_palette( ( struct fb_cmap * ) args->buffer ); |
---|
[3cbb63a] | 238 | break; |
---|
| 239 | |
---|
[83987a5] | 240 | default: |
---|
| 241 | args->ioctl_return = 0; |
---|
| 242 | break; |
---|
| 243 | } |
---|
| 244 | return RTEMS_SUCCESSFUL; |
---|
[3cbb63a] | 245 | } |
---|