1 /* $NetBSD: toshide.c,v 1.3 2010/11/05 18:07:24 jakllsch 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.3 2010/11/05 18:07:24 jakllsch 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 pcireg_t interface; 118 int channel; 119 120 if (pciide_chipen(sc, pa) == 0) 121 return; 122 123 aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 124 "bus-master DMA support present"); 125 126 pciide_mapreg_dma(sc, pa); 127 aprint_verbose("\n"); 128 129 sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA32 | ATAC_CAP_DATA16; 130 sc->sc_wdcdev.sc_atac.atac_pio_cap = 5; 131 132 if (sc->sc_dma_ok) { 133 sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA; 134 sc->sc_wdcdev.irqack = pciide_irqack; 135 sc->sc_wdcdev.sc_atac.atac_dma_cap = 3; 136 sc->sc_wdcdev.sc_atac.atac_udma_cap = 2; 137 } 138 139 sc->sc_wdcdev.sc_atac.atac_set_modes = piccolo_setup_channel; 140 141 sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; 142 sc->sc_wdcdev.sc_atac.atac_nchannels = 1; 143 /* 144 * XXX one for now. We'll figure out how to talk to the second channel 145 * later, hopefully! Second interface config is via the 146 * "alternate PCI Configuration Space" whatever that is! 147 */ 148 149 interface = PCI_INTERFACE(pa->pa_class); 150 151 wdc_allocate_regs(&sc->sc_wdcdev); 152 153 for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; 154 channel++) { 155 cp = &sc->pciide_channels[channel]; 156 if (pciide_chansetup(sc, channel, interface) == 0) 157 continue; 158 159 pciide_mapchan(pa, cp, interface, pciide_pci_intr); 160 } 161 } 162 163 static void 164 piccolo_setup_channel(struct ata_channel *chp) 165 { 166 struct ata_drive_datas *drvp; 167 struct pciide_channel *cp = CHAN_TO_PCHAN(chp); 168 struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); 169 u_int32_t idedma_ctl; 170 int drive, s; 171 pcireg_t pxdx; 172 #ifdef TOSHIDE_DEBUG 173 pcireg_t pxdx_prime; 174 #endif 175 176 idedma_ctl = 0; 177 178 /* Set up DMA if needed. */ 179 pciide_channel_dma_setup(cp); 180 181 for (drive = 0; drive < 2; drive++) { 182 183 drvp = &chp->ch_drive[drive]; 184 /* If no drive, skip */ 185 if ((drvp->drive_flags & DRIVE) == 0) 186 continue; 187 188 if (drvp->drive_flags & DRIVE_UDMA) { 189 /* use Ultra/DMA */ 190 s = splbio(); 191 drvp->drive_flags &= ~DRIVE_DMA; 192 splx(s); 193 194 /* 195 * Use UDMA - we can go up to mode 2 so no need to 196 * check anything since nearly all drives with UDMA 197 * are mode 2 or faster 198 */ 199 pxdx = pci_conf_read(sc->sc_pc, sc->sc_tag, 200 PICCOLO_DMA_TIMING); 201 pxdx &= PICCOLO_UDMA_MASK; 202 pxdx |= piccolo_udma_times[2]; 203 pci_conf_write(sc->sc_pc, sc->sc_tag, 204 PICCOLO_DMA_TIMING, pxdx); 205 #ifdef TOSHIDE_DEBUG 206 /* XXX sanity check */ 207 pxdx_prime = pci_conf_read(sc->sc_pc, sc->sc_tag, 208 PICCOLO_DMA_TIMING); 209 aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 210 "UDMA want %x, set %x, got %x\n", 211 piccolo_udma_times[2], pxdx, pxdx_prime); 212 #endif 213 idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); 214 215 } 216 else if (drvp->drive_flags & DRIVE_DMA) { 217 /* 218 * Use Multiword DMA 219 */ 220 if (drvp->PIO_mode > (drvp->DMA_mode + 2)) 221 drvp->PIO_mode = drvp->DMA_mode + 2; 222 if (drvp->DMA_mode + 2 > (drvp->PIO_mode)) 223 drvp->DMA_mode = (drvp->PIO_mode > 2) ? 224 drvp->PIO_mode - 2 : 0; 225 226 pxdx = pci_conf_read(sc->sc_pc, sc->sc_tag, 227 PICCOLO_DMA_TIMING); 228 pxdx &= PICCOLO_DMA_MASK; 229 pxdx |= piccolo_mw_dma_times[drvp->DMA_mode]; 230 pci_conf_write(sc->sc_pc, sc->sc_tag, 231 PICCOLO_DMA_TIMING, pxdx); 232 #ifdef TOSHIDE_DEBUG 233 /* XXX sanity check */ 234 pxdx_prime = pci_conf_read(sc->sc_pc, sc->sc_tag, 235 PICCOLO_DMA_TIMING); 236 aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 237 "DMA %d want %x, set %x, got %x\n", 238 drvp->DMA_mode, 239 piccolo_mw_dma_times[drvp->DMA_mode], pxdx, 240 pxdx_prime); 241 #endif 242 idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); 243 244 } 245 else { 246 pxdx = pci_conf_read(sc->sc_pc, sc->sc_tag, 247 PICCOLO_PIO_TIMING); 248 pxdx &= PICCOLO_PIO_MASK; 249 pxdx |= piccolo_pio_times[drvp->PIO_mode]; 250 pci_conf_write(sc->sc_pc, sc->sc_tag, 251 PICCOLO_PIO_TIMING, pxdx); 252 #ifdef TOSHIDE_DEBUG 253 /* XXX sanity check */ 254 pxdx_prime = pci_conf_read(sc->sc_pc, sc->sc_tag, 255 PICCOLO_PIO_TIMING); 256 aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 257 "PIO %d want %x, set %x, got %x\n", drvp->PIO_mode, 258 piccolo_pio_times[drvp->PIO_mode], pxdx, 259 pxdx_prime); 260 #endif 261 } 262 263 } 264 if (idedma_ctl != 0) { 265 /* Add software bits in status register */ 266 bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, 267 idedma_ctl); 268 } 269 } 270