source: rtems/c/src/lib/libbsp/i386/pc386/console/fb_vga.c @ becbeda

4.115
Last change on this file since becbeda was becbeda, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 9, 2015 at 8:48:22 PM

pc386/console/fb*.c: Use atomics to avoid dependency on pthreads

closes #2364.

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