1 /* $NetBSD: iteide.c,v 1.19 2013/10/07 19:51:55 jakllsch Exp $ */ 2 3 /* 4 * Copyright (c) 2004 The NetBSD Foundation, Inc. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Grant Beattie. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: iteide.c,v 1.19 2013/10/07 19:51:55 jakllsch Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 39 #include <dev/pci/pcivar.h> 40 #include <dev/pci/pcidevs.h> 41 #include <dev/pci/pciidereg.h> 42 #include <dev/pci/pciidevar.h> 43 #include <dev/pci/pciide_ite_reg.h> 44 45 static void ite_chip_map(struct pciide_softc*, const struct pci_attach_args*); 46 static void ite_setup_channel(struct ata_channel*); 47 48 static int iteide_match(device_t, cfdata_t, void *); 49 static void iteide_attach(device_t, device_t, void *); 50 51 CFATTACH_DECL_NEW(iteide, sizeof(struct pciide_softc), 52 iteide_match, iteide_attach, pciide_detach, NULL); 53 54 static const struct pciide_product_desc pciide_ite_products[] = { 55 { PCI_PRODUCT_ITE_IT8211, 56 0, 57 "Integrated Technology Express IDE controller", 58 ite_chip_map, 59 }, 60 { PCI_PRODUCT_ITE_IT8212, 61 0, 62 "Integrated Technology Express IDE controller", 63 ite_chip_map, 64 }, 65 { 0, 66 0, 67 NULL, 68 NULL 69 } 70 }; 71 72 static int 73 iteide_match(device_t parent, cfdata_t match, void *aux) 74 { 75 struct pci_attach_args *pa = aux; 76 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ITE && 77 PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE) { 78 if (pciide_lookup_product(pa->pa_id, pciide_ite_products)) 79 return (2); 80 } 81 return (0); 82 } 83 84 static void 85 iteide_attach(device_t parent, device_t self, void *aux) 86 { 87 struct pci_attach_args *pa = aux; 88 struct pciide_softc *sc = device_private(self); 89 90 sc->sc_wdcdev.sc_atac.atac_dev = self; 91 92 pciide_common_attach(sc, pa, 93 pciide_lookup_product(pa->pa_id, pciide_ite_products)); 94 } 95 96 static void 97 ite_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa) 98 { 99 struct pciide_channel *cp; 100 int channel; 101 pcireg_t interface; 102 pcireg_t cfg, modectl; 103 104 /* fake interface since IT8212 claims to be a RAID device */ 105 interface = PCIIDE_INTERFACE_BUS_MASTER_DMA | 106 PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1); 107 108 cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG); 109 modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE); 110 ATADEBUG_PRINT(("%s: cfg=0x%x, modectl=0x%x\n", 111 device_xname(sc->sc_wdcdev.sc_atac.atac_dev), cfg & IT_CFG_MASK, 112 modectl & IT_MODE_MASK), DEBUG_PROBE); 113 114 if (pciide_chipen(sc, pa) == 0) 115 return; 116 117 aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 118 "bus-master DMA support present"); 119 pciide_mapreg_dma(sc, pa); 120 aprint_verbose("\n"); 121 122 sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DATA32; 123 124 if (sc->sc_dma_ok) { 125 sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA; 126 sc->sc_wdcdev.irqack = pciide_irqack; 127 } 128 sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; 129 sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; 130 sc->sc_wdcdev.sc_atac.atac_udma_cap = 6; 131 132 sc->sc_wdcdev.sc_atac.atac_set_modes = ite_setup_channel; 133 sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; 134 sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS; 135 sc->sc_wdcdev.wdc_maxdrives = 2; 136 137 wdc_allocate_regs(&sc->sc_wdcdev); 138 139 /* Disable RAID */ 140 modectl &= ~IT_MODE_RAID1; 141 /* Disable CPU firmware mode */ 142 modectl &= ~IT_MODE_CPU; 143 144 pci_conf_write(sc->sc_pc, sc->sc_tag, IT_MODE, modectl); 145 146 for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; channel++) { 147 cp = &sc->pciide_channels[channel]; 148 149 if (pciide_chansetup(sc, channel, interface) == 0) 150 continue; 151 152 pciide_mapchan(pa, cp, interface, pciide_pci_intr); 153 } 154 /* Re-read configuration registers after channels setup */ 155 cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG); 156 modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE); 157 ATADEBUG_PRINT(("%s: cfg=0x%x, modectl=0x%x\n", 158 device_xname(sc->sc_wdcdev.sc_atac.atac_dev), cfg & IT_CFG_MASK, 159 modectl & IT_MODE_MASK), DEBUG_PROBE); 160 } 161 162 static void 163 ite_setup_channel(struct ata_channel *chp) 164 { 165 struct ata_drive_datas *drvp; 166 int drive, mode = 0; 167 u_int32_t idedma_ctl; 168 struct pciide_channel *cp = CHAN_TO_PCHAN(chp); 169 struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); 170 int channel = chp->ch_channel; 171 pcireg_t cfg, modectl; 172 pcireg_t tim; 173 174 cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG); 175 modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE); 176 tim = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_TIM(channel)); 177 ATADEBUG_PRINT(("%s:%d: tim=0x%x\n", 178 device_xname(sc->sc_wdcdev.sc_atac.atac_dev), 179 channel, tim), DEBUG_PROBE); 180 181 /* Setup DMA if needed */ 182 pciide_channel_dma_setup(cp); 183 184 /* Clear all bits for this channel */ 185 idedma_ctl = 0; 186 187 /* Per channel settings */ 188 for (drive = 0; drive < 2; drive++) { 189 drvp = &chp->ch_drive[drive]; 190 191 /* If no drive, skip */ 192 if (drvp->drive_type == ATA_DRIVET_NONE) 193 continue; 194 195 if ((chp->ch_atac->atac_cap & ATAC_CAP_UDMA) != 0 && 196 (drvp->drive_flags & ATA_DRIVE_UDMA) != 0) { 197 /* Setup UltraDMA mode */ 198 drvp->drive_flags &= ~ATA_DRIVE_DMA; 199 modectl &= ~IT_MODE_DMA(channel, drive); 200 201 #if 0 202 /* Check cable, only works in CPU firmware mode */ 203 if (drvp->UDMA_mode > 2 && 204 (cfg & IT_CFG_CABLE(channel, drive)) == 0) { 205 ATADEBUG_PRINT(("(%s:%d:%d): " 206 "80-wire cable not detected\n", 207 device_xname(sc->sc_wdcdev.sc_atac.atac_dev), 208 channel, drive), DEBUG_PROBE); 209 drvp->UDMA_mode = 2; 210 } 211 #endif 212 213 if (drvp->UDMA_mode >= 5) 214 tim |= IT_TIM_UDMA5(drive); 215 else 216 tim &= ~IT_TIM_UDMA5(drive); 217 218 mode = drvp->PIO_mode; 219 } else if ((chp->ch_atac->atac_cap & ATAC_CAP_DMA) != 0 && 220 (drvp->drive_flags & ATA_DRIVE_DMA) != 0) { 221 /* Setup multiword DMA mode */ 222 drvp->drive_flags &= ~ATA_DRIVE_UDMA; 223 modectl |= IT_MODE_DMA(channel, drive); 224 225 /* mode = min(pio, dma + 2) */ 226 if (drvp->PIO_mode <= (drvp->DMA_mode + 2)) 227 mode = drvp->PIO_mode; 228 else 229 mode = drvp->DMA_mode + 2; 230 } else { 231 goto pio; 232 } 233 idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); 234 235 pio: 236 /* Setup PIO mode */ 237 if (mode <= 2) { 238 drvp->DMA_mode = 0; 239 drvp->PIO_mode = 0; 240 mode = 0; 241 } else { 242 drvp->PIO_mode = mode; 243 drvp->DMA_mode = mode - 2; 244 } 245 246 /* Enable IORDY if PIO mode >= 3 */ 247 if (drvp->PIO_mode >= 3) 248 cfg |= IT_CFG_IORDY(channel); 249 } 250 251 ATADEBUG_PRINT(("%s: tim=0x%x\n", 252 device_xname(sc->sc_wdcdev.sc_atac.atac_dev), tim), DEBUG_PROBE); 253 254 pci_conf_write(sc->sc_pc, sc->sc_tag, IT_CFG, cfg); 255 pci_conf_write(sc->sc_pc, sc->sc_tag, IT_MODE, modectl); 256 pci_conf_write(sc->sc_pc, sc->sc_tag, IT_TIM(channel), tim); 257 258 if (idedma_ctl != 0) { 259 /* Add software bits in status register */ 260 bus_space_write_1(sc->sc_dma_iot, 261 cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); 262 } 263 } 264