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 * Match during probe and attach. The device does not yet have a softc. 81 */ 82 const struct sili_device * 83 sili_lookup_device(device_t dev) 84 { 85 const struct sili_device *ad; 86 u_int16_t vendor = pci_get_vendor(dev); 87 u_int16_t product = pci_get_device(dev); 88 #if 0 89 u_int8_t class = pci_get_class(dev); 90 u_int8_t subclass = pci_get_subclass(dev); 91 u_int8_t progif = pci_read_config(dev, PCIR_PROGIF, 1); 92 #endif 93 94 for (ad = &sili_devices[0]; ad->ad_vendor; ++ad) { 95 if (ad->ad_vendor == vendor && ad->ad_product == product) 96 return (ad); 97 } 98 return (NULL); 99 #if 0 100 /* 101 * Last ad is the default match if the PCI device matches SATA. 102 */ 103 if (class == PCIC_STORAGE && subclass == PCIS_STORAGE_SATA && 104 progif == PCIP_STORAGE_SATA_SILI_1_0) { 105 return (ad); 106 } 107 return (NULL); 108 #endif 109 } 110 111 static int 112 sili_pci_attach(device_t dev) 113 { 114 struct sili_softc *sc = device_get_softc(dev); 115 struct sili_port *ap; 116 const char *gen; 117 u_int32_t nports, reg; 118 bus_addr_t addr; 119 int i; 120 int error; 121 122 /* 123 * Map the SILI controller's IRQ, BAR(0) (global regs), 124 * and BAR(1) (port regs and lram). 125 */ 126 sc->sc_dev = dev; 127 sc->sc_rid_irq = SILI_IRQ_RID; 128 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_rid_irq, 129 RF_SHAREABLE | RF_ACTIVE); 130 if (sc->sc_irq == NULL) { 131 device_printf(dev, "unable to map interrupt\n"); 132 sili_pci_detach(dev); 133 return (ENXIO); 134 } 135 136 /* 137 * When mapping the register window store the tag and handle 138 * separately so we can use the tag with per-port bus handle 139 * sub-spaces. 140 */ 141 sc->sc_rid_regs = PCIR_BAR(0); 142 sc->sc_regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 143 &sc->sc_rid_regs, RF_ACTIVE); 144 if (sc->sc_regs == NULL) { 145 device_printf(dev, "unable to map registers\n"); 146 sili_pci_detach(dev); 147 return (ENXIO); 148 } 149 sc->sc_iot = rman_get_bustag(sc->sc_regs); 150 sc->sc_ioh = rman_get_bushandle(sc->sc_regs); 151 152 sc->sc_rid_pregs = PCIR_BAR(2); 153 sc->sc_pregs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 154 &sc->sc_rid_pregs, RF_ACTIVE); 155 if (sc->sc_pregs == NULL) { 156 device_printf(dev, "unable to map port registers\n"); 157 sili_pci_detach(dev); 158 return (ENXIO); 159 } 160 sc->sc_piot = rman_get_bustag(sc->sc_pregs); 161 sc->sc_pioh = rman_get_bushandle(sc->sc_pregs); 162 163 /* 164 * Initialize the chipset and then set the interrupt vector up 165 */ 166 error = sili_init(sc); 167 if (error) { 168 sili_pci_detach(dev); 169 return (ENXIO); 170 } 171 172 /* 173 * We assume at least 4 commands. 174 */ 175 sc->sc_ncmds = SILI_MAX_CMDS; 176 sc->sc_flags |= SILI_F_64BIT; 177 sc->sc_flags |= SILI_F_NCQ; 178 sc->sc_flags |= SILI_F_SSNTF; 179 sc->sc_flags |= SILI_F_SPM; 180 181 addr = (sc->sc_flags & SILI_F_64BIT) ? 182 BUS_SPACE_MAXADDR : BUS_SPACE_MAXADDR_32BIT; 183 184 /* 185 * DMA tags for allocation of DMA memory buffers, lists, and so 186 * forth. These are typically per-port. 187 * 188 * The stuff is mostly built into the BAR mappings. We only need 189 * tags for our external SGE list and data. 190 */ 191 error = 0; 192 error += bus_dma_tag_create( 193 NULL, /* parent tag */ 194 256, /* alignment */ 195 65536, /* boundary */ 196 addr, /* loaddr? */ 197 BUS_SPACE_MAXADDR, /* hiaddr */ 198 NULL, /* filter */ 199 NULL, /* filterarg */ 200 sizeof(struct sili_prb) * SILI_MAX_CMDS, 201 /* [max]size */ 202 1, /* maxsegs */ 203 sizeof(struct sili_prb) * SILI_MAX_CMDS, 204 /* maxsegsz */ 205 0, /* flags */ 206 &sc->sc_tag_prbs); /* return tag */ 207 208 /* 209 * The data tag is used for later dmamaps and not immediately 210 * allocated. 211 */ 212 error += bus_dma_tag_create( 213 NULL, /* parent tag */ 214 4, /* alignment */ 215 0, /* boundary */ 216 addr, /* loaddr? */ 217 BUS_SPACE_MAXADDR, /* hiaddr */ 218 NULL, /* filter */ 219 NULL, /* filterarg */ 220 4096 * 1024, /* maxiosize */ 221 SILI_MAX_SGET, /* maxsegs */ 222 65536, /* maxsegsz */ 223 0, /* flags */ 224 &sc->sc_tag_data); /* return tag */ 225 226 if (error) { 227 device_printf(dev, "unable to create dma tags\n"); 228 sili_pci_detach(dev); 229 return (ENXIO); 230 } 231 232 if (sili_read(sc, SILI_REG_GCTL) & SILI_REG_GCTL_300CAP) { 233 gen = "1 (1.5Gbps) and 2 (3Gbps)"; 234 sc->sc_flags |= SILI_F_300; 235 } else { 236 gen = "1 (1.5Gbps)"; 237 } 238 239 nports = sc->sc_ad->ad_nports; 240 KKASSERT(nports <= SILI_MAX_PORTS); 241 242 device_printf(dev, "ports=%d tags=31, cap=NCQ,FBSS,SPM\n", nports); 243 244 /* 245 * Allocate per-port resources 246 * 247 * All ports are attached in parallel but the CAM scan-bus 248 * is held up until all ports are attached so we get a deterministic 249 * order. 250 */ 251 for (i = 0; error == 0 && i < nports; i++) { 252 error = sili_port_alloc(sc, i); 253 } 254 255 /* 256 * Setup the interrupt vector and enable interrupts. Note that 257 * since the irq may be shared we do not set it up until we are 258 * ready to go. 259 */ 260 if (error == 0) { 261 error = bus_setup_intr(dev, sc->sc_irq, INTR_MPSAFE, 262 sili_intr, sc, 263 &sc->sc_irq_handle, NULL); 264 } 265 266 if (error) { 267 device_printf(dev, "unable to install interrupt\n"); 268 sili_pci_detach(dev); 269 return (ENXIO); 270 } 271 272 /* 273 * Interrupt subsystem is good to go now, enable all port interrupts 274 */ 275 crit_enter(); 276 reg = sili_read(sc, SILI_REG_GCTL); 277 for (i = 0; i < nports; ++i) 278 reg |= SILI_REG_GCTL_PORTEN(i); 279 sili_write(sc, SILI_REG_GCTL, reg); 280 sc->sc_flags |= SILI_F_INT_GOOD; 281 crit_exit(); 282 sili_intr(sc); 283 284 /* 285 * All ports are probing in parallel. Wait for them to finish 286 * and then issue the cam attachment and bus scan serially so 287 * the 'da' assignments are deterministic. 288 */ 289 for (i = 0; i < nports; i++) { 290 if ((ap = sc->sc_ports[i]) != NULL) { 291 while (ap->ap_signal & AP_SIGF_INIT) 292 tsleep(&ap->ap_signal, 0, "ahprb1", hz); 293 sili_os_lock_port(ap); 294 if (sili_cam_attach(ap) == 0) { 295 sili_cam_changed(ap, NULL, -1); 296 sili_os_unlock_port(ap); 297 while ((ap->ap_flags & AP_F_SCAN_COMPLETED) == 0) { 298 tsleep(&ap->ap_flags, 0, "ahprb2", hz); 299 } 300 } else { 301 sili_os_unlock_port(ap); 302 } 303 } 304 } 305 306 return(0); 307 } 308 309 /* 310 * Device unload / detachment 311 */ 312 static int 313 sili_pci_detach(device_t dev) 314 { 315 struct sili_softc *sc = device_get_softc(dev); 316 struct sili_port *ap; 317 int i; 318 319 /* 320 * Disable the controller and de-register the interrupt, if any. 321 * 322 * XXX interlock last interrupt? 323 */ 324 sc->sc_flags &= ~SILI_F_INT_GOOD; 325 if (sc->sc_regs) 326 sili_write(sc, SILI_REG_GCTL, SILI_REG_GCTL_GRESET); 327 328 if (sc->sc_irq_handle) { 329 bus_teardown_intr(dev, sc->sc_irq, sc->sc_irq_handle); 330 sc->sc_irq_handle = NULL; 331 } 332 333 /* 334 * Free port structures and DMA memory 335 */ 336 for (i = 0; i < SILI_MAX_PORTS; i++) { 337 ap = sc->sc_ports[i]; 338 if (ap) { 339 sili_cam_detach(ap); 340 sili_port_free(sc, i); 341 } 342 } 343 344 /* 345 * Clean up the bus space 346 */ 347 if (sc->sc_irq) { 348 bus_release_resource(dev, SYS_RES_IRQ, 349 sc->sc_rid_irq, sc->sc_irq); 350 sc->sc_irq = NULL; 351 } 352 if (sc->sc_regs) { 353 bus_release_resource(dev, SYS_RES_MEMORY, 354 sc->sc_rid_regs, sc->sc_regs); 355 sc->sc_regs = NULL; 356 } 357 if (sc->sc_pregs) { 358 bus_release_resource(dev, SYS_RES_MEMORY, 359 sc->sc_rid_pregs, sc->sc_pregs); 360 sc->sc_regs = NULL; 361 } 362 363 if (sc->sc_tag_prbs) { 364 bus_dma_tag_destroy(sc->sc_tag_prbs); 365 sc->sc_tag_prbs = NULL; 366 } 367 if (sc->sc_tag_data) { 368 bus_dma_tag_destroy(sc->sc_tag_data); 369 sc->sc_tag_data = NULL; 370 } 371 372 return (0); 373 } 374