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 sizeof(struct sili_prb) * SILI_MAX_CMDS, 217 /* [max]size */ 218 1, /* maxsegs */ 219 sizeof(struct sili_prb) * SILI_MAX_CMDS, 220 /* maxsegsz */ 221 0, /* flags */ 222 &sc->sc_tag_prbs); /* return tag */ 223 224 /* 225 * The data tag is used for later dmamaps and not immediately 226 * allocated. 227 */ 228 error += bus_dma_tag_create( 229 NULL, /* parent tag */ 230 4, /* alignment */ 231 0, /* boundary */ 232 addr, /* loaddr? */ 233 BUS_SPACE_MAXADDR, /* hiaddr */ 234 4096 * 1024, /* maxiosize */ 235 SILI_MAX_SGET, /* maxsegs */ 236 65536, /* maxsegsz */ 237 0, /* flags */ 238 &sc->sc_tag_data); /* return tag */ 239 240 if (error) { 241 device_printf(dev, "unable to create dma tags\n"); 242 sili_pci_detach(dev); 243 return (ENXIO); 244 } 245 246 if (sili_read(sc, SILI_REG_GCTL) & SILI_REG_GCTL_300CAP) { 247 gen = "1 (1.5Gbps) and 2 (3Gbps)"; 248 sc->sc_flags |= SILI_F_300; 249 } else { 250 gen = "1 (1.5Gbps)"; 251 } 252 253 nports = sc->sc_ad->ad_nports; 254 KKASSERT(nports <= SILI_MAX_PORTS); 255 256 device_printf(dev, "ports=%d tags=31, gen %s, cap=NCQ,FBSS,SPM\n", 257 nports, gen); 258 259 /* 260 * Allocate per-port resources 261 * 262 * All ports are attached in parallel but the CAM scan-bus 263 * is held up until all ports are attached so we get a deterministic 264 * order. 265 */ 266 for (i = 0; error == 0 && i < nports; i++) { 267 error = sili_port_alloc(sc, i); 268 } 269 270 /* 271 * Setup the interrupt vector and enable interrupts. Note that 272 * since the irq may be shared we do not set it up until we are 273 * ready to go. 274 */ 275 if (error == 0) { 276 error = bus_setup_intr(dev, sc->sc_irq, INTR_MPSAFE, 277 sili_intr, sc, 278 &sc->sc_irq_handle, NULL); 279 } 280 281 if (error) { 282 device_printf(dev, "unable to install interrupt\n"); 283 sili_pci_detach(dev); 284 return (ENXIO); 285 } 286 287 /* 288 * Interrupt subsystem is good to go now, enable all port interrupts 289 */ 290 crit_enter(); 291 reg = sili_read(sc, SILI_REG_GCTL); 292 for (i = 0; i < nports; ++i) 293 reg |= SILI_REG_GCTL_PORTEN(i); 294 sili_write(sc, SILI_REG_GCTL, reg); 295 sc->sc_flags |= SILI_F_INT_GOOD; 296 crit_exit(); 297 sili_intr(sc); 298 299 /* 300 * All ports are probing in parallel. Wait for them to finish 301 * and then issue the cam attachment and bus scan serially so 302 * the 'da' assignments are deterministic. 303 */ 304 for (i = 0; i < nports; i++) { 305 if ((ap = sc->sc_ports[i]) != NULL) { 306 while (ap->ap_signal & AP_SIGF_INIT) 307 tsleep(&ap->ap_signal, 0, "ahprb1", hz); 308 sili_os_lock_port(ap); 309 if (sili_cam_attach(ap) == 0) { 310 sili_cam_changed(ap, NULL, -1); 311 sili_os_unlock_port(ap); 312 while ((ap->ap_flags & AP_F_SCAN_COMPLETED) == 0) { 313 tsleep(&ap->ap_flags, 0, "ahprb2", hz); 314 } 315 } else { 316 sili_os_unlock_port(ap); 317 } 318 } 319 } 320 321 return(0); 322 } 323 324 /* 325 * Device unload / detachment 326 */ 327 static int 328 sili_pci_detach(device_t dev) 329 { 330 struct sili_softc *sc = device_get_softc(dev); 331 struct sili_port *ap; 332 int i; 333 334 /* 335 * Disable the controller and de-register the interrupt, if any. 336 * 337 * XXX interlock last interrupt? 338 */ 339 sc->sc_flags &= ~SILI_F_INT_GOOD; 340 if (sc->sc_regs) 341 sili_write(sc, SILI_REG_GCTL, SILI_REG_GCTL_GRESET); 342 343 if (sc->sc_irq_handle) { 344 bus_teardown_intr(dev, sc->sc_irq, sc->sc_irq_handle); 345 sc->sc_irq_handle = NULL; 346 } 347 348 /* 349 * Free port structures and DMA memory 350 */ 351 for (i = 0; i < SILI_MAX_PORTS; i++) { 352 ap = sc->sc_ports[i]; 353 if (ap) { 354 sili_cam_detach(ap); 355 sili_port_free(sc, i); 356 } 357 } 358 359 /* 360 * Clean up the bus space 361 */ 362 if (sc->sc_irq) { 363 bus_release_resource(dev, SYS_RES_IRQ, 364 sc->sc_rid_irq, sc->sc_irq); 365 sc->sc_irq = NULL; 366 } 367 if (sc->sc_irq_type == PCI_INTR_TYPE_MSI) 368 pci_release_msi(dev); 369 370 if (sc->sc_regs) { 371 bus_release_resource(dev, SYS_RES_MEMORY, 372 sc->sc_rid_regs, sc->sc_regs); 373 sc->sc_regs = NULL; 374 } 375 if (sc->sc_pregs) { 376 bus_release_resource(dev, SYS_RES_MEMORY, 377 sc->sc_rid_pregs, sc->sc_pregs); 378 sc->sc_regs = NULL; 379 } 380 381 if (sc->sc_tag_prbs) { 382 bus_dma_tag_destroy(sc->sc_tag_prbs); 383 sc->sc_tag_prbs = NULL; 384 } 385 if (sc->sc_tag_data) { 386 bus_dma_tag_destroy(sc->sc_tag_data); 387 sc->sc_tag_data = NULL; 388 } 389 390 return (0); 391 } 392