diff options
author | Alexander Yurchenko <grange@cvs.openbsd.org> | 2003-10-17 08:14:10 +0000 |
---|---|---|
committer | Alexander Yurchenko <grange@cvs.openbsd.org> | 2003-10-17 08:14:10 +0000 |
commit | 6dbc421deb21d25ce2935f847921dc56a8399cbb (patch) | |
tree | dc0980203c1dd3c84fe617bd090ac4259903d662 /sys/dev/ata/ata_wdc.c | |
parent | dc1014eb963fbe3c6148ff2c44c5843259f66b55 (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.c | 22 |
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); |