did.c (60348818) did.c (0db3240d)
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

--- 6 unchanged lines hidden (view full) ---

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/*
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

--- 6 unchanged lines hidden (view full) ---

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 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27/*
28 * did.c
29 * The acronym did means "Dev-Info-Data". Many properties and
30 * characteristics of topology nodes are, with a bit of coaxing
31 * derived from devinfo nodes. These routines do some of the
32 * derivation and also encapsulate the discoveries in did_t

--- 43 unchanged lines hidden (view full) ---

76 return;
77 slotnm_destroy(p->snm_next);
78 if (p->snm_name != NULL)
79 topo_mod_strfree(p->snm_mod, p->snm_name);
80 topo_mod_free(p->snm_mod, p, sizeof (slotnm_t));
81}
82
83static int
24 */
25
26/*
27 * did.c
28 * The acronym did means "Dev-Info-Data". Many properties and
29 * characteristics of topology nodes are, with a bit of coaxing
30 * derived from devinfo nodes. These routines do some of the
31 * derivation and also encapsulate the discoveries in did_t

--- 43 unchanged lines hidden (view full) ---

75 return;
76 slotnm_destroy(p->snm_next);
77 if (p->snm_name != NULL)
78 topo_mod_strfree(p->snm_mod, p->snm_name);
79 topo_mod_free(p->snm_mod, p, sizeof (slotnm_t));
80}
81
82static int
84slotnm_cp(did_t *from, did_t *to, int *nslots)
85{
86 slotnm_t *nxt, *new;
87 slotnm_t *last = NULL;
88
89 *nslots = 0;
90 for (nxt = from->dp_slotnames; nxt != NULL; nxt = nxt->snm_next) {
91 new = slotnm_create(to->dp_mod, nxt->snm_dev, nxt->snm_name);
92 if (new == NULL) {
93 if (to->dp_slotnames != NULL)
94 slotnm_destroy(to->dp_slotnames);
95 to->dp_slotnames = NULL;
96 *nslots = 0;
97 return (-1);
98 }
99 if (last == NULL) {
100 to->dp_slotnames = last = new;
101 } else {
102 last->snm_next = new;
103 last = new;
104 }
105 (*nslots)++;
106 }
107 if (*nslots > 0)
108 topo_mod_dprintf(to->dp_mod,
109 "%p inherits %d slot label(s) from %p.\n",
110 to, *nslots, from);
111 return (0);
112}
113
114static int
115di_devtype_get(topo_mod_t *mp, di_node_t src, char **devtype)
116{
117 int sz;
118 uchar_t *buf;
119
120 /*
121 * For PCI the device type defined the type of device directly below.
122 * For PCIe RP and Switches, the device-type should be "pciex". For

--- 6 unchanged lines hidden (view full) ---

129 *devtype = NULL;
130 }
131
132 if (*devtype != NULL)
133 return (0);
134 return (-1);
135}
136
83di_devtype_get(topo_mod_t *mp, di_node_t src, char **devtype)
84{
85 int sz;
86 uchar_t *buf;
87
88 /*
89 * For PCI the device type defined the type of device directly below.
90 * For PCIe RP and Switches, the device-type should be "pciex". For

--- 6 unchanged lines hidden (view full) ---

97 *devtype = NULL;
98 }
99
100 if (*devtype != NULL)
101 return (0);
102 return (-1);
103}
104
105typedef struct smbios_slot_cb {
106 int cb_slotnum;
107 const char *cb_label;
108} smbios_slot_cb_t;
109
137static int
110static int
111di_smbios_find_slot(smbios_hdl_t *shp, const smbios_struct_t *strp, void *data)
112{
113 smbios_slot_cb_t *cbp = data;
114 smbios_slot_t slot;
115
116 if (strp->smbstr_type != SMB_TYPE_SLOT ||
117 smbios_info_slot(shp, strp->smbstr_id, &slot) != 0)
118 return (0);
119
120 if (slot.smbl_id == cbp->cb_slotnum) {
121 cbp->cb_label = slot.smbl_name;
122 return (1);
123 }
124
125 return (0);
126}
127
128static int
138di_physlotinfo_get(topo_mod_t *mp, di_node_t src, int *slotnum, char **slotname)
139{
140 char *slotbuf;
141 int sz;
142 uchar_t *buf;
129di_physlotinfo_get(topo_mod_t *mp, di_node_t src, int *slotnum, char **slotname)
130{
131 char *slotbuf;
132 int sz;
133 uchar_t *buf;
134 smbios_hdl_t *shp;
135 boolean_t got_slotprop = B_FALSE;
143
144 *slotnum = -1;
136
137 *slotnum = -1;
138
145 (void) di_uintprop_get(mp, src, DI_PHYSPROP, (uint_t *)slotnum);
146
139 (void) di_uintprop_get(mp, src, DI_PHYSPROP, (uint_t *)slotnum);
140
147 if (*slotnum == -1)
148 return (0);
149
150 /*
151 * For PCI-Express, there is only one downstream device, so check for
152 * a slot-names property, and if it exists, ignore the slotmask value
153 * and use the string as the label.
154 */
155 if (di_bytes_get(mp, src, DI_SLOTPROP, &sz, &buf) == 0 &&
156 sz > 4) {
141 /*
142 * For PCI-Express, there is only one downstream device, so check for
143 * a slot-names property, and if it exists, ignore the slotmask value
144 * and use the string as the label.
145 */
146 if (di_bytes_get(mp, src, DI_SLOTPROP, &sz, &buf) == 0 &&
147 sz > 4) {
148 /*
149 * If there is a DI_SLOTPROP of the form SlotX (ie set up from
150 * the IRQ routing table) then trust that in preference to
151 * DI_PHYSPROP (which is set up from the PCIe slotcap reg).
152 */
153 got_slotprop = B_TRUE;
154 (void) sscanf((char *)&buf[4], "Slot%d", slotnum);
155 }
156
157 if (*slotnum == -1)
158 return (0);
159
160 /*
161 * Order of preference
162 * 1) take slotnum and look up in SMBIOS table
163 * 2) use slot-names
164 * 3) fabricate name based on slotnum
165 */
166 if ((shp = topo_mod_smbios(mp)) != NULL) {
167 /*
168 * The PCI spec describes slot number 0 as reserved for
169 * internal PCI devices. Not all platforms respect
170 * this, so we have to treat slot 0 as a valid device.
171 * But other platforms use 0 to identify an internal
172 * device. We deal with this by letting SMBIOS be the
173 * final decision maker. If SMBIOS is supported, but
174 * the given slot number is not represented in the
175 * SMBIOS tables, then ignore the slot entirely.
176 */
177 smbios_slot_cb_t cbdata;
178
179 cbdata.cb_slotnum = *slotnum;
180 cbdata.cb_label = NULL;
181 if (smbios_iter(shp, di_smbios_find_slot, &cbdata) <= 0)
182 return (0);
183 slotbuf = (char *)cbdata.cb_label;
184 topo_mod_dprintf(mp, "%s: node=%p: using smbios name\n",
185 __func__, src);
186 } else if (got_slotprop == B_TRUE) {
157 slotbuf = (char *)&buf[4];
187 slotbuf = (char *)&buf[4];
158 topo_mod_dprintf(mp, "di_physlotinfo_get: node=%p: "
159 "found %s property\n", src, DI_SLOTPROP);
188 topo_mod_dprintf(mp, "%s: node=%p: found %s property\n",
189 __func__, src, DI_SLOTPROP);
160 } else {
161 /*
162 * Make generic description string "SLOT <num>", allow up to
163 * 10 digits for number
164 */
165 slotbuf = alloca(16);
166 (void) snprintf(slotbuf, 16, "SLOT %d", *slotnum);
190 } else {
191 /*
192 * Make generic description string "SLOT <num>", allow up to
193 * 10 digits for number
194 */
195 slotbuf = alloca(16);
196 (void) snprintf(slotbuf, 16, "SLOT %d", *slotnum);
167 topo_mod_dprintf(mp, "di_physlotinfo_get: node=%p: "
168 "using generic slot name\n", src);
197 topo_mod_dprintf(mp, "%s: node=%p: using generic slot name\n",
198 __func__, src);
169 }
170 if ((*slotname = topo_mod_strdup(mp, slotbuf)) == NULL)
171 return (-1);
172
199 }
200 if ((*slotname = topo_mod_strdup(mp, slotbuf)) == NULL)
201 return (-1);
202
173 topo_mod_dprintf(mp, "di_physlotinfo_get: node=%p: slotname=%s\n",
174 src, *slotname);
203 topo_mod_dprintf(mp, "%s: node=%p: slotname=%s\n",
204 __func__, src, *slotname);
175
176 return (0);
177}
178
179static int
180di_slotinfo_get(topo_mod_t *mp, di_node_t src, int *nslots,
181 slotnm_t **slotnames)
182{

--- 102 unchanged lines hidden (view full) ---

285 np->dp_subclass = GETSUBCLASS(code);
286 } else {
287 np->dp_class = -1;
288 }
289 /*
290 * There *may* be a device type we can capture.
291 */
292 (void) di_devtype_get(mp, src, &np->dp_devtype);
205
206 return (0);
207}
208
209static int
210di_slotinfo_get(topo_mod_t *mp, di_node_t src, int *nslots,
211 slotnm_t **slotnames)
212{

--- 102 unchanged lines hidden (view full) ---

315 np->dp_subclass = GETSUBCLASS(code);
316 } else {
317 np->dp_class = -1;
318 }
319 /*
320 * There *may* be a device type we can capture.
321 */
322 (void) di_devtype_get(mp, src, &np->dp_devtype);
293 /*
294 * There *may* be a physical slot number property we can capture.
295 */
296 if (di_physlotinfo_get(mp,
297 src, &np->dp_physlot, &np->dp_physlot_name) < 0) {
298 if (np->dp_devtype != NULL)
299 topo_mod_strfree(mp, np->dp_devtype);
300 topo_mod_free(mp, np, sizeof (did_t));
301 return (NULL);
323
324 if (irc >= 0) {
325 /*
326 * This is a pciex node.
327 */
328 if (di_physlotinfo_get(mp, src, &np->dp_physlot,
329 &np->dp_physlot_name) < 0) {
330 if (np->dp_devtype != NULL)
331 topo_mod_strfree(mp, np->dp_devtype);
332 topo_mod_free(mp, np, sizeof (did_t));
333 return (NULL);
334 }
335 } else {
336 /*
337 * This is a pci node.
338 */
339 if (di_slotinfo_get(mp, src, &np->dp_nslots,
340 &np->dp_slotnames) < 0) {
341 if (np->dp_devtype != NULL)
342 topo_mod_strfree(mp, np->dp_devtype);
343 topo_mod_free(mp, np, sizeof (did_t));
344 return (NULL);
345 }
302 }
346 }
303 /*
304 * There *may* be PCI slot info we can capture
305 */
306 if (di_slotinfo_get(mp, src, &np->dp_nslots, &np->dp_slotnames) < 0) {
307 if (np->dp_devtype != NULL)
308 topo_mod_strfree(mp, np->dp_devtype);
309 if (np->dp_physlot_name != NULL)
310 topo_mod_strfree(mp, np->dp_physlot_name);
311 topo_mod_free(mp, np, sizeof (did_t));
312 return (NULL);
313 }
314 did_hash_insert(mp, src, np);
315 did_hold(np);
316 return (np);
317}
318
319did_t *
320did_link_get(did_t *dp)
321{

--- 124 unchanged lines hidden (view full) ---

446
447int
448did_rc(did_t *did)
449{
450 assert(did != NULL);
451 return (did->dp_rc);
452}
453
347 did_hash_insert(mp, src, np);
348 did_hold(np);
349 return (np);
350}
351
352did_t *
353did_link_get(did_t *dp)
354{

--- 124 unchanged lines hidden (view full) ---

479
480int
481did_rc(did_t *did)
482{
483 assert(did != NULL);
484 return (did->dp_rc);
485}
486
454static int
455did_numlabels(did_t *dp)
456{
457 assert(dp != NULL);
458 return (dp->dp_nslots);
459}
460
461int
462did_excap(did_t *dp)
463{
464 assert(dp != NULL);
465 return ((int)dp->dp_excap);
466}
467
468void

--- 10 unchanged lines hidden (view full) ---

479}
480
481const char *
482did_physlot_name(did_t *dp, int dev)
483{
484 slotnm_t *slot;
485
486 assert(dp != NULL);
487int
488did_excap(did_t *dp)
489{
490 assert(dp != NULL);
491 return ((int)dp->dp_excap);
492}
493
494void

--- 10 unchanged lines hidden (view full) ---

505}
506
507const char *
508did_physlot_name(did_t *dp, int dev)
509{
510 slotnm_t *slot;
511
512 assert(dp != NULL);
513
514 /*
515 * For pciex, name will be in dp_physlot_name
516 */
487 if (dp->dp_physlot_name != NULL)
488 return (dp->dp_physlot_name);
517 if (dp->dp_physlot_name != NULL)
518 return (dp->dp_physlot_name);
519
520 /*
521 * For pci, name will be in dp_slotnames
522 */
489 for (slot = dp->dp_slotnames; slot != NULL; slot = slot->snm_next)
490 if (slot->snm_dev == dev)
491 break;
492 if (slot != NULL)
493 return (slot->snm_name);
494 return (NULL);
495}
496

