Unify cd emulation access and main disk access code.
[seabios.git] / src / block.c
index 70fffae962db303e31da61511262766b5a6c155f..10ddcfc7a98c766e2ddbe0a10422cca5b92e9fe8 100644 (file)
@@ -9,8 +9,9 @@
 #include "biosvar.h" // GET_GLOBAL
 #include "cmos.h" // inb_cmos
 #include "util.h" // dprintf
+#include "ata.h" // process_ata_op
 
-struct drives_s Drives VAR16_32;
+struct drives_s Drives VAR16VISIBLE;
 
 
 /****************************************************************
@@ -162,11 +163,11 @@ fill_fdpt(int driveid)
     fdpt->checksum -= checksum(fdpt, sizeof(*fdpt));
 
     if (driveid == 0)
-        SET_IVT(0x41, get_ebda_seg()
-                , offsetof(struct extended_bios_data_area_s, fdpt[0]));
+        SET_IVT(0x41, SEGOFF(get_ebda_seg(), offsetof(
+                                 struct extended_bios_data_area_s, fdpt[0])));
     else
-        SET_IVT(0x46, get_ebda_seg()
-                , offsetof(struct extended_bios_data_area_s, fdpt[1]));
+        SET_IVT(0x46, SEGOFF(get_ebda_seg(), offsetof(
+                                 struct extended_bios_data_area_s, fdpt[1])));
 }
 
 // Map a drive (that was registered via add_bcv_hd)
@@ -223,6 +224,94 @@ map_floppy_drive(int driveid)
     }
 }
 
+// Show a one line description (without trailing newline) of a drive.
+void
+describe_drive(int driveid)
+{
+    ASSERT32();
+    u8 type = GET_GLOBAL(Drives.drives[driveid].type);
+    switch (type) {
+    case DTYPE_FLOPPY:
+        describe_floppy(driveid);
+        break;
+    case DTYPE_ATA:
+        describe_ata(driveid);
+        break;
+    case DTYPE_ATAPI:
+        describe_atapi(driveid);
+        break;
+    case DTYPE_RAMDISK:
+        describe_ramdisk(driveid);
+        break;
+    default:
+        printf("Unknown");
+        break;
+    }
+}
+
+
+/****************************************************************
+ * 16bit calling interface
+ ****************************************************************/
+
+// Execute a disk_op request.
+int
+process_op(struct disk_op_s *op)
+{
+    u8 type = GET_GLOBAL(Drives.drives[op->driveid].type);
+    switch (type) {
+    case DTYPE_FLOPPY:
+        return process_floppy_op(op);
+    case DTYPE_ATA:
+        return process_ata_op(op);
+    case DTYPE_ATAPI:
+        return process_atapi_op(op);
+    case DTYPE_RAMDISK:
+        return process_ramdisk_op(op);
+    case DTYPE_CDEMU:
+        return process_cdemu_op(op);
+    default:
+        op->count = 0;
+        return DISK_RET_EPARAM;
+    }
+}
+
+// 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)
+{
+    struct disk_op_s dop;
+    memcpy_far(GET_SEG(SS), &dop
+               , op_seg, op_far
+               , sizeof(dop));
+
+    dprintf(DEBUG_HDL_13, "disk_op d=%d lba=%d buf=%p count=%d cmd=%d\n"
+            , dop.driveid, (u32)dop.lba, dop.buf_fl
+            , dop.count, dop.command);
+
+    irq_enable();
+
+    int status = process_op(&dop);
+
+    irq_disable();
+
+    // Update count with total sectors transferred.
+    SET_FARVAR(op_seg, op_far->count, dop.count);
+
+    return status;
+}
+
+// Execute a "disk_op_s" request by jumping to a stack in the ebda.
+int
+send_disk_op(struct disk_op_s *op)
+{
+    if (! CONFIG_DRIVES)
+        return -1;
+    ASSERT16();
+
+    return stack_hop((u32)op, GET_SEG(SS), 0, __send_disk_op);
+}
+
 
 /****************************************************************
  * Setup