pcibus.c revision 5114ab9e55159f74e60386eedf4934dfd140be47
842ae4bd224140319ae7feec1872b93dfd491143fielding * CDDL HEADER START
842ae4bd224140319ae7feec1872b93dfd491143fielding * The contents of this file are subject to the terms of the
842ae4bd224140319ae7feec1872b93dfd491143fielding * Common Development and Distribution License, Version 1.0 only
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"). You may not use this file except in compliance
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * with the License.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * See the License for the specific language governing permissions
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * and limitations under the License.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * When distributing Covered Code, include this CDDL HEADER in each
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * If applicable, add the following below this CDDL HEADER, with the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * fields enclosed by brackets "[]" replaced with your own identifying
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * information: Portions Copyright [yyyy] [name of copyright owner]
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * CDDL HEADER END
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Use is subject to license terms.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#pragma ident "%Z%%M% %I% %E% SMI"
51469a0d2057aa24107b6f5a04e145824e10da1fdirkxvoid instantiate_children(tnode_t *, di_node_t, di_prom_handle_t);
1fbf6ba0f5207e6637b49f9a9dfcc779bbe952a9trawick/* Devtree = di_init("/", DINFOCACHE); */
bb036ec40eb03d669a5838214bf5ac211da0340baaron topo_out(TOPO_ERR, "PCI enumerator: di_init failed.\n");
860d483ae528603f7e1f962903e71ac28358bef6wrowe "PCI enumerator: di_prom_handle_init failed.\n");
e8f95a682820a599fe41b22977010636be5c2717jim * If this devinfo node came originally from OBP data, we'll have prom
e8f95a682820a599fe41b22977010636be5c2717jim * properties associated with the node where we can find properties of
e8f95a682820a599fe41b22977010636be5c2717jim * interest. We ignore anything after the the first four bytes of the
860d483ae528603f7e1f962903e71ac28358bef6wrowe * property, and interpet those first four bytes as our unsigned
e8f95a682820a599fe41b22977010636be5c2717jim * integer. If we don't find the property or it's not large enough,
860d483ae528603f7e1f962903e71ac28358bef6wrowe * 'val' will remained unchanged and we'll return -1. Otherwise 'val'
860d483ae528603f7e1f962903e71ac28358bef6wrowe * gets updated with the property value and we return 0.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingpromprop2uint(di_node_t n, di_prom_handle_t ph, const char *propnm,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while ((pp = di_prom_prop_next(ph, n, pp)) != DI_PROM_PROP_NIL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return (0);
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb return (-1);
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb * If this devinfo node was added by the PCI hotplug framework it
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb * doesn't have the PROM properties, but hopefully has the properties
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb * we're looking for attached directly to the devinfo node. We only
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb * care about the first four bytes of the property, which we read as
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * our unsigned integer. The remaining bytes are ignored. If we
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * don't find the property we're looking for, or can't get its value,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * 'val' remains unchanged and we return -1. Otherwise 'val' gets the
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein * property value and we return 0.
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbbhwprop2uint(di_node_t n, const char *propnm, uint_t *val)
480e6d6e3fbf8fc23af721f430a97afb0012be6ftrawick return (0);
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe return (-1);
bb65aeae7af1d33b64252bbc1b966942d757ac60wrowe * copy_ancestor_prop
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb * Look for a prop of name 'prop' on an ancestor node in the
48d7c43629323c8d5ee9f7bd0d194de0a376b391rbb * topo tree and duplicate that property and its value on node.
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbbstatic void
608d821d7b7d5b856cccef7e9a14582087acd20bjorton const char *value;
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx * copy_prop
860d483ae528603f7e1f962903e71ac28358bef6wrowe * Look for a prop of name 'prop' on the 'from' node in the
2a1011ba69b24f3224bcb358d542017d5f389f78wrowe * topo tree and duplicate that property and its value on node.
e23b77006a8b079c0ad52e42ba2029e759455b8fjortoncopy_prop(const char *prop, tnode_t *node, tnode_t *from)
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx const char *value;
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankgset_devtype_prop(tnode_t *node, di_node_t dinode, di_prom_handle_t ph)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while ((hp = di_prop_next(dinode, hp)) != DI_PROP_NIL) {
873c287c391b0bbc4719b68bb84946515811e1batrawick if (strcmp(di_prom_prop_name(pp), DEVTYPEPROP) == 0) {
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawick * Look for a hardware property containing the contents of this node's
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * pci express capability register. For now, only look at hardware
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * properties and not prom properties. Take the prom handle, though, in
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * case we decide we need to check prom properties at a later date.
7a0780c774fcd7823d2e3a79f55b2f3522602992clar/*ARGSUSED*/
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (hwprop2uint(dinode, SAVED_PCIEX_CAP_REG, (uint_t *)&excap) != 0)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return (-1);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx * Set an EXCAP prop for pci-express capabilities.
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding (void) topo_set_prop(node, EXCAPTPROP, PCIEX_ROOT);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (void) topo_set_prop(node, EXCAPTPROP, PCIEX_SWUP);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding (void) topo_set_prop(node, EXCAPTPROP, PCIEX_SWDWN);
57f96c9788ac60144fbe2e16eb355b22cbc8965fylavic (void) topo_set_prop(node, EXCAPTPROP, PCIEX_DEVICE);
57f96c9788ac60144fbe2e16eb355b22cbc8965fylavic * Get any physical slot name property on this node. The node has to
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * declare itself as representing a physical slot number by having a
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * .PHYSLOTNUM property. We then look for a .PHYSLOTNAME<slot-#>
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * property on the node or an ancestor of the node. If the property
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm * is found on an ancestor, this routine has the side-effect of
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * copying the property to this node.
c2989417297fc5ad287068f41a7972349c44ca2etakashiconst char *
7a0780c774fcd7823d2e3a79f55b2f3522602992clar const char *str;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if ((str = topo_get_prop(node, ".PHYSLOTNUM")) == NULL)
c2989417297fc5ad287068f41a7972349c44ca2etakashi (void) snprintf(tmpbuf, 20, ".PHYSLOTNAME%d", physlot);
b8ee7946aa85a6b2eefd7f9fcf2ed5dc69a7103asctemmeset_std_properties(tnode_t *node, di_node_t dinode, di_prom_handle_t ph)
62ba6bde073be4d332ffc9c89768757d3f646da5dirkx const char *labelval;
62ba6bde073be4d332ffc9c89768757d3f646da5dirkx const char *platval;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * If it's a root complex, set the pciex capabilities property
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding (void) topo_set_prop(node, EXCAPTPROP, PCIEX_ROOT);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * If it's a device node, we pretty much don't add any props
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * Create a DEVTYPE property as necessary
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * Cheat for now and always say the thing is ON
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * For functions, set LABEL based on a .SLOTNM<devno> property
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * in our parent's parent or a .PHYSLOTNAME<slot-#> property
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * in an ancestor, or the parent's parent's LABEL, but only if
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * LABEL is not already set. Also set PLATFRU and PLATASRU
ae491e926e412a749fc27c0d79f8d953a8d9a153brianp * based on any .PLATFRU<devno> and .PLATASRU<devno>
06e2d72d72d35442e1ba8cfe9f343ac0fb2b8cffdreid * properties from parent's parent.
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx if ((labelval = topo_get_prop(node, LABEL)) == NULL) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) snprintf(tmpbuf, MAXPATHLEN, ".SLOTNM%d", devno);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((labelval = topo_get_prop(pop, tmpbuf)) != NULL ||
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick (void) snprintf(tmpbuf, MAXPATHLEN, ".%s%d", PLATASRU, devno);
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick * Pecking order for determining the value of PLAT-FRU:
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick * PLAT-FRU already defined by the .topo file, done.
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick * .PLATFRU<devno> defined, copy that as the value, done.
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * LABEL defined (and not inherited), copy that as the value,
dcde46ca353d5d66bbac2b8e1135ac828992b808dreid * Copy value from an ancestor.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (void) snprintf(tmpbuf, MAXPATHLEN, ".%s%d", PLATFRU, devno);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((platval = topo_get_prop(pop, tmpbuf)) != NULL) {
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf * fix_dev_prop -- sometimes di_devfs_path() doesn't tell the whole
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf * story, leaving off the device and function number. Chances are if
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf * devfs doesn't put these on then we'll never see this device as an
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf * error detector called out in an ereport. Unfortunately, there are
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf * races and we sometimes do get ereports from devices that devfs
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf * decides aren't there. For example, the error injector card seems
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf * to bounce in and out of existence according to devfs. We tack on
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf * the missing dev and fn here so that the DEV property used to look
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf * up the topology node is correct.
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sfstatic void
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf const char *curdev;
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf /* Check if there is a DEV prop to fix. */
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf * We only care about the last component of the dev path. If
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf * we don't find a slash, something is probably weird and we'll
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf * just bail.
873c287c391b0bbc4719b68bb84946515811e1batrawick * If an @ sign is present in the last component, the
873c287c391b0bbc4719b68bb84946515811e1batrawick * di_devfs_path() result had the device,fn unit-address.
873c287c391b0bbc4719b68bb84946515811e1batrawick * In that case there's nothing we need do.
873c287c391b0bbc4719b68bb84946515811e1batrawick need = snprintf(NULL, 0, "%s@%x,%x", curdev, devno, fnno);
873c287c391b0bbc4719b68bb84946515811e1batrawick (void) snprintf(newpath, need, "%s@%x", curdev, devno);
873c287c391b0bbc4719b68bb84946515811e1batrawick (void) snprintf(newpath, need, "%s@%x,%x", curdev, devno, fnno);
873c287c391b0bbc4719b68bb84946515811e1batrawickslot_info_from_props(di_node_t n, di_prom_handle_t ph,
62ba6bde073be4d332ffc9c89768757d3f646da5dirkx if (slotsz != sizeof (int))
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (slotsz != sizeof (int))
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (hwprop2uint(n, SAVED_PCIEX_CAP_REG, &excap) != 0 ||
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton hwprop2uint(n, SAVED_PCIEX_SLOTCAP_REG, &slotcap) != 0)
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton *physlot = slotcap >> PCIE_SLOTCAP_PHY_SLOT_NUM_SHIFT;
860d483ae528603f7e1f962903e71ac28358bef6wroweset_slot_info(tnode_t *tn, di_node_t n, di_prom_handle_t ph)
860d483ae528603f7e1f962903e71ac28358bef6wrowe const char *slotnumstr;
860d483ae528603f7e1f962903e71ac28358bef6wrowe * An absolute physical slot number defined in the .topo overrides
860d483ae528603f7e1f962903e71ac28358bef6wrowe * anything we might find in devinfo properties.
860d483ae528603f7e1f962903e71ac28358bef6wrowe if ((slotnumstr = topo_get_prop(tn, ".PHYSLOTNUM")) != NULL) {
860d483ae528603f7e1f962903e71ac28358bef6wrowe * Check for failure to interpret the property
860d483ae528603f7e1f962903e71ac28358bef6wrowe * as a valid slot number, or for a bogus slot
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (slotnumstr == left || physlot < 0 || physlot > 0x1fff)
860d483ae528603f7e1f962903e71ac28358bef6wrowe * No .topo override, so look for "slot-names" or
860d483ae528603f7e1f962903e71ac28358bef6wrowe * "physical-slot#" properties.
860d483ae528603f7e1f962903e71ac28358bef6wrowe slot_info_from_props(n, ph, &physlot, &slotmap, &slotbuf) < 0)
860d483ae528603f7e1f962903e71ac28358bef6wrowe * physical-slot# of zero indicates everything is on-board, ...
860d483ae528603f7e1f962903e71ac28358bef6wrowe * ... else it's the pciexpress indicator for what slot the child is
860d483ae528603f7e1f962903e71ac28358bef6wrowe * in and so we'll set a property for later use in describing the
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankg * If no .PHYSLOTNUM property is set, we should set one
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * so folks coming along later can use that number to find
e8f95a682820a599fe41b22977010636be5c2717jim * the .PHYSLOTNAME<.PHYSLOTNUM> property.
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * A .PHYSLOTNAME defined in the .topo overrides any
e8f95a682820a599fe41b22977010636be5c2717jim * value we would set. The name is allowed to be on
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * any of our ancestors, so we copy it here first.
860d483ae528603f7e1f962903e71ac28358bef6wrowe (void) snprintf(tmpbuf, 20, ".PHYSLOTNAME%d", physlot);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * No .PHYSLOTNAME<slot-#> is set, so we
860d483ae528603f7e1f962903e71ac28358bef6wrowe * create one, making it the somewhat boring
cf9ada3713548ca11de76ff801839b79c879d380jorton * "hc:///component=SLOT <slot-#>".
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * Let a slot name defined in the .topo override
860d483ae528603f7e1f962903e71ac28358bef6wrowe * the value from the slot-names property. This
860d483ae528603f7e1f962903e71ac28358bef6wrowe * allows us to fix up mistakes in the OBP (can
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * you say chalupa) or elsewise fudge the label
860d483ae528603f7e1f962903e71ac28358bef6wrowe * creatively from the .topo file.
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * Use any attachment point info to indirectly set PLATASRU
860d483ae528603f7e1f962903e71ac28358bef6wrowe * and PLATFRU properties on children of the bus node. We set
860d483ae528603f7e1f962903e71ac28358bef6wrowe * .ASRU# and .FRU# values to be inherited by the appropriate
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * children. We allow these to be overridden in the .topo file
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * by not setting a property value here if one already exists.
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton MAXPATHLEN, ".%s%d", PLATASRU, dim->dev_minor % 256);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton MAXPATHLEN, "hc:///component=%s", di_minor_name(dim));
e8f95a682820a599fe41b22977010636be5c2717jim "hc:///component=%s:%s",
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sfstatic void
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) di_walk_minor(n, "ddi_ctl:attachment_point:pci", 0,
e23b77006a8b079c0ad52e42ba2029e759455b8fjortonstatic const char *
873c287c391b0bbc4719b68bb84946515811e1batrawickset_pci_properties(tnode_t *tn, di_node_t n, di_prom_handle_t ph)
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton uint_t vendor = 0x10000; /* out of legal range for a vendor-id */
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton uint_t device = 0x10000; /* out of legal range for a device-id */
19ce7effbcc8a735f1a883f9266e086fde2adb63poirier (void) snprintf(idstring, IDBUFLEN, "pci%x,%x", vendor, device);
cbe23d0a0ff097b3d544d714657452abc80e3c87fieldingget_class_code_and_reg(uint_t *cc, uint_t *reg, di_node_t n,
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return (-1);
b24a6ceb8011a209f3c6d4523f04d27120cbd97afielding return (-1);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return (0);
7a0780c774fcd7823d2e3a79f55b2f3522602992clarexpected_child(tnode_t *parent, const char *expect_type, int intent)
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * We prefer to instance a child node that's uninstanced, so
860d483ae528603f7e1f962903e71ac28358bef6wrowe * it inherits all the right properties.
62ba6bde073be4d332ffc9c89768757d3f646da5dirkx "Expected to set instance %d of a %s topo node. "
7a0780c774fcd7823d2e3a79f55b2f3522602992clarstatic void
b24a6ceb8011a209f3c6d4523f04d27120cbd97afieldingexamine_prom_props(tnode_t *pn, di_node_t n, di_prom_handle_t ph)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding const char *topof;
19ce7effbcc8a735f1a883f9266e086fde2adb63poirier const char *parentcap;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * Get the child's pci express capabilities (if any). We'll later
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx * convert this to a property on the appropriate topo node.
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx * If the child is a root complex, enumerate it as such rather
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx * than as just another dev/fn of the parent pcibus.
3a36c0105198c15925b69c40ff0fc8f83dc34af2rbb if (childcap > 0 && childetyp == PCIE_PCIECAP_DEV_TYPE_ROOT) {
20fb0ba160cf0ca91b3f0f0d552cbe60d92b0449fielding (pn = expected_child(ppn, PCIEX_ROOT, devno)) == NULL) {
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx "complex, but grand-parent topo node "
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx * Beneath a root complex we expect to find a switch,
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx * bridge or direct link. Whichever it is, it will be
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * enumerated as a pci-express bus/dev/fn trio.
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if ((cn = expected_child(pn, PCIEX_BUS, -1)) == NULL) {
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx "found pci-express root complex "
10a20aaa2426eff21e054473bbcab8cd2f104e59colm "child node to instance.\n");
e8f95a682820a599fe41b22977010636be5c2717jim * Sanity check here: The child of an upstream switch should
e5d11e25c54c1bd138a5fc1114ea44debdf67844jwoolley * be a downstream switch.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((parentcap = topo_get_prop(pn, EXCAPTPROP)) != NULL) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton "Devinfo child of UP switch is not a "
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton "down switch.\n");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * If the parent is an unenumerated bus, do it a favor and set
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * an instance number based on the bus defined for this
7a20709574a559549580a3b7cd199b9f9bf41018jailletc topo_out(TOPO_DEBUG, "Set parent's bus instance #%d,"
d3dbafe0347b788a86bbe18ee6111750af41cec9trawick (cn = expected_child(pn, PCI_DEVICE, devno)) == NULL)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_out(TOPO_DEBUG, "Topo node is neither " PCI_BUS
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding "the child node would be.\n");
d321fe00a917cfbe45929d741d74e2c89960b0b8trawick topo_out(TOPO_DEBUG, "Set device instance #%d.\n", devno);
01bea0a73866e80109c4d637610ce639ea1e89b1jailletc (cn = expected_child(pn, PCI_FUNCTION, fnno)) == NULL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (cn = expected_child(pn, PCIEX_FUNCTION, fnno)) == NULL)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_out(TOPO_DEBUG, "Set function instance #%d.\n", fnno);
d80638b1d2cf4b956aff22733d29f6eff05be2e7wrowe if ((topof = set_pci_properties(pn, n, ph)) != NULL) {
d80638b1d2cf4b956aff22733d29f6eff05be2e7wrowe * Look for topology information specific to this
23b4e2f556ce39696c4e31c6e72893f7489ff8d9dirkx * vendor-id & device-id, if any.
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * What sort of child is this? If there is no
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * PCI-express capability or if the capability is a
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * bridge to PCI, then children we will enumerate are
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * PCI buses.
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding "no PCI-express capabilities, or a "
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "bridge to PCI.\n");
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding "BUT the topo nodes lacks a "
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding "child node.\n");
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "and has PCI-express capability.\n");
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "but the topo nodes lacks a "
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding "child node.\n");
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * We don't know the instance number of this bus,
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * so we'll have to rely on it getting filled in
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * later by one of its children.
e8f95a682820a599fe41b22977010636be5c2717jiminstantiate_children(tnode_t *tn, di_node_t n, di_prom_handle_t ph)
cbe23d0a0ff097b3d544d714657452abc80e3c87fieldingdrivers_match(const char *drvr_type, const char *devprop)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG, "search for drivers of type %s.\n", drvr_type);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG, "%s within %s ? ", dnpath, devprop);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * Only do this for PCI_BUS nodes
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if ((cn = expected_child(node, PCI_DEVICE, 32)) == NULL)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding (cn1 = expected_child(cn, PCIEX_FUNCTION, 0)) == NULL)
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx * The topo node for the hostbridge should inherit the node's
79c880354e58e1d239306791f3d6c367a193c862trawick * DRIVER property. The hostbridge is driven by the same
52d46d469b9d75f316bd73cb05e15ae404d7f2c0brianp * software as the bus.
7a0780c774fcd7823d2e3a79f55b2f3522602992clarstatic void
7a0780c774fcd7823d2e3a79f55b2f3522602992clarinstantiate_all(tnode_t *node, const char *drvr_type, di_prom_handle_t ph)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar const char *devprop;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * Search for devinfo nodes for psycho, schizo, or generic
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * pci bus and find one that matches the DEV property path
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * passed to us.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Check to see if "node" is the descendant of a topo node that's not
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * enumerated, but whose instance number is unambiguous. If it is,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * we can enumerate that puppy because we now know that the ancestor
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * is for real.
509622419be000045d461ef38fb97df778fdf81djailletc * The enum_pci_bus() routine gets called by topo to set instance
509622419be000045d461ef38fb97df778fdf81djailletc * numbers for all the PCI bus nodes. The enumerator takes care of
509622419be000045d461ef38fb97df778fdf81djailletc * all devices, functions, bridges, and sub-buses beneath the bus
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * node as well.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * First thing, decide if we're looking for pci-express or
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * good old pci. Then orient ourselves within the devinfo
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * tree. The static topo info hopefully will have left us an
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * orienting clue by providing a DEV property.
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * Alternatively if there is no DEV, but there's a SCAN
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * property, we'll scan for pci buses.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "Bus tnode has no DEV or SCAN prop\n");
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (express == 0 &&
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * We've found ourselves in the devtree. A correctly written
e8f95a682820a599fe41b22977010636be5c2717jim * .topo file will have left the instance number unambiguous
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * (a range of exactly one number) and so we'll know and can
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * officially establish the instance number of the bus or root
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * complex. This creates a new topo node returned to us, with
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * children for which we must set instance numbers...
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "Unexpected bus instance min %d != max %d.\n",
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * We represent the hostbridge's PCI bus module as a "device"
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * on the bus outside of the range of normal devices.
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * Beneath a root complex we expect to find a switch,
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * bridge or direct link. Whichever it is, it will be
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * enumerated as a pci-express bus/dev/fn trio.
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if ((self = expected_child(self, PCIEX_BUS, -1)) == NULL) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "Found pci-express root complex "
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding " child node to instance.\n");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * find_devinfo_childdev()
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Search through pci/pci-express devinfo nodes that are a child of
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * the parent, looking for ones whose device # matches devno. The
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * function is recallable because a device can have multiple
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * functions.
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmfind_devinfo_childdev(di_node_t parent, di_node_t child, int devno, int *fnno)
30309f86bfd564437654aa822a19cd0cb29ca6f8wrowe if (get_class_code_and_reg(&cc, ®, cn, Promtree) < 0)
778f2416d2d9153ee72568a1aa7e11b7dc8946f4jorton * The enum_pci_dev() routine gets called by topo to explicitly set
778f2416d2d9153ee72568a1aa7e11b7dc8946f4jorton * instance numbers for specific PCI or PCI-Express device nodes.
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawick const char *dev;
daa3fa016bd51cdb39762a4510be99ba55c0b290aaron const char *topof;
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm * Our parent's parent node should have a DEV property. From
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm * this we should be able to orient ourselves in the devinfo
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm if ((ancdn = di_init(dev, DINFOCPYALL)) == DI_NODE_NIL) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding "PCI enumerator: "
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton "di_init failed for device ancestor failed.\n");
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * We've found ourselves in the devtree. A correctly written
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * .topo file will have left the instance number unambiguous
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * (a range of exactly one number) and so we'll know and can
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * officially establish the instance number of the device.
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * This creates a new topo node returned to us, with children
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * for which we must set instance numbers...
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton "Unexpected device instance min %d != max %d.\n",
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton selfdn = find_devinfo_childdev(ancdn, DI_NODE_NIL, min, &fno);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton topo_out(TOPO_DEBUG, "No device # %d found.\n", min);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG, "Set device instance #%d.\n", min);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (fn = expected_child(node, PCI_FUNCTION, fno)) == NULL) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "child node.\n");
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (fn = expected_child(node, PCIEX_FUNCTION, fno)) == NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "child node.\n");
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton topo_out(TOPO_DEBUG, "Set function instance #%d.\n", fno);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Look for topology information specific to this
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * vendor-id & device-id, if any.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding selfdn = find_devinfo_childdev(DI_NODE_NIL, selfdn, min, &fno);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * Any enumerations other than buses should have already
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * happened at the time the bus was enumerated, so we can just