1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/fm/protocol.h> 28 #include <assert.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <strings.h> 33 #include <alloca.h> 34 #include <sys/param.h> 35 #include <sys/pci.h> 36 #include <sys/pcie.h> 37 #include <libdevinfo.h> 38 #include <libnvpair.h> 39 #include <fm/topo_mod.h> 40 #include <fm/topo_hc.h> 41 42 #include <hostbridge.h> 43 #include <pcibus.h> 44 #include <did.h> 45 #include <did_props.h> 46 #include <util.h> 47 48 extern txprop_t Bus_common_props[]; 49 extern txprop_t Dev_common_props[]; 50 extern txprop_t Fn_common_props[]; 51 extern int Bus_propcnt; 52 extern int Dev_propcnt; 53 extern int Fn_propcnt; 54 55 extern int platform_pci_label(topo_mod_t *mod, tnode_t *, nvlist_t *, 56 nvlist_t **); 57 extern int platform_pci_fru(topo_mod_t *mod, tnode_t *, nvlist_t *, 58 nvlist_t **); 59 static void pci_release(topo_mod_t *, tnode_t *); 60 static int pci_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t, 61 topo_instance_t, void *, void *); 62 static int pci_label(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, 63 nvlist_t **); 64 static int pci_fru(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, 65 nvlist_t **); 66 67 static const topo_modops_t Pci_ops = 68 { pci_enum, pci_release }; 69 static const topo_modinfo_t Pci_info = 70 { PCI_BUS, FM_FMRI_SCHEME_HC, PCI_ENUMR_VERS, &Pci_ops }; 71 72 static const topo_method_t Pci_methods[] = { 73 { TOPO_METH_LABEL, TOPO_METH_LABEL_DESC, 74 TOPO_METH_LABEL_VERSION, TOPO_STABILITY_INTERNAL, pci_label }, 75 { TOPO_METH_FRU_COMPUTE, TOPO_METH_FRU_COMPUTE_DESC, 76 TOPO_METH_FRU_COMPUTE_VERSION, TOPO_STABILITY_INTERNAL, pci_fru }, 77 { NULL } 78 }; 79 80 int 81 _topo_init(topo_mod_t *modhdl, topo_version_t version) 82 { 83 /* 84 * Turn on module debugging output 85 */ 86 if (getenv("TOPOPCIDBG") != NULL) 87 topo_mod_setdebug(modhdl); 88 topo_mod_dprintf(modhdl, "initializing pcibus builtin\n"); 89 90 if (version != PCI_ENUMR_VERS) 91 return (topo_mod_seterrno(modhdl, EMOD_VER_NEW)); 92 93 if (topo_mod_register(modhdl, &Pci_info, TOPO_VERSION) != 0) { 94 topo_mod_dprintf(modhdl, "failed to register module"); 95 return (-1); 96 } 97 topo_mod_dprintf(modhdl, "PCI Enumr initd\n"); 98 99 return (0); 100 } 101 102 void 103 _topo_fini(topo_mod_t *modhdl) 104 { 105 topo_mod_unregister(modhdl); 106 } 107 108 static int 109 pci_label(topo_mod_t *mp, tnode_t *node, topo_version_t version, 110 nvlist_t *in, nvlist_t **out) 111 { 112 if (version > TOPO_METH_LABEL_VERSION) 113 return (topo_mod_seterrno(mp, EMOD_VER_NEW)); 114 return (platform_pci_label(mp, node, in, out)); 115 } 116 static int 117 pci_fru(topo_mod_t *mp, tnode_t *node, topo_version_t version, 118 nvlist_t *in, nvlist_t **out) 119 { 120 if (version > TOPO_METH_FRU_COMPUTE_VERSION) 121 return (topo_mod_seterrno(mp, EMOD_VER_NEW)); 122 return (platform_pci_fru(mp, node, in, out)); 123 } 124 static tnode_t * 125 pci_tnode_create(topo_mod_t *mod, tnode_t *parent, 126 const char *name, topo_instance_t i, void *priv) 127 { 128 tnode_t *ntn; 129 130 if ((ntn = tnode_create(mod, parent, name, i, priv)) == NULL) 131 return (NULL); 132 if (topo_method_register(mod, ntn, Pci_methods) < 0) { 133 topo_mod_dprintf(mod, "topo_method_register failed: %s\n", 134 topo_strerror(topo_mod_errno(mod))); 135 topo_node_unbind(ntn); 136 return (NULL); 137 } 138 return (ntn); 139 } 140 141 /*ARGSUSED*/ 142 static int 143 hostbridge_asdevice(topo_mod_t *mod, tnode_t *bus) 144 { 145 di_node_t di; 146 tnode_t *dev32; 147 148 di = topo_node_getspecific(bus); 149 assert(di != DI_NODE_NIL); 150 151 if ((dev32 = pcidev_declare(mod, bus, di, 32)) == NULL) 152 return (-1); 153 if (pcifn_declare(mod, dev32, di, 0) == NULL) { 154 topo_node_unbind(dev32); 155 return (-1); 156 } 157 return (0); 158 } 159 160 tnode_t * 161 pciexfn_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn, 162 topo_instance_t i) 163 { 164 did_t *pd; 165 tnode_t *ntn, *ptn; 166 di_node_t pdn; 167 uint_t class, subclass; 168 char *devtyp, *pdevtyp; 169 int pcie_devtyp, pexcap; 170 boolean_t dev_is_pcie, pdev_is_pcie; 171 172 /* We need the parent's dev info node for some of the info */ 173 ptn = find_predecessor(parent, PCIEX_FUNCTION); 174 /* If this is the first child under root, get root's ptn */ 175 if (ptn == NULL) 176 ptn = find_predecessor(parent, PCIEX_ROOT); 177 if (ptn == NULL) 178 return (NULL); 179 pdn = topo_node_getspecific(ptn); 180 181 /* Get the required info to populate the excap */ 182 (void) pci_classcode_get(mod, dn, &class, &subclass); 183 devtyp = pci_devtype_get(mod, dn); 184 pdevtyp = pci_devtype_get(mod, pdn); 185 pexcap = pciex_cap_get(mod, pdn); 186 187 dev_is_pcie = devtyp && (strcmp(devtyp, "pciex") == 0); 188 pdev_is_pcie = pdevtyp && (strcmp(pdevtyp, "pciex") == 0); 189 190 /* 191 * Populate the excap with correct PCIe device type. 192 * 193 * Device Parent Device Parent Device 194 * excap device-type device-type excap Class Code 195 * ------------------------------------------------------------------- 196 * PCI(default) pci N/A N/A != bridge 197 * PCIe pciex N/A N/A != bridge 198 * Root Port Defined in hostbridge 199 * Switch Up pciex pciex != up = bridge 200 * Switch Down pciex pciex = up = bridge 201 * PCIe-PCI pciex pci N/A = bridge 202 * PCI-PCIe pci pciex N/A = bridge 203 */ 204 pcie_devtyp = PCIE_PCIECAP_DEV_TYPE_PCI_DEV; 205 if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI) { 206 if (pdev_is_pcie) { 207 if (dev_is_pcie) { 208 if (pexcap != PCIE_PCIECAP_DEV_TYPE_UP) 209 pcie_devtyp = PCIE_PCIECAP_DEV_TYPE_UP; 210 else 211 pcie_devtyp = 212 PCIE_PCIECAP_DEV_TYPE_DOWN; 213 } else { 214 pcie_devtyp = PCIE_PCIECAP_DEV_TYPE_PCIE2PCI; 215 } 216 } else { 217 if (dev_is_pcie) 218 pcie_devtyp = PCIE_PCIECAP_DEV_TYPE_PCI2PCIE; 219 } 220 } else { 221 if (pdev_is_pcie) 222 pcie_devtyp = PCIE_PCIECAP_DEV_TYPE_PCIE_DEV; 223 } 224 225 if ((pd = did_find(mod, dn)) == NULL) 226 return (NULL); 227 did_excap_set(pd, pcie_devtyp); 228 229 if ((ntn = pci_tnode_create(mod, parent, PCIEX_FUNCTION, i, dn)) 230 == NULL) 231 return (NULL); 232 if (did_props_set(ntn, pd, Fn_common_props, Fn_propcnt) < 0) { 233 topo_node_unbind(ntn); 234 return (NULL); 235 } 236 /* 237 * We may find pci-express buses or plain-pci buses beneath a function 238 */ 239 if (child_range_add(mod, ntn, PCIEX_BUS, 0, MAX_HB_BUSES) < 0) { 240 topo_node_unbind(ntn); 241 return (NULL); 242 } 243 if (child_range_add(mod, ntn, PCI_BUS, 0, MAX_HB_BUSES) < 0) { 244 topo_node_range_destroy(ntn, PCIEX_BUS); 245 topo_node_unbind(ntn); 246 return (NULL); 247 } 248 return (ntn); 249 } 250 251 tnode_t * 252 pciexdev_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn, 253 topo_instance_t i) 254 { 255 did_t *pd; 256 tnode_t *ntn; 257 258 if ((pd = did_find(mod, dn)) == NULL) 259 return (NULL); 260 did_settnode(pd, parent); 261 262 if ((ntn = pci_tnode_create(mod, parent, PCIEX_DEVICE, i, dn)) == NULL) 263 return (NULL); 264 if (did_props_set(ntn, pd, Dev_common_props, Dev_propcnt) < 0) { 265 topo_node_unbind(ntn); 266 return (NULL); 267 } 268 269 /* 270 * We can expect to find pci-express functions beneath the device 271 */ 272 if (child_range_add(mod, 273 ntn, PCIEX_FUNCTION, 0, MAX_PCIDEV_FNS) < 0) { 274 topo_node_unbind(ntn); 275 return (NULL); 276 } 277 return (ntn); 278 } 279 280 tnode_t * 281 pciexbus_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn, 282 topo_instance_t i) 283 { 284 did_t *pd; 285 tnode_t *ntn; 286 287 if ((pd = did_find(mod, dn)) == NULL) 288 return (NULL); 289 did_settnode(pd, parent); 290 if ((ntn = pci_tnode_create(mod, parent, PCIEX_BUS, i, dn)) == NULL) 291 return (NULL); 292 if (did_props_set(ntn, pd, Bus_common_props, Bus_propcnt) < 0) { 293 topo_node_unbind(ntn); 294 return (NULL); 295 } 296 /* 297 * We can expect to find pci-express devices beneath the bus 298 */ 299 if (child_range_add(mod, 300 ntn, PCIEX_DEVICE, 0, MAX_PCIBUS_DEVS) < 0) { 301 topo_node_unbind(ntn); 302 return (NULL); 303 } 304 return (ntn); 305 } 306 307 tnode_t * 308 pcifn_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn, 309 topo_instance_t i) 310 { 311 did_t *pd; 312 tnode_t *ntn; 313 314 if ((pd = did_find(mod, dn)) == NULL) 315 return (NULL); 316 did_excap_set(pd, PCIE_PCIECAP_DEV_TYPE_PCI_DEV); 317 318 if ((ntn = pci_tnode_create(mod, parent, PCI_FUNCTION, i, dn)) == NULL) 319 return (NULL); 320 if (did_props_set(ntn, pd, Fn_common_props, Fn_propcnt) < 0) { 321 topo_node_unbind(ntn); 322 return (NULL); 323 } 324 /* 325 * We may find pci buses beneath a function 326 */ 327 if (child_range_add(mod, ntn, PCI_BUS, 0, MAX_HB_BUSES) < 0) { 328 topo_node_unbind(ntn); 329 return (NULL); 330 } 331 return (ntn); 332 } 333 334 tnode_t * 335 pcidev_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn, 336 topo_instance_t i) 337 { 338 did_t *pd; 339 tnode_t *ntn; 340 341 if ((pd = did_find(mod, dn)) == NULL) 342 return (NULL); 343 /* remember parent tnode */ 344 did_settnode(pd, parent); 345 346 if ((ntn = pci_tnode_create(mod, parent, PCI_DEVICE, i, dn)) == NULL) 347 return (NULL); 348 if (did_props_set(ntn, pd, Dev_common_props, Dev_propcnt) < 0) { 349 topo_node_unbind(ntn); 350 return (NULL); 351 } 352 353 /* 354 * We can expect to find pci functions beneath the device 355 */ 356 if (child_range_add(mod, ntn, PCI_FUNCTION, 0, MAX_PCIDEV_FNS) < 0) { 357 topo_node_unbind(ntn); 358 return (NULL); 359 } 360 return (ntn); 361 } 362 363 tnode_t * 364 pcibus_declare(topo_mod_t *mod, tnode_t *parent, di_node_t dn, 365 topo_instance_t i) 366 { 367 did_t *pd; 368 tnode_t *ntn; 369 int hbchild = 0; 370 371 if ((pd = did_find(mod, dn)) == NULL) 372 return (NULL); 373 did_settnode(pd, parent); 374 if ((ntn = pci_tnode_create(mod, parent, PCI_BUS, i, dn)) == NULL) 375 return (NULL); 376 /* 377 * If our devinfo node is lacking certain information of its 378 * own, and our parent topology node is a hostbridge, we may 379 * need/want to inherit information available in the 380 * hostbridge node's private data. 381 */ 382 if (strcmp(topo_node_name(parent), HOSTBRIDGE) == 0) 383 hbchild = 1; 384 if (did_props_set(ntn, pd, Bus_common_props, Bus_propcnt) < 0) { 385 topo_node_unbind(ntn); 386 return (NULL); 387 } 388 /* 389 * We can expect to find pci devices beneath the bus 390 */ 391 if (child_range_add(mod, ntn, PCI_DEVICE, 0, MAX_PCIBUS_DEVS) < 0) { 392 topo_node_unbind(ntn); 393 return (NULL); 394 } 395 /* 396 * On each bus child of the hostbridge, we represent the 397 * hostbridge as a device outside the range of legal device 398 * numbers. 399 */ 400 if (hbchild == 1) { 401 if (hostbridge_asdevice(mod, ntn) < 0) { 402 topo_node_range_destroy(ntn, PCI_DEVICE); 403 topo_node_unbind(ntn); 404 return (NULL); 405 } 406 } 407 return (ntn); 408 } 409 410 static int 411 pci_bridge_declare(topo_mod_t *mod, tnode_t *fn, di_node_t din, int board, 412 int bridge, int rc, int depth) 413 { 414 int err; 415 char *devtyp; 416 417 devtyp = pci_devtype_get(mod, din); 418 /* Check if the children are PCI or PCIe */ 419 if (devtyp && (strcmp(devtyp, "pciex") == 0)) 420 err = pci_children_instantiate(mod, fn, din, board, bridge, 421 rc, TRUST_BDF, depth + 1); 422 else 423 err = pci_children_instantiate(mod, fn, din, board, bridge, 424 rc - TO_PCI, TRUST_BDF, depth + 1); 425 return (err); 426 } 427 428 static void 429 declare_dev_and_fn(topo_mod_t *mod, tnode_t *bus, tnode_t **dev, di_node_t din, 430 int board, int bridge, int rc, int devno, int fnno, int depth) 431 { 432 int dcnt = 0; 433 tnode_t *fn; 434 uint_t class, subclass; 435 uint_t vid, did; 436 did_t *dp = NULL; 437 438 if (*dev == NULL) { 439 if (rc >= 0) 440 *dev = pciexdev_declare(mod, bus, din, devno); 441 else 442 *dev = pcidev_declare(mod, bus, din, devno); 443 if (*dev == NULL) 444 return; 445 ++dcnt; 446 } 447 if (rc >= 0) 448 fn = pciexfn_declare(mod, *dev, din, fnno); 449 else 450 fn = pcifn_declare(mod, *dev, din, fnno); 451 452 if (fn == NULL) { 453 if (dcnt) { 454 topo_node_unbind(*dev); 455 *dev = NULL; 456 } 457 return; 458 } 459 460 if (pci_classcode_get(mod, din, &class, &subclass) < 0) { 461 topo_node_unbind(fn); 462 if (dcnt) 463 topo_node_unbind(*dev); 464 return; 465 } 466 467 /* 468 * This function may be a bridge. If not, check for a possible 469 * topology map file and kick off its enumeration of lower-level 470 * devices. 471 */ 472 if (class == PCI_CLASS_BRIDGE && subclass == PCI_BRIDGE_PCI) { 473 (void) pci_bridge_declare(mod, fn, din, board, bridge, rc, 474 depth); 475 } 476 477 /* 478 * Check for a Neptune-based NIC. This could either be a Neptune 479 * adapter card or an Neptune ASIC on a board (e.g. motherboard) 480 * 481 * For Netpune adapter cards, use xfp-hc-topology.xml to expand 482 * topology to include the XFP optical module, which is a FRU on 483 * the Neptune based 10giga fiber NICs. 484 * 485 * For Neptune ASICs, use the XAUI enumerator to expand topology. 486 * The 10giga ports are externalized by a XAUI cards, which 487 * are FRUs. The XAUI enumerator in turn instantiates the XFP 488 * optical module FRUs. 489 */ 490 else if (class == PCI_CLASS_NET && 491 di_uintprop_get(mod, din, DI_VENDIDPROP, &vid) >= 0 && 492 di_uintprop_get(mod, din, DI_DEVIDPROP, &did) >= 0) { 493 if (vid == SUN_VENDOR_ID && did == NEPTUNE_DEVICE_ID) { 494 /* 495 * Is this an adapter card? Check the bus's physlot 496 */ 497 dp = did_find(mod, topo_node_getspecific(bus)); 498 if (did_physlot(dp) >= 0) { 499 topo_mod_dprintf(mod, "Found Neptune slot\n"); 500 (void) topo_mod_enummap(mod, fn, 501 "xfp", FM_FMRI_SCHEME_HC); 502 } else { 503 topo_mod_dprintf(mod, "Found Neptune ASIC\n"); 504 if (topo_mod_load(mod, XAUI, TOPO_VERSION) == 505 NULL) { 506 topo_mod_dprintf(mod, "pcibus enum " 507 "could not load xaui enum\n"); 508 (void) topo_mod_seterrno(mod, 509 EMOD_PARTIAL_ENUM); 510 return; 511 } else { 512 if (topo_node_range_create(mod, fn, 513 XAUI, 0, 1) < 0) { 514 topo_mod_dprintf(mod, 515 "child_range_add for " 516 "XAUI failed: %s\n", 517 topo_strerror( 518 topo_mod_errno(mod))); 519 return; 520 } 521 (void) topo_mod_enumerate(mod, fn, 522 XAUI, XAUI, fnno, fnno, fn); 523 } 524 } 525 } 526 } 527 } 528 529 int 530 pci_children_instantiate(topo_mod_t *mod, tnode_t *parent, di_node_t pn, 531 int board, int bridge, int rc, int bover, int depth) 532 { 533 did_t *pps[MAX_PCIBUS_DEVS][MAX_PCIDEV_FNS]; 534 did_t *bp = NULL; 535 did_t *np; 536 di_node_t sib; 537 di_node_t din; 538 tnode_t *bn = NULL; 539 tnode_t *dn = NULL; 540 int pb = -1; 541 int b, d, f; 542 543 for (d = 0; d < MAX_PCIBUS_DEVS; d++) 544 for (f = 0; f < MAX_PCIDEV_FNS; f++) 545 pps[d][f] = NULL; 546 547 /* start at the parent's first sibling */ 548 sib = di_child_node(pn); 549 while (sib != DI_NODE_NIL) { 550 np = did_create(mod, sib, board, bridge, rc, bover); 551 if (np == NULL) 552 return (-1); 553 did_BDF(np, &b, &d, &f); 554 pps[d][f] = np; 555 if (bp == NULL) 556 bp = np; 557 if (pb < 0) 558 pb = ((bover == TRUST_BDF) ? b : bover); 559 sib = di_sibling_node(sib); 560 } 561 if (pb < 0 && bover < 0) 562 return (0); 563 if (rc >= 0) 564 bn = pciexbus_declare(mod, parent, pn, ((pb < 0) ? bover : pb)); 565 else 566 bn = pcibus_declare(mod, parent, pn, ((pb < 0) ? bover : pb)); 567 if (bn == NULL) 568 return (-1); 569 if (pb < 0) 570 return (0); 571 572 for (d = 0; d < MAX_PCIBUS_DEVS; d++) { 573 for (f = 0; f < MAX_PCIDEV_FNS; f++) { 574 if (pps[d][f] == NULL) 575 continue; 576 din = did_dinode(pps[d][f]); 577 578 /* 579 * Try to enumerate as many devices and functions as 580 * possible. If we fail to declare a device, break 581 * out of the function loop. 582 */ 583 declare_dev_and_fn(mod, bn, 584 &dn, din, board, bridge, rc, d, f, depth); 585 did_rele(pps[d][f]); 586 587 if (dn == NULL) 588 break; 589 } 590 dn = NULL; 591 } 592 return (0); 593 } 594 595 static int 596 pciexbus_enum(topo_mod_t *mp, tnode_t *ptn, char *pnm, topo_instance_t min, 597 topo_instance_t max) 598 { 599 di_node_t pdn; 600 int rc; 601 int retval; 602 603 /* 604 * PCI-Express; root complex shares the hostbridge's instance 605 * number. Parent node's private data is a simple di_node_t 606 * and we have to construct our own did hash and did_t. 607 */ 608 rc = topo_node_instance(ptn); 609 610 if ((pdn = topo_node_getspecific(ptn)) == DI_NODE_NIL) { 611 topo_mod_dprintf(mp, 612 "Parent %s node missing private data.\n" 613 "Unable to proceed with %s enumeration.\n", pnm, PCIEX_BUS); 614 return (0); 615 } 616 if (did_hash_init(mp) != 0) 617 return (-1); 618 if ((did_create(mp, pdn, 0, 0, rc, TRUST_BDF)) == NULL) 619 return (-1); /* errno already set */ 620 621 retval = pci_children_instantiate(mp, ptn, pdn, 0, 0, rc, 622 (min == max) ? min : TRUST_BDF, 0); 623 did_hash_fini(mp); 624 625 return (retval); 626 } 627 628 static int 629 pcibus_enum(topo_mod_t *mp, tnode_t *ptn, char *pnm, topo_instance_t min, 630 topo_instance_t max, void *data) 631 { 632 did_t *didp, *hbdid = (did_t *)data; 633 int retval; 634 635 /* 636 * XXTOPO: we should not be sharing private node data with another 637 * module. PCI Bus; Parent node's private data is a did_t. We'll 638 * use the did hash established by the parent. 639 */ 640 did_setspecific(mp, data); 641 642 /* 643 * If we're looking for a specific bus-instance, find the right 644 * did_t in the chain, otherwise, there should be only one did_t. 645 */ 646 if (min == max) { 647 int b; 648 didp = hbdid; 649 while (didp != NULL) { 650 did_BDF(didp, &b, NULL, NULL); 651 if (b == min) 652 break; 653 didp = did_link_get(didp); 654 } 655 if (didp == NULL) { 656 topo_mod_dprintf(mp, 657 "Parent %s node missing private data related\n" 658 "to %s instance %d.\n", pnm, PCI_BUS, min); 659 topo_mod_setspecific(mp, NULL); 660 return (0); 661 } 662 } else { 663 assert(did_link_get(hbdid) == NULL); 664 didp = hbdid; 665 } 666 retval = pci_children_instantiate(mp, ptn, did_dinode(didp), 667 did_board(didp), did_bridge(didp), did_rc(didp), 668 (min == max) ? min : TRUST_BDF, 0); 669 670 topo_mod_setspecific(mp, NULL); 671 672 return (retval); 673 } 674 675 /*ARGSUSED*/ 676 static int 677 pci_enum(topo_mod_t *mod, tnode_t *ptn, const char *name, 678 topo_instance_t min, topo_instance_t max, void *notused, void *data) 679 { 680 int retval; 681 char *pname; 682 683 topo_mod_dprintf(mod, "Enumerating pci!\n"); 684 685 if (strcmp(name, PCI_BUS) != 0 && strcmp(name, PCIEX_BUS) != 0) { 686 topo_mod_dprintf(mod, 687 "Currently only know how to enumerate %s or %s.\n", 688 PCI_BUS, PCIEX_BUS); 689 return (0); 690 } 691 pname = topo_node_name(ptn); 692 if (strcmp(pname, HOSTBRIDGE) != 0 && strcmp(pname, PCIEX_ROOT) != 0) { 693 topo_mod_dprintf(mod, 694 "Currently can only enumerate a %s or %s directly\n", 695 PCI_BUS, PCIEX_BUS); 696 topo_mod_dprintf(mod, 697 "descended from a %s or %s node.\n", 698 HOSTBRIDGE, PCIEX_ROOT); 699 return (0); 700 } 701 702 if (strcmp(name, PCI_BUS) == 0) { 703 retval = pcibus_enum(mod, ptn, pname, min, max, data); 704 } else if (strcmp(name, PCIEX_BUS) == 0) { 705 retval = pciexbus_enum(mod, ptn, pname, min, max); 706 } else { 707 topo_mod_dprintf(mod, 708 "Currently only know how to enumerate %s or %s not %s.\n", 709 PCI_BUS, PCIEX_BUS, name); 710 return (0); 711 } 712 713 return (retval); 714 } 715 716 /*ARGSUSED*/ 717 static void 718 pci_release(topo_mod_t *mp, tnode_t *node) 719 { 720 topo_method_unregister_all(mp, node); 721 722 /* 723 * node private data (did_t) for this node is destroyed in 724 * did_hash_destroy() 725 */ 726 727 topo_node_unbind(node); 728 } 729