148static int cardbus_write_ivar(device_t cbdev, device_t child, int which, 149 uintptr_t value); 150 151/************************************************************************/ 152/* Probe/Attach */ 153/************************************************************************/ 154 155static int 156cardbus_probe(device_t cbdev) 157{ 158 device_set_desc(cbdev, "CardBus bus"); 159 return 0; 160} 161 162static int 163cardbus_attach(device_t cbdev) 164{ 165 return 0; 166} 167 168static int 169cardbus_detach(device_t cbdev) 170{ 171 cardbus_detach_card(cbdev); 172 return 0; 173} 174 175static int 176cardbus_suspend(device_t self) 177{ 178 cardbus_detach_card(self); 179 return (0); 180} 181 182static int 183cardbus_resume(device_t self) 184{ 185 return (0); 186} 187 188/************************************************************************/ 189/* Attach/Detach card */ 190/************************************************************************/ 191 192static void 193cardbus_device_setup_regs(device_t brdev, int b, int s, int f, pcicfgregs *cfg) 194{ 195 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_INTLINE, 196 pci_get_irq(device_get_parent(brdev)), 1); 197 cfg->intline = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_INTLINE, 1); 198 199 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_CACHELNSZ, 0x08, 1); 200 cfg->cachelnsz = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_CACHELNSZ, 1); 201 202 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_LATTIMER, 0xa8, 1); 203 cfg->lattimer = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_LATTIMER, 1); 204 205 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_MINGNT, 0x14, 1); 206 cfg->mingnt = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_MINGNT, 1); 207 208 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_MAXLAT, 0x14, 1); 209 cfg->maxlat = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_MAXLAT, 1); 210} 211 212static int 213cardbus_attach_card(device_t cbdev) 214{ 215 device_t brdev = device_get_parent(cbdev); 216 int cardattached = 0; 217 static int curr_bus_number = 2; /* XXX EVILE BAD (see below) */ 218 int bus, slot, func; 219 220 cardbus_detach_card(cbdev); /* detach existing cards */ 221 222 POWER_ENABLE_SOCKET(brdev, cbdev); 223 bus = pcib_get_bus(cbdev); 224 if (bus == 0) { 225 /* 226 * XXX EVILE BAD XXX 227 * Not all BIOSes initialize the secondary bus number properly, 228 * so if the default is bad, we just put one in and hope it 229 * works. 230 */ 231 bus = curr_bus_number; 232 pci_write_config(brdev, PCIR_SECBUS_2, curr_bus_number, 1); 233 pci_write_config(brdev, PCIR_SUBBUS_2, curr_bus_number + 2, 1); 234 curr_bus_number += 3; 235 } 236 /* For each function, set it up and try to attach a driver to it */ 237 for (slot = 0; slot <= CARDBUS_SLOTMAX; slot++) { 238 int cardbusfunchigh = 0; 239 for (func = 0; func <= cardbusfunchigh; func++) { 240 struct cardbus_devinfo *dinfo = 241 cardbus_read_device(brdev, bus, slot, func); 242 243 if (dinfo == NULL) 244 continue; 245 if (dinfo->pci.cfg.mfdev) 246 cardbusfunchigh = CARDBUS_FUNCMAX; 247 248 cardbus_device_setup_regs(brdev, bus, slot, func, 249 &dinfo->pci.cfg); 250 cardbus_print_verbose(dinfo); 251 dinfo->pci.cfg.dev = device_add_child(cbdev, NULL, -1); 252 if (!dinfo->pci.cfg.dev) { 253 DEVPRINTF((cbdev, "Cannot add child!\n")); 254 cardbus_freecfg(dinfo); 255 continue; 256 } 257 resource_list_init(&dinfo->pci.resources); 258 device_set_ivars(dinfo->pci.cfg.dev, dinfo); 259 cardbus_do_cis(cbdev, dinfo->pci.cfg.dev); 260 if (device_probe_and_attach(dinfo->pci.cfg.dev) != 0) 261 cardbus_release_all_resources(cbdev, dinfo); 262 else 263 cardattached++; 264 } 265 } 266 267 if (cardattached > 0) 268 return (0); 269 POWER_DISABLE_SOCKET(brdev, cbdev); 270 return (ENOENT); 271} 272 273static int 274cardbus_detach_card(device_t cbdev) 275{ 276 int numdevs; 277 device_t *devlist; 278 int tmp; 279 int err = 0; 280 281 device_get_children(cbdev, &devlist, &numdevs); 282 283 if (numdevs == 0) { 284 free(devlist, M_TEMP); 285 return (ENOENT); 286 } 287 288 for (tmp = 0; tmp < numdevs; tmp++) { 289 struct cardbus_devinfo *dinfo = device_get_ivars(devlist[tmp]); 290 int status = device_get_state(devlist[tmp]); 291 292 if (dinfo->pci.cfg.dev != devlist[tmp]) 293 device_printf(cbdev, "devinfo dev mismatch\n"); 294 if (status == DS_ATTACHED || status == DS_BUSY) 295 device_detach(devlist[tmp]); 296 cardbus_release_all_resources(cbdev, dinfo); 297 device_delete_child(cbdev, devlist[tmp]); 298 cardbus_freecfg(dinfo); 299 } 300 POWER_DISABLE_SOCKET(device_get_parent(cbdev), cbdev); 301 free(devlist, M_TEMP); 302 return (err); 303} 304 305static void 306cardbus_driver_added(device_t cbdev, driver_t *driver) 307{ 308 int numdevs; 309 device_t *devlist; 310 int tmp; 311 struct cardbus_devinfo *dinfo; 312 313 device_get_children(cbdev, &devlist, &numdevs); 314 315 DEVICE_IDENTIFY(driver, cbdev); 316 POWER_ENABLE_SOCKET(device_get_parent(cbdev), cbdev); 317 for (tmp = 0; tmp < numdevs; tmp++) { 318 if (device_get_state(devlist[tmp]) == DS_NOTPRESENT) { 319 dinfo = device_get_ivars(devlist[tmp]); 320#ifdef notyet 321 cardbus_device_setup_regs(brdev, bus, slot, func, 322 &dinfo->pci.cfg); 323#endif 324 cardbus_print_verbose(dinfo); 325 resource_list_init(&dinfo->pci.resources); 326 cardbus_do_cis(cbdev, dinfo->pci.cfg.dev); 327 if (device_probe_and_attach(dinfo->pci.cfg.dev) != 0) { 328 cardbus_release_all_resources(cbdev, dinfo); 329 } 330 } 331 } 332 333 free(devlist, M_TEMP); 334} 335 336/************************************************************************/ 337/* PCI-Like config reading (copied from pci.c */ 338/************************************************************************/ 339 340/* read configuration header into pcicfgrect structure */ 341 342static void 343cardbus_read_extcap(device_t cbdev, pcicfgregs *cfg) 344{ 345#define REG(n, w) PCIB_READ_CONFIG(cbdev, cfg->bus, cfg->slot, cfg->func, n, w) 346 int ptr, nextptr, ptrptr; 347 348 switch (cfg->hdrtype) { 349 case 0: 350 ptrptr = 0x34; 351 break; 352 case 2: 353 ptrptr = 0x14; 354 break; 355 default: 356 return; /* no extended capabilities support */ 357 } 358 nextptr = REG(ptrptr, 1); /* sanity check? */ 359 360 /* 361 * Read capability entries. 362 */ 363 while (nextptr != 0) { 364 /* Sanity check */ 365 if (nextptr > 255) { 366 printf("illegal PCI extended capability offset %d\n", 367 nextptr); 368 return; 369 } 370 /* Find the next entry */ 371 ptr = nextptr; 372 nextptr = REG(ptr + 1, 1); 373 374 /* Process this entry */ 375 switch (REG(ptr, 1)) { 376 case 0x01: /* PCI power management */ 377 if (cfg->pp_cap == 0) { 378 cfg->pp_cap = REG(ptr + PCIR_POWER_CAP, 2); 379 cfg->pp_status = ptr + PCIR_POWER_STATUS; 380 cfg->pp_pmcsr = ptr + PCIR_POWER_PMCSR; 381 if ((nextptr - ptr) > PCIR_POWER_DATA) 382 cfg->pp_data = ptr + PCIR_POWER_DATA; 383 } 384 break; 385 default: 386 break; 387 } 388 } 389#undef REG 390} 391 392/* extract header type specific config data */ 393 394static void 395cardbus_hdrtypedata(device_t brdev, int b, int s, int f, pcicfgregs *cfg) 396{ 397#define REG(n, w) PCIB_READ_CONFIG(brdev, b, s, f, n, w) 398 switch (cfg->hdrtype) { 399 case 0: 400 cfg->subvendor = REG(PCIR_SUBVEND_0, 2); 401 cfg->subdevice = REG(PCIR_SUBDEV_0, 2); 402 cfg->nummaps = PCI_MAXMAPS_0; 403 break; 404 case 1: 405 cfg->subvendor = REG(PCIR_SUBVEND_1, 2); 406 cfg->subdevice = REG(PCIR_SUBDEV_1, 2); 407 cfg->nummaps = PCI_MAXMAPS_1; 408 break; 409 case 2: 410 cfg->subvendor = REG(PCIR_SUBVEND_2, 2); 411 cfg->subdevice = REG(PCIR_SUBDEV_2, 2); 412 cfg->nummaps = PCI_MAXMAPS_2; 413 break; 414 } 415#undef REG 416} 417 418static struct cardbus_devinfo * 419cardbus_read_device(device_t brdev, int b, int s, int f) 420{ 421#define REG(n, w) PCIB_READ_CONFIG(brdev, b, s, f, n, w) 422 pcicfgregs *cfg = NULL; 423 struct cardbus_devinfo *devlist_entry = NULL; 424 425 if (REG(PCIR_DEVVENDOR, 4) != 0xffffffff) { 426 devlist_entry = malloc(sizeof(struct cardbus_devinfo), 427 M_DEVBUF, M_ZERO); 428 if (devlist_entry == NULL) 429 return (NULL); 430 431 cfg = &devlist_entry->pci.cfg; 432 433 cfg->bus = b; 434 cfg->slot = s; 435 cfg->func = f; 436 cfg->vendor = REG(PCIR_VENDOR, 2); 437 cfg->device = REG(PCIR_DEVICE, 2); 438 cfg->cmdreg = REG(PCIR_COMMAND, 2); 439 cfg->statreg = REG(PCIR_STATUS, 2); 440 cfg->baseclass = REG(PCIR_CLASS, 1); 441 cfg->subclass = REG(PCIR_SUBCLASS, 1); 442 cfg->progif = REG(PCIR_PROGIF, 1); 443 cfg->revid = REG(PCIR_REVID, 1); 444 cfg->hdrtype = REG(PCIR_HEADERTYPE, 1); 445 cfg->cachelnsz = REG(PCIR_CACHELNSZ, 1); 446 cfg->lattimer = REG(PCIR_LATTIMER, 1); 447 cfg->intpin = REG(PCIR_INTPIN, 1); 448 cfg->intline = REG(PCIR_INTLINE, 1); 449 450 cfg->mingnt = REG(PCIR_MINGNT, 1); 451 cfg->maxlat = REG(PCIR_MAXLAT, 1); 452 453 cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0; 454 cfg->hdrtype &= ~PCIM_MFDEV; 455 456 cardbus_hdrtypedata(brdev, b, s, f, cfg); 457 458 if (REG(PCIR_STATUS, 2) & PCIM_STATUS_CAPPRESENT) 459 cardbus_read_extcap(brdev, cfg); 460 461 devlist_entry->pci.conf.pc_sel.pc_bus = cfg->bus; 462 devlist_entry->pci.conf.pc_sel.pc_dev = cfg->slot; 463 devlist_entry->pci.conf.pc_sel.pc_func = cfg->func; 464 devlist_entry->pci.conf.pc_hdr = cfg->hdrtype; 465 466 devlist_entry->pci.conf.pc_subvendor = cfg->subvendor; 467 devlist_entry->pci.conf.pc_subdevice = cfg->subdevice; 468 devlist_entry->pci.conf.pc_vendor = cfg->vendor; 469 devlist_entry->pci.conf.pc_device = cfg->device; 470 471 devlist_entry->pci.conf.pc_class = cfg->baseclass; 472 devlist_entry->pci.conf.pc_subclass = cfg->subclass; 473 devlist_entry->pci.conf.pc_progif = cfg->progif; 474 devlist_entry->pci.conf.pc_revid = cfg->revid; 475 } 476 return (devlist_entry); 477#undef REG 478} 479 480/* free pcicfgregs structure and all depending data structures */ 481 482static int 483cardbus_freecfg(struct cardbus_devinfo *dinfo) 484{ 485 free(dinfo, M_DEVBUF); 486 487 return (0); 488} 489 490static void 491cardbus_print_verbose(struct cardbus_devinfo *dinfo) 492{ 493 if (bootverbose || cardbus_debug > 0) 494 { 495 pcicfgregs *cfg = &dinfo->pci.cfg; 496 497 printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", 498 cfg->vendor, cfg->device, cfg->revid); 499 printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n", 500 cfg->baseclass, cfg->subclass, cfg->progif, 501 cfg->hdrtype, cfg->mfdev); 502 printf("\tcmdreg=0x%04x, statreg=0x%04x, " 503 "cachelnsz=%d (dwords)\n", 504 cfg->cmdreg, cfg->statreg, cfg->cachelnsz); 505 printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), " 506 "maxlat=0x%02x (%d ns)\n", 507 cfg->lattimer, cfg->lattimer * 30, 508 cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, 509 cfg->maxlat * 250); 510 if (cfg->intpin > 0) 511 printf("\tintpin=%c, irq=%d\n", 512 cfg->intpin + 'a' - 1, cfg->intline); 513 } 514} 515 516/************************************************************************/ 517/* Resources */ 518/************************************************************************/ 519 520static int 521cardbus_set_resource(device_t cbdev, device_t child, int type, int rid, 522 u_long start, u_long count, struct resource *res) 523{ 524 struct cardbus_devinfo *dinfo; 525 struct resource_list *rl; 526 struct resource_list_entry *rle; 527 528 if (device_get_parent(child) != cbdev) 529 return ENOENT; 530 531 dinfo = device_get_ivars(child); 532 rl = &dinfo->pci.resources; 533 rle = resource_list_find(rl, type, rid); 534 if (rle == NULL) { 535 resource_list_add(rl, type, rid, start, start + count - 1, 536 count); 537 if (res != NULL) { 538 rle = resource_list_find(rl, type, rid); 539 rle->res = res; 540 } 541 } else { 542 if (rle->res == NULL) { 543 } else if (rle->res->r_dev == cbdev && 544 (!(rman_get_flags(rle->res) & RF_ACTIVE))) { 545 int f; 546 f = rman_get_flags(rle->res); 547 bus_release_resource(cbdev, type, rid, res); 548 rle->res = bus_alloc_resource(cbdev, type, &rid, 549 start, start + count - 1, 550 count, f); 551 } else { 552 device_printf(cbdev, "set_resource: resource busy\n"); 553 return EBUSY; 554 } 555 rle->start = start; 556 rle->end = start + count - 1; 557 rle->count = count; 558 if (res != NULL) 559 rle->res = res; 560 } 561 if (device_get_parent(child) == cbdev) 562 pci_write_config(child, rid, start, 4); 563 return 0; 564} 565 566static int 567cardbus_get_resource(device_t cbdev, device_t child, int type, int rid, 568 u_long *startp, u_long *countp) 569{ 570 struct cardbus_devinfo *dinfo; 571 struct resource_list *rl; 572 struct resource_list_entry *rle; 573 574 if (device_get_parent(child) != cbdev) 575 return ENOENT; 576 577 dinfo = device_get_ivars(child); 578 rl = &dinfo->pci.resources; 579 rle = resource_list_find(rl, type, rid); 580 if (!rle) 581 return ENOENT; 582 if (startp) 583 *startp = rle->start; 584 if (countp) 585 *countp = rle->count; 586 return 0; 587} 588 589static void 590cardbus_delete_resource(device_t cbdev, device_t child, int type, int rid) 591{ 592 struct cardbus_devinfo *dinfo; 593 struct resource_list *rl; 594 struct resource_list_entry *rle; 595 596 if (device_get_parent(child) != cbdev) 597 return; 598 599 dinfo = device_get_ivars(child); 600 rl = &dinfo->pci.resources; 601 rle = resource_list_find(rl, type, rid); 602 if (rle) { 603 if (rle->res) { 604 if (rle->res->r_dev != cbdev || 605 rman_get_flags(rle->res) & RF_ACTIVE) { 606 device_printf(cbdev, "delete_resource: " 607 "Resource still owned by child, oops. " 608 "(type=%d, rid=%d, addr=%lx)\n", 609 rle->type, rle->rid, 610 rman_get_start(rle->res)); 611 return; 612 } 613 bus_release_resource(cbdev, type, rid, rle->res); 614 } 615 resource_list_delete(rl, type, rid); 616 } 617 if (device_get_parent(child) == cbdev) 618 pci_write_config(child, rid, 0, 4); 619} 620 621static int 622cardbus_set_resource_method(device_t cbdev, device_t child, int type, int rid, 623 u_long start, u_long count) 624{ 625 int ret; 626 ret = cardbus_set_resource(cbdev, child, type, rid, start, count, NULL); 627 if (ret != 0) 628 return ret; 629 return BUS_SET_RESOURCE(device_get_parent(cbdev), child, type, rid, 630 start, count); 631} 632 633static int 634cardbus_get_resource_method(device_t cbdev, device_t child, int type, int rid, 635 u_long *startp, u_long *countp) 636{ 637 int ret; 638 ret = cardbus_get_resource(cbdev, child, type, rid, startp, countp); 639 if (ret != 0) 640 return ret; 641 return BUS_GET_RESOURCE(device_get_parent(cbdev), child, type, rid, 642 startp, countp); 643} 644 645static void 646cardbus_delete_resource_method(device_t cbdev, device_t child, 647 int type, int rid) 648{ 649 cardbus_delete_resource(cbdev, child, type, rid); 650 BUS_DELETE_RESOURCE(device_get_parent(cbdev), child, type, rid); 651} 652 653static void 654cardbus_release_all_resources(device_t cbdev, struct cardbus_devinfo *dinfo) 655{ 656 struct resource_list_entry *rle; 657 658 /* Free all allocated resources */ 659 SLIST_FOREACH(rle, &dinfo->pci.resources, link) { 660 if (rle->res) { 661 if (rle->res->r_dev != cbdev) 662 device_printf(cbdev, "release_all_resource: " 663 "Resource still owned by child, oops. " 664 "(type=%d, rid=%d, addr=%lx)\n", 665 rle->type, rle->rid, 666 rman_get_start(rle->res)); 667 BUS_RELEASE_RESOURCE(device_get_parent(cbdev), 668 rle->res->r_dev, 669 rle->type, rle->rid, 670 rle->res); 671 rle->res = NULL; 672 /* 673 * zero out config so the card won't acknowledge 674 * access to the space anymore 675 */ 676 pci_write_config(dinfo->pci.cfg.dev, rle->rid, 0, 4); 677 } 678 } 679 resource_list_free(&dinfo->pci.resources); 680} 681 682static struct resource * 683cardbus_alloc_resource(device_t cbdev, device_t child, int type, 684 int *rid, u_long start, u_long end, u_long count, u_int flags) 685{ 686 struct cardbus_devinfo *dinfo; 687 struct resource_list_entry *rle = 0; 688 int passthrough = (device_get_parent(child) != cbdev); 689 690 if (passthrough) { 691 return (BUS_ALLOC_RESOURCE(device_get_parent(cbdev), child, 692 type, rid, start, end, count, flags)); 693 } 694 695 dinfo = device_get_ivars(child); 696 rle = resource_list_find(&dinfo->pci.resources, type, *rid); 697 698 if (!rle) 699 return NULL; /* no resource of that type/rid */ 700 701 if (!rle->res) { 702 device_printf(cbdev, "WARNING: Resource not reserved by bus\n"); 703 return NULL; 704 } else { 705 /* Release the cardbus hold on the resource */ 706 if (rle->res->r_dev != cbdev) 707 return NULL; 708 bus_release_resource(cbdev, type, *rid, rle->res); 709 rle->res = NULL; 710 switch (type) { 711 case SYS_RES_IOPORT: 712 case SYS_RES_MEMORY: 713 if (!(flags & RF_ALIGNMENT_MASK)) 714 flags |= rman_make_alignment_flags(rle->count); 715 break; 716 case SYS_RES_IRQ: 717 flags |= RF_SHAREABLE; 718 break; 719 } 720 /* Allocate the resource to the child */ 721 return resource_list_alloc(&dinfo->pci.resources, cbdev, child, 722 type, rid, rle->start, rle->end, rle->count, flags); 723 } 724} 725 726static int 727cardbus_release_resource(device_t cbdev, device_t child, int type, int rid, 728 struct resource *r) 729{ 730 struct cardbus_devinfo *dinfo; 731 int passthrough = (device_get_parent(child) != cbdev); 732 struct resource_list_entry *rle = 0; 733 int flags; 734 int ret; 735 736 if (passthrough) { 737 return BUS_RELEASE_RESOURCE(device_get_parent(cbdev), child, 738 type, rid, r); 739 } 740 741 dinfo = device_get_ivars(child); 742 /* 743 * According to the PCI 2.2 spec, devices may share an address 744 * decoder between memory mapped ROM access and memory 745 * mapped register access. To be safe, disable ROM access 746 * whenever it is released. 747 */ 748 if (rid == CARDBUS_ROM_REG) { 749 uint32_t rom_reg; 750 751 rom_reg = pci_read_config(child, rid, 4); 752 rom_reg &= ~CARDBUS_ROM_ENABLE; 753 pci_write_config(child, rid, rom_reg, 4); 754 } 755 756 rle = resource_list_find(&dinfo->pci.resources, type, rid); 757 758 if (!rle) { 759 device_printf(cbdev, "Allocated resource not found\n"); 760 return ENOENT; 761 } 762 if (!rle->res) { 763 device_printf(cbdev, "Allocated resource not recorded\n"); 764 return ENOENT; 765 } 766 767 ret = BUS_RELEASE_RESOURCE(device_get_parent(cbdev), child, 768 type, rid, r); 769 switch (type) { 770 case SYS_RES_IOPORT: 771 case SYS_RES_MEMORY: 772 flags = rman_make_alignment_flags(rle->count); 773 break; 774 case SYS_RES_IRQ: 775 flags = RF_SHAREABLE; 776 break; 777 default: 778 flags = 0; 779 } 780 /* Restore cardbus hold on the resource */ 781 rle->res = bus_alloc_resource(cbdev, type, &rid, 782 rle->start, rle->end, rle->count, flags); 783 if (rle->res == NULL) 784 device_printf(cbdev, "release_resource: " 785 "unable to reacquire resource\n"); 786 return ret; 787} 788 789static int 790cardbus_setup_intr(device_t cbdev, device_t child, struct resource *irq, 791 int flags, driver_intr_t *intr, void *arg, void **cookiep) 792{ 793 int ret; 794 device_t cdev; 795 struct cardbus_devinfo *dinfo; 796 797 ret = bus_generic_setup_intr(cbdev, child, irq, flags, intr, arg, 798 cookiep); 799 if (ret != 0) 800 return ret; 801 802 for (cdev = child; cbdev != device_get_parent(cdev); 803 cdev = device_get_parent(cdev)) 804 /* NOTHING */; 805 dinfo = device_get_ivars(cdev); 806 807 return 0; 808} 809 810static int 811cardbus_teardown_intr(device_t cbdev, device_t child, struct resource *irq, 812 void *cookie) 813{ 814 int ret; 815 device_t cdev; 816 struct cardbus_devinfo *dinfo; 817 818 ret = bus_generic_teardown_intr(cbdev, child, irq, cookie); 819 if (ret != 0) 820 return ret; 821 822 for (cdev = child; cbdev != device_get_parent(cdev); 823 cdev = device_get_parent(cdev)) 824 /* NOTHING */; 825 dinfo = device_get_ivars(cdev); 826 827 return (0); 828} 829 830 831/************************************************************************/ 832/* Other Bus Methods */ 833/************************************************************************/ 834 835static int 836cardbus_print_resources(struct resource_list *rl, const char *name, 837 int type, const char *format) 838{ 839 struct resource_list_entry *rle; 840 int printed, retval; 841 842 printed = 0; 843 retval = 0; 844 /* Yes, this is kinda cheating */ 845 SLIST_FOREACH(rle, rl, link) { 846 if (rle->type == type) { 847 if (printed == 0) 848 retval += printf(" %s ", name); 849 else if (printed > 0) 850 retval += printf(","); 851 printed++; 852 retval += printf(format, rle->start); 853 if (rle->count > 1) { 854 retval += printf("-"); 855 retval += printf(format, rle->start + 856 rle->count - 1); 857 } 858 } 859 } 860 return retval; 861} 862 863static int 864cardbus_print_child(device_t cbdev, device_t child) 865{ 866 struct cardbus_devinfo *dinfo; 867 struct resource_list *rl; 868 pcicfgregs *cfg; 869 int retval = 0; 870 871 dinfo = device_get_ivars(child); 872 cfg = &dinfo->pci.cfg; 873 rl = &dinfo->pci.resources; 874 875 retval += bus_print_child_header(cbdev, child); 876 877 retval += cardbus_print_resources(rl, "port", SYS_RES_IOPORT, "%#lx"); 878 retval += cardbus_print_resources(rl, "mem", SYS_RES_MEMORY, "%#lx"); 879 retval += cardbus_print_resources(rl, "irq", SYS_RES_IRQ, "%ld"); 880 if (device_get_flags(cbdev)) 881 retval += printf(" flags %#x", device_get_flags(cbdev)); 882 883 retval += printf(" at device %d.%d", pci_get_slot(child), 884 pci_get_function(child)); 885 886 retval += bus_print_child_footer(cbdev, child); 887 888 return (retval); 889} 890 891static void 892cardbus_probe_nomatch(device_t cbdev, device_t child) 893{ 894 struct cardbus_devinfo *dinfo; 895 pcicfgregs *cfg; 896 897 dinfo = device_get_ivars(child); 898 cfg = &dinfo->pci.cfg; 899 device_printf(cbdev, "<unknown card>"); 900 printf(" (vendor=0x%04x, dev=0x%04x)", cfg->vendor, cfg->device); 901 printf(" at %d.%d", pci_get_slot(child), pci_get_function(child)); 902 if (cfg->intpin > 0 && cfg->intline != 255) { 903 printf(" irq %d", cfg->intline); 904 } 905 printf("\n"); 906 907 return; 908} 909 910static int 911cardbus_child_location_str(device_t cbdev, device_t child, char *buf, 912 size_t buflen) 913{ 914 struct cardbus_devinfo *dinfo; 915 pcicfgregs *cfg; 916 917 dinfo = device_get_ivars(child); 918 cfg = &dinfo->pci.cfg; 919 snprintf(buf, buflen, "slot=%d function=%d", pci_get_slot(child), 920 pci_get_function(child)); 921 return (0); 922} 923 924static int 925cardbus_child_pnpinfo_str(device_t cbdev, device_t child, char *buf, 926 size_t buflen) 927{ 928 struct cardbus_devinfo *dinfo; 929 pcicfgregs *cfg; 930 931 dinfo = device_get_ivars(child); 932 cfg = &dinfo->pci.cfg; 933 snprintf(buf, buflen, "vendor=0x%04x device=0x%04x subvendor=0x%04x " 934 "subdevice=0x%04x", cfg->vendor, cfg->device, cfg->subvendor, 935 cfg->subdevice); 936 return (0); 937} 938 939static int 940cardbus_read_ivar(device_t cbdev, device_t child, int which, u_long *result) 941{ 942 struct cardbus_devinfo *dinfo; 943 pcicfgregs *cfg; 944 945 dinfo = device_get_ivars(child); 946 cfg = &dinfo->pci.cfg; 947 948 switch (which) { 949 case PCI_IVAR_ETHADDR: 950 /* 951 * The generic accessor doesn't deal with failure, so 952 * we set the return value, then return an error. 953 */ 954 if ((dinfo->fepresent & (1 << TPL_FUNCE_LAN_NID)) == 0) {
| 148static int cardbus_write_ivar(device_t cbdev, device_t child, int which, 149 uintptr_t value); 150 151/************************************************************************/ 152/* Probe/Attach */ 153/************************************************************************/ 154 155static int 156cardbus_probe(device_t cbdev) 157{ 158 device_set_desc(cbdev, "CardBus bus"); 159 return 0; 160} 161 162static int 163cardbus_attach(device_t cbdev) 164{ 165 return 0; 166} 167 168static int 169cardbus_detach(device_t cbdev) 170{ 171 cardbus_detach_card(cbdev); 172 return 0; 173} 174 175static int 176cardbus_suspend(device_t self) 177{ 178 cardbus_detach_card(self); 179 return (0); 180} 181 182static int 183cardbus_resume(device_t self) 184{ 185 return (0); 186} 187 188/************************************************************************/ 189/* Attach/Detach card */ 190/************************************************************************/ 191 192static void 193cardbus_device_setup_regs(device_t brdev, int b, int s, int f, pcicfgregs *cfg) 194{ 195 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_INTLINE, 196 pci_get_irq(device_get_parent(brdev)), 1); 197 cfg->intline = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_INTLINE, 1); 198 199 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_CACHELNSZ, 0x08, 1); 200 cfg->cachelnsz = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_CACHELNSZ, 1); 201 202 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_LATTIMER, 0xa8, 1); 203 cfg->lattimer = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_LATTIMER, 1); 204 205 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_MINGNT, 0x14, 1); 206 cfg->mingnt = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_MINGNT, 1); 207 208 PCIB_WRITE_CONFIG(brdev, b, s, f, PCIR_MAXLAT, 0x14, 1); 209 cfg->maxlat = PCIB_READ_CONFIG(brdev, b, s, f, PCIR_MAXLAT, 1); 210} 211 212static int 213cardbus_attach_card(device_t cbdev) 214{ 215 device_t brdev = device_get_parent(cbdev); 216 int cardattached = 0; 217 static int curr_bus_number = 2; /* XXX EVILE BAD (see below) */ 218 int bus, slot, func; 219 220 cardbus_detach_card(cbdev); /* detach existing cards */ 221 222 POWER_ENABLE_SOCKET(brdev, cbdev); 223 bus = pcib_get_bus(cbdev); 224 if (bus == 0) { 225 /* 226 * XXX EVILE BAD XXX 227 * Not all BIOSes initialize the secondary bus number properly, 228 * so if the default is bad, we just put one in and hope it 229 * works. 230 */ 231 bus = curr_bus_number; 232 pci_write_config(brdev, PCIR_SECBUS_2, curr_bus_number, 1); 233 pci_write_config(brdev, PCIR_SUBBUS_2, curr_bus_number + 2, 1); 234 curr_bus_number += 3; 235 } 236 /* For each function, set it up and try to attach a driver to it */ 237 for (slot = 0; slot <= CARDBUS_SLOTMAX; slot++) { 238 int cardbusfunchigh = 0; 239 for (func = 0; func <= cardbusfunchigh; func++) { 240 struct cardbus_devinfo *dinfo = 241 cardbus_read_device(brdev, bus, slot, func); 242 243 if (dinfo == NULL) 244 continue; 245 if (dinfo->pci.cfg.mfdev) 246 cardbusfunchigh = CARDBUS_FUNCMAX; 247 248 cardbus_device_setup_regs(brdev, bus, slot, func, 249 &dinfo->pci.cfg); 250 cardbus_print_verbose(dinfo); 251 dinfo->pci.cfg.dev = device_add_child(cbdev, NULL, -1); 252 if (!dinfo->pci.cfg.dev) { 253 DEVPRINTF((cbdev, "Cannot add child!\n")); 254 cardbus_freecfg(dinfo); 255 continue; 256 } 257 resource_list_init(&dinfo->pci.resources); 258 device_set_ivars(dinfo->pci.cfg.dev, dinfo); 259 cardbus_do_cis(cbdev, dinfo->pci.cfg.dev); 260 if (device_probe_and_attach(dinfo->pci.cfg.dev) != 0) 261 cardbus_release_all_resources(cbdev, dinfo); 262 else 263 cardattached++; 264 } 265 } 266 267 if (cardattached > 0) 268 return (0); 269 POWER_DISABLE_SOCKET(brdev, cbdev); 270 return (ENOENT); 271} 272 273static int 274cardbus_detach_card(device_t cbdev) 275{ 276 int numdevs; 277 device_t *devlist; 278 int tmp; 279 int err = 0; 280 281 device_get_children(cbdev, &devlist, &numdevs); 282 283 if (numdevs == 0) { 284 free(devlist, M_TEMP); 285 return (ENOENT); 286 } 287 288 for (tmp = 0; tmp < numdevs; tmp++) { 289 struct cardbus_devinfo *dinfo = device_get_ivars(devlist[tmp]); 290 int status = device_get_state(devlist[tmp]); 291 292 if (dinfo->pci.cfg.dev != devlist[tmp]) 293 device_printf(cbdev, "devinfo dev mismatch\n"); 294 if (status == DS_ATTACHED || status == DS_BUSY) 295 device_detach(devlist[tmp]); 296 cardbus_release_all_resources(cbdev, dinfo); 297 device_delete_child(cbdev, devlist[tmp]); 298 cardbus_freecfg(dinfo); 299 } 300 POWER_DISABLE_SOCKET(device_get_parent(cbdev), cbdev); 301 free(devlist, M_TEMP); 302 return (err); 303} 304 305static void 306cardbus_driver_added(device_t cbdev, driver_t *driver) 307{ 308 int numdevs; 309 device_t *devlist; 310 int tmp; 311 struct cardbus_devinfo *dinfo; 312 313 device_get_children(cbdev, &devlist, &numdevs); 314 315 DEVICE_IDENTIFY(driver, cbdev); 316 POWER_ENABLE_SOCKET(device_get_parent(cbdev), cbdev); 317 for (tmp = 0; tmp < numdevs; tmp++) { 318 if (device_get_state(devlist[tmp]) == DS_NOTPRESENT) { 319 dinfo = device_get_ivars(devlist[tmp]); 320#ifdef notyet 321 cardbus_device_setup_regs(brdev, bus, slot, func, 322 &dinfo->pci.cfg); 323#endif 324 cardbus_print_verbose(dinfo); 325 resource_list_init(&dinfo->pci.resources); 326 cardbus_do_cis(cbdev, dinfo->pci.cfg.dev); 327 if (device_probe_and_attach(dinfo->pci.cfg.dev) != 0) { 328 cardbus_release_all_resources(cbdev, dinfo); 329 } 330 } 331 } 332 333 free(devlist, M_TEMP); 334} 335 336/************************************************************************/ 337/* PCI-Like config reading (copied from pci.c */ 338/************************************************************************/ 339 340/* read configuration header into pcicfgrect structure */ 341 342static void 343cardbus_read_extcap(device_t cbdev, pcicfgregs *cfg) 344{ 345#define REG(n, w) PCIB_READ_CONFIG(cbdev, cfg->bus, cfg->slot, cfg->func, n, w) 346 int ptr, nextptr, ptrptr; 347 348 switch (cfg->hdrtype) { 349 case 0: 350 ptrptr = 0x34; 351 break; 352 case 2: 353 ptrptr = 0x14; 354 break; 355 default: 356 return; /* no extended capabilities support */ 357 } 358 nextptr = REG(ptrptr, 1); /* sanity check? */ 359 360 /* 361 * Read capability entries. 362 */ 363 while (nextptr != 0) { 364 /* Sanity check */ 365 if (nextptr > 255) { 366 printf("illegal PCI extended capability offset %d\n", 367 nextptr); 368 return; 369 } 370 /* Find the next entry */ 371 ptr = nextptr; 372 nextptr = REG(ptr + 1, 1); 373 374 /* Process this entry */ 375 switch (REG(ptr, 1)) { 376 case 0x01: /* PCI power management */ 377 if (cfg->pp_cap == 0) { 378 cfg->pp_cap = REG(ptr + PCIR_POWER_CAP, 2); 379 cfg->pp_status = ptr + PCIR_POWER_STATUS; 380 cfg->pp_pmcsr = ptr + PCIR_POWER_PMCSR; 381 if ((nextptr - ptr) > PCIR_POWER_DATA) 382 cfg->pp_data = ptr + PCIR_POWER_DATA; 383 } 384 break; 385 default: 386 break; 387 } 388 } 389#undef REG 390} 391 392/* extract header type specific config data */ 393 394static void 395cardbus_hdrtypedata(device_t brdev, int b, int s, int f, pcicfgregs *cfg) 396{ 397#define REG(n, w) PCIB_READ_CONFIG(brdev, b, s, f, n, w) 398 switch (cfg->hdrtype) { 399 case 0: 400 cfg->subvendor = REG(PCIR_SUBVEND_0, 2); 401 cfg->subdevice = REG(PCIR_SUBDEV_0, 2); 402 cfg->nummaps = PCI_MAXMAPS_0; 403 break; 404 case 1: 405 cfg->subvendor = REG(PCIR_SUBVEND_1, 2); 406 cfg->subdevice = REG(PCIR_SUBDEV_1, 2); 407 cfg->nummaps = PCI_MAXMAPS_1; 408 break; 409 case 2: 410 cfg->subvendor = REG(PCIR_SUBVEND_2, 2); 411 cfg->subdevice = REG(PCIR_SUBDEV_2, 2); 412 cfg->nummaps = PCI_MAXMAPS_2; 413 break; 414 } 415#undef REG 416} 417 418static struct cardbus_devinfo * 419cardbus_read_device(device_t brdev, int b, int s, int f) 420{ 421#define REG(n, w) PCIB_READ_CONFIG(brdev, b, s, f, n, w) 422 pcicfgregs *cfg = NULL; 423 struct cardbus_devinfo *devlist_entry = NULL; 424 425 if (REG(PCIR_DEVVENDOR, 4) != 0xffffffff) { 426 devlist_entry = malloc(sizeof(struct cardbus_devinfo), 427 M_DEVBUF, M_ZERO); 428 if (devlist_entry == NULL) 429 return (NULL); 430 431 cfg = &devlist_entry->pci.cfg; 432 433 cfg->bus = b; 434 cfg->slot = s; 435 cfg->func = f; 436 cfg->vendor = REG(PCIR_VENDOR, 2); 437 cfg->device = REG(PCIR_DEVICE, 2); 438 cfg->cmdreg = REG(PCIR_COMMAND, 2); 439 cfg->statreg = REG(PCIR_STATUS, 2); 440 cfg->baseclass = REG(PCIR_CLASS, 1); 441 cfg->subclass = REG(PCIR_SUBCLASS, 1); 442 cfg->progif = REG(PCIR_PROGIF, 1); 443 cfg->revid = REG(PCIR_REVID, 1); 444 cfg->hdrtype = REG(PCIR_HEADERTYPE, 1); 445 cfg->cachelnsz = REG(PCIR_CACHELNSZ, 1); 446 cfg->lattimer = REG(PCIR_LATTIMER, 1); 447 cfg->intpin = REG(PCIR_INTPIN, 1); 448 cfg->intline = REG(PCIR_INTLINE, 1); 449 450 cfg->mingnt = REG(PCIR_MINGNT, 1); 451 cfg->maxlat = REG(PCIR_MAXLAT, 1); 452 453 cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0; 454 cfg->hdrtype &= ~PCIM_MFDEV; 455 456 cardbus_hdrtypedata(brdev, b, s, f, cfg); 457 458 if (REG(PCIR_STATUS, 2) & PCIM_STATUS_CAPPRESENT) 459 cardbus_read_extcap(brdev, cfg); 460 461 devlist_entry->pci.conf.pc_sel.pc_bus = cfg->bus; 462 devlist_entry->pci.conf.pc_sel.pc_dev = cfg->slot; 463 devlist_entry->pci.conf.pc_sel.pc_func = cfg->func; 464 devlist_entry->pci.conf.pc_hdr = cfg->hdrtype; 465 466 devlist_entry->pci.conf.pc_subvendor = cfg->subvendor; 467 devlist_entry->pci.conf.pc_subdevice = cfg->subdevice; 468 devlist_entry->pci.conf.pc_vendor = cfg->vendor; 469 devlist_entry->pci.conf.pc_device = cfg->device; 470 471 devlist_entry->pci.conf.pc_class = cfg->baseclass; 472 devlist_entry->pci.conf.pc_subclass = cfg->subclass; 473 devlist_entry->pci.conf.pc_progif = cfg->progif; 474 devlist_entry->pci.conf.pc_revid = cfg->revid; 475 } 476 return (devlist_entry); 477#undef REG 478} 479 480/* free pcicfgregs structure and all depending data structures */ 481 482static int 483cardbus_freecfg(struct cardbus_devinfo *dinfo) 484{ 485 free(dinfo, M_DEVBUF); 486 487 return (0); 488} 489 490static void 491cardbus_print_verbose(struct cardbus_devinfo *dinfo) 492{ 493 if (bootverbose || cardbus_debug > 0) 494 { 495 pcicfgregs *cfg = &dinfo->pci.cfg; 496 497 printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", 498 cfg->vendor, cfg->device, cfg->revid); 499 printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n", 500 cfg->baseclass, cfg->subclass, cfg->progif, 501 cfg->hdrtype, cfg->mfdev); 502 printf("\tcmdreg=0x%04x, statreg=0x%04x, " 503 "cachelnsz=%d (dwords)\n", 504 cfg->cmdreg, cfg->statreg, cfg->cachelnsz); 505 printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), " 506 "maxlat=0x%02x (%d ns)\n", 507 cfg->lattimer, cfg->lattimer * 30, 508 cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, 509 cfg->maxlat * 250); 510 if (cfg->intpin > 0) 511 printf("\tintpin=%c, irq=%d\n", 512 cfg->intpin + 'a' - 1, cfg->intline); 513 } 514} 515 516/************************************************************************/ 517/* Resources */ 518/************************************************************************/ 519 520static int 521cardbus_set_resource(device_t cbdev, device_t child, int type, int rid, 522 u_long start, u_long count, struct resource *res) 523{ 524 struct cardbus_devinfo *dinfo; 525 struct resource_list *rl; 526 struct resource_list_entry *rle; 527 528 if (device_get_parent(child) != cbdev) 529 return ENOENT; 530 531 dinfo = device_get_ivars(child); 532 rl = &dinfo->pci.resources; 533 rle = resource_list_find(rl, type, rid); 534 if (rle == NULL) { 535 resource_list_add(rl, type, rid, start, start + count - 1, 536 count); 537 if (res != NULL) { 538 rle = resource_list_find(rl, type, rid); 539 rle->res = res; 540 } 541 } else { 542 if (rle->res == NULL) { 543 } else if (rle->res->r_dev == cbdev && 544 (!(rman_get_flags(rle->res) & RF_ACTIVE))) { 545 int f; 546 f = rman_get_flags(rle->res); 547 bus_release_resource(cbdev, type, rid, res); 548 rle->res = bus_alloc_resource(cbdev, type, &rid, 549 start, start + count - 1, 550 count, f); 551 } else { 552 device_printf(cbdev, "set_resource: resource busy\n"); 553 return EBUSY; 554 } 555 rle->start = start; 556 rle->end = start + count - 1; 557 rle->count = count; 558 if (res != NULL) 559 rle->res = res; 560 } 561 if (device_get_parent(child) == cbdev) 562 pci_write_config(child, rid, start, 4); 563 return 0; 564} 565 566static int 567cardbus_get_resource(device_t cbdev, device_t child, int type, int rid, 568 u_long *startp, u_long *countp) 569{ 570 struct cardbus_devinfo *dinfo; 571 struct resource_list *rl; 572 struct resource_list_entry *rle; 573 574 if (device_get_parent(child) != cbdev) 575 return ENOENT; 576 577 dinfo = device_get_ivars(child); 578 rl = &dinfo->pci.resources; 579 rle = resource_list_find(rl, type, rid); 580 if (!rle) 581 return ENOENT; 582 if (startp) 583 *startp = rle->start; 584 if (countp) 585 *countp = rle->count; 586 return 0; 587} 588 589static void 590cardbus_delete_resource(device_t cbdev, device_t child, int type, int rid) 591{ 592 struct cardbus_devinfo *dinfo; 593 struct resource_list *rl; 594 struct resource_list_entry *rle; 595 596 if (device_get_parent(child) != cbdev) 597 return; 598 599 dinfo = device_get_ivars(child); 600 rl = &dinfo->pci.resources; 601 rle = resource_list_find(rl, type, rid); 602 if (rle) { 603 if (rle->res) { 604 if (rle->res->r_dev != cbdev || 605 rman_get_flags(rle->res) & RF_ACTIVE) { 606 device_printf(cbdev, "delete_resource: " 607 "Resource still owned by child, oops. " 608 "(type=%d, rid=%d, addr=%lx)\n", 609 rle->type, rle->rid, 610 rman_get_start(rle->res)); 611 return; 612 } 613 bus_release_resource(cbdev, type, rid, rle->res); 614 } 615 resource_list_delete(rl, type, rid); 616 } 617 if (device_get_parent(child) == cbdev) 618 pci_write_config(child, rid, 0, 4); 619} 620 621static int 622cardbus_set_resource_method(device_t cbdev, device_t child, int type, int rid, 623 u_long start, u_long count) 624{ 625 int ret; 626 ret = cardbus_set_resource(cbdev, child, type, rid, start, count, NULL); 627 if (ret != 0) 628 return ret; 629 return BUS_SET_RESOURCE(device_get_parent(cbdev), child, type, rid, 630 start, count); 631} 632 633static int 634cardbus_get_resource_method(device_t cbdev, device_t child, int type, int rid, 635 u_long *startp, u_long *countp) 636{ 637 int ret; 638 ret = cardbus_get_resource(cbdev, child, type, rid, startp, countp); 639 if (ret != 0) 640 return ret; 641 return BUS_GET_RESOURCE(device_get_parent(cbdev), child, type, rid, 642 startp, countp); 643} 644 645static void 646cardbus_delete_resource_method(device_t cbdev, device_t child, 647 int type, int rid) 648{ 649 cardbus_delete_resource(cbdev, child, type, rid); 650 BUS_DELETE_RESOURCE(device_get_parent(cbdev), child, type, rid); 651} 652 653static void 654cardbus_release_all_resources(device_t cbdev, struct cardbus_devinfo *dinfo) 655{ 656 struct resource_list_entry *rle; 657 658 /* Free all allocated resources */ 659 SLIST_FOREACH(rle, &dinfo->pci.resources, link) { 660 if (rle->res) { 661 if (rle->res->r_dev != cbdev) 662 device_printf(cbdev, "release_all_resource: " 663 "Resource still owned by child, oops. " 664 "(type=%d, rid=%d, addr=%lx)\n", 665 rle->type, rle->rid, 666 rman_get_start(rle->res)); 667 BUS_RELEASE_RESOURCE(device_get_parent(cbdev), 668 rle->res->r_dev, 669 rle->type, rle->rid, 670 rle->res); 671 rle->res = NULL; 672 /* 673 * zero out config so the card won't acknowledge 674 * access to the space anymore 675 */ 676 pci_write_config(dinfo->pci.cfg.dev, rle->rid, 0, 4); 677 } 678 } 679 resource_list_free(&dinfo->pci.resources); 680} 681 682static struct resource * 683cardbus_alloc_resource(device_t cbdev, device_t child, int type, 684 int *rid, u_long start, u_long end, u_long count, u_int flags) 685{ 686 struct cardbus_devinfo *dinfo; 687 struct resource_list_entry *rle = 0; 688 int passthrough = (device_get_parent(child) != cbdev); 689 690 if (passthrough) { 691 return (BUS_ALLOC_RESOURCE(device_get_parent(cbdev), child, 692 type, rid, start, end, count, flags)); 693 } 694 695 dinfo = device_get_ivars(child); 696 rle = resource_list_find(&dinfo->pci.resources, type, *rid); 697 698 if (!rle) 699 return NULL; /* no resource of that type/rid */ 700 701 if (!rle->res) { 702 device_printf(cbdev, "WARNING: Resource not reserved by bus\n"); 703 return NULL; 704 } else { 705 /* Release the cardbus hold on the resource */ 706 if (rle->res->r_dev != cbdev) 707 return NULL; 708 bus_release_resource(cbdev, type, *rid, rle->res); 709 rle->res = NULL; 710 switch (type) { 711 case SYS_RES_IOPORT: 712 case SYS_RES_MEMORY: 713 if (!(flags & RF_ALIGNMENT_MASK)) 714 flags |= rman_make_alignment_flags(rle->count); 715 break; 716 case SYS_RES_IRQ: 717 flags |= RF_SHAREABLE; 718 break; 719 } 720 /* Allocate the resource to the child */ 721 return resource_list_alloc(&dinfo->pci.resources, cbdev, child, 722 type, rid, rle->start, rle->end, rle->count, flags); 723 } 724} 725 726static int 727cardbus_release_resource(device_t cbdev, device_t child, int type, int rid, 728 struct resource *r) 729{ 730 struct cardbus_devinfo *dinfo; 731 int passthrough = (device_get_parent(child) != cbdev); 732 struct resource_list_entry *rle = 0; 733 int flags; 734 int ret; 735 736 if (passthrough) { 737 return BUS_RELEASE_RESOURCE(device_get_parent(cbdev), child, 738 type, rid, r); 739 } 740 741 dinfo = device_get_ivars(child); 742 /* 743 * According to the PCI 2.2 spec, devices may share an address 744 * decoder between memory mapped ROM access and memory 745 * mapped register access. To be safe, disable ROM access 746 * whenever it is released. 747 */ 748 if (rid == CARDBUS_ROM_REG) { 749 uint32_t rom_reg; 750 751 rom_reg = pci_read_config(child, rid, 4); 752 rom_reg &= ~CARDBUS_ROM_ENABLE; 753 pci_write_config(child, rid, rom_reg, 4); 754 } 755 756 rle = resource_list_find(&dinfo->pci.resources, type, rid); 757 758 if (!rle) { 759 device_printf(cbdev, "Allocated resource not found\n"); 760 return ENOENT; 761 } 762 if (!rle->res) { 763 device_printf(cbdev, "Allocated resource not recorded\n"); 764 return ENOENT; 765 } 766 767 ret = BUS_RELEASE_RESOURCE(device_get_parent(cbdev), child, 768 type, rid, r); 769 switch (type) { 770 case SYS_RES_IOPORT: 771 case SYS_RES_MEMORY: 772 flags = rman_make_alignment_flags(rle->count); 773 break; 774 case SYS_RES_IRQ: 775 flags = RF_SHAREABLE; 776 break; 777 default: 778 flags = 0; 779 } 780 /* Restore cardbus hold on the resource */ 781 rle->res = bus_alloc_resource(cbdev, type, &rid, 782 rle->start, rle->end, rle->count, flags); 783 if (rle->res == NULL) 784 device_printf(cbdev, "release_resource: " 785 "unable to reacquire resource\n"); 786 return ret; 787} 788 789static int 790cardbus_setup_intr(device_t cbdev, device_t child, struct resource *irq, 791 int flags, driver_intr_t *intr, void *arg, void **cookiep) 792{ 793 int ret; 794 device_t cdev; 795 struct cardbus_devinfo *dinfo; 796 797 ret = bus_generic_setup_intr(cbdev, child, irq, flags, intr, arg, 798 cookiep); 799 if (ret != 0) 800 return ret; 801 802 for (cdev = child; cbdev != device_get_parent(cdev); 803 cdev = device_get_parent(cdev)) 804 /* NOTHING */; 805 dinfo = device_get_ivars(cdev); 806 807 return 0; 808} 809 810static int 811cardbus_teardown_intr(device_t cbdev, device_t child, struct resource *irq, 812 void *cookie) 813{ 814 int ret; 815 device_t cdev; 816 struct cardbus_devinfo *dinfo; 817 818 ret = bus_generic_teardown_intr(cbdev, child, irq, cookie); 819 if (ret != 0) 820 return ret; 821 822 for (cdev = child; cbdev != device_get_parent(cdev); 823 cdev = device_get_parent(cdev)) 824 /* NOTHING */; 825 dinfo = device_get_ivars(cdev); 826 827 return (0); 828} 829 830 831/************************************************************************/ 832/* Other Bus Methods */ 833/************************************************************************/ 834 835static int 836cardbus_print_resources(struct resource_list *rl, const char *name, 837 int type, const char *format) 838{ 839 struct resource_list_entry *rle; 840 int printed, retval; 841 842 printed = 0; 843 retval = 0; 844 /* Yes, this is kinda cheating */ 845 SLIST_FOREACH(rle, rl, link) { 846 if (rle->type == type) { 847 if (printed == 0) 848 retval += printf(" %s ", name); 849 else if (printed > 0) 850 retval += printf(","); 851 printed++; 852 retval += printf(format, rle->start); 853 if (rle->count > 1) { 854 retval += printf("-"); 855 retval += printf(format, rle->start + 856 rle->count - 1); 857 } 858 } 859 } 860 return retval; 861} 862 863static int 864cardbus_print_child(device_t cbdev, device_t child) 865{ 866 struct cardbus_devinfo *dinfo; 867 struct resource_list *rl; 868 pcicfgregs *cfg; 869 int retval = 0; 870 871 dinfo = device_get_ivars(child); 872 cfg = &dinfo->pci.cfg; 873 rl = &dinfo->pci.resources; 874 875 retval += bus_print_child_header(cbdev, child); 876 877 retval += cardbus_print_resources(rl, "port", SYS_RES_IOPORT, "%#lx"); 878 retval += cardbus_print_resources(rl, "mem", SYS_RES_MEMORY, "%#lx"); 879 retval += cardbus_print_resources(rl, "irq", SYS_RES_IRQ, "%ld"); 880 if (device_get_flags(cbdev)) 881 retval += printf(" flags %#x", device_get_flags(cbdev)); 882 883 retval += printf(" at device %d.%d", pci_get_slot(child), 884 pci_get_function(child)); 885 886 retval += bus_print_child_footer(cbdev, child); 887 888 return (retval); 889} 890 891static void 892cardbus_probe_nomatch(device_t cbdev, device_t child) 893{ 894 struct cardbus_devinfo *dinfo; 895 pcicfgregs *cfg; 896 897 dinfo = device_get_ivars(child); 898 cfg = &dinfo->pci.cfg; 899 device_printf(cbdev, "<unknown card>"); 900 printf(" (vendor=0x%04x, dev=0x%04x)", cfg->vendor, cfg->device); 901 printf(" at %d.%d", pci_get_slot(child), pci_get_function(child)); 902 if (cfg->intpin > 0 && cfg->intline != 255) { 903 printf(" irq %d", cfg->intline); 904 } 905 printf("\n"); 906 907 return; 908} 909 910static int 911cardbus_child_location_str(device_t cbdev, device_t child, char *buf, 912 size_t buflen) 913{ 914 struct cardbus_devinfo *dinfo; 915 pcicfgregs *cfg; 916 917 dinfo = device_get_ivars(child); 918 cfg = &dinfo->pci.cfg; 919 snprintf(buf, buflen, "slot=%d function=%d", pci_get_slot(child), 920 pci_get_function(child)); 921 return (0); 922} 923 924static int 925cardbus_child_pnpinfo_str(device_t cbdev, device_t child, char *buf, 926 size_t buflen) 927{ 928 struct cardbus_devinfo *dinfo; 929 pcicfgregs *cfg; 930 931 dinfo = device_get_ivars(child); 932 cfg = &dinfo->pci.cfg; 933 snprintf(buf, buflen, "vendor=0x%04x device=0x%04x subvendor=0x%04x " 934 "subdevice=0x%04x", cfg->vendor, cfg->device, cfg->subvendor, 935 cfg->subdevice); 936 return (0); 937} 938 939static int 940cardbus_read_ivar(device_t cbdev, device_t child, int which, u_long *result) 941{ 942 struct cardbus_devinfo *dinfo; 943 pcicfgregs *cfg; 944 945 dinfo = device_get_ivars(child); 946 cfg = &dinfo->pci.cfg; 947 948 switch (which) { 949 case PCI_IVAR_ETHADDR: 950 /* 951 * The generic accessor doesn't deal with failure, so 952 * we set the return value, then return an error. 953 */ 954 if ((dinfo->fepresent & (1 << TPL_FUNCE_LAN_NID)) == 0) {
|
1161 1162 command = PCI_READ_CONFIG(cbdev, child, PCIR_COMMAND, 2); 1163 command &= ~bit; 1164 PCI_WRITE_CONFIG(cbdev, child, PCIR_COMMAND, command, 2); 1165} 1166 1167static void 1168cardbus_enable_busmaster_method(device_t cbdev, device_t child) 1169{ 1170 cardbus_set_command_bit(cbdev, child, PCIM_CMD_BUSMASTEREN); 1171} 1172 1173static void 1174cardbus_disable_busmaster_method(device_t cbdev, device_t child) 1175{ 1176 cardbus_clear_command_bit(cbdev, child, PCIM_CMD_BUSMASTEREN); 1177} 1178 1179static void 1180cardbus_enable_io_method(device_t cbdev, device_t child, int space) 1181{ 1182 switch (space) { 1183 case SYS_RES_IOPORT: 1184 cardbus_set_command_bit(cbdev, child, PCIM_CMD_PORTEN); 1185 break; 1186 case SYS_RES_MEMORY: 1187 cardbus_set_command_bit(cbdev, child, PCIM_CMD_MEMEN); 1188 break; 1189 } 1190} 1191 1192static void 1193cardbus_disable_io_method(device_t cbdev, device_t child, int space) 1194{ 1195 switch (space) { 1196 case SYS_RES_IOPORT: 1197 cardbus_clear_command_bit(cbdev, child, PCIM_CMD_PORTEN); 1198 break; 1199 case SYS_RES_MEMORY: 1200 cardbus_clear_command_bit(cbdev, child, PCIM_CMD_MEMEN); 1201 break; 1202 } 1203} 1204 1205static device_method_t cardbus_methods[] = { 1206 /* Device interface */ 1207 DEVMETHOD(device_probe, cardbus_probe), 1208 DEVMETHOD(device_attach, cardbus_attach), 1209 DEVMETHOD(device_detach, cardbus_detach), 1210 DEVMETHOD(device_shutdown, bus_generic_shutdown), 1211 DEVMETHOD(device_suspend, cardbus_suspend), 1212 DEVMETHOD(device_resume, cardbus_resume), 1213 1214 /* Bus interface */ 1215 DEVMETHOD(bus_print_child, cardbus_print_child), 1216 DEVMETHOD(bus_probe_nomatch, cardbus_probe_nomatch), 1217 DEVMETHOD(bus_read_ivar, cardbus_read_ivar), 1218 DEVMETHOD(bus_write_ivar, cardbus_write_ivar), 1219 DEVMETHOD(bus_driver_added, cardbus_driver_added), 1220 DEVMETHOD(bus_alloc_resource, cardbus_alloc_resource), 1221 DEVMETHOD(bus_release_resource, cardbus_release_resource), 1222 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 1223 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 1224 DEVMETHOD(bus_setup_intr, cardbus_setup_intr), 1225 DEVMETHOD(bus_teardown_intr, cardbus_teardown_intr), 1226 1227 DEVMETHOD(bus_set_resource, cardbus_set_resource_method), 1228 DEVMETHOD(bus_get_resource, cardbus_get_resource_method), 1229 DEVMETHOD(bus_delete_resource, cardbus_delete_resource_method), 1230 DEVMETHOD(bus_child_pnpinfo_str, cardbus_child_pnpinfo_str), 1231 DEVMETHOD(bus_child_location_str, cardbus_child_location_str), 1232 1233 /* Card Interface */ 1234 DEVMETHOD(card_attach_card, cardbus_attach_card), 1235 DEVMETHOD(card_detach_card, cardbus_detach_card), 1236 DEVMETHOD(card_cis_read, cardbus_cis_read), 1237 DEVMETHOD(card_cis_free, cardbus_cis_free), 1238 1239 /* Cardbus/PCI interface */ 1240 DEVMETHOD(pci_read_config, cardbus_read_config_method), 1241 DEVMETHOD(pci_write_config, cardbus_write_config_method), 1242 DEVMETHOD(pci_enable_busmaster, cardbus_enable_busmaster_method), 1243 DEVMETHOD(pci_disable_busmaster, cardbus_disable_busmaster_method), 1244 DEVMETHOD(pci_enable_io, cardbus_enable_io_method), 1245 DEVMETHOD(pci_disable_io, cardbus_disable_io_method), 1246 DEVMETHOD(pci_get_powerstate, cardbus_get_powerstate_method), 1247 DEVMETHOD(pci_set_powerstate, cardbus_set_powerstate_method), 1248 1249 {0,0} 1250}; 1251 1252static driver_t cardbus_driver = { 1253 "cardbus", 1254 cardbus_methods, 1255 0 /* no softc */ 1256}; 1257 1258static devclass_t cardbus_devclass; 1259 1260DRIVER_MODULE(cardbus, cbb, cardbus_driver, cardbus_devclass, 0, 0); 1261MODULE_VERSION(cardbus, 1); 1262MODULE_DEPEND(cardbus, exca, 1, 1, 1); 1263/* 1264MODULE_DEPEND(cardbus, pccbb, 1, 1, 1); 1265*/
| 1161 1162 command = PCI_READ_CONFIG(cbdev, child, PCIR_COMMAND, 2); 1163 command &= ~bit; 1164 PCI_WRITE_CONFIG(cbdev, child, PCIR_COMMAND, command, 2); 1165} 1166 1167static void 1168cardbus_enable_busmaster_method(device_t cbdev, device_t child) 1169{ 1170 cardbus_set_command_bit(cbdev, child, PCIM_CMD_BUSMASTEREN); 1171} 1172 1173static void 1174cardbus_disable_busmaster_method(device_t cbdev, device_t child) 1175{ 1176 cardbus_clear_command_bit(cbdev, child, PCIM_CMD_BUSMASTEREN); 1177} 1178 1179static void 1180cardbus_enable_io_method(device_t cbdev, device_t child, int space) 1181{ 1182 switch (space) { 1183 case SYS_RES_IOPORT: 1184 cardbus_set_command_bit(cbdev, child, PCIM_CMD_PORTEN); 1185 break; 1186 case SYS_RES_MEMORY: 1187 cardbus_set_command_bit(cbdev, child, PCIM_CMD_MEMEN); 1188 break; 1189 } 1190} 1191 1192static void 1193cardbus_disable_io_method(device_t cbdev, device_t child, int space) 1194{ 1195 switch (space) { 1196 case SYS_RES_IOPORT: 1197 cardbus_clear_command_bit(cbdev, child, PCIM_CMD_PORTEN); 1198 break; 1199 case SYS_RES_MEMORY: 1200 cardbus_clear_command_bit(cbdev, child, PCIM_CMD_MEMEN); 1201 break; 1202 } 1203} 1204 1205static device_method_t cardbus_methods[] = { 1206 /* Device interface */ 1207 DEVMETHOD(device_probe, cardbus_probe), 1208 DEVMETHOD(device_attach, cardbus_attach), 1209 DEVMETHOD(device_detach, cardbus_detach), 1210 DEVMETHOD(device_shutdown, bus_generic_shutdown), 1211 DEVMETHOD(device_suspend, cardbus_suspend), 1212 DEVMETHOD(device_resume, cardbus_resume), 1213 1214 /* Bus interface */ 1215 DEVMETHOD(bus_print_child, cardbus_print_child), 1216 DEVMETHOD(bus_probe_nomatch, cardbus_probe_nomatch), 1217 DEVMETHOD(bus_read_ivar, cardbus_read_ivar), 1218 DEVMETHOD(bus_write_ivar, cardbus_write_ivar), 1219 DEVMETHOD(bus_driver_added, cardbus_driver_added), 1220 DEVMETHOD(bus_alloc_resource, cardbus_alloc_resource), 1221 DEVMETHOD(bus_release_resource, cardbus_release_resource), 1222 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 1223 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 1224 DEVMETHOD(bus_setup_intr, cardbus_setup_intr), 1225 DEVMETHOD(bus_teardown_intr, cardbus_teardown_intr), 1226 1227 DEVMETHOD(bus_set_resource, cardbus_set_resource_method), 1228 DEVMETHOD(bus_get_resource, cardbus_get_resource_method), 1229 DEVMETHOD(bus_delete_resource, cardbus_delete_resource_method), 1230 DEVMETHOD(bus_child_pnpinfo_str, cardbus_child_pnpinfo_str), 1231 DEVMETHOD(bus_child_location_str, cardbus_child_location_str), 1232 1233 /* Card Interface */ 1234 DEVMETHOD(card_attach_card, cardbus_attach_card), 1235 DEVMETHOD(card_detach_card, cardbus_detach_card), 1236 DEVMETHOD(card_cis_read, cardbus_cis_read), 1237 DEVMETHOD(card_cis_free, cardbus_cis_free), 1238 1239 /* Cardbus/PCI interface */ 1240 DEVMETHOD(pci_read_config, cardbus_read_config_method), 1241 DEVMETHOD(pci_write_config, cardbus_write_config_method), 1242 DEVMETHOD(pci_enable_busmaster, cardbus_enable_busmaster_method), 1243 DEVMETHOD(pci_disable_busmaster, cardbus_disable_busmaster_method), 1244 DEVMETHOD(pci_enable_io, cardbus_enable_io_method), 1245 DEVMETHOD(pci_disable_io, cardbus_disable_io_method), 1246 DEVMETHOD(pci_get_powerstate, cardbus_get_powerstate_method), 1247 DEVMETHOD(pci_set_powerstate, cardbus_set_powerstate_method), 1248 1249 {0,0} 1250}; 1251 1252static driver_t cardbus_driver = { 1253 "cardbus", 1254 cardbus_methods, 1255 0 /* no softc */ 1256}; 1257 1258static devclass_t cardbus_devclass; 1259 1260DRIVER_MODULE(cardbus, cbb, cardbus_driver, cardbus_devclass, 0, 0); 1261MODULE_VERSION(cardbus, 1); 1262MODULE_DEPEND(cardbus, exca, 1, 1, 1); 1263/* 1264MODULE_DEPEND(cardbus, pccbb, 1, 1, 1); 1265*/
|