xref: /titanic_52/usr/src/uts/common/avs/ns/nsctl/nsctl.c (revision b97d6ca7333c353b6ca20c20c99fb1be8d32a8de)
1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte /*
22d9d73587SMark J Musante  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23fcf3ce44SJohn Forte  * Use is subject to license terms.
24*b97d6ca7SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27fcf3ce44SJohn Forte #include <sys/types.h>
28fcf3ce44SJohn Forte #include <sys/ksynch.h>
29fcf3ce44SJohn Forte #include <sys/kmem.h>
30fcf3ce44SJohn Forte #include <sys/file.h>
31fcf3ce44SJohn Forte #include <sys/errno.h>
32fcf3ce44SJohn Forte #include <sys/open.h>
33fcf3ce44SJohn Forte #include <sys/cred.h>
34fcf3ce44SJohn Forte #include <sys/conf.h>
35fcf3ce44SJohn Forte #include <sys/uio.h>
36fcf3ce44SJohn Forte #include <sys/cmn_err.h>
37fcf3ce44SJohn Forte #include <sys/modctl.h>
38fcf3ce44SJohn Forte #include <sys/ddi.h>
39fcf3ce44SJohn Forte 
40fcf3ce44SJohn Forte #define	__NSC_GEN__
41fcf3ce44SJohn Forte #include <sys/nsctl/nsc_dev.h>
42fcf3ce44SJohn Forte #include <sys/nsctl/nsc_gen.h>
43fcf3ce44SJohn Forte #include <sys/nsctl/nsc_ioctl.h>
44fcf3ce44SJohn Forte #include <sys/nsctl/nsc_power.h>
45fcf3ce44SJohn Forte #include <sys/nsctl/nsc_mem.h>
46fcf3ce44SJohn Forte #include "../nsctl.h"
47fcf3ce44SJohn Forte 
48fcf3ce44SJohn Forte #include <sys/nsctl/nsvers.h>
49fcf3ce44SJohn Forte 
50fcf3ce44SJohn Forte #ifdef DS_DDICT
51fcf3ce44SJohn Forte #include "../contract.h"
52fcf3ce44SJohn Forte #endif
53fcf3ce44SJohn Forte 
54fcf3ce44SJohn Forte extern void nscsetup();
55*b97d6ca7SMilan Jurik extern int _nsc_init_raw(int);
56fcf3ce44SJohn Forte extern void _nsc_deinit_raw();
57fcf3ce44SJohn Forte extern void _nsc_init_start();
58fcf3ce44SJohn Forte extern void _nsc_init_os(), _nsc_deinit_os();
59fcf3ce44SJohn Forte extern void _nsc_init_dev(), _nsc_init_mem();
60fcf3ce44SJohn Forte extern void _nsc_init_gen(), _nsc_init_rmlock();
61fcf3ce44SJohn Forte extern void _nsc_init_resv(), _nsc_deinit_resv();
62fcf3ce44SJohn Forte extern void _nsc_init_frz(), _nsc_deinit_frz();
63fcf3ce44SJohn Forte extern void _nsc_init_ncio(), _nsc_deinit_ncio();
64fcf3ce44SJohn Forte extern void _nsc_deinit_mem(), _nsc_deinit_rmlock();
65fcf3ce44SJohn Forte extern void _nsc_deinit_dev();
66fcf3ce44SJohn Forte 
67*b97d6ca7SMilan Jurik extern int _nsc_frz_start(char *, int *);
68*b97d6ca7SMilan Jurik extern int _nsc_frz_stop(char *, int *);
69*b97d6ca7SMilan Jurik extern int _nsc_frz_isfrozen(char *, int *);
70fcf3ce44SJohn Forte 
71fcf3ce44SJohn Forte extern nsc_mem_t *_nsc_local_mem;
72fcf3ce44SJohn Forte extern nsc_rmhdr_t *_nsc_rmhdr_ptr;
73fcf3ce44SJohn Forte extern nsc_def_t _nsc_raw_def[];
74fcf3ce44SJohn Forte extern int _nsc_raw_flags;
75fcf3ce44SJohn Forte 
76fcf3ce44SJohn Forte int nsc_devflag = D_MP;
77fcf3ce44SJohn Forte 
78fcf3ce44SJohn Forte int _nsc_init_done = 0;
79fcf3ce44SJohn Forte 
80fcf3ce44SJohn Forte kmutex_t _nsc_drv_lock;
81fcf3ce44SJohn Forte nsc_io_t *_nsc_file_io;
82fcf3ce44SJohn Forte nsc_io_t *_nsc_vchr_io;
83fcf3ce44SJohn Forte nsc_io_t *_nsc_raw_io;
84fcf3ce44SJohn Forte 
85fcf3ce44SJohn Forte nsc_fd_t **_nsc_minor_fd;
86fcf3ce44SJohn Forte kmutex_t **_nsc_minor_slp;
87fcf3ce44SJohn Forte 
88fcf3ce44SJohn Forte 
89fcf3ce44SJohn Forte /* Maximum number of devices - tunable in nsctl.conf */
90fcf3ce44SJohn Forte static int _nsc_max_devices;
91fcf3ce44SJohn Forte 
92fcf3ce44SJohn Forte /* Internal version of _nsc_max_devices */
93fcf3ce44SJohn Forte int _nsc_maxdev;
94fcf3ce44SJohn Forte 
95fcf3ce44SJohn Forte extern void _nsc_global_setup(void);
96fcf3ce44SJohn Forte 
97fcf3ce44SJohn Forte static int nsc_load(), nsc_unload();
98d9d73587SMark J Musante static void nscteardown();
99fcf3ce44SJohn Forte 
100fcf3ce44SJohn Forte /*
101fcf3ce44SJohn Forte  * Solaris specific driver module interface code.
102fcf3ce44SJohn Forte  */
103fcf3ce44SJohn Forte 
104fcf3ce44SJohn Forte extern int nscopen(dev_t *, int, int, cred_t *);
105fcf3ce44SJohn Forte extern int nscioctl(dev_t, int, intptr_t, int, cred_t *, int *);
106fcf3ce44SJohn Forte extern int nscclose(dev_t, int, int, cred_t *);
107fcf3ce44SJohn Forte extern int nscread(dev_t, uio_t *, cred_t *);
108fcf3ce44SJohn Forte extern int nscwrite(dev_t, uio_t *, cred_t *);
109fcf3ce44SJohn Forte 
110fcf3ce44SJohn Forte static dev_info_t *nsctl_dip;		/* Single DIP for driver */
111fcf3ce44SJohn Forte 
112fcf3ce44SJohn Forte static int _nsctl_print(dev_t, char *);
113fcf3ce44SJohn Forte 
114fcf3ce44SJohn Forte static	struct	cb_ops nsctl_cb_ops = {
115fcf3ce44SJohn Forte 	nscopen,		/* open */
116fcf3ce44SJohn Forte 	nscclose,	/* close */
117fcf3ce44SJohn Forte 	nodev,		/* not a block driver, strategy not an entry point */
118fcf3ce44SJohn Forte 	_nsctl_print,	/* no print routine */
119fcf3ce44SJohn Forte 	nodev,		/* no dump routine */
120fcf3ce44SJohn Forte 	nscread,		/* read */
121fcf3ce44SJohn Forte 	nscwrite,	/* write */
122fcf3ce44SJohn Forte 	(int (*)()) nscioctl,	/* ioctl */
123fcf3ce44SJohn Forte 	nodev,		/* no devmap routine */
124fcf3ce44SJohn Forte 	nodev,		/* no mmap routine */
125fcf3ce44SJohn Forte 	nodev,		/* no segmap routine */
126fcf3ce44SJohn Forte 	nochpoll,	/* no chpoll routine */
127fcf3ce44SJohn Forte 	ddi_prop_op,
128fcf3ce44SJohn Forte 	0,		/* not a STREAMS driver, no cb_str routine */
129fcf3ce44SJohn Forte 	D_NEW | D_MP | D_64BIT,	/* safe for multi-thread/multi-processor */
130fcf3ce44SJohn Forte 	CB_REV,
131fcf3ce44SJohn Forte 	nodev,		/* aread */
132fcf3ce44SJohn Forte 	nodev,		/* awrite */
133fcf3ce44SJohn Forte };
134fcf3ce44SJohn Forte 
135fcf3ce44SJohn Forte static int _nsctl_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
136fcf3ce44SJohn Forte static int _nsctl_attach(dev_info_t *, ddi_attach_cmd_t);
137fcf3ce44SJohn Forte static int _nsctl_detach(dev_info_t *, ddi_detach_cmd_t);
138fcf3ce44SJohn Forte 
139fcf3ce44SJohn Forte static	struct	dev_ops nsctl_ops = {
140fcf3ce44SJohn Forte 	DEVO_REV,			/* Driver build version */
141fcf3ce44SJohn Forte 	0,				/* device reference count */
142fcf3ce44SJohn Forte 	_nsctl_getinfo,
143fcf3ce44SJohn Forte 	nulldev,			/* Identify */
144fcf3ce44SJohn Forte 	nulldev,			/* Probe */
145fcf3ce44SJohn Forte 	_nsctl_attach,
146fcf3ce44SJohn Forte 	_nsctl_detach,
147fcf3ce44SJohn Forte 	nodev,				/* Reset */
148fcf3ce44SJohn Forte 	&nsctl_cb_ops,
149fcf3ce44SJohn Forte 	(struct bus_ops *)0
150fcf3ce44SJohn Forte };
151fcf3ce44SJohn Forte 
152fcf3ce44SJohn Forte static struct modldrv nsctl_ldrv = {
153fcf3ce44SJohn Forte 	&mod_driverops,
154fcf3ce44SJohn Forte 	"nws:Control:" ISS_VERSION_STR,
155fcf3ce44SJohn Forte 	&nsctl_ops
156fcf3ce44SJohn Forte };
157fcf3ce44SJohn Forte 
158fcf3ce44SJohn Forte static	struct modlinkage nsctl_modlinkage = {
159fcf3ce44SJohn Forte 	MODREV_1,
160fcf3ce44SJohn Forte 	&nsctl_ldrv,
161fcf3ce44SJohn Forte 	NULL
162fcf3ce44SJohn Forte };
163fcf3ce44SJohn Forte 
164fcf3ce44SJohn Forte /*
165fcf3ce44SJohn Forte  * Solaris module load time code
166fcf3ce44SJohn Forte  */
167fcf3ce44SJohn Forte 
168fcf3ce44SJohn Forte int nsc_min_nodeid;
169fcf3ce44SJohn Forte int nsc_max_nodeid;
170fcf3ce44SJohn Forte 
171fcf3ce44SJohn Forte int
172fcf3ce44SJohn Forte _init(void)
173fcf3ce44SJohn Forte {
174fcf3ce44SJohn Forte 	int err;
175fcf3ce44SJohn Forte 
176fcf3ce44SJohn Forte 	err = nsc_load();
177fcf3ce44SJohn Forte 
178fcf3ce44SJohn Forte 	if (!err)
179fcf3ce44SJohn Forte 		err = mod_install(&nsctl_modlinkage);
180fcf3ce44SJohn Forte 
181fcf3ce44SJohn Forte 	if (err) {
182fcf3ce44SJohn Forte 		(void) nsc_unload();
1833270659fSSrikanth, Ramana 		cmn_err(CE_NOTE, "!nsctl_init: err %d", err);
184fcf3ce44SJohn Forte 	}
185fcf3ce44SJohn Forte 
186fcf3ce44SJohn Forte 	return (err);
187fcf3ce44SJohn Forte 
188fcf3ce44SJohn Forte }
189fcf3ce44SJohn Forte 
190fcf3ce44SJohn Forte /*
191fcf3ce44SJohn Forte  * Solaris module unload time code
192fcf3ce44SJohn Forte  */
193fcf3ce44SJohn Forte 
194fcf3ce44SJohn Forte int
195fcf3ce44SJohn Forte _fini(void)
196fcf3ce44SJohn Forte {
197fcf3ce44SJohn Forte 	int err;
198fcf3ce44SJohn Forte 
199fcf3ce44SJohn Forte 	if ((err = mod_remove(&nsctl_modlinkage)) == 0) {
200fcf3ce44SJohn Forte 		err = nsc_unload();
201fcf3ce44SJohn Forte 	}
202fcf3ce44SJohn Forte 	return (err);
203fcf3ce44SJohn Forte }
204fcf3ce44SJohn Forte 
205fcf3ce44SJohn Forte /*
206fcf3ce44SJohn Forte  * Solaris module info code
207fcf3ce44SJohn Forte  */
208fcf3ce44SJohn Forte int
209fcf3ce44SJohn Forte _info(struct modinfo *modinfop)
210fcf3ce44SJohn Forte {
211fcf3ce44SJohn Forte 	return (mod_info(&nsctl_modlinkage, modinfop));
212fcf3ce44SJohn Forte }
213fcf3ce44SJohn Forte 
214fcf3ce44SJohn Forte /*
215fcf3ce44SJohn Forte  * Attach an instance of the device. This happens before an open
216fcf3ce44SJohn Forte  * can succeed.
217fcf3ce44SJohn Forte  */
218fcf3ce44SJohn Forte static int
219fcf3ce44SJohn Forte _nsctl_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
220fcf3ce44SJohn Forte {
221fcf3ce44SJohn Forte 	int rc;
222fcf3ce44SJohn Forte 
223fcf3ce44SJohn Forte 	if (cmd == DDI_ATTACH) {
224fcf3ce44SJohn Forte 		nsctl_dip = dip;
225fcf3ce44SJohn Forte 
226fcf3ce44SJohn Forte 		/* Announce presence of the device */
227fcf3ce44SJohn Forte 		ddi_report_dev(dip);
228fcf3ce44SJohn Forte 
229fcf3ce44SJohn Forte 		/*
230fcf3ce44SJohn Forte 		 * Get the node parameters now that we can look up.
231fcf3ce44SJohn Forte 		 */
232fcf3ce44SJohn Forte 		nsc_min_nodeid = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
233fcf3ce44SJohn Forte 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
234fcf3ce44SJohn Forte 		    "nsc_min_nodeid", 0);
235fcf3ce44SJohn Forte 
236fcf3ce44SJohn Forte 		nsc_max_nodeid = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
237fcf3ce44SJohn Forte 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
238fcf3ce44SJohn Forte 		    "nsc_max_nodeid", 5);
239fcf3ce44SJohn Forte 
240fcf3ce44SJohn Forte 		_nsc_max_devices = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
241fcf3ce44SJohn Forte 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
242fcf3ce44SJohn Forte 		    "nsc_max_devices", 128);
243fcf3ce44SJohn Forte 
244fcf3ce44SJohn Forte 		_nsc_maxdev = _nsc_max_devices;
245fcf3ce44SJohn Forte 		nscsetup();
246fcf3ce44SJohn Forte 
247fcf3ce44SJohn Forte 		/*
248fcf3ce44SJohn Forte 		 * Init raw requires the _nsc_max_devices value and so
249fcf3ce44SJohn Forte 		 * cannot be done before the nsc_max_devices property has
250fcf3ce44SJohn Forte 		 * been read which can only be done after the module is
251fcf3ce44SJohn Forte 		 * attached and we have a dip.
252fcf3ce44SJohn Forte 		 */
253fcf3ce44SJohn Forte 
254fcf3ce44SJohn Forte 		if ((rc = _nsc_init_raw(_nsc_max_devices)) != 0) {
255fcf3ce44SJohn Forte 			cmn_err(CE_WARN,
2563270659fSSrikanth, Ramana 			    "!nsctl: unable to initialize raw io provider: %d",
257fcf3ce44SJohn Forte 			    rc);
258fcf3ce44SJohn Forte 			return (DDI_FAILURE);
259fcf3ce44SJohn Forte 		}
260fcf3ce44SJohn Forte 
261fcf3ce44SJohn Forte 		/*
262fcf3ce44SJohn Forte 		 * Init rest of soft state structure
263fcf3ce44SJohn Forte 		 */
264fcf3ce44SJohn Forte 
265fcf3ce44SJohn Forte 		rc = ddi_create_minor_node(dip, "c,nsctl", S_IFCHR, 0,
266fcf3ce44SJohn Forte 		    DDI_PSEUDO, 0);
267fcf3ce44SJohn Forte 		if (rc != DDI_SUCCESS) {
268fcf3ce44SJohn Forte 			/* free anything we allocated here */
269fcf3ce44SJohn Forte 			cmn_err(CE_WARN,
2703270659fSSrikanth, Ramana 			    "!_nsctl_attach: ddi_create_minor_node failed %d",
271fcf3ce44SJohn Forte 			    rc);
272fcf3ce44SJohn Forte 			return (DDI_FAILURE);
273fcf3ce44SJohn Forte 		}
274fcf3ce44SJohn Forte 
275fcf3ce44SJohn Forte 		/* Announce presence of the device */
276fcf3ce44SJohn Forte 		ddi_report_dev(dip);
277fcf3ce44SJohn Forte 
278fcf3ce44SJohn Forte 		/* mark the device as attached, opens may proceed */
279fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
280fcf3ce44SJohn Forte 	} else
281fcf3ce44SJohn Forte 		return (DDI_FAILURE);
282fcf3ce44SJohn Forte }
283fcf3ce44SJohn Forte 
284fcf3ce44SJohn Forte static int
285fcf3ce44SJohn Forte _nsctl_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
286fcf3ce44SJohn Forte {
287fcf3ce44SJohn Forte 	if (cmd == DDI_DETACH) {
288d9d73587SMark J Musante 		nscteardown();
289fcf3ce44SJohn Forte 		_nsc_deinit_raw();
290fcf3ce44SJohn Forte 
291fcf3ce44SJohn Forte 		ddi_remove_minor_node(dip, NULL);
292fcf3ce44SJohn Forte 		nsctl_dip = NULL;
293fcf3ce44SJohn Forte 
294fcf3ce44SJohn Forte 		return (DDI_SUCCESS);
295fcf3ce44SJohn Forte 	}
296fcf3ce44SJohn Forte 	else
297fcf3ce44SJohn Forte 		return (DDI_FAILURE);
298fcf3ce44SJohn Forte }
299fcf3ce44SJohn Forte 
300fcf3ce44SJohn Forte 
301fcf3ce44SJohn Forte /* ARGSUSED */
302fcf3ce44SJohn Forte static int
303fcf3ce44SJohn Forte _nsctl_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
304fcf3ce44SJohn Forte {
305fcf3ce44SJohn Forte 	dev_t dev;
306fcf3ce44SJohn Forte 	int rc;
307fcf3ce44SJohn Forte 
308fcf3ce44SJohn Forte 	switch (cmd) {
309fcf3ce44SJohn Forte 		case DDI_INFO_DEVT2INSTANCE:
310fcf3ce44SJohn Forte 			/* The "instance" number is the minor number */
311fcf3ce44SJohn Forte 			dev = (dev_t)arg;
312fcf3ce44SJohn Forte 			*result = (void *)(unsigned long)getminor(dev);
313fcf3ce44SJohn Forte 			rc = DDI_SUCCESS;
314fcf3ce44SJohn Forte 			break;
315fcf3ce44SJohn Forte 
316fcf3ce44SJohn Forte 		case DDI_INFO_DEVT2DEVINFO:
317fcf3ce44SJohn Forte 			*result = nsctl_dip;
318fcf3ce44SJohn Forte 			rc = DDI_SUCCESS;
319fcf3ce44SJohn Forte 			break;
320fcf3ce44SJohn Forte 
321fcf3ce44SJohn Forte 		default:
322fcf3ce44SJohn Forte 			rc = DDI_FAILURE;
323fcf3ce44SJohn Forte 			break;
324fcf3ce44SJohn Forte 	}
325fcf3ce44SJohn Forte 
326fcf3ce44SJohn Forte 	return (rc);
327fcf3ce44SJohn Forte }
328fcf3ce44SJohn Forte 
329fcf3ce44SJohn Forte 
330fcf3ce44SJohn Forte /* ARGSUSED */
331fcf3ce44SJohn Forte static int
332fcf3ce44SJohn Forte _nsctl_print(dev_t dev, char *s)
333fcf3ce44SJohn Forte {
3343270659fSSrikanth, Ramana 	cmn_err(CE_WARN, "!nsctl:%s", s);
335fcf3ce44SJohn Forte 	return (0);
336fcf3ce44SJohn Forte }
337fcf3ce44SJohn Forte 
338fcf3ce44SJohn Forte 
339fcf3ce44SJohn Forte void
340fcf3ce44SJohn Forte nsc_init()
341fcf3ce44SJohn Forte {
342fcf3ce44SJohn Forte 	if (_nsc_init_done)
343fcf3ce44SJohn Forte 		return;
344fcf3ce44SJohn Forte 
345fcf3ce44SJohn Forte 	_nsc_init_start();
346fcf3ce44SJohn Forte 	_nsc_init_gen();
347fcf3ce44SJohn Forte 	_nsc_init_svc();
348fcf3ce44SJohn Forte 	_nsc_init_mem();
349fcf3ce44SJohn Forte 	_nsc_init_dev();
350fcf3ce44SJohn Forte 	_nsc_init_rmlock();
351fcf3ce44SJohn Forte 	_nsc_init_resv();
352fcf3ce44SJohn Forte 	_nsc_init_os();
353fcf3ce44SJohn Forte 	(void) _nsc_init_power();
354fcf3ce44SJohn Forte 
355fcf3ce44SJohn Forte 	/*
356fcf3ce44SJohn Forte 	 * When using mc, nscsetup is done through mc callback to global_init.
357fcf3ce44SJohn Forte 	 */
358fcf3ce44SJohn Forte 	nscsetup();
359fcf3ce44SJohn Forte 
360fcf3ce44SJohn Forte 	mutex_init(&_nsc_drv_lock, NULL, MUTEX_DRIVER, NULL);
361fcf3ce44SJohn Forte 
362fcf3ce44SJohn Forte 	_nsc_raw_io = nsc_register_io("raw",
363fcf3ce44SJohn Forte 	    NSC_RAW_ID | _nsc_raw_flags, _nsc_raw_def);
364fcf3ce44SJohn Forte 
365fcf3ce44SJohn Forte 	if (!_nsc_raw_io)
3663270659fSSrikanth, Ramana 		cmn_err(CE_WARN, "!_nsc_init: register io failed - raw");
367fcf3ce44SJohn Forte 
368fcf3ce44SJohn Forte 	_nsc_init_ncio();
369fcf3ce44SJohn Forte 	_nsc_init_frz();
370fcf3ce44SJohn Forte 
371fcf3ce44SJohn Forte 	_nsc_init_done = 1;
372fcf3ce44SJohn Forte }
373fcf3ce44SJohn Forte 
374fcf3ce44SJohn Forte 
375fcf3ce44SJohn Forte /*
376fcf3ce44SJohn Forte  * Called after the mc refresh is complete (SEG_INIT callbacks have
377fcf3ce44SJohn Forte  * been received) and module _attach() is done.  Only does any real
378fcf3ce44SJohn Forte  * work when all of the above conditions have been met.
379fcf3ce44SJohn Forte  */
380fcf3ce44SJohn Forte void
381fcf3ce44SJohn Forte nscsetup()
382fcf3ce44SJohn Forte {
383d9d73587SMark J Musante 	if (nsc_max_devices() == 0 || _nsc_minor_fd != NULL)
384fcf3ce44SJohn Forte 		return;
385fcf3ce44SJohn Forte 
386fcf3ce44SJohn Forte 	_nsc_minor_fd = nsc_kmem_zalloc(sizeof (nsc_fd_t *)*_nsc_maxdev,
387fcf3ce44SJohn Forte 	    0, _nsc_local_mem);
388fcf3ce44SJohn Forte 
389d9d73587SMark J Musante 	if (!_nsc_minor_fd) {
3903270659fSSrikanth, Ramana 		cmn_err(CE_WARN, "!nscsetup - alloc failed");
391d9d73587SMark J Musante 		return;
392d9d73587SMark J Musante 	}
393d9d73587SMark J Musante 
394fcf3ce44SJohn Forte 	_nsc_minor_slp = nsc_kmem_zalloc(sizeof (kmutex_t *)*_nsc_maxdev,
395fcf3ce44SJohn Forte 	    0, _nsc_local_mem);
396fcf3ce44SJohn Forte 
397d9d73587SMark J Musante 	if (!_nsc_minor_slp)  {
3983270659fSSrikanth, Ramana 		cmn_err(CE_WARN, "!nscsetup - alloc failed");
399d9d73587SMark J Musante 		nsc_kmem_free(_nsc_minor_fd, sizeof (nsc_fd_t *) * _nsc_maxdev);
400d9d73587SMark J Musante 		_nsc_minor_fd = (nsc_fd_t **)NULL;
401d9d73587SMark J Musante 	}
402fcf3ce44SJohn Forte }
403fcf3ce44SJohn Forte 
404d9d73587SMark J Musante static void
405d9d73587SMark J Musante nscteardown()
406d9d73587SMark J Musante {
407d9d73587SMark J Musante 	int i;
408d9d73587SMark J Musante 
409d9d73587SMark J Musante 	if (_nsc_minor_fd == NULL)
410d9d73587SMark J Musante 		return;
411d9d73587SMark J Musante 
412d9d73587SMark J Musante #ifdef DEBUG
413d9d73587SMark J Musante 	/* Check all devices were closed.  Index 0 is the prototype dev. */
414d9d73587SMark J Musante 	for (i = 1; i < _nsc_maxdev; i++) {
415d9d73587SMark J Musante 		ASSERT(_nsc_minor_slp[i] == NULL);
416d9d73587SMark J Musante 		ASSERT(_nsc_minor_fd[i] == NULL);
417d9d73587SMark J Musante 	}
418d9d73587SMark J Musante #endif /* DEBUG */
419d9d73587SMark J Musante 
420d9d73587SMark J Musante 	nsc_kmem_free(_nsc_minor_fd, sizeof (nsc_fd_t *) * _nsc_maxdev);
421d9d73587SMark J Musante 	nsc_kmem_free(_nsc_minor_slp, sizeof (kmutex_t *) * _nsc_maxdev);
422d9d73587SMark J Musante 
423d9d73587SMark J Musante 	_nsc_minor_fd = (nsc_fd_t **)NULL;
424d9d73587SMark J Musante 	_nsc_minor_slp = (kmutex_t **)NULL;
425d9d73587SMark J Musante }
426fcf3ce44SJohn Forte 
427fcf3ce44SJohn Forte int
428fcf3ce44SJohn Forte nsc_load()
429fcf3ce44SJohn Forte {
430fcf3ce44SJohn Forte 	nsc_init();
431fcf3ce44SJohn Forte 	return (0);
432fcf3ce44SJohn Forte }
433fcf3ce44SJohn Forte 
434fcf3ce44SJohn Forte 
435fcf3ce44SJohn Forte int
436fcf3ce44SJohn Forte nsc_unload()
437fcf3ce44SJohn Forte {
438fcf3ce44SJohn Forte 	if (!_nsc_init_done) {
439fcf3ce44SJohn Forte 		return (0);
440fcf3ce44SJohn Forte 	}
441fcf3ce44SJohn Forte 
442d9d73587SMark J Musante 	nscteardown();
443d9d73587SMark J Musante 
444fcf3ce44SJohn Forte 	(void) _nsc_deinit_power();
445fcf3ce44SJohn Forte 	_nsc_deinit_resv();
446fcf3ce44SJohn Forte 	_nsc_deinit_mem();
447fcf3ce44SJohn Forte 	_nsc_deinit_rmlock();
448fcf3ce44SJohn Forte 	_nsc_deinit_svc();
449fcf3ce44SJohn Forte 	_nsc_deinit_frz();
450fcf3ce44SJohn Forte 	_nsc_deinit_ncio();
451fcf3ce44SJohn Forte 
452fcf3ce44SJohn Forte 	if (_nsc_vchr_io)
453fcf3ce44SJohn Forte 		(void) nsc_unregister_io(_nsc_vchr_io, 0);
454fcf3ce44SJohn Forte 
455fcf3ce44SJohn Forte 	if (_nsc_file_io)
456fcf3ce44SJohn Forte 		(void) nsc_unregister_io(_nsc_file_io, 0);
457fcf3ce44SJohn Forte 
458fcf3ce44SJohn Forte 	_nsc_vchr_io = NULL;
459fcf3ce44SJohn Forte 	_nsc_file_io = NULL;
460fcf3ce44SJohn Forte 
461fcf3ce44SJohn Forte 	if (_nsc_raw_io)
462fcf3ce44SJohn Forte 		(void) nsc_unregister_io(_nsc_raw_io, 0);
463fcf3ce44SJohn Forte 
464fcf3ce44SJohn Forte 	_nsc_raw_io = NULL;
465fcf3ce44SJohn Forte 
466fcf3ce44SJohn Forte 	_nsc_deinit_dev();
467fcf3ce44SJohn Forte 	_nsc_deinit_os();
468fcf3ce44SJohn Forte 
469fcf3ce44SJohn Forte 	_nsc_init_done = 0;
470fcf3ce44SJohn Forte 	return (0);
471fcf3ce44SJohn Forte }
472fcf3ce44SJohn Forte 
473fcf3ce44SJohn Forte 
474fcf3ce44SJohn Forte /* ARGSUSED */
475fcf3ce44SJohn Forte 
476fcf3ce44SJohn Forte int
477fcf3ce44SJohn Forte nscopen(dev_t *devp, int flag, int otyp, cred_t *crp)
478fcf3ce44SJohn Forte {
479fcf3ce44SJohn Forte 	kmutex_t *slp;
480fcf3ce44SJohn Forte 	int i, error;
481fcf3ce44SJohn Forte 
482fcf3ce44SJohn Forte 	if (error = drv_priv(crp))
483fcf3ce44SJohn Forte 		return (error);
484fcf3ce44SJohn Forte 
485fcf3ce44SJohn Forte 	if (!_nsc_minor_fd || !_nsc_minor_slp)
486fcf3ce44SJohn Forte 		return (ENXIO);
487fcf3ce44SJohn Forte 
488fcf3ce44SJohn Forte 	if (getminor(*devp) != 0)
489fcf3ce44SJohn Forte 		return (ENXIO);
490fcf3ce44SJohn Forte 
491fcf3ce44SJohn Forte 	slp = nsc_kmem_alloc(sizeof (kmutex_t), 0, _nsc_local_mem);
492fcf3ce44SJohn Forte 	mutex_init(slp, NULL, MUTEX_DRIVER, NULL);
493fcf3ce44SJohn Forte 
494fcf3ce44SJohn Forte 	mutex_enter(&_nsc_drv_lock);
495fcf3ce44SJohn Forte 
496fcf3ce44SJohn Forte 	for (i = 1; i < _nsc_maxdev; i++) {
497fcf3ce44SJohn Forte 		if (_nsc_minor_slp[i] == NULL) {
498fcf3ce44SJohn Forte 			_nsc_minor_slp[i] = slp;
499fcf3ce44SJohn Forte 			break;
500fcf3ce44SJohn Forte 		}
501fcf3ce44SJohn Forte 	}
502fcf3ce44SJohn Forte 
503fcf3ce44SJohn Forte 	mutex_exit(&_nsc_drv_lock);
504fcf3ce44SJohn Forte 
505fcf3ce44SJohn Forte 	if (i >= _nsc_maxdev) {
506fcf3ce44SJohn Forte 		mutex_destroy(slp);
507fcf3ce44SJohn Forte 		nsc_kmem_free(slp, sizeof (kmutex_t));
508fcf3ce44SJohn Forte 		return (EAGAIN);
509fcf3ce44SJohn Forte 	}
510fcf3ce44SJohn Forte 
511fcf3ce44SJohn Forte 	*devp = makedevice(getmajor(*devp), i);
512fcf3ce44SJohn Forte 
513fcf3ce44SJohn Forte 	return (0);
514fcf3ce44SJohn Forte }
515fcf3ce44SJohn Forte 
516fcf3ce44SJohn Forte 
517fcf3ce44SJohn Forte int
518fcf3ce44SJohn Forte _nscopen(dev_t dev, intptr_t arg, int mode, int *rvp)
519fcf3ce44SJohn Forte {
520fcf3ce44SJohn Forte 	minor_t mindev = getminor(dev);
521fcf3ce44SJohn Forte 	struct nscioc_open *op;
522fcf3ce44SJohn Forte 	nsc_fd_t *fd;
523fcf3ce44SJohn Forte 	int rc;
524fcf3ce44SJohn Forte 
525fcf3ce44SJohn Forte 	op = nsc_kmem_alloc(sizeof (*op), KM_SLEEP, _nsc_local_mem);
526fcf3ce44SJohn Forte 	if (op == NULL) {
527fcf3ce44SJohn Forte 		return (ENOMEM);
528fcf3ce44SJohn Forte 	}
529fcf3ce44SJohn Forte 
530fcf3ce44SJohn Forte 	if (ddi_copyin((void *)arg, op, sizeof (*op), mode) < 0) {
531fcf3ce44SJohn Forte 		nsc_kmem_free(op, sizeof (*op));
532fcf3ce44SJohn Forte 		return (EFAULT);
533fcf3ce44SJohn Forte 	}
534fcf3ce44SJohn Forte 
535fcf3ce44SJohn Forte 	mutex_enter(_nsc_minor_slp[mindev]);
536fcf3ce44SJohn Forte 
537fcf3ce44SJohn Forte 	if (_nsc_minor_fd[mindev]) {
538fcf3ce44SJohn Forte 		mutex_exit(_nsc_minor_slp[mindev]);
539fcf3ce44SJohn Forte 		nsc_kmem_free(op, sizeof (*op));
540fcf3ce44SJohn Forte 		return (EBUSY);
541fcf3ce44SJohn Forte 	}
542fcf3ce44SJohn Forte 
543fcf3ce44SJohn Forte 	op->path[sizeof (op->path)-1] = 0;
544fcf3ce44SJohn Forte 
545fcf3ce44SJohn Forte 	fd = nsc_open(op->path, (op->flag & NSC_TYPES), 0, 0, &rc);
546fcf3ce44SJohn Forte 
547fcf3ce44SJohn Forte 	if (fd == NULL) {
548fcf3ce44SJohn Forte 		mutex_exit(_nsc_minor_slp[mindev]);
549fcf3ce44SJohn Forte 		nsc_kmem_free(op, sizeof (*op));
550fcf3ce44SJohn Forte 		return (rc);
551fcf3ce44SJohn Forte 	}
552fcf3ce44SJohn Forte 
553fcf3ce44SJohn Forte 	mode |= (op->mode - FOPEN);
554fcf3ce44SJohn Forte 
555fcf3ce44SJohn Forte 	if (mode & (FWRITE|FEXCL)) {
556fcf3ce44SJohn Forte 		if ((rc = nsc_reserve(fd, NSC_PCATCH)) != 0) {
557fcf3ce44SJohn Forte 			mutex_exit(_nsc_minor_slp[mindev]);
558fcf3ce44SJohn Forte 			(void) nsc_close(fd);
559fcf3ce44SJohn Forte 			nsc_kmem_free(op, sizeof (*op));
560fcf3ce44SJohn Forte 			return (rc);
561fcf3ce44SJohn Forte 		}
562fcf3ce44SJohn Forte 	}
563fcf3ce44SJohn Forte 
564fcf3ce44SJohn Forte 	*rvp = 0;
565fcf3ce44SJohn Forte 	_nsc_minor_fd[mindev] = fd;
566fcf3ce44SJohn Forte 
567fcf3ce44SJohn Forte 	mutex_exit(_nsc_minor_slp[mindev]);
568fcf3ce44SJohn Forte 	nsc_kmem_free(op, sizeof (*op));
569fcf3ce44SJohn Forte 	return (0);
570fcf3ce44SJohn Forte }
571fcf3ce44SJohn Forte 
572fcf3ce44SJohn Forte 
573fcf3ce44SJohn Forte /* ARGSUSED */
574fcf3ce44SJohn Forte 
575fcf3ce44SJohn Forte int
576fcf3ce44SJohn Forte nscclose(dev_t dev, int flag, int otyp, cred_t *crp)
577fcf3ce44SJohn Forte {
578fcf3ce44SJohn Forte 	minor_t mindev = getminor(dev);
579fcf3ce44SJohn Forte 	kmutex_t *slp;
580fcf3ce44SJohn Forte 	nsc_fd_t *fd;
581fcf3ce44SJohn Forte 
582fcf3ce44SJohn Forte 	if (!_nsc_minor_fd || !_nsc_minor_slp)
583fcf3ce44SJohn Forte 		return (0);
584fcf3ce44SJohn Forte 
585fcf3ce44SJohn Forte 	if ((slp = _nsc_minor_slp[mindev]) == 0)
586fcf3ce44SJohn Forte 		return (0);
587fcf3ce44SJohn Forte 
588fcf3ce44SJohn Forte 	if ((fd = _nsc_minor_fd[mindev]) != NULL)
589fcf3ce44SJohn Forte 		(void) nsc_close(fd);
590fcf3ce44SJohn Forte 
591fcf3ce44SJohn Forte 	_nsc_minor_fd[mindev] = NULL;
592fcf3ce44SJohn Forte 	_nsc_minor_slp[mindev] = NULL;
593fcf3ce44SJohn Forte 
594fcf3ce44SJohn Forte 	mutex_destroy(slp);
595fcf3ce44SJohn Forte 	nsc_kmem_free(slp, sizeof (kmutex_t));
596fcf3ce44SJohn Forte 	return (0);
597fcf3ce44SJohn Forte }
598fcf3ce44SJohn Forte 
599fcf3ce44SJohn Forte 
600fcf3ce44SJohn Forte /* ARGSUSED */
601fcf3ce44SJohn Forte 
602fcf3ce44SJohn Forte int
603fcf3ce44SJohn Forte nscread(dev_t dev, uio_t *uiop, cred_t *crp)
604fcf3ce44SJohn Forte {
605fcf3ce44SJohn Forte 	minor_t mindev = getminor(dev);
606fcf3ce44SJohn Forte 	int rc, resv;
607fcf3ce44SJohn Forte 	nsc_fd_t *fd;
608fcf3ce44SJohn Forte 
609fcf3ce44SJohn Forte 	if ((fd = _nsc_minor_fd[mindev]) == 0)
610fcf3ce44SJohn Forte 		return (EIO);
611fcf3ce44SJohn Forte 
612fcf3ce44SJohn Forte 	mutex_enter(_nsc_minor_slp[mindev]);
613fcf3ce44SJohn Forte 
614fcf3ce44SJohn Forte 	resv = (nsc_held(fd) == 0);
615fcf3ce44SJohn Forte 
616fcf3ce44SJohn Forte 	if (resv && (rc = nsc_reserve(fd, NSC_PCATCH)) != 0) {
617fcf3ce44SJohn Forte 		mutex_exit(_nsc_minor_slp[mindev]);
618fcf3ce44SJohn Forte 		return (rc);
619fcf3ce44SJohn Forte 	}
620fcf3ce44SJohn Forte 
621fcf3ce44SJohn Forte 	rc = nsc_uread(fd, uiop, crp);
622fcf3ce44SJohn Forte 
623fcf3ce44SJohn Forte 	if (resv)
624fcf3ce44SJohn Forte 		nsc_release(fd);
625fcf3ce44SJohn Forte 
626fcf3ce44SJohn Forte 	mutex_exit(_nsc_minor_slp[mindev]);
627fcf3ce44SJohn Forte 	return (rc);
628fcf3ce44SJohn Forte }
629fcf3ce44SJohn Forte 
630fcf3ce44SJohn Forte 
631fcf3ce44SJohn Forte /* ARGSUSED */
632fcf3ce44SJohn Forte 
633fcf3ce44SJohn Forte int
634fcf3ce44SJohn Forte nscwrite(dev_t dev, uio_t *uiop, cred_t *crp)
635fcf3ce44SJohn Forte {
636fcf3ce44SJohn Forte 	minor_t mindev = getminor(dev);
637fcf3ce44SJohn Forte 	int rc, resv;
638fcf3ce44SJohn Forte 	nsc_fd_t *fd;
639fcf3ce44SJohn Forte 
640fcf3ce44SJohn Forte 	if ((fd = _nsc_minor_fd[mindev]) == 0)
641fcf3ce44SJohn Forte 		return (EIO);
642fcf3ce44SJohn Forte 
643fcf3ce44SJohn Forte 	mutex_enter(_nsc_minor_slp[mindev]);
644fcf3ce44SJohn Forte 
645fcf3ce44SJohn Forte 	resv = (nsc_held(fd) == 0);
646fcf3ce44SJohn Forte 
647fcf3ce44SJohn Forte 	if (resv && (rc = nsc_reserve(fd, NSC_PCATCH)) != 0) {
648fcf3ce44SJohn Forte 		mutex_exit(_nsc_minor_slp[mindev]);
649fcf3ce44SJohn Forte 		return (rc);
650fcf3ce44SJohn Forte 	}
651fcf3ce44SJohn Forte 
652fcf3ce44SJohn Forte 	rc = nsc_uwrite(fd, uiop, crp);
653fcf3ce44SJohn Forte 
654fcf3ce44SJohn Forte 	if (resv)
655fcf3ce44SJohn Forte 		nsc_release(fd);
656fcf3ce44SJohn Forte 
657fcf3ce44SJohn Forte 	mutex_exit(_nsc_minor_slp[mindev]);
658fcf3ce44SJohn Forte 	return (rc);
659fcf3ce44SJohn Forte }
660fcf3ce44SJohn Forte 
661fcf3ce44SJohn Forte 
662fcf3ce44SJohn Forte int
663fcf3ce44SJohn Forte _nscreserve(dev_t dev, int *rvp)
664fcf3ce44SJohn Forte {
665fcf3ce44SJohn Forte 	minor_t mindev = getminor(dev);
666fcf3ce44SJohn Forte 	nsc_fd_t *fd;
667fcf3ce44SJohn Forte 	int rc;
668fcf3ce44SJohn Forte 
669fcf3ce44SJohn Forte 	if ((fd = _nsc_minor_fd[mindev]) == 0)
670fcf3ce44SJohn Forte 		return (EIO);
671fcf3ce44SJohn Forte 
672fcf3ce44SJohn Forte 	mutex_enter(_nsc_minor_slp[mindev]);
673fcf3ce44SJohn Forte 
674fcf3ce44SJohn Forte 	if (nsc_held(fd)) {
675fcf3ce44SJohn Forte 		mutex_exit(_nsc_minor_slp[mindev]);
676fcf3ce44SJohn Forte 		return (EBUSY);
677fcf3ce44SJohn Forte 	}
678fcf3ce44SJohn Forte 
679fcf3ce44SJohn Forte 	if ((rc = nsc_reserve(fd, NSC_PCATCH)) != 0) {
680fcf3ce44SJohn Forte 		mutex_exit(_nsc_minor_slp[mindev]);
681fcf3ce44SJohn Forte 		return (rc);
682fcf3ce44SJohn Forte 	}
683fcf3ce44SJohn Forte 
684fcf3ce44SJohn Forte 	*rvp = 0;
685fcf3ce44SJohn Forte 
686fcf3ce44SJohn Forte 	mutex_exit(_nsc_minor_slp[mindev]);
687fcf3ce44SJohn Forte 	return (0);
688fcf3ce44SJohn Forte }
689fcf3ce44SJohn Forte 
690fcf3ce44SJohn Forte 
691fcf3ce44SJohn Forte int
692fcf3ce44SJohn Forte _nscrelease(dev_t dev, int *rvp)
693fcf3ce44SJohn Forte {
694fcf3ce44SJohn Forte 	minor_t mindev = getminor(dev);
695fcf3ce44SJohn Forte 	nsc_fd_t *fd;
696fcf3ce44SJohn Forte 
697fcf3ce44SJohn Forte 	if ((fd = _nsc_minor_fd[mindev]) == 0)
698fcf3ce44SJohn Forte 		return (EIO);
699fcf3ce44SJohn Forte 
700fcf3ce44SJohn Forte 	mutex_enter(_nsc_minor_slp[mindev]);
701fcf3ce44SJohn Forte 
702fcf3ce44SJohn Forte 	if (!nsc_held(fd)) {
703fcf3ce44SJohn Forte 		mutex_exit(_nsc_minor_slp[mindev]);
704fcf3ce44SJohn Forte 		return (EINVAL);
705fcf3ce44SJohn Forte 	}
706fcf3ce44SJohn Forte 
707fcf3ce44SJohn Forte 	nsc_release(fd);
708fcf3ce44SJohn Forte 
709fcf3ce44SJohn Forte 	*rvp = 0;
710fcf3ce44SJohn Forte 
711fcf3ce44SJohn Forte 	mutex_exit(_nsc_minor_slp[mindev]);
712fcf3ce44SJohn Forte 	return (0);
713fcf3ce44SJohn Forte }
714fcf3ce44SJohn Forte 
715fcf3ce44SJohn Forte 
716fcf3ce44SJohn Forte int
717fcf3ce44SJohn Forte _nscpartsize(dev_t dev, intptr_t arg, int mode)
718fcf3ce44SJohn Forte {
719fcf3ce44SJohn Forte 	struct nscioc_partsize partsize;
720fcf3ce44SJohn Forte 	minor_t mindev = getminor(dev);
721fcf3ce44SJohn Forte 	nsc_size_t size;
722fcf3ce44SJohn Forte 	int rc, resv;
723fcf3ce44SJohn Forte 	nsc_fd_t *fd;
724fcf3ce44SJohn Forte 
725fcf3ce44SJohn Forte 	if ((fd = _nsc_minor_fd[mindev]) == 0)
726fcf3ce44SJohn Forte 		return (EIO);
727fcf3ce44SJohn Forte 
728fcf3ce44SJohn Forte 	mutex_enter(_nsc_minor_slp[mindev]);
729fcf3ce44SJohn Forte 
730fcf3ce44SJohn Forte 	resv = (nsc_held(fd) == 0);
731fcf3ce44SJohn Forte 
732fcf3ce44SJohn Forte 	if (resv && (rc = nsc_reserve(fd, NSC_PCATCH)) != 0) {
733fcf3ce44SJohn Forte 		mutex_exit(_nsc_minor_slp[mindev]);
734fcf3ce44SJohn Forte 		return (rc);
735fcf3ce44SJohn Forte 	}
736fcf3ce44SJohn Forte 
737fcf3ce44SJohn Forte 	rc = nsc_partsize(fd, &size);
738fcf3ce44SJohn Forte 	partsize.partsize = (uint64_t)size;
739fcf3ce44SJohn Forte 
740fcf3ce44SJohn Forte 	if (resv)
741fcf3ce44SJohn Forte 		nsc_release(fd);
742fcf3ce44SJohn Forte 
743fcf3ce44SJohn Forte 	mutex_exit(_nsc_minor_slp[mindev]);
744fcf3ce44SJohn Forte 
745fcf3ce44SJohn Forte 	if (ddi_copyout((void *)&partsize, (void *)arg,
746fcf3ce44SJohn Forte 	    sizeof (partsize), mode) < 0) {
747fcf3ce44SJohn Forte 		return (EFAULT);
748fcf3ce44SJohn Forte 	}
749fcf3ce44SJohn Forte 
750fcf3ce44SJohn Forte 	return (rc);
751fcf3ce44SJohn Forte }
752fcf3ce44SJohn Forte 
753fcf3ce44SJohn Forte 
754fcf3ce44SJohn Forte /* ARGSUSED */
755fcf3ce44SJohn Forte 
756fcf3ce44SJohn Forte int
757fcf3ce44SJohn Forte nscioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp, int *rvp)
758fcf3ce44SJohn Forte {
759fcf3ce44SJohn Forte 	struct nscioc_bsize *bsize = NULL;
760fcf3ce44SJohn Forte 	char *path = NULL;
761fcf3ce44SJohn Forte 	int rc = 0;
762fcf3ce44SJohn Forte 
763fcf3ce44SJohn Forte 	*rvp = 0;
764fcf3ce44SJohn Forte 
765fcf3ce44SJohn Forte 	switch (cmd) {
766fcf3ce44SJohn Forte 	case NSCIOC_OPEN:
767fcf3ce44SJohn Forte 		rc = _nscopen(dev, arg, mode, rvp);
768fcf3ce44SJohn Forte 		break;
769fcf3ce44SJohn Forte 
770fcf3ce44SJohn Forte 	case NSCIOC_RESERVE:
771fcf3ce44SJohn Forte 		rc = _nscreserve(dev, rvp);
772fcf3ce44SJohn Forte 		break;
773fcf3ce44SJohn Forte 
774fcf3ce44SJohn Forte 	case NSCIOC_RELEASE:
775fcf3ce44SJohn Forte 		rc = _nscrelease(dev, rvp);
776fcf3ce44SJohn Forte 		break;
777fcf3ce44SJohn Forte 
778fcf3ce44SJohn Forte 	case NSCIOC_PARTSIZE:
779fcf3ce44SJohn Forte 		rc = _nscpartsize(dev, arg, mode);
780fcf3ce44SJohn Forte 		break;
781fcf3ce44SJohn Forte 
782fcf3ce44SJohn Forte 	case NSCIOC_FREEZE:
783fcf3ce44SJohn Forte 		path = nsc_kmem_alloc(NSC_MAXPATH, KM_SLEEP, _nsc_local_mem);
784fcf3ce44SJohn Forte 		if (path == NULL) {
785fcf3ce44SJohn Forte 			rc = ENOMEM;
786fcf3ce44SJohn Forte 			break;
787fcf3ce44SJohn Forte 		}
788fcf3ce44SJohn Forte 		if (ddi_copyin((void *)arg, path, NSC_MAXPATH, mode) < 0)
789fcf3ce44SJohn Forte 			rc = EFAULT;
790fcf3ce44SJohn Forte 		else {
791fcf3ce44SJohn Forte 			path[NSC_MAXPATH-1] = 0;
792fcf3ce44SJohn Forte 			rc = _nsc_frz_start(path, rvp);
793fcf3ce44SJohn Forte 		}
794fcf3ce44SJohn Forte 		break;
795fcf3ce44SJohn Forte 
796fcf3ce44SJohn Forte 	case NSCIOC_UNFREEZE:
797fcf3ce44SJohn Forte 		path = nsc_kmem_alloc(NSC_MAXPATH, KM_SLEEP, _nsc_local_mem);
798fcf3ce44SJohn Forte 		if (path == NULL) {
799fcf3ce44SJohn Forte 			rc = ENOMEM;
800fcf3ce44SJohn Forte 			break;
801fcf3ce44SJohn Forte 		}
802fcf3ce44SJohn Forte 		if (ddi_copyin((void *)arg, path, NSC_MAXPATH, mode) < 0)
803fcf3ce44SJohn Forte 			rc = EFAULT;
804fcf3ce44SJohn Forte 		else {
805fcf3ce44SJohn Forte 			path[NSC_MAXPATH-1] = 0;
806fcf3ce44SJohn Forte 			rc = _nsc_frz_stop(path, rvp);
807fcf3ce44SJohn Forte 		}
808fcf3ce44SJohn Forte 		break;
809fcf3ce44SJohn Forte 
810fcf3ce44SJohn Forte 	case NSCIOC_ISFROZEN:
811fcf3ce44SJohn Forte 		path = nsc_kmem_alloc(NSC_MAXPATH, KM_SLEEP, _nsc_local_mem);
812fcf3ce44SJohn Forte 		if (path == NULL) {
813fcf3ce44SJohn Forte 			rc = ENOMEM;
814fcf3ce44SJohn Forte 			break;
815fcf3ce44SJohn Forte 		}
816fcf3ce44SJohn Forte 		if (ddi_copyin((void *)arg, path, NSC_MAXPATH, mode) < 0)
817fcf3ce44SJohn Forte 			rc = EFAULT;
818fcf3ce44SJohn Forte 		else {
819fcf3ce44SJohn Forte 			path[NSC_MAXPATH-1] = 0;
820fcf3ce44SJohn Forte 			rc = _nsc_frz_isfrozen(path, rvp);
821fcf3ce44SJohn Forte 		}
822fcf3ce44SJohn Forte 		break;
823fcf3ce44SJohn Forte 
824fcf3ce44SJohn Forte #ifdef ENABLE_POWER_MSG
825fcf3ce44SJohn Forte 	case NSCIOC_POWERMSG:
826fcf3ce44SJohn Forte 		rc = _nsc_power((void *)arg, rvp);
827fcf3ce44SJohn Forte 		break;
828fcf3ce44SJohn Forte #endif
829fcf3ce44SJohn Forte 
830fcf3ce44SJohn Forte 	case NSCIOC_NSKERND:
831fcf3ce44SJohn Forte 		rc = nskernd_command(arg, mode, rvp);
832fcf3ce44SJohn Forte 		break;
833fcf3ce44SJohn Forte 
834fcf3ce44SJohn Forte 	/* return sizes of global memory segments */
835fcf3ce44SJohn Forte 	case NSCIOC_GLOBAL_SIZES:
836fcf3ce44SJohn Forte 		if (!_nsc_init_done) {
837fcf3ce44SJohn Forte 			rc = EINVAL;
838fcf3ce44SJohn Forte 			break;
839fcf3ce44SJohn Forte 		}
840fcf3ce44SJohn Forte 
841fcf3ce44SJohn Forte 		rc = _nsc_get_global_sizes((void *)arg, rvp);
842fcf3ce44SJohn Forte 
843fcf3ce44SJohn Forte 		break;
844fcf3ce44SJohn Forte 
845fcf3ce44SJohn Forte 	/* return contents of global segments */
846fcf3ce44SJohn Forte 	case NSCIOC_GLOBAL_DATA:
847fcf3ce44SJohn Forte 		if (!_nsc_init_done) {
848fcf3ce44SJohn Forte 			rc = EINVAL;
849fcf3ce44SJohn Forte 			break;
850fcf3ce44SJohn Forte 		}
851fcf3ce44SJohn Forte 
852fcf3ce44SJohn Forte 		rc = _nsc_get_global_data((void *)arg, rvp);
853fcf3ce44SJohn Forte 		break;
854fcf3ce44SJohn Forte 
855fcf3ce44SJohn Forte 	/*
856fcf3ce44SJohn Forte 	 * nvmem systems:
857fcf3ce44SJohn Forte 	 * clear the hdr dirty bit to prevent loading from nvme on reboot
858fcf3ce44SJohn Forte 	 */
859fcf3ce44SJohn Forte 	case NSCIOC_NVMEM_CLEANF:
860fcf3ce44SJohn Forte 		rc = _nsc_clear_dirty(1);	/* dont be nice about it */
861fcf3ce44SJohn Forte 		break;
862fcf3ce44SJohn Forte 	case NSCIOC_NVMEM_CLEAN:
863fcf3ce44SJohn Forte 		rc = _nsc_clear_dirty(0);
864fcf3ce44SJohn Forte 		break;
865fcf3ce44SJohn Forte 
866fcf3ce44SJohn Forte 	case NSCIOC_BSIZE:
867fcf3ce44SJohn Forte 		bsize = nsc_kmem_alloc(sizeof (*bsize), KM_SLEEP,
868fcf3ce44SJohn Forte 		    _nsc_local_mem);
869fcf3ce44SJohn Forte 		if (bsize == NULL) {
870fcf3ce44SJohn Forte 			rc = ENOMEM;
871fcf3ce44SJohn Forte 			break;
872fcf3ce44SJohn Forte 		}
873fcf3ce44SJohn Forte 
874fcf3ce44SJohn Forte 		if (ddi_copyin((void *)arg, bsize, sizeof (*bsize), mode) < 0) {
875fcf3ce44SJohn Forte 			rc = EFAULT;
876fcf3ce44SJohn Forte 			break;
877fcf3ce44SJohn Forte 		}
878fcf3ce44SJohn Forte 
879fcf3ce44SJohn Forte 		rc = nskern_bsize(bsize, rvp);
880fcf3ce44SJohn Forte 		if (rc == 0) {
881fcf3ce44SJohn Forte 			if (ddi_copyout(bsize, (void *)arg,
882fcf3ce44SJohn Forte 			    sizeof (*bsize), mode) < 0) {
883fcf3ce44SJohn Forte 				rc = EFAULT;
884fcf3ce44SJohn Forte 				break;
885fcf3ce44SJohn Forte 			}
886fcf3ce44SJohn Forte 		}
887fcf3ce44SJohn Forte 
888fcf3ce44SJohn Forte 		break;
889fcf3ce44SJohn Forte 
890fcf3ce44SJohn Forte 	default:
891fcf3ce44SJohn Forte 		return (ENOTTY);
892fcf3ce44SJohn Forte 	}
893fcf3ce44SJohn Forte 
894fcf3ce44SJohn Forte 	if (bsize != NULL) {
895fcf3ce44SJohn Forte 		nsc_kmem_free(bsize, sizeof (*bsize));
896fcf3ce44SJohn Forte 		bsize = NULL;
897fcf3ce44SJohn Forte 	}
898fcf3ce44SJohn Forte 	if (path != NULL) {
899fcf3ce44SJohn Forte 		nsc_kmem_free(path, NSC_MAXPATH);
900fcf3ce44SJohn Forte 		path = NULL;
901fcf3ce44SJohn Forte 	}
902fcf3ce44SJohn Forte 	return (rc);
903fcf3ce44SJohn Forte }
904fcf3ce44SJohn Forte 
905fcf3ce44SJohn Forte 
906fcf3ce44SJohn Forte int
907fcf3ce44SJohn Forte nsc_max_devices(void)
908fcf3ce44SJohn Forte {
909fcf3ce44SJohn Forte 	return (_nsc_max_devices);
910fcf3ce44SJohn Forte }
911fcf3ce44SJohn Forte 
912fcf3ce44SJohn Forte 
913fcf3ce44SJohn Forte /*
914fcf3ce44SJohn Forte  * Used by _nsc_global_setup() in case nvram is dirty and has saved a different
915fcf3ce44SJohn Forte  * value for nsc_max_devices. We need to use the saved value, not the new
916fcf3ce44SJohn Forte  * one configured by the user.
917fcf3ce44SJohn Forte  */
918fcf3ce44SJohn Forte void
919fcf3ce44SJohn Forte _nsc_set_max_devices(int maxdev)
920fcf3ce44SJohn Forte {
921fcf3ce44SJohn Forte 	_nsc_max_devices = maxdev;
922fcf3ce44SJohn Forte 	_nsc_maxdev = _nsc_max_devices;
923fcf3ce44SJohn Forte }
924