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 <stdlib.h> 30 #include <string.h> 31 #include <strings.h> 32 #include <sys/fm/protocol.h> 33 #include <fm/topo_mod.h> 34 #include <fm/topo_hc.h> 35 #include <fm/libtopo.h> 36 37 int 38 child_range_add(topo_mod_t *mp, tnode_t *tn, const char *cnm, 39 topo_instance_t imin, topo_instance_t imax) 40 { 41 int e; 42 43 e = topo_node_range_create(mp, tn, cnm, imin, imax); 44 if (e != 0) { 45 topo_mod_dprintf(mp, "add child range (%s) failed: %s\n", 46 cnm, topo_strerror(topo_mod_errno(mp))); 47 return (-1); 48 } 49 return (0); 50 } 51 52 ulong_t 53 strtonum(topo_mod_t *mp, char *str, int *err) 54 { 55 ulong_t r; 56 char *e; 57 58 r = strtoul(str, &e, 16); 59 if (e == str) { 60 topo_mod_dprintf(mp, 61 "Trouble converting %s to a number!\n", str); 62 *err = -1; 63 return (0); 64 } 65 *err = 0; 66 return (r); 67 } 68 69 static int 70 get_pci_vpd_sn_pn(topo_mod_t *mp, di_node_t dn, char **serial, char **part) 71 { 72 char *s = NULL, *p = NULL; 73 di_prom_handle_t promtree = DI_PROM_HANDLE_NIL; 74 75 if ((promtree = topo_mod_prominfo(mp)) == DI_PROM_HANDLE_NIL) { 76 topo_mod_dprintf(mp, 77 "get vpd data: di_prom_handle_init failed.\n"); 78 return (-1); 79 } 80 81 /* Get Serial Number and Part Number */ 82 if ((di_prom_prop_lookup_bytes(promtree, dn, "vpd-serial-number", 83 (uchar_t **)&s) > 0) && (s != NULL)) 84 *serial = topo_mod_strdup(mp, s); 85 86 if ((di_prom_prop_lookup_bytes(promtree, dn, "vpd-part-number", 87 (uchar_t **)&p) > 0) && (p != NULL)) 88 *part = topo_mod_strdup(mp, p); 89 90 return (0); 91 } 92 93 tnode_t * 94 tnode_create(topo_mod_t *mp, tnode_t *parent, 95 const char *name, topo_instance_t i, void *priv) 96 { 97 nvlist_t *fmri; 98 tnode_t *ntn; 99 nvlist_t *auth; 100 char *serial = NULL, *part = NULL; 101 102 auth = topo_mod_auth(mp, parent); 103 /* 104 * Get PCI/PCIEX Device Serial Number and Part Number 105 * from PCI VPD 106 */ 107 if ((strcmp(name, PCI_DEVICE) == 0) || 108 (strcmp(name, PCIEX_DEVICE) == 0)) 109 (void) get_pci_vpd_sn_pn(mp, priv, &serial, &part); 110 111 fmri = topo_mod_hcfmri(mp, parent, FM_HC_SCHEME_VERSION, name, i, NULL, 112 auth, part, NULL, serial); 113 nvlist_free(auth); 114 topo_mod_strfree(mp, serial); 115 topo_mod_strfree(mp, part); 116 117 if (fmri == NULL) { 118 topo_mod_dprintf(mp, 119 "Unable to make nvlist for %s bind.\n", name); 120 return (NULL); 121 } 122 123 ntn = topo_node_bind(mp, parent, name, i, fmri); 124 if (ntn == NULL) { 125 topo_mod_dprintf(mp, 126 "topo_node_bind (%s%d/%s%d) failed: %s\n", 127 topo_node_name(parent), topo_node_instance(parent), 128 name, i, 129 topo_strerror(topo_mod_errno(mp))); 130 nvlist_free(fmri); 131 return (NULL); 132 } 133 nvlist_free(fmri); 134 topo_node_setspecific(ntn, priv); 135 136 return (ntn); 137 } 138 139 /*ARGSUSED*/ 140 int 141 labelmethod_inherit(topo_mod_t *mp, tnode_t *tn, nvlist_t *in, nvlist_t **out) 142 { 143 int err; 144 145 /* 146 * Ignore the input and output nvlists and directly set the 147 * label as inheritance from the parent 148 */ 149 *out = NULL; 150 if (topo_node_label_set(tn, NULL, &err) < 0) { 151 if (err != ETOPO_PROP_NOENT) 152 return (topo_mod_seterrno(mp, err)); 153 } 154 return (0); 155 } 156