Separate ATA code from generic disk code.
[seabios.git] / src / disk.c
index d4b80dea83db55238c54299aedf19654024be0e7..263c0d9a802e2e18df621da9a3978d50e58660a2 100644 (file)
@@ -12,7 +12,7 @@
 #include "pic.h" // eoi_pic2
 #include "bregs.h" // struct bregs
 #include "pci.h" // pci_bdf_to_bus
-#include "atabits.h" // ATA_CB_STAT
+#include "ata.h" // ATA_CB_DC
 
 
 /****************************************************************
@@ -55,14 +55,12 @@ __send_disk_op(struct disk_op_s *op_far, u16 op_seg)
 
     irq_enable();
 
-    int status;
-    if (!dop.command)
-        // If verify or seek
-        status = 0;
-    if (dop.command == CMD_CDROM_READ)
-        status = cdrom_read(&dop);
-    else
-        status = ata_cmd_data(&dop);
+    int status = 0;
+    u8 type = GET_GLOBAL(Drives.drives[dop.driveid].type);
+    if (type == DTYPE_ATA)
+        status = process_ata_op(&dop);
+    else if (type == DTYPE_ATAPI)
+        status = process_atapi_op(&dop);
 
     irq_disable();
 
@@ -79,7 +77,7 @@ __send_disk_op(struct disk_op_s *op_far, u16 op_seg)
 static int
 send_disk_op(struct disk_op_s *op)
 {
-    if (! CONFIG_ATA)
+    if (! CONFIG_DRIVES)
         return -1;
 
     return stack_hop((u32)op, GET_SEG(SS), 0, __send_disk_op);
@@ -126,7 +124,7 @@ basic_access(struct bregs *regs, u8 device, u16 command)
     struct disk_op_s dop;
     dop.driveid = device;
     dop.command = command;
-    int lba = legacy_lba(regs, get_global_seg(), &ATA.devices[device].lchs);
+    int lba = legacy_lba(regs, get_global_seg(), &Drives.drives[device].lchs);
     if (lba < 0)
         return;
     dop.lba = lba;
@@ -150,7 +148,7 @@ 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_CDROM_READ : 0);
+    dop.command = command;
     u16 ebda_seg = get_ebda_seg();
     int vlba = legacy_lba(
         regs, ebda_seg
@@ -220,16 +218,11 @@ extended_access(struct bregs *regs, u8 device, u16 command)
     dop.lba = GET_INT13EXT(regs, lba);
     dop.command = command;
     dop.driveid = device;
-    u8 type = GET_GLOBAL(ATA.devices[device].type);
-    if (type == ATA_TYPE_ATA) {
-        if (dop.lba >= GET_GLOBAL(ATA.devices[device].sectors)) {
-            dprintf(1, "int13_harddisk: function %02x. LBA out of range\n"
-                    , regs->ah);
-            disk_ret(regs, DISK_RET_EPARAM);
-            return;
-        }
-    } else {
-        dop.command = CMD_CDROM_READ;
+    if (dop.lba >= GET_GLOBAL(Drives.drives[device].sectors)) {
+        dprintf(1, "int13_harddisk: function %02x. LBA out of range\n"
+                , regs->ah);
+        disk_ret(regs, DISK_RET_EPARAM);
+        return;
     }
 
     u16 segment = GET_INT13EXT(regs, segment);
@@ -257,7 +250,10 @@ extended_access(struct bregs *regs, u8 device, u16 command)
 static void
 disk_1300(struct bregs *regs, u8 device)
 {
-    ata_reset(device);
+    struct disk_op_s dop;
+    dop.driveid = device;
+    dop.command = CMD_RESET;
+    send_disk_op(&dop);
 }
 
 // read disk status
@@ -274,21 +270,21 @@ disk_1301(struct bregs *regs, u8 device)
 static void
 disk_1302(struct bregs *regs, u8 device)
 {
-    basic_access(regs, device, ATA_CMD_READ_SECTORS);
+    basic_access(regs, device, CMD_READ);
 }
 
 // write disk sectors
 static void
 disk_1303(struct bregs *regs, u8 device)
 {
-    basic_access(regs, device, ATA_CMD_WRITE_SECTORS);
+    basic_access(regs, device, CMD_WRITE);
 }
 
 // verify disk sectors
 static void
 disk_1304(struct bregs *regs, u8 device)
 {
-    basic_access(regs, device, 0);
+    basic_access(regs, device, CMD_VERIFY);
     // FIXME verify
 }
 
@@ -304,9 +300,9 @@ static void
 disk_1308(struct bregs *regs, u8 device)
 {
     // Get logical geometry from table
-    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);
+    u16 nlc = GET_GLOBAL(Drives.drives[device].lchs.cylinders);
+    u16 nlh = GET_GLOBAL(Drives.drives[device].lchs.heads);
+    u16 nlspt = GET_GLOBAL(Drives.drives[device].lchs.spt);
     u16 count = GET_BDA(hdcount);
 
     nlc = nlc - 2; /* 0 based , last sector not used */
