1 /* 2 * (MPSAFE) 3 * 4 * Copyright (c) 2006 David Gwynne <dlg@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * 19 * Copyright (c) 2009 The DragonFly Project. All rights reserved. 20 * 21 * This code is derived from software contributed to The DragonFly Project 22 * by Matthew Dillon <dillon@backplane.com> 23 * 24 * Redistribution and use in source and binary forms, with or without 25 * modification, are permitted provided that the following conditions 26 * are met: 27 * 28 * 1. Redistributions of source code must retain the above copyright 29 * notice, this list of conditions and the following disclaimer. 30 * 2. Redistributions in binary form must reproduce the above copyright 31 * notice, this list of conditions and the following disclaimer in 32 * the documentation and/or other materials provided with the 33 * distribution. 34 * 3. Neither the name of The DragonFly Project nor the names of its 35 * contributors may be used to endorse or promote products derived 36 * from this software without specific, prior written permission. 37 * 38 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 39 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 40 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 41 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 42 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 43 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 44 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 46 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 47 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 48 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 49 * SUCH DAMAGE. 50 * 51 * $OpenBSD: sili.c,v 1.147 2009/02/16 21:19:07 miod Exp $ 52 */ 53 54 #include "sili.h" 55 56 static int sili_pci_attach(device_t); 57 static int sili_pci_detach(device_t); 58 59 static const struct sili_device sili_devices[] = { 60 { 61 .ad_vendor = PCI_VENDOR_SII, 62 .ad_product = PCI_PRODUCT_SII_3132, 63 .ad_nports = 2, 64 .ad_attach = sili_pci_attach, 65 .ad_detach = sili_pci_detach, 66 .name = "SiliconImage-3132-SATA" 67 }, 68 { 69 .ad_vendor = PCI_VENDOR_SII, 70 .ad_product = 0x3124, 71 .ad_nports = 4, 72 .ad_attach = sili_pci_attach, 73 .ad_detach = sili_pci_detach, 74 .name = "Rosewill-3124-SATA" 75 }, 76 { 0, 0, 0, NULL, NULL, NULL } 77 }; 78 79 /* 80 * Don't enable MSI by default; it does not seem to 81 * work at all on Silicon Image 3132. 82 */ 83 static int sili_msi_enable = 0; 84 TUNABLE_INT("hw.sili.msi.enable", &sili_msi_enable); 85 86 /* 87 * Match during probe and attach. The device does not yet have a softc. 88 */ 89 const struct sili_device * 90 sili_lookup_device(device_t dev) 91 { 92 const struct sili_device *ad; 93 u_int16_t vendor = pci_get_vendor(dev); 94 u_int16_t product = pci_get_device(dev); 95 #if 0 96 u_int8_t class = pci_get_class(dev); 97 u_int8_t subclass = pci_get_subclass(dev); 98 u_int8_t progif = pci_read_config(dev, PCIR_PROGIF, 1); 99 #endif 100 101 for (ad = &sili_devices[0]; ad->ad_vendor; ++ad) { 102 if (ad->ad_vendor == vendor && ad->ad_product == product) 103 return (ad); 104 } 105 return (NULL); 106 #if 0 107 /* 108 * Last ad is the default match if the PCI device matches SATA. 109 */ 110 if (class == PCIC_STORAGE && subclass == PCIS_STORAGE_SATA && 111 progif == PCIP_STORAGE_SATA_SILI_1_0) { 112 return (ad); 113 } 114 return (NULL); 115 #endif 116 } 117 118 static int 119 sili_pci_attach(device_t dev) 120 { 121 struct sili_softc *sc = device_get_softc(dev); 122 struct sili_port *ap; 123 const char *gen; 124 u_int32_t nports, reg; 125 bus_addr_t addr; 126 int i, error, msi_enable; 127 u_int irq_flags; 128 129 /* 130 * Map the SILI controller's IRQ, BAR(0) (global regs), 131 * and BAR(1) (port regs and lram). 132 */ 133 134 msi_enable = sili_msi_enable; 135 if (!pci_is_pcie(dev)) { 136 /* 137 * Don't enable MSI on PCI devices by default; 138 * well, this may cause less trouble. 139 */ 140 msi_enable = 0; 141 } 142 sc->sc_irq_type = pci_alloc_1intr(dev, msi_enable, &sc->sc_rid_irq, 143 &irq_flags); 144 145 sc->sc_dev = dev; 146 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_rid_irq, 147 irq_flags); 148 if (sc->sc_irq == NULL) { 149 device_printf(dev, "unable to map interrupt\n"); 150 sili_pci_detach(dev); 151 return (ENXIO); 152 } 153 154 /* 155 * When mapping the register window store the tag and handle 156 * separately so we can use the tag with per-port bus handle 157 * sub-spaces. 158 */ 159 sc->sc_rid_regs = PCIR_BAR(0); 160 sc->sc_regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 161 &sc->sc_rid_regs, RF_ACTIVE); 162 if (sc->sc_regs == NULL) { 163 device_printf(dev, "unable to map registers\n"); 164 sili_pci_detach(dev); 165 return (ENXIO); 166 } 167 sc->sc_iot = rman_get_bustag(sc->sc_regs); 168 sc->sc_ioh = rman_get_bushandle(sc->sc_regs); 169 170 sc->sc_rid_pregs = PCIR_BAR(2); 171 sc->sc_pregs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 172 &sc->sc_rid_pregs, RF_ACTIVE); 173 if (sc->sc_pregs == NULL) { 174 device_printf(dev, "unable to map port registers\n"); 175 sili_pci_detach(dev); 176 return (ENXIO); 177 } 178 sc->sc_piot = rman_get_bustag(sc->sc_pregs); 179 sc->sc_pioh = rman_get_bushandle(sc->sc_pregs); 180 181 /* 182 * Initialize the chipset and then set the interrupt vector up 183 */ 184 error = sili_init(sc); 185 if (error) { 186 sili_pci_detach(dev); 187 return (ENXIO); 188 } 189 190 /* 191 * We assume at least 4 commands. 192 */ 193 sc->sc_ncmds = SILI_MAX_CMDS; 194 sc->sc_flags |= SILI_F_64BIT; 195 sc->sc_flags |= SILI_F_NCQ; 196 sc->sc_flags |= SILI_F_SSNTF; 197 sc->sc_flags |= SILI_F_SPM; 198 199 addr = (sc->sc_flags & SILI_F_64BIT) ? 200 BUS_SPACE_MAXADDR : BUS_SPACE_MAXADDR_32BIT; 201 202 /* 203 * DMA tags for allocation of DMA memory buffers, lists, and so 204 * forth. These are typically per-port. 205 * 206 * The stuff is mostly built into the BAR mappings. We only need 207 * tags for our external SGE list and data. 208 */ 209 error = 0; 210 error += bus_dma_tag_create( 211 NULL, /* parent tag */ 212 256, /* alignment */ 213 65536, /* boundary */ 214 addr, /* loaddr? */ 215 BUS_SPACE_MAXADDR, /* hiaddr */ 216 NULL, /* filter */ 217 NULL, /* filterarg */ 218 sizeof(struct sili_prb) * SILI_MAX_CMDS, 219 /* [max]size */ 220 1, /* maxsegs */ 221 sizeof(struct sili_prb) * SILI_MAX_CMDS, 222 /* maxsegsz */ 223 0, /* flags */ 224 &sc->sc_tag_prbs); /* return tag */ 225 226 /* 227 * The data tag is used for later dmamaps and not immediately 228 * allocated. 229 */ 230 error += bus_dma_tag_create( 231 NULL, /* parent tag */ 232 4, /* alignment */ 233 0, /* boundary */ 234 addr, /* loaddr? */ 235 BUS_SPACE_MAXADDR, /* hiaddr */ 236 NULL, /* filter */ 237 NULL, /* filterarg */ 238 4096 * 1024, /* maxiosize */ 239 SILI_MAX_SGET, /* maxsegs */ 240 65536, /* maxsegsz */ 241 0, /* flags */ 242 &sc->sc_tag_data); /* return tag */ 243 244 if (error) { 245 device_printf(dev, "unable to create dma tags\n"); 246 sili_pci_detach(dev); 247 return (ENXIO); 248 } 249 250 if (sili_read(sc, SILI_REG_GCTL) & SILI_REG_GCTL_300CAP) { 251 gen = "1 (1.5Gbps) and 2 (3Gbps)"; 252 sc->sc_flags |= SILI_F_300; 253 } else { 254 gen = "1 (1.5Gbps)"; 255 } 256 257 nports = sc->sc_ad->ad_nports; 258 KKASSERT(nports <= SILI_MAX_PORTS); 259 260 device_printf(dev, "ports=%d tags=31, gen %s, cap=NCQ,FBSS,SPM\n", 261 nports, gen); 262 263 /* 264 * Allocate per-port resources 265 * 266 * All ports are attached in parallel but the CAM scan-bus 267 * is held up until all ports are attached so we get a deterministic 268 * order. 269 */ 270 for (i = 0; error == 0 && i < nports; i++) { 271 error = sili_port_alloc(sc, i); 272 } 273 274 /* 275 * Setup the interrupt vector and enable interrupts. Note that 276 * since the irq may be shared we do not set it up until we are 277 * ready to go. 278 */ 279 if (error == 0) { 280 error = bus_setup_intr(dev, sc->sc_irq, INTR_MPSAFE, 281 sili_intr, sc, 282 &sc->sc_irq_handle, NULL); 283 } 284 285 if (error) { 286 device_printf(dev, "unable to install interrupt\n"); 287 sili_pci_detach(dev); 288 return (ENXIO); 289 } 290 291 /* 292 * Interrupt subsystem is good to go now, enable all port interrupts 293 */ 294 crit_enter(); 295 reg = sili_read(sc, SILI_REG_GCTL); 296 for (i = 0; i < nports; ++i) 297 reg |= SILI_REG_GCTL_PORTEN(i); 298 sili_write(sc, SILI_REG_GCTL, reg); 299 sc->sc_flags |= SILI_F_INT_GOOD; 300 crit_exit(); 301 sili_intr(sc); 302 303 /* 304 * All ports are probing in parallel. Wait for them to finish 305 * and then issue the cam attachment and bus scan serially so 306 * the 'da' assignments are deterministic. 307 */ 308 for (i = 0; i < nports; i++) { 309 if ((ap = sc->sc_ports[i]) != NULL) { 310 while (ap->ap_signal & AP_SIGF_INIT) 311 tsleep(&ap->ap_signal, 0, "ahprb1", hz); 312 sili_os_lock_port(ap); 313 if (sili_cam_attach(ap) == 0) { 314 sili_cam_changed(ap, NULL, -1); 315 sili_os_unlock_port(ap); 316 while ((ap->ap_flags & AP_F_SCAN_COMPLETED) == 0) { 317 tsleep(&ap->ap_flags, 0, "ahprb2", hz); 318 } 319 } else { 320 sili_os_unlock_port(ap); 321 } 322 } 323 } 324 325 return(0); 326 } 327 328 /* 329 * Device unload / detachment 330 */ 331 static int 332 sili_pci_detach(device_t dev) 333 { 334 struct sili_softc *sc = device_get_softc(dev); 335 struct sili_port *ap; 336 int i; 337 338 /* 339 * Disable the controller and de-register the interrupt, if any. 340 * 341 * XXX interlock last interrupt? 342 */ 343 sc->sc_flags &= ~SILI_F_INT_GOOD; 344 if (sc->sc_regs) 345 sili_write(sc, SILI_REG_GCTL, SILI_REG_GCTL_GRESET); 346 347 if (sc->sc_irq_handle) { 348 bus_teardown_intr(dev, sc->sc_irq, sc->sc_irq_handle); 349 sc->sc_irq_handle = NULL; 350 } 351 352 /* 353 * Free port structures and DMA memory 354 */ 355 for (i = 0; i < SILI_MAX_PORTS; i++) { 356 ap = sc->sc_ports[i]; 357 if (ap) { 358 sili_cam_detach(ap); 359 sili_port_free(sc, i); 360 } 361 } 362 363 /* 364 * Clean up the bus space 365 */ 366 if (sc->sc_irq) { 367 bus_release_resource(dev, SYS_RES_IRQ, 368 sc->sc_rid_irq, sc->sc_irq); 369 sc->sc_irq = NULL; 370 } 371 if (sc->sc_irq_type == PCI_INTR_TYPE_MSI) 372 pci_release_msi(dev); 373 374 if (sc->sc_regs) { 375 bus_release_resource(dev, SYS_RES_MEMORY, 376 sc->sc_rid_regs, sc->sc_regs); 377 sc->sc_regs = NULL; 378 } 379 if (sc->sc_pregs) { 380 bus_release_resource(dev, SYS_RES_MEMORY, 381 sc->sc_rid_pregs, sc->sc_pregs); 382 sc->sc_regs = NULL; 383 } 384 385 if (sc->sc_tag_prbs) { 386 bus_dma_tag_destroy(sc->sc_tag_prbs); 387 sc->sc_tag_prbs = NULL; 388 } 389 if (sc->sc_tag_data) { 390 bus_dma_tag_destroy(sc->sc_tag_data); 391 sc->sc_tag_data = NULL; 392 } 393 394 return (0); 395 } 396