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