1 1.47 andvar /* $NetBSD: cmdide.c,v 1.47 2021/12/26 16:08:21 andvar Exp $ */ 2 1.1 bouyer 3 1.1 bouyer /* 4 1.1 bouyer * Copyright (c) 1999, 2000, 2001 Manuel Bouyer. 5 1.1 bouyer * 6 1.1 bouyer * Redistribution and use in source and binary forms, with or without 7 1.1 bouyer * modification, are permitted provided that the following conditions 8 1.1 bouyer * are met: 9 1.1 bouyer * 1. Redistributions of source code must retain the above copyright 10 1.1 bouyer * notice, this list of conditions and the following disclaimer. 11 1.1 bouyer * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 bouyer * notice, this list of conditions and the following disclaimer in the 13 1.1 bouyer * documentation and/or other materials provided with the distribution. 14 1.1 bouyer * 15 1.1 bouyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.1 bouyer * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 1.1 bouyer * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 1.18 perry * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 1.1 bouyer * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 1.1 bouyer * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 1.1 bouyer * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 1.1 bouyer * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 1.1 bouyer * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 1.1 bouyer * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 1.1 bouyer */ 26 1.1 bouyer 27 1.19 lukem #include <sys/cdefs.h> 28 1.47 andvar __KERNEL_RCSID(0, "$NetBSD: cmdide.c,v 1.47 2021/12/26 16:08:21 andvar Exp $"); 29 1.19 lukem 30 1.1 bouyer #include <sys/param.h> 31 1.1 bouyer #include <sys/systm.h> 32 1.43 jdolecek #include <sys/atomic.h> 33 1.1 bouyer 34 1.1 bouyer #include <dev/pci/pcivar.h> 35 1.1 bouyer #include <dev/pci/pcidevs.h> 36 1.1 bouyer #include <dev/pci/pciidereg.h> 37 1.1 bouyer #include <dev/pci/pciidevar.h> 38 1.1 bouyer #include <dev/pci/pciide_cmd_reg.h> 39 1.1 bouyer 40 1.43 jdolecek #define CMDIDE_ACT_CHANNEL_NONE 0xff 41 1.1 bouyer 42 1.28 cube static int cmdide_match(device_t, cfdata_t, void *); 43 1.28 cube static void cmdide_attach(device_t, device_t, void *); 44 1.1 bouyer 45 1.28 cube CFATTACH_DECL_NEW(cmdide, sizeof(struct pciide_softc), 46 1.31 jakllsch cmdide_match, cmdide_attach, pciide_detach, NULL); 47 1.1 bouyer 48 1.32 dyoung static void cmd_chip_map(struct pciide_softc*, const struct pci_attach_args*); 49 1.32 dyoung static void cmd0643_9_chip_map(struct pciide_softc*, 50 1.32 dyoung const struct pci_attach_args*); 51 1.14 thorpej static void cmd0643_9_setup_channel(struct ata_channel*); 52 1.32 dyoung static void cmd_channel_map(const struct pci_attach_args *, 53 1.32 dyoung struct pciide_softc *, int); 54 1.43 jdolecek static int cmd064x_claim_hw(struct ata_channel *, int); 55 1.43 jdolecek static void cmd064x_free_hw(struct ata_channel *); 56 1.2 thorpej static int cmd_pci_intr(void *); 57 1.14 thorpej static void cmd646_9_irqack(struct ata_channel *); 58 1.32 dyoung static void cmd680_chip_map(struct pciide_softc*, 59 1.32 dyoung const struct pci_attach_args*); 60 1.14 thorpej static void cmd680_setup_channel(struct ata_channel*); 61 1.32 dyoung static void cmd680_channel_map(const struct pci_attach_args *, 62 1.32 dyoung struct pciide_softc *, int); 63 1.1 bouyer 64 1.40 jdolecek /* Older CMD64X doesn't have independent channels */ 65 1.2 thorpej static const struct pciide_product_desc pciide_cmd_products[] = { 66 1.1 bouyer { PCI_PRODUCT_CMDTECH_640, 67 1.40 jdolecek IDE_SHARED_CHANNELS, 68 1.1 bouyer "CMD Technology PCI0640", 69 1.1 bouyer cmd_chip_map 70 1.1 bouyer }, 71 1.1 bouyer { PCI_PRODUCT_CMDTECH_643, 72 1.40 jdolecek IDE_SHARED_CHANNELS, 73 1.1 bouyer "CMD Technology PCI0643", 74 1.1 bouyer cmd0643_9_chip_map, 75 1.1 bouyer }, 76 1.1 bouyer { PCI_PRODUCT_CMDTECH_646, 77 1.40 jdolecek IDE_SHARED_CHANNELS, 78 1.1 bouyer "CMD Technology PCI0646", 79 1.1 bouyer cmd0643_9_chip_map, 80 1.1 bouyer }, 81 1.1 bouyer { PCI_PRODUCT_CMDTECH_648, 82 1.40 jdolecek IDE_SHARED_CHANNELS, 83 1.1 bouyer "CMD Technology PCI0648", 84 1.1 bouyer cmd0643_9_chip_map, 85 1.1 bouyer }, 86 1.1 bouyer { PCI_PRODUCT_CMDTECH_649, 87 1.3 mycroft 0, 88 1.1 bouyer "CMD Technology PCI0649", 89 1.1 bouyer cmd0643_9_chip_map, 90 1.1 bouyer }, 91 1.1 bouyer { PCI_PRODUCT_CMDTECH_680, 92 1.42 jdolecek 0, 93 1.1 bouyer "Silicon Image 0680", 94 1.1 bouyer cmd680_chip_map, 95 1.1 bouyer }, 96 1.1 bouyer { 0, 97 1.1 bouyer 0, 98 1.1 bouyer NULL, 99 1.1 bouyer NULL 100 1.1 bouyer } 101 1.1 bouyer }; 102 1.1 bouyer 103 1.2 thorpej static int 104 1.28 cube cmdide_match(device_t parent, cfdata_t match, void *aux) 105 1.1 bouyer { 106 1.1 bouyer struct pci_attach_args *pa = aux; 107 1.1 bouyer 108 1.1 bouyer if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CMDTECH) { 109 1.1 bouyer if (pciide_lookup_product(pa->pa_id, pciide_cmd_products)) 110 1.1 bouyer return (2); 111 1.1 bouyer } 112 1.1 bouyer return (0); 113 1.1 bouyer } 114 1.1 bouyer 115 1.2 thorpej static void 116 1.28 cube cmdide_attach(device_t parent, device_t self, void *aux) 117 1.1 bouyer { 118 1.1 bouyer struct pci_attach_args *pa = aux; 119 1.28 cube struct pciide_softc *sc = device_private(self); 120 1.28 cube 121 1.28 cube sc->sc_wdcdev.sc_atac.atac_dev = self; 122 1.1 bouyer 123 1.1 bouyer pciide_common_attach(sc, pa, 124 1.1 bouyer pciide_lookup_product(pa->pa_id, pciide_cmd_products)); 125 1.1 bouyer 126 1.1 bouyer } 127 1.1 bouyer 128 1.2 thorpej static void 129 1.32 dyoung cmd_channel_map(const struct pci_attach_args *pa, struct pciide_softc *sc, 130 1.2 thorpej int channel) 131 1.1 bouyer { 132 1.1 bouyer struct pciide_channel *cp = &sc->pciide_channels[channel]; 133 1.1 bouyer u_int8_t ctrl = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_CTRL); 134 1.40 jdolecek int interface; 135 1.40 jdolecek bool one_channel = ISSET(sc->sc_pp->ide_flags, IDE_SHARED_CHANNELS); 136 1.1 bouyer 137 1.18 perry /* 138 1.1 bouyer * The 0648/0649 can be told to identify as a RAID controller. 139 1.1 bouyer * In this case, we have to fake interface 140 1.1 bouyer */ 141 1.1 bouyer if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_MASS_STORAGE_IDE) { 142 1.1 bouyer interface = PCIIDE_INTERFACE_SETTABLE(0) | 143 1.1 bouyer PCIIDE_INTERFACE_SETTABLE(1); 144 1.1 bouyer if (pciide_pci_read(pa->pa_pc, pa->pa_tag, CMD_CONF) & 145 1.1 bouyer CMD_CONF_DSA1) 146 1.1 bouyer interface |= PCIIDE_INTERFACE_PCI(0) | 147 1.1 bouyer PCIIDE_INTERFACE_PCI(1); 148 1.1 bouyer } else { 149 1.1 bouyer interface = PCI_INTERFACE(pa->pa_class); 150 1.1 bouyer } 151 1.1 bouyer 152 1.14 thorpej sc->wdc_chanarray[channel] = &cp->ata_channel; 153 1.1 bouyer cp->name = PCIIDE_CHANNEL_NAME(channel); 154 1.14 thorpej cp->ata_channel.ch_channel = channel; 155 1.16 thorpej cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; 156 1.1 bouyer 157 1.1 bouyer if (channel > 0 && one_channel) { 158 1.47 andvar /* Channels are not independent, need synchronization */ 159 1.43 jdolecek sc->sc_wdcdev.sc_atac.atac_claim_hw = cmd064x_claim_hw; 160 1.43 jdolecek sc->sc_wdcdev.sc_atac.atac_free_hw = cmd064x_free_hw; 161 1.43 jdolecek sc->sc_cmd_act_channel = CMDIDE_ACT_CHANNEL_NONE; 162 1.1 bouyer } 163 1.1 bouyer 164 1.28 cube aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, 165 1.40 jdolecek "%s channel %s to %s mode%s\n", cp->name, 166 1.1 bouyer (interface & PCIIDE_INTERFACE_SETTABLE(channel)) ? 167 1.1 bouyer "configured" : "wired", 168 1.1 bouyer (interface & PCIIDE_INTERFACE_PCI(channel)) ? 169 1.40 jdolecek "native-PCI" : "compatibility", 170 1.47 andvar one_channel ? ", channel non-independent" : ""); 171 1.1 bouyer 172 1.1 bouyer /* 173 1.1 bouyer * with a CMD PCI64x, if we get here, the first channel is enabled: 174 1.1 bouyer * there's no way to disable the first channel without disabling 175 1.1 bouyer * the whole device 176 1.1 bouyer */ 177 1.1 bouyer if (channel != 0 && (ctrl & CMD_CTRL_2PORT) == 0) { 178 1.28 cube aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, 179 1.28 cube "%s channel ignored (disabled)\n", cp->name); 180 1.14 thorpej cp->ata_channel.ch_flags |= ATACH_DISABLED; 181 1.1 bouyer return; 182 1.1 bouyer } 183 1.1 bouyer 184 1.30 jakllsch pciide_mapchan(pa, cp, interface, cmd_pci_intr); 185 1.1 bouyer } 186 1.1 bouyer 187 1.43 jdolecek /* 188 1.43 jdolecek * Check if we can execute next xfer on the channel. 189 1.43 jdolecek * Called with chp channel lock held. 190 1.43 jdolecek */ 191 1.43 jdolecek static int 192 1.43 jdolecek cmd064x_claim_hw(struct ata_channel *chp, int maysleep) 193 1.43 jdolecek { 194 1.43 jdolecek struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); 195 1.43 jdolecek 196 1.43 jdolecek return atomic_cas_uint(&sc->sc_cmd_act_channel, 197 1.43 jdolecek CMDIDE_ACT_CHANNEL_NONE, chp->ch_channel) 198 1.43 jdolecek == CMDIDE_ACT_CHANNEL_NONE; 199 1.43 jdolecek } 200 1.43 jdolecek 201 1.43 jdolecek /* Allow another channel to run. Called with ochp channel lock held. */ 202 1.43 jdolecek static void 203 1.43 jdolecek cmd064x_free_hw(struct ata_channel *ochp) 204 1.43 jdolecek { 205 1.43 jdolecek struct pciide_softc *sc = CHAN_TO_PCIIDE(ochp); 206 1.43 jdolecek uint oact = atomic_cas_uint(&sc->sc_cmd_act_channel, 207 1.43 jdolecek ochp->ch_channel, CMDIDE_ACT_CHANNEL_NONE); 208 1.43 jdolecek struct ata_channel *nchp; 209 1.43 jdolecek 210 1.43 jdolecek KASSERT(oact == ochp->ch_channel); 211 1.43 jdolecek 212 1.43 jdolecek /* Start the other channel(s) */ 213 1.43 jdolecek for(uint i = 0; i < sc->sc_wdcdev.sc_atac.atac_nchannels; i++) { 214 1.43 jdolecek /* Skip the current channel */ 215 1.43 jdolecek if (i == oact) 216 1.43 jdolecek continue; 217 1.43 jdolecek 218 1.43 jdolecek nchp = &sc->pciide_channels[i].ata_channel; 219 1.43 jdolecek if (nchp->ch_ndrives == 0) 220 1.43 jdolecek continue; 221 1.43 jdolecek 222 1.43 jdolecek atastart(nchp); 223 1.43 jdolecek } 224 1.43 jdolecek } 225 1.43 jdolecek 226 1.2 thorpej static int 227 1.2 thorpej cmd_pci_intr(void *arg) 228 1.1 bouyer { 229 1.1 bouyer struct pciide_softc *sc = arg; 230 1.1 bouyer struct pciide_channel *cp; 231 1.14 thorpej struct ata_channel *wdc_cp; 232 1.18 perry int i, rv, crv; 233 1.1 bouyer u_int32_t priirq, secirq; 234 1.1 bouyer 235 1.1 bouyer rv = 0; 236 1.1 bouyer priirq = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_CONF); 237 1.1 bouyer secirq = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_ARTTIM23); 238 1.16 thorpej for (i = 0; i < sc->sc_wdcdev.sc_atac.atac_nchannels; i++) { 239 1.1 bouyer cp = &sc->pciide_channels[i]; 240 1.14 thorpej wdc_cp = &cp->ata_channel; 241 1.1 bouyer /* If a compat channel skip. */ 242 1.1 bouyer if (cp->compat) 243 1.1 bouyer continue; 244 1.1 bouyer if ((i == 0 && (priirq & CMD_CONF_DRV0_INTR)) || 245 1.1 bouyer (i == 1 && (secirq & CMD_ARTTIM23_IRQ))) { 246 1.1 bouyer crv = wdcintr(wdc_cp); 247 1.11 bouyer if (crv == 0) { 248 1.46 jdolecek aprint_verbose("%s:%d: bogus intr\n", 249 1.28 cube device_xname( 250 1.28 cube sc->sc_wdcdev.sc_atac.atac_dev), i); 251 1.11 bouyer } else 252 1.1 bouyer rv = 1; 253 1.1 bouyer } 254 1.1 bouyer } 255 1.1 bouyer return rv; 256 1.1 bouyer } 257 1.1 bouyer 258 1.2 thorpej static void 259 1.32 dyoung cmd_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa) 260 1.1 bouyer { 261 1.1 bouyer int channel; 262 1.1 bouyer 263 1.1 bouyer /* 264 1.1 bouyer * For a CMD PCI064x, the use of PCI_COMMAND_IO_ENABLE 265 1.5 wiz * and base addresses registers can be disabled at 266 1.1 bouyer * hardware level. In this case, the device is wired 267 1.1 bouyer * in compat mode and its first channel is always enabled, 268 1.1 bouyer * but we can't rely on PCI_COMMAND_IO_ENABLE. 269 1.1 bouyer * In fact, it seems that the first channel of the CMD PCI0640 270 1.1 bouyer * can't be disabled. 271 1.1 bouyer */ 272 1.1 bouyer 273 1.1 bouyer #ifdef PCIIDE_CMD064x_DISABLE 274 1.1 bouyer if (pciide_chipen(sc, pa) == 0) 275 1.1 bouyer return; 276 1.1 bouyer #endif 277 1.1 bouyer 278 1.28 cube aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, 279 1.28 cube "hardware does not support DMA\n"); 280 1.1 bouyer sc->sc_dma_ok = 0; 281 1.1 bouyer 282 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; 283 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS; 284 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16; 285 1.37 bouyer sc->sc_wdcdev.wdc_maxdrives = 2; 286 1.1 bouyer 287 1.14 thorpej wdc_allocate_regs(&sc->sc_wdcdev); 288 1.14 thorpej 289 1.16 thorpej for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; 290 1.16 thorpej channel++) { 291 1.1 bouyer cmd_channel_map(pa, sc, channel); 292 1.1 bouyer } 293 1.1 bouyer } 294 1.1 bouyer 295 1.2 thorpej static void 296 1.32 dyoung cmd0643_9_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa) 297 1.18 perry { 298 1.1 bouyer int channel; 299 1.1 bouyer pcireg_t rev = PCI_REVISION(pa->pa_class); 300 1.1 bouyer 301 1.1 bouyer /* 302 1.1 bouyer * For a CMD PCI064x, the use of PCI_COMMAND_IO_ENABLE 303 1.5 wiz * and base addresses registers can be disabled at 304 1.1 bouyer * hardware level. In this case, the device is wired 305 1.1 bouyer * in compat mode and its first channel is always enabled, 306 1.1 bouyer * but we can't rely on PCI_COMMAND_IO_ENABLE. 307 1.1 bouyer * In fact, it seems that the first channel of the CMD PCI0640 308 1.1 bouyer * can't be disabled. 309 1.1 bouyer */ 310 1.1 bouyer 311 1.1 bouyer #ifdef PCIIDE_CMD064x_DISABLE 312 1.1 bouyer if (pciide_chipen(sc, pa) == 0) 313 1.1 bouyer return; 314 1.1 bouyer #endif 315 1.1 bouyer 316 1.28 cube aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 317 1.28 cube "bus-master DMA support present"); 318 1.1 bouyer pciide_mapreg_dma(sc, pa); 319 1.27 ad aprint_verbose("\n"); 320 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DATA32; 321 1.1 bouyer if (sc->sc_dma_ok) { 322 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA; 323 1.1 bouyer switch (sc->sc_pp->ide_product) { 324 1.1 bouyer case PCI_PRODUCT_CMDTECH_649: 325 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_UDMA; 326 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_udma_cap = 5; 327 1.1 bouyer sc->sc_wdcdev.irqack = cmd646_9_irqack; 328 1.1 bouyer break; 329 1.1 bouyer case PCI_PRODUCT_CMDTECH_648: 330 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_UDMA; 331 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_udma_cap = 4; 332 1.1 bouyer sc->sc_wdcdev.irqack = cmd646_9_irqack; 333 1.1 bouyer break; 334 1.1 bouyer case PCI_PRODUCT_CMDTECH_646: 335 1.1 bouyer if (rev >= CMD0646U2_REV) { 336 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_UDMA; 337 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_udma_cap = 2; 338 1.1 bouyer } else if (rev >= CMD0646U_REV) { 339 1.1 bouyer /* 340 1.1 bouyer * Linux's driver claims that the 646U is broken 341 1.1 bouyer * with UDMA. Only enable it if we know what we're 342 1.1 bouyer * doing 343 1.1 bouyer */ 344 1.1 bouyer #ifdef PCIIDE_CMD0646U_ENABLEUDMA 345 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_UDMA; 346 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_udma_cap = 2; 347 1.1 bouyer #endif 348 1.1 bouyer /* explicitly disable UDMA */ 349 1.1 bouyer pciide_pci_write(sc->sc_pc, sc->sc_tag, 350 1.1 bouyer CMD_UDMATIM(0), 0); 351 1.1 bouyer pciide_pci_write(sc->sc_pc, sc->sc_tag, 352 1.1 bouyer CMD_UDMATIM(1), 0); 353 1.1 bouyer } 354 1.1 bouyer sc->sc_wdcdev.irqack = cmd646_9_irqack; 355 1.1 bouyer break; 356 1.1 bouyer default: 357 1.1 bouyer sc->sc_wdcdev.irqack = pciide_irqack; 358 1.1 bouyer } 359 1.1 bouyer } 360 1.1 bouyer 361 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; 362 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS; 363 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; 364 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; 365 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_set_modes = cmd0643_9_setup_channel; 366 1.38 kiyohara sc->sc_wdcdev.wdc_maxdrives = 2; 367 1.1 bouyer 368 1.13 thorpej ATADEBUG_PRINT(("cmd0643_9_chip_map: old timings reg 0x%x 0x%x\n", 369 1.1 bouyer pci_conf_read(sc->sc_pc, sc->sc_tag, 0x54), 370 1.1 bouyer pci_conf_read(sc->sc_pc, sc->sc_tag, 0x58)), 371 1.1 bouyer DEBUG_PROBE); 372 1.1 bouyer 373 1.14 thorpej wdc_allocate_regs(&sc->sc_wdcdev); 374 1.14 thorpej 375 1.16 thorpej for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; 376 1.16 thorpej channel++) 377 1.1 bouyer cmd_channel_map(pa, sc, channel); 378 1.4 simonb 379 1.1 bouyer /* 380 1.1 bouyer * note - this also makes sure we clear the irq disable and reset 381 1.1 bouyer * bits 382 1.1 bouyer */ 383 1.1 bouyer pciide_pci_write(sc->sc_pc, sc->sc_tag, CMD_DMA_MODE, CMD_DMA_MULTIPLE); 384 1.13 thorpej ATADEBUG_PRINT(("cmd0643_9_chip_map: timings reg now 0x%x 0x%x\n", 385 1.1 bouyer pci_conf_read(sc->sc_pc, sc->sc_tag, 0x54), 386 1.1 bouyer pci_conf_read(sc->sc_pc, sc->sc_tag, 0x58)), 387 1.1 bouyer DEBUG_PROBE); 388 1.1 bouyer } 389 1.1 bouyer 390 1.2 thorpej static void 391 1.14 thorpej cmd0643_9_setup_channel(struct ata_channel *chp) 392 1.1 bouyer { 393 1.1 bouyer struct ata_drive_datas *drvp; 394 1.1 bouyer u_int8_t tim; 395 1.1 bouyer u_int32_t idedma_ctl, udma_reg; 396 1.17 thorpej int drive, s; 397 1.15 thorpej struct pciide_channel *cp = CHAN_TO_PCHAN(chp); 398 1.15 thorpej struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); 399 1.1 bouyer 400 1.1 bouyer idedma_ctl = 0; 401 1.1 bouyer /* setup DMA if needed */ 402 1.1 bouyer pciide_channel_dma_setup(cp); 403 1.1 bouyer 404 1.1 bouyer for (drive = 0; drive < 2; drive++) { 405 1.1 bouyer drvp = &chp->ch_drive[drive]; 406 1.1 bouyer /* If no drive, skip */ 407 1.37 bouyer if (drvp->drive_type == ATA_DRIVET_NONE) 408 1.1 bouyer continue; 409 1.1 bouyer /* add timing values, setup DMA if needed */ 410 1.1 bouyer tim = cmd0643_9_data_tim_pio[drvp->PIO_mode]; 411 1.37 bouyer if (drvp->drive_flags & (ATA_DRIVE_DMA | ATA_DRIVE_UDMA)) { 412 1.37 bouyer if (drvp->drive_flags & ATA_DRIVE_UDMA) { 413 1.1 bouyer /* UltraDMA on a 646U2, 0648 or 0649 */ 414 1.17 thorpej s = splbio(); 415 1.37 bouyer drvp->drive_flags &= ~ATA_DRIVE_DMA; 416 1.17 thorpej splx(s); 417 1.1 bouyer udma_reg = pciide_pci_read(sc->sc_pc, 418 1.10 thorpej sc->sc_tag, CMD_UDMATIM(chp->ch_channel)); 419 1.1 bouyer if (drvp->UDMA_mode > 2 && 420 1.1 bouyer (pciide_pci_read(sc->sc_pc, sc->sc_tag, 421 1.1 bouyer CMD_BICSR) & 422 1.10 thorpej CMD_BICSR_80(chp->ch_channel)) == 0) 423 1.1 bouyer drvp->UDMA_mode = 2; 424 1.1 bouyer if (drvp->UDMA_mode > 2) 425 1.1 bouyer udma_reg &= ~CMD_UDMATIM_UDMA33(drive); 426 1.18 perry else if (sc->sc_wdcdev.sc_atac.atac_udma_cap > 2) 427 1.1 bouyer udma_reg |= CMD_UDMATIM_UDMA33(drive); 428 1.1 bouyer udma_reg |= CMD_UDMATIM_UDMA(drive); 429 1.1 bouyer udma_reg &= ~(CMD_UDMATIM_TIM_MASK << 430 1.1 bouyer CMD_UDMATIM_TIM_OFF(drive)); 431 1.1 bouyer udma_reg |= 432 1.1 bouyer (cmd0646_9_tim_udma[drvp->UDMA_mode] << 433 1.1 bouyer CMD_UDMATIM_TIM_OFF(drive)); 434 1.1 bouyer pciide_pci_write(sc->sc_pc, sc->sc_tag, 435 1.10 thorpej CMD_UDMATIM(chp->ch_channel), udma_reg); 436 1.1 bouyer } else { 437 1.1 bouyer /* 438 1.1 bouyer * use Multiword DMA. 439 1.1 bouyer * Timings will be used for both PIO and DMA, 440 1.1 bouyer * so adjust DMA mode if needed 441 1.1 bouyer * if we have a 0646U2/8/9, turn off UDMA 442 1.1 bouyer */ 443 1.16 thorpej if (sc->sc_wdcdev.sc_atac.atac_cap & ATAC_CAP_UDMA) { 444 1.1 bouyer udma_reg = pciide_pci_read(sc->sc_pc, 445 1.1 bouyer sc->sc_tag, 446 1.10 thorpej CMD_UDMATIM(chp->ch_channel)); 447 1.1 bouyer udma_reg &= ~CMD_UDMATIM_UDMA(drive); 448 1.1 bouyer pciide_pci_write(sc->sc_pc, sc->sc_tag, 449 1.10 thorpej CMD_UDMATIM(chp->ch_channel), 450 1.1 bouyer udma_reg); 451 1.1 bouyer } 452 1.1 bouyer if (drvp->PIO_mode >= 3 && 453 1.1 bouyer (drvp->DMA_mode + 2) > drvp->PIO_mode) { 454 1.1 bouyer drvp->DMA_mode = drvp->PIO_mode - 2; 455 1.1 bouyer } 456 1.1 bouyer tim = cmd0643_9_data_tim_dma[drvp->DMA_mode]; 457 1.1 bouyer } 458 1.1 bouyer idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); 459 1.1 bouyer } 460 1.1 bouyer pciide_pci_write(sc->sc_pc, sc->sc_tag, 461 1.10 thorpej CMD_DATA_TIM(chp->ch_channel, drive), tim); 462 1.1 bouyer } 463 1.1 bouyer if (idedma_ctl != 0) { 464 1.1 bouyer /* Add software bits in status register */ 465 1.6 fvdl bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, 466 1.1 bouyer idedma_ctl); 467 1.1 bouyer } 468 1.1 bouyer } 469 1.1 bouyer 470 1.2 thorpej static void 471 1.14 thorpej cmd646_9_irqack(struct ata_channel *chp) 472 1.1 bouyer { 473 1.1 bouyer u_int32_t priirq, secirq; 474 1.15 thorpej struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); 475 1.1 bouyer 476 1.10 thorpej if (chp->ch_channel == 0) { 477 1.1 bouyer priirq = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_CONF); 478 1.1 bouyer pciide_pci_write(sc->sc_pc, sc->sc_tag, CMD_CONF, priirq); 479 1.1 bouyer } else { 480 1.1 bouyer secirq = pciide_pci_read(sc->sc_pc, sc->sc_tag, CMD_ARTTIM23); 481 1.1 bouyer pciide_pci_write(sc->sc_pc, sc->sc_tag, CMD_ARTTIM23, secirq); 482 1.1 bouyer } 483 1.1 bouyer pciide_irqack(chp); 484 1.1 bouyer } 485 1.1 bouyer 486 1.2 thorpej static void 487 1.32 dyoung cmd680_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa) 488 1.18 perry { 489 1.1 bouyer int channel; 490 1.1 bouyer 491 1.1 bouyer if (pciide_chipen(sc, pa) == 0) 492 1.1 bouyer return; 493 1.1 bouyer 494 1.28 cube aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 495 1.28 cube "bus-master DMA support present"); 496 1.1 bouyer pciide_mapreg_dma(sc, pa); 497 1.27 ad aprint_verbose("\n"); 498 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DATA32; 499 1.1 bouyer if (sc->sc_dma_ok) { 500 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA; 501 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_UDMA; 502 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_udma_cap = 6; 503 1.1 bouyer sc->sc_wdcdev.irqack = pciide_irqack; 504 1.1 bouyer } 505 1.1 bouyer 506 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; 507 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS; 508 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; 509 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; 510 1.16 thorpej sc->sc_wdcdev.sc_atac.atac_set_modes = cmd680_setup_channel; 511 1.38 kiyohara sc->sc_wdcdev.wdc_maxdrives = 2; 512 1.1 bouyer 513 1.1 bouyer pciide_pci_write(sc->sc_pc, sc->sc_tag, 0x80, 0x00); 514 1.1 bouyer pciide_pci_write(sc->sc_pc, sc->sc_tag, 0x84, 0x00); 515 1.1 bouyer pciide_pci_write(sc->sc_pc, sc->sc_tag, 0x8a, 516 1.1 bouyer pciide_pci_read(sc->sc_pc, sc->sc_tag, 0x8a) | 0x01); 517 1.14 thorpej 518 1.14 thorpej wdc_allocate_regs(&sc->sc_wdcdev); 519 1.14 thorpej 520 1.16 thorpej for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; 521 1.16 thorpej channel++) 522 1.1 bouyer cmd680_channel_map(pa, sc, channel); 523 1.1 bouyer } 524 1.1 bouyer 525 1.2 thorpej static void 526 1.32 dyoung cmd680_channel_map(const struct pci_attach_args *pa, struct pciide_softc *sc, 527 1.2 thorpej int channel) 528 1.1 bouyer { 529 1.1 bouyer struct pciide_channel *cp = &sc->pciide_channels[channel]; 530 1.1 bouyer int interface, i, reg; 531 1.1 bouyer static const u_int8_t init_val[] = 532 1.1 bouyer { 0x8a, 0x32, 0x8a, 0x32, 0x8a, 0x32, 533 1.1 bouyer 0x92, 0x43, 0x92, 0x43, 0x09, 0x40, 0x09, 0x40 }; 534 1.1 bouyer 535 1.1 bouyer if (PCI_SUBCLASS(pa->pa_class) != PCI_SUBCLASS_MASS_STORAGE_IDE) { 536 1.1 bouyer interface = PCIIDE_INTERFACE_SETTABLE(0) | 537 1.1 bouyer PCIIDE_INTERFACE_SETTABLE(1); 538 1.1 bouyer interface |= PCIIDE_INTERFACE_PCI(0) | 539 1.1 bouyer PCIIDE_INTERFACE_PCI(1); 540 1.1 bouyer } else { 541 1.1 bouyer interface = PCI_INTERFACE(pa->pa_class); 542 1.1 bouyer } 543 1.1 bouyer 544 1.14 thorpej sc->wdc_chanarray[channel] = &cp->ata_channel; 545 1.1 bouyer cp->name = PCIIDE_CHANNEL_NAME(channel); 546 1.14 thorpej cp->ata_channel.ch_channel = channel; 547 1.16 thorpej cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; 548 1.1 bouyer 549 1.1 bouyer /* XXX */ 550 1.1 bouyer reg = 0xa2 + channel * 16; 551 1.1 bouyer for (i = 0; i < sizeof(init_val); i++) 552 1.1 bouyer pciide_pci_write(sc->sc_pc, sc->sc_tag, reg + i, init_val[i]); 553 1.1 bouyer 554 1.28 cube aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, 555 1.28 cube "%s channel %s to %s mode\n", cp->name, 556 1.1 bouyer (interface & PCIIDE_INTERFACE_SETTABLE(channel)) ? 557 1.1 bouyer "configured" : "wired", 558 1.1 bouyer (interface & PCIIDE_INTERFACE_PCI(channel)) ? 559 1.1 bouyer "native-PCI" : "compatibility"); 560 1.1 bouyer 561 1.30 jakllsch pciide_mapchan(pa, cp, interface, pciide_pci_intr); 562 1.1 bouyer } 563 1.1 bouyer 564 1.2 thorpej static void 565 1.14 thorpej cmd680_setup_channel(struct ata_channel *chp) 566 1.1 bouyer { 567 1.1 bouyer struct ata_drive_datas *drvp; 568 1.1 bouyer u_int8_t mode, off, scsc; 569 1.1 bouyer u_int16_t val; 570 1.1 bouyer u_int32_t idedma_ctl; 571 1.17 thorpej int drive, s; 572 1.15 thorpej struct pciide_channel *cp = CHAN_TO_PCHAN(chp); 573 1.15 thorpej struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); 574 1.1 bouyer pci_chipset_tag_t pc = sc->sc_pc; 575 1.1 bouyer pcitag_t pa = sc->sc_tag; 576 1.1 bouyer static const u_int8_t udma2_tbl[] = 577 1.1 bouyer { 0x0f, 0x0b, 0x07, 0x06, 0x03, 0x02, 0x01 }; 578 1.1 bouyer static const u_int8_t udma_tbl[] = 579 1.1 bouyer { 0x0c, 0x07, 0x05, 0x04, 0x02, 0x01, 0x00 }; 580 1.1 bouyer static const u_int16_t dma_tbl[] = 581 1.1 bouyer { 0x2208, 0x10c2, 0x10c1 }; 582 1.1 bouyer static const u_int16_t pio_tbl[] = 583 1.1 bouyer { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; 584 1.1 bouyer 585 1.1 bouyer idedma_ctl = 0; 586 1.1 bouyer pciide_channel_dma_setup(cp); 587 1.10 thorpej mode = pciide_pci_read(pc, pa, 0x80 + chp->ch_channel * 4); 588 1.1 bouyer 589 1.1 bouyer for (drive = 0; drive < 2; drive++) { 590 1.1 bouyer drvp = &chp->ch_drive[drive]; 591 1.1 bouyer /* If no drive, skip */ 592 1.37 bouyer if (drvp->drive_type == ATA_DRIVET_NONE) 593 1.1 bouyer continue; 594 1.1 bouyer mode &= ~(0x03 << (drive * 4)); 595 1.37 bouyer if (drvp->drive_flags & ATA_DRIVE_UDMA) { 596 1.17 thorpej s = splbio(); 597 1.37 bouyer drvp->drive_flags &= ~ATA_DRIVE_DMA; 598 1.17 thorpej splx(s); 599 1.10 thorpej off = 0xa0 + chp->ch_channel * 16; 600 1.1 bouyer if (drvp->UDMA_mode > 2 && 601 1.1 bouyer (pciide_pci_read(pc, pa, off) & 0x01) == 0) 602 1.1 bouyer drvp->UDMA_mode = 2; 603 1.1 bouyer scsc = pciide_pci_read(pc, pa, 0x8a); 604 1.1 bouyer if (drvp->UDMA_mode == 6 && (scsc & 0x30) == 0) { 605 1.1 bouyer pciide_pci_write(pc, pa, 0x8a, scsc | 0x01); 606 1.1 bouyer scsc = pciide_pci_read(pc, pa, 0x8a); 607 1.1 bouyer if ((scsc & 0x30) == 0) 608 1.1 bouyer drvp->UDMA_mode = 5; 609 1.1 bouyer } 610 1.1 bouyer mode |= 0x03 << (drive * 4); 611 1.10 thorpej off = 0xac + chp->ch_channel * 16 + drive * 2; 612 1.1 bouyer val = pciide_pci_read(pc, pa, off) & ~0x3f; 613 1.1 bouyer if (scsc & 0x30) 614 1.1 bouyer val |= udma2_tbl[drvp->UDMA_mode]; 615 1.1 bouyer else 616 1.1 bouyer val |= udma_tbl[drvp->UDMA_mode]; 617 1.1 bouyer pciide_pci_write(pc, pa, off, val); 618 1.1 bouyer idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); 619 1.37 bouyer } else if (drvp->drive_flags & ATA_DRIVE_DMA) { 620 1.1 bouyer mode |= 0x02 << (drive * 4); 621 1.10 thorpej off = 0xa8 + chp->ch_channel * 16 + drive * 2; 622 1.1 bouyer val = dma_tbl[drvp->DMA_mode]; 623 1.1 bouyer pciide_pci_write(pc, pa, off, val & 0xff); 624 1.20 christos pciide_pci_write(pc, pa, off+1, val >> 8); 625 1.1 bouyer idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); 626 1.1 bouyer } else { 627 1.1 bouyer mode |= 0x01 << (drive * 4); 628 1.10 thorpej off = 0xa4 + chp->ch_channel * 16 + drive * 2; 629 1.1 bouyer val = pio_tbl[drvp->PIO_mode]; 630 1.1 bouyer pciide_pci_write(pc, pa, off, val & 0xff); 631 1.20 christos pciide_pci_write(pc, pa, off+1, val >> 8); 632 1.1 bouyer } 633 1.1 bouyer } 634 1.1 bouyer 635 1.10 thorpej pciide_pci_write(pc, pa, 0x80 + chp->ch_channel * 4, mode); 636 1.1 bouyer if (idedma_ctl != 0) { 637 1.1 bouyer /* Add software bits in status register */ 638 1.6 fvdl bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, 639 1.1 bouyer idedma_ctl); 640 1.1 bouyer } 641 1.1 bouyer } 642