Index: /trunk/src/VBox/Devices/PC/BIOS-new/ahci.c
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/ahci.c	(revision 39650)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/ahci.c	(revision 39651)
@@ -674,10 +674,10 @@
 
                 bios_dsk->ahcidev[devcount_ahci].port = u8Port;
-                bios_dsk->devices[hd_index].type        = ATA_TYPE_AHCI;
-                bios_dsk->devices[hd_index].device      = ATA_DEVICE_HD;
+                bios_dsk->devices[hd_index].type        = DSK_TYPE_AHCI;
+                bios_dsk->devices[hd_index].device      = DSK_DEVICE_HD;
                 bios_dsk->devices[hd_index].removable   = removable;
                 bios_dsk->devices[hd_index].lock        = 0;
                 bios_dsk->devices[hd_index].blksize     = 512;
-                bios_dsk->devices[hd_index].translation = ATA_TRANSLATION_LBA;
+                bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
                 bios_dsk->devices[hd_index].sectors     = cSectors;
 
@@ -704,5 +704,5 @@
                         idxCmosChsBase = 0;
                 }
-                if (idxCmosChsBase != 0)
+                if (idxCmosChsBase && inb_cmos(idxCmosChsBase+7))
                 {
                     cCylinders = inb_cmos(idxCmosChsBase) + (inb_cmos(idxCmosChsBase+1) << 8);
@@ -712,7 +712,9 @@
                 else
                 {
+#if 0   // LCHS equals PCHS?
                     cCylinders = 0;
                     cHeads = 0;
                     cSectorsPerTrack = 0;
+#endif
                 }
                 DBG_AHCI("AHCI: Dev %d LCHS=%d/%d/%d\n", 
@@ -751,6 +753,6 @@
 
                 bios_dsk->ahcidev[devcount_ahci].port = u8Port;
-                bios_dsk->devices[hd_index].type      = ATA_TYPE_AHCI;
-                bios_dsk->devices[hd_index].device    = ATA_DEVICE_CDROM;
+                bios_dsk->devices[hd_index].type      = DSK_TYPE_AHCI;
+                bios_dsk->devices[hd_index].device    = DSK_DEVICE_CDROM;
                 bios_dsk->devices[hd_index].removable = removable;
                 bios_dsk->devices[hd_index].blksize   = 2048;
Index: /trunk/src/VBox/Devices/PC/BIOS-new/ata.c
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/ata.c	(revision 39650)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/ata.c	(revision 39651)
@@ -96,11 +96,11 @@
     // Devices info init.
     for (device=0; device<BX_MAX_ATA_DEVICES; device++) {
-        bios_dsk->devices[device].type        = ATA_TYPE_NONE;
-        bios_dsk->devices[device].device      = ATA_DEVICE_NONE;
+        bios_dsk->devices[device].type        = DSK_TYPE_NONE;
+        bios_dsk->devices[device].device      = DSK_DEVICE_NONE;
         bios_dsk->devices[device].removable   = 0;
         bios_dsk->devices[device].lock        = 0;
         bios_dsk->devices[device].mode        = ATA_MODE_NONE;
         bios_dsk->devices[device].blksize     = 0x200;
-        bios_dsk->devices[device].translation = ATA_TRANSLATION_NONE;
+        bios_dsk->devices[device].translation = GEO_TRANSLATION_NONE;
         bios_dsk->devices[device].lchs.heads     = 0;
         bios_dsk->devices[device].lchs.cylinders = 0;
@@ -159,5 +159,5 @@
     outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN);
 
-    if (bios_dsk->devices[device].type != ATA_TYPE_NONE) {
+    if (bios_dsk->devices[device].type != DSK_TYPE_NONE) {
         // 8.2.1 (g) -- check for sc==sn==0x01
         // select device
@@ -429,5 +429,5 @@
 
         if ( (sc == 0x55) && (sn == 0xaa) ) {
-            bios_dsk->devices[device].type = ATA_TYPE_UNKNOWN;
+            bios_dsk->devices[device].type = DSK_TYPE_UNKNOWN;
 
             // reset the channel
@@ -444,9 +444,9 @@
 
                 if ((cl==0x14) && (ch==0xeb)) {
-                    bios_dsk->devices[device].type = ATA_TYPE_ATAPI;
+                    bios_dsk->devices[device].type = DSK_TYPE_ATAPI;
                 } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) {
-                    bios_dsk->devices[device].type = ATA_TYPE_ATA;
+                    bios_dsk->devices[device].type = DSK_TYPE_ATA;
                 } else if ((cl==0xff) && (ch==0xff)) {
-                    bios_dsk->devices[device].type = ATA_TYPE_NONE;
+                    bios_dsk->devices[device].type = DSK_TYPE_NONE;
                 }
             }
@@ -459,5 +459,5 @@
 
         // Now we send a IDENTIFY command to ATA device
-        if (type == ATA_TYPE_ATA) {
+        if (type == DSK_TYPE_ATA) {
             uint32_t    sectors;
             uint16_t    cylinders, heads, spt, blksize;
@@ -467,5 +467,5 @@
 
             //Temporary values to do the transfer
-            bios_dsk->devices[device].device = ATA_DEVICE_HD;
+            bios_dsk->devices[device].device = DSK_DEVICE_HD;
             bios_dsk->devices[device].mode   = ATA_MODE_PIO16;
             bios_dsk->drqp.buffer = buffer;
@@ -531,5 +531,5 @@
                     cylinders,heads, spt, lcylinders, lheads, lspt);
 
-            bios_dsk->devices[device].device         = ATA_DEVICE_HD;
+            bios_dsk->devices[device].device         = DSK_DEVICE_HD;
             bios_dsk->devices[device].removable      = removable;
             bios_dsk->devices[device].mode           = mode;
@@ -576,10 +576,10 @@
 
         // Now we send an IDENTIFY command to ATAPI device
-        if (type == ATA_TYPE_ATAPI) {
+        if (type == DSK_TYPE_ATAPI) {
             uint8_t     type, removable, mode;
             uint16_t    blksize;
 
             // Temporary values to do the transfer
-            bios_dsk->devices[device].device = ATA_DEVICE_CDROM;
+            bios_dsk->devices[device].device = DSK_DEVICE_CDROM;
             bios_dsk->devices[device].mode   = ATA_MODE_PIO16;
             bios_dsk->drqp.buffer = buffer;
@@ -611,8 +611,8 @@
 
             switch (type) {
-            case ATA_TYPE_ATA:
+            case DSK_TYPE_ATA:
                 sizeinmb = bios_dsk->devices[device].sectors;
                 sizeinmb >>= 11;
-            case ATA_TYPE_ATAPI:
+            case DSK_TYPE_ATAPI:
                 // Read ATA/ATAPI version
                 ataversion = ((uint16_t)(*(buffer+161))<<8) | *(buffer+160);
@@ -644,5 +644,5 @@
             switch (type) {
             int c;
-            case ATA_TYPE_ATA:
+            case DSK_TYPE_ATA:
                 printf("ata%d %s: ", channel, slave ? " slave" : "master");
                 i=0;
@@ -651,15 +651,15 @@
                 printf(" ATA-%d Hard-Disk (%lu MBytes)\n", version, sizeinmb);
                 break;
-            case ATA_TYPE_ATAPI:
+            case DSK_TYPE_ATAPI:
                 printf("ata%d %s: ", channel, slave ? " slave" : "master");
                 i=0;
                 while(c=*(model+i++))
                     printf("%c", c);
-                if (bios_dsk->devices[device].device == ATA_DEVICE_CDROM)
+                if (bios_dsk->devices[device].device == DSK_DEVICE_CDROM)
                     printf(" ATAPI-%d CD-ROM/DVD-ROM\n", version);
                 else
                     printf(" ATAPI-%d Device\n", version);
                 break;
-            case ATA_TYPE_UNKNOWN:
+            case DSK_TYPE_UNKNOWN:
                 printf("ata%d %s: Unknown device\n", channel , slave ? " slave" : "master");
                 break;
Index: /trunk/src/VBox/Devices/PC/BIOS-new/disk.c
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/disk.c	(revision 39650)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/disk.c	(revision 39651)
@@ -52,4 +52,31 @@
 #  define BX_DEBUG_INT13_HD(...)
 #endif
+
+/* Generic disk read/write routine signature. */
+typedef __fastcall (* dsk_rw_func)(bio_dsk_t __far *bios_dsk);
+
+/* Controller specific disk access routines. Declared as a union to reduce
+ * the need for conditionals when choosing between read/write functions.
+ * Note that we get away with using near pointers, which is nice.
+ */
+typedef union {
+    struct {
+        dsk_rw_func     read;
+        dsk_rw_func     write;
+    } s;
+    dsk_rw_func a[2];
+} dsk_acc_t;
+
+/* Pointers to HW specific disk access routines. */
+dsk_acc_t   dskacc[DSKTYP_CNT] = {
+    [DSK_TYPE_ATA]  = { ata_read_sectors,  ata_write_sectors },
+#ifdef VBOX_WITH_AHCI
+    [DSK_TYPE_AHCI] = { ahci_read_sectors, ahci_write_sectors },
+#endif
+#ifdef VBOX_WITH_SCSI
+    [DSK_TYPE_SCSI] = { scsi_read_sectors, scsi_write_sectors },
+#endif
+};
+
 
 //@todo: put in a header
@@ -167,30 +194,5 @@
         bios_dsk->drqp.dev_id   = device;
 
-        if ( GET_AH() == 0x02 )
-        {
-#ifdef VBOX_WITH_AHCI
-            if (VBOX_IS_AHCI_DEVICE(device))
-                status = ahci_read_sectors(bios_dsk);
-            else
-#endif
-#ifdef VBOX_WITH_SCSI
-            if (VBOX_IS_SCSI_DEVICE(device))
-                status = scsi_read_sectors(bios_dsk);
-            else
-#endif
-                status = ata_read_sectors(bios_dsk);
-        } else {
-#ifdef VBOX_WITH_AHCI
-            if (VBOX_IS_AHCI_DEVICE(device))
-                status = ahci_write_sectors(bios_dsk);
-            else
-#endif
-#ifdef VBOX_WITH_SCSI
-            if (VBOX_IS_SCSI_DEVICE(device))
-                status = scsi_write_sectors(bios_dsk);
-            else
-#endif
-                status = ata_write_sectors(bios_dsk);
-        }
+        status = dskacc[bios_dsk->devices[device].type].a[GET_AH() - 0x02](bios_dsk);
 
         // Set nb of sector transferred
@@ -305,4 +307,5 @@
     uint16_t            size, count;
     uint8_t             device, status;
+    uint8_t             type;
     bio_dsk_t __far     *bios_dsk;
     int13ext_t __far    *i13_ext;
@@ -363,4 +366,5 @@
         lba = i13_ext->lba1;
 
+        type = bios_dsk->devices[device].type;
         if (lba >= bios_dsk->devices[device].sectors) {
               BX_INFO("%s: function %02x. LBA out of range\n", __func__, GET_AH());
@@ -368,5 +372,5 @@
         }
 
-        // If verify or seek
+        /* Don't bother with seek or verify. */
         if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 ))
             goto int13x_success;
@@ -384,32 +388,7 @@
         bios_dsk->drqp.dev_id  = device;
         
-        // Execute the command
-        if ( GET_AH() == 0x42 ) {
-#ifdef VBOX_WITH_AHCI
-            if (VBOX_IS_AHCI_DEVICE(device))
-                status = ahci_read_sectors(bios_dsk);
-            else
-#endif
-#ifdef VBOX_WITH_SCSI
-            if (VBOX_IS_SCSI_DEVICE(device))
-                status = scsi_read_sectors(bios_dsk);
-            else
-#endif
-                status = ata_read_sectors(bios_dsk);
-        } else {
-#ifdef VBOX_WITH_AHCI
-            if (VBOX_IS_AHCI_DEVICE(device))
-                status = ahci_write_sectors(bios_dsk);
-            else 
-#endif
-#ifdef VBOX_WITH_SCSI
-            if (VBOX_IS_SCSI_DEVICE(device))
-                status = scsi_write_sectors(bios_dsk);
-            else 
-#endif
-                status = ata_write_sectors(bios_dsk);
-        }
-
-        count = bios_dsk->drqp.trsfsectors;
+        /* Execute the read or write command. */
+        status = dskacc[type].a[GET_AH() - 0x42](bios_dsk);
+        count  = bios_dsk->drqp.trsfsectors;
         i13_ext->count = count;
         
@@ -478,9 +457,9 @@
             translation = bios_dsk->devices[device].translation;
             
-            options  = (translation == ATA_TRANSLATION_NONE ? 0 : 1 << 3);  // chs translation
+            options  = (translation == GEO_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);
+            options |= (translation == GEO_TRANSLATION_LBA ? 1 : 0 << 9);
+            options |= (translation == GEO_TRANSLATION_RECHS ? 3 : 0 << 9);
             
             bios_dsk->dpte.iobase1  = iobase1;
Index: /trunk/src/VBox/Devices/PC/BIOS-new/ebda.h
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/ebda.h	(revision 39650)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/ebda.h	(revision 39651)
@@ -72,20 +72,30 @@
 #define BX_MAX_STORAGE_DEVICES (BX_MAX_ATA_DEVICES + BX_MAX_SCSI_DEVICES + BX_MAX_AHCI_DEVICES)
 
-/* Generic storage device types. Bit of a misnomer! */
-#define ATA_TYPE_NONE       0x00
-#define ATA_TYPE_UNKNOWN    0x01
-#define ATA_TYPE_ATA        0x02
-#define ATA_TYPE_ATAPI      0x03
-#define ATA_TYPE_SCSI       0x04 // SCSI disk
-#define ATA_TYPE_AHCI       0x05 // SATA disk
-
-#define ATA_DEVICE_NONE     0x00
-#define ATA_DEVICE_HD       0xFF
-#define ATA_DEVICE_CDROM    0x05
-
-#define ATA_TRANSLATION_NONE  0
-#define ATA_TRANSLATION_LBA   1
-#define ATA_TRANSLATION_LARGE 2
-#define ATA_TRANSLATION_RECHS 3
+/* Generic storage device types. These depend on the controller type and
+ * determine which device access routines should be called.
+ */
+enum dsk_type_enm {
+    DSK_TYPE_NONE,      /* Unknown device. */
+    DSK_TYPE_UNKNOWN,   /* Unknown ATA device. */
+    DSK_TYPE_ATA,       /* ATA disk. */
+    DSK_TYPE_ATAPI,     /* ATAPI device. */
+    DSK_TYPE_SCSI,      /* SCSI disk. */
+    DSK_TYPE_AHCI,      /* SATA disk via AHCI. */
+    DSKTYP_CNT          /* Number of disk types. */
+};
+
+/* Disk device types. */
+//@todo: Do we really need these?
+#define DSK_DEVICE_NONE     0x00    /* No device attached. */
+#define DSK_DEVICE_HD       0xFF    /* Device is a hard disk. */
+#define DSK_DEVICE_CDROM    0x05    /* Device is a CD-ROM. */
+
+/* Geometry translation modes. */
+enum geo_xlat_enm {
+    GEO_TRANSLATION_NONE,   /* No geometry translation. */
+    GEO_TRANSLATION_LBA,    /* LBA translation. */
+    GEO_TRANSLATION_LARGE,  /* Large CHS translation. */
+    GEO_TRANSLATION_RECHS
+};
 
 #if 1 //BX_USE_ATADRV
@@ -205,4 +215,10 @@
 } disk_req_t;
 
+uint16_t ahci_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
+                         uint16_t header, uint32_t length, uint8_t inout, char __far *buffer);
+
+uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf, 
+                        uint16_t header, uint32_t length, uint8_t inout, char __far *buffer);
+
 /* All BIOS disk information. Disk-related code in the BIOS should not need
  * anything outside of this structure.
@@ -299,11 +315,4 @@
 int __fastcall ahci_write_sectors(bio_dsk_t __far *bios_dsk);
 
-
-uint16_t ahci_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
-                         uint16_t header, uint32_t length, uint8_t inout, char __far *buffer);
-
-uint16_t ata_cmd_packet(uint16_t device, uint8_t cmdlen, char __far *cmdbuf, 
-                        uint16_t header, uint32_t length, uint8_t inout, char __far *buffer);
-
 // @todo: put this elsewhere (and change/eliminate?)
 #define SET_DISK_RET_STATUS(status) write_byte(0x0040, 0x0074, status)
Index: /trunk/src/VBox/Devices/PC/BIOS-new/eltorito.c
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/eltorito.c	(revision 39650)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/eltorito.c	(revision 39651)
@@ -213,8 +213,8 @@
         return 0;
     
-//    if (bios_dsk->devices[device].type != ATA_TYPE_ATAPI)
+//    if (bios_dsk->devices[device].type != DSK_TYPE_ATAPI)
 //        return 0;
     
-    if (bios_dsk->devices[device].device != ATA_DEVICE_CDROM)
+    if (bios_dsk->devices[device].device != DSK_DEVICE_CDROM)
         return 0;
     
Index: /trunk/src/VBox/Devices/PC/BIOS-new/scsi.c
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS-new/scsi.c	(revision 39650)
+++ /trunk/src/VBox/Devices/PC/BIOS-new/scsi.c	(revision 39651)
@@ -334,10 +334,10 @@
                 bios_dsk->scsidev[hdcount_scsi].io_base   = io_base;
                 bios_dsk->scsidev[hdcount_scsi].target_id = i;
-                bios_dsk->devices[hd_index].type        = ATA_TYPE_SCSI;
-                bios_dsk->devices[hd_index].device      = ATA_DEVICE_HD;
+                bios_dsk->devices[hd_index].type        = DSK_TYPE_SCSI;
+                bios_dsk->devices[hd_index].device      = DSK_DEVICE_HD;
                 bios_dsk->devices[hd_index].removable   = 0;
                 bios_dsk->devices[hd_index].lock        = 0;
                 bios_dsk->devices[hd_index].blksize     = sector_size;
-                bios_dsk->devices[hd_index].translation = ATA_TRANSLATION_LBA;
+                bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
 
                 /* Write LCHS values. */
