summaryrefslogtreecommitdiff
path: root/sys/dev/ata/ata_wdc.c
diff options
context:
space:
mode:
authorAlexander Yurchenko <grange@cvs.openbsd.org>2003-10-17 08:14:10 +0000
committerAlexander Yurchenko <grange@cvs.openbsd.org>2003-10-17 08:14:10 +0000
commit6dbc421deb21d25ce2935f847921dc56a8399cbb (patch)
treedc0980203c1dd3c84fe617bd090ac4259903d662 /sys/dev/ata/ata_wdc.c
parentdc1014eb963fbe3c6148ff2c44c5843259f66b55 (diff)
Merge an old fix from NetBSD:
- do not stop/unload current DMA operation if an IRQ was not detected by DMA engine unless the force flag was given, fixes DMA problems in shared IRQ setups; - ack interrupt before entering DMA codepath Tested by many. Work by niklas@ but he doesn't want to commit it for some reason.
Diffstat (limited to 'sys/dev/ata/ata_wdc.c')
-rw-r--r--sys/dev/ata/ata_wdc.c22
1 files changed, 9 insertions, 13 deletions
diff --git a/sys/dev/ata/ata_wdc.c b/sys/dev/ata/ata_wdc.c
index 10d934b217c..9ea56043b7a 100644
--- a/sys/dev/ata/ata_wdc.c
+++ b/sys/dev/ata/ata_wdc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ata_wdc.c,v 1.23 2003/10/16 11:30:00 grange Exp $ */
+/* $OpenBSD: ata_wdc.c,v 1.24 2003/10/17 08:14:09 grange Exp $ */
/* $NetBSD: ata_wdc.c,v 1.21 1999/08/09 09:43:11 bouyer Exp $ */
/*
@@ -315,6 +315,7 @@ again:
/* start the DMA channel */
(*chp->wdc->dma_start)(chp->wdc->dma_arg,
chp->channel, xfer->drive);
+ chp->ch_flags |= WDCF_DMA_WAIT;
/* wait for irq */
goto intr;
} /* else not DMA */
@@ -382,6 +383,10 @@ intr: /* Wait for IRQ (either real or polled) */
} else {
/* Wait for at last 400ns for status bit to be valid */
delay(1);
+ if (chp->ch_flags & WDCF_DMA_WAIT) {
+ wdc_dmawait(chp, xfer, ATA_DELAY);
+ chp->ch_flags &= ~WDCF_DMA_WAIT;
+ }
wdc_ata_bio_intr(chp, xfer, 0);
if ((ata_bio->flags & ATA_ITSDONE) == 0)
goto again;
@@ -438,14 +443,12 @@ wdc_ata_bio_intr(chp, xfer, irq)
goto timeout;
}
+ if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
+ chp->wdc->irqack(chp);
drv_err = wdc_ata_err(drvp, ata_bio);
if (xfer->c_flags & C_DMA) {
- chp->wdc->dma_status =
- (*chp->wdc->dma_finish)(chp->wdc->dma_arg,
- chp->channel, xfer->drive);
-
if (chp->wdc->dma_status != 0) {
if (drv_err != WDC_ATA_ERR) {
ata_bio->error = ERR_DMA;
@@ -466,9 +469,6 @@ wdc_ata_bio_intr(chp, xfer, irq)
ata_dmaerr(drvp);
}
- if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
- chp->wdc->irqack(chp);
-
/* if we had an error, end */
if (drv_err == WDC_ATA_ERR) {
wdc_ata_bio_done(chp, xfer);
@@ -509,12 +509,8 @@ end:
return 1;
timeout:
- if (xfer->c_flags & C_DMA) {
- chp->wdc->dma_status =
- (*chp->wdc->dma_finish)(chp->wdc->dma_arg,
- chp->channel, xfer->drive);
+ if (xfer->c_flags & C_DMA)
ata_dmaerr(drvp);
- }
ata_bio->error = TIMEOUT;
wdc_ata_bio_done(chp, xfer);