File indexing completed on 2025-05-11 08:23:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <stdlib.h>
0018 #include <stdio.h>
0019 #include <errno.h>
0020 #include <sys/types.h>
0021 #include <pthread.h>
0022
0023 #include <bsp.h>
0024 #include <bsp/irq.h>
0025 #include <rtems/libio.h>
0026 #include <rtems/pci.h>
0027
0028 #include <rtems/fb.h>
0029 #include <rtems/framebuffer.h>
0030 #include <rtems/score/atomic.h>
0031
0032
0033 static Atomic_Flag driver_mutex;
0034
0035
0036
0037
0038 static struct fb_var_screeninfo fb_var;
0039 static struct fb_fix_screeninfo fb_fix;
0040
0041 #define CIRRUS_VENDOR_ID 0x1013
0042 #define CIRRUS_GD5446_DEVICE_ID 0x00b8
0043
0044 typedef struct _DisplayModeRec {
0045 struct _DisplayModeRec *prev;
0046 struct _DisplayModeRec *next;
0047 char *name;
0048 int type;
0049
0050
0051 int Clock;
0052 int HDisplay;
0053 int HSyncStart;
0054 int HSyncEnd;
0055 int HTotal;
0056 int HSkew;
0057 int VDisplay;
0058 int VSyncStart;
0059 int VSyncEnd;
0060 int VTotal;
0061 int VScan;
0062 int Flags;
0063
0064
0065 int ClockIndex;
0066 int SynthClock;
0067
0068 int CrtcHDisplay;
0069 int CrtcHBlankStart;
0070 int CrtcHSyncStart;
0071 int CrtcHSyncEnd;
0072 int CrtcHBlankEnd;
0073 int CrtcHTotal;
0074 int CrtcHSkew;
0075 int CrtcVDisplay;
0076 int CrtcVBlankStart;
0077 int CrtcVSyncStart;
0078 int CrtcVSyncEnd;
0079 int CrtcVBlankEnd;
0080 int CrtcVTotal;
0081 int CrtcHAdjusted;
0082 int CrtcVAdjusted;
0083 int PrivSize;
0084 int32_t *Private;
0085 int PrivFlags;
0086
0087 float HSync, VRefresh;
0088 } DisplayModeRec, *DisplayModePtr;
0089
0090 static DisplayModeRec available_modes[] = {
0091 {
0092 .Clock = 31500 ,
0093 .HDisplay = 640 ,
0094 .HSyncStart = 664 ,
0095 .HSyncEnd = 704 ,
0096 .HTotal = 832 ,
0097 .HSkew = 0 ,
0098 .VDisplay = 480 ,
0099 .VSyncStart = 489 ,
0100 .VSyncEnd = 491 ,
0101 .VTotal = 520 ,
0102 .VScan = 0,
0103 .Flags = 0
0104 },
0105 {
0106 .Clock = 40000 ,
0107 .HDisplay = 800 ,
0108 .HSyncStart = 840 ,
0109 .HSyncEnd = 968 ,
0110 .HTotal = 1056 ,
0111 .HSkew = 0 ,
0112 .VDisplay = 600 ,
0113 .VSyncStart = 601 ,
0114 .VSyncEnd = 605 ,
0115 .VTotal = 628 ,
0116 .VScan = 0,
0117 .Flags = 0
0118 },
0119 };
0120 static DisplayModePtr active_mode;
0121
0122
0123
0124
0125 #define CIRRUS_DISPLAY_MODE 0
0126
0127
0128
0129
0130 #define CIRRUS_DEFAULT_BPP 24
0131
0132
0133 struct cirrus_board_str{
0134 int pci_bus;
0135 int pci_device;
0136 int pci_function;
0137 void *reg_base;
0138 };
0139
0140 static struct cirrus_board_str cirrus_board_info;
0141
0142
0143
0144
0145 static int
0146 cirrus_pci_read( struct cirrus_board_str *cirrus_board, uint32_t *mem_base, uint32_t *cirrus_register_base)
0147 {
0148 int r;
0149
0150 r = pci_read_config_dword(
0151 cirrus_board->pci_bus, cirrus_board->pci_device, cirrus_board->pci_function,
0152 PCI_BASE_ADDRESS_0, mem_base);
0153 if( r != PCIB_ERR_SUCCESS)
0154 return RTEMS_UNSATISFIED;
0155
0156 r = pci_read_config_dword(
0157 cirrus_board->pci_bus, cirrus_board->pci_device, cirrus_board->pci_function,
0158 PCI_BASE_ADDRESS_1, cirrus_register_base);
0159 if( r != PCIB_ERR_SUCCESS)
0160 return RTEMS_UNSATISFIED;
0161
0162 *mem_base &= PCI_BASE_ADDRESS_MEM_MASK;
0163 *cirrus_register_base &= PCI_BASE_ADDRESS_MEM_MASK;
0164
0165 return RTEMS_SUCCESSFUL;
0166 }
0167
0168 static inline int
0169 fb_cirrus_read_config_dword(
0170 struct cirrus_board_str *fbst,
0171 unsigned char where,
0172 uint32_t *pval)
0173 {
0174 return pci_read_config_dword(
0175 fbst->pci_bus, fbst->pci_device, fbst->pci_function,
0176 where, pval);
0177 }
0178
0179 static inline int
0180 fb_cirrus_write_config_dword(
0181 struct cirrus_board_str *fbst,
0182 unsigned char where,
0183 uint32_t val)
0184 {
0185 return pci_write_config_dword(
0186 fbst->pci_bus, fbst->pci_device, fbst->pci_function,
0187 where, val);
0188 }
0189
0190 static inline void
0191 fb_cirrus_write_reg8 (
0192 const struct cirrus_board_str *fbst,
0193 unsigned int reg,
0194 unsigned int val)
0195 {
0196 *(volatile uint8_t*)((char *)fbst->reg_base + reg) = val;
0197 }
0198
0199 static inline unsigned int
0200 fb_cirrus_read_reg8 (
0201 const struct cirrus_board_str *fbst,
0202 unsigned int reg)
0203 {
0204 return *(volatile uint8_t*)((char *)fbst->reg_base + reg);
0205 }
0206
0207 #define SEQ_INDEX 0x04
0208 #define SEQ_DATA 0x05
0209
0210 static inline void
0211 fb_cirrus_write_seq_reg (
0212 const struct cirrus_board_str *fbst,
0213 unsigned int reg,
0214 unsigned int val)
0215 {
0216 fb_cirrus_write_reg8(fbst, SEQ_INDEX, reg);
0217 fb_cirrus_write_reg8(fbst, SEQ_DATA, val);
0218 }
0219
0220 static inline unsigned int
0221 fb_cirrus_read_seq_reg (
0222 const struct cirrus_board_str *fbst,
0223 unsigned int reg)
0224 {
0225 fb_cirrus_write_reg8(fbst, SEQ_INDEX, reg);
0226 return fb_cirrus_read_reg8(fbst, SEQ_DATA);
0227 }
0228
0229 #define CRT_INDEX 0x14
0230 #define CRT_DATA 0x15
0231
0232 static inline void
0233 fb_cirrus_write_crt_reg (
0234 const struct cirrus_board_str *fbst,
0235 unsigned int reg,
0236 unsigned int val)
0237 {
0238 fb_cirrus_write_reg8(fbst, CRT_INDEX, reg);
0239 fb_cirrus_write_reg8(fbst, CRT_DATA, val);
0240 }
0241
0242 static inline unsigned int
0243 fb_cirrus_read_crt_reg (
0244 const struct cirrus_board_str *fbst,
0245 unsigned int reg)
0246 {
0247 fb_cirrus_write_reg8(fbst, CRT_INDEX, reg);
0248 return fb_cirrus_read_reg8(fbst, CRT_DATA);
0249 }
0250
0251 #define GDC_INDEX 0x0E
0252 #define GDC_DATA 0x0F
0253
0254 static inline void
0255 fb_cirrus_write_gdc_reg (
0256 const struct cirrus_board_str *fbst,
0257 unsigned int reg,
0258 unsigned int val)
0259 {
0260 fb_cirrus_write_reg8(fbst, GDC_INDEX, reg);
0261 fb_cirrus_write_reg8(fbst, GDC_DATA, val);
0262 }
0263
0264 static inline unsigned int
0265 fb_cirrus_read_gdc_reg (
0266 const struct cirrus_board_str *fbst,
0267 unsigned int reg)
0268 {
0269 fb_cirrus_write_reg8(fbst, GDC_INDEX, reg);
0270 return fb_cirrus_read_reg8(fbst, GDC_DATA);
0271 }
0272
0273 #define VGA_DAC_MASK 0x06
0274
0275 static inline void
0276 fb_cirrus_write_hdr_reg (
0277 const struct cirrus_board_str *fbst,
0278 unsigned int val)
0279 {
0280 volatile unsigned int dummy RTEMS_UNUSED;
0281 dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
0282 dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
0283 dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
0284 dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
0285 fb_cirrus_write_reg8(fbst, VGA_DAC_MASK, val);
0286 }
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298 rtems_device_driver
0299 frame_buffer_initialize(
0300 rtems_device_major_number major,
0301 rtems_device_minor_number minor,
0302 void *arg
0303 )
0304 {
0305 rtems_status_code status;
0306 int res;
0307
0308 printk( "FB_CIRRUS -- driver initializing..\n" );
0309
0310 res = pci_find_device(
0311 CIRRUS_VENDOR_ID,
0312 CIRRUS_GD5446_DEVICE_ID,
0313 minor,
0314 &cirrus_board_info.pci_bus,
0315 &cirrus_board_info.pci_device,
0316 &cirrus_board_info.pci_function
0317 );
0318
0319 if ( res != PCIB_ERR_SUCCESS ) {
0320 printk( "FB_CIRRUS initialize -- device not found\n" );
0321
0322 return RTEMS_UNSATISFIED;
0323 }
0324 else{
0325 printk( "FB_CIRRUS -- driver initializing..\n" );
0326
0327
0328
0329 status = rtems_io_register_name (FRAMEBUFFER_DEVICE_0_NAME, major, 0);
0330 if (status != RTEMS_SUCCESSFUL) {
0331 printk("Error registering " FRAMEBUFFER_DEVICE_0_NAME
0332 " FB_CIRRUS framebuffer device!\n");
0333 rtems_fatal_error_occurred( status );
0334 }
0335
0336 _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
0337
0338 return RTEMS_SUCCESSFUL;
0339 }
0340 }
0341
0342
0343
0344
0345
0346
0347 static void
0348 cirrus_adjust_frame( struct cirrus_board_str *board, int x, int y)
0349 {
0350 uint32_t Base;
0351 uint8_t tmp;
0352
0353 Base = ((y * fb_var.xres + x) >> 3);
0354 if (fb_var.bits_per_pixel != 1)
0355 Base *= (fb_var.bits_per_pixel >> 2);
0356
0357 printk("FB_CIRRUS: cirrus_adjust_frame %d %d >>> %d %x\n", x, y, Base, Base);
0358
0359 if ((Base & ~0x000FFFFF) != 0) {
0360 printk("FB_CIRRUS: Internal error: cirrus_adjust_frame: cannot handle overflow\n");
0361 return;
0362 }
0363
0364 fb_cirrus_write_crt_reg( board, 0x0C, (Base >> 8) & 0xff);
0365 fb_cirrus_write_crt_reg( board, 0x0D, Base & 0xff);
0366
0367 tmp = fb_cirrus_read_crt_reg( board, 0x1B);
0368 tmp &= 0xF2;
0369 tmp |= (Base >> 16) & 0x01;
0370 tmp |= (Base >> 15) & 0x0C;
0371 fb_cirrus_write_crt_reg( board, 0x1B, tmp);
0372
0373 tmp = fb_cirrus_read_crt_reg( board, 0x1D);
0374 tmp &= 0x7F;
0375 tmp |= (Base >> 12) & 0x80;
0376 fb_cirrus_write_crt_reg( board, 0x1D, tmp);
0377 }
0378
0379 static int
0380 cirrus_set_mode(DisplayModePtr mode)
0381 {
0382 int depthcode = fb_var.bits_per_pixel;;
0383 int width;
0384 int HDiv2 = 0, VDiv2 = 0;
0385 const struct cirrus_board_str *cirrus_board_ptr = &cirrus_board_info;
0386 int temp;
0387 int hdr = -1;
0388
0389 printk("FB_CIRRUS: mode %d bpp, %d Hz %d %d %d %d %d %d %d %d\n",
0390 fb_var.bits_per_pixel,
0391 mode->Clock,
0392 mode->HDisplay,
0393 mode->HSyncStart,
0394 mode->HSyncEnd,
0395 mode->HTotal,
0396 mode->VDisplay,
0397 mode->VSyncStart,
0398 mode->VSyncEnd,
0399 mode->VTotal);
0400
0401 if ( mode->Clock > 85500 ) {
0402
0403
0404
0405 if (!mode->CrtcHAdjusted) {
0406 mode->HDisplay >>= 1;
0407 mode->HSyncStart >>= 1;
0408 mode->HTotal >>= 1;
0409 mode->HSyncEnd >>= 1;
0410 mode->SynthClock >>= 1;
0411 mode->CrtcHAdjusted = TRUE;
0412 }
0413 depthcode += 64;
0414 HDiv2 = 1;
0415 }
0416 if (mode->VTotal >= 1024 ) {
0417
0418
0419 if (!mode->CrtcVAdjusted) {
0420 mode->VDisplay >>= 1;
0421 mode->VSyncStart >>= 1;
0422 mode->VSyncEnd >>= 1;
0423 mode->VTotal >>= 1;
0424 mode->CrtcVAdjusted = TRUE;
0425 }
0426 VDiv2 = 1;
0427 }
0428
0429
0430
0431
0432 fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x00, 0x00);
0433 fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x01, 0x01);
0434 fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x02, 0x0F);
0435 fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x03, 0x00);
0436 fb_cirrus_write_seq_reg(cirrus_board_ptr, 0x04, 0x0E);
0437
0438
0439
0440
0441 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x00, (mode->HTotal >> 3) - 5 );
0442 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x01, (mode->HDisplay >> 3) - 1);
0443 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x02, (mode->HSyncStart >> 3) - 1);
0444 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x03, ((mode->HSyncEnd >> 3) & 0x1F) | 0x80);
0445 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x04, (mode->HSyncStart >> 3));
0446 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x05,
0447 (((mode->HSyncEnd >> 3) & 0x20 ) << 2 )
0448 | (((mode->HSyncEnd >> 3)) & 0x1F));
0449 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x06, (mode->VTotal - 2) & 0xFF);
0450 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x07,
0451 (((mode->VTotal -2) & 0x100) >> 8 )
0452 | (((mode->VDisplay -1) & 0x100) >> 7 )
0453 | ((mode->VSyncStart & 0x100) >> 6 )
0454 | (((mode->VSyncStart) & 0x100) >> 5 )
0455 | 0x10
0456 | (((mode->VTotal -2) & 0x200) >> 4 )
0457 | (((mode->VDisplay -1) & 0x200) >> 3 )
0458 | ((mode->VSyncStart & 0x200) >> 2 ));
0459 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x08, 0x00);
0460 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x09, ((mode->VSyncStart & 0x200) >>4) | 0x40);
0461 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0A, 0x00);
0462 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0B, 0x00);
0463 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0C, 0x00);
0464 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0D, 0x00);
0465 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0E, 0x00);
0466 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x0F, 0x00);
0467 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x10, mode->VSyncStart & 0xFF);
0468 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x11, (mode->VSyncEnd & 0x0F) | 0x20);
0469 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x12, (mode->VDisplay -1) & 0xFF);
0470 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x13, 0x00);
0471 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x14, 0x00);
0472 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x15, mode->VSyncStart & 0xFF);
0473 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x16, (mode->VSyncStart +1) & 0xFF);
0474
0475 temp = 0xAF;
0476 if(VDiv2)
0477 temp |= 0x04;
0478 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x17, temp);
0479
0480 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x18, 0xFF);
0481
0482 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x1A ,
0483 (((mode->HTotal >> 3) & 0xC0 ) >> 2)
0484 | (((mode->VTotal - 2) & 0x300 ) >> 2));
0485
0486 width = fb_fix.line_length >> 3;
0487 if (fb_var.bits_per_pixel == 1)
0488 width <<= 2;
0489 if(width >= 0xFF)
0490 printk("FB_CIRRUS: Warning line size over the limit ... reduce bpp or width resolution");
0491 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x13, width);
0492
0493 temp = fb_cirrus_read_crt_reg( cirrus_board_ptr, 0x1B);
0494 temp &= 0xAF;
0495 temp |= (width >> (3+4)) & 0x10;
0496 temp |= (width >> (3+3)) & 0x40;
0497 temp |= 0x22;
0498 fb_cirrus_write_crt_reg( cirrus_board_ptr, 0x1B, temp);
0499
0500
0501
0502
0503
0504 temp = fb_cirrus_read_seq_reg( cirrus_board_ptr, 0x07);
0505 temp &= 0xe0;
0506 switch (depthcode) {
0507 case 1:
0508 case 4:
0509 temp |= 0x10;
0510 break;
0511 case 8:
0512 temp |= 0x11;
0513 break;
0514 case 64+8:
0515 temp |= 0x17;
0516 break;
0517 case 15:
0518 temp |= 0x17;
0519 hdr = 0xC0;
0520 break;
0521 case 16:
0522 temp |= 0x17;
0523 hdr = 0xC1;
0524 break;
0525 case 24:
0526 temp |= 0x15;
0527 hdr = 0xC5;
0528 break;
0529 case 32:
0530 temp |= 0x19;
0531 hdr = 0xC5;
0532 break;
0533 default:
0534 printk("FB_CIRRUS: Cannot Initialize display to requested mode\n");
0535 printk("FB_CIRRUS: returning RTEMS_UNSATISFIED on depthcode %d\n", depthcode);
0536 return RTEMS_UNSATISFIED;
0537 }
0538 fb_cirrus_write_seq_reg( cirrus_board_ptr, 0x07, temp);
0539
0540
0541
0542
0543
0544 if(hdr > 0)
0545 fb_cirrus_write_hdr_reg( cirrus_board_ptr, hdr);
0546
0547
0548
0549
0550 temp = fb_cirrus_read_gdc_reg( cirrus_board_ptr, 0x12);
0551 if (HDiv2)
0552 temp |= 0x20;
0553 else
0554 temp &= ~0x20;
0555 fb_cirrus_write_gdc_reg( cirrus_board_ptr, 0x12, temp);
0556
0557
0558 fb_cirrus_write_gdc_reg(cirrus_board_ptr, 0x05, 0x40);
0559
0560
0561 fb_cirrus_write_gdc_reg(cirrus_board_ptr, 0x06, 0x01);
0562
0563 return TRUE;
0564 }
0565
0566 static void
0567 cirrus_prepare_mode( void )
0568 {
0569
0570 active_mode = &available_modes[CIRRUS_DISPLAY_MODE];
0571
0572 fb_var.bits_per_pixel = CIRRUS_DEFAULT_BPP;
0573
0574 fb_var.xres = active_mode->HDisplay;
0575 fb_var.yres = active_mode->VDisplay;
0576
0577 fb_fix.line_length = (fb_var.xres * fb_var.bits_per_pixel + 7) / 8;
0578
0579 fb_fix.type = FB_TYPE_PACKED_PIXELS;
0580 fb_fix.visual = FB_VISUAL_TRUECOLOR;
0581
0582 }
0583
0584
0585
0586
0587 rtems_device_driver
0588 frame_buffer_open(
0589 rtems_device_major_number major,
0590 rtems_device_minor_number minor,
0591 void *arg
0592 )
0593 {
0594 int r;
0595 uint32_t smem_start, regs_start;
0596
0597 if (_Atomic_Flag_test_and_set(&driver_mutex, ATOMIC_ORDER_ACQUIRE) != 0 ) {
0598 printk( "FB_CIRRUS could not lock driver_mutex\n" );
0599
0600 return RTEMS_UNSATISFIED;
0601 }
0602
0603 r = cirrus_pci_read(&cirrus_board_info, &smem_start, ®s_start);
0604 if ( r == RTEMS_UNSATISFIED )
0605 return RTEMS_UNSATISFIED;
0606
0607 fb_fix.smem_start = (volatile char *)smem_start;
0608 fb_fix.smem_len = 0x1000000;
0609 cirrus_board_info.reg_base = (void *)regs_start;
0610
0611 cirrus_prepare_mode();
0612
0613 cirrus_set_mode( active_mode );
0614
0615 cirrus_adjust_frame( &cirrus_board_info, 0, 0);
0616
0617 if (1) {
0618 uint32_t pixmask;
0619 int x, y;
0620
0621 if(fb_var.bits_per_pixel == 32)
0622 pixmask = 0xffffff;
0623 else
0624 pixmask = (1 << fb_var.bits_per_pixel) - 1;
0625
0626 printk("FB_CIRRUS: mode set, test patter output\n");
0627
0628 for(y = 0; y < fb_var.yres; y++) {
0629 for(x = 0; x < fb_var.xres; x++) {
0630 uint32_t color;
0631 char *addr = (char *)fb_fix.smem_start;
0632 addr += y * fb_fix.line_length;
0633 addr += x * fb_var.bits_per_pixel / 8;
0634 color = x & 1 ? 0 : y & 1 ? pixmask & 0x000ff00f : pixmask;
0635 if(y == fb_var.yres - 1) {
0636 if((x > 0) && (x < fb_var.xres-1))
0637 color = pixmask & 0x00555555;
0638 }
0639 switch (fb_var.bits_per_pixel) {
0640 case 8: *(volatile uint8_t*) addr = color;
0641 break;
0642 case 16: *(volatile uint16_t*) addr = color;
0643 break;
0644 case 24: *(volatile uint32_t*) addr =
0645 (*(volatile uint32_t*) addr & 0xff000000) | color;
0646 break;
0647 case 32: *(volatile uint32_t*) addr = color;
0648 break;
0649 }
0650 }
0651 }
0652 }
0653
0654 return RTEMS_SUCCESSFUL;
0655
0656 }
0657
0658
0659
0660
0661 rtems_device_driver
0662 frame_buffer_close(
0663 rtems_device_major_number major,
0664 rtems_device_minor_number minor,
0665 void *arg
0666 )
0667 {
0668 _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
0669
0670
0671
0672
0673
0674
0675 fb_cirrus_write_gdc_reg(&cirrus_board_info, 0x06, 0x00);
0676
0677 printk( "FB_CIRRUS: close called.\n" );
0678 return RTEMS_SUCCESSFUL;
0679 }
0680
0681
0682
0683
0684 rtems_device_driver
0685 frame_buffer_read(
0686 rtems_device_major_number major,
0687 rtems_device_minor_number minor,
0688 void *arg
0689 )
0690 {
0691 rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
0692 rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
0693 memcpy(rw_args->buffer, (const void *) (fb_fix.smem_start + rw_args->offset), rw_args->bytes_moved);
0694 return RTEMS_SUCCESSFUL;
0695 }
0696
0697
0698
0699
0700 rtems_device_driver
0701 frame_buffer_write(
0702 rtems_device_major_number major,
0703 rtems_device_minor_number minor,
0704 void *arg
0705 )
0706 {
0707 rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
0708 rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
0709 memcpy( (void *) (fb_fix.smem_start + rw_args->offset), rw_args->buffer, rw_args->bytes_moved);
0710 return RTEMS_SUCCESSFUL;
0711 }
0712
0713 static int
0714 get_fix_screen_info( struct fb_fix_screeninfo *info )
0715 {
0716 *info = fb_fix;
0717 return 0;
0718 }
0719
0720 static int
0721 get_var_screen_info( struct fb_var_screeninfo *info )
0722 {
0723 *info = fb_var;
0724 return 0;
0725 }
0726
0727
0728
0729
0730
0731 rtems_device_driver
0732 frame_buffer_control(
0733 rtems_device_major_number major,
0734 rtems_device_minor_number minor,
0735 void *arg
0736 )
0737 {
0738 rtems_libio_ioctl_args_t *args = arg;
0739
0740 printk( "FB_CIRRUS ioctl called, cmd=%x\n", args->command );
0741
0742 switch( args->command ) {
0743 case FBIOGET_FSCREENINFO:
0744 args->ioctl_return = get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer );
0745 break;
0746 case FBIOGET_VSCREENINFO:
0747 args->ioctl_return = get_var_screen_info( ( struct fb_var_screeninfo * ) args->buffer );
0748 break;
0749 case FBIOPUT_VSCREENINFO:
0750
0751 args->ioctl_return = -1;
0752 return RTEMS_UNSATISFIED;
0753 case FBIOGETCMAP:
0754
0755 args->ioctl_return = -1;
0756 return RTEMS_UNSATISFIED;
0757 case FBIOPUTCMAP:
0758
0759 args->ioctl_return = -1;
0760 return RTEMS_UNSATISFIED;
0761 default:
0762 args->ioctl_return = 0;
0763 break;
0764 }
0765 return RTEMS_SUCCESSFUL;
0766 }