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
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 #include <inttypes.h>
0046
0047 #include <bsp.h>
0048
0049 #include <bsp/fb_default_mode.h>
0050 #include <bsp/fb_vesa.h>
0051 #include <bsp/realmode_int.h>
0052
0053 #include <pthread.h>
0054
0055 #include <rtems/libio.h>
0056
0057 #include <rtems/fb.h>
0058 #include <rtems/framebuffer.h>
0059
0060 #include <rtems/score/atomic.h>
0061
0062 #include <stdlib.h>
0063
0064 #define FB_VESA_NAME "FB_VESA_RM"
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 #pragma GCC diagnostic ignored "-Waddress-of-packed-member"
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 const char * const rtems_fb_default_mode;
0092
0093
0094
0095
0096
0097
0098
0099
0100 void vesa_realmode_bootup_init(void);
0101
0102
0103 static Atomic_Flag driver_mutex;
0104
0105
0106
0107
0108 static struct fb_var_screeninfo fb_var;
0109 static struct fb_fix_screeninfo fb_fix;
0110
0111 static int32_t vbe_used_mode;
0112
0113 uint32_t VBE_controller_information( VBE_vbe_info_block *info_block,
0114 uint16_t queried_VBE_Version)
0115 {
0116 uint16_t size;
0117 VBE_vbe_info_block *VBE_buffer =
0118 (VBE_vbe_info_block *)i386_get_default_rm_buffer(&size);
0119 i386_realmode_interrupt_registers parret;
0120 parret.reg_eax = VBE_RetVBEConInf;
0121 uint16_t seg, off;
0122 i386_Physical_to_real(VBE_buffer, &seg, &off);
0123 parret.reg_edi = (uint32_t)off;
0124 parret.reg_es = seg;
0125
0126 if (queried_VBE_Version >= 0x200)
0127 {
0128 memcpy(
0129 &VBE_buffer->VbeSignature,
0130 VBE20plus_SIGNATURE,
0131 sizeof(VBE_buffer->VbeSignature)
0132 );
0133 }
0134 if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0)
0135 return -1;
0136 if ((parret.reg_eax & 0xFFFF) ==
0137 (VBE_callSuccessful<<8 | VBE_functionSupported))
0138 {
0139 *info_block = *VBE_buffer;
0140 }
0141 return (parret.reg_eax & 0xFFFF);
0142 }
0143
0144 uint32_t VBE_mode_information( VBE_mode_info_block *info_block,
0145 uint16_t mode_number)
0146 {
0147 uint16_t size;
0148 VBE_mode_info_block *VBE_buffer =
0149 (VBE_mode_info_block *)i386_get_default_rm_buffer(&size);
0150 i386_realmode_interrupt_registers parret;
0151 parret.reg_eax = VBE_RetVBEModInf;
0152 parret.reg_ecx = mode_number;
0153 uint16_t seg, off;
0154 i386_Physical_to_real(VBE_buffer, &seg, &off);
0155 parret.reg_edi = (uint32_t)off;
0156 parret.reg_es = seg;
0157 if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0)
0158 return -1;
0159 if ((parret.reg_eax & 0xFFFF) ==
0160 (VBE_callSuccessful<<8 | VBE_functionSupported))
0161 {
0162 *info_block = *VBE_buffer;
0163 }
0164 return (parret.reg_eax & 0xFFFF);
0165 }
0166
0167 uint32_t VBE_set_mode( uint16_t mode_number,
0168 VBE_CRTC_info_block *info_block)
0169 {
0170 uint16_t size;
0171 VBE_CRTC_info_block *VBE_buffer =
0172 (VBE_CRTC_info_block *)i386_get_default_rm_buffer(&size);
0173 i386_realmode_interrupt_registers parret;
0174
0175 *VBE_buffer = *info_block;
0176 parret.reg_eax = VBE_SetVBEMod;
0177 parret.reg_ebx = mode_number;
0178 uint16_t seg, off;
0179 i386_Physical_to_real(VBE_buffer, &seg, &off);
0180 parret.reg_edi = (uint32_t)off;
0181 parret.reg_es = seg;
0182 if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0)
0183 return -1;
0184 return (parret.reg_eax & 0xFFFF);
0185 }
0186
0187 uint32_t VBE_current_mode(uint16_t *mode_number)
0188 {
0189 i386_realmode_interrupt_registers parret;
0190 parret.reg_eax = VBE_RetCurVBEMod;
0191 if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0)
0192 return -1;
0193 *mode_number = (uint16_t)parret.reg_ebx;
0194 return (parret.reg_eax & 0xFFFF);
0195 }
0196
0197 uint32_t VBE_report_DDC_capabilities(uint16_t controller_unit_number,
0198 uint8_t *seconds_to_transfer_EDID_block,
0199 uint8_t *DDC_level_supported)
0200 {
0201 i386_realmode_interrupt_registers parret;
0202 parret.reg_eax = VBE_DisDatCha;
0203 parret.reg_ebx = VBEDDC_Capabilities;
0204 parret.reg_ecx = controller_unit_number;
0205 parret.reg_edi = 0;
0206 parret.reg_es = 0;
0207 if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0)
0208 return -1;
0209 *seconds_to_transfer_EDID_block = (uint8_t)parret.reg_ebx >> 8;
0210 *DDC_level_supported = (uint8_t)parret.reg_ebx;
0211 return (parret.reg_eax & 0xFFFF);
0212 }
0213
0214 uint32_t VBE_read_EDID(uint16_t controller_unit_number,
0215 uint16_t EDID_block_number,
0216 EDID_edid1 *buffer)
0217 {
0218 uint16_t size;
0219 EDID_edid1 *VBE_buffer = (EDID_edid1*)i386_get_default_rm_buffer(&size);
0220 i386_realmode_interrupt_registers parret;
0221 parret.reg_eax = VBE_DisDatCha;
0222 parret.reg_ebx = VBEDDC_ReadEDID;
0223 parret.reg_ecx = controller_unit_number;
0224 parret.reg_edx = EDID_block_number;
0225 uint16_t seg, off;
0226 i386_Physical_to_real(VBE_buffer, &seg, &off);
0227 parret.reg_edi = (uint32_t)off;
0228 parret.reg_es = seg;
0229 if (i386_real_interrupt_call(INTERRUPT_NO_VIDEO_SERVICES, &parret) == 0)
0230 return -1;
0231 if ((parret.reg_eax & 0xFFFF) ==
0232 (VBE_callSuccessful<<8 | VBE_functionSupported))
0233 {
0234 *buffer = *VBE_buffer;
0235 }
0236 return (parret.reg_eax & 0xFFFF);
0237 }
0238
0239
0240
0241
0242 typedef struct {
0243
0244 uint16_t mode_number;
0245
0246 uint16_t resX;
0247
0248 uint16_t resY;
0249
0250 uint8_t bpp;
0251 } Mode_params;
0252
0253 typedef enum {
0254 NO_SUITABLE_MODE = -1,
0255 BAD_FORMAT = -2,
0256 AUTO_SELECT = -3,
0257 DONT_INIT = -4,
0258 NO_MODE_REQ = -5,
0259 } mode_err_ret_val;
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278 static int32_t find_mode_by_resolution(Mode_params *mode_list,
0279 uint8_t list_length,
0280 Mode_params *searched_resolution)
0281 {
0282 uint8_t i = 0;
0283 while (i < list_length)
0284 {
0285 if (searched_resolution->resX == mode_list[i].resX &&
0286 searched_resolution->resY == mode_list[i].resY)
0287 {
0288 if (searched_resolution->bpp==0 ||
0289 searched_resolution->bpp==mode_list[i].bpp)
0290 {
0291 searched_resolution->bpp = mode_list[i].bpp;
0292 searched_resolution->mode_number = mode_list[i].mode_number;
0293 return mode_list[i].mode_number;
0294 }
0295 }
0296 i++;
0297 }
0298 return NO_SUITABLE_MODE;
0299 }
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318 static int32_t find_mode_from_string(Mode_params *mode_list,
0319 uint8_t list_length,
0320 const char *video_string)
0321 {
0322 const char* opt;
0323 Mode_params cmdline_mode;
0324 char* endptr;
0325 cmdline_mode.bpp = 16;
0326 opt = video_string;
0327 if (opt)
0328 {
0329 if (strncmp(opt, "auto", 4) == 0)
0330 return AUTO_SELECT;
0331 if (strncmp(opt, "none", 4) == 0 ||
0332 strncmp(opt, "off", 3) == 0)
0333 {
0334 return DONT_INIT;
0335 }
0336 cmdline_mode.resX = strtol(opt, &endptr, 10);
0337 if (*endptr != 'x')
0338 {
0339 return BAD_FORMAT;
0340 }
0341 opt = endptr+1;
0342 cmdline_mode.resY = strtol(opt, &endptr, 10);
0343 switch (*endptr)
0344 {
0345 case '-':
0346 opt = endptr+1;
0347 if (strlen(opt) <= 2)
0348 cmdline_mode.bpp = strtol(opt, &endptr, 10);
0349 else
0350 {
0351 cmdline_mode.bpp = strtol(opt, &endptr, 10);
0352 if (*endptr != ' ')
0353 {
0354 return BAD_FORMAT;
0355 }
0356 }
0357 case ' ':
0358 case 0:
0359 break;
0360 default:
0361 return BAD_FORMAT;
0362 }
0363
0364 return find_mode_by_resolution(mode_list, list_length, &cmdline_mode);
0365 }
0366 return NO_MODE_REQ;
0367 }
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386 static int32_t find_mode_using_cmdline(Mode_params *mode_list,
0387 uint8_t list_length)
0388 {
0389 const char* opt;
0390 opt = bsp_cmdline_arg("--video=");
0391 if (opt)
0392 {
0393 opt += sizeof("--video=")-1;
0394 return find_mode_from_string(mode_list, list_length, opt);
0395 }
0396 return NO_MODE_REQ;
0397 }
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407 static int32_t find_mode_using_EDID( Mode_params *mode_list,
0408 uint8_t list_length)
0409 {
0410 EDID_edid1 edid;
0411 uint8_t checksum, iterator;
0412 uint8_t index, j;
0413 Mode_params EDIDmode;
0414 checksum = 0;
0415 iterator = 0;
0416 EDIDmode.bpp = 0;
0417 if (VBE_read_EDID(0, 0, &edid) !=
0418 (VBE_callSuccessful<<8 | VBE_functionSupported))
0419 {
0420 printk(FB_VESA_NAME " Function 15h (read EDID) not supported.\n");
0421 return -1;
0422 }
0423
0424 if (edid.Version == 1)
0425 {
0426 while (iterator < sizeof(EDID_edid1))
0427 {
0428 checksum += *((uint8_t *)&edid+iterator);
0429 iterator++;
0430 }
0431 if (checksum)
0432
0433 printk(FB_VESA_NAME " EDID v1 checksum failed\n");
0434
0435
0436
0437 index = 0;
0438 while (index < 4)
0439 {
0440
0441 if (edid.dtd_md[index].md.Flag0[0] == 0 &&
0442 edid.dtd_md[index].md.Flag0[1] == 0 &&
0443 edid.dtd_md[index].md.Flag1 == 0)
0444 {
0445 index++;
0446 continue;
0447 }
0448 EDIDmode.resX = DTD_horizontal_active(&edid.dtd_md[0].dtd);
0449 EDIDmode.resY = DTD_vertical_active(&edid.dtd_md[0].dtd);
0450 if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
0451 -1)
0452 return EDIDmode.mode_number;
0453
0454 index++;
0455 }
0456
0457
0458 if (edid.ExtensionFlag > 0)
0459 {
0460
0461 }
0462
0463 index = 1;
0464 while (index < 4)
0465 {
0466 if (edid.dtd_md[index].md.DataTypeTag ==
0467 EDID_DTT_CVT3ByteTimingCodes &&
0468 edid.dtd_md[index].md.Flag0[0] == 0 &&
0469 edid.dtd_md[index].md.Flag0[1] == 0 &&
0470 edid.dtd_md[index].md.Flag1 == 0 &&
0471 edid.dtd_md[index].md.Flag2 == 0)
0472 {
0473 EDID_CVT_timing_codes_3B *cvt = (EDID_CVT_timing_codes_3B *)
0474 &edid.dtd_md[index].md.DescriptorData[0];
0475 j = 0;
0476 while (j < 4)
0477 {
0478 EDIDmode.resY = edid1_CVT_addressable_lines_high(
0479 &cvt->cvt[j]
0480 );
0481 switch (edid1_CVT_aspect_ratio(&cvt->cvt[j]))
0482 {
0483 case EDID_CVT_AspectRatio_4_3:
0484 EDIDmode.resX = (EDIDmode.resY*4)/3;
0485 break;
0486 case EDID_CVT_AspectRatio_16_9:
0487 EDIDmode.resX = (EDIDmode.resY*16)/9;
0488 break;
0489 case EDID_CVT_AspectRatio_16_10:
0490 EDIDmode.resX = (EDIDmode.resY*16)/10;
0491 break;
0492 case EDID_CVT_AspectRatio_15_9:
0493 EDIDmode.resX = (EDIDmode.resY*15)/9;
0494 break;
0495 }
0496 EDIDmode.resX = (EDIDmode.resX/8)*8;
0497 if (find_mode_by_resolution(
0498 mode_list, list_length, &EDIDmode) != -1)
0499 return EDIDmode.mode_number;
0500
0501 j++;
0502 }
0503 }
0504 index++;
0505 }
0506
0507
0508
0509
0510
0511 index = 0;
0512 while (index < 8)
0513 {
0514
0515 if (edid1_STI_is_unused(&edid.STI[index]))
0516 {
0517 index++;
0518 continue;
0519 }
0520 EDIDmode.resX = (edid.STI[index].HorizontalActivePixels+31)*8;
0521 switch (edid.STI[index].ImageAspectRatio_RefreshRate &
0522 EDID1_STI_ImageAspectRatioMask)
0523 {
0524 case EDID_STI_AspectRatio_16_10:
0525 EDIDmode.resY = (EDIDmode.resX*10)/16;
0526 break;
0527 case EDID_STI_AspectRatio_4_3:
0528 EDIDmode.resY = (EDIDmode.resX*3)/4;
0529 break;
0530 case EDID_STI_AspectRatio_5_4:
0531 EDIDmode.resY = (EDIDmode.resX*4)/5;
0532 break;
0533 case EDID_STI_AspectRatio_16_9:
0534 EDIDmode.resY = (EDIDmode.resX*9)/16;
0535 break;
0536 }
0537 if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
0538 -1)
0539 return EDIDmode.mode_number;
0540
0541 index++;
0542 }
0543
0544
0545
0546
0547 if (edid1_established_tim(&edid, EST_1280x1024_75Hz))
0548 {
0549 EDIDmode.resX = 1280;
0550 EDIDmode.resY = 1024;
0551 EDIDmode.bpp = 0;
0552 if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
0553 -1)
0554 return EDIDmode.mode_number;
0555 }
0556 if (edid1_established_tim(&edid, EST_1152x870_75Hz))
0557 {
0558 EDIDmode.resX = 1152;
0559 EDIDmode.resY = 870;
0560 EDIDmode.bpp = 0;
0561 if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
0562 -1)
0563 return EDIDmode.mode_number;
0564 }
0565 if (edid1_established_tim(&edid, EST_1024x768_75Hz) ||
0566 edid1_established_tim(&edid, EST_1024x768_70Hz) ||
0567 edid1_established_tim(&edid, EST_1024x768_60Hz) ||
0568 edid1_established_tim(&edid, EST_1024x768_87Hz))
0569 {
0570 EDIDmode.resX = 1024;
0571 EDIDmode.resY = 768;
0572 EDIDmode.bpp = 0;
0573 if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
0574 -1)
0575 return EDIDmode.mode_number;
0576 }
0577 if (edid1_established_tim(&edid, EST_832x624_75Hz))
0578 {
0579 EDIDmode.resX = 832;
0580 EDIDmode.resY = 624;
0581 EDIDmode.bpp = 0;
0582 if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
0583 -1)
0584 return EDIDmode.mode_number;
0585 }
0586 if (edid1_established_tim(&edid, EST_800x600_60Hz) ||
0587 edid1_established_tim(&edid, EST_800x600_56Hz) ||
0588 edid1_established_tim(&edid, EST_800x600_75Hz) ||
0589 edid1_established_tim(&edid, EST_800x600_72Hz))
0590 {
0591 EDIDmode.resX = 800;
0592 EDIDmode.resY = 600;
0593 EDIDmode.bpp = 0;
0594 if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
0595 -1)
0596 return EDIDmode.mode_number;
0597 }
0598 if (edid1_established_tim(&edid, EST_720x400_88Hz) ||
0599 edid1_established_tim(&edid, EST_720x400_70Hz))
0600 {
0601 EDIDmode.resX = 720;
0602 EDIDmode.resY = 400;
0603 EDIDmode.bpp = 0;
0604 if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
0605 -1)
0606 return EDIDmode.mode_number;
0607 }
0608 if (edid1_established_tim(&edid, EST_640x480_75Hz) ||
0609 edid1_established_tim(&edid, EST_640x480_72Hz) ||
0610 edid1_established_tim(&edid, EST_640x480_67Hz) ||
0611 edid1_established_tim(&edid, EST_640x480_60Hz))
0612 {
0613 EDIDmode.resX = 640;
0614 EDIDmode.resY = 480;
0615 EDIDmode.bpp = 0;
0616 if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) !=
0617 -1)
0618 return EDIDmode.mode_number;
0619 }
0620 }
0621 else
0622 printk(FB_VESA_NAME " error reading EDID: unsupported version\n");
0623 return -1;
0624 }
0625
0626 void vesa_realmode_bootup_init(void)
0627 {
0628 uint32_t vbe_ret_val;
0629 uint16_t size;
0630 VBE_vbe_info_block *vib = (VBE_vbe_info_block *)
0631 i386_get_default_rm_buffer(&size);
0632 vbe_ret_val = VBE_controller_information(vib, 0x300);
0633 if (vbe_ret_val == -1)
0634 {
0635 printk(FB_VESA_NAME " error calling real mode interrupt.\n");
0636 return;
0637 }
0638 if (vbe_ret_val != (VBE_callSuccessful<<8 | VBE_functionSupported))
0639 {
0640 printk(FB_VESA_NAME " Function 00h (read VBE info block)"
0641 "not supported.\n");
0642 }
0643
0644
0645
0646
0647
0648
0649
0650 #define MAX_NO_OF_SORTED_MODES 100
0651 Mode_params sorted_mode_params[MAX_NO_OF_SORTED_MODES];
0652
0653 uint16_t *vmpSegOff = (uint16_t *)&vib->VideoModePtr;
0654 uint16_t *modeNOPtr = (uint16_t*)
0655 i386_Real_to_physical(*(vmpSegOff+1), *vmpSegOff);
0656 uint16_t iterator = 0;
0657
0658 if (*(uint16_t*)vib->VideoModePtr == VBE_STUB_VideoModeList)
0659 {
0660 printk(FB_VESA_NAME " VBE Core not implemented!\n");
0661 }
0662 else
0663 {
0664
0665 while (*(modeNOPtr+iterator) != VBE_END_OF_VideoModeList &&
0666 *(modeNOPtr+iterator) != 0)
0667 {
0668 if (iterator < MAX_NO_OF_SORTED_MODES)
0669 {
0670 sorted_mode_params[iterator].mode_number =*(modeNOPtr+iterator);
0671 iterator ++;
0672 }
0673 else
0674 break;
0675 }
0676 if (iterator < MAX_NO_OF_SORTED_MODES)
0677 sorted_mode_params[iterator].mode_number = 0;
0678 }
0679
0680 VBE_mode_info_block *mib = (VBE_mode_info_block *)
0681 i386_get_default_rm_buffer(&size);
0682 iterator = 0;
0683 uint8_t nextFilteredMode = 0;
0684 uint16_t required_mode_attributes = VBE_modSupInHWMask |
0685 VBE_ColorModeMask | VBE_GraphicsModeMask | VBE_LinFraBufModeAvaiMask;
0686
0687
0688 while (iterator < MAX_NO_OF_SORTED_MODES &&
0689 sorted_mode_params[iterator].mode_number!=0)
0690 {
0691 VBE_mode_information(mib, sorted_mode_params[iterator].mode_number);
0692 if ((mib->ModeAttributes&required_mode_attributes) ==
0693 required_mode_attributes)
0694 {
0695 sorted_mode_params[nextFilteredMode].mode_number =
0696 sorted_mode_params[iterator].mode_number;
0697 sorted_mode_params[nextFilteredMode].resX = mib->XResolution;
0698 sorted_mode_params[nextFilteredMode].resY = mib->YResolution;
0699 sorted_mode_params[nextFilteredMode].bpp = mib->BitsPerPixel;
0700 nextFilteredMode ++;
0701 }
0702 iterator ++;
0703 }
0704 sorted_mode_params[nextFilteredMode].mode_number = 0;
0705
0706 uint8_t number_of_modes = nextFilteredMode;
0707
0708
0709 vbe_used_mode = find_mode_using_cmdline(sorted_mode_params,
0710 number_of_modes);
0711
0712 if (vbe_used_mode == NO_MODE_REQ) {
0713 vbe_used_mode = find_mode_from_string(sorted_mode_params,
0714 number_of_modes, rtems_fb_default_mode);
0715 if (vbe_used_mode != NO_MODE_REQ) {
0716 printk(FB_VESA_NAME " using application option to select"
0717 " video mode\n");
0718 }
0719 }
0720 else
0721 {
0722 printk(FB_VESA_NAME " using command line option '--video='"
0723 "to select video mode\n");
0724 }
0725
0726 switch (vbe_used_mode) {
0727 case NO_SUITABLE_MODE:
0728 printk(FB_VESA_NAME " requested mode not found\n");
0729 return;
0730 case BAD_FORMAT:
0731 printk(FB_VESA_NAME " bad format of video requested\n");
0732 return;
0733 case DONT_INIT:
0734 printk(FB_VESA_NAME " selected not to initialize graphics\n");
0735 return;
0736 case NO_MODE_REQ:
0737 printk(FB_VESA_NAME " not initialized, no video selected\n");
0738 return;
0739 }
0740
0741
0742 Mode_params modeXchgPlace;
0743 iterator = 0;
0744 uint8_t j;
0745 uint8_t idxBestMode;
0746 while (iterator < number_of_modes)
0747 {
0748 idxBestMode = iterator;
0749 j = iterator+1;
0750 while (j < number_of_modes)
0751 {
0752 if (sorted_mode_params[j].resX >
0753 sorted_mode_params[idxBestMode].resX)
0754 idxBestMode = j;
0755 else if (sorted_mode_params[j].resX ==
0756 sorted_mode_params[idxBestMode].resX)
0757 {
0758 if (sorted_mode_params[j].resY >
0759 sorted_mode_params[idxBestMode].resY)
0760 idxBestMode = j;
0761 else if (sorted_mode_params[j].resY ==
0762 sorted_mode_params[idxBestMode].resY)
0763 {
0764 if (sorted_mode_params[j].bpp >
0765 sorted_mode_params[idxBestMode].bpp)
0766 idxBestMode = j;
0767 }
0768 }
0769 j++;
0770 }
0771 if (idxBestMode != iterator)
0772 {
0773 modeXchgPlace = sorted_mode_params[iterator];
0774 sorted_mode_params[iterator] = sorted_mode_params[idxBestMode];
0775 sorted_mode_params[idxBestMode] = modeXchgPlace;
0776 }
0777 iterator++;
0778 }
0779
0780 if (vbe_used_mode == AUTO_SELECT)
0781 {
0782 printk(FB_VESA_NAME " auto video mode selected"
0783 "\n\ttrying EDID ...\n");
0784
0785 vbe_used_mode = find_mode_using_EDID(sorted_mode_params,
0786 number_of_modes);
0787 if (vbe_used_mode == -1)
0788 {
0789 printk(FB_VESA_NAME" monitor's EDID video parameters not supported"
0790 "\n\tusing mode with highest resolution, bpp\n");
0791
0792 vbe_used_mode = sorted_mode_params[0].mode_number;
0793 }
0794 }
0795
0796
0797 vbe_ret_val = VBE_mode_information(mib, vbe_used_mode);
0798 if ((vbe_ret_val&0xff)!=VBE_functionSupported ||
0799 (vbe_ret_val>>8)!=VBE_callSuccessful)
0800 {
0801 printk(FB_VESA_NAME " Cannot get mode info anymore. ax=0x%lx\n",
0802 (uintptr_t) vbe_ret_val);
0803 }
0804
0805 fb_var.xres = mib->XResolution;
0806 fb_var.yres = mib->YResolution;
0807 fb_var.bits_per_pixel = mib->BitsPerPixel;
0808 fb_var.red.offset = mib->LinRedFieldPosition;
0809 fb_var.red.length = mib->LinRedMaskSize;
0810 fb_var.red.msb_right = 0;
0811 fb_var.green.offset = mib->LinGreenFieldPosition;
0812 fb_var.green.length = mib->LinGreenMaskSize;
0813 fb_var.green.msb_right = 0;
0814 fb_var.blue.offset = mib->LinBlueFieldPosition;
0815 fb_var.blue.length = mib->LinBlueMaskSize;
0816 fb_var.blue.msb_right = 0;
0817 fb_var.transp.offset = mib->LinRsvdFieldPosition;
0818 fb_var.transp.length = mib->LinRsvdMaskSize;
0819 fb_var.transp.msb_right =0;
0820
0821 fb_fix.smem_start = (char *)mib->PhysBasePtr;
0822 fb_fix.line_length = mib->LinBytesPerScanLine;
0823 fb_fix.smem_len = fb_fix.line_length*fb_var.yres;
0824 fb_fix.type = FB_TYPE_PACKED_PIXELS;
0825 if (fb_var.bits_per_pixel < 24)
0826 fb_fix.visual = FB_VISUAL_DIRECTCOLOR;
0827 else
0828 fb_fix.visual = FB_VISUAL_TRUECOLOR;
0829
0830
0831 vbe_ret_val = VBE_set_mode(vbe_used_mode | VBE_linearFlatFrameBufMask,
0832 (VBE_CRTC_info_block *)(i386_get_default_rm_buffer(&size)));
0833 if (vbe_ret_val>>8 == VBE_callFailed)
0834 printk(FB_VESA_NAME " VBE: Requested mode is not available.");
0835
0836 if ((vbe_ret_val&0xff)!= (VBE_functionSupported | VBE_callSuccessful<<8))
0837 printk(FB_VESA_NAME " Call to function 2h (set VBE mode) failed. "
0838 "ax=0x%" PRIx32 "\n", vbe_ret_val);
0839
0840 vib = (void *) 0;
0841 mib = (void *) 0;
0842 }
0843
0844
0845
0846
0847 rtems_device_driver
0848 frame_buffer_initialize(
0849 rtems_device_major_number major,
0850 rtems_device_minor_number minor,
0851 void *arg
0852 )
0853 {
0854 rtems_status_code status;
0855
0856 printk(FB_VESA_NAME " frame buffer -- driver initializing..\n" );
0857
0858
0859
0860
0861 status = rtems_io_register_name(FRAMEBUFFER_DEVICE_0_NAME, major, 0);
0862 if (status != RTEMS_SUCCESSFUL)
0863 {
0864 printk("Error registering " FRAMEBUFFER_DEVICE_0_NAME
0865 " - " FB_VESA_NAME " frame buffer device!\n");
0866 rtems_fatal_error_occurred( status );
0867 }
0868
0869 _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
0870
0871 return RTEMS_SUCCESSFUL;
0872 }
0873
0874
0875
0876
0877 rtems_device_driver
0878 frame_buffer_open(
0879 rtems_device_major_number major,
0880 rtems_device_minor_number minor,
0881 void *arg
0882 )
0883 {
0884 printk( FB_VESA_NAME " open device\n" );
0885
0886 if (_Atomic_Flag_test_and_set(&driver_mutex, ATOMIC_ORDER_ACQUIRE) != 0 )
0887 {
0888 printk( FB_VESA_NAME " could not lock vesa_mutex\n" );
0889
0890 return RTEMS_UNSATISFIED;
0891 }
0892
0893 return RTEMS_SUCCESSFUL;
0894
0895 }
0896
0897
0898
0899
0900 rtems_device_driver
0901 frame_buffer_close(
0902 rtems_device_major_number major,
0903 rtems_device_minor_number minor,
0904 void *arg
0905 )
0906 {
0907 printk( FB_VESA_NAME " close device\n" );
0908 _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
0909
0910
0911
0912
0913 printk(FB_VESA_NAME ": close called.\n" );
0914 return RTEMS_SUCCESSFUL;
0915 }
0916
0917
0918
0919
0920 rtems_device_driver
0921 frame_buffer_read(
0922 rtems_device_major_number major,
0923 rtems_device_minor_number minor,
0924 void *arg
0925 )
0926 {
0927 printk( FB_VESA_NAME " read device\n" );
0928 rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
0929 rw_args->bytes_moved =
0930 ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ?
0931 (fb_fix.smem_len - rw_args->offset) :
0932 rw_args->count;
0933 memcpy(rw_args->buffer, (const void *)
0934 (fb_fix.smem_start + rw_args->offset), rw_args->bytes_moved);
0935 return RTEMS_SUCCESSFUL;
0936 }
0937
0938
0939
0940
0941 rtems_device_driver
0942 frame_buffer_write(
0943 rtems_device_major_number major,
0944 rtems_device_minor_number minor,
0945 void *arg
0946 )
0947 {
0948 printk( FB_VESA_NAME " write device\n" );
0949 rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
0950 rw_args->bytes_moved =
0951 ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ?
0952 (fb_fix.smem_len - rw_args->offset) :
0953 rw_args->count;
0954 memcpy( (void *) (fb_fix.smem_start + rw_args->offset),
0955 rw_args->buffer, rw_args->bytes_moved);
0956 return RTEMS_SUCCESSFUL;
0957 }
0958
0959 static int get_fix_screen_info( struct fb_fix_screeninfo *info )
0960 {
0961 *info = fb_fix;
0962 return 0;
0963 }
0964
0965 static int get_var_screen_info( struct fb_var_screeninfo *info )
0966 {
0967 *info = fb_var;
0968 return 0;
0969 }
0970
0971
0972
0973
0974
0975 rtems_device_driver
0976 frame_buffer_control(
0977 rtems_device_major_number major,
0978 rtems_device_minor_number minor,
0979 void *arg
0980 )
0981 {
0982 rtems_libio_ioctl_args_t *args = arg;
0983
0984 printk( FB_VESA_NAME " ioctl called, cmd=%lx\n", (uintptr_t) args->command );
0985 printk("fbxres %d, fbyres %d\n", (int) fb_var.xres, (int) fb_var.yres);
0986 printk("fbbpp %d\n", (int) fb_var.bits_per_pixel);
0987
0988 switch (args->command)
0989 {
0990 case FBIOGET_FSCREENINFO:
0991 args->ioctl_return =
0992 get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer );
0993 break;
0994 case FBIOGET_VSCREENINFO:
0995 args->ioctl_return =
0996 get_var_screen_info( ( struct fb_var_screeninfo * ) args->buffer );
0997 break;
0998 case FBIOPUT_VSCREENINFO:
0999
1000 args->ioctl_return = -1;
1001 return RTEMS_UNSATISFIED;
1002 case FBIOGETCMAP:
1003
1004 args->ioctl_return = -1;
1005 return RTEMS_UNSATISFIED;
1006 case FBIOPUTCMAP:
1007
1008 args->ioctl_return = -1;
1009 return RTEMS_UNSATISFIED;
1010 default:
1011 args->ioctl_return = 0;
1012 break;
1013 }
1014 return RTEMS_SUCCESSFUL;
1015 }