| 1 | /* $NetBSD: satalink.c,v 1.53 2016/08/23 09:46:45 msaitoh Exp $ */ |
| 2 | |
| 3 | /*- |
| 4 | * Copyright (c) 2003 The NetBSD Foundation, Inc. |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * This code is derived from software contributed to The NetBSD Foundation |
| 8 | * by Jason R. Thorpe of Wasabi Systems, Inc. |
| 9 | * |
| 10 | * Redistribution and use in source and binary forms, with or without |
| 11 | * modification, are permitted provided that the following conditions |
| 12 | * are met: |
| 13 | * 1. Redistributions of source code must retain the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer. |
| 15 | * 2. Redistributions in binary form must reproduce the above copyright |
| 16 | * notice, this list of conditions and the following disclaimer in the |
| 17 | * documentation and/or other materials provided with the distribution. |
| 18 | * |
| 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
| 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
| 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 29 | * POSSIBILITY OF SUCH DAMAGE. |
| 30 | */ |
| 31 | |
| 32 | #include <sys/cdefs.h> |
| 33 | __KERNEL_RCSID(0, "$NetBSD: satalink.c,v 1.53 2016/08/23 09:46:45 msaitoh Exp $" ); |
| 34 | |
| 35 | #include <sys/param.h> |
| 36 | #include <sys/systm.h> |
| 37 | #include <sys/malloc.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_sii3112_reg.h> |
| 44 | |
| 45 | #include <dev/ata/satareg.h> |
| 46 | #include <dev/ata/satavar.h> |
| 47 | #include <dev/ata/atareg.h> |
| 48 | |
| 49 | /* |
| 50 | * Register map for BA5 register space, indexed by channel. |
| 51 | */ |
| 52 | static const struct { |
| 53 | bus_addr_t ba5_IDEDMA_CMD; |
| 54 | bus_addr_t ba5_IDEDMA_CTL; |
| 55 | bus_addr_t ba5_IDEDMA_TBL; |
| 56 | bus_addr_t ba5_IDEDMA_CMD2; |
| 57 | bus_addr_t ba5_IDEDMA_CTL2; |
| 58 | bus_addr_t ba5_IDE_TF0; |
| 59 | bus_addr_t ba5_IDE_TF1; |
| 60 | bus_addr_t ba5_IDE_TF2; |
| 61 | bus_addr_t ba5_IDE_TF3; |
| 62 | bus_addr_t ba5_IDE_TF4; |
| 63 | bus_addr_t ba5_IDE_TF5; |
| 64 | bus_addr_t ba5_IDE_TF6; |
| 65 | bus_addr_t ba5_IDE_TF7; |
| 66 | bus_addr_t ba5_IDE_TF8; |
| 67 | bus_addr_t ba5_IDE_RAD; |
| 68 | bus_addr_t ba5_IDE_TF9; |
| 69 | bus_addr_t ba5_IDE_TF10; |
| 70 | bus_addr_t ba5_IDE_TF11; |
| 71 | bus_addr_t ba5_IDE_TF12; |
| 72 | bus_addr_t ba5_IDE_TF13; |
| 73 | bus_addr_t ba5_IDE_TF14; |
| 74 | bus_addr_t ba5_IDE_TF15; |
| 75 | bus_addr_t ba5_IDE_TF16; |
| 76 | bus_addr_t ba5_IDE_TF17; |
| 77 | bus_addr_t ba5_IDE_TF18; |
| 78 | bus_addr_t ba5_IDE_TF19; |
| 79 | bus_addr_t ba5_IDE_RABC; |
| 80 | bus_addr_t ba5_IDE_CMD_STS; |
| 81 | bus_addr_t ba5_IDE_CFG_STS; |
| 82 | bus_addr_t ba5_IDE_DTM; |
| 83 | bus_addr_t ba5_SControl; |
| 84 | bus_addr_t ba5_SStatus; |
| 85 | bus_addr_t ba5_SError; |
| 86 | bus_addr_t ba5_SActive; /* 3114 */ |
| 87 | bus_addr_t ba5_SMisc; |
| 88 | bus_addr_t ba5_PHY_CONFIG; |
| 89 | bus_addr_t ba5_SIEN; |
| 90 | bus_addr_t ba5_SFISCfg; |
| 91 | } satalink_ba5_regmap[] = { |
| 92 | { /* Channel 0 */ |
| 93 | .ba5_IDEDMA_CMD = 0x000, |
| 94 | .ba5_IDEDMA_CTL = 0x002, |
| 95 | .ba5_IDEDMA_TBL = 0x004, |
| 96 | .ba5_IDEDMA_CMD2 = 0x010, |
| 97 | .ba5_IDEDMA_CTL2 = 0x012, |
| 98 | .ba5_IDE_TF0 = 0x080, /* wd_data */ |
| 99 | .ba5_IDE_TF1 = 0x081, /* wd_error */ |
| 100 | .ba5_IDE_TF2 = 0x082, /* wd_seccnt */ |
| 101 | .ba5_IDE_TF3 = 0x083, /* wd_sector */ |
| 102 | .ba5_IDE_TF4 = 0x084, /* wd_cyl_lo */ |
| 103 | .ba5_IDE_TF5 = 0x085, /* wd_cyl_hi */ |
| 104 | .ba5_IDE_TF6 = 0x086, /* wd_sdh */ |
| 105 | .ba5_IDE_TF7 = 0x087, /* wd_command */ |
| 106 | .ba5_IDE_TF8 = 0x08a, /* wd_altsts */ |
| 107 | .ba5_IDE_RAD = 0x08c, |
| 108 | .ba5_IDE_TF9 = 0x091, /* Features 2 */ |
| 109 | .ba5_IDE_TF10 = 0x092, /* Sector Count 2 */ |
| 110 | .ba5_IDE_TF11 = 0x093, /* Start Sector 2 */ |
| 111 | .ba5_IDE_TF12 = 0x094, /* Cylinder Low 2 */ |
| 112 | .ba5_IDE_TF13 = 0x095, /* Cylinder High 2 */ |
| 113 | .ba5_IDE_TF14 = 0x096, /* Device/Head 2 */ |
| 114 | .ba5_IDE_TF15 = 0x097, /* Cmd Sts 2 */ |
| 115 | .ba5_IDE_TF16 = 0x098, /* Sector Count 2 ext */ |
| 116 | .ba5_IDE_TF17 = 0x099, /* Start Sector 2 ext */ |
| 117 | .ba5_IDE_TF18 = 0x09a, /* Cyl Low 2 ext */ |
| 118 | .ba5_IDE_TF19 = 0x09b, /* Cyl High 2 ext */ |
| 119 | .ba5_IDE_RABC = 0x09c, |
| 120 | .ba5_IDE_CMD_STS = 0x0a0, |
| 121 | .ba5_IDE_CFG_STS = 0x0a1, |
| 122 | .ba5_IDE_DTM = 0x0b4, |
| 123 | .ba5_SControl = 0x100, |
| 124 | .ba5_SStatus = 0x104, |
| 125 | .ba5_SError = 0x108, |
| 126 | .ba5_SActive = 0x10c, |
| 127 | .ba5_SMisc = 0x140, |
| 128 | .ba5_PHY_CONFIG = 0x144, |
| 129 | .ba5_SIEN = 0x148, |
| 130 | .ba5_SFISCfg = 0x14c, |
| 131 | }, |
| 132 | { /* Channel 1 */ |
| 133 | .ba5_IDEDMA_CMD = 0x008, |
| 134 | .ba5_IDEDMA_CTL = 0x00a, |
| 135 | .ba5_IDEDMA_TBL = 0x00c, |
| 136 | .ba5_IDEDMA_CMD2 = 0x018, |
| 137 | .ba5_IDEDMA_CTL2 = 0x01a, |
| 138 | .ba5_IDE_TF0 = 0x0c0, /* wd_data */ |
| 139 | .ba5_IDE_TF1 = 0x0c1, /* wd_error */ |
| 140 | .ba5_IDE_TF2 = 0x0c2, /* wd_seccnt */ |
| 141 | .ba5_IDE_TF3 = 0x0c3, /* wd_sector */ |
| 142 | .ba5_IDE_TF4 = 0x0c4, /* wd_cyl_lo */ |
| 143 | .ba5_IDE_TF5 = 0x0c5, /* wd_cyl_hi */ |
| 144 | .ba5_IDE_TF6 = 0x0c6, /* wd_sdh */ |
| 145 | .ba5_IDE_TF7 = 0x0c7, /* wd_command */ |
| 146 | .ba5_IDE_TF8 = 0x0ca, /* wd_altsts */ |
| 147 | .ba5_IDE_RAD = 0x0cc, |
| 148 | .ba5_IDE_TF9 = 0x0d1, /* Features 2 */ |
| 149 | .ba5_IDE_TF10 = 0x0d2, /* Sector Count 2 */ |
| 150 | .ba5_IDE_TF11 = 0x0d3, /* Start Sector 2 */ |
| 151 | .ba5_IDE_TF12 = 0x0d4, /* Cylinder Low 2 */ |
| 152 | .ba5_IDE_TF13 = 0x0d5, /* Cylinder High 2 */ |
| 153 | .ba5_IDE_TF14 = 0x0d6, /* Device/Head 2 */ |
| 154 | .ba5_IDE_TF15 = 0x0d7, /* Cmd Sts 2 */ |
| 155 | .ba5_IDE_TF16 = 0x0d8, /* Sector Count 2 ext */ |
| 156 | .ba5_IDE_TF17 = 0x0d9, /* Start Sector 2 ext */ |
| 157 | .ba5_IDE_TF18 = 0x0da, /* Cyl Low 2 ext */ |
| 158 | .ba5_IDE_TF19 = 0x0db, /* Cyl High 2 ext */ |
| 159 | .ba5_IDE_RABC = 0x0dc, |
| 160 | .ba5_IDE_CMD_STS = 0x0e0, |
| 161 | .ba5_IDE_CFG_STS = 0x0e1, |
| 162 | .ba5_IDE_DTM = 0x0f4, |
| 163 | .ba5_SControl = 0x180, |
| 164 | .ba5_SStatus = 0x184, |
| 165 | .ba5_SError = 0x188, |
| 166 | .ba5_SActive = 0x18c, |
| 167 | .ba5_SMisc = 0x1c0, |
| 168 | .ba5_PHY_CONFIG = 0x1c4, |
| 169 | .ba5_SIEN = 0x1c8, |
| 170 | .ba5_SFISCfg = 0x1cc, |
| 171 | }, |
| 172 | { /* Channel 2 (3114) */ |
| 173 | .ba5_IDEDMA_CMD = 0x200, |
| 174 | .ba5_IDEDMA_CTL = 0x202, |
| 175 | .ba5_IDEDMA_TBL = 0x204, |
| 176 | .ba5_IDEDMA_CMD2 = 0x210, |
| 177 | .ba5_IDEDMA_CTL2 = 0x212, |
| 178 | .ba5_IDE_TF0 = 0x280, /* wd_data */ |
| 179 | .ba5_IDE_TF1 = 0x281, /* wd_error */ |
| 180 | .ba5_IDE_TF2 = 0x282, /* wd_seccnt */ |
| 181 | .ba5_IDE_TF3 = 0x283, /* wd_sector */ |
| 182 | .ba5_IDE_TF4 = 0x284, /* wd_cyl_lo */ |
| 183 | .ba5_IDE_TF5 = 0x285, /* wd_cyl_hi */ |
| 184 | .ba5_IDE_TF6 = 0x286, /* wd_sdh */ |
| 185 | .ba5_IDE_TF7 = 0x287, /* wd_command */ |
| 186 | .ba5_IDE_TF8 = 0x28a, /* wd_altsts */ |
| 187 | .ba5_IDE_RAD = 0x28c, |
| 188 | .ba5_IDE_TF9 = 0x291, /* Features 2 */ |
| 189 | .ba5_IDE_TF10 = 0x292, /* Sector Count 2 */ |
| 190 | .ba5_IDE_TF11 = 0x293, /* Start Sector 2 */ |
| 191 | .ba5_IDE_TF12 = 0x294, /* Cylinder Low 2 */ |
| 192 | .ba5_IDE_TF13 = 0x295, /* Cylinder High 2 */ |
| 193 | .ba5_IDE_TF14 = 0x296, /* Device/Head 2 */ |
| 194 | .ba5_IDE_TF15 = 0x297, /* Cmd Sts 2 */ |
| 195 | .ba5_IDE_TF16 = 0x298, /* Sector Count 2 ext */ |
| 196 | .ba5_IDE_TF17 = 0x299, /* Start Sector 2 ext */ |
| 197 | .ba5_IDE_TF18 = 0x29a, /* Cyl Low 2 ext */ |
| 198 | .ba5_IDE_TF19 = 0x29b, /* Cyl High 2 ext */ |
| 199 | .ba5_IDE_RABC = 0x29c, |
| 200 | .ba5_IDE_CMD_STS = 0x2a0, |
| 201 | .ba5_IDE_CFG_STS = 0x2a1, |
| 202 | .ba5_IDE_DTM = 0x2b4, |
| 203 | .ba5_SControl = 0x300, |
| 204 | .ba5_SStatus = 0x304, |
| 205 | .ba5_SError = 0x308, |
| 206 | .ba5_SActive = 0x30c, |
| 207 | .ba5_SMisc = 0x340, |
| 208 | .ba5_PHY_CONFIG = 0x344, |
| 209 | .ba5_SIEN = 0x348, |
| 210 | .ba5_SFISCfg = 0x34c, |
| 211 | }, |
| 212 | { /* Channel 3 (3114) */ |
| 213 | .ba5_IDEDMA_CMD = 0x208, |
| 214 | .ba5_IDEDMA_CTL = 0x20a, |
| 215 | .ba5_IDEDMA_TBL = 0x20c, |
| 216 | .ba5_IDEDMA_CMD2 = 0x218, |
| 217 | .ba5_IDEDMA_CTL2 = 0x21a, |
| 218 | .ba5_IDE_TF0 = 0x2c0, /* wd_data */ |
| 219 | .ba5_IDE_TF1 = 0x2c1, /* wd_error */ |
| 220 | .ba5_IDE_TF2 = 0x2c2, /* wd_seccnt */ |
| 221 | .ba5_IDE_TF3 = 0x2c3, /* wd_sector */ |
| 222 | .ba5_IDE_TF4 = 0x2c4, /* wd_cyl_lo */ |
| 223 | .ba5_IDE_TF5 = 0x2c5, /* wd_cyl_hi */ |
| 224 | .ba5_IDE_TF6 = 0x2c6, /* wd_sdh */ |
| 225 | .ba5_IDE_TF7 = 0x2c7, /* wd_command */ |
| 226 | .ba5_IDE_TF8 = 0x2ca, /* wd_altsts */ |
| 227 | .ba5_IDE_RAD = 0x2cc, |
| 228 | .ba5_IDE_TF9 = 0x2d1, /* Features 2 */ |
| 229 | .ba5_IDE_TF10 = 0x2d2, /* Sector Count 2 */ |
| 230 | .ba5_IDE_TF11 = 0x2d3, /* Start Sector 2 */ |
| 231 | .ba5_IDE_TF12 = 0x2d4, /* Cylinder Low 2 */ |
| 232 | .ba5_IDE_TF13 = 0x2d5, /* Cylinder High 2 */ |
| 233 | .ba5_IDE_TF14 = 0x2d6, /* Device/Head 2 */ |
| 234 | .ba5_IDE_TF15 = 0x2d7, /* Cmd Sts 2 */ |
| 235 | .ba5_IDE_TF16 = 0x2d8, /* Sector Count 2 ext */ |
| 236 | .ba5_IDE_TF17 = 0x2d9, /* Start Sector 2 ext */ |
| 237 | .ba5_IDE_TF18 = 0x2da, /* Cyl Low 2 ext */ |
| 238 | .ba5_IDE_TF19 = 0x2db, /* Cyl High 2 ext */ |
| 239 | .ba5_IDE_RABC = 0x2dc, |
| 240 | .ba5_IDE_CMD_STS = 0x2e0, |
| 241 | .ba5_IDE_CFG_STS = 0x2e1, |
| 242 | .ba5_IDE_DTM = 0x2f4, |
| 243 | .ba5_SControl = 0x380, |
| 244 | .ba5_SStatus = 0x384, |
| 245 | .ba5_SError = 0x388, |
| 246 | .ba5_SActive = 0x38c, |
| 247 | .ba5_SMisc = 0x3c0, |
| 248 | .ba5_PHY_CONFIG = 0x3c4, |
| 249 | .ba5_SIEN = 0x3c8, |
| 250 | .ba5_SFISCfg = 0x3cc, |
| 251 | }, |
| 252 | }; |
| 253 | |
| 254 | #define ba5_SIS 0x214 /* summary interrupt status */ |
| 255 | |
| 256 | /* Interrupt steering bit in BA5[0x200]. */ |
| 257 | #define IDEDMA_CMD_INT_STEER (1U << 1) |
| 258 | |
| 259 | static int satalink_match(device_t, cfdata_t, void *); |
| 260 | static void satalink_attach(device_t, device_t, void *); |
| 261 | |
| 262 | CFATTACH_DECL_NEW(satalink, sizeof(struct pciide_softc), |
| 263 | satalink_match, satalink_attach, pciide_detach, NULL); |
| 264 | |
| 265 | static void sii3112_chip_map(struct pciide_softc*, |
| 266 | const struct pci_attach_args*); |
| 267 | static void sii3114_chip_map(struct pciide_softc*, |
| 268 | const struct pci_attach_args*); |
| 269 | static void sii3112_drv_probe(struct ata_channel*); |
| 270 | static void sii3112_setup_channel(struct ata_channel*); |
| 271 | |
| 272 | static const struct pciide_product_desc pciide_satalink_products[] = { |
| 273 | { PCI_PRODUCT_CMDTECH_3112, |
| 274 | 0, |
| 275 | "Silicon Image SATALink 3112" , |
| 276 | sii3112_chip_map, |
| 277 | }, |
| 278 | { PCI_PRODUCT_CMDTECH_3512, |
| 279 | 0, |
| 280 | "Silicon Image SATALink 3512" , |
| 281 | sii3112_chip_map, |
| 282 | }, |
| 283 | { PCI_PRODUCT_CMDTECH_AAR_1210SA, |
| 284 | 0, |
| 285 | "Adaptec AAR-1210SA serial ATA RAID controller" , |
| 286 | sii3112_chip_map, |
| 287 | }, |
| 288 | { PCI_PRODUCT_CMDTECH_3114, |
| 289 | 0, |
| 290 | "Silicon Image SATALink 3114" , |
| 291 | sii3114_chip_map, |
| 292 | }, |
| 293 | { PCI_PRODUCT_ATI_IXP_SATA_300, |
| 294 | 0, |
| 295 | "ATI IXP 300 SATA" , |
| 296 | sii3112_chip_map, |
| 297 | }, |
| 298 | { 0, |
| 299 | 0, |
| 300 | NULL, |
| 301 | NULL |
| 302 | } |
| 303 | }; |
| 304 | |
| 305 | static int |
| 306 | satalink_match(device_t parent, cfdata_t match, void *aux) |
| 307 | { |
| 308 | struct pci_attach_args *pa = aux; |
| 309 | |
| 310 | if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_CMDTECH) { |
| 311 | if (pciide_lookup_product(pa->pa_id, pciide_satalink_products)) |
| 312 | return (2); |
| 313 | } |
| 314 | return (0); |
| 315 | } |
| 316 | |
| 317 | static void |
| 318 | satalink_attach(device_t parent, device_t self, void *aux) |
| 319 | { |
| 320 | struct pci_attach_args *pa = aux; |
| 321 | struct pciide_softc *sc = device_private(self); |
| 322 | |
| 323 | sc->sc_wdcdev.sc_atac.atac_dev = self; |
| 324 | |
| 325 | pciide_common_attach(sc, pa, |
| 326 | pciide_lookup_product(pa->pa_id, pciide_satalink_products)); |
| 327 | |
| 328 | } |
| 329 | |
| 330 | static inline uint32_t |
| 331 | ba5_read_4_ind(struct pciide_softc *sc, bus_addr_t reg) |
| 332 | { |
| 333 | uint32_t rv; |
| 334 | int s; |
| 335 | |
| 336 | s = splbio(); |
| 337 | pci_conf_write(sc->sc_pc, sc->sc_tag, SII3112_BA5_IND_ADDR, reg); |
| 338 | rv = pci_conf_read(sc->sc_pc, sc->sc_tag, SII3112_BA5_IND_DATA); |
| 339 | splx(s); |
| 340 | |
| 341 | return (rv); |
| 342 | } |
| 343 | |
| 344 | static inline uint32_t |
| 345 | ba5_read_4(struct pciide_softc *sc, bus_addr_t reg) |
| 346 | { |
| 347 | |
| 348 | if (__predict_true(sc->sc_ba5_en != 0)) |
| 349 | return (bus_space_read_4(sc->sc_ba5_st, sc->sc_ba5_sh, reg)); |
| 350 | |
| 351 | return (ba5_read_4_ind(sc, reg)); |
| 352 | } |
| 353 | |
| 354 | #define BA5_READ_4(sc, chan, reg) \ |
| 355 | ba5_read_4((sc), satalink_ba5_regmap[(chan)].reg) |
| 356 | |
| 357 | static inline void |
| 358 | ba5_write_4_ind(struct pciide_softc *sc, bus_addr_t reg, uint32_t val) |
| 359 | { |
| 360 | int s; |
| 361 | |
| 362 | s = splbio(); |
| 363 | pci_conf_write(sc->sc_pc, sc->sc_tag, SII3112_BA5_IND_ADDR, reg); |
| 364 | pci_conf_write(sc->sc_pc, sc->sc_tag, SII3112_BA5_IND_DATA, val); |
| 365 | splx(s); |
| 366 | } |
| 367 | |
| 368 | static inline void |
| 369 | ba5_write_4(struct pciide_softc *sc, bus_addr_t reg, uint32_t val) |
| 370 | { |
| 371 | |
| 372 | if (__predict_true(sc->sc_ba5_en != 0)) |
| 373 | bus_space_write_4(sc->sc_ba5_st, sc->sc_ba5_sh, reg, val); |
| 374 | else |
| 375 | ba5_write_4_ind(sc, reg, val); |
| 376 | } |
| 377 | |
| 378 | #define BA5_WRITE_4(sc, chan, reg, val) \ |
| 379 | ba5_write_4((sc), satalink_ba5_regmap[(chan)].reg, (val)) |
| 380 | |
| 381 | /* |
| 382 | * When the Silicon Image 3112 retries a PCI memory read command, |
| 383 | * it may retry it as a memory read multiple command under some |
| 384 | * circumstances. This can totally confuse some PCI controllers, |
| 385 | * so ensure that it will never do this by making sure that the |
| 386 | * Read Threshold (FIFO Read Request Control) field of the FIFO |
| 387 | * Valid Byte Count and Control registers for both channels (BA5 |
| 388 | * offset 0x40 and 0x44) are set to be at least as large as the |
| 389 | * cacheline size register. |
| 390 | * This may also happen on the 3114 (ragge 050527) |
| 391 | */ |
| 392 | static void |
| 393 | sii_fixup_cacheline(struct pciide_softc *sc, const struct pci_attach_args *pa, |
| 394 | int n) |
| 395 | { |
| 396 | pcireg_t cls, reg; |
| 397 | int i; |
| 398 | static bus_addr_t addr[] = { 0x40, 0x44, 0x240, 0x244 }; |
| 399 | |
| 400 | cls = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); |
| 401 | cls = (cls >> PCI_CACHELINE_SHIFT) & PCI_CACHELINE_MASK; |
| 402 | cls *= 4; |
| 403 | if (cls > 224) { |
| 404 | cls = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); |
| 405 | cls &= ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT); |
| 406 | cls |= ((224/4) << PCI_CACHELINE_SHIFT); |
| 407 | pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG, cls); |
| 408 | cls = 224; |
| 409 | } |
| 410 | if (cls < 32) |
| 411 | cls = 32; |
| 412 | cls = (cls + 31) / 32; |
| 413 | for (i = 0; i < n; i++) { |
| 414 | reg = ba5_read_4(sc, addr[i]); |
| 415 | if ((reg & 0x7) < cls) |
| 416 | ba5_write_4(sc, addr[i], (reg & 0x07) | cls); |
| 417 | } |
| 418 | } |
| 419 | |
| 420 | static void |
| 421 | sii3112_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa) |
| 422 | { |
| 423 | struct pciide_channel *cp; |
| 424 | pcireg_t interface, scs_cmd, cfgctl; |
| 425 | int channel; |
| 426 | |
| 427 | if (pciide_chipen(sc, pa) == 0) |
| 428 | return; |
| 429 | |
| 430 | #define SII3112_RESET_BITS \ |
| 431 | (SCS_CMD_PBM_RESET | SCS_CMD_ARB_RESET | \ |
| 432 | SCS_CMD_FF1_RESET | SCS_CMD_FF0_RESET | \ |
| 433 | SCS_CMD_IDE1_RESET | SCS_CMD_IDE0_RESET) |
| 434 | |
| 435 | /* |
| 436 | * Reset everything and then unblock all of the interrupts. |
| 437 | */ |
| 438 | scs_cmd = pci_conf_read(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD); |
| 439 | pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD, |
| 440 | scs_cmd | SII3112_RESET_BITS); |
| 441 | delay(50 * 1000); |
| 442 | pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD, |
| 443 | scs_cmd & SCS_CMD_BA5_EN); |
| 444 | delay(50 * 1000); |
| 445 | |
| 446 | if (scs_cmd & SCS_CMD_BA5_EN) { |
| 447 | aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 448 | "SATALink BA5 register space enabled\n" ); |
| 449 | if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x14, |
| 450 | PCI_MAPREG_TYPE_MEM| |
| 451 | PCI_MAPREG_MEM_TYPE_32BIT, 0, |
| 452 | &sc->sc_ba5_st, &sc->sc_ba5_sh, |
| 453 | NULL, &sc->sc_ba5_ss) != 0) |
| 454 | aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 455 | "unable to map SATALink BA5 register space\n" ); |
| 456 | else |
| 457 | sc->sc_ba5_en = 1; |
| 458 | } else { |
| 459 | aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 460 | "SATALink BA5 register space disabled\n" ); |
| 461 | |
| 462 | cfgctl = pci_conf_read(pa->pa_pc, pa->pa_tag, |
| 463 | SII3112_PCI_CFGCTL); |
| 464 | pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_PCI_CFGCTL, |
| 465 | cfgctl | CFGCTL_BA5INDEN); |
| 466 | } |
| 467 | |
| 468 | aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 469 | "bus-master DMA support present" ); |
| 470 | pciide_mapreg_dma(sc, pa); |
| 471 | aprint_verbose("\n" ); |
| 472 | |
| 473 | /* |
| 474 | * Rev. <= 0x01 of the 3112 have a bug that can cause data |
| 475 | * corruption if DMA transfers cross an 8K boundary. This is |
| 476 | * apparently hard to tickle, but we'll go ahead and play it |
| 477 | * safe. |
| 478 | */ |
| 479 | if ((PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMDTECH_3112 || |
| 480 | PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_CMDTECH_AAR_1210SA) && |
| 481 | PCI_REVISION(pa->pa_class) <= 0x01) { |
| 482 | sc->sc_dma_maxsegsz = 8192; |
| 483 | sc->sc_dma_boundary = 8192; |
| 484 | } |
| 485 | |
| 486 | sii_fixup_cacheline(sc, pa, 2); |
| 487 | |
| 488 | sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32; |
| 489 | sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; |
| 490 | if (sc->sc_dma_ok) { |
| 491 | sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA; |
| 492 | sc->sc_wdcdev.irqack = pciide_irqack; |
| 493 | sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; |
| 494 | sc->sc_wdcdev.sc_atac.atac_udma_cap = 6; |
| 495 | } |
| 496 | sc->sc_wdcdev.sc_atac.atac_set_modes = sii3112_setup_channel; |
| 497 | |
| 498 | /* We can use SControl and SStatus to probe for drives. */ |
| 499 | sc->sc_wdcdev.sc_atac.atac_probe = sii3112_drv_probe; |
| 500 | |
| 501 | sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; |
| 502 | sc->sc_wdcdev.sc_atac.atac_nchannels = PCIIDE_NUM_CHANNELS; |
| 503 | sc->sc_wdcdev.wdc_maxdrives = 1; |
| 504 | |
| 505 | wdc_allocate_regs(&sc->sc_wdcdev); |
| 506 | |
| 507 | /* |
| 508 | * The 3112 either identifies itself as a RAID storage device |
| 509 | * or a Misc storage device. Fake up the interface bits for |
| 510 | * what our driver expects. |
| 511 | */ |
| 512 | if (PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE) { |
| 513 | interface = PCI_INTERFACE(pa->pa_class); |
| 514 | } else { |
| 515 | interface = PCIIDE_INTERFACE_BUS_MASTER_DMA | |
| 516 | PCIIDE_INTERFACE_PCI(0) | PCIIDE_INTERFACE_PCI(1); |
| 517 | } |
| 518 | |
| 519 | for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; |
| 520 | channel++) { |
| 521 | cp = &sc->pciide_channels[channel]; |
| 522 | if (pciide_chansetup(sc, channel, interface) == 0) |
| 523 | continue; |
| 524 | pciide_mapchan(pa, cp, interface, pciide_pci_intr); |
| 525 | } |
| 526 | } |
| 527 | |
| 528 | static void |
| 529 | sii3114_mapreg_dma(struct pciide_softc *sc, const struct pci_attach_args *pa) |
| 530 | { |
| 531 | struct pciide_channel *pc; |
| 532 | int chan, reg; |
| 533 | bus_size_t size; |
| 534 | |
| 535 | sc->sc_wdcdev.dma_arg = sc; |
| 536 | sc->sc_wdcdev.dma_init = pciide_dma_init; |
| 537 | sc->sc_wdcdev.dma_start = pciide_dma_start; |
| 538 | sc->sc_wdcdev.dma_finish = pciide_dma_finish; |
| 539 | |
| 540 | if (device_cfdata(sc->sc_wdcdev.sc_atac.atac_dev)->cf_flags & |
| 541 | PCIIDE_OPTIONS_NODMA) { |
| 542 | aprint_verbose( |
| 543 | ", but unused (forced off by config file)" ); |
| 544 | sc->sc_dma_ok = 0; |
| 545 | return; |
| 546 | } |
| 547 | |
| 548 | /* |
| 549 | * Slice off a subregion of BA5 for each of the channel's DMA |
| 550 | * registers. |
| 551 | */ |
| 552 | |
| 553 | sc->sc_dma_iot = sc->sc_ba5_st; |
| 554 | for (chan = 0; chan < 4; chan++) { |
| 555 | pc = &sc->pciide_channels[chan]; |
| 556 | for (reg = 0; reg < IDEDMA_NREGS; reg++) { |
| 557 | size = 4; |
| 558 | if (size > (IDEDMA_SCH_OFFSET - reg)) |
| 559 | size = IDEDMA_SCH_OFFSET - reg; |
| 560 | if (bus_space_subregion(sc->sc_ba5_st, |
| 561 | sc->sc_ba5_sh, |
| 562 | satalink_ba5_regmap[chan].ba5_IDEDMA_CMD + reg, |
| 563 | size, &pc->dma_iohs[reg]) != 0) { |
| 564 | sc->sc_dma_ok = 0; |
| 565 | aprint_verbose(", but can't subregion offset " |
| 566 | "%lu size %lu" , |
| 567 | (u_long) satalink_ba5_regmap[ |
| 568 | chan].ba5_IDEDMA_CMD + reg, |
| 569 | (u_long) size); |
| 570 | return; |
| 571 | } |
| 572 | } |
| 573 | } |
| 574 | |
| 575 | /* DMA registers all set up! */ |
| 576 | sc->sc_dmat = pa->pa_dmat; |
| 577 | sc->sc_dma_ok = 1; |
| 578 | } |
| 579 | |
| 580 | static int |
| 581 | sii3114_chansetup(struct pciide_softc *sc, int channel) |
| 582 | { |
| 583 | static const char *channel_names[] = { |
| 584 | "port 0" , |
| 585 | "port 1" , |
| 586 | "port 2" , |
| 587 | "port 3" , |
| 588 | }; |
| 589 | struct pciide_channel *cp = &sc->pciide_channels[channel]; |
| 590 | |
| 591 | sc->wdc_chanarray[channel] = &cp->ata_channel; |
| 592 | |
| 593 | /* |
| 594 | * We must always keep the Interrupt Steering bit set in channel 2's |
| 595 | * IDEDMA_CMD register. |
| 596 | */ |
| 597 | if (channel == 2) |
| 598 | cp->idedma_cmd = IDEDMA_CMD_INT_STEER; |
| 599 | |
| 600 | cp->name = channel_names[channel]; |
| 601 | cp->ata_channel.ch_channel = channel; |
| 602 | cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; |
| 603 | cp->ata_channel.ch_queue = |
| 604 | malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); |
| 605 | if (cp->ata_channel.ch_queue == NULL) { |
| 606 | aprint_error("%s %s channel: " |
| 607 | "can't allocate memory for command queue" , |
| 608 | device_xname(sc->sc_wdcdev.sc_atac.atac_dev), cp->name); |
| 609 | return (0); |
| 610 | } |
| 611 | return (1); |
| 612 | } |
| 613 | |
| 614 | static void |
| 615 | sii3114_mapchan(struct pciide_channel *cp) |
| 616 | { |
| 617 | struct ata_channel *wdc_cp = &cp->ata_channel; |
| 618 | struct pciide_softc *sc = CHAN_TO_PCIIDE(wdc_cp); |
| 619 | struct wdc_regs *wdr = CHAN_TO_WDC_REGS(wdc_cp); |
| 620 | int i; |
| 621 | |
| 622 | cp->compat = 0; |
| 623 | cp->ih = sc->sc_pci_ih; |
| 624 | |
| 625 | wdr->cmd_iot = sc->sc_ba5_st; |
| 626 | if (bus_space_subregion(sc->sc_ba5_st, sc->sc_ba5_sh, |
| 627 | satalink_ba5_regmap[wdc_cp->ch_channel].ba5_IDE_TF0, |
| 628 | 9, &wdr->cmd_baseioh) != 0) { |
| 629 | aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 630 | "couldn't subregion %s cmd base\n" , cp->name); |
| 631 | goto bad; |
| 632 | } |
| 633 | |
| 634 | wdr->ctl_iot = sc->sc_ba5_st; |
| 635 | if (bus_space_subregion(sc->sc_ba5_st, sc->sc_ba5_sh, |
| 636 | satalink_ba5_regmap[wdc_cp->ch_channel].ba5_IDE_TF8, |
| 637 | 1, &cp->ctl_baseioh) != 0) { |
| 638 | aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 639 | "couldn't subregion %s ctl base\n" , cp->name); |
| 640 | goto bad; |
| 641 | } |
| 642 | wdr->ctl_ioh = cp->ctl_baseioh; |
| 643 | |
| 644 | for (i = 0; i < WDC_NREG; i++) { |
| 645 | if (bus_space_subregion(wdr->cmd_iot, wdr->cmd_baseioh, |
| 646 | i, i == 0 ? 4 : 1, |
| 647 | &wdr->cmd_iohs[i]) != 0) { |
| 648 | aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 649 | "couldn't subregion %s channel cmd regs\n" , |
| 650 | cp->name); |
| 651 | goto bad; |
| 652 | } |
| 653 | } |
| 654 | wdc_init_shadow_regs(wdc_cp); |
| 655 | wdr->data32iot = wdr->cmd_iot; |
| 656 | wdr->data32ioh = wdr->cmd_iohs[0]; |
| 657 | wdcattach(wdc_cp); |
| 658 | return; |
| 659 | |
| 660 | bad: |
| 661 | cp->ata_channel.ch_flags |= ATACH_DISABLED; |
| 662 | } |
| 663 | |
| 664 | static void |
| 665 | sii3114_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa) |
| 666 | { |
| 667 | struct pciide_channel *cp; |
| 668 | pcireg_t scs_cmd; |
| 669 | pci_intr_handle_t intrhandle; |
| 670 | const char *intrstr; |
| 671 | int channel; |
| 672 | char intrbuf[PCI_INTRSTR_LEN]; |
| 673 | |
| 674 | if (pciide_chipen(sc, pa) == 0) |
| 675 | return; |
| 676 | |
| 677 | #define SII3114_RESET_BITS \ |
| 678 | (SCS_CMD_PBM_RESET | SCS_CMD_ARB_RESET | \ |
| 679 | SCS_CMD_FF1_RESET | SCS_CMD_FF0_RESET | \ |
| 680 | SCS_CMD_FF3_RESET | SCS_CMD_FF2_RESET | \ |
| 681 | SCS_CMD_IDE1_RESET | SCS_CMD_IDE0_RESET | \ |
| 682 | SCS_CMD_IDE3_RESET | SCS_CMD_IDE2_RESET) |
| 683 | |
| 684 | /* |
| 685 | * Reset everything and then unblock all of the interrupts. |
| 686 | */ |
| 687 | scs_cmd = pci_conf_read(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD); |
| 688 | pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD, |
| 689 | scs_cmd | SII3114_RESET_BITS); |
| 690 | delay(50 * 1000); |
| 691 | pci_conf_write(pa->pa_pc, pa->pa_tag, SII3112_SCS_CMD, |
| 692 | scs_cmd & SCS_CMD_M66EN); |
| 693 | delay(50 * 1000); |
| 694 | |
| 695 | /* |
| 696 | * On the 3114, the BA5 register space is always enabled. In |
| 697 | * order to use the 3114 in any sane way, we must use this BA5 |
| 698 | * register space, and so we consider it an error if we cannot |
| 699 | * map it. |
| 700 | * |
| 701 | * As a consequence of using BA5, our register mapping is different |
| 702 | * from a normal PCI IDE controller's, and so we are unable to use |
| 703 | * most of the common PCI IDE register mapping functions. |
| 704 | */ |
| 705 | if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x14, |
| 706 | PCI_MAPREG_TYPE_MEM| |
| 707 | PCI_MAPREG_MEM_TYPE_32BIT, 0, |
| 708 | &sc->sc_ba5_st, &sc->sc_ba5_sh, |
| 709 | NULL, &sc->sc_ba5_ss) != 0) { |
| 710 | aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 711 | "unable to map SATALink BA5 register space\n" ); |
| 712 | return; |
| 713 | } |
| 714 | sc->sc_ba5_en = 1; |
| 715 | |
| 716 | aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 717 | "%dMHz PCI bus\n" , (scs_cmd & SCS_CMD_M66EN) ? 66 : 33); |
| 718 | |
| 719 | /* |
| 720 | * Set the Interrupt Steering bit in the IDEDMA_CMD register of |
| 721 | * channel 2. This is required at all times for proper operation |
| 722 | * when using the BA5 register space (otherwise interrupts from |
| 723 | * all 4 channels won't work). |
| 724 | */ |
| 725 | BA5_WRITE_4(sc, 2, ba5_IDEDMA_CMD, IDEDMA_CMD_INT_STEER); |
| 726 | |
| 727 | aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 728 | "bus-master DMA support present" ); |
| 729 | sii3114_mapreg_dma(sc, pa); |
| 730 | aprint_verbose("\n" ); |
| 731 | |
| 732 | sii_fixup_cacheline(sc, pa, 4); |
| 733 | |
| 734 | sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DATA16 | ATAC_CAP_DATA32; |
| 735 | sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; |
| 736 | if (sc->sc_dma_ok) { |
| 737 | sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA; |
| 738 | sc->sc_wdcdev.irqack = pciide_irqack; |
| 739 | sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; |
| 740 | sc->sc_wdcdev.sc_atac.atac_udma_cap = 6; |
| 741 | } |
| 742 | sc->sc_wdcdev.sc_atac.atac_set_modes = sii3112_setup_channel; |
| 743 | |
| 744 | /* We can use SControl and SStatus to probe for drives. */ |
| 745 | sc->sc_wdcdev.sc_atac.atac_probe = sii3112_drv_probe; |
| 746 | |
| 747 | sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; |
| 748 | sc->sc_wdcdev.sc_atac.atac_nchannels = 4; |
| 749 | sc->sc_wdcdev.wdc_maxdrives = 1; |
| 750 | |
| 751 | wdc_allocate_regs(&sc->sc_wdcdev); |
| 752 | |
| 753 | /* Map and establish the interrupt handler. */ |
| 754 | if (pci_intr_map(pa, &intrhandle) != 0) { |
| 755 | aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 756 | "couldn't map native-PCI interrupt\n" ); |
| 757 | return; |
| 758 | } |
| 759 | intrstr = pci_intr_string(pa->pa_pc, intrhandle, intrbuf, sizeof(intrbuf)); |
| 760 | sc->sc_pci_ih = pci_intr_establish(pa->pa_pc, intrhandle, IPL_BIO, |
| 761 | /* XXX */ |
| 762 | pciide_pci_intr, sc); |
| 763 | if (sc->sc_pci_ih != NULL) { |
| 764 | aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 765 | "using %s for native-PCI interrupt\n" , |
| 766 | intrstr ? intrstr : "unknown interrupt" ); |
| 767 | } else { |
| 768 | aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 769 | "couldn't establish native-PCI interrupt" ); |
| 770 | if (intrstr != NULL) |
| 771 | aprint_error(" at %s" , intrstr); |
| 772 | aprint_error("\n" ); |
| 773 | return; |
| 774 | } |
| 775 | |
| 776 | for (channel = 0; channel < sc->sc_wdcdev.sc_atac.atac_nchannels; |
| 777 | channel++) { |
| 778 | cp = &sc->pciide_channels[channel]; |
| 779 | if (sii3114_chansetup(sc, channel) == 0) |
| 780 | continue; |
| 781 | sii3114_mapchan(cp); |
| 782 | } |
| 783 | } |
| 784 | |
| 785 | /* Probe the drives using SATA registers. |
| 786 | * Note we can't use wdc_sataprobe as we may not be able to map ba5 |
| 787 | */ |
| 788 | static void |
| 789 | sii3112_drv_probe(struct ata_channel *chp) |
| 790 | { |
| 791 | struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); |
| 792 | struct wdc_regs *wdr = CHAN_TO_WDC_REGS(chp); |
| 793 | uint32_t scontrol, sstatus; |
| 794 | uint8_t /* scnt, sn, */ cl, ch; |
| 795 | int s; |
| 796 | |
| 797 | /* |
| 798 | * The 3112 is a 2-port part, and only has one drive per channel |
| 799 | * (each port emulates a master drive). |
| 800 | * |
| 801 | * The 3114 is similar, but has 4 channels. |
| 802 | */ |
| 803 | |
| 804 | /* |
| 805 | * Request communication initialization sequence, any speed. |
| 806 | * Performing this is the equivalent of an ATA Reset. |
| 807 | */ |
| 808 | scontrol = SControl_DET_INIT | SControl_SPD_ANY; |
| 809 | |
| 810 | /* |
| 811 | * XXX We don't yet support SATA power management; disable all |
| 812 | * power management state transitions. |
| 813 | */ |
| 814 | scontrol |= SControl_IPM_NONE; |
| 815 | |
| 816 | BA5_WRITE_4(sc, chp->ch_channel, ba5_SControl, scontrol); |
| 817 | delay(50 * 1000); |
| 818 | scontrol &= ~SControl_DET_INIT; |
| 819 | BA5_WRITE_4(sc, chp->ch_channel, ba5_SControl, scontrol); |
| 820 | delay(50 * 1000); |
| 821 | |
| 822 | sstatus = BA5_READ_4(sc, chp->ch_channel, ba5_SStatus); |
| 823 | #if 0 |
| 824 | aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 825 | "port %d: SStatus=0x%08x, SControl=0x%08x\n" , |
| 826 | chp->ch_channel, sstatus, |
| 827 | BA5_READ_4(sc, chp->ch_channel, ba5_SControl)); |
| 828 | #endif |
| 829 | switch (sstatus & SStatus_DET_mask) { |
| 830 | case SStatus_DET_NODEV: |
| 831 | /* No device; be silent. */ |
| 832 | break; |
| 833 | |
| 834 | case SStatus_DET_DEV_NE: |
| 835 | aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 836 | "port %d: device connected, but " |
| 837 | "communication not established\n" , chp->ch_channel); |
| 838 | break; |
| 839 | |
| 840 | case SStatus_DET_OFFLINE: |
| 841 | aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 842 | "port %d: PHY offline\n" , chp->ch_channel); |
| 843 | break; |
| 844 | |
| 845 | case SStatus_DET_DEV: |
| 846 | /* |
| 847 | * XXX ATAPI detection doesn't currently work. Don't |
| 848 | * XXX know why. But, it's not like the standard method |
| 849 | * XXX can detect an ATAPI device connected via a SATA/PATA |
| 850 | * XXX bridge, so at least this is no worse. --thorpej |
| 851 | */ |
| 852 | bus_space_write_1(wdr->cmd_iot, wdr->cmd_iohs[wd_sdh], 0, |
| 853 | WDSD_IBM | (0 << 4)); |
| 854 | delay(10); /* 400ns delay */ |
| 855 | /* Save register contents. */ |
| 856 | #if 0 |
| 857 | scnt = bus_space_read_1(wdr->cmd_iot, |
| 858 | wdr->cmd_iohs[wd_seccnt], 0); |
| 859 | sn = bus_space_read_1(wdr->cmd_iot, |
| 860 | wdr->cmd_iohs[wd_sector], 0); |
| 861 | #endif |
| 862 | cl = bus_space_read_1(wdr->cmd_iot, |
| 863 | wdr->cmd_iohs[wd_cyl_lo], 0); |
| 864 | ch = bus_space_read_1(wdr->cmd_iot, |
| 865 | wdr->cmd_iohs[wd_cyl_hi], 0); |
| 866 | #if 0 |
| 867 | printf("%s: port %d: scnt=0x%x sn=0x%x cl=0x%x ch=0x%x\n" , |
| 868 | device_xname(sc->sc_wdcdev.sc_atac.atac_dev), chp->ch_channel, |
| 869 | scnt, sn, cl, ch); |
| 870 | #endif |
| 871 | if (atabus_alloc_drives(chp, 1) != 0) |
| 872 | return; |
| 873 | /* |
| 874 | * scnt and sn are supposed to be 0x1 for ATAPI, but in some |
| 875 | * cases we get wrong values here, so ignore it. |
| 876 | */ |
| 877 | s = splbio(); |
| 878 | if (cl == 0x14 && ch == 0xeb) |
| 879 | chp->ch_drive[0].drive_type = ATA_DRIVET_ATAPI; |
| 880 | else |
| 881 | chp->ch_drive[0].drive_type = ATA_DRIVET_ATA; |
| 882 | splx(s); |
| 883 | |
| 884 | aprint_normal_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 885 | "port %d: device present, speed: %s\n" , |
| 886 | chp->ch_channel, |
| 887 | sata_speed(sstatus)); |
| 888 | break; |
| 889 | |
| 890 | default: |
| 891 | aprint_error_dev(sc->sc_wdcdev.sc_atac.atac_dev, |
| 892 | "port %d: unknown SStatus: 0x%08x\n" , |
| 893 | chp->ch_channel, sstatus); |
| 894 | } |
| 895 | } |
| 896 | |
| 897 | static void |
| 898 | sii3112_setup_channel(struct ata_channel *chp) |
| 899 | { |
| 900 | struct ata_drive_datas *drvp; |
| 901 | int drive, s; |
| 902 | u_int32_t idedma_ctl, dtm; |
| 903 | struct pciide_channel *cp = CHAN_TO_PCHAN(chp); |
| 904 | struct pciide_softc *sc = CHAN_TO_PCIIDE(chp); |
| 905 | |
| 906 | /* setup DMA if needed */ |
| 907 | pciide_channel_dma_setup(cp); |
| 908 | |
| 909 | idedma_ctl = 0; |
| 910 | dtm = 0; |
| 911 | |
| 912 | for (drive = 0; drive < 2; drive++) { |
| 913 | drvp = &chp->ch_drive[drive]; |
| 914 | /* If no drive, skip */ |
| 915 | if (drvp->drive_type == ATA_DRIVET_NONE) |
| 916 | continue; |
| 917 | if (drvp->drive_flags & ATA_DRIVE_UDMA) { |
| 918 | /* use Ultra/DMA */ |
| 919 | s = splbio(); |
| 920 | drvp->drive_flags &= ~ATA_DRIVE_DMA; |
| 921 | splx(s); |
| 922 | idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); |
| 923 | dtm |= DTM_IDEx_DMA; |
| 924 | } else if (drvp->drive_flags & ATA_DRIVE_DMA) { |
| 925 | idedma_ctl |= IDEDMA_CTL_DRV_DMA(drive); |
| 926 | dtm |= DTM_IDEx_DMA; |
| 927 | } else { |
| 928 | dtm |= DTM_IDEx_PIO; |
| 929 | } |
| 930 | } |
| 931 | |
| 932 | /* |
| 933 | * Nothing to do to setup modes; it is meaningless in S-ATA |
| 934 | * (but many S-ATA drives still want to get the SET_FEATURE |
| 935 | * command). |
| 936 | */ |
| 937 | if (idedma_ctl != 0) { |
| 938 | /* Add software bits in status register */ |
| 939 | bus_space_write_1(sc->sc_dma_iot, cp->dma_iohs[IDEDMA_CTL], 0, |
| 940 | idedma_ctl); |
| 941 | } |
| 942 | BA5_WRITE_4(sc, chp->ch_channel, ba5_IDE_DTM, dtm); |
| 943 | } |
| 944 | |