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