WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [Patch][RFC] Update rombios.c

To: xen-devel@xxxxxxxxxxxxxxxxxxx, Tim.Deegan@xxxxxxxxxxxxx, samuel.thibault@xxxxxxxxxx, Yu Ke <ke.yu@xxxxxxxxx>, Stefan Berger <stefanb@xxxxxxxxxx>, Ke Liping <liping.ke@xxxxxxxxx>, Juergen Keil <jk@xxxxxxxx>, Keir Fraser <keir.fraser@xxxxxxxxxx>, "Daniel P. Berrange" <berrange@xxxxxxxxxx>, Seiji Munetoh <seiji.munetoh@xxxxxxxxx>, Ben Guthro <bguthro@xxxxxxxxxxxxxx>, Steve Ofsthun <sofsthun@xxxxxxxxxxxxxxx>, Travis Betak <travis.betak@xxxxxxx>, Bruce Rogers <brogers@xxxxxxxxxx>
Subject: [Xen-devel] [Patch][RFC] Update rombios.c
From: Akio Takebe <takebe_akio@xxxxxxxxxxxxxx>
Date: Wed, 17 Dec 2008 23:50:35 +0900
Cc:
Delivery-date: Wed, 17 Dec 2008 06:51:49 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 2.0.0.18 (X11/20081119)
Hi, all

This patch update rombios to the latest Bochs's.
I'd like to corabolate bochs community to enhance the guest bios.
I'm not familiar around TCGBIOS.
So could you review the patch?

I tested boot/shutdown, S3 suspend/resume with linux guest.
Any comments are welcome :-)

Best Regards,

Akio Takebe
diff -r a76b4e00e186 tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c  Tue Dec 16 13:14:25 2008 +0000
+++ b/tools/firmware/rombios/rombios.c  Wed Dec 17 23:38:15 2008 +0900
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////
-// $Id: rombios.c,v 1.138 2005/05/07 15:55:26 vruppert Exp $
+// $Id: rombios.c,v 1.221 2008/12/07 17:32:29 sshwarts Exp $
 /////////////////////////////////////////////////////////////////////////
 //
 //  Copyright (C) 2002  MandrakeSoft S.A.
@@ -22,9 +22,9 @@
 //
 //  You should have received a copy of the GNU Lesser General Public
 //  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-
-// ROM BIOS for use with Bochs/Plex x86 emulation environment
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 
USA
+
+// ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
 
 #define uint8_t unsigned char
 #define uint16_t unsigned short
@@ -81,10 +81,10 @@
 //
 // NOTES for El-Torito Boot (cbbochs@xxxxxxx)
 //   - CD-ROM booting is only available if ATA/ATAPI Driver is available
-//   - Current code is only able to boot mono-session cds 
+//   - Current code is only able to boot mono-session cds
 //   - Current code can not boot and emulate a hard-disk
 //     the bios will panic otherwise
-//   - Current code also use memory in EBDA segement. 
+//   - Current code also use memory in EBDA segement.
 //   - I used cmos byte 0x3D to store extended information on boot-device
 //   - Code has to be modified modified to handle multiple cdrom drives
 //   - Here are the cdrom boot failure codes:
@@ -102,13 +102,13 @@
 //      12 : can not read cd - boot image
 //
 //   ATA driver
-//   - EBDA segment. 
+//   - EBDA segment.
 //     I used memory starting at 0x121 in the segment
 //   - the translation policy is defined in cmos regs 0x39 & 0x3a
 //
 // TODO :
 //
-//   int74 
+//   int74
 //     - needs to be reworked.  Uses direct [bp] offsets. (?)
 //
 //   int13:
@@ -128,13 +128,13 @@
 //   - Implement remaining int13_cdemu functions (as defined by El-Torito 
specs)
 //   - cdrom drive is hardcoded to ide 0 device 1 in several places. see 
"FIXME ElTorito Hardcoded"
 //   - int13 Fix DL when emulating a cd. In that case DL is decremented before 
calling real int13.
-//     This is ok. But DL should be reincremented afterwards. 
+//     This is ok. But DL should be reincremented afterwards.
 //   - Fix all "FIXME ElTorito Various"
 //   - should be able to boot any cdrom instead of the first one
 //
 //   BCC Bug: find a generic way to handle the bug of #asm after an "if"  
(fixed in 0.16.7)
 
-#define DEBUG_ROMBIOS      0
+#include "rombios.h"
 
 #define DEBUG_ATA          0
 #define DEBUG_INT13_HD     0
@@ -159,7 +159,7 @@
 #define BX_USE_ATADRV    1
 #define BX_ELTORITO_BOOT 1
 
-#define BX_TCGBIOS       0              /* main switch for TCG BIOS ext. */
+#define BX_TCGBIOS       0   /* main switch for TCG BIOS ext. */
 
 #define BX_MAX_ATA_INTERFACES   4
 #define BX_MAX_ATA_DEVICES      (BX_MAX_ATA_INTERFACES*2)
@@ -181,7 +181,6 @@
   // EBDA is used for PS/2 mouse support, and IDE BIOS, etc.
 #define EBDA_SEG           0x9FC0
 #define EBDA_SIZE          1              // In KiB
-#define EBDA_SEG_PTR       0x40E /* Find true EBDA segment at 0:40E */
 #define BASE_MEM_IN_K   (640 - EBDA_SIZE)
 
 /* 256 bytes at 0x9ff00 -- 0x9ffff is used for the IPL boot table. */
@@ -189,15 +188,13 @@
 #define IPL_TABLE_ENTRIES    8
 #define IPL_COUNT_OFFSET     0x0380  /* u16: number of valid table entries */
 #define IPL_SEQUENCE_OFFSET  0x0382  /* u16: next boot device */
-
-  // Define the application NAME
-#ifdef HVMASSIST
-#  define BX_APPNAME "HVMAssist"
-#elif PLEX86
-#  define BX_APPNAME "Plex86"
-#else
-#  define BX_APPNAME "Bochs"
-#endif
+#define IPL_BOOTFIRST_OFFSET 0x0384  /* u16: user selected device */
+#define IPL_SIZE             0xff
+#define IPL_TYPE_FLOPPY      0x01
+#define IPL_TYPE_HARDDISK    0x02
+#define IPL_TYPE_CDROM       0x03
+#define IPL_TYPE_BEV         0x80
+
 
   // Sanity Checks
 #if BX_USE_ATADRV && BX_CPU<3
@@ -216,15 +213,10 @@
 #    error APM BIOS can only be used with 386+ cpu
 #endif
 
-#ifndef BX_SMP_PROCESSORS
-#define BX_SMP_PROCESSORS 1
-#    warning BX_SMP_PROCESSORS not defined, defaulting to 1
-#endif
-  
-#define PANIC_PORT  0x400
-#define PANIC_PORT2 0x401
-#define INFO_PORT   0x402
-#define DEBUG_PORT  0x403
+// define this if you want to make PCIBIOS working on a specific bridge only
+// undef enables PCIBIOS when at least one PCI device is found
+// i440FX is emulated by Bochs and QEMU
+#define PCI_FIXED_HOST_BRIDGE 0x12378086 ;; i440FX PCI bridge
 
 // #20  is dec 20
 // #$20 is hex 20 = 32
@@ -257,7 +249,7 @@
 
 MACRO HALT
   ;; the HALT macro is called with the line number of the HALT call.
-  ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex 
+  ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex
   ;; to print a BX_PANIC message.  This will normally halt the simulation
   ;; with a message such as "BIOS panic at rombios.c, line 4091".
   ;; However, users can choose to make panics non-fatal and continue.
@@ -296,9 +288,9 @@
   void memsetb(seg,offset,value,count);
   void memcpyb(dseg,doffset,sseg,soffset,count);
   void memcpyd(dseg,doffset,sseg,soffset,count);
-  
+
   // memset of count bytes
-    void 
+    void
   memsetb(seg,offset,value,count)
     Bit16u seg;
     Bit16u offset;
@@ -308,14 +300,14 @@
   ASM_START
     push bp
     mov  bp, sp
-  
+
       push ax
       push cx
       push es
       push di
-  
+
       mov  cx, 10[bp] ; count
-      cmp  cx, #0x00
+      test cx, cx
       je   memsetb_end
       mov  ax, 4[bp] ; segment
       mov  es, ax
@@ -325,19 +317,19 @@
       cld
       rep
        stosb
-  
+
   memsetb_end:
       pop di
       pop es
       pop cx
       pop ax
-  
+
     pop bp
   ASM_END
   }
-  
+
   // memcpy of count bytes
-    void 
+    void
   memcpyb(dseg,doffset,sseg,soffset,count)
     Bit16u dseg;
     Bit16u doffset;
@@ -348,16 +340,16 @@
   ASM_START
     push bp
     mov  bp, sp
-  
+
       push ax
       push cx
       push es
       push di
       push ds
       push si
-  
+
       mov  cx, 12[bp] ; count
-      cmp  cx, #0x0000
+      test cx, cx
       je   memcpyb_end
       mov  ax, 4[bp] ; dsegment
       mov  es, ax
@@ -370,7 +362,7 @@
       cld
       rep
        movsb
-  
+
   memcpyb_end:
       pop si
       pop ds
@@ -378,14 +370,13 @@
       pop es
       pop cx
       pop ax
-  
+
     pop bp
   ASM_END
   }
 
-#if 0 
   // memcpy of count dword
-    void 
+    void
   memcpyd(dseg,doffset,sseg,soffset,count)
     Bit16u dseg;
     Bit16u doffset;
@@ -396,16 +387,16 @@
   ASM_START
     push bp
     mov  bp, sp
-  
+
       push ax
       push cx
       push es
       push di
       push ds
       push si
-  
+
       mov  cx, 12[bp] ; count
-      cmp  cx, #0x0000
+      test cx, cx
       je   memcpyd_end
       mov  ax, 4[bp] ; dsegment
       mov  es, ax
@@ -418,7 +409,7 @@
       cld
       rep
        movsd
-  
+
   memcpyd_end:
       pop si
       pop ds
@@ -426,16 +417,15 @@
       pop es
       pop cx
       pop ax
-  
+
     pop bp
   ASM_END
   }
-#endif
 
   // read_dword and write_dword functions
   static Bit32u         read_dword();
   static void           write_dword();
-  
+
     Bit32u
   read_dword(seg, offset)
     Bit16u seg;
@@ -444,25 +434,24 @@
   ASM_START
     push bp
     mov  bp, sp
-  
+
       push bx
       push ds
       mov  ax, 4[bp] ; segment
       mov  ds, ax
       mov  bx, 6[bp] ; offset
       mov  ax, [bx]
-      inc  bx
-      inc  bx
+      add  bx, #2
       mov  dx, [bx]
       ;; ax = return value (word)
       ;; dx = return value (word)
       pop  ds
       pop  bx
-  
+
     pop  bp
   ASM_END
   }
-  
+
     void
   write_dword(seg, offset, data)
     Bit16u seg;
@@ -472,7 +461,7 @@
   ASM_START
     push bp
     mov  bp, sp
-  
+
       push ax
       push bx
       push ds
@@ -481,50 +470,49 @@
       mov  bx, 6[bp] ; offset
       mov  ax, 8[bp] ; data word
       mov  [bx], ax  ; write data word
-      inc  bx
-      inc  bx
+      add  bx, #2
       mov  ax, 10[bp] ; data word
       mov  [bx], ax  ; write data word
       pop  ds
       pop  bx
       pop  ax
-  
+
     pop  bp
   ASM_END
   }
-  
+
   // Bit32u (unsigned long) and long helper functions
   ASM_START
-  
+
   ;; and function
   landl:
   landul:
-    SEG SS 
+    SEG SS
       and ax,[di]
-    SEG SS 
+    SEG SS
       and bx,2[di]
     ret
-  
+
   ;; add function
   laddl:
   laddul:
-    SEG SS 
+    SEG SS
       add ax,[di]
-    SEG SS 
+    SEG SS
       adc bx,2[di]
     ret
-  
+
   ;; cmp function
   lcmpl:
   lcmpul:
     and eax, #0x0000FFFF
     shl ebx, #16
-    add eax, ebx
+    or  eax, ebx
     shr ebx, #16
     SEG SS
       cmp eax, dword ptr [di]
     ret
-  
+
   ;; sub function
   lsubl:
   lsubul:
@@ -533,26 +521,26 @@
     SEG SS
     sbb bx,2[di]
     ret
-  
+
   ;; mul function
   lmull:
   lmulul:
     and eax, #0x0000FFFF
     shl ebx, #16
-    add eax, ebx
+    or  eax, ebx
     SEG SS
     mul eax, dword ptr [di]
     mov ebx, eax
     shr ebx, #16
     ret
-  
+
   ;; dec function
   ldecl:
   ldecul:
     SEG SS
     dec dword ptr [bx]
     ret
-  
+
   ;; or function
   lorl:
   lorul:
@@ -561,31 +549,31 @@
     SEG SS
     or  bx,2[di]
     ret
-  
+
   ;; inc function
   lincl:
   lincul:
     SEG SS
     inc dword ptr [bx]
     ret
-  
+
   ;; tst function
   ltstl:
   ltstul:
     and eax, #0x0000FFFF
     shl ebx, #16
-    add eax, ebx
+    or  eax, ebx
     shr ebx, #16
     test eax, eax
     ret
-  
+
   ;; sr function
   lsrul:
     mov  cx,di
     jcxz lsr_exit
     and  eax, #0x0000FFFF
     shl  ebx, #16
-    add  eax, ebx
+    or   eax, ebx
   lsr_loop:
     shr  eax, #1
     loop lsr_loop
@@ -593,7 +581,7 @@
     shr  ebx, #16
   lsr_exit:
     ret
-  
+
   ;; sl function
   lsll:
   lslul:
@@ -601,15 +589,15 @@
     jcxz lsl_exit
     and  eax, #0x0000FFFF
     shl  ebx, #16
-    add  eax, ebx
-  lsl_loop: 
+    or   eax, ebx
+  lsl_loop:
     shl  eax, #1
     loop lsl_loop
     mov  ebx, eax
     shr  ebx, #16
   lsl_exit:
     ret
-  
+
   idiv_:
     cwd
     idiv bx
@@ -623,7 +611,7 @@
   ldivul:
     and  eax, #0x0000FFFF
     shl  ebx, #16
-    add  eax, ebx
+    or   eax, ebx
     xor  edx, edx
     SEG SS
     mov  bx,  2[di]
@@ -672,7 +660,7 @@
     Bit8u  revision;
     Bit8u  checksum;
     } dpte_t;
- 
+
   typedef struct {
     Bit8u  iface;        // ISA or PCI
     Bit16u iobase1;      // IO Base 1
@@ -685,15 +673,15 @@
     Bit8u  device;       // Detected type of attached devices (hd/cd/none)
     Bit8u  removable;    // Removable device flag
     Bit8u  lock;         // Locks for removable devices
-    // Bit8u  lba_capable;  // LBA capable flag - always yes for bochs devices
-    Bit8u  mode;         // transfert mode : PIO 16/32 bits - IRQ - ISADMA - 
PCIDMA
+    Bit8u  mode;         // transfer mode : PIO 16/32 bits - IRQ - ISADMA - 
PCIDMA
     Bit16u blksize;      // block size
 
     Bit8u  translation;  // type of translation
     chs_t  lchs;         // Logical CHS
     chs_t  pchs;         // Physical CHS
 
-    Bit32u sectors;      // Total sectors count
+    Bit32u sectors_low;  // Total sectors count
+    Bit32u sectors_high;
     } ata_device_t;
 
   typedef struct {
@@ -704,10 +692,10 @@
     ata_device_t  devices[BX_MAX_ATA_DEVICES];
     //
     // map between (bios hd id - 0x80) and ata channels
-    Bit8u  hdcount, hdidmap[BX_MAX_ATA_DEVICES];                
+    Bit8u  hdcount, hdidmap[BX_MAX_ATA_DEVICES];
 
     // map between (bios cd id - 0xE0) and ata channels
-    Bit8u  cdcount, cdidmap[BX_MAX_ATA_DEVICES];                
+    Bit8u  cdcount, cdidmap[BX_MAX_ATA_DEVICES];
 
     // Buffer for DPTE table
     dpte_t dpte;
@@ -717,9 +705,9 @@
     Bit32u trsfbytes;
 
     } ata_t;
-  
-#if BX_ELTORITO_BOOT
-  // ElTorito Device Emulation data 
+
+#if BX_ELTORITO_BOOT
+  // ElTorito Device Emulation data
   typedef struct {
     Bit8u  active;
     Bit8u  media;
@@ -730,20 +718,20 @@
     Bit16u buffer_segment;
     Bit16u load_segment;
     Bit16u sector_count;
-    
+
     // Virtual device
     chs_t  vdevice;
     } cdemu_t;
 #endif // BX_ELTORITO_BOOT
-  
+
 #include "32bitgateway.h"
 
   // for access to EBDA area
-  //     The EBDA structure should conform to 
-  //     http://www.cybertrails.com/~fys/rombios.htm document
+  //     The EBDA structure should conform to
+  //     http://www.frontiernet.net/~fys/rombios.htm document
   //     I made the ata and cdemu structs begin at 0x121 in the EBDA seg
-  // EBDA must be at most 768 bytes; it lives at 0x9fc00, and the boot 
-  // device tables are at 0x9ff00 -- 0x9ffff
+  // EBDA must be at most 768 bytes; it lives at EBDA_SEG, and the boot
+  // device tables are at EBDA_SEG:IPL_TABLE_OFFSET
   typedef struct {
     unsigned char ebda_size;
     unsigned char cmos_shutdown_status;
@@ -765,7 +753,7 @@
 
     upcall_t upcall;
     } ebda_data_t;
-  
+
   #define EBDA_CMOS_SHUTDOWN_STATUS_OFFSET 1
   #define EbdaData ((ebda_data_t *) 0)
 
@@ -779,7 +767,7 @@
     Bit32u lba1;
     Bit32u lba2;
     } int13ext_t;
- 
+
   #define Int13Ext ((int13ext_t *) 0)
 
   // Disk Physical Table definition
@@ -805,7 +793,7 @@
     Bit8u   reserved3;
     Bit8u   checksum;
     } dpt_t;
- 
+
   #define Int13DPT ((dpt_t *) 0)
 
 #endif // BX_USE_ATADRV
@@ -835,9 +823,9 @@
     } r16;
   struct {
     Bit32u filler[4];
-    Bit8u  bl, bh; 
+    Bit8u  bl, bh;
     Bit16u filler1;
-    Bit8u  dl, dh; 
+    Bit8u  dl, dh;
     Bit16u filler2;
     Bit8u  cl, ch;
     Bit16u filler3;
@@ -870,6 +858,14 @@
   Bit16u cs;
   flags_t flags;
   } iret_addr_t;
+
+typedef struct {
+  Bit16u type;
+  Bit16u flags;
+  Bit32u vector;
+  Bit32u description;
+  Bit32u reserved;
+  } ipl_entry_t;
 
 
 
@@ -910,8 +906,6 @@
 static void           int70_function();
 static void           int74_function();
 static Bit16u         get_CS();
-//static Bit16u         get_DS();
-//static void           set_DS();
 static Bit16u         get_SS();
 static unsigned int   enqueue_key();
 static unsigned int   dequeue_key();
@@ -930,7 +924,10 @@
 static void           keyboard_panic();
 static void           shutdown_status_panic();
 static void           nmi_handler_msg();
-
+static void           delay_ticks();
+static void           delay_ticks_and_check_for_keystroke();
+
+static void           interactive_bootkey();
 static void           print_bios_banner();
 static void           print_boot_device();
 static void           print_boot_failure();
@@ -964,33 +961,9 @@
 
 #endif // BX_ELTORITO_BOOT
 
-static char bios_cvs_version_string[] = "$Revision: 1.138 $";
-static char bios_date_string[] = "$Date: 2005/05/07 15:55:26 $";
-
-static char CVSID[] = "$Id: rombios.c,v 1.138 2005/05/07 15:55:26 vruppert Exp 
$";
-
-/* Offset to skip the CVS $Id: prefix */ 
-#define bios_version_string  (CVSID + 4)
-
-#define BIOS_PRINTF_HALT     1
-#define BIOS_PRINTF_SCREEN   2
-#define BIOS_PRINTF_INFO     4
-#define BIOS_PRINTF_DEBUG    8
-#define BIOS_PRINTF_ALL      (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO)
-#define BIOS_PRINTF_DEBHALT  (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO | 
BIOS_PRINTF_HALT)
-
-#define printf(format, p...)  bios_printf(BIOS_PRINTF_SCREEN, format, ##p)
-
-// Defines the output macros. 
-// BX_DEBUG goes to INFO port until we can easily choose debug info on a 
-// per-device basis. Debug info are sent only in debug mode
-#if DEBUG_ROMBIOS
-#  define BX_DEBUG(format, p...)  bios_printf(BIOS_PRINTF_INFO, format, ##p)   
 
-#else
-#  define BX_DEBUG(format, p...) 
-#endif
-#define BX_INFO(format, p...)   bios_printf(BIOS_PRINTF_INFO, format, ##p)
-#define BX_PANIC(format, p...)  bios_printf(BIOS_PRINTF_DEBHALT, format, ##p)
+static char bios_cvs_version_string[] = "$Revision: 1.221 $ $Date: 2008/12/07 
17:32:29 $";
+
+#define BIOS_COPYRIGHT_STRING "(c) 2002 MandrakeSoft S.A. Written by Kevin 
Lawton & the Bochs team."
 
 #if DEBUG_ATA
 #  define BX_DEBUG_ATA(a...) BX_DEBUG(a)
@@ -1163,9 +1136,9 @@
       { 0x5100, 0x5133, 0x7600,   none, 0x20 }, /* 3 PgDn */
       { 0x5200, 0x5230,   none,   none, 0x20 }, /* 0 Ins */
       { 0x5300, 0x532e,   none,   none, 0x20 }, /* Del */
-      {   none,   none,   none,   none, none }, /* ??? */
-      {   none,   none,   none,   none, none }, /* ??? */
-      {   none,   none,   none,   none, none }, /* ??? */
+      {   none,   none,   none,   none, none },
+      {   none,   none,   none,   none, none },
+      { 0x565c, 0x567c,   none,   none, none }, /* \| */
       { 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */
       { 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */
       };
@@ -1422,31 +1395,6 @@
 ASM_END
 }
 
-//  Bit16u
-//get_DS()
-//{
-//ASM_START
-//  mov  ax, ds
-//ASM_END
-//}
-//
-//  void
-//set_DS(ds_selector)
-//  Bit16u ds_selector;
-//{
-//ASM_START
-//  push bp
-//  mov  bp, sp
-//
-//    push ax
-//    mov  ax, 4[bp] ; ds_selector
-//    mov  ds, ax
-//    pop  ax
-//
-//  pop  bp
-//ASM_END
-//}
-
   Bit16u
 get_SS()
 {
@@ -1462,7 +1410,7 @@
   Bit8u nr_entries = read_byte(0x9000, 0x1e8);
   Bit32u base_mem;
   if (nr_entries > 32)
-       nr_entries = 32;
+       nr_entries = 32;
   write_word(0xe000, 0x8, nr_entries);
   memcpyb(0xe000, 0x10, 0x9000, 0x2d0, nr_entries * 0x14);
   /* Report the proper base memory size at address 0x0413: otherwise
@@ -1570,7 +1518,7 @@
   pop  bp
   ASM_END
 }
- 
+
   void
 send(action, c)
   Bit16u action;
@@ -1626,14 +1574,121 @@
   send(action, val - (nval * 10) + '0');
 }
 
+  void
+put_luint(action, val, width, neg)
+  Bit16u action;
+  unsigned long val;
+  short width;
+  bx_bool neg;
+{
+  unsigned long nval = val / 10;
+  if (nval)
+    put_luint(action, nval, width - 1, neg);
+  else {
+    while (--width > 0) send(action, ' ');
+    if (neg) send(action, '-');
+  }
+  send(action, val - (nval * 10) + '0');
+}
+
+void put_str(action, segment, offset)
+  Bit16u action;
+  Bit16u segment;
+  Bit16u offset;
+{
+  Bit8u c;
+
+  while (c = read_byte(segment, offset)) {
+    send(action, c);
+    offset++;
+  }
+}
+
+  void
+delay_ticks(ticks)
+  Bit16u ticks;
+{
+  long ticks_to_wait, delta;
+  Bit32u prev_ticks, t;
+
+   /*
+    * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock.
+    * We also have to be careful about interrupt storms.
+    */
+ASM_START
+  pushf
+  sti
+ASM_END
+  ticks_to_wait = ticks;
+  prev_ticks = read_dword(0x0, 0x46c);
+  do
+  {
+ASM_START
+    hlt
+ASM_END
+    t = read_dword(0x0, 0x46c);
+    if (t > prev_ticks)
+    {
+      delta = t - prev_ticks;     /* The temp var is required or bcc screws 
up. */
+      ticks_to_wait -= delta;
+    }
+    else if (t < prev_ticks)
+    {
+      ticks_to_wait -= t;         /* wrapped */
+    }
+
+    prev_ticks = t;
+  } while (ticks_to_wait > 0);
+ASM_START
+  cli
+  popf
+ASM_END
+}
+
+  Bit8u
+check_for_keystroke()
+{
+ASM_START
+  mov  ax, #0x100
+  int  #0x16
+  jz   no_key
+  mov  al, #1
+  jmp  done
+no_key:
+  xor  al, al
+done:
+ASM_END
+}
+
+  Bit8u
+get_keystroke()
+{
+ASM_START
+  mov  ax, #0x0
+  int  #0x16
+  xchg ah, al
+ASM_END
+}
+
+  void
+delay_ticks_and_check_for_keystroke(ticks, count)
+  Bit16u ticks, count;
+{
+  Bit16u i;
+  for (i = 1; i <= count; i++) {
+    delay_ticks(ticks);
+    if (check_for_keystroke())
+      break;
+  }
+}
+
 //--------------------------------------------------------------------------
 // bios_printf()
-//   A compact variable argument printf function which prints its output via
-//   an I/O port so that it can be logged by Bochs/Plex.  
-//   Currently, only %x is supported (or %02x, %04x, etc).
-//
-//   Supports %[format_width][format]
-//   where format can be d,x,c,s
+//   A compact variable argument printf function.
+//
+//   Supports %[format_width][length]format
+//   where format can be x,X,u,d,s,S,c
+//   and the optional length modifier is l (ell)
 //--------------------------------------------------------------------------
   void
 bios_printf(action, s)
@@ -1644,7 +1699,7 @@
   bx_bool  in_format;
   short i;
   Bit16u  *arg_ptr;
-  Bit16u   arg_seg, arg, nibble, shift_count, format_width;
+  Bit16u   arg_seg, arg, nibble, hibyte, shift_count, format_width, hexadd;
 
   arg_ptr = &s;
   arg_seg = get_SS();
@@ -1671,16 +1726,48 @@
       else {
         arg_ptr++; // increment to next arg
         arg = read_word(arg_seg, arg_ptr);
-        if (c == 'x') {
+        if (c == 'x' || c == 'X') {
           if (format_width == 0)
             format_width = 4;
+          if (c == 'x')
+            hexadd = 'a';
+          else
+            hexadd = 'A';
           for (i=format_width-1; i>=0; i--) {
             nibble = (arg >> (4 * i)) & 0x000f;
-            send (action, (nibble<=9)? (nibble+'0') : (nibble-10+'A'));
+            send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
             }
           }
         else if (c == 'u') {
           put_uint(action, arg, format_width, 0);
+          }
+        else if (c == 'l') {
+          s++;
+          c = read_byte(get_CS(), s); /* is it ld,lx,lu? */
+          arg_ptr++; /* increment to next arg */
+          hibyte = read_word(arg_seg, arg_ptr);
+          if (c == 'd') {
+            if (hibyte & 0x8000)
+              put_luint(action, 0L-(((Bit32u) hibyte << 16) | arg), 
format_width-1, 1);
+            else
+              put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 
0);
+           }
+          else if (c == 'u') {
+            put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0);
+           }
+          else if (c == 'x' || c == 'X')
+           {
+            if (format_width == 0)
+              format_width = 8;
+            if (c == 'x')
+              hexadd = 'a';
+            else
+              hexadd = 'A';
+            for (i=format_width-1; i>=0; i--) {
+              nibble = ((((Bit32u) hibyte <<16) | arg) >> (4 * i)) & 0x000f;
+              send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
+              }
+           }
           }
         else if (c == 'd') {
           if (arg & 0x8000)
@@ -1689,7 +1776,13 @@
             put_int(action, arg, format_width, 0);
           }
         else if (c == 's') {
-          bios_printf(action & (~BIOS_PRINTF_HALT), arg);
+          put_str(action, get_CS(), arg);
+          }
+        else if (c == 'S') {
+          hibyte = arg;
+          arg_ptr++;
+          arg = read_word(arg_seg, arg_ptr);
+          put_str(action, hibyte, arg);
           }
         else if (c == 'c') {
           send(action, arg);
@@ -1706,7 +1799,7 @@
     }
 
   if (action & BIOS_PRINTF_HALT) {
-    // freeze in a busy loop.  
+    // freeze in a busy loop.
 ASM_START
     cli
  halt2_loop:
@@ -1740,8 +1833,8 @@
             max = 0x2000;
             }
         }
