Rename VAR16_32 to VAR16VISIBLE.
[seabios.git] / src / ata.c
index 49af87f830a050f51c0e009ffd8af2896700584a..98d114159fda800072da2b01e0f4ecb760157d51 100644 (file)
--- a/src/ata.c
+++ b/src/ata.c
@@ -23,7 +23,7 @@
 
 #define IDE_TIMEOUT 32000 //32 seconds max for IDE ops
 
-struct ata_channel_s ATA_channels[CONFIG_MAX_ATA_INTERFACES] VAR16_32;
+struct ata_channel_s ATA_channels[CONFIG_MAX_ATA_INTERFACES] VAR16VISIBLE;
 
 
 /****************************************************************
@@ -115,6 +115,9 @@ ata_reset(int driveid)
                 goto done;
             }
         }
+    } else {
+        // QEMU doesn't reset dh on reset, so set it explicitly.
+        outb(ATA_CB_DH_DEV0, iobase1 + ATA_CB_DH);
     }
 
     // On a user-reset request, wait for RDY if it is an ATA device.
@@ -137,7 +140,9 @@ isready(int driveid)
     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;
+    if ((status & (ATA_CB_STAT_BSY|ATA_CB_STAT_RDY)) == ATA_CB_STAT_RDY)
+        return DISK_RET_SUCCESS;
+    return DISK_RET_ENOTREADY;
 }
 
 static int
@@ -147,13 +152,18 @@ process_ata_misc_op(struct disk_op_s *op)
         return 0;
 
     switch (op->command) {
-    default:
-        return 0;
     case CMD_RESET:
         ata_reset(op->driveid);
-        return 0;
+        return DISK_RET_SUCCESS;
     case CMD_ISREADY:
         return isready(op->driveid);
+    case CMD_FORMAT:
+    case CMD_VERIFY:
+    case CMD_SEEK:
+        return DISK_RET_SUCCESS;
+    default:
+        op->count = 0;
+        return DISK_RET_EPARAM;
     }
 }
 
@@ -351,14 +361,20 @@ process_ata_op(struct disk_op_s *op)
     if (!CONFIG_ATA)
         return 0;
 
+    int ret;
     switch (op->command) {
     case CMD_READ:
-        return ata_cmd_data(op, 0, ATA_CMD_READ_SECTORS);
+        ret = ata_cmd_data(op, 0, ATA_CMD_READ_SECTORS);
+        break;
     case CMD_WRITE:
-        return ata_cmd_data(op, 1, ATA_CMD_WRITE_SECTORS);
+        ret = ata_cmd_data(op, 1, ATA_CMD_WRITE_SECTORS);
+        break;
     default:
         return process_ata_misc_op(op);
     }
+    if (ret)
+        return DISK_RET_EBADTRACK;
+    return DISK_RET_SUCCESS;
 }
 
 
@@ -436,12 +452,20 @@ cdrom_read(struct disk_op_s *op)
 int
 process_atapi_op(struct disk_op_s *op)
 {
+    int ret;
     switch (op->command) {
     case CMD_READ:
-        return cdrom_read(op);
+        ret = cdrom_read(op);
+        break;
+    case CMD_FORMAT:
+    case CMD_WRITE:
+        return DISK_RET_EWRITEPROTECT;
     default:
         return process_ata_misc_op(op);
     }
+    if (ret)
+        return DISK_RET_EBADTRACK;
+    return DISK_RET_SUCCESS;
 }
 
 // Send a simple atapi command to a drive.
@@ -623,7 +647,7 @@ ata_detect()
 {
     // Device detection
     u64 end = calc_future_tsc(IDE_TIMEOUT);
-    int ataid, last_reset_ataid=-1, driveid=0;
+    int ataid, last_reset_ataid=-1;
     for (ataid=0; ataid<CONFIG_MAX_ATA_INTERFACES*2; ataid++) {
         u8 channel = ataid / 2;
         u8 slave = ataid % 2;
@@ -656,6 +680,7 @@ ata_detect()
             continue;
 
         // Prepare new driveid.
+        u8 driveid = GET_GLOBAL(Drives.drivecount);
         if (driveid >= ARRAY_SIZE(Drives.drives))
             break;
         memset(&Drives.drives[driveid], 0, sizeof(Drives.drives[0]));
@@ -691,7 +716,7 @@ ata_detect()
                 // No ATA drive found
                 continue;
         }
-        driveid++;
+        SET_GLOBAL(Drives.drivecount, driveid+1);
 
         u16 resetresult = buffer[93];
         dprintf(6, "ata_detect resetresult=%04x\n", resetresult);