Refactor ata code.
authorKevin O'Connor <kevin@koconnor.net>
Sat, 29 Mar 2008 16:53:57 +0000 (12:53 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Sat, 29 Mar 2008 16:53:57 +0000 (12:53 -0400)
Have await_ide return status code (so callers don't need to reread status).
Introduce pause_await_ide for cases where we need to wait an ata cycle.
Implement 400ns wait according to ata specs.
Consistently used 'driveid' instead of 'biosid', 'devid', 'device'.
Unify cdrom and hd transfer code into single function - ata_transfer.
Use less inlining.
Remove unused ebda variable 'trsfbytes'.

src/ata.c
src/ata.h
src/biosvar.h

index eba9972a5057c2efc641ee8de837cf8a171884a4..f7f4a57c332dc2e27c84bae70bac4aa00da9b58e 100644 (file)
--- a/src/ata.c
+++ b/src/ata.c
 #define NOT_BSY_NOT_DRQ 4
 #define NOT_BSY_RDY 5
 
+#define IDE_SECTOR_SIZE 512
+#define CDROM_SECTOR_SIZE 2048
+
 #define IDE_TIMEOUT 32000u //32 seconds max for IDE ops
 
 #define DEBUGF1(fmt, args...) bprintf(0, fmt , ##args)
 #define DEBUGF(fmt, args...)
 
-// XXX - lots of redundancy in this file.
 
+/****************************************************************
+ * Helper functions
+ ****************************************************************/
+
+// Wait for the specified ide state
 static int
 await_ide(u8 when_done, u16 base, u16 timeout)
 {
     u32 time=0, last=0;
-    // for the times you're supposed to throw one away
-    u16 status = inb(base + ATA_CB_STAT);
     for (;;) {
-        status = inb(base+ATA_CB_STAT);
+        u8 status = inb(base+ATA_CB_STAT);
         time++;
         u8 result;
         if (when_done == BSY)
@@ -49,7 +54,7 @@ await_ide(u8 when_done, u16 base, u16 timeout)
             result = 0;
 
         if (result)
-            return 0;
+            return status;
         // mod 2048 each 16 ms
         if (time>>16 != last) {
             last = time >>16;
@@ -63,29 +68,42 @@ await_ide(u8 when_done, u16 base, u16 timeout)
                    , when_done, time>>11, timeout);
             return -1;
         }
-        if ((timeout == 0) || ((time>>11) > timeout))
+        if (timeout == 0 || (time>>11) > timeout)
             break;
     }
     BX_INFO("IDE time out\n");
     return -1;
 }
 
+// Wait for ide state - pauses for one ata cycle first.
+static inline int
+pause_await_ide(u8 when_done, u16 iobase1, u16 iobase2, u16 timeout)
+{
+    // Wait one PIO transfer cycle.
+    inb(iobase2 + ATA_CB_ASTAT);
 
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : software reset
-// ---------------------------------------------------------------------------
-// ATA-3
-// 8.2.1 Software reset - Device 0
+    return await_ide(when_done, iobase1, timeout);
+}
+
+// Delay for x nanoseconds
+static void
+nsleep(u32 delay)
+{
+    // XXX - how to implement ndelay?
+    while (delay--)
+        nop();
+}
 
+// Reset a drive
 void
-ata_reset(u16 device)
+ata_reset(int driveid)
 {
     u16 iobase1, iobase2;
     u8  channel, slave, sn, sc;
     u8  type;
 
-    channel = device / 2;
-    slave = device % 2;
+    channel = driveid / 2;
+    slave = driveid % 2;
 
     iobase1 = GET_EBDA(ata.channels[channel].iobase1);
     iobase2 = GET_EBDA(ata.channels[channel].iobase2);
@@ -101,7 +119,7 @@ ata_reset(u16 device)
     // 8.2.1 (f) -- clear SRST
     outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC);
 
-    type=GET_EBDA(ata.devices[device].type);
+    type=GET_EBDA(ata.devices[driveid].type);
     if (type != ATA_TYPE_NONE) {
 
         // 8.2.1 (g) -- check for sc==sn==0x01
@@ -125,24 +143,7 @@ ata_reset(u16 device)
     outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
 }
 
-
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : execute a data command
-// ---------------------------------------------------------------------------
-      // returns
-      // 0 : no error
-      // 1 : BUSY bit set
-      // 2 : read error
-      // 3 : expected DRQ=1
-      // 4 : no sectors left to read/verify
-      // 5 : more sectors to read/verify
-      // 6 : no sectors left to write
-      // 7 : more sectors to write
-
 struct ata_pio_command {
-    void *far_buffer;
-    u8 biosid;
-
     u8 feature;
     u8 sector_count;
     u8 lba_low;
@@ -157,15 +158,15 @@ struct ata_pio_command {
     u8 lba_high2;
 };
 
+// Send an ata command to the drive.
 static int
-send_cmd(struct ata_pio_command *cmd)
+send_cmd(int driveid, struct ata_pio_command *cmd)
 {
-    u16 biosid = cmd->biosid;
-    u8 channel = biosid / 2;
+    u8 channel = driveid / 2;
     u16 iobase1 = GET_EBDA(ata.channels[channel].iobase1);
     u16 iobase2 = GET_EBDA(ata.channels[channel].iobase2);
 
-    u8 status = inb(iobase1 + ATA_CB_STAT);
+    int status = inb(iobase1 + ATA_CB_STAT);
     if (status & ATA_CB_STAT_BSY)
         return 1;
 
@@ -185,9 +186,12 @@ send_cmd(struct ata_pio_command *cmd)
     outb(cmd->device, iobase1 + ATA_CB_DH);
     outb(cmd->command, iobase1 + ATA_CB_CMD);
 
-    await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
+    nsleep(400);
+
+    status = await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
+    if (status < 0)
+        return status;
 
-    status = inb(iobase1 + ATA_CB_STAT);
     if (status & ATA_CB_STAT_ERR) {
         DEBUGF("send_cmd : read error\n");
         return 2;
@@ -201,56 +205,82 @@ send_cmd(struct ata_pio_command *cmd)
     return 0;
 }
 
-static int
-ata_transfer(struct ata_pio_command *cmd)
+// Read and discard x number of bytes from an io channel.
+static void
+insx_discard(int mode, int iobase1, int bytes)
 {
-    DEBUGF("ata_transfer id=%d cmd=%d lba=%d count=%d buf=%p\n"
-           , cmd->biosid, cmd->command
-           , (cmd->lba_high << 16) | (cmd->lba_mid << 8) | cmd->lba_low
-           , cmd->sector_count, cmd->far_buffer);
+    int count, i;
+    if (mode == ATA_MODE_PIO32) {
+        count = bytes / 4;
+        for (i=0; i<count; i++)
+            inl(iobase1);
+    } else {
+        count = bytes / 2;
+        for (i=0; i<count; i++)
+            inw(iobase1);
+    }
+}
 
-    // Reset count of transferred data
-    SET_EBDA(ata.trsfsectors,0);
-    SET_EBDA(ata.trsfbytes,0L);
+// Transfer 'count' blocks (of 'blocksize' bytes) to/from drive
+// 'driveid'.  If 'skipfirst' or 'skiplast' is set then the first
+// and/or last block may be partially transferred.  This function is
+// inlined because all the callers use different forms and because the
+// large number of parameters would consume a lot of stack space.
+static inline int
+ata_transfer(int driveid, int iswrite, int count, int blocksize
+             , int skipfirst, int skiplast, void *far_buffer)
+{
+    DEBUGF("ata_transfer id=%d write=%d count=%d bs=%d"
+           " skipf=%d skipl=%d buf=%p\n"
+           , driveid, iswrite, count, blocksize
+           , skipfirst, skiplast, far_buffer);
 
-    int ret = send_cmd(cmd);
-    if (ret)
-        return ret;
+    // Reset count of transferred data
+    SET_EBDA(ata.trsfsectors, 0);
 
-    u16 biosid = cmd->biosid;
-    u8 channel  = biosid / 2;
+    u8 channel  = driveid / 2;
     u16 iobase1 = GET_EBDA(ata.channels[channel].iobase1);
     u16 iobase2 = GET_EBDA(ata.channels[channel].iobase2);
-    u8 mode     = GET_EBDA(ata.devices[biosid].mode);
-    int iswrite = (cmd->command & ~0x40) == ATA_CMD_WRITE_SECTORS;
-    u8 current = 0;
-    u16 count = cmd->sector_count;
-    u8 status;
-    void *far_buffer = cmd->far_buffer;
+    u8 mode     = GET_EBDA(ata.devices[driveid].mode);
+    int current = 0;
+    int status;
     for (;;) {
+        int bsize = blocksize;
+        if (skipfirst && current == 0) {
+            insx_discard(mode, iobase1, skipfirst);
+            bsize -= skipfirst;
+        }
+        if (skiplast && current == count-1)
+            bsize -= skiplast;
+
         if (iswrite) {
             // Write data to controller
-            DEBUGF("Write sector id=%d dest=%p\n", biosid, far_buffer);
+            DEBUGF("Write sector id=%d dest=%p\n", driveid, far_buffer);
             if (mode == ATA_MODE_PIO32)
-                outsl_far(iobase1, far_buffer, 512 / 4);
+                outsl_far(iobase1, far_buffer, bsize / 4);
             else
-                outsw_far(iobase1, far_buffer, 512 / 2);
+                outsw_far(iobase1, far_buffer, bsize / 2);
         } else {
             // Read data from controller
-            DEBUGF("Read sector id=%d dest=%p\n", biosid, far_buffer);
+            DEBUGF("Read sector id=%d dest=%p\n", driveid, far_buffer);
             if (mode == ATA_MODE_PIO32)
-                insl_far(iobase1, far_buffer, 512 / 4);
+                insl_far(iobase1, far_buffer, bsize / 4);
             else
-                insw_far(iobase1, far_buffer, 512 / 2);
-            await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
+                insw_far(iobase1, far_buffer, bsize / 2);
         }
-        far_buffer += 512;
+        far_buffer += bsize;
+
+        if (skiplast && current == count-1)
+            insx_discard(mode, iobase1, skiplast);
+
+        status = pause_await_ide(NOT_BSY, iobase1, iobase2, IDE_TIMEOUT);
+        if (status < 0)
+            // Error
+            return status;
 
         current++;
-        SET_EBDA(ata.trsfsectors,current);
-        count--;
-        status = inb(iobase1 + ATA_CB_STAT);
-        if (count == 0)
+        SET_EBDA(ata.trsfsectors, current);
+        if (current == count)
             break;
         status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ
                    | ATA_CB_STAT_ERR);
@@ -276,14 +306,19 @@ ata_transfer(struct ata_pio_command *cmd)
     return 0;
 }
 
-inline int
-ata_cmd_data(u16 biosid, u16 command, u32 lba, u16 count, void *far_buffer)
+
+/****************************************************************
+ * ATA hard drive functions
+ ****************************************************************/
+
+// Read/write count blocks from a harddrive.
+int
+ata_cmd_data(int driveid, u16 command, u32 lba, u16 count, void *far_buffer)
 {
-    u8 slave   = biosid % 2;
+    u8 slave   = driveid % 2;
 
     struct ata_pio_command cmd;
-    cmd.far_buffer = far_buffer;
-    cmd.biosid = biosid;
+    memset(&cmd, 0, sizeof(cmd));
 
     if (count >= (1<<8) || lba + count >= (1<<28)) {
         cmd.sector_count2 = count >> 8;
@@ -303,183 +338,60 @@ ata_cmd_data(u16 biosid, u16 command, u32 lba, u16 count, void *far_buffer)
     cmd.device = ((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0)
                   | ((lba >> 24) & 0xf) | ATA_CB_DH_LBA);
     cmd.command = command;
-    return ata_transfer(&cmd);
-}
 
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : execute a packet command
-// ---------------------------------------------------------------------------
-      // returns
-      // 0 : no error
-      // 1 : error in parameters
-      // 2 : BUSY bit set
-      // 3 : error
-      // 4 : not ready
-static inline int
-__ata_cmd_packet(u16 biosid, u8 *cmdbuf, u8 cmdlen
-                 , u16 header, u32 length, void *far_buffer)
-{
-    DEBUGF("ata_cmd_packet d=%d cmdlen=%d h=%d l=%d buf=%p\n"
-           , biosid, cmdlen, header, length, far_buffer);
+    int ret = send_cmd(driveid, &cmd);
+    if (ret)
+        return ret;
+
+    int iswrite = command == ATA_CMD_WRITE_SECTORS;
+    return ata_transfer(driveid, iswrite, count, IDE_SECTOR_SIZE
+                        , 0, 0, far_buffer);
+}
 
-    u8 channel = biosid / 2;
-    u8 slave = biosid % 2;
 
-    // The header length must be even
-    if (header & 1) {
-        DEBUGF("ata_cmd_packet : header must be even (%04x)\n", header);
-        return 1;
-    }
+/****************************************************************
+ * ATAPI functions
+ ****************************************************************/
 
+// Low-level atapi command transmit function.
+static int
+send_atapi_cmd(int driveid, u8 *cmdbuf, u8 cmdlen, u16 blocksize)
+{
+    u8 channel = driveid / 2;
+    u8 slave = driveid % 2;
     u16 iobase1 = GET_EBDA(ata.channels[channel].iobase1);
     u16 iobase2 = GET_EBDA(ata.channels[channel].iobase2);
-    u8 mode     = GET_EBDA(ata.devices[biosid].mode);
 
     struct ata_pio_command cmd;
     cmd.sector_count = 0;
     cmd.feature = 0;
     cmd.lba_low = 0;
-    cmd.lba_mid = 0xf0;
-    cmd.lba_high = 0xff;
+    cmd.lba_mid = blocksize;
+    cmd.lba_high = blocksize >> 8;
     cmd.device = slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0;
     cmd.command = ATA_CMD_PACKET;
 
-    cmd.biosid = biosid;
-    int ret = send_cmd(&cmd);
+    int ret = send_cmd(driveid, &cmd);
     if (ret)
         return ret;
 
-    // Reset count of transferred data
-    SET_EBDA(ata.trsfsectors,0);
-    SET_EBDA(ata.trsfbytes,0L);
-
     // Send command to device
     outsw_far(iobase1, MAKE_FARPTR(GET_SEG(SS), (u32)cmdbuf), cmdlen / 2);
 
-    u8 status;
-    u16 loops = 0;
-    for (;;) {
-        if (loops == 0) {//first time through
-            status = inb(iobase2 + ATA_CB_ASTAT);
-            await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT);
-        } else
-            await_ide(NOT_BSY, iobase1, IDE_TIMEOUT);
-        loops++;
-
-        status = inb(iobase1 + ATA_CB_STAT);
-        inb(iobase1 + ATA_CB_SC);
-
-        // Check if command completed
-        if(((inb(iobase1 + ATA_CB_SC)&0x7)==0x3) &&
-           ((status & (ATA_CB_STAT_RDY | ATA_CB_STAT_ERR)) == ATA_CB_STAT_RDY))
-            break;
-
-        if (status & ATA_CB_STAT_ERR) {
-            DEBUGF("ata_cmd_packet : error (status %02x)\n", status);
-            return 3;
-        }
-
-        // Get the byte count
-        u16 lcount =  (((u16)(inb(iobase1 + ATA_CB_CH))<<8)
-                       + inb(iobase1 + ATA_CB_CL));
-
-        // adjust to read what we want
-        u16 lbefore, lafter;
-        if (header > lcount) {
-            lbefore=lcount;
-            header-=lcount;
-            lcount=0;
-        } else {
-            lbefore=header;
-            header=0;
-            lcount-=lbefore;
-        }
-
-        if (lcount > length) {
-            lafter=lcount-length;
-            lcount=length;
-            length=0;
-        } else {
-            lafter=0;
-            length-=lcount;
-        }
-
-        // Save byte count
-        u16 count = lcount;
-
-        DEBUGF("Trying to read %04x bytes (%04x %04x %04x) to %p\n"
-               , lbefore+lcount+lafter, lbefore, lcount, lafter, far_buffer);
-
-        // If counts not dividable by 4, use 16bits mode
-        u8 lmode = mode;
-        if (lbefore & 0x03) lmode=ATA_MODE_PIO16;
-        if (lcount  & 0x03) lmode=ATA_MODE_PIO16;
-        if (lafter  & 0x03) lmode=ATA_MODE_PIO16;
-
-        // adds an extra byte if count are odd. before is always even
-        if (lcount & 0x01) {
-            lcount+=1;
-            if ((lafter > 0) && (lafter & 0x01)) {
-                lafter-=1;
-            }
-        }
-
-        if (lmode == ATA_MODE_PIO32) {
-            lcount>>=2; lbefore>>=2; lafter>>=2;
-        } else {
-            lcount>>=1; lbefore>>=1; lafter>>=1;
-        }
-
-        int i;
-        for (i=0; i<lbefore; i++)
-            if (lmode == ATA_MODE_PIO32)
-                inl(iobase1);
-            else
-                inw(iobase1);
-
-        if (lmode == ATA_MODE_PIO32)
-            insl_far(iobase1, far_buffer, lcount);
-        else
-            insw_far(iobase1, far_buffer, lcount);
-
-        for (i=0; i<lafter; i++)
-            if (lmode == ATA_MODE_PIO32)
-                inl(iobase1);
-            else
-                inw(iobase1);
-
-        // Compute new buffer address
-        far_buffer += count;
-
-        // Save transferred bytes count
-        SET_EBDA(ata.trsfsectors, loops);
-    }
-
-    // Final check, device must be ready
-    if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF
-                    | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) )
-         != ATA_CB_STAT_RDY ) {
-        DEBUGF("ata_cmd_packet : not ready (status %02x)\n"
-               , (unsigned) status);
-        return 4;
-    }
+    int status = pause_await_ide(NOT_BSY_DRQ, iobase1, iobase2, IDE_TIMEOUT);
+    if (status < 0)
+        return status;
 
-    // Enable interrupts
-    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
     return 0;
 }
 
