Densely populate ATA.devices list.
authorKevin O'Connor <kevin@koconnor.net>
Wed, 12 Aug 2009 00:43:38 +0000 (20:43 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Wed, 12 Aug 2009 00:43:38 +0000 (20:43 -0400)
Populate ATA.devices in order of drives found; the array index no
    longer correlates with the ATA.channels list.
Add cntl_id to device struct for finding the channel info.

src/ata.c
src/disk.c
src/disk.h

index 20d360ab5e560607395c75ffa62205046f1b178d..a833c1d46aa632cddb90880f06fa0700bb1d19aa 100644 (file)
--- a/src/ata.c
+++ b/src/ata.c
@@ -79,11 +79,12 @@ ndelay_await_not_bsy(u16 iobase1)
 }
 
 // Reset a drive
-void
+static void
 ata_reset(int driveid)
 {
-    u8 channel = driveid / 2;
-    u8 slave = driveid % 2;
+    u8 ataid = GET_GLOBAL(ATA.devices[driveid].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);
 
@@ -132,7 +133,8 @@ static int
 isready(int driveid)
 {
     // Read the status from controller
-    u8 channel = driveid / 2;
+    u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
+    u8 channel = ataid / 2;
     u16 iobase1 = GET_GLOBAL(ATA.channels[channel].iobase1);
     u8 status = inb(iobase1 + ATA_CB_STAT);
     return (status & ( ATA_CB_STAT_BSY | ATA_CB_STAT_RDY )) == ATA_CB_STAT_RDY;
@@ -176,8 +178,9 @@ struct ata_pio_command {
 static int
 send_cmd(int driveid, struct ata_pio_command *cmd)
 {
-    u8 channel = driveid / 2;
-    u8 slave = driveid % 2;
+    u8 ataid = GET_GLOBAL(ATA.devices[driveid].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);
 
@@ -243,7 +246,8 @@ ata_transfer(struct disk_op_s *op, int iswrite, int blocksize)
     dprintf(16, "ata_transfer id=%d write=%d count=%d bs=%d buf=%p\n"
             , op->driveid, iswrite, op->count, blocksize, op->buf_fl);
 
-    u8 channel  = op->driveid / 2;
+    u8 ataid = GET_GLOBAL(ATA.devices[op->driveid].cntl_id);
+    u8 channel = ataid / 2;
     u16 iobase1 = GET_GLOBAL(ATA.channels[channel].iobase1);
     u16 iobase2 = GET_GLOBAL(ATA.channels[channel].iobase2);
     int count = op->count;
@@ -360,7 +364,8 @@ process_ata_op(struct disk_op_s *op)
 static int
 send_atapi_cmd(int driveid, u8 *cmdbuf, u8 cmdlen, u16 blocksize)
 {
-    u8 channel = driveid / 2;
+    u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
+    u8 channel = ataid / 2;
     u16 iobase1 = GET_GLOBAL(ATA.channels[channel].iobase1);
     u16 iobase2 = GET_GLOBAL(ATA.channels[channel].iobase2);
 
@@ -461,9 +466,10 @@ get_translation(int driveid)
 {
     if (! CONFIG_COREBOOT) {
         // Emulators pass in the translation info via nvram.
-        u8 channel = driveid / 2;
+        u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
+        u8 channel = ataid / 2;
         u8 translation = inb_cmos(CMOS_BIOS_DISKTRANSFLAG + channel/2);
-        translation >>= 2 * (driveid % 4);
+        translation >>= 2 * (ataid % 4);
         translation &= 0x03;
         return translation;
     }
@@ -486,8 +492,9 @@ setup_translation(int driveid)
     u8 translation = get_translation(driveid);
     SET_GLOBAL(ATA.devices[driveid].translation, translation);
 
-    u8 channel = driveid / 2;
-    u8 slave = driveid % 2;
+    u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
+    u8 channel = ataid / 2;
+    u8 slave = ataid % 2;
     u16 heads = GET_GLOBAL(ATA.devices[driveid].pchs.heads);
     u16 cylinders = GET_GLOBAL(ATA.devices[driveid].pchs.cylinders);
     u16 spt = GET_GLOBAL(ATA.devices[driveid].pchs.spt);
@@ -615,8 +622,9 @@ init_drive_atapi(int driveid, u16 *buffer)
     u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05;
 
     // Report drive info to user.
-    u8 channel = driveid / 2;
-    u8 slave = driveid % 2;
+    u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
+    u8 channel = ataid / 2;
+    u8 slave = ataid % 2;
     printf("ata%d-%d: %s ATAPI-%d %s\n", channel, slave
            , ATA.devices[driveid].model, ATA.devices[driveid].version
            , (iscd ? "CD-Rom/DVD-Rom" : "Device"));
@@ -666,8 +674,9 @@ init_drive_ata(int driveid, u16 *buffer)
     setup_translation(driveid);
 
     // Report drive info to user.
-    u8 channel = driveid / 2;
-    u8 slave = driveid % 2;
+    u8 ataid = GET_GLOBAL(ATA.devices[driveid].cntl_id);
+    u8 channel = ataid / 2;
+    u8 slave = ataid % 2;
     char *model = ATA.devices[driveid].model;
     printf("ata%d-%d: %s ATA-%d Hard-Disk ", channel, slave, model
            , ATA.devices[driveid].version);
@@ -711,10 +720,10 @@ ata_detect()
 {
     // Device detection
     u64 end = calc_future_tsc(IDE_TIMEOUT);
-    int driveid, last_reset_driveid=-1;
-    for(driveid=0; driveid<CONFIG_MAX_ATA_DEVICES; driveid++) {
-        u8 channel = driveid / 2;
-        u8 slave = driveid % 2;
+    int ataid, last_reset_ataid=-1, driveid=0;
+    for (ataid=0; ataid<CONFIG_MAX_ATA_INTERFACES*2; ataid++) {
+        u8 channel = ataid / 2;
+        u8 slave = ataid % 2;
 
         u16 iobase1 = GET_GLOBAL(ATA.channels[channel].iobase1);
         if (!iobase1)
@@ -738,17 +747,23 @@ ata_detect()
         outb(0xaa, iobase1+ATA_CB_SN);
         u8 sc = inb(iobase1+ATA_CB_SC);
         u8 sn = inb(iobase1+ATA_CB_SN);
-        dprintf(6, "ata_detect drive=%d sc=%x sn=%x dh=%x\n"
-                , driveid, sc, sn, dh);
+        dprintf(6, "ata_detect ataid=%d sc=%x sn=%x dh=%x\n"
+                , ataid, sc, sn, dh);
         if (sc != 0x55 || sn != 0xaa || dh != newdh)
             continue;
 
+        // Prepare new driveid.
+        if (driveid >= ARRAY_SIZE(ATA.devices))
+            break;
+        memset(&ATA.devices[driveid], 0, sizeof(ATA.devices[0]));
+        ATA.devices[driveid].cntl_id = ataid;
+
         // reset the channel
-        if (slave && driveid == last_reset_driveid + 1) {
+        if (slave && ataid == last_reset_ataid + 1) {
             // The drive was just reset - no need to reset it again.
         } else {
             ata_reset(driveid);
-            last_reset_driveid = driveid;
+            last_reset_ataid = ataid;
         }
 
         // check for ATAPI
@@ -773,6 +788,7 @@ ata_detect()
                 // No ATA drive found
                 continue;
         }
+        driveid++;
 
         u16 resetresult = buffer[93];
         dprintf(6, "ata_detect resetresult=%04x\n", resetresult);
@@ -780,7 +796,7 @@ ata_detect()
             // resetresult looks valid and device 0 is responding to
             // device 1 requests - device 1 must not be present - skip
             // detection.
-            driveid++;
+            ataid++;
     }
 
     printf("\n");
index 4ace85c56f75f1f49bb35179e7df0168f8d6f429..609beaad0378e2261fc54f1335c0d00ec05278af 100644 (file)
@@ -464,7 +464,14 @@ disk_1348(struct bregs *regs, u8 device)
             , size, type, npc, nph, npspt, (u32)lba, blksize);
 
     SET_INT13DPT(regs, size, 26);
-    if (type == DTYPE_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);
@@ -475,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;
     }
@@ -501,8 +500,9 @@ 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;
+    u8 ataid = GET_GLOBAL(ATA.devices[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);
index 260affaec4221f794d4884c456417a0821051f58..915c53ff06eef16535aaba1e503b8f725c163167 100644 (file)
@@ -175,10 +175,11 @@ struct ata_channel_s {
 };
 
 struct ata_device_s {
-    u8  type;         // Detected type of ata (ata/atapi/none/unknown)
+    u8  type;         // Detected type of ata (ata/atapi/none)
     u8  removable;    // Removable device flag
     u16 blksize;      // block size
     u8  version;      // ATA/ATAPI version
+    int cntl_id;
 
     char model[41];