|
|
1.1 ! root 1: /****************************************************************************** ! 2: * Copyright (c) 2004, 2008 IBM Corporation ! 3: * All rights reserved. ! 4: * This program and the accompanying materials ! 5: * are made available under the terms of the BSD License ! 6: * which accompanies this distribution, and is available at ! 7: * http://www.opensource.org/licenses/bsd-license.php ! 8: * ! 9: * Contributors: ! 10: * IBM Corporation - initial implementation ! 11: *****************************************************************************/ ! 12: ! 13: #include <stdio.h> ! 14: #include <stdlib.h> ! 15: #include <string.h> ! 16: ! 17: #include <stdint.h> ! 18: #include <cpu.h> ! 19: ! 20: #include "debug.h" ! 21: ! 22: #include <x86emu/x86emu.h> ! 23: #include <x86emu/regs.h> ! 24: #include <x86emu/prim_ops.h> // for push_word ! 25: ! 26: #include "biosemu.h" ! 27: #include "io.h" ! 28: #include "mem.h" ! 29: #include "interrupt.h" ! 30: #include "device.h" ! 31: ! 32: static X86EMU_memFuncs my_mem_funcs = { ! 33: my_rdb, my_rdw, my_rdl, ! 34: my_wrb, my_wrw, my_wrl ! 35: }; ! 36: ! 37: static X86EMU_pioFuncs my_pio_funcs = { ! 38: my_inb, my_inw, my_inl, ! 39: my_outb, my_outw, my_outl ! 40: }; ! 41: ! 42: // pointer to VBEInfoBuffer, set by vbe_prepare ! 43: uint8_t *vbe_info_buffer = 0; ! 44: // virtual BIOS Memory ! 45: uint8_t *biosmem; ! 46: uint32_t biosmem_size; ! 47: ! 48: // these structs are for input from and output to OF ! 49: typedef struct { ! 50: uint8_t display_type; // 0=NONE, 1= analog, 2=digital ! 51: uint16_t screen_width; ! 52: uint16_t screen_height; ! 53: uint16_t screen_linebytes; // bytes per line in framebuffer, may be more than screen_width ! 54: uint8_t color_depth; // color depth in bpp ! 55: uint32_t framebuffer_address; ! 56: uint8_t edid_block_zero[128]; ! 57: } __attribute__ ((__packed__)) screen_info_t; ! 58: ! 59: typedef struct { ! 60: uint8_t signature[4]; ! 61: uint16_t size_reserved; ! 62: uint8_t monitor_number; ! 63: uint16_t max_screen_width; ! 64: uint8_t color_depth; ! 65: } __attribute__ ((__packed__)) screen_info_input_t; ! 66: ! 67: // these structs only store a subset of the VBE defined fields ! 68: // only those needed. ! 69: typedef struct { ! 70: char signature[4]; ! 71: uint16_t version; ! 72: uint8_t *oem_string_ptr; ! 73: uint32_t capabilities; ! 74: uint16_t video_mode_list[256]; // lets hope we never have more than 256 video modes... ! 75: uint16_t total_memory; ! 76: } vbe_info_t; ! 77: ! 78: typedef struct { ! 79: uint16_t video_mode; ! 80: uint8_t mode_info_block[256]; ! 81: uint16_t attributes; ! 82: uint16_t linebytes; ! 83: uint16_t x_resolution; ! 84: uint16_t y_resolution; ! 85: uint8_t x_charsize; ! 86: uint8_t y_charsize; ! 87: uint8_t bits_per_pixel; ! 88: uint8_t memory_model; ! 89: uint32_t framebuffer_address; ! 90: } vbe_mode_info_t; ! 91: ! 92: typedef struct { ! 93: uint8_t port_number; // i.e. monitor number ! 94: uint8_t edid_transfer_time; ! 95: uint8_t ddc_level; ! 96: uint8_t edid_block_zero[128]; ! 97: } vbe_ddc_info_t; ! 98: ! 99: static inline uint8_t ! 100: vbe_prepare() ! 101: { ! 102: vbe_info_buffer = biosmem + (VBE_SEGMENT << 4); // segment:offset off VBE Data Area ! 103: //clear buffer ! 104: memset(vbe_info_buffer, 0, 512); ! 105: //set VbeSignature to "VBE2" to indicate VBE 2.0+ request ! 106: vbe_info_buffer[0] = 'V'; ! 107: vbe_info_buffer[0] = 'B'; ! 108: vbe_info_buffer[0] = 'E'; ! 109: vbe_info_buffer[0] = '2'; ! 110: // ES:DI store pointer to buffer in virtual mem see vbe_info_buffer above... ! 111: M.x86.R_EDI = 0x0; ! 112: M.x86.R_ES = VBE_SEGMENT; ! 113: ! 114: return 0; // successfull init ! 115: } ! 116: ! 117: // VBE Function 00h ! 118: uint8_t ! 119: vbe_info(vbe_info_t * info) ! 120: { ! 121: vbe_prepare(); ! 122: // call VBE function 00h (Info Function) ! 123: M.x86.R_EAX = 0x4f00; ! 124: ! 125: // enable trace ! 126: CHECK_DBG(DEBUG_TRACE_X86EMU) { ! 127: X86EMU_trace_on(); ! 128: } ! 129: // run VESA Interrupt ! 130: runInt10(); ! 131: ! 132: if (M.x86.R_AL != 0x4f) { ! 133: DEBUG_PRINTF_VBE("%s: VBE Info Function NOT supported! AL=%x\n", ! 134: __FUNCTION__, M.x86.R_AL); ! 135: return -1; ! 136: } ! 137: ! 138: if (M.x86.R_AH != 0x0) { ! 139: DEBUG_PRINTF_VBE ! 140: ("%s: VBE Info Function Return Code NOT OK! AH=%x\n", ! 141: __FUNCTION__, M.x86.R_AH); ! 142: return M.x86.R_AH; ! 143: } ! 144: //printf("VBE Info Dump:"); ! 145: //dump(vbe_info_buffer, 64); ! 146: ! 147: //offset 0: signature ! 148: info->signature[0] = vbe_info_buffer[0]; ! 149: info->signature[1] = vbe_info_buffer[1]; ! 150: info->signature[2] = vbe_info_buffer[2]; ! 151: info->signature[3] = vbe_info_buffer[3]; ! 152: ! 153: // offset 4: 16bit le containing VbeVersion ! 154: info->version = in16le(vbe_info_buffer + 4); ! 155: ! 156: // offset 6: 32bit le containg segment:offset of OEM String in virtual Mem. ! 157: info->oem_string_ptr = ! 158: biosmem + ((in16le(vbe_info_buffer + 8) << 4) + ! 159: in16le(vbe_info_buffer + 6)); ! 160: ! 161: // offset 10: 32bit le capabilities ! 162: info->capabilities = in32le(vbe_info_buffer + 10); ! 163: ! 164: // offset 14: 32 bit le containing segment:offset of supported video mode table ! 165: uint16_t *video_mode_ptr; ! 166: video_mode_ptr = ! 167: (uint16_t *) (biosmem + ! 168: ((in16le(vbe_info_buffer + 16) << 4) + ! 169: in16le(vbe_info_buffer + 14))); ! 170: uint32_t i = 0; ! 171: do { ! 172: info->video_mode_list[i] = in16le(video_mode_ptr + i); ! 173: i++; ! 174: } ! 175: while ((i < ! 176: (sizeof(info->video_mode_list) / ! 177: sizeof(info->video_mode_list[0]))) ! 178: && (info->video_mode_list[i - 1] != 0xFFFF)); ! 179: ! 180: //offset 18: 16bit le total memory in 64KB blocks ! 181: info->total_memory = in16le(vbe_info_buffer + 18); ! 182: ! 183: return 0; ! 184: } ! 185: ! 186: // VBE Function 01h ! 187: uint8_t ! 188: vbe_get_mode_info(vbe_mode_info_t * mode_info) ! 189: { ! 190: vbe_prepare(); ! 191: // call VBE function 01h (Return VBE Mode Info Function) ! 192: M.x86.R_EAX = 0x4f01; ! 193: M.x86.R_CX = mode_info->video_mode; ! 194: ! 195: // enable trace ! 196: CHECK_DBG(DEBUG_TRACE_X86EMU) { ! 197: X86EMU_trace_on(); ! 198: } ! 199: // run VESA Interrupt ! 200: runInt10(); ! 201: ! 202: if (M.x86.R_AL != 0x4f) { ! 203: DEBUG_PRINTF_VBE ! 204: ("%s: VBE Return Mode Info Function NOT supported! AL=%x\n", ! 205: __FUNCTION__, M.x86.R_AL); ! 206: return -1; ! 207: } ! 208: ! 209: if (M.x86.R_AH != 0x0) { ! 210: DEBUG_PRINTF_VBE ! 211: ("%s: VBE Return Mode Info (mode: %04x) Function Return Code NOT OK! AH=%02x\n", ! 212: __FUNCTION__, mode_info->video_mode, M.x86.R_AH); ! 213: return M.x86.R_AH; ! 214: } ! 215: //pointer to mode_info_block is in ES:DI ! 216: memcpy(mode_info->mode_info_block, ! 217: biosmem + ((M.x86.R_ES << 4) + M.x86.R_DI), ! 218: sizeof(mode_info->mode_info_block)); ! 219: ! 220: //printf("Mode Info Dump:"); ! 221: //dump(mode_info_block, 64); ! 222: ! 223: // offset 0: 16bit le mode attributes ! 224: mode_info->attributes = in16le(mode_info->mode_info_block); ! 225: ! 226: // offset 16: 16bit le bytes per scan line ! 227: mode_info->linebytes = in16le(mode_info->mode_info_block + 16); ! 228: ! 229: // offset 18: 16bit le x resolution ! 230: mode_info->x_resolution = in16le(mode_info->mode_info_block + 18); ! 231: ! 232: // offset 20: 16bit le y resolution ! 233: mode_info->y_resolution = in16le(mode_info->mode_info_block + 20); ! 234: ! 235: // offset 22: 8bit le x charsize ! 236: mode_info->x_charsize = *(mode_info->mode_info_block + 22); ! 237: ! 238: // offset 23: 8bit le y charsize ! 239: mode_info->y_charsize = *(mode_info->mode_info_block + 23); ! 240: ! 241: // offset 25: 8bit le bits per pixel ! 242: mode_info->bits_per_pixel = *(mode_info->mode_info_block + 25); ! 243: ! 244: // offset 27: 8bit le memory model ! 245: mode_info->memory_model = *(mode_info->mode_info_block + 27); ! 246: ! 247: // offset 40: 32bit le containg offset of frame buffer memory ptr ! 248: mode_info->framebuffer_address = ! 249: in32le(mode_info->mode_info_block + 40); ! 250: ! 251: return 0; ! 252: } ! 253: ! 254: // VBE Function 02h ! 255: uint8_t ! 256: vbe_set_mode(vbe_mode_info_t * mode_info) ! 257: { ! 258: vbe_prepare(); ! 259: // call VBE function 02h (Set VBE Mode Function) ! 260: M.x86.R_EAX = 0x4f02; ! 261: M.x86.R_BX = mode_info->video_mode; ! 262: M.x86.R_BX |= 0x4000; // set bit 14 to request linear framebuffer mode ! 263: M.x86.R_BX &= 0x7FFF; // clear bit 15 to request clearing of framebuffer ! 264: ! 265: DEBUG_PRINTF_VBE("%s: setting mode: 0x%04x\n", __FUNCTION__, ! 266: M.x86.R_BX); ! 267: ! 268: // enable trace ! 269: CHECK_DBG(DEBUG_TRACE_X86EMU) { ! 270: X86EMU_trace_on(); ! 271: } ! 272: // run VESA Interrupt ! 273: runInt10(); ! 274: ! 275: if (M.x86.R_AL != 0x4f) { ! 276: DEBUG_PRINTF_VBE ! 277: ("%s: VBE Set Mode Function NOT supported! AL=%x\n", ! 278: __FUNCTION__, M.x86.R_AL); ! 279: return -1; ! 280: } ! 281: ! 282: if (M.x86.R_AH != 0x0) { ! 283: DEBUG_PRINTF_VBE ! 284: ("%s: mode: %x VBE Set Mode Function Return Code NOT OK! AH=%x\n", ! 285: __FUNCTION__, mode_info->video_mode, M.x86.R_AH); ! 286: return M.x86.R_AH; ! 287: } ! 288: return 0; ! 289: } ! 290: ! 291: //VBE Function 08h ! 292: uint8_t ! 293: vbe_set_palette_format(uint8_t format) ! 294: { ! 295: vbe_prepare(); ! 296: // call VBE function 09h (Set/Get Palette Data Function) ! 297: M.x86.R_EAX = 0x4f08; ! 298: M.x86.R_BL = 0x00; // set format ! 299: M.x86.R_BH = format; ! 300: ! 301: DEBUG_PRINTF_VBE("%s: setting palette format: %d\n", __FUNCTION__, ! 302: format); ! 303: ! 304: // enable trace ! 305: CHECK_DBG(DEBUG_TRACE_X86EMU) { ! 306: X86EMU_trace_on(); ! 307: } ! 308: // run VESA Interrupt ! 309: runInt10(); ! 310: ! 311: if (M.x86.R_AL != 0x4f) { ! 312: DEBUG_PRINTF_VBE ! 313: ("%s: VBE Set Palette Format Function NOT supported! AL=%x\n", ! 314: __FUNCTION__, M.x86.R_AL); ! 315: return -1; ! 316: } ! 317: ! 318: if (M.x86.R_AH != 0x0) { ! 319: DEBUG_PRINTF_VBE ! 320: ("%s: VBE Set Palette Format Function Return Code NOT OK! AH=%x\n", ! 321: __FUNCTION__, M.x86.R_AH); ! 322: return M.x86.R_AH; ! 323: } ! 324: return 0; ! 325: } ! 326: ! 327: // VBE Function 09h ! 328: uint8_t ! 329: vbe_set_color(uint16_t color_number, uint32_t color_value) ! 330: { ! 331: vbe_prepare(); ! 332: // call VBE function 09h (Set/Get Palette Data Function) ! 333: M.x86.R_EAX = 0x4f09; ! 334: M.x86.R_BL = 0x00; // set color ! 335: M.x86.R_CX = 0x01; // set only one entry ! 336: M.x86.R_DX = color_number; ! 337: // ES:DI is address where color_value is stored, we store it at 2000:0000 ! 338: M.x86.R_ES = 0x2000; ! 339: M.x86.R_DI = 0x0; ! 340: ! 341: // store color value at ES:DI ! 342: out32le(biosmem + (M.x86.R_ES << 4) + M.x86.R_DI, color_value); ! 343: ! 344: DEBUG_PRINTF_VBE("%s: setting color #%x: 0x%04x\n", __FUNCTION__, ! 345: color_number, color_value); ! 346: ! 347: // enable trace ! 348: CHECK_DBG(DEBUG_TRACE_X86EMU) { ! 349: X86EMU_trace_on(); ! 350: } ! 351: // run VESA Interrupt ! 352: runInt10(); ! 353: ! 354: if (M.x86.R_AL != 0x4f) { ! 355: DEBUG_PRINTF_VBE ! 356: ("%s: VBE Set Palette Function NOT supported! AL=%x\n", ! 357: __FUNCTION__, M.x86.R_AL); ! 358: return -1; ! 359: } ! 360: ! 361: if (M.x86.R_AH != 0x0) { ! 362: DEBUG_PRINTF_VBE ! 363: ("%s: VBE Set Palette Function Return Code NOT OK! AH=%x\n", ! 364: __FUNCTION__, M.x86.R_AH); ! 365: return M.x86.R_AH; ! 366: } ! 367: return 0; ! 368: } ! 369: ! 370: uint8_t ! 371: vbe_get_color(uint16_t color_number, uint32_t * color_value) ! 372: { ! 373: vbe_prepare(); ! 374: // call VBE function 09h (Set/Get Palette Data Function) ! 375: M.x86.R_EAX = 0x4f09; ! 376: M.x86.R_BL = 0x00; // get color ! 377: M.x86.R_CX = 0x01; // get only one entry ! 378: M.x86.R_DX = color_number; ! 379: // ES:DI is address where color_value is stored, we store it at 2000:0000 ! 380: M.x86.R_ES = 0x2000; ! 381: M.x86.R_DI = 0x0; ! 382: ! 383: // enable trace ! 384: CHECK_DBG(DEBUG_TRACE_X86EMU) { ! 385: X86EMU_trace_on(); ! 386: } ! 387: // run VESA Interrupt ! 388: runInt10(); ! 389: ! 390: if (M.x86.R_AL != 0x4f) { ! 391: DEBUG_PRINTF_VBE ! 392: ("%s: VBE Set Palette Function NOT supported! AL=%x\n", ! 393: __FUNCTION__, M.x86.R_AL); ! 394: return -1; ! 395: } ! 396: ! 397: if (M.x86.R_AH != 0x0) { ! 398: DEBUG_PRINTF_VBE ! 399: ("%s: VBE Set Palette Function Return Code NOT OK! AH=%x\n", ! 400: __FUNCTION__, M.x86.R_AH); ! 401: return M.x86.R_AH; ! 402: } ! 403: // read color value from ES:DI ! 404: *color_value = in32le(biosmem + (M.x86.R_ES << 4) + M.x86.R_DI); ! 405: ! 406: DEBUG_PRINTF_VBE("%s: getting color #%x --> 0x%04x\n", __FUNCTION__, ! 407: color_number, *color_value); ! 408: ! 409: return 0; ! 410: } ! 411: ! 412: // VBE Function 15h ! 413: uint8_t ! 414: vbe_get_ddc_info(vbe_ddc_info_t * ddc_info) ! 415: { ! 416: vbe_prepare(); ! 417: // call VBE function 15h (DDC Info Function) ! 418: M.x86.R_EAX = 0x4f15; ! 419: M.x86.R_BL = 0x00; // get DDC Info ! 420: M.x86.R_CX = ddc_info->port_number; ! 421: M.x86.R_ES = 0x0; ! 422: M.x86.R_DI = 0x0; ! 423: ! 424: // enable trace ! 425: CHECK_DBG(DEBUG_TRACE_X86EMU) { ! 426: X86EMU_trace_on(); ! 427: } ! 428: // run VESA Interrupt ! 429: runInt10(); ! 430: ! 431: if (M.x86.R_AL != 0x4f) { ! 432: DEBUG_PRINTF_VBE ! 433: ("%s: VBE Get DDC Info Function NOT supported! AL=%x\n", ! 434: __FUNCTION__, M.x86.R_AL); ! 435: return -1; ! 436: } ! 437: ! 438: if (M.x86.R_AH != 0x0) { ! 439: DEBUG_PRINTF_VBE ! 440: ("%s: port: %x VBE Get DDC Info Function Return Code NOT OK! AH=%x\n", ! 441: __FUNCTION__, ddc_info->port_number, M.x86.R_AH); ! 442: return M.x86.R_AH; ! 443: } ! 444: // BH = approx. time in seconds to transfer one EDID block ! 445: ddc_info->edid_transfer_time = M.x86.R_BH; ! 446: // BL = DDC Level ! 447: ddc_info->ddc_level = M.x86.R_BL; ! 448: ! 449: vbe_prepare(); ! 450: // call VBE function 15h (DDC Info Function) ! 451: M.x86.R_EAX = 0x4f15; ! 452: M.x86.R_BL = 0x01; // read EDID ! 453: M.x86.R_CX = ddc_info->port_number; ! 454: M.x86.R_DX = 0x0; // block number ! 455: // ES:DI is address where EDID is stored, we store it at 2000:0000 ! 456: M.x86.R_ES = 0x2000; ! 457: M.x86.R_DI = 0x0; ! 458: ! 459: // enable trace ! 460: CHECK_DBG(DEBUG_TRACE_X86EMU) { ! 461: X86EMU_trace_on(); ! 462: } ! 463: // run VESA Interrupt ! 464: runInt10(); ! 465: ! 466: if (M.x86.R_AL != 0x4f) { ! 467: DEBUG_PRINTF_VBE ! 468: ("%s: VBE Read EDID Function NOT supported! AL=%x\n", ! 469: __FUNCTION__, M.x86.R_AL); ! 470: return -1; ! 471: } ! 472: ! 473: if (M.x86.R_AH != 0x0) { ! 474: DEBUG_PRINTF_VBE ! 475: ("%s: port: %x VBE Read EDID Function Return Code NOT OK! AH=%x\n", ! 476: __FUNCTION__, ddc_info->port_number, M.x86.R_AH); ! 477: return M.x86.R_AH; ! 478: } ! 479: ! 480: memcpy(ddc_info->edid_block_zero, ! 481: biosmem + (M.x86.R_ES << 4) + M.x86.R_DI, ! 482: sizeof(ddc_info->edid_block_zero)); ! 483: ! 484: return 0; ! 485: } ! 486: ! 487: uint32_t ! 488: vbe_get_info(uint8_t argc, char ** argv) ! 489: { ! 490: uint8_t rval; ! 491: uint32_t i; ! 492: if (argc < 4) { ! 493: printf ! 494: ("Usage %s <vmem_base> <device_path> <address of screen_info_t>\n", ! 495: argv[0]); ! 496: int i = 0; ! 497: for (i = 0; i < argc; i++) { ! 498: printf("argv[%d]: %s\n", i, argv[i]); ! 499: } ! 500: return -1; ! 501: } ! 502: // get a copy of input struct... ! 503: screen_info_input_t input = ! 504: *((screen_info_input_t *) strtoul((char *) argv[4], 0, 16)); ! 505: // output is pointer to the address passed as argv[4] ! 506: screen_info_t *output = ! 507: (screen_info_t *) strtoul((char *) argv[4], 0, 16); ! 508: // zero output ! 509: memset(output, 0, sizeof(screen_info_t)); ! 510: ! 511: // argv[1] is address of virtual BIOS mem... ! 512: // argv[2] is the size ! 513: biosmem = (uint8_t *) strtoul(argv[1], 0, 16); ! 514: biosmem_size = strtoul(argv[2], 0, 16);; ! 515: if (biosmem_size < MIN_REQUIRED_VMEM_SIZE) { ! 516: printf("Error: Not enough virtual memory: %x, required: %x!\n", ! 517: biosmem_size, MIN_REQUIRED_VMEM_SIZE); ! 518: return -1; ! 519: } ! 520: // argv[3] is the device to open and use... ! 521: if (dev_init((char *) argv[3]) != 0) { ! 522: printf("Error initializing device!\n"); ! 523: return -1; ! 524: } ! 525: //setup interrupt handler ! 526: X86EMU_intrFuncs intrFuncs[256]; ! 527: for (i = 0; i < 256; i++) ! 528: intrFuncs[i] = handleInterrupt; ! 529: X86EMU_setupIntrFuncs(intrFuncs); ! 530: X86EMU_setupPioFuncs(&my_pio_funcs); ! 531: X86EMU_setupMemFuncs(&my_mem_funcs); ! 532: ! 533: // set mem_base ! 534: M.mem_base = (long) biosmem; ! 535: M.mem_size = biosmem_size; ! 536: DEBUG_PRINTF_VBE("membase set: %08x, size: %08x\n", (int) M.mem_base, ! 537: (int) M.mem_size); ! 538: ! 539: vbe_info_t info; ! 540: rval = vbe_info(&info); ! 541: if (rval != 0) ! 542: return rval; ! 543: ! 544: DEBUG_PRINTF_VBE("VbeSignature: %s\n", info.signature); ! 545: DEBUG_PRINTF_VBE("VbeVersion: 0x%04x\n", info.version); ! 546: DEBUG_PRINTF_VBE("OemString: %s\n", info.oem_string_ptr); ! 547: DEBUG_PRINTF_VBE("Capabilities:\n"); ! 548: DEBUG_PRINTF_VBE("\tDAC: %s\n", ! 549: (info.capabilities & 0x1) == ! 550: 0 ? "fixed 6bit" : "switchable 6/8bit"); ! 551: DEBUG_PRINTF_VBE("\tVGA: %s\n", ! 552: (info.capabilities & 0x2) == ! 553: 0 ? "compatible" : "not compatible"); ! 554: DEBUG_PRINTF_VBE("\tRAMDAC: %s\n", ! 555: (info.capabilities & 0x4) == ! 556: 0 ? "normal" : "use blank bit in Function 09h"); ! 557: ! 558: // argv[4] may be a pointer with enough space to return screen_info_t ! 559: // as input, it must contain a screen_info_input_t with the following content: ! 560: // byte[0:3] = "DDC\0" (zero-terminated signature header) ! 561: // byte[4:5] = reserved space for the return struct... just in case we ever change ! 562: // the struct and dont have reserved enough memory (and let's hope the struct ! 563: // never gets larger than 64KB) ! 564: // byte[6] = monitor port number for DDC requests ("only" one byte... so lets hope we never have more than 255 monitors... ! 565: // byte[7:8] = max. screen width (OF may want to limit this) ! 566: // byte[9] = required color depth in bpp ! 567: if (strncmp((char *) input.signature, "DDC", 4) != 0) { ! 568: printf ! 569: ("%s: Invalid input signature! expected: %s, is: %s\n", ! 570: __FUNCTION__, "DDC", input.signature); ! 571: return -1; ! 572: } ! 573: if (input.size_reserved != sizeof(screen_info_t)) { ! 574: printf ! 575: ("%s: Size of return struct is wrong, required: %d, available: %d\n", ! 576: __FUNCTION__, (int) sizeof(screen_info_t), ! 577: input.size_reserved); ! 578: return -1; ! 579: } ! 580: ! 581: vbe_ddc_info_t ddc_info; ! 582: ddc_info.port_number = input.monitor_number; ! 583: vbe_get_ddc_info(&ddc_info); ! 584: ! 585: #if 0 ! 586: DEBUG_PRINTF_VBE("DDC: edid_tranfer_time: %d\n", ! 587: ddc_info.edid_transfer_time); ! 588: DEBUG_PRINTF_VBE("DDC: ddc_level: %x\n", ddc_info.ddc_level); ! 589: DEBUG_PRINTF_VBE("DDC: EDID: \n"); ! 590: CHECK_DBG(DEBUG_VBE) { ! 591: dump(ddc_info.edid_block_zero, ! 592: sizeof(ddc_info.edid_block_zero)); ! 593: } ! 594: #endif ! 595: if (*((uint64_t *) ddc_info.edid_block_zero) != ! 596: (uint64_t) 0x00FFFFFFFFFFFF00) { ! 597: // invalid EDID signature... probably no monitor ! 598: ! 599: output->display_type = 0x0; ! 600: return 0; ! 601: } else if ((ddc_info.edid_block_zero[20] & 0x80) != 0) { ! 602: // digital display ! 603: output->display_type = 2; ! 604: } else { ! 605: // analog ! 606: output->display_type = 1; ! 607: } ! 608: DEBUG_PRINTF_VBE("DDC: found display type %d\n", output->display_type); ! 609: memcpy(output->edid_block_zero, ddc_info.edid_block_zero, ! 610: sizeof(ddc_info.edid_block_zero)); ! 611: i = 0; ! 612: vbe_mode_info_t mode_info; ! 613: vbe_mode_info_t best_mode_info; ! 614: // initialize best_mode to 0 ! 615: memset(&best_mode_info, 0, sizeof(best_mode_info)); ! 616: while ((mode_info.video_mode = info.video_mode_list[i]) != 0xFFFF) { ! 617: //DEBUG_PRINTF_VBE("%x: Mode: %04x\n", i, mode_info.video_mode); ! 618: vbe_get_mode_info(&mode_info); ! 619: #if 0 ! 620: DEBUG_PRINTF_VBE("Video Mode 0x%04x available, %s\n", ! 621: mode_info.video_mode, ! 622: (mode_info.attributes & 0x1) == ! 623: 0 ? "not supported" : "supported"); ! 624: DEBUG_PRINTF_VBE("\tTTY: %s\n", ! 625: (mode_info.attributes & 0x4) == ! 626: 0 ? "no" : "yes"); ! 627: DEBUG_PRINTF_VBE("\tMode: %s %s\n", ! 628: (mode_info.attributes & 0x8) == ! 629: 0 ? "monochrome" : "color", ! 630: (mode_info.attributes & 0x10) == ! 631: 0 ? "text" : "graphics"); ! 632: DEBUG_PRINTF_VBE("\tVGA: %s\n", ! 633: (mode_info.attributes & 0x20) == ! 634: 0 ? "compatible" : "not compatible"); ! 635: DEBUG_PRINTF_VBE("\tWindowed Mode: %s\n", ! 636: (mode_info.attributes & 0x40) == ! 637: 0 ? "yes" : "no"); ! 638: DEBUG_PRINTF_VBE("\tFramebuffer: %s\n", ! 639: (mode_info.attributes & 0x80) == ! 640: 0 ? "no" : "yes"); ! 641: DEBUG_PRINTF_VBE("\tResolution: %dx%d\n", ! 642: mode_info.x_resolution, ! 643: mode_info.y_resolution); ! 644: DEBUG_PRINTF_VBE("\tChar Size: %dx%d\n", ! 645: mode_info.x_charsize, mode_info.y_charsize); ! 646: DEBUG_PRINTF_VBE("\tColor Depth: %dbpp\n", ! 647: mode_info.bits_per_pixel); ! 648: DEBUG_PRINTF_VBE("\tMemory Model: 0x%x\n", ! 649: mode_info.memory_model); ! 650: DEBUG_PRINTF_VBE("\tFramebuffer Offset: %08x\n", ! 651: mode_info.framebuffer_address); ! 652: #endif ! 653: if ((mode_info.bits_per_pixel == input.color_depth) ! 654: && (mode_info.x_resolution <= input.max_screen_width) ! 655: && ((mode_info.attributes & 0x80) != 0) // framebuffer mode ! 656: && ((mode_info.attributes & 0x10) != 0) // graphics ! 657: && ((mode_info.attributes & 0x8) != 0) // color ! 658: && (mode_info.x_resolution > best_mode_info.x_resolution)) // better than previous best_mode ! 659: { ! 660: // yiiiihaah... we found a new best mode ! 661: memcpy(&best_mode_info, &mode_info, sizeof(mode_info)); ! 662: } ! 663: i++; ! 664: } ! 665: ! 666: if (best_mode_info.video_mode != 0) { ! 667: DEBUG_PRINTF_VBE ! 668: ("Best Video Mode found: 0x%x, %dx%d, %dbpp, framebuffer_address: 0x%x\n", ! 669: best_mode_info.video_mode, ! 670: best_mode_info.x_resolution, ! 671: best_mode_info.y_resolution, ! 672: best_mode_info.bits_per_pixel, ! 673: best_mode_info.framebuffer_address); ! 674: ! 675: //printf("Mode Info Dump:"); ! 676: //dump(best_mode_info.mode_info_block, 64); ! 677: ! 678: // set the video mode ! 679: vbe_set_mode(&best_mode_info); ! 680: ! 681: if ((info.capabilities & 0x1) != 0) { ! 682: // switch to 8 bit palette format ! 683: vbe_set_palette_format(8); ! 684: } ! 685: // setup a palette: ! 686: // - first 216 colors are mixed colors for each component in 6 steps ! 687: // (6*6*6=216) ! 688: // - then 10 shades of the three primary colors ! 689: // - then 10 shades of grey ! 690: // ------- ! 691: // = 256 colors ! 692: // ! 693: // - finally black is color 0 and white color FF (because SLOF expects it ! 694: // this way...) ! 695: // this resembles the palette that the kernel/X Server seems to expect... ! 696: ! 697: uint8_t mixed_color_values[6] = ! 698: { 0xFF, 0xDA, 0xB3, 0x87, 0x54, 0x00 }; ! 699: uint8_t primary_color_values[10] = ! 700: { 0xF3, 0xE7, 0xCD, 0xC0, 0xA5, 0x96, 0x77, 0x66, 0x3F, ! 701: 0x27 ! 702: }; ! 703: uint8_t mc_size = sizeof(mixed_color_values); ! 704: uint8_t prim_size = sizeof(primary_color_values); ! 705: ! 706: uint8_t curr_color_index; ! 707: uint32_t curr_color; ! 708: ! 709: uint8_t r, g, b; ! 710: // 216 mixed colors ! 711: for (r = 0; r < mc_size; r++) { ! 712: for (g = 0; g < mc_size; g++) { ! 713: for (b = 0; b < mc_size; b++) { ! 714: curr_color_index = ! 715: (r * mc_size * mc_size) + ! 716: (g * mc_size) + b; ! 717: curr_color = 0; ! 718: curr_color |= ((uint32_t) mixed_color_values[r]) << 16; //red value ! 719: curr_color |= ((uint32_t) mixed_color_values[g]) << 8; //green value ! 720: curr_color |= (uint32_t) mixed_color_values[b]; //blue value ! 721: vbe_set_color(curr_color_index, ! 722: curr_color); ! 723: } ! 724: } ! 725: } ! 726: ! 727: // 10 shades of each primary color ! 728: // red ! 729: for (r = 0; r < prim_size; r++) { ! 730: curr_color_index = mc_size * mc_size * mc_size + r; ! 731: curr_color = ((uint32_t) primary_color_values[r]) << 16; ! 732: vbe_set_color(curr_color_index, curr_color); ! 733: } ! 734: //green ! 735: for (g = 0; g < prim_size; g++) { ! 736: curr_color_index = ! 737: mc_size * mc_size * mc_size + prim_size + g; ! 738: curr_color = ((uint32_t) primary_color_values[g]) << 8; ! 739: vbe_set_color(curr_color_index, curr_color); ! 740: } ! 741: //blue ! 742: for (b = 0; b < prim_size; b++) { ! 743: curr_color_index = ! 744: mc_size * mc_size * mc_size + prim_size * 2 + b; ! 745: curr_color = (uint32_t) primary_color_values[b]; ! 746: vbe_set_color(curr_color_index, curr_color); ! 747: } ! 748: // 10 shades of grey ! 749: for (i = 0; i < prim_size; i++) { ! 750: curr_color_index = ! 751: mc_size * mc_size * mc_size + prim_size * 3 + i; ! 752: curr_color = 0; ! 753: curr_color |= ((uint32_t) primary_color_values[i]) << 16; //red ! 754: curr_color |= ((uint32_t) primary_color_values[i]) << 8; //green ! 755: curr_color |= ((uint32_t) primary_color_values[i]); //blue ! 756: vbe_set_color(curr_color_index, curr_color); ! 757: } ! 758: ! 759: // SLOF is using color 0x0 (black) and 0xFF (white) to draw to the screen... ! 760: vbe_set_color(0x00, 0x00000000); ! 761: vbe_set_color(0xFF, 0x00FFFFFF); ! 762: ! 763: output->screen_width = best_mode_info.x_resolution; ! 764: output->screen_height = best_mode_info.y_resolution; ! 765: output->screen_linebytes = best_mode_info.linebytes; ! 766: output->color_depth = best_mode_info.bits_per_pixel; ! 767: output->framebuffer_address = ! 768: best_mode_info.framebuffer_address; ! 769: } else { ! 770: printf("%s: No suitable video mode found!\n", __FUNCTION__); ! 771: //unset display_type... ! 772: output->display_type = 0; ! 773: } ! 774: return 0; ! 775: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.