Subject: Re: kern/25659: drive not recognized because of delays
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Brian Buhrow <buhrow@lothlorien.nfbcal.org>
List: netbsd-bugs
Date: 04/21/2005 22:09:01
The following reply was made to PR kern/25659; it has been noted by GNATS.
From: buhrow@lothlorien.nfbcal.org (Brian Buhrow)
To: gnats-bugs@netbsd.org
Cc: buhrow@lothlorien.nfbcal.org
Subject: Re: kern/25659: drive not recognized because of delays
Date: Thu, 21 Apr 2005 15:08:21 -0700
Hello. I'm finding that this problem plagues IDE drives attached to
standard IDE controllers as well as the problem Steven outlines above.
Below is a patch to wdc.c which addresses the issues I'm seeing with a
number of drives attached to Intel IDE controllers driven by the piixide(4)
driver.
In general, I think wdc.c is a bit too trigger happy, and given the
increasing speeds of processors, slowing it down a bit will lead to fewer
failures to recognize attached drives.
The following patch is tested and works on production machines. I
hope this issue can be addressed before NetBSD-3 comes out.
In the mean time, I hope someone finds this useful
-Brian
P.S. This is patched against the netBSD-2-0 branch of the wdc.c file.
Index: wdc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/wdc.c,v
retrieving revision 1.172.2.7
diff -u -r1.172.2.7 wdc.c
--- wdc.c 17 Sep 2004 04:04:57 -0000 1.172.2.7
+++ wdc.c 21 Apr 2005 20:56:30 -0000
@@ -206,13 +206,13 @@
}
/* for ATA/OLD drives, wait for DRDY, 3s timeout */
- for (i = 0; i < mstohz(3000); i++) {
+ for (i = 0; i < mstohz(9000); i++) {
if (chp->ch_drive[0].drive_flags & (DRIVE_ATA|DRIVE_OLD)) {
if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
wdc->select(chp,0);
bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
0, WDSD_IBM);
- delay(10); /* 400ns delay */
+ delay(40); /* 400ns delay */
st0 = bus_space_read_1(chp->cmd_iot,
chp->cmd_iohs[wd_status], 0);
}
@@ -222,7 +222,7 @@
wdc->select(chp,1);
bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
0, WDSD_IBM | 0x10);
- delay(10); /* 400ns delay */
+ delay(40); /* 400ns delay */
st1 = bus_space_read_1(chp->cmd_iot,
chp->cmd_iohs[wd_status], 0);
}
@@ -246,7 +246,7 @@
chp->ch_channel, st0, st1), DEBUG_PROBE);
/* Wait a bit, some devices are weird just after a reset. */
- delay(5000);
+ delay(9000);
for (i = 0; i < 2; i++) {
/* XXX This should be done by other code. */
@@ -503,7 +503,7 @@
bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
WDSD_IBM);
- delay(10); /* 400ns delay */
+ delay(40); /* 400ns delay */
st0 = bus_space_read_1(chp->cmd_iot,
chp->cmd_iohs[wd_status], 0);
@@ -512,10 +512,11 @@
bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
WDSD_IBM | 0x10);
- delay(10); /* 400ns delay */
+ delay(40); /* 400ns delay */
st1 = bus_space_read_1(chp->cmd_iot,
chp->cmd_iohs[wd_status], 0);
+ delay(1000000);
WDCDEBUG_PRINT(("%s:%d: before reset, st0=0x%x, st1=0x%x\n",
wdc != NULL ? wdc->sc_dev.dv_xname : "wdcprobe",
chp->ch_channel, st0, st1), DEBUG_PROBE);
@@ -700,17 +701,17 @@
if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
wdc->select(chp,0);
bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0, WDSD_IBM);
- delay(10); /* 400ns delay */
+ delay(40); /* 400ns delay */
/* assert SRST, wait for reset to complete */
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
WDCTL_RST | WDCTL_IDS | WDCTL_4BIT);
- DELAY(1000);
+ DELAY(4000);
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
WDCTL_IDS | WDCTL_4BIT);
- DELAY(2000);
+ DELAY(8000);
(void) bus_space_read_1(chp->cmd_iot, chp->cmd_iohs[wd_error], 0);
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
- delay(10); /* 400ns delay */
+ delay(40); /* 400ns delay */
/* ACK interrupt in case there is one pending left (Promise ATA100) */
if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_IRQACK))
wdc->irqack(chp);
@@ -738,7 +739,7 @@
wdc->select(chp,drive);
bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
WDSD_IBM | (drive << 4));
- delay(10); /* 400ns delay */
+ delay(80); /* 400ns delay */
/* Save registers contents */
sc = bus_space_read_1(chp->cmd_iot,
chp->cmd_iohs[wd_seccnt], 0);
@@ -1030,14 +1031,14 @@
s = splbio();
/* master */
bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0, WDSD_IBM);
- delay(10); /* 400ns delay */
+ delay(40); /* 400ns delay */
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
WDCTL_RST | WDCTL_IDS | WDCTL_4BIT);
delay(2000);
(void) bus_space_read_1(chp->cmd_iot, chp->cmd_iohs[wd_error], 0);
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
WDCTL_4BIT | WDCTL_IDS);
- delay(10); /* 400ns delay */
+ delay(40); /* 400ns delay */
if (poll != RESET_SLEEP) {
if (wdc->cap & WDC_CAPABILITY_IRQACK)
wdc->irqack(chp);
@@ -1710,7 +1711,7 @@
* Polled command. Wait for drive ready or drq. Done in intr().
* Wait for at last 400ns for status bit to be valid.
*/
- delay(10); /* 400ns delay */
+ delay(40); /* 400ns delay */
__wdccommand_intr(chp, xfer, 0);
}
@@ -1862,7 +1863,7 @@
/* enable interrupts */
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
WDCTL_4BIT);
- delay(10); /* some drives need a little delay here */
+ delay(40); /* some drives need a little delay here */
}
wdc_free_xfer(chp, xfer);
if (wdc_c->flags & AT_WAIT)