-  
-    // Due to timer issues, and if the IPS setting is > 15000000, 
+
+    // Due to timer issues, and if the IPS setting is > 15000000,
     // the incoming keys might not be flushed here. That will
     // cause a panic a few lines below.  See sourceforge bug report :
     // [ 642031 ] FATAL: Keyboard RESET error:993
@@ -1878,12 +1971,11 @@
 keyboard_panic(status)
   Bit16u status;
 {
-  // If you're getting a 993 keyboard panic here, 
+  // If you're getting a 993 keyboard panic here,
   // please see the comment in keyboard_init
-  
+
   BX_PANIC("Keyboard error:%u\n",status);
 }
-
 
 #define CMOS_SHUTDOWN_S3 0xFE
 //--------------------------------------------------------------------------
@@ -1939,6 +2031,11 @@
   BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status);
 }
 
+void s3_resume_panic()
+{
+  BX_PANIC("Returned from s3_resume.\n");
+}
+
 //--------------------------------------------------------------------------
 // print_bios_banner
 //   displays a the bios version
@@ -1946,74 +2043,84 @@
 void
 print_bios_banner()
 {
-  printf(BX_APPNAME" BIOS, %d cpu%s, ", BX_SMP_PROCESSORS, 
BX_SMP_PROCESSORS>1?"s":"");
-  printf("%s %s\n", bios_cvs_version_string, bios_date_string);
+  printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ",
+    BIOS_BUILD_DATE, bios_cvs_version_string);
+  printf(
+#if BX_APM
+  "apmbios "
+#endif
+#if BX_PCIBIOS
+  "pcibios "
+#endif
+#if BX_ELTORITO_BOOT
+  "eltorito "
+#endif
+#if BX_ROMBIOS32
+  "rombios32 "
+#endif
 #if BX_TCGBIOS
-  printf("TCG-enabled BIOS.\n");
-#endif
-  printf("\n");
-}
-
+  "TCG-enabled"
+#endif
+  "\n\n");
+}
 
 //--------------------------------------------------------------------------
 // BIOS Boot Specification 1.0.1 compatibility
 //
-// Very basic support for the BIOS Boot Specification, which allows expansion 
-// ROMs to register themselves as boot devices, instead of just stealing the 
+// Very basic support for the BIOS Boot Specification, which allows expansion
+// ROMs to register themselves as boot devices, instead of just stealing the
 // INT 19h boot vector.
-// 
+//
 // This is a hack: to do it properly requires a proper PnP BIOS and we aren't
-// one; we just lie to the option ROMs to make them behave correctly. 
-// We also don't support letting option ROMs register as bootable disk 
-// drives (BCVs), only as bootable devices (BEVs). 
+// one; we just lie to the option ROMs to make them behave correctly.
+// We also don't support letting option ROMs register as bootable disk
+// drives (BCVs), only as bootable devices (BEVs).
 //
 // 
http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm
 //--------------------------------------------------------------------------
 
-struct ipl_entry {
-  Bit16u type;
-  Bit16u flags;
-  Bit32u vector;
-  Bit32u description;
-  Bit32u reserved;
-};
-
-static void 
-init_boot_vectors() 
-{
-  struct ipl_entry e; 
+static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};
+
+static void
+init_boot_vectors()
+{
+  ipl_entry_t e;
   Bit16u count = 0;
   Bit16u ss = get_SS();
+  Bit16u ebda_seg = read_word(0x0040, 0x000E);
 
   /* Clear out the IPL table. */
-  memsetb(EBDA_SEG, IPL_TABLE_OFFSET, 0, 0xff);
+  memsetb(ebda_seg, IPL_TABLE_OFFSET, 0, IPL_SIZE);
+
+  /* User selected device not set */
+  write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, 0xFFFF);
 
   /* Floppy drive */
-  e.type = 1; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
-  memcpyb(EBDA_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
+  e.type = IPL_TYPE_FLOPPY; e.flags = 0; e.vector = 0; e.description = 0; 
e.reserved = 0;
+  memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
   count++;
 
   /* First HDD */
-  e.type = 2; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
-  memcpyb(EBDA_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
+  e.type = IPL_TYPE_HARDDISK; e.flags = 0; e.vector = 0; e.description = 0; 
e.reserved = 0;
+  memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
   count++;
 
 #if BX_ELTORITO_BOOT
   /* CDROM */
-  e.type = 3; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
-  memcpyb(EBDA_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
+  e.type = IPL_TYPE_CDROM; e.flags = 0; e.vector = 0; e.description = 0; 
e.reserved = 0;
+  memcpyb(ebda_seg, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
   count++;
-#endif  
+#endif
 
   /* Remember how many devices we have */
-  write_word(EBDA_SEG, IPL_COUNT_OFFSET, count);
+  write_word(ebda_seg, IPL_COUNT_OFFSET, count);
   /* Not tried booting anything yet */
-  write_word(EBDA_SEG, IPL_SEQUENCE_OFFSET, 0xffff);
+  write_word(ebda_seg, IPL_SEQUENCE_OFFSET, 0xffff);
 }
 
 static Bit8u
 get_boot_vector(i, e)
-Bit16u i; struct ipl_entry *e; 
+Bit16u i; ipl_entry_t *e;
 {
   Bit16u count;
   Bit16u ss = get_SS();
@@ -2026,22 +2133,107 @@
   return 1;
 }
 
+#if BX_ELTORITO_BOOT
+  void
+interactive_bootkey()
+{
+  ipl_entry_t e;
+  Bit16u count;
+  char description[33];
+  Bit8u scan_code;
+  Bit8u i;
+  Bit16u ss = get_SS();
+  Bit16u valid_choice = 0;
+  Bit16u ebda_seg = read_word(0x0040, 0x000E);
+
+  while (check_for_keystroke())
+    get_keystroke();
+
+  printf("\nPress F12 for boot menu.\n\n");
+
+  delay_ticks_and_check_for_keystroke(11, 5); /* ~3 seconds */
+  if (check_for_keystroke())
+  {
+    scan_code = get_keystroke();
+    if (scan_code == 0x86) /* F12 */
+    {
+      while (check_for_keystroke())
+        get_keystroke();
+
+      printf("Select boot device:\n\n");
+
+      count = read_word(ebda_seg, IPL_COUNT_OFFSET);
+      for (i = 0; i < count; i++)
+      {
+        memcpyb(ss, &e, ebda_seg, IPL_TABLE_OFFSET + i * sizeof (e), sizeof 
(e));
+        printf("%d. ", i+1);
+        switch(e.type)
+        {
+          case IPL_TYPE_FLOPPY:
+          case IPL_TYPE_HARDDISK:
+          case IPL_TYPE_CDROM:
+            printf("%s\n", drivetypes[e.type]);
+            break;
+          case IPL_TYPE_BEV:
+            printf("%s", drivetypes[4]);
+            if (e.description != 0)
+            {
+              memcpyb(ss, &description, (Bit16u)(e.description >> 16), 
(Bit16u)(e.description & 0xffff), 32);
+              description[32] = 0;
+              printf(" [%S]", ss, description);
+           }
+           printf("\n");
+           break;
+        }
+      }
+
+      count++;
+      while (!valid_choice) {
+        scan_code = get_keystroke();
+        if (scan_code == 0x01 || scan_code == 0x58) /* ESC or F12 */
+        {
+          valid_choice = 1;
+        }
+        else if (scan_code <= count)
+        {
+          valid_choice = 1;
+          scan_code -= 1;
+          /* Set user selected device */
+          write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, scan_code);
+        }
+      }
+    printf("\n");
+    }
+  }
+}
+#endif // BX_ELTORITO_BOOT
 
 //--------------------------------------------------------------------------
 // print_boot_device
 //   displays the boot device
 //--------------------------------------------------------------------------
 
-static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};
-
 void
-print_boot_device(type)
+print_boot_device(e)
+  ipl_entry_t *e;
+{
   Bit16u type;
-{
-  /* NIC appears as type 0x80 */ 
-  if (type == 0x80 ) type = 0x4;
-  if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n"); 
-  printf("Booting from %s...\n", drivetypes[type]);
+  char description[33];
+  Bit16u ss = get_SS();
+  type = e->type;
+  /* NIC appears as type 0x80 */
+  if (type == IPL_TYPE_BEV) type = 0x4;
+  if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n");
+  printf("Booting from %s", drivetypes[type]);
+  /* print product string if BEV */
+  if (type == 4 && e->description != 0) {
+    /* first 32 bytes are significant */
+    memcpyb(ss, &description, (Bit16u)(e->description >> 16), 
(Bit16u)(e->description & 0xffff), 32);
+    /* terminate string */
+    description[32] = 0;
+    printf(" [%S]", ss, description);
+  }
+  printf("...\n");
 }
 
 //--------------------------------------------------------------------------
@@ -2052,17 +2244,17 @@
 print_boot_failure(type, reason)
   Bit16u type; Bit8u reason;
 {
-  if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n"); 
+  if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n");
 
   printf("Boot from %s failed", drivetypes[type]);
   if (type < 4) {
     /* Report the reason too */
-  if (reason==0) 
-    printf(": not a bootable disk");
-  else
-    printf(": could not read the boot disk");
-  }
-  printf("\n");
+    if (reason==0)
+      printf(": not a bootable disk");
+    else
+      printf(": could not read the boot disk");
+  }
+  printf("\n\n");
 }
 
 //--------------------------------------------------------------------------
@@ -2074,219 +2266,9 @@
   Bit16u code;
 {
   bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "CDROM boot failure code 
: %04x\n",code);
-  
+
   return;
 }
-
-#define WAIT_HZ 18
-/**
- * Check for keystroke.
- * @returns    True if keystroke available, False if not.
- */
-Bit8u check_for_keystroke()
-{
-ASM_START
-    mov  ax, #0x100
-    int  #0x16
-    jz   no_key
-    mov  al, #1
-    jmp  done
-no_key:
-    xor  al, al
-done:
-ASM_END
-}
-
-/**
- * Get keystroke.
- * @returns    BIOS scan code.
- */
-Bit8u get_keystroke()
-{
-ASM_START
-    mov  ax, #0x0
-    int  #0x16
-    xchg ah, al
-ASM_END
-}
-
-/**
- * Waits (sleeps) for the given number of ticks.
- * Checks for keystroke.
- *
- * @returns BIOS scan code if available, 0 if not.
- * @param   ticks       Number of ticks to sleep.
- * @param   stop_on_key Whether to stop immediately upon keypress.
- */
-Bit8u wait(ticks, stop_on_key)
-  Bit16u ticks;
-  Bit8u stop_on_key;
-{
-    long ticks_to_wait, delta;
-    Bit32u prev_ticks, t;
-    Bit8u scan_code = 0;
-
-    /*
-     * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock.
-     * We also have to be careful about interrupt storms.
-     */
-    ticks_to_wait = ticks;
-    prev_ticks = read_dword(0x0, 0x46c);
-    do
-    {
-        t = read_dword(0x0, 0x46c);
-        if (t > prev_ticks)
-        {
-            delta = t - prev_ticks;     /* The temp var is required or bcc 
screws up. */
-            ticks_to_wait -= delta;
-        }
-        else if (t < prev_ticks)
-            ticks_to_wait -= t;         /* wrapped */
-        prev_ticks = t;
-
-        if (check_for_keystroke())
-        {
-            scan_code = get_keystroke();
-            bios_printf(BIOS_PRINTF_DEBUG, "Key pressed: %x\n", scan_code);
-            if (stop_on_key)
-                return scan_code;
-        }
-    } while (ticks_to_wait > 0);
-    return scan_code;
-}
-
-static void clearscreen() {
-    /* Hide cursor, clear screen and move cursor to starting position */
-ASM_START
-        push bx
-        push cx
-        push dx
-
-        mov  ax, #0x100
-        mov  cx, #0x1000
-        int  #0x10
-
-        mov  ax, #0x700
-        mov  bh, #7
-        xor  cx, cx
-        mov  dx, #0x184f
-        int  #0x10
-
-        mov  ax, #0x200
-        xor  bx, bx
-        xor  dx, dx
-        int  #0x10
-
-        pop  dx
-        pop  cx
-        pop  bx
-ASM_END
-}
-
-int bootmenu(selected)
-  int selected;
-{
-    Bit8u scode;
-    int max;
-    Bit16u ebda_seg = read_word(0x0040, 0x000E);
-
-    /* get the number of boot devices */
-    max = read_word(ebda_seg, IPL_COUNT_OFFSET);
-
-    for(;;) {
-        if (selected > max || selected < 1) selected = 1;
-        clearscreen();
-        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n\n\n\n\n\n");
-        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "          Select 
boot device\n\n");
-        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "            1. 
Floppy\n");
-        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "            2. 
Hard drive\n");
-        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "            3. 
CD-ROM\n");
-        if (max == 4)
-            bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "            4. 
Network\n");
-        bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "\n\n          
Currently selected: %d\n", selected);
-
-        do {
-            scode = wait(WAIT_HZ, 1);
-        } while (scode == 0);
-        switch(scode) {
-        case 0x02:
-        case 0x03:
-        case 0x04:
-            selected = scode - 1;
-            break;
-        case 0x05:
-            if (max == 4)
-                selected = scode -1 ;
-            else
-                scode = 0;
-            break;
-        case 0x48:
-            selected -= 1;
-            if (selected < 1)
-                selected = 1;
-            scode = 0;
-            break;
-        case 0x50:
-            selected += 1;
-            if (selected > max)
-                selected = max;
-            scode = 0;
-            break;
-        case 0x1c:
-            break;
-        default:
-            scode = 0;
-            break;
-        }
-        if (scode != 0)
-            break;
-    }
-
-    switch (selected) {
-    case 1:
-        return 0x3D;
-    case 2:
-        return 0x3E;
-    case 3:
-        return 0x3F;
-    case 4:
-        return 0x58;
-    default:
-        return 0;
-    }
-}
-
-void interactive_bootkey()
-{
-    Bit16u i;
-    Bit8u scan = 0;
-
-    bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO,
-                "\n\nPress F10 to select boot device.\n");
-
-    scan = wait(1, 0);
-    if (scan == 0x44)
-        scan = bootmenu(inb_cmos(0x3d) & 0x0f);
-
-    /* set the default based on the keypress or menu */
-    switch(scan) {
-    case 0x3D:
-        outb_cmos(0x3d, 0x01);
-        break;
-    case 0x3E:
-        outb_cmos(0x3d, 0x02);
-        break;
-    case 0x3F:
-        outb_cmos(0x3d, 0x03);
-        break;
-    case 0x58:
-        outb_cmos(0x3d, 0x04);
-        break;
-    default:
-        break;
-    }
-}
-
 
 void
 nmi_handler_msg()
@@ -2306,7 +2288,7 @@
 #if BX_DEBUG_SERIAL
   outb(BX_DEBUG_PORT+UART_LCR, 0x03); /* setup for serial logging: 8N1 */
 #endif
-  BX_INFO("%s\n", bios_version_string);
+  BX_INFO("%s\n", bios_cvs_version_string);
 }
 
   bx_bool
@@ -2341,41 +2323,35 @@
   outb(0xfedc, 0x00);
 }
 
-void 
+int
 s3_resume()
 {
     Bit32u s3_wakeup_vector;
-    Bit16u s3_wakeup_ip, s3_wakeup_cs;
-    Bit8u cmos_shutdown_status;
-
-ASM_START
-    push ds
-    push ax
-    xor ax, ax
-    mov ds, ax
-    mov ax, word ptr [EBDA_SEG_PTR]
-    mov ds, ax
-    mov al, [EBDA_CMOS_SHUTDOWN_STATUS_OFFSET]
-    mov .s3_resume.cmos_shutdown_status[bp], al
-    pop ax
-    pop ds
-ASM_END
-
-    if (cmos_shutdown_status != CMOS_SHUTDOWN_S3)
-        return;
-
+    Bit8u s3_resume_flag;
+
+    s3_resume_flag = read_byte(0x40, 0xb0);
+#ifdef HVMASSIST
     s3_wakeup_vector = get_s3_waking_vector();
-    if (!s3_wakeup_vector)
-        return;
-
-    s3_wakeup_ip = s3_wakeup_vector & 0xF;
-    s3_wakeup_cs = s3_wakeup_vector >> 4;
-
-ASM_START
-    push .s3_resume.s3_wakeup_cs[bp]
-    push .s3_resume.s3_wakeup_ip[bp]
-    retf
-ASM_END
+#else
+    s3_wakeup_vector = read_dword(0x40, 0xb2);
+#endif
+
+    BX_INFO("S3 resume called %x 0x%lx\n", s3_resume_flag, s3_wakeup_vector);
+    if (s3_resume_flag != CMOS_SHUTDOWN_S3 || !s3_wakeup_vector)
+           return 0;
+
+    write_byte(0x40, 0xb0, 0);
+
+    /* setup wakeup vector */
+    write_word(0x40, 0xb6, (s3_wakeup_vector & 0xF)); /* IP */
+    write_word(0x40, 0xb8, (s3_wakeup_vector >> 4)); /* CS */
+
+    BX_INFO("S3 resume jump to %x:%x\n", (s3_wakeup_vector >> 4),
+                   (s3_wakeup_vector & 0xF));
+ASM_START
+    jmpf [0x04b6]
+ASM_END
+    return 1;
 }
 
 #if BX_USE_ATADRV
@@ -2425,6 +2401,7 @@
 // bits 7-4 of the device/head (CB_DH) reg
 #define ATA_CB_DH_DEV0 0xa0    // select device 0
 #define ATA_CB_DH_DEV1 0xb0    // select device 1
+#define ATA_CB_DH_LBA 0x40    // use LBA
 
 // status reg (CB_STAT and CB_ASTAT) bits
 #define ATA_CB_STAT_BSY  0x80  // busy
@@ -2474,6 +2451,7 @@
 #define ATA_CMD_READ_SECTORS                 0x20
 #define ATA_CMD_READ_VERIFY_SECTORS          0x40
 #define ATA_CMD_RECALIBRATE                  0x10
+#define ATA_CMD_REQUEST_SENSE                0x03
 #define ATA_CMD_SEEK                         0x70
 #define ATA_CMD_SET_FEATURES                 0xEF
 #define ATA_CMD_SET_MULTIPLE_MODE            0xC6
@@ -2518,7 +2496,7 @@
 #define ATA_DATA_NO      0x00
 #define ATA_DATA_IN      0x01
 #define ATA_DATA_OUT     0x02
-  
+
 // ---------------------------------------------------------------------------
 // ATA/ATAPI driver : initialization
 // ---------------------------------------------------------------------------
@@ -2527,7 +2505,7 @@
   Bit16u ebda_seg=read_word(0x0040,0x000E);
   Bit8u  channel, device;
 
-  // Channels info init. 
+  // Channels info init.
   for (channel=0; channel<BX_MAX_ATA_INTERFACES; channel++) {
     write_byte(ebda_seg,&EbdaData->ata.channels[channel].iface,ATA_IFACE_NONE);
     write_word(ebda_seg,&EbdaData->ata.channels[channel].iobase1,0x0);
@@ -2535,7 +2513,7 @@
     write_byte(ebda_seg,&EbdaData->ata.channels[channel].irq,0);
     }
 
-  // Devices info init. 
+  // Devices info init.
   for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
     write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE);
     write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_NONE);
@@ -2550,11 +2528,12 @@
     write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads,0);
     write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders,0);
     write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt,0);
-    
-    write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors,0L);
-    }
-
-  // hdidmap  and cdidmap init. 
+
+    write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low,0L);
+    write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high,0L);
+    }
+
+  // hdidmap  and cdidmap init.
   for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
     write_byte(ebda_seg,&EbdaData->ata.hdidmap[device],BX_MAX_ATA_DEVICES);
     write_byte(ebda_seg,&EbdaData->ata.cdidmap[device],BX_MAX_ATA_DEVICES);
@@ -2562,6 +2541,58 @@
 
   write_byte(ebda_seg,&EbdaData->ata.hdcount,0);
   write_byte(ebda_seg,&EbdaData->ata.cdcount,0);
+}
+
+#define TIMEOUT 0
+#define BSY 1
+#define NOT_BSY 2
+#define NOT_BSY_DRQ 3
+#define NOT_BSY_NOT_DRQ 4
+#define NOT_BSY_RDY 5
+
+#define IDE_TIMEOUT 32000u //32 seconds max for IDE ops
+
+int await_ide();
+static int await_ide(when_done,base,timeout)
+  Bit8u when_done;
+  Bit16u base;
+  Bit16u timeout;
+{
+  Bit32u time=0,last=0;
+  Bit16u status;
+  Bit8u result;
+  status = inb(base + ATA_CB_STAT); // for the times you're supposed to throw 
one away
+  for(;;) {
+    status = inb(base+ATA_CB_STAT);
+    time++;
+    if (when_done == BSY)
+      result = status & ATA_CB_STAT_BSY;
+    else if (when_done == NOT_BSY)
+      result = !(status & ATA_CB_STAT_BSY);
+    else if (when_done == NOT_BSY_DRQ)
+      result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_DRQ);
+    else if (when_done == NOT_BSY_NOT_DRQ)
+      result = !(status & ATA_CB_STAT_BSY) && !(status & ATA_CB_STAT_DRQ);
+    else if (when_done == NOT_BSY_RDY)
+      result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_RDY);
+    else if (when_done == TIMEOUT)
+      result = 0;
+
+    if (result) return 0;
+    if (time>>16 != last) // mod 2048 each 16 ms
+    {
+      last = time >>16;
+      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);
+    }
+    if (status & ATA_CB_STAT_ERR)
+    {
+      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);
+      return -1;
+    }
+    if ((timeout == 0) || ((time>>11) > timeout)) break;
+  }
+  BX_INFO("IDE time out\n");
+  return -1;
 }
 
 // ---------------------------------------------------------------------------
@@ -2604,7 +2635,7 @@
 
   // Device detection
   hdcount=cdcount=0;
-  
+
   for(device=0; device<BX_MAX_ATA_DEVICES; device++) {
     Bit16u iobase1, iobase2;
     Bit8u  channel, slave, shift;
@@ -2634,33 +2665,34 @@
 
     if ( (sc == 0x55) && (sn == 0xaa) ) {
       
write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_UNKNOWN);
-    
+
       // reset the channel
-      ata_reset (device);
-      
+      ata_reset(device);
+
       // check for ATA or ATAPI
       outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
       sc = inb(iobase1+ATA_CB_SC);
       sn = inb(iobase1+ATA_CB_SN);
-      if ( (sc==0x01) && (sn==0x01) ) {
+      if ((sc==0x01) && (sn==0x01)) {
         cl = inb(iobase1+ATA_CB_CL);
         ch = inb(iobase1+ATA_CB_CH);
         st = inb(iobase1+ATA_CB_STAT);
 
-        if ( (cl==0x14) && (ch==0xeb) ) {
+        if ((cl==0x14) && (ch==0xeb)) {
           
write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATAPI);
-          }
-        else if ( (cl==0x00) && (ch==0x00) && (st!=0x00) ) {
+        } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) {
           
write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_ATA);
-          }
-        }
-      }
+        } else if ((cl==0xff) && (ch==0xff)) {
+          
write_byte(ebda_seg,&EbdaData->ata.devices[device].type,ATA_TYPE_NONE);
+        }
+      }
+    }
 
     type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type);
-    
-    // Now we send a IDENTIFY command to ATA device 
+
+    // Now we send a IDENTIFY command to ATA device
     if(type == ATA_TYPE_ATA) {
-      Bit32u sectors;
+      Bit32u sectors_low, sectors_high;
       Bit16u cylinders, heads, spt, blksize;
       Bit8u  translation, removable, mode;
 
@@ -2671,21 +2703,26 @@
       write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
       write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16);
 
-      if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, 
get_SS(),buffer) !=0 )
+      if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, 0L, 
get_SS(),buffer) !=0 )
         BX_PANIC("ata-detect: Failed to detect ATA device\n");
 
       removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
-#ifndef        NO_PIO32
+#ifndef        NO_PIO32
       mode      = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : 
ATA_MODE_PIO16;
 #endif
-
       blksize   = read_word(get_SS(),buffer+10);
-      
+
       cylinders = read_word(get_SS(),buffer+(1*2)); // word 1
       heads     = read_word(get_SS(),buffer+(3*2)); // word 3
       spt       = read_word(get_SS(),buffer+(6*2)); // word 6
 
-      sectors   = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61
+      if (read_word(get_SS(),buffer+(83*2)) & (1 << 10)) { // word 83 - lba48 
support
+        sectors_low  = read_dword(get_SS(),buffer+(100*2)); // word 100 and 
word 101
+        sectors_high = read_dword(get_SS(),buffer+(102*2)); // word 102 and 
word 103
+      } else {
+        sectors_low = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 
61
+        sectors_high = 0;
+      }
 
       write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
       write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable);
@@ -2694,7 +2731,8 @@
       write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads, heads);
       write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders, 
cylinders);
       write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt);
-      write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors, sectors);
+      write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, 
sectors_low);
+      write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high, 
sectors_high);
       BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, 
slave,cylinders, heads, spt);
 
       translation = inb_cmos(0x39 + channel/2);
@@ -2722,14 +2760,14 @@
           break;
         case ATA_TRANSLATION_LBA:
           spt = 63;
-          sectors /= 63;
-          heads = sectors / 1024;
+          sectors_low /= 63;
+          heads = sectors_low / 1024;
           if (heads>128) heads = 255;
           else if (heads>64) heads = 128;
           else if (heads>32) heads = 64;
           else if (heads>16) heads = 32;
           else heads=16;
-          cylinders = sectors / heads;
+          cylinders = sectors_low / heads;
           break;
         case ATA_TRANSLATION_RECHS:
           // Take care not to overflow
@@ -2756,15 +2794,15 @@
       write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, heads);
       write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, 
cylinders);
       write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, spt);
- 
-      // fill hdidmap 
+
+      // fill hdidmap
       write_byte(ebda_seg,&EbdaData->ata.hdidmap[hdcount], device);
       hdcount++;
       }
-    
+
     // Now we send a IDENTIFY command to ATAPI device
     if(type == ATA_TYPE_ATAPI) {
- 
+
       Bit8u  type, removable, mode;
       Bit16u blksize;
 
@@ -2775,12 +2813,12 @@
       
write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_CDROM);
       write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16);
 
-      if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 
0L, get_SS(),buffer) != 0)
+      if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 
0L, 0L, get_SS(),buffer) != 0)
         BX_PANIC("ata-detect: Failed to detect ATAPI device\n");
 
       type      = read_byte(get_SS(),buffer+1) & 0x1f;
       removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
-#ifndef        NO_PIO32
+#ifndef        NO_PIO32
       mode      = read_byte(get_SS(),buffer+96) ? ATA_MODE_PIO32 : 
ATA_MODE_PIO16;
 #endif
       blksize   = 2048;
@@ -2790,24 +2828,24 @@
       write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, mode);
       write_word(ebda_seg,&EbdaData->ata.devices[device].blksize, blksize);
 
-      // fill cdidmap 
+      // fill cdidmap
       write_byte(ebda_seg,&EbdaData->ata.cdidmap[cdcount], device);
       cdcount++;
       }
-  
+
       {
       Bit32u sizeinmb;
       Bit16u ataversion;
       Bit8u  c, i, version, model[41];
-      
+
       switch (type) {
         case ATA_TYPE_ATA:
-          sizeinmb = 
read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors);
-          sizeinmb >>= 11;
+          sizeinmb = 
(read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high) << 21)
+            | (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low) 
>> 11);
         case ATA_TYPE_ATAPI:
           // Read ATA/ATAPI version
           
ataversion=((Bit16u)(read_byte(get_SS(),buffer+161))<<8)|read_byte(get_SS(),buffer+160);
-          for(version=15;version>0;version--) { 
+          for(version=15;version>0;version--) {
             if((ataversion&(1<<version))!=0)
             break;
             }
@@ -2816,7 +2854,7 @@
           for(i=0;i<20;i++){
             
write_byte(get_SS(),model+(i*2),read_byte(get_SS(),buffer+(i*2)+54+1));
             
write_byte(get_SS(),model+(i*2)+1,read_byte(get_SS(),buffer+(i*2)+54));
-            }
+          }
 
           // Reformat
           write_byte(get_SS(),model+40,0x00);
@@ -2824,7 +2862,13 @@
             if(read_byte(get_SS(),model+i)==0x20)
               write_byte(get_SS(),model+i,0x00);
             else break;
