diff options
author | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 1999-07-22 02:54:07 +0000 |
---|---|---|
committer | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 1999-07-22 02:54:07 +0000 |
commit | f237139cfc1d3ae4925187db3ef95410975c2718 (patch) | |
tree | ca9661fa1e4044797a64f9e4abc87124cd1ebf1d | |
parent | 7ef77e86739fadc6a05aad588c19c8ffd9074fea (diff) |
Create wdc_enable_intr, wdc_disable_intr, wdc_select_drive.
wdc_select_drive implements the drive selection protocol
as documented in the ATA-5 preliminary specs.
-rw-r--r-- | sys/dev/ic/wdc.c | 73 | ||||
-rw-r--r-- | sys/dev/ic/wdcvar.h | 12 |
2 files changed, 71 insertions, 14 deletions
diff --git a/sys/dev/ic/wdc.c b/sys/dev/ic/wdc.c index 9a0a1fc78d7..3cb28ad1d6c 100644 --- a/sys/dev/ic/wdc.c +++ b/sys/dev/ic/wdc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wdc.c,v 1.2 1999/07/18 22:44:48 csapuntz Exp $ */ +/* $OpenBSD: wdc.c,v 1.3 1999/07/22 02:54:06 csapuntz Exp $ */ /* $NetBSD: wdc.c,v 1.68 1999/06/23 19:00:17 bouyer Exp $ */ @@ -160,6 +160,46 @@ atapi_print(aux, pnp) return (UNCONF); } +void +wdc_disable_intr(chp) + struct channel_softc *chp; +{ + bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, + WDCTL_IDS); +} + +void +wdc_enable_intr(chp) + struct channel_softc *chp; +{ + bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, + WDCTL_4BIT); +} + +int +wdc_select_drive(chp, drive, howlong) + struct channel_softc *chp; + int drive; + int howlong; +{ + + if (wait_for_unbusy(chp, howlong)) { + return -1; + } + + bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh, + WDSD_IBM | (drive << 4)); + + delay(1); + + if (wdcwait(chp, WDCS_DRQ, 0, howlong)) { + return -1; + } + + return 0; +} + + /* Test to see controller with at last one attached drive is there. * Returns a bit for each possible drive found (0x01 for drive 0, * 0x02 for drive 1). @@ -587,7 +627,7 @@ wdcreset(chp, verb) delay(1000); bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_IDS); - delay(1000); + delay(2000); (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); @@ -604,6 +644,7 @@ wdcreset(chp, verb) printf(" drive 1"); printf("\n"); } + return (drv_mask1 != drv_mask2) ? 1 : 0; } @@ -614,6 +655,10 @@ __wdcwait_reset(chp, drv_mask) { 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++) { bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh, @@ -669,6 +714,7 @@ wdcwait(chp, mask, bits, timeout) { u_char status; int time = 0; + #ifdef WDCNDELAY_DEBUG extern int cold; #endif @@ -682,7 +728,7 @@ wdcwait(chp, mask, bits, timeout) for (;;) { chp->ch_status = status = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status); - if ((status & WDCS_BSY) == 0 && (status & mask) == bits) + if ((status & WDCS_BSY) == 0 && (status & mask) == bits) break; if (++time > timeout) { WDCDEBUG_PRINT(("wdcwait: timeout, status %x " @@ -1074,14 +1120,23 @@ __wdccommand_start(chp, xfer) chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive), DEBUG_FUNCS); - bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh, - WDSD_IBM | (drive << 4)); - if (wdcwait(chp, wdc_c->r_st_bmask, wdc_c->r_st_bmask, - wdc_c->timeout) != 0) { + /* + * Disable interrupts if we're polling + */ + + if (xfer->c_flags & C_POLL) { + wdc_disable_intr(chp); + } + + /* + * Make sure the bus isn't busy + */ + if (wdc_select_drive(chp, drive, wdc_c->timeout) != 0) { wdc_c->flags |= AT_TIMEOU; __wdccommand_done(chp, xfer); return; } + wdccommand(chp, drive, wdc_c->r_command, wdc_c->r_cyl, wdc_c->r_head, wdc_c->r_sector, wdc_c->r_count, wdc_c->r_precomp); if ((wdc_c->flags & AT_POLL) == 0) { @@ -1178,6 +1233,9 @@ __wdccommand_done(chp, xfer) wdc_c->r_precomp = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_precomp); } + if (xfer->c_flags & C_POLL) { + wdc_enable_intr(chp); + } wdc_free_xfer(chp, xfer); WDCDEBUG_PRINT(("__wdccommand_done before callback\n"), DEBUG_INTR); if (needdone) { @@ -1211,6 +1269,7 @@ wdccommand(chp, drive, command, cylin, head, sector, count, precomp) /* Select drive, head, and addressing mode. */ bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh, WDSD_IBM | (drive << 4) | head); + /* Load parameters. wd_features(ATA/ATAPI) = wd_precomp(ST506) */ bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_precomp, precomp); diff --git a/sys/dev/ic/wdcvar.h b/sys/dev/ic/wdcvar.h index 1d4fb228154..9319311eb0b 100644 --- a/sys/dev/ic/wdcvar.h +++ b/sys/dev/ic/wdcvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: wdcvar.h,v 1.1 1999/07/18 21:25:16 csapuntz Exp $ */ +/* $OpenBSD: wdcvar.h,v 1.2 1999/07/22 02:54:06 csapuntz Exp $ */ /* $NetBSD: wdcvar.h,v 1.17 1999/04/11 20:50:29 bouyer Exp $ */ /*- @@ -37,12 +37,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#if 0 -/* XXX for scsipi_adapter */ -#include <dev/scsipi/scsipi_all.h> -#include <dev/scsipi/scsipiconf.h> -#endif - struct atapiscsi_softc; #define WAITTIME (10 * hz) /* time to wait for a completion */ @@ -202,3 +196,7 @@ void wdc_atapibus_attach __P((struct channel_softc *)); void wdc_atapibus_final_attach __P((struct channel_softc *)); int atapi_print __P((void *, const char *)); + +void wdc_disable_intr __P((struct channel_softc *)); +void wdc_enable_intr __P((struct channel_softc *)); +int wdc_select_drive __P((struct channel_softc *, int, int)); |