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