@@ -347,12 +343,14 @@ disk_1310(struct bregs *regs, u8 device)
 {
     // should look at 40:8E also???
 
-    // Read the status from controller
-    u8 status = inb(GET_GLOBAL(ATA.channels[device/2].iobase1) + ATA_CB_STAT);
-    if ( (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY )
-        disk_ret(regs, DISK_RET_SUCCESS);
-    else
+    struct disk_op_s dop;
+    dop.driveid = device;
+    dop.command = CMD_ISREADY;
+    int status = send_disk_op(&dop);
+    if (status)
         disk_ret(regs, DISK_RET_ENOTREADY);
+    else
+        disk_ret(regs, DISK_RET_SUCCESS);
 }
 
 // recalibrate
@@ -374,9 +372,9 @@ static void
 disk_1315(struct bregs *regs, u8 device)
 {
     // Get logical geometry from table
-    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);
+    u16 nlc   = GET_GLOBAL(Drives.drives[device].lchs.cylinders);
+    u16 nlh   = GET_GLOBAL(Drives.drives[device].lchs.heads);
+    u16 nlspt = GET_GLOBAL(Drives.drives[device].lchs.spt);
 
     // Compute sector count seen by int13
     u32 lba = (u32)(nlc - 1) * (u32)nlh * (u32)nlspt;
@@ -401,21 +399,21 @@ disk_1341(struct bregs *regs, u8 device)
 static void
 disk_1342(struct bregs *regs, u8 device)
 {
-    extended_access(regs, device, ATA_CMD_READ_SECTORS);
+    extended_access(regs, device, CMD_READ);
 }
 
 // IBM/MS extended write
 static void
 disk_1343(struct bregs *regs, u8 device)
 {
-    extended_access(regs, device, ATA_CMD_WRITE_SECTORS);
+    extended_access(regs, device, CMD_WRITE);
 }
 
 // IBM/MS verify
 static void
 disk_1344(struct bregs *regs, u8 device)
 {
-    extended_access(regs, device, 0);
+    extended_access(regs, device, CMD_VERIFY);
 }
 
 // IBM/MS lock/unlock drive
@@ -438,7 +436,7 @@ disk_1346(struct bregs *regs, u8 device)
 static void
 disk_1347(struct bregs *regs, u8 device)
 {
-    extended_access(regs, device, 0);
+    extended_access(regs, device, CMD_SEEK);
 }
 
 // IBM/MS get drive parameters
@@ -455,18 +453,25 @@ disk_1348(struct bregs *regs, u8 device)
 
     // EDD 1.x
 
-    u8  type    = GET_GLOBAL(ATA.devices[device].type);
-    u16 npc     = GET_GLOBAL(ATA.devices[device].pchs.cylinders);
-    u16 nph     = GET_GLOBAL(ATA.devices[device].pchs.heads);
-    u16 npspt   = GET_GLOBAL(ATA.devices[device].pchs.spt);
-    u64 lba     = GET_GLOBAL(ATA.devices[device].sectors);
-    u16 blksize = GET_GLOBAL(ATA.devices[device].blksize);
+    u8  type    = GET_GLOBAL(Drives.drives[device].type);
+    u16 npc     = GET_GLOBAL(Drives.drives[device].pchs.cylinders);
+    u16 nph     = GET_GLOBAL(Drives.drives[device].pchs.heads);
+    u16 npspt   = GET_GLOBAL(Drives.drives[device].pchs.spt);
+    u64 lba     = GET_GLOBAL(Drives.drives[device].sectors);
+    u16 blksize = GET_GLOBAL(Drives.drives[device].blksize);
 
     dprintf(DEBUG_HDL_13, "disk_1348 size=%d t=%d chs=%d,%d,%d lba=%d bs=%d\n"
             , size, type, npc, nph, npspt, (u32)lba, blksize);
 
     SET_INT13DPT(regs, size, 26);
-    if (type == ATA_TYPE_ATA) {
+    if (type == DTYPE_ATAPI) {
+        // 0x74 = removable, media change, lockable, max values
+        SET_INT13DPT(regs, infos, 0x74);
+        SET_INT13DPT(regs, cylinders, 0xffffffff);
+        SET_INT13DPT(regs, heads, 0xffffffff);
+        SET_INT13DPT(regs, spt, 0xffffffff);
+        SET_INT13DPT(regs, sector_count, (u64)-1);
+    } else {
         if (lba > (u64)npspt*nph*0x3fff) {
             SET_INT13DPT(regs, infos, 0x00); // geometry is invalid
             SET_INT13DPT(regs, cylinders, 0x3fff);
@@ -477,18 +482,10 @@ disk_1348(struct bregs *regs, u8 device)
         SET_INT13DPT(regs, heads, (u32)nph);
         SET_INT13DPT(regs, spt, (u32)npspt);
         SET_INT13DPT(regs, sector_count, lba);
-    } else {
-        // ATAPI
-        // 0x74 = removable, media change, lockable, max values
-        SET_INT13DPT(regs, infos, 0x74);
-        SET_INT13DPT(regs, cylinders, 0xffffffff);
-        SET_INT13DPT(regs, heads, 0xffffffff);
-        SET_INT13DPT(regs, spt, 0xffffffff);
-        SET_INT13DPT(regs, sector_count, (u64)-1);
     }
     SET_INT13DPT(regs, blksize, blksize);
 
-    if (size < 30) {
+    if (size < 30 || (type != DTYPE_ATA && type != DTYPE_ATAPI)) {
         disk_ret(regs, DISK_RET_SUCCESS);
         return;
     }
@@ -503,20 +500,21 @@ disk_1348(struct bregs *regs, u8 device)
                  , offsetof(struct extended_bios_data_area_s, dpte));
 
     // Fill in dpte
-    u8 channel = device / 2;
-    u8 slave = device % 2;
-    u16 iobase1 = GET_GLOBAL(ATA.channels[channel].iobase1);
-    u16 iobase2 = GET_GLOBAL(ATA.channels[channel].iobase2);
-    u8 irq = GET_GLOBAL(ATA.channels[channel].irq);
+    u8 ataid = GET_GLOBAL(Drives.drives[device].cntl_id);
+    u8 channel = ataid / 2;
+    u8 slave = ataid % 2;
+    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
+    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
+    u8 irq = GET_GLOBAL(ATA_channels[channel].irq);
 
     u16 options = 0;
-    if (type == ATA_TYPE_ATA) {
-        u8 translation = GET_GLOBAL(ATA.devices[device].translation);
-        if (translation != ATA_TRANSLATION_NONE) {
+    if (type == DTYPE_ATA) {
+        u8 translation = GET_GLOBAL(Drives.drives[device].translation);
+        if (translation != TRANSLATION_NONE) {
             options |= 1<<3; // CHS translation
-            if (translation == ATA_TRANSLATION_LBA)
+            if (translation == TRANSLATION_LBA)
                 options |= 1<<9;
-            if (translation == ATA_TRANSLATION_RECHS)
+            if (translation == TRANSLATION_RECHS)
                 options |= 3<<9;
         }
     } else {
@@ -561,7 +559,7 @@ disk_1348(struct bregs *regs, u8 device)
     SET_INT13DPT(regs, host_bus[2], 'I');
     SET_INT13DPT(regs, host_bus[3], 0);
 
-    u32 bdf = GET_GLOBAL(ATA.channels[channel].pci_bdf);
+    u32 bdf = GET_GLOBAL(ATA_channels[channel].pci_bdf);
     u32 path = (pci_bdf_to_bus(bdf) | (pci_bdf_to_dev(bdf) << 8)
                 | (pci_bdf_to_fn(bdf) << 16));
     SET_INT13DPT(regs, iface_path, path);
@@ -682,25 +680,25 @@ disk_13(struct bregs *regs, u8 device)
  * Entry points
  ****************************************************************/
 
-static u8
+static int
 get_device(struct bregs *regs, u8 iscd, u8 drive)
 {
     // basic check : device has to be defined
-    if (drive >= CONFIG_MAX_ATA_DEVICES) {
+    if (drive >= ARRAY_SIZE(Drives.idmap[0])) {
         disk_ret(regs, DISK_RET_EPARAM);
-        return CONFIG_MAX_ATA_DEVICES;
+        return -1;
     }
 
     // Get the ata channel
-    u8 device = GET_GLOBAL(ATA.idmap[iscd][drive]);
+    u8 driveid = GET_GLOBAL(Drives.idmap[iscd][drive]);
 
     // basic check : device has to be valid
-    if (device >= CONFIG_MAX_ATA_DEVICES) {
+    if (driveid >= ARRAY_SIZE(Drives.drives)) {
         disk_ret(regs, DISK_RET_EPARAM);
-        return CONFIG_MAX_ATA_DEVICES;
+        return -1;
     }
 
-    return device;
+    return driveid;
 }
 
 static void
@@ -711,24 +709,24 @@ handle_legacy_disk(struct bregs *regs, u8 drive)
         return;
     }
 
-    if (! CONFIG_ATA) {
+    if (! CONFIG_DRIVES) {
         // XXX - old code had other disk access method.
         disk_ret(regs, DISK_RET_EPARAM);
         return;
     }
 
     if (drive >= 0xe0) {
-        u8 device = get_device(regs, 1, drive - 0xe0);
-        if (device >= CONFIG_MAX_ATA_DEVICES)
+        int driveid = get_device(regs, 1, drive - 0xe0);
+        if (driveid < 0)
             return;
-        cdrom_13(regs, device);
+        cdrom_13(regs, driveid);
         return;
     }
 
-    u8 device = get_device(regs, 0, drive - 0x80);
-    if (device >= CONFIG_MAX_ATA_DEVICES)
+    int driveid = get_device(regs, 0, drive - 0x80);
+    if (driveid < 0)
         return;
-    disk_13(regs, device);
+    disk_13(regs, driveid);
 }
 
 void VISIBLE16