145d3dd9Robert Mustacchi/*
245d3dd9Robert Mustacchi * This file and its contents are supplied under the terms of the
345d3dd9Robert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
445d3dd9Robert Mustacchi * You may only use this file in accordance with the terms of version
545d3dd9Robert Mustacchi * 1.0 of the CDDL.
645d3dd9Robert Mustacchi *
745d3dd9Robert Mustacchi * A full copy of the text of the CDDL should have accompanied this
845d3dd9Robert Mustacchi * source.  A copy of the CDDL is also available via the Internet at
945d3dd9Robert Mustacchi * http://www.illumos.org/license/CDDL.
1045d3dd9Robert Mustacchi */
1145d3dd9Robert Mustacchi
1245d3dd9Robert Mustacchi/*
138abca89Rob Johnston * Copyright (c) 2019, Joyent, Inc.
1445d3dd9Robert Mustacchi */
1545d3dd9Robert Mustacchi
1645d3dd9Robert Mustacchi#include <sys/fm/protocol.h>
1745d3dd9Robert Mustacchi#include <fm/topo_mod.h>
1845d3dd9Robert Mustacchi#include <fm/topo_list.h>
1945d3dd9Robert Mustacchi#include <fm/topo_method.h>
2045d3dd9Robert Mustacchi
2145d3dd9Robert Mustacchi#include <topo_port.h>
2245d3dd9Robert Mustacchi
2345d3dd9Robert Mustacchi/*
2445d3dd9Robert Mustacchi * Common routines to create port entries in the topology tree.
2545d3dd9Robert Mustacchi */
2645d3dd9Robert Mustacchi
2745d3dd9Robert Mustacchistatic const topo_pgroup_info_t port_pgroup = {
2845d3dd9Robert Mustacchi	TOPO_PGROUP_PORT,
2945d3dd9Robert Mustacchi	TOPO_STABILITY_PRIVATE,
3045d3dd9Robert Mustacchi	TOPO_STABILITY_PRIVATE,
3145d3dd9Robert Mustacchi	1
3245d3dd9Robert Mustacchi};
3345d3dd9Robert Mustacchi
348abca89Rob Johnstonstatic const topo_method_t port_methods[] = {
358abca89Rob Johnston	{ TOPO_METH_OCCUPIED, TOPO_METH_OCCUPIED_DESC,
368abca89Rob Johnston	    TOPO_METH_OCCUPIED_VERSION, TOPO_STABILITY_INTERNAL,
378abca89Rob Johnston	    topo_mod_hc_occupied },
388abca89Rob Johnston	{ NULL }
398abca89Rob Johnston};
408abca89Rob Johnston
4145d3dd9Robert Mustacchiint
4245d3dd9Robert Mustacchiport_range_create(topo_mod_t *mod, tnode_t *pnode, topo_instance_t min,
4345d3dd9Robert Mustacchi    topo_instance_t max)
4445d3dd9Robert Mustacchi{
4545d3dd9Robert Mustacchi	return (topo_node_range_create(mod, pnode, PORT, min, max));
4645d3dd9Robert Mustacchi}
4745d3dd9Robert Mustacchi
4845d3dd9Robert Mustacchi/*
4945d3dd9Robert Mustacchi * Create a port node, specifying the type of port it is. This will create the
5045d3dd9Robert Mustacchi * common port property group and populate it. The caller will need to populate
5145d3dd9Robert Mustacchi * the port-specific property group as needed.
5245d3dd9Robert Mustacchi */
5345d3dd9Robert Mustacchistatic tnode_t *
5445d3dd9Robert Mustacchiport_create_common(topo_mod_t *mod, tnode_t *pnode, topo_instance_t inst,
5545d3dd9Robert Mustacchi    const char *type)
5645d3dd9Robert Mustacchi{
5745d3dd9Robert Mustacchi	int err;
5845d3dd9Robert Mustacchi	tnode_t *tn = NULL;
5945d3dd9Robert Mustacchi	nvlist_t *fmri = NULL, *auth = NULL, *presource = NULL;
6045d3dd9Robert Mustacchi
6145d3dd9Robert Mustacchi	if (type == NULL) {
6245d3dd9Robert Mustacchi		topo_mod_dprintf(mod, "port_create_common missing type "
6345d3dd9Robert Mustacchi		    "argument\n");
6445d3dd9Robert Mustacchi		goto error;
6545d3dd9Robert Mustacchi	}
6645d3dd9Robert Mustacchi
6745d3dd9Robert Mustacchi	if ((auth = topo_mod_auth(mod, pnode)) == NULL) {
6845d3dd9Robert Mustacchi		topo_mod_dprintf(mod, "topo_mod_auth() failed: %s\n",
6945d3dd9Robert Mustacchi		    topo_mod_errmsg(mod));
7045d3dd9Robert Mustacchi		goto error;
7145d3dd9Robert Mustacchi	}
7245d3dd9Robert Mustacchi
7345d3dd9Robert Mustacchi	if ((fmri = topo_mod_hcfmri(mod, pnode, FM_HC_SCHEME_VERSION, PORT,
7445d3dd9Robert Mustacchi	    inst, NULL, auth, NULL, NULL, NULL)) == NULL) {
7545d3dd9Robert Mustacchi		topo_mod_dprintf(mod, "topo_mod_hcfmri() failed: %s\n",
7645d3dd9Robert Mustacchi		    topo_mod_errmsg(mod));
7745d3dd9Robert Mustacchi		goto error;
7845d3dd9Robert Mustacchi	}
7945d3dd9Robert Mustacchi
8045d3dd9Robert Mustacchi	if ((tn = topo_node_bind(mod, pnode, PORT, inst, fmri)) == NULL) {
8145d3dd9Robert Mustacchi		topo_mod_dprintf(mod, "topo_node_bind() failed: %s\n",
8245d3dd9Robert Mustacchi		    topo_mod_errmsg(mod));
8345d3dd9Robert Mustacchi		goto error;
8445d3dd9Robert Mustacchi	}
8545d3dd9Robert Mustacchi
8645d3dd9Robert Mustacchi	/*
8745d3dd9Robert Mustacchi	 * The FRU is always set to the FMRI of the parent device for a port.
8845d3dd9Robert Mustacchi	 */
8945d3dd9Robert Mustacchi	if (topo_node_resource(pnode, &presource, &err) != 0) {
9045d3dd9Robert Mustacchi		topo_mod_dprintf(mod, "topo_node_resource() failed: %s\n",
9145d3dd9Robert Mustacchi		    topo_strerror(err));
9245d3dd9Robert Mustacchi		goto error;
9345d3dd9Robert Mustacchi	}
9445d3dd9Robert Mustacchi
9545d3dd9Robert Mustacchi	if (topo_node_fru_set(tn, presource, 0, &err) != 0) {
9645d3dd9Robert Mustacchi		topo_mod_dprintf(mod, "topo_node_fru_set() failed: %s\n",
9745d3dd9Robert Mustacchi		    topo_strerror(err));
9845d3dd9Robert Mustacchi		goto error;
9945d3dd9Robert Mustacchi	}
10045d3dd9Robert Mustacchi
10145d3dd9Robert Mustacchi	if (topo_pgroup_create(tn, &port_pgroup, &err) != 0) {
10245d3dd9Robert Mustacchi		topo_mod_dprintf(mod, "failed to create property group %s: "
10345d3dd9Robert Mustacchi		    "%s\n", TOPO_PGROUP_PORT, topo_strerror(err));
10445d3dd9Robert Mustacchi		goto error;
10545d3dd9Robert Mustacchi	}
10645d3dd9Robert Mustacchi
10745d3dd9Robert Mustacchi	if (topo_prop_set_string(tn, TOPO_PGROUP_PORT, TOPO_PROP_PORT_TYPE,
10845d3dd9Robert Mustacchi	    TOPO_PROP_IMMUTABLE, type, &err) != 0) {
10945d3dd9Robert Mustacchi		topo_mod_dprintf(mod, "failed to set %s property: %s\n",
11045d3dd9Robert Mustacchi		    TOPO_PROP_PORT_TYPE, topo_strerror(err));
11145d3dd9Robert Mustacchi		goto error;
11245d3dd9Robert Mustacchi	}
11345d3dd9Robert Mustacchi
1148abca89Rob Johnston	if (topo_method_register(mod, tn, port_methods) != 0) {
1158abca89Rob Johnston		topo_mod_dprintf(mod, "topo_method_register() failed on "
1168abca89Rob Johnston		    "%s=%d: %s", PORT, inst, topo_mod_errmsg(mod));
1178abca89Rob Johnston		/* errno set */
1188abca89Rob Johnston		goto error;
1198abca89Rob Johnston	}
1208abca89Rob Johnston
12145d3dd9Robert Mustacchi	nvlist_free(fmri);
12245d3dd9Robert Mustacchi	nvlist_free(auth);
12345d3dd9Robert Mustacchi	nvlist_free(presource);
12445d3dd9Robert Mustacchi	return (tn);
12545d3dd9Robert Mustacchierror:
12645d3dd9Robert Mustacchi	topo_node_unbind(tn);
12745d3dd9Robert Mustacchi	nvlist_free(fmri);
12845d3dd9Robert Mustacchi	nvlist_free(auth);
12945d3dd9Robert Mustacchi	nvlist_free(presource);
13045d3dd9Robert Mustacchi	return (NULL);
13145d3dd9Robert Mustacchi}
13245d3dd9Robert Mustacchi
13345d3dd9Robert Mustacchiint
13445d3dd9Robert Mustacchiport_create_sff(topo_mod_t *mod, tnode_t *pnode, topo_instance_t inst,
13545d3dd9Robert Mustacchi    tnode_t **nodep)
13645d3dd9Robert Mustacchi{
13745d3dd9Robert Mustacchi	tnode_t *tn;
13845d3dd9Robert Mustacchi
13945d3dd9Robert Mustacchi	tn = port_create_common(mod, pnode, inst, TOPO_PROP_PORT_TYPE_SFF);
14045d3dd9Robert Mustacchi	if (tn == NULL)
14145d3dd9Robert Mustacchi		return (-1);
14245d3dd9Robert Mustacchi	*nodep = tn;
14345d3dd9Robert Mustacchi	return (0);
14445d3dd9Robert Mustacchi}
145672fc84Robert Mustacchi
146672fc84Robert Mustacchiint
147672fc84Robert Mustacchiport_create_usb(topo_mod_t *mod, tnode_t *pnode, topo_instance_t inst,
148672fc84Robert Mustacchi    tnode_t **nodep)
149672fc84Robert Mustacchi{
150672fc84Robert Mustacchi	tnode_t *tn;
151672fc84Robert Mustacchi
152672fc84Robert Mustacchi	tn = port_create_common(mod, pnode, inst, TOPO_PROP_PORT_TYPE_USB);
153672fc84Robert Mustacchi	if (tn == NULL)
154672fc84Robert Mustacchi		return (-1);
155672fc84Robert Mustacchi	*nodep = tn;
156672fc84Robert Mustacchi	return (0);
157672fc84Robert Mustacchi}
1588a2b682Robert Mustacchi
1598a2b682Robert Mustacchiint
1608a2b682Robert Mustacchiport_create_unknown(topo_mod_t *mod, tnode_t *pnode, topo_instance_t inst,
1618a2b682Robert Mustacchi    tnode_t **nodep)
1628a2b682Robert Mustacchi{
1638a2b682Robert Mustacchi	tnode_t *tn;
1648a2b682Robert Mustacchi
1658a2b682Robert Mustacchi	tn = port_create_common(mod, pnode, inst, TOPO_PROP_PORT_TYPE_UNKNOWN);
1668a2b682Robert Mustacchi	if (tn == NULL)
1678a2b682Robert Mustacchi		return (-1);
1688a2b682Robert Mustacchi	*nodep = tn;
1698a2b682Robert Mustacchi	return (0);
1708a2b682Robert Mustacchi}
171