~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Bochs x86 Emulator
bochs/bios/rombios.c

Version: ~ [ 2.3.5 ] ~ [ 2.3 ] ~

** Warning: Cannot open xref database.

1 ///////////////////////////////////////////////////////////////////////// 2 // $Id: rombios.c,v 1.183 2007/09/10 20:00:29 vruppert Exp $ 3 ///////////////////////////////////////////////////////////////////////// 4 // 5 // Copyright (C) 2002 MandrakeSoft S.A. 6 // 7 // MandrakeSoft S.A. 8 // 43, rue d'Aboukir 9 // 75002 Paris - France 10 // http://www.linux-mandrake.com/ 11 // http://www.mandrakesoft.com/ 12 // 13 // This library is free software; you can redistribute it and/or 14 // modify it under the terms of the GNU Lesser General Public 15 // License as published by the Free Software Foundation; either 16 // version 2 of the License, or (at your option) any later version. 17 // 18 // This library is distributed in the hope that it will be useful, 19 // but WITHOUT ANY WARRANTY; without even the implied warranty of 20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 // Lesser General Public License for more details. 22 // 23 // You should have received a copy of the GNU Lesser General Public 24 // License along with this library; if not, write to the Free Software 25 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 26 27 // ROM BIOS for use with Bochs/Plex86/QEMU emulation environment 28 29 30 // ROM BIOS compatability entry points: 31 // =================================== 32 // $e05b ; POST Entry Point 33 // $e2c3 ; NMI Handler Entry Point 34 // $e3fe ; INT 13h Fixed Disk Services Entry Point 35 // $e401 ; Fixed Disk Parameter Table 36 // $e6f2 ; INT 19h Boot Load Service Entry Point 37 // $e6f5 ; Configuration Data Table 38 // $e729 ; Baud Rate Generator Table 39 // $e739 ; INT 14h Serial Communications Service Entry Point 40 // $e82e ; INT 16h Keyboard Service Entry Point 41 // $e987 ; INT 09h Keyboard Service Entry Point 42 // $ec59 ; INT 13h Diskette Service Entry Point 43 // $ef57 ; INT 0Eh Diskette Hardware ISR Entry Point 44 // $efc7 ; Diskette Controller Parameter Table 45 // $efd2 ; INT 17h Printer Service Entry Point 46 // $f045 ; INT 10 Functions 0-Fh Entry Point 47 // $f065 ; INT 10h Video Support Service Entry Point 48 // $f0a4 ; MDA/CGA Video Parameter Table (INT 1Dh) 49 // $f841 ; INT 12h Memory Size Service Entry Point 50 // $f84d ; INT 11h Equipment List Service Entry Point 51 // $f859 ; INT 15h System Services Entry Point 52 // $fa6e ; Character Font for 320x200 & 640x200 Graphics (lower 128 characters) 53 // $fe6e ; INT 1Ah Time-of-day Service Entry Point 54 // $fea5 ; INT 08h System Timer ISR Entry Point 55 // $fef3 ; Initial Interrupt Vector Offsets Loaded by POST 56 // $ff53 ; IRET Instruction for Dummy Interrupt Handler 57 // $ff54 ; INT 05h Print Screen Service Entry Point 58 // $fff0 ; Power-up Entry Point 59 // $fff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY 60 // $fffe ; System Model ID 61 62 // NOTES for ATA/ATAPI driver (cbbochs@free.fr) 63 // Features 64 // - supports up to 4 ATA interfaces 65 // - device/geometry detection 66 // - 16bits/32bits device access 67 // - pchs/lba access 68 // - datain/dataout/packet command support 69 // 70 // NOTES for El-Torito Boot (cbbochs@free.fr) 71 // - CD-ROM booting is only available if ATA/ATAPI Driver is available 72 // - Current code is only able to boot mono-session cds 73 // - Current code can not boot and emulate a hard-disk 74 // the bios will panic otherwise 75 // - Current code also use memory in EBDA segement. 76 // - I used cmos byte 0x3D to store extended information on boot-device 77 // - Code has to be modified modified to handle multiple cdrom drives 78 // - Here are the cdrom boot failure codes: 79 // 1 : no atapi device found 80 // 2 : no atapi cdrom found 81 // 3 : can not read cd - BRVD 82 // 4 : cd is not eltorito (BRVD) 83 // 5 : cd is not eltorito (ISO TAG) 84 // 6 : cd is not eltorito (ELTORITO TAG) 85 // 7 : can not read cd - boot catalog 86 // 8 : boot catalog : bad header 87 // 9 : boot catalog : bad platform 88 // 10 : boot catalog : bad signature 89 // 11 : boot catalog : bootable flag not set 90 // 12 : can not read cd - boot image 91 // 92 // ATA driver 93 // - EBDA segment. 94 // I used memory starting at 0x121 in the segment 95 // - the translation policy is defined in cmos regs 0x39 & 0x3a 96 // 97 // TODO : 98 // 99 // int74 100 // - needs to be reworked. Uses direct [bp] offsets. (?) 101 // 102 // int13: 103 // - f04 (verify sectors) isn't complete (?) 104 // - f02/03/04 should set current cyl,etc in BDA (?) 105 // - rewrite int13_relocated & clean up int13 entry code 106 // 107 // NOTES: 108 // - NMI access (bit7 of addr written to 70h) 109 // 110 // ATA driver 111 // - should handle the "don't detect" bit (cmos regs 0x3b & 0x3c) 112 // - could send the multiple-sector read/write commands 113 // 114 // El-Torito 115 // - Emulate a Hard-disk (currently only diskette can be emulated) see "FIXME ElTorito Harddisk" 116 // - Implement remaining int13_cdemu functions (as defined by El-Torito specs) 117 // - cdrom drive is hardcoded to ide 0 device 1 in several places. see "FIXME ElTorito Hardcoded" 118 // - int13 Fix DL when emulating a cd. In that case DL is decremented before calling real int13. 119 // This is ok. But DL should be reincremented afterwards. 120 // - Fix all "FIXME ElTorito Various" 121 // - should be able to boot any cdrom instead of the first one 122 // 123 // BCC Bug: find a generic way to handle the bug of #asm after an "if" (fixed in 0.16.7) 124 125 #include "rombios.h" 126 127 #define DEBUG_ATA 0 128 #define DEBUG_INT13_HD 0 129 #define DEBUG_INT13_CD 0 130 #define DEBUG_INT13_ET 0 131 #define DEBUG_INT13_FL 0 132 #define DEBUG_INT15 0 133 #define DEBUG_INT16 0 134 #define DEBUG_INT1A 0 135 #define DEBUG_INT74 0 136 #define DEBUG_APM 0 137 138 #define BX_CPU 3 139 #define BX_USE_PS2_MOUSE 1 140 #define BX_CALL_INT15_4F 1 141 #define BX_USE_EBDA 1 142 #define BX_SUPPORT_FLOPPY 1 143 #define BX_FLOPPY_ON_CNT 37 /* 2 seconds */ 144 #define BX_PCIBIOS 1 145 #define BX_APM 1 146 147 #define BX_USE_ATADRV 1 148 #define BX_ELTORITO_BOOT 1 149 150 #define BX_MAX_ATA_INTERFACES 4 151 #define BX_MAX_ATA_DEVICES (BX_MAX_ATA_INTERFACES*2) 152 153 #define BX_VIRTUAL_PORTS 1 /* normal output to Bochs ports */ 154 #define BX_DEBUG_SERIAL 0 /* output to COM1 */ 155 156 /* model byte 0xFC = AT */ 157 #define SYS_MODEL_ID 0xFC 158 #define SYS_SUBMODEL_ID 0x00 159 #define BIOS_REVISION 1 160 #define BIOS_CONFIG_TABLE 0xe6f5 161 162 #ifndef BIOS_BUILD_DATE 163 # define BIOS_BUILD_DATE "06/23/99" 164 #endif 165 166 // 1K of base memory used for Extended Bios Data Area (EBDA) 167 // EBDA is used for PS/2 mouse support, and IDE BIOS, etc. 168 #define EBDA_SEG 0x9FC0 169 #define EBDA_SIZE 1 // In KiB 170 #define BASE_MEM_IN_K (640 - EBDA_SIZE) 171 172 // Define the application NAME 173 #if defined(BX_QEMU) 174 # define BX_APPNAME "QEMU" 175 #elif defined(PLEX86) 176 # define BX_APPNAME "Plex86" 177 #else 178 # define BX_APPNAME "Bochs" 179 #endif 180 181 // Sanity Checks 182 #if BX_USE_ATADRV && BX_CPU<3 183 # error The ATA/ATAPI Driver can only to be used with a 386+ cpu 184 #endif 185 #if BX_USE_ATADRV && !BX_USE_EBDA 186 # error ATA/ATAPI Driver can only be used if EBDA is available 187 #endif 188 #if BX_ELTORITO_BOOT && !BX_USE_ATADRV 189 # error El-Torito Boot can only be use if ATA/ATAPI Driver is available 190 #endif 191 #if BX_PCIBIOS && BX_CPU<3 192 # error PCI BIOS can only be used with 386+ cpu 193 #endif 194 #if BX_APM && BX_CPU<3 195 # error APM BIOS can only be used with 386+ cpu 196 #endif 197 198 // define this if you want to make PCIBIOS working on a specific bridge only 199 // undef enables PCIBIOS when at least one PCI device is found 200 // i440FX is emulated by Bochs and QEMU 201 #define PCI_FIXED_HOST_BRIDGE 0x12378086 ;; i440FX PCI bridge 202 203 // #20 is dec 20 204 // #$20 is hex 20 = 32 205 // #0x20 is hex 20 = 32 206 // LDA #$20 207 // JSR $E820 208 // LDD .i,S 209 // JSR $C682 210 // mov al, #$20 211 212 // all hex literals should be prefixed with '0x' 213 // grep "#[0-9a-fA-F][0-9a-fA-F]" rombios.c 214 // no mov SEG-REG, #value, must mov register into seg-reg 215 // grep -i "mov[ ]*.s" rombios.c 216 217 // This is for compiling with gcc2 and gcc3 218 #define ASM_START #asm 219 #define ASM_END #endasm 220 221 ASM_START 222 .rom 223 224 .org 0x0000 225 226 #if BX_CPU >= 3 227 use16 386 228 #else 229 use16 286 230 #endif 231 232 MACRO HALT 233 ;; the HALT macro is called with the line number of the HALT call. 234 ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex 235 ;; to print a BX_PANIC message. This will normally halt the simulation 236 ;; with a message such as "BIOS panic at rombios.c, line 4091". 237 ;; However, users can choose to make panics non-fatal and continue. 238 #if BX_VIRTUAL_PORTS 239 mov dx,#PANIC_PORT 240 mov ax,#?1 241 out dx,ax 242 #else 243 mov dx,#0x80 244 mov ax,#?1 245 out dx,al 246 #endif 247 MEND 248 249 MACRO JMP_AP 250 db 0xea 251 dw ?2 252 dw ?1 253 MEND 254 255 MACRO SET_INT_VECTOR 256 mov ax, ?3 257 mov ?1*4, ax 258 mov ax, ?2 259 mov ?1*4+2, ax 260 MEND 261 262 ASM_END 263 264 typedef unsigned char Bit8u; 265 typedef unsigned short Bit16u; 266 typedef unsigned short bx_bool; 267 typedef unsigned long Bit32u; 268 269 270 void memsetb(seg,offset,value,count); 271 void memcpyb(dseg,doffset,sseg,soffset,count); 272 void memcpyd(dseg,doffset,sseg,soffset,count); 273 274 // memset of count bytes 275 void 276 memsetb(seg,offset,value,count) 277 Bit16u seg; 278 Bit16u offset; 279 Bit16u value; 280 Bit16u count; 281 { 282 ASM_START 283 push bp 284 mov bp, sp 285 286 push ax 287 push cx 288 push es 289 push di 290 291 mov cx, 10[bp] ; count 292 cmp cx, #0x00 293 je memsetb_end 294 mov ax, 4[bp] ; segment 295 mov es, ax 296 mov ax, 6[bp] ; offset 297 mov di, ax 298 mov al, 8[bp] ; value 299 cld 300 rep 301 stosb 302 303 memsetb_end: 304 pop di 305 pop es 306 pop cx 307 pop ax 308 309 pop bp 310 ASM_END 311 } 312 313 // memcpy of count bytes 314 void 315 memcpyb(dseg,doffset,sseg,soffset,count) 316 Bit16u dseg; 317 Bit16u doffset; 318 Bit16u sseg; 319 Bit16u soffset; 320 Bit16u count; 321 { 322 ASM_START 323 push bp 324 mov bp, sp 325 326 push ax 327 push cx 328 push es 329 push di 330 push ds 331 push si 332 333 mov cx, 12[bp] ; count 334 cmp cx, #0x0000 335 je memcpyb_end 336 mov ax, 4[bp] ; dsegment 337 mov es, ax 338 mov ax, 6[bp] ; doffset 339 mov di, ax 340 mov ax, 8[bp] ; ssegment 341 mov ds, ax 342 mov ax, 10[bp] ; soffset 343 mov si, ax 344 cld 345 rep 346 movsb 347 348 memcpyb_end: 349 pop si 350 pop ds 351 pop di 352 pop es 353 pop cx 354 pop ax 355 356 pop bp 357 ASM_END 358 } 359 360 // memcpy of count dword 361 void 362 memcpyd(dseg,doffset,sseg,soffset,count) 363 Bit16u dseg; 364 Bit16u doffset; 365 Bit16u sseg; 366 Bit16u soffset; 367 Bit16u count; 368 { 369 ASM_START 370 push bp 371 mov bp, sp 372 373 push ax 374 push cx 375 push es 376 push di 377 push ds 378 push si 379 380 mov cx, 12[bp] ; count 381 cmp cx, #0x0000 382 je memcpyd_end 383 mov ax, 4[bp] ; dsegment 384 mov es, ax 385 mov ax, 6[bp] ; doffset 386 mov di, ax 387 mov ax, 8[bp] ; ssegment 388 mov ds, ax 389 mov ax, 10[bp] ; soffset 390 mov si, ax 391 cld 392 rep 393 movsd 394 395 memcpyd_end: 396 pop si 397 pop ds 398 pop di 399 pop es 400 pop cx 401 pop ax 402 403 pop bp 404 ASM_END 405 } 406 407 // read_dword and write_dword functions 408 static Bit32u read_dword(); 409 static void write_dword(); 410 411 Bit32u 412 read_dword(seg, offset) 413 Bit16u seg; 414 Bit16u offset; 415 { 416 ASM_START 417 push bp 418 mov bp, sp 419 420 push bx 421 push ds 422 mov ax, 4[bp] ; segment 423 mov ds, ax 424 mov bx, 6[bp] ; offset 425 mov ax, [bx] 426 inc bx 427 inc bx 428 mov dx, [bx] 429 ;; ax = return value (word) 430 ;; dx = return value (word) 431 pop ds 432 pop bx 433 434 pop bp 435 ASM_END 436 } 437 438 void 439 write_dword(seg, offset, data) 440 Bit16u seg; 441 Bit16u offset; 442 Bit32u data; 443 { 444 ASM_START 445 push bp 446 mov bp, sp 447 448 push ax 449 push bx 450 push ds 451 mov ax, 4[bp] ; segment 452 mov ds, ax 453 mov bx, 6[bp] ; offset 454 mov ax, 8[bp] ; data word 455 mov [bx], ax ; write data word 456 inc bx 457 inc bx 458 mov ax, 10[bp] ; data word 459 mov [bx], ax ; write data word 460 pop ds 461 pop bx 462 pop ax 463 464 pop bp 465 ASM_END 466 } 467 468 // Bit32u (unsigned long) and long helper functions 469 ASM_START 470 471 ;; and function 472 landl: 473 landul: 474 SEG SS 475 and ax,[di] 476 SEG SS 477 and bx,2[di] 478 ret 479 480 ;; add function 481 laddl: 482 laddul: 483 SEG SS 484 add ax,[di] 485 SEG SS 486 adc bx,2[di] 487 ret 488 489 ;; cmp function 490 lcmpl: 491 lcmpul: 492 and eax, #0x0000FFFF 493 shl ebx, #16 494 add eax, ebx 495 shr ebx, #16 496 SEG SS 497 cmp eax, dword ptr [di] 498 ret 499 500 ;; sub function 501 lsubl: 502 lsubul: 503 SEG SS 504 sub ax,[di] 505 SEG SS 506 sbb bx,2[di] 507 ret 508 509 ;; mul function 510 lmull: 511 lmulul: 512 and eax, #0x0000FFFF 513 shl ebx, #16 514 add eax, ebx 515 SEG SS 516 mul eax, dword ptr [di] 517 mov ebx, eax 518 shr ebx, #16 519 ret 520 521 ;; dec function 522 ldecl: 523 ldecul: 524 SEG SS 525 dec dword ptr [bx] 526 ret 527 528 ;; or function 529 lorl: 530 lorul: 531 SEG SS 532 or ax,[di] 533 SEG SS 534 or bx,2[di] 535 ret 536 537 ;; inc function 538 lincl: 539 lincul: 540 SEG SS 541 inc dword ptr [bx] 542 ret 543 544 ;; tst function 545 ltstl: 546 ltstul: 547 and eax, #0x0000FFFF 548 shl ebx, #16 549 add eax, ebx 550 shr ebx, #16 551 test eax, eax 552 ret 553 554 ;; sr function 555 lsrul: 556 mov cx,di 557 jcxz lsr_exit 558 and eax, #0x0000FFFF 559 shl ebx, #16 560 add eax, ebx 561 lsr_loop: 562 shr eax, #1 563 loop lsr_loop 564 mov ebx, eax 565 shr ebx, #16 566 lsr_exit: 567 ret 568 569 ;; sl function 570 lsll: 571 lslul: 572 mov cx,di 573 jcxz lsl_exit 574 and eax, #0x0000FFFF 575 shl ebx, #16 576 add eax, ebx 577 lsl_loop: 578 shl eax, #1 579 loop lsl_loop 580 mov ebx, eax 581 shr ebx, #16 582 lsl_exit: 583 ret 584 585 idiv_: 586 cwd 587 idiv bx 588 ret 589 590 idiv_u: 591 xor dx,dx 592 div bx 593 ret 594 595 ldivul: 596 and eax, #0x0000FFFF 597 shl ebx, #16 598 add eax, ebx 599 xor edx, edx 600 SEG SS 601 mov bx, 2[di] 602 shl ebx, #16 603 SEG SS 604 mov bx, [di] 605 div ebx 606 mov ebx, eax 607 shr ebx, #16 608 ret 609 610 ASM_END 611 612 // for access to RAM area which is used by interrupt vectors 613 // and BIOS Data Area 614 615 typedef struct { 616 unsigned char filler1[0x400]; 617 unsigned char filler2[0x6c]; 618 Bit16u ticks_low; 619 Bit16u ticks_high; 620 Bit8u midnight_flag; 621 } bios_data_t; 622 623 #define BiosData ((bios_data_t *) 0) 624 625 #if BX_USE_ATADRV 626 typedef struct { 627 Bit16u heads; // # heads 628 Bit16u cylinders; // # cylinders 629 Bit16u spt; // # sectors / track 630 } chs_t; 631 632 // DPTE definition 633 typedef struct { 634 Bit16u iobase1; 635 Bit16u iobase2; 636 Bit8u prefix; 637 Bit8u unused; 638 Bit8u irq; 639 Bit8u blkcount; 640 Bit8u dma; 641 Bit8u pio; 642 Bit16u options; 643 Bit16u reserved; 644 Bit8u revision; 645 Bit8u checksum; 646 } dpte_t; 647 648 typedef struct { 649 Bit8u iface; // ISA or PCI 650 Bit16u iobase1; // IO Base 1 651 Bit16u iobase2; // IO Base 2 652 Bit8u irq; // IRQ 653 } ata_channel_t; 654 655 typedef struct { 656 Bit8u type; // Detected type of ata (ata/atapi/none/unknown) 657 Bit8u device; // Detected type of attached devices (hd/cd/none) 658 Bit8u removable; // Removable device flag 659 Bit8u lock; // Locks for removable devices 660 // Bit8u lba_capable; // LBA capable flag - always yes for bochs devices 661 Bit8u mode; // transfert mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA 662 Bit16u blksize; // block size 663 664 Bit8u translation; // type of translation 665 chs_t lchs; // Logical CHS 666 chs_t pchs; // Physical CHS 667 668 Bit32u sectors; // Total sectors count 669 } ata_device_t; 670 671 typedef struct { 672 // ATA channels info 673 ata_channel_t channels[BX_MAX_ATA_INTERFACES]; 674 675 // ATA devices info 676 ata_device_t devices[BX_MAX_ATA_DEVICES]; 677 // 678 // map between (bios hd id - 0x80) and ata channels 679 Bit8u hdcount, hdidmap[BX_MAX_ATA_DEVICES]; 680 681 // map between (bios cd id - 0xE0) and ata channels 682 Bit8u cdcount, cdidmap[BX_MAX_ATA_DEVICES]; 683 684 // Buffer for DPTE table 685 dpte_t dpte; 686 687 // Count of transferred sectors and bytes 688 Bit16u trsfsectors; 689 Bit32u trsfbytes; 690 691 } ata_t; 692 693 #if BX_ELTORITO_BOOT 694 // ElTorito Device Emulation data 695 typedef struct { 696 Bit8u active; 697 Bit8u media; 698 Bit8u emulated_drive; 699 Bit8u controller_index; 700 Bit16u device_spec; 701 Bit32u ilba; 702 Bit16u buffer_segment; 703 Bit16u load_segment; 704 Bit16u sector_count; 705 706 // Virtual device 707 chs_t vdevice; 708 } cdemu_t; 709 #endif // BX_ELTORITO_BOOT 710 711 // for access to EBDA area 712 // The EBDA structure should conform to 713 // http://www.frontiernet.net/~fys/rombios.htm document 714 // I made the ata and cdemu structs begin at 0x121 in the EBDA seg 715 // EBDA must be at most 768 bytes; it lives at 0x9fc00, and the boot 716 // device tables are at 0x9ff00 -- 0x9ffff 717 typedef struct { 718 unsigned char filler1[0x3D]; 719 720 // FDPT - Can be splitted in data members if needed 721 unsigned char fdpt0[0x10]; 722 unsigned char fdpt1[0x10]; 723 724 unsigned char filler2[0xC4]; 725 726 // ATA Driver data 727 ata_t ata; 728 729 #if BX_ELTORITO_BOOT 730 // El Torito Emulation data 731 cdemu_t cdemu; 732 #endif // BX_ELTORITO_BOOT 733 734 } ebda_data_t; 735 736 #define EbdaData ((ebda_data_t *) 0) 737 738 // for access to the int13ext structure 739 typedef struct { 740 Bit8u size; 741 Bit8u reserved; 742 Bit16u count; 743 Bit16u offset; 744 Bit16u segment; 745 Bit32u lba1; 746 Bit32u lba2; 747 } int13ext_t; 748 749 #define Int13Ext ((int13ext_t *) 0) 750 751 // Disk Physical Table definition 752 typedef struct { 753 Bit16u size; 754 Bit16u infos; 755 Bit32u cylinders; 756 Bit32u heads; 757 Bit32u spt; 758 Bit32u sector_count1; 759 Bit32u sector_count2; 760 Bit16u blksize; 761 Bit16u dpte_segment; 762 Bit16u dpte_offset; 763 Bit16u key; 764 Bit8u dpi_length; 765 Bit8u reserved1; 766 Bit16u reserved2; 767 Bit8u host_bus[4]; 768 Bit8u iface_type[8]; 769 Bit8u iface_path[8]; 770 Bit8u device_path[8]; 771 Bit8u reserved3; 772 Bit8u checksum; 773 } dpt_t; 774 775 #define Int13DPT ((dpt_t *) 0) 776 777 #endif // BX_USE_ATADRV 778 779 typedef struct { 780 union { 781 struct { 782 Bit16u di, si, bp, sp; 783 Bit16u bx, dx, cx, ax; 784 } r16; 785 struct { 786 Bit16u filler[4]; 787 Bit8u bl, bh, dl, dh, cl, ch, al, ah; 788 } r8; 789 } u; 790 } pusha_regs_t; 791 792 typedef struct { 793 union { 794 struct { 795 Bit32u edi, esi, ebp, esp; 796 Bit32u ebx, edx, ecx, eax; 797 } r32; 798 struct { 799 Bit16u di, filler1, si, filler2, bp, filler3, sp, filler4; 800 Bit16u bx, filler5, dx, filler6, cx, filler7, ax, filler8; 801 } r16; 802 struct { 803 Bit32u filler[4]; 804 Bit8u bl, bh; 805 Bit16u filler1; 806 Bit8u dl, dh; 807 Bit16u filler2; 808 Bit8u cl, ch; 809 Bit16u filler3; 810 Bit8u al, ah; 811 Bit16u filler4; 812 } r8; 813 } u; 814 } pushad_regs_t; 815 816 typedef struct { 817 union { 818 struct { 819 Bit16u flags; 820 } r16; 821 struct { 822 Bit8u flagsl; 823 Bit8u flagsh; 824 } r8; 825 } u; 826 } flags_t; 827 828 #define SetCF(x) x.u.r8.flagsl |= 0x01 829 #define SetZF(x) x.u.r8.flagsl |= 0x40 830 #define ClearCF(x) x.u.r8.flagsl &= 0xfe 831 #define ClearZF(x) x.u.r8.flagsl &= 0xbf 832 #define GetCF(x) (x.u.r8.flagsl & 0x01) 833 834 typedef struct { 835 Bit16u ip; 836 Bit16u cs; 837 flags_t flags; 838 } iret_addr_t; 839 840 841 842 static Bit8u inb(); 843 static Bit8u inb_cmos(); 844 static void outb(); 845 static void outb_cmos(); 846 static Bit16u inw(); 847 static void outw(); 848 static void init_rtc(); 849 static bx_bool rtc_updating(); 850 851 static Bit8u read_byte(); 852 static Bit16u read_word(); 853 static void write_byte(); 854 static void write_word(); 855 static void bios_printf(); 856 857 static Bit8u inhibit_mouse_int_and_events(); 858 static void enable_mouse_int_and_events(); 859 static Bit8u send_to_mouse_ctrl(); 860 static Bit8u get_mouse_data(); 861 static void set_kbd_command_byte(); 862 863 static void int09_function(); 864 static void int13_harddisk(); 865 static void int13_cdrom(); 866 static void int13_cdemu(); 867 static void int13_eltorito(); 868 static void int13_diskette_function(); 869 static void int14_function(); 870 static void int15_function(); 871 static void int16_function(); 872 static void int17_function(); 873 static void int19_function(); 874 static void int1a_function(); 875 static void int70_function(); 876 static void int74_function(); 877 static Bit16u get_CS(); 878 static Bit16u get_SS(); 879 static unsigned int enqueue_key(); 880 static unsigned int dequeue_key(); 881 static void get_hd_geometry(); 882 static void set_diskette_ret_status(); 883 static void set_diskette_current_cyl(); 884 static void determine_floppy_media(); 885 static bx_bool floppy_drive_exists(); 886 static bx_bool floppy_drive_recal(); 887 static bx_bool floppy_media_known(); 888 static bx_bool floppy_media_sense(); 889 static bx_bool set_enable_a20(); 890 static void debugger_on(); 891 static void debugger_off(); 892 static void keyboard_init(); 893 static void keyboard_panic(); 894 static void shutdown_status_panic(); 895 static void nmi_handler_msg(); 896 897 static void print_bios_banner(); 898 static void print_boot_device(); 899 static void print_boot_failure(); 900 static void print_cdromboot_failure(); 901 902 # if BX_USE_ATADRV 903 904 // ATA / ATAPI driver 905 void ata_init(); 906 void ata_detect(); 907 void ata_reset(); 908 909 Bit16u ata_cmd_non_data(); 910 Bit16u ata_cmd_data_in(); 911 Bit16u ata_cmd_data_out(); 912 Bit16u ata_cmd_packet(); 913 914 Bit16u atapi_get_sense(); 915 Bit16u atapi_is_ready(); 916 Bit16u atapi_is_cdrom(); 917 918 #endif // BX_USE_ATADRV 919 920 #if BX_ELTORITO_BOOT 921 922 void cdemu_init(); 923 Bit8u cdemu_isactive(); 924 Bit8u cdemu_emulated_drive(); 925 926 Bit16u cdrom_boot(); 927 928 #endif // BX_ELTORITO_BOOT 929 930 static char bios_cvs_version_string[] = "$Revision: 1.183 $ $Date: 2007/09/10 20:00:29 $"; 931 932 #define BIOS_COPYRIGHT_STRING "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team." 933 934 #if DEBUG_ATA 935 # define BX_DEBUG_ATA(a...) BX_DEBUG(a) 936 #else 937 # define BX_DEBUG_ATA(a...) 938 #endif 939 #if DEBUG_INT13_HD 940 # define BX_DEBUG_INT13_HD(a...) BX_DEBUG(a) 941 #else 942 # define BX_DEBUG_INT13_HD(a...) 943 #endif 944 #if DEBUG_INT13_CD 945 # define BX_DEBUG_INT13_CD(a...) BX_DEBUG(a) 946 #else 947 # define BX_DEBUG_INT13_CD(a...) 948 #endif 949 #if DEBUG_INT13_ET 950 # define BX_DEBUG_INT13_ET(a...) BX_DEBUG(a) 951 #else 952 # define BX_DEBUG_INT13_ET(a...) 953 #endif 954 #if DEBUG_INT13_FL 955 # define BX_DEBUG_INT13_FL(a...) BX_DEBUG(a) 956 #else 957 # define BX_DEBUG_INT13_FL(a...) 958 #endif 959 #if DEBUG_INT15 960 # define BX_DEBUG_INT15(a...) BX_DEBUG(a) 961 #else 962 # define BX_DEBUG_INT15(a...) 963 #endif 964 #if DEBUG_INT16 965 # define BX_DEBUG_INT16(a...) BX_DEBUG(a) 966 #else 967 # define BX_DEBUG_INT16(a...) 968 #endif 969 #if DEBUG_INT1A 970 # define BX_DEBUG_INT1A(a...) BX_DEBUG(a) 971 #else 972 # define BX_DEBUG_INT1A(a...) 973 #endif 974 #if DEBUG_INT74 975 # define BX_DEBUG_INT74(a...) BX_DEBUG(a) 976 #else 977 # define BX_DEBUG_INT74(a...) 978 #endif 979 980 #define SET_AL(val8) AX = ((AX & 0xff00) | (val8)) 981 #define SET_BL(val8) BX = ((BX & 0xff00) | (val8)) 982 #define SET_CL(val8) CX = ((CX & 0xff00) | (val8)) 983 #define SET_DL(val8) DX = ((DX & 0xff00) | (val8)) 984 #define SET_AH(val8) AX = ((AX & 0x00ff) | ((val8) << 8)) 985 #define SET_BH(val8) BX = ((BX & 0x00ff) | ((val8) << 8)) 986 #define SET_CH(val8) CX = ((CX & 0x00ff) | ((val8) << 8)) 987 #define SET_DH(val8) DX = ((DX & 0x00ff) | ((val8) << 8)) 988 989 #define GET_AL() ( AX & 0x00ff ) 990 #define GET_BL() ( BX & 0x00ff ) 991 #define GET_CL() ( CX & 0x00ff ) 992 #define GET_DL() ( DX & 0x00ff ) 993 #define GET_AH() ( AX >> 8 ) 994 #define GET_BH() ( BX >> 8 ) 995 #define GET_CH() ( CX >> 8 ) 996 #define GET_DH() ( DX >> 8 ) 997 998 #define GET_ELDL() ( ELDX & 0x00ff ) 999 #define GET_ELDH() ( ELDX >> 8 ) 1000 1001 #define SET_CF() FLAGS |= 0x0001 1002 #define CLEAR_CF() FLAGS &= 0xfffe 1003 #define GET_CF() (FLAGS & 0x0001) 1004 1005 #define SET_ZF() FLAGS |= 0x0040 1006 #define CLEAR_ZF() FLAGS &= 0xffbf 1007 #define GET_ZF() (FLAGS & 0x0040) 1008 1009 #define UNSUPPORTED_FUNCTION 0x86 1010 1011 #define none 0 1012 #define MAX_SCAN_CODE 0x58 1013 1014 static struct { 1015 Bit16u normal; 1016 Bit16u shift; 1017 Bit16u control; 1018 Bit16u alt; 1019 Bit8u lock_flags; 1020 } scan_to_scanascii[MAX_SCAN_CODE + 1] = { 1021 { none, none, none, none, none }, 1022 { 0x011b, 0x011b, 0x011b, 0x0100, none }, /* escape */ 1023 { 0x0231, 0x0221, none, 0x7800, none }, /* 1! */ 1024 { 0x0332, 0x0340, 0x0300, 0x7900, none }, /* 2@ */ 1025 { 0x0433, 0x0423, none, 0x7a00, none }, /* 3# */ 1026 { 0x0534, 0x0524, none, 0x7b00, none }, /* 4$ */ 1027 { 0x0635, 0x0625, none, 0x7c00, none }, /* 5% */ 1028 { 0x0736, 0x075e, 0x071e, 0x7d00, none }, /* 6^ */ 1029 { 0x0837, 0x0826, none, 0x7e00, none }, /* 7& */ 1030 { 0x0938, 0x092a, none, 0x7f00, none }, /* 8* */ 1031 { 0x0a39, 0x0a28, none, 0x8000, none }, /* 9( */ 1032 { 0x0b30, 0x0b29, none, 0x8100, none }, /* 0) */ 1033 { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200, none }, /* -_ */ 1034 { 0x0d3d, 0x0d2b, none, 0x8300, none }, /* =+ */ 1035 { 0x0e08, 0x0e08, 0x0e7f, none, none }, /* backspace */ 1036 { 0x0f09, 0x0f00, none, none, none }, /* tab */ 1037 { 0x1071, 0x1051, 0x1011, 0x1000, 0x40 }, /* Q */ 1038 { 0x1177, 0x1157, 0x1117, 0x1100, 0x40 }, /* W */ 1039 { 0x1265, 0x1245, 0x1205, 0x1200, 0x40 }, /* E */ 1040 { 0x1372, 0x1352, 0x1312, 0x1300, 0x40 }, /* R */ 1041 { 0x1474, 0x1454, 0x1414, 0x1400, 0x40 }, /* T */ 1042 { 0x1579, 0x1559, 0x1519, 0x1500, 0x40 }, /* Y */ 1043 { 0x1675, 0x1655, 0x1615, 0x1600, 0x40 }, /* U */ 1044 { 0x1769, 0x1749, 0x1709, 0x1700, 0x40 }, /* I */ 1045 { 0x186f, 0x184f, 0x180f, 0x1800, 0x40 }, /* O */ 1046 { 0x1970, 0x1950, 0x1910, 0x1900, 0x40 }, /* P */ 1047 { 0x1a5b, 0x1a7b, 0x1a1b, none, none }, /* [{ */ 1048 { 0x1b5d, 0x1b7d, 0x1b1d, none, none }, /* ]} */ 1049 { 0x1c0d, 0x1c0d, 0x1c0a, none, none }, /* Enter */ 1050 { none, none, none, none, none }, /* L Ctrl */ 1051 { 0x1e61, 0x1e41, 0x1e01, 0x1e00, 0x40 }, /* A */ 1052 { 0x1f73, 0x1f53, 0x1f13, 0x1f00, 0x40 }, /* S */ 1053 { 0x2064, 0x2044, 0x2004, 0x2000, 0x40 }, /* D */ 1054 { 0x2166, 0x2146, 0x2106, 0x2100, 0x40 }, /* F */ 1055 { 0x2267, 0x2247, 0x2207, 0x2200, 0x40 }, /* G */ 1056 { 0x2368, 0x2348, 0x2308, 0x2300, 0x40 }, /* H */ 1057 { 0x246a, 0x244a, 0x240a, 0x2400, 0x40 }, /* J */ 1058 { 0x256b, 0x254b, 0x250b, 0x2500, 0x40 }, /* K */ 1059 { 0x266c, 0x264c, 0x260c, 0x2600, 0x40 }, /* L */ 1060 { 0x273b, 0x273a, none, none, none }, /* ;: */ 1061 { 0x2827, 0x2822, none, none, none }, /* '" */ 1062 { 0x2960, 0x297e, none, none, none }, /* `~ */ 1063 { none, none, none, none, none }, /* L shift */ 1064 { 0x2b5c, 0x2b7c, 0x2b1c, none, none }, /* |\ */ 1065 { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00, 0x40 }, /* Z */ 1066 { 0x2d78, 0x2d58, 0x2d18, 0x2d00, 0x40 }, /* X */ 1067 { 0x2e63, 0x2e43, 0x2e03, 0x2e00, 0x40 }, /* C */ 1068 { 0x2f76, 0x2f56, 0x2f16, 0x2f00, 0x40 }, /* V */ 1069 { 0x3062, 0x3042, 0x3002, 0x3000, 0x40 }, /* B */ 1070 { 0x316e, 0x314e, 0x310e, 0x3100, 0x40 }, /* N */ 1071 { 0x326d, 0x324d, 0x320d, 0x3200, 0x40 }, /* M */ 1072 { 0x332c, 0x333c, none, none, none }, /* ,< */ 1073 { 0x342e, 0x343e, none, none, none }, /* .> */ 1074 { 0x352f, 0x353f, none, none, none }, /* /? */ 1075 { none, none, none, none, none }, /* R Shift */ 1076 { 0x372a, 0x372a, none, none, none }, /* * */ 1077 { none, none, none, none, none }, /* L Alt */ 1078 { 0x3920, 0x3920, 0x3920, 0x3920, none }, /* space */ 1079 { none, none, none, none, none }, /* caps lock */ 1080 { 0x3b00, 0x5400, 0x5e00, 0x6800, none }, /* F1 */ 1081 { 0x3c00, 0x5500, 0x5f00, 0x6900, none }, /* F2 */ 1082 { 0x3d00, 0x5600, 0x6000, 0x6a00, none }, /* F3 */ 1083 { 0x3e00, 0x5700, 0x6100, 0x6b00, none }, /* F4 */ 1084 { 0x3f00, 0x5800, 0x6200, 0x6c00, none }, /* F5 */ 1085 { 0x4000, 0x5900, 0x6300, 0x6d00, none }, /* F6 */ 1086 { 0x4100, 0x5a00, 0x6400, 0x6e00, none }, /* F7 */ 1087 { 0x4200, 0x5b00, 0x6500, 0x6f00, none }, /* F8 */ 1088 { 0x4300, 0x5c00, 0x6600, 0x7000, none }, /* F9 */ 1089 { 0x4400, 0x5d00, 0x6700, 0x7100, none }, /* F10 */ 1090 { none, none, none, none, none }, /* Num Lock */ 1091 { none, none, none, none, none }, /* Scroll Lock */ 1092 { 0x4700, 0x4737, 0x7700, none, 0x20 }, /* 7 Home */ 1093 { 0x4800, 0x4838, none, none, 0x20 }, /* 8 UP */ 1094 { 0x4900, 0x4939, 0x8400, none, 0x20 }, /* 9 PgUp */ 1095 { 0x4a2d, 0x4a2d, none, none, none }, /* - */ 1096 { 0x4b00, 0x4b34, 0x7300, none, 0x20 }, /* 4 Left */ 1097 { 0x4c00, 0x4c35, none, none, 0x20 }, /* 5 */ 1098 { 0x4d00, 0x4d36, 0x7400, none, 0x20 }, /* 6 Right */ 1099 { 0x4e2b, 0x4e2b, none, none, none }, /* + */ 1100 { 0x4f00, 0x4f31, 0x7500, none, 0x20 }, /* 1 End */ 1101 { 0x5000, 0x5032, none, none, 0x20 }, /* 2 Down */ 1102 { 0x5100, 0x5133, 0x7600, none, 0x20 }, /* 3 PgDn */ 1103 { 0x5200, 0x5230, none, none, 0x20 }, /* 0 Ins */ 1104 { 0x5300, 0x532e, none, none, 0x20 }, /* Del */ 1105 { none, none, none, none, none }, 1106 { none, none, none, none, none }, 1107 { 0x565c, 0x567c, none, none, none }, /* \| */ 1108 { 0x5700, 0x5700, none, none, none }, /* F11 */ 1109 { 0x5800, 0x5800, none, none, none } /* F12 */ 1110 }; 1111 1112 Bit8u 1113 inb(port) 1114 Bit16u port; 1115 { 1116 ASM_START 1117 push bp 1118 mov bp, sp 1119 1120 push dx 1121 mov dx, 4[bp] 1122 in al, dx 1123 pop dx 1124 1125 pop bp 1126 ASM_END 1127 } 1128 1129 #if BX_USE_ATADRV 1130 Bit16u 1131 inw(port) 1132 Bit16u port; 1133 { 1134 ASM_START 1135 push bp 1136 mov bp, sp 1137 1138 push dx 1139 mov dx, 4[bp] 1140 in ax, dx 1141 pop dx 1142 1143 pop bp 1144 ASM_END 1145 } 1146 #endif 1147 1148 void 1149 outb(port, val) 1150 Bit16u port; 1151 Bit8u val; 1152 { 1153 ASM_START 1154 push bp 1155 mov bp, sp 1156 1157 push ax 1158 push dx 1159 mov dx, 4[bp] 1160 mov al, 6[bp] 1161 out dx, al 1162 pop dx 1163 pop ax 1164 1165 pop bp 1166 ASM_END 1167 } 1168 1169 #if BX_USE_ATADRV 1170 void 1171 outw(port, val) 1172 Bit16u port; 1173 Bit16u val; 1174 { 1175 ASM_START 1176 push bp 1177 mov bp, sp 1178 1179 push ax 1180 push dx 1181 mov dx, 4[bp] 1182 mov ax, 6[bp] 1183 out dx, ax 1184 pop dx 1185 pop ax 1186 1187 pop bp 1188 ASM_END 1189 } 1190 #endif 1191 1192 void 1193 outb_cmos(cmos_reg, val) 1194 Bit8u cmos_reg; 1195 Bit8u val; 1196 { 1197 ASM_START 1198 push bp 1199 mov bp, sp 1200 1201 mov al, 4[bp] ;; cmos_reg 1202 out 0x70, al 1203 mov al, 6[bp] ;; val 1204 out 0x71, al 1205 1206 pop bp 1207 ASM_END 1208 } 1209 1210 Bit8u 1211 inb_cmos(cmos_reg) 1212 Bit8u cmos_reg; 1213 { 1214 ASM_START 1215 push bp 1216 mov bp, sp 1217 1218 mov al, 4[bp] ;; cmos_reg 1219 out 0x70, al 1220 in al, 0x71 1221 1222 pop bp 1223 ASM_END 1224 } 1225 1226 void 1227 init_rtc() 1228 { 1229 outb_cmos(0x0a, 0x26); 1230 outb_cmos(0x0b, 0x02); 1231 inb_cmos(0x0c); 1232 inb_cmos(0x0d); 1233 } 1234 1235 bx_bool 1236 rtc_updating() 1237 { 1238 // This function checks to see if the update-in-progress bit 1239 // is set in CMOS Status Register A. If not, it returns 0. 1240 // If it is set, it tries to wait until there is a transition 1241 // to 0, and will return 0 if such a transition occurs. A 1 1242 // is returned only after timing out. The maximum period 1243 // that this bit should be set is constrained to 244useconds. 1244 // The count I use below guarantees coverage or more than 1245 // this time, with any reasonable IPS setting. 1246 1247 Bit16u count; 1248 1249 count = 25000; 1250 while (--count != 0) { 1251 if ( (inb_cmos(0x0a) & 0x80) == 0 ) 1252 return(0); 1253 } 1254 return(1); // update-in-progress never transitioned to 0 1255 } 1256 1257 1258 Bit8u 1259 read_byte(seg, offset) 1260 Bit16u seg; 1261 Bit16u offset; 1262 { 1263 ASM_START 1264 push bp 1265 mov bp, sp 1266 1267 push bx 1268 push ds 1269 mov ax, 4[bp] ; segment 1270 mov ds, ax 1271 mov bx, 6[bp] ; offset 1272 mov al, [bx] 1273 ;; al = return value (byte) 1274 pop ds 1275 pop bx 1276 1277 pop bp 1278 ASM_END 1279 } 1280 1281 Bit16u 1282 read_word(seg, offset) 1283 Bit16u seg; 1284 Bit16u offset; 1285 { 1286 ASM_START 1287 push bp 1288 mov bp, sp 1289 1290 push bx 1291 push ds 1292 mov ax, 4[bp] ; segment 1293 mov ds, ax 1294 mov bx, 6[bp] ; offset 1295 mov ax, [bx] 1296 ;; ax = return value (word) 1297 pop ds 1298 pop bx 1299 1300 pop bp 1301 ASM_END 1302 } 1303 1304 void 1305 write_byte(seg, offset, data) 1306 Bit16u seg; 1307 Bit16u offset; 1308 Bit8u data; 1309 { 1310 ASM_START 1311 push bp 1312 mov bp, sp 1313 1314 push ax 1315 push bx 1316 push ds 1317 mov ax, 4[bp] ; segment 1318 mov ds, ax 1319 mov bx, 6[bp] ; offset 1320 mov al, 8[bp] ; data byte 1321 mov [bx], al ; write data byte 1322 pop ds 1323 pop bx 1324 pop ax 1325 1326 pop bp 1327 ASM_END 1328 } 1329 1330 void 1331 write_word(seg, offset, data) 1332 Bit16u seg; 1333 Bit16u offset; 1334 Bit16u data; 1335 { 1336 ASM_START 1337 push bp 1338 mov bp, sp 1339 1340 push ax 1341 push bx 1342 push ds 1343 mov ax, 4[bp] ; segment 1344 mov ds, ax 1345 mov bx, 6[bp] ; offset 1346 mov ax, 8[bp] ; data word 1347 mov [bx], ax ; write data word 1348 pop ds 1349 pop bx 1350 pop ax 1351 1352 pop bp 1353 ASM_END 1354 } 1355 1356 Bit16u 1357 get_CS() 1358 { 1359 ASM_START 1360 mov ax, cs 1361 ASM_END 1362 } 1363 1364 Bit16u 1365 get_SS() 1366 { 1367 ASM_START 1368 mov ax, ss 1369 ASM_END 1370 } 1371 1372 #if BX_DEBUG_SERIAL 1373 /* serial debug port*/ 1374 #define BX_DEBUG_PORT 0x03f8 1375 1376 /* data */ 1377 #define UART_RBR 0x00 1378 #define UART_THR 0x00 1379 1380 /* control */ 1381 #define UART_IER 0x01 1382 #define UART_IIR 0x02 1383 #define UART_FCR 0x02 1384 #define UART_LCR 0x03 1385 #define UART_MCR 0x04 1386 #define UART_DLL 0x00 1387 #define UART_DLM 0x01 1388 1389 /* status */ 1390 #define UART_LSR 0x05 1391 #define UART_MSR 0x06 1392 #define UART_SCR 0x07 1393 1394 int uart_can_tx_byte(base_port) 1395 Bit16u base_port; 1396 { 1397 return inb(base_port + UART_LSR) & 0x20; 1398 } 1399 1400 void uart_wait_to_tx_byte(base_port) 1401 Bit16u base_port; 1402 { 1403 while (!uart_can_tx_byte(base_port)); 1404 } 1405 1406 void uart_wait_until_sent(base_port) 1407 Bit16u base_port; 1408 { 1409 while (!(inb(base_port + UART_LSR) & 0x40)); 1410 } 1411 1412 void uart_tx_byte(base_port, data) 1413 Bit16u base_port; 1414 Bit8u data; 1415 { 1416 uart_wait_to_tx_byte(base_port); 1417 outb(base_port + UART_THR, data); 1418 uart_wait_until_sent(base_port); 1419 } 1420 #endif 1421 1422 void 1423 wrch(c) 1424 Bit8u c; 1425 { 1426 ASM_START 1427 push bp 1428 mov bp, sp 1429 1430 push bx 1431 mov ah, #0x0e 1432 mov al, 4[bp] 1433 xor bx,bx 1434 int #0x10 1435 pop bx 1436 1437 pop bp 1438 ASM_END 1439 } 1440 1441 void 1442 send(action, c) 1443 Bit16u action; 1444 Bit8u c; 1445 { 1446 #if BX_DEBUG_SERIAL 1447 if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r'); 1448 uart_tx_byte(BX_DEBUG_PORT, c); 1449 #endif 1450 #if BX_VIRTUAL_PORTS 1451 if (action & BIOS_PRINTF_DEBUG) outb(DEBUG_PORT, c); 1452 if (action & BIOS_PRINTF_INFO) outb(INFO_PORT, c); 1453 #endif 1454 if (action & BIOS_PRINTF_SCREEN) { 1455 if (c == '\n') wrch('\r'); 1456 wrch(c); 1457 } 1458 } 1459 1460 void 1461 put_int(action, val, width, neg) 1462 Bit16u action; 1463 short val, width; 1464 bx_bool neg; 1465 { 1466 short nval = val / 10; 1467 if (nval) 1468 put_int(action, nval, width - 1, neg); 1469 else { 1470 while (--width > 0) send(action, ' '); 1471 if (neg) send(action, '-'); 1472 } 1473 send(action, val - (nval * 10) + ''); 1474 } 1475 1476 void 1477 put_uint(action, val, width, neg) 1478 Bit16u action; 1479 unsigned short val; 1480 short width; 1481 bx_bool neg; 1482 { 1483 unsigned short nval = val / 10; 1484 if (nval) 1485 put_uint(action, nval, width - 1, neg); 1486 else { 1487 while (--width > 0) send(action, ' '); 1488 if (neg) send(action, '-'); 1489 } 1490 send(action, val - (nval * 10) + ''); 1491 } 1492 1493 void 1494 put_luint(action, val, width, neg) 1495 Bit16u action; 1496 unsigned long val; 1497 short width; 1498 bx_bool neg; 1499 { 1500 unsigned long nval = val / 10; 1501 if (nval) 1502 put_luint(action, nval, width - 1, neg); 1503 else { 1504 while (--width > 0) send(action, ' '); 1505 if (neg) send(action, '-'); 1506 } 1507 send(action, val - (nval * 10) + ''); 1508 } 1509 1510 void put_str(action, s) 1511 Bit16u action; 1512 Bit8u *s; 1513 { 1514 Bit8u c; 1515 if (!s) 1516 s = "<NULL>"; 1517 1518 while (c = read_byte(get_CS(), s)) { 1519 send(action, c); 1520 s++; 1521 } 1522 } 1523 1524 //-------------------------------------------------------------------------- 1525 // bios_printf() 1526 // A compact variable argument printf function which prints its output via 1527 // an I/O port so that it can be logged by Bochs/Plex. 1528 // Currently, only %x is supported (or %02x, %04x, etc). 1529 // 1530 // Supports %[format_width][format] 1531 // where format can be d,x,c,s 1532 //-------------------------------------------------------------------------- 1533 void 1534 bios_printf(action, s) 1535 Bit16u action; 1536 Bit8u *s; 1537 { 1538 Bit8u c, format_char; 1539 bx_bool in_format; 1540 short i; 1541 Bit16u *arg_ptr; 1542 Bit16u arg_seg, arg, nibble, hibyte, shift_count, format_width; 1543 1544 arg_ptr = &s; 1545 arg_seg = get_SS(); 1546 1547 in_format = 0; 1548 format_width = 0; 1549 1550 if ((action & BIOS_PRINTF_DEBHALT) == BIOS_PRINTF_DEBHALT) { 1551 #if BX_VIRTUAL_PORTS 1552 outb(PANIC_PORT2, 0x00); 1553 #endif 1554 bios_printf (BIOS_PRINTF_SCREEN, "FATAL: "); 1555 } 1556 1557 while (c = read_byte(get_CS(), s)) { 1558 if ( c == '%' ) { 1559 in_format = 1; 1560 format_width = 0; 1561 } 1562 else if (in_format) { 1563 if ( (c>='') && (c<='9') ) { 1564 format_width = (format_width * 10) + (c - ''); 1565 } 1566 else { 1567 arg_ptr++; // increment to next arg 1568 arg = read_word(arg_seg, arg_ptr); 1569 if (c == 'x') { 1570 if (format_width == 0) 1571 format_width = 4; 1572 for (i=format_width-1; i>=0; i--) { 1573 nibble = (arg >> (4 * i)) & 0x000f; 1574 send (action, (nibble<=9)? (nibble+'') : (nibble-10+'A')); 1575 } 1576 } 1577 else if (c == 'u') { 1578 put_uint(action, arg, format_width, 0); 1579 } 1580 else if (c == 'l') { 1581 s++; 1582 arg_ptr++; /* increment to next arg */ 1583 hibyte = read_word(arg_seg, arg_ptr); 1584 put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0); 1585 } 1586 else if (c == 'd') { 1587 if (arg & 0x8000) 1588 put_int(action, -arg, format_width - 1, 1); 1589 else 1590 put_int(action, arg, format_width, 0); 1591 } 1592 else if (c == 's') { 1593 put_str(action, arg); 1594 } 1595 else if (c == 'c') { 1596 send(action, arg); 1597 } 1598 else 1599 BX_PANIC("bios_printf: unknown format\n"); 1600 in_format = 0; 1601 } 1602 } 1603 else { 1604 send(action, c); 1605 } 1606 s ++; 1607 } 1608 1609 if (action & BIOS_PRINTF_HALT) { 1610 // freeze in a busy loop. 1611 ASM_START 1612 cli 1613 halt2_loop: 1614 hlt 1615 jmp halt2_loop 1616 ASM_END 1617 } 1618 } 1619 1620 //-------------------------------------------------------------------------- 1621 // keyboard_init 1622 //-------------------------------------------------------------------------- 1623 // this file is based on LinuxBIOS implementation of keyboard.c 1624 // could convert to #asm to gain space 1625 void 1626 keyboard_init() 1627 { 1628 Bit16u max; 1629 1630 /* ------------------- Flush buffers ------------------------*/ 1631 /* Wait until buffer is empty */ 1632 max=0xffff; 1633 while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00); 1634 1635 /* flush incoming keys */ 1636 max=0x2000; 1637 while (--max > 0) { 1638 outb(0x80, 0x00); 1639 if (inb(0x64) & 0x01) { 1640 inb(0x60); 1641 max = 0x2000; 1642 } 1643 } 1644 1645 // Due to timer issues, and if the IPS setting is > 15000000, 1646 // the incoming keys might not be flushed here. That will 1647 // cause a panic a few lines below. See sourceforge bug report : 1648 // [ 642031 ] FATAL: Keyboard RESET error:993 1649 1650 /* ------------------- controller side ----------------------*/ 1651 /* send cmd = 0xAA, self test 8042 */ 1652 outb(0x64, 0xaa); 1653 1654 /* Wait until buffer is empty */ 1655 max=0xffff; 1656 while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00); 1657 if (max==0x0) keyboard_panic(00); 1658 1659 /* Wait for data */ 1660 max=0xffff; 1661 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x01); 1662 if (max==0x0) keyboard_panic(01); 1663 1664 /* read self-test result, 0x55 should be returned from 0x60 */ 1665 if ((inb(0x60) != 0x55)){ 1666 keyboard_panic(991); 1667 } 1668 1669 /* send cmd = 0xAB, keyboard interface test */ 1670 outb(0x64,0xab); 1671 1672 /* Wait until buffer is empty */ 1673 max=0xffff; 1674 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x10); 1675 if (max==0x0) keyboard_panic(10); 1676 1677 /* Wait for data */ 1678 max=0xffff; 1679 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x11); 1680 if (max==0x0) keyboard_panic(11); 1681 1682 /* read keyboard interface test result, */ 1683 /* 0x00 should be returned form 0x60 */ 1684 if ((inb(0x60) != 0x00)) { 1685 keyboard_panic(992); 1686 } 1687 1688 /* Enable Keyboard clock */ 1689 outb(0x64,0xae); 1690 outb(0x64,0xa8); 1691 1692 /* ------------------- keyboard side ------------------------*/ 1693 /* reset kerboard and self test (keyboard side) */ 1694 outb(0x60, 0xff); 1695 1696 /* Wait until buffer is empty */ 1697 max=0xffff; 1698 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x20); 1699 if (max==0x0) keyboard_panic(20); 1700 1701 /* Wait for data */ 1702 max=0xffff; 1703 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x21); 1704 if (max==0x0) keyboard_panic(21); 1705 1706 /* keyboard should return ACK */ 1707 if ((inb(0x60) != 0xfa)) { 1708 keyboard_panic(993); 1709 } 1710 1711 /* Wait for data */ 1712 max=0xffff; 1713 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x31); 1714 if (max==0x0) keyboard_panic(31); 1715 1716 if ((inb(0x60) != 0xaa)) { 1717 keyboard_panic(994); 1718 } 1719 1720 /* Disable keyboard */ 1721 outb(0x60, 0xf5); 1722 1723 /* Wait until buffer is empty */ 1724 max=0xffff; 1725 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x40); 1726 if (max==0x0) keyboard_panic(40); 1727 1728 /* Wait for data */ 1729 max=0xffff; 1730 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x41); 1731 if (max==0x0) keyboard_panic(41); 1732 1733 /* keyboard should return ACK */ 1734 if ((inb(0x60) != 0xfa)) { 1735 keyboard_panic(995); 1736 } 1737 1738 /* Write Keyboard Mode */ 1739 outb(0x64, 0x60); 1740 1741 /* Wait until buffer is empty */ 1742 max=0xffff; 1743 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x50); 1744 if (max==0x0) keyboard_panic(50); 1745 1746 /* send cmd: scan code convert, disable mouse, enable IRQ 1 */ 1747 outb(0x60, 0x61); 1748 1749 /* Wait until buffer is empty */ 1750 max=0xffff; 1751 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x60); 1752 if (max==0x0) keyboard_panic(60); 1753 1754 /* Enable keyboard */ 1755 outb(0x60, 0xf4); 1756 1757 /* Wait until buffer is empty */ 1758 max=0xffff; 1759 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x70); 1760 if (max==0x0) keyboard_panic(70); 1761 1762 /* Wait for data */ 1763 max=0xffff; 1764 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x71); 1765 if (max==0x0) keyboard_panic(70); 1766 1767 /* keyboard should return ACK */ 1768 if ((inb(0x60) != 0xfa)) { 1769 keyboard_panic(996); 1770 } 1771 1772 outb(0x80, 0x77); 1773 } 1774 1775 //-------------------------------------------------------------------------- 1776 // keyboard_panic 1777 //-------------------------------------------------------------------------- 1778 void 1779 keyboard_panic(status) 1780 Bit16u status; 1781 { 1782 // If you're getting a 993 keyboard panic here, 1783 // please see the comment in keyboard_init 1784 1785 BX_PANIC("Keyboard error:%u\n",status); 1786 } 1787 1788 //-------------------------------------------------------------------------- 1789 // shutdown_status_panic 1790 // called when the shutdown statsu is not implemented, displays the status 1791 //-------------------------------------------------------------------------- 1792 void 1793 shutdown_status_panic(status) 1794 Bit16u status; 1795 { 1796 BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status); 1797 } 1798 1799 //-------------------------------------------------------------------------- 1800 // print_bios_banner 1801 // displays a the bios version 1802 //-------------------------------------------------------------------------- 1803 void 1804 print_bios_banner() 1805 { 1806 printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ", 1807 BIOS_BUILD_DATE, bios_cvs_version_string); 1808 printf( 1809 #if BX_APM 1810 "apmbios " 1811 #endif 1812 #if BX_PCIBIOS 1813 "pcibios " 1814 #endif 1815 #if BX_ELTORITO_BOOT 1816 "eltorito " 1817 #endif 1818 #if BX_ROMBIOS32 1819 "rombios32 " 1820 #endif 1821 "\n\n"); 1822 } 1823 1824 //-------------------------------------------------------------------------- 1825 // BIOS Boot Specification 1.0.1 compatibility 1826 // 1827 // Very basic support for the BIOS Boot Specification, which allows expansion 1828 // ROMs to register themselves as boot devices, instead of just stealing the 1829 // INT 19h boot vector. 1830 // 1831 // This is a hack: to do it properly requires a proper PnP BIOS and we aren't 1832 // one; we just lie to the option ROMs to make them behave correctly. 1833 // We also don't support letting option ROMs register as bootable disk 1834 // drives (BCVs), only as bootable devices (BEVs). 1835 // 1836 // http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm 1837 //-------------------------------------------------------------------------- 1838 1839 /* 256 bytes at 0x9ff00 -- 0x9ffff is used for the IPL boot table. */ 1840 #define IPL_SEG 0x9ff0 1841 #define IPL_TABLE_OFFSET 0x0000 1842 #define IPL_TABLE_ENTRIES 8 1843 #define IPL_COUNT_OFFSET 0x0080 /* u16: number of valid table entries */ 1844 #define IPL_SEQUENCE_OFFSET 0x0082 /* u16: next boot device */ 1845 1846 struct ipl_entry { 1847 Bit16u type; 1848 Bit16u flags; 1849 Bit32u vector; 1850 Bit32u description; 1851 Bit32u reserved; 1852 }; 1853 1854 static void 1855 init_boot_vectors() 1856 { 1857 struct ipl_entry e; 1858 Bit16u count = 0; 1859 Bit16u ss = get_SS(); 1860 1861 /* Clear out the IPL table. */ 1862 memsetb(IPL_SEG, IPL_TABLE_OFFSET, 0, 0xff); 1863 1864 /* Floppy drive */ 1865 e.type = 1; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; 1866 memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); 1867 count++; 1868 1869 /* First HDD */ 1870 e.type = 2; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; 1871 memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); 1872 count++; 1873 1874 #if BX_ELTORITO_BOOT 1875 /* CDROM */ 1876 e.type = 3; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; 1877 memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); 1878 count++; 1879 #endif 1880 1881 /* Remember how many devices we have */ 1882 write_word(IPL_SEG, IPL_COUNT_OFFSET, count); 1883 /* Not tried booting anything yet */ 1884 write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xffff); 1885 } 1886 1887 static Bit8u 1888 get_boot_vector(i, e) 1889 Bit16u i; struct ipl_entry *e; 1890 { 1891 Bit16u count; 1892 Bit16u ss = get_SS(); 1893 /* Get the count of boot devices, and refuse to overrun the array */ 1894 count = read_word(IPL_SEG, IPL_COUNT_OFFSET); 1895 if (i >= count) return 0; 1896 /* OK to read this device */ 1897 memcpyb(ss, e, IPL_SEG, IPL_TABLE_OFFSET + i * sizeof (*e), sizeof (*e)); 1898 return 1; 1899 } 1900 1901 1902 //-------------------------------------------------------------------------- 1903 // print_boot_device 1904 // displays the boot device 1905 //-------------------------------------------------------------------------- 1906 1907 static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"}; 1908 1909 void 1910 print_boot_device(type) 1911 Bit16u type; 1912 { 1913 /* NIC appears as type 0x80 */ 1914 if (type == 0x80 ) type = 0x4; 1915 if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n"); 1916 printf("Booting from %s...\n", drivetypes[type]); 1917 } 1918 1919 //-------------------------------------------------------------------------- 1920 // print_boot_failure 1921 // displays the reason why boot failed 1922 //-------------------------------------------------------------------------- 1923 void 1924 print_boot_failure(type, reason) 1925 Bit16u type; Bit8u reason; 1926 { 1927 if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n"); 1928 1929 printf("Boot from %s failed", drivetypes[type]); 1930 if (type < 4) { 1931 /* Report the reason too */ 1932 if (reason==0) 1933 printf(": not a bootable disk"); 1934 else 1935 printf(": could not read the boot disk"); 1936 } 1937 printf("\n"); 1938 } 1939 1940 //-------------------------------------------------------------------------- 1941 // print_cdromboot_failure 1942 // displays the reason why boot failed 1943 //-------------------------------------------------------------------------- 1944 void 1945 print_cdromboot_failure( code ) 1946 Bit16u code; 1947 { 1948 bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "CDROM boot failure code : %04x\n",code); 1949 1950 return; 1951 } 1952 1953 void 1954 nmi_handler_msg() 1955 { 1956 BX_PANIC("NMI Handler called\n"); 1957 } 1958 1959 void 1960 int18_panic_msg() 1961 { 1962 BX_PANIC("INT18: BOOT FAILURE\n"); 1963 } 1964 1965 void 1966 log_bios_start() 1967 { 1968 #if BX_DEBUG_SERIAL 1969 outb(BX_DEBUG_PORT+UART_LCR, 0x03); /* setup for serial logging: 8N1 */ 1970 #endif 1971 BX_INFO("%s\n", bios_cvs_version_string); 1972 } 1973 1974 bx_bool 1975 set_enable_a20(val) 1976 bx_bool val; 1977 { 1978 Bit8u oldval; 1979 1980 // Use PS2 System Control port A to set A20 enable 1981 1982 // get current setting first 1983 oldval = inb(0x92); 1984 1985 // change A20 status 1986 if (val) 1987 outb(0x92, oldval | 0x02); 1988 else 1989 outb(0x92, oldval & 0xfd); 1990 1991 return((oldval & 0x02) != 0); 1992 } 1993 1994 void 1995 debugger_on() 1996 { 1997 outb(0xfedc, 0x01); 1998 } 1999 2000 void 2001 debugger_off() 2002 { 2003 outb(0xfedc, 0x00); 2004 } 2005 2006 #if BX_USE_ATADRV 2007 2008 // --------------------------------------------------------------------------- 2009 // Start of ATA/ATAPI Driver 2010 // --------------------------------------------------------------------------- 2011 2012 // Global defines -- ATA register and register bits. 2013 // command block & control block regs 2014 #define ATA_CB_DATA 0 // data reg in/out pio_base_addr1+0 2015 #define ATA_CB_ERR 1 // error in pio_base_addr1+1 2016 #define ATA_CB_FR 1 // feature reg out pio_base_addr1+1 2017 #define ATA_CB_SC 2 // sector count in/out pio_base_addr1+2 2018 #define ATA_CB_SN 3 // sector number in/out pio_base_addr1+3 2019 #define ATA_CB_CL 4 // cylinder low in/out pio_base_addr1+4 2020 #define ATA_CB_CH 5 // cylinder high in/out pio_base_addr1+5 2021 #define ATA_CB_DH 6 // device head in/out pio_base_addr1+6 2022 #define ATA_CB_STAT 7 // primary status in pio_base_addr1+7 2023 #define ATA_CB_CMD 7 // command out pio_base_addr1+7 2024 #define ATA_CB_ASTAT 6 // alternate status in pio_base_addr2+6 2025 #define ATA_CB_DC 6 // device control out pio_base_addr2+6 2026 #define ATA_CB_DA 7 // device address in pio_base_addr2+7 2027 2028 #define ATA_CB_ER_ICRC 0x80 // ATA Ultra DMA bad CRC 2029 #define ATA_CB_ER_BBK 0x80 // ATA bad block 2030 #define ATA_CB_ER_UNC 0x40 // ATA uncorrected error 2031 #define ATA_CB_ER_MC 0x20 // ATA media change 2032 #define ATA_CB_ER_IDNF 0x10 // ATA id not found 2033 #define ATA_CB_ER_MCR 0x08 // ATA media change request 2034 #define ATA_CB_ER_ABRT 0x04 // ATA command aborted 2035 #define ATA_CB_ER_NTK0 0x02 // ATA track 0 not found 2036 #define ATA_CB_ER_NDAM 0x01 // ATA address mark not found 2037 2038 #define ATA_CB_ER_P_SNSKEY 0xf0 // ATAPI sense key (mask) 2039 #define ATA_CB_ER_P_MCR 0x08 // ATAPI Media Change Request 2040 #define ATA_CB_ER_P_ABRT 0x04 // ATAPI command abort 2041 #define ATA_CB_ER_P_EOM 0x02 // ATAPI End of Media 2042 #define ATA_CB_ER_P_ILI 0x01 // ATAPI Illegal Length Indication 2043 2044 // ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC) 2045 #define ATA_CB_SC_P_TAG 0xf8 // ATAPI tag (mask) 2046 #define ATA_CB_SC_P_REL 0x04 // ATAPI release 2047 #define ATA_CB_SC_P_IO 0x02 // ATAPI I/O 2048 #define ATA_CB_SC_P_CD 0x01 // ATAPI C/D 2049 2050 // bits 7-4 of the device/head (CB_DH) reg 2051 #define ATA_CB_DH_DEV0 0xa0 // select device 0 2052 #define ATA_CB_DH_DEV1 0xb0 // select device 1 2053 2054 // status reg (CB_STAT and CB_ASTAT) bits 2055 #define ATA_CB_STAT_BSY 0x80 // busy 2056 #define ATA_CB_STAT_RDY 0x40 // ready 2057 #define ATA_CB_STAT_DF 0x20 // device fault 2058 #define ATA_CB_STAT_WFT 0x20 // write fault (old name) 2059 #define ATA_CB_STAT_SKC 0x10 // seek complete 2060 #define ATA_CB_STAT_SERV 0x10 // service 2061 #define ATA_CB_STAT_DRQ 0x08 // data request 2062 #define ATA_CB_STAT_CORR 0x04 // corrected 2063 #define ATA_CB_STAT_IDX 0x02 // index 2064 #define ATA_CB_STAT_ERR 0x01 // error (ATA) 2065 #define ATA_CB_STAT_CHK 0x01 // check (ATAPI) 2066 2067 // device control reg (CB_DC) bits 2068 #define ATA_CB_DC_HD15 0x08 // bit should always be set to one 2069 #define ATA_CB_DC_SRST 0x04 // soft reset 2070 #define ATA_CB_DC_NIEN 0x02 // disable interrupts 2071 2072 // Most mandtory and optional ATA commands (from ATA-3), 2073 #define ATA_CMD_CFA_ERASE_SECTORS 0xC0 2074 #define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE 0x03 2075 #define ATA_CMD_CFA_TRANSLATE_SECTOR 0x87 2076 #define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD 2077 #define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38 2078 #define ATA_CMD_CHECK_POWER_MODE1 0xE5 2079 #define ATA_CMD_CHECK_POWER_MODE2 0x98 2080 #define ATA_CMD_DEVICE_RESET 0x08 2081 #define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90 2082 #define ATA_CMD_FLUSH_CACHE 0xE7 2083 #define ATA_CMD_FORMAT_TRACK 0x50 2084 #define ATA_CMD_IDENTIFY_DEVICE 0xEC 2085 #define ATA_CMD_IDENTIFY_DEVICE_PACKET 0xA1 2086 #define ATA_CMD_IDENTIFY_PACKET_DEVICE 0xA1 2087 #define ATA_CMD_IDLE1 0xE3 2088 #define ATA_CMD_IDLE2 0x97 2089 #define ATA_CMD_IDLE_IMMEDIATE1 0xE1 2090 #define ATA_CMD_IDLE_IMMEDIATE2 0x95 2091 #define ATA_CMD_INITIALIZE_DRIVE_PARAMETERS 0x91 2092 #define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91 2093 #define ATA_CMD_NOP 0x00 2094 #define ATA_CMD_PACKET 0xA0 2095 #define ATA_CMD_READ_BUFFER 0xE4 2096 #define ATA_CMD_READ_DMA 0xC8 2097 #define ATA_CMD_READ_DMA_QUEUED 0xC7 2098 #define ATA_CMD_READ_MULTIPLE 0xC4 2099 #define ATA_CMD_READ_SECTORS 0x20 2100 #define ATA_CMD_READ_VERIFY_SECTORS 0x40 2101 #define ATA_CMD_RECALIBRATE 0x10 2102 #define ATA_CMD_SEEK 0x70 2103 #define ATA_CMD_SET_FEATURES 0xEF 2104 #define ATA_CMD_SET_MULTIPLE_MODE 0xC6 2105 #define ATA_CMD_SLEEP1 0xE6 2106 #define ATA_CMD_SLEEP2 0x99 2107 #define ATA_CMD_STANDBY1 0xE2 2108 #define ATA_CMD_STANDBY2 0x96 2109 #define ATA_CMD_STANDBY_IMMEDIATE1 0xE0 2110 #define ATA_CMD_STANDBY_IMMEDIATE2 0x94 2111 #define ATA_CMD_WRITE_BUFFER 0xE8 2112 #define ATA_CMD_WRITE_DMA 0xCA 2113 #define ATA_CMD_WRITE_DMA_QUEUED 0xCC 2114 #define ATA_CMD_WRITE_MULTIPLE 0xC5 2115 #define ATA_CMD_WRITE_SECTORS 0x30 2116 #define ATA_CMD_WRITE_VERIFY 0x3C 2117 2118 #define ATA_IFACE_NONE 0x00 2119 #define ATA_IFACE_ISA 0x00 2120 #define ATA_IFACE_PCI 0x01 2121 2122 #define ATA_TYPE_NONE 0x00 2123 #define ATA_TYPE_UNKNOWN 0x01 2124 #define ATA_TYPE_ATA 0x02 2125 #define ATA_TYPE_ATAPI 0x03 2126 2127 #define ATA_DEVICE_NONE 0x00 2128 #define ATA_DEVICE_HD 0xFF 2129 #define ATA_DEVICE_CDROM 0x05 2130 2131 #define ATA_MODE_NONE 0x00 2132 #define ATA_MODE_PIO16 0x00 2133 #define ATA_MODE_PIO32 0x01 2134 #define ATA_MODE_ISADMA 0x02 2135 #define ATA_MODE_PCIDMA 0x03 2136 #define ATA_MODE_USEIRQ 0x10 2137 2138 #define ATA_TRANSLATION_NONE 0 2139 #define ATA_TRANSLATION_LBA 1 2140 #define ATA_TRANSLATION_LARGE 2 2141 #define ATA_TRANSLATION_RECHS 3 2142 2143 #define ATA_DATA_NO 0x00 2144 #define ATA_DATA_IN 0x01 2145 #define ATA_DATA_OUT 0x02 2146 2147 // --------------------------------------------------------------------------- 2148 // ATA/ATAPI driver : initialization 2149 // --------------------------------------------------------------------------- 2150 void ata_init( ) 2151 { 2152 Bit16u ebda_seg=read_word(0x0040,0x000E); 2153 Bit8u channel, device; 2154 2155 // Channels info init. 2156 for (channel=0; channel<BX_MAX_ATA_INTERFACES; channel++) { 2157 write_byte(ebda_seg,&EbdaData->ata.channels[channel].iface,ATA_IFACE_NONE); 2158 write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1,0x0); 2159 write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase2,0x0); 2160 write_byte(ebda_seg,&EbdaData->ata.channels[channel].irq,0); 2161 } 2162 2163 // Devices info init. 2164 for (device=0; device<BX_MAX_ATA_DEVICES; device++) { 2165 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE); 2166 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_NONE); 2167 write_byte(ebda_seg,&EbdaData->ata.devices[device].removable,0); 2168 write_byte(ebda_seg,&EbdaData->ata.devices[device].lock,0); 2169 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode,ATA_MODE_NONE); 2170 write_word(ebda_seg,&EbdaData->ata.devices[device].blksize,0); 2171 write_byte(ebda_seg,&EbdaData->ata.devices[device].translation,ATA_TRANSLATION_NONE); 2172 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads,0); 2173 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders,0); 2174 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt,0); 2175 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads,0); 2176 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders,0); 2177 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt,0); 2178 2179 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors,0L); 2180 } 2181 2182 // hdidmap and cdidmap init. 2183 for (device=0; device<BX_MAX_ATA_DEVICES; device++) { 2184 write_byte(ebda_seg,&EbdaData->ata.hdidmap[device],BX_MAX_ATA_DEVICES); 2185 write_byte(ebda_seg,&EbdaData->ata.cdidmap[device],BX_MAX_ATA_DEVICES); 2186 } 2187 2188 write_byte(ebda_seg,&EbdaData->ata.hdcount,0); 2189 write_byte(ebda_seg,&EbdaData->ata.cdcount,0); 2190 } 2191 2192 // --------------------------------------------------------------------------- 2193 // ATA/ATAPI driver : device detection 2194 // --------------------------------------------------------------------------- 2195 2196 void ata_detect( ) 2197 { 2198 Bit16u ebda_seg=read_word(0x0040,0x000E); 2199 Bit8u hdcount, cdcount, device, type; 2200 Bit8u buffer[0x0200]; 2201 2202 #if BX_MAX_ATA_INTERFACES > 0 2203 write_byte(ebda_seg,&EbdaData->ata.channels[0].iface,ATA_IFACE_ISA); 2204 write_word(ebda_seg,&EbdaData->ata.channels[0].iobase1,0x1f0); 2205 write_word(ebda_seg,&EbdaData->ata.channels[0].iobase2,0x3f0); 2206 write_byte(ebda_seg,&EbdaData->ata.channels[0].irq,14); 2207 #endif 2208 #if BX_MAX_ATA_INTERFACES > 1 2209 write_byte(ebda_seg,&EbdaData->ata.channels[1].iface,ATA_IFACE_ISA); 2210 write_word(ebda_seg,&EbdaData->ata.channels[1].iobase1,0x170); 2211 write_word(ebda_seg,&EbdaData->ata.channels[1].iobase2,0x370); 2212 write_byte(ebda_seg,&EbdaData->ata.channels[1].irq,15); 2213 #endif 2214 #if BX_MAX_ATA_INTERFACES > 2 2215 write_byte(ebda_seg,&EbdaData->ata.channels[2].iface,ATA_IFACE_ISA); 2216 write_word(ebda_seg,&EbdaData->ata.channels[2].iobase1,0x1e8); 2217 write_word(ebda_seg,&EbdaData->ata.channels[2].iobase2,0x3e0); 2218 write_byte(ebda_seg,&EbdaData->ata.channels[2].irq,12); 2219 #endif 2220 #if BX_MAX_ATA_INTERFACES > 3 2221 write_byte(ebda_seg,&EbdaData->ata.channels[3].iface,ATA_IFACE_ISA); 2222 write_word(ebda_seg,&EbdaData->ata.channels[3].iobase1,0x168); 2223 write_word(ebda_seg,&EbdaData->ata.channels[3].iobase2,0x360); 2224 write_byte(ebda_seg,&EbdaData->ata.channels[3].irq,11); 2225 #endif 2226 #if BX_MAX_ATA_INTERFACES > 4 2227 #error Please fill the ATA interface informations 2228 #endif 2229 2230 // Device detection 2231 hdcount=cdcount=0; 2232 2233 for(device=0; device<BX_MAX_ATA_DEVICES; device++) { 2234 Bit16u iobase1, iobase2; 2235 Bit8u channel, slave, shift; 2236 Bit8u sc, sn, cl, ch, st; 2237 2238 channel = device / 2; 2239 slave = device % 2; 2240 2241 iobase1 =read_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1); 2242 iobase2 =read_word(ebda_seg,&EbdaData->ata.channels[channel].iobase2); 2243 2244 // Disable interrupts 2245 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); 2246 2247 // Look for device 2248 outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0); 2249 outb(iobase1+ATA_CB_SC, 0x55); 2250 outb(iobase1+ATA_CB_SN, 0xaa); 2251 outb(iobase1+ATA_CB_SC, 0xaa); 2252 outb(iobase1+ATA_CB_SN, 0x55); 2253 outb(iobase1+ATA_CB_SC, 0x55); 2254 outb(iobase1+ATA_CB_SN, 0xaa); 2255 2256 // If we found something 2257 sc = inb(iobase1+ATA_CB_SC); 2258 sn = inb(iobase1+ATA_CB_SN); 2259 2260 if ( (sc == 0x55) && (sn == 0xaa) ) { 2261 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_UNKNOWN); 2262 2263 // reset the channel 2264 ata_reset(device); 2265 2266 // check for ATA or ATAPI 2267 outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0); 2268 sc = inb(iobase1+ATA_CB_SC); 2269 sn = inb(iobase1+ATA_CB_SN); 2270 if ((sc==0x01) && (sn==0x01)) { 2271 cl = inb(iobase1+ATA_CB_CL); 2272 ch = inb(iobase1+ATA_CB_CH); 2273 st = inb(iobase1+ATA_CB_STAT); 2274 2275 if ((cl==0x14) && (ch==0xeb)) { 2276 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATAPI); 2277 } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) { 2278 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATA); 2279 } else if ((cl==0xff) && (ch==0xff)) { 2280 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE); 2281 } 2282 } 2283 } 2284 2285 type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type); 2286 2287 // Now we send a IDENTIFY command to ATA device 2288 if(type == ATA_TYPE_ATA) { 2289 Bit32u sectors; 2290 Bit16u cylinders, heads, spt, blksize; 2291 Bit8u translation, removable, mode; 2292 2293 //Temporary values to do the transfer 2294 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD); 2295 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16); 2296 2297 if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, get_SS(),buffer) !=0 ) 2298 BX_PANIC("ata-detect: Failed to detect ATA device\n"); 2299 2300 removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0; 2301 mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16; 2302 blksize = read_word(get_SS(),buffer+10); 2303 2304 cylinders = read_word(get_SS(),buffer+(1*2)); // word 1 2305 heads = read_word(get_SS(),buffer+(3*2)); // word 3 2306 spt = read_word(get_SS(),buffer+(6*2)); // word 6 2307 2308 sectors = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61 2309 2310 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD); 2311 write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable); 2312 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode); 2313 write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize); 2314 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads, heads); 2315 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders, cylinders); 2316 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt); 2317 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors, sectors); 2318 BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt); 2319 2320 translation = inb_cmos(0x39 + channel/2); 2321 for (shift=device%4; shift>0; shift--) translation >>= 2; 2322 translation &= 0x03; 2323 2324 write_byte(ebda_seg,&EbdaData->ata.devices[device].translation, translation); 2325 2326 switch (translation) { 2327 case ATA_TRANSLATION_NONE: 2328 BX_INFO("none"); 2329 break; 2330 case ATA_TRANSLATION_LBA: 2331 BX_INFO("lba"); 2332 break; 2333 case ATA_TRANSLATION_LARGE: 2334 BX_INFO("large"); 2335 break; 2336 case ATA_TRANSLATION_RECHS: 2337 BX_INFO("r-echs"); 2338 break; 2339 } 2340 switch (translation) { 2341 case ATA_TRANSLATION_NONE: 2342 break; 2343 case ATA_TRANSLATION_LBA: 2344 spt = 63; 2345 sectors /= 63; 2346 heads = sectors / 1024; 2347 if (heads>128) heads = 255; 2348 else if (heads>64) heads = 128; 2349 else if (heads>32) heads = 64; 2350 else if (heads>16) heads = 32; 2351 else heads=16; 2352 cylinders = sectors / heads; 2353 break; 2354 case ATA_TRANSLATION_RECHS: 2355 // Take care not to overflow 2356 if (heads==16) { 2357 if(cylinders>61439) cylinders=61439; 2358 heads=15; 2359 cylinders = (Bit16u)((Bit32u)(cylinders)*16/15); 2360 } 2361 // then go through the large bitshift process 2362 case ATA_TRANSLATION_LARGE: 2363 while(cylinders > 1024) { 2364 cylinders >>= 1; 2365 heads <<= 1; 2366 2367 // If we max out the head count 2368 if (heads > 127) break; 2369 } 2370 break; 2371 } 2372 // clip to 1024 cylinders in lchs 2373 if (cylinders > 1024) cylinders=1024; 2374 BX_INFO(" LCHS=%d/%d/%d\n", cylinders, heads, spt); 2375 2376 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, heads); 2377 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, cylinders); 2378 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, spt); 2379 2380 // fill hdidmap 2381 write_byte(ebda_seg,&EbdaData->ata.hdidmap[hdcount], device); 2382 hdcount++; 2383 } 2384 2385 // Now we send a IDENTIFY command to ATAPI device 2386 if(type == ATA_TYPE_ATAPI) { 2387 2388 Bit8u type, removable, mode; 2389 Bit16u blksize; 2390 2391 //Temporary values to do the transfer 2392 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_CDROM); 2393 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16); 2394 2395 if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, get_SS(),buffer) != 0) 2396 BX_PANIC("ata-detect: Failed to detect ATAPI device\n"); 2397 2398 type = read_byte(get_SS(),buffer+1) & 0x1f; 2399 removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0; 2400 mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16; 2401 blksize = 2048; 2402 2403 write_byte(ebda_seg,&EbdaData->ata.devices[device].device, type); 2404 write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable); 2405 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode); 2406 write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize); 2407 2408 // fill cdidmap 2409 write_byte(ebda_seg,&EbdaData->ata.cdidmap[cdcount], device); 2410 cdcount++; 2411 } 2412 2413 { 2414 Bit32u sizeinmb; 2415 Bit16u ataversion; 2416 Bit8u c, i, version, model[41]; 2417 2418 switch (type) { 2419 case ATA_TYPE_ATA: 2420 sizeinmb = read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors); 2421 sizeinmb >>= 11; 2422 case ATA_TYPE_ATAPI: 2423 // Read ATA/ATAPI version 2424 ataversion=((Bit16u)(read_byte(get_SS(),buffer+161))<<8)|read_byte(get_SS(),buffer+160); 2425 for(version=15;version>0;version--) { 2426 if((ataversion&(1<<version))!=0) 2427 break; 2428 } 2429 2430 // Read model name 2431 for(i=0;i<20;i++){ 2432 write_byte(get_SS(),model+(i*2),read_byte(get_SS(),buffer+(i*2)+54+1)); 2433 write_byte(get_SS(),model+(i*2)+1,read_byte(get_SS(),buffer+(i*2)+54)); 2434 } 2435 2436 // Reformat 2437 write_byte(get_SS(),model+40,0x00); 2438 for(i=39;i>0;i--){ 2439 if(read_byte(get_SS(),model+i)==0x20) 2440 write_byte(get_SS(),model+i,0x00); 2441 else break; 2442 } 2443 break; 2444 } 2445 2446 switch (type) { 2447 case ATA_TYPE_ATA: 2448 printf("ata%d %s: ",channel,slave?" slave":"master"); 2449 i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c); 2450 printf(" ATA-%d Hard-Disk (%lu MBytes)\n", version, sizeinmb); 2451 break; 2452 case ATA_TYPE_ATAPI: 2453 printf("ata%d %s: ",channel,slave?" slave":"master"); 2454 i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c); 2455 if(read_byte(ebda_seg,&EbdaData->ata.devices[device].device)==ATA_DEVICE_CDROM) 2456 printf(" ATAPI-%d CD-Rom/DVD-Rom\n",version); 2457 else 2458 printf(" ATAPI-%d Device\n",version); 2459 break; 2460 case ATA_TYPE_UNKNOWN: 2461 printf("ata%d %s: Unknown device\n",channel,slave?" slave":"master"); 2462 break; 2463 } 2464 } 2465 } 2466 2467 // Store the devices counts 2468 write_byte(ebda_seg,&EbdaData->ata.hdcount, hdcount); 2469 write_byte(ebda_seg,&EbdaData->ata.cdcount, cdcount); 2470 write_byte(0x40,0x75, hdcount); 2471 2472 printf("\n"); 2473 2474 // FIXME : should use bios=cmos|auto|disable bits 2475 // FIXME : should know about translation bits 2476 // FIXME : move hard_drive_post here 2477 2478 } 2479 2480 // --------------------------------------------------------------------------- 2481 // ATA/ATAPI driver : software reset 2482 // --------------------------------------------------------------------------- 2483 // ATA-3 2484 // 8.2.1 Software reset - Device 0 2485 2486 void ata_reset(device) 2487 Bit16u device; 2488 { 2489 Bit16u ebda_seg=read_word(0x0040,0x000E); 2490 Bit16u iobase1, iobase2; 2491 Bit8u channel, slave, sn, sc; 2492 Bit16u max; 2493 2494 channel = device / 2; 2495 slave = device % 2; 2496 2497 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 2498 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2); 2499 2500 // Reset 2501 2502 // 8.2.1 (a) -- set SRST in DC 2503 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST); 2504 2505 // 8.2.1 (b) -- wait for BSY 2506 max=0xff; 2507 while(--max>0) { 2508 Bit8u status = inb(iobase1+ATA_CB_STAT); 2509 if ((status & ATA_CB_STAT_BSY) != 0) break; 2510 } 2511 2512 // 8.2.1 (f) -- clear SRST 2513 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); 2514 2515 if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_NONE) { 2516 2517 // 8.2.1 (g) -- check for sc==sn==0x01 2518 // select device 2519 outb(iobase1+ATA_CB_DH, slave?ATA_CB_DH_DEV1:ATA_CB_DH_DEV0); 2520 sc = inb(iobase1+ATA_CB_SC); 2521 sn = inb(iobase1+ATA_CB_SN); 2522 2523 if ( (sc==0x01) && (sn==0x01) ) { 2524 2525 // 8.2.1 (h) -- wait for not BSY 2526 max=0xff; 2527 while(--max>0) { 2528 Bit8u status = inb(iobase1+ATA_CB_STAT); 2529 if ((status & ATA_CB_STAT_BSY) == 0) break; 2530 } 2531 } 2532 } 2533 2534 // 8.2.1 (i) -- wait for DRDY 2535 max=0xfff; 2536 while(--max>0) { 2537 Bit8u status = inb(iobase1+ATA_CB_STAT); 2538 if ((status & ATA_CB_STAT_RDY) != 0) break; 2539 } 2540 2541 // Enable interrupts 2542 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15); 2543 } 2544 2545 // --------------------------------------------------------------------------- 2546 // ATA/ATAPI driver : execute a non data command 2547 // --------------------------------------------------------------------------- 2548 2549 Bit16u ata_cmd_non_data() 2550 {return 0;} 2551 2552 // --------------------------------------------------------------------------- 2553 // ATA/ATAPI driver : execute a data-in command 2554 // --------------------------------------------------------------------------- 2555 // returns 2556 // 0 : no error 2557 // 1 : BUSY bit set 2558 // 2 : read error 2559 // 3 : expected DRQ=1 2560 // 4 : no sectors left to read/verify 2561 // 5 : more sectors to read/verify 2562 // 6 : no sectors left to write 2563 // 7 : more sectors to write 2564 Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, lba, segment, offset) 2565 Bit16u device, command, count, cylinder, head, sector, segment, offset; 2566 Bit32u lba; 2567 { 2568 Bit16u ebda_seg=read_word(0x0040,0x000E); 2569 Bit16u iobase1, iobase2, blksize; 2570 Bit8u channel, slave; 2571 Bit8u status, current, mode; 2572 2573 channel = device / 2; 2574 slave = device % 2; 2575 2576 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 2577 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2); 2578 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode); 2579 blksize = 0x200; // was = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize); 2580 if (mode == ATA_MODE_PIO32) blksize>>=2; 2581 else blksize>>=1; 2582 2583 // sector will be 0 only on lba access. Convert to lba-chs 2584 if (sector == 0) { 2585 sector = (Bit16u) (lba & 0x000000ffL); 2586 lba >>= 8; 2587 cylinder = (Bit16u) (lba & 0x0000ffffL); 2588 lba >>= 16; 2589 head = ((Bit16u) (lba & 0x0000000fL)) | 0x40; 2590 } 2591 2592 // Reset count of transferred data 2593 write_word(ebda_seg, &EbdaData->ata.trsfsectors,0); 2594 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L); 2595 current = 0; 2596 2597 status = inb(iobase1 + ATA_CB_STAT); 2598 if (status & ATA_CB_STAT_BSY) return 1; 2599 2600 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); 2601 outb(iobase1 + ATA_CB_FR, 0x00); 2602 outb(iobase1 + ATA_CB_SC, count); 2603 outb(iobase1 + ATA_CB_SN, sector); 2604 outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff); 2605 outb(iobase1 + ATA_CB_CH, cylinder >> 8); 2606 outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head ); 2607 outb(iobase1 + ATA_CB_CMD, command); 2608 2609 while (1) { 2610 status = inb(iobase1 + ATA_CB_STAT); 2611 if ( !(status & ATA_CB_STAT_BSY) ) break; 2612 } 2613 2614 if (status & ATA_CB_STAT_ERR) { 2615 BX_DEBUG_ATA("ata_cmd_data_in : read error\n"); 2616 return 2; 2617 } else if ( !(status & ATA_CB_STAT_DRQ) ) { 2618 BX_DEBUG_ATA("ata_cmd_data_in : DRQ not set (status %02x)\n", (unsigned) status); 2619 return 3; 2620 } 2621 2622 // FIXME : move seg/off translation here 2623 2624 ASM_START 2625 sti ;; enable higher priority interrupts 2626 ASM_END 2627 2628 while (1) { 2629 2630 ASM_START 2631 push bp 2632 mov bp, sp 2633 mov di, _ata_cmd_data_in.offset + 2[bp] 2634 mov ax, _ata_cmd_data_in.segment + 2[bp] 2635 mov cx, _ata_cmd_data_in.blksize + 2[bp] 2636 2637 ;; adjust if there will be an overrun. 2K max sector size 2638 cmp di, #0xf800 ;; 2639 jbe ata_in_no_adjust 2640 2641 ata_in_adjust: 2642 sub di, #0x0800 ;; sub 2 kbytes from offset 2643 add ax, #0x0080 ;; add 2 Kbytes to segment 2644 2645 ata_in_no_adjust: 2646 mov es, ax ;; segment in es 2647 2648 mov dx, _ata_cmd_data_in.iobase1 + 2[bp] ;; ATA data read port 2649 2650 mov ah, _ata_cmd_data_in.mode + 2[bp] 2651 cmp ah, #ATA_MODE_PIO32 2652 je ata_in_32 2653 2654 ata_in_16: 2655 rep 2656 insw ;; CX words transfered from port(DX) to ES:[DI] 2657 jmp ata_in_done 2658 2659 ata_in_32: 2660 rep 2661 insd ;; CX dwords transfered from port(DX) to ES:[DI] 2662 2663 ata_in_done: 2664 mov _ata_cmd_data_in.offset + 2[bp], di 2665 mov _ata_cmd_data_in.segment + 2[bp], es 2666 pop bp 2667 ASM_END 2668 2669 current++; 2670 write_word(ebda_seg, &EbdaData->ata.trsfsectors,current); 2671 count--; 2672 status = inb(iobase1 + ATA_CB_STAT); 2673 if (count == 0) { 2674 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 2675 != ATA_CB_STAT_RDY ) { 2676 BX_DEBUG_ATA("ata_cmd_data_in : no sectors left (status %02x)\n", (unsigned) status); 2677 return 4; 2678 } 2679 break; 2680 } 2681 else { 2682 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 2683 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) { 2684 BX_DEBUG_ATA("ata_cmd_data_in : more sectors left (status %02x)\n", (unsigned) status); 2685 return 5; 2686 } 2687 continue; 2688 } 2689 } 2690 // Enable interrupts 2691 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15); 2692 return 0; 2693 } 2694 2695 // --------------------------------------------------------------------------- 2696 // ATA/ATAPI driver : execute a data-out command 2697 // --------------------------------------------------------------------------- 2698 // returns 2699 // 0 : no error 2700 // 1 : BUSY bit set 2701 // 2 : read error 2702 // 3 : expected DRQ=1 2703 // 4 : no sectors left to read/verify 2704 // 5 : more sectors to read/verify 2705 // 6 : no sectors left to write 2706 // 7 : more sectors to write 2707 Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, lba, segment, offset) 2708 Bit16u device, command, count, cylinder, head, sector, segment, offset; 2709 Bit32u lba; 2710 { 2711 Bit16u ebda_seg=read_word(0x0040,0x000E); 2712 Bit16u iobase1, iobase2, blksize; 2713 Bit8u channel, slave; 2714 Bit8u status, current, mode; 2715 2716 channel = device / 2; 2717 slave = device % 2; 2718 2719 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 2720 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2); 2721 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode); 2722 blksize = 0x200; // was = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize); 2723 if (mode == ATA_MODE_PIO32) blksize>>=2; 2724 else blksize>>=1; 2725 2726 // sector will be 0 only on lba access. Convert to lba-chs 2727 if (sector == 0) { 2728 sector = (Bit16u) (lba & 0x000000ffL); 2729 lba >>= 8; 2730 cylinder = (Bit16u) (lba & 0x0000ffffL); 2731 lba >>= 16; 2732 head = ((Bit16u) (lba & 0x0000000fL)) | 0x40; 2733 } 2734 2735 // Reset count of transferred data 2736 write_word(ebda_seg, &EbdaData->ata.trsfsectors,0); 2737 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L); 2738 current = 0; 2739 2740 status = inb(iobase1 + ATA_CB_STAT); 2741 if (status & ATA_CB_STAT_BSY) return 1; 2742 2743 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); 2744 outb(iobase1 + ATA_CB_FR, 0x00); 2745 outb(iobase1 + ATA_CB_SC, count); 2746 outb(iobase1 + ATA_CB_SN, sector); 2747 outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff); 2748 outb(iobase1 + ATA_CB_CH, cylinder >> 8); 2749 outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head ); 2750 outb(iobase1 + ATA_CB_CMD, command); 2751 2752 while (1) { 2753 status = inb(iobase1 + ATA_CB_STAT); 2754 if ( !(status & ATA_CB_STAT_BSY) ) break; 2755 } 2756 2757 if (status & ATA_CB_STAT_ERR) { 2758 BX_DEBUG_ATA("ata_cmd_data_out : read error\n"); 2759 return 2; 2760 } else if ( !(status & ATA_CB_STAT_DRQ) ) { 2761 BX_DEBUG_ATA("ata_cmd_data_out : DRQ not set (status %02x)\n", (unsigned) status); 2762 return 3; 2763 } 2764 2765 // FIXME : move seg/off translation here 2766 2767 ASM_START 2768 sti ;; enable higher priority interrupts 2769 ASM_END 2770 2771 while (1) { 2772 2773 ASM_START 2774 push bp 2775 mov bp, sp 2776 mov si, _ata_cmd_data_out.offset + 2[bp] 2777 mov ax, _ata_cmd_data_out.segment + 2[bp] 2778 mov cx, _ata_cmd_data_out.blksize + 2[bp] 2779 2780 ;; adjust if there will be an overrun. 2K max sector size 2781 cmp si, #0xf800 ;; 2782 jbe ata_out_no_adjust 2783 2784 ata_out_adjust: 2785 sub si, #0x0800 ;; sub 2 kbytes from offset 2786 add ax, #0x0080 ;; add 2 Kbytes to segment 2787 2788 ata_out_no_adjust: 2789 mov es, ax ;; segment in es 2790 2791 mov dx, _ata_cmd_data_out.iobase1 + 2[bp] ;; ATA data write port 2792 2793 mov ah, _ata_cmd_data_out.mode + 2[bp] 2794 cmp ah, #ATA_MODE_PIO32 2795 je ata_out_32 2796 2797 ata_out_16: 2798 seg ES 2799 rep 2800 outsw ;; CX words transfered from port(DX) to ES:[SI] 2801 jmp ata_out_done 2802 2803 ata_out_32: 2804 seg ES 2805 rep 2806 outsd ;; CX dwords transfered from port(DX) to ES:[SI] 2807 2808 ata_out_done: 2809 mov _ata_cmd_data_out.offset + 2[bp], si 2810 mov _ata_cmd_data_out.segment + 2[bp], es 2811 pop bp 2812 ASM_END 2813 2814 current++; 2815 write_word(ebda_seg, &EbdaData->ata.trsfsectors,current); 2816 count--; 2817 status = inb(iobase1 + ATA_CB_STAT); 2818 if (count == 0) { 2819 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 2820 != ATA_CB_STAT_RDY ) { 2821 BX_DEBUG_ATA("ata_cmd_data_out : no sectors left (status %02x)\n", (unsigned) status); 2822 return 6; 2823 } 2824 break; 2825 } 2826 else { 2827 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 2828 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) { 2829 BX_DEBUG_ATA("ata_cmd_data_out : more sectors left (status %02x)\n", (unsigned) status); 2830 return 7; 2831 } 2832 continue; 2833 } 2834 } 2835 // Enable interrupts 2836 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15); 2837 return 0; 2838 } 2839 2840 // --------------------------------------------------------------------------- 2841 // ATA/ATAPI driver : execute a packet command 2842 // --------------------------------------------------------------------------- 2843 // returns 2844 // 0 : no error 2845 // 1 : error in parameters 2846 // 2 : BUSY bit set 2847 // 3 : error 2848 // 4 : not ready 2849 Bit16u ata_cmd_packet(device, cmdlen, cmdseg, cmdoff, header, length, inout, bufseg, bufoff) 2850 Bit8u cmdlen,inout; 2851 Bit16u device,cmdseg, cmdoff, bufseg, bufoff; 2852 Bit16u header; 2853 Bit32u length; 2854 { 2855 Bit16u ebda_seg=read_word(0x0040,0x000E); 2856 Bit16u iobase1, iobase2; 2857 Bit16u lcount, lbefore, lafter, count; 2858 Bit8u channel, slave; 2859 Bit8u status, mode, lmode; 2860 Bit32u total, transfer; 2861 2862 channel = device / 2; 2863 slave = device % 2; 2864 2865 // Data out is not supported yet 2866 if (inout == ATA_DATA_OUT) { 2867 BX_INFO("ata_cmd_packet: DATA_OUT not supported yet\n"); 2868 return 1; 2869 } 2870 2871 // The header length must be even 2872 if (header & 1) { 2873 BX_DEBUG_ATA("ata_cmd_packet : header must be even (%04x)\n",header); 2874 return 1; 2875 } 2876 2877 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 2878 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2); 2879 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode); 2880 transfer= 0L; 2881 2882 if (cmdlen < 12) cmdlen=12; 2883 if (cmdlen > 12) cmdlen=16; 2884 cmdlen>>=1; 2885 2886 // Reset count of transferred data 2887 write_word(ebda_seg, &EbdaData->ata.trsfsectors,0); 2888 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L); 2889 2890 status = inb(iobase1 + ATA_CB_STAT); 2891 if (status & ATA_CB_STAT_BSY) return 2; 2892 2893 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); 2894 // outb(iobase1 + ATA_CB_FR, 0x00); 2895 // outb(iobase1 + ATA_CB_SC, 0x00); 2896 // outb(iobase1 + ATA_CB_SN, 0x00); 2897 outb(iobase1 + ATA_CB_CL, 0xfff0 & 0x00ff); 2898 outb(iobase1 + ATA_CB_CH, 0xfff0 >> 8); 2899 outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0); 2900 outb(iobase1 + ATA_CB_CMD, ATA_CMD_PACKET); 2901 2902 // Device should ok to receive command 2903 while (1) { 2904 status = inb(iobase1 + ATA_CB_STAT); 2905 if ( !(status & ATA_CB_STAT_BSY) ) break; 2906 } 2907 2908 if (status & ATA_CB_STAT_ERR) { 2909 BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status); 2910 return 3; 2911 } else if ( !(status & ATA_CB_STAT_DRQ) ) { 2912 BX_DEBUG_ATA("ata_cmd_packet : DRQ not set (status %02x)\n", (unsigned) status); 2913 return 4; 2914 } 2915 2916 // Normalize address 2917 cmdseg += (cmdoff / 16); 2918 cmdoff %= 16; 2919 2920 // Send command to device 2921 ASM_START 2922 sti ;; enable higher priority interrupts 2923 2924 push bp 2925 mov bp, sp 2926 2927 mov si, _ata_cmd_packet.cmdoff + 2[bp] 2928 mov ax, _ata_cmd_packet.cmdseg + 2[bp] 2929 mov cx, _ata_cmd_packet.cmdlen + 2[bp] 2930 mov es, ax ;; segment in es 2931 2932 mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data write port 2933 2934 seg ES 2935 rep 2936 outsw ;; CX words transfered from port(DX) to ES:[SI] 2937 2938 pop bp 2939 ASM_END 2940 2941 if (inout == ATA_DATA_NO) { 2942 status = inb(iobase1 + ATA_CB_STAT); 2943 } 2944 else { 2945 while (1) { 2946 2947 status = inb(iobase1 + ATA_CB_STAT); 2948 2949 // Check if command completed 2950 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ) ) ==0 ) break; 2951 2952 if (status & ATA_CB_STAT_ERR) { 2953 BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status); 2954 return 3; 2955 } 2956 2957 // Device must be ready to send data 2958 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 2959 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) { 2960 BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", status); 2961 return 4; 2962 } 2963 2964 // Normalize address 2965 bufseg += (bufoff / 16); 2966 bufoff %= 16; 2967 2968 // Get the byte count 2969 lcount = ((Bit16u)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL); 2970 2971 // adjust to read what we want 2972 if(header>lcount) { 2973 lbefore=lcount; 2974 header-=lcount; 2975 lcount=0; 2976 } 2977 else { 2978 lbefore=header; 2979 header=0; 2980 lcount-=lbefore; 2981 } 2982 2983 if(lcount>length) { 2984 lafter=lcount-length; 2985 lcount=length; 2986 length=0; 2987 } 2988 else { 2989 lafter=0; 2990 length-=lcount; 2991 } 2992 2993 // Save byte count 2994 count = lcount; 2995 2996 BX_DEBUG_ATA("Trying to read %04x bytes (%04x %04x %04x) ",lbefore+lcount+lafter,lbefore,lcount,lafter); 2997 BX_DEBUG_ATA("to 0x%04x:0x%04x\n",bufseg,bufoff); 2998 2999 // If counts not dividable by 4, use 16bits mode 3000 lmode = mode; 3001 if (lbefore & 0x03) lmode=ATA_MODE_PIO16; 3002 if (lcount & 0x03) lmode=ATA_MODE_PIO16; 3003 if (lafter & 0x03) lmode=ATA_MODE_PIO16; 3004 3005 // adds an extra byte if count are odd. before is always even 3006 if (lcount & 0x01) { 3007 lcount+=1; 3008 if ((lafter > 0) && (lafter & 0x01)) { 3009 lafter-=1; 3010 } 3011 } 3012 3013 if (lmode == ATA_MODE_PIO32) { 3014 lcount>>=2; lbefore>>=2; lafter>>=2; 3015 } 3016 else { 3017 lcount>>=1; lbefore>>=1; lafter>>=1; 3018 } 3019 3020 ; // FIXME bcc bug 3021 3022 ASM_START 3023 push bp 3024 mov bp, sp 3025 3026 mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data read port 3027 3028 mov cx, _ata_cmd_packet.lbefore + 2[bp] 3029 jcxz ata_packet_no_before 3030 3031 mov ah, _ata_cmd_packet.lmode + 2[bp] 3032 cmp ah, #ATA_MODE_PIO32 3033 je ata_packet_in_before_32 3034 3035 ata_packet_in_before_16: 3036 in ax, dx 3037 loop ata_packet_in_before_16 3038 jmp ata_packet_no_before 3039 3040 ata_packet_in_before_32: 3041 push eax 3042 ata_packet_in_before_32_loop: 3043 in eax, dx 3044 loop ata_packet_in_before_32_loop 3045 pop eax 3046 3047 ata_packet_no_before: 3048 mov cx, _ata_cmd_packet.lcount + 2[bp] 3049 jcxz ata_packet_after 3050 3051 mov di, _ata_cmd_packet.bufoff + 2[bp] 3052 mov ax, _ata_cmd_packet.bufseg + 2[bp] 3053 mov es, ax 3054 3055 mov ah, _ata_cmd_packet.lmode + 2[bp] 3056 cmp ah, #ATA_MODE_PIO32 3057 je ata_packet_in_32 3058 3059 ata_packet_in_16: 3060 rep 3061 insw ;; CX words transfered tp port(DX) to ES:[DI] 3062 jmp ata_packet_after 3063 3064 ata_packet_in_32: 3065 rep 3066 insd ;; CX dwords transfered to port(DX) to ES:[DI] 3067 3068 ata_packet_after: 3069 mov cx, _ata_cmd_packet.lafter + 2[bp] 3070 jcxz ata_packet_done 3071 3072 mov ah, _ata_cmd_packet.lmode + 2[bp] 3073 cmp ah, #ATA_MODE_PIO32 3074 je ata_packet_in_after_32 3075 3076 ata_packet_in_after_16: 3077 in ax, dx 3078 loop ata_packet_in_after_16 3079 jmp ata_packet_done 3080 3081 ata_packet_in_after_32: 3082 push eax 3083 ata_packet_in_after_32_loop: 3084 in eax, dx 3085 loop ata_packet_in_after_32_loop 3086 pop eax 3087 3088 ata_packet_done: 3089 pop bp 3090 ASM_END 3091 3092 // Compute new buffer address 3093 bufoff += count; 3094 3095 // Save transferred bytes count 3096 transfer += count; 3097 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,transfer); 3098 } 3099 } 3100 3101 // Final check, device must be ready 3102 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 3103 != ATA_CB_STAT_RDY ) { 3104 BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", (unsigned) status); 3105 return 4; 3106 } 3107 3108 // Enable interrupts 3109 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15); 3110 return 0; 3111 } 3112 3113 // --------------------------------------------------------------------------- 3114 // End of ATA/ATAPI Driver 3115 // --------------------------------------------------------------------------- 3116 3117 // --------------------------------------------------------------------------- 3118 // Start of ATA/ATAPI generic functions 3119 // --------------------------------------------------------------------------- 3120 3121 Bit16u 3122 atapi_get_sense(device) 3123 Bit16u device; 3124 { 3125 Bit8u atacmd[12]; 3126 Bit8u buffer[16]; 3127 Bit8u i; 3128 3129 memsetb(get_SS(),atacmd,0,12); 3130 3131 // Request SENSE 3132 atacmd[0]=0x03; 3133 atacmd[4]=0x20; 3134 if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 16L, ATA_DATA_IN, get_SS(), buffer) != 0) 3135 return 0x0002; 3136 3137 if ((buffer[0] & 0x7e) == 0x70) { 3138 return (((Bit16u)buffer[2]&0x0f)*0x100)+buffer[12]; 3139 } 3140 3141 return 0; 3142 } 3143 3144 Bit16u 3145 atapi_is_ready(device) 3146 Bit16u device; 3147 { 3148 Bit8u atacmd[12]; 3149 Bit8u buffer[]; 3150 3151 memsetb(get_SS(),atacmd,0,12); 3152 3153 // Test Unit Ready 3154 if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO, get_SS(), buffer) != 0) 3155 return 0x000f; 3156 3157 if (atapi_get_sense(device) !=0 ) { 3158 memsetb(get_SS(),atacmd,0,12); 3159 3160 // try to send Test Unit Ready again 3161 if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO, get_SS(), buffer) != 0) 3162 return 0x000f; 3163 3164 return atapi_get_sense(device); 3165 } 3166 return 0; 3167 } 3168 3169 Bit16u 3170 atapi_is_cdrom(device) 3171 Bit8u device; 3172 { 3173 Bit16u ebda_seg=read_word(0x0040,0x000E); 3174 3175 if (device >= BX_MAX_ATA_DEVICES) 3176 return 0; 3177 3178 if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_ATAPI) 3179 return 0; 3180 3181 if (read_byte(ebda_seg,&EbdaData->ata.devices[device].device) != ATA_DEVICE_CDROM) 3182 return 0; 3183 3184 return 1; 3185 } 3186 3187 // --------------------------------------------------------------------------- 3188 // End of ATA/ATAPI generic functions 3189 // --------------------------------------------------------------------------- 3190 3191 #endif // BX_USE_ATADRV 3192 3193 #if BX_ELTORITO_BOOT 3194 3195 // --------------------------------------------------------------------------- 3196 // Start of El-Torito boot functions 3197 // --------------------------------------------------------------------------- 3198 3199 void 3200 cdemu_init() 3201 { 3202 Bit16u ebda_seg=read_word(0x0040,0x000E); 3203 3204 // the only important data is this one for now 3205 write_byte(ebda_seg,&EbdaData->cdemu.active,0x00); 3206 } 3207 3208 Bit8u 3209 cdemu_isactive() 3210 { 3211 Bit16u ebda_seg=read_word(0x0040,0x000E); 3212 3213 return(read_byte(ebda_seg,&EbdaData->cdemu.active)); 3214 } 3215 3216 Bit8u 3217 cdemu_emulated_drive() 3218 { 3219 Bit16u ebda_seg=read_word(0x0040,0x000E); 3220 3221 return(read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)); 3222 } 3223 3224 static char isotag[6]="CD001"; 3225 static char eltorito[24]="EL TORITO SPECIFICATION"; 3226 // 3227 // Returns ah: emulated drive, al: error code 3228 // 3229 Bit16u 3230 cdrom_boot() 3231 { 3232 Bit16u ebda_seg=read_word(0x0040,0x000E); 3233 Bit8u atacmd[12], buffer[2048]; 3234 Bit32u lba; 3235 Bit16u boot_segment, nbsectors, i, error; 3236 Bit8u device; 3237 3238 // Find out the first cdrom 3239 for (device=0; device<BX_MAX_ATA_DEVICES;device++) { 3240 if (atapi_is_cdrom(device)) break; 3241 } 3242 3243 // if not found 3244 if(device >= BX_MAX_ATA_DEVICES) return 2; 3245 3246 // Read the Boot Record Volume Descriptor 3247 memsetb(get_SS(),atacmd,0,12); 3248 atacmd[0]=0x28; // READ command 3249 atacmd[7]=(0x01 & 0xff00) >> 8; // Sectors 3250 atacmd[8]=(0x01 & 0x00ff); // Sectors 3251 atacmd[2]=(0x11 & 0xff000000) >> 24; // LBA 3252 atacmd[3]=(0x11 & 0x00ff0000) >> 16; 3253 atacmd[4]=(0x11 & 0x0000ff00) >> 8; 3254 atacmd[5]=(0x11 & 0x000000ff); 3255 if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0) 3256 return 3; 3257 3258 // Validity checks 3259 if(buffer[0]!=0)return 4; 3260 for(i=0;i<5;i++){ 3261 if(buffer[1+i]!=read_byte(0xf000,&isotag[i]))return 5; 3262 } 3263 for(i=0;i<23;i++) 3264 if(buffer[7+i]!=read_byte(0xf000,&eltorito[i]))return 6; 3265 3266 // ok, now we calculate the Boot catalog address 3267 lba=buffer[0x4A]*0x1000000+buffer[0x49]*0x10000+buffer[0x48]*0x100+buffer[0x47]; 3268 3269 // And we read the Boot Catalog 3270 memsetb(get_SS(),atacmd,0,12); 3271 atacmd[0]=0x28; // READ command 3272 atacmd[7]=(0x01 & 0xff00) >> 8; // Sectors 3273 atacmd[8]=(0x01 & 0x00ff); // Sectors 3274 atacmd[2]=(lba & 0xff000000) >> 24; // LBA 3275 atacmd[3]=(lba & 0x00ff0000) >> 16; 3276 atacmd[4]=(lba & 0x0000ff00) >> 8; 3277 atacmd[5]=(lba & 0x000000ff); 3278 if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0) 3279 return 7; 3280 3281 // Validation entry 3282 if(buffer[0x00]!=0x01)return 8; // Header 3283 if(buffer[0x01]!=0x00)return 9; // Platform 3284 if(buffer[0x1E]!=0x55)return 10; // key 1 3285 if(buffer[0x1F]!=0xAA)return 10; // key 2 3286 3287 // Initial/Default Entry 3288 if(buffer[0x20]!=0x88)return 11; // Bootable 3289 3290 write_byte(ebda_seg,&EbdaData->cdemu.media,buffer[0x21]); 3291 if(buffer[0x21]==0){ 3292 // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0. 3293 // Win2000 cd boot needs to know it booted from cd 3294 write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0xE0); 3295 } 3296 else if(buffer[0x21]<4) 3297 write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x00); 3298 else 3299 write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x80); 3300 3301 write_byte(ebda_seg,&EbdaData->cdemu.controller_index,device/2); 3302 write_byte(ebda_seg,&EbdaData->cdemu.device_spec,device%2); 3303 3304 boot_segment=buffer[0x23]*0x100+buffer[0x22]; 3305 if(boot_segment==0x0000)boot_segment=0x07C0; 3306 3307 write_word(ebda_seg,&EbdaData->cdemu.load_segment,boot_segment); 3308 write_word(ebda_seg,&EbdaData->cdemu.buffer_segment,0x0000); 3309 3310 nbsectors=buffer[0x27]*0x100+buffer[0x26]; 3311 write_word(ebda_seg,&EbdaData->cdemu.sector_count,nbsectors); 3312 3313 lba=buffer[0x2B]*0x1000000+buffer[0x2A]*0x10000+buffer[0x29]*0x100+buffer[0x28]; 3314 write_dword(ebda_seg,&EbdaData->cdemu.ilba,lba); 3315 3316 // And we read the image in memory 3317 memsetb(get_SS(),atacmd,0,12); 3318 atacmd[0]=0x28; // READ command 3319 atacmd[7]=((1+(nbsectors-1)/4) & 0xff00) >> 8; // Sectors 3320 atacmd[8]=((1+(nbsectors-1)/4) & 0x00ff); // Sectors 3321 atacmd[2]=(lba & 0xff000000) >> 24; // LBA 3322 atacmd[3]=(lba & 0x00ff0000) >> 16; 3323 atacmd[4]=(lba & 0x0000ff00) >> 8; 3324 atacmd[5]=(lba & 0x000000ff); 3325 if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, nbsectors*512L, ATA_DATA_IN, boot_segment,0)) != 0) 3326 return 12; 3327 3328 // Remember the media type 3329 switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) { 3330 case 0x01: // 1.2M floppy 3331 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,15); 3332 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80); 3333 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2); 3334 break; 3335 case 0x02: // 1.44M floppy 3336 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,18); 3337 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80); 3338 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2); 3339 break; 3340 case 0x03: // 2.88M floppy 3341 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,36); 3342 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80); 3343 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2); 3344 break; 3345 case 0x04: // Harddrive 3346 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,read_byte(boot_segment,446+6)&0x3f); 3347 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders, 3348 (read_byte(boot_segment,446+6)<<2) + read_byte(boot_segment,446+7) + 1); 3349 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,read_byte(boot_segment,446+5) + 1); 3350 break; 3351 } 3352 3353 if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0) { 3354 // Increase bios installed hardware number of devices 3355 if(read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)==0x00) 3356 write_byte(0x40,0x10,read_byte(0x40,0x10)|0x41); 3357 else 3358 write_byte(ebda_seg, &EbdaData->ata.hdcount, read_byte(ebda_seg, &EbdaData->ata.hdcount) + 1); 3359 } 3360 3361 3362 // everything is ok, so from now on, the emulation is active 3363 if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0) 3364 write_byte(ebda_seg,&EbdaData->cdemu.active,0x01); 3365 3366 // return the boot drive + no error 3367 return (read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)*0x100)+0; 3368 } 3369 3370 // --------------------------------------------------------------------------- 3371 // End of El-Torito boot functions 3372 // --------------------------------------------------------------------------- 3373 #endif // BX_ELTORITO_BOOT 3374 3375 void 3376 int14_function(regs, ds, iret_addr) 3377 pusha_regs_t regs; // regs pushed from PUSHA instruction 3378 Bit16u ds; // previous DS:, DS set to 0x0000 by asm wrapper 3379 iret_addr_t iret_addr; // CS,IP,Flags pushed from original INT call 3380 { 3381 Bit16u addr,timer,val16; 3382 Bit8u timeout; 3383 3384 ASM_START 3385 sti 3386 ASM_END 3387 3388 addr = read_word(0x0040, (regs.u.r16.dx << 1)); 3389 timeout = read_byte(0x0040, 0x007C + regs.u.r16.dx); 3390 if ((regs.u.r16.dx < 4) && (addr > 0)) { 3391 switch (regs.u.r8.ah) { 3392 case 0: 3393 outb(addr+3, inb(addr+3) | 0x80); 3394 if (regs.u.r8.al & 0xE0 == 0) { 3395 outb(addr, 0x17); 3396 outb(addr+1, 0x04); 3397 } else { 3398 val16 = 0x600 >> ((regs.u.r8.al & 0xE0) >> 5); 3399 outb(addr, val16 & 0xFF); 3400 outb(addr+1, val16 >> 8); 3401 } 3402 outb(addr+3, regs.u.r8.al & 0x1F); 3403 regs.u.r8.ah = inb(addr+5); 3404 regs.u.r8.al = inb(addr+6); 3405 ClearCF(iret_addr.flags); 3406 break; 3407 case 1: 3408 timer = read_word(0x0040, 0x006C); 3409 while (((inb(addr+5) & 0x60) != 0x60) && (timeout)) { 3410 val16 = read_word(0x0040, 0x006C); 3411 if (val16 != timer) { 3412 timer = val16; 3413 timeout--; 3414 } 3415 } 3416 if (timeout) outb(addr, regs.u.r8.al); 3417 regs.u.r8.ah = inb(addr+5); 3418 if (!timeout) regs.u.r8.ah |= 0x80; 3419 ClearCF(iret_addr.flags); 3420 break; 3421 case 2: 3422 timer = read_word(0x0040, 0x006C); 3423 while (((inb(addr+5) & 0x01) == 0) && (timeout)) { 3424 val16 = read_word(0x0040, 0x006C); 3425 if (val16 != timer) { 3426 timer = val16; 3427 timeout--; 3428 } 3429 } 3430 if (timeout) { 3431 regs.u.r8.ah = 0; 3432 regs.u.r8.al = inb(addr); 3433 } else { 3434 regs.u.r8.ah = inb(addr+5); 3435 } 3436 ClearCF(iret_addr.flags); 3437 break; 3438 case 3: 3439 regs.u.r8.ah = inb(addr+5); 3440 regs.u.r8.al = inb(addr+6); 3441 ClearCF(iret_addr.flags); 3442 break; 3443 default: 3444 SetCF(iret_addr.flags); // Unsupported 3445 } 3446 } else { 3447 SetCF(iret_addr.flags); // Unsupported 3448 } 3449 } 3450 3451 void 3452 int15_function(regs, ES, DS, FLAGS) 3453 pusha_regs_t regs; // REGS pushed via pusha 3454 Bit16u ES, DS, FLAGS; 3455 { 3456 Bit16u ebda_seg=read_word(0x0040,0x000E); 3457 bx_bool prev_a20_enable; 3458 Bit16u base15_00; 3459 Bit8u base23_16; 3460 Bit16u ss; 3461 Bit16u CX,DX; 3462 3463 Bit16u bRegister; 3464 Bit8u irqDisable; 3465 3466 BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax); 3467 3468 switch (regs.u.r8.ah) { 3469 case 0x24: /* A20 Control */ 3470 switch (regs.u.r8.al) { 3471 case 0x00: 3472 set_enable_a20(0); 3473 CLEAR_CF(); 3474 regs.u.r8.ah = 0; 3475 break; 3476 case 0x01: 3477 set_enable_a20(1); 3478 CLEAR_CF(); 3479 regs.u.r8.ah = 0; 3480 break; 3481 case 0x02: 3482 regs.u.r8.al = (inb(0x92) >> 1) & 0x01; 3483 CLEAR_CF(); 3484 regs.u.r8.ah = 0; 3485 break; 3486 case 0x03: 3487 CLEAR_CF(); 3488 regs.u.r8.ah = 0; 3489 regs.u.r16.bx = 3; 3490 break; 3491 default: 3492 BX_INFO("int15: Func 24h, subfunc %02xh, A20 gate control not supported\n", (unsigned) regs.u.r8.al); 3493 SET_CF(); 3494 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3495 } 3496 break; 3497 3498 case 0x41: 3499 SET_CF(); 3500 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3501 break; 3502 3503 case 0x4f: 3504 /* keyboard intercept */ 3505 #if BX_CPU < 2 3506 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3507 #else 3508 // nop 3509 #endif 3510 SET_CF(); 3511 break; 3512 3513 case 0x52: // removable media eject 3514 CLEAR_CF(); 3515 regs.u.r8.ah = 0; // "ok ejection may proceed" 3516 break; 3517 3518 case 0x83: { 3519 if( regs.u.r8.al == 0 ) { 3520 // Set Interval requested. 3521 if( ( read_byte( 0x40, 0xA0 ) & 1 ) == 0 ) { 3522 // Interval not already set. 3523 write_byte( 0x40, 0xA0, 1 ); // Set status byte. 3524 write_word( 0x40, 0x98, ES ); // Byte location, segment 3525 write_word( 0x40, 0x9A, regs.u.r16.bx ); // Byte location, offset 3526 write_word( 0x40, 0x9C, regs.u.r16.dx ); // Low word, delay 3527 write_word( 0x40, 0x9E, regs.u.r16.cx ); // High word, delay. 3528 CLEAR_CF( ); 3529 irqDisable = inb( 0xA1 ); 3530 outb( 0xA1, irqDisable & 0xFE ); 3531 bRegister = inb_cmos( 0xB ); // Unmask IRQ8 so INT70 will get through. 3532 outb_cmos( 0xB, bRegister | 0x40 ); // Turn on the Periodic Interrupt timer 3533 } else { 3534 // Interval already set. 3535 BX_DEBUG_INT15("int15: Func 83h, failed, already waiting.\n" ); 3536 SET_CF(); 3537 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3538 } 3539 } else if( regs.u.r8.al == 1 ) { 3540 // Clear Interval requested 3541 write_byte( 0x40, 0xA0, 0 ); // Clear status byte 3542 CLEAR_CF( ); 3543 bRegister = inb_cmos( 0xB ); 3544 outb_cmos( 0xB, bRegister & ~0x40 ); // Turn off the Periodic Interrupt timer 3545 } else { 3546 BX_DEBUG_INT15("int15: Func 83h, failed.\n" ); 3547 SET_CF(); 3548 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3549 regs.u.r8.al--; 3550 } 3551 3552 break; 3553 } 3554 3555 case 0x87: 3556 #if BX_CPU < 3 3557 # error "Int15 function 87h not supported on < 80386" 3558 #endif 3559 // +++ should probably have descriptor checks 3560 // +++ should have exception handlers 3561 3562 // turn off interrupts 3563 ASM_START 3564 cli 3565 ASM_END 3566 3567 prev_a20_enable = set_enable_a20(1); // enable A20 line 3568 3569 // 128K max of transfer on 386+ ??? 3570 // source == destination ??? 3571 3572 // ES:SI points to descriptor table 3573 // offset use initially comments 3574 // ============================================== 3575 // 00..07 Unused zeros Null descriptor 3576 // 08..0f GDT zeros filled in by BIOS 3577 // 10..17 source ssssssss source of data 3578 // 18..1f dest dddddddd destination of data 3579 // 20..27 CS zeros filled in by BIOS 3580 // 28..2f SS zeros filled in by BIOS 3581 3582 //es:si 3583 //eeee0 3584 //0ssss 3585 //----- 3586 3587 // check for access rights of source & dest here 3588 3589 // Initialize GDT descriptor 3590 base15_00 = (ES << 4) + regs.u.r16.si; 3591 base23_16 = ES >> 12; 3592 if (base15_00 < (ES<<4)) 3593 base23_16++; 3594 write_word(ES, regs.u.r16.si+0x08+0, 47); // limit 15:00 = 6 * 8bytes/descriptor 3595 write_word(ES, regs.u.r16.si+0x08+2, base15_00);// base 15:00 3596 write_byte(ES, regs.u.r16.si+0x08+4, base23_16);// base 23:16 3597 write_byte(ES, regs.u.r16.si+0x08+5, 0x93); // access 3598 write_word(ES, regs.u.r16.si+0x08+6, 0x0000); // base 31:24/reserved/limit 19:16 3599 3600 // Initialize CS descriptor 3601 write_word(ES, regs.u.r16.si+0x20+0, 0xffff);// limit 15:00 = normal 64K limit 3602 write_word(ES, regs.u.r16.si+0x20+2, 0x0000);// base 15:00 3603 write_byte(ES, regs.u.r16.si+0x20+4, 0x000f);// base 23:16 3604 write_byte(ES, regs.u.r16.si+0x20+5, 0x9b); // access 3605 write_word(ES, regs.u.r16.si+0x20+6, 0x0000);// base 31:24/reserved/limit 19:16 3606 3607 // Initialize SS descriptor 3608 ss = get_SS(); 3609 base15_00 = ss << 4; 3610 base23_16 = ss >> 12; 3611 write_word(ES, regs.u.r16.si+0x28+0, 0xffff); // limit 15:00 = normal 64K limit 3612 write_word(ES, regs.u.r16.si+0x28+2, base15_00);// base 15:00 3613 write_byte(ES, regs.u.r16.si+0x28+4, base23_16);// base 23:16 3614 write_byte(ES, regs.u.r16.si+0x28+5, 0x93); // access 3615 write_word(ES, regs.u.r16.si+0x28+6, 0x0000); // base 31:24/reserved/limit 19:16 3616 3617 CX = regs.u.r16.cx; 3618 ASM_START 3619 // Compile generates locals offset info relative to SP. 3620 // Get CX (word count) from stack. 3621 mov bx, sp 3622 SEG SS 3623 mov cx, _int15_function.CX [bx] 3624 3625 // since we need to set SS:SP, save them to the BDA 3626 // for future restore 3627 push eax 3628 xor eax, eax 3629 mov ds, ax 3630 mov 0x0469, ss 3631 mov 0x0467, sp 3632 3633 SEG ES 3634 lgdt [si + 0x08] 3635 SEG CS 3636 lidt [pmode_IDT_info] 3637 ;; perhaps do something with IDT here 3638 3639 ;; set PE bit in CR0 3640 mov eax, cr0 3641 or al, #0x01 3642 mov cr0, eax 3643 ;; far jump to flush CPU queue after transition to protected mode 3644 JMP_AP(0x0020, protected_mode) 3645 3646 protected_mode: 3647 ;; GDT points to valid descriptor table, now load SS, DS, ES 3648 mov ax, #0x28 ;; 101 000 = 5th descriptor in table, TI=GDT, RPL=00 3649 mov ss, ax 3650 mov ax, #0x10 ;; 010 000 = 2nd descriptor in table, TI=GDT, RPL=00 3651 mov ds, ax 3652 mov ax, #0x18 ;; 011 000 = 3rd descriptor in table, TI=GDT, RPL=00 3653 mov es, ax 3654 xor si, si 3655 xor di, di 3656 cld 3657 rep 3658 movsw ;; move CX words from DS:SI to ES:DI 3659 3660 ;; make sure DS and ES limits are 64KB 3661 mov ax, #0x28 3662 mov ds, ax 3663 mov es, ax 3664 3665 ;; reset PG bit in CR0 ??? 3666 mov eax, cr0 3667 and al, #0xFE 3668 mov cr0, eax 3669 3670 ;; far jump to flush CPU queue after transition to real mode 3671 JMP_AP(0xf000, real_mode) 3672 3673 real_mode: 3674 ;; restore IDT to normal real-mode defaults 3675 SEG CS 3676 lidt [rmode_IDT_info] 3677 3678 // restore SS:SP from the BDA 3679 xor ax, ax 3680 mov ds, ax 3681 mov ss, 0x0469 3682 mov sp, 0x0467 3683 pop eax 3684 ASM_END 3685 3686 set_enable_a20(prev_a20_enable); 3687 3688 // turn back on interrupts 3689 ASM_START 3690 sti 3691 ASM_END 3692 3693 regs.u.r8.ah = 0; 3694 CLEAR_CF(); 3695 break; 3696 3697 3698 case 0x88: 3699 // Get the amount of extended memory (above 1M) 3700 #if BX_CPU < 2 3701 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3702 SET_CF(); 3703 #else 3704 regs.u.r8.al = inb_cmos(0x30); 3705 regs.u.r8.ah = inb_cmos(0x31); 3706 3707 // According to Ralf Brown's interrupt the limit should be 15M, 3708 // but real machines mostly return max. 63M. 3709 if(regs.u.r16.ax > 0xffc0) 3710 regs.u.r16.ax = 0xffc0; 3711 3712 CLEAR_CF(); 3713 #endif 3714 break; 3715 3716 case 0x90: 3717 /* Device busy interrupt. Called by Int 16h when no key available */ 3718 break; 3719 3720 case 0x91: 3721 /* Interrupt complete. Called by Int 16h when key becomes available */ 3722 break; 3723 3724 case 0xbf: 3725 BX_INFO("*** int 15h function AH=bf not yet supported!\n"); 3726 SET_CF(); 3727 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3728 break; 3729 3730 case 0xC0: 3731 #if 0 3732 SET_CF(); 3733 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3734 break; 3735 #endif 3736 CLEAR_CF(); 3737 regs.u.r8.ah = 0; 3738 regs.u.r16.bx = BIOS_CONFIG_TABLE; 3739 ES = 0xF000; 3740 break; 3741 3742 case 0xc1: 3743 ES = ebda_seg; 3744 CLEAR_CF(); 3745 break; 3746 3747 case 0xd8: 3748 bios_printf(BIOS_PRINTF_DEBUG, "EISA BIOS not present\n"); 3749 SET_CF(); 3750 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3751 break; 3752 3753 default: 3754 BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n", 3755 (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx); 3756 SET_CF(); 3757 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3758 break; 3759 } 3760 } 3761 3762 #if BX_USE_PS2_MOUSE 3763 void 3764 int15_function_mouse(regs, ES, DS, FLAGS) 3765 pusha_regs_t regs; // REGS pushed via pusha 3766 Bit16u ES, DS, FLAGS; 3767 { 3768 Bit16u ebda_seg=read_word(0x0040,0x000E); 3769 Bit8u mouse_flags_1, mouse_flags_2; 3770 Bit16u mouse_driver_seg; 3771 Bit16u mouse_driver_offset; 3772 Bit8u comm_byte, prev_command_byte; 3773 Bit8u ret, mouse_data1, mouse_data2, mouse_data3; 3774 3775 BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax); 3776 3777 switch (regs.u.r8.ah) { 3778 case 0xC2: 3779 // Return Codes status in AH 3780 // ========================= 3781 // 00: success 3782 // 01: invalid subfunction (AL > 7) 3783 // 02: invalid input value (out of allowable range) 3784 // 03: interface error 3785 // 04: resend command received from mouse controller, 3786 // device driver should attempt command again 3787 // 05: cannot enable mouse, since no far call has been installed 3788 // 80/86: mouse service not implemented 3789 3790 switch (regs.u.r8.al) { 3791 case 0: // Disable/Enable Mouse 3792 BX_DEBUG_INT15("case 0:\n"); 3793 switch (regs.u.r8.bh) { 3794 case 0: // Disable Mouse 3795 BX_DEBUG_INT15("case 0: disable mouse\n"); 3796 inhibit_mouse_int_and_events(); // disable IRQ12 and packets 3797 ret = send_to_mouse_ctrl(0xF5); // disable mouse command 3798 if (ret == 0) { 3799 ret = get_mouse_data(&mouse_data1); 3800 if ( (ret == 0) || (mouse_data1 == 0xFA) ) { 3801 CLEAR_CF(); 3802 regs.u.r8.ah = 0; 3803 return; 3804 } 3805 } 3806 3807 // error 3808 SET_CF(); 3809 regs.u.r8.ah = ret; 3810 return; 3811 break; 3812 3813 case 1: // Enable Mouse 3814 BX_DEBUG_INT15("case 1: enable mouse\n"); 3815 mouse_flags_2 = read_byte(ebda_seg, 0x0027); 3816 if ( (mouse_flags_2 & 0x80) == 0 ) { 3817 BX_DEBUG_INT15("INT 15h C2 Enable Mouse, no far call handler\n"); 3818 SET_CF(); // error 3819 regs.u.r8.ah = 5; // no far call installed 3820 return; 3821 } 3822 inhibit_mouse_int_and_events(); // disable IRQ12 and packets 3823 ret = send_to_mouse_ctrl(0xF4); // enable mouse command 3824 if (ret == 0) { 3825 ret = get_mouse_data(&mouse_data1); 3826 if ( (ret == 0) && (mouse_data1 == 0xFA) ) { 3827 enable_mouse_int_and_events(); // turn IRQ12 and packet generation on 3828 CLEAR_CF(); 3829 regs.u.r8.ah = 0; 3830 return; 3831 } 3832 } 3833 SET_CF(); 3834 regs.u.r8.ah = ret; 3835 return; 3836 3837 default: // invalid subfunction 3838 BX_DEBUG_INT15("INT 15h C2 AL=0, BH=%02x\n", (unsigned) regs.u.r8.bh); 3839 SET_CF(); // error 3840 regs.u.r8.ah = 1; // invalid subfunction 3841 return; 3842 } 3843 break; 3844 3845 case 1: // Reset Mouse 3846 case 5: // Initialize Mouse 3847 BX_DEBUG_INT15("case 1 or 5:\n"); 3848 if (regs.u.r8.al == 5) { 3849 if (regs.u.r8.bh != 3) { 3850 SET_CF(); 3851 regs.u.r8.ah = 0x02; // invalid input 3852 return; 3853 } 3854 mouse_flags_2 = read_byte(ebda_seg, 0x0027); 3855 mouse_flags_2 = (mouse_flags_2 & 0x00) | regs.u.r8.bh; 3856 mouse_flags_1 = 0x00; 3857 write_byte(ebda_seg, 0x0026, mouse_flags_1); 3858 write_byte(ebda_seg, 0x0027, mouse_flags_2); 3859 } 3860 3861 inhibit_mouse_int_and_events(); // disable IRQ12 and packets 3862 ret = send_to_mouse_ctrl(0xFF); // reset mouse command 3863 if (ret == 0) { 3864 ret = get_mouse_data(&mouse_data3); 3865 // if no mouse attached, it will return RESEND 3866 if (mouse_data3 == 0xfe) { 3867 SET_CF(); 3868 return; 3869 } 3870 if (mouse_data3 != 0xfa) 3871 BX_PANIC("Mouse reset returned %02x (should be ack)\n", (unsigned)mouse_data3); 3872 if ( ret == 0 ) { 3873 ret = get_mouse_data(&mouse_data1); 3874 if ( ret == 0 ) { 3875 ret = get_mouse_data(&mouse_data2); 3876 if ( ret == 0 ) { 3877 // turn IRQ12 and packet generation on 3878 enable_mouse_int_and_events(); 3879 CLEAR_CF(); 3880 regs.u.r8.ah = 0; 3881 regs.u.r8.bl = mouse_data1; 3882 regs.u.r8.bh = mouse_data2; 3883 return; 3884 } 3885 } 3886 } 3887 } 3888 3889 // error 3890 SET_CF(); 3891 regs.u.r8.ah = ret; 3892 return; 3893 3894 case 2: // Set Sample Rate 3895 BX_DEBUG_INT15("case 2:\n"); 3896 switch (regs.u.r8.bh) { 3897 case 0: mouse_data1 = 10; break; // 10 reports/sec 3898 case 1: mouse_data1 = 20; break; // 20 reports/sec 3899 case 2: mouse_data1 = 40; break; // 40 reports/sec 3900 case 3: mouse_data1 = 60; break; // 60 reports/sec 3901 case 4: mouse_data1 = 80; break; // 80 reports/sec 3902 case 5: mouse_data1 = 100; break; // 100 reports/sec (default) 3903 case 6: mouse_data1 = 200; break; // 200 reports/sec 3904 default: mouse_data1 = 0; 3905 } 3906 if (mouse_data1 > 0) { 3907 ret = send_to_mouse_ctrl(0xF3); // set sample rate command 3908 if (ret == 0) { 3909 ret = get_mouse_data(&mouse_data2); 3910 ret = send_to_mouse_ctrl(mouse_data1); 3911 ret = get_mouse_data(&mouse_data2); 3912 CLEAR_CF(); 3913 regs.u.r8.ah = 0; 3914 } else { 3915 // error 3916 SET_CF(); 3917 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3918 } 3919 } else { 3920 // error 3921 SET_CF(); 3922 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3923 } 3924 break; 3925 3926 case 3: // Set Resolution 3927 BX_DEBUG_INT15("case 3:\n"); 3928 // BH: 3929 // 0 = 25 dpi, 1 count per millimeter 3930 // 1 = 50 dpi, 2 counts per millimeter 3931 // 2 = 100 dpi, 4 counts per millimeter 3932 // 3 = 200 dpi, 8 counts per millimeter 3933 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets 3934 if (regs.u.r8.bh < 4) { 3935 ret = send_to_mouse_ctrl(0xE8); // set resolution command 3936 if (ret == 0) { 3937 ret = get_mouse_data(&mouse_data1); 3938 if (mouse_data1 != 0xfa) 3939 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1); 3940 ret = send_to_mouse_ctrl(regs.u.r8.bh); 3941 ret = get_mouse_data(&mouse_data1); 3942 if (mouse_data1 != 0xfa) 3943 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1); 3944 CLEAR_CF(); 3945 regs.u.r8.ah = 0; 3946 } else { 3947 // error 3948 SET_CF(); 3949 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3950 } 3951 } else { 3952 // error 3953 SET_CF(); 3954 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3955 } 3956 set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable 3957 break; 3958 3959 case 4: // Get Device ID 3960 BX_DEBUG_INT15("case 4:\n"); 3961 inhibit_mouse_int_and_events(); // disable IRQ12 and packets 3962 ret = send_to_mouse_ctrl(0xF2); // get mouse ID command 3963 if (ret == 0) { 3964 ret = get_mouse_data(&mouse_data1); 3965 ret = get_mouse_data(&mouse_data2); 3966 CLEAR_CF(); 3967 regs.u.r8.ah = 0; 3968 regs.u.r8.bh = mouse_data2; 3969 } else { 3970 // error 3971 SET_CF(); 3972 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3973 } 3974 break; 3975 3976 case 6: // Return Status & Set Scaling Factor... 3977 BX_DEBUG_INT15("case 6:\n"); 3978 switch (regs.u.r8.bh) { 3979 case 0: // Return Status 3980 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets 3981 ret = send_to_mouse_ctrl(0xE9); // get mouse info command 3982 if (ret == 0) { 3983 ret = get_mouse_data(&mouse_data1); 3984 if (mouse_data1 != 0xfa) 3985 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1); 3986 if (ret == 0) { 3987 ret = get_mouse_data(&mouse_data1); 3988 if ( ret == 0 ) { 3989 ret = get_mouse_data(&mouse_data2); 3990 if ( ret == 0 ) { 3991 ret = get_mouse_data(&mouse_data3); 3992 if ( ret == 0 ) { 3993 CLEAR_CF(); 3994 regs.u.r8.ah = 0; 3995 regs.u.r8.bl = mouse_data1; 3996 regs.u.r8.cl = mouse_data2; 3997 regs.u.r8.dl = mouse_data3; 3998 set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable 3999 return; 4000 } 4001 } 4002 } 4003 } 4004 } 4005 4006 // error 4007 SET_CF(); 4008 regs.u.r8.ah = ret; 4009 set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable 4010 return; 4011 4012 case 1: // Set Scaling Factor to 1:1 4013 case 2: // Set Scaling Factor to 2:1 4014 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets 4015 if (regs.u.r8.bh == 1) { 4016 ret = send_to_mouse_ctrl(0xE6); 4017 } else { 4018 ret = send_to_mouse_ctrl(0xE7); 4019 } 4020 if (ret == 0) { 4021 get_mouse_data(&mouse_data1); 4022 ret = (mouse_data1 != 0xFA); 4023 } 4024 if (ret == 0) { 4025 CLEAR_CF(); 4026 regs.u.r8.ah = 0; 4027 } else { 4028 // error 4029 SET_CF(); 4030 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4031 } 4032 set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable 4033 break; 4034 4035 default: 4036 BX_PANIC("INT 15h C2 AL=6, BH=%02x\n", (unsigned) regs.u.r8.bh); 4037 } 4038 break; 4039 4040 case 7: // Set Mouse Handler Address 4041 BX_DEBUG_INT15("case 7:\n"); 4042 mouse_driver_seg = ES; 4043 mouse_driver_offset = regs.u.r16.bx; 4044 write_word(ebda_seg, 0x0022, mouse_driver_offset); 4045 write_word(ebda_seg, 0x0024, mouse_driver_seg); 4046 mouse_flags_2 = read_byte(ebda_seg, 0x0027); 4047 if (mouse_driver_offset == 0 && mouse_driver_seg == 0) { 4048 /* remove handler */ 4049 if ( (mouse_flags_2 & 0x80) != 0 ) { 4050 mouse_flags_2 &= ~0x80; 4051 inhibit_mouse_int_and_events(); // disable IRQ12 and packets 4052 } 4053 } 4054 else { 4055 /* install handler */ 4056 mouse_flags_2 |= 0x80; 4057 } 4058 write_byte(ebda_seg, 0x0027, mouse_flags_2); 4059 CLEAR_CF(); 4060 regs.u.r8.ah = 0; 4061 break; 4062 4063 default: 4064 BX_DEBUG_INT15("case default:\n"); 4065 regs.u.r8.ah = 1; // invalid function 4066 SET_CF(); 4067 } 4068 break; 4069 4070 default: 4071 BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n", 4072 (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx); 4073 SET_CF(); 4074 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4075 break; 4076 } 4077 } 4078 #endif 4079 4080 4081 void set_e820_range(ES, DI, start, end, type) 4082 Bit16u ES; 4083 Bit16u DI; 4084 Bit32u start; 4085 Bit32u end; 4086 Bit16u type; 4087 { 4088 write_word(ES, DI, start); 4089 write_word(ES, DI+2, start >> 16); 4090 write_word(ES, DI+4, 0x00); 4091 write_word(ES, DI+6, 0x00); 4092 4093 end -= start; 4094 write_word(ES, DI+8, end); 4095 write_word(ES, DI+10, end >> 16); 4096 write_word(ES, DI+12, 0x0000); 4097 write_word(ES, DI+14, 0x0000); 4098 4099 write_word(ES, DI+16, type); 4100 write_word(ES, DI+18, 0x0); 4101 } 4102 4103 void 4104 int15_function32(regs, ES, DS, FLAGS) 4105 pushad_regs_t regs; // REGS pushed via pushad 4106 Bit16u ES, DS, FLAGS; 4107 { 4108 Bit32u extended_memory_size=0; // 64bits long 4109 Bit16u CX,DX; 4110 4111 BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax); 4112 4113 switch (regs.u.r8.ah) { 4114 case 0x86: 4115 // Wait for CX:DX microseconds. currently using the 4116 // refresh request port 0x61 bit4, toggling every 15usec 4117 4118 CX = regs.u.r16.cx; 4119 DX = regs.u.r16.dx; 4120 4121 ASM_START 4122 sti 4123 4124 ;; Get the count in eax 4125 mov bx, sp 4126 SEG SS 4127 mov ax, _int15_function32.CX [bx] 4128 shl eax, #16 4129 SEG SS 4130 mov ax, _int15_function32.DX [bx] 4131 4132 ;; convert to numbers of 15usec ticks 4133 mov ebx, #15 4134 xor edx, edx 4135 div eax, ebx 4136 mov ecx, eax 4137 4138 ;; wait for ecx number of refresh requests 4139 in al, #0x61 4140 and al,#0x10 4141 mov ah, al 4142 4143 or ecx, ecx 4144 je int1586_tick_end 4145 int1586_tick: 4146 in al, #0x61 4147 and al,#0x10 4148 cmp al, ah 4149 je int1586_tick 4150 mov ah, al 4151 dec ecx 4152 jnz int1586_tick 4153 int1586_tick_end: 4154 ASM_END 4155 4156 break; 4157 4158 case 0xe8: 4159 switch(regs.u.r8.al) 4160 { 4161 case 0x20: // coded by osmaker aka K.J. 4162 if(regs.u.r32.edx == 0x534D4150) 4163 { 4164 extended_memory_size = inb_cmos(0x35); 4165 extended_memory_size <<= 8; 4166 extended_memory_size |= inb_cmos(0x34); 4167 extended_memory_size *= 64; 4168 // greater than EFF00000??? 4169 if(extended_memory_size > 0x3bc000) { 4170 extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000 4171 } 4172 extended_memory_size *= 1024; 4173 extended_memory_size += (16L * 1024 * 1024); 4174 4175 if(extended_memory_size <= (16L * 1024 * 1024)) { 4176 extended_memory_size = inb_cmos(0x31); 4177 extended_memory_size <<= 8; 4178 extended_memory_size |= inb_cmos(0x30); 4179 extended_memory_size *= 1024; 4180 } 4181 4182 switch(regs.u.r16.bx) 4183 { 4184 case 0: 4185 set_e820_range(ES, regs.u.r16.di, 4186 0x0000000L, 0x0009fc00L, 1); 4187 regs.u.r32.ebx = 1; 4188 regs.u.r32.eax = 0x534D4150; 4189 regs.u.r32.ecx = 0x14; 4190 CLEAR_CF(); 4191 return; 4192 break; 4193 case 1: 4194 set_e820_range(ES, regs.u.r16.di, 4195 0x0009fc00L, 0x000a0000L, 2); 4196 regs.u.r32.ebx = 2; 4197 regs.u.r32.eax = 0x534D4150; 4198 regs.u.r32.ecx = 0x14; 4199 CLEAR_CF(); 4200 return; 4201 break; 4202 case 2: 4203 set_e820_range(ES, regs.u.r16.di, 4204 0x000e8000L, 0x00100000L, 2); 4205 regs.u.r32.ebx = 3; 4206 regs.u.r32.eax = 0x534D4150; 4207 regs.u.r32.ecx = 0x14; 4208 CLEAR_CF(); 4209 return; 4210 break; 4211 case 3: 4212 set_e820_range(ES, regs.u.r16.di, 4213 0x00100000L, 4214 extended_memory_size - ACPI_DATA_SIZE, 1); 4215 regs.u.r32.ebx = 4; 4216 regs.u.r32.eax = 0x534D4150; 4217 regs.u.r32.ecx = 0x14; 4218 CLEAR_CF(); 4219 return; 4220 break; 4221 case 4: 4222 set_e820_range(ES, regs.u.r16.di, 4223 extended_memory_size - ACPI_DATA_SIZE, 4224 extended_memory_size, 3); // ACPI RAM 4225 regs.u.r32.ebx = 5; 4226 regs.u.r32.eax = 0x534D4150; 4227 regs.u.r32.ecx = 0x14; 4228 CLEAR_CF(); 4229 return; 4230 break; 4231 case 5: 4232 /* 256KB BIOS area at the end of 4 GB */ 4233 set_e820_range(ES, regs.u.r16.di, 4234 0xfffc0000L, 0x00000000L, 2); 4235 regs.u.r32.ebx = 0; 4236 regs.u.r32.eax = 0x534D4150; 4237 regs.u.r32.ecx = 0x14; 4238 CLEAR_CF(); 4239 return; 4240 default: /* AX=E820, DX=534D4150, BX unrecognized */ 4241 goto int15_unimplemented; 4242 break; 4243 } 4244 } else { 4245 // if DX != 0x534D4150) 4246 goto int15_unimplemented; 4247 } 4248 break; 4249 4250 case 0x01: 4251 // do we have any reason to fail here ? 4252 CLEAR_CF(); 4253 4254 // my real system sets ax and bx to 0 4255 // this is confirmed by Ralph Brown list 4256 // but syslinux v1.48 is known to behave 4257 // strangely if ax is set to 0 4258 // regs.u.r16.ax = 0; 4259 // regs.u.r16.bx = 0; 4260 4261 // Get the amount of extended memory (above 1M) 4262 regs.u.r8.cl = inb_cmos(0x30); 4263 regs.u.r8.ch = inb_cmos(0x31); 4264 4265 // limit to 15M 4266 if(regs.u.r16.cx > 0x3c00) 4267 { 4268 regs.u.r16.cx = 0x3c00; 4269 } 4270 4271 // Get the amount of extended memory above 16M in 64k blocs 4272 regs.u.r8.dl = inb_cmos(0x34); 4273 regs.u.r8.dh = inb_cmos(0x35); 4274 4275 // Set configured memory equal to extended memory 4276 regs.u.r16.ax = regs.u.r16.cx; 4277 regs.u.r16.bx = regs.u.r16.dx; 4278 break; 4279 default: /* AH=0xE8?? but not implemented */ 4280 goto int15_unimplemented; 4281 } 4282 break; 4283 int15_unimplemented: 4284 // fall into the default 4285 default: 4286 BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n", 4287 (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx); 4288 SET_CF(); 4289 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4290 break; 4291 } 4292 } 4293 4294 void 4295 int16_function(DI, SI, BP, SP, BX, DX, CX, AX, FLAGS) 4296 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, FLAGS; 4297 { 4298 Bit8u scan_code, ascii_code, shift_flags, led_flags, count; 4299 Bit16u kbd_code, max; 4300 4301 BX_DEBUG_INT16("int16: AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX); 4302 4303 shift_flags = read_byte(0x0040, 0x17); 4304 led_flags = read_byte(0x0040, 0x97); 4305 if ((((shift_flags >> 4) & 0x07) ^ (led_flags & 0x07)) != 0) { 4306 ASM_START 4307 cli 4308 ASM_END 4309 outb(0x60, 0xed); 4310 while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21); 4311 if ((inb(0x60) == 0xfa)) { 4312 led_flags &= 0xf8; 4313 led_flags |= ((shift_flags >> 4) & 0x07); 4314 outb(0x60, led_flags & 0x07); 4315 while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21); 4316 inb(0x60); 4317 write_byte(0x0040, 0x97, led_flags); 4318 } 4319 ASM_START 4320 sti 4321 ASM_END 4322 } 4323 4324 switch (GET_AH()) { 4325 case 0x00: /* read keyboard input */ 4326 4327 if ( !dequeue_key(&scan_code, &ascii_code, 1) ) { 4328 BX_PANIC("KBD: int16h: out of keyboard input\n"); 4329 } 4330 if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0; 4331 else if (ascii_code == 0xE0) ascii_code = 0; 4332 AX = (scan_code << 8) | ascii_code; 4333 break; 4334 4335 case 0x01: /* check keyboard status */ 4336 if ( !dequeue_key(&scan_code, &ascii_code, 0) ) { 4337 SET_ZF(); 4338 return; 4339 } 4340 if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0; 4341 else if (ascii_code == 0xE0) ascii_code = 0; 4342 AX = (scan_code << 8) | ascii_code; 4343 CLEAR_ZF(); 4344 break; 4345 4346 case 0x02: /* get shift flag status */ 4347 shift_flags = read_byte(0x0040, 0x17); 4348 SET_AL(shift_flags); 4349 break; 4350 4351 case 0x05: /* store key-stroke into buffer */ 4352 if ( !enqueue_key(GET_CH(), GET_CL()) ) { 4353 SET_AL(1); 4354 } 4355 else { 4356 SET_AL(0); 4357 } 4358 break; 4359 4360 case 0x09: /* GET KEYBOARD FUNCTIONALITY */ 4361 // bit Bochs Description 4362 // 7 0 reserved 4363 // 6 0 INT 16/AH=20h-22h supported (122-key keyboard support) 4364 // 5 1 INT 16/AH=10h-12h supported (enhanced keyboard support) 4365 // 4 1 INT 16/AH=0Ah supported 4366 // 3 0 INT 16/AX=0306h supported 4367 // 2 0 INT 16/AX=0305h supported 4368 // 1 0 INT 16/AX=0304h supported 4369 // 0 0 INT 16/AX=0300h supported 4370 // 4371 SET_AL(0x30); 4372 break; 4373 4374 case 0x0A: /* GET KEYBOARD ID */ 4375 count = 2; 4376 kbd_code = 0x0; 4377 outb(0x60, 0xf2); 4378 /* Wait for data */ 4379 max=0xffff; 4380 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x00); 4381 if (max>0x0) { 4382 if ((inb(0x60) == 0xfa)) { 4383 do { 4384 max=0xffff; 4385 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x00); 4386 if (max>0x0) { 4387 kbd_code >>= 8; 4388 kbd_code |= (inb(0x60) << 8); 4389 } 4390 } while (--count>0); 4391 } 4392 } 4393 BX=kbd_code; 4394 break; 4395 4396 case 0x10: /* read MF-II keyboard input */ 4397 4398 if ( !dequeue_key(&scan_code, &ascii_code, 1) ) { 4399 BX_PANIC("KBD: int16h: out of keyboard input\n"); 4400 } 4401 if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0; 4402 AX = (scan_code << 8) | ascii_code; 4403 break; 4404 4405 case 0x11: /* check MF-II keyboard status */ 4406 if ( !dequeue_key(&scan_code, &ascii_code, 0) ) { 4407 SET_ZF(); 4408 return; 4409 } 4410 if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0; 4411 AX = (scan_code << 8) | ascii_code; 4412 CLEAR_ZF(); 4413 break; 4414 4415 case 0x12: /* get extended keyboard status */ 4416 shift_flags = read_byte(0x0040, 0x17); 4417 SET_AL(shift_flags); 4418 shift_flags = read_byte(0x0040, 0x18) & 0x73; 4419 shift_flags |= read_byte(0x0040, 0x96) & 0x0c; 4420 SET_AH(shift_flags); 4421 BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX); 4422 break; 4423 4424 case 0x92: /* keyboard capability check called by DOS 5.0+ keyb */ 4425 SET_AH(0x80); // function int16 ah=0x10-0x12 supported 4426 break; 4427 4428 case 0xA2: /* 122 keys capability check called by DOS 5.0+ keyb */ 4429 // don't change AH : function int16 ah=0x20-0x22 NOT supported 4430 break; 4431 4432 case 0x6F: 4433 if (GET_AL() == 0x08) 4434 SET_AH(0x02); // unsupported, aka normal keyboard 4435 4436 default: 4437 BX_INFO("KBD: unsupported int 16h function %02x\n", GET_AH()); 4438 } 4439 } 4440 4441 unsigned int 4442 dequeue_key(scan_code, ascii_code, incr) 4443 Bit8u *scan_code; 4444 Bit8u *ascii_code; 4445 unsigned int incr; 4446 { 4447 Bit16u buffer_start, buffer_end, buffer_head, buffer_tail; 4448 Bit16u ss; 4449 Bit8u acode, scode; 4450 4451 #if BX_CPU < 2 4452 buffer_start = 0x001E; 4453 buffer_end = 0x003E; 4454 #else 4455 buffer_start = read_word(0x0040, 0x0080); 4456 buffer_end = read_word(0x0040, 0x0082); 4457 #endif 4458 4459 buffer_head = read_word(0x0040, 0x001a); 4460 buffer_tail = read_word(0x0040, 0x001c); 4461 4462 if (buffer_head != buffer_tail) { 4463 ss = get_SS(); 4464 acode = read_byte(0x0040, buffer_head); 4465 scode = read_byte(0x0040, buffer_head+1); 4466 write_byte(ss, ascii_code, acode); 4467 write_byte(ss, scan_code, scode); 4468 4469 if (incr) { 4470 buffer_head += 2; 4471 if (buffer_head >= buffer_end) 4472 buffer_head = buffer_start; 4473 write_word(0x0040, 0x001a, buffer_head); 4474 } 4475 return(1); 4476 } 4477 else { 4478 return(0); 4479 } 4480 } 4481 4482 static char panic_msg_keyb_buffer_full[] = "%s: keyboard input buffer full\n"; 4483 4484 Bit8u 4485 inhibit_mouse_int_and_events() 4486 { 4487 Bit8u command_byte, prev_command_byte; 4488 4489 // Turn off IRQ generation and aux data line 4490 if ( inb(0x64) & 0x02 ) 4491 BX_PANIC(panic_msg_keyb_buffer_full,"inhibmouse"); 4492 outb(0x64, 0x20); // get command byte 4493 while ( (inb(0x64) & 0x01) != 0x01 ); 4494 prev_command_byte = inb(0x60); 4495 command_byte = prev_command_byte; 4496 //while ( (inb(0x64) & 0x02) ); 4497 if ( inb(0x64) & 0x02 ) 4498 BX_PANIC(panic_msg_keyb_buffer_full,"inhibmouse"); 4499 command_byte &= 0xfd; // turn off IRQ 12 generation 4500 command_byte |= 0x20; // disable mouse serial clock line 4501 outb(0x64, 0x60); // write command byte 4502 outb(0x60, command_byte); 4503 return(prev_command_byte); 4504 } 4505 4506 void 4507 enable_mouse_int_and_events() 4508 { 4509 Bit8u command_byte; 4510 4511 // Turn on IRQ generation and aux data line 4512 if ( inb(0x64) & 0x02 ) 4513 BX_PANIC(panic_msg_keyb_buffer_full,"enabmouse"); 4514 outb(0x64, 0x20); // get command byte 4515 while ( (inb(0x64) & 0x01) != 0x01 ); 4516 command_byte = inb(0x60); 4517 //while ( (inb(0x64) & 0x02) ); 4518 if ( inb(0x64) & 0x02 ) 4519 BX_PANIC(panic_msg_keyb_buffer_full,"enabmouse"); 4520 command_byte |= 0x02; // turn on IRQ 12 generation 4521 command_byte &= 0xdf; // enable mouse serial clock line 4522 outb(0x64, 0x60); // write command byte 4523 outb(0x60, command_byte); 4524 } 4525 4526 Bit8u 4527 send_to_mouse_ctrl(sendbyte) 4528 Bit8u sendbyte; 4529 { 4530 Bit8u response; 4531 4532 // wait for chance to write to ctrl 4533 if ( inb(0x64) & 0x02 ) 4534 BX_PANIC(panic_msg_keyb_buffer_full,"sendmouse"); 4535 outb(0x64, 0xD4); 4536 outb(0x60, sendbyte); 4537 return(0); 4538 } 4539 4540 4541 Bit8u 4542 get_mouse_data(data) 4543 Bit8u *data; 4544 { 4545 Bit8u response; 4546 Bit16u ss; 4547 4548 while ( (inb(0x64) & 0x21) != 0x21 ) { 4549 } 4550 4551 response = inb(0x60); 4552 4553 ss = get_SS(); 4554 write_byte(ss, data, response); 4555 return(0); 4556 } 4557 4558 void 4559 set_kbd_command_byte(command_byte) 4560 Bit8u command_byte; 4561 { 4562 if ( inb(0x64) & 0x02 ) 4563 BX_PANIC(panic_msg_keyb_buffer_full,"setkbdcomm"); 4564 outb(0x64, 0xD4); 4565 4566 outb(0x64, 0x60); // write command byte 4567 outb(0x60, command_byte); 4568 } 4569 4570 void 4571 int09_function(DI, SI, BP, SP, BX, DX, CX, AX) 4572 Bit16u DI, SI, BP, SP, BX, DX, CX, AX; 4573 { 4574 Bit8u scancode, asciicode, shift_flags; 4575 Bit8u mf2_flags, mf2_state; 4576 4577 // 4578 // DS has been set to F000 before call 4579 // 4580 4581 4582 scancode = GET_AL(); 4583 4584 if (scancode == 0) { 4585 BX_INFO("KBD: int09 handler: AL=0\n"); 4586 return; 4587 } 4588 4589 4590 shift_flags = read_byte(0x0040, 0x17); 4591 mf2_flags = read_byte(0x0040, 0x18); 4592 mf2_state = read_byte(0x0040, 0x96); 4593 asciicode = 0; 4594 4595 switch (scancode) { 4596 case 0x3a: /* Caps Lock press */ 4597 shift_flags ^= 0x40; 4598 write_byte(0x0040, 0x17, shift_flags); 4599 mf2_flags |= 0x40; 4600 write_byte(0x0040, 0x18, mf2_flags); 4601 break; 4602 case 0xba: /* Caps Lock release */ 4603 mf2_flags &= ~0x40; 4604 write_byte(0x0040, 0x18, mf2_flags); 4605 break; 4606 4607 case 0x2a: /* L Shift press */ 4608 shift_flags |= 0x02; 4609 write_byte(0x0040, 0x17, shift_flags); 4610 break; 4611 case 0xaa: /* L Shift release */ 4612 shift_flags &= ~0x02; 4613 write_byte(0x0040, 0x17, shift_flags); 4614 break; 4615 4616 case 0x36: /* R Shift press */ 4617 shift_flags |= 0x01; 4618 write_byte(0x0040, 0x17, shift_flags); 4619 break; 4620 case 0xb6: /* R Shift release */ 4621 shift_flags &= ~0x01; 4622 write_byte(0x0040, 0x17, shift_flags); 4623 break; 4624 4625 case 0x1d: /* Ctrl press */ 4626 if ((mf2_state & 0x01) == 0) { 4627 shift_flags |= 0x04; 4628 write_byte(0x0040, 0x17, shift_flags); 4629 if (mf2_state & 0x02) { 4630 mf2_state |= 0x04; 4631 write_byte(0x0040, 0x96, mf2_state); 4632 } else { 4633 mf2_flags |= 0x01; 4634 write_byte(0x0040, 0x18, mf2_flags); 4635 } 4636 } 4637 break; 4638 case 0x9d: /* Ctrl release */ 4639 if ((mf2_state & 0x01) == 0) { 4640 shift_flags &= ~0x04; 4641 write_byte(0x0040, 0x17, shift_flags); 4642 if (mf2_state & 0x02) { 4643 mf2_state &= ~0x04; 4644 write_byte(0x0040, 0x96, mf2_state); 4645 } else { 4646 mf2_flags &= ~0x01; 4647 write_byte(0x0040, 0x18, mf2_flags); 4648 } 4649 } 4650 break; 4651 4652 case 0x38: /* Alt press */ 4653 shift_flags |= 0x08; 4654 write_byte(0x0040, 0x17, shift_flags); 4655 if (mf2_state & 0x02) { 4656 mf2_state |= 0x08; 4657 write_byte(0x0040, 0x96, mf2_state); 4658 } else { 4659 mf2_flags |= 0x02; 4660 write_byte(0x0040, 0x18, mf2_flags); 4661 } 4662 break; 4663 case 0xb8: /* Alt release */ 4664 shift_flags &= ~0x08; 4665 write_byte(0x0040, 0x17, shift_flags); 4666 if (mf2_state & 0x02) { 4667 mf2_state &= ~0x08; 4668 write_byte(0x0040, 0x96, mf2_state); 4669 } else { 4670 mf2_flags &= ~0x02; 4671 write_byte(0x0040, 0x18, mf2_flags); 4672 } 4673 break; 4674 4675 case 0x45: /* Num Lock press */ 4676 if ((mf2_state & 0x03) == 0) { 4677 mf2_flags |= 0x20; 4678 write_byte(0x0040, 0x18, mf2_flags); 4679 shift_flags ^= 0x20; 4680 write_byte(0x0040, 0x17, shift_flags); 4681 } 4682 break; 4683 case 0xc5: /* Num Lock release */ 4684 if ((mf2_state & 0x03) == 0) { 4685 mf2_flags &= ~0x20; 4686 write_byte(0x0040, 0x18, mf2_flags); 4687 } 4688 break; 4689 4690 case 0x46: /* Scroll Lock press */ 4691 mf2_flags |= 0x10; 4692 write_byte(0x0040, 0x18, mf2_flags); 4693 shift_flags ^= 0x10; 4694 write_byte(0x0040, 0x17, shift_flags); 4695 break; 4696 4697 case 0xc6: /* Scroll Lock release */ 4698 mf2_flags &= ~0x10; 4699 write_byte(0x0040, 0x18, mf2_flags); 4700 break; 4701 4702 default: 4703 if (scancode & 0x80) { 4704 break; /* toss key releases ... */ 4705 } 4706 if (scancode > MAX_SCAN_CODE) { 4707 BX_INFO("KBD: int09h_handler(): unknown scancode read: 0x%02x!\n", scancode); 4708 return; 4709 } 4710 if (shift_flags & 0x08) { /* ALT */ 4711 asciicode = scan_to_scanascii[scancode].alt; 4712 scancode = scan_to_scanascii[scancode].alt >> 8; 4713 } else if (shift_flags & 0x04) { /* CONTROL */ 4714 asciicode = scan_to_scanascii[scancode].control; 4715 scancode = scan_to_scanascii[scancode].control >> 8; 4716 } else if (((mf2_state & 0x02) > 0) && ((scancode >= 0x47) && (scancode <= 0x53))) { 4717 /* extended keys handling */ 4718 asciicode = 0xe0; 4719 scancode = scan_to_scanascii[scancode].normal >> 8; 4720 } else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */ 4721 /* check if lock state should be ignored 4722 * because a SHIFT key are pressed */ 4723 4724 if (shift_flags & scan_to_scanascii[scancode].lock_flags) { 4725 asciicode = scan_to_scanascii[scancode].normal; 4726 scancode = scan_to_scanascii[scancode].normal >> 8; 4727 } else { 4728 asciicode = scan_to_scanascii[scancode].shift; 4729 scancode = scan_to_scanascii[scancode].shift >> 8; 4730 } 4731 } else { 4732 /* check if lock is on */ 4733 if (shift_flags & scan_to_scanascii[scancode].lock_flags) { 4734 asciicode = scan_to_scanascii[scancode].shift; 4735 scancode = scan_to_scanascii[scancode].shift >> 8; 4736 } else { 4737 asciicode = scan_to_scanascii[scancode].normal; 4738 scancode = scan_to_scanascii[scancode].normal >> 8; 4739 } 4740 } 4741 if (scancode==0 && asciicode==0) { 4742 BX_INFO("KBD: int09h_handler(): scancode & asciicode are zero?\n"); 4743 } 4744 enqueue_key(scancode, asciicode); 4745 break; 4746 } 4747 if ((scancode & 0x7f) != 0x1d) { 4748 mf2_state &= ~0x01; 4749 } 4750 mf2_state &= ~0x02; 4751 write_byte(0x0040, 0x96, mf2_state); 4752 } 4753 4754 unsigned int 4755 enqueue_key(scan_code, ascii_code) 4756 Bit8u scan_code, ascii_code; 4757 { 4758 Bit16u buffer_start, buffer_end, buffer_head, buffer_tail, temp_tail; 4759 4760 #if BX_CPU < 2 4761 buffer_start = 0x001E; 4762 buffer_end = 0x003E; 4763 #else 4764 buffer_start = read_word(0x0040, 0x0080); 4765 buffer_end = read_word(0x0040, 0x0082); 4766 #endif 4767 4768 buffer_head = read_word(0x0040, 0x001A); 4769 buffer_tail = read_word(0x0040, 0x001C); 4770 4771 temp_tail = buffer_tail; 4772 buffer_tail += 2; 4773 if (buffer_tail >= buffer_end) 4774 buffer_tail = buffer_start; 4775 4776 if (buffer_tail == buffer_head) { 4777 return(0); 4778 } 4779 4780 write_byte(0x0040, temp_tail, ascii_code); 4781 write_byte(0x0040, temp_tail+1, scan_code); 4782 write_word(0x0040, 0x001C, buffer_tail); 4783 return(1); 4784 } 4785 4786 4787 void 4788 int74_function(make_farcall, Z, Y, X, status) 4789 Bit16u make_farcall, Z, Y, X, status; 4790 { 4791 Bit16u ebda_seg=read_word(0x0040,0x000E); 4792 Bit8u in_byte, index, package_count; 4793 Bit8u mouse_flags_1, mouse_flags_2; 4794 4795 BX_DEBUG_INT74("entering int74_function\n"); 4796 make_farcall = 0; 4797 4798 in_byte = inb(0x64); 4799 if ( (in_byte & 0x21) != 0x21 ) { 4800 return; 4801 } 4802 in_byte = inb(0x60); 4803 BX_DEBUG_INT74("int74: read byte %02x\n", in_byte); 4804 4805 mouse_flags_1 = read_byte(ebda_seg, 0x0026); 4806 mouse_flags_2 = read_byte(ebda_seg, 0x0027); 4807 4808 if ( (mouse_flags_2 & 0x80) != 0x80 ) { 4809 return; 4810 } 4811 4812 package_count = mouse_flags_2 & 0x07; 4813 index = mouse_flags_1 & 0x07; 4814 write_byte(ebda_seg, 0x28 + index, in_byte); 4815 4816 if ( (index+1) >= package_count ) { 4817 BX_DEBUG_INT74("int74_function: make_farcall=1\n"); 4818 status = read_byte(ebda_seg, 0x0028 + 0); 4819 X = read_byte(ebda_seg, 0x0028 + 1); 4820 Y = read_byte(ebda_seg, 0x0028 + 2); 4821 Z = 0; 4822 mouse_flags_1 = 0; 4823 // check if far call handler installed 4824 if (mouse_flags_2 & 0x80) 4825 make_farcall = 1; 4826 } 4827 else { 4828 mouse_flags_1++; 4829 } 4830 write_byte(ebda_seg, 0x0026, mouse_flags_1); 4831 } 4832 4833 #define SET_DISK_RET_STATUS(status) write_byte(0x0040, 0x0074, status) 4834 4835 #if BX_USE_ATADRV 4836 4837 void 4838 int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) 4839 Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; 4840 { 4841 Bit32u lba; 4842 Bit16u ebda_seg=read_word(0x0040,0x000E); 4843 Bit16u cylinder, head, sector; 4844 Bit16u segment, offset; 4845 Bit16u npc, nph, npspt, nlc, nlh, nlspt; 4846 Bit16u size, count; 4847 Bit8u device, status; 4848 4849 BX_DEBUG_INT13_HD("int13_harddisk: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); 4850 4851 write_byte(0x0040, 0x008e, 0); // clear completion flag 4852 4853 // basic check : device has to be defined 4854 if ( (GET_ELDL() < 0x80) || (GET_ELDL() >= 0x80 + BX_MAX_ATA_DEVICES) ) { 4855 BX_INFO("int13_harddisk: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL()); 4856 goto int13_fail; 4857 } 4858 4859 // Get the ata channel 4860 device=read_byte(ebda_seg,&EbdaData->ata.hdidmap[GET_ELDL()-0x80]); 4861 4862 // basic check : device has to be valid 4863 if (device >= BX_MAX_ATA_DEVICES) { 4864 BX_INFO("int13_harddisk: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL()); 4865 goto int13_fail; 4866 } 4867 4868 switch (GET_AH()) { 4869 4870 case 0x00: /* disk controller reset */ 4871 ata_reset (device); 4872 goto int13_success; 4873 break; 4874 4875 case 0x01: /* read disk status */ 4876 status = read_byte(0x0040, 0x0074); 4877 SET_AH(status); 4878 SET_DISK_RET_STATUS(0); 4879 /* set CF if error status read */ 4880 if (status) goto int13_fail_nostatus; 4881 else goto int13_success_noah; 4882 break; 4883 4884 case 0x02: // read disk sectors 4885 case 0x03: // write disk sectors 4886 case 0x04: // verify disk sectors 4887 4888 count = GET_AL(); 4889 cylinder = GET_CH(); 4890 cylinder |= ( ((Bit16u) GET_CL()) << 2) & 0x300; 4891 sector = (GET_CL() & 0x3f); 4892 head = GET_DH(); 4893 4894 segment = ES; 4895 offset = BX; 4896 4897 if ((count > 128) || (count == 0) || (sector == 0)) { 4898 BX_INFO("int13_harddisk: function %02x, parameter out of range!\n",GET_AH()); 4899 goto int13_fail; 4900 } 4901 4902 nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders); 4903 nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads); 4904 nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt); 4905 4906 // sanity check on cyl heads, sec 4907 if( (cylinder >= nlc) || (head >= nlh) || (sector > nlspt )) { 4908 BX_INFO("int13_harddisk: function %02x, parameters out of range %04x/%04x/%04x!\n", GET_AH(), cylinder, head, sector); 4909 goto int13_fail; 4910 } 4911 4912 // FIXME verify 4913 if ( GET_AH() == 0x04 ) goto int13_success; 4914 4915 nph = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads); 4916 npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt); 4917 4918 // if needed, translate lchs to lba, and execute command 4919 if ( (nph != nlh) || (npspt != nlspt)) { 4920 lba = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1; 4921 sector = 0; // this forces the command to be lba 4922 } 4923 4924 if ( GET_AH() == 0x02 ) 4925 status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba, segment, offset); 4926 else 4927 status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba, segment, offset); 4928 4929 // Set nb of sector transferred 4930 SET_AL(read_word(ebda_seg, &EbdaData->ata.trsfsectors)); 4931 4932 if (status != 0) { 4933 BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status); 4934 SET_AH(0x0c); 4935 goto int13_fail_noah; 4936 } 4937 4938 goto int13_success; 4939 break; 4940 4941 case 0x05: /* format disk track */ 4942 BX_INFO("format disk track called\n"); 4943 goto int13_success; 4944 return; 4945 break; 4946 4947 case 0x08: /* read disk drive parameters */ 4948 4949 // Get logical geometry from table 4950 nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders); 4951 nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads); 4952 nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt); 4953 count = read_byte(ebda_seg, &EbdaData->ata.hdcount); 4954 4955 nlc = nlc - 2; /* 0 based , last sector not used */ 4956 SET_AL(0); 4957 SET_CH(nlc & 0xff); 4958 SET_CL(((nlc >> 2) & 0xc0) | (nlspt & 0x3f)); 4959 SET_DH(nlh - 1); 4960 SET_DL(count); /* FIXME returns 0, 1, or n hard drives */ 4961 4962 // FIXME should set ES & DI 4963 4964 goto int13_success; 4965 break; 4966 4967 case 0x10: /* check drive ready */ 4968 // should look at 40:8E also??? 4969 4970 // Read the status from controller 4971 status = inb(read_word(ebda_seg, &EbdaData->ata.channels[device/2].iobase1) + ATA_CB_STAT); 4972 if ( (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY ) { 4973 goto int13_success; 4974 } 4975 else { 4976 SET_AH(0xAA); 4977 goto int13_fail_noah; 4978 } 4979 break; 4980 4981 case 0x15: /* read disk drive size */ 4982 4983 // Get physical geometry from table 4984 npc = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.cylinders); 4985 nph = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads); 4986 npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt); 4987 4988 // Compute sector count seen by int13 4989 lba = (Bit32u)(npc - 1) * (Bit32u)nph * (Bit32u)npspt; 4990 CX = lba >> 16; 4991 DX = lba & 0xffff; 4992 4993 SET_AH(3); // hard disk accessible 4994 goto int13_success_noah; 4995 break; 4996 4997 case 0x41: // IBM/MS installation check 4998 BX=0xaa55; // install check 4999 SET_AH(0x30); // EDD 3.0 5000 CX=0x0007; // ext disk access and edd, removable supported 5001 goto int13_success_noah; 5002 break; 5003 5004 case 0x42: // IBM/MS extended read 5005 case 0x43: // IBM/MS extended write 5006 case 0x44: // IBM/MS verify 5007 case 0x47: // IBM/MS extended seek 5008 5009 count=read_word(DS, SI+(Bit16u)&Int13Ext->count); 5010 segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment); 5011 offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset); 5012 5013 // Can't use 64 bits lba 5014 lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2); 5015 if (lba != 0L) { 5016 BX_PANIC("int13_harddisk: function %02x. Can't use 64bits lba\n",GET_AH()); 5017 goto int13_fail; 5018 } 5019 5020 // Get 32 bits lba and check 5021 lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1); 5022 if (lba >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors) ) { 5023 BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH()); 5024 goto int13_fail; 5025 } 5026 5027 // If verify or seek 5028 if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 )) 5029 goto int13_success; 5030 5031 // Execute the command 5032 if ( GET_AH() == 0x42 ) 5033 status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba, segment, offset); 5034 else 5035 status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba, segment, offset); 5036 5037 count=read_word(ebda_seg, &EbdaData->ata.trsfsectors); 5038 write_word(DS, SI+(Bit16u)&Int13Ext->count, count); 5039 5040 if (status != 0) { 5041 BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status); 5042 SET_AH(0x0c); 5043 goto int13_fail_noah; 5044 } 5045 5046 goto int13_success; 5047 break; 5048 5049 case 0x45: // IBM/MS lock/unlock drive 5050 case 0x49: // IBM/MS extended media change 5051 goto int13_success; // Always success for HD 5052 break; 5053 5054 case 0x46: // IBM/MS eject media 5055 SET_AH(0xb2); // Volume Not Removable 5056 goto int13_fail_noah; // Always fail for HD 5057 break; 5058 5059 case 0x48: // IBM/MS get drive parameters 5060 size=read_word(DS,SI+(Bit16u)&Int13DPT->size); 5061 5062 // Buffer is too small 5063 if(size < 0x1a) 5064 goto int13_fail; 5065 5066 // EDD 1.x 5067 if(size >= 0x1a) { 5068 Bit16u blksize; 5069 5070 npc = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.cylinders); 5071 nph = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads); 5072 npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt); 5073 lba = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors); 5074 blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize); 5075 5076 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a); 5077 write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is valid 5078 write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc); 5079 write_dword(DS, SI+(Bit16u)&Int13DPT->heads, (Bit32u)nph); 5080 write_dword(DS, SI+(Bit16u)&Int13DPT->spt, (Bit32u)npspt); 5081 write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba); // FIXME should be Bit64 5082 write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0L); 5083 write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize); 5084 } 5085 5086 // EDD 2.x 5087 if(size >= 0x1e) { 5088 Bit8u channel, dev, irq, mode, checksum, i, translation; 5089 Bit16u iobase1, iobase2, options; 5090 5091 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e); 5092 5093 write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg); 5094 write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte); 5095 5096 // Fill in dpte 5097 channel = device / 2; 5098 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 5099 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2); 5100 irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq); 5101 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode); 5102 translation = read_byte(ebda_seg, &EbdaData->ata.devices[device].translation); 5103 5104 options = (translation==ATA_TRANSLATION_NONE?0:1<<3); // chs translation 5105 options |= (1<<4); // lba translation 5106 options |= (mode==ATA_MODE_PIO32?1:0<<7); 5107 options |= (translation==ATA_TRANSLATION_LBA?1:0<<9); 5108 options |= (translation==ATA_TRANSLATION_RECHS?3:0<<9); 5109 5110 write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1); 5111 write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2); 5112 write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 ); 5113 write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb ); 5114 write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq ); 5115 write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 ); 5116 write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 ); 5117 write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 ); 5118 write_word(ebda_seg, &EbdaData->ata.dpte.options, options); 5119 write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0); 5120 write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11); 5121 5122 checksum=0; 5123 for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, (&EbdaData->ata.dpte) + i); 5124 checksum = ~checksum; 5125 write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum); 5126 } 5127 5128 // EDD 3.x 5129 if(size >= 0x42) { 5130 Bit8u channel, iface, checksum, i; 5131 Bit16u iobase1; 5132 5133 channel = device / 2; 5134 iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface); 5135 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 5136 5137 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42); 5138 write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd); 5139 write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24); 5140 write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0); 5141 write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0); 5142 5143 if (iface==ATA_IFACE_ISA) { 5144 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I'); 5145 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S'); 5146 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A'); 5147 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0); 5148 } 5149 else { 5150 // FIXME PCI 5151 } 5152 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A'); 5153 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T'); 5154 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A'); 5155 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0); 5156 5157 if (iface==ATA_IFACE_ISA) { 5158 write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1); 5159 write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0); 5160 write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L); 5161 } 5162 else { 5163 // FIXME PCI 5164 } 5165 write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2); 5166 write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0); 5167 write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0); 5168 write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L); 5169 5170 checksum=0; 5171 for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i); 5172 checksum = ~checksum; 5173 write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum); 5174 } 5175 5176 goto int13_success; 5177 break; 5178 5179 case 0x4e: // // IBM/MS set hardware configuration 5180 // DMA, prefetch, PIO maximum not supported 5181 switch (GET_AL()) { 5182 case 0x01: 5183 case 0x03: 5184 case 0x04: 5185 case 0x06: 5186 goto int13_success; 5187 break; 5188 default : 5189 goto int13_fail; 5190 } 5191 break; 5192 5193 case 0x09: /* initialize drive parameters */ 5194 case 0x0c: /* seek to specified cylinder */ 5195 case 0x0d: /* alternate disk reset */ 5196 case 0x11: /* recalibrate */ 5197 case 0x14: /* controller internal diagnostic */ 5198 BX_INFO("int13_harddisk: function %02xh unimplemented, returns success\n", GET_AH()); 5199 goto int13_success; 5200 break; 5201 5202 case 0x0a: /* read disk sectors with ECC */ 5203 case 0x0b: /* write disk sectors with ECC */ 5204 case 0x18: // set media type for format 5205 case 0x50: // IBM/MS send packet command 5206 default: 5207 BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", GET_AH()); 5208 goto int13_fail; 5209 break; 5210 } 5211 5212 int13_fail: 5213 SET_AH(0x01); // defaults to invalid function in AH or invalid parameter 5214 int13_fail_noah: 5215 SET_DISK_RET_STATUS(GET_AH()); 5216 int13_fail_nostatus: 5217 SET_CF(); // error occurred 5218 return; 5219 5220 int13_success: 5221 SET_AH(0x00); // no error 5222 int13_success_noah: 5223 SET_DISK_RET_STATUS(0x00); 5224 CLEAR_CF(); // no error 5225 return; 5226 } 5227 5228 // --------------------------------------------------------------------------- 5229 // Start of int13 for cdrom 5230 // --------------------------------------------------------------------------- 5231 5232 void 5233 int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) 5234 Bit16u EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; 5235 { 5236 Bit16u ebda_seg=read_word(0x0040,0x000E); 5237 Bit8u device, status, locks; 5238 Bit8u atacmd[12]; 5239 Bit32u lba; 5240 Bit16u count, segment, offset, i, size; 5241 5242 BX_DEBUG_INT13_CD("int13_cdrom: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); 5243 5244 SET_DISK_RET_STATUS(0x00); 5245 5246 /* basic check : device should be 0xE0+ */ 5247 if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0+BX_MAX_ATA_DEVICES) ) { 5248 BX_INFO("int13_cdrom: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL()); 5249 goto int13_fail; 5250 } 5251 5252 // Get the ata channel 5253 device=read_byte(ebda_seg,&EbdaData->ata.cdidmap[GET_ELDL()-0xE0]); 5254 5255 /* basic check : device has to be valid */ 5256 if (device >= BX_MAX_ATA_DEVICES) { 5257 BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL()); 5258 goto int13_fail; 5259 } 5260 5261 switch (GET_AH()) { 5262 5263 // all those functions return SUCCESS 5264 case 0x00: /* disk controller reset */ 5265 case 0x09: /* initialize drive parameters */ 5266 case 0x0c: /* seek to specified cylinder */ 5267 case 0x0d: /* alternate disk reset */ 5268 case 0x10: /* check drive ready */ 5269 case 0x11: /* recalibrate */ 5270 case 0x14: /* controller internal diagnostic */ 5271 case 0x16: /* detect disk change */ 5272 goto int13_success; 5273 break; 5274 5275 // all those functions return disk write-protected 5276 case 0x03: /* write disk sectors */ 5277 case 0x05: /* format disk track */ 5278 case 0x43: // IBM/MS extended write 5279 SET_AH(0x03); 5280 goto int13_fail_noah; 5281 break; 5282 5283 case 0x01: /* read disk status */ 5284 status = read_byte(0x0040, 0x0074); 5285 SET_AH(status); 5286 SET_DISK_RET_STATUS(0); 5287 5288 /* set CF if error status read */ 5289 if (status) goto int13_fail_nostatus; 5290 else goto int13_success_noah; 5291 break; 5292 5293 case 0x15: /* read disk drive size */ 5294 SET_AH(0x02); 5295 goto int13_fail_noah; 5296 break; 5297 5298 case 0x41: // IBM/MS installation check 5299 BX=0xaa55; // install check 5300 SET_AH(0x30); // EDD 2.1 5301 CX=0x0007; // ext disk access, removable and edd 5302 goto int13_success_noah; 5303 break; 5304 5305 case 0x42: // IBM/MS extended read 5306 case 0x44: // IBM/MS verify sectors 5307 case 0x47: // IBM/MS extended seek 5308 5309 count=read_word(DS, SI+(Bit16u)&Int13Ext->count); 5310 segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment); 5311 offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset); 5312 5313 // Can't use 64 bits lba 5314 lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2); 5315 if (lba != 0L) { 5316 BX_PANIC("int13_cdrom: function %02x. Can't use 64bits lba\n",GET_AH()); 5317 goto int13_fail; 5318 } 5319 5320 // Get 32 bits lba 5321 lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1); 5322 5323 // If verify or seek 5324 if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 )) 5325 goto int13_success; 5326 5327 memsetb(get_SS(),atacmd,0,12); 5328 atacmd[0]=0x28; // READ command 5329 atacmd[7]=(count & 0xff00) >> 8; // Sectors 5330 atacmd[8]=(count & 0x00ff); // Sectors 5331 atacmd[2]=(lba & 0xff000000) >> 24; // LBA 5332 atacmd[3]=(lba & 0x00ff0000) >> 16; 5333 atacmd[4]=(lba & 0x0000ff00) >> 8; 5334 atacmd[5]=(lba & 0x000000ff); 5335 status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L, ATA_DATA_IN, segment,offset); 5336 5337 count = (Bit16u)(read_dword(ebda_seg, &EbdaData->ata.trsfbytes) >> 11); 5338 write_word(DS, SI+(Bit16u)&Int13Ext->count, count); 5339 5340 if (status != 0) { 5341 BX_INFO("int13_cdrom: function %02x, status %02x !\n",GET_AH(),status); 5342 SET_AH(0x0c); 5343 goto int13_fail_noah; 5344 } 5345 5346 goto int13_success; 5347 break; 5348 5349 case 0x45: // IBM/MS lock/unlock drive 5350 if (GET_AL() > 2) goto int13_fail; 5351 5352 locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock); 5353 5354 switch (GET_AL()) { 5355 case 0 : // lock 5356 if (locks == 0xff) { 5357 SET_AH(0xb4); 5358 SET_AL(1); 5359 goto int13_fail_noah; 5360 } 5361 write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, ++locks); 5362 SET_AL(1); 5363 break; 5364 case 1 : // unlock 5365 if (locks == 0x00) { 5366 SET_AH(0xb0); 5367 SET_AL(0); 5368 goto int13_fail_noah; 5369 } 5370 write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, --locks); 5371 SET_AL(locks==0?0:1); 5372 break; 5373 case 2 : // status 5374 SET_AL(locks==0?0:1); 5375 break; 5376 } 5377 goto int13_success; 5378 break; 5379 5380 case 0x46: // IBM/MS eject media 5381 locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock); 5382 5383 if (locks != 0) { 5384 SET_AH(0xb1); // media locked 5385 goto int13_fail_noah; 5386 } 5387 // FIXME should handle 0x31 no media in device 5388 // FIXME should handle 0xb5 valid request failed 5389 5390 // Call removable media eject 5391 ASM_START 5392 push bp 5393 mov bp, sp 5394 5395 mov ah, #0x52 5396 int 15 5397 mov _int13_cdrom.status + 2[bp], ah 5398 jnc int13_cdrom_rme_end 5399 mov _int13_cdrom.status, #1 5400 int13_cdrom_rme_end: 5401 pop bp 5402 ASM_END 5403 5404 if (status != 0) { 5405 SET_AH(0xb1); // media locked 5406 goto int13_fail_noah; 5407 } 5408 5409 goto int13_success; 5410 break; 5411 5412 case 0x48: // IBM/MS get drive parameters 5413 size = read_word(DS,SI+(Bit16u)&Int13Ext->size); 5414 5415 // Buffer is too small 5416 if(size < 0x1a) 5417 goto int13_fail; 5418 5419 // EDD 1.x 5420 if(size >= 0x1a) { 5421 Bit16u cylinders, heads, spt, blksize; 5422 5423 blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize); 5424 5425 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a); 5426 write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x74); // removable, media change, lockable, max values 5427 write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0xffffffff); 5428 write_dword(DS, SI+(Bit16u)&Int13DPT->heads, 0xffffffff); 5429 write_dword(DS, SI+(Bit16u)&Int13DPT->spt, 0xffffffff); 5430 write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, 0xffffffff); // FIXME should be Bit64 5431 write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff); 5432 write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize); 5433 } 5434 5435 // EDD 2.x 5436 if(size >= 0x1e) { 5437 Bit8u channel, dev, irq, mode, checksum, i; 5438 Bit16u iobase1, iobase2, options; 5439 5440 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e); 5441 5442 write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg); 5443 write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte); 5444 5445 // Fill in dpte 5446 channel = device / 2; 5447 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 5448 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2); 5449 irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq); 5450 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode); 5451 5452 // FIXME atapi device 5453 options = (1<<4); // lba translation 5454 options |= (1<<5); // removable device 5455 options |= (1<<6); // atapi device 5456 options |= (mode==ATA_MODE_PIO32?1:0<<7); 5457 5458 write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1); 5459 write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2); 5460 write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 ); 5461 write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb ); 5462 write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq ); 5463 write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 ); 5464 write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 ); 5465 write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 ); 5466 write_word(ebda_seg, &EbdaData->ata.dpte.options, options); 5467 write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0); 5468 write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11); 5469 5470 checksum=0; 5471 for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, (&EbdaData->ata.dpte) + i); 5472 checksum = ~checksum; 5473 write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum); 5474 } 5475 5476 // EDD 3.x 5477 if(size >= 0x42) { 5478 Bit8u channel, iface, checksum, i; 5479 Bit16u iobase1; 5480 5481 channel = device / 2; 5482 iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface); 5483 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 5484 5485 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42); 5486 write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd); 5487 write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24); 5488 write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0); 5489 write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0); 5490 5491 if (iface==ATA_IFACE_ISA) { 5492 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I'); 5493 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S'); 5494 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A'); 5495 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0); 5496 } 5497 else { 5498 // FIXME PCI 5499 } 5500 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A'); 5501 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T'); 5502 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A'); 5503 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0); 5504 5505 if (iface==ATA_IFACE_ISA) { 5506 write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1); 5507 write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0); 5508 write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L); 5509 } 5510 else { 5511 // FIXME PCI 5512 } 5513 write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2); 5514 write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0); 5515 write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0); 5516 write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L); 5517 5518 checksum=0; 5519 for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i); 5520 checksum = ~checksum; 5521 write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum); 5522 } 5523 5524 goto int13_success; 5525 break; 5526 5527 case 0x49: // IBM/MS extended media change 5528 // always send changed ?? 5529 SET_AH(06); 5530 goto int13_fail_nostatus; 5531 break; 5532 5533 case 0x4e: // // IBM/MS set hardware configuration 5534 // DMA, prefetch, PIO maximum not supported 5535 switch (GET_AL()) { 5536 case 0x01: 5537 case 0x03: 5538 case 0x04: 5539 case 0x06: 5540 goto int13_success; 5541 break; 5542 default : 5543 goto int13_fail; 5544 } 5545 break; 5546 5547 // all those functions return unimplemented 5548 case 0x02: /* read sectors */ 5549 case 0x04: /* verify sectors */ 5550 case 0x08: /* read disk drive parameters */ 5551 case 0x0a: /* read disk sectors with ECC */ 5552 case 0x0b: /* write disk sectors with ECC */ 5553 case 0x18: /* set media type for format */ 5554 case 0x50: // ? - send packet command 5555 default: 5556 BX_INFO("int13_cdrom: unsupported AH=%02x\n", GET_AH()); 5557 goto int13_fail; 5558 break; 5559 } 5560 5561 int13_fail: 5562 SET_AH(0x01); // defaults to invalid function in AH or invalid parameter 5563 int13_fail_noah: 5564 SET_DISK_RET_STATUS(GET_AH()); 5565 int13_fail_nostatus: 5566 SET_CF(); // error occurred 5567 return; 5568 5569 int13_success: 5570 SET_AH(0x00); // no error 5571 int13_success_noah: 5572 SET_DISK_RET_STATUS(0x00); 5573 CLEAR_CF(); // no error 5574 return; 5575 } 5576 5577 // --------------------------------------------------------------------------- 5578 // End of int13 for cdrom 5579 // --------------------------------------------------------------------------- 5580 5581 #if BX_ELTORITO_BOOT 5582 // --------------------------------------------------------------------------- 5583 // Start of int13 for eltorito functions 5584 // --------------------------------------------------------------------------- 5585 5586 void 5587 int13_eltorito(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS) 5588 Bit16u DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS; 5589 { 5590 Bit16u ebda_seg=read_word(0x0040,0x000E); 5591 5592 BX_DEBUG_INT13_ET("int13_eltorito: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); 5593 // BX_DEBUG_INT13_ET("int13_eltorito: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), DS, ES, DI, SI); 5594 5595 switch (GET_AH()) { 5596 5597 // FIXME ElTorito Various. Should be implemented 5598 case 0x4a: // ElTorito - Initiate disk emu 5599 case 0x4c: // ElTorito - Initiate disk emu and boot 5600 case 0x4d: // ElTorito - Return Boot catalog 5601 BX_PANIC("Int13 eltorito call with AX=%04x. Please report\n",AX); 5602 goto int13_fail; 5603 break; 5604 5605 case 0x4b: // ElTorito - Terminate disk emu 5606 // FIXME ElTorito Hardcoded 5607 write_byte(DS,SI+0x00,0x13); 5608 write_byte(DS,SI+0x01,read_byte(ebda_seg,&EbdaData->cdemu.media)); 5609 write_byte(DS,SI+0x02,read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)); 5610 write_byte(DS,SI+0x03,read_byte(ebda_seg,&EbdaData->cdemu.controller_index)); 5611 write_dword(DS,SI+0x04,read_dword(ebda_seg,&EbdaData->cdemu.ilba)); 5612 write_word(DS,SI+0x08,read_word(ebda_seg,&EbdaData->cdemu.device_spec)); 5613 write_word(DS,SI+0x0a,read_word(ebda_seg,&EbdaData->cdemu.buffer_segment)); 5614 write_word(DS,SI+0x0c,read_word(ebda_seg,&EbdaData->cdemu.load_segment)); 5615 write_word(DS,SI+0x0e,read_word(ebda_seg,&EbdaData->cdemu.sector_count)); 5616 write_byte(DS,SI+0x10,read_byte(ebda_seg,&EbdaData->cdemu.vdevice.cylinders)); 5617 write_byte(DS,SI+0x11,read_byte(ebda_seg,&EbdaData->cdemu.vdevice.spt)); 5618 write_byte(DS,SI+0x12,read_byte(ebda_seg,&EbdaData->cdemu.vdevice.heads)); 5619 5620 // If we have to terminate emulation 5621 if(GET_AL() == 0x00) { 5622 // FIXME ElTorito Various. Should be handled accordingly to spec 5623 write_byte(ebda_seg,&EbdaData->cdemu.active, 0x00); // bye bye 5624 } 5625 5626 goto int13_success; 5627 break; 5628 5629 default: 5630 BX_INFO("int13_eltorito: unsupported AH=%02x\n", GET_AH()); 5631 goto int13_fail; 5632 break; 5633 } 5634 5635 int13_fail: 5636 SET_AH(0x01); // defaults to invalid function in AH or invalid parameter 5637 SET_DISK_RET_STATUS(GET_AH()); 5638 SET_CF(); // error occurred 5639 return; 5640 5641 int13_success: 5642 SET_AH(0x00); // no error 5643 SET_DISK_RET_STATUS(0x00); 5644 CLEAR_CF(); // no error 5645 return; 5646 } 5647 5648 // --------------------------------------------------------------------------- 5649 // End of int13 for eltorito functions 5650 // --------------------------------------------------------------------------- 5651 5652 // --------------------------------------------------------------------------- 5653 // Start of int13 when emulating a device from the cd 5654 // ----------------------------