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 /* 22*8694SMark.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(); 95*8694SMark.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 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(); 1807836SJohn.Forte@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 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 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 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, 2537836SJohn.Forte@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, 2677836SJohn.Forte@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 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) { 285*8694SMark.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 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 3297836SJohn.Forte@Sun.COM _nsctl_print(dev_t dev, char *s) 3307836SJohn.Forte@Sun.COM { 3317836SJohn.Forte@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 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) 3637836SJohn.Forte@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 3787836SJohn.Forte@Sun.COM nscsetup() 3797836SJohn.Forte@Sun.COM { 380*8694SMark.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 386*8694SMark.Musante@Sun.COM if (!_nsc_minor_fd) { 387*8694SMark.Musante@Sun.COM cmn_err(CE_WARN, "nscsetup - alloc failed"); 388*8694SMark.Musante@Sun.COM return; 389*8694SMark.Musante@Sun.COM } 390*8694SMark.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 394*8694SMark.Musante@Sun.COM if (!_nsc_minor_slp) { 3957836SJohn.Forte@Sun.COM cmn_err(CE_WARN, "nscsetup - alloc failed"); 396*8694SMark.Musante@Sun.COM nsc_kmem_free(_nsc_minor_fd, sizeof (nsc_fd_t *) * _nsc_maxdev); 397*8694SMark.Musante@Sun.COM _nsc_minor_fd = (nsc_fd_t **)NULL; 398*8694SMark.Musante@Sun.COM } 3997836SJohn.Forte@Sun.COM } 4007836SJohn.Forte@Sun.COM 401*8694SMark.Musante@Sun.COM static void 402*8694SMark.Musante@Sun.COM nscteardown() 403*8694SMark.Musante@Sun.COM { 404*8694SMark.Musante@Sun.COM int i; 405*8694SMark.Musante@Sun.COM 406*8694SMark.Musante@Sun.COM if (_nsc_minor_fd == NULL) 407*8694SMark.Musante@Sun.COM return; 408*8694SMark.Musante@Sun.COM 409*8694SMark.Musante@Sun.COM #ifdef DEBUG 410*8694SMark.Musante@Sun.COM /* Check all devices were closed. Index 0 is the prototype dev. */ 411*8694SMark.Musante@Sun.COM for (i = 1; i < _nsc_maxdev; i++) { 412*8694SMark.Musante@Sun.COM ASSERT(_nsc_minor_slp[i] == NULL); 413*8694SMark.Musante@Sun.COM ASSERT(_nsc_minor_fd[i] == NULL); 414*8694SMark.Musante@Sun.COM } 415*8694SMark.Musante@Sun.COM #endif /* DEBUG */ 416*8694SMark.Musante@Sun.COM 417*8694SMark.Musante@Sun.COM nsc_kmem_free(_nsc_minor_fd, sizeof (nsc_fd_t *) * _nsc_maxdev); 418*8694SMark.Musante@Sun.COM nsc_kmem_free(_nsc_minor_slp, sizeof (kmutex_t *) * _nsc_maxdev); 419*8694SMark.Musante@Sun.COM 420*8694SMark.Musante@Sun.COM _nsc_minor_fd = (nsc_fd_t **)NULL; 421*8694SMark.Musante@Sun.COM _nsc_minor_slp = (kmutex_t **)NULL; 422*8694SMark.Musante@Sun.COM } 4237836SJohn.Forte@Sun.COM 4247836SJohn.Forte@Sun.COM int 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 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 439*8694SMark.Musante@Sun.COM nscteardown(); 440*8694SMark.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 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 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 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 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 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 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 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 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 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 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 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