4.2-RELEASE ata0-master probe failed(solved)

2000-11-26 Thread Tai-hwa Liang

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);

Re: 4.2-RELEASE ata0-master probe failed(solved)

2000-11-26 Thread Soren Schmidt

It seems Tai-hwa Liang wrote:
 Hi,
 
   According to my injected debugging message, the first time
 "inb(scp-altioaddr)" was executed in ata_intr(), it returns 0xd0(busy):

Uhm 0xd0 is SERVICE and READY and BUSY, which doesn't make sense...

 /* 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;
 }

This effectively disables the whole purpose of using the "alternative
status" register. Using the alt reg does not clear the interrupt
and we do not want to if this drive didn't interrupt. So this hack
breaks the driver on systems with more than one controller on
an interrupt (which is quiet common nowadays).
Your problem might be that the altioaddr is not correct, so we get
bogus status from it...

   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):

They are hard to read, they are mostly just whitespace pollution, the only
real changes I see is the above, which wont work unfortunately...

-Søren


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-stable" in the body of the message