-            }
+          }
+          if (i>36) {
+            write_byte(get_SS(),model+36,0x00);
+            for(i=35;i>32;i--){
+              write_byte(get_SS(),model+i,0x2E);
+            }
+          }
           break;
         }
 
@@ -2832,10 +2876,10 @@
         case ATA_TYPE_ATA:
           printf("ata%d %s: ",channel,slave?" slave":"master");
           i=0; while(c=read_byte(get_SS(),model+i++)) printf("%c",c);
-          if (sizeinmb < 1UL<<16)
-            printf(" ATA-%d Hard-Disk (%04u 
MBytes)\n",version,(Bit16u)sizeinmb);
-          else
-            printf(" ATA-%d Hard-Disk (%04u 
GBytes)\n",version,(Bit16u)(sizeinmb>>10));
+         if (sizeinmb < (1UL<<16))
+            printf(" ATA-%d Hard-Disk (%4u MBytes)\n", version, 
(Bit16u)sizeinmb);
+         else
+            printf(" ATA-%d Hard-Disk (%4u GBytes)\n", version, 
(Bit16u)(sizeinmb>>10));
           break;
         case ATA_TYPE_ATAPI:
           printf("ata%d %s: ",channel,slave?" slave":"master");
@@ -2856,17 +2900,17 @@
   write_byte(ebda_seg,&EbdaData->ata.hdcount, hdcount);
   write_byte(ebda_seg,&EbdaData->ata.cdcount, cdcount);
   write_byte(0x40,0x75, hdcount);
- 
+
   printf("\n");
 
   // FIXME : should use bios=cmos|auto|disable bits
   // FIXME : should know about translation bits
-  // FIXME : move hard_drive_post here 
-  
-}
-
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : software reset 
+  // FIXME : move hard_drive_post here
+
+}
+
+// ---------------------------------------------------------------------------
+// ATA/ATAPI driver : software reset
 // ---------------------------------------------------------------------------
 // ATA-3
 // 8.2.1 Software reset - Device 0
@@ -2876,7 +2920,8 @@
 {
   Bit16u ebda_seg=read_word(0x0040,0x000E);
   Bit16u iobase1, iobase2;
-  Bit8u  channel, slave, sn, sc; 
+  Bit8u  channel, slave, sn, sc;
+  Bit8u  type;
   Bit16u max;
 
   channel = device / 2;
@@ -2891,16 +2936,13 @@
   outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST);
 
 // 8.2.1 (b) -- wait for BSY
-  max=0xff;
-  while(--max>0) {
-    Bit8u status = inb(iobase1+ATA_CB_STAT);
-    if ((status & ATA_CB_STAT_BSY) != 0) break;
-  }
+  await_ide(BSY, iobase1, 20);
 
 // 8.2.1 (f) -- clear SRST
   outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
 
-  if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != 
ATA_TYPE_NONE) {
+  type=read_byte(ebda_seg,&EbdaData->ata.devices[device].type);
+  if (type != ATA_TYPE_NONE) {
 
 // 8.2.1 (g) -- check for sc==sn==0x01
     // select device
@@ -2909,21 +2951,14 @@
     sn = inb(iobase1+ATA_CB_SN);
 
     if ( (sc==0x01) && (sn==0x01) ) {
+      if (type == ATA_TYPE_ATA) //ATA
+        await_ide(NOT_BSY_RDY, iobase1, IDE_TIMEOUT);
+      else //ATAPI
+        await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
+    }
 
 // 8.2.1 (h) -- wait for not BSY
-      max=0xff;
-      while(--max>0) {
-        Bit8u status = inb(iobase1+ATA_CB_STAT);
-        if ((status & ATA_CB_STAT_BSY) == 0) break;
-        }
-      }
-    }
-
-// 8.2.1 (i) -- wait for DRDY
-  max=0xfff;
-  while(--max>0) {
-    Bit8u status = inb(iobase1+ATA_CB_STAT);
-      if ((status & ATA_CB_STAT_RDY) != 0) break;
+    await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
   }
 
   // Enable interrupts
@@ -2931,7 +2966,7 @@
 }
 
 // ---------------------------------------------------------------------------
-// ATA/ATAPI driver : execute a non data command 
+// ATA/ATAPI driver : execute a non data command
 // ---------------------------------------------------------------------------
 
 Bit16u ata_cmd_non_data()
@@ -2949,9 +2984,9 @@
       // 5 : more sectors to read/verify
       // 6 : no sectors left to write
       // 7 : more sectors to write
-Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, lba, 
segment, offset)
+Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, 
lba_low, lba_high, segment, offset)
 Bit16u device, command, count, cylinder, head, sector, segment, offset;
-Bit32u lba;
+Bit32u lba_low, lba_high;
 {
   Bit16u ebda_seg=read_word(0x0040,0x000E);
   Bit16u iobase1, iobase2, blksize;
@@ -2980,22 +3015,20 @@
 
   // sector will be 0 only on lba access. Convert to lba-chs
   if (sector == 0) {
-    if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) {
+    if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) {
       outb(iobase1 + ATA_CB_FR, 0x00);
       outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff);
-      outb(iobase1 + ATA_CB_SN, lba >> 24);
-      outb(iobase1 + ATA_CB_CL, 0);
-      outb(iobase1 + ATA_CB_CH, 0);
+      outb(iobase1 + ATA_CB_SN, lba_low >> 24);
+      outb(iobase1 + ATA_CB_CL, lba_high & 0xff);
+      outb(iobase1 + ATA_CB_CH, lba_high >> 8);
       command |= 0x04;
       count &= (1UL << 8) - 1;
-      lba &= (1UL << 24) - 1;
-      }
-    sector = (Bit16u) (lba & 0x000000ffL);
-    lba >>= 8;
-    cylinder = (Bit16u) (lba & 0x0000ffffL);
-    lba >>= 16;
-    head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
-    }
+      lba_low &= (1UL << 24) - 1;
+      }
+    sector = (Bit16u) (lba_low & 0x000000ffL);
+    cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
+    head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
+  }
 
   outb(iobase1 + ATA_CB_FR, 0x00);
   outb(iobase1 + ATA_CB_SC, count);
@@ -3005,10 +3038,8 @@
   outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | 
(Bit8u) head );
   outb(iobase1 + ATA_CB_CMD, command);
 
-  while (1) {
-    status = inb(iobase1 + ATA_CB_STAT);
-    if ( !(status & ATA_CB_STAT_BSY) ) break;
-    }
+  await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
+  status = inb(iobase1 + ATA_CB_STAT);
 
   if (status & ATA_CB_STAT_ERR) {
     BX_DEBUG_ATA("ata_cmd_data_in : read error\n");
@@ -3029,12 +3060,12 @@
 ASM_START
         push bp
         mov  bp, sp
-        mov  di, _ata_cmd_data_in.offset + 2[bp]  
-        mov  ax, _ata_cmd_data_in.segment + 2[bp] 
-        mov  cx, _ata_cmd_data_in.blksize + 2[bp] 
+        mov  di, _ata_cmd_data_in.offset + 2[bp]
+        mov  ax, _ata_cmd_data_in.segment + 2[bp]
+        mov  cx, _ata_cmd_data_in.blksize + 2[bp]
 
         ;; adjust if there will be an overrun. 2K max sector size
-        cmp   di, #0xf800 ;; 
+        cmp   di, #0xf800 ;;
         jbe   ata_in_no_adjust
 
 ata_in_adjust:
@@ -3046,7 +3077,7 @@
 
         mov   dx, _ata_cmd_data_in.iobase1 + 2[bp] ;; ATA data read port
 
-        mov  ah, _ata_cmd_data_in.mode + 2[bp] 
+        mov  ah, _ata_cmd_data_in.mode + 2[bp]
         cmp  ah, #ATA_MODE_PIO32
         je   ata_in_32
 
@@ -3068,9 +3099,10 @@
     current++;
     write_word(ebda_seg, &EbdaData->ata.trsfsectors,current);
     count--;
+    await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
     status = inb(iobase1 + ATA_CB_STAT);
     if (count == 0) {
-      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | 
ATA_CB_STAT_ERR) ) 
+      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | 
ATA_CB_STAT_ERR) )
           != ATA_CB_STAT_RDY ) {
         BX_DEBUG_ATA("ata_cmd_data_in : no sectors left (status %02x)\n", 
(unsigned) status);
         return 4;
@@ -3078,7 +3110,7 @@
       break;
       }
     else {
-      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | 
ATA_CB_STAT_ERR) ) 
+      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | 
ATA_CB_STAT_ERR) )
           != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
         BX_DEBUG_ATA("ata_cmd_data_in : more sectors left (status %02x)\n", 
(unsigned) status);
         return 5;
@@ -3103,9 +3135,9 @@
       // 5 : more sectors to read/verify
       // 6 : no sectors left to write
       // 7 : more sectors to write
-Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, lba, 
segment, offset)
+Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, 
lba_low, lba_high, segment, offset)
 Bit16u device, command, count, cylinder, head, sector, segment, offset;
-Bit32u lba;
+Bit32u lba_low, lba_high;
 {
   Bit16u ebda_seg=read_word(0x0040,0x000E);
   Bit16u iobase1, iobase2, blksize;
@@ -3134,22 +3166,20 @@
 
   // sector will be 0 only on lba access. Convert to lba-chs
   if (sector == 0) {
-    if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) {
+    if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) {
       outb(iobase1 + ATA_CB_FR, 0x00);
       outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff);
-      outb(iobase1 + ATA_CB_SN, lba >> 24);
-      outb(iobase1 + ATA_CB_CL, 0);
-      outb(iobase1 + ATA_CB_CH, 0);
+      outb(iobase1 + ATA_CB_SN, lba_low >> 24);
+      outb(iobase1 + ATA_CB_CL, lba_high & 0xff);
+      outb(iobase1 + ATA_CB_CH, lba_high >> 8);
       command |= 0x04;
       count &= (1UL << 8) - 1;
-      lba &= (1UL << 24) - 1;
-      }
-    sector = (Bit16u) (lba & 0x000000ffL);
-    lba >>= 8;
-    cylinder = (Bit16u) (lba & 0x0000ffffL);
-    lba >>= 16;
-    head = ((Bit16u) (lba & 0x0000000fL)) | 0x40;
-    }
+      lba_low &= (1UL << 24) - 1;
+      }
+    sector = (Bit16u) (lba_low & 0x000000ffL);
+    cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
+    head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
+  }
 
   outb(iobase1 + ATA_CB_FR, 0x00);
   outb(iobase1 + ATA_CB_SC, count);
@@ -3159,10 +3189,8 @@
   outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | 
(Bit8u) head );
   outb(iobase1 + ATA_CB_CMD, command);
 
-  while (1) {
-    status = inb(iobase1 + ATA_CB_STAT);
-    if ( !(status & ATA_CB_STAT_BSY) ) break;
-    }
+  await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
+  status = inb(iobase1 + ATA_CB_STAT);
 
   if (status & ATA_CB_STAT_ERR) {
     BX_DEBUG_ATA("ata_cmd_data_out : read error\n");
@@ -3183,12 +3211,12 @@
 ASM_START
         push bp
         mov  bp, sp
-        mov  si, _ata_cmd_data_out.offset + 2[bp]  
-        mov  ax, _ata_cmd_data_out.segment + 2[bp] 
-        mov  cx, _ata_cmd_data_out.blksize + 2[bp] 
+        mov  si, _ata_cmd_data_out.offset + 2[bp]
+        mov  ax, _ata_cmd_data_out.segment + 2[bp]
+        mov  cx, _ata_cmd_data_out.blksize + 2[bp]
 
         ;; adjust if there will be an overrun. 2K max sector size
-        cmp   si, #0xf800 ;; 
+        cmp   si, #0xf800 ;;
         jbe   ata_out_no_adjust
 
 ata_out_adjust:
@@ -3200,7 +3228,7 @@
 
         mov   dx, _ata_cmd_data_out.iobase1 + 2[bp] ;; ATA data write port
 
-        mov  ah, _ata_cmd_data_out.mode + 2[bp] 
+        mov  ah, _ata_cmd_data_out.mode + 2[bp]
         cmp  ah, #ATA_MODE_PIO32
         je   ata_out_32
 
@@ -3226,7 +3254,7 @@
     count--;
     status = inb(iobase1 + ATA_CB_STAT);
     if (count == 0) {
-      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | 
ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 
+      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | 
ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
           != ATA_CB_STAT_RDY ) {
         BX_DEBUG_ATA("ata_cmd_data_out : no sectors left (status %02x)\n", 
(unsigned) status);
         return 6;
@@ -3234,7 +3262,7 @@
       break;
       }
     else {
-      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | 
ATA_CB_STAT_ERR) ) 
+      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | 
ATA_CB_STAT_ERR) )
           != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
         BX_DEBUG_ATA("ata_cmd_data_out : more sectors left (status %02x)\n", 
(unsigned) status);
         return 7;
@@ -3301,19 +3329,17 @@
   if (status & ATA_CB_STAT_BSY) return 2;
 
   outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
-  // outb(iobase1 + ATA_CB_FR, 0x00);
-  // outb(iobase1 + ATA_CB_SC, 0x00);
-  // outb(iobase1 + ATA_CB_SN, 0x00);
+  outb(iobase1 + ATA_CB_FR, 0x00);
+  outb(iobase1 + ATA_CB_SC, 0x00);
+  outb(iobase1 + ATA_CB_SN, 0x00);
   outb(iobase1 + ATA_CB_CL, 0xfff0 & 0x00ff);
   outb(iobase1 + ATA_CB_CH, 0xfff0 >> 8);
   outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0);
   outb(iobase1 + ATA_CB_CMD, ATA_CMD_PACKET);
 
   // Device should ok to receive command
-  while (1) {
-    status = inb(iobase1 + ATA_CB_STAT);
-    if ( !(status & ATA_CB_STAT_BSY) ) break;
-    }
+  await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
+  status = inb(iobase1 + ATA_CB_STAT);
 
   if (status & ATA_CB_STAT_ERR) {
     BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status);
@@ -3330,13 +3356,13 @@
   // Send command to device
 ASM_START
       sti  ;; enable higher priority interrupts
- 
+
       push bp
       mov  bp, sp
-    
-      mov  si, _ata_cmd_packet.cmdoff + 2[bp]  
-      mov  ax, _ata_cmd_packet.cmdseg + 2[bp] 
-      mov  cx, _ata_cmd_packet.cmdlen + 2[bp] 
+
+      mov  si, _ata_cmd_packet.cmdoff + 2[bp]
+      mov  ax, _ata_cmd_packet.cmdseg + 2[bp]
+      mov  cx, _ata_cmd_packet.cmdlen + 2[bp]
       mov  es, ax      ;; segment in es
 
       mov  dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data write port
@@ -3349,32 +3375,38 @@
 ASM_END
 
   if (inout == ATA_DATA_NO) {
+    await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
     status = inb(iobase1 + ATA_CB_STAT);
     }
   else {
+        Bit16u loops = 0;
+        Bit8u sc;
   while (1) {
 
+      if (loops == 0) {//first time through
+        status = inb(iobase2 + ATA_CB_ASTAT);
+        await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
+      }
+      else
+        await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
+      loops++;
+
       status = inb(iobase1 + ATA_CB_STAT);
+      sc = inb(iobase1 + ATA_CB_SC);
 
       // Check if command completed
-      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ) ) ==0 ) break;
+      if(((inb(iobase1 + ATA_CB_SC)&0x7)==0x3) &&
+         ((status & (ATA_CB_STAT_RDY | ATA_CB_STAT_ERR)) == ATA_CB_STAT_RDY)) 
break;
 
       if (status & ATA_CB_STAT_ERR) {
         BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status);
         return 3;
       }
 
-      // Device must be ready to send data
-      if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | 
ATA_CB_STAT_ERR) ) 
-            != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) {
-        BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", status);
-        return 4;
-        }
-
       // Normalize address
       bufseg += (bufoff / 16);
       bufoff %= 16;
-    
+
       // Get the byte count
       lcount =  ((Bit16u)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + 
ATA_CB_CL);
 
@@ -3435,10 +3467,10 @@
 
         mov  dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data read port
 
-        mov  cx, _ata_cmd_packet.lbefore + 2[bp] 
+        mov  cx, _ata_cmd_packet.lbefore + 2[bp]
         jcxz ata_packet_no_before
 
-        mov  ah, _ata_cmd_packet.lmode + 2[bp] 
+        mov  ah, _ata_cmd_packet.lmode + 2[bp]
         cmp  ah, #ATA_MODE_PIO32
         je   ata_packet_in_before_32
 
@@ -3455,14 +3487,14 @@
         pop  eax
 
 ata_packet_no_before:
-        mov  cx, _ata_cmd_packet.lcount + 2[bp] 
+        mov  cx, _ata_cmd_packet.lcount + 2[bp]
         jcxz ata_packet_after
 
-        mov  di, _ata_cmd_packet.bufoff + 2[bp]  
-        mov  ax, _ata_cmd_packet.bufseg + 2[bp] 
+        mov  di, _ata_cmd_packet.bufoff + 2[bp]
+        mov  ax, _ata_cmd_packet.bufseg + 2[bp]
         mov  es, ax
 
-        mov  ah, _ata_cmd_packet.lmode + 2[bp] 
+        mov  ah, _ata_cmd_packet.lmode + 2[bp]
         cmp  ah, #ATA_MODE_PIO32
         je   ata_packet_in_32
 
@@ -3476,10 +3508,10 @@
           insd ;; CX dwords transfered to port(DX) to ES:[DI]
 
 ata_packet_after:
-        mov  cx, _ata_cmd_packet.lafter + 2[bp] 
+        mov  cx, _ata_cmd_packet.lafter + 2[bp]
         jcxz ata_packet_done
 
-        mov  ah, _ata_cmd_packet.lmode + 2[bp] 
+        mov  ah, _ata_cmd_packet.lmode + 2[bp]
         cmp  ah, #ATA_MODE_PIO32
         je   ata_packet_in_after_32
 
@@ -3509,7 +3541,7 @@
     }
 
   // Final check, device must be ready
-  if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | 
ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) 
+  if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | 
ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
          != ATA_CB_STAT_RDY ) {
     BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", (unsigned) 
status);
     return 4;
@@ -3528,55 +3560,108 @@
 // Start of ATA/ATAPI generic functions
 // ---------------------------------------------------------------------------
 
-  Bit16u 
-atapi_get_sense(device)
+  Bit16u
+atapi_get_sense(device, seg, asc, ascq)
   Bit16u device;
 {
   Bit8u  atacmd[12];
-  Bit8u  buffer[16];
+  Bit8u  buffer[18];
   Bit8u i;
 
   memsetb(get_SS(),atacmd,0,12);
 
-  // Request SENSE 
-  atacmd[0]=0x03;    
-  atacmd[4]=0x20;    
-  if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 16L, ATA_DATA_IN, 
get_SS(), buffer) != 0)
+  // Request SENSE
+  atacmd[0]=ATA_CMD_REQUEST_SENSE;
+  atacmd[4]=sizeof(buffer);
+  if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 18L, ATA_DATA_IN, 
get_SS(), buffer) != 0)
     return 0x0002;
 
-  if ((buffer[0] & 0x7e) == 0x70) {
-    return (((Bit16u)buffer[2]&0x0f)*0x100)+buffer[12];
-    }
+  write_byte(seg,asc,buffer[12]);
+  write_byte(seg,ascq,buffer[13]);
 
   return 0;
 }
 
-  Bit16u 
+  Bit16u
 atapi_is_ready(device)
   Bit16u device;
 {
-  Bit8u  atacmd[12];
-  Bit8u  buffer[];
-
-  memsetb(get_SS(),atacmd,0,12);
- 
-  // Test Unit Ready
-  if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO, 
get_SS(), buffer) != 0)
-    return 0x000f;
-
-  if (atapi_get_sense(device) !=0 ) {
-    memsetb(get_SS(),atacmd,0,12);
-
-    // try to send Test Unit Ready again
-    if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 0L, ATA_DATA_NO, 
get_SS(), buffer) != 0)
-      return 0x000f;
-
-    return atapi_get_sense(device);
-    }
+  Bit8u packet[12];
+  Bit8u buf[8];
+  Bit32u block_len;
+  Bit32u sectors;
+  Bit32u timeout; //measured in ms
+  Bit32u time;
+  Bit8u asc, ascq;
+  Bit8u in_progress;
+  Bit16u ebda_seg = read_word(0x0040,0x000E);
+  if (read_byte(ebda_seg,&EbdaData->ata.devices[device].type) != 
ATA_TYPE_ATAPI) {
+    printf("not implemented for non-ATAPI device\n");
+    return -1;
+  }
+
+  BX_DEBUG_ATA("ata_detect_medium: begin\n");
+  memsetb(get_SS(),packet, 0, sizeof packet);
+  packet[0] = 0x25; /* READ CAPACITY */
+
+  /* Retry READ CAPACITY 50 times unless MEDIUM NOT PRESENT
+   * is reported by the device. If the device reports "IN PROGRESS",
+   * 30 seconds is added. */
+  timeout = 5000;
+  time = 0;
+  in_progress = 0;
+  while (time < timeout) {
+    if (ata_cmd_packet(device, sizeof(packet), get_SS(), packet, 0, 8L, 
ATA_DATA_IN, get_SS(), buf) == 0)
+      goto ok;
+
+    if (atapi_get_sense(device, get_SS(), &asc, &ascq) == 0) {
+      if (asc == 0x3a) { /* MEDIUM NOT PRESENT */
+        BX_DEBUG_ATA("Device reports MEDIUM NOT PRESENT\n");
+        return -1;
+      }
+
+      if (asc == 0x04 && ascq == 0x01 && !in_progress) {
+        /* IN PROGRESS OF BECOMING READY */
+        printf("Waiting for device to detect medium... ");
+        /* Allow 30 seconds more */
+        timeout = 30000;
+        in_progress = 1;
+      }
+    }
+    time += 100;
+  }
+  BX_DEBUG_ATA("read capacity failed\n");
+  return -1;
+ok:
+
+  block_len = (Bit32u) buf[4] << 24
+    | (Bit32u) buf[5] << 16
+    | (Bit32u) buf[6] << 8
+    | (Bit32u) buf[7] << 0;
+  BX_DEBUG_ATA("block_len=%u\n", block_len);
+
+  if (block_len!= 2048 && block_len!= 512)
+  {
+    printf("Unsupported sector size %u\n", block_len);
+    return -1;
+  }
+  write_dword(ebda_seg,&EbdaData->ata.devices[device].blksize, block_len);
+
+  sectors = (Bit32u) buf[0] << 24
+    | (Bit32u) buf[1] << 16
+    | (Bit32u) buf[2] << 8
+    | (Bit32u) buf[3] << 0;
+
+  BX_DEBUG_ATA("sectors=%u\n", sectors);
+  if (block_len == 2048)
+    sectors <<= 2; /* # of sectors in 512-byte "soft" sector */
+  if (sectors != 
read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low))
+    printf("%dMB medium detected\n", sectors>>(20-9));
+  write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors);
   return 0;
 }
 
-  Bit16u 
+  Bit16u
 atapi_is_cdrom(device)
   Bit8u device;
 {
@@ -3636,7 +3721,7 @@
 //
 // Returns ah: emulated drive, al: error code
 //
-  Bit16u 
+  Bit16u
 cdrom_boot()
 {
   Bit16u ebda_seg=read_word(0x0040,0x000E);
@@ -3649,9 +3734,12 @@
   for (device=0; device<BX_MAX_ATA_DEVICES;device++) {
     if (atapi_is_cdrom(device)) break;
     }
-  
+
   // if not found
   if(device >= BX_MAX_ATA_DEVICES) return 2;
+
+  if(error = atapi_is_ready(device) != 0)
+    BX_INFO("ata_is_ready returned %d\n",error);
 
   // Read the Boot Record Volume Descriptor
   memsetb(get_SS(),atacmd,0,12);
@@ -3672,7 +3760,7 @@
    }
   for(i=0;i<23;i++)
     if(buffer[7+i]!=read_byte(0xf000,&eltorito[i]))return 6;
-  
+
   // ok, now we calculate the Boot catalog address
   
lba=buffer[0x4A]*0x1000000+buffer[0x49]*0x10000+buffer[0x48]*0x100+buffer[0x47];
 
@@ -3687,7 +3775,7 @@
   atacmd[5]=(lba & 0x000000ff);
   if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, 
ATA_DATA_IN, get_SS(), buffer)) != 0)
     return 7;
- 
+
   // Validation entry
   if(buffer[0x00]!=0x01)return 8;   // Header
   if(buffer[0x01]!=0x00)return 9;   // Platform
@@ -3706,10 +3794,10 @@
 
   write_byte(ebda_seg,&EbdaData->cdemu.media,buffer[0x21]);
   if(buffer[0x21]==0){
-    // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0. 
+    // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0.
     // Win2000 cd boot needs to know it booted from cd
     write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0xE0);
-    } 
+    }
   else if(buffer[0x21]<4)
     write_byte(ebda_seg,&EbdaData->cdemu.emulated_drive,0x00);
   else
@@ -3723,7 +3811,7 @@
 
   write_word(ebda_seg,&EbdaData->cdemu.load_segment,boot_segment);
   write_word(ebda_seg,&EbdaData->cdemu.buffer_segment,0x0000);
-  
+
   nbsectors=buffer[0x27]*0x100+buffer[0x26];
   write_word(ebda_seg,&EbdaData->cdemu.sector_count,nbsectors);
 
@@ -3748,7 +3836,6 @@
   tcpa_ipl((Bit32u)1L,(Bit32u)boot_segment,(Bit32u)0L,(Bit32u)512L);
 #endif
 
-
   // Remember the media type
   switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) {
     case 0x01:  // 1.2M floppy
@@ -3769,7 +3856,7 @@
     case 0x04:  // Harddrive
       
write_word(ebda_seg,&EbdaData->cdemu.vdevice.spt,read_byte(boot_segment,446+6)&0x3f);
       write_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders,
-             (read_byte(boot_segment,446+6)<<2) + 
read_byte(boot_segment,446+7) + 1);
+              (read_byte(boot_segment,446+6)<<2) + 
read_byte(boot_segment,446+7) + 1);
       
write_word(ebda_seg,&EbdaData->cdemu.vdevice.heads,read_byte(boot_segment,446+5)
 + 1);
       break;
    }
@@ -3782,7 +3869,7 @@
       write_byte(ebda_seg, &EbdaData->ata.hdcount, read_byte(ebda_seg, 
&EbdaData->ata.hdcount) + 1);
    }
 
-  
+
   // everything is ok, so from now on, the emulation is active
   if(read_byte(ebda_seg,&EbdaData->cdemu.media)!=0)
     write_byte(ebda_seg,&EbdaData->cdemu.active,0x01);
@@ -4128,9 +4215,10 @@
       regs.u.r8.al = inb_cmos(0x30);
       regs.u.r8.ah = inb_cmos(0x31);
 
-      // limit to 15M
-      if(regs.u.r16.ax > 0x3c00)
-        regs.u.r16.ax = 0x3c00;
+      // According to Ralf Brown's interrupt the limit should be 15M,
+      // but real machines mostly return max. 63M.
+      if(regs.u.r16.ax > 0xffc0)
+        regs.u.r16.ax = 0xffc0;
 
       CLEAR_CF();
 #endif
@@ -4348,13 +4436,35 @@
 
         case 3: // Set Resolution
 BX_DEBUG_INT15("case 3:\n");
-          // BX:
+          // BH:
           //      0 =  25 dpi, 1 count  per millimeter
           //      1 =  50 dpi, 2 counts per millimeter
           //      2 = 100 dpi, 4 counts per millimeter
           //      3 = 200 dpi, 8 counts per millimeter
-          CLEAR_CF();
-          regs.u.r8.ah = 0;
+          comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and 
packets
+          if (regs.u.r8.bh < 4) {
+            ret = send_to_mouse_ctrl(0xE8); // set resolution command
+            if (ret == 0) {
+              ret = get_mouse_data(&mouse_data1);
+              if (mouse_data1 != 0xfa)
+                BX_PANIC("Mouse status returned %02x (should be ack)\n", 
(unsigned)mouse_data1);
+              ret = send_to_mouse_ctrl(regs.u.r8.bh);
+              ret = get_mouse_data(&mouse_data1);
+              if (mouse_data1 != 0xfa)
+                BX_PANIC("Mouse status returned %02x (should be ack)\n", 
(unsigned)mouse_data1);
+              CLEAR_CF();
+              regs.u.r8.ah = 0;
+            } else {
+              // error
+              SET_CF();
+              regs.u.r8.ah = UNSUPPORTED_FUNCTION;
+            }
+          } else {
+            // error
+            SET_CF();
+            regs.u.r8.ah = UNSUPPORTED_FUNCTION;
+          }
+          set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
           break;
 
         case 4: // Get Device ID
@@ -4476,7 +4586,30 @@
       break;
     }
 }
