Subject: Re: kern/22869: Slave IDE drive not detected
To: Manuel Bouyer <bouyer@antioche.lip6.fr>
From: Charles M. Hannum <abuse@spamalicious.com>
List: tech-kern
Date: 09/22/2003 21:08:50
Well, I tried the following change, and it helped a bit. It prevents
trying to further probe the ghost on the laptop's primary bus. It
also avoids waiting for BSY to clear on the bogus drive 1 with my CF
cards. However, the real IDENTIFY command never manages to complete
on the CF cards now. I'll look into this some more later.
Index: wdc.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/wdc.c,v
retrieving revision 1.125
diff -u -r1.125 wdc.c
--- wdc.c 2003/09/19 21:36:02 1.125
+++ wdc.c 2003/09/22 21:07:43
@@ -205,14 +205,14 @@
chp->wdc->select(chp,0);
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
WDSD_IBM);
- delay(10);
+ delay(10); /* 400ns delay */
st0 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
if (chp->wdc && (chp->wdc->cap & WDC_CAPABILITY_SELECT))
chp->wdc->select(chp,1);
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
WDSD_IBM | 0x10);
- delay(10);
+ delay(10); /* 400ns delay */
st1 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
WDCDEBUG_PRINT(("%s:%d: before reset, st0=0x%x, st1=0x%x\n",
@@ -231,14 +231,14 @@
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
WDSD_IBM);
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo,
- 0x01);
+ 0x02);
if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_cyl_lo) != 0x01)
+ wd_cyl_lo) != 0x02)
ret_value &= ~0x01;
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo,
- 0x02);
+ 0x01);
if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_cyl_lo) != 0x02)
+ wd_cyl_lo) != 0x01)
ret_value &= ~0x01;
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sector,
0x01);
@@ -250,6 +250,9 @@
if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
wd_sector) != 0x02)
ret_value &= ~0x01;
+ if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
+ wd_cyl_lo) != 0x01)
+ ret_value &= ~0x01;
}
/* Register writability test, drive 1. */
@@ -259,14 +262,14 @@
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
WDSD_IBM | 0x10);
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo,
- 0x01);
+ 0x02);
if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_cyl_lo) != 0x01)
+ wd_cyl_lo) != 0x02)
ret_value &= ~0x02;
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo,
- 0x02);
+ 0x01);
if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_cyl_lo) != 0x02)
+ wd_cyl_lo) != 0x01)
ret_value &= ~0x02;
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sector,
0x01);
@@ -278,28 +281,9 @@
if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
wd_sector) != 0x02)
ret_value &= ~0x02;
- }
-
- /* Register ghost test. */
- if (ret_value == 0x03) {
- if (chp->wdc && (chp->wdc->cap & WDC_CAPABILITY_SELECT))
- chp->wdc->select(chp,1);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | 0x10);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sector, 0x01);
- if (chp->wdc && (chp->wdc->cap & WDC_CAPABILITY_SELECT))
- chp->wdc->select(chp,0);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sector, 0x02);
- if (chp->wdc && (chp->wdc->cap & WDC_CAPABILITY_SELECT))
- chp->wdc->select(chp,1);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | 0x10);
- if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_sector) == 0x02) {
- printf("ghost detected\n");
- ret_value = 0x01;
- }
+ if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
+ wd_cyl_lo) != 0x01)
+ ret_value &= ~0x02;
}
if (ret_value == 0)
@@ -312,16 +296,15 @@
/* assert SRST, wait for reset to complete */
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
WDSD_IBM);
- delay(10);
+ delay(10); /* 400ns delay */
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
WDCTL_RST | WDCTL_IDS);
- DELAY(1000);
- bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
- WDCTL_IDS);
delay(1000);
+ bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_IDS);
+ delay(1000);
(void) bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
- delay(10);
+ delay(10); /* 400ns delay */
ret_value = __wdcwait_reset(chp, ret_value);
WDCDEBUG_PRINT(("%s:%d: after reset, ret_value=0x%d\n",
@@ -345,7 +328,7 @@
chp->wdc->select(chp,drive);
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
WDSD_IBM | (drive << 4));
- delay(10);
+ delay(10); /* 400ns delay */
/* Save registers contents */
sc = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_seccnt);
sn = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_sector);
@@ -362,13 +345,28 @@
*/
if (cl == 0x14 && ch == 0xeb) {
chp->ch_drive[drive].drive_flags |= DRIVE_ATAPI;
- } else {
+ continue;
+ }
+ bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_command,
+ WDCC_IDENTIFY);
+ delay(10); /* 400ns delay */
+ if (bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status) & (WDCS_BSY | WDCS_DRQ)) {
chp->ch_drive[drive].drive_flags |= DRIVE_ATA;
if (chp->wdc == NULL ||
(chp->wdc->cap & WDC_CAPABILITY_PREATA) != 0)
chp->ch_drive[drive].drive_flags |= DRIVE_OLD;
}
}
+
+ bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
+ WDCTL_RST | WDCTL_IDS);
+ delay(1000);
+ bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_IDS);
+ delay(1000);
+ (void) bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
+ bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
+ delay(10);
+
return (ret_value);
}
@@ -464,7 +462,7 @@
chp->wdc->select(chp,i);
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
WDSD_IBM | (i << 4));
- delay(10);
+ delay(10); /* 400ns delay */
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh,
wd_error, 0x58);
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh,
@@ -479,11 +477,6 @@
chp->channel, i), DEBUG_PROBE);
chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
}
- if (chp->wdc->cap & WDC_CAPABILITY_SELECT)
- chp->wdc->select(chp,i);
- bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
- WDSD_IBM | (i << 4));
- delay(100);
if (wait_for_ready(chp, 10000) != 0) {
WDCDEBUG_PRINT(("%s:%d:%d: not ready\n",
chp->wdc->sc_dev.dv_xname,
@@ -493,6 +486,7 @@
}
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh,
wd_command, WDCC_RECAL);
+ delay(10); /* 400ns delay */
if (wait_for_ready(chp, 10000) != 0) {
WDCDEBUG_PRINT(("%s:%d:%d: WDCC_RECAL failed\n",
chp->wdc->sc_dev.dv_xname,
@@ -859,7 +853,7 @@
WDCTL_RST | WDCTL_IDS);
delay(1000);
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
- WDCTL_IDS);
+ WDCTL_RST | WDCTL_4BIT);
delay(1000);
(void) bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
@@ -886,7 +880,7 @@
int drv_mask;
{
int timeout;
- u_int8_t st0, st1;
+ u_int8_t st0, er0, st1, er1;
#ifdef WDCDEBUG
u_int8_t sc0, sn0, cl0, ch0;
u_int8_t sc1, sn1, cl1, ch1;
@@ -899,6 +893,7 @@
WDSD_IBM); /* master */
delay(10);
st0 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
+ er0 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
#ifdef WDCDEBUG
sc0 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_seccnt);
sn0 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_sector);
@@ -911,6 +906,7 @@
WDSD_IBM | 0x10); /* slave */
delay(10);
st1 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
+ er1 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
#ifdef WDCDEBUG
sc1 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_seccnt);
sn1 = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_sector);
@@ -944,6 +940,10 @@
if (st1 & WDCS_BSY)
drv_mask &= ~0x02;
end:
+ if (er0 != 0x01 && er0 != 0x81)
+ drv_mask &= ~0x01;
+ if (er1 != 0x01)
+ drv_mask &= ~0x02;
WDCDEBUG_PRINT(("%s:%d:0: after reset, sc=0x%x sn=0x%x "
"cl=0x%x ch=0x%x\n",
chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe",
@@ -953,9 +953,9 @@
chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe",
chp->channel, sc1, sn1, cl1, ch1), DEBUG_PROBE);
- WDCDEBUG_PRINT(("%s:%d: wdcwait_reset() end, st0=0x%x, st1=0x%x\n",
+ WDCDEBUG_PRINT(("%s:%d: wdcwait_reset() end, st0=0x%x er0=0x%x, st1=0x%x er1=0x%x\n",
chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe", chp->channel,
- st0, st1), DEBUG_PROBE);
+ st0, er0, st1, er1), DEBUG_PROBE);
return drv_mask;
}