--- 65 unchanged lines hidden (view full) ---

562 did_t *dp;
563
564 if ((dp = did_find(mp, dn)) == NULL)
565 return (-1);
566 did_rele(dp);
567 return (dp->dp_excap);
568}
569
523 for (slot = dp->dp_slotnames; slot != NULL; slot = slot->snm_next)
524 if (slot->snm_dev == dev)
525 break;
526 if (slot != NULL)
527 return (slot->snm_name);
528 return (NULL);
529}
530

--- 65 unchanged lines hidden (view full) ---

596 did_t *dp;
597
598 if ((dp = did_find(mp, dn)) == NULL)
599 return (-1);
600 did_rele(dp);
601 return (dp->dp_excap);
602}
603
570int
571did_inherit(did_t *pdp, did_t *dp)
572{
573 /*
574 * If the child already has a label, we're done.
575 */
576 assert(dp != NULL);
577 if (did_numlabels(dp) > 0)
578 return (0);
579
580 assert(pdp != NULL);
581
582 /*
583 * If the child and parent are the same, we're done.
584 */
585 if (dp == pdp)
586 return (0);
587
588 if (pdp->dp_physlot_name != NULL) {
589 topo_mod_dprintf(dp->dp_mod,
590 "%p inherits physlot label from %p.\n", dp, pdp);
591 dp->dp_physlot_name =
592 topo_mod_strdup(dp->dp_mod, pdp->dp_physlot_name);
593 if (dp->dp_physlot_name == NULL)
594 return (-1);
595 }
596 if (slotnm_cp(pdp, dp, &dp->dp_nslots) < 0)
597 return (-1);
598 return (0);
599}
600
601void
602did_setspecific(topo_mod_t *mp, void *data)
603{
604 did_t *hbdid;
605
606 hbdid = (did_t *)data;
607 topo_mod_setspecific(mp, hbdid->dp_hash);
608}

--- 13 unchanged lines hidden ---
604void
605did_setspecific(topo_mod_t *mp, void *data)
606{
607 did_t *hbdid;
608
609 hbdid = (did_t *)data;
610 topo_mod_setspecific(mp, hbdid->dp_hash);
611}

--- 13 unchanged lines hidden ---