1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * SUNW,Sun-Fire platform ioboard topology enumerator
31 */
32
33 #include <string.h>
34 #include <libdevinfo.h>
35 #include <fm/topo_mod.h>
36 #include <fm/topo_hc.h>
37
38 #include <did.h>
39 #include <hostbridge.h>
40 #include <ioboard.h>
41 #include <util.h>
42
43 /*ARGSUSED*/
44 int
platform_iob_label(topo_mod_t * mod,tnode_t * node,nvlist_t * ignored,nvlist_t ** out)45 platform_iob_label(topo_mod_t *mod, tnode_t *node, nvlist_t *ignored,
46 nvlist_t **out)
47 {
48 /*
49 * For SUNW,Sun-Fire the label is simply N0.IBXX where XX is the
50 * instance number of the ioboard.
51 */
52 char buf[13]; /* up to a million I/O boards :-) */
53
54 *out = NULL;
55 (void) snprintf(buf, 10, "N0.IB%d", topo_node_instance(node));
56 if (topo_mod_nvalloc(mod, out, NV_UNIQUE_NAME) == 0 &&
57 nvlist_add_string(*out, TOPO_METH_LABEL_RET_STR, buf) == 0)
58 return (0);
59 nvlist_free(*out);
60 *out = NULL;
61 return (-1);
62 }
63
64 #define IOB_BASEADDR 0x18
65 #define BUS_ADDRDIST 0x2
66
67 /*ARGSUSED*/
68 int
platform_iob_enum(topo_mod_t * mod,tnode_t * parent,topo_instance_t imin,topo_instance_t imax)69 platform_iob_enum(topo_mod_t *mod, tnode_t *parent, topo_instance_t imin,
70 topo_instance_t imax)
71 {
72 /*
73 * A SUNW,Sun-Fire and its successors may have up to 4 I/O boards,
74 * numbered 6 through 9. Each board has two hostbridges, and
75 * there are a pair of PCI buses under each hostbridge. We can
76 * discover the existence of a board by the presence of
77 * devinfo nodes for those hostbridges. We let the hostbridge
78 * enumerator actually create nodes for the hostbridges,
79 * passing them the did_t's for all the hostbridge nodes we
80 * know indicate that the ioboard exists.
81 */
82 di_node_t devtree;
83 di_node_t pnode;
84 did_t *iobs[18][2][2];
85 int brd, br, bus, i;
86
87 devtree = topo_mod_devinfo(mod);
88 if (devtree == DI_NODE_NIL) {
89 topo_mod_dprintf(mod, "devinfo init failed.");
90 return (-1);
91 }
92
93 for (i = 6; i <= 9; i++) {
94 iobs[i][0][0] = iobs[i][0][1] = NULL;
95 iobs[i][1][0] = iobs[i][1][1] = NULL;
96 }
97
98 pnode = di_drv_first_node(SCHIZO, devtree);
99 while (pnode != DI_NODE_NIL) {
100 did_t *d;
101
102 d = split_bus_address(mod,
103 pnode, IOB_BASEADDR, BUS_ADDRDIST, 6, 9, &brd, &br, &bus);
104 if (d == NULL) {
105 pnode = di_drv_next_node(pnode);
106 continue;
107 }
108 iobs[brd][br][bus] = d;
109 pnode = di_drv_next_node(pnode);
110 }
111
112 for (i = 6; i < 9; i++) {
113 tnode_t *ion;
114 /*
115 * Make sure we found all the buses and bridges
116 */
117 if (iobs[i][0][0] == NULL || iobs[i][0][1] == NULL ||
118 iobs[i][1][0] == NULL || iobs[i][1][1] == NULL)
119 continue;
120 did_did_link_set(iobs[i][0][0], iobs[i][0][1]);
121 did_did_link_set(iobs[i][1][0], iobs[i][1][1]);
122 did_did_chain_set(iobs[i][0][0], iobs[i][1][0]);
123 if ((ion = ioboard_declare(mod, parent, i, iobs[i][0][0]))
124 == NULL) {
125 topo_mod_dprintf(mod,
126 "Creation of tnode for %s%d failed.\n", IOBOARD, i);
127 continue;
128 }
129 if (topo_mod_enumerate(mod,
130 ion, HOSTBRIDGE, HOSTBRIDGE, 0, 0, iobs[i][0][0]) < 0) {
131 topo_mod_dprintf(mod,
132 "Enumeration of %s%d/%s%d failed.\n",
133 IOBOARD, i, HOSTBRIDGE, 0);
134 continue;
135 }
136 if (topo_mod_enumerate(mod,
137 ion, HOSTBRIDGE, HOSTBRIDGE, 1, 1, iobs[i][0][0]) < 0) {
138 topo_mod_dprintf(mod,
139 "Enumeration of %s%d/%s%d failed.\n",
140 IOBOARD, i, HOSTBRIDGE, 1);
141 continue;
142 }
143 }
144 return (0);
145 }
146