-#endif
+#endif // BX_USE_PS2_MOUSE
+
+
+void set_e820_range(ES, DI, start, end, type)
+     Bit16u ES;
+     Bit16u DI;
+     Bit32u start;
+     Bit32u end;
+     Bit16u type;
+{
+    write_word(ES, DI, start);
+    write_word(ES, DI+2, start >> 16);
+    write_word(ES, DI+4, 0x00);
+    write_word(ES, DI+6, 0x00);
+
+    end -= start;
+    write_word(ES, DI+8, end);
+    write_word(ES, DI+10, end >> 16);
+    write_word(ES, DI+12, 0x0000);
+    write_word(ES, DI+14, 0x0000);
+
+    write_word(ES, DI+16, type);
+    write_word(ES, DI+18, 0x0);
+}
 
   void
 int15_function32(regs, ES, DS, FLAGS)
@@ -4490,17 +4623,20 @@
 
   switch (regs.u.r8.ah) {
     case 0x86:
-      // Wait for CX:DX microseconds. currently using the 
-      // refresh request port 0x61 bit4, toggling every 15usec 
+      // Wait for CX:DX microseconds. currently using the
+      // refresh request port 0x61 bit4, toggling every 15usec
 
       CX = regs.u.r16.cx;
       DX = regs.u.r16.dx;
 
 ASM_START
+      sti
+
       ;; Get the count in eax
-      mov  ax, .int15_function32.CX [bp]
+      mov  bx, sp
+      mov  ax, _int15_function32.CX [bx]
       shl  eax, #16
-      mov  ax, .int15_function32.DX [bp]
+      mov  ax, _int15_function32.DX [bx]
 
       ;; convert to numbers of 15usec ticks
       mov ebx, #15
@@ -4531,7 +4667,8 @@
     case 0xe8:
         switch(regs.u.r8.al)
         {
-        case 0x20: {
+#ifdef HVMASSIST
+       case 0x20: {
             Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
 
             if (regs.u.r32.edx != 0x534D4150) /* SMAP */
@@ -4579,7 +4716,7 @@
             // Get the amount of extended memory (above 1M)
             regs.u.r8.cl = inb_cmos(0x30);
             regs.u.r8.ch = inb_cmos(0x31);
-          
+
             // limit to 15M
             if (regs.u.r16.cx > (15*1024))
                 regs.u.r16.cx = 15*1024;
@@ -4607,7 +4744,7 @@
             regs.u.r16.bx = regs.u.r16.dx;
             break;
         }
-       default:  /* AH=0xE8?? but not implemented */
+        default:  /* AH=0xE8?? but not implemented */
             goto int15_unimplemented;
         }
         break;
@@ -4620,16 +4757,178 @@
       regs.u.r8.ah = UNSUPPORTED_FUNCTION;
       break;
     }
+#else
+         case 0x20: // coded by osmaker aka K.J.
+            if(regs.u.r32.edx == 0x534D4150)
+            {
+                extended_memory_size = inb_cmos(0x35);
+                extended_memory_size <<= 8;
+                extended_memory_size |= inb_cmos(0x34);
+                extended_memory_size *= 64;
+                // greater than EFF00000???
+                if(extended_memory_size > 0x3bc000) {
+                    extended_memory_size = 0x3bc000; // everything after this 
is reserved memory until we get to 0x100000000
+                }
+                extended_memory_size *= 1024;
+                extended_memory_size += (16L * 1024 * 1024);
+
+                if(extended_memory_size <= (16L * 1024 * 1024)) {
+                    extended_memory_size = inb_cmos(0x31);
+                    extended_memory_size <<= 8;
+                    extended_memory_size |= inb_cmos(0x30);
+                    extended_memory_size *= 1024;
+                    extended_memory_size += (1L * 1024 * 1024);
+                }
+
+                switch(regs.u.r16.bx)
+                {
+                    case 0:
+                        set_e820_range(ES, regs.u.r16.di,
+                                       0x0000000L, 0x0009f000L, 1);
+                        regs.u.r32.ebx = 1;
+                        regs.u.r32.eax = 0x534D4150;
+                        regs.u.r32.ecx = 0x14;
+                        CLEAR_CF();
+                        return;
+                        break;
+                    case 1:
+                        set_e820_range(ES, regs.u.r16.di,
+                                       0x0009f000L, 0x000a0000L, 2);
+                        regs.u.r32.ebx = 2;
+                        regs.u.r32.eax = 0x534D4150;
+                        regs.u.r32.ecx = 0x14;
+                        CLEAR_CF();
+                        return;
+                        break;
+                    case 2:
+                        set_e820_range(ES, regs.u.r16.di,
+                                       0x000e8000L, 0x00100000L, 2);
+                        regs.u.r32.ebx = 3;
+                        regs.u.r32.eax = 0x534D4150;
+                        regs.u.r32.ecx = 0x14;
+                        CLEAR_CF();
+                        return;
+                        break;
+                    case 3:
+#if BX_ROMBIOS32
+                        set_e820_range(ES, regs.u.r16.di,
+                                       0x00100000L,
+                                       extended_memory_size - ACPI_DATA_SIZE, 
1);
+                        regs.u.r32.ebx = 4;
+#else
+                        set_e820_range(ES, regs.u.r16.di,
+                                       0x00100000L,
+                                       extended_memory_size, 1);
+                        regs.u.r32.ebx = 5;
+#endif
+                        regs.u.r32.eax = 0x534D4150;
+                        regs.u.r32.ecx = 0x14;
+                        CLEAR_CF();
+                        return;
+                        break;
+                    case 4:
+                        set_e820_range(ES, regs.u.r16.di,
+                                       extended_memory_size - ACPI_DATA_SIZE,
+                                       extended_memory_size, 3); // ACPI RAM
+                        regs.u.r32.ebx = 5;
+                        regs.u.r32.eax = 0x534D4150;
+                        regs.u.r32.ecx = 0x14;
+                        CLEAR_CF();
+                        return;
+                        break;
+                    case 5:
+                        /* 256KB BIOS area at the end of 4 GB */
+                        set_e820_range(ES, regs.u.r16.di,
+                                       0xfffc0000L, 0x00000000L, 2);
+                        regs.u.r32.ebx = 0;
+                        regs.u.r32.eax = 0x534D4150;
+                        regs.u.r32.ecx = 0x14;
+                        CLEAR_CF();
+                        return;
+                    default:  /* AX=E820, DX=534D4150, BX unrecognized */
+                        goto int15_unimplemented;
+                        break;
+                }
+            } else {
+              // if DX != 0x534D4150)
+              goto int15_unimplemented;
+            }
+            break;
+
+        case 0x01:
+          // do we have any reason to fail here ?
+          CLEAR_CF();
+
+          // my real system sets ax and bx to 0
+          // this is confirmed by Ralph Brown list
+          // but syslinux v1.48 is known to behave
+          // strangely if ax is set to 0
+          // regs.u.r16.ax = 0;
+          // regs.u.r16.bx = 0;
+
+          // Get the amount of extended memory (above 1M)
+          regs.u.r8.cl = inb_cmos(0x30);
+          regs.u.r8.ch = inb_cmos(0x31);
+
+          // limit to 15M
+          if(regs.u.r16.cx > 0x3c00)
+          {
+            regs.u.r16.cx = 0x3c00;
+          }
+
+          // Get the amount of extended memory above 16M in 64k blocs
+          regs.u.r8.dl = inb_cmos(0x34);
+          regs.u.r8.dh = inb_cmos(0x35);
+
+          // Set configured memory equal to extended memory
+          regs.u.r16.ax = regs.u.r16.cx;
+          regs.u.r16.bx = regs.u.r16.dx;
+          break;
+        default:  /* AH=0xE8?? but not implemented */
+          goto int15_unimplemented;
+       }
+       break;
+    int15_unimplemented:
+       // fall into the default
+    default:
+      BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n",
+        (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx);
+      SET_CF();
+      regs.u.r8.ah = UNSUPPORTED_FUNCTION;
+      break;
+    }
+#endif /* HVMASSIST */
 }
 
   void
 int16_function(DI, SI, BP, SP, BX, DX, CX, AX, FLAGS)
   Bit16u DI, SI, BP, SP, BX, DX, CX, AX, FLAGS;
 {
-  Bit8u scan_code, ascii_code, shift_flags, count;
+  Bit8u scan_code, ascii_code, shift_flags, led_flags, count;
   Bit16u kbd_code, max;
 
   BX_DEBUG_INT16("int16: AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX);
+
+  shift_flags = read_byte(0x0040, 0x17);
+  led_flags = read_byte(0x0040, 0x97);
+  if ((((shift_flags >> 4) & 0x07) ^ (led_flags & 0x07)) != 0) {
+ASM_START
+    cli
+ASM_END
+    outb(0x60, 0xed);
+    while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21);
+    if ((inb(0x60) == 0xfa)) {
+      led_flags &= 0xf8;
+      led_flags |= ((shift_flags >> 4) & 0x07);
+      outb(0x60, led_flags & 0x07);
+      while ((inb(0x64) & 0x01) == 0) outb(0x80, 0x21);
+      inb(0x60);
+      write_byte(0x0040, 0x97, led_flags);
+    }
+ASM_START
+    sti
+ASM_END
+  }
 
   switch (GET_AH()) {
     case 0x00: /* read keyboard input */
@@ -4668,7 +4967,7 @@
       break;
 
     case 0x09: /* GET KEYBOARD FUNCTIONALITY */
-      // bit Bochs Description     
+      // bit Bochs Description
       //  7    0   reserved
       //  6    0   INT 16/AH=20h-22h supported (122-key keyboard support)
       //  5    1   INT 16/AH=10h-12h supported (enhanced keyboard support)
@@ -4698,7 +4997,7 @@
               kbd_code |= (inb(0x60) << 8);
             }
           } while (--count>0);
-       }
+        }
       }
       BX=kbd_code;
       break;
@@ -4725,7 +5024,8 @@
     case 0x12: /* get extended keyboard status */
       shift_flags = read_byte(0x0040, 0x17);
       SET_AL(shift_flags);
-      shift_flags = read_byte(0x0040, 0x18);
+      shift_flags = read_byte(0x0040, 0x18) & 0x73;
+      shift_flags |= read_byte(0x0040, 0x96) & 0x0c;
       SET_AH(shift_flags);
       BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX);
       break;
@@ -4740,7 +5040,7 @@
 
     case 0x6F:
       if (GET_AL() == 0x08)
-       SET_AH(0x02); // unsupported, aka normal keyboard
+        SET_AH(0x02); // unsupported, aka normal keyboard
 
     default:
       BX_INFO("KBD: unsupported int 16h function %02x\n", GET_AH());
@@ -4881,7 +5181,7 @@
   Bit16u DI, SI, BP, SP, BX, DX, CX, AX;
 {
   Bit8u scancode, asciicode, shift_flags;
-  Bit8u mf2_flags, mf2_state, led_flags;
+  Bit8u mf2_flags, mf2_state;
 
   //
   // DS has been set to F000 before call
@@ -4899,7 +5199,6 @@
   shift_flags = read_byte(0x0040, 0x17);
   mf2_flags = read_byte(0x0040, 0x18);
   mf2_state = read_byte(0x0040, 0x96);
-  led_flags = read_byte(0x0040, 0x97);
   asciicode = 0;
 
   switch (scancode) {
@@ -4908,8 +5207,6 @@
       write_byte(0x0040, 0x17, shift_flags);
       mf2_flags |= 0x40;
       write_byte(0x0040, 0x18, mf2_flags);
-      led_flags ^= 0x04;
-      write_byte(0x0040, 0x97, led_flags);
       break;
     case 0xba: /* Caps Lock release */
       mf2_flags &= ~0x40;
@@ -4917,11 +5214,8 @@
       break;
 
     case 0x2a: /* L Shift press */
-      /*shift_flags &= ~0x40;*/
       shift_flags |= 0x02;
       write_byte(0x0040, 0x17, shift_flags);
-      led_flags &= ~0x04;
-      write_byte(0x0040, 0x97, led_flags);
       break;
     case 0xaa: /* L Shift release */
       shift_flags &= ~0x02;
@@ -4929,11 +5223,8 @@
       break;
 
     case 0x36: /* R Shift press */
-      /*shift_flags &= ~0x40;*/
       shift_flags |= 0x01;
       write_byte(0x0040, 0x17, shift_flags);
-      led_flags &= ~0x04;
-      write_byte(0x0040, 0x97, led_flags);
       break;
     case 0xb6: /* R Shift release */
       shift_flags &= ~0x01;
@@ -4941,71 +5232,75 @@
       break;
 
     case 0x1d: /* Ctrl press */
-      shift_flags |= 0x04;
-      write_byte(0x0040, 0x17, shift_flags);
-      if (mf2_state & 0x01) {
-        mf2_flags |= 0x04;
-      } else {
-        mf2_flags |= 0x01;
-        }
-      write_byte(0x0040, 0x18, mf2_flags);
+      if ((mf2_state & 0x01) == 0) {
+        shift_flags |= 0x04;
+        write_byte(0x0040, 0x17, shift_flags);
+        if (mf2_state & 0x02) {
+          mf2_state |= 0x04;
+          write_byte(0x0040, 0x96, mf2_state);
+        } else {
+          mf2_flags |= 0x01;
+          write_byte(0x0040, 0x18, mf2_flags);
+        }
+      }
       break;
     case 0x9d: /* Ctrl release */
-      shift_flags &= ~0x04;
-      write_byte(0x0040, 0x17, shift_flags);
-      if (mf2_state & 0x01) {
-        mf2_flags &= ~0x04;
-      } else {
-        mf2_flags &= ~0x01;
-        }
-      write_byte(0x0040, 0x18, mf2_flags);
+      if ((mf2_state & 0x01) == 0) {
+        shift_flags &= ~0x04;
+        write_byte(0x0040, 0x17, shift_flags);
+        if (mf2_state & 0x02) {
+          mf2_state &= ~0x04;
+          write_byte(0x0040, 0x96, mf2_state);
+        } else {
+          mf2_flags &= ~0x01;
+          write_byte(0x0040, 0x18, mf2_flags);
+        }
+      }
       break;
 
     case 0x38: /* Alt press */
       shift_flags |= 0x08;
       write_byte(0x0040, 0x17, shift_flags);
-      if (mf2_state & 0x01) {
-        mf2_flags |= 0x08;
+      if (mf2_state & 0x02) {
+        mf2_state |= 0x08;
+        write_byte(0x0040, 0x96, mf2_state);
       } else {
         mf2_flags |= 0x02;
-        }
-      write_byte(0x0040, 0x18, mf2_flags);
+        write_byte(0x0040, 0x18, mf2_flags);
+      }
       break;
     case 0xb8: /* Alt release */
       shift_flags &= ~0x08;
       write_byte(0x0040, 0x17, shift_flags);
-      if (mf2_state & 0x01) {
-        mf2_flags &= ~0x08;
+      if (mf2_state & 0x02) {
+        mf2_state &= ~0x08;
+        write_byte(0x0040, 0x96, mf2_state);
       } else {
         mf2_flags &= ~0x02;
-        }
-      write_byte(0x0040, 0x18, mf2_flags);
+        write_byte(0x0040, 0x18, mf2_flags);
+      }
       break;
 
     case 0x45: /* Num Lock press */
-      if ((mf2_state & 0x01) == 0) {
+      if ((mf2_state & 0x03) == 0) {
         mf2_flags |= 0x20;
         write_byte(0x0040, 0x18, mf2_flags);
         shift_flags ^= 0x20;
-        led_flags ^= 0x02;
         write_byte(0x0040, 0x17, shift_flags);
-        write_byte(0x0040, 0x97, led_flags);
-        }
+      }
       break;
     case 0xc5: /* Num Lock release */
-      if ((mf2_state & 0x01) == 0) {
+      if ((mf2_state & 0x03) == 0) {
         mf2_flags &= ~0x20;
         write_byte(0x0040, 0x18, mf2_flags);
-        }
+      }
       break;
 
     case 0x46: /* Scroll Lock press */
       mf2_flags |= 0x10;
       write_byte(0x0040, 0x18, mf2_flags);
       shift_flags ^= 0x10;
-      led_flags ^= 0x01;
       write_byte(0x0040, 0x17, shift_flags);
-      write_byte(0x0040, 0x97, led_flags);
       break;
 
     case 0xc6: /* Scroll Lock release */
@@ -5018,50 +5313,55 @@
             machine_reset();
         /* Fall through */
     default:
-      if (scancode & 0x80) return; /* toss key releases ... */
+      if (scancode & 0x80) {
+        break; /* toss key releases ... */
+      }
       if (scancode > MAX_SCAN_CODE) {
-        BX_INFO("KBD: int09h_handler(): unknown scancode (%x) read!\n", 
scancode);
-        return;
-        }
+        BX_INFO("KBD: int09h_handler(): unknown scancode read: 0x%02x!\n", 
scancode);
+        return;
+      }
       if (shift_flags & 0x08) { /* ALT */
         asciicode = scan_to_scanascii[scancode].alt;
         scancode = scan_to_scanascii[scancode].alt >> 8;
-        }
-      else if (shift_flags & 0x04) { /* CONTROL */
+      } else if (shift_flags & 0x04) { /* CONTROL */
         asciicode = scan_to_scanascii[scancode].control;
         scancode = scan_to_scanascii[scancode].control >> 8;
-        }
-      else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */
-        /* check if lock state should be ignored 
+      } else if (((mf2_state & 0x02) > 0) && ((scancode >= 0x47) && (scancode 
<= 0x53))) {
+        /* extended keys handling */
+        asciicode = 0xe0;
+        scancode = scan_to_scanascii[scancode].normal >> 8;
+      } else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */
+        /* check if lock state should be ignored
          * because a SHIFT key are pressed */
-         
+
         if (shift_flags & scan_to_scanascii[scancode].lock_flags) {
           asciicode = scan_to_scanascii[scancode].normal;
           scancode = scan_to_scanascii[scancode].normal >> 8;
-          }
-        else {
+        } else {
           asciicode = scan_to_scanascii[scancode].shift;
           scancode = scan_to_scanascii[scancode].shift >> 8;
-          }
-        }
-      else {
+        }
+      } else {
         /* check if lock is on */
         if (shift_flags & scan_to_scanascii[scancode].lock_flags) {
           asciicode = scan_to_scanascii[scancode].shift;
           scancode = scan_to_scanascii[scancode].shift >> 8;
-          }
-        else {
+        } else {
           asciicode = scan_to_scanascii[scancode].normal;
           scancode = scan_to_scanascii[scancode].normal >> 8;
-          }
-        }
+        }
+      }
       if (scancode==0 && asciicode==0) {
         BX_INFO("KBD: int09h_handler(): scancode & asciicode are zero?\n");
-        }
+      }
       enqueue_key(scancode, asciicode);
       break;
-    }
-  mf2_state &= ~0x01;
+  }
+  if ((scancode & 0x7f) != 0x1d) {
+    mf2_state &= ~0x01;
+  }
+  mf2_state &= ~0x02;
+  write_byte(0x0040, 0x96, mf2_state);
 }
 
   unsigned int
@@ -5069,9 +5369,6 @@
   Bit8u scan_code, ascii_code;
 {
   Bit16u buffer_start, buffer_end, buffer_head, buffer_tail, temp_tail;
-
-  //BX_INFO("KBD:   enqueue_key() called scan:%02x, ascii:%02x\n",
-  //    scan_code, ascii_code);
 
 #if BX_CPU < 2
   buffer_start = 0x001E;
@@ -5122,9 +5419,8 @@
   mouse_flags_2 = read_byte(ebda_seg, 0x0027);
 
   if ( (mouse_flags_2 & 0x80) != 0x80 ) {
-      //    BX_PANIC("int74_function:\n");
-      return;
-    }
+      return;
+  }
 
   package_count = mouse_flags_2 & 0x07;
   index = mouse_flags_1 & 0x07;
@@ -5152,10 +5448,10 @@
 #if BX_USE_ATADRV
 
   void
-int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
-  Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
-{
-  Bit32u lba;
+int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
+  Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
+{
+  Bit32u lba_low, lba_high;
   Bit16u ebda_seg=read_word(0x0040,0x000E);
   Bit16u cylinder, head, sector;
   Bit16u segment, offset;
@@ -5176,12 +5472,12 @@
   // Get the ata channel
   device=read_byte(ebda_seg,&EbdaData->ata.hdidmap[GET_ELDL()-0x80]);
 
-  // basic check : device has to be valid 
+  // basic check : device has to be valid
   if (device >= BX_MAX_ATA_DEVICES) {
     BX_INFO("int13_harddisk: function %02x, unmapped device for ELDL=%02x\n", 
GET_AH(), GET_ELDL());
     goto int13_fail;
     }
-  
+
   switch (GET_AH()) {
 
     case 0x00: /* disk controller reset */
@@ -5199,7 +5495,7 @@
       break;
 
     case 0x02: // read disk sectors
-    case 0x03: // write disk sectors 
+    case 0x03: // write disk sectors
     case 0x04: // verify disk sectors
 
       count       = GET_AL();
@@ -5211,10 +5507,10 @@
       segment = ES;
       offset  = BX;
 
-      if ( (count > 128) || (count == 0) ) {
-        BX_INFO("int13_harddisk: function %02x, count out of 
range!\n",GET_AH());
+      if ((count > 128) || (count == 0) || (sector == 0)) {
+        BX_INFO("int13_harddisk: function %02x, parameter out of 
range!\n",GET_AH());
         goto int13_fail;
-        }
+      }
 
       nlc   = read_word(ebda_seg, 
&EbdaData->ata.devices[device].lchs.cylinders);
       nlh   = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
@@ -5225,7 +5521,7 @@
         BX_INFO("int13_harddisk: function %02x, parameters out of range 
%04x/%04x/%04x!\n", GET_AH(), cylinder, head, sector);
         goto int13_fail;
         }
-      
+
       // FIXME verify
       if ( GET_AH() == 0x04 ) goto int13_success;
 
@@ -5234,14 +5530,15 @@
 
       // if needed, translate lchs to lba, and execute command
       if ( (nph != nlh) || (npspt != nlspt)) {
-        lba = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * 
(Bit32u)nlspt) + (Bit32u)sector - 1;
+        lba_low = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * 
(Bit32u)nlspt) + (Bit32u)sector - 1;
+        lba_high = 0;
         sector = 0; // this forces the command to be lba
         }
 
       if ( GET_AH() == 0x02 )
-        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, 
head, sector, lba, segment, offset);
+        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, 
head, sector, lba_low, lba_high, segment, offset);
       else
-        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 
cylinder, head, sector, lba, segment, offset);
+        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 
cylinder, head, sector, lba_low, lba_high, segment, offset);
 
       // Set nb of sector transferred
       SET_AL(read_word(ebda_seg, &EbdaData->ata.trsfsectors));
@@ -5262,7 +5559,7 @@
       break;
 
     case 0x08: /* read disk drive parameters */
-      
+
       // Get logical geometry from table
       nlc   = read_word(ebda_seg, 
&EbdaData->ata.devices[device].lchs.cylinders);
       nlh   = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
@@ -5277,13 +5574,13 @@
       SET_DL(count); /* FIXME returns 0, 1, or n hard drives */
 
       // FIXME should set ES & DI
-      
+
       goto int13_success;
       break;
 
     case 0x10: /* check drive ready */
       // should look at 40:8E also???
-      
+
       // Read the status from controller
       status = inb(read_word(ebda_seg, 
&EbdaData->ata.channels[device/2].iobase1) + ATA_CB_STAT);
       if ( (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY 
) {
@@ -5297,15 +5594,15 @@
 
     case 0x15: /* read disk drive size */
 
-      // Get physical geometry from table
-      npc   = read_word(ebda_seg, 
&EbdaData->ata.devices[device].pchs.cylinders);
-      nph   = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads);
-      npspt = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt);
+      // Get logical geometry from table
+      nlc   = read_word(ebda_seg, 
&EbdaData->ata.devices[device].lchs.cylinders);
+      nlh   = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.heads);
+      nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt);
 
       // Compute sector count seen by int13
-      lba = (Bit32u)(npc - 1) * (Bit32u)nph * (Bit32u)npspt;
-      CX = lba >> 16;
-      DX = lba & 0xffff;
+      lba_low = (Bit32u)(nlc - 1) * (Bit32u)nlh * (Bit32u)nlspt;
+      CX = lba_low >> 16;
+      DX = lba_low & 0xffff;
 
       SET_AH(3);  // hard disk accessible
       goto int13_success_noah;
@@ -5326,17 +5623,18 @@
       count=read_word(DS, SI+(Bit16u)&Int13Ext->count);
       segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
       offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
- 
-      // Can't use 64 bits lba
-      lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
-      if (lba != 0L) {
-        BX_PANIC("int13_harddisk: function %02x. Can't use 64bits 
lba\n",GET_AH());
+
+      // Get 32 msb lba and check
+      lba_high=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
+      if (lba_high > read_dword(ebda_seg, 
&EbdaData->ata.devices[device].sectors_high) ) {
+        BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
         goto int13_fail;
         }
 
-      // Get 32 bits lba and check
-      lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
-      if (lba >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors) 
) {
+      // Get 32 lsb lba and check
+      lba_low=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
+      if (lba_high == read_dword(ebda_seg, 
&EbdaData->ata.devices[device].sectors_high)
+          && lba_low >= read_dword(ebda_seg, 
&EbdaData->ata.devices[device].sectors_low) ) {
         BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
         goto int13_fail;
         }
@@ -5344,12 +5642,12 @@
       // If verify or seek
       if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
         goto int13_success;
-      
+
       // Execute the command
       if ( GET_AH() == 0x42 )
-        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, 
lba, segment, offset);
+        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, 
lba_low, lba_high, segment, offset);
       else
-        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, 
lba, segment, offset);
+        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, 
lba_low, lba_high, segment, offset);
 
       count=read_word(ebda_seg, &EbdaData->ata.trsfsectors);
       write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
@@ -5367,7 +5665,7 @@
     case 0x49: // IBM/MS extended media change
       goto int13_success;    // Always success for HD
       break;
-      
+
     case 0x46: // IBM/MS eject media
       SET_AH(0xb2);          // Volume Not Removable
       goto int13_fail_noah;  // Always fail for HD
@@ -5377,7 +5675,7 @@
       size=read_word(DS,SI+(Bit16u)&Int13DPT->size);
 
       // Buffer is too small
-      if(size < 0x1a) 
+      if(size < 0x1a)
         goto int13_fail;
 
       // EDD 1.x
@@ -5387,17 +5685,26 @@
         npc     = read_word(ebda_seg, 
&EbdaData->ata.devices[device].pchs.cylinders);
         nph     = read_word(ebda_seg, 
&EbdaData->ata.devices[device].pchs.heads);
         npspt   = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt);
-        lba     = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors);
+        lba_low = read_dword(ebda_seg, 
&EbdaData->ata.devices[device].sectors_low);
+        lba_high = read_dword(ebda_seg, 
&EbdaData->ata.devices[device].sectors_high);
         blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize);
 
         write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
-        write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is valid
-        write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc);
+        if (lba_high || (lba_low/npspt)/nph > 0x3fff)
+        {
+          write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x00); // geometry is 
invalid
+          write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0x3fff);
+        }
+        else
+        {
+          write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x02); // geometry is 
valid
+          write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, (Bit32u)npc);
+        }
         write_dword(DS, SI+(Bit16u)&Int13DPT->heads, (Bit32u)nph);
         write_dword(DS, SI+(Bit16u)&Int13DPT->spt, (Bit32u)npspt);
-        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba);  // FIXME 
should be Bit64
-        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0L);  
-        write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);  
+        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba_low);
+        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, lba_high);
+        write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
         }
 
       // EDD 2.x
@@ -5407,8 +5714,8 @@
 
         write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e);
 
-        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);  
-        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, 
&EbdaData->ata.dpte);  
+        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);
+        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte);
 
         // Fill in dpte
         channel = device / 2;
@@ -5418,14 +5725,365 @@
         mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
         translation = read_byte(ebda_seg, 
&EbdaData->ata.devices[device].translation);
 
-        options  = (translation==ATA_TRANSLATION_NONE?0:1<<3); // chs 
translation
+        options  = (translation==ATA_TRANSLATION_NONE?0:1)<<3; // chs 
translation
         options |= (1<<4); // lba translation
+        options |= (mode==ATA_MODE_PIO32?1:0)<<7;
+        options |= (translation==ATA_TRANSLATION_LBA?1:0)<<9;
+        options |= (translation==ATA_TRANSLATION_RECHS?3:0)<<9;
+
+        write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1);
+        write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC);
+        write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 
2))<<4 );
+        write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
+        write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
+        write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 );
+        write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 );
+        write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 );
+        write_word(ebda_seg, &EbdaData->ata.dpte.options, options);
+        write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0);
+        if (size >=0x42)
+          write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
+        else
+          write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x10);
+
+        checksum=0;
+        for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, 
((Bit8u*)(&EbdaData->ata.dpte)) + i);
+        checksum = ~checksum;
+        write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
+        }
+
+      // EDD 3.x
+      if(size >= 0x42) {
+        Bit8u channel, iface, checksum, i;
+        Bit16u iobase1;
+
+        channel = device / 2;
+        iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface);
+        iobase1 = read_word(ebda_seg, 
&EbdaData->ata.channels[channel].iobase1);
+
+        write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42);
+        write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd);
+        write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24);
+        write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0);
+        write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0);
+
+        if (iface==ATA_IFACE_ISA) {
+          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I');
+          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S');
+          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
+          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
+          }
+        else {
+          // FIXME PCI
+          }
+        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
+        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T');
+        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A');
+        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0);
+
+        if (iface==ATA_IFACE_ISA) {
+          write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1);
+          write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
+          write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
+          }
+        else {
+          // FIXME PCI
+          }
+        write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
+        write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0);
+        write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0);
+        write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L);
+
+        checksum=0;
+        for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i);
+        checksum = ~checksum;
+        write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum);
+        }
+
+      goto int13_success;
+      break;
+
+    case 0x4e: // // IBM/MS set hardware configuration
+      // DMA, prefetch, PIO maximum not supported
+      switch (GET_AL()) {
+        case 0x01:
+        case 0x03:
+        case 0x04:
+        case 0x06:
+          goto int13_success;
+          break;
+        default :
+          goto int13_fail;
+        }
+      break;
+
+    case 0x09: /* initialize drive parameters */
+    case 0x0c: /* seek to specified cylinder */
+    case 0x0d: /* alternate disk reset */
+    case 0x11: /* recalibrate */
+    case 0x14: /* controller internal diagnostic */
+      BX_INFO("int13_harddisk: function %02xh unimplemented, returns 
success\n", GET_AH());
+      goto int13_success;
+      break;
+
+    case 0x0a: /* read disk sectors with ECC */
+    case 0x0b: /* write disk sectors with ECC */
+    case 0x18: // set media type for format
+    case 0x50: // IBM/MS send packet command
+    default:
+      BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", 
GET_AH());
+      goto int13_fail;
+      break;
+    }
+
+int13_fail:
+    SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
+int13_fail_noah:
+    SET_DISK_RET_STATUS(GET_AH());
+int13_fail_nostatus:
+    SET_CF();     // error occurred
+    return;
+
+int13_success:
+    SET_AH(0x00); // no error
+int13_success_noah:
+    SET_DISK_RET_STATUS(0x00);
+    CLEAR_CF();   // no error
+    return;
+}
+
+// ---------------------------------------------------------------------------
+// Start of int13 for cdrom
+// ---------------------------------------------------------------------------
+
+  void
+int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
+  Bit16u EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
+{
+  Bit16u ebda_seg=read_word(0x0040,0x000E);
+  Bit8u  device, status, locks;
+  Bit8u  atacmd[12];
+  Bit32u lba;
+  Bit16u count, segment, offset, i, size;
+
+  BX_DEBUG_INT13_CD("int13_cdrom: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", 
AX, BX, CX, DX, ES);
+
+  SET_DISK_RET_STATUS(0x00);
+
+  /* basic check : device should be 0xE0+ */
+  if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0+BX_MAX_ATA_DEVICES) ) {
+    BX_INFO("int13_cdrom: function %02x, ELDL out of range %02x\n", GET_AH(), 
GET_ELDL());
+    goto int13_fail;
+    }
+
+  // Get the ata channel
+  device=read_byte(ebda_seg,&EbdaData->ata.cdidmap[GET_ELDL()-0xE0]);
+
+  /* basic check : device has to be valid  */
+  if (device >= BX_MAX_ATA_DEVICES) {
+    BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n", 
GET_AH(), GET_ELDL());
+    goto int13_fail;
+    }
+
+  switch (GET_AH()) {
+
+    // all those functions return SUCCESS
+    case 0x00: /* disk controller reset */
+    case 0x09: /* initialize drive parameters */
+    case 0x0c: /* seek to specified cylinder */
+    case 0x0d: /* alternate disk reset */
+    case 0x10: /* check drive ready */
+    case 0x11: /* recalibrate */
+    case 0x14: /* controller internal diagnostic */
+    case 0x16: /* detect disk change */
+      goto int13_success;
+      break;
+
+    // all those functions return disk write-protected
+    case 0x03: /* write disk sectors */
+    case 0x05: /* format disk track */
+    case 0x43: // IBM/MS extended write
+      SET_AH(0x03);
+      goto int13_fail_noah;
+      break;
+
+    case 0x01: /* read disk status */
+      status = read_byte(0x0040, 0x0074);
+      SET_AH(status);
+      SET_DISK_RET_STATUS(0);
+
+      /* set CF if error status read */
+      if (status) goto int13_fail_nostatus;
+      else        goto int13_success_noah;
+      break;
+
+    case 0x15: /* read disk drive size */
+      SET_AH(0x02);
+      goto int13_fail_noah;
+      break;
+
+    case 0x41: // IBM/MS installation check
+      BX=0xaa55;     // install check
+      SET_AH(0x30);  // EDD 2.1
+      CX=0x0007;     // ext disk access, removable and edd
+      goto int13_success_noah;
+      break;
+
+    case 0x42: // IBM/MS extended read
+    case 0x44: // IBM/MS verify sectors
+    case 0x47: // IBM/MS extended seek
+
+      count=read_word(DS, SI+(Bit16u)&Int13Ext->count);
+      segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
+      offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
+
+      // Can't use 64 bits lba
+      lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
+      if (lba != 0L) {
+        BX_PANIC("int13_cdrom: function %02x. Can't use 64bits 
lba\n",GET_AH());
+        goto int13_fail;
+        }
+
+      // Get 32 bits lba
+      lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
+
+      // If verify or seek
+      if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
+        goto int13_success;
+
+      memsetb(get_SS(),atacmd,0,12);
+      atacmd[0]=0x28;                      // READ command
+      atacmd[7]=(count & 0xff00) >> 8;     // Sectors
+      atacmd[8]=(count & 0x00ff);          // Sectors
+      atacmd[2]=(lba & 0xff000000) >> 24;  // LBA
+      atacmd[3]=(lba & 0x00ff0000) >> 16;
+      atacmd[4]=(lba & 0x0000ff00) >> 8;
+      atacmd[5]=(lba & 0x000000ff);
+      status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L, 
ATA_DATA_IN, segment,offset);
+
+      count = (Bit16u)(read_dword(ebda_seg, &EbdaData->ata.trsfbytes) >> 11);
+      write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
+
+      if (status != 0) {
+        BX_INFO("int13_cdrom: function %02x, status %02x !\n",GET_AH(),status);
+        SET_AH(0x0c);
+        goto int13_fail_noah;
+        }
+
+      goto int13_success;
+      break;
+
+    case 0x45: // IBM/MS lock/unlock drive
+      if (GET_AL() > 2) goto int13_fail;
+
+      locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
+
+      switch (GET_AL()) {
+        case 0 :  // lock
+          if (locks == 0xff) {
+            SET_AH(0xb4);
+            SET_AL(1);
+            goto int13_fail_noah;
+            }
+          write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, ++locks);
+          SET_AL(1);
+          break;
+        case 1 :  // unlock
+          if (locks == 0x00) {
+            SET_AH(0xb0);
+            SET_AL(0);
+            goto int13_fail_noah;
+            }
+          write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, --locks);
+          SET_AL(locks==0?0:1);
+          break;
+        case 2 :  // status
+          SET_AL(locks==0?0:1);
+          break;
+        }
+      goto int13_success;
+      break;
+
+    case 0x46: // IBM/MS eject media
+      locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
+
+      if (locks != 0) {
+        SET_AH(0xb1); // media locked
+        goto int13_fail_noah;
+        }
+      // FIXME should handle 0x31 no media in device
+      // FIXME should handle 0xb5 valid request failed
+
+      // Call removable media eject
+      ASM_START
+        push bp
+        mov  bp, sp
+
+        mov ah, #0x52
+        int #0x15
+        mov _int13_cdrom.status + 2[bp], ah
+        jnc int13_cdrom_rme_end
+        mov _int13_cdrom.status, #1
+int13_cdrom_rme_end:
+        pop bp
+      ASM_END
+
+      if (status != 0) {
+        SET_AH(0xb1); // media locked
+        goto int13_fail_noah;
+      }
+
+      goto int13_success;
+      break;
+
+    case 0x48: // IBM/MS get drive parameters
+      size = read_word(DS,SI+(Bit16u)&Int13Ext->size);
+
+      // Buffer is too small
+      if(size < 0x1a)
+        goto int13_fail;
+
+      // EDD 1.x
+      if(size >= 0x1a) {
+        Bit16u   cylinders, heads, spt, blksize;
+
+        blksize   = read_word(ebda_seg, 
&EbdaData->ata.devices[device].blksize);
+
+        write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
+        write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x74); // removable, media 
change, lockable, max values
+        write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0xffffffff);
+        write_dword(DS, SI+(Bit16u)&Int13DPT->heads, 0xffffffff);
+        write_dword(DS, SI+(Bit16u)&Int13DPT->spt, 0xffffffff);
+        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, 0xffffffff);  // 
FIXME should be Bit64
+        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff);
+        write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
+        }
+
+      // EDD 2.x
+      if(size >= 0x1e) {
+        Bit8u  channel, dev, irq, mode, checksum, i;
+        Bit16u iobase1, iobase2, options;
+
+        write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e);
+
+        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);
+        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, &EbdaData->ata.dpte);
+
+        // Fill in dpte
+        channel = device / 2;
+        iobase1 = read_word(ebda_seg, 
&EbdaData->ata.channels[channel].iobase1);
+        iobase2 = read_word(ebda_seg, 
&EbdaData->ata.channels[channel].iobase2);
+        irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq);
+        mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
+
+        // FIXME atapi device
+        options  = (1<<4); // lba translation
+        options |= (1<<5); // removable device
+        options |= (1<<6); // atapi device
         options |= (mode==ATA_MODE_PIO32?1:0<<7);
-        options |= (translation==ATA_TRANSLATION_LBA?1:0<<9); 
-        options |= (translation==ATA_TRANSLATION_RECHS?3:0<<9); 
 
         write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1);
-        write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2);
+        write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC);
         write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 
2))<<4 );
         write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
         write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
@@ -5435,9 +6093,9 @@
         write_word(ebda_seg, &EbdaData->ata.dpte.options, options);
         write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0);
         write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
- 
+
         checksum=0;
-        for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, 
(&EbdaData->ata.dpte) + i);
+        for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, 
((Bit8u*)(&EbdaData->ata.dpte)) + i);
         checksum = ~checksum;
         write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
         }
@@ -5463,7 +6121,7 @@
           write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
           write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
           }
-        else { 
+        else {
           // FIXME PCI
           }
         write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
@@ -5476,7 +6134,7 @@
           write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
           write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
           }
-        else { 
+        else {
           // FIXME PCI
           }
         write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
@@ -5491,6 +6149,12 @@
         }
 
       goto int13_success;
+      break;
+
+    case 0x49: // IBM/MS extended media change
+      // always send changed ??
+      SET_AH(06);
+      goto int13_fail_nostatus;
       break;
 
     case 0x4e: // // IBM/MS set hardware configuration
@@ -5507,361 +6171,6 @@
         }
       break;
 
-    case 0x09: /* initialize drive parameters */
-    case 0x0c: /* seek to specified cylinder */
-    case 0x0d: /* alternate disk reset */
-    case 0x11: /* recalibrate */
-    case 0x14: /* controller internal diagnostic */
-      BX_INFO("int13h_harddisk function %02xh unimplemented, returns 
success\n", GET_AH());
-      goto int13_success;
-      break;
-
-    case 0x0a: /* read disk sectors with ECC */
-    case 0x0b: /* write disk sectors with ECC */
-    case 0x18: // set media type for format
-    case 0x50: // IBM/MS send packet command
-    default:
-      BX_INFO("int13_harddisk function %02xh unsupported, returns fail\n", 
GET_AH());
-      goto int13_fail;
-      break;
-    }
-
-int13_fail:
-    SET_AH(0x01); // defaults to invalid function in AH or invalid parameter
-int13_fail_noah:
-    SET_DISK_RET_STATUS(GET_AH());
-int13_fail_nostatus:
-    SET_CF();     // error occurred
-    return;
-
-int13_success:
-    SET_AH(0x00); // no error
-int13_success_noah:
-    SET_DISK_RET_STATUS(0x00);
-    CLEAR_CF();   // no error
-    return;
-}
-
-// ---------------------------------------------------------------------------
-// Start of int13 for cdrom
-// ---------------------------------------------------------------------------
-
-  void
-int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
-  Bit16u EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
-{
-  Bit16u ebda_seg=read_word(0x0040,0x000E);
-  Bit8u  device, status, locks;
-  Bit8u  atacmd[12];
-  Bit32u lba;
-  Bit16u count, segment, offset, i, size;
-
-  BX_DEBUG_INT13_CD("int13_cdrom: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", 
AX, BX, CX, DX, ES);
-  // BX_DEBUG_INT13_CD("int13_cdrom: SS=%04x DS=%04x ES=%04x DI=%04x 
SI=%04x\n",get_SS(), DS, ES, DI, SI);
-  
-  SET_DISK_RET_STATUS(0x00);
-
-  /* basic check : device should be 0xE0+ */
-  if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0+BX_MAX_ATA_DEVICES) ) {
-    BX_INFO("int13_cdrom: function %02x, ELDL out of range %02x\n", GET_AH(), 
GET_ELDL());
-    goto int13_fail;
-    }
-
-  // Get the ata channel
-  device=read_byte(ebda_seg,&EbdaData->ata.cdidmap[GET_ELDL()-0xE0]);
-
-  /* basic check : device has to be valid  */
-  if (device >= BX_MAX_ATA_DEVICES) {
-    BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n", 
GET_AH(), GET_ELDL());
-    goto int13_fail;
-    }
-  
-  switch (GET_AH()) {
-
-    // all those functions return SUCCESS
-    case 0x00: /* disk controller reset */
-    case 0x09: /* initialize drive parameters */
-    case 0x0c: /* seek to specified cylinder */
-    case 0x0d: /* alternate disk reset */  
-    case 0x10: /* check drive ready */    
-    case 0x11: /* recalibrate */      
-    case 0x14: /* controller internal diagnostic */
-    case 0x16: /* detect disk change */
-      goto int13_success;
-      break;
-
-    // all those functions return disk write-protected
-    case 0x03: /* write disk sectors */
-    case 0x05: /* format disk track */
-    case 0x43: // IBM/MS extended write
-      SET_AH(0x03);
-      goto int13_fail_noah;
-      break;
-
-    case 0x01: /* read disk status */
-      status = read_byte(0x0040, 0x0074);
-      SET_AH(status);
-      SET_DISK_RET_STATUS(0);
-
-      /* set CF if error status read */
-      if (status) goto int13_fail_nostatus;
-      else        goto int13_success_noah;
-      break;      
-
-    case 0x15: /* read disk drive size */
-      SET_AH(0x02);
-      goto int13_fail_noah;
-      break;
-
-    case 0x41: // IBM/MS installation check
-      BX=0xaa55;     // install check
-      SET_AH(0x30);  // EDD 2.1
-      CX=0x0007;     // ext disk access, removable and edd
-      goto int13_success_noah;
-      break;
-
-    case 0x42: // IBM/MS extended read
-    case 0x44: // IBM/MS verify sectors
-    case 0x47: // IBM/MS extended seek
-       
-      count=read_word(DS, SI+(Bit16u)&Int13Ext->count);
-      segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
-      offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
- 
-      // Can't use 64 bits lba
-      lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
-      if (lba != 0L) {
-        BX_PANIC("int13_cdrom: function %02x. Can't use 64bits 
lba\n",GET_AH());
-        goto int13_fail;
-        }
-
-      // Get 32 bits lba 
-      lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
-
-      // If verify or seek
-      if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
-        goto int13_success;
-      
-      memsetb(get_SS(),atacmd,0,12);
-      atacmd[0]=0x28;                      // READ command
-      atacmd[7]=(count & 0xff00) >> 8;     // Sectors
-      atacmd[8]=(count & 0x00ff);          // Sectors
-      atacmd[2]=(lba & 0xff000000) >> 24;  // LBA
-      atacmd[3]=(lba & 0x00ff0000) >> 16;
-      atacmd[4]=(lba & 0x0000ff00) >> 8;
-      atacmd[5]=(lba & 0x000000ff);
-      status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L, 
ATA_DATA_IN, segment,offset); 
-
-      count = (Bit16u)(read_dword(ebda_seg, &EbdaData->ata.trsfbytes) >> 11);
-      write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
-
-      if (status != 0) {
-        BX_INFO("int13_cdrom: function %02x, status %02x !\n",GET_AH(),status);
-        SET_AH(0x0c);
-        goto int13_fail_noah;
-        }
-
-      goto int13_success;
-      break;
-
-    case 0x45: // IBM/MS lock/unlock drive
-      if (GET_AL() > 2) goto int13_fail;
-
-      locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
-
-      switch (GET_AL()) {
-        case 0 :  // lock
-          if (locks == 0xff) {
-            SET_AH(0xb4);
-            SET_AL(1);
-            goto int13_fail_noah;
-            }
-          write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, ++locks);
-          SET_AL(1);
-          break;
-        case 1 :  // unlock
-          if (locks == 0x00) {
-            SET_AH(0xb0);
-            SET_AL(0);
-            goto int13_fail_noah;
-            }
-          write_byte(ebda_seg, &EbdaData->ata.devices[device].lock, --locks);
-          SET_AL(locks==0?0:1);
-          break;
-        case 2 :  // status
-          SET_AL(locks==0?0:1);
-          break;
-        }
-      goto int13_success;
-      break;
-
-    case 0x46: // IBM/MS eject media
-      locks = read_byte(ebda_seg, &EbdaData->ata.devices[device].lock);
-      
-      if (locks != 0) {
-        SET_AH(0xb1); // media locked
-        goto int13_fail_noah;
-        }
-      // FIXME should handle 0x31 no media in device
-      // FIXME should handle 0xb5 valid request failed
-    
-      // Call removable media eject
-      ASM_START
-        push bp
-        mov  bp, sp
-
-        mov ah, #0x52
-        int 15
-        mov _int13_cdrom.status + 2[bp], ah
-        jnc int13_cdrom_rme_end
-        mov _int13_cdrom.status, #1
-int13_cdrom_rme_end:
-        pop bp
-      ASM_END
-
-      if (status != 0) {
-        SET_AH(0xb1); // media locked
-        goto int13_fail_noah;
-      }
-
-      goto int13_success;
-      break;
-
-    case 0x48: // IBM/MS get drive parameters
-      size = read_word(DS,SI+(Bit16u)&Int13Ext->size);
-
-      // Buffer is too small
-      if(size < 0x1a) 
-        goto int13_fail;
-
-      // EDD 1.x
-      if(size >= 0x1a) {
-        Bit16u   cylinders, heads, spt, blksize;
-
-        blksize   = read_word(ebda_seg, 
&EbdaData->ata.devices[device].blksize);
-
-        write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
-        write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x74); // removable, media 
change, lockable, max values
-        write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0xffffffff);
-        write_dword(DS, SI+(Bit16u)&Int13DPT->heads, 0xffffffff);
-        write_dword(DS, SI+(Bit16u)&Int13DPT->spt, 0xffffffff);
-        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, 0xffffffff);  // 
FIXME should be Bit64
-        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0xffffffff);  
-        write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);  
-        }
-
-      // EDD 2.x
-      if(size >= 0x1e) {
-        Bit8u  channel, dev, irq, mode, checksum, i;
-        Bit16u iobase1, iobase2, options;
-
-        write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1e);
-
-        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_segment, ebda_seg);  
-        write_word(DS, SI+(Bit16u)&Int13DPT->dpte_offset, 
&EbdaData->ata.dpte);  
-
-        // Fill in dpte
-        channel = device / 2;
-        iobase1 = read_word(ebda_seg, 
&EbdaData->ata.channels[channel].iobase1);
-        iobase2 = read_word(ebda_seg, 
&EbdaData->ata.channels[channel].iobase2);
-        irq = read_byte(ebda_seg, &EbdaData->ata.channels[channel].irq);
-        mode = read_byte(ebda_seg, &EbdaData->ata.devices[device].mode);
-
-        // FIXME atapi device
-        options  = (1<<4); // lba translation
-        options |= (1<<5); // removable device
-        options |= (1<<6); // atapi device
-        options |= (mode==ATA_MODE_PIO32?1:0<<7);
-
-        write_word(ebda_seg, &EbdaData->ata.dpte.iobase1, iobase1);
-        write_word(ebda_seg, &EbdaData->ata.dpte.iobase2, iobase2);
-        write_byte(ebda_seg, &EbdaData->ata.dpte.prefix, (0xe | (device % 
2))<<4 );
-        write_byte(ebda_seg, &EbdaData->ata.dpte.unused, 0xcb );
-        write_byte(ebda_seg, &EbdaData->ata.dpte.irq, irq );
-        write_byte(ebda_seg, &EbdaData->ata.dpte.blkcount, 1 );
-        write_byte(ebda_seg, &EbdaData->ata.dpte.dma, 0 );
-        write_byte(ebda_seg, &EbdaData->ata.dpte.pio, 0 );
-        write_word(ebda_seg, &EbdaData->ata.dpte.options, options);
-        write_word(ebda_seg, &EbdaData->ata.dpte.reserved, 0);
-        write_byte(ebda_seg, &EbdaData->ata.dpte.revision, 0x11);
-
-        checksum=0;
-        for (i=0; i<15; i++) checksum+=read_byte(ebda_seg, 
(&EbdaData->ata.dpte) + i);
-        checksum = ~checksum;
-        write_byte(ebda_seg, &EbdaData->ata.dpte.checksum, checksum);
-        }
-
-      // EDD 3.x
-      if(size >= 0x42) {
-        Bit8u channel, iface, checksum, i;
-        Bit16u iobase1;
-
-        channel = device / 2;
-        iface = read_byte(ebda_seg, &EbdaData->ata.channels[channel].iface);
-        iobase1 = read_word(ebda_seg, 
&EbdaData->ata.channels[channel].iobase1);
-
-        write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x42);
-        write_word(DS, SI+(Bit16u)&Int13DPT->key, 0xbedd);
-        write_byte(DS, SI+(Bit16u)&Int13DPT->dpi_length, 0x24);
-        write_byte(DS, SI+(Bit16u)&Int13DPT->reserved1, 0);
-        write_word(DS, SI+(Bit16u)&Int13DPT->reserved2, 0);
-
-        if (iface==ATA_IFACE_ISA) {
-          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[0], 'I');
-          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[1], 'S');
-          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[2], 'A');
-          write_byte(DS, SI+(Bit16u)&Int13DPT->host_bus[3], 0);
-          }
-        else { 
-          // FIXME PCI
-          }
-        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[0], 'A');
-        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[1], 'T');
-        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[2], 'A');
-        write_byte(DS, SI+(Bit16u)&Int13DPT->iface_type[3], 0);
-
-        if (iface==ATA_IFACE_ISA) {
-          write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[0], iobase1);
-          write_word(DS, SI+(Bit16u)&Int13DPT->iface_path[2], 0);
-          write_dword(DS, SI+(Bit16u)&Int13DPT->iface_path[4], 0L);
-          }
-        else { 
-          // FIXME PCI
-          }
-        write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[0], device%2);
-        write_byte(DS, SI+(Bit16u)&Int13DPT->device_path[1], 0);
-        write_word(DS, SI+(Bit16u)&Int13DPT->device_path[2], 0);
-        write_dword(DS, SI+(Bit16u)&Int13DPT->device_path[4], 0L);
-
-        checksum=0;
-        for (i=30; i<64; i++) checksum+=read_byte(DS, SI + i);
-        checksum = ~checksum;
-        write_byte(DS, SI+(Bit16u)&Int13DPT->checksum, checksum);
-        }
-
-      goto int13_success;
-      break;
-
-    case 0x49: // IBM/MS extended media change
-      // always send changed ??
-      SET_AH(06);
-      goto int13_fail_nostatus;
-      break;
-      
-    case 0x4e: // // IBM/MS set hardware configuration
-      // DMA, prefetch, PIO maximum not supported
-      switch (GET_AL()) {
-        case 0x01:
-        case 0x03:
-        case 0x04:
-        case 0x06:
-          goto int13_success;
-          break;
-        default :
-          goto int13_fail;
-        }
-      break;
-
     // all those functions return unimplemented
     case 0x02: /* read sectors */
     case 0x04: /* verify sectors */
@@ -5909,7 +6218,7 @@
 
   BX_DEBUG_INT13_ET("int13_eltorito: AX=%04x BX=%04x CX=%04x DX=%04x 
ES=%04x\n", AX, BX, CX, DX, ES);
   // BX_DEBUG_INT13_ET("int13_eltorito: SS=%04x DS=%04x ES=%04x DI=%04x 
SI=%04x\n",get_SS(), DS, ES, DI, SI);
-  
+
   switch (GET_AH()) {
 
     // FIXME ElTorito Various. Should be implemented
@@ -5984,11 +6293,10 @@
   Bit8u  atacmd[12];
 
   BX_DEBUG_INT13_ET("int13_cdemu: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", 
AX, BX, CX, DX, ES);
-  //BX_DEBUG_INT13_ET("int13_cdemu: SS=%04x ES=%04x DI=%04x SI=%04x\n", 
get_SS(), ES, DI, SI);
-  
+
   /* at this point, we are emulating a floppy/harddisk */
-  
-  // Recompute the device number 
+
+  // Recompute the device number
   device  = read_byte(ebda_seg,&EbdaData->cdemu.controller_index) * 2;
   device += read_byte(ebda_seg,&EbdaData->cdemu.device_spec);
 
@@ -6001,7 +6309,6 @@
     goto int13_fail;
     }
 
-  
   switch (GET_AH()) {
 
     // all those functions return SUCCESS
@@ -6010,7 +6317,7 @@
     case 0x0c: /* seek to specified cylinder */
     case 0x0d: /* alternate disk reset */  // FIXME ElTorito Various. should 
really reset ?
     case 0x10: /* check drive ready */     // FIXME ElTorito Various. should 
check if ready ?
-    case 0x11: /* recalibrate */      
+    case 0x11: /* recalibrate */
     case 0x14: /* controller internal diagnostic */
     case 0x16: /* detect disk change */
       goto int13_success;
@@ -6035,9 +6342,9 @@
 
     case 0x02: // read disk sectors
     case 0x04: // verify disk sectors
-      vspt       = read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt); 
-      vcylinders = read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders); 
-      vheads     = read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads); 
+      vspt       = read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt);
+      vcylinders = read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders);
+      vheads     = read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads);
 
       ilba       = read_dword(ebda_seg,&EbdaData->cdemu.ilba);
 
@@ -6066,17 +6373,17 @@
 
       // calculate the virtual lba inside the image
       
vlba=((((Bit32u)cylinder*(Bit32u)vheads)+(Bit32u)head)*(Bit32u)vspt)+((Bit32u)(sector-1));
- 
+
       // In advance so we don't loose the count
       SET_AL(nbsectors);
 
       // start lba on cd
-      slba  = (Bit32u)vlba/4; 
+      slba  = (Bit32u)vlba/4;
       before= (Bit16u)vlba%4;
 
       // end lba on cd
       elba = (Bit32u)(vlba+nbsectors-1)/4;
-      
+
       memsetb(get_SS(),atacmd,0,12);
       atacmd[0]=0x28;                      // READ command
       atacmd[7]=((Bit16u)(elba-slba+1) & 0xff00) >> 8; // Sectors
@@ -6096,10 +6403,10 @@
       break;
 
     case 0x08: /* read disk drive parameters */
-      vspt=read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt); 
-      vcylinders=read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders) - 1; 
-      vheads=read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads) - 1; 
- 
+      vspt=read_word(ebda_seg,&EbdaData->cdemu.vdevice.spt);
+      vcylinders=read_word(ebda_seg,&EbdaData->cdemu.vdevice.cylinders) - 1;
+      vheads=read_word(ebda_seg,&EbdaData->cdemu.vdevice.heads) - 1;
+
       SET_AL( 0x00 );
       SET_BL( 0x00 );
       SET_CH( vcylinders & 0xff );
@@ -6107,7 +6414,7 @@
       SET_DH( vheads );
       SET_DL( 0x02 );   // FIXME ElTorito Various. should send the real count 
of drives 1 or 2
                         // FIXME ElTorito Harddisk. should send the HD count
- 
+
       switch(read_byte(ebda_seg,&EbdaData->cdemu.media)) {
         case 0x01: SET_BL( 0x02 ); break;
         case 0x02: SET_BL( 0x04 ); break;
@@ -6143,7 +6450,7 @@
     case 0x45: // IBM/MS lock/unlock drive
     case 0x46: // IBM/MS eject media
     case 0x47: // IBM/MS extended seek
-    case 0x48: // IBM/MS get drive parameters 
+    case 0x48: // IBM/MS get drive parameters
     case 0x49: // IBM/MS extended media change
     case 0x4e: // ? - set hardware configuration
     case 0x50: // ? - send packet command
@@ -6231,8 +6538,8 @@
 }
 
   void
