1 // ============================================================================================ 2 /* 3 * vgabios.c 4 */ 5 // ============================================================================================ 6 // 7 // Copyright (C) 2001-2008 the LGPL VGABios developers Team 8 // 9 // This library is free software; you can redistribute it and/or 10 // modify it under the terms of the GNU Lesser General Public 11 // License as published by the Free Software Foundation; either 12 // version 2 of the License, or (at your option) any later version. 13 // 14 // This library is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 // Lesser General Public License for more details. 18 // 19 // You should have received a copy of the GNU Lesser General Public 20 // License along with this library; if not, write to the Free Software 21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 // 23 // ============================================================================================ 24 // 25 // This VGA Bios is specific to the plex86/bochs Emulated VGA card. 26 // You can NOT drive any physical vga card with it. 27 // 28 // ============================================================================================ 29 // 30 // This file contains code ripped from : 31 // - rombios.c of plex86 32 // 33 // This VGA Bios contains fonts from : 34 // - fntcol16.zip (c) by Joseph Gil avalable at : 35 // ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip 36 // These fonts are public domain 37 // 38 // This VGA Bios is based on information taken from : 39 // - Kevin Lawton's vga card emulation for bochs/plex86 40 // - Ralf Brown's interrupts list available at http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html 41 // - Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/ 42 // - Michael Abrash's Graphics Programming Black Book 43 // - Francois Gervais' book "programmation des cartes graphiques cga-ega-vga" edited by sybex 44 // - DOSEMU 1.0.1 source code for several tables values and formulas 45 // 46 // Thanks for patches, comments and ideas to : 47 // - techt (at) pikeonline.net 48 // 49 // ============================================================================================ 50 51 #include "vgabios.h" 52 53 #ifdef VBE 54 #include "vbe.h" 55 #endif 56 57 #define USE_BX_INFO 58 59 /* Declares */ 60 static Bit8u read_byte(); 61 static Bit16u read_word(); 62 static void write_byte(); 63 static void write_word(); 64 static Bit8u inb(); 65 static Bit16u inw(); 66 static void outb(); 67 static void outw(); 68 69 static Bit16u get_SS(); 70 71 // Output 72 static void printf(); 73 static void unimplemented(); 74 static void unknown(); 75 76 static Bit8u find_vga_entry(); 77 78 static void memsetb(); 79 static void memsetw(); 80 static void memcpyb(); 81 static void memcpyw(); 82 83 static void biosfn_set_video_mode(); 84 static void biosfn_set_cursor_shape(); 85 static void biosfn_set_cursor_pos(); 86 static void biosfn_get_cursor_pos(); 87 static void biosfn_set_active_page(); 88 static void biosfn_scroll(); 89 static void biosfn_read_char_attr(); 90 static void biosfn_write_char_attr(); 91 static void biosfn_write_char_only(); 92 static void biosfn_write_pixel(); 93 static void biosfn_read_pixel(); 94 static void biosfn_write_teletype(); 95 static void biosfn_perform_gray_scale_summing(); 96 static void biosfn_load_text_user_pat(); 97 static void biosfn_load_text_8_14_pat(); 98 static void biosfn_load_text_8_8_pat(); 99 static void biosfn_load_text_8_16_pat(); 100 static void biosfn_load_gfx_8_8_chars(); 101 static void biosfn_load_gfx_user_chars(); 102 static void biosfn_load_gfx_8_14_chars(); 103 static void biosfn_load_gfx_8_8_dd_chars(); 104 static void biosfn_load_gfx_8_16_chars(); 105 static void biosfn_get_font_info(); 106 static void biosfn_alternate_prtsc(); 107 static void biosfn_switch_video_interface(); 108 static void biosfn_enable_video_refresh_control(); 109 static void biosfn_write_string(); 110 static void biosfn_read_state_info(); 111 static void biosfn_read_video_state_size(); 112 static Bit16u biosfn_save_video_state(); 113 static Bit16u biosfn_restore_video_state(); 114 extern Bit8u video_save_pointer_table[]; 115 116 // This is for compiling with gcc2 and gcc3 117 #define ASM_START #asm 118 #define ASM_END #endasm 119 120 ASM_START 121 122 MACRO SET_INT_VECTOR 123 push ds 124 xor ax, ax 125 mov ds, ax 126 mov ax, ?3 127 mov ?1*4, ax 128 mov ax, ?2 129 mov ?1*4+2, ax 130 pop ds 131 MEND 132 133 ASM_END 134 135 ASM_START 136 .text 137 .rom 138 .org 0 139 140 use16 386 141 142 vgabios_start: 143 .byte 0x55, 0xaa /* BIOS signature, required for BIOS extensions */ 144 145 .byte 0x40 /* BIOS extension length in units of 512 bytes */ 146 147 148 vgabios_entry_point: 149 150 jmp vgabios_init_func 151 152 #ifdef PCIBIOS 153 .org 0x18 154 .word vgabios_pci_data 155 #endif 156 157 // Info from Bart Oldeman 158 .org 0x1e 159 .ascii "IBM" 160 .byte 0x00 161 162 vgabios_name: 163 .ascii "Plex86/Bochs VGABios" 164 #ifdef PCIBIOS 165 .ascii " (PCI)" 166 #endif 167 .ascii " " 168 .byte 0x00 169 170 vgabios_version: 171 #ifndef VGABIOS_VERS 172 .ascii "current-cvs" 173 #else 174 .ascii VGABIOS_VERS 175 #endif 176 .ascii " " 177 178 vgabios_date: 179 .ascii VGABIOS_DATE 180 .byte 0x0a,0x0d 181 .byte 0x00 182 183 vgabios_copyright: 184 .ascii "(C) 2008 the LGPL VGABios developers Team" 185 .byte 0x0a,0x0d 186 .byte 0x00 187 188 vgabios_license: 189 .ascii "This VGA/VBE Bios is released under the GNU LGPL" 190 .byte 0x0a,0x0d 191 .byte 0x0a,0x0d 192 .byte 0x00 193 194 vgabios_website: 195 .ascii "Please visit :" 196 .byte 0x0a,0x0d 197 ;;.ascii " . http://www.plex86.org" 198 ;;.byte 0x0a,0x0d 199 .ascii " . http://bochs.sourceforge.net" 200 .byte 0x0a,0x0d 201 .ascii " . http://www.nongnu.org/vgabios" 202 .byte 0x0a,0x0d 203 .byte 0x0a,0x0d 204 .byte 0x00 205 206 #ifdef PCIBIOS 207 vgabios_pci_data: 208 .ascii "PCIR" 209 #ifdef CIRRUS 210 .word 0x1013 211 .word 0x00b8 // CLGD5446 212 #else 213 #error "Unknown PCI vendor and device id" 214 #endif 215 .word 0 // reserved 216 .word 0x18 // dlen 217 .byte 0 // revision 218 .byte 0x0 // class,hi: vga display 219 .word 0x300 // class,lo: vga display 220 .word 0x40 // bios size 221 .word 1 // revision 222 .byte 0 // intel x86 data 223 .byte 0x80 // last image 224 .word 0 // reserved 225 #endif 226 227 228 ;; ============================================================================================ 229 ;; 230 ;; Init Entry point 231 ;; 232 ;; ============================================================================================ 233 vgabios_init_func: 234 235 ;; init vga card 236 call init_vga_card 237 238 ;; init basic bios vars 239 call init_bios_area 240 241 #ifdef VBE 242 ;; init vbe functions 243 call vbe_init 244 #endif 245 246 ;; set int10 vect 247 SET_INT_VECTOR(0x10, #0xC000, #vgabios_int10_handler) 248 249 #ifdef CIRRUS 250 call cirrus_init 251 #endif 252 253 ;; display splash screen 254 call _display_splash_screen 255 256 ;; init video mode and clear the screen 257 mov ax,#0x0003 258 int #0x10 259 260 ;; show info 261 call _display_info 262 263 #ifdef VBE 264 ;; show vbe info 265 call vbe_display_info 266 #endif 267 268 #ifdef CIRRUS 269 ;; show cirrus info 270 call cirrus_display_info 271 #endif 272 273 retf 274 ASM_END 275 276 /* 277 * int10 handled here 278 */ 279 ASM_START 280 vgabios_int10_handler: 281 pushf 282 #ifdef DEBUG 283 push es 284 push ds 285 pusha 286 mov bx, #0xc000 287 mov ds, bx 288 call _int10_debugmsg 289 popa 290 pop ds 291 pop es 292 #endif 293 cmp ah, #0x0f 294 jne int10_test_1A 295 call biosfn_get_video_mode 296 jmp int10_end 297 int10_test_1A: 298 cmp ah, #0x1a 299 jne int10_test_0B 300 call biosfn_group_1A 301 jmp int10_end 302 int10_test_0B: 303 cmp ah, #0x0b 304 jne int10_test_1103 305 call biosfn_group_0B 306 jmp int10_end 307 int10_test_1103: 308 cmp ax, #0x1103 309 jne int10_test_12 310 call biosfn_set_text_block_specifier 311 jmp int10_end 312 int10_test_12: 313 cmp ah, #0x12 314 jne int10_test_101B 315 cmp bl, #0x10 316 jne int10_test_BL30 317 call biosfn_get_ega_info 318 jmp int10_end 319 int10_test_BL30: 320 cmp bl, #0x30 321 jne int10_test_BL31 322 call biosfn_select_vert_res 323 jmp int10_end 324 int10_test_BL31: 325 cmp bl, #0x31 326 jne int10_test_BL32 327 call biosfn_enable_default_palette_loading 328 jmp int10_end 329 int10_test_BL32: 330 cmp bl, #0x32 331 jne int10_test_BL33 332 call biosfn_enable_video_addressing 333 jmp int10_end 334 int10_test_BL33: 335 cmp bl, #0x33 336 jne int10_test_BL34 337 call biosfn_enable_grayscale_summing 338 jmp int10_end 339 int10_test_BL34: 340 cmp bl, #0x34 341 jne int10_normal 342 call biosfn_enable_cursor_emulation 343 jmp int10_end 344 int10_test_101B: 345 cmp ax, #0x101b 346 je int10_normal 347 cmp ah, #0x10 348 #ifndef VBE 349 jne int10_normal 350 #else 351 jne int10_test_4F 352 #endif 353 call biosfn_group_10 354 jmp int10_end 355 #ifdef VBE 356 int10_test_4F: 357 cmp ah, #0x4f 358 jne int10_normal 359 cmp al, #0x03 360 jne int10_test_vbe_05 361 call vbe_biosfn_return_current_mode 362 jmp int10_end 363 int10_test_vbe_05: 364 cmp al, #0x05 365 jne int10_test_vbe_06 366 call vbe_biosfn_display_window_control 367 jmp int10_end 368 int10_test_vbe_06: 369 cmp al, #0x06 370 jne int10_test_vbe_07 371 call vbe_biosfn_set_get_logical_scan_line_length 372 jmp int10_end 373 int10_test_vbe_07: 374 cmp al, #0x07 375 jne int10_test_vbe_08 376 call vbe_biosfn_set_get_display_start 377 jmp int10_end 378 int10_test_vbe_08: 379 cmp al, #0x08 380 jne int10_test_vbe_0A 381 call vbe_biosfn_set_get_dac_palette_format 382 jmp int10_end 383 int10_test_vbe_0A: 384 cmp al, #0x0A 385 jne int10_normal 386 call vbe_biosfn_return_protected_mode_interface 387 jmp int10_end 388 #endif 389 390 int10_normal: 391 push es 392 push ds 393 pusha 394 395 ;; We have to set ds to access the right data segment 396 mov bx, #0xc000 397 mov ds, bx 398 call _int10_func 399 400 popa 401 pop ds 402 pop es 403 int10_end: 404 popf 405 iret 406 ASM_END 407 408 #include "vgatables.h" 409 #include "vgafonts.h" 410 411 /* 412 * Boot time harware inits 413 */ 414 ASM_START 415 init_vga_card: 416 ;; switch to color mode and enable CPU access 480 lines 417 mov dx, #0x3C2 418 mov al, #0xC3 419 outb dx,al 420 421 ;; more than 64k 3C4/04 422 mov dx, #0x3C4 423 mov al, #0x04 424 outb dx,al 425 mov dx, #0x3C5 426 mov al, #0x02 427 outb dx,al 428 429 #if defined(USE_BX_INFO) || defined(DEBUG) 430 mov bx, #msg_vga_init 431 push bx 432 call _printf 433 inc sp 434 inc sp 435 #endif 436 ret 437 438 #if defined(USE_BX_INFO) || defined(DEBUG) 439 msg_vga_init: 440 .ascii "VGABios $Id$" 441 .byte 0x0d,0x0a,0x00 442 #endif 443 ASM_END 444 445 // -------------------------------------------------------------------------------------------- 446 /* 447 * Boot time bios area inits 448 */ 449 ASM_START 450 init_bios_area: 451 push ds 452 mov ax, # BIOSMEM_SEG 453 mov ds, ax 454 455 ;; init detected hardware BIOS Area 456 mov bx, # BIOSMEM_INITIAL_MODE 457 mov ax, [bx] 458 and ax, #0xffcf 459 ;; set 80x25 color (not clear from RBIL but usual) 460 or ax, #0x0020 461 mov [bx], ax 462 463 ;; Just for the first int10 find its children 464 465 ;; the default char height 466 mov bx, # BIOSMEM_CHAR_HEIGHT 467 mov al, #0x10 468 mov [bx], al 469 470 ;; Clear the screen 471 mov bx, # BIOSMEM_VIDEO_CTL 472 mov al, #0x60 473 mov [bx], al 474 475 ;; Set the basic screen we have 476 mov bx, # BIOSMEM_SWITCHES 477 mov al, #0xf9 478 mov [bx], al 479 480 ;; Set the basic modeset options 481 mov bx, # BIOSMEM_MODESET_CTL 482 mov al, #0x51 483 mov [bx], al 484 485 ;; Set the default MSR 486 mov bx, # BIOSMEM_CURRENT_MSR 487 mov al, #0x09 488 mov [bx], al 489 490 pop ds 491 ret 492 493 _video_save_pointer_table: 494 .word _video_param_table 495 .word 0xc000 496 497 .word 0 /* XXX: fill it */ 498 .word 0 499 500 .word 0 /* XXX: fill it */ 501 .word 0 502 503 .word 0 /* XXX: fill it */ 504 .word 0 505 506 .word 0 /* XXX: fill it */ 507 .word 0 508 509 .word 0 /* XXX: fill it */ 510 .word 0 511 512 .word 0 /* XXX: fill it */ 513 .word 0 514 515 ASM_END 516 517 // -------------------------------------------------------------------------------------------- 518 /* 519 * Boot time Splash screen 520 */ 521 static void display_splash_screen() 522 { 523 } 524 525 // -------------------------------------------------------------------------------------------- 526 /* 527 * Tell who we are 528 */ 529 530 static void display_info() 531 { 532 ASM_START 533 mov ax,#0xc000 534 mov ds,ax 535 mov si,#vgabios_name 536 call _display_string 537 mov si,#vgabios_version 538 call _display_string 539 540 ;;mov si,#vgabios_copyright 541 ;;call _display_string 542 ;;mov si,#crlf 543 ;;call _display_string 544 545 mov si,#vgabios_license 546 call _display_string 547 mov si,#vgabios_website 548 call _display_string 549 ASM_END 550 } 551 552 static void display_string() 553 { 554 // Get length of string 555 ASM_START 556 mov ax,ds 557 mov es,ax 558 mov di,si 559 xor cx,cx 560 not cx 561 xor al,al 562 cld 563 repne 564 scasb 565 not cx 566 dec cx 567 push cx 568 569 mov ax,#0x0300 570 mov bx,#0x0000 571 int #0x10 572 573 pop cx 574 mov ax,#0x1301 575 mov bx,#0x000b 576 mov bp,si 577 int #0x10 578 ASM_END 579 } 580 581 // -------------------------------------------------------------------------------------------- 582 #ifdef DEBUG 583 static void int10_debugmsg(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS) 584 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS; 585 { 586 // 0E is write char... 587 if(GET_AH()!=0x0E) 588 printf("vgabios call ah%02x al%02x bx%04x cx%04x dx%04x\n",GET_AH(),GET_AL(),BX,CX,DX); 589 } 590 #endif 591 592 // -------------------------------------------------------------------------------------------- 593 /* 594 * int10 main dispatcher 595 */ 596 static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS) 597 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, DS, FLAGS; 598 { 599 600 // BIOS functions 601 switch(GET_AH()) 602 { 603 case 0x00: 604 biosfn_set_video_mode(GET_AL()); 605 switch(GET_AL()&0x7F) 606 {case 6: 607 SET_AL(0x3F); 608 break; 609 case 0: 610 case 1: 611 case 2: 612 case 3: 613 case 4: 614 case 5: 615 case 7: 616 SET_AL(0x30); 617 break; 618 default: 619 SET_AL(0x20); 620 } 621 break; 622 case 0x01: 623 biosfn_set_cursor_shape(GET_CH(),GET_CL()); 624 break; 625 case 0x02: 626 biosfn_set_cursor_pos(GET_BH(),DX); 627 break; 628 case 0x03: 629 biosfn_get_cursor_pos(GET_BH(),&CX,&DX); 630 break; 631 case 0x04: 632 // Read light pen pos (unimplemented) 633 #ifdef DEBUG 634 unimplemented(); 635 #endif 636 AX=0x00; 637 BX=0x00; 638 CX=0x00; 639 DX=0x00; 640 break; 641 case 0x05: 642 biosfn_set_active_page(GET_AL()); 643 break; 644 case 0x06: 645 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_UP); 646 break; 647 case 0x07: 648 biosfn_scroll(GET_AL(),GET_BH(),GET_CH(),GET_CL(),GET_DH(),GET_DL(),0xFF,SCROLL_DOWN); 649 break; 650 case 0x08: 651 biosfn_read_char_attr(GET_BH(),&AX); 652 break; 653 case 0x09: 654 biosfn_write_char_attr(GET_AL(),GET_BH(),GET_BL(),CX); 655 break; 656 case 0x0A: 657 biosfn_write_char_only(GET_AL(),GET_BH(),GET_BL(),CX); 658 break; 659 case 0x0C: 660 biosfn_write_pixel(GET_BH(),GET_AL(),CX,DX); 661 break; 662 case 0x0D: 663 biosfn_read_pixel(GET_BH(),CX,DX,&AX); 664 break; 665 case 0x0E: 666 // Ralf Brown Interrupt list is WRONG on bh(page) 667 // We do output only on the current page ! 668 biosfn_write_teletype(GET_AL(),0xff,GET_BL(),NO_ATTR); 669 break; 670 case 0x10: 671 // All other functions of group AH=0x10 rewritten in assembler 672 biosfn_perform_gray_scale_summing(BX,CX); 673 break; 674 case 0x11: 675 switch(GET_AL()) 676 { 677 case 0x00: 678 case 0x10: 679 biosfn_load_text_user_pat(GET_AL(),ES,BP,CX,DX,GET_BL(),GET_BH()); 680 break; 681 case 0x01: 682 case 0x11: 683 biosfn_load_text_8_14_pat(GET_AL(),GET_BL()); 684 break; 685 case 0x02: 686 case 0x12: 687 biosfn_load_text_8_8_pat(GET_AL(),GET_BL()); 688 break; 689 case 0x04: 690 case 0x14: 691 biosfn_load_text_8_16_pat(GET_AL(),GET_BL()); 692 break; 693 case 0x20: 694 biosfn_load_gfx_8_8_chars(ES,BP); 695 break; 696 case 0x21: 697 biosfn_load_gfx_user_chars(ES,BP,CX,GET_BL(),GET_DL()); 698 break; 699 case 0x22: 700 biosfn_load_gfx_8_14_chars(GET_BL()); 701 break; 702 case 0x23: 703 biosfn_load_gfx_8_8_dd_chars(GET_BL()); 704 break; 705 case 0x24: 706 biosfn_load_gfx_8_16_chars(GET_BL()); 707 break; 708 case 0x30: 709 biosfn_get_font_info(GET_BH(),&ES,&BP,&CX,&DX); 710 break; 711 #ifdef DEBUG 712 default: 713 unknown(); 714 #endif 715 } 716 717 break; 718 case 0x12: 719 switch(GET_BL()) 720 { 721 case 0x20: 722 biosfn_alternate_prtsc(); 723 break; 724 case 0x35: 725 biosfn_switch_video_interface(GET_AL(),ES,DX); 726 SET_AL(0x12); 727 break; 728 case 0x36: 729 biosfn_enable_video_refresh_control(GET_AL()); 730 SET_AL(0x12); 731 break; 732 #ifdef DEBUG 733 default: 734 unknown(); 735 #endif 736 } 737 break; 738 case 0x13: 739 biosfn_write_string(GET_AL(),GET_BH(),GET_BL(),CX,GET_DH(),GET_DL(),ES,BP); 740 break; 741 case 0x1B: 742 biosfn_read_state_info(BX,ES,DI); 743 SET_AL(0x1B); 744 break; 745 case 0x1C: 746 switch(GET_AL()) 747 { 748 case 0x00: 749 biosfn_read_video_state_size(CX,&BX); 750 break; 751 case 0x01: 752 biosfn_save_video_state(CX,ES,BX); 753 break; 754 case 0x02: 755 biosfn_restore_video_state(CX,ES,BX); 756 break; 757 #ifdef DEBUG 758 default: 759 unknown(); 760 #endif 761 } 762 SET_AL(0x1C); 763 break; 764 765 #ifdef VBE 766 case 0x4f: 767 if (vbe_has_vbe_display()) { 768 switch(GET_AL()) 769 { 770 case 0x00: 771 vbe_biosfn_return_controller_information(&AX,ES,DI); 772 break; 773 case 0x01: 774 vbe_biosfn_return_mode_information(&AX,CX,ES,DI); 775 break; 776 case 0x02: 777 vbe_biosfn_set_mode(&AX,BX,ES,DI); 778 break; 779 case 0x04: 780 vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX); 781 break; 782 case 0x09: 783 //FIXME 784 #ifdef DEBUG 785 unimplemented(); 786 #endif 787 // function failed 788 AX=0x100; 789 break; 790 case 0x0A: 791 //FIXME 792 #ifdef DEBUG 793 unimplemented(); 794 #endif 795 // function failed 796 AX=0x100; 797 break; 798 default: 799 #ifdef DEBUG 800 unknown(); 801 #endif 802 // function failed 803 AX=0x100; 804 } 805 } 806 else { 807 // No VBE display 808 AX=0x0100; 809 } 810 break; 811 #endif 812 813 #ifdef DEBUG 814 default: 815 unknown(); 816 #endif 817 } 818 } 819 820 // ============================================================================================ 821 // 822 // BIOS functions 823 // 824 // ============================================================================================ 825 826 static void biosfn_set_video_mode(mode) Bit8u mode; 827 {// mode: Bit 7 is 1 if no clear screen 828 829 // Should we clear the screen ? 830 Bit8u noclearmem=mode&0x80; 831 Bit8u line,mmask,*palette,vpti; 832 Bit16u i,twidth,theightm1,cheight; 833 Bit8u modeset_ctl,video_ctl,vga_switches; 834 Bit16u crtc_addr; 835 836 #ifdef VBE 837 if (vbe_has_vbe_display()) { 838 dispi_set_enable(VBE_DISPI_DISABLED); 839 } 840 #endif // def VBE 841 842 // The real mode 843 mode=mode&0x7f; 844 845 // find the entry in the video modes 846 line=find_vga_entry(mode); 847 848 #ifdef DEBUG 849 printf("mode search %02x found line %02x\n",mode,line); 850 #endif 851 852 if(line==0xFF) 853 return; 854 855 vpti=line_to_vpti[line]; 856 twidth=video_param_table[vpti].twidth; 857 theightm1=video_param_table[vpti].theightm1; 858 cheight=video_param_table[vpti].cheight; 859 860 // Read the bios vga control 861 video_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL); 862 863 // Read the bios vga switches 864 vga_switches=read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES); 865 866 // Read the bios mode set control 867 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL); 868 869 // Then we know the number of lines 870 // FIXME 871 872 // if palette loading (bit 3 of modeset ctl = 0) 873 if((modeset_ctl&0x08)==0) 874 {// Set the PEL mask 875 outb(VGAREG_PEL_MASK,vga_modes[line].pelmask); 876 877 // Set the whole dac always, from 0 878 outb(VGAREG_DAC_WRITE_ADDRESS,0x00); 879 880 // From which palette 881 switch(vga_modes[line].dacmodel) 882 {case 0: 883 palette=&palette0; 884 break; 885 case 1: 886 palette=&palette1; 887 break; 888 case 2: 889 palette=&palette2; 890 break; 891 case 3: 892 palette=&palette3; 893 break; 894 } 895 // Always 256*3 values 896 for(i=0;i<0x0100;i++) 897 {if(i<=dac_regs[vga_modes[line].dacmodel]) 898 {outb(VGAREG_DAC_DATA,palette[(i*3)+0]); 899 outb(VGAREG_DAC_DATA,palette[(i*3)+1]); 900 outb(VGAREG_DAC_DATA,palette[(i*3)+2]); 901 } 902 else 903 {outb(VGAREG_DAC_DATA,0); 904 outb(VGAREG_DAC_DATA,0); 905 outb(VGAREG_DAC_DATA,0); 906 } 907 } 908 if((modeset_ctl&0x02)==0x02) 909 { 910 biosfn_perform_gray_scale_summing(0x00, 0x100); 911 } 912 } 913 914 // Reset Attribute Ctl flip-flop 915 inb(VGAREG_ACTL_RESET); 916 917 // Set Attribute Ctl 918 for(i=0;i<=0x13;i++) 919 {outb(VGAREG_ACTL_ADDRESS,i); 920 outb(VGAREG_ACTL_WRITE_DATA,video_param_table[vpti].actl_regs[i]); 921 } 922 outb(VGAREG_ACTL_ADDRESS,0x14); 923 outb(VGAREG_ACTL_WRITE_DATA,0x00); 924 925 // Set Sequencer Ctl 926 outb(VGAREG_SEQU_ADDRESS,0); 927 outb(VGAREG_SEQU_DATA,0x03); 928 for(i=1;i<=4;i++) 929 {outb(VGAREG_SEQU_ADDRESS,i); 930 outb(VGAREG_SEQU_DATA,video_param_table[vpti].sequ_regs[i - 1]); 931 } 932 933 // Set Grafx Ctl 934 for(i=0;i<=8;i++) 935 {outb(VGAREG_GRDC_ADDRESS,i); 936 outb(VGAREG_GRDC_DATA,video_param_table[vpti].grdc_regs[i]); 937 } 938 939 // Set CRTC address VGA or MDA 940 crtc_addr=vga_modes[line].memmodel==MTEXT?VGAREG_MDA_CRTC_ADDRESS:VGAREG_VGA_CRTC_ADDRESS; 941 942 // Disable CRTC write protection 943 outw(crtc_addr,0x0011); 944 // Set CRTC regs 945 for(i=0;i<=0x18;i++) 946 {outb(crtc_addr,i); 947 outb(crtc_addr+1,video_param_table[vpti].crtc_regs[i]); 948 } 949 950 // Set the misc register 951 outb(VGAREG_WRITE_MISC_OUTPUT,video_param_table[vpti].miscreg); 952 953 // Enable video 954 outb(VGAREG_ACTL_ADDRESS,0x20); 955 inb(VGAREG_ACTL_RESET); 956 957 if(noclearmem==0x00) 958 { 959 if(vga_modes[line].class==TEXT) 960 { 961 memsetw(vga_modes[line].sstart,0,0x0720,0x4000); // 32k 962 } 963 else 964 { 965 if(mode<0x0d) 966 { 967 memsetw(vga_modes[line].sstart,0,0x0000,0x4000); // 32k 968 } 969 else 970 { 971 outb( VGAREG_SEQU_ADDRESS, 0x02 ); 972 mmask = inb( VGAREG_SEQU_DATA ); 973 outb( VGAREG_SEQU_DATA, 0x0f ); // all planes 974 memsetw(vga_modes[line].sstart,0,0x0000,0x8000); // 64k 975 outb( VGAREG_SEQU_DATA, mmask ); 976 } 977 } 978 } 979 980 // Set the BIOS mem 981 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,mode); 982 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS,twidth); 983 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,*(Bit16u *)&video_param_table[vpti].slength_l); 984 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,crtc_addr); 985 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS,theightm1); 986 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,cheight); 987 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|noclearmem)); 988 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES,0xF9); 989 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x7f); 990 991 // FIXME We nearly have the good tables. to be reworked 992 write_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x08); // 8 is VGA should be ok for now 993 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER, video_save_pointer_table); 994 write_word(BIOSMEM_SEG,BIOSMEM_VS_POINTER+2, 0xc000); 995 996 // FIXME 997 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x00); // Unavailable on vanilla vga, but... 998 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x00); // Unavailable on vanilla vga, but... 999 1000 // Set cursor shape 1001 if(vga_modes[line].class==TEXT) 1002 { 1003 biosfn_set_cursor_shape(0x06,0x07); 1004 } 1005 1006 // Set cursor pos for page 0..7 1007 for(i=0;i<8;i++) 1008 biosfn_set_cursor_pos(i,0x0000); 1009 1010 // Set active page 0 1011 biosfn_set_active_page(0x00); 1012 1013 // Write the fonts in memory 1014 if(vga_modes[line].class==TEXT) 1015 { 1016 ASM_START 1017 ;; copy and activate 8x16 font 1018 mov ax, #0x1104 1019 mov bl, #0x00 1020 int #0x10 1021 mov ax, #0x1103 1022 mov bl, #0x00 1023 int #0x10 1024 ASM_END 1025 } 1026 1027 // Set the ints 0x1F and 0x43 1028 ASM_START 1029 SET_INT_VECTOR(0x1f, #0xC000, #_vgafont8+128*8) 1030 ASM_END 1031 1032 switch(cheight) 1033 {case 8: 1034 ASM_START 1035 SET_INT_VECTOR(0x43, #0xC000, #_vgafont8) 1036 ASM_END 1037 break; 1038 case 14: 1039 ASM_START 1040 SET_INT_VECTOR(0x43, #0xC000, #_vgafont14) 1041 ASM_END 1042 break; 1043 case 16: 1044 ASM_START 1045 SET_INT_VECTOR(0x43, #0xC000, #_vgafont16) 1046 ASM_END 1047 break; 1048 } 1049 } 1050 1051 // -------------------------------------------------------------------------------------------- 1052 static void biosfn_set_cursor_shape (CH,CL) 1053 Bit8u CH;Bit8u CL; 1054 {Bit16u cheight,curs,crtc_addr; 1055 Bit8u modeset_ctl; 1056 1057 CH&=0x3f; 1058 CL&=0x1f; 1059 1060 curs=(CH<<8)+CL; 1061 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE,curs); 1062 1063 modeset_ctl=read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL); 1064 cheight = read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT); 1065 if((modeset_ctl&0x01) && (cheight>8) && (CL<8) && (CH<0x20)) 1066 { 1067 if(CL!=(CH+1)) 1068 { 1069 CH = ((CH+1) * cheight / 8) -1; 1070 } 1071 else 1072 { 1073 CH = ((CL+1) * cheight / 8) - 2; 1074 } 1075 CL = ((CL+1) * cheight / 8) - 1; 1076 } 1077 1078 // CTRC regs 0x0a and 0x0b 1079 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); 1080 outb(crtc_addr,0x0a); 1081 outb(crtc_addr+1,CH); 1082 outb(crtc_addr,0x0b); 1083 outb(crtc_addr+1,CL); 1084 } 1085 1086 // -------------------------------------------------------------------------------------------- 1087 static void biosfn_set_cursor_pos (page, cursor) 1088 Bit8u page;Bit16u cursor; 1089 { 1090 Bit8u xcurs,ycurs,current; 1091 Bit16u nbcols,nbrows,address,crtc_addr; 1092 1093 // Should not happen... 1094 if(page>7)return; 1095 1096 // Bios cursor pos 1097 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*page, cursor); 1098 1099 // Set the hardware cursor 1100 current=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); 1101 if(page==current) 1102 { 1103 // Get the dimensions 1104 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); 1105 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; 1106 1107 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; 1108 1109 // Calculate the address knowing nbcols nbrows and page num 1110 address=SCREEN_IO_START(nbcols,nbrows,page)+xcurs+ycurs*nbcols; 1111 1112 // CRTC regs 0x0e and 0x0f 1113 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); 1114 outb(crtc_addr,0x0e); 1115 outb(crtc_addr+1,(address&0xff00)>>8); 1116 outb(crtc_addr,0x0f); 1117 outb(crtc_addr+1,address&0x00ff); 1118 } 1119 } 1120 1121 // -------------------------------------------------------------------------------------------- 1122 static void biosfn_get_cursor_pos (page,shape, pos) 1123 Bit8u page;Bit16u *shape;Bit16u *pos; 1124 { 1125 Bit16u ss=get_SS(); 1126 1127 // Default 1128 write_word(ss, shape, 0); 1129 write_word(ss, pos, 0); 1130 1131 if(page>7)return; 1132 // FIXME should handle VGA 14/16 lines 1133 write_word(ss,shape,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); 1134 write_word(ss,pos,read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2)); 1135 } 1136 1137 // -------------------------------------------------------------------------------------------- 1138 static void biosfn_set_active_page (page) 1139 Bit8u page; 1140 { 1141 Bit16u cursor,dummy,crtc_addr; 1142 Bit16u nbcols,nbrows,address; 1143 Bit8u mode,line; 1144 1145 if(page>7)return; 1146 1147 // Get the mode 1148 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); 1149 line=find_vga_entry(mode); 1150 if(line==0xFF)return; 1151 1152 // Get pos curs pos for the right page 1153 biosfn_get_cursor_pos(page,&dummy,&cursor); 1154 1155 if(vga_modes[line].class==TEXT) 1156 { 1157 // Get the dimensions 1158 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); 1159 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; 1160 1161 // Calculate the address knowing nbcols nbrows and page num 1162 address=SCREEN_MEM_START(nbcols,nbrows,page); 1163 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START,address); 1164 1165 // Start address 1166 address=SCREEN_IO_START(nbcols,nbrows,page); 1167 } 1168 else 1169 { 1170 address = page * (*(Bit16u *)&video_param_table[line_to_vpti[line]].slength_l); 1171 } 1172 1173 // CRTC regs 0x0c and 0x0d 1174 crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); 1175 outb(crtc_addr,0x0c); 1176 outb(crtc_addr+1,(address&0xff00)>>8); 1177 outb(crtc_addr,0x0d); 1178 outb(crtc_addr+1,address&0x00ff); 1179 1180 // And change the BIOS page 1181 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE,page); 1182 1183 #ifdef DEBUG 1184 printf("Set active page %02x address %04x\n",page,address); 1185 #endif 1186 1187 // Display the cursor, now the page is active 1188 biosfn_set_cursor_pos(page,cursor); 1189 } 1190 1191 // -------------------------------------------------------------------------------------------- 1192 static void vgamem_copy_pl4(xstart,ysrc,ydest,cols,nbcols,cheight) 1193 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight; 1194 { 1195 Bit16u src,dest; 1196 Bit8u i; 1197 1198 src=ysrc*cheight*nbcols+xstart; 1199 dest=ydest*cheight*nbcols+xstart; 1200 outw(VGAREG_GRDC_ADDRESS, 0x0105); 1201 for(i=0;i<cheight;i++) 1202 { 1203 memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols); 1204 } 1205 outw(VGAREG_GRDC_ADDRESS, 0x0005); 1206 } 1207 1208 // -------------------------------------------------------------------------------------------- 1209 static void vgamem_fill_pl4(xstart,ystart,cols,nbcols,cheight,attr) 1210 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr; 1211 { 1212 Bit16u dest; 1213 Bit8u i; 1214 1215 dest=ystart*cheight*nbcols+xstart; 1216 outw(VGAREG_GRDC_ADDRESS, 0x0205); 1217 for(i=0;i<cheight;i++) 1218 { 1219 memsetb(0xa000,dest+i*nbcols,attr,cols); 1220 } 1221 outw(VGAREG_GRDC_ADDRESS, 0x0005); 1222 } 1223 1224 // -------------------------------------------------------------------------------------------- 1225 static void vgamem_copy_cga(xstart,ysrc,ydest,cols,nbcols,cheight) 1226 Bit8u xstart;Bit8u ysrc;Bit8u ydest;Bit8u cols;Bit8u nbcols;Bit8u cheight; 1227 { 1228 Bit16u src,dest; 1229 Bit8u i; 1230 1231 src=((ysrc*cheight*nbcols)>>1)+xstart; 1232 dest=((ydest*cheight*nbcols)>>1)+xstart; 1233 for(i=0;i<cheight;i++) 1234 { 1235 if (i & 1) 1236 memcpyb(0xb800,0x2000+dest+(i>>1)*nbcols,0xb800,0x2000+src+(i>>1)*nbcols,cols); 1237 else 1238 memcpyb(0xb800,dest+(i>>1)*nbcols,0xb800,src+(i>>1)*nbcols,cols); 1239 } 1240 } 1241 1242 // -------------------------------------------------------------------------------------------- 1243 static void vgamem_fill_cga(xstart,ystart,cols,nbcols,cheight,attr) 1244 Bit8u xstart;Bit8u ystart;Bit8u cols;Bit8u nbcols;Bit8u cheight;Bit8u attr; 1245 { 1246 Bit16u dest; 1247 Bit8u i; 1248 1249 dest=((ystart*cheight*nbcols)>>1)+xstart; 1250 for(i=0;i<cheight;i++) 1251 { 1252 if (i & 1) 1253 memsetb(0xb800,0x2000+dest+(i>>1)*nbcols,attr,cols); 1254 else 1255 memsetb(0xb800,dest+(i>>1)*nbcols,attr,cols); 1256 } 1257 } 1258 1259 // -------------------------------------------------------------------------------------------- 1260 static void biosfn_scroll (nblines,attr,rul,cul,rlr,clr,page,dir) 1261 Bit8u nblines;Bit8u attr;Bit8u rul;Bit8u cul;Bit8u rlr;Bit8u clr;Bit8u page;Bit8u dir; 1262 { 1263 // page == 0xFF if current 1264 1265 Bit8u mode,line,cheight,bpp,cols; 1266 Bit16u nbcols,nbrows,i; 1267 Bit16u address; 1268 1269 if(rul>rlr)return; 1270 if(cul>clr)return; 1271 1272 // Get the mode 1273 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); 1274 line=find_vga_entry(mode); 1275 if(line==0xFF)return; 1276 1277 // Get the dimensions 1278 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; 1279 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); 1280 1281 // Get the current page 1282 if(page==0xFF) 1283 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); 1284 1285 if(rlr>=nbrows)rlr=nbrows-1; 1286 if(clr>=nbcols)clr=nbcols-1; 1287 if(nblines>nbrows)nblines=0; 1288 cols=clr-cul+1; 1289 1290 if(vga_modes[line].class==TEXT) 1291 { 1292 // Compute the address 1293 address=SCREEN_MEM_START(nbcols,nbrows,page); 1294 #ifdef DEBUG 1295 printf("Scroll, address %04x (%04x %04x %02x)\n",address,nbrows,nbcols,page); 1296 #endif 1297 1298 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1) 1299 { 1300 memsetw(vga_modes[line].sstart,address,(Bit16u)attr*0x100+' ',nbrows*nbcols); 1301 } 1302 else 1303 {// if Scroll up 1304 if(dir==SCROLL_UP) 1305 {for(i=rul;i<=rlr;i++) 1306 { 1307 if((i+nblines>rlr)||(nblines==0)) 1308 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols); 1309 else 1310 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i+nblines)*nbcols+cul)*2,cols); 1311 } 1312 } 1313 else 1314 {for(i=rlr;i>=rul;i--) 1315 { 1316 if((i<rul+nblines)||(nblines==0)) 1317 memsetw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,(Bit16u)attr*0x100+' ',cols); 1318 else 1319 memcpyw(vga_modes[line].sstart,address+(i*nbcols+cul)*2,vga_modes[line].sstart,((i-nblines)*nbcols+cul)*2,cols); 1320 if (i>rlr) break; 1321 } 1322 } 1323 } 1324 } 1325 else 1326 { 1327 // FIXME gfx mode not complete 1328 cheight=video_param_table[line_to_vpti[line]].cheight; 1329 switch(vga_modes[line].memmodel) 1330 { 1331 case PLANAR4: 1332 case PLANAR1: 1333 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1) 1334 { 1335 outw(VGAREG_GRDC_ADDRESS, 0x0205); 1336 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight); 1337 outw(VGAREG_GRDC_ADDRESS, 0x0005); 1338 } 1339 else 1340 {// if Scroll up 1341 if(dir==SCROLL_UP) 1342 {for(i=rul;i<=rlr;i++) 1343 { 1344 if((i+nblines>rlr)||(nblines==0)) 1345 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr); 1346 else 1347 vgamem_copy_pl4(cul,i+nblines,i,cols,nbcols,cheight); 1348 } 1349 } 1350 else 1351 {for(i=rlr;i>=rul;i--) 1352 { 1353 if((i<rul+nblines)||(nblines==0)) 1354 vgamem_fill_pl4(cul,i,cols,nbcols,cheight,attr); 1355 else 1356 vgamem_copy_pl4(cul,i,i-nblines,cols,nbcols,cheight); 1357 if (i>rlr) break; 1358 } 1359 } 1360 } 1361 break; 1362 case CGA: 1363 bpp=vga_modes[line].pixbits; 1364 if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1) 1365 { 1366 memsetb(vga_modes[line].sstart,0,attr,nbrows*nbcols*cheight*bpp); 1367 } 1368 else 1369 { 1370 if(bpp==2) 1371 { 1372 cul<<=1; 1373 cols<<=1; 1374 nbcols<<=1; 1375 } 1376 // if Scroll up 1377 if(dir==SCROLL_UP) 1378 {for(i=rul;i<=rlr;i++) 1379 { 1380 if((i+nblines>rlr)||(nblines==0)) 1381 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr); 1382 else 1383 vgamem_copy_cga(cul,i+nblines,i,cols,nbcols,cheight); 1384 } 1385 } 1386 else 1387 {for(i=rlr;i>=rul;i--) 1388 { 1389 if((i<rul+nblines)||(nblines==0)) 1390 vgamem_fill_cga(cul,i,cols,nbcols,cheight,attr); 1391 else 1392 vgamem_copy_cga(cul,i,i-nblines,cols,nbcols,cheight); 1393 if (i>rlr) break; 1394 } 1395 } 1396 } 1397 break; 1398 #ifdef DEBUG 1399 default: 1400 printf("Scroll in graphics mode "); 1401 unimplemented(); 1402 #endif 1403 } 1404 } 1405 } 1406 1407 // -------------------------------------------------------------------------------------------- 1408 static void biosfn_read_char_attr (page,car) 1409 Bit8u page;Bit16u *car; 1410 {Bit16u ss=get_SS(); 1411 Bit8u xcurs,ycurs,mode,line; 1412 Bit16u nbcols,nbrows,address; 1413 Bit16u cursor,dummy; 1414 1415 // Get the mode 1416 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); 1417 line=find_vga_entry(mode); 1418 if(line==0xFF)return; 1419 1420 // Get the cursor pos for the page 1421 biosfn_get_cursor_pos(page,&dummy,&cursor); 1422 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; 1423 1424 // Get the dimensions 1425 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; 1426 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); 1427 1428 if(vga_modes[line].class==TEXT) 1429 { 1430 // Compute the address 1431 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; 1432 1433 write_word(ss,car,read_word(vga_modes[line].sstart,address)); 1434 } 1435 else 1436 { 1437 // FIXME gfx mode 1438 #ifdef DEBUG 1439 unimplemented(); 1440 #endif 1441 } 1442 } 1443 1444 // -------------------------------------------------------------------------------------------- 1445 static void write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight) 1446 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u cheight; 1447 { 1448 Bit8u i,j,mask; 1449 Bit8u *fdata; 1450 Bit16u addr,dest,src; 1451 1452 switch(cheight) 1453 {case 14: 1454 fdata = &vgafont14; 1455 break; 1456 case 16: 1457 fdata = &vgafont16; 1458 break; 1459 default: 1460 fdata = &vgafont8; 1461 } 1462 addr=xcurs+ycurs*cheight*nbcols; 1463 src = car * cheight; 1464 outw(VGAREG_SEQU_ADDRESS, 0x0f02); 1465 outw(VGAREG_GRDC_ADDRESS, 0x0205); 1466 if(attr&0x80) 1467 { 1468 outw(VGAREG_GRDC_ADDRESS, 0x1803); 1469 } 1470 else 1471 { 1472 outw(VGAREG_GRDC_ADDRESS, 0x0003); 1473 } 1474 for(i=0;i<cheight;i++) 1475 { 1476 dest=addr+i*nbcols; 1477 for(j=0;j<8;j++) 1478 { 1479 mask=0x80>>j; 1480 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08); 1481 read_byte(0xa000,dest); 1482 if(fdata[src+i]&mask) 1483 { 1484 write_byte(0xa000,dest,attr&0x0f); 1485 } 1486 else 1487 { 1488 write_byte(0xa000,dest,0x00); 1489 } 1490 } 1491 } 1492 ASM_START 1493 mov dx, # VGAREG_GRDC_ADDRESS 1494 mov ax, #0xff08 1495 out dx, ax 1496 mov ax, #0x0005 1497 out dx, ax 1498 mov ax, #0x0003 1499 out dx, ax 1500 ASM_END 1501 } 1502 1503 // -------------------------------------------------------------------------------------------- 1504 static void write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp) 1505 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols;Bit8u bpp; 1506 { 1507 Bit8u i,j,mask,data; 1508 Bit8u *fdata; 1509 Bit16u addr,dest,src; 1510 1511 fdata = &vgafont8; 1512 addr=(xcurs*bpp)+ycurs*320; 1513 src = car * 8; 1514 for(i=0;i<8;i++) 1515 { 1516 dest=addr+(i>>1)*80; 1517 if (i & 1) dest += 0x2000; 1518 mask = 0x80; 1519 if (bpp == 1) 1520 { 1521 if (attr & 0x80) 1522 { 1523 data = read_byte(0xb800,dest); 1524 } 1525 else 1526 { 1527 data = 0x00; 1528 } 1529 for(j=0;j<8;j++) 1530 { 1531 if (fdata[src+i] & mask) 1532 { 1533 if (attr & 0x80) 1534 { 1535 data ^= (attr & 0x01) << (7-j); 1536 } 1537 else 1538 { 1539 data |= (attr & 0x01) << (7-j); 1540 } 1541 } 1542 mask >>= 1; 1543 } 1544 write_byte(0xb800,dest,data); 1545 } 1546 else 1547 { 1548 while (mask > 0) 1549 { 1550 if (attr & 0x80) 1551 { 1552 data = read_byte(0xb800,dest); 1553 } 1554 else 1555 { 1556 data = 0x00; 1557 } 1558 for(j=0;j<4;j++) 1559 { 1560 if (fdata[src+i] & mask) 1561 { 1562 if (attr & 0x80) 1563 { 1564 data ^= (attr & 0x03) << ((3-j)*2); 1565 } 1566 else 1567 { 1568 data |= (attr & 0x03) << ((3-j)*2); 1569 } 1570 } 1571 mask >>= 1; 1572 } 1573 write_byte(0xb800,dest,data); 1574 dest += 1; 1575 } 1576 } 1577 } 1578 } 1579 1580 // -------------------------------------------------------------------------------------------- 1581 static void write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols) 1582 Bit8u car;Bit8u attr;Bit8u xcurs;Bit8u ycurs;Bit8u nbcols; 1583 { 1584 Bit8u i,j,mask,data; 1585 Bit8u *fdata; 1586 Bit16u addr,dest,src; 1587 1588 fdata = &vgafont8; 1589 addr=xcurs*8+ycurs*nbcols*64; 1590 src = car * 8; 1591 for(i=0;i<8;i++) 1592 { 1593 dest=addr+i*nbcols*8; 1594 mask = 0x80; 1595 for(j=0;j<8;j++) 1596 { 1597 data = 0x00; 1598 if (fdata[src+i] & mask) 1599 { 1600 data = attr; 1601 } 1602 write_byte(0xa000,dest+j,data); 1603 mask >>= 1; 1604 } 1605 } 1606 } 1607 1608 // -------------------------------------------------------------------------------------------- 1609 static void biosfn_write_char_attr (car,page,attr,count) 1610 Bit8u car;Bit8u page;Bit8u attr;Bit16u count; 1611 { 1612 Bit8u cheight,xcurs,ycurs,mode,line,bpp; 1613 Bit16u nbcols,nbrows,address; 1614 Bit16u cursor,dummy; 1615 1616 // Get the mode 1617 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); 1618 line=find_vga_entry(mode); 1619 if(line==0xFF)return; 1620 1621 // Get the cursor pos for the page 1622 biosfn_get_cursor_pos(page,&dummy,&cursor); 1623 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; 1624 1625 // Get the dimensions 1626 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; 1627 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); 1628 1629 if(vga_modes[line].class==TEXT) 1630 { 1631 // Compute the address 1632 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; 1633 1634 dummy=((Bit16u)attr<<8)+car; 1635 memsetw(vga_modes[line].sstart,address,dummy,count); 1636 } 1637 else 1638 { 1639 // FIXME gfx mode not complete 1640 cheight=video_param_table[line_to_vpti[line]].cheight; 1641 bpp=vga_modes[line].pixbits; 1642 while((count-->0) && (xcurs<nbcols)) 1643 { 1644 switch(vga_modes[line].memmodel) 1645 { 1646 case PLANAR4: 1647 case PLANAR1: 1648 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight); 1649 break; 1650 case CGA: 1651 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp); 1652 break; 1653 case LINEAR8: 1654 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols); 1655 break; 1656 #ifdef DEBUG 1657 default: 1658 unimplemented(); 1659 #endif 1660 } 1661 xcurs++; 1662 } 1663 } 1664 } 1665 1666 // -------------------------------------------------------------------------------------------- 1667 static void biosfn_write_char_only (car,page,attr,count) 1668 Bit8u car;Bit8u page;Bit8u attr;Bit16u count; 1669 { 1670 Bit8u cheight,xcurs,ycurs,mode,line,bpp; 1671 Bit16u nbcols,nbrows,address; 1672 Bit16u cursor,dummy; 1673 1674 // Get the mode 1675 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); 1676 line=find_vga_entry(mode); 1677 if(line==0xFF)return; 1678 1679 // Get the cursor pos for the page 1680 biosfn_get_cursor_pos(page,&dummy,&cursor); 1681 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; 1682 1683 // Get the dimensions 1684 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; 1685 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); 1686 1687 if(vga_modes[line].class==TEXT) 1688 { 1689 // Compute the address 1690 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; 1691 1692 while(count-->0) 1693 {write_byte(vga_modes[line].sstart,address,car); 1694 address+=2; 1695 } 1696 } 1697 else 1698 { 1699 // FIXME gfx mode not complete 1700 cheight=video_param_table[line_to_vpti[line]].cheight; 1701 bpp=vga_modes[line].pixbits; 1702 while((count-->0) && (xcurs<nbcols)) 1703 { 1704 switch(vga_modes[line].memmodel) 1705 { 1706 case PLANAR4: 1707 case PLANAR1: 1708 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight); 1709 break; 1710 case CGA: 1711 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp); 1712 break; 1713 case LINEAR8: 1714 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols); 1715 break; 1716 #ifdef DEBUG 1717 default: 1718 unimplemented(); 1719 #endif 1720 } 1721 xcurs++; 1722 } 1723 } 1724 } 1725 1726 // -------------------------------------------------------------------------------------------- 1727 ASM_START 1728 biosfn_group_0B: 1729 cmp bh, #0x00 1730 je biosfn_set_border_color 1731 cmp bh, #0x01 1732 je biosfn_set_palette 1733 #ifdef DEBUG 1734 call _unknown 1735 #endif 1736 ret 1737 biosfn_set_border_color: 1738 push ax 1739 push bx 1740 push cx 1741 push dx 1742 mov dx, # VGAREG_ACTL_RESET 1743 in al, dx 1744 mov dx, # VGAREG_ACTL_ADDRESS 1745 mov al, #0x00 1746 out dx, al 1747 mov al, bl 1748 and al, #0x0f 1749 test al, #0x08 1750 jz set_low_border 1751 add al, #0x08 1752 set_low_border: 1753 out dx, al 1754 mov cl, #0x01 1755 and bl, #0x10 1756 set_intensity_loop: 1757 mov dx, # VGAREG_ACTL_ADDRESS 1758 mov al, cl 1759 out dx, al 1760 mov dx, # VGAREG_ACTL_READ_DATA 1761 in al, dx 1762 and al, #0xef 1763 or al, bl 1764 mov dx, # VGAREG_ACTL_ADDRESS 1765 out dx, al 1766 inc cl 1767 cmp cl, #0x04 1768 jne set_intensity_loop 1769 mov al, #0x20 1770 out dx, al 1771 pop dx 1772 pop cx 1773 pop bx 1774 pop ax 1775 ret 1776 biosfn_set_palette: 1777 push ax 1778 push bx 1779 push cx 1780 push dx 1781 mov dx, # VGAREG_ACTL_RESET 1782 in al, dx 1783 mov cl, #0x01 1784 and bl, #0x01 1785 set_cga_palette_loop: 1786 mov dx, # VGAREG_ACTL_ADDRESS 1787 mov al, cl 1788 out dx, al 1789 mov dx, # VGAREG_ACTL_READ_DATA 1790 in al, dx 1791 and al, #0xfe 1792 or al, bl 1793 mov dx, # VGAREG_ACTL_ADDRESS 1794 out dx, al 1795 inc cl 1796 cmp cl, #0x04 1797 jne set_cga_palette_loop 1798 mov al, #0x20 1799 out dx, al 1800 pop dx 1801 pop cx 1802 pop bx 1803 pop ax 1804 ret 1805 ASM_END 1806 1807 // -------------------------------------------------------------------------------------------- 1808 static void biosfn_write_pixel (BH,AL,CX,DX) Bit8u BH;Bit8u AL;Bit16u CX;Bit16u DX; 1809 { 1810 Bit8u mode,line,mask,attr,data; 1811 Bit16u addr; 1812 1813 // Get the mode 1814 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); 1815 line=find_vga_entry(mode); 1816 if(line==0xFF)return; 1817 if(vga_modes[line].class==TEXT)return; 1818 1819 switch(vga_modes[line].memmodel) 1820 { 1821 case PLANAR4: 1822 case PLANAR1: 1823 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); 1824 mask = 0x80 >> (CX & 0x07); 1825 outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08); 1826 outw(VGAREG_GRDC_ADDRESS, 0x0205); 1827 data = read_byte(0xa000,addr); 1828 if (AL & 0x80) 1829 { 1830 outw(VGAREG_GRDC_ADDRESS, 0x1803); 1831 } 1832 write_byte(0xa000,addr,AL); 1833 ASM_START 1834 mov dx, # VGAREG_GRDC_ADDRESS 1835 mov ax, #0xff08 1836 out dx, ax 1837 mov ax, #0x0005 1838 out dx, ax 1839 mov ax, #0x0003 1840 out dx, ax 1841 ASM_END 1842 break; 1843 case CGA: 1844 if(vga_modes[line].pixbits==2) 1845 { 1846 addr=(CX>>2)+(DX>>1)*80; 1847 } 1848 else 1849 { 1850 addr=(CX>>3)+(DX>>1)*80; 1851 } 1852 if (DX & 1) addr += 0x2000; 1853 data = read_byte(0xb800,addr); 1854 if(vga_modes[line].pixbits==2) 1855 { 1856 attr = (AL & 0x03) << ((3 - (CX & 0x03)) * 2); 1857 mask = 0x03 << ((3 - (CX & 0x03)) * 2); 1858 } 1859 else 1860 { 1861 attr = (AL & 0x01) << (7 - (CX & 0x07)); 1862 mask = 0x01 << (7 - (CX & 0x07)); 1863 } 1864 if (AL & 0x80) 1865 { 1866 data ^= attr; 1867 } 1868 else 1869 { 1870 data &= ~mask; 1871 data |= attr; 1872 } 1873 write_byte(0xb800,addr,data); 1874 break; 1875 case LINEAR8: 1876 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8); 1877 write_byte(0xa000,addr,AL); 1878 break; 1879 #ifdef DEBUG 1880 default: 1881 unimplemented(); 1882 #endif 1883 } 1884 } 1885 1886 // -------------------------------------------------------------------------------------------- 1887 static void biosfn_read_pixel (BH,CX,DX,AX) Bit8u BH;Bit16u CX;Bit16u DX;Bit16u *AX; 1888 { 1889 Bit8u mode,line,mask,attr,data,i; 1890 Bit16u addr; 1891 Bit16u ss=get_SS(); 1892 1893 // Get the mode 1894 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); 1895 line=find_vga_entry(mode); 1896 if(line==0xFF)return; 1897 if(vga_modes[line].class==TEXT)return; 1898 1899 switch(vga_modes[line].memmodel) 1900 { 1901 case PLANAR4: 1902 case PLANAR1: 1903 addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); 1904 mask = 0x80 >> (CX & 0x07); 1905 attr = 0x00; 1906 for(i=0;i<4;i++) 1907 { 1908 outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04); 1909 data = read_byte(0xa000,addr) & mask; 1910 if (data > 0) attr |= (0x01 << i); 1911 } 1912 break; 1913 case CGA: 1914 addr=(CX>>2)+(DX>>1)*80; 1915 if (DX & 1) addr += 0x2000; 1916 data = read_byte(0xb800,addr); 1917 if(vga_modes[line].pixbits==2) 1918 { 1919 attr = (data >> ((3 - (CX & 0x03)) * 2)) & 0x03; 1920 } 1921 else 1922 { 1923 attr = (data >> (7 - (CX & 0x07))) & 0x01; 1924 } 1925 break; 1926 case LINEAR8: 1927 addr=CX+DX*(read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)*8); 1928 attr=read_byte(0xa000,addr); 1929 break; 1930 default: 1931 #ifdef DEBUG 1932 unimplemented(); 1933 #endif 1934 attr = 0; 1935 } 1936 write_word(ss,AX,(read_word(ss,AX) & 0xff00) | attr); 1937 } 1938 1939 // -------------------------------------------------------------------------------------------- 1940 static void biosfn_write_teletype (car, page, attr, flag) 1941 Bit8u car;Bit8u page;Bit8u attr;Bit8u flag; 1942 {// flag = WITH_ATTR / NO_ATTR 1943 1944 Bit8u cheight,xcurs,ycurs,mode,line,bpp; 1945 Bit16u nbcols,nbrows,address; 1946 Bit16u cursor,dummy; 1947 1948 // special case if page is 0xff, use current page 1949 if(page==0xff) 1950 page=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE); 1951 1952 // Get the mode 1953 mode=read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE); 1954 line=find_vga_entry(mode); 1955 if(line==0xFF)return; 1956 1957 // Get the cursor pos for the page 1958 biosfn_get_cursor_pos(page,&dummy,&cursor); 1959 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; 1960 1961 // Get the dimensions 1962 nbrows=read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1; 1963 nbcols=read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); 1964 1965 switch(car) 1966 { 1967 case 7: 1968 //FIXME should beep 1969 break; 1970 1971 case 8: 1972 if(xcurs>0)xcurs--; 1973 break; 1974 1975 case '\r': 1976 xcurs=0; 1977 break; 1978 1979 case '\n': 1980 ycurs++; 1981 break; 1982 1983 case '\t': 1984 do 1985 { 1986 biosfn_write_teletype(' ',page,attr,flag); 1987 biosfn_get_cursor_pos(page,&dummy,&cursor); 1988 xcurs=cursor&0x00ff;ycurs=(cursor&0xff00)>>8; 1989 }while(xcurs%8==0); 1990 break; 1991 1992 default: 1993 1994 if(vga_modes[line].class==TEXT) 1995 { 1996 // Compute the address 1997 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+ycurs*nbcols)*2; 1998 1999 // Write the char 2000 write_byte(vga_modes[line].sstart,address,car); 2001 2002 if(flag==WITH_ATTR) 2003 write_byte(vga_modes[line].sstart,address+1,attr); 2004 } 2005 else 2006 { 2007 // FIXME gfx mode not complete 2008 cheight=video_param_table[line_to_vpti[line]].cheight; 2009 bpp=vga_modes[line].pixbits; 2010 switch(vga_modes[line].memmodel) 2011 { 2012 case PLANAR4: 2013 case PLANAR1: 2014 write_gfx_char_pl4(car,attr,xcurs,ycurs,nbcols,cheight); 2015 break; 2016 case CGA: 2017 write_gfx_char_cga(car,attr,xcurs,ycurs,nbcols,bpp); 2018 break; 2019 case LINEAR8: 2020 write_gfx_char_lin(car,attr,xcurs,ycurs,nbcols); 2021 break; 2022 #ifdef DEBUG 2023 default: 2024 unimplemented(); 2025 #endif 2026 } 2027 } 2028 xcurs++; 2029 } 2030 2031 // Do we need to wrap ? 2032 if(xcurs==nbcols) 2033 {xcurs=0; 2034 ycurs++; 2035 } 2036 2037 // Do we need to scroll ? 2038 if(ycurs==nbrows) 2039 { 2040 if(vga_modes[line].class==TEXT) 2041 { 2042 address=SCREEN_MEM_START(nbcols,nbrows,page)+(xcurs+(ycurs-1)*nbcols)*2; 2043 attr=read_byte(vga_modes[line].sstart,address+1); 2044 biosfn_scroll(0x01,attr,0,0,nbrows-1,nbcols-1,page,SCROLL_UP); 2045 } 2046 else 2047 { 2048 biosfn_scroll(0x01,0x00,0,0,nbrows-1,nbcols-1,page,SCROLL_UP); 2049 } 2050 ycurs-=1; 2051 } 2052 2053 // Set the cursor for the page 2054 cursor=ycurs; cursor<<=8; cursor+=xcurs; 2055 biosfn_set_cursor_pos(page,cursor); 2056 } 2057 2058 // -------------------------------------------------------------------------------------------- 2059 ASM_START 2060 biosfn_get_video_mode: 2061 push ds 2062 mov ax, # BIOSMEM_SEG 2063 mov ds, ax 2064 push bx 2065 mov bx, # BIOSMEM_CURRENT_PAGE 2066 mov al, [bx] 2067 pop bx 2068 mov bh, al 2069 push bx 2070 mov bx, # BIOSMEM_VIDEO_CTL 2071 mov ah, [bx] 2072 and ah, #0x80 2073 mov bx, # BIOSMEM_CURRENT_MODE 2074 mov al, [bx] 2075 or al, ah 2076 mov bx, # BIOSMEM_NB_COLS 2077 mov ah, [bx] 2078 pop bx 2079 pop ds 2080 ret 2081 ASM_END 2082 2083 // -------------------------------------------------------------------------------------------- 2084 ASM_START 2085 biosfn_group_10: 2086 cmp al, #0x00 2087 jne int10_test_1001 2088 jmp biosfn_set_single_palette_reg 2089 int10_test_1001: 2090 cmp al, #0x01 2091 jne int10_test_1002 2092 jmp biosfn_set_overscan_border_color 2093 int10_test_1002: 2094 cmp al, #0x02 2095 jne int10_test_1003 2096 jmp biosfn_set_all_palette_reg 2097 int10_test_1003: 2098 cmp al, #0x03 2099 jne int10_test_1007 2100 jmp biosfn_toggle_intensity 2101 int10_test_1007: 2102 cmp al, #0x07 2103 jne int10_test_1008 2104 jmp biosfn_get_single_palette_reg 2105 int10_test_1008: 2106 cmp al, #0x08 2107 jne int10_test_1009 2108 jmp biosfn_read_overscan_border_color 2109 int10_test_1009: 2110 cmp al, #0x09 2111 jne int10_test_1010 2112 jmp biosfn_get_all_palette_reg 2113 int10_test_1010: 2114 cmp al, #0x10 2115 jne int10_test_1012 2116 jmp biosfn_set_single_dac_reg 2117 int10_test_1012: 2118 cmp al, #0x12 2119 jne int10_test_1013 2120 jmp biosfn_set_all_dac_reg 2121 int10_test_1013: 2122 cmp al, #0x13 2123 jne int10_test_1015 2124 jmp biosfn_select_video_dac_color_page 2125 int10_test_1015: 2126 cmp al, #0x15 2127 jne int10_test_1017 2128 jmp biosfn_read_single_dac_reg 2129 int10_test_1017: 2130 cmp al, #0x17 2131 jne int10_test_1018 2132 jmp biosfn_read_all_dac_reg 2133 int10_test_1018: 2134 cmp al, #0x18 2135 jne int10_test_1019 2136 jmp biosfn_set_pel_mask 2137 int10_test_1019: 2138 cmp al, #0x19 2139 jne int10_test_101A 2140 jmp biosfn_read_pel_mask 2141 int10_test_101A: 2142 cmp al, #0x1a 2143 jne int10_group_10_unknown 2144 jmp biosfn_read_video_dac_state 2145 int10_group_10_unknown: 2146 #ifdef DEBUG 2147 call _unknown 2148 #endif 2149 ret 2150 2151 biosfn_set_single_palette_reg: 2152 cmp bl, #0x14 2153 ja no_actl_reg1 2154 push ax 2155 push dx 2156 mov dx, # VGAREG_ACTL_RESET 2157 in al, dx 2158 mov dx, # VGAREG_ACTL_ADDRESS 2159 mov al, bl 2160 out dx, al 2161 mov al, bh 2162 out dx, al 2163 mov al, #0x20 2164 out dx, al 2165 pop dx 2166 pop ax 2167 no_actl_reg1: 2168 ret 2169 ASM_END 2170 2171 // -------------------------------------------------------------------------------------------- 2172 ASM_START 2173 biosfn_set_overscan_border_color: 2174 push bx 2175 mov bl, #0x11 2176 call biosfn_set_single_palette_reg 2177 pop bx 2178 ret 2179 ASM_END 2180 2181 // -------------------------------------------------------------------------------------------- 2182 ASM_START 2183 biosfn_set_all_palette_reg: 2184 push ax 2185 push bx 2186 push cx 2187 push dx 2188 mov bx, dx 2189 mov dx, # VGAREG_ACTL_RESET 2190 in al, dx 2191 mov cl, #0x00 2192 mov dx, # VGAREG_ACTL_ADDRESS 2193 set_palette_loop: 2194 mov al, cl 2195 out dx, al 2196 seg es 2197 mov al, [bx] 2198 out dx, al 2199 inc bx 2200 inc cl 2201 cmp cl, #0x10 2202 jne set_palette_loop 2203 mov al, #0x11 2204 out dx, al 2205 seg es 2206 mov al, [bx] 2207 out dx, al 2208 mov al, #0x20 2209 out dx, al 2210 pop dx 2211 pop cx 2212 pop bx 2213 pop ax 2214 ret 2215 ASM_END 2216 2217 // -------------------------------------------------------------------------------------------- 2218 ASM_START 2219 biosfn_toggle_intensity: 2220 push ax 2221 push bx 2222 push dx 2223 mov dx, # VGAREG_ACTL_RESET 2224 in al, dx 2225 mov dx, # VGAREG_ACTL_ADDRESS 2226 mov al, #0x10 2227 out dx, al 2228 mov dx, # VGAREG_ACTL_READ_DATA 2229 in al, dx 2230 and al, #0xf7 2231 and bl, #0x01 2232 shl bl, 3 2233 or al, bl 2234 mov dx, # VGAREG_ACTL_ADDRESS 2235 out dx, al 2236 mov al, #0x20 2237 out dx, al 2238 pop dx 2239 pop bx 2240 pop ax 2241 ret 2242 ASM_END 2243 2244 // -------------------------------------------------------------------------------------------- 2245 ASM_START 2246 biosfn_get_single_palette_reg: 2247 cmp bl, #0x14 2248 ja no_actl_reg2 2249 push ax 2250 push dx 2251 mov dx, # VGAREG_ACTL_RESET 2252 in al, dx 2253 mov dx, # VGAREG_ACTL_ADDRESS 2254 mov al, bl 2255 out dx, al 2256 mov dx, # VGAREG_ACTL_READ_DATA 2257 in al, dx 2258 mov bh, al 2259 mov dx, # VGAREG_ACTL_RESET 2260 in al, dx 2261 mov dx, # VGAREG_ACTL_ADDRESS 2262 mov al, #0x20 2263 out dx, al 2264 pop dx 2265 pop ax 2266 no_actl_reg2: 2267 ret 2268 ASM_END 2269 2270 // -------------------------------------------------------------------------------------------- 2271 ASM_START 2272 biosfn_read_overscan_border_color: 2273 push ax 2274 push bx 2275 mov bl, #0x11 2276 call biosfn_get_single_palette_reg 2277 mov al, bh 2278 pop bx 2279 mov bh, al 2280 pop ax 2281 ret 2282 ASM_END 2283 2284 // -------------------------------------------------------------------------------------------- 2285 ASM_START 2286 biosfn_get_all_palette_reg: 2287 push ax 2288 push bx 2289 push cx 2290 push dx 2291 mov bx, dx 2292 mov cl, #0x00 2293 get_palette_loop: 2294 mov dx, # VGAREG_ACTL_RESET 2295 in al, dx 2296 mov dx, # VGAREG_ACTL_ADDRESS 2297 mov al, cl 2298 out dx, al 2299 mov dx, # VGAREG_ACTL_READ_DATA 2300 in al, dx 2301 seg es 2302 mov [bx], al 2303 inc bx 2304 inc cl 2305 cmp cl, #0x10 2306 jne get_palette_loop 2307 mov dx, # VGAREG_ACTL_RESET 2308 in al, dx 2309 mov dx, # VGAREG_ACTL_ADDRESS 2310 mov al, #0x11 2311 out dx, al 2312 mov dx, # VGAREG_ACTL_READ_DATA 2313 in al, dx 2314 seg es 2315 mov [bx], al 2316 mov dx, # VGAREG_ACTL_RESET 2317 in al, dx 2318 mov dx, # VGAREG_ACTL_ADDRESS 2319 mov al, #0x20 2320 out dx, al 2321 pop dx 2322 pop cx 2323 pop bx 2324 pop ax 2325 ret 2326 ASM_END 2327 2328 // -------------------------------------------------------------------------------------------- 2329 ASM_START 2330 biosfn_set_single_dac_reg: 2331 push ax 2332 push dx 2333 mov dx, # VGAREG_DAC_WRITE_ADDRESS 2334 mov al, bl 2335 out dx, al 2336 mov dx, # VGAREG_DAC_DATA 2337 pop ax 2338 push ax 2339 mov al, ah 2340 out dx, al 2341 mov al, ch 2342 out dx, al 2343 mov al, cl 2344 out dx, al 2345 pop dx 2346 pop ax 2347 ret 2348 ASM_END 2349 2350 // -------------------------------------------------------------------------------------------- 2351 ASM_START 2352 biosfn_set_all_dac_reg: 2353 push ax 2354 push bx 2355 push cx 2356 push dx 2357 mov dx, # VGAREG_DAC_WRITE_ADDRESS 2358 mov al, bl 2359 out dx, al 2360 pop dx 2361 push dx 2362 mov bx, dx 2363 mov dx, # VGAREG_DAC_DATA 2364 set_dac_loop: 2365 seg es 2366 mov al, [bx] 2367 out dx, al 2368 inc bx 2369 seg es 2370 mov al, [bx] 2371 out dx, al 2372 inc bx 2373 seg es 2374 mov al, [bx] 2375 out dx, al 2376 inc bx 2377 dec cx 2378 jnz set_dac_loop 2379 pop dx 2380 pop cx 2381 pop bx 2382 pop ax 2383 ret 2384 ASM_END 2385 2386 // -------------------------------------------------------------------------------------------- 2387 ASM_START 2388 biosfn_select_video_dac_color_page: 2389 push ax 2390 push bx 2391 push dx 2392 mov dx, # VGAREG_ACTL_RESET 2393 in al, dx 2394 mov dx, # VGAREG_ACTL_ADDRESS 2395 mov al, #0x10 2396 out dx, al 2397 mov dx, # VGAREG_ACTL_READ_DATA 2398 in al, dx 2399 and bl, #0x01 2400 jnz set_dac_page 2401 and al, #0x7f 2402 shl bh, 7 2403 or al, bh 2404 mov dx, # VGAREG_ACTL_ADDRESS 2405 out dx, al 2406 jmp set_actl_normal 2407 set_dac_page: 2408 push ax 2409 mov dx, # VGAREG_ACTL_RESET 2410 in al, dx 2411 mov dx, # VGAREG_ACTL_ADDRESS 2412 mov al, #0x14 2413 out dx, al 2414 pop ax 2415 and al, #0x80 2416 jnz set_dac_16_page 2417 shl bh, 2 2418 set_dac_16_page: 2419 and bh, #0x0f 2420 mov al, bh 2421 out dx, al 2422 set_actl_normal: 2423 mov al, #0x20 2424 out dx, al 2425 pop dx 2426 pop bx 2427 pop ax 2428 ret 2429 ASM_END 2430 2431 // -------------------------------------------------------------------------------------------- 2432 ASM_START 2433 biosfn_read_single_dac_reg: 2434 push ax 2435 push dx 2436 mov dx, # VGAREG_DAC_READ_ADDRESS 2437 mov al, bl 2438 out dx, al 2439 pop ax 2440 mov ah, al 2441 mov dx, # VGAREG_DAC_DATA 2442 in al, dx 2443 xchg al, ah 2444 push ax 2445 in al, dx 2446 mov ch, al 2447 in al, dx 2448 mov cl, al 2449 pop dx 2450 pop ax 2451 ret 2452 ASM_END 2453 2454 // -------------------------------------------------------------------------------------------- 2455 ASM_START 2456 biosfn_read_all_dac_reg: 2457 push ax 2458 push bx 2459 push cx 2460 push dx 2461 mov dx, # VGAREG_DAC_READ_ADDRESS 2462 mov al, bl 2463 out dx, al 2464 pop dx 2465 push dx 2466 mov bx, dx 2467 mov dx, # VGAREG_DAC_DATA 2468 read_dac_loop: 2469 in al, dx 2470 seg es 2471 mov [bx], al 2472 inc bx 2473 in al, dx 2474 seg es 2475 mov [bx], al 2476 inc bx 2477 in al, dx 2478 seg es 2479 mov [bx], al 2480 inc bx 2481 dec cx 2482 jnz read_dac_loop 2483 pop dx 2484 pop cx 2485 pop bx 2486 pop ax 2487 ret 2488 ASM_END 2489 2490 // -------------------------------------------------------------------------------------------- 2491 ASM_START 2492 biosfn_set_pel_mask: 2493 push ax 2494 push dx 2495 mov dx, # VGAREG_PEL_MASK 2496 mov al, bl 2497 out dx, al 2498 pop dx 2499 pop ax 2500 ret 2501 ASM_END 2502 2503 // -------------------------------------------------------------------------------------------- 2504 ASM_START 2505 biosfn_read_pel_mask: 2506 push ax 2507 push dx 2508 mov dx, # VGAREG_PEL_MASK 2509 in al, dx 2510 mov bl, al 2511 pop dx 2512 pop ax 2513 ret 2514 ASM_END 2515 2516 // -------------------------------------------------------------------------------------------- 2517 ASM_START 2518 biosfn_read_video_dac_state: 2519 push ax 2520 push dx 2521 mov dx, # VGAREG_ACTL_RESET 2522 in al, dx 2523 mov dx, # VGAREG_ACTL_ADDRESS 2524 mov al, #0x10 2525 out dx, al 2526 mov dx, # VGAREG_ACTL_READ_DATA 2527 in al, dx 2528 mov bl, al 2529 shr bl, 7 2530 mov dx, # VGAREG_ACTL_RESET 2531 in al, dx 2532 mov dx, # VGAREG_ACTL_ADDRESS 2533 mov al, #0x14 2534 out dx, al 2535 mov dx, # VGAREG_ACTL_READ_DATA 2536 in al, dx 2537 mov bh, al 2538 and bh, #0x0f 2539 test bl, #0x01 2540 jnz get_dac_16_page 2541 shr bh, 2 2542 get_dac_16_page: 2543 mov dx, # VGAREG_ACTL_RESET 2544 in al, dx 2545 mov dx, # VGAREG_ACTL_ADDRESS 2546 mov al, #0x20 2547 out dx, al 2548 pop dx 2549 pop ax 2550 ret 2551 ASM_END 2552 2553 // -------------------------------------------------------------------------------------------- 2554 static void biosfn_perform_gray_scale_summing (start,count) 2555 Bit16u start;Bit16u count; 2556 {Bit8u r,g,b; 2557 Bit16u i; 2558 Bit16u index; 2559 2560 inb(VGAREG_ACTL_RESET); 2561 outb(VGAREG_ACTL_ADDRESS,0x00); 2562 2563 for( index = 0; index < count; index++ ) 2564 { 2565 // set read address and switch to read mode 2566 outb(VGAREG_DAC_READ_ADDRESS,start); 2567 // get 6-bit wide RGB data values 2568 r=inb( VGAREG_DAC_DATA ); 2569 g=inb( VGAREG_DAC_DATA ); 2570 b=inb( VGAREG_DAC_DATA ); 2571 2572 // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue ) 2573 i = ( ( 77*r + 151*g + 28*b ) + 0x80 ) >> 8; 2574 2575 if(i>0x3f)i=0x3f; 2576 2577 // set write address and switch to write mode 2578 outb(VGAREG_DAC_WRITE_ADDRESS,start); 2579 // write new intensity value 2580 outb( VGAREG_DAC_DATA, i&0xff ); 2581 outb( VGAREG_DAC_DATA, i&0xff ); 2582 outb( VGAREG_DAC_DATA, i&0xff ); 2583 start++; 2584 } 2585 inb(VGAREG_ACTL_RESET); 2586 outb(VGAREG_ACTL_ADDRESS,0x20); 2587 } 2588 2589 // -------------------------------------------------------------------------------------------- 2590 static void get_font_access() 2591 { 2592 ASM_START 2593 mov dx, # VGAREG_SEQU_ADDRESS 2594 mov ax, #0x0100 2595 out dx, ax 2596 mov ax, #0x0402 2597 out dx, ax 2598 mov ax, #0x0704 2599 out dx, ax 2600 mov ax, #0x0300 2601 out dx, ax 2602 mov dx, # VGAREG_GRDC_ADDRESS 2603 mov ax, #0x0204 2604 out dx, ax 2605 mov ax, #0x0005 2606 out dx, ax 2607 mov ax, #0x0406 2608 out dx, ax 2609 ASM_END 2610 } 2611 2612 static void release_font_access() 2613 { 2614 ASM_START 2615 mov dx, # VGAREG_SEQU_ADDRESS 2616 mov ax, #0x0100 2617 out dx, ax 2618 mov ax, #0x0302 2619 out dx, ax 2620 mov ax, #0x0304 2621 out dx, ax 2622 mov ax, #0x0300 2623 out dx, ax 2624 mov dx, # VGAREG_READ_MISC_OUTPUT 2625 in al, dx 2626 and al, #0x01 2627 shl al, 2 2628 or al, #0x0a 2629 mov ah, al 2630 mov al, #0x06 2631 mov dx, # VGAREG_GRDC_ADDRESS 2632 out dx, ax 2633 mov ax, #0x0004 2634 out dx, ax 2635 mov ax, #0x1005 2636 out dx, ax 2637 ASM_END 2638 } 2639 2640 ASM_START 2641 idiv_u: 2642 xor dx,dx 2643 div bx 2644 ret 2645 ASM_END 2646 2647 static void set_scan_lines(lines) Bit8u lines; 2648 { 2649 Bit16u crtc_addr,cols,page,vde; 2650 Bit8u crtc_r9,ovl,rows; 2651 2652 crtc_addr = read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS); 2653 outb(crtc_addr, 0x09); 2654 crtc_r9 = inb(crtc_addr+1); 2655 crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1); 2656 outb(crtc_addr+1, crtc_r9); 2657 if(lines==8) 2658 { 2659 biosfn_set_cursor_shape(0x06,0x07); 2660 } 2661 else 2662 { 2663 biosfn_set_cursor_shape(lines-4,lines-3); 2664 } 2665 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, lines); 2666 outb(crtc_addr, 0x12); 2667 vde = inb(crtc_addr+1); 2668 outb(crtc_addr, 0x07); 2669 ovl = inb(crtc_addr+1); 2670 vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1); 2671 rows = vde / lines; 2672 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, rows-1); 2673 cols = read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS); 2674 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, rows * cols * 2); 2675 } 2676 2677 static void biosfn_load_text_user_pat (AL,ES,BP,CX,DX,BL,BH) Bit8u AL;Bit16u ES;Bit16u BP;Bit16u CX;Bit16u DX;Bit8u BL;Bit8u BH; 2678 { 2679 Bit16u blockaddr,dest,i,src; 2680 2681 get_font_access(); 2682 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11); 2683 for(i=0;i<CX;i++) 2684 { 2685 src = BP + i * BH; 2686 dest = blockaddr + (DX + i) * 32; 2687 memcpyb(0xA000, dest, ES, src, BH); 2688 } 2689 release_font_access(); 2690 if(AL>=0x10) 2691 { 2692 set_scan_lines(BH); 2693 } 2694 } 2695 2696 static void biosfn_load_text_8_14_pat (AL,BL) Bit8u AL;Bit8u BL; 2697 { 2698 Bit16u blockaddr,dest,i,src; 2699 2700 get_font_access(); 2701 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11); 2702 for(i=0;i<0x100;i++) 2703 { 2704 src = i * 14; 2705 dest = blockaddr + i * 32; 2706 memcpyb(0xA000, dest, 0xC000, vgafont14+src, 14); 2707 } 2708 release_font_access(); 2709 if(AL>=0x10) 2710 { 2711 set_scan_lines(14); 2712 } 2713 } 2714 2715 static void biosfn_load_text_8_8_pat (AL,BL) Bit8u AL;Bit8u BL; 2716 { 2717 Bit16u blockaddr,dest,i,src; 2718 2719 get_font_access(); 2720 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11); 2721 for(i=0;i<0x100;i++) 2722 { 2723 src = i * 8; 2724 dest = blockaddr + i * 32; 2725 memcpyb(0xA000, dest, 0xC000, vgafont8+src, 8); 2726 } 2727 release_font_access(); 2728 if(AL>=0x10) 2729 { 2730 set_scan_lines(8); 2731 } 2732 } 2733 2734 // -------------------------------------------------------------------------------------------- 2735 ASM_START 2736 biosfn_set_text_block_specifier: 2737 push ax 2738 push dx 2739 mov dx, # VGAREG_SEQU_ADDRESS 2740 mov ah, bl 2741 mov al, #0x03 2742 out dx, ax 2743 pop dx 2744 pop ax 2745 ret 2746 ASM_END 2747 2748 // -------------------------------------------------------------------------------------------- 2749 static void biosfn_load_text_8_16_pat (AL,BL) Bit8u AL;Bit8u BL; 2750 { 2751 Bit16u blockaddr,dest,i,src; 2752 2753 get_font_access(); 2754 blockaddr = ((BL & 0x03) << 14) + ((BL & 0x04) << 11); 2755 for(i=0;i<0x100;i++) 2756 { 2757 src = i * 16; 2758 dest = blockaddr + i * 32; 2759 memcpyb(0xA000, dest, 0xC000, vgafont16+src, 16); 2760 } 2761 release_font_access(); 2762 if(AL>=0x10) 2763 { 2764 set_scan_lines(16); 2765 } 2766 } 2767 2768 static void biosfn_load_gfx_8_8_chars (ES,BP) Bit16u ES;Bit16u BP; 2769 { 2770 #ifdef DEBUG 2771 unimplemented(); 2772 #endif 2773 } 2774 static void biosfn_load_gfx_user_chars (ES,BP,CX,BL,DL) Bit16u ES;Bit16u BP;Bit16u CX;Bit8u BL;Bit8u DL; 2775 { 2776 #ifdef DEBUG 2777 unimplemented(); 2778 #endif 2779 } 2780 static void biosfn_load_gfx_8_14_chars (BL) Bit8u BL; 2781 { 2782 #ifdef DEBUG 2783 unimplemented(); 2784 #endif 2785 } 2786 static void biosfn_load_gfx_8_8_dd_chars (BL) Bit8u BL; 2787 { 2788 #ifdef DEBUG 2789 unimplemented(); 2790 #endif 2791 } 2792 static void biosfn_load_gfx_8_16_chars (BL) Bit8u BL; 2793 { 2794 #ifdef DEBUG 2795 unimplemented(); 2796 #endif 2797 } 2798 // -------------------------------------------------------------------------------------------- 2799 static void biosfn_get_font_info (BH,ES,BP,CX,DX) 2800 Bit8u BH;Bit16u *ES;Bit16u *BP;Bit16u *CX;Bit16u *DX; 2801 {Bit16u ss=get_SS(); 2802 2803 switch(BH) 2804 {case 0x00: 2805 write_word(ss,ES,read_word(0x00,0x1f*4)); 2806 write_word(ss,BP,read_word(0x00,(0x1f*4)+2)); 2807 break; 2808 case 0x01: 2809 write_word(ss,ES,read_word(0x00,0x43*4)); 2810 write_word(ss,BP,read_word(0x00,(0x43*4)+2)); 2811 break; 2812 case 0x02: 2813 write_word(ss,ES,0xC000); 2814 write_word(ss,BP,vgafont14); 2815 break; 2816 case 0x03: 2817 write_word(ss,ES,0xC000); 2818 write_word(ss,BP,vgafont8); 2819 break; 2820 case 0x04: 2821 write_word(ss,ES,0xC000); 2822 write_word(ss,BP,vgafont8+128*8); 2823 break; 2824 case 0x05: 2825 write_word(ss,ES,0xC000); 2826 write_word(ss,BP,vgafont14alt); 2827 break; 2828 case 0x06: 2829 write_word(ss,ES,0xC000); 2830 write_word(ss,BP,vgafont16); 2831 break; 2832 case 0x07: 2833 write_word(ss,ES,0xC000); 2834 write_word(ss,BP,vgafont16alt); 2835 break; 2836 default: 2837 #ifdef DEBUG 2838 printf("Get font info BH(%02x) was discarded\n",BH); 2839 #endif 2840 return; 2841 } 2842 // Set byte/char of on screen font 2843 write_word(ss,CX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); 2844 2845 // Set Highest char row 2846 write_word(ss,DX,(Bit16u)read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); 2847 } 2848 2849 // -------------------------------------------------------------------------------------------- 2850 ASM_START 2851 biosfn_get_ega_info: 2852 push ds 2853 push ax 2854 mov ax, # BIOSMEM_SEG 2855 mov ds, ax 2856 xor ch, ch 2857 mov bx, # BIOSMEM_SWITCHES 2858 mov cl, [bx] 2859 and cl, #0x0f 2860 mov bx, # BIOSMEM_CRTC_ADDRESS 2861 mov ax, [bx] 2862 mov bx, #0x0003 2863 cmp ax, # VGAREG_MDA_CRTC_ADDRESS 2864 jne mode_ega_color 2865 mov bh, #0x01 2866 mode_ega_color: 2867 pop ax 2868 pop ds 2869 ret 2870 ASM_END 2871 2872 // -------------------------------------------------------------------------------------------- 2873 static void biosfn_alternate_prtsc() 2874 { 2875 #ifdef DEBUG 2876 unimplemented(); 2877 #endif 2878 } 2879 2880 // -------------------------------------------------------------------------------------------- 2881 ASM_START 2882 biosfn_select_vert_res: 2883 2884 ; res : 00 200 lines, 01 350 lines, 02 400 lines 2885 2886 push ds 2887 push bx 2888 push dx 2889 mov dl, al 2890 mov ax, # BIOSMEM_SEG 2891 mov ds, ax 2892 mov bx, # BIOSMEM_MODESET_CTL 2893 mov al, [bx] 2894 mov bx, # BIOSMEM_SWITCHES 2895 mov ah, [bx] 2896 cmp dl, #0x01 2897 je vert_res_350 2898 jb vert_res_200 2899 cmp dl, #0x02 2900 je vert_res_400 2901 #ifdef DEBUG 2902 mov al, dl 2903 xor ah, ah 2904 push ax 2905 mov bx, #msg_vert_res 2906 push bx 2907 call _printf 2908 add sp, #4 2909 #endif 2910 jmp set_retcode 2911 vert_res_400: 2912 2913 ; reset modeset ctl bit 7 and set bit 4 2914 ; set switches bit 3-0 to 0x09 2915 2916 and al, #0x7f 2917 or al, #0x10 2918 and ah, #0xf0 2919 or ah, #0x09 2920 jnz set_vert_res 2921 vert_res_350: 2922 2923 ; reset modeset ctl bit 7 and bit 4 2924 ; set switches bit 3-0 to 0x09 2925 2926 and al, #0x6f 2927 and ah, #0xf0 2928 or ah, #0x09 2929 jnz set_vert_res 2930 vert_res_200: 2931 2932 ; set modeset ctl bit 7 and reset bit 4 2933 ; set switches bit 3-0 to 0x08 2934 2935 and al, #0xef 2936 or al, #0x80 2937 and ah, #0xf0 2938 or ah, #0x08 2939 set_vert_res: 2940 mov bx, # BIOSMEM_MODESET_CTL 2941 mov [bx], al 2942 mov bx, # BIOSMEM_SWITCHES 2943 mov [bx], ah 2944 set_retcode: 2945 mov ax, #0x1212 2946 pop dx 2947 pop bx 2948 pop ds 2949 ret 2950 2951 #ifdef DEBUG 2952 msg_vert_res: 2953 .ascii "Select vert res (%02x) was discarded" 2954 .byte 0x0d,0x0a,0x00 2955 #endif 2956 2957 2958 biosfn_enable_default_palette_loading: 2959 push ds 2960 push bx 2961 push dx 2962 mov dl, al 2963 and dl, #0x01 2964 shl dl, 3 2965 mov ax, # BIOSMEM_SEG 2966 mov ds, ax 2967 mov bx, # BIOSMEM_MODESET_CTL 2968 mov al, [bx] 2969 and al, #0xf7 2970 or al, dl 2971 mov [bx], al 2972 mov ax, #0x1212 2973 pop dx 2974 pop bx 2975 pop ds 2976 ret 2977 2978 2979 biosfn_enable_video_addressing: 2980 push bx 2981 push dx 2982 mov bl, al 2983 and bl, #0x01 2984 xor bl, #0x01 2985 shl bl, 1 2986 mov dx, # VGAREG_READ_MISC_OUTPUT 2987 in al, dx 2988 and al, #0xfd 2989 or al, bl 2990 mov dx, # VGAREG_WRITE_MISC_OUTPUT 2991 out dx, al 2992 mov ax, #0x1212 2993 pop dx 2994 pop bx 2995 ret 2996 2997 2998 biosfn_enable_grayscale_summing: 2999 push ds 3000 push bx 3001 push dx 3002 mov dl, al 3003 and dl, #0x01 3004 xor dl, #0x01 3005 shl dl, 1 3006 mov ax, # BIOSMEM_SEG 3007 mov ds, ax 3008 mov bx, # BIOSMEM_MODESET_CTL 3009 mov al, [bx] 3010 and al, #0xfd 3011 or al, dl 3012 mov [bx], al 3013 mov ax, #0x1212 3014 pop dx 3015 pop bx 3016 pop ds 3017 ret 3018 3019 3020 biosfn_enable_cursor_emulation: 3021 push ds 3022 push bx 3023 push dx 3024 mov dl, al 3025 and dl, #0x01 3026 xor dl, #0x01 3027 mov ax, # BIOSMEM_SEG 3028 mov ds, ax 3029 mov bx, # BIOSMEM_MODESET_CTL 3030 mov al, [bx] 3031 and al, #0xfe 3032 or al, dl 3033 mov [bx], al 3034 mov ax, #0x1212 3035 pop dx 3036 pop bx 3037 pop ds 3038 ret 3039 ASM_END 3040 3041 // -------------------------------------------------------------------------------------------- 3042 static void biosfn_switch_video_interface (AL,ES,DX) Bit8u AL;Bit16u ES;Bit16u DX; 3043 { 3044 #ifdef DEBUG 3045 unimplemented(); 3046 #endif 3047 } 3048 static void biosfn_enable_video_refresh_control (AL) Bit8u AL; 3049 { 3050 #ifdef DEBUG 3051 unimplemented(); 3052 #endif 3053 } 3054 3055 // -------------------------------------------------------------------------------------------- 3056 static void biosfn_write_string (flag,page,attr,count,row,col,seg,offset) 3057 Bit8u flag;Bit8u page;Bit8u attr;Bit16u count;Bit8u row;Bit8u col;Bit16u seg;Bit16u offset; 3058 { 3059 Bit16u newcurs,oldcurs,dummy; 3060 Bit8u car,carattr; 3061 3062 // Read curs info for the page 3063 biosfn_get_cursor_pos(page,&dummy,&oldcurs); 3064 3065 // if row=0xff special case : use current cursor position 3066 if(row==0xff) 3067 {col=oldcurs&0x00ff; 3068 row=(oldcurs&0xff00)>>8; 3069 } 3070 3071 newcurs=row; newcurs<<=8; newcurs+=col; 3072 biosfn_set_cursor_pos(page,newcurs); 3073 3074 while(count--!=0) 3075 { 3076 car=read_byte(seg,offset++); 3077 if((flag&0x02)!=0) 3078 attr=read_byte(seg,offset++); 3079 3080 biosfn_write_teletype(car,page,attr,WITH_ATTR); 3081 } 3082 3083 // Set back curs pos 3084 if((flag&0x01)==0) 3085 biosfn_set_cursor_pos(page,oldcurs); 3086 } 3087 3088 // -------------------------------------------------------------------------------------------- 3089 ASM_START 3090 biosfn_group_1A: 3091 cmp al, #0x00 3092 je biosfn_read_display_code 3093 cmp al, #0x01 3094 je biosfn_set_display_code 3095 #ifdef DEBUG 3096 call _unknown 3097 #endif 3098 ret 3099 biosfn_read_display_code: 3100 push ds 3101 push ax 3102 mov ax, # BIOSMEM_SEG 3103 mov ds, ax 3104 mov bx, # BIOSMEM_DCC_INDEX 3105 mov al, [bx] 3106 mov bl, al 3107 xor bh, bh 3108 pop ax 3109 mov al, ah 3110 pop ds 3111 ret 3112 biosfn_set_display_code: 3113 push ds 3114 push ax 3115 push bx 3116 mov ax, # BIOSMEM_SEG 3117 mov ds, ax 3118 mov ax, bx 3119 mov bx, # BIOSMEM_DCC_INDEX 3120 mov [bx], al 3121 #ifdef DEBUG 3122 mov al, ah 3123 xor ah, ah 3124 push ax 3125 mov bx, #msg_alt_dcc 3126 push bx 3127 call _printf 3128 add sp, #4 3129 #endif 3130 pop bx 3131 pop ax 3132 mov al, ah 3133 pop ds 3134 ret 3135 3136 #ifdef DEBUG 3137 msg_alt_dcc: 3138 .ascii "Alternate Display code (%02x) was discarded" 3139 .byte 0x0d,0x0a,0x00 3140 #endif 3141 ASM_END 3142 3143 // -------------------------------------------------------------------------------------------- 3144 static void biosfn_read_state_info (BX,ES,DI) 3145 Bit16u BX;Bit16u ES;Bit16u DI; 3146 { 3147 // Address of static functionality table 3148 write_word(ES,DI+0x00,&static_functionality); 3149 write_word(ES,DI+0x02,0xC000); 3150 3151 // Hard coded copy from BIOS area. Should it be cleaner ? 3152 memcpyb(ES,DI+0x04,BIOSMEM_SEG,0x49,30); 3153 memcpyb(ES,DI+0x22,BIOSMEM_SEG,0x84,3); 3154 3155 write_byte(ES,DI+0x25,read_byte(BIOSMEM_SEG,BIOSMEM_DCC_INDEX)); 3156 write_byte(ES,DI+0x26,0); 3157 write_byte(ES,DI+0x27,16); 3158 write_byte(ES,DI+0x28,0); 3159 write_byte(ES,DI+0x29,8); 3160 write_byte(ES,DI+0x2a,2); 3161 write_byte(ES,DI+0x2b,0); 3162 write_byte(ES,DI+0x2c,0); 3163 write_byte(ES,DI+0x31,3); 3164 write_byte(ES,DI+0x32,0); 3165 3166 memsetb(ES,DI+0x33,0,13); 3167 } 3168 3169 // -------------------------------------------------------------------------------------------- 3170 // -------------------------------------------------------------------------------------------- 3171 static Bit16u biosfn_read_video_state_size2 (CX) 3172 Bit16u CX; 3173 { 3174 Bit16u size; 3175 size = 0; 3176 if (CX & 1) { 3177 size += 0x46; 3178 } 3179 if (CX & 2) { 3180 size += (5 + 8 + 5) * 2 + 6; 3181 } 3182 if (CX & 4) { 3183 size += 3 + 256 * 3 + 1; 3184 } 3185 return size; 3186 } 3187 3188 static void biosfn_read_video_state_size (CX, BX) 3189 Bit16u CX; Bit16u *BX; 3190 { 3191 Bit16u ss=get_SS(); 3192 write_word(ss, BX, biosfn_read_video_state_size2(CX)); 3193 } 3194 3195 static Bit16u biosfn_save_video_state (CX,ES,BX) 3196 Bit16u CX;Bit16u ES;Bit16u BX; 3197 { 3198 Bit16u i, v, crtc_addr, ar_index; 3199 3200 crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS); 3201 if (CX & 1) { 3202 write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++; 3203 write_byte(ES, BX, inb(crtc_addr)); BX++; 3204 write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++; 3205 inb(VGAREG_ACTL_RESET); 3206 ar_index = inb(VGAREG_ACTL_ADDRESS); 3207 write_byte(ES, BX, ar_index); BX++; 3208 write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++; 3209 3210 for(i=1;i<=4;i++){ 3211 outb(VGAREG_SEQU_ADDRESS, i); 3212 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++; 3213 } 3214 outb(VGAREG_SEQU_ADDRESS, 0); 3215 write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++; 3216 3217 for(i=0;i<=0x18;i++) { 3218 outb(crtc_addr,i); 3219 write_byte(ES, BX, inb(crtc_addr+1)); BX++; 3220 } 3221 3222 for(i=0;i<=0x13;i++) { 3223 inb(VGAREG_ACTL_RESET); 3224 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20)); 3225 write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++; 3226 } 3227 inb(VGAREG_ACTL_RESET); 3228 3229 for(i=0;i<=8;i++) { 3230 outb(VGAREG_GRDC_ADDRESS,i); 3231 write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++; 3232 } 3233 3234 write_word(ES, BX, crtc_addr); BX+= 2; 3235 3236 /* XXX: read plane latches */ 3237 write_byte(ES, BX, 0); BX++; 3238 write_byte(ES, BX, 0); BX++; 3239 write_byte(ES, BX, 0); BX++; 3240 write_byte(ES, BX, 0); BX++; 3241 } 3242 if (CX & 2) { 3243 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++; 3244 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2; 3245 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2; 3246 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2; 3247 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++; 3248 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2; 3249 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++; 3250 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++; 3251 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++; 3252 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2; 3253 for(i=0;i<8;i++) { 3254 write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i)); 3255 BX += 2; 3256 } 3257 write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2; 3258 write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++; 3259 /* current font */ 3260 write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2; 3261 write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2; 3262 write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2; 3263 write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2; 3264 } 3265 if (CX & 4) { 3266 /* XXX: check this */ 3267 write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */ 3268 write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */ 3269 write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++; 3270 // Set the whole dac always, from 0 3271 outb(VGAREG_DAC_WRITE_ADDRESS,0x00); 3272 for(i=0;i<256*3;i++) { 3273 write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++; 3274 } 3275 write_byte(ES, BX, 0); BX++; /* color select register */ 3276 } 3277 return BX; 3278 } 3279 3280 static Bit16u biosfn_restore_video_state (CX,ES,BX) 3281 Bit16u CX;Bit16u ES;Bit16u BX; 3282 { 3283 Bit16u i, crtc_addr, v, addr1, ar_index; 3284 3285 if (CX & 1) { 3286 // Reset Attribute Ctl flip-flop 3287 inb(VGAREG_ACTL_RESET); 3288 3289 crtc_addr = read_word(ES, BX + 0x40); 3290 addr1 = BX; 3291 BX += 5; 3292 3293 for(i=1;i<=4;i++){ 3294 outb(VGAREG_SEQU_ADDRESS, i); 3295 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++; 3296 } 3297 outb(VGAREG_SEQU_ADDRESS, 0); 3298 outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++; 3299 3300 // Disable CRTC write protection 3301 outw(crtc_addr,0x0011); 3302 // Set CRTC regs 3303 for(i=0;i<=0x18;i++) { 3304 if (i != 0x11) { 3305 outb(crtc_addr,i); 3306 outb(crtc_addr+1, read_byte(ES, BX)); 3307 } 3308 BX++; 3309 } 3310 // select crtc base address 3311 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01; 3312 if (crtc_addr = 0x3d4) 3313 v |= 0x01; 3314 outb(VGAREG_WRITE_MISC_OUTPUT, v); 3315 3316 // enable write protection if needed 3317 outb(crtc_addr, 0x11); 3318 outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11)); 3319 3320 // Set Attribute Ctl 3321 ar_index = read_byte(ES, addr1 + 0x03); 3322 inb(VGAREG_ACTL_RESET); 3323 for(i=0;i<=0x13;i++) { 3324 outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20)); 3325 outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++; 3326 } 3327 outb(VGAREG_ACTL_ADDRESS, ar_index); 3328 inb(VGAREG_ACTL_RESET); 3329 3330 for(i=0;i<=8;i++) { 3331 outb(VGAREG_GRDC_ADDRESS,i); 3332 outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++; 3333 } 3334 BX += 2; /* crtc_addr */ 3335 BX += 4; /* plane latches */ 3336 3337 outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++; 3338 outb(crtc_addr, read_byte(ES, addr1)); addr1++; 3339 outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++; 3340 addr1++; 3341 outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++; 3342 } 3343 if (CX & 2) { 3344 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++; 3345 write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2; 3346 write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2; 3347 write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2; 3348 write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++; 3349 write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2; 3350 write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++; 3351 write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++; 3352 write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++; 3353 write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2; 3354 for(i=0;i<8;i++) { 3355 write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX)); 3356 BX += 2; 3357 } 3358 write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2; 3359 write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++; 3360 /* current font */ 3361 write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2; 3362 write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2; 3363 write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2; 3364 write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2; 3365 } 3366 if (CX & 4) { 3367 BX++; 3368 v = read_byte(ES, BX); BX++; 3369 outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++; 3370 // Set the whole dac always, from 0 3371 outb(VGAREG_DAC_WRITE_ADDRESS,0x00); 3372 for(i=0;i<256*3;i++) { 3373 outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++; 3374 } 3375 BX++; 3376 outb(VGAREG_DAC_WRITE_ADDRESS, v); 3377 } 3378 return BX; 3379 } 3380 3381 // ============================================================================================ 3382 // 3383 // Video Utils 3384 // 3385 // ============================================================================================ 3386 3387 // -------------------------------------------------------------------------------------------- 3388 static Bit8u find_vga_entry(mode) 3389 Bit8u mode; 3390 { 3391 Bit8u i,line=0xFF; 3392 for(i=0;i<=MODE_MAX;i++) 3393 if(vga_modes[i].svgamode==mode) 3394 {line=i; 3395 break; 3396 } 3397 return line; 3398 } 3399 3400 /* =========================================================== */ 3401 /* 3402 * Misc Utils 3403 */ 3404 /* =========================================================== */ 3405 3406 // -------------------------------------------------------------------------------------------- 3407 static void memsetb(seg,offset,value,count) 3408 Bit16u seg; 3409 Bit16u offset; 3410 Bit16u value; 3411 Bit16u count; 3412 { 3413 ASM_START 3414 push bp 3415 mov bp, sp 3416 3417 push ax 3418 push cx 3419 push es 3420 push di 3421 3422 mov cx, 10[bp] ; count 3423 cmp cx, #0x00 3424 je memsetb_end 3425 mov ax, 4[bp] ; segment 3426 mov es, ax 3427 mov ax, 6[bp] ; offset 3428 mov di, ax 3429 mov al, 8[bp] ; value 3430 cld 3431 rep 3432 stosb 3433 3434 memsetb_end: 3435 pop di 3436 pop es 3437 pop cx 3438 pop ax 3439 3440 pop bp 3441 ASM_END 3442 } 3443 3444 // -------------------------------------------------------------------------------------------- 3445 static void memsetw(seg,offset,value,count) 3446 Bit16u seg; 3447 Bit16u offset; 3448 Bit16u value; 3449 Bit16u count; 3450 { 3451 ASM_START 3452 push bp 3453 mov bp, sp 3454 3455 push ax 3456 push cx 3457 push es 3458 push di 3459 3460 mov cx, 10[bp] ; count 3461 cmp cx, #0x00 3462 je memsetw_end 3463 mov ax, 4[bp] ; segment 3464 mov es, ax 3465 mov ax, 6[bp] ; offset 3466 mov di, ax 3467 mov ax, 8[bp] ; value 3468 cld 3469 rep 3470 stosw 3471 3472 memsetw_end: 3473 pop di 3474 pop es 3475 pop cx 3476 pop ax 3477 3478 pop bp 3479 ASM_END 3480 } 3481 3482 // -------------------------------------------------------------------------------------------- 3483 static void memcpyb(dseg,doffset,sseg,soffset,count) 3484 Bit16u dseg; 3485 Bit16u doffset; 3486 Bit16u sseg; 3487 Bit16u soffset; 3488 Bit16u count; 3489 { 3490 ASM_START 3491 push bp 3492 mov bp, sp 3493 3494 push ax 3495 push cx 3496 push es 3497 push di 3498 push ds 3499 push si 3500 3501 mov cx, 12[bp] ; count 3502 cmp cx, #0x0000 3503 je memcpyb_end 3504 mov ax, 4[bp] ; dsegment 3505 mov es, ax 3506 mov ax, 6[bp] ; doffset 3507 mov di, ax 3508 mov ax, 8[bp] ; ssegment 3509 mov ds, ax 3510 mov ax, 10[bp] ; soffset 3511 mov si, ax 3512 cld 3513 rep 3514 movsb 3515 3516 memcpyb_end: 3517 pop si 3518 pop ds 3519 pop di 3520 pop es 3521 pop cx 3522 pop ax 3523 3524 pop bp 3525 ASM_END 3526 } 3527 3528 // -------------------------------------------------------------------------------------------- 3529 static void memcpyw(dseg,doffset,sseg,soffset,count) 3530 Bit16u dseg; 3531 Bit16u doffset; 3532 Bit16u sseg; 3533 Bit16u soffset; 3534 Bit16u count; 3535 { 3536 ASM_START 3537 push bp 3538 mov bp, sp 3539 3540 push ax 3541 push cx 3542 push es 3543 push di 3544 push ds 3545 push si 3546 3547 mov cx, 12[bp] ; count 3548 cmp cx, #0x0000 3549 je memcpyw_end 3550 mov ax, 4[bp] ; dsegment 3551 mov es, ax 3552 mov ax, 6[bp] ; doffset 3553 mov di, ax 3554 mov ax, 8[bp] ; ssegment 3555 mov ds, ax 3556 mov ax, 10[bp] ; soffset 3557 mov si, ax 3558 cld 3559 rep 3560 movsw 3561 3562 memcpyw_end: 3563 pop si 3564 pop ds 3565 pop di 3566 pop es 3567 pop cx 3568 pop ax 3569 3570 pop bp 3571 ASM_END 3572 } 3573 3574 /* =========================================================== */ 3575 /* 3576 * These functions where ripped from Kevin's rombios.c 3577 */ 3578 /* =========================================================== */ 3579 3580 // -------------------------------------------------------------------------------------------- 3581 static Bit8u 3582 read_byte(seg, offset) 3583 Bit16u seg; 3584 Bit16u offset; 3585 { 3586 ASM_START 3587 push bp 3588 mov bp, sp 3589 3590 push bx 3591 push ds 3592 mov ax, 4[bp] ; segment 3593 mov ds, ax 3594 mov bx, 6[bp] ; offset 3595 mov al, [bx] 3596 ;; al = return value (byte) 3597 pop ds 3598 pop bx 3599 3600 pop bp 3601 ASM_END 3602 } 3603 3604 // -------------------------------------------------------------------------------------------- 3605 static Bit16u 3606 read_word(seg, offset) 3607 Bit16u seg; 3608 Bit16u offset; 3609 { 3610 ASM_START 3611 push bp 3612 mov bp, sp 3613 3614 push bx 3615 push ds 3616 mov ax, 4[bp] ; segment 3617 mov ds, ax 3618 mov bx, 6[bp] ; offset 3619 mov ax, [bx] 3620 ;; ax = return value (word) 3621 pop ds 3622 pop bx 3623 3624 pop bp 3625 ASM_END 3626 } 3627 3628 // -------------------------------------------------------------------------------------------- 3629 static void 3630 write_byte(seg, offset, data) 3631 Bit16u seg; 3632 Bit16u offset; 3633 Bit8u data; 3634 { 3635 ASM_START 3636 push bp 3637 mov bp, sp 3638 3639 push ax 3640 push bx 3641 push ds 3642 mov ax, 4[bp] ; segment 3643 mov ds, ax 3644 mov bx, 6[bp] ; offset 3645 mov al, 8[bp] ; data byte 3646 mov [bx], al ; write data byte 3647 pop ds 3648 pop bx 3649 pop ax 3650 3651 pop bp 3652 ASM_END 3653 } 3654 3655 // -------------------------------------------------------------------------------------------- 3656 static void 3657 write_word(seg, offset, data) 3658 Bit16u seg; 3659 Bit16u offset; 3660 Bit16u data; 3661 { 3662 ASM_START 3663 push bp 3664 mov bp, sp 3665 3666 push ax 3667 push bx 3668 push ds 3669 mov ax, 4[bp] ; segment 3670 mov ds, ax 3671 mov bx, 6[bp] ; offset 3672 mov ax, 8[bp] ; data word 3673 mov [bx], ax ; write data word 3674 pop ds 3675 pop bx 3676 pop ax 3677 3678 pop bp 3679 ASM_END 3680 } 3681 3682 // -------------------------------------------------------------------------------------------- 3683 Bit8u 3684 inb(port) 3685 Bit16u port; 3686 { 3687 ASM_START 3688 push bp 3689 mov bp, sp 3690 3691 push dx 3692 mov dx, 4[bp] 3693 in al, dx 3694 pop dx 3695 3696 pop bp 3697 ASM_END 3698 } 3699 3700 Bit16u 3701 inw(port) 3702 Bit16u port; 3703 { 3704 ASM_START 3705 push bp 3706 mov bp, sp 3707 3708 push dx 3709 mov dx, 4[bp] 3710 in ax, dx 3711 pop dx 3712 3713 pop bp 3714 ASM_END 3715 } 3716 3717 // -------------------------------------------------------------------------------------------- 3718 void 3719 outb(port, val) 3720 Bit16u port; 3721 Bit8u val; 3722 { 3723 ASM_START 3724 push bp 3725 mov bp, sp 3726 3727 push ax 3728 push dx 3729 mov dx, 4[bp] 3730 mov al, 6[bp] 3731 out dx, al 3732 pop dx 3733 pop ax 3734 3735 pop bp 3736 ASM_END 3737 } 3738 3739 // -------------------------------------------------------------------------------------------- 3740 void 3741 outw(port, val) 3742 Bit16u port; 3743 Bit16u val; 3744 { 3745 ASM_START 3746 push bp 3747 mov bp, sp 3748 3749 push ax 3750 push dx 3751 mov dx, 4[bp] 3752 mov ax, 6[bp] 3753 out dx, ax 3754 pop dx 3755 pop ax 3756 3757 pop bp 3758 ASM_END 3759 } 3760 3761 Bit16u get_SS() 3762 { 3763 ASM_START 3764 mov ax, ss 3765 ASM_END 3766 } 3767 3768 #ifdef DEBUG 3769 void unimplemented() 3770 { 3771 printf("--> Unimplemented\n"); 3772 } 3773 3774 void unknown() 3775 { 3776 printf("--> Unknown int10\n"); 3777 } 3778 #endif 3779 3780 // -------------------------------------------------------------------------------------------- 3781 #if defined(USE_BX_INFO) || defined(DEBUG) || defined(CIRRUS_DEBUG) 3782 void printf(s) 3783 Bit8u *s; 3784 { 3785 Bit8u c, format_char; 3786 Boolean in_format; 3787 unsigned format_width, i; 3788 Bit16u *arg_ptr; 3789 Bit16u arg_seg, arg, digit, nibble, shift_count; 3790 3791 arg_ptr = &s; 3792 arg_seg = get_SS(); 3793 3794 in_format = 0; 3795 format_width = 0; 3796 3797 while (c = read_byte(0xc000, s)) { 3798 if ( c == '%' ) { 3799 in_format = 1; 3800 format_width = 0; 3801 } 3802 else if (in_format) { 3803 if ( (c>='0') && (c<='9') ) { 3804 format_width = (format_width * 10) + (c - '0'); 3805 } 3806 else if (c == 'x') { 3807 arg_ptr++; // increment to next arg 3808 arg = read_word(arg_seg, arg_ptr); 3809 if (format_width == 0) 3810 format_width = 4; 3811 i = 0; 3812 digit = format_width - 1; 3813 for (i=0; i<format_width; i++) { 3814 nibble = (arg >> (4 * digit)) & 0x000f; 3815 if (nibble <= 9) 3816 outb(0x0500, nibble + '0'); 3817 else 3818 outb(0x0500, (nibble - 10) + 'A'); 3819 digit--; 3820 } 3821 in_format = 0; 3822 } 3823 //else if (c == 'd') { 3824 // in_format = 0; 3825 // } 3826 } 3827 else { 3828 outb(0x0500, c); 3829 } 3830 s ++; 3831 } 3832 } 3833 #endif 3834 3835 ASM_START 3836 ; get LFB address from PCI 3837 ; in - ax: PCI device vendor 3838 ; out - ax: LFB address (high 16 bit) 3839 ;; NOTE - may be called in protected mode 3840 _pci_get_lfb_addr: 3841 push bx 3842 push cx 3843 push dx 3844 push eax 3845 mov bx, ax 3846 xor cx, cx 3847 mov dl, #0x00 3848 call pci_read_reg 3849 cmp ax, #0xffff 3850 jz pci_get_lfb_addr_5 3851 pci_get_lfb_addr_3: 3852 mov dl, #0x00 3853 call pci_read_reg 3854 cmp ax, bx ;; check vendor 3855 jz pci_get_lfb_addr_4 3856 add cx, #0x8 3857 cmp cx, #0x200 ;; search bus #0 and #1 3858 jb pci_get_lfb_addr_3 3859 pci_get_lfb_addr_5: 3860 xor dx, dx ;; no LFB 3861 jmp pci_get_lfb_addr_6 3862 pci_get_lfb_addr_4: 3863 mov dl, #0x10 ;; I/O space #0 3864 call pci_read_reg 3865 test ax, #0xfff1 3866 jnz pci_get_lfb_addr_5 3867 shr eax, #16 3868 mov dx, ax ;; LFB address 3869 pci_get_lfb_addr_6: 3870 pop eax 3871 mov ax, dx 3872 pop dx 3873 pop cx 3874 pop bx 3875 ret 3876 3877 ; read PCI register 3878 ; in - cx: device/function 3879 ; in - dl: register 3880 ; out - eax: value 3881 pci_read_reg: 3882 mov eax, #0x00800000 3883 mov ax, cx 3884 shl eax, #8 3885 mov al, dl 3886 mov dx, #0xcf8 3887 out dx, eax 3888 add dl, #4 3889 in eax, dx 3890 ret 3891 ASM_END 3892 3893 #ifdef VBE 3894 #include "vbe.c" 3895 #endif 3896 3897 #ifdef CIRRUS 3898 #include "clext.c" 3899 #endif 3900 3901 // -------------------------------------------------------------------------------------------- 3902 3903 ASM_START 3904 ;; DATA_SEG_DEFS_HERE 3905 ASM_END 3906 3907 ASM_START 3908 .ascii "vgabios ends here" 3909 .byte 0x00 3910 vgabios_end: 3911 .byte 0xCB 3912 ;; BLOCK_STRINGS_BEGIN 3913 ASM_END 3914