xref: /onnv-gate/usr/src/uts/common/avs/ns/nsctl/nsctl.c (revision 9093:cd587b0bd19c)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
228694SMark.Musante@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237836SJohn.Forte@Sun.COM  * Use is subject to license terms.
247836SJohn.Forte@Sun.COM  */
257836SJohn.Forte@Sun.COM 
267836SJohn.Forte@Sun.COM #include <sys/types.h>
277836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
287836SJohn.Forte@Sun.COM #include <sys/kmem.h>
297836SJohn.Forte@Sun.COM #include <sys/file.h>
307836SJohn.Forte@Sun.COM #include <sys/errno.h>
317836SJohn.Forte@Sun.COM #include <sys/open.h>
327836SJohn.Forte@Sun.COM #include <sys/cred.h>
337836SJohn.Forte@Sun.COM #include <sys/conf.h>
347836SJohn.Forte@Sun.COM #include <sys/uio.h>
357836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
367836SJohn.Forte@Sun.COM #include <sys/modctl.h>
377836SJohn.Forte@Sun.COM #include <sys/ddi.h>
387836SJohn.Forte@Sun.COM 
397836SJohn.Forte@Sun.COM #define	__NSC_GEN__
407836SJohn.Forte@Sun.COM #include <sys/nsctl/nsc_dev.h>
417836SJohn.Forte@Sun.COM #include <sys/nsctl/nsc_gen.h>
427836SJohn.Forte@Sun.COM #include <sys/nsctl/nsc_ioctl.h>
437836SJohn.Forte@Sun.COM #include <sys/nsctl/nsc_power.h>
447836SJohn.Forte@Sun.COM #include <sys/nsctl/nsc_mem.h>
457836SJohn.Forte@Sun.COM #include "../nsctl.h"
467836SJohn.Forte@Sun.COM 
477836SJohn.Forte@Sun.COM #include <sys/nsctl/nsvers.h>
487836SJohn.Forte@Sun.COM 
497836SJohn.Forte@Sun.COM #ifdef DS_DDICT
507836SJohn.Forte@Sun.COM #include "../contract.h"
517836SJohn.Forte@Sun.COM #endif
527836SJohn.Forte@Sun.COM 
537836SJohn.Forte@Sun.COM extern void nscsetup();
547836SJohn.Forte@Sun.COM extern int _nsc_init_raw();
557836SJohn.Forte@Sun.COM extern void _nsc_deinit_raw();
567836SJohn.Forte@Sun.COM extern void _nsc_init_start();
577836SJohn.Forte@Sun.COM extern void _nsc_init_os(), _nsc_deinit_os();
587836SJohn.Forte@Sun.COM extern void _nsc_init_dev(), _nsc_init_mem();
597836SJohn.Forte@Sun.COM extern void _nsc_init_gen(), _nsc_init_rmlock();
607836SJohn.Forte@Sun.COM extern void _nsc_init_resv(), _nsc_deinit_resv();
617836SJohn.Forte@Sun.COM extern void _nsc_init_frz(), _nsc_deinit_frz();
627836SJohn.Forte@Sun.COM extern void _nsc_init_ncio(), _nsc_deinit_ncio();
637836SJohn.Forte@Sun.COM extern void _nsc_deinit_mem(), _nsc_deinit_rmlock();
647836SJohn.Forte@Sun.COM extern void _nsc_deinit_dev();
657836SJohn.Forte@Sun.COM 
667836SJohn.Forte@Sun.COM extern int _nsc_frz_start(), _nsc_frz_stop(), _nsc_frz_isfrozen();
677836SJohn.Forte@Sun.COM 
687836SJohn.Forte@Sun.COM extern nsc_mem_t *_nsc_local_mem;
697836SJohn.Forte@Sun.COM extern nsc_rmhdr_t *_nsc_rmhdr_ptr;
707836SJohn.Forte@Sun.COM extern nsc_def_t _nsc_raw_def[];
717836SJohn.Forte@Sun.COM extern int _nsc_raw_flags;
727836SJohn.Forte@Sun.COM 
737836SJohn.Forte@Sun.COM int nsc_devflag = D_MP;
747836SJohn.Forte@Sun.COM 
757836SJohn.Forte@Sun.COM int _nsc_init_done = 0;
767836SJohn.Forte@Sun.COM 
777836SJohn.Forte@Sun.COM kmutex_t _nsc_drv_lock;
787836SJohn.Forte@Sun.COM nsc_io_t *_nsc_file_io;
797836SJohn.Forte@Sun.COM nsc_io_t *_nsc_vchr_io;
807836SJohn.Forte@Sun.COM nsc_io_t *_nsc_raw_io;
817836SJohn.Forte@Sun.COM 
827836SJohn.Forte@Sun.COM nsc_fd_t **_nsc_minor_fd;
837836SJohn.Forte@Sun.COM kmutex_t **_nsc_minor_slp;
847836SJohn.Forte@Sun.COM 
857836SJohn.Forte@Sun.COM 
867836SJohn.Forte@Sun.COM /* Maximum number of devices - tunable in nsctl.conf */
877836SJohn.Forte@Sun.COM static int _nsc_max_devices;
887836SJohn.Forte@Sun.COM 
897836SJohn.Forte@Sun.COM /* Internal version of _nsc_max_devices */
907836SJohn.Forte@Sun.COM int _nsc_maxdev;
917836SJohn.Forte@Sun.COM 
927836SJohn.Forte@Sun.COM extern void _nsc_global_setup(void);
937836SJohn.Forte@Sun.COM 
947836SJohn.Forte@Sun.COM static int nsc_load(), nsc_unload();
958694SMark.Musante@Sun.COM static void nscteardown();
967836SJohn.Forte@Sun.COM 
977836SJohn.Forte@Sun.COM /*
987836SJohn.Forte@Sun.COM  * Solaris specific driver module interface code.
997836SJohn.Forte@Sun.COM  */
1007836SJohn.Forte@Sun.COM 
1017836SJohn.Forte@Sun.COM extern int nscopen(dev_t *, int, int, cred_t *);
1027836SJohn.Forte@Sun.COM extern int nscioctl(dev_t, int, intptr_t, int, cred_t *, int *);
1037836SJohn.Forte@Sun.COM extern int nscclose(dev_t, int, int, cred_t *);
1047836SJohn.Forte@Sun.COM extern int nscread(dev_t, uio_t *, cred_t *);
1057836SJohn.Forte@Sun.COM extern int nscwrite(dev_t, uio_t *, cred_t *);
1067836SJohn.Forte@Sun.COM 
1077836SJohn.Forte@Sun.COM static dev_info_t *nsctl_dip;		/* Single DIP for driver */
1087836SJohn.Forte@Sun.COM 
1097836SJohn.Forte@Sun.COM static int _nsctl_print(dev_t, char *);
1107836SJohn.Forte@Sun.COM 
1117836SJohn.Forte@Sun.COM static	struct	cb_ops nsctl_cb_ops = {
1127836SJohn.Forte@Sun.COM 	nscopen,		/* open */
1137836SJohn.Forte@Sun.COM 	nscclose,	/* close */
1147836SJohn.Forte@Sun.COM 	nodev,		/* not a block driver, strategy not an entry point */
1157836SJohn.Forte@Sun.COM 	_nsctl_print,	/* no print routine */
1167836SJohn.Forte@Sun.COM 	nodev,		/* no dump routine */
1177836SJohn.Forte@Sun.COM 	nscread,		/* read */
1187836SJohn.Forte@Sun.COM 	nscwrite,	/* write */
1197836SJohn.Forte@Sun.COM 	(int (*)()) nscioctl,	/* ioctl */
1207836SJohn.Forte@Sun.COM 	nodev,		/* no devmap routine */
1217836SJohn.Forte@Sun.COM 	nodev,		/* no mmap routine */
1227836SJohn.Forte@Sun.COM 	nodev,		/* no segmap routine */
1237836SJohn.Forte@Sun.COM 	nochpoll,	/* no chpoll routine */
1247836SJohn.Forte@Sun.COM 	ddi_prop_op,
1257836SJohn.Forte@Sun.COM 	0,		/* not a STREAMS driver, no cb_str routine */
1267836SJohn.Forte@Sun.COM 	D_NEW | D_MP | D_64BIT,	/* safe for multi-thread/multi-processor */
1277836SJohn.Forte@Sun.COM 	CB_REV,
1287836SJohn.Forte@Sun.COM 	nodev,		/* aread */
1297836SJohn.Forte@Sun.COM 	nodev,		/* awrite */
1307836SJohn.Forte@Sun.COM };
1317836SJohn.Forte@Sun.COM 
1327836SJohn.Forte@Sun.COM static int _nsctl_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
1337836SJohn.Forte@Sun.COM static int _nsctl_attach(dev_info_t *, ddi_attach_cmd_t);
1347836SJohn.Forte@Sun.COM static int _nsctl_detach(dev_info_t *, ddi_detach_cmd_t);
1357836SJohn.Forte@Sun.COM 
1367836SJohn.Forte@Sun.COM static	struct	dev_ops nsctl_ops = {
1377836SJohn.Forte@Sun.COM 	DEVO_REV,			/* Driver build version */
1387836SJohn.Forte@Sun.COM 	0,				/* device reference count */
1397836SJohn.Forte@Sun.COM 	_nsctl_getinfo,
1407836SJohn.Forte@Sun.COM 	nulldev,			/* Identify */
1417836SJohn.Forte@Sun.COM 	nulldev,			/* Probe */
1427836SJohn.Forte@Sun.COM 	_nsctl_attach,
1437836SJohn.Forte@Sun.COM 	_nsctl_detach,
1447836SJohn.Forte@Sun.COM 	nodev,				/* Reset */
1457836SJohn.Forte@Sun.COM 	&nsctl_cb_ops,
1467836SJohn.Forte@Sun.COM 	(struct bus_ops *)0
1477836SJohn.Forte@Sun.COM };
1487836SJohn.Forte@Sun.COM 
1497836SJohn.Forte@Sun.COM static struct modldrv nsctl_ldrv = {
1507836SJohn.Forte@Sun.COM 	&mod_driverops,
1517836SJohn.Forte@Sun.COM 	"nws:Control:" ISS_VERSION_STR,
1527836SJohn.Forte@Sun.COM 	&nsctl_ops
1537836SJohn.Forte@Sun.COM };
1547836SJohn.Forte@Sun.COM 
1557836SJohn.Forte@Sun.COM static	struct modlinkage nsctl_modlinkage = {
1567836SJohn.Forte@Sun.COM 	MODREV_1,
1577836SJohn.Forte@Sun.COM 	&nsctl_ldrv,
1587836SJohn.Forte@Sun.COM 	NULL
1597836SJohn.Forte@Sun.COM };
1607836SJohn.Forte@Sun.COM 
1617836SJohn.Forte@Sun.COM /*
1627836SJohn.Forte@Sun.COM  * Solaris module load time code
1637836SJohn.Forte@Sun.COM  */
1647836SJohn.Forte@Sun.COM 
1657836SJohn.Forte@Sun.COM int nsc_min_nodeid;
1667836SJohn.Forte@Sun.COM int nsc_max_nodeid;
1677836SJohn.Forte@Sun.COM 
1687836SJohn.Forte@Sun.COM int
_init(void)1697836SJohn.Forte@Sun.COM _init(void)
1707836SJohn.Forte@Sun.COM {
1717836SJohn.Forte@Sun.COM 	int err;
1727836SJohn.Forte@Sun.COM 
1737836SJohn.Forte@Sun.COM 	err = nsc_load();
1747836SJohn.Forte@Sun.COM 
1757836SJohn.Forte@Sun.COM 	if (!err)
1767836SJohn.Forte@Sun.COM 		err = mod_install(&nsctl_modlinkage);
1777836SJohn.Forte@Sun.COM 
1787836SJohn.Forte@Sun.COM 	if (err) {
1797836SJohn.Forte@Sun.COM 		(void) nsc_unload();
180*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_NOTE, "!nsctl_init: err %d", err);
1817836SJohn.Forte@Sun.COM 	}
1827836SJohn.Forte@Sun.COM 
1837836SJohn.Forte@Sun.COM 	return (err);
1847836SJohn.Forte@Sun.COM 
1857836SJohn.Forte@Sun.COM }
1867836SJohn.Forte@Sun.COM 
1877836SJohn.Forte@Sun.COM /*
1887836SJohn.Forte@Sun.COM  * Solaris module unload time code
1897836SJohn.Forte@Sun.COM  */
1907836SJohn.Forte@Sun.COM 
1917836SJohn.Forte@Sun.COM int
_fini(void)1927836SJohn.Forte@Sun.COM _fini(void)
1937836SJohn.Forte@Sun.COM {
1947836SJohn.Forte@Sun.COM 	int err;
1957836SJohn.Forte@Sun.COM 
1967836SJohn.Forte@Sun.COM 	if ((err = mod_remove(&nsctl_modlinkage)) == 0) {
1977836SJohn.Forte@Sun.COM 		err = nsc_unload();
1987836SJohn.Forte@Sun.COM 	}
1997836SJohn.Forte@Sun.COM 	return (err);
2007836SJohn.Forte@Sun.COM }
2017836SJohn.Forte@Sun.COM 
2027836SJohn.Forte@Sun.COM /*
2037836SJohn.Forte@Sun.COM  * Solaris module info code
2047836SJohn.Forte@Sun.COM  */
2057836SJohn.Forte@Sun.COM int
_info(struct modinfo * modinfop)2067836SJohn.Forte@Sun.COM _info(struct modinfo *modinfop)
2077836SJohn.Forte@Sun.COM {
2087836SJohn.Forte@Sun.COM 	return (mod_info(&nsctl_modlinkage, modinfop));
2097836SJohn.Forte@Sun.COM }
2107836SJohn.Forte@Sun.COM 
2117836SJohn.Forte@Sun.COM /*
2127836SJohn.Forte@Sun.COM  * Attach an instance of the device. This happens before an open
2137836SJohn.Forte@Sun.COM  * can succeed.
2147836SJohn.Forte@Sun.COM  */
2157836SJohn.Forte@Sun.COM static int
_nsctl_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2167836SJohn.Forte@Sun.COM _nsctl_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2177836SJohn.Forte@Sun.COM {
2187836SJohn.Forte@Sun.COM 	int rc;
2197836SJohn.Forte@Sun.COM 
2207836SJohn.Forte@Sun.COM 	if (cmd == DDI_ATTACH) {
2217836SJohn.Forte@Sun.COM 		nsctl_dip = dip;
2227836SJohn.Forte@Sun.COM 
2237836SJohn.Forte@Sun.COM 		/* Announce presence of the device */
2247836SJohn.Forte@Sun.COM 		ddi_report_dev(dip);
2257836SJohn.Forte@Sun.COM 
2267836SJohn.Forte@Sun.COM 		/*
2277836SJohn.Forte@Sun.COM 		 * Get the node parameters now that we can look up.
2287836SJohn.Forte@Sun.COM 		 */
2297836SJohn.Forte@Sun.COM 		nsc_min_nodeid = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2307836SJohn.Forte@Sun.COM 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2317836SJohn.Forte@Sun.COM 		    "nsc_min_nodeid", 0);
2327836SJohn.Forte@Sun.COM 
2337836SJohn.Forte@Sun.COM 		nsc_max_nodeid = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2347836SJohn.Forte@Sun.COM 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2357836SJohn.Forte@Sun.COM 		    "nsc_max_nodeid", 5);
2367836SJohn.Forte@Sun.COM 
2377836SJohn.Forte@Sun.COM 		_nsc_max_devices = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2387836SJohn.Forte@Sun.COM 		    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
2397836SJohn.Forte@Sun.COM 		    "nsc_max_devices", 128);
2407836SJohn.Forte@Sun.COM 
2417836SJohn.Forte@Sun.COM 		_nsc_maxdev = _nsc_max_devices;
2427836SJohn.Forte@Sun.COM 		nscsetup();
2437836SJohn.Forte@Sun.COM 
2447836SJohn.Forte@Sun.COM 		/*
2457836SJohn.Forte@Sun.COM 		 * Init raw requires the _nsc_max_devices value and so
2467836SJohn.Forte@Sun.COM 		 * cannot be done before the nsc_max_devices property has
2477836SJohn.Forte@Sun.COM 		 * been read which can only be done after the module is
2487836SJohn.Forte@Sun.COM 		 * attached and we have a dip.
2497836SJohn.Forte@Sun.COM 		 */
2507836SJohn.Forte@Sun.COM 
2517836SJohn.Forte@Sun.COM 		if ((rc = _nsc_init_raw(_nsc_max_devices)) != 0) {
2527836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
253*9093SRamana.Srikanth@Sun.COM 			    "!nsctl: unable to initialize raw io provider: %d",
2547836SJohn.Forte@Sun.COM 			    rc);
2557836SJohn.Forte@Sun.COM 			return (DDI_FAILURE);
2567836SJohn.Forte@Sun.COM 		}
2577836SJohn.Forte@Sun.COM 
2587836SJohn.Forte@Sun.COM 		/*
2597836SJohn.Forte@Sun.COM 		 * Init rest of soft state structure
2607836SJohn.Forte@Sun.COM 		 */
2617836SJohn.Forte@Sun.COM 
2627836SJohn.Forte@Sun.COM 		rc = ddi_create_minor_node(dip, "c,nsctl", S_IFCHR, 0,
2637836SJohn.Forte@Sun.COM 		    DDI_PSEUDO, 0);
2647836SJohn.Forte@Sun.COM 		if (rc != DDI_SUCCESS) {
2657836SJohn.Forte@Sun.COM 			/* free anything we allocated here */
2667836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
267*9093SRamana.Srikanth@Sun.COM 			    "!_nsctl_attach: ddi_create_minor_node failed %d",
2687836SJohn.Forte@Sun.COM 			    rc);
2697836SJohn.Forte@Sun.COM 			return (DDI_FAILURE);
2707836SJohn.Forte@Sun.COM 		}
2717836SJohn.Forte@Sun.COM 
2727836SJohn.Forte@Sun.COM 		/* Announce presence of the device */
2737836SJohn.Forte@Sun.COM 		ddi_report_dev(dip);
2747836SJohn.Forte@Sun.COM 
2757836SJohn.Forte@Sun.COM 		/* mark the device as attached, opens may proceed */
2767836SJohn.Forte@Sun.COM 		return (DDI_SUCCESS);
2777836SJohn.Forte@Sun.COM 	} else
2787836SJohn.Forte@Sun.COM 		return (DDI_FAILURE);
2797836SJohn.Forte@Sun.COM }
2807836SJohn.Forte@Sun.COM 
2817836SJohn.Forte@Sun.COM static int
_nsctl_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)2827836SJohn.Forte@Sun.COM _nsctl_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2837836SJohn.Forte@Sun.COM {
2847836SJohn.Forte@Sun.COM 	if (cmd == DDI_DETACH) {
2858694SMark.Musante@Sun.COM 		nscteardown();
2867836SJohn.Forte@Sun.COM 		_nsc_deinit_raw();
2877836SJohn.Forte@Sun.COM 
2887836SJohn.Forte@Sun.COM 		ddi_remove_minor_node(dip, NULL);
2897836SJohn.Forte@Sun.COM 		nsctl_dip = NULL;
2907836SJohn.Forte@Sun.COM 
2917836SJohn.Forte@Sun.COM 		return (DDI_SUCCESS);
2927836SJohn.Forte@Sun.COM 	}
2937836SJohn.Forte@Sun.COM 	else
2947836SJohn.Forte@Sun.COM 		return (DDI_FAILURE);
2957836SJohn.Forte@Sun.COM }
2967836SJohn.Forte@Sun.COM 
2977836SJohn.Forte@Sun.COM 
2987836SJohn.Forte@Sun.COM /* ARGSUSED */
2997836SJohn.Forte@Sun.COM static int
_nsctl_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)3007836SJohn.Forte@Sun.COM _nsctl_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
3017836SJohn.Forte@Sun.COM {
3027836SJohn.Forte@Sun.COM 	dev_t dev;
3037836SJohn.Forte@Sun.COM 	int rc;
3047836SJohn.Forte@Sun.COM 
3057836SJohn.Forte@Sun.COM 	switch (cmd) {
3067836SJohn.Forte@Sun.COM 		case DDI_INFO_DEVT2INSTANCE:
3077836SJohn.Forte@Sun.COM 			/* The "instance" number is the minor number */
3087836SJohn.Forte@Sun.COM 			dev = (dev_t)arg;
3097836SJohn.Forte@Sun.COM 			*result = (void *)(unsigned long)getminor(dev);
3107836SJohn.Forte@Sun.COM 			rc = DDI_SUCCESS;
3117836SJohn.Forte@Sun.COM 			break;
3127836SJohn.Forte@Sun.COM 
3137836SJohn.Forte@Sun.COM 		case DDI_INFO_DEVT2DEVINFO:
3147836SJohn.Forte@Sun.COM 			*result = nsctl_dip;
3157836SJohn.Forte@Sun.COM 			rc = DDI_SUCCESS;
3167836SJohn.Forte@Sun.COM 			break;
3177836SJohn.Forte@Sun.COM 
3187836SJohn.Forte@Sun.COM 		default:
3197836SJohn.Forte@Sun.COM 			rc = DDI_FAILURE;
3207836SJohn.Forte@Sun.COM 			break;
3217836SJohn.Forte@Sun.COM 	}
3227836SJohn.Forte@Sun.COM 
3237836SJohn.Forte@Sun.COM 	return (rc);
3247836SJohn.Forte@Sun.COM }
3257836SJohn.Forte@Sun.COM 
3267836SJohn.Forte@Sun.COM 
3277836SJohn.Forte@Sun.COM /* ARGSUSED */
3287836SJohn.Forte@Sun.COM static int
_nsctl_print(dev_t dev,char * s)3297836SJohn.Forte@Sun.COM _nsctl_print(dev_t dev, char *s)
3307836SJohn.Forte@Sun.COM {
331*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!nsctl:%s", s);
3327836SJohn.Forte@Sun.COM 	return (0);
3337836SJohn.Forte@Sun.COM }
3347836SJohn.Forte@Sun.COM 
3357836SJohn.Forte@Sun.COM 
3367836SJohn.Forte@Sun.COM void
nsc_init()3377836SJohn.Forte@Sun.COM nsc_init()
3387836SJohn.Forte@Sun.COM {
3397836SJohn.Forte@Sun.COM 	if (_nsc_init_done)
3407836SJohn.Forte@Sun.COM 		return;
3417836SJohn.Forte@Sun.COM 
3427836SJohn.Forte@Sun.COM 	_nsc_init_start();
3437836SJohn.Forte@Sun.COM 	_nsc_init_gen();
3447836SJohn.Forte@Sun.COM 	_nsc_init_svc();
3457836SJohn.Forte@Sun.COM 	_nsc_init_mem();
3467836SJohn.Forte@Sun.COM 	_nsc_init_dev();
3477836SJohn.Forte@Sun.COM 	_nsc_init_rmlock();
3487836SJohn.Forte@Sun.COM 	_nsc_init_resv();
3497836SJohn.Forte@Sun.COM 	_nsc_init_os();
3507836SJohn.Forte@Sun.COM 	(void) _nsc_init_power();
3517836SJohn.Forte@Sun.COM 
3527836SJohn.Forte@Sun.COM 	/*
3537836SJohn.Forte@Sun.COM 	 * When using mc, nscsetup is done through mc callback to global_init.
3547836SJohn.Forte@Sun.COM 	 */
3557836SJohn.Forte@Sun.COM 	nscsetup();
3567836SJohn.Forte@Sun.COM 
3577836SJohn.Forte@Sun.COM 	mutex_init(&_nsc_drv_lock, NULL, MUTEX_DRIVER, NULL);
3587836SJohn.Forte@Sun.COM 
3597836SJohn.Forte@Sun.COM 	_nsc_raw_io = nsc_register_io("raw",
3607836SJohn.Forte@Sun.COM 	    NSC_RAW_ID | _nsc_raw_flags, _nsc_raw_def);
3617836SJohn.Forte@Sun.COM 
3627836SJohn.Forte@Sun.COM 	if (!_nsc_raw_io)
363*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!_nsc_init: register io failed - raw");
3647836SJohn.Forte@Sun.COM 
3657836SJohn.Forte@Sun.COM 	_nsc_init_ncio();
3667836SJohn.Forte@Sun.COM 	_nsc_init_frz();
3677836SJohn.Forte@Sun.COM 
3687836SJohn.Forte@Sun.COM 	_nsc_init_done = 1;
3697836SJohn.Forte@Sun.COM }
3707836SJohn.Forte@Sun.COM 
3717836SJohn.Forte@Sun.COM 
3727836SJohn.Forte@Sun.COM /*
3737836SJohn.Forte@Sun.COM  * Called after the mc refresh is complete (SEG_INIT callbacks have
3747836SJohn.Forte@Sun.COM  * been received) and module _attach() is done.  Only does any real
3757836SJohn.Forte@Sun.COM  * work when all of the above conditions have been met.
3767836SJohn.Forte@Sun.COM  */
3777836SJohn.Forte@Sun.COM void
nscsetup()3787836SJohn.Forte@Sun.COM nscsetup()
3797836SJohn.Forte@Sun.COM {
3808694SMark.Musante@Sun.COM 	if (nsc_max_devices() == 0 || _nsc_minor_fd != NULL)
3817836SJohn.Forte@Sun.COM 		return;
3827836SJohn.Forte@Sun.COM 
3837836SJohn.Forte@Sun.COM 	_nsc_minor_fd = nsc_kmem_zalloc(sizeof (nsc_fd_t *)*_nsc_maxdev,
3847836SJohn.Forte@Sun.COM 	    0, _nsc_local_mem);
3857836SJohn.Forte@Sun.COM 
3868694SMark.Musante@Sun.COM 	if (!_nsc_minor_fd) {
387*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!nscsetup - alloc failed");
3888694SMark.Musante@Sun.COM 		return;
3898694SMark.Musante@Sun.COM 	}
3908694SMark.Musante@Sun.COM 
3917836SJohn.Forte@Sun.COM 	_nsc_minor_slp = nsc_kmem_zalloc(sizeof (kmutex_t *)*_nsc_maxdev,
3927836SJohn.Forte@Sun.COM 	    0, _nsc_local_mem);
3937836SJohn.Forte@Sun.COM 
3948694SMark.Musante@Sun.COM 	if (!_nsc_minor_slp)  {
395*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!nscsetup - alloc failed");
3968694SMark.Musante@Sun.COM 		nsc_kmem_free(_nsc_minor_fd, sizeof (nsc_fd_t *) * _nsc_maxdev);
3978694SMark.Musante@Sun.COM 		_nsc_minor_fd = (nsc_fd_t **)NULL;
3988694SMark.Musante@Sun.COM 	}
3997836SJohn.Forte@Sun.COM }
4007836SJohn.Forte@Sun.COM 
4018694SMark.Musante@Sun.COM static void
nscteardown()4028694SMark.Musante@Sun.COM nscteardown()
4038694SMark.Musante@Sun.COM {
4048694SMark.Musante@Sun.COM 	int i;
4058694SMark.Musante@Sun.COM 
4068694SMark.Musante@Sun.COM 	if (_nsc_minor_fd == NULL)
4078694SMark.Musante@Sun.COM 		return;
4088694SMark.Musante@Sun.COM 
4098694SMark.Musante@Sun.COM #ifdef DEBUG
4108694SMark.Musante@Sun.COM 	/* Check all devices were closed.  Index 0 is the prototype dev. */
4118694SMark.Musante@Sun.COM 	for (i = 1; i < _nsc_maxdev; i++) {
4128694SMark.Musante@Sun.COM 		ASSERT(_nsc_minor_slp[i] == NULL);
4138694SMark.Musante@Sun.COM 		ASSERT(_nsc_minor_fd[i] == NULL);
4148694SMark.Musante@Sun.COM 	}
4158694SMark.Musante@Sun.COM #endif /* DEBUG */
4168694SMark.Musante@Sun.COM 
4178694SMark.Musante@Sun.COM 	nsc_kmem_free(_nsc_minor_fd, sizeof (nsc_fd_t *) * _nsc_maxdev);
4188694SMark.Musante@Sun.COM 	nsc_kmem_free(_nsc_minor_slp, sizeof (kmutex_t *) * _nsc_maxdev);
4198694SMark.Musante@Sun.COM 
4208694SMark.Musante@Sun.COM 	_nsc_minor_fd = (nsc_fd_t **)NULL;
4218694SMark.Musante@Sun.COM 	_nsc_minor_slp = (kmutex_t **)NULL;
4228694SMark.Musante@Sun.COM }
4237836SJohn.Forte@Sun.COM 
4247836SJohn.Forte@Sun.COM int
nsc_load()4257836SJohn.Forte@Sun.COM nsc_load()
4267836SJohn.Forte@Sun.COM {
4277836SJohn.Forte@Sun.COM 	nsc_init();
4287836SJohn.Forte@Sun.COM 	return (0);
4297836SJohn.Forte@Sun.COM }
4307836SJohn.Forte@Sun.COM 
4317836SJohn.Forte@Sun.COM 
4327836SJohn.Forte@Sun.COM int
nsc_unload()4337836SJohn.Forte@Sun.COM nsc_unload()
4347836SJohn.Forte@Sun.COM {
4357836SJohn.Forte@Sun.COM 	if (!_nsc_init_done) {
4367836SJohn.Forte@Sun.COM 		return (0);
4377836SJohn.Forte@Sun.COM 	}
4387836SJohn.Forte@Sun.COM 
4398694SMark.Musante@Sun.COM 	nscteardown();
4408694SMark.Musante@Sun.COM 
4417836SJohn.Forte@Sun.COM 	(void) _nsc_deinit_power();
4427836SJohn.Forte@Sun.COM 	_nsc_deinit_resv();
4437836SJohn.Forte@Sun.COM 	_nsc_deinit_mem();
4447836SJohn.Forte@Sun.COM 	_nsc_deinit_rmlock();
4457836SJohn.Forte@Sun.COM 	_nsc_deinit_svc();
4467836SJohn.Forte@Sun.COM 	_nsc_deinit_frz();
4477836SJohn.Forte@Sun.COM 	_nsc_deinit_ncio();
4487836SJohn.Forte@Sun.COM 
4497836SJohn.Forte@Sun.COM 	if (_nsc_vchr_io)
4507836SJohn.Forte@Sun.COM 		(void) nsc_unregister_io(_nsc_vchr_io, 0);
4517836SJohn.Forte@Sun.COM 
4527836SJohn.Forte@Sun.COM 	if (_nsc_file_io)
4537836SJohn.Forte@Sun.COM 		(void) nsc_unregister_io(_nsc_file_io, 0);
4547836SJohn.Forte@Sun.COM 
4557836SJohn.Forte@Sun.COM 	_nsc_vchr_io = NULL;
4567836SJohn.Forte@Sun.COM 	_nsc_file_io = NULL;
4577836SJohn.Forte@Sun.COM 
4587836SJohn.Forte@Sun.COM 	if (_nsc_raw_io)
4597836SJohn.Forte@Sun.COM 		(void) nsc_unregister_io(_nsc_raw_io, 0);
4607836SJohn.Forte@Sun.COM 
4617836SJohn.Forte@Sun.COM 	_nsc_raw_io = NULL;
4627836SJohn.Forte@Sun.COM 
4637836SJohn.Forte@Sun.COM 	_nsc_deinit_dev();
4647836SJohn.Forte@Sun.COM 	_nsc_deinit_os();
4657836SJohn.Forte@Sun.COM 
4667836SJohn.Forte@Sun.COM 	_nsc_init_done = 0;
4677836SJohn.Forte@Sun.COM 	return (0);
4687836SJohn.Forte@Sun.COM }
4697836SJohn.Forte@Sun.COM 
4707836SJohn.Forte@Sun.COM 
4717836SJohn.Forte@Sun.COM /* ARGSUSED */
4727836SJohn.Forte@Sun.COM 
4737836SJohn.Forte@Sun.COM int
nscopen(dev_t * devp,int flag,int otyp,cred_t * crp)4747836SJohn.Forte@Sun.COM nscopen(dev_t *devp, int flag, int otyp, cred_t *crp)
4757836SJohn.Forte@Sun.COM {
4767836SJohn.Forte@Sun.COM 	kmutex_t *slp;
4777836SJohn.Forte@Sun.COM 	int i, error;
4787836SJohn.Forte@Sun.COM 
4797836SJohn.Forte@Sun.COM 	if (error = drv_priv(crp))
4807836SJohn.Forte@Sun.COM 		return (error);
4817836SJohn.Forte@Sun.COM 
4827836SJohn.Forte@Sun.COM 	if (!_nsc_minor_fd || !_nsc_minor_slp)
4837836SJohn.Forte@Sun.COM 		return (ENXIO);
4847836SJohn.Forte@Sun.COM 
4857836SJohn.Forte@Sun.COM 	if (getminor(*devp) != 0)
4867836SJohn.Forte@Sun.COM 		return (ENXIO);
4877836SJohn.Forte@Sun.COM 
4887836SJohn.Forte@Sun.COM 	slp = nsc_kmem_alloc(sizeof (kmutex_t), 0, _nsc_local_mem);
4897836SJohn.Forte@Sun.COM 	mutex_init(slp, NULL, MUTEX_DRIVER, NULL);
4907836SJohn.Forte@Sun.COM 
4917836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_drv_lock);
4927836SJohn.Forte@Sun.COM 
4937836SJohn.Forte@Sun.COM 	for (i = 1; i < _nsc_maxdev; i++) {
4947836SJohn.Forte@Sun.COM 		if (_nsc_minor_slp[i] == NULL) {
4957836SJohn.Forte@Sun.COM 			_nsc_minor_slp[i] = slp;
4967836SJohn.Forte@Sun.COM 			break;
4977836SJohn.Forte@Sun.COM 		}
4987836SJohn.Forte@Sun.COM 	}
4997836SJohn.Forte@Sun.COM 
5007836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_drv_lock);
5017836SJohn.Forte@Sun.COM 
5027836SJohn.Forte@Sun.COM 	if (i >= _nsc_maxdev) {
5037836SJohn.Forte@Sun.COM 		mutex_destroy(slp);
5047836SJohn.Forte@Sun.COM 		nsc_kmem_free(slp, sizeof (kmutex_t));
5057836SJohn.Forte@Sun.COM 		return (EAGAIN);
5067836SJohn.Forte@Sun.COM 	}
5077836SJohn.Forte@Sun.COM 
5087836SJohn.Forte@Sun.COM 	*devp = makedevice(getmajor(*devp), i);
5097836SJohn.Forte@Sun.COM 
5107836SJohn.Forte@Sun.COM 	return (0);
5117836SJohn.Forte@Sun.COM }
5127836SJohn.Forte@Sun.COM 
5137836SJohn.Forte@Sun.COM 
5147836SJohn.Forte@Sun.COM int
_nscopen(dev_t dev,intptr_t arg,int mode,int * rvp)5157836SJohn.Forte@Sun.COM _nscopen(dev_t dev, intptr_t arg, int mode, int *rvp)
5167836SJohn.Forte@Sun.COM {
5177836SJohn.Forte@Sun.COM 	minor_t mindev = getminor(dev);
5187836SJohn.Forte@Sun.COM 	struct nscioc_open *op;
5197836SJohn.Forte@Sun.COM 	nsc_fd_t *fd;
5207836SJohn.Forte@Sun.COM 	int rc;
5217836SJohn.Forte@Sun.COM 
5227836SJohn.Forte@Sun.COM 	op = nsc_kmem_alloc(sizeof (*op), KM_SLEEP, _nsc_local_mem);
5237836SJohn.Forte@Sun.COM 	if (op == NULL) {
5247836SJohn.Forte@Sun.COM 		return (ENOMEM);
5257836SJohn.Forte@Sun.COM 	}
5267836SJohn.Forte@Sun.COM 
5277836SJohn.Forte@Sun.COM 	if (ddi_copyin((void *)arg, op, sizeof (*op), mode) < 0) {
5287836SJohn.Forte@Sun.COM 		nsc_kmem_free(op, sizeof (*op));
5297836SJohn.Forte@Sun.COM 		return (EFAULT);
5307836SJohn.Forte@Sun.COM 	}
5317836SJohn.Forte@Sun.COM 
5327836SJohn.Forte@Sun.COM 	mutex_enter(_nsc_minor_slp[mindev]);
5337836SJohn.Forte@Sun.COM 
5347836SJohn.Forte@Sun.COM 	if (_nsc_minor_fd[mindev]) {
5357836SJohn.Forte@Sun.COM 		mutex_exit(_nsc_minor_slp[mindev]);
5367836SJohn.Forte@Sun.COM 		nsc_kmem_free(op, sizeof (*op));
5377836SJohn.Forte@Sun.COM 		return (EBUSY);
5387836SJohn.Forte@Sun.COM 	}
5397836SJohn.Forte@Sun.COM 
5407836SJohn.Forte@Sun.COM 	op->path[sizeof (op->path)-1] = 0;
5417836SJohn.Forte@Sun.COM 
5427836SJohn.Forte@Sun.COM 	fd = nsc_open(op->path, (op->flag & NSC_TYPES), 0, 0, &rc);
5437836SJohn.Forte@Sun.COM 
5447836SJohn.Forte@Sun.COM 	if (fd == NULL) {
5457836SJohn.Forte@Sun.COM 		mutex_exit(_nsc_minor_slp[mindev]);
5467836SJohn.Forte@Sun.COM 		nsc_kmem_free(op, sizeof (*op));
5477836SJohn.Forte@Sun.COM 		return (rc);
5487836SJohn.Forte@Sun.COM 	}
5497836SJohn.Forte@Sun.COM 
5507836SJohn.Forte@Sun.COM 	mode |= (op->mode - FOPEN);
5517836SJohn.Forte@Sun.COM 
5527836SJohn.Forte@Sun.COM 	if (mode & (FWRITE|FEXCL)) {
5537836SJohn.Forte@Sun.COM 		if ((rc = nsc_reserve(fd, NSC_PCATCH)) != 0) {
5547836SJohn.Forte@Sun.COM 			mutex_exit(_nsc_minor_slp[mindev]);
5557836SJohn.Forte@Sun.COM 			(void) nsc_close(fd);
5567836SJohn.Forte@Sun.COM 			nsc_kmem_free(op, sizeof (*op));
5577836SJohn.Forte@Sun.COM 			return (rc);
5587836SJohn.Forte@Sun.COM 		}
5597836SJohn.Forte@Sun.COM 	}
5607836SJohn.Forte@Sun.COM 
5617836SJohn.Forte@Sun.COM 	*rvp = 0;
5627836SJohn.Forte@Sun.COM 	_nsc_minor_fd[mindev] = fd;
5637836SJohn.Forte@Sun.COM 
5647836SJohn.Forte@Sun.COM 	mutex_exit(_nsc_minor_slp[mindev]);
5657836SJohn.Forte@Sun.COM 	nsc_kmem_free(op, sizeof (*op));
5667836SJohn.Forte@Sun.COM 	return (0);
5677836SJohn.Forte@Sun.COM }
5687836SJohn.Forte@Sun.COM 
5697836SJohn.Forte@Sun.COM 
5707836SJohn.Forte@Sun.COM /* ARGSUSED */
5717836SJohn.Forte@Sun.COM 
5727836SJohn.Forte@Sun.COM int
nscclose(dev_t dev,int flag,int otyp,cred_t * crp)5737836SJohn.Forte@Sun.COM nscclose(dev_t dev, int flag, int otyp, cred_t *crp)
5747836SJohn.Forte@Sun.COM {
5757836SJohn.Forte@Sun.COM 	minor_t mindev = getminor(dev);
5767836SJohn.Forte@Sun.COM 	kmutex_t *slp;
5777836SJohn.Forte@Sun.COM 	nsc_fd_t *fd;
5787836SJohn.Forte@Sun.COM 
5797836SJohn.Forte@Sun.COM 	if (!_nsc_minor_fd || !_nsc_minor_slp)
5807836SJohn.Forte@Sun.COM 		return (0);
5817836SJohn.Forte@Sun.COM 
5827836SJohn.Forte@Sun.COM 	if ((slp = _nsc_minor_slp[mindev]) == 0)
5837836SJohn.Forte@Sun.COM 		return (0);
5847836SJohn.Forte@Sun.COM 
5857836SJohn.Forte@Sun.COM 	if ((fd = _nsc_minor_fd[mindev]) != NULL)
5867836SJohn.Forte@Sun.COM 		(void) nsc_close(fd);
5877836SJohn.Forte@Sun.COM 
5887836SJohn.Forte@Sun.COM 	_nsc_minor_fd[mindev] = NULL;
5897836SJohn.Forte@Sun.COM 	_nsc_minor_slp[mindev] = NULL;
5907836SJohn.Forte@Sun.COM 
5917836SJohn.Forte@Sun.COM 	mutex_destroy(slp);
5927836SJohn.Forte@Sun.COM 	nsc_kmem_free(slp, sizeof (kmutex_t));
5937836SJohn.Forte@Sun.COM 	return (0);
5947836SJohn.Forte@Sun.COM }
5957836SJohn.Forte@Sun.COM 
5967836SJohn.Forte@Sun.COM 
5977836SJohn.Forte@Sun.COM /* ARGSUSED */
5987836SJohn.Forte@Sun.COM 
5997836SJohn.Forte@Sun.COM int
nscread(dev_t dev,uio_t * uiop,cred_t * crp)6007836SJohn.Forte@Sun.COM nscread(dev_t dev, uio_t *uiop, cred_t *crp)
6017836SJohn.Forte@Sun.COM {
6027836SJohn.Forte@Sun.COM 	minor_t mindev = getminor(dev);
6037836SJohn.Forte@Sun.COM 	int rc, resv;
6047836SJohn.Forte@Sun.COM 	nsc_fd_t *fd;
6057836SJohn.Forte@Sun.COM 
6067836SJohn.Forte@Sun.COM 	if ((fd = _nsc_minor_fd[mindev]) == 0)
6077836SJohn.Forte@Sun.COM 		return (EIO);
6087836SJohn.Forte@Sun.COM 
6097836SJohn.Forte@Sun.COM 	mutex_enter(_nsc_minor_slp[mindev]);
6107836SJohn.Forte@Sun.COM 
6117836SJohn.Forte@Sun.COM 	resv = (nsc_held(fd) == 0);
6127836SJohn.Forte@Sun.COM 
6137836SJohn.Forte@Sun.COM 	if (resv && (rc = nsc_reserve(fd, NSC_PCATCH)) != 0) {
6147836SJohn.Forte@Sun.COM 		mutex_exit(_nsc_minor_slp[mindev]);
6157836SJohn.Forte@Sun.COM 		return (rc);
6167836SJohn.Forte@Sun.COM 	}
6177836SJohn.Forte@Sun.COM 
6187836SJohn.Forte@Sun.COM 	rc = nsc_uread(fd, uiop, crp);
6197836SJohn.Forte@Sun.COM 
6207836SJohn.Forte@Sun.COM 	if (resv)
6217836SJohn.Forte@Sun.COM 		nsc_release(fd);
6227836SJohn.Forte@Sun.COM 
6237836SJohn.Forte@Sun.COM 	mutex_exit(_nsc_minor_slp[mindev]);
6247836SJohn.Forte@Sun.COM 	return (rc);
6257836SJohn.Forte@Sun.COM }
6267836SJohn.Forte@Sun.COM 
6277836SJohn.Forte@Sun.COM 
6287836SJohn.Forte@Sun.COM /* ARGSUSED */
6297836SJohn.Forte@Sun.COM 
6307836SJohn.Forte@Sun.COM int
nscwrite(dev_t dev,uio_t * uiop,cred_t * crp)6317836SJohn.Forte@Sun.COM nscwrite(dev_t dev, uio_t *uiop, cred_t *crp)
6327836SJohn.Forte@Sun.COM {
6337836SJohn.Forte@Sun.COM 	minor_t mindev = getminor(dev);
6347836SJohn.Forte@Sun.COM 	int rc, resv;
6357836SJohn.Forte@Sun.COM 	nsc_fd_t *fd;
6367836SJohn.Forte@Sun.COM 
6377836SJohn.Forte@Sun.COM 	if ((fd = _nsc_minor_fd[mindev]) == 0)
6387836SJohn.Forte@Sun.COM 		return (EIO);
6397836SJohn.Forte@Sun.COM 
6407836SJohn.Forte@Sun.COM 	mutex_enter(_nsc_minor_slp[mindev]);
6417836SJohn.Forte@Sun.COM 
6427836SJohn.Forte@Sun.COM 	resv = (nsc_held(fd) == 0);
6437836SJohn.Forte@Sun.COM 
6447836SJohn.Forte@Sun.COM 	if (resv && (rc = nsc_reserve(fd, NSC_PCATCH)) != 0) {
6457836SJohn.Forte@Sun.COM 		mutex_exit(_nsc_minor_slp[mindev]);
6467836SJohn.Forte@Sun.COM 		return (rc);
6477836SJohn.Forte@Sun.COM 	}
6487836SJohn.Forte@Sun.COM 
6497836SJohn.Forte@Sun.COM 	rc = nsc_uwrite(fd, uiop, crp);
6507836SJohn.Forte@Sun.COM 
6517836SJohn.Forte@Sun.COM 	if (resv)
6527836SJohn.Forte@Sun.COM 		nsc_release(fd);
6537836SJohn.Forte@Sun.COM 
6547836SJohn.Forte@Sun.COM 	mutex_exit(_nsc_minor_slp[mindev]);
6557836SJohn.Forte@Sun.COM 	return (rc);
6567836SJohn.Forte@Sun.COM }
6577836SJohn.Forte@Sun.COM 
6587836SJohn.Forte@Sun.COM 
6597836SJohn.Forte@Sun.COM int
_nscreserve(dev_t dev,int * rvp)6607836SJohn.Forte@Sun.COM _nscreserve(dev_t dev, int *rvp)
6617836SJohn.Forte@Sun.COM {
6627836SJohn.Forte@Sun.COM 	minor_t mindev = getminor(dev);
6637836SJohn.Forte@Sun.COM 	nsc_fd_t *fd;
6647836SJohn.Forte@Sun.COM 	int rc;
6657836SJohn.Forte@Sun.COM 
6667836SJohn.Forte@Sun.COM 	if ((fd = _nsc_minor_fd[mindev]) == 0)
6677836SJohn.Forte@Sun.COM 		return (EIO);
6687836SJohn.Forte@Sun.COM 
6697836SJohn.Forte@Sun.COM 	mutex_enter(_nsc_minor_slp[mindev]);
6707836SJohn.Forte@Sun.COM 
6717836SJohn.Forte@Sun.COM 	if (nsc_held(fd)) {
6727836SJohn.Forte@Sun.COM 		mutex_exit(_nsc_minor_slp[mindev]);
6737836SJohn.Forte@Sun.COM 		return (EBUSY);
6747836SJohn.Forte@Sun.COM 	}
6757836SJohn.Forte@Sun.COM 
6767836SJohn.Forte@Sun.COM 	if ((rc = nsc_reserve(fd, NSC_PCATCH)) != 0) {
6777836SJohn.Forte@Sun.COM 		mutex_exit(_nsc_minor_slp[mindev]);
6787836SJohn.Forte@Sun.COM 		return (rc);
6797836SJohn.Forte@Sun.COM 	}
6807836SJohn.Forte@Sun.COM 
6817836SJohn.Forte@Sun.COM 	*rvp = 0;
6827836SJohn.Forte@Sun.COM 
6837836SJohn.Forte@Sun.COM 	mutex_exit(_nsc_minor_slp[mindev]);
6847836SJohn.Forte@Sun.COM 	return (0);
6857836SJohn.Forte@Sun.COM }
6867836SJohn.Forte@Sun.COM 
6877836SJohn.Forte@Sun.COM 
6887836SJohn.Forte@Sun.COM int
_nscrelease(dev_t dev,int * rvp)6897836SJohn.Forte@Sun.COM _nscrelease(dev_t dev, int *rvp)
6907836SJohn.Forte@Sun.COM {
6917836SJohn.Forte@Sun.COM 	minor_t mindev = getminor(dev);
6927836SJohn.Forte@Sun.COM 	nsc_fd_t *fd;
6937836SJohn.Forte@Sun.COM 
6947836SJohn.Forte@Sun.COM 	if ((fd = _nsc_minor_fd[mindev]) == 0)
6957836SJohn.Forte@Sun.COM 		return (EIO);
6967836SJohn.Forte@Sun.COM 
6977836SJohn.Forte@Sun.COM 	mutex_enter(_nsc_minor_slp[mindev]);
6987836SJohn.Forte@Sun.COM 
6997836SJohn.Forte@Sun.COM 	if (!nsc_held(fd)) {
7007836SJohn.Forte@Sun.COM 		mutex_exit(_nsc_minor_slp[mindev]);
7017836SJohn.Forte@Sun.COM 		return (EINVAL);
7027836SJohn.Forte@Sun.COM 	}
7037836SJohn.Forte@Sun.COM 
7047836SJohn.Forte@Sun.COM 	nsc_release(fd);
7057836SJohn.Forte@Sun.COM 
7067836SJohn.Forte@Sun.COM 	*rvp = 0;
7077836SJohn.Forte@Sun.COM 
7087836SJohn.Forte@Sun.COM 	mutex_exit(_nsc_minor_slp[mindev]);
7097836SJohn.Forte@Sun.COM 	return (0);
7107836SJohn.Forte@Sun.COM }
7117836SJohn.Forte@Sun.COM 
7127836SJohn.Forte@Sun.COM 
7137836SJohn.Forte@Sun.COM int
_nscpartsize(dev_t dev,intptr_t arg,int mode)7147836SJohn.Forte@Sun.COM _nscpartsize(dev_t dev, intptr_t arg, int mode)
7157836SJohn.Forte@Sun.COM {
7167836SJohn.Forte@Sun.COM 	struct nscioc_partsize partsize;
7177836SJohn.Forte@Sun.COM 	minor_t mindev = getminor(dev);
7187836SJohn.Forte@Sun.COM 	nsc_size_t size;
7197836SJohn.Forte@Sun.COM 	int rc, resv;
7207836SJohn.Forte@Sun.COM 	nsc_fd_t *fd;
7217836SJohn.Forte@Sun.COM 
7227836SJohn.Forte@Sun.COM 	if ((fd = _nsc_minor_fd[mindev]) == 0)
7237836SJohn.Forte@Sun.COM 		return (EIO);
7247836SJohn.Forte@Sun.COM 
7257836SJohn.Forte@Sun.COM 	mutex_enter(_nsc_minor_slp[mindev]);
7267836SJohn.Forte@Sun.COM 
7277836SJohn.Forte@Sun.COM 	resv = (nsc_held(fd) == 0);
7287836SJohn.Forte@Sun.COM 
7297836SJohn.Forte@Sun.COM 	if (resv && (rc = nsc_reserve(fd, NSC_PCATCH)) != 0) {
7307836SJohn.Forte@Sun.COM 		mutex_exit(_nsc_minor_slp[mindev]);
7317836SJohn.Forte@Sun.COM 		return (rc);
7327836SJohn.Forte@Sun.COM 	}
7337836SJohn.Forte@Sun.COM 
7347836SJohn.Forte@Sun.COM 	rc = nsc_partsize(fd, &size);
7357836SJohn.Forte@Sun.COM 	partsize.partsize = (uint64_t)size;
7367836SJohn.Forte@Sun.COM 
7377836SJohn.Forte@Sun.COM 	if (resv)
7387836SJohn.Forte@Sun.COM 		nsc_release(fd);
7397836SJohn.Forte@Sun.COM 
7407836SJohn.Forte@Sun.COM 	mutex_exit(_nsc_minor_slp[mindev]);
7417836SJohn.Forte@Sun.COM 
7427836SJohn.Forte@Sun.COM 	if (ddi_copyout((void *)&partsize, (void *)arg,
7437836SJohn.Forte@Sun.COM 	    sizeof (partsize), mode) < 0) {
7447836SJohn.Forte@Sun.COM 		return (EFAULT);
7457836SJohn.Forte@Sun.COM 	}
7467836SJohn.Forte@Sun.COM 
7477836SJohn.Forte@Sun.COM 	return (rc);
7487836SJohn.Forte@Sun.COM }
7497836SJohn.Forte@Sun.COM 
7507836SJohn.Forte@Sun.COM 
7517836SJohn.Forte@Sun.COM /* ARGSUSED */
7527836SJohn.Forte@Sun.COM 
7537836SJohn.Forte@Sun.COM int
nscioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * crp,int * rvp)7547836SJohn.Forte@Sun.COM nscioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *crp, int *rvp)
7557836SJohn.Forte@Sun.COM {
7567836SJohn.Forte@Sun.COM 	struct nscioc_bsize *bsize = NULL;
7577836SJohn.Forte@Sun.COM 	char *path = NULL;
7587836SJohn.Forte@Sun.COM 	int rc = 0;
7597836SJohn.Forte@Sun.COM 
7607836SJohn.Forte@Sun.COM 	*rvp = 0;
7617836SJohn.Forte@Sun.COM 
7627836SJohn.Forte@Sun.COM 	switch (cmd) {
7637836SJohn.Forte@Sun.COM 	case NSCIOC_OPEN:
7647836SJohn.Forte@Sun.COM 		rc = _nscopen(dev, arg, mode, rvp);
7657836SJohn.Forte@Sun.COM 		break;
7667836SJohn.Forte@Sun.COM 
7677836SJohn.Forte@Sun.COM 	case NSCIOC_RESERVE:
7687836SJohn.Forte@Sun.COM 		rc = _nscreserve(dev, rvp);
7697836SJohn.Forte@Sun.COM 		break;
7707836SJohn.Forte@Sun.COM 
7717836SJohn.Forte@Sun.COM 	case NSCIOC_RELEASE:
7727836SJohn.Forte@Sun.COM 		rc = _nscrelease(dev, rvp);
7737836SJohn.Forte@Sun.COM 		break;
7747836SJohn.Forte@Sun.COM 
7757836SJohn.Forte@Sun.COM 	case NSCIOC_PARTSIZE:
7767836SJohn.Forte@Sun.COM 		rc = _nscpartsize(dev, arg, mode);
7777836SJohn.Forte@Sun.COM 		break;
7787836SJohn.Forte@Sun.COM 
7797836SJohn.Forte@Sun.COM 	case NSCIOC_FREEZE:
7807836SJohn.Forte@Sun.COM 		path = nsc_kmem_alloc(NSC_MAXPATH, KM_SLEEP, _nsc_local_mem);
7817836SJohn.Forte@Sun.COM 		if (path == NULL) {
7827836SJohn.Forte@Sun.COM 			rc = ENOMEM;
7837836SJohn.Forte@Sun.COM 			break;
7847836SJohn.Forte@Sun.COM 		}
7857836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)arg, path, NSC_MAXPATH, mode) < 0)
7867836SJohn.Forte@Sun.COM 			rc = EFAULT;
7877836SJohn.Forte@Sun.COM 		else {
7887836SJohn.Forte@Sun.COM 			path[NSC_MAXPATH-1] = 0;
7897836SJohn.Forte@Sun.COM 			rc = _nsc_frz_start(path, rvp);
7907836SJohn.Forte@Sun.COM 		}
7917836SJohn.Forte@Sun.COM 		break;
7927836SJohn.Forte@Sun.COM 
7937836SJohn.Forte@Sun.COM 	case NSCIOC_UNFREEZE:
7947836SJohn.Forte@Sun.COM 		path = nsc_kmem_alloc(NSC_MAXPATH, KM_SLEEP, _nsc_local_mem);
7957836SJohn.Forte@Sun.COM 		if (path == NULL) {
7967836SJohn.Forte@Sun.COM 			rc = ENOMEM;
7977836SJohn.Forte@Sun.COM 			break;
7987836SJohn.Forte@Sun.COM 		}
7997836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)arg, path, NSC_MAXPATH, mode) < 0)
8007836SJohn.Forte@Sun.COM 			rc = EFAULT;
8017836SJohn.Forte@Sun.COM 		else {
8027836SJohn.Forte@Sun.COM 			path[NSC_MAXPATH-1] = 0;
8037836SJohn.Forte@Sun.COM 			rc = _nsc_frz_stop(path, rvp);
8047836SJohn.Forte@Sun.COM 		}
8057836SJohn.Forte@Sun.COM 		break;
8067836SJohn.Forte@Sun.COM 
8077836SJohn.Forte@Sun.COM 	case NSCIOC_ISFROZEN:
8087836SJohn.Forte@Sun.COM 		path = nsc_kmem_alloc(NSC_MAXPATH, KM_SLEEP, _nsc_local_mem);
8097836SJohn.Forte@Sun.COM 		if (path == NULL) {
8107836SJohn.Forte@Sun.COM 			rc = ENOMEM;
8117836SJohn.Forte@Sun.COM 			break;
8127836SJohn.Forte@Sun.COM 		}
8137836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)arg, path, NSC_MAXPATH, mode) < 0)
8147836SJohn.Forte@Sun.COM 			rc = EFAULT;
8157836SJohn.Forte@Sun.COM 		else {
8167836SJohn.Forte@Sun.COM 			path[NSC_MAXPATH-1] = 0;
8177836SJohn.Forte@Sun.COM 			rc = _nsc_frz_isfrozen(path, rvp);
8187836SJohn.Forte@Sun.COM 		}
8197836SJohn.Forte@Sun.COM 		break;
8207836SJohn.Forte@Sun.COM 
8217836SJohn.Forte@Sun.COM #ifdef ENABLE_POWER_MSG
8227836SJohn.Forte@Sun.COM 	case NSCIOC_POWERMSG:
8237836SJohn.Forte@Sun.COM 		rc = _nsc_power((void *)arg, rvp);
8247836SJohn.Forte@Sun.COM 		break;
8257836SJohn.Forte@Sun.COM #endif
8267836SJohn.Forte@Sun.COM 
8277836SJohn.Forte@Sun.COM 	case NSCIOC_NSKERND:
8287836SJohn.Forte@Sun.COM 		rc = nskernd_command(arg, mode, rvp);
8297836SJohn.Forte@Sun.COM 		break;
8307836SJohn.Forte@Sun.COM 
8317836SJohn.Forte@Sun.COM 	/* return sizes of global memory segments */
8327836SJohn.Forte@Sun.COM 	case NSCIOC_GLOBAL_SIZES:
8337836SJohn.Forte@Sun.COM 		if (!_nsc_init_done) {
8347836SJohn.Forte@Sun.COM 			rc = EINVAL;
8357836SJohn.Forte@Sun.COM 			break;
8367836SJohn.Forte@Sun.COM 		}
8377836SJohn.Forte@Sun.COM 
8387836SJohn.Forte@Sun.COM 		rc = _nsc_get_global_sizes((void *)arg, rvp);
8397836SJohn.Forte@Sun.COM 
8407836SJohn.Forte@Sun.COM 		break;
8417836SJohn.Forte@Sun.COM 
8427836SJohn.Forte@Sun.COM 	/* return contents of global segments */
8437836SJohn.Forte@Sun.COM 	case NSCIOC_GLOBAL_DATA:
8447836SJohn.Forte@Sun.COM 		if (!_nsc_init_done) {
8457836SJohn.Forte@Sun.COM 			rc = EINVAL;
8467836SJohn.Forte@Sun.COM 			break;
8477836SJohn.Forte@Sun.COM 		}
8487836SJohn.Forte@Sun.COM 
8497836SJohn.Forte@Sun.COM 		rc = _nsc_get_global_data((void *)arg, rvp);
8507836SJohn.Forte@Sun.COM 		break;
8517836SJohn.Forte@Sun.COM 
8527836SJohn.Forte@Sun.COM 	/*
8537836SJohn.Forte@Sun.COM 	 * nvmem systems:
8547836SJohn.Forte@Sun.COM 	 * clear the hdr dirty bit to prevent loading from nvme on reboot
8557836SJohn.Forte@Sun.COM 	 */
8567836SJohn.Forte@Sun.COM 	case NSCIOC_NVMEM_CLEANF:
8577836SJohn.Forte@Sun.COM 		rc = _nsc_clear_dirty(1);	/* dont be nice about it */
8587836SJohn.Forte@Sun.COM 		break;
8597836SJohn.Forte@Sun.COM 	case NSCIOC_NVMEM_CLEAN:
8607836SJohn.Forte@Sun.COM 		rc = _nsc_clear_dirty(0);
8617836SJohn.Forte@Sun.COM 		break;
8627836SJohn.Forte@Sun.COM 
8637836SJohn.Forte@Sun.COM 	case NSCIOC_BSIZE:
8647836SJohn.Forte@Sun.COM 		bsize = nsc_kmem_alloc(sizeof (*bsize), KM_SLEEP,
8657836SJohn.Forte@Sun.COM 		    _nsc_local_mem);
8667836SJohn.Forte@Sun.COM 		if (bsize == NULL) {
8677836SJohn.Forte@Sun.COM 			rc = ENOMEM;
8687836SJohn.Forte@Sun.COM 			break;
8697836SJohn.Forte@Sun.COM 		}
8707836SJohn.Forte@Sun.COM 
8717836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)arg, bsize, sizeof (*bsize), mode) < 0) {
8727836SJohn.Forte@Sun.COM 			rc = EFAULT;
8737836SJohn.Forte@Sun.COM 			break;
8747836SJohn.Forte@Sun.COM 		}
8757836SJohn.Forte@Sun.COM 
8767836SJohn.Forte@Sun.COM 		rc = nskern_bsize(bsize, rvp);
8777836SJohn.Forte@Sun.COM 		if (rc == 0) {
8787836SJohn.Forte@Sun.COM 			if (ddi_copyout(bsize, (void *)arg,
8797836SJohn.Forte@Sun.COM 			    sizeof (*bsize), mode) < 0) {
8807836SJohn.Forte@Sun.COM 				rc = EFAULT;
8817836SJohn.Forte@Sun.COM 				break;
8827836SJohn.Forte@Sun.COM 			}
8837836SJohn.Forte@Sun.COM 		}
8847836SJohn.Forte@Sun.COM 
8857836SJohn.Forte@Sun.COM 		break;
8867836SJohn.Forte@Sun.COM 
8877836SJohn.Forte@Sun.COM 	default:
8887836SJohn.Forte@Sun.COM 		return (ENOTTY);
8897836SJohn.Forte@Sun.COM 	}
8907836SJohn.Forte@Sun.COM 
8917836SJohn.Forte@Sun.COM 	if (bsize != NULL) {
8927836SJohn.Forte@Sun.COM 		nsc_kmem_free(bsize, sizeof (*bsize));
8937836SJohn.Forte@Sun.COM 		bsize = NULL;
8947836SJohn.Forte@Sun.COM 	}
8957836SJohn.Forte@Sun.COM 	if (path != NULL) {
8967836SJohn.Forte@Sun.COM 		nsc_kmem_free(path, NSC_MAXPATH);
8977836SJohn.Forte@Sun.COM 		path = NULL;
8987836SJohn.Forte@Sun.COM 	}
8997836SJohn.Forte@Sun.COM 	return (rc);
9007836SJohn.Forte@Sun.COM }
9017836SJohn.Forte@Sun.COM 
9027836SJohn.Forte@Sun.COM 
9037836SJohn.Forte@Sun.COM int
nsc_max_devices(void)9047836SJohn.Forte@Sun.COM nsc_max_devices(void)
9057836SJohn.Forte@Sun.COM {
9067836SJohn.Forte@Sun.COM 	return (_nsc_max_devices);
9077836SJohn.Forte@Sun.COM }
9087836SJohn.Forte@Sun.COM 
9097836SJohn.Forte@Sun.COM 
9107836SJohn.Forte@Sun.COM /*
9117836SJohn.Forte@Sun.COM  * Used by _nsc_global_setup() in case nvram is dirty and has saved a different
9127836SJohn.Forte@Sun.COM  * value for nsc_max_devices. We need to use the saved value, not the new
9137836SJohn.Forte@Sun.COM  * one configured by the user.
9147836SJohn.Forte@Sun.COM  */
9157836SJohn.Forte@Sun.COM void
_nsc_set_max_devices(int maxdev)9167836SJohn.Forte@Sun.COM _nsc_set_max_devices(int maxdev)
9177836SJohn.Forte@Sun.COM {
9187836SJohn.Forte@Sun.COM 	_nsc_max_devices = maxdev;
9197836SJohn.Forte@Sun.COM 	_nsc_maxdev = _nsc_max_devices;
9207836SJohn.Forte@Sun.COM }
921