xref: /illumos-gate/usr/src/lib/libv12n/sparc/libv12n.c (revision d0b12b66)
182629e30SMike Christensen /*
282629e30SMike Christensen  * CDDL HEADER START
382629e30SMike Christensen  *
482629e30SMike Christensen  * The contents of this file are subject to the terms of the
582629e30SMike Christensen  * Common Development and Distribution License (the "License").
682629e30SMike Christensen  * You may not use this file except in compliance with the License.
782629e30SMike Christensen  *
882629e30SMike Christensen  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
982629e30SMike Christensen  * or http://www.opensolaris.org/os/licensing.
1082629e30SMike Christensen  * See the License for the specific language governing permissions
1182629e30SMike Christensen  * and limitations under the License.
1282629e30SMike Christensen  *
1382629e30SMike Christensen  * When distributing Covered Code, include this CDDL HEADER in each
1482629e30SMike Christensen  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1582629e30SMike Christensen  * If applicable, add the following below this CDDL HEADER, with the
1682629e30SMike Christensen  * fields enclosed by brackets "[]" replaced with your own identifying
1782629e30SMike Christensen  * information: Portions Copyright [yyyy] [name of copyright owner]
1882629e30SMike Christensen  *
1982629e30SMike Christensen  * CDDL HEADER END
2082629e30SMike Christensen  */
2182629e30SMike Christensen /*
221a024a48SMike Christensen  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2382629e30SMike Christensen  */
2482629e30SMike Christensen 
2582629e30SMike Christensen #include <dlfcn.h>
2682629e30SMike Christensen #include <errno.h>
2782629e30SMike Christensen #include <fcntl.h>
2882629e30SMike Christensen #include <stdio.h>
2982629e30SMike Christensen #include <stdlib.h>
3082629e30SMike Christensen #include <strings.h>
3182629e30SMike Christensen #include <synch.h>
3282629e30SMike Christensen #include <thread.h>
3382629e30SMike Christensen #include <unistd.h>
3482629e30SMike Christensen #include <utility.h>
3582629e30SMike Christensen #include <sys/mdesc.h>
3682629e30SMike Christensen #include <sys/mdesc_impl.h>
3782629e30SMike Christensen #include <sys/debug.h>
3882629e30SMike Christensen #include <sys/stat.h>
3982629e30SMike Christensen #include <sys/types.h>
4082629e30SMike Christensen #include <sys/utsname.h>
4182629e30SMike Christensen 
4282629e30SMike Christensen #include "ldma.h"
4382629e30SMike Christensen #include "libds.h"
4482629e30SMike Christensen #include "libv12n.h"
4582629e30SMike Christensen 
4682629e30SMike Christensen /*
4782629e30SMike Christensen  * sun4 support for libv12n.
4882629e30SMike Christensen  *
4982629e30SMike Christensen  * Non-sun4v support is minimal.  The v12n_capabilities() function will
5082629e30SMike Christensen  * only return 0 (not supported, not enabled, no implementation).
5182629e30SMike Christensen  *
5282629e30SMike Christensen  * For sun4v the support for v12n_capabilities(), v12n_domain_roles(),
5382629e30SMike Christensen  * v12n_domain_name() and v12n_domain_uuid() are supported by scanning the
5482629e30SMike Christensen  * MD from /dev/mdesc for specific properties.  For v12n_ctrl_domain() and
5582629e30SMike Christensen  * v12n_chassis_serialno(), the ldoms agent daemon (ldmad) on the control
5682629e30SMike Christensen  * domain supplies the required information via the "agent-system" domain
5782629e30SMike Christensen  * service.
5882629e30SMike Christensen  */
5982629e30SMike Christensen 
6082629e30SMike Christensen /* libds statics */
6182629e30SMike Christensen static void *v12n_ds_dlhdl = NULL;
6282629e30SMike Christensen static int (*v12n_ds_send_msg)(ds_hdl_t, void *, size_t) = NULL;
6382629e30SMike Christensen static int (*v12n_ds_clnt_reg)(ds_capability_t *, ds_ops_t *);
6482629e30SMike Christensen static int (*v12n_ds_unreg_svc)(char *, boolean_t);
6582629e30SMike Christensen 
6682629e30SMike Christensen /*
6782629e30SMike Christensen  * Defines to support the 'agent-system' domain service.
6882629e30SMike Christensen  */
6982629e30SMike Christensen 
7082629e30SMike Christensen #define	LDMA_SYSTEM_NVERS		\
7182629e30SMike Christensen 			(sizeof (v12n_ldma_system_vers) / sizeof (ds_ver_t))
7282629e30SMike Christensen static ds_ver_t v12n_ldma_system_vers[] = { { 1, 0} };
7382629e30SMike Christensen 
7482629e30SMike Christensen static ds_capability_t v12n_ldma_cap = {
7582629e30SMike Christensen 	LDMA_NAME_SYSTEM,	/* svc_id */
7682629e30SMike Christensen 	v12n_ldma_system_vers,	/* vers */
7782629e30SMike Christensen 	LDMA_SYSTEM_NVERS	/* nvers */
7882629e30SMike Christensen };
7982629e30SMike Christensen 
8082629e30SMike Christensen static void v12n_ldma_register_handler(ds_hdl_t hdl, ds_cb_arg_t arg,
8182629e30SMike Christensen     ds_ver_t *ver, ds_domain_hdl_t dhdl);
8282629e30SMike Christensen static void v12n_ldma_data_handler(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf,
8382629e30SMike Christensen     size_t buflen);
8482629e30SMike Christensen 
8582629e30SMike Christensen static ds_ops_t v12n_ldma_ops = {
8682629e30SMike Christensen 	v12n_ldma_register_handler,	/* ds_reg_cb */
8782629e30SMike Christensen 	NULL,				/* ds_unreg_cb */
8882629e30SMike Christensen 	v12n_ldma_data_handler,		/* ds_data_cb */
8982629e30SMike Christensen 	NULL				/* ds_cb_arg */
9082629e30SMike Christensen };
9182629e30SMike Christensen 
9282629e30SMike Christensen /* v12n_ldma_cv_state values */
9382629e30SMike Christensen #define	V12N_LDMA_CVINVALID	-1	/* invalid value for cv_state */
9482629e30SMike Christensen #define	V12N_LDMA_REGWAITING	0	/* waiting for ctrl domain reg */
9582629e30SMike Christensen #define	V12N_LDMA_REGRECEIVED	1	/* received ctrl domain reg */
9682629e30SMike Christensen #define	V12N_LDMA_MSGWAITING	2	/* waiting for message response */
9782629e30SMike Christensen #define	V12N_LDMA_MSGRECEIVED	3	/* received message response */
9882629e30SMike Christensen #define	V12N_LDMA_MSGERROR	4	/* received a bad message */
9982629e30SMike Christensen 
10082629e30SMike Christensen /* 'agent-system' data used in async registration/data message handlers */
10182629e30SMike Christensen static ds_hdl_t v12n_ldma_ctrl_hdl = DS_INVALID_HDL;
10282629e30SMike Christensen static int v12n_ldma_msgtype;
10382629e30SMike Christensen static char *v12n_ldma_msgstr;
10482629e30SMike Christensen static mutex_t v12n_ldma_lock = DEFAULTMUTEX;
10582629e30SMike Christensen static cond_t v12n_ldma_cv = DEFAULTCV;
10682629e30SMike Christensen static int v12n_ldma_cv_state = V12N_LDMA_CVINVALID;
10782629e30SMike Christensen static mutex_t v12n_ldma_cv_lock = DEFAULTMUTEX;
10882629e30SMike Christensen 
10982629e30SMike Christensen /* 'agent-system' timeout values in seconds */
11082629e30SMike Christensen static int v12n_ldma_timeout = 15;
11182629e30SMike Christensen static int v12n_ldma_sleeptime = 1;
11282629e30SMike Christensen 
11382629e30SMike Christensen 
11482629e30SMike Christensen #define	V12N_LDOMS_SUPPORTED	(V12N_CAP_SUPPORTED | V12N_CAP_ENABLED | \
11582629e30SMike Christensen 				    V12N_CAP_IMPL_LDOMS)
11682629e30SMike Christensen 
11782629e30SMike Christensen #define	MD_DEVICE		"/dev/mdesc"
11882629e30SMike Christensen 
11982629e30SMike Christensen /*
12082629e30SMike Christensen  * libv12n routines to support /dev/mdesc.
12182629e30SMike Christensen  */
12282629e30SMike Christensen 
12382629e30SMike Christensen /*
12482629e30SMike Christensen  * Wrapper for MD free: need unused size argument.
12582629e30SMike Christensen  */
12682629e30SMike Christensen /* ARGSUSED */
12782629e30SMike Christensen static void
v12n_md_free(void * buf,size_t n)12882629e30SMike Christensen v12n_md_free(void *buf, size_t n)
12982629e30SMike Christensen {
13082629e30SMike Christensen 	free(buf);
13182629e30SMike Christensen }
13282629e30SMike Christensen 
13382629e30SMike Christensen /*
13482629e30SMike Christensen  * Wrapper for MD init: read MD and invoke md_init_intern.
13582629e30SMike Christensen  */
13682629e30SMike Christensen static md_t *
v12n_md_init()13782629e30SMike Christensen v12n_md_init()
13882629e30SMike Christensen {
13982629e30SMike Christensen 	md_t *mdp;
14082629e30SMike Christensen 	char *buf = NULL;
14182629e30SMike Christensen 	md_header_t mdh;
14282629e30SMike Christensen 	int md_size;
14382629e30SMike Christensen 	int fd;
14482629e30SMike Christensen 
14582629e30SMike Christensen 	/*
14682629e30SMike Christensen 	 * Open the Machine Description (MD)
14782629e30SMike Christensen 	 */
14882629e30SMike Christensen 	fd = open(MD_DEVICE, O_RDONLY);
14982629e30SMike Christensen 	if (fd == -1) {
15082629e30SMike Christensen 		return (NULL);
15182629e30SMike Christensen 	}
15282629e30SMike Christensen 
15382629e30SMike Christensen 	if (read(fd, &mdh, sizeof (md_header_t)) != sizeof (md_header_t))
15482629e30SMike Christensen 		goto errdone;
15582629e30SMike Christensen 
15682629e30SMike Christensen 	md_size = sizeof (md_header_t) + mdh.node_blk_sz + mdh.name_blk_sz +
15782629e30SMike Christensen 	    mdh.data_blk_sz;
15882629e30SMike Christensen 
15982629e30SMike Christensen 	if ((buf = malloc(md_size)) == NULL)
16082629e30SMike Christensen 		goto errdone;
16182629e30SMike Christensen 
16282629e30SMike Christensen 	(void) memcpy(buf, &mdh, sizeof (md_header_t));
16382629e30SMike Christensen 	if (read(fd, buf + sizeof (md_header_t),
16482629e30SMike Christensen 	    md_size - sizeof (md_header_t)) != md_size - sizeof (md_header_t)) {
16582629e30SMike Christensen 		goto errdone;
16682629e30SMike Christensen 	}
16782629e30SMike Christensen 
16882629e30SMike Christensen 	mdp = md_init_intern((uint64_t *)((void *)buf), malloc, v12n_md_free);
16982629e30SMike Christensen 
17082629e30SMike Christensen 	(void) close(fd);
17182629e30SMike Christensen 
17282629e30SMike Christensen 	return (mdp);
17382629e30SMike Christensen 
17482629e30SMike Christensen errdone:
17582629e30SMike Christensen 	(void) close(fd);
17682629e30SMike Christensen 	free(buf);
17782629e30SMike Christensen 
17882629e30SMike Christensen 	return (NULL);
17982629e30SMike Christensen }
18082629e30SMike Christensen 
18182629e30SMike Christensen /*
18282629e30SMike Christensen  * Wrapper for md_fini.  Allow NULL md ptr and free MD buffer.
18382629e30SMike Christensen  */
18482629e30SMike Christensen static void
v12n_md_fini(void * md)18582629e30SMike Christensen v12n_md_fini(void *md)
18682629e30SMike Christensen {
18782629e30SMike Christensen 	md_impl_t *mdp = (md_impl_t *)md;
18882629e30SMike Christensen 
18982629e30SMike Christensen 	if (mdp) {
19082629e30SMike Christensen 		free(mdp->caddr);
19182629e30SMike Christensen 		(void) md_fini(md);
19282629e30SMike Christensen 	}
19382629e30SMike Christensen }
19482629e30SMike Christensen 
19582629e30SMike Christensen /*
19682629e30SMike Christensen  * See if LDoms domaining is enabled, returns 1 if enabled.
19782629e30SMike Christensen  * Get the value of the 'domaining-enabled' property under the
19882629e30SMike Christensen  * 'platform' node.  Value of 1 => domaining is enabled.
19982629e30SMike Christensen  */
20082629e30SMike Christensen static int
v12n_domaining_enabled()20182629e30SMike Christensen v12n_domaining_enabled()
20282629e30SMike Christensen {
20382629e30SMike Christensen 	mde_cookie_t *nodes, rootnode;
20482629e30SMike Christensen 	int nnodes;
20582629e30SMike Christensen 	uint64_t prop_val = 0;
20682629e30SMike Christensen 	md_t *mdp;
20782629e30SMike Christensen 
20882629e30SMike Christensen 	if ((mdp = v12n_md_init()) == NULL) {
20982629e30SMike Christensen 		return (0);
21082629e30SMike Christensen 	}
21182629e30SMike Christensen 
21282629e30SMike Christensen 	nnodes = md_node_count(mdp);
21382629e30SMike Christensen 	nodes = malloc(nnodes * sizeof (mde_cookie_t));
21482629e30SMike Christensen 	if (nodes == NULL) {
21582629e30SMike Christensen 		v12n_md_fini(mdp);
21682629e30SMike Christensen 		return (0);
21782629e30SMike Christensen 	}
21882629e30SMike Christensen 
21982629e30SMike Christensen 	rootnode = md_root_node(mdp);
22082629e30SMike Christensen 
22182629e30SMike Christensen 	nnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"),
22282629e30SMike Christensen 	    md_find_name(mdp, "fwd"), nodes);
22382629e30SMike Christensen 
22482629e30SMike Christensen 	if (nnodes >= 1) {
22582629e30SMike Christensen 		(void) md_get_prop_val(mdp, nodes[0], "domaining-enabled",
22682629e30SMike Christensen 		    &prop_val);
22782629e30SMike Christensen 	}
22882629e30SMike Christensen 
22982629e30SMike Christensen 	v12n_md_fini(mdp);
23082629e30SMike Christensen 	free(nodes);
23182629e30SMike Christensen 	return (prop_val == 1);
23282629e30SMike Christensen }
23382629e30SMike Christensen 
23482629e30SMike Christensen int
v12n_capabilities()23582629e30SMike Christensen v12n_capabilities()
23682629e30SMike Christensen {
23782629e30SMike Christensen 	struct utsname uinfo;
23882629e30SMike Christensen 	struct stat st;
23982629e30SMike Christensen 	int cap;
24082629e30SMike Christensen 
24182629e30SMike Christensen 	/*
24282629e30SMike Christensen 	 * Check if this is an LDoms system. When using LDoms each
24382629e30SMike Christensen 	 * domain should have a /dev/mdesc device providing access to
24482629e30SMike Christensen 	 * the Machine Description (MD) of the domain. If this device
24582629e30SMike Christensen 	 * does not exist then this is not an LDoms system.
24682629e30SMike Christensen 	 */
24782629e30SMike Christensen 	if (uname(&uinfo) == -1 || strcmp(uinfo.machine, "sun4v")) {
24882629e30SMike Christensen 		/*
24982629e30SMike Christensen 		 * Not sun4v -> LDoms not supported
25082629e30SMike Christensen 		 */
25182629e30SMike Christensen 		cap = 0;
25282629e30SMike Christensen 	} else if (stat(MD_DEVICE, &st) == 0) {
25382629e30SMike Christensen 		/*
25482629e30SMike Christensen 		 * sun4v + /dev/mdesc exists -> Check if LDoms enabled
25582629e30SMike Christensen 		 * via the 'domaining-enabled' property.
25682629e30SMike Christensen 		 */
25782629e30SMike Christensen 		cap = (V12N_CAP_SUPPORTED | V12N_CAP_IMPL_LDOMS |
25882629e30SMike Christensen 		    (v12n_domaining_enabled() ? V12N_CAP_ENABLED : 0));
25982629e30SMike Christensen 	} else if (errno == ENOENT) {
26082629e30SMike Christensen 		/*
26182629e30SMike Christensen 		 * sun4v + /dev/mdesc does not exist -> LDoms supported
26282629e30SMike Christensen 		 * but not enabled.
26382629e30SMike Christensen 		 */
26482629e30SMike Christensen 		cap = (V12N_CAP_SUPPORTED | V12N_CAP_IMPL_LDOMS);
26582629e30SMike Christensen 	}
26682629e30SMike Christensen 
26782629e30SMike Christensen 	return (cap);
26882629e30SMike Christensen }
26982629e30SMike Christensen 
27082629e30SMike Christensen /*
27182629e30SMike Christensen  * Routines to support v12n_domain_roles.
27282629e30SMike Christensen  */
27382629e30SMike Christensen static int
v12n_scan_md_nodes(md_t * mdp,char * node_name,char * node_str_prop,char ** props)27482629e30SMike Christensen v12n_scan_md_nodes(md_t *mdp, char *node_name, char *node_str_prop,
27582629e30SMike Christensen     char **props)
27682629e30SMike Christensen {
27782629e30SMike Christensen 	mde_cookie_t *nodes, rootnode;
27882629e30SMike Christensen 	int nnodes, i, j;
27982629e30SMike Christensen 	char *prop_str;
28082629e30SMike Christensen 
28182629e30SMike Christensen 	nnodes = md_node_count(mdp);
28282629e30SMike Christensen 	nodes = malloc(nnodes * sizeof (mde_cookie_t));
28382629e30SMike Christensen 	if (nodes == NULL) {
28482629e30SMike Christensen 		return (0);
28582629e30SMike Christensen 	}
28682629e30SMike Christensen 
28782629e30SMike Christensen 	rootnode = md_root_node(mdp);
28882629e30SMike Christensen 
28982629e30SMike Christensen 	nnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, node_name),
29082629e30SMike Christensen 	    md_find_name(mdp, "fwd"), nodes);
29182629e30SMike Christensen 
29282629e30SMike Christensen 	if (node_str_prop == NULL)
29382629e30SMike Christensen 		return (nnodes > 0);
29482629e30SMike Christensen 
29582629e30SMike Christensen 	for (i = 0; i < nnodes; i++) {
29682629e30SMike Christensen 		if (md_get_prop_str(mdp, nodes[i], node_str_prop, &prop_str))
29782629e30SMike Christensen 			continue;
29882629e30SMike Christensen 		for (j = 0; props[j] != NULL; j++) {
29982629e30SMike Christensen 			if (strcmp(prop_str, props[j]) == 0) {
30082629e30SMike Christensen 				free(nodes);
30182629e30SMike Christensen 				return (1);
30282629e30SMike Christensen 			}
30382629e30SMike Christensen 		}
30482629e30SMike Christensen 	}
30582629e30SMike Christensen 	free(nodes);
30682629e30SMike Christensen 	return (0);
30782629e30SMike Christensen }
30882629e30SMike Christensen 
30982629e30SMike Christensen /*
31082629e30SMike Christensen  * Check if MD has a hypervisor access point, returns 1 if true.
31182629e30SMike Christensen  * Check the MD for a 'virtual-device-port' node whose 'vldc-svc-name' is
31282629e30SMike Christensen  * 'hvctl'.
31382629e30SMike Christensen  */
31482629e30SMike Christensen static int
v12n_check_hv_access(md_t * mdp)31582629e30SMike Christensen v12n_check_hv_access(md_t *mdp)
31682629e30SMike Christensen {
31782629e30SMike Christensen 	static char *hvctl_str[] = {
31882629e30SMike Christensen 		"hvctl",
31982629e30SMike Christensen 		NULL
32082629e30SMike Christensen 	};
32182629e30SMike Christensen 
32282629e30SMike Christensen 	return (v12n_scan_md_nodes(mdp, "virtual-device-port", "vldc-svc-name",
32382629e30SMike Christensen 	    hvctl_str));
32482629e30SMike Christensen }
32582629e30SMike Christensen 
32682629e30SMike Christensen /*
32782629e30SMike Christensen  * Check if MD has a virtual device service (vcc, vsw, vds), returns 1 if true.
32882629e30SMike Christensen  * Need to check all the MD 'virtual-device' nodes for a 'device-type' property
32982629e30SMike Christensen  * of 'vcc', 'vsw' or 'vds'.
33082629e30SMike Christensen  */
33182629e30SMike Christensen static int
v12n_check_virtual_service(md_t * mdp)33282629e30SMike Christensen v12n_check_virtual_service(md_t *mdp)
33382629e30SMike Christensen {
33482629e30SMike Christensen 	static char *vdevs[] = {
33582629e30SMike Christensen 		"vcc",
33682629e30SMike Christensen 		"vsw",
33782629e30SMike Christensen 		"vds",
33882629e30SMike Christensen 		NULL
33982629e30SMike Christensen 	};
34082629e30SMike Christensen 
34182629e30SMike Christensen 	return (v12n_scan_md_nodes(mdp, "virtual-device", "device-type",
34282629e30SMike Christensen 	    vdevs));
34382629e30SMike Christensen }
34482629e30SMike Christensen 
34582629e30SMike Christensen /*
34682629e30SMike Christensen  * Check if MD has an physical I/O device node, returns 1 if true.
34782629e30SMike Christensen  */
34882629e30SMike Christensen static int
v12n_check_io_service(md_t * mdp)34982629e30SMike Christensen v12n_check_io_service(md_t *mdp)
35082629e30SMike Christensen {
35182629e30SMike Christensen 	return (v12n_scan_md_nodes(mdp, "iodevice", NULL, NULL));
35282629e30SMike Christensen }
35382629e30SMike Christensen 
35482629e30SMike Christensen /*
35582629e30SMike Christensen  * Check if a MD node is root PCI device, returns 1 if true.
35682629e30SMike Christensen  * Need to check all the MD 'iodevice' nodes for a 'device-type' property
35782629e30SMike Christensen  * of 'pciex'.
35882629e30SMike Christensen  */
35982629e30SMike Christensen static int
v12n_check_root(md_t * mdp)36082629e30SMike Christensen v12n_check_root(md_t *mdp)
36182629e30SMike Christensen {
36282629e30SMike Christensen 	static char *pciex[] = {
36382629e30SMike Christensen 		"pciex",
36482629e30SMike Christensen 		NULL
36582629e30SMike Christensen 	};
36682629e30SMike Christensen 
36782629e30SMike Christensen 	return (v12n_scan_md_nodes(mdp, "iodevice", "device-type", pciex));
36882629e30SMike Christensen }
36982629e30SMike Christensen 
37082629e30SMike Christensen /*
37182629e30SMike Christensen  * Get the domain roles for the domain.
37282629e30SMike Christensen  */
37382629e30SMike Christensen int
v12n_domain_roles()37482629e30SMike Christensen v12n_domain_roles()
37582629e30SMike Christensen {
37682629e30SMike Christensen 	md_t *mdp;
37782629e30SMike Christensen 	int roles = 0;
37882629e30SMike Christensen 
37982629e30SMike Christensen 	if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
38082629e30SMike Christensen 		errno = ENOTSUP;
38182629e30SMike Christensen 		return (-1);
38282629e30SMike Christensen 	}
38382629e30SMike Christensen 
38482629e30SMike Christensen 	if ((mdp = v12n_md_init()) == NULL) {
38582629e30SMike Christensen 		errno = EACCES;
38682629e30SMike Christensen 		return (-1);
38782629e30SMike Christensen 	}
38882629e30SMike Christensen 
38982629e30SMike Christensen 	if (v12n_check_hv_access(mdp))
39082629e30SMike Christensen 		roles |= V12N_ROLE_CONTROL;
39182629e30SMike Christensen 
39282629e30SMike Christensen 	if (v12n_check_virtual_service(mdp))
39382629e30SMike Christensen 		roles |= V12N_ROLE_SERVICE;
39482629e30SMike Christensen 
39582629e30SMike Christensen 	if (v12n_check_io_service(mdp))
39682629e30SMike Christensen 		roles |= V12N_ROLE_IO;
39782629e30SMike Christensen 
39882629e30SMike Christensen 	if (v12n_check_root(mdp))
39982629e30SMike Christensen 		roles |= V12N_ROLE_ROOT;
40082629e30SMike Christensen 
40182629e30SMike Christensen 	v12n_md_fini(mdp);
40282629e30SMike Christensen 
40382629e30SMike Christensen 	return (roles);
40482629e30SMike Christensen }
40582629e30SMike Christensen 
40682629e30SMike Christensen /*
40782629e30SMike Christensen  * Get domain name from MD's virtual domain service node, returns 1 on success.
40882629e30SMike Christensen  * The domain name is a string property 'vlds-domain-name' under the
40982629e30SMike Christensen  * 'virtual-device' device node whose name is 'virtual-domain-service'.
41082629e30SMike Christensen  */
41182629e30SMike Christensen static int
v12n_get_md_domain_name(md_t * mdp,char ** vds_dnamep)41282629e30SMike Christensen v12n_get_md_domain_name(md_t *mdp, char **vds_dnamep)
41382629e30SMike Christensen {
41482629e30SMike Christensen 	mde_cookie_t *vdev_nodes, rootnode;
41582629e30SMike Christensen 	int list_size, nvdevs, num_nodes, i, rv;
41682629e30SMike Christensen 	char *vldc_name;
41782629e30SMike Christensen 
41882629e30SMike Christensen 	num_nodes = md_node_count(mdp);
41982629e30SMike Christensen 	list_size = num_nodes * sizeof (mde_cookie_t);
42082629e30SMike Christensen 	vdev_nodes = malloc(list_size);
42182629e30SMike Christensen 	if (vdev_nodes == NULL) {
42282629e30SMike Christensen 		return (0);
42382629e30SMike Christensen 	}
42482629e30SMike Christensen 
42582629e30SMike Christensen 	rootnode = md_root_node(mdp);
42682629e30SMike Christensen 
42782629e30SMike Christensen 	nvdevs = md_scan_dag(mdp, rootnode, md_find_name(mdp, "virtual-device"),
42882629e30SMike Christensen 	    md_find_name(mdp, "fwd"), vdev_nodes);
42982629e30SMike Christensen 
43082629e30SMike Christensen 	rv = 0;
43182629e30SMike Christensen 	for (i = 0; i < nvdevs; i++) {
43282629e30SMike Christensen 		if (md_get_prop_str(mdp, vdev_nodes[i], "name", &vldc_name))
43382629e30SMike Christensen 			continue;
43482629e30SMike Christensen 		if (strcmp(vldc_name, "virtual-domain-service") == 0) {
43582629e30SMike Christensen 			rv = (md_get_prop_str(mdp, vdev_nodes[i],
43682629e30SMike Christensen 			    "vlds-domain-name", vds_dnamep) == 0);
43782629e30SMike Christensen 			break;
43882629e30SMike Christensen 		}
43982629e30SMike Christensen 	}
44082629e30SMike Christensen 	free(vdev_nodes);
44182629e30SMike Christensen 	return (rv);
44282629e30SMike Christensen }
44382629e30SMike Christensen 
44482629e30SMike Christensen /*
44582629e30SMike Christensen  * String copyout utility.
44682629e30SMike Christensen  */
44782629e30SMike Christensen static size_t
v12n_string_copyout(char * sout,char * sfrom,size_t count)44882629e30SMike Christensen v12n_string_copyout(char *sout, char *sfrom, size_t count)
44982629e30SMike Christensen {
45082629e30SMike Christensen 	size_t ret = strlen(sfrom) + 1;
45182629e30SMike Christensen 
45282629e30SMike Christensen 	if (sout != NULL && count > 0) {
45382629e30SMike Christensen 		count = MIN(ret, count);
45482629e30SMike Christensen 		(void) memcpy(sout, sfrom, count);
45582629e30SMike Christensen 	}
45682629e30SMike Christensen 	return (ret);
45782629e30SMike Christensen }
45882629e30SMike Christensen 
45982629e30SMike Christensen /*
46082629e30SMike Christensen  * Get the domain name of this domain.
46182629e30SMike Christensen  */
46282629e30SMike Christensen size_t
v12n_domain_name(char * buf,size_t count)46382629e30SMike Christensen v12n_domain_name(char *buf, size_t count)
46482629e30SMike Christensen {
46582629e30SMike Christensen 	md_t *mdp = NULL;
46682629e30SMike Christensen 	char *ldmname;
46782629e30SMike Christensen 	int rv = -1;
46882629e30SMike Christensen 
46982629e30SMike Christensen 	if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
47082629e30SMike Christensen 		errno = ENOTSUP;
47182629e30SMike Christensen 	} else if ((mdp = v12n_md_init()) == NULL) {
47282629e30SMike Christensen 		errno = EACCES;
47382629e30SMike Christensen 	} else if (!v12n_get_md_domain_name(mdp, &ldmname)) {
47482629e30SMike Christensen 		errno = ESRCH;
47582629e30SMike Christensen 	} else {
47682629e30SMike Christensen 		rv = v12n_string_copyout(buf, ldmname, count);
47782629e30SMike Christensen 	}
47882629e30SMike Christensen 
47982629e30SMike Christensen 	v12n_md_fini(mdp);
48082629e30SMike Christensen 	return (rv);
48182629e30SMike Christensen }
48282629e30SMike Christensen 
48382629e30SMike Christensen /*
48482629e30SMike Christensen  * Get UUID string from MD, returns 1 on success.
48582629e30SMike Christensen  * The UUID is a string property 'uuid' under the 'platform' node of the MD.
48682629e30SMike Christensen  */
48782629e30SMike Christensen static int
v12n_get_md_uuid_str(md_t * mdp,char ** uuid_strp)48882629e30SMike Christensen v12n_get_md_uuid_str(md_t *mdp, char **uuid_strp)
48982629e30SMike Christensen {
49082629e30SMike Christensen 	mde_cookie_t *plat_nodes, rootnode;
49182629e30SMike Christensen 	int list_size, npnodes, num_nodes, rv;
49282629e30SMike Christensen 
49382629e30SMike Christensen 	num_nodes = md_node_count(mdp);
49482629e30SMike Christensen 	list_size = num_nodes * sizeof (mde_cookie_t);
49582629e30SMike Christensen 	plat_nodes = malloc(list_size);
49682629e30SMike Christensen 	if (plat_nodes == NULL) {
49782629e30SMike Christensen 		return (0);
49882629e30SMike Christensen 	}
49982629e30SMike Christensen 
50082629e30SMike Christensen 	rootnode = md_root_node(mdp);
50182629e30SMike Christensen 
50282629e30SMike Christensen 	npnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"),
50382629e30SMike Christensen 	    md_find_name(mdp, "fwd"), plat_nodes);
50482629e30SMike Christensen 
50582629e30SMike Christensen 	if (npnodes >= 1)
50682629e30SMike Christensen 		rv = !md_get_prop_str(mdp, plat_nodes[0], "uuid", uuid_strp);
50782629e30SMike Christensen 	else
50882629e30SMike Christensen 		rv = 0;
50982629e30SMike Christensen 
51082629e30SMike Christensen 	free(plat_nodes);
51182629e30SMike Christensen 	return (rv);
51282629e30SMike Christensen }
51382629e30SMike Christensen 
51482629e30SMike Christensen /*
51582629e30SMike Christensen  * Get the domain UUID.
51682629e30SMike Christensen  */
51782629e30SMike Christensen int
v12n_domain_uuid(uuid_t uuid)51882629e30SMike Christensen v12n_domain_uuid(uuid_t uuid)
51982629e30SMike Christensen {
52082629e30SMike Christensen 	md_t *mdp = NULL;
52182629e30SMike Christensen 	char *uuid_str;
52282629e30SMike Christensen 	int rv = -1;
52382629e30SMike Christensen 
52482629e30SMike Christensen 	if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
52582629e30SMike Christensen 		errno = ENOTSUP;
52682629e30SMike Christensen 	} else if ((mdp = v12n_md_init()) == NULL) {
52782629e30SMike Christensen 		errno = EACCES;
52882629e30SMike Christensen 	} else if (!v12n_get_md_uuid_str(mdp, &uuid_str)) {
52982629e30SMike Christensen 		errno = ESRCH;
53082629e30SMike Christensen 	} else {
53182629e30SMike Christensen 		rv = uuid_parse(uuid_str, uuid);
53282629e30SMike Christensen 	}
53382629e30SMike Christensen 
53482629e30SMike Christensen 	v12n_md_fini(mdp);
53582629e30SMike Christensen 
53682629e30SMike Christensen 	return (rv);
53782629e30SMike Christensen }
53882629e30SMike Christensen 
53982629e30SMike Christensen /*
540*d0b12b66SToomas Soome  * Send 'agent-system' request message.
54182629e30SMike Christensen  */
54282629e30SMike Christensen static int
v12n_ldma_send_request()54382629e30SMike Christensen v12n_ldma_send_request()
54482629e30SMike Christensen {
54582629e30SMike Christensen 	ldma_message_header_t ldmamsg;
54682629e30SMike Christensen 
54782629e30SMike Christensen 	if (v12n_ds_send_msg == NULL || v12n_ldma_ctrl_hdl == DS_INVALID_HDL)
54882629e30SMike Christensen 		return (ENOENT);
54982629e30SMike Christensen 
55082629e30SMike Christensen 	ldmamsg.msg_num = 0;
55182629e30SMike Christensen 	ldmamsg.msg_type = v12n_ldma_msgtype;
55282629e30SMike Christensen 	ldmamsg.msg_info = 0;
55382629e30SMike Christensen 	return (v12n_ds_send_msg(v12n_ldma_ctrl_hdl, (char *)&ldmamsg,
55482629e30SMike Christensen 	    sizeof (ldmamsg)));
55582629e30SMike Christensen }
55682629e30SMike Christensen 
55782629e30SMike Christensen /*
55882629e30SMike Christensen  * 'agent-system' registration handler.
55982629e30SMike Christensen  * If we get a registration from the control domain (domain 0), then send
56082629e30SMike Christensen  * the requested message.  Otherwise, ignore the registration.
56182629e30SMike Christensen  */
56282629e30SMike Christensen /* ARGSUSED */
56382629e30SMike Christensen static void
v12n_ldma_register_handler(ds_hdl_t hdl,ds_cb_arg_t arg,ds_ver_t * ver,ds_domain_hdl_t dhdl)56482629e30SMike Christensen v12n_ldma_register_handler(ds_hdl_t hdl, ds_cb_arg_t arg, ds_ver_t *ver,
56582629e30SMike Christensen     ds_domain_hdl_t dhdl)
56682629e30SMike Christensen {
56782629e30SMike Christensen 
56882629e30SMike Christensen 	/* got registration from control domain */
56982629e30SMike Christensen 	if (dhdl == 0) {
57082629e30SMike Christensen 		(void) mutex_lock(&v12n_ldma_cv_lock);
57182629e30SMike Christensen 		if (v12n_ldma_cv_state == V12N_LDMA_REGWAITING) {
57282629e30SMike Christensen 			v12n_ldma_ctrl_hdl = hdl;
57382629e30SMike Christensen 			v12n_ldma_cv_state = V12N_LDMA_REGRECEIVED;
57482629e30SMike Christensen 			(void) cond_signal(&v12n_ldma_cv);
57582629e30SMike Christensen 		}
57682629e30SMike Christensen 		(void) mutex_unlock(&v12n_ldma_cv_lock);
57782629e30SMike Christensen 	}
57882629e30SMike Christensen }
57982629e30SMike Christensen 
58082629e30SMike Christensen /*
58182629e30SMike Christensen  * 'agent-system' data handler.
58282629e30SMike Christensen  */
58382629e30SMike Christensen /* ARGSUSED */
58482629e30SMike Christensen static void
v12n_ldma_data_handler(ds_hdl_t hdl,ds_cb_arg_t arg,void * buf,size_t buflen)58582629e30SMike Christensen v12n_ldma_data_handler(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf,
58682629e30SMike Christensen     size_t buflen)
58782629e30SMike Christensen {
58882629e30SMike Christensen 	char *data;
58982629e30SMike Christensen 	ldma_message_header_t *ldmp;
59082629e30SMike Christensen 	int n;
59182629e30SMike Christensen 	int cv_state = V12N_LDMA_MSGERROR;
59282629e30SMike Christensen 
59382629e30SMike Christensen 	/*
59482629e30SMike Christensen 	 * Ignore any message not from the control domain.
59582629e30SMike Christensen 	 */
59682629e30SMike Christensen 	if (v12n_ldma_ctrl_hdl != hdl)
59782629e30SMike Christensen 		return;
59882629e30SMike Christensen 
59982629e30SMike Christensen 	/*
60082629e30SMike Christensen 	 * Ignore any unexpected message.
60182629e30SMike Christensen 	 */
60282629e30SMike Christensen 	if (buflen < LDMA_MESSAGE_HEADER_SIZE)
60382629e30SMike Christensen 		return;
60482629e30SMike Christensen 
60582629e30SMike Christensen 	/*
60682629e30SMike Christensen 	 * Ignore message with unexpected msgnum.
60782629e30SMike Christensen 	 */
60882629e30SMike Christensen 	ldmp = (ldma_message_header_t *)buf;
60982629e30SMike Christensen 	if (ldmp->msg_num != 0)
61082629e30SMike Christensen 		return;
61182629e30SMike Christensen 
61282629e30SMike Christensen 	switch (ldmp->msg_type) {
61382629e30SMike Christensen 
61482629e30SMike Christensen 	case LDMA_MSG_RESULT:
61582629e30SMike Christensen 		if (ldmp->msg_info == 0 ||
61682629e30SMike Christensen 		    ldmp->msg_info > LDMA_MESSAGE_DLEN(buflen)) {
61782629e30SMike Christensen 			cv_state = V12N_LDMA_MSGERROR;
61882629e30SMike Christensen 			break;
61982629e30SMike Christensen 		}
62082629e30SMike Christensen 		data = LDMA_HDR2DATA(buf);
62182629e30SMike Christensen 
62282629e30SMike Christensen 		/* ensure that data ends with a '\0' */
62382629e30SMike Christensen 		data[ldmp->msg_info - 1] = '\0';
62482629e30SMike Christensen 		switch (v12n_ldma_msgtype) {
62582629e30SMike Christensen 
62682629e30SMike Christensen 		case LDMA_MSGSYS_GET_SYSINFO:
62782629e30SMike Christensen 			/*
62882629e30SMike Christensen 			 * Control domain nodename is second string in the
62982629e30SMike Christensen 			 * message.  Make sure there is enough data in the msg
63082629e30SMike Christensen 			 * to have a second string.
63182629e30SMike Christensen 			 */
63282629e30SMike Christensen 			n = strlen(data);
63382629e30SMike Christensen 			if (LDMA_MESSAGE_DLEN(buflen) <= n + 3) {
63482629e30SMike Christensen 				cv_state = V12N_LDMA_MSGERROR;
63582629e30SMike Christensen 				break;
63682629e30SMike Christensen 			}
63782629e30SMike Christensen 			data += n + 1;
63882629e30SMike Christensen 			if ((v12n_ldma_msgstr = strdup(data)) == NULL)
63982629e30SMike Christensen 				cv_state = V12N_LDMA_MSGERROR;
64082629e30SMike Christensen 			else
64182629e30SMike Christensen 				cv_state = V12N_LDMA_MSGRECEIVED;
64282629e30SMike Christensen 			break;
64382629e30SMike Christensen 
64482629e30SMike Christensen 		case LDMA_MSGSYS_GET_CHASSISNO:
64582629e30SMike Christensen 			if ((v12n_ldma_msgstr = strdup(data)) == NULL)
64682629e30SMike Christensen 				cv_state = V12N_LDMA_MSGERROR;
64782629e30SMike Christensen 			else
64882629e30SMike Christensen 				cv_state = V12N_LDMA_MSGRECEIVED;
64982629e30SMike Christensen 			break;
65082629e30SMike Christensen 
65182629e30SMike Christensen 		default:
65282629e30SMike Christensen 			/* v12n_ldma_msgtype must be valid */
65382629e30SMike Christensen 			ASSERT(0);
65482629e30SMike Christensen 		}
65582629e30SMike Christensen 		break;
65682629e30SMike Christensen 
65782629e30SMike Christensen 	case LDMA_MSG_ERROR:
65882629e30SMike Christensen 		cv_state = V12N_LDMA_MSGERROR;
65982629e30SMike Christensen 		break;
66082629e30SMike Christensen 
66182629e30SMike Christensen 	default:
66282629e30SMike Christensen 		/* unexpected message, ignored */
66382629e30SMike Christensen 		return;
66482629e30SMike Christensen 	}
66582629e30SMike Christensen 
66682629e30SMike Christensen 	(void) mutex_lock(&v12n_ldma_cv_lock);
66782629e30SMike Christensen 	v12n_ldma_cv_state = cv_state;
66882629e30SMike Christensen 	(void) cond_signal(&v12n_ldma_cv);
66982629e30SMike Christensen 	(void) mutex_unlock(&v12n_ldma_cv_lock);
67082629e30SMike Christensen }
67182629e30SMike Christensen 
67282629e30SMike Christensen 
67382629e30SMike Christensen /*
67482629e30SMike Christensen  * libds doesn't exist on non-sun4v, dynamically load it and get the
67582629e30SMike Christensen  * function pointers to the needed lib functions.
67682629e30SMike Christensen  */
67782629e30SMike Christensen static int
v12n_libds_init(void)67882629e30SMike Christensen v12n_libds_init(void)
67982629e30SMike Christensen {
68082629e30SMike Christensen 	if (v12n_ds_dlhdl != NULL) {
68182629e30SMike Christensen 		if (v12n_ds_clnt_reg == NULL || v12n_ds_send_msg == NULL ||
68282629e30SMike Christensen 		    v12n_ds_unreg_svc == NULL)
68382629e30SMike Christensen 			return (ENOENT);
68482629e30SMike Christensen 		return (0);
68582629e30SMike Christensen 	}
68682629e30SMike Christensen 
68782629e30SMike Christensen 	if ((v12n_ds_dlhdl = dlopen("libds.so.1",
68882629e30SMike Christensen 	    RTLD_NOW | RTLD_GLOBAL)) == NULL)
68982629e30SMike Christensen 		return (ENOENT);
69082629e30SMike Christensen 
69182629e30SMike Christensen 	if ((v12n_ds_clnt_reg = (int (*)(ds_capability_t *, ds_ops_t *))
69282629e30SMike Christensen 	    dlsym(v12n_ds_dlhdl, "ds_clnt_reg")) == NULL)
69382629e30SMike Christensen 		return (ENOENT);
69482629e30SMike Christensen 
69582629e30SMike Christensen 	if ((v12n_ds_send_msg = (int (*)(ds_hdl_t, void *, size_t))
69682629e30SMike Christensen 	    dlsym(v12n_ds_dlhdl, "ds_send_msg")) == NULL)
69782629e30SMike Christensen 		return (ENOENT);
69882629e30SMike Christensen 
69982629e30SMike Christensen 	if ((v12n_ds_unreg_svc = (int (*)(char *, boolean_t))
70082629e30SMike Christensen 	    dlsym(v12n_ds_dlhdl, "ds_unreg_svc")) == NULL)
70182629e30SMike Christensen 		return (ENOENT);
70282629e30SMike Christensen 
70382629e30SMike Christensen 	return (0);
70482629e30SMike Christensen }
70582629e30SMike Christensen 
70682629e30SMike Christensen /*
70782629e30SMike Christensen  * Initiate and wait for an ldmad 'agent-system' domain service.
70882629e30SMike Christensen  * Dynamically load libds, register the client 'agent-system' service
70982629e30SMike Christensen  * and wait for a specified amount of time for the 'agent-system'
71082629e30SMike Christensen  * service on the control domain to respond to the request.
71182629e30SMike Christensen  */
71282629e30SMike Christensen static int
v12n_get_ldma_system_msg(int msgtype,char ** strp)71382629e30SMike Christensen v12n_get_ldma_system_msg(int msgtype, char **strp)
71482629e30SMike Christensen {
71582629e30SMike Christensen 	int tout;
71682629e30SMike Christensen 	int err = 0;
71782629e30SMike Christensen 	timestruc_t timeout;
71882629e30SMike Christensen 
71982629e30SMike Christensen 	/*
72082629e30SMike Christensen 	 * Ensure that there's only one thread trying to do a
72182629e30SMike Christensen 	 * 'agent-system' client registration/message at a time.
72282629e30SMike Christensen 	 */
72382629e30SMike Christensen 	(void) mutex_lock(&v12n_ldma_lock);
7241a024a48SMike Christensen 	if ((err = v12n_libds_init()) != 0) {
7251a024a48SMike Christensen 		(void) mutex_unlock(&v12n_ldma_lock);
7261a024a48SMike Christensen 		return (err);
7271a024a48SMike Christensen 	}
72882629e30SMike Christensen 
72982629e30SMike Christensen 	v12n_ldma_msgtype = msgtype;
73082629e30SMike Christensen 	v12n_ldma_msgstr = NULL;
73182629e30SMike Christensen 
73282629e30SMike Christensen 	/* initialize v12n_ldma_cv_state variable before registering service */
73382629e30SMike Christensen 	(void) mutex_lock(&v12n_ldma_cv_lock);
73482629e30SMike Christensen 	v12n_ldma_cv_state = V12N_LDMA_REGWAITING;
73582629e30SMike Christensen 	(void) mutex_unlock(&v12n_ldma_cv_lock);
73682629e30SMike Christensen 
73782629e30SMike Christensen 	/*
73882629e30SMike Christensen 	 * Other instances may be trying to load the "agent-system" service.
73982629e30SMike Christensen 	 * If a collision happens (EBUSY error), wait and try again.
74082629e30SMike Christensen 	 */
74182629e30SMike Christensen 	for (tout = 0; tout < v12n_ldma_timeout; tout += v12n_ldma_sleeptime) {
74282629e30SMike Christensen 		if ((err = v12n_ds_clnt_reg(&v12n_ldma_cap,
74382629e30SMike Christensen 		    &v12n_ldma_ops)) == 0)
74482629e30SMike Christensen 			break;
74582629e30SMike Christensen 		if (err != EALREADY) {
74682629e30SMike Christensen 			goto done;
74782629e30SMike Christensen 		}
74882629e30SMike Christensen 		(void) sleep(v12n_ldma_sleeptime);
74982629e30SMike Christensen 	}
75082629e30SMike Christensen 
75182629e30SMike Christensen 	if (tout >= v12n_ldma_timeout) {
75282629e30SMike Christensen 		err = EBUSY;
75382629e30SMike Christensen 		goto done;
75482629e30SMike Christensen 	}
75582629e30SMike Christensen 
75682629e30SMike Christensen 	/*
75782629e30SMike Christensen 	 * Wait for control domain registration.
75882629e30SMike Christensen 	 */
75982629e30SMike Christensen 	timeout.tv_sec = v12n_ldma_timeout;
76082629e30SMike Christensen 	timeout.tv_nsec = 0;
76182629e30SMike Christensen 
76282629e30SMike Christensen 	(void) mutex_lock(&v12n_ldma_cv_lock);
76382629e30SMike Christensen 	while (v12n_ldma_cv_state == V12N_LDMA_REGWAITING) {
76482629e30SMike Christensen 		if ((err = cond_reltimedwait(&v12n_ldma_cv,
76582629e30SMike Christensen 		    &v12n_ldma_cv_lock, &timeout)) != EINTR)
76682629e30SMike Christensen 			break;
76782629e30SMike Christensen 	}
76882629e30SMike Christensen 
76982629e30SMike Christensen 	/*
77082629e30SMike Christensen 	 * Check for timeout or an error.
77182629e30SMike Christensen 	 */
77282629e30SMike Christensen 	if (v12n_ldma_cv_state != V12N_LDMA_REGRECEIVED) {
77382629e30SMike Christensen 		if (err == 0)
77482629e30SMike Christensen 			err = EPROTO;
77582629e30SMike Christensen 		(void) mutex_unlock(&v12n_ldma_cv_lock);
77682629e30SMike Christensen 		goto done;
77782629e30SMike Christensen 	}
77882629e30SMike Christensen 
77982629e30SMike Christensen 	/*
78082629e30SMike Christensen 	 * Received a registration request, send the request message.
78182629e30SMike Christensen 	 */
78282629e30SMike Christensen 	v12n_ldma_cv_state = V12N_LDMA_MSGWAITING;
78382629e30SMike Christensen 	if ((err = v12n_ldma_send_request()) != 0) {
78482629e30SMike Christensen 		(void) mutex_unlock(&v12n_ldma_cv_lock);
78582629e30SMike Christensen 		goto done;
78682629e30SMike Christensen 	}
78782629e30SMike Christensen 
78882629e30SMike Christensen 	while (v12n_ldma_cv_state == V12N_LDMA_MSGWAITING) {
78982629e30SMike Christensen 		if ((err = cond_reltimedwait(&v12n_ldma_cv,
79082629e30SMike Christensen 		    &v12n_ldma_cv_lock, &timeout)) != EINTR)
79182629e30SMike Christensen 			break;
79282629e30SMike Christensen 	}
79382629e30SMike Christensen 
79482629e30SMike Christensen 	if (v12n_ldma_cv_state != V12N_LDMA_MSGRECEIVED) {
79582629e30SMike Christensen 		if (err == 0)
79682629e30SMike Christensen 			err = EPROTO;
79782629e30SMike Christensen 		(void) mutex_unlock(&v12n_ldma_cv_lock);
79882629e30SMike Christensen 		goto done;
79982629e30SMike Christensen 	}
80082629e30SMike Christensen 
80182629e30SMike Christensen 	v12n_ldma_cv_state = V12N_LDMA_CVINVALID;
80282629e30SMike Christensen 	(void) mutex_unlock(&v12n_ldma_cv_lock);
80382629e30SMike Christensen 
80482629e30SMike Christensen 	/*
80582629e30SMike Christensen 	 * If v12n_ldma_msgstr is set, a valid data response was seen.
80682629e30SMike Christensen 	 */
80782629e30SMike Christensen 	if (v12n_ldma_msgstr == NULL)
80882629e30SMike Christensen 		err = ENODATA;
80982629e30SMike Christensen 	else {
81082629e30SMike Christensen 		if (*v12n_ldma_msgstr == '\0' ||
81182629e30SMike Christensen 		    (*strp = strdup(v12n_ldma_msgstr)) == NULL)
81282629e30SMike Christensen 			err = ENODATA;
81382629e30SMike Christensen 		free(v12n_ldma_msgstr);
81482629e30SMike Christensen 		v12n_ldma_msgstr = NULL;
81582629e30SMike Christensen 	}
81682629e30SMike Christensen 
81782629e30SMike Christensen done:
81882629e30SMike Christensen 	v12n_ds_unreg_svc(LDMA_NAME_SYSTEM, B_TRUE);
81982629e30SMike Christensen 	v12n_ldma_msgtype = -1;
82082629e30SMike Christensen 	v12n_ldma_ctrl_hdl = DS_INVALID_HDL;
82182629e30SMike Christensen 	(void) mutex_unlock(&v12n_ldma_lock);
82282629e30SMike Christensen 
82382629e30SMike Christensen 	return (err);
82482629e30SMike Christensen }
82582629e30SMike Christensen 
82682629e30SMike Christensen /*
82782629e30SMike Christensen  * Get the nodename of the control domain.  Returns the equivalent
82882629e30SMike Christensen  * of 'uname -n' on the control domain.
82982629e30SMike Christensen  *   This is obtained via the 'agent-system' domain service provided
83082629e30SMike Christensen  *   by ldmad.
83182629e30SMike Christensen  */
83282629e30SMike Christensen size_t
v12n_ctrl_domain(char * buf,size_t count)83382629e30SMike Christensen v12n_ctrl_domain(char *buf, size_t count)
83482629e30SMike Christensen {
83582629e30SMike Christensen 	char *str;
83682629e30SMike Christensen 	int err;
83782629e30SMike Christensen 	size_t rv = (size_t)(-1);
83882629e30SMike Christensen 
83982629e30SMike Christensen 	if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
84082629e30SMike Christensen 		errno = ENOTSUP;
84182629e30SMike Christensen 	} else if ((err = v12n_get_ldma_system_msg(LDMA_MSGSYS_GET_SYSINFO,
84282629e30SMike Christensen 	    &str)) != 0) {
84382629e30SMike Christensen 		errno = err;
84482629e30SMike Christensen 	} else {
84582629e30SMike Christensen 		rv = v12n_string_copyout(buf, str, count);
84682629e30SMike Christensen 	}
84782629e30SMike Christensen 	return (rv);
84882629e30SMike Christensen }
84982629e30SMike Christensen 
85082629e30SMike Christensen /*
85182629e30SMike Christensen  * Get the Chassis serial number from the Control Domain.
85282629e30SMike Christensen  *   This is obtained via the 'agent-system' domain service provided
85382629e30SMike Christensen  *   by ldmad.
85482629e30SMike Christensen  */
85582629e30SMike Christensen size_t
v12n_chassis_serialno(char * buf,size_t count)85682629e30SMike Christensen v12n_chassis_serialno(char *buf, size_t count)
85782629e30SMike Christensen {
85882629e30SMike Christensen 	char *str;
85982629e30SMike Christensen 	int err;
86082629e30SMike Christensen 	size_t rv = (size_t)(-1);
86182629e30SMike Christensen 
86282629e30SMike Christensen 	if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
86382629e30SMike Christensen 		errno = ENOTSUP;
86482629e30SMike Christensen 	} else if ((err = v12n_get_ldma_system_msg(LDMA_MSGSYS_GET_CHASSISNO,
86582629e30SMike Christensen 	    &str)) != 0) {
86682629e30SMike Christensen 		errno = err;
86782629e30SMike Christensen 	} else {
86882629e30SMike Christensen 		rv = v12n_string_copyout(buf, str, count);
86982629e30SMike Christensen 	}
87082629e30SMike Christensen 	return (rv);
87182629e30SMike Christensen }
872