diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2009-09-29 17:51:09 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2009-09-29 17:51:09 +0000 |
commit | ea936621b858439241476551a88c4c5a040de69d (patch) | |
tree | 7db6d9f8f611996032a2079c4bc8586c15c26e8f | |
parent | 1eaea0f36001fb9020bc14558a0a6376b119c5e5 (diff) |
Support the Phison PS5000. IO Data and other vendors are now using this
on an expresscard SSD adaptor.
ok jsg
-rw-r--r-- | share/man/man4/pciide.4 | 6 | ||||
-rw-r--r-- | sys/dev/pci/pciide.c | 132 |
2 files changed, 134 insertions, 4 deletions
diff --git a/share/man/man4/pciide.4 b/share/man/man4/pciide.4 index bd3a80659ef..e4ee74baf24 100644 --- a/share/man/man4/pciide.4 +++ b/share/man/man4/pciide.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: pciide.4,v 1.82 2009/06/26 02:46:27 kevlo Exp $ +.\" $OpenBSD: pciide.4,v 1.83 2009/09/29 17:51:08 deraadt Exp $ .\" $NetBSD: pciide.4,v 1.8 1999/03/16 01:19:17 garbled Exp $ .\" .\" Copyright (c) 1998 Manuel Bouyer. @@ -31,7 +31,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd $Mdocdate: June 26 2009 $ +.Dd $Mdocdate: September 29 2009 $ .Dt PCIIDE 4 .Os .Sh NAME @@ -107,6 +107,8 @@ PDC20371, PDC20375, PDC20376, PDC20377, PDC20378, PDC20379, PDC20571, PDC20575, PDC20579, PDC20771, PDC20775, PDC40518, PDC40519, PDC40718, PDC40719, PDC40779 .It +Phison PS5000 +.It ServerWorks SATA, OSB4, CSB5, CSB6 (including support for the third channel) .It Silicon Image SiI3112, SiI3512, SiI3114 diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c index e12340f3a4e..fe224f6b17d 100644 --- a/sys/dev/pci/pciide.c +++ b/sys/dev/pci/pciide.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pciide.c,v 1.298 2009/09/05 10:24:58 miod Exp $ */ +/* $OpenBSD: pciide.c,v 1.299 2009/09/29 17:51:07 deraadt Exp $ */ /* $NetBSD: pciide.c,v 1.127 2001/08/03 01:31:08 tsutsui Exp $ */ /* @@ -281,6 +281,9 @@ void ixp_setup_channel(struct channel_softc *); void jmicron_chip_map(struct pciide_softc *, struct pci_attach_args *); void jmicron_setup_channel(struct channel_softc *); +void phison_chip_map(struct pciide_softc *, struct pci_attach_args *); +void phison_setup_channel(struct channel_softc *); + void sch_chip_map(struct pciide_softc *, struct pci_attach_args *); void sch_setup_channel(struct channel_softc *); @@ -1166,6 +1169,13 @@ const struct pciide_product_desc pciide_jmicron_products[] = { } }; +const struct pciide_product_desc pciide_phison_products[] = { + { PCI_PRODUCT_PHISON_PS5000, + 0, + phison_chip_map + }, +}; + struct pciide_vendor_desc { u_int32_t ide_vendor; const struct pciide_product_desc *ide_products; @@ -1208,7 +1218,9 @@ const struct pciide_vendor_desc pciide_vendors[] = { { PCI_VENDOR_ATI, pciide_ati_products, sizeof(pciide_ati_products)/sizeof(pciide_ati_products[0]) }, { PCI_VENDOR_JMICRON, pciide_jmicron_products, - sizeof(pciide_jmicron_products)/sizeof(pciide_jmicron_products[0]) } + sizeof(pciide_jmicron_products)/sizeof(pciide_jmicron_products[0]) }, + { PCI_VENDOR_PHISON, pciide_phison_products, + sizeof(pciide_phison_products)/sizeof(pciide_phison_products[0]) } }; /* options passed via the 'flags' config keyword */ @@ -8482,6 +8494,122 @@ pio: } void +phison_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa) +{ + struct pciide_channel *cp; + int channel; + pcireg_t interface = PCI_INTERFACE(pa->pa_class); + bus_size_t cmdsize, ctlsize; + u_int32_t conf; + + printf(": DMA"); + pciide_mapreg_dma(sc, pa); + + sc->sc_wdcdev.cap = WDC_CAPABILITY_DATA16 | WDC_CAPABILITY_DATA32 | + WDC_CAPABILITY_MODE; + if (sc->sc_dma_ok) { + sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA | WDC_CAPABILITY_UDMA; + sc->sc_wdcdev.cap |= WDC_CAPABILITY_IRQACK; + sc->sc_wdcdev.irqack = pciide_irqack; + } + sc->sc_wdcdev.PIO_cap = 4; + sc->sc_wdcdev.DMA_cap = 2; + sc->sc_wdcdev.UDMA_cap = 5; + sc->sc_wdcdev.set_modes = phison_setup_channel; + sc->sc_wdcdev.channels = sc->wdc_chanarray; + sc->sc_wdcdev.nchannels = 1; + + pciide_print_channels(sc->sc_wdcdev.nchannels, interface); + + for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) { + cp = &sc->pciide_channels[channel]; + + if (pciide_chansetup(sc, channel, interface) == 0) + continue; + + pciide_map_compat_intr(pa, cp, channel, interface); + if (cp->hw_ok == 0) + continue; + pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize, + pciide_pci_intr); + if (cp->hw_ok == 0) { + pciide_unmap_compat_intr(pa, cp, channel, interface); + continue; + } + + sc->sc_wdcdev.set_modes(&cp->wdc_channel); + } + WDCDEBUG_PRINT(("%s: new conf register 0x%x\n", + sc->sc_wdcdev.sc_dev.dv_xname, conf), DEBUG_PROBE); + pci_conf_write(sc->sc_pc, sc->sc_tag, NFORCE_CONF, conf); +} + +void +phison_setup_channel(struct channel_softc *chp) +{ + struct ata_drive_datas *drvp; + int drive, mode; + u_int32_t idedma_ctl; + struct pciide_channel *cp = (struct pciide_channel *)chp; + struct pciide_softc *sc = (struct pciide_softc *)cp->wdc_channel.wdc; + int channel = chp->channel; + + /* Setup DMA if needed */ + pciide_channel_dma_setup(cp); + + /* Clear all bits for this channel */ + idedma_ctl = 0; + + /* Per channel settings */ + for (drive = 0; drive < 2; drive++) { + drvp = &chp->ch_drive[drive]; + + /* If no drive, skip */ + if ((drvp->drive_flags & DRIVE) == 0) + continue; + + if ((chp->wdc->cap & WDC_CAPABILITY_UDMA) != 0 && + (drvp->drive_flags & DRIVE_UDMA) != 0) { + /* Setup UltraDMA mode */ + drvp->drive_flags &= ~DRIVE_DMA; + mode = drvp->PIO_mode; + } else if ((chp->wdc->cap & WDC_CAPABILITY_DMA) != 0 && + (drvp->drive_flags & DRIVE_DMA) != 0) { + /* Setup multiword DMA mode */ + drvp->drive_flags &= ~DRIVE_UDMA; + + /* mode = min(pio, dma + 2) */ + if (drvp->PIO_mode <= (drvp->DMA_mode + 2)) + mode = drvp->PIO_mode; + else + mode = drvp->DMA_mode + 2; + } else { + mode = drvp->PIO_mode; + goto pio; + } + idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); + +pio: + /* Setup PIO mode */ + if (mode <= 2) { + drvp->DMA_mode = 0; + drvp->PIO_mode = 0; + } else { + drvp->PIO_mode = mode; + drvp->DMA_mode = mode - 2; + } + } + + if (idedma_ctl != 0) { + /* Add software bits in status register */ + bus_space_write_1(sc->sc_dma_iot, sc->sc_dma_ioh, + IDEDMA_CTL(channel), idedma_ctl); + } + + pciide_print_modes(cp); +} + +void sch_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa) { struct pciide_channel *cp; |