source: rtems/c/src/lib/libbsp/i386/pc386/console/fb_cirrus.c @ c499856

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on Mar 20, 2014 at 9:10:47 PM

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 20.9 KB
Line 
1/*
2 *  FB driver for Cirrus GD5446 graphic hardware.
3 *  Tested to be compatible with QEMU GD5446 emulation but not on real HW.
4 *
5 *  Copyright (c) 2012 - Alexandru-Sever Horin (alex.sever.h@gmail.com).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.org/license/LICENSE.
10 *
11 *  The code is based on next information sources:
12 *    - CL-GD5446 Technical Reference Manual, 1996, Second Edition
13 *    - RTEMS fb_vga.c - Rosimildo da Silva ( rdasilva@connecttel.com )
14 *    - Cirrus xf86 driver - used as VGA hardware setup sequence documentation
15 */
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <errno.h>
20#include <sys/types.h>
21#include <pthread.h>
22
23#include <bsp.h>
24#include <bsp/irq.h>
25#include <rtems/libio.h>
26#include <rtems/pci.h>
27
28#include <rtems/fb.h>
29#include <rtems/framebuffer.h>
30
31/* mutex to limit driver to protect against multiple opens */
32static pthread_mutex_t cirrus_mutex = PTHREAD_MUTEX_INITIALIZER;
33
34/* screen information for the VGA driver
35 * standard structures
36 */
37static struct fb_var_screeninfo fb_var;
38static struct fb_fix_screeninfo fb_fix;
39
40#define CIRRUS_VENDOR_ID         0x1013
41#define CIRRUS_GD5446_DEVICE_ID  0x00b8
42
43typedef struct _DisplayModeRec {
44  struct _DisplayModeRec *prev;
45  struct _DisplayModeRec *next;
46  char *name;                 /* identifier for the mode */
47  int type;
48
49  /* These are the values that the user sees/provides */
50  int Clock;                  /* pixel clock freq (kHz) */
51  int HDisplay;               /* horizontal timing */
52  int HSyncStart;
53  int HSyncEnd;
54  int HTotal;
55  int HSkew;
56  int VDisplay;               /* vertical timing */
57  int VSyncStart;
58  int VSyncEnd;
59  int VTotal;
60  int VScan;
61  int Flags;
62
63  /* These are the values the hardware uses */
64  int ClockIndex;
65  int SynthClock;             /* Actual clock freq to
66   * be programmed  (kHz) */
67  int CrtcHDisplay;
68  int CrtcHBlankStart;
69  int CrtcHSyncStart;
70  int CrtcHSyncEnd;
71  int CrtcHBlankEnd;
72  int CrtcHTotal;
73  int CrtcHSkew;
74  int CrtcVDisplay;
75  int CrtcVBlankStart;
76  int CrtcVSyncStart;
77  int CrtcVSyncEnd;
78  int CrtcVBlankEnd;
79  int CrtcVTotal;
80  int CrtcHAdjusted;
81  int CrtcVAdjusted;
82  int PrivSize;
83  int32_t *Private;
84  int PrivFlags;
85
86  float HSync, VRefresh;
87} DisplayModeRec, *DisplayModePtr;
88
89static DisplayModeRec available_modes[] = {
90    {
91        .Clock      = 31500 ,
92        .HDisplay   = 640 ,
93        .HSyncStart = 664 ,
94        .HSyncEnd   = 704 ,
95        .HTotal     = 832 ,
96        .HSkew      = 0 ,
97        .VDisplay   = 480 ,       /* vertical timing */
98        .VSyncStart = 489 ,
99        .VSyncEnd   = 491 ,
100        .VTotal     = 520 ,
101        .VScan      = 0,
102        .Flags      = 0
103    },
104    {
105        .Clock      = 40000 ,
106        .HDisplay   = 800 ,
107        .HSyncStart = 840 ,
108        .HSyncEnd   = 968 ,
109        .HTotal     = 1056 ,
110        .HSkew      = 0 ,
111        .VDisplay   = 600 ,       /* vertical timing */
112        .VSyncStart = 601 ,
113        .VSyncEnd   = 605 ,
114        .VTotal     = 628 ,
115        .VScan      = 0,
116        .Flags      = 0
117    },
118};
119static DisplayModePtr active_mode;
120
121/* The display mode used for the board hardcoded in the following define
122 * Index in above structure
123 */
124#define CIRRUS_DISPLAY_MODE  0
125
126/* The display bytes per pixel used for the board hardcoded in the following define
127 * Index in above structure
128 */
129#define CIRRUS_DEFAULT_BPP 24
130
131/* cirrus board information */
132struct cirrus_board_str{
133  int    pci_bus;
134  int    pci_device;
135  int    pci_function;
136  void  *reg_base;
137};
138
139static struct cirrus_board_str cirrus_board_info;
140
141/*
142 * get information from the board
143 */
144static int
145cirrus_pci_read( struct cirrus_board_str *cirrus_board, uint32_t *mem_base, uint32_t *cirrus_register_base)
146{
147  int r;
148
149  r = pci_read_config_dword(
150      cirrus_board->pci_bus, cirrus_board->pci_device, cirrus_board->pci_function,
151      PCI_BASE_ADDRESS_0, mem_base);
152  if( r != PCIB_ERR_SUCCESS)
153    return RTEMS_UNSATISFIED;
154
155  r = pci_read_config_dword(
156      cirrus_board->pci_bus, cirrus_board->pci_device, cirrus_board->pci_function,
157      PCI_BASE_ADDRESS_1, cirrus_register_base);
158  if( r != PCIB_ERR_SUCCESS)
159    return RTEMS_UNSATISFIED;
160
161  *mem_base &= PCI_BASE_ADDRESS_MEM_MASK;
162  *cirrus_register_base     &= PCI_BASE_ADDRESS_MEM_MASK;
163
164  return RTEMS_SUCCESSFUL;
165}
166
167static inline int
168fb_cirrus_read_config_dword(
169    struct cirrus_board_str *fbst,
170    unsigned char where,
171    uint32_t     *pval)
172{
173  return pci_read_config_dword(
174      fbst->pci_bus, fbst->pci_device, fbst->pci_function,
175      where, pval);
176}
177
178static inline int
179fb_cirrus_write_config_dword(
180    struct cirrus_board_str *fbst,
181    unsigned char where,
182    uint32_t     val)
183{
184  return pci_write_config_dword(
185      fbst->pci_bus, fbst->pci_device, fbst->pci_function,
186      where, val);
187}
188
189static inline void
190fb_cirrus_write_reg8 (
191    const struct cirrus_board_str *fbst,
192    unsigned int reg,
193    unsigned int val)
194{
195  *(volatile uint8_t*)((char *)fbst->reg_base + reg) = val;
196}
197
198static inline unsigned int
199fb_cirrus_read_reg8 (
200    const struct cirrus_board_str *fbst,
201    unsigned int reg)
202{
203  return *(volatile uint8_t*)((char *)fbst->reg_base + reg);
204}
205
206#define SEQ_INDEX 0x04
207#define SEQ_DATA 0x05
208
209static inline void
210fb_cirrus_write_seq_reg (
211    const struct cirrus_board_str *fbst,
212    unsigned int reg,
213    unsigned int val)
214{
215  fb_cirrus_write_reg8(fbst, SEQ_INDEX, reg);
216  fb_cirrus_write_reg8(fbst, SEQ_DATA, val);
217}
218
219static inline unsigned int
220fb_cirrus_read_seq_reg (
221    const struct cirrus_board_str *fbst,
222    unsigned int reg)
223{
224  fb_cirrus_write_reg8(fbst, SEQ_INDEX, reg);
225  return fb_cirrus_read_reg8(fbst, SEQ_DATA);
226}
227
228#define CRT_INDEX 0x14
229#define CRT_DATA 0x15
230
231static inline void
232fb_cirrus_write_crt_reg (
233    const struct cirrus_board_str *fbst,
234    unsigned int reg,
235    unsigned int val)
236{
237  fb_cirrus_write_reg8(fbst, CRT_INDEX, reg);
238  fb_cirrus_write_reg8(fbst, CRT_DATA, val);
239}
240
241static inline unsigned int
242fb_cirrus_read_crt_reg (
243    const struct cirrus_board_str *fbst,
244    unsigned int reg)
245{
246  fb_cirrus_write_reg8(fbst, CRT_INDEX, reg);
247  return fb_cirrus_read_reg8(fbst, CRT_DATA);
248}
249
250#define GDC_INDEX 0x0E
251#define GDC_DATA 0x0F
252
253static inline void
254fb_cirrus_write_gdc_reg (
255    const struct cirrus_board_str *fbst,
256    unsigned int reg,
257    unsigned int val)
258{
259  fb_cirrus_write_reg8(fbst, GDC_INDEX, reg);
260  fb_cirrus_write_reg8(fbst, GDC_DATA, val);
261}
262
263static inline unsigned int
264fb_cirrus_read_gdc_reg (
265    const struct cirrus_board_str *fbst,
266    unsigned int reg)
267{
268  fb_cirrus_write_reg8(fbst, GDC_INDEX, reg);
269  return fb_cirrus_read_reg8(fbst, GDC_DATA);
270}
271
272#define VGA_DAC_MASK 0x06
273
274static inline void
275fb_cirrus_write_hdr_reg (
276    const struct cirrus_board_str *fbst,
277    unsigned int val)
278{
279  volatile unsigned int dummy __attribute__((unused));
280  dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
281  dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
282  dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
283  dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
284  fb_cirrus_write_reg8(fbst, VGA_DAC_MASK, val);
285}
286
287/* Functionality to support multiple VGA frame buffers can be added easily,
288 * but is not supported at this moment because there is no need for two or
289 * more "classic" VGA adapters.  Multiple frame buffer drivers may be
290 * implemented and If we had implement it they would be named as "/dev/fb0",
291 * "/dev/fb1", "/dev/fb2" and so on.
292 */
293
294/*
295 * fb_cirrus device driver INITIALIZE entry point.
296 */
297rtems_device_driver
298frame_buffer_initialize(
299    rtems_device_major_number  major,
300    rtems_device_minor_number  minor,
301    void                      *arg
302)
303{
304  rtems_status_code status;
305  int res;
306
307  printk( "FB_CIRRUS -- driver initializing..\n" );
308
309  res = pci_find_device(
310      CIRRUS_VENDOR_ID,
311      CIRRUS_GD5446_DEVICE_ID,
312      minor,
313      &cirrus_board_info.pci_bus,
314      &cirrus_board_info.pci_device,
315      &cirrus_board_info.pci_function
316  );
317
318  if ( res != PCIB_ERR_SUCCESS ) {
319      printk( "FB_CIRRUS initialize -- device not found\n" );
320
321      return RTEMS_UNSATISFIED;
322  }
323  else{
324      printk( "FB_CIRRUS -- driver initializing..\n" );
325      /*
326       * Register the device
327       */
328      status = rtems_io_register_name (FRAMEBUFFER_DEVICE_0_NAME, major, 0);
329      if (status != RTEMS_SUCCESSFUL) {
330          printk("Error registering " FRAMEBUFFER_DEVICE_0_NAME
331                 " FB_CIRRUS framebuffer device!\n");
332          rtems_fatal_error_occurred( status );
333      }
334
335      return RTEMS_SUCCESSFUL;
336  }
337}
338
339/*
340 * This function is used to initialize the Start Address - the first
341 * displayed location in the video memory.
342 * Usually mandatory
343 */
344static void
345cirrus_adjust_frame( struct cirrus_board_str *board, int x, int y)
346{
347  uint32_t Base;
348  uint8_t tmp;
349
350  Base = ((y * fb_var.xres + x) >> 3);
351  if (fb_var.bits_per_pixel != 1)
352    Base *= (fb_var.bits_per_pixel >> 2);
353
354  printk("FB_CIRRUS: cirrus_adjust_frame %d %d >>> %d %x\n", x, y, Base, Base);
355
356  if ((Base & ~0x000FFFFF) != 0) {
357      printk("FB_CIRRUS: Internal error: cirrus_adjust_frame: cannot handle overflow\n");
358      return;
359  }
360
361  fb_cirrus_write_crt_reg( board,  0x0C, (Base >> 8) & 0xff);
362  fb_cirrus_write_crt_reg( board,  0x0D, Base & 0xff);
363
364  tmp = fb_cirrus_read_crt_reg( board,  0x1B);
365  tmp &= 0xF2;
366  tmp |= (Base >> 16) & 0x01;
367  tmp |= (Base >> 15) & 0x0C;
368  fb_cirrus_write_crt_reg( board,  0x1B, tmp);
369
370  tmp = fb_cirrus_read_crt_reg( board, 0x1D);
371  tmp &= 0x7F;
372  tmp |= (Base >> 12) & 0x80;
373  fb_cirrus_write_crt_reg( board,  0x1D, tmp);
374}
375
376static int
377cirrus_set_mode(DisplayModePtr mode)
378{
379  int depthcode = fb_var.bits_per_pixel;;
380  int width;
381  int HDiv2 = 0, VDiv2 = 0;
382  const struct cirrus_board_str *cirrus_board_ptr = &cirrus_board_info;
383  int temp;
384  int hdr = -1;
385
386  printk("FB_CIRRUS: mode  %d bpp, %d Hz    %d %d %d %d   %d %d %d %d\n",
387      fb_var.bits_per_pixel,
388      mode->Clock,
389      mode->HDisplay,
390      mode->HSyncStart,
391      mode->HSyncEnd,
392      mode->HTotal,
393      mode->VDisplay,
394      mode->VSyncStart,
395      mode->VSyncEnd,
396      mode->VTotal);
397
398  if ( mode->Clock >  85500 ) {
399      /* The actual DAC register value is set later. */
400      /* The CRTC is clocked at VCLK / 2, so we must half the */
401      /* horizontal timings. */
402      if (!mode->CrtcHAdjusted) {
403          mode->HDisplay >>= 1;
404          mode->HSyncStart >>= 1;
405          mode->HTotal >>= 1;
406          mode->HSyncEnd >>= 1;
407          mode->SynthClock >>= 1;
408          mode->CrtcHAdjusted = TRUE;
409      }
410      depthcode += 64;
411      HDiv2 = 1;
412  }
413  if (mode->VTotal >= 1024 ) {
414      /* For non-interlaced vertical timing >= 1024, the vertical timings */
415      /* are divided by 2 and VGA CRTC 0x17 bit 2  is set. */
416      if (!mode->CrtcVAdjusted) {
417          mode->VDisplay >>= 1;
418          mode->VSyncStart >>= 1;
419          mode->VSyncEnd >>= 1;
420          mode->VTotal >>= 1;
421          mode->CrtcVAdjusted = TRUE;
422      }
423      VDiv2 = 1;
424  }
425
426  /****************************************************
427   * Sequential registers
428   */
429  fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x00, 0x00);
430  fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x01, 0x01);
431  fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x02, 0x0F);
432  fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x03, 0x00);
433  fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x04, 0x0E);
434
435  /****************************************************
436   * CRTC Controller Registers
437   */
438  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x00, (mode->HTotal >> 3) - 5 );
439  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x01, (mode->HDisplay >> 3) - 1);
440  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x02, (mode->HSyncStart >> 3) - 1);
441  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x03, ((mode->HSyncEnd >> 3) & 0x1F) | 0x80);
442  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x04, (mode->HSyncStart >> 3));
443  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x05,
444      (((mode->HSyncEnd >> 3) & 0x20 ) << 2 )
445      | (((mode->HSyncEnd >> 3)) & 0x1F));
446  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x06, (mode->VTotal - 2) & 0xFF);
447  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x07,
448      (((mode->VTotal -2) & 0x100) >> 8 )
449      | (((mode->VDisplay -1) & 0x100) >> 7 )
450      | ((mode->VSyncStart & 0x100) >> 6 )
451      | (((mode->VSyncStart) & 0x100) >> 5 )
452      | 0x10
453      | (((mode->VTotal -2) & 0x200)   >> 4 )
454      | (((mode->VDisplay -1) & 0x200) >> 3 )
455      | ((mode->VSyncStart & 0x200) >> 2 ));
456  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x08, 0x00);
457  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x09, ((mode->VSyncStart & 0x200) >>4) | 0x40);
458  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0A, 0x00);
459  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0B, 0x00);
460  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0C, 0x00);
461  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0D, 0x00);
462  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0E, 0x00);
463  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0F, 0x00);
464  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x10, mode->VSyncStart & 0xFF);
465  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x11, (mode->VSyncEnd & 0x0F) | 0x20);
466  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x12, (mode->VDisplay -1) & 0xFF);
467  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x13, 0x00);  /* no interlace */
468  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x14, 0x00);
469  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x15, mode->VSyncStart & 0xFF);
470  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x16, (mode->VSyncStart +1) & 0xFF);
471
472  temp = 0xAF;
473  if(VDiv2)
474    temp |= 0x04;
475  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x17, temp);
476
477  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x18, 0xFF);
478
479  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x1A ,
480      (((mode->HTotal >> 3) & 0xC0 ) >> 2)
481      | (((mode->VTotal - 2) & 0x300 ) >> 2));
482
483  width = fb_fix.line_length >> 3;
484  if (fb_var.bits_per_pixel == 1)
485    width <<= 2;
486  if(width >= 0xFF)
487    printk("FB_CIRRUS: Warning line size over the limit ... reduce bpp or width resolution");
488  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x13,  width);
489  /* Offset extension (see CR13) */
490  temp = fb_cirrus_read_crt_reg( cirrus_board_ptr, 0x1B);
491  temp &= 0xAF;
492  temp |= (width >> (3+4)) & 0x10;
493  temp |= (width >> (3+3)) & 0x40;
494  temp |= 0x22;
495  fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x1B,  temp);
496
497  /****************************************************
498   * Sequential register
499   * Enable linear mode and high-res packed pixel mode
500   */
501  temp = fb_cirrus_read_seq_reg( cirrus_board_ptr, 0x07);
502  temp &= 0xe0;
503  switch (depthcode) {
504  case 1:
505  case 4:
506    temp |= 0x10;
507    break;
508  case 8:
509    temp |= 0x11;
510    break;
511  case 64+8:
512  temp |= 0x17;
513  break;
514  case 15:
515    temp |= 0x17;
516    hdr = 0xC0; /* 5:5:5 Sierra */
517    break;
518  case 16:
519    temp |= 0x17;
520    hdr = 0xC1; /* 5:6:5 XGA mode */
521    break;
522  case 24:
523    temp |= 0x15;
524    hdr = 0xC5; /* 8:8:8 16M colors */
525    break;
526  case 32:
527    temp |= 0x19;
528    hdr = 0xC5; /* 8:8:8 16M colors */
529    break;
530  default:
531    printk("FB_CIRRUS: Cannot Initialize display to requested mode\n");
532    printk("FB_CIRRUS: returning RTEMS_UNSATISFIED on depthcode %d\n", depthcode);
533    return RTEMS_UNSATISFIED;
534  }
535  fb_cirrus_write_seq_reg( cirrus_board_ptr, 0x07, temp);
536  /* this just set  packed pixel mode with according bpp */
537
538  /****************************************************
539   * HDR Register
540   */
541  if(hdr > 0)
542    fb_cirrus_write_hdr_reg( cirrus_board_ptr, hdr);
543
544  /****************************************************
545   * Graphic Data Controller Registers
546   */
547  temp = fb_cirrus_read_gdc_reg( cirrus_board_ptr, 0x12);
548  if (HDiv2)
549    temp |= 0x20;
550  else
551    temp &= ~0x20;
552  fb_cirrus_write_gdc_reg( cirrus_board_ptr, 0x12, temp);
553
554  /* Enable high-color modes */
555  fb_cirrus_write_gdc_reg(cirrus_board_ptr, 0x05, 0x40);
556
557  /* VGA graphics mode */
558  fb_cirrus_write_gdc_reg(cirrus_board_ptr, 0x06, 0x01);
559
560  return TRUE;
561}
562
563static void
564cirrus_prepare_mode( void )
565{
566
567  active_mode = &available_modes[CIRRUS_DISPLAY_MODE];
568
569  fb_var.bits_per_pixel = CIRRUS_DEFAULT_BPP;
570
571  fb_var.xres  = active_mode->HDisplay;
572  fb_var.yres  = active_mode->VDisplay;
573
574  fb_fix.line_length = (fb_var.xres * fb_var.bits_per_pixel + 7) / 8;
575
576  fb_fix.type   = FB_TYPE_PACKED_PIXELS;
577  fb_fix.visual = FB_VISUAL_TRUECOLOR;
578
579}
580
581/*
582 * fb_cirrus device driver OPEN entry point
583 */
584rtems_device_driver
585frame_buffer_open(
586    rtems_device_major_number  major,
587    rtems_device_minor_number  minor,
588    void                      *arg
589)
590{
591  int r;
592  uint32_t smem_start, regs_start;
593
594  if (pthread_mutex_trylock(&cirrus_mutex)!= 0){
595      printk( "FB_CIRRUS could not lock cirrus_mutex\n" );
596
597      return RTEMS_UNSATISFIED;
598  }
599
600  r = cirrus_pci_read(&cirrus_board_info, &smem_start, &regs_start);
601  if ( r == RTEMS_UNSATISFIED )
602    return RTEMS_UNSATISFIED;
603
604  fb_fix.smem_start  = (volatile char *)smem_start;
605  fb_fix.smem_len    = 0x1000000;
606  cirrus_board_info.reg_base = (void *)regs_start;
607
608  cirrus_prepare_mode();
609
610  cirrus_set_mode( active_mode );
611
612  cirrus_adjust_frame( &cirrus_board_info, 0, 0);
613
614  if (1) {
615      uint32_t pixmask;
616      int x, y;
617
618      if(fb_var.bits_per_pixel == 32)
619        pixmask = 0xffffff;
620      else
621        pixmask = (1 << fb_var.bits_per_pixel) - 1;
622
623      printk("FB_CIRRUS: mode set, test patter output\n");
624
625      for(y = 0; y < fb_var.yres; y++) {
626          for(x = 0; x < fb_var.xres; x++) {
627              uint32_t color;
628              char *addr = (char *)fb_fix.smem_start;
629              addr += y * fb_fix.line_length;
630              addr += x * fb_var.bits_per_pixel / 8;
631              color = x & 1 ? 0 : y & 1 ? pixmask & 0x000ff00f : pixmask;
632              if(y == fb_var.yres - 1) {
633                  if((x > 0) && (x < fb_var.xres-1))
634                    color = pixmask & 0x00555555;
635              }
636              switch (fb_var.bits_per_pixel) {
637              case 8:  *(volatile uint8_t*) addr = color;
638              break;
639              case 16: *(volatile uint16_t*) addr = color;
640              break;
641              case 24: *(volatile uint32_t*) addr =
642                  (*(volatile uint32_t*) addr & 0xff000000) | color;
643              break;
644              case 32: *(volatile uint32_t*) addr = color;
645              break;
646              }
647          }
648      }
649  }
650
651  return RTEMS_SUCCESSFUL;
652
653}
654
655/*
656 * fb_cirrus device driver CLOSE entry point
657 */
658rtems_device_driver
659frame_buffer_close(
660    rtems_device_major_number  major,
661    rtems_device_minor_number  minor,
662    void                      *arg
663)
664{
665  if (pthread_mutex_unlock(&cirrus_mutex) == 0){
666      /* restore previous state.  for VGA this means return to text mode.
667       * leave out if graphics hardware has been initialized in
668       * frame_buffer_initialize() */
669
670      /* VGA text mode */
671      fb_cirrus_write_gdc_reg(&cirrus_board_info, 0x06, 0x00);
672
673      printk( "FB_CIRRUS: close called.\n" );
674      return RTEMS_SUCCESSFUL;
675  }
676
677  return RTEMS_UNSATISFIED;
678}
679
680/*
681 * fb_cirrus device driver READ entry point.
682 */
683rtems_device_driver
684frame_buffer_read(
685    rtems_device_major_number  major,
686    rtems_device_minor_number  minor,
687    void                      *arg
688)
689{
690  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
691  rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
692  memcpy(rw_args->buffer, (const void *) (fb_fix.smem_start + rw_args->offset), rw_args->bytes_moved);
693  return RTEMS_SUCCESSFUL;
694}
695
696/*
697 * frame_buffer device driver WRITE entry point.
698 */
699rtems_device_driver
700frame_buffer_write(
701    rtems_device_major_number  major,
702    rtems_device_minor_number  minor,
703    void                      *arg
704)
705{
706  rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
707  rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
708  memcpy( (void *) (fb_fix.smem_start + rw_args->offset), rw_args->buffer, rw_args->bytes_moved);
709  return RTEMS_SUCCESSFUL;
710}
711
712static int
713get_fix_screen_info( struct fb_fix_screeninfo *info )
714{
715  *info = fb_fix;
716  return 0;
717}
718
719static int
720get_var_screen_info( struct fb_var_screeninfo *info )
721{
722  *info =  fb_var;
723  return 0;
724}
725
726/*
727 * IOCTL entry point -- This method is called to carry
728 * all services of this interface.
729 */
730rtems_device_driver
731frame_buffer_control(
732    rtems_device_major_number  major,
733    rtems_device_minor_number  minor,
734    void                      *arg
735)
736{
737  rtems_libio_ioctl_args_t *args = arg;
738
739  printk( "FB_CIRRUS ioctl called, cmd=%x\n", args->command  );
740
741  switch( args->command ) {
742  case FBIOGET_FSCREENINFO:
743    args->ioctl_return =  get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer );
744    break;
745  case FBIOGET_VSCREENINFO:
746    args->ioctl_return =  get_var_screen_info( ( struct fb_var_screeninfo * ) args->buffer );
747    break;
748  case FBIOPUT_VSCREENINFO:
749    /* not implemented yet */
750    args->ioctl_return = -1;
751    return RTEMS_UNSATISFIED;
752  case FBIOGETCMAP:
753    /* no palette - truecolor mode */
754    args->ioctl_return = -1;
755    return RTEMS_UNSATISFIED;
756  case FBIOPUTCMAP:
757    /* no palette - truecolor mode */
758    args->ioctl_return = -1;
759    return RTEMS_UNSATISFIED;
760  default:
761    args->ioctl_return = 0;
762    break;
763  }
764  return RTEMS_SUCCESSFUL;
765}
Note: See TracBrowser for help on using the repository browser.