Densely populate ATA.devices list.
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.
diff --git a/src/ata.c b/src/ata.c
index 20d360a..a833c1d 100644
--- a/src/ata.c
+++ b/src/ata.c
@@ -79,11 +79,12 @@
}
// 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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
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 @@
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 @@
{
// 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 @@
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 @@
// No ATA drive found
continue;
}
+ driveid++;
u16 resetresult = buffer[93];
dprintf(6, "ata_detect resetresult=%04x\n", resetresult);
@@ -780,7 +796,7 @@
// resetresult looks valid and device 0 is responding to
// device 1 requests - device 1 must not be present - skip
// detection.
- driveid++;
+ ataid++;
}
printf("\n");
diff --git a/src/disk.c b/src/disk.c
index 4ace85c..609beaa 100644
--- a/src/disk.c
+++ b/src/disk.c
@@ -464,7 +464,14 @@
, 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 @@
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 @@
, 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);
diff --git a/src/disk.h b/src/disk.h
index 260affa..915c53f 100644
--- a/src/disk.h
+++ b/src/disk.h
@@ -175,10 +175,11 @@
};
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];