xref: /onnv-gate/usr/src/uts/common/avs/ns/sdbc/sd_misc.c (revision 11066:cebb50cbe4f9)
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 /*
229093SRamana.Srikanth@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 #define	_SCM_
277836SJohn.Forte@Sun.COM 
287836SJohn.Forte@Sun.COM #include <sys/types.h>
297836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
307836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
317836SJohn.Forte@Sun.COM #include <sys/modctl.h>
327836SJohn.Forte@Sun.COM #include <sys/conf.h>
337836SJohn.Forte@Sun.COM #include <sys/errno.h>
347836SJohn.Forte@Sun.COM #include <sys/file.h>
357836SJohn.Forte@Sun.COM #include <sys/kmem.h>
367836SJohn.Forte@Sun.COM #include <sys/cred.h>
377836SJohn.Forte@Sun.COM #include <sys/ddi.h>
387836SJohn.Forte@Sun.COM #include <sys/nsc_thread.h>
397836SJohn.Forte@Sun.COM 
407836SJohn.Forte@Sun.COM #include "sd_bcache.h"
417836SJohn.Forte@Sun.COM #include "sd_misc.h"
427836SJohn.Forte@Sun.COM #include "sd_trace.h"
437836SJohn.Forte@Sun.COM #include "sd_ft.h"
447836SJohn.Forte@Sun.COM #include "sd_io.h"
457836SJohn.Forte@Sun.COM #include "sd_bio.h"
467836SJohn.Forte@Sun.COM #include "sd_pcu.h"
477836SJohn.Forte@Sun.COM #include "sd_tdaemon.h"
487836SJohn.Forte@Sun.COM #include "sdbc_ioctl.h"
497836SJohn.Forte@Sun.COM #include <sys/ncall/ncall.h>
507836SJohn.Forte@Sun.COM #include <sys/nsctl/nsctl.h>
517836SJohn.Forte@Sun.COM #include <sys/nsctl/nsvers.h>
527836SJohn.Forte@Sun.COM 
537836SJohn.Forte@Sun.COM #include <sys/sdt.h>		/* dtrace is S10 or later */
547836SJohn.Forte@Sun.COM 
557836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s.h>
567836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_s_k.h>
577836SJohn.Forte@Sun.COM #include <sys/unistat/spcs_errors.h>
587836SJohn.Forte@Sun.COM static dev_info_t *dev_dip;
597836SJohn.Forte@Sun.COM dev_info_t *sdbc_get_dip();
607836SJohn.Forte@Sun.COM 
617836SJohn.Forte@Sun.COM 
627836SJohn.Forte@Sun.COM /*
637836SJohn.Forte@Sun.COM  *  A global variable to set the threshold for large writes to
647836SJohn.Forte@Sun.COM  *  be in write through mode when NVRAM is present. This should
657836SJohn.Forte@Sun.COM  *  solve the NVRAM bandwidth problem.
667836SJohn.Forte@Sun.COM  */
677836SJohn.Forte@Sun.COM 
687836SJohn.Forte@Sun.COM int sdbc_wrthru_len;
697836SJohn.Forte@Sun.COM nsc_size_t sdbc_max_fbas = _SD_MAX_FBAS;
707836SJohn.Forte@Sun.COM int sdbc_max_devs = 0;
717836SJohn.Forte@Sun.COM 
727836SJohn.Forte@Sun.COM krwlock_t sdbc_queue_lock;
737836SJohn.Forte@Sun.COM 
747836SJohn.Forte@Sun.COM static int _sd_debug_level = 0;
757836SJohn.Forte@Sun.COM 
767836SJohn.Forte@Sun.COM static kmutex_t _sd_block_lk;
777836SJohn.Forte@Sun.COM 
787836SJohn.Forte@Sun.COM #define	REGISTER_SVC(X, Y) (ncall_register_svc(X, Y))
797836SJohn.Forte@Sun.COM #define	UNREGISTER_SVC(X) (ncall_unregister_svc(X))
807836SJohn.Forte@Sun.COM 
817836SJohn.Forte@Sun.COM const int sdbc_major_rev = ISS_VERSION_MAJ;
827836SJohn.Forte@Sun.COM const int sdbc_minor_rev = ISS_VERSION_MIN;
837836SJohn.Forte@Sun.COM const int sdbc_micro_rev = ISS_VERSION_MIC;
847836SJohn.Forte@Sun.COM const int sdbc_baseline_rev = ISS_VERSION_NUM;
857836SJohn.Forte@Sun.COM static char sdbc_version[16];
867836SJohn.Forte@Sun.COM 
877836SJohn.Forte@Sun.COM static int _sdbc_attached = 0;
887836SJohn.Forte@Sun.COM 
897836SJohn.Forte@Sun.COM static int _sdbc_print(dev_t dev, char *s);
907836SJohn.Forte@Sun.COM static int sdbcunload(void);
917836SJohn.Forte@Sun.COM static int sdbcload(void);
927836SJohn.Forte@Sun.COM static int sdbcopen(dev_t *devp, int flag, int otyp, cred_t *crp);
937836SJohn.Forte@Sun.COM static int sdbcclose(dev_t dev, int flag, int otyp, cred_t *crp);
947836SJohn.Forte@Sun.COM static int sdbcioctl(dev_t dev, int cmd, void *arg, int mode, cred_t *crp,
957836SJohn.Forte@Sun.COM     int *rvp);
967836SJohn.Forte@Sun.COM static int _sdbc_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
977836SJohn.Forte@Sun.COM static int _sdbc_probe(dev_info_t *dip);
987836SJohn.Forte@Sun.COM static int _sdbc_attach(dev_info_t *, ddi_attach_cmd_t);
997836SJohn.Forte@Sun.COM static int _sdbc_detach(dev_info_t *, ddi_detach_cmd_t);
1007836SJohn.Forte@Sun.COM static int _sdbc_reset(dev_info_t *, ddi_reset_cmd_t);
1017836SJohn.Forte@Sun.COM 
1027836SJohn.Forte@Sun.COM #ifdef sun
1037836SJohn.Forte@Sun.COM /*
1047836SJohn.Forte@Sun.COM  * Solaris specific driver module interface code.
1057836SJohn.Forte@Sun.COM  */
1067836SJohn.Forte@Sun.COM 
1077836SJohn.Forte@Sun.COM #ifdef USES_SOFT_STATE
1087836SJohn.Forte@Sun.COM struct	sdbc_state {
1097836SJohn.Forte@Sun.COM 	dev_info_t	*dip;		/* everyone would need a devinfo */
1107836SJohn.Forte@Sun.COM };
1117836SJohn.Forte@Sun.COM 
1127836SJohn.Forte@Sun.COM static	void	*sdbc_statep;		/* for soft state routines */
1137836SJohn.Forte@Sun.COM #endif /* USES_SOFT_STATE */
1147836SJohn.Forte@Sun.COM 
1157836SJohn.Forte@Sun.COM static	struct	cb_ops sdbc_cb_ops = {
1167836SJohn.Forte@Sun.COM 	sdbcopen,	/* open */
1177836SJohn.Forte@Sun.COM 	sdbcclose,	/* close */
1187836SJohn.Forte@Sun.COM 	nodev,		/* not a block driver, strategy not an entry point */
1197836SJohn.Forte@Sun.COM 	_sdbc_print,	/* no print routine */
1207836SJohn.Forte@Sun.COM 	nodev,		/* no dump routine */
1217836SJohn.Forte@Sun.COM 	nodev,		/* read */
1227836SJohn.Forte@Sun.COM 	nodev,		/* write */
1237836SJohn.Forte@Sun.COM 	(int (*) ()) sdbcioctl,	/* ioctl */
1247836SJohn.Forte@Sun.COM 	nodev,		/* no devmap routine */
1257836SJohn.Forte@Sun.COM 	nodev,		/* no mmap routine */
1267836SJohn.Forte@Sun.COM 	nodev,		/* no segmap routine */
1277836SJohn.Forte@Sun.COM 	nochpoll,	/* no chpoll routine */
1287836SJohn.Forte@Sun.COM 	ddi_prop_op,
1297836SJohn.Forte@Sun.COM 	0,		/* not a STREAMS driver, no cb_str routine */
1307836SJohn.Forte@Sun.COM 	D_NEW | D_MP,	/* safe for multi-thread/multi-processor */
1317836SJohn.Forte@Sun.COM };
1327836SJohn.Forte@Sun.COM 
1337836SJohn.Forte@Sun.COM 
1347836SJohn.Forte@Sun.COM static	struct	dev_ops sdbc_ops = {
1357836SJohn.Forte@Sun.COM 	DEVO_REV,			/* Driver build version */
1367836SJohn.Forte@Sun.COM 	0,				/* device reference count */
1377836SJohn.Forte@Sun.COM 	_sdbc_getinfo,
1387836SJohn.Forte@Sun.COM 	nulldev,
1397836SJohn.Forte@Sun.COM 	_sdbc_probe,
1407836SJohn.Forte@Sun.COM 	_sdbc_attach,
1417836SJohn.Forte@Sun.COM 	_sdbc_detach,
1427836SJohn.Forte@Sun.COM 	_sdbc_reset,
1437836SJohn.Forte@Sun.COM 	&sdbc_cb_ops,
1447836SJohn.Forte@Sun.COM 	(struct bus_ops *)NULL
1457836SJohn.Forte@Sun.COM };
1467836SJohn.Forte@Sun.COM 
1477836SJohn.Forte@Sun.COM static struct modldrv sdbc_ldrv = {
1487836SJohn.Forte@Sun.COM 	&mod_driverops,
1497836SJohn.Forte@Sun.COM 	"nws:Storage Cache:" ISS_VERSION_STR,
1507836SJohn.Forte@Sun.COM 	&sdbc_ops
1517836SJohn.Forte@Sun.COM };
1527836SJohn.Forte@Sun.COM 
1537836SJohn.Forte@Sun.COM static	struct modlinkage sdbc_modlinkage = {
1547836SJohn.Forte@Sun.COM 	MODREV_1,
1557836SJohn.Forte@Sun.COM 	&sdbc_ldrv,
1567836SJohn.Forte@Sun.COM 	NULL
1577836SJohn.Forte@Sun.COM };
1587836SJohn.Forte@Sun.COM 
1597836SJohn.Forte@Sun.COM /*
1607836SJohn.Forte@Sun.COM  * dynmem interface
1617836SJohn.Forte@Sun.COM  */
1627836SJohn.Forte@Sun.COM static int mutex_and_condvar_flag;
1637836SJohn.Forte@Sun.COM 
1647836SJohn.Forte@Sun.COM /*
1657836SJohn.Forte@Sun.COM  * Solaris module load time code
1667836SJohn.Forte@Sun.COM  */
1677836SJohn.Forte@Sun.COM int
_init(void)1687836SJohn.Forte@Sun.COM _init(void)
1697836SJohn.Forte@Sun.COM {
1707836SJohn.Forte@Sun.COM 
1717836SJohn.Forte@Sun.COM 	int err;
1727836SJohn.Forte@Sun.COM 
1737836SJohn.Forte@Sun.COM 	mutex_and_condvar_flag = 0;
1747836SJohn.Forte@Sun.COM 
1757836SJohn.Forte@Sun.COM #ifdef USES_SOFT_STATE
1767836SJohn.Forte@Sun.COM 	ddi_soft_state_init(&sdbc_statep, sizeof (struct sdbc_state),
1777836SJohn.Forte@Sun.COM 	    MAX_INSTANCES);
1787836SJohn.Forte@Sun.COM #endif /* USES_SOFT_STATE */
1797836SJohn.Forte@Sun.COM 
1807836SJohn.Forte@Sun.COM 	/*
1817836SJohn.Forte@Sun.COM 	 * It is "load" time, call the unixware equivalent.
1827836SJohn.Forte@Sun.COM 	 */
1837836SJohn.Forte@Sun.COM 	err = sdbcload();
1847836SJohn.Forte@Sun.COM 	if (!err)
1857836SJohn.Forte@Sun.COM 		err = mod_install(&sdbc_modlinkage);
1867836SJohn.Forte@Sun.COM 
1877836SJohn.Forte@Sun.COM 	if (err) {
1887836SJohn.Forte@Sun.COM 		(void) sdbcunload();
1897836SJohn.Forte@Sun.COM #ifdef USES_SOFT_STATE
1907836SJohn.Forte@Sun.COM 		ddi_soft_state_fini(&sdbc_statep);
1917836SJohn.Forte@Sun.COM #endif /* USES_SOFT_STATE */
1927836SJohn.Forte@Sun.COM 	}
1937836SJohn.Forte@Sun.COM 
1947836SJohn.Forte@Sun.COM 	if (!err) {
1957836SJohn.Forte@Sun.COM 		mutex_and_condvar_flag = 1;
1967836SJohn.Forte@Sun.COM 		mutex_init(&dynmem_processing_dm.thread_dm_lock, "dynmem",
1977836SJohn.Forte@Sun.COM 		    MUTEX_DRIVER, NULL);
1987836SJohn.Forte@Sun.COM 		cv_init(&dynmem_processing_dm.thread_dm_cv, "dynmem",
1997836SJohn.Forte@Sun.COM 		    CV_DRIVER, NULL);
2007836SJohn.Forte@Sun.COM 	}
2017836SJohn.Forte@Sun.COM 
2027836SJohn.Forte@Sun.COM 	return (err);
2037836SJohn.Forte@Sun.COM 
2047836SJohn.Forte@Sun.COM }
2057836SJohn.Forte@Sun.COM /*
2067836SJohn.Forte@Sun.COM  * Solaris module unload time code
2077836SJohn.Forte@Sun.COM  */
2087836SJohn.Forte@Sun.COM 
2097836SJohn.Forte@Sun.COM int
_fini(void)2107836SJohn.Forte@Sun.COM _fini(void)
2117836SJohn.Forte@Sun.COM {
2127836SJohn.Forte@Sun.COM 	int err;
2137836SJohn.Forte@Sun.COM 
2147836SJohn.Forte@Sun.COM 	if (_sd_cache_initialized) {
2157836SJohn.Forte@Sun.COM 		return (EBUSY);
2167836SJohn.Forte@Sun.COM 	} else if (_sd_ioset &&
2177836SJohn.Forte@Sun.COM 	    (_sd_ioset->set_nlive || _sd_ioset->set_nthread)) {
2189093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!sdbc:_fini() %d threads still "
2197836SJohn.Forte@Sun.COM 		    "active; %d threads in set\n", _sd_ioset->set_nlive,
2207836SJohn.Forte@Sun.COM 		    _sd_ioset->set_nthread);
2217836SJohn.Forte@Sun.COM 		return (EBUSY);
2227836SJohn.Forte@Sun.COM 	}
2237836SJohn.Forte@Sun.COM 	if ((err = mod_remove(&sdbc_modlinkage)) == 0) {
2247836SJohn.Forte@Sun.COM 		DTRACE_PROBE2(_sdbc_fini_mod_remove_succeeded,
2257836SJohn.Forte@Sun.COM 		    int, err,
2267836SJohn.Forte@Sun.COM 		    struct modlinkage *, &sdbc_modlinkage);
2277836SJohn.Forte@Sun.COM 		err = sdbcunload();
2287836SJohn.Forte@Sun.COM #ifdef USES_SOFT_STATE
2297836SJohn.Forte@Sun.COM 		ddi_soft_state_fini(&sdbc_statep);
2307836SJohn.Forte@Sun.COM #endif /* USES_SOFT_STATE */
2317836SJohn.Forte@Sun.COM 
2327836SJohn.Forte@Sun.COM 		if (mutex_and_condvar_flag) {
2337836SJohn.Forte@Sun.COM 			cv_destroy(&dynmem_processing_dm.thread_dm_cv);
2347836SJohn.Forte@Sun.COM 			mutex_destroy(&dynmem_processing_dm.thread_dm_lock);
2357836SJohn.Forte@Sun.COM 			mutex_and_condvar_flag = 0;
2367836SJohn.Forte@Sun.COM 		}
2377836SJohn.Forte@Sun.COM 	}
2387836SJohn.Forte@Sun.COM 
2397836SJohn.Forte@Sun.COM 	return (err);
2407836SJohn.Forte@Sun.COM }
2417836SJohn.Forte@Sun.COM 
2427836SJohn.Forte@Sun.COM /*
2437836SJohn.Forte@Sun.COM  * Solaris module info code
2447836SJohn.Forte@Sun.COM  */
2457836SJohn.Forte@Sun.COM int
_info(struct modinfo * modinfop)2467836SJohn.Forte@Sun.COM _info(struct modinfo *modinfop)
2477836SJohn.Forte@Sun.COM {
2487836SJohn.Forte@Sun.COM 	return (mod_info(&sdbc_modlinkage, modinfop));
2497836SJohn.Forte@Sun.COM }
2507836SJohn.Forte@Sun.COM 
2517836SJohn.Forte@Sun.COM /*ARGSUSED*/
2527836SJohn.Forte@Sun.COM static int
_sdbc_probe(dev_info_t * dip)2537836SJohn.Forte@Sun.COM _sdbc_probe(dev_info_t *dip)
2547836SJohn.Forte@Sun.COM {
2557836SJohn.Forte@Sun.COM 	return (DDI_PROBE_SUCCESS);
2567836SJohn.Forte@Sun.COM }
2577836SJohn.Forte@Sun.COM 
2587836SJohn.Forte@Sun.COM /*
2597836SJohn.Forte@Sun.COM  * Attach an instance of the device. This happens before an open
2607836SJohn.Forte@Sun.COM  * can succeed.
2617836SJohn.Forte@Sun.COM  */
2627836SJohn.Forte@Sun.COM static int
_sdbc_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2637836SJohn.Forte@Sun.COM _sdbc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2647836SJohn.Forte@Sun.COM {
2657836SJohn.Forte@Sun.COM 	_dm_process_vars_t local_dm_process_vars;
2667836SJohn.Forte@Sun.COM 	struct buf bp;
2677836SJohn.Forte@Sun.COM 
2687836SJohn.Forte@Sun.COM 	if (cmd != DDI_ATTACH)
2697836SJohn.Forte@Sun.COM 		return (DDI_FAILURE);
2707836SJohn.Forte@Sun.COM 
2717836SJohn.Forte@Sun.COM 	/*
2727836SJohn.Forte@Sun.COM 	 *  Get the threshold value for setting large writes in
2737836SJohn.Forte@Sun.COM 	 *  write through mode(when NVRAM is present)
2747836SJohn.Forte@Sun.COM 	 */
2757836SJohn.Forte@Sun.COM 
2767836SJohn.Forte@Sun.COM 	sdbc_wrthru_len =  ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2777836SJohn.Forte@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_wrthru_thresh", 64);
2787836SJohn.Forte@Sun.COM 
2797836SJohn.Forte@Sun.COM 	/* Get sdbc_max_fbas from sdbc.conf */
2807836SJohn.Forte@Sun.COM 	sdbc_max_fbas =  ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2817836SJohn.Forte@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_max_fbas",
2827836SJohn.Forte@Sun.COM 	    _SD_MAX_FBAS);
2837836SJohn.Forte@Sun.COM 
2847836SJohn.Forte@Sun.COM 	bp.b_bcount = (size_t)FBA_SIZE(sdbc_max_fbas);
2857836SJohn.Forte@Sun.COM 	minphys(&bp); /* clamps value to maxphys */
2867836SJohn.Forte@Sun.COM 
2877836SJohn.Forte@Sun.COM 	sdbc_max_fbas = FBA_NUM(bp.b_bcount);
2887836SJohn.Forte@Sun.COM 
2897836SJohn.Forte@Sun.COM 	if (sdbc_max_fbas > _SD_MAX_FBAS) {
2907836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
2919093SRamana.Srikanth@Sun.COM 		    "!_sdbc_attach: sdbc_max_fbas set to %d", _SD_MAX_FBAS);
2927836SJohn.Forte@Sun.COM 		sdbc_max_fbas = _SD_MAX_FBAS;
2937836SJohn.Forte@Sun.COM 	}
2947836SJohn.Forte@Sun.COM 
2957836SJohn.Forte@Sun.COM 	/*
2967836SJohn.Forte@Sun.COM 	 * -get the maximum list length for multipage dynmem
2977836SJohn.Forte@Sun.COM 	 * -time between aging
2987836SJohn.Forte@Sun.COM 	 * -number of agings before dealloc
2997836SJohn.Forte@Sun.COM 	 * -what to report D0=shutdown, D1=thread variables
3007836SJohn.Forte@Sun.COM 	 */
3017836SJohn.Forte@Sun.COM 	dynmem_processing_dm.max_dyn_list = MAX_DYN_LIST_DEFAULT;
3027836SJohn.Forte@Sun.COM 	dynmem_processing_dm.monitor_dynmem_process =
3037836SJohn.Forte@Sun.COM 	    MONITOR_DYNMEM_PROCESS_DEFAULT;
3047836SJohn.Forte@Sun.COM 	dynmem_processing_dm.cache_aging_ct1 = CACHE_AGING_CT_DEFAULT;
3057836SJohn.Forte@Sun.COM 	dynmem_processing_dm.cache_aging_ct2 = CACHE_AGING_CT_DEFAULT;
3067836SJohn.Forte@Sun.COM 	dynmem_processing_dm.cache_aging_ct3 = CACHE_AGING_CT_DEFAULT;
3077836SJohn.Forte@Sun.COM 	dynmem_processing_dm.cache_aging_sec1 = CACHE_AGING_SEC1_DEFAULT;
3087836SJohn.Forte@Sun.COM 	dynmem_processing_dm.cache_aging_sec2 = CACHE_AGING_SEC2_DEFAULT;
3097836SJohn.Forte@Sun.COM 	dynmem_processing_dm.cache_aging_sec3 = CACHE_AGING_SEC3_DEFAULT;
3107836SJohn.Forte@Sun.COM 	dynmem_processing_dm.cache_aging_pcnt1 = CACHE_AGING_PCNT1_DEFAULT;
3117836SJohn.Forte@Sun.COM 	dynmem_processing_dm.cache_aging_pcnt2 = CACHE_AGING_PCNT2_DEFAULT;
3127836SJohn.Forte@Sun.COM 	dynmem_processing_dm.max_holds_pcnt = MAX_HOLDS_PCNT_DEFAULT;
3137836SJohn.Forte@Sun.COM 	dynmem_processing_dm.process_directive = PROCESS_DIRECTIVE_DEFAULT;
3147836SJohn.Forte@Sun.COM 
3157836SJohn.Forte@Sun.COM 	local_dm_process_vars.max_dyn_list = ddi_prop_get_int(DDI_DEV_T_ANY,
3167836SJohn.Forte@Sun.COM 	    dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_max_dyn_list",
3177836SJohn.Forte@Sun.COM 	    MAX_DYN_LIST_DEFAULT);
3187836SJohn.Forte@Sun.COM 
3197836SJohn.Forte@Sun.COM 	local_dm_process_vars.monitor_dynmem_process =
3207836SJohn.Forte@Sun.COM 	    ddi_prop_get_int(DDI_DEV_T_ANY, dip,
3217836SJohn.Forte@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_monitor_dynmem",
3227836SJohn.Forte@Sun.COM 	    MONITOR_DYNMEM_PROCESS_DEFAULT);
3237836SJohn.Forte@Sun.COM 
3247836SJohn.Forte@Sun.COM 	local_dm_process_vars.cache_aging_ct1 = ddi_prop_get_int(DDI_DEV_T_ANY,
3257836SJohn.Forte@Sun.COM 	    dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_ct1",
3267836SJohn.Forte@Sun.COM 	    CACHE_AGING_CT_DEFAULT);
3277836SJohn.Forte@Sun.COM 
3287836SJohn.Forte@Sun.COM 	local_dm_process_vars.cache_aging_ct2 = ddi_prop_get_int(DDI_DEV_T_ANY,
3297836SJohn.Forte@Sun.COM 	    dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_ct2",
3307836SJohn.Forte@Sun.COM 	    CACHE_AGING_CT_DEFAULT);
3317836SJohn.Forte@Sun.COM 
3327836SJohn.Forte@Sun.COM 	local_dm_process_vars.cache_aging_ct3 = ddi_prop_get_int(DDI_DEV_T_ANY,
3337836SJohn.Forte@Sun.COM 	    dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_ct3",
3347836SJohn.Forte@Sun.COM 	    CACHE_AGING_CT_DEFAULT);
3357836SJohn.Forte@Sun.COM 
3367836SJohn.Forte@Sun.COM 	local_dm_process_vars.cache_aging_sec1 = ddi_prop_get_int(DDI_DEV_T_ANY,
3377836SJohn.Forte@Sun.COM 	    dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_sec1",
3387836SJohn.Forte@Sun.COM 	    CACHE_AGING_SEC1_DEFAULT);
3397836SJohn.Forte@Sun.COM 
3407836SJohn.Forte@Sun.COM 	local_dm_process_vars.cache_aging_sec2 = ddi_prop_get_int(DDI_DEV_T_ANY,
3417836SJohn.Forte@Sun.COM 	    dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_sec2",
3427836SJohn.Forte@Sun.COM 	    CACHE_AGING_SEC2_DEFAULT);
3437836SJohn.Forte@Sun.COM 
3447836SJohn.Forte@Sun.COM 	local_dm_process_vars.cache_aging_sec3 = ddi_prop_get_int(DDI_DEV_T_ANY,
3457836SJohn.Forte@Sun.COM 	    dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_sec3",
3467836SJohn.Forte@Sun.COM 	    CACHE_AGING_SEC3_DEFAULT);
3477836SJohn.Forte@Sun.COM 
3487836SJohn.Forte@Sun.COM 	local_dm_process_vars.cache_aging_pcnt1 =
3497836SJohn.Forte@Sun.COM 	    ddi_prop_get_int(DDI_DEV_T_ANY, dip,
3507836SJohn.Forte@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_pcnt1",
3517836SJohn.Forte@Sun.COM 	    CACHE_AGING_PCNT1_DEFAULT);
3527836SJohn.Forte@Sun.COM 
3537836SJohn.Forte@Sun.COM 	local_dm_process_vars.cache_aging_pcnt2 =
3547836SJohn.Forte@Sun.COM 	    ddi_prop_get_int(DDI_DEV_T_ANY, dip,
3557836SJohn.Forte@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_cache_aging_pcnt2",
3567836SJohn.Forte@Sun.COM 	    CACHE_AGING_PCNT2_DEFAULT);
3577836SJohn.Forte@Sun.COM 
3587836SJohn.Forte@Sun.COM 	local_dm_process_vars.process_directive =
3597836SJohn.Forte@Sun.COM 	    ddi_prop_get_int(DDI_DEV_T_ANY, dip,
3607836SJohn.Forte@Sun.COM 	    DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_process_directive",
3617836SJohn.Forte@Sun.COM 	    PROCESS_DIRECTIVE_DEFAULT);
3627836SJohn.Forte@Sun.COM 
3637836SJohn.Forte@Sun.COM 	local_dm_process_vars.max_holds_pcnt = ddi_prop_get_int(DDI_DEV_T_ANY,
3647836SJohn.Forte@Sun.COM 	    dip, DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "sdbc_max_holds_pcnt",
3657836SJohn.Forte@Sun.COM 	    MAX_HOLDS_PCNT_DEFAULT);
3667836SJohn.Forte@Sun.COM 
3677836SJohn.Forte@Sun.COM 	(void) sdbc_edit_xfer_process_vars_dm(&local_dm_process_vars);
3687836SJohn.Forte@Sun.COM 
3697836SJohn.Forte@Sun.COM #define	MINOR_NAME	"c,sdbc"		/* character device */
3707836SJohn.Forte@Sun.COM #define	MINOR_NUMBER	0
3717836SJohn.Forte@Sun.COM #ifdef MINOR_NAME
3727836SJohn.Forte@Sun.COM 	if (ddi_create_minor_node(dip, MINOR_NAME, S_IFCHR,
3739093SRamana.Srikanth@Sun.COM 	    MINOR_NUMBER, DDI_PSEUDO, 0) != DDI_SUCCESS) {
3749093SRamana.Srikanth@Sun.COM 		/* free anything we allocated here */
3759093SRamana.Srikanth@Sun.COM 		return (DDI_FAILURE);
3769093SRamana.Srikanth@Sun.COM 	}
3777836SJohn.Forte@Sun.COM #endif /* MINOR_NAME */
3787836SJohn.Forte@Sun.COM 
3797836SJohn.Forte@Sun.COM 	/* Announce presence of the device */
3807836SJohn.Forte@Sun.COM 	ddi_report_dev(dip);
3817836SJohn.Forte@Sun.COM 	dev_dip = dip;
3827836SJohn.Forte@Sun.COM 	/* mark the device as attached, opens may proceed */
3837836SJohn.Forte@Sun.COM 	_sdbc_attached = 1;
3847836SJohn.Forte@Sun.COM 
3857836SJohn.Forte@Sun.COM 	rw_init(&sdbc_queue_lock, NULL, RW_DRIVER, NULL);
3867836SJohn.Forte@Sun.COM 
3877836SJohn.Forte@Sun.COM 	return (DDI_SUCCESS);
3887836SJohn.Forte@Sun.COM }
3897836SJohn.Forte@Sun.COM 
3907836SJohn.Forte@Sun.COM /*ARGSUSED*/
3917836SJohn.Forte@Sun.COM static int
_sdbc_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)3927836SJohn.Forte@Sun.COM _sdbc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3937836SJohn.Forte@Sun.COM {
3947836SJohn.Forte@Sun.COM 	if (cmd == DDI_DETACH) {
3957836SJohn.Forte@Sun.COM 		/*
3967836SJohn.Forte@Sun.COM 		 * Check first if the cache is still in use
3977836SJohn.Forte@Sun.COM 		 * and if it is, prevent the detach.
3987836SJohn.Forte@Sun.COM 		 */
3997836SJohn.Forte@Sun.COM 		if (_sd_cache_initialized)
4007836SJohn.Forte@Sun.COM 			return (EBUSY);
4017836SJohn.Forte@Sun.COM 
4027836SJohn.Forte@Sun.COM 		_sdbc_attached = 0;
4037836SJohn.Forte@Sun.COM 
4047836SJohn.Forte@Sun.COM 		rw_destroy(&sdbc_queue_lock);
4057836SJohn.Forte@Sun.COM 		dev_dip = NULL;
4067836SJohn.Forte@Sun.COM 
4077836SJohn.Forte@Sun.COM 		return (DDI_SUCCESS);
4087836SJohn.Forte@Sun.COM 	} else
4097836SJohn.Forte@Sun.COM 		return (DDI_FAILURE);
4107836SJohn.Forte@Sun.COM }
4117836SJohn.Forte@Sun.COM 
4127836SJohn.Forte@Sun.COM /*ARGSUSED*/
4137836SJohn.Forte@Sun.COM static int
_sdbc_reset(dev_info_t * dip,ddi_reset_cmd_t cmd)4147836SJohn.Forte@Sun.COM _sdbc_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
4157836SJohn.Forte@Sun.COM {
4167836SJohn.Forte@Sun.COM 	return (DDI_SUCCESS);
4177836SJohn.Forte@Sun.COM }
4187836SJohn.Forte@Sun.COM 
4197836SJohn.Forte@Sun.COM /*ARGSUSED*/
4207836SJohn.Forte@Sun.COM static int
_sdbc_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)4217836SJohn.Forte@Sun.COM _sdbc_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
4227836SJohn.Forte@Sun.COM {
4237836SJohn.Forte@Sun.COM 	dev_t dev;
4247836SJohn.Forte@Sun.COM #ifdef USES_SOFT_STATE
4257836SJohn.Forte@Sun.COM 	struct sdbc_state *xsp;
4267836SJohn.Forte@Sun.COM 	int instance;
4277836SJohn.Forte@Sun.COM #endif /* USES_SOFT_STATE */
4287836SJohn.Forte@Sun.COM 	int rc;
4297836SJohn.Forte@Sun.COM 
4307836SJohn.Forte@Sun.COM 	switch (cmd) {
4317836SJohn.Forte@Sun.COM 		case DDI_INFO_DEVT2INSTANCE:
4327836SJohn.Forte@Sun.COM 			dev = (dev_t)arg;
4337836SJohn.Forte@Sun.COM 			/* The "instance" number is the minor number */
4347836SJohn.Forte@Sun.COM 			*result = (void *)(unsigned long)getminor(dev);
4357836SJohn.Forte@Sun.COM 			rc = DDI_SUCCESS;
4367836SJohn.Forte@Sun.COM 			break;
4377836SJohn.Forte@Sun.COM 
4387836SJohn.Forte@Sun.COM 		case DDI_INFO_DEVT2DEVINFO:
4397836SJohn.Forte@Sun.COM 			dev = (dev_t)arg;
4407836SJohn.Forte@Sun.COM #ifdef USES_SOFT_STATE
4417836SJohn.Forte@Sun.COM 			/* the instance number is the minor number */
4427836SJohn.Forte@Sun.COM 			instance = getminor(dev);
4437836SJohn.Forte@Sun.COM 			xsp = ddi_get_soft_state(sdbc_statep, instance);
4447836SJohn.Forte@Sun.COM 			if (xsp == NULL)
4457836SJohn.Forte@Sun.COM 				return (DDI_FAILURE);
4467836SJohn.Forte@Sun.COM 			*result = (void *) xsp->dip;
4477836SJohn.Forte@Sun.COM #else
4487836SJohn.Forte@Sun.COM 			*result = (void *) NULL;
4497836SJohn.Forte@Sun.COM #endif /* USES_SOFT_STATE */
4507836SJohn.Forte@Sun.COM 			rc = DDI_SUCCESS;
4517836SJohn.Forte@Sun.COM 			break;
4527836SJohn.Forte@Sun.COM 
4537836SJohn.Forte@Sun.COM 		default:
4547836SJohn.Forte@Sun.COM 			rc = DDI_FAILURE;
4557836SJohn.Forte@Sun.COM 			break;
4567836SJohn.Forte@Sun.COM 	}
4577836SJohn.Forte@Sun.COM 	return (rc);
4587836SJohn.Forte@Sun.COM }
4597836SJohn.Forte@Sun.COM 
4607836SJohn.Forte@Sun.COM /*ARGSUSED*/
4617836SJohn.Forte@Sun.COM int
_sdbc_print(dev_t dev,char * s)4627836SJohn.Forte@Sun.COM _sdbc_print(dev_t dev, char *s)
4637836SJohn.Forte@Sun.COM {
4649093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!sdbc(_sdbc_print) %s", s);
4657836SJohn.Forte@Sun.COM 	return (0);
4667836SJohn.Forte@Sun.COM }
4677836SJohn.Forte@Sun.COM #else
4687836SJohn.Forte@Sun.COM MOD_DRV_WRAPPER(sdbc, sdbcload, sdbcunload, NULL, "Storage Device Block Cache");
4697836SJohn.Forte@Sun.COM #endif /* sun */
4707836SJohn.Forte@Sun.COM 
4717836SJohn.Forte@Sun.COM static int sdbc_inited;
4727836SJohn.Forte@Sun.COM 
4737836SJohn.Forte@Sun.COM static int
sdbcinit(void)4747836SJohn.Forte@Sun.COM sdbcinit(void)
4757836SJohn.Forte@Sun.COM {
4767836SJohn.Forte@Sun.COM 	int rc;
4777836SJohn.Forte@Sun.COM 
4787836SJohn.Forte@Sun.COM 	sdbc_inited = 0;
4797836SJohn.Forte@Sun.COM 
4807836SJohn.Forte@Sun.COM 	(void) strncpy(sdbc_version, _VERSION_, sizeof (sdbc_version));
4817836SJohn.Forte@Sun.COM 
4827836SJohn.Forte@Sun.COM 	mutex_init(&_sd_cache_lock, NULL, MUTEX_DRIVER, NULL);
4837836SJohn.Forte@Sun.COM 	mutex_init(&_sdbc_config_lock, NULL, MUTEX_DRIVER, NULL);
4847836SJohn.Forte@Sun.COM 
4857836SJohn.Forte@Sun.COM #ifdef m88k
4867836SJohn.Forte@Sun.COM 	REGISTER_SVC(SD_DUAL_WRITE,	r_sd_ifs_write);
4877836SJohn.Forte@Sun.COM 	REGISTER_SVC(SD_DUAL_READ,	r_sd_ifs_read);
4887836SJohn.Forte@Sun.COM 	REGISTER_SVC(SD_SET_CD,		r_sd_set_cd);
4897836SJohn.Forte@Sun.COM 	REGISTER_SVC(SD_GETSIZE,	r_sd_getsize);
4907836SJohn.Forte@Sun.COM 	REGISTER_SVC(SD_DUAL_OPEN,	r_sd_ifs_open);
4917836SJohn.Forte@Sun.COM 	REGISTER_SVC(SD_REMOTE_FLUSH,	r_sd_remote_flush);
4927836SJohn.Forte@Sun.COM 	REGISTER_SVC(SD_SGREMOTE_FLUSH,	r_sd_sgremote_flush);
4937836SJohn.Forte@Sun.COM 	REGISTER_SVC(SD_DISK_IO,	r_sd_disk_io);
4947836SJohn.Forte@Sun.COM 	REGISTER_SVC(SD_GET_BMAP,	r_rem_get_bmap);
4957836SJohn.Forte@Sun.COM 
4967836SJohn.Forte@Sun.COM 	if ((rc = hpf_register_module("SDBC", _sd_hpf_stats)) != 0)
4977836SJohn.Forte@Sun.COM 		return (rc);
4987836SJohn.Forte@Sun.COM #endif
4997836SJohn.Forte@Sun.COM 	REGISTER_SVC(SD_ENABLE,		r_sd_ifs_cache_enable);
5007836SJohn.Forte@Sun.COM 	REGISTER_SVC(SD_DISABLE,	r_sd_ifs_cache_disable);
5017836SJohn.Forte@Sun.COM 	REGISTER_SVC(SD_CD_DISCARD,	r_cd_discard);
5027836SJohn.Forte@Sun.COM 
5037836SJohn.Forte@Sun.COM 	cv_init(&_sd_flush_cv, NULL, CV_DRIVER, NULL);
5047836SJohn.Forte@Sun.COM 
5057836SJohn.Forte@Sun.COM 	mutex_init(&_sd_block_lk, NULL, MUTEX_DRIVER, NULL);
5067836SJohn.Forte@Sun.COM 
5077836SJohn.Forte@Sun.COM 	sdbc_max_devs = nsc_max_devices();
5087836SJohn.Forte@Sun.COM 
5097836SJohn.Forte@Sun.COM 	/*
5107836SJohn.Forte@Sun.COM 	 * Initialize the bitmap array that would be useful in determining
5117836SJohn.Forte@Sun.COM 	 * if the mask is not fragmented, instead of determinig this
5127836SJohn.Forte@Sun.COM 	 * at run time. Also initialize a lookup array for each mask, with
5137836SJohn.Forte@Sun.COM 	 * the starting position, the length, and the mask subset
5147836SJohn.Forte@Sun.COM 	 */
5157836SJohn.Forte@Sun.COM 	_sd_init_contig_bmap();
5167836SJohn.Forte@Sun.COM 	_sd_init_lookup_map();
5177836SJohn.Forte@Sun.COM 
5187836SJohn.Forte@Sun.COM 	if ((rc = _sdbc_iobuf_load()) != 0)
5197836SJohn.Forte@Sun.COM 		return (rc);
5207836SJohn.Forte@Sun.COM 	if ((rc = _sdbc_handles_load()) != 0)
5217836SJohn.Forte@Sun.COM 		return (rc);
5227836SJohn.Forte@Sun.COM 	if ((rc = _sdbc_tr_load()) != 0)
5237836SJohn.Forte@Sun.COM 		return (rc);
5247836SJohn.Forte@Sun.COM 	if ((rc = _sdbc_ft_load()) != 0)
5257836SJohn.Forte@Sun.COM 		return (rc);
5267836SJohn.Forte@Sun.COM 	if ((rc = _sdbc_tdaemon_load()) != 0)
5277836SJohn.Forte@Sun.COM 		return (rc);
5287836SJohn.Forte@Sun.COM 	if ((rc = _sdbc_hash_load()) != 0)
5297836SJohn.Forte@Sun.COM 		return (rc);
5307836SJohn.Forte@Sun.COM #ifdef DEBUG
5317836SJohn.Forte@Sun.COM 	_sdbc_ioj_load();
5327836SJohn.Forte@Sun.COM #endif
5337836SJohn.Forte@Sun.COM 	sdbc_inited = 1;
5347836SJohn.Forte@Sun.COM 
5357836SJohn.Forte@Sun.COM 	return (0);
5367836SJohn.Forte@Sun.COM }
5377836SJohn.Forte@Sun.COM 
5387836SJohn.Forte@Sun.COM static int
sdbcunload(void)5397836SJohn.Forte@Sun.COM sdbcunload(void)
5407836SJohn.Forte@Sun.COM {
5417836SJohn.Forte@Sun.COM 	if (_sd_cache_initialized) {
5427836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
5439093SRamana.Srikanth@Sun.COM 		    "!sdbc(sdbcunload) cannot unload module - cache in use!");
5447836SJohn.Forte@Sun.COM 		return (EEXIST);
5457836SJohn.Forte@Sun.COM 	}
5467836SJohn.Forte@Sun.COM #ifdef m88k
5477836SJohn.Forte@Sun.COM 	UNREGISTER_SVC(SD_DUAL_WRITE);
5487836SJohn.Forte@Sun.COM 	UNREGISTER_SVC(SD_DUAL_READ);
5497836SJohn.Forte@Sun.COM 	UNREGISTER_SVC(SD_SET_CD);
5507836SJohn.Forte@Sun.COM 	UNREGISTER_SVC(SD_GETSIZE);
5517836SJohn.Forte@Sun.COM 	UNREGISTER_SVC(SD_DUAL_OPEN);
5527836SJohn.Forte@Sun.COM 	UNREGISTER_SVC(SD_REMOTE_FLUSH);
5537836SJohn.Forte@Sun.COM 	UNREGISTER_SVC(SD_SGREMOTE_FLUSH);
5547836SJohn.Forte@Sun.COM 	UNREGISTER_SVC(SD_DISK_IO);
5557836SJohn.Forte@Sun.COM 	UNREGISTER_SVC(SD_GET_BMAP);
5567836SJohn.Forte@Sun.COM 
5577836SJohn.Forte@Sun.COM 	(void) hpf_unregister_module("SDBC");
5587836SJohn.Forte@Sun.COM #endif
5597836SJohn.Forte@Sun.COM 	UNREGISTER_SVC(SD_ENABLE);
5607836SJohn.Forte@Sun.COM 	UNREGISTER_SVC(SD_DISABLE);
5617836SJohn.Forte@Sun.COM 	UNREGISTER_SVC(SD_CD_DISCARD);
5627836SJohn.Forte@Sun.COM 
5637836SJohn.Forte@Sun.COM 	cv_destroy(&_sd_flush_cv);
5647836SJohn.Forte@Sun.COM 	mutex_destroy(&_sd_block_lk);
5657836SJohn.Forte@Sun.COM 
5667836SJohn.Forte@Sun.COM 	_sdbc_hash_unload();
5677836SJohn.Forte@Sun.COM 	_sdbc_ft_unload();
5687836SJohn.Forte@Sun.COM 	_sdbc_tr_unload();
5697836SJohn.Forte@Sun.COM 	_sdbc_tdaemon_unload();
5707836SJohn.Forte@Sun.COM 	_sdbc_handles_unload();
5717836SJohn.Forte@Sun.COM 	_sdbc_iobuf_unload();
5727836SJohn.Forte@Sun.COM #ifdef DEBUG
5737836SJohn.Forte@Sun.COM 	_sdbc_ioj_unload();
5747836SJohn.Forte@Sun.COM #endif
5757836SJohn.Forte@Sun.COM 
5767836SJohn.Forte@Sun.COM 	mutex_destroy(&_sd_cache_lock);
5777836SJohn.Forte@Sun.COM 	mutex_destroy(&_sdbc_config_lock);
5787836SJohn.Forte@Sun.COM 
5797836SJohn.Forte@Sun.COM 	/*
5807836SJohn.Forte@Sun.COM 	 * Normally we would unregister memory at deconfig time.
5817836SJohn.Forte@Sun.COM 	 * However when chasing things like memory leaks it is
5827836SJohn.Forte@Sun.COM 	 * useful to defer until unload time.
5837836SJohn.Forte@Sun.COM 	 */
5847836SJohn.Forte@Sun.COM 	if (_sdbc_memtype_deconfigure_delayed)
5857836SJohn.Forte@Sun.COM 		_sdbc_memtype_deconfigure();
5867836SJohn.Forte@Sun.COM 
5877836SJohn.Forte@Sun.COM 	return (0);
5887836SJohn.Forte@Sun.COM }
5897836SJohn.Forte@Sun.COM 
5907836SJohn.Forte@Sun.COM 
5917836SJohn.Forte@Sun.COM static int
sdbcload(void)5927836SJohn.Forte@Sun.COM sdbcload(void)
5937836SJohn.Forte@Sun.COM {
5947836SJohn.Forte@Sun.COM 	int err;
5957836SJohn.Forte@Sun.COM 
5967836SJohn.Forte@Sun.COM 	if ((err = sdbcinit()) != 0) {
5977836SJohn.Forte@Sun.COM 		(void) sdbcunload();
5987836SJohn.Forte@Sun.COM 		return (err);
5997836SJohn.Forte@Sun.COM 	}
6007836SJohn.Forte@Sun.COM 	return (0);
6017836SJohn.Forte@Sun.COM }
6027836SJohn.Forte@Sun.COM 
6037836SJohn.Forte@Sun.COM 
6047836SJohn.Forte@Sun.COM /* ARGSUSED */
6057836SJohn.Forte@Sun.COM 
6067836SJohn.Forte@Sun.COM static int
sdbcopen(dev_t * devp,int flag,int otyp,cred_t * crp)6077836SJohn.Forte@Sun.COM sdbcopen(dev_t *devp, int flag, int otyp, cred_t *crp)
6087836SJohn.Forte@Sun.COM {
6097836SJohn.Forte@Sun.COM 	int nd = nsc_node_id();
6107836SJohn.Forte@Sun.COM 
6117836SJohn.Forte@Sun.COM 	/*
6127836SJohn.Forte@Sun.COM 	 * If we were statically linked in then returning an error out
6137836SJohn.Forte@Sun.COM 	 * of sdbcinit won't prevent someone from coming thru here.
6147836SJohn.Forte@Sun.COM 	 * We must prevent them from getting any further.
6157836SJohn.Forte@Sun.COM 	 */
6167836SJohn.Forte@Sun.COM 	if (!sdbc_inited)
6177836SJohn.Forte@Sun.COM 		return (EINVAL);
6187836SJohn.Forte@Sun.COM 
6197836SJohn.Forte@Sun.COM 	if (nd < nsc_min_nodeid) {
6207836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
6219093SRamana.Srikanth@Sun.COM 		    "!sdbc(sdbcopen) open failed, systemid (%d) must be >= %d",
6227836SJohn.Forte@Sun.COM 		    nd, nsc_min_nodeid);
6237836SJohn.Forte@Sun.COM 		return (EINVAL);
6247836SJohn.Forte@Sun.COM 	}
6257836SJohn.Forte@Sun.COM 	if (!_sdbc_attached)
6267836SJohn.Forte@Sun.COM 		return (ENXIO);
6277836SJohn.Forte@Sun.COM 
6287836SJohn.Forte@Sun.COM 	return (0);
6297836SJohn.Forte@Sun.COM }
6307836SJohn.Forte@Sun.COM 
6317836SJohn.Forte@Sun.COM 
6327836SJohn.Forte@Sun.COM /* ARGSUSED */
6337836SJohn.Forte@Sun.COM 
6347836SJohn.Forte@Sun.COM static int
sdbcclose(dev_t dev,int flag,int otyp,cred_t * crp)6357836SJohn.Forte@Sun.COM sdbcclose(dev_t dev, int flag, int otyp, cred_t *crp)
6367836SJohn.Forte@Sun.COM {
6377836SJohn.Forte@Sun.COM 	return (0);
6387836SJohn.Forte@Sun.COM }
6397836SJohn.Forte@Sun.COM 
6407836SJohn.Forte@Sun.COM #ifdef _MULTI_DATAMODEL
6417836SJohn.Forte@Sun.COM static int
convert_ioctl_args(int cmd,void * arg,int mode,_sdbc_ioctl_t * args)6427836SJohn.Forte@Sun.COM convert_ioctl_args(int cmd, void *arg, int mode, _sdbc_ioctl_t *args)
6437836SJohn.Forte@Sun.COM /*
6447836SJohn.Forte@Sun.COM  * convert_ioctl-args - Do a case by case conversion of a ILP32 ioctl
6457836SJohn.Forte@Sun.COM  * structure to an LP64 structure.
6467836SJohn.Forte@Sun.COM  * The main concern here is whether to sign-extend or not. The rule
6477836SJohn.Forte@Sun.COM  * is that pointers are not sign extended, the rest are obvious.
6487836SJohn.Forte@Sun.COM  * Since most everything is sign-extended the definition of
6497836SJohn.Forte@Sun.COM  * _sdbc_ioctl32_t uses signed fields.
6507836SJohn.Forte@Sun.COM  *
6517836SJohn.Forte@Sun.COM  */
6527836SJohn.Forte@Sun.COM {
6537836SJohn.Forte@Sun.COM 	_sdbc_ioctl32_t args32;
6547836SJohn.Forte@Sun.COM 
6557836SJohn.Forte@Sun.COM 	if (ddi_copyin(arg, &args32, sizeof (_sdbc_ioctl32_t), mode))
6567836SJohn.Forte@Sun.COM 		return (EFAULT);
6577836SJohn.Forte@Sun.COM 
6587836SJohn.Forte@Sun.COM 	bzero((void *) args, sizeof (_sdbc_ioctl_t));
6597836SJohn.Forte@Sun.COM 
6607836SJohn.Forte@Sun.COM 	switch (cmd) {
6617836SJohn.Forte@Sun.COM 
6627836SJohn.Forte@Sun.COM 	case SDBC_UNUSED_1:
6637836SJohn.Forte@Sun.COM 	case SDBC_UNUSED_2:
6647836SJohn.Forte@Sun.COM 	case SDBC_UNUSED_3:
6657836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
6667836SJohn.Forte@Sun.COM 		cmn_err(CE_WARN,
6679093SRamana.Srikanth@Sun.COM 		    "!sdbc(convert_ioctl_args) obsolete sdbc ioctl used");
6687836SJohn.Forte@Sun.COM 		return (EINVAL);
6697836SJohn.Forte@Sun.COM 
6707836SJohn.Forte@Sun.COM 	case SDBC_ADUMP:
6717836SJohn.Forte@Sun.COM 		args->arg0 = args32.arg0; /* cd */
6727836SJohn.Forte@Sun.COM 		args->arg1 = (uint32_t)args32.arg1; /* &tt */
6737836SJohn.Forte@Sun.COM 		args->arg2 = (uint32_t)args32.arg2; /* NULL (buf) */
6747836SJohn.Forte@Sun.COM 		args->arg3 = args32.arg3; /*  size of buf */
6757836SJohn.Forte@Sun.COM 		args->arg4 = args32.arg4; /* flag */
6767836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
6777836SJohn.Forte@Sun.COM 		break;
6787836SJohn.Forte@Sun.COM 
6797836SJohn.Forte@Sun.COM 	case SDBC_TEST_INIT:
6807836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* fname (char *) */
6817836SJohn.Forte@Sun.COM 		args->arg1 = args32.arg1; /* index */
6827836SJohn.Forte@Sun.COM 		args->arg2 = args32.arg2; /* len */
6837836SJohn.Forte@Sun.COM 		args->arg3 = args32.arg3; /* track size */
6847836SJohn.Forte@Sun.COM 		args->arg4 = args32.arg4; /* flag */
6857836SJohn.Forte@Sun.COM 		break;
6867836SJohn.Forte@Sun.COM 
6877836SJohn.Forte@Sun.COM 	case SDBC_TEST_START:
6887836SJohn.Forte@Sun.COM 		args->arg0 = args32.arg0; /* num */
6897836SJohn.Forte@Sun.COM 		args->arg1 = args32.arg1; /* type */
6907836SJohn.Forte@Sun.COM 		args->arg2 = args32.arg2; /* loops */
6917836SJohn.Forte@Sun.COM 		args->arg3 = args32.arg3; /* from */
6927836SJohn.Forte@Sun.COM 		args->arg4 = args32.arg4; /* seed */
6937836SJohn.Forte@Sun.COM 		break;
6947836SJohn.Forte@Sun.COM 
6957836SJohn.Forte@Sun.COM 	case SDBC_TEST_END:
6967836SJohn.Forte@Sun.COM 		break;
6977836SJohn.Forte@Sun.COM 
6987836SJohn.Forte@Sun.COM 	case SDBC_ENABLE:
6997836SJohn.Forte@Sun.COM 	case SDBC_VERSION:
7007836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* pointer */
7017836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7027836SJohn.Forte@Sun.COM 		break;
7037836SJohn.Forte@Sun.COM 
7047836SJohn.Forte@Sun.COM 	case SDBC_DISABLE:
7057836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7067836SJohn.Forte@Sun.COM 		break;
7077836SJohn.Forte@Sun.COM 
7087836SJohn.Forte@Sun.COM 	case SDBC_GET_CLUSTER_SIZE:
7097836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* (int * ) */
7107836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7117836SJohn.Forte@Sun.COM 		break;
7127836SJohn.Forte@Sun.COM 
7137836SJohn.Forte@Sun.COM 	/* get the gl_file data */
7147836SJohn.Forte@Sun.COM 	case SDBC_GET_CLUSTER_DATA:
7157836SJohn.Forte@Sun.COM 		/* pointer to array[2*cluster_size] */
7167836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0;
7177836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7187836SJohn.Forte@Sun.COM 		break;
7197836SJohn.Forte@Sun.COM 
7207836SJohn.Forte@Sun.COM 	/*  get the size of the global info pages for each board */
7217836SJohn.Forte@Sun.COM 	case SDBC_GET_GLMUL_SIZES:
7227836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* int[CACHE_MEM_PAD] * */
7237836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7247836SJohn.Forte@Sun.COM 		break;
7257836SJohn.Forte@Sun.COM 
7267836SJohn.Forte@Sun.COM 	/* get the global info about write blocks */
7277836SJohn.Forte@Sun.COM 	case SDBC_GET_GLMUL_INFO:
7287836SJohn.Forte@Sun.COM 		/* pointer to array[2*(sum of GLMUL_SIZES)] */
7297836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0;
7307836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7317836SJohn.Forte@Sun.COM 		break;
7327836SJohn.Forte@Sun.COM 
7337836SJohn.Forte@Sun.COM 	case SDBC_SET_CD_HINT:
7347836SJohn.Forte@Sun.COM 		args->arg0 = args32.arg0; /* cd */
7357836SJohn.Forte@Sun.COM 		args->arg1 = args32.arg1; /* hint */
7367836SJohn.Forte@Sun.COM 		args->arg2 = args32.arg2; /* flag */
7377836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7387836SJohn.Forte@Sun.COM 		break;
7397836SJohn.Forte@Sun.COM 
7407836SJohn.Forte@Sun.COM 	case SDBC_GET_CD_HINT:
7417836SJohn.Forte@Sun.COM 		args->arg0 = args32.arg0;
7427836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7437836SJohn.Forte@Sun.COM 		break;
7447836SJohn.Forte@Sun.COM 
7457836SJohn.Forte@Sun.COM 	case SDBC_SET_NODE_HINT:
7467836SJohn.Forte@Sun.COM 		args->arg0 = args32.arg0; /* hint */
7477836SJohn.Forte@Sun.COM 		args->arg1 = args32.arg1; /* flag */
7487836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7497836SJohn.Forte@Sun.COM 		break;
7507836SJohn.Forte@Sun.COM 
7517836SJohn.Forte@Sun.COM 	case SDBC_GET_NODE_HINT:
7527836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7537836SJohn.Forte@Sun.COM 		break;
7547836SJohn.Forte@Sun.COM 
7557836SJohn.Forte@Sun.COM 	case SDBC_STATS:
7567836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* (_sd_stats_t *) */
7577836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7587836SJohn.Forte@Sun.COM 		break;
7597836SJohn.Forte@Sun.COM 
7607836SJohn.Forte@Sun.COM 	case SDBC_ZAP_STATS:
7617836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7627836SJohn.Forte@Sun.COM 		break;
7637836SJohn.Forte@Sun.COM 
7647836SJohn.Forte@Sun.COM 	case SDBC_GET_CD_BLK:
7657836SJohn.Forte@Sun.COM 		args->arg0 = args32.arg0; /* cd */
7667836SJohn.Forte@Sun.COM 		args->arg1 = (uint32_t)args32.arg1; /* blk */
7677836SJohn.Forte@Sun.COM 		args->arg2 = (uint32_t)args32.arg2; /* (addr[5] *) */
7687836SJohn.Forte@Sun.COM 		break;
7697836SJohn.Forte@Sun.COM 
7707836SJohn.Forte@Sun.COM 	case SDBC_GET_CONFIG:
7717836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* (_sdbc_config_t *) */
7727836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7737836SJohn.Forte@Sun.COM 		break;
7747836SJohn.Forte@Sun.COM 
7757836SJohn.Forte@Sun.COM 	case SDBC_SET_CONFIG:
7767836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* (_sdbc_config_t *) */
7777836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7787836SJohn.Forte@Sun.COM 		break;
7797836SJohn.Forte@Sun.COM 
7807836SJohn.Forte@Sun.COM 	case SDBC_MAXFILES:
7817836SJohn.Forte@Sun.COM 		args->arg0 = (uint32_t)args32.arg0; /* (int * ) */
7827836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7837836SJohn.Forte@Sun.COM 		break;
7847836SJohn.Forte@Sun.COM 
7857836SJohn.Forte@Sun.COM #ifdef DEBUG
7867836SJohn.Forte@Sun.COM 	/* toggle flusher flag for testing */
7877836SJohn.Forte@Sun.COM 	case SDBC_TOGGLE_FLUSH:
7887836SJohn.Forte@Sun.COM 		args->sdbc_ustatus = (spcs_s_info_t)args32.sdbc_ustatus;
7897836SJohn.Forte@Sun.COM 		break;
7907836SJohn.Forte@Sun.COM 
7917836SJohn.Forte@Sun.COM 	case SDBC_INJ_IOERR: /* cd, errnum */
7927836SJohn.Forte@Sun.COM 		args->arg0 = args32.arg0; /* cd */
7937836SJohn.Forte@Sun.COM 		args->arg1 = args32.arg1; /* i/o error number */
7947836SJohn.Forte@Sun.COM 		args->arg2 = args32.arg2; /* countdown to issuing error */
7957836SJohn.Forte@Sun.COM 		break;
7967836SJohn.Forte@Sun.COM 
7977836SJohn.Forte@Sun.COM 	/* clear injected i/o errors */
7987836SJohn.Forte@Sun.COM 	case SDBC_CLR_IOERR: /* cd */
7997836SJohn.Forte@Sun.COM 		args->arg0 = args32.arg0; /* cd */
8007836SJohn.Forte@Sun.COM 		break;
8017836SJohn.Forte@Sun.COM #endif /* DEBUG */
8027836SJohn.Forte@Sun.COM 	default:
8037836SJohn.Forte@Sun.COM 		return (EINVAL);
8047836SJohn.Forte@Sun.COM 	}
8057836SJohn.Forte@Sun.COM 
8067836SJohn.Forte@Sun.COM 	return (0);
8077836SJohn.Forte@Sun.COM }
8087836SJohn.Forte@Sun.COM #endif /* _MULTI_DATAMODEL */
8097836SJohn.Forte@Sun.COM 
8107836SJohn.Forte@Sun.COM static int
sdbc_get_cd_blk(_sdbc_ioctl_t * args,int mode)8117836SJohn.Forte@Sun.COM sdbc_get_cd_blk(_sdbc_ioctl_t *args, int mode)
8127836SJohn.Forte@Sun.COM {
8137836SJohn.Forte@Sun.COM 
8147836SJohn.Forte@Sun.COM 	_sd_cctl_t *cc_ent;
8157836SJohn.Forte@Sun.COM 	caddr_t data;
8167836SJohn.Forte@Sun.COM 	char *taddr;
8177836SJohn.Forte@Sun.COM 	intptr_t addr[5];
8187836SJohn.Forte@Sun.COM #ifdef _MULTI_DATAMODEL
8197836SJohn.Forte@Sun.COM 	uint32_t addr_32[5];
8207836SJohn.Forte@Sun.COM #endif /* _MULTI_DATAMODEL */
8217836SJohn.Forte@Sun.COM 	char *lookup_file = NULL;
8227836SJohn.Forte@Sun.COM 	int rc;
8237836SJohn.Forte@Sun.COM 	sdbc_info_t info;
8247836SJohn.Forte@Sun.COM 	nsc_off_t fba_pos;	/* disk block number */
8257836SJohn.Forte@Sun.COM 
8267836SJohn.Forte@Sun.COM 	if (_sd_cache_initialized == 0) {
8277836SJohn.Forte@Sun.COM 		return (EINVAL);
8287836SJohn.Forte@Sun.COM 	}
8297836SJohn.Forte@Sun.COM 
8307836SJohn.Forte@Sun.COM 	/* copyin the block number */
8317836SJohn.Forte@Sun.COM 	if (ddi_copyin((void *)args->arg1, &fba_pos, sizeof (nsc_off_t),
8327836SJohn.Forte@Sun.COM 	    mode)) {
8337836SJohn.Forte@Sun.COM 		return (EFAULT);
8347836SJohn.Forte@Sun.COM 	}
8357836SJohn.Forte@Sun.COM 
8367836SJohn.Forte@Sun.COM #ifdef _MULTI_DATAMODEL
8377836SJohn.Forte@Sun.COM 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
8387836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)args->arg2, addr_32, sizeof (addr_32),
8397836SJohn.Forte@Sun.COM 		    mode)) {
8407836SJohn.Forte@Sun.COM 			return (EFAULT);
8417836SJohn.Forte@Sun.COM 		}
8427836SJohn.Forte@Sun.COM 		addr[0] = addr_32[0]; /* (sdbc_info_t *) */
8437836SJohn.Forte@Sun.COM 		addr[1] = addr_32[1]; /* (char *) cdata */
8447836SJohn.Forte@Sun.COM 		addr[2] = addr_32[2]; /* ( int * ) cblk_size */
8457836SJohn.Forte@Sun.COM 		addr[3] = addr_32[3]; /* ( char * ) filename */
8467836SJohn.Forte@Sun.COM 		addr[4] = addr_32[4]; /* ( char *) wdata */
8477836SJohn.Forte@Sun.COM 	} else {
8487836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)args->arg2, addr, sizeof (addr), mode)) {
8497836SJohn.Forte@Sun.COM 			return (EFAULT);
8507836SJohn.Forte@Sun.COM 		}
8517836SJohn.Forte@Sun.COM 	}
8527836SJohn.Forte@Sun.COM #else /* _MULTI_DATAMODEL */
8537836SJohn.Forte@Sun.COM 	if (ddi_copyin((void *)args->arg2, addr, sizeof (addr), mode)) {
8547836SJohn.Forte@Sun.COM 		return (EFAULT);
8557836SJohn.Forte@Sun.COM 	}
8567836SJohn.Forte@Sun.COM #endif /* _MULTI_DATAMODEL */
8577836SJohn.Forte@Sun.COM 
8587836SJohn.Forte@Sun.COM 	(void) copyout(&CACHE_BLOCK_SIZE, (void *)addr[2], sizeof (int));
8597836SJohn.Forte@Sun.COM 
8607836SJohn.Forte@Sun.COM 	if (_sd_get_cd_blk((int)args->arg0, FBA_TO_BLK_NUM(fba_pos),
8617836SJohn.Forte@Sun.COM 	    &cc_ent, &data, &lookup_file)) {
8627836SJohn.Forte@Sun.COM 		if (lookup_file != NULL)
8637836SJohn.Forte@Sun.COM 			(void) copyout(lookup_file, (void *)addr[3],
8647836SJohn.Forte@Sun.COM 			    NSC_MAXPATH);
8657836SJohn.Forte@Sun.COM 		return (ENOENT);
8667836SJohn.Forte@Sun.COM 	}
8677836SJohn.Forte@Sun.COM 	rc = 0;
8687836SJohn.Forte@Sun.COM 	taddr = NULL;
8697836SJohn.Forte@Sun.COM 
8707836SJohn.Forte@Sun.COM 	info.ci_write = cc_ent->cc_write ? 1 : 0;
8717836SJohn.Forte@Sun.COM 	info.ci_dirty = cc_ent->cc_dirty;
8727836SJohn.Forte@Sun.COM 	info.ci_valid = cc_ent->cc_valid;
8737836SJohn.Forte@Sun.COM 	info.ci_cd = CENTRY_CD(cc_ent);
8747836SJohn.Forte@Sun.COM 	info.ci_dblk = BLK_TO_FBA_NUM(CENTRY_BLK(cc_ent));
8757836SJohn.Forte@Sun.COM 	(void) copyout(lookup_file, (void *)addr[3], NSC_MAXPATH);
8767836SJohn.Forte@Sun.COM 	(void) copyout(&info, (void *)addr[0], sizeof (sdbc_info_t));
8777836SJohn.Forte@Sun.COM 
8787836SJohn.Forte@Sun.COM 	(void) copyout(data, (void *)addr[1], CACHE_BLOCK_SIZE);
8797836SJohn.Forte@Sun.COM 
8807836SJohn.Forte@Sun.COM 	/* get the write data if any */
8817836SJohn.Forte@Sun.COM 	if (cc_ent->cc_write) {
8827836SJohn.Forte@Sun.COM 
8837836SJohn.Forte@Sun.COM 		if (sdbc_safestore) {
8847836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
8859093SRamana.Srikanth@Sun.COM 			    "!sdbc(sdbc_get_cd_blk) cc_write 0x%p sc-res 0x%p",
8867836SJohn.Forte@Sun.COM 			    (void *)cc_ent->cc_write,
8877836SJohn.Forte@Sun.COM 			    (void *)cc_ent->cc_write->sc_res);
8887836SJohn.Forte@Sun.COM 
8897836SJohn.Forte@Sun.COM 			if ((taddr = kmem_alloc(CACHE_BLOCK_SIZE,
8907836SJohn.Forte@Sun.COM 			    KM_NOSLEEP)) == NULL) {
8917836SJohn.Forte@Sun.COM 				cmn_err(CE_WARN,
8929093SRamana.Srikanth@Sun.COM 				    "!sdbc(sdbc_get_cd_blk) kmem_alloc failed."
8937836SJohn.Forte@Sun.COM 				    " cannot get write data");
8947836SJohn.Forte@Sun.COM 				info.ci_write = NULL;
8957836SJohn.Forte@Sun.COM 				rc = EFAULT;
8967836SJohn.Forte@Sun.COM 			} else if (SSOP_READ_CBLOCK(sdbc_safestore,
8977836SJohn.Forte@Sun.COM 			    cc_ent->cc_write->sc_res, taddr,
8987836SJohn.Forte@Sun.COM 			    CACHE_BLOCK_SIZE, 0) == SS_ERR) {
8997836SJohn.Forte@Sun.COM 
9007836SJohn.Forte@Sun.COM 				cmn_err(CE_WARN, "sdbc(sdbc_get_cd_blk) "
9019093SRamana.Srikanth@Sun.COM 				    "!safestore read failed");
9027836SJohn.Forte@Sun.COM 				rc = EFAULT;
9037836SJohn.Forte@Sun.COM 
9047836SJohn.Forte@Sun.COM 			} else if (copyout(taddr, (void *)addr[4],
9057836SJohn.Forte@Sun.COM 			    CACHE_BLOCK_SIZE)) {
9067836SJohn.Forte@Sun.COM 				cmn_err(CE_WARN,
9079093SRamana.Srikanth@Sun.COM 				    "!sdbc(sdbc_get_cd_blk) copyout failed."
9087836SJohn.Forte@Sun.COM 				    " cannot get write data");
9097836SJohn.Forte@Sun.COM 				rc = EFAULT;
9107836SJohn.Forte@Sun.COM 			}
9117836SJohn.Forte@Sun.COM 		}
9127836SJohn.Forte@Sun.COM 
9137836SJohn.Forte@Sun.COM 	}
9147836SJohn.Forte@Sun.COM 
9157836SJohn.Forte@Sun.COM 	if (taddr)
9167836SJohn.Forte@Sun.COM 		kmem_free(taddr, CACHE_BLOCK_SIZE);
9177836SJohn.Forte@Sun.COM 
9187836SJohn.Forte@Sun.COM 	return (rc);
9197836SJohn.Forte@Sun.COM }
9207836SJohn.Forte@Sun.COM 
9217836SJohn.Forte@Sun.COM /* ARGSUSED */
9227836SJohn.Forte@Sun.COM static int
sdbcioctl(dev_t dev,int cmd,void * arg,int mode,cred_t * crp,int * rvp)9237836SJohn.Forte@Sun.COM sdbcioctl(dev_t dev, int cmd, void *arg, int mode, cred_t *crp, int *rvp)
9247836SJohn.Forte@Sun.COM {
9257836SJohn.Forte@Sun.COM 	int rc = 0;
9267836SJohn.Forte@Sun.COM 	_sdbc_ioctl_t args;
9277836SJohn.Forte@Sun.COM 	int convert_32 = 0;
9287836SJohn.Forte@Sun.COM 	spcs_s_info_t kstatus;
9297836SJohn.Forte@Sun.COM 
9307836SJohn.Forte@Sun.COM 	*rvp = 0;
9317836SJohn.Forte@Sun.COM 
9327836SJohn.Forte@Sun.COM #ifdef _MULTI_DATAMODEL
9337836SJohn.Forte@Sun.COM 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
9347836SJohn.Forte@Sun.COM 		int rc;
9357836SJohn.Forte@Sun.COM 		convert_32 = 1;
9367836SJohn.Forte@Sun.COM 		if ((rc = convert_ioctl_args(cmd, arg, mode, &args)) != 0)
9377836SJohn.Forte@Sun.COM 			return (rc);
9387836SJohn.Forte@Sun.COM 	} else {
9397836SJohn.Forte@Sun.COM 		if (ddi_copyin(arg, &args, sizeof (_sdbc_ioctl_t), mode)) {
9407836SJohn.Forte@Sun.COM 			return (EFAULT);
9417836SJohn.Forte@Sun.COM 		}
9427836SJohn.Forte@Sun.COM 	}
9437836SJohn.Forte@Sun.COM #else /* _MULTI_DATAMODEL */
9447836SJohn.Forte@Sun.COM 	if (ddi_copyin(arg, &args, sizeof (_sdbc_ioctl_t), mode)) {
9457836SJohn.Forte@Sun.COM 		return (EFAULT);
9467836SJohn.Forte@Sun.COM 	}
9477836SJohn.Forte@Sun.COM #endif /* _MULTI_DATAMODEL */
9487836SJohn.Forte@Sun.COM 
9497836SJohn.Forte@Sun.COM 	kstatus = spcs_s_kcreate();
9507836SJohn.Forte@Sun.COM 	if (!kstatus)
9517836SJohn.Forte@Sun.COM 		return (ENOMEM);
9527836SJohn.Forte@Sun.COM 
9537836SJohn.Forte@Sun.COM 	switch (cmd) {
9547836SJohn.Forte@Sun.COM 
9557836SJohn.Forte@Sun.COM 	case SDBC_UNUSED_1:
9567836SJohn.Forte@Sun.COM 	case SDBC_UNUSED_2:
9577836SJohn.Forte@Sun.COM 	case SDBC_UNUSED_3:
9587836SJohn.Forte@Sun.COM 
9597836SJohn.Forte@Sun.COM 		return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
9607836SJohn.Forte@Sun.COM 		    SDBC_EOBSOLETE));
9617836SJohn.Forte@Sun.COM 
9627836SJohn.Forte@Sun.COM 	case SDBC_ADUMP:
9637836SJohn.Forte@Sun.COM 		rc = _sd_adump(&args, rvp);
9647836SJohn.Forte@Sun.COM 		break;
9657836SJohn.Forte@Sun.COM 
9667836SJohn.Forte@Sun.COM 	case SDBC_TEST_INIT:
9677836SJohn.Forte@Sun.COM 		rc = _sd_test_init(&args);
9687836SJohn.Forte@Sun.COM 		break;
9697836SJohn.Forte@Sun.COM 
9707836SJohn.Forte@Sun.COM 	case SDBC_TEST_START:
9717836SJohn.Forte@Sun.COM 		rc = _sd_test_start(&args, rvp);
9727836SJohn.Forte@Sun.COM 		break;
9737836SJohn.Forte@Sun.COM 
9747836SJohn.Forte@Sun.COM 	case SDBC_TEST_END:
9757836SJohn.Forte@Sun.COM 		rc = _sd_test_end();
9767836SJohn.Forte@Sun.COM 		break;
9777836SJohn.Forte@Sun.COM 
9787836SJohn.Forte@Sun.COM 	case SDBC_ENABLE:
9797836SJohn.Forte@Sun.COM 		mutex_enter(&_sdbc_config_lock);
9807836SJohn.Forte@Sun.COM 		rc = _sdbc_configure((_sd_cache_param_t *)args.arg0,
9819093SRamana.Srikanth@Sun.COM 		    NULL, kstatus);
9827836SJohn.Forte@Sun.COM 		if (rc && rc != EALREADY && rc != SDBC_ENONETMEM) {
9837836SJohn.Forte@Sun.COM 			(void) _sdbc_deconfigure(kstatus);
9847836SJohn.Forte@Sun.COM 			mutex_exit(&_sdbc_config_lock);
9859093SRamana.Srikanth@Sun.COM 			return (spcs_s_ocopyoutf
9869093SRamana.Srikanth@Sun.COM 			    (&kstatus, args.sdbc_ustatus, rc));
9877836SJohn.Forte@Sun.COM 		}
9887836SJohn.Forte@Sun.COM 		mutex_exit(&_sdbc_config_lock);
9897836SJohn.Forte@Sun.COM 		return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, rc));
9907836SJohn.Forte@Sun.COM 
9917836SJohn.Forte@Sun.COM 	case SDBC_DISABLE:
9927836SJohn.Forte@Sun.COM 		mutex_enter(&_sdbc_config_lock);
9937836SJohn.Forte@Sun.COM 		if (_sd_cache_initialized == 0) {
9947836SJohn.Forte@Sun.COM 
9957836SJohn.Forte@Sun.COM 			mutex_exit(&_sdbc_config_lock);
9967836SJohn.Forte@Sun.COM 			return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
9977836SJohn.Forte@Sun.COM 			    SDBC_EDISABLE));
9987836SJohn.Forte@Sun.COM 		}
9997836SJohn.Forte@Sun.COM 		rc = _sdbc_deconfigure(kstatus);
10007836SJohn.Forte@Sun.COM 		mutex_exit(&_sdbc_config_lock);
10017836SJohn.Forte@Sun.COM 		return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, rc));
10027836SJohn.Forte@Sun.COM 
10037836SJohn.Forte@Sun.COM 	case SDBC_GET_CLUSTER_SIZE:
10047836SJohn.Forte@Sun.COM 		if (_sd_cache_initialized == 0) {
10057836SJohn.Forte@Sun.COM 
10067836SJohn.Forte@Sun.COM 			return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
10077836SJohn.Forte@Sun.COM 			    SDBC_ECLUSTER_SIZE));
10087836SJohn.Forte@Sun.COM 		}
10097836SJohn.Forte@Sun.COM 
10107836SJohn.Forte@Sun.COM 		rc = sd_get_file_info_size((void *)args.arg0);
10117836SJohn.Forte@Sun.COM 		break;
10127836SJohn.Forte@Sun.COM 
10137836SJohn.Forte@Sun.COM 	/* get the gl_file data */
10147836SJohn.Forte@Sun.COM 	case SDBC_GET_CLUSTER_DATA:
10157836SJohn.Forte@Sun.COM 		if (_sd_cache_initialized == 0) {
10167836SJohn.Forte@Sun.COM 
10177836SJohn.Forte@Sun.COM 			return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
10187836SJohn.Forte@Sun.COM 			    SDBC_ECLUSTER_DATA));
10197836SJohn.Forte@Sun.COM 		}
10207836SJohn.Forte@Sun.COM 		rc = sd_get_file_info_data((void *)args.arg0);
10217836SJohn.Forte@Sun.COM 		break;
10227836SJohn.Forte@Sun.COM 
10237836SJohn.Forte@Sun.COM 	/*  get the size of the global info pages for each board */
10247836SJohn.Forte@Sun.COM 	case SDBC_GET_GLMUL_SIZES:
10257836SJohn.Forte@Sun.COM 		if (_sd_cache_initialized == 0) {
10267836SJohn.Forte@Sun.COM 			return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
10277836SJohn.Forte@Sun.COM 			    SDBC_EGLMUL_SIZE));
10287836SJohn.Forte@Sun.COM 		}
10297836SJohn.Forte@Sun.COM 		rc = sd_get_glmul_sizes((void *)args.arg0);
10307836SJohn.Forte@Sun.COM 		break;
10317836SJohn.Forte@Sun.COM 
10327836SJohn.Forte@Sun.COM 	/* get the global info about write blocks */
10337836SJohn.Forte@Sun.COM 	case SDBC_GET_GLMUL_INFO:
10347836SJohn.Forte@Sun.COM 		if (_sd_cache_initialized == 0) {
10357836SJohn.Forte@Sun.COM 
10367836SJohn.Forte@Sun.COM 			return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
10377836SJohn.Forte@Sun.COM 			    SDBC_EGLMUL_INFO));
10387836SJohn.Forte@Sun.COM 
10397836SJohn.Forte@Sun.COM 		}
10407836SJohn.Forte@Sun.COM 		rc = sd_get_glmul_info((void *)args.arg0);
10417836SJohn.Forte@Sun.COM 		break;
10427836SJohn.Forte@Sun.COM 
10437836SJohn.Forte@Sun.COM 	case SDBC_SET_CD_HINT:
10447836SJohn.Forte@Sun.COM 		if (_sd_cache_initialized == 0)
10457836SJohn.Forte@Sun.COM 			return (spcs_s_ocopyoutf(&kstatus,
10467836SJohn.Forte@Sun.COM 			    args.sdbc_ustatus, EINVAL));
10477836SJohn.Forte@Sun.COM 		rc = ((args.arg2) ?
10487836SJohn.Forte@Sun.COM 		    _sd_set_hint((int)args.arg0, (uint_t)args.arg1) :
10497836SJohn.Forte@Sun.COM 		    _sd_clear_hint((int)args.arg0, (uint_t)args.arg1));
10507836SJohn.Forte@Sun.COM 		return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, rc));
10517836SJohn.Forte@Sun.COM 
10527836SJohn.Forte@Sun.COM 	case SDBC_GET_CD_HINT:
10537836SJohn.Forte@Sun.COM 		{
10547836SJohn.Forte@Sun.COM 			uint_t hint;
10557836SJohn.Forte@Sun.COM 
10567836SJohn.Forte@Sun.COM 			if (_sd_cache_initialized == 0)
10577836SJohn.Forte@Sun.COM 				return (spcs_s_ocopyoutf(&kstatus,
10587836SJohn.Forte@Sun.COM 				    args.sdbc_ustatus, EINVAL));
10597836SJohn.Forte@Sun.COM 			if ((rc = _sd_get_cd_hint((int)args.arg0, &hint)) == 0)
10607836SJohn.Forte@Sun.COM 				*rvp = hint;
10617836SJohn.Forte@Sun.COM 			return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
10627836SJohn.Forte@Sun.COM 			    rc));
10637836SJohn.Forte@Sun.COM 		}
10647836SJohn.Forte@Sun.COM 
10657836SJohn.Forte@Sun.COM 	case SDBC_SET_NODE_HINT:
10667836SJohn.Forte@Sun.COM 		rc = ((args.arg1) ? _sd_set_node_hint((uint_t)args.arg0) :
10677836SJohn.Forte@Sun.COM 		    _sd_clear_node_hint((uint_t)args.arg0));
10687836SJohn.Forte@Sun.COM 		if (rc)
10697836SJohn.Forte@Sun.COM 			return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
10707836SJohn.Forte@Sun.COM 			    rc));
10717836SJohn.Forte@Sun.COM 		/* FALLTHRU */
10727836SJohn.Forte@Sun.COM 	case SDBC_GET_NODE_HINT:
10737836SJohn.Forte@Sun.COM 		{
10747836SJohn.Forte@Sun.COM 			uint_t hint;
10757836SJohn.Forte@Sun.COM 			if ((rc = _sd_get_node_hint(&hint)) == 0)
10767836SJohn.Forte@Sun.COM 				*rvp = hint;
10777836SJohn.Forte@Sun.COM 			return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
10787836SJohn.Forte@Sun.COM 			    rc));
10797836SJohn.Forte@Sun.COM 		}
10807836SJohn.Forte@Sun.COM 
10817836SJohn.Forte@Sun.COM 	case SDBC_STATS:
10827836SJohn.Forte@Sun.COM 		rc = _sd_get_stats((void *)args.arg0, convert_32);
10837836SJohn.Forte@Sun.COM 		return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, rc));
10847836SJohn.Forte@Sun.COM 
10857836SJohn.Forte@Sun.COM 	case SDBC_ZAP_STATS:
10867836SJohn.Forte@Sun.COM 		_sd_zap_stats();
10877836SJohn.Forte@Sun.COM 		return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, 0));
10887836SJohn.Forte@Sun.COM 
10897836SJohn.Forte@Sun.COM 	case SDBC_GET_CD_BLK:
10907836SJohn.Forte@Sun.COM 		if (_sd_cache_initialized == 0)
10917836SJohn.Forte@Sun.COM 			return (spcs_s_ocopyoutf(&kstatus,
10927836SJohn.Forte@Sun.COM 			    args.sdbc_ustatus, EINVAL));
10937836SJohn.Forte@Sun.COM 		rc = sdbc_get_cd_blk(&args, mode);
10947836SJohn.Forte@Sun.COM 		break;
10957836SJohn.Forte@Sun.COM 
10967836SJohn.Forte@Sun.COM 	case SDBC_GET_CONFIG:
10977836SJohn.Forte@Sun.COM 		{
10987836SJohn.Forte@Sun.COM 		_sdbc_config_t sdbc_config_info;
10997836SJohn.Forte@Sun.COM 
11007836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)args.arg0,
11017836SJohn.Forte@Sun.COM 		    &sdbc_config_info,
11027836SJohn.Forte@Sun.COM 		    sizeof (_sdbc_config_t),
11037836SJohn.Forte@Sun.COM 		    mode)) {
11047836SJohn.Forte@Sun.COM 			spcs_s_kfree(kstatus);
11057836SJohn.Forte@Sun.COM 			return (EFAULT);
11067836SJohn.Forte@Sun.COM 		}
11077836SJohn.Forte@Sun.COM 		rc = _sdbc_get_config(&sdbc_config_info);
11087836SJohn.Forte@Sun.COM 		(void) ddi_copyout(&sdbc_config_info,
11097836SJohn.Forte@Sun.COM 		    (void *)args.arg0,
11107836SJohn.Forte@Sun.COM 		    sizeof (_sdbc_config_t),
11117836SJohn.Forte@Sun.COM 		    mode);
11127836SJohn.Forte@Sun.COM 		return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, rc));
11137836SJohn.Forte@Sun.COM 		}
11147836SJohn.Forte@Sun.COM 
11157836SJohn.Forte@Sun.COM 	case SDBC_SET_CONFIG:
11167836SJohn.Forte@Sun.COM 	{
11177836SJohn.Forte@Sun.COM 		_sdbc_config_t mgmt_config_info;
11187836SJohn.Forte@Sun.COM 
11197836SJohn.Forte@Sun.COM 		if (ddi_copyin((void *)args.arg0,
11207836SJohn.Forte@Sun.COM 		    &mgmt_config_info,
11217836SJohn.Forte@Sun.COM 		    sizeof (_sdbc_config_t),
11227836SJohn.Forte@Sun.COM 		    mode)) {
11237836SJohn.Forte@Sun.COM 			spcs_s_kfree(kstatus);
11247836SJohn.Forte@Sun.COM 			return (EFAULT);
11257836SJohn.Forte@Sun.COM 		}
11267836SJohn.Forte@Sun.COM 
11277836SJohn.Forte@Sun.COM 		rc = _sdbc_configure(NULL, &mgmt_config_info, kstatus);
11287836SJohn.Forte@Sun.COM 		if (rc && rc != EALREADY) {
11297836SJohn.Forte@Sun.COM 			(void) _sdbc_deconfigure(kstatus);
11309093SRamana.Srikanth@Sun.COM 			return (spcs_s_ocopyoutf
11319093SRamana.Srikanth@Sun.COM 			    (&kstatus, args.sdbc_ustatus, rc));
11327836SJohn.Forte@Sun.COM 		}
11337836SJohn.Forte@Sun.COM 
11347836SJohn.Forte@Sun.COM 		return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus, rc));
11357836SJohn.Forte@Sun.COM 	}
11367836SJohn.Forte@Sun.COM 
11377836SJohn.Forte@Sun.COM 	case SDBC_MAXFILES:
11387836SJohn.Forte@Sun.COM 		if (copyout(&sdbc_max_devs, (void *)args.arg0,
11397836SJohn.Forte@Sun.COM 		    sizeof (sdbc_max_devs)))
11407836SJohn.Forte@Sun.COM 			rc = EFAULT;
11417836SJohn.Forte@Sun.COM 		else
11427836SJohn.Forte@Sun.COM 			rc = 0;
11437836SJohn.Forte@Sun.COM 
11447836SJohn.Forte@Sun.COM 		break;
11457836SJohn.Forte@Sun.COM 
11467836SJohn.Forte@Sun.COM 	case SDBC_VERSION:
11477836SJohn.Forte@Sun.COM 	{
11487836SJohn.Forte@Sun.COM 		cache_version_t cache_version;
11497836SJohn.Forte@Sun.COM 
11507836SJohn.Forte@Sun.COM 		cache_version.major = sdbc_major_rev;
11517836SJohn.Forte@Sun.COM 		cache_version.minor = sdbc_minor_rev;
11527836SJohn.Forte@Sun.COM 		cache_version.micro = sdbc_micro_rev;
11537836SJohn.Forte@Sun.COM 		cache_version.baseline = sdbc_baseline_rev;
11547836SJohn.Forte@Sun.COM 
11557836SJohn.Forte@Sun.COM 		if (ddi_copyout(&cache_version, (void *)args.arg0,
11569093SRamana.Srikanth@Sun.COM 		    sizeof (cache_version_t), mode)) {
11577836SJohn.Forte@Sun.COM 			rc = EFAULT;
11587836SJohn.Forte@Sun.COM 			break;
11597836SJohn.Forte@Sun.COM 		}
11607836SJohn.Forte@Sun.COM 
11617836SJohn.Forte@Sun.COM 		break;
11627836SJohn.Forte@Sun.COM 	}
11637836SJohn.Forte@Sun.COM 
11647836SJohn.Forte@Sun.COM 
11657836SJohn.Forte@Sun.COM #ifdef DEBUG
11667836SJohn.Forte@Sun.COM 	/* toggle flusher flag for testing */
11677836SJohn.Forte@Sun.COM 	case SDBC_TOGGLE_FLUSH:
11687836SJohn.Forte@Sun.COM 		_sdbc_flush_flag ^= 1;
11697836SJohn.Forte@Sun.COM 		*rvp = _sdbc_flush_flag;
11707836SJohn.Forte@Sun.COM 		rc = 0;
11717836SJohn.Forte@Sun.COM 
11727836SJohn.Forte@Sun.COM 		return (spcs_s_ocopyoutf(&kstatus, args.sdbc_ustatus,
11737836SJohn.Forte@Sun.COM 		    SDBC_ETOGGLE_FLUSH, _sdbc_flush_flag ? "on" : "off"));
11747836SJohn.Forte@Sun.COM 
11757836SJohn.Forte@Sun.COM 
11767836SJohn.Forte@Sun.COM 	/* inject i/o errors */
11777836SJohn.Forte@Sun.COM 	case SDBC_INJ_IOERR: /* cd, errnum */
11787836SJohn.Forte@Sun.COM 		if (_sd_cache_initialized == 0)
11797836SJohn.Forte@Sun.COM 			return (spcs_s_ocopyoutf(&kstatus,
11807836SJohn.Forte@Sun.COM 			    args.sdbc_ustatus, EINVAL));
11817836SJohn.Forte@Sun.COM 		rc = _sdbc_inject_ioerr(args.arg0, args.arg1, args.arg2);
11827836SJohn.Forte@Sun.COM 		break;
11837836SJohn.Forte@Sun.COM 
11847836SJohn.Forte@Sun.COM 	/* clear injected i/o errors */
11857836SJohn.Forte@Sun.COM 	case SDBC_CLR_IOERR: /* cd */
11867836SJohn.Forte@Sun.COM 		if (_sd_cache_initialized == 0)
11877836SJohn.Forte@Sun.COM 			return (spcs_s_ocopyoutf(&kstatus,
11887836SJohn.Forte@Sun.COM 			    args.sdbc_ustatus, EINVAL));
11897836SJohn.Forte@Sun.COM 		rc = _sdbc_clear_ioerr(args.arg0);
11907836SJohn.Forte@Sun.COM 		break;
11917836SJohn.Forte@Sun.COM 
11927836SJohn.Forte@Sun.COM #endif /* DEBUG */
11937836SJohn.Forte@Sun.COM 	default:
11949093SRamana.Srikanth@Sun.COM 		_sd_print(3, "!SDBC unknown ioctl: 0x%x unsupported", cmd);
11957836SJohn.Forte@Sun.COM 		rc = EINVAL;
11967836SJohn.Forte@Sun.COM 		break;
11977836SJohn.Forte@Sun.COM 	}
11987836SJohn.Forte@Sun.COM 
11997836SJohn.Forte@Sun.COM 	spcs_s_kfree(kstatus);
12007836SJohn.Forte@Sun.COM 	return (rc);
12017836SJohn.Forte@Sun.COM }
12027836SJohn.Forte@Sun.COM 
12037836SJohn.Forte@Sun.COM 
12047836SJohn.Forte@Sun.COM /*
12057836SJohn.Forte@Sun.COM  * _sd_timed_block - sleep waiting for ticks time delay.
12067836SJohn.Forte@Sun.COM  * ticks - # of ticks to sleep
12077836SJohn.Forte@Sun.COM  * cvp - pointer to the cv we wait on while we delay.
12087836SJohn.Forte@Sun.COM  *
12097836SJohn.Forte@Sun.COM  * NO spin locks can be held at entry!
12107836SJohn.Forte@Sun.COM  *
12117836SJohn.Forte@Sun.COM  */
12127836SJohn.Forte@Sun.COM void
_sd_timed_block(clock_t ticks,kcondvar_t * cvp)12137836SJohn.Forte@Sun.COM _sd_timed_block(clock_t ticks, kcondvar_t *cvp)
12147836SJohn.Forte@Sun.COM {
12157836SJohn.Forte@Sun.COM 	mutex_enter(&_sd_block_lk);
1216*11066Srafael.vanoni@sun.com 	(void) cv_reltimedwait(cvp, &_sd_block_lk, ticks, TR_CLOCK_TICK);
12177836SJohn.Forte@Sun.COM 	mutex_exit(&_sd_block_lk);
12187836SJohn.Forte@Sun.COM }
12197836SJohn.Forte@Sun.COM 
12207836SJohn.Forte@Sun.COM 
12217836SJohn.Forte@Sun.COM /*
12227836SJohn.Forte@Sun.COM  * _sd_unblock - awake a sleeper waiting on cv pointed to by cvp.
12237836SJohn.Forte@Sun.COM  *
12247836SJohn.Forte@Sun.COM  * NO spin locks can be held at entry as we may sleep.
12257836SJohn.Forte@Sun.COM  *
12267836SJohn.Forte@Sun.COM  */
12277836SJohn.Forte@Sun.COM void
_sd_unblock(kcondvar_t * cvp)12287836SJohn.Forte@Sun.COM _sd_unblock(kcondvar_t *cvp)
12297836SJohn.Forte@Sun.COM {
12307836SJohn.Forte@Sun.COM 
12317836SJohn.Forte@Sun.COM 	mutex_enter(&_sd_block_lk);
12327836SJohn.Forte@Sun.COM 	cv_broadcast(cvp);
12337836SJohn.Forte@Sun.COM 	mutex_exit(&_sd_block_lk);
12347836SJohn.Forte@Sun.COM }
12357836SJohn.Forte@Sun.COM 
12367836SJohn.Forte@Sun.COM /* ARGSUSED */
12377836SJohn.Forte@Sun.COM void
_sd_data_log(int num,_sd_cctl_t * centry,nsc_off_t st,nsc_size_t len)12387836SJohn.Forte@Sun.COM _sd_data_log(int num, _sd_cctl_t *centry, nsc_off_t st, nsc_size_t len)
12397836SJohn.Forte@Sun.COM {
12407836SJohn.Forte@Sun.COM #if defined(_SD_FBA_DATA_LOG)
12417836SJohn.Forte@Sun.COM 	nsc_size_t i;
12427836SJohn.Forte@Sun.COM 	nsc_off_t blk;
12437836SJohn.Forte@Sun.COM 
12447836SJohn.Forte@Sun.COM 	blk = BLK_TO_FBA_NUM(CENTRY_BLK(centry));
12457836SJohn.Forte@Sun.COM 	for (i = st; i < (st + len); i++)
12467836SJohn.Forte@Sun.COM 		SDTRACE(num, CENTRY_CD(centry), 1, blk + i,
12479093SRamana.Srikanth@Sun.COM 		    *(int *)(centry->cc_data + FBA_SIZE(i)),
12489093SRamana.Srikanth@Sun.COM 		    *(int *)(centry->cc_data + FBA_SIZE(i) + 4));
12497836SJohn.Forte@Sun.COM #endif /* _SD_FBA_DATA_LOG */
12507836SJohn.Forte@Sun.COM }
12517836SJohn.Forte@Sun.COM 
12527836SJohn.Forte@Sun.COM /* ARGSUSED */
12537836SJohn.Forte@Sun.COM void
_sd_data_log_chain(int num,_sd_cctl_t * centry,nsc_off_t fba_pos,nsc_size_t fba_len)12547836SJohn.Forte@Sun.COM _sd_data_log_chain(int num, _sd_cctl_t *centry, nsc_off_t fba_pos,
12557836SJohn.Forte@Sun.COM     nsc_size_t fba_len)
12567836SJohn.Forte@Sun.COM {
12577836SJohn.Forte@Sun.COM #if defined(_SD_FBA_DATA_LOG)
12587836SJohn.Forte@Sun.COM 	sdbc_cblk_fba_t st_cblk_len;	/* FBA len of starting cache block */
12597836SJohn.Forte@Sun.COM 	sdbc_cblk_fba_t end_cblk_len;	/* FBA len of ending cache block */
12607836SJohn.Forte@Sun.COM 	sdbc_cblk_fba_t st_cblk_off;	/* FBA offset into starting cblock */
12617836SJohn.Forte@Sun.COM 
12627836SJohn.Forte@Sun.COM 	while (CENTRY_BLK(centry) != FBA_TO_BLK_NUM(fba_pos))
12637836SJohn.Forte@Sun.COM 		centry = centry->cc_chain;
12647836SJohn.Forte@Sun.COM 
12657836SJohn.Forte@Sun.COM 	st_cblk_off = BLK_FBA_OFF(fba_pos);
12667836SJohn.Forte@Sun.COM 	st_cblk_len = BLK_FBAS - st_cblk_off;
12677836SJohn.Forte@Sun.COM 	if (st_cblk_len >= fba_len) {
12687836SJohn.Forte@Sun.COM 		end_cblk_len = 0;
12697836SJohn.Forte@Sun.COM 		st_cblk_len = fba_len;
12707836SJohn.Forte@Sun.COM 	} else {
12717836SJohn.Forte@Sun.COM 		end_cblk_len = BLK_FBA_OFF(fba_pos + fba_len);
12727836SJohn.Forte@Sun.COM 	}
12737836SJohn.Forte@Sun.COM 
12747836SJohn.Forte@Sun.COM 	DATA_LOG(num, centry, st_cblk_off, st_cblk_len);
12757836SJohn.Forte@Sun.COM 
12767836SJohn.Forte@Sun.COM 	fba_len -= st_cblk_len;
12777836SJohn.Forte@Sun.COM 	centry = centry->cc_chain;
12787836SJohn.Forte@Sun.COM 
12797836SJohn.Forte@Sun.COM 	while (fba_len > end_cblk_len) {
12807836SJohn.Forte@Sun.COM 		DATA_LOG(num, centry, 0, BLK_FBAS);
12817836SJohn.Forte@Sun.COM 		fba_len -= BLK_FBAS;
12827836SJohn.Forte@Sun.COM 		centry = centry->cc_chain;
12837836SJohn.Forte@Sun.COM 	}
12847836SJohn.Forte@Sun.COM 	if (end_cblk_len) DATA_LOG(num, centry, 0, end_cblk_len);
12857836SJohn.Forte@Sun.COM #endif /* _SD_FBA_DATA_LOG */
12867836SJohn.Forte@Sun.COM }
12877836SJohn.Forte@Sun.COM 
12887836SJohn.Forte@Sun.COM 
12897836SJohn.Forte@Sun.COM void
_sd_zap_stats(void)12907836SJohn.Forte@Sun.COM _sd_zap_stats(void)
12917836SJohn.Forte@Sun.COM {
12927836SJohn.Forte@Sun.COM 	int i;
12937836SJohn.Forte@Sun.COM 
12947836SJohn.Forte@Sun.COM 	if (_sd_cache_stats == NULL)
12957836SJohn.Forte@Sun.COM 		return;
12967836SJohn.Forte@Sun.COM 
12977836SJohn.Forte@Sun.COM 	_sd_cache_stats->st_rdhits = 0;
12987836SJohn.Forte@Sun.COM 	_sd_cache_stats->st_rdmiss = 0;
12997836SJohn.Forte@Sun.COM 	_sd_cache_stats->st_wrhits = 0;
13007836SJohn.Forte@Sun.COM 	_sd_cache_stats->st_wrmiss = 0;
13017836SJohn.Forte@Sun.COM 	_sd_lru_q.sq_noreq_stat = 0;
13027836SJohn.Forte@Sun.COM 	_sd_lru_q.sq_req_stat = 0;
13037836SJohn.Forte@Sun.COM 
13047836SJohn.Forte@Sun.COM 	for (i = 0; i < sdbc_max_devs; i++) {
13057836SJohn.Forte@Sun.COM 		_sd_cache_stats->st_shared[i].sh_cache_read  = 0;
13067836SJohn.Forte@Sun.COM 		_sd_cache_stats->st_shared[i].sh_cache_write = 0;
13077836SJohn.Forte@Sun.COM 		_sd_cache_stats->st_shared[i].sh_disk_read   = 0;
13087836SJohn.Forte@Sun.COM 		_sd_cache_stats->st_shared[i].sh_disk_write  = 0;
13097836SJohn.Forte@Sun.COM 	}
13107836SJohn.Forte@Sun.COM }
13117836SJohn.Forte@Sun.COM 
13127836SJohn.Forte@Sun.COM 
13137836SJohn.Forte@Sun.COM /*
13147836SJohn.Forte@Sun.COM  * Return the cache sizes used by the Sense Subsystem Status CCW
13157836SJohn.Forte@Sun.COM  */
13167836SJohn.Forte@Sun.COM int
_sd_cache_sizes(int * asize,int * wsize)13177836SJohn.Forte@Sun.COM _sd_cache_sizes(int *asize, int *wsize)
13187836SJohn.Forte@Sun.COM {
13197836SJohn.Forte@Sun.COM 	int	psize;
13207836SJohn.Forte@Sun.COM 
13217836SJohn.Forte@Sun.COM 	*asize = 0;
13227836SJohn.Forte@Sun.COM 	*wsize = 0;
13237836SJohn.Forte@Sun.COM 
13247836SJohn.Forte@Sun.COM 	/*
13257836SJohn.Forte@Sun.COM 	 * add in the total cache size and the
13267836SJohn.Forte@Sun.COM 	 * non-volatile (battery-backed) cache size.
13277836SJohn.Forte@Sun.COM 	 */
13287836SJohn.Forte@Sun.COM 	if (_sd_net_config.sn_configured) {
13297836SJohn.Forte@Sun.COM 		psize = _sd_net_config.sn_psize;
13307836SJohn.Forte@Sun.COM 		*asize += (_sd_net_config.sn_cpages * psize);
13317836SJohn.Forte@Sun.COM 		*wsize += (safestore_config.ssc_wsize);
13327836SJohn.Forte@Sun.COM 	}
13337836SJohn.Forte@Sun.COM 
13347836SJohn.Forte@Sun.COM 	return (0);
13357836SJohn.Forte@Sun.COM }
13367836SJohn.Forte@Sun.COM 
13377836SJohn.Forte@Sun.COM 
13387836SJohn.Forte@Sun.COM /*PRINTFLIKE2*/
13397836SJohn.Forte@Sun.COM void
_sd_print(int level,char * fmt,...)13407836SJohn.Forte@Sun.COM _sd_print(int level, char *fmt, ...)
13417836SJohn.Forte@Sun.COM {
13427836SJohn.Forte@Sun.COM 	va_list adx;
13437836SJohn.Forte@Sun.COM 	if (level <= _sd_debug_level) {
13447836SJohn.Forte@Sun.COM 		va_start(adx, fmt);
13457836SJohn.Forte@Sun.COM 		vcmn_err(CE_NOTE, fmt, adx);
13467836SJohn.Forte@Sun.COM 		va_end(adx);
13477836SJohn.Forte@Sun.COM 
13487836SJohn.Forte@Sun.COM 	}
13497836SJohn.Forte@Sun.COM }
13507836SJohn.Forte@Sun.COM 
13517836SJohn.Forte@Sun.COM 
13527836SJohn.Forte@Sun.COM int
_sd_get_cd_blk(int cd,nsc_off_t cblk,_sd_cctl_t ** cc,caddr_t * data,char ** filename)13537836SJohn.Forte@Sun.COM _sd_get_cd_blk(int cd, nsc_off_t cblk, _sd_cctl_t **cc, caddr_t *data,
13547836SJohn.Forte@Sun.COM     char **filename)
13557836SJohn.Forte@Sun.COM {
13567836SJohn.Forte@Sun.COM 	_sd_cctl_t *cc_ent;
13577836SJohn.Forte@Sun.COM 
13587836SJohn.Forte@Sun.COM 	if (FILE_OPENED(cd) != 0) {
13597836SJohn.Forte@Sun.COM 		*filename = _sd_cache_files[cd].cd_info->sh_filename;
13607836SJohn.Forte@Sun.COM 		if (cc_ent = (_sd_cctl_t *)
13617836SJohn.Forte@Sun.COM 		    _sd_hash_search(cd, cblk, _sd_htable)) {
13627836SJohn.Forte@Sun.COM 			*cc = cc_ent;
13637836SJohn.Forte@Sun.COM 			*data = (caddr_t)cc_ent->cc_data;
13647836SJohn.Forte@Sun.COM 			return (0);
13657836SJohn.Forte@Sun.COM 		}
13667836SJohn.Forte@Sun.COM 	}
13677836SJohn.Forte@Sun.COM 	return (-1);
13687836SJohn.Forte@Sun.COM }
13697836SJohn.Forte@Sun.COM 
13707836SJohn.Forte@Sun.COM /*
13717836SJohn.Forte@Sun.COM  * central dyn mem processing vars edit rtn.
13727836SJohn.Forte@Sun.COM  * input a local copy and xfer to global
13737836SJohn.Forte@Sun.COM  *
13747836SJohn.Forte@Sun.COM  * sec0,sec1,sec2
13757836SJohn.Forte@Sun.COM  * range check 1 to 255 (arbitrary but in any case must be <= 2000 due to
13767836SJohn.Forte@Sun.COM  *	32bit signed int limits in later calc)
13777836SJohn.Forte@Sun.COM  * aging_ct
13787836SJohn.Forte@Sun.COM  * range check 1 to 255 (only 8 bits reserved for aging ctr)
13797836SJohn.Forte@Sun.COM  *
13807836SJohn.Forte@Sun.COM  */
13817836SJohn.Forte@Sun.COM int
sdbc_edit_xfer_process_vars_dm(_dm_process_vars_t * process_vars)13827836SJohn.Forte@Sun.COM sdbc_edit_xfer_process_vars_dm(_dm_process_vars_t *process_vars)
13837836SJohn.Forte@Sun.COM {
13847836SJohn.Forte@Sun.COM 	if (process_vars->max_dyn_list > 0)
13857836SJohn.Forte@Sun.COM 		dynmem_processing_dm.max_dyn_list = process_vars->max_dyn_list;
13867836SJohn.Forte@Sun.COM 
13877836SJohn.Forte@Sun.COM 	/* no edit on monitor_dynmem_process */
13887836SJohn.Forte@Sun.COM 	dynmem_processing_dm.monitor_dynmem_process =
13897836SJohn.Forte@Sun.COM 	    process_vars->monitor_dynmem_process;
13907836SJohn.Forte@Sun.COM 	/* no edit on process_directive */
13917836SJohn.Forte@Sun.COM 	dynmem_processing_dm.process_directive =
13927836SJohn.Forte@Sun.COM 	    process_vars->process_directive;
13937836SJohn.Forte@Sun.COM 
13947836SJohn.Forte@Sun.COM 	if (process_vars->cache_aging_ct1 > 0 &&
13957836SJohn.Forte@Sun.COM 	    process_vars->cache_aging_ct1 <= CACHE_AGING_CT_MAX)
13967836SJohn.Forte@Sun.COM 		dynmem_processing_dm.cache_aging_ct1 =
13977836SJohn.Forte@Sun.COM 		    process_vars->cache_aging_ct1;
13987836SJohn.Forte@Sun.COM 	if (process_vars->cache_aging_ct2 > 0 &&
13997836SJohn.Forte@Sun.COM 	    process_vars->cache_aging_ct2 <= CACHE_AGING_CT_MAX)
14007836SJohn.Forte@Sun.COM 		dynmem_processing_dm.cache_aging_ct2 =
14017836SJohn.Forte@Sun.COM 		    process_vars->cache_aging_ct2;
14027836SJohn.Forte@Sun.COM 	if (process_vars->cache_aging_ct3 > 0 &&
14037836SJohn.Forte@Sun.COM 	    process_vars->cache_aging_ct3 <= CACHE_AGING_CT_MAX)
14047836SJohn.Forte@Sun.COM 		dynmem_processing_dm.cache_aging_ct3 =
14057836SJohn.Forte@Sun.COM 		    process_vars->cache_aging_ct3;
14067836SJohn.Forte@Sun.COM 	if (process_vars->cache_aging_sec1 > 0 &&
14077836SJohn.Forte@Sun.COM 	    process_vars->cache_aging_sec1 <= CACHE_AGING_SEC1_MAX)
14087836SJohn.Forte@Sun.COM 		dynmem_processing_dm.cache_aging_sec1 =
14097836SJohn.Forte@Sun.COM 		    process_vars->cache_aging_sec1;
14107836SJohn.Forte@Sun.COM 	if (process_vars->cache_aging_sec2 > 0 &&
14117836SJohn.Forte@Sun.COM 	    process_vars->cache_aging_sec2 <= CACHE_AGING_SEC2_MAX)
14127836SJohn.Forte@Sun.COM 		dynmem_processing_dm.cache_aging_sec2 =
14137836SJohn.Forte@Sun.COM 		    process_vars->cache_aging_sec2;
14147836SJohn.Forte@Sun.COM 	if (process_vars->cache_aging_sec3 > 0 &&
14157836SJohn.Forte@Sun.COM 	    process_vars->cache_aging_sec3 <= CACHE_AGING_SEC3_MAX)
14167836SJohn.Forte@Sun.COM 		dynmem_processing_dm.cache_aging_sec3 =
14177836SJohn.Forte@Sun.COM 		    process_vars->cache_aging_sec3;
14187836SJohn.Forte@Sun.COM 	if (process_vars->cache_aging_pcnt1 >= 0 &&
14197836SJohn.Forte@Sun.COM 	    process_vars->cache_aging_pcnt1 <= CACHE_AGING_PCNT1_MAX)
14207836SJohn.Forte@Sun.COM 		dynmem_processing_dm.cache_aging_pcnt1 =
14217836SJohn.Forte@Sun.COM 		    process_vars->cache_aging_pcnt1;
14227836SJohn.Forte@Sun.COM 	if (process_vars->cache_aging_pcnt2 >= 0 &&
14237836SJohn.Forte@Sun.COM 	    process_vars->cache_aging_pcnt2 <= CACHE_AGING_PCNT2_MAX)
14247836SJohn.Forte@Sun.COM 		dynmem_processing_dm.cache_aging_pcnt2 =
14257836SJohn.Forte@Sun.COM 		    process_vars->cache_aging_pcnt2;
14267836SJohn.Forte@Sun.COM 	if (process_vars->max_holds_pcnt >= 0 &&
14277836SJohn.Forte@Sun.COM 	    process_vars->max_holds_pcnt <= MAX_HOLDS_PCNT_MAX)
14287836SJohn.Forte@Sun.COM 		dynmem_processing_dm.max_holds_pcnt =
14297836SJohn.Forte@Sun.COM 		    process_vars->max_holds_pcnt;
14307836SJohn.Forte@Sun.COM 	return (0);
14317836SJohn.Forte@Sun.COM }
14327836SJohn.Forte@Sun.COM 
14337836SJohn.Forte@Sun.COM dev_info_t *
sdbc_get_dip()14347836SJohn.Forte@Sun.COM sdbc_get_dip()
14357836SJohn.Forte@Sun.COM {
14367836SJohn.Forte@Sun.COM 	return (dev_dip);
14377836SJohn.Forte@Sun.COM }
1438