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 #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 return (NULL); 51 52 for (p = 0; p < Physlot_Names->psn_nplats; p++) { 53 if (strcmp(Physlot_Names->psn_names[p].pnm_platform, 54 platform) != 0) 55 continue; 56 for (i = 0; i < Physlot_Names->psn_names[p].pnm_nnames; i++) { 57 physnm_t ps; 58 ps = Physlot_Names->psn_names[p].pnm_names[i]; 59 if (ps.ps_num == n) { 60 rlabel = ps.ps_label; 61 break; 62 } 63 } 64 break; 65 } 66 return (rlabel); 67 } 68 69 static const char * 70 pci_slotname_rewrite(char *platform, const char *label) 71 { 72 const char *rlabel = label; 73 int s, i; 74 75 if (Slot_Rewrites == NULL) 76 return (rlabel); 77 78 for (s = 0; s < Slot_Rewrites->srw_nplats; s++) { 79 if (strcmp(Slot_Rewrites->srw_platrewrites[s].prw_platform, 80 platform) != 0) 81 continue; 82 for (i = 0; 83 i < Slot_Rewrites->srw_platrewrites[s].prw_nrewrites; 84 i++) { 85 slot_rwd_t rw; 86 rw = Slot_Rewrites->srw_platrewrites[s].prw_rewrites[i]; 87 if (strcmp(rw.srw_obp, label) == 0) { 88 rlabel = rw.srw_new; 89 break; 90 } 91 } 92 break; 93 } 94 assert(rlabel != NULL); 95 return (rlabel); 96 } 97 98 static const char * 99 pci_missing_match(topo_mod_t *mod, char *platform, did_t *dp) 100 { 101 const char *rlabel = NULL; 102 int board, bridge, rc, bus, dev; 103 int p, i; 104 105 if (Missing_Names == NULL) 106 return (NULL); 107 bridge = did_bridge(dp); 108 board = did_board(dp); 109 rc = did_rc(dp); 110 did_BDF(dp, &bus, &dev, NULL); 111 112 topo_mod_dprintf(mod, "Missing a name for %d, %d, %d, %d, %d ?\n", 113 board, bridge, rc, bus, dev); 114 115 for (p = 0; p < Missing_Names->mn_nplats; p++) { 116 if (strcmp(Missing_Names->mn_names[p].pdl_platform, 117 platform) != 0) 118 continue; 119 for (i = 0; i < Missing_Names->mn_names[p].pdl_nnames; i++) { 120 devlab_t m; 121 m = Missing_Names->mn_names[p].pdl_names[i]; 122 if (m.dl_board == board && m.dl_bridge == bridge && 123 m.dl_rc == rc && m.dl_bus == bus && 124 m.dl_dev == dev) { 125 rlabel = m.dl_label; 126 break; 127 } 128 } 129 break; 130 } 131 return (rlabel); 132 } 133 134 static const char * 135 pci_slotname_lookup(topo_mod_t *mod, tnode_t *node, did_t *dp) 136 { 137 const char *l; 138 char *plat, *pp; 139 int err; 140 int d; 141 142 if (topo_prop_get_string(node, 143 FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT, &plat, &err) < 0) { 144 (void) topo_mod_seterrno(mod, err); 145 return (NULL); 146 } 147 148 /* 149 * Trim SUNW, from the platform name 150 */ 151 pp = strchr(plat, ','); 152 ++pp; 153 154 did_BDF(dp, NULL, &d, NULL); 155 if ((l = pci_physslot_name_lookup(pp, dp)) == NULL) 156 if ((l = did_label(dp, d)) != NULL) { 157 l = pci_slotname_rewrite(pp, l); 158 } else { 159 l = pci_missing_match(mod, pp, dp); 160 } 161 topo_mod_strfree(mod, plat); 162 return (l); 163 } 164 165 int 166 pci_label_cmn(topo_mod_t *mod, tnode_t *node, nvlist_t *in, nvlist_t **out) 167 { 168 uint64_t ptr; 169 const char *l; 170 did_t *dp; 171 char *nm; 172 int err; 173 174 /* 175 * If it's not a device or a PCI-express bus (which could potentially 176 * represent a slot, and therefore we might need to capture its slot 177 * name information), just inherit any label from our parent 178 */ 179 *out = NULL; 180 nm = topo_node_name(node); 181 if (strcmp(nm, PCI_DEVICE) != 0 && strcmp(nm, PCIEX_DEVICE) != 0 && 182 strcmp(nm, PCIEX_BUS) != 0) { 183 if (topo_node_label_set(node, NULL, &err) < 0) 184 if (err != ETOPO_PROP_NOENT) 185 return (topo_mod_seterrno(mod, err)); 186 return (0); 187 } 188 189 if (nvlist_lookup_uint64(in, TOPO_METH_LABEL_ARG_NVL, &ptr) != 0) { 190 topo_mod_dprintf(mod, 191 "label method argument not found.\n"); 192 return (-1); 193 } 194 dp = (did_t *)(uintptr_t)ptr; 195 196 /* 197 * Is there a slotname associated with the device? 198 */ 199 if ((l = pci_slotname_lookup(mod, node, dp)) != NULL) { 200 nvlist_t *rnvl; 201 202 if (topo_mod_nvalloc(mod, &rnvl, NV_UNIQUE_NAME) != 0 || 203 nvlist_add_string(rnvl, TOPO_METH_LABEL_RET_STR, l) != 0) 204 return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); 205 *out = rnvl; 206 return (0); 207 } else { 208 if (topo_node_label_set(node, NULL, &err) < 0) 209 if (err != ETOPO_PROP_NOENT) 210 return (topo_mod_seterrno(mod, err)); 211 return (0); 212 } 213 } 214