xref: /onnv-gate/usr/src/uts/common/avs/ns/nsctl/nsc_gen.c (revision 9093:cd587b0bd19c)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
22*9093SRamana.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 #include <sys/types.h>
277836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
287836SJohn.Forte@Sun.COM #include <sys/errno.h>
297836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
307836SJohn.Forte@Sun.COM #include <sys/kmem.h>
317836SJohn.Forte@Sun.COM #include <sys/ddi.h>
327836SJohn.Forte@Sun.COM #include <sys/varargs.h>
337836SJohn.Forte@Sun.COM #if defined(DEBUG) && !defined(DS_DDICT)
347836SJohn.Forte@Sun.COM #include <sys/kobj.h>
357836SJohn.Forte@Sun.COM #endif
367836SJohn.Forte@Sun.COM 
377836SJohn.Forte@Sun.COM #include <sys/ncall/ncall.h>
387836SJohn.Forte@Sun.COM 
397836SJohn.Forte@Sun.COM #define	__NSC_GEN__
407836SJohn.Forte@Sun.COM #include "nsc_gen.h"
417836SJohn.Forte@Sun.COM #include "nsc_mem.h"
427836SJohn.Forte@Sun.COM #include "../nsctl.h"
437836SJohn.Forte@Sun.COM #ifdef DS_DDICT
447836SJohn.Forte@Sun.COM #include "../contract.h"
457836SJohn.Forte@Sun.COM #endif
467836SJohn.Forte@Sun.COM 
477836SJohn.Forte@Sun.COM 
487836SJohn.Forte@Sun.COM static kcondvar_t _nsc_delay_cv;
497836SJohn.Forte@Sun.COM static kmutex_t _nsc_delay_mutex;
507836SJohn.Forte@Sun.COM 
517836SJohn.Forte@Sun.COM static nsc_service_t *_nsc_services;
527836SJohn.Forte@Sun.COM static kmutex_t _nsc_svc_mutex;
537836SJohn.Forte@Sun.COM 
547836SJohn.Forte@Sun.COM static int _nsc_rmmap_inuse(nsc_rmmap_t *, ulong_t *, size_t *);
557836SJohn.Forte@Sun.COM 
567836SJohn.Forte@Sun.COM static void _nsc_sprint_dec(char **, int, int, int);
577836SJohn.Forte@Sun.COM static void _nsc_sprint_hex(char **, unsigned int, int, int, int, int);
587836SJohn.Forte@Sun.COM 
597836SJohn.Forte@Sun.COM clock_t HZ;
607836SJohn.Forte@Sun.COM 
617836SJohn.Forte@Sun.COM extern nsc_rmhdr_t *_nsc_rmhdr_ptr;
627836SJohn.Forte@Sun.COM 
637836SJohn.Forte@Sun.COM void
_nsc_init_gen()647836SJohn.Forte@Sun.COM _nsc_init_gen()
657836SJohn.Forte@Sun.COM {
667836SJohn.Forte@Sun.COM 	HZ = drv_usectohz(1000000);
677836SJohn.Forte@Sun.COM }
687836SJohn.Forte@Sun.COM 
697836SJohn.Forte@Sun.COM 
707836SJohn.Forte@Sun.COM void
nsc_decode_param(nsc_def_t * args,nsc_def_t * def,long * v)717836SJohn.Forte@Sun.COM nsc_decode_param(nsc_def_t *args, nsc_def_t *def, long *v)
727836SJohn.Forte@Sun.COM {
737836SJohn.Forte@Sun.COM 	nsc_def_t *dp;
747836SJohn.Forte@Sun.COM 
757836SJohn.Forte@Sun.COM 	for (; def && def->name; def++) {
767836SJohn.Forte@Sun.COM 		for (dp = args; dp && dp->name; dp++) {
777836SJohn.Forte@Sun.COM 			if (strcmp(dp->name, def->name) == 0) {
787836SJohn.Forte@Sun.COM 				v[def->offset] = dp->value;
797836SJohn.Forte@Sun.COM 				break;
807836SJohn.Forte@Sun.COM 			}
817836SJohn.Forte@Sun.COM 		}
827836SJohn.Forte@Sun.COM 
837836SJohn.Forte@Sun.COM 		if ((!dp || !dp->name) && !v[def->offset])
847836SJohn.Forte@Sun.COM 			v[def->offset] = def->value;
857836SJohn.Forte@Sun.COM 	}
867836SJohn.Forte@Sun.COM }
877836SJohn.Forte@Sun.COM 
887836SJohn.Forte@Sun.COM 
897836SJohn.Forte@Sun.COM clock_t
nsc_lbolt()907836SJohn.Forte@Sun.COM nsc_lbolt()
917836SJohn.Forte@Sun.COM {
927836SJohn.Forte@Sun.COM #ifdef _SunOS_5_6
937836SJohn.Forte@Sun.COM 	clock_t lbolt;
947836SJohn.Forte@Sun.COM 	time_t time;
957836SJohn.Forte@Sun.COM 
967836SJohn.Forte@Sun.COM 	if (drv_getparm(LBOLT, &lbolt) == 0)
977836SJohn.Forte@Sun.COM 		return (lbolt);
987836SJohn.Forte@Sun.COM 
997836SJohn.Forte@Sun.COM 	if (drv_getparm(TIME, &time) != 0)
1007836SJohn.Forte@Sun.COM 		return ((clock_t)0);
1017836SJohn.Forte@Sun.COM 
1027836SJohn.Forte@Sun.COM 	time %= (60 * 60 * 24 * 365);
1037836SJohn.Forte@Sun.COM 
1047836SJohn.Forte@Sun.COM 	return (clock_t)(time * HZ);
1057836SJohn.Forte@Sun.COM #else
1067836SJohn.Forte@Sun.COM 	return (ddi_get_lbolt());
1077836SJohn.Forte@Sun.COM #endif
1087836SJohn.Forte@Sun.COM }
1097836SJohn.Forte@Sun.COM 
1107836SJohn.Forte@Sun.COM 
1117836SJohn.Forte@Sun.COM time_t
nsc_time()1127836SJohn.Forte@Sun.COM nsc_time()
1137836SJohn.Forte@Sun.COM {
1147836SJohn.Forte@Sun.COM 	time_t time;
1157836SJohn.Forte@Sun.COM 
1167836SJohn.Forte@Sun.COM 	if (drv_getparm(TIME, &time) != 0)
1177836SJohn.Forte@Sun.COM 		return ((time_t)0);
1187836SJohn.Forte@Sun.COM 
1197836SJohn.Forte@Sun.COM 	return (time);
1207836SJohn.Forte@Sun.COM }
1217836SJohn.Forte@Sun.COM 
1227836SJohn.Forte@Sun.COM 
1237836SJohn.Forte@Sun.COM int
nsc_node_up(int node)1247836SJohn.Forte@Sun.COM nsc_node_up(int node)
1257836SJohn.Forte@Sun.COM {
1267836SJohn.Forte@Sun.COM 	return (node == ncall_self());
1277836SJohn.Forte@Sun.COM }
1287836SJohn.Forte@Sun.COM 
1297836SJohn.Forte@Sun.COM 
1307836SJohn.Forte@Sun.COM 
1317836SJohn.Forte@Sun.COM /*
1327836SJohn.Forte@Sun.COM  * HACK increment nodeid in data parameter
1337836SJohn.Forte@Sun.COM  */
1347836SJohn.Forte@Sun.COM int
nsc_nodeid_data()1357836SJohn.Forte@Sun.COM nsc_nodeid_data()
1367836SJohn.Forte@Sun.COM {
1377836SJohn.Forte@Sun.COM 	int data;
1387836SJohn.Forte@Sun.COM 	return ((data = nsc_node_id()) == 0 ? 1 : data);
1397836SJohn.Forte@Sun.COM }
1407836SJohn.Forte@Sun.COM 
1417836SJohn.Forte@Sun.COM 
1427836SJohn.Forte@Sun.COM int
nsc_node_id(void)1437836SJohn.Forte@Sun.COM nsc_node_id(void)
1447836SJohn.Forte@Sun.COM {
1457836SJohn.Forte@Sun.COM 	return (ncall_self());
1467836SJohn.Forte@Sun.COM }
1477836SJohn.Forte@Sun.COM 
1487836SJohn.Forte@Sun.COM char *
nsc_node_name()1497836SJohn.Forte@Sun.COM nsc_node_name()
1507836SJohn.Forte@Sun.COM {
1517836SJohn.Forte@Sun.COM 	return (ncall_nodename(ncall_self()));
1527836SJohn.Forte@Sun.COM }
1537836SJohn.Forte@Sun.COM 
1547836SJohn.Forte@Sun.COM 
1557836SJohn.Forte@Sun.COM /*
1567836SJohn.Forte@Sun.COM  * int
1577836SJohn.Forte@Sun.COM  * _nsc_rmmap_init (nsc_rmmap_t *map, char *name, int nslot,
1587836SJohn.Forte@Sun.COM  *					size_t size, ulong_t offset)
1597836SJohn.Forte@Sun.COM  *	Initialise a global resource map.
1607836SJohn.Forte@Sun.COM  *
1617836SJohn.Forte@Sun.COM  * Calling/Exit State:
1627836SJohn.Forte@Sun.COM  *	Returns TRUE if the map was successfully created. Otherwise
1637836SJohn.Forte@Sun.COM  *	returns FALSE.
1647836SJohn.Forte@Sun.COM  *
1657836SJohn.Forte@Sun.COM  * Description:
1667836SJohn.Forte@Sun.COM  *	Initialises a global resource map. If the map already exists
1677836SJohn.Forte@Sun.COM  *	the arguments are validated against it.
1687836SJohn.Forte@Sun.COM  */
1697836SJohn.Forte@Sun.COM int
_nsc_rmmap_init(nsc_rmmap_t * map,char * name,int nslot,size_t size,ulong_t offset)1707836SJohn.Forte@Sun.COM _nsc_rmmap_init(nsc_rmmap_t *map, char *name,
1717836SJohn.Forte@Sun.COM     int nslot, size_t size, ulong_t offset)
1727836SJohn.Forte@Sun.COM {
1737836SJohn.Forte@Sun.COM 	nsc_rmmap_t *nvmap = NULL;
1747836SJohn.Forte@Sun.COM 
1757836SJohn.Forte@Sun.COM 	if (!size)
1767836SJohn.Forte@Sun.COM 		return (0);
1777836SJohn.Forte@Sun.COM 
1787836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_global_lock);
1797836SJohn.Forte@Sun.COM 
1807836SJohn.Forte@Sun.COM 	if (_nsc_rm_nvmem_base)
1817836SJohn.Forte@Sun.COM 		nvmap = _nsc_global_nvmemmap_lookup(map);
1827836SJohn.Forte@Sun.COM 
1837836SJohn.Forte@Sun.COM 	if (!map->size)
1847836SJohn.Forte@Sun.COM 		map->size = size;
1857836SJohn.Forte@Sun.COM 	if (!map->inuse)
1867836SJohn.Forte@Sun.COM 		map->inuse = nslot;
1877836SJohn.Forte@Sun.COM 	if (!map->offset)
1887836SJohn.Forte@Sun.COM 		map->offset = offset;
1897836SJohn.Forte@Sun.COM 
1907836SJohn.Forte@Sun.COM 	if (!map->name[0])
1917836SJohn.Forte@Sun.COM 		(void) strncpy(map->name, name, _NSC_MAXNAME);
1927836SJohn.Forte@Sun.COM 
1937836SJohn.Forte@Sun.COM 	/* actually we only need to do this if an update occurred above */
1947836SJohn.Forte@Sun.COM 	if (nvmap) {
1957836SJohn.Forte@Sun.COM 		(void) nsc_commit_mem(map, nvmap,
1967836SJohn.Forte@Sun.COM 		    sizeof (nsc_rmmap_t), nsc_cm_errhdlr);
1977836SJohn.Forte@Sun.COM 	}
1987836SJohn.Forte@Sun.COM 
1997836SJohn.Forte@Sun.COM 	if (strncmp(map->name, name, _NSC_MAXNAME) ||
2007836SJohn.Forte@Sun.COM 	    (uint32_t)size != map->size || (int32_t)offset != map->offset) {
2017836SJohn.Forte@Sun.COM 		mutex_exit(&_nsc_global_lock);
2027836SJohn.Forte@Sun.COM 		return (0);
2037836SJohn.Forte@Sun.COM 	}
2047836SJohn.Forte@Sun.COM 
2057836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_global_lock);
2067836SJohn.Forte@Sun.COM 	return (1);
2077836SJohn.Forte@Sun.COM }
2087836SJohn.Forte@Sun.COM 
2097836SJohn.Forte@Sun.COM 
2107836SJohn.Forte@Sun.COM /*
2117836SJohn.Forte@Sun.COM  * ulong_t
2127836SJohn.Forte@Sun.COM  * _nsc_rmmap_alloc (nsc_rmmap_t *map, char *name,
2137836SJohn.Forte@Sun.COM  *					size_t size, void (*alloc)())
2147836SJohn.Forte@Sun.COM  *	Allocate entry in a global resource map.
2157836SJohn.Forte@Sun.COM  *
2167836SJohn.Forte@Sun.COM  * Calling/Exit State:
2177836SJohn.Forte@Sun.COM  *	On success, returns the base of the allocated area. Otherwise,
2187836SJohn.Forte@Sun.COM  *	returns NULL. The function 'alloc' will be called if the
2197836SJohn.Forte@Sun.COM  *	allocated area is not currently in use.
2207836SJohn.Forte@Sun.COM  *
2217836SJohn.Forte@Sun.COM  * Description:
2227836SJohn.Forte@Sun.COM  *	Allocates an entry in the global resource map. If the entry
2237836SJohn.Forte@Sun.COM  *	already exists but is a different size an error is returned.
2247836SJohn.Forte@Sun.COM  */
2257836SJohn.Forte@Sun.COM ulong_t
_nsc_rmmap_alloc(nsc_rmmap_t * map,char * name,size_t size,void (* alloc)())2267836SJohn.Forte@Sun.COM _nsc_rmmap_alloc(nsc_rmmap_t *map, char *name, size_t size, void (*alloc)())
2277836SJohn.Forte@Sun.COM {
2287836SJohn.Forte@Sun.COM 	int i, nslot = map[0].inuse;
2297836SJohn.Forte@Sun.COM 	size_t want = size;
2307836SJohn.Forte@Sun.COM 	ulong_t offset;
2317836SJohn.Forte@Sun.COM 	nsc_rmmap_t *nvmap = NULL;
2327836SJohn.Forte@Sun.COM 
2337836SJohn.Forte@Sun.COM 	if (!size)
2347836SJohn.Forte@Sun.COM 		return (0);
2357836SJohn.Forte@Sun.COM 
2367836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_global_lock);
2377836SJohn.Forte@Sun.COM 	if (_nsc_rm_nvmem_base)
2387836SJohn.Forte@Sun.COM 		nvmap = _nsc_global_nvmemmap_lookup(map);
2397836SJohn.Forte@Sun.COM 
2407836SJohn.Forte@Sun.COM 	for (i = 1; i < nslot; i++) {
2417836SJohn.Forte@Sun.COM 		if (!map[i].inuse || !map[i].size)
2427836SJohn.Forte@Sun.COM 			continue;
2437836SJohn.Forte@Sun.COM 		if (strncmp(map[i].name, name, _NSC_MAXNAME))
2447836SJohn.Forte@Sun.COM 			continue;
2457836SJohn.Forte@Sun.COM 		if ((uint32_t)size == map[i].size) {
2467836SJohn.Forte@Sun.COM 			map[i].inuse |= (1 << nsc_node_id());
2477836SJohn.Forte@Sun.COM 			if (nvmap) {
2487836SJohn.Forte@Sun.COM 				(void) nsc_commit_mem(&map[i], &nvmap[i],
2497836SJohn.Forte@Sun.COM 				    sizeof (nsc_rmmap_t), nsc_cm_errhdlr);
2507836SJohn.Forte@Sun.COM 			}
2517836SJohn.Forte@Sun.COM 			mutex_exit(&_nsc_global_lock);
2527836SJohn.Forte@Sun.COM 			return (map[i].offset);
2537836SJohn.Forte@Sun.COM 		}
2547836SJohn.Forte@Sun.COM 
2557836SJohn.Forte@Sun.COM 		mutex_exit(&_nsc_global_lock);
2567836SJohn.Forte@Sun.COM 		return (0);
2577836SJohn.Forte@Sun.COM 	}
2587836SJohn.Forte@Sun.COM 
2597836SJohn.Forte@Sun.COM 	offset = map[0].offset;
2607836SJohn.Forte@Sun.COM 
2617836SJohn.Forte@Sun.COM 	while ((int32_t)offset < (map[0].offset + map[0].size)) {
2627836SJohn.Forte@Sun.COM 		if (_nsc_rmmap_inuse(map, &offset, &want))
2637836SJohn.Forte@Sun.COM 			continue;
2647836SJohn.Forte@Sun.COM 
2657836SJohn.Forte@Sun.COM 		if (size > want) {
2667836SJohn.Forte@Sun.COM 			offset += want;
2677836SJohn.Forte@Sun.COM 			want = size;
2687836SJohn.Forte@Sun.COM 			continue;
2697836SJohn.Forte@Sun.COM 		}
2707836SJohn.Forte@Sun.COM 
2717836SJohn.Forte@Sun.COM 		for (i = 1; i < nslot; i++)
2727836SJohn.Forte@Sun.COM 			if (!map[i].inuse || !map[i].size)
2737836SJohn.Forte@Sun.COM 				break;
2747836SJohn.Forte@Sun.COM 
2757836SJohn.Forte@Sun.COM 		if (i == nslot)
2767836SJohn.Forte@Sun.COM 			break;
2777836SJohn.Forte@Sun.COM 
2787836SJohn.Forte@Sun.COM 		bzero(&map[i], sizeof (map[i]));
2797836SJohn.Forte@Sun.COM 		(void) strncpy(map[i].name, name, _NSC_MAXNAME);
2807836SJohn.Forte@Sun.COM 
2817836SJohn.Forte@Sun.COM 		map[i].size = size;
2827836SJohn.Forte@Sun.COM 		map[i].offset = offset;
2837836SJohn.Forte@Sun.COM 		map[i].inuse = (1 << nsc_node_id());
2847836SJohn.Forte@Sun.COM 		if (nvmap) {  /* update the map and hdr dirty bit. */
2857836SJohn.Forte@Sun.COM 			(void) nsc_commit_mem(&map[i], &nvmap[i],
2867836SJohn.Forte@Sun.COM 			    sizeof (nsc_rmmap_t), nsc_cm_errhdlr);
2877836SJohn.Forte@Sun.COM 		}
2887836SJohn.Forte@Sun.COM 
2897836SJohn.Forte@Sun.COM 		if (alloc)
2907836SJohn.Forte@Sun.COM 			(*alloc)(offset, size);
2917836SJohn.Forte@Sun.COM 
2927836SJohn.Forte@Sun.COM 		mutex_exit(&_nsc_global_lock);
2937836SJohn.Forte@Sun.COM 		return (offset);
2947836SJohn.Forte@Sun.COM 	}
2957836SJohn.Forte@Sun.COM 
2967836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_global_lock);
2977836SJohn.Forte@Sun.COM 	return (0);
2987836SJohn.Forte@Sun.COM }
2997836SJohn.Forte@Sun.COM 
3007836SJohn.Forte@Sun.COM 
3017836SJohn.Forte@Sun.COM /*
3027836SJohn.Forte@Sun.COM  * void
3037836SJohn.Forte@Sun.COM  * _nsc_rmmap_free (nsc_rmmap_t *map, char *name)
3047836SJohn.Forte@Sun.COM  *	Free entry in a global resource map.
3057836SJohn.Forte@Sun.COM  *
3067836SJohn.Forte@Sun.COM  * Description:
3077836SJohn.Forte@Sun.COM  *	Frees an entry in the global resource map.
3087836SJohn.Forte@Sun.COM  */
3097836SJohn.Forte@Sun.COM void
_nsc_rmmap_free(nsc_rmmap_t * map,char * name,nsc_mem_t * mp)3107836SJohn.Forte@Sun.COM _nsc_rmmap_free(nsc_rmmap_t *map, char *name, nsc_mem_t *mp)
3117836SJohn.Forte@Sun.COM {
3127836SJohn.Forte@Sun.COM 	int i, nslot = map[0].inuse;
3137836SJohn.Forte@Sun.COM 	nsc_rmmap_t *nvmap = NULL;
3147836SJohn.Forte@Sun.COM 
3157836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_global_lock);
3167836SJohn.Forte@Sun.COM 	if (_nsc_rm_nvmem_base)
3177836SJohn.Forte@Sun.COM 		nvmap = _nsc_global_nvmemmap_lookup(map);
3187836SJohn.Forte@Sun.COM 
3197836SJohn.Forte@Sun.COM 	for (i = 1; i < nslot; i++) {
3207836SJohn.Forte@Sun.COM 		if (!map[i].inuse || !map[i].size)
3217836SJohn.Forte@Sun.COM 			continue;
3227836SJohn.Forte@Sun.COM 		if (strncmp(map[i].name, name, _NSC_MAXNAME))
3237836SJohn.Forte@Sun.COM 			continue;
3247836SJohn.Forte@Sun.COM 
3257836SJohn.Forte@Sun.COM 		map[i].inuse &= ~(1 << nsc_node_id());
3267836SJohn.Forte@Sun.COM 		if (nvmap) {
3277836SJohn.Forte@Sun.COM 			/*
3287836SJohn.Forte@Sun.COM 			 * if dirty, set the inuse bit so this area
3297836SJohn.Forte@Sun.COM 			 * will not be _nsc_global_zero'd on restart.
3307836SJohn.Forte@Sun.COM 			 */
3317836SJohn.Forte@Sun.COM 			if (mp && (mp->type & NSC_MEM_NVDIRTY)) {
3327836SJohn.Forte@Sun.COM 				map[i].inuse |= (1 << nsc_node_id());
3337836SJohn.Forte@Sun.COM 			}
3347836SJohn.Forte@Sun.COM 
3357836SJohn.Forte@Sun.COM 			(void) nsc_commit_mem(&map[i], &nvmap[i],
3367836SJohn.Forte@Sun.COM 			    sizeof (nsc_rmmap_t), nsc_cm_errhdlr);
3377836SJohn.Forte@Sun.COM 		}
3387836SJohn.Forte@Sun.COM 		mutex_exit(&_nsc_global_lock);
3397836SJohn.Forte@Sun.COM 		return;
3407836SJohn.Forte@Sun.COM 	}
3417836SJohn.Forte@Sun.COM 
3427836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_global_lock);
3437836SJohn.Forte@Sun.COM 
344*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!nsctl: _nsc_rmmap_free: invalid free");
3457836SJohn.Forte@Sun.COM }
3467836SJohn.Forte@Sun.COM 
3477836SJohn.Forte@Sun.COM 
3487836SJohn.Forte@Sun.COM /*
3497836SJohn.Forte@Sun.COM  * size_t
3507836SJohn.Forte@Sun.COM  * _nsc_rmmap_size (nsc_rmmap_t *map, char *name)
3517836SJohn.Forte@Sun.COM  *	Find size of area in map.
3527836SJohn.Forte@Sun.COM  *
3537836SJohn.Forte@Sun.COM  * Calling/Exit State:
3547836SJohn.Forte@Sun.COM  *	Returns the size of the specified area in the map,
3557836SJohn.Forte@Sun.COM  *	or 0 if it is currently unallocated.
3567836SJohn.Forte@Sun.COM  */
3577836SJohn.Forte@Sun.COM size_t
_nsc_rmmap_size(nsc_rmmap_t * map,char * name)3587836SJohn.Forte@Sun.COM _nsc_rmmap_size(nsc_rmmap_t *map, char *name)
3597836SJohn.Forte@Sun.COM {
3607836SJohn.Forte@Sun.COM 	int i, nslot = map[0].inuse;
3617836SJohn.Forte@Sun.COM 	size_t size = 0;
3627836SJohn.Forte@Sun.COM 
3637836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_global_lock);
3647836SJohn.Forte@Sun.COM 
3657836SJohn.Forte@Sun.COM 	for (i = 1; i < nslot; i++) {
3667836SJohn.Forte@Sun.COM 		if (!map[i].inuse || !map[i].size)
3677836SJohn.Forte@Sun.COM 			continue;
3687836SJohn.Forte@Sun.COM 
3697836SJohn.Forte@Sun.COM 		if (strncmp(map[i].name, name, _NSC_MAXNAME) == 0) {
3707836SJohn.Forte@Sun.COM 			size = map[i].size;
3717836SJohn.Forte@Sun.COM 			break;
3727836SJohn.Forte@Sun.COM 		}
3737836SJohn.Forte@Sun.COM 	}
3747836SJohn.Forte@Sun.COM 
3757836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_global_lock);
3767836SJohn.Forte@Sun.COM 	return (size);
3777836SJohn.Forte@Sun.COM }
3787836SJohn.Forte@Sun.COM 
3797836SJohn.Forte@Sun.COM 
3807836SJohn.Forte@Sun.COM /*
3817836SJohn.Forte@Sun.COM  * size_t
3827836SJohn.Forte@Sun.COM  * _nsc_rmmap_avail (nsc_rmmap_t *map)
3837836SJohn.Forte@Sun.COM  *	Find available space in global resource map.
3847836SJohn.Forte@Sun.COM  *
3857836SJohn.Forte@Sun.COM  * Calling/Exit State:
3867836SJohn.Forte@Sun.COM  *	Returns the size of the largest available area in
3877836SJohn.Forte@Sun.COM  *	the global resource map.
3887836SJohn.Forte@Sun.COM  */
3897836SJohn.Forte@Sun.COM size_t
_nsc_rmmap_avail(nsc_rmmap_t * map)3907836SJohn.Forte@Sun.COM _nsc_rmmap_avail(nsc_rmmap_t *map)
3917836SJohn.Forte@Sun.COM {
3927836SJohn.Forte@Sun.COM 	size_t size, avail = 0;
3937836SJohn.Forte@Sun.COM 	ulong_t offset;
3947836SJohn.Forte@Sun.COM 
3957836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_global_lock);
3967836SJohn.Forte@Sun.COM 
3977836SJohn.Forte@Sun.COM 	size = 1;
3987836SJohn.Forte@Sun.COM 	offset = map[0].offset;
3997836SJohn.Forte@Sun.COM 
4007836SJohn.Forte@Sun.COM 	while ((int32_t)offset < (map[0].offset + map[0].size))
4017836SJohn.Forte@Sun.COM 		if (!_nsc_rmmap_inuse(map, &offset, &size)) {
4027836SJohn.Forte@Sun.COM 			if (size > avail)
4037836SJohn.Forte@Sun.COM 				avail = size;
4047836SJohn.Forte@Sun.COM 			offset += size;
4057836SJohn.Forte@Sun.COM 			size = 1;
4067836SJohn.Forte@Sun.COM 		}
4077836SJohn.Forte@Sun.COM 
4087836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_global_lock);
4097836SJohn.Forte@Sun.COM 	return (avail);
4107836SJohn.Forte@Sun.COM }
4117836SJohn.Forte@Sun.COM 
4127836SJohn.Forte@Sun.COM 
4137836SJohn.Forte@Sun.COM /*
4147836SJohn.Forte@Sun.COM  * static int
4157836SJohn.Forte@Sun.COM  * _nsc_rmmap_inuse (nsc_rmmap_t *map, ulong_t *offsetp, size_t *sizep)
4167836SJohn.Forte@Sun.COM  *	Check if a section of the map is in use.
4177836SJohn.Forte@Sun.COM  *
4187836SJohn.Forte@Sun.COM  * Calling/Exit State:
4197836SJohn.Forte@Sun.COM  *	The global lock must be held across calls to the function.
4207836SJohn.Forte@Sun.COM  *
4217836SJohn.Forte@Sun.COM  *	Returns TRUE if the specified area is currently in use and
4227836SJohn.Forte@Sun.COM  *	updates offset to point just past the section that was found
4237836SJohn.Forte@Sun.COM  *	to be in use.
4247836SJohn.Forte@Sun.COM  *
4257836SJohn.Forte@Sun.COM  *	Otherwise, returns FALSE and updates size to reflect the
4267836SJohn.Forte@Sun.COM  *	amount of free space at the specified offset.
4277836SJohn.Forte@Sun.COM  *
4287836SJohn.Forte@Sun.COM  * Description:
4297836SJohn.Forte@Sun.COM  *	Checks the specified global map to determine if any part
4307836SJohn.Forte@Sun.COM  *	of the area is in use.
4317836SJohn.Forte@Sun.COM  */
4327836SJohn.Forte@Sun.COM static int
_nsc_rmmap_inuse(nsc_rmmap_t * map,ulong_t * offsetp,size_t * sizep)4337836SJohn.Forte@Sun.COM _nsc_rmmap_inuse(nsc_rmmap_t *map, ulong_t *offsetp, size_t *sizep)
4347836SJohn.Forte@Sun.COM {
4357836SJohn.Forte@Sun.COM 	size_t avail, size = (*sizep);
4367836SJohn.Forte@Sun.COM 	ulong_t offset = (*offsetp);
4377836SJohn.Forte@Sun.COM 	int i, nslot;
4387836SJohn.Forte@Sun.COM 
4397836SJohn.Forte@Sun.COM 	nslot = map[0].inuse;
4407836SJohn.Forte@Sun.COM 	avail = map[0].offset + map[0].size - offset;
4417836SJohn.Forte@Sun.COM 
4427836SJohn.Forte@Sun.COM 	for (i = 1; i < nslot; i++) {
4437836SJohn.Forte@Sun.COM 		if (!map[i].size || !map[i].inuse)
4447836SJohn.Forte@Sun.COM 			continue;
4457836SJohn.Forte@Sun.COM 		if ((int32_t)(offset + size) > map[i].offset &&
4467836SJohn.Forte@Sun.COM 		    (int32_t)offset < (map[i].offset + map[i].size)) {
4477836SJohn.Forte@Sun.COM 			(*offsetp) = map[i].offset + map[i].size;
4487836SJohn.Forte@Sun.COM 			return (1);
4497836SJohn.Forte@Sun.COM 		}
4507836SJohn.Forte@Sun.COM 
4517836SJohn.Forte@Sun.COM 		if (map[i].offset >= (int32_t)offset)
4527836SJohn.Forte@Sun.COM 			if (avail > map[i].offset - offset)
4537836SJohn.Forte@Sun.COM 				avail = map[i].offset - offset;
4547836SJohn.Forte@Sun.COM 	}
4557836SJohn.Forte@Sun.COM 
4567836SJohn.Forte@Sun.COM 	(*sizep) = avail;
4577836SJohn.Forte@Sun.COM 	return (0);
4587836SJohn.Forte@Sun.COM }
4597836SJohn.Forte@Sun.COM 
4607836SJohn.Forte@Sun.COM /*
4617836SJohn.Forte@Sun.COM  * int
4627836SJohn.Forte@Sun.COM  * nsc_delay_sig (clock_t tics)
4637836SJohn.Forte@Sun.COM  *	Delay for a number of clock ticks.
4647836SJohn.Forte@Sun.COM  *
4657836SJohn.Forte@Sun.COM  * Calling/Exit State:
4667836SJohn.Forte@Sun.COM  *	Returns FALSE if the delay was interrupted by a
4677836SJohn.Forte@Sun.COM  *	signal, TRUE otherwise.
4687836SJohn.Forte@Sun.COM  *
4697836SJohn.Forte@Sun.COM  * Description:
4707836SJohn.Forte@Sun.COM  *	Delays execution for the specified number of ticks
4717836SJohn.Forte@Sun.COM  *	or until a signal is received.
4727836SJohn.Forte@Sun.COM  */
4737836SJohn.Forte@Sun.COM int
nsc_delay_sig(clock_t tics)4747836SJohn.Forte@Sun.COM nsc_delay_sig(clock_t tics)
4757836SJohn.Forte@Sun.COM {
4767836SJohn.Forte@Sun.COM 	clock_t target, remain, rc;
4777836SJohn.Forte@Sun.COM 
4787836SJohn.Forte@Sun.COM 	target = nsc_lbolt() + tics;
4797836SJohn.Forte@Sun.COM 	rc = 1;
4807836SJohn.Forte@Sun.COM 
4817836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_delay_mutex);
4827836SJohn.Forte@Sun.COM 
4837836SJohn.Forte@Sun.COM 	/* CONSTCOND */
4847836SJohn.Forte@Sun.COM 
4857836SJohn.Forte@Sun.COM 	while (1) {
4867836SJohn.Forte@Sun.COM 		remain = target - nsc_lbolt();
4877836SJohn.Forte@Sun.COM 
4887836SJohn.Forte@Sun.COM 		if (remain <= 0 || rc == -1) {
4897836SJohn.Forte@Sun.COM 			/* timeout */
4907836SJohn.Forte@Sun.COM 			break;
4917836SJohn.Forte@Sun.COM 		}
4927836SJohn.Forte@Sun.COM 
4937836SJohn.Forte@Sun.COM 		rc = cv_timedwait_sig(&_nsc_delay_cv,
4947836SJohn.Forte@Sun.COM 		    &_nsc_delay_mutex, target);
4957836SJohn.Forte@Sun.COM 
4967836SJohn.Forte@Sun.COM 		if (rc == 0) {
4977836SJohn.Forte@Sun.COM 			/* signalled */
4987836SJohn.Forte@Sun.COM 			mutex_exit(&_nsc_delay_mutex);
4997836SJohn.Forte@Sun.COM 			return (FALSE);
5007836SJohn.Forte@Sun.COM 		}
5017836SJohn.Forte@Sun.COM 	}
5027836SJohn.Forte@Sun.COM 
5037836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_delay_mutex);
5047836SJohn.Forte@Sun.COM 
5057836SJohn.Forte@Sun.COM 	return (TRUE);
5067836SJohn.Forte@Sun.COM }
5077836SJohn.Forte@Sun.COM 
5087836SJohn.Forte@Sun.COM 
5097836SJohn.Forte@Sun.COM /*
5107836SJohn.Forte@Sun.COM  * void
5117836SJohn.Forte@Sun.COM  * nsc_sprintf (char *s, char *fmt, ...)
5127836SJohn.Forte@Sun.COM  *	String printf.
5137836SJohn.Forte@Sun.COM  *
5147836SJohn.Forte@Sun.COM  * Calling/Exit State:
5157836SJohn.Forte@Sun.COM  *	Builds a NULL terminated string in the buffer
5167836SJohn.Forte@Sun.COM  *	pointed to by 's', using the format 'fmt'.
5177836SJohn.Forte@Sun.COM  *
5187836SJohn.Forte@Sun.COM  * Description:
5197836SJohn.Forte@Sun.COM  *	Simple version of sprintf supporting fairly
5207836SJohn.Forte@Sun.COM  *	basic formats.
5217836SJohn.Forte@Sun.COM  */
5227836SJohn.Forte@Sun.COM 
5237836SJohn.Forte@Sun.COM /* PRINTFLIKE2 */
5247836SJohn.Forte@Sun.COM 
5257836SJohn.Forte@Sun.COM void
nsc_sprintf(char * s,char * fmt,...)5267836SJohn.Forte@Sun.COM nsc_sprintf(char *s, char *fmt, ...)
5277836SJohn.Forte@Sun.COM {
5287836SJohn.Forte@Sun.COM 	int alt, zero, len;
5297836SJohn.Forte@Sun.COM 	char c, *cp;
5307836SJohn.Forte@Sun.COM 	va_list p;
5317836SJohn.Forte@Sun.COM 
5327836SJohn.Forte@Sun.COM 	va_start(p, fmt);
5337836SJohn.Forte@Sun.COM 
5347836SJohn.Forte@Sun.COM 	/* CONSTCOND */
5357836SJohn.Forte@Sun.COM 
5367836SJohn.Forte@Sun.COM 	while (1) {
5377836SJohn.Forte@Sun.COM 		alt = 0, zero = 0, len = 0;
5387836SJohn.Forte@Sun.COM 
5397836SJohn.Forte@Sun.COM 		if ((c = *fmt++) != '%') {
5407836SJohn.Forte@Sun.COM 			if (!c)
5417836SJohn.Forte@Sun.COM 				break;
5427836SJohn.Forte@Sun.COM 			*s++ = c;
5437836SJohn.Forte@Sun.COM 			continue;
5447836SJohn.Forte@Sun.COM 		}
5457836SJohn.Forte@Sun.COM 
5467836SJohn.Forte@Sun.COM 		if ((c = *fmt++) == 0) {
5477836SJohn.Forte@Sun.COM 			*s++ = '%';
5487836SJohn.Forte@Sun.COM 			break;
5497836SJohn.Forte@Sun.COM 		}
5507836SJohn.Forte@Sun.COM 
5517836SJohn.Forte@Sun.COM 		alt = (c == '#');
5527836SJohn.Forte@Sun.COM 		if (alt && !(c = *fmt++))
5537836SJohn.Forte@Sun.COM 			break;
5547836SJohn.Forte@Sun.COM 
5557836SJohn.Forte@Sun.COM 		zero = (c == '0');
5567836SJohn.Forte@Sun.COM 		if (zero && !(c = *fmt++))
5577836SJohn.Forte@Sun.COM 			break;
5587836SJohn.Forte@Sun.COM 
5597836SJohn.Forte@Sun.COM 		while ((len ? '0' : '1') <= c && c <= '9') {
5607836SJohn.Forte@Sun.COM 			len = (len * 10) + (c - '0');
5617836SJohn.Forte@Sun.COM 			if (!(c = *fmt++))
5627836SJohn.Forte@Sun.COM 				break;
5637836SJohn.Forte@Sun.COM 		}
5647836SJohn.Forte@Sun.COM 
5657836SJohn.Forte@Sun.COM 		if (c == 's') {
5667836SJohn.Forte@Sun.COM 			cp = (char *)va_arg(p, caddr_t);
5677836SJohn.Forte@Sun.COM 			while (*cp)
5687836SJohn.Forte@Sun.COM 				*s++ = *cp++;
5697836SJohn.Forte@Sun.COM 			continue;
5707836SJohn.Forte@Sun.COM 		}
5717836SJohn.Forte@Sun.COM 
5727836SJohn.Forte@Sun.COM 		if (c == 'd' || c == 'u') {
5737836SJohn.Forte@Sun.COM 			_nsc_sprint_dec(&s, va_arg(p, int), zero, len);
5747836SJohn.Forte@Sun.COM 			continue;
5757836SJohn.Forte@Sun.COM 		}
5767836SJohn.Forte@Sun.COM 
5777836SJohn.Forte@Sun.COM 		if (c == 'x' || c == 'X') {
5787836SJohn.Forte@Sun.COM 			_nsc_sprint_hex(&s, va_arg(p, uint_t),
5797836SJohn.Forte@Sun.COM 			    (c == 'X'), alt, zero, len);
5807836SJohn.Forte@Sun.COM 			continue;
5817836SJohn.Forte@Sun.COM 		}
5827836SJohn.Forte@Sun.COM 
5837836SJohn.Forte@Sun.COM 		*s++ = '%';
5847836SJohn.Forte@Sun.COM 		if (alt)
5857836SJohn.Forte@Sun.COM 			*s++ = '#';
5867836SJohn.Forte@Sun.COM 		if (zero)
5877836SJohn.Forte@Sun.COM 			*s++ = '0';
5887836SJohn.Forte@Sun.COM 
5897836SJohn.Forte@Sun.COM 		if (len)
5907836SJohn.Forte@Sun.COM 			_nsc_sprint_dec(&s, len, 0, 0);
5917836SJohn.Forte@Sun.COM 		*s++ = c;
5927836SJohn.Forte@Sun.COM 	}
5937836SJohn.Forte@Sun.COM 
5947836SJohn.Forte@Sun.COM 	if (alt || zero || len) {
5957836SJohn.Forte@Sun.COM 		*s++ = '%';
5967836SJohn.Forte@Sun.COM 
5977836SJohn.Forte@Sun.COM 		if (alt)
5987836SJohn.Forte@Sun.COM 			*s++ = '#';
5997836SJohn.Forte@Sun.COM 		if (zero)
6007836SJohn.Forte@Sun.COM 			*s++ = '0';
6017836SJohn.Forte@Sun.COM 
6027836SJohn.Forte@Sun.COM 		if (len)
6037836SJohn.Forte@Sun.COM 			_nsc_sprint_dec(&s, len, 0, 0);
6047836SJohn.Forte@Sun.COM 	}
6057836SJohn.Forte@Sun.COM 
6067836SJohn.Forte@Sun.COM 	va_end(p);
6077836SJohn.Forte@Sun.COM 	*s = 0;
6087836SJohn.Forte@Sun.COM }
6097836SJohn.Forte@Sun.COM 
6107836SJohn.Forte@Sun.COM 
6117836SJohn.Forte@Sun.COM /*
6127836SJohn.Forte@Sun.COM  * static void
6137836SJohn.Forte@Sun.COM  * _nsc_sprint_dec (char **sptr, int n, int zero, int len)
6147836SJohn.Forte@Sun.COM  *	Decimal to string conversion.
6157836SJohn.Forte@Sun.COM  *
6167836SJohn.Forte@Sun.COM  * Calling/Exit State:
6177836SJohn.Forte@Sun.COM  *	Stores a character representation of 'n' in the
6187836SJohn.Forte@Sun.COM  *	buffer referenced by 'sptr' and	updates the pointer
6197836SJohn.Forte@Sun.COM  *	accordingly.
6207836SJohn.Forte@Sun.COM  *
6217836SJohn.Forte@Sun.COM  * Description:
6227836SJohn.Forte@Sun.COM  *	Generates a string representation of a signed decimal
6237836SJohn.Forte@Sun.COM  *	integer.
6247836SJohn.Forte@Sun.COM  */
6257836SJohn.Forte@Sun.COM 
6267836SJohn.Forte@Sun.COM static void
_nsc_sprint_dec(char ** sptr,int n,int zero,int len)6277836SJohn.Forte@Sun.COM _nsc_sprint_dec(char **sptr, int n, int zero, int len)
6287836SJohn.Forte@Sun.COM {
6297836SJohn.Forte@Sun.COM 	unsigned int v = (n < 0) ? (-n) : n;
6307836SJohn.Forte@Sun.COM 	char c[20];
6317836SJohn.Forte@Sun.COM 	int i;
6327836SJohn.Forte@Sun.COM 
6337836SJohn.Forte@Sun.COM 	for (i = 0; v; i++) {
6347836SJohn.Forte@Sun.COM 		c[i] = (v % 10) + '0';
6357836SJohn.Forte@Sun.COM 		v /= 10;
6367836SJohn.Forte@Sun.COM 	}
6377836SJohn.Forte@Sun.COM 
6387836SJohn.Forte@Sun.COM 	len -= (i ? i : 1);
6397836SJohn.Forte@Sun.COM 
6407836SJohn.Forte@Sun.COM 	if (n < 0 && !zero)
6417836SJohn.Forte@Sun.COM 		for (len--; len > 0; len--)
6427836SJohn.Forte@Sun.COM 			*(*sptr)++ = ' ';
6437836SJohn.Forte@Sun.COM 
6447836SJohn.Forte@Sun.COM 	if (n < 0) {
6457836SJohn.Forte@Sun.COM 		*(*sptr)++ = '-';
6467836SJohn.Forte@Sun.COM 		len--;
6477836SJohn.Forte@Sun.COM 	}
6487836SJohn.Forte@Sun.COM 
6497836SJohn.Forte@Sun.COM 	for (; len > 0; len--)
6507836SJohn.Forte@Sun.COM 		*(*sptr)++ = (zero ? '0' : ' ');
6517836SJohn.Forte@Sun.COM 
6527836SJohn.Forte@Sun.COM 	if (!i)
6537836SJohn.Forte@Sun.COM 		*(*sptr)++ = '0';
6547836SJohn.Forte@Sun.COM 
6557836SJohn.Forte@Sun.COM 	while (i--)
6567836SJohn.Forte@Sun.COM 		*(*sptr)++ = c[i];
6577836SJohn.Forte@Sun.COM }
6587836SJohn.Forte@Sun.COM 
6597836SJohn.Forte@Sun.COM 
6607836SJohn.Forte@Sun.COM /*
6617836SJohn.Forte@Sun.COM  * static void
6627836SJohn.Forte@Sun.COM  * _nsc_sprint_hex (char **sptr, unsigned int v,
6637836SJohn.Forte@Sun.COM  *			int up, int alt, int zero, int len)
6647836SJohn.Forte@Sun.COM  *	Hexadecimal to string conversion.
6657836SJohn.Forte@Sun.COM  *
6667836SJohn.Forte@Sun.COM  * Calling/Exit State:
6677836SJohn.Forte@Sun.COM  *	Stores a character representation of 'v' in the
6687836SJohn.Forte@Sun.COM  *	buffer referenced by 'sptr' and	updates the pointer
6697836SJohn.Forte@Sun.COM  *	accordingly.
6707836SJohn.Forte@Sun.COM  *
6717836SJohn.Forte@Sun.COM  * Description:
6727836SJohn.Forte@Sun.COM  *	Generates a string representation of an unsigned
6737836SJohn.Forte@Sun.COM  *	hexadecimal integer.
6747836SJohn.Forte@Sun.COM  */
6757836SJohn.Forte@Sun.COM 
6767836SJohn.Forte@Sun.COM static void
_nsc_sprint_hex(char ** sptr,uint_t v,int up,int alt,int zero,int len)6777836SJohn.Forte@Sun.COM _nsc_sprint_hex(char **sptr, uint_t v, int up, int alt, int zero, int len)
6787836SJohn.Forte@Sun.COM {
6797836SJohn.Forte@Sun.COM 	char *str = "0123456789abcdef";
6807836SJohn.Forte@Sun.COM 	char c[20];
6817836SJohn.Forte@Sun.COM 	int i;
6827836SJohn.Forte@Sun.COM 
6837836SJohn.Forte@Sun.COM 	if (up)
6847836SJohn.Forte@Sun.COM 		str = "0123456789ABCDEF";
6857836SJohn.Forte@Sun.COM 
6867836SJohn.Forte@Sun.COM 	for (i = 0; v; i++) {
6877836SJohn.Forte@Sun.COM 		c[i] = str[(v % 16)];
6887836SJohn.Forte@Sun.COM 		v /= 16;
6897836SJohn.Forte@Sun.COM 	}
6907836SJohn.Forte@Sun.COM 
6917836SJohn.Forte@Sun.COM 	if (alt) {
6927836SJohn.Forte@Sun.COM 		*(*sptr)++ = '0';
6937836SJohn.Forte@Sun.COM 		*(*sptr)++ = (up ? 'X' : 'x');
6947836SJohn.Forte@Sun.COM 	}
6957836SJohn.Forte@Sun.COM 
6967836SJohn.Forte@Sun.COM 	for (len -= (i ? i : 1); len > 0; len--)
6977836SJohn.Forte@Sun.COM 		*(*sptr)++ = (zero ? '0' : ' ');
6987836SJohn.Forte@Sun.COM 
6997836SJohn.Forte@Sun.COM 	if (!i)
7007836SJohn.Forte@Sun.COM 		*(*sptr)++ = '0';
7017836SJohn.Forte@Sun.COM 	while (i--)
7027836SJohn.Forte@Sun.COM 		*(*sptr)++ = c[i];
7037836SJohn.Forte@Sun.COM }
7047836SJohn.Forte@Sun.COM 
7057836SJohn.Forte@Sun.COM 
7067836SJohn.Forte@Sun.COM /*
7077836SJohn.Forte@Sun.COM  * char *
7087836SJohn.Forte@Sun.COM  * nsc_strdup (char *s)
7097836SJohn.Forte@Sun.COM  *	Duplicate string.
7107836SJohn.Forte@Sun.COM  *
7117836SJohn.Forte@Sun.COM  * Calling/Exit State:
7127836SJohn.Forte@Sun.COM  *	Returns the address of the new string.
7137836SJohn.Forte@Sun.COM  *
7147836SJohn.Forte@Sun.COM  * Description:
7157836SJohn.Forte@Sun.COM  *	Allocates a suitably sized area of memory and
7167836SJohn.Forte@Sun.COM  *	copies the string into it. The string should be
7177836SJohn.Forte@Sun.COM  *	free'd using nsc_strfree().
7187836SJohn.Forte@Sun.COM  */
7197836SJohn.Forte@Sun.COM char *
nsc_strdup(char * s)7207836SJohn.Forte@Sun.COM nsc_strdup(char *s)
7217836SJohn.Forte@Sun.COM {
7227836SJohn.Forte@Sun.COM 	char *cp;
7237836SJohn.Forte@Sun.COM 
7247836SJohn.Forte@Sun.COM 	if (s == NULL)
7257836SJohn.Forte@Sun.COM 		return (NULL);
7267836SJohn.Forte@Sun.COM 
7277836SJohn.Forte@Sun.COM 	cp = nsc_kmem_alloc(strlen(s) + 1, KM_SLEEP, NULL);
7287836SJohn.Forte@Sun.COM 	(void) strcpy(cp, s);
7297836SJohn.Forte@Sun.COM 	return (cp);
7307836SJohn.Forte@Sun.COM }
7317836SJohn.Forte@Sun.COM 
7327836SJohn.Forte@Sun.COM 
7337836SJohn.Forte@Sun.COM /*
7347836SJohn.Forte@Sun.COM  * void
7357836SJohn.Forte@Sun.COM  * nsc_strfree (char *s)
7367836SJohn.Forte@Sun.COM  *	Free string.
7377836SJohn.Forte@Sun.COM  *
7387836SJohn.Forte@Sun.COM  * Description:
7397836SJohn.Forte@Sun.COM  *	Frees a string previously allocated by nsc_strdup.
7407836SJohn.Forte@Sun.COM  */
7417836SJohn.Forte@Sun.COM void
nsc_strfree(char * s)7427836SJohn.Forte@Sun.COM nsc_strfree(char *s)
7437836SJohn.Forte@Sun.COM {
7447836SJohn.Forte@Sun.COM 	if (s)
7457836SJohn.Forte@Sun.COM 		nsc_kmem_free(s, strlen(s) + 1);
7467836SJohn.Forte@Sun.COM }
7477836SJohn.Forte@Sun.COM 
7487836SJohn.Forte@Sun.COM 
7497836SJohn.Forte@Sun.COM /*
7507836SJohn.Forte@Sun.COM  * int
7517836SJohn.Forte@Sun.COM  * nsc_strmatch (char *s, char *pat)
7527836SJohn.Forte@Sun.COM  *	Match string against pattern.
7537836SJohn.Forte@Sun.COM  *
7547836SJohn.Forte@Sun.COM  * Calling/Exit State:
7557836SJohn.Forte@Sun.COM  *	Returns TRUE if the string matches against the
7567836SJohn.Forte@Sun.COM  *	pattern, FALSE otherwise.
7577836SJohn.Forte@Sun.COM  *
7587836SJohn.Forte@Sun.COM  * Description:
7597836SJohn.Forte@Sun.COM  *	Compares string against regular expression which
7607836SJohn.Forte@Sun.COM  *	can contain '*', '?' and '[]' constructs.
7617836SJohn.Forte@Sun.COM  */
7627836SJohn.Forte@Sun.COM int
nsc_strmatch(char * s,char * pat)7637836SJohn.Forte@Sun.COM nsc_strmatch(char *s, char *pat)
7647836SJohn.Forte@Sun.COM {
7657836SJohn.Forte@Sun.COM 	int neg;
7667836SJohn.Forte@Sun.COM 
7677836SJohn.Forte@Sun.COM 	for (; *pat; pat++, s++) {
7687836SJohn.Forte@Sun.COM 		if (*pat == '*') {
7697836SJohn.Forte@Sun.COM 			while (*pat == '*')
7707836SJohn.Forte@Sun.COM 				pat++;
7717836SJohn.Forte@Sun.COM 
7727836SJohn.Forte@Sun.COM 			if (!*pat)
7737836SJohn.Forte@Sun.COM 				return (1);
7747836SJohn.Forte@Sun.COM 
7757836SJohn.Forte@Sun.COM 			for (; *s; s++)
7767836SJohn.Forte@Sun.COM 				if (*pat == '[' || *pat == '?' || *pat == *s)
7777836SJohn.Forte@Sun.COM 					if (nsc_strmatch(s, pat))
7787836SJohn.Forte@Sun.COM 						return (1);
7797836SJohn.Forte@Sun.COM 			return (0);
7807836SJohn.Forte@Sun.COM 		}
7817836SJohn.Forte@Sun.COM 
7827836SJohn.Forte@Sun.COM 		if (!*s)
7837836SJohn.Forte@Sun.COM 			return (0);
7847836SJohn.Forte@Sun.COM 
7857836SJohn.Forte@Sun.COM 		if (*pat == '[') {
7867836SJohn.Forte@Sun.COM 			if ((neg = (*++pat == '^')) != 0)
7877836SJohn.Forte@Sun.COM 				pat++;
7887836SJohn.Forte@Sun.COM 
7897836SJohn.Forte@Sun.COM 			while (*pat) {
7907836SJohn.Forte@Sun.COM 				if (*pat == *s)
7917836SJohn.Forte@Sun.COM 					break;
7927836SJohn.Forte@Sun.COM 
7937836SJohn.Forte@Sun.COM 				if (pat[1] == '-' && pat[2] != ']') {
7947836SJohn.Forte@Sun.COM 					if (*pat <= *s && *s <= pat[2])
7957836SJohn.Forte@Sun.COM 						break;
7967836SJohn.Forte@Sun.COM 					pat += 2;
7977836SJohn.Forte@Sun.COM 				}
7987836SJohn.Forte@Sun.COM 
7997836SJohn.Forte@Sun.COM 				if (*++pat == ']') {
8007836SJohn.Forte@Sun.COM 					if (neg)
8017836SJohn.Forte@Sun.COM 						goto lp;
8027836SJohn.Forte@Sun.COM 					else
8037836SJohn.Forte@Sun.COM 						return (0);
8047836SJohn.Forte@Sun.COM 				}
8057836SJohn.Forte@Sun.COM 			}
8067836SJohn.Forte@Sun.COM 
8077836SJohn.Forte@Sun.COM 			while (*pat && *++pat != ']')
8087836SJohn.Forte@Sun.COM 			;
8097836SJohn.Forte@Sun.COM 
8107836SJohn.Forte@Sun.COM 			if (!*pat || neg)
8117836SJohn.Forte@Sun.COM 				return (0);
812*9093SRamana.Srikanth@Sun.COM lp:
8137836SJohn.Forte@Sun.COM 			continue;
8147836SJohn.Forte@Sun.COM 		}
8157836SJohn.Forte@Sun.COM 
8167836SJohn.Forte@Sun.COM 		if (*pat != '?' && *pat != *s)
8177836SJohn.Forte@Sun.COM 			return (0);
8187836SJohn.Forte@Sun.COM 	}
8197836SJohn.Forte@Sun.COM 
8207836SJohn.Forte@Sun.COM 	return (!*s);
8217836SJohn.Forte@Sun.COM }
8227836SJohn.Forte@Sun.COM 
8237836SJohn.Forte@Sun.COM 
8247836SJohn.Forte@Sun.COM /*
8257836SJohn.Forte@Sun.COM  * uint64_t
8267836SJohn.Forte@Sun.COM  * nsc_strhash(char *str)
8277836SJohn.Forte@Sun.COM  *	Calculate a simple hash for the specified string
8287836SJohn.Forte@Sun.COM  *
8297836SJohn.Forte@Sun.COM  * Calling/Exit State:
8307836SJohn.Forte@Sun.COM  *	Returns a simple hash of the NULL terminated string, str.
8317836SJohn.Forte@Sun.COM  *
8327836SJohn.Forte@Sun.COM  * Description:
8337836SJohn.Forte@Sun.COM  */
8347836SJohn.Forte@Sun.COM uint64_t
nsc_strhash(char * str)8357836SJohn.Forte@Sun.COM nsc_strhash(char *str)
8367836SJohn.Forte@Sun.COM {
8377836SJohn.Forte@Sun.COM 	uint64_t hash = (uint64_t)0;
8387836SJohn.Forte@Sun.COM 
8397836SJohn.Forte@Sun.COM 	if (str == NULL)
8407836SJohn.Forte@Sun.COM 		return (hash);
8417836SJohn.Forte@Sun.COM 
8427836SJohn.Forte@Sun.COM 	while (*str != '\0') {
8437836SJohn.Forte@Sun.COM 		hash <<= 1;
8447836SJohn.Forte@Sun.COM 		hash += (uint64_t)*str;
8457836SJohn.Forte@Sun.COM 		str++;
8467836SJohn.Forte@Sun.COM 	}
8477836SJohn.Forte@Sun.COM 
8487836SJohn.Forte@Sun.COM 	return (hash);
8497836SJohn.Forte@Sun.COM }
8507836SJohn.Forte@Sun.COM 
8517836SJohn.Forte@Sun.COM 
8527836SJohn.Forte@Sun.COM /*
8537836SJohn.Forte@Sun.COM  * int
8547836SJohn.Forte@Sun.COM  * nsc_fatal(void)
8557836SJohn.Forte@Sun.COM  *	Fatal error stub function
8567836SJohn.Forte@Sun.COM  *
8577836SJohn.Forte@Sun.COM  * Calling/Exit State:
8587836SJohn.Forte@Sun.COM  *	Returns EINVAL (non-DEBUG) or forces a panic.
8597836SJohn.Forte@Sun.COM  *
8607836SJohn.Forte@Sun.COM  * Description:
8617836SJohn.Forte@Sun.COM  *	This is a stub function suitable for default actions in
8627836SJohn.Forte@Sun.COM  *	nsctl i/o provider definitions. It should be used when
8637836SJohn.Forte@Sun.COM  *	calling the stub would be a programming error. The most
8647836SJohn.Forte@Sun.COM  *	common reason for nsc_fatal() being called is that an
8657836SJohn.Forte@Sun.COM  *	nsctl client module has called an nsc_fd_t i/o function
8667836SJohn.Forte@Sun.COM  *	without the fd already reserved.
8677836SJohn.Forte@Sun.COM  *
8687836SJohn.Forte@Sun.COM  *	The function will display a diagnostic message and when
8697836SJohn.Forte@Sun.COM  *	built -DDEBUG will force a panic and display the textual
8707836SJohn.Forte@Sun.COM  *	name of the symbol closest to the caller address of this
8717836SJohn.Forte@Sun.COM  *	function.
8727836SJohn.Forte@Sun.COM  */
8737836SJohn.Forte@Sun.COM int
nsc_fatal()8747836SJohn.Forte@Sun.COM nsc_fatal()
8757836SJohn.Forte@Sun.COM {
8767836SJohn.Forte@Sun.COM 	void *caller = nsc_caller();
8777836SJohn.Forte@Sun.COM #ifdef DEBUG
8787836SJohn.Forte@Sun.COM 	caddr_t caller_sym = NULL;
8797836SJohn.Forte@Sun.COM 	ulong_t offset = 0UL;
8807836SJohn.Forte@Sun.COM 
8817836SJohn.Forte@Sun.COM #ifndef DS_DDICT
8827836SJohn.Forte@Sun.COM 	caller_sym = kobj_getsymname((uintptr_t)caller, &offset);
8837836SJohn.Forte@Sun.COM #endif	/* !DS_DDICT */
8847836SJohn.Forte@Sun.COM 
885*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!nsctl: nsc_fatal called at 0x%p (%s+0x%lx)",
8867836SJohn.Forte@Sun.COM 	    caller, caller_sym ? caller_sym : "?", offset);
8877836SJohn.Forte@Sun.COM 
8887836SJohn.Forte@Sun.COM 	/*
8897836SJohn.Forte@Sun.COM 	 * Force TRAP due to NULL pointer dereference
8907836SJohn.Forte@Sun.COM 	 * - CE_PANIC can result in the stack trace being unreadable
8917836SJohn.Forte@Sun.COM 	 * by (k)adb.
8927836SJohn.Forte@Sun.COM 	 */
8937836SJohn.Forte@Sun.COM 	*(int *)0 = 0x12345678;
8947836SJohn.Forte@Sun.COM 
8957836SJohn.Forte@Sun.COM #else	/* !DEBUG */
8967836SJohn.Forte@Sun.COM 
897*9093SRamana.Srikanth@Sun.COM 	cmn_err(CE_WARN, "!nsctl: nsc_fatal called at 0x%p", caller);
8987836SJohn.Forte@Sun.COM 
8997836SJohn.Forte@Sun.COM #endif	/* DEBUG */
9007836SJohn.Forte@Sun.COM 
9017836SJohn.Forte@Sun.COM 	return (EINVAL);
9027836SJohn.Forte@Sun.COM }
9037836SJohn.Forte@Sun.COM 
9047836SJohn.Forte@Sun.COM 
nsc_null()9057836SJohn.Forte@Sun.COM int nsc_null() { return (0); }
nsc_true()9067836SJohn.Forte@Sun.COM int nsc_true() { return (1); }
nsc_inval()9077836SJohn.Forte@Sun.COM int nsc_inval() { return (-1); }
nsc_ioerr()9087836SJohn.Forte@Sun.COM int nsc_ioerr() { return (EIO); }
9097836SJohn.Forte@Sun.COM 
9107836SJohn.Forte@Sun.COM /*ARGSUSED*/
9117836SJohn.Forte@Sun.COM int
nsc_commit_mem(void * src,void * dst,size_t len,nsc_mem_err_cb err_action)9127836SJohn.Forte@Sun.COM nsc_commit_mem(void *src, void *dst, size_t len, nsc_mem_err_cb err_action)
9137836SJohn.Forte@Sun.COM {
9147836SJohn.Forte@Sun.COM 
9157836SJohn.Forte@Sun.COM 	return (0);
9167836SJohn.Forte@Sun.COM }
9177836SJohn.Forte@Sun.COM 
9187836SJohn.Forte@Sun.COM static int _nsc_nvmem_errs;
9197836SJohn.Forte@Sun.COM 
9207836SJohn.Forte@Sun.COM /* ARGSUSED */
9217836SJohn.Forte@Sun.COM void
nsc_cm_errhdlr(void * src,void * dst,size_t len,int errval)9227836SJohn.Forte@Sun.COM nsc_cm_errhdlr(void *src, void *dst, size_t len, int errval)
9237836SJohn.Forte@Sun.COM {
9247836SJohn.Forte@Sun.COM 	static int _nsc_baddma_already_seen = 0;
9257836SJohn.Forte@Sun.COM 
9267836SJohn.Forte@Sun.COM 	if (!(_nsc_baddma_already_seen % 100)) {
927*9093SRamana.Srikanth@Sun.COM 		cmn_err(CE_WARN, "!nsc_cm_errhdlr: media down, forced_wrthru");
9287836SJohn.Forte@Sun.COM 
9297836SJohn.Forte@Sun.COM 		_nsc_baddma_already_seen += 1;
9307836SJohn.Forte@Sun.COM 
9317836SJohn.Forte@Sun.COM 		if (_nsc_baddma_already_seen >= 100) {
9327836SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
933*9093SRamana.Srikanth@Sun.COM 			    "!nsc_cm_errhdlr: this message "
9347836SJohn.Forte@Sun.COM 			    "displayed every 100 errors");
9357836SJohn.Forte@Sun.COM 		}
9367836SJohn.Forte@Sun.COM 	}
9377836SJohn.Forte@Sun.COM 
9387836SJohn.Forte@Sun.COM 	(void) nsc_node_hints_set(NSC_FORCED_WRTHRU);
9397836SJohn.Forte@Sun.COM 
9407836SJohn.Forte@Sun.COM 	_nsc_nvmem_errs++;
9417836SJohn.Forte@Sun.COM }
9427836SJohn.Forte@Sun.COM 
9437836SJohn.Forte@Sun.COM 
9447836SJohn.Forte@Sun.COM void
_nsc_init_svc(void)9457836SJohn.Forte@Sun.COM _nsc_init_svc(void)
9467836SJohn.Forte@Sun.COM {
9477836SJohn.Forte@Sun.COM 	mutex_init(&_nsc_svc_mutex, NULL, MUTEX_DRIVER, NULL);
9487836SJohn.Forte@Sun.COM 	mutex_init(&_nsc_delay_mutex, NULL, MUTEX_DRIVER, NULL);
9497836SJohn.Forte@Sun.COM 	cv_init(&_nsc_delay_cv, NULL, CV_DRIVER, NULL);
9507836SJohn.Forte@Sun.COM }
9517836SJohn.Forte@Sun.COM 
9527836SJohn.Forte@Sun.COM 
9537836SJohn.Forte@Sun.COM void
_nsc_deinit_svc(void)9547836SJohn.Forte@Sun.COM _nsc_deinit_svc(void)
9557836SJohn.Forte@Sun.COM {
9567836SJohn.Forte@Sun.COM 	if (_nsc_services != NULL) {
9577836SJohn.Forte@Sun.COM 		cmn_err(CE_PANIC,
958*9093SRamana.Srikanth@Sun.COM 		    "nsctl: services registered in _nsc_deinit_svc");
9597836SJohn.Forte@Sun.COM 		/* NOTREACHED */
9607836SJohn.Forte@Sun.COM 	}
9617836SJohn.Forte@Sun.COM 
9627836SJohn.Forte@Sun.COM 	cv_destroy(&_nsc_delay_cv);
9637836SJohn.Forte@Sun.COM 	mutex_destroy(&_nsc_delay_mutex);
9647836SJohn.Forte@Sun.COM 	mutex_destroy(&_nsc_svc_mutex);
9657836SJohn.Forte@Sun.COM }
9667836SJohn.Forte@Sun.COM 
9677836SJohn.Forte@Sun.COM 
9687836SJohn.Forte@Sun.COM nsc_svc_t *
nsc_register_svc(char * name,void (* service_fn)(intptr_t))9697836SJohn.Forte@Sun.COM nsc_register_svc(char *name, void (*service_fn)(intptr_t))
9707836SJohn.Forte@Sun.COM {
9717836SJohn.Forte@Sun.COM 	nsc_service_t *sp, *new;
9727836SJohn.Forte@Sun.COM 	nsc_svc_t *svc;
9737836SJohn.Forte@Sun.COM 
9747836SJohn.Forte@Sun.COM 	new = nsc_kmem_zalloc(sizeof (*new), KM_SLEEP, 0);
9757836SJohn.Forte@Sun.COM 	if (new == NULL)
9767836SJohn.Forte@Sun.COM 		return (NULL);
9777836SJohn.Forte@Sun.COM 
9787836SJohn.Forte@Sun.COM 	svc = nsc_kmem_zalloc(sizeof (*svc), KM_SLEEP, 0);
9797836SJohn.Forte@Sun.COM 	if (svc == NULL) {
9807836SJohn.Forte@Sun.COM 		nsc_kmem_free(new, sizeof (*new));
9817836SJohn.Forte@Sun.COM 		return (NULL);
9827836SJohn.Forte@Sun.COM 	}
9837836SJohn.Forte@Sun.COM 
9847836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_svc_mutex);
9857836SJohn.Forte@Sun.COM 
9867836SJohn.Forte@Sun.COM 	for (sp = _nsc_services; sp != NULL; sp = sp->s_next)
9877836SJohn.Forte@Sun.COM 		if (strcmp(name, sp->s_name) == 0)
9887836SJohn.Forte@Sun.COM 			break;
9897836SJohn.Forte@Sun.COM 
9907836SJohn.Forte@Sun.COM 	if (sp == NULL) {
9917836SJohn.Forte@Sun.COM 		sp = new;
9927836SJohn.Forte@Sun.COM 		sp->s_name = nsc_strdup(name);
9937836SJohn.Forte@Sun.COM 		if (sp->s_name == NULL) {
9947836SJohn.Forte@Sun.COM 			mutex_exit(&_nsc_svc_mutex);
9957836SJohn.Forte@Sun.COM 			nsc_kmem_free(new, sizeof (*new));
9967836SJohn.Forte@Sun.COM 			nsc_kmem_free(svc, sizeof (*svc));
9977836SJohn.Forte@Sun.COM 			return (NULL);
9987836SJohn.Forte@Sun.COM 		}
9997836SJohn.Forte@Sun.COM 
10007836SJohn.Forte@Sun.COM 		rw_init(&sp->s_rwlock, NULL, RW_DRIVER, NULL);
10017836SJohn.Forte@Sun.COM 		sp->s_next = _nsc_services;
10027836SJohn.Forte@Sun.COM 		_nsc_services = sp;
10037836SJohn.Forte@Sun.COM 	}
10047836SJohn.Forte@Sun.COM 
10057836SJohn.Forte@Sun.COM 	rw_enter(&sp->s_rwlock, RW_WRITER);
10067836SJohn.Forte@Sun.COM 
10077836SJohn.Forte@Sun.COM 	svc->svc_fn = service_fn;
10087836SJohn.Forte@Sun.COM 	svc->svc_svc = sp;
10097836SJohn.Forte@Sun.COM 
10107836SJohn.Forte@Sun.COM 	if (svc->svc_fn != NULL) {
10117836SJohn.Forte@Sun.COM 		svc->svc_next = sp->s_servers;
10127836SJohn.Forte@Sun.COM 		sp->s_servers = svc;
10137836SJohn.Forte@Sun.COM 	} else {
10147836SJohn.Forte@Sun.COM 		svc->svc_next = sp->s_clients;
10157836SJohn.Forte@Sun.COM 		sp->s_clients = svc;
10167836SJohn.Forte@Sun.COM 	}
10177836SJohn.Forte@Sun.COM 
10187836SJohn.Forte@Sun.COM 	rw_exit(&sp->s_rwlock);
10197836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_svc_mutex);
10207836SJohn.Forte@Sun.COM 
10217836SJohn.Forte@Sun.COM 	if (sp != new)
10227836SJohn.Forte@Sun.COM 		nsc_kmem_free(new, sizeof (*new));
10237836SJohn.Forte@Sun.COM 
10247836SJohn.Forte@Sun.COM 	return (svc);
10257836SJohn.Forte@Sun.COM }
10267836SJohn.Forte@Sun.COM 
10277836SJohn.Forte@Sun.COM 
10287836SJohn.Forte@Sun.COM int
nsc_unregister_svc(nsc_svc_t * svc)10297836SJohn.Forte@Sun.COM nsc_unregister_svc(nsc_svc_t *svc)
10307836SJohn.Forte@Sun.COM {
10317836SJohn.Forte@Sun.COM 	nsc_service_t *sp, **spp;
10327836SJohn.Forte@Sun.COM 	nsc_svc_t **svcp;
10337836SJohn.Forte@Sun.COM 
10347836SJohn.Forte@Sun.COM 	if (svc == NULL)
10357836SJohn.Forte@Sun.COM 		return (EINVAL);
10367836SJohn.Forte@Sun.COM 
10377836SJohn.Forte@Sun.COM 	sp = svc->svc_svc;
10387836SJohn.Forte@Sun.COM 	if (sp == NULL)
10397836SJohn.Forte@Sun.COM 		return (EINVAL);
10407836SJohn.Forte@Sun.COM 
10417836SJohn.Forte@Sun.COM 	mutex_enter(&_nsc_svc_mutex);
10427836SJohn.Forte@Sun.COM 	rw_enter(&sp->s_rwlock, RW_WRITER);
10437836SJohn.Forte@Sun.COM 
10447836SJohn.Forte@Sun.COM 	svcp = (svc->svc_fn == NULL) ? &sp->s_clients : &sp->s_servers;
10457836SJohn.Forte@Sun.COM 	for (; *svcp; svcp = &((*svcp)->svc_next))
10467836SJohn.Forte@Sun.COM 		if (svc == (*svcp))
10477836SJohn.Forte@Sun.COM 			break;
10487836SJohn.Forte@Sun.COM 
10497836SJohn.Forte@Sun.COM 	if (*svcp)
10507836SJohn.Forte@Sun.COM 		(*svcp) = svc->svc_next;
10517836SJohn.Forte@Sun.COM 
10527836SJohn.Forte@Sun.COM 	nsc_kmem_free(svc, sizeof (*svc));
10537836SJohn.Forte@Sun.COM 
10547836SJohn.Forte@Sun.COM 	if (sp->s_servers == NULL && sp->s_clients == NULL) {
10557836SJohn.Forte@Sun.COM 		for (spp = &_nsc_services; *spp; spp = &((*spp)->s_next))
10567836SJohn.Forte@Sun.COM 			if ((*spp) == sp)
10577836SJohn.Forte@Sun.COM 				break;
10587836SJohn.Forte@Sun.COM 
10597836SJohn.Forte@Sun.COM 		if (*spp)
10607836SJohn.Forte@Sun.COM 			(*spp) = sp->s_next;
10617836SJohn.Forte@Sun.COM 
10627836SJohn.Forte@Sun.COM 		rw_exit(&sp->s_rwlock);
10637836SJohn.Forte@Sun.COM 		mutex_exit(&_nsc_svc_mutex);
10647836SJohn.Forte@Sun.COM 
10657836SJohn.Forte@Sun.COM 		rw_destroy(&sp->s_rwlock);
10667836SJohn.Forte@Sun.COM 		nsc_strfree(sp->s_name);
10677836SJohn.Forte@Sun.COM 
10687836SJohn.Forte@Sun.COM 		nsc_kmem_free(sp, sizeof (*sp));
10697836SJohn.Forte@Sun.COM 		return (0);
10707836SJohn.Forte@Sun.COM 	}
10717836SJohn.Forte@Sun.COM 
10727836SJohn.Forte@Sun.COM 	rw_exit(&sp->s_rwlock);
10737836SJohn.Forte@Sun.COM 	mutex_exit(&_nsc_svc_mutex);
10747836SJohn.Forte@Sun.COM 
10757836SJohn.Forte@Sun.COM 	return (0);
10767836SJohn.Forte@Sun.COM }
10777836SJohn.Forte@Sun.COM 
10787836SJohn.Forte@Sun.COM 
10797836SJohn.Forte@Sun.COM int
nsc_call_svc(nsc_svc_t * svc,intptr_t arg)10807836SJohn.Forte@Sun.COM nsc_call_svc(nsc_svc_t *svc, intptr_t arg)
10817836SJohn.Forte@Sun.COM {
10827836SJohn.Forte@Sun.COM 	nsc_service_t *sp;
10837836SJohn.Forte@Sun.COM 	nsc_svc_t *svcp;
10847836SJohn.Forte@Sun.COM 	int found;
10857836SJohn.Forte@Sun.COM 
10867836SJohn.Forte@Sun.COM 	if (svc == NULL)
10877836SJohn.Forte@Sun.COM 		return (EINVAL);
10887836SJohn.Forte@Sun.COM 
10897836SJohn.Forte@Sun.COM 	sp = svc->svc_svc;
10907836SJohn.Forte@Sun.COM 	if (sp == NULL)
10917836SJohn.Forte@Sun.COM 		return (EINVAL);
10927836SJohn.Forte@Sun.COM 
10937836SJohn.Forte@Sun.COM 	rw_enter(&sp->s_rwlock, RW_READER);
10947836SJohn.Forte@Sun.COM 
10957836SJohn.Forte@Sun.COM 	found = (sp->s_servers != NULL);
10967836SJohn.Forte@Sun.COM 
10977836SJohn.Forte@Sun.COM 	for (svcp = sp->s_servers; svcp; svcp = svcp->svc_next)
10987836SJohn.Forte@Sun.COM 		(*svcp->svc_fn)(arg);
10997836SJohn.Forte@Sun.COM 
11007836SJohn.Forte@Sun.COM 	rw_exit(&sp->s_rwlock);
11017836SJohn.Forte@Sun.COM 
11027836SJohn.Forte@Sun.COM 	if (found == 0)
11037836SJohn.Forte@Sun.COM 		return (ENOSYS);
11047836SJohn.Forte@Sun.COM 
11057836SJohn.Forte@Sun.COM 	return (0);
11067836SJohn.Forte@Sun.COM }
1107