diff --git a/src/VBox/Devices/PC/BIOS/Makefile.kmk b/src/VBox/Devices/PC/BIOS/Makefile.kmk
index fa9cb6f..6655ecb 100644
--- a/src/VBox/Devices/PC/BIOS/Makefile.kmk
+++ b/src/VBox/Devices/PC/BIOS/Makefile.kmk
@@ -68,7 +68,8 @@ ifdef VBOX_WITH_OPEN_WATCOM
  	pcibio32.asm \
  	apm_pm.asm \
  	$(VBoxPcBios32_1_TARGET) \
- 	orgs.asm
+ 	orgs.asm \
+	ow_glue64.asm
 
  # For 32-bit C code in PC BIOS.
  LIBRARIES += VBoxPcBios32
diff --git a/src/VBox/Devices/PC/BIOS/ahci.c b/src/VBox/Devices/PC/BIOS/ahci.c
index fd638c9..4f3a4c8 100644
--- a/src/VBox/Devices/PC/BIOS/ahci.c
+++ b/src/VBox/Devices/PC/BIOS/ahci.c
@@ -359,8 +359,8 @@ static uint16_t ahci_cmd_data(bio_dsk_t __far *bios_dsk, uint8_t cmd)
     ahci->abCmd[7]  = RT_BIT_32(6); /* LBA access. */
 
     ahci->abCmd[8]  = (bios_dsk->drqp.lba >> 24) & 0xff;
-    ahci->abCmd[9]  = 0;
-    ahci->abCmd[10] = 0;
+    ahci->abCmd[9]  = (bios_dsk->drqp.lba >> 32) & 0xff;
+    ahci->abCmd[10] = (bios_dsk->drqp.lba >> 40) & 0xff;
     ahci->abCmd[11] = 0;
 
     ahci->abCmd[12] = (uint8_t)(n_sect & 0xff);
@@ -524,9 +524,9 @@ int ahci_read_sectors(bio_dsk_t __far *bios_dsk)
     if (device_id > BX_MAX_AHCI_DEVICES)
         BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
 
-    DBG_AHCI("%s: %u sectors @ LBA %lu, device %d, port %d\n", __func__,
-             bios_dsk->drqp.nsect, bios_dsk->drqp.lba, device_id,
-             bios_dsk->ahcidev[device_id].port);
+    DBG_AHCI("%s: %u sectors @ LBA 0x%llx, device %d, port %d\n", __func__,
+             bios_dsk->drqp.nsect, bios_dsk->drqp.lba,
+             device_id, 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);
@@ -556,7 +556,7 @@ int ahci_write_sectors(bio_dsk_t __far *bios_dsk)
     if (device_id > BX_MAX_AHCI_DEVICES)
         BX_PANIC("%s: device_id out of range %d\n", __func__, device_id);
 
-    DBG_AHCI("%s: %u sectors @ LBA %lu, device %d, port %d\n", __func__,
+    DBG_AHCI("%s: %u sectors @ LBA 0x%llx, device %d, port %d\n", __func__,
              bios_dsk->drqp.nsect, bios_dsk->drqp.lba, device_id,
              bios_dsk->ahcidev[device_id].port);
 
@@ -601,7 +601,7 @@ uint16_t ahci_cmd_packet(uint16_t device_id, uint8_t cmdlen, char __far *cmdbuf,
     DBG_AHCI("%s: reading %u %u-byte sectors\n", __func__,
              bios_dsk->drqp.nsect, bios_dsk->drqp.sect_sz);
 
-    bios_dsk->drqp.lba     = (uint32_t)length << 8;     //@todo: xfer length limit
+    bios_dsk->drqp.lba     = length << 8;     //@todo: xfer length limit
     bios_dsk->drqp.buffer  = buffer;
     bios_dsk->drqp.nsect   = length / bios_dsk->drqp.sect_sz;
 //    bios_dsk->drqp.sect_sz = 2048;
@@ -689,7 +689,7 @@ void ahci_port_detect_device(ahci_t __far *ahci, uint8_t u8Port)
             VBOXAHCI_PORT_READ_REG(ahci->iobase, u8Port, AHCI_REG_PORT_SIG, val);
             if (val == 0x101)
             {
-                uint32_t    sectors;
+                uint64_t    sectors;
                 uint16_t    cylinders, heads, spt;
                 chs_t       lgeo;
                 uint8_t     idxCmosChsBase;
@@ -712,11 +712,10 @@ void ahci_port_detect_device(ahci_t __far *ahci, uint8_t u8Port)
                 spt       = *(uint16_t *)(abBuffer+(6*2));  // word 6
                 sectors   = *(uint32_t *)(abBuffer+(60*2)); // word 60 and word 61
 
-                /** @todo update sectors to be a 64 bit number (also lba...). */
                 if (sectors == 0x0FFFFFFF)  /* For disks bigger than ~128GB */
-                    sectors = *(uint32_t *)(abBuffer+(100*2)); // words 100 to 103 (someday)
+                    sectors = *(uint64_t *)(abBuffer+(100*2)); // words 100 to 103
 
-                DBG_AHCI("AHCI: %ld sectors\n", sectors);
+                DBG_AHCI("AHCI: 0x%llx sectors\n", sectors);
 
                 bios_dsk->ahcidev[devcount_ahci].port = u8Port;
                 bios_dsk->devices[hd_index].type        = DSK_TYPE_AHCI;
@@ -758,8 +757,9 @@ void ahci_port_detect_device(ahci_t __far *ahci, uint8_t u8Port)
                 else
                     set_geom_lba(&lgeo, sectors);   /* Default EDD-style translated LBA geometry. */
 
-                BX_INFO("AHCI %d-P#%d: PCHS=%u/%u/%u LCHS=%u/%u/%u %lu sectors\n", devcount_ahci,
-                        u8Port, cylinders, heads, spt, lgeo.cylinders, lgeo.heads, lgeo.spt, sectors);
+                BX_INFO("AHCI %d-P#%d: PCHS=%u/%u/%u LCHS=%u/%u/%u 0x%llx sectors\n", devcount_ahci,
+                        u8Port, cylinders, heads, spt, lgeo.cylinders, lgeo.heads, lgeo.spt,
+                        sectors);
 
                 bios_dsk->devices[hd_index].lchs = lgeo;
 
diff --git a/src/VBox/Devices/PC/BIOS/ata.c b/src/VBox/Devices/PC/BIOS/ata.c
index 45b79e9..af3e9fe 100644
--- a/src/VBox/Devices/PC/BIOS/ata.c
+++ b/src/VBox/Devices/PC/BIOS/ata.c
@@ -108,7 +108,7 @@ void BIOSCALL ata_init(void)
         bios_dsk->devices[device].pchs.heads     = 0;
         bios_dsk->devices[device].pchs.cylinders = 0;
         bios_dsk->devices[device].pchs.spt       = 0;
-        bios_dsk->devices[device].sectors     = 0;
+        bios_dsk->devices[device].sectors        = 0;
     }
 
     // hdidmap  and cdidmap init.
@@ -206,7 +206,7 @@ void   ata_reset(uint16_t device)
       // 7 : more sectors to write
 uint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t count)
 {
-    uint32_t        lba;
+    uint64_t        lba;
     uint16_t        iobase1, iobase2, blksize, mult_blk_cnt;
     uint16_t        cylinder;
     uint16_t        head;
@@ -255,8 +255,8 @@ uint16_t ata_cmd_data_in(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t c
     if (sector == 0) {
         if (lba + count >= 268435456)
         {
-            sector = (lba & 0xff000000L) >> 24;
-            cylinder = 0; /* The parameter lba is just a 32 bit value. */
+            sector = (lba >> 24) & 0x00ff;
+            cylinder = (lba >> 32) & 0xffff;
             outb(iobase1 + ATA_CB_SC, (count & 0xff00) >> 8);
             outb(iobase1 + ATA_CB_SN, sector);
             outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
@@ -459,7 +459,7 @@ void BIOSCALL ata_detect(void)
 
         // Now we send a IDENTIFY command to ATA device
         if (type == DSK_TYPE_ATA) {
-            uint32_t    sectors;
+            uint64_t    sectors;
             uint16_t    cylinders, heads, spt, blksize;
             chs_t       lgeo;
             uint8_t     chsgeo_base;
@@ -483,9 +483,8 @@ void BIOSCALL ata_detect(void)
             spt       = *(uint16_t *)(buffer+(6*2)); // word 6
 
             sectors   = *(uint32_t *)(buffer+(60*2)); // word 60 and word 61
-            /** @todo update sectors to be a 64 bit number (also lba...). */
             if (sectors == 0x0FFFFFFF)  /* For disks bigger than ~128GB */
-                sectors = *(uint32_t *)(buffer+(100*2)); // words 100 to 103 (someday)
+                sectors = *(uint64_t *)(buffer+(100*2)); // words 100 to 103
             switch (device)
             {
             case 0:
@@ -594,8 +593,7 @@ void BIOSCALL ata_detect(void)
 
             switch (type) {
             case DSK_TYPE_ATA:
-                sizeinmb = bios_dsk->devices[device].sectors;
-                sizeinmb >>= 11;
+                sizeinmb = (bios_dsk->devices[device].sectors >> 11);
             case DSK_TYPE_ATAPI:
                 // Read ATA/ATAPI version
                 ataversion = ((uint16_t)(*(buffer+161))<<8) | *(buffer+160);
@@ -682,7 +680,7 @@ void BIOSCALL ata_detect(void)
       // 7 : more sectors to write
 uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t count)
 {
-    uint32_t        lba;
+    uint64_t        lba;
     char __far      *buffer;
     uint16_t        iobase1, iobase2, blksize;
     uint16_t        cylinder;
@@ -723,8 +721,8 @@ uint16_t ata_cmd_data_out(bio_dsk_t __far *bios_dsk, uint16_t command, uint16_t
     if (sector == 0) {
         if (lba + count >= 268435456)
         {
-            sector = (lba & 0xff000000L) >> 24;
-            cylinder = 0; /* The parameter lba is just a 32 bit value. */
+            sector = (lba >> 24) & 0x00ff;
+            cylinder = (lba >> 32) & 0xffff;
             outb(iobase1 + ATA_CB_SC, (count & 0xff00) >> 8);
             outb(iobase1 + ATA_CB_SN, sector);
             outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff);
@@ -836,14 +834,17 @@ int ata_read_sectors(bio_dsk_t __far *bios_dsk)
     if (bios_dsk->drqp.sector) {
         /* CHS addressing. */
         bios_dsk->devices[device_id].blksize = n_sect * 0x200;
+        BX_DEBUG_ATA("%s: reading %u sectors (CHS)\n", __func__, n_sect);
         status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_MULTIPLE, n_sect);
         bios_dsk->devices[device_id].blksize = 0x200;
     } else {
         /* LBA addressing. */
-        if (bios_dsk->drqp.lba + n_sect >= 268435456)
+        if (bios_dsk->drqp.lba + n_sect >= 268435456) {
+            BX_DEBUG_ATA("%s: reading %u sector (LBA,EXT)\n", __func__, n_sect);
             status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_SECTORS_EXT, n_sect);
-        else {
+        } else {
             bios_dsk->devices[device_id].blksize = n_sect * 0x200;
+            BX_DEBUG_ATA("%s: reading %u sector (LBA,MULT)\n", __func__, n_sect);
             status = ata_cmd_data_in(bios_dsk, ATA_CMD_READ_MULTIPLE, n_sect);
             bios_dsk->devices[device_id].blksize = 0x200;
         }
diff --git a/src/VBox/Devices/PC/BIOS/disk.c b/src/VBox/Devices/PC/BIOS/disk.c
index 355a976..ecfb49f 100644
--- a/src/VBox/Devices/PC/BIOS/disk.c
+++ b/src/VBox/Devices/PC/BIOS/disk.c
@@ -98,12 +98,14 @@ dsk_acc_t   dskacc[DSKTYP_CNT] = {
  * Phoenix EDD 3.0. This is used as a fallback to generate sane logical
  * geometry in case none was provided in CMOS.
  */
-void set_geom_lba(chs_t __far *lgeo, uint32_t nsectors)
+void set_geom_lba(chs_t __far *lgeo, uint64_t nsectors64)
 {
     uint32_t    limit = 8257536;    /* 1024 * 128 * 63 */
+    uint32_t    nsectors;
     unsigned    heads = 255;
     int         i;
 
+    nsectors = (nsectors64 >> 32) ? 0xFFFFFFFFL : (uint32_t)nsectors64;
     /* Start with ~4GB limit, go down to 504MB. */
     for (i = 0; i < 4; ++i) {
         if (nsectors <= limit)
@@ -330,7 +332,7 @@ int13_success_noah:
 
 void BIOSCALL int13_harddisk_ext(disk_regs_t r)
 {
-    uint32_t            lba;
+    uint64_t            lba;
     uint16_t            ebda_seg = read_word(0x0040,0x000E);
     uint16_t            segment, offset;
     uint16_t            npc, nph, npspt;
@@ -383,18 +385,13 @@ void BIOSCALL int13_harddisk_ext(disk_regs_t r)
         segment = i13_ext->segment;
         offset  = i13_ext->offset;
 
-        BX_DEBUG_INT13_HD("%s: %d sectors from lba %lu @ %04x:%04x\n", __func__,
-                          count, i13_ext->lba1, segment, offset);
-
-        // Can't use 64 bits lba
+        // Get 64 bits lba and check
         lba = i13_ext->lba2;
-        if (lba != 0L) {
-            BX_PANIC("%s: function %02x. Can't use 64bits lba\n", __func__, GET_AH());
-            goto int13x_fail;
-        }
+        lba <<= 32;
+        lba |= i13_ext->lba1;
 
-        // Get 32 bits lba and check
-        lba = i13_ext->lba1;
+        BX_DEBUG_INT13_HD("%s: %d sectors from LBA 0x%llx @ %04x:%04x\n", __func__,
+                          count, lba, segment, offset);
 
         type = bios_dsk->devices[device].type;
         if (lba >= bios_dsk->devices[device].sectors) {
@@ -466,8 +463,8 @@ void BIOSCALL int13_harddisk_ext(disk_regs_t r)
             dpt->heads     = nph;
             dpt->spt       = npspt;
             dpt->blksize   = blksize;
-            dpt->sector_count1 = lba;   // FIXME should be Bit64
-            dpt->sector_count2 = 0;
+            dpt->sector_count1 = lba;
+            dpt->sector_count2 = lba >> 32;
         }
 
         /* Fill in EDD 2.x table. */
diff --git a/src/VBox/Devices/PC/BIOS/ebda.h b/src/VBox/Devices/PC/BIOS/ebda.h
index dd9352d..a1cd5df 100644
--- a/src/VBox/Devices/PC/BIOS/ebda.h
+++ b/src/VBox/Devices/PC/BIOS/ebda.h
@@ -192,7 +192,7 @@ typedef struct {
     uint16_t    blksize;      /* Disk block size. */
     chs_t       lchs;         /* Logical CHS geometry. */
     chs_t       pchs;         /* Physical CHS geometry. */
-    uint32_t    sectors;      /* Total sector count. */
+    uint64_t    sectors;      /* Total sector count. */
 } disk_dev_t;
 
 /* A structure for passing disk request information around. This structure
@@ -200,7 +200,7 @@ typedef struct {
  * one such structure is sufficient.
  */
 typedef struct {
-    uint32_t    lba;                /* Starting LBA. */
+    uint64_t    lba;                /* Starting LBA. */
     void __far  *buffer;            /* Read/write data buffer pointer. */
     uint8_t     dev_id;             /* Device ID; index into devices array. */
     uint16_t    nsect;              /* Number of sectors to be transferred. */
@@ -317,7 +317,7 @@ int __fastcall scsi_write_sectors(bio_dsk_t __far *bios_dsk);
 int __fastcall ahci_read_sectors(bio_dsk_t __far *bios_dsk);
 int __fastcall ahci_write_sectors(bio_dsk_t __far *bios_dsk);
 
-extern void set_geom_lba(chs_t __far *lgeo, uint32_t nsectors);
+extern void set_geom_lba(chs_t __far *lgeo, uint64_t nsectors);
 
 // @todo: put this elsewhere (and change/eliminate?)
 #define SET_DISK_RET_STATUS(status) write_byte(0x0040, 0x0074, status)
diff --git a/src/VBox/Devices/PC/BIOS/ow_glue64.asm b/src/VBox/Devices/PC/BIOS/ow_glue64.asm
new file mode 100644
index 0000000..cde216f
--- /dev/null
+++ b/src/VBox/Devices/PC/BIOS/ow_glue64.asm
@@ -0,0 +1,56 @@
+;;
+;; Copyright (C) 2006-2015 Oracle Corporation
+;;
+;; This file is part of VirtualBox Open Source Edition (OSE), as
+;; available from http://www.virtualbox.org. This file is free software;
+;; you can redistribute it and/or modify it under the terms of the GNU
+;; General Public License (GPL) as published by the Free Software
+;; Foundation, in version 2 as it comes in the "COPYING" file of the
+;; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+;; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+;;
+;; --------------------------------------------------------------------
+;;
+;; Shift routines necessary for the OpenWatcom compiler to link code
+;; that uses shifts on 64-bit integers
+;;
+
+ name    ow_glue64
+
+_TEXT segment word public 'CODE'
+      assume  cs:_TEXT
+
+public __U8LS
+public __U8RS
+
+__U8LS proc near
+        test si, si
+        je short out1
+loop1:
+        sal dx, 1
+        rcl cx, 1
+        rcl bx, 1
+        rcl ax, 1
+        dec si
+        jne short loop1
+out1:
+        retn
+__U8LS endp
+
+__U8RS proc near
+        test si, si
+        je short out2
+loop2:
+        shr ax, 1
+        rcr bx, 1
+        rcr cx, 1
+        rcr dx, 1
+        dec si
+        jne short loop2
+out2:
+        retn
+__U8RS endp
+
+_TEXT ends
+
+ end
diff --git a/src/VBox/Devices/PC/BIOS/print.c b/src/VBox/Devices/PC/BIOS/print.c
index af5e85f..1d09471 100644
--- a/src/VBox/Devices/PC/BIOS/print.c
+++ b/src/VBox/Devices/PC/BIOS/print.c
@@ -144,7 +144,9 @@ void put_str_near(uint16_t action, const char __near *s)
 //
 //   Supports %[format_width][length]format
 //   where format can be x,X,u,d,s,S,c
-//   and the optional length modifier is l (ell)
+//   and the optional length modifier is l (ell, long 32-bit) or ll
+//   (long long, 64-bit).
+//   Only x,X work with ll
 //--------------------------------------------------------------------------
 void bios_printf(uint16_t action, const char *s, ...)
 {
@@ -189,6 +191,32 @@ void bios_printf(uint16_t action, const char *s, ...)
                 else if (c == 'u') {
                     put_uint(action, arg, format_width, 0);
                 }
+                else if (c == 'l' && s[1] == 'l') {
+                    uint64_t llval;
+                    uint16_t *cp16;
+
+                    s += 2;
+                    c = *s;
+                    cp16 = (uint16_t *)&llval;
+                    cp16[0] = arg;
+                    cp16[1] = va_arg( args, uint16_t );
+                    cp16[2] = va_arg( args, uint16_t );
+                    cp16[3] = va_arg( args, uint16_t );
+                    if (c == 'x' || c == 'X') {
+                        if (format_width == 0)
+                            format_width = 16;
+                        if (c == 'x')
+                            hexadd = 'a';
+                        else
+                            hexadd = 'A';
+                        for (i=format_width-1; i>=0; i--) {
+                            nibble =  (llval >> (i * 4)) & 0x000f;
+                            send (action, (nibble<=9)? (nibble+'0') : (nibble-10+hexadd));
+                        }
+                    } else {
+                        BX_PANIC("bios_printf: unknown %ll format\n");
+                    }
+                }
                 else if (c == 'l') {
                     s++;
                     c = *s; /* is it ld,lx,lu? */
diff --git a/src/VBox/Devices/PC/BIOS/scsi.c b/src/VBox/Devices/PC/BIOS/scsi.c
index 36393de..1df60c8 100644
--- a/src/VBox/Devices/PC/BIOS/scsi.c
+++ b/src/VBox/Devices/PC/BIOS/scsi.c
@@ -48,10 +48,14 @@
 #define VBSCSI_MAX_DEVICES 16 /* Maximum number of devices a SCSI device can have. */
 
 /* Command opcodes. */
+#define SCSI_SERVICE_ACT   0x9e
 #define SCSI_INQUIRY       0x12
-#define SCSI_READ_CAPACITY 0x25
+#define SCSI_READ_CAP_10   0x25
 #define SCSI_READ_10       0x28
 #define SCSI_WRITE_10      0x2a
+#define SCSI_READ_CAP_16   0x10    /* Not an opcode by itself, sub-action for the "Service Action" */
+#define SCSI_READ_16       0x88
+#define SCSI_WRITE_16      0x8a
 
 /* Data transfer direction. */
 #define SCSI_TXDIR_FROM_DEVICE 0
@@ -68,10 +72,19 @@ typedef struct {
     uint8_t     pad2;       /* Unused. */
 } cdb_rw10;
 
+/* READ_16/WRITE_16 CDB layout. */
+typedef struct {
+    uint16_t    command;    /* Command. */
+    uint64_t    lba;        /* LBA, MSB first! */
+    uint32_t    nsect32;    /* Sector count, MSB first! */
+    uint8_t     pad1;       /* Unused. */
+    uint8_t     pad2;       /* Unused. */
+} cdb_rw16;
+
 #pragma pack()
 
 ct_assert(sizeof(cdb_rw10) == 10);
-
+ct_assert(sizeof(cdb_rw16) == 16);
 
 void insb_discard(unsigned nbytes, unsigned port);
 #pragma aux insb_discard =  \
@@ -93,8 +106,7 @@ int scsi_cmd_data_in(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
         status = inb(io_base + VBSCSI_REGISTER_STATUS);
     while (status & VBSCSI_BUSY);
 
-
-    sizes = ((length >> 12) & 0xF0) | cbCDB;
+    sizes = ((length >> 12) & 0xF0) | (cbCDB == 16) ? 0 : cbCDB;
     outb(io_base + VBSCSI_REGISTER_COMMAND, target_id);                 /* Write the target ID. */
     outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_FROM_DEVICE);    /* Write the transfer direction. */
     outb(io_base + VBSCSI_REGISTER_COMMAND, sizes);                     /* Write CDB size and top bufsize bits. */
@@ -145,7 +157,7 @@ int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
     while (status & VBSCSI_BUSY);
 
 
-    sizes = ((length >> 12) & 0xF0) | cbCDB;
+    sizes = ((length >> 12) & 0xF0) | (cbCDB == 16) ? 0 : cbCDB;
     outb(io_base + VBSCSI_REGISTER_COMMAND, target_id);                 /* Write the target ID. */
     outb(io_base + VBSCSI_REGISTER_COMMAND, SCSI_TXDIR_TO_DEVICE);      /* Write the transfer direction. */
     outb(io_base + VBSCSI_REGISTER_COMMAND, sizes);                     /* Write CDB size and top bufsize bits. */
@@ -184,6 +196,17 @@ int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
     return 0;
 }
 
+static uint64_t swap_64(uint64_t val)
+{
+    uint64_t rval;
+
+    rval = swap_32(val & 0xffffffff);
+    rval <<= 32;
+    rval |= swap_32(val >> 32);
+
+    return rval;
+}
+
 /**
  * Read sectors from an attached SCSI device.
  *
@@ -194,8 +217,8 @@ int scsi_cmd_data_out(uint16_t io_base, uint8_t target_id, uint8_t __far *aCDB,
 int scsi_read_sectors(bio_dsk_t __far *bios_dsk)
 {
     uint8_t             rc;
-    cdb_rw10            cdb;
-    uint16_t            count;
+    cdb_rw16            cdb;
+    uint32_t            count;
     uint16_t            io_base;
     uint8_t             target_id;
     uint8_t             device_id;
@@ -207,10 +230,10 @@ int scsi_read_sectors(bio_dsk_t __far *bios_dsk)
     count    = bios_dsk->drqp.nsect;
 
     /* Prepare a CDB. */
-    cdb.command = SCSI_READ_10;
-    cdb.lba     = swap_32(bios_dsk->drqp.lba);
+    cdb.command = SCSI_READ_16;
+    cdb.lba     = swap_64(bios_dsk->drqp.lba);
     cdb.pad1    = 0;
-    cdb.nsect   = swap_16(count);
+    cdb.nsect32 = swap_32(count);
     cdb.pad2    = 0;
 
 
@@ -220,7 +243,7 @@ int scsi_read_sectors(bio_dsk_t __far *bios_dsk)
     DBG_SCSI("%s: reading %u sectors, device %d, target %d\n", __func__,
              count, device_id, bios_dsk->scsidev[device_id].target_id);
 
-    rc = scsi_cmd_data_in(io_base, target_id, (void __far *)&cdb, 10,
+    rc = scsi_cmd_data_in(io_base, target_id, (void __far *)&cdb, 16,
                           bios_dsk->drqp.buffer, (count * 512L));
 
     if (!rc)
@@ -243,8 +266,8 @@ int scsi_read_sectors(bio_dsk_t __far *bios_dsk)
 int scsi_write_sectors(bio_dsk_t __far *bios_dsk)
 {
     uint8_t             rc;
-    cdb_rw10            cdb;
-    uint16_t            count;
+    cdb_rw16            cdb;
+    uint32_t            count;
     uint16_t            io_base;
     uint8_t             target_id;
     uint8_t             device_id;
@@ -256,10 +279,10 @@ int scsi_write_sectors(bio_dsk_t __far *bios_dsk)
     count    = bios_dsk->drqp.nsect;
 
     /* Prepare a CDB. */
-    cdb.command = SCSI_WRITE_10;
-    cdb.lba     = swap_32(bios_dsk->drqp.lba);
+    cdb.command = SCSI_WRITE_16;
+    cdb.lba     = swap_64(bios_dsk->drqp.lba);
     cdb.pad1    = 0;
-    cdb.nsect   = swap_16(count);
+    cdb.nsect32 = swap_32(count);
     cdb.pad2    = 0;
 
     io_base   = bios_dsk->scsidev[device_id].io_base;
@@ -268,7 +291,7 @@ int scsi_write_sectors(bio_dsk_t __far *bios_dsk)
     DBG_SCSI("%s: writing %u sectors, device %d, target %d\n", __func__,
              count, device_id, bios_dsk->scsidev[device_id].target_id);
 
-    rc = scsi_cmd_data_out(io_base, target_id, (void __far *)&cdb, 10,
+    rc = scsi_cmd_data_out(io_base, target_id, (void __far *)&cdb, 16,
                            bios_dsk->drqp.buffer, (count * 512L));
 
     if (!rc)
@@ -402,7 +425,7 @@ void scsi_enumerate_attached_devices(uint16_t io_base)
     for (i = 0; i < VBSCSI_MAX_DEVICES; i++)
     {
         uint8_t     rc;
-        uint8_t     aCDB[10];
+        uint8_t     aCDB[16];
         uint8_t     hd_index, devcount_scsi;
 
         aCDB[0] = SCSI_INQUIRY;
@@ -427,31 +450,31 @@ void scsi_enumerate_attached_devices(uint16_t io_base)
             /* We add the disk only if the maximum is not reached yet. */
             if (devcount_scsi < BX_MAX_SCSI_DEVICES)
             {
-                uint32_t    sectors, sector_size, cylinders;
+                uint64_t    sectors, t;
+                uint32_t    sector_size, cylinders;
                 uint16_t    heads, sectors_per_track;
                 uint8_t     hdcount;
                 uint8_t     cmos_base;
 
                 /* Issue a read capacity command now. */
                 _fmemset(aCDB, 0, sizeof(aCDB));
-                aCDB[0] = SCSI_READ_CAPACITY;
+                aCDB[0] = SCSI_SERVICE_ACT;
+                aCDB[1] = SCSI_READ_CAP_16;
+                aCDB[13] = 32; /* Allocation length. */
 
-                rc = scsi_cmd_data_in(io_base, i, aCDB, 10, buffer, 8);
+                rc = scsi_cmd_data_in(io_base, i, aCDB, 16, buffer, 32);
                 if (rc != 0)
                     BX_PANIC("%s: SCSI_READ_CAPACITY failed\n", __func__);
 
-                /* Build sector number and size from the buffer. */
-                //@todo: byte swapping for dword sized items should be farmed out...
-                sectors =   ((uint32_t)buffer[0] << 24)
-                          | ((uint32_t)buffer[1] << 16)
-                          | ((uint32_t)buffer[2] << 8)
-                          | ((uint32_t)buffer[3]);
-                ++sectors;  /* Returned value is the last LBA, zero-based. */
+                /* The value returned is the last addressable LBA, not
+                 * the size, which what "+ 1" is for.
+                 */
+                sectors = swap_64(*(uint64_t *)buffer) + 1;
 
-                sector_size =   ((uint32_t)buffer[4] << 24)
-                              | ((uint32_t)buffer[5] << 16)
-                              | ((uint32_t)buffer[6] << 8)
-                              | ((uint32_t)buffer[7]);
+                sector_size =   ((uint32_t)buffer[8] << 24)
+                              | ((uint32_t)buffer[9] << 16)
+                              | ((uint32_t)buffer[10] << 8)
+                              | ((uint32_t)buffer[11]);
 
                 /* We only support the disk if sector size is 512 bytes. */
                 if (sector_size != 512)
@@ -496,18 +519,22 @@ void scsi_enumerate_attached_devices(uint16_t io_base)
                     {
                         heads = 255;
                         sectors_per_track = 63;
+                        /* Approximate x / (255 * 63) using shifts */
+                        t = (sectors >> 6) + (sectors >> 12);
+                        cylinders = (t >> 8) + (t >> 16);
                     }
                     else if (sectors >= (uint32_t)2 * 1024 * 1024)
                     {
                         heads = 128;
                         sectors_per_track = 32;
+                        cylinders = sectors >> 12;
                     }
                     else
                     {
                         heads = 64;
                         sectors_per_track = 32;
+                        cylinders = sectors >> 11;
                     }
-                    cylinders = (uint32_t)(sectors / (heads * sectors_per_track));
                 }
 
                 /* Calculate index into the generic disk table. */
@@ -522,24 +549,22 @@ void scsi_enumerate_attached_devices(uint16_t io_base)
                 bios_dsk->devices[hd_index].blksize     = sector_size;
                 bios_dsk->devices[hd_index].translation = GEO_TRANSLATION_LBA;
 
-                /* Write LCHS values. */
+                /* Write LCHS/PCHS values. */
                 bios_dsk->devices[hd_index].lchs.heads = heads;
                 bios_dsk->devices[hd_index].lchs.spt   = sectors_per_track;
-                if (cylinders > 1024)
-                    bios_dsk->devices[hd_index].lchs.cylinders = 1024;
-                else
-                    bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;
-
-                BX_INFO("SCSI %d-ID#%d: LCHS=%u/%u/%u %lu sectors\n", devcount_scsi,
-                        i, (uint16_t)cylinders, heads, sectors_per_track, sectors);
-
-                /* Write PCHS values. */
                 bios_dsk->devices[hd_index].pchs.heads = heads;
                 bios_dsk->devices[hd_index].pchs.spt   = sectors_per_track;
-                if (cylinders > 1024)
+
+                if (cylinders > 1024) {
+                    bios_dsk->devices[hd_index].lchs.cylinders = 1024;
                     bios_dsk->devices[hd_index].pchs.cylinders = 1024;
-                else
+                } else {
+                    bios_dsk->devices[hd_index].lchs.cylinders = (uint16_t)cylinders;
                     bios_dsk->devices[hd_index].pchs.cylinders = (uint16_t)cylinders;
+                }
+
+                BX_INFO("SCSI %d-ID#%d: LCHS=%lu/%u/%u 0x%llx sectors\n", devcount_scsi,
+                        i, (uint32_t)cylinders, heads, sectors_per_track, sectors);
 
                 bios_dsk->devices[hd_index].sectors = sectors;
 
diff --git a/src/VBox/Devices/Storage/VBoxSCSI.cpp b/src/VBox/Devices/Storage/VBoxSCSI.cpp
index 04fefa5..d638d50 100644
--- a/src/VBox/Devices/Storage/VBoxSCSI.cpp
+++ b/src/VBox/Devices/Storage/VBoxSCSI.cpp
@@ -173,7 +173,10 @@ int vboxscsiWriteRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint8_t uVal)
             }
             else if (pVBoxSCSI->enmState == VBOXSCSISTATE_READ_CDB_SIZE_BUFHI)
             {
-                uint8_t cbCDB = uVal & 0x0F;
+                uint8_t cbCDB = (uVal & 0x0F);
+
+                if (cbCDB == 0)
+                    cbCDB = 16;
                 if (cbCDB > VBOXSCSI_CDB_SIZE_MAX)
                     vboxscsiReset(pVBoxSCSI, true /*fEverything*/);
                 else
diff --git a/src/VBox/Devices/Storage/VBoxSCSI.h b/src/VBox/Devices/Storage/VBoxSCSI.h
index 4f4b5e2..776dff5 100644
--- a/src/VBox/Devices/Storage/VBoxSCSI.h
+++ b/src/VBox/Devices/Storage/VBoxSCSI.h
@@ -87,7 +87,7 @@ typedef enum VBOXSCSISTATE
 #define VBOXSCSI_TXDIR_TO_DEVICE   1
 
 /** Maximum CDB size the BIOS driver sends. */
-#define VBOXSCSI_CDB_SIZE_MAX     10
+#define VBOXSCSI_CDB_SIZE_MAX     16
 
 typedef struct VBOXSCSI
 {
@@ -100,7 +100,7 @@ typedef struct VBOXSCSI
     /** The size of the CDB we are issuing. */
     uint8_t              cbCDB;
     /** The command to issue. */
-    uint8_t              abCDB[12];
+    uint8_t              abCDB[VBOXSCSI_CDB_SIZE_MAX + 4];
     /** Current position in the array. */
     uint8_t              iCDB;
 
