summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Yurchenko <grange@cvs.openbsd.org>2003-07-23 22:07:16 +0000
committerAlexander Yurchenko <grange@cvs.openbsd.org>2003-07-23 22:07:16 +0000
commitc828fcd5606221baa4bcf2cda327d01774e99bb3 (patch)
tree39ed56e5cdffc1a6159671b70ab244cf3f011380
parent26663ca3acb8e283d5dd460ed33ff13d743223ee (diff)
Old Promise ATA controllers need some additional operations
during DMA transfers to work correctly with LBA48 drives. Based on diff from Takeshi Nakayama <tn@catvmics.ne.jp> for NetBSD with some corrections from FreeBSD ATA driver.
-rw-r--r--sys/dev/ata/ata_wdc.c4
-rw-r--r--sys/dev/ic/wdcvar.h3
-rw-r--r--sys/dev/pci/pciide.c53
-rw-r--r--sys/dev/pci/pciide_pdc202xx_reg.h4
4 files changed, 60 insertions, 4 deletions
diff --git a/sys/dev/ata/ata_wdc.c b/sys/dev/ata/ata_wdc.c
index 88a8455c879..623676d97c4 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.20 2003/02/21 20:10:33 grange Exp $ */
+/* $OpenBSD: ata_wdc.c,v 1.21 2003/07/23 22:07:15 grange Exp $ */
/* $NetBSD: ata_wdc.c,v 1.21 1999/08/09 09:43:11 bouyer Exp $ */
/*
@@ -222,6 +222,8 @@ _wdc_ata_bio_start(chp, xfer)
if (drvp->n_xfers <= NXFER)
drvp->n_xfers++;
dma_flags = (ata_bio->flags & ATA_READ) ? WDC_DMA_READ : 0;
+ if (ata_bio->flags & ATA_LBA48)
+ dma_flags |= WDC_DMA_LBA48;
}
if (ata_bio->flags & ATA_SINGLE)
ata_delay = ATA_DELAY;
diff --git a/sys/dev/ic/wdcvar.h b/sys/dev/ic/wdcvar.h
index ef41a4778cd..1aa9561063c 100644
--- a/sys/dev/ic/wdcvar.h
+++ b/sys/dev/ic/wdcvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdcvar.h,v 1.26 2003/07/05 14:41:56 grange Exp $ */
+/* $OpenBSD: wdcvar.h,v 1.27 2003/07/23 22:07:15 grange Exp $ */
/* $NetBSD: wdcvar.h,v 1.17 1999/04/11 20:50:29 bouyer Exp $ */
/*-
@@ -178,6 +178,7 @@ struct wdc_softc { /* Per controller state */
/* flags passed to DMA functions */
#define WDC_DMA_READ 0x01
#define WDC_DMA_IRQW 0x02
+#define WDC_DMA_LBA48 0x04
int dma_status; /* status return from dma_finish() */
#define WDC_DMAST_NOIRQ 0x01 /* missing IRQ */
#define WDC_DMAST_ERR 0x02 /* DMA error */
diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c
index 17d487bb054..76b7cef8c4d 100644
--- a/sys/dev/pci/pciide.c
+++ b/sys/dev/pci/pciide.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pciide.c,v 1.133 2003/07/20 22:26:50 tedu Exp $ */
+/* $OpenBSD: pciide.c,v 1.134 2003/07/23 22:07:15 grange Exp $ */
/* $NetBSD: pciide.c,v 1.127 2001/08/03 01:31:08 tsutsui Exp $ */
/*
@@ -257,6 +257,8 @@ void pdc202xx_setup_channel(struct channel_softc*);
void pdc20268_setup_channel(struct channel_softc*);
int pdc202xx_pci_intr(void *);
int pdc20265_pci_intr(void *);
+void pdc20262_dma_start(void *, int, int);
+int pdc20262_dma_finish(void *, int, int);
void opti_chip_map(struct pciide_softc*, struct pci_attach_args*);
void opti_setup_channel(struct channel_softc*);
@@ -4610,6 +4612,11 @@ pdc202xx_chip_map(sc, pa)
sc->sc_wdcdev.channels = sc->wdc_chanarray;
sc->sc_wdcdev.nchannels = PCIIDE_NUM_CHANNELS;
+ if (PDC_IS_262(sc)) {
+ sc->sc_wdcdev.dma_start = pdc20262_dma_start;
+ sc->sc_wdcdev.dma_finish = pdc20262_dma_finish;
+ }
+
pciide_print_channels(sc->sc_wdcdev.nchannels, interface);
if (!PDC_IS_268(sc)) {
/* setup failsafe defaults */
@@ -4967,6 +4974,50 @@ pdc20265_pci_intr(arg)
return rv;
}
+void
+pdc20262_dma_start(void *v, int channel, int drive)
+{
+ struct pciide_softc *sc = v;
+ struct pciide_dma_maps *dma_maps =
+ &sc->pciide_channels[channel].dma_maps[drive];
+ u_int8_t clock;
+ u_int32_t count;
+
+ if (dma_maps->dma_flags & WDC_DMA_LBA48) {
+ clock = bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh,
+ PDC262_U66);
+ bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,
+ PDC262_U66, clock | PDC262_U66_EN(channel));
+ count = dma_maps->dmamap_xfer->dm_mapsize >> 1;
+ count |= dma_maps->dma_flags & WDC_DMA_READ ?
+ PDC262_ATAPI_LBA48_READ : PDC262_ATAPI_LBA48_WRITE;
+ bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh,
+ PDC262_ATAPI(channel), count);
+ }
+
+ pciide_dma_start(v, channel, drive);
+}
+
+int
+pdc20262_dma_finish(void *v, int channel, int drive)
+{
+ struct pciide_softc *sc = v;
+ struct pciide_dma_maps *dma_maps =
+ &sc->pciide_channels[channel].dma_maps[drive];
+ u_int8_t clock;
+
+ if (dma_maps->dma_flags & WDC_DMA_LBA48) {
+ clock = bus_space_read_1(sc->sc_dma_iot, sc->sc_dma_ioh,
+ PDC262_U66);
+ bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh,
+ PDC262_U66, clock & ~PDC262_U66_EN(channel));
+ bus_space_write_4(sc->sc_dma_iot, sc->sc_dma_ioh,
+ PDC262_ATAPI(channel), 0);
+ }
+
+ return (pciide_dma_finish(v, channel, drive));
+}
+
/*
* Inline functions for accessing the timing registers of the
* OPTi controller.
diff --git a/sys/dev/pci/pciide_pdc202xx_reg.h b/sys/dev/pci/pciide_pdc202xx_reg.h
index e0646595710..075416159fb 100644
--- a/sys/dev/pci/pciide_pdc202xx_reg.h
+++ b/sys/dev/pci/pciide_pdc202xx_reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pciide_pdc202xx_reg.h,v 1.8 2003/02/21 20:10:34 grange Exp $ */
+/* $OpenBSD: pciide_pdc202xx_reg.h,v 1.9 2003/07/23 22:07:15 grange Exp $ */
/* $NetBSD: pciide_pdc202xx_reg.h,v 1.5 2001/07/05 08:38:27 toshii Exp $ */
/*
@@ -100,6 +100,8 @@
#define PDC262_ATAPI_DMA_READ 0x00001000
#define PDC262_ATAPI_DMA_WRITE 0x00002000
#define PDC262_ATAPI_UDMA 0x00004000
+#define PDC262_ATAPI_LBA48_READ 0x05000000
+#define PDC262_ATAPI_LBA48_WRITE 0x06000000
/*
* The timings provided here cmoes from the PDC20262 docs. I hope they are