Index: /trunk/src/VBox/Devices/PC/BIOS-new/ahci.c
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/ahci.c	(revision 39609)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/ahci.c	(revision 39610)
@@ -15,6 +15,4 @@
  * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
  */
-
-//@todo!!!! save/restore high bits of EAX/ECX and whatever else may be needed.
 
 #include <stdint.h>
@@ -87,4 +85,6 @@
     /** Physical address of the sink buffer (for pre/post skip). */
     uint32_t        sink_buf_phys;
+    /** Saved high bits of EAX. */
+    uint16_t        saved_eax_hi;
     /** VDS EDDS DMA buffer descriptor structure. */
     vds_edds        edds;
@@ -181,4 +181,5 @@
     parm [dx] value [dx ax] modify nomemory;
 
+/* Warning: Destroys high bits of EAX. */
 void outpd(uint16_t port, uint32_t val);
 #pragma aux outpd =     \
@@ -191,4 +192,33 @@
 
 
+/* Machinery to save/restore high bits of EAX. 32-bit port I/O needs to use
+ * EAX, but saving/restoring EAX around each port access would be inefficient.
+ * Instead, each externally callable routine must save the high bits before
+ * modifying them and restore the high bits before exiting.
+ */
+
+/* Note: Reading high EAX bits destroys them - *must* be restored later. */
+uint16_t eax_hi_rd(void);
+#pragma aux eax_hi_rd = \
+    ".386"              \
+    "shr    eax, 16"    \
+    value [ax] modify nomemory;
+
+void eax_hi_wr(uint16_t);
+#pragma aux eax_hi_wr = \
+    ".386"              \
+    "shl    eax, 16"    \
+    parm [ax] modify nomemory;
+
+void high_bits_save(ahci_t __far *ahci)
+{
+    ahci->saved_eax_hi = eax_hi_rd();
+}
+
+void high_bits_restore(ahci_t __far *ahci)
+{
+    eax_hi_wr(ahci->saved_eax_hi);
+}
+
 /**
  * Sets a given set of bits in a register.
@@ -333,4 +363,11 @@
 
     ahci->cur_prd = prdt_idx;
+
+#ifdef DEBUG_AHCI
+    for (prdt_idx = 0; prdt_idx < ahci->cur_prd; ++prdt_idx) {
+        DBG_AHCI("S/G entry %u: %5lu bytes @ %08lX\n", prdt_idx,
+                 ahci->aPrdt[prdt_idx].len + 1, ahci->aPrdt[prdt_idx].phys_addr);
+    }
+#endif
 
     /* Build variable part of first command DWORD (reuses 'cmd'). */
@@ -462,4 +499,5 @@
              bios_dsk->ahcidev[device_id].port);
 
+    high_bits_save(bios_dsk->ahci_seg :> 0);
     ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
     ahci_cmd_data(bios_dsk, AHCI_CMD_READ_DMA_EXT);
@@ -467,4 +505,5 @@
     rep_movsw(bios_dsk->drqp.buffer, bios_dsk->drqp.buffer, bios_dsk->drqp.nsect * 512 / 2);
 #endif
+    high_bits_restore(bios_dsk->ahci_seg :> 0);
     return 0;   //@todo!!
 }
@@ -489,6 +528,8 @@
              bios_dsk->ahcidev[device_id].port);
 
+    high_bits_save(bios_dsk->ahci_seg :> 0);
     ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
     ahci_cmd_data(bios_dsk, AHCI_CMD_WRITE_DMA_EXT);
+    high_bits_restore(bios_dsk->ahci_seg :> 0);
     return 0;   //@todo!!
 }
@@ -503,5 +544,5 @@
 {
     bio_dsk_t __far *bios_dsk = read_word(0x0040, 0x000E) :> &EbdaData->bdisk;
-    ahci_t __far    *ahci     = bios_dsk->ahci_seg :> 0;
+    ahci_t __far    *ahci;
 
     /* Data out is currently not supported. */
@@ -530,4 +571,7 @@
     bios_dsk->drqp.nsect   = length / bios_dsk->drqp.sect_sz;
 //    bios_dsk->drqp.sect_sz = 2048;
+
+    ahci = bios_dsk->ahci_seg :> 0;
+    high_bits_save(ahci);
 
     ahci_port_init(bios_dsk->ahci_seg :> 0, bios_dsk->ahcidev[device_id].port);
@@ -554,4 +598,6 @@
     rep_movsw(bios_dsk->drqp.buffer, bios_dsk->drqp.buffer, bios_dsk->drqp.trsfbytes / 2);
 #endif
+    high_bits_restore(ahci);
+
     return ahci->aCmdHdr[1] == 0 ? 4 : 0;
 //    return 0;   //@todo!!
Index: /trunk/src/VBox/Devices/PC/BIOS-new/disk.c
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/disk.c	(revision 39609)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/disk.c	(revision 39610)
@@ -349,5 +349,8 @@
         segment = i13_ext->segment;
         offset  = i13_ext->offset;
-        
+
+        BX_DEBUG_INT13_HD("%s: %d sectors from lba %u @ %04x:%04x\n", __func__, 
+                          count, i13_ext->lba1, segment, offset);
+
         // Can't use 64 bits lba
         lba = i13_ext->lba2;
@@ -379,4 +382,5 @@
         bios_dsk->drqp.sect_sz = 512;   //@todo: device specific?
         bios_dsk->drqp.sector  = 0;     /* Indicate LBA. */
+        bios_dsk->drqp.dev_id  = device;
         
         // Execute the command
Index: /trunk/src/VBox/Devices/PC/BIOS-new/eltorito.c
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/eltorito.c	(revision 39609)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/eltorito.c	(revision 39610)
@@ -508,5 +508,8 @@
         segment   = ES;
         offset    = BX;
-        
+
+        BX_DEBUG_INT13_ET("%s: read to %04x:%04x @ VCHS %u/%u/%u (%u sectors)\n", __func__,
+                          ES, BX, cylinder, head, sector, nbsectors);
+
         // no sector to read ?
         if(nbsectors==0)
