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