Merge commit 'a058d1cc571af5fbcfe7f1d719df1abbfdb722f3' into merges
[unleashed.git] / usr / src / cmd / prtconf / prt_xxx.c
blobf8d270aa1be1bc765c0d37fdb2bf52cc15af40e1
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
26 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
29 #include <stdio.h>
30 #include <stddef.h>
31 #include <fcntl.h>
32 #include <string.h>
33 #include <libdevinfo.h>
34 #include <sys/pctypes.h>
35 #include <sys/utsname.h>
36 #include <sys/avintr.h>
38 #include "prtconf.h"
40 struct priv_data {
41 char *drv_name; /* parent name */
42 void (*pd_print)(uintptr_t, int); /* print function */
45 extern void indent_to_level();
46 static void obio_printregs(struct regspec *, int);
47 static void obio_printranges(struct rangespec *, int);
48 static void obio_printintr(struct intrspec *, int);
49 static void obio_print(uintptr_t, int);
50 static void sbus_print(uintptr_t, int);
51 static struct priv_data *match_priv_data(di_node_t);
54 * This is a hardcoded list of drivers we print parent private
55 * data as of Solaris 7.
57 static struct di_priv_format ppd_format[] = {
60 * obio format: applies the following list
61 * of nexus drivers. Note that obio driver
62 * went away with sun4m.
64 "central dma ebus fhc isa pci pci_pci rootnex",
65 sizeof (struct ddi_parent_private_data),
67 sizeof (struct regspec), /* first pointer */
68 offsetof(struct ddi_parent_private_data, par_reg),
69 offsetof(struct ddi_parent_private_data, par_nreg),
71 sizeof (struct intrspec), /* second pointer */
72 offsetof(struct ddi_parent_private_data, par_intr),
73 offsetof(struct ddi_parent_private_data, par_nintr),
75 sizeof (struct rangespec), /* third pointer */
76 offsetof(struct ddi_parent_private_data, par_rng),
77 offsetof(struct ddi_parent_private_data, par_nrng),
79 0, 0, 0, /* no more pointers */
80 0, 0, 0
83 { /* sbus format--it's different on sun4u!! */
84 "sbus",
85 sizeof (struct ddi_parent_private_data),
87 sizeof (struct regspec), /* first pointer */
88 offsetof(struct ddi_parent_private_data, par_reg),
89 offsetof(struct ddi_parent_private_data, par_nreg),
91 sizeof (struct intrspec), /* second pointer */
92 offsetof(struct ddi_parent_private_data, par_intr),
93 offsetof(struct ddi_parent_private_data, par_nintr),
95 sizeof (struct rangespec), /* third pointer */
96 offsetof(struct ddi_parent_private_data, par_rng),
97 offsetof(struct ddi_parent_private_data, par_nrng),
99 0, 0, 0, /* no more pointers */
100 0, 0, 0
104 static struct priv_data prt_priv_data[] = {
105 { ppd_format[0].drv_name, obio_print},
106 { ppd_format[1].drv_name, sbus_print}
109 static int nprt_priv_data = sizeof (prt_priv_data)/sizeof (struct priv_data);
111 void
112 init_priv_data(struct di_priv_data *fetch)
114 /* no driver private data */
115 fetch->version = DI_PRIVDATA_VERSION_0;
116 fetch->n_driver = 0;
117 fetch->driver = NULL;
119 fetch->n_parent = nprt_priv_data;
120 fetch->parent = ppd_format;
123 static void
124 obio_printregs(struct regspec *rp, int ilev)
126 indent_to_level(ilev);
127 (void) printf(" Bus Type=0x%x, Address=0x%x, Size=0x%x\n",
128 rp->regspec_bustype, rp->regspec_addr, rp->regspec_size);
131 static void
132 obio_printranges(struct rangespec *rp, int ilev)
134 indent_to_level(ilev);
135 (void) printf(" Ch: %.2x,%.8x Pa: %.2x,%.8x, Sz: %x\n",
136 rp->rng_cbustype, rp->rng_coffset,
137 rp->rng_bustype, rp->rng_offset,
138 rp->rng_size);
141 static void
142 obio_printintr(struct intrspec *ip, int ilev)
144 indent_to_level(ilev);
145 (void) printf(" Interrupt Priority=0x%x (ipl %d)",
146 ip->intrspec_pri, INT_IPL(ip->intrspec_pri));
147 if (ip->intrspec_vec)
148 (void) printf(", vector=0x%x (%d)",
149 ip->intrspec_vec, ip->intrspec_vec);
150 (void) printf("\n");
153 static void
154 obio_print(uintptr_t data, int ilev)
156 int i, nreg, nrng, nintr;
157 struct ddi_parent_private_data *dp;
158 struct regspec *reg;
159 struct intrspec *intr;
160 struct rangespec *rng;
162 dp = (struct ddi_parent_private_data *)data;
163 #ifdef DEBUG
164 dprintf("obio parent private data: nreg = 0x%x offset = 0x%x"
165 " nintr = 0x%x offset = 0x%x nrng = 0x%x offset = %x\n",
166 dp->par_nreg, *((di_off_t *)(&dp->par_reg)),
167 dp->par_nintr, *((di_off_t *)(&dp->par_intr)),
168 dp->par_nrng, *((di_off_t *)(&dp->par_rng)));
169 #endif /* DEBUG */
170 nreg = dp->par_nreg;
171 nintr = dp->par_nintr;
172 nrng = dp->par_nrng;
175 * All pointers are translated to di_off_t by the devinfo driver.
176 * This is a private agreement between libdevinfo and prtconf.
178 if (nreg != 0) {
179 indent_to_level(ilev);
180 (void) printf("Register Specifications:\n");
182 reg = (struct regspec *)(data + *(di_off_t *)(&dp->par_reg));
183 for (i = 0; i < nreg; ++i)
184 obio_printregs(reg + i, ilev);
187 if (nrng != 0) {
188 indent_to_level(ilev);
189 (void) printf("Range Specifications:\n");
191 rng = (struct rangespec *)(data + *(di_off_t *)(&dp->par_rng));
192 for (i = 0; i < nrng; ++i)
193 obio_printranges(rng + i, ilev);
196 if (nintr != 0) {
197 indent_to_level(ilev);
198 (void) printf("Interrupt Specifications:\n");
200 intr = (struct intrspec *)(data + *(di_off_t *)(&dp->par_intr));
201 for (i = 0; i < nintr; ++i)
202 obio_printintr(intr + i, ilev);
206 static void
207 sbus_print(uintptr_t data, int ilev)
209 int i, nreg, nrng, nintr;
210 struct ddi_parent_private_data *dp;
211 struct regspec *reg;
212 struct intrspec *intr;
213 struct rangespec *rng;
215 dp = (struct ddi_parent_private_data *)data;
216 #ifdef DEBUG
217 dprintf("sbus parent private data: nreg = 0x%x offset = 0x%x"
218 " nintr = 0x%x offset = 0x%x nrng = 0x%x offset = %x\n",
219 dp->par_nreg, *((di_off_t *)(&dp->par_reg)),
220 dp->par_nintr, *((di_off_t *)(&dp->par_intr)),
221 dp->par_nrng, *((di_off_t *)(&dp->par_rng)));
222 #endif /* DEBUG */
223 nreg = dp->par_nreg;
224 nintr = dp->par_nintr;
225 nrng = dp->par_nrng;
228 * All pointers are translated to di_off_t by the devinfo driver.
229 * This is a private agreement between libdevinfo and prtconf.
231 if (nreg != 0) {
232 indent_to_level(ilev);
233 (void) printf("Register Specifications:\n");
235 reg = (struct regspec *)(data + *(di_off_t *)(&dp->par_reg));
236 for (i = 0; i < nreg; ++i)
237 obio_printregs(reg + i, ilev);
241 if (nrng != 0) {
242 indent_to_level(ilev);
243 (void) printf("Range Specifications:\n");
245 rng = (struct rangespec *)(data + *(di_off_t *)(&dp->par_rng));
246 for (i = 0; i < nrng; ++i)
247 obio_printranges(rng + i, ilev);
251 * To print interrupt property for children of sbus on sun4u requires
252 * definitions in sysiosbus.h.
254 * We can't #include <sys/sysiosbus.h> to have the build work on
255 * non sun4u machines. It's not right either to
256 * #include "../../uts/sun4u/sys/sysiosbus.h"
257 * As a result, we will not print the information.
259 if ((nintr != 0) && (strcmp(opts.o_uts.machine, "sun4u") != 0)) {
260 indent_to_level(ilev);
261 (void) printf("Interrupt Specifications:\n");
263 for (i = 0; i < nintr; ++i) {
264 intr = (struct intrspec *)
265 (data + *(di_off_t *)(&dp->par_intr));
266 obio_printintr(intr + i, ilev);
271 static struct priv_data *
272 match_priv_data(di_node_t node)
274 int i;
275 size_t len;
276 char *drv_name, *tmp;
277 di_node_t parent;
278 struct priv_data *pdp;
280 if ((parent = di_parent_node(node)) == DI_NODE_NIL)
281 return (NULL);
283 if ((drv_name = di_driver_name(parent)) == NULL)
284 return (NULL);
286 pdp = prt_priv_data;
287 len = strlen(drv_name);
288 for (i = 0; i < nprt_priv_data; ++i, ++pdp) {
289 tmp = pdp->drv_name;
290 while (tmp && (*tmp != '\0')) {
291 if (strncmp(tmp, drv_name, len) == 0) {
292 #ifdef DEBUG
293 dprintf("matched parent private data"
294 " at Node <%s> parent driver <%s>\n",
295 di_node_name(node), drv_name);
296 #endif /* DEBUG */
297 return (pdp);
300 * skip a white space
302 if (tmp = strchr(tmp, ' '))
303 tmp++;
307 return (NULL);
310 void
311 dump_priv_data(int ilev, di_node_t node)
313 uintptr_t priv;
314 struct priv_data *pdp;
316 if ((priv = (uintptr_t)di_parent_private_data(node)) == (uintptr_t)NULL)
317 return;
319 if ((pdp = match_priv_data(node)) == NULL) {
320 #ifdef DEBUG
321 dprintf("Error: parent private data format unknown\n");
322 #endif /* DEBUG */
323 return;
326 pdp->pd_print(priv, ilev);
328 /* ignore driver private data for now */
331 #define LOOKUP_PROP(proptype, ph, nodetype, dev, node, name, data) \
332 ((nodetype == DI_PROM_NODEID) ? \
333 di_prom_prop_lookup_##proptype(ph, node, name, data) : \
334 di_prop_lookup_##proptype(dev, node, name, data))
335 #define ISPCI(s) \
336 (((s) != NULL) && ((strcmp((s), "pci") == 0) || \
337 (strcmp((s), "pciex") == 0)))
339 * Print vendor ID and device ID for PCI devices
342 print_pciid(di_node_t node, di_prom_handle_t ph, pcidb_hdl_t *pci)
344 pcidb_vendor_t *vend = NULL;
345 pcidb_device_t *dev = NULL;
346 di_node_t pnode = di_parent_node(node);
347 char *s = NULL;
348 int *i, type = di_nodeid(node);
350 if (LOOKUP_PROP(strings, ph, type, DDI_DEV_T_ANY, pnode,
351 "device_type", &s) <= 0)
352 return (0);
354 if (!ISPCI(s))
355 return (0); /* not a pci device */
357 (void) printf(" (%s", s);
358 if (LOOKUP_PROP(ints, ph, type, DDI_DEV_T_ANY, node,
359 "vendor-id", &i) > 0)
360 (void) printf("%x", i[0]);
362 if (pci != NULL)
363 vend = pcidb_lookup_vendor(pci, i[0]);
365 if (LOOKUP_PROP(ints, ph, type, DDI_DEV_T_ANY, node,
366 "device-id", &i) > 0)
367 (void) printf(",%x", i[0]);
369 if (vend != NULL)
370 dev = pcidb_lookup_device_by_vendor(vend, i[0]);
372 (void) printf(") [");
374 if (vend != NULL)
375 (void) printf("%s ", pcidb_vendor_name(vend));
376 else
377 (void) printf("unknown vendor, ");
379 if (dev != NULL)
380 (void) printf("%s", pcidb_device_name(dev));
381 else
382 (void) printf("unknown device");
384 (void) printf("]");
385 return (1);