-int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
-  Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
+int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
+  Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
 {
   Bit8u    drive, num_sectors, sector, head, status, mod;
   Bit8u    drive_map;
@@ -6338,7 +6645,7 @@
         }
 
       if ( (num_sectors > 128) || (num_sectors == 0) )
-        BX_PANIC("int13_harddisk(): num_sectors out of range!\n");
+        BX_PANIC("int13_harddisk: num_sectors out of range!\n");
 
       if (head > 15)
         BX_PANIC("hard drive BIOS:(read/verify) head > 15\n");
@@ -6484,7 +6791,7 @@
         }
 
       if ( (num_sectors > 128) || (num_sectors == 0) )
-        BX_PANIC("int13_harddisk(): num_sectors out of range!\n");
+        BX_PANIC("int13_harddisk: num_sectors out of range!\n");
 
       if (head > 15)
         BX_PANIC("hard drive BIOS:(read) head > 15\n");
@@ -6594,7 +6901,7 @@
 
     case 0x08: /* read disk drive parameters */
 BX_DEBUG_INT13_HD("int13_f08\n");
-      
+
       drive = GET_ELDL ();
       get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
 
@@ -6734,10 +7041,10 @@
       break;
 
     case 0x18: // set media type for format
-    case 0x41: // IBM/MS 
-    case 0x42: // IBM/MS 
-    case 0x43: // IBM/MS 
-    case 0x44: // IBM/MS 
+    case 0x41: // IBM/MS
+    case 0x42: // IBM/MS
+    case 0x43: // IBM/MS
+    case 0x44: // IBM/MS
     case 0x45: // IBM/MS lock/unlock drive
     case 0x46: // IBM/MS eject media
     case 0x47: // IBM/MS extended seek
@@ -6782,7 +7089,7 @@
     hd_type = inb_cmos(0x12) & 0x0f;
     if (hd_type != 0x0f)
       BX_INFO(panic_msg_reg12h,1);
-    hd_type = inb_cmos(0x1a); // HD0: extended type
+    hd_type = inb_cmos(0x1a); // HD1: extended type
     if (hd_type != 47)
       BX_INFO(panic_msg_reg19h,0,0x1a);
     iobase = 0x24;
@@ -6801,10 +7108,71 @@
 
 #endif //else BX_USE_ATADRV
 
+#if BX_SUPPORT_FLOPPY
 
 //////////////////////
 // FLOPPY functions //
 //////////////////////
+
+void floppy_reset_controller()
+{
+  Bit8u val8;
+
+  // Reset controller
+  val8 = inb(0x03f2);
+  outb(0x03f2, val8 & ~0x04);
+  outb(0x03f2, val8 | 0x04);
+
+  // Wait for controller to come out of reset
+  do {
+    val8 = inb(0x3f4);
+  } while ( (val8 & 0xc0) != 0x80 );
+}
+
+void floppy_prepare_controller(drive)
+  Bit16u drive;
+{
+  Bit8u  val8, dor, prev_reset;
+
+  // set 40:3e bit 7 to 0
+  val8 = read_byte(0x0040, 0x003e);
+  val8 &= 0x7f;
+  write_byte(0x0040, 0x003e, val8);
+
+  // turn on motor of selected drive, DMA & int enabled, normal operation
+  prev_reset = inb(0x03f2) & 0x04;
+  if (drive)
+    dor = 0x20;
+  else
+    dor = 0x10;
+  dor |= 0x0c;
+  dor |= drive;
+  outb(0x03f2, dor);
+
+  // reset the disk motor timeout value of INT 08
+  write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
+
+  // wait for drive readiness
+  do {
+    val8 = inb(0x3f4);
+  } while ( (val8 & 0xc0) != 0x80 );
+
+  if (prev_reset == 0) {
+    // turn on interrupts
+ASM_START
+    sti
+ASM_END
+    // wait on 40:3e bit 7 to become 1
+    do {
+      val8 = read_byte(0x0040, 0x003e);
+    } while ( (val8 & 0x80) == 0 );
+    val8 &= 0x7f;
+ASM_START
+    cli
+ASM_END
+    write_byte(0x0040, 0x003e, val8);
+  }
+}
 
   bx_bool
 floppy_media_known(drive)
@@ -6912,7 +7280,7 @@
     retval = 1;
     }
   //
-  // Extended floppy size uses special cmos setting 
+  // Extended floppy size uses special cmos setting
   else if ( drive_type == 6 ) {
     // 160k 5.25" drive
     config_data = 0x00; // 0000 0000
@@ -6953,63 +7321,41 @@
 floppy_drive_recal(drive)
   Bit16u drive;
 {
-  Bit8u  val8, dor;
+  Bit8u  val8;
   Bit16u curr_cyl_offset;
 
-  // set 40:3e bit 7 to 0
-  val8 = read_byte(0x0000, 0x043e);
-  val8 &= 0x7f;
-  write_byte(0x0000, 0x043e, val8);
-
-  // turn on motor of selected drive, DMA & int enabled, normal operation
-  if (drive)
-    dor = 0x20;
-  else
-    dor = 0x10;
-  dor |= 0x0c;
-  dor |= drive;
-  outb(0x03f2, dor);
-
-  // reset the disk motor timeout value of INT 08
-  write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
-
-  // check port 3f4 for drive readiness
-  val8 = inb(0x3f4);
-  if ( (val8 & 0xf0) != 0x80 )
-    BX_PANIC("floppy recal:f07: ctrl not ready\n");
+  floppy_prepare_controller(drive);
 
   // send Recalibrate command (2 bytes) to controller
   outb(0x03f5, 0x07);  // 07: Recalibrate
   outb(0x03f5, drive); // 0=drive0, 1=drive1
 
- // turn on interrupts
+  // turn on interrupts
 ASM_START
   sti
 ASM_END
 
   // wait on 40:3e bit 7 to become 1
-  val8 = (read_byte(0x0000, 0x043e) & 0x80);
-  while ( val8 == 0 ) {
-    val8 = (read_byte(0x0000, 0x043e) & 0x80);
-    }
-
- val8 = 0; // separate asm from while() loop
- // turn off interrupts
+  do {
+    val8 = (read_byte(0x0040, 0x003e) & 0x80);
+  } while ( val8 == 0 );
+
+  val8 = 0; // separate asm from while() loop
+  // turn off interrupts
 ASM_START
   cli
 ASM_END
 
   // set 40:3e bit 7 to 0, and calibrated bit
-  val8 = read_byte(0x0000, 0x043e);
+  val8 = read_byte(0x0040, 0x003e);
   val8 &= 0x7f;
   if (drive) {
     val8 |= 0x02; // Drive 1 calibrated
     curr_cyl_offset = 0x0095;
-    }
-  else {
+  } else {
     val8 |= 0x01; // Drive 0 calibrated
     curr_cyl_offset = 0x0094;
-    }
+  }
   write_byte(0x0040, 0x003e, val8);
   write_byte(0x0040, curr_cyl_offset, 0); // current cylinder is 0
 
@@ -7036,7 +7382,6 @@
     return(1);
 }
 
-#if BX_SUPPORT_FLOPPY
   void
 int13_diskette_function(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, 
FLAGS)
   Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
@@ -7049,7 +7394,6 @@
   Bit16u es, last_addr;
 
   BX_DEBUG_INT13_FL("int13_diskette: AX=%04x BX=%04x CX=%04x DX=%04x 
ES=%04x\n", AX, BX, CX, DX, ES);
-  // BX_DEBUG_INT13_FL("int13_diskette: SS=%04x DS=%04x ES=%04x DI=%04x 
SI=%04x\n",get_SS(), get_DS(), ES, DI, SI);
 
   ah = GET_AH();
 
@@ -7062,7 +7406,7 @@
         set_diskette_ret_status(1);
         SET_CF();
         return;
-        }
+      }
       drive_type = inb_cmos(0x10);
 
       if (drive == 0)
@@ -7074,7 +7418,7 @@
         set_diskette_ret_status(0x80);
         SET_CF();
         return;
-        }
+      }
       SET_AH(0);
       set_diskette_ret_status(0);
       CLEAR_CF(); // successful
@@ -7087,7 +7431,7 @@
       SET_AH(val8);
       if (val8) {
         SET_CF();
-        }
+      }
       return;
 
     case 0x02: // Read Diskette Sectors
@@ -7099,15 +7443,15 @@
       head        = GET_DH();
       drive       = GET_ELDL();
 
-      if ( (drive > 1) || (head > 1) ||
-           (num_sectors == 0) || (num_sectors > 72) ) {
-BX_INFO("floppy: drive>1 || head>1 ...\n");
+      if ((drive > 1) || (head > 1) || (sector == 0) ||
+          (num_sectors == 0) || (num_sectors > 72)) {
+        BX_INFO("int13_diskette: read/write/verify: parameter out of range\n");
         SET_AH(1);
         set_diskette_ret_status(1);
         SET_AL(0); // no sectors read
         SET_CF(); // error occurred
         return;
-        }
+      }
 
       // see if drive exists
       if (floppy_drive_exists(drive) == 0) {
@@ -7116,7 +7460,7 @@
         SET_AL(0); // no sectors read
         SET_CF(); // error occurred
         return;
-        }
+      }
 
       // see if media in drive, and type is known
       if (floppy_media_known(drive) == 0) {
@@ -7126,8 +7470,8 @@
           SET_AL(0); // no sectors read
           SET_CF(); // error occurred
           return;
-          }
-        }
+        }
+      }
 
       if (ah == 0x02) {
         // Read Diskette Sectors
@@ -7146,7 +7490,7 @@
         if ( base_address < base_es ) {
           // in case of carry, adjust page by 1
           page++;
-          }
+        }
         base_count = (num_sectors * 512) - 1;
 
         // check for 64K boundary overrun
@@ -7157,7 +7501,7 @@
           SET_AL(0); // no sectors read
           SET_CF(); // error occurred
           return;
-          }
+        }
 
         BX_DEBUG_INT13_FL("masking DMA-1 c2\n");
         outb(0x000a, 0x06);
@@ -7190,28 +7534,7 @@
         //--------------------------------------
         // set up floppy controller for transfer
         //--------------------------------------
-
-        // set 40:3e bit 7 to 0
-        val8 = read_byte(0x0000, 0x043e);
-        val8 &= 0x7f;
-        write_byte(0x0000, 0x043e, val8);
-
-        // turn on motor of selected drive, DMA & int enabled, normal operation
-        if (drive)
-          dor = 0x20;
-        else
-          dor = 0x10;
-        dor |= 0x0c;
-        dor |= drive;
-        outb(0x03f2, dor);
-
-        // reset the disk motor timeout value of INT 08
-        write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
-
-        // check port 3f4 for drive readiness
-        val8 = inb(0x3f4);
-        if ( (val8 & 0xf0) != 0x80 )
-          BX_PANIC("int13_diskette:f02: ctrl not ready\n");
+        floppy_prepare_controller(drive);
 
         // send read-normal-data command (9 bytes) to controller
         outb(0x03f5, 0xe6); // e6: read normal data
@@ -7224,27 +7547,35 @@
         outb(0x03f5, 0); // Gap length
         outb(0x03f5, 0xff); // Gap length
 
-       // turn on interrupts
+        // turn on interrupts
   ASM_START
         sti
   ASM_END
 
         // wait on 40:3e bit 7 to become 1
-        val8 = (read_byte(0x0000, 0x043e) & 0x80);
-        while ( val8 == 0 ) {
-          val8 = (read_byte(0x0000, 0x043e) & 0x80);
-          }
-
-       val8 = 0; // separate asm from while() loop
-       // turn off interrupts
+        do {
+          val8 = read_byte(0x0040, 0x0040);
+          if (val8 == 0) {
+            floppy_reset_controller();
+            SET_AH(0x80); // drive not ready (timeout)
+            set_diskette_ret_status(0x80);
+            SET_AL(0); // no sectors read
+            SET_CF(); // error occurred
+            return;
+          }
+          val8 = (read_byte(0x0040, 0x003e) & 0x80);
+        } while ( val8 == 0 );
+
+        val8 = 0; // separate asm from while() loop
+        // turn off interrupts
   ASM_START
         cli
   ASM_END
 
         // set 40:3e bit 7 to 0
-        val8 = read_byte(0x0000, 0x043e);
+        val8 = read_byte(0x0040, 0x003e);
         val8 &= 0x7f;
-        write_byte(0x0000, 0x043e, val8);
+        write_byte(0x0040, 0x003e, val8);
 
         // check port 3f4 for accessibility to status bytes
         val8 = inb(0x3f4);
@@ -7275,7 +7606,7 @@
           SET_AL(0); // no sectors read
           SET_CF(); // error occurred
           return;
-          }
+        }
 
         // ??? should track be new val from return_status[3] ?
         set_diskette_current_cyl(drive, track);
@@ -7283,8 +7614,7 @@
         SET_AH(0x00); // success
         CLEAR_CF();   // success
         return;
-        }
-      else if (ah == 0x03) {
+      } else if (ah == 0x03) {
         // Write Diskette Sectors
 
         //-----------------------------------
@@ -7301,7 +7631,7 @@
         if ( base_address < base_es ) {
           // in case of carry, adjust page by 1
           page++;
-          }
+        }
         base_count = (num_sectors * 512) - 1;
 
         // check for 64K boundary overrun
@@ -7312,7 +7642,7 @@
           SET_AL(0); // no sectors read
           SET_CF(); // error occurred
           return;
-          }
+        }
 
         BX_DEBUG_INT13_FL("masking DMA-1 c2\n");
         outb(0x000a, 0x06);
@@ -7338,30 +7668,9 @@
         //--------------------------------------
         // set up floppy controller for transfer
         //--------------------------------------
-
-        // set 40:3e bit 7 to 0
-        val8 = read_byte(0x0000, 0x043e);
-        val8 &= 0x7f;
-        write_byte(0x0000, 0x043e, val8);
-
-        // turn on motor of selected drive, DMA & int enabled, normal operation
-        if (drive)
-          dor = 0x20;
-        else
-          dor = 0x10;
-        dor |= 0x0c;
-        dor |= drive;
-        outb(0x03f2, dor);
-
-        // reset the disk motor timeout value of INT 08
-        write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
-
-        // check port 3f4 for drive readiness
-        val8 = inb(0x3f4);
-        if ( (val8 & 0xf0) != 0x80 )
-          BX_PANIC("int13_diskette:f03: ctrl not ready\n");
-
-        // send read-normal-data command (9 bytes) to controller
+        floppy_prepare_controller(drive);
+
+        // send write-normal-data command (9 bytes) to controller
         outb(0x03f5, 0xc5); // c5: write normal data
         outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
         outb(0x03f5, track);
@@ -7372,27 +7681,35 @@
         outb(0x03f5, 0); // Gap length
         outb(0x03f5, 0xff); // Gap length
 
-       // turn on interrupts
+        // turn on interrupts
   ASM_START
         sti
   ASM_END
 
         // wait on 40:3e bit 7 to become 1
-        val8 = (read_byte(0x0000, 0x043e) & 0x80);
-        while ( val8 == 0 ) {
-          val8 = (read_byte(0x0000, 0x043e) & 0x80);
-          }
-
-       val8 = 0; // separate asm from while() loop
-       // turn off interrupts
+        do {
+          val8 = read_byte(0x0040, 0x0040);
+          if (val8 == 0) {
+            floppy_reset_controller();
+            SET_AH(0x80); // drive not ready (timeout)
+            set_diskette_ret_status(0x80);
+            SET_AL(0); // no sectors written
+            SET_CF(); // error occurred
+            return;
+          }
+          val8 = (read_byte(0x0040, 0x003e) & 0x80);
+        } while ( val8 == 0 );
+
+        val8 = 0; // separate asm from while() loop
+        // turn off interrupts
   ASM_START
         cli
   ASM_END
 
         // set 40:3e bit 7 to 0
-        val8 = read_byte(0x0000, 0x043e);
+        val8 = read_byte(0x0040, 0x003e);
         val8 &= 0x7f;
-        write_byte(0x0000, 0x043e, val8);
+        write_byte(0x0040, 0x003e, val8);
 
         // check port 3f4 for accessibility to status bytes
         val8 = inb(0x3f4);
@@ -7436,8 +7753,7 @@
         SET_AH(0x00); // success
         CLEAR_CF();   // success
         return;
-        }
-      else {  // if (ah == 0x04)
+      } else {  // if (ah == 0x04)
         // Verify Diskette Sectors
 
         // ??? should track be new val from return_status[3] ?
@@ -7446,8 +7762,8 @@
         CLEAR_CF();   // success
         SET_AH(0x00); // success
         return;
-        }
-
+      }
+      break;
 
     case 0x05: // format diskette track
 BX_DEBUG_INT13_FL("floppy f05\n");
@@ -7462,7 +7778,7 @@
         SET_AH(1);
         set_diskette_ret_status(1);
         SET_CF(); // error occurred
-        }
+      }
 
       // see if drive exists
       if (floppy_drive_exists(drive) == 0) {
@@ -7470,7 +7786,7 @@
         set_diskette_ret_status(0x80);
         SET_CF(); // error occurred
         return;
-        }
+      }
 
       // see if media in drive, and type is known
       if (floppy_media_known(drive) == 0) {
@@ -7480,8 +7796,8 @@
           SET_AL(0); // no sectors read
           SET_CF(); // error occurred
           return;
-          }
-        }
+        }
+      }
 
       // set up DMA controller for transfer
       page = (ES >> 12);   // upper 4 bits
@@ -7491,7 +7807,7 @@
       if ( base_address < base_es ) {
         // in case of carry, adjust page by 1
         page++;
-        }
+      }
       base_count = (num_sectors * 4) - 1;
 
       // check for 64K boundary overrun
@@ -7502,7 +7818,7 @@
         SET_AL(0); // no sectors read
         SET_CF(); // error occurred
         return;
-        }
+      }
 
       outb(0x000a, 0x06);
       outb(0x000c, 0x00); // clear flip-flop
@@ -7519,27 +7835,9 @@
       outb(0x000a, 0x02);
 
       // set up floppy controller for transfer
-      val8 = read_byte(0x0000, 0x043e);
-      val8 &= 0x7f;
-      write_byte(0x0000, 0x043e, val8);
-      // turn on motor of selected drive, DMA & int enabled, normal operation
-      if (drive)
-        dor = 0x20;
-      else
-        dor = 0x10;
-      dor |= 0x0c;
-      dor |= drive;
-      outb(0x03f2, dor);
-
-      // reset the disk motor timeout value of INT 08
-      write_byte(0x40,0x40, BX_FLOPPY_ON_CNT);
-
-      // check port 3f4 for drive readiness
-      val8 = inb(0x3f4);
-      if ( (val8 & 0xf0) != 0x80 )
-        BX_PANIC("int13_diskette:f05: ctrl not ready\n");
-
-      // send read-normal-data command (6 bytes) to controller
+      floppy_prepare_controller(drive);
+
+      // send format-track command (6 bytes) to controller
       outb(0x03f5, 0x4d); // 4d: format track
       outb(0x03f5, (head << 2) | drive); // HD DR1 DR2
       outb(0x03f5, 2); // 512 byte sector size
@@ -7550,20 +7848,29 @@
   ASM_START
       sti
   ASM_END
+
       // wait on 40:3e bit 7 to become 1
-      val8 = (read_byte(0x0000, 0x043e) & 0x80);
-      while ( val8 == 0 ) {
-        val8 = (read_byte(0x0000, 0x043e) & 0x80);
-        }
-     val8 = 0; // separate asm from while() loop
-     // turn off interrupts
+      do {
+        val8 = read_byte(0x0040, 0x0040);
+        if (val8 == 0) {
+          floppy_reset_controller();
+          SET_AH(0x80); // drive not ready (timeout)
+          set_diskette_ret_status(0x80);
+          SET_CF(); // error occurred
+          return;
+        }
+        val8 = (read_byte(0x0040, 0x003e) & 0x80);
+      } while ( val8 == 0 );
+
+      val8 = 0; // separate asm from while() loop
+      // turn off interrupts
   ASM_START
       cli
   ASM_END
       // set 40:3e bit 7 to 0
-      val8 = read_byte(0x0000, 0x043e);
+      val8 = read_byte(0x0040, 0x003e);
       val8 &= 0x7f;
-      write_byte(0x0000, 0x043e, val8);
+      write_byte(0x0040, 0x003e, val8);
       // check port 3f4 for accessibility to status bytes
       val8 = inb(0x3f4);
       if ( (val8 & 0xc0) != 0xc0 )
@@ -7915,8 +8222,9 @@
   Bit16u bootseg;
   Bit16u bootip;
   Bit16u status;
-
-  struct ipl_entry e;
+  Bit16u bootfirst;
+
+  ipl_entry_t e;
 
   // if BX_ELTORITO_BOOT is not defined, old behavior
   //   check bit 5 in CMOS reg 0x2d.  load either 0x00 or 0x80 into DL
@@ -7930,7 +8238,7 @@
   //     CMOS reg 0x38 & 0xf0 : 3rd boot device
   //   boot device codes:
   //     0x00 : not defined
-  //     0x01 : first floppy 
+  //     0x01 : first floppy
   //     0x02 : first harddrive
   //     0x03 : first cdrom
   //     0x04 - 0x0f : PnP expansion ROMs (e.g. Etherboot)
@@ -7942,16 +8250,25 @@
   bootdev |= ((inb_cmos(0x38) & 0xf0) << 4);
   bootdev >>= 4 * seq_nr;
   bootdev &= 0xf;
-  if (bootdev == 0) BX_PANIC("No bootable device.\n");
-  
+
+  /* Read user selected device */
+  bootfirst = read_word(ebda_seg, IPL_BOOTFIRST_OFFSET);
+  if (bootfirst != 0xFFFF) {
+    bootdev = bootfirst;
+    /* User selected device not set */
+    write_word(ebda_seg, IPL_BOOTFIRST_OFFSET, 0xFFFF);
+    /* Reset boot sequence */
+    write_word(ebda_seg, IPL_SEQUENCE_OFFSET, 0xFFFF);
+  } else if (bootdev == 0) BX_PANIC("No bootable device.\n");
+
   /* Translate from CMOS runes to an IPL table offset by subtracting 1 */
   bootdev -= 1;
-#else  
+#else
   if (seq_nr ==2) BX_PANIC("No more boot devices.");
-  if (!!(inb_cmos(0x2d) & 0x20) ^ (seq_nr == 1)) 
+  if (!!(inb_cmos(0x2d) & 0x20) ^ (seq_nr == 1))
       /* Boot from floppy if the bit is set or it's the second boot */
     bootdev = 0x00;
-  else 
+  else
     bootdev = 0x01;
 #endif
 
@@ -7963,13 +8280,13 @@
 
   /* Do the loading, and set up vector as a far pointer to the boot
    * address, and bootdrv as the boot drive */
