Module Name: src Committed By: jakllsch Date: Sun Jul 10 20:01:37 UTC 2011
Modified Files: src/sys/dev/pci: pciide_apollo_reg.h viaide.c Log Message: Add complete support for all channels on VT6421A SATA/PATA controller to viaide(4). To generate a diff of this commit: cvs rdiff -u -r1.19 -r1.20 src/sys/dev/pci/pciide_apollo_reg.h cvs rdiff -u -r1.75 -r1.76 src/sys/dev/pci/viaide.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/pci/pciide_apollo_reg.h diff -u src/sys/dev/pci/pciide_apollo_reg.h:1.19 src/sys/dev/pci/pciide_apollo_reg.h:1.20 --- src/sys/dev/pci/pciide_apollo_reg.h:1.19 Thu Jun 30 20:09:40 2011 +++ src/sys/dev/pci/pciide_apollo_reg.h Sun Jul 10 20:01:37 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pciide_apollo_reg.h,v 1.19 2011/06/30 20:09:40 wiz Exp $ */ +/* $NetBSD: pciide_apollo_reg.h,v 1.20 2011/07/10 20:01:37 jakllsch Exp $ */ /* * Copyright (c) 1998 Manuel Bouyer. @@ -91,6 +91,7 @@ #define APO_VIA_REGBASE 0x40 #define APO_AMD_REGBASE 0x40 #define APO_NVIDIA_REGBASE 0x50 +#define APO_VIA_VT6421_REGBASE 0xa0 /* misc. configuration registers */ #define APO_IDECONF(sc) ((sc)->sc_apo_regbase + 0x00) @@ -110,7 +111,7 @@ #define APO_IDECONF_FIFO_CONF_MASK 0x60000000 /* Misc. controls register - VIA only */ -#define APO_CTLMISC(sc) 0x44 +#define APO_CTLMISC(sc) ((sc)->sc_apo_regbase + 0x04) #define APO_CTLMISC_BM_STS_RTY 0x00000008 #define APO_CTLMISC_FIFO_HWS 0x00000010 #define APO_CTLMISC_WR_IRDY_WS 0x00000020 @@ -129,7 +130,7 @@ (((1 - (channel)) << 4) + ((1 - (drive)) << 3) + 4)) /* misc timings control - VIA only */ -#define APO_MISCTIM(sc) 0x4c +#define APO_MISCTIM(sc) ((sc)->sc_apo_regbase + 0x0c) /* Ultra-DMA control (586A/B only, amd and nvidia ) */ #define APO_UDMA(sc) ((sc)->sc_apo_regbase + 0x10) Index: src/sys/dev/pci/viaide.c diff -u src/sys/dev/pci/viaide.c:1.75 src/sys/dev/pci/viaide.c:1.76 --- src/sys/dev/pci/viaide.c:1.75 Tue May 17 17:34:54 2011 +++ src/sys/dev/pci/viaide.c Sun Jul 10 20:01:37 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: viaide.c,v 1.75 2011/05/17 17:34:54 dyoung Exp $ */ +/* $NetBSD: viaide.c,v 1.76 2011/07/10 20:01:37 jakllsch Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Manuel Bouyer. @@ -26,10 +26,11 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: viaide.c,v 1.75 2011/05/17 17:34:54 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: viaide.c,v 1.76 2011/07/10 20:01:37 jakllsch Exp $"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/malloc.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> @@ -46,7 +47,7 @@ static void via_mapregs_compat_native(const struct pci_attach_args *, struct pciide_channel *); static int via_sata_chip_map_common(struct pciide_softc *, - struct pci_attach_args *); + const struct pci_attach_args *); static void via_sata_chip_map(struct pciide_softc *, const struct pci_attach_args *, int); static void via_sata_chip_map_6(struct pciide_softc *, @@ -311,7 +312,7 @@ }, { PCI_PRODUCT_VIATECH_VT6421_RAID, 0, - "VIA Technologies VT6421 Serial RAID Controller", + "VIA Technologies VT6421 Serial ATA RAID Controller", via_sata_chip_map_new, }, { PCI_PRODUCT_VIATECH_VT8237_SATA, @@ -366,7 +367,7 @@ static int viaide_match(device_t parent, cfdata_t match, void *aux) { - struct pci_attach_args *pa = aux; + const struct pci_attach_args *pa = aux; if (viaide_lookup(pa->pa_id) != NULL) return (2); @@ -376,7 +377,7 @@ static void viaide_attach(device_t parent, device_t self, void *aux) { - struct pci_attach_args *pa = aux; + const struct pci_attach_args *pa = aux; struct pciide_softc *sc = device_private(self); const struct pciide_product_desc *pp; @@ -835,10 +836,14 @@ } static int -via_sata_chip_map_common(struct pciide_softc *sc, struct pci_attach_args *pa) +via_sata_chip_map_common(struct pciide_softc *sc, + const struct pci_attach_args *cpa) { pcireg_t csr; int maptype, ret; + struct pci_attach_args pac, *pa = &pac; + + pac = *cpa; if (pciide_chipen(sc, pa) == 0) return 0; @@ -908,18 +913,15 @@ } static void -via_sata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa0, +via_sata_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa, int satareg_shift) { struct pciide_channel *cp; struct ata_channel *wdc_cp; struct wdc_regs *wdr; - struct pci_attach_args pacopy, *pa; pcireg_t interface; int channel; - pacopy = *pa0; - pa = &pacopy; interface = PCI_INTERFACE(pa->pa_class); if (via_sata_chip_map_common(sc, pa) == 0) @@ -983,33 +985,118 @@ } static void +via_vt6421_mapreg_dma(struct pciide_softc *sc, const struct pci_attach_args *pa) +{ + struct pciide_channel *pc; + int chan, reg; + bus_size_t size; + + sc->sc_dma_ok = (pci_mapreg_map(pa, PCIIDE_REG_BUS_MASTER_DMA, + PCI_MAPREG_TYPE_IO, 0, &sc->sc_dma_iot, &sc->sc_dma_ioh, + NULL, &sc->sc_dma_ios) == 0); + sc->sc_dmat = pa->pa_dmat; + if (sc->sc_dma_ok == 0) { + aprint_verbose(", but unused (couldn't map registers)"); + } else { + sc->sc_wdcdev.dma_arg = sc; + sc->sc_wdcdev.dma_init = pciide_dma_init; + sc->sc_wdcdev.dma_start = pciide_dma_start; + sc->sc_wdcdev.dma_finish = pciide_dma_finish; + } + + if (device_cfdata(sc->sc_wdcdev.sc_atac.atac_dev)->cf_flags & + PCIIDE_OPTIONS_NODMA) { + aprint_verbose( + ", but unused (forced off by config file)"); + sc->sc_dma_ok = 0; + } + + if (sc->sc_dma_ok == 0) + return; + + for (chan = 0; chan < 4; chan++) { + pc = &sc->pciide_channels[chan]; + for (reg = 0; reg < IDEDMA_NREGS; reg++) { + size = 4; + if (size > (IDEDMA_SCH_OFFSET - reg)) + size = IDEDMA_SCH_OFFSET - reg; + if (bus_space_subregion(sc->sc_dma_iot, sc->sc_dma_ioh, + IDEDMA_SCH_OFFSET * chan + reg, size, + &pc->dma_iohs[reg]) != 0) { + sc->sc_dma_ok = 0; + aprint_verbose(", but can't subregion offset " + "%d size %lu", + reg, (u_long)size); + return; + } + } + } +} + +static int +via_vt6421_chansetup(struct pciide_softc *sc, int channel) +{ + struct pciide_channel *cp = &sc->pciide_channels[channel]; + + sc->wdc_chanarray[channel] = &cp->ata_channel; + + cp->ata_channel.ch_channel = channel; + cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; + cp->ata_channel.ch_queue = + malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); + cp->ata_channel.ch_ndrive = 2; + if (cp->ata_channel.ch_queue == NULL) { + aprint_error("%s channel %d: " + "can't allocate memory for command queue", + device_xname(sc->sc_wdcdev.sc_atac.atac_dev), channel); + return 0; + } + return 1; +} + +static void via_sata_chip_map_new(struct pciide_softc *sc, - const struct pci_attach_args *pa0) + const struct pci_attach_args *pa) { struct pciide_channel *cp; struct ata_channel *wdc_cp; struct wdc_regs *wdr; - struct pci_attach_args pacopy, *pa; - pcireg_t interface; int channel; pci_intr_handle_t intrhandle; const char *intrstr; int i; - pacopy = *pa0; - pa = &pacopy; - interface = PCI_INTERFACE(pa->pa_class); - - if (via_sata_chip_map_common(sc, pa) == 0) + if (pciide_chipen(sc, pa) == 0) return; - if (interface == 0) { - ATADEBUG_PRINT(("via_sata_chip_map interface == 0\n"), - DEBUG_PROBE); - interface = PCIIDE_INTERFACE_BUS_MASTER_DMA | - PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1); + sc->sc_apo_regbase = APO_VIA_VT6421_REGBASE; + + if (pci_mapreg_map(pa, PCI_BAR(5), PCI_MAPREG_TYPE_IO, 0, + &sc->sc_ba5_st, &sc->sc_ba5_sh, NULL, &sc->sc_ba5_ss) != 0) { + aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, + "couldn't map SATA regs\n"); } + aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, + "bus-master DMA support present"); + via_vt6421_mapreg_dma(sc, pa); + aprint_verbose("\n"); + + sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32; + sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; + if (sc->sc_dma_ok) { + sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA; + sc->sc_wdcdev.irqack = pciide_irqack; + sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; + sc->sc_wdcdev.sc_atac.atac_udma_cap = 6; + } + sc->sc_wdcdev.sc_atac.atac_set_modes = sata_setup_channel; + + sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; + sc->sc_wdcdev.sc_atac.atac_nchannels = 3; + + wdc_allocate_regs(&sc->sc_wdcdev); + if (pci_intr_map(pa, &intrhandle) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, "couldn't map native-PCI interrupt\n"); @@ -1033,9 +1120,9 @@ for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; channel++) { cp = &sc->pciide_channels[channel]; - if (pciide_chansetup(sc, channel, interface) == 0) + if (via_vt6421_chansetup(sc, channel) == 0) continue; - cp->ata_channel.ch_ndrive = 1; + cp->ata_channel.ch_ndrive = 2; wdc_cp = &cp->ata_channel; wdr = CHAN_TO_WDC_REGS(wdc_cp); @@ -1065,9 +1152,8 @@ wdc_cp->ch_channel); continue; } - sc->sc_wdcdev.sc_atac.atac_probe = wdc_sataprobe; - if (pci_mapreg_map(pa, (PCI_MAPREG_START + (4 * (channel))), + if (pci_mapreg_map(pa, PCI_BAR(wdc_cp->ch_channel), PCI_MAPREG_TYPE_IO, 0, &wdr->cmd_iot, &wdr->cmd_baseioh, NULL, &wdr->cmd_ios) != 0) { aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev,