1 ///////////////////////////////////////////////////////////////////////// 2 // $Id$ 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 (at) 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 (at) 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 /* 256 bytes at 0x9ff00 -- 0x9ffff is used for the IPL boot table. */ 173 #define IPL_SEG 0x9ff0 174 #define IPL_TABLE_OFFSET 0x0000 175 #define IPL_TABLE_ENTRIES 8 176 #define IPL_COUNT_OFFSET 0x0080 /* u16: number of valid table entries */ 177 #define IPL_SEQUENCE_OFFSET 0x0082 /* u16: next boot device */ 178 #define IPL_BOOTFIRST_OFFSET 0x0084 /* u16: user selected device */ 179 #define IPL_SIZE 0xff 180 #define IPL_TYPE_FLOPPY 0x01 181 #define IPL_TYPE_HARDDISK 0x02 182 #define IPL_TYPE_CDROM 0x03 183 #define IPL_TYPE_BEV 0x80 184 185 // Sanity Checks 186 #if BX_USE_ATADRV && BX_CPU<3 187 # error The ATA/ATAPI Driver can only to be used with a 386+ cpu 188 #endif 189 #if BX_USE_ATADRV && !BX_USE_EBDA 190 # error ATA/ATAPI Driver can only be used if EBDA is available 191 #endif 192 #if BX_ELTORITO_BOOT && !BX_USE_ATADRV 193 # error El-Torito Boot can only be use if ATA/ATAPI Driver is available 194 #endif 195 #if BX_PCIBIOS && BX_CPU<3 196 # error PCI BIOS can only be used with 386+ cpu 197 #endif 198 #if BX_APM && BX_CPU<3 199 # error APM BIOS can only be used with 386+ cpu 200 #endif 201 202 // define this if you want to make PCIBIOS working on a specific bridge only 203 // undef enables PCIBIOS when at least one PCI device is found 204 // i440FX is emulated by Bochs and QEMU 205 #define PCI_FIXED_HOST_BRIDGE 0x12378086 ;; i440FX PCI bridge 206 207 // #20 is dec 20 208 // #$20 is hex 20 = 32 209 // #0x20 is hex 20 = 32 210 // LDA #$20 211 // JSR $E820 212 // LDD .i,S 213 // JSR $C682 214 // mov al, #$20 215 216 // all hex literals should be prefixed with '0x' 217 // grep "#[0-9a-fA-F][0-9a-fA-F]" rombios.c 218 // no mov SEG-REG, #value, must mov register into seg-reg 219 // grep -i "mov[ ]*.s" rombios.c 220 221 // This is for compiling with gcc2 and gcc3 222 #define ASM_START #asm 223 #define ASM_END #endasm 224 225 ASM_START 226 .rom 227 228 .org 0x0000 229 230 #if BX_CPU >= 3 231 use16 386 232 #else 233 use16 286 234 #endif 235 236 MACRO HALT 237 ;; the HALT macro is called with the line number of the HALT call. 238 ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex 239 ;; to print a BX_PANIC message. This will normally halt the simulation 240 ;; with a message such as "BIOS panic at rombios.c, line 4091". 241 ;; However, users can choose to make panics non-fatal and continue. 242 #if BX_VIRTUAL_PORTS 243 mov dx,#PANIC_PORT 244 mov ax,#?1 245 out dx,ax 246 #else 247 mov dx,#0x80 248 mov ax,#?1 249 out dx,al 250 #endif 251 MEND 252 253 MACRO JMP_AP 254 db 0xea 255 dw ?2 256 dw ?1 257 MEND 258 259 MACRO SET_INT_VECTOR 260 mov ax, ?3 261 mov ?1*4, ax 262 mov ax, ?2 263 mov ?1*4+2, ax 264 MEND 265 266 ASM_END 267 268 typedef unsigned char Bit8u; 269 typedef unsigned short Bit16u; 270 typedef unsigned short bx_bool; 271 typedef unsigned long Bit32u; 272 273 274 void memsetb(seg,offset,value,count); 275 void memcpyb(dseg,doffset,sseg,soffset,count); 276 void memcpyd(dseg,doffset,sseg,soffset,count); 277 278 // memset of count bytes 279 void 280 memsetb(seg,offset,value,count) 281 Bit16u seg; 282 Bit16u offset; 283 Bit16u value; 284 Bit16u count; 285 { 286 ASM_START 287 push bp 288 mov bp, sp 289 290 push ax 291 push cx 292 push es 293 push di 294 295 mov cx, 10[bp] ; count 296 test cx, cx 297 je memsetb_end 298 mov ax, 4[bp] ; segment 299 mov es, ax 300 mov ax, 6[bp] ; offset 301 mov di, ax 302 mov al, 8[bp] ; value 303 cld 304 rep 305 stosb 306 307 memsetb_end: 308 pop di 309 pop es 310 pop cx 311 pop ax 312 313 pop bp 314 ASM_END 315 } 316 317 // memcpy of count bytes 318 void 319 memcpyb(dseg,doffset,sseg,soffset,count) 320 Bit16u dseg; 321 Bit16u doffset; 322 Bit16u sseg; 323 Bit16u soffset; 324 Bit16u count; 325 { 326 ASM_START 327 push bp 328 mov bp, sp 329 330 push ax 331 push cx 332 push es 333 push di 334 push ds 335 push si 336 337 mov cx, 12[bp] ; count 338 test cx, cx 339 je memcpyb_end 340 mov ax, 4[bp] ; dsegment 341 mov es, ax 342 mov ax, 6[bp] ; doffset 343 mov di, ax 344 mov ax, 8[bp] ; ssegment 345 mov ds, ax 346 mov ax, 10[bp] ; soffset 347 mov si, ax 348 cld 349 rep 350 movsb 351 352 memcpyb_end: 353 pop si 354 pop ds 355 pop di 356 pop es 357 pop cx 358 pop ax 359 360 pop bp 361 ASM_END 362 } 363 364 // memcpy of count dword 365 void 366 memcpyd(dseg,doffset,sseg,soffset,count) 367 Bit16u dseg; 368 Bit16u doffset; 369 Bit16u sseg; 370 Bit16u soffset; 371 Bit16u count; 372 { 373 ASM_START 374 push bp 375 mov bp, sp 376 377 push ax 378 push cx 379 push es 380 push di 381 push ds 382 push si 383 384 mov cx, 12[bp] ; count 385 test cx, cx 386 je memcpyd_end 387 mov ax, 4[bp] ; dsegment 388 mov es, ax 389 mov ax, 6[bp] ; doffset 390 mov di, ax 391 mov ax, 8[bp] ; ssegment 392 mov ds, ax 393 mov ax, 10[bp] ; soffset 394 mov si, ax 395 cld 396 rep 397 movsd 398 399 memcpyd_end: 400 pop si 401 pop ds 402 pop di 403 pop es 404 pop cx 405 pop ax 406 407 pop bp 408 ASM_END 409 } 410 411 // read_dword and write_dword functions 412 static Bit32u read_dword(); 413 static void write_dword(); 414 415 Bit32u 416 read_dword(seg, offset) 417 Bit16u seg; 418 Bit16u offset; 419 { 420 ASM_START 421 push bp 422 mov bp, sp 423 424 push bx 425 push ds 426 mov ax, 4[bp] ; segment 427 mov ds, ax 428 mov bx, 6[bp] ; offset 429 mov ax, [bx] 430 add bx, #2 431 mov dx, [bx] 432 ;; ax = return value (word) 433 ;; dx = return value (word) 434 pop ds 435 pop bx 436 437 pop bp 438 ASM_END 439 } 440 441 void 442 write_dword(seg, offset, data) 443 Bit16u seg; 444 Bit16u offset; 445 Bit32u data; 446 { 447 ASM_START 448 push bp 449 mov bp, sp 450 451 push ax 452 push bx 453 push ds 454 mov ax, 4[bp] ; segment 455 mov ds, ax 456 mov bx, 6[bp] ; offset 457 mov ax, 8[bp] ; data word 458 mov [bx], ax ; write data word 459 add bx, #2 460 mov ax, 10[bp] ; data word 461 mov [bx], ax ; write data word 462 pop ds 463 pop bx 464 pop ax 465 466 pop bp 467 ASM_END 468 } 469 470 // Bit32u (unsigned long) and long helper functions 471 ASM_START 472 473 ;; and function 474 landl: 475 landul: 476 SEG SS 477 and ax,[di] 478 SEG SS 479 and bx,2[di] 480 ret 481 482 ;; add function 483 laddl: 484 laddul: 485 SEG SS 486 add ax,[di] 487 SEG SS 488 adc bx,2[di] 489 ret 490 491 ;; cmp function 492 lcmpl: 493 lcmpul: 494 and eax, #0x0000FFFF 495 shl ebx, #16 496 or eax, ebx 497 shr ebx, #16 498 SEG SS 499 cmp eax, dword ptr [di] 500 ret 501 502 ;; sub function 503 lsubl: 504 lsubul: 505 SEG SS 506 sub ax,[di] 507 SEG SS 508 sbb bx,2[di] 509 ret 510 511 ;; mul function 512 lmull: 513 lmulul: 514 and eax, #0x0000FFFF 515 shl ebx, #16 516 or eax, ebx 517 SEG SS 518 mul eax, dword ptr [di] 519 mov ebx, eax 520 shr ebx, #16 521 ret 522 523 ;; dec function 524 ldecl: 525 ldecul: 526 SEG SS 527 dec dword ptr [bx] 528 ret 529 530 ;; or function 531 lorl: 532 lorul: 533 SEG SS 534 or ax,[di] 535 SEG SS 536 or bx,2[di] 537 ret 538 539 ;; inc function 540 lincl: 541 lincul: 542 SEG SS 543 inc dword ptr [bx] 544 ret 545 546 ;; tst function 547 ltstl: 548 ltstul: 549 and eax, #0x0000FFFF 550 shl ebx, #16 551 or eax, ebx 552 shr ebx, #16 553 test eax, eax 554 ret 555 556 ;; sr function 557 lsrul: 558 mov cx,di 559 jcxz lsr_exit 560 and eax, #0x0000FFFF 561 shl ebx, #16 562 or eax, ebx 563 lsr_loop: 564 shr eax, #1 565 loop lsr_loop 566 mov ebx, eax 567 shr ebx, #16 568 lsr_exit: 569 ret 570 571 ;; sl function 572 lsll: 573 lslul: 574 mov cx,di 575 jcxz lsl_exit 576 and eax, #0x0000FFFF 577 shl ebx, #16 578 or eax, ebx 579 lsl_loop: 580 shl eax, #1 581 loop lsl_loop 582 mov ebx, eax 583 shr ebx, #16 584 lsl_exit: 585 ret 586 587 idiv_: 588 cwd 589 idiv bx 590 ret 591 592 idiv_u: 593 xor dx,dx 594 div bx 595 ret 596 597 ldivul: 598 and eax, #0x0000FFFF 599 shl ebx, #16 600 or eax, ebx 601 xor edx, edx 602 SEG SS 603 mov bx, 2[di] 604 shl ebx, #16 605 SEG SS 606 mov bx, [di] 607 div ebx 608 mov ebx, eax 609 shr ebx, #16 610 ret 611 612 ASM_END 613 614 // for access to RAM area which is used by interrupt vectors 615 // and BIOS Data Area 616 617 typedef struct { 618 unsigned char filler1[0x400]; 619 unsigned char filler2[0x6c]; 620 Bit16u ticks_low; 621 Bit16u ticks_high; 622 Bit8u midnight_flag; 623 } bios_data_t; 624 625 #define BiosData ((bios_data_t *) 0) 626 627 #if BX_USE_ATADRV 628 typedef struct { 629 Bit16u heads; // # heads 630 Bit16u cylinders; // # cylinders 631 Bit16u spt; // # sectors / track 632 } chs_t; 633 634 // DPTE definition 635 typedef struct { 636 Bit16u iobase1; 637 Bit16u iobase2; 638 Bit8u prefix; 639 Bit8u unused; 640 Bit8u irq; 641 Bit8u blkcount; 642 Bit8u dma; 643 Bit8u pio; 644 Bit16u options; 645 Bit16u reserved; 646 Bit8u revision; 647 Bit8u checksum; 648 } dpte_t; 649 650 typedef struct { 651 Bit8u iface; // ISA or PCI 652 Bit16u iobase1; // IO Base 1 653 Bit16u iobase2; // IO Base 2 654 Bit8u irq; // IRQ 655 } ata_channel_t; 656 657 typedef struct { 658 Bit8u type; // Detected type of ata (ata/atapi/none/unknown) 659 Bit8u device; // Detected type of attached devices (hd/cd/none) 660 Bit8u removable; // Removable device flag 661 Bit8u lock; // Locks for removable devices 662 Bit8u mode; // transfer mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA 663 Bit16u blksize; // block size 664 665 Bit8u translation; // type of translation 666 chs_t lchs; // Logical CHS 667 chs_t pchs; // Physical CHS 668 669 Bit32u sectors_low; // Total sectors count 670 Bit32u sectors_high; 671 } ata_device_t; 672 673 typedef struct { 674 // ATA channels info 675 ata_channel_t channels[BX_MAX_ATA_INTERFACES]; 676 677 // ATA devices info 678 ata_device_t devices[BX_MAX_ATA_DEVICES]; 679 // 680 // map between (bios hd id - 0x80) and ata channels 681 Bit8u hdcount, hdidmap[BX_MAX_ATA_DEVICES]; 682 683 // map between (bios cd id - 0xE0) and ata channels 684 Bit8u cdcount, cdidmap[BX_MAX_ATA_DEVICES]; 685 686 // Buffer for DPTE table 687 dpte_t dpte; 688 689 // Count of transferred sectors and bytes 690 Bit16u trsfsectors; 691 Bit32u trsfbytes; 692 693 } ata_t; 694 695 #if BX_ELTORITO_BOOT 696 // ElTorito Device Emulation data 697 typedef struct { 698 Bit8u active; 699 Bit8u media; 700 Bit8u emulated_drive; 701 Bit8u controller_index; 702 Bit16u device_spec; 703 Bit32u ilba; 704 Bit16u buffer_segment; 705 Bit16u load_segment; 706 Bit16u sector_count; 707 708 // Virtual device 709 chs_t vdevice; 710 } cdemu_t; 711 #endif // BX_ELTORITO_BOOT 712 713 // for access to EBDA area 714 // The EBDA structure should conform to 715 // http://www.frontiernet.net/~fys/rombios.htm document 716 // I made the ata and cdemu structs begin at 0x121 in the EBDA seg 717 // EBDA must be at most 768 bytes; it lives at EBDA_SEG, and the boot 718 // device tables are at IPL_SEG 719 typedef struct { 720 unsigned char filler1[0x3D]; 721 722 // FDPT - Can be splitted in data members if needed 723 unsigned char fdpt0[0x10]; 724 unsigned char fdpt1[0x10]; 725 726 unsigned char filler2[0xC4]; 727 728 // ATA Driver data 729 ata_t ata; 730 731 #if BX_ELTORITO_BOOT 732 // El Torito Emulation data 733 cdemu_t cdemu; 734 #endif // BX_ELTORITO_BOOT 735 736 } ebda_data_t; 737 738 #define EbdaData ((ebda_data_t *) 0) 739 740 // for access to the int13ext structure 741 typedef struct { 742 Bit8u size; 743 Bit8u reserved; 744 Bit16u count; 745 Bit16u offset; 746 Bit16u segment; 747 Bit32u lba1; 748 Bit32u lba2; 749 } int13ext_t; 750 751 #define Int13Ext ((int13ext_t *) 0) 752 753 // Disk Physical Table definition 754 typedef struct { 755 Bit16u size; 756 Bit16u infos; 757 Bit32u cylinders; 758 Bit32u heads; 759 Bit32u spt; 760 Bit32u sector_count1; 761 Bit32u sector_count2; 762 Bit16u blksize; 763 Bit16u dpte_offset; 764 Bit16u dpte_segment; 765 Bit16u key; 766 Bit8u dpi_length; 767 Bit8u reserved1; 768 Bit16u reserved2; 769 Bit8u host_bus[4]; 770 Bit8u iface_type[8]; 771 Bit8u iface_path[8]; 772 Bit8u device_path[8]; 773 Bit8u reserved3; 774 Bit8u checksum; 775 } dpt_t; 776 777 #define Int13DPT ((dpt_t *) 0) 778 779 #endif // BX_USE_ATADRV 780 781 typedef struct { 782 union { 783 struct { 784 Bit16u di, si, bp, sp; 785 Bit16u bx, dx, cx, ax; 786 } r16; 787 struct { 788 Bit16u filler[4]; 789 Bit8u bl, bh, dl, dh, cl, ch, al, ah; 790 } r8; 791 } u; 792 } pusha_regs_t; 793 794 typedef struct { 795 union { 796 struct { 797 Bit32u edi, esi, ebp, esp; 798 Bit32u ebx, edx, ecx, eax; 799 } r32; 800 struct { 801 Bit16u di, filler1, si, filler2, bp, filler3, sp, filler4; 802 Bit16u bx, filler5, dx, filler6, cx, filler7, ax, filler8; 803 } r16; 804 struct { 805 Bit32u filler[4]; 806 Bit8u bl, bh; 807 Bit16u filler1; 808 Bit8u dl, dh; 809 Bit16u filler2; 810 Bit8u cl, ch; 811 Bit16u filler3; 812 Bit8u al, ah; 813 Bit16u filler4; 814 } r8; 815 } u; 816 } pushad_regs_t; 817 818 typedef struct { 819 union { 820 struct { 821 Bit16u flags; 822 } r16; 823 struct { 824 Bit8u flagsl; 825 Bit8u flagsh; 826 } r8; 827 } u; 828 } flags_t; 829 830 #define SetCF(x) x.u.r8.flagsl |= 0x01 831 #define SetZF(x) x.u.r8.flagsl |= 0x40 832 #define ClearCF(x) x.u.r8.flagsl &= 0xfe 833 #define ClearZF(x) x.u.r8.flagsl &= 0xbf 834 #define GetCF(x) (x.u.r8.flagsl & 0x01) 835 836 typedef struct { 837 Bit16u ip; 838 Bit16u cs; 839 flags_t flags; 840 } iret_addr_t; 841 842 typedef struct { 843 Bit16u type; 844 Bit16u flags; 845 Bit32u vector; 846 Bit32u description; 847 Bit32u reserved; 848 } ipl_entry_t; 849 850 851 852 static Bit8u inb(); 853 static Bit8u inb_cmos(); 854 static void outb(); 855 static void outb_cmos(); 856 static Bit16u inw(); 857 static void outw(); 858 static void init_rtc(); 859 static bx_bool rtc_updating(); 860 861 static Bit8u read_byte(); 862 static Bit16u read_word(); 863 static void write_byte(); 864 static void write_word(); 865 static void bios_printf(); 866 867 static Bit8u inhibit_mouse_int_and_events(); 868 static void enable_mouse_int_and_events(); 869 static Bit8u send_to_mouse_ctrl(); 870 static Bit8u get_mouse_data(); 871 static void set_kbd_command_byte(); 872 873 static void int09_function(); 874 static void int13_harddisk(); 875 static void int13_cdrom(); 876 static void int13_cdemu(); 877 static void int13_eltorito(); 878 static void int13_diskette_function(); 879 static void int14_function(); 880 static void int15_function(); 881 static void int16_function(); 882 static void int17_function(); 883 static void int19_function(); 884 static void int1a_function(); 885 static void int70_function(); 886 static void int74_function(); 887 static Bit16u get_CS(); 888 static Bit16u get_SS(); 889 static unsigned int enqueue_key(); 890 static unsigned int dequeue_key(); 891 static void get_hd_geometry(); 892 static void set_diskette_ret_status(); 893 static void set_diskette_current_cyl(); 894 static void determine_floppy_media(); 895 static bx_bool floppy_drive_exists(); 896 static bx_bool floppy_drive_recal(); 897 static bx_bool floppy_media_known(); 898 static bx_bool floppy_media_sense(); 899 static bx_bool set_enable_a20(); 900 static void debugger_on(); 901 static void debugger_off(); 902 static void keyboard_init(); 903 static void keyboard_panic(); 904 static void shutdown_status_panic(); 905 static void nmi_handler_msg(); 906 static void delay_ticks(); 907 static void delay_ticks_and_check_for_keystroke(); 908 909 static void interactive_bootkey(); 910 static void print_bios_banner(); 911 static void print_boot_device(); 912 static void print_boot_failure(); 913 static void print_cdromboot_failure(); 914 915 # if BX_USE_ATADRV 916 917 // ATA / ATAPI driver 918 void ata_init(); 919 void ata_detect(); 920 void ata_reset(); 921 922 Bit16u ata_cmd_non_data(); 923 Bit16u ata_cmd_data_in(); 924 Bit16u ata_cmd_data_out(); 925 Bit16u ata_cmd_packet(); 926 927 Bit16u atapi_get_sense(); 928 Bit16u atapi_is_ready(); 929 Bit16u atapi_is_cdrom(); 930 931 #endif // BX_USE_ATADRV 932 933 #if BX_ELTORITO_BOOT 934 935 void cdemu_init(); 936 Bit8u cdemu_isactive(); 937 Bit8u cdemu_emulated_drive(); 938 939 Bit16u cdrom_boot(); 940 941 #endif // BX_ELTORITO_BOOT 942 943 static char bios_cvs_version_string[] = "$Revision$ $Date$"; 944 945 #define BIOS_COPYRIGHT_STRING "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team." 946 947 #if DEBUG_ATA 948 # define BX_DEBUG_ATA(a...) BX_DEBUG(a) 949 #else 950 # define BX_DEBUG_ATA(a...) 951 #endif 952 #if DEBUG_INT13_HD 953 # define BX_DEBUG_INT13_HD(a...) BX_DEBUG(a) 954 #else 955 # define BX_DEBUG_INT13_HD(a...) 956 #endif 957 #if DEBUG_INT13_CD 958 # define BX_DEBUG_INT13_CD(a...) BX_DEBUG(a) 959 #else 960 # define BX_DEBUG_INT13_CD(a...) 961 #endif 962 #if DEBUG_INT13_ET 963 # define BX_DEBUG_INT13_ET(a...) BX_DEBUG(a) 964 #else 965 # define BX_DEBUG_INT13_ET(a...) 966 #endif 967 #if DEBUG_INT13_FL 968 # define BX_DEBUG_INT13_FL(a...) BX_DEBUG(a) 969 #else 970 # define BX_DEBUG_INT13_FL(a...) 971 #endif 972 #if DEBUG_INT15 973 # define BX_DEBUG_INT15(a...) BX_DEBUG(a) 974 #else 975 # define BX_DEBUG_INT15(a...) 976 #endif 977 #if DEBUG_INT16 978 # define BX_DEBUG_INT16(a...) BX_DEBUG(a) 979 #else 980 # define BX_DEBUG_INT16(a...) 981 #endif 982 #if DEBUG_INT1A 983 # define BX_DEBUG_INT1A(a...) BX_DEBUG(a) 984 #else 985 # define BX_DEBUG_INT1A(a...) 986 #endif 987 #if DEBUG_INT74 988 # define BX_DEBUG_INT74(a...) BX_DEBUG(a) 989 #else 990 # define BX_DEBUG_INT74(a...) 991 #endif 992 993 #define SET_AL(val8) AX = ((AX & 0xff00) | (val8)) 994 #define SET_BL(val8) BX = ((BX & 0xff00) | (val8)) 995 #define SET_CL(val8) CX = ((CX & 0xff00) | (val8)) 996 #define SET_DL(val8) DX = ((DX & 0xff00) | (val8)) 997 #define SET_AH(val8) AX = ((AX & 0x00ff) | ((val8) << 8)) 998 #define SET_BH(val8) BX = ((BX & 0x00ff) | ((val8) << 8)) 999 #define SET_CH(val8) CX = ((CX & 0x00ff) | ((val8) << 8)) 1000 #define SET_DH(val8) DX = ((DX & 0x00ff) | ((val8) << 8)) 1001 1002 #define GET_AL() ( AX & 0x00ff ) 1003 #define GET_BL() ( BX & 0x00ff ) 1004 #define GET_CL() ( CX & 0x00ff ) 1005 #define GET_DL() ( DX & 0x00ff ) 1006 #define GET_AH() ( AX >> 8 ) 1007 #define GET_BH() ( BX >> 8 ) 1008 #define GET_CH() ( CX >> 8 ) 1009 #define GET_DH() ( DX >> 8 ) 1010 1011 #define GET_ELDL() ( ELDX & 0x00ff ) 1012 #define GET_ELDH() ( ELDX >> 8 ) 1013 1014 #define SET_CF() FLAGS |= 0x0001 1015 #define CLEAR_CF() FLAGS &= 0xfffe 1016 #define GET_CF() (FLAGS & 0x0001) 1017 1018 #define SET_ZF() FLAGS |= 0x0040 1019 #define CLEAR_ZF() FLAGS &= 0xffbf 1020 #define GET_ZF() (FLAGS & 0x0040) 1021 1022 #define UNSUPPORTED_FUNCTION 0x86 1023 1024 #define none 0 1025 #define MAX_SCAN_CODE 0x58 1026 1027 static struct { 1028 Bit16u normal; 1029 Bit16u shift; 1030 Bit16u control; 1031 Bit16u alt; 1032 Bit8u lock_flags; 1033 } scan_to_scanascii[MAX_SCAN_CODE + 1] = { 1034 { none, none, none, none, none }, 1035 { 0x011b, 0x011b, 0x011b, 0x0100, none }, /* escape */ 1036 { 0x0231, 0x0221, none, 0x7800, none }, /* 1! */ 1037 { 0x0332, 0x0340, 0x0300, 0x7900, none }, /* 2@ */ 1038 { 0x0433, 0x0423, none, 0x7a00, none }, /* 3# */ 1039 { 0x0534, 0x0524, none, 0x7b00, none }, /* 4$ */ 1040 { 0x0635, 0x0625, none, 0x7c00, none }, /* 5% */ 1041 { 0x0736, 0x075e, 0x071e, 0x7d00, none }, /* 6^ */ 1042 { 0x0837, 0x0826, none, 0x7e00, none }, /* 7& */ 1043 { 0x0938, 0x092a, none, 0x7f00, none }, /* 8* */ 1044 { 0x0a39, 0x0a28, none, 0x8000, none }, /* 9( */ 1045 { 0x0b30, 0x0b29, none, 0x8100, none }, /* 0) */ 1046 { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200, none }, /* -_ */ 1047 { 0x0d3d, 0x0d2b, none, 0x8300, none }, /* =+ */ 1048 { 0x0e08, 0x0e08, 0x0e7f, none, none }, /* backspace */ 1049 { 0x0f09, 0x0f00, none, none, none }, /* tab */ 1050 { 0x1071, 0x1051, 0x1011, 0x1000, 0x40 }, /* Q */ 1051 { 0x1177, 0x1157, 0x1117, 0x1100, 0x40 }, /* W */ 1052 { 0x1265, 0x1245, 0x1205, 0x1200, 0x40 }, /* E */ 1053 { 0x1372, 0x1352, 0x1312, 0x1300, 0x40 }, /* R */ 1054 { 0x1474, 0x1454, 0x1414, 0x1400, 0x40 }, /* T */ 1055 { 0x1579, 0x1559, 0x1519, 0x1500, 0x40 }, /* Y */ 1056 { 0x1675, 0x1655, 0x1615, 0x1600, 0x40 }, /* U */ 1057 { 0x1769, 0x1749, 0x1709, 0x1700, 0x40 }, /* I */ 1058 { 0x186f, 0x184f, 0x180f, 0x1800, 0x40 }, /* O */ 1059 { 0x1970, 0x1950, 0x1910, 0x1900, 0x40 }, /* P */ 1060 { 0x1a5b, 0x1a7b, 0x1a1b, none, none }, /* [{ */ 1061 { 0x1b5d, 0x1b7d, 0x1b1d, none, none }, /* ]} */ 1062 { 0x1c0d, 0x1c0d, 0x1c0a, none, none }, /* Enter */ 1063 { none, none, none, none, none }, /* L Ctrl */ 1064 { 0x1e61, 0x1e41, 0x1e01, 0x1e00, 0x40 }, /* A */ 1065 { 0x1f73, 0x1f53, 0x1f13, 0x1f00, 0x40 }, /* S */ 1066 { 0x2064, 0x2044, 0x2004, 0x2000, 0x40 }, /* D */ 1067 { 0x2166, 0x2146, 0x2106, 0x2100, 0x40 }, /* F */ 1068 { 0x2267, 0x2247, 0x2207, 0x2200, 0x40 }, /* G */ 1069 { 0x2368, 0x2348, 0x2308, 0x2300, 0x40 }, /* H */ 1070 { 0x246a, 0x244a, 0x240a, 0x2400, 0x40 }, /* J */ 1071 { 0x256b, 0x254b, 0x250b, 0x2500, 0x40 }, /* K */ 1072 { 0x266c, 0x264c, 0x260c, 0x2600, 0x40 }, /* L */ 1073 { 0x273b, 0x273a, none, none, none }, /* ;: */ 1074 { 0x2827, 0x2822, none, none, none }, /* '" */ 1075 { 0x2960, 0x297e, none, none, none }, /* `~ */ 1076 { none, none, none, none, none }, /* L shift */ 1077 { 0x2b5c, 0x2b7c, 0x2b1c, none, none }, /* |\ */ 1078 { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00, 0x40 }, /* Z */ 1079 { 0x2d78, 0x2d58, 0x2d18, 0x2d00, 0x40 }, /* X */ 1080 { 0x2e63, 0x2e43, 0x2e03, 0x2e00, 0x40 }, /* C */ 1081 { 0x2f76, 0x2f56, 0x2f16, 0x2f00, 0x40 }, /* V */ 1082 { 0x3062, 0x3042, 0x3002, 0x3000, 0x40 }, /* B */ 1083 { 0x316e, 0x314e, 0x310e, 0x3100, 0x40 }, /* N */ 1084 { 0x326d, 0x324d, 0x320d, 0x3200, 0x40 }, /* M */ 1085 { 0x332c, 0x333c, none, none, none }, /* ,< */ 1086 { 0x342e, 0x343e, none, none, none }, /* .> */ 1087 { 0x352f, 0x353f, none, none, none }, /* /? */ 1088 { none, none, none, none, none }, /* R Shift */ 1089 { 0x372a, 0x372a, none, none, none }, /* * */ 1090 { none, none, none, none, none }, /* L Alt */ 1091 { 0x3920, 0x3920, 0x3920, 0x3920, none }, /* space */ 1092 { none, none, none, none, none }, /* caps lock */ 1093 { 0x3b00, 0x5400, 0x5e00, 0x6800, none }, /* F1 */ 1094 { 0x3c00, 0x5500, 0x5f00, 0x6900, none }, /* F2 */ 1095 { 0x3d00, 0x5600, 0x6000, 0x6a00, none }, /* F3 */ 1096 { 0x3e00, 0x5700, 0x6100, 0x6b00, none }, /* F4 */ 1097 { 0x3f00, 0x5800, 0x6200, 0x6c00, none }, /* F5 */ 1098 { 0x4000, 0x5900, 0x6300, 0x6d00, none }, /* F6 */ 1099 { 0x4100, 0x5a00, 0x6400, 0x6e00, none }, /* F7 */ 1100 { 0x4200, 0x5b00, 0x6500, 0x6f00, none }, /* F8 */ 1101 { 0x4300, 0x5c00, 0x6600, 0x7000, none }, /* F9 */ 1102 { 0x4400, 0x5d00, 0x6700, 0x7100, none }, /* F10 */ 1103 { none, none, none, none, none }, /* Num Lock */ 1104 { none, none, none, none, none }, /* Scroll Lock */ 1105 { 0x4700, 0x4737, 0x7700, none, 0x20 }, /* 7 Home */ 1106 { 0x4800, 0x4838, none, none, 0x20 }, /* 8 UP */ 1107 { 0x4900, 0x4939, 0x8400, none, 0x20 }, /* 9 PgUp */ 1108 { 0x4a2d, 0x4a2d, none, none, none }, /* - */ 1109 { 0x4b00, 0x4b34, 0x7300, none, 0x20 }, /* 4 Left */ 1110 { 0x4c00, 0x4c35, none, none, 0x20 }, /* 5 */ 1111 { 0x4d00, 0x4d36, 0x7400, none, 0x20 }, /* 6 Right */ 1112 { 0x4e2b, 0x4e2b, none, none, none }, /* + */ 1113 { 0x4f00, 0x4f31, 0x7500, none, 0x20 }, /* 1 End */ 1114 { 0x5000, 0x5032, none, none, 0x20 }, /* 2 Down */ 1115 { 0x5100, 0x5133, 0x7600, none, 0x20 }, /* 3 PgDn */ 1116 { 0x5200, 0x5230, none, none, 0x20 }, /* 0 Ins */ 1117 { 0x5300, 0x532e, none, none, 0x20 }, /* Del */ 1118 { none, none, none, none, none }, 1119 { none, none, none, none, none }, 1120 { 0x565c, 0x567c, none, none, none }, /* \| */ 1121 { 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */ 1122 { 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */ 1123 }; 1124 1125 Bit8u 1126 inb(port) 1127 Bit16u port; 1128 { 1129 ASM_START 1130 push bp 1131 mov bp, sp 1132 1133 push dx 1134 mov dx, 4[bp] 1135 in al, dx 1136 pop dx 1137 1138 pop bp 1139 ASM_END 1140 } 1141 1142 #if BX_USE_ATADRV 1143 Bit16u 1144 inw(port) 1145 Bit16u port; 1146 { 1147 ASM_START 1148 push bp 1149 mov bp, sp 1150 1151 push dx 1152 mov dx, 4[bp] 1153 in ax, dx 1154 pop dx 1155 1156 pop bp 1157 ASM_END 1158 } 1159 #endif 1160 1161 void 1162 outb(port, val) 1163 Bit16u port; 1164 Bit8u val; 1165 { 1166 ASM_START 1167 push bp 1168 mov bp, sp 1169 1170 push ax 1171 push dx 1172 mov dx, 4[bp] 1173 mov al, 6[bp] 1174 out dx, al 1175 pop dx 1176 pop ax 1177 1178 pop bp 1179 ASM_END 1180 } 1181 1182 #if BX_USE_ATADRV 1183 void 1184 outw(port, val) 1185 Bit16u port; 1186 Bit16u val; 1187 { 1188 ASM_START 1189 push bp 1190 mov bp, sp 1191 1192 push ax 1193 push dx 1194 mov dx, 4[bp] 1195 mov ax, 6[bp] 1196 out dx, ax 1197 pop dx 1198 pop ax 1199 1200 pop bp 1201 ASM_END 1202 } 1203 #endif 1204 1205 void 1206 outb_cmos(cmos_reg, val) 1207 Bit8u cmos_reg; 1208 Bit8u val; 1209 { 1210 ASM_START 1211 push bp 1212 mov bp, sp 1213 1214 mov al, 4[bp] ;; cmos_reg 1215 out 0x70, al 1216 mov al, 6[bp] ;; val 1217 out 0x71, al 1218 1219 pop bp 1220 ASM_END 1221 } 1222 1223 Bit8u 1224 inb_cmos(cmos_reg) 1225 Bit8u cmos_reg; 1226 { 1227 ASM_START 1228 push bp 1229 mov bp, sp 1230 1231 mov al, 4[bp] ;; cmos_reg 1232 out 0x70, al 1233 in al, 0x71 1234 1235 pop bp 1236 ASM_END 1237 } 1238 1239 void 1240 init_rtc() 1241 { 1242 outb_cmos(0x0a, 0x26); 1243 outb_cmos(0x0b, 0x02); 1244 inb_cmos(0x0c); 1245 inb_cmos(0x0d); 1246 } 1247 1248 bx_bool 1249 rtc_updating() 1250 { 1251 // This function checks to see if the update-in-progress bit 1252 // is set in CMOS Status Register A. If not, it returns 0. 1253 // If it is set, it tries to wait until there is a transition 1254 // to 0, and will return 0 if such a transition occurs. A 1 1255 // is returned only after timing out. The maximum period 1256 // that this bit should be set is constrained to 244useconds. 1257 // The count I use below guarantees coverage or more than 1258 // this time, with any reasonable IPS setting. 1259 1260 Bit16u count; 1261 1262 count = 25000; 1263 while (--count != 0) { 1264 if ( (inb_cmos(0x0a) & 0x80) == 0 ) 1265 return(0); 1266 } 1267 return(1); // update-in-progress never transitioned to 0 1268 } 1269 1270 1271 Bit8u 1272 read_byte(seg, offset) 1273 Bit16u seg; 1274 Bit16u offset; 1275 { 1276 ASM_START 1277 push bp 1278 mov bp, sp 1279 1280 push bx 1281 push ds 1282 mov ax, 4[bp] ; segment 1283 mov ds, ax 1284 mov bx, 6[bp] ; offset 1285 mov al, [bx] 1286 ;; al = return value (byte) 1287 pop ds 1288 pop bx 1289 1290 pop bp 1291 ASM_END 1292 } 1293 1294 Bit16u 1295 read_word(seg, offset) 1296 Bit16u seg; 1297 Bit16u offset; 1298 { 1299 ASM_START 1300 push bp 1301 mov bp, sp 1302 1303 push bx 1304 push ds 1305 mov ax, 4[bp] ; segment 1306 mov ds, ax 1307 mov bx, 6[bp] ; offset 1308 mov ax, [bx] 1309 ;; ax = return value (word) 1310 pop ds 1311 pop bx 1312 1313 pop bp 1314 ASM_END 1315 } 1316 1317 void 1318 write_byte(seg, offset, data) 1319 Bit16u seg; 1320 Bit16u offset; 1321 Bit8u data; 1322 { 1323 ASM_START 1324 push bp 1325 mov bp, sp 1326 1327 push ax 1328 push bx 1329 push ds 1330 mov ax, 4[bp] ; segment 1331 mov ds, ax 1332 mov bx, 6[bp] ; offset 1333 mov al, 8[bp] ; data byte 1334 mov [bx], al ; write data byte 1335 pop ds 1336 pop bx 1337 pop ax 1338 1339 pop bp 1340 ASM_END 1341 } 1342 1343 void 1344 write_word(seg, offset, data) 1345 Bit16u seg; 1346 Bit16u offset; 1347 Bit16u data; 1348 { 1349 ASM_START 1350 push bp 1351 mov bp, sp 1352 1353 push ax 1354 push bx 1355 push ds 1356 mov ax, 4[bp] ; segment 1357 mov ds, ax 1358 mov bx, 6[bp] ; offset 1359 mov ax, 8[bp] ; data word 1360 mov [bx], ax ; write data word 1361 pop ds 1362 pop bx 1363 pop ax 1364 1365 pop bp 1366 ASM_END 1367 } 1368 1369 Bit16u 1370 get_CS() 1371 { 1372 ASM_START 1373 mov ax, cs 1374 ASM_END 1375 } 1376 1377 Bit16u 1378 get_SS() 1379 { 1380 ASM_START 1381 mov ax, ss 1382 ASM_END 1383 } 1384 1385 #if BX_DEBUG_SERIAL 1386 /* serial debug port*/ 1387 #define BX_DEBUG_PORT 0x03f8 1388 1389 /* data */ 1390 #define UART_RBR 0x00 1391 #define UART_THR 0x00 1392 1393 /* control */ 1394 #define UART_IER 0x01 1395 #define UART_IIR 0x02 1396 #define UART_FCR 0x02 1397 #define UART_LCR 0x03 1398 #define UART_MCR 0x04 1399 #define UART_DLL 0x00 1400 #define UART_DLM 0x01 1401 1402 /* status */ 1403 #define UART_LSR 0x05 1404 #define UART_MSR 0x06 1405 #define UART_SCR 0x07 1406 1407 int uart_can_tx_byte(base_port) 1408 Bit16u base_port; 1409 { 1410 return inb(base_port + UART_LSR) & 0x20; 1411 } 1412 1413 void uart_wait_to_tx_byte(base_port) 1414 Bit16u base_port; 1415 { 1416 while (!uart_can_tx_byte(base_port)); 1417 } 1418 1419 void uart_wait_until_sent(base_port) 1420 Bit16u base_port; 1421 { 1422 while (!(inb(base_port + UART_LSR) & 0x40)); 1423 } 1424 1425 void uart_tx_byte(base_port, data) 1426 Bit16u base_port; 1427 Bit8u data; 1428 { 1429 uart_wait_to_tx_byte(base_port); 1430 outb(base_port + UART_THR, data); 1431 uart_wait_until_sent(base_port); 1432 } 1433 #endif 1434 1435 void 1436 wrch(c) 1437 Bit8u c; 1438 { 1439 ASM_START 1440 push bp 1441 mov bp, sp 1442 1443 push bx 1444 mov ah, #0x0e 1445 mov al, 4[bp] 1446 xor bx,bx 1447 int #0x10 1448 pop bx 1449 1450 pop bp 1451 ASM_END 1452 } 1453 1454 void 1455 send(action, c) 1456 Bit16u action; 1457 Bit8u c; 1458 { 1459 #if BX_DEBUG_SERIAL 1460 if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r'); 1461 uart_tx_byte(BX_DEBUG_PORT, c); 1462 #endif 1463 #if BX_VIRTUAL_PORTS 1464 if (action & BIOS_PRINTF_DEBUG) outb(DEBUG_PORT, c); 1465 if (action & BIOS_PRINTF_INFO) outb(INFO_PORT, c); 1466 #endif 1467 if (action & BIOS_PRINTF_SCREEN) { 1468 if (c == '\n') wrch('\r'); 1469 wrch(c); 1470 } 1471 } 1472 1473 void 1474 put_int(action, val, width, neg) 1475 Bit16u action; 1476 short val, width; 1477 bx_bool neg; 1478 { 1479 short nval = val / 10; 1480 if (nval) 1481 put_int(action, nval, width - 1, neg); 1482 else { 1483 while (--width > 0) send(action, ' '); 1484 if (neg) send(action, '-'); 1485 } 1486 send(action, val - (nval * 10) + '0'); 1487 } 1488 1489 void 1490 put_uint(action, val, width, neg) 1491 Bit16u action; 1492 unsigned short val; 1493 short width; 1494 bx_bool neg; 1495 { 1496 unsigned short nval = val / 10; 1497 if (nval) 1498 put_uint(action, nval, width - 1, neg); 1499 else { 1500 while (--width > 0) send(action, ' '); 1501 if (neg) send(action, '-'); 1502 } 1503 send(action, val - (nval * 10) + '0'); 1504 } 1505 1506 void 1507 put_luint(action, val, width, neg) 1508 Bit16u action; 1509 unsigned long val; 1510 short width; 1511 bx_bool neg; 1512 { 1513 unsigned long nval = val / 10; 1514 if (nval) 1515 put_luint(action, nval, width - 1, neg); 1516 else { 1517 while (--width > 0) send(action, ' '); 1518 if (neg) send(action, '-'); 1519 } 1520 send(action, val - (nval * 10) + '0'); 1521 } 1522 1523 void put_str(action, segment, offset) 1524 Bit16u action; 1525 Bit16u segment; 1526 Bit16u offset; 1527 { 1528 Bit8u c; 1529 1530 while (c = read_byte(segment, offset)) { 1531 send(action, c); 1532 offset++; 1533 } 1534 } 1535 1536 void 1537 delay_ticks(ticks) 1538 Bit16u ticks; 1539 { 1540 long ticks_to_wait, delta; 1541 Bit32u prev_ticks, t; 1542 1543 /* 1544 * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock. 1545 * We also have to be careful about interrupt storms. 1546 */ 1547 ASM_START 1548 pushf 1549 sti 1550 ASM_END 1551 ticks_to_wait = ticks; 1552 prev_ticks = read_dword(0x0, 0x46c); 1553 do 1554 { 1555 ASM_START 1556 hlt 1557 ASM_END 1558 t = read_dword(0x0, 0x46c); 1559 if (t > prev_ticks) 1560 { 1561 delta = t - prev_ticks; /* The temp var is required or bcc screws up. */ 1562 ticks_to_wait -= delta; 1563 } 1564 else if (t < prev_ticks) 1565 { 1566 ticks_to_wait -= t; /* wrapped */ 1567 } 1568 1569 prev_ticks = t; 1570 } while (ticks_to_wait > 0); 1571 ASM_START 1572 cli 1573 popf 1574 ASM_END 1575 } 1576 1577 Bit8u 1578 check_for_keystroke() 1579 { 1580 ASM_START 1581 mov ax, #0x100 1582 int #0x16 1583 jz no_key 1584 mov al, #1 1585 jmp done 1586 no_key: 1587 xor al, al 1588 done: 1589 ASM_END 1590 } 1591 1592 Bit8u 1593 get_keystroke() 1594 { 1595 ASM_START 1596 mov ax, #0x0 1597 int #0x16 1598 xchg ah, al 1599 ASM_END 1600 } 1601 1602 void 1603 delay_ticks_and_check_for_keystroke(ticks, count) 1604 Bit16u ticks, count; 1605 { 1606 Bit16u i; 1607 for (i = 1; i <= count; i++) { 1608 delay_ticks(ticks); 1609 if (check_for_keystroke()) 1610 break; 1611 } 1612 } 1613 1614 //-------------------------------------------------------------------------- 1615 // bios_printf() 1616 // A compact variable argument printf function. 1617 // 1618 // Supports %[format_width][length]format 1619 // where format can be x,X,u,d,s,S,c 1620 // and the optional length modifier is l (ell) 1621 //-------------------------------------------------------------------------- 1622 void 1623 bios_printf(action, s) 1624 Bit16u action; 1625 Bit8u *s; 1626 { 1627 Bit8u c, format_char; 1628 bx_bool in_format; 1629 short i; 1630 Bit16u *arg_ptr; 1631 Bit16u arg_seg, arg, nibble, hibyte, shift_count, format_width, hexadd; 1632 1633 arg_ptr = &s; 1634 arg_seg = get_SS(); 1635 1636 in_format = 0; 1637 format_width = 0; 1638 1639 if ((action & BIOS_PRINTF_DEBHALT) == BIOS_PRINTF_DEBHALT) { 1640 #if BX_VIRTUAL_PORTS 1641 outb(PANIC_PORT2, 0x00); 1642 #endif 1643 bios_printf (BIOS_PRINTF_SCREEN, "FATAL: "); 1644 } 1645 1646 while (c = read_byte(get_CS(), s)) { 1647 if ( c == '%' ) { 1648 in_format = 1; 1649 format_width = 0; 1650 } 1651 else if (in_format) { 1652 if ( (c>='0') && (c<='9') ) { 1653 format_width = (format_width * 10) + (c - '0'); 1654 } 1655 else { 1656 arg_ptr++; // increment to next arg 1657 arg = read_word(arg_seg, arg_ptr); 1658 if (c == 'x' || c == 'X') { 1659 if (format_width == 0) 1660 format_width = 4; 1661 if (c == 'x') 1662 hexadd = 'a'; 1663 else 1664 hexadd = 'A'; 1665 for (i=format_width-1; i>=0; i--) { 1666 nibble = (arg >> (4 * i)) & 0x000f; 1667 send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd)); 1668 } 1669 } 1670 else if (c == 'u') { 1671 put_uint(action, arg, format_width, 0); 1672 } 1673 else if (c == 'l') { 1674 s++; 1675 c = read_byte(get_CS(), s); /* is it ld,lx,lu? */ 1676 arg_ptr++; /* increment to next arg */ 1677 hibyte = read_word(arg_seg, arg_ptr); 1678 if (c == 'd') { 1679 if (hibyte & 0x8000) 1680 put_luint(action, 0L-(((Bit32u) hibyte << 16) | arg), format_width-1, 1); 1681 else 1682 put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0); 1683 } 1684 else if (c == 'u') { 1685 put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0); 1686 } 1687 else if (c == 'x' || c == 'X') 1688 { 1689 if (format_width == 0) 1690 format_width = 8; 1691 if (c == 'x') 1692 hexadd = 'a'; 1693 else 1694 hexadd = 'A'; 1695 for (i=format_width-1; i>=0; i--) { 1696 nibble = ((((Bit32u) hibyte <<16) | arg) >> (4 * i)) & 0x000f; 1697 send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd)); 1698 } 1699 } 1700 } 1701 else if (c == 'd') { 1702 if (arg & 0x8000) 1703 put_int(action, -arg, format_width - 1, 1); 1704 else 1705 put_int(action, arg, format_width, 0); 1706 } 1707 else if (c == 's') { 1708 put_str(action, get_CS(), arg); 1709 } 1710 else if (c == 'S') { 1711 hibyte = arg; 1712 arg_ptr++; 1713 arg = read_word(arg_seg, arg_ptr); 1714 put_str(action, hibyte, arg); 1715 } 1716 else if (c == 'c') { 1717 send(action, arg); 1718 } 1719 else 1720 BX_PANIC("bios_printf: unknown format\n"); 1721 in_format = 0; 1722 } 1723 } 1724 else { 1725 send(action, c); 1726 } 1727 s ++; 1728 } 1729 1730 if (action & BIOS_PRINTF_HALT) { 1731 // freeze in a busy loop. 1732 ASM_START 1733 cli 1734 halt2_loop: 1735 hlt 1736 jmp halt2_loop 1737 ASM_END 1738 } 1739 } 1740 1741 //-------------------------------------------------------------------------- 1742 // keyboard_init 1743 //-------------------------------------------------------------------------- 1744 // this file is based on LinuxBIOS implementation of keyboard.c 1745 // could convert to #asm to gain space 1746 void 1747 keyboard_init() 1748 { 1749 Bit16u max; 1750 1751 /* ------------------- Flush buffers ------------------------*/ 1752 /* Wait until buffer is empty */ 1753 max=0xffff; 1754 while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00); 1755 1756 /* flush incoming keys */ 1757 max=0x2000; 1758 while (--max > 0) { 1759 outb(0x80, 0x00); 1760 if (inb(0x64) & 0x01) { 1761 inb(0x60); 1762 max = 0x2000; 1763 } 1764 } 1765 1766 // Due to timer issues, and if the IPS setting is > 15000000, 1767 // the incoming keys might not be flushed here. That will 1768 // cause a panic a few lines below. See sourceforge bug report : 1769 // [ 642031 ] FATAL: Keyboard RESET error:993 1770 1771 /* ------------------- controller side ----------------------*/ 1772 /* send cmd = 0xAA, self test 8042 */ 1773 outb(0x64, 0xaa); 1774 1775 /* Wait until buffer is empty */ 1776 max=0xffff; 1777 while ( (inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x00); 1778 if (max==0x0) keyboard_panic(00); 1779 1780 /* Wait for data */ 1781 max=0xffff; 1782 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x01); 1783 if (max==0x0) keyboard_panic(01); 1784 1785 /* read self-test result, 0x55 should be returned from 0x60 */ 1786 if ((inb(0x60) != 0x55)){ 1787 keyboard_panic(991); 1788 } 1789 1790 /* send cmd = 0xAB, keyboard interface test */ 1791 outb(0x64,0xab); 1792 1793 /* Wait until buffer is empty */ 1794 max=0xffff; 1795 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x10); 1796 if (max==0x0) keyboard_panic(10); 1797 1798 /* Wait for data */ 1799 max=0xffff; 1800 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x11); 1801 if (max==0x0) keyboard_panic(11); 1802 1803 /* read keyboard interface test result, */ 1804 /* 0x00 should be returned form 0x60 */ 1805 if ((inb(0x60) != 0x00)) { 1806 keyboard_panic(992); 1807 } 1808 1809 /* Enable Keyboard clock */ 1810 outb(0x64,0xae); 1811 outb(0x64,0xa8); 1812 1813 /* ------------------- keyboard side ------------------------*/ 1814 /* reset kerboard and self test (keyboard side) */ 1815 outb(0x60, 0xff); 1816 1817 /* Wait until buffer is empty */ 1818 max=0xffff; 1819 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x20); 1820 if (max==0x0) keyboard_panic(20); 1821 1822 /* Wait for data */ 1823 max=0xffff; 1824 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x21); 1825 if (max==0x0) keyboard_panic(21); 1826 1827 /* keyboard should return ACK */ 1828 if ((inb(0x60) != 0xfa)) { 1829 keyboard_panic(993); 1830 } 1831 1832 /* Wait for data */ 1833 max=0xffff; 1834 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x31); 1835 if (max==0x0) keyboard_panic(31); 1836 1837 if ((inb(0x60) != 0xaa)) { 1838 keyboard_panic(994); 1839 } 1840 1841 /* Disable keyboard */ 1842 outb(0x60, 0xf5); 1843 1844 /* Wait until buffer is empty */ 1845 max=0xffff; 1846 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x40); 1847 if (max==0x0) keyboard_panic(40); 1848 1849 /* Wait for data */ 1850 max=0xffff; 1851 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x41); 1852 if (max==0x0) keyboard_panic(41); 1853 1854 /* keyboard should return ACK */ 1855 if ((inb(0x60) != 0xfa)) { 1856 keyboard_panic(995); 1857 } 1858 1859 /* Write Keyboard Mode */ 1860 outb(0x64, 0x60); 1861 1862 /* Wait until buffer is empty */ 1863 max=0xffff; 1864 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x50); 1865 if (max==0x0) keyboard_panic(50); 1866 1867 /* send cmd: scan code convert, disable mouse, enable IRQ 1 */ 1868 outb(0x60, 0x61); 1869 1870 /* Wait until buffer is empty */ 1871 max=0xffff; 1872 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x60); 1873 if (max==0x0) keyboard_panic(60); 1874 1875 /* Enable keyboard */ 1876 outb(0x60, 0xf4); 1877 1878 /* Wait until buffer is empty */ 1879 max=0xffff; 1880 while ((inb(0x64) & 0x02) && (--max>0)) outb(0x80, 0x70); 1881 if (max==0x0) keyboard_panic(70); 1882 1883 /* Wait for data */ 1884 max=0xffff; 1885 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x71); 1886 if (max==0x0) keyboard_panic(70); 1887 1888 /* keyboard should return ACK */ 1889 if ((inb(0x60) != 0xfa)) { 1890 keyboard_panic(996); 1891 } 1892 1893 outb(0x80, 0x77); 1894 } 1895 1896 //-------------------------------------------------------------------------- 1897 // keyboard_panic 1898 //-------------------------------------------------------------------------- 1899 void 1900 keyboard_panic(status) 1901 Bit16u status; 1902 { 1903 // If you're getting a 993 keyboard panic here, 1904 // please see the comment in keyboard_init 1905 1906 BX_PANIC("Keyboard error:%u\n",status); 1907 } 1908 1909 //-------------------------------------------------------------------------- 1910 // shutdown_status_panic 1911 // called when the shutdown statsu is not implemented, displays the status 1912 //-------------------------------------------------------------------------- 1913 void 1914 shutdown_status_panic(status) 1915 Bit16u status; 1916 { 1917 BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status); 1918 } 1919 1920 void s3_resume_panic() 1921 { 1922 BX_PANIC("Returned from s3_resume.\n"); 1923 } 1924 1925 //-------------------------------------------------------------------------- 1926 // print_bios_banner 1927 // displays a the bios version 1928 //-------------------------------------------------------------------------- 1929 void 1930 print_bios_banner() 1931 { 1932 printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ", 1933 BIOS_BUILD_DATE, bios_cvs_version_string); 1934 printf( 1935 #if BX_APM 1936 "apmbios " 1937 #endif 1938 #if BX_PCIBIOS 1939 "pcibios " 1940 #endif 1941 #if BX_ELTORITO_BOOT 1942 "eltorito " 1943 #endif 1944 #if BX_ROMBIOS32 1945 "rombios32 " 1946 #endif 1947 "\n\n"); 1948 } 1949 1950 //-------------------------------------------------------------------------- 1951 // BIOS Boot Specification 1.0.1 compatibility 1952 // 1953 // Very basic support for the BIOS Boot Specification, which allows expansion 1954 // ROMs to register themselves as boot devices, instead of just stealing the 1955 // INT 19h boot vector. 1956 // 1957 // This is a hack: to do it properly requires a proper PnP BIOS and we aren't 1958 // one; we just lie to the option ROMs to make them behave correctly. 1959 // We also don't support letting option ROMs register as bootable disk 1960 // drives (BCVs), only as bootable devices (BEVs). 1961 // 1962 // http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm 1963 //-------------------------------------------------------------------------- 1964 1965 static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"}; 1966 1967 static void 1968 init_boot_vectors() 1969 { 1970 ipl_entry_t e; 1971 Bit16u count = 0; 1972 Bit16u ss = get_SS(); 1973 1974 /* Clear out the IPL table. */ 1975 memsetb(IPL_SEG, IPL_TABLE_OFFSET, 0, IPL_SIZE); 1976 1977 /* User selected device not set */ 1978 write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, 0xFFFF); 1979 1980 /* Floppy drive */ 1981 e.type = IPL_TYPE_FLOPPY; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; 1982 memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); 1983 count++; 1984 1985 /* First HDD */ 1986 e.type = IPL_TYPE_HARDDISK; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; 1987 memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); 1988 count++; 1989 1990 #if BX_ELTORITO_BOOT 1991 /* CDROM */ 1992 e.type = IPL_TYPE_CDROM; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; 1993 memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e)); 1994 count++; 1995 #endif 1996 1997 /* Remember how many devices we have */ 1998 write_word(IPL_SEG, IPL_COUNT_OFFSET, count); 1999 /* Not tried booting anything yet */ 2000 write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xffff); 2001 } 2002 2003 static Bit8u 2004 get_boot_vector(i, e) 2005 Bit16u i; ipl_entry_t *e; 2006 { 2007 Bit16u count; 2008 Bit16u ss = get_SS(); 2009 /* Get the count of boot devices, and refuse to overrun the array */ 2010 count = read_word(IPL_SEG, IPL_COUNT_OFFSET); 2011 if (i >= count) return 0; 2012 /* OK to read this device */ 2013 memcpyb(ss, e, IPL_SEG, IPL_TABLE_OFFSET + i * sizeof (*e), sizeof (*e)); 2014 return 1; 2015 } 2016 2017 #if BX_ELTORITO_BOOT 2018 void 2019 interactive_bootkey() 2020 { 2021 ipl_entry_t e; 2022 Bit16u count; 2023 char description[33]; 2024 Bit8u scan_code; 2025 Bit8u i; 2026 Bit16u ss = get_SS(); 2027 Bit16u valid_choice = 0; 2028 2029 while (check_for_keystroke()) 2030 get_keystroke(); 2031 2032 printf("Press F12 for boot menu.\n\n"); 2033 2034 delay_ticks_and_check_for_keystroke(11, 5); /* ~3 seconds */ 2035 if (check_for_keystroke()) 2036 { 2037 scan_code = get_keystroke(); 2038 if (scan_code == 0x86) /* F12 */ 2039 { 2040 while (check_for_keystroke()) 2041 get_keystroke(); 2042 2043 printf("Select boot device:\n\n"); 2044 2045 count = read_word(IPL_SEG, IPL_COUNT_OFFSET); 2046 for (i = 0; i < count; i++) 2047 { 2048 memcpyb(ss, &e, IPL_SEG, IPL_TABLE_OFFSET + i * sizeof (e), sizeof (e)); 2049 printf("%d. ", i+1); 2050 switch(e.type) 2051 { 2052 case IPL_TYPE_FLOPPY: 2053 case IPL_TYPE_HARDDISK: 2054 case IPL_TYPE_CDROM: 2055 printf("%s\n", drivetypes[e.type]); 2056 break; 2057 case IPL_TYPE_BEV: 2058 printf("%s", drivetypes[4]); 2059 if (e.description != 0) 2060 { 2061 memcpyb(ss, &description, (Bit16u)(e.description >> 16), (Bit16u)(e.description & 0xffff), 32); 2062 description[32] = 0; 2063 printf(" [%S]", ss, description); 2064 } 2065 printf("\n"); 2066 break; 2067 } 2068 } 2069 2070 count++; 2071 while (!valid_choice) { 2072 scan_code = get_keystroke(); 2073 if (scan_code == 0x01 || scan_code == 0x58) /* ESC or F12 */ 2074 { 2075 valid_choice = 1; 2076 } 2077 else if (scan_code <= count) 2078 { 2079 valid_choice = 1; 2080 scan_code -= 1; 2081 /* Set user selected device */ 2082 write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, scan_code); 2083 } 2084 } 2085 printf("\n"); 2086 } 2087 } 2088 } 2089 #endif // BX_ELTORITO_BOOT 2090 2091 //-------------------------------------------------------------------------- 2092 // print_boot_device 2093 // displays the boot device 2094 //-------------------------------------------------------------------------- 2095 2096 void 2097 print_boot_device(e) 2098 ipl_entry_t *e; 2099 { 2100 Bit16u type; 2101 char description[33]; 2102 Bit16u ss = get_SS(); 2103 type = e->type; 2104 /* NIC appears as type 0x80 */ 2105 if (type == IPL_TYPE_BEV) type = 0x4; 2106 if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n"); 2107 printf("Booting from %s", drivetypes[type]); 2108 /* print product string if BEV */ 2109 if (type == 4 && e->description != 0) { 2110 /* first 32 bytes are significant */ 2111 memcpyb(ss, &description, (Bit16u)(e->description >> 16), (Bit16u)(e->description & 0xffff), 32); 2112 /* terminate string */ 2113 description[32] = 0; 2114 printf(" [%S]", ss, description); 2115 } 2116 printf("...\n"); 2117 } 2118 2119 //-------------------------------------------------------------------------- 2120 // print_boot_failure 2121 // displays the reason why boot failed 2122 //-------------------------------------------------------------------------- 2123 void 2124 print_boot_failure(type, reason) 2125 Bit16u type; Bit8u reason; 2126 { 2127 if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n"); 2128 2129 printf("Boot failed"); 2130 if (type < 4) { 2131 /* Report the reason too */ 2132 if (reason==0) 2133 printf(": not a bootable disk"); 2134 else 2135 printf(": could not read the boot disk"); 2136 } 2137 printf("\n\n"); 2138 } 2139 2140 //-------------------------------------------------------------------------- 2141 // print_cdromboot_failure 2142 // displays the reason why boot failed 2143 //-------------------------------------------------------------------------- 2144 void 2145 print_cdromboot_failure( code ) 2146 Bit16u code; 2147 { 2148 bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "CDROM boot failure code : %04x\n",code); 2149 2150 return; 2151 } 2152 2153 void 2154 nmi_handler_msg() 2155 { 2156 BX_PANIC("NMI Handler called\n"); 2157 } 2158 2159 void 2160 int18_panic_msg() 2161 { 2162 BX_PANIC("INT18: BOOT FAILURE\n"); 2163 } 2164 2165 void 2166 log_bios_start() 2167 { 2168 #if BX_DEBUG_SERIAL 2169 outb(BX_DEBUG_PORT+UART_LCR, 0x03); /* setup for serial logging: 8N1 */ 2170 #endif 2171 BX_INFO("%s\n", bios_cvs_version_string); 2172 } 2173 2174 bx_bool 2175 set_enable_a20(val) 2176 bx_bool val; 2177 { 2178 Bit8u oldval; 2179 2180 // Use PS2 System Control port A to set A20 enable 2181 2182 // get current setting first 2183 oldval = inb(0x92); 2184 2185 // change A20 status 2186 if (val) 2187 outb(0x92, oldval | 0x02); 2188 else 2189 outb(0x92, oldval & 0xfd); 2190 2191 return((oldval & 0x02) != 0); 2192 } 2193 2194 void 2195 debugger_on() 2196 { 2197 outb(0xfedc, 0x01); 2198 } 2199 2200 void 2201 debugger_off() 2202 { 2203 outb(0xfedc, 0x00); 2204 } 2205 2206 int 2207 s3_resume() 2208 { 2209 Bit32u s3_wakeup_vector; 2210 Bit8u s3_resume_flag; 2211 2212 s3_resume_flag = read_byte(0x40, 0xb0); 2213 s3_wakeup_vector = read_dword(0x40, 0xb2); 2214 2215 BX_INFO("S3 resume called %x 0x%lx\n", s3_resume_flag, s3_wakeup_vector); 2216 if (s3_resume_flag != 0xFE || !s3_wakeup_vector) 2217 return 0; 2218 2219 write_byte(0x40, 0xb0, 0); 2220 2221 /* setup wakeup vector */ 2222 write_word(0x40, 0xb6, (s3_wakeup_vector & 0xF)); /* IP */ 2223 write_word(0x40, 0xb8, (s3_wakeup_vector >> 4)); /* CS */ 2224 2225 BX_INFO("S3 resume jump to %x:%x\n", (s3_wakeup_vector >> 4), 2226 (s3_wakeup_vector & 0xF)); 2227 ASM_START 2228 jmpf [0x04b6] 2229 ASM_END 2230 return 1; 2231 } 2232 2233 #if BX_USE_ATADRV 2234 2235 // --------------------------------------------------------------------------- 2236 // Start of ATA/ATAPI Driver 2237 // --------------------------------------------------------------------------- 2238 2239 // Global defines -- ATA register and register bits. 2240 // command block & control block regs 2241 #define ATA_CB_DATA 0 // data reg in/out pio_base_addr1+0 2242 #define ATA_CB_ERR 1 // error in pio_base_addr1+1 2243 #define ATA_CB_FR 1 // feature reg out pio_base_addr1+1 2244 #define ATA_CB_SC 2 // sector count in/out pio_base_addr1+2 2245 #define ATA_CB_SN 3 // sector number in/out pio_base_addr1+3 2246 #define ATA_CB_CL 4 // cylinder low in/out pio_base_addr1+4 2247 #define ATA_CB_CH 5 // cylinder high in/out pio_base_addr1+5 2248 #define ATA_CB_DH 6 // device head in/out pio_base_addr1+6 2249 #define ATA_CB_STAT 7 // primary status in pio_base_addr1+7 2250 #define ATA_CB_CMD 7 // command out pio_base_addr1+7 2251 #define ATA_CB_ASTAT 6 // alternate status in pio_base_addr2+6 2252 #define ATA_CB_DC 6 // device control out pio_base_addr2+6 2253 #define ATA_CB_DA 7 // device address in pio_base_addr2+7 2254 2255 #define ATA_CB_ER_ICRC 0x80 // ATA Ultra DMA bad CRC 2256 #define ATA_CB_ER_BBK 0x80 // ATA bad block 2257 #define ATA_CB_ER_UNC 0x40 // ATA uncorrected error 2258 #define ATA_CB_ER_MC 0x20 // ATA media change 2259 #define ATA_CB_ER_IDNF 0x10 // ATA id not found 2260 #define ATA_CB_ER_MCR 0x08 // ATA media change request 2261 #define ATA_CB_ER_ABRT 0x04 // ATA command aborted 2262 #define ATA_CB_ER_NTK0 0x02 // ATA track 0 not found 2263 #define ATA_CB_ER_NDAM 0x01 // ATA address mark not found 2264 2265 #define ATA_CB_ER_P_SNSKEY 0xf0 // ATAPI sense key (mask) 2266 #define ATA_CB_ER_P_MCR 0x08 // ATAPI Media Change Request 2267 #define ATA_CB_ER_P_ABRT 0x04 // ATAPI command abort 2268 #define ATA_CB_ER_P_EOM 0x02 // ATAPI End of Media 2269 #define ATA_CB_ER_P_ILI 0x01 // ATAPI Illegal Length Indication 2270 2271 // ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC) 2272 #define ATA_CB_SC_P_TAG 0xf8 // ATAPI tag (mask) 2273 #define ATA_CB_SC_P_REL 0x04 // ATAPI release 2274 #define ATA_CB_SC_P_IO 0x02 // ATAPI I/O 2275 #define ATA_CB_SC_P_CD 0x01 // ATAPI C/D 2276 2277 // bits 7-4 of the device/head (CB_DH) reg 2278 #define ATA_CB_DH_DEV0 0xa0 // select device 0 2279 #define ATA_CB_DH_DEV1 0xb0 // select device 1 2280 #define ATA_CB_DH_LBA 0x40 // use LBA 2281 2282 // status reg (CB_STAT and CB_ASTAT) bits 2283 #define ATA_CB_STAT_BSY 0x80 // busy 2284 #define ATA_CB_STAT_RDY 0x40 // ready 2285 #define ATA_CB_STAT_DF 0x20 // device fault 2286 #define ATA_CB_STAT_WFT 0x20 // write fault (old name) 2287 #define ATA_CB_STAT_SKC 0x10 // seek complete 2288 #define ATA_CB_STAT_SERV 0x10 // service 2289 #define ATA_CB_STAT_DRQ 0x08 // data request 2290 #define ATA_CB_STAT_CORR 0x04 // corrected 2291 #define ATA_CB_STAT_IDX 0x02 // index 2292 #define ATA_CB_STAT_ERR 0x01 // error (ATA) 2293 #define ATA_CB_STAT_CHK 0x01 // check (ATAPI) 2294 2295 // device control reg (CB_DC) bits 2296 #define ATA_CB_DC_HD15 0x08 // bit should always be set to one 2297 #define ATA_CB_DC_SRST 0x04 // soft reset 2298 #define ATA_CB_DC_NIEN 0x02 // disable interrupts 2299 2300 // Most mandtory and optional ATA commands (from ATA-3), 2301 #define ATA_CMD_CFA_ERASE_SECTORS 0xC0 2302 #define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE 0x03 2303 #define ATA_CMD_CFA_TRANSLATE_SECTOR 0x87 2304 #define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD 2305 #define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38 2306 #define ATA_CMD_CHECK_POWER_MODE1 0xE5 2307 #define ATA_CMD_CHECK_POWER_MODE2 0x98 2308 #define ATA_CMD_DEVICE_RESET 0x08 2309 #define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90 2310 #define ATA_CMD_FLUSH_CACHE 0xE7 2311 #define ATA_CMD_FORMAT_TRACK 0x50 2312 #define ATA_CMD_IDENTIFY_DEVICE 0xEC 2313 #define ATA_CMD_IDENTIFY_DEVICE_PACKET 0xA1 2314 #define ATA_CMD_IDENTIFY_PACKET_DEVICE 0xA1 2315 #define ATA_CMD_IDLE1 0xE3 2316 #define ATA_CMD_IDLE2 0x97 2317 #define ATA_CMD_IDLE_IMMEDIATE1 0xE1 2318 #define ATA_CMD_IDLE_IMMEDIATE2 0x95 2319 #define ATA_CMD_INITIALIZE_DRIVE_PARAMETERS 0x91 2320 #define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91 2321 #define ATA_CMD_NOP 0x00 2322 #define ATA_CMD_PACKET 0xA0 2323 #define ATA_CMD_READ_BUFFER 0xE4 2324 #define ATA_CMD_READ_DMA 0xC8 2325 #define ATA_CMD_READ_DMA_QUEUED 0xC7 2326 #define ATA_CMD_READ_MULTIPLE 0xC4 2327 #define ATA_CMD_READ_SECTORS 0x20 2328 #define ATA_CMD_READ_VERIFY_SECTORS 0x40 2329 #define ATA_CMD_RECALIBRATE 0x10 2330 #define ATA_CMD_REQUEST_SENSE 0x03 2331 #define ATA_CMD_SEEK 0x70 2332 #define ATA_CMD_SET_FEATURES 0xEF 2333 #define ATA_CMD_SET_MULTIPLE_MODE 0xC6 2334 #define ATA_CMD_SLEEP1 0xE6 2335 #define ATA_CMD_SLEEP2 0x99 2336 #define ATA_CMD_STANDBY1 0xE2 2337 #define ATA_CMD_STANDBY2 0x96 2338 #define ATA_CMD_STANDBY_IMMEDIATE1 0xE0 2339 #define ATA_CMD_STANDBY_IMMEDIATE2 0x94 2340 #define ATA_CMD_WRITE_BUFFER 0xE8 2341 #define ATA_CMD_WRITE_DMA 0xCA 2342 #define ATA_CMD_WRITE_DMA_QUEUED 0xCC 2343 #define ATA_CMD_WRITE_MULTIPLE 0xC5 2344 #define ATA_CMD_WRITE_SECTORS 0x30 2345 #define ATA_CMD_WRITE_VERIFY 0x3C 2346 2347 #define ATA_IFACE_NONE 0x00 2348 #define ATA_IFACE_ISA 0x00 2349 #define ATA_IFACE_PCI 0x01 2350 2351 #define ATA_TYPE_NONE 0x00 2352 #define ATA_TYPE_UNKNOWN 0x01 2353 #define ATA_TYPE_ATA 0x02 2354 #define ATA_TYPE_ATAPI 0x03 2355 2356 #define ATA_DEVICE_NONE 0x00 2357 #define ATA_DEVICE_HD 0xFF 2358 #define ATA_DEVICE_CDROM 0x05 2359 2360 #define ATA_MODE_NONE 0x00 2361 #define ATA_MODE_PIO16 0x00 2362 #define ATA_MODE_PIO32 0x01 2363 #define ATA_MODE_ISADMA 0x02 2364 #define ATA_MODE_PCIDMA 0x03 2365 #define ATA_MODE_USEIRQ 0x10 2366 2367 #define ATA_TRANSLATION_NONE 0 2368 #define ATA_TRANSLATION_LBA 1 2369 #define ATA_TRANSLATION_LARGE 2 2370 #define ATA_TRANSLATION_RECHS 3 2371 2372 #define ATA_DATA_NO 0x00 2373 #define ATA_DATA_IN 0x01 2374 #define ATA_DATA_OUT 0x02 2375 2376 // --------------------------------------------------------------------------- 2377 // ATA/ATAPI driver : initialization 2378 // --------------------------------------------------------------------------- 2379 void ata_init( ) 2380 { 2381 Bit16u ebda_seg=read_word(0x0040,0x000E); 2382 Bit8u channel, device; 2383 2384 // Channels info init. 2385 for (channel=0; channel<BX_MAX_ATA_INTERFACES; channel++) { 2386 write_byte(ebda_seg,&EbdaData->ata.channels[channel].iface,ATA_IFACE_NONE); 2387 write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1,0x0); 2388 write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase2,0x0); 2389 write_byte(ebda_seg,&EbdaData->ata.channels[channel].irq,0); 2390 } 2391 2392 // Devices info init. 2393 for (device=0; device<BX_MAX_ATA_DEVICES; device++) { 2394 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE); 2395 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_NONE); 2396 write_byte(ebda_seg,&EbdaData->ata.devices[device].removable,0); 2397 write_byte(ebda_seg,&EbdaData->ata.devices[device].lock,0); 2398 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode,ATA_MODE_NONE); 2399 write_word(ebda_seg,&EbdaData->ata.devices[device].blksize,0); 2400 write_byte(ebda_seg,&EbdaData->ata.devices[device].translation,ATA_TRANSLATION_NONE); 2401 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads,0); 2402 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders,0); 2403 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt,0); 2404 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads,0); 2405 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders,0); 2406 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt,0); 2407 2408 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low,0L); 2409 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high,0L); 2410 } 2411 2412 // hdidmap and cdidmap init. 2413 for (device=0; device<BX_MAX_ATA_DEVICES; device++) { 2414 write_byte(ebda_seg,&EbdaData->ata.hdidmap[device],BX_MAX_ATA_DEVICES); 2415 write_byte(ebda_seg,&EbdaData->ata.cdidmap[device],BX_MAX_ATA_DEVICES); 2416 } 2417 2418 write_byte(ebda_seg,&EbdaData->ata.hdcount,0); 2419 write_byte(ebda_seg,&EbdaData->ata.cdcount,0); 2420 } 2421 2422 #define TIMEOUT 0 2423 #define BSY 1 2424 #define NOT_BSY 2 2425 #define NOT_BSY_DRQ 3 2426 #define NOT_BSY_NOT_DRQ 4 2427 #define NOT_BSY_RDY 5 2428 2429 #define IDE_TIMEOUT 32000u //32 seconds max for IDE ops 2430 2431 int await_ide(); 2432 static int await_ide(when_done,base,timeout) 2433 Bit8u when_done; 2434 Bit16u base; 2435 Bit16u timeout; 2436 { 2437 Bit32u time=0,last=0; 2438 Bit16u status; 2439 Bit8u result; 2440 status = inb(base + ATA_CB_STAT); // for the times you're supposed to throw one away 2441 for(;;) { 2442 status = inb(base+ATA_CB_STAT); 2443 time++; 2444 if (when_done == BSY) 2445 result = status & ATA_CB_STAT_BSY; 2446 else if (when_done == NOT_BSY) 2447 result = !(status & ATA_CB_STAT_BSY); 2448 else if (when_done == NOT_BSY_DRQ) 2449 result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_DRQ); 2450 else if (when_done == NOT_BSY_NOT_DRQ) 2451 result = !(status & ATA_CB_STAT_BSY) && !(status & ATA_CB_STAT_DRQ); 2452 else if (when_done == NOT_BSY_RDY) 2453 result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_RDY); 2454 else if (when_done == TIMEOUT) 2455 result = 0; 2456 2457 if (result) return 0; 2458 if (time>>16 != last) // mod 2048 each 16 ms 2459 { 2460 last = time >>16; 2461 BX_DEBUG_ATA("await_ide: (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %ld timeout= %d\n",when_done,time>>11, timeout); 2462 } 2463 if (status & ATA_CB_STAT_ERR) 2464 { 2465 BX_DEBUG_ATA("await_ide: ERROR (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %ld timeout= %d\n",when_done,time>>11, timeout); 2466 return -1; 2467 } 2468 if ((timeout == 0) || ((time>>11) > timeout)) break; 2469 } 2470 BX_INFO("IDE time out\n"); 2471 return -1; 2472 } 2473 2474 // --------------------------------------------------------------------------- 2475 // ATA/ATAPI driver : device detection 2476 // --------------------------------------------------------------------------- 2477 2478 void ata_detect( ) 2479 { 2480 Bit16u ebda_seg=read_word(0x0040,0x000E); 2481 Bit8u hdcount, cdcount, device, type; 2482 Bit8u buffer[0x0200]; 2483 2484 #if BX_MAX_ATA_INTERFACES > 0 2485 write_byte(ebda_seg,&EbdaData->ata.channels[0].iface,ATA_IFACE_ISA); 2486 write_word(ebda_seg,&EbdaData->ata.channels[0].iobase1,0x1f0); 2487 write_word(ebda_seg,&EbdaData->ata.channels[0].iobase2,0x3f0); 2488 write_byte(ebda_seg,&EbdaData->ata.channels[0].irq,14); 2489 #endif 2490 #if BX_MAX_ATA_INTERFACES > 1 2491 write_byte(ebda_seg,&EbdaData->ata.channels[1].iface,ATA_IFACE_ISA); 2492 write_word(ebda_seg,&EbdaData->ata.channels[1].iobase1,0x170); 2493 write_word(ebda_seg,&EbdaData->ata.channels[1].iobase2,0x370); 2494 write_byte(ebda_seg,&EbdaData->ata.channels[1].irq,15); 2495 #endif 2496 #if BX_MAX_ATA_INTERFACES > 2 2497 write_byte(ebda_seg,&EbdaData->ata.channels[2].iface,ATA_IFACE_ISA); 2498 write_word(ebda_seg,&EbdaData->ata.channels[2].iobase1,0x1e8); 2499 write_word(ebda_seg,&EbdaData->ata.channels[2].iobase2,0x3e0); 2500 write_byte(ebda_seg,&EbdaData->ata.channels[2].irq,12); 2501 #endif 2502 #if BX_MAX_ATA_INTERFACES > 3 2503 write_byte(ebda_seg,&EbdaData->ata.channels[3].iface,ATA_IFACE_ISA); 2504 write_word(ebda_seg,&EbdaData->ata.channels[3].iobase1,0x168); 2505 write_word(ebda_seg,&EbdaData->ata.channels[3].iobase2,0x360); 2506 write_byte(ebda_seg,&EbdaData->ata.channels[3].irq,11); 2507 #endif 2508 #if BX_MAX_ATA_INTERFACES > 4 2509 #error Please fill the ATA interface informations 2510 #endif 2511 2512 // Device detection 2513 hdcount=cdcount=0; 2514 2515 for(device=0; device<BX_MAX_ATA_DEVICES; device++) { 2516 Bit16u iobase1, iobase2; 2517 Bit8u channel, slave, shift; 2518 Bit8u sc, sn, cl, ch, st; 2519 2520 channel = device / 2; 2521 slave = device % 2; 2522 2523 iobase1 =read_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1); 2524 iobase2 =read_word(ebda_seg,&EbdaData->ata.channels[channel].iobase2); 2525 2526 // Disable interrupts 2527 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); 2528 2529 // Look for device 2530 outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0); 2531 outb(iobase1+ATA_CB_SC, 0x55); 2532 outb(iobase1+ATA_CB_SN, 0xaa); 2533 outb(iobase1+ATA_CB_SC, 0xaa); 2534 outb(iobase1+ATA_CB_SN, 0x55); 2535 outb(iobase1+ATA_CB_SC, 0x55); 2536 outb(iobase1+ATA_CB_SN, 0xaa); 2537 2538 // If we found something 2539 sc = inb(iobase1+ATA_CB_SC); 2540 sn = inb(iobase1+ATA_CB_SN); 2541 2542 if ( (sc == 0x55) && (sn == 0xaa) ) { 2543 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_UNKNOWN); 2544 2545 // reset the channel 2546 ata_reset(device); 2547 2548 // check for ATA or ATAPI 2549 outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0); 2550 sc = inb(iobase1+ATA_CB_SC); 2551 sn = inb(iobase1+ATA_CB_SN); 2552 if ((sc==0x01) && (sn==0x01)) { 2553 cl = inb(iobase1+ATA_CB_CL); 2554 ch = inb(iobase1+ATA_CB_CH); 2555 st = inb(iobase1+ATA_CB_STAT); 2556 2557 if ((cl==0x14) && (ch==0xeb)) { 2558 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATAPI); 2559 } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) { 2560 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATA); 2561 } else if ((cl==0xff) && (ch==0xff)) { 2562 write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE); 2563 } 2564 } 2565 } 2566 2567 type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type); 2568 2569 // Now we send a IDENTIFY command to ATA device 2570 if(type == ATA_TYPE_ATA) { 2571 Bit32u sectors_low, sectors_high; 2572 Bit16u cylinders, heads, spt, blksize; 2573 Bit8u translation, removable, mode; 2574 2575 //Temporary values to do the transfer 2576 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD); 2577 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16); 2578 2579 if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) !=0 ) 2580 BX_PANIC("ata-detect: Failed to detect ATA device\n"); 2581 2582 removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0; 2583 mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16; 2584 blksize = read_word(get_SS(),buffer+10); 2585 2586 cylinders = read_word(get_SS(),buffer+(1*2)); // word 1 2587 heads = read_word(get_SS(),buffer+(3*2)); // word 3 2588 spt = read_word(get_SS(),buffer+(6*2)); // word 6 2589 2590 if (read_word(get_SS(),buffer+(83*2)) & (1 << 10)) { // word 83 - lba48 support 2591 sectors_low = read_dword(get_SS(),buffer+(100*2)); // word 100 and word 101 2592 sectors_high = read_dword(get_SS(),buffer+(102*2)); // word 102 and word 103 2593 } else { 2594 sectors_low = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61 2595 sectors_high = 0; 2596 } 2597 2598 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD); 2599 write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable); 2600 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode); 2601 write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize); 2602 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads, heads); 2603 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders, cylinders); 2604 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt); 2605 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors_low); 2606 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high, sectors_high); 2607 BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt); 2608 2609 translation = inb_cmos(0x39 + channel/2); 2610 for (shift=device%4; shift>0; shift--) translation >>= 2; 2611 translation &= 0x03; 2612 2613 write_byte(ebda_seg,&EbdaData->ata.devices[device].translation, translation); 2614 2615 switch (translation) { 2616 case ATA_TRANSLATION_NONE: 2617 BX_INFO("none"); 2618 break; 2619 case ATA_TRANSLATION_LBA: 2620 BX_INFO("lba"); 2621 break; 2622 case ATA_TRANSLATION_LARGE: 2623 BX_INFO("large"); 2624 break; 2625 case ATA_TRANSLATION_RECHS: 2626 BX_INFO("r-echs"); 2627 break; 2628 } 2629 switch (translation) { 2630 case ATA_TRANSLATION_NONE: 2631 break; 2632 case ATA_TRANSLATION_LBA: 2633 spt = 63; 2634 sectors_low /= 63; 2635 heads = sectors_low / 1024; 2636 if (heads>128) heads = 255; 2637 else if (heads>64) heads = 128; 2638 else if (heads>32) heads = 64; 2639 else if (heads>16) heads = 32; 2640 else heads=16; 2641 cylinders = sectors_low / heads; 2642 break; 2643 case ATA_TRANSLATION_RECHS: 2644 // Take care not to overflow 2645 if (heads==16) { 2646 if(cylinders>61439) cylinders=61439; 2647 heads=15; 2648 cylinders = (Bit16u)((Bit32u)(cylinders)*16/15); 2649 } 2650 // then go through the large bitshift process 2651 case ATA_TRANSLATION_LARGE: 2652 while(cylinders > 1024) { 2653 cylinders >>= 1; 2654 heads <<= 1; 2655 2656 // If we max out the head count 2657 if (heads > 127) break; 2658 } 2659 break; 2660 } 2661 // clip to 1024 cylinders in lchs 2662 if (cylinders > 1024) cylinders=1024; 2663 BX_INFO(" LCHS=%d/%d/%d\n", cylinders, heads, spt); 2664 2665 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, heads); 2666 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, cylinders); 2667 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, spt); 2668 2669 // fill hdidmap 2670 write_byte(ebda_seg,&EbdaData->ata.hdidmap[hdcount], device); 2671 hdcount++; 2672 } 2673 2674 // Now we send a IDENTIFY command to ATAPI device 2675 if(type == ATA_TYPE_ATAPI) { 2676 2677 Bit8u type, removable, mode; 2678 Bit16u blksize; 2679 2680 //Temporary values to do the transfer 2681 write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_CDROM); 2682 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16); 2683 2684 if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) != 0) 2685 BX_PANIC("ata-detect: Failed to detect ATAPI device\n"); 2686 2687 type = read_byte(get_SS(),buffer+1) & 0x1f; 2688 removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0; 2689 mode = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16; 2690 blksize = 2048; 2691 2692 write_byte(ebda_seg,&EbdaData->ata.devices[device].device, type); 2693 write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable); 2694 write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode); 2695 write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize); 2696 2697 // fill cdidmap 2698 write_byte(ebda_seg,&EbdaData->ata.cdidmap[cdcount], device); 2699 cdcount++; 2700 } 2701 2702 { 2703 Bit32u sizeinmb; 2704 Bit16u ataversion; 2705 Bit8u c, i, version, model[41]; 2706 2707 switch (type) { 2708 case ATA_TYPE_ATA: 2709 sizeinmb = (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high) << 21) 2710 | (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low) >> 11); 2711 case ATA_TYPE_ATAPI: 2712 // Read ATA/ATAPI version 2713 ataversion=((Bit16u)(read_byte(get_SS(),buffer+161))<<8)|read_byte(get_SS(),buffer+160); 2714 for(version=15;version>0;version--) { 2715 if((ataversion&(1<<version))!=0) 2716 break; 2717 } 2718 2719 // Read model name 2720 for(i=0;i<20;i++){ 2721 write_byte(get_SS(),model+(i*2),read_byte(get_SS(),buffer+(i*2)+54+1)); 2722 write_byte(get_SS(),model+(i*2)+1,read_byte(get_SS(),buffer+(i*2)+54)); 2723 } 2724 2725 // Reformat 2726 write_byte(get_SS(),model+40,0x00); 2727 for(i=39;i>0;i--){ 2728 if(read_byte(get_SS(),model+i)==0x20) 2729 write_byte(get_SS(),model+i,0x00); 2730 else break; 2731 } 2732 if (i>36) { 2733 write_byte(get_SS(),model+36,0x00); 2734 for(i=35;i>32;i--){ 2735 write_byte(get_SS(),model+i,0x2E); 2736 } 2737 } 2738 break; 2739 } 2740 2741 switch (type) { 2742 case ATA_TYPE_ATA: 2743 printf("ata%d %s: ",channel,slave?" slave":"master"); 2744 i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c); 2745 if (sizeinmb < (1UL<<16)) 2746 printf(" ATA-%d Hard-Disk (%4u MBytes)\n", version, (Bit16u)sizeinmb); 2747 else 2748 printf(" ATA-%d Hard-Disk (%4u GBytes)\n", version, (Bit16u)(sizeinmb>>10)); 2749 break; 2750 case ATA_TYPE_ATAPI: 2751 printf("ata%d %s: ",channel,slave?" slave":"master"); 2752 i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c); 2753 if(read_byte(ebda_seg,&EbdaData->ata.devices[device].device)==ATA_DEVICE_CDROM) 2754 printf(" ATAPI-%d CD-Rom/DVD-Rom\n",version); 2755 else 2756 printf(" ATAPI-%d Device\n",version); 2757 break; 2758 case ATA_TYPE_UNKNOWN: 2759 printf("ata%d %s: Unknown device\n",channel,slave?" slave":"master"); 2760 break; 2761 } 2762 } 2763 } 2764 2765 // Store the devices counts 2766 write_byte(ebda_seg,&EbdaData->ata.hdcount, hdcount); 2767 write_byte(ebda_seg,&EbdaData->ata.cdcount, cdcount); 2768 write_byte(0x40,0x75, hdcount); 2769 2770 printf("\n"); 2771 2772 // FIXME : should use bios=cmos|auto|disable bits 2773 // FIXME : should know about translation bits 2774 // FIXME : move hard_drive_post here 2775 2776 } 2777 2778 // --------------------------------------------------------------------------- 2779 // ATA/ATAPI driver : software reset 2780 // --------------------------------------------------------------------------- 2781 // ATA-3 2782 // 8.2.1 Software reset - Device 0 2783 2784 void ata_reset(device) 2785 Bit16u device; 2786 { 2787 Bit16u ebda_seg=read_word(0x0040,0x000E); 2788 Bit16u iobase1, iobase2; 2789 Bit8u channel, slave, sn, sc; 2790 Bit8u type; 2791 Bit16u max; 2792 2793 channel = device / 2; 2794 slave = device % 2; 2795 2796 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 2797 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2); 2798 2799 // Reset 2800 2801 // 8.2.1 (a) -- set SRST in DC 2802 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST); 2803 2804 // 8.2.1 (b) -- wait for BSY 2805 await_ide(BSY, iobase1, 20); 2806 2807 // 8.2.1 (f) -- clear SRST 2808 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); 2809 2810 type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type); 2811 if (type != ATA_TYPE_NONE) { 2812 2813 // 8.2.1 (g) -- check for sc==sn==0x01 2814 // select device 2815 outb(iobase1+ATA_CB_DH, slave?ATA_CB_DH_DEV1:ATA_CB_DH_DEV0); 2816 sc = inb(iobase1+ATA_CB_SC); 2817 sn = inb(iobase1+ATA_CB_SN); 2818 2819 if ( (sc==0x01) && (sn==0x01) ) { 2820 if (type == ATA_TYPE_ATA) //ATA 2821 await_ide(NOT_BSY_RDY, iobase1, IDE_TIMEOUT); 2822 else //ATAPI 2823 await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); 2824 } 2825 2826 // 8.2.1 (h) -- wait for not BSY 2827 await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); 2828 } 2829 2830 // Enable interrupts 2831 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15); 2832 } 2833 2834 // --------------------------------------------------------------------------- 2835 // ATA/ATAPI driver : execute a non data command 2836 // --------------------------------------------------------------------------- 2837 2838 Bit16u ata_cmd_non_data() 2839 {return 0;} 2840 2841 // --------------------------------------------------------------------------- 2842 // ATA/ATAPI driver : execute a data-in command 2843 // --------------------------------------------------------------------------- 2844 // returns 2845 // 0 : no error 2846 // 1 : BUSY bit set 2847 // 2 : read error 2848 // 3 : expected DRQ=1 2849 // 4 : no sectors left to read/verify 2850 // 5 : more sectors to read/verify 2851 // 6 : no sectors left to write 2852 // 7 : more sectors to write 2853 Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset) 2854 Bit16u device, command, count, cylinder, head, sector, segment, offset; 2855 Bit32u lba_low, lba_high; 2856 { 2857 Bit16u ebda_seg=read_word(0x0040,0x000E); 2858 Bit16u iobase1, iobase2, blksize; 2859 Bit8u channel, slave; 2860 Bit8u status, current, mode; 2861 2862 channel = device / 2; 2863 slave = device % 2; 2864 2865 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 2866 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2); 2867 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode); 2868 blksize = 0x200; // was = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize); 2869 if (mode == ATA_MODE_PIO32) blksize>>=2; 2870 else blksize>>=1; 2871 2872 // Reset count of transferred data 2873 write_word(ebda_seg, &EbdaData->ata.trsfsectors,0); 2874 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L); 2875 current = 0; 2876 2877 status = inb(iobase1 + ATA_CB_STAT); 2878 if (status & ATA_CB_STAT_BSY) return 1; 2879 2880 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); 2881 2882 // sector will be 0 only on lba access. Convert to lba-chs 2883 if (sector == 0) { 2884 if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) { 2885 outb(iobase1 + ATA_CB_FR, 0x00); 2886 outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff); 2887 outb(iobase1 + ATA_CB_SN, lba_low >> 24); 2888 outb(iobase1 + ATA_CB_CL, lba_high & 0xff); 2889 outb(iobase1 + ATA_CB_CH, lba_high >> 8); 2890 command |= 0x04; 2891 count &= (1UL << 8) - 1; 2892 lba_low &= (1UL << 24) - 1; 2893 } 2894 sector = (Bit16u) (lba_low & 0x000000ffL); 2895 cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL); 2896 head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA; 2897 } 2898 2899 outb(iobase1 + ATA_CB_FR, 0x00); 2900 outb(iobase1 + ATA_CB_SC, count); 2901 outb(iobase1 + ATA_CB_SN, sector); 2902 outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff); 2903 outb(iobase1 + ATA_CB_CH, cylinder >> 8); 2904 outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head ); 2905 outb(iobase1 + ATA_CB_CMD, command); 2906 2907 await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT); 2908 status = inb(iobase1 + ATA_CB_STAT); 2909 2910 if (status & ATA_CB_STAT_ERR) { 2911 BX_DEBUG_ATA("ata_cmd_data_in : read error\n"); 2912 return 2; 2913 } else if ( !(status & ATA_CB_STAT_DRQ) ) { 2914 BX_DEBUG_ATA("ata_cmd_data_in : DRQ not set (status %02x)\n", (unsigned) status); 2915 return 3; 2916 } 2917 2918 // FIXME : move seg/off translation here 2919 2920 ASM_START 2921 sti ;; enable higher priority interrupts 2922 ASM_END 2923 2924 while (1) { 2925 2926 ASM_START 2927 push bp 2928 mov bp, sp 2929 mov di, _ata_cmd_data_in.offset + 2[bp] 2930 mov ax, _ata_cmd_data_in.segment + 2[bp] 2931 mov cx, _ata_cmd_data_in.blksize + 2[bp] 2932 2933 ;; adjust if there will be an overrun. 2K max sector size 2934 cmp di, #0xf800 ;; 2935 jbe ata_in_no_adjust 2936 2937 ata_in_adjust: 2938 sub di, #0x0800 ;; sub 2 kbytes from offset 2939 add ax, #0x0080 ;; add 2 Kbytes to segment 2940 2941 ata_in_no_adjust: 2942 mov es, ax ;; segment in es 2943 2944 mov dx, _ata_cmd_data_in.iobase1 + 2[bp] ;; ATA data read port 2945 2946 mov ah, _ata_cmd_data_in.mode + 2[bp] 2947 cmp ah, #ATA_MODE_PIO32 2948 je ata_in_32 2949 2950 ata_in_16: 2951 rep 2952 insw ;; CX words transfered from port(DX) to ES:[DI] 2953 jmp ata_in_done 2954 2955 ata_in_32: 2956 rep 2957 insd ;; CX dwords transfered from port(DX) to ES:[DI] 2958 2959 ata_in_done: 2960 mov _ata_cmd_data_in.offset + 2[bp], di 2961 mov _ata_cmd_data_in.segment + 2[bp], es 2962 pop bp 2963 ASM_END 2964 2965 current++; 2966 write_word(ebda_seg, &EbdaData->ata.trsfsectors,current); 2967 count--; 2968 await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); 2969 status = inb(iobase1 + ATA_CB_STAT); 2970 if (count == 0) { 2971 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 2972 != ATA_CB_STAT_RDY ) { 2973 BX_DEBUG_ATA("ata_cmd_data_in : no sectors left (status %02x)\n", (unsigned) status); 2974 return 4; 2975 } 2976 break; 2977 } 2978 else { 2979 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 2980 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) { 2981 BX_DEBUG_ATA("ata_cmd_data_in : more sectors left (status %02x)\n", (unsigned) status); 2982 return 5; 2983 } 2984 continue; 2985 } 2986 } 2987 // Enable interrupts 2988 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15); 2989 return 0; 2990 } 2991 2992 // --------------------------------------------------------------------------- 2993 // ATA/ATAPI driver : execute a data-out command 2994 // --------------------------------------------------------------------------- 2995 // returns 2996 // 0 : no error 2997 // 1 : BUSY bit set 2998 // 2 : read error 2999 // 3 : expected DRQ=1 3000 // 4 : no sectors left to read/verify 3001 // 5 : more sectors to read/verify 3002 // 6 : no sectors left to write 3003 // 7 : more sectors to write 3004 Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset) 3005 Bit16u device, command, count, cylinder, head, sector, segment, offset; 3006 Bit32u lba_low, lba_high; 3007 { 3008 Bit16u ebda_seg=read_word(0x0040,0x000E); 3009 Bit16u iobase1, iobase2, blksize; 3010 Bit8u channel, slave; 3011 Bit8u status, current, mode; 3012 3013 channel = device / 2; 3014 slave = device % 2; 3015 3016 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 3017 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2); 3018 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode); 3019 blksize = 0x200; // was = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize); 3020 if (mode == ATA_MODE_PIO32) blksize>>=2; 3021 else blksize>>=1; 3022 3023 // Reset count of transferred data 3024 write_word(ebda_seg, &EbdaData->ata.trsfsectors,0); 3025 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L); 3026 current = 0; 3027 3028 status = inb(iobase1 + ATA_CB_STAT); 3029 if (status & ATA_CB_STAT_BSY) return 1; 3030 3031 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); 3032 3033 // sector will be 0 only on lba access. Convert to lba-chs 3034 if (sector == 0) { 3035 if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) { 3036 outb(iobase1 + ATA_CB_FR, 0x00); 3037 outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff); 3038 outb(iobase1 + ATA_CB_SN, lba_low >> 24); 3039 outb(iobase1 + ATA_CB_CL, lba_high & 0xff); 3040 outb(iobase1 + ATA_CB_CH, lba_high >> 8); 3041 command |= 0x04; 3042 count &= (1UL << 8) - 1; 3043 lba_low &= (1UL << 24) - 1; 3044 } 3045 sector = (Bit16u) (lba_low & 0x000000ffL); 3046 cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL); 3047 head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA; 3048 } 3049 3050 outb(iobase1 + ATA_CB_FR, 0x00); 3051 outb(iobase1 + ATA_CB_SC, count); 3052 outb(iobase1 + ATA_CB_SN, sector); 3053 outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff); 3054 outb(iobase1 + ATA_CB_CH, cylinder >> 8); 3055 outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head ); 3056 outb(iobase1 + ATA_CB_CMD, command); 3057 3058 await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT); 3059 status = inb(iobase1 + ATA_CB_STAT); 3060 3061 if (status & ATA_CB_STAT_ERR) { 3062 BX_DEBUG_ATA("ata_cmd_data_out : read error\n"); 3063 return 2; 3064 } else if ( !(status & ATA_CB_STAT_DRQ) ) { 3065 BX_DEBUG_ATA("ata_cmd_data_out : DRQ not set (status %02x)\n", (unsigned) status); 3066 return 3; 3067 } 3068 3069 // FIXME : move seg/off translation here 3070 3071 ASM_START 3072 sti ;; enable higher priority interrupts 3073 ASM_END 3074 3075 while (1) { 3076 3077 ASM_START 3078 push bp 3079 mov bp, sp 3080 mov si, _ata_cmd_data_out.offset + 2[bp] 3081 mov ax, _ata_cmd_data_out.segment + 2[bp] 3082 mov cx, _ata_cmd_data_out.blksize + 2[bp] 3083 3084 ;; adjust if there will be an overrun. 2K max sector size 3085 cmp si, #0xf800 ;; 3086 jbe ata_out_no_adjust 3087 3088 ata_out_adjust: 3089 sub si, #0x0800 ;; sub 2 kbytes from offset 3090 add ax, #0x0080 ;; add 2 Kbytes to segment 3091 3092 ata_out_no_adjust: 3093 mov es, ax ;; segment in es 3094 3095 mov dx, _ata_cmd_data_out.iobase1 + 2[bp] ;; ATA data write port 3096 3097 mov ah, _ata_cmd_data_out.mode + 2[bp] 3098 cmp ah, #ATA_MODE_PIO32 3099 je ata_out_32 3100 3101 ata_out_16: 3102 seg ES 3103 rep 3104 outsw ;; CX words transfered from port(DX) to ES:[SI] 3105 jmp ata_out_done 3106 3107 ata_out_32: 3108 seg ES 3109 rep 3110 outsd ;; CX dwords transfered from port(DX) to ES:[SI] 3111 3112 ata_out_done: 3113 mov _ata_cmd_data_out.offset + 2[bp], si 3114 mov _ata_cmd_data_out.segment + 2[bp], es 3115 pop bp 3116 ASM_END 3117 3118 current++; 3119 write_word(ebda_seg, &EbdaData->ata.trsfsectors,current); 3120 count--; 3121 status = inb(iobase1 + ATA_CB_STAT); 3122 if (count == 0) { 3123 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 3124 != ATA_CB_STAT_RDY ) { 3125 BX_DEBUG_ATA("ata_cmd_data_out : no sectors left (status %02x)\n", (unsigned) status); 3126 return 6; 3127 } 3128 break; 3129 } 3130 else { 3131 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 3132 != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) { 3133 BX_DEBUG_ATA("ata_cmd_data_out : more sectors left (status %02x)\n", (unsigned) status); 3134 return 7; 3135 } 3136 continue; 3137 } 3138 } 3139 // Enable interrupts 3140 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15); 3141 return 0; 3142 } 3143 3144 // --------------------------------------------------------------------------- 3145 // ATA/ATAPI driver : execute a packet command 3146 // --------------------------------------------------------------------------- 3147 // returns 3148 // 0 : no error 3149 // 1 : error in parameters 3150 // 2 : BUSY bit set 3151 // 3 : error 3152 // 4 : not ready 3153 Bit16u ata_cmd_packet(device, cmdlen, cmdseg, cmdoff, header, length, inout, bufseg, bufoff) 3154 Bit8u cmdlen,inout; 3155 Bit16u device,cmdseg, cmdoff, bufseg, bufoff; 3156 Bit16u header; 3157 Bit32u length; 3158 { 3159 Bit16u ebda_seg=read_word(0x0040,0x000E); 3160 Bit16u iobase1, iobase2; 3161 Bit16u lcount, lbefore, lafter, count; 3162 Bit8u channel, slave; 3163 Bit8u status, mode, lmode; 3164 Bit32u total, transfer; 3165 3166 channel = device / 2; 3167 slave = device % 2; 3168 3169 // Data out is not supported yet 3170 if (inout == ATA_DATA_OUT) { 3171 BX_INFO("ata_cmd_packet: DATA_OUT not supported yet\n"); 3172 return 1; 3173 } 3174 3175 // The header length must be even 3176 if (header & 1) { 3177 BX_DEBUG_ATA("ata_cmd_packet : header must be even (%04x)\n",header); 3178 return 1; 3179 } 3180 3181 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 3182 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2); 3183 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode); 3184 transfer= 0L; 3185 3186 if (cmdlen < 12) cmdlen=12; 3187 if (cmdlen > 12) cmdlen=16; 3188 cmdlen>>=1; 3189 3190 // Reset count of transferred data 3191 write_word(ebda_seg, &EbdaData->ata.trsfsectors,0); 3192 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,0L); 3193 3194 status = inb(iobase1 + ATA_CB_STAT); 3195 if (status & ATA_CB_STAT_BSY) return 2; 3196 3197 outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); 3198 outb(iobase1 + ATA_CB_FR, 0x00); 3199 outb(iobase1 + ATA_CB_SC, 0x00); 3200 outb(iobase1 + ATA_CB_SN, 0x00); 3201 outb(iobase1 + ATA_CB_CL, 0xfff0 & 0x00ff); 3202 outb(iobase1 + ATA_CB_CH, 0xfff0 >> 8); 3203 outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0); 3204 outb(iobase1 + ATA_CB_CMD, ATA_CMD_PACKET); 3205 3206 // Device should ok to receive command 3207 await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT); 3208 status = inb(iobase1 + ATA_CB_STAT); 3209 3210 if (status & ATA_CB_STAT_ERR) { 3211 BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status); 3212 return 3; 3213 } else if ( !(status & ATA_CB_STAT_DRQ) ) { 3214 BX_DEBUG_ATA("ata_cmd_packet : DRQ not set (status %02x)\n", (unsigned) status); 3215 return 4; 3216 } 3217 3218 // Normalize address 3219 cmdseg += (cmdoff / 16); 3220 cmdoff %= 16; 3221 3222 // Send command to device 3223 ASM_START 3224 sti ;; enable higher priority interrupts 3225 3226 push bp 3227 mov bp, sp 3228 3229 mov si, _ata_cmd_packet.cmdoff + 2[bp] 3230 mov ax, _ata_cmd_packet.cmdseg + 2[bp] 3231 mov cx, _ata_cmd_packet.cmdlen + 2[bp] 3232 mov es, ax ;; segment in es 3233 3234 mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data write port 3235 3236 seg ES 3237 rep 3238 outsw ;; CX words transfered from port(DX) to ES:[SI] 3239 3240 pop bp 3241 ASM_END 3242 3243 if (inout == ATA_DATA_NO) { 3244 await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); 3245 status = inb(iobase1 + ATA_CB_STAT); 3246 } 3247 else { 3248 Bit16u loops = 0; 3249 Bit8u sc; 3250 while (1) { 3251 3252 if (loops == 0) {//first time through 3253 status = inb(iobase2 + ATA_CB_ASTAT); 3254 await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT); 3255 } 3256 else 3257 await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); 3258 loops++; 3259 3260 status = inb(iobase1 + ATA_CB_STAT); 3261 sc = inb(iobase1 + ATA_CB_SC); 3262 3263 // Check if command completed 3264 if(((inb(iobase1 + ATA_CB_SC)&0x7)==0x3) && 3265 ((status & (ATA_CB_STAT_RDY | ATA_CB_STAT_ERR)) == ATA_CB_STAT_RDY)) break; 3266 3267 if (status & ATA_CB_STAT_ERR) { 3268 BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status); 3269 return 3; 3270 } 3271 3272 // Normalize address 3273 bufseg += (bufoff / 16); 3274 bufoff %= 16; 3275 3276 // Get the byte count 3277 lcount = ((Bit16u)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL); 3278 3279 // adjust to read what we want 3280 if(header>lcount) { 3281 lbefore=lcount; 3282 header-=lcount; 3283 lcount=0; 3284 } 3285 else { 3286 lbefore=header; 3287 header=0; 3288 lcount-=lbefore; 3289 } 3290 3291 if(lcount>length) { 3292 lafter=lcount-length; 3293 lcount=length; 3294 length=0; 3295 } 3296 else { 3297 lafter=0; 3298 length-=lcount; 3299 } 3300 3301 // Save byte count 3302 count = lcount; 3303 3304 BX_DEBUG_ATA("Trying to read %04x bytes (%04x %04x %04x) ",lbefore+lcount+lafter,lbefore,lcount,lafter); 3305 BX_DEBUG_ATA("to 0x%04x:0x%04x\n",bufseg,bufoff); 3306 3307 // If counts not dividable by 4, use 16bits mode 3308 lmode = mode; 3309 if (lbefore & 0x03) lmode=ATA_MODE_PIO16; 3310 if (lcount & 0x03) lmode=ATA_MODE_PIO16; 3311 if (lafter & 0x03) lmode=ATA_MODE_PIO16; 3312 3313 // adds an extra byte if count are odd. before is always even 3314 if (lcount & 0x01) { 3315 lcount+=1; 3316 if ((lafter > 0) && (lafter & 0x01)) { 3317 lafter-=1; 3318 } 3319 } 3320 3321 if (lmode == ATA_MODE_PIO32) { 3322 lcount>>=2; lbefore>>=2; lafter>>=2; 3323 } 3324 else { 3325 lcount>>=1; lbefore>>=1; lafter>>=1; 3326 } 3327 3328 ; // FIXME bcc bug 3329 3330 ASM_START 3331 push bp 3332 mov bp, sp 3333 3334 mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data read port 3335 3336 mov cx, _ata_cmd_packet.lbefore + 2[bp] 3337 jcxz ata_packet_no_before 3338 3339 mov ah, _ata_cmd_packet.lmode + 2[bp] 3340 cmp ah, #ATA_MODE_PIO32 3341 je ata_packet_in_before_32 3342 3343 ata_packet_in_before_16: 3344 in ax, dx 3345 loop ata_packet_in_before_16 3346 jmp ata_packet_no_before 3347 3348 ata_packet_in_before_32: 3349 push eax 3350 ata_packet_in_before_32_loop: 3351 in eax, dx 3352 loop ata_packet_in_before_32_loop 3353 pop eax 3354 3355 ata_packet_no_before: 3356 mov cx, _ata_cmd_packet.lcount + 2[bp] 3357 jcxz ata_packet_after 3358 3359 mov di, _ata_cmd_packet.bufoff + 2[bp] 3360 mov ax, _ata_cmd_packet.bufseg + 2[bp] 3361 mov es, ax 3362 3363 mov ah, _ata_cmd_packet.lmode + 2[bp] 3364 cmp ah, #ATA_MODE_PIO32 3365 je ata_packet_in_32 3366 3367 ata_packet_in_16: 3368 rep 3369 insw ;; CX words transfered tp port(DX) to ES:[DI] 3370 jmp ata_packet_after 3371 3372 ata_packet_in_32: 3373 rep 3374 insd ;; CX dwords transfered to port(DX) to ES:[DI] 3375 3376 ata_packet_after: 3377 mov cx, _ata_cmd_packet.lafter + 2[bp] 3378 jcxz ata_packet_done 3379 3380 mov ah, _ata_cmd_packet.lmode + 2[bp] 3381 cmp ah, #ATA_MODE_PIO32 3382 je ata_packet_in_after_32 3383 3384 ata_packet_in_after_16: 3385 in ax, dx 3386 loop ata_packet_in_after_16 3387 jmp ata_packet_done 3388 3389 ata_packet_in_after_32: 3390 push eax 3391 ata_packet_in_after_32_loop: 3392 in eax, dx 3393 loop ata_packet_in_after_32_loop 3394 pop eax 3395 3396 ata_packet_done: 3397 pop bp 3398 ASM_END 3399 3400 // Compute new buffer address 3401 bufoff += count; 3402 3403 // Save transferred bytes count 3404 transfer += count; 3405 write_dword(ebda_seg, &EbdaData->ata.trsfbytes,transfer); 3406 } 3407 } 3408 3409 // Final check, device must be ready 3410 if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 3411 != ATA_CB_STAT_RDY ) { 3412 BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", (unsigned) status); 3413 return 4; 3414 } 3415 3416 // Enable interrupts 3417 outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15); 3418 return 0; 3419 } 3420 3421 // --------------------------------------------------------------------------- 3422 // End of ATA/ATAPI Driver 3423 // --------------------------------------------------------------------------- 3424 3425 // --------------------------------------------------------------------------- 3426 // Start of ATA/ATAPI generic functions 3427 // --------------------------------------------------------------------------- 3428 3429 Bit16u 3430 atapi_get_sense(device, seg, asc, ascq) 3431 Bit16u device; 3432 { 3433 Bit8u atacmd[12]; 3434 Bit8u buffer[18]; 3435 Bit8u i; 3436 3437 memsetb(get_SS(),atacmd,0,12); 3438 3439 // Request SENSE 3440 atacmd[0]=ATA_CMD_REQUEST_SENSE; 3441 atacmd[4]=sizeof(buffer); 3442 if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 18L, ATA_DATA_IN, get_SS(), buffer) != 0) 3443 return 0x0002; 3444 3445 write_byte(seg,asc,buffer[12]); 3446 write_byte(seg,ascq,buffer[13]); 3447 3448 return 0; 3449 } 3450 3451 Bit16u 3452 atapi_is_ready(device) 3453 Bit16u device; 3454 { 3455 Bit8u packet[12]; 3456 Bit8u buf[8]; 3457 Bit32u block_len; 3458 Bit32u sectors; 3459 Bit32u timeout; //measured in ms 3460 Bit32u time; 3461 Bit8u asc, ascq; 3462 Bit8u in_progress; 3463 Bit16u ebda_seg = read_word(0x0040,0x000E); 3464 if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_ATAPI) { 3465 printf("not implemented for non-ATAPI device\n"); 3466 return -1; 3467 } 3468 3469 BX_DEBUG_ATA("ata_detect_medium: begin\n"); 3470 memsetb(get_SS(),packet, 0, sizeof packet); 3471 packet[0] = 0x25; /* READ CAPACITY */ 3472 3473 /* Retry READ CAPACITY 50 times unless MEDIUM NOT PRESENT 3474 * is reported by the device. If the device reports "IN PROGRESS", 3475 * 30 seconds is added. */ 3476 timeout = 5000; 3477 time = 0; 3478 in_progress = 0; 3479 while (time < timeout) { 3480 if (ata_cmd_packet(device, sizeof(packet), get_SS(), packet, 0, 8L, ATA_DATA_IN, get_SS(), buf) == 0) 3481 goto ok; 3482 3483 if (atapi_get_sense(device, get_SS(), &asc, &ascq) == 0) { 3484 if (asc == 0x3a) { /* MEDIUM NOT PRESENT */ 3485 BX_DEBUG_ATA("Device reports MEDIUM NOT PRESENT\n"); 3486 return -1; 3487 } 3488 3489 if (asc == 0x04 && ascq == 0x01 && !in_progress) { 3490 /* IN PROGRESS OF BECOMING READY */ 3491 printf("Waiting for device to detect medium... "); 3492 /* Allow 30 seconds more */ 3493 timeout = 30000; 3494 in_progress = 1; 3495 } 3496 } 3497 time += 100; 3498 } 3499 BX_DEBUG_ATA("read capacity failed\n"); 3500 return -1; 3501 ok: 3502 3503 block_len = (Bit32u) buf[4] << 24 3504 | (Bit32u) buf[5] << 16 3505 | (Bit32u) buf[6] << 8 3506 | (Bit32u) buf[7] << 0; 3507 BX_DEBUG_ATA("block_len=%u\n", block_len); 3508 3509 if (block_len!= 2048 && block_len!= 512) 3510 { 3511 printf("Unsupported sector size %u\n", block_len); 3512 return -1; 3513 } 3514 write_dword(ebda_seg,&EbdaData->ata.devices[device].blksize, block_len); 3515 3516 sectors = (Bit32u) buf[0] << 24 3517 | (Bit32u) buf[1] << 16 3518 | (Bit32u) buf[2] << 8 3519 | (Bit32u) buf[3] << 0; 3520 3521 BX_DEBUG_ATA("sectors=%u\n", sectors); 3522 if (block_len == 2048) 3523 sectors <<= 2; /* # of sectors in 512-byte "soft" sector */ 3524 if (sectors != read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low)) 3525 printf("%dMB medium detected\n", sectors>>(20-9)); 3526 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors); 3527 return 0; 3528 } 3529 3530 Bit16u 3531 atapi_is_cdrom(device) 3532 Bit8u device; 3533 { 3534 Bit16u ebda_seg=read_word(0x0040,0x000E); 3535 3536 if (device >= BX_MAX_ATA_DEVICES) 3537 return 0; 3538 3539 if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_ATAPI) 3540 return 0; 3541 3542 if (read_byte(ebda_seg,&EbdaData->ata.devices[device].device) != ATA_DEVICE_CDROM) 3543 return 0; 3544 3545 return 1; 3546 } 3547 3548 // --------------------------------------------------------------------------- 3549 // End of ATA/ATAPI generic functions 3550 // --------------------------------------------------------------------------- 3551 3552 #endif // BX_USE_ATADRV 3553 3554 #if BX_ELTORITO_BOOT 3555 3556 // --------------------------------------------------------------------------- 3557 // Start of El-Torito boot functions 3558 // --------------------------------------------------------------------------- 3559 3560 void 3561 cdemu_init() 3562 { 3563 Bit16u ebda_seg=read_word(0x0040,0x000E); 3564 3565 // the only important data is this one for now 3566 write_byte(ebda_seg,&EbdaData->cdemu.active,0x00); 3567 } 3568 3569 Bit8u 3570 cdemu_isactive() 3571 { 3572 Bit16u ebda_seg=read_word(0x0040,0x000E); 3573 3574 return(read_byte(ebda_seg,&EbdaData->cdemu.active)); 3575 } 3576 3577 Bit8u 3578 cdemu_emulated_drive() 3579 { 3580 Bit16u ebda_seg=read_word(0x0040,0x000E); 3581 3582 return(read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)); 3583 } 3584 3585 static char isotag[6]="CD001"; 3586 static char eltorito[24]="EL TORITO SPECIFICATION"; 3587 // 3588 // Returns ah: emulated drive, al: error code 3589 // 3590 Bit16u 3591 cdrom_boot() 3592 { 3593 Bit16u ebda_seg=read_word(0x0040,0x000E); 3594 Bit8u atacmd[12], buffer[2048]; 3595 Bit32u lba; 3596 Bit16u boot_segment, nbsectors, i, error; 3597 Bit8u device; 3598 3599 // Find out the first cdrom 3600 for (device=0; device<BX_MAX_ATA_DEVICES;device++) { 3601 if (atapi_is_cdrom(device)) break; 3602 } 3603 3604 // if not found 3605 if(device >= BX_MAX_ATA_DEVICES) return 2; 3606 3607 if(error = atapi_is_ready(device) != 0) 3608 BX_INFO("ata_is_ready returned %d\n",error); 3609 3610 // Read the Boot Record Volume Descriptor 3611 memsetb(get_SS(),atacmd,0,12); 3612 atacmd[0]=0x28; // READ command 3613 atacmd[7]=(0x01 & 0xff00) >> 8; // Sectors 3614 atacmd[8]=(0x01 & 0x00ff); // Sectors 3615 atacmd[2]=(0x11 & 0xff000000) >> 24; // LBA 3616 atacmd[3]=(0x11 & 0x00ff0000) >> 16; 3617 atacmd[4]=(0x11 & 0x0000ff00) >> 8; 3618 atacmd[5]=(0x11 & 0x000000ff); 3619 if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0) 3620 return 3; 3621 3622 // Validity checks 3623 if(buffer[0]!=0)return 4; 3624 for(i=0;i<5;i++){ 3625 if(buffer[1+i]!=read_byte(0xf000,&isotag[i]))return 5; 3626 } 3627 for(i=0;i<23;i++) 3628 if(buffer[7+i]!=read_byte(0xf000,&eltorito[i]))return 6; 3629 3630 // ok, now we calculate the Boot catalog address 3631 lba=buffer[0x4A]*0x1000000+buffer[0x49]*0x10000+buffer[0x48]*0x100+buffer[0x47]; 3632 3633 // And we read the Boot Catalog 3634 memsetb(get_SS(),atacmd,0,12); 3635 atacmd[0]=0x28; // READ command 3636 atacmd[7]=(0x01 & 0xff00) >> 8; // Sectors 3637 atacmd[8]=(0x01 & 0x00ff); // Sectors 3638 atacmd[2]=(lba & 0xff000000) >> 24; // LBA 3639 atacmd[3]=(lba & 0x00ff0000) >> 16; 3640 atacmd[4]=(lba & 0x0000ff00) >> 8; 3641 atacmd[5]=(lba & 0x000000ff); 3642 if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0) 3643 return 7; 3644 3645 // Validation entry 3646 if(buffer[0x00]!=0x01)return 8; // Header 3647 if(buffer[0x01]!=0x00)return 9; // Platform 3648 if(buffer[0x1E]!=0x55)return 10; // key 1 3649 if(buffer[0x1F]!=0xAA)return 10; // key 2 3650 3651 // Initial/Default Entry 3652 if(buffer[0x20]!=0x88)return 11; // Bootable 3653 3654 write_byte(ebda_seg,&EbdaData->cdemu.media,buffer[0x21]); 3655 if(buffer[0x21]==0){ 3656 // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0. 3657 // Win2000 cd boot needs to know it booted from cd 3658 write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0xE0); 3659 } 3660 else if(buffer[0x21]<4) 3661 write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x00); 3662 else 3663 write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x80); 3664 3665 write_byte(ebda_seg,&EbdaData->cdemu.controller_index,device/2); 3666 write_byte(ebda_seg,&EbdaData->cdemu.device_spec,device%2); 3667 3668 boot_segment=buffer[0x23]*0x100+buffer[0x22]; 3669 if(boot_segment==0x0000)boot_segment=0x07C0; 3670 3671 write_word(ebda_seg,&EbdaData->cdemu.load_segment,boot_segment); 3672 write_word(ebda_seg,&EbdaData->cdemu.buffer_segment,0x0000); 3673 3674 nbsectors=buffer[0x27]*0x100+buffer[0x26]; 3675 write_word(ebda_seg,&EbdaData->cdemu.sector_count,nbsectors); 3676 3677 lba=buffer[0x2B]*0x1000000+buffer[0x2A]*0x10000+buffer[0x29]*0x100+buffer[0x28]; 3678 write_dword(ebda_seg,&EbdaData->cdemu.ilba,lba); 3679 3680 // And we read the image in memory 3681 memsetb(get_SS(),atacmd,0,12); 3682 atacmd[0]=0x28; // READ command 3683 atacmd[7]=((1+(nbsectors-1)/4) & 0xff00) >> 8; // Sectors 3684 atacmd[8]=((1+(nbsectors-1)/4) & 0x00ff); // Sectors 3685 atacmd[2]=(lba & 0xff000000) >> 24; // LBA 3686 atacmd[3]=(lba & 0x00ff0000) >> 16; 3687 atacmd[4]=(lba & 0x0000ff00) >> 8; 3688 atacmd[5]=(lba & 0x000000ff); 3689 if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, nbsectors*512L, ATA_DATA_IN, boot_segment,0)) != 0) 3690 return 12; 3691 3692 // Remember the media type 3693 switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) { 3694 case 0x01: // 1.2M floppy 3695 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,15); 3696 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80); 3697 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2); 3698 break; 3699 case 0x02: // 1.44M floppy 3700 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,18); 3701 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80); 3702 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2); 3703 break; 3704 case 0x03: // 2.88M floppy 3705 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,36); 3706 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,80); 3707 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,2); 3708 break; 3709 case 0x04: // Harddrive 3710 write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,read_byte(boot_segment,446+6)&0x3f); 3711 write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders, 3712 (read_byte(boot_segment,446+6)<<2) + read_byte(boot_segment,446+7) + 1); 3713 write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,read_byte(boot_segment,446+5) + 1); 3714 break; 3715 } 3716 3717 if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0) { 3718 // Increase bios installed hardware number of devices 3719 if(read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)==0x00) 3720 write_byte(0x40,0x10,read_byte(0x40,0x10)|0x41); 3721 else 3722 write_byte(ebda_seg, &EbdaData->ata.hdcount, read_byte(ebda_seg, &EbdaData->ata.hdcount) + 1); 3723 } 3724 3725 3726 // everything is ok, so from now on, the emulation is active 3727 if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0) 3728 write_byte(ebda_seg,&EbdaData->cdemu.active,0x01); 3729 3730 // return the boot drive + no error 3731 return (read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)*0x100)+0; 3732 } 3733 3734 // --------------------------------------------------------------------------- 3735 // End of El-Torito boot functions 3736 // --------------------------------------------------------------------------- 3737 #endif // BX_ELTORITO_BOOT 3738 3739 void 3740 int14_function(regs, ds, iret_addr) 3741 pusha_regs_t regs; // regs pushed from PUSHA instruction 3742 Bit16u ds; // previous DS:, DS set to 0x0000 by asm wrapper 3743 iret_addr_t iret_addr; // CS,IP,Flags pushed from original INT call 3744 { 3745 Bit16u addr,timer,val16; 3746 Bit8u timeout; 3747 3748 ASM_START 3749 sti 3750 ASM_END 3751 3752 addr = read_word(0x0040, (regs.u.r16.dx << 1)); 3753 timeout = read_byte(0x0040, 0x007C + regs.u.r16.dx); 3754 if ((regs.u.r16.dx < 4) && (addr > 0)) { 3755 switch (regs.u.r8.ah) { 3756 case 0: 3757 outb(addr+3, inb(addr+3) | 0x80); 3758 if (regs.u.r8.al & 0xE0 == 0) { 3759 outb(addr, 0x17); 3760 outb(addr+1, 0x04); 3761 } else { 3762 val16 = 0x600 >> ((regs.u.r8.al & 0xE0) >> 5); 3763 outb(addr, val16 & 0xFF); 3764 outb(addr+1, val16 >> 8); 3765 } 3766 outb(addr+3, regs.u.r8.al & 0x1F); 3767 regs.u.r8.ah = inb(addr+5); 3768 regs.u.r8.al = inb(addr+6); 3769 ClearCF(iret_addr.flags); 3770 break; 3771 case 1: 3772 timer = read_word(0x0040, 0x006C); 3773 while (((inb(addr+5) & 0x60) != 0x60) && (timeout)) { 3774 val16 = read_word(0x0040, 0x006C); 3775 if (val16 != timer) { 3776 timer = val16; 3777 timeout--; 3778 } 3779 } 3780 if (timeout) outb(addr, regs.u.r8.al); 3781 regs.u.r8.ah = inb(addr+5); 3782 if (!timeout) regs.u.r8.ah |= 0x80; 3783 ClearCF(iret_addr.flags); 3784 break; 3785 case 2: 3786 timer = read_word(0x0040, 0x006C); 3787 while (((inb(addr+5) & 0x01) == 0) && (timeout)) { 3788 val16 = read_word(0x0040, 0x006C); 3789 if (val16 != timer) { 3790 timer = val16; 3791 timeout--; 3792 } 3793 } 3794 if (timeout) { 3795 regs.u.r8.ah = 0; 3796 regs.u.r8.al = inb(addr); 3797 } else { 3798 regs.u.r8.ah = inb(addr+5); 3799 } 3800 ClearCF(iret_addr.flags); 3801 break; 3802 case 3: 3803 regs.u.r8.ah = inb(addr+5); 3804 regs.u.r8.al = inb(addr+6); 3805 ClearCF(iret_addr.flags); 3806 break; 3807 default: 3808 SetCF(iret_addr.flags); // Unsupported 3809 } 3810 } else { 3811 SetCF(iret_addr.flags); // Unsupported 3812 } 3813 } 3814 3815 void 3816 int15_function(regs, ES, DS, FLAGS) 3817 pusha_regs_t regs; // REGS pushed via pusha 3818 Bit16u ES, DS, FLAGS; 3819 { 3820 Bit16u ebda_seg=read_word(0x0040,0x000E); 3821 bx_bool prev_a20_enable; 3822 Bit16u base15_00; 3823 Bit8u base23_16; 3824 Bit16u ss; 3825 Bit16u CX,DX; 3826 3827 Bit16u bRegister; 3828 Bit8u irqDisable; 3829 3830 BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax); 3831 3832 switch (regs.u.r8.ah) { 3833 case 0x24: /* A20 Control */ 3834 switch (regs.u.r8.al) { 3835 case 0x00: 3836 set_enable_a20(0); 3837 CLEAR_CF(); 3838 regs.u.r8.ah = 0; 3839 break; 3840 case 0x01: 3841 set_enable_a20(1); 3842 CLEAR_CF(); 3843 regs.u.r8.ah = 0; 3844 break; 3845 case 0x02: 3846 regs.u.r8.al = (inb(0x92) >> 1) & 0x01; 3847 CLEAR_CF(); 3848 regs.u.r8.ah = 0; 3849 break; 3850 case 0x03: 3851 CLEAR_CF(); 3852 regs.u.r8.ah = 0; 3853 regs.u.r16.bx = 3; 3854 break; 3855 default: 3856 BX_INFO("int15: Func 24h, subfunc %02xh, A20 gate control not supported\n", (unsigned) regs.u.r8.al); 3857 SET_CF(); 3858 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3859 } 3860 break; 3861 3862 case 0x41: 3863 SET_CF(); 3864 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3865 break; 3866 3867 case 0x4f: 3868 /* keyboard intercept */ 3869 #if BX_CPU < 2 3870 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3871 #else 3872 // nop 3873 #endif 3874 SET_CF(); 3875 break; 3876 3877 case 0x52: // removable media eject 3878 CLEAR_CF(); 3879 regs.u.r8.ah = 0; // "ok ejection may proceed" 3880 break; 3881 3882 case 0x83: { 3883 if( regs.u.r8.al == 0 ) { 3884 // Set Interval requested. 3885 if( ( read_byte( 0x40, 0xA0 ) & 1 ) == 0 ) { 3886 // Interval not already set. 3887 write_byte( 0x40, 0xA0, 1 ); // Set status byte. 3888 write_word( 0x40, 0x98, ES ); // Byte location, segment 3889 write_word( 0x40, 0x9A, regs.u.r16.bx ); // Byte location, offset 3890 write_word( 0x40, 0x9C, regs.u.r16.dx ); // Low word, delay 3891 write_word( 0x40, 0x9E, regs.u.r16.cx ); // High word, delay. 3892 CLEAR_CF( ); 3893 irqDisable = inb( 0xA1 ); 3894 outb( 0xA1, irqDisable & 0xFE ); 3895 bRegister = inb_cmos( 0xB ); // Unmask IRQ8 so INT70 will get through. 3896 outb_cmos( 0xB, bRegister | 0x40 ); // Turn on the Periodic Interrupt timer 3897 } else { 3898 // Interval already set. 3899 BX_DEBUG_INT15("int15: Func 83h, failed, already waiting.\n" ); 3900 SET_CF(); 3901 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3902 } 3903 } else if( regs.u.r8.al == 1 ) { 3904 // Clear Interval requested 3905 write_byte( 0x40, 0xA0, 0 ); // Clear status byte 3906 CLEAR_CF( ); 3907 bRegister = inb_cmos( 0xB ); 3908 outb_cmos( 0xB, bRegister & ~0x40 ); // Turn off the Periodic Interrupt timer 3909 } else { 3910 BX_DEBUG_INT15("int15: Func 83h, failed.\n" ); 3911 SET_CF(); 3912 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 3913 regs.u.r8.al--; 3914 } 3915 3916 break; 3917 } 3918 3919 case 0x87: 3920 #if BX_CPU < 3 3921 # error "Int15 function 87h not supported on < 80386" 3922 #endif 3923 // +++ should probably have descriptor checks 3924 // +++ should have exception handlers 3925 3926 // turn off interrupts 3927 ASM_START 3928 cli 3929 ASM_END 3930 3931 prev_a20_enable = set_enable_a20(1); // enable A20 line 3932 3933 // 128K max of transfer on 386+ ??? 3934 // source == destination ??? 3935 3936 // ES:SI points to descriptor table 3937 // offset use initially comments 3938 // ============================================== 3939 // 00..07 Unused zeros Null descriptor 3940 // 08..0f GDT zeros filled in by BIOS 3941 // 10..17 source ssssssss source of data 3942 // 18..1f dest dddddddd destination of data 3943 // 20..27 CS zeros filled in by BIOS 3944 // 28..2f SS zeros filled in by BIOS 3945 3946 //es:si 3947 //eeee0 3948 //0ssss 3949 //----- 3950 3951 // check for access rights of source & dest here 3952 3953 // Initialize GDT descriptor 3954 base15_00 = (ES << 4) + regs.u.r16.si; 3955 base23_16 = ES >> 12; 3956 if (base15_00 < (ES<<4)) 3957 base23_16++; 3958 write_word(ES, regs.u.r16.si+0x08+0, 47); // limit 15:00 = 6 * 8bytes/descriptor 3959 write_word(ES, regs.u.r16.si+0x08+2, base15_00);// base 15:00 3960 write_byte(ES, regs.u.r16.si+0x08+4, base23_16);// base 23:16 3961 write_byte(ES, regs.u.r16.si+0x08+5, 0x93); // access 3962 write_word(ES, regs.u.r16.si+0x08+6, 0x0000); // base 31:24/reserved/limit 19:16 3963 3964 // Initialize CS descriptor 3965 write_word(ES, regs.u.r16.si+0x20+0, 0xffff);// limit 15:00 = normal 64K limit 3966 write_word(ES, regs.u.r16.si+0x20+2, 0x0000);// base 15:00 3967 write_byte(ES, regs.u.r16.si+0x20+4, 0x000f);// base 23:16 3968 write_byte(ES, regs.u.r16.si+0x20+5, 0x9b); // access 3969 write_word(ES, regs.u.r16.si+0x20+6, 0x0000);// base 31:24/reserved/limit 19:16 3970 3971 // Initialize SS descriptor 3972 ss = get_SS(); 3973 base15_00 = ss << 4; 3974 base23_16 = ss >> 12; 3975 write_word(ES, regs.u.r16.si+0x28+0, 0xffff); // limit 15:00 = normal 64K limit 3976 write_word(ES, regs.u.r16.si+0x28+2, base15_00);// base 15:00 3977 write_byte(ES, regs.u.r16.si+0x28+4, base23_16);// base 23:16 3978 write_byte(ES, regs.u.r16.si+0x28+5, 0x93); // access 3979 write_word(ES, regs.u.r16.si+0x28+6, 0x0000); // base 31:24/reserved/limit 19:16 3980 3981 CX = regs.u.r16.cx; 3982 ASM_START 3983 // Compile generates locals offset info relative to SP. 3984 // Get CX (word count) from stack. 3985 mov bx, sp 3986 SEG SS 3987 mov cx, _int15_function.CX [bx] 3988 3989 // since we need to set SS:SP, save them to the BDA 3990 // for future restore 3991 push eax 3992 xor eax, eax 3993 mov ds, ax 3994 mov 0x0469, ss 3995 mov 0x0467, sp 3996 3997 SEG ES 3998 lgdt [si + 0x08] 3999 SEG CS 4000 lidt [pmode_IDT_info] 4001 ;; perhaps do something with IDT here 4002 4003 ;; set PE bit in CR0 4004 mov eax, cr0 4005 or al, #0x01 4006 mov cr0, eax 4007 ;; far jump to flush CPU queue after transition to protected mode 4008 JMP_AP(0x0020, protected_mode) 4009 4010 protected_mode: 4011 ;; GDT points to valid descriptor table, now load SS, DS, ES 4012 mov ax, #0x28 ;; 101 000 = 5th descriptor in table, TI=GDT, RPL=00 4013 mov ss, ax 4014 mov ax, #0x10 ;; 010 000 = 2nd descriptor in table, TI=GDT, RPL=00 4015 mov ds, ax 4016 mov ax, #0x18 ;; 011 000 = 3rd descriptor in table, TI=GDT, RPL=00 4017 mov es, ax 4018 xor si, si 4019 xor di, di 4020 cld 4021 rep 4022 movsw ;; move CX words from DS:SI to ES:DI 4023 4024 ;; make sure DS and ES limits are 64KB 4025 mov ax, #0x28 4026 mov ds, ax 4027 mov es, ax 4028 4029 ;; reset PG bit in CR0 ??? 4030 mov eax, cr0 4031 and al, #0xFE 4032 mov cr0, eax 4033 4034 ;; far jump to flush CPU queue after transition to real mode 4035 JMP_AP(0xf000, real_mode) 4036 4037 real_mode: 4038 ;; restore IDT to normal real-mode defaults 4039 SEG CS 4040 lidt [rmode_IDT_info] 4041 4042 // restore SS:SP from the BDA 4043 xor ax, ax 4044 mov ds, ax 4045 mov ss, 0x0469 4046 mov sp, 0x0467 4047 pop eax 4048 ASM_END 4049 4050 set_enable_a20(prev_a20_enable); 4051 4052 // turn back on interrupts 4053 ASM_START 4054 sti 4055 ASM_END 4056 4057 regs.u.r8.ah = 0; 4058 CLEAR_CF(); 4059 break; 4060 4061 4062 case 0x88: 4063 // Get the amount of extended memory (above 1M) 4064 #if BX_CPU < 2 4065 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4066 SET_CF(); 4067 #else 4068 regs.u.r8.al = inb_cmos(0x30); 4069 regs.u.r8.ah = inb_cmos(0x31); 4070 4071 // According to Ralf Brown's interrupt the limit should be 15M, 4072 // but real machines mostly return max. 63M. 4073 if(regs.u.r16.ax > 0xffc0) 4074 regs.u.r16.ax = 0xffc0; 4075 4076 CLEAR_CF(); 4077 #endif 4078 break; 4079 4080 case 0x90: 4081 /* Device busy interrupt. Called by Int 16h when no key available */ 4082 break; 4083 4084 case 0x91: 4085 /* Interrupt complete. Called by Int 16h when key becomes available */ 4086 break; 4087 4088 case 0xbf: 4089 BX_INFO("*** int 15h function AH=bf not yet supported!\n"); 4090 SET_CF(); 4091 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4092 break; 4093 4094 case 0xC0: 4095 #if 0 4096 SET_CF(); 4097 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4098 break; 4099 #endif 4100 CLEAR_CF(); 4101 regs.u.r8.ah = 0; 4102 regs.u.r16.bx = BIOS_CONFIG_TABLE; 4103 ES = 0xF000; 4104 break; 4105 4106 case 0xc1: 4107 ES = ebda_seg; 4108 CLEAR_CF(); 4109 break; 4110 4111 case 0xd8: 4112 bios_printf(BIOS_PRINTF_DEBUG, "EISA BIOS not present\n"); 4113 SET_CF(); 4114 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4115 break; 4116 4117 default: 4118 BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n", 4119 (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx); 4120 SET_CF(); 4121 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4122 break; 4123 } 4124 } 4125 4126 #if BX_USE_PS2_MOUSE 4127 void 4128 int15_function_mouse(regs, ES, DS, FLAGS) 4129 pusha_regs_t regs; // REGS pushed via pusha 4130 Bit16u ES, DS, FLAGS; 4131 { 4132 Bit16u ebda_seg=read_word(0x0040,0x000E); 4133 Bit8u mouse_flags_1, mouse_flags_2; 4134 Bit16u mouse_driver_seg; 4135 Bit16u mouse_driver_offset; 4136 Bit8u comm_byte, prev_command_byte; 4137 Bit8u ret, mouse_data1, mouse_data2, mouse_data3; 4138 4139 BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax); 4140 4141 switch (regs.u.r8.ah) { 4142 case 0xC2: 4143 // Return Codes status in AH 4144 // ========================= 4145 // 00: success 4146 // 01: invalid subfunction (AL > 7) 4147 // 02: invalid input value (out of allowable range) 4148 // 03: interface error 4149 // 04: resend command received from mouse controller, 4150 // device driver should attempt command again 4151 // 05: cannot enable mouse, since no far call has been installed 4152 // 80/86: mouse service not implemented 4153 4154 switch (regs.u.r8.al) { 4155 case 0: // Disable/Enable Mouse 4156 BX_DEBUG_INT15("case 0:\n"); 4157 switch (regs.u.r8.bh) { 4158 case 0: // Disable Mouse 4159 BX_DEBUG_INT15("case 0: disable mouse\n"); 4160 inhibit_mouse_int_and_events(); // disable IRQ12 and packets 4161 ret = send_to_mouse_ctrl(0xF5); // disable mouse command 4162 if (ret == 0) { 4163 ret = get_mouse_data(&mouse_data1); 4164 if ( (ret == 0) || (mouse_data1 == 0xFA) ) { 4165 CLEAR_CF(); 4166 regs.u.r8.ah = 0; 4167 return; 4168 } 4169 } 4170 4171 // error 4172 SET_CF(); 4173 regs.u.r8.ah = ret; 4174 return; 4175 break; 4176 4177 case 1: // Enable Mouse 4178 BX_DEBUG_INT15("case 1: enable mouse\n"); 4179 mouse_flags_2 = read_byte(ebda_seg, 0x0027); 4180 if ( (mouse_flags_2 & 0x80) == 0 ) { 4181 BX_DEBUG_INT15("INT 15h C2 Enable Mouse, no far call handler\n"); 4182 SET_CF(); // error 4183 regs.u.r8.ah = 5; // no far call installed 4184 return; 4185 } 4186 inhibit_mouse_int_and_events(); // disable IRQ12 and packets 4187 ret = send_to_mouse_ctrl(0xF4); // enable mouse command 4188 if (ret == 0) { 4189 ret = get_mouse_data(&mouse_data1); 4190 if ( (ret == 0) && (mouse_data1 == 0xFA) ) { 4191 enable_mouse_int_and_events(); // turn IRQ12 and packet generation on 4192 CLEAR_CF(); 4193 regs.u.r8.ah = 0; 4194 return; 4195 } 4196 } 4197 SET_CF(); 4198 regs.u.r8.ah = ret; 4199 return; 4200 4201 default: // invalid subfunction 4202 BX_DEBUG_INT15("INT 15h C2 AL=0, BH=%02x\n", (unsigned) regs.u.r8.bh); 4203 SET_CF(); // error 4204 regs.u.r8.ah = 1; // invalid subfunction 4205 return; 4206 } 4207 break; 4208 4209 case 1: // Reset Mouse 4210 case 5: // Initialize Mouse 4211 BX_DEBUG_INT15("case 1 or 5:\n"); 4212 if (regs.u.r8.al == 5) { 4213 if (regs.u.r8.bh != 3) { 4214 SET_CF(); 4215 regs.u.r8.ah = 0x02; // invalid input 4216 return; 4217 } 4218 mouse_flags_2 = read_byte(ebda_seg, 0x0027); 4219 mouse_flags_2 = (mouse_flags_2 & 0x00) | regs.u.r8.bh; 4220 mouse_flags_1 = 0x00; 4221 write_byte(ebda_seg, 0x0026, mouse_flags_1); 4222 write_byte(ebda_seg, 0x0027, mouse_flags_2); 4223 } 4224 4225 inhibit_mouse_int_and_events(); // disable IRQ12 and packets 4226 ret = send_to_mouse_ctrl(0xFF); // reset mouse command 4227 if (ret == 0) { 4228 ret = get_mouse_data(&mouse_data3); 4229 // if no mouse attached, it will return RESEND 4230 if (mouse_data3 == 0xfe) { 4231 SET_CF(); 4232 return; 4233 } 4234 if (mouse_data3 != 0xfa) 4235 BX_PANIC("Mouse reset returned %02x (should be ack)\n", (unsigned)mouse_data3); 4236 if ( ret == 0 ) { 4237 ret = get_mouse_data(&mouse_data1); 4238 if ( ret == 0 ) { 4239 ret = get_mouse_data(&mouse_data2); 4240 if ( ret == 0 ) { 4241 // turn IRQ12 and packet generation on 4242 enable_mouse_int_and_events(); 4243 CLEAR_CF(); 4244 regs.u.r8.ah = 0; 4245 regs.u.r8.bl = mouse_data1; 4246 regs.u.r8.bh = mouse_data2; 4247 return; 4248 } 4249 } 4250 } 4251 } 4252 4253 // error 4254 SET_CF(); 4255 regs.u.r8.ah = ret; 4256 return; 4257 4258 case 2: // Set Sample Rate 4259 BX_DEBUG_INT15("case 2:\n"); 4260 switch (regs.u.r8.bh) { 4261 case 0: mouse_data1 = 10; break; // 10 reports/sec 4262 case 1: mouse_data1 = 20; break; // 20 reports/sec 4263 case 2: mouse_data1 = 40; break; // 40 reports/sec 4264 case 3: mouse_data1 = 60; break; // 60 reports/sec 4265 case 4: mouse_data1 = 80; break; // 80 reports/sec 4266 case 5: mouse_data1 = 100; break; // 100 reports/sec (default) 4267 case 6: mouse_data1 = 200; break; // 200 reports/sec 4268 default: mouse_data1 = 0; 4269 } 4270 if (mouse_data1 > 0) { 4271 ret = send_to_mouse_ctrl(0xF3); // set sample rate command 4272 if (ret == 0) { 4273 ret = get_mouse_data(&mouse_data2); 4274 ret = send_to_mouse_ctrl(mouse_data1); 4275 ret = get_mouse_data(&mouse_data2); 4276 CLEAR_CF(); 4277 regs.u.r8.ah = 0; 4278 } else { 4279 // error 4280 SET_CF(); 4281 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4282 } 4283 } else { 4284 // error 4285 SET_CF(); 4286 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4287 } 4288 break; 4289 4290 case 3: // Set Resolution 4291 BX_DEBUG_INT15("case 3:\n"); 4292 // BH: 4293 // 0 = 25 dpi, 1 count per millimeter 4294 // 1 = 50 dpi, 2 counts per millimeter 4295 // 2 = 100 dpi, 4 counts per millimeter 4296 // 3 = 200 dpi, 8 counts per millimeter 4297 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets 4298 if (regs.u.r8.bh < 4) { 4299 ret = send_to_mouse_ctrl(0xE8); // set resolution command 4300 if (ret == 0) { 4301 ret = get_mouse_data(&mouse_data1); 4302 if (mouse_data1 != 0xfa) 4303 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1); 4304 ret = send_to_mouse_ctrl(regs.u.r8.bh); 4305 ret = get_mouse_data(&mouse_data1); 4306 if (mouse_data1 != 0xfa) 4307 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1); 4308 CLEAR_CF(); 4309 regs.u.r8.ah = 0; 4310 } else { 4311 // error 4312 SET_CF(); 4313 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4314 } 4315 } else { 4316 // error 4317 SET_CF(); 4318 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4319 } 4320 set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable 4321 break; 4322 4323 case 4: // Get Device ID 4324 BX_DEBUG_INT15("case 4:\n"); 4325 inhibit_mouse_int_and_events(); // disable IRQ12 and packets 4326 ret = send_to_mouse_ctrl(0xF2); // get mouse ID command 4327 if (ret == 0) { 4328 ret = get_mouse_data(&mouse_data1); 4329 ret = get_mouse_data(&mouse_data2); 4330 CLEAR_CF(); 4331 regs.u.r8.ah = 0; 4332 regs.u.r8.bh = mouse_data2; 4333 } else { 4334 // error 4335 SET_CF(); 4336 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4337 } 4338 break; 4339 4340 case 6: // Return Status & Set Scaling Factor... 4341 BX_DEBUG_INT15("case 6:\n"); 4342 switch (regs.u.r8.bh) { 4343 case 0: // Return Status 4344 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets 4345 ret = send_to_mouse_ctrl(0xE9); // get mouse info command 4346 if (ret == 0) { 4347 ret = get_mouse_data(&mouse_data1); 4348 if (mouse_data1 != 0xfa) 4349 BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1); 4350 if (ret == 0) { 4351 ret = get_mouse_data(&mouse_data1); 4352 if ( ret == 0 ) { 4353 ret = get_mouse_data(&mouse_data2); 4354 if ( ret == 0 ) { 4355 ret = get_mouse_data(&mouse_data3); 4356 if ( ret == 0 ) { 4357 CLEAR_CF(); 4358 regs.u.r8.ah = 0; 4359 regs.u.r8.bl = mouse_data1; 4360 regs.u.r8.cl = mouse_data2; 4361 regs.u.r8.dl = mouse_data3; 4362 set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable 4363 return; 4364 } 4365 } 4366 } 4367 } 4368 } 4369 4370 // error 4371 SET_CF(); 4372 regs.u.r8.ah = ret; 4373 set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable 4374 return; 4375 4376 case 1: // Set Scaling Factor to 1:1 4377 case 2: // Set Scaling Factor to 2:1 4378 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets 4379 if (regs.u.r8.bh == 1) { 4380 ret = send_to_mouse_ctrl(0xE6); 4381 } else { 4382 ret = send_to_mouse_ctrl(0xE7); 4383 } 4384 if (ret == 0) { 4385 get_mouse_data(&mouse_data1); 4386 ret = (mouse_data1 != 0xFA); 4387 } 4388 if (ret == 0) { 4389 CLEAR_CF(); 4390 regs.u.r8.ah = 0; 4391 } else { 4392 // error 4393 SET_CF(); 4394 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4395 } 4396 set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable 4397 break; 4398 4399 default: 4400 BX_PANIC("INT 15h C2 AL=6, BH=%02x\n", (unsigned) regs.u.r8.bh); 4401 } 4402 break; 4403 4404 case 7: // Set Mouse Handler Address 4405 BX_DEBUG_INT15("case 7:\n"); 4406 mouse_driver_seg = ES; 4407 mouse_driver_offset = regs.u.r16.bx; 4408 write_word(ebda_seg, 0x0022, mouse_driver_offset); 4409 write_word(ebda_seg, 0x0024, mouse_driver_seg); 4410 mouse_flags_2 = read_byte(ebda_seg, 0x0027); 4411 if (mouse_driver_offset == 0 && mouse_driver_seg == 0) { 4412 /* remove handler */ 4413 if ( (mouse_flags_2 & 0x80) != 0 ) { 4414 mouse_flags_2 &= ~0x80; 4415 inhibit_mouse_int_and_events(); // disable IRQ12 and packets 4416 } 4417 } 4418 else { 4419 /* install handler */ 4420 mouse_flags_2 |= 0x80; 4421 } 4422 write_byte(ebda_seg, 0x0027, mouse_flags_2); 4423 CLEAR_CF(); 4424 regs.u.r8.ah = 0; 4425 break; 4426 4427 default: 4428 BX_DEBUG_INT15("case default:\n"); 4429 regs.u.r8.ah = 1; // invalid function 4430 SET_CF(); 4431 } 4432 break; 4433 4434 default: 4435 BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n", 4436 (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx); 4437 SET_CF(); 4438 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4439 break; 4440 } 4441 } 4442 #endif // BX_USE_PS2_MOUSE 4443 4444 4445 void set_e820_range(ES, DI, start, end, extra_start, extra_end, type) 4446 Bit16u ES; 4447 Bit16u DI; 4448 Bit32u start; 4449 Bit32u end; 4450 Bit8u extra_start; 4451 Bit8u extra_end; 4452 Bit16u type; 4453 { 4454 write_word(ES, DI, start); 4455 write_word(ES, DI+2, start >> 16); 4456 write_word(ES, DI+4, extra_start); 4457 write_word(ES, DI+6, 0x00); 4458 4459 end -= start; 4460 extra_end -= extra_start; 4461 write_word(ES, DI+8, end); 4462 write_word(ES, DI+10, end >> 16); 4463 write_word(ES, DI+12, extra_end); 4464 write_word(ES, DI+14, 0x0000); 4465 4466 write_word(ES, DI+16, type); 4467 write_word(ES, DI+18, 0x0); 4468 } 4469 4470 void 4471 int15_function32(regs, ES, DS, FLAGS) 4472 pushad_regs_t regs; // REGS pushed via pushad 4473 Bit16u ES, DS, FLAGS; 4474 { 4475 Bit32u extended_memory_size=0; // 64bits long 4476 Bit32u extra_lowbits_memory_size=0; 4477 Bit16u CX,DX; 4478 Bit8u extra_highbits_memory_size=0; 4479 4480 BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax); 4481 4482 switch (regs.u.r8.ah) { 4483 case 0x86: 4484 // Wait for CX:DX microseconds. currently using the 4485 // refresh request port 0x61 bit4, toggling every 15usec 4486 4487 CX = regs.u.r16.cx; 4488 DX = regs.u.r16.dx; 4489 4490 ASM_START 4491 sti 4492 4493 ;; Get the count in eax 4494 mov bx, sp 4495 SEG SS 4496 mov ax, _int15_function32.CX [bx] 4497 shl eax, #16 4498 SEG SS 4499 mov ax, _int15_function32.DX [bx] 4500 4501 ;; convert to numbers of 15usec ticks 4502 mov ebx, #15 4503 xor edx, edx 4504 div eax, ebx 4505 mov ecx, eax 4506 4507 ;; wait for ecx number of refresh requests 4508 in al, #0x61 4509 and al,#0x10 4510 mov ah, al 4511 4512 or ecx, ecx 4513 je int1586_tick_end 4514 int1586_tick: 4515 in al, #0x61 4516 and al,#0x10 4517 cmp al, ah 4518 je int1586_tick 4519 mov ah, al 4520 dec ecx 4521 jnz int1586_tick 4522 int1586_tick_end: 4523 ASM_END 4524 4525 break; 4526 4527 case 0xe8: 4528 switch(regs.u.r8.al) 4529 { 4530 case 0x20: // coded by osmaker aka K.J. 4531 if(regs.u.r32.edx == 0x534D4150) 4532 { 4533 extended_memory_size = inb_cmos(0x35); 4534 extended_memory_size <<= 8; 4535 extended_memory_size |= inb_cmos(0x34); 4536 extended_memory_size *= 64; 4537 // greater than EFF00000??? 4538 if(extended_memory_size > 0x3bc000) { 4539 extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000 4540 } 4541 extended_memory_size *= 1024; 4542 extended_memory_size += (16L * 1024 * 1024); 4543 4544 if(extended_memory_size <= (16L * 1024 * 1024)) { 4545 extended_memory_size = inb_cmos(0x31); 4546 extended_memory_size <<= 8; 4547 extended_memory_size |= inb_cmos(0x30); 4548 extended_memory_size *= 1024; 4549 extended_memory_size += (1L * 1024 * 1024); 4550 } 4551 4552 extra_lowbits_memory_size = inb_cmos(0x5c); 4553 extra_lowbits_memory_size <<= 8; 4554 extra_lowbits_memory_size |= inb_cmos(0x5b); 4555 extra_lowbits_memory_size *= 64; 4556 extra_lowbits_memory_size *= 1024; 4557 extra_highbits_memory_size = inb_cmos(0x5d); 4558 4559 switch(regs.u.r16.bx) 4560 { 4561 case 0: 4562 set_e820_range(ES, regs.u.r16.di, 4563 0x0000000L, 0x0009f000L, 0, 0, 1); 4564 regs.u.r32.ebx = 1; 4565 break; 4566 case 1: 4567 set_e820_range(ES, regs.u.r16.di, 4568 0x0009f000L, 0x000a0000L, 0, 0, 2); 4569 regs.u.r32.ebx = 2; 4570 break; 4571 case 2: 4572 set_e820_range(ES, regs.u.r16.di, 4573 0x000e8000L, 0x00100000L, 0, 0, 2); 4574 regs.u.r32.ebx = 3; 4575 break; 4576 case 3: 4577 #if BX_ROMBIOS32 4578 set_e820_range(ES, regs.u.r16.di, 4579 0x00100000L, 4580 extended_memory_size - ACPI_DATA_SIZE ,0, 0, 1); 4581 regs.u.r32.ebx = 4; 4582 #else 4583 set_e820_range(ES, regs.u.r16.di, 4584 0x00100000L, 4585 extended_memory_size, 1); 4586 regs.u.r32.ebx = 5; 4587 #endif 4588 break; 4589 case 4: 4590 set_e820_range(ES, regs.u.r16.di, 4591 extended_memory_size - ACPI_DATA_SIZE, 4592 extended_memory_size ,0, 0, 3); // ACPI RAM 4593 regs.u.r32.ebx = 5; 4594 break; 4595 case 5: 4596 /* 256KB BIOS area at the end of 4 GB */ 4597 set_e820_range(ES, regs.u.r16.di, 4598 0xfffc0000L, 0x00000000L ,0, 0, 2); 4599 if (extra_highbits_memory_size || extra_lowbits_memory_size) 4600 regs.u.r32.ebx = 6; 4601 else 4602 regs.u.r32.ebx = 0; 4603 break; 4604 case 6: 4605 /* Maping of memory above 4 GB */ 4606 set_e820_range(ES, regs.u.r16.di, 0x00000000L, 4607 extra_lowbits_memory_size, 1, extra_highbits_memory_size 4608 + 1, 1); 4609 regs.u.r32.ebx = 0; 4610 break; 4611 default: /* AX=E820, DX=534D4150, BX unrecognized */ 4612 goto int15_unimplemented; 4613 break; 4614 } 4615 regs.u.r32.eax = 0x534D4150; 4616 regs.u.r32.ecx = 0x14; 4617 CLEAR_CF(); 4618 } else { 4619 // if DX != 0x534D4150) 4620 goto int15_unimplemented; 4621 } 4622 break; 4623 4624 case 0x01: 4625 // do we have any reason to fail here ? 4626 CLEAR_CF(); 4627 4628 // my real system sets ax and bx to 0 4629 // this is confirmed by Ralph Brown list 4630 // but syslinux v1.48 is known to behave 4631 // strangely if ax is set to 0 4632 // regs.u.r16.ax = 0; 4633 // regs.u.r16.bx = 0; 4634 4635 // Get the amount of extended memory (above 1M) 4636 regs.u.r8.cl = inb_cmos(0x30); 4637 regs.u.r8.ch = inb_cmos(0x31); 4638 4639 // limit to 15M 4640 if(regs.u.r16.cx > 0x3c00) 4641 { 4642 regs.u.r16.cx = 0x3c00; 4643 } 4644 4645 // Get the amount of extended memory above 16M in 64k blocs 4646 regs.u.r8.dl = inb_cmos(0x34); 4647 regs.u.r8.dh = inb_cmos(0x35); 4648 4649 // Set configured memory equal to extended memory 4650 regs.u.r16.ax = regs.u.r16.cx; 4651 regs.u.r16.bx = regs.u.r16.dx; 4652 break; 4653 default: /* AH=0xE8?? but not implemented */ 4654 goto int15_unimplemented; 4655 } 4656 break; 4657 int15_unimplemented: 4658 // fall into the default 4659 default: 4660 BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n", 4661 (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx); 4662 SET_CF(); 4663 regs.u.r8.ah = UNSUPPORTED_FUNCTION; 4664 break; 4665 } 4666 } 4667 4668 void 4669 int16_function(DI, SI, BP, SP, BX, DX, CX, AX, FLAGS) 4670 Bit16u DI, SI, BP, SP, BX, DX, CX, AX, FLAGS; 4671 { 4672 Bit8u scan_code, ascii_code, shift_flags, led_flags, count; 4673 Bit16u kbd_code, max; 4674 4675 BX_DEBUG_INT16("int16: AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX); 4676 4677 shift_flags = read_byte(0x0040, 0x17); 4678 led_flags = read_byte(0x0040, 0x97); 4679 if ((((shift_flags >> 4) & 0x07) ^ (led_flags & 0x07)) != 0) { 4680 ASM_START 4681 cli 4682 ASM_END 4683 outb(0x60, 0xed); 4684 while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21); 4685 if ((inb(0x60) == 0xfa)) { 4686 led_flags &= 0xf8; 4687 led_flags |= ((shift_flags >> 4) & 0x07); 4688 outb(0x60, led_flags & 0x07); 4689 while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21); 4690 inb(0x60); 4691 write_byte(0x0040, 0x97, led_flags); 4692 } 4693 ASM_START 4694 sti 4695 ASM_END 4696 } 4697 4698 switch (GET_AH()) { 4699 case 0x00: /* read keyboard input */ 4700 4701 if ( !dequeue_key(&scan_code, &ascii_code, 1) ) { 4702 BX_PANIC("KBD: int16h: out of keyboard input\n"); 4703 } 4704 if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0; 4705 else if (ascii_code == 0xE0) ascii_code = 0; 4706 AX = (scan_code << 8) | ascii_code; 4707 break; 4708 4709 case 0x01: /* check keyboard status */ 4710 if ( !dequeue_key(&scan_code, &ascii_code, 0) ) { 4711 SET_ZF(); 4712 return; 4713 } 4714 if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0; 4715 else if (ascii_code == 0xE0) ascii_code = 0; 4716 AX = (scan_code << 8) | ascii_code; 4717 CLEAR_ZF(); 4718 break; 4719 4720 case 0x02: /* get shift flag status */ 4721 shift_flags = read_byte(0x0040, 0x17); 4722 SET_AL(shift_flags); 4723 break; 4724 4725 case 0x05: /* store key-stroke into buffer */ 4726 if ( !enqueue_key(GET_CH(), GET_CL()) ) { 4727 SET_AL(1); 4728 } 4729 else { 4730 SET_AL(0); 4731 } 4732 break; 4733 4734 case 0x09: /* GET KEYBOARD FUNCTIONALITY */ 4735 // bit Bochs Description 4736 // 7 0 reserved 4737 // 6 0 INT 16/AH=20h-22h supported (122-key keyboard support) 4738 // 5 1 INT 16/AH=10h-12h supported (enhanced keyboard support) 4739 // 4 1 INT 16/AH=0Ah supported 4740 // 3 0 INT 16/AX=0306h supported 4741 // 2 0 INT 16/AX=0305h supported 4742 // 1 0 INT 16/AX=0304h supported 4743 // 0 0 INT 16/AX=0300h supported 4744 // 4745 SET_AL(0x30); 4746 break; 4747 4748 case 0x0A: /* GET KEYBOARD ID */ 4749 count = 2; 4750 kbd_code = 0x0; 4751 outb(0x60, 0xf2); 4752 /* Wait for data */ 4753 max=0xffff; 4754 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x00); 4755 if (max>0x0) { 4756 if ((inb(0x60) == 0xfa)) { 4757 do { 4758 max=0xffff; 4759 while ( ((inb(0x64) & 0x01) == 0) && (--max>0) ) outb(0x80, 0x00); 4760 if (max>0x0) { 4761 kbd_code >>= 8; 4762 kbd_code |= (inb(0x60) << 8); 4763 } 4764 } while (--count>0); 4765 } 4766 } 4767 BX=kbd_code; 4768 break; 4769 4770 case 0x10: /* read MF-II keyboard input */ 4771 4772 if ( !dequeue_key(&scan_code, &ascii_code, 1) ) { 4773 BX_PANIC("KBD: int16h: out of keyboard input\n"); 4774 } 4775 if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0; 4776 AX = (scan_code << 8) | ascii_code; 4777 break; 4778 4779 case 0x11: /* check MF-II keyboard status */ 4780 if ( !dequeue_key(&scan_code, &ascii_code, 0) ) { 4781 SET_ZF(); 4782 return; 4783 } 4784 if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0; 4785 AX = (scan_code << 8) | ascii_code; 4786 CLEAR_ZF(); 4787 break; 4788 4789 case 0x12: /* get extended keyboard status */ 4790 shift_flags = read_byte(0x0040, 0x17); 4791 SET_AL(shift_flags); 4792 shift_flags = read_byte(0x0040, 0x18) & 0x73; 4793 shift_flags |= read_byte(0x0040, 0x96) & 0x0c; 4794 SET_AH(shift_flags); 4795 BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX); 4796 break; 4797 4798 case 0x92: /* keyboard capability check called by DOS 5.0+ keyb */ 4799 SET_AH(0x80); // function int16 ah=0x10-0x12 supported 4800 break; 4801 4802 case 0xA2: /* 122 keys capability check called by DOS 5.0+ keyb */ 4803 // don't change AH : function int16 ah=0x20-0x22 NOT supported 4804 break; 4805 4806 case 0x6F: 4807 if (GET_AL() == 0x08) 4808 SET_AH(0x02); // unsupported, aka normal keyboard 4809 4810 default: 4811 BX_INFO("KBD: unsupported int 16h function %02x\n", GET_AH()); 4812 } 4813 } 4814 4815 unsigned int 4816 dequeue_key(scan_code, ascii_code, incr) 4817 Bit8u *scan_code; 4818 Bit8u *ascii_code; 4819 unsigned int incr; 4820 { 4821 Bit16u buffer_start, buffer_end, buffer_head, buffer_tail; 4822 Bit16u ss; 4823 Bit8u acode, scode; 4824 4825 #if BX_CPU < 2 4826 buffer_start = 0x001E; 4827 buffer_end = 0x003E; 4828 #else 4829 buffer_start = read_word(0x0040, 0x0080); 4830 buffer_end = read_word(0x0040, 0x0082); 4831 #endif 4832 4833 buffer_head = read_word(0x0040, 0x001a); 4834 buffer_tail = read_word(0x0040, 0x001c); 4835 4836 if (buffer_head != buffer_tail) { 4837 ss = get_SS(); 4838 acode = read_byte(0x0040, buffer_head); 4839 scode = read_byte(0x0040, buffer_head+1); 4840 write_byte(ss, ascii_code, acode); 4841 write_byte(ss, scan_code, scode); 4842 4843 if (incr) { 4844 buffer_head += 2; 4845 if (buffer_head >= buffer_end) 4846 buffer_head = buffer_start; 4847 write_word(0x0040, 0x001a, buffer_head); 4848 } 4849 return(1); 4850 } 4851 else { 4852 return(0); 4853 } 4854 } 4855 4856 static char panic_msg_keyb_buffer_full[] = "%s: keyboard input buffer full\n"; 4857 4858 Bit8u 4859 inhibit_mouse_int_and_events() 4860 { 4861 Bit8u command_byte, prev_command_byte; 4862 4863 // Turn off IRQ generation and aux data line 4864 if ( inb(0x64) & 0x02 ) 4865 BX_PANIC(panic_msg_keyb_buffer_full,"inhibmouse"); 4866 outb(0x64, 0x20); // get command byte 4867 while ( (inb(0x64) & 0x01) != 0x01 ); 4868 prev_command_byte = inb(0x60); 4869 command_byte = prev_command_byte; 4870 //while ( (inb(0x64) & 0x02) ); 4871 if ( inb(0x64) & 0x02 ) 4872 BX_PANIC(panic_msg_keyb_buffer_full,"inhibmouse"); 4873 command_byte &= 0xfd; // turn off IRQ 12 generation 4874 command_byte |= 0x20; // disable mouse serial clock line 4875 outb(0x64, 0x60); // write command byte 4876 outb(0x60, command_byte); 4877 return(prev_command_byte); 4878 } 4879 4880 void 4881 enable_mouse_int_and_events() 4882 { 4883 Bit8u command_byte; 4884 4885 // Turn on IRQ generation and aux data line 4886 if ( inb(0x64) & 0x02 ) 4887 BX_PANIC(panic_msg_keyb_buffer_full,"enabmouse"); 4888 outb(0x64, 0x20); // get command byte 4889 while ( (inb(0x64) & 0x01) != 0x01 ); 4890 command_byte = inb(0x60); 4891 //while ( (inb(0x64) & 0x02) ); 4892 if ( inb(0x64) & 0x02 ) 4893 BX_PANIC(panic_msg_keyb_buffer_full,"enabmouse"); 4894 command_byte |= 0x02; // turn on IRQ 12 generation 4895 command_byte &= 0xdf; // enable mouse serial clock line 4896 outb(0x64, 0x60); // write command byte 4897 outb(0x60, command_byte); 4898 } 4899 4900 Bit8u 4901 send_to_mouse_ctrl(sendbyte) 4902 Bit8u sendbyte; 4903 { 4904 Bit8u response; 4905 4906 // wait for chance to write to ctrl 4907 if ( inb(0x64) & 0x02 ) 4908 BX_PANIC(panic_msg_keyb_buffer_full,"sendmouse"); 4909 outb(0x64, 0xD4); 4910 outb(0x60, sendbyte); 4911 return(0); 4912 } 4913 4914 4915 Bit8u 4916 get_mouse_data(data) 4917 Bit8u *data; 4918 { 4919 Bit8u response; 4920 Bit16u ss; 4921 4922 while ( (inb(0x64) & 0x21) != 0x21 ) { 4923 } 4924 4925 response = inb(0x60); 4926 4927 ss = get_SS(); 4928 write_byte(ss, data, response); 4929 return(0); 4930 } 4931 4932 void 4933 set_kbd_command_byte(command_byte) 4934 Bit8u command_byte; 4935 { 4936 if ( inb(0x64) & 0x02 ) 4937 BX_PANIC(panic_msg_keyb_buffer_full,"setkbdcomm"); 4938 outb(0x64, 0xD4); 4939 4940 outb(0x64, 0x60); // write command byte 4941 outb(0x60, command_byte); 4942 } 4943 4944 void 4945 int09_function(DI, SI, BP, SP, BX, DX, CX, AX) 4946 Bit16u DI, SI, BP, SP, BX, DX, CX, AX; 4947 { 4948 Bit8u scancode, asciicode, shift_flags; 4949 Bit8u mf2_flags, mf2_state; 4950 4951 // 4952 // DS has been set to F000 before call 4953 // 4954 4955 4956 scancode = GET_AL(); 4957 4958 if (scancode == 0) { 4959 BX_INFO("KBD: int09 handler: AL=0\n"); 4960 return; 4961 } 4962 4963 4964 shift_flags = read_byte(0x0040, 0x17); 4965 mf2_flags = read_byte(0x0040, 0x18); 4966 mf2_state = read_byte(0x0040, 0x96); 4967 asciicode = 0; 4968 4969 switch (scancode) { 4970 case 0x3a: /* Caps Lock press */ 4971 shift_flags ^= 0x40; 4972 write_byte(0x0040, 0x17, shift_flags); 4973 mf2_flags |= 0x40; 4974 write_byte(0x0040, 0x18, mf2_flags); 4975 break; 4976 case 0xba: /* Caps Lock release */ 4977 mf2_flags &= ~0x40; 4978 write_byte(0x0040, 0x18, mf2_flags); 4979 break; 4980 4981 case 0x2a: /* L Shift press */ 4982 shift_flags |= 0x02; 4983 write_byte(0x0040, 0x17, shift_flags); 4984 break; 4985 case 0xaa: /* L Shift release */ 4986 shift_flags &= ~0x02; 4987 write_byte(0x0040, 0x17, shift_flags); 4988 break; 4989 4990 case 0x36: /* R Shift press */ 4991 shift_flags |= 0x01; 4992 write_byte(0x0040, 0x17, shift_flags); 4993 break; 4994 case 0xb6: /* R Shift release */ 4995 shift_flags &= ~0x01; 4996 write_byte(0x0040, 0x17, shift_flags); 4997 break; 4998 4999 case 0x1d: /* Ctrl press */ 5000 if ((mf2_state & 0x01) == 0) { 5001 shift_flags |= 0x04; 5002 write_byte(0x0040, 0x17, shift_flags); 5003 if (mf2_state & 0x02) { 5004 mf2_state |= 0x04; 5005 write_byte(0x0040, 0x96, mf2_state); 5006 } else { 5007 mf2_flags |= 0x01; 5008 write_byte(0x0040, 0x18, mf2_flags); 5009 } 5010 } 5011 break; 5012 case 0x9d: /* Ctrl release */ 5013 if ((mf2_state & 0x01) == 0) { 5014 shift_flags &= ~0x04; 5015 write_byte(0x0040, 0x17, shift_flags); 5016 if (mf2_state & 0x02) { 5017 mf2_state &= ~0x04; 5018 write_byte(0x0040, 0x96, mf2_state); 5019 } else { 5020 mf2_flags &= ~0x01; 5021 write_byte(0x0040, 0x18, mf2_flags); 5022 } 5023 } 5024 break; 5025 5026 case 0x38: /* Alt press */ 5027 shift_flags |= 0x08; 5028 write_byte(0x0040, 0x17, shift_flags); 5029 if (mf2_state & 0x02) { 5030 mf2_state |= 0x08; 5031 write_byte(0x0040, 0x96, mf2_state); 5032 } else { 5033 mf2_flags |= 0x02; 5034 write_byte(0x0040, 0x18, mf2_flags); 5035 } 5036 break; 5037 case 0xb8: /* Alt release */ 5038 shift_flags &= ~0x08; 5039 write_byte(0x0040, 0x17, shift_flags); 5040 if (mf2_state & 0x02) { 5041 mf2_state &= ~0x08; 5042 write_byte(0x0040, 0x96, mf2_state); 5043 } else { 5044 mf2_flags &= ~0x02; 5045 write_byte(0x0040, 0x18, mf2_flags); 5046 } 5047 break; 5048 5049 case 0x45: /* Num Lock press */ 5050 if ((mf2_state & 0x03) == 0) { 5051 mf2_flags |= 0x20; 5052 write_byte(0x0040, 0x18, mf2_flags); 5053 shift_flags ^= 0x20; 5054 write_byte(0x0040, 0x17, shift_flags); 5055 } 5056 break; 5057 case 0xc5: /* Num Lock release */ 5058 if ((mf2_state & 0x03) == 0) { 5059 mf2_flags &= ~0x20; 5060 write_byte(0x0040, 0x18, mf2_flags); 5061 } 5062 break; 5063 5064 case 0x46: /* Scroll Lock press */ 5065 mf2_flags |= 0x10; 5066 write_byte(0x0040, 0x18, mf2_flags); 5067 shift_flags ^= 0x10; 5068 write_byte(0x0040, 0x17, shift_flags); 5069 break; 5070 5071 case 0xc6: /* Scroll Lock release */ 5072 mf2_flags &= ~0x10; 5073 write_byte(0x0040, 0x18, mf2_flags); 5074 break; 5075 5076 default: 5077 if (scancode & 0x80) { 5078 break; /* toss key releases ... */ 5079 } 5080 if (scancode > MAX_SCAN_CODE) { 5081 BX_INFO("KBD: int09h_handler(): unknown scancode read: 0x%02x!\n", scancode); 5082 return; 5083 } 5084 if (shift_flags & 0x08) { /* ALT */ 5085 asciicode = scan_to_scanascii[scancode].alt; 5086 scancode = scan_to_scanascii[scancode].alt >> 8; 5087 } else if (shift_flags & 0x04) { /* CONTROL */ 5088 asciicode = scan_to_scanascii[scancode].control; 5089 scancode = scan_to_scanascii[scancode].control >> 8; 5090 } else if (((mf2_state & 0x02) > 0) && ((scancode >= 0x47) && (scancode <= 0x53))) { 5091 /* extended keys handling */ 5092 asciicode = 0xe0; 5093 scancode = scan_to_scanascii[scancode].normal >> 8; 5094 } else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */ 5095 /* check if lock state should be ignored 5096 * because a SHIFT key are pressed */ 5097 5098 if (shift_flags & scan_to_scanascii[scancode].lock_flags) { 5099 asciicode = scan_to_scanascii[scancode].normal; 5100 scancode = scan_to_scanascii[scancode].normal >> 8; 5101 } else { 5102 asciicode = scan_to_scanascii[scancode].shift; 5103 scancode = scan_to_scanascii[scancode].shift >> 8; 5104 } 5105 } else { 5106 /* check if lock is on */ 5107 if (shift_flags & scan_to_scanascii[scancode].lock_flags) { 5108 asciicode = scan_to_scanascii[scancode].shift; 5109 scancode = scan_to_scanascii[scancode].shift >> 8; 5110 } else { 5111 asciicode = scan_to_scanascii[scancode].normal; 5112 scancode = scan_to_scanascii[scancode].normal >> 8; 5113 } 5114 } 5115 if (scancode==0 && asciicode==0) { 5116 BX_INFO("KBD: int09h_handler(): scancode & asciicode are zero?\n"); 5117 } 5118 enqueue_key(scancode, asciicode); 5119 break; 5120 } 5121 if ((scancode & 0x7f) != 0x1d) { 5122 mf2_state &= ~0x01; 5123 } 5124 mf2_state &= ~0x02; 5125 write_byte(0x0040, 0x96, mf2_state); 5126 } 5127 5128 unsigned int 5129 enqueue_key(scan_code, ascii_code) 5130 Bit8u scan_code, ascii_code; 5131 { 5132 Bit16u buffer_start, buffer_end, buffer_head, buffer_tail, temp_tail; 5133 5134 #if BX_CPU < 2 5135 buffer_start = 0x001E; 5136 buffer_end = 0x003E; 5137 #else 5138 buffer_start = read_word(0x0040, 0x0080); 5139 buffer_end = read_word(0x0040, 0x0082); 5140 #endif 5141 5142 buffer_head = read_word(0x0040, 0x001A); 5143 buffer_tail = read_word(0x0040, 0x001C); 5144 5145 temp_tail = buffer_tail; 5146 buffer_tail += 2; 5147 if (buffer_tail >= buffer_end) 5148 buffer_tail = buffer_start; 5149 5150 if (buffer_tail == buffer_head) { 5151 return(0); 5152 } 5153 5154 write_byte(0x0040, temp_tail, ascii_code); 5155 write_byte(0x0040, temp_tail+1, scan_code); 5156 write_word(0x0040, 0x001C, buffer_tail); 5157 return(1); 5158 } 5159 5160 5161 void 5162 int74_function(make_farcall, Z, Y, X, status) 5163 Bit16u make_farcall, Z, Y, X, status; 5164 { 5165 Bit16u ebda_seg=read_word(0x0040,0x000E); 5166 Bit8u in_byte, index, package_count; 5167 Bit8u mouse_flags_1, mouse_flags_2; 5168 5169 BX_DEBUG_INT74("entering int74_function\n"); 5170 make_farcall = 0; 5171 5172 in_byte = inb(0x64); 5173 if ( (in_byte & 0x21) != 0x21 ) { 5174 return; 5175 } 5176 in_byte = inb(0x60); 5177 BX_DEBUG_INT74("int74: read byte %02x\n", in_byte); 5178 5179 mouse_flags_1 = read_byte(ebda_seg, 0x0026); 5180 mouse_flags_2 = read_byte(ebda_seg, 0x0027); 5181 5182 if ( (mouse_flags_2 & 0x80) != 0x80 ) { 5183 return; 5184 } 5185 5186 package_count = mouse_flags_2 & 0x07; 5187 index = mouse_flags_1 & 0x07; 5188 write_byte(ebda_seg, 0x28 + index, in_byte); 5189 5190 if ( (index+1) >= package_count ) { 5191 BX_DEBUG_INT74("int74_function: make_farcall=1\n"); 5192 status = read_byte(ebda_seg, 0x0028 + 0); 5193 X = read_byte(ebda_seg, 0x0028 + 1); 5194 Y = read_byte(ebda_seg, 0x0028 + 2); 5195 Z = 0; 5196 mouse_flags_1 = 0; 5197 // check if far call handler installed 5198 if (mouse_flags_2 & 0x80) 5199 make_farcall = 1; 5200 } 5201 else { 5202 mouse_flags_1++; 5203 } 5204 write_byte(ebda_seg, 0x0026, mouse_flags_1); 5205 } 5206 5207 #define SET_DISK_RET_STATUS(status) write_byte(0x0040, 0x0074, status) 5208 5209 #if BX_USE_ATADRV 5210 5211 void 5212 int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) 5213 Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; 5214 { 5215 Bit32u lba_low, lba_high; 5216 Bit16u ebda_seg=read_word(0x0040,0x000E); 5217 Bit16u cylinder, head, sector; 5218 Bit16u segment, offset; 5219 Bit16u npc, nph, npspt, nlc, nlh, nlspt; 5220 Bit16u size, count; 5221 Bit8u device, status; 5222 5223 BX_DEBUG_INT13_HD("int13_harddisk: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); 5224 5225 write_byte(0x0040, 0x008e, 0); // clear completion flag 5226 5227 // basic check : device has to be defined 5228 if ( (GET_ELDL() < 0x80) || (GET_ELDL() >= 0x80 + BX_MAX_ATA_DEVICES) ) { 5229 BX_INFO("int13_harddisk: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL()); 5230 goto int13_fail; 5231 } 5232 5233 // Get the ata channel 5234 device=read_byte(ebda_seg,&EbdaData->ata.hdidmap[GET_ELDL()-0x80]); 5235 5236 // basic check : device has to be valid 5237 if (device >= BX_MAX_ATA_DEVICES) { 5238 BX_INFO("int13_harddisk: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL()); 5239 goto int13_fail; 5240 } 5241 5242 switch (GET_AH()) { 5243 5244 case 0x00: /* disk controller reset */ 5245 ata_reset (device); 5246 goto int13_success; 5247 break; 5248 5249 case 0x01: /* read disk status */ 5250 status = read_byte(0x0040, 0x0074); 5251 SET_AH(status); 5252 SET_DISK_RET_STATUS(0); 5253 /* set CF if error status read */ 5254 if (status) goto int13_fail_nostatus; 5255 else goto int13_success_noah; 5256 break; 5257 5258 case 0x02: // read disk sectors 5259 case 0x03: // write disk sectors 5260 case 0x04: // verify disk sectors 5261 5262 count = GET_AL(); 5263 cylinder = GET_CH(); 5264 cylinder |= ( ((Bit16u) GET_CL()) << 2) & 0x300; 5265 sector = (GET_CL() & 0x3f); 5266 head = GET_DH(); 5267 5268 segment = ES; 5269 offset = BX; 5270 5271 if ((count > 128) || (count == 0) || (sector == 0)) { 5272 BX_INFO("int13_harddisk: function %02x, parameter out of range!\n",GET_AH()); 5273 goto int13_fail; 5274 } 5275 5276 nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders); 5277 nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads); 5278 nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt); 5279 5280 // sanity check on cyl heads, sec 5281 if( (cylinder >= nlc) || (head >= nlh) || (sector > nlspt )) { 5282 BX_INFO("int13_harddisk: function %02x, parameters out of range %04x/%04x/%04x!\n", GET_AH(), cylinder, head, sector); 5283 goto int13_fail; 5284 } 5285 5286 // FIXME verify 5287 if ( GET_AH() == 0x04 ) goto int13_success; 5288 5289 nph = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads); 5290 npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt); 5291 5292 // if needed, translate lchs to lba, and execute command 5293 if ( (nph != nlh) || (npspt != nlspt)) { 5294 lba_low = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1; 5295 lba_high = 0; 5296 sector = 0; // this forces the command to be lba 5297 } 5298 5299 if ( GET_AH() == 0x02 ) 5300 status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset); 5301 else 5302 status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset); 5303 5304 // Set nb of sector transferred 5305 SET_AL(read_word(ebda_seg, &EbdaData->ata.trsfsectors)); 5306 5307 if (status != 0) { 5308 BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status); 5309 SET_AH(0x0c); 5310 goto int13_fail_noah; 5311 } 5312 5313 goto int13_success; 5314 break; 5315 5316 case 0x05: /* format disk track */ 5317 BX_INFO("format disk track called\n"); 5318 goto int13_success; 5319 return; 5320 break; 5321 5322 case 0x08: /* read disk drive parameters */ 5323 5324 // Get logical geometry from table 5325 nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders); 5326 nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads); 5327 nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt); 5328 count = read_byte(ebda_seg, &EbdaData->ata.hdcount); 5329 5330 nlc = nlc - 2; /* 0 based , last sector not used */ 5331 SET_AL(0); 5332 SET_CH(nlc & 0xff); 5333 SET_CL(((nlc >> 2) & 0xc0) | (nlspt & 0x3f)); 5334 SET_DH(nlh - 1); 5335 SET_DL(count); /* FIXME returns 0, 1, or n hard drives */ 5336 5337 // FIXME should set ES & DI 5338 5339 goto int13_success; 5340 break; 5341 5342 case 0x10: /* check drive ready */ 5343 // should look at 40:8E also??? 5344 5345 // Read the status from controller 5346 status = inb(read_word(ebda_seg, &EbdaData->ata.channels[device/2].iobase1) + ATA_CB_STAT); 5347 if ( (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY ) { 5348 goto int13_success; 5349 } 5350 else { 5351 SET_AH(0xAA); 5352 goto int13_fail_noah; 5353 } 5354 break; 5355 5356 case 0x15: /* read disk drive size */ 5357 5358 // Get logical geometry from table 5359 nlc = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders); 5360 nlh = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads); 5361 nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt); 5362 5363 // Compute sector count seen by int13 5364 lba_low = (Bit32u)(nlc - 1) * (Bit32u)nlh * (Bit32u)nlspt; 5365 CX = lba_low >> 16; 5366 DX = lba_low & 0xffff; 5367 5368 SET_AH(3); // hard disk accessible 5369 goto int13_success_noah; 5370 break; 5371 5372 case 0x41: // IBM/MS installation check 5373 BX=0xaa55; // install check 5374 SET_AH(0x30); // EDD 3.0 5375 CX=0x0007; // ext disk access and edd, removable supported 5376 goto int13_success_noah; 5377 break; 5378 5379 case 0x42: // IBM/MS extended read 5380 case 0x43: // IBM/MS extended write 5381 case 0x44: // IBM/MS verify 5382 case 0x47: // IBM/MS extended seek 5383 5384 count=read_word(DS, SI+(Bit16u)&Int13Ext->count); 5385 segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment); 5386 offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset); 5387 5388 // Get 32 msb lba and check 5389 lba_high=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2); 5390 if (lba_high > read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high) ) { 5391 BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH()); 5392 goto int13_fail; 5393 } 5394 5395 // Get 32 lsb lba and check 5396 lba_low=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1); 5397 if (lba_high == read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high) 5398 && lba_low >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low) ) { 5399 BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH()); 5400 goto int13_fail; 5401 } 5402 5403 // If verify or seek 5404 if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 )) 5405 goto int13_success; 5406 5407 // Execute the command 5408 if ( GET_AH() == 0x42 ) 5409 status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset); 5410 else 5411 status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset); 5412 5413 count=read_word(ebda_seg, &EbdaData->ata.trsfsectors); 5414 write_word(DS, SI+(Bit16u)&Int13Ext->count, count); 5415 5416 if (status != 0) { 5417 BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status); 5418 SET_AH(0x0c); 5419 goto int13_fail_noah; 5420 } 5421 5422 goto int13_success; 5423 break; 5424 5425 case 0x45: // IBM/MS lock/unlock drive 5426 case 0x49: // IBM/MS extended media change 5427 goto int13_success; // Always success for HD 5428 break; 5429 5430 case 0x46: // IBM/MS eject media 5431 SET_AH(0xb2); // Volume Not Removable 5432 goto int13_fail_noah; // Always fail for HD 5433 break; 5434 5435 case 0x48: // IBM/MS get drive parameters 5436 size=read_word(DS,SI+(Bit16u)&Int13DPT->size); 5437 5438 // Buffer is too small 5439 if(size < 0x1a) 5440 goto int13_fail; 5441 5442 // EDD 1.x 5443 if(size >= 0x1a) { 5444 Bit16u blksize; 5445 5446 npc = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.cylinders); 5447 nph = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads); 5448 npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt); 5449 lba_low = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low); 5450 lba_high = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high); 5451 blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize); 5452 5453 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a); 5454 if (lba_high || (lba_low/npspt)/nph > 0x3fff) 5455 { 5456 write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x00); // geometry is invalid 5457 write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0x3fff); 5458 } 5459 else 5460 { 5461 write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is valid 5462 write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc); 5463 } 5464 write_dword(DS, SI+(Bit16u)&Int13DPT->heads, (Bit32u)nph); 5465 write_dword(DS, SI+(Bit16u)&Int13DPT->spt, (Bit32u)npspt); 5466 write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba_low); 5467 write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, lba_high); 5468 write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize); 5469 } 5470 5471 // EDD 2.x 5472 if(size >= 0x1e) { 5473 Bit8u channel, dev, irq, mode, checksum, i, translation; 5474 Bit16u iobase1, iobase2, options; 5475 5476 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e); 5477 5478 write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg); 5479 write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte); 5480 5481 // Fill in dpte 5482 channel = device / 2; 5483 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 5484 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2); 5485 irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq); 5486 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode); 5487 translation = read_byte(ebda_seg, &EbdaData->ata.devices[device].translation); 5488 5489 options = (translation==ATA_TRANSLATION_NONE?0:1)<<3; // chs translation 5490 options |= (1<<4); // lba translation 5491 options |= (mode==ATA_MODE_PIO32?1:0)<<7; 5492 options |= (translation==ATA_TRANSLATION_LBA?1:0)<<9; 5493 options |= (translation==ATA_TRANSLATION_RECHS?3:0)<<9; 5494 5495 write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1); 5496 write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC); 5497 write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 ); 5498 write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb ); 5499 write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq ); 5500 write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 ); 5501 write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 ); 5502 write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 ); 5503 write_word(ebda_seg, &EbdaData->ata.dpte.options, options); 5504 write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0); 5505 if (size >=0x42) 5506 write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11); 5507 else 5508 write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x10); 5509 5510 checksum=0; 5511 for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, ((Bit8u*)(&EbdaData->ata.dpte)) + i); 5512 checksum = ~checksum; 5513 write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum); 5514 } 5515 5516 // EDD 3.x 5517 if(size >= 0x42) { 5518 Bit8u channel, iface, checksum, i; 5519 Bit16u iobase1; 5520 5521 channel = device / 2; 5522 iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface); 5523 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 5524 5525 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42); 5526 write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd); 5527 write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24); 5528 write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0); 5529 write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0); 5530 5531 if (iface==ATA_IFACE_ISA) { 5532 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I'); 5533 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S'); 5534 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A'); 5535 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0); 5536 } 5537 else { 5538 // FIXME PCI 5539 } 5540 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A'); 5541 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T'); 5542 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A'); 5543 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0); 5544 5545 if (iface==ATA_IFACE_ISA) { 5546 write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1); 5547 write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0); 5548 write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L); 5549 } 5550 else { 5551 // FIXME PCI 5552 } 5553 write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2); 5554 write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0); 5555 write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0); 5556 write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L); 5557 5558 checksum=0; 5559 for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i); 5560 checksum = ~checksum; 5561 write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum); 5562 } 5563 5564 goto int13_success; 5565 break; 5566 5567 case 0x4e: // // IBM/MS set hardware configuration 5568 // DMA, prefetch, PIO maximum not supported 5569 switch (GET_AL()) { 5570 case 0x01: 5571 case 0x03: 5572 case 0x04: 5573 case 0x06: 5574 goto int13_success; 5575 break; 5576 default : 5577 goto int13_fail; 5578 } 5579 break; 5580 5581 case 0x09: /* initialize drive parameters */ 5582 case 0x0c: /* seek to specified cylinder */ 5583 case 0x0d: /* alternate disk reset */ 5584 case 0x11: /* recalibrate */ 5585 case 0x14: /* controller internal diagnostic */ 5586 BX_INFO("int13_harddisk: function %02xh unimplemented, returns success\n", GET_AH()); 5587 goto int13_success; 5588 break; 5589 5590 case 0x0a: /* read disk sectors with ECC */ 5591 case 0x0b: /* write disk sectors with ECC */ 5592 case 0x18: // set media type for format 5593 case 0x50: // IBM/MS send packet command 5594 default: 5595 BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", GET_AH()); 5596 goto int13_fail; 5597 break; 5598 } 5599 5600 int13_fail: 5601 SET_AH(0x01); // defaults to invalid function in AH or invalid parameter 5602 int13_fail_noah: 5603 SET_DISK_RET_STATUS(GET_AH()); 5604 int13_fail_nostatus: 5605 SET_CF(); // error occurred 5606 return; 5607 5608 int13_success: 5609 SET_AH(0x00); // no error 5610 int13_success_noah: 5611 SET_DISK_RET_STATUS(0x00); 5612 CLEAR_CF(); // no error 5613 return; 5614 } 5615 5616 // --------------------------------------------------------------------------- 5617 // Start of int13 for cdrom 5618 // --------------------------------------------------------------------------- 5619 5620 void 5621 int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) 5622 Bit16u EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; 5623 { 5624 Bit16u ebda_seg=read_word(0x0040,0x000E); 5625 Bit8u device, status, locks; 5626 Bit8u atacmd[12]; 5627 Bit32u lba; 5628 Bit16u count, segment, offset, i, size; 5629 5630 BX_DEBUG_INT13_CD("int13_cdrom: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); 5631 5632 SET_DISK_RET_STATUS(0x00); 5633 5634 /* basic check : device should be 0xE0+ */ 5635 if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0+BX_MAX_ATA_DEVICES) ) { 5636 BX_INFO("int13_cdrom: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL()); 5637 goto int13_fail; 5638 } 5639 5640 // Get the ata channel 5641 device=read_byte(ebda_seg,&EbdaData->ata.cdidmap[GET_ELDL()-0xE0]); 5642 5643 /* basic check : device has to be valid */ 5644 if (device >= BX_MAX_ATA_DEVICES) { 5645 BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL()); 5646 goto int13_fail; 5647 } 5648 5649 switch (GET_AH()) { 5650 5651 // all those functions return SUCCESS 5652 case 0x00: /* disk controller reset */ 5653 case 0x09: /* initialize drive parameters */ 5654 case 0x0c: /* seek to specified cylinder */ 5655 case 0x0d: /* alternate disk reset */ 5656 case 0x10: /* check drive ready */ 5657 case 0x11: /* recalibrate */ 5658 case 0x14: /* controller internal diagnostic */ 5659 case 0x16: /* detect disk change */ 5660 goto int13_success; 5661 break; 5662 5663 // all those functions return disk write-protected 5664 case 0x03: /* write disk sectors */ 5665 case 0x05: /* format disk track */ 5666 case 0x43: // IBM/MS extended write 5667 SET_AH(0x03); 5668 goto int13_fail_noah; 5669 break; 5670 5671 case 0x01: /* read disk status */ 5672 status = read_byte(0x0040, 0x0074); 5673 SET_AH(status); 5674 SET_DISK_RET_STATUS(0); 5675 5676 /* set CF if error status read */ 5677 if (status) goto int13_fail_nostatus; 5678 else goto int13_success_noah; 5679 break; 5680 5681 case 0x15: /* read disk drive size */ 5682 SET_AH(0x02); 5683 goto int13_fail_noah; 5684 break; 5685 5686 case 0x41: // IBM/MS installation check 5687 BX=0xaa55; // install check 5688 SET_AH(0x30); // EDD 2.1 5689 CX=0x0007; // ext disk access, removable and edd 5690 goto int13_success_noah; 5691 break; 5692 5693 case 0x42: // IBM/MS extended read 5694 case 0x44: // IBM/MS verify sectors 5695 case 0x47: // IBM/MS extended seek 5696 5697 count=read_word(DS, SI+(Bit16u)&Int13Ext->count); 5698 segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment); 5699 offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset); 5700 5701 // Can't use 64 bits lba 5702 lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2); 5703 if (lba != 0L) { 5704 BX_PANIC("int13_cdrom: function %02x. Can't use 64bits lba\n",GET_AH()); 5705 goto int13_fail; 5706 } 5707 5708 // Get 32 bits lba 5709 lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1); 5710 5711 // If verify or seek 5712 if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 )) 5713 goto int13_success; 5714 5715 memsetb(get_SS(),atacmd,0,12); 5716 atacmd[0]=0x28; // READ command 5717 atacmd[7]=(count & 0xff00) >> 8; // Sectors 5718 atacmd[8]=(count & 0x00ff); // Sectors 5719 atacmd[2]=(lba & 0xff000000) >> 24; // LBA 5720 atacmd[3]=(lba & 0x00ff0000) >> 16; 5721 atacmd[4]=(lba & 0x0000ff00) >> 8; 5722 atacmd[5]=(lba & 0x000000ff); 5723 status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L, ATA_DATA_IN, segment,offset); 5724 5725 count = (Bit16u)(read_dword(ebda_seg, &EbdaData->ata.trsfbytes) >> 11); 5726 write_word(DS, SI+(Bit16u)&Int13Ext->count, count); 5727 5728 if (status != 0) { 5729 BX_INFO("int13_cdrom: function %02x, status %02x !\n",GET_AH(),status); 5730 SET_AH(0x0c); 5731 goto int13_fail_noah; 5732 } 5733 5734 goto int13_success; 5735 break; 5736 5737 case 0x45: // IBM/MS lock/unlock drive 5738 if (GET_AL() > 2) goto int13_fail; 5739 5740 locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock); 5741 5742 switch (GET_AL()) { 5743 case 0 : // lock 5744 if (locks == 0xff) { 5745 SET_AH(0xb4); 5746 SET_AL(1); 5747 goto int13_fail_noah; 5748 } 5749 write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, ++locks); 5750 SET_AL(1); 5751 break; 5752 case 1 : // unlock 5753 if (locks == 0x00) { 5754 SET_AH(0xb0); 5755 SET_AL(0); 5756 goto int13_fail_noah; 5757 } 5758 write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, --locks); 5759 SET_AL(locks==0?0:1); 5760 break; 5761 case 2 : // status 5762 SET_AL(locks==0?0:1); 5763 break; 5764 } 5765 goto int13_success; 5766 break; 5767 5768 case 0x46: // IBM/MS eject media 5769 locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock); 5770 5771 if (locks != 0) { 5772 SET_AH(0xb1); // media locked 5773 goto int13_fail_noah; 5774 } 5775 // FIXME should handle 0x31 no media in device 5776 // FIXME should handle 0xb5 valid request failed 5777 5778 // Call removable media eject 5779 ASM_START 5780 push bp 5781 mov bp, sp 5782 5783 mov ah, #0x52 5784 int #0x15 5785 mov _int13_cdrom.status + 2[bp], ah 5786 jnc int13_cdrom_rme_end 5787 mov _int13_cdrom.status, #1 5788 int13_cdrom_rme_end: 5789 pop bp 5790 ASM_END 5791 5792 if (status != 0) { 5793 SET_AH(0xb1); // media locked 5794 goto int13_fail_noah; 5795 } 5796 5797 goto int13_success; 5798 break; 5799 5800 case 0x48: // IBM/MS get drive parameters 5801 size = read_word(DS,SI+(Bit16u)&Int13Ext->size); 5802 5803 // Buffer is too small 5804 if(size < 0x1a) 5805 goto int13_fail; 5806 5807 // EDD 1.x 5808 if(size >= 0x1a) { 5809 Bit16u cylinders, heads, spt, blksize; 5810 5811 blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize); 5812 5813 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a); 5814 write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x74); // removable, media change, lockable, max values 5815 write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0xffffffff); 5816 write_dword(DS, SI+(Bit16u)&Int13DPT->heads, 0xffffffff); 5817 write_dword(DS, SI+(Bit16u)&Int13DPT->spt, 0xffffffff); 5818 write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, 0xffffffff); // FIXME should be Bit64 5819 write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff); 5820 write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize); 5821 } 5822 5823 // EDD 2.x 5824 if(size >= 0x1e) { 5825 Bit8u channel, dev, irq, mode, checksum, i; 5826 Bit16u iobase1, iobase2, options; 5827 5828 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e); 5829 5830 write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg); 5831 write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte); 5832 5833 // Fill in dpte 5834 channel = device / 2; 5835 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 5836 iobase2 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase2); 5837 irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq); 5838 mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode); 5839 5840 // FIXME atapi device 5841 options = (1<<4); // lba translation 5842 options |= (1<<5); // removable device 5843 options |= (1<<6); // atapi device 5844 options |= (mode==ATA_MODE_PIO32?1:0<<7); 5845 5846 write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1); 5847 write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC); 5848 write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 ); 5849 write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb ); 5850 write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq ); 5851 write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 ); 5852 write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 ); 5853 write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 ); 5854 write_word(ebda_seg, &EbdaData->ata.dpte.options, options); 5855 write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0); 5856 write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11); 5857 5858 checksum=0; 5859 for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, ((Bit8u*)(&EbdaData->ata.dpte)) + i); 5860 checksum = ~checksum; 5861 write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum); 5862 } 5863 5864 // EDD 3.x 5865 if(size >= 0x42) { 5866 Bit8u channel, iface, checksum, i; 5867 Bit16u iobase1; 5868 5869 channel = device / 2; 5870 iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface); 5871 iobase1 = read_word(ebda_seg, &EbdaData->ata.channels[channel].iobase1); 5872 5873 write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42); 5874 write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd); 5875 write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24); 5876 write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0); 5877 write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0); 5878 5879 if (iface==ATA_IFACE_ISA) { 5880 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I'); 5881 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S'); 5882 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A'); 5883 write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0); 5884 } 5885 else { 5886 // FIXME PCI 5887 } 5888 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A'); 5889 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T'); 5890 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A'); 5891 write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0); 5892 5893 if (iface==ATA_IFACE_ISA) { 5894 write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1); 5895 write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0); 5896 write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L); 5897 } 5898 else { 5899 // FIXME PCI 5900 } 5901 write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2); 5902 write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0); 5903 write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0); 5904 write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L); 5905 5906 checksum=0; 5907 for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i); 5908 checksum = ~checksum; 5909 write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum); 5910 } 5911 5912 goto int13_success; 5913 break; 5914 5915 case 0x49: // IBM/MS extended media change 5916 // always send changed ?? 5917 SET_AH(06); 5918 goto int13_fail_nostatus; 5919 break; 5920 5921 case 0x4e: // // IBM/MS set hardware configuration 5922 // DMA, prefetch, PIO maximum not supported 5923 switch (GET_AL()) { 5924 case 0x01: 5925 case 0x03: 5926 case 0x04: 5927 case 0x06: 5928 goto int13_success; 5929 break; 5930 default : 5931 goto int13_fail; 5932 } 5933 break; 5934 5935 // all those functions return unimplemented 5936 case 0x02: /* read sectors */ 5937 case 0x04: /* verify sectors */ 5938 case 0x08: /* read disk drive parameters */ 5939 case 0x0a: /* read disk sectors with ECC */ 5940 case 0x0b: /* write disk sectors with ECC */ 5941 case 0x18: /* set media type for format */ 5942 case 0x50: // ? - send packet command 5943 default: 5944 BX_INFO("int13_cdrom: unsupported AH=%02x\n", GET_AH()); 5945 goto int13_fail; 5946 break; 5947 } 5948 5949 int13_fail: 5950 SET_AH(0x01); // defaults to invalid function in AH or invalid parameter 5951 int13_fail_noah: 5952 SET_DISK_RET_STATUS(GET_AH()); 5953 int13_fail_nostatus: 5954 SET_CF(); // error occurred 5955 return; 5956 5957 int13_success: 5958 SET_AH(0x00); // no error 5959 int13_success_noah: 5960 SET_DISK_RET_STATUS(0x00); 5961 CLEAR_CF(); // no error 5962 return; 5963 } 5964 5965 // --------------------------------------------------------------------------- 5966 // End of int13 for cdrom 5967 // --------------------------------------------------------------------------- 5968 5969 #if BX_ELTORITO_BOOT 5970 // --------------------------------------------------------------------------- 5971 // Start of int13 for eltorito functions 5972 // --------------------------------------------------------------------------- 5973 5974 void 5975 int13_eltorito(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS) 5976 Bit16u DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS; 5977 { 5978 Bit16u ebda_seg=read_word(0x0040,0x000E); 5979 5980 BX_DEBUG_INT13_ET("int13_eltorito: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); 5981 // BX_DEBUG_INT13_ET("int13_eltorito: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), DS, ES, DI, SI); 5982 5983 switch (GET_AH()) { 5984 5985 // FIXME ElTorito Various. Should be implemented 5986 case 0x4a: // ElTorito - Initiate disk emu 5987 case 0x4c: // ElTorito - Initiate disk emu and boot 5988 case 0x4d: // ElTorito - Return Boot catalog 5989 BX_PANIC("Int13 eltorito call with AX=%04x. Please report\n",AX); 5990 goto int13_fail; 5991 break; 5992 5993 case 0x4b: // ElTorito - Terminate disk emu 5994 // FIXME ElTorito Hardcoded 5995 write_byte(DS,SI+0x00,0x13); 5996 write_byte(DS,SI+0x01,read_byte(ebda_seg,&EbdaData->cdemu.media)); 5997 write_byte(DS,SI+0x02,read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive)); 5998 write_byte(DS,SI+0x03,read_byte(ebda_seg,&EbdaData->cdemu.controller_index)); 5999 write_dword(DS,SI+0x04,read_dword(ebda_seg,&EbdaData->cdemu.ilba)); 6000 write_word(DS,SI+0x08,read_word(ebda_seg,&EbdaData->cdemu.device_spec)); 6001 write_word(DS,SI+0x0a,read_word(ebda_seg,&EbdaData->cdemu.buffer_segment)); 6002 write_word(DS,SI+0x0c,read_word(ebda_seg,&EbdaData->cdemu.load_segment)); 6003 write_word(DS,SI+0x0e,read_word(ebda_seg,&EbdaData->cdemu.sector_count)); 6004 write_byte(DS,SI+0x10,read_byte(ebda_seg,&EbdaData->cdemu.vdevice.cylinders)); 6005 write_byte(DS,SI+0x11,read_byte(ebda_seg,&EbdaData->cdemu.vdevice.spt)); 6006 write_byte(DS,SI+0x12,read_byte(ebda_seg,&EbdaData->cdemu.vdevice.heads)); 6007 6008 // If we have to terminate emulation 6009 if(GET_AL() == 0x00) { 6010 // FIXME ElTorito Various. Should be handled accordingly to spec 6011 write_byte(ebda_seg,&EbdaData->cdemu.active, 0x00); // bye bye 6012 } 6013 6014 goto int13_success; 6015 break; 6016 6017 default: 6018 BX_INFO("int13_eltorito: unsupported AH=%02x\n", GET_AH()); 6019 goto int13_fail; 6020 break; 6021 } 6022 6023 int13_fail: 6024 SET_AH(0x01); // defaults to invalid function in AH or invalid parameter 6025 SET_DISK_RET_STATUS(GET_AH()); 6026 SET_CF(); // error occurred 6027 return; 6028 6029 int13_success: 6030 SET_AH(0x00); // no error 6031 SET_DISK_RET_STATUS(0x00); 6032 CLEAR_CF(); // no error 6033 return; 6034 } 6035 6036 // --------------------------------------------------------------------------- 6037 // End of int13 for eltorito functions 6038 // --------------------------------------------------------------------------- 6039 6040 // --------------------------------------------------------------------------- 6041 // Start of int13 when emulating a device from the cd 6042 // --------------------------------------------------------------------------- 6043 6044 void 6045 int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS) 6046 Bit16u DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS; 6047 { 6048 Bit16u ebda_seg=read_word(0x0040,0x000E); 6049 Bit8u device, status; 6050 Bit16u vheads, vspt, vcylinders; 6051 Bit16u head, sector, cylinder, nbsectors; 6052 Bit32u vlba, ilba, slba, elba; 6053 Bit16u before, segment, offset; 6054 Bit8u atacmd[12]; 6055 6056 BX_DEBUG_INT13_ET("int13_cdemu: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); 6057 6058 /* at this point, we are emulating a floppy/harddisk */ 6059 6060 // Recompute the device number 6061 device = read_byte(ebda_seg,&EbdaData->cdemu.controller_index) * 2; 6062 device += read_byte(ebda_seg,&EbdaData->cdemu.device_spec); 6063 6064 SET_DISK_RET_STATUS(0x00); 6065 6066 /* basic checks : emulation should be active, dl should equal the emulated drive */ 6067 if( (read_byte(ebda_seg,&EbdaData->cdemu.active) ==0 ) 6068 || (read_byte(ebda_seg,&EbdaData->cdemu.emulated_drive ) != GET_DL())) { 6069 BX_INFO("int13_cdemu: function %02x, emulation not active for DL= %02x\n", GET_AH(), GET_DL()); 6070 goto int13_fail; 6071 } 6072 6073 switch (GET_AH()) { 6074 6075 // all those functions return SUCCESS 6076 case 0x00: /* disk controller reset */ 6077 case 0x09: /* initialize drive parameters */ 6078 case 0x0c: /* seek to specified cylinder */ 6079 case 0x0d: /* alternate disk reset */ // FIXME ElTorito Various. should really reset ? 6080 case 0x10: /* check drive ready */ // FIXME ElTorito Various. should check if ready ? 6081 case 0x11: /* recalibrate */ 6082 case 0x14: /* controller internal diagnostic */ 6083 case 0x16: /* detect disk change */ 6084 goto int13_success; 6085 break; 6086 6087 // all those functions return disk write-protected 6088 case 0x03: /* write disk sectors */ 6089 case 0x05: /* format disk track */ 6090 SET_AH(0x03); 6091 goto int13_fail_noah; 6092 break; 6093 6094 case 0x01: /* read disk status */ 6095 status=read_byte(0x0040, 0x0074); 6096 SET_AH(status); 6097 SET_DISK_RET_STATUS(0); 6098 6099 /* set CF if error status read */ 6100 if (status) goto int13_fail_nostatus; 6101 else goto int13_success_noah; 6102 break; 6103 6104 case 0x02: // read disk sectors 6105 case 0x04: // verify disk sectors 6106 vspt = read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt); 6107 vcylinders = read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders); 6108 vheads = read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads); 6109 6110 ilba = read_dword(ebda_seg,&EbdaData->cdemu.ilba); 6111 6112 sector = GET_CL() & 0x003f; 6113 cylinder = (GET_CL() & 0x00c0) << 2 | GET_CH(); 6114 head = GET_DH(); 6115 nbsectors = GET_AL(); 6116 segment = ES; 6117 offset = BX; 6118 6119 // no sector to read ? 6120 if(nbsectors==0) goto int13_success; 6121 6122 // sanity checks sco openserver needs this! 6123 if ((sector > vspt) 6124 || (cylinder >= vcylinders) 6125 || (head >= vheads)) { 6126 goto int13_fail; 6127 } 6128 6129 // After controls, verify do nothing 6130 if (GET_AH() == 0x04) goto int13_success; 6131 6132 segment = ES+(BX / 16); 6133 offset = BX % 16; 6134 6135 // calculate the virtual lba inside the image 6136 vlba=((((Bit32u)cylinder*(Bit32u)vheads)+(Bit32u)head)*(Bit32u)vspt)+((Bit32u)(sector-1)); 6137 6138 // In advance so we don't loose the count 6139 SET_AL(nbsectors); 6140 6141 // start lba on cd 6142 slba = (Bit32u)vlba/4; 6143 before= (Bit16u)vlba%4; 6144 6145 // end lba on cd 6146 elba = (Bit32u)(vlba+nbsectors-1)/4; 6147 6148 memsetb(get_SS(),atacmd,0,12); 6149 atacmd[0]=0x28; // READ command 6150 atacmd[7]=((Bit16u)(elba-slba+1) & 0xff00) >> 8; // Sectors 6151 atacmd[8]=((Bit16u)(elba-slba+1) & 0x00ff); // Sectors 6152 atacmd[2]=(ilba+slba & 0xff000000) >> 24; // LBA 6153 atacmd[3]=(ilba+slba & 0x00ff0000) >> 16; 6154 atacmd[4]=(ilba+slba & 0x0000ff00) >> 8; 6155 atacmd[5]=(ilba+slba & 0x000000ff); 6156 if((status = ata_cmd_packet(device, 12, get_SS(), atacmd, before*512, nbsectors*512L, ATA_DATA_IN, segment,offset)) != 0) { 6157 BX_INFO("int13_cdemu: function %02x, error %02x !\n",GET_AH(),status); 6158 SET_AH(0x02); 6159 SET_AL(0); 6160 goto int13_fail_noah; 6161 } 6162 6163 goto int13_success; 6164 break; 6165 6166 case 0x08: /* read disk drive parameters */ 6167 vspt=read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt); 6168 vcylinders=read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders) - 1; 6169 vheads=read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads) - 1; 6170 6171 SET_AL( 0x00 ); 6172 SET_BL( 0x00 ); 6173 SET_CH( vcylinders & 0xff ); 6174 SET_CL((( vcylinders >> 2) & 0xc0) | ( vspt & 0x3f )); 6175 SET_DH( vheads ); 6176 SET_DL( 0x02 ); // FIXME ElTorito Various. should send the real count of drives 1 or 2 6177 // FIXME ElTorito Harddisk. should send the HD count 6178 6179 switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) { 6180 case 0x01: SET_BL( 0x02 ); break; 6181 case 0x02: SET_BL( 0x04 ); break; 6182 case 0x03: SET_BL( 0x06 ); break; 6183 } 6184 6185 ASM_START 6186 push bp 6187 mov bp, sp 6188 mov ax, #diskette_param_table2 6189 mov _int13_cdemu.DI+2[bp], ax 6190 mov _int13_cdemu.ES+2[bp], cs 6191 pop bp 6192 ASM_END 6193 goto int13_success; 6194 break; 6195 6196 case 0x15: /* read disk drive size */ 6197 // FIXME ElTorito Harddisk. What geometry to send ? 6198 SET_AH(0x03); 6199 goto int13_success_noah; 6200 break; 6201 6202 // all those functions return unimplemented 6203 case 0x0a: /* read disk sectors with ECC */ 6204 case 0x0b: /* write disk sectors with ECC */ 6205 case 0x18: /* set media type for format */ 6206 case 0x41: // IBM/MS installation check 6207 // FIXME ElTorito Harddisk. Darwin would like to use EDD 6208 case 0x42: // IBM/MS extended read 6209 case 0x43: // IBM/MS extended write 6210 case 0x44: // IBM/MS verify sectors 6211 case 0x45: // IBM/MS lock/unlock drive 6212 case 0x46: // IBM/MS eject media 6213 case 0x47: // IBM/MS extended seek 6214 case 0x48: // IBM/MS get drive parameters 6215 case 0x49: // IBM/MS extended media change 6216 case 0x4e: // ? - set hardware configuration 6217 case 0x50: // ? - send packet command 6218 default: 6219 BX_INFO("int13_cdemu function AH=%02x unsupported, returns fail\n", GET_AH()); 6220 goto int13_fail; 6221 break; 6222 } 6223 6224 int13_fail: 6225 SET_AH(0x01); // defaults to invalid function in AH or invalid parameter 6226 int13_fail_noah: 6227 SET_DISK_RET_STATUS(GET_AH()); 6228 int13_fail_nostatus: 6229 SET_CF(); // error occurred 6230 return; 6231 6232 int13_success: 6233 SET_AH(0x00); // no error 6234 int13_success_noah: 6235 SET_DISK_RET_STATUS(0x00); 6236 CLEAR_CF(); // no error 6237 return; 6238 } 6239 6240 // --------------------------------------------------------------------------- 6241 // End of int13 when emulating a device from the cd 6242 // --------------------------------------------------------------------------- 6243 6244 #endif // BX_ELTORITO_BOOT 6245 6246 #else //BX_USE_ATADRV 6247 6248 void 6249 outLBA(cylinder,hd_heads,head,hd_sectors,sector,dl) 6250 Bit16u cylinder; 6251 Bit16u hd_heads; 6252 Bit16u head; 6253 Bit16u hd_sectors; 6254 Bit16u sector; 6255 Bit16u dl; 6256 { 6257 ASM_START 6258 push bp 6259 mov bp, sp 6260 push eax 6261 push ebx 6262 push edx 6263 xor eax,eax 6264 mov ax,4[bp] // cylinder 6265 xor ebx,ebx 6266 mov bl,6[bp] // hd_heads 6267 imul ebx 6268 6269 mov bl,8[bp] // head 6270 add eax,ebx 6271 mov bl,10[bp] // hd_sectors 6272 imul ebx 6273 mov bl,12[bp] // sector 6274 add eax,ebx 6275 6276 dec eax 6277 mov dx,#0x1f3 6278 out dx,al 6279 mov dx,#0x1f4 6280 mov al,ah 6281 out dx,al 6282 shr eax,#16 6283 mov dx,#0x1f5 6284 out dx,al 6285 and ah,#0xf 6286 mov bl,14[bp] // dl 6287 and bl,#1 6288 shl bl,#4 6289 or ah,bl 6290 or ah,#0xe0 6291 mov al,ah 6292 mov dx,#0x01f6 6293 out dx,al 6294 pop edx 6295 pop ebx 6296 pop eax 6297 pop bp 6298 ASM_END 6299 } 6300 6301 void 6302 int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) 6303 Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; 6304 { 6305 Bit8u drive, num_sectors, sector, head, status, mod; 6306 Bit8u drive_map; 6307 Bit8u n_drives; 6308 Bit16u cyl_mod, ax; 6309 Bit16u max_cylinder, cylinder, total_sectors; 6310 Bit16u hd_cylinders; 6311 Bit8u hd_heads, hd_sectors; 6312 Bit16u val16; 6313 Bit8u sector_count; 6314 unsigned int i; 6315 Bit16u tempbx; 6316 Bit16u dpsize; 6317 6318 Bit16u count, segment, offset; 6319 Bit32u lba; 6320 Bit16u error; 6321 6322 BX_DEBUG_INT13_HD("int13 harddisk: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); 6323 6324 write_byte(0x0040, 0x008e, 0); // clear completion flag 6325 6326 /* at this point, DL is >= 0x80 to be passed from the floppy int13h 6327 handler code */ 6328 /* check how many disks first (cmos reg 0x12), return an error if 6329 drive not present */ 6330 drive_map = inb_cmos(0x12); 6331 drive_map = (((drive_map & 0xf0)==0) ? 0 : 1) | 6332 (((drive_map & 0x0f)==0) ? 0 : 2); 6333 n_drives = (drive_map==0) ? 0 : 6334 ((drive_map==3) ? 2 : 1); 6335 6336 if (!(drive_map & (1<<(GET_ELDL()&0x7f)))) { /* allow 0, 1, or 2 disks */ 6337 SET_AH(0x01); 6338 SET_DISK_RET_STATUS(0x01); 6339 SET_CF(); /* error occurred */ 6340 return; 6341 } 6342 6343 switch (GET_AH()) { 6344 6345 case 0x00: /* disk controller reset */ 6346 BX_DEBUG_INT13_HD("int13_f00\n"); 6347 6348 SET_AH(0); 6349 SET_DISK_RET_STATUS(0); 6350 set_diskette_ret_status(0); 6351 set_diskette_current_cyl(0, 0); /* current cylinder, diskette 1 */ 6352 set_diskette_current_cyl(1, 0); /* current cylinder, diskette 2 */ 6353 CLEAR_CF(); /* successful */ 6354 return; 6355 break; 6356 6357 case 0x01: /* read disk status */ 6358 BX_DEBUG_INT13_HD("int13_f01\n"); 6359 status = read_byte(0x0040, 0x0074); 6360 SET_AH(status); 6361 SET_DISK_RET_STATUS(0); 6362 /* set CF if error status read */ 6363 if (status) SET_CF(); 6364 else CLEAR_CF(); 6365 return; 6366 break; 6367 6368 case 0x04: // verify disk sectors 6369 case 0x02: // read disk sectors 6370 drive = GET_ELDL(); 6371 get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors); 6372 6373 num_sectors = GET_AL(); 6374 cylinder = (GET_CL() & 0x00c0) << 2 | GET_CH(); 6375 sector = (GET_CL() & 0x3f); 6376 head = GET_DH(); 6377 6378 6379 if (hd_cylinders > 1024) { 6380 if (hd_cylinders <= 2048) { 6381 cylinder <<= 1; 6382 } 6383 else if (hd_cylinders <= 4096) { 6384 cylinder <<= 2; 6385 } 6386 else if (hd_cylinders <= 8192) { 6387 cylinder <<= 3; 6388 } 6389 else { // hd_cylinders <= 16384 6390 cylinder <<= 4; 6391 } 6392 6393 ax = head / hd_heads; 6394 cyl_mod = ax & 0xff; 6395 head = ax >> 8; 6396 cylinder |= cyl_mod; 6397 } 6398 6399 if ( (cylinder >= hd_cylinders) || 6400 (sector > hd_sectors) || 6401 (head >= hd_heads) ) { 6402 SET_AH(1); 6403 SET_DISK_RET_STATUS(1); 6404 SET_CF(); /* error occurred */ 6405 return; 6406 } 6407 6408 if ( (num_sectors > 128) || (num_sectors == 0) ) 6409 BX_PANIC("int13_harddisk: num_sectors out of range!\n"); 6410 6411 if (head > 15) 6412 BX_PANIC("hard drive BIOS:(read/verify) head > 15\n"); 6413 6414 if ( GET_AH() == 0x04 ) { 6415 SET_AH(0); 6416 SET_DISK_RET_STATUS(0); 6417 CLEAR_CF(); 6418 return; 6419 } 6420 6421 status = inb(0x1f7); 6422 if (status & 0x80) { 6423 BX_PANIC("hard drive BIOS:(read/verify) BUSY bit set\n"); 6424 } 6425 outb(0x01f2, num_sectors); 6426 /* activate LBA? (tomv) */ 6427 if (hd_heads > 16) { 6428 BX_DEBUG_INT13_HD("CHS: %x %x %x\n", cylinder, head, sector); 6429 outLBA(cylinder,hd_heads,head,hd_sectors,sector,drive); 6430 } 6431 else { 6432 outb(0x01f3, sector); 6433 outb(0x01f4, cylinder & 0x00ff); 6434 outb(0x01f5, cylinder >> 8); 6435 outb(0x01f6, 0xa0 | ((drive & 0x01)<<4) | (head & 0x0f)); 6436 } 6437 outb(0x01f7, 0x20); 6438 6439 while (1) { 6440 status = inb(0x1f7); 6441 if ( !(status & 0x80) ) break; 6442 } 6443 6444 if (status & 0x01) { 6445 BX_PANIC("hard drive BIOS:(read/verify) read error\n"); 6446 } else if ( !(status & 0x08) ) { 6447 BX_DEBUG_INT13_HD("status was %02x\n", (unsigned) status); 6448 BX_PANIC("hard drive BIOS:(read/verify) expected DRQ=1\n"); 6449 } 6450 6451 sector_count = 0; 6452 tempbx = BX; 6453 6454 ASM_START 6455 sti ;; enable higher priority interrupts 6456 ASM_END 6457 6458 while (1) { 6459 ASM_START 6460 ;; store temp bx in real DI register 6461 push bp 6462 mov bp, sp 6463 mov di, _int13_harddisk.tempbx + 2 [bp] 6464 pop bp 6465 6466 ;; adjust if there will be an overrun 6467 cmp di, #0xfe00 6468 jbe i13_f02_no_adjust 6469 i13_f02_adjust: 6470 sub di, #0x0200 ; sub 512 bytes from offset 6471 mov ax, es 6472 add ax, #0x0020 ; add 512 to segment 6473 mov es, ax 6474 6475 i13_f02_no_adjust: 6476 mov cx, #0x0100 ;; counter (256 words = 512b) 6477 mov dx, #0x01f0 ;; AT data read port 6478 6479 rep 6480 insw ;; CX words transfered from port(DX) to ES:[DI] 6481 6482 i13_f02_done: 6483 ;; store real DI register back to temp bx 6484 push bp 6485 mov bp, sp 6486 mov _int13_harddisk.tempbx + 2 [bp], di 6487 pop bp 6488 ASM_END 6489 6490 sector_count++; 6491 num_sectors--; 6492 if (num_sectors == 0) { 6493 status = inb(0x1f7); 6494 if ( (status & 0xc9) != 0x40 ) 6495 BX_PANIC("no sectors left to read/verify, status is %02x\n", (unsigned) status); 6496 break; 6497 } 6498 else { 6499 status = inb(0x1f7); 6500 if ( (status & 0xc9) != 0x48 ) 6501 BX_PANIC("more sectors left to read/verify, status is %02x\n", (unsigned) status); 6502 continue; 6503 } 6504 } 6505 6506 SET_AH(0); 6507 SET_DISK_RET_STATUS(0); 6508 SET_AL(sector_count); 6509 CLEAR_CF(); /* successful */ 6510 return; 6511 break; 6512 6513 6514 case 0x03: /* write disk sectors */ 6515 BX_DEBUG_INT13_HD("int13_f03\n"); 6516 drive = GET_ELDL (); 6517 get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors); 6518 6519 num_sectors = GET_AL(); 6520 cylinder = GET_CH(); 6521 cylinder |= ( ((Bit16u) GET_CL()) << 2) & 0x300; 6522 sector = (GET_CL() & 0x3f); 6523 head = GET_DH(); 6524 6525 if (hd_cylinders > 1024) { 6526 if (hd_cylinders <= 2048) { 6527 cylinder <<= 1; 6528 } 6529 else if (hd_cylinders <= 4096) { 6530 cylinder <<= 2; 6531 } 6532 else if (hd_cylinders <= 8192) { 6533 cylinder <<= 3; 6534 } 6535 else { // hd_cylinders <= 16384 6536 cylinder <<= 4; 6537 } 6538 6539 ax = head / hd_heads; 6540 cyl_mod = ax & 0xff; 6541 head = ax >> 8; 6542 cylinder |= cyl_mod; 6543 } 6544 6545 if ( (cylinder >= hd_cylinders) || 6546 (sector > hd_sectors) || 6547 (head >= hd_heads) ) { 6548 SET_AH( 1); 6549 SET_DISK_RET_STATUS(1); 6550 SET_CF(); /* error occurred */ 6551 return; 6552 } 6553 6554 if ( (num_sectors > 128) || (num_sectors == 0) ) 6555 BX_PANIC("int13_harddisk: num_sectors out of range!\n"); 6556 6557 if (head > 15) 6558 BX_PANIC("hard drive BIOS:(read) head > 15\n"); 6559 6560 status = inb(0x1f7); 6561 if (status & 0x80) { 6562 BX_PANIC("hard drive BIOS:(read) BUSY bit set\n"); 6563 } 6564 // should check for Drive Ready Bit also in status reg 6565 outb(0x01f2, num_sectors); 6566 6567 /* activate LBA? (tomv) */ 6568 if (hd_heads > 16) { 6569 BX_DEBUG_INT13_HD("CHS (write): %x %x %x\n", cylinder, head, sector); 6570 outLBA(cylinder,hd_heads,head,hd_sectors,sector,GET_ELDL()); 6571 } 6572 else { 6573 outb(0x01f3, sector); 6574 outb(0x01f4, cylinder & 0x00ff); 6575 outb(0x01f5, cylinder >> 8); 6576 outb(0x01f6, 0xa0 | ((GET_ELDL() & 0x01)<<4) | (head & 0x0f)); 6577 } 6578 outb(0x01f7, 0x30); 6579 6580 // wait for busy bit to turn off after seeking 6581 while (1) { 6582 status = inb(0x1f7); 6583 if ( !(status & 0x80) ) break; 6584 } 6585 6586 if ( !(status & 0x08) ) { 6587 BX_DEBUG_INT13_HD("status was %02x\n", (unsigned) status); 6588 BX_PANIC("hard drive BIOS:(write) data-request bit not set\n"); 6589 } 6590 6591 sector_count = 0; 6592 tempbx = BX; 6593 6594 ASM_START 6595 sti ;; enable higher priority interrupts 6596 ASM_END 6597 6598 while (1) { 6599 ASM_START 6600 ;; store temp bx in real SI register 6601 push bp 6602 mov bp, sp 6603 mov si, _int13_harddisk.tempbx + 2 [bp] 6604 pop bp 6605 6606 ;; adjust if there will be an overrun 6607 cmp si, #0xfe00 6608 jbe i13_f03_no_adjust 6609 i13_f03_adjust: 6610 sub si, #0x0200 ; sub 512 bytes from offset 6611 mov ax, es 6612 add ax, #0x0020 ; add 512 to segment 6613 mov es, ax 6614 6615 i13_f03_no_adjust: 6616 mov cx, #0x0100 ;; counter (256 words = 512b) 6617 mov dx, #0x01f0 ;; AT data read port 6618 6619 seg ES 6620 rep 6621 outsw ;; CX words tranfered from ES:[SI] to port(DX) 6622 6623 ;; store real SI register back to temp bx 6624 push bp 6625 mov bp, sp 6626 mov _int13_harddisk.tempbx + 2 [bp], si 6627 pop bp 6628 ASM_END 6629 6630 sector_count++; 6631 num_sectors--; 6632 if (num_sectors == 0) { 6633 status = inb(0x1f7); 6634 if ( (status & 0xe9) != 0x40 ) 6635 BX_PANIC("no sectors left to write, status is %02x\n", (unsigned) status); 6636 break; 6637 } 6638 else { 6639 status = inb(0x1f7); 6640 if ( (status & 0xc9) != 0x48 ) 6641 BX_PANIC("more sectors left to write, status is %02x\n", (unsigned) status); 6642 continue; 6643 } 6644 } 6645 6646 SET_AH(0); 6647 SET_DISK_RET_STATUS(0); 6648 SET_AL(sector_count); 6649 CLEAR_CF(); /* successful */ 6650 return; 6651 break; 6652 6653 case 0x05: /* format disk track */ 6654 BX_DEBUG_INT13_HD("int13_f05\n"); 6655 BX_PANIC("format disk track called\n"); 6656 /* nop */ 6657 SET_AH(0); 6658 SET_DISK_RET_STATUS(0); 6659 CLEAR_CF(); /* successful */ 6660 return; 6661 break; 6662 6663 case 0x08: /* read disk drive parameters */ 6664 BX_DEBUG_INT13_HD("int13_f08\n"); 6665 6666 drive = GET_ELDL (); 6667 get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors); 6668 6669 // translate CHS 6670 // 6671 if (hd_cylinders <= 1024) { 6672 // hd_cylinders >>= 0; 6673 // hd_heads <<= 0; 6674 } 6675 else if (hd_cylinders <= 2048) { 6676 hd_cylinders >>= 1; 6677 hd_heads <<= 1; 6678 } 6679 else if (hd_cylinders <= 4096) { 6680 hd_cylinders >>= 2; 6681 hd_heads <<= 2; 6682 } 6683 else if (hd_cylinders <= 8192) { 6684 hd_cylinders >>= 3; 6685 hd_heads <<= 3; 6686 } 6687 else { // hd_cylinders <= 16384 6688 hd_cylinders >>= 4; 6689 hd_heads <<= 4; 6690 } 6691 6692 max_cylinder = hd_cylinders - 2; /* 0 based */ 6693 SET_AL(0); 6694 SET_CH(max_cylinder & 0xff); 6695 SET_CL(((max_cylinder >> 2) & 0xc0) | (hd_sectors & 0x3f)); 6696 SET_DH(hd_heads - 1); 6697 SET_DL(n_drives); /* returns 0, 1, or 2 hard drives */ 6698 SET_AH(0); 6699 SET_DISK_RET_STATUS(0); 6700 CLEAR_CF(); /* successful */ 6701 6702 return; 6703 break; 6704 6705 case 0x09: /* initialize drive parameters */ 6706 BX_DEBUG_INT13_HD("int13_f09\n"); 6707 SET_AH(0); 6708 SET_DISK_RET_STATUS(0); 6709 CLEAR_CF(); /* successful */ 6710 return; 6711 break; 6712 6713 case 0x0a: /* read disk sectors with ECC */ 6714 BX_DEBUG_INT13_HD("int13_f0a\n"); 6715 case 0x0b: /* write disk sectors with ECC */ 6716 BX_DEBUG_INT13_HD("int13_f0b\n"); 6717 BX_PANIC("int13h Functions 0Ah & 0Bh not implemented!\n"); 6718 return; 6719 break; 6720 6721 case 0x0c: /* seek to specified cylinder */ 6722 BX_DEBUG_INT13_HD("int13_f0c\n"); 6723 BX_INFO("int13h function 0ch (seek) not implemented!\n"); 6724 SET_AH(0); 6725 SET_DISK_RET_STATUS(0); 6726 CLEAR_CF(); /* successful */ 6727 return; 6728 break; 6729 6730 case 0x0d: /* alternate disk reset */ 6731 BX_DEBUG_INT13_HD("int13_f0d\n"); 6732 SET_AH(0); 6733 SET_DISK_RET_STATUS(0); 6734 CLEAR_CF(); /* successful */ 6735 return; 6736 break; 6737 6738 case 0x10: /* check drive ready */ 6739 BX_DEBUG_INT13_HD("int13_f10\n"); 6740 //SET_AH(0); 6741 //SET_DISK_RET_STATUS(0); 6742 //CLEAR_CF(); /* successful */ 6743 //return; 6744 //break; 6745 6746 // should look at 40:8E also??? 6747 status = inb(0x01f7); 6748 if ( (status & 0xc0) == 0x40 ) { 6749 SET_AH(0); 6750 SET_DISK_RET_STATUS(0); 6751 CLEAR_CF(); // drive ready 6752 return; 6753 } 6754 else { 6755 SET_AH(0xAA); 6756 SET_DISK_RET_STATUS(0xAA); 6757 SET_CF(); // not ready 6758 return; 6759 } 6760 break; 6761 6762 case 0x11: /* recalibrate */ 6763 BX_DEBUG_INT13_HD("int13_f11\n"); 6764 SET_AH(0); 6765 SET_DISK_RET_STATUS(0); 6766 CLEAR_CF(); /* successful */ 6767 return; 6768 break; 6769 6770 case 0x14: /* controller internal diagnostic */ 6771 BX_DEBUG_INT13_HD("int13_f14\n"); 6772 SET_AH(0); 6773 SET_DISK_RET_STATUS(0); 6774 CLEAR_CF(); /* successful */ 6775 SET_AL(0); 6776 return; 6777 break; 6778 6779 case 0x15: /* read disk drive size */ 6780 drive = GET_ELDL(); 6781 get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors); 6782 ASM_START 6783 push bp 6784 mov bp, sp 6785 mov al, _int13_harddisk.hd_heads + 2 [bp] 6786 mov ah, _int13_harddisk.hd_sectors + 2 [bp] 6787 mul al, ah ;; ax = heads * sectors 6788 mov bx, _int13_harddisk.hd_cylinders + 2 [bp] 6789 dec bx ;; use (cylinders - 1) ??? 6790 mul ax, bx ;; dx:ax = (cylinders -1) * (heads * sectors) 6791 ;; now we need to move the 32bit result dx:ax to what the 6792 ;; BIOS wants which is cx:dx. 6793 ;; and then into CX:DX on the stack 6794 mov _int13_harddisk.CX + 2 [bp], dx 6795 mov _int13_harddisk.DX + 2 [bp], ax 6796 pop bp 6797 ASM_END 6798 SET_AH(3); // hard disk accessible 6799 SET_DISK_RET_STATUS(0); // ??? should this be 0 6800 CLEAR_CF(); // successful 6801 return; 6802 break; 6803 6804 case 0x18: // set media type for format 6805 case 0x41: // IBM/MS 6806 case 0x42: // IBM/MS 6807 case 0x43: // IBM/MS 6808 case 0x44: // IBM/MS 6809 case 0x45: // IBM/MS lock/unlock drive 6810 case 0x46: // IBM/MS eject media 6811 case 0x47: // IBM/MS extended seek 6812 case 0x49: // IBM/MS extended media change 6813 case 0x50: // IBM/MS send packet command 6814 default: 6815 BX_INFO("int13_harddisk: unsupported AH=%02x\n", GET_AH()); 6816 6817 SET_AH(1); // code=invalid function in AH or invalid parameter 6818 SET_DISK_RET_STATUS(1); 6819 SET_CF(); /* unsuccessful */ 6820 return; 6821 break; 6822 } 6823 } 6824 6825 static char panic_msg_reg12h[] = "HD%d cmos reg 12h not type F\n"; 6826 static char panic_msg_reg19h[] = "HD%d cmos reg %02xh not user definable type 47\n"; 6827 6828 void 6829 get_hd_geometry(drive, hd_cylinders, hd_heads, hd_sectors) 6830 Bit8u drive; 6831 Bit16u *hd_cylinders; 6832 Bit8u *hd_heads; 6833 Bit8u *hd_sectors; 6834 { 6835 Bit8u hd_type; 6836 Bit16u ss; 6837 Bit16u cylinders; 6838 Bit8u iobase; 6839 6840 ss = get_SS(); 6841 if (drive == 0x80) { 6842 hd_type = inb_cmos(0x12) & 0xf0; 6843 if (hd_type != 0xf0) 6844 BX_INFO(panic_msg_reg12h,0); 6845 hd_type = inb_cmos(0x19); // HD0: extended type 6846 if (hd_type != 47) 6847 BX_INFO(panic_msg_reg19h,0,0x19); 6848 iobase = 0x1b; 6849 } else { 6850 hd_type = inb_cmos(0x12) & 0x0f; 6851 if (hd_type != 0x0f) 6852 BX_INFO(panic_msg_reg12h,1); 6853 hd_type = inb_cmos(0x1a); // HD1: extended type 6854 if (hd_type != 47) 6855 BX_INFO(panic_msg_reg19h,0,0x1a); 6856 iobase = 0x24; 6857 } 6858 6859 // cylinders 6860 cylinders = inb_cmos(iobase) | (inb_cmos(iobase+1) << 8); 6861 write_word(ss, hd_cylinders, cylinders); 6862 6863 // heads 6864 write_byte(ss, hd_heads, inb_cmos(iobase+2)); 6865 6866 // sectors per track 6867 write_byte(ss, hd_sectors, inb_cmos(iobase+8)); 6868 } 6869 6870 #endif //else BX_USE_ATADRV 6871 6872 #if BX_SUPPORT_FLOPPY 6873 6874 ////////////////////// 6875 // FLOPPY functions // 6876 ////////////////////// 6877 6878 void floppy_reset_controller() 6879 { 6880 Bit8u val8; 6881 6882 // Reset controller 6883 val8 = inb(0x03f2); 6884 outb(0x03f2, val8 & ~0x04); 6885 outb(0x03f2, val8 | 0x04); 6886 6887 // Wait for controller to come out of reset 6888 do { 6889 val8 = inb(0x3f4); 6890 } while ( (val8 & 0xc0) != 0x80 ); 6891 } 6892 6893 void floppy_prepare_controller(drive) 6894 Bit16u drive; 6895 { 6896 Bit8u val8, dor, prev_reset; 6897 6898 // set 40:3e bit 7 to 0 6899 val8 = read_byte(0x0040, 0x003e); 6900 val8 &= 0x7f; 6901 write_byte(0x0040, 0x003e, val8); 6902 6903 // turn on motor of selected drive, DMA & int enabled, normal operation 6904 prev_reset = inb(0x03f2) & 0x04; 6905 if (drive) 6906 dor = 0x20; 6907 else 6908 dor = 0x10; 6909 dor |= 0x0c; 6910 dor |= drive; 6911 outb(0x03f2, dor); 6912 6913 // reset the disk motor timeout value of INT 08 6914 write_byte(0x40,0x40, BX_FLOPPY_ON_CNT); 6915 6916 // wait for drive readiness 6917 do { 6918 val8 = inb(0x3f4); 6919 } while ( (val8 & 0xc0) != 0x80 ); 6920 6921 if (prev_reset == 0) { 6922 // turn on interrupts 6923 ASM_START 6924 sti 6925 ASM_END 6926 // wait on 40:3e bit 7 to become 1 6927 do { 6928 val8 = read_byte(0x0040, 0x003e); 6929 } while ( (val8 & 0x80) == 0 ); 6930 val8 &= 0x7f; 6931 ASM_START 6932 cli 6933 ASM_END 6934 write_byte(0x0040, 0x003e, val8); 6935 } 6936 } 6937 6938 bx_bool 6939 floppy_media_known(drive) 6940 Bit16u drive; 6941 { 6942 Bit8u val8; 6943 Bit16u media_state_offset; 6944 6945 val8 = read_byte(0x0040, 0x003e); // diskette recal status 6946 if (drive) 6947 val8 >>= 1; 6948 val8 &= 0x01; 6949 if (val8 == 0) 6950 return(0); 6951 6952 media_state_offset = 0x0090; 6953 if (drive) 6954 media_state_offset += 1; 6955 6956 val8 = read_byte(0x0040, media_state_offset); 6957 val8 = (val8 >> 4) & 0x01; 6958 if (val8 == 0) 6959 return(0); 6960 6961 // check pass, return KNOWN 6962 return(1); 6963 } 6964 6965 bx_bool 6966 floppy_media_sense(drive) 6967 Bit16u drive; 6968 { 6969 bx_bool retval; 6970 Bit16u media_state_offset; 6971 Bit8u drive_type, config_data, media_state; 6972 6973 if (floppy_drive_recal(drive) == 0) { 6974 return(0); 6975 } 6976 6977 // for now cheat and get drive type from CMOS, 6978 // assume media is same as drive type 6979 6980 // ** config_data ** 6981 // Bitfields for diskette media control: 6982 // Bit(s) Description (Table M0028) 6983 // 7-6 last data rate set by controller 6984 // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps 6985 // 5-4 last diskette drive step rate selected 6986 // 00=0Ch, 01=0Dh, 10=0Eh, 11=0Ah 6987 // 3-2 {data rate at start of operation} 6988 // 1-0 reserved 6989 6990 // ** media_state ** 6991 // Bitfields for diskette drive media state: 6992 // Bit(s) Description (Table M0030) 6993 // 7-6 data rate 6994 // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps 6995 // 5 double stepping required (e.g. 360kB in 1.2MB) 6996 // 4 media type established 6997 // 3 drive capable of supporting 4MB media 6998 // 2-0 on exit from BIOS, contains 6999 // 000 trying 360kB in 360kB 7000 // 001 trying 360kB in 1.2MB 7001 // 010 trying 1.2MB in 1.2MB 7002 // 011 360kB in 360kB established 7003 // 100 360kB in 1.2MB established 7004 // 101 1.2MB in 1.2MB established 7005 // 110 reserved 7006 // 111 all other formats/drives 7007 7008 drive_type = inb_cmos(0x10); 7009 if (drive == 0) 7010 drive_type >>= 4; 7011 else 7012 drive_type &= 0x0f; 7013 if ( drive_type == 1 ) { 7014 // 360K 5.25" drive 7015 config_data = 0x00; // 0000 0000 7016 media_state = 0x25; // 0010 0101 7017 retval = 1; 7018 } 7019 else if ( drive_type == 2 ) { 7020 // 1.2 MB 5.25" drive 7021 config_data = 0x00; // 0000 0000 7022 media_state = 0x25; // 0010 0101 // need double stepping??? (bit 5) 7023 retval = 1; 7024 } 7025 else if ( drive_type == 3 ) { 7026 // 720K 3.5" drive 7027 config_data = 0x00; // 0000 0000 ??? 7028 media_state = 0x17; // 0001 0111 7029 retval = 1; 7030 } 7031 else if ( drive_type == 4 ) { 7032 // 1.44 MB 3.5" drive 7033 config_data = 0x00; // 0000 0000 7034 media_state = 0x17; // 0001 0111 7035 retval = 1; 7036 } 7037 else if ( drive_type == 5 ) { 7038 // 2.88 MB 3.5" drive 7039 config_data = 0xCC; // 1100 1100 7040 media_state = 0xD7; // 1101 0111 7041 retval = 1; 7042 } 7043 // 7044 // Extended floppy size uses special cmos setting 7045 else if ( drive_type == 6 ) { 7046 // 160k 5.25" drive 7047 config_data = 0x00; // 0000 0000 7048 media_state = 0x27; // 0010 0111 7049 retval = 1; 7050 } 7051 else if ( drive_type == 7 ) { 7052 // 180k 5.25" drive 7053 config_data = 0x00; // 0000 0000 7054 media_state = 0x27; // 0010 0111 7055 retval = 1; 7056 } 7057 else if ( drive_type == 8 ) { 7058 // 320k 5.25" drive 7059 config_data = 0x00; // 0000 0000 7060 media_state = 0x27; // 0010 0111 7061 retval = 1; 7062 } 7063 7064 else { 7065 // not recognized 7066 config_data = 0x00; // 0000 0000 7067 media_state = 0x00; // 0000 0000 7068 retval = 0; 7069 } 7070 7071 if (drive == 0) 7072 media_state_offset = 0x90; 7073 else 7074 media_state_offset = 0x91; 7075 write_byte(0x0040, 0x008B, config_data); 7076 write_byte(0x0040, media_state_offset, media_state); 7077 7078 return(retval); 7079 } 7080 7081 bx_bool 7082 floppy_drive_recal(drive) 7083 Bit16u drive; 7084 { 7085 Bit8u val8; 7086 Bit16u curr_cyl_offset; 7087 7088 floppy_prepare_controller(drive); 7089 7090 // send Recalibrate command (2 bytes) to controller 7091 outb(0x03f5, 0x07); // 07: Recalibrate 7092 outb(0x03f5, drive); // 0=drive0, 1=drive1 7093 7094 // turn on interrupts 7095 ASM_START 7096 sti 7097 ASM_END 7098 7099 // wait on 40:3e bit 7 to become 1 7100 do { 7101 val8 = (read_byte(0x0040, 0x003e) & 0x80); 7102 } while ( val8 == 0 ); 7103 7104 val8 = 0; // separate asm from while() loop 7105 // turn off interrupts 7106 ASM_START 7107 cli 7108 ASM_END 7109 7110 // set 40:3e bit 7 to 0, and calibrated bit 7111 val8 = read_byte(0x0040, 0x003e); 7112 val8 &= 0x7f; 7113 if (drive) { 7114 val8 |= 0x02; // Drive 1 calibrated 7115 curr_cyl_offset = 0x0095; 7116 } else { 7117 val8 |= 0x01; // Drive 0 calibrated 7118 curr_cyl_offset = 0x0094; 7119 } 7120 write_byte(0x0040, 0x003e, val8); 7121 write_byte(0x0040, curr_cyl_offset, 0); // current cylinder is 0 7122 7123 return(1); 7124 } 7125 7126 7127 7128 bx_bool 7129 floppy_drive_exists(drive) 7130 Bit16u drive; 7131 { 7132 Bit8u drive_type; 7133 7134 // check CMOS to see if drive exists 7135 drive_type = inb_cmos(0x10); 7136 if (drive == 0) 7137 drive_type >>= 4; 7138 else 7139 drive_type &= 0x0f; 7140 if ( drive_type == 0 ) 7141 return(0); 7142 else 7143 return(1); 7144 } 7145 7146 void 7147 int13_diskette_function(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) 7148 Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; 7149 { 7150 Bit8u drive, num_sectors, track, sector, head, status; 7151 Bit16u base_address, base_count, base_es; 7152 Bit8u page, mode_register, val8, dor; 7153 Bit8u return_status[7]; 7154 Bit8u drive_type, num_floppies, ah; 7155 Bit16u es, last_addr; 7156 7157 BX_DEBUG_INT13_FL("int13_diskette: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); 7158 7159 ah = GET_AH(); 7160 7161 switch ( ah ) { 7162 case 0x00: // diskette controller reset 7163 BX_DEBUG_INT13_FL("floppy f00\n"); 7164 drive = GET_ELDL(); 7165 if (drive > 1) { 7166 SET_AH(1); // invalid param 7167 set_diskette_ret_status(1); 7168 SET_CF(); 7169 return; 7170 } 7171 drive_type = inb_cmos(0x10); 7172 7173 if (drive == 0) 7174 drive_type >>= 4; 7175 else 7176 drive_type &= 0x0f; 7177 if (drive_type == 0) { 7178 SET_AH(0x80); // drive not responding 7179 set_diskette_ret_status(0x80); 7180 SET_CF(); 7181 return; 7182 } 7183 SET_AH(0); 7184 set_diskette_ret_status(0); 7185 CLEAR_CF(); // successful 7186 set_diskette_current_cyl(drive, 0); // current cylinder 7187 return; 7188 7189 case 0x01: // Read Diskette Status 7190 CLEAR_CF(); 7191 val8 = read_byte(0x0000, 0x0441); 7192 SET_AH(val8); 7193 if (val8) { 7194 SET_CF(); 7195 } 7196 return; 7197 7198 case 0x02: // Read Diskette Sectors 7199 case 0x03: // Write Diskette Sectors 7200 case 0x04: // Verify Diskette Sectors 7201 num_sectors = GET_AL(); 7202 track = GET_CH(); 7203 sector = GET_CL(); 7204 head = GET_DH(); 7205 drive = GET_ELDL(); 7206 7207 if ((drive > 1) || (head > 1) || (sector == 0) || 7208 (num_sectors == 0) || (num_sectors > 72)) { 7209 BX_INFO("int13_diskette: read/write/verify: parameter out of range\n"); 7210 SET_AH(1); 7211 set_diskette_ret_status(1); 7212 SET_AL(0); // no sectors read 7213 SET_CF(); // error occurred 7214 return; 7215 } 7216 7217 // see if drive exists 7218 if (floppy_drive_exists(drive) == 0) { 7219 SET_AH(0x80); // not responding 7220 set_diskette_ret_status(0x80); 7221 SET_AL(0); // no sectors read 7222 SET_CF(); // error occurred 7223 return; 7224 } 7225 7226 // see if media in drive, and type is known 7227 if (floppy_media_known(drive) == 0) { 7228 if (floppy_media_sense(drive) == 0) { 7229 SET_AH(0x0C); // Media type not found 7230 set_diskette_ret_status(0x0C); 7231 SET_AL(0); // no sectors read 7232 SET_CF(); // error occurred 7233 return; 7234 } 7235 } 7236 7237 if (ah == 0x02) { 7238 // Read Diskette Sectors 7239 7240 //----------------------------------- 7241 // set up DMA controller for transfer 7242 //----------------------------------- 7243 7244 // es:bx = pointer to where to place information from diskette 7245 // port 04: DMA-1 base and current address, channel 2 7246 // port 05: DMA-1 base and current count, channel 2 7247 page = (ES >> 12); // upper 4 bits 7248 base_es = (ES << 4); // lower 16bits contributed by ES 7249 base_address = base_es + BX; // lower 16 bits of address 7250 // contributed by ES:BX 7251 if ( base_address < base_es ) { 7252 // in case of carry, adjust page by 1 7253 page++; 7254 } 7255 base_count = (num_sectors * 512) - 1; 7256 7257 // check for 64K boundary overrun 7258 last_addr = base_address + base_count; 7259 if (last_addr < base_address) { 7260 SET_AH(0x09); 7261 set_diskette_ret_status(0x09); 7262 SET_AL(0); // no sectors read 7263 SET_CF(); // error occurred 7264 return; 7265 } 7266 7267 BX_DEBUG_INT13_FL("masking DMA-1 c2\n"); 7268 outb(0x000a, 0x06); 7269 7270 BX_DEBUG_INT13_FL("clear flip-flop\n"); 7271 outb(0x000c, 0x00); // clear flip-flop 7272 outb(0x0004, base_address); 7273 outb(0x0004, base_address>>8); 7274 BX_DEBUG_INT13_FL("clear flip-flop\n"); 7275 outb(0x000c, 0x00); // clear flip-flop 7276 outb(0x0005, base_count); 7277 outb(0x0005, base_count>>8); 7278 7279 // port 0b: DMA-1 Mode Register 7280 mode_register = 0x46; // single mode, increment, autoinit disable, 7281 // transfer type=write, channel 2 7282 BX_DEBUG_INT13_FL("setting mode register\n"); 7283 outb(0x000b, mode_register); 7284 7285 BX_DEBUG_INT13_FL("setting page register\n"); 7286 // port 81: DMA-1 Page Register, channel 2 7287 outb(0x0081, page); 7288 7289 BX_DEBUG_INT13_FL("unmask chan 2\n"); 7290 outb(0x000a, 0x02); // unmask channel 2 7291 7292 BX_DEBUG_INT13_FL("unmasking DMA-1 c2\n"); 7293 outb(0x000a, 0x02); 7294 7295 //-------------------------------------- 7296 // set up floppy controller for transfer 7297 //-------------------------------------- 7298 floppy_prepare_controller(drive); 7299 7300 // send read-normal-data command (9 bytes) to controller 7301 outb(0x03f5, 0xe6); // e6: read normal data 7302 outb(0x03f5, (head << 2) | drive); // HD DR1 DR2 7303 outb(0x03f5, track); 7304 outb(0x03f5, head); 7305 outb(0x03f5, sector); 7306 outb(0x03f5, 2); // 512 byte sector size 7307 outb(0x03f5, sector + num_sectors - 1); // last sector to read on track 7308 outb(0x03f5, 0); // Gap length 7309 outb(0x03f5, 0xff); // Gap length 7310 7311 // turn on interrupts 7312 ASM_START 7313 sti 7314 ASM_END 7315 7316 // wait on 40:3e bit 7 to become 1 7317 do { 7318 val8 = read_byte(0x0040, 0x0040); 7319 if (val8 == 0) { 7320 floppy_reset_controller(); 7321 SET_AH(0x80); // drive not ready (timeout) 7322 set_diskette_ret_status(0x80); 7323 SET_AL(0); // no sectors read 7324 SET_CF(); // error occurred 7325 return; 7326 } 7327 val8 = (read_byte(0x0040, 0x003e) & 0x80); 7328 } while ( val8 == 0 ); 7329 7330 val8 = 0; // separate asm from while() loop 7331 // turn off interrupts 7332 ASM_START 7333 cli 7334 ASM_END 7335 7336 // set 40:3e bit 7 to 0 7337 val8 = read_byte(0x0040, 0x003e); 7338 val8 &= 0x7f; 7339 write_byte(0x0040, 0x003e, val8); 7340 7341 // check port 3f4 for accessibility to status bytes 7342 val8 = inb(0x3f4); 7343 if ( (val8 & 0xc0) != 0xc0 ) 7344 BX_PANIC("int13_diskette: ctrl not ready\n"); 7345 7346 // read 7 return status bytes from controller 7347 // using loop index broken, have to unroll... 7348 return_status[0] = inb(0x3f5); 7349 return_status[1] = inb(0x3f5); 7350 return_status[2] = inb(0x3f5); 7351 return_status[3] = inb(0x3f5); 7352 return_status[4] = inb(0x3f5); 7353 return_status[5] = inb(0x3f5); 7354 return_status[6] = inb(0x3f5); 7355 // record in BIOS Data Area 7356 write_byte(0x0040, 0x0042, return_status[0]); 7357 write_byte(0x0040, 0x0043, return_status[1]); 7358 write_byte(0x0040, 0x0044, return_status[2]); 7359 write_byte(0x0040, 0x0045, return_status[3]); 7360 write_byte(0x0040, 0x0046, return_status[4]); 7361 write_byte(0x0040, 0x0047, return_status[5]); 7362 write_byte(0x0040, 0x0048, return_status[6]); 7363 7364 if ( (return_status[0] & 0xc0) != 0 ) { 7365 SET_AH(0x20); 7366 set_diskette_ret_status(0x20); 7367 SET_AL(0); // no sectors read 7368 SET_CF(); // error occurred 7369 return; 7370 } 7371 7372 // ??? should track be new val from return_status[3] ? 7373 set_diskette_current_cyl(drive, track); 7374 // AL = number of sectors read (same value as passed) 7375 SET_AH(0x00); // success 7376 CLEAR_CF(); // success 7377 return; 7378 } else if (ah == 0x03) { 7379 // Write Diskette Sectors 7380 7381 //----------------------------------- 7382 // set up DMA controller for transfer 7383 //----------------------------------- 7384 7385 // es:bx = pointer to where to place information from diskette 7386 // port 04: DMA-1 base and current address, channel 2 7387 // port 05: DMA-1 base and current count, channel 2 7388 page = (ES >> 12); // upper 4 bits 7389 base_es = (ES << 4); // lower 16bits contributed by ES 7390 base_address = base_es + BX; // lower 16 bits of address 7391 // contributed by ES:BX 7392 if ( base_address < base_es ) { 7393 // in case of carry, adjust page by 1 7394 page++; 7395 } 7396 base_count = (num_sectors * 512) - 1; 7397 7398 // check for 64K boundary overrun 7399 last_addr = base_address + base_count; 7400 if (last_addr < base_address) { 7401 SET_AH(0x09); 7402 set_diskette_ret_status(0x09); 7403 SET_AL(0); // no sectors read 7404 SET_CF(); // error occurred 7405 return; 7406 } 7407 7408 BX_DEBUG_INT13_FL("masking DMA-1 c2\n"); 7409 outb(0x000a, 0x06); 7410 7411 outb(0x000c, 0x00); // clear flip-flop 7412 outb(0x0004, base_address); 7413 outb(0x0004, base_address>>8); 7414 outb(0x000c, 0x00); // clear flip-flop 7415 outb(0x0005, base_count); 7416 outb(0x0005, base_count>>8); 7417 7418 // port 0b: DMA-1 Mode Register 7419 mode_register = 0x4a; // single mode, increment, autoinit disable, 7420 // transfer type=read, channel 2 7421 outb(0x000b, mode_register); 7422 7423 // port 81: DMA-1 Page Register, channel 2 7424 outb(0x0081, page); 7425 7426 BX_DEBUG_INT13_FL("unmasking DMA-1 c2\n"); 7427 outb(0x000a, 0x02); 7428 7429 //-------------------------------------- 7430 // set up floppy controller for transfer 7431 //-------------------------------------- 7432 floppy_prepare_controller(drive); 7433 7434 // send write-normal-data command (9 bytes) to controller 7435 outb(0x03f5, 0xc5); // c5: write normal data 7436 outb(0x03f5, (head << 2) | drive); // HD DR1 DR2 7437 outb(0x03f5, track); 7438 outb(0x03f5, head); 7439 outb(0x03f5, sector); 7440 outb(0x03f5, 2); // 512 byte sector size 7441 outb(0x03f5, sector + num_sectors - 1); // last sector to write on track 7442 outb(0x03f5, 0); // Gap length 7443 outb(0x03f5, 0xff); // Gap length 7444 7445 // turn on interrupts 7446 ASM_START 7447 sti 7448 ASM_END 7449 7450 // wait on 40:3e bit 7 to become 1 7451 do { 7452 val8 = read_byte(0x0040, 0x0040); 7453 if (val8 == 0) { 7454 floppy_reset_controller(); 7455 SET_AH(0x80); // drive not ready (timeout) 7456 set_diskette_ret_status(0x80); 7457 SET_AL(0); // no sectors written 7458 SET_CF(); // error occurred 7459 return; 7460 } 7461 val8 = (read_byte(0x0040, 0x003e) & 0x80); 7462 } while ( val8 == 0 ); 7463 7464 val8 = 0; // separate asm from while() loop 7465 // turn off interrupts 7466 ASM_START 7467 cli 7468 ASM_END 7469 7470 // set 40:3e bit 7 to 0 7471 val8 = read_byte(0x0040, 0x003e); 7472 val8 &= 0x7f; 7473 write_byte(0x0040, 0x003e, val8); 7474 7475 // check port 3f4 for accessibility to status bytes 7476 val8 = inb(0x3f4); 7477 if ( (val8 & 0xc0) != 0xc0 ) 7478 BX_PANIC("int13_diskette: ctrl not ready\n"); 7479 7480 // read 7 return status bytes from controller 7481 // using loop index broken, have to unroll... 7482 return_status[0] = inb(0x3f5); 7483 return_status[1] = inb(0x3f5); 7484 return_status[2] = inb(0x3f5); 7485 return_status[3] = inb(0x3f5); 7486 return_status[4] = inb(0x3f5); 7487 return_status[5] = inb(0x3f5); 7488 return_status[6] = inb(0x3f5); 7489 // record in BIOS Data Area 7490 write_byte(0x0040, 0x0042, return_status[0]); 7491 write_byte(0x0040, 0x0043, return_status[1]); 7492 write_byte(0x0040, 0x0044, return_status[2]); 7493 write_byte(0x0040, 0x0045, return_status[3]); 7494 write_byte(0x0040, 0x0046, return_status[4]); 7495 write_byte(0x0040, 0x0047, return_status[5]); 7496 write_byte(0x0040, 0x0048, return_status[6]); 7497 7498 if ( (return_status[0] & 0xc0) != 0 ) { 7499 if ( (return_status[1] & 0x02) != 0 ) { 7500 // diskette not writable. 7501 // AH=status code=0x03 (tried to write on write-protected disk) 7502 // AL=number of sectors written=0 7503 AX = 0x0300; 7504 SET_CF(); 7505 return; 7506 } else { 7507 BX_PANIC("int13_diskette_function: read error\n"); 7508 } 7509 } 7510 7511 // ??? should track be new val from return_status[3] ? 7512 set_diskette_current_cyl(drive, track); 7513 // AL = number of sectors read (same value as passed) 7514 SET_AH(0x00); // success 7515 CLEAR_CF(); // success 7516 return; 7517 } else { // if (ah == 0x04) 7518 // Verify Diskette Sectors 7519 7520 // ??? should track be new val from return_status[3] ? 7521 set_diskette_current_cyl(drive, track); 7522 // AL = number of sectors verified (same value as passed) 7523 CLEAR_CF(); // success 7524 SET_AH(0x00); // success 7525 return; 7526 } 7527 break; 7528 7529 case 0x05: // format diskette track 7530 BX_DEBUG_INT13_FL("floppy f05\n");