summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Yurchenko <grange@cvs.openbsd.org>2004-06-02 18:55:09 +0000
committerAlexander Yurchenko <grange@cvs.openbsd.org>2004-06-02 18:55:09 +0000
commit5a39fe414db9196464fc4176ea67c2fd7c2701d6 (patch)
treebc673bfa57f489b486a05c89aa0b6c848eefd187
parent12fd1578a303513cd03b772c5e909bb6020d7f8f (diff)
Add quirks field to the wdc softc and implement the first one:
WDC_QUIRK_NOSHORTDMA which disables DMA for the one-sector transfers. Use this quirk for the Geode SC1100 IDE to fix hanging during fdisk reported in PR 3729. Thanks to Alexandre Belloni <abelloni@nerim.net> for testing. ok costa@
-rw-r--r--sys/dev/ata/ata_wdc.c6
-rw-r--r--sys/dev/ic/wdcvar.h4
-rw-r--r--sys/dev/pci/pciide.c8
3 files changed, 14 insertions, 4 deletions
diff --git a/sys/dev/ata/ata_wdc.c b/sys/dev/ata/ata_wdc.c
index c6ef07b91a4..304bcc09973 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.26 2004/01/23 20:48:33 grange Exp $ */
+/* $OpenBSD: ata_wdc.c,v 1.27 2004/06/02 18:55:08 grange Exp $ */
/* $NetBSD: ata_wdc.c,v 1.21 1999/08/09 09:43:11 bouyer Exp $ */
/*
@@ -144,7 +144,9 @@ wdc_ata_bio(struct ata_drive_datas *drvp, struct ata_bio *ata_bio)
xfer->c_flags |= C_POLL;
if (!(ata_bio->flags & ATA_POLL) &&
(drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
- (ata_bio->flags & ATA_SINGLE) == 0)
+ (ata_bio->flags & ATA_SINGLE) == 0 &&
+ (ata_bio->bcount > 512 ||
+ (chp->wdc->quirks & WDC_QUIRK_NOSHORTDMA) == 0))
xfer->c_flags |= C_DMA;
xfer->drive = drvp->drive;
xfer->cmd = ata_bio;
diff --git a/sys/dev/ic/wdcvar.h b/sys/dev/ic/wdcvar.h
index 87fbb305cf6..a3c9cea2e10 100644
--- a/sys/dev/ic/wdcvar.h
+++ b/sys/dev/ic/wdcvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdcvar.h,v 1.32 2003/10/21 18:58:50 jmc Exp $ */
+/* $OpenBSD: wdcvar.h,v 1.33 2004/06/02 18:55:08 grange Exp $ */
/* $NetBSD: wdcvar.h,v 1.17 1999/04/11 20:50:29 bouyer Exp $ */
/*-
@@ -163,6 +163,8 @@ struct wdc_softc { /* Per controller state */
u_int8_t UDMA_cap; /* highest UDMA mode supported */
int nchannels; /* Number of channels on this controller */
struct channel_softc **channels; /* channels-specific datas (array) */
+ u_int16_t quirks; /* per-device oddities */
+#define WDC_QUIRK_NOSHORTDMA 0x0001 /* can't do short DMA transfers */
#if 0
/*
diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c
index e9b13ca3435..8ca47e1a3ef 100644
--- a/sys/dev/pci/pciide.c
+++ b/sys/dev/pci/pciide.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pciide.c,v 1.167 2004/05/24 22:52:52 mickey Exp $ */
+/* $OpenBSD: pciide.c,v 1.168 2004/06/02 18:55:08 grange Exp $ */
/* $NetBSD: pciide.c,v 1.127 2001/08/03 01:31:08 tsutsui Exp $ */
/*
@@ -4215,6 +4215,12 @@ ns_scx200_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
sc->sc_dma_boundary = IDEDMA_BYTE_COUNT_MAX - PAGE_SIZE;
}
+ /*
+ * This chip seems to be unable to do one-sector transfers
+ * using DMA.
+ */
+ sc->sc_wdcdev.quirks = WDC_QUIRK_NOSHORTDMA;
+
pciide_print_channels(sc->sc_wdcdev.nchannels, interface);
for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {