diff options
author | Alexander Yurchenko <grange@cvs.openbsd.org> | 2003-07-23 22:07:16 +0000 |
---|---|---|
committer | Alexander Yurchenko <grange@cvs.openbsd.org> | 2003-07-23 22:07:16 +0000 |
commit | c828fcd5606221baa4bcf2cda327d01774e99bb3 (patch) | |
tree | 39ed56e5cdffc1a6159671b70ab244cf3f011380 | |
parent | 26663ca3acb8e283d5dd460ed33ff13d743223ee (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.c | 4 | ||||
-rw-r--r-- | sys/dev/ic/wdcvar.h | 3 | ||||
-rw-r--r-- | sys/dev/pci/pciide.c | 53 | ||||
-rw-r--r-- | sys/dev/pci/pciide_pdc202xx_reg.h | 4 |
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 |