Hi,
According to my injected debugging message, the first time
"inb(scp-altioaddr)" was executed in ata_intr(), it returns 0xd0(busy):
/* if drive is busy it didn't interrupt */
if (inb(scp-altioaddr) ATA_S_BUSY)
return;
The booting message then said: "ata0-master: ata_comand: timeout
waiting for intr," and stopped to interact with my hard disk attached on
ata0-master anymore. However, if I forced an interrupt clear before busy
return, the timeout condition can be resolved all further disk I/O
operations went normally:
/* if drive is busy it didn't interrupt */
if (inb(scp-altioaddr) ATA_S_BUSY)
{
/* clear interrupt */
inb(scp-ioaddr + ATA_STATUS);
return;
}
Include the above hacks, there are two other temporary "fixes"
against ata-all.c, 1.50.2.14. All of them work in my 4.2-R box. The first
is to replace the status checking routine in ata_intr() with the old one
(in 1.50.2.7):
--- /sys/dev/ata/ata-all.c.old Fri Nov 24 11:19:59 2000
+++ /sys/dev/ata/ata-all.c Sat Nov 25 00:20:25 2000
@@ -1120,12 +1120,18 @@
}
DELAY(1);
+#if0
/* if drive is busy it didn't interrupt */
if (inb(scp-altioaddr) ATA_S_BUSY)
return;
/* clear interrupt and get status */
scp-status = inb(scp-ioaddr + ATA_STATUS);
+#else
+/* get status, if drive is busy it didn't interrupt so return */
+if ((scp-status = inb(scp-ioaddr + ATA_STATUS)) ATA_S_BUSY)
+ return;
+#endif
if (scp-status ATA_S_ERROR)
scp-error = inb(scp-ioaddr + ATA_ERROR);
@@ -1264,37 +1270,37 @@
/* wait for BUSY to go inactive */
for (timeout = 0; timeout 31; timeout++) {
if (status0 ATA_S_BUSY) {
-outb(scp-ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
-DELAY(10);
-status0 = inb(scp-ioaddr + ATA_STATUS);
-if (!(status0 ATA_S_BUSY)) {
-/* check for ATAPI signature while its still there */
+ outb(scp-ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
+ DELAY(10);
+ status0 = inb(scp-ioaddr + ATA_STATUS);
+ if (!(status0 ATA_S_BUSY)) {
+ /* check for ATAPI signature while its still there */
a = inb(scp-ioaddr + ATA_CYL_LSB);
b = inb(scp-ioaddr + ATA_CYL_MSB);
if (bootverbose)
ata_printf(scp, ATA_MASTER,
"ATAPI probe a=%02x b=%02x\n", a, b);
if (a == ATAPI_MAGIC_LSB b == ATAPI_MAGIC_MSB)
-scp-devices |= ATA_ATAPI_MASTER;
-}
-}
-if (status1 ATA_S_BUSY) {
-outb(scp-ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
-DELAY(10);
-status1 = inb(scp-ioaddr + ATA_STATUS);
-if (!(status1 ATA_S_BUSY)) {
-/* check for ATAPI signature while its still there */
+ scp-devices |= ATA_ATAPI_MASTER;
+ }
+ }
+ if (status1 ATA_S_BUSY) {
+ outb(scp-ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
+ DELAY(10);
+ status1 = inb(scp-ioaddr + ATA_STATUS);
+ if (!(status1 ATA_S_BUSY)) {
+ /* check for ATAPI signature while its still there */
a = inb(scp-ioaddr + ATA_CYL_LSB);
b = inb(scp-ioaddr + ATA_CYL_MSB);
if (bootverbose)
ata_printf(scp, ATA_SLAVE,
"ATAPI probe a=%02x b=%02x\n", a, b);
if (a == ATAPI_MAGIC_LSB b == ATAPI_MAGIC_MSB)
-scp-devices |= ATA_ATAPI_SLAVE;
-}
-}
+ scp-devices |= ATA_ATAPI_SLAVE;
+ }
+ }
if (*mask == 0x01) /* wait for master only */
- if (!(status0 ATA_S_BUSY))
+ if (!(status0 ATA_S_BUSY))
break;
if (*mask == 0x02) /* wait for slave only */
if (!(status1 ATA_S_BUSY))
@@ -1319,27 +1325,27 @@
if (*mask 0x01 ostat0 != 0x00 !(scp-devices ATA_ATAPI_MASTER)) {
outb(scp-ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
-DELAY(10);
+ DELAY(10);
outb(scp-ioaddr + ATA_ERROR, 0x58);
outb(scp-ioaddr + ATA_CYL_LSB, 0xa5);
a = inb(scp-ioaddr + ATA_ERROR);
b = inb(scp-ioaddr + ATA_CYL_LSB);
if (bootverbose)
ata_printf(scp, ATA_MASTER, "ATA probe a=%02x b=%02x\n", a, b);
-if (a != 0x58 b == 0xa5)
-scp-devices |= ATA_ATA_MASTER;
+ if (a != 0x58 b == 0xa5)
+ scp-devices |= ATA_ATA_MASTER;
}
if (*mask 0x02 ostat1 != 0x00 !(scp-devices ATA_ATAPI_SLAVE)) {
outb(scp-ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE);
-DELAY(10);
+ DELAY(10);
outb(scp-ioaddr + ATA_ERROR, 0x58);
outb(scp-ioaddr + ATA_CYL_LSB, 0xa5);
a = inb(scp-ioaddr + ATA_ERROR);