1 /* $NetBSD: toshide.c,v 1.2 2009/09/20 01:12:30 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: toshide.c,v 1.2 2009/09/20 01:12:30 christos Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 35 #include <dev/pci/pcivar.h> 36 #include <dev/pci/pcidevs.h> 37 #include <dev/pci/pciidereg.h> 38 #include <dev/pci/pciidevar.h> 39 #include <dev/pci/pciide_piccolo_reg.h> 40 41 static void piccolo_chip_map(struct pciide_softc *, struct pci_attach_args *); 42 static void piccolo_setup_channel(struct ata_channel *); 43 44 static int piccolo_match(device_t, cfdata_t, void *); 45 static void piccolo_attach(device_t, device_t, void *); 46 47 CFATTACH_DECL_NEW(toshide, sizeof(struct pciide_softc), 48 piccolo_match, piccolo_attach, NULL, NULL); 49 50 static const struct pciide_product_desc pciide_toshiba2_products[] = { 51 { 52 PCI_PRODUCT_TOSHIBA2_PICCOLO, 53 0, 54 "Toshiba Piccolo IDE controller", 55 piccolo_chip_map, 56 }, 57 { 58 PCI_PRODUCT_TOSHIBA2_PICCOLO2, 59 0, 60 "Toshiba Piccolo 2 IDE controller", 61 piccolo_chip_map, 62 }, 63 { 64 PCI_PRODUCT_TOSHIBA2_PICCOLO3, 65 0, 66 "Toshiba Piccolo 3 IDE controller", 67 piccolo_chip_map, 68 }, 69 { 70 PCI_PRODUCT_TOSHIBA2_PICCOLO5, 71 0, 72 "Toshiba Piccolo 5 IDE controller", 73 piccolo_chip_map, 74 }, 75 { 76 0, 77 0, 78 NULL, 79 NULL, 80 } 81 }; 82 83 static int 84 piccolo_match(device_t parent, cfdata_t match, void *aux) 85 { 86 struct pci_attach_args *pa = aux; 87 88 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TOSHIBA2) { 89 if (pciide_lookup_product(pa->pa_id, pciide_toshiba2_products)) 90 return 2; 91 } 92 return 0; 93 } 94 95 static void 96 piccolo_attach(device_t parent, device_t self, void *aux) 97 { 98 struct pci_attach_args *pa = aux; 99 struct pciide_softc *sc = device_private(self); 100 const struct pciide_product_desc *pp; 101 102 sc->sc_wdcdev.sc_atac.atac_dev = self; 103 104 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TOSHIBA2) 105 pp = pciide_lookup_product(pa->pa_id, pciide_toshiba2_products); 106 else 107 pp = NULL; 108 if (pp == NULL) 109 panic("toshide_attach"); 110 pciide_common_attach(sc, pa, pp); 111 } 112 113 static void 114 piccolo_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa) 115 { 116 struct pciide_channel *cp; 117 bus_size_t cmdsize, ctlsize; 118 pcireg_t interface; 119 int channel; 120 121 if (pciide_chipen(sc, pa) == 0) 122 return; 123 124 aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 125 "bus-master DMA support present"); 126 127 pciide_mapreg_dma(sc, pa); 128 aprint_verbose("\n"); 129 130 sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA32 | ATAC_CAP_DATA16; 131 sc->sc_wdcdev.sc_atac.atac_pio_cap = 5; 132 133 if (sc->sc_dma_ok) { 134 sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA; 135 sc->sc_wdcdev.irqack = pciide_irqack; 136 sc->sc_wdcdev.sc_atac.atac_dma_cap = 3; 137 sc->sc_wdcdev.sc_atac.atac_udma_cap = 2; 138 } 139 140 sc->sc_wdcdev.sc_atac.atac_set_modes = piccolo_setup_channel; 141 142 sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; 143 sc->sc_wdcdev.sc_atac.atac_nchannels = 1; 144 /* 145 * XXX one for now. We'll figure out how to talk to the second channel 146 * later, hopefully! Second interface config is via the 147 * "alternate PCI Configuration Space" whatever that is! 148 */ 149 150 interface = PCI_INTERFACE(pa->pa_class); 151 152 wdc_allocate_regs(&sc->sc_wdcdev); 153 154 for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; 155 channel++) { 156 cp = &sc->pciide_channels[channel]; 157 if (pciide_chansetup(sc, channel, interface) == 0) 158 continue; 159 160 pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize, 161 pciide_pci_intr); 162 } 163 } 164 165 static void 166 piccolo_setup_channel(struct ata_channel *chp) 167 { 168 struct ata_drive_datas *drvp; 169 struct pciide_channel *cp = CHAN_TO_PCHAN(chp); 170 struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); 171 u_int32_t idedma_ctl; 172 int drive, s; 173 pcireg_t pxdx; 174 #ifdef TOSHIDE_DEBUG 175 pcireg_t pxdx_prime; 176 #endif 177 178 idedma_ctl = 0; 179 180 /* Set up DMA if needed. */ 181 pciide_channel_dma_setup(cp); 182 183 for (drive = 0; drive < 2; drive++) { 184 185 drvp = &chp->ch_drive[drive]; 186 /* If no drive, skip */ 187 if ((drvp->drive_flags & DRIVE) == 0) 188 continue; 189 190 if (drvp->drive_flags & DRIVE_UDMA) { 191 /* use Ultra/DMA */ 192 s = splbio(); 193 drvp->drive_flags &= ~DRIVE_DMA; 194 splx(s); 195 196 /* 197 * Use UDMA - we can go up to mode 2 so no need to 198 * check anything since nearly all drives with UDMA 199 * are mode 2 or faster 200 */ 201 pxdx = pci_conf_read(sc->sc_pc, sc->sc_tag, 202 PICCOLO_DMA_TIMING); 203 pxdx &= PICCOLO_UDMA_MASK; 204 pxdx |= piccolo_udma_times[2]; 205 pci_conf_write(sc->sc_pc, sc->sc_tag, 206 PICCOLO_DMA_TIMING, pxdx); 207 #ifdef TOSHIDE_DEBUG 208 /* XXX sanity check */ 209 pxdx_prime = pci_conf_read(sc->sc_pc, sc->sc_tag, 210 PICCOLO_DMA_TIMING); 211 aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 212 "UDMA want %x, set %x, got %x\n", 213 piccolo_udma_times[2], pxdx, pxdx_prime); 214 #endif 215 idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); 216 217 } 218 else if (drvp->drive_flags & DRIVE_DMA) { 219 /* 220 * Use Multiword DMA 221 */ 222 if (drvp->PIO_mode > (drvp->DMA_mode + 2)) 223 drvp->PIO_mode = drvp->DMA_mode + 2; 224 if (drvp->DMA_mode + 2 > (drvp->PIO_mode)) 225 drvp->DMA_mode = (drvp->PIO_mode > 2) ? 226 drvp->PIO_mode - 2 : 0; 227 228 pxdx = pci_conf_read(sc->sc_pc, sc->sc_tag, 229 PICCOLO_DMA_TIMING); 230 pxdx &= PICCOLO_DMA_MASK; 231 pxdx |= piccolo_mw_dma_times[drvp->DMA_mode]; 232 pci_conf_write(sc->sc_pc, sc->sc_tag, 233 PICCOLO_DMA_TIMING, pxdx); 234 #ifdef TOSHIDE_DEBUG 235 /* XXX sanity check */ 236 pxdx_prime = pci_conf_read(sc->sc_pc, sc->sc_tag, 237 PICCOLO_DMA_TIMING); 238 aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 239 "DMA %d want %x, set %x, got %x\n", 240 drvp->DMA_mode, 241 piccolo_mw_dma_times[drvp->DMA_mode], pxdx, 242 pxdx_prime); 243 #endif 244 idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); 245 246 } 247 else { 248 pxdx = pci_conf_read(sc->sc_pc, sc->sc_tag, 249 PICCOLO_PIO_TIMING); 250 pxdx &= PICCOLO_PIO_MASK; 251 pxdx |= piccolo_pio_times[drvp->PIO_mode]; 252 pci_conf_write(sc->sc_pc, sc->sc_tag, 253 PICCOLO_PIO_TIMING, pxdx); 254 #ifdef TOSHIDE_DEBUG 255 /* XXX sanity check */ 256 pxdx_prime = pci_conf_read(sc->sc_pc, sc->sc_tag, 257 PICCOLO_PIO_TIMING); 258 aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 259 "PIO %d want %x, set %x, got %x\n", drvp->PIO_mode, 260 piccolo_pio_times[drvp->PIO_mode], pxdx, 261 pxdx_prime); 262 #endif 263 } 264 265 } 266 if (idedma_ctl != 0) { 267 /* Add software bits in status register */ 268 bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, 269 idedma_ctl); 270 } 271 } 272