summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorbouyer <bouyer@NetBSD.org>1999-04-01 21:46:28 +0000
committerbouyer <bouyer@NetBSD.org>1999-04-01 21:46:28 +0000
commitb43b844f6ff4fdb9d63fa2e3793b07825f6b3832 (patch)
tree35873bc8edc256363d148a8141f60ac9b404f422 /sys/dev
parentf7ca917a9860e96edbd1e50f84ec30da0edf139e (diff)
- change the interrupt routines to take a 3rd arguments, set to 1 if we
are called from the interrupt or timeout handler, 0 otherwise. - use this to know if we can busy-wait for wait_for_unbusy or wait_for_ready This fixes a bug where CDs withot the DRQ_INTR capability would not busy-wait for the CMDOUT phase. While I'm there change 2 delay() to DELAY() for consistency, and garbage-collect some old code from wdcintr() which has been ifdef'd out for some time now.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ata/ata_wdc.c27
-rw-r--r--sys/dev/ic/wdc.c46
-rw-r--r--sys/dev/ic/wdcvar.h4
-rw-r--r--sys/dev/scsipi/atapi_wdc.c41
4 files changed, 46 insertions, 72 deletions
diff --git a/sys/dev/ata/ata_wdc.c b/sys/dev/ata/ata_wdc.c
index a829d31a990..14e74ad4eca 100644
--- a/sys/dev/ata/ata_wdc.c
+++ b/sys/dev/ata/ata_wdc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ata_wdc.c,v 1.18 1999/03/25 16:17:36 bouyer Exp $ */
+/* $NetBSD: ata_wdc.c,v 1.19 1999/04/01 21:46:28 bouyer Exp $ */
/*
* Copyright (c) 1998 Manuel Bouyer.
@@ -117,9 +117,9 @@ int wdcdebug_wd_mask = 0;
#define ATA_DELAY 10000 /* 10s for a drive I/O */
void wdc_ata_bio_start __P((struct channel_softc *,struct wdc_xfer *));
-int wdc_ata_bio_intr __P((struct channel_softc *, struct wdc_xfer *));
+int wdc_ata_bio_intr __P((struct channel_softc *, struct wdc_xfer *, int));
void wdc_ata_bio_done __P((struct channel_softc *, struct wdc_xfer *));
-int wdc_ata_ctrl_intr __P((struct channel_softc *, struct wdc_xfer *));
+int wdc_ata_ctrl_intr __P((struct channel_softc *, struct wdc_xfer *, int));
int wdc_ata_err __P((struct ata_drive_datas *, struct ata_bio *));
#define WDC_ATA_NOERR 0x00 /* Drive doesn't report an error */
#define WDC_ATA_RECOV 0x01 /* There was a recovered error */
@@ -199,8 +199,8 @@ wdc_ata_bio_start(chp, xfer)
ATA_DELAY / 1000 * hz);
} else {
/* Wait for at last 400ns for status bit to be valid */
- delay(1);
- wdc_ata_ctrl_intr(chp, xfer);
+ DELAY(1);
+ wdc_ata_ctrl_intr(chp, xfer, 0);
}
return;
}
@@ -372,7 +372,7 @@ intr: /* Wait for IRQ (either real or polled) */
} else {
/* Wait for at last 400ns for status bit to be valid */
delay(1);
- wdc_ata_bio_intr(chp, xfer);
+ wdc_ata_bio_intr(chp, xfer, 0);
if ((ata_bio->flags & ATA_ITSDONE) == 0)
goto again;
}
@@ -388,9 +388,10 @@ timeout:
}
int
-wdc_ata_bio_intr(chp, xfer)
+wdc_ata_bio_intr(chp, xfer, irq)
struct channel_softc *chp;
struct wdc_xfer *xfer;
+ int irq;
{
struct ata_bio *ata_bio = xfer->cmd;
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
@@ -417,9 +418,8 @@ wdc_ata_bio_intr(chp, xfer)
/* Ack interrupt done by wait_for_unbusy */
if (wait_for_unbusy(chp,
- (ata_bio->flags & ATA_POLL) ? ATA_DELAY : 0) < 0) {
- if ((ata_bio->flags & ATA_POLL) == 0 &&
- (xfer->c_flags & C_TIMEOU) == 0)
+ (irq == 0) ? ATA_DELAY : 0) < 0) {
+ if (irq && (xfer->c_flags & C_TIMEOU) == 0)
return 0; /* IRQ was not for us */
printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip%d\n",
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
@@ -585,14 +585,15 @@ wdc_ata_bio_done(chp, xfer)
* Implement operations needed before read/write.
*/
int
-wdc_ata_ctrl_intr(chp, xfer)
+wdc_ata_ctrl_intr(chp, xfer, irq)
struct channel_softc *chp;
struct wdc_xfer *xfer;
+ int irq;
{
struct ata_bio *ata_bio = xfer->cmd;
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
char *errstring = NULL;
- int delay = (ata_bio->flags & ATA_POLL) ? ATA_DELAY : 0;
+ int delay = (irq == 0) ? ATA_DELAY : 0;
WDCDEBUG_PRINT(("wdc_ata_ctrl_intr: state %d\n", drvp->state),
DEBUG_FUNCS);
@@ -708,7 +709,7 @@ again:
return 1;
timeout:
- if ((xfer->c_flags & C_TIMEOU) == 0 && delay == 0) {
+ if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
return 0; /* IRQ was not for us */
}
printf("%s:%d:%d: %s timed out\n",
diff --git a/sys/dev/ic/wdc.c b/sys/dev/ic/wdc.c
index 9d28848c41b..32b25b55ed3 100644
--- a/sys/dev/ic/wdc.c
+++ b/sys/dev/ic/wdc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: wdc.c,v 1.65 1999/03/31 11:18:31 bouyer Exp $ */
+/* $NetBSD: wdc.c,v 1.66 1999/04/01 21:46:29 bouyer Exp $ */
/*
@@ -117,7 +117,7 @@ static void __wdcerror __P((struct channel_softc*, char *));
static int __wdcwait_reset __P((struct channel_softc *, int));
void __wdccommand_done __P((struct channel_softc *, struct wdc_xfer *));
void __wdccommand_start __P((struct channel_softc *, struct wdc_xfer *));
-int __wdccommand_intr __P((struct channel_softc *, struct wdc_xfer *));
+int __wdccommand_intr __P((struct channel_softc *, struct wdc_xfer *, int));
int wdprint __P((void *, const char *));
@@ -518,35 +518,7 @@ wdcintr(arg)
struct wdc_xfer *xfer;
if ((chp->ch_flags & WDCF_IRQ_WAIT) == 0) {
-#if 0
- /* Clear the pending interrupt and abort. */
- u_int8_t s =
- bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_status);
-#ifdef WDCDEBUG
- u_int8_t e =
- bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
- u_int8_t i =
- bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_seccnt);
-#else
- bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_error);
- bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_seccnt);
-#endif
-
- WDCDEBUG_PRINT(("wdcintr: inactive controller, "
- "punting st=%02x er=%02x irr=%02x\n", s, e, i), DEBUG_INTR);
-
- if (s & WDCS_DRQ) {
- int len;
- len = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh,
- wd_cyl_lo) + 256 * bus_space_read_1(chp->cmd_iot,
- chp->cmd_ioh, wd_cyl_hi);
- WDCDEBUG_PRINT(("wdcintr: clearing up %d bytes\n",
- len), DEBUG_INTR);
- wdcbit_bucket (chp, len);
- }
-#else
WDCDEBUG_PRINT(("wdcintr: inactive controller\n"), DEBUG_INTR);
-#endif
return 0;
}
@@ -554,7 +526,7 @@ wdcintr(arg)
untimeout(wdctimeout, chp);
chp->ch_flags &= ~WDCF_IRQ_WAIT;
xfer = chp->ch_queue->sc_xfer.tqh_first;
- return xfer->c_intr(chp, xfer);
+ return xfer->c_intr(chp, xfer, 1);
}
/* Put all disk in RESET state */
@@ -738,7 +710,7 @@ wdctimeout(arg)
*/
xfer->c_flags |= C_TIMEOU;
chp->ch_flags &= ~WDCF_IRQ_WAIT;
- xfer->c_intr(chp, xfer);
+ xfer->c_intr(chp, xfer, 1);
} else
__wdcerror(chp, "missing untimeout");
splx(s);
@@ -1079,13 +1051,14 @@ __wdccommand_start(chp, xfer)
* Wait for at last 400ns for status bit to be valid.
*/
delay(10);
- __wdccommand_intr(chp, xfer);
+ __wdccommand_intr(chp, xfer, 0);
}
int
-__wdccommand_intr(chp, xfer)
+__wdccommand_intr(chp, xfer, irq)
struct channel_softc *chp;
struct wdc_xfer *xfer;
+ int irq;
{
struct wdc_command *wdc_c = xfer->cmd;
int bcount = wdc_c->bcount;
@@ -1094,9 +1067,8 @@ __wdccommand_intr(chp, xfer)
WDCDEBUG_PRINT(("__wdccommand_intr %s:%d:%d\n",
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive), DEBUG_INTR);
if (wdcwait(chp, wdc_c->r_st_pmask, wdc_c->r_st_pmask,
- (wdc_c->flags & AT_POLL) ? wdc_c->timeout : 0)) {
- if ((xfer->c_flags & C_TIMEOU) == 0 &&
- (wdc_c->flags & AT_POLL) == 0)
+ (irq == 0) ? wdc_c->timeout : 0)) {
+ if (irq && (xfer->c_flags & C_TIMEOU) == 0)
return 0; /* IRQ was not for us */
wdc_c->flags |= AT_TIMEOU;
__wdccommand_done(chp, xfer);
diff --git a/sys/dev/ic/wdcvar.h b/sys/dev/ic/wdcvar.h
index bf2f8502d63..f5f0436e03a 100644
--- a/sys/dev/ic/wdcvar.h
+++ b/sys/dev/ic/wdcvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: wdcvar.h,v 1.15 1999/02/08 15:22:29 bouyer Exp $ */
+/* $NetBSD: wdcvar.h,v 1.16 1999/04/01 21:46:30 bouyer Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -145,7 +145,7 @@ struct wdc_xfer {
TAILQ_ENTRY(wdc_xfer) c_xferchain;
LIST_ENTRY(wdc_xfer) free_list;
void (*c_start) __P((struct channel_softc *, struct wdc_xfer *));
- int (*c_intr) __P((struct channel_softc *, struct wdc_xfer *));
+ int (*c_intr) __P((struct channel_softc *, struct wdc_xfer *, int));
};
/*
diff --git a/sys/dev/scsipi/atapi_wdc.c b/sys/dev/scsipi/atapi_wdc.c
index 9a3911d1f32..57efb270eac 100644
--- a/sys/dev/scsipi/atapi_wdc.c
+++ b/sys/dev/scsipi/atapi_wdc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: atapi_wdc.c,v 1.19 1999/03/25 16:17:37 bouyer Exp $ */
+/* $NetBSD: atapi_wdc.c,v 1.20 1999/04/01 21:46:30 bouyer Exp $ */
/*
* Copyright (c) 1998 Manuel Bouyer.
@@ -86,8 +86,8 @@ int wdcdebug_atapi_mask = 0;
void wdc_atapi_minphys __P((struct buf *bp));
void wdc_atapi_start __P((struct channel_softc *,struct wdc_xfer *));
-int wdc_atapi_intr __P((struct channel_softc *, struct wdc_xfer *));
-int wdc_atapi_ctrl __P((struct channel_softc *, struct wdc_xfer *));
+int wdc_atapi_intr __P((struct channel_softc *, struct wdc_xfer *, int));
+int wdc_atapi_ctrl __P((struct channel_softc *, struct wdc_xfer *, int));
void wdc_atapi_done __P((struct channel_softc *, struct wdc_xfer *));
void wdc_atapi_reset __P((struct channel_softc *, struct wdc_xfer *));
int wdc_atapi_send_cmd __P((struct scsipi_xfer *sc_xfer));
@@ -246,7 +246,7 @@ wdc_atapi_start(chp, xfer)
xfer->drive, drvp->state);
panic("wdc_atapi_start: bad state");
}
- wdc_atapi_ctrl(chp, xfer);
+ wdc_atapi_ctrl(chp, xfer, 0);
return;
}
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
@@ -281,26 +281,23 @@ wdc_atapi_start(chp, xfer)
if ((sc_xfer->sc_link->scsipi_atapi.cap & 0x0300) != ACAP_DRQ_INTR ||
sc_xfer->flags & SCSI_POLL) {
/* Wait for at last 400ns for status bit to be valid */
- delay(1);
- if (wdc_atapi_intr(chp, xfer) == 0) {
- sc_xfer->error = XS_TIMEOUT;
- wdc_atapi_reset(chp, xfer);
- return;
- }
+ DELAY(1);
+ wdc_atapi_intr(chp, xfer, 0);
}
if (sc_xfer->flags & SCSI_POLL) {
while ((sc_xfer->flags & ITSDONE) == 0) {
/* Wait for at last 400ns for status bit to be valid */
- delay(1);
- wdc_atapi_intr(chp, xfer);
+ DELAY(1);
+ wdc_atapi_intr(chp, xfer, 0);
}
}
}
int
-wdc_atapi_intr(chp, xfer)
+wdc_atapi_intr(chp, xfer, irq)
struct channel_softc *chp;
struct wdc_xfer *xfer;
+ int irq;
{
struct scsipi_xfer *sc_xfer = xfer->cmd;
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
@@ -326,9 +323,8 @@ wdc_atapi_intr(chp, xfer)
bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
WDSD_IBM | (xfer->drive << 4));
if (wait_for_unbusy(chp,
- (sc_xfer->flags & SCSI_POLL) ? sc_xfer->timeout : 0) != 0) {
- if ((sc_xfer->flags & SCSI_POLL) == 0 &&
- (xfer->c_flags & C_TIMEOU) == 0)
+ (irq == 0) ? sc_xfer->timeout : 0) != 0) {
+ if (irq && (xfer->c_flags & C_TIMEOU) == 0)
return 0; /* IRQ was not for us */
printf("%s:%d:%d: device timeout, c_bcount=%d, c_skip=%d\n",
chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
@@ -592,7 +588,11 @@ again:
if (xfer->c_flags & C_DMA) {
dma_err = (*chp->wdc->dma_finish)(chp->wdc->dma_arg,
chp->channel, xfer->drive, dma_flags);
- xfer->c_bcount -= sc_xfer->datalen;
+ if (xfer->c_flags & C_SENSE)
+ xfer->c_bcount -=
+ sizeof(sc_xfer->sense.scsi_sense);
+ else
+ xfer->c_bcount -= sc_xfer->datalen;
}
if (xfer->c_flags & C_SENSE) {
if ((chp->ch_status & WDCS_ERR) || dma_err < 0) {
@@ -680,14 +680,15 @@ again:
}
int
-wdc_atapi_ctrl(chp, xfer)
+wdc_atapi_ctrl(chp, xfer, irq)
struct channel_softc *chp;
struct wdc_xfer *xfer;
+ int irq;
{
struct scsipi_xfer *sc_xfer = xfer->cmd;
struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
char *errstring = NULL;
- int delay = (sc_xfer->flags & SCSI_POLL) ? ATAPI_DELAY : 0;
+ int delay = (irq == 0) ? ATAPI_DELAY : 0;
/* Ack interrupt done in wait_for_unbusy */
again:
@@ -753,7 +754,7 @@ again:
return 1;
timeout:
- if ((xfer->c_flags & C_TIMEOU) == 0 && delay == 0) {
+ if (irq && (xfer->c_flags & C_TIMEOU) == 0) {
return 0; /* IRQ was not for us */
}
printf("%s:%d:%d: %s timed out\n",