1 /* $NetBSD: acardide.c,v 1.14 2004/08/21 00:28:34 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Izumi Tsutsui. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 32 #include <dev/pci/pcivar.h> 33 #include <dev/pci/pcidevs.h> 34 #include <dev/pci/pciidereg.h> 35 #include <dev/pci/pciidevar.h> 36 #include <dev/pci/pciide_acard_reg.h> 37 38 static void acard_chip_map(struct pciide_softc*, struct pci_attach_args*); 39 static void acard_setup_channel(struct ata_channel*); 40 #if 0 /* XXX !! */ 41 static int acard_pci_intr(void *); 42 #endif 43 44 static int acardide_match(struct device *, struct cfdata *, void *); 45 static void acardide_attach(struct device *, struct device *, void *); 46 47 CFATTACH_DECL(acardide, sizeof(struct pciide_softc), 48 acardide_match, acardide_attach, NULL, NULL); 49 50 static const struct pciide_product_desc pciide_acard_products[] = { 51 { PCI_PRODUCT_ACARD_ATP850U, 52 0, 53 "Acard ATP850U Ultra33 IDE Controller", 54 acard_chip_map, 55 }, 56 { PCI_PRODUCT_ACARD_ATP860, 57 0, 58 "Acard ATP860 Ultra66 IDE Controller", 59 acard_chip_map, 60 }, 61 { PCI_PRODUCT_ACARD_ATP860A, 62 0, 63 "Acard ATP860-A Ultra66 IDE Controller", 64 acard_chip_map, 65 }, 66 { PCI_PRODUCT_ACARD_ATP865, 67 0, 68 "Acard ATP865 Ultra100 IDE Controller", 69 acard_chip_map, 70 }, 71 { PCI_PRODUCT_ACARD_ATP865A, 72 0, 73 "Acard ATP865-A Ultra100 IDE Controller", 74 acard_chip_map, 75 }, 76 { 0, 77 0, 78 NULL, 79 NULL 80 } 81 }; 82 83 static int 84 acardide_match(struct device *parent, struct cfdata *match, void *aux) 85 { 86 struct pci_attach_args *pa = aux; 87 88 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ACARD) { 89 if (pciide_lookup_product(pa->pa_id, pciide_acard_products)) 90 return (2); 91 } 92 return (0); 93 } 94 95 static void 96 acardide_attach(struct device *parent, struct device *self, void *aux) 97 { 98 struct pci_attach_args *pa = aux; 99 struct pciide_softc *sc = (struct pciide_softc *)self; 100 101 pciide_common_attach(sc, pa, 102 pciide_lookup_product(pa->pa_id, pciide_acard_products)); 103 104 } 105 106 #define ACARD_IS_850(sc) \ 107 ((sc)->sc_pp->ide_product == PCI_PRODUCT_ACARD_ATP850U) 108 109 static void 110 acard_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa) 111 { 112 struct pciide_channel *cp; 113 int i; 114 pcireg_t interface; 115 bus_size_t cmdsize, ctlsize; 116 117 if (pciide_chipen(sc, pa) == 0) 118 return; 119 120 /* 121 * when the chip is in native mode it identifies itself as a 122 * 'misc mass storage'. Fake interface in this case. 123 */ 124 if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE) { 125 interface = PCI_INTERFACE(pa->pa_class); 126 } else { 127 interface = PCIIDE_INTERFACE_BUS_MASTER_DMA | 128 PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1); 129 } 130 131 aprint_normal("%s: bus-master DMA support present", 132 sc->sc_wdcdev.sc_atac.atac_dev.dv_xname); 133 pciide_mapreg_dma(sc, pa); 134 aprint_normal("\n"); 135 sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DATA32; 136 137 if (sc->sc_dma_ok) { 138 sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA; 139 sc->sc_wdcdev.irqack = pciide_irqack; 140 } 141 sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; 142 sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; 143 switch (sc->sc_pp->ide_product) { 144 case PCI_PRODUCT_ACARD_ATP860: 145 case PCI_PRODUCT_ACARD_ATP860A: 146 sc->sc_wdcdev.sc_atac.atac_udma_cap = 4; 147 break; 148 case PCI_PRODUCT_ACARD_ATP865: 149 case PCI_PRODUCT_ACARD_ATP865A: 150 sc->sc_wdcdev.sc_atac.atac_udma_cap = 5; 151 break; 152 default: 153 sc->sc_wdcdev.sc_atac.atac_udma_cap = 2; 154 break; 155 } 156 157 sc->sc_wdcdev.sc_atac.atac_set_modes = acard_setup_channel; 158 sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; 159 sc->sc_wdcdev.sc_atac.atac_nchannels = 2; 160 161 wdc_allocate_regs(&sc->sc_wdcdev); 162 163 for (i = 0; i < sc->sc_wdcdev.sc_atac.atac_nchannels; i++) { 164 cp = &sc->pciide_channels[i]; 165 if (pciide_chansetup(sc, i, interface) == 0) 166 continue; 167 pciide_mapchan(pa, cp, interface, &cmdsize, &ctlsize, 168 pciide_pci_intr); 169 } 170 if (!ACARD_IS_850(sc)) { 171 u_int32_t reg; 172 reg = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL); 173 reg &= ~ATP860_CTRL_INT; 174 pci_conf_write(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL, reg); 175 } 176 } 177 178 static void 179 acard_setup_channel(struct ata_channel *chp) 180 { 181 struct ata_drive_datas *drvp; 182 struct atac_softc *atac = chp->ch_atac; 183 struct pciide_channel *cp = CHAN_TO_PCHAN(chp); 184 struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); 185 int channel = chp->ch_channel; 186 int drive, s; 187 u_int32_t idetime, udma_mode; 188 u_int32_t idedma_ctl; 189 190 /* setup DMA if needed */ 191 pciide_channel_dma_setup(cp); 192 193 if (ACARD_IS_850(sc)) { 194 idetime = 0; 195 udma_mode = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP850_UDMA); 196 udma_mode &= ~ATP850_UDMA_MASK(channel); 197 } else { 198 idetime = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP860_IDETIME); 199 idetime &= ~ATP860_SETTIME_MASK(channel); 200 udma_mode = pci_conf_read(sc->sc_pc, sc->sc_tag, ATP860_UDMA); 201 udma_mode &= ~ATP860_UDMA_MASK(channel); 202 203 /* check 80 pins cable */ 204 if ((chp->ch_drive[0].drive_flags & DRIVE_UDMA) || 205 (chp->ch_drive[1].drive_flags & DRIVE_UDMA)) { 206 if (pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL) 207 & ATP860_CTRL_80P(chp->ch_channel)) { 208 if (chp->ch_drive[0].UDMA_mode > 2) 209 chp->ch_drive[0].UDMA_mode = 2; 210 if (chp->ch_drive[1].UDMA_mode > 2) 211 chp->ch_drive[1].UDMA_mode = 2; 212 } 213 } 214 } 215 216 idedma_ctl = 0; 217 218 /* Per drive settings */ 219 for (drive = 0; drive < 2; drive++) { 220 drvp = &chp->ch_drive[drive]; 221 /* If no drive, skip */ 222 if ((drvp->drive_flags & DRIVE) == 0) 223 continue; 224 /* add timing values, setup DMA if needed */ 225 if ((atac->atac_cap & ATAC_CAP_UDMA) && 226 (drvp->drive_flags & DRIVE_UDMA)) { 227 /* use Ultra/DMA */ 228 if (ACARD_IS_850(sc)) { 229 idetime |= ATP850_SETTIME(drive, 230 acard_act_udma[drvp->UDMA_mode], 231 acard_rec_udma[drvp->UDMA_mode]); 232 udma_mode |= ATP850_UDMA_MODE(channel, drive, 233 acard_udma_conf[drvp->UDMA_mode]); 234 } else { 235 idetime |= ATP860_SETTIME(channel, drive, 236 acard_act_udma[drvp->UDMA_mode], 237 acard_rec_udma[drvp->UDMA_mode]); 238 udma_mode |= ATP860_UDMA_MODE(channel, drive, 239 acard_udma_conf[drvp->UDMA_mode]); 240 } 241 idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); 242 } else if ((atac->atac_cap & ATAC_CAP_DMA) && 243 (drvp->drive_flags & DRIVE_DMA)) { 244 /* use Multiword DMA */ 245 s = splbio(); 246 drvp->drive_flags &= ~DRIVE_UDMA; 247 splx(s); 248 if (ACARD_IS_850(sc)) { 249 idetime |= ATP850_SETTIME(drive, 250 acard_act_dma[drvp->DMA_mode], 251 acard_rec_dma[drvp->DMA_mode]); 252 } else { 253 idetime |= ATP860_SETTIME(channel, drive, 254 acard_act_dma[drvp->DMA_mode], 255 acard_rec_dma[drvp->DMA_mode]); 256 } 257 idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); 258 } else { 259 /* PIO only */ 260 s = splbio(); 261 drvp->drive_flags &= ~(DRIVE_UDMA | DRIVE_DMA); 262 splx(s); 263 if (ACARD_IS_850(sc)) { 264 idetime |= ATP850_SETTIME(drive, 265 acard_act_pio[drvp->PIO_mode], 266 acard_rec_pio[drvp->PIO_mode]); 267 } else { 268 idetime |= ATP860_SETTIME(channel, drive, 269 acard_act_pio[drvp->PIO_mode], 270 acard_rec_pio[drvp->PIO_mode]); 271 } 272 pci_conf_write(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL, 273 pci_conf_read(sc->sc_pc, sc->sc_tag, ATP8x0_CTRL) 274 | ATP8x0_CTRL_EN(channel)); 275 } 276 } 277 278 if (idedma_ctl != 0) { 279 /* Add software bits in status register */ 280 bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, 281 idedma_ctl); 282 } 283 284 if (ACARD_IS_850(sc)) { 285 pci_conf_write(sc->sc_pc, sc->sc_tag, 286 ATP850_IDETIME(channel), idetime); 287 pci_conf_write(sc->sc_pc, sc->sc_tag, ATP850_UDMA, udma_mode); 288 } else { 289 pci_conf_write(sc->sc_pc, sc->sc_tag, ATP860_IDETIME, idetime); 290 pci_conf_write(sc->sc_pc, sc->sc_tag, ATP860_UDMA, udma_mode); 291 } 292 } 293 294 #if 0 /* XXX !! */ 295 static int 296 acard_pci_intr(void *arg) 297 { 298 struct pciide_softc *sc = arg; 299 struct pciide_channel *cp; 300 struct ata_channel *wdc_cp; 301 int rv = 0; 302 int dmastat, i, crv; 303 304 for (i = 0; i < sc->sc_wdcdev.sc_atac.atac_nchannels; i++) { 305 cp = &sc->pciide_channels[i]; 306 dmastat = bus_space_read_1(sc->sc_dma_iot, 307 cp->dma_iohs[IDEDMA_CTL], 0); 308 if ((dmastat & IDEDMA_CTL_INTR) == 0) 309 continue; 310 wdc_cp = &cp->ata_channel; 311 if ((wdc_cp->ch_flags & ATACH_IRQ_WAIT) == 0) { 312 (void)wdcintr(wdc_cp); 313 bus_space_write_1(sc->sc_dma_iot, 314 cp->dma_iohs[IDEDMA_CTL], 0, dmastat); 315 continue; 316 } 317 crv = wdcintr(wdc_cp); 318 if (crv == 0) { 319 printf("%s:%d: bogus intr\n", 320 sc->sc_wdcdev.sc_atac.atac_dev.dv_xname, i); 321 bus_space_write_1(sc->sc_dma_iot, 322 cp->dma_iohs[IDEDMA_CTL], 0, dmastat); 323 } else if (crv == 1) 324 rv = 1; 325 else if (rv == 0) 326 rv = crv; 327 } 328 return rv; 329 } 330 #endif 331