xref: /titanic_52/usr/src/uts/common/avs/ncall/ncall.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte /*
27*fcf3ce44SJohn Forte  * Media independent RPC-like comms
28*fcf3ce44SJohn Forte  */
29*fcf3ce44SJohn Forte 
30*fcf3ce44SJohn Forte #include <sys/types.h>
31*fcf3ce44SJohn Forte #include <sys/conf.h>
32*fcf3ce44SJohn Forte #include <sys/stat.h>
33*fcf3ce44SJohn Forte #include <sys/errno.h>
34*fcf3ce44SJohn Forte #include <sys/cmn_err.h>
35*fcf3ce44SJohn Forte #include <sys/ksynch.h>
36*fcf3ce44SJohn Forte #include <sys/kmem.h>
37*fcf3ce44SJohn Forte #include <sys/modctl.h>
38*fcf3ce44SJohn Forte #include <sys/ddi.h>
39*fcf3ce44SJohn Forte #include <sys/sunddi.h>
40*fcf3ce44SJohn Forte 
41*fcf3ce44SJohn Forte #include <sys/varargs.h>
42*fcf3ce44SJohn Forte #ifdef DS_DDICT
43*fcf3ce44SJohn Forte #include <sys/nsctl/contract.h>
44*fcf3ce44SJohn Forte #endif
45*fcf3ce44SJohn Forte #include "ncall.h"
46*fcf3ce44SJohn Forte #include "ncall_module.h"
47*fcf3ce44SJohn Forte 
48*fcf3ce44SJohn Forte #include <sys/nsctl/nsvers.h>
49*fcf3ce44SJohn Forte 
50*fcf3ce44SJohn Forte /*
51*fcf3ce44SJohn Forte  * cb_ops functions.
52*fcf3ce44SJohn Forte  */
53*fcf3ce44SJohn Forte 
54*fcf3ce44SJohn Forte static int ncallioctl(dev_t, int, intptr_t, int, cred_t *, int *);
55*fcf3ce44SJohn Forte static int ncallprint(dev_t, char *);
56*fcf3ce44SJohn Forte 
57*fcf3ce44SJohn Forte 
58*fcf3ce44SJohn Forte static struct cb_ops ncall_cb_ops = {
59*fcf3ce44SJohn Forte 	nulldev,	/* open */
60*fcf3ce44SJohn Forte 	nulldev,	/* close */
61*fcf3ce44SJohn Forte 	nulldev,	/* strategy */
62*fcf3ce44SJohn Forte 	ncallprint,
63*fcf3ce44SJohn Forte 	nodev,		/* dump */
64*fcf3ce44SJohn Forte 	nodev,		/* read */
65*fcf3ce44SJohn Forte 	nodev,		/* write */
66*fcf3ce44SJohn Forte 	ncallioctl,
67*fcf3ce44SJohn Forte 	nodev,		/* devmap */
68*fcf3ce44SJohn Forte 	nodev,		/* mmap */
69*fcf3ce44SJohn Forte 	nodev,		/* segmap */
70*fcf3ce44SJohn Forte 	nochpoll,	/* poll */
71*fcf3ce44SJohn Forte 	ddi_prop_op,
72*fcf3ce44SJohn Forte 	NULL,		/* NOT a stream */
73*fcf3ce44SJohn Forte 	D_NEW | D_MP | D_64BIT,
74*fcf3ce44SJohn Forte 	CB_REV,
75*fcf3ce44SJohn Forte 	nodev,		/* aread */
76*fcf3ce44SJohn Forte 	nodev,		/* awrite */
77*fcf3ce44SJohn Forte };
78*fcf3ce44SJohn Forte 
79*fcf3ce44SJohn Forte 
80*fcf3ce44SJohn Forte /*
81*fcf3ce44SJohn Forte  * dev_ops functions.
82*fcf3ce44SJohn Forte  */
83*fcf3ce44SJohn Forte 
84*fcf3ce44SJohn Forte static int ncall_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
85*fcf3ce44SJohn Forte static int ncall_attach(dev_info_t *, ddi_attach_cmd_t);
86*fcf3ce44SJohn Forte static int ncall_detach(dev_info_t *, ddi_detach_cmd_t);
87*fcf3ce44SJohn Forte 
88*fcf3ce44SJohn Forte static struct dev_ops ncall_ops = {
89*fcf3ce44SJohn Forte 	DEVO_REV,
90*fcf3ce44SJohn Forte 	0,
91*fcf3ce44SJohn Forte 	ncall_getinfo,
92*fcf3ce44SJohn Forte 	nulldev,	/* identify */
93*fcf3ce44SJohn Forte 	nulldev,	/* probe */
94*fcf3ce44SJohn Forte 	ncall_attach,
95*fcf3ce44SJohn Forte 	ncall_detach,
96*fcf3ce44SJohn Forte 	nodev,		/* reset */
97*fcf3ce44SJohn Forte 	&ncall_cb_ops,
98*fcf3ce44SJohn Forte 	(struct bus_ops *)0,
99*fcf3ce44SJohn Forte 	NULL		/* power */
100*fcf3ce44SJohn Forte };
101*fcf3ce44SJohn Forte 
102*fcf3ce44SJohn Forte /*
103*fcf3ce44SJohn Forte  * Module linkage.
104*fcf3ce44SJohn Forte  */
105*fcf3ce44SJohn Forte 
106*fcf3ce44SJohn Forte extern struct mod_ops mod_driverops;
107*fcf3ce44SJohn Forte 
108*fcf3ce44SJohn Forte static struct modldrv modldrv = {
109*fcf3ce44SJohn Forte 	&mod_driverops,
110*fcf3ce44SJohn Forte 	"nws:Kernel Call:" ISS_VERSION_STR,
111*fcf3ce44SJohn Forte 	&ncall_ops
112*fcf3ce44SJohn Forte };
113*fcf3ce44SJohn Forte 
114*fcf3ce44SJohn Forte static struct modlinkage modlinkage = {
115*fcf3ce44SJohn Forte 	MODREV_1,
116*fcf3ce44SJohn Forte 	&modldrv,
117*fcf3ce44SJohn Forte 	0
118*fcf3ce44SJohn Forte };
119*fcf3ce44SJohn Forte 
120*fcf3ce44SJohn Forte typedef struct ncall_modinfo_s {
121*fcf3ce44SJohn Forte 	struct ncall_modinfo_s	*next;
122*fcf3ce44SJohn Forte 	ncall_module_t		*module;
123*fcf3ce44SJohn Forte } ncall_modinfo_t;
124*fcf3ce44SJohn Forte 
125*fcf3ce44SJohn Forte static dev_info_t *ncall_dip;		/* Single DIP for driver */
126*fcf3ce44SJohn Forte static kmutex_t ncall_mutex;
127*fcf3ce44SJohn Forte 
128*fcf3ce44SJohn Forte static ncall_modinfo_t *ncall_modules;
129*fcf3ce44SJohn Forte static int ncall_active;
130*fcf3ce44SJohn Forte 
131*fcf3ce44SJohn Forte static ncall_node_t ncall_nodeinfo;
132*fcf3ce44SJohn Forte 
133*fcf3ce44SJohn Forte static int ncallgetnodes(intptr_t, int, int *);
134*fcf3ce44SJohn Forte extern void ncall_init_stub(void);
135*fcf3ce44SJohn Forte 
136*fcf3ce44SJohn Forte int
137*fcf3ce44SJohn Forte _init(void)
138*fcf3ce44SJohn Forte {
139*fcf3ce44SJohn Forte 	int error;
140*fcf3ce44SJohn Forte 
141*fcf3ce44SJohn Forte 	mutex_init(&ncall_mutex, NULL, MUTEX_DRIVER, NULL);
142*fcf3ce44SJohn Forte 
143*fcf3ce44SJohn Forte 	if ((error = mod_install(&modlinkage)) != 0) {
144*fcf3ce44SJohn Forte 		mutex_destroy(&ncall_mutex);
145*fcf3ce44SJohn Forte 		return (error);
146*fcf3ce44SJohn Forte 	}
147*fcf3ce44SJohn Forte 
148*fcf3ce44SJohn Forte 	return (0);
149*fcf3ce44SJohn Forte }
150*fcf3ce44SJohn Forte 
151*fcf3ce44SJohn Forte 
152*fcf3ce44SJohn Forte int
153*fcf3ce44SJohn Forte _fini(void)
154*fcf3ce44SJohn Forte {
155*fcf3ce44SJohn Forte 	int error;
156*fcf3ce44SJohn Forte 
157*fcf3ce44SJohn Forte 	if ((error = mod_remove(&modlinkage)) != 0)
158*fcf3ce44SJohn Forte 		return (error);
159*fcf3ce44SJohn Forte 
160*fcf3ce44SJohn Forte 	mutex_destroy(&ncall_mutex);
161*fcf3ce44SJohn Forte 	return (error);
162*fcf3ce44SJohn Forte }
163*fcf3ce44SJohn Forte 
164*fcf3ce44SJohn Forte 
165*fcf3ce44SJohn Forte int
166*fcf3ce44SJohn Forte _info(struct modinfo *modinfop)
167*fcf3ce44SJohn Forte {
168*fcf3ce44SJohn Forte 	return (mod_info(&modlinkage, modinfop));
169*fcf3ce44SJohn Forte }
170*fcf3ce44SJohn Forte 
171*fcf3ce44SJohn Forte static int
172*fcf3ce44SJohn Forte ncall_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
173*fcf3ce44SJohn Forte {
174*fcf3ce44SJohn Forte 	switch (cmd) {
175*fcf3ce44SJohn Forte 
176*fcf3ce44SJohn Forte 	case DDI_ATTACH:
177*fcf3ce44SJohn Forte 		ncall_dip = dip;
178*fcf3ce44SJohn Forte 
179*fcf3ce44SJohn Forte 		if (ddi_create_minor_node(dip, "c,ncall", S_IFCHR,
180*fcf3ce44SJohn Forte 		    0, DDI_PSEUDO, 0) != DDI_SUCCESS)
181*fcf3ce44SJohn Forte 			goto failed;
182*fcf3ce44SJohn Forte 
183*fcf3ce44SJohn Forte 		ddi_report_dev(dip);
184*fcf3ce44SJohn Forte 
185*fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
186*fcf3ce44SJohn Forte 
187*fcf3ce44SJohn Forte 	default:
188*fcf3ce44SJohn Forte 		return (DDI_FAILURE);
189*fcf3ce44SJohn Forte 	}
190*fcf3ce44SJohn Forte 
191*fcf3ce44SJohn Forte failed:
192*fcf3ce44SJohn Forte 	(void) ncall_detach(dip, DDI_DETACH);
193*fcf3ce44SJohn Forte 	return (DDI_FAILURE);
194*fcf3ce44SJohn Forte }
195*fcf3ce44SJohn Forte 
196*fcf3ce44SJohn Forte 
197*fcf3ce44SJohn Forte static int
198*fcf3ce44SJohn Forte ncall_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
199*fcf3ce44SJohn Forte {
200*fcf3ce44SJohn Forte 	switch (cmd) {
201*fcf3ce44SJohn Forte 
202*fcf3ce44SJohn Forte 	case DDI_DETACH:
203*fcf3ce44SJohn Forte 
204*fcf3ce44SJohn Forte 		/*
205*fcf3ce44SJohn Forte 		 * If still active, then refuse to detach.
206*fcf3ce44SJohn Forte 		 */
207*fcf3ce44SJohn Forte 
208*fcf3ce44SJohn Forte 		if (ncall_modules != NULL || ncall_active)
209*fcf3ce44SJohn Forte 			return (DDI_FAILURE);
210*fcf3ce44SJohn Forte 
211*fcf3ce44SJohn Forte 		/*
212*fcf3ce44SJohn Forte 		 * Remove all minor nodes.
213*fcf3ce44SJohn Forte 		 */
214*fcf3ce44SJohn Forte 
215*fcf3ce44SJohn Forte 		ddi_remove_minor_node(dip, NULL);
216*fcf3ce44SJohn Forte 		ncall_dip = NULL;
217*fcf3ce44SJohn Forte 
218*fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
219*fcf3ce44SJohn Forte 
220*fcf3ce44SJohn Forte 	default:
221*fcf3ce44SJohn Forte 		return (DDI_FAILURE);
222*fcf3ce44SJohn Forte 	}
223*fcf3ce44SJohn Forte }
224*fcf3ce44SJohn Forte 
225*fcf3ce44SJohn Forte 
226*fcf3ce44SJohn Forte /* ARGSUSED */
227*fcf3ce44SJohn Forte 
228*fcf3ce44SJohn Forte static int
229*fcf3ce44SJohn Forte ncall_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
230*fcf3ce44SJohn Forte {
231*fcf3ce44SJohn Forte 	int rc = DDI_FAILURE;
232*fcf3ce44SJohn Forte 
233*fcf3ce44SJohn Forte 	switch (infocmd) {
234*fcf3ce44SJohn Forte 
235*fcf3ce44SJohn Forte 	case DDI_INFO_DEVT2DEVINFO:
236*fcf3ce44SJohn Forte 		*result = ncall_dip;
237*fcf3ce44SJohn Forte 		rc = DDI_SUCCESS;
238*fcf3ce44SJohn Forte 		break;
239*fcf3ce44SJohn Forte 
240*fcf3ce44SJohn Forte 	case DDI_INFO_DEVT2INSTANCE:
241*fcf3ce44SJohn Forte 		/*
242*fcf3ce44SJohn Forte 		 * We only have a single instance.
243*fcf3ce44SJohn Forte 		 */
244*fcf3ce44SJohn Forte 		*result = 0;
245*fcf3ce44SJohn Forte 		rc = DDI_SUCCESS;
246*fcf3ce44SJohn Forte 		break;
247*fcf3ce44SJohn Forte 
248*fcf3ce44SJohn Forte 	default:
249*fcf3ce44SJohn Forte 		break;
250*fcf3ce44SJohn Forte 	}
251*fcf3ce44SJohn Forte 
252*fcf3ce44SJohn Forte 	return (rc);
253*fcf3ce44SJohn Forte }
254*fcf3ce44SJohn Forte 
255*fcf3ce44SJohn Forte 
256*fcf3ce44SJohn Forte /* ARGSUSED */
257*fcf3ce44SJohn Forte static int
258*fcf3ce44SJohn Forte ncallprint(dev_t dev, char *str)
259*fcf3ce44SJohn Forte {
260*fcf3ce44SJohn Forte 	cmn_err(CE_WARN, "%s%d: %s", ddi_get_name(ncall_dip),
261*fcf3ce44SJohn Forte 	    ddi_get_instance(ncall_dip), str);
262*fcf3ce44SJohn Forte 
263*fcf3ce44SJohn Forte 	return (0);
264*fcf3ce44SJohn Forte }
265*fcf3ce44SJohn Forte 
266*fcf3ce44SJohn Forte 
267*fcf3ce44SJohn Forte int
268*fcf3ce44SJohn Forte ncall_register_module(ncall_module_t *mp, ncall_node_t *nodep)
269*fcf3ce44SJohn Forte {
270*fcf3ce44SJohn Forte 	ncall_modinfo_t *new;
271*fcf3ce44SJohn Forte 	int rc = 0;
272*fcf3ce44SJohn Forte 
273*fcf3ce44SJohn Forte 	if (mp == NULL || mp->ncall_version != NCALL_MODULE_VER)
274*fcf3ce44SJohn Forte 		return (EINVAL);
275*fcf3ce44SJohn Forte 
276*fcf3ce44SJohn Forte 	new = kmem_alloc(sizeof (*new), KM_SLEEP);
277*fcf3ce44SJohn Forte 
278*fcf3ce44SJohn Forte 	if (new != NULL) {
279*fcf3ce44SJohn Forte 		new->module = mp;
280*fcf3ce44SJohn Forte 
281*fcf3ce44SJohn Forte 		mutex_enter(&ncall_mutex);
282*fcf3ce44SJohn Forte 
283*fcf3ce44SJohn Forte 		new->next = ncall_modules;
284*fcf3ce44SJohn Forte 		ncall_modules = new;
285*fcf3ce44SJohn Forte 
286*fcf3ce44SJohn Forte 		mutex_exit(&ncall_mutex);
287*fcf3ce44SJohn Forte 	} else {
288*fcf3ce44SJohn Forte 		rc = ENOMEM;
289*fcf3ce44SJohn Forte 	}
290*fcf3ce44SJohn Forte 
291*fcf3ce44SJohn Forte 	*nodep = ncall_nodeinfo;	/* structure copy */
292*fcf3ce44SJohn Forte 	return (rc);
293*fcf3ce44SJohn Forte }
294*fcf3ce44SJohn Forte 
295*fcf3ce44SJohn Forte 
296*fcf3ce44SJohn Forte int
297*fcf3ce44SJohn Forte ncall_unregister_module(ncall_module_t *mod)
298*fcf3ce44SJohn Forte {
299*fcf3ce44SJohn Forte 	ncall_modinfo_t **mpp;
300*fcf3ce44SJohn Forte 	int rc = ESRCH;
301*fcf3ce44SJohn Forte 
302*fcf3ce44SJohn Forte 	mutex_enter(&ncall_mutex);
303*fcf3ce44SJohn Forte 
304*fcf3ce44SJohn Forte 	for (mpp = &ncall_modules; *mpp != NULL; mpp = &((*mpp)->next)) {
305*fcf3ce44SJohn Forte 		if ((*mpp)->module == mod) {
306*fcf3ce44SJohn Forte 			*mpp = (*mpp)->next;
307*fcf3ce44SJohn Forte 			rc = 0;
308*fcf3ce44SJohn Forte 			break;
309*fcf3ce44SJohn Forte 		}
310*fcf3ce44SJohn Forte 	}
311*fcf3ce44SJohn Forte 
312*fcf3ce44SJohn Forte 	mutex_exit(&ncall_mutex);
313*fcf3ce44SJohn Forte 
314*fcf3ce44SJohn Forte 	return (rc);
315*fcf3ce44SJohn Forte }
316*fcf3ce44SJohn Forte 
317*fcf3ce44SJohn Forte 
318*fcf3ce44SJohn Forte static int
319*fcf3ce44SJohn Forte ncall_stop(void)
320*fcf3ce44SJohn Forte {
321*fcf3ce44SJohn Forte 	ncall_modinfo_t *mod;
322*fcf3ce44SJohn Forte 	int rc = 0;
323*fcf3ce44SJohn Forte 
324*fcf3ce44SJohn Forte 	mutex_enter(&ncall_mutex);
325*fcf3ce44SJohn Forte 
326*fcf3ce44SJohn Forte 	while ((rc == 0) && ((mod = ncall_modules) != NULL)) {
327*fcf3ce44SJohn Forte 		mutex_exit(&ncall_mutex);
328*fcf3ce44SJohn Forte 
329*fcf3ce44SJohn Forte 		rc = (*mod->module->ncall_stop)();
330*fcf3ce44SJohn Forte 
331*fcf3ce44SJohn Forte 		mutex_enter(&ncall_mutex);
332*fcf3ce44SJohn Forte 	}
333*fcf3ce44SJohn Forte 
334*fcf3ce44SJohn Forte 	mutex_exit(&ncall_mutex);
335*fcf3ce44SJohn Forte 
336*fcf3ce44SJohn Forte 	return (rc);
337*fcf3ce44SJohn Forte }
338*fcf3ce44SJohn Forte 
339*fcf3ce44SJohn Forte 
340*fcf3ce44SJohn Forte /* ARGSUSED */
341*fcf3ce44SJohn Forte static int ncallioctl(dev_t dev, int cmd, intptr_t arg, int mode,
342*fcf3ce44SJohn Forte     cred_t *crp, int *rvalp)
343*fcf3ce44SJohn Forte {
344*fcf3ce44SJohn Forte 	ncall_node_t node = { 0, };
345*fcf3ce44SJohn Forte 	int mirror;
346*fcf3ce44SJohn Forte 	int rc = 0;
347*fcf3ce44SJohn Forte 
348*fcf3ce44SJohn Forte 	*rvalp = 0;
349*fcf3ce44SJohn Forte 
350*fcf3ce44SJohn Forte 	if ((rc = drv_priv(crp)) != 0)
351*fcf3ce44SJohn Forte 		return (rc);
352*fcf3ce44SJohn Forte 
353*fcf3ce44SJohn Forte 	switch (cmd) {
354*fcf3ce44SJohn Forte 
355*fcf3ce44SJohn Forte 	case NC_IOC_START:
356*fcf3ce44SJohn Forte 		if (ncall_active) {
357*fcf3ce44SJohn Forte 			rc = EALREADY;
358*fcf3ce44SJohn Forte 			break;
359*fcf3ce44SJohn Forte 		}
360*fcf3ce44SJohn Forte 
361*fcf3ce44SJohn Forte 		if (ddi_copyin((void *)arg, &node, sizeof (node), mode) < 0)
362*fcf3ce44SJohn Forte 			return (EFAULT);
363*fcf3ce44SJohn Forte 
364*fcf3ce44SJohn Forte 		bcopy(&node, &ncall_nodeinfo, sizeof (ncall_nodeinfo));
365*fcf3ce44SJohn Forte 		ncall_init_stub();
366*fcf3ce44SJohn Forte 		ncall_active = 1;
367*fcf3ce44SJohn Forte 		break;
368*fcf3ce44SJohn Forte 
369*fcf3ce44SJohn Forte 	case NC_IOC_STOP:
370*fcf3ce44SJohn Forte 		ncall_active = 0;
371*fcf3ce44SJohn Forte 		rc = ncall_stop();
372*fcf3ce44SJohn Forte 		break;
373*fcf3ce44SJohn Forte 
374*fcf3ce44SJohn Forte 	case NC_IOC_GETNODE:
375*fcf3ce44SJohn Forte 		if (!ncall_active) {
376*fcf3ce44SJohn Forte 			rc = ENONET;
377*fcf3ce44SJohn Forte 			break;
378*fcf3ce44SJohn Forte 		}
379*fcf3ce44SJohn Forte 		if (ddi_copyout(&ncall_nodeinfo, (void *)arg,
380*fcf3ce44SJohn Forte 		    sizeof (ncall_nodeinfo), mode) < 0) {
381*fcf3ce44SJohn Forte 			rc = EFAULT;
382*fcf3ce44SJohn Forte 			break;
383*fcf3ce44SJohn Forte 		}
384*fcf3ce44SJohn Forte 		mirror = ncall_mirror(ncall_nodeinfo.nc_nodeid);
385*fcf3ce44SJohn Forte 		/*
386*fcf3ce44SJohn Forte 		 * can't return -1, as this will mask the ioctl
387*fcf3ce44SJohn Forte 		 * failure, so return 0.
388*fcf3ce44SJohn Forte 		 */
389*fcf3ce44SJohn Forte 		if (mirror == -1)
390*fcf3ce44SJohn Forte 			mirror = 0;
391*fcf3ce44SJohn Forte 		*rvalp = mirror;
392*fcf3ce44SJohn Forte 		break;
393*fcf3ce44SJohn Forte 
394*fcf3ce44SJohn Forte 	case NC_IOC_GETNETNODES:
395*fcf3ce44SJohn Forte 		rc = ncallgetnodes(arg, mode, rvalp);
396*fcf3ce44SJohn Forte 		break;
397*fcf3ce44SJohn Forte 
398*fcf3ce44SJohn Forte 	case NC_IOC_PING:
399*fcf3ce44SJohn Forte 		if (!ncall_active) {
400*fcf3ce44SJohn Forte 			rc = ENONET;
401*fcf3ce44SJohn Forte 			break;
402*fcf3ce44SJohn Forte 		}
403*fcf3ce44SJohn Forte 
404*fcf3ce44SJohn Forte 		if (ddi_copyin((void *)arg, &node, sizeof (node), mode) < 0) {
405*fcf3ce44SJohn Forte 			rc = EFAULT;
406*fcf3ce44SJohn Forte 			break;
407*fcf3ce44SJohn Forte 		}
408*fcf3ce44SJohn Forte 
409*fcf3ce44SJohn Forte 		node.nc_nodename[sizeof (node.nc_nodename)-1] = '\0';
410*fcf3ce44SJohn Forte 		rc = ncall_ping(node.nc_nodename, rvalp);
411*fcf3ce44SJohn Forte 		break;
412*fcf3ce44SJohn Forte 
413*fcf3ce44SJohn Forte 	default:
414*fcf3ce44SJohn Forte 		rc = EINVAL;
415*fcf3ce44SJohn Forte 		break;
416*fcf3ce44SJohn Forte 	}
417*fcf3ce44SJohn Forte 
418*fcf3ce44SJohn Forte 	return (rc);
419*fcf3ce44SJohn Forte }
420*fcf3ce44SJohn Forte 
421*fcf3ce44SJohn Forte 
422*fcf3ce44SJohn Forte void
423*fcf3ce44SJohn Forte ncall_register_svc(int svc_id, void (*func)(ncall_t *, int *))
424*fcf3ce44SJohn Forte {
425*fcf3ce44SJohn Forte 	if (ncall_modules)
426*fcf3ce44SJohn Forte 		(*ncall_modules->module->ncall_register_svc)(svc_id, func);
427*fcf3ce44SJohn Forte }
428*fcf3ce44SJohn Forte 
429*fcf3ce44SJohn Forte 
430*fcf3ce44SJohn Forte void
431*fcf3ce44SJohn Forte ncall_unregister_svc(int svc_id)
432*fcf3ce44SJohn Forte {
433*fcf3ce44SJohn Forte 	if (ncall_modules)
434*fcf3ce44SJohn Forte 		(*ncall_modules->module->ncall_unregister_svc)(svc_id);
435*fcf3ce44SJohn Forte }
436*fcf3ce44SJohn Forte 
437*fcf3ce44SJohn Forte 
438*fcf3ce44SJohn Forte int
439*fcf3ce44SJohn Forte ncall_nodeid(char *nodename)
440*fcf3ce44SJohn Forte {
441*fcf3ce44SJohn Forte 	if (ncall_modules)
442*fcf3ce44SJohn Forte 		return ((ncall_modules->module->ncall_nodeid)(nodename));
443*fcf3ce44SJohn Forte 	else
444*fcf3ce44SJohn Forte 		return (0);
445*fcf3ce44SJohn Forte }
446*fcf3ce44SJohn Forte 
447*fcf3ce44SJohn Forte 
448*fcf3ce44SJohn Forte char *
449*fcf3ce44SJohn Forte ncall_nodename(int nodeid)
450*fcf3ce44SJohn Forte {
451*fcf3ce44SJohn Forte 	if (ncall_modules)
452*fcf3ce44SJohn Forte 		return ((*ncall_modules->module->ncall_nodename)(nodeid));
453*fcf3ce44SJohn Forte 	else
454*fcf3ce44SJohn Forte 		return ("unknown");
455*fcf3ce44SJohn Forte }
456*fcf3ce44SJohn Forte 
457*fcf3ce44SJohn Forte 
458*fcf3ce44SJohn Forte int
459*fcf3ce44SJohn Forte ncall_mirror(int nodeid)
460*fcf3ce44SJohn Forte {
461*fcf3ce44SJohn Forte 	if (ncall_modules)
462*fcf3ce44SJohn Forte 		return ((*ncall_modules->module->ncall_mirror)(nodeid));
463*fcf3ce44SJohn Forte 	else
464*fcf3ce44SJohn Forte 		return (-1);
465*fcf3ce44SJohn Forte }
466*fcf3ce44SJohn Forte 
467*fcf3ce44SJohn Forte 
468*fcf3ce44SJohn Forte int
469*fcf3ce44SJohn Forte ncall_self(void)
470*fcf3ce44SJohn Forte {
471*fcf3ce44SJohn Forte 	if (ncall_modules)
472*fcf3ce44SJohn Forte 		return ((*ncall_modules->module->ncall_self)());
473*fcf3ce44SJohn Forte 	else
474*fcf3ce44SJohn Forte 		return (-1);
475*fcf3ce44SJohn Forte }
476*fcf3ce44SJohn Forte 
477*fcf3ce44SJohn Forte 
478*fcf3ce44SJohn Forte int
479*fcf3ce44SJohn Forte ncall_alloc(int host_id, int flags, int net, ncall_t **ncall_p)
480*fcf3ce44SJohn Forte {
481*fcf3ce44SJohn Forte 	int rc = ENOLINK;
482*fcf3ce44SJohn Forte 
483*fcf3ce44SJohn Forte 	if (ncall_modules)
484*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_alloc)(host_id,
485*fcf3ce44SJohn Forte 		    flags, net, ncall_p);
486*fcf3ce44SJohn Forte 
487*fcf3ce44SJohn Forte 	return (rc);
488*fcf3ce44SJohn Forte }
489*fcf3ce44SJohn Forte 
490*fcf3ce44SJohn Forte 
491*fcf3ce44SJohn Forte int
492*fcf3ce44SJohn Forte ncall_timedsend(ncall_t *ncall, int flags, int svc_id,
493*fcf3ce44SJohn Forte     struct timeval *t, ...)
494*fcf3ce44SJohn Forte {
495*fcf3ce44SJohn Forte 	va_list ap;
496*fcf3ce44SJohn Forte 	int rc = ENOLINK;
497*fcf3ce44SJohn Forte 
498*fcf3ce44SJohn Forte 	va_start(ap, t);
499*fcf3ce44SJohn Forte 
500*fcf3ce44SJohn Forte 	if (ncall_modules)
501*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_timedsend)(ncall, flags,
502*fcf3ce44SJohn Forte 		    svc_id, t, ap);
503*fcf3ce44SJohn Forte 
504*fcf3ce44SJohn Forte 	va_end(ap);
505*fcf3ce44SJohn Forte 
506*fcf3ce44SJohn Forte 	return (rc);
507*fcf3ce44SJohn Forte }
508*fcf3ce44SJohn Forte 
509*fcf3ce44SJohn Forte int
510*fcf3ce44SJohn Forte ncall_timedsendnotify(ncall_t *ncall, int flags, int svc_id,
511*fcf3ce44SJohn Forte     struct timeval *t, void (*ncall_callback)(ncall_t *, void *),
512*fcf3ce44SJohn Forte     void *vptr, ...)
513*fcf3ce44SJohn Forte {
514*fcf3ce44SJohn Forte 	va_list ap;
515*fcf3ce44SJohn Forte 	int rc = ENOLINK;
516*fcf3ce44SJohn Forte 
517*fcf3ce44SJohn Forte 	va_start(ap, vptr);
518*fcf3ce44SJohn Forte 
519*fcf3ce44SJohn Forte 	if (ncall_modules)
520*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_timedsendnotify)(ncall,
521*fcf3ce44SJohn Forte 		    flags, svc_id, t, ncall_callback, vptr, ap);
522*fcf3ce44SJohn Forte 	va_end(ap);
523*fcf3ce44SJohn Forte 
524*fcf3ce44SJohn Forte 	return (rc);
525*fcf3ce44SJohn Forte }
526*fcf3ce44SJohn Forte 
527*fcf3ce44SJohn Forte int
528*fcf3ce44SJohn Forte ncall_broadcast(ncall_t *ncall, int flags, int svc_id,
529*fcf3ce44SJohn Forte     struct timeval *t, ...)
530*fcf3ce44SJohn Forte {
531*fcf3ce44SJohn Forte 	va_list ap;
532*fcf3ce44SJohn Forte 	int rc = ENOLINK;
533*fcf3ce44SJohn Forte 
534*fcf3ce44SJohn Forte 	va_start(ap, t);
535*fcf3ce44SJohn Forte 
536*fcf3ce44SJohn Forte 	if (ncall_modules)
537*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_broadcast)(ncall, flags,
538*fcf3ce44SJohn Forte 		    svc_id, t, ap);
539*fcf3ce44SJohn Forte 	va_end(ap);
540*fcf3ce44SJohn Forte 
541*fcf3ce44SJohn Forte 	return (rc);
542*fcf3ce44SJohn Forte }
543*fcf3ce44SJohn Forte 
544*fcf3ce44SJohn Forte 
545*fcf3ce44SJohn Forte int
546*fcf3ce44SJohn Forte ncall_send(ncall_t *ncall, int flags, int svc_id, ...)
547*fcf3ce44SJohn Forte {
548*fcf3ce44SJohn Forte 	va_list ap;
549*fcf3ce44SJohn Forte 	int rc = ENOLINK;
550*fcf3ce44SJohn Forte 
551*fcf3ce44SJohn Forte 	va_start(ap, svc_id);
552*fcf3ce44SJohn Forte 
553*fcf3ce44SJohn Forte 	if (ncall_modules)
554*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_timedsend)(ncall, flags,
555*fcf3ce44SJohn Forte 		    svc_id, NULL, ap);
556*fcf3ce44SJohn Forte 
557*fcf3ce44SJohn Forte 	va_end(ap);
558*fcf3ce44SJohn Forte 
559*fcf3ce44SJohn Forte 	return (rc);
560*fcf3ce44SJohn Forte }
561*fcf3ce44SJohn Forte 
562*fcf3ce44SJohn Forte 
563*fcf3ce44SJohn Forte int
564*fcf3ce44SJohn Forte ncall_read_reply(ncall_t *ncall, int n, ...)
565*fcf3ce44SJohn Forte {
566*fcf3ce44SJohn Forte 	va_list ap;
567*fcf3ce44SJohn Forte 	int rc = ENOLINK;
568*fcf3ce44SJohn Forte 
569*fcf3ce44SJohn Forte 	va_start(ap, n);
570*fcf3ce44SJohn Forte 
571*fcf3ce44SJohn Forte 	if (ncall_modules)
572*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_read_reply)(ncall, n, ap);
573*fcf3ce44SJohn Forte 
574*fcf3ce44SJohn Forte 	va_end(ap);
575*fcf3ce44SJohn Forte 
576*fcf3ce44SJohn Forte 	return (rc);
577*fcf3ce44SJohn Forte }
578*fcf3ce44SJohn Forte 
579*fcf3ce44SJohn Forte 
580*fcf3ce44SJohn Forte void
581*fcf3ce44SJohn Forte ncall_reset(ncall_t *ncall)
582*fcf3ce44SJohn Forte {
583*fcf3ce44SJohn Forte 	if (ncall_modules)
584*fcf3ce44SJohn Forte 		(*ncall_modules->module->ncall_reset)(ncall);
585*fcf3ce44SJohn Forte }
586*fcf3ce44SJohn Forte 
587*fcf3ce44SJohn Forte 
588*fcf3ce44SJohn Forte void
589*fcf3ce44SJohn Forte ncall_free(ncall_t *ncall)
590*fcf3ce44SJohn Forte {
591*fcf3ce44SJohn Forte 	if (ncall_modules)
592*fcf3ce44SJohn Forte 		(*ncall_modules->module->ncall_free)(ncall);
593*fcf3ce44SJohn Forte }
594*fcf3ce44SJohn Forte 
595*fcf3ce44SJohn Forte 
596*fcf3ce44SJohn Forte int
597*fcf3ce44SJohn Forte ncall_put_data(ncall_t *ncall, void *data, int len)
598*fcf3ce44SJohn Forte {
599*fcf3ce44SJohn Forte 	int rc = ENOLINK;
600*fcf3ce44SJohn Forte 
601*fcf3ce44SJohn Forte 	if (ncall_modules)
602*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_put_data)(ncall, data, len);
603*fcf3ce44SJohn Forte 
604*fcf3ce44SJohn Forte 	return (rc);
605*fcf3ce44SJohn Forte }
606*fcf3ce44SJohn Forte 
607*fcf3ce44SJohn Forte 
608*fcf3ce44SJohn Forte int
609*fcf3ce44SJohn Forte ncall_get_data(ncall_t *ncall, void *data, int len)
610*fcf3ce44SJohn Forte {
611*fcf3ce44SJohn Forte 	int rc = ENOLINK;
612*fcf3ce44SJohn Forte 
613*fcf3ce44SJohn Forte 	if (ncall_modules)
614*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_get_data)(ncall, data, len);
615*fcf3ce44SJohn Forte 
616*fcf3ce44SJohn Forte 	return (rc);
617*fcf3ce44SJohn Forte }
618*fcf3ce44SJohn Forte 
619*fcf3ce44SJohn Forte 
620*fcf3ce44SJohn Forte int
621*fcf3ce44SJohn Forte ncall_sender(ncall_t *ncall)
622*fcf3ce44SJohn Forte {
623*fcf3ce44SJohn Forte 	int rc = -1;
624*fcf3ce44SJohn Forte 
625*fcf3ce44SJohn Forte 	if (ncall_modules)
626*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_sender)(ncall);
627*fcf3ce44SJohn Forte 
628*fcf3ce44SJohn Forte 	return (rc);
629*fcf3ce44SJohn Forte }
630*fcf3ce44SJohn Forte 
631*fcf3ce44SJohn Forte 
632*fcf3ce44SJohn Forte void
633*fcf3ce44SJohn Forte ncall_reply(ncall_t *ncall, ...)
634*fcf3ce44SJohn Forte {
635*fcf3ce44SJohn Forte 	va_list ap;
636*fcf3ce44SJohn Forte 
637*fcf3ce44SJohn Forte 	if (ncall_modules) {
638*fcf3ce44SJohn Forte 		va_start(ap, ncall);
639*fcf3ce44SJohn Forte 
640*fcf3ce44SJohn Forte 		(*ncall_modules->module->ncall_reply)(ncall, ap);
641*fcf3ce44SJohn Forte 
642*fcf3ce44SJohn Forte 		va_end(ap);
643*fcf3ce44SJohn Forte 	}
644*fcf3ce44SJohn Forte }
645*fcf3ce44SJohn Forte 
646*fcf3ce44SJohn Forte 
647*fcf3ce44SJohn Forte void
648*fcf3ce44SJohn Forte ncall_pend(ncall_t *ncall)
649*fcf3ce44SJohn Forte {
650*fcf3ce44SJohn Forte 	if (ncall_modules)
651*fcf3ce44SJohn Forte 		(*ncall_modules->module->ncall_pend)(ncall);
652*fcf3ce44SJohn Forte }
653*fcf3ce44SJohn Forte 
654*fcf3ce44SJohn Forte 
655*fcf3ce44SJohn Forte void
656*fcf3ce44SJohn Forte ncall_done(ncall_t *ncall)
657*fcf3ce44SJohn Forte {
658*fcf3ce44SJohn Forte 	if (ncall_modules)
659*fcf3ce44SJohn Forte 		(*ncall_modules->module->ncall_done)(ncall);
660*fcf3ce44SJohn Forte }
661*fcf3ce44SJohn Forte 
662*fcf3ce44SJohn Forte int
663*fcf3ce44SJohn Forte ncall_ping(char *nodename, int *up)
664*fcf3ce44SJohn Forte {
665*fcf3ce44SJohn Forte 	int rc = ENOLINK;
666*fcf3ce44SJohn Forte 	if (ncall_modules)
667*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_ping)(nodename, up);
668*fcf3ce44SJohn Forte 	return (rc);
669*fcf3ce44SJohn Forte }
670*fcf3ce44SJohn Forte 
671*fcf3ce44SJohn Forte int
672*fcf3ce44SJohn Forte ncall_maxnodes()
673*fcf3ce44SJohn Forte {
674*fcf3ce44SJohn Forte 	int rc = 0;
675*fcf3ce44SJohn Forte 
676*fcf3ce44SJohn Forte 	if (ncall_modules)
677*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_maxnodes)();
678*fcf3ce44SJohn Forte 
679*fcf3ce44SJohn Forte 	return (rc);
680*fcf3ce44SJohn Forte }
681*fcf3ce44SJohn Forte 
682*fcf3ce44SJohn Forte int
683*fcf3ce44SJohn Forte ncall_nextnode(void **vptr)
684*fcf3ce44SJohn Forte {
685*fcf3ce44SJohn Forte 	int rc = 0;
686*fcf3ce44SJohn Forte 
687*fcf3ce44SJohn Forte 	if (ncall_modules)
688*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_nextnode)(vptr);
689*fcf3ce44SJohn Forte 
690*fcf3ce44SJohn Forte 	return (rc);
691*fcf3ce44SJohn Forte }
692*fcf3ce44SJohn Forte 
693*fcf3ce44SJohn Forte int
694*fcf3ce44SJohn Forte ncall_errcode(ncall_t *ncall, int *result)
695*fcf3ce44SJohn Forte {
696*fcf3ce44SJohn Forte 	int rc = ENOLINK;
697*fcf3ce44SJohn Forte 	if (ncall_modules)
698*fcf3ce44SJohn Forte 		rc = (*ncall_modules->module->ncall_errcode)(ncall, result);
699*fcf3ce44SJohn Forte 
700*fcf3ce44SJohn Forte 	return (rc);
701*fcf3ce44SJohn Forte }
702*fcf3ce44SJohn Forte 
703*fcf3ce44SJohn Forte static int
704*fcf3ce44SJohn Forte ncallgetnodes(intptr_t uaddr, int mode, int *rvalp)
705*fcf3ce44SJohn Forte {
706*fcf3ce44SJohn Forte 	ncall_node_t *nodelist;
707*fcf3ce44SJohn Forte 	int slot;
708*fcf3ce44SJohn Forte 	int rc;
709*fcf3ce44SJohn Forte 	int nodecnt;
710*fcf3ce44SJohn Forte 	int nodeid;
711*fcf3ce44SJohn Forte 	void *sequence;
712*fcf3ce44SJohn Forte 	char *nodename;
713*fcf3ce44SJohn Forte 
714*fcf3ce44SJohn Forte 	rc = 0;
715*fcf3ce44SJohn Forte 
716*fcf3ce44SJohn Forte 	nodecnt = ncall_maxnodes();
717*fcf3ce44SJohn Forte 	if (nodecnt <= 0) {
718*fcf3ce44SJohn Forte 		return (ENONET);
719*fcf3ce44SJohn Forte 	}
720*fcf3ce44SJohn Forte 
721*fcf3ce44SJohn Forte 	/*
722*fcf3ce44SJohn Forte 	 * If the user passes up a null address argument, then
723*fcf3ce44SJohn Forte 	 * he/she doesn't want the actual nodes, but the configured
724*fcf3ce44SJohn Forte 	 * maximum, so space can be correctly allocated.
725*fcf3ce44SJohn Forte 	 */
726*fcf3ce44SJohn Forte 
727*fcf3ce44SJohn Forte 	if (uaddr == NULL) {
728*fcf3ce44SJohn Forte 		*rvalp = nodecnt;
729*fcf3ce44SJohn Forte 		return (0);
730*fcf3ce44SJohn Forte 	}
731*fcf3ce44SJohn Forte 	nodelist = kmem_zalloc(sizeof (*nodelist) * nodecnt, KM_SLEEP);
732*fcf3ce44SJohn Forte 
733*fcf3ce44SJohn Forte 	slot = 0;
734*fcf3ce44SJohn Forte 	sequence = NULL;
735*fcf3ce44SJohn Forte 	while ((nodeid = ncall_nextnode(&sequence)) > 0) {
736*fcf3ce44SJohn Forte 		nodename = ncall_nodename(nodeid);
737*fcf3ce44SJohn Forte 		/*
738*fcf3ce44SJohn Forte 		 * There is a small window where nextnode can
739*fcf3ce44SJohn Forte 		 * return a valid nodeid, and it being disabled
740*fcf3ce44SJohn Forte 		 * which will get nodename to return "".
741*fcf3ce44SJohn Forte 		 * Discard the nodeid if this happens.
742*fcf3ce44SJohn Forte 		 */
743*fcf3ce44SJohn Forte 		if (strlen(nodename) > 0) {
744*fcf3ce44SJohn Forte 			int size = sizeof (nodelist[slot].nc_nodename) - 1;
745*fcf3ce44SJohn Forte 			ASSERT(slot < nodecnt);
746*fcf3ce44SJohn Forte 			/*
747*fcf3ce44SJohn Forte 			 * make sure its null terminated when it
748*fcf3ce44SJohn Forte 			 * gets to userland.
749*fcf3ce44SJohn Forte 			 */
750*fcf3ce44SJohn Forte 			nodelist[slot].nc_nodename[size] = 0;
751*fcf3ce44SJohn Forte 			(void) strncpy(nodelist[slot].nc_nodename, nodename,
752*fcf3ce44SJohn Forte 			    size);
753*fcf3ce44SJohn Forte 			nodelist[slot].nc_nodeid = nodeid;
754*fcf3ce44SJohn Forte 			slot++;
755*fcf3ce44SJohn Forte 		}
756*fcf3ce44SJohn Forte 	}
757*fcf3ce44SJohn Forte 	if (ddi_copyout(nodelist, (void *)uaddr, sizeof (*nodelist) * slot,
758*fcf3ce44SJohn Forte 	    mode) < 0) {
759*fcf3ce44SJohn Forte 		rc = EFAULT;
760*fcf3ce44SJohn Forte 	} else {
761*fcf3ce44SJohn Forte 		/*
762*fcf3ce44SJohn Forte 		 * tell them how many have come back.
763*fcf3ce44SJohn Forte 		 */
764*fcf3ce44SJohn Forte 		*rvalp = slot;
765*fcf3ce44SJohn Forte 	}
766*fcf3ce44SJohn Forte 	kmem_free(nodelist, sizeof (*nodelist) * nodecnt);
767*fcf3ce44SJohn Forte 	return (rc);
768*fcf3ce44SJohn Forte }
769