-int
-ata_cmd_packet(u16 biosid, u8 *cmdbuf, u8 cmdlen
-               , u32 length, void *far_buffer)
+// Low-level cdrom read atapi command transmit function.
+static inline int
+send_cdrom_cmd(int driveid, u32 lba, u16 count)
 {
-    return __ata_cmd_packet(biosid, cmdbuf, cmdlen, 0, length, far_buffer);
-}
+    u8 atacmd[12];
+    memset(atacmd, 0, sizeof(atacmd));
 
-static void
-build_cdrom_cmd(u8 *atacmd, u32 lba, u16 count)
-{
-    memset(atacmd, 0, 12);
     atacmd[0]=0x28;                     // READ command
     atacmd[7]=(count & 0xff00) >> 8;    // Sectors
     atacmd[8]=(count & 0x00ff);         // Sectors
@@ -487,47 +399,71 @@ build_cdrom_cmd(u8 *atacmd, u32 lba, u16 count)
     atacmd[3]=(lba & 0x00ff0000) >> 16;
     atacmd[4]=(lba & 0x0000ff00) >> 8;
     atacmd[5]=(lba & 0x000000ff);
+
+    return send_atapi_cmd(driveid, atacmd, sizeof(atacmd), CDROM_SECTOR_SIZE);
 }
 
 // Read sectors from the cdrom.
 int
-cdrom_read(u16 biosid, u32 lba, u32 count, void *far_buffer)
+cdrom_read(int driveid, u32 lba, u32 count, void *far_buffer)
 {
-    u8 atacmd[12];
-    build_cdrom_cmd(atacmd, lba, count);
-    return ata_cmd_packet(biosid, atacmd, sizeof(atacmd)
-                          , count*2048, far_buffer);
+    int ret = send_cdrom_cmd(driveid, lba, count);
+    if (ret)
+        return ret;
+
+    return ata_transfer(driveid, 0, count, CDROM_SECTOR_SIZE, 0, 0, far_buffer);
 }
 
 // Pretend the cdrom has 512 byte sectors (instead of 2048) and read
 // sectors.
 int
-cdrom_read_512(u16 biosid, u32 vlba, u32 count, void *far_buffer)
+cdrom_read_512(int driveid, u32 vlba, u32 vcount, void *far_buffer)
 {
-    u32 slba = vlba / 4;
-    u16 before = vlba % 4;
-    u32 elba = (vlba + count - 1) / 4;
-
-    u8 atacmd[12];
-    build_cdrom_cmd(atacmd, slba, elba - slba + 1);
+    u32 velba = vlba + vcount - 1;
+    u32 lba = vlba / 4;
+    u32 elba = velba / 4;
+    int count = elba - lba + 1;
+    int before = vlba % 4;
+    int after = 3 - (velba % 4);
+
+    DEBUGF("cdrom_read_512: id=%d vlba=%d vcount=%d buf=%p lba=%d elba=%d"
+           " count=%d before=%d after=%d\n"
+           , driveid, vlba, vcount, far_buffer, lba, elba
+           , count, before, after);
+
+    int ret = send_cdrom_cmd(driveid, lba, count);
+    if (ret)
+        return ret;
 
-    int status = __ata_cmd_packet(biosid, atacmd, sizeof(atacmd)
-                                  , before*512, count*512, far_buffer);
-    if (status) {
+    ret = ata_transfer(driveid, 0, count, CDROM_SECTOR_SIZE
+                       , before*512, after*512, far_buffer);
+    if (ret) {
         SET_EBDA(ata.trsfsectors, 0);
-        return status;
+        return ret;
     }
-    SET_EBDA(ata.trsfsectors, count);
+    SET_EBDA(ata.trsfsectors, vcount);
     return 0;
 }
 
+// Send a simple atapi command to a drive.
+int
+ata_cmd_packet(int driveid, u8 *cmdbuf, u8 cmdlen
+               , u32 length, void *far_buffer)
+{
+    int ret = send_atapi_cmd(driveid, cmdbuf, cmdlen, length);
+    if (ret)
+        return ret;
+
+    return ata_transfer(driveid, 0, 1, length, 0, 0, far_buffer);
+}
+
 
-// ---------------------------------------------------------------------------
-// ATA/ATAPI driver : device detection
-// ---------------------------------------------------------------------------
+/****************************************************************
+ * ATA detect and init
+ ****************************************************************/
 
 static void
-report_model(u8 devid, u8 *buffer)
+report_model(int driveid, u8 *buffer)
 {
     u8 model[41];
 
@@ -546,8 +482,8 @@ report_model(u8 devid, u8 *buffer)
         model[i] = 0x00;
     }
 
-    u8 channel = devid / 2;
-    u8 slave = devid % 2;
+    u8 channel = driveid / 2;
+    u8 slave = driveid % 2;
     // XXX - model on stack not %cs
     printf("ata%d %s: %s", channel, slave ? " slave" : "master", model);
 }
