1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright (c) 2019, Joyent, Inc. 14 */ 15 16 #include <sys/fm/protocol.h> 17 #include <fm/topo_mod.h> 18 #include <fm/topo_list.h> 19 #include <fm/topo_method.h> 20 21 #include <topo_port.h> 22 23 /* 24 * Common routines to create port entries in the topology tree. 25 */ 26 27 static const topo_pgroup_info_t port_pgroup = { 28 TOPO_PGROUP_PORT, 29 TOPO_STABILITY_PRIVATE, 30 TOPO_STABILITY_PRIVATE, 31 1 32 }; 33 34 static const topo_method_t port_methods[] = { 35 { TOPO_METH_OCCUPIED, TOPO_METH_OCCUPIED_DESC, 36 TOPO_METH_OCCUPIED_VERSION, TOPO_STABILITY_INTERNAL, 37 topo_mod_hc_occupied }, 38 { NULL } 39 }; 40 41 int 42 port_range_create(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min, 43 topo_instance_t max) 44 { 45 return (topo_node_range_create(mod, pnode, PORT, min, max)); 46 } 47 48 /* 49 * Create a port node, specifying the type of port it is. This will create the 50 * common port property group and populate it. The caller will need to populate 51 * the port-specific property group as needed. 52 */ 53 static tnode_t * 54 port_create_common(topo_mod_t *mod, tnode_t *pnode, topo_instance_t inst, 55 const char *type) 56 { 57 int err; 58 tnode_t *tn = NULL; 59 nvlist_t *fmri = NULL, *auth = NULL, *presource = NULL; 60 61 if (type == NULL) { 62 topo_mod_dprintf(mod, "port_create_common missing type " 63 "argument\n"); 64 goto error; 65 } 66 67 if ((auth = topo_mod_auth(mod, pnode)) == NULL) { 68 topo_mod_dprintf(mod, "topo_mod_auth() failed: %s\n", 69 topo_mod_errmsg(mod)); 70 goto error; 71 } 72 73 if ((fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION, PORT, 74 inst, NULL, auth, NULL, NULL, NULL)) == NULL) { 75 topo_mod_dprintf(mod, "topo_mod_hcfmri() failed: %s\n", 76 topo_mod_errmsg(mod)); 77 goto error; 78 } 79 80 if ((tn = topo_node_bind(mod, pnode, PORT, inst, fmri)) == NULL) { 81 topo_mod_dprintf(mod, "topo_node_bind() failed: %s\n", 82 topo_mod_errmsg(mod)); 83 goto error; 84 } 85 86 /* 87 * The FRU is always set to the FMRI of the parent device for a port. 88 */ 89 if (topo_node_resource(pnode, &presource, &err) != 0) { 90 topo_mod_dprintf(mod, "topo_node_resource() failed: %s\n", 91 topo_strerror(err)); 92 goto error; 93 } 94 95 if (topo_node_fru_set(tn, presource, 0, &err) != 0) { 96 topo_mod_dprintf(mod, "topo_node_fru_set() failed: %s\n", 97 topo_strerror(err)); 98 goto error; 99 } 100 101 if (topo_pgroup_create(tn, &port_pgroup, &err) != 0) { 102 topo_mod_dprintf(mod, "failed to create property group %s: " 103 "%s\n", TOPO_PGROUP_PORT, topo_strerror(err)); 104 goto error; 105 } 106 107 if (topo_prop_set_string(tn, TOPO_PGROUP_PORT, TOPO_PROP_PORT_TYPE, 108 TOPO_PROP_IMMUTABLE, type, &err) != 0) { 109 topo_mod_dprintf(mod, "failed to set %s property: %s\n", 110 TOPO_PROP_PORT_TYPE, topo_strerror(err)); 111 goto error; 112 } 113 114 if (topo_method_register(mod, tn, port_methods) != 0) { 115 topo_mod_dprintf(mod, "topo_method_register() failed on " 116 "%s=%" PRIu64 ": %s", PORT, inst, topo_mod_errmsg(mod)); 117 /* errno set */ 118 goto error; 119 } 120 121 nvlist_free(fmri); 122 nvlist_free(auth); 123 nvlist_free(presource); 124 return (tn); 125 error: 126 topo_node_unbind(tn); 127 nvlist_free(fmri); 128 nvlist_free(auth); 129 nvlist_free(presource); 130 return (NULL); 131 } 132 133 int 134 port_create_sff(topo_mod_t *mod, tnode_t *pnode, topo_instance_t inst, 135 tnode_t **nodep) 136 { 137 tnode_t *tn; 138 139 tn = port_create_common(mod, pnode, inst, TOPO_PROP_PORT_TYPE_SFF); 140 if (tn == NULL) 141 return (-1); 142 *nodep = tn; 143 return (0); 144 } 145 146 int 147 port_create_usb(topo_mod_t *mod, tnode_t *pnode, topo_instance_t inst, 148 tnode_t **nodep) 149 { 150 tnode_t *tn; 151 152 tn = port_create_common(mod, pnode, inst, TOPO_PROP_PORT_TYPE_USB); 153 if (tn == NULL) 154 return (-1); 155 *nodep = tn; 156 return (0); 157 } 158 159 int 160 port_create_unknown(topo_mod_t *mod, tnode_t *pnode, topo_instance_t inst, 161 tnode_t **nodep) 162 { 163 tnode_t *tn; 164 165 tn = port_create_common(mod, pnode, inst, TOPO_PROP_PORT_TYPE_UNKNOWN); 166 if (tn == NULL) 167 return (-1); 168 *nodep = tn; 169 return (0); 170 } 171