[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Test this IDE probe path
- To: misc_(_at_)_openbsd_(_dot_)_org, tech_(_at_)_openbsd_(_dot_)_org
- Subject: Test this IDE probe path
- From: Constantine Sapuntzakis <csapuntz_(_at_)_stanford_(_dot_)_edu>
- Date: Tue, 24 Oct 2000 23:58:34 -0700 (PDT)
- Cc: gluk_(_at_)_ptci_(_dot_)_ru
This should get rid of phantom WDC problems. Please tell me if it
gets rid of real drives too.
Thanks to gluk_(_at_)_ptci_(_dot_)_ru
-Costa
Index: wdc.c
===================================================================
RCS file: /cvs/src/sys/dev/ic/wdc.c,v
retrieving revision 1.20
diff -u -r1.20 wdc.c
--- wdc.c 2000/07/20 19:15:23 1.20
+++ wdc.c 2000/10/25 06:46:39
@@ -345,16 +345,17 @@
}
-/* Test to see controller with at last one attached drive is there.
+/* Test to see controller with at least one attached drive is there.
* Returns a bit for each possible drive found (0x01 for drive 0,
* 0x02 for drive 1).
* Logic:
- * - If a status register is at 0xff, assume there is no drive here
- * (ISA has pull-up resistors). If no drive at all -> return.
+ * - If a status register is at 0x7f, assume there is no drive here
+ * (ISA has pull-up resistors, but bit 7 sometimes has pull-down resistor?).
+ * If no drive at all -> return.
* - reset the controller, wait for it to complete (may take up to 31s !).
* If timeout -> return.
- * - test ATA/ATAPI signatures. If at last one drive found -> return.
- * - try an ATA command on the master.
+ * - test ATA/ATAPI signatures. Wait for ready if drive isn't ATAPI.
+ * - return drive mask.
*/
int
@@ -364,6 +365,7 @@
u_int8_t st0, st1, sc, sn, cl, ch;
u_int8_t ret_value = 0x03;
u_int8_t drive;
+ int i;
if (!chp->_vtbl)
chp->_vtbl = &wdc_default_vtbl;
@@ -390,24 +392,19 @@
chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe",
chp->channel, st0, st1), DEBUG_PROBE);
- if (st0 == 0xff)
+ if ((st0 & 0x7f) == 0x7f)
ret_value &= ~0x01;
- if (st1 == 0xff)
+ if ((st1 & 0x7f) == 0x7f)
ret_value &= ~0x02;
if (ret_value == 0)
return 0;
}
/* assert SRST, wait for reset to complete */
- CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM);
+ CHP_WRITE_REG(chp,wdr_ctlr, WDCTL_RST | WDCTL_4BIT);
delay(10);
- CHP_WRITE_REG(chp,wdr_ctlr, WDCTL_RST | WDCTL_IDS);
- DELAY(1000);
- CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_IDS);
- delay(1000);
- (void) CHP_READ_REG(chp, wdr_error);
CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_4BIT);
- delay(10);
+ delay(2000);
ret_value = __wdcwait_reset(chp, ret_value);
WDCDEBUG_PRINT(("%s:%d: after reset, ret_value=0x%d\n",
@@ -420,9 +417,10 @@
/*
* Test presence of drives. First test register signatures looking for
- * ATAPI devices. If it's not an ATAPI and reset said there may be
- * something here assume it's ATA or OLD. Ghost will be killed later in
- * attach routine.
+ * ATA/ATAPI devices. If drive isn't ATAPI, wait for it's readiness.
+ * Timeout -> no drive, if any, drive is ATA or OLD. Distinction
+ * between ATA and OLD will be done later in attach routine
+ * by issuing an IDENTIFY command.
*/
for (drive = 0; drive < 2; drive++) {
if ((ret_value & (0x01 << drive)) == 0)
@@ -436,8 +434,8 @@
cl = CHP_READ_REG(chp, wdr_cyl_lo);
ch = CHP_READ_REG(chp, wdr_cyl_hi);
- WDCDEBUG_PRINT(("%s:%d:%d: after reset, st=0x%x, sc=0x%x sn=0x%x "
- "cl=0x%x ch=0x%x\n",
+ WDCDEBUG_PRINT(("%s:%d:%d: after reset, st=0x%x, sc=0x%x"
+ " sn=0x%x cl=0x%x ch=0x%x\n",
chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe",
chp->channel, drive, st0, sc, sn, cl, ch), DEBUG_PROBE);
/*
@@ -447,11 +445,36 @@
*/
if (cl == 0x14 && ch == 0xeb) {
chp->ch_drive[drive].drive_flags |= DRIVE_ATAPI;
- } else {
+ } else if (sc == 0x01 && sn == 0x01 &&
+ cl == 0x0 && ch == 0x0) {
+
+ for(i = 0; i < 1000; i++) {
+ st0 = CHP_READ_REG(chp, wdr_status);
+ if ((st0 & WDCS_BSY) == 0 && (st0 & WDCS_DRDY) != 0) {
+ WDCDEBUG_PRINT(("%s:%d:%d: waiting for ready %d msec\n",
+ chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe",
+ chp->channel, drive, i), DEBUG_PROBE);
+ break;
+ } else {
+ delay(1000); /* 1 millisecond */
+ }
+ }
+
+ if((st0 & WDCS_BSY) != 0 || (st0 & WDCS_DRDY) == 0) {
+ ret_value &= ~(0x01 << drive);
+ continue;
+ }
+
+ /*
+ * here is ATA or OLD drive, we are
+ * distinct it in wdcattach()
+ */
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;
+ } else {
+ ret_value &= ~(0x01 << drive);
}
}
@@ -537,59 +560,26 @@
(WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32)) ==
WDC_CAPABILITY_DATA32)
chp->ch_drive[i].drive_flags |= DRIVE_CAP32;
+
if ((chp->ch_drive[i].drive_flags & DRIVE) == 0)
continue;
if (i == 1 && ((chp->ch_drive[0].drive_flags & DRIVE) == 0))
chp->ch_flags |= WDCF_ONESLAVE;
-
- /* Issue a IDENTIFY command, to try to detect slave ghost */
+ /*
+ * Issue an IDENTIFY command in order to distinct ATA from OLD.
+ * This also kill ATAPI ghost.
+ */
if (ata_get_params(&chp->ch_drive[i], at_poll, ¶ms) ==
CMD_OK) {
/* If IDENTIFY succeded, this is not an OLD ctrl */
- chp->ch_drive[0].drive_flags &= ~DRIVE_OLD;
- chp->ch_drive[1].drive_flags &= ~DRIVE_OLD;
+ chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
} else {
chp->ch_drive[i].drive_flags &=
~(DRIVE_ATA | DRIVE_ATAPI);
WDCDEBUG_PRINT(("%s:%d:%d: IDENTIFY failed\n",
chp->wdc->sc_dev.dv_xname,
chp->channel, i), DEBUG_PROBE);
- if ((chp->ch_drive[i].drive_flags & DRIVE_OLD) == 0)
- continue;
- /*
- * Pre-ATA drive ?
- * Test registers writability (Error register not
- * writable, but cyllo is), then try an ATA command.
- */
- CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (i << 4));
- delay(10);
- CHP_WRITE_REG(chp, wdr_features, 0x58);
- CHP_WRITE_REG(chp, wdr_cyl_lo, 0xa5);
- if ((CHP_READ_REG(chp, wdr_error) == 0x58) ||
- (CHP_READ_REG(chp, wdr_cyl_lo) != 0xa5)) {
- WDCDEBUG_PRINT(("%s:%d:%d: register "
- "writability failed\n",
- chp->wdc->sc_dev.dv_xname,
- chp->channel, i), DEBUG_PROBE);
- chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
- }
- CHP_WRITE_REG(chp, wdr_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,
- chp->channel, i), DEBUG_PROBE);
- chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
- continue;
- }
- CHP_WRITE_REG(chp, wdr_command, WDCC_RECAL);
- if (wait_for_ready(chp, 10000) != 0) {
- WDCDEBUG_PRINT(("%s:%d:%d: WDCC_RECAL failed\n",
- chp->wdc->sc_dev.dv_xname,
- chp->channel, i), DEBUG_PROBE);
- chp->ch_drive[i].drive_flags &= ~DRIVE_OLD;
- }
}
}
ctrl_flags = chp->wdc->sc_dev.dv_cfdata->cf_flags;
@@ -824,13 +814,10 @@
if (!chp->_vtbl)
chp->_vtbl = &wdc_default_vtbl;
- CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM); /* master */
- CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_RST | WDCTL_IDS);
- delay(1000);
- CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_IDS);
- delay(2000);
- (void) CHP_READ_REG(chp,wdr_error);
+ CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_RST | WDCTL_4BIT);
+ delay(10);
CHP_WRITE_REG(chp, wdr_ctlr, WDCTL_4BIT);
+ delay(2000);
drv_mask1 = (chp->ch_drive[0].drive_flags & DRIVE) ? 0x01:0x00;
drv_mask1 |= (chp->ch_drive[1].drive_flags & DRIVE) ? 0x02:0x00;
@@ -856,9 +843,6 @@
int timeout;
u_int8_t st0, st1;
- /* Wait 50ms for drive firmware to settle */
- delay(50000);
-
/* wait for BSY to deassert */
for (timeout = 0; timeout < WDCNDELAY_RST;timeout++) {
CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM); /* master */
@@ -888,15 +872,16 @@
}
delay(WDCDELAY);
}
- /* Reset timed out. Maybe it's because drv_mask was not rigth */
+ /* Reset timed out. Maybe it's because drv_mask was not right */
if (st0 & WDCS_BSY)
drv_mask &= ~0x01;
if (st1 & WDCS_BSY)
drv_mask &= ~0x02;
end:
- WDCDEBUG_PRINT(("%s:%d: wdcwait_reset() end, st0=0x%x, st1=0x%x\n",
+ WDCDEBUG_PRINT(("%s:%d: wdcwait_reset() end, st0=0x%x, st1=0x%x, "
+ "reset time=%d msec\n",
chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe", chp->channel,
- st0, st1), DEBUG_PROBE);
+ st0, st1, timeout*WDCDELAY/1000), DEBUG_PROBE);
return drv_mask;
}
Visit your host, monkey.org