|
|
1.1 ! root 1: // VGA bios implementation ! 2: // ! 3: // Copyright (C) 2009-2012 Kevin O'Connor <[email protected]> ! 4: // Copyright (C) 2001-2008 the LGPL VGABios developers Team ! 5: // ! 6: // This file may be distributed under the terms of the GNU LGPLv3 license. ! 7: ! 8: #include "bregs.h" // struct bregs ! 9: #include "biosvar.h" // GET_BDA ! 10: #include "util.h" // memset ! 11: #include "vgabios.h" // calc_page_size ! 12: #include "optionroms.h" // struct pci_data ! 13: #include "config.h" // CONFIG_* ! 14: #include "stdvga.h" // stdvga_set_cursor_shape ! 15: #include "clext.h" // clext_1012 ! 16: #include "vgahw.h" // vgahw_set_mode ! 17: #include "vbe.h" // VBE_RETURN_STATUS_FAILED ! 18: #include "pci.h" // pci_config_readw ! 19: #include "pci_regs.h" // PCI_VENDOR_ID ! 20: ! 21: // Standard Video Save Pointer Table ! 22: struct VideoSavePointer_s { ! 23: struct segoff_s videoparam; ! 24: struct segoff_s paramdynamicsave; ! 25: struct segoff_s textcharset; ! 26: struct segoff_s graphcharset; ! 27: struct segoff_s secsavepointer; ! 28: u8 reserved[8]; ! 29: } PACKED; ! 30: ! 31: static struct VideoSavePointer_s video_save_pointer_table VAR16; ! 32: ! 33: struct VideoParam_s video_param_table[29] VAR16; ! 34: ! 35: ! 36: /**************************************************************** ! 37: * PCI Data ! 38: ****************************************************************/ ! 39: ! 40: struct pci_data rom_pci_data VAR16VISIBLE = { ! 41: .signature = PCI_ROM_SIGNATURE, ! 42: .vendor = CONFIG_VGA_VID, ! 43: .device = CONFIG_VGA_DID, ! 44: .dlen = 0x18, ! 45: .class_hi = 0x300, ! 46: .irevision = 1, ! 47: .type = PCIROM_CODETYPE_X86, ! 48: .indicator = 0x80, ! 49: }; ! 50: ! 51: ! 52: /**************************************************************** ! 53: * Helper functions ! 54: ****************************************************************/ ! 55: ! 56: // Return the bits per pixel in system memory for a given mode. ! 57: int ! 58: vga_bpp(struct vgamode_s *vmode_g) ! 59: { ! 60: switch (GET_GLOBAL(vmode_g->memmodel)) { ! 61: case MM_TEXT: ! 62: return 16; ! 63: case MM_PLANAR: ! 64: return 1; ! 65: } ! 66: u8 depth = GET_GLOBAL(vmode_g->depth); ! 67: if (depth > 8) ! 68: return ALIGN(depth, 8); ! 69: return depth; ! 70: } ! 71: ! 72: u16 ! 73: calc_page_size(u8 memmodel, u16 width, u16 height) ! 74: { ! 75: switch (memmodel) { ! 76: case MM_TEXT: ! 77: return ALIGN(width * height * 2, 2*1024); ! 78: case MM_CGA: ! 79: return 16*1024; ! 80: default: ! 81: return ALIGN(width * height / 8, 8*1024); ! 82: } ! 83: } ! 84: ! 85: static void ! 86: set_cursor_shape(u8 start, u8 end) ! 87: { ! 88: start &= 0x3f; ! 89: end &= 0x1f; ! 90: ! 91: u16 curs = (start << 8) + end; ! 92: SET_BDA(cursor_type, curs); ! 93: ! 94: u8 modeset_ctl = GET_BDA(modeset_ctl); ! 95: u16 cheight = GET_BDA(char_height); ! 96: if ((modeset_ctl & 0x01) && (cheight > 8) && (end < 8) && (start < 0x20)) { ! 97: if (end != (start + 1)) ! 98: start = ((start + 1) * cheight / 8) - 1; ! 99: else ! 100: start = ((end + 1) * cheight / 8) - 2; ! 101: end = ((end + 1) * cheight / 8) - 1; ! 102: } ! 103: stdvga_set_cursor_shape(start, end); ! 104: } ! 105: ! 106: static u16 ! 107: get_cursor_shape(u8 page) ! 108: { ! 109: if (page > 7) ! 110: return 0; ! 111: // FIXME should handle VGA 14/16 lines ! 112: return GET_BDA(cursor_type); ! 113: } ! 114: ! 115: static void ! 116: set_cursor_pos(struct cursorpos cp) ! 117: { ! 118: u8 page = cp.page, x = cp.x, y = cp.y; ! 119: ! 120: // Should not happen... ! 121: if (page > 7) ! 122: return; ! 123: ! 124: // Bios cursor pos ! 125: SET_BDA(cursor_pos[page], (y << 8) | x); ! 126: ! 127: // Set the hardware cursor ! 128: u8 current = GET_BDA(video_page); ! 129: if (cp.page != current) ! 130: return; ! 131: ! 132: // Calculate the memory address ! 133: int address = (GET_BDA(video_pagesize) * page ! 134: + (x + y * GET_BDA(video_cols)) * 2); ! 135: stdvga_set_cursor_pos(address); ! 136: } ! 137: ! 138: static struct cursorpos ! 139: get_cursor_pos(u8 page) ! 140: { ! 141: if (page == 0xff) ! 142: // special case - use current page ! 143: page = GET_BDA(video_page); ! 144: if (page > 7) { ! 145: struct cursorpos cp = { 0, 0, 0xfe }; ! 146: return cp; ! 147: } ! 148: // FIXME should handle VGA 14/16 lines ! 149: u16 xy = GET_BDA(cursor_pos[page]); ! 150: struct cursorpos cp = {xy, xy>>8, page}; ! 151: return cp; ! 152: } ! 153: ! 154: static void ! 155: set_active_page(u8 page) ! 156: { ! 157: if (page > 7) ! 158: return; ! 159: ! 160: // Get the mode ! 161: struct vgamode_s *vmode_g = get_current_mode(); ! 162: if (!vmode_g) ! 163: return; ! 164: ! 165: // Get cursor pos for the given page ! 166: struct cursorpos cp = get_cursor_pos(page); ! 167: ! 168: // Calculate memory address of start of page ! 169: int address = GET_BDA(video_pagesize) * page; ! 170: vgahw_set_displaystart(vmode_g, address); ! 171: ! 172: // And change the BIOS page ! 173: SET_BDA(video_pagestart, address); ! 174: SET_BDA(video_page, page); ! 175: ! 176: dprintf(1, "Set active page %02x address %04x\n", page, address); ! 177: ! 178: // Display the cursor, now the page is active ! 179: set_cursor_pos(cp); ! 180: } ! 181: ! 182: static void ! 183: set_scan_lines(u8 lines) ! 184: { ! 185: stdvga_set_scan_lines(lines); ! 186: if (lines == 8) ! 187: set_cursor_shape(0x06, 0x07); ! 188: else ! 189: set_cursor_shape(lines - 4, lines - 3); ! 190: SET_BDA(char_height, lines); ! 191: u16 vde = stdvga_get_vde(); ! 192: u8 rows = vde / lines; ! 193: SET_BDA(video_rows, rows - 1); ! 194: u16 cols = GET_BDA(video_cols); ! 195: SET_BDA(video_pagesize, calc_page_size(MM_TEXT, cols, rows)); ! 196: } ! 197: ! 198: ! 199: /**************************************************************** ! 200: * Character writing ! 201: ****************************************************************/ ! 202: ! 203: // Scroll the screen one line. This function is designed to be called ! 204: // tail-recursive to reduce stack usage. ! 205: static void noinline ! 206: scroll_one(u16 nbrows, u16 nbcols, u8 page) ! 207: { ! 208: struct cursorpos ul = {0, 0, page}; ! 209: struct cursorpos lr = {nbcols-1, nbrows-1, page}; ! 210: vgafb_scroll(1, -1, ul, lr); ! 211: } ! 212: ! 213: // Write a character to the screen at a given position. Implement ! 214: // special characters and scroll the screen if necessary. ! 215: static void ! 216: write_teletype(struct cursorpos *pcp, struct carattr ca) ! 217: { ! 218: struct cursorpos cp = *pcp; ! 219: ! 220: // Get the dimensions ! 221: u16 nbrows = GET_BDA(video_rows) + 1; ! 222: u16 nbcols = GET_BDA(video_cols); ! 223: ! 224: switch (ca.car) { ! 225: case 7: ! 226: //FIXME should beep ! 227: break; ! 228: case 8: ! 229: if (cp.x > 0) ! 230: cp.x--; ! 231: break; ! 232: case '\r': ! 233: cp.x = 0; ! 234: break; ! 235: case '\n': ! 236: cp.y++; ! 237: break; ! 238: case '\t': ! 239: ca.car = ' '; ! 240: do { ! 241: vgafb_write_char(cp, ca); ! 242: cp.x++; ! 243: } while (cp.x < nbcols && cp.x % 8); ! 244: break; ! 245: default: ! 246: vgafb_write_char(cp, ca); ! 247: cp.x++; ! 248: } ! 249: ! 250: // Do we need to wrap ? ! 251: if (cp.x == nbcols) { ! 252: cp.x = 0; ! 253: cp.y++; ! 254: } ! 255: // Do we need to scroll ? ! 256: if (cp.y < nbrows) { ! 257: *pcp = cp; ! 258: return; ! 259: } ! 260: // Scroll screen ! 261: cp.y--; ! 262: *pcp = cp; ! 263: scroll_one(nbrows, nbcols, cp.page); ! 264: } ! 265: ! 266: ! 267: /**************************************************************** ! 268: * Save and restore bda state ! 269: ****************************************************************/ ! 270: ! 271: void ! 272: save_bda_state(u16 seg, struct saveBDAstate *info) ! 273: { ! 274: SET_FARVAR(seg, info->video_mode, GET_BDA(vbe_mode)); ! 275: SET_FARVAR(seg, info->video_cols, GET_BDA(video_cols)); ! 276: SET_FARVAR(seg, info->video_pagesize, GET_BDA(video_pagesize)); ! 277: SET_FARVAR(seg, info->crtc_address, GET_BDA(crtc_address)); ! 278: SET_FARVAR(seg, info->video_rows, GET_BDA(video_rows)); ! 279: SET_FARVAR(seg, info->char_height, GET_BDA(char_height)); ! 280: SET_FARVAR(seg, info->video_ctl, GET_BDA(video_ctl)); ! 281: SET_FARVAR(seg, info->video_switches, GET_BDA(video_switches)); ! 282: SET_FARVAR(seg, info->modeset_ctl, GET_BDA(modeset_ctl)); ! 283: SET_FARVAR(seg, info->cursor_type, GET_BDA(cursor_type)); ! 284: int i; ! 285: for (i=0; i<8; i++) ! 286: SET_FARVAR(seg, info->cursor_pos[i], GET_BDA(cursor_pos[i])); ! 287: SET_FARVAR(seg, info->video_pagestart, GET_BDA(video_pagestart)); ! 288: SET_FARVAR(seg, info->video_page, GET_BDA(video_page)); ! 289: /* current font */ ! 290: SET_FARVAR(seg, info->font0, GET_IVT(0x1f)); ! 291: SET_FARVAR(seg, info->font1, GET_IVT(0x43)); ! 292: } ! 293: ! 294: void ! 295: restore_bda_state(u16 seg, struct saveBDAstate *info) ! 296: { ! 297: u16 mode = GET_FARVAR(seg, info->video_mode); ! 298: SET_BDA(vbe_mode, mode); ! 299: if (mode < 0x100) ! 300: SET_BDA(video_mode, mode); ! 301: else ! 302: SET_BDA(video_mode, 0xff); ! 303: SET_BDA(video_cols, GET_FARVAR(seg, info->video_cols)); ! 304: SET_BDA(video_pagesize, GET_FARVAR(seg, info->video_pagesize)); ! 305: SET_BDA(crtc_address, GET_FARVAR(seg, info->crtc_address)); ! 306: SET_BDA(video_rows, GET_FARVAR(seg, info->video_rows)); ! 307: SET_BDA(char_height, GET_FARVAR(seg, info->char_height)); ! 308: SET_BDA(video_ctl, GET_FARVAR(seg, info->video_ctl)); ! 309: SET_BDA(video_switches, GET_FARVAR(seg, info->video_switches)); ! 310: SET_BDA(modeset_ctl, GET_FARVAR(seg, info->modeset_ctl)); ! 311: SET_BDA(cursor_type, GET_FARVAR(seg, info->cursor_type)); ! 312: int i; ! 313: for (i = 0; i < 8; i++) ! 314: SET_BDA(cursor_pos[i], GET_FARVAR(seg, info->cursor_pos[i])); ! 315: SET_BDA(video_pagestart, GET_FARVAR(seg, info->video_pagestart)); ! 316: SET_BDA(video_page, GET_FARVAR(seg, info->video_page)); ! 317: /* current font */ ! 318: SET_IVT(0x1f, GET_FARVAR(seg, info->font0)); ! 319: SET_IVT(0x43, GET_FARVAR(seg, info->font1)); ! 320: } ! 321: ! 322: ! 323: /**************************************************************** ! 324: * Mode setting ! 325: ****************************************************************/ ! 326: ! 327: struct vgamode_s * ! 328: get_current_mode(void) ! 329: { ! 330: return vgahw_find_mode(GET_BDA(vbe_mode) & ~MF_VBEFLAGS); ! 331: } ! 332: ! 333: // Setup BDA after a mode switch. ! 334: int ! 335: vga_set_mode(int mode, int flags) ! 336: { ! 337: dprintf(1, "set VGA mode %x\n", mode); ! 338: struct vgamode_s *vmode_g = vgahw_find_mode(mode); ! 339: if (!vmode_g) ! 340: return VBE_RETURN_STATUS_FAILED; ! 341: ! 342: int ret = vgahw_set_mode(vmode_g, flags); ! 343: if (ret) ! 344: return ret; ! 345: ! 346: // Set the BIOS mem ! 347: int width = GET_GLOBAL(vmode_g->width); ! 348: int height = GET_GLOBAL(vmode_g->height); ! 349: u8 memmodel = GET_GLOBAL(vmode_g->memmodel); ! 350: int cheight = GET_GLOBAL(vmode_g->cheight); ! 351: if (mode < 0x100) ! 352: SET_BDA(video_mode, mode); ! 353: else ! 354: SET_BDA(video_mode, 0xff); ! 355: SET_BDA(vbe_mode, mode | (flags & MF_VBEFLAGS)); ! 356: if (memmodel == MM_TEXT) { ! 357: SET_BDA(video_cols, width); ! 358: SET_BDA(video_rows, height-1); ! 359: SET_BDA(cursor_type, 0x0607); ! 360: } else { ! 361: int cwidth = GET_GLOBAL(vmode_g->cwidth); ! 362: SET_BDA(video_cols, width / cwidth); ! 363: SET_BDA(video_rows, (height / cheight) - 1); ! 364: SET_BDA(cursor_type, 0x0000); ! 365: } ! 366: SET_BDA(video_pagesize, calc_page_size(memmodel, width, height)); ! 367: SET_BDA(crtc_address, stdvga_get_crtc()); ! 368: SET_BDA(char_height, cheight); ! 369: SET_BDA(video_ctl, 0x60 | (flags & MF_NOCLEARMEM ? 0x80 : 0x00)); ! 370: SET_BDA(video_switches, 0xF9); ! 371: SET_BDA(modeset_ctl, GET_BDA(modeset_ctl) & 0x7f); ! 372: int i; ! 373: for (i=0; i<8; i++) ! 374: SET_BDA(cursor_pos[i], 0x0000); ! 375: SET_BDA(video_pagestart, 0x0000); ! 376: SET_BDA(video_page, 0x00); ! 377: ! 378: // FIXME We nearly have the good tables. to be reworked ! 379: SET_BDA(dcc_index, 0x08); // 8 is VGA should be ok for now ! 380: SET_BDA(video_savetable ! 381: , SEGOFF(get_global_seg(), (u32)&video_save_pointer_table)); ! 382: ! 383: // FIXME ! 384: SET_BDA(video_msr, 0x00); // Unavailable on vanilla vga, but... ! 385: SET_BDA(video_pal, 0x00); // Unavailable on vanilla vga, but... ! 386: ! 387: // Set the ints 0x1F and 0x43 ! 388: SET_IVT(0x1f, SEGOFF(get_global_seg(), (u32)&vgafont8[128 * 8])); ! 389: ! 390: switch (cheight) { ! 391: case 8: ! 392: SET_IVT(0x43, SEGOFF(get_global_seg(), (u32)vgafont8)); ! 393: break; ! 394: case 14: ! 395: SET_IVT(0x43, SEGOFF(get_global_seg(), (u32)vgafont14)); ! 396: break; ! 397: case 16: ! 398: SET_IVT(0x43, SEGOFF(get_global_seg(), (u32)vgafont16)); ! 399: break; ! 400: } ! 401: ! 402: return 0; ! 403: } ! 404: ! 405: ! 406: /**************************************************************** ! 407: * VGA int 10 handler ! 408: ****************************************************************/ ! 409: ! 410: static void ! 411: handle_1000(struct bregs *regs) ! 412: { ! 413: int mode = regs->al & 0x7f; ! 414: ! 415: // Set regs->al ! 416: if (mode > 7) ! 417: regs->al = 0x20; ! 418: else if (mode == 6) ! 419: regs->al = 0x3f; ! 420: else ! 421: regs->al = 0x30; ! 422: ! 423: int flags = GET_BDA(modeset_ctl) & (MF_NOPALETTE|MF_GRAYSUM); ! 424: if (regs->al & 0x80) ! 425: flags |= MF_NOCLEARMEM; ! 426: ! 427: vga_set_mode(mode, flags); ! 428: } ! 429: ! 430: static void ! 431: handle_1001(struct bregs *regs) ! 432: { ! 433: set_cursor_shape(regs->ch, regs->cl); ! 434: } ! 435: ! 436: static void ! 437: handle_1002(struct bregs *regs) ! 438: { ! 439: struct cursorpos cp = {regs->dl, regs->dh, regs->bh}; ! 440: set_cursor_pos(cp); ! 441: } ! 442: ! 443: static void ! 444: handle_1003(struct bregs *regs) ! 445: { ! 446: regs->cx = get_cursor_shape(regs->bh); ! 447: struct cursorpos cp = get_cursor_pos(regs->bh); ! 448: regs->dl = cp.x; ! 449: regs->dh = cp.y; ! 450: } ! 451: ! 452: // Read light pen pos (unimplemented) ! 453: static void ! 454: handle_1004(struct bregs *regs) ! 455: { ! 456: debug_stub(regs); ! 457: regs->ax = regs->bx = regs->cx = regs->dx = 0; ! 458: } ! 459: ! 460: static void ! 461: handle_1005(struct bregs *regs) ! 462: { ! 463: set_active_page(regs->al); ! 464: } ! 465: ! 466: static void ! 467: verify_scroll(struct bregs *regs, int dir) ! 468: { ! 469: u8 ulx = regs->cl, uly = regs->ch, lrx = regs->dl, lry = regs->dh; ! 470: u16 nbrows = GET_BDA(video_rows) + 1; ! 471: if (lry >= nbrows) ! 472: lry = nbrows - 1; ! 473: u16 nbcols = GET_BDA(video_cols); ! 474: if (lrx >= nbcols) ! 475: lrx = nbcols - 1; ! 476: ! 477: if (ulx > lrx || uly > lry) ! 478: return; ! 479: ! 480: int nblines = regs->al; ! 481: if (!nblines || nblines > lry - uly + 1) ! 482: nblines = lry - uly + 1; ! 483: ! 484: u8 page = GET_BDA(video_page); ! 485: struct cursorpos ul = {ulx, uly, page}; ! 486: struct cursorpos lr = {lrx, lry, page}; ! 487: vgafb_scroll(dir * nblines, regs->bh, ul, lr); ! 488: } ! 489: ! 490: static void ! 491: handle_1006(struct bregs *regs) ! 492: { ! 493: verify_scroll(regs, 1); ! 494: } ! 495: ! 496: static void ! 497: handle_1007(struct bregs *regs) ! 498: { ! 499: verify_scroll(regs, -1); ! 500: } ! 501: ! 502: static void ! 503: handle_1008(struct bregs *regs) ! 504: { ! 505: struct carattr ca = vgafb_read_char(get_cursor_pos(regs->bh)); ! 506: regs->al = ca.car; ! 507: regs->ah = ca.attr; ! 508: } ! 509: ! 510: static void noinline ! 511: write_chars(u8 page, struct carattr ca, u16 count) ! 512: { ! 513: u16 nbcols = GET_BDA(video_cols); ! 514: struct cursorpos cp = get_cursor_pos(page); ! 515: while (count--) { ! 516: vgafb_write_char(cp, ca); ! 517: cp.x++; ! 518: if (cp.x >= nbcols) { ! 519: cp.x -= nbcols; ! 520: cp.y++; ! 521: } ! 522: } ! 523: } ! 524: ! 525: static void ! 526: handle_1009(struct bregs *regs) ! 527: { ! 528: struct carattr ca = {regs->al, regs->bl, 1}; ! 529: write_chars(regs->bh, ca, regs->cx); ! 530: } ! 531: ! 532: static void ! 533: handle_100a(struct bregs *regs) ! 534: { ! 535: struct carattr ca = {regs->al, regs->bl, 0}; ! 536: write_chars(regs->bh, ca, regs->cx); ! 537: } ! 538: ! 539: ! 540: static void ! 541: handle_100b00(struct bregs *regs) ! 542: { ! 543: stdvga_set_border_color(regs->bl); ! 544: } ! 545: ! 546: static void ! 547: handle_100b01(struct bregs *regs) ! 548: { ! 549: stdvga_set_palette(regs->bl); ! 550: } ! 551: ! 552: static void ! 553: handle_100bXX(struct bregs *regs) ! 554: { ! 555: debug_stub(regs); ! 556: } ! 557: ! 558: static void ! 559: handle_100b(struct bregs *regs) ! 560: { ! 561: switch (regs->bh) { ! 562: case 0x00: handle_100b00(regs); break; ! 563: case 0x01: handle_100b01(regs); break; ! 564: default: handle_100bXX(regs); break; ! 565: } ! 566: } ! 567: ! 568: ! 569: static void ! 570: handle_100c(struct bregs *regs) ! 571: { ! 572: // XXX - page (regs->bh) is unused ! 573: vgafb_write_pixel(regs->al, regs->cx, regs->dx); ! 574: } ! 575: ! 576: static void ! 577: handle_100d(struct bregs *regs) ! 578: { ! 579: // XXX - page (regs->bh) is unused ! 580: regs->al = vgafb_read_pixel(regs->cx, regs->dx); ! 581: } ! 582: ! 583: static void noinline ! 584: handle_100e(struct bregs *regs) ! 585: { ! 586: // Ralf Brown Interrupt list is WRONG on bh(page) ! 587: // We do output only on the current page ! ! 588: struct carattr ca = {regs->al, regs->bl, 0}; ! 589: struct cursorpos cp = get_cursor_pos(0xff); ! 590: write_teletype(&cp, ca); ! 591: set_cursor_pos(cp); ! 592: } ! 593: ! 594: static void ! 595: handle_100f(struct bregs *regs) ! 596: { ! 597: regs->bh = GET_BDA(video_page); ! 598: regs->al = GET_BDA(video_mode) | (GET_BDA(video_ctl) & 0x80); ! 599: regs->ah = GET_BDA(video_cols); ! 600: } ! 601: ! 602: ! 603: static void ! 604: handle_101000(struct bregs *regs) ! 605: { ! 606: if (regs->bl > 0x14) ! 607: return; ! 608: stdvga_attr_write(regs->bl, regs->bh); ! 609: } ! 610: ! 611: static void ! 612: handle_101001(struct bregs *regs) ! 613: { ! 614: stdvga_set_overscan_border_color(regs->bh); ! 615: } ! 616: ! 617: static void ! 618: handle_101002(struct bregs *regs) ! 619: { ! 620: stdvga_set_all_palette_reg(regs->es, (u8*)(regs->dx + 0)); ! 621: } ! 622: ! 623: static void ! 624: handle_101003(struct bregs *regs) ! 625: { ! 626: stdvga_toggle_intensity(regs->bl); ! 627: } ! 628: ! 629: static void ! 630: handle_101007(struct bregs *regs) ! 631: { ! 632: if (regs->bl > 0x14) ! 633: return; ! 634: regs->bh = stdvga_attr_read(regs->bl); ! 635: } ! 636: ! 637: static void ! 638: handle_101008(struct bregs *regs) ! 639: { ! 640: regs->bh = stdvga_get_overscan_border_color(); ! 641: } ! 642: ! 643: static void ! 644: handle_101009(struct bregs *regs) ! 645: { ! 646: stdvga_get_all_palette_reg(regs->es, (u8*)(regs->dx + 0)); ! 647: } ! 648: ! 649: static void noinline ! 650: handle_101010(struct bregs *regs) ! 651: { ! 652: u8 rgb[3] = {regs->dh, regs->ch, regs->cl}; ! 653: stdvga_dac_write(GET_SEG(SS), rgb, regs->bx, 1); ! 654: } ! 655: ! 656: static void ! 657: handle_101012(struct bregs *regs) ! 658: { ! 659: stdvga_dac_write(regs->es, (u8*)(regs->dx + 0), regs->bx, regs->cx); ! 660: } ! 661: ! 662: static void ! 663: handle_101013(struct bregs *regs) ! 664: { ! 665: stdvga_select_video_dac_color_page(regs->bl, regs->bh); ! 666: } ! 667: ! 668: static void noinline ! 669: handle_101015(struct bregs *regs) ! 670: { ! 671: u8 rgb[3]; ! 672: stdvga_dac_read(GET_SEG(SS), rgb, regs->bx, 1); ! 673: regs->dh = rgb[0]; ! 674: regs->ch = rgb[1]; ! 675: regs->cl = rgb[2]; ! 676: } ! 677: ! 678: static void ! 679: handle_101017(struct bregs *regs) ! 680: { ! 681: stdvga_dac_read(regs->es, (u8*)(regs->dx + 0), regs->bx, regs->cx); ! 682: } ! 683: ! 684: static void ! 685: handle_101018(struct bregs *regs) ! 686: { ! 687: stdvga_pelmask_write(regs->bl); ! 688: } ! 689: ! 690: static void ! 691: handle_101019(struct bregs *regs) ! 692: { ! 693: regs->bl = stdvga_pelmask_read(); ! 694: } ! 695: ! 696: static void ! 697: handle_10101a(struct bregs *regs) ! 698: { ! 699: stdvga_read_video_dac_state(®s->bl, ®s->bh); ! 700: } ! 701: ! 702: static void ! 703: handle_10101b(struct bregs *regs) ! 704: { ! 705: stdvga_perform_gray_scale_summing(regs->bx, regs->cx); ! 706: } ! 707: ! 708: static void ! 709: handle_1010XX(struct bregs *regs) ! 710: { ! 711: debug_stub(regs); ! 712: } ! 713: ! 714: static void ! 715: handle_1010(struct bregs *regs) ! 716: { ! 717: switch (regs->al) { ! 718: case 0x00: handle_101000(regs); break; ! 719: case 0x01: handle_101001(regs); break; ! 720: case 0x02: handle_101002(regs); break; ! 721: case 0x03: handle_101003(regs); break; ! 722: case 0x07: handle_101007(regs); break; ! 723: case 0x08: handle_101008(regs); break; ! 724: case 0x09: handle_101009(regs); break; ! 725: case 0x10: handle_101010(regs); break; ! 726: case 0x12: handle_101012(regs); break; ! 727: case 0x13: handle_101013(regs); break; ! 728: case 0x15: handle_101015(regs); break; ! 729: case 0x17: handle_101017(regs); break; ! 730: case 0x18: handle_101018(regs); break; ! 731: case 0x19: handle_101019(regs); break; ! 732: case 0x1a: handle_10101a(regs); break; ! 733: case 0x1b: handle_10101b(regs); break; ! 734: default: handle_1010XX(regs); break; ! 735: } ! 736: } ! 737: ! 738: ! 739: static void ! 740: handle_101100(struct bregs *regs) ! 741: { ! 742: stdvga_load_font(regs->es, (void*)(regs->bp+0), regs->cx ! 743: , regs->dx, regs->bl, regs->bh); ! 744: } ! 745: ! 746: static void ! 747: handle_101101(struct bregs *regs) ! 748: { ! 749: stdvga_load_font(get_global_seg(), vgafont14, 0x100, 0, regs->bl, 14); ! 750: } ! 751: ! 752: static void ! 753: handle_101102(struct bregs *regs) ! 754: { ! 755: stdvga_load_font(get_global_seg(), vgafont8, 0x100, 0, regs->bl, 8); ! 756: } ! 757: ! 758: static void ! 759: handle_101103(struct bregs *regs) ! 760: { ! 761: stdvga_set_text_block_specifier(regs->bl); ! 762: } ! 763: ! 764: static void ! 765: handle_101104(struct bregs *regs) ! 766: { ! 767: stdvga_load_font(get_global_seg(), vgafont16, 0x100, 0, regs->bl, 16); ! 768: } ! 769: ! 770: static void ! 771: handle_101110(struct bregs *regs) ! 772: { ! 773: stdvga_load_font(regs->es, (void*)(regs->bp+0), regs->cx ! 774: , regs->dx, regs->bl, regs->bh); ! 775: set_scan_lines(regs->bh); ! 776: } ! 777: ! 778: static void ! 779: handle_101111(struct bregs *regs) ! 780: { ! 781: stdvga_load_font(get_global_seg(), vgafont14, 0x100, 0, regs->bl, 14); ! 782: set_scan_lines(14); ! 783: } ! 784: ! 785: static void ! 786: handle_101112(struct bregs *regs) ! 787: { ! 788: stdvga_load_font(get_global_seg(), vgafont8, 0x100, 0, regs->bl, 8); ! 789: set_scan_lines(8); ! 790: } ! 791: ! 792: static void ! 793: handle_101114(struct bregs *regs) ! 794: { ! 795: stdvga_load_font(get_global_seg(), vgafont16, 0x100, 0, regs->bl, 16); ! 796: set_scan_lines(16); ! 797: } ! 798: ! 799: static void ! 800: handle_101130(struct bregs *regs) ! 801: { ! 802: switch (regs->bh) { ! 803: case 0x00: { ! 804: struct segoff_s so = GET_IVT(0x1f); ! 805: regs->es = so.seg; ! 806: regs->bp = so.offset; ! 807: break; ! 808: } ! 809: case 0x01: { ! 810: struct segoff_s so = GET_IVT(0x43); ! 811: regs->es = so.seg; ! 812: regs->bp = so.offset; ! 813: break; ! 814: } ! 815: case 0x02: ! 816: regs->es = get_global_seg(); ! 817: regs->bp = (u32)vgafont14; ! 818: break; ! 819: case 0x03: ! 820: regs->es = get_global_seg(); ! 821: regs->bp = (u32)vgafont8; ! 822: break; ! 823: case 0x04: ! 824: regs->es = get_global_seg(); ! 825: regs->bp = (u32)vgafont8 + 128 * 8; ! 826: break; ! 827: case 0x05: ! 828: regs->es = get_global_seg(); ! 829: regs->bp = (u32)vgafont14alt; ! 830: break; ! 831: case 0x06: ! 832: regs->es = get_global_seg(); ! 833: regs->bp = (u32)vgafont16; ! 834: break; ! 835: case 0x07: ! 836: regs->es = get_global_seg(); ! 837: regs->bp = (u32)vgafont16alt; ! 838: break; ! 839: default: ! 840: dprintf(1, "Get font info BH(%02x) was discarded\n", regs->bh); ! 841: return; ! 842: } ! 843: // Set byte/char of on screen font ! 844: regs->cx = GET_BDA(char_height) & 0xff; ! 845: ! 846: // Set Highest char row ! 847: regs->dl = GET_BDA(video_rows); ! 848: } ! 849: ! 850: static void ! 851: handle_1011XX(struct bregs *regs) ! 852: { ! 853: debug_stub(regs); ! 854: } ! 855: ! 856: static void ! 857: handle_1011(struct bregs *regs) ! 858: { ! 859: switch (regs->al) { ! 860: case 0x00: handle_101100(regs); break; ! 861: case 0x01: handle_101101(regs); break; ! 862: case 0x02: handle_101102(regs); break; ! 863: case 0x03: handle_101103(regs); break; ! 864: case 0x04: handle_101104(regs); break; ! 865: case 0x10: handle_101110(regs); break; ! 866: case 0x11: handle_101111(regs); break; ! 867: case 0x12: handle_101112(regs); break; ! 868: case 0x14: handle_101114(regs); break; ! 869: case 0x30: handle_101130(regs); break; ! 870: default: handle_1011XX(regs); break; ! 871: } ! 872: } ! 873: ! 874: ! 875: static void ! 876: handle_101210(struct bregs *regs) ! 877: { ! 878: u16 crtc_addr = GET_BDA(crtc_address); ! 879: if (crtc_addr == VGAREG_MDA_CRTC_ADDRESS) ! 880: regs->bx = 0x0103; ! 881: else ! 882: regs->bx = 0x0003; ! 883: regs->cx = GET_BDA(video_switches) & 0x0f; ! 884: } ! 885: ! 886: static void ! 887: handle_101230(struct bregs *regs) ! 888: { ! 889: u8 mctl = GET_BDA(modeset_ctl); ! 890: u8 vswt = GET_BDA(video_switches); ! 891: switch (regs->al) { ! 892: case 0x00: ! 893: // 200 lines ! 894: mctl = (mctl & ~0x10) | 0x80; ! 895: vswt = (vswt & ~0x0f) | 0x08; ! 896: break; ! 897: case 0x01: ! 898: // 350 lines ! 899: mctl &= ~0x90; ! 900: vswt = (vswt & ~0x0f) | 0x09; ! 901: break; ! 902: case 0x02: ! 903: // 400 lines ! 904: mctl = (mctl & ~0x80) | 0x10; ! 905: vswt = (vswt & ~0x0f) | 0x09; ! 906: break; ! 907: default: ! 908: dprintf(1, "Select vert res (%02x) was discarded\n", regs->al); ! 909: break; ! 910: } ! 911: SET_BDA(modeset_ctl, mctl); ! 912: SET_BDA(video_switches, vswt); ! 913: regs->al = 0x12; ! 914: } ! 915: ! 916: static void ! 917: handle_101231(struct bregs *regs) ! 918: { ! 919: u8 v = (regs->al & 0x01) << 3; ! 920: u8 mctl = GET_BDA(video_ctl) & ~0x08; ! 921: SET_BDA(video_ctl, mctl | v); ! 922: regs->al = 0x12; ! 923: } ! 924: ! 925: static void ! 926: handle_101232(struct bregs *regs) ! 927: { ! 928: stdvga_enable_video_addressing(regs->al); ! 929: regs->al = 0x12; ! 930: } ! 931: ! 932: static void ! 933: handle_101233(struct bregs *regs) ! 934: { ! 935: u8 v = ((regs->al << 1) & 0x02) ^ 0x02; ! 936: u8 v2 = GET_BDA(modeset_ctl) & ~0x02; ! 937: SET_BDA(modeset_ctl, v | v2); ! 938: regs->al = 0x12; ! 939: } ! 940: ! 941: static void ! 942: handle_101234(struct bregs *regs) ! 943: { ! 944: u8 v = (regs->al & 0x01) ^ 0x01; ! 945: u8 v2 = GET_BDA(modeset_ctl) & ~0x01; ! 946: SET_BDA(modeset_ctl, v | v2); ! 947: regs->al = 0x12; ! 948: } ! 949: ! 950: static void ! 951: handle_101235(struct bregs *regs) ! 952: { ! 953: debug_stub(regs); ! 954: regs->al = 0x12; ! 955: } ! 956: ! 957: static void ! 958: handle_101236(struct bregs *regs) ! 959: { ! 960: debug_stub(regs); ! 961: regs->al = 0x12; ! 962: } ! 963: ! 964: static void ! 965: handle_1012XX(struct bregs *regs) ! 966: { ! 967: debug_stub(regs); ! 968: } ! 969: ! 970: static void ! 971: handle_1012(struct bregs *regs) ! 972: { ! 973: if (CONFIG_VGA_CIRRUS && regs->bl >= 0x80) { ! 974: clext_1012(regs); ! 975: return; ! 976: } ! 977: ! 978: switch (regs->bl) { ! 979: case 0x10: handle_101210(regs); break; ! 980: case 0x30: handle_101230(regs); break; ! 981: case 0x31: handle_101231(regs); break; ! 982: case 0x32: handle_101232(regs); break; ! 983: case 0x33: handle_101233(regs); break; ! 984: case 0x34: handle_101234(regs); break; ! 985: case 0x35: handle_101235(regs); break; ! 986: case 0x36: handle_101236(regs); break; ! 987: default: handle_1012XX(regs); break; ! 988: } ! 989: } ! 990: ! 991: ! 992: // Write string ! 993: static void noinline ! 994: handle_1013(struct bregs *regs) ! 995: { ! 996: struct cursorpos cp; ! 997: if (regs->dh == 0xff) ! 998: // if row=0xff special case : use current cursor position ! 999: cp = get_cursor_pos(regs->bh); ! 1000: else ! 1001: cp = (struct cursorpos) {regs->dl, regs->dh, regs->bh}; ! 1002: ! 1003: u16 count = regs->cx; ! 1004: u8 *offset_far = (void*)(regs->bp + 0); ! 1005: u8 attr = regs->bl; ! 1006: while (count--) { ! 1007: u8 car = GET_FARVAR(regs->es, *offset_far); ! 1008: offset_far++; ! 1009: if (regs->al & 2) { ! 1010: attr = GET_FARVAR(regs->es, *offset_far); ! 1011: offset_far++; ! 1012: } ! 1013: ! 1014: struct carattr ca = {car, attr, 1}; ! 1015: write_teletype(&cp, ca); ! 1016: } ! 1017: ! 1018: if (regs->al & 1) ! 1019: set_cursor_pos(cp); ! 1020: } ! 1021: ! 1022: ! 1023: static void ! 1024: handle_101a00(struct bregs *regs) ! 1025: { ! 1026: regs->bx = GET_BDA(dcc_index); ! 1027: regs->al = 0x1a; ! 1028: } ! 1029: ! 1030: static void ! 1031: handle_101a01(struct bregs *regs) ! 1032: { ! 1033: SET_BDA(dcc_index, regs->bl); ! 1034: dprintf(1, "Alternate Display code (%02x) was discarded\n", regs->bh); ! 1035: regs->al = 0x1a; ! 1036: } ! 1037: ! 1038: static void ! 1039: handle_101aXX(struct bregs *regs) ! 1040: { ! 1041: debug_stub(regs); ! 1042: } ! 1043: ! 1044: static void ! 1045: handle_101a(struct bregs *regs) ! 1046: { ! 1047: switch (regs->al) { ! 1048: case 0x00: handle_101a00(regs); break; ! 1049: case 0x01: handle_101a01(regs); break; ! 1050: default: handle_101aXX(regs); break; ! 1051: } ! 1052: } ! 1053: ! 1054: ! 1055: static u8 static_functionality[0x10] VAR16 = { ! 1056: /* 0 */ 0xff, // All modes supported #1 ! 1057: /* 1 */ 0xe0, // All modes supported #2 ! 1058: /* 2 */ 0x0f, // All modes supported #3 ! 1059: /* 3 */ 0x00, 0x00, 0x00, 0x00, // reserved ! 1060: /* 7 */ 0x07, // 200, 350, 400 scan lines ! 1061: /* 8 */ 0x02, // mamimum number of visible charsets in text mode ! 1062: /* 9 */ 0x08, // total number of charset blocks in text mode ! 1063: /* a */ 0xe7, // Change to add new functions ! 1064: /* b */ 0x0c, // Change to add new functions ! 1065: /* c */ 0x00, // reserved ! 1066: /* d */ 0x00, // reserved ! 1067: /* e */ 0x00, // Change to add new functions ! 1068: /* f */ 0x00 // reserved ! 1069: }; ! 1070: ! 1071: struct funcInfo { ! 1072: struct segoff_s static_functionality; ! 1073: u8 bda_0x49[30]; ! 1074: u8 bda_0x84[3]; ! 1075: u8 dcc_index; ! 1076: u8 dcc_alt; ! 1077: u16 colors; ! 1078: u8 pages; ! 1079: u8 scan_lines; ! 1080: u8 primary_char; ! 1081: u8 secondar_char; ! 1082: u8 misc; ! 1083: u8 non_vga_mode; ! 1084: u8 reserved_2f[2]; ! 1085: u8 video_mem; ! 1086: u8 save_flags; ! 1087: u8 disp_info; ! 1088: u8 reserved_34[12]; ! 1089: }; ! 1090: ! 1091: static void ! 1092: handle_101b(struct bregs *regs) ! 1093: { ! 1094: u16 seg = regs->es; ! 1095: struct funcInfo *info = (void*)(regs->di+0); ! 1096: memset_far(seg, info, 0, sizeof(*info)); ! 1097: // Address of static functionality table ! 1098: SET_FARVAR(seg, info->static_functionality ! 1099: , SEGOFF(get_global_seg(), (u32)static_functionality)); ! 1100: ! 1101: // Hard coded copy from BIOS area. Should it be cleaner ? ! 1102: memcpy_far(seg, info->bda_0x49, SEG_BDA, (void*)0x49 ! 1103: , sizeof(info->bda_0x49)); ! 1104: memcpy_far(seg, info->bda_0x84, SEG_BDA, (void*)0x84 ! 1105: , sizeof(info->bda_0x84)); ! 1106: ! 1107: SET_FARVAR(seg, info->dcc_index, GET_BDA(dcc_index)); ! 1108: SET_FARVAR(seg, info->colors, 16); ! 1109: SET_FARVAR(seg, info->pages, 8); ! 1110: SET_FARVAR(seg, info->scan_lines, 2); ! 1111: SET_FARVAR(seg, info->video_mem, 3); ! 1112: regs->al = 0x1B; ! 1113: } ! 1114: ! 1115: ! 1116: static void ! 1117: handle_101c(struct bregs *regs) ! 1118: { ! 1119: u16 seg = regs->es; ! 1120: void *data = (void*)(regs->bx+0); ! 1121: u16 states = regs->cx; ! 1122: if (states & ~0x07) ! 1123: goto fail; ! 1124: int ret; ! 1125: switch (regs->al) { ! 1126: case 0x00: ! 1127: ret = vgahw_size_state(states); ! 1128: if (ret < 0) ! 1129: goto fail; ! 1130: regs->bx = ret / 64; ! 1131: break; ! 1132: case 0x01: ! 1133: ret = vgahw_save_state(seg, data, states); ! 1134: if (ret) ! 1135: goto fail; ! 1136: break; ! 1137: case 0x02: ! 1138: ret = vgahw_restore_state(seg, data, states); ! 1139: if (ret) ! 1140: goto fail; ! 1141: break; ! 1142: default: ! 1143: goto fail; ! 1144: } ! 1145: regs->al = 0x1c; ! 1146: fail: ! 1147: return; ! 1148: } ! 1149: ! 1150: static void ! 1151: handle_10XX(struct bregs *regs) ! 1152: { ! 1153: debug_stub(regs); ! 1154: } ! 1155: ! 1156: // INT 10h Video Support Service Entry Point ! 1157: void VISIBLE16 ! 1158: handle_10(struct bregs *regs) ! 1159: { ! 1160: debug_enter(regs, DEBUG_VGA_10); ! 1161: switch (regs->ah) { ! 1162: case 0x00: handle_1000(regs); break; ! 1163: case 0x01: handle_1001(regs); break; ! 1164: case 0x02: handle_1002(regs); break; ! 1165: case 0x03: handle_1003(regs); break; ! 1166: case 0x04: handle_1004(regs); break; ! 1167: case 0x05: handle_1005(regs); break; ! 1168: case 0x06: handle_1006(regs); break; ! 1169: case 0x07: handle_1007(regs); break; ! 1170: case 0x08: handle_1008(regs); break; ! 1171: case 0x09: handle_1009(regs); break; ! 1172: case 0x0a: handle_100a(regs); break; ! 1173: case 0x0b: handle_100b(regs); break; ! 1174: case 0x0c: handle_100c(regs); break; ! 1175: case 0x0d: handle_100d(regs); break; ! 1176: case 0x0e: handle_100e(regs); break; ! 1177: case 0x0f: handle_100f(regs); break; ! 1178: case 0x10: handle_1010(regs); break; ! 1179: case 0x11: handle_1011(regs); break; ! 1180: case 0x12: handle_1012(regs); break; ! 1181: case 0x13: handle_1013(regs); break; ! 1182: case 0x1a: handle_101a(regs); break; ! 1183: case 0x1b: handle_101b(regs); break; ! 1184: case 0x1c: handle_101c(regs); break; ! 1185: case 0x4f: handle_104f(regs); break; ! 1186: default: handle_10XX(regs); break; ! 1187: } ! 1188: } ! 1189: ! 1190: ! 1191: /**************************************************************** ! 1192: * VGA post ! 1193: ****************************************************************/ ! 1194: ! 1195: static void ! 1196: init_bios_area(void) ! 1197: { ! 1198: // init detected hardware BIOS Area ! 1199: // set 80x25 color (not clear from RBIL but usual) ! 1200: u16 eqf = GET_BDA(equipment_list_flags); ! 1201: SET_BDA(equipment_list_flags, (eqf & 0xffcf) | 0x20); ! 1202: ! 1203: // Just for the first int10 find its children ! 1204: ! 1205: // the default char height ! 1206: SET_BDA(char_height, 0x10); ! 1207: ! 1208: // Clear the screen ! 1209: SET_BDA(video_ctl, 0x60); ! 1210: ! 1211: // Set the basic screen we have ! 1212: SET_BDA(video_switches, 0xf9); ! 1213: ! 1214: // Set the basic modeset options ! 1215: SET_BDA(modeset_ctl, 0x51); ! 1216: ! 1217: // Set the default MSR ! 1218: SET_BDA(video_msr, 0x09); ! 1219: } ! 1220: ! 1221: int VgaBDF VAR16 = -1; ! 1222: int HaveRunInit VAR16; ! 1223: ! 1224: void VISIBLE16 ! 1225: vga_post(struct bregs *regs) ! 1226: { ! 1227: debug_serial_setup(); ! 1228: dprintf(1, "Start SeaVGABIOS (version %s)\n", VERSION); ! 1229: debug_enter(regs, DEBUG_VGA_POST); ! 1230: ! 1231: if (CONFIG_VGA_PCI && !GET_GLOBAL(HaveRunInit)) { ! 1232: u16 bdf = regs->ax; ! 1233: if ((pci_config_readw(bdf, PCI_VENDOR_ID) ! 1234: == GET_GLOBAL(rom_pci_data.vendor)) ! 1235: && (pci_config_readw(bdf, PCI_DEVICE_ID) ! 1236: == GET_GLOBAL(rom_pci_data.device))) ! 1237: SET_VGA(VgaBDF, bdf); ! 1238: } ! 1239: ! 1240: int ret = vgahw_init(); ! 1241: if (ret) { ! 1242: dprintf(1, "Failed to initialize VGA hardware. Exiting.\n"); ! 1243: return; ! 1244: } ! 1245: ! 1246: if (GET_GLOBAL(HaveRunInit)) ! 1247: return; ! 1248: ! 1249: init_bios_area(); ! 1250: ! 1251: SET_VGA(video_save_pointer_table.videoparam ! 1252: , SEGOFF(get_global_seg(), (u32)video_param_table)); ! 1253: stdvga_build_video_param(); ! 1254: ! 1255: extern void entry_10(void); ! 1256: SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10)); ! 1257: ! 1258: SET_VGA(HaveRunInit, 1); ! 1259: ! 1260: // Fixup checksum ! 1261: extern u8 _rom_header_size, _rom_header_checksum; ! 1262: SET_VGA(_rom_header_checksum, 0); ! 1263: u8 sum = -checksum_far(get_global_seg(), 0, ! 1264: GET_GLOBAL(_rom_header_size) * 512); ! 1265: SET_VGA(_rom_header_checksum, sum); ! 1266: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.