-  print_boot_device(e.type);
+  print_boot_device(&e);
 
   switch(e.type) {
-  case 0x01: /* FDD */
-  case 0x02: /* HDD */
-
-    bootdrv = (e.type == 0x02) ? 0x80 : 0x00;
+  case IPL_TYPE_FLOPPY: /* FDD */
+  case IPL_TYPE_HARDDISK: /* HDD */
+
+    bootdrv = (e.type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00;
     bootseg = 0x07c0;
     status = 0;
 
@@ -7984,7 +8301,7 @@
     mov  dl, _int18_function.bootdrv + 2[bp]
     mov  ax, _int18_function.bootseg + 2[bp]
     mov  es, ax         ;; segment
-    mov  bx, #0x0000    ;; offset
+    xor  bx, bx         ;; offset
     mov  ah, #0x02      ;; function 2, read diskette sector
     mov  al, #0x01      ;; read 1 sector
     mov  ch, #0x00      ;; track 0
@@ -8002,7 +8319,7 @@
     pop  ax
     pop  bp
 ASM_END
-    
+
     if (status != 0) {
       print_boot_failure(e.type, 1);
       return;
@@ -8010,7 +8327,7 @@
 
     /* Always check the signature on a HDD boot sector; on FDD, only do
      * the check if the CMOS doesn't tell us to skip it */
-    if (e.type != 0x00 || !((inb_cmos(0x38) & 0x01))) {
+    if ((e.type != IPL_TYPE_FLOPPY) || !((inb_cmos(0x38) & 0x01))) {
       if (read_word(bootseg,0x1fe) != 0xaa55) {
         print_boot_failure(e.type, 0);
         return;
@@ -8028,7 +8345,7 @@
   break;
 
 #if BX_ELTORITO_BOOT
-  case 0x03: /* CD-ROM */
+  case IPL_TYPE_CDROM: /* CD-ROM */
     status = cdrom_boot();
 
     // If failure
@@ -8047,7 +8364,7 @@
     break;
 #endif
 
-  case 0x80: /* Expansion ROM with a Bootstrap Entry Vector (a far pointer) */
+  case IPL_TYPE_BEV: /* Expansion ROM with a Bootstrap Entry Vector (a far 
pointer) */
     bootseg = e.vector >> 16;
     bootip = e.vector & 0xffff;
     break;
@@ -8055,16 +8372,20 @@
   default: return;
   }
 
-  
+  /* Debugging info */
+  BX_INFO("Booting from %x:%x\n", bootseg, bootip);
+
   /* Jump to the boot vector */
 ASM_START
     mov  bp, sp
+//    push cs
+//    push #int18_handler
     ;; Build an iret stack frame that will take us to the boot vector.
     ;; iret pops ip, then cs, then flags, so push them in the opposite order.
     pushf
-    mov  ax, _int18_function.bootseg + 0[bp] 
+    mov  ax, _int18_function.bootseg + 0[bp]
     push ax
-    mov  ax, _int18_function.bootip + 0[bp] 
+    mov  ax, _int18_function.bootip + 0[bp]
     push ax
     ;; Set the magic number in ax and the boot drive in dl.
     mov  ax, #0xaa55
@@ -8267,7 +8588,11 @@
       } else if (regs.u.r8.bl == 0x83) {
         BX_INFO("bad PCI vendor ID %04x\n", regs.u.r16.dx);
       } else if (regs.u.r8.bl == 0x86) {
-        BX_INFO("PCI device %04x:%04x not found\n", regs.u.r16.dx, 
regs.u.r16.cx);
+        if (regs.u.r8.al == 0x02) {
+          BX_INFO("PCI device %04x:%04x not found at index %d\n", 
regs.u.r16.dx, regs.u.r16.cx, regs.u.r16.si);
+        } else {
+          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);
+        }
       }
       regs.u.r8.ah = regs.u.r8.bl;
       SetCF(iret_addr.flags);
@@ -8313,11 +8638,11 @@
           // Done waiting.
           Bit16u segment, offset;
 
-          offset = read_word( 0x40, 0x98 );
-          segment = read_word( 0x40, 0x9A );
+          segment = read_word( 0x40, 0x98 );
+          offset = read_word( 0x40, 0x9A );
           write_byte( 0x40, 0xA0, 0 );  // Turn of status byte.
           outb_cmos( 0xB, registerB & 0x37 ); // Clear the Periodic Interrupt.
-          write_byte( segment, offset, 0x80 );  // Write to specified flag 
byte.
+          write_byte(segment, offset, read_byte(segment, offset) | 0x80 );  // 
Write to specified flag byte.
         } else {
           // Continue waiting.
           time -= 0x3D1;
@@ -8525,13 +8850,18 @@
 #endif
 
 int13_disk:
+  ;; int13_harddisk modifies high word of EAX
+  shr   eax, #16
+  push  ax
   call  _int13_harddisk
+  pop   ax
+  shl   eax, #16
 
 int13_out:
   pop ds
   pop es
   popa
-  iret 
+  iret
 
 ;----------
 ;- INT18h -
@@ -8544,19 +8874,19 @@
   xor  ax, ax
   mov  ss, ax
 
-  ;; Get the boot sequence number out of the IPL memory
   ;; The first time we do this it will have been set to -1 so 
   ;; we will start from device 0.
   mov  ds, ax
-  mov  bx, word ptr [EBDA_SEG_PTR]
+  mov  bx, word ptr [0x40E]       ;; EBDA segment
   mov  ds, bx                     ;; Set segment
   mov  bx, IPL_SEQUENCE_OFFSET    ;; BX is now the sequence number
   inc  bx                         ;; ++
   mov  IPL_SEQUENCE_OFFSET, bx    ;; Write it back
-  mov  ds, ax                     ;; and reset the segment to zero. 
+  mov  ds, ax                     ;; and reset the segment to zero.
 
   ;; Call the C code for the next boot device
   push bx
+
   call _int18_function
 
   ;; Boot failed: invoke the boot recovery function...
@@ -8566,6 +8896,7 @@
 ;- INT19h -
 ;----------
 int19_relocated: ;; Boot function, relocated
+
   ;;
   ;; *** Warning: INT 19h resets the whole machine *** 
   ;;
@@ -8577,10 +8908,12 @@
   ;; boot sequence will start, which is more or less the required behaviour.
   ;; 
   ;; Reset SP and SS
+
   mov  ax, #0xfffe
   mov  sp, ax
   xor  ax, ax
   mov  ss, ax
+
   call _machine_reset
 
 ;----------
@@ -8594,7 +8927,7 @@
 ;- POST: Floppy Drive -
 ;----------------------
 floppy_drive_post:
-  mov  ax, #0x0000
+  xor  ax, ax
   mov  ds, ax
 
   mov  al, #0x00
@@ -8676,7 +9009,7 @@
   mov  dx, #0x03f6
   out  dx, al
 
-  mov  ax, #0x0000
+  xor  ax, ax
   mov  ds, ax
   mov  0x0474, al /* hard disk status of last operation */
   mov  0x0477, al /* hard disk port offset (XT only ???) */
@@ -8691,8 +9024,8 @@
   SET_INT_VECTOR(0x76, #0xF000, #int76_handler)
   ;; INT 41h: hard disk 0 configuration pointer
   ;; INT 46h: hard disk 1 configuration pointer
-  SET_INT_VECTOR(0x41, word ptr [EBDA_SEG_PTR], #0x003D)
-  SET_INT_VECTOR(0x46, word ptr [EBDA_SEG_PTR], #0x004D)
+  SET_INT_VECTOR(0x41, word ptr [0x40E], #0x003D) /* EBDA:003D */
+  SET_INT_VECTOR(0x46, word ptr [0x40E], #0x004D) /* EBDA:004D */
 
   ;; move disk geometry data from CMOS to EBDA disk parameter table(s)
   mov  al, #0x12
@@ -8723,7 +9056,7 @@
 
   xor  ax, ax
   mov  ds, ax
-  mov  ax, word ptr [EBDA_SEG_PTR]
+  mov  ax, word ptr [0x40E] ;; EBDA segment
   mov  ds, ax
 
   ;;; Filling EBDA table for hard disk 0.
@@ -8869,7 +9202,9 @@
   ;; 0x2b    landing zone high        D
   ;; 0x2c    sectors/track            E
 ;;; Fill EBDA table for hard disk 1.
-  mov  ax, #EBDA_SEG
+  xor  ax, ax
+  mov  ds, ax
+  mov  ax, word ptr [0x40E] ;; EBDA segment
   mov  ds, ax
   mov  al, #0x28
   out  #0x70, al
@@ -8992,7 +9327,7 @@
 #endif
   xor ax, ax            ; mov EBDA seg into 40E
   mov ds, ax
-  mov word ptr [EBDA_SEG_PTR], #EBDA_SEG
+  mov word ptr [0x40E], #EBDA_SEG
   ret;;
 
 ;--------------------
@@ -9000,13 +9335,42 @@
 ;--------------------
 ; relocated here because the primary POST area isnt big enough.
 eoi_jmp_post:
-  call eoi_both_pics
-
+  mov   al, #0x20
+  out   #0xA0, al ;; slave  PIC EOI
+  mov   al, #0x20
+  out   #0x20, al ;; master PIC EOI
+
+jmp_post_0x467:
   xor ax, ax
   mov ds, ax
 
   jmp far ptr [0x467]
 
+iret_post_0x467:
+  xor ax, ax
+  mov ds, ax
+
+  mov sp, [0x467]
+  mov ss, [0x469]
+  iret
+
+retf_post_0x467:
+  xor ax, ax
+  mov ds, ax
+
+  mov sp, [0x467]
+  mov ss, [0x469]
+  retf
+
+s3_post:
+#if BX_ROMBIOS32
+  call rombios32_init
+#endif
+  call _s3_resume
+  mov bl, #0x00
+  and ax, ax
+  jz normal_post
+  call _s3_resume_panic
 
 ;--------------------
 eoi_both_pics:
@@ -9159,16 +9523,22 @@
 
 .align 16
 bios32_entry_point:
-  pushf
-  cmp eax, #0x49435024
+  pushfd
+  cmp eax, #0x49435024 ;; "$PCI"
   jne unknown_service
   mov eax, #0x80000000
   mov dx, #0x0cf8
   out dx, eax
   mov dx, #0x0cfc
   in  eax, dx
-  cmp eax, #0x12378086
+#ifdef PCI_FIXED_HOST_BRIDGE
+  cmp eax, #PCI_FIXED_HOST_BRIDGE
   jne unknown_service
+#else
+  ;; say ok if a device is present
+  cmp eax, #0xffffffff
+  je unknown_service
+#endif
   mov ebx, #0x000f0000
   mov ecx, #0
   mov edx, #pcibios_protected
@@ -9177,12 +9547,15 @@
 unknown_service:
   mov al, #0x80
 bios32_end:
-  popf
+#ifdef BX_QEMU
+  and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu
+#endif
+  popfd
   retf
 
 .align 16
 pcibios_protected:
-  pushf
+  pushfd
   cli
   push esi
   push edi
@@ -9190,15 +9563,15 @@
   jne pci_pro_f02
   mov bx, #0x0210
   mov cx, #0
-  mov edx, #0x20494350
+  mov edx, #0x20494350 ;; "PCI "
   mov al, #0x01
   jmp pci_pro_ok
 pci_pro_f02: ;; find pci device
   cmp al, #0x02
-  jne pci_pro_f08
+  jne pci_pro_f03
   shl ecx, #16
   mov cx, dx
-  mov bx, #0x0000
+  xor bx, bx
   mov di, #0x00
 pci_pro_devloop:
   call pci_pro_select_reg
@@ -9213,6 +9586,27 @@
   inc bx
   cmp bx, #0x0100
   jne pci_pro_devloop
+  mov ah, #0x86
+  jmp pci_pro_fail
+pci_pro_f03: ;; find class code
+  cmp al, #0x03
+  jne pci_pro_f08
+  xor bx, bx
+  mov di, #0x08
+pci_pro_devloop2:
+  call pci_pro_select_reg
+  mov dx, #0x0cfc
+  in  eax, dx
+  shr eax, #8
+  cmp eax, ecx
+  jne pci_pro_nextdev2
+  cmp si, #0
+  je  pci_pro_ok
+  dec si
+pci_pro_nextdev2:
+  inc bx
+  cmp bx, #0x0100
+  jne pci_pro_devloop2
   mov ah, #0x86
   jmp pci_pro_fail
 pci_pro_f08: ;; read configuration byte
@@ -9288,16 +9682,20 @@
 pci_pro_fail:
   pop edi
   pop esi
-  sti
-  popf
+#ifdef BX_QEMU
+  and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu
+#endif
+  popfd
   stc
   retf
 pci_pro_ok:
   xor ah, ah
   pop edi
   pop esi
-  sti
-  popf
+#ifdef BX_QEMU
+  and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu
+#endif
+  popfd
   clc
   retf
 
@@ -9324,8 +9722,14 @@
   out dx, eax
   mov dx, #0x0cfc
   in  eax, dx
-  cmp eax, #0x12378086
+#ifdef PCI_FIXED_HOST_BRIDGE
+  cmp eax, #PCI_FIXED_HOST_BRIDGE
   je  pci_present
+#else
+  ;; say ok if a device is present
+  cmp eax, #0xffffffff
+  jne  pci_present
+#endif
   pop dx
   pop eax
   mov ah, #0xff
@@ -9339,7 +9743,7 @@
   mov ax, #0x0001
   mov bx, #0x0210
   mov cx, #0
-  mov edx, #0x20494350
+  mov edx, #0x20494350 ;; "PCI "
   mov edi, #0xf0000
   mov di, #pcibios_protected
   clc
@@ -9348,10 +9752,10 @@
   push esi
   push edi
   cmp al, #0x02
-  jne pci_real_f08
+  jne pci_real_f03
   shl ecx, #16
   mov cx, dx
-  mov bx, #0x0000
+  xor bx, bx
   mov di, #0x00
 pci_real_devloop:
   call pci_real_select_reg
@@ -9368,7 +9772,30 @@
   jne pci_real_devloop
   mov dx, cx
   shr ecx, #16
-  mov ah, #0x86
+  mov ax, #0x8602
+  jmp pci_real_fail
+pci_real_f03: ;; find class code
+  cmp al, #0x03
+  jne pci_real_f08
+  xor bx, bx
+  mov di, #0x08
+pci_real_devloop2:
+  call pci_real_select_reg
+  mov dx, #0x0cfc
+  in  eax, dx
+  shr eax, #8
+  cmp eax, ecx
+  jne pci_real_nextdev2
+  cmp si, #0
+  je  pci_real_ok
+  dec si
+pci_real_nextdev2:
+  inc bx
+  cmp bx, #0x0100
+  jne pci_real_devloop2
+  mov dx, cx
+  shr ecx, #16
+  mov ax, #0x8603
   jmp pci_real_fail
 pci_real_f08: ;; read configuration byte
   cmp al, #0x08
@@ -9430,7 +9857,7 @@
   jmp pci_real_ok
 pci_real_f0d: ;; write configuration dword
   cmp al, #0x0d
-  jne pci_real_unknown
+  jne pci_real_f0e
   call pci_real_select_reg
   push dx
   mov dx, #0x0cfc
@@ -9438,6 +9865,46 @@
   out dx, eax
   pop dx
   jmp pci_real_ok
+pci_real_f0e: ;; get irq routing options
+  cmp al, #0x0e
+  jne pci_real_unknown
+  SEG ES
+  cmp word ptr [di], #pci_routing_table_structure_end - 
pci_routing_table_structure_start
+  jb pci_real_too_small
+  SEG ES
+  mov word ptr [di], #pci_routing_table_structure_end - 
pci_routing_table_structure_start
+  pushf
+  push ds
+  push es
+  push cx
+  push si
+  push di
+  cld
+  mov si, #pci_routing_table_structure_start
+  push cs
+  pop ds
+  SEG ES
+  mov cx, [di+2]
+  SEG ES
+  mov es, [di+4]
+  mov di, cx
+  mov cx, #pci_routing_table_structure_end - pci_routing_table_structure_start
+  rep
+      movsb
+  pop di
+  pop si
+  pop cx
+  pop es
+  pop ds
+  popf
+  mov bx, #(1 << 9) | (1 << 11)   ;; irq 9 and 11 are used
+  jmp pci_real_ok
+pci_real_too_small:
+  SEG ES
+  mov word ptr [di], #pci_routing_table_structure_end - 
pci_routing_table_structure_start
+  mov ah, #0x89
+  jmp pci_real_fail
+
 pci_real_unknown:
   mov ah, #0x81
 pci_real_fail:
@@ -9464,7 +9931,7 @@
   out dx,  eax
   pop dx
   ret
-  
+
 .align 16
 pci_routing_table_structure:
   db 0x24, 0x50, 0x49, 0x52  ;; "$PIR" signature
@@ -9472,21 +9939,22 @@
   dw 32 + (6 * 16) ;; table size
   db 0 ;; PCI interrupt router bus
   db 0x08 ;; PCI interrupt router DevFunc
-  dw 0x0000 ;; PCI exclusive IRQs 
+  dw 0x0000 ;; PCI exclusive IRQs
   dw 0x8086 ;; compatible PCI interrupt router vendor ID
-  dw 0x7000 ;; compatible PCI interrupt router device ID
+  dw 0x122e ;; compatible PCI interrupt router device ID
   dw 0,0 ;; Miniport data
   db 0,0,0,0,0,0,0,0,0,0,0 ;; reserved
-  db 0x07 ;; checksum
+  db 0x37 ;; checksum
+pci_routing_table_structure_start:
   ;; first slot entry PCI-to-ISA (embedded)
   db 0 ;; pci bus number
   db 0x08 ;; pci device number (bit 7-3)
   db 0x61 ;; link value INTA#: pointer into PCI2ISA config space
-  dw 0x0c20 ;; IRQ bitmap INTA# 
+  dw 0x0c20 ;; IRQ bitmap INTA#
   db 0x62 ;; link value INTB#
-  dw 0x0c20 ;; IRQ bitmap INTB# 
+  dw 0x0c20 ;; IRQ bitmap INTB#
   db 0x63 ;; link value INTC#
-  dw 0x0c20 ;; IRQ bitmap INTC# 
+  dw 0x0c20 ;; IRQ bitmap INTC#
   db 0x60 ;; link value INTD#
   dw 0x0c20 ;; IRQ bitmap INTD#
   db 0 ;; physical slot (0 = embedded)
@@ -9495,11 +9963,11 @@
   db 0 ;; pci bus number
   db 0x10 ;; pci device number (bit 7-3)
   db 0x62 ;; link value INTA#
-  dw 0x0c20 ;; IRQ bitmap INTA# 
+  dw 0x0c20 ;; IRQ bitmap INTA#
   db 0x63 ;; link value INTB#
-  dw 0x0c20 ;; IRQ bitmap INTB# 
+  dw 0x0c20 ;; IRQ bitmap INTB#
   db 0x60 ;; link value INTC#
-  dw 0x0c20 ;; IRQ bitmap INTC# 
+  dw 0x0c20 ;; IRQ bitmap INTC#
   db 0x61 ;; link value INTD#
   dw 0x0c20 ;; IRQ bitmap INTD#
   db 1 ;; physical slot (0 = embedded)
@@ -9508,11 +9976,11 @@
   db 0 ;; pci bus number
   db 0x18 ;; pci device number (bit 7-3)
   db 0x63 ;; link value INTA#
-  dw 0x0c20 ;; IRQ bitmap INTA# 
+  dw 0x0c20 ;; IRQ bitmap INTA#
   db 0x60 ;; link value INTB#
-  dw 0x0c20 ;; IRQ bitmap INTB# 
+  dw 0x0c20 ;; IRQ bitmap INTB#
   db 0x61 ;; link value INTC#
-  dw 0x0c20 ;; IRQ bitmap INTC# 
+  dw 0x0c20 ;; IRQ bitmap INTC#
   db 0x62 ;; link value INTD#
   dw 0x0c20 ;; IRQ bitmap INTD#
   db 2 ;; physical slot (0 = embedded)
@@ -9521,11 +9989,11 @@
   db 0 ;; pci bus number
   db 0x20 ;; pci device number (bit 7-3)
   db 0x60 ;; link value INTA#
-  dw 0x0c20 ;; IRQ bitmap INTA# 
+  dw 0x0c20 ;; IRQ bitmap INTA#
   db 0x61 ;; link value INTB#
-  dw 0x0c20 ;; IRQ bitmap INTB# 
+  dw 0x0c20 ;; IRQ bitmap INTB#
   db 0x62 ;; link value INTC#
-  dw 0x0c20 ;; IRQ bitmap INTC# 
+  dw 0x0c20 ;; IRQ bitmap INTC#
   db 0x63 ;; link value INTD#
   dw 0x0c20 ;; IRQ bitmap INTD#
   db 3 ;; physical slot (0 = embedded)
@@ -9534,11 +10002,11 @@
   db 0 ;; pci bus number
   db 0x28 ;; pci device number (bit 7-3)
   db 0x61 ;; link value INTA#
-  dw 0x0c20 ;; IRQ bitmap INTA# 
+  dw 0x0c20 ;; IRQ bitmap INTA#
   db 0x62 ;; link value INTB#
-  dw 0x0c20 ;; IRQ bitmap INTB# 
+  dw 0x0c20 ;; IRQ bitmap INTB#
   db 0x63 ;; link value INTC#
-  dw 0x0c20 ;; IRQ bitmap INTC# 
+  dw 0x0c20 ;; IRQ bitmap INTC#
   db 0x60 ;; link value INTD#
   dw 0x0c20 ;; IRQ bitmap INTD#
   db 4 ;; physical slot (0 = embedded)
@@ -9547,16 +10015,351 @@
   db 0 ;; pci bus number
   db 0x30 ;; pci device number (bit 7-3)
   db 0x62 ;; link value INTA#
-  dw 0x0c20 ;; IRQ bitmap INTA# 
+  dw 0x0c20 ;; IRQ bitmap INTA#
   db 0x63 ;; link value INTB#
-  dw 0x0c20 ;; IRQ bitmap INTB# 
+  dw 0x0c20 ;; IRQ bitmap INTB#
   db 0x60 ;; link value INTC#
-  dw 0x0c20 ;; IRQ bitmap INTC# 
+  dw 0x0c20 ;; IRQ bitmap INTC#
   db 0x61 ;; link value INTD#
   dw 0x0c20 ;; IRQ bitmap INTD#
   db 5 ;; physical slot (0 = embedded)
   db 0 ;; reserved
+pci_routing_table_structure_end:
+
+#if !BX_ROMBIOS32
+pci_irq_list:
+  db 11, 10, 9, 5;
+
+pcibios_init_sel_reg:
+  push eax
+  mov eax, #0x800000
+  mov ax,  bx
+  shl eax, #8
+  and dl,  #0xfc
+  or  al,  dl
+  mov dx,  #0x0cf8
+  out dx,  eax
+  pop eax
+  ret
+
+pcibios_init_iomem_bases:
+  push bp
+  mov  bp, sp
+  mov  eax, #0xe0000000 ;; base for memory init
+  push eax
+  mov  ax, #0xc000 ;; base for i/o init
+  push ax
+  mov  ax, #0x0010 ;; start at base address #0
+  push ax
+  mov  bx, #0x0008
+pci_init_io_loop1:
+  mov  dl, #0x00
+  call pcibios_init_sel_reg
+  mov  dx, #0x0cfc
+  in   ax, dx
+  cmp  ax, #0xffff
+  jz   next_pci_dev
+  mov  dl, #0x04 ;; disable i/o and memory space access
+  call pcibios_init_sel_reg
+  mov  dx, #0x0cfc
+  in   al, dx
+  and  al, #0xfc
+  out  dx, al
+pci_init_io_loop2:
+  mov  dl, [bp-8]
+  call pcibios_init_sel_reg
+  mov  dx, #0x0cfc
+  in   eax, dx
+  test al, #0x01
+  jnz  init_io_base
+  mov  ecx, eax
+  mov  eax, #0xffffffff
+  out  dx, eax
+  in   eax, dx
+  cmp  eax, ecx
+  je   next_pci_base
+  xor  eax, #0xffffffff
+  mov  ecx, eax
+  mov  eax, [bp-4]
+  out  dx, eax
+  add  eax, ecx ;; calculate next free mem base
+  add  eax, #0x01000000
+  and  eax, #0xff000000
+  mov  [bp-4], eax
+  jmp  next_pci_base
+init_io_base:
+  mov  cx, ax
+  mov  ax, #0xffff
+  out  dx, ax
+  in   ax, dx
+  cmp  ax, cx
+  je   next_pci_base
+  xor  ax, #0xfffe
+  mov  cx, ax
+  mov  ax, [bp-6]
+  out  dx, ax
+  add  ax, cx ;; calculate next free i/o base
+  add  ax, #0x0100
+  and  ax, #0xff00
+  mov  [bp-6], ax
+next_pci_base:
+  mov  al, [bp-8]
+  add  al, #0x04
+  cmp  al, #0x28
+  je   enable_iomem_space
+  mov  byte ptr[bp-8], al
+  jmp  pci_init_io_loop2
+enable_iomem_space:
+  mov  dl, #0x04 ;; enable i/o and memory space access if available
+  call pcibios_init_sel_reg
+  mov  dx, #0x0cfc
+  in   al, dx
+  or   al, #0x07
+  out  dx, al
+next_pci_dev:
+  mov  byte ptr[bp-8], #0x10
+  inc  bx
+  cmp  bx, #0x0100
+  jne  pci_init_io_loop1
+  mov  sp, bp
+  pop  bp
+  ret
+
+pcibios_init_set_elcr:
+  push ax
+  push cx
+  mov  dx, #0x04d0
+  test al, #0x08
+  jz   is_master_pic
+  inc  dx
+  and  al, #0x07
+is_master_pic:
+  mov  cl, al
+  mov  bl, #0x01
+  shl  bl, cl
+  in   al, dx
+  or   al, bl
+  out  dx, al
+  pop  cx
+  pop  ax
+  ret
+
+pcibios_init_irqs:
+  push ds
+  push bp
+  mov  ax, #0xf000
+  mov  ds, ax
+  mov  dx, #0x04d0 ;; reset ELCR1 + ELCR2
+  mov  al, #0x00
+  out  dx, al
+  inc  dx
+  out  dx, al
+  mov  si, #pci_routing_table_structure
+  mov  bh, [si+8]
+  mov  bl, [si+9]
+  mov  dl, #0x00
+  call pcibios_init_sel_reg
+  mov  dx, #0x0cfc
+  in   eax, dx
+  cmp  eax, [si+12] ;; check irq router
+  jne  pci_init_end
+  mov  dl, [si+34]
+  call pcibios_init_sel_reg
+  push bx ;; save irq router bus + devfunc
+  mov  dx, #0x0cfc
+  mov  ax, #0x8080
+  out  dx, ax ;; reset PIRQ route control
+  add  dx, #2
+  out  dx, ax
+  mov  ax, [si+6]
+  sub  ax, #0x20
+  shr  ax, #4
+  mov  cx, ax
+  add  si, #0x20 ;; set pointer to 1st entry
+  mov  bp, sp
+  mov  ax, #pci_irq_list
+  push ax
+  xor  ax, ax
+  push ax
+pci_init_irq_loop1:
+  mov  bh, [si]
+  mov  bl, [si+1]
+pci_init_irq_loop2:
+  mov  dl, #0x00
+  call pcibios_init_sel_reg
+  mov  dx, #0x0cfc
+  in   ax, dx
+  cmp  ax, #0xffff
+  jnz  pci_test_int_pin
+  test bl, #0x07
+  jz   next_pir_entry
+  jmp  next_pci_func
+pci_test_int_pin:
+  mov  dl, #0x3c
+  call pcibios_init_sel_reg
+  mov  dx, #0x0cfd
+  in   al, dx
+  and  al, #0x07
+  jz   next_pci_func
+  dec  al ;; determine pirq reg
+  mov  dl, #0x03
+  mul  al, dl
+  add  al, #0x02
+  xor  ah, ah
+  mov  bx, ax
+  mov  al, [si+bx]
+  mov  dl, al
+  mov  bx, [bp]
+  call pcibios_init_sel_reg
+  mov  dx, #0x0cfc
+  and  al, #0x03
+  add  dl, al
+  in   al, dx
+  cmp  al, #0x80
+  jb   pirq_found
+  mov  bx, [bp-2] ;; pci irq list pointer
+  mov  al, [bx]
+  out  dx, al
+  inc  bx
+  mov  [bp-2], bx
+  call pcibios_init_set_elcr
+pirq_found:
+  mov  bh, [si]
+  mov  bl, [si+1]
+  add  bl, [bp-3] ;; pci function number
+  mov  dl, #0x3c
+  call pcibios_init_sel_reg
+  mov  dx, #0x0cfc
+  out  dx, al
+next_pci_func:
+  inc  byte ptr[bp-3]
+  inc  bl
+  test bl, #0x07
+  jnz  pci_init_irq_loop2
+next_pir_entry:
+  add  si, #0x10
+  mov  byte ptr[bp-3], #0x00
+  loop pci_init_irq_loop1
+  mov  sp, bp
+  pop  bx
+pci_init_end:
+  pop  bp
+  pop  ds
+  ret
+#endif // !BX_ROMBIOS32
 #endif // BX_PCIBIOS
+
+#if BX_ROMBIOS32
+rombios32_init:
+  ;; save a20 and enable it
+  in al, 0x92
+  push ax
+  or al, #0x02
+  out 0x92, al
+
+  ;; save SS:SP to the BDA
+  xor ax, ax
+  mov ds, ax
+  mov 0x0469, ss
+  mov 0x0467, sp
+
+  SEG CS
+    lidt [pmode_IDT_info]
+  SEG CS
+    lgdt [rombios32_gdt_48]
+  ;; set PE bit in CR0
+  mov  eax, cr0
+  or   al, #0x01
+  mov  cr0, eax
+  ;; start protected mode code: ljmpl 0x10:rombios32_init1
+  db 0x66, 0xea
+  dw rombios32_05
+  dw 0x000f       ;; high 16 bit address
+  dw 0x0010
+
+use32 386
+rombios32_05:
+  ;; init data segments
+  mov eax, #0x18
+  mov ds, ax
+  mov es, ax
+  mov ss, ax
+  xor eax, eax
+  mov fs, ax
+  mov gs, ax
+  cld
+
+  ;; init the stack pointer to point below EBDA
+  mov ax, [0x040e]
+  shl eax, #4
+  mov esp, #-0x10
+  add esp, eax
+
+  ;; pass pointer to s3_resume_flag and s3_resume_vector to rombios32
+  push #0x04b0
+  push #0x04b2
+
+  ;; call rombios32 code
+  mov eax, #0x000e0000
+  call eax
+
+  ;; return to 16 bit protected mode first
+  db 0xea
+  dd rombios32_10
+  dw 0x20
+
+use16 386
+rombios32_10:
+  ;; restore data segment limits to 0xffff
+  mov ax, #0x28
+  mov ds, ax
+  mov es, ax
+  mov ss, ax
+  mov fs, ax
+  mov gs, ax
+
+  ;; reset PE bit in CR0
+  mov  eax, cr0
+  and  al, #0xFE
+  mov  cr0, eax
+
+  ;; far jump to flush CPU queue after transition to real mode
+  JMP_AP(0xf000, rombios32_real_mode)
+
+rombios32_real_mode:
+  ;; restore IDT to normal real-mode defaults
+  SEG CS
+    lidt [rmode_IDT_info]
+
+  xor ax, ax
+  mov ds, ax
+  mov es, ax
+  mov fs, ax
+  mov gs, ax
+
+  ;; restore SS:SP from the BDA
+  mov ss, 0x0469
+  xor esp, esp
+  mov sp, 0x0467
+  ;; restore a20
+  pop ax
+  out 0x92, al
+  ret
+
+rombios32_gdt_48:
+  dw 0x30
+  dw rombios32_gdt
+  dw 0x000f
+
+rombios32_gdt:
+  dw 0, 0, 0, 0
+  dw 0, 0, 0, 0
+  dw 0xffff, 0, 0x9b00, 0x00cf ; 32 bit flat code segment (0x10)
+  dw 0xffff, 0, 0x9300, 0x00cf ; 32 bit flat data segment (0x18)
+  dw 0xffff, 0, 0x9b0f, 0x0000 ; 16 bit code segment base=0xf0000 limit=0xffff
+  dw 0xffff, 0, 0x9300, 0x0000 ; 16 bit data segment base=0x0 limit=0xffff
+#endif // BX_ROMBIOS32
+
 
 ; parallel port detection: base address in DX, index in BX, timeout in CL
 detect_parport:
@@ -9628,13 +10431,12 @@
   ret
 
 
-;; We need a copy of this string, but we are not actually a PnP BIOS, 
+;; We need a copy of this string, but we are not actually a PnP BIOS,
 ;; so make sure it is *not* aligned, so OSes will not see it if they scan.
 .align 16
   db 0
 pnp_string:
   .ascii "$PnP"
-
 
 rom_scan:
   ;; Scan for existence of valid expansion ROMS.
@@ -9652,8 +10454,9 @@
 #if BX_TCGBIOS
   call _tcpa_start_option_rom_scan    /* specs: 3.2.3.3 + 10.4.3 */
 #endif
-  mov  cx, #0xc000
+
 rom_scan_loop:
+  push ax       ;; Save AX
   mov  ds, cx
   mov  ax, #0x0004 ;; start with increment of 4 (512-byte) blocks = 2k
   cmp [0], #0xAA55 ;; look for signature
@@ -9670,6 +10473,8 @@
   add  al, #0x04
 block_count_rounded:
 
+  xor  bx, bx   ;; Restore DS back to 0000:
+  mov  ds, bx
 #if BX_TCGBIOS
   push ax
   push ds
@@ -9680,7 +10485,7 @@
   push ecx       ;; segment where option rom is located at
   call _tcpa_option_rom                   /* specs: 3.2.3.3 */
   add sp, #4    ;; pop segment
-  pop ecx      ;; original ecx
+  pop ecx      ;; original ecx
   pop ds
   pop ax
 #endif
@@ -9704,11 +10509,11 @@
   xor  ax, ax
   mov  al, [bx]
 
-  ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS.  
+  ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS.
   ;; That should stop it grabbing INT 19h; we will use its BEV instead.
   mov  bx, #0xf000
   mov  es, bx
-  lea  di, pnp_string 
+  lea  di, pnp_string
 
   xor  bx, bx   ;; Restore DS back to 0000:
   mov  ds, bx
@@ -9721,8 +10526,8 @@
   add  sp, #2   ;; Pop offset value
   pop  cx       ;; Pop seg value (restore CX)
 
-  ;; Look at the ROM's PnP Expansion header.  Properly, we're supposed 
-  ;; to init all the ROMs and then go back and build an IPL table of 
+  ;; Look at the ROM's PnP Expansion header.  Properly, we're supposed
+  ;; to init all the ROMs and then go back and build an IPL table of
   ;; all the bootable devices, but we can get away with one pass.
   mov  ds, cx       ;; ROM base
   mov  bx, 0x001a   ;; 0x1A is the offset into ROM header that contains...
@@ -9730,7 +10535,7 @@
   cmp  ax, #0x5024  ;; we look for signature "$PnP"
   jne  no_bev
   mov  ax, 2[bx]
-  cmp  ax, #0x506e 
+  cmp  ax, #0x506e
   jne  no_bev
 
   mov  ax, 0x16[bx] ;; 0x16 is the offset of Boot Connection Vector
@@ -9753,25 +10558,31 @@
   cli           ;; In case expansion ROM BIOS turns IF on
   add  sp, #2   ;; Pop offset value
   pop  cx       ;; Pop seg value (restore CX)
-  jmp  no_bev
+  jmp   no_bev
 
 no_bcv:
   mov  ax, 0x1a[bx] ;; 0x1A is also the offset into the expansion header of...
   cmp  ax, #0x0000  ;; the Bootstrap Entry Vector, or zero if there is none.
   je   no_bev
 
-  ;; Found a device that thinks it can boot the system.  Record its BEV.
+  ;; Found a device that thinks it can boot the system.  Record its BEV and 
product name string.
+  mov  di, 0x10[bx]            ;; Pointer to the product name string or zero 
if none
   xor  bx, bx
   mov  ds, bx
-  mov  bx, word ptr [EBDA_SEG_PTR]
-  mov  ds, bx                  ;; Go to the segment where the IPL table lives 
+  mov  bx, word ptr [0x40E]    ;; EBDA segment
+  mov  ds, bx                  ;; Go to the segment where the IPL table lives
   mov  bx, IPL_COUNT_OFFSET    ;; Read the number of entries so far
   cmp  bx, #IPL_TABLE_ENTRIES
   je   no_bev                  ;; Get out if the table is full
   shl  bx, #0x4                ;; Turn count into offset (entries are 16 bytes)
-  mov  IPL_TABLE_OFFSET+0[bx], #0x80 ;; This entry is a BEV device
-  mov  IPL_TABLE_OFFSET+6[bx], cx    ;; Build a far pointer from the segment...
-  mov  IPL_TABLE_OFFSET+4[bx], ax    ;; and the offset
+  mov  IPL_TABLE_OFFSET+0[bx], #IPL_TYPE_BEV ;; This entry is a BEV device
+  mov  IPL_TABLE_OFFSET+6[bx], cx            ;; Build a far pointer from the 
segment...
+  mov  IPL_TABLE_OFFSET+4[bx], ax            ;; and the offset
+  cmp  di, #0x0000
+  je   no_prod_str
+  mov  0xA[bx], cx             ;; Build a far pointer from the segment...
+  mov  8[bx], di               ;; and the offset
+no_prod_str:
   shr  bx, #0x4                ;; Turn the offset back into a count
   inc  bx                      ;; We have one more entry now
   mov  IPL_COUNT_OFFSET, bx    ;; Remember that.
@@ -9783,7 +10594,8 @@
   shl  ax, #5   ;; convert 512-bytes blocks to 16-byte increments
                 ;; because the segment selector is shifted left 4 bits.
   add  cx, ax
-  cmp  cx, #0xe000
+  pop  ax       ;; Restore AX
+  cmp  cx, ax
   jbe  rom_scan_loop
 
   xor  ax, ax   ;; Restore DS back to 0000:
@@ -9848,10 +10660,36 @@
 #endif
 
 
-;; for 'C' strings and other data, insert them here with
-;; a the following hack:
-;; DATA_SEG_DEFS_HERE
-
+post_init_pic:
+  mov al, #0x11 ; send initialisation commands
+  out 0x20, al
+  out 0xa0, al
+  mov al, #0x08
+  out 0x21, al
+  mov al, #0x70
+  out 0xa1, al
+  mov al, #0x04
+  out 0x21, al
+  mov al, #0x02
+  out 0xa1, al
+  mov al, #0x01
+  out 0x21, al
+  out 0xa1, al
+  mov  al, #0xb8
+  out  0x21, AL ;master pic: unmask IRQ 0, 1, 2, 6
+#if BX_USE_PS2_MOUSE
+  mov  al, #0x8f
+#else
+  mov  al, #0x9f
+#endif
+  out  0xa1, AL ;slave  pic: unmask IRQ 12, 13, 14
+  ret
+
+;; the following area can be used to write dynamically generated tables
+  .align 16
+bios_table_area_start:
+  dd 0xaafb4442
+  dd bios_table_area_end - bios_table_area_start - 8;
 
 ;--------
 ;- POST -
@@ -9887,16 +10725,65 @@
 
   ;; Examine CMOS shutdown status.
   mov al, bl
-  mov dx, #EBDA_SEG
-  mov ds, dx
-  mov [EBDA_CMOS_SHUTDOWN_STATUS_OFFSET], AL
+
+  ;; 0x00, 0x09, 0x0D+ = normal startup
+  cmp AL, #0x00
+  jz normal_post
+  cmp AL, #0x0d
+  jae normal_post
+  cmp AL, #0x09
+  je normal_post
+
+  ;; 0x05 = eoi + jmp via [0x40:0x67] jump
+  cmp al, #0x05
+  je  eoi_jmp_post
+
+  ;; 0x0A = jmp via [0x40:0x67] jump
+  cmp al, #0x0a
+  je  jmp_post_0x467
+
+  ;; 0x0B = iret via [0x40:0x67]
+  cmp al, #0x0b
+  je  iret_post_0x467
+
+  ;; 0x0C = retf via [0x40:0x67]
+  cmp al, #0x0c
+  je  retf_post_0x467
+
+  ;; Examine CMOS shutdown status.
+  ;;  0x01,0x02,0x03,0x04,0x06,0x07,0x08 = Unimplemented shutdown status.
+  push bx
+  call _shutdown_status_panic
+
+#if 0
+  HALT(__LINE__)
+  ;
+  ;#if 0
+  ;  0xb0, 0x20,       /* mov al, #0x20 */
+  ;  0xe6, 0x20,       /* out 0x20, al    ;send EOI to PIC */
+  ;#endif
+  ;
+  pop es
+  pop ds
+  popa
+  iret
+#endif
+
+normal_post:
+  ; case 0: normal startup
 
   cli
   mov  ax, #0xfffe
   mov  sp, ax
-  mov  ax, #0x0000
+  xor  ax, ax
   mov  ds, ax
   mov  ss, ax
+
+  ;; Save shutdown status
+  mov 0x04b0, bl
+
+  cmp bl, #0xfe
+  jz s3_post
 
   ;; zero out BIOS data area (40:00..40:ff)
   mov  es, ax
@@ -9909,18 +10796,16 @@
   call _log_bios_start
 
   ;; set all interrupts to default handler
-  mov  bx, #0x0000    ;; offset index
+  xor  bx, bx         ;; offset index
   mov  cx, #0x0100    ;; counter (256 interrupts)
   mov  ax, #dummy_iret_handler
   mov  dx, #0xF000
 
 post_default_ints:
   mov  [bx], ax
-  inc  bx
-  inc  bx
+  add  bx, #2
   mov  [bx], dx
-  inc  bx
-  inc  bx
+  add  bx, #2
   loop post_default_ints
 
   ;; set vector 0x79 to zero
@@ -10076,28 +10961,51 @@
   SET_INT_VECTOR(0x10, #0xF000, #int10_handler)
 
   ;; PIC
-  mov al, #0x11 ; send initialisation commands
-  out 0x20, al
-  out 0xa0, al
-  mov al, #0x08
-  out 0x21, al
-  mov al, #0x70
-  out 0xa1, al
-  mov al, #0x04
-  out 0x21, al
-  mov al, #0x02
-  out 0xa1, al
-  mov al, #0x01
-  out 0x21, al
-  out 0xa1, al
-  mov  al, #0xb8
-  out  0x21, AL ;master pic: unmask IRQ 0, 1, 2, 6
-#if BX_USE_PS2_MOUSE
-  mov  al, #0x8f
-#else
-  mov  al, #0x9f
-#endif
-  out  0xa1, AL ;slave  pic: unmask IRQ 12, 13, 14
+  call post_init_pic
+
+  mov  cx, #0xc000  ;; init vga bios
+  mov  ax, #0xc780
+  call rom_scan
+
+  call _print_bios_banner
+
+#if BX_ROMBIOS32
+  call rombios32_init
+#else
+#if BX_PCIBIOS
+  call pcibios_init_iomem_bases
+  call pcibios_init_irqs
+#endif //BX_PCIBIOS
+#endif
+
+  ;;
+  ;; Floppy setup
+  ;;
+  call floppy_drive_post
+
+  ;;
+  ;; Hard Drive setup
+  ;;
+  call hard_drive_post
+
+#if BX_USE_ATADRV
+
+  ;;
+  ;; ATA/ATAPI driver setup
+  ;;
+  call _ata_init
+  call _ata_detect
+  ;;
+
+#endif // BX_USE_ATADRV
+
+#if BX_ELTORITO_BOOT
+  ;;
+  ;; eltorito floppy/harddisk emulation from cd
+  ;;
+  call _cdemu_init
+  ;;
+#endif // BX_ELTORITO_BOOT
 
 #ifdef HVMASSIST
   call _enable_rom_write_access
@@ -10109,52 +11017,19 @@
 
   call _init_boot_vectors
 
+  mov  cx, #0xc800  ;; init option roms
+  mov  ax, #0xe000
   call rom_scan
 
-  call _print_bios_banner 
-
-  ;;
-  ;; Floppy setup
-  ;;
-  call floppy_drive_post
-
-#if BX_USE_ATADRV
-
-  ;;
-  ;; Hard Drive setup
-  ;;
-  call hard_drive_post
-
-  ;;
-  ;; ATA/ATAPI driver setup
-  ;;
-  call _ata_init
-  call _ata_detect
-  ;;
-#else // BX_USE_ATADRV
-
-  ;;
-  ;; Hard Drive setup
-  ;;
-  call hard_drive_post
-
-#endif // BX_USE_ATADRV
-
-#if BX_ELTORITO_BOOT
-  ;;
-  ;; eltorito floppy/harddisk emulation from cd
-  ;;
-  call _cdemu_init
-  ;;
+#if BX_ELTORITO_BOOT
+  call _interactive_bootkey
 #endif // BX_ELTORITO_BOOT
-
-  call _s3_resume
-  call _interactive_bootkey
 
 #if BX_TCGBIOS
   call tcpa_post_part2
 #endif
 
+  sti        ;; enable interrupts
   ;; Start the boot sequence.   See the comments in int19_relocated 
   ;; for why we use INT 18h instead of INT 19h here.
   int  #0x18
@@ -10167,7 +11042,7 @@
   iret
 
 int75_handler:
-  out  0xf0, al         // clear irq13 
+  out  0xf0, al         // clear irq13
   call eoi_both_pics    // clear interrupt
   int  2                // legacy nmi call
   iret
@@ -10266,7 +11141,7 @@
 int14_handler:
   push ds
   pusha
-  mov  ax, #0x0000
+  xor  ax, ax
   mov  ds, ax
   call _int14_function
   popa
@@ -10371,26 +11246,7 @@
   jz  int09_finish
 
   in  al, #0x60             ;;read key from keyboard controller
-  //test al, #0x80            ;;look for key release
-  //jnz  int09_process_key    ;; dont pass releases to intercept?
-
-  ;; check for extended key
-  cmp  al, #0xe0
-  jne int09_call_int15_4f
-  
-  push ds
-  xor  ax, ax
-  mov  ds, ax
-  mov  al, BYTE [0x496]     ;; mf2_state |= 0x01
-  or   al, #0x01
-  mov  BYTE [0x496], al
-  pop  ds
-  
-  in  al, #0x60             ;;read another key from keyboard controller
-
   sti
-
-int09_call_int15_4f:
   push  ds
   pusha
 #ifdef BX_CALL_INT15_4F
@@ -10400,8 +11256,27 @@
   jnc  int09_done
 #endif
 
-
-//int09_process_key:
+  ;; check for extended key
+  cmp  al, #0xe0
+  jne int09_check_pause
+  xor  ax, ax
+  mov  ds, ax
+  mov  al, BYTE [0x496]     ;; mf2_state |= 0x02
+  or   al, #0x02
+  mov  BYTE [0x496], al
+  jmp int09_done
+
+int09_check_pause: ;; check for pause key
+  cmp  al, #0xe1
+  jne int09_process_key
+  xor  ax, ax
+  mov  ds, ax
+  mov  al, BYTE [0x496]     ;; mf2_state |= 0x01
+  or   al, #0x01
+  mov  BYTE [0x496], al
+  jmp int09_done
+
+int09_process_key:
   mov   bx, #0xf000
   mov   ds, bx
   call  _int09_function
@@ -10417,8 +11292,6 @@
   out #0x64, al
   pop ax
   iret
-
-
 
 
 ;----------------------------------------
@@ -10459,7 +11332,7 @@
   je int0e_loop2
 int0e_normal:
   push ds
-  mov  ax, #0x0000 ;; segment 0000
+  xor  ax, ax ;; segment 0000
   mov  ds, ax
   call eoi_master_pic
   mov  al, 0x043e
@@ -10496,7 +11369,7 @@
 int17_handler:
   push ds
   pusha
-  mov  ax, #0x0000
+  xor  ax, ax
   mov  ds, ax
   call _int17_function
   popa
@@ -10686,11 +11559,11 @@
 ;;
 int70_handler:
   push ds
-  pusha
+  pushad
   xor  ax, ax
   mov  ds, ax
   call _int70_function
-  popa
+  popad
   pop  ds
   iret
 
@@ -10748,7 +11621,7 @@
 
 
 .org 0xff00
-.ascii "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team."
+.ascii BIOS_COPYRIGHT_STRING
 
 ;------------------------------------------------
 ;- IRET Instruction for Dummy Interrupt Handler -
@@ -10770,7 +11643,7 @@
 #ifdef HVMTEST
   jmp 0xd000:0x0003;
 #else
-  jmp 0xf000:post
+   jmp 0xf000:post
 #endif
 
 .org 0xfff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY
@@ -10783,10 +11656,10 @@
 .org 0xfa6e ;; Character Font for 320x200 & 640x200 Graphics (lower 128 
characters)
 ASM_END
 /*
- * This font comes from the fntcol16.zip package (c) by  Joseph Gil 
+ * This font comes from the fntcol16.zip package (c) by  Joseph Gil
  * found at ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
  * This font is public domain
- */ 
+ */
 static Bit8u vgafont8[128*8]=
 {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -10962,328 +11835,10 @@
 db 0,0,0,0,0,0,0   ; 31 bytes
 ASM_END
 
-#else // !HVMASSIST
-
-ASM_START
-.org 0xcc00
+#endif // HVMASSIST
+ASM_START
+.org 0xcff0
+bios_table_area_end:
 // bcc-generated data will be placed here
-
-// For documentation of this config structure, look on developer.intel.com and
-// search for multiprocessor specification.  Note that when you change anything
-// you must update the checksum (a pain!).  It would be better to construct 
this
-// with C structures, or at least fill in the checksum automatically.
-//
-// Maybe this structs could be moved elsewhere than d000
-
-#if (BX_SMP_PROCESSORS==1)
-  // no structure necessary.
-#elif (BX_SMP_PROCESSORS==2)
-// define the Intel MP Configuration Structure for 2 processors at
-// APIC ID 0,1.  I/O APIC at ID=2.
-.align 16
-mp_config_table:
-  db 0x50, 0x43, 0x4d, 0x50  ;; "PCMP" signature
-  dw (mp_config_end-mp_config_table)  ;; table length
-  db 4 ;; spec rev
-  db 0x65 ;; checksum
-  .ascii "BOCHSCPU"     ;; OEM id = "BOCHSCPU"
-  db 0x30, 0x2e, 0x31, 0x20 ;; vendor id = "0.1         "
-  db 0x20, 0x20, 0x20, 0x20 
-  db 0x20, 0x20, 0x20, 0x20
-  dw 0,0 ;; oem table ptr
-  dw 0 ;; oem table size
-  dw 20 ;; entry count
-  dw 0x0000, 0xfee0 ;; memory mapped address of local APIC
-  dw 0 ;; extended table length
-  db 0 ;; extended table checksum
-  db 0 ;; reserved
-mp_config_proc0:
-  db 0 ;; entry type=processor
-  db 0 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 3 ;; cpu flags: enabled, bootstrap processor
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_proc1:
-  db 0 ;; entry type=processor
-  db 1 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 1 ;; cpu flags: enabled
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_isa_bus:
-  db 1 ;; entry type=bus
-  db 0 ;; bus ID
-  db 0x49, 0x53, 0x41, 0x20, 0x20, 0x20  ;; bus type="ISA   "
-mp_config_ioapic:
-  db 2 ;; entry type=I/O APIC
-  db 2 ;; apic id=2. linux will set.
-  db 0x11 ;; I/O APIC version number
-  db 1 ;; flags=1=enabled
-  dw 0x0000, 0xfec0 ;; memory mapped address of I/O APIC
-mp_config_irqs:
-  db 3 ;; entry type=I/O interrupt
-  db 0 ;; interrupt type=vectored interrupt
-  db 0,0 ;; flags po=0, el=0 (linux uses as default)
-  db 0 ;; source bus ID is ISA
-  db 0 ;; source bus IRQ
-  db 2 ;; destination I/O APIC ID
-  db 0 ;; destination I/O APIC interrrupt in
-  ;; repeat pattern for interrupts 0-15
-  db 3,0,0,0,0,1,2,1
-  db 3,0,0,0,0,2,2,2
-  db 3,0,0,0,0,3,2,3
-  db 3,0,0,0,0,4,2,4
-  db 3,0,0,0,0,5,2,5
-  db 3,0,0,0,0,6,2,6
-  db 3,0,0,0,0,7,2,7
-  db 3,0,0,0,0,8,2,8
-  db 3,0,0,0,0,9,2,9
-  db 3,0,0,0,0,10,2,10
-  db 3,0,0,0,0,11,2,11
-  db 3,0,0,0,0,12,2,12
-  db 3,0,0,0,0,13,2,13
-  db 3,0,0,0,0,14,2,14
-  db 3,0,0,0,0,15,2,15
-#elif (BX_SMP_PROCESSORS==4)
-// define the Intel MP Configuration Structure for 4 processors at
-// APIC ID 0,1,2,3.  I/O APIC at ID=4.
-.align 16
-mp_config_table:
-  db 0x50, 0x43, 0x4d, 0x50  ;; "PCMP" signature
-  dw (mp_config_end-mp_config_table)  ;; table length
-  db 4 ;; spec rev
-  db 0xdd ;; checksum
-  .ascii "BOCHSCPU"     ;; OEM id = "BOCHSCPU"
-  db 0x30, 0x2e, 0x31, 0x20 ;; vendor id = "0.1         "
-  db 0x20, 0x20, 0x20, 0x20 
-  db 0x20, 0x20, 0x20, 0x20
-  dw 0,0 ;; oem table ptr
-  dw 0 ;; oem table size
-  dw 22 ;; entry count
-  dw 0x0000, 0xfee0 ;; memory mapped address of local APIC
-  dw 0 ;; extended table length
-  db 0 ;; extended table checksum
-  db 0 ;; reserved
-mp_config_proc0:
-  db 0 ;; entry type=processor
-  db 0 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 3 ;; cpu flags: enabled, bootstrap processor
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_proc1:
-  db 0 ;; entry type=processor
-  db 1 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 1 ;; cpu flags: enabled
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_proc2:
-  db 0 ;; entry type=processor
-  db 2 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 1 ;; cpu flags: enabled
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_proc3:
-  db 0 ;; entry type=processor
-  db 3 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 1 ;; cpu flags: enabled
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_isa_bus:
-  db 1 ;; entry type=bus
-  db 0 ;; bus ID
-  db 0x49, 0x53, 0x41, 0x20, 0x20, 0x20  ;; bus type="ISA   "
-mp_config_ioapic:
-  db 2 ;; entry type=I/O APIC
-  db 4 ;; apic id=4. linux will set.
-  db 0x11 ;; I/O APIC version number
-  db 1 ;; flags=1=enabled
-  dw 0x0000, 0xfec0 ;; memory mapped address of I/O APIC
-mp_config_irqs:
-  db 3 ;; entry type=I/O interrupt
-  db 0 ;; interrupt type=vectored interrupt
-  db 0,0 ;; flags po=0, el=0 (linux uses as default)
-  db 0 ;; source bus ID is ISA
-  db 0 ;; source bus IRQ
-  db 4 ;; destination I/O APIC ID
-  db 0 ;; destination I/O APIC interrrupt in
-  ;; repeat pattern for interrupts 0-15
-  db 3,0,0,0,0,1,4,1
-  db 3,0,0,0,0,2,4,2
-  db 3,0,0,0,0,3,4,3
-  db 3,0,0,0,0,4,4,4
-  db 3,0,0,0,0,5,4,5
-  db 3,0,0,0,0,6,4,6
-  db 3,0,0,0,0,7,4,7
-  db 3,0,0,0,0,8,4,8
-  db 3,0,0,0,0,9,4,9
-  db 3,0,0,0,0,10,4,10
-  db 3,0,0,0,0,11,4,11
-  db 3,0,0,0,0,12,4,12
-  db 3,0,0,0,0,13,4,13
-  db 3,0,0,0,0,14,4,14
-  db 3,0,0,0,0,15,4,15
-#elif (BX_SMP_PROCESSORS==8)
-// define the Intel MP Configuration Structure for 8 processors at
-// APIC ID 0,1,2,3,4,5,6,7.  I/O APIC at ID=8.
-.align 16
-mp_config_table:
-  db 0x50, 0x43, 0x4d, 0x50  ;; "PCMP" signature
-  dw (mp_config_end-mp_config_table)  ;; table length
-  db 4 ;; spec rev
-  db 0xc3 ;; checksum
-  .ascii "BOCHSCPU"     ;; OEM id = "BOCHSCPU"
-  db 0x30, 0x2e, 0x31, 0x20 ;; vendor id = "0.1         "
-  db 0x20, 0x20, 0x20, 0x20 
-  db 0x20, 0x20, 0x20, 0x20
-  dw 0,0 ;; oem table ptr
-  dw 0 ;; oem table size
-  dw 26 ;; entry count
-  dw 0x0000, 0xfee0 ;; memory mapped address of local APIC
-  dw 0 ;; extended table length
-  db 0 ;; extended table checksum
-  db 0 ;; reserved
-mp_config_proc0:
-  db 0 ;; entry type=processor
-  db 0 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 3 ;; cpu flags: enabled, bootstrap processor
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_proc1:
-  db 0 ;; entry type=processor
-  db 1 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 1 ;; cpu flags: enabled
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_proc2:
-  db 0 ;; entry type=processor
-  db 2 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 1 ;; cpu flags: enabled
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_proc3:
-  db 0 ;; entry type=processor
-  db 3 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 1 ;; cpu flags: enabled
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_proc4:
-  db 0 ;; entry type=processor
-  db 4 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 1 ;; cpu flags: enabled
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_proc5:
-  db 0 ;; entry type=processor
-  db 5 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 1 ;; cpu flags: enabled
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_proc6:
-  db 0 ;; entry type=processor
-  db 6 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 1 ;; cpu flags: enabled
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_proc7:
-  db 0 ;; entry type=processor
-  db 7 ;; local APIC id
-  db 0x11 ;; local APIC version number
-  db 1 ;; cpu flags: enabled
-  db 0,6,0,0 ;; cpu signature
-  dw 0x201,0 ;; feature flags
-  dw 0,0 ;; reserved
-  dw 0,0 ;; reserved
-mp_config_isa_bus:
-  db 1 ;; entry type=bus
-  db 0 ;; bus ID
-  db 0x49, 0x53, 0x41, 0x20, 0x20, 0x20  ;; bus type="ISA   "
-mp_config_ioapic:
-  db 2 ;; entry type=I/O APIC
-  db 8 ;; apic id=8
-  db 0x11 ;; I/O APIC version number
-  db 1 ;; flags=1=enabled
-  dw 0x0000, 0xfec0 ;; memory mapped address of I/O APIC
-mp_config_irqs:
-  db 3 ;; entry type=I/O interrupt
-  db 0 ;; interrupt type=vectored interrupt
-  db 0,0 ;; flags po=0, el=0 (linux uses as default)
-  db 0 ;; source bus ID is ISA
-  db 0 ;; source bus IRQ
-  db 8 ;; destination I/O APIC ID
-  db 0 ;; destination I/O APIC interrrupt in
-  ;; repeat pattern for interrupts 0-15
-  db 3,0,0,0,0,1,8,1
-  db 3,0,0,0,0,2,8,2
-  db 3,0,0,0,0,3,8,3
-  db 3,0,0,0,0,4,8,4
-  db 3,0,0,0,0,5,8,5
-  db 3,0,0,0,0,6,8,6
-  db 3,0,0,0,0,7,8,7
-  db 3,0,0,0,0,8,8,8
-  db 3,0,0,0,0,9,8,9
-  db 3,0,0,0,0,10,8,10
-  db 3,0,0,0,0,11,8,11
-  db 3,0,0,0,0,12,8,12
-  db 3,0,0,0,0,13,8,13
-  db 3,0,0,0,0,14,8,14
-  db 3,0,0,0,0,15,8,15
-#else
-#  error Sorry, rombios only has configurations for 1, 2, 4 or 8 processors.
-#endif  // if (BX_SMP_PROCESSORS==...)
-
-mp_config_end:   // this label used to find length of mp structure
- db 0
-
-#if (BX_SMP_PROCESSORS>1)
-.align 16
-mp_floating_pointer_structure:
-db 0x5f, 0x4d, 0x50, 0x5f   ; "_MP_" signature
-dw mp_config_table, 0xf ;; pointer to MP configuration table
-db 1     ;; length of this struct in 16-bit byte chunks
-db 4     ;; MP spec revision
-db 0xc1  ;; checksum
-db 0     ;; MP feature byte 1.  value 0 means look at the config table
-db 0,0,0,0     ;; MP feature bytes 2-5.
-#endif
-
-ASM_END
-
-#endif // HVMASSIST
+ASM_END
+
diff -r a76b4e00e186 tools/firmware/rombios/rombios.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/rombios.h  Wed Dec 17 23:38:15 2008 +0900
@@ -0,0 +1,70 @@
+/////////////////////////////////////////////////////////////////////////
+// $Id: rombios.h,v 1.8 2008/12/04 18:48:33 sshwarts Exp $
+/////////////////////////////////////////////////////////////////////////
+//
+//  Copyright (C) 2006 Volker Ruppert
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2 of the License, or (at your option) any later version.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 
USA
+
+/* define it to include QEMU specific code */
+//#define BX_QEMU
+#define LEGACY
+
+#ifndef LEGACY
+#  define BX_ROMBIOS32     1
+#else
+#  define BX_ROMBIOS32     0
+#endif
+#define DEBUG_ROMBIOS    1
+
+#define PANIC_PORT  0x400
+#define PANIC_PORT2 0x401
+#define INFO_PORT   0x402
+#define DEBUG_PORT  0x403
+
+#define BIOS_PRINTF_HALT     1
+#define BIOS_PRINTF_SCREEN   2
+#define BIOS_PRINTF_INFO     4
+#define BIOS_PRINTF_DEBUG    8
+#define BIOS_PRINTF_ALL      (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO)
+#define BIOS_PRINTF_DEBHALT  (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO | 
BIOS_PRINTF_HALT)
+
+#define printf(format, p...)  bios_printf(BIOS_PRINTF_SCREEN, format, ##p)
+
+// Defines the output macros.
+// BX_DEBUG goes to INFO port until we can easily choose debug info on a
+// per-device basis. Debug info are sent only in debug mode
+#if DEBUG_ROMBIOS
+#  define BX_DEBUG(format, p...)  bios_printf(BIOS_PRINTF_INFO, format, ##p)
+#else
+#  define BX_DEBUG(format, p...)
+#endif
+#define BX_INFO(format, p...)   bios_printf(BIOS_PRINTF_INFO, format, ##p)
+#define BX_PANIC(format, p...)  bios_printf(BIOS_PRINTF_DEBHALT, format, ##p)
+
+#define ACPI_DATA_SIZE    0x00010000L
+#define PM_IO_BASE        0xb000
+#define SMB_IO_BASE       0xb100
+
+  // Define the application NAME
+#if define HVMASSIST
+#  define BX_APPNAME "HVMAssist"
+#elif defined(BX_QEMU)
+#  define BX_APPNAME "QEMU"
+#elif defined(PLEX86)
+#  define BX_APPNAME "Plex86"
+#else
+#  define BX_APPNAME "Bochs"
+#endif
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>