Home | History | Annotate | Download | only in bios
      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) {
   3