ia64/xen-unstable

changeset 18941:0a393ba0ec0a

rombios: Update to Bochs latest

Signed-off-by: Akio Takebe <takebe_akio@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Dec 18 14:52:53 2008 +0000 (2008-12-18)
parents 768759d4e319
children 54c5d8247aaf
files tools/firmware/rombios/rombios.c tools/firmware/rombios/rombios.h
line diff
     1.1 --- a/tools/firmware/rombios/rombios.c	Thu Dec 18 11:29:33 2008 +0000
     1.2 +++ b/tools/firmware/rombios/rombios.c	Thu Dec 18 14:52:53 2008 +0000
     1.3 @@ -1,5 +1,5 @@
     1.4  /////////////////////////////////////////////////////////////////////////
     1.5 -// $Id: rombios.c,v 1.138 2005/05/07 15:55:26 vruppert Exp $
     1.6 +// $Id: rombios.c,v 1.221 2008/12/07 17:32:29 sshwarts Exp $
     1.7  /////////////////////////////////////////////////////////////////////////
     1.8  //
     1.9  //  Copyright (C) 2002  MandrakeSoft S.A.
    1.10 @@ -22,9 +22,9 @@
    1.11  //
    1.12  //  You should have received a copy of the GNU Lesser General Public
    1.13  //  License along with this library; if not, write to the Free Software
    1.14 -//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    1.15 -
    1.16 -// ROM BIOS for use with Bochs/Plex x86 emulation environment
    1.17 +//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
    1.18 +
    1.19 +// ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
    1.20  
    1.21  #define uint8_t unsigned char
    1.22  #define uint16_t unsigned short
    1.23 @@ -81,10 +81,10 @@
    1.24  //
    1.25  // NOTES for El-Torito Boot (cbbochs@free.fr)
    1.26  //   - CD-ROM booting is only available if ATA/ATAPI Driver is available
    1.27 -//   - Current code is only able to boot mono-session cds 
    1.28 +//   - Current code is only able to boot mono-session cds
    1.29  //   - Current code can not boot and emulate a hard-disk
    1.30  //     the bios will panic otherwise
    1.31 -//   - Current code also use memory in EBDA segement. 
    1.32 +//   - Current code also use memory in EBDA segement.
    1.33  //   - I used cmos byte 0x3D to store extended information on boot-device
    1.34  //   - Code has to be modified modified to handle multiple cdrom drives
    1.35  //   - Here are the cdrom boot failure codes:
    1.36 @@ -102,13 +102,13 @@
    1.37  //      12 : can not read cd - boot image
    1.38  //
    1.39  //   ATA driver
    1.40 -//   - EBDA segment. 
    1.41 +//   - EBDA segment.
    1.42  //     I used memory starting at 0x121 in the segment
    1.43  //   - the translation policy is defined in cmos regs 0x39 & 0x3a
    1.44  //
    1.45  // TODO :
    1.46  //
    1.47 -//   int74 
    1.48 +//   int74
    1.49  //     - needs to be reworked.  Uses direct [bp] offsets. (?)
    1.50  //
    1.51  //   int13:
    1.52 @@ -128,13 +128,13 @@
    1.53  //   - Implement remaining int13_cdemu functions (as defined by El-Torito specs)
    1.54  //   - cdrom drive is hardcoded to ide 0 device 1 in several places. see "FIXME ElTorito Hardcoded"
    1.55  //   - int13 Fix DL when emulating a cd. In that case DL is decremented before calling real int13.
    1.56 -//     This is ok. But DL should be reincremented afterwards. 
    1.57 +//     This is ok. But DL should be reincremented afterwards.
    1.58  //   - Fix all "FIXME ElTorito Various"
    1.59  //   - should be able to boot any cdrom instead of the first one
    1.60  //
    1.61  //   BCC Bug: find a generic way to handle the bug of #asm after an "if"  (fixed in 0.16.7)
    1.62  
    1.63 -#define DEBUG_ROMBIOS      0
    1.64 +#include "rombios.h"
    1.65  
    1.66  #define DEBUG_ATA          0
    1.67  #define DEBUG_INT13_HD     0
    1.68 @@ -159,7 +159,7 @@
    1.69  #define BX_USE_ATADRV    1
    1.70  #define BX_ELTORITO_BOOT 1
    1.71  
    1.72 -#define BX_TCGBIOS       0              /* main switch for TCG BIOS ext. */
    1.73 +#define BX_TCGBIOS       0   /* main switch for TCG BIOS ext. */
    1.74  
    1.75  #define BX_MAX_ATA_INTERFACES   4
    1.76  #define BX_MAX_ATA_DEVICES      (BX_MAX_ATA_INTERFACES*2)
    1.77 @@ -181,7 +181,6 @@
    1.78    // EBDA is used for PS/2 mouse support, and IDE BIOS, etc.
    1.79  #define EBDA_SEG           0x9FC0
    1.80  #define EBDA_SIZE          1              // In KiB
    1.81 -#define EBDA_SEG_PTR       0x40E /* Find true EBDA segment at 0:40E */
    1.82  #define BASE_MEM_IN_K   (640 - EBDA_SIZE)
    1.83  
    1.84  /* 256 bytes at 0x9ff00 -- 0x9ffff is used for the IPL boot table. */
    1.85 @@ -189,15 +188,13 @@
    1.86  #define IPL_TABLE_ENTRIES    8
    1.87  #define IPL_COUNT_OFFSET     0x0380  /* u16: number of valid table entries */
    1.88  #define IPL_SEQUENCE_OFFSET  0x0382  /* u16: next boot device */
    1.89 -
    1.90 -  // Define the application NAME
    1.91 -#ifdef HVMASSIST
    1.92 -#  define BX_APPNAME "HVMAssist"
    1.93 -#elif PLEX86
    1.94 -#  define BX_APPNAME "Plex86"
    1.95 -#else
    1.96 -#  define BX_APPNAME "Bochs"
    1.97 -#endif
    1.98 +#define IPL_BOOTFIRST_OFFSET 0x0384  /* u16: user selected device */
    1.99 +#define IPL_SIZE             0xff
   1.100 +#define IPL_TYPE_FLOPPY      0x01
   1.101 +#define IPL_TYPE_HARDDISK    0x02
   1.102 +#define IPL_TYPE_CDROM       0x03
   1.103 +#define IPL_TYPE_BEV         0x80
   1.104 +
   1.105  
   1.106    // Sanity Checks
   1.107  #if BX_USE_ATADRV && BX_CPU<3
   1.108 @@ -216,15 +213,10 @@
   1.109  #    error APM BIOS can only be used with 386+ cpu
   1.110  #endif
   1.111  
   1.112 -#ifndef BX_SMP_PROCESSORS
   1.113 -#define BX_SMP_PROCESSORS 1
   1.114 -#    warning BX_SMP_PROCESSORS not defined, defaulting to 1
   1.115 -#endif
   1.116 -  
   1.117 -#define PANIC_PORT  0x400
   1.118 -#define PANIC_PORT2 0x401
   1.119 -#define INFO_PORT   0x402
   1.120 -#define DEBUG_PORT  0x403
   1.121 +// define this if you want to make PCIBIOS working on a specific bridge only
   1.122 +// undef enables PCIBIOS when at least one PCI device is found
   1.123 +// i440FX is emulated by Bochs and QEMU
   1.124 +#define PCI_FIXED_HOST_BRIDGE 0x12378086 ;; i440FX PCI bridge
   1.125  
   1.126  // #20  is dec 20
   1.127  // #$20 is hex 20 = 32
   1.128 @@ -257,7 +249,7 @@ use16 286
   1.129  
   1.130  MACRO HALT
   1.131    ;; the HALT macro is called with the line number of the HALT call.
   1.132 -  ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex 
   1.133 +  ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex
   1.134    ;; to print a BX_PANIC message.  This will normally halt the simulation
   1.135    ;; with a message such as "BIOS panic at rombios.c, line 4091".
   1.136    ;; However, users can choose to make panics non-fatal and continue.
   1.137 @@ -296,9 +288,9 @@ typedef unsigned long  Bit32u;
   1.138    void memsetb(seg,offset,value,count);
   1.139    void memcpyb(dseg,doffset,sseg,soffset,count);
   1.140    void memcpyd(dseg,doffset,sseg,soffset,count);
   1.141 -  
   1.142 +
   1.143    // memset of count bytes
   1.144 -    void 
   1.145 +    void
   1.146    memsetb(seg,offset,value,count)
   1.147      Bit16u seg;
   1.148      Bit16u offset;
   1.149 @@ -308,14 +300,14 @@ typedef unsigned long  Bit32u;
   1.150    ASM_START
   1.151      push bp
   1.152      mov  bp, sp
   1.153 -  
   1.154 +
   1.155        push ax
   1.156        push cx
   1.157        push es
   1.158        push di
   1.159 -  
   1.160 +
   1.161        mov  cx, 10[bp] ; count
   1.162 -      cmp  cx, #0x00
   1.163 +      test cx, cx
   1.164        je   memsetb_end
   1.165        mov  ax, 4[bp] ; segment
   1.166        mov  es, ax
   1.167 @@ -325,19 +317,19 @@ typedef unsigned long  Bit32u;
   1.168        cld
   1.169        rep
   1.170         stosb
   1.171 -  
   1.172 +
   1.173    memsetb_end:
   1.174        pop di
   1.175        pop es
   1.176        pop cx
   1.177        pop ax
   1.178 -  
   1.179 +
   1.180      pop bp
   1.181    ASM_END
   1.182    }
   1.183 -  
   1.184 +
   1.185    // memcpy of count bytes
   1.186 -    void 
   1.187 +    void
   1.188    memcpyb(dseg,doffset,sseg,soffset,count)
   1.189      Bit16u dseg;
   1.190      Bit16u doffset;
   1.191 @@ -348,16 +340,16 @@ typedef unsigned long  Bit32u;
   1.192    ASM_START
   1.193      push bp
   1.194      mov  bp, sp
   1.195 -  
   1.196 +
   1.197        push ax
   1.198        push cx
   1.199        push es
   1.200        push di
   1.201        push ds
   1.202        push si
   1.203 -  
   1.204 +
   1.205        mov  cx, 12[bp] ; count
   1.206 -      cmp  cx, #0x0000
   1.207 +      test cx, cx
   1.208        je   memcpyb_end
   1.209        mov  ax, 4[bp] ; dsegment
   1.210        mov  es, ax
   1.211 @@ -370,7 +362,7 @@ typedef unsigned long  Bit32u;
   1.212        cld
   1.213        rep
   1.214         movsb
   1.215 -  
   1.216 +
   1.217    memcpyb_end:
   1.218        pop si
   1.219        pop ds
   1.220 @@ -378,14 +370,13 @@ typedef unsigned long  Bit32u;
   1.221        pop es
   1.222        pop cx
   1.223        pop ax
   1.224 -  
   1.225 +
   1.226      pop bp
   1.227    ASM_END
   1.228    }
   1.229  
   1.230 -#if 0 
   1.231    // memcpy of count dword
   1.232 -    void 
   1.233 +    void
   1.234    memcpyd(dseg,doffset,sseg,soffset,count)
   1.235      Bit16u dseg;
   1.236      Bit16u doffset;
   1.237 @@ -396,16 +387,16 @@ typedef unsigned long  Bit32u;
   1.238    ASM_START
   1.239      push bp
   1.240      mov  bp, sp
   1.241 -  
   1.242 +
   1.243        push ax
   1.244        push cx
   1.245        push es
   1.246        push di
   1.247        push ds
   1.248        push si
   1.249 -  
   1.250 +
   1.251        mov  cx, 12[bp] ; count
   1.252 -      cmp  cx, #0x0000
   1.253 +      test cx, cx
   1.254        je   memcpyd_end
   1.255        mov  ax, 4[bp] ; dsegment
   1.256        mov  es, ax
   1.257 @@ -418,7 +409,7 @@ typedef unsigned long  Bit32u;
   1.258        cld
   1.259        rep
   1.260         movsd
   1.261 -  
   1.262 +
   1.263    memcpyd_end:
   1.264        pop si
   1.265        pop ds
   1.266 @@ -426,16 +417,15 @@ typedef unsigned long  Bit32u;
   1.267        pop es
   1.268        pop cx
   1.269        pop ax
   1.270 -  
   1.271 +
   1.272      pop bp
   1.273    ASM_END
   1.274    }
   1.275 -#endif
   1.276  
   1.277    // read_dword and write_dword functions
   1.278    static Bit32u         read_dword();
   1.279    static void           write_dword();
   1.280 -  
   1.281 +
   1.282      Bit32u
   1.283    read_dword(seg, offset)
   1.284      Bit16u seg;
   1.285 @@ -444,25 +434,24 @@ typedef unsigned long  Bit32u;
   1.286    ASM_START
   1.287      push bp
   1.288      mov  bp, sp
   1.289 -  
   1.290 +
   1.291        push bx
   1.292        push ds
   1.293        mov  ax, 4[bp] ; segment
   1.294        mov  ds, ax
   1.295        mov  bx, 6[bp] ; offset
   1.296        mov  ax, [bx]
   1.297 -      inc  bx
   1.298 -      inc  bx
   1.299 +      add  bx, #2
   1.300        mov  dx, [bx]
   1.301        ;; ax = return value (word)
   1.302        ;; dx = return value (word)
   1.303        pop  ds
   1.304        pop  bx
   1.305 -  
   1.306 +
   1.307      pop  bp
   1.308    ASM_END
   1.309    }
   1.310 -  
   1.311 +
   1.312      void
   1.313    write_dword(seg, offset, data)
   1.314      Bit16u seg;
   1.315 @@ -472,7 +461,7 @@ typedef unsigned long  Bit32u;
   1.316    ASM_START
   1.317      push bp
   1.318      mov  bp, sp
   1.319 -  
   1.320 +
   1.321        push ax
   1.322        push bx
   1.323        push ds
   1.324 @@ -481,50 +470,49 @@ typedef unsigned long  Bit32u;
   1.325        mov  bx, 6[bp] ; offset
   1.326        mov  ax, 8[bp] ; data word
   1.327        mov  [bx], ax  ; write data word
   1.328 -      inc  bx
   1.329 -      inc  bx
   1.330 +      add  bx, #2
   1.331        mov  ax, 10[bp] ; data word
   1.332        mov  [bx], ax  ; write data word
   1.333        pop  ds
   1.334        pop  bx
   1.335        pop  ax
   1.336 -  
   1.337 +
   1.338      pop  bp
   1.339    ASM_END
   1.340    }
   1.341 -  
   1.342 +
   1.343    // Bit32u (unsigned long) and long helper functions
   1.344    ASM_START
   1.345 -  
   1.346 +
   1.347    ;; and function
   1.348    landl:
   1.349    landul:
   1.350 -    SEG SS 
   1.351 +    SEG SS
   1.352        and ax,[di]
   1.353 -    SEG SS 
   1.354 +    SEG SS
   1.355        and bx,2[di]
   1.356      ret
   1.357 -  
   1.358 +
   1.359    ;; add function
   1.360    laddl:
   1.361    laddul:
   1.362 -    SEG SS 
   1.363 +    SEG SS
   1.364        add ax,[di]
   1.365 -    SEG SS 
   1.366 +    SEG SS
   1.367        adc bx,2[di]
   1.368      ret
   1.369 -  
   1.370 +
   1.371    ;; cmp function
   1.372    lcmpl:
   1.373    lcmpul:
   1.374      and eax, #0x0000FFFF
   1.375      shl ebx, #16
   1.376 -    add eax, ebx
   1.377 +    or  eax, ebx
   1.378      shr ebx, #16
   1.379      SEG SS
   1.380        cmp eax, dword ptr [di]
   1.381      ret
   1.382 -  
   1.383 +
   1.384    ;; sub function
   1.385    lsubl:
   1.386    lsubul:
   1.387 @@ -533,26 +521,26 @@ typedef unsigned long  Bit32u;
   1.388      SEG SS
   1.389      sbb bx,2[di]
   1.390      ret
   1.391 -  
   1.392 +
   1.393    ;; mul function
   1.394    lmull:
   1.395    lmulul:
   1.396      and eax, #0x0000FFFF
   1.397      shl ebx, #16
   1.398 -    add eax, ebx
   1.399 +    or  eax, ebx
   1.400      SEG SS
   1.401      mul eax, dword ptr [di]
   1.402      mov ebx, eax
   1.403      shr ebx, #16
   1.404      ret
   1.405 -  
   1.406 +
   1.407    ;; dec function
   1.408    ldecl:
   1.409    ldecul:
   1.410      SEG SS
   1.411      dec dword ptr [bx]
   1.412      ret
   1.413 -  
   1.414 +
   1.415    ;; or function
   1.416    lorl:
   1.417    lorul:
   1.418 @@ -561,31 +549,31 @@ typedef unsigned long  Bit32u;
   1.419      SEG SS
   1.420      or  bx,2[di]
   1.421      ret
   1.422 -  
   1.423 +
   1.424    ;; inc function
   1.425    lincl:
   1.426    lincul:
   1.427      SEG SS
   1.428      inc dword ptr [bx]
   1.429      ret
   1.430 -  
   1.431 +
   1.432    ;; tst function
   1.433    ltstl:
   1.434    ltstul:
   1.435      and eax, #0x0000FFFF
   1.436      shl ebx, #16
   1.437 -    add eax, ebx
   1.438 +    or  eax, ebx
   1.439      shr ebx, #16
   1.440      test eax, eax
   1.441      ret
   1.442 -  
   1.443 +
   1.444    ;; sr function
   1.445    lsrul:
   1.446      mov  cx,di
   1.447      jcxz lsr_exit
   1.448      and  eax, #0x0000FFFF
   1.449      shl  ebx, #16
   1.450 -    add  eax, ebx
   1.451 +    or   eax, ebx
   1.452    lsr_loop:
   1.453      shr  eax, #1
   1.454      loop lsr_loop
   1.455 @@ -593,7 +581,7 @@ typedef unsigned long  Bit32u;
   1.456      shr  ebx, #16
   1.457    lsr_exit:
   1.458      ret
   1.459 -  
   1.460 +
   1.461    ;; sl function
   1.462    lsll:
   1.463    lslul:
   1.464 @@ -601,15 +589,15 @@ typedef unsigned long  Bit32u;
   1.465      jcxz lsl_exit
   1.466      and  eax, #0x0000FFFF
   1.467      shl  ebx, #16
   1.468 -    add  eax, ebx
   1.469 -  lsl_loop: 
   1.470 +    or   eax, ebx
   1.471 +  lsl_loop:
   1.472      shl  eax, #1
   1.473      loop lsl_loop
   1.474      mov  ebx, eax
   1.475      shr  ebx, #16
   1.476    lsl_exit:
   1.477      ret
   1.478 -  
   1.479 +
   1.480    idiv_:
   1.481      cwd
   1.482      idiv bx
   1.483 @@ -623,7 +611,7 @@ typedef unsigned long  Bit32u;
   1.484    ldivul:
   1.485      and  eax, #0x0000FFFF
   1.486      shl  ebx, #16
   1.487 -    add  eax, ebx
   1.488 +    or   eax, ebx
   1.489      xor  edx, edx
   1.490      SEG SS
   1.491      mov  bx,  2[di]
   1.492 @@ -672,7 +660,7 @@ typedef struct {
   1.493      Bit8u  revision;
   1.494      Bit8u  checksum;
   1.495      } dpte_t;
   1.496 - 
   1.497 +
   1.498    typedef struct {
   1.499      Bit8u  iface;        // ISA or PCI
   1.500      Bit16u iobase1;      // IO Base 1
   1.501 @@ -685,15 +673,15 @@ typedef struct {
   1.502      Bit8u  device;       // Detected type of attached devices (hd/cd/none)
   1.503      Bit8u  removable;    // Removable device flag
   1.504      Bit8u  lock;         // Locks for removable devices
   1.505 -    // Bit8u  lba_capable;  // LBA capable flag - always yes for bochs devices
   1.506 -    Bit8u  mode;         // transfert mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA
   1.507 +    Bit8u  mode;         // transfer mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA
   1.508      Bit16u blksize;      // block size
   1.509  
   1.510      Bit8u  translation;  // type of translation
   1.511      chs_t  lchs;         // Logical CHS
   1.512      chs_t  pchs;         // Physical CHS
   1.513  
   1.514 -    Bit32u sectors;      // Total sectors count
   1.515 +    Bit32u sectors_low;  // Total sectors count
   1.516 +    Bit32u sectors_high;
   1.517      } ata_device_t;
   1.518  
   1.519    typedef struct {
   1.520 @@ -704,10 +692,10 @@ typedef struct {
   1.521      ata_device_t  devices[BX_MAX_ATA_DEVICES];
   1.522      //
   1.523      // map between (bios hd id - 0x80) and ata channels
   1.524 -    Bit8u  hdcount, hdidmap[BX_MAX_ATA_DEVICES];                
   1.525 +    Bit8u  hdcount, hdidmap[BX_MAX_ATA_DEVICES];
   1.526  
   1.527      // map between (bios cd id - 0xE0) and ata channels
   1.528 -    Bit8u  cdcount, cdidmap[BX_MAX_ATA_DEVICES];                
   1.529 +    Bit8u  cdcount, cdidmap[BX_MAX_ATA_DEVICES];
   1.530  
   1.531      // Buffer for DPTE table
   1.532      dpte_t dpte;
   1.533 @@ -717,9 +705,9 @@ typedef struct {
   1.534      Bit32u trsfbytes;
   1.535  
   1.536      } ata_t;
   1.537 -  
   1.538 +
   1.539  #if BX_ELTORITO_BOOT
   1.540 -  // ElTorito Device Emulation data 
   1.541 +  // ElTorito Device Emulation data
   1.542    typedef struct {
   1.543      Bit8u  active;
   1.544      Bit8u  media;
   1.545 @@ -730,20 +718,20 @@ typedef struct {
   1.546      Bit16u buffer_segment;
   1.547      Bit16u load_segment;
   1.548      Bit16u sector_count;
   1.549 -    
   1.550 +
   1.551      // Virtual device
   1.552      chs_t  vdevice;
   1.553      } cdemu_t;
   1.554  #endif // BX_ELTORITO_BOOT
   1.555 -  
   1.556 +
   1.557  #include "32bitgateway.h"
   1.558  
   1.559    // for access to EBDA area
   1.560 -  //     The EBDA structure should conform to 
   1.561 -  //     http://www.cybertrails.com/~fys/rombios.htm document
   1.562 +  //     The EBDA structure should conform to
   1.563 +  //     http://www.frontiernet.net/~fys/rombios.htm document
   1.564    //     I made the ata and cdemu structs begin at 0x121 in the EBDA seg
   1.565 -  // EBDA must be at most 768 bytes; it lives at 0x9fc00, and the boot 
   1.566 -  // device tables are at 0x9ff00 -- 0x9ffff
   1.567 +  // EBDA must be at most 768 bytes; it lives at EBDA_SEG, and the boot
   1.568 +  // device tables are at EBDA_SEG:IPL_TABLE_OFFSET
   1.569    typedef struct {
   1.570      unsigned char ebda_size;
   1.571      unsigned char cmos_shutdown_status;
   1.572 @@ -765,7 +753,7 @@ typedef struct {
   1.573  
   1.574      upcall_t upcall;
   1.575      } ebda_data_t;
   1.576 -  
   1.577 +
   1.578    #define EBDA_CMOS_SHUTDOWN_STATUS_OFFSET 1
   1.579    #define EbdaData ((ebda_data_t *) 0)
   1.580  
   1.581 @@ -779,7 +767,7 @@ typedef struct {
   1.582      Bit32u lba1;
   1.583      Bit32u lba2;
   1.584      } int13ext_t;
   1.585 - 
   1.586 +
   1.587    #define Int13Ext ((int13ext_t *) 0)
   1.588  
   1.589    // Disk Physical Table definition
   1.590 @@ -805,7 +793,7 @@ typedef struct {
   1.591      Bit8u   reserved3;
   1.592      Bit8u   checksum;
   1.593      } dpt_t;
   1.594 - 
   1.595 +
   1.596    #define Int13DPT ((dpt_t *) 0)
   1.597  
   1.598  #endif // BX_USE_ATADRV
   1.599 @@ -835,9 +823,9 @@ typedef struct {
   1.600      } r16;
   1.601    struct {
   1.602      Bit32u filler[4];
   1.603 -    Bit8u  bl, bh; 
   1.604 +    Bit8u  bl, bh;
   1.605      Bit16u filler1;
   1.606 -    Bit8u  dl, dh; 
   1.607 +    Bit8u  dl, dh;
   1.608      Bit16u filler2;
   1.609      Bit8u  cl, ch;
   1.610      Bit16u filler3;
   1.611 @@ -871,6 +859,14 @@ typedef struct {
   1.612    flags_t flags;
   1.613    } iret_addr_t;
   1.614  
   1.615 +typedef struct {
   1.616 +  Bit16u type;
   1.617 +  Bit16u flags;
   1.618 +  Bit32u vector;
   1.619 +  Bit32u description;
   1.620 +  Bit32u reserved;
   1.621 +  } ipl_entry_t;
   1.622 +
   1.623  
   1.624  
   1.625  static Bit8u          inb();
   1.626 @@ -910,8 +906,6 @@ static void           int1a_function();
   1.627  static void           int70_function();
   1.628  static void           int74_function();
   1.629  static Bit16u         get_CS();
   1.630 -//static Bit16u         get_DS();
   1.631 -//static void           set_DS();
   1.632  static Bit16u         get_SS();
   1.633  static unsigned int   enqueue_key();
   1.634  static unsigned int   dequeue_key();
   1.635 @@ -930,7 +924,10 @@ static void           keyboard_init();
   1.636  static void           keyboard_panic();
   1.637  static void           shutdown_status_panic();
   1.638  static void           nmi_handler_msg();
   1.639 -
   1.640 +static void           delay_ticks();
   1.641 +static void           delay_ticks_and_check_for_keystroke();
   1.642 +
   1.643 +static void           interactive_bootkey();
   1.644  static void           print_bios_banner();
   1.645  static void           print_boot_device();
   1.646  static void           print_boot_failure();
   1.647 @@ -964,33 +961,9 @@ Bit16u cdrom_boot();
   1.648  
   1.649  #endif // BX_ELTORITO_BOOT
   1.650  
   1.651 -static char bios_cvs_version_string[] = "$Revision: 1.138 $";
   1.652 -static char bios_date_string[] = "$Date: 2005/05/07 15:55:26 $";
   1.653 -
   1.654 -static char CVSID[] = "$Id: rombios.c,v 1.138 2005/05/07 15:55:26 vruppert Exp $";
   1.655 -
   1.656 -/* Offset to skip the CVS $Id: prefix */ 
   1.657 -#define bios_version_string  (CVSID + 4)
   1.658 -
   1.659 -#define BIOS_PRINTF_HALT     1
   1.660 -#define BIOS_PRINTF_SCREEN   2
   1.661 -#define BIOS_PRINTF_INFO     4
   1.662 -#define BIOS_PRINTF_DEBUG    8
   1.663 -#define BIOS_PRINTF_ALL      (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO)
   1.664 -#define BIOS_PRINTF_DEBHALT  (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO | BIOS_PRINTF_HALT)
   1.665 -
   1.666 -#define printf(format, p...)  bios_printf(BIOS_PRINTF_SCREEN, format, ##p)
   1.667 -
   1.668 -// Defines the output macros. 
   1.669 -// BX_DEBUG goes to INFO port until we can easily choose debug info on a 
   1.670 -// per-device basis. Debug info are sent only in debug mode
   1.671 -#if DEBUG_ROMBIOS
   1.672 -#  define BX_DEBUG(format, p...)  bios_printf(BIOS_PRINTF_INFO, format, ##p)    
   1.673 -#else
   1.674 -#  define BX_DEBUG(format, p...) 
   1.675 -#endif
   1.676 -#define BX_INFO(format, p...)   bios_printf(BIOS_PRINTF_INFO, format, ##p)
   1.677 -#define BX_PANIC(format, p...)  bios_printf(BIOS_PRINTF_DEBHALT, format, ##p)
   1.678 +static char bios_cvs_version_string[] = "$Revision: 1.221 $ $Date: 2008/12/07 17:32:29 $";
   1.679 +
   1.680 +#define BIOS_COPYRIGHT_STRING "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team."
   1.681  
   1.682  #if DEBUG_ATA
   1.683  #  define BX_DEBUG_ATA(a...) BX_DEBUG(a)
   1.684 @@ -1163,9 +1136,9 @@ static struct {
   1.685        { 0x5100, 0x5133, 0x7600,   none, 0x20 }, /* 3 PgDn */
   1.686        { 0x5200, 0x5230,   none,   none, 0x20 }, /* 0 Ins */
   1.687        { 0x5300, 0x532e,   none,   none, 0x20 }, /* Del */
   1.688 -      {   none,   none,   none,   none, none }, /* ??? */
   1.689 -      {   none,   none,   none,   none, none }, /* ??? */
   1.690 -      {   none,   none,   none,   none, none }, /* ??? */
   1.691 +      {   none,   none,   none,   none, none },
   1.692 +      {   none,   none,   none,   none, none },
   1.693 +      { 0x565c, 0x567c,   none,   none, none }, /* \| */
   1.694        { 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */
   1.695        { 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */
   1.696        };
   1.697 @@ -1422,31 +1395,6 @@ ASM_START
   1.698  ASM_END
   1.699  }
   1.700  
   1.701 -//  Bit16u
   1.702 -//get_DS()
   1.703 -//{
   1.704 -//ASM_START
   1.705 -//  mov  ax, ds
   1.706 -//ASM_END
   1.707 -//}
   1.708 -//
   1.709 -//  void
   1.710 -//set_DS(ds_selector)
   1.711 -//  Bit16u ds_selector;
   1.712 -//{
   1.713 -//ASM_START
   1.714 -//  push bp
   1.715 -//  mov  bp, sp
   1.716 -//
   1.717 -//    push ax
   1.718 -//    mov  ax, 4[bp] ; ds_selector
   1.719 -//    mov  ds, ax
   1.720 -//    pop  ax
   1.721 -//
   1.722 -//  pop  bp
   1.723 -//ASM_END
   1.724 -//}
   1.725 -
   1.726    Bit16u
   1.727  get_SS()
   1.728  {
   1.729 @@ -1462,7 +1410,7 @@ copy_e820_table()
   1.730    Bit8u nr_entries = read_byte(0x9000, 0x1e8);
   1.731    Bit32u base_mem;
   1.732    if (nr_entries > 32)
   1.733 -  	nr_entries = 32;
   1.734 +       nr_entries = 32;
   1.735    write_word(0xe000, 0x8, nr_entries);
   1.736    memcpyb(0xe000, 0x10, 0x9000, 0x2d0, nr_entries * 0x14);
   1.737    /* Report the proper base memory size at address 0x0413: otherwise
   1.738 @@ -1570,7 +1518,7 @@ wrch(c)
   1.739    pop  bp
   1.740    ASM_END
   1.741  }
   1.742 - 
   1.743 +
   1.744    void
   1.745  send(action, c)
   1.746    Bit16u action;
   1.747 @@ -1626,14 +1574,121 @@ put_uint(action, val, width, neg)
   1.748    send(action, val - (nval * 10) + '0');
   1.749  }
   1.750  
   1.751 +  void
   1.752 +put_luint(action, val, width, neg)
   1.753 +  Bit16u action;
   1.754 +  unsigned long val;
   1.755 +  short width;
   1.756 +  bx_bool neg;
   1.757 +{
   1.758 +  unsigned long nval = val / 10;
   1.759 +  if (nval)
   1.760 +    put_luint(action, nval, width - 1, neg);
   1.761 +  else {
   1.762 +    while (--width > 0) send(action, ' ');
   1.763 +    if (neg) send(action, '-');
   1.764 +  }
   1.765 +  send(action, val - (nval * 10) + '0');
   1.766 +}
   1.767 +
   1.768 +void put_str(action, segment, offset)
   1.769 +  Bit16u action;
   1.770 +  Bit16u segment;
   1.771 +  Bit16u offset;
   1.772 +{
   1.773 +  Bit8u c;
   1.774 +
   1.775 +  while (c = read_byte(segment, offset)) {
   1.776 +    send(action, c);
   1.777 +    offset++;
   1.778 +  }
   1.779 +}
   1.780 +
   1.781 +  void
   1.782 +delay_ticks(ticks)
   1.783 +  Bit16u ticks;
   1.784 +{
   1.785 +  long ticks_to_wait, delta;
   1.786 +  Bit32u prev_ticks, t;
   1.787 +
   1.788 +   /*
   1.789 +    * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock.
   1.790 +    * We also have to be careful about interrupt storms.
   1.791 +    */
   1.792 +ASM_START
   1.793 +  pushf
   1.794 +  sti
   1.795 +ASM_END
   1.796 +  ticks_to_wait = ticks;
   1.797 +  prev_ticks = read_dword(0x0, 0x46c);
   1.798 +  do
   1.799 +  {
   1.800 +ASM_START
   1.801 +    hlt
   1.802 +ASM_END
   1.803 +    t = read_dword(0x0, 0x46c);
   1.804 +    if (t > prev_ticks)
   1.805 +    {
   1.806 +      delta = t - prev_ticks;     /* The temp var is required or bcc screws up. */
   1.807 +      ticks_to_wait -= delta;
   1.808 +    }
   1.809 +    else if (t < prev_ticks)
   1.810 +    {
   1.811 +      ticks_to_wait -= t;         /* wrapped */
   1.812 +    }
   1.813 +
   1.814 +    prev_ticks = t;
   1.815 +  } while (ticks_to_wait > 0);
   1.816 +ASM_START
   1.817 +  cli
   1.818 +  popf
   1.819 +ASM_END
   1.820 +}
   1.821 +
   1.822 +  Bit8u
   1.823 +check_for_keystroke()
   1.824 +{
   1.825 +ASM_START
   1.826 +  mov  ax, #0x100
   1.827 +  int  #0x16
   1.828 +  jz   no_key
   1.829 +  mov  al, #1
   1.830 +  jmp  done
   1.831 +no_key:
   1.832 +  xor  al, al
   1.833 +done:
   1.834 +ASM_END
   1.835 +}
   1.836 +
   1.837 +  Bit8u
   1.838 +get_keystroke()
   1.839 +{
   1.840 +ASM_START
   1.841 +  mov  ax, #0x0
   1.842 +  int  #0x16
   1.843 +  xchg ah, al
   1.844 +ASM_END
   1.845 +}
   1.846 +
   1.847 +  void
   1.848 +delay_ticks_and_check_for_keystroke(ticks, count)
   1.849 +  Bit16u ticks, count;
   1.850 +{
   1.851 +  Bit16u i;
   1.852 +  for (i = 1; i <= count; i++) {
   1.853 +    delay_ticks(ticks);
   1.854 +    if (check_for_keystroke())
   1.855 +      break;
   1.856 +  }
   1.857 +}
   1.858 +
   1.859  //--------------------------------------------------------------------------
   1.860  // bios_printf()
   1.861 -//   A compact variable argument printf function which prints its output via
   1.862 -//   an I/O port so that it can be logged by Bochs/Plex.  
   1.863 -//   Currently, only %x is supported (or %02x, %04x, etc).
   1.864 +//   A compact variable argument printf function.
   1.865  //
   1.866 -//   Supports %[format_width][format]
   1.867 -//   where format can be d,x,c,s
   1.868 +//   Supports %[format_width][length]format
   1.869 +//   where format can be x,X,u,d,s,S,c
   1.870 +//   and the optional length modifier is l (ell)
   1.871  //--------------------------------------------------------------------------
   1.872    void
   1.873  bios_printf(action, s)
   1.874 @@ -1644,7 +1699,7 @@ bios_printf(action, s)
   1.875    bx_bool  in_format;
   1.876    short i;
   1.877    Bit16u  *arg_ptr;
   1.878 -  Bit16u   arg_seg, arg, nibble, shift_count, format_width;
   1.879 +  Bit16u   arg_seg, arg, nibble, hibyte, shift_count, format_width, hexadd;
   1.880  
   1.881    arg_ptr = &s;
   1.882    arg_seg = get_SS();
   1.883 @@ -1671,17 +1726,49 @@ bios_printf(action, s)
   1.884        else {
   1.885          arg_ptr++; // increment to next arg
   1.886          arg = read_word(arg_seg, arg_ptr);
   1.887 -        if (c == 'x') {
   1.888 +        if (c == 'x' || c == 'X') {
   1.889            if (format_width == 0)
   1.890              format_width = 4;
   1.891 +          if (c == 'x')
   1.892 +            hexadd = 'a';
   1.893 +          else
   1.894 +            hexadd = 'A';
   1.895            for (i=format_width-1; i>=0; i--) {
   1.896              nibble = (arg >> (4 * i)) & 0x000f;
   1.897 -            send (action, (nibble<=9)? (nibble+'0') : (nibble-10+'A'));
   1.898 +            send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
   1.899              }
   1.900            }
   1.901          else if (c == 'u') {
   1.902            put_uint(action, arg, format_width, 0);
   1.903            }
   1.904 +        else if (c == 'l') {
   1.905 +          s++;
   1.906 +          c = read_byte(get_CS(), s); /* is it ld,lx,lu? */
   1.907 +          arg_ptr++; /* increment to next arg */
   1.908 +          hibyte = read_word(arg_seg, arg_ptr);
   1.909 +          if (c == 'd') {
   1.910 +            if (hibyte & 0x8000)
   1.911 +              put_luint(action, 0L-(((Bit32u) hibyte << 16) | arg), format_width-1, 1);
   1.912 +            else
   1.913 +              put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0);
   1.914 +           }
   1.915 +          else if (c == 'u') {
   1.916 +            put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0);
   1.917 +           }
   1.918 +          else if (c == 'x' || c == 'X')
   1.919 +           {
   1.920 +            if (format_width == 0)
   1.921 +              format_width = 8;
   1.922 +            if (c == 'x')
   1.923 +              hexadd = 'a';
   1.924 +            else
   1.925 +              hexadd = 'A';
   1.926 +            for (i=format_width-1; i>=0; i--) {
   1.927 +              nibble = ((((Bit32u) hibyte <<16) | arg) >> (4 * i)) & 0x000f;
   1.928 +              send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
   1.929 +              }
   1.930 +           }
   1.931 +          }
   1.932          else if (c == 'd') {
   1.933            if (arg & 0x8000)
   1.934              put_int(action, -arg, format_width - 1, 1);
   1.935 @@ -1689,7 +1776,13 @@ bios_printf(action, s)
   1.936              put_int(action, arg, format_width, 0);
   1.937            }
   1.938          else if (c == 's') {
   1.939 -          bios_printf(action & (~BIOS_PRINTF_HALT), arg);
   1.940 +          put_str(action, get_CS(), arg);
   1.941 +          }
   1.942 +        else if (c == 'S') {
   1.943 +          hibyte = arg;
   1.944 +          arg_ptr++;
   1.945 +          arg = read_word(arg_seg, arg_ptr);
   1.946 +          put_str(action, hibyte, arg);
   1.947            }
   1.948          else if (c == 'c') {
   1.949            send(action, arg);
   1.950 @@ -1706,7 +1799,7 @@ bios_printf(action, s)
   1.951      }
   1.952  
   1.953    if (action & BIOS_PRINTF_HALT) {
   1.954 -    // freeze in a busy loop.  
   1.955 +    // freeze in a busy loop.
   1.956  ASM_START
   1.957      cli
   1.958   halt2_loop:
   1.959 @@ -1740,8 +1833,8 @@ keyboard_init()
   1.960              max = 0x2000;
   1.961              }
   1.962          }
   1.963 -  
   1.964 -    // Due to timer issues, and if the IPS setting is > 15000000, 
   1.965 +
   1.966 +    // Due to timer issues, and if the IPS setting is > 15000000,
   1.967      // the incoming keys might not be flushed here. That will
   1.968      // cause a panic a few lines below.  See sourceforge bug report :
   1.969      // [ 642031 ] FATAL: Keyboard RESET error:993
   1.970 @@ -1878,13 +1971,12 @@ keyboard_init()
   1.971  keyboard_panic(status)
   1.972    Bit16u status;
   1.973  {
   1.974 -  // If you're getting a 993 keyboard panic here, 
   1.975 +  // If you're getting a 993 keyboard panic here,
   1.976    // please see the comment in keyboard_init
   1.977 -  
   1.978 +
   1.979    BX_PANIC("Keyboard error:%u\n",status);
   1.980  }
   1.981  
   1.982 -
   1.983  #define CMOS_SHUTDOWN_S3 0xFE
   1.984  //--------------------------------------------------------------------------
   1.985  // machine_reset
   1.986 @@ -1939,6 +2031,11 @@ shutdown_status_panic(status)
   1.987    BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status);
   1.988  }
   1.989  
   1.990 +void s3_resume_panic()
   1.991 +{
   1.992 +  BX_PANIC("Returned from s3_resume.\n");
   1.993 +}
   1.994 +
   1.995  //--------------------------------------------------------------------------
   1.996  // print_bios_banner
   1.997  //   displays a the bios version
   1.998 @@ -1946,74 +2043,84 @@ shutdown_status_panic(status)
   1.999  void
  1.1000  print_bios_banner()
  1.1001  {
  1.1002 -  printf(BX_APPNAME" BIOS, %d cpu%s, ", BX_SMP_PROCESSORS, BX_SMP_PROCESSORS>1?"s":"");
  1.1003 -  printf("%s %s\n", bios_cvs_version_string, bios_date_string);
  1.1004 +  printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ",
  1.1005 +    BIOS_BUILD_DATE, bios_cvs_version_string);
  1.1006 +  printf(
  1.1007 +#if BX_APM
  1.1008 +  "apmbios "
  1.1009 +#endif
  1.1010 +#if BX_PCIBIOS
  1.1011 +  "pcibios "
  1.1012 +#endif
  1.1013 +#if BX_ELTORITO_BOOT
  1.1014 +  "eltorito "
  1.1015 +#endif
  1.1016 +#if BX_ROMBIOS32
  1.1017 +  "rombios32 "
  1.1018 +#endif
  1.1019  #if BX_TCGBIOS
  1.1020 -  printf("TCG-enabled BIOS.\n");
  1.1021 -#endif
  1.1022 -  printf("\n");
  1.1023 -}
  1.1024 -
  1.1025 +  "TCG-enabled"
  1.1026 +#endif
  1.1027 +  "\n\n");
  1.1028 +}
  1.1029  
  1.1030  //--------------------------------------------------------------------------
  1.1031  // BIOS Boot Specification 1.0.1 compatibility
  1.1032  //
  1.1033 -// Very basic support for the BIOS Boot Specification, which allows expansion 
  1.1034 -// ROMs to register themselves as boot devices, instead of just stealing the 
  1.1035 +// Very basic support for the BIOS Boot Specification, which allows expansion
  1.1036 +// ROMs to register themselves as boot devices, instead of just stealing the
  1.1037  // INT 19h boot vector.
  1.1038 -// 
  1.1039 +//
  1.1040  // This is a hack: to do it properly requires a proper PnP BIOS and we aren't
  1.1041 -// one; we just lie to the option ROMs to make them behave correctly. 
  1.1042 -// We also don't support letting option ROMs register as bootable disk 
  1.1043 -// drives (BCVs), only as bootable devices (BEVs). 
  1.1044 +// one; we just lie to the option ROMs to make them behave correctly.
  1.1045 +// We also don't support letting option ROMs register as bootable disk
  1.1046 +// drives (BCVs), only as bootable devices (BEVs).
  1.1047  //
  1.1048  // http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm
  1.1049  //--------------------------------------------------------------------------
  1.1050  
  1.1051 -struct ipl_entry {
  1.1052 -  Bit16u type;
  1.1053 -  Bit16u flags;
  1.1054 -  Bit32u vector;
  1.1055 -  Bit32u description;
  1.1056 -  Bit32u reserved;
  1.1057 -};
  1.1058 -
  1.1059 -static void 
  1.1060 -init_boot_vectors() 
  1.1061 -{
  1.1062 -  struct ipl_entry e; 
  1.1063 +static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};
  1.1064 +
  1.1065 +static void
  1.1066 +init_boot_vectors()
  1.1067 +{
  1.1068 +  ipl_entry_t e;
  1.1069    Bit16u count = 0;
  1.1070    Bit16u ss = get_SS();
  1.1071 +  Bit16u ebda_seg = read_word(0x0040, 0x000E);
  1.1072  
  1.1073    /* Clear out the IPL table. */
  1.1074 -  memsetb(EBDA_SEG, IPL_TABLE_OFFSET, 0, 0xff);
  1.1075 +  memsetb(ebda_seg, IPL_TABLE_OFFSET, 0, IPL_SIZE);
  1.1076 +
  1.1077 +  /* User selected device not set */
  1.1078 +  write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, 0xFFFF);
  1.1079  
  1.1080    /* Floppy drive */
  1.1081 -  e.type = 1; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
  1.1082 -  memcpyb(EBDA_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
  1.1083 +  e.type = IPL_TYPE_FLOPPY; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
  1.1084 +  memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
  1.1085    count++;
  1.1086  
  1.1087    /* First HDD */
  1.1088 -  e.type = 2; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
  1.1089 -  memcpyb(EBDA_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
  1.1090 +  e.type = IPL_TYPE_HARDDISK; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
  1.1091 +  memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
  1.1092    count++;
  1.1093  
  1.1094  #if BX_ELTORITO_BOOT
  1.1095    /* CDROM */
  1.1096 -  e.type = 3; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
  1.1097 -  memcpyb(EBDA_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
  1.1098 +  e.type = IPL_TYPE_CDROM; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
  1.1099 +  memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
  1.1100    count++;
  1.1101 -#endif  
  1.1102 +#endif
  1.1103  
  1.1104    /* Remember how many devices we have */
  1.1105 -  write_word(EBDA_SEG, IPL_COUNT_OFFSET, count);
  1.1106 +  write_word(ebda_seg, IPL_COUNT_OFFSET, count);
  1.1107    /* Not tried booting anything yet */
  1.1108 -  write_word(EBDA_SEG, IPL_SEQUENCE_OFFSET, 0xffff);
  1.1109 +  write_word(ebda_seg, IPL_SEQUENCE_OFFSET, 0xffff);
  1.1110  }
  1.1111  
  1.1112  static Bit8u
  1.1113  get_boot_vector(i, e)
  1.1114 -Bit16u i; struct ipl_entry *e; 
  1.1115 +Bit16u i; ipl_entry_t *e;
  1.1116  {
  1.1117    Bit16u count;
  1.1118    Bit16u ss = get_SS();
  1.1119 @@ -2026,22 +2133,107 @@ Bit16u i; struct ipl_entry *e;
  1.1120    return 1;
  1.1121  }
  1.1122  
  1.1123 +#if BX_ELTORITO_BOOT
  1.1124 +  void
  1.1125 +interactive_bootkey()
  1.1126 +{
  1.1127 +  ipl_entry_t e;
  1.1128 +  Bit16u count;
  1.1129 +  char description[33];
  1.1130 +  Bit8u scan_code;
  1.1131 +  Bit8u i;
  1.1132 +  Bit16u ss = get_SS();
  1.1133 +  Bit16u valid_choice = 0;
  1.1134 +  Bit16u ebda_seg = read_word(0x0040, 0x000E);
  1.1135 +
  1.1136 +  while (check_for_keystroke())
  1.1137 +    get_keystroke();
  1.1138 +
  1.1139 +  printf("\nPress F12 for boot menu.\n\n");
  1.1140 +
  1.1141 +  delay_ticks_and_check_for_keystroke(11, 5); /* ~3 seconds */
  1.1142 +  if (check_for_keystroke())
  1.1143 +  {
  1.1144 +    scan_code = get_keystroke();
  1.1145 +    if (scan_code == 0x86) /* F12 */
  1.1146 +    {
  1.1147 +      while (check_for_keystroke())
  1.1148 +        get_keystroke();
  1.1149 +
  1.1150 +      printf("Select boot device:\n\n");
  1.1151 +
  1.1152 +      count = read_word(ebda_seg, IPL_COUNT_OFFSET);
  1.1153 +      for (i = 0; i < count; i++)
  1.1154 +      {
  1.1155 +        memcpyb(ss, &e, ebda_seg, IPL_TABLE_OFFSET + i * sizeof (e), sizeof (e));
  1.1156 +        printf("%d. ", i+1);
  1.1157 +        switch(e.type)
  1.1158 +        {
  1.1159 +          case IPL_TYPE_FLOPPY:
  1.1160 +          case IPL_TYPE_HARDDISK:
  1.1161 +          case IPL_TYPE_CDROM:
  1.1162 +            printf("%s\n", drivetypes[e.type]);
  1.1163 +            break;
  1.1164 +          case IPL_TYPE_BEV:
  1.1165 +            printf("%s", drivetypes[4]);
  1.1166 +            if (e.description != 0)
  1.1167 +            {
  1.1168 +              memcpyb(ss, &description, (Bit16u)(e.description >> 16), (Bit16u)(e.description & 0xffff), 32);
  1.1169 +              description[32] = 0;
  1.1170 +              printf(" [%S]", ss, description);
  1.1171 +           }
  1.1172 +           printf("\n");
  1.1173 +           break;
  1.1174 +        }
  1.1175 +      }
  1.1176 +
  1.1177 +      count++;
  1.1178 +      while (!valid_choice) {
  1.1179 +        scan_code = get_keystroke();
  1.1180 +        if (scan_code == 0x01 || scan_code == 0x58) /* ESC or F12 */
  1.1181 +        {
  1.1182 +          valid_choice = 1;
  1.1183 +        }
  1.1184 +        else if (scan_code <= count)
  1.1185 +        {
  1.1186 +          valid_choice = 1;
  1.1187 +          scan_code -= 1;
  1.1188 +          /* Set user selected device */
  1.1189 +          write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, scan_code);
  1.1190 +        }
  1.1191 +      }
  1.1192 +    printf("\n");
  1.1193 +    }
  1.1194 +  }
  1.1195 +}
  1.1196 +#endif // BX_ELTORITO_BOOT
  1.1197  
  1.1198  //--------------------------------------------------------------------------
  1.1199  // print_boot_device
  1.1200  //   displays the boot device
  1.1201  //--------------------------------------------------------------------------
  1.1202  
  1.1203 -static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};
  1.1204 -
  1.1205  void
  1.1206 -print_boot_device(type)
  1.1207 +print_boot_device(e)
  1.1208 +  ipl_entry_t *e;
  1.1209 +{
  1.1210    Bit16u type;
  1.1211 -{
  1.1212 -  /* NIC appears as type 0x80 */ 
  1.1213 -  if (type == 0x80 ) type = 0x4;
  1.1214 -  if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n"); 
  1.1215 -  printf("Booting from %s...\n", drivetypes[type]);
  1.1216 +  char description[33];
  1.1217 +  Bit16u ss = get_SS();
  1.1218 +  type = e->type;
  1.1219 +  /* NIC appears as type 0x80 */
  1.1220 +  if (type == IPL_TYPE_BEV) type = 0x4;
  1.1221 +  if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n");
  1.1222 +  printf("Booting from %s", drivetypes[type]);
  1.1223 +  /* print product string if BEV */
  1.1224 +  if (type == 4 && e->description != 0) {
  1.1225 +    /* first 32 bytes are significant */
  1.1226 +    memcpyb(ss, &description, (Bit16u)(e->description >> 16), (Bit16u)(e->description & 0xffff), 32);
  1.1227 +    /* terminate string */
  1.1228 +    description[32] = 0;
  1.1229 +    printf(" [%S]", ss, description);
  1.1230 +  }
  1.1231 +  printf("...\n");
  1.1232  }
  1.1233  
  1.1234  //--------------------------------------------------------------------------
  1.1235 @@ -2052,17 +2244,17 @@ print_boot_device(type)
  1.1236  print_boot_failure(type, reason)
  1.1237    Bit16u type; Bit8u reason;
  1.1238  {
  1.1239 -  if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n"); 
  1.1240 +  if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n");
  1.1241  
  1.1242    printf("Boot from %s failed", drivetypes[type]);
  1.1243    if (type < 4) {
  1.1244      /* Report the reason too */
  1.1245 -  if (reason==0) 
  1.1246 -    printf(": not a bootable disk");
  1.1247 -  else
  1.1248 -    printf(": could not read the boot disk");
  1.1249 +    if (reason==0)
  1.1250 +      printf(": not a bootable disk");
  1.1251 +    else
  1.1252 +      printf(": could not read the boot disk");
  1.1253    }
  1.1254 -  printf("\n");
  1.1255 +  printf("\n\n");
  1.1256  }
  1.1257  
  1.1258  //--------------------------------------------------------------------------
  1.1259 @@ -2074,220 +2266,10 @@ print_cdromboot_failure( code )
  1.1260    Bit16u code;
  1.1261  {
  1.1262    bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "CDROM boot failure code : %04x\n",code);
  1.1263 -  
  1.1264 +
  1.1265    return;
  1.1266  }
  1.1267  
  1.1268 -#define WAIT_HZ 18
  1.1269 -/**
  1.1270 - * Check for keystroke.
  1.1271 - * @returns    True if keystroke available, False if not.
  1.1272 - */
  1.1273 -Bit8u check_for_keystroke()
  1.1274 -{
  1.1275 -ASM_START
  1.1276 -    mov  ax, #0x100
  1.1277 -    int  #0x16
  1.1278 -    jz   no_key
  1.1279 -    mov  al, #1
  1.1280 -    jmp  done
  1.1281 -no_key:
  1.1282 -    xor  al, al
  1.1283 -done:
  1.1284 -ASM_END
  1.1285 -}
  1.1286 -
  1.1287 -/**
  1.1288 - * Get keystroke.
  1.1289 - * @returns    BIOS scan code.
  1.1290 - */
  1.1291 -Bit8u get_keystroke()
  1.1292 -{
  1.1293 -ASM_START
  1.1294 -    mov  ax, #0x0
  1.1295 -    int  #0x16
  1.1296 -    xchg ah, al
  1.1297 -ASM_END
  1.1298 -}
  1.1299 -
  1.1300 -/**
  1.1301 - * Waits (sleeps) for the given number of ticks.
  1.1302 - * Checks for keystroke.
  1.1303 - *
  1.1304 - * @returns BIOS scan code if available, 0 if not.
  1.1305 - * @param   ticks       Number of ticks to sleep.
  1.1306 - * @param   stop_on_key Whether to stop immediately upon keypress.
  1.1307 - */
  1.1308 -Bit8u wait(ticks, stop_on_key)
  1.1309 -  Bit16u ticks;
  1.1310 -  Bit8u stop_on_key;
  1.1311 -{
  1.1312 -    long ticks_to_wait, delta;
  1.1313 -    Bit32u prev_ticks, t;
  1.1314 -    Bit8u scan_code = 0;
  1.1315 -
  1.1316 -    /*
  1.1317 -     * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock.
  1.1318 -     * We also have to be careful about interrupt storms.
  1.1319 -     */
  1.1320 -    ticks_to_wait = ticks;
  1.1321 -    prev_ticks = read_dword(0x0, 0x46c);
  1.1322 -    do
  1.1323 -    {
  1.1324 -        t = read_dword(0x0, 0x46c);
  1.1325 -        if (t > prev_ticks)
  1.1326 -        {
  1.1327 -            delta = t - prev_ticks;     /* The temp var is required or bcc screws up. */
  1.1328 -            ticks_to_wait -= delta;
  1.1329 -        }
  1.1330 -        else if (t < prev_ticks)
  1.1331 -            ticks_to_wait -= t;         /* wrapped */
  1.1332 -        prev_ticks = t;
  1.1333 -
  1.1334 -        if (check_for_keystroke())
  1.1335 -        {
  1.1336 -            scan_code = get_keystroke();
  1.1337 -            bios_printf(BIOS_PRINTF_DEBUG, "Key pressed: %x\n", scan_code);
  1.1338 -            if (stop_on_key)
  1.1339 -                return scan_code;
  1.1340 -        }
  1.1341 -    } while (ticks_to_wait > 0);
  1.1342 -    return scan_code;
  1.1343 -}
  1.1344 -
  1.1345 -static void clearscreen() {
  1.1346 -    /* Hide cursor, clear screen and move cursor to starting position */
  1.1347 -ASM_START
  1.1348 -        push bx
  1.1349 -        push cx
  1.1350 -        push dx
  1.1351 -
  1.1352 -        mov  ax, #0x100
  1.1353 -        mov  cx, #0x1000
  1.1354 -        int  #0x10
  1.1355 -
  1.1356 -        mov  ax, #0x700
  1.1357 -        mov  bh, #7
  1.1358 -        xor  cx, cx
  1.1359 -        mov  dx, #0x184f
  1.1360 -        int  #0x10
  1.1361 -
  1.1362 -        mov  ax, #0x200
  1.1363 -        xor  bx, bx
  1.1364 -        xor  dx, dx
  1.1365 -        int  #0x10
  1.1366 -
  1.1367 -        pop  dx
  1.1368 -        pop  cx
  1.1369 -        pop  bx
  1.1370 -ASM_END
  1.1371 -}
  1.1372 -
  1.1373 -int bootmenu(selected)
  1.1374 -  int selected;
  1.1375 -{
  1.1376 -    Bit8u scode;
  1.1377 -    int max;
  1.1378 -    Bit16u ebda_seg = read_word(0x0040, 0x000E);
  1.1379 -
  1.1380 -    /* get the number of boot devices */
  1.1381 -    max = read_word(ebda_seg, IPL_COUNT_OFFSET);
  1.1382 -
  1.1383 -    for(;;) {
  1.1384 -        if (selected > max || selected < 1) selected = 1;
  1.1385 -        clearscreen();
  1.1386 -        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n\n\n\n\n\n");
  1.1387 -        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "          Select boot device\n\n");
  1.1388 -        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "            1. Floppy\n");
  1.1389 -        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "            2. Hard drive\n");
  1.1390 -        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "            3. CD-ROM\n");
  1.1391 -        if (max == 4)
  1.1392 -            bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "            4. Network\n");
  1.1393 -        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n          Currently selected: %d\n", selected);
  1.1394 -
  1.1395 -        do {
  1.1396 -            scode = wait(WAIT_HZ, 1);
  1.1397 -        } while (scode == 0);
  1.1398 -        switch(scode) {
  1.1399 -        case 0x02:
  1.1400 -        case 0x03:
  1.1401 -        case 0x04:
  1.1402 -            selected = scode - 1;
  1.1403 -            break;
  1.1404 -        case 0x05:
  1.1405 -            if (max == 4)
  1.1406 -                selected = scode -1 ;
  1.1407 -            else
  1.1408 -                scode = 0;
  1.1409 -            break;
  1.1410 -        case 0x48:
  1.1411 -            selected -= 1;
  1.1412 -            if (selected < 1)
  1.1413 -                selected = 1;
  1.1414 -            scode = 0;
  1.1415 -            break;
  1.1416 -        case 0x50:
  1.1417 -            selected += 1;
  1.1418 -            if (selected > max)
  1.1419 -                selected = max;
  1.1420 -            scode = 0;
  1.1421 -            break;
  1.1422 -        case 0x1c:
  1.1423 -            break;
  1.1424 -        default:
  1.1425 -            scode = 0;
  1.1426 -            break;
  1.1427 -        }
  1.1428 -        if (scode != 0)
  1.1429 -            break;
  1.1430 -    }
  1.1431 -
  1.1432 -    switch (selected) {
  1.1433 -    case 1:
  1.1434 -        return 0x3D;
  1.1435 -    case 2:
  1.1436 -        return 0x3E;
  1.1437 -    case 3:
  1.1438 -        return 0x3F;
  1.1439 -    case 4:
  1.1440 -        return 0x58;
  1.1441 -    default:
  1.1442 -        return 0;
  1.1443 -    }
  1.1444 -}
  1.1445 -
  1.1446 -void interactive_bootkey()
  1.1447 -{
  1.1448 -    Bit16u i;
  1.1449 -    Bit8u scan = 0;
  1.1450 -
  1.1451 -    bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO,
  1.1452 -                "\n\nPress F10 to select boot device.\n");
  1.1453 -
  1.1454 -    scan = wait(1, 0);
  1.1455 -    if (scan == 0x44)
  1.1456 -        scan = bootmenu(inb_cmos(0x3d) & 0x0f);
  1.1457 -
  1.1458 -    /* set the default based on the keypress or menu */
  1.1459 -    switch(scan) {
  1.1460 -    case 0x3D:
  1.1461 -        outb_cmos(0x3d, 0x01);
  1.1462 -        break;
  1.1463 -    case 0x3E:
  1.1464 -        outb_cmos(0x3d, 0x02);
  1.1465 -        break;
  1.1466 -    case 0x3F:
  1.1467 -        outb_cmos(0x3d, 0x03);
  1.1468 -        break;
  1.1469 -    case 0x58:
  1.1470 -        outb_cmos(0x3d, 0x04);
  1.1471 -        break;
  1.1472 -    default:
  1.1473 -        break;
  1.1474 -    }
  1.1475 -}
  1.1476 -
  1.1477 -
  1.1478  void
  1.1479  nmi_handler_msg()
  1.1480  {
  1.1481 @@ -2306,7 +2288,7 @@ log_bios_start()
  1.1482  #if BX_DEBUG_SERIAL
  1.1483    outb(BX_DEBUG_PORT+UART_LCR, 0x03); /* setup for serial logging: 8N1 */
  1.1484  #endif
  1.1485 -  BX_INFO("%s\n", bios_version_string);
  1.1486 +  BX_INFO("%s\n", bios_cvs_version_string);
  1.1487  }
  1.1488  
  1.1489    bx_bool
  1.1490 @@ -2341,41 +2323,35 @@ debugger_off()
  1.1491    outb(0xfedc, 0x00);
  1.1492  }
  1.1493  
  1.1494 -void 
  1.1495 +int
  1.1496  s3_resume()
  1.1497  {
  1.1498      Bit32u s3_wakeup_vector;
  1.1499 -    Bit16u s3_wakeup_ip, s3_wakeup_cs;
  1.1500 -    Bit8u cmos_shutdown_status;
  1.1501 -
  1.1502 +    Bit8u s3_resume_flag;
  1.1503 +
  1.1504 +    s3_resume_flag = read_byte(0x40, 0xb0);
  1.1505 +#ifdef HVMASSIST
  1.1506 +    s3_wakeup_vector = get_s3_waking_vector();
  1.1507 +#else
  1.1508 +    s3_wakeup_vector = read_dword(0x40, 0xb2);
  1.1509 +#endif
  1.1510 +
  1.1511 +    BX_INFO("S3 resume called %x 0x%lx\n", s3_resume_flag, s3_wakeup_vector);
  1.1512 +    if (s3_resume_flag != CMOS_SHUTDOWN_S3 || !s3_wakeup_vector)
  1.1513 +	    return 0;
  1.1514 +
  1.1515 +    write_byte(0x40, 0xb0, 0);
  1.1516 +
  1.1517 +    /* setup wakeup vector */
  1.1518 +    write_word(0x40, 0xb6, (s3_wakeup_vector & 0xF)); /* IP */
  1.1519 +    write_word(0x40, 0xb8, (s3_wakeup_vector >> 4)); /* CS */
  1.1520 +
  1.1521 +    BX_INFO("S3 resume jump to %x:%x\n", (s3_wakeup_vector >> 4),
  1.1522 +		    (s3_wakeup_vector & 0xF));
  1.1523  ASM_START
  1.1524 -    push ds
  1.1525 -    push ax
  1.1526 -    xor ax, ax
  1.1527 -    mov ds, ax
  1.1528 -    mov ax, word ptr [EBDA_SEG_PTR]
  1.1529 -    mov ds, ax
  1.1530 -    mov al, [EBDA_CMOS_SHUTDOWN_STATUS_OFFSET]
  1.1531 -    mov .s3_resume.cmos_shutdown_status[bp], al
  1.1532 -    pop ax
  1.1533 -    pop ds
  1.1534 +    jmpf [0x04b6]
  1.1535  ASM_END
  1.1536 -
  1.1537 -    if (cmos_shutdown_status != CMOS_SHUTDOWN_S3)
  1.1538 -        return;
  1.1539 -
  1.1540 -    s3_wakeup_vector = get_s3_waking_vector();
  1.1541 -    if (!s3_wakeup_vector)
  1.1542 -        return;
  1.1543 -
  1.1544 -    s3_wakeup_ip = s3_wakeup_vector & 0xF;
  1.1545 -    s3_wakeup_cs = s3_wakeup_vector >> 4;
  1.1546 -
  1.1547 -ASM_START
  1.1548 -    push .s3_resume.s3_wakeup_cs[bp]
  1.1549 -    push .s3_resume.s3_wakeup_ip[bp]
  1.1550 -    retf
  1.1551 -ASM_END
  1.1552 +    return 1;
  1.1553  }
  1.1554  
  1.1555  #if BX_USE_ATADRV
  1.1556 @@ -2425,6 +2401,7 @@ ASM_END
  1.1557  // bits 7-4 of the device/head (CB_DH) reg
  1.1558  #define ATA_CB_DH_DEV0 0xa0    // select device 0
  1.1559  #define ATA_CB_DH_DEV1 0xb0    // select device 1
  1.1560 +#define ATA_CB_DH_LBA 0x40    // use LBA
  1.1561  
  1.1562  // status reg (CB_STAT and CB_ASTAT) bits
  1.1563  #define ATA_CB_STAT_BSY  0x80  // busy
  1.1564 @@ -2474,6 +2451,7 @@ ASM_END
  1.1565  #define ATA_CMD_READ_SECTORS                 0x20
  1.1566  #define ATA_CMD_READ_VERIFY_SECTORS          0x40
  1.1567  #define ATA_CMD_RECALIBRATE                  0x10
  1.1568 +#define ATA_CMD_REQUEST_SENSE                0x03
  1.1569  #define ATA_CMD_SEEK                         0x70
  1.1570  #define ATA_CMD_SET_FEATURES                 0xEF
  1.1571  #define ATA_CMD_SET_MULTIPLE_MODE            0xC6
  1.1572 @@ -2518,7 +2496,7 @@ ASM_END
  1.1573  #define ATA_DATA_NO      0x00
  1.1574  #define ATA_DATA_IN      0x01
  1.1575  #define ATA_DATA_OUT     0x02
  1.1576 -  
  1.1577 +
  1.1578  // ---------------------------------------------------------------------------
  1.1579  // ATA/ATAPI driver : initialization
  1.1580  // ---------------------------------------------------------------------------
  1.1581 @@ -2527,7 +2505,7 @@ void ata_init( )
  1.1582    Bit16u ebda_seg=read_word(0x0040,0x000E);
  1.1583    Bit8u  channel, device;
  1.1584  
  1.1585 -  // Channels info init. 
  1.1586 +  // Channels info init.
  1.1587    for (channel=0; channel<BX_MAX_ATA_INTERFACES; channel++) {
  1.1588      write_byte(ebda_seg,&EbdaData->ata.channels[channel].iface,ATA_IFACE_NONE);
  1.1589      write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1,0x0);
  1.1590 @@ -2535,7 +2513,7 @@ void ata_init( )
  1.1591      write_byte(ebda_seg,&EbdaData->ata.channels[channel].irq,0);
  1.1592      }
  1.1593  
  1.1594 -  // Devices info init. 
  1.1595 +  // Devices info init.
  1.1596    for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
  1.1597      write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE);
  1.1598      write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_NONE);
  1.1599 @@ -2550,11 +2528,12 @@ void ata_init( )
  1.1600      write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads,0);
  1.1601      write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders,0);
  1.1602      write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt,0);
  1.1603 -    
  1.1604 -    write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors,0L);
  1.1605 +
  1.1606 +    write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low,0L);
  1.1607 +    write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high,0L);
  1.1608      }
  1.1609  
  1.1610 -  // hdidmap  and cdidmap init. 
  1.1611 +  // hdidmap  and cdidmap init.
  1.1612    for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
  1.1613      write_byte(ebda_seg,&EbdaData->ata.hdidmap[device],BX_MAX_ATA_DEVICES);
  1.1614      write_byte(ebda_seg,&EbdaData->ata.cdidmap[device],BX_MAX_ATA_DEVICES);
  1.1615 @@ -2564,6 +2543,58 @@ void ata_init( )
  1.1616    write_byte(ebda_seg,&EbdaData->ata.cdcount,0);
  1.1617  }
  1.1618  
  1.1619 +#define TIMEOUT 0
  1.1620 +#define BSY 1
  1.1621 +#define NOT_BSY 2
  1.1622 +#define NOT_BSY_DRQ 3
  1.1623 +#define NOT_BSY_NOT_DRQ 4
  1.1624 +#define NOT_BSY_RDY 5
  1.1625 +
  1.1626 +#define IDE_TIMEOUT 32000u //32 seconds max for IDE ops
  1.1627 +
  1.1628 +int await_ide();
  1.1629 +static int await_ide(when_done,base,timeout)
  1.1630 +  Bit8u when_done;
  1.1631 +  Bit16u base;
  1.1632 +  Bit16u timeout;
  1.1633 +{
  1.1634 +  Bit32u time=0,last=0;
  1.1635 +  Bit16u status;
  1.1636 +  Bit8u result;
  1.1637 +  status = inb(base + ATA_CB_STAT); // for the times you're supposed to throw one away
  1.1638 +  for(;;) {
  1.1639 +    status = inb(base+ATA_CB_STAT);
  1.1640 +    time++;
  1.1641 +    if (when_done == BSY)
  1.1642 +      result = status & ATA_CB_STAT_BSY;
  1.1643 +    else if (when_done == NOT_BSY)
  1.1644 +      result = !(status & ATA_CB_STAT_BSY);
  1.1645 +    else if (when_done == NOT_BSY_DRQ)
  1.1646 +      result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_DRQ);
  1.1647 +    else if (when_done == NOT_BSY_NOT_DRQ)
  1.1648 +      result = !(status & ATA_CB_STAT_BSY) && !(status & ATA_CB_STAT_DRQ);
  1.1649 +    else if (when_done == NOT_BSY_RDY)
  1.1650 +      result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_RDY);
  1.1651 +    else if (when_done == TIMEOUT)
  1.1652 +      result = 0;
  1.1653 +
  1.1654 +    if (result) return 0;
  1.1655 +    if (time>>16 != last) // mod 2048 each 16 ms
  1.1656 +    {
  1.1657 +      last = time >>16;
  1.1658 +      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);
  1.1659 +    }
  1.1660 +    if (status & ATA_CB_STAT_ERR)
  1.1661 +    {
  1.1662 +      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);
  1.1663 +      return -1;
  1.1664 +    }
  1.1665 +    if ((timeout == 0) || ((time>>11) > timeout)) break;
  1.1666 +  }
  1.1667 +  BX_INFO("IDE time out\n");
  1.1668 +  return -1;
  1.1669 +}
  1.1670 +
  1.1671  // ---------------------------------------------------------------------------
  1.1672  // ATA/ATAPI driver : device detection
  1.1673  // ---------------------------------------------------------------------------
  1.1674 @@ -2604,7 +2635,7 @@ void ata_detect( )
  1.1675  
  1.1676    // Device detection
  1.1677    hdcount=cdcount=0;
  1.1678 -  
  1.1679 +
  1.1680    for(device=0; device<BX_MAX_ATA_DEVICES; device++) {
  1.1681      Bit16u iobase1, iobase2;
  1.1682      Bit8u  channel, slave, shift;
  1.1683 @@ -2634,33 +2665,34 @@ void ata_detect( )
  1.1684  
  1.1685      if ( (sc == 0x55) && (sn == 0xaa) ) {
  1.1686        write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_UNKNOWN);
  1.1687 -    
  1.1688 +
  1.1689        // reset the channel
  1.1690 -      ata_reset (device);
  1.1691 -      
  1.1692 +      ata_reset(device);
  1.1693 +
  1.1694        // check for ATA or ATAPI
  1.1695        outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
  1.1696        sc = inb(iobase1+ATA_CB_SC);
  1.1697        sn = inb(iobase1+ATA_CB_SN);
  1.1698 -      if ( (sc==0x01) && (sn==0x01) ) {
  1.1699 +      if ((sc==0x01) && (sn==0x01)) {
  1.1700          cl = inb(iobase1+ATA_CB_CL);
  1.1701          ch = inb(iobase1+ATA_CB_CH);
  1.1702          st = inb(iobase1+ATA_CB_STAT);
  1.1703  
  1.1704 -        if ( (cl==0x14) && (ch==0xeb) ) {
  1.1705 +        if ((cl==0x14) && (ch==0xeb)) {
  1.1706            write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATAPI);
  1.1707 -          }
  1.1708 -        else if ( (cl==0x00) && (ch==0x00) && (st!=0x00) ) {
  1.1709 +        } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) {
  1.1710            write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATA);
  1.1711 -          }
  1.1712 +        } else if ((cl==0xff) && (ch==0xff)) {
  1.1713 +          write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE);
  1.1714          }
  1.1715        }
  1.1716 +    }
  1.1717  
  1.1718      type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type);
  1.1719 -    
  1.1720 -    // Now we send a IDENTIFY command to ATA device 
  1.1721 +
  1.1722 +    // Now we send a IDENTIFY command to ATA device
  1.1723      if(type == ATA_TYPE_ATA) {
  1.1724 -      Bit32u sectors;
  1.1725 +      Bit32u sectors_low, sectors_high;
  1.1726        Bit16u cylinders, heads, spt, blksize;
  1.1727        Bit8u  translation, removable, mode;
  1.1728  
  1.1729 @@ -2671,21 +2703,26 @@ void ata_detect( )
  1.1730        write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
  1.1731        write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16);
  1.1732  
  1.1733 -      if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, get_SS(),buffer) !=0 )
  1.1734 +      if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) !=0 )
  1.1735          BX_PANIC("ata-detect: Failed to detect ATA device\n");
  1.1736  
  1.1737        removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
  1.1738 -#ifndef	NO_PIO32
  1.1739 +#ifndef        NO_PIO32
  1.1740        mode      = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
  1.1741  #endif
  1.1742 -
  1.1743        blksize   = read_word(get_SS(),buffer+10);
  1.1744 -      
  1.1745 +
  1.1746        cylinders = read_word(get_SS(),buffer+(1*2)); // word 1
  1.1747        heads     = read_word(get_SS(),buffer+(3*2)); // word 3
  1.1748        spt       = read_word(get_SS(),buffer+(6*2)); // word 6
  1.1749  
  1.1750 -      sectors   = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61
  1.1751 +      if (read_word(get_SS(),buffer+(83*2)) & (1 << 10)) { // word 83 - lba48 support
  1.1752 +        sectors_low  = read_dword(get_SS(),buffer+(100*2)); // word 100 and word 101
  1.1753 +        sectors_high = read_dword(get_SS(),buffer+(102*2)); // word 102 and word 103
  1.1754 +      } else {
  1.1755 +        sectors_low = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61
  1.1756 +        sectors_high = 0;
  1.1757 +      }
  1.1758  
  1.1759        write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
  1.1760        write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable);
  1.1761 @@ -2694,7 +2731,8 @@ void ata_detect( )
  1.1762        write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads, heads);
  1.1763        write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders, cylinders);
  1.1764        write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt);
  1.1765 -      write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors, sectors);
  1.1766 +      write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors_low);
  1.1767 +      write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high, sectors_high);
  1.1768        BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt);
  1.1769  
  1.1770        translation = inb_cmos(0x39 + channel/2);
  1.1771 @@ -2722,14 +2760,14 @@ void ata_detect( )
  1.1772            break;
  1.1773          case ATA_TRANSLATION_LBA:
  1.1774            spt = 63;
  1.1775 -          sectors /= 63;
  1.1776 -          heads = sectors / 1024;
  1.1777 +          sectors_low /= 63;
  1.1778 +          heads = sectors_low / 1024;
  1.1779            if (heads>128) heads = 255;
  1.1780            else if (heads>64) heads = 128;
  1.1781            else if (heads>32) heads = 64;
  1.1782            else if (heads>16) heads = 32;
  1.1783            else heads=16;
  1.1784 -          cylinders = sectors / heads;
  1.1785 +          cylinders = sectors_low / heads;
  1.1786            break;
  1.1787          case ATA_TRANSLATION_RECHS:
  1.1788            // Take care not to overflow
  1.1789 @@ -2756,15 +2794,15 @@ void ata_detect( )
  1.1790        write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, heads);
  1.1791        write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, cylinders);
  1.1792        write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, spt);
  1.1793 - 
  1.1794 -      // fill hdidmap 
  1.1795 +
  1.1796 +      // fill hdidmap
  1.1797        write_byte(ebda_seg,&EbdaData->ata.hdidmap[hdcount], device);
  1.1798        hdcount++;
  1.1799        }
  1.1800 -    
  1.1801 +
  1.1802      // Now we send a IDENTIFY command to ATAPI device
  1.1803      if(type == ATA_TYPE_ATAPI) {
  1.1804 - 
  1.1805 +
  1.1806        Bit8u  type, removable, mode;
  1.1807        Bit16u blksize;
  1.1808  
  1.1809 @@ -2775,12 +2813,12 @@ void ata_detect( )
  1.1810        write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_CDROM);
  1.1811        write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16);
  1.1812  
  1.1813 -      if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, get_SS(),buffer) != 0)
  1.1814 +      if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) != 0)
  1.1815          BX_PANIC("ata-detect: Failed to detect ATAPI device\n");
  1.1816  
  1.1817        type      = read_byte(get_SS(),buffer+1) & 0x1f;
  1.1818        removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
  1.1819 -#ifndef	NO_PIO32
  1.1820 +#ifndef        NO_PIO32
  1.1821        mode      = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
  1.1822  #endif
  1.1823        blksize   = 2048;
  1.1824 @@ -2790,24 +2828,24 @@ void ata_detect( )
  1.1825        write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode);
  1.1826        write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize);
  1.1827  
  1.1828 -      // fill cdidmap 
  1.1829 +      // fill cdidmap
  1.1830        write_byte(ebda_seg,&EbdaData->ata.cdidmap[cdcount], device);
  1.1831        cdcount++;
  1.1832        }
  1.1833 -  
  1.1834 +
  1.1835        {
  1.1836        Bit32u sizeinmb;
  1.1837        Bit16u ataversion;
  1.1838        Bit8u  c, i, version, model[41];
  1.1839 -      
  1.1840 +
  1.1841        switch (type) {
  1.1842          case ATA_TYPE_ATA:
  1.1843 -          sizeinmb = read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors);
  1.1844 -          sizeinmb >>= 11;
  1.1845 +          sizeinmb = (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high) << 21)
  1.1846 +            | (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low) >> 11);
  1.1847          case ATA_TYPE_ATAPI:
  1.1848            // Read ATA/ATAPI version
  1.1849            ataversion=((Bit16u)(read_byte(get_SS(),buffer+161))<<8)|read_byte(get_SS(),buffer+160);
  1.1850 -          for(version=15;version>0;version--) { 
  1.1851 +          for(version=15;version>0;version--) {
  1.1852              if((ataversion&(1<<version))!=0)
  1.1853              break;
  1.1854              }
  1.1855 @@ -2816,7 +2854,7 @@ void ata_detect( )
  1.1856            for(i=0;i<20;i++){
  1.1857              write_byte(get_SS(),model+(i*2),read_byte(get_SS(),buffer+(i*2)+54+1));
  1.1858              write_byte(get_SS(),model+(i*2)+1,read_byte(get_SS(),buffer+(i*2)+54));
  1.1859 -            }
  1.1860 +          }
  1.1861  
  1.1862            // Reformat
  1.1863            write_byte(get_SS(),model+40,0x00);
  1.1864 @@ -2824,7 +2862,13 @@ void ata_detect( )
  1.1865              if(read_byte(get_SS(),model+i)==0x20)
  1.1866                write_byte(get_SS(),model+i,0x00);
  1.1867              else break;
  1.1868 +          }
  1.1869 +          if (i>36) {
  1.1870 +            write_byte(get_SS(),model+36,0x00);
  1.1871 +            for(i=35;i>32;i--){
  1.1872 +              write_byte(get_SS(),model+i,0x2E);
  1.1873              }
  1.1874 +          }
  1.1875            break;
  1.1876          }
  1.1877  
  1.1878 @@ -2832,10 +2876,10 @@ void ata_detect( )
  1.1879          case ATA_TYPE_ATA:
  1.1880            printf("ata%d %s: ",channel,slave?" slave":"master");
  1.1881            i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c);
  1.1882 -          if (sizeinmb < 1UL<<16)
  1.1883 -            printf(" ATA-%d Hard-Disk (%04u MBytes)\n",version,(Bit16u)sizeinmb);
  1.1884 -          else
  1.1885 -            printf(" ATA-%d Hard-Disk (%04u GBytes)\n",version,(Bit16u)(sizeinmb>>10));
  1.1886 +	  if (sizeinmb < (1UL<<16))
  1.1887 +            printf(" ATA-%d Hard-Disk (%4u MBytes)\n", version, (Bit16u)sizeinmb);
  1.1888 +	  else
  1.1889 +            printf(" ATA-%d Hard-Disk (%4u GBytes)\n", version, (Bit16u)(sizeinmb>>10));
  1.1890            break;
  1.1891          case ATA_TYPE_ATAPI:
  1.1892            printf("ata%d %s: ",channel,slave?" slave":"master");
  1.1893 @@ -2856,17 +2900,17 @@ void ata_detect( )
  1.1894    write_byte(ebda_seg,&EbdaData->ata.hdcount, hdcount);
  1.1895    write_byte(ebda_seg,&EbdaData->ata.cdcount, cdcount);
  1.1896    write_byte(0x40,0x75, hdcount);
  1.1897 - 
  1.1898 +
  1.1899    printf("\n");
  1.1900  
  1.1901    // FIXME : should use bios=cmos|auto|disable bits
  1.1902    // FIXME : should know about translation bits
  1.1903 -  // FIXME : move hard_drive_post here 
  1.1904 -  
  1.1905 +  // FIXME : move hard_drive_post here
  1.1906 +
  1.1907  }
  1.1908  
  1.1909  // ---------------------------------------------------------------------------
  1.1910 -// ATA/ATAPI driver : software reset 
  1.1911 +// ATA/ATAPI driver : software reset
  1.1912  // ---------------------------------------------------------------------------
  1.1913  // ATA-3
  1.1914  // 8.2.1 Software reset - Device 0
  1.1915 @@ -2876,7 +2920,8 @@ Bit16u device;
  1.1916  {
  1.1917    Bit16u ebda_seg=read_word(0x0040,0x000E);
  1.1918    Bit16u iobase1, iobase2;
  1.1919 -  Bit8u  channel, slave, sn, sc; 
  1.1920 +  Bit8u  channel, slave, sn, sc;
  1.1921 +  Bit8u  type;
  1.1922    Bit16u max;
  1.1923  
  1.1924    channel = device / 2;
  1.1925 @@ -2891,16 +2936,13 @@ Bit16u device;
  1.1926    outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST);
  1.1927  
  1.1928  // 8.2.1 (b) -- wait for BSY
  1.1929 -  max=0xff;
  1.1930 -  while(--max>0) {
  1.1931 -    Bit8u status = inb(iobase1+ATA_CB_STAT);
  1.1932 -    if ((status & ATA_CB_STAT_BSY) != 0) break;
  1.1933 -  }
  1.1934 +  await_ide(BSY, iobase1, 20);
  1.1935  
  1.1936  // 8.2.1 (f) -- clear SRST
  1.1937    outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
  1.1938  
  1.1939 -  if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_NONE) {
  1.1940 +  type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type);
  1.1941 +  if (type != ATA_TYPE_NONE) {
  1.1942  
  1.1943  // 8.2.1 (g) -- check for sc==sn==0x01
  1.1944      // select device
  1.1945 @@ -2909,21 +2951,14 @@ Bit16u device;
  1.1946      sn = inb(iobase1+ATA_CB_SN);
  1.1947  
  1.1948      if ( (sc==0x01) && (sn==0x01) ) {
  1.1949 +      if (type == ATA_TYPE_ATA) //ATA
  1.1950 +        await_ide(NOT_BSY_RDY, iobase1, IDE_TIMEOUT);
  1.1951 +      else //ATAPI
  1.1952 +        await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
  1.1953 +    }
  1.1954  
  1.1955  // 8.2.1 (h) -- wait for not BSY
  1.1956 -      max=0xff;
  1.1957 -      while(--max>0) {
  1.1958 -        Bit8u status = inb(iobase1+ATA_CB_STAT);
  1.1959 -        if ((status & ATA_CB_STAT_BSY) == 0) break;
  1.1960 -        }
  1.1961 -      }
  1.1962 -    }
  1.1963 -
  1.1964 -// 8.2.1 (i) -- wait for DRDY
  1.1965 -  max=0xfff;
  1.1966 -  while(--max>0) {
  1.1967 -    Bit8u status = inb(iobase1+ATA_CB_STAT);
  1.1968 -      if ((status & ATA_CB_STAT_RDY) != 0) break;
  1.1969 +    await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
  1.1970    }
  1.1971  
  1.1972    // Enable interrupts
  1.1973 @@ -2931,7 +2966,7 @@ Bit16u device;
  1.1974  }
  1.1975  
  1.1976  // ---------------------------------------------------------------------------
  1.1977 -// ATA/ATAPI driver : execute a non data command 
  1.1978 +// ATA/ATAPI driver : execute a non data command
  1.1979  // ---------------------------------------------------------------------------
  1.1980  
  1.1981  Bit16u ata_cmd_non_data()
  1.1982 @@ -2949,9 +2984,9 @@ Bit16u ata_cmd_non_data()
  1.1983        // 5 : more sectors to read/verify
  1.1984        // 6 : no sectors left to write
  1.1985        // 7 : more sectors to write
  1.1986 -Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, lba, segment, offset)
  1.1987 +Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset)
  1.1988  Bit16u device, command, count, cylinder, head, sector, segment, offset;
  1.1989 -Bit32u lba;
  1.1990 +Bit32u lba_low, lba_high;
  1.1991  {
  1.1992    Bit16u ebda_seg=read_word(0x0040,0x000E);
  1.1993    Bit16u iobase1, iobase2, blksize;
  1.1994 @@ -2980,22 +3015,20 @@ Bit32u lba;
  1.1995  
  1.1996    // sector will be 0 only on lba access. Convert to lba-chs
  1.1997    if (sector == 0) {
  1.1998 -    if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) {
  1.1999 +    if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) {
  1.2000        outb(iobase1 + ATA_CB_FR, 0x00);
  1.2001        outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff);
  1.2002 -      outb(iobase1 + ATA_CB_SN, lba >> 24);
  1.2003 -      outb(iobase1 + ATA_CB_CL, 0);
  1.2004 -      outb(iobase1 + ATA_CB_CH, 0);
  1.2005 +      outb(iobase1 + ATA_CB_SN, lba_low >> 24);
  1.2006 +      outb(iobase1 + ATA_CB_CL, lba_high & 0xff);
  1.2007 +      outb(iobase1 + ATA_CB_CH, lba_high >> 8);
  1.2008        command |= 0x04;
  1.2009        count &= (1UL << 8) - 1;
  1.2010 -      lba &= (1UL << 24) - 1;
  1.2011 +      lba_low &= (1UL << 24) - 1;
  1.2012        }
  1.2013 -    sector = (Bit16u) (lba & 0x000000ffL);
  1.2014 -    lba >>= 8;
  1.2015 -    cylinder = (Bit16u) (lba & 0x0000ffffL);
  1.2016 -    lba >>= 16;
  1.2017 -    head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
  1.2018 -    }
  1.2019 +    sector = (Bit16u) (lba_low & 0x000000ffL);
  1.2020 +    cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
  1.2021 +    head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
  1.2022 +  }
  1.2023  
  1.2024    outb(iobase1 + ATA_CB_FR, 0x00);
  1.2025    outb(iobase1 + ATA_CB_SC, count);
  1.2026 @@ -3005,10 +3038,8 @@ Bit32u lba;
  1.2027    outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head );
  1.2028    outb(iobase1 + ATA_CB_CMD, command);
  1.2029  
  1.2030 -  while (1) {
  1.2031 -    status = inb(iobase1 + ATA_CB_STAT);
  1.2032 -    if ( !(status & ATA_CB_STAT_BSY) ) break;
  1.2033 -    }
  1.2034 +  await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
  1.2035 +  status = inb(iobase1 + ATA_CB_STAT);
  1.2036  
  1.2037    if (status & ATA_CB_STAT_ERR) {
  1.2038      BX_DEBUG_ATA("ata_cmd_data_in : read error\n");
  1.2039 @@ -3029,12 +3060,12 @@ ASM_END
  1.2040  ASM_START
  1.2041          push bp
  1.2042          mov  bp, sp
  1.2043 -        mov  di, _ata_cmd_data_in.offset + 2[bp]  
  1.2044 -        mov  ax, _ata_cmd_data_in.segment + 2[bp] 
  1.2045 -        mov  cx, _ata_cmd_data_in.blksize + 2[bp] 
  1.2046 +        mov  di, _ata_cmd_data_in.offset + 2[bp]
  1.2047 +        mov  ax, _ata_cmd_data_in.segment + 2[bp]
  1.2048 +        mov  cx, _ata_cmd_data_in.blksize + 2[bp]
  1.2049  
  1.2050          ;; adjust if there will be an overrun. 2K max sector size
  1.2051 -        cmp   di, #0xf800 ;; 
  1.2052 +        cmp   di, #0xf800 ;;
  1.2053          jbe   ata_in_no_adjust
  1.2054  
  1.2055  ata_in_adjust:
  1.2056 @@ -3046,7 +3077,7 @@ ata_in_no_adjust:
  1.2057  
  1.2058          mov   dx, _ata_cmd_data_in.iobase1 + 2[bp] ;; ATA data read port
  1.2059  
  1.2060 -        mov  ah, _ata_cmd_data_in.mode + 2[bp] 
  1.2061 +        mov  ah, _ata_cmd_data_in.mode + 2[bp]
  1.2062          cmp  ah, #ATA_MODE_PIO32
  1.2063          je   ata_in_32
  1.2064  
  1.2065 @@ -3068,9 +3099,10 @@ ASM_END
  1.2066      current++;
  1.2067      write_word(ebda_seg, &EbdaData->ata.trsfsectors,current);
  1.2068      count--;
  1.2069 +    await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
  1.2070      status = inb(iobase1 + ATA_CB_STAT);
  1.2071      if (count == 0) {
  1.2072 -      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 
  1.2073 +      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
  1.2074            != ATA_CB_STAT_RDY ) {
  1.2075          BX_DEBUG_ATA("ata_cmd_data_in : no sectors left (status %02x)\n", (unsigned) status);
  1.2076          return 4;
  1.2077 @@ -3078,7 +3110,7 @@ ASM_END
  1.2078        break;
  1.2079        }
  1.2080      else {
  1.2081 -      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 
  1.2082 +      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
  1.2083            != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
  1.2084          BX_DEBUG_ATA("ata_cmd_data_in : more sectors left (status %02x)\n", (unsigned) status);
  1.2085          return 5;
  1.2086 @@ -3103,9 +3135,9 @@ ASM_END
  1.2087        // 5 : more sectors to read/verify
  1.2088        // 6 : no sectors left to write
  1.2089        // 7 : more sectors to write
  1.2090 -Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, lba, segment, offset)
  1.2091 +Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset)
  1.2092  Bit16u device, command, count, cylinder, head, sector, segment, offset;
  1.2093 -Bit32u lba;
  1.2094 +Bit32u lba_low, lba_high;
  1.2095  {
  1.2096    Bit16u ebda_seg=read_word(0x0040,0x000E);
  1.2097    Bit16u iobase1, iobase2, blksize;
  1.2098 @@ -3134,22 +3166,20 @@ Bit32u lba;
  1.2099  
  1.2100    // sector will be 0 only on lba access. Convert to lba-chs
  1.2101    if (sector == 0) {
  1.2102 -    if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) {
  1.2103 +    if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) {
  1.2104        outb(iobase1 + ATA_CB_FR, 0x00);
  1.2105        outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff);
  1.2106 -      outb(iobase1 + ATA_CB_SN, lba >> 24);
  1.2107 -      outb(iobase1 + ATA_CB_CL, 0);
  1.2108 -      outb(iobase1 + ATA_CB_CH, 0);
  1.2109 +      outb(iobase1 + ATA_CB_SN, lba_low >> 24);
  1.2110 +      outb(iobase1 + ATA_CB_CL, lba_high & 0xff);
  1.2111 +      outb(iobase1 + ATA_CB_CH, lba_high >> 8);
  1.2112        command |= 0x04;
  1.2113        count &= (1UL << 8) - 1;
  1.2114 -      lba &= (1UL << 24) - 1;
  1.2115 +      lba_low &= (1UL << 24) - 1;
  1.2116        }
  1.2117 -    sector = (Bit16u) (lba & 0x000000ffL);
  1.2118 -    lba >>= 8;
  1.2119 -    cylinder = (Bit16u) (lba & 0x0000ffffL);
  1.2120 -    lba >>= 16;
  1.2121 -    head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
  1.2122 -    }
  1.2123 +    sector = (Bit16u) (lba_low & 0x000000ffL);
  1.2124 +    cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
  1.2125 +    head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
  1.2126 +  }
  1.2127  
  1.2128    outb(iobase1 + ATA_CB_FR, 0x00);
  1.2129    outb(iobase1 + ATA_CB_SC, count);
  1.2130 @@ -3159,10 +3189,8 @@ Bit32u lba;
  1.2131    outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head );
  1.2132    outb(iobase1 + ATA_CB_CMD, command);
  1.2133  
  1.2134 -  while (1) {
  1.2135 -    status = inb(iobase1 + ATA_CB_STAT);
  1.2136 -    if ( !(status & ATA_CB_STAT_BSY) ) break;
  1.2137 -    }
  1.2138 +  await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
  1.2139 +  status = inb(iobase1 + ATA_CB_STAT);
  1.2140  
  1.2141    if (status & ATA_CB_STAT_ERR) {
  1.2142      BX_DEBUG_ATA("ata_cmd_data_out : read error\n");
  1.2143 @@ -3183,12 +3211,12 @@ ASM_END
  1.2144  ASM_START
  1.2145          push bp
  1.2146          mov  bp, sp
  1.2147 -        mov  si, _ata_cmd_data_out.offset + 2[bp]  
  1.2148 -        mov  ax, _ata_cmd_data_out.segment + 2[bp] 
  1.2149 -        mov  cx, _ata_cmd_data_out.blksize + 2[bp] 
  1.2150 +        mov  si, _ata_cmd_data_out.offset + 2[bp]
  1.2151 +        mov  ax, _ata_cmd_data_out.segment + 2[bp]
  1.2152 +        mov  cx, _ata_cmd_data_out.blksize + 2[bp]
  1.2153  
  1.2154          ;; adjust if there will be an overrun. 2K max sector size
  1.2155 -        cmp   si, #0xf800 ;; 
  1.2156 +        cmp   si, #0xf800 ;;
  1.2157          jbe   ata_out_no_adjust
  1.2158  
  1.2159  ata_out_adjust:
  1.2160 @@ -3200,7 +3228,7 @@ ata_out_no_adjust:
  1.2161  
  1.2162          mov   dx, _ata_cmd_data_out.iobase1 + 2[bp] ;; ATA data write port
  1.2163  
  1.2164 -        mov  ah, _ata_cmd_data_out.mode + 2[bp] 
  1.2165 +        mov  ah, _ata_cmd_data_out.mode + 2[bp]
  1.2166          cmp  ah, #ATA_MODE_PIO32
  1.2167          je   ata_out_32
  1.2168  
  1.2169 @@ -3226,7 +3254,7 @@ ASM_END
  1.2170      count--;
  1.2171      status = inb(iobase1 + ATA_CB_STAT);
  1.2172      if (count == 0) {
  1.2173 -      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 
  1.2174 +      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
  1.2175            != ATA_CB_STAT_RDY ) {
  1.2176          BX_DEBUG_ATA("ata_cmd_data_out : no sectors left (status %02x)\n", (unsigned) status);
  1.2177          return 6;
  1.2178 @@ -3234,7 +3262,7 @@ ASM_END
  1.2179        break;
  1.2180        }
  1.2181      else {
  1.2182 -      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 
  1.2183 +      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
  1.2184            != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
  1.2185          BX_DEBUG_ATA("ata_cmd_data_out : more sectors left (status %02x)\n", (unsigned) status);
  1.2186          return 7;
  1.2187 @@ -3301,19 +3329,17 @@ Bit32u length;
  1.2188    if (status & ATA_CB_STAT_BSY) return 2;
  1.2189  
  1.2190    outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
  1.2191 -  // outb(iobase1 + ATA_CB_FR, 0x00);
  1.2192 -  // outb(iobase1 + ATA_CB_SC, 0x00);
  1.2193 -  // outb(iobase1 + ATA_CB_SN, 0x00);
  1.2194 +  outb(iobase1 + ATA_CB_FR, 0x00);
  1.2195 +  outb(iobase1 + ATA_CB_SC, 0x00);
  1.2196 +  outb(iobase1 + ATA_CB_SN, 0x00);
  1.2197    outb(iobase1 + ATA_CB_CL, 0xfff0 & 0x00ff);
  1.2198    outb(iobase1 + ATA_CB_CH, 0xfff0 >> 8);
  1.2199    outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
  1.2200    outb(iobase1 + ATA_CB_CMD, ATA_CMD_PACKET);
  1.2201  
  1.2202    // Device should ok to receive command
  1.2203 -  while (1) {
  1.2204 -    status = inb(iobase1 + ATA_CB_STAT);
  1.2205 -    if ( !(status & ATA_CB_STAT_BSY) ) break;
  1.2206 -    }
  1.2207 +  await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
  1.2208 +  status = inb(iobase1 + ATA_CB_STAT);
  1.2209  
  1.2210    if (status & ATA_CB_STAT_ERR) {
  1.2211      BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status);
  1.2212 @@ -3330,13 +3356,13 @@ Bit32u length;
  1.2213    // Send command to device
  1.2214  ASM_START
  1.2215        sti  ;; enable higher priority interrupts
  1.2216 - 
  1.2217 +
  1.2218        push bp
  1.2219        mov  bp, sp
  1.2220 -    
  1.2221 -      mov  si, _ata_cmd_packet.cmdoff + 2[bp]  
  1.2222 -      mov  ax, _ata_cmd_packet.cmdseg + 2[bp] 
  1.2223 -      mov  cx, _ata_cmd_packet.cmdlen + 2[bp] 
  1.2224 +
  1.2225 +      mov  si, _ata_cmd_packet.cmdoff + 2[bp]
  1.2226 +      mov  ax, _ata_cmd_packet.cmdseg + 2[bp]
  1.2227 +      mov  cx, _ata_cmd_packet.cmdlen + 2[bp]
  1.2228        mov  es, ax      ;; segment in es
  1.2229  
  1.2230        mov  dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data write port
  1.2231 @@ -3349,32 +3375,38 @@ ASM_START
  1.2232  ASM_END
  1.2233  
  1.2234    if (inout == ATA_DATA_NO) {
  1.2235 +    await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
  1.2236      status = inb(iobase1 + ATA_CB_STAT);
  1.2237      }
  1.2238    else {
  1.2239 +        Bit16u loops = 0;
  1.2240 +        Bit8u sc;
  1.2241    while (1) {
  1.2242  
  1.2243 +      if (loops == 0) {//first time through
  1.2244 +        status = inb(iobase2 + ATA_CB_ASTAT);
  1.2245 +        await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
  1.2246 +      }
  1.2247 +      else
  1.2248 +        await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
  1.2249 +      loops++;
  1.2250 +
  1.2251        status = inb(iobase1 + ATA_CB_STAT);
  1.2252 +      sc = inb(iobase1 + ATA_CB_SC);
  1.2253  
  1.2254        // Check if command completed
  1.2255 -      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ) ) ==0 ) break;
  1.2256 +      if(((inb(iobase1 + ATA_CB_SC)&0x7)==0x3) &&
  1.2257 +         ((status & (ATA_CB_STAT_RDY | ATA_CB_STAT_ERR)) == ATA_CB_STAT_RDY)) break;
  1.2258  
  1.2259        if (status & ATA_CB_STAT_ERR) {
  1.2260          BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status);
  1.2261          return 3;
  1.2262        }
  1.2263  
  1.2264 -      // Device must be ready to send data
  1.2265 -      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 
  1.2266 -            != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
  1.2267 -        BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", status);
  1.2268 -        return 4;
  1.2269 -        }
  1.2270 -
  1.2271        // Normalize address
  1.2272        bufseg += (bufoff / 16);
  1.2273        bufoff %= 16;
  1.2274 -    
  1.2275 +
  1.2276        // Get the byte count
  1.2277        lcount =  ((Bit16u)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL);
  1.2278  
  1.2279 @@ -3435,10 +3467,10 @@ ASM_START
  1.2280  
  1.2281          mov  dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data read port
  1.2282  
  1.2283 -        mov  cx, _ata_cmd_packet.lbefore + 2[bp] 
  1.2284 +        mov  cx, _ata_cmd_packet.lbefore + 2[bp]
  1.2285          jcxz ata_packet_no_before
  1.2286  
  1.2287 -        mov  ah, _ata_cmd_packet.lmode + 2[bp] 
  1.2288 +        mov  ah, _ata_cmd_packet.lmode + 2[bp]
  1.2289          cmp  ah, #ATA_MODE_PIO32
  1.2290          je   ata_packet_in_before_32
  1.2291  
  1.2292 @@ -3455,14 +3487,14 @@ ata_packet_in_before_32_loop:
  1.2293          pop  eax
  1.2294  
  1.2295  ata_packet_no_before:
  1.2296 -        mov  cx, _ata_cmd_packet.lcount + 2[bp] 
  1.2297 +        mov  cx, _ata_cmd_packet.lcount + 2[bp]
  1.2298          jcxz ata_packet_after
  1.2299  
  1.2300 -        mov  di, _ata_cmd_packet.bufoff + 2[bp]  
  1.2301 -        mov  ax, _ata_cmd_packet.bufseg + 2[bp] 
  1.2302 +        mov  di, _ata_cmd_packet.bufoff + 2[bp]
  1.2303 +        mov  ax, _ata_cmd_packet.bufseg + 2[bp]
  1.2304          mov  es, ax
  1.2305  
  1.2306 -        mov  ah, _ata_cmd_packet.lmode + 2[bp] 
  1.2307 +        mov  ah, _ata_cmd_packet.lmode + 2[bp]
  1.2308          cmp  ah, #ATA_MODE_PIO32
  1.2309          je   ata_packet_in_32
  1.2310  
  1.2311 @@ -3476,10 +3508,10 @@ ata_packet_in_32:
  1.2312            insd ;; CX dwords transfered to port(DX) to ES:[DI]
  1.2313  
  1.2314  ata_packet_after:
  1.2315 -        mov  cx, _ata_cmd_packet.lafter + 2[bp] 
  1.2316 +        mov  cx, _ata_cmd_packet.lafter + 2[bp]
  1.2317          jcxz ata_packet_done
  1.2318  
  1.2319 -        mov  ah, _ata_cmd_packet.lmode + 2[bp] 
  1.2320 +        mov  ah, _ata_cmd_packet.lmode + 2[bp]
  1.2321          cmp  ah, #ATA_MODE_PIO32
  1.2322          je   ata_packet_in_after_32
  1.2323  
  1.2324 @@ -3509,7 +3541,7 @@ ASM_END
  1.2325      }
  1.2326  
  1.2327    // Final check, device must be ready
  1.2328 -  if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 
  1.2329 +  if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
  1.2330           != ATA_CB_STAT_RDY ) {
  1.2331      BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", (unsigned) status);
  1.2332      return 4;
  1.2333 @@ -3528,55 +3560,108 @@ ASM_END
  1.2334  // Start of ATA/ATAPI generic functions
  1.2335  // ---------------------------------------------------------------------------
  1.2336  
  1.2337 -  Bit16u 
  1.2338 -atapi_get_sense(device)
  1.2339 +  Bit16u
  1.2340 +atapi_get_sense(device, seg, asc, ascq)
  1.2341    Bit16u device;
  1.2342  {
  1.2343    Bit8u  atacmd[12];
  1.2344 -  Bit8u  buffer[16];
  1.2345 +  Bit8u  buffer[18];
  1.2346    Bit8u i;
  1.2347  
  1.2348    memsetb(get_SS(),atacmd,0,12);
  1.2349  
  1.2350 -  // Request SENSE 
  1.2351 -  atacmd[0]=0x03;    
  1.2352 -  atacmd[4]=0x20;    
  1.2353 -  if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 16L, ATA_DATA_IN, get_SS(), buffer) != 0)
  1.2354 +  // Request SENSE
  1.2355 +  atacmd[0]=ATA_CMD_REQUEST_SENSE;
  1.2356 +  atacmd[4]=sizeof(buffer);
  1.2357 +  if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 18L, ATA_DATA_IN, get_SS(), buffer) != 0)
  1.2358      return 0x0002;
  1.2359  
  1.2360 -  if ((buffer[0] & 0x7e) == 0x70) {
  1.2361 -    return (((Bit16u)buffer[2]&0x0f)*0x100)+buffer[12];
  1.2362 -    }
  1.2363 +  write_byte(seg,asc,buffer[12]);
  1.2364 +  write_byte(seg,ascq,buffer[13]);
  1.2365  
  1.2366    return 0;
  1.2367  }
  1.2368  
  1.2369 -  Bit16u 
  1.2370 +  Bit16u
  1.2371  atapi_is_ready(device)
  1.2372    Bit16u device;
  1.2373  {
  1.2374 -  Bit8u  atacmd[12];
  1.2375 -  Bit8u  buffer[];
  1.2376 -
  1.2377 -  memsetb(get_SS(),atacmd,0,12);
  1.2378 - 
  1.2379 -  // Test Unit Ready
  1.2380 -  if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO, get_SS(), buffer) != 0)
  1.2381 -    return 0x000f;
  1.2382 -
  1.2383 -  if (atapi_get_sense(device) !=0 ) {
  1.2384 -    memsetb(get_SS(),atacmd,0,12);
  1.2385 -
  1.2386 -    // try to send Test Unit Ready again
  1.2387 -    if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO, get_SS(), buffer) != 0)
  1.2388 -      return 0x000f;
  1.2389 -
  1.2390 -    return atapi_get_sense(device);
  1.2391 +  Bit8u packet[12];
  1.2392 +  Bit8u buf[8];
  1.2393 +  Bit32u block_len;
  1.2394 +  Bit32u sectors;
  1.2395 +  Bit32u timeout; //measured in ms
  1.2396 +  Bit32u time;
  1.2397 +  Bit8u asc, ascq;
  1.2398 +  Bit8u in_progress;
  1.2399 +  Bit16u ebda_seg = read_word(0x0040,0x000E);
  1.2400 +  if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != ATA_TYPE_ATAPI) {
  1.2401 +    printf("not implemented for non-ATAPI device\n");
  1.2402 +    return -1;
  1.2403 +  }
  1.2404 +
  1.2405 +  BX_DEBUG_ATA("ata_detect_medium: begin\n");
  1.2406 +  memsetb(get_SS(),packet, 0, sizeof packet);
  1.2407 +  packet[0] = 0x25; /* READ CAPACITY */
  1.2408 +
  1.2409 +  /* Retry READ CAPACITY 50 times unless MEDIUM NOT PRESENT
  1.2410 +   * is reported by the device. If the device reports "IN PROGRESS",
  1.2411 +   * 30 seconds is added. */
  1.2412 +  timeout = 5000;
  1.2413 +  time = 0;
  1.2414 +  in_progress = 0;
  1.2415 +  while (time < timeout) {
  1.2416 +    if (ata_cmd_packet(device, sizeof(packet), get_SS(), packet, 0, 8L, ATA_DATA_IN, get_SS(), buf) == 0)
  1.2417 +      goto ok;
  1.2418 +
  1.2419 +    if (atapi_get_sense(device, get_SS(), &asc, &ascq) == 0) {
  1.2420 +      if (asc == 0x3a) { /* MEDIUM NOT PRESENT */
  1.2421 +        BX_DEBUG_ATA("Device reports MEDIUM NOT PRESENT\n");
  1.2422 +        return -1;
  1.2423 +      }
  1.2424 +
  1.2425 +      if (asc == 0x04 && ascq == 0x01 && !in_progress) {
  1.2426 +        /* IN PROGRESS OF BECOMING READY */
  1.2427 +        printf("Waiting for device to detect medium... ");
  1.2428 +        /* Allow 30 seconds more */
  1.2429 +        timeout = 30000;
  1.2430 +        in_progress = 1;
  1.2431 +      }
  1.2432      }
  1.2433 +    time += 100;
  1.2434 +  }
  1.2435 +  BX_DEBUG_ATA("read capacity failed\n");
  1.2436 +  return -1;
  1.2437 +ok:
  1.2438 +
  1.2439 +  block_len = (Bit32u) buf[4] << 24
  1.2440 +    | (Bit32u) buf[5] << 16
  1.2441 +    | (Bit32u) buf[6] << 8
  1.2442 +    | (Bit32u) buf[7] << 0;
  1.2443 +  BX_DEBUG_ATA("block_len=%u\n", block_len);
  1.2444 +
  1.2445 +  if (block_len!= 2048 && block_len!= 512)
  1.2446 +  {
  1.2447 +    printf("Unsupported sector size %u\n", block_len);
  1.2448 +    return -1;
  1.2449 +  }
  1.2450 +  write_dword(ebda_seg,&EbdaData->ata.devices[device].blksize, block_len);
  1.2451 +
  1.2452 +  sectors = (Bit32u) buf[0] << 24
  1.2453 +    | (Bit32u) buf[1] << 16
  1.2454 +    | (Bit32u) buf[2] << 8
  1.2455 +    | (Bit32u) buf[3] << 0;
  1.2456 +
  1.2457 +  BX_DEBUG_ATA("sectors=%u\n", sectors);
  1.2458 +  if (block_len == 2048)
  1.2459 +    sectors <<= 2; /* # of sectors in 512-byte "soft" sector */
  1.2460 +  if (sectors != read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low))
  1.2461 +    printf("%dMB medium detected\n", sectors>>(20-9));
  1.2462 +  write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors);
  1.2463    return 0;
  1.2464  }
  1.2465  
  1.2466 -  Bit16u 
  1.2467 +  Bit16u
  1.2468  atapi_is_cdrom(device)
  1.2469    Bit8u device;
  1.2470  {
  1.2471 @@ -3636,7 +3721,7 @@ static char eltorito[24]="EL TORITO SPEC
  1.2472  //
  1.2473  // Returns ah: emulated drive, al: error code
  1.2474  //
  1.2475 -  Bit16u 
  1.2476 +  Bit16u
  1.2477  cdrom_boot()
  1.2478  {
  1.2479    Bit16u ebda_seg=read_word(0x0040,0x000E);
  1.2480 @@ -3649,10 +3734,13 @@ cdrom_boot()
  1.2481    for (device=0; device<BX_MAX_ATA_DEVICES;device++) {
  1.2482      if (atapi_is_cdrom(device)) break;
  1.2483      }
  1.2484 -  
  1.2485 +
  1.2486    // if not found
  1.2487    if(device >= BX_MAX_ATA_DEVICES) return 2;
  1.2488  
  1.2489 +  if(error = atapi_is_ready(device) != 0)
  1.2490 +    BX_INFO("ata_is_ready returned %d\n",error);
  1.2491 +
  1.2492    // Read the Boot Record Volume Descriptor
  1.2493    memsetb(get_SS(),atacmd,0,12);
  1.2494    atacmd[0]=0x28;                      // READ command
  1.2495 @@ -3672,7 +3760,7 @@ cdrom_boot()
  1.2496     }
  1.2497    for(i=0;i<23;i++)
  1.2498      if(buffer[7+i]!=read_byte(0xf000,&eltorito[i]))return 6;
  1.2499 -  
  1.2500 +
  1.2501    // ok, now we calculate the Boot catalog address
  1.2502    lba=buffer[0x4A]*0x1000000+buffer[0x49]*0x10000+buffer[0x48]*0x100+buffer[0x47];
  1.2503  
  1.2504 @@ -3687,7 +3775,7 @@ cdrom_boot()
  1.2505    atacmd[5]=(lba & 0x000000ff);
  1.2506    if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0)
  1.2507      return 7;
  1.2508 - 
  1.2509 +
  1.2510    // Validation entry
  1.2511    if(buffer[0x00]!=0x01)return 8;   // Header
  1.2512    if(buffer[0x01]!=0x00)return 9;   // Platform
  1.2513 @@ -3706,10 +3794,10 @@ cdrom_boot()
  1.2514  
  1.2515    write_byte(ebda_seg,&EbdaData->cdemu.media,buffer[0x21]);
  1.2516    if(buffer[0x21]==0){
  1.2517 -    // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0. 
  1.2518 +    // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0.
  1.2519      // Win2000 cd boot needs to know it booted from cd
  1.2520      write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0xE0);
  1.2521 -    } 
  1.2522 +    }
  1.2523    else if(buffer[0x21]<4)
  1.2524      write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x00);
  1.2525    else
  1.2526 @@ -3723,7 +3811,7 @@ cdrom_boot()
  1.2527  
  1.2528    write_word(ebda_seg,&EbdaData->cdemu.load_segment,boot_segment);
  1.2529    write_word(ebda_seg,&EbdaData->cdemu.buffer_segment,0x0000);
  1.2530 -  
  1.2531 +
  1.2532    nbsectors=buffer[0x27]*0x100+buffer[0x26];
  1.2533    write_word(ebda_seg,&EbdaData->cdemu.sector_count,nbsectors);
  1.2534  
  1.2535 @@ -3748,7 +3836,6 @@ cdrom_boot()
  1.2536    tcpa_ipl((Bit32u)1L,(Bit32u)boot_segment,(Bit32u)0L,(Bit32u)512L);
  1.2537  #endif
  1.2538  
  1.2539 -
  1.2540    // Remember the media type
  1.2541    switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) {
  1.2542      case 0x01:  // 1.2M floppy
  1.2543 @@ -3769,7 +3856,7 @@ cdrom_boot()
  1.2544      case 0x04:  // Harddrive
  1.2545        write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,read_byte(boot_segment,446+6)&0x3f);
  1.2546        write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,
  1.2547 -	      (read_byte(boot_segment,446+6)<<2) + read_byte(boot_segment,446+7) + 1);
  1.2548 +              (read_byte(boot_segment,446+6)<<2) + read_byte(boot_segment,446+7) + 1);
  1.2549        write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,read_byte(boot_segment,446+5) + 1);
  1.2550        break;
  1.2551     }
  1.2552 @@ -3782,7 +3869,7 @@ cdrom_boot()
  1.2553        write_byte(ebda_seg, &EbdaData->ata.hdcount, read_byte(ebda_seg, &EbdaData->ata.hdcount) + 1);
  1.2554     }
  1.2555  
  1.2556 -  
  1.2557 +
  1.2558    // everything is ok, so from now on, the emulation is active
  1.2559    if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0)
  1.2560      write_byte(ebda_seg,&EbdaData->cdemu.active,0x01);
  1.2561 @@ -4128,9 +4215,10 @@ ASM_END
  1.2562        regs.u.r8.al = inb_cmos(0x30);
  1.2563        regs.u.r8.ah = inb_cmos(0x31);
  1.2564  
  1.2565 -      // limit to 15M
  1.2566 -      if(regs.u.r16.ax > 0x3c00)
  1.2567 -        regs.u.r16.ax = 0x3c00;
  1.2568 +      // According to Ralf Brown's interrupt the limit should be 15M,
  1.2569 +      // but real machines mostly return max. 63M.
  1.2570 +      if(regs.u.r16.ax > 0xffc0)
  1.2571 +        regs.u.r16.ax = 0xffc0;
  1.2572  
  1.2573        CLEAR_CF();
  1.2574  #endif
  1.2575 @@ -4348,13 +4436,35 @@ BX_DEBUG_INT15("case 2:\n");
  1.2576  
  1.2577          case 3: // Set Resolution
  1.2578  BX_DEBUG_INT15("case 3:\n");
  1.2579 -          // BX:
  1.2580 +          // BH:
  1.2581            //      0 =  25 dpi, 1 count  per millimeter
  1.2582            //      1 =  50 dpi, 2 counts per millimeter
  1.2583            //      2 = 100 dpi, 4 counts per millimeter
  1.2584            //      3 = 200 dpi, 8 counts per millimeter
  1.2585 -          CLEAR_CF();
  1.2586 -          regs.u.r8.ah = 0;
  1.2587 +          comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets
  1.2588 +          if (regs.u.r8.bh < 4) {
  1.2589 +            ret = send_to_mouse_ctrl(0xE8); // set resolution command
  1.2590 +            if (ret == 0) {
  1.2591 +              ret = get_mouse_data(&mouse_data1);
  1.2592 +              if (mouse_data1 != 0xfa)
  1.2593 +                BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
  1.2594 +              ret = send_to_mouse_ctrl(regs.u.r8.bh);
  1.2595 +              ret = get_mouse_data(&mouse_data1);
  1.2596 +              if (mouse_data1 != 0xfa)
  1.2597 +                BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1);
  1.2598 +              CLEAR_CF();
  1.2599 +              regs.u.r8.ah = 0;
  1.2600 +            } else {
  1.2601 +              // error
  1.2602 +              SET_CF();
  1.2603 +              regs.u.r8.ah = UNSUPPORTED_FUNCTION;
  1.2604 +            }
  1.2605 +          } else {
  1.2606 +            // error
  1.2607 +            SET_CF();
  1.2608 +            regs.u.r8.ah = UNSUPPORTED_FUNCTION;
  1.2609 +          }
  1.2610 +          set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
  1.2611            break;
  1.2612  
  1.2613          case 4: // Get Device ID
  1.2614 @@ -4476,7 +4586,30 @@ BX_DEBUG_INT15("case default:\n");
  1.2615        break;
  1.2616      }
  1.2617  }
  1.2618 -#endif
  1.2619 +#endif // BX_USE_PS2_MOUSE
  1.2620 +
  1.2621 +
  1.2622 +void set_e820_range(ES, DI, start, end, type)
  1.2623 +     Bit16u ES;
  1.2624 +     Bit16u DI;
  1.2625 +     Bit32u start;
  1.2626 +     Bit32u end;
  1.2627 +     Bit16u type;
  1.2628 +{
  1.2629 +    write_word(ES, DI, start);
  1.2630 +    write_word(ES, DI+2, start >> 16);
  1.2631 +    write_word(ES, DI+4, 0x00);
  1.2632 +    write_word(ES, DI+6, 0x00);
  1.2633 +
  1.2634 +    end -= start;
  1.2635 +    write_word(ES, DI+8, end);
  1.2636 +    write_word(ES, DI+10, end >> 16);
  1.2637 +    write_word(ES, DI+12, 0x0000);
  1.2638 +    write_word(ES, DI+14, 0x0000);
  1.2639 +
  1.2640 +    write_word(ES, DI+16, type);
  1.2641 +    write_word(ES, DI+18, 0x0);
  1.2642 +}
  1.2643  
  1.2644    void
  1.2645  int15_function32(regs, ES, DS, FLAGS)
  1.2646 @@ -4490,17 +4623,20 @@ BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.
  1.2647  
  1.2648    switch (regs.u.r8.ah) {
  1.2649      case 0x86:
  1.2650 -      // Wait for CX:DX microseconds. currently using the 
  1.2651 -      // refresh request port 0x61 bit4, toggling every 15usec 
  1.2652 +      // Wait for CX:DX microseconds. currently using the
  1.2653 +      // refresh request port 0x61 bit4, toggling every 15usec
  1.2654  
  1.2655        CX = regs.u.r16.cx;
  1.2656        DX = regs.u.r16.dx;
  1.2657  
  1.2658  ASM_START
  1.2659 +      sti
  1.2660 +
  1.2661        ;; Get the count in eax
  1.2662 -      mov  ax, .int15_function32.CX [bp]
  1.2663 +      mov  bx, sp
  1.2664 +      mov  ax, _int15_function32.CX [bx]
  1.2665        shl  eax, #16
  1.2666 -      mov  ax, .int15_function32.DX [bp]
  1.2667 +      mov  ax, _int15_function32.DX [bx]
  1.2668  
  1.2669        ;; convert to numbers of 15usec ticks
  1.2670        mov ebx, #15
  1.2671 @@ -4531,7 +4667,8 @@ ASM_END
  1.2672      case 0xe8:
  1.2673          switch(regs.u.r8.al)
  1.2674          {
  1.2675 -        case 0x20: {
  1.2676 +#ifdef HVMASSIST
  1.2677 +       case 0x20: {
  1.2678              Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
  1.2679  
  1.2680              if (regs.u.r32.edx != 0x534D4150) /* SMAP */
  1.2681 @@ -4579,7 +4716,7 @@ ASM_END
  1.2682              // Get the amount of extended memory (above 1M)
  1.2683              regs.u.r8.cl = inb_cmos(0x30);
  1.2684              regs.u.r8.ch = inb_cmos(0x31);
  1.2685 -          
  1.2686 +
  1.2687              // limit to 15M
  1.2688              if (regs.u.r16.cx > (15*1024))
  1.2689                  regs.u.r16.cx = 15*1024;
  1.2690 @@ -4607,7 +4744,7 @@ ASM_END
  1.2691              regs.u.r16.bx = regs.u.r16.dx;
  1.2692              break;
  1.2693          }
  1.2694 -	default:  /* AH=0xE8?? but not implemented */
  1.2695 +        default:  /* AH=0xE8?? but not implemented */
  1.2696              goto int15_unimplemented;
  1.2697          }
  1.2698          break;
  1.2699 @@ -4620,17 +4757,179 @@ ASM_END
  1.2700        regs.u.r8.ah = UNSUPPORTED_FUNCTION;
  1.2701        break;
  1.2702      }
  1.2703 +#else
  1.2704 +         case 0x20: // coded by osmaker aka K.J.
  1.2705 +            if(regs.u.r32.edx == 0x534D4150)
  1.2706 +            {
  1.2707 +                extended_memory_size = inb_cmos(0x35);
  1.2708 +                extended_memory_size <<= 8;
  1.2709 +                extended_memory_size |= inb_cmos(0x34);
  1.2710 +                extended_memory_size *= 64;
  1.2711 +                // greater than EFF00000???
  1.2712 +                if(extended_memory_size > 0x3bc000) {
  1.2713 +                    extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000
  1.2714 +                }
  1.2715 +                extended_memory_size *= 1024;
  1.2716 +                extended_memory_size += (16L * 1024 * 1024);
  1.2717 +
  1.2718 +                if(extended_memory_size <= (16L * 1024 * 1024)) {
  1.2719 +                    extended_memory_size = inb_cmos(0x31);
  1.2720 +                    extended_memory_size <<= 8;
  1.2721 +                    extended_memory_size |= inb_cmos(0x30);
  1.2722 +                    extended_memory_size *= 1024;
  1.2723 +                    extended_memory_size += (1L * 1024 * 1024);
  1.2724 +                }
  1.2725 +
  1.2726 +                switch(regs.u.r16.bx)
  1.2727 +                {
  1.2728 +                    case 0:
  1.2729 +                        set_e820_range(ES, regs.u.r16.di,
  1.2730 +                                       0x0000000L, 0x0009f000L, 1);
  1.2731 +                        regs.u.r32.ebx = 1;
  1.2732 +                        regs.u.r32.eax = 0x534D4150;
  1.2733 +                        regs.u.r32.ecx = 0x14;
  1.2734 +                        CLEAR_CF();
  1.2735 +                        return;
  1.2736 +                        break;
  1.2737 +                    case 1:
  1.2738 +                        set_e820_range(ES, regs.u.r16.di,
  1.2739 +                                       0x0009f000L, 0x000a0000L, 2);
  1.2740 +                        regs.u.r32.ebx = 2;
  1.2741 +                        regs.u.r32.eax = 0x534D4150;
  1.2742 +                        regs.u.r32.ecx = 0x14;
  1.2743 +                        CLEAR_CF();
  1.2744 +                        return;
  1.2745 +                        break;
  1.2746 +                    case 2:
  1.2747 +                        set_e820_range(ES, regs.u.r16.di,
  1.2748 +                                       0x000e8000L, 0x00100000L, 2);
  1.2749 +                        regs.u.r32.ebx = 3;
  1.2750 +                        regs.u.r32.eax = 0x534D4150;
  1.2751 +                        regs.u.r32.ecx = 0x14;
  1.2752 +                        CLEAR_CF();
  1.2753 +                        return;
  1.2754 +                        break;
  1.2755 +                    case 3:
  1.2756 +#if BX_ROMBIOS32
  1.2757 +                        set_e820_range(ES, regs.u.r16.di,
  1.2758 +                                       0x00100000L,
  1.2759 +                                       extended_memory_size - ACPI_DATA_SIZE, 1);
  1.2760 +                        regs.u.r32.ebx = 4;
  1.2761 +#else
  1.2762 +                        set_e820_range(ES, regs.u.r16.di,
  1.2763 +                                       0x00100000L,
  1.2764 +                                       extended_memory_size, 1);
  1.2765 +                        regs.u.r32.ebx = 5;
  1.2766 +#endif
  1.2767 +                        regs.u.r32.eax = 0x534D4150;
  1.2768 +                        regs.u.r32.ecx = 0x14;
  1.2769 +                        CLEAR_CF();
  1.2770 +                        return;
  1.2771 +                        break;
  1.2772 +                    case 4:
  1.2773 +                        set_e820_range(ES, regs.u.r16.di,
  1.2774 +                                       extended_memory_size - ACPI_DATA_SIZE,
  1.2775 +                                       extended_memory_size, 3); // ACPI RAM
  1.2776 +                        regs.u.r32.ebx = 5;
  1.2777 +                        regs.u.r32.eax = 0x534D4150;
  1.2778 +                        regs.u.r32.ecx = 0x14;
  1.2779 +                        CLEAR_CF();
  1.2780 +                        return;
  1.2781 +                        break;
  1.2782 +                    case 5:
  1.2783 +                        /* 256KB BIOS area at the end of 4 GB */
  1.2784 +                        set_e820_range(ES, regs.u.r16.di,
  1.2785 +                                       0xfffc0000L, 0x00000000L, 2);
  1.2786 +                        regs.u.r32.ebx = 0;
  1.2787 +                        regs.u.r32.eax = 0x534D4150;
  1.2788 +                        regs.u.r32.ecx = 0x14;
  1.2789 +                        CLEAR_CF();
  1.2790 +                        return;
  1.2791 +                    default:  /* AX=E820, DX=534D4150, BX unrecognized */
  1.2792 +                        goto int15_unimplemented;
  1.2793 +                        break;
  1.2794 +                }
  1.2795 +            } else {
  1.2796 +              // if DX != 0x534D4150)
  1.2797 +              goto int15_unimplemented;
  1.2798 +            }
  1.2799 +            break;
  1.2800 +
  1.2801 +        case 0x01:
  1.2802 +          // do we have any reason to fail here ?
  1.2803 +          CLEAR_CF();
  1.2804 +
  1.2805 +          // my real system sets ax and bx to 0
  1.2806 +          // this is confirmed by Ralph Brown list
  1.2807 +          // but syslinux v1.48 is known to behave
  1.2808 +          // strangely if ax is set to 0
  1.2809 +          // regs.u.r16.ax = 0;
  1.2810 +          // regs.u.r16.bx = 0;
  1.2811 +
  1.2812 +          // Get the amount of extended memory (above 1M)
  1.2813 +          regs.u.r8.cl = inb_cmos(0x30);
  1.2814 +          regs.u.r8.ch = inb_cmos(0x31);
  1.2815 +
  1.2816 +          // limit to 15M
  1.2817 +          if(regs.u.r16.cx > 0x3c00)
  1.2818 +          {
  1.2819 +            regs.u.r16.cx = 0x3c00;
  1.2820 +          }
  1.2821 +
  1.2822 +          // Get the amount of extended memory above 16M in 64k blocs
  1.2823 +          regs.u.r8.dl = inb_cmos(0x34);
  1.2824 +          regs.u.r8.dh = inb_cmos(0x35);
  1.2825 +
  1.2826 +          // Set configured memory equal to extended memory
  1.2827 +          regs.u.r16.ax = regs.u.r16.cx;
  1.2828 +          regs.u.r16.bx = regs.u.r16.dx;
  1.2829 +          break;
  1.2830 +        default:  /* AH=0xE8?? but not implemented */
  1.2831 +          goto int15_unimplemented;
  1.2832 +       }
  1.2833 +       break;
  1.2834 +    int15_unimplemented:
  1.2835 +       // fall into the default
  1.2836 +    default:
  1.2837 +      BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n",
  1.2838 +        (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx);
  1.2839 +      SET_CF();
  1.2840 +      regs.u.r8.ah = UNSUPPORTED_FUNCTION;
  1.2841 +      break;
  1.2842 +    }
  1.2843 +#endif /* HVMASSIST */
  1.2844  }
  1.2845  
  1.2846    void
  1.2847  int16_function(DI, SI, BP, SP, BX, DX, CX, AX, FLAGS)
  1.2848    Bit16u DI, SI, BP, SP, BX, DX, CX, AX, FLAGS;
  1.2849  {
  1.2850 -  Bit8u scan_code, ascii_code, shift_flags, count;
  1.2851 +  Bit8u scan_code, ascii_code, shift_flags, led_flags, count;
  1.2852    Bit16u kbd_code, max;
  1.2853  
  1.2854    BX_DEBUG_INT16("int16: AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX);
  1.2855  
  1.2856 +  shift_flags = read_byte(0x0040, 0x17);
  1.2857 +  led_flags = read_byte(0x0040, 0x97);
  1.2858 +  if ((((shift_flags >> 4) & 0x07) ^ (led_flags & 0x07)) != 0) {
  1.2859 +ASM_START
  1.2860 +    cli
  1.2861 +ASM_END
  1.2862 +    outb(0x60, 0xed);
  1.2863 +    while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21);
  1.2864 +    if ((inb(0x60) == 0xfa)) {
  1.2865 +      led_flags &= 0xf8;
  1.2866 +      led_flags |= ((shift_flags >> 4) & 0x07);
  1.2867 +      outb(0x60, led_flags & 0x07);
  1.2868 +      while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21);
  1.2869 +      inb(0x60);
  1.2870 +      write_byte(0x0040, 0x97, led_flags);
  1.2871 +    }
  1.2872 +ASM_START
  1.2873 +    sti
  1.2874 +ASM_END
  1.2875 +  }
  1.2876 +
  1.2877    switch (GET_AH()) {
  1.2878      case 0x00: /* read keyboard input */
  1.2879  
  1.2880 @@ -4668,7 +4967,7 @@ int16_function(DI, SI, BP, SP, BX, DX, C
  1.2881        break;
  1.2882  
  1.2883      case 0x09: /* GET KEYBOARD FUNCTIONALITY */
  1.2884 -      // bit Bochs Description     
  1.2885 +      // bit Bochs Description
  1.2886        //  7    0   reserved
  1.2887        //  6    0   INT 16/AH=20h-22h supported (122-key keyboard support)
  1.2888        //  5    1   INT 16/AH=10h-12h supported (enhanced keyboard support)
  1.2889 @@ -4698,7 +4997,7 @@ int16_function(DI, SI, BP, SP, BX, DX, C
  1.2890                kbd_code |= (inb(0x60) << 8);
  1.2891              }
  1.2892            } while (--count>0);
  1.2893 -	}
  1.2894 +        }
  1.2895        }
  1.2896        BX=kbd_code;
  1.2897        break;
  1.2898 @@ -4725,7 +5024,8 @@ int16_function(DI, SI, BP, SP, BX, DX, C
  1.2899      case 0x12: /* get extended keyboard status */
  1.2900        shift_flags = read_byte(0x0040, 0x17);
  1.2901        SET_AL(shift_flags);
  1.2902 -      shift_flags = read_byte(0x0040, 0x18);
  1.2903 +      shift_flags = read_byte(0x0040, 0x18) & 0x73;
  1.2904 +      shift_flags |= read_byte(0x0040, 0x96) & 0x0c;
  1.2905        SET_AH(shift_flags);
  1.2906        BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX);
  1.2907        break;
  1.2908 @@ -4740,7 +5040,7 @@ int16_function(DI, SI, BP, SP, BX, DX, C
  1.2909  
  1.2910      case 0x6F:
  1.2911        if (GET_AL() == 0x08)
  1.2912 -	SET_AH(0x02); // unsupported, aka normal keyboard
  1.2913 +        SET_AH(0x02); // unsupported, aka normal keyboard
  1.2914  
  1.2915      default:
  1.2916        BX_INFO("KBD: unsupported int 16h function %02x\n", GET_AH());
  1.2917 @@ -4881,7 +5181,7 @@ int09_function(DI, SI, BP, SP, BX, DX, C
  1.2918    Bit16u DI, SI, BP, SP, BX, DX, CX, AX;
  1.2919  {
  1.2920    Bit8u scancode, asciicode, shift_flags;
  1.2921 -  Bit8u mf2_flags, mf2_state, led_flags;
  1.2922 +  Bit8u mf2_flags, mf2_state;
  1.2923  
  1.2924    //
  1.2925    // DS has been set to F000 before call
  1.2926 @@ -4899,7 +5199,6 @@ int09_function(DI, SI, BP, SP, BX, DX, C
  1.2927    shift_flags = read_byte(0x0040, 0x17);
  1.2928    mf2_flags = read_byte(0x0040, 0x18);
  1.2929    mf2_state = read_byte(0x0040, 0x96);
  1.2930 -  led_flags = read_byte(0x0040, 0x97);
  1.2931    asciicode = 0;
  1.2932  
  1.2933    switch (scancode) {
  1.2934 @@ -4908,8 +5207,6 @@ int09_function(DI, SI, BP, SP, BX, DX, C
  1.2935        write_byte(0x0040, 0x17, shift_flags);
  1.2936        mf2_flags |= 0x40;
  1.2937        write_byte(0x0040, 0x18, mf2_flags);
  1.2938 -      led_flags ^= 0x04;
  1.2939 -      write_byte(0x0040, 0x97, led_flags);
  1.2940        break;
  1.2941      case 0xba: /* Caps Lock release */
  1.2942        mf2_flags &= ~0x40;
  1.2943 @@ -4917,11 +5214,8 @@ int09_function(DI, SI, BP, SP, BX, DX, C
  1.2944        break;
  1.2945  
  1.2946      case 0x2a: /* L Shift press */
  1.2947 -      /*shift_flags &= ~0x40;*/
  1.2948        shift_flags |= 0x02;
  1.2949        write_byte(0x0040, 0x17, shift_flags);
  1.2950 -      led_flags &= ~0x04;
  1.2951 -      write_byte(0x0040, 0x97, led_flags);
  1.2952        break;
  1.2953      case 0xaa: /* L Shift release */
  1.2954        shift_flags &= ~0x02;
  1.2955 @@ -4929,11 +5223,8 @@ int09_function(DI, SI, BP, SP, BX, DX, C
  1.2956        break;
  1.2957  
  1.2958      case 0x36: /* R Shift press */
  1.2959 -      /*shift_flags &= ~0x40;*/
  1.2960        shift_flags |= 0x01;
  1.2961        write_byte(0x0040, 0x17, shift_flags);
  1.2962 -      led_flags &= ~0x04;
  1.2963 -      write_byte(0x0040, 0x97, led_flags);
  1.2964        break;
  1.2965      case 0xb6: /* R Shift release */
  1.2966        shift_flags &= ~0x01;
  1.2967 @@ -4941,71 +5232,75 @@ int09_function(DI, SI, BP, SP, BX, DX, C
  1.2968        break;
  1.2969  
  1.2970      case 0x1d: /* Ctrl press */
  1.2971 -      shift_flags |= 0x04;
  1.2972 -      write_byte(0x0040, 0x17, shift_flags);
  1.2973 -      if (mf2_state & 0x01) {
  1.2974 -        mf2_flags |= 0x04;
  1.2975 -      } else {
  1.2976 -        mf2_flags |= 0x01;
  1.2977 -        }
  1.2978 -      write_byte(0x0040, 0x18, mf2_flags);
  1.2979 +      if ((mf2_state & 0x01) == 0) {
  1.2980 +        shift_flags |= 0x04;
  1.2981 +        write_byte(0x0040, 0x17, shift_flags);
  1.2982 +        if (mf2_state & 0x02) {
  1.2983 +          mf2_state |= 0x04;
  1.2984 +          write_byte(0x0040, 0x96, mf2_state);
  1.2985 +        } else {
  1.2986 +          mf2_flags |= 0x01;
  1.2987 +          write_byte(0x0040, 0x18, mf2_flags);
  1.2988 +        }
  1.2989 +      }
  1.2990        break;
  1.2991      case 0x9d: /* Ctrl release */
  1.2992 -      shift_flags &= ~0x04;
  1.2993 -      write_byte(0x0040, 0x17, shift_flags);
  1.2994 -      if (mf2_state & 0x01) {
  1.2995 -        mf2_flags &= ~0x04;
  1.2996 -      } else {
  1.2997 -        mf2_flags &= ~0x01;
  1.2998 -        }
  1.2999 -      write_byte(0x0040, 0x18, mf2_flags);
  1.3000 +      if ((mf2_state & 0x01) == 0) {
  1.3001 +        shift_flags &= ~0x04;
  1.3002 +        write_byte(0x0040, 0x17, shift_flags);
  1.3003 +        if (mf2_state & 0x02) {
  1.3004 +          mf2_state &= ~0x04;
  1.3005 +          write_byte(0x0040, 0x96, mf2_state);
  1.3006 +        } else {
  1.3007 +          mf2_flags &= ~0x01;
  1.3008 +          write_byte(0x0040, 0x18, mf2_flags);
  1.3009 +        }
  1.3010 +      }
  1.3011        break;
  1.3012  
  1.3013      case 0x38: /* Alt press */
  1.3014        shift_flags |= 0x08;
  1.3015        write_byte(0x0040, 0x17, shift_flags);
  1.3016 -      if (mf2_state & 0x01) {
  1.3017 -        mf2_flags |= 0x08;
  1.3018 +      if (mf2_state & 0x02) {
  1.3019 +        mf2_state |= 0x08;
  1.3020 +        write_byte(0x0040, 0x96, mf2_state);
  1.3021        } else {
  1.3022          mf2_flags |= 0x02;
  1.3023 -        }
  1.3024 -      write_byte(0x0040, 0x18, mf2_flags);
  1.3025 +        write_byte(0x0040, 0x18, mf2_flags);
  1.3026 +      }
  1.3027        break;
  1.3028      case 0xb8: /* Alt release */
  1.3029        shift_flags &= ~0x08;
  1.3030        write_byte(0x0040, 0x17, shift_flags);
  1.3031 -      if (mf2_state & 0x01) {
  1.3032 -        mf2_flags &= ~0x08;
  1.3033 +      if (mf2_state & 0x02) {
  1.3034 +        mf2_state &= ~0x08;
  1.3035 +        write_byte(0x0040, 0x96, mf2_state);
  1.3036        } else {
  1.3037          mf2_flags &= ~0x02;
  1.3038 -        }
  1.3039 -      write_byte(0x0040, 0x18, mf2_flags);
  1.3040 +        write_byte(0x0040, 0x18, mf2_flags);
  1.3041 +      }
  1.3042        break;
  1.3043  
  1.3044      case 0x45: /* Num Lock press */
  1.3045 -      if ((mf2_state & 0x01) == 0) {
  1.3046 +      if ((mf2_state & 0x03) == 0) {
  1.3047          mf2_flags |= 0x20;
  1.3048          write_byte(0x0040, 0x18, mf2_flags);
  1.3049          shift_flags ^= 0x20;
  1.3050 -        led_flags ^= 0x02;
  1.3051          write_byte(0x0040, 0x17, shift_flags);
  1.3052 -        write_byte(0x0040, 0x97, led_flags);
  1.3053 -        }
  1.3054 +      }
  1.3055        break;
  1.3056      case 0xc5: /* Num Lock release */
  1.3057 -      if ((mf2_state & 0x01) == 0) {
  1.3058 +      if ((mf2_state & 0x03) == 0) {
  1.3059          mf2_flags &= ~0x20;
  1.3060          write_byte(0x0040, 0x18, mf2_flags);
  1.3061 -        }
  1.3062 +      }
  1.3063        break;
  1.3064  
  1.3065      case 0x46: /* Scroll Lock press */
  1.3066        mf2_flags |= 0x10;
  1.3067        write_byte(0x0040, 0x18, mf2_flags);
  1.3068        shift_flags ^= 0x10;
  1.3069 -      led_flags ^= 0x01;
  1.3070        write_byte(0x0040, 0x17, shift_flags);
  1.3071 -      write_byte(0x0040, 0x97, led_flags);
  1.3072        break;
  1.3073  
  1.3074      case 0xc6: /* Scroll Lock release */
  1.3075 @@ -5018,50 +5313,55 @@ int09_function(DI, SI, BP, SP, BX, DX, C
  1.3076              machine_reset();
  1.3077          /* Fall through */
  1.3078      default:
  1.3079 -      if (scancode & 0x80) return; /* toss key releases ... */
  1.3080 +      if (scancode & 0x80) {
  1.3081 +        break; /* toss key releases ... */
  1.3082 +      }
  1.3083        if (scancode > MAX_SCAN_CODE) {
  1.3084 -        BX_INFO("KBD: int09h_handler(): unknown scancode (%x) read!\n", scancode);
  1.3085 +        BX_INFO("KBD: int09h_handler(): unknown scancode read: 0x%02x!\n", scancode);
  1.3086          return;
  1.3087 -        }
  1.3088 +      }
  1.3089        if (shift_flags & 0x08) { /* ALT */
  1.3090          asciicode = scan_to_scanascii[scancode].alt;
  1.3091          scancode = scan_to_scanascii[scancode].alt >> 8;
  1.3092 -        }
  1.3093 -      else if (shift_flags & 0x04) { /* CONTROL */
  1.3094 +      } else if (shift_flags & 0x04) { /* CONTROL */
  1.3095          asciicode = scan_to_scanascii[scancode].control;
  1.3096          scancode = scan_to_scanascii[scancode].control >> 8;
  1.3097 -        }
  1.3098 -      else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */
  1.3099 -        /* check if lock state should be ignored 
  1.3100 +      } else if (((mf2_state & 0x02) > 0) && ((scancode >= 0x47) && (scancode <= 0x53))) {
  1.3101 +        /* extended keys handling */
  1.3102 +        asciicode = 0xe0;
  1.3103 +        scancode = scan_to_scanascii[scancode].normal >> 8;
  1.3104 +      } else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */
  1.3105 +        /* check if lock state should be ignored
  1.3106           * because a SHIFT key are pressed */
  1.3107 -         
  1.3108 +
  1.3109          if (shift_flags & scan_to_scanascii[scancode].lock_flags) {
  1.3110            asciicode = scan_to_scanascii[scancode].normal;
  1.3111            scancode = scan_to_scanascii[scancode].normal >> 8;
  1.3112 -          }
  1.3113 -        else {
  1.3114 +        } else {
  1.3115            asciicode = scan_to_scanascii[scancode].shift;
  1.3116            scancode = scan_to_scanascii[scancode].shift >> 8;
  1.3117 -          }
  1.3118 -        }
  1.3119 -      else {
  1.3120 +        }
  1.3121 +      } else {
  1.3122          /* check if lock is on */
  1.3123          if (shift_flags & scan_to_scanascii[scancode].lock_flags) {
  1.3124            asciicode = scan_to_scanascii[scancode].shift;
  1.3125            scancode = scan_to_scanascii[scancode].shift >> 8;
  1.3126 -          }
  1.3127 -        else {
  1.3128 +        } else {
  1.3129            asciicode = scan_to_scanascii[scancode].normal;
  1.3130            scancode = scan_to_scanascii[scancode].normal >> 8;
  1.3131 -          }
  1.3132 -        }
  1.3133 +        }
  1.3134 +      }
  1.3135        if (scancode==0 && asciicode==0) {
  1.3136          BX_INFO("KBD: int09h_handler(): scancode & asciicode are zero?\n");
  1.3137 -        }
  1.3138 +      }
  1.3139        enqueue_key(scancode, asciicode);
  1.3140        break;
  1.3141 -    }
  1.3142 -  mf2_state &= ~0x01;
  1.3143 +  }
  1.3144 +  if ((scancode & 0x7f) != 0x1d) {
  1.3145 +    mf2_state &= ~0x01;
  1.3146 +  }
  1.3147 +  mf2_state &= ~0x02;
  1.3148 +  write_byte(0x0040, 0x96, mf2_state);
  1.3149  }
  1.3150  
  1.3151    unsigned int
  1.3152 @@ -5070,9 +5370,6 @@ enqueue_key(scan_code, ascii_code)
  1.3153  {
  1.3154    Bit16u buffer_start, buffer_end, buffer_head, buffer_tail, temp_tail;
  1.3155  
  1.3156 -  //BX_INFO("KBD:   enqueue_key() called scan:%02x, ascii:%02x\n",
  1.3157 -  //    scan_code, ascii_code);
  1.3158 -
  1.3159  #if BX_CPU < 2
  1.3160    buffer_start = 0x001E;
  1.3161    buffer_end   = 0x003E;
  1.3162 @@ -5122,9 +5419,8 @@ BX_DEBUG_INT74("int74: read byte %02x\n"
  1.3163    mouse_flags_2 = read_byte(ebda_seg, 0x0027);
  1.3164  
  1.3165    if ( (mouse_flags_2 & 0x80) != 0x80 ) {
  1.3166 -      //    BX_PANIC("int74_function:\n");
  1.3167        return;
  1.3168 -    }
  1.3169 +  }
  1.3170  
  1.3171    package_count = mouse_flags_2 & 0x07;
  1.3172    index = mouse_flags_1 & 0x07;
  1.3173 @@ -5152,10 +5448,10 @@ BX_DEBUG_INT74("int74_function: make_far
  1.3174  #if BX_USE_ATADRV
  1.3175  
  1.3176    void
  1.3177 -int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
  1.3178 -  Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
  1.3179 -{
  1.3180 -  Bit32u lba;
  1.3181 +int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
  1.3182 +  Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
  1.3183 +{
  1.3184 +  Bit32u lba_low, lba_high;
  1.3185    Bit16u ebda_seg=read_word(0x0040,0x000E);
  1.3186    Bit16u cylinder, head, sector;
  1.3187    Bit16u segment, offset;
  1.3188 @@ -5176,12 +5472,12 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3189    // Get the ata channel
  1.3190    device=read_byte(ebda_seg,&EbdaData->ata.hdidmap[GET_ELDL()-0x80]);
  1.3191  
  1.3192 -  // basic check : device has to be valid 
  1.3193 +  // basic check : device has to be valid
  1.3194    if (device >= BX_MAX_ATA_DEVICES) {
  1.3195      BX_INFO("int13_harddisk: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL());
  1.3196      goto int13_fail;
  1.3197      }
  1.3198 -  
  1.3199 +
  1.3200    switch (GET_AH()) {
  1.3201  
  1.3202      case 0x00: /* disk controller reset */
  1.3203 @@ -5199,7 +5495,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3204        break;
  1.3205  
  1.3206      case 0x02: // read disk sectors
  1.3207 -    case 0x03: // write disk sectors 
  1.3208 +    case 0x03: // write disk sectors
  1.3209      case 0x04: // verify disk sectors
  1.3210  
  1.3211        count       = GET_AL();
  1.3212 @@ -5211,10 +5507,10 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3213        segment = ES;
  1.3214        offset  = BX;
  1.3215  
  1.3216 -      if ( (count > 128) || (count == 0) ) {
  1.3217 -        BX_INFO("int13_harddisk: function %02x, count out of range!\n",GET_AH());
  1.3218 +      if ((count > 128) || (count == 0) || (sector == 0)) {
  1.3219 +        BX_INFO("int13_harddisk: function %02x, parameter out of range!\n",GET_AH());
  1.3220          goto int13_fail;
  1.3221 -        }
  1.3222 +      }
  1.3223  
  1.3224        nlc   = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders);
  1.3225        nlh   = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
  1.3226 @@ -5225,7 +5521,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3227          BX_INFO("int13_harddisk: function %02x, parameters out of range %04x/%04x/%04x!\n", GET_AH(), cylinder, head, sector);
  1.3228          goto int13_fail;
  1.3229          }
  1.3230 -      
  1.3231 +
  1.3232        // FIXME verify
  1.3233        if ( GET_AH() == 0x04 ) goto int13_success;
  1.3234  
  1.3235 @@ -5234,14 +5530,15 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3236  
  1.3237        // if needed, translate lchs to lba, and execute command
  1.3238        if ( (nph != nlh) || (npspt != nlspt)) {
  1.3239 -        lba = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1;
  1.3240 +        lba_low = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1;
  1.3241 +        lba_high = 0;
  1.3242          sector = 0; // this forces the command to be lba
  1.3243          }
  1.3244  
  1.3245        if ( GET_AH() == 0x02 )
  1.3246 -        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba, segment, offset);
  1.3247 +        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset);
  1.3248        else
  1.3249 -        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba, segment, offset);
  1.3250 +        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset);
  1.3251  
  1.3252        // Set nb of sector transferred
  1.3253        SET_AL(read_word(ebda_seg, &EbdaData->ata.trsfsectors));
  1.3254 @@ -5262,7 +5559,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3255        break;
  1.3256  
  1.3257      case 0x08: /* read disk drive parameters */
  1.3258 -      
  1.3259 +
  1.3260        // Get logical geometry from table
  1.3261        nlc   = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders);
  1.3262        nlh   = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
  1.3263 @@ -5277,13 +5574,13 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3264        SET_DL(count); /* FIXME returns 0, 1, or n hard drives */
  1.3265  
  1.3266        // FIXME should set ES & DI
  1.3267 -      
  1.3268 +
  1.3269        goto int13_success;
  1.3270        break;
  1.3271  
  1.3272      case 0x10: /* check drive ready */
  1.3273        // should look at 40:8E also???
  1.3274 -      
  1.3275 +
  1.3276        // Read the status from controller
  1.3277        status = inb(read_word(ebda_seg, &EbdaData->ata.channels[device/2].iobase1) + ATA_CB_STAT);
  1.3278        if ( (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY ) {
  1.3279 @@ -5297,15 +5594,15 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3280  
  1.3281      case 0x15: /* read disk drive size */
  1.3282  
  1.3283 -      // Get physical geometry from table
  1.3284 -      npc   = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.cylinders);
  1.3285 -      nph   = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads);
  1.3286 -      npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt);
  1.3287 +      // Get logical geometry from table
  1.3288 +      nlc   = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.cylinders);
  1.3289 +      nlh   = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
  1.3290 +      nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt);
  1.3291  
  1.3292        // Compute sector count seen by int13
  1.3293 -      lba = (Bit32u)(npc - 1) * (Bit32u)nph * (Bit32u)npspt;
  1.3294 -      CX = lba >> 16;
  1.3295 -      DX = lba & 0xffff;
  1.3296 +      lba_low = (Bit32u)(nlc - 1) * (Bit32u)nlh * (Bit32u)nlspt;
  1.3297 +      CX = lba_low >> 16;
  1.3298 +      DX = lba_low & 0xffff;
  1.3299  
  1.3300        SET_AH(3);  // hard disk accessible
  1.3301        goto int13_success_noah;
  1.3302 @@ -5326,17 +5623,18 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3303        count=read_word(DS, SI+(Bit16u)&Int13Ext->count);
  1.3304        segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
  1.3305        offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
  1.3306 - 
  1.3307 -      // Can't use 64 bits lba
  1.3308 -      lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
  1.3309 -      if (lba != 0L) {
  1.3310 -        BX_PANIC("int13_harddisk: function %02x. Can't use 64bits lba\n",GET_AH());
  1.3311 +
  1.3312 +      // Get 32 msb lba and check
  1.3313 +      lba_high=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
  1.3314 +      if (lba_high > read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high) ) {
  1.3315 +        BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
  1.3316          goto int13_fail;
  1.3317          }
  1.3318  
  1.3319 -      // Get 32 bits lba and check
  1.3320 -      lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
  1.3321 -      if (lba >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors) ) {
  1.3322 +      // Get 32 lsb lba and check
  1.3323 +      lba_low=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
  1.3324 +      if (lba_high == read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high)
  1.3325 +          && lba_low >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low) ) {
  1.3326          BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
  1.3327          goto int13_fail;
  1.3328          }
  1.3329 @@ -5344,12 +5642,12 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3330        // If verify or seek
  1.3331        if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
  1.3332          goto int13_success;
  1.3333 -      
  1.3334 +
  1.3335        // Execute the command
  1.3336        if ( GET_AH() == 0x42 )
  1.3337 -        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba, segment, offset);
  1.3338 +        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset);
  1.3339        else
  1.3340 -        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba, segment, offset);
  1.3341 +        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset);
  1.3342  
  1.3343        count=read_word(ebda_seg, &EbdaData->ata.trsfsectors);
  1.3344        write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
  1.3345 @@ -5367,7 +5665,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3346      case 0x49: // IBM/MS extended media change
  1.3347        goto int13_success;    // Always success for HD
  1.3348        break;
  1.3349 -      
  1.3350 +
  1.3351      case 0x46: // IBM/MS eject media
  1.3352        SET_AH(0xb2);          // Volume Not Removable
  1.3353        goto int13_fail_noah;  // Always fail for HD
  1.3354 @@ -5377,7 +5675,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3355        size=read_word(DS,SI+(Bit16u)&Int13DPT->size);
  1.3356  
  1.3357        // Buffer is too small
  1.3358 -      if(size < 0x1a) 
  1.3359 +      if(size < 0x1a)
  1.3360          goto int13_fail;
  1.3361  
  1.3362        // EDD 1.x
  1.3363 @@ -5387,17 +5685,26 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3364          npc     = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.cylinders);
  1.3365          nph     = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads);
  1.3366          npspt   = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt);
  1.3367 -        lba     = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors);
  1.3368 +        lba_low = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low);
  1.3369 +        lba_high = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high);
  1.3370          blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize);
  1.3371  
  1.3372          write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
  1.3373 -        write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is valid
  1.3374 -        write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc);
  1.3375 +        if (lba_high || (lba_low/npspt)/nph > 0x3fff)
  1.3376 +        {
  1.3377 +          write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x00); // geometry is invalid
  1.3378 +          write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0x3fff);
  1.3379 +        }
  1.3380 +        else
  1.3381 +        {
  1.3382 +          write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is valid
  1.3383 +          write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc);
  1.3384 +        }
  1.3385          write_dword(DS, SI+(Bit16u)&Int13DPT->heads, (Bit32u)nph);
  1.3386          write_dword(DS, SI+(Bit16u)&Int13DPT->spt, (Bit32u)npspt);
  1.3387 -        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba);  // FIXME should be Bit64
  1.3388 -        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0L);  
  1.3389 -        write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);  
  1.3390 +        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba_low);
  1.3391 +        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, lba_high);
  1.3392 +        write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
  1.3393          }
  1.3394  
  1.3395        // EDD 2.x
  1.3396 @@ -5407,8 +5714,8 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3397  
  1.3398          write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e);
  1.3399  
  1.3400 -        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);  
  1.3401 -        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte);  
  1.3402 +        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);
  1.3403 +        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte);
  1.3404  
  1.3405          // Fill in dpte
  1.3406          channel = device / 2;
  1.3407 @@ -5418,14 +5725,14 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3408          mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
  1.3409          translation = read_byte(ebda_seg, &EbdaData->ata.devices[device].translation);
  1.3410  
  1.3411 -        options  = (translation==ATA_TRANSLATION_NONE?0:1<<3); // chs translation
  1.3412 +        options  = (translation==ATA_TRANSLATION_NONE?0:1)<<3; // chs translation
  1.3413          options |= (1<<4); // lba translation
  1.3414 -        options |= (mode==ATA_MODE_PIO32?1:0<<7);
  1.3415 -        options |= (translation==ATA_TRANSLATION_LBA?1:0<<9); 
  1.3416 -        options |= (translation==ATA_TRANSLATION_RECHS?3:0<<9); 
  1.3417 +        options |= (mode==ATA_MODE_PIO32?1:0)<<7;
  1.3418 +        options |= (translation==ATA_TRANSLATION_LBA?1:0)<<9;
  1.3419 +        options |= (translation==ATA_TRANSLATION_RECHS?3:0)<<9;
  1.3420  
  1.3421          write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1);
  1.3422 -        write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2);
  1.3423 +        write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC);
  1.3424          write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 );
  1.3425          write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
  1.3426          write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
  1.3427 @@ -5434,10 +5741,13 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3428          write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 );
  1.3429          write_word(ebda_seg, &EbdaData->ata.dpte.options, options);
  1.3430          write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0);
  1.3431 -        write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
  1.3432 - 
  1.3433 +        if (size >=0x42)
  1.3434 +          write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
  1.3435 +        else
  1.3436 +          write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x10);
  1.3437 +
  1.3438          checksum=0;
  1.3439 -        for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, (&EbdaData->ata.dpte) + i);
  1.3440 +        for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, ((Bit8u*)(&EbdaData->ata.dpte)) + i);
  1.3441          checksum = ~checksum;
  1.3442          write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
  1.3443          }
  1.3444 @@ -5463,7 +5773,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3445            write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
  1.3446            write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
  1.3447            }
  1.3448 -        else { 
  1.3449 +        else {
  1.3450            // FIXME PCI
  1.3451            }
  1.3452          write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
  1.3453 @@ -5476,7 +5786,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3454            write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
  1.3455            write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
  1.3456            }
  1.3457 -        else { 
  1.3458 +        else {
  1.3459            // FIXME PCI
  1.3460            }
  1.3461          write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
  1.3462 @@ -5512,7 +5822,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3463      case 0x0d: /* alternate disk reset */
  1.3464      case 0x11: /* recalibrate */
  1.3465      case 0x14: /* controller internal diagnostic */
  1.3466 -      BX_INFO("int13h_harddisk function %02xh unimplemented, returns success\n", GET_AH());
  1.3467 +      BX_INFO("int13_harddisk: function %02xh unimplemented, returns success\n", GET_AH());
  1.3468        goto int13_success;
  1.3469        break;
  1.3470  
  1.3471 @@ -5521,7 +5831,7 @@ int13_harddisk(DS, ES, DI, SI, BP, ELDX,
  1.3472      case 0x18: // set media type for format
  1.3473      case 0x50: // IBM/MS send packet command
  1.3474      default:
  1.3475 -      BX_INFO("int13_harddisk function %02xh unsupported, returns fail\n", GET_AH());
  1.3476 +      BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", GET_AH());
  1.3477        goto int13_fail;
  1.3478        break;
  1.3479      }
  1.3480 @@ -5557,8 +5867,7 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL
  1.3481    Bit16u count, segment, offset, i, size;
  1.3482  
  1.3483    BX_DEBUG_INT13_CD("int13_cdrom: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
  1.3484 -  // BX_DEBUG_INT13_CD("int13_cdrom: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), DS, ES, DI, SI);
  1.3485 -  
  1.3486 +
  1.3487    SET_DISK_RET_STATUS(0x00);
  1.3488  
  1.3489    /* basic check : device should be 0xE0+ */
  1.3490 @@ -5575,16 +5884,16 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL
  1.3491      BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL());
  1.3492      goto int13_fail;
  1.3493      }
  1.3494 -  
  1.3495 +
  1.3496    switch (GET_AH()) {
  1.3497  
  1.3498      // all those functions return SUCCESS
  1.3499      case 0x00: /* disk controller reset */
  1.3500      case 0x09: /* initialize drive parameters */
  1.3501      case 0x0c: /* seek to specified cylinder */
  1.3502 -    case 0x0d: /* alternate disk reset */  
  1.3503 -    case 0x10: /* check drive ready */    
  1.3504 -    case 0x11: /* recalibrate */      
  1.3505 +    case 0x0d: /* alternate disk reset */
  1.3506 +    case 0x10: /* check drive ready */
  1.3507 +    case 0x11: /* recalibrate */
  1.3508      case 0x14: /* controller internal diagnostic */
  1.3509      case 0x16: /* detect disk change */
  1.3510        goto int13_success;
  1.3511 @@ -5606,7 +5915,7 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL
  1.3512        /* set CF if error status read */
  1.3513        if (status) goto int13_fail_nostatus;
  1.3514        else        goto int13_success_noah;
  1.3515 -      break;      
  1.3516 +      break;
  1.3517  
  1.3518      case 0x15: /* read disk drive size */
  1.3519        SET_AH(0x02);
  1.3520 @@ -5623,11 +5932,11 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL
  1.3521      case 0x42: // IBM/MS extended read
  1.3522      case 0x44: // IBM/MS verify sectors
  1.3523      case 0x47: // IBM/MS extended seek
  1.3524 -       
  1.3525 +
  1.3526        count=read_word(DS, SI+(Bit16u)&Int13Ext->count);
  1.3527        segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
  1.3528        offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
  1.3529 - 
  1.3530 +
  1.3531        // Can't use 64 bits lba
  1.3532        lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
  1.3533        if (lba != 0L) {
  1.3534 @@ -5635,13 +5944,13 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL
  1.3535          goto int13_fail;
  1.3536          }
  1.3537  
  1.3538 -      // Get 32 bits lba 
  1.3539 +      // Get 32 bits lba
  1.3540        lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
  1.3541  
  1.3542        // If verify or seek
  1.3543        if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
  1.3544          goto int13_success;
  1.3545 -      
  1.3546 +
  1.3547        memsetb(get_SS(),atacmd,0,12);
  1.3548        atacmd[0]=0x28;                      // READ command
  1.3549        atacmd[7]=(count & 0xff00) >> 8;     // Sectors
  1.3550 @@ -5650,7 +5959,7 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL
  1.3551        atacmd[3]=(lba & 0x00ff0000) >> 16;
  1.3552        atacmd[4]=(lba & 0x0000ff00) >> 8;
  1.3553        atacmd[5]=(lba & 0x000000ff);
  1.3554 -      status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L, ATA_DATA_IN, segment,offset); 
  1.3555 +      status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L, ATA_DATA_IN, segment,offset);
  1.3556  
  1.3557        count = (Bit16u)(read_dword(ebda_seg, &EbdaData->ata.trsfbytes) >> 11);
  1.3558        write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
  1.3559 @@ -5697,21 +6006,21 @@ int13_cdrom(EHBX, DS, ES, DI, SI, BP, EL
  1.3560  
  1.3561      case 0x46: // IBM/MS eject media
  1.3562        locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
  1.3563 -      
  1.3564 +
  1.3565        if (locks != 0) {
  1.3566          SET_AH(0xb1); // media locked
  1.3567          goto int13_fail_noah;
  1.3568          }
  1.3569        // FIXME should handle 0x31 no media in device
  1.3570        // FIXME should handle 0xb5 valid request failed
  1.3571 -    
  1.3572 +
  1.3573        // Call removable media eject
  1.3574        ASM_START
  1.3575          push bp
  1.3576          mov  bp, sp
  1.3577  
  1.3578          mov ah, #0x52
  1.3579 -        int 15
  1.3580 +        int #0x15
  1.3581          mov _int13_cdrom.status + 2[bp], ah
  1.3582          jnc int13_cdrom_rme_end
  1.3583          mov _int13_cdrom.status, #1
  1.3584 @@ -5731,7 +6040,7 @@ int13_cdrom_rme_end:
  1.3585        size = read_word(DS,SI+(Bit16u)&Int13Ext->size);
  1.3586  
  1.3587        // Buffer is too small
  1.3588 -      if(size < 0x1a) 
  1.3589 +      if(size < 0x1a)
  1.3590          goto int13_fail;
  1.3591  
  1.3592        // EDD 1.x
  1.3593 @@ -5746,8 +6055,8 @@ int13_cdrom_rme_end:
  1.3594          write_dword(DS, SI+(Bit16u)&Int13DPT->heads, 0xffffffff);
  1.3595          write_dword(DS, SI+(Bit16u)&Int13DPT->spt, 0xffffffff);
  1.3596          write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, 0xffffffff);  // FIXME should be Bit64
  1.3597 -        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff);  
  1.3598 -        write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);  
  1.3599 +        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff);
  1.3600 +        write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
  1.3601          }
  1.3602  
  1.3603        // EDD 2.x
  1.3604 @@ -5757,8 +6066,8 @@ int13_cdrom_rme_end:
  1.3605  
  1.3606          write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e);
  1.3607  
  1.3608 -        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);  
  1.3609 -        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte);  
  1.3610 +        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);
  1.3611 +        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte);
  1.3612  
  1.3613          // Fill in dpte
  1.3614          channel = device / 2;
  1.3615 @@ -5774,7 +6083,7 @@ int13_cdrom_rme_end:
  1.3616          options |= (mode==ATA_MODE_PIO32?1:0<<7);
  1.3617  
  1.3618          write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1);
  1.3619 -        write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2);
  1.3620 +        write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC);
  1.3621          write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 );
  1.3622          write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
  1.3623          write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
  1.3624 @@ -5786,7 +6095,7 @@ int13_cdrom_rme_end:
  1.3625          write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
  1.3626  
  1.3627          checksum=0;
  1.3628 -        for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, (&EbdaData->ata.dpte) + i);
  1.3629 +        for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, ((Bit8u*)(&EbdaData->ata.dpte)) + i);
  1.3630          checksum = ~checksum;
  1.3631          write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
  1.3632          }
  1.3633 @@ -5812,7 +6121,7 @@ int13_cdrom_rme_end:
  1.3634            write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
  1.3635            write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
  1.3636            }
  1.3637 -        else { 
  1.3638 +        else {
  1.3639            // FIXME PCI
  1.3640            }
  1.3641          write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
  1.3642 @@ -5825,7 +6134,7 @@ int13_cdrom_rme_end:
  1.3643            write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
  1.3644            write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
  1.3645            }
  1.3646 -        else { 
  1.3647 +        else {
  1.3648            // FIXME PCI
  1.3649            }
  1.3650          write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
  1.3651 @@ -5847,7 +6156,7 @@ int13_cdrom_rme_end:
  1.3652        SET_AH(06);
  1.3653        goto int13_fail_nostatus;
  1.3654        break;
  1.3655 -      
  1.3656 +
  1.3657      case 0x4e: // // IBM/MS set hardware configuration
  1.3658        // DMA, prefetch, PIO maximum not supported
  1.3659        switch (GET_AL()) {
  1.3660 @@ -5909,7 +6218,7 @@ int13_eltorito(DS, ES, DI, SI, BP, SP, B
  1.3661  
  1.3662    BX_DEBUG_INT13_ET("int13_eltorito: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
  1.3663    // BX_DEBUG_INT13_ET("int13_eltorito: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), DS, ES, DI, SI);
  1.3664 -  
  1.3665 +
  1.3666    switch (GET_AH()) {
  1.3667  
  1.3668      // FIXME ElTorito Various. Should be implemented
  1.3669 @@ -5984,11 +6293,10 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, 
  1.3670    Bit8u  atacmd[12];
  1.3671  
  1.3672    BX_DEBUG_INT13_ET("int13_cdemu: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
  1.3673 -  //BX_DEBUG_INT13_ET("int13_cdemu: SS=%04x ES=%04x DI=%04x SI=%04x\n", get_SS(), ES, DI, SI);
  1.3674 -  
  1.3675 +
  1.3676    /* at this point, we are emulating a floppy/harddisk */
  1.3677 -  
  1.3678 -  // Recompute the device number 
  1.3679 +
  1.3680 +  // Recompute the device number
  1.3681    device  = read_byte(ebda_seg,&EbdaData->cdemu.controller_index) * 2;
  1.3682    device += read_byte(ebda_seg,&EbdaData->cdemu.device_spec);
  1.3683  
  1.3684 @@ -6001,7 +6309,6 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, 
  1.3685      goto int13_fail;
  1.3686      }
  1.3687  
  1.3688 -  
  1.3689    switch (GET_AH()) {
  1.3690  
  1.3691      // all those functions return SUCCESS
  1.3692 @@ -6010,7 +6317,7 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, 
  1.3693      case 0x0c: /* seek to specified cylinder */
  1.3694      case 0x0d: /* alternate disk reset */  // FIXME ElTorito Various. should really reset ?
  1.3695      case 0x10: /* check drive ready */     // FIXME ElTorito Various. should check if ready ?
  1.3696 -    case 0x11: /* recalibrate */      
  1.3697 +    case 0x11: /* recalibrate */
  1.3698      case 0x14: /* controller internal diagnostic */
  1.3699      case 0x16: /* detect disk change */
  1.3700        goto int13_success;
  1.3701 @@ -6035,9 +6342,9 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, 
  1.3702  
  1.3703      case 0x02: // read disk sectors
  1.3704      case 0x04: // verify disk sectors
  1.3705 -      vspt       = read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt); 
  1.3706 -      vcylinders = read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders); 
  1.3707 -      vheads     = read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads); 
  1.3708 +      vspt       = read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt);
  1.3709 +      vcylinders = read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders);
  1.3710 +      vheads     = read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads);
  1.3711  
  1.3712        ilba       = read_dword(ebda_seg,&EbdaData->cdemu.ilba);
  1.3713  
  1.3714 @@ -6066,17 +6373,17 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, 
  1.3715  
  1.3716        // calculate the virtual lba inside the image
  1.3717        vlba=((((Bit32u)cylinder*(Bit32u)vheads)+(Bit32u)head)*(Bit32u)vspt)+((Bit32u)(sector-1));
  1.3718 - 
  1.3719 +
  1.3720        // In advance so we don't loose the count
  1.3721        SET_AL(nbsectors);
  1.3722  
  1.3723        // start lba on cd
  1.3724 -      slba  = (Bit32u)vlba/4; 
  1.3725 +      slba  = (Bit32u)vlba/4;
  1.3726        before= (Bit16u)vlba%4;
  1.3727  
  1.3728        // end lba on cd
  1.3729        elba = (Bit32u)(vlba+nbsectors-1)/4;
  1.3730 -      
  1.3731 +
  1.3732        memsetb(get_SS(),atacmd,0,12);
  1.3733        atacmd[0]=0x28;                      // READ command
  1.3734        atacmd[7]=((Bit16u)(elba-slba+1) & 0xff00) >> 8; // Sectors
  1.3735 @@ -6096,10 +6403,10 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, 
  1.3736        break;
  1.3737  
  1.3738      case 0x08: /* read disk drive parameters */
  1.3739 -      vspt=read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt); 
  1.3740 -      vcylinders=read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders) - 1; 
  1.3741 -      vheads=read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads) - 1; 
  1.3742 - 
  1.3743 +      vspt=read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt);
  1.3744 +      vcylinders=read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders) - 1;
  1.3745 +      vheads=read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads) - 1;
  1.3746 +
  1.3747        SET_AL( 0x00 );
  1.3748        SET_BL( 0x00 );
  1.3749        SET_CH( vcylinders & 0xff );
  1.3750 @@ -6107,7 +6414,7 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, 
  1.3751        SET_DH( vheads );
  1.3752        SET_DL( 0x02 );   // FIXME ElTorito Various. should send the real count of drives 1 or 2
  1.3753                          // FIXME ElTorito Harddisk. should send the HD count
  1.3754 - 
  1.3755 +
  1.3756        switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) {
  1.3757          case 0x01: SET_BL( 0x02 ); break;
  1.3758          case 0x02: SET_BL( 0x04 ); break;
  1.3759 @@ -6143,7 +6450,7 @@ ASM_END
  1.3760      case 0x45: // IBM/MS lock/unlock drive
  1.3761      case 0x46: // IBM/MS eject media
  1.3762      case 0x47: // IBM/MS extended seek
  1.3763 -    case 0x48: // IBM/MS get drive parameters 
  1.3764 +    case 0x48: // IBM/MS get drive parameters
  1.3765      case 0x49: // IBM/MS extended media change
  1.3766      case 0x4e: // ? - set hardware configuration
  1.3767      case 0x50: // ? - send packet command
  1.3768 @@ -6231,8 +6538,8 @@ ASM_END
  1.3769  }
  1.3770  
  1.3771    void
  1.3772 -int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
  1.3773 -  Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
  1.3774 +int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
  1.3775 +  Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
  1.3776  {
  1.3777    Bit8u    drive, num_sectors, sector, head, status, mod;
  1.3778    Bit8u    drive_map;
  1.3779 @@ -6338,7 +6645,7 @@ BX_DEBUG_INT13_HD("int13_f01\n");
  1.3780          }
  1.3781  
  1.3782        if ( (num_sectors > 128) || (num_sectors == 0) )
  1.3783 -        BX_PANIC("int13_harddisk(): num_sectors out of range!\n");
  1.3784 +        BX_PANIC("int13_harddisk: num_sectors out of range!\n");
  1.3785  
  1.3786        if (head > 15)
  1.3787          BX_PANIC("hard drive BIOS:(read/verify) head > 15\n");
  1.3788 @@ -6484,7 +6791,7 @@ BX_DEBUG_INT13_HD("int13_f03\n");
  1.3789          }
  1.3790  
  1.3791        if ( (num_sectors > 128) || (num_sectors == 0) )
  1.3792 -        BX_PANIC("int13_harddisk(): num_sectors out of range!\n");
  1.3793 +        BX_PANIC("int13_harddisk: num_sectors out of range!\n");
  1.3794  
  1.3795        if (head > 15)
  1.3796          BX_PANIC("hard drive BIOS:(read) head > 15\n");
  1.3797 @@ -6594,7 +6901,7 @@ BX_DEBUG_INT13_HD("int13_f05\n");
  1.3798  
  1.3799      case 0x08: /* read disk drive parameters */
  1.3800  BX_DEBUG_INT13_HD("int13_f08\n");
  1.3801 -      
  1.3802 +
  1.3803        drive = GET_ELDL ();
  1.3804        get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
  1.3805  
  1.3806 @@ -6734,10 +7041,10 @@ ASM_END
  1.3807        break;
  1.3808  
  1.3809      case 0x18: // set media type for format
  1.3810 -    case 0x41: // IBM/MS 
  1.3811 -    case 0x42: // IBM/MS 
  1.3812 -    case 0x43: // IBM/MS 
  1.3813 -    case 0x44: // IBM/MS 
  1.3814 +    case 0x41: // IBM/MS
  1.3815 +    case 0x42: // IBM/MS
  1.3816 +    case 0x43: // IBM/MS
  1.3817 +    case 0x44: // IBM/MS
  1.3818      case 0x45: // IBM/MS lock/unlock drive
  1.3819      case 0x46: // IBM/MS eject media
  1.3820      case 0x47: // IBM/MS extended seek
  1.3821 @@ -6782,7 +7089,7 @@ get_hd_geometry(drive, hd_cylinders, hd_
  1.3822      hd_type = inb_cmos(0x12) & 0x0f;
  1.3823      if (hd_type != 0x0f)
  1.3824        BX_INFO(panic_msg_reg12h,1);
  1.3825 -    hd_type = inb_cmos(0x1a); // HD0: extended type
  1.3826 +    hd_type = inb_cmos(0x1a); // HD1: extended type
  1.3827      if (hd_type != 47)
  1.3828        BX_INFO(panic_msg_reg19h,0,0x1a);
  1.3829      iobase = 0x24;
  1.3830 @@ -6801,11 +7108,72 @@ get_hd_geometry(drive, hd_cylinders, hd_
  1.3831  
  1.3832  #endif //else BX_USE_ATADRV
  1.3833  
  1.3834 +#if BX_SUPPORT_FLOPPY
  1.3835  
  1.3836  //////////////////////
  1.3837  // FLOPPY functions //
  1.3838  //////////////////////
  1.3839  
  1.3840 +void floppy_reset_controller()
  1.3841 +{
  1.3842 +  Bit8u val8;
  1.3843 +
  1.3844 +  // Reset controller
  1.3845 +  val8 = inb(0x03f2);
  1.3846 +  outb(0x03f2, val8 & ~0x04);
  1.3847 +  outb(0x03f2, val8 | 0x04);
  1.3848 +
  1.3849 +  // Wait for controller to come out of reset
  1.3850 +  do {
  1.3851 +    val8 = inb(0x3f4);
  1.3852 +  } while ( (val8 & 0xc0) != 0x80 );
  1.3853 +}
  1.3854 +
  1.3855 +void floppy_prepare_controller(drive)
  1.3856 +  Bit16u drive;
  1.3857 +{
  1.3858 +  Bit8u  val8, dor, prev_reset;
  1.3859 +
  1.3860 +  // set 40:3e bit 7 to 0
  1.3861 +  val8 = read_byte(0x0040, 0x003e);
  1.3862 +  val8 &= 0x7f;
  1.3863 +  write_byte(0x0040, 0x003e, val8);
  1.3864 +
  1.3865 +  // turn on motor of selected drive, DMA & int enabled, normal operation
  1.3866 +  prev_reset = inb(0x03f2) & 0x04;
  1.3867 +  if (drive)
  1.3868 +    dor = 0x20;
  1.3869 +  else
  1.3870 +    dor = 0x10;
  1.3871 +  dor |= 0x0c;
  1.3872 +  dor |= drive;
  1.3873 +  outb(0x03f2, dor);
  1.3874 +
  1.3875 +  // reset the disk motor timeout value of INT 08
  1.3876 +  write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
  1.3877 +
  1.3878 +  // wait for drive readiness
  1.3879 +  do {
  1.3880 +    val8 = inb(0x3f4);
  1.3881 +  } while ( (val8 & 0xc0) != 0x80 );
  1.3882 +
  1.3883 +  if (prev_reset == 0) {
  1.3884 +    // turn on interrupts
  1.3885 +ASM_START
  1.3886 +    sti
  1.3887 +ASM_END
  1.3888 +    // wait on 40:3e bit 7 to become 1
  1.3889 +    do {
  1.3890 +      val8 = read_byte(0x0040, 0x003e);
  1.3891 +    } while ( (val8 & 0x80) == 0 );
  1.3892 +    val8 &= 0x7f;
  1.3893 +ASM_START
  1.3894 +    cli
  1.3895 +ASM_END
  1.3896 +    write_byte(0x0040, 0x003e, val8);
  1.3897 +  }
  1.3898 +}
  1.3899 +
  1.3900    bx_bool
  1.3901  floppy_media_known(drive)
  1.3902    Bit16u drive;
  1.3903 @@ -6912,7 +7280,7 @@ floppy_media_sense(drive)
  1.3904      retval = 1;
  1.3905      }
  1.3906    //
  1.3907 -  // Extended floppy size uses special cmos setting 
  1.3908 +  // Extended floppy size uses special cmos setting
  1.3909    else if ( drive_type == 6 ) {
  1.3910      // 160k 5.25" drive
  1.3911      config_data = 0x00; // 0000 0000
  1.3912 @@ -6953,63 +7321,41 @@ floppy_media_sense(drive)
  1.3913  floppy_drive_recal(drive)
  1.3914    Bit16u drive;
  1.3915  {
  1.3916 -  Bit8u  val8, dor;
  1.3917 +  Bit8u  val8;
  1.3918    Bit16u curr_cyl_offset;
  1.3919  
  1.3920 -  // set 40:3e bit 7 to 0
  1.3921 -  val8 = read_byte(0x0000, 0x043e);
  1.3922 -  val8 &= 0x7f;
  1.3923 -  write_byte(0x0000, 0x043e, val8);
  1.3924 -
  1.3925 -  // turn on motor of selected drive, DMA & int enabled, normal operation
  1.3926 -  if (drive)
  1.3927 -    dor = 0x20;
  1.3928 -  else
  1.3929 -    dor = 0x10;
  1.3930 -  dor |= 0x0c;
  1.3931 -  dor |= drive;
  1.3932 -  outb(0x03f2, dor);
  1.3933 -
  1.3934 -  // reset the disk motor timeout value of INT 08
  1.3935 -  write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
  1.3936 -
  1.3937 -  // check port 3f4 for drive readiness
  1.3938 -  val8 = inb(0x3f4);
  1.3939 -  if ( (val8 & 0xf0) != 0x80 )
  1.3940 -    BX_PANIC("floppy recal:f07: ctrl not ready\n");
  1.3941 +  floppy_prepare_controller(drive);
  1.3942  
  1.3943    // send Recalibrate command (2 bytes) to controller
  1.3944    outb(0x03f5, 0x07);  // 07: Recalibrate
  1.3945    outb(0x03f5, drive); // 0=drive0, 1=drive1
  1.3946  
  1.3947 - // turn on interrupts
  1.3948 +  // turn on interrupts
  1.3949  ASM_START
  1.3950    sti
  1.3951  ASM_END
  1.3952  
  1.3953    // wait on 40:3e bit 7 to become 1
  1.3954 -  val8 = (read_byte(0x0000, 0x043e) & 0x80);
  1.3955 -  while ( val8 == 0 ) {
  1.3956 -    val8 = (read_byte(0x0000, 0x043e) & 0x80);
  1.3957 -    }
  1.3958 -
  1.3959 - val8 = 0; // separate asm from while() loop
  1.3960 - // turn off interrupts
  1.3961 +  do {
  1.3962 +    val8 = (read_byte(0x0040, 0x003e) & 0x80);
  1.3963 +  } while ( val8 == 0 );
  1.3964 +
  1.3965 +  val8 = 0; // separate asm from while() loop
  1.3966 +  // turn off interrupts
  1.3967  ASM_START
  1.3968    cli
  1.3969  ASM_END
  1.3970  
  1.3971    // set 40:3e bit 7 to 0, and calibrated bit
  1.3972 -  val8 = read_byte(0x0000, 0x043e);
  1.3973 +  val8 = read_byte(0x0040, 0x003e);
  1.3974    val8 &= 0x7f;
  1.3975    if (drive) {
  1.3976      val8 |= 0x02; // Drive 1 calibrated
  1.3977      curr_cyl_offset = 0x0095;
  1.3978 -    }
  1.3979 -  else {
  1.3980 +  } else {
  1.3981      val8 |= 0x01; // Drive 0 calibrated
  1.3982      curr_cyl_offset = 0x0094;
  1.3983 -    }
  1.3984 +  }
  1.3985    write_byte(0x0040, 0x003e, val8);
  1.3986    write_byte(0x0040, curr_cyl_offset, 0); // current cylinder is 0
  1.3987  
  1.3988 @@ -7036,7 +7382,6 @@ floppy_drive_exists(drive)
  1.3989      return(1);
  1.3990  }
  1.3991  
  1.3992 -#if BX_SUPPORT_FLOPPY
  1.3993    void
  1.3994  int13_diskette_function(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
  1.3995    Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
  1.3996 @@ -7049,7 +7394,6 @@ int13_diskette_function(DS, ES, DI, SI, 
  1.3997    Bit16u es, last_addr;
  1.3998  
  1.3999    BX_DEBUG_INT13_FL("int13_diskette: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES);
  1.4000 -  // BX_DEBUG_INT13_FL("int13_diskette: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), get_DS(), ES, DI, SI);
  1.4001  
  1.4002    ah = GET_AH();
  1.4003  
  1.4004 @@ -7062,7 +7406,7 @@ BX_DEBUG_INT13_FL("floppy f00\n");
  1.4005          set_diskette_ret_status(1);
  1.4006          SET_CF();
  1.4007          return;
  1.4008 -        }
  1.4009 +      }
  1.4010        drive_type = inb_cmos(0x10);
  1.4011  
  1.4012        if (drive == 0)
  1.4013 @@ -7074,7 +7418,7 @@ BX_DEBUG_INT13_FL("floppy f00\n");
  1.4014          set_diskette_ret_status(0x80);
  1.4015          SET_CF();
  1.4016          return;
  1.4017 -        }
  1.4018 +      }
  1.4019        SET_AH(0);
  1.4020        set_diskette_ret_status(0);
  1.4021        CLEAR_CF(); // successful
  1.4022 @@ -7087,7 +7431,7 @@ BX_DEBUG_INT13_FL("floppy f00\n");
  1.4023        SET_AH(val8);
  1.4024        if (val8) {
  1.4025          SET_CF();
  1.4026 -        }
  1.4027 +      }
  1.4028        return;
  1.4029  
  1.4030      case 0x02: // Read Diskette Sectors
  1.4031 @@ -7099,15 +7443,15 @@ BX_DEBUG_INT13_FL("floppy f00\n");
  1.4032        head        = GET_DH();
  1.4033        drive       = GET_ELDL();
  1.4034  
  1.4035 -      if ( (drive > 1) || (head > 1) ||
  1.4036 -           (num_sectors == 0) || (num_sectors > 72) ) {
  1.4037 -BX_INFO("floppy: drive>1 || head>1 ...\n");
  1.4038 +      if ((drive > 1) || (head > 1) || (sector == 0) ||
  1.4039 +          (num_sectors == 0) || (num_sectors > 72)) {
  1.4040 +        BX_INFO("int13_diskette: read/write/verify: parameter out of range\n");
  1.4041          SET_AH(1);
  1.4042          set_diskette_ret_status(1);
  1.4043          SET_AL(0); // no sectors read
  1.4044          SET_CF(); // error occurred
  1.4045          return;
  1.4046 -        }
  1.4047 +      }
  1.4048  
  1.4049        // see if drive exists
  1.4050        if (floppy_drive_exists(drive) == 0) {
  1.4051 @@ -7116,7 +7460,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4052          SET_AL(0); // no sectors read
  1.4053          SET_CF(); // error occurred
  1.4054          return;
  1.4055 -        }
  1.4056 +      }
  1.4057  
  1.4058        // see if media in drive, and type is known
  1.4059        if (floppy_media_known(drive) == 0) {
  1.4060 @@ -7126,8 +7470,8 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4061            SET_AL(0); // no sectors read
  1.4062            SET_CF(); // error occurred
  1.4063            return;
  1.4064 -          }
  1.4065 -        }
  1.4066 +        }
  1.4067 +      }
  1.4068  
  1.4069        if (ah == 0x02) {
  1.4070          // Read Diskette Sectors
  1.4071 @@ -7146,7 +7490,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4072          if ( base_address < base_es ) {
  1.4073            // in case of carry, adjust page by 1
  1.4074            page++;
  1.4075 -          }
  1.4076 +        }
  1.4077          base_count = (num_sectors * 512) - 1;
  1.4078  
  1.4079          // check for 64K boundary overrun
  1.4080 @@ -7157,7 +7501,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4081            SET_AL(0); // no sectors read
  1.4082            SET_CF(); // error occurred
  1.4083            return;
  1.4084 -          }
  1.4085 +        }
  1.4086  
  1.4087          BX_DEBUG_INT13_FL("masking DMA-1 c2\n");
  1.4088          outb(0x000a, 0x06);
  1.4089 @@ -7190,28 +7534,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4090          //--------------------------------------
  1.4091          // set up floppy controller for transfer
  1.4092          //--------------------------------------
  1.4093 -
  1.4094 -        // set 40:3e bit 7 to 0
  1.4095 -        val8 = read_byte(0x0000, 0x043e);
  1.4096 -        val8 &= 0x7f;
  1.4097 -        write_byte(0x0000, 0x043e, val8);
  1.4098 -
  1.4099 -        // turn on motor of selected drive, DMA & int enabled, normal operation
  1.4100 -        if (drive)
  1.4101 -          dor = 0x20;
  1.4102 -        else
  1.4103 -          dor = 0x10;
  1.4104 -        dor |= 0x0c;
  1.4105 -        dor |= drive;
  1.4106 -        outb(0x03f2, dor);
  1.4107 -
  1.4108 -        // reset the disk motor timeout value of INT 08
  1.4109 -        write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
  1.4110 -
  1.4111 -        // check port 3f4 for drive readiness
  1.4112 -        val8 = inb(0x3f4);
  1.4113 -        if ( (val8 & 0xf0) != 0x80 )
  1.4114 -          BX_PANIC("int13_diskette:f02: ctrl not ready\n");
  1.4115 +        floppy_prepare_controller(drive);
  1.4116  
  1.4117          // send read-normal-data command (9 bytes) to controller
  1.4118          outb(0x03f5, 0xe6); // e6: read normal data
  1.4119 @@ -7224,27 +7547,35 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4120          outb(0x03f5, 0); // Gap length
  1.4121          outb(0x03f5, 0xff); // Gap length
  1.4122  
  1.4123 -       // turn on interrupts
  1.4124 +        // turn on interrupts
  1.4125    ASM_START
  1.4126          sti
  1.4127    ASM_END
  1.4128  
  1.4129          // wait on 40:3e bit 7 to become 1
  1.4130 -        val8 = (read_byte(0x0000, 0x043e) & 0x80);
  1.4131 -        while ( val8 == 0 ) {
  1.4132 -          val8 = (read_byte(0x0000, 0x043e) & 0x80);
  1.4133 +        do {
  1.4134 +          val8 = read_byte(0x0040, 0x0040);
  1.4135 +          if (val8 == 0) {
  1.4136 +            floppy_reset_controller();
  1.4137 +            SET_AH(0x80); // drive not ready (timeout)
  1.4138 +            set_diskette_ret_status(0x80);
  1.4139 +            SET_AL(0); // no sectors read
  1.4140 +            SET_CF(); // error occurred
  1.4141 +            return;
  1.4142            }
  1.4143 -
  1.4144 -       val8 = 0; // separate asm from while() loop
  1.4145 -       // turn off interrupts
  1.4146 +          val8 = (read_byte(0x0040, 0x003e) & 0x80);
  1.4147 +        } while ( val8 == 0 );
  1.4148 +
  1.4149 +        val8 = 0; // separate asm from while() loop
  1.4150 +        // turn off interrupts
  1.4151    ASM_START
  1.4152          cli
  1.4153    ASM_END
  1.4154  
  1.4155          // set 40:3e bit 7 to 0
  1.4156 -        val8 = read_byte(0x0000, 0x043e);
  1.4157 +        val8 = read_byte(0x0040, 0x003e);
  1.4158          val8 &= 0x7f;
  1.4159 -        write_byte(0x0000, 0x043e, val8);
  1.4160 +        write_byte(0x0040, 0x003e, val8);
  1.4161  
  1.4162          // check port 3f4 for accessibility to status bytes
  1.4163          val8 = inb(0x3f4);
  1.4164 @@ -7275,7 +7606,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4165            SET_AL(0); // no sectors read
  1.4166            SET_CF(); // error occurred
  1.4167            return;
  1.4168 -          }
  1.4169 +        }
  1.4170  
  1.4171          // ??? should track be new val from return_status[3] ?
  1.4172          set_diskette_current_cyl(drive, track);
  1.4173 @@ -7283,8 +7614,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4174          SET_AH(0x00); // success
  1.4175          CLEAR_CF();   // success
  1.4176          return;
  1.4177 -        }
  1.4178 -      else if (ah == 0x03) {
  1.4179 +      } else if (ah == 0x03) {
  1.4180          // Write Diskette Sectors
  1.4181  
  1.4182          //-----------------------------------
  1.4183 @@ -7301,7 +7631,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4184          if ( base_address < base_es ) {
  1.4185            // in case of carry, adjust page by 1
  1.4186            page++;
  1.4187 -          }
  1.4188 +        }
  1.4189          base_count = (num_sectors * 512) - 1;
  1.4190  
  1.4191          // check for 64K boundary overrun
  1.4192 @@ -7312,7 +7642,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4193            SET_AL(0); // no sectors read
  1.4194            SET_CF(); // error occurred
  1.4195            return;
  1.4196 -          }
  1.4197 +        }
  1.4198  
  1.4199          BX_DEBUG_INT13_FL("masking DMA-1 c2\n");
  1.4200          outb(0x000a, 0x06);
  1.4201 @@ -7338,30 +7668,9 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4202          //--------------------------------------
  1.4203          // set up floppy controller for transfer
  1.4204          //--------------------------------------
  1.4205 -
  1.4206 -        // set 40:3e bit 7 to 0
  1.4207 -        val8 = read_byte(0x0000, 0x043e);
  1.4208 -        val8 &= 0x7f;
  1.4209 -        write_byte(0x0000, 0x043e, val8);
  1.4210 -
  1.4211 -        // turn on motor of selected drive, DMA & int enabled, normal operation
  1.4212 -        if (drive)
  1.4213 -          dor = 0x20;
  1.4214 -        else
  1.4215 -          dor = 0x10;
  1.4216 -        dor |= 0x0c;
  1.4217 -        dor |= drive;
  1.4218 -        outb(0x03f2, dor);
  1.4219 -
  1.4220 -        // reset the disk motor timeout value of INT 08
  1.4221 -        write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
  1.4222 -
  1.4223 -        // check port 3f4 for drive readiness
  1.4224 -        val8 = inb(0x3f4);
  1.4225 -        if ( (val8 & 0xf0) != 0x80 )
  1.4226 -          BX_PANIC("int13_diskette:f03: ctrl not ready\n");
  1.4227 -
  1.4228 -        // send read-normal-data command (9 bytes) to controller
  1.4229 +        floppy_prepare_controller(drive);
  1.4230 +
  1.4231 +        // send write-normal-data command (9 bytes) to controller
  1.4232          outb(0x03f5, 0xc5); // c5: write normal data
  1.4233          outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
  1.4234          outb(0x03f5, track);
  1.4235 @@ -7372,27 +7681,35 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4236          outb(0x03f5, 0); // Gap length
  1.4237          outb(0x03f5, 0xff); // Gap length
  1.4238  
  1.4239 -       // turn on interrupts
  1.4240 +        // turn on interrupts
  1.4241    ASM_START
  1.4242          sti
  1.4243    ASM_END
  1.4244  
  1.4245          // wait on 40:3e bit 7 to become 1
  1.4246 -        val8 = (read_byte(0x0000, 0x043e) & 0x80);
  1.4247 -        while ( val8 == 0 ) {
  1.4248 -          val8 = (read_byte(0x0000, 0x043e) & 0x80);
  1.4249 +        do {
  1.4250 +          val8 = read_byte(0x0040, 0x0040);
  1.4251 +          if (val8 == 0) {
  1.4252 +            floppy_reset_controller();
  1.4253 +            SET_AH(0x80); // drive not ready (timeout)
  1.4254 +            set_diskette_ret_status(0x80);
  1.4255 +            SET_AL(0); // no sectors written
  1.4256 +            SET_CF(); // error occurred
  1.4257 +            return;
  1.4258            }
  1.4259 -
  1.4260 -       val8 = 0; // separate asm from while() loop
  1.4261 -       // turn off interrupts
  1.4262 +          val8 = (read_byte(0x0040, 0x003e) & 0x80);
  1.4263 +        } while ( val8 == 0 );
  1.4264 +
  1.4265 +        val8 = 0; // separate asm from while() loop
  1.4266 +        // turn off interrupts
  1.4267    ASM_START
  1.4268          cli
  1.4269    ASM_END
  1.4270  
  1.4271          // set 40:3e bit 7 to 0
  1.4272 -        val8 = read_byte(0x0000, 0x043e);
  1.4273 +        val8 = read_byte(0x0040, 0x003e);
  1.4274          val8 &= 0x7f;
  1.4275 -        write_byte(0x0000, 0x043e, val8);
  1.4276 +        write_byte(0x0040, 0x003e, val8);
  1.4277  
  1.4278          // check port 3f4 for accessibility to status bytes
  1.4279          val8 = inb(0x3f4);
  1.4280 @@ -7436,8 +7753,7 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4281          SET_AH(0x00); // success
  1.4282          CLEAR_CF();   // success
  1.4283          return;
  1.4284 -        }
  1.4285 -      else {  // if (ah == 0x04)
  1.4286 +      } else {  // if (ah == 0x04)
  1.4287          // Verify Diskette Sectors
  1.4288  
  1.4289          // ??? should track be new val from return_status[3] ?
  1.4290 @@ -7446,8 +7762,8 @@ BX_INFO("floppy: drive>1 || head>1 ...\n
  1.4291          CLEAR_CF();   // success
  1.4292          SET_AH(0x00); // success
  1.4293          return;
  1.4294 -        }
  1.4295 -
  1.4296 +      }
  1.4297 +      break;
  1.4298  
  1.4299      case 0x05: // format diskette track
  1.4300  BX_DEBUG_INT13_FL("floppy f05\n");
  1.4301 @@ -7462,7 +7778,7 @@ BX_DEBUG_INT13_FL("floppy f05\n");
  1.4302          SET_AH(1);
  1.4303          set_diskette_ret_status(1);
  1.4304          SET_CF(); // error occurred
  1.4305 -        }
  1.4306 +      }
  1.4307  
  1.4308        // see if drive exists
  1.4309        if (floppy_drive_exists(drive) == 0) {
  1.4310 @@ -7470,7 +7786,7 @@ BX_DEBUG_INT13_FL("floppy f05\n");
  1.4311          set_diskette_ret_status(0x80);
  1.4312          SET_CF(); // error occurred
  1.4313          return;
  1.4314 -        }
  1.4315 +      }
  1.4316  
  1.4317        // see if media in drive, and type is known
  1.4318        if (floppy_media_known(drive) == 0) {
  1.4319 @@ -7480,8 +7796,8 @@ BX_DEBUG_INT13_FL("floppy f05\n");
  1.4320            SET_AL(0); // no sectors read
  1.4321            SET_CF(); // error occurred
  1.4322            return;
  1.4323 -          }
  1.4324 -        }
  1.4325 +        }
  1.4326 +      }
  1.4327  
  1.4328        // set up DMA controller for transfer
  1.4329        page = (ES >> 12);   // upper 4 bits
  1.4330 @@ -7491,7 +7807,7 @@ BX_DEBUG_INT13_FL("floppy f05\n");
  1.4331        if ( base_address < base_es ) {
  1.4332          // in case of carry, adjust page by 1
  1.4333          page++;
  1.4334 -        }
  1.4335 +      }
  1.4336        base_count = (num_sectors * 4) - 1;
  1.4337  
  1.4338        // check for 64K boundary overrun
  1.4339 @@ -7502,7 +7818,7 @@ BX_DEBUG_INT13_FL("floppy f05\n");
  1.4340          SET_AL(0); // no sectors read
  1.4341          SET_CF(); // error occurred
  1.4342          return;
  1.4343 -        }
  1.4344 +      }
  1.4345  
  1.4346        outb(0x000a, 0x06);
  1.4347        outb(0x000c, 0x00); // clear flip-flop
  1.4348 @@ -7519,27 +7835,9 @@ BX_DEBUG_INT13_FL("floppy f05\n");
  1.4349        outb(0x000a, 0x02);
  1.4350  
  1.4351        // set up floppy controller for transfer
  1.4352 -      val8 = read_byte(0x0000, 0x043e);
  1.4353 -      val8 &= 0x7f;
  1.4354 -      write_byte(0x0000, 0x043e, val8);
  1.4355 -      // turn on motor of selected drive, DMA & int enabled, normal operation
  1.4356 -      if (drive)
  1.4357 -        dor = 0x20;
  1.4358 -      else
  1.4359 -        dor = 0x10;
  1.4360 -      dor |= 0x0c;
  1.4361 -      dor |= drive;
  1.4362 -      outb(0x03f2, dor);
  1.4363 -
  1.4364 -      // reset the disk motor timeout value of INT 08
  1.4365 -      write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
  1.4366 -
  1.4367 -      // check port 3f4 for drive readiness
  1.4368 -      val8 = inb(0x3f4);
  1.4369 -      if ( (val8 & 0xf0) != 0x80 )
  1.4370 -        BX_PANIC("int13_diskette:f05: ctrl not ready\n");
  1.4371 -
  1.4372 -      // send read-normal-data command (6 bytes) to controller
  1.4373 +      floppy_prepare_controller(drive);
  1.4374 +
  1.4375 +      // send format-track command (6 bytes) to controller
  1.4376        outb(0x03f5, 0x4d); // 4d: format track
  1.4377        outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
  1.4378        outb(0x03f5, 2); // 512 byte sector size
  1.4379 @@ -7550,20 +7848,29 @@ BX_DEBUG_INT13_FL("floppy f05\n");
  1.4380    ASM_START
  1.4381        sti
  1.4382    ASM_END
  1.4383 +
  1.4384        // wait on 40:3e bit 7 to become 1
  1.4385 -      val8 = (read_byte(0x0000, 0x043e) & 0x80);
  1.4386 -      while ( val8 == 0 ) {
  1.4387 -        val8 = (read_byte(0x0000, 0x043e) & 0x80);
  1.4388 -        }
  1.4389 -     val8 = 0; // separate asm from while() loop
  1.4390 -     // turn off interrupts
  1.4391 +      do {
  1.4392 +        val8 = read_byte(0x0040, 0x0040);
  1.4393 +        if (val8 == 0) {
  1.4394 +          floppy_reset_controller();
  1.4395 +          SET_AH(0x80); // drive not ready (timeout)
  1.4396 +          set_diskette_ret_status(0x80);
  1.4397 +          SET_CF(); // error occurred
  1.4398 +          return;
  1.4399 +        }
  1.4400 +        val8 = (read_byte(0x0040, 0x003e) & 0x80);
  1.4401 +      } while ( val8 == 0 );
  1.4402 +
  1.4403 +      val8 = 0; // separate asm from while() loop
  1.4404 +      // turn off interrupts
  1.4405    ASM_START
  1.4406        cli
  1.4407    ASM_END
  1.4408        // set 40:3e bit 7 to 0
  1.4409 -      val8 = read_byte(0x0000, 0x043e);
  1.4410 +      val8 = read_byte(0x0040, 0x003e);
  1.4411        val8 &= 0x7f;
  1.4412 -      write_byte(0x0000, 0x043e, val8);
  1.4413 +      write_byte(0x0040, 0x003e, val8);
  1.4414        // check port 3f4 for accessibility to status bytes
  1.4415        val8 = inb(0x3f4);
  1.4416        if ( (val8 & 0xc0) != 0xc0 )
  1.4417 @@ -7915,8 +8222,9 @@ Bit16u seq_nr;
  1.4418    Bit16u bootseg;
  1.4419    Bit16u bootip;
  1.4420    Bit16u status;
  1.4421 -
  1.4422 -  struct ipl_entry e;
  1.4423 +  Bit16u bootfirst;
  1.4424 +
  1.4425 +  ipl_entry_t e;
  1.4426  
  1.4427    // if BX_ELTORITO_BOOT is not defined, old behavior
  1.4428    //   check bit 5 in CMOS reg 0x2d.  load either 0x00 or 0x80 into DL
  1.4429 @@ -7930,7 +8238,7 @@ Bit16u seq_nr;
  1.4430    //     CMOS reg 0x38 & 0xf0 : 3rd boot device
  1.4431    //   boot device codes:
  1.4432    //     0x00 : not defined
  1.4433 -  //     0x01 : first floppy 
  1.4434 +  //     0x01 : first floppy
  1.4435    //     0x02 : first harddrive
  1.4436    //     0x03 : first cdrom
  1.4437    //     0x04 - 0x0f : PnP expansion ROMs (e.g. Etherboot)
  1.4438 @@ -7942,16 +8250,25 @@ Bit16u seq_nr;
  1.4439    bootdev |= ((inb_cmos(0x38) & 0xf0) << 4);
  1.4440    bootdev >>= 4 * seq_nr;
  1.4441    bootdev &= 0xf;
  1.4442 -  if (bootdev == 0) BX_PANIC("No bootable device.\n");
  1.4443 -  
  1.4444 +
  1.4445 +  /* Read user selected device */
  1.4446 +  bootfirst = read_word(ebda_seg, IPL_BOOTFIRST_OFFSET);
  1.4447 +  if (bootfirst != 0xFFFF) {
  1.4448 +    bootdev = bootfirst;
  1.4449 +    /* User selected device not set */
  1.4450 +    write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, 0xFFFF);
  1.4451 +    /* Reset boot sequence */
  1.4452 +    write_word(ebda_seg, IPL_SEQUENCE_OFFSET, 0xFFFF);
  1.4453 +  } else if (bootdev == 0) BX_PANIC("No bootable device.\n");
  1.4454 +
  1.4455    /* Translate from CMOS runes to an IPL table offset by subtracting 1 */
  1.4456    bootdev -= 1;
  1.4457 -#else  
  1.4458 +#else
  1.4459    if (seq_nr ==2) BX_PANIC("No more boot devices.");
  1.4460 -  if (!!(inb_cmos(0x2d) & 0x20) ^ (seq_nr == 1)) 
  1.4461 +  if (!!(inb_cmos(0x2d) & 0x20) ^ (seq_nr == 1))
  1.4462        /* Boot from floppy if the bit is set or it's the second boot */
  1.4463      bootdev = 0x00;
  1.4464 -  else 
  1.4465 +  else
  1.4466      bootdev = 0x01;
  1.4467  #endif
  1.4468  
  1.4469 @@ -7963,13 +8280,13 @@ Bit16u seq_nr;
  1.4470  
  1.4471    /* Do the loading, and set up vector as a far pointer to the boot
  1.4472     * address, and bootdrv as the boot drive */
  1.4473 -  print_boot_device(e.type);
  1.4474 +  print_boot_device(&e);
  1.4475  
  1.4476    switch(e.type) {
  1.4477 -  case 0x01: /* FDD */
  1.4478 -  case 0x02: /* HDD */
  1.4479 -
  1.4480 -    bootdrv = (e.type == 0x02) ? 0x80 : 0x00;
  1.4481 +  case IPL_TYPE_FLOPPY: /* FDD */
  1.4482 +  case IPL_TYPE_HARDDISK: /* HDD */
  1.4483 +
  1.4484 +    bootdrv = (e.type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00;
  1.4485      bootseg = 0x07c0;
  1.4486      status = 0;
  1.4487  
  1.4488 @@ -7984,7 +8301,7 @@ ASM_START
  1.4489      mov  dl, _int18_function.bootdrv + 2[bp]
  1.4490      mov  ax, _int18_function.bootseg + 2[bp]
  1.4491      mov  es, ax         ;; segment
  1.4492 -    mov  bx, #0x0000    ;; offset
  1.4493 +    xor  bx, bx         ;; offset
  1.4494      mov  ah, #0x02      ;; function 2, read diskette sector
  1.4495      mov  al, #0x01      ;; read 1 sector
  1.4496      mov  ch, #0x00      ;; track 0
  1.4497 @@ -8002,7 +8319,7 @@ int19_load_done:
  1.4498      pop  ax
  1.4499      pop  bp
  1.4500  ASM_END
  1.4501 -    
  1.4502 +
  1.4503      if (status != 0) {
  1.4504        print_boot_failure(e.type, 1);
  1.4505        return;
  1.4506 @@ -8010,7 +8327,7 @@ ASM_END
  1.4507  
  1.4508      /* Always check the signature on a HDD boot sector; on FDD, only do
  1.4509       * the check if the CMOS doesn't tell us to skip it */
  1.4510 -    if (e.type != 0x00 || !((inb_cmos(0x38) & 0x01))) {
  1.4511 +    if ((e.type != IPL_TYPE_FLOPPY) || !((inb_cmos(0x38) & 0x01))) {
  1.4512        if (read_word(bootseg,0x1fe) != 0xaa55) {
  1.4513          print_boot_failure(e.type, 0);
  1.4514          return;
  1.4515 @@ -8028,7 +8345,7 @@ ASM_END
  1.4516    break;
  1.4517  
  1.4518  #if BX_ELTORITO_BOOT
  1.4519 -  case 0x03: /* CD-ROM */
  1.4520 +  case IPL_TYPE_CDROM: /* CD-ROM */
  1.4521      status = cdrom_boot();
  1.4522  
  1.4523      // If failure
  1.4524 @@ -8047,7 +8364,7 @@ ASM_END
  1.4525      break;
  1.4526  #endif
  1.4527  
  1.4528 -  case 0x80: /* Expansion ROM with a Bootstrap Entry Vector (a far pointer) */
  1.4529 +  case IPL_TYPE_BEV: /* Expansion ROM with a Bootstrap Entry Vector (a far pointer) */
  1.4530      bootseg = e.vector >> 16;
  1.4531      bootip = e.vector & 0xffff;
  1.4532      break;
  1.4533 @@ -8055,16 +8372,20 @@ ASM_END
  1.4534    default: return;
  1.4535    }
  1.4536  
  1.4537 -  
  1.4538 +  /* Debugging info */
  1.4539 +  BX_INFO("Booting from %x:%x\n", bootseg, bootip);
  1.4540 +
  1.4541    /* Jump to the boot vector */
  1.4542  ASM_START
  1.4543      mov  bp, sp
  1.4544 +//    push cs
  1.4545 +//    push #int18_handler
  1.4546      ;; Build an iret stack frame that will take us to the boot vector.
  1.4547      ;; iret pops ip, then cs, then flags, so push them in the opposite order.
  1.4548      pushf
  1.4549 -    mov  ax, _int18_function.bootseg + 0[bp] 
  1.4550 +    mov  ax, _int18_function.bootseg + 0[bp]
  1.4551      push ax
  1.4552 -    mov  ax, _int18_function.bootip + 0[bp] 
  1.4553 +    mov  ax, _int18_function.bootip + 0[bp]
  1.4554      push ax
  1.4555      ;; Set the magic number in ax and the boot drive in dl.
  1.4556      mov  ax, #0xaa55
  1.4557 @@ -8267,7 +8588,11 @@ int1a_function(regs, ds, iret_addr)
  1.4558        } else if (regs.u.r8.bl == 0x83) {
  1.4559          BX_INFO("bad PCI vendor ID %04x\n", regs.u.r16.dx);
  1.4560        } else if (regs.u.r8.bl == 0x86) {
  1.4561 -        BX_INFO("PCI device %04x:%04x not found\n", regs.u.r16.dx, regs.u.r16.cx);
  1.4562 +        if (regs.u.r8.al == 0x02) {
  1.4563 +          BX_INFO("PCI device %04x:%04x not found at index %d\n", regs.u.r16.dx, regs.u.r16.cx, regs.u.r16.si);
  1.4564 +        } else {
  1.4565 +          BX_INFO("no PCI device with class code 0x%02x%04x found at index %d\n", regs.u.r8.cl, regs.u.r16.dx, regs.u.r16.si);
  1.4566 +        }
  1.4567        }
  1.4568        regs.u.r8.ah = regs.u.r8.bl;
  1.4569        SetCF(iret_addr.flags);
  1.4570 @@ -8313,11 +8638,11 @@ ASM_END
  1.4571            // Done waiting.
  1.4572            Bit16u segment, offset;
  1.4573  
  1.4574 -          offset = read_word( 0x40, 0x98 );
  1.4575 -          segment = read_word( 0x40, 0x9A );
  1.4576 +          segment = read_word( 0x40, 0x98 );
  1.4577 +          offset = read_word( 0x40, 0x9A );
  1.4578            write_byte( 0x40, 0xA0, 0 );  // Turn of status byte.
  1.4579            outb_cmos( 0xB, registerB & 0x37 ); // Clear the Periodic Interrupt.
  1.4580 -          write_byte( segment, offset, 0x80 );  // Write to specified flag byte.
  1.4581 +          write_byte(segment, offset, read_byte(segment, offset) | 0x80 );  // Write to specified flag byte.
  1.4582          } else {
  1.4583            // Continue waiting.
  1.4584            time -= 0x3D1;
  1.4585 @@ -8525,13 +8850,18 @@ int13_notcdrom:
  1.4586  #endif
  1.4587  
  1.4588  int13_disk:
  1.4589 +  ;; int13_harddisk modifies high word of EAX
  1.4590 +  shr   eax, #16
  1.4591 +  push  ax
  1.4592    call  _int13_harddisk
  1.4593 +  pop   ax
  1.4594 +  shl   eax, #16
  1.4595  
  1.4596  int13_out:
  1.4597    pop ds
  1.4598    pop es
  1.4599    popa
  1.4600 -  iret 
  1.4601 +  iret
  1.4602  
  1.4603  ;----------
  1.4604  ;- INT18h -
  1.4605 @@ -8544,19 +8874,19 @@ int18_handler: ;; Boot Failure recovery:
  1.4606    xor  ax, ax
  1.4607    mov  ss, ax
  1.4608  
  1.4609 -  ;; Get the boot sequence number out of the IPL memory
  1.4610    ;; The first time we do this it will have been set to -1 so 
  1.4611    ;; we will start from device 0.
  1.4612    mov  ds, ax
  1.4613 -  mov  bx, word ptr [EBDA_SEG_PTR]
  1.4614 +  mov  bx, word ptr [0x40E]       ;; EBDA segment
  1.4615    mov  ds, bx                     ;; Set segment
  1.4616    mov  bx, IPL_SEQUENCE_OFFSET    ;; BX is now the sequence number
  1.4617    inc  bx                         ;; ++
  1.4618    mov  IPL_SEQUENCE_OFFSET, bx    ;; Write it back
  1.4619 -  mov  ds, ax                     ;; and reset the segment to zero. 
  1.4620 +  mov  ds, ax                     ;; and reset the segment to zero.
  1.4621  
  1.4622    ;; Call the C code for the next boot device
  1.4623    push bx
  1.4624 +
  1.4625    call _int18_function
  1.4626  
  1.4627    ;; Boot failed: invoke the boot recovery function...
  1.4628 @@ -8566,6 +8896,7 @@ int18_handler: ;; Boot Failure recovery:
  1.4629  ;- INT19h -
  1.4630  ;----------
  1.4631  int19_relocated: ;; Boot function, relocated
  1.4632 +
  1.4633    ;;
  1.4634    ;; *** Warning: INT 19h resets the whole machine *** 
  1.4635    ;;
  1.4636 @@ -8577,10 +8908,12 @@ int19_relocated: ;; Boot function, reloc
  1.4637    ;; boot sequence will start, which is more or less the required behaviour.
  1.4638    ;; 
  1.4639    ;; Reset SP and SS
  1.4640 +
  1.4641    mov  ax, #0xfffe
  1.4642    mov  sp, ax
  1.4643    xor  ax, ax
  1.4644    mov  ss, ax
  1.4645 +
  1.4646    call _machine_reset
  1.4647  
  1.4648  ;----------
  1.4649 @@ -8594,7 +8927,7 @@ int1c_handler: ;; User Timer Tick
  1.4650  ;- POST: Floppy Drive -
  1.4651  ;----------------------
  1.4652  floppy_drive_post:
  1.4653 -  mov  ax, #0x0000
  1.4654 +  xor  ax, ax
  1.4655    mov  ds, ax
  1.4656  
  1.4657    mov  al, #0x00
  1.4658 @@ -8676,7 +9009,7 @@ hard_drive_post:
  1.4659    mov  dx, #0x03f6
  1.4660    out  dx, al
  1.4661  
  1.4662 -  mov  ax, #0x0000
  1.4663 +  xor  ax, ax
  1.4664    mov  ds, ax
  1.4665    mov  0x0474, al /* hard disk status of last operation */
  1.4666    mov  0x0477, al /* hard disk port offset (XT only ???) */
  1.4667 @@ -8691,8 +9024,8 @@ hard_drive_post:
  1.4668    SET_INT_VECTOR(0x76, #0xF000, #int76_handler)
  1.4669    ;; INT 41h: hard disk 0 configuration pointer
  1.4670    ;; INT 46h: hard disk 1 configuration pointer
  1.4671 -  SET_INT_VECTOR(0x41, word ptr [EBDA_SEG_PTR], #0x003D)
  1.4672 -  SET_INT_VECTOR(0x46, word ptr [EBDA_SEG_PTR], #0x004D)
  1.4673 +  SET_INT_VECTOR(0x41, word ptr [0x40E], #0x003D) /* EBDA:003D */
  1.4674 +  SET_INT_VECTOR(0x46, word ptr [0x40E], #0x004D) /* EBDA:004D */
  1.4675  
  1.4676    ;; move disk geometry data from CMOS to EBDA disk parameter table(s)
  1.4677    mov  al, #0x12
  1.4678 @@ -8723,7 +9056,7 @@ post_d0_type47:
  1.4679  
  1.4680    xor  ax, ax
  1.4681    mov  ds, ax
  1.4682 -  mov  ax, word ptr [EBDA_SEG_PTR]
  1.4683 +  mov  ax, word ptr [0x40E] ;; EBDA segment
  1.4684    mov  ds, ax
  1.4685  
  1.4686    ;;; Filling EBDA table for hard disk 0.
  1.4687 @@ -8869,7 +9202,9 @@ post_d1_type47:
  1.4688    ;; 0x2b    landing zone high        D
  1.4689    ;; 0x2c    sectors/track            E
  1.4690  ;;; Fill EBDA table for hard disk 1.
  1.4691 -  mov  ax, #EBDA_SEG
  1.4692 +  xor  ax, ax
  1.4693 +  mov  ds, ax
  1.4694 +  mov  ax, word ptr [0x40E] ;; EBDA segment
  1.4695    mov  ds, ax
  1.4696    mov  al, #0x28
  1.4697    out  #0x70, al
  1.4698 @@ -8992,7 +9327,7 @@ ebda_post:
  1.4699  #endif
  1.4700    xor ax, ax            ; mov EBDA seg into 40E
  1.4701    mov ds, ax
  1.4702 -  mov word ptr [EBDA_SEG_PTR], #EBDA_SEG
  1.4703 +  mov word ptr [0x40E], #EBDA_SEG
  1.4704    ret;;
  1.4705  
  1.4706  ;--------------------
  1.4707 @@ -9000,13 +9335,42 @@ ebda_post:
  1.4708  ;--------------------
  1.4709  ; relocated here because the primary POST area isnt big enough.
  1.4710  eoi_jmp_post:
  1.4711 -  call eoi_both_pics
  1.4712 -
  1.4713 +  mov   al, #0x20
  1.4714 +  out   #0xA0, al ;; slave  PIC EOI
  1.4715 +  mov   al, #0x20
  1.4716 +  out   #0x20, al ;; master PIC EOI
  1.4717 +
  1.4718 +jmp_post_0x467:
  1.4719    xor ax, ax
  1.4720    mov ds, ax
  1.4721  
  1.4722    jmp far ptr [0x467]
  1.4723  
  1.4724 +iret_post_0x467:
  1.4725 +  xor ax, ax
  1.4726 +  mov ds, ax
  1.4727 +
  1.4728 +  mov sp, [0x467]
  1.4729 +  mov ss, [0x469]
  1.4730 +  iret
  1.4731 +
  1.4732 +retf_post_0x467:
  1.4733 +  xor ax, ax
  1.4734 +  mov ds, ax
  1.4735 +
  1.4736 +  mov sp, [0x467]
  1.4737 +  mov ss, [0x469]
  1.4738 +  retf
  1.4739 +
  1.4740 +s3_post:
  1.4741 +#if BX_ROMBIOS32
  1.4742 +  call rombios32_init
  1.4743 +#endif
  1.4744 +  call _s3_resume
  1.4745 +  mov bl, #0x00
  1.4746 +  and ax, ax
  1.4747 +  jz normal_post
  1.4748 +  call _s3_resume_panic
  1.4749  
  1.4750  ;--------------------
  1.4751  eoi_both_pics:
  1.4752 @@ -9159,16 +9523,22 @@ bios32_structure:
  1.4753  
  1.4754  .align 16
  1.4755  bios32_entry_point:
  1.4756 -  pushf
  1.4757 -  cmp eax, #0x49435024
  1.4758 +  pushfd
  1.4759 +  cmp eax, #0x49435024 ;; "$PCI"
  1.4760    jne unknown_service
  1.4761    mov eax, #0x80000000
  1.4762    mov dx, #0x0cf8
  1.4763    out dx, eax
  1.4764    mov dx, #0x0cfc
  1.4765    in  eax, dx
  1.4766 -  cmp eax, #0x12378086
  1.4767 +#ifdef PCI_FIXED_HOST_BRIDGE
  1.4768 +  cmp eax, #PCI_FIXED_HOST_BRIDGE
  1.4769    jne unknown_service
  1.4770 +#else
  1.4771 +  ;; say ok if a device is present
  1.4772 +  cmp eax, #0xffffffff
  1.4773 +  je unknown_service
  1.4774 +#endif
  1.4775    mov ebx, #0x000f0000
  1.4776    mov ecx, #0
  1.4777    mov edx, #pcibios_protected
  1.4778 @@ -9177,12 +9547,15 @@ bios32_entry_point:
  1.4779  unknown_service:
  1.4780    mov al, #0x80
  1.4781  bios32_end:
  1.4782 -  popf
  1.4783 +#ifdef BX_QEMU
  1.4784 +  and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu
  1.4785 +#endif
  1.4786 +  popfd
  1.4787    retf
  1.4788  
  1.4789  .align 16
  1.4790  pcibios_protected:
  1.4791 -  pushf
  1.4792 +  pushfd
  1.4793    cli
  1.4794    push esi
  1.4795    push edi
  1.4796 @@ -9190,15 +9563,15 @@ pcibios_protected:
  1.4797    jne pci_pro_f02
  1.4798    mov bx, #0x0210
  1.4799    mov cx, #0
  1.4800 -  mov edx, #0x20494350
  1.4801 +  mov edx, #0x20494350 ;; "PCI "
  1.4802    mov al, #0x01
  1.4803    jmp pci_pro_ok
  1.4804  pci_pro_f02: ;; find pci device
  1.4805    cmp al, #0x02
  1.4806 -  jne pci_pro_f08
  1.4807 +  jne pci_pro_f03
  1.4808    shl ecx, #16
  1.4809    mov cx, dx
  1.4810 -  mov bx, #0x0000
  1.4811 +  xor bx, bx
  1.4812    mov di, #0x00
  1.4813  pci_pro_devloop:
  1.4814    call pci_pro_select_reg
  1.4815 @@ -9215,6 +9588,27 @@ pci_pro_nextdev:
  1.4816    jne pci_pro_devloop
  1.4817    mov ah, #0x86
  1.4818    jmp pci_pro_fail
  1.4819 +pci_pro_f03: ;; find class code
  1.4820 +  cmp al, #0x03
  1.4821 +  jne pci_pro_f08
  1.4822 +  xor bx, bx
  1.4823 +  mov di, #0x08
  1.4824 +pci_pro_devloop2:
  1.4825 +  call pci_pro_select_reg
  1.4826 +  mov dx, #0x0cfc
  1.4827 +  in  eax, dx
  1.4828 +  shr eax, #8
  1.4829 +  cmp eax, ecx
  1.4830 +  jne pci_pro_nextdev2
  1.4831 +  cmp si, #0
  1.4832 +  je  pci_pro_ok
  1.4833 +  dec si
  1.4834 +pci_pro_nextdev2:
  1.4835 +  inc bx
  1.4836 +  cmp bx, #0x0100
  1.4837 +  jne pci_pro_devloop2
  1.4838 +  mov ah, #0x86
  1.4839 +  jmp pci_pro_fail
  1.4840  pci_pro_f08: ;; read configuration byte
  1.4841    cmp al, #0x08
  1.4842    jne pci_pro_f09
  1.4843 @@ -9288,16 +9682,20 @@ pci_pro_unknown:
  1.4844  pci_pro_fail:
  1.4845    pop edi
  1.4846    pop esi
  1.4847 -  sti
  1.4848 -  popf
  1.4849 +#ifdef BX_QEMU
  1.4850 +  and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu
  1.4851 +#endif
  1.4852 +  popfd
  1.4853    stc
  1.4854    retf
  1.4855  pci_pro_ok:
  1.4856    xor ah, ah
  1.4857    pop edi
  1.4858    pop esi
  1.4859 -  sti
  1.4860 -  popf
  1.4861 +#ifdef BX_QEMU
  1.4862 +  and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu
  1.4863 +#endif
  1.4864 +  popfd
  1.4865    clc
  1.4866    retf
  1.4867  
  1.4868 @@ -9324,8 +9722,14 @@ pcibios_real:
  1.4869    out dx, eax
  1.4870    mov dx, #0x0cfc
  1.4871    in  eax, dx
  1.4872 -  cmp eax, #0x12378086
  1.4873 +#ifdef PCI_FIXED_HOST_BRIDGE
  1.4874 +  cmp eax, #PCI_FIXED_HOST_BRIDGE
  1.4875    je  pci_present
  1.4876 +#else
  1.4877 +  ;; say ok if a device is present
  1.4878 +  cmp eax, #0xffffffff
  1.4879 +  jne  pci_present
  1.4880 +#endif
  1.4881    pop dx
  1.4882    pop eax
  1.4883    mov ah, #0xff
  1.4884 @@ -9339,7 +9743,7 @@ pci_present:
  1.4885    mov ax, #0x0001
  1.4886    mov bx, #0x0210
  1.4887    mov cx, #0
  1.4888 -  mov edx, #0x20494350
  1.4889 +  mov edx, #0x20494350 ;; "PCI "
  1.4890    mov edi, #0xf0000
  1.4891    mov di, #pcibios_protected
  1.4892    clc
  1.4893 @@ -9348,10 +9752,10 @@ pci_real_f02: ;; find pci device
  1.4894    push esi
  1.4895    push edi
  1.4896    cmp al, #0x02
  1.4897 -  jne pci_real_f08
  1.4898 +  jne pci_real_f03
  1.4899    shl ecx, #16
  1.4900    mov cx, dx
  1.4901 -  mov bx, #0x0000
  1.4902 +  xor bx, bx
  1.4903    mov di, #0x00
  1.4904  pci_real_devloop:
  1.4905    call pci_real_select_reg
  1.4906 @@ -9368,7 +9772,30 @@ pci_real_nextdev:
  1.4907    jne pci_real_devloop
  1.4908    mov dx, cx
  1.4909    shr ecx, #16
  1.4910 -  mov ah, #0x86
  1.4911 +  mov ax, #0x8602
  1.4912 +  jmp pci_real_fail
  1.4913 +pci_real_f03: ;; find class code
  1.4914 +  cmp al, #0x03
  1.4915 +  jne pci_real_f08
  1.4916 +  xor bx, bx
  1.4917 +  mov di, #0x08
  1.4918 +pci_real_devloop2:
  1.4919 +  call pci_real_select_reg
  1.4920 +  mov dx, #0x0cfc
  1.4921 +  in  eax, dx
  1.4922 +  shr eax, #8
  1.4923 +  cmp eax, ecx
  1.4924 +  jne pci_real_nextdev2
  1.4925 +  cmp si, #0
  1.4926 +  je  pci_real_ok
  1.4927 +  dec si
  1.4928 +pci_real_nextdev2:
  1.4929 +  inc bx
  1.4930 +  cmp bx, #0x0100
  1.4931 +  jne pci_real_devloop2
  1.4932 +  mov dx, cx
  1.4933 +  shr ecx, #16
  1.4934 +  mov ax, #0x8603
  1.4935    jmp pci_real_fail
  1.4936  pci_real_f08: ;; read configuration byte
  1.4937    cmp al, #0x08
  1.4938 @@ -9430,7 +9857,7 @@ pci_real_f0c: ;; write configuration wor
  1.4939    jmp pci_real_ok
  1.4940  pci_real_f0d: ;; write configuration dword
  1.4941    cmp al, #0x0d
  1.4942 -  jne pci_real_unknown
  1.4943 +  jne pci_real_f0e
  1.4944    call pci_real_select_reg
  1.4945    push dx
  1.4946    mov dx, #0x0cfc
  1.4947 @@ -9438,6 +9865,46 @@ pci_real_f0d: ;; write configuration dwo
  1.4948    out dx, eax
  1.4949    pop dx
  1.4950    jmp pci_real_ok
  1.4951 +pci_real_f0e: ;; get irq routing options
  1.4952 +  cmp al, #0x0e
  1.4953 +  jne pci_real_unknown
  1.4954 +  SEG ES
  1.4955 +  cmp word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start
  1.4956 +  jb pci_real_too_small
  1.4957 +  SEG ES
  1.4958 +  mov word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start
  1.4959 +  pushf
  1.4960 +  push ds
  1.4961 +  push es
  1.4962 +  push cx
  1.4963 +  push si
  1.4964 +  push di
  1.4965 +  cld
  1.4966 +  mov si, #pci_routing_table_structure_start
  1.4967 +  push cs
  1.4968 +  pop ds
  1.4969 +  SEG ES
  1.4970 +  mov cx, [di+2]
  1.4971 +  SEG ES
  1.4972 +  mov es, [di+4]
  1.4973 +  mov di, cx
  1.4974 +  mov cx, #pci_routing_table_structure_end - pci_routing_table_structure_start
  1.4975 +  rep
  1.4976 +      movsb
  1.4977 +  pop di
  1.4978 +  pop si
  1.4979 +  pop cx
  1.4980 +  pop es
  1.4981 +  pop ds
  1.4982 +  popf
  1.4983 +  mov bx, #(1 << 9) | (1 << 11)   ;; irq 9 and 11 are used
  1.4984 +  jmp pci_real_ok
  1.4985 +pci_real_too_small:
  1.4986 +  SEG ES
  1.4987 +  mov word ptr [di], #pci_routing_table_structure_end - pci_routing_table_structure_start
  1.4988 +  mov ah, #0x89
  1.4989 +  jmp pci_real_fail
  1.4990 +
  1.4991  pci_real_unknown:
  1.4992    mov ah, #0x81
  1.4993  pci_real_fail:
  1.4994 @@ -9464,7 +9931,7 @@ pci_real_select_reg:
  1.4995    out dx,  eax
  1.4996    pop dx
  1.4997    ret
  1.4998 -  
  1.4999 +
  1.5000  .align 16
  1.5001  pci_routing_table_structure:
  1.5002    db 0x24, 0x50, 0x49, 0x52  ;; "$PIR" signature
  1.5003 @@ -9472,21 +9939,22 @@ pci_routing_table_structure:
  1.5004    dw 32 + (6 * 16) ;; table size
  1.5005    db 0 ;; PCI interrupt router bus
  1.5006    db 0x08 ;; PCI interrupt router DevFunc
  1.5007 -  dw 0x0000 ;; PCI exclusive IRQs 
  1.5008 +  dw 0x0000 ;; PCI exclusive IRQs
  1.5009    dw 0x8086 ;; compatible PCI interrupt router vendor ID
  1.5010 -  dw 0x7000 ;; compatible PCI interrupt router device ID
  1.5011 +  dw 0x122e ;; compatible PCI interrupt router device ID
  1.5012    dw 0,0 ;; Miniport data
  1.5013    db 0,0,0,0,0,0,0,0,0,0,0 ;; reserved
  1.5014 -  db 0x07 ;; checksum
  1.5015 +  db 0x37 ;; checksum
  1.5016 +pci_routing_table_structure_start:
  1.5017    ;; first slot entry PCI-to-ISA (embedded)
  1.5018    db 0 ;; pci bus number
  1.5019    db 0x08 ;; pci device number (bit 7-3)
  1.5020    db 0x61 ;; link value INTA#: pointer into PCI2ISA config space
  1.5021 -  dw 0x0c20 ;; IRQ bitmap INTA# 
  1.5022 +  dw 0x0c20 ;; IRQ bitmap INTA#
  1.5023    db 0x62 ;; link value INTB#
  1.5024 -  dw 0x0c20 ;; IRQ bitmap INTB# 
  1.5025 +  dw 0x0c20 ;; IRQ bitmap INTB#
  1.5026    db 0x63 ;; link value INTC#
  1.5027 -  dw 0x0c20 ;; IRQ bitmap INTC# 
  1.5028 +  dw 0x0c20 ;; IRQ bitmap INTC#
  1.5029    db 0x60 ;; link value INTD#
  1.5030    dw 0x0c20 ;; IRQ bitmap INTD#
  1.5031    db 0 ;; physical slot (0 = embedded)
  1.5032 @@ -9495,11 +9963,11 @@ pci_routing_table_structure:
  1.5033    db 0 ;; pci bus number
  1.5034    db 0x10 ;; pci device number (bit 7-3)
  1.5035    db 0x62 ;; link value INTA#
  1.5036 -  dw 0x0c20 ;; IRQ bitmap INTA# 
  1.5037 +  dw 0x0c20 ;; IRQ bitmap INTA#
  1.5038    db 0x63 ;; link value INTB#
  1.5039 -  dw 0x0c20 ;; IRQ bitmap INTB# 
  1.5040 +  dw 0x0c20 ;; IRQ bitmap INTB#
  1.5041    db 0x60 ;; link value INTC#
  1.5042 -  dw 0x0c20 ;; IRQ bitmap INTC# 
  1.5043 +  dw 0x0c20 ;; IRQ bitmap INTC#
  1.5044    db 0x61 ;; link value INTD#
  1.5045    dw 0x0c20 ;; IRQ bitmap INTD#
  1.5046    db 1 ;; physical slot (0 = embedded)
  1.5047 @@ -9508,11 +9976,11 @@ pci_routing_table_structure:
  1.5048    db 0 ;; pci bus number
  1.5049    db 0x18 ;; pci device number (bit 7-3)
  1.5050    db 0x63 ;; link value INTA#
  1.5051 -  dw 0x0c20 ;; IRQ bitmap INTA# 
  1.5052 +  dw 0x0c20 ;; IRQ bitmap INTA#
  1.5053    db 0x60 ;; link value INTB#
  1.5054 -  dw 0x0c20 ;; IRQ bitmap INTB# 
  1.5055 +  dw 0x0c20 ;; IRQ bitmap INTB#
  1.5056    db 0x61 ;; link value INTC#
  1.5057 -  dw 0x0c20 ;; IRQ bitmap INTC# 
  1.5058 +  dw 0x0c20 ;; IRQ bitmap INTC#
  1.5059    db 0x62 ;; link value INTD#
  1.5060    dw 0x0c20 ;; IRQ bitmap INTD#
  1.5061    db 2 ;; physical slot (0 = embedded)
  1.5062 @@ -9521,11 +9989,11 @@ pci_routing_table_structure:
  1.5063    db 0 ;; pci bus number
  1.5064    db 0x20 ;; pci device number (bit 7-3)
  1.5065    db 0x60 ;; link value INTA#
  1.5066 -  dw 0x0c20 ;; IRQ bitmap INTA# 
  1.5067 +  dw 0x0c20 ;; IRQ bitmap INTA#
  1.5068    db 0x61 ;; link value INTB#
  1.5069 -  dw 0x0c20 ;; IRQ bitmap INTB# 
  1.5070 +  dw 0x0c20 ;; IRQ bitmap INTB#
  1.5071    db 0x62 ;; link value INTC#
  1.5072 -  dw 0x0c20 ;; IRQ bitmap INTC# 
  1.5073 +  dw 0x0c20 ;; IRQ bitmap INTC#
  1.5074    db 0x63 ;; link value INTD#
  1.5075    dw 0x0c20 ;; IRQ bitmap INTD#
  1.5076    db 3 ;; physical slot (0 = embedded)
  1.5077 @@ -9534,11 +10002,11 @@ pci_routing_table_structure:
  1.5078    db 0 ;; pci bus number
  1.5079    db 0x28 ;; pci device number (bit 7-3)
  1.5080    db 0x61 ;; link value INTA#
  1.5081 -  dw 0x0c20 ;; IRQ bitmap INTA# 
  1.5082 +  dw 0x0c20 ;; IRQ bitmap INTA#
  1.5083    db 0x62 ;; link value INTB#
  1.5084 -  dw 0x0c20 ;; IRQ bitmap INTB# 
  1.5085 +  dw 0x0c20 ;; IRQ bitmap INTB#
  1.5086    db 0x63 ;; link value INTC#
  1.5087 -  dw 0x0c20 ;; IRQ bitmap INTC# 
  1.5088 +  dw 0x0c20 ;; IRQ bitmap INTC#
  1.5089    db 0x60 ;; link value INTD#
  1.5090    dw 0x0c20 ;; IRQ bitmap INTD#
  1.5091    db 4 ;; physical slot (0 = embedded)
  1.5092 @@ -9547,17 +10015,352 @@ pci_routing_table_structure:
  1.5093    db 0 ;; pci bus number
  1.5094    db 0x30 ;; pci device number (bit 7-3)
  1.5095    db 0x62 ;; link value INTA#
  1.5096 -  dw 0x0c20 ;; IRQ bitmap INTA# 
  1.5097 +  dw 0x0c20 ;; IRQ bitmap INTA#
  1.5098    db 0x63 ;; link value INTB#
  1.5099 -  dw 0x0c20 ;; IRQ bitmap INTB# 
  1.5100 +  dw 0x0c20 ;; IRQ bitmap INTB#
  1.5101    db 0x60 ;; link value INTC#
  1.5102 -  dw 0x0c20 ;; IRQ bitmap INTC# 
  1.5103 +  dw 0x0c20 ;; IRQ bitmap INTC#
  1.5104    db 0x61 ;; link value INTD#
  1.5105    dw 0x0c20 ;; IRQ bitmap INTD#
  1.5106    db 5 ;; physical slot (0 = embedded)
  1.5107    db 0 ;; reserved
  1.5108 +pci_routing_table_structure_end:
  1.5109 +
  1.5110 +#if !BX_ROMBIOS32
  1.5111 +pci_irq_list:
  1.5112 +  db 11, 10, 9, 5;
  1.5113 +
  1.5114 +pcibios_init_sel_reg:
  1.5115 +  push eax
  1.5116 +  mov eax, #0x800000
  1.5117 +  mov ax,  bx
  1.5118 +  shl eax, #8
  1.5119 +  and dl,  #0xfc
  1.5120 +  or  al,  dl
  1.5121 +  mov dx,  #0x0cf8
  1.5122 +  out dx,  eax
  1.5123 +  pop eax
  1.5124 +  ret
  1.5125 +
  1.5126 +pcibios_init_iomem_bases:
  1.5127 +  push bp
  1.5128 +  mov  bp, sp
  1.5129 +  mov  eax, #0xe0000000 ;; base for memory init
  1.5130 +  push eax
  1.5131 +  mov  ax, #0xc000 ;; base for i/o init
  1.5132 +  push ax
  1.5133 +  mov  ax, #0x0010 ;; start at base address #0
  1.5134 +  push ax
  1.5135 +  mov  bx, #0x0008
  1.5136 +pci_init_io_loop1:
  1.5137 +  mov  dl, #0x00
  1.5138 +  call pcibios_init_sel_reg
  1.5139 +  mov  dx, #0x0cfc
  1.5140 +  in   ax, dx
  1.5141 +  cmp  ax, #0xffff
  1.5142 +  jz   next_pci_dev
  1.5143 +  mov  dl, #0x04 ;; disable i/o and memory space access
  1.5144 +  call pcibios_init_sel_reg
  1.5145 +  mov  dx, #0x0cfc
  1.5146 +  in   al, dx
  1.5147 +  and  al, #0xfc
  1.5148 +  out  dx, al
  1.5149 +pci_init_io_loop2:
  1.5150 +  mov  dl, [bp-8]
  1.5151 +  call pcibios_init_sel_reg
  1.5152 +  mov  dx, #0x0cfc
  1.5153 +  in   eax, dx
  1.5154 +  test al, #0x01
  1.5155 +  jnz  init_io_base
  1.5156 +  mov  ecx, eax
  1.5157 +  mov  eax, #0xffffffff
  1.5158 +  out  dx, eax
  1.5159 +  in   eax, dx
  1.5160 +  cmp  eax, ecx
  1.5161 +  je   next_pci_base
  1.5162 +  xor  eax, #0xffffffff
  1.5163 +  mov  ecx, eax
  1.5164 +  mov  eax, [bp-4]
  1.5165 +  out  dx, eax
  1.5166 +  add  eax, ecx ;; calculate next free mem base
  1.5167 +  add  eax, #0x01000000
  1.5168 +  and  eax, #0xff000000
  1.5169 +  mov  [bp-4], eax
  1.5170 +  jmp  next_pci_base
  1.5171 +init_io_base:
  1.5172 +  mov  cx, ax
  1.5173 +  mov  ax, #0xffff
  1.5174 +  out  dx, ax
  1.5175 +  in   ax, dx
  1.5176 +  cmp  ax, cx
  1.5177 +  je   next_pci_base
  1.5178 +  xor  ax, #0xfffe
  1.5179 +  mov  cx, ax
  1.5180 +  mov  ax, [bp-6]
  1.5181 +  out  dx, ax
  1.5182 +  add  ax, cx ;; calculate next free i/o base
  1.5183 +  add  ax, #0x0100
  1.5184 +  and  ax, #0xff00
  1.5185 +  mov  [bp-6], ax
  1.5186 +next_pci_base:
  1.5187 +  mov  al, [bp-8]
  1.5188 +  add  al, #0x04
  1.5189 +  cmp  al, #0x28
  1.5190 +  je   enable_iomem_space
  1.5191 +  mov  byte ptr[bp-8], al
  1.5192 +  jmp  pci_init_io_loop2
  1.5193 +enable_iomem_space:
  1.5194 +  mov  dl, #0x04 ;; enable i/o and memory space access if available
  1.5195 +  call pcibios_init_sel_reg
  1.5196 +  mov  dx, #0x0cfc
  1.5197 +  in   al, dx
  1.5198 +  or   al, #0x07
  1.5199 +  out  dx, al
  1.5200 +next_pci_dev:
  1.5201 +  mov  byte ptr[bp-8], #0x10
  1.5202 +  inc  bx
  1.5203 +  cmp  bx, #0x0100
  1.5204 +  jne  pci_init_io_loop1
  1.5205 +  mov  sp, bp
  1.5206 +  pop  bp
  1.5207 +  ret
  1.5208 +
  1.5209 +pcibios_init_set_elcr:
  1.5210 +  push ax
  1.5211 +  push cx
  1.5212 +  mov  dx, #0x04d0
  1.5213 +  test al, #0x08
  1.5214 +  jz   is_master_pic
  1.5215 +  inc  dx
  1.5216 +  and  al, #0x07
  1.5217 +is_master_pic:
  1.5218 +  mov  cl, al
  1.5219 +  mov  bl, #0x01
  1.5220 +  shl  bl, cl
  1.5221 +  in   al, dx
  1.5222 +  or   al, bl
  1.5223 +  out  dx, al
  1.5224 +  pop  cx
  1.5225 +  pop  ax
  1.5226 +  ret
  1.5227 +
  1.5228 +pcibios_init_irqs:
  1.5229 +  push ds
  1.5230 +  push bp
  1.5231 +  mov  ax, #0xf000
  1.5232 +  mov  ds, ax
  1.5233 +  mov  dx, #0x04d0 ;; reset ELCR1 + ELCR2
  1.5234 +  mov  al, #0x00
  1.5235 +  out  dx, al
  1.5236 +  inc  dx
  1.5237 +  out  dx, al
  1.5238 +  mov  si, #pci_routing_table_structure
  1.5239 +  mov  bh, [si+8]
  1.5240 +  mov  bl, [si+9]
  1.5241 +  mov  dl, #0x00
  1.5242 +  call pcibios_init_sel_reg
  1.5243 +  mov  dx, #0x0cfc
  1.5244 +  in   eax, dx
  1.5245 +  cmp  eax, [si+12] ;; check irq router
  1.5246 +  jne  pci_init_end
  1.5247 +  mov  dl, [si+34]
  1.5248 +  call pcibios_init_sel_reg
  1.5249 +  push bx ;; save irq router bus + devfunc
  1.5250 +  mov  dx, #0x0cfc
  1.5251 +  mov  ax, #0x8080
  1.5252 +  out  dx, ax ;; reset PIRQ route control
  1.5253 +  add  dx, #2
  1.5254 +  out  dx, ax
  1.5255 +  mov  ax, [si+6]
  1.5256 +  sub  ax, #0x20
  1.5257 +  shr  ax, #4
  1.5258 +  mov  cx, ax
  1.5259 +  add  si, #0x20 ;; set pointer to 1st entry
  1.5260 +  mov  bp, sp
  1.5261 +  mov  ax, #pci_irq_list
  1.5262 +  push ax
  1.5263 +  xor  ax, ax
  1.5264 +  push ax
  1.5265 +pci_init_irq_loop1:
  1.5266 +  mov  bh, [si]
  1.5267 +  mov  bl, [si+1]
  1.5268 +pci_init_irq_loop2:
  1.5269 +  mov  dl, #0x00
  1.5270 +  call pcibios_init_sel_reg
  1.5271 +  mov  dx, #0x0cfc
  1.5272 +  in   ax, dx
  1.5273 +  cmp  ax, #0xffff
  1.5274 +  jnz  pci_test_int_pin
  1.5275 +  test bl, #0x07
  1.5276 +  jz   next_pir_entry
  1.5277 +  jmp  next_pci_func
  1.5278 +pci_test_int_pin:
  1.5279 +  mov  dl, #0x3c
  1.5280 +  call pcibios_init_sel_reg
  1.5281 +  mov  dx, #0x0cfd
  1.5282 +  in   al, dx
  1.5283 +  and  al, #0x07
  1.5284 +  jz   next_pci_func
  1.5285 +  dec  al ;; determine pirq reg
  1.5286 +  mov  dl, #0x03
  1.5287 +  mul  al, dl
  1.5288 +  add  al, #0x02
  1.5289 +  xor  ah, ah
  1.5290 +  mov  bx, ax
  1.5291 +  mov  al, [si+bx]
  1.5292 +  mov  dl, al
  1.5293 +  mov  bx, [bp]
  1.5294 +  call pcibios_init_sel_reg
  1.5295 +  mov  dx, #0x0cfc
  1.5296 +  and  al, #0x03
  1.5297 +  add  dl, al
  1.5298 +  in   al, dx
  1.5299 +  cmp  al, #0x80
  1.5300 +  jb   pirq_found
  1.5301 +  mov  bx, [bp-2] ;; pci irq list pointer
  1.5302 +  mov  al, [bx]
  1.5303 +  out  dx, al
  1.5304 +  inc  bx
  1.5305 +  mov  [bp-2], bx
  1.5306 +  call pcibios_init_set_elcr
  1.5307 +pirq_found:
  1.5308 +  mov  bh, [si]
  1.5309 +  mov  bl, [si+1]
  1.5310 +  add  bl, [bp-3] ;; pci function number
  1.5311 +  mov  dl, #0x3c
  1.5312 +  call pcibios_init_sel_reg
  1.5313 +  mov  dx, #0x0cfc
  1.5314 +  out  dx, al
  1.5315 +next_pci_func:
  1.5316 +  inc  byte ptr[bp-3]
  1.5317 +  inc  bl
  1.5318 +  test bl, #0x07
  1.5319 +  jnz  pci_init_irq_loop2
  1.5320 +next_pir_entry:
  1.5321 +  add  si, #0x10
  1.5322 +  mov  byte ptr[bp-3], #0x00
  1.5323 +  loop pci_init_irq_loop1
  1.5324 +  mov  sp, bp
  1.5325 +  pop  bx
  1.5326 +pci_init_end:
  1.5327 +  pop  bp
  1.5328 +  pop  ds
  1.5329 +  ret
  1.5330 +#endif // !BX_ROMBIOS32
  1.5331  #endif // BX_PCIBIOS
  1.5332  
  1.5333 +#if BX_ROMBIOS32
  1.5334 +rombios32_init:
  1.5335 +  ;; save a20 and enable it
  1.5336 +  in al, 0x92
  1.5337 +  push ax
  1.5338 +  or al, #0x02
  1.5339 +  out 0x92, al
  1.5340 +
  1.5341 +  ;; save SS:SP to the BDA
  1.5342 +  xor ax, ax
  1.5343 +  mov ds, ax
  1.5344 +  mov 0x0469, ss
  1.5345 +  mov 0x0467, sp
  1.5346 +
  1.5347 +  SEG CS
  1.5348 +    lidt [pmode_IDT_info]
  1.5349 +  SEG CS
  1.5350 +    lgdt [rombios32_gdt_48]
  1.5351 +  ;; set PE bit in CR0
  1.5352 +  mov  eax, cr0
  1.5353 +  or   al, #0x01
  1.5354 +  mov  cr0, eax
  1.5355 +  ;; start protected mode code: ljmpl 0x10:rombios32_init1
  1.5356 +  db 0x66, 0xea
  1.5357 +  dw rombios32_05
  1.5358 +  dw 0x000f       ;; high 16 bit address
  1.5359 +  dw 0x0010
  1.5360 +
  1.5361 +use32 386
  1.5362 +rombios32_05:
  1.5363 +  ;; init data segments
  1.5364 +  mov eax, #0x18
  1.5365 +  mov ds, ax
  1.5366 +  mov es, ax
  1.5367 +  mov ss, ax
  1.5368 +  xor eax, eax
  1.5369 +  mov fs, ax
  1.5370 +  mov gs, ax
  1.5371 +  cld
  1.5372 +
  1.5373 +  ;; init the stack pointer to point below EBDA
  1.5374 +  mov ax, [0x040e]
  1.5375 +  shl eax, #4
  1.5376 +  mov esp, #-0x10
  1.5377 +  add esp, eax
  1.5378 +
  1.5379 +  ;; pass pointer to s3_resume_flag and s3_resume_vector to rombios32
  1.5380 +  push #0x04b0
  1.5381 +  push #0x04b2
  1.5382 +
  1.5383 +  ;; call rombios32 code
  1.5384 +  mov eax, #0x000e0000
  1.5385 +  call eax
  1.5386 +
  1.5387 +  ;; return to 16 bit protected mode first
  1.5388 +  db 0xea
  1.5389 +  dd rombios32_10
  1.5390 +  dw 0x20
  1.5391 +
  1.5392 +use16 386
  1.5393 +rombios32_10:
  1.5394 +  ;; restore data segment limits to 0xffff
  1.5395 +  mov ax, #0x28
  1.5396 +  mov ds, ax
  1.5397 +  mov es, ax
  1.5398 +  mov ss, ax
  1.5399 +  mov fs, ax
  1.5400 +  mov gs, ax
  1.5401 +
  1.5402 +  ;; reset PE bit in CR0
  1.5403 +  mov  eax, cr0
  1.5404 +  and  al, #0xFE
  1.5405 +  mov  cr0, eax
  1.5406 +
  1.5407 +  ;; far jump to flush CPU queue after transition to real mode
  1.5408 +  JMP_AP(0xf000, rombios32_real_mode)
  1.5409 +
  1.5410 +rombios32_real_mode:
  1.5411 +  ;; restore IDT to normal real-mode defaults
  1.5412 +  SEG CS
  1.5413 +    lidt [rmode_IDT_info]
  1.5414 +
  1.5415 +  xor ax, ax
  1.5416 +  mov ds, ax
  1.5417 +  mov es, ax
  1.5418 +  mov fs, ax
  1.5419 +  mov gs, ax
  1.5420 +
  1.5421 +  ;; restore SS:SP from the BDA
  1.5422 +  mov ss, 0x0469
  1.5423 +  xor esp, esp
  1.5424 +  mov sp, 0x0467
  1.5425 +  ;; restore a20
  1.5426 +  pop ax
  1.5427 +  out 0x92, al
  1.5428 +  ret
  1.5429 +
  1.5430 +rombios32_gdt_48:
  1.5431 +  dw 0x30
  1.5432 +  dw rombios32_gdt
  1.5433 +  dw 0x000f
  1.5434 +
  1.5435 +rombios32_gdt:
  1.5436 +  dw 0, 0, 0, 0
  1.5437 +  dw 0, 0, 0, 0
  1.5438 +  dw 0xffff, 0, 0x9b00, 0x00cf ; 32 bit flat code segment (0x10)
  1.5439 +  dw 0xffff, 0, 0x9300, 0x00cf ; 32 bit flat data segment (0x18)
  1.5440 +  dw 0xffff, 0, 0x9b0f, 0x0000 ; 16 bit code segment base=0xf0000 limit=0xffff
  1.5441 +  dw 0xffff, 0, 0x9300, 0x0000 ; 16 bit data segment base=0x0 limit=0xffff
  1.5442 +#endif // BX_ROMBIOS32
  1.5443 +
  1.5444 +
  1.5445  ; parallel port detection: base address in DX, index in BX, timeout in CL
  1.5446  detect_parport:
  1.5447    push dx
  1.5448 @@ -9628,14 +10431,13 @@ checksum_loop:
  1.5449    ret
  1.5450  
  1.5451  
  1.5452 -;; We need a copy of this string, but we are not actually a PnP BIOS, 
  1.5453 +;; We need a copy of this string, but we are not actually a PnP BIOS,
  1.5454  ;; so make sure it is *not* aligned, so OSes will not see it if they scan.
  1.5455  .align 16
  1.5456    db 0
  1.5457  pnp_string:
  1.5458    .ascii "$PnP"
  1.5459  
  1.5460 -
  1.5461  rom_scan:
  1.5462    ;; Scan for existence of valid expansion ROMS.
  1.5463    ;;   Video ROM:   from 0xC0000..0xC7FFF in 2k increments
  1.5464 @@ -9652,8 +10454,9 @@ rom_scan:
  1.5465  #if BX_TCGBIOS
  1.5466    call _tcpa_start_option_rom_scan    /* specs: 3.2.3.3 + 10.4.3 */
  1.5467  #endif
  1.5468 -  mov  cx, #0xc000
  1.5469 +
  1.5470  rom_scan_loop:
  1.5471 +  push ax       ;; Save AX
  1.5472    mov  ds, cx
  1.5473    mov  ax, #0x0004 ;; start with increment of 4 (512-byte) blocks = 2k
  1.5474    cmp [0], #0xAA55 ;; look for signature
  1.5475 @@ -9670,6 +10473,8 @@ rom_scan_loop:
  1.5476    add  al, #0x04
  1.5477  block_count_rounded:
  1.5478  
  1.5479 +  xor  bx, bx   ;; Restore DS back to 0000:
  1.5480 +  mov  ds, bx
  1.5481  #if BX_TCGBIOS
  1.5482    push ax
  1.5483    push ds
  1.5484 @@ -9680,7 +10485,7 @@ block_count_rounded:
  1.5485    push ecx       ;; segment where option rom is located at
  1.5486    call _tcpa_option_rom                   /* specs: 3.2.3.3 */
  1.5487    add sp, #4    ;; pop segment
  1.5488 -  pop ecx	;; original ecx
  1.5489 +  pop ecx      ;; original ecx
  1.5490    pop ds
  1.5491    pop ax
  1.5492  #endif
  1.5493 @@ -9704,11 +10509,11 @@ fetch_bdf:
  1.5494    xor  ax, ax
  1.5495    mov  al, [bx]
  1.5496  
  1.5497 -  ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS.  
  1.5498 +  ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS.
  1.5499    ;; That should stop it grabbing INT 19h; we will use its BEV instead.
  1.5500    mov  bx, #0xf000
  1.5501    mov  es, bx
  1.5502 -  lea  di, pnp_string 
  1.5503 +  lea  di, pnp_string
  1.5504  
  1.5505    xor  bx, bx   ;; Restore DS back to 0000:
  1.5506    mov  ds, bx
  1.5507 @@ -9721,8 +10526,8 @@ fetch_bdf:
  1.5508    add  sp, #2   ;; Pop offset value
  1.5509    pop  cx       ;; Pop seg value (restore CX)
  1.5510  
  1.5511 -  ;; Look at the ROM's PnP Expansion header.  Properly, we're supposed 
  1.5512 -  ;; to init all the ROMs and then go back and build an IPL table of 
  1.5513 +  ;; Look at the ROM's PnP Expansion header.  Properly, we're supposed
  1.5514 +  ;; to init all the ROMs and then go back and build an IPL table of
  1.5515    ;; all the bootable devices, but we can get away with one pass.
  1.5516    mov  ds, cx       ;; ROM base
  1.5517    mov  bx, 0x001a   ;; 0x1A is the offset into ROM header that contains...
  1.5518 @@ -9730,7 +10535,7 @@ fetch_bdf:
  1.5519    cmp  ax, #0x5024  ;; we look for signature "$PnP"
  1.5520    jne  no_bev
  1.5521    mov  ax, 2[bx]
  1.5522 -  cmp  ax, #0x506e 
  1.5523 +  cmp  ax, #0x506e
  1.5524    jne  no_bev
  1.5525  
  1.5526    mov  ax, 0x16[bx] ;; 0x16 is the offset of Boot Connection Vector
  1.5527 @@ -9753,25 +10558,31 @@ fetch_bdf:
  1.5528    cli           ;; In case expansion ROM BIOS turns IF on
  1.5529    add  sp, #2   ;; Pop offset value
  1.5530    pop  cx       ;; Pop seg value (restore CX)
  1.5531 -  jmp  no_bev
  1.5532 +  jmp   no_bev
  1.5533  
  1.5534  no_bcv:
  1.5535    mov  ax, 0x1a[bx] ;; 0x1A is also the offset into the expansion header of...
  1.5536    cmp  ax, #0x0000  ;; the Bootstrap Entry Vector, or zero if there is none.
  1.5537    je   no_bev
  1.5538  
  1.5539 -  ;; Found a device that thinks it can boot the system.  Record its BEV.
  1.5540 +  ;; Found a device that thinks it can boot the system.  Record its BEV and product name string.
  1.5541 +  mov  di, 0x10[bx]            ;; Pointer to the product name string or zero if none
  1.5542    xor  bx, bx
  1.5543    mov  ds, bx
  1.5544 -  mov  bx, word ptr [EBDA_SEG_PTR]
  1.5545 -  mov  ds, bx                  ;; Go to the segment where the IPL table lives 
  1.5546 +  mov  bx, word ptr [0x40E]    ;; EBDA segment
  1.5547 +  mov  ds, bx                  ;; Go to the segment where the IPL table lives
  1.5548    mov  bx, IPL_COUNT_OFFSET    ;; Read the number of entries so far
  1.5549    cmp  bx, #IPL_TABLE_ENTRIES
  1.5550    je   no_bev                  ;; Get out if the table is full
  1.5551    shl  bx, #0x4                ;; Turn count into offset (entries are 16 bytes)
  1.5552 -  mov  IPL_TABLE_OFFSET+0[bx], #0x80 ;; This entry is a BEV device
  1.5553 -  mov  IPL_TABLE_OFFSET+6[bx], cx    ;; Build a far pointer from the segment...
  1.5554 -  mov  IPL_TABLE_OFFSET+4[bx], ax    ;; and the offset
  1.5555 +  mov  IPL_TABLE_OFFSET+0[bx], #IPL_TYPE_BEV ;; This entry is a BEV device
  1.5556 +  mov  IPL_TABLE_OFFSET+6[bx], cx            ;; Build a far pointer from the segment...
  1.5557 +  mov  IPL_TABLE_OFFSET+4[bx], ax            ;; and the offset
  1.5558 +  cmp  di, #0x0000
  1.5559 +  je   no_prod_str
  1.5560 +  mov  0xA[bx], cx             ;; Build a far pointer from the segment...
  1.5561 +  mov  8[bx], di               ;; and the offset
  1.5562 +no_prod_str:
  1.5563    shr  bx, #0x4                ;; Turn the offset back into a count
  1.5564    inc  bx                      ;; We have one more entry now
  1.5565    mov  IPL_COUNT_OFFSET, bx    ;; Remember that.
  1.5566 @@ -9783,7 +10594,8 @@ rom_scan_increment:
  1.5567    shl  ax, #5   ;; convert 512-bytes blocks to 16-byte increments
  1.5568                  ;; because the segment selector is shifted left 4 bits.
  1.5569    add  cx, ax
  1.5570 -  cmp  cx, #0xe000
  1.5571 +  pop  ax       ;; Restore AX
  1.5572 +  cmp  cx, ax
  1.5573    jbe  rom_scan_loop
  1.5574  
  1.5575    xor  ax, ax   ;; Restore DS back to 0000:
  1.5576 @@ -9848,10 +10660,36 @@ tcpa_post_part2:
  1.5577  #endif
  1.5578  
  1.5579  
  1.5580 -;; for 'C' strings and other data, insert them here with
  1.5581 -;; a the following hack:
  1.5582 -;; DATA_SEG_DEFS_HERE
  1.5583 -
  1.5584 +post_init_pic:
  1.5585 +  mov al, #0x11 ; send initialisation commands
  1.5586 +  out 0x20, al
  1.5587 +  out 0xa0, al
  1.5588 +  mov al, #0x08
  1.5589 +  out 0x21, al
  1.5590 +  mov al, #0x70
  1.5591 +  out 0xa1, al
  1.5592 +  mov al, #0x04
  1.5593 +  out 0x21, al
  1.5594 +  mov al, #0x02
  1.5595 +  out 0xa1, al
  1.5596 +  mov al, #0x01
  1.5597 +  out 0x21, al
  1.5598 +  out 0xa1, al
  1.5599 +  mov  al, #0xb8
  1.5600 +  out  0x21, AL ;master pic: unmask IRQ 0, 1, 2, 6
  1.5601 +#if BX_USE_PS2_MOUSE
  1.5602 +  mov  al, #0x8f
  1.5603 +#else
  1.5604 +  mov  al, #0x9f
  1.5605 +#endif
  1.5606 +  out  0xa1, AL ;slave  pic: unmask IRQ 12, 13, 14
  1.5607 +  ret
  1.5608 +
  1.5609 +;; the following area can be used to write dynamically generated tables
  1.5610 +  .align 16
  1.5611 +bios_table_area_start:
  1.5612 +  dd 0xaafb4442
  1.5613 +  dd bios_table_area_end - bios_table_area_start - 8;
  1.5614  
  1.5615  ;--------
  1.5616  ;- POST -
  1.5617 @@ -9887,17 +10725,66 @@ post:
  1.5618  
  1.5619    ;; Examine CMOS shutdown status.
  1.5620    mov al, bl
  1.5621 -  mov dx, #EBDA_SEG
  1.5622 -  mov ds, dx
  1.5623 -  mov [EBDA_CMOS_SHUTDOWN_STATUS_OFFSET], AL
  1.5624 +
  1.5625 +  ;; 0x00, 0x09, 0x0D+ = normal startup
  1.5626 +  cmp AL, #0x00
  1.5627 +  jz normal_post
  1.5628 +  cmp AL, #0x0d
  1.5629 +  jae normal_post
  1.5630 +  cmp AL, #0x09
  1.5631 +  je normal_post
  1.5632 +
  1.5633 +  ;; 0x05 = eoi + jmp via [0x40:0x67] jump
  1.5634 +  cmp al, #0x05
  1.5635 +  je  eoi_jmp_post
  1.5636 +
  1.5637 +  ;; 0x0A = jmp via [0x40:0x67] jump
  1.5638 +  cmp al, #0x0a
  1.5639 +  je  jmp_post_0x467
  1.5640 +
  1.5641 +  ;; 0x0B = iret via [0x40:0x67]
  1.5642 +  cmp al, #0x0b
  1.5643 +  je  iret_post_0x467
  1.5644 +
  1.5645 +  ;; 0x0C = retf via [0x40:0x67]
  1.5646 +  cmp al, #0x0c
  1.5647 +  je  retf_post_0x467
  1.5648 +
  1.5649 +  ;; Examine CMOS shutdown status.
  1.5650 +  ;;  0x01,0x02,0x03,0x04,0x06,0x07,0x08 = Unimplemented shutdown status.
  1.5651 +  push bx
  1.5652 +  call _shutdown_status_panic
  1.5653 +
  1.5654 +#if 0
  1.5655 +  HALT(__LINE__)
  1.5656 +  ;
  1.5657 +  ;#if 0
  1.5658 +  ;  0xb0, 0x20,       /* mov al, #0x20 */
  1.5659 +  ;  0xe6, 0x20,       /* out 0x20, al    ;send EOI to PIC */
  1.5660 +  ;#endif
  1.5661 +  ;
  1.5662 +  pop es
  1.5663 +  pop ds
  1.5664 +  popa
  1.5665 +  iret
  1.5666 +#endif
  1.5667 +
  1.5668 +normal_post:
  1.5669 +  ; case 0: normal startup
  1.5670  
  1.5671    cli
  1.5672    mov  ax, #0xfffe
  1.5673    mov  sp, ax
  1.5674 -  mov  ax, #0x0000
  1.5675 +  xor  ax, ax
  1.5676    mov  ds, ax
  1.5677    mov  ss, ax
  1.5678  
  1.5679 +  ;; Save shutdown status
  1.5680 +  mov 0x04b0, bl
  1.5681 +
  1.5682 +  cmp bl, #0xfe
  1.5683 +  jz s3_post
  1.5684 +
  1.5685    ;; zero out BIOS data area (40:00..40:ff)
  1.5686    mov  es, ax
  1.5687    mov  cx, #0x0080 ;; 128 words
  1.5688 @@ -9909,18 +10796,16 @@ post:
  1.5689    call _log_bios_start
  1.5690  
  1.5691    ;; set all interrupts to default handler
  1.5692 -  mov  bx, #0x0000    ;; offset index
  1.5693 +  xor  bx, bx         ;; offset index
  1.5694    mov  cx, #0x0100    ;; counter (256 interrupts)
  1.5695    mov  ax, #dummy_iret_handler
  1.5696    mov  dx, #0xF000
  1.5697  
  1.5698  post_default_ints:
  1.5699    mov  [bx], ax
  1.5700 -  inc  bx
  1.5701 -  inc  bx
  1.5702 +  add  bx, #2
  1.5703    mov  [bx], dx
  1.5704 -  inc  bx
  1.5705 -  inc  bx
  1.5706 +  add  bx, #2
  1.5707    loop post_default_ints
  1.5708  
  1.5709    ;; set vector 0x79 to zero
  1.5710 @@ -10076,28 +10961,51 @@ post_default_ints:
  1.5711    SET_INT_VECTOR(0x10, #0xF000, #int10_handler)
  1.5712  
  1.5713    ;; PIC
  1.5714 -  mov al, #0x11 ; send initialisation commands
  1.5715 -  out 0x20, al
  1.5716 -  out 0xa0, al
  1.5717 -  mov al, #0x08
  1.5718 -  out 0x21, al
  1.5719 -  mov al, #0x70
  1.5720 -  out 0xa1, al
  1.5721 -  mov al, #0x04
  1.5722 -  out 0x21, al
  1.5723 -  mov al, #0x02
  1.5724 -  out 0xa1, al
  1.5725 -  mov al, #0x01
  1.5726 -  out 0x21, al
  1.5727 -  out 0xa1, al
  1.5728 -  mov  al, #0xb8
  1.5729 -  out  0x21, AL ;master pic: unmask IRQ 0, 1, 2, 6
  1.5730 -#if BX_USE_PS2_MOUSE
  1.5731 -  mov  al, #0x8f
  1.5732 +  call post_init_pic
  1.5733 +
  1.5734 +  mov  cx, #0xc000  ;; init vga bios
  1.5735 +  mov  ax, #0xc780
  1.5736 +  call rom_scan
  1.5737 +
  1.5738 +  call _print_bios_banner
  1.5739 +
  1.5740 +#if BX_ROMBIOS32
  1.5741 +  call rombios32_init
  1.5742  #else
  1.5743 -  mov  al, #0x9f
  1.5744 -#endif
  1.5745 -  out  0xa1, AL ;slave  pic: unmask IRQ 12, 13, 14
  1.5746 +#if BX_PCIBIOS
  1.5747 +  call pcibios_init_iomem_bases
  1.5748 +  call pcibios_init_irqs
  1.5749 +#endif //BX_PCIBIOS
  1.5750 +#endif
  1.5751 +
  1.5752 +  ;;
  1.5753 +  ;; Floppy setup
  1.5754 +  ;;
  1.5755 +  call floppy_drive_post
  1.5756 +
  1.5757 +  ;;
  1.5758 +  ;; Hard Drive setup
  1.5759 +  ;;
  1.5760 +  call hard_drive_post
  1.5761 +
  1.5762 +#if BX_USE_ATADRV
  1.5763 +
  1.5764 +  ;;
  1.5765 +  ;; ATA/ATAPI driver setup
  1.5766 +  ;;
  1.5767 +  call _ata_init
  1.5768 +  call _ata_detect
  1.5769 +  ;;
  1.5770 +
  1.5771 +#endif // BX_USE_ATADRV
  1.5772 +
  1.5773 +#if BX_ELTORITO_BOOT
  1.5774 +  ;;
  1.5775 +  ;; eltorito floppy/harddisk emulation from cd
  1.5776 +  ;;
  1.5777 +  call _cdemu_init
  1.5778 +  ;;
  1.5779 +#endif // BX_ELTORITO_BOOT
  1.5780  
  1.5781  #ifdef HVMASSIST
  1.5782    call _enable_rom_write_access
  1.5783 @@ -10109,52 +11017,19 @@ post_default_ints:
  1.5784  
  1.5785    call _init_boot_vectors
  1.5786  
  1.5787 +  mov  cx, #0xc800  ;; init option roms
  1.5788 +  mov  ax, #0xe000
  1.5789    call rom_scan
  1.5790  
  1.5791 -  call _print_bios_banner 
  1.5792 -
  1.5793 -  ;;
  1.5794 -  ;; Floppy setup
  1.5795 -  ;;
  1.5796 -  call floppy_drive_post
  1.5797 -
  1.5798 -#if BX_USE_ATADRV
  1.5799 -
  1.5800 -  ;;
  1.5801 -  ;; Hard Drive setup
  1.5802 -  ;;
  1.5803 -  call hard_drive_post
  1.5804 -
  1.5805 -  ;;
  1.5806 -  ;; ATA/ATAPI driver setup
  1.5807 -  ;;
  1.5808 -  call _ata_init
  1.5809 -  call _ata_detect
  1.5810 -  ;;
  1.5811 -#else // BX_USE_ATADRV
  1.5812 -
  1.5813 -  ;;
  1.5814 -  ;; Hard Drive setup
  1.5815 -  ;;
  1.5816 -  call hard_drive_post
  1.5817 -
  1.5818 -#endif // BX_USE_ATADRV
  1.5819 -
  1.5820  #if BX_ELTORITO_BOOT
  1.5821 -  ;;
  1.5822 -  ;; eltorito floppy/harddisk emulation from cd
  1.5823 -  ;;
  1.5824 -  call _cdemu_init
  1.5825 -  ;;
  1.5826 +  call _interactive_bootkey
  1.5827  #endif // BX_ELTORITO_BOOT
  1.5828  
  1.5829 -  call _s3_resume
  1.5830 -  call _interactive_bootkey
  1.5831 -
  1.5832  #if BX_TCGBIOS
  1.5833    call tcpa_post_part2
  1.5834  #endif
  1.5835  
  1.5836 +  sti        ;; enable interrupts
  1.5837    ;; Start the boot sequence.   See the comments in int19_relocated 
  1.5838    ;; for why we use INT 18h instead of INT 19h here.
  1.5839    int  #0x18
  1.5840 @@ -10167,7 +11042,7 @@ nmi:
  1.5841    iret
  1.5842  
  1.5843  int75_handler:
  1.5844 -  out  0xf0, al         // clear irq13 
  1.5845 +  out  0xf0, al         // clear irq13
  1.5846    call eoi_both_pics    // clear interrupt
  1.5847    int  2                // legacy nmi call
  1.5848    iret
  1.5849 @@ -10266,7 +11141,7 @@ db 0x00
  1.5850  int14_handler:
  1.5851    push ds
  1.5852    pusha
  1.5853 -  mov  ax, #0x0000
  1.5854 +  xor  ax, ax
  1.5855    mov  ds, ax
  1.5856    call _int14_function
  1.5857    popa
  1.5858 @@ -10371,26 +11246,7 @@ int09_handler:
  1.5859    jz  int09_finish
  1.5860  
  1.5861    in  al, #0x60             ;;read key from keyboard controller
  1.5862 -  //test al, #0x80            ;;look for key release
  1.5863 -  //jnz  int09_process_key    ;; dont pass releases to intercept?
  1.5864 -
  1.5865 -  ;; check for extended key
  1.5866 -  cmp  al, #0xe0
  1.5867 -  jne int09_call_int15_4f
  1.5868 -  
  1.5869 -  push ds
  1.5870 -  xor  ax, ax
  1.5871 -  mov  ds, ax
  1.5872 -  mov  al, BYTE [0x496]     ;; mf2_state |= 0x01
  1.5873 -  or   al, #0x01
  1.5874 -  mov  BYTE [0x496], al
  1.5875 -  pop  ds
  1.5876 -  
  1.5877 -  in  al, #0x60             ;;read another key from keyboard controller
  1.5878 -
  1.5879    sti
  1.5880 -
  1.5881 -int09_call_int15_4f:
  1.5882    push  ds
  1.5883    pusha
  1.5884  #ifdef BX_CALL_INT15_4F
  1.5885 @@ -10400,8 +11256,27 @@ int09_call_int15_4f:
  1.5886    jnc  int09_done
  1.5887  #endif
  1.5888  
  1.5889 -
  1.5890 -//int09_process_key:
  1.5891 +  ;; check for extended key
  1.5892 +  cmp  al, #0xe0
  1.5893 +  jne int09_check_pause
  1.5894 +  xor  ax, ax
  1.5895 +  mov  ds, ax
  1.5896 +  mov  al, BYTE [0x496]     ;; mf2_state |= 0x02
  1.5897 +  or   al, #0x02
  1.5898 +  mov  BYTE [0x496], al
  1.5899 +  jmp int09_done
  1.5900 +
  1.5901 +int09_check_pause: ;; check for pause key
  1.5902 +  cmp  al, #0xe1
  1.5903 +  jne int09_process_key
  1.5904 +  xor  ax, ax
  1.5905 +  mov  ds, ax
  1.5906 +  mov  al, BYTE [0x496]     ;; mf2_state |= 0x01
  1.5907 +  or   al, #0x01
  1.5908 +  mov  BYTE [0x496], al
  1.5909 +  jmp int09_done
  1.5910 +
  1.5911 +int09_process_key:
  1.5912    mov   bx, #0xf000
  1.5913    mov   ds, bx
  1.5914    call  _int09_function
  1.5915 @@ -10419,8 +11294,6 @@ int09_finish:
  1.5916    iret
  1.5917  
  1.5918  
  1.5919 -
  1.5920 -
  1.5921  ;----------------------------------------
  1.5922  ;- INT 13h Diskette Service Entry Point -
  1.5923  ;----------------------------------------
  1.5924 @@ -10459,7 +11332,7 @@ int0e_loop2:
  1.5925    je int0e_loop2
  1.5926  int0e_normal:
  1.5927    push ds
  1.5928 -  mov  ax, #0x0000 ;; segment 0000
  1.5929 +  xor  ax, ax ;; segment 0000
  1.5930    mov  ds, ax
  1.5931    call eoi_master_pic
  1.5932    mov  al, 0x043e
  1.5933 @@ -10496,7 +11369,7 @@ db  0x08
  1.5934  int17_handler:
  1.5935    push ds
  1.5936    pusha
  1.5937 -  mov  ax, #0x0000
  1.5938 +  xor  ax, ax
  1.5939    mov  ds, ax
  1.5940    call _int17_function
  1.5941    popa
  1.5942 @@ -10686,11 +11559,11 @@ int1a_callfunction:
  1.5943  ;;
  1.5944  int70_handler:
  1.5945    push ds
  1.5946 -  pusha
  1.5947 +  pushad
  1.5948    xor  ax, ax
  1.5949    mov  ds, ax
  1.5950    call _int70_function
  1.5951 -  popa
  1.5952 +  popad
  1.5953    pop  ds
  1.5954    iret
  1.5955  
  1.5956 @@ -10748,7 +11621,7 @@ int08_store_ticks:
  1.5957  
  1.5958  
  1.5959  .org 0xff00
  1.5960 -.ascii "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team."
  1.5961 +.ascii BIOS_COPYRIGHT_STRING
  1.5962  
  1.5963  ;------------------------------------------------
  1.5964  ;- IRET Instruction for Dummy Interrupt Handler -
  1.5965 @@ -10770,7 +11643,7 @@ dummy_iret_handler:
  1.5966  #ifdef HVMTEST
  1.5967    jmp 0xd000:0x0003;
  1.5968  #else
  1.5969 -  jmp 0xf000:post
  1.5970 +   jmp 0xf000:post
  1.5971  #endif
  1.5972  
  1.5973  .org 0xfff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY
  1.5974 @@ -10783,10 +11656,10 @@ db 0x00   ; filler
  1.5975  .org 0xfa6e ;; Character Font for 320x200 & 640x200 Graphics (lower 128 characters)
  1.5976  ASM_END
  1.5977  /*
  1.5978 - * This font comes from the fntcol16.zip package (c) by  Joseph Gil 
  1.5979 + * This font comes from the fntcol16.zip package (c) by  Joseph Gil
  1.5980   * found at ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
  1.5981   * This font is public domain
  1.5982 - */ 
  1.5983 + */
  1.5984  static Bit8u vgafont8[128*8]=
  1.5985  {
  1.5986   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  1.5987 @@ -10962,328 +11835,10 @@ db 0,0,0,0,0,0,0,0 ; 24 bytes
  1.5988  db 0,0,0,0,0,0,0   ; 31 bytes
  1.5989  ASM_END
  1.5990  
  1.5991 -#else // !HVMASSIST
  1.5992 -
  1.5993 +#endif // HVMASSIST
  1.5994  ASM_START
  1.5995 -.org 0xcc00
  1.5996 +.org 0xcff0
  1.5997 +bios_table_area_end:
  1.5998  // bcc-generated data will be placed here
  1.5999 -
  1.6000 -// For documentation of this config structure, look on developer.intel.com and
  1.6001 -// search for multiprocessor specification.  Note that when you change anything
  1.6002 -// you must update the checksum (a pain!).  It would be better to construct this
  1.6003 -// with C structures, or at least fill in the checksum automatically.
  1.6004 -//
  1.6005 -// Maybe this structs could be moved elsewhere than d000
  1.6006 -
  1.6007 -#if (BX_SMP_PROCESSORS==1)
  1.6008 -  // no structure necessary.
  1.6009 -#elif (BX_SMP_PROCESSORS==2)
  1.6010 -// define the Intel MP Configuration Structure for 2 processors at
  1.6011 -// APIC ID 0,1.  I/O APIC at ID=2.
  1.6012 -.align 16
  1.6013 -mp_config_table:
  1.6014 -  db 0x50, 0x43, 0x4d, 0x50  ;; "PCMP" signature
  1.6015 -  dw (mp_config_end-mp_config_table)  ;; table length
  1.6016 -  db 4 ;; spec rev
  1.6017 -  db 0x65 ;; checksum
  1.6018 -  .ascii "BOCHSCPU"     ;; OEM id = "BOCHSCPU"
  1.6019 -  db 0x30, 0x2e, 0x31, 0x20 ;; vendor id = "0.1         "
  1.6020 -  db 0x20, 0x20, 0x20, 0x20 
  1.6021 -  db 0x20, 0x20, 0x20, 0x20
  1.6022 -  dw 0,0 ;; oem table ptr
  1.6023 -  dw 0 ;; oem table size
  1.6024 -  dw 20 ;; entry count
  1.6025 -  dw 0x0000, 0xfee0 ;; memory mapped address of local APIC
  1.6026 -  dw 0 ;; extended table length
  1.6027 -  db 0 ;; extended table checksum
  1.6028 -  db 0 ;; reserved
  1.6029 -mp_config_proc0:
  1.6030 -  db 0 ;; entry type=processor
  1.6031 -  db 0 ;; local APIC id
  1.6032 -  db 0x11 ;; local APIC version number
  1.6033 -  db 3 ;; cpu flags: enabled, bootstrap processor
  1.6034 -  db 0,6,0,0 ;; cpu signature
  1.6035 -  dw 0x201,0 ;; feature flags
  1.6036 -  dw 0,0 ;; reserved
  1.6037 -  dw 0,0 ;; reserved
  1.6038 -mp_config_proc1:
  1.6039 -  db 0 ;; entry type=processor
  1.6040 -  db 1 ;; local APIC id
  1.6041 -  db 0x11 ;; local APIC version number
  1.6042 -  db 1 ;; cpu flags: enabled
  1.6043 -  db 0,6,0,0 ;; cpu signature
  1.6044 -  dw 0x201,0 ;; feature flags
  1.6045 -  dw 0,0 ;; reserved
  1.6046 -  dw 0,0 ;; reserved
  1.6047 -mp_config_isa_bus:
  1.6048 -  db 1 ;; entry type=bus
  1.6049 -  db 0 ;; bus ID
  1.6050 -  db 0x49, 0x53, 0x41, 0x20, 0x20, 0x20  ;; bus type="ISA   "
  1.6051 -mp_config_ioapic:
  1.6052 -  db 2 ;; entry type=I/O APIC
  1.6053 -  db 2 ;; apic id=2. linux will set.
  1.6054 -  db 0x11 ;; I/O APIC version number
  1.6055 -  db 1 ;; flags=1=enabled
  1.6056 -  dw 0x0000, 0xfec0 ;; memory mapped address of I/O APIC
  1.6057 -mp_config_irqs:
  1.6058 -  db 3 ;; entry type=I/O interrupt
  1.6059 -  db 0 ;; interrupt type=vectored interrupt
  1.6060 -  db 0,0 ;; flags po=0, el=0 (linux uses as default)
  1.6061 -  db 0 ;; source bus ID is ISA
  1.6062 -  db 0 ;; source bus IRQ
  1.6063 -  db 2 ;; destination I/O APIC ID
  1.6064 -  db 0 ;; destination I/O APIC interrrupt in
  1.6065 -  ;; repeat pattern for interrupts 0-15
  1.6066 -  db 3,0,0,0,0,1,2,1
  1.6067 -  db 3,0,0,0,0,2,2,2
  1.6068 -  db 3,0,0,0,0,3,2,3
  1.6069 -  db 3,0,0,0,0,4,2,4
  1.6070 -  db 3,0,0,0,0,5,2,5
  1.6071 -  db 3,0,0,0,0,6,2,6
  1.6072 -  db 3,0,0,0,0,7,2,7
  1.6073 -  db 3,0,0,0,0,8,2,8
  1.6074 -  db 3,0,0,0,0,9,2,9
  1.6075 -  db 3,0,0,0,0,10,2,10
  1.6076 -  db 3,0,0,0,0,11,2,11
  1.6077 -  db 3,0,0,0,0,12,2,12
  1.6078 -  db 3,0,0,0,0,13,2,13
  1.6079 -  db 3,0,0,0,0,14,2,14
  1.6080 -  db 3,0,0,0,0,15,2,15
  1.6081 -#elif (BX_SMP_PROCESSORS==4)
  1.6082 -// define the Intel MP Configuration Structure for 4 processors at
  1.6083 -// APIC ID 0,1,2,3.  I/O APIC at ID=4.
  1.6084 -.align 16
  1.6085 -mp_config_table:
  1.6086 -  db 0x50, 0x43, 0x4d, 0x50  ;; "PCMP" signature
  1.6087 -  dw (mp_config_end-mp_config_table)  ;; table length
  1.6088 -  db 4 ;; spec rev
  1.6089 -  db 0xdd ;; checksum
  1.6090 -  .ascii "BOCHSCPU"     ;; OEM id = "BOCHSCPU"
  1.6091 -  db 0x30, 0x2e, 0x31, 0x20 ;; vendor id = "0.1         "
  1.6092 -  db 0x20, 0x20, 0x20, 0x20 
  1.6093 -  db 0x20, 0x20, 0x20, 0x20
  1.6094 -  dw 0,0 ;; oem table ptr
  1.6095 -  dw 0 ;; oem table size
  1.6096 -  dw 22 ;; entry count
  1.6097 -  dw 0x0000, 0xfee0 ;; memory mapped address of local APIC
  1.6098 -  dw 0 ;; extended table length
  1.6099 -  db 0 ;; extended table checksum
  1.6100 -  db 0 ;; reserved
  1.6101 -mp_config_proc0:
  1.6102 -  db 0 ;; entry type=processor
  1.6103 -  db 0 ;; local APIC id
  1.6104 -  db 0x11 ;; local APIC version number
  1.6105 -  db 3 ;; cpu flags: enabled, bootstrap processor
  1.6106 -  db 0,6,0,0 ;; cpu signature
  1.6107 -  dw 0x201,0 ;; feature flags
  1.6108 -  dw 0,0 ;; reserved
  1.6109 -  dw 0,0 ;; reserved
  1.6110 -mp_config_proc1:
  1.6111 -  db 0 ;; entry type=processor
  1.6112 -  db 1 ;; local APIC id
  1.6113 -  db 0x11 ;; local APIC version number
  1.6114 -  db 1 ;; cpu flags: enabled
  1.6115 -  db 0,6,0,0 ;; cpu signature
  1.6116 -  dw 0x201,0 ;; feature flags
  1.6117 -  dw 0,0 ;; reserved
  1.6118 -  dw 0,0 ;; reserved
  1.6119 -mp_config_proc2:
  1.6120 -  db 0 ;; entry type=processor
  1.6121 -  db 2 ;; local APIC id
  1.6122 -  db 0x11 ;; local APIC version number
  1.6123 -  db 1 ;; cpu flags: enabled
  1.6124 -  db 0,6,0,0 ;; cpu signature
  1.6125 -  dw 0x201,0 ;; feature flags
  1.6126 -  dw 0,0 ;; reserved
  1.6127 -  dw 0,0 ;; reserved
  1.6128 -mp_config_proc3:
  1.6129 -  db 0 ;; entry type=processor
  1.6130 -  db 3 ;; local APIC id
  1.6131 -  db 0x11 ;; local APIC version number
  1.6132 -  db 1 ;; cpu flags: enabled
  1.6133 -  db 0,6,0,0 ;; cpu signature
  1.6134 -  dw 0x201,0 ;; feature flags
  1.6135 -  dw 0,0 ;; reserved
  1.6136 -  dw 0,0 ;; reserved
  1.6137 -mp_config_isa_bus:
  1.6138 -  db 1 ;; entry type=bus
  1.6139 -  db 0 ;; bus ID
  1.6140 -  db 0x49, 0x53, 0x41, 0x20, 0x20, 0x20  ;; bus type="ISA   "
  1.6141 -mp_config_ioapic:
  1.6142 -  db 2 ;; entry type=I/O APIC
  1.6143 -  db 4 ;; apic id=4. linux will set.
  1.6144 -  db 0x11 ;; I/O APIC version number
  1.6145 -  db 1 ;; flags=1=enabled
  1.6146 -  dw 0x0000, 0xfec0 ;; memory mapped address of I/O APIC
  1.6147 -mp_config_irqs:
  1.6148 -  db 3 ;; entry type=I/O interrupt
  1.6149 -  db 0 ;; interrupt type=vectored interrupt
  1.6150 -  db 0,0 ;; flags po=0, el=0 (linux uses as default)
  1.6151 -  db 0 ;; source bus ID is ISA
  1.6152 -  db 0 ;; source bus IRQ
  1.6153 -  db 4 ;; destination I/O APIC ID
  1.6154 -  db 0 ;; destination I/O APIC interrrupt in
  1.6155 -  ;; repeat pattern for interrupts 0-15
  1.6156 -  db 3,0,0,0,0,1,4,1
  1.6157 -  db 3,0,0,0,0,2,4,2
  1.6158 -  db 3,0,0,0,0,3,4,3
  1.6159 -  db 3,0,0,0,0,4,4,4
  1.6160 -  db 3,0,0,0,0,5,4,5
  1.6161 -  db 3,0,0,0,0,6,4,6
  1.6162 -  db 3,0,0,0,0,7,4,7
  1.6163 -  db 3,0,0,0,0,8,4,8
  1.6164 -  db 3,0,0,0,0,9,4,9
  1.6165 -  db 3,0,0,0,0,10,4,10
  1.6166 -  db 3,0,0,0,0,11,4,11
  1.6167 -  db 3,0,0,0,0,12,4,12
  1.6168 -  db 3,0,0,0,0,13,4,13
  1.6169 -  db 3,0,0,0,0,14,4,14
  1.6170 -  db 3,0,0,0,0,15,4,15
  1.6171 -#elif (BX_SMP_PROCESSORS==8)
  1.6172 -// define the Intel MP Configuration Structure for 8 processors at
  1.6173 -// APIC ID 0,1,2,3,4,5,6,7.  I/O APIC at ID=8.
  1.6174 -.align 16
  1.6175 -mp_config_table:
  1.6176 -  db 0x50, 0x43, 0x4d, 0x50  ;; "PCMP" signature
  1.6177 -  dw (mp_config_end-mp_config_table)  ;; table length
  1.6178 -  db 4 ;; spec rev
  1.6179 -  db 0xc3 ;; checksum
  1.6180 -  .ascii "BOCHSCPU"     ;; OEM id = "BOCHSCPU"
  1.6181 -  db 0x30, 0x2e, 0x31, 0x20 ;; vendor id = "0.1         "
  1.6182 -  db 0x20, 0x20, 0x20, 0x20 
  1.6183 -  db 0x20, 0x20, 0x20, 0x20
  1.6184 -  dw 0,0 ;; oem table ptr
  1.6185 -  dw 0 ;; oem table size
  1.6186 -  dw 26 ;; entry count
  1.6187 -  dw 0x0000, 0xfee0 ;; memory mapped address of local APIC
  1.6188 -  dw 0 ;; extended table length
  1.6189 -  db 0 ;; extended table checksum
  1.6190 -  db 0 ;; reserved
  1.6191 -mp_config_proc0:
  1.6192 -  db 0 ;; entry type=processor
  1.6193 -  db 0 ;; local APIC id
  1.6194 -  db 0x11 ;; local APIC version number
  1.6195 -  db 3 ;; cpu flags: enabled, bootstrap processor
  1.6196 -  db 0,6,0,0 ;; cpu signature
  1.6197 -  dw 0x201,0 ;; feature flags
  1.6198 -  dw 0,0 ;; reserved
  1.6199 -  dw 0,0 ;; reserved
  1.6200 -mp_config_proc1:
  1.6201 -  db 0 ;; entry type=processor
  1.6202 -  db 1 ;; local APIC id
  1.6203 -  db 0x11 ;; local APIC version number
  1.6204 -  db 1 ;; cpu flags: enabled
  1.6205 -  db 0,6,0,0 ;; cpu signature
  1.6206 -  dw 0x201,0 ;; feature flags
  1.6207 -  dw 0,0 ;; reserved
  1.6208 -  dw 0,0 ;; reserved
  1.6209 -mp_config_proc2:
  1.6210 -  db 0 ;; entry type=processor
  1.6211 -  db 2 ;; local APIC id
  1.6212 -  db 0x11 ;; local APIC version number
  1.6213 -  db 1 ;; cpu flags: enabled
  1.6214 -  db 0,6,0,0 ;; cpu signature
  1.6215 -  dw 0x201,0 ;; feature flags
  1.6216 -  dw 0,0 ;; reserved
  1.6217 -  dw 0,0 ;; reserved
  1.6218 -mp_config_proc3:
  1.6219 -  db 0 ;; entry type=processor
  1.6220 -  db 3 ;; local APIC id
  1.6221 -  db 0x11 ;; local APIC version number
  1.6222 -  db 1 ;; cpu flags: enabled
  1.6223 -  db 0,6,0,0 ;; cpu signature
  1.6224 -  dw 0x201,0 ;; feature flags
  1.6225 -  dw 0,0 ;; reserved
  1.6226 -  dw 0,0 ;; reserved
  1.6227 -mp_config_proc4:
  1.6228 -  db 0 ;; entry type=processor
  1.6229 -  db 4 ;; local APIC id
  1.6230 -  db 0x11 ;; local APIC version number
  1.6231 -  db 1 ;; cpu flags: enabled
  1.6232 -  db 0,6,0,0 ;; cpu signature
  1.6233 -  dw 0x201,0 ;; feature flags
  1.6234 -  dw 0,0 ;; reserved
  1.6235 -  dw 0,0 ;; reserved
  1.6236 -mp_config_proc5:
  1.6237 -  db 0 ;; entry type=processor
  1.6238 -  db 5 ;; local APIC id
  1.6239 -  db 0x11 ;; local APIC version number
  1.6240 -  db 1 ;; cpu flags: enabled
  1.6241 -  db 0,6,0,0 ;; cpu signature
  1.6242 -  dw 0x201,0 ;; feature flags
  1.6243 -  dw 0,0 ;; reserved
  1.6244 -  dw 0,0 ;; reserved
  1.6245 -mp_config_proc6:
  1.6246 -  db 0 ;; entry type=processor
  1.6247 -  db 6 ;; local APIC id
  1.6248 -  db 0x11 ;; local APIC version number
  1.6249 -  db 1 ;; cpu flags: enabled
  1.6250 -  db 0,6,0,0 ;; cpu signature
  1.6251 -  dw 0x201,0 ;; feature flags
  1.6252 -  dw 0,0 ;; reserved
  1.6253 -  dw 0,0 ;; reserved
  1.6254 -mp_config_proc7:
  1.6255 -  db 0 ;; entry type=processor
  1.6256 -  db 7 ;; local APIC id
  1.6257 -  db 0x11 ;; local APIC version number
  1.6258 -  db 1 ;; cpu flags: enabled
  1.6259 -  db 0,6,0,0 ;; cpu signature
  1.6260 -  dw 0x201,0 ;; feature flags
  1.6261 -  dw 0,0 ;; reserved
  1.6262 -  dw 0,0 ;; reserved
  1.6263 -mp_config_isa_bus:
  1.6264 -  db 1 ;; entry type=bus
  1.6265 -  db 0 ;; bus ID
  1.6266 -  db 0x49, 0x53, 0x41, 0x20, 0x20, 0x20  ;; bus type="ISA   "
  1.6267 -mp_config_ioapic:
  1.6268 -  db 2 ;; entry type=I/O APIC
  1.6269 -  db 8 ;; apic id=8
  1.6270 -  db 0x11 ;; I/O APIC version number
  1.6271 -  db 1 ;; flags=1=enabled
  1.6272 -  dw 0x0000, 0xfec0 ;; memory mapped address of I/O APIC
  1.6273 -mp_config_irqs:
  1.6274 -  db 3 ;; entry type=I/O interrupt
  1.6275 -  db 0 ;; interrupt type=vectored interrupt
  1.6276 -  db 0,0 ;; flags po=0, el=0 (linux uses as default)
  1.6277 -  db 0 ;; source bus ID is ISA
  1.6278 -  db 0 ;; source bus IRQ
  1.6279 -  db 8 ;; destination I/O APIC ID
  1.6280 -  db 0 ;; destination I/O APIC interrrupt in
  1.6281 -  ;; repeat pattern for interrupts 0-15
  1.6282 -  db 3,0,0,0,0,1,8,1
  1.6283 -  db 3,0,0,0,0,2,8,2
  1.6284 -  db 3,0,0,0,0,3,8,3
  1.6285 -  db 3,0,0,0,0,4,8,4
  1.6286 -  db 3,0,0,0,0,5,8,5
  1.6287 -  db 3,0,0,0,0,6,8,6
  1.6288 -  db 3,0,0,0,0,7,8,7
  1.6289 -  db 3,0,0,0,0,8,8,8
  1.6290 -  db 3,0,0,0,0,9,8,9
  1.6291 -  db 3,0,0,0,0,10,8,10
  1.6292 -  db 3,0,0,0,0,11,8,11
  1.6293 -  db 3,0,0,0,0,12,8,12
  1.6294 -  db 3,0,0,0,0,13,8,13
  1.6295 -  db 3,0,0,0,0,14,8,14
  1.6296 -  db 3,0,0,0,0,15,8,15
  1.6297 -#else
  1.6298 -#  error Sorry, rombios only has configurations for 1, 2, 4 or 8 processors.
  1.6299 -#endif  // if (BX_SMP_PROCESSORS==...)
  1.6300 -
  1.6301 -mp_config_end:   // this label used to find length of mp structure
  1.6302 - db 0
  1.6303 -
  1.6304 -#if (BX_SMP_PROCESSORS>1)
  1.6305 -.align 16
  1.6306 -mp_floating_pointer_structure:
  1.6307 -db 0x5f, 0x4d, 0x50, 0x5f   ; "_MP_" signature
  1.6308 -dw mp_config_table, 0xf ;; pointer to MP configuration table
  1.6309 -db 1     ;; length of this struct in 16-bit byte chunks
  1.6310 -db 4     ;; MP spec revision
  1.6311 -db 0xc1  ;; checksum
  1.6312 -db 0     ;; MP feature byte 1.  value 0 means look at the config table
  1.6313 -db 0,0,0,0     ;; MP feature bytes 2-5.
  1.6314 -#endif
  1.6315 -
  1.6316  ASM_END
  1.6317  
  1.6318 -#endif // HVMASSIST
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/firmware/rombios/rombios.h	Thu Dec 18 14:52:53 2008 +0000
     2.3 @@ -0,0 +1,70 @@
     2.4 +/////////////////////////////////////////////////////////////////////////
     2.5 +// $Id: rombios.h,v 1.8 2008/12/04 18:48:33 sshwarts Exp $
     2.6 +/////////////////////////////////////////////////////////////////////////
     2.7 +//
     2.8 +//  Copyright (C) 2006 Volker Ruppert
     2.9 +//
    2.10 +//  This library is free software; you can redistribute it and/or
    2.11 +//  modify it under the terms of the GNU Lesser General Public
    2.12 +//  License as published by the Free Software Foundation; either
    2.13 +//  version 2 of the License, or (at your option) any later version.
    2.14 +//
    2.15 +//  This library is distributed in the hope that it will be useful,
    2.16 +//  but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.17 +//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    2.18 +//  Lesser General Public License for more details.
    2.19 +//
    2.20 +//  You should have received a copy of the GNU Lesser General Public
    2.21 +//  License along with this library; if not, write to the Free Software
    2.22 +//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
    2.23 +
    2.24 +/* define it to include QEMU specific code */
    2.25 +//#define BX_QEMU
    2.26 +#define LEGACY
    2.27 +
    2.28 +#ifndef LEGACY
    2.29 +#  define BX_ROMBIOS32     1
    2.30 +#else
    2.31 +#  define BX_ROMBIOS32     0
    2.32 +#endif
    2.33 +#define DEBUG_ROMBIOS    1
    2.34 +
    2.35 +#define PANIC_PORT  0x400
    2.36 +#define PANIC_PORT2 0x401
    2.37 +#define INFO_PORT   0x402
    2.38 +#define DEBUG_PORT  0x403
    2.39 +
    2.40 +#define BIOS_PRINTF_HALT     1
    2.41 +#define BIOS_PRINTF_SCREEN   2
    2.42 +#define BIOS_PRINTF_INFO     4
    2.43 +#define BIOS_PRINTF_DEBUG    8
    2.44 +#define BIOS_PRINTF_ALL      (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO)
    2.45 +#define BIOS_PRINTF_DEBHALT  (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO | BIOS_PRINTF_HALT)
    2.46 +
    2.47 +#define printf(format, p...)  bios_printf(BIOS_PRINTF_SCREEN, format, ##p)
    2.48 +
    2.49 +// Defines the output macros.
    2.50 +// BX_DEBUG goes to INFO port until we can easily choose debug info on a
    2.51 +// per-device basis. Debug info are sent only in debug mode
    2.52 +#if DEBUG_ROMBIOS
    2.53 +#  define BX_DEBUG(format, p...)  bios_printf(BIOS_PRINTF_INFO, format, ##p)
    2.54 +#else
    2.55 +#  define BX_DEBUG(format, p...)
    2.56 +#endif
    2.57 +#define BX_INFO(format, p...)   bios_printf(BIOS_PRINTF_INFO, format, ##p)
    2.58 +#define BX_PANIC(format, p...)  bios_printf(BIOS_PRINTF_DEBHALT, format, ##p)
    2.59 +
    2.60 +#define ACPI_DATA_SIZE    0x00010000L
    2.61 +#define PM_IO_BASE        0xb000
    2.62 +#define SMB_IO_BASE       0xb100
    2.63 +
    2.64 +  // Define the application NAME
    2.65 +#if define HVMASSIST
    2.66 +#  define BX_APPNAME "HVMAssist"
    2.67 +#elif defined(BX_QEMU)
    2.68 +#  define BX_APPNAME "QEMU"
    2.69 +#elif defined(PLEX86)
    2.70 +#  define BX_APPNAME "Plex86"
    2.71 +#else
    2.72 +#  define BX_APPNAME "Bochs"
    2.73 +#endif