@@ -564,18 +500,18 @@ get_ata_version(u8 *buffer)
 }
 
 static void
-init_drive_atapi(u8 devid)
+init_drive_atapi(int driveid)
 {
-    SET_EBDA(ata.devices[devid].type,ATA_TYPE_ATAPI);
+    SET_EBDA(ata.devices[driveid].type,ATA_TYPE_ATAPI);
 
     // Temporary values to do the transfer
-    SET_EBDA(ata.devices[devid].device,ATA_DEVICE_CDROM);
-    SET_EBDA(ata.devices[devid].mode, ATA_MODE_PIO16);
+    SET_EBDA(ata.devices[driveid].device,ATA_DEVICE_CDROM);
+    SET_EBDA(ata.devices[driveid].mode, ATA_MODE_PIO16);
 
     // Now we send a IDENTIFY command to ATAPI device
     u8 buffer[0x0200];
     memset(buffer, 0, sizeof(buffer));
-    u16 ret = ata_cmd_data(devid, ATA_CMD_IDENTIFY_DEVICE_PACKET
+    u16 ret = ata_cmd_data(driveid, ATA_CMD_IDENTIFY_DEVICE_PACKET
                            , 1, 1
                            , MAKE_FARPTR(GET_SEG(SS), (u32)buffer));
     if (ret != 0)
@@ -584,39 +520,39 @@ init_drive_atapi(u8 devid)
     u8 type      = buffer[1] & 0x1f;
     u8 removable = (buffer[0] & 0x80) ? 1 : 0;
     u8 mode      = buffer[96] ? ATA_MODE_PIO32 : ATA_MODE_PIO16;
-    u16 blksize  = 2048;
+    u16 blksize  = CDROM_SECTOR_SIZE;
 
-    SET_EBDA(ata.devices[devid].device, type);
-    SET_EBDA(ata.devices[devid].removable, removable);
-    SET_EBDA(ata.devices[devid].mode, mode);
-    SET_EBDA(ata.devices[devid].blksize, blksize);
+    SET_EBDA(ata.devices[driveid].device, type);
+    SET_EBDA(ata.devices[driveid].removable, removable);
+    SET_EBDA(ata.devices[driveid].mode, mode);
+    SET_EBDA(ata.devices[driveid].blksize, blksize);
 
     // fill cdidmap
     u8 cdcount = GET_EBDA(ata.cdcount);
-    SET_EBDA(ata.idmap[1][cdcount], devid);
+    SET_EBDA(ata.idmap[1][cdcount], driveid);
     SET_EBDA(ata.cdcount, ++cdcount);
 
-    report_model(devid, buffer);
+    report_model(driveid, buffer);
     u8 version = get_ata_version(buffer);
-    if (GET_EBDA(ata.devices[devid].device)==ATA_DEVICE_CDROM)
+    if (GET_EBDA(ata.devices[driveid].device)==ATA_DEVICE_CDROM)
         printf(" ATAPI-%d CD-Rom/DVD-Rom\n", version);
     else
         printf(" ATAPI-%d Device\n", version);
 }
 
 static void
-init_drive_ata(u8 devid)
+init_drive_ata(int driveid)
 {
-    SET_EBDA(ata.devices[devid].type,ATA_TYPE_ATA);
+    SET_EBDA(ata.devices[driveid].type,ATA_TYPE_ATA);
 
     // Temporary values to do the transfer
-    SET_EBDA(ata.devices[devid].device, ATA_DEVICE_HD);
-    SET_EBDA(ata.devices[devid].mode, ATA_MODE_PIO16);
+    SET_EBDA(ata.devices[driveid].device, ATA_DEVICE_HD);
+    SET_EBDA(ata.devices[driveid].mode, ATA_MODE_PIO16);
 
     // Now we send a IDENTIFY command to ATA device
     u8 buffer[0x0200];
     memset(buffer, 0, sizeof(buffer));
-    u16 ret = ata_cmd_data(devid, ATA_CMD_IDENTIFY_DEVICE
+    u16 ret = ata_cmd_data(driveid, ATA_CMD_IDENTIFY_DEVICE
                            , 1, 1
                            , MAKE_FARPTR(GET_SEG(SS), (u32)buffer));
     if (ret)
@@ -632,24 +568,24 @@ init_drive_ata(u8 devid)
 
     u32 sectors   = *(u32*)&buffer[60*2]; // word 60 and word 61
 
-    SET_EBDA(ata.devices[devid].device,ATA_DEVICE_HD);
-    SET_EBDA(ata.devices[devid].removable, removable);
-    SET_EBDA(ata.devices[devid].mode, mode);
-    SET_EBDA(ata.devices[devid].blksize, blksize);
-    SET_EBDA(ata.devices[devid].pchs.heads, heads);
-    SET_EBDA(ata.devices[devid].pchs.cylinders, cylinders);
-    SET_EBDA(ata.devices[devid].pchs.spt, spt);
-    SET_EBDA(ata.devices[devid].sectors, sectors);
-
-    u8 channel = devid / 2;
-    u8 slave = devid % 2;
+    SET_EBDA(ata.devices[driveid].device,ATA_DEVICE_HD);
+    SET_EBDA(ata.devices[driveid].removable, removable);
+    SET_EBDA(ata.devices[driveid].mode, mode);
+    SET_EBDA(ata.devices[driveid].blksize, blksize);
+    SET_EBDA(ata.devices[driveid].pchs.heads, heads);
+    SET_EBDA(ata.devices[driveid].pchs.cylinders, cylinders);
+    SET_EBDA(ata.devices[driveid].pchs.spt, spt);
+    SET_EBDA(ata.devices[driveid].sectors, sectors);
+
+    u8 channel = driveid / 2;
+    u8 slave = driveid % 2;
     u8 translation = inb_cmos(CMOS_BIOS_DISKTRANSFLAG + channel/2);
     u8 shift;
-    for (shift=devid%4; shift>0; shift--)
+    for (shift=driveid%4; shift>0; shift--)
         translation >>= 2;
     translation &= 0x03;
 
-    SET_EBDA(ata.devices[devid].translation, translation);
+    SET_EBDA(ata.devices[driveid].translation, translation);
 
     BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation="
             , channel, slave, cylinders, heads, spt);
@@ -702,19 +638,19 @@ init_drive_ata(u8 devid)
         cylinders = 1024;
     BX_INFO(" LCHS=%d/%d/%d\n", cylinders, heads, spt);
 
-    SET_EBDA(ata.devices[devid].lchs.heads, heads);
-    SET_EBDA(ata.devices[devid].lchs.cylinders, cylinders);
-    SET_EBDA(ata.devices[devid].lchs.spt, spt);
+    SET_EBDA(ata.devices[driveid].lchs.heads, heads);
+    SET_EBDA(ata.devices[driveid].lchs.cylinders, cylinders);
+    SET_EBDA(ata.devices[driveid].lchs.spt, spt);
 
     // fill hdidmap
     u8 hdcount = GET_EBDA(ata.hdcount);
-    SET_EBDA(ata.idmap[0][hdcount], devid);
+    SET_EBDA(ata.idmap[0][hdcount], driveid);
     SET_EBDA(ata.hdcount, ++hdcount);
 
-    u32 sizeinmb = GET_EBDA(ata.devices[devid].sectors);
+    u32 sizeinmb = GET_EBDA(ata.devices[driveid].sectors);
     sizeinmb >>= 11;
 
-    report_model(devid, buffer);
+    report_model(driveid, buffer);
     u8 version = get_ata_version(buffer);
     if (sizeinmb < (1 << 16))
         printf(" ATA-%d Hard-Disk (%u MBytes)\n", version, sizeinmb);
@@ -723,12 +659,12 @@ init_drive_ata(u8 devid)
 }
 
 static void
-init_drive_unknown(u8 devid)
+init_drive_unknown(int driveid)
 {
-    SET_EBDA(ata.devices[devid].type,ATA_TYPE_UNKNOWN);
+    SET_EBDA(ata.devices[driveid].type,ATA_TYPE_UNKNOWN);
 
-    u8 channel = devid / 2;
-    u8 slave = devid % 2;
+    u8 channel = driveid / 2;
+    u8 slave = driveid % 2;
     printf("ata%d %s: Unknown device\n", channel, slave ? " slave" : "master");
 }
 
@@ -764,10 +700,10 @@ ata_detect()
 #endif
 
     // Device detection
-    u8 devid;
-    for(devid=0; devid<CONFIG_MAX_ATA_DEVICES; devid++) {
-        u8 channel = devid / 2;
-        u8 slave = devid % 2;
+    int driveid;
+    for(driveid=0; driveid<CONFIG_MAX_ATA_DEVICES; driveid++) {
+        u8 channel = driveid / 2;
+        u8 slave = driveid % 2;
 
         u16 iobase1 = GET_EBDA(ata.channels[channel].iobase1);
         u16 iobase2 = GET_EBDA(ata.channels[channel].iobase2);
@@ -792,14 +728,14 @@ ata_detect()
             continue;
 
         // reset the channel
-        ata_reset(devid);
+        ata_reset(driveid);
 
         // check for ATA or ATAPI
         outb(slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0, iobase1+ATA_CB_DH);
         sc = inb(iobase1+ATA_CB_SC);
         sn = inb(iobase1+ATA_CB_SN);
         if (sc!=0x01 || sn!=0x01) {
-            init_drive_unknown(devid);
+            init_drive_unknown(driveid);
             continue;
         }
         u8 cl = inb(iobase1+ATA_CB_CL);
@@ -807,14 +743,14 @@ ata_detect()
         u8 st = inb(iobase1+ATA_CB_STAT);
 
         if (cl==0x14 && ch==0xeb)
-            init_drive_atapi(devid);
+            init_drive_atapi(driveid);
         else if (cl==0x00 && ch==0x00 && st!=0x00)
-            init_drive_ata(devid);
+            init_drive_ata(driveid);
         else if (cl==0xff && ch==0xff)
             // None
             continue;
         else
-            init_drive_unknown(devid);
+            init_drive_unknown(driveid);
     }
 
     // Store the device count
index 5d430a00563097b42d6af013e2090fb5420e367d..54a2434fd86f36f1bb2a49baf75bee4fdf6e8786 100644 (file)
--- a/src/ata.h
+++ b/src/ata.h
 #include "atabits.h" // ATA_CB_DH_DEV1
 
 // Function definitions
-void ata_reset(u16 device);
-int ata_cmd_data(u16 biosid, u16 command, u32 lba, u16 count, void *far_buffer);
-int ata_cmd_packet(u16 device, u8 *cmdbuf, u8 cmdlen
+void ata_reset(int driveid);
+int ata_cmd_data(int driveid, u16 command, u32 lba, u16 count, void *far_buffer);
+int ata_cmd_packet(int driveid, u8 *cmdbuf, u8 cmdlen
                    , u32 length, void *far_buffer);
-int cdrom_read(u16 device, u32 lba, u32 count, void *far_buffer);
-int cdrom_read_512(u16 device, u32 lba, u32 count, void *far_buffer);
+int cdrom_read(int driveid, u32 lba, u32 count, void *far_buffer);
+int cdrom_read_512(int driveid, u32 lba, u32 count, void *far_buffer);
 void ata_detect();
 
 #endif /* __ATA_H */
index 36794c384452bbfec5f0ba3a15e8b03f63401167..6cf59804271b43866628d8ce10d11974d48aebd5 100644 (file)
@@ -194,7 +194,6 @@ struct ata_s {
 
     // Count of transferred sectors and bytes
     u16 trsfsectors;
-    u32 trsfbytes;
 } PACKED;
 
 // ElTorito Device Emulation data