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

4.115
Last change on this file since becbeda was becbeda, checked in by Joel Sherrill <joel.sherrill@…>, on 06/09/15 at 20:48:22

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

closes #2364.

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