1 /* $NetBSD: iteide.c,v 1.10 2008/04/10 19:13:37 cegger 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.10 2008/04/10 19:13:37 cegger 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*, 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, NULL, 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, struct pci_attach_args *pa) 98 { 99 struct pciide_channel *cp; 100 int channel; 101 pcireg_t interface; 102 bus_size_t cmdsize, ctlsize; 103 pcireg_t cfg, modectl; 104 105 /* fake interface since IT8212 claims to be a RAID device */ 106 interface = PCIIDE_INTERFACE_BUS_MASTER_DMA | 107 PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1); 108 109 cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG); 110 modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE); 111 ATADEBUG_PRINT(("%s: cfg=0x%x, modectl=0x%x\n", 112 device_xname(sc->sc_wdcdev.sc_atac.atac_dev), cfg & IT_CFG_MASK, 113 modectl & IT_MODE_MASK), DEBUG_PROBE); 114 115 if (pciide_chipen(sc, pa) == 0) 116 return; 117 118 aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 119 "bus-master DMA support present"); 120 pciide_mapreg_dma(sc, pa); 121 aprint_verbose("\n"); 122 123 sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DATA32; 124 125 if (sc->sc_dma_ok) { 126 sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA; 127 sc->sc_wdcdev.irqack = pciide_irqack; 128 } 129 sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; 130 sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; 131 sc->sc_wdcdev.sc_atac.atac_udma_cap = 6; 132 133 sc->sc_wdcdev.sc_atac.atac_set_modes = ite_setup_channel; 134 sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; 135 sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS; 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, &cmdsize, &ctlsize, 153 pciide_pci_intr); 154 } 155 /* Re-read configuration registers after channels setup */ 156 cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG); 157 modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE); 158 ATADEBUG_PRINT(("%s: cfg=0x%x, modectl=0x%x\n", 159 device_xname(sc->sc_wdcdev.sc_atac.atac_dev), cfg & IT_CFG_MASK, 160 modectl & IT_MODE_MASK), DEBUG_PROBE); 161 } 162 163 static void 164 ite_setup_channel(struct ata_channel *chp) 165 { 166 struct ata_drive_datas *drvp; 167 int drive, mode = 0; 168 u_int32_t idedma_ctl; 169 struct pciide_channel *cp = CHAN_TO_PCHAN(chp); 170 struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); 171 int channel = chp->ch_channel; 172 pcireg_t cfg, modectl; 173 pcireg_t tim; 174 175 cfg = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_CFG); 176 modectl = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_MODE); 177 tim = pci_conf_read(sc->sc_pc, sc->sc_tag, IT_TIM(channel)); 178 ATADEBUG_PRINT(("%s:%d: tim=0x%x\n", 179 device_xname(sc->sc_wdcdev.sc_atac.atac_dev), 180 channel, tim), DEBUG_PROBE); 181 182 /* Setup DMA if needed */ 183 pciide_channel_dma_setup(cp); 184 185 /* Clear all bits for this channel */ 186 idedma_ctl = 0; 187 188 /* Per channel settings */ 189 for (drive = 0; drive < 2; drive++) { 190 drvp = &chp->ch_drive[drive]; 191 192 /* If no drive, skip */ 193 if ((drvp->drive_flags & DRIVE) == 0) 194 continue; 195 196 if ((chp->ch_atac->atac_cap & ATAC_CAP_UDMA) != 0 && 197 (drvp->drive_flags & DRIVE_UDMA) != 0) { 198 /* Setup UltraDMA mode */ 199 drvp->drive_flags &= ~DRIVE_DMA; 200 modectl &= ~IT_MODE_DMA(channel, drive); 201 202 #if 0 203 /* Check cable, only works in CPU firmware mode */ 204 if (drvp->UDMA_mode > 2 && 205 (cfg & IT_CFG_CABLE(channel, drive)) == 0) { 206 ATADEBUG_PRINT(("(%s:%d:%d): " 207 "80-wire cable not detected\n", 208 device_xname(&sc->sc_wdcdev.sc_atac.atac_dev), 209 channel, drive), DEBUG_PROBE); 210 drvp->UDMA_mode = 2; 211 } 212 #endif 213 214 if (drvp->UDMA_mode >= 5) 215 tim |= IT_TIM_UDMA5(drive); 216 else 217 tim &= ~IT_TIM_UDMA5(drive); 218 219 mode = drvp->PIO_mode; 220 } else if ((chp->ch_atac->atac_cap & ATAC_CAP_DMA) != 0 && 221 (drvp->drive_flags & DRIVE_DMA) != 0) { 222 /* Setup multiword DMA mode */ 223 drvp->drive_flags &= ~DRIVE_UDMA; 224 modectl |= IT_MODE_DMA(channel, drive); 225 226 /* mode = min(pio, dma + 2) */ 227 if (drvp->PIO_mode <= (drvp->DMA_mode + 2)) 228 mode = drvp->PIO_mode; 229 else 230 mode = drvp->DMA_mode + 2; 231 } else { 232 goto pio; 233 } 234 idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); 235 236 pio: 237 /* Setup PIO mode */ 238 if (mode <= 2) { 239 drvp->DMA_mode = 0; 240 drvp->PIO_mode = 0; 241 mode = 0; 242 } else { 243 drvp->PIO_mode = mode; 244 drvp->DMA_mode = mode - 2; 245 } 246 247 /* Enable IORDY if PIO mode >= 3 */ 248 if (drvp->PIO_mode >= 3) 249 cfg |= IT_CFG_IORDY(channel); 250 } 251 252 ATADEBUG_PRINT(("%s: tim=0x%x\n", 253 device_xname(sc->sc_wdcdev.sc_atac.atac_dev), tim), DEBUG_PROBE); 254 255 pci_conf_write(sc->sc_pc, sc->sc_tag, IT_CFG, cfg); 256 pci_conf_write(sc->sc_pc, sc->sc_tag, IT_MODE, modectl); 257 pci_conf_write(sc->sc_pc, sc->sc_tag, IT_TIM(channel), tim); 258 259 if (idedma_ctl != 0) { 260 /* Add software bits in status register */ 261 bus_space_write_1(sc->sc_dma_iot, 262 cp->dma_iohs[IDEDMA_CTL], 0, idedma_ctl); 263 } 264 } 265