xref: /titanic_50/usr/src/lib/libv12n/sparc/libv12n.c (revision 82629e3015252bf18319ba3815c773df23e21436)
1*82629e30SMike Christensen /*
2*82629e30SMike Christensen  * CDDL HEADER START
3*82629e30SMike Christensen  *
4*82629e30SMike Christensen  * The contents of this file are subject to the terms of the
5*82629e30SMike Christensen  * Common Development and Distribution License (the "License").
6*82629e30SMike Christensen  * You may not use this file except in compliance with the License.
7*82629e30SMike Christensen  *
8*82629e30SMike Christensen  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*82629e30SMike Christensen  * or http://www.opensolaris.org/os/licensing.
10*82629e30SMike Christensen  * See the License for the specific language governing permissions
11*82629e30SMike Christensen  * and limitations under the License.
12*82629e30SMike Christensen  *
13*82629e30SMike Christensen  * When distributing Covered Code, include this CDDL HEADER in each
14*82629e30SMike Christensen  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*82629e30SMike Christensen  * If applicable, add the following below this CDDL HEADER, with the
16*82629e30SMike Christensen  * fields enclosed by brackets "[]" replaced with your own identifying
17*82629e30SMike Christensen  * information: Portions Copyright [yyyy] [name of copyright owner]
18*82629e30SMike Christensen  *
19*82629e30SMike Christensen  * CDDL HEADER END
20*82629e30SMike Christensen  */
21*82629e30SMike Christensen /*
22*82629e30SMike Christensen  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23*82629e30SMike Christensen  * Use is subject to license terms.
24*82629e30SMike Christensen  */
25*82629e30SMike Christensen 
26*82629e30SMike Christensen #include <dlfcn.h>
27*82629e30SMike Christensen #include <errno.h>
28*82629e30SMike Christensen #include <fcntl.h>
29*82629e30SMike Christensen #include <stdio.h>
30*82629e30SMike Christensen #include <stdlib.h>
31*82629e30SMike Christensen #include <strings.h>
32*82629e30SMike Christensen #include <synch.h>
33*82629e30SMike Christensen #include <thread.h>
34*82629e30SMike Christensen #include <unistd.h>
35*82629e30SMike Christensen #include <utility.h>
36*82629e30SMike Christensen #include <sys/mdesc.h>
37*82629e30SMike Christensen #include <sys/mdesc_impl.h>
38*82629e30SMike Christensen #include <sys/debug.h>
39*82629e30SMike Christensen #include <sys/stat.h>
40*82629e30SMike Christensen #include <sys/types.h>
41*82629e30SMike Christensen #include <sys/utsname.h>
42*82629e30SMike Christensen 
43*82629e30SMike Christensen #include "ldma.h"
44*82629e30SMike Christensen #include "libds.h"
45*82629e30SMike Christensen #include "libv12n.h"
46*82629e30SMike Christensen 
47*82629e30SMike Christensen /*
48*82629e30SMike Christensen  * sun4 support for libv12n.
49*82629e30SMike Christensen  *
50*82629e30SMike Christensen  * Non-sun4v support is minimal.  The v12n_capabilities() function will
51*82629e30SMike Christensen  * only return 0 (not supported, not enabled, no implementation).
52*82629e30SMike Christensen  *
53*82629e30SMike Christensen  * For sun4v the support for v12n_capabilities(), v12n_domain_roles(),
54*82629e30SMike Christensen  * v12n_domain_name() and v12n_domain_uuid() are supported by scanning the
55*82629e30SMike Christensen  * MD from /dev/mdesc for specific properties.  For v12n_ctrl_domain() and
56*82629e30SMike Christensen  * v12n_chassis_serialno(), the ldoms agent daemon (ldmad) on the control
57*82629e30SMike Christensen  * domain supplies the required information via the "agent-system" domain
58*82629e30SMike Christensen  * service.
59*82629e30SMike Christensen  */
60*82629e30SMike Christensen 
61*82629e30SMike Christensen /* libds statics */
62*82629e30SMike Christensen static void *v12n_ds_dlhdl = NULL;
63*82629e30SMike Christensen static int (*v12n_ds_send_msg)(ds_hdl_t, void *, size_t) = NULL;
64*82629e30SMike Christensen static int (*v12n_ds_clnt_reg)(ds_capability_t *, ds_ops_t *);
65*82629e30SMike Christensen static int (*v12n_ds_unreg_svc)(char *, boolean_t);
66*82629e30SMike Christensen 
67*82629e30SMike Christensen /*
68*82629e30SMike Christensen  * Defines to support the 'agent-system' domain service.
69*82629e30SMike Christensen  */
70*82629e30SMike Christensen 
71*82629e30SMike Christensen #define	LDMA_SYSTEM_NVERS		\
72*82629e30SMike Christensen 			(sizeof (v12n_ldma_system_vers) / sizeof (ds_ver_t))
73*82629e30SMike Christensen static ds_ver_t v12n_ldma_system_vers[] = { { 1, 0} };
74*82629e30SMike Christensen 
75*82629e30SMike Christensen static ds_capability_t v12n_ldma_cap = {
76*82629e30SMike Christensen 	LDMA_NAME_SYSTEM,	/* svc_id */
77*82629e30SMike Christensen 	v12n_ldma_system_vers,	/* vers */
78*82629e30SMike Christensen 	LDMA_SYSTEM_NVERS	/* nvers */
79*82629e30SMike Christensen };
80*82629e30SMike Christensen 
81*82629e30SMike Christensen static void v12n_ldma_register_handler(ds_hdl_t hdl, ds_cb_arg_t arg,
82*82629e30SMike Christensen     ds_ver_t *ver, ds_domain_hdl_t dhdl);
83*82629e30SMike Christensen static void v12n_ldma_data_handler(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf,
84*82629e30SMike Christensen     size_t buflen);
85*82629e30SMike Christensen 
86*82629e30SMike Christensen static ds_ops_t v12n_ldma_ops = {
87*82629e30SMike Christensen 	v12n_ldma_register_handler,	/* ds_reg_cb */
88*82629e30SMike Christensen 	NULL,				/* ds_unreg_cb */
89*82629e30SMike Christensen 	v12n_ldma_data_handler,		/* ds_data_cb */
90*82629e30SMike Christensen 	NULL				/* ds_cb_arg */
91*82629e30SMike Christensen };
92*82629e30SMike Christensen 
93*82629e30SMike Christensen /* v12n_ldma_cv_state values */
94*82629e30SMike Christensen #define	V12N_LDMA_CVINVALID	-1	/* invalid value for cv_state */
95*82629e30SMike Christensen #define	V12N_LDMA_REGWAITING	0	/* waiting for ctrl domain reg */
96*82629e30SMike Christensen #define	V12N_LDMA_REGRECEIVED	1	/* received ctrl domain reg */
97*82629e30SMike Christensen #define	V12N_LDMA_MSGWAITING	2	/* waiting for message response */
98*82629e30SMike Christensen #define	V12N_LDMA_MSGRECEIVED	3	/* received message response */
99*82629e30SMike Christensen #define	V12N_LDMA_MSGERROR	4	/* received a bad message */
100*82629e30SMike Christensen 
101*82629e30SMike Christensen /* 'agent-system' data used in async registration/data message handlers */
102*82629e30SMike Christensen static ds_hdl_t v12n_ldma_ctrl_hdl = DS_INVALID_HDL;
103*82629e30SMike Christensen static int v12n_ldma_msgtype;
104*82629e30SMike Christensen static char *v12n_ldma_msgstr;
105*82629e30SMike Christensen static mutex_t v12n_ldma_lock = DEFAULTMUTEX;
106*82629e30SMike Christensen static cond_t v12n_ldma_cv = DEFAULTCV;
107*82629e30SMike Christensen static int v12n_ldma_cv_state = V12N_LDMA_CVINVALID;
108*82629e30SMike Christensen static mutex_t v12n_ldma_cv_lock = DEFAULTMUTEX;
109*82629e30SMike Christensen 
110*82629e30SMike Christensen /* 'agent-system' timeout values in seconds */
111*82629e30SMike Christensen static int v12n_ldma_timeout = 15;
112*82629e30SMike Christensen static int v12n_ldma_sleeptime = 1;
113*82629e30SMike Christensen 
114*82629e30SMike Christensen 
115*82629e30SMike Christensen #define	V12N_LDOMS_SUPPORTED	(V12N_CAP_SUPPORTED | V12N_CAP_ENABLED | \
116*82629e30SMike Christensen 				    V12N_CAP_IMPL_LDOMS)
117*82629e30SMike Christensen 
118*82629e30SMike Christensen #define	MD_DEVICE		"/dev/mdesc"
119*82629e30SMike Christensen 
120*82629e30SMike Christensen /*
121*82629e30SMike Christensen  * libv12n routines to support /dev/mdesc.
122*82629e30SMike Christensen  */
123*82629e30SMike Christensen 
124*82629e30SMike Christensen /*
125*82629e30SMike Christensen  * Wrapper for MD free: need unused size argument.
126*82629e30SMike Christensen  */
127*82629e30SMike Christensen /* ARGSUSED */
128*82629e30SMike Christensen static void
129*82629e30SMike Christensen v12n_md_free(void *buf, size_t n)
130*82629e30SMike Christensen {
131*82629e30SMike Christensen 	free(buf);
132*82629e30SMike Christensen }
133*82629e30SMike Christensen 
134*82629e30SMike Christensen /*
135*82629e30SMike Christensen  * Wrapper for MD init: read MD and invoke md_init_intern.
136*82629e30SMike Christensen  */
137*82629e30SMike Christensen static md_t *
138*82629e30SMike Christensen v12n_md_init()
139*82629e30SMike Christensen {
140*82629e30SMike Christensen 	md_t *mdp;
141*82629e30SMike Christensen 	char *buf = NULL;
142*82629e30SMike Christensen 	md_header_t mdh;
143*82629e30SMike Christensen 	int md_size;
144*82629e30SMike Christensen 	int fd;
145*82629e30SMike Christensen 
146*82629e30SMike Christensen 	/*
147*82629e30SMike Christensen 	 * Open the Machine Description (MD)
148*82629e30SMike Christensen 	 */
149*82629e30SMike Christensen 	fd = open(MD_DEVICE, O_RDONLY);
150*82629e30SMike Christensen 	if (fd == -1) {
151*82629e30SMike Christensen 		return (NULL);
152*82629e30SMike Christensen 	}
153*82629e30SMike Christensen 
154*82629e30SMike Christensen 	if (read(fd, &mdh, sizeof (md_header_t)) != sizeof (md_header_t))
155*82629e30SMike Christensen 		goto errdone;
156*82629e30SMike Christensen 
157*82629e30SMike Christensen 	md_size = sizeof (md_header_t) + mdh.node_blk_sz + mdh.name_blk_sz +
158*82629e30SMike Christensen 	    mdh.data_blk_sz;
159*82629e30SMike Christensen 
160*82629e30SMike Christensen 	if ((buf = malloc(md_size)) == NULL)
161*82629e30SMike Christensen 		goto errdone;
162*82629e30SMike Christensen 
163*82629e30SMike Christensen 	(void) memcpy(buf, &mdh, sizeof (md_header_t));
164*82629e30SMike Christensen 	if (read(fd, buf + sizeof (md_header_t),
165*82629e30SMike Christensen 	    md_size - sizeof (md_header_t)) != md_size - sizeof (md_header_t)) {
166*82629e30SMike Christensen 		goto errdone;
167*82629e30SMike Christensen 	}
168*82629e30SMike Christensen 
169*82629e30SMike Christensen 	mdp = md_init_intern((uint64_t *)((void *)buf), malloc, v12n_md_free);
170*82629e30SMike Christensen 
171*82629e30SMike Christensen 	(void) close(fd);
172*82629e30SMike Christensen 
173*82629e30SMike Christensen 	return (mdp);
174*82629e30SMike Christensen 
175*82629e30SMike Christensen errdone:
176*82629e30SMike Christensen 	(void) close(fd);
177*82629e30SMike Christensen 	free(buf);
178*82629e30SMike Christensen 
179*82629e30SMike Christensen 	return (NULL);
180*82629e30SMike Christensen }
181*82629e30SMike Christensen 
182*82629e30SMike Christensen /*
183*82629e30SMike Christensen  * Wrapper for md_fini.  Allow NULL md ptr and free MD buffer.
184*82629e30SMike Christensen  */
185*82629e30SMike Christensen static void
186*82629e30SMike Christensen v12n_md_fini(void *md)
187*82629e30SMike Christensen {
188*82629e30SMike Christensen 	md_impl_t *mdp = (md_impl_t *)md;
189*82629e30SMike Christensen 
190*82629e30SMike Christensen 	if (mdp) {
191*82629e30SMike Christensen 		free(mdp->caddr);
192*82629e30SMike Christensen 		(void) md_fini(md);
193*82629e30SMike Christensen 	}
194*82629e30SMike Christensen }
195*82629e30SMike Christensen 
196*82629e30SMike Christensen /*
197*82629e30SMike Christensen  * See if LDoms domaining is enabled, returns 1 if enabled.
198*82629e30SMike Christensen  * Get the value of the 'domaining-enabled' property under the
199*82629e30SMike Christensen  * 'platform' node.  Value of 1 => domaining is enabled.
200*82629e30SMike Christensen  */
201*82629e30SMike Christensen static int
202*82629e30SMike Christensen v12n_domaining_enabled()
203*82629e30SMike Christensen {
204*82629e30SMike Christensen 	mde_cookie_t *nodes, rootnode;
205*82629e30SMike Christensen 	int nnodes;
206*82629e30SMike Christensen 	uint64_t prop_val = 0;
207*82629e30SMike Christensen 	md_t *mdp;
208*82629e30SMike Christensen 
209*82629e30SMike Christensen 	if ((mdp = v12n_md_init()) == NULL) {
210*82629e30SMike Christensen 		return (0);
211*82629e30SMike Christensen 	}
212*82629e30SMike Christensen 
213*82629e30SMike Christensen 	nnodes = md_node_count(mdp);
214*82629e30SMike Christensen 	nodes = malloc(nnodes * sizeof (mde_cookie_t));
215*82629e30SMike Christensen 	if (nodes == NULL) {
216*82629e30SMike Christensen 		v12n_md_fini(mdp);
217*82629e30SMike Christensen 		return (0);
218*82629e30SMike Christensen 	}
219*82629e30SMike Christensen 
220*82629e30SMike Christensen 	rootnode = md_root_node(mdp);
221*82629e30SMike Christensen 
222*82629e30SMike Christensen 	nnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"),
223*82629e30SMike Christensen 	    md_find_name(mdp, "fwd"), nodes);
224*82629e30SMike Christensen 
225*82629e30SMike Christensen 	if (nnodes >= 1) {
226*82629e30SMike Christensen 		(void) md_get_prop_val(mdp, nodes[0], "domaining-enabled",
227*82629e30SMike Christensen 		    &prop_val);
228*82629e30SMike Christensen 	}
229*82629e30SMike Christensen 
230*82629e30SMike Christensen 	v12n_md_fini(mdp);
231*82629e30SMike Christensen 	free(nodes);
232*82629e30SMike Christensen 	return (prop_val == 1);
233*82629e30SMike Christensen }
234*82629e30SMike Christensen 
235*82629e30SMike Christensen int
236*82629e30SMike Christensen v12n_capabilities()
237*82629e30SMike Christensen {
238*82629e30SMike Christensen 	struct utsname uinfo;
239*82629e30SMike Christensen 	struct stat st;
240*82629e30SMike Christensen 	int cap;
241*82629e30SMike Christensen 
242*82629e30SMike Christensen 	/*
243*82629e30SMike Christensen 	 * Check if this is an LDoms system. When using LDoms each
244*82629e30SMike Christensen 	 * domain should have a /dev/mdesc device providing access to
245*82629e30SMike Christensen 	 * the Machine Description (MD) of the domain. If this device
246*82629e30SMike Christensen 	 * does not exist then this is not an LDoms system.
247*82629e30SMike Christensen 	 */
248*82629e30SMike Christensen 	if (uname(&uinfo) == -1 || strcmp(uinfo.machine, "sun4v")) {
249*82629e30SMike Christensen 		/*
250*82629e30SMike Christensen 		 * Not sun4v -> LDoms not supported
251*82629e30SMike Christensen 		 */
252*82629e30SMike Christensen 		cap = 0;
253*82629e30SMike Christensen 	} else if (stat(MD_DEVICE, &st) == 0) {
254*82629e30SMike Christensen 		/*
255*82629e30SMike Christensen 		 * sun4v + /dev/mdesc exists -> Check if LDoms enabled
256*82629e30SMike Christensen 		 * via the 'domaining-enabled' property.
257*82629e30SMike Christensen 		 */
258*82629e30SMike Christensen 		cap = (V12N_CAP_SUPPORTED | V12N_CAP_IMPL_LDOMS |
259*82629e30SMike Christensen 		    (v12n_domaining_enabled() ? V12N_CAP_ENABLED : 0));
260*82629e30SMike Christensen 	} else if (errno == ENOENT) {
261*82629e30SMike Christensen 		/*
262*82629e30SMike Christensen 		 * sun4v + /dev/mdesc does not exist -> LDoms supported
263*82629e30SMike Christensen 		 * but not enabled.
264*82629e30SMike Christensen 		 */
265*82629e30SMike Christensen 		cap = (V12N_CAP_SUPPORTED | V12N_CAP_IMPL_LDOMS);
266*82629e30SMike Christensen 	}
267*82629e30SMike Christensen 
268*82629e30SMike Christensen 	return (cap);
269*82629e30SMike Christensen }
270*82629e30SMike Christensen 
271*82629e30SMike Christensen /*
272*82629e30SMike Christensen  * Routines to support v12n_domain_roles.
273*82629e30SMike Christensen  */
274*82629e30SMike Christensen static int
275*82629e30SMike Christensen v12n_scan_md_nodes(md_t *mdp, char *node_name, char *node_str_prop,
276*82629e30SMike Christensen     char **props)
277*82629e30SMike Christensen {
278*82629e30SMike Christensen 	mde_cookie_t *nodes, rootnode;
279*82629e30SMike Christensen 	int nnodes, i, j;
280*82629e30SMike Christensen 	char *prop_str;
281*82629e30SMike Christensen 
282*82629e30SMike Christensen 	nnodes = md_node_count(mdp);
283*82629e30SMike Christensen 	nodes = malloc(nnodes * sizeof (mde_cookie_t));
284*82629e30SMike Christensen 	if (nodes == NULL) {
285*82629e30SMike Christensen 		return (0);
286*82629e30SMike Christensen 	}
287*82629e30SMike Christensen 
288*82629e30SMike Christensen 	rootnode = md_root_node(mdp);
289*82629e30SMike Christensen 
290*82629e30SMike Christensen 	nnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, node_name),
291*82629e30SMike Christensen 	    md_find_name(mdp, "fwd"), nodes);
292*82629e30SMike Christensen 
293*82629e30SMike Christensen 	if (node_str_prop == NULL)
294*82629e30SMike Christensen 		return (nnodes > 0);
295*82629e30SMike Christensen 
296*82629e30SMike Christensen 	for (i = 0; i < nnodes; i++) {
297*82629e30SMike Christensen 		if (md_get_prop_str(mdp, nodes[i], node_str_prop, &prop_str))
298*82629e30SMike Christensen 			continue;
299*82629e30SMike Christensen 		for (j = 0; props[j] != NULL; j++) {
300*82629e30SMike Christensen 			if (strcmp(prop_str, props[j]) == 0) {
301*82629e30SMike Christensen 				free(nodes);
302*82629e30SMike Christensen 				return (1);
303*82629e30SMike Christensen 			}
304*82629e30SMike Christensen 		}
305*82629e30SMike Christensen 	}
306*82629e30SMike Christensen 	free(nodes);
307*82629e30SMike Christensen 	return (0);
308*82629e30SMike Christensen }
309*82629e30SMike Christensen 
310*82629e30SMike Christensen /*
311*82629e30SMike Christensen  * Check if MD has a hypervisor access point, returns 1 if true.
312*82629e30SMike Christensen  * Check the MD for a 'virtual-device-port' node whose 'vldc-svc-name' is
313*82629e30SMike Christensen  * 'hvctl'.
314*82629e30SMike Christensen  */
315*82629e30SMike Christensen static int
316*82629e30SMike Christensen v12n_check_hv_access(md_t *mdp)
317*82629e30SMike Christensen {
318*82629e30SMike Christensen 	static char *hvctl_str[] = {
319*82629e30SMike Christensen 		"hvctl",
320*82629e30SMike Christensen 		NULL
321*82629e30SMike Christensen 	};
322*82629e30SMike Christensen 
323*82629e30SMike Christensen 	return (v12n_scan_md_nodes(mdp, "virtual-device-port", "vldc-svc-name",
324*82629e30SMike Christensen 	    hvctl_str));
325*82629e30SMike Christensen }
326*82629e30SMike Christensen 
327*82629e30SMike Christensen /*
328*82629e30SMike Christensen  * Check if MD has a virtual device service (vcc, vsw, vds), returns 1 if true.
329*82629e30SMike Christensen  * Need to check all the MD 'virtual-device' nodes for a 'device-type' property
330*82629e30SMike Christensen  * of 'vcc', 'vsw' or 'vds'.
331*82629e30SMike Christensen  */
332*82629e30SMike Christensen static int
333*82629e30SMike Christensen v12n_check_virtual_service(md_t *mdp)
334*82629e30SMike Christensen {
335*82629e30SMike Christensen 	static char *vdevs[] = {
336*82629e30SMike Christensen 		"vcc",
337*82629e30SMike Christensen 		"vsw",
338*82629e30SMike Christensen 		"vds",
339*82629e30SMike Christensen 		NULL
340*82629e30SMike Christensen 	};
341*82629e30SMike Christensen 
342*82629e30SMike Christensen 	return (v12n_scan_md_nodes(mdp, "virtual-device", "device-type",
343*82629e30SMike Christensen 	    vdevs));
344*82629e30SMike Christensen }
345*82629e30SMike Christensen 
346*82629e30SMike Christensen /*
347*82629e30SMike Christensen  * Check if MD has an physical I/O device node, returns 1 if true.
348*82629e30SMike Christensen  */
349*82629e30SMike Christensen static int
350*82629e30SMike Christensen v12n_check_io_service(md_t *mdp)
351*82629e30SMike Christensen {
352*82629e30SMike Christensen 	return (v12n_scan_md_nodes(mdp, "iodevice", NULL, NULL));
353*82629e30SMike Christensen }
354*82629e30SMike Christensen 
355*82629e30SMike Christensen /*
356*82629e30SMike Christensen  * Check if a MD node is root PCI device, returns 1 if true.
357*82629e30SMike Christensen  * Need to check all the MD 'iodevice' nodes for a 'device-type' property
358*82629e30SMike Christensen  * of 'pciex'.
359*82629e30SMike Christensen  */
360*82629e30SMike Christensen static int
361*82629e30SMike Christensen v12n_check_root(md_t *mdp)
362*82629e30SMike Christensen {
363*82629e30SMike Christensen 	static char *pciex[] = {
364*82629e30SMike Christensen 		"pciex",
365*82629e30SMike Christensen 		NULL
366*82629e30SMike Christensen 	};
367*82629e30SMike Christensen 
368*82629e30SMike Christensen 	return (v12n_scan_md_nodes(mdp, "iodevice", "device-type", pciex));
369*82629e30SMike Christensen }
370*82629e30SMike Christensen 
371*82629e30SMike Christensen /*
372*82629e30SMike Christensen  * Get the domain roles for the domain.
373*82629e30SMike Christensen  */
374*82629e30SMike Christensen int
375*82629e30SMike Christensen v12n_domain_roles()
376*82629e30SMike Christensen {
377*82629e30SMike Christensen 	md_t *mdp;
378*82629e30SMike Christensen 	int roles = 0;
379*82629e30SMike Christensen 
380*82629e30SMike Christensen 	if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
381*82629e30SMike Christensen 		errno = ENOTSUP;
382*82629e30SMike Christensen 		return (-1);
383*82629e30SMike Christensen 	}
384*82629e30SMike Christensen 
385*82629e30SMike Christensen 	if ((mdp = v12n_md_init()) == NULL) {
386*82629e30SMike Christensen 		errno = EACCES;
387*82629e30SMike Christensen 		return (-1);
388*82629e30SMike Christensen 	}
389*82629e30SMike Christensen 
390*82629e30SMike Christensen 	if (v12n_check_hv_access(mdp))
391*82629e30SMike Christensen 		roles |= V12N_ROLE_CONTROL;
392*82629e30SMike Christensen 
393*82629e30SMike Christensen 	if (v12n_check_virtual_service(mdp))
394*82629e30SMike Christensen 		roles |= V12N_ROLE_SERVICE;
395*82629e30SMike Christensen 
396*82629e30SMike Christensen 	if (v12n_check_io_service(mdp))
397*82629e30SMike Christensen 		roles |= V12N_ROLE_IO;
398*82629e30SMike Christensen 
399*82629e30SMike Christensen 	if (v12n_check_root(mdp))
400*82629e30SMike Christensen 		roles |= V12N_ROLE_ROOT;
401*82629e30SMike Christensen 
402*82629e30SMike Christensen 	v12n_md_fini(mdp);
403*82629e30SMike Christensen 
404*82629e30SMike Christensen 	return (roles);
405*82629e30SMike Christensen }
406*82629e30SMike Christensen 
407*82629e30SMike Christensen /*
408*82629e30SMike Christensen  * Get domain name from MD's virtual domain service node, returns 1 on success.
409*82629e30SMike Christensen  * The domain name is a string property 'vlds-domain-name' under the
410*82629e30SMike Christensen  * 'virtual-device' device node whose name is 'virtual-domain-service'.
411*82629e30SMike Christensen  */
412*82629e30SMike Christensen static int
413*82629e30SMike Christensen v12n_get_md_domain_name(md_t *mdp, char **vds_dnamep)
414*82629e30SMike Christensen {
415*82629e30SMike Christensen 	mde_cookie_t *vdev_nodes, rootnode;
416*82629e30SMike Christensen 	int list_size, nvdevs, num_nodes, i, rv;
417*82629e30SMike Christensen 	char *vldc_name;
418*82629e30SMike Christensen 
419*82629e30SMike Christensen 	num_nodes = md_node_count(mdp);
420*82629e30SMike Christensen 	list_size = num_nodes * sizeof (mde_cookie_t);
421*82629e30SMike Christensen 	vdev_nodes = malloc(list_size);
422*82629e30SMike Christensen 	if (vdev_nodes == NULL) {
423*82629e30SMike Christensen 		return (0);
424*82629e30SMike Christensen 	}
425*82629e30SMike Christensen 
426*82629e30SMike Christensen 	rootnode = md_root_node(mdp);
427*82629e30SMike Christensen 
428*82629e30SMike Christensen 	nvdevs = md_scan_dag(mdp, rootnode, md_find_name(mdp, "virtual-device"),
429*82629e30SMike Christensen 	    md_find_name(mdp, "fwd"), vdev_nodes);
430*82629e30SMike Christensen 
431*82629e30SMike Christensen 	rv = 0;
432*82629e30SMike Christensen 	for (i = 0; i < nvdevs; i++) {
433*82629e30SMike Christensen 		if (md_get_prop_str(mdp, vdev_nodes[i], "name", &vldc_name))
434*82629e30SMike Christensen 			continue;
435*82629e30SMike Christensen 		if (strcmp(vldc_name, "virtual-domain-service") == 0) {
436*82629e30SMike Christensen 			rv = (md_get_prop_str(mdp, vdev_nodes[i],
437*82629e30SMike Christensen 			    "vlds-domain-name", vds_dnamep) == 0);
438*82629e30SMike Christensen 			break;
439*82629e30SMike Christensen 		}
440*82629e30SMike Christensen 	}
441*82629e30SMike Christensen 	free(vdev_nodes);
442*82629e30SMike Christensen 	return (rv);
443*82629e30SMike Christensen }
444*82629e30SMike Christensen 
445*82629e30SMike Christensen /*
446*82629e30SMike Christensen  * String copyout utility.
447*82629e30SMike Christensen  */
448*82629e30SMike Christensen static size_t
449*82629e30SMike Christensen v12n_string_copyout(char *sout, char *sfrom, size_t count)
450*82629e30SMike Christensen {
451*82629e30SMike Christensen 	size_t ret = strlen(sfrom) + 1;
452*82629e30SMike Christensen 
453*82629e30SMike Christensen 	if (sout != NULL && count > 0) {
454*82629e30SMike Christensen 		count = MIN(ret, count);
455*82629e30SMike Christensen 		(void) memcpy(sout, sfrom, count);
456*82629e30SMike Christensen 	}
457*82629e30SMike Christensen 	return (ret);
458*82629e30SMike Christensen }
459*82629e30SMike Christensen 
460*82629e30SMike Christensen /*
461*82629e30SMike Christensen  * Get the domain name of this domain.
462*82629e30SMike Christensen  */
463*82629e30SMike Christensen size_t
464*82629e30SMike Christensen v12n_domain_name(char *buf, size_t count)
465*82629e30SMike Christensen {
466*82629e30SMike Christensen 	md_t *mdp = NULL;
467*82629e30SMike Christensen 	char *ldmname;
468*82629e30SMike Christensen 	int rv = -1;
469*82629e30SMike Christensen 
470*82629e30SMike Christensen 	if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
471*82629e30SMike Christensen 		errno = ENOTSUP;
472*82629e30SMike Christensen 	} else if ((mdp = v12n_md_init()) == NULL) {
473*82629e30SMike Christensen 		errno = EACCES;
474*82629e30SMike Christensen 	} else if (!v12n_get_md_domain_name(mdp, &ldmname)) {
475*82629e30SMike Christensen 		errno = ESRCH;
476*82629e30SMike Christensen 	} else {
477*82629e30SMike Christensen 		rv = v12n_string_copyout(buf, ldmname, count);
478*82629e30SMike Christensen 	}
479*82629e30SMike Christensen 
480*82629e30SMike Christensen 	v12n_md_fini(mdp);
481*82629e30SMike Christensen 	return (rv);
482*82629e30SMike Christensen }
483*82629e30SMike Christensen 
484*82629e30SMike Christensen /*
485*82629e30SMike Christensen  * Get UUID string from MD, returns 1 on success.
486*82629e30SMike Christensen  * The UUID is a string property 'uuid' under the 'platform' node of the MD.
487*82629e30SMike Christensen  */
488*82629e30SMike Christensen static int
489*82629e30SMike Christensen v12n_get_md_uuid_str(md_t *mdp, char **uuid_strp)
490*82629e30SMike Christensen {
491*82629e30SMike Christensen 	mde_cookie_t *plat_nodes, rootnode;
492*82629e30SMike Christensen 	int list_size, npnodes, num_nodes, rv;
493*82629e30SMike Christensen 
494*82629e30SMike Christensen 	num_nodes = md_node_count(mdp);
495*82629e30SMike Christensen 	list_size = num_nodes * sizeof (mde_cookie_t);
496*82629e30SMike Christensen 	plat_nodes = malloc(list_size);
497*82629e30SMike Christensen 	if (plat_nodes == NULL) {
498*82629e30SMike Christensen 		return (0);
499*82629e30SMike Christensen 	}
500*82629e30SMike Christensen 
501*82629e30SMike Christensen 	rootnode = md_root_node(mdp);
502*82629e30SMike Christensen 
503*82629e30SMike Christensen 	npnodes = md_scan_dag(mdp, rootnode, md_find_name(mdp, "platform"),
504*82629e30SMike Christensen 	    md_find_name(mdp, "fwd"), plat_nodes);
505*82629e30SMike Christensen 
506*82629e30SMike Christensen 	if (npnodes >= 1)
507*82629e30SMike Christensen 		rv = !md_get_prop_str(mdp, plat_nodes[0], "uuid", uuid_strp);
508*82629e30SMike Christensen 	else
509*82629e30SMike Christensen 		rv = 0;
510*82629e30SMike Christensen 
511*82629e30SMike Christensen 	free(plat_nodes);
512*82629e30SMike Christensen 	return (rv);
513*82629e30SMike Christensen }
514*82629e30SMike Christensen 
515*82629e30SMike Christensen /*
516*82629e30SMike Christensen  * Get the domain UUID.
517*82629e30SMike Christensen  */
518*82629e30SMike Christensen int
519*82629e30SMike Christensen v12n_domain_uuid(uuid_t uuid)
520*82629e30SMike Christensen {
521*82629e30SMike Christensen 	md_t *mdp = NULL;
522*82629e30SMike Christensen 	char *uuid_str;
523*82629e30SMike Christensen 	int rv = -1;
524*82629e30SMike Christensen 
525*82629e30SMike Christensen 	if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
526*82629e30SMike Christensen 		errno = ENOTSUP;
527*82629e30SMike Christensen 	} else if ((mdp = v12n_md_init()) == NULL) {
528*82629e30SMike Christensen 		errno = EACCES;
529*82629e30SMike Christensen 	} else if (!v12n_get_md_uuid_str(mdp, &uuid_str)) {
530*82629e30SMike Christensen 		errno = ESRCH;
531*82629e30SMike Christensen 	} else {
532*82629e30SMike Christensen 		rv = uuid_parse(uuid_str, uuid);
533*82629e30SMike Christensen 	}
534*82629e30SMike Christensen 
535*82629e30SMike Christensen 	v12n_md_fini(mdp);
536*82629e30SMike Christensen 
537*82629e30SMike Christensen 	return (rv);
538*82629e30SMike Christensen }
539*82629e30SMike Christensen 
540*82629e30SMike Christensen /*
541*82629e30SMike Christensen  * Send 'agent-sytem' request message.
542*82629e30SMike Christensen  */
543*82629e30SMike Christensen static int
544*82629e30SMike Christensen v12n_ldma_send_request()
545*82629e30SMike Christensen {
546*82629e30SMike Christensen 	ldma_message_header_t ldmamsg;
547*82629e30SMike Christensen 
548*82629e30SMike Christensen 	if (v12n_ds_send_msg == NULL || v12n_ldma_ctrl_hdl == DS_INVALID_HDL)
549*82629e30SMike Christensen 		return (ENOENT);
550*82629e30SMike Christensen 
551*82629e30SMike Christensen 	ldmamsg.msg_num = 0;
552*82629e30SMike Christensen 	ldmamsg.msg_type = v12n_ldma_msgtype;
553*82629e30SMike Christensen 	ldmamsg.msg_info = 0;
554*82629e30SMike Christensen 	return (v12n_ds_send_msg(v12n_ldma_ctrl_hdl, (char *)&ldmamsg,
555*82629e30SMike Christensen 	    sizeof (ldmamsg)));
556*82629e30SMike Christensen }
557*82629e30SMike Christensen 
558*82629e30SMike Christensen /*
559*82629e30SMike Christensen  * 'agent-system' registration handler.
560*82629e30SMike Christensen  * If we get a registration from the control domain (domain 0), then send
561*82629e30SMike Christensen  * the requested message.  Otherwise, ignore the registration.
562*82629e30SMike Christensen  */
563*82629e30SMike Christensen /* ARGSUSED */
564*82629e30SMike Christensen static void
565*82629e30SMike Christensen v12n_ldma_register_handler(ds_hdl_t hdl, ds_cb_arg_t arg, ds_ver_t *ver,
566*82629e30SMike Christensen     ds_domain_hdl_t dhdl)
567*82629e30SMike Christensen {
568*82629e30SMike Christensen 
569*82629e30SMike Christensen 	/* got registration from control domain */
570*82629e30SMike Christensen 	if (dhdl == 0) {
571*82629e30SMike Christensen 		(void) mutex_lock(&v12n_ldma_cv_lock);
572*82629e30SMike Christensen 		if (v12n_ldma_cv_state == V12N_LDMA_REGWAITING) {
573*82629e30SMike Christensen 			v12n_ldma_ctrl_hdl = hdl;
574*82629e30SMike Christensen 			v12n_ldma_cv_state = V12N_LDMA_REGRECEIVED;
575*82629e30SMike Christensen 			(void) cond_signal(&v12n_ldma_cv);
576*82629e30SMike Christensen 		}
577*82629e30SMike Christensen 		(void) mutex_unlock(&v12n_ldma_cv_lock);
578*82629e30SMike Christensen 	}
579*82629e30SMike Christensen }
580*82629e30SMike Christensen 
581*82629e30SMike Christensen /*
582*82629e30SMike Christensen  * 'agent-system' data handler.
583*82629e30SMike Christensen  */
584*82629e30SMike Christensen /* ARGSUSED */
585*82629e30SMike Christensen static void
586*82629e30SMike Christensen v12n_ldma_data_handler(ds_hdl_t hdl, ds_cb_arg_t arg, void *buf,
587*82629e30SMike Christensen     size_t buflen)
588*82629e30SMike Christensen {
589*82629e30SMike Christensen 	char *data;
590*82629e30SMike Christensen 	ldma_message_header_t *ldmp;
591*82629e30SMike Christensen 	int n;
592*82629e30SMike Christensen 	int cv_state = V12N_LDMA_MSGERROR;
593*82629e30SMike Christensen 
594*82629e30SMike Christensen 	/*
595*82629e30SMike Christensen 	 * Ignore any message not from the control domain.
596*82629e30SMike Christensen 	 */
597*82629e30SMike Christensen 	if (v12n_ldma_ctrl_hdl != hdl)
598*82629e30SMike Christensen 		return;
599*82629e30SMike Christensen 
600*82629e30SMike Christensen 	/*
601*82629e30SMike Christensen 	 * Ignore any unexpected message.
602*82629e30SMike Christensen 	 */
603*82629e30SMike Christensen 	if (buflen < LDMA_MESSAGE_HEADER_SIZE)
604*82629e30SMike Christensen 		return;
605*82629e30SMike Christensen 
606*82629e30SMike Christensen 	/*
607*82629e30SMike Christensen 	 * Ignore message with unexpected msgnum.
608*82629e30SMike Christensen 	 */
609*82629e30SMike Christensen 	ldmp = (ldma_message_header_t *)buf;
610*82629e30SMike Christensen 	if (ldmp->msg_num != 0)
611*82629e30SMike Christensen 		return;
612*82629e30SMike Christensen 
613*82629e30SMike Christensen 	switch (ldmp->msg_type) {
614*82629e30SMike Christensen 
615*82629e30SMike Christensen 	case LDMA_MSG_RESULT:
616*82629e30SMike Christensen 		if (ldmp->msg_info == 0 ||
617*82629e30SMike Christensen 		    ldmp->msg_info > LDMA_MESSAGE_DLEN(buflen)) {
618*82629e30SMike Christensen 			cv_state = V12N_LDMA_MSGERROR;
619*82629e30SMike Christensen 			break;
620*82629e30SMike Christensen 		}
621*82629e30SMike Christensen 		data = LDMA_HDR2DATA(buf);
622*82629e30SMike Christensen 
623*82629e30SMike Christensen 		/* ensure that data ends with a '\0' */
624*82629e30SMike Christensen 		data[ldmp->msg_info - 1] = '\0';
625*82629e30SMike Christensen 		switch (v12n_ldma_msgtype) {
626*82629e30SMike Christensen 
627*82629e30SMike Christensen 		case LDMA_MSGSYS_GET_SYSINFO:
628*82629e30SMike Christensen 			/*
629*82629e30SMike Christensen 			 * Control domain nodename is second string in the
630*82629e30SMike Christensen 			 * message.  Make sure there is enough data in the msg
631*82629e30SMike Christensen 			 * to have a second string.
632*82629e30SMike Christensen 			 */
633*82629e30SMike Christensen 			n = strlen(data);
634*82629e30SMike Christensen 			if (LDMA_MESSAGE_DLEN(buflen) <= n + 3) {
635*82629e30SMike Christensen 				cv_state = V12N_LDMA_MSGERROR;
636*82629e30SMike Christensen 				break;
637*82629e30SMike Christensen 			}
638*82629e30SMike Christensen 			data += n + 1;
639*82629e30SMike Christensen 			if ((v12n_ldma_msgstr = strdup(data)) == NULL)
640*82629e30SMike Christensen 				cv_state = V12N_LDMA_MSGERROR;
641*82629e30SMike Christensen 			else
642*82629e30SMike Christensen 				cv_state = V12N_LDMA_MSGRECEIVED;
643*82629e30SMike Christensen 			break;
644*82629e30SMike Christensen 
645*82629e30SMike Christensen 		case LDMA_MSGSYS_GET_CHASSISNO:
646*82629e30SMike Christensen 			if ((v12n_ldma_msgstr = strdup(data)) == NULL)
647*82629e30SMike Christensen 				cv_state = V12N_LDMA_MSGERROR;
648*82629e30SMike Christensen 			else
649*82629e30SMike Christensen 				cv_state = V12N_LDMA_MSGRECEIVED;
650*82629e30SMike Christensen 			break;
651*82629e30SMike Christensen 
652*82629e30SMike Christensen 		default:
653*82629e30SMike Christensen 			/* v12n_ldma_msgtype must be valid */
654*82629e30SMike Christensen 			ASSERT(0);
655*82629e30SMike Christensen 		}
656*82629e30SMike Christensen 		break;
657*82629e30SMike Christensen 
658*82629e30SMike Christensen 	case LDMA_MSG_ERROR:
659*82629e30SMike Christensen 		cv_state = V12N_LDMA_MSGERROR;
660*82629e30SMike Christensen 		break;
661*82629e30SMike Christensen 
662*82629e30SMike Christensen 	default:
663*82629e30SMike Christensen 		/* unexpected message, ignored */
664*82629e30SMike Christensen 		return;
665*82629e30SMike Christensen 	}
666*82629e30SMike Christensen 
667*82629e30SMike Christensen 	(void) mutex_lock(&v12n_ldma_cv_lock);
668*82629e30SMike Christensen 	v12n_ldma_cv_state = cv_state;
669*82629e30SMike Christensen 	(void) cond_signal(&v12n_ldma_cv);
670*82629e30SMike Christensen 	(void) mutex_unlock(&v12n_ldma_cv_lock);
671*82629e30SMike Christensen }
672*82629e30SMike Christensen 
673*82629e30SMike Christensen 
674*82629e30SMike Christensen /*
675*82629e30SMike Christensen  * libds doesn't exist on non-sun4v, dynamically load it and get the
676*82629e30SMike Christensen  * function pointers to the needed lib functions.
677*82629e30SMike Christensen  */
678*82629e30SMike Christensen static int
679*82629e30SMike Christensen v12n_libds_init(void)
680*82629e30SMike Christensen {
681*82629e30SMike Christensen 	if (v12n_ds_dlhdl != NULL) {
682*82629e30SMike Christensen 		if (v12n_ds_clnt_reg == NULL || v12n_ds_send_msg == NULL ||
683*82629e30SMike Christensen 		    v12n_ds_unreg_svc == NULL)
684*82629e30SMike Christensen 			return (ENOENT);
685*82629e30SMike Christensen 		return (0);
686*82629e30SMike Christensen 	}
687*82629e30SMike Christensen 
688*82629e30SMike Christensen 	if ((v12n_ds_dlhdl = dlopen("libds.so.1",
689*82629e30SMike Christensen 	    RTLD_NOW | RTLD_GLOBAL)) == NULL)
690*82629e30SMike Christensen 		return (ENOENT);
691*82629e30SMike Christensen 
692*82629e30SMike Christensen 	if ((v12n_ds_clnt_reg = (int (*)(ds_capability_t *, ds_ops_t *))
693*82629e30SMike Christensen 	    dlsym(v12n_ds_dlhdl, "ds_clnt_reg")) == NULL)
694*82629e30SMike Christensen 		return (ENOENT);
695*82629e30SMike Christensen 
696*82629e30SMike Christensen 	if ((v12n_ds_send_msg = (int (*)(ds_hdl_t, void *, size_t))
697*82629e30SMike Christensen 	    dlsym(v12n_ds_dlhdl, "ds_send_msg")) == NULL)
698*82629e30SMike Christensen 		return (ENOENT);
699*82629e30SMike Christensen 
700*82629e30SMike Christensen 	if ((v12n_ds_unreg_svc = (int (*)(char *, boolean_t))
701*82629e30SMike Christensen 	    dlsym(v12n_ds_dlhdl, "ds_unreg_svc")) == NULL)
702*82629e30SMike Christensen 		return (ENOENT);
703*82629e30SMike Christensen 
704*82629e30SMike Christensen 	return (0);
705*82629e30SMike Christensen }
706*82629e30SMike Christensen 
707*82629e30SMike Christensen /*
708*82629e30SMike Christensen  * Initiate and wait for an ldmad 'agent-system' domain service.
709*82629e30SMike Christensen  * Dynamically load libds, register the client 'agent-system' service
710*82629e30SMike Christensen  * and wait for a specified amount of time for the 'agent-system'
711*82629e30SMike Christensen  * service on the control domain to respond to the request.
712*82629e30SMike Christensen  */
713*82629e30SMike Christensen static int
714*82629e30SMike Christensen v12n_get_ldma_system_msg(int msgtype, char **strp)
715*82629e30SMike Christensen {
716*82629e30SMike Christensen 	int tout;
717*82629e30SMike Christensen 	int err = 0;
718*82629e30SMike Christensen 	timestruc_t timeout;
719*82629e30SMike Christensen 
720*82629e30SMike Christensen 	/*
721*82629e30SMike Christensen 	 * Ensure that there's only one thread trying to do a
722*82629e30SMike Christensen 	 * 'agent-system' client registration/message at a time.
723*82629e30SMike Christensen 	 */
724*82629e30SMike Christensen 	(void) mutex_lock(&v12n_ldma_lock);
725*82629e30SMike Christensen 	if ((err = v12n_libds_init()) != 0)
726*82629e30SMike Christensen 		goto done;
727*82629e30SMike Christensen 
728*82629e30SMike Christensen 	v12n_ldma_msgtype = msgtype;
729*82629e30SMike Christensen 	v12n_ldma_msgstr = NULL;
730*82629e30SMike Christensen 
731*82629e30SMike Christensen 	/* initialize v12n_ldma_cv_state variable before registering service */
732*82629e30SMike Christensen 	(void) mutex_lock(&v12n_ldma_cv_lock);
733*82629e30SMike Christensen 	v12n_ldma_cv_state = V12N_LDMA_REGWAITING;
734*82629e30SMike Christensen 	(void) mutex_unlock(&v12n_ldma_cv_lock);
735*82629e30SMike Christensen 
736*82629e30SMike Christensen 	/*
737*82629e30SMike Christensen 	 * Other instances may be trying to load the "agent-system" service.
738*82629e30SMike Christensen 	 * If a collision happens (EBUSY error), wait and try again.
739*82629e30SMike Christensen 	 */
740*82629e30SMike Christensen 	for (tout = 0; tout < v12n_ldma_timeout; tout += v12n_ldma_sleeptime) {
741*82629e30SMike Christensen 		if ((err = v12n_ds_clnt_reg(&v12n_ldma_cap,
742*82629e30SMike Christensen 		    &v12n_ldma_ops)) == 0)
743*82629e30SMike Christensen 			break;
744*82629e30SMike Christensen 		if (err != EALREADY) {
745*82629e30SMike Christensen 			goto done;
746*82629e30SMike Christensen 		}
747*82629e30SMike Christensen 		(void) sleep(v12n_ldma_sleeptime);
748*82629e30SMike Christensen 	}
749*82629e30SMike Christensen 
750*82629e30SMike Christensen 	if (tout >= v12n_ldma_timeout) {
751*82629e30SMike Christensen 		err = EBUSY;
752*82629e30SMike Christensen 		goto done;
753*82629e30SMike Christensen 	}
754*82629e30SMike Christensen 
755*82629e30SMike Christensen 	/*
756*82629e30SMike Christensen 	 * Wait for control domain registration.
757*82629e30SMike Christensen 	 */
758*82629e30SMike Christensen 	timeout.tv_sec = v12n_ldma_timeout;
759*82629e30SMike Christensen 	timeout.tv_nsec = 0;
760*82629e30SMike Christensen 
761*82629e30SMike Christensen 	(void) mutex_lock(&v12n_ldma_cv_lock);
762*82629e30SMike Christensen 	while (v12n_ldma_cv_state == V12N_LDMA_REGWAITING) {
763*82629e30SMike Christensen 		if ((err = cond_reltimedwait(&v12n_ldma_cv,
764*82629e30SMike Christensen 		    &v12n_ldma_cv_lock, &timeout)) != EINTR)
765*82629e30SMike Christensen 			break;
766*82629e30SMike Christensen 	}
767*82629e30SMike Christensen 
768*82629e30SMike Christensen 	/*
769*82629e30SMike Christensen 	 * Check for timeout or an error.
770*82629e30SMike Christensen 	 */
771*82629e30SMike Christensen 	if (v12n_ldma_cv_state != V12N_LDMA_REGRECEIVED) {
772*82629e30SMike Christensen 		if (err == 0)
773*82629e30SMike Christensen 			err = EPROTO;
774*82629e30SMike Christensen 		(void) mutex_unlock(&v12n_ldma_cv_lock);
775*82629e30SMike Christensen 		goto done;
776*82629e30SMike Christensen 	}
777*82629e30SMike Christensen 
778*82629e30SMike Christensen 	/*
779*82629e30SMike Christensen 	 * Received a registration request, send the request message.
780*82629e30SMike Christensen 	 */
781*82629e30SMike Christensen 	v12n_ldma_cv_state = V12N_LDMA_MSGWAITING;
782*82629e30SMike Christensen 	if ((err = v12n_ldma_send_request()) != 0) {
783*82629e30SMike Christensen 		(void) mutex_unlock(&v12n_ldma_cv_lock);
784*82629e30SMike Christensen 		goto done;
785*82629e30SMike Christensen 	}
786*82629e30SMike Christensen 
787*82629e30SMike Christensen 	while (v12n_ldma_cv_state == V12N_LDMA_MSGWAITING) {
788*82629e30SMike Christensen 		if ((err = cond_reltimedwait(&v12n_ldma_cv,
789*82629e30SMike Christensen 		    &v12n_ldma_cv_lock, &timeout)) != EINTR)
790*82629e30SMike Christensen 			break;
791*82629e30SMike Christensen 	}
792*82629e30SMike Christensen 
793*82629e30SMike Christensen 	if (v12n_ldma_cv_state != V12N_LDMA_MSGRECEIVED) {
794*82629e30SMike Christensen 		if (err == 0)
795*82629e30SMike Christensen 			err = EPROTO;
796*82629e30SMike Christensen 		(void) mutex_unlock(&v12n_ldma_cv_lock);
797*82629e30SMike Christensen 		goto done;
798*82629e30SMike Christensen 	}
799*82629e30SMike Christensen 
800*82629e30SMike Christensen 	v12n_ldma_cv_state = V12N_LDMA_CVINVALID;
801*82629e30SMike Christensen 	(void) mutex_unlock(&v12n_ldma_cv_lock);
802*82629e30SMike Christensen 
803*82629e30SMike Christensen 	/*
804*82629e30SMike Christensen 	 * If v12n_ldma_msgstr is set, a valid data response was seen.
805*82629e30SMike Christensen 	 */
806*82629e30SMike Christensen 	if (v12n_ldma_msgstr == NULL)
807*82629e30SMike Christensen 		err = ENODATA;
808*82629e30SMike Christensen 	else {
809*82629e30SMike Christensen 		if (*v12n_ldma_msgstr == '\0' ||
810*82629e30SMike Christensen 		    (*strp = strdup(v12n_ldma_msgstr)) == NULL)
811*82629e30SMike Christensen 			err = ENODATA;
812*82629e30SMike Christensen 		free(v12n_ldma_msgstr);
813*82629e30SMike Christensen 		v12n_ldma_msgstr = NULL;
814*82629e30SMike Christensen 	}
815*82629e30SMike Christensen 
816*82629e30SMike Christensen done:
817*82629e30SMike Christensen 	v12n_ds_unreg_svc(LDMA_NAME_SYSTEM, B_TRUE);
818*82629e30SMike Christensen 	v12n_ldma_msgtype = -1;
819*82629e30SMike Christensen 	v12n_ldma_ctrl_hdl = DS_INVALID_HDL;
820*82629e30SMike Christensen 	(void) mutex_unlock(&v12n_ldma_lock);
821*82629e30SMike Christensen 
822*82629e30SMike Christensen 	return (err);
823*82629e30SMike Christensen }
824*82629e30SMike Christensen 
825*82629e30SMike Christensen /*
826*82629e30SMike Christensen  * Get the nodename of the control domain.  Returns the equivalent
827*82629e30SMike Christensen  * of 'uname -n' on the control domain.
828*82629e30SMike Christensen  *   This is obtained via the 'agent-system' domain service provided
829*82629e30SMike Christensen  *   by ldmad.
830*82629e30SMike Christensen  */
831*82629e30SMike Christensen size_t
832*82629e30SMike Christensen v12n_ctrl_domain(char *buf, size_t count)
833*82629e30SMike Christensen {
834*82629e30SMike Christensen 	char *str;
835*82629e30SMike Christensen 	int err;
836*82629e30SMike Christensen 	size_t rv = (size_t)(-1);
837*82629e30SMike Christensen 
838*82629e30SMike Christensen 	if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
839*82629e30SMike Christensen 		errno = ENOTSUP;
840*82629e30SMike Christensen 	} else if ((err = v12n_get_ldma_system_msg(LDMA_MSGSYS_GET_SYSINFO,
841*82629e30SMike Christensen 	    &str)) != 0) {
842*82629e30SMike Christensen 		errno = err;
843*82629e30SMike Christensen 	} else {
844*82629e30SMike Christensen 		rv = v12n_string_copyout(buf, str, count);
845*82629e30SMike Christensen 	}
846*82629e30SMike Christensen 	return (rv);
847*82629e30SMike Christensen }
848*82629e30SMike Christensen 
849*82629e30SMike Christensen /*
850*82629e30SMike Christensen  * Get the Chassis serial number from the Control Domain.
851*82629e30SMike Christensen  *   This is obtained via the 'agent-system' domain service provided
852*82629e30SMike Christensen  *   by ldmad.
853*82629e30SMike Christensen  */
854*82629e30SMike Christensen size_t
855*82629e30SMike Christensen v12n_chassis_serialno(char *buf, size_t count)
856*82629e30SMike Christensen {
857*82629e30SMike Christensen 	char *str;
858*82629e30SMike Christensen 	int err;
859*82629e30SMike Christensen 	size_t rv = (size_t)(-1);
860*82629e30SMike Christensen 
861*82629e30SMike Christensen 	if (v12n_capabilities() != V12N_LDOMS_SUPPORTED) {
862*82629e30SMike Christensen 		errno = ENOTSUP;
863*82629e30SMike Christensen 	} else if ((err = v12n_get_ldma_system_msg(LDMA_MSGSYS_GET_CHASSISNO,
864*82629e30SMike Christensen 	    &str)) != 0) {
865*82629e30SMike Christensen 		errno = err;
866*82629e30SMike Christensen 	} else {
867*82629e30SMike Christensen 		rv = v12n_string_copyout(buf, str, count);
868*82629e30SMike Christensen 	}
869*82629e30SMike Christensen 	return (rv);
870*82629e30SMike Christensen }
871