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 2008 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 #include <libnvpair.h> 30 #include <fm/topo_mod.h> 31 #include <assert.h> 32 #include <string.h> 33 #include <sys/fm/protocol.h> 34 35 #include <did.h> 36 #include <pcibus.h> 37 #include <pcibus_labels.h> 38 39 extern slotnm_rewrite_t *Slot_Rewrites; 40 extern physlot_names_t *Physlot_Names; 41 extern missing_names_t *Missing_Names; 42 43 static const char * 44 pci_physslot_name_lookup(char *platform, did_t *dp) 45 { 46 const char *rlabel = NULL; 47 int n, p, i; 48 49 if ((n = did_physslot(dp)) < 0 || Physlot_Names == NULL || 50 platform == NULL) 51 return (NULL); 52 53 for (p = 0; p < Physlot_Names->psn_nplats; p++) { 54 if (strcmp(Physlot_Names->psn_names[p].pnm_platform, 55 platform) != 0) 56 continue; 57 for (i = 0; i < Physlot_Names->psn_names[p].pnm_nnames; i++) { 58 physnm_t ps; 59 ps = Physlot_Names->psn_names[p].pnm_names[i]; 60 if (ps.ps_num == n) { 61 rlabel = ps.ps_label; 62 break; 63 } 64 } 65 break; 66 } 67 return (rlabel); 68 } 69 70 static const char * 71 pci_slotname_rewrite(char *platform, const char *label) 72 { 73 const char *rlabel = label; 74 int s, i; 75 76 if (Slot_Rewrites == NULL) 77 return (rlabel); 78 79 for (s = 0; s < Slot_Rewrites->srw_nplats; s++) { 80 if (strcmp(Slot_Rewrites->srw_platrewrites[s].prw_platform, 81 platform) != 0) 82 continue; 83 for (i = 0; 84 i < Slot_Rewrites->srw_platrewrites[s].prw_nrewrites; 85 i++) { 86 slot_rwd_t rw; 87 rw = Slot_Rewrites->srw_platrewrites[s].prw_rewrites[i]; 88 if (strcmp(rw.srw_obp, label) == 0) { 89 rlabel = rw.srw_new; 90 break; 91 } 92 } 93 break; 94 } 95 assert(rlabel != NULL); 96 return (rlabel); 97 } 98 99 static const char * 100 pci_missing_match(topo_mod_t *mod, char *platform, did_t *dp) 101 { 102 const char *rlabel = NULL; 103 int board, bridge, rc, bus, dev; 104 int p, i; 105 106 if (Missing_Names == NULL) 107 return (NULL); 108 bridge = did_bridge(dp); 109 board = did_board(dp); 110 rc = did_rc(dp); 111 did_BDF(dp, &bus, &dev, NULL); 112 113 topo_mod_dprintf(mod, "Missing a name for %d, %d, %d, %d, %d ?\n", 114 board, bridge, rc, bus, dev); 115 116 for (p = 0; p < Missing_Names->mn_nplats; p++) { 117 if (strcmp(Missing_Names->mn_names[p].pdl_platform, 118 platform) != 0) 119 continue; 120 for (i = 0; i < Missing_Names->mn_names[p].pdl_nnames; i++) { 121 devlab_t m; 122 m = Missing_Names->mn_names[p].pdl_names[i]; 123 if (m.dl_board == board && m.dl_bridge == bridge && 124 m.dl_rc == rc && m.dl_bus == bus && 125 m.dl_dev == dev) { 126 rlabel = m.dl_label; 127 break; 128 } 129 } 130 break; 131 } 132 return (rlabel); 133 } 134 135 const char * 136 pci_slotname_lookup(topo_mod_t *mod, tnode_t *node, did_t *dp, did_t *pdp) 137 { 138 const char *l; 139 char *plat, *pp; 140 int err; 141 int d; 142 143 if (topo_prop_get_string(node, 144 FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT, &plat, &err) < 0) { 145 (void) topo_mod_seterrno(mod, err); 146 return (NULL); 147 } 148 149 /* 150 * Trim SUNW, from the platform name 151 */ 152 pp = strchr(plat, ','); 153 if (pp == NULL) 154 pp = plat; 155 else 156 ++pp; 157 158 did_BDF(dp, NULL, &d, NULL); 159 if ((l = pci_physslot_name_lookup(pp, pdp)) == NULL) 160 if ((l = did_label(pdp, d)) != NULL) { 161 l = pci_slotname_rewrite(pp, l); 162 } else { 163 l = pci_missing_match(mod, pp, dp); 164 } 165 topo_mod_strfree(mod, plat); 166 return (l); 167 } 168 169 int 170 pci_label_cmn(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out) 171 { 172 uint64_t ptr; 173 const char *l; 174 did_t *dp, *pdp; 175 tnode_t *pnode; 176 char *nm; 177 int err; 178 179 /* 180 * If it's not a device or a PCI-express bus (which could potentially 181 * represent a slot, and therefore we might need to capture its slot 182 * name information), just inherit any label from our parent 183 */ 184 *out = NULL; 185 nm = topo_node_name(node); 186 if (strcmp(nm, PCI_DEVICE) != 0 && strcmp(nm, PCIEX_DEVICE) != 0 && 187 strcmp(nm, PCIEX_BUS) != 0) { 188 if (topo_node_label_set(node, NULL, &err) < 0) 189 if (err != ETOPO_PROP_NOENT) 190 return (topo_mod_seterrno(mod, err)); 191 return (0); 192 } 193 194 if (nvlist_lookup_uint64(in, TOPO_METH_LABEL_ARG_NVL, &ptr) != 0) { 195 topo_mod_dprintf(mod, 196 "label method argument not found.\n"); 197 return (-1); 198 } 199 dp = (did_t *)(uintptr_t)ptr; 200 pnode = did_gettnode(dp); 201 pdp = did_find(mod, topo_node_getspecific(pnode)); 202 203 /* 204 * Is there a slotname associated with the device? 205 */ 206 if ((l = pci_slotname_lookup(mod, node, dp, pdp)) != NULL) { 207 nvlist_t *rnvl; 208 209 if (topo_mod_nvalloc(mod, &rnvl, NV_UNIQUE_NAME) != 0 || 210 nvlist_add_string(rnvl, TOPO_METH_LABEL_RET_STR, l) != 0) 211 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); 212 *out = rnvl; 213 return (0); 214 } else { 215 if (topo_node_label_set(node, NULL, &err) < 0) 216 if (err != ETOPO_PROP_NOENT) 217 return (topo_mod_seterrno(mod, err)); 218 return (0); 219 } 220 } 221 222 int 223 pci_fru_cmn(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out) 224 { 225 int err = 0; 226 uint64_t ptr; 227 did_t *dp, *pdp; 228 tnode_t *pnode; 229 char *nm; 230 231 *out = NULL; 232 nm = topo_node_name(node); 233 if (strcmp(nm, PCI_DEVICE) != 0 && strcmp(nm, PCIEX_DEVICE) != 0 && 234 strcmp(nm, PCIEX_BUS) != 0) 235 return (0); 236 237 if (nvlist_lookup_uint64(in, "nv1", &ptr) != 0) { 238 topo_mod_dprintf(mod, 239 "label method argument not found.\n"); 240 return (-1); 241 } 242 dp = (did_t *)(uintptr_t)ptr; 243 pnode = did_gettnode(dp); 244 pdp = did_find(mod, topo_node_getspecific(pnode)); 245 246 /* 247 * Is there a slotname associated with the device? 248 */ 249 if (pci_slotname_lookup(mod, pnode, dp, pdp) != NULL) { 250 nvlist_t *rnvl; 251 252 if (topo_node_resource(node, &rnvl, &err) < 0 || rnvl == NULL) { 253 topo_mod_dprintf(mod, "pci_fru_compute error: %s\n", 254 topo_strerror(topo_mod_errno(mod))); 255 return (topo_mod_seterrno(mod, err)); 256 } 257 *out = rnvl; 258 } 259 return (0); 260 } 261