Separate cdemu disk accesses from regular disk accesses.

Breakup basic_access() into basic_access, cdemu_access, and legacy_lba.
Also, check for verify and seek calls in __send_disk_op instead of all
    callers.
Also, send_disk_op returns sector count in dop.count instead of via ebda.
diff --git a/src/cdrom.c b/src/cdrom.c
index 8ccbeea..b96afa0 100644
--- a/src/cdrom.c
+++ b/src/cdrom.c
@@ -180,6 +180,18 @@
  * CD emulation
  ****************************************************************/
 
+static void
+cdemu_1302(struct bregs *regs, u8 device)
+{
+    cdemu_access(regs, device, ATA_CMD_READ_SECTORS);
+}
+
+static void
+cdemu_1304(struct bregs *regs, u8 device)
+{
+    cdemu_access(regs, device, 0);
+}
+
 // read disk drive parameters
 static void
 cdemu_1308(struct bregs *regs, u8 device)
@@ -217,11 +229,9 @@
     device += GET_EBDA2(ebda_seg, cdemu.device_spec);
 
     switch (regs->ah) {
-    // These functions are the same as for hard disks
-    case 0x02:
-    case 0x04:
-        disk_13(regs, device);
-        break;
+    case 0x02: cdemu_1302(regs, device); break;
+    case 0x04: cdemu_1304(regs, device); break;
+    case 0x08: cdemu_1308(regs, device); break;
 
     // These functions are the same as standard CDROM.
     case 0x00:
@@ -239,8 +249,6 @@
         cdrom_13(regs, device);
         break;
 
-    case 0x08: cdemu_1308(regs, device); break;
-
     default:   disk_13XX(regs, device); break;
     }
 }
diff --git a/src/disk.c b/src/disk.c
index 898fe49..e56bcd0 100644
--- a/src/disk.c
+++ b/src/disk.c
@@ -40,6 +40,7 @@
 #define DISK_STUB(regs)                         \
     __disk_stub((regs), __LINE__, __func__)
 
+// Execute a "disk_op_s" request - this runs on a stack in the ebda.
 static int
 __send_disk_op(struct disk_op_s *op_far, u16 op_seg)
 {
@@ -55,6 +56,9 @@
     irq_enable();
 
     int status;
+    if (!dop.command)
+        // If verify or seek
+        status = 0;
     if (dop.command == CMD_CDEMU_READ)
         status = cdrom_read_512(&dop);
     else if (dop.command == CMD_CDROM_READ)
@@ -64,9 +68,16 @@
 
     irq_disable();
 
+    // Update count with total sectors transferred.
+    SET_FARVAR(op_seg, op_far->count, GET_EBDA(sector_count));
+
+    if (status)
+        dprintf(1, "disk_op cmd %d error %d!\n", dop.command, status);
+
     return status;
 }
 
+// Execute a "disk_op_s" request by jumping to a stack in the ebda.
 static int
 send_disk_op(struct disk_op_s *op)
 {
@@ -76,39 +87,20 @@
     return stack_hop((u32)op, GET_SEG(SS), 0, __send_disk_op);
 }
 
-static void
-basic_access(struct bregs *regs, u8 device, u16 command)
+// Obtain the requested disk lba from an old-style chs request.
+static int
+legacy_lba(struct bregs *regs, struct disk_op_s *op, u16 nlc, u16 nlh, u16 nlspt)
 {
-    struct disk_op_s dop;
-    dop.lba = 0;
-    dop.driveid = device;
-    u8 type = GET_GLOBAL(ATA.devices[device].type);
-    u16 nlc, nlh, nlspt;
-    if (type == ATA_TYPE_ATA) {
-        nlc   = GET_GLOBAL(ATA.devices[device].lchs.cylinders);
-        nlh   = GET_GLOBAL(ATA.devices[device].lchs.heads);
-        nlspt = GET_GLOBAL(ATA.devices[device].lchs.spt);
-        dop.command = command;
-    } else {
-        // Must be cd emulation.
-        u16 ebda_seg = get_ebda_seg();
-        nlc   = GET_EBDA2(ebda_seg, cdemu.cylinders);
-        nlh   = GET_EBDA2(ebda_seg, cdemu.heads);
-        nlspt = GET_EBDA2(ebda_seg, cdemu.spt);
-        dop.lba = GET_EBDA2(ebda_seg, cdemu.ilba) * 4;
-        dop.command = CMD_CDEMU_READ;
-    }
+    op->count = regs->al;
+    u16 cylinder = regs->ch | ((((u16)regs->cl) << 2) & 0x300);
+    u16 sector = regs->cl & 0x3f;
+    u16 head = regs->dh;
 
-    dop.count       = regs->al;
-    u16 cylinder    = regs->ch | ((((u16) regs->cl) << 2) & 0x300);
-    u16 sector      = regs->cl & 0x3f;
-    u16 head        = regs->dh;
-
-    if (dop.count > 128 || dop.count == 0 || sector == 0) {
+    if (op->count > 128 || op->count == 0 || sector == 0) {
         dprintf(1, "int13_harddisk: function %02x, parameter out of range!\n"
                 , regs->ah);
         disk_ret(regs, DISK_RET_EPARAM);
-        return;
+        return -1;
     }
 
     // sanity check on cyl heads, sec
@@ -117,37 +109,73 @@
                 " range %04x/%04x/%04x!\n"
                 , regs->ah, cylinder, head, sector);
         disk_ret(regs, DISK_RET_EPARAM);
-        return;
-    }
-
-    if (!command) {
-        // If verify or seek
-        disk_ret(regs, DISK_RET_SUCCESS);
-        return;
+        return -1;
     }
 
     // translate lchs to lba
