pcibus.c revision 5114ab9e55159f74e60386eedf4934dfd140be47
842ae4bd224140319ae7feec1872b93dfd491143fielding/*
842ae4bd224140319ae7feec1872b93dfd491143fielding * CDDL HEADER START
842ae4bd224140319ae7feec1872b93dfd491143fielding *
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.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * or http://www.opensolaris.org/os/licensing.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * See the License for the specific language governing permissions
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * and limitations under the License.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
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 *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * CDDL HEADER END
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Use is subject to license terms.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#pragma ident "%Z%%M% %I% %E% SMI"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <fm/libtopo_enum.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <sys/fm/protocol.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <stdio.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <stdlib.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <string.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <strings.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <alloca.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <sys/param.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <sys/pci.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include <sys/pcie.h>
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "enumpci.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic struct tenumr pci_enumr = {
d0a46853bff16e9598a3298f262b0d3fd58d6c53martin NULL,
c53a68af52e2428d833746388b412fb4793759b2trawick topo_pci_init,
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx topo_pci_fini,
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx topo_pci_enum
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx};
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx
51469a0d2057aa24107b6f5a04e145824e10da1fdirkxstatic di_prom_handle_t Promtree = DI_PROM_HANDLE_NIL;
51469a0d2057aa24107b6f5a04e145824e10da1fdirkxstatic di_node_t Devtree = DI_NODE_NIL;
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx
51469a0d2057aa24107b6f5a04e145824e10da1fdirkxvoid instantiate_children(tnode_t *, di_node_t, di_prom_handle_t);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkxdi_node_t pciex_di_match(const char *);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkxdi_node_t pci_di_match(const char *);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx
51469a0d2057aa24107b6f5a04e145824e10da1fdirkxstruct tenumr *
383a9c6af58f5a670e8ef8b7f222ce71dbb7bee5dirkx_enum_init(void)
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx{
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx return (&pci_enumr);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx}
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx
bb036ec40eb03d669a5838214bf5ac211da0340baaronint
bb036ec40eb03d669a5838214bf5ac211da0340baarontopo_pci_init(void)
bb036ec40eb03d669a5838214bf5ac211da0340baaron{
1fbf6ba0f5207e6637b49f9a9dfcc779bbe952a9trawick/* Devtree = di_init("/", DINFOCACHE); */
bb036ec40eb03d669a5838214bf5ac211da0340baaron Devtree = di_init("/", DINFOCPYALL);
1fbf6ba0f5207e6637b49f9a9dfcc779bbe952a9trawick
bb036ec40eb03d669a5838214bf5ac211da0340baaron if (Devtree == DI_NODE_NIL) {
bb036ec40eb03d669a5838214bf5ac211da0340baaron topo_out(TOPO_ERR, "PCI enumerator: di_init failed.\n");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return (TE_INITFAIL);
78657729e2a01d274ab2894015cd384e175f17d7jwoolley }
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
af9be3a217c70b689b7275ed0690fc74483e7c4fdirkx Promtree = di_prom_init();
af9be3a217c70b689b7275ed0690fc74483e7c4fdirkx if (Promtree == DI_PROM_HANDLE_NIL) {
860d483ae528603f7e1f962903e71ac28358bef6wrowe di_fini(Devtree);
860d483ae528603f7e1f962903e71ac28358bef6wrowe topo_out(TOPO_ERR,
860d483ae528603f7e1f962903e71ac28358bef6wrowe "PCI enumerator: di_prom_handle_init failed.\n");
860d483ae528603f7e1f962903e71ac28358bef6wrowe return (TE_INITFAIL);
56b4c2f79f228da54b5815060ec3eb809dd9dcf9aaron }
56b4c2f79f228da54b5815060ec3eb809dd9dcf9aaron topo_out(TOPO_DEBUG, "PCI Enumr initd\n");
56b4c2f79f228da54b5815060ec3eb809dd9dcf9aaron return (TE_INITOK);
56b4c2f79f228da54b5815060ec3eb809dd9dcf9aaron}
56b4c2f79f228da54b5815060ec3eb809dd9dcf9aaron
10a20aaa2426eff21e054473bbcab8cd2f104e59colmvoid
10a20aaa2426eff21e054473bbcab8cd2f104e59colmtopo_pci_fini(void)
10a20aaa2426eff21e054473bbcab8cd2f104e59colm{
fb192621397afdd92da43370bf0d0cc8565e2264colm di_prom_fini(Promtree);
af9be3a217c70b689b7275ed0690fc74483e7c4fdirkx di_fini(Devtree);
860d483ae528603f7e1f962903e71ac28358bef6wrowe}
860d483ae528603f7e1f962903e71ac28358bef6wrowe
e8f95a682820a599fe41b22977010636be5c2717jim/*
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.
0332d54091b06276292793a2b67cedc34b921fd5jorton */
860d483ae528603f7e1f962903e71ac28358bef6wrowestatic int
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingpromprop2uint(di_node_t n, di_prom_handle_t ph, const char *propnm,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding uint_t *val)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding di_prom_prop_t pp = DI_PROM_PROP_NIL;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding uchar_t *buf;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while ((pp = di_prom_prop_next(ph, n, pp)) != DI_PROM_PROP_NIL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcmp(di_prom_prop_name(pp), propnm) == 0) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (di_prom_prop_data(pp, &buf) < sizeof (uint_t))
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding continue;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding bcopy(buf, val, sizeof (uint_t));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return (0);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb return (-1);
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb}
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb/*
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.
33cc48e1677642f4027deb6421ab6d7f3787ee0ffielding */
cccd31fa4a72fe23cc3249c06db181b274a55a69gsteinstatic int
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbbhwprop2uint(di_node_t n, const char *propnm, uint_t *val)
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb{
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb di_prop_t hp = DI_PROP_NIL;
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb uchar_t *buf;
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein
314ad8e9005a0266a2e7f61a44834c58893293b4rbb while ((hp = di_prop_next(n, hp)) != DI_PROP_NIL) {
3d5ab266a622a2c6e1907819a6891a0a61f32632wrowe if (strcmp(di_prop_name(hp), propnm) == 0) {
54c358157ff30a1c4f4f8b27f3a687f254afa493wrowe if (di_prop_bytes(hp, &buf) < sizeof (uint_t))
f706ad4ddbeb3b9814f52e83006e505cbb2cf662rbb continue;
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein bcopy(buf, val, sizeof (uint_t));
480e6d6e3fbf8fc23af721f430a97afb0012be6ftrawick return (0);
480e6d6e3fbf8fc23af721f430a97afb0012be6ftrawick }
cccd31fa4a72fe23cc3249c06db181b274a55a69gstein }
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe return (-1);
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb}
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*
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.
bb65aeae7af1d33b64252bbc1b966942d757ac60wrowe */
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbbstatic void
2a1011ba69b24f3224bcb358d542017d5f389f78wrowecopy_ancestor_prop(tnode_t *node, const char *prop)
608d821d7b7d5b856cccef7e9a14582087acd20bjorton{
608d821d7b7d5b856cccef7e9a14582087acd20bjorton const char *value;
608d821d7b7d5b856cccef7e9a14582087acd20bjorton tnode_t *p = node;
2a1011ba69b24f3224bcb358d542017d5f389f78wrowe
2a1011ba69b24f3224bcb358d542017d5f389f78wrowe if (p == NULL || prop == NULL)
2a1011ba69b24f3224bcb358d542017d5f389f78wrowe return;
2a1011ba69b24f3224bcb358d542017d5f389f78wrowe
2a1011ba69b24f3224bcb358d542017d5f389f78wrowe while ((p = topo_parent(p)) != NULL)
4281cf6a722c99ae21394dc2000bd48efcebdb3akbrand if ((value = topo_get_prop(p, prop)) != NULL) {
2a1011ba69b24f3224bcb358d542017d5f389f78wrowe (void) topo_set_prop(node, prop, value);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx break;
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx }
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx}
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx/*
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.
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton */
e23b77006a8b079c0ad52e42ba2029e759455b8fjortonstatic void
e23b77006a8b079c0ad52e42ba2029e759455b8fjortoncopy_prop(const char *prop, tnode_t *node, tnode_t *from)
2a1011ba69b24f3224bcb358d542017d5f389f78wrowe{
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx const char *value;
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankg if (node == NULL || prop == NULL || from == NULL)
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankg return;
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankg
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankg if ((value = topo_get_prop(from, prop)) != NULL)
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankg (void) topo_set_prop(node, prop, value);
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankg}
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankg
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankgstatic void
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankgset_fru_info(tnode_t *node)
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankg{
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankg if (topo_get_prop(node, PLATFRU) == NULL)
f00cb80197f824c3ff00dd4fdff3b2c267a519d1kbrand copy_ancestor_prop(node, PLATFRU);
f00cb80197f824c3ff00dd4fdff3b2c267a519d1kbrand}
f00cb80197f824c3ff00dd4fdff3b2c267a519d1kbrand
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankgstatic void
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankgset_devtype_prop(tnode_t *node, di_node_t dinode, di_prom_handle_t ph)
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx{
bb65aeae7af1d33b64252bbc1b966942d757ac60wrowe di_prom_prop_t pp = DI_PROM_PROP_NIL;
cf721750997514b9cbed94bf3672ff6b3e2c2132trawick di_prop_t hp = DI_PROP_NIL;
48d7c43629323c8d5ee9f7bd0d194de0a376b391rbb uchar_t *typbuf;
eacd93a9763f18f9cfd5f61ad1526f7ef32dd8d1rpluem char *tmpbuf;
eacd93a9763f18f9cfd5f61ad1526f7ef32dd8d1rpluem int sz = -1;
eacd93a9763f18f9cfd5f61ad1526f7ef32dd8d1rpluem
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding tmpbuf = alloca(MAXPATHLEN);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while ((hp = di_prop_next(dinode, hp)) != DI_PROP_NIL) {
20fb0ba160cf0ca91b3f0f0d552cbe60d92b0449fielding if (strcmp(di_prop_name(hp), DEVTYPEPROP) == 0) {
20fb0ba160cf0ca91b3f0f0d552cbe60d92b0449fielding if ((sz = di_prop_bytes(hp, &typbuf)) < 0)
20fb0ba160cf0ca91b3f0f0d552cbe60d92b0449fielding continue;
20fb0ba160cf0ca91b3f0f0d552cbe60d92b0449fielding break;
20fb0ba160cf0ca91b3f0f0d552cbe60d92b0449fielding }
20fb0ba160cf0ca91b3f0f0d552cbe60d92b0449fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (sz < 0) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while ((pp = di_prom_prop_next(ph, dinode, pp)) !=
873c287c391b0bbc4719b68bb84946515811e1batrawick DI_PROM_PROP_NIL) {
873c287c391b0bbc4719b68bb84946515811e1batrawick if (strcmp(di_prom_prop_name(pp), DEVTYPEPROP) == 0) {
873c287c391b0bbc4719b68bb84946515811e1batrawick sz = di_prom_prop_data(pp, &typbuf);
873c287c391b0bbc4719b68bb84946515811e1batrawick if (sz < 0)
873c287c391b0bbc4719b68bb84946515811e1batrawick continue;
873c287c391b0bbc4719b68bb84946515811e1batrawick break;
873c287c391b0bbc4719b68bb84946515811e1batrawick }
42530a2f3c65ed623376b86644e1b0e02f1393c0trawick }
42530a2f3c65ed623376b86644e1b0e02f1393c0trawick }
873c287c391b0bbc4719b68bb84946515811e1batrawick
873c287c391b0bbc4719b68bb84946515811e1batrawick if (sz > 0 && sz < MAXPATHLEN - 1) {
873c287c391b0bbc4719b68bb84946515811e1batrawick bcopy(typbuf, tmpbuf, sz);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding tmpbuf[sz] = 0;
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx (void) topo_set_prop(node, DEVTYPE, tmpbuf);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
30309f86bfd564437654aa822a19cd0cb29ca6f8wrowe
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm/*
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 */
7a0780c774fcd7823d2e3a79f55b2f3522602992clar/*ARGSUSED*/
7a0780c774fcd7823d2e3a79f55b2f3522602992clarstatic int
7a0780c774fcd7823d2e3a79f55b2f3522602992clarget_excap(di_node_t dinode, di_prom_handle_t ph)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar{
7a0780c774fcd7823d2e3a79f55b2f3522602992clar int excap;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (hwprop2uint(dinode, SAVED_PCIEX_CAP_REG, (uint_t *)&excap) != 0)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return (-1);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return (excap);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar}
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clar/*
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx * Set an EXCAP prop for pci-express capabilities.
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb */
51469a0d2057aa24107b6f5a04e145824e10da1fdirkxstatic void
51469a0d2057aa24107b6f5a04e145824e10da1fdirkxset_excap_prop(tnode_t *node, int excap)
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (excap < 0)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding switch (excap & PCIE_PCIECAP_DEV_TYPE_MASK) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding case PCIE_PCIECAP_DEV_TYPE_ROOT:
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding (void) topo_set_prop(node, EXCAPTPROP, PCIEX_ROOT);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding break;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding case PCIE_PCIECAP_DEV_TYPE_UP:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (void) topo_set_prop(node, EXCAPTPROP, PCIEX_SWUP);
98a01f71dcbda3cde96eaae23fadf2d4a145bacdtakashi break;
98a01f71dcbda3cde96eaae23fadf2d4a145bacdtakashi case PCIE_PCIECAP_DEV_TYPE_DOWN:
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding (void) topo_set_prop(node, EXCAPTPROP, PCIEX_SWDWN);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding break;
e5d4e153edb152c76a3aa67904ae8cf30cb0fe5fmadhum case PCIE_PCIECAP_DEV_TYPE_PCI2PCIE:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (void) topo_set_prop(node, EXCAPTPROP, PCIEX_BUS);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding break;
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb case PCIE_PCIECAP_DEV_TYPE_PCIE2PCI:
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (void) topo_set_prop(node, EXCAPTPROP, PCI_BUS);
81bd9331da3bd0f53255d52b1475480ff3a4b395trawick break;
57f96c9788ac60144fbe2e16eb355b22cbc8965fylavic case PCIE_PCIECAP_DEV_TYPE_PCIE_DEV:
57f96c9788ac60144fbe2e16eb355b22cbc8965fylavic (void) topo_set_prop(node, EXCAPTPROP, PCIEX_DEVICE);
d321fe00a917cfbe45929d741d74e2c89960b0b8trawick break;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
7a0780c774fcd7823d2e3a79f55b2f3522602992clar}
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clar/*
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.
7a0780c774fcd7823d2e3a79f55b2f3522602992clar */
c2989417297fc5ad287068f41a7972349c44ca2etakashiconst char *
c2989417297fc5ad287068f41a7972349c44ca2etakashislotname_from_tprops(tnode_t *node)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar{
7a0780c774fcd7823d2e3a79f55b2f3522602992clar const char *str;
77c6374e145713c55bc3d6e648abe917b04921f3trawick char *tmpbuf;
c2989417297fc5ad287068f41a7972349c44ca2etakashi char *left;
c2989417297fc5ad287068f41a7972349c44ca2etakashi int physlot;
c2989417297fc5ad287068f41a7972349c44ca2etakashi
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if ((str = topo_get_prop(node, ".PHYSLOTNUM")) == NULL)
77c6374e145713c55bc3d6e648abe917b04921f3trawick return (NULL);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
c2989417297fc5ad287068f41a7972349c44ca2etakashi physlot = (int)strtol(str, &left, 0);
dc610ff4888acc61dc6c8de2b8974a4dce9c074fsf if (str == left || physlot < 0 || physlot > 0x1fff)
30309f86bfd564437654aa822a19cd0cb29ca6f8wrowe return (NULL);
c2989417297fc5ad287068f41a7972349c44ca2etakashi
c2989417297fc5ad287068f41a7972349c44ca2etakashi tmpbuf = alloca(20);
c2989417297fc5ad287068f41a7972349c44ca2etakashi (void) snprintf(tmpbuf, 20, ".PHYSLOTNAME%d", physlot);
c2989417297fc5ad287068f41a7972349c44ca2etakashi if ((str = topo_get_prop(node, tmpbuf)) != NULL)
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx return (str);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar copy_ancestor_prop(node, tmpbuf);
b8ee7946aa85a6b2eefd7f9fcf2ed5dc69a7103asctemme return (topo_get_prop(node, tmpbuf));
b8ee7946aa85a6b2eefd7f9fcf2ed5dc69a7103asctemme}
b8ee7946aa85a6b2eefd7f9fcf2ed5dc69a7103asctemme
b8ee7946aa85a6b2eefd7f9fcf2ed5dc69a7103asctemmestatic void
b8ee7946aa85a6b2eefd7f9fcf2ed5dc69a7103asctemmeset_std_properties(tnode_t *node, di_node_t dinode, di_prom_handle_t ph)
62ba6bde073be4d332ffc9c89768757d3f646da5dirkx{
62ba6bde073be4d332ffc9c89768757d3f646da5dirkx const char *labelval;
62ba6bde073be4d332ffc9c89768757d3f646da5dirkx const char *platval;
23b4e2f556ce39696c4e31c6e72893f7489ff8d9dirkx tnode_t *pop;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar char *tmpbuf;
0bcc11df5f030cf62289599a25f5831913a4b438trawick char *dnpath;
0bcc11df5f030cf62289599a25f5831913a4b438trawick char *dnm;
0bcc11df5f030cf62289599a25f5831913a4b438trawick int devno;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding /*
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * If it's a root complex, set the pciex capabilities property
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding */
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (strcmp(PCIEX_ROOT, topo_name(node)) == 0)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding (void) topo_set_prop(node, EXCAPTPROP, PCIEX_ROOT);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding /*
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * If it's a device node, we pretty much don't add any props
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding */
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (strcmp(PCI_DEVICE, topo_name(node)) == 0 ||
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding strcmp(PCIEX_DEVICE, topo_name(node)) == 0) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding set_fru_info(node);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx tmpbuf = alloca(MAXPATHLEN);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton /*
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * Create a DEVTYPE property as necessary
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton */
860d483ae528603f7e1f962903e71ac28358bef6wrowe set_devtype_prop(node, dinode, ph);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /*
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * Cheat for now and always say the thing is ON
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (void) topo_set_prop(node, ON, TPROP_TRUE);
87a528a7622973988232079ba02763748c9c7071pquerna
0906f649b3d720299e47ed1148e79051e8941b2adirkx if ((dnpath = di_devfs_path(dinode)) != NULL) {
446b877d2ab69d9bbcd9152a2d54814f05f1c00brbb (void) topo_set_prop(node, DEV, dnpath);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding di_devfs_path_free(dnpath);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((dnm = di_driver_name(dinode)) != NULL)
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx (void) topo_set_prop(node, DRIVER, dnm);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx /*
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.
dc610ff4888acc61dc6c8de2b8974a4dce9c074fsf */
30309f86bfd564437654aa822a19cd0cb29ca6f8wrowe if (strcmp(PCI_FUNCTION, topo_name(node)) != 0 &&
30309f86bfd564437654aa822a19cd0cb29ca6f8wrowe strcmp(PCIEX_FUNCTION, topo_name(node)) != 0)
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb return;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
bbe866808ba50d71809ab58bbee377cadf60d3b7dreid pop = topo_parent(topo_parent(node));
bbe866808ba50d71809ab58bbee377cadf60d3b7dreid devno = topo_get_instance_num(topo_parent(node));
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
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 ||
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (labelval = slotname_from_tprops(pop)) != NULL) {
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick (void) topo_set_prop(node, LABEL, labelval);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding } else {
c2989417297fc5ad287068f41a7972349c44ca2etakashi copy_ancestor_prop(node, LABEL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
dcde46ca353d5d66bbac2b8e1135ac828992b808dreid }
dcde46ca353d5d66bbac2b8e1135ac828992b808dreid
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (topo_get_prop(node, PLATASRU) == NULL) {
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick (void) snprintf(tmpbuf, MAXPATHLEN, ".%s%d", PLATASRU, devno);
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick if ((platval = topo_get_prop(pop, tmpbuf)) != NULL)
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick (void) topo_set_prop(node, PLATASRU, platval);
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick }
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick
c2989417297fc5ad287068f41a7972349c44ca2etakashi /*
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick * Pecking order for determining the value of PLAT-FRU:
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick *
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,
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * done.
dcde46ca353d5d66bbac2b8e1135ac828992b808dreid * Copy value from an ancestor.
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding */
be2ca76a08c2fc1695f5b3178d5893f0e92240bftrawick if (topo_get_prop(node, PLATFRU) == NULL) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (void) snprintf(tmpbuf, MAXPATHLEN, ".%s%d", PLATFRU, devno);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((platval = topo_get_prop(pop, tmpbuf)) != NULL) {
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf (void) topo_set_prop(node, PLATFRU, platval);
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf } else {
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf if (labelval != NULL)
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf (void) topo_set_prop(node, PLATFRU, labelval);
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf else
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf copy_ancestor_prop(node, PLATFRU);
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf }
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf }
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf}
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf/*
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.
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf */
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sfstatic void
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sffix_dev_prop(tnode_t *node, int devno, int fnno)
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf{
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf const char *curdev;
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf char *lastslash;
10d599dd767725a492703af2e3156d414b8a78d4trawick char *newpath;
10d599dd767725a492703af2e3156d414b8a78d4trawick int need;
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf /* Check if there is a DEV prop to fix. */
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf if ((curdev = topo_get_prop(node, DEV)) == NULL)
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf return;
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf /*
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.
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf */
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf if ((lastslash = strrchr(curdev, '/')) == NULL)
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf return;
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sf /*
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 */
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawick if (strchr(lastslash, '@') != NULL)
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawick return;
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawick
873c287c391b0bbc4719b68bb84946515811e1batrawick if (fnno == 0)
873c287c391b0bbc4719b68bb84946515811e1batrawick need = snprintf(NULL, 0, "%s@%x", curdev, devno);
873c287c391b0bbc4719b68bb84946515811e1batrawick else
873c287c391b0bbc4719b68bb84946515811e1batrawick need = snprintf(NULL, 0, "%s@%x,%x", curdev, devno, fnno);
873c287c391b0bbc4719b68bb84946515811e1batrawick need++;
873c287c391b0bbc4719b68bb84946515811e1batrawick
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawick newpath = alloca(need);
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawick
873c287c391b0bbc4719b68bb84946515811e1batrawick if (fnno == 0)
873c287c391b0bbc4719b68bb84946515811e1batrawick (void) snprintf(newpath, need, "%s@%x", curdev, devno);
873c287c391b0bbc4719b68bb84946515811e1batrawick else
873c287c391b0bbc4719b68bb84946515811e1batrawick (void) snprintf(newpath, need, "%s@%x,%x", curdev, devno, fnno);
873c287c391b0bbc4719b68bb84946515811e1batrawick (void) topo_set_prop(node, DEV, newpath);
873c287c391b0bbc4719b68bb84946515811e1batrawick}
873c287c391b0bbc4719b68bb84946515811e1batrawick
873c287c391b0bbc4719b68bb84946515811e1batrawickstatic int
873c287c391b0bbc4719b68bb84946515811e1batrawickslot_info_from_props(di_node_t n, di_prom_handle_t ph,
873c287c391b0bbc4719b68bb84946515811e1batrawick int *physlot, uint_t *slotmap, uchar_t **slotbuf)
873c287c391b0bbc4719b68bb84946515811e1batrawick{
873c287c391b0bbc4719b68bb84946515811e1batrawick di_prom_prop_t pp = DI_PROM_PROP_NIL;
873c287c391b0bbc4719b68bb84946515811e1batrawick di_prop_t hp = DI_PROP_NIL;
873c287c391b0bbc4719b68bb84946515811e1batrawick uint_t slotcap = 0;
873c287c391b0bbc4719b68bb84946515811e1batrawick uint_t excap = 0;
873c287c391b0bbc4719b68bb84946515811e1batrawick char *prnm;
873c287c391b0bbc4719b68bb84946515811e1batrawick int slotsz = -1;
873c287c391b0bbc4719b68bb84946515811e1batrawick
873c287c391b0bbc4719b68bb84946515811e1batrawick while ((hp = di_prop_next(n, hp)) != DI_PROP_NIL) {
873c287c391b0bbc4719b68bb84946515811e1batrawick prnm = di_prop_name(hp);
873c287c391b0bbc4719b68bb84946515811e1batrawick if (strcmp(prnm, SLOTPROP) == 0) {
873c287c391b0bbc4719b68bb84946515811e1batrawick slotsz = di_prop_bytes(hp, slotbuf);
873c287c391b0bbc4719b68bb84946515811e1batrawick if (slotsz < sizeof (uint_t))
873c287c391b0bbc4719b68bb84946515811e1batrawick continue;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding bcopy(*slotbuf, slotmap, sizeof (uint_t));
62ba6bde073be4d332ffc9c89768757d3f646da5dirkx break;
62ba6bde073be4d332ffc9c89768757d3f646da5dirkx } else if (strcmp(prnm, PHYSPROP) == 0) {
62ba6bde073be4d332ffc9c89768757d3f646da5dirkx slotsz = di_prop_bytes(hp, slotbuf);
62ba6bde073be4d332ffc9c89768757d3f646da5dirkx if (slotsz != sizeof (int))
860d483ae528603f7e1f962903e71ac28358bef6wrowe continue;
4729a2e31b3afeaf2423fc8334f18628efb8fab7jorton bcopy(*slotbuf, physlot, sizeof (int));
860d483ae528603f7e1f962903e71ac28358bef6wrowe break;
860d483ae528603f7e1f962903e71ac28358bef6wrowe }
860d483ae528603f7e1f962903e71ac28358bef6wrowe }
860d483ae528603f7e1f962903e71ac28358bef6wrowe
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (slotsz < 0) {
860d483ae528603f7e1f962903e71ac28358bef6wrowe while ((pp = di_prom_prop_next(ph, n, pp)) !=
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton DI_PROM_PROP_NIL) {
cf9ada3713548ca11de76ff801839b79c879d380jorton prnm = di_prom_prop_name(pp);
cf9ada3713548ca11de76ff801839b79c879d380jorton if (strcmp(prnm, SLOTPROP) == 0) {
c7760b87a01538ca7cc6a9a7aa3d9d910cfc3fe9wrowe slotsz = di_prom_prop_data(pp, slotbuf);
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (slotsz < sizeof (uint_t))
860d483ae528603f7e1f962903e71ac28358bef6wrowe continue;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton bcopy(*slotbuf, slotmap, sizeof (uint_t));
cf9ada3713548ca11de76ff801839b79c879d380jorton break;
cf9ada3713548ca11de76ff801839b79c879d380jorton } else if (strcmp(prnm, PHYSPROP) == 0) {
c7760b87a01538ca7cc6a9a7aa3d9d910cfc3fe9wrowe slotsz = di_prom_prop_data(pp, slotbuf);
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (slotsz != sizeof (int))
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton continue;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton bcopy(*slotbuf, physlot, sizeof (int));
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton break;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (slotsz < 0) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (hwprop2uint(n, SAVED_PCIEX_CAP_REG, &excap) != 0 ||
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (excap & PCIE_PCIECAP_SLOT_IMPL) == 0 ||
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton hwprop2uint(n, SAVED_PCIEX_SLOTCAP_REG, &slotcap) != 0)
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton return (slotsz);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton *physlot = slotcap >> PCIE_SLOTCAP_PHY_SLOT_NUM_SHIFT;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton slotsz = 0;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton return (slotsz);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton}
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
860d483ae528603f7e1f962903e71ac28358bef6wrowestatic void
860d483ae528603f7e1f962903e71ac28358bef6wroweset_slot_info(tnode_t *tn, di_node_t n, di_prom_handle_t ph)
860d483ae528603f7e1f962903e71ac28358bef6wrowe{
860d483ae528603f7e1f962903e71ac28358bef6wrowe const char *slotnumstr;
860d483ae528603f7e1f962903e71ac28358bef6wrowe uchar_t *slotbuf;
860d483ae528603f7e1f962903e71ac28358bef6wrowe uint_t slotmap = 0;
860d483ae528603f7e1f962903e71ac28358bef6wrowe char *slotname;
860d483ae528603f7e1f962903e71ac28358bef6wrowe char *tmphcbuf;
860d483ae528603f7e1f962903e71ac28358bef6wrowe char *fmribuf;
860d483ae528603f7e1f962903e71ac28358bef6wrowe char *tmpbuf;
860d483ae528603f7e1f962903e71ac28358bef6wrowe char *left;
860d483ae528603f7e1f962903e71ac28358bef6wrowe int physlot = -1;
860d483ae528603f7e1f962903e71ac28358bef6wrowe int andbit;
860d483ae528603f7e1f962903e71ac28358bef6wrowe
860d483ae528603f7e1f962903e71ac28358bef6wrowe /*
860d483ae528603f7e1f962903e71ac28358bef6wrowe * An absolute physical slot number defined in the .topo overrides
860d483ae528603f7e1f962903e71ac28358bef6wrowe * anything we might find in devinfo properties.
860d483ae528603f7e1f962903e71ac28358bef6wrowe */
860d483ae528603f7e1f962903e71ac28358bef6wrowe if ((slotnumstr = topo_get_prop(tn, ".PHYSLOTNUM")) != NULL) {
860d483ae528603f7e1f962903e71ac28358bef6wrowe physlot = (int)strtol(slotnumstr, &left, 0);
4729a2e31b3afeaf2423fc8334f18628efb8fab7jorton /*
860d483ae528603f7e1f962903e71ac28358bef6wrowe * Check for failure to interpret the property
860d483ae528603f7e1f962903e71ac28358bef6wrowe * as a valid slot number, or for a bogus slot
860d483ae528603f7e1f962903e71ac28358bef6wrowe * number.
860d483ae528603f7e1f962903e71ac28358bef6wrowe */
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (slotnumstr == left || physlot < 0 || physlot > 0x1fff)
860d483ae528603f7e1f962903e71ac28358bef6wrowe physlot = -1;
860d483ae528603f7e1f962903e71ac28358bef6wrowe }
860d483ae528603f7e1f962903e71ac28358bef6wrowe
860d483ae528603f7e1f962903e71ac28358bef6wrowe /*
860d483ae528603f7e1f962903e71ac28358bef6wrowe * No .topo override, so look for "slot-names" or
860d483ae528603f7e1f962903e71ac28358bef6wrowe * "physical-slot#" properties.
860d483ae528603f7e1f962903e71ac28358bef6wrowe */
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (physlot < 0 &&
860d483ae528603f7e1f962903e71ac28358bef6wrowe slot_info_from_props(n, ph, &physlot, &slotmap, &slotbuf) < 0)
860d483ae528603f7e1f962903e71ac28358bef6wrowe return;
860d483ae528603f7e1f962903e71ac28358bef6wrowe
860d483ae528603f7e1f962903e71ac28358bef6wrowe /*
860d483ae528603f7e1f962903e71ac28358bef6wrowe * physical-slot# of zero indicates everything is on-board, ...
860d483ae528603f7e1f962903e71ac28358bef6wrowe */
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (physlot == 0)
860d483ae528603f7e1f962903e71ac28358bef6wrowe return;
860d483ae528603f7e1f962903e71ac28358bef6wrowe
860d483ae528603f7e1f962903e71ac28358bef6wrowe /*
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
860d483ae528603f7e1f962903e71ac28358bef6wrowe * FRU.
860d483ae528603f7e1f962903e71ac28358bef6wrowe */
4729a2e31b3afeaf2423fc8334f18628efb8fab7jorton if (physlot > 0 && physlot <= 0x1fff) {
860d483ae528603f7e1f962903e71ac28358bef6wrowe /*
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.
f00cb80197f824c3ff00dd4fdff3b2c267a519d1kbrand */
f00cb80197f824c3ff00dd4fdff3b2c267a519d1kbrand tmpbuf = alloca(20);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (topo_get_prop(tn, ".PHYSLOTNUM") == NULL) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (void) snprintf(tmpbuf, 20, "%d", physlot);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (void) topo_set_prop(tn, ".PHYSLOTNUM", tmpbuf);
e8f95a682820a599fe41b22977010636be5c2717jim }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton /*
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 */
860d483ae528603f7e1f962903e71ac28358bef6wrowe (void) snprintf(tmpbuf, 20, ".PHYSLOTNAME%d", physlot);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (topo_get_prop(tn, tmpbuf) == NULL)
860d483ae528603f7e1f962903e71ac28358bef6wrowe copy_ancestor_prop(tn, tmpbuf);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (topo_get_prop(tn, tmpbuf) == NULL) {
23bc6974af15e69a9aa4b5b3fc06b800b53ca234sf /*
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * No .PHYSLOTNAME<slot-#> is set, so we
860d483ae528603f7e1f962903e71ac28358bef6wrowe * create one, making it the somewhat boring
cf9ada3713548ca11de76ff801839b79c879d380jorton * "hc:///component=SLOT <slot-#>".
7a0780c774fcd7823d2e3a79f55b2f3522602992clar */
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton fmribuf = alloca(32);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (void) snprintf(fmribuf, 32,
860d483ae528603f7e1f962903e71ac28358bef6wrowe "hc:///component=SLOT %d", physlot);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (void) topo_set_prop(tn, tmpbuf, fmribuf);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return;
860d483ae528603f7e1f962903e71ac28358bef6wrowe }
23bc6974af15e69a9aa4b5b3fc06b800b53ca234sf
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (slotmap == 0)
23bc6974af15e69a9aa4b5b3fc06b800b53ca234sf return;
23bc6974af15e69a9aa4b5b3fc06b800b53ca234sf
860d483ae528603f7e1f962903e71ac28358bef6wrowe tmpbuf = alloca(10);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton tmphcbuf = alloca(MAXPATHLEN);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
7a0780c774fcd7823d2e3a79f55b2f3522602992clar slotname = (char *)&slotbuf[4];
860d483ae528603f7e1f962903e71ac28358bef6wrowe for (andbit = 0; andbit < 32; andbit++) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (slotmap & (1<<andbit)) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton char *s = slotname;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (void) snprintf(tmpbuf, 10, ".SLOTNM%d", andbit);
860d483ae528603f7e1f962903e71ac28358bef6wrowe slotname += strlen(s) + 1;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar /*
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 */
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (topo_get_prop(tn, tmpbuf) == NULL) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) snprintf(tmphcbuf,
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton MAXPATHLEN, "hc:///component=%s", s);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) topo_set_prop(tn, tmpbuf, tmphcbuf);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton}
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
e23b77006a8b079c0ad52e42ba2029e759455b8fjortonstatic int
860d483ae528603f7e1f962903e71ac28358bef6wroweminorwalkcb(di_node_t din, di_minor_t dim, void *arg)
860d483ae528603f7e1f962903e71ac28358bef6wrowe{
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton tnode_t *tn = (tnode_t *)arg;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton char *pnm;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton char *devname;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton char *apath;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton apath = alloca(MAXPATHLEN);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton pnm = alloca(MAXPATHLEN);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton /*
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 */
860d483ae528603f7e1f962903e71ac28358bef6wrowe if ((devname = di_devfs_path(din)) == NULL)
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton return (DI_WALK_CONTINUE);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
860d483ae528603f7e1f962903e71ac28358bef6wrowe (void) snprintf(pnm,
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton MAXPATHLEN, ".%s%d", PLATASRU, dim->dev_minor % 256);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (topo_get_prop(tn, pnm) == NULL) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) snprintf(apath,
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton MAXPATHLEN, "hc:///component=%s", di_minor_name(dim));
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) topo_set_prop(tn, pnm, apath);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) snprintf(pnm,
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton MAXPATHLEN, ".%s%d", PLATFRU, dim->dev_minor % 256);
ee6367f61ca2ece7c95a923780bbb3dc312bb812fuankg if (topo_get_prop(tn, pnm) == NULL) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) snprintf(apath,
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton MAXPATHLEN,
e8f95a682820a599fe41b22977010636be5c2717jim "hc:///component=%s:%s",
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton devname,
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton di_minor_name(dim));
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) topo_set_prop(tn, pnm, apath);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton di_devfs_path_free(devname);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton return (DI_WALK_CONTINUE);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton}
e8f95a682820a599fe41b22977010636be5c2717jim
a2e8dd6454c7cbf9f4534b73c9b0a0775f734160sfstatic void
e23b77006a8b079c0ad52e42ba2029e759455b8fjortonset_attachpt_info(tnode_t *tn, di_node_t n)
f00cb80197f824c3ff00dd4fdff3b2c267a519d1kbrand{
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) di_walk_minor(n, "ddi_ctl:attachment_point:pci", 0,
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void *)tn, minorwalkcb);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton}
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton#define IDBUFLEN 13
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
e23b77006a8b079c0ad52e42ba2029e759455b8fjortonstatic const char *
873c287c391b0bbc4719b68bb84946515811e1batrawickset_pci_properties(tnode_t *tn, di_node_t n, di_prom_handle_t ph)
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton{
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton static char idstring[IDBUFLEN]; /* pciVVVV,DDDD */
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 */
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton char *tmpbuf;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton tmpbuf = alloca(MAXPATHLEN);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) hwprop2uint(n, DEVIDPROP, &device);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (device == 0x10000)
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) promprop2uint(n, ph, DEVIDPROP, &device);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (device != 0x10000) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) snprintf(tmpbuf, MAXPATHLEN, "%x", device);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) topo_set_prop(tn, DEVIDTPROP, tmpbuf);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
860d483ae528603f7e1f962903e71ac28358bef6wrowe
860d483ae528603f7e1f962903e71ac28358bef6wrowe (void) hwprop2uint(n, VENDIDPROP, &vendor);
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (vendor == 0x10000)
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton (void) promprop2uint(n, ph, VENDIDPROP, &vendor);
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (vendor != 0x10000) {
860d483ae528603f7e1f962903e71ac28358bef6wrowe (void) snprintf(tmpbuf, MAXPATHLEN, "%x", vendor);
23b4e2f556ce39696c4e31c6e72893f7489ff8d9dirkx (void) topo_set_prop(tn, VENDIDTPROP, tmpbuf);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
19ce7effbcc8a735f1a883f9266e086fde2adb63poirier
19ce7effbcc8a735f1a883f9266e086fde2adb63poirier if (device != 0x10000 && vendor != 0x10000) {
19ce7effbcc8a735f1a883f9266e086fde2adb63poirier (void) snprintf(idstring, IDBUFLEN, "pci%x,%x", vendor, device);
19ce7effbcc8a735f1a883f9266e086fde2adb63poirier return (idstring);
0906f649b3d720299e47ed1148e79051e8941b2adirkx }
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return (NULL);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar}
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
e8f95a682820a599fe41b22977010636be5c2717jimstatic int
cbe23d0a0ff097b3d544d714657452abc80e3c87fieldingget_class_code_and_reg(uint_t *cc, uint_t *reg, di_node_t n,
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding di_prom_handle_t ph)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar{
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (hwprop2uint(n, REGPROP, reg) < 0 &&
7a0780c774fcd7823d2e3a79f55b2f3522602992clar promprop2uint(n, ph, REGPROP, reg) < 0)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return (-1);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (hwprop2uint(n, CLASSPROP, cc) < 0 &&
7a0780c774fcd7823d2e3a79f55b2f3522602992clar promprop2uint(n, ph, CLASSPROP, cc) < 0)
b24a6ceb8011a209f3c6d4523f04d27120cbd97afielding return (-1);
d321fe00a917cfbe45929d741d74e2c89960b0b8trawick
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return (0);
13055ee369dd9ae4d627af35cbc0d462a11bc8a9jorton}
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clarstatic tnode_t *
7a0780c774fcd7823d2e3a79f55b2f3522602992clarexpected_child(tnode_t *parent, const char *expect_type, int intent)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar{
7a0780c774fcd7823d2e3a79f55b2f3522602992clar tnode_t *cn = NULL;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar int min, max;
e8f95a682820a599fe41b22977010636be5c2717jim
860d483ae528603f7e1f962903e71ac28358bef6wrowe /*
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton * We prefer to instance a child node that's uninstanced, so
860d483ae528603f7e1f962903e71ac28358bef6wrowe * it inherits all the right properties.
860d483ae528603f7e1f962903e71ac28358bef6wrowe */
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton while ((cn = topo_next_child(parent, cn)) != NULL) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (strcmp(topo_name(cn), expect_type) != 0)
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton continue;
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (topo_get_instance_num(cn) < 0) {
860d483ae528603f7e1f962903e71ac28358bef6wrowe topo_get_instance_range(cn, &min, &max);
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (intent < 0 || (intent >= min && intent <= max))
860d483ae528603f7e1f962903e71ac28358bef6wrowe break;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
860d483ae528603f7e1f962903e71ac28358bef6wrowe }
860d483ae528603f7e1f962903e71ac28358bef6wrowe
860d483ae528603f7e1f962903e71ac28358bef6wrowe if (cn == NULL) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG,
62ba6bde073be4d332ffc9c89768757d3f646da5dirkx "Expected to set instance %d of a %s topo node. "
b24a6ceb8011a209f3c6d4523f04d27120cbd97afielding "But found no match.", intent, expect_type);
b24a6ceb8011a209f3c6d4523f04d27120cbd97afielding }
b24a6ceb8011a209f3c6d4523f04d27120cbd97afielding return (cn);
b24a6ceb8011a209f3c6d4523f04d27120cbd97afielding}
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clarstatic void
b24a6ceb8011a209f3c6d4523f04d27120cbd97afieldingexamine_prom_props(tnode_t *pn, di_node_t n, di_prom_handle_t ph)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar{
7a0780c774fcd7823d2e3a79f55b2f3522602992clar tnode_t *ppn;
b24a6ceb8011a209f3c6d4523f04d27120cbd97afielding tnode_t *cn = NULL;
0906f649b3d720299e47ed1148e79051e8941b2adirkx uint_t reg, cc;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding const char *topof;
19ce7effbcc8a735f1a883f9266e086fde2adb63poirier const char *parentcap;
873c287c391b0bbc4719b68bb84946515811e1batrawick uint_t childclass, childsubclass;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int childcap, childetyp;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int busno, devno, fnno;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (get_class_code_and_reg(&cc, &reg, n, ph) < 0)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
3a36c0105198c15925b69c40ff0fc8f83dc34af2rbb busno = PCI_REG_BUS_G(reg);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx devno = PCI_REG_DEV_G(reg);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx fnno = PCI_REG_FUNC_G(reg);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx /*
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 */
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx childcap = get_excap(n, ph);
3a36c0105198c15925b69c40ff0fc8f83dc34af2rbb if (childcap > 0)
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx childetyp = childcap & PCIE_PCIECAP_DEV_TYPE_MASK;
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx childclass = GETCLASS(cc);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar childsubclass = GETSUBCLASS(cc);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx
7a0780c774fcd7823d2e3a79f55b2f3522602992clar /*
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx * If the child is a root complex, enumerate it as such rather
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx * than as just another dev/fn of the parent pcibus.
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx */
3a36c0105198c15925b69c40ff0fc8f83dc34af2rbb if (childcap > 0 && childetyp == PCIE_PCIECAP_DEV_TYPE_ROOT) {
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx if ((ppn = topo_parent(pn)) == NULL ||
20fb0ba160cf0ca91b3f0f0d552cbe60d92b0449fielding (pn = expected_child(ppn, PCIEX_ROOT, devno)) == NULL) {
20fb0ba160cf0ca91b3f0f0d552cbe60d92b0449fielding topo_out(TOPO_DEBUG, "found pci-express root"
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx "complex, but grand-parent topo node "
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "lacks a " PCIEX_ROOT " child node.\n");
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx return;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx pn = topo_set_instance_num(pn, devno);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx set_excap_prop(pn, childcap);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx set_slot_info(pn, n, ph);
3a36c0105198c15925b69c40ff0fc8f83dc34af2rbb /*
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.
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx */
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if ((cn = expected_child(pn, PCIEX_BUS, -1)) == NULL) {
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx topo_out(TOPO_DEBUG,
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx "found pci-express root complex "
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx "that lacks a " PCIEX_BUS
10a20aaa2426eff21e054473bbcab8cd2f104e59colm "child node to instance.\n");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding instantiate_children(cn, n, ph);
e7984a3685a36d71c6fb55c59484a2967bcca8fccolm return;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
e7984a3685a36d71c6fb55c59484a2967bcca8fccolm
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding /*
e8f95a682820a599fe41b22977010636be5c2717jim * Sanity check here: The child of an upstream switch should
e5d11e25c54c1bd138a5fc1114ea44debdf67844jwoolley * be a downstream switch.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if ((parentcap = topo_get_prop(pn, EXCAPTPROP)) != NULL) {
ee044568b891a057768282bccd2498832108d32dsctemme if (strcmp(parentcap, PCIEX_SWUP) == 0) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (childclass != PCI_CLASS_BRIDGE ||
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton childetyp != PCIE_PCIECAP_DEV_TYPE_DOWN) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton topo_out(TOPO_DEBUG,
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton "Devinfo child of UP switch is not a "
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton "down switch.\n");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
509622419be000045d461ef38fb97df778fdf81djailletc }
509622419be000045d461ef38fb97df778fdf81djailletc }
509622419be000045d461ef38fb97df778fdf81djailletc
509622419be000045d461ef38fb97df778fdf81djailletc /*
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
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * device.
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding */
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if ((strcmp(PCI_BUS, topo_name(pn)) == 0 ||
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding strcmp(PCIEX_BUS, topo_name(pn)) == 0) &&
81bd9331da3bd0f53255d52b1475480ff3a4b395trawick topo_get_instance_num(pn) < 0) {
81bd9331da3bd0f53255d52b1475480ff3a4b395trawick pn = topo_set_instance_num(pn, busno);
7a20709574a559549580a3b7cd199b9f9bf41018jailletc topo_out(TOPO_DEBUG, "Set parent's bus instance #%d,"
7a20709574a559549580a3b7cd199b9f9bf41018jailletc " np=%p.\n", busno, (void *)pn);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding set_slot_info(pn, di_parent_node(n), ph);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar set_attachpt_info(pn, di_parent_node(n));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding set_fru_info(pn);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
d321fe00a917cfbe45929d741d74e2c89960b0b8trawick if (strcmp(PCI_BUS, topo_name(pn)) == 0 &&
d3dbafe0347b788a86bbe18ee6111750af41cec9trawick (cn = expected_child(pn, PCI_DEVICE, devno)) == NULL)
9667009c60cf53ad7f1bfe9b73efecf403956d9dtrawick return;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (strcmp(PCIEX_BUS, topo_name(pn)) == 0 &&
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (cn = expected_child(pn, PCIEX_DEVICE, devno)) ==
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding NULL)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return;
e8f95a682820a599fe41b22977010636be5c2717jim if (cn == NULL) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_out(TOPO_DEBUG, "Topo node is neither " PCI_BUS
e8f95a682820a599fe41b22977010636be5c2717jim " nor " PCIEX_BUS " so, we don't know what the heck "
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding "the child node would be.\n");
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding pn = topo_set_instance_num(cn, devno);
d321fe00a917cfbe45929d741d74e2c89960b0b8trawick topo_out(TOPO_DEBUG, "Set device instance #%d.\n", devno);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar set_std_properties(pn, n, ph);
01bea0a73866e80109c4d637610ce639ea1e89b1jailletc
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (strcmp(PCI_DEVICE, topo_name(pn)) == 0 &&
01bea0a73866e80109c4d637610ce639ea1e89b1jailletc (cn = expected_child(pn, PCI_FUNCTION, fnno)) == NULL)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (strcmp(PCIEX_DEVICE, topo_name(pn)) == 0 &&
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (cn = expected_child(pn, PCIEX_FUNCTION, fnno)) == NULL)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar pn = topo_set_instance_num(cn, fnno);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_out(TOPO_DEBUG, "Set function instance #%d.\n", fnno);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar set_excap_prop(pn, childcap);
f5d423af3d9e3f161aaea17b4ef3851608d43878clar set_std_properties(pn, n, ph);
e8f95a682820a599fe41b22977010636be5c2717jim fix_dev_prop(pn, devno, fnno);
d80638b1d2cf4b956aff22733d29f6eff05be2e7wrowe
d80638b1d2cf4b956aff22733d29f6eff05be2e7wrowe if ((topof = set_pci_properties(pn, n, ph)) != NULL) {
f5d423af3d9e3f161aaea17b4ef3851608d43878clar /*
d80638b1d2cf4b956aff22733d29f6eff05be2e7wrowe * Look for topology information specific to this
23b4e2f556ce39696c4e31c6e72893f7489ff8d9dirkx * vendor-id & device-id, if any.
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding */
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding (void) topo_load(topof, pn);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (childclass == PCI_CLASS_BRIDGE) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_out(TOPO_DEBUG, "device/fn is a bridge, ");
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (childsubclass != PCI_BRIDGE_PCI) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_out(TOPO_DEBUG, "but not to PCI.\n");
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding /*
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.
7a0780c774fcd7823d2e3a79f55b2f3522602992clar */
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (childcap < 0 ||
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding childetyp == PCIE_PCIECAP_DEV_TYPE_PCIE2PCI) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_out(TOPO_DEBUG,
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding "no PCI-express capabilities, or a "
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "bridge to PCI.\n");
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if ((cn = expected_child(pn, PCI_BUS, -1)) == NULL) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_out(TOPO_DEBUG,
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding "BUT the topo nodes lacks a "
7a0780c774fcd7823d2e3a79f55b2f3522602992clar PCI_BUS
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding "child node.\n");
d37377982fe3219083902f67dd667f1808f5547dwrowe return;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
7a0780c774fcd7823d2e3a79f55b2f3522602992clar } else {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_out(TOPO_DEBUG,
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "and has PCI-express capability.\n");
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding cn = expected_child(pn, PCIEX_BUS, -1);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (cn == NULL) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG,
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "but the topo nodes lacks a "
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding PCIEX_BUS
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding "child node.\n");
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
e8f95a682820a599fe41b22977010636be5c2717jim }
7a0780c774fcd7823d2e3a79f55b2f3522602992clar /*
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.
7a0780c774fcd7823d2e3a79f55b2f3522602992clar */
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding instantiate_children(cn, n, Promtree);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding}
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
cbe23d0a0ff097b3d544d714657452abc80e3c87fieldingvoid
e8f95a682820a599fe41b22977010636be5c2717jiminstantiate_children(tnode_t *tn, di_node_t n, di_prom_handle_t ph)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding{
7a0780c774fcd7823d2e3a79f55b2f3522602992clar di_node_t pn;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding pn = di_child_node(n);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding while (pn != DI_NODE_NIL) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar examine_prom_props(tn, pn, ph);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding pn = di_sibling_node(pn);
e8f95a682820a599fe41b22977010636be5c2717jim }
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding}
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
cbe23d0a0ff097b3d544d714657452abc80e3c87fieldingstatic di_node_t
cbe23d0a0ff097b3d544d714657452abc80e3c87fieldingdrivers_match(const char *drvr_type, const char *devprop)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar{
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding di_node_t pnode;
e8f95a682820a599fe41b22977010636be5c2717jim char *dnpath;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG, "search for drivers of type %s.\n", drvr_type);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding pnode = di_drv_first_node(drvr_type, Devtree);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar while (pnode != DI_NODE_NIL) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if ((dnpath = di_devfs_path(pnode)) == NULL)
e8f95a682820a599fe41b22977010636be5c2717jim continue;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG, "%s within %s ? ", dnpath, devprop);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (strcmp(devprop, dnpath) == 0) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_out(TOPO_DEBUG, "yesh!\n");
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding di_devfs_path_free(dnpath);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding break;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_out(TOPO_DEBUG, "no.\n");
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding di_devfs_path_free(dnpath);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding pnode = di_drv_next_node(pnode);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return (pnode);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding}
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fieldingstatic void
cbe23d0a0ff097b3d544d714657452abc80e3c87fieldingrepresent_hostbridge_pbm(tnode_t *node)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding{
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding tnode_t *parent;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding tnode_t *cn, *cn1;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding /*
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding * Only do this for PCI_BUS nodes
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding */
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (strcmp(PCI_BUS, topo_name(node)) != 0)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if ((cn = expected_child(node, PCI_DEVICE, 32)) == NULL)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar cn = topo_set_instance_num(cn, 32);
e8f95a682820a599fe41b22977010636be5c2717jim set_fru_info(cn);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (strcmp(PCI_DEVICE, topo_name(cn)) == 0 &&
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (cn1 = expected_child(cn, PCI_FUNCTION, 0)) == NULL)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (strcmp(PCIEX_DEVICE, topo_name(cn)) == 0 &&
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding (cn1 = expected_child(cn, PCIEX_FUNCTION, 0)) == NULL)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding cn = topo_set_instance_num(cn1, 0);
20fb0ba160cf0ca91b3f0f0d552cbe60d92b0449fielding copy_ancestor_prop(cn, DEV);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx copy_ancestor_prop(cn, ATTACHD);
f5d423af3d9e3f161aaea17b4ef3851608d43878clar copy_ancestor_prop(cn, DRIVER);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx copy_ancestor_prop(cn, ON);
f5d423af3d9e3f161aaea17b4ef3851608d43878clar set_fru_info(cn);
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx (void) topo_set_prop(node, DEV, "none");
d80638b1d2cf4b956aff22733d29f6eff05be2e7wrowe
d80638b1d2cf4b956aff22733d29f6eff05be2e7wrowe /*
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.
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx */
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if ((parent = topo_parent(node)) != NULL &&
7a0780c774fcd7823d2e3a79f55b2f3522602992clar strcmp(topo_name(parent), "hostbridge") == 0)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar copy_prop(DRIVER, parent, node);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar}
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clarstatic void
7a0780c774fcd7823d2e3a79f55b2f3522602992clarinstantiate_all(tnode_t *node, const char *drvr_type, di_prom_handle_t ph)
8eba5e2e323a9c28df8824675547f28743ca92d6trawick{
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding di_node_t pnode;
7a20709574a559549580a3b7cd199b9f9bf41018jailletc char *dnpath;
7a20709574a559549580a3b7cd199b9f9bf41018jailletc
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding pnode = di_drv_first_node(drvr_type, Devtree);
20fb0ba160cf0ca91b3f0f0d552cbe60d92b0449fielding while (pnode != DI_NODE_NIL) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar const char *devprop;
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx tnode_t *parent;
51469a0d2057aa24107b6f5a04e145824e10da1fdirkx
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if ((dnpath = di_devfs_path(pnode)) == NULL)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding continue;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if ((parent = topo_parent(node)) != NULL)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar devprop = topo_get_prop(parent, DEV);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (parent == NULL ||
d80638b1d2cf4b956aff22733d29f6eff05be2e7wrowe devprop == NULL ||
7a0780c774fcd7823d2e3a79f55b2f3522602992clar strcmp(devprop, dnpath) == 0) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding set_std_properties(node, pnode, ph);
d80638b1d2cf4b956aff22733d29f6eff05be2e7wrowe set_slot_info(node, pnode, ph);
e8f95a682820a599fe41b22977010636be5c2717jim set_attachpt_info(node, pnode);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding set_fru_info(node);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar represent_hostbridge_pbm(node);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar instantiate_children(node, pnode, ph);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
7a0780c774fcd7823d2e3a79f55b2f3522602992clar di_devfs_path_free(dnpath);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar pnode = di_drv_next_node(pnode);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
7a0780c774fcd7823d2e3a79f55b2f3522602992clar}
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clardi_node_t
7a0780c774fcd7823d2e3a79f55b2f3522602992clarpci_di_match(const char *devproppath)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding{
7a0780c774fcd7823d2e3a79f55b2f3522602992clar di_node_t pnode;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
7a0780c774fcd7823d2e3a79f55b2f3522602992clar /*
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.
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding */
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding pnode = drivers_match(PSYCHO, devproppath);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (pnode != DI_NODE_NIL)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return (pnode);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding pnode = drivers_match(SCHIZO, devproppath);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (pnode != DI_NODE_NIL)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return (pnode);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding pnode = drivers_match(NPE, devproppath);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (pnode != DI_NODE_NIL)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return (pnode);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding pnode = drivers_match(PX, devproppath);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (pnode != DI_NODE_NIL)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return (pnode);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding pnode = drivers_match(PCI, devproppath);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return (pnode);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding}
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fieldingdi_node_t
7a0780c774fcd7823d2e3a79f55b2f3522602992clarpciex_di_match(const char *devproppath)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar{
d80638b1d2cf4b956aff22733d29f6eff05be2e7wrowe di_node_t pnode;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
10a20aaa2426eff21e054473bbcab8cd2f104e59colm pnode = drivers_match(NPE, devproppath);
10a20aaa2426eff21e054473bbcab8cd2f104e59colm if (pnode != DI_NODE_NIL)
10a20aaa2426eff21e054473bbcab8cd2f104e59colm return (pnode);
10a20aaa2426eff21e054473bbcab8cd2f104e59colm
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding pnode = drivers_match(PX, devproppath);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return (pnode);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*
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.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingstatic void
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingconfirm_ancestors(tnode_t *node)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar{
7a0780c774fcd7823d2e3a79f55b2f3522602992clar tnode_t *parent;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int min, max;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clar parent = topo_parent(node);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding while (parent != NULL) {
ee044568b891a057768282bccd2498832108d32dsctemme if (topo_get_instance_num(parent) < 0) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_get_instance_range(parent, &min, &max);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (min == max && min >= 0)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (void) topo_set_instance_num(parent, min);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
509622419be000045d461ef38fb97df778fdf81djailletc parent = topo_parent(parent);
509622419be000045d461ef38fb97df778fdf81djailletc }
509622419be000045d461ef38fb97df778fdf81djailletc}
509622419be000045d461ef38fb97df778fdf81djailletc
509622419be000045d461ef38fb97df778fdf81djailletc/*
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.
7a0780c774fcd7823d2e3a79f55b2f3522602992clar */
7a0780c774fcd7823d2e3a79f55b2f3522602992clarvoid
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingenum_pci_bus(tnode_t *node)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding{
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding const char *dev, *scan;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding di_node_t selfdn;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding tnode_t *self;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar int express;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding int min, max;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
7a0780c774fcd7823d2e3a79f55b2f3522602992clar /*
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 *
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * Alternatively if there is no DEV, but there's a SCAN
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * property, we'll scan for pci buses.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (strcmp(PCIEX_ROOT, topo_name(node)) == 0)
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding express = 1;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar else if (strcmp(PCI_BUS, topo_name(node)) == 0)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding express = 0;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding else
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return;
d321fe00a917cfbe45929d741d74e2c89960b0b8trawick
d3dbafe0347b788a86bbe18ee6111750af41cec9trawick if ((dev = topo_get_prop(node, DEV)) == NULL) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding scan = topo_get_prop(node, SCAN);
9667009c60cf53ad7f1bfe9b73efecf403956d9dtrawick if (scan == NULL) {
9667009c60cf53ad7f1bfe9b73efecf403956d9dtrawick topo_out(TOPO_DEBUG,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "Bus tnode has no DEV or SCAN prop\n");
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (express == 0) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding instantiate_all(node, PCI, Promtree);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding instantiate_all(node, NPE, Promtree);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar instantiate_all(node, PX, Promtree);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar } else {
26734c75baf170a492ef6a82f07b24ee1af7d0b1sf instantiate_all(node, NPE, Promtree);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar instantiate_all(node, PX, Promtree);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
01bea0a73866e80109c4d637610ce639ea1e89b1jailletc return;
d321fe00a917cfbe45929d741d74e2c89960b0b8trawick } else {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (express == 0 &&
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (selfdn = pci_di_match(dev)) == DI_NODE_NIL) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG,
01bea0a73866e80109c4d637610ce639ea1e89b1jailletc "No match found for %s in devinfo.\n", dev);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (express == 1 &&
01bea0a73866e80109c4d637610ce639ea1e89b1jailletc (selfdn = pciex_di_match(dev)) == DI_NODE_NIL) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG,
e8f95a682820a599fe41b22977010636be5c2717jim "No match found for %s in devinfo.\n", dev);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clar /*
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...
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding */
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_get_instance_range(node, &min, &max);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (min < 0 || max < 0 || min != max) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding topo_out(TOPO_DEBUG,
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "Unexpected bus instance min %d != max %d.\n",
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding min, max);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding return;
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding self = topo_set_instance_num(node, min);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding set_std_properties(self, selfdn, Promtree);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding set_slot_info(self, selfdn, Promtree);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding set_attachpt_info(self, selfdn);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding set_fru_info(self);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding if (express == 0) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding /*
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * We represent the hostbridge's PCI bus module as a "device"
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * on the bus outside of the range of normal devices.
7a0780c774fcd7823d2e3a79f55b2f3522602992clar */
7a0780c774fcd7823d2e3a79f55b2f3522602992clar represent_hostbridge_pbm(self);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar } else {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar /*
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 */
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if ((self = expected_child(self, PCIEX_BUS, -1)) == NULL) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG,
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "Found pci-express root complex "
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "that lacks a " PCIEX_BUS
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding " child node to instance.\n");
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
7a0780c774fcd7823d2e3a79f55b2f3522602992clar instantiate_children(self, selfdn, Promtree);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding confirm_ancestors(self);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar}
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * find_devinfo_childdev()
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
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.
23b4e2f556ce39696c4e31c6e72893f7489ff8d9dirkx */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingdi_node_t
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmfind_devinfo_childdev(di_node_t parent, di_node_t child, int devno, int *fnno)
860d483ae528603f7e1f962903e71ac28358bef6wrowe{
23b4e2f556ce39696c4e31c6e72893f7489ff8d9dirkx di_node_t cn;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar uint_t reg, cc;
52d9e6442afa54065774d6c36bdb61f495953bf2fielding int cdevno;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (child != DI_NODE_NIL)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cn = di_sibling_node(child);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding else
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding cn = di_child_node(parent);
0906f649b3d720299e47ed1148e79051e8941b2adirkx while (cn != DI_NODE_NIL) {
30309f86bfd564437654aa822a19cd0cb29ca6f8wrowe if (get_class_code_and_reg(&cc, &reg, cn, Promtree) < 0)
1104271514ab6eee6391f8a0e670d9cc98184d9bfielding continue;
1104271514ab6eee6391f8a0e670d9cc98184d9bfielding cdevno = PCI_REG_DEV_G(reg);
1104271514ab6eee6391f8a0e670d9cc98184d9bfielding *fnno = PCI_REG_FUNC_G(reg);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (cdevno == devno)
57b7c64eaa9d7934d51d23c8e23f0b6cf6ce6a8atrawick break;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar cn = di_sibling_node(cn);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
f4a8b04b47f09a21b65646b66b19c9649ff7f03arbb return (cn);
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawick}
778f2416d2d9153ee72568a1aa7e11b7dc8946f4jorton
778f2416d2d9153ee72568a1aa7e11b7dc8946f4jorton/*
778f2416d2d9153ee72568a1aa7e11b7dc8946f4jorton * The enum_pci_dev() routine gets called by topo to explicitly set
778f2416d2d9153ee72568a1aa7e11b7dc8946f4jorton * instance numbers for specific PCI or PCI-Express device nodes.
dc610ff4888acc61dc6c8de2b8974a4dce9c074fsf */
dc610ff4888acc61dc6c8de2b8974a4dce9c074fsfvoid
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawickenum_pci_dev(tnode_t *node)
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawick{
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawick const char *dev;
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawick di_node_t ancdn, selfdn;
6707208ba4e9a5841ca1ab830830fd286ea5b7c5trawick tnode_t *fn = DI_NODE_NIL;
9179fa90e821c964d10f28b97fc6acee776af7cfwrowe tnode_t *pn;
daa3fa016bd51cdb39762a4510be99ba55c0b290aaron const char *topof;
daa3fa016bd51cdb39762a4510be99ba55c0b290aaron int fno;
daa3fa016bd51cdb39762a4510be99ba55c0b290aaron int excap;
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm int min, max;
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim /*
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 * tree.
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm */
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim if (((pn = topo_parent(node)) == NULL) ||
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm ((pn = topo_parent(pn)) == NULL) ||
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm ((dev = topo_get_prop(pn, DEV)) == NULL))
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm return;
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm if ((ancdn = di_init(dev, DINFOCPYALL)) == DI_NODE_NIL) {
b8fbac7d9e095a4cf4679d0a4b7a678baf9e319ecolm topo_out(TOPO_ERR,
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding "PCI enumerator: "
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton "di_init failed for device ancestor failed.\n");
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton return;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton /*
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 */
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton topo_get_instance_range(node, &min, &max);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (min < 0 || max < 0 || min != max) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton topo_out(TOPO_DEBUG,
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton "Unexpected device instance min %d != max %d.\n",
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton min, max);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton di_fini(ancdn);
9e897f011a21e8d982f1b5c6548f9882a8ca85d3wrowe return;
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton selfdn = find_devinfo_childdev(ancdn, DI_NODE_NIL, min, &fno);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (selfdn == DI_NODE_NIL) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton topo_out(TOPO_DEBUG, "No device # %d found.\n", min);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton di_fini(ancdn);
1fbf6ba0f5207e6637b49f9a9dfcc779bbe952a9trawick return;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
873c287c391b0bbc4719b68bb84946515811e1batrawick node = topo_set_instance_num(node, min);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG, "Set device instance #%d.\n", min);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar set_std_properties(node, selfdn, Promtree);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar do {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar excap = get_excap(selfdn, Promtree);
873c287c391b0bbc4719b68bb84946515811e1batrawick if (strcmp(PCI_DEVICE, topo_name(node)) == 0 &&
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (fn = expected_child(node, PCI_FUNCTION, fno)) == NULL) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG,
7a0780c774fcd7823d2e3a79f55b2f3522602992clar PCI_DEVICE "node lacks a " PCI_FUNCTION
7a0780c774fcd7823d2e3a79f55b2f3522602992clar "child node.\n");
7a0780c774fcd7823d2e3a79f55b2f3522602992clar di_fini(ancdn);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar return;
7a0780c774fcd7823d2e3a79f55b2f3522602992clar }
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim if (strcmp(PCIEX_DEVICE, topo_name(node)) == 0 &&
7a0780c774fcd7823d2e3a79f55b2f3522602992clar (fn = expected_child(node, PCIEX_FUNCTION, fno)) == NULL) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar topo_out(TOPO_DEBUG,
7a0780c774fcd7823d2e3a79f55b2f3522602992clar PCIEX_DEVICE "node lacks a " PCIEX_FUNCTION
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding "child node.\n");
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding di_fini(ancdn);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return;
694479b59aaa89e78fd4612bc060abddf7c8b6f1trawick }
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton fn = topo_set_instance_num(fn, fno);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton topo_out(TOPO_DEBUG, "Set function instance #%d.\n", fno);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton set_excap_prop(fn, excap);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton set_std_properties(fn, selfdn, Promtree);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton fix_dev_prop(fn, min, fno);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton topof = set_pci_properties(fn, selfdn, Promtree);
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton if (topof != NULL) {
e23b77006a8b079c0ad52e42ba2029e759455b8fjorton /*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Look for topology information specific to this
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * vendor-id & device-id, if any.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding (void) topo_load(topof, fn);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding selfdn = find_devinfo_childdev(DI_NODE_NIL, selfdn, min, &fno);
23b4e2f556ce39696c4e31c6e72893f7489ff8d9dirkx } while (selfdn != DI_NODE_NIL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (fn != DI_NODE_NIL)
7a0780c774fcd7823d2e3a79f55b2f3522602992clar confirm_ancestors(fn);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar di_fini(ancdn);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar}
7a0780c774fcd7823d2e3a79f55b2f3522602992clar
7a0780c774fcd7823d2e3a79f55b2f3522602992clarvoid
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingtopo_pci_enum(tnode_t *node)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
7a0780c774fcd7823d2e3a79f55b2f3522602992clar /*
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * Any enumerations other than buses should have already
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * happened at the time the bus was enumerated, so we can just
7a0780c774fcd7823d2e3a79f55b2f3522602992clar * return.
509622419be000045d461ef38fb97df778fdf81djailletc */
7a0780c774fcd7823d2e3a79f55b2f3522602992clar if (strcmp(PCI_BUS, topo_name(node)) == 0 ||
7a0780c774fcd7823d2e3a79f55b2f3522602992clar strcmp(PCIEX_ROOT, topo_name(node)) == 0) {
7a0780c774fcd7823d2e3a79f55b2f3522602992clar enum_pci_bus(node);
7a0780c774fcd7823d2e3a79f55b2f3522602992clar } else if (strcmp(PCI_DEVICE, topo_name(node)) == 0 ||
7a0780c774fcd7823d2e3a79f55b2f3522602992clar strcmp(PCIEX_DEVICE, topo_name(node)) == 0) {
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding enum_pci_dev(node);
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding }
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding}
cbe23d0a0ff097b3d544d714657452abc80e3c87fielding