summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ata/ata.c19
-rw-r--r--sys/dev/ic/wdc.c115
2 files changed, 51 insertions, 83 deletions
diff --git a/sys/dev/ata/ata.c b/sys/dev/ata/ata.c
index 8975a858823..a4fe7dd82a4 100644
--- a/sys/dev/ata/ata.c
+++ b/sys/dev/ata/ata.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ata.c,v 1.11 2001/07/09 20:10:40 csapuntz Exp $ */
+/* $OpenBSD: ata.c,v 1.12 2001/07/12 01:45:42 csapuntz Exp $ */
/* $NetBSD: ata.c,v 1.9 1999/04/15 09:41:09 bouyer Exp $ */
/*
* Copyright (c) 1998 Manuel Bouyer. All rights reserved.
@@ -70,18 +70,16 @@ ata_get_params(drvp, flags, prms)
int i;
u_int16_t *p;
- int try = 0;
WDCDEBUG_PRINT(("ata_get_parms\n"), DEBUG_FUNCS);
- again:
bzero(tb, sizeof(tb));
bzero(prms, sizeof(struct ataparams));
bzero(&wdc_c, sizeof(struct wdc_command));
if (drvp->drive_flags & DRIVE_ATA) {
wdc_c.r_command = WDCC_IDENTIFY;
- wdc_c.r_st_bmask = (try == 0) ? WDCS_DRDY : 0;
+ wdc_c.r_st_bmask = WDCS_DRDY;
wdc_c.r_st_pmask = WDCS_DRQ;
wdc_c.timeout = 1000; /* 1s */
} else if (drvp->drive_flags & DRIVE_ATAPI) {
@@ -105,22 +103,9 @@ ata_get_params(drvp, flags, prms)
}
if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {
- struct channel_softc *chp = drvp->chnl_softc;
-
WDCDEBUG_PRINT(("IDENTIFY failed: 0x%x\n", wdc_c.flags)
, DEBUG_PROBE);
- /* Andreas Gunnarsson reports a setup with a flash
- disk where the ATA drive remains comatose until
- it is sent a command */
- if (try == 0 && (drvp->drive_flags & DRIVE_ATA) &&
- (wdc_c.flags & AT_TIMEOU) &&
- !(chp->ch_status & WDCS_BSY)) {
- WDCDEBUG_PRINT(("Retrying IDENTIFY\n"), DEBUG_PROBE);
- try++;
- goto again;
- }
-
return CMD_ERR;
} else {
#if BYTE_ORDER == BIG_ENDIAN
diff --git a/sys/dev/ic/wdc.c b/sys/dev/ic/wdc.c
index 9566ae63d1a..a8ce69606ab 100644
--- a/sys/dev/ic/wdc.c
+++ b/sys/dev/ic/wdc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdc.c,v 1.36 2001/06/25 19:31:49 csapuntz Exp $ */
+/* $OpenBSD: wdc.c,v 1.37 2001/07/12 01:45:43 csapuntz Exp $ */
/* $NetBSD: wdc.c,v 1.68 1999/06/23 19:00:17 bouyer Exp $ */
@@ -347,20 +347,8 @@ wdc_floating_bus(chp, drive)
return 1;
}
- /*
- * Test register writability
- */
- CHP_WRITE_REG(chp, wdr_cyl_lo, 0xaa);
- CHP_WRITE_REG(chp, wdr_cyl_hi, 0x55);
- CHP_WRITE_REG(chp, wdr_seccnt, 0xff);
-
- if (CHP_READ_REG(chp, wdr_cyl_lo) == 0xaa &&
- CHP_READ_REG(chp, wdr_cyl_hi) == 0x55)
- return 0;
- CHP_WRITE_REG(chp, wdr_seccnt, 0x58);
-
- return 1;
+ return 0;
}
@@ -403,7 +391,9 @@ wdc_ata_present(chp, drive)
int drive;
{
int time_to_done;
+ int retry_cnt = 0;
+ retry:
/*
You're actually supposed to wait up to 10 seconds
for DRDY. However, as a practical matter, most
@@ -413,59 +403,37 @@ wdc_ata_present(chp, drive)
to the ATA standard, the master should reply with 00
for any reads to a non-existant slave.
*/
+ time_to_done = wdc_wait_for_status(chp,
+ (WDCS_DRDY | WDCS_DSC | WDCS_DRQ),
+ (WDCS_DRDY | WDCS_DSC), 1000);
+ if (time_to_done == -1) {
+ if (retry_cnt == 0 && chp->ch_status == 0x00) {
+ /* At least one flash card needs to be kicked */
+ wdccommandshort(chp, drive, WDCC_CHECK_PWR);
+ retry_cnt++;
+ goto retry;
+ }
+ return 0;
+ }
- time_to_done = wdc_wait_for_status(chp, WDCS_DRDY, WDCS_DRDY, 1000);
- if (time_to_done == -1) return 0;
+ if ((chp->ch_status & 0xfc) != (WDCS_DRDY | WDCS_DSC))
+ return 0;
WDCDEBUG_PRINT(("%s:%d:%d: waiting for ready %d msec\n",
chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe",
chp->channel, drive, time_to_done), DEBUG_PROBE);
- /*
- This section has been disabled because my Promise Ultra/66
- starts interrupting like crazy when I issue a NOP. This
- needs to be researched. - csapuntz@openbsd.org
- */
-#if 0
- /*
- The NOP command always aborts.
-
- If a drive doesn't understand NOP, it will abort the
- command.
-
- If a drive does understand NOP, it will abort the command.
-
- If a drive is not present, we may get random crud on
- register reads which will hopefully not pass the test.
-
- Thanks to gluk@ptci.ru for designing this check.
- */
-
- CHP_WRITE_REG(chp, wdr_features, 0);
- CHP_WRITE_REG(chp, wdr_command, WDCC_NOP);
- delay(10);
-
- time_to_done = wdc_wait_for_status(chp, 0, 0, 1000);
-
- if (time_to_done == -1) {
- WDCDEBUG_PRINT(("%s:%d:%d: timeout waiting for NOP to complete\n",
- chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe",
- chp->channel, drive), DEBUG_PROBE);
- return 0;
- }
-
- WDCDEBUG_PRINT(("%s:%d:%d: NOP completed in %d msec\n",
- chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe",
- chp->channel, drive, time_to_done), DEBUG_PROBE);
+ /*
+ * Test register writability
+ */
+ CHP_WRITE_REG(chp, wdr_cyl_lo, 0xaa);
+ CHP_WRITE_REG(chp, wdr_cyl_hi, 0x55);
+ CHP_WRITE_REG(chp, wdr_seccnt, 0xff);
+ DELAY(10);
- if (!(chp->ch_status & WDCS_ERR) &&
- !(chp->ch_error & WDCE_ABRT)) {
- WDCDEBUG_PRINT(("%s:%d:%d: NOP command did not ABORT command\n",
- chp->wdc ? chp->wdc->sc_dev.dv_xname : "wdcprobe",
- chp->channel, drive), DEBUG_PROBE);
+ if (CHP_READ_REG(chp, wdr_cyl_lo) != 0xaa &&
+ CHP_READ_REG(chp, wdr_cyl_hi) != 0x55)
return 0;
- }
-#endif
return 1;
}
@@ -484,17 +452,18 @@ wdcprobe(chp)
u_int8_t st0, st1, sc, sn, cl, ch;
u_int8_t ret_value = 0x03;
u_int8_t drive;
-
- if (!chp->_vtbl)
+
+ if (chp->_vtbl == 0) {
+ int s = splbio();
chp->_vtbl = &wdc_default_vtbl;
+ splx(s);
+ }
#ifdef WDCDEBUG
if ((chp->ch_flags & WDCF_VERBOSE_PROBE) ||
(chp->wdc &&
(chp->wdc->sc_dev.dv_cfdata->cf_flags & WDC_OPTION_PROBE_VERBOSE)))
- wdcdebug_mask |= DEBUG_PROBE;
-
-
+ wdcdebug_mask |= DEBUG_PROBE;
#endif
if (chp->wdc == NULL ||
@@ -565,7 +534,12 @@ wdcprobe(chp)
*/
if (cl == 0x14 && ch == 0xeb) {
chp->ch_drive[drive].drive_flags |= DRIVE_ATAPI;
- } else if (wdc_ata_present(chp, drive)) {
+ continue;
+ }
+
+ wdc_disable_intr(chp);
+ /* ATA detect */
+ if (wdc_ata_present(chp, drive)) {
chp->ch_drive[drive].drive_flags |= DRIVE_ATA;
if (chp->wdc == NULL ||
(chp->wdc->cap & WDC_CAPABILITY_PREATA) != 0)
@@ -573,6 +547,7 @@ wdcprobe(chp)
} else {
ret_value &= ~(1 << drive);
}
+ wdc_enable_intr(chp);
}
#ifdef WDCDEBUG
@@ -845,8 +820,16 @@ wdcintr(arg)
struct channel_softc *chp = arg;
struct wdc_xfer *xfer;
int ret;
-
+
if ((chp->ch_flags & WDCF_IRQ_WAIT) == 0) {
+ /* Acknowledge interrupt by reading status */
+ if (chp->_vtbl == 0) {
+ bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
+ wdr_status & _WDC_REGMASK);
+ } else {
+ CHP_READ_REG(chp, wdr_status);
+ }
+
WDCDEBUG_PRINT(("wdcintr: inactive controller\n"), DEBUG_INTR);
return 0;
}