--- old/usr/src/uts/common/avs/ns/nsctl/nsc_dev.c	Fri Jul 27 15:35:54 2018
+++ /dev/null	Fri Jul 27 15:07:21 2018
@@ -1,2215 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/types.h>
-#include <sys/debug.h>
-#include <sys/ksynch.h>
-#include <sys/kmem.h>
-#include <sys/cmn_err.h>
-#include <sys/errno.h>
-#include <sys/ddi.h>
-
-#include <sys/ncall/ncall.h>
-
-#define	__NSC_GEN__
-#include "nsc_dev.h"
-
-#ifdef DS_DDICT
-#include "../contract.h"
-#endif
-
-#include "../nsctl.h"
-
-#define	NSC_DEVMIN	"DevMin"
-#define	NSC_DEVMAJ	"DevMaj"
-
-#define	_I(x)	(((long)(&((nsc_io_t *)0)->x))/sizeof (long))
-#define	_F(x)	(((long)(&((nsc_fd_t *)0)->x))/sizeof (long))
-
-
-nsc_def_t _nsc_io_def[] = {
-	"Open",		(uintptr_t)nsc_null,	_I(open),
-	"Close",	(uintptr_t)nsc_null,	_I(close),
-	"Attach",	(uintptr_t)nsc_null,	_I(attach),
-	"Detach",	(uintptr_t)nsc_null,	_I(detach),
-	"Flush",	(uintptr_t)nsc_null,	_I(flush),
-	"Provide",	0,		_I(provide),
-	0,		0,		0
-};
-
-nsc_def_t _nsc_fd_def[] = {
-	"Pinned",	(uintptr_t)nsc_null,	_F(sf_pinned),
-	"Unpinned",	(uintptr_t)nsc_null,	_F(sf_unpinned),
-	"Attach",	(uintptr_t)nsc_null,	_F(sf_attach),
-	"Detach",	(uintptr_t)nsc_null,	_F(sf_detach),
-	"Flush",	(uintptr_t)nsc_null,	_F(sf_flush),
-	0,		0,		0
-};
-
-kmutex_t _nsc_io_lock;
-kmutex_t _nsc_devval_lock;
-
-nsc_io_t *_nsc_io_top = NULL;
-nsc_io_t *_nsc_null_io = NULL;
-nsc_dev_t *_nsc_dev_top = NULL;
-nsc_dev_t *_nsc_dev_pend = NULL;
-nsc_path_t *_nsc_path_top = NULL;
-nsc_devval_t *_nsc_devval_top = NULL;
-
-extern nsc_def_t _nsc_disk_def[];
-extern nsc_def_t _nsc_cache_def[];
-
-extern nsc_mem_t *_nsc_local_mem;
-extern nsc_rmmap_t *_nsc_global_map;
-
-static clock_t _nsc_io_lbolt;
-
-static nsc_io_t *_nsc_find_io(char *, int, int *);
-nsc_io_t *_nsc_reserve_io(char *, int);
-static nsc_io_t *_nsc_alloc_io(int, char *, int);
-
-static int _nsc_open_fn(nsc_fd_t *, int);
-static int _nsc_close_fn(nsc_fd_t *);
-static int _nsc_alloc_fd(char *, int, int, nsc_fd_t **);
-static int _nsc_alloc_iodev(nsc_dev_t *, int, nsc_iodev_t **);
-static int _nsc_alloc_dev(char *, nsc_dev_t **);
-static int _nsc_reopen_io(char *, int);
-static int _nsc_reopen_dev(nsc_dev_t *, int);
-static int _nsc_relock_dev(nsc_dev_t *, nsc_fd_t *, nsc_iodev_t *);
-static int _nsc_reopen_fd(nsc_fd_t *, int);
-static int _nsc_decode_io(nsc_def_t *, nsc_io_t *);
-
-void _nsc_release_io(nsc_io_t *);
-static void _nsc_free_fd(nsc_fd_t *);
-static void _nsc_free_iodev(nsc_iodev_t *);
-static void _nsc_free_dev(nsc_dev_t *);
-static void _nsc_free_io(nsc_io_t *);
-static void _nsc_relink_fd(nsc_fd_t *, nsc_fd_t **, nsc_fd_t **, nsc_iodev_t *);
-
-static int _nsc_setval(nsc_dev_t *, char *, char *, int, int);
-static void r_nsc_setval(ncall_t *, int *);
-static void r_nsc_setval_all(ncall_t *, int *);
-
-extern void _nsc_add_disk(nsc_io_t *);
-extern void _nsc_add_cache(nsc_io_t *);
-
-
-/*
- * void
- * _nsc_init_dev (void)
- *	Initialise device subsystem.
- *
- * Calling/Exit State:
- *	Called at driver initialisation time to allocate necessary
- *	data structures.
- */
-void
-_nsc_init_dev()
-{
-	mutex_init(&_nsc_io_lock, NULL, MUTEX_DRIVER, NULL);
-	mutex_init(&_nsc_devval_lock, NULL, MUTEX_DRIVER, NULL);
-
-	_nsc_null_io = nsc_register_io("null", NSC_NULL, (nsc_def_t *)0);
-
-	if (!_nsc_null_io)
-		cmn_err(CE_PANIC, "nsctl: nsc_init_dev");
-
-	ncall_register_svc(NSC_SETVAL_ALL, r_nsc_setval_all);
-	ncall_register_svc(NSC_SETVAL, r_nsc_setval);
-}
-
-
-void
-_nsc_deinit_dev()
-{
-	nsc_devval_t *dv;
-	nsc_val_t *vp;
-
-	mutex_enter(&_nsc_devval_lock);
-
-	while ((dv = _nsc_devval_top) != NULL) {
-		while ((vp = dv->dv_values) != NULL) {
-			dv->dv_values = vp->sv_next;
-			nsc_kmem_free(vp, sizeof (*vp));
-		}
-
-		_nsc_devval_top = dv->dv_next;
-		nsc_kmem_free(dv, sizeof (*dv));
-	}
-
-	mutex_exit(&_nsc_devval_lock);
-
-	ncall_unregister_svc(NSC_SETVAL_ALL);
-	ncall_unregister_svc(NSC_SETVAL);
-
-	mutex_destroy(&_nsc_devval_lock);
-	mutex_destroy(&_nsc_io_lock);
-}
-
-
-/*
- * nsc_io_t *
- * nsc_register_io (char *name, int type, nsc_def_t *def)
- *	Register an I/O module.
- *
- * Calling/Exit State:
- *	Returns a token for use in future calls to nsc_unregister_io.
- *	The ID and flags for the module are specified by 'type' and
- *	the appropriate entry points are defined using 'def'. If
- *	registration fails NULL is returned.
- *
- * Description:
- *	Registers an I/O module for use by subsequent calls to
- *	nsc_open.
- */
-nsc_io_t *
-nsc_register_io(name, type, def)
-char *name;
-int type;
-nsc_def_t *def;
-{
-	nsc_io_t *io, *tp;
-	int rc, id, flag;
-	nsc_io_t **iop;
-
-	id = (type & NSC_TYPES);
-	flag = (type & ~NSC_TYPES);
-
-	if ((!(id & NSC_ID) || (id & ~NSC_IDS)) &&
-			(id != NSC_NULL || _nsc_null_io))
-		return (NULL);
-
-	if (!(io = _nsc_alloc_io(id, name, flag)))
-		return (NULL);
-
-	rc = _nsc_decode_io(def, io);
-
-	if (!rc && id != NSC_NULL) {
-		_nsc_free_io(io);
-		return (NULL);
-	}
-
-	mutex_enter(&_nsc_io_lock);
-
-	for (tp = _nsc_io_top; tp; tp = tp->next) {
-		if (strcmp(tp->name, name) == 0 || tp->id == id) {
-			mutex_exit(&_nsc_io_lock);
-			_nsc_free_io(io);
-			return (NULL);
-		}
-	}
-
-	for (iop = &_nsc_io_top; *iop; iop = &(*iop)->next)
-		if (id >= (*iop)->id)
-			break;
-
-	io->next = (*iop);
-	(*iop) = io;
-
-	_nsc_io_lbolt = nsc_lbolt();
-
-	while ((rc = _nsc_reopen_io(NULL, 0)) != 0)
-		if (rc != ERESTART)
-			break;
-
-	mutex_exit(&_nsc_io_lock);
-	return (io);
-}
-
-
-/*
- * static int
- * _nsc_decode_io (nsc_def_t *def, nsc_io_t *io)
- *	Decode I/O module definition.
- *
- * Calling/Exit State:
- *	Returns TRUE if the definition contains an adequate
- *	description of an I/O module.
- *
- * Description:
- *	Decode the definition of an I/O module and supply
- *	translation routines where possible for operations
- *	that are not defined.
- */
-static int
-_nsc_decode_io(def, io)
-nsc_def_t *def;
-nsc_io_t *io;
-{
-	nsc_decode_param(def, _nsc_io_def, (long *)io);
-	nsc_decode_param(def, _nsc_disk_def, (long *)io);
-	nsc_decode_param(def, _nsc_cache_def, (long *)io);
-
-	_nsc_add_disk(io);
-	_nsc_add_cache(io);
-
-	return (1);
-}
-
-
-/*
- * int
- * nsc_unregister_io (nsc_io_t *io, int flag)
- *	Un-register an I/O module.
- *
- * Calling/Exit State:
- *	Returns 0 on success, otherwise returns an error code.
- *
- * Description:
- *	The specified I/O module is un-registered if possible.
- *	All open file descriptors using the module will be closed
- *	in preparation for a subsequent re-open.
- *
- *	If NSC_PCATCH is specified and a signal is received,
- *	the unregister will be terminated and EINTR returned.
- */
-int
-nsc_unregister_io(nsc_io_t *io, int flag)
-{
-	nsc_path_t *sp;
-	nsc_io_t *xio;
-	int rc = 0;
-
-	if (io == _nsc_null_io)
-		return (EINVAL);
-
-	mutex_enter(&_nsc_io_lock);
-
-	for (xio = _nsc_io_top; xio; xio = xio->next)
-		if (xio == io)
-			break;
-
-	if (!xio || io->pend) {
-		mutex_exit(&_nsc_io_lock);
-		return (xio ? EALREADY : 0);
-	}
-
-	io->pend = 1;
-lp:
-	for (sp = _nsc_path_top; sp; sp = sp->sp_next)
-		if (sp->sp_io == io) {
-			mutex_exit(&_nsc_io_lock);
-
-			if ((rc = nsc_unregister_path(sp, flag)) != 0) {
-				io->pend = 0;
-				return (rc);
-			}
-
-			mutex_enter(&_nsc_io_lock);
-			goto lp;
-		}
-
-	_nsc_io_lbolt = nsc_lbolt();
-
-	while (io->refcnt && !rc) {
-		while ((rc = _nsc_reopen_io(NULL, flag)) != 0)
-			if (rc != ERESTART)
-				break;
-
-		if (rc || !io->refcnt)
-			break;
-
-		if (!cv_wait_sig(&io->cv, &_nsc_io_lock))
-			rc = EINTR;
-	}
-
-	/*
-	 * We have tried to get rid of all the IO provider's clients.
-	 * If there are still anonymous buffers outstanding, then fail
-	 * the unregister.
-	 */
-
-	if (!rc && io->abufcnt > 0)
-		rc = EUSERS;
-
-	if (rc)
-		io->pend = 0;
-
-	mutex_exit(&_nsc_io_lock);
-
-	if (!rc)
-		_nsc_free_io(io);
-
-	return (rc);
-}
-
-
-/*
- * nsc_path_t *
- * nsc_register_path (char *path, int type, nsc_io_t *io)
- *	Register interest in pathname.
- *
- * Calling/Exit State:
- *	Returns a token for use in future calls to
- *	nsc_unregister_path. The 'path' argument can contain
- *	wild characters. If registration fails NULL is returned.
- *	May not be called for io providers that support NSC_ANON.
- *
- * Description:
- *	Registers an interest in any pathnames matching 'path'
- *	which are opened with the specified type.
- */
-nsc_path_t *
-nsc_register_path(char *path, int type, nsc_io_t *io)
-{
-	nsc_path_t *sp, **spp;
-	int rc;
-
-	if ((type & NSC_IDS) || !io || (io->provide & NSC_ANON) ||
-	    !(sp = nsc_kmem_zalloc(sizeof (*sp), KM_SLEEP, _nsc_local_mem)))
-		return (NULL);
-
-	sp->sp_path = nsc_strdup(path);
-	sp->sp_type = type;
-	sp->sp_io = io;
-
-	mutex_enter(&_nsc_io_lock);
-
-	for (spp = &_nsc_path_top; *spp; spp = &(*spp)->sp_next)
-		if (io->id >= (*spp)->sp_io->id)
-			break;
-
-	sp->sp_next = (*spp);
-	(*spp) = sp;
-
-	_nsc_io_lbolt = nsc_lbolt();
-
-	while ((rc = _nsc_reopen_io(path, 0)) != 0)
-		if (rc != ERESTART)
-			break;
-
-	mutex_exit(&_nsc_io_lock);
-	return (sp);
-}
-
-
-/*
- * int
- * nsc_unregister_path (nsc_path_t *sp, int flag)
- *	Un-register interest in pathname.
- *
- * Calling/Exit State:
- *	Returns 0 on success, otherwise returns an error code.
- *
- * Description:
- *	Interest in the specified pathname is un-registered
- *	if possible. All appropriate file descriptors will be
- *	closed in preparation for a subsequent re-open.
- *
- *	If NSC_PCATCH is specified and a signal is received,
- *	the unregister will be terminated and EINTR returned.
- */
-int
-nsc_unregister_path(sp, flag)
-nsc_path_t *sp;
-int flag;
-{
-	nsc_path_t *xsp, **spp;
-	int rc;
-
-	mutex_enter(&_nsc_io_lock);
-
-	for (xsp = _nsc_path_top; xsp; xsp = xsp->sp_next)
-		if (xsp == sp)
-			break;
-
-	if (!xsp || sp->sp_pend) {
-		mutex_exit(&_nsc_io_lock);
-		return (xsp ? EALREADY : 0);
-	}
-
-	sp->sp_pend = 1;
-	_nsc_io_lbolt = nsc_lbolt();
-
-	while ((rc = _nsc_reopen_io(sp->sp_path, flag)) != 0)
-		if (rc != ERESTART) {
-			sp->sp_pend = 0;
-			mutex_exit(&_nsc_io_lock);
-			return (rc);
-		}
-
-	for (spp = &_nsc_path_top; *spp; spp = &(*spp)->sp_next)
-		if (*spp == sp)
-			break;
-
-	if (*spp)
-		(*spp) = sp->sp_next;
-
-	mutex_exit(&_nsc_io_lock);
-
-	nsc_strfree(sp->sp_path);
-	nsc_kmem_free(sp, sizeof (*sp));
-	return (0);
-}
-
-
-/*
- * static int
- * _nsc_reopen_io (char *path, int flag)
- *	Force re-open of all file descriptors.
- *
- * Calling/Exit State:
- *	The _nsc_io_lock must be held across calls to
- *	this function.
- *
- *	Returns 0 if the force succeeds without releasing
- *	_nsc_io_lock, otherwise returns an error code.
- *
- * Description:
- *	A re-open is forced for all file descriptors as
- *	appropriate. For performance reasons available
- *	devices are re-opened before those that would block.
- */
-static int
-_nsc_reopen_io(path, flag)
-char *path;
-int flag;
-{
-	nsc_dev_t *dp, *dev;
-	int rc, errno = 0;
-	int try, run;
-
-	for (run = 1, try = (NSC_TRY | NSC_DEFER); run--; try = 0) {
-		for (dev = _nsc_dev_top; dev; dev = dev->nsc_next) {
-			if (path && !nsc_strmatch(dev->nsc_path, path))
-				continue;
-
-			if (!(rc = _nsc_reopen_dev(dev, flag | try)))
-				continue;
-
-			for (dp = _nsc_dev_top; dp; dp = dp->nsc_next)
-				if (dp == dev)
-					break;
-
-			if (!dp)
-				return (ERESTART);
-
-			if (try && !(flag & NSC_TRY))
-				run = 1;
-			if (!run && errno != ERESTART)
-				errno = rc;
-		}
-	}
-
-	return (errno);
-}
-
-
-/*
- * static int
- * _nsc_reopen_dev (nsc_dev_t *dev, int flag)
- *	Force re-open of entire device.
- *
- * Calling/Exit State:
- *	The _nsc_io_lock must be held across calls to
- *	this function.
- *
- *	Returns 0 if the force succeeds without releasing
- *	_nsc_io_lock, otherwise returns an error code.
- *
- * Description:
- *	A re-open is forced for all file descriptors for the
- *	device as appropriate.
- */
-static int
-_nsc_reopen_dev(dev, flag)
-nsc_dev_t *dev;
-int flag;
-{
-	int rc, errno = 0;
-	nsc_iodev_t *iodev;
-	int try, run;
-	nsc_fd_t *fd;
-
-	mutex_enter(&dev->nsc_lock);
-
-	for (run = 1, try = (NSC_TRY | NSC_DEFER); run--; try = 0)
-		for (iodev = dev->nsc_list; iodev; iodev = iodev->si_next) {
-			for (fd = iodev->si_open; fd; fd = fd->sf_next) {
-				if (!(rc = _nsc_reopen_fd(fd, flag | try)))
-					continue;
-
-				if (rc == -ERESTART)
-					return (ERESTART);
-
-				if (!_nsc_relock_dev(dev, fd, iodev))
-					return (ERESTART);
-
-				if (try && !(flag & NSC_TRY))
-					run = 1;
-				if (!run && errno != ERESTART)
-					errno = rc;
-			}
-		}
-
-	for (run = 1, try = (NSC_TRY | NSC_DEFER); run--; try = 0)
-		for (fd = dev->nsc_close; fd; fd = fd->sf_next) {
-			if (!(rc = _nsc_reopen_fd(fd, flag | try)))
-				continue;
-
-			if (rc == -ERESTART)
-				return (ERESTART);
-
-			if (!_nsc_relock_dev(dev, fd, NULL))
-				return (ERESTART);
-
-			if (try && !(flag & NSC_TRY))
-				run = 1;
-			if (!run && errno != ERESTART)
-				errno = rc;
-		}
-
-	mutex_exit(&dev->nsc_lock);
-	return (errno);
-}
-
-
-/*
- * static int
- * _nsc_relock_dev (nsc_dev_t *dev, nsc_fd_t *fd, nsc_iodev_t *iodev)
- *	Relock device structure if possible.
- *
- * Calling/Exit State:
- *	The _nsc_io_lock must be held across calls to
- *	this function.
- *
- *	Checks whether the file descriptor is still part
- *	of the specified device and I/O device. If so the
- *	device lock is taken. Otherwise FALSE is returned.
- */
-static int
-_nsc_relock_dev(nsc_dev_t *dev, nsc_fd_t *fd, nsc_iodev_t *iodev)
-{
-	nsc_fd_t *fp = NULL;
-	nsc_iodev_t *iop;
-	nsc_dev_t *dp;
-
-	for (dp = _nsc_dev_top; dp; dp = dp->nsc_next)
-		if (dp == dev)
-			break;
-
-	if (!dp)
-		return (0);
-
-	mutex_enter(&dev->nsc_lock);
-
-	if (iodev)
-		for (iop = dev->nsc_list; iop; iop = iop->si_next)
-			if (iop == iodev)
-				break;
-
-	if (!iodev || iop) {
-		fp = (iodev) ? iodev->si_open : dev->nsc_close;
-
-		for (; fp; fp = fp->sf_next)
-			if (fp == fd)
-				break;
-	}
-
-	if (!fp) {
-		mutex_exit(&dev->nsc_lock);
-		return (0);
-	}
-
-	return (1);
-}
-
-
-/*
- * static int
- * _nsc_reopen_fd (nsc_fd_t *dev, int flag)
- *	Force re-open of file descriptor.
- *
- * Calling/Exit State:
- *	Both _nsc_io_lock and the device lock must be held
- *	across calls to this function.
- *
- *	Returns 0 if the force succeeds without releasing
- *	any locks, otherwise returns an error code. If an
- *	error code is returned the device lock is released.
- *
- * Description:
- *	If appropriate the file descriptor is closed in order
- *	to force a subsequent open using the currently available
- *	resources.
- */
-static int
-_nsc_reopen_fd(fd, flag)
-nsc_fd_t *fd;
-int flag;
-{
-	nsc_dev_t *dev = fd->sf_dev;
-	nsc_iodev_t *iodev = fd->sf_iodev;
-	int changed = 0;
-	int rc;
-
-	if (!fd->sf_pend && !iodev)
-		return (0);
-
-	if (fd->sf_pend == _NSC_OPEN)
-		if (fd->sf_lbolt - _nsc_io_lbolt > 0)
-			return (0);
-
-	if (iodev &&
-	    (iodev->si_io ==
-		_nsc_find_io(dev->nsc_path, fd->sf_type, &changed)) &&
-	    !changed)
-		return (0);
-
-	if (iodev)
-		fd->sf_reopen = 1;
-
-	mutex_exit(&_nsc_io_lock);
-
-	dev->nsc_reopen = 1;
-
-	rc = _nsc_close_fd(fd, flag);
-
-	dev->nsc_reopen = 0;
-
-	if (rc == EAGAIN && (flag & NSC_DEFER) && fd->sf_reopen)
-		dev->nsc_drop = 1;
-
-	mutex_exit(&dev->nsc_lock);
-
-	if (rc == -ERESTART)
-		delay(2);	/* allow other threads cpu time */
-
-	mutex_enter(&_nsc_io_lock);
-	return (rc ? rc : ERESTART);
-}
-
-
-/*
- * nsc_fd_t *
- * nsc_open (char *path, int type, nsc_def_t *def, blind_t arg, int *sts)
- *	Open file descriptor for pathname.
- *
- * Calling/Exit State:
- *	Returns file descriptor if open succeeds, otherwise
- *	returns 0 and puts error code in the location pointed
- *	to by sts.
- *
- * Description:
- *	Open the specified pathname using an appropriate access
- *	method.
- */
-nsc_fd_t *
-nsc_open(path, type, def, arg, sts)
-char *path;
-int type;
-nsc_def_t *def;
-blind_t arg;
-int *sts;
-{
-	int flag, rc;
-	nsc_fd_t *fd;
-
-	flag = (type & ~NSC_TYPES);
-	type &= NSC_TYPES;
-
-	if ((flag & NSC_READ) == 0)
-		flag |= NSC_RDWR;
-
-	if ((rc = _nsc_alloc_fd(path, type, flag, &fd)) != 0) {
-		if (sts)
-			*sts = rc;
-		return (NULL);
-	}
-
-	fd->sf_arg = arg;
-	fd->sf_aio = _nsc_null_io;
-
-	nsc_decode_param(def, _nsc_fd_def, (long *)fd);
-
-	mutex_enter(&fd->sf_dev->nsc_lock);
-
-	while ((rc = _nsc_open_fd(fd, flag)) != 0)
-		if (rc != ERESTART)
-			break;
-
-	mutex_exit(&fd->sf_dev->nsc_lock);
-
-	if (rc) {
-		_nsc_free_fd(fd);
-		if (sts)
-			*sts = rc;
-		return (NULL);
-	}
-
-	return (fd);
-}
-
-
-/*
- * int
- * _nsc_open_fd (nsc_fd_t *fd, int flag)
- *	Open file descriptor.
- *
- * Calling/Exit State:
- *	The device lock must be held across calls to
- *	this function.
- *
- *	Returns 0 if the open succeeds, otherwise
- *	returns an error code.
- *
- * Description:
- *	Open the specified file descriptor.
- */
-int
-_nsc_open_fd(fd, flag)
-nsc_fd_t *fd;
-int flag;
-{
-	nsc_dev_t *dev = fd->sf_dev;
-	int rc;
-
-	if (fd->sf_pend)
-		return (_nsc_wait_dev(dev, flag));
-
-	if (fd->sf_iodev)
-		return (0);
-	if (flag & NSC_NOBLOCK)
-		return (EAGAIN);
-
-	fd->sf_pend = _NSC_OPEN;
-	fd->sf_lbolt = nsc_lbolt();
-
-	mutex_exit(&dev->nsc_lock);
-
-	rc = _nsc_open_fn(fd, flag);
-
-	mutex_enter(&dev->nsc_lock);
-	fd->sf_pend = 0;
-
-	if (!rc)
-		fd->sf_iodev->si_pend = 0;
-
-	if (dev->nsc_wait || dev->nsc_refcnt <= 0)
-		cv_broadcast(&dev->nsc_cv);
-
-	return (rc ? rc : ERESTART);
-}
-
-
-/*
- * static int
- * _nsc_open_fn (nsc_fd_t *fd, int flag)
- *	Allocate I/O device and open file descriptor.
- *
- * Calling/Exit State:
- *	No locks may be held across this function.
- *
- *	If the open succeeds an I/O device will be
- *	attached to the file descriptor, marked as
- *	pending and 0 returned. Otherwise, returns
- *	an error code.
- *
- * Description:
- *	Allocate an I/O device and open the specified
- *	file descriptor.
- */
-static int
-_nsc_open_fn(fd, flag)
-nsc_fd_t *fd;
-int flag;
-{
-	nsc_dev_t *dev = fd->sf_dev;
-	nsc_iodev_t *iodev;
-	int rc;
-
-	if ((rc = _nsc_alloc_iodev(dev, fd->sf_type, &iodev)) != 0)
-		return (rc);
-
-	mutex_enter(&dev->nsc_lock);
-
-	if (iodev->si_pend) {
-		rc = _nsc_wait_dev(dev, flag);
-		mutex_exit(&dev->nsc_lock);
-		_nsc_free_iodev(iodev);
-		return (rc);
-	}
-
-	iodev->si_pend = _NSC_OPEN;
-	mutex_exit(&dev->nsc_lock);
-
-	rc = (*iodev->si_io->open)(dev->nsc_path,
-			(fd->sf_flag & ~NSC_RDWR), &fd->sf_cd, iodev);
-
-	if (rc) {
-		iodev->si_pend = 0;
-		_nsc_free_iodev(iodev);
-		return (rc);
-	}
-
-	/* save away the DevMaj and DevMin values */
-	if (iodev->si_io->id == NSC_RAW_ID) {
-		rc = _nsc_setval(dev, NULL, NSC_DEVMAJ,
-		    (int)getmajor((dev_t)fd->sf_cd), FALSE);
-#ifdef DEBUG
-		if (rc != 1) {
-			cmn_err(CE_NOTE, "!nsctl: could not set DevMaj (%s:%x)",
-			    dev->nsc_path, (int)getmajor((dev_t)fd->sf_cd));
-		}
-#endif
-
-		rc = _nsc_setval(dev, NULL, NSC_DEVMIN,
-		    (int)getminor((dev_t)fd->sf_cd), FALSE);
-#ifdef DEBUG
-		if (rc != 1) {
-			cmn_err(CE_NOTE, "!nsctl: could not set DevMin (%s:%x)",
-			    dev->nsc_path, (int)getminor((dev_t)fd->sf_cd));
-		}
-#endif
-	}
-
-	fd->sf_iodev = iodev;
-	_nsc_relink_fd(fd, &dev->nsc_close, &iodev->si_open, iodev);
-
-	return (0);
-}
-
-
-/*
- * int
- * nsc_close (nsc_fd_t *fd)
- *	Close file descriptor for pathname.
- *
- * Calling/Exit State:
- *	Returns 0 if close succeeds, otherwise returns error
- *	code.
- *
- * Description:
- *	Close the specified file descriptor. It is assumed
- *	that all other users of this file descriptor have
- *	finished. Any reserve will be discarded before the
- *	close is performed.
- */
-int
-nsc_close(fd)
-nsc_fd_t *fd;
-{
-	int rc;
-
-	if (!fd)
-		return (0);
-
-	while (fd->sf_reserve)
-		nsc_release(fd);
-
-	mutex_enter(&fd->sf_dev->nsc_lock);
-
-	fd->sf_owner = NULL;
-
-	while ((rc = _nsc_close_fd(fd, 0)) != 0)
-		if (rc != ERESTART)
-			break;
-
-	nsc_decode_param(_nsc_fd_def, _nsc_fd_def, (long *)fd);
-
-	mutex_exit(&fd->sf_dev->nsc_lock);
-
-	if (!rc)
-		_nsc_free_fd(fd);
-	return (rc);
-}
-
-
-/*
- * int
- * _nsc_close_fd (nsc_fd_t *fd, int flag)
- *	Close file descriptor.
- *
- * Calling/Exit State:
- *	The device lock must be held across calls to
- *	this function.
- *
- *	Returns 0 if the close succeeds, otherwise
- *	returns an error code.
- *
- * Description:
- *	Close the specified file descriptor.
- */
-int
-_nsc_close_fd(fd, flag)
-nsc_fd_t *fd;
-int flag;
-{
-	nsc_dev_t *dev = fd->sf_dev;
-	nsc_iodev_t *iodev;
-	int rc;
-
-	if (fd->sf_pend) {
-		if (fd->sf_pend == _NSC_CLOSE && dev->nsc_reopen != 0)
-			return (-ERESTART);
-
-		return (_nsc_wait_dev(dev, flag));
-	}
-
-	flag |= NSC_RDWR;
-	iodev = fd->sf_iodev;
-
-	if (!iodev)
-		return (0);
-
-	if ((rc = _nsc_detach_fd(fd, flag)) != 0)
-		return (rc);
-
-	if (iodev->si_pend)
-		return (_nsc_wait_dev(dev, flag));
-
-	if (iodev->si_open == fd && !fd->sf_next) {
-		if ((rc = _nsc_detach_iodev(iodev, NULL, flag)) != 0)
-			return (rc);
-
-		if (dev->nsc_list == iodev && !iodev->si_next)
-			if ((rc = _nsc_detach_dev(dev, NULL, flag)) != 0)
-				return (rc);
-	}
-
-	if (flag & NSC_NOBLOCK)
-		return (EAGAIN);
-
-	fd->sf_pend = _NSC_CLOSE;
-	iodev->si_pend = _NSC_CLOSE;
-	mutex_exit(&dev->nsc_lock);
-
-	rc = _nsc_close_fn(fd);
-
-	mutex_enter(&dev->nsc_lock);
-	fd->sf_pend = 0;
-
-	fd->sf_reopen = 0;
-	if (rc)
-		iodev->si_pend = 0;
-
-	if (dev->nsc_wait || dev->nsc_refcnt <= 0)
-		cv_broadcast(&dev->nsc_cv);
-
-	return (rc ? rc : ERESTART);
-}
-
-
-/*
- * static int
- * _nsc_close_fn (nsc_fd_t *fd)
- *	Close file descriptor and free I/O device.
- *
- * Calling/Exit State:
- *	No locks may be held across this function.
- *
- *	Returns 0 if the close succeeds, otherwise
- *	returns an error code.
- *
- *	If the close succeeds the I/O device will be
- *	detached from the file descriptor, released
- *	and 0 returned. Otherwise, returns an error
- *	code.
- *
- * Description:
- *	Close the specified file descriptor and free
- *	the I/O device.
- */
-static int
-_nsc_close_fn(fd)
-nsc_fd_t *fd;
-{
-	nsc_iodev_t *iodev = fd->sf_iodev;
-	nsc_dev_t *dev = fd->sf_dev;
-	int last, rc;
-
-	last = (iodev->si_open == fd && !fd->sf_next);
-
-	if (last || (iodev->si_io->flag & NSC_REFCNT))
-		if ((rc = (*iodev->si_io->close)(fd->sf_cd)) != 0)
-			return (rc);
-
-	fd->sf_iodev = NULL;
-	_nsc_relink_fd(fd, &iodev->si_open, &dev->nsc_close, iodev);
-
-	iodev->si_pend = 0;
-	_nsc_free_iodev(iodev);
-
-	return (0);
-}
-
-
-/*
- * void
- * nsc_set_owner (nsc_fd_t *fd, nsc_iodev_t *iodev)
- *	Set owner associated with file descriptor.
- *
- * Calling/Exit State:
- *	Sets the owner field in the file descriptor.
- */
-void
-nsc_set_owner(nsc_fd_t *fd, nsc_iodev_t *iodev)
-{
-	if (fd) {
-		mutex_enter(&fd->sf_dev->nsc_lock);
-		fd->sf_owner = iodev;
-		mutex_exit(&fd->sf_dev->nsc_lock);
-	}
-}
-
-
-/*
- * char *
- * nsc_pathname (nsc_fd_t *fd)
- *	Pathname associated with file descriptor.
- *
- * Calling/Exit State:
- *	Returns a pointer to the pathname associated
- *	with the given file descriptor.
- */
-char *
-nsc_pathname(fd)
-nsc_fd_t *fd;
-{
-	return ((fd) ? (fd->sf_dev->nsc_path) : 0);
-}
-
-
-/*
- * int
- * nsc_fdpathcmp(nsc_fd_t *fd, uint64_t phash, char *path)
- *	Compare fd to pathname and hash
- *
- * Calling/Exit State:
- *	Returns comparison value like strcmp(3C).
- *
- * Description:
- *	Does an optimised comparison of the pathname and associated hash
- *	value (as returned from nsc_strhash()) against the pathname of
- *	the filedescriptor, fd.
- */
-int
-nsc_fdpathcmp(nsc_fd_t *fd, uint64_t phash, char *path)
-{
-	int rc = -1;
-
-	if (fd != NULL && fd->sf_dev->nsc_phash == phash)
-		rc = strcmp(fd->sf_dev->nsc_path, path);
-
-	return (rc);
-}
-
-
-static int
-_nsc_setval(nsc_dev_t *dev, char *path, char *name, int val, int do_ncall)
-{
-	nsc_devval_t *dv;
-	nsc_rval_t *rval;
-	ncall_t *ncall;
-	nsc_val_t *vp;
-	uint64_t phash;
-	char *pp;
-	int rc;
-
-	ASSERT(dev != NULL || path != NULL);
-#ifdef DEBUG
-	if (dev != NULL && path != NULL) {
-		ASSERT(strcmp(dev->nsc_path, path) == 0);
-	}
-#endif
-
-	pp = (dev != NULL) ? dev->nsc_path : path;
-
-	if (strlen(name) >= NSC_SETVAL_MAX) {
-#ifdef DEBUG
-		cmn_err(CE_WARN, "!nsc_setval: max name size(%d) exceeded(%d)",
-		    NSC_SETVAL_MAX-1, (int)strlen(name));
-#endif
-		return (0);
-	}
-
-	phash = nsc_strhash(pp);
-
-	mutex_enter(&_nsc_devval_lock);
-
-	if (dev != NULL)
-		dv = dev->nsc_values;
-	else {
-		for (dv = _nsc_devval_top; dv != NULL; dv = dv->dv_next) {
-			if (phash == dv->dv_phash &&
-			    strcmp(pp, dv->dv_path) == 0)
-				/* found dv for device */
-				break;
-		}
-	}
-
-	if (dv == NULL) {
-		dv = nsc_kmem_zalloc(sizeof (*dv), KM_SLEEP, _nsc_local_mem);
-		if (dv == NULL) {
-			mutex_exit(&_nsc_devval_lock);
-			return (0);
-		}
-
-		(void) strncpy(dv->dv_path, pp, sizeof (dv->dv_path));
-		dv->dv_phash = phash;
-
-		dv->dv_next = _nsc_devval_top;
-		_nsc_devval_top = dv;
-		if (dev != NULL)
-			dev->nsc_values = dv;
-	}
-
-	for (vp = dv->dv_values; vp; vp = vp->sv_next) {
-		if (strcmp(vp->sv_name, name) == 0) {
-			vp->sv_value = val;
-			break;
-		}
-	}
-
-	if (vp == NULL) {
-		vp = nsc_kmem_zalloc(sizeof (*vp), KM_SLEEP, _nsc_local_mem);
-		if (vp != NULL) {
-			(void) strncpy(vp->sv_name, name, sizeof (vp->sv_name));
-			vp->sv_value = val;
-			vp->sv_next = dv->dv_values;
-			dv->dv_values = vp;
-		}
-	}
-
-	mutex_exit(&_nsc_devval_lock);
-
-	/*
-	 * phoenix: ncall the new value to the other node now.
-	 */
-
-	if (vp && do_ncall) {
-		/* CONSTCOND */
-		ASSERT(sizeof (nsc_rval_t) <= NCALL_DATA_SZ);
-
-		rval = nsc_kmem_zalloc(sizeof (*rval), KM_SLEEP,
-		    _nsc_local_mem);
-		if (rval == NULL) {
-			goto out;
-		}
-
-		rc = ncall_alloc(ncall_mirror(ncall_self()), 0, 0, &ncall);
-		if (rc == 0) {
-			(void) strncpy(rval->path, pp, sizeof (rval->path));
-			(void) strncpy(rval->name, name, sizeof (rval->name));
-			rval->value = val;
-
-			rc = ncall_put_data(ncall, rval, sizeof (*rval));
-			if (rc == 0) {
-				/*
-				 * Send synchronously and read a reply
-				 * so that we know that the remote
-				 * setval has completed before this
-				 * function returns and hence whilst
-				 * the device is still reserved on this
-				 * node.
-				 */
-				if (ncall_send(ncall, 0, NSC_SETVAL) == 0)
-					(void) ncall_read_reply(ncall, 1, &rc);
-			}
-
-			ncall_free(ncall);
-		}
-
-		nsc_kmem_free(rval, sizeof (*rval));
-	}
-
-out:
-	return (vp ? 1 : 0);
-}
-
-
-/* ARGSUSED */
-
-static void
-r_nsc_setval(ncall_t *ncall, int *ap)
-{
-	nsc_rval_t *rval;
-	int rc;
-
-	rval = nsc_kmem_zalloc(sizeof (*rval), KM_SLEEP, _nsc_local_mem);
-	if (rval == NULL) {
-		ncall_reply(ncall, ENOMEM);
-		return;
-	}
-
-	rc = ncall_get_data(ncall, rval, sizeof (*rval));
-	if (rc != 0) {
-		ncall_reply(ncall, EFAULT);
-		return;
-	}
-
-	if (_nsc_setval(NULL, rval->path, rval->name, rval->value, FALSE))
-		rc = 0;
-	else
-		rc = ENOMEM;
-
-	ncall_reply(ncall, rc);
-	nsc_kmem_free(rval, sizeof (*rval));
-}
-
-
-/* ARGSUSED */
-
-static void
-r_nsc_setval_all(ncall_t *ncall, int *ap)
-{
-	nsc_rval_t *in = NULL, *out = NULL;
-	nsc_devval_t *dv;
-	nsc_val_t *vp;
-	ncall_t *np;
-	uint64_t phash;
-	int rc;
-
-	/* CONSTCOND */
-	ASSERT(sizeof (nsc_rval_t) <= NCALL_DATA_SZ);
-
-	in = nsc_kmem_zalloc(sizeof (*in), KM_SLEEP, _nsc_local_mem);
-	out = nsc_kmem_zalloc(sizeof (*out), KM_SLEEP, _nsc_local_mem);
-	if (in == NULL || out == NULL) {
-		if (in != NULL) {
-			nsc_kmem_free(in, sizeof (*in));
-			in = NULL;
-		}
-		if (out != NULL) {
-			nsc_kmem_free(out, sizeof (*out));
-			out = NULL;
-		}
-		ncall_reply(ncall, ENOMEM);
-	}
-
-	rc = ncall_get_data(ncall, in, sizeof (*in));
-	if (rc != 0) {
-		ncall_reply(ncall, EFAULT);
-		return;
-	}
-
-	phash = nsc_strhash(in->path);
-
-	(void) strncpy(out->path, in->path, sizeof (out->path));
-
-	rc = ncall_alloc(ncall_mirror(ncall_self()), 0, 0, &np);
-	if (rc != 0) {
-		ncall_reply(ncall, ENOMEM);
-		return;
-	}
-
-	mutex_enter(&_nsc_devval_lock);
-
-	for (dv = _nsc_devval_top; dv; dv = dv->dv_next) {
-		if (dv->dv_phash == phash &&
-		    strcmp(dv->dv_path, in->path) == 0)
-			break;
-	}
-
-	if (dv) {
-		for (vp = dv->dv_values; vp; vp = vp->sv_next) {
-			if (strcmp(vp->sv_name, NSC_DEVMIN) == 0 ||
-			    strcmp(vp->sv_name, NSC_DEVMAJ) == 0) {
-				/* ignore the implicit DevMin/DevMaj values */
-				continue;
-			}
-
-			(void) strncpy(out->name, vp->sv_name,
-			    sizeof (out->name));
-			out->value = vp->sv_value;
-
-			rc = ncall_put_data(np, out, sizeof (*out));
-			if (rc == 0) {
-				/*
-				 * Send synchronously and read a reply
-				 * so that we know that the remote
-				 * setval has completed before this
-				 * function returns.
-				 */
-				if (ncall_send(np, 0, NSC_SETVAL) == 0)
-					(void) ncall_read_reply(np, 1, &rc);
-			}
-
-			ncall_reset(np);
-		}
-
-		ncall_free(np);
-		rc = 0;
-	} else {
-		rc = ENODEV;
-	}
-
-	mutex_exit(&_nsc_devval_lock);
-
-	ncall_reply(ncall, rc);
-
-	nsc_kmem_free(out, sizeof (*out));
-	nsc_kmem_free(in, sizeof (*in));
-}
-
-
-/*
- * int
- * nsc_setval (nsc_fd_t *fd, char *name, int val)
- *	Set value for device.
- *
- * Calling/Exit State:
- *	Returns 1 if the value has been set, otherwise 0.
- *	Must be called with the fd reserved.
- *
- * Description:
- *	Sets the specified global variable for the device
- *	to the value provided.
- */
-int
-nsc_setval(nsc_fd_t *fd, char *name, int val)
-{
-	if (!fd)
-		return (0);
-
-	if (!nsc_held(fd))
-		return (0);
-
-	return (_nsc_setval(fd->sf_dev, NULL, name, val, TRUE));
-}
-
-
-/*
- * int
- * nsc_getval (nsc_fd_t *fd, char *name, int *vp)
- *	Get value from device.
- *
- * Calling/Exit State:
- *	Returns 1 if the value has been found, otherwise 0.
- *	Must be called with the fd reserved, except for "DevMaj" / "DevMin".
- *
- * Description:
- *	Finds the value of the specified device variable for
- *	the device and returns it in the location pointed to
- *	by vp.
- */
-int
-nsc_getval(nsc_fd_t *fd, char *name, int *vp)
-{
-	nsc_devval_t *dv;
-	nsc_val_t *val;
-
-	if (!fd)
-		return (0);
-
-	/*
-	 * Don't check for nsc_held() for the device number values
-	 * since these are magically created and cannot change when
-	 * the fd is not reserved.
-	 */
-
-	if (strcmp(name, NSC_DEVMAJ) != 0 &&
-	    strcmp(name, NSC_DEVMIN) != 0 &&
-	    !nsc_held(fd))
-		return (0);
-
-	mutex_enter(&_nsc_devval_lock);
-
-	dv = fd->sf_dev->nsc_values;
-	val = NULL;
-
-	if (dv != NULL) {
-		for (val = dv->dv_values; val; val = val->sv_next) {
-			if (strcmp(val->sv_name, name) == 0) {
-				*vp = val->sv_value;
-				break;
-			}
-		}
-	}
-
-	mutex_exit(&_nsc_devval_lock);
-
-	return (val ? 1 : 0);
-}
-
-
-/*
- * char *
- * nsc_shared (nsc_fd_t *fd)
- *	Device is currently shared.
- *
- * Calling/Exit State:
- *	The device lock must be held across calls to this
- *	this function.
- *
- *	Returns an indication of whether the device accessed
- *	by the file descriptor is currently referenced by more
- *	than one user.
- *
- *	This is only intended for use in performance critical
- *	situations.
- */
-int
-nsc_shared(fd)
-nsc_fd_t *fd;
-{
-	nsc_iodev_t *iodev;
-	int cnt = 0;
-
-	if (!fd)
-		return (0);
-	if (!fd->sf_iodev)
-		return (1);
-
-	for (iodev = fd->sf_dev->nsc_list; iodev; iodev = iodev->si_next)
-		for (fd = iodev->si_open; fd; fd = fd->sf_next)
-			if (!fd->sf_owner && cnt++)
-				return (1);
-
-	return (0);
-}
-
-
-/*
- * kmutex_t *
- * nsc_lock_addr (nsc_fd_t *fd)
- *	Address of device lock.
- *
- * Calling/Exit State:
- *	Returns a pointer to the spin lock associated with the
- *	device.
- *
- * Description:
- *	This is only intended for use in performance critical
- *	situations in conjunction with nsc_reserve_lk.
- */
-kmutex_t *
-nsc_lock_addr(fd)
-nsc_fd_t *fd;
-{
-	return (&fd->sf_dev->nsc_lock);
-}
-
-
-/*
- * int
- * _nsc_call_io (long f, blind_t a, blind_t b, blind_t c)
- *	Call information function.
- *
- * Calling/Exit State:
- *	Returns result from function or 0 if not available.
- *	f represents the offset into the I/O structure at which
- *	the required function can be found and a, b, c are the
- *	desired arguments.
- *
- * Description:
- *	Calls the requested function for the first available
- *	cache interface.
- */
-int
-_nsc_call_io(long f, blind_t a, blind_t b, blind_t c)
-{
-	nsc_io_t *io;
-	int (*fn)();
-	int rc;
-
-	io = _nsc_reserve_io(NULL, NSC_SDBC_ID);
-	if (!io)
-		io = _nsc_reserve_io(NULL, NSC_NULL);
-
-	fn = (blindfn_t)(((long *)io)[f]);
-	rc = (*fn)(a, b, c);
-
-	_nsc_release_io(io);
-	return (rc);
-}
-
-
-/*
- * nsc_io_t *
- * _nsc_reserve_io (char *, int type)
- *	Reserve I/O module.
- *
- * Calling/Exit State:
- *	Returns address of I/O structure matching specified
- *	type, or NULL.
- *
- * Description:
- *	Searches for an appropriate I/O module and increments
- *	the reference count to prevent it being unregistered.
- */
-nsc_io_t *
-_nsc_reserve_io(path, type)
-char *path;
-int type;
-{
-	nsc_io_t *io;
-
-	mutex_enter(&_nsc_io_lock);
-
-	if ((io = _nsc_find_io(path, type, NULL)) != 0)
-		io->refcnt++;
-
-	mutex_exit(&_nsc_io_lock);
-	return (io);
-}
-
-
-/*
- * static nsc_io_t *
- * _nsc_find_io (char *path, int type, int *changed)
- *	Find I/O module.
- *
- * Calling/Exit State:
- *	The _nsc_io_lock must be held across calls to
- *	this function.
- *
- *	Returns address of I/O structure matching specified
- *	type, or NULL.
- *
- *	'changed' will be set to non-zero if there is a pending
- *	nsc_path_t that matches the criteria for the requested type.
- *	This allows nsctl to distinguish between multiple
- *	nsc_register_path's done by the same I/O provider.
- *
- * Description:
- *	Searches for an appropriate I/O module.
- *
- *	1.  If <type> is a single module id find the specified I/O
- *	    module by module id.
- *
- *	2.  Find the highest module that provides any of the I/O types
- *	    included in <type>, taking into account any modules
- *	    registered via the nsc_register_path() interface if <path>
- *	    is non-NULL.
- *
- *	3.  Find an I/O module following the rules in (2), but whose
- *	    module id is less than the id OR'd into <type>.
- *
- *	If no module is found by the above algorithms and NSC_NULL was
- *	included in <type>, return the _nsc_null_io module. Otherwise
- *	return NULL.
- */
-static nsc_io_t *
-_nsc_find_io(char *path, int type, int *changed)
-{
-	nsc_path_t *sp = NULL;
-	nsc_path_t *pp = NULL;
-	nsc_io_t *io;
-
-	type &= NSC_TYPES;
-
-	if (path) {
-		for (sp = _nsc_path_top; sp; sp = sp->sp_next) {
-			if ((type & NSC_ID) &&
-			    sp->sp_io->id >= (type & NSC_IDS))
-				continue;
-
-			if (sp->sp_pend || (type & sp->sp_type) == 0)
-				continue;
-
-			if (nsc_strmatch(path, sp->sp_path))
-				break;
-		}
-
-		if (sp) {
-			/* look for matching pending paths */
-			for (pp = _nsc_path_top; pp; pp = pp->sp_next) {
-				if (pp->sp_pend &&
-				    (type & pp->sp_type) &&
-				    nsc_strmatch(path, pp->sp_path)) {
-					break;
-				}
-			}
-		}
-	}
-
-	for (io = _nsc_io_top; io; io = io->next) {
-		if (io->pend)
-			continue;
-
-		if (type & NSC_ID) {
-			if ((type & ~NSC_IDS) == 0) {
-				if (io->id == type)
-					break;
-				continue;
-			}
-
-			if (io->id >= (type & NSC_IDS))
-				continue;
-		}
-
-		if (io->provide & type)
-			break;
-	}
-
-	if (pp && (!io || pp->sp_io->id >= io->id)) {
-		/*
-		 * Mark this as a path change.
-		 */
-		if (changed) {
-			*changed = 1;
-		}
-	}
-
-	if (sp && (!io || sp->sp_io->id >= io->id))
-		io = sp->sp_io;
-
-	if (!io && !(type & NSC_NULL))
-		return (NULL);
-
-	if (!io)
-		io = _nsc_null_io;
-
-	return (io);
-}
-
-
-/*
- * void
- * _nsc_release_io (nsc_io_t *)
- *	Release I/O module.
- *
- * Description:
- *	Releases reference to I/O structure and wakes up
- *	anybody waiting on it.
- */
-void
-_nsc_release_io(io)
-nsc_io_t *io;
-{
-	mutex_enter(&_nsc_io_lock);
-
-	io->refcnt--;
-	cv_broadcast(&io->cv);
-
-	mutex_exit(&_nsc_io_lock);
-}
-
-
-/*
- * static int
- * _nsc_alloc_fd (char *path, int type, int flag, nsc_fd_t **fdp)
- *	Allocate file descriptor structure.
- *
- * Calling/Exit State:
- *	Stores address of file descriptor through fdp and
- *	returns 0 on success, otherwise returns error code.
- *
- * Description:
- *	A new file descriptor is allocated and linked in to
- *	the file descriptor chain which is protected by the
- *	device lock.
- *
- *	On return the file descriptor must contain all the
- *	information necessary to perform an open. Details
- *	specific to user callbacks are not required yet.
- */
-static int
-_nsc_alloc_fd(path, type, flag, fdp)
-char *path;
-int type, flag;
-nsc_fd_t **fdp;
-{
-	nsc_dev_t *dev;
-	nsc_fd_t *fd;
-	int rc;
-
-	if (!(fd = (nsc_fd_t *)nsc_kmem_zalloc(
-				sizeof (*fd), KM_SLEEP, _nsc_local_mem)))
-		return (ENOMEM);
-
-	if ((rc = _nsc_alloc_dev(path, &dev)) != 0) {
-		nsc_kmem_free(fd, sizeof (*fd));
-		return (rc);
-	}
-
-	mutex_enter(&dev->nsc_lock);
-
-	fd->sf_type = type;
-	fd->sf_flag = flag;
-	fd->sf_dev = dev;
-	fd->sf_next = dev->nsc_close;
-	dev->nsc_close = fd;
-
-	mutex_exit(&dev->nsc_lock);
-
-	*fdp = fd;
-	return (0);
-}
-
-
-/*
- * static int
- * _nsc_free_fd (nsc_fd_t *)
- *	Free file descriptor.
- *
- * Description:
- *	The file descriptor is removed from the chain and free'd
- *	once pending activity has completed.
- */
-static void
-_nsc_free_fd(fd)
-nsc_fd_t *fd;
-{
-	nsc_dev_t *dev = fd->sf_dev;
-	nsc_fd_t **fdp;
-
-	if (!fd)
-		return;
-
-	mutex_enter(&dev->nsc_lock);
-
-	for (fdp = &dev->nsc_close; *fdp; fdp = &(*fdp)->sf_next)
-		if (*fdp == fd) {
-			*fdp = fd->sf_next;
-			break;
-		}
-
-	if (dev->nsc_wait || dev->nsc_refcnt <= 0)
-		cv_broadcast(&dev->nsc_cv);
-
-	while (fd->sf_pend)
-		(void) _nsc_wait_dev(dev, 0);
-
-	mutex_exit(&dev->nsc_lock);
-
-	_nsc_free_dev(dev);
-
-	nsc_kmem_free(fd, sizeof (*fd));
-}
-
-
-/*
- * static void
- * _nsc_relink_fd (nsc_fd_t *fd, nsc_fd_t **from,
- *				nsc_fd_t **to, nsc_iodev_t *iodev)
- *	Relink file descriptor.
- *
- * Description:
- *	Remove the file descriptor from the 'from' chain and
- *	add it to the 'to' chain. The busy flag in iodev is
- *	used to prevent modifications to the chain whilst a
- *	callback is in progress.
- */
-static void
-_nsc_relink_fd(nsc_fd_t *fd, nsc_fd_t **from, nsc_fd_t **to, nsc_iodev_t *iodev)
-{
-	nsc_dev_t *dev = fd->sf_dev;
-	nsc_fd_t **fdp;
-
-	mutex_enter(&dev->nsc_lock);
-
-	while (iodev->si_busy)
-		(void) _nsc_wait_dev(dev, 0);
-
-	for (fdp = from; *fdp; fdp = &(*fdp)->sf_next)
-		if (*fdp == fd) {
-			*fdp = fd->sf_next;
-			break;
-		}
-
-	fd->sf_next = (*to);
-	(*to) = fd;
-
-	mutex_exit(&dev->nsc_lock);
-}
-
-
-/*
- * static int
- * _nsc_alloc_iodev (nsc_dev_t *dev, int type, nsc_iodev_t **iodevp)
- *	Allocate I/O device structure.
- *
- * Calling/Exit State:
- *	Stores address of I/O device structure through iodevp
- *	and returns 0 on success, otherwise returns error code.
- *
- * Description:
- *	If an entry for the I/O device already exists increment
- *	the reference count and return the address, otherwise
- *	allocate a new structure.
- *
- *	A new structure is allocated before scanning the chain
- *	to avoid calling the memory allocator with a spin lock
- *	held. If an entry is found the new structure is free'd.
- *
- *	The I/O device chain is protected by the device lock.
- */
-static int
-_nsc_alloc_iodev(dev, type, iodevp)
-nsc_dev_t *dev;
-int type;
-nsc_iodev_t **iodevp;
-{
-	nsc_iodev_t *iodev, *ip;
-	nsc_io_t *io;
-
-	if (!(iodev = (nsc_iodev_t *)nsc_kmem_zalloc(
-				sizeof (*iodev), KM_SLEEP, _nsc_local_mem)))
-		return (ENOMEM);
-
-	mutex_init(&iodev->si_lock, NULL, MUTEX_DRIVER, NULL);
-	cv_init(&iodev->si_cv, NULL, CV_DRIVER, NULL);
-
-	if (!(io = _nsc_reserve_io(dev->nsc_path, type))) {
-		mutex_destroy(&iodev->si_lock);
-		cv_destroy(&iodev->si_cv);
-		nsc_kmem_free(iodev, sizeof (*iodev));
-		return (ENXIO);
-	}
-
-	iodev->si_refcnt++;
-	iodev->si_io = io;
-	iodev->si_dev = dev;
-
-	mutex_enter(&_nsc_io_lock);
-	dev->nsc_refcnt++;
-	mutex_exit(&_nsc_io_lock);
-
-	mutex_enter(&dev->nsc_lock);
-
-	for (ip = dev->nsc_list; ip; ip = ip->si_next)
-		if (ip->si_io == io) {
-			ip->si_refcnt++;
-			break;
-		}
-
-	if (!ip) {
-		iodev->si_next = dev->nsc_list;
-		dev->nsc_list = iodev;
-	}
-
-	mutex_exit(&dev->nsc_lock);
-
-	if (ip) {
-		_nsc_free_iodev(iodev);
-		iodev = ip;
-	}
-
-	*iodevp = iodev;
-	return (0);
-}
-
-
-/*
- * static int
- * _nsc_free_iodev (nsc_iodev_t *iodev)
- *	Free I/O device structure.
- *
- * Description:
- *	Decrements the reference count of a previously allocated
- *	I/O device structure. If this is the last reference it
- *	is removed from the device chain and free'd once pending
- *	activity has completed.
- */
-static void
-_nsc_free_iodev(nsc_iodev_t *iodev)
-{
-	nsc_iodev_t **ipp;
-	nsc_dev_t *dev;
-
-	if (!iodev)
-		return;
-
-	dev = iodev->si_dev;
-
-	mutex_enter(&dev->nsc_lock);
-
-	if (--iodev->si_refcnt > 0) {
-		mutex_exit(&dev->nsc_lock);
-		return;
-	}
-
-	for (ipp = &dev->nsc_list; *ipp; ipp = &(*ipp)->si_next)
-		if (*ipp == iodev) {
-			*ipp = iodev->si_next;
-			break;
-		}
-
-	if (dev->nsc_wait || dev->nsc_refcnt <= 0)
-		cv_broadcast(&dev->nsc_cv);
-
-	while (iodev->si_pend || iodev->si_rpend || iodev->si_busy)
-		(void) _nsc_wait_dev(dev, 0);
-
-	mutex_exit(&dev->nsc_lock);
-
-	_nsc_release_io(iodev->si_io);
-	_nsc_free_dev(dev);
-
-	mutex_destroy(&iodev->si_lock);
-	cv_destroy(&iodev->si_cv);
-
-	nsc_kmem_free(iodev, sizeof (*iodev));
-}
-
-
-/*
- * static int
- * _nsc_alloc_dev (char *path, nsc_dev_t **devp)
- *	Allocate device structure.
- *
- * Calling/Exit State:
- *	Stores address of device structure through devp
- *	and returns 0 on success, otherwise returns error
- *	code.
- *
- * Description:
- *	If an entry for the device already exists increment
- *	the reference count and return the address, otherwise
- *	allocate a new structure.
- *
- *	A new structure is allocated before scanning the device
- *	chain to avoid calling the memory allocator with a spin
- *	lock held. If the device is found the new structure is
- *	free'd.
- *
- *	The device chain is protected by _nsc_io_lock.
- */
-static int
-_nsc_alloc_dev(char *path, nsc_dev_t **devp)
-{
-	nsc_dev_t *dev, *dp, **ddp;
-	nsc_devval_t *dv;
-	nsc_rval_t *rval;
-	ncall_t *ncall;
-	int rc;
-
-	if (!(dev = (nsc_dev_t *)nsc_kmem_zalloc(
-	    sizeof (*dev), KM_SLEEP, _nsc_local_mem)))
-		return (ENOMEM);
-
-	dev->nsc_refcnt++;
-
-	mutex_init(&dev->nsc_lock, NULL, MUTEX_DRIVER, NULL);
-	cv_init(&dev->nsc_cv, NULL, CV_DRIVER, NULL);
-
-	dev->nsc_phash = nsc_strhash(path);
-	dev->nsc_path = nsc_strdup(path);
-
-	mutex_enter(&_nsc_io_lock);
-
-	dev->nsc_next = _nsc_dev_pend;
-	_nsc_dev_pend = dev;
-
-	mutex_exit(&_nsc_io_lock);
-
-	mutex_enter(&_nsc_io_lock);
-
-	for (dp = _nsc_dev_top; dp; dp = dp->nsc_next)
-		if (dp->nsc_phash == dev->nsc_phash &&
-		    strcmp(dp->nsc_path, dev->nsc_path) == 0) {
-			dp->nsc_refcnt++;
-			break;
-		}
-
-	if (!dp) {
-		for (ddp = &_nsc_dev_pend; *ddp; ddp = &(*ddp)->nsc_next)
-			if (*ddp == dev) {
-				*ddp = dev->nsc_next;
-				break;
-			}
-
-		dev->nsc_next = _nsc_dev_top;
-		_nsc_dev_top = dev;
-	}
-
-	mutex_exit(&_nsc_io_lock);
-
-	if (dp) {
-		_nsc_free_dev(dev);
-		dev = dp;
-	}
-
-	/*
-	 * Try and find the device/values header for this device
-	 * and link it back to the device structure.
-	 */
-
-	mutex_enter(&_nsc_devval_lock);
-
-	if (dev->nsc_values == NULL) {
-		for (dv = _nsc_devval_top; dv; dv = dv->dv_next) {
-			if (dv->dv_phash == dev->nsc_phash &&
-			    strcmp(dv->dv_path, dev->nsc_path) == 0) {
-				dev->nsc_values = dv;
-				break;
-			}
-		}
-	}
-
-	mutex_exit(&_nsc_devval_lock);
-
-	/*
-	 * Refresh the device/values from the other node
-	 */
-
-	rval = nsc_kmem_zalloc(sizeof (*rval), KM_SLEEP, _nsc_local_mem);
-	if (rval == NULL) {
-		goto out;
-	}
-
-	rc = ncall_alloc(ncall_mirror(ncall_self()), 0, 0, &ncall);
-	if (rc == 0) {
-		(void) strncpy(rval->path, path, sizeof (rval->path));
-
-		rc = ncall_put_data(ncall, rval, sizeof (*rval));
-		if (rc == 0) {
-			/*
-			 * Send synchronously and read a reply
-			 * so that we know that the updates
-			 * have completed before this
-			 * function returns.
-			 */
-			if (ncall_send(ncall, 0, NSC_SETVAL_ALL) == 0)
-				(void) ncall_read_reply(ncall, 1, &rc);
-		}
-
-		ncall_free(ncall);
-	}
-
-	nsc_kmem_free(rval, sizeof (*rval));
-
-out:
-	*devp = dev;
-	return (0);
-}
-
-
-/*
- * static void
- * _nsc_free_dev (nsc_dev_t *dev)
- *	Free device structure.
- *
- * Description:
- *	Decrements the reference count of a previously allocated
- *	device structure. If this is the last reference it is
- *	removed from the device chain and free'd once pending
- *	activity has completed.
- *
- *	Whilst waiting for pending activity to cease the device is
- *	relinked onto the pending chain.
- */
-static void
-_nsc_free_dev(dev)
-nsc_dev_t *dev;
-{
-	nsc_dev_t **ddp;
-
-	if (!dev)
-		return;
-
-	mutex_enter(&_nsc_io_lock);
-
-	if (--dev->nsc_refcnt > 0) {
-		mutex_exit(&_nsc_io_lock);
-		return;
-	}
-
-	for (ddp = &_nsc_dev_top; *ddp; ddp = &(*ddp)->nsc_next)
-		if (*ddp == dev) {
-			*ddp = dev->nsc_next;
-			dev->nsc_next = _nsc_dev_pend;
-			_nsc_dev_pend = dev;
-			break;
-		}
-
-	mutex_exit(&_nsc_io_lock);
-
-	mutex_enter(&dev->nsc_lock);
-
-	while (dev->nsc_pend || dev->nsc_rpend || dev->nsc_wait) {
-		cv_wait(&dev->nsc_cv, &dev->nsc_lock);
-	}
-
-	mutex_exit(&dev->nsc_lock);
-
-	mutex_enter(&_nsc_io_lock);
-
-	for (ddp = &_nsc_dev_pend; *ddp; ddp = &(*ddp)->nsc_next)
-		if (*ddp == dev) {
-			*ddp = dev->nsc_next;
-			break;
-		}
-
-	mutex_exit(&_nsc_io_lock);
-
-	mutex_destroy(&dev->nsc_lock);
-	cv_destroy(&dev->nsc_cv);
-	nsc_strfree(dev->nsc_path);
-
-	nsc_kmem_free(dev, sizeof (*dev));
-}
-
-
-/*
- * static nsc_io_t *
- * _nsc_alloc_io (int id, char *name, int flag)
- *	Allocate an I/O structure.
- *
- * Calling/Exit State:
- *	Returns the address of the I/O structure, or NULL.
- */
-static nsc_io_t *
-_nsc_alloc_io(id, name, flag)
-int id;
-char *name;
-int flag;
-{
-	nsc_io_t *io;
-
-	if (!(io = (nsc_io_t *)nsc_kmem_zalloc(
-			sizeof (*io), KM_NOSLEEP, _nsc_local_mem)))
-		return (NULL);
-
-	cv_init(&io->cv, NULL, CV_DRIVER, NULL);
-
-	io->id = id;
-	io->name = name;
-	io->flag = flag;
-
-	return (io);
-}
-
-
-/*
- * static void
- * _nsc_free_io (int id, char *name, int flag)
- *	Free an I/O structure.
- *
- * Calling/Exit State:
- *	Free the I/O structure and remove it from the chain.
- */
-static void
-_nsc_free_io(io)
-nsc_io_t *io;
-{
-	nsc_io_t **iop;
-
-	mutex_enter(&_nsc_io_lock);
-
-	for (iop = &_nsc_io_top; *iop; iop = &(*iop)->next)
-		if (*iop == io)
-			break;
-
-	if (*iop)
-		(*iop) = io->next;
-
-	mutex_exit(&_nsc_io_lock);
-
-	cv_destroy(&io->cv);
-	nsc_kmem_free(io, sizeof (*io));
-}
