1 /*- 2 * Copyright (c) 2003 M. Warner Losh. All Rights Reserved. 3 * Copyright (c) 2000,2001 Jonathan Chen. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: src/sys/dev/cardbus/cardbus.c,v 1.28 2002/11/27 17:30:41 imp Exp $ 27 * $FreeBSD @153896,@153900,@159532,@166104 merged 28 * $FreeBSD @169620,@169633 merged 29 * $DragonFly: src/sys/dev/pccard/cardbus/cardbus.c,v 1.13 2008/01/11 10:53:46 sephe Exp $ 30 */ 31 32 /* 33 * Cardbus Bus Driver 34 * 35 * much of the bus code was stolen directly from sys/pci/pci.c 36 * (Copyright (c) 1997, Stefan Esser <se@freebsd.org>) 37 * 38 * Written by Jonathan Chen <jon@freebsd.org> 39 */ 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/malloc.h> 44 #include <sys/module.h> 45 #include <sys/kernel.h> 46 #include <sys/sysctl.h> 47 48 #include <sys/bus.h> 49 #include <sys/rman.h> 50 51 #include <sys/pciio.h> 52 #include <bus/pci/pcivar.h> 53 #include <bus/pci/pcireg.h> 54 #include <bus/pci/pci_private.h> 55 56 #include <dev/pccard/cardbus/cardbusreg.h> 57 #include <dev/pccard/cardbus/cardbusvar.h> 58 #include <dev/pccard/cardbus/cardbus_cis.h> 59 #include <bus/pccard/pccard_cis.h> 60 #include <bus/pccard/pccardvar.h> 61 62 #include "power_if.h" 63 #include "pcib_if.h" 64 65 /* sysctl vars */ 66 SYSCTL_NODE(_hw, OID_AUTO, cardbus, CTLFLAG_RD, 0, "CardBus parameters"); 67 68 int cardbus_debug = 0; 69 TUNABLE_INT("hw.cardbus.debug", &cardbus_debug); 70 SYSCTL_INT(_hw_cardbus, OID_AUTO, debug, CTLFLAG_RW, 71 &cardbus_debug, 0, 72 "CardBus debug"); 73 74 int cardbus_cis_debug = 0; 75 TUNABLE_INT("hw.cardbus.cis_debug", &cardbus_cis_debug); 76 SYSCTL_INT(_hw_cardbus, OID_AUTO, cis_debug, CTLFLAG_RW, 77 &cardbus_cis_debug, 0, 78 "CardBus CIS debug"); 79 80 #define DPRINTF(a) if (cardbus_debug) kprintf a 81 #define DEVPRINTF(x) if (cardbus_debug) device_printf x 82 83 84 static int cardbus_attach(device_t cbdev); 85 static int cardbus_attach_card(device_t cbdev); 86 static int cardbus_detach(device_t cbdev); 87 static int cardbus_detach_card(device_t cbdev); 88 static void cardbus_device_setup_regs(pcicfgregs *cfg); 89 static void cardbus_driver_added(device_t cbdev, driver_t *driver); 90 static int cardbus_probe(device_t cbdev); 91 static int cardbus_read_ivar(device_t cbdev, device_t child, int which, 92 uintptr_t *result); 93 static void cardbus_release_all_resources(device_t cbdev, 94 struct cardbus_devinfo *dinfo); 95 static int cardbus_write_ivar(device_t cbdev, device_t child, int which, 96 uintptr_t value); 97 98 /************************************************************************/ 99 /* Probe/Attach */ 100 /************************************************************************/ 101 102 static int 103 cardbus_probe(device_t cbdev) 104 { 105 device_set_desc(cbdev, "CardBus bus"); 106 return 0; 107 } 108 109 static int 110 cardbus_attach(device_t cbdev) 111 { 112 return 0; 113 } 114 115 static int 116 cardbus_detach(device_t cbdev) 117 { 118 cardbus_detach_card(cbdev); 119 return 0; 120 } 121 122 static int 123 cardbus_suspend(device_t self) 124 { 125 cardbus_detach_card(self); 126 return (0); 127 } 128 129 static int 130 cardbus_resume(device_t self) 131 { 132 return (0); 133 } 134 135 /************************************************************************/ 136 /* Attach/Detach card */ 137 /************************************************************************/ 138 139 static void 140 cardbus_device_setup_regs(pcicfgregs *cfg) 141 { 142 device_t dev = cfg->dev; 143 int i; 144 145 /* 146 * Some cards power up with garbage in their BARs. This 147 * code clears all that junk out. 148 */ 149 for (i = 0; i < PCIR_MAX_BAR_0; i++) 150 pci_write_config(dev, PCIR_BAR(i), 0, 4); 151 152 cfg->intline = 153 pci_get_irq(device_get_parent(device_get_parent(dev))); 154 pci_write_config(dev, PCIR_INTLINE, cfg->intline, 1); 155 pci_write_config(dev, PCIR_CACHELNSZ, 0x08, 1); 156 pci_write_config(dev, PCIR_LATTIMER, 0xa8, 1); 157 pci_write_config(dev, PCIR_MINGNT, 0x14, 1); 158 pci_write_config(dev, PCIR_MAXLAT, 0x14, 1); 159 } 160 161 static int 162 cardbus_attach_card(device_t cbdev) 163 { 164 device_t brdev = device_get_parent(cbdev); 165 device_t child; 166 int cardattached = 0; 167 int bus, slot, func, domain; 168 169 cardbus_detach_card(cbdev); /* detach existing cards */ 170 POWER_ENABLE_SOCKET(brdev, cbdev); 171 bus = pcib_get_bus(cbdev); 172 domain = pcib_get_domain(cbdev); 173 174 /* For each function, set it up and try to attach a driver to it */ 175 for (slot = 0; slot <= CARDBUS_SLOTMAX; slot++) { 176 int cardbusfunchigh = 0; 177 178 for (func = 0; func <= cardbusfunchigh; func++) { 179 struct cardbus_devinfo *dinfo; 180 181 dinfo = (struct cardbus_devinfo *) 182 pci_read_device(brdev, domain, bus, slot, func, 183 sizeof(struct cardbus_devinfo)); 184 if (dinfo == NULL) 185 continue; 186 if (dinfo->pci.cfg.mfdev) 187 cardbusfunchigh = CARDBUS_FUNCMAX; 188 189 child = device_add_child(cbdev, NULL, -1); 190 if (child == NULL) { 191 DEVPRINTF((cbdev, "Cannot add child!\n")); 192 pci_freecfg((struct pci_devinfo *)dinfo); 193 continue; 194 } 195 dinfo->pci.cfg.dev = child; 196 resource_list_init(&dinfo->pci.resources); 197 device_set_ivars(child, dinfo); 198 if (cardbus_do_cis(cbdev, child) != 0) { 199 DEVPRINTF((cbdev, 200 "Warning: Bogus CIS ignored\n")); 201 } 202 pci_cfg_save(dinfo->pci.cfg.dev, &dinfo->pci, 0); 203 pci_cfg_restore(dinfo->pci.cfg.dev, &dinfo->pci); 204 cardbus_device_setup_regs(&dinfo->pci.cfg); 205 pci_add_resources(brdev, cbdev, child, 1, 206 dinfo->mprefetchable); 207 pci_print_verbose(&dinfo->pci); 208 if (device_probe_and_attach(child) != 0) 209 pci_cfg_save(dinfo->pci.cfg.dev, &dinfo->pci, 1); 210 else 211 cardattached++; 212 } 213 } 214 215 if (cardattached > 0) 216 return (0); 217 POWER_DISABLE_SOCKET(brdev, cbdev); 218 return (ENOENT); 219 } 220 221 static int 222 cardbus_detach_card(device_t cbdev) 223 { 224 int numdevs; 225 device_t *devlist; 226 int tmp; 227 int err = 0; 228 229 if (device_get_children(cbdev, &devlist, &numdevs) != 0) 230 return (ENOENT); 231 232 if (numdevs == 0) { 233 kfree(devlist, M_TEMP); 234 return (ENOENT); 235 } 236 237 for (tmp = 0; tmp < numdevs; tmp++) { 238 struct cardbus_devinfo *dinfo = device_get_ivars(devlist[tmp]); 239 int status = device_get_state(devlist[tmp]); 240 241 if (dinfo->pci.cfg.dev != devlist[tmp]) 242 device_printf(cbdev, "devinfo dev mismatch\n"); 243 if (status == DS_ATTACHED || status == DS_BUSY) 244 device_detach(devlist[tmp]); 245 cardbus_release_all_resources(cbdev, dinfo); 246 device_delete_child(cbdev, devlist[tmp]); 247 pci_freecfg((struct pci_devinfo *)dinfo); 248 } 249 POWER_DISABLE_SOCKET(device_get_parent(cbdev), cbdev); 250 kfree(devlist, M_TEMP); 251 return (err); 252 } 253 254 static void 255 cardbus_driver_added(device_t cbdev, driver_t *driver) 256 { 257 int numdevs; 258 device_t *devlist; 259 device_t dev; 260 int i; 261 struct cardbus_devinfo *dinfo; 262 263 DEVICE_IDENTIFY(driver, cbdev); 264 if (device_get_children(cbdev, &devlist, &numdevs) != 0) 265 return; 266 267 /* 268 * If there are no drivers attached, but there are children, 269 * then power the card up. 270 */ 271 for (i = 0; i < numdevs; i++) { 272 dev = devlist[i]; 273 if (device_get_state(dev) != DS_NOTPRESENT) 274 break; 275 } 276 if (i > 0 && i == numdevs) 277 POWER_ENABLE_SOCKET(device_get_parent(cbdev), cbdev); 278 for (i = 0; i < numdevs; i++) { 279 dev = devlist[i]; 280 if (device_get_state(dev) != DS_NOTPRESENT) 281 continue; 282 dinfo = device_get_ivars(dev); 283 pci_print_verbose(&dinfo->pci); 284 if (bootverbose) 285 kprintf("pci%d:%d:%d:%d: reprobing on driver added\n", 286 dinfo->pci.cfg.domain, dinfo->pci.cfg.bus, 287 dinfo->pci.cfg.slot, dinfo->pci.cfg.func); 288 pci_cfg_restore(dinfo->pci.cfg.dev, &dinfo->pci); 289 if (device_probe_and_attach(dev) != 0) 290 pci_cfg_save(dev, &dinfo->pci, 1); 291 } 292 kfree(devlist, M_TEMP); 293 } 294 295 static void 296 cardbus_release_all_resources(device_t cbdev, struct cardbus_devinfo *dinfo) 297 { 298 struct resource_list_entry *rle; 299 300 /* Free all allocated resources */ 301 SLIST_FOREACH(rle, &dinfo->pci.resources, link) { 302 if (rle->res) { 303 BUS_RELEASE_RESOURCE(device_get_parent(cbdev), 304 cbdev, rle->type, rle->rid, rle->res); 305 rle->res = NULL; 306 /* 307 * zero out config so the card won't acknowledge 308 * access to the space anymore 309 */ 310 pci_write_config(dinfo->pci.cfg.dev, rle->rid, 0, 4); 311 } 312 } 313 resource_list_free(&dinfo->pci.resources); 314 } 315 316 /************************************************************************/ 317 /* Other Bus Methods */ 318 /************************************************************************/ 319 320 static int 321 cardbus_read_ivar(device_t cbdev, device_t child, int which, uintptr_t *result) 322 { 323 struct cardbus_devinfo *dinfo; 324 pcicfgregs *cfg; 325 326 dinfo = device_get_ivars(child); 327 cfg = &dinfo->pci.cfg; 328 329 switch (which) { 330 case PCI_IVAR_ETHADDR: 331 /* 332 * The generic accessor doesn't deal with failure, so 333 * we set the return value, then return an error. 334 */ 335 if (dinfo->fepresent & (1 << PCCARD_TPLFE_TYPE_LAN_NID)) { 336 *((uint8_t **) result) = dinfo->funce.lan.nid; 337 break; 338 } 339 *((uint8_t **) result) = NULL; 340 return (EINVAL); 341 default: 342 return (pci_read_ivar(cbdev, child, which, result)); 343 } 344 return 0; 345 } 346 347 static int 348 cardbus_write_ivar(device_t cbdev, device_t child, int which, uintptr_t value) 349 { 350 return(pci_write_ivar(cbdev, child, which, value)); 351 } 352 353 static device_method_t cardbus_methods[] = { 354 /* Device interface */ 355 DEVMETHOD(device_probe, cardbus_probe), 356 DEVMETHOD(device_attach, cardbus_attach), 357 DEVMETHOD(device_detach, cardbus_detach), 358 DEVMETHOD(device_suspend, cardbus_suspend), 359 DEVMETHOD(device_resume, cardbus_resume), 360 361 /* Bus interface */ 362 DEVMETHOD(bus_read_ivar, cardbus_read_ivar), 363 DEVMETHOD(bus_write_ivar, cardbus_write_ivar), 364 DEVMETHOD(bus_driver_added, cardbus_driver_added), 365 366 /* Card Interface */ 367 DEVMETHOD(card_attach_card, cardbus_attach_card), 368 DEVMETHOD(card_detach_card, cardbus_detach_card), 369 370 {0,0} 371 }; 372 373 DEFINE_CLASS_1(cardbus, cardbus_driver, cardbus_methods, 0, pci_driver); 374 375 static devclass_t cardbus_devclass; 376 377 DRIVER_MODULE(cardbus, cbb, cardbus_driver, cardbus_devclass, 0, 0); 378 MODULE_VERSION(cardbus, 1); 379