-    dop.lba += (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt)
-                + (u32)sector - 1);
+    op->lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt)
+               + (u32)sector - 1);
 
     u16 segment = regs->es;
     u16 offset  = regs->bx;
-    dop.buf_fl = MAKE_FLATPTR(segment, offset);
+    op->buf_fl = MAKE_FLATPTR(segment, offset);
+
+    return 0;
+}
+
+// Perform read/write/verify using old-style chs accesses
+static void
+basic_access(struct bregs *regs, u8 device, u16 command)
+{
+    struct disk_op_s dop;
+    dop.driveid = device;
+    dop.command = command;
+    u16 nlc = GET_GLOBAL(ATA.devices[device].lchs.cylinders);
+    u16 nlh = GET_GLOBAL(ATA.devices[device].lchs.heads);
+    u16 nlspt = GET_GLOBAL(ATA.devices[device].lchs.spt);
+    int ret = legacy_lba(regs, &dop, nlc, nlh, nlspt);
+    if (ret)
+        return;
 
     int status = send_disk_op(&dop);
 
-    // Set nb of sector transferred
-    regs->al = GET_EBDA(sector_count);
+    regs->al = dop.count;
 
-    if (status != 0) {
-        dprintf(1, "int13_harddisk: function %02x, error %d!\n"
-                , regs->ah, status);
+    if (status) {
         disk_ret(regs, DISK_RET_EBADTRACK);
         return;
     }
     disk_ret(regs, DISK_RET_SUCCESS);
 }
 
+// Perform cdemu read/verify
+void
+cdemu_access(struct bregs *regs, u8 device, u16 command)
+{
+    struct disk_op_s dop;
+    dop.driveid = device;
+    dop.command = (command == ATA_CMD_READ_SECTORS ? CMD_CDEMU_READ : 0);
+    u16 ebda_seg = get_ebda_seg();
+    u16 nlc = GET_EBDA2(ebda_seg, cdemu.cylinders);
+    u16 nlh = GET_EBDA2(ebda_seg, cdemu.heads);
+    u16 nlspt = GET_EBDA2(ebda_seg, cdemu.spt);
+    int ret = legacy_lba(regs, &dop, nlc, nlh, nlspt);
+    if (ret)
+        return;
+    dop.lba += GET_EBDA2(ebda_seg, cdemu.ilba) * 4;
+
+    int status = send_disk_op(&dop);
+
+    regs->al = dop.count;
+
+    if (status) {
+        disk_ret(regs, DISK_RET_EBADTRACK);
+        return;
+    }
+    disk_ret(regs, DISK_RET_SUCCESS);
+}
+
+// Perform read/write/verify using new-style "int13ext" accesses.
 static void
 extended_access(struct bregs *regs, u8 device, u16 command)
 {
@@ -168,12 +196,6 @@
         dop.command = CMD_CDROM_READ;
     }
 
-    if (!command) {
-        // If verify or seek
-        disk_ret(regs, DISK_RET_SUCCESS);
-        return;
-    }
-
     u16 segment = GET_INT13EXT(regs, segment);
     u16 offset = GET_INT13EXT(regs, offset);
     dop.buf_fl = MAKE_FLATPTR(segment, offset);
@@ -181,11 +203,9 @@
 
     int status = send_disk_op(&dop);
 
-    SET_INT13EXT(regs, count, GET_EBDA(sector_count));
+    SET_INT13EXT(regs, count, dop.count);
 
-    if (status != 0) {
-        dprintf(1, "int13_harddisk: function %02x, error %d!\n"
-                , regs->ah, status);
+    if (status) {
         disk_ret(regs, DISK_RET_EBADTRACK);
         return;
     }
diff --git a/src/disk.h b/src/disk.h
index 8e9f1cb..b4d8444 100644
--- a/src/disk.h
+++ b/src/disk.h
@@ -224,6 +224,7 @@
 // disk.c
 void disk_13(struct bregs *regs, u8 device);
 void disk_13XX(struct bregs *regs, u8 device);
+void cdemu_access(struct bregs *regs, u8 device, u16 command);
 
 // cdrom.c
 void cdrom_13(struct bregs *regs, u8 device);