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/debug.h>
287836SJohn.Forte@Sun.COM #include <sys/ksynch.h>
297836SJohn.Forte@Sun.COM #include <sys/kmem.h>
307836SJohn.Forte@Sun.COM #include <sys/cmn_err.h>
317836SJohn.Forte@Sun.COM #include <sys/errno.h>
327836SJohn.Forte@Sun.COM #include <sys/ddi.h>
337836SJohn.Forte@Sun.COM
347836SJohn.Forte@Sun.COM #include <sys/ncall/ncall.h>
357836SJohn.Forte@Sun.COM
367836SJohn.Forte@Sun.COM #define __NSC_GEN__
377836SJohn.Forte@Sun.COM #include "nsc_dev.h"
387836SJohn.Forte@Sun.COM
397836SJohn.Forte@Sun.COM #ifdef DS_DDICT
407836SJohn.Forte@Sun.COM #include "../contract.h"
417836SJohn.Forte@Sun.COM #endif
427836SJohn.Forte@Sun.COM
437836SJohn.Forte@Sun.COM #include "../nsctl.h"
447836SJohn.Forte@Sun.COM
457836SJohn.Forte@Sun.COM #define NSC_DEVMIN "DevMin"
467836SJohn.Forte@Sun.COM #define NSC_DEVMAJ "DevMaj"
477836SJohn.Forte@Sun.COM
487836SJohn.Forte@Sun.COM #define _I(x) (((long)(&((nsc_io_t *)0)->x))/sizeof (long))
497836SJohn.Forte@Sun.COM #define _F(x) (((long)(&((nsc_fd_t *)0)->x))/sizeof (long))
507836SJohn.Forte@Sun.COM
517836SJohn.Forte@Sun.COM
527836SJohn.Forte@Sun.COM nsc_def_t _nsc_io_def[] = {
537836SJohn.Forte@Sun.COM "Open", (uintptr_t)nsc_null, _I(open),
547836SJohn.Forte@Sun.COM "Close", (uintptr_t)nsc_null, _I(close),
557836SJohn.Forte@Sun.COM "Attach", (uintptr_t)nsc_null, _I(attach),
567836SJohn.Forte@Sun.COM "Detach", (uintptr_t)nsc_null, _I(detach),
577836SJohn.Forte@Sun.COM "Flush", (uintptr_t)nsc_null, _I(flush),
587836SJohn.Forte@Sun.COM "Provide", 0, _I(provide),
597836SJohn.Forte@Sun.COM 0, 0, 0
607836SJohn.Forte@Sun.COM };
617836SJohn.Forte@Sun.COM
627836SJohn.Forte@Sun.COM nsc_def_t _nsc_fd_def[] = {
637836SJohn.Forte@Sun.COM "Pinned", (uintptr_t)nsc_null, _F(sf_pinned),
647836SJohn.Forte@Sun.COM "Unpinned", (uintptr_t)nsc_null, _F(sf_unpinned),
657836SJohn.Forte@Sun.COM "Attach", (uintptr_t)nsc_null, _F(sf_attach),
667836SJohn.Forte@Sun.COM "Detach", (uintptr_t)nsc_null, _F(sf_detach),
677836SJohn.Forte@Sun.COM "Flush", (uintptr_t)nsc_null, _F(sf_flush),
687836SJohn.Forte@Sun.COM 0, 0, 0
697836SJohn.Forte@Sun.COM };
707836SJohn.Forte@Sun.COM
717836SJohn.Forte@Sun.COM kmutex_t _nsc_io_lock;
727836SJohn.Forte@Sun.COM kmutex_t _nsc_devval_lock;
737836SJohn.Forte@Sun.COM
747836SJohn.Forte@Sun.COM nsc_io_t *_nsc_io_top = NULL;
757836SJohn.Forte@Sun.COM nsc_io_t *_nsc_null_io = NULL;
767836SJohn.Forte@Sun.COM nsc_dev_t *_nsc_dev_top = NULL;
777836SJohn.Forte@Sun.COM nsc_dev_t *_nsc_dev_pend = NULL;
787836SJohn.Forte@Sun.COM nsc_path_t *_nsc_path_top = NULL;
797836SJohn.Forte@Sun.COM nsc_devval_t *_nsc_devval_top = NULL;
807836SJohn.Forte@Sun.COM
817836SJohn.Forte@Sun.COM extern nsc_def_t _nsc_disk_def[];
827836SJohn.Forte@Sun.COM extern nsc_def_t _nsc_cache_def[];
837836SJohn.Forte@Sun.COM
847836SJohn.Forte@Sun.COM extern nsc_mem_t *_nsc_local_mem;
857836SJohn.Forte@Sun.COM extern nsc_rmmap_t *_nsc_global_map;
867836SJohn.Forte@Sun.COM
877836SJohn.Forte@Sun.COM static clock_t _nsc_io_lbolt;
887836SJohn.Forte@Sun.COM
897836SJohn.Forte@Sun.COM static nsc_io_t *_nsc_find_io(char *, int, int *);
907836SJohn.Forte@Sun.COM nsc_io_t *_nsc_reserve_io(char *, int);
917836SJohn.Forte@Sun.COM static nsc_io_t *_nsc_alloc_io(int, char *, int);
927836SJohn.Forte@Sun.COM
937836SJohn.Forte@Sun.COM static int _nsc_open_fn(nsc_fd_t *, int);
947836SJohn.Forte@Sun.COM static int _nsc_close_fn(nsc_fd_t *);
957836SJohn.Forte@Sun.COM static int _nsc_alloc_fd(char *, int, int, nsc_fd_t **);
967836SJohn.Forte@Sun.COM static int _nsc_alloc_iodev(nsc_dev_t *, int, nsc_iodev_t **);
977836SJohn.Forte@Sun.COM static int _nsc_alloc_dev(char *, nsc_dev_t **);
987836SJohn.Forte@Sun.COM static int _nsc_reopen_io(char *, int);
997836SJohn.Forte@Sun.COM static int _nsc_reopen_dev(nsc_dev_t *, int);
1007836SJohn.Forte@Sun.COM static int _nsc_relock_dev(nsc_dev_t *, nsc_fd_t *, nsc_iodev_t *);
1017836SJohn.Forte@Sun.COM static int _nsc_reopen_fd(nsc_fd_t *, int);
1027836SJohn.Forte@Sun.COM static int _nsc_decode_io(nsc_def_t *, nsc_io_t *);
1037836SJohn.Forte@Sun.COM
1047836SJohn.Forte@Sun.COM void _nsc_release_io(nsc_io_t *);
1057836SJohn.Forte@Sun.COM static void _nsc_free_fd(nsc_fd_t *);
1067836SJohn.Forte@Sun.COM static void _nsc_free_iodev(nsc_iodev_t *);
1077836SJohn.Forte@Sun.COM static void _nsc_free_dev(nsc_dev_t *);
1087836SJohn.Forte@Sun.COM static void _nsc_free_io(nsc_io_t *);
1097836SJohn.Forte@Sun.COM static void _nsc_relink_fd(nsc_fd_t *, nsc_fd_t **, nsc_fd_t **, nsc_iodev_t *);
1107836SJohn.Forte@Sun.COM
1117836SJohn.Forte@Sun.COM static int _nsc_setval(nsc_dev_t *, char *, char *, int, int);
1127836SJohn.Forte@Sun.COM static void r_nsc_setval(ncall_t *, int *);
1137836SJohn.Forte@Sun.COM static void r_nsc_setval_all(ncall_t *, int *);
1147836SJohn.Forte@Sun.COM
1157836SJohn.Forte@Sun.COM extern void _nsc_add_disk(nsc_io_t *);
1167836SJohn.Forte@Sun.COM extern void _nsc_add_cache(nsc_io_t *);
1177836SJohn.Forte@Sun.COM
1187836SJohn.Forte@Sun.COM
1197836SJohn.Forte@Sun.COM /*
1207836SJohn.Forte@Sun.COM * void
1217836SJohn.Forte@Sun.COM * _nsc_init_dev (void)
1227836SJohn.Forte@Sun.COM * Initialise device subsystem.
1237836SJohn.Forte@Sun.COM *
1247836SJohn.Forte@Sun.COM * Calling/Exit State:
1257836SJohn.Forte@Sun.COM * Called at driver initialisation time to allocate necessary
1267836SJohn.Forte@Sun.COM * data structures.
1277836SJohn.Forte@Sun.COM */
1287836SJohn.Forte@Sun.COM void
_nsc_init_dev()1297836SJohn.Forte@Sun.COM _nsc_init_dev()
1307836SJohn.Forte@Sun.COM {
1317836SJohn.Forte@Sun.COM mutex_init(&_nsc_io_lock, NULL, MUTEX_DRIVER, NULL);
1327836SJohn.Forte@Sun.COM mutex_init(&_nsc_devval_lock, NULL, MUTEX_DRIVER, NULL);
1337836SJohn.Forte@Sun.COM
1347836SJohn.Forte@Sun.COM _nsc_null_io = nsc_register_io("null", NSC_NULL, (nsc_def_t *)0);
1357836SJohn.Forte@Sun.COM
1367836SJohn.Forte@Sun.COM if (!_nsc_null_io)
1377836SJohn.Forte@Sun.COM cmn_err(CE_PANIC, "nsctl: nsc_init_dev");
1387836SJohn.Forte@Sun.COM
1397836SJohn.Forte@Sun.COM ncall_register_svc(NSC_SETVAL_ALL, r_nsc_setval_all);
1407836SJohn.Forte@Sun.COM ncall_register_svc(NSC_SETVAL, r_nsc_setval);
1417836SJohn.Forte@Sun.COM }
1427836SJohn.Forte@Sun.COM
1437836SJohn.Forte@Sun.COM
1447836SJohn.Forte@Sun.COM void
_nsc_deinit_dev()1457836SJohn.Forte@Sun.COM _nsc_deinit_dev()
1467836SJohn.Forte@Sun.COM {
1477836SJohn.Forte@Sun.COM nsc_devval_t *dv;
1487836SJohn.Forte@Sun.COM nsc_val_t *vp;
1497836SJohn.Forte@Sun.COM
1507836SJohn.Forte@Sun.COM mutex_enter(&_nsc_devval_lock);
1517836SJohn.Forte@Sun.COM
1527836SJohn.Forte@Sun.COM while ((dv = _nsc_devval_top) != NULL) {
1537836SJohn.Forte@Sun.COM while ((vp = dv->dv_values) != NULL) {
1547836SJohn.Forte@Sun.COM dv->dv_values = vp->sv_next;
1557836SJohn.Forte@Sun.COM nsc_kmem_free(vp, sizeof (*vp));
1567836SJohn.Forte@Sun.COM }
1577836SJohn.Forte@Sun.COM
1587836SJohn.Forte@Sun.COM _nsc_devval_top = dv->dv_next;
1597836SJohn.Forte@Sun.COM nsc_kmem_free(dv, sizeof (*dv));
1607836SJohn.Forte@Sun.COM }
1617836SJohn.Forte@Sun.COM
1627836SJohn.Forte@Sun.COM mutex_exit(&_nsc_devval_lock);
1637836SJohn.Forte@Sun.COM
1647836SJohn.Forte@Sun.COM ncall_unregister_svc(NSC_SETVAL_ALL);
1657836SJohn.Forte@Sun.COM ncall_unregister_svc(NSC_SETVAL);
1667836SJohn.Forte@Sun.COM
1677836SJohn.Forte@Sun.COM mutex_destroy(&_nsc_devval_lock);
1687836SJohn.Forte@Sun.COM mutex_destroy(&_nsc_io_lock);
1697836SJohn.Forte@Sun.COM }
1707836SJohn.Forte@Sun.COM
1717836SJohn.Forte@Sun.COM
1727836SJohn.Forte@Sun.COM /*
1737836SJohn.Forte@Sun.COM * nsc_io_t *
1747836SJohn.Forte@Sun.COM * nsc_register_io (char *name, int type, nsc_def_t *def)
1757836SJohn.Forte@Sun.COM * Register an I/O module.
1767836SJohn.Forte@Sun.COM *
1777836SJohn.Forte@Sun.COM * Calling/Exit State:
1787836SJohn.Forte@Sun.COM * Returns a token for use in future calls to nsc_unregister_io.
1797836SJohn.Forte@Sun.COM * The ID and flags for the module are specified by 'type' and
1807836SJohn.Forte@Sun.COM * the appropriate entry points are defined using 'def'. If
1817836SJohn.Forte@Sun.COM * registration fails NULL is returned.
1827836SJohn.Forte@Sun.COM *
1837836SJohn.Forte@Sun.COM * Description:
1847836SJohn.Forte@Sun.COM * Registers an I/O module for use by subsequent calls to
1857836SJohn.Forte@Sun.COM * nsc_open.
1867836SJohn.Forte@Sun.COM */
1877836SJohn.Forte@Sun.COM nsc_io_t *
nsc_register_io(name,type,def)1887836SJohn.Forte@Sun.COM nsc_register_io(name, type, def)
1897836SJohn.Forte@Sun.COM char *name;
1907836SJohn.Forte@Sun.COM int type;
1917836SJohn.Forte@Sun.COM nsc_def_t *def;
1927836SJohn.Forte@Sun.COM {
1937836SJohn.Forte@Sun.COM nsc_io_t *io, *tp;
1947836SJohn.Forte@Sun.COM int rc, id, flag;
1957836SJohn.Forte@Sun.COM nsc_io_t **iop;
1967836SJohn.Forte@Sun.COM
1977836SJohn.Forte@Sun.COM id = (type & NSC_TYPES);
1987836SJohn.Forte@Sun.COM flag = (type & ~NSC_TYPES);
1997836SJohn.Forte@Sun.COM
2007836SJohn.Forte@Sun.COM if ((!(id & NSC_ID) || (id & ~NSC_IDS)) &&
2017836SJohn.Forte@Sun.COM (id != NSC_NULL || _nsc_null_io))
2027836SJohn.Forte@Sun.COM return (NULL);
2037836SJohn.Forte@Sun.COM
2047836SJohn.Forte@Sun.COM if (!(io = _nsc_alloc_io(id, name, flag)))
2057836SJohn.Forte@Sun.COM return (NULL);
2067836SJohn.Forte@Sun.COM
2077836SJohn.Forte@Sun.COM rc = _nsc_decode_io(def, io);
2087836SJohn.Forte@Sun.COM
2097836SJohn.Forte@Sun.COM if (!rc && id != NSC_NULL) {
2107836SJohn.Forte@Sun.COM _nsc_free_io(io);
2117836SJohn.Forte@Sun.COM return (NULL);
2127836SJohn.Forte@Sun.COM }
2137836SJohn.Forte@Sun.COM
2147836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
2157836SJohn.Forte@Sun.COM
2167836SJohn.Forte@Sun.COM for (tp = _nsc_io_top; tp; tp = tp->next) {
2177836SJohn.Forte@Sun.COM if (strcmp(tp->name, name) == 0 || tp->id == id) {
2187836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
2197836SJohn.Forte@Sun.COM _nsc_free_io(io);
2207836SJohn.Forte@Sun.COM return (NULL);
2217836SJohn.Forte@Sun.COM }
2227836SJohn.Forte@Sun.COM }
2237836SJohn.Forte@Sun.COM
2247836SJohn.Forte@Sun.COM for (iop = &_nsc_io_top; *iop; iop = &(*iop)->next)
2257836SJohn.Forte@Sun.COM if (id >= (*iop)->id)
2267836SJohn.Forte@Sun.COM break;
2277836SJohn.Forte@Sun.COM
2287836SJohn.Forte@Sun.COM io->next = (*iop);
2297836SJohn.Forte@Sun.COM (*iop) = io;
2307836SJohn.Forte@Sun.COM
2317836SJohn.Forte@Sun.COM _nsc_io_lbolt = nsc_lbolt();
2327836SJohn.Forte@Sun.COM
2337836SJohn.Forte@Sun.COM while ((rc = _nsc_reopen_io(NULL, 0)) != 0)
2347836SJohn.Forte@Sun.COM if (rc != ERESTART)
2357836SJohn.Forte@Sun.COM break;
2367836SJohn.Forte@Sun.COM
2377836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
2387836SJohn.Forte@Sun.COM return (io);
2397836SJohn.Forte@Sun.COM }
2407836SJohn.Forte@Sun.COM
2417836SJohn.Forte@Sun.COM
2427836SJohn.Forte@Sun.COM /*
2437836SJohn.Forte@Sun.COM * static int
2447836SJohn.Forte@Sun.COM * _nsc_decode_io (nsc_def_t *def, nsc_io_t *io)
2457836SJohn.Forte@Sun.COM * Decode I/O module definition.
2467836SJohn.Forte@Sun.COM *
2477836SJohn.Forte@Sun.COM * Calling/Exit State:
2487836SJohn.Forte@Sun.COM * Returns TRUE if the definition contains an adequate
2497836SJohn.Forte@Sun.COM * description of an I/O module.
2507836SJohn.Forte@Sun.COM *
2517836SJohn.Forte@Sun.COM * Description:
2527836SJohn.Forte@Sun.COM * Decode the definition of an I/O module and supply
2537836SJohn.Forte@Sun.COM * translation routines where possible for operations
2547836SJohn.Forte@Sun.COM * that are not defined.
2557836SJohn.Forte@Sun.COM */
2567836SJohn.Forte@Sun.COM static int
_nsc_decode_io(def,io)2577836SJohn.Forte@Sun.COM _nsc_decode_io(def, io)
2587836SJohn.Forte@Sun.COM nsc_def_t *def;
2597836SJohn.Forte@Sun.COM nsc_io_t *io;
2607836SJohn.Forte@Sun.COM {
2617836SJohn.Forte@Sun.COM nsc_decode_param(def, _nsc_io_def, (long *)io);
2627836SJohn.Forte@Sun.COM nsc_decode_param(def, _nsc_disk_def, (long *)io);
2637836SJohn.Forte@Sun.COM nsc_decode_param(def, _nsc_cache_def, (long *)io);
2647836SJohn.Forte@Sun.COM
2657836SJohn.Forte@Sun.COM _nsc_add_disk(io);
2667836SJohn.Forte@Sun.COM _nsc_add_cache(io);
2677836SJohn.Forte@Sun.COM
2687836SJohn.Forte@Sun.COM return (1);
2697836SJohn.Forte@Sun.COM }
2707836SJohn.Forte@Sun.COM
2717836SJohn.Forte@Sun.COM
2727836SJohn.Forte@Sun.COM /*
2737836SJohn.Forte@Sun.COM * int
2747836SJohn.Forte@Sun.COM * nsc_unregister_io (nsc_io_t *io, int flag)
2757836SJohn.Forte@Sun.COM * Un-register an I/O module.
2767836SJohn.Forte@Sun.COM *
2777836SJohn.Forte@Sun.COM * Calling/Exit State:
2787836SJohn.Forte@Sun.COM * Returns 0 on success, otherwise returns an error code.
2797836SJohn.Forte@Sun.COM *
2807836SJohn.Forte@Sun.COM * Description:
2817836SJohn.Forte@Sun.COM * The specified I/O module is un-registered if possible.
2827836SJohn.Forte@Sun.COM * All open file descriptors using the module will be closed
2837836SJohn.Forte@Sun.COM * in preparation for a subsequent re-open.
2847836SJohn.Forte@Sun.COM *
2857836SJohn.Forte@Sun.COM * If NSC_PCATCH is specified and a signal is received,
2867836SJohn.Forte@Sun.COM * the unregister will be terminated and EINTR returned.
2877836SJohn.Forte@Sun.COM */
2887836SJohn.Forte@Sun.COM int
nsc_unregister_io(nsc_io_t * io,int flag)2897836SJohn.Forte@Sun.COM nsc_unregister_io(nsc_io_t *io, int flag)
2907836SJohn.Forte@Sun.COM {
2917836SJohn.Forte@Sun.COM nsc_path_t *sp;
2927836SJohn.Forte@Sun.COM nsc_io_t *xio;
2937836SJohn.Forte@Sun.COM int rc = 0;
2947836SJohn.Forte@Sun.COM
2957836SJohn.Forte@Sun.COM if (io == _nsc_null_io)
2967836SJohn.Forte@Sun.COM return (EINVAL);
2977836SJohn.Forte@Sun.COM
2987836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
2997836SJohn.Forte@Sun.COM
3007836SJohn.Forte@Sun.COM for (xio = _nsc_io_top; xio; xio = xio->next)
3017836SJohn.Forte@Sun.COM if (xio == io)
3027836SJohn.Forte@Sun.COM break;
3037836SJohn.Forte@Sun.COM
3047836SJohn.Forte@Sun.COM if (!xio || io->pend) {
3057836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
3067836SJohn.Forte@Sun.COM return (xio ? EALREADY : 0);
3077836SJohn.Forte@Sun.COM }
3087836SJohn.Forte@Sun.COM
3097836SJohn.Forte@Sun.COM io->pend = 1;
3107836SJohn.Forte@Sun.COM lp:
3117836SJohn.Forte@Sun.COM for (sp = _nsc_path_top; sp; sp = sp->sp_next)
3127836SJohn.Forte@Sun.COM if (sp->sp_io == io) {
3137836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
3147836SJohn.Forte@Sun.COM
3157836SJohn.Forte@Sun.COM if ((rc = nsc_unregister_path(sp, flag)) != 0) {
3167836SJohn.Forte@Sun.COM io->pend = 0;
3177836SJohn.Forte@Sun.COM return (rc);
3187836SJohn.Forte@Sun.COM }
3197836SJohn.Forte@Sun.COM
3207836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
3217836SJohn.Forte@Sun.COM goto lp;
3227836SJohn.Forte@Sun.COM }
3237836SJohn.Forte@Sun.COM
3247836SJohn.Forte@Sun.COM _nsc_io_lbolt = nsc_lbolt();
3257836SJohn.Forte@Sun.COM
3267836SJohn.Forte@Sun.COM while (io->refcnt && !rc) {
3277836SJohn.Forte@Sun.COM while ((rc = _nsc_reopen_io(NULL, flag)) != 0)
3287836SJohn.Forte@Sun.COM if (rc != ERESTART)
3297836SJohn.Forte@Sun.COM break;
3307836SJohn.Forte@Sun.COM
3317836SJohn.Forte@Sun.COM if (rc || !io->refcnt)
3327836SJohn.Forte@Sun.COM break;
3337836SJohn.Forte@Sun.COM
3347836SJohn.Forte@Sun.COM if (!cv_wait_sig(&io->cv, &_nsc_io_lock))
3357836SJohn.Forte@Sun.COM rc = EINTR;
3367836SJohn.Forte@Sun.COM }
3377836SJohn.Forte@Sun.COM
3387836SJohn.Forte@Sun.COM /*
3397836SJohn.Forte@Sun.COM * We have tried to get rid of all the IO provider's clients.
3407836SJohn.Forte@Sun.COM * If there are still anonymous buffers outstanding, then fail
3417836SJohn.Forte@Sun.COM * the unregister.
3427836SJohn.Forte@Sun.COM */
3437836SJohn.Forte@Sun.COM
3447836SJohn.Forte@Sun.COM if (!rc && io->abufcnt > 0)
3457836SJohn.Forte@Sun.COM rc = EUSERS;
3467836SJohn.Forte@Sun.COM
3477836SJohn.Forte@Sun.COM if (rc)
3487836SJohn.Forte@Sun.COM io->pend = 0;
3497836SJohn.Forte@Sun.COM
3507836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
3517836SJohn.Forte@Sun.COM
3527836SJohn.Forte@Sun.COM if (!rc)
3537836SJohn.Forte@Sun.COM _nsc_free_io(io);
3547836SJohn.Forte@Sun.COM
3557836SJohn.Forte@Sun.COM return (rc);
3567836SJohn.Forte@Sun.COM }
3577836SJohn.Forte@Sun.COM
3587836SJohn.Forte@Sun.COM
3597836SJohn.Forte@Sun.COM /*
3607836SJohn.Forte@Sun.COM * nsc_path_t *
3617836SJohn.Forte@Sun.COM * nsc_register_path (char *path, int type, nsc_io_t *io)
3627836SJohn.Forte@Sun.COM * Register interest in pathname.
3637836SJohn.Forte@Sun.COM *
3647836SJohn.Forte@Sun.COM * Calling/Exit State:
3657836SJohn.Forte@Sun.COM * Returns a token for use in future calls to
3667836SJohn.Forte@Sun.COM * nsc_unregister_path. The 'path' argument can contain
3677836SJohn.Forte@Sun.COM * wild characters. If registration fails NULL is returned.
3687836SJohn.Forte@Sun.COM * May not be called for io providers that support NSC_ANON.
3697836SJohn.Forte@Sun.COM *
3707836SJohn.Forte@Sun.COM * Description:
3717836SJohn.Forte@Sun.COM * Registers an interest in any pathnames matching 'path'
3727836SJohn.Forte@Sun.COM * which are opened with the specified type.
3737836SJohn.Forte@Sun.COM */
3747836SJohn.Forte@Sun.COM nsc_path_t *
nsc_register_path(char * path,int type,nsc_io_t * io)3757836SJohn.Forte@Sun.COM nsc_register_path(char *path, int type, nsc_io_t *io)
3767836SJohn.Forte@Sun.COM {
3777836SJohn.Forte@Sun.COM nsc_path_t *sp, **spp;
3787836SJohn.Forte@Sun.COM int rc;
3797836SJohn.Forte@Sun.COM
3807836SJohn.Forte@Sun.COM if ((type & NSC_IDS) || !io || (io->provide & NSC_ANON) ||
3817836SJohn.Forte@Sun.COM !(sp = nsc_kmem_zalloc(sizeof (*sp), KM_SLEEP, _nsc_local_mem)))
3827836SJohn.Forte@Sun.COM return (NULL);
3837836SJohn.Forte@Sun.COM
3847836SJohn.Forte@Sun.COM sp->sp_path = nsc_strdup(path);
3857836SJohn.Forte@Sun.COM sp->sp_type = type;
3867836SJohn.Forte@Sun.COM sp->sp_io = io;
3877836SJohn.Forte@Sun.COM
3887836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
3897836SJohn.Forte@Sun.COM
3907836SJohn.Forte@Sun.COM for (spp = &_nsc_path_top; *spp; spp = &(*spp)->sp_next)
3917836SJohn.Forte@Sun.COM if (io->id >= (*spp)->sp_io->id)
3927836SJohn.Forte@Sun.COM break;
3937836SJohn.Forte@Sun.COM
3947836SJohn.Forte@Sun.COM sp->sp_next = (*spp);
3957836SJohn.Forte@Sun.COM (*spp) = sp;
3967836SJohn.Forte@Sun.COM
3977836SJohn.Forte@Sun.COM _nsc_io_lbolt = nsc_lbolt();
3987836SJohn.Forte@Sun.COM
3997836SJohn.Forte@Sun.COM while ((rc = _nsc_reopen_io(path, 0)) != 0)
4007836SJohn.Forte@Sun.COM if (rc != ERESTART)
4017836SJohn.Forte@Sun.COM break;
4027836SJohn.Forte@Sun.COM
4037836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
4047836SJohn.Forte@Sun.COM return (sp);
4057836SJohn.Forte@Sun.COM }
4067836SJohn.Forte@Sun.COM
4077836SJohn.Forte@Sun.COM
4087836SJohn.Forte@Sun.COM /*
4097836SJohn.Forte@Sun.COM * int
4107836SJohn.Forte@Sun.COM * nsc_unregister_path (nsc_path_t *sp, int flag)
4117836SJohn.Forte@Sun.COM * Un-register interest in pathname.
4127836SJohn.Forte@Sun.COM *
4137836SJohn.Forte@Sun.COM * Calling/Exit State:
4147836SJohn.Forte@Sun.COM * Returns 0 on success, otherwise returns an error code.
4157836SJohn.Forte@Sun.COM *
4167836SJohn.Forte@Sun.COM * Description:
4177836SJohn.Forte@Sun.COM * Interest in the specified pathname is un-registered
4187836SJohn.Forte@Sun.COM * if possible. All appropriate file descriptors will be
4197836SJohn.Forte@Sun.COM * closed in preparation for a subsequent re-open.
4207836SJohn.Forte@Sun.COM *
4217836SJohn.Forte@Sun.COM * If NSC_PCATCH is specified and a signal is received,
4227836SJohn.Forte@Sun.COM * the unregister will be terminated and EINTR returned.
4237836SJohn.Forte@Sun.COM */
4247836SJohn.Forte@Sun.COM int
nsc_unregister_path(sp,flag)4257836SJohn.Forte@Sun.COM nsc_unregister_path(sp, flag)
4267836SJohn.Forte@Sun.COM nsc_path_t *sp;
4277836SJohn.Forte@Sun.COM int flag;
4287836SJohn.Forte@Sun.COM {
4297836SJohn.Forte@Sun.COM nsc_path_t *xsp, **spp;
4307836SJohn.Forte@Sun.COM int rc;
4317836SJohn.Forte@Sun.COM
4327836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
4337836SJohn.Forte@Sun.COM
4347836SJohn.Forte@Sun.COM for (xsp = _nsc_path_top; xsp; xsp = xsp->sp_next)
4357836SJohn.Forte@Sun.COM if (xsp == sp)
4367836SJohn.Forte@Sun.COM break;
4377836SJohn.Forte@Sun.COM
4387836SJohn.Forte@Sun.COM if (!xsp || sp->sp_pend) {
4397836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
4407836SJohn.Forte@Sun.COM return (xsp ? EALREADY : 0);
4417836SJohn.Forte@Sun.COM }
4427836SJohn.Forte@Sun.COM
4437836SJohn.Forte@Sun.COM sp->sp_pend = 1;
4447836SJohn.Forte@Sun.COM _nsc_io_lbolt = nsc_lbolt();
4457836SJohn.Forte@Sun.COM
4467836SJohn.Forte@Sun.COM while ((rc = _nsc_reopen_io(sp->sp_path, flag)) != 0)
4477836SJohn.Forte@Sun.COM if (rc != ERESTART) {
4487836SJohn.Forte@Sun.COM sp->sp_pend = 0;
4497836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
4507836SJohn.Forte@Sun.COM return (rc);
4517836SJohn.Forte@Sun.COM }
4527836SJohn.Forte@Sun.COM
4537836SJohn.Forte@Sun.COM for (spp = &_nsc_path_top; *spp; spp = &(*spp)->sp_next)
4547836SJohn.Forte@Sun.COM if (*spp == sp)
4557836SJohn.Forte@Sun.COM break;
4567836SJohn.Forte@Sun.COM
4577836SJohn.Forte@Sun.COM if (*spp)
4587836SJohn.Forte@Sun.COM (*spp) = sp->sp_next;
4597836SJohn.Forte@Sun.COM
4607836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
4617836SJohn.Forte@Sun.COM
4627836SJohn.Forte@Sun.COM nsc_strfree(sp->sp_path);
4637836SJohn.Forte@Sun.COM nsc_kmem_free(sp, sizeof (*sp));
4647836SJohn.Forte@Sun.COM return (0);
4657836SJohn.Forte@Sun.COM }
4667836SJohn.Forte@Sun.COM
4677836SJohn.Forte@Sun.COM
4687836SJohn.Forte@Sun.COM /*
4697836SJohn.Forte@Sun.COM * static int
4707836SJohn.Forte@Sun.COM * _nsc_reopen_io (char *path, int flag)
4717836SJohn.Forte@Sun.COM * Force re-open of all file descriptors.
4727836SJohn.Forte@Sun.COM *
4737836SJohn.Forte@Sun.COM * Calling/Exit State:
4747836SJohn.Forte@Sun.COM * The _nsc_io_lock must be held across calls to
4757836SJohn.Forte@Sun.COM * this function.
4767836SJohn.Forte@Sun.COM *
4777836SJohn.Forte@Sun.COM * Returns 0 if the force succeeds without releasing
4787836SJohn.Forte@Sun.COM * _nsc_io_lock, otherwise returns an error code.
4797836SJohn.Forte@Sun.COM *
4807836SJohn.Forte@Sun.COM * Description:
4817836SJohn.Forte@Sun.COM * A re-open is forced for all file descriptors as
4827836SJohn.Forte@Sun.COM * appropriate. For performance reasons available
4837836SJohn.Forte@Sun.COM * devices are re-opened before those that would block.
4847836SJohn.Forte@Sun.COM */
4857836SJohn.Forte@Sun.COM static int
_nsc_reopen_io(path,flag)4867836SJohn.Forte@Sun.COM _nsc_reopen_io(path, flag)
4877836SJohn.Forte@Sun.COM char *path;
4887836SJohn.Forte@Sun.COM int flag;
4897836SJohn.Forte@Sun.COM {
4907836SJohn.Forte@Sun.COM nsc_dev_t *dp, *dev;
4917836SJohn.Forte@Sun.COM int rc, errno = 0;
4927836SJohn.Forte@Sun.COM int try, run;
4937836SJohn.Forte@Sun.COM
4947836SJohn.Forte@Sun.COM for (run = 1, try = (NSC_TRY | NSC_DEFER); run--; try = 0) {
4957836SJohn.Forte@Sun.COM for (dev = _nsc_dev_top; dev; dev = dev->nsc_next) {
4967836SJohn.Forte@Sun.COM if (path && !nsc_strmatch(dev->nsc_path, path))
4977836SJohn.Forte@Sun.COM continue;
4987836SJohn.Forte@Sun.COM
4997836SJohn.Forte@Sun.COM if (!(rc = _nsc_reopen_dev(dev, flag | try)))
5007836SJohn.Forte@Sun.COM continue;
5017836SJohn.Forte@Sun.COM
5027836SJohn.Forte@Sun.COM for (dp = _nsc_dev_top; dp; dp = dp->nsc_next)
5037836SJohn.Forte@Sun.COM if (dp == dev)
5047836SJohn.Forte@Sun.COM break;
5057836SJohn.Forte@Sun.COM
5067836SJohn.Forte@Sun.COM if (!dp)
5077836SJohn.Forte@Sun.COM return (ERESTART);
5087836SJohn.Forte@Sun.COM
5097836SJohn.Forte@Sun.COM if (try && !(flag & NSC_TRY))
5107836SJohn.Forte@Sun.COM run = 1;
5117836SJohn.Forte@Sun.COM if (!run && errno != ERESTART)
5127836SJohn.Forte@Sun.COM errno = rc;
5137836SJohn.Forte@Sun.COM }
5147836SJohn.Forte@Sun.COM }
5157836SJohn.Forte@Sun.COM
5167836SJohn.Forte@Sun.COM return (errno);
5177836SJohn.Forte@Sun.COM }
5187836SJohn.Forte@Sun.COM
5197836SJohn.Forte@Sun.COM
5207836SJohn.Forte@Sun.COM /*
5217836SJohn.Forte@Sun.COM * static int
5227836SJohn.Forte@Sun.COM * _nsc_reopen_dev (nsc_dev_t *dev, int flag)
5237836SJohn.Forte@Sun.COM * Force re-open of entire device.
5247836SJohn.Forte@Sun.COM *
5257836SJohn.Forte@Sun.COM * Calling/Exit State:
5267836SJohn.Forte@Sun.COM * The _nsc_io_lock must be held across calls to
5277836SJohn.Forte@Sun.COM * this function.
5287836SJohn.Forte@Sun.COM *
5297836SJohn.Forte@Sun.COM * Returns 0 if the force succeeds without releasing
5307836SJohn.Forte@Sun.COM * _nsc_io_lock, otherwise returns an error code.
5317836SJohn.Forte@Sun.COM *
5327836SJohn.Forte@Sun.COM * Description:
5337836SJohn.Forte@Sun.COM * A re-open is forced for all file descriptors for the
5347836SJohn.Forte@Sun.COM * device as appropriate.
5357836SJohn.Forte@Sun.COM */
5367836SJohn.Forte@Sun.COM static int
_nsc_reopen_dev(dev,flag)5377836SJohn.Forte@Sun.COM _nsc_reopen_dev(dev, flag)
5387836SJohn.Forte@Sun.COM nsc_dev_t *dev;
5397836SJohn.Forte@Sun.COM int flag;
5407836SJohn.Forte@Sun.COM {
5417836SJohn.Forte@Sun.COM int rc, errno = 0;
5427836SJohn.Forte@Sun.COM nsc_iodev_t *iodev;
5437836SJohn.Forte@Sun.COM int try, run;
5447836SJohn.Forte@Sun.COM nsc_fd_t *fd;
5457836SJohn.Forte@Sun.COM
5467836SJohn.Forte@Sun.COM mutex_enter(&dev->nsc_lock);
5477836SJohn.Forte@Sun.COM
5487836SJohn.Forte@Sun.COM for (run = 1, try = (NSC_TRY | NSC_DEFER); run--; try = 0)
5497836SJohn.Forte@Sun.COM for (iodev = dev->nsc_list; iodev; iodev = iodev->si_next) {
5507836SJohn.Forte@Sun.COM for (fd = iodev->si_open; fd; fd = fd->sf_next) {
5517836SJohn.Forte@Sun.COM if (!(rc = _nsc_reopen_fd(fd, flag | try)))
5527836SJohn.Forte@Sun.COM continue;
5537836SJohn.Forte@Sun.COM
5547836SJohn.Forte@Sun.COM if (rc == -ERESTART)
5557836SJohn.Forte@Sun.COM return (ERESTART);
5567836SJohn.Forte@Sun.COM
5577836SJohn.Forte@Sun.COM if (!_nsc_relock_dev(dev, fd, iodev))
5587836SJohn.Forte@Sun.COM return (ERESTART);
5597836SJohn.Forte@Sun.COM
5607836SJohn.Forte@Sun.COM if (try && !(flag & NSC_TRY))
5617836SJohn.Forte@Sun.COM run = 1;
5627836SJohn.Forte@Sun.COM if (!run && errno != ERESTART)
5637836SJohn.Forte@Sun.COM errno = rc;
5647836SJohn.Forte@Sun.COM }
5657836SJohn.Forte@Sun.COM }
5667836SJohn.Forte@Sun.COM
5677836SJohn.Forte@Sun.COM for (run = 1, try = (NSC_TRY | NSC_DEFER); run--; try = 0)
5687836SJohn.Forte@Sun.COM for (fd = dev->nsc_close; fd; fd = fd->sf_next) {
5697836SJohn.Forte@Sun.COM if (!(rc = _nsc_reopen_fd(fd, flag | try)))
5707836SJohn.Forte@Sun.COM continue;
5717836SJohn.Forte@Sun.COM
5727836SJohn.Forte@Sun.COM if (rc == -ERESTART)
5737836SJohn.Forte@Sun.COM return (ERESTART);
5747836SJohn.Forte@Sun.COM
5757836SJohn.Forte@Sun.COM if (!_nsc_relock_dev(dev, fd, NULL))
5767836SJohn.Forte@Sun.COM return (ERESTART);
5777836SJohn.Forte@Sun.COM
5787836SJohn.Forte@Sun.COM if (try && !(flag & NSC_TRY))
5797836SJohn.Forte@Sun.COM run = 1;
5807836SJohn.Forte@Sun.COM if (!run && errno != ERESTART)
5817836SJohn.Forte@Sun.COM errno = rc;
5827836SJohn.Forte@Sun.COM }
5837836SJohn.Forte@Sun.COM
5847836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
5857836SJohn.Forte@Sun.COM return (errno);
5867836SJohn.Forte@Sun.COM }
5877836SJohn.Forte@Sun.COM
5887836SJohn.Forte@Sun.COM
5897836SJohn.Forte@Sun.COM /*
5907836SJohn.Forte@Sun.COM * static int
5917836SJohn.Forte@Sun.COM * _nsc_relock_dev (nsc_dev_t *dev, nsc_fd_t *fd, nsc_iodev_t *iodev)
5927836SJohn.Forte@Sun.COM * Relock device structure if possible.
5937836SJohn.Forte@Sun.COM *
5947836SJohn.Forte@Sun.COM * Calling/Exit State:
5957836SJohn.Forte@Sun.COM * The _nsc_io_lock must be held across calls to
5967836SJohn.Forte@Sun.COM * this function.
5977836SJohn.Forte@Sun.COM *
5987836SJohn.Forte@Sun.COM * Checks whether the file descriptor is still part
5997836SJohn.Forte@Sun.COM * of the specified device and I/O device. If so the
6007836SJohn.Forte@Sun.COM * device lock is taken. Otherwise FALSE is returned.
6017836SJohn.Forte@Sun.COM */
6027836SJohn.Forte@Sun.COM static int
_nsc_relock_dev(nsc_dev_t * dev,nsc_fd_t * fd,nsc_iodev_t * iodev)6037836SJohn.Forte@Sun.COM _nsc_relock_dev(nsc_dev_t *dev, nsc_fd_t *fd, nsc_iodev_t *iodev)
6047836SJohn.Forte@Sun.COM {
6057836SJohn.Forte@Sun.COM nsc_fd_t *fp = NULL;
6067836SJohn.Forte@Sun.COM nsc_iodev_t *iop;
6077836SJohn.Forte@Sun.COM nsc_dev_t *dp;
6087836SJohn.Forte@Sun.COM
6097836SJohn.Forte@Sun.COM for (dp = _nsc_dev_top; dp; dp = dp->nsc_next)
6107836SJohn.Forte@Sun.COM if (dp == dev)
6117836SJohn.Forte@Sun.COM break;
6127836SJohn.Forte@Sun.COM
6137836SJohn.Forte@Sun.COM if (!dp)
6147836SJohn.Forte@Sun.COM return (0);
6157836SJohn.Forte@Sun.COM
6167836SJohn.Forte@Sun.COM mutex_enter(&dev->nsc_lock);
6177836SJohn.Forte@Sun.COM
6187836SJohn.Forte@Sun.COM if (iodev)
6197836SJohn.Forte@Sun.COM for (iop = dev->nsc_list; iop; iop = iop->si_next)
6207836SJohn.Forte@Sun.COM if (iop == iodev)
6217836SJohn.Forte@Sun.COM break;
6227836SJohn.Forte@Sun.COM
6237836SJohn.Forte@Sun.COM if (!iodev || iop) {
6247836SJohn.Forte@Sun.COM fp = (iodev) ? iodev->si_open : dev->nsc_close;
6257836SJohn.Forte@Sun.COM
6267836SJohn.Forte@Sun.COM for (; fp; fp = fp->sf_next)
6277836SJohn.Forte@Sun.COM if (fp == fd)
6287836SJohn.Forte@Sun.COM break;
6297836SJohn.Forte@Sun.COM }
6307836SJohn.Forte@Sun.COM
6317836SJohn.Forte@Sun.COM if (!fp) {
6327836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
6337836SJohn.Forte@Sun.COM return (0);
6347836SJohn.Forte@Sun.COM }
6357836SJohn.Forte@Sun.COM
6367836SJohn.Forte@Sun.COM return (1);
6377836SJohn.Forte@Sun.COM }
6387836SJohn.Forte@Sun.COM
6397836SJohn.Forte@Sun.COM
6407836SJohn.Forte@Sun.COM /*
6417836SJohn.Forte@Sun.COM * static int
6427836SJohn.Forte@Sun.COM * _nsc_reopen_fd (nsc_fd_t *dev, int flag)
6437836SJohn.Forte@Sun.COM * Force re-open of file descriptor.
6447836SJohn.Forte@Sun.COM *
6457836SJohn.Forte@Sun.COM * Calling/Exit State:
6467836SJohn.Forte@Sun.COM * Both _nsc_io_lock and the device lock must be held
6477836SJohn.Forte@Sun.COM * across calls to this function.
6487836SJohn.Forte@Sun.COM *
6497836SJohn.Forte@Sun.COM * Returns 0 if the force succeeds without releasing
6507836SJohn.Forte@Sun.COM * any locks, otherwise returns an error code. If an
6517836SJohn.Forte@Sun.COM * error code is returned the device lock is released.
6527836SJohn.Forte@Sun.COM *
6537836SJohn.Forte@Sun.COM * Description:
6547836SJohn.Forte@Sun.COM * If appropriate the file descriptor is closed in order
6557836SJohn.Forte@Sun.COM * to force a subsequent open using the currently available
6567836SJohn.Forte@Sun.COM * resources.
6577836SJohn.Forte@Sun.COM */
6587836SJohn.Forte@Sun.COM static int
_nsc_reopen_fd(fd,flag)6597836SJohn.Forte@Sun.COM _nsc_reopen_fd(fd, flag)
6607836SJohn.Forte@Sun.COM nsc_fd_t *fd;
6617836SJohn.Forte@Sun.COM int flag;
6627836SJohn.Forte@Sun.COM {
6637836SJohn.Forte@Sun.COM nsc_dev_t *dev = fd->sf_dev;
6647836SJohn.Forte@Sun.COM nsc_iodev_t *iodev = fd->sf_iodev;
6657836SJohn.Forte@Sun.COM int changed = 0;
6667836SJohn.Forte@Sun.COM int rc;
6677836SJohn.Forte@Sun.COM
6687836SJohn.Forte@Sun.COM if (!fd->sf_pend && !iodev)
6697836SJohn.Forte@Sun.COM return (0);
6707836SJohn.Forte@Sun.COM
6717836SJohn.Forte@Sun.COM if (fd->sf_pend == _NSC_OPEN)
6727836SJohn.Forte@Sun.COM if (fd->sf_lbolt - _nsc_io_lbolt > 0)
6737836SJohn.Forte@Sun.COM return (0);
6747836SJohn.Forte@Sun.COM
6757836SJohn.Forte@Sun.COM if (iodev &&
6767836SJohn.Forte@Sun.COM (iodev->si_io ==
6777836SJohn.Forte@Sun.COM _nsc_find_io(dev->nsc_path, fd->sf_type, &changed)) &&
6787836SJohn.Forte@Sun.COM !changed)
6797836SJohn.Forte@Sun.COM return (0);
6807836SJohn.Forte@Sun.COM
6817836SJohn.Forte@Sun.COM if (iodev)
6827836SJohn.Forte@Sun.COM fd->sf_reopen = 1;
6837836SJohn.Forte@Sun.COM
6847836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
6857836SJohn.Forte@Sun.COM
6867836SJohn.Forte@Sun.COM dev->nsc_reopen = 1;
6877836SJohn.Forte@Sun.COM
6887836SJohn.Forte@Sun.COM rc = _nsc_close_fd(fd, flag);
6897836SJohn.Forte@Sun.COM
6907836SJohn.Forte@Sun.COM dev->nsc_reopen = 0;
6917836SJohn.Forte@Sun.COM
6927836SJohn.Forte@Sun.COM if (rc == EAGAIN && (flag & NSC_DEFER) && fd->sf_reopen)
6937836SJohn.Forte@Sun.COM dev->nsc_drop = 1;
6947836SJohn.Forte@Sun.COM
6957836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
6967836SJohn.Forte@Sun.COM
6977836SJohn.Forte@Sun.COM if (rc == -ERESTART)
6987836SJohn.Forte@Sun.COM delay(2); /* allow other threads cpu time */
6997836SJohn.Forte@Sun.COM
7007836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
7017836SJohn.Forte@Sun.COM return (rc ? rc : ERESTART);
7027836SJohn.Forte@Sun.COM }
7037836SJohn.Forte@Sun.COM
7047836SJohn.Forte@Sun.COM
7057836SJohn.Forte@Sun.COM /*
7067836SJohn.Forte@Sun.COM * nsc_fd_t *
7077836SJohn.Forte@Sun.COM * nsc_open (char *path, int type, nsc_def_t *def, blind_t arg, int *sts)
7087836SJohn.Forte@Sun.COM * Open file descriptor for pathname.
7097836SJohn.Forte@Sun.COM *
7107836SJohn.Forte@Sun.COM * Calling/Exit State:
7117836SJohn.Forte@Sun.COM * Returns file descriptor if open succeeds, otherwise
7127836SJohn.Forte@Sun.COM * returns 0 and puts error code in the location pointed
7137836SJohn.Forte@Sun.COM * to by sts.
7147836SJohn.Forte@Sun.COM *
7157836SJohn.Forte@Sun.COM * Description:
7167836SJohn.Forte@Sun.COM * Open the specified pathname using an appropriate access
7177836SJohn.Forte@Sun.COM * method.
7187836SJohn.Forte@Sun.COM */
7197836SJohn.Forte@Sun.COM nsc_fd_t *
nsc_open(path,type,def,arg,sts)7207836SJohn.Forte@Sun.COM nsc_open(path, type, def, arg, sts)
7217836SJohn.Forte@Sun.COM char *path;
7227836SJohn.Forte@Sun.COM int type;
7237836SJohn.Forte@Sun.COM nsc_def_t *def;
7247836SJohn.Forte@Sun.COM blind_t arg;
7257836SJohn.Forte@Sun.COM int *sts;
7267836SJohn.Forte@Sun.COM {
7277836SJohn.Forte@Sun.COM int flag, rc;
7287836SJohn.Forte@Sun.COM nsc_fd_t *fd;
7297836SJohn.Forte@Sun.COM
7307836SJohn.Forte@Sun.COM flag = (type & ~NSC_TYPES);
7317836SJohn.Forte@Sun.COM type &= NSC_TYPES;
7327836SJohn.Forte@Sun.COM
7337836SJohn.Forte@Sun.COM if ((flag & NSC_READ) == 0)
7347836SJohn.Forte@Sun.COM flag |= NSC_RDWR;
7357836SJohn.Forte@Sun.COM
7367836SJohn.Forte@Sun.COM if ((rc = _nsc_alloc_fd(path, type, flag, &fd)) != 0) {
7377836SJohn.Forte@Sun.COM if (sts)
7387836SJohn.Forte@Sun.COM *sts = rc;
7397836SJohn.Forte@Sun.COM return (NULL);
7407836SJohn.Forte@Sun.COM }
7417836SJohn.Forte@Sun.COM
7427836SJohn.Forte@Sun.COM fd->sf_arg = arg;
7437836SJohn.Forte@Sun.COM fd->sf_aio = _nsc_null_io;
7447836SJohn.Forte@Sun.COM
7457836SJohn.Forte@Sun.COM nsc_decode_param(def, _nsc_fd_def, (long *)fd);
7467836SJohn.Forte@Sun.COM
7477836SJohn.Forte@Sun.COM mutex_enter(&fd->sf_dev->nsc_lock);
7487836SJohn.Forte@Sun.COM
7497836SJohn.Forte@Sun.COM while ((rc = _nsc_open_fd(fd, flag)) != 0)
7507836SJohn.Forte@Sun.COM if (rc != ERESTART)
7517836SJohn.Forte@Sun.COM break;
7527836SJohn.Forte@Sun.COM
7537836SJohn.Forte@Sun.COM mutex_exit(&fd->sf_dev->nsc_lock);
7547836SJohn.Forte@Sun.COM
7557836SJohn.Forte@Sun.COM if (rc) {
7567836SJohn.Forte@Sun.COM _nsc_free_fd(fd);
7577836SJohn.Forte@Sun.COM if (sts)
7587836SJohn.Forte@Sun.COM *sts = rc;
7597836SJohn.Forte@Sun.COM return (NULL);
7607836SJohn.Forte@Sun.COM }
7617836SJohn.Forte@Sun.COM
7627836SJohn.Forte@Sun.COM return (fd);
7637836SJohn.Forte@Sun.COM }
7647836SJohn.Forte@Sun.COM
7657836SJohn.Forte@Sun.COM
7667836SJohn.Forte@Sun.COM /*
7677836SJohn.Forte@Sun.COM * int
7687836SJohn.Forte@Sun.COM * _nsc_open_fd (nsc_fd_t *fd, int flag)
7697836SJohn.Forte@Sun.COM * Open file descriptor.
7707836SJohn.Forte@Sun.COM *
7717836SJohn.Forte@Sun.COM * Calling/Exit State:
7727836SJohn.Forte@Sun.COM * The device lock must be held across calls to
7737836SJohn.Forte@Sun.COM * this function.
7747836SJohn.Forte@Sun.COM *
7757836SJohn.Forte@Sun.COM * Returns 0 if the open succeeds, otherwise
7767836SJohn.Forte@Sun.COM * returns an error code.
7777836SJohn.Forte@Sun.COM *
7787836SJohn.Forte@Sun.COM * Description:
7797836SJohn.Forte@Sun.COM * Open the specified file descriptor.
7807836SJohn.Forte@Sun.COM */
7817836SJohn.Forte@Sun.COM int
_nsc_open_fd(fd,flag)7827836SJohn.Forte@Sun.COM _nsc_open_fd(fd, flag)
7837836SJohn.Forte@Sun.COM nsc_fd_t *fd;
7847836SJohn.Forte@Sun.COM int flag;
7857836SJohn.Forte@Sun.COM {
7867836SJohn.Forte@Sun.COM nsc_dev_t *dev = fd->sf_dev;
7877836SJohn.Forte@Sun.COM int rc;
7887836SJohn.Forte@Sun.COM
7897836SJohn.Forte@Sun.COM if (fd->sf_pend)
7907836SJohn.Forte@Sun.COM return (_nsc_wait_dev(dev, flag));
7917836SJohn.Forte@Sun.COM
7927836SJohn.Forte@Sun.COM if (fd->sf_iodev)
7937836SJohn.Forte@Sun.COM return (0);
7947836SJohn.Forte@Sun.COM if (flag & NSC_NOBLOCK)
7957836SJohn.Forte@Sun.COM return (EAGAIN);
7967836SJohn.Forte@Sun.COM
7977836SJohn.Forte@Sun.COM fd->sf_pend = _NSC_OPEN;
7987836SJohn.Forte@Sun.COM fd->sf_lbolt = nsc_lbolt();
7997836SJohn.Forte@Sun.COM
8007836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
8017836SJohn.Forte@Sun.COM
8027836SJohn.Forte@Sun.COM rc = _nsc_open_fn(fd, flag);
8037836SJohn.Forte@Sun.COM
8047836SJohn.Forte@Sun.COM mutex_enter(&dev->nsc_lock);
8057836SJohn.Forte@Sun.COM fd->sf_pend = 0;
8067836SJohn.Forte@Sun.COM
8077836SJohn.Forte@Sun.COM if (!rc)
8087836SJohn.Forte@Sun.COM fd->sf_iodev->si_pend = 0;
8097836SJohn.Forte@Sun.COM
8107836SJohn.Forte@Sun.COM if (dev->nsc_wait || dev->nsc_refcnt <= 0)
8117836SJohn.Forte@Sun.COM cv_broadcast(&dev->nsc_cv);
8127836SJohn.Forte@Sun.COM
8137836SJohn.Forte@Sun.COM return (rc ? rc : ERESTART);
8147836SJohn.Forte@Sun.COM }
8157836SJohn.Forte@Sun.COM
8167836SJohn.Forte@Sun.COM
8177836SJohn.Forte@Sun.COM /*
8187836SJohn.Forte@Sun.COM * static int
8197836SJohn.Forte@Sun.COM * _nsc_open_fn (nsc_fd_t *fd, int flag)
8207836SJohn.Forte@Sun.COM * Allocate I/O device and open file descriptor.
8217836SJohn.Forte@Sun.COM *
8227836SJohn.Forte@Sun.COM * Calling/Exit State:
8237836SJohn.Forte@Sun.COM * No locks may be held across this function.
8247836SJohn.Forte@Sun.COM *
8257836SJohn.Forte@Sun.COM * If the open succeeds an I/O device will be
8267836SJohn.Forte@Sun.COM * attached to the file descriptor, marked as
8277836SJohn.Forte@Sun.COM * pending and 0 returned. Otherwise, returns
8287836SJohn.Forte@Sun.COM * an error code.
8297836SJohn.Forte@Sun.COM *
8307836SJohn.Forte@Sun.COM * Description:
8317836SJohn.Forte@Sun.COM * Allocate an I/O device and open the specified
8327836SJohn.Forte@Sun.COM * file descriptor.
8337836SJohn.Forte@Sun.COM */
8347836SJohn.Forte@Sun.COM static int
_nsc_open_fn(fd,flag)8357836SJohn.Forte@Sun.COM _nsc_open_fn(fd, flag)
8367836SJohn.Forte@Sun.COM nsc_fd_t *fd;
8377836SJohn.Forte@Sun.COM int flag;
8387836SJohn.Forte@Sun.COM {
8397836SJohn.Forte@Sun.COM nsc_dev_t *dev = fd->sf_dev;
8407836SJohn.Forte@Sun.COM nsc_iodev_t *iodev;
8417836SJohn.Forte@Sun.COM int rc;
8427836SJohn.Forte@Sun.COM
8437836SJohn.Forte@Sun.COM if ((rc = _nsc_alloc_iodev(dev, fd->sf_type, &iodev)) != 0)
8447836SJohn.Forte@Sun.COM return (rc);
8457836SJohn.Forte@Sun.COM
8467836SJohn.Forte@Sun.COM mutex_enter(&dev->nsc_lock);
8477836SJohn.Forte@Sun.COM
8487836SJohn.Forte@Sun.COM if (iodev->si_pend) {
8497836SJohn.Forte@Sun.COM rc = _nsc_wait_dev(dev, flag);
8507836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
8517836SJohn.Forte@Sun.COM _nsc_free_iodev(iodev);
8527836SJohn.Forte@Sun.COM return (rc);
8537836SJohn.Forte@Sun.COM }
8547836SJohn.Forte@Sun.COM
8557836SJohn.Forte@Sun.COM iodev->si_pend = _NSC_OPEN;
8567836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
8577836SJohn.Forte@Sun.COM
8587836SJohn.Forte@Sun.COM rc = (*iodev->si_io->open)(dev->nsc_path,
8597836SJohn.Forte@Sun.COM (fd->sf_flag & ~NSC_RDWR), &fd->sf_cd, iodev);
8607836SJohn.Forte@Sun.COM
8617836SJohn.Forte@Sun.COM if (rc) {
8627836SJohn.Forte@Sun.COM iodev->si_pend = 0;
8637836SJohn.Forte@Sun.COM _nsc_free_iodev(iodev);
8647836SJohn.Forte@Sun.COM return (rc);
8657836SJohn.Forte@Sun.COM }
8667836SJohn.Forte@Sun.COM
8677836SJohn.Forte@Sun.COM /* save away the DevMaj and DevMin values */
8687836SJohn.Forte@Sun.COM if (iodev->si_io->id == NSC_RAW_ID) {
8697836SJohn.Forte@Sun.COM rc = _nsc_setval(dev, NULL, NSC_DEVMAJ,
8707836SJohn.Forte@Sun.COM (int)getmajor((dev_t)fd->sf_cd), FALSE);
8717836SJohn.Forte@Sun.COM #ifdef DEBUG
8727836SJohn.Forte@Sun.COM if (rc != 1) {
873*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!nsctl: could not set DevMaj (%s:%x)",
8747836SJohn.Forte@Sun.COM dev->nsc_path, (int)getmajor((dev_t)fd->sf_cd));
8757836SJohn.Forte@Sun.COM }
8767836SJohn.Forte@Sun.COM #endif
8777836SJohn.Forte@Sun.COM
8787836SJohn.Forte@Sun.COM rc = _nsc_setval(dev, NULL, NSC_DEVMIN,
8797836SJohn.Forte@Sun.COM (int)getminor((dev_t)fd->sf_cd), FALSE);
8807836SJohn.Forte@Sun.COM #ifdef DEBUG
8817836SJohn.Forte@Sun.COM if (rc != 1) {
882*9093SRamana.Srikanth@Sun.COM cmn_err(CE_NOTE, "!nsctl: could not set DevMin (%s:%x)",
8837836SJohn.Forte@Sun.COM dev->nsc_path, (int)getminor((dev_t)fd->sf_cd));
8847836SJohn.Forte@Sun.COM }
8857836SJohn.Forte@Sun.COM #endif
8867836SJohn.Forte@Sun.COM }
8877836SJohn.Forte@Sun.COM
8887836SJohn.Forte@Sun.COM fd->sf_iodev = iodev;
8897836SJohn.Forte@Sun.COM _nsc_relink_fd(fd, &dev->nsc_close, &iodev->si_open, iodev);
8907836SJohn.Forte@Sun.COM
8917836SJohn.Forte@Sun.COM return (0);
8927836SJohn.Forte@Sun.COM }
8937836SJohn.Forte@Sun.COM
8947836SJohn.Forte@Sun.COM
8957836SJohn.Forte@Sun.COM /*
8967836SJohn.Forte@Sun.COM * int
8977836SJohn.Forte@Sun.COM * nsc_close (nsc_fd_t *fd)
8987836SJohn.Forte@Sun.COM * Close file descriptor for pathname.
8997836SJohn.Forte@Sun.COM *
9007836SJohn.Forte@Sun.COM * Calling/Exit State:
9017836SJohn.Forte@Sun.COM * Returns 0 if close succeeds, otherwise returns error
9027836SJohn.Forte@Sun.COM * code.
9037836SJohn.Forte@Sun.COM *
9047836SJohn.Forte@Sun.COM * Description:
9057836SJohn.Forte@Sun.COM * Close the specified file descriptor. It is assumed
9067836SJohn.Forte@Sun.COM * that all other users of this file descriptor have
9077836SJohn.Forte@Sun.COM * finished. Any reserve will be discarded before the
9087836SJohn.Forte@Sun.COM * close is performed.
9097836SJohn.Forte@Sun.COM */
9107836SJohn.Forte@Sun.COM int
nsc_close(fd)9117836SJohn.Forte@Sun.COM nsc_close(fd)
9127836SJohn.Forte@Sun.COM nsc_fd_t *fd;
9137836SJohn.Forte@Sun.COM {
9147836SJohn.Forte@Sun.COM int rc;
9157836SJohn.Forte@Sun.COM
9167836SJohn.Forte@Sun.COM if (!fd)
9177836SJohn.Forte@Sun.COM return (0);
9187836SJohn.Forte@Sun.COM
9197836SJohn.Forte@Sun.COM while (fd->sf_reserve)
9207836SJohn.Forte@Sun.COM nsc_release(fd);
9217836SJohn.Forte@Sun.COM
9227836SJohn.Forte@Sun.COM mutex_enter(&fd->sf_dev->nsc_lock);
9237836SJohn.Forte@Sun.COM
9247836SJohn.Forte@Sun.COM fd->sf_owner = NULL;
9257836SJohn.Forte@Sun.COM
9267836SJohn.Forte@Sun.COM while ((rc = _nsc_close_fd(fd, 0)) != 0)
9277836SJohn.Forte@Sun.COM if (rc != ERESTART)
9287836SJohn.Forte@Sun.COM break;
9297836SJohn.Forte@Sun.COM
9307836SJohn.Forte@Sun.COM nsc_decode_param(_nsc_fd_def, _nsc_fd_def, (long *)fd);
9317836SJohn.Forte@Sun.COM
9327836SJohn.Forte@Sun.COM mutex_exit(&fd->sf_dev->nsc_lock);
9337836SJohn.Forte@Sun.COM
9347836SJohn.Forte@Sun.COM if (!rc)
9357836SJohn.Forte@Sun.COM _nsc_free_fd(fd);
9367836SJohn.Forte@Sun.COM return (rc);
9377836SJohn.Forte@Sun.COM }
9387836SJohn.Forte@Sun.COM
9397836SJohn.Forte@Sun.COM
9407836SJohn.Forte@Sun.COM /*
9417836SJohn.Forte@Sun.COM * int
9427836SJohn.Forte@Sun.COM * _nsc_close_fd (nsc_fd_t *fd, int flag)
9437836SJohn.Forte@Sun.COM * Close file descriptor.
9447836SJohn.Forte@Sun.COM *
9457836SJohn.Forte@Sun.COM * Calling/Exit State:
9467836SJohn.Forte@Sun.COM * The device lock must be held across calls to
9477836SJohn.Forte@Sun.COM * this function.
9487836SJohn.Forte@Sun.COM *
9497836SJohn.Forte@Sun.COM * Returns 0 if the close succeeds, otherwise
9507836SJohn.Forte@Sun.COM * returns an error code.
9517836SJohn.Forte@Sun.COM *
9527836SJohn.Forte@Sun.COM * Description:
9537836SJohn.Forte@Sun.COM * Close the specified file descriptor.
9547836SJohn.Forte@Sun.COM */
9557836SJohn.Forte@Sun.COM int
_nsc_close_fd(fd,flag)9567836SJohn.Forte@Sun.COM _nsc_close_fd(fd, flag)
9577836SJohn.Forte@Sun.COM nsc_fd_t *fd;
9587836SJohn.Forte@Sun.COM int flag;
9597836SJohn.Forte@Sun.COM {
9607836SJohn.Forte@Sun.COM nsc_dev_t *dev = fd->sf_dev;
9617836SJohn.Forte@Sun.COM nsc_iodev_t *iodev;
9627836SJohn.Forte@Sun.COM int rc;
9637836SJohn.Forte@Sun.COM
9647836SJohn.Forte@Sun.COM if (fd->sf_pend) {
9657836SJohn.Forte@Sun.COM if (fd->sf_pend == _NSC_CLOSE && dev->nsc_reopen != 0)
9667836SJohn.Forte@Sun.COM return (-ERESTART);
9677836SJohn.Forte@Sun.COM
9687836SJohn.Forte@Sun.COM return (_nsc_wait_dev(dev, flag));
9697836SJohn.Forte@Sun.COM }
9707836SJohn.Forte@Sun.COM
9717836SJohn.Forte@Sun.COM flag |= NSC_RDWR;
9727836SJohn.Forte@Sun.COM iodev = fd->sf_iodev;
9737836SJohn.Forte@Sun.COM
9747836SJohn.Forte@Sun.COM if (!iodev)
9757836SJohn.Forte@Sun.COM return (0);
9767836SJohn.Forte@Sun.COM
9777836SJohn.Forte@Sun.COM if ((rc = _nsc_detach_fd(fd, flag)) != 0)
9787836SJohn.Forte@Sun.COM return (rc);
9797836SJohn.Forte@Sun.COM
9807836SJohn.Forte@Sun.COM if (iodev->si_pend)
9817836SJohn.Forte@Sun.COM return (_nsc_wait_dev(dev, flag));
9827836SJohn.Forte@Sun.COM
9837836SJohn.Forte@Sun.COM if (iodev->si_open == fd && !fd->sf_next) {
9847836SJohn.Forte@Sun.COM if ((rc = _nsc_detach_iodev(iodev, NULL, flag)) != 0)
9857836SJohn.Forte@Sun.COM return (rc);
9867836SJohn.Forte@Sun.COM
9877836SJohn.Forte@Sun.COM if (dev->nsc_list == iodev && !iodev->si_next)
9887836SJohn.Forte@Sun.COM if ((rc = _nsc_detach_dev(dev, NULL, flag)) != 0)
9897836SJohn.Forte@Sun.COM return (rc);
9907836SJohn.Forte@Sun.COM }
9917836SJohn.Forte@Sun.COM
9927836SJohn.Forte@Sun.COM if (flag & NSC_NOBLOCK)
9937836SJohn.Forte@Sun.COM return (EAGAIN);
9947836SJohn.Forte@Sun.COM
9957836SJohn.Forte@Sun.COM fd->sf_pend = _NSC_CLOSE;
9967836SJohn.Forte@Sun.COM iodev->si_pend = _NSC_CLOSE;
9977836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
9987836SJohn.Forte@Sun.COM
9997836SJohn.Forte@Sun.COM rc = _nsc_close_fn(fd);
10007836SJohn.Forte@Sun.COM
10017836SJohn.Forte@Sun.COM mutex_enter(&dev->nsc_lock);
10027836SJohn.Forte@Sun.COM fd->sf_pend = 0;
10037836SJohn.Forte@Sun.COM
10047836SJohn.Forte@Sun.COM fd->sf_reopen = 0;
10057836SJohn.Forte@Sun.COM if (rc)
10067836SJohn.Forte@Sun.COM iodev->si_pend = 0;
10077836SJohn.Forte@Sun.COM
10087836SJohn.Forte@Sun.COM if (dev->nsc_wait || dev->nsc_refcnt <= 0)
10097836SJohn.Forte@Sun.COM cv_broadcast(&dev->nsc_cv);
10107836SJohn.Forte@Sun.COM
10117836SJohn.Forte@Sun.COM return (rc ? rc : ERESTART);
10127836SJohn.Forte@Sun.COM }
10137836SJohn.Forte@Sun.COM
10147836SJohn.Forte@Sun.COM
10157836SJohn.Forte@Sun.COM /*
10167836SJohn.Forte@Sun.COM * static int
10177836SJohn.Forte@Sun.COM * _nsc_close_fn (nsc_fd_t *fd)
10187836SJohn.Forte@Sun.COM * Close file descriptor and free I/O device.
10197836SJohn.Forte@Sun.COM *
10207836SJohn.Forte@Sun.COM * Calling/Exit State:
10217836SJohn.Forte@Sun.COM * No locks may be held across this function.
10227836SJohn.Forte@Sun.COM *
10237836SJohn.Forte@Sun.COM * Returns 0 if the close succeeds, otherwise
10247836SJohn.Forte@Sun.COM * returns an error code.
10257836SJohn.Forte@Sun.COM *
10267836SJohn.Forte@Sun.COM * If the close succeeds the I/O device will be
10277836SJohn.Forte@Sun.COM * detached from the file descriptor, released
10287836SJohn.Forte@Sun.COM * and 0 returned. Otherwise, returns an error
10297836SJohn.Forte@Sun.COM * code.
10307836SJohn.Forte@Sun.COM *
10317836SJohn.Forte@Sun.COM * Description:
10327836SJohn.Forte@Sun.COM * Close the specified file descriptor and free
10337836SJohn.Forte@Sun.COM * the I/O device.
10347836SJohn.Forte@Sun.COM */
10357836SJohn.Forte@Sun.COM static int
_nsc_close_fn(fd)10367836SJohn.Forte@Sun.COM _nsc_close_fn(fd)
10377836SJohn.Forte@Sun.COM nsc_fd_t *fd;
10387836SJohn.Forte@Sun.COM {
10397836SJohn.Forte@Sun.COM nsc_iodev_t *iodev = fd->sf_iodev;
10407836SJohn.Forte@Sun.COM nsc_dev_t *dev = fd->sf_dev;
10417836SJohn.Forte@Sun.COM int last, rc;
10427836SJohn.Forte@Sun.COM
10437836SJohn.Forte@Sun.COM last = (iodev->si_open == fd && !fd->sf_next);
10447836SJohn.Forte@Sun.COM
10457836SJohn.Forte@Sun.COM if (last || (iodev->si_io->flag & NSC_REFCNT))
10467836SJohn.Forte@Sun.COM if ((rc = (*iodev->si_io->close)(fd->sf_cd)) != 0)
10477836SJohn.Forte@Sun.COM return (rc);
10487836SJohn.Forte@Sun.COM
10497836SJohn.Forte@Sun.COM fd->sf_iodev = NULL;
10507836SJohn.Forte@Sun.COM _nsc_relink_fd(fd, &iodev->si_open, &dev->nsc_close, iodev);
10517836SJohn.Forte@Sun.COM
10527836SJohn.Forte@Sun.COM iodev->si_pend = 0;
10537836SJohn.Forte@Sun.COM _nsc_free_iodev(iodev);
10547836SJohn.Forte@Sun.COM
10557836SJohn.Forte@Sun.COM return (0);
10567836SJohn.Forte@Sun.COM }
10577836SJohn.Forte@Sun.COM
10587836SJohn.Forte@Sun.COM
10597836SJohn.Forte@Sun.COM /*
10607836SJohn.Forte@Sun.COM * void
10617836SJohn.Forte@Sun.COM * nsc_set_owner (nsc_fd_t *fd, nsc_iodev_t *iodev)
10627836SJohn.Forte@Sun.COM * Set owner associated with file descriptor.
10637836SJohn.Forte@Sun.COM *
10647836SJohn.Forte@Sun.COM * Calling/Exit State:
10657836SJohn.Forte@Sun.COM * Sets the owner field in the file descriptor.
10667836SJohn.Forte@Sun.COM */
10677836SJohn.Forte@Sun.COM void
nsc_set_owner(nsc_fd_t * fd,nsc_iodev_t * iodev)10687836SJohn.Forte@Sun.COM nsc_set_owner(nsc_fd_t *fd, nsc_iodev_t *iodev)
10697836SJohn.Forte@Sun.COM {
10707836SJohn.Forte@Sun.COM if (fd) {
10717836SJohn.Forte@Sun.COM mutex_enter(&fd->sf_dev->nsc_lock);
10727836SJohn.Forte@Sun.COM fd->sf_owner = iodev;
10737836SJohn.Forte@Sun.COM mutex_exit(&fd->sf_dev->nsc_lock);
10747836SJohn.Forte@Sun.COM }
10757836SJohn.Forte@Sun.COM }
10767836SJohn.Forte@Sun.COM
10777836SJohn.Forte@Sun.COM
10787836SJohn.Forte@Sun.COM /*
10797836SJohn.Forte@Sun.COM * char *
10807836SJohn.Forte@Sun.COM * nsc_pathname (nsc_fd_t *fd)
10817836SJohn.Forte@Sun.COM * Pathname associated with file descriptor.
10827836SJohn.Forte@Sun.COM *
10837836SJohn.Forte@Sun.COM * Calling/Exit State:
10847836SJohn.Forte@Sun.COM * Returns a pointer to the pathname associated
10857836SJohn.Forte@Sun.COM * with the given file descriptor.
10867836SJohn.Forte@Sun.COM */
10877836SJohn.Forte@Sun.COM char *
nsc_pathname(fd)10887836SJohn.Forte@Sun.COM nsc_pathname(fd)
10897836SJohn.Forte@Sun.COM nsc_fd_t *fd;
10907836SJohn.Forte@Sun.COM {
10917836SJohn.Forte@Sun.COM return ((fd) ? (fd->sf_dev->nsc_path) : 0);
10927836SJohn.Forte@Sun.COM }
10937836SJohn.Forte@Sun.COM
10947836SJohn.Forte@Sun.COM
10957836SJohn.Forte@Sun.COM /*
10967836SJohn.Forte@Sun.COM * int
10977836SJohn.Forte@Sun.COM * nsc_fdpathcmp(nsc_fd_t *fd, uint64_t phash, char *path)
10987836SJohn.Forte@Sun.COM * Compare fd to pathname and hash
10997836SJohn.Forte@Sun.COM *
11007836SJohn.Forte@Sun.COM * Calling/Exit State:
11017836SJohn.Forte@Sun.COM * Returns comparison value like strcmp(3C).
11027836SJohn.Forte@Sun.COM *
11037836SJohn.Forte@Sun.COM * Description:
11047836SJohn.Forte@Sun.COM * Does an optimised comparison of the pathname and associated hash
11057836SJohn.Forte@Sun.COM * value (as returned from nsc_strhash()) against the pathname of
11067836SJohn.Forte@Sun.COM * the filedescriptor, fd.
11077836SJohn.Forte@Sun.COM */
11087836SJohn.Forte@Sun.COM int
nsc_fdpathcmp(nsc_fd_t * fd,uint64_t phash,char * path)11097836SJohn.Forte@Sun.COM nsc_fdpathcmp(nsc_fd_t *fd, uint64_t phash, char *path)
11107836SJohn.Forte@Sun.COM {
11117836SJohn.Forte@Sun.COM int rc = -1;
11127836SJohn.Forte@Sun.COM
11137836SJohn.Forte@Sun.COM if (fd != NULL && fd->sf_dev->nsc_phash == phash)
11147836SJohn.Forte@Sun.COM rc = strcmp(fd->sf_dev->nsc_path, path);
11157836SJohn.Forte@Sun.COM
11167836SJohn.Forte@Sun.COM return (rc);
11177836SJohn.Forte@Sun.COM }
11187836SJohn.Forte@Sun.COM
11197836SJohn.Forte@Sun.COM
11207836SJohn.Forte@Sun.COM static int
_nsc_setval(nsc_dev_t * dev,char * path,char * name,int val,int do_ncall)11217836SJohn.Forte@Sun.COM _nsc_setval(nsc_dev_t *dev, char *path, char *name, int val, int do_ncall)
11227836SJohn.Forte@Sun.COM {
11237836SJohn.Forte@Sun.COM nsc_devval_t *dv;
11247836SJohn.Forte@Sun.COM nsc_rval_t *rval;
11257836SJohn.Forte@Sun.COM ncall_t *ncall;
11267836SJohn.Forte@Sun.COM nsc_val_t *vp;
11277836SJohn.Forte@Sun.COM uint64_t phash;
11287836SJohn.Forte@Sun.COM char *pp;
11297836SJohn.Forte@Sun.COM int rc;
11307836SJohn.Forte@Sun.COM
11317836SJohn.Forte@Sun.COM ASSERT(dev != NULL || path != NULL);
11327836SJohn.Forte@Sun.COM #ifdef DEBUG
11337836SJohn.Forte@Sun.COM if (dev != NULL && path != NULL) {
11347836SJohn.Forte@Sun.COM ASSERT(strcmp(dev->nsc_path, path) == 0);
11357836SJohn.Forte@Sun.COM }
11367836SJohn.Forte@Sun.COM #endif
11377836SJohn.Forte@Sun.COM
11387836SJohn.Forte@Sun.COM pp = (dev != NULL) ? dev->nsc_path : path;
11397836SJohn.Forte@Sun.COM
11407836SJohn.Forte@Sun.COM if (strlen(name) >= NSC_SETVAL_MAX) {
11417836SJohn.Forte@Sun.COM #ifdef DEBUG
1142*9093SRamana.Srikanth@Sun.COM cmn_err(CE_WARN, "!nsc_setval: max name size(%d) exceeded(%d)",
11437836SJohn.Forte@Sun.COM NSC_SETVAL_MAX-1, (int)strlen(name));
11447836SJohn.Forte@Sun.COM #endif
11457836SJohn.Forte@Sun.COM return (0);
11467836SJohn.Forte@Sun.COM }
11477836SJohn.Forte@Sun.COM
11487836SJohn.Forte@Sun.COM phash = nsc_strhash(pp);
11497836SJohn.Forte@Sun.COM
11507836SJohn.Forte@Sun.COM mutex_enter(&_nsc_devval_lock);
11517836SJohn.Forte@Sun.COM
11527836SJohn.Forte@Sun.COM if (dev != NULL)
11537836SJohn.Forte@Sun.COM dv = dev->nsc_values;
11547836SJohn.Forte@Sun.COM else {
11557836SJohn.Forte@Sun.COM for (dv = _nsc_devval_top; dv != NULL; dv = dv->dv_next) {
11567836SJohn.Forte@Sun.COM if (phash == dv->dv_phash &&
11577836SJohn.Forte@Sun.COM strcmp(pp, dv->dv_path) == 0)
11587836SJohn.Forte@Sun.COM /* found dv for device */
11597836SJohn.Forte@Sun.COM break;
11607836SJohn.Forte@Sun.COM }
11617836SJohn.Forte@Sun.COM }
11627836SJohn.Forte@Sun.COM
11637836SJohn.Forte@Sun.COM if (dv == NULL) {
11647836SJohn.Forte@Sun.COM dv = nsc_kmem_zalloc(sizeof (*dv), KM_SLEEP, _nsc_local_mem);
11657836SJohn.Forte@Sun.COM if (dv == NULL) {
11667836SJohn.Forte@Sun.COM mutex_exit(&_nsc_devval_lock);
11677836SJohn.Forte@Sun.COM return (0);
11687836SJohn.Forte@Sun.COM }
11697836SJohn.Forte@Sun.COM
11707836SJohn.Forte@Sun.COM (void) strncpy(dv->dv_path, pp, sizeof (dv->dv_path));
11717836SJohn.Forte@Sun.COM dv->dv_phash = phash;
11727836SJohn.Forte@Sun.COM
11737836SJohn.Forte@Sun.COM dv->dv_next = _nsc_devval_top;
11747836SJohn.Forte@Sun.COM _nsc_devval_top = dv;
11757836SJohn.Forte@Sun.COM if (dev != NULL)
11767836SJohn.Forte@Sun.COM dev->nsc_values = dv;
11777836SJohn.Forte@Sun.COM }
11787836SJohn.Forte@Sun.COM
11797836SJohn.Forte@Sun.COM for (vp = dv->dv_values; vp; vp = vp->sv_next) {
11807836SJohn.Forte@Sun.COM if (strcmp(vp->sv_name, name) == 0) {
11817836SJohn.Forte@Sun.COM vp->sv_value = val;
11827836SJohn.Forte@Sun.COM break;
11837836SJohn.Forte@Sun.COM }
11847836SJohn.Forte@Sun.COM }
11857836SJohn.Forte@Sun.COM
11867836SJohn.Forte@Sun.COM if (vp == NULL) {
11877836SJohn.Forte@Sun.COM vp = nsc_kmem_zalloc(sizeof (*vp), KM_SLEEP, _nsc_local_mem);
11887836SJohn.Forte@Sun.COM if (vp != NULL) {
11897836SJohn.Forte@Sun.COM (void) strncpy(vp->sv_name, name, sizeof (vp->sv_name));
11907836SJohn.Forte@Sun.COM vp->sv_value = val;
11917836SJohn.Forte@Sun.COM vp->sv_next = dv->dv_values;
11927836SJohn.Forte@Sun.COM dv->dv_values = vp;
11937836SJohn.Forte@Sun.COM }
11947836SJohn.Forte@Sun.COM }
11957836SJohn.Forte@Sun.COM
11967836SJohn.Forte@Sun.COM mutex_exit(&_nsc_devval_lock);
11977836SJohn.Forte@Sun.COM
11987836SJohn.Forte@Sun.COM /*
11997836SJohn.Forte@Sun.COM * phoenix: ncall the new value to the other node now.
12007836SJohn.Forte@Sun.COM */
12017836SJohn.Forte@Sun.COM
12027836SJohn.Forte@Sun.COM if (vp && do_ncall) {
12037836SJohn.Forte@Sun.COM /* CONSTCOND */
12047836SJohn.Forte@Sun.COM ASSERT(sizeof (nsc_rval_t) <= NCALL_DATA_SZ);
12057836SJohn.Forte@Sun.COM
12067836SJohn.Forte@Sun.COM rval = nsc_kmem_zalloc(sizeof (*rval), KM_SLEEP,
12077836SJohn.Forte@Sun.COM _nsc_local_mem);
12087836SJohn.Forte@Sun.COM if (rval == NULL) {
12097836SJohn.Forte@Sun.COM goto out;
12107836SJohn.Forte@Sun.COM }
12117836SJohn.Forte@Sun.COM
12127836SJohn.Forte@Sun.COM rc = ncall_alloc(ncall_mirror(ncall_self()), 0, 0, &ncall);
12137836SJohn.Forte@Sun.COM if (rc == 0) {
12147836SJohn.Forte@Sun.COM (void) strncpy(rval->path, pp, sizeof (rval->path));
12157836SJohn.Forte@Sun.COM (void) strncpy(rval->name, name, sizeof (rval->name));
12167836SJohn.Forte@Sun.COM rval->value = val;
12177836SJohn.Forte@Sun.COM
12187836SJohn.Forte@Sun.COM rc = ncall_put_data(ncall, rval, sizeof (*rval));
12197836SJohn.Forte@Sun.COM if (rc == 0) {
12207836SJohn.Forte@Sun.COM /*
12217836SJohn.Forte@Sun.COM * Send synchronously and read a reply
12227836SJohn.Forte@Sun.COM * so that we know that the remote
12237836SJohn.Forte@Sun.COM * setval has completed before this
12247836SJohn.Forte@Sun.COM * function returns and hence whilst
12257836SJohn.Forte@Sun.COM * the device is still reserved on this
12267836SJohn.Forte@Sun.COM * node.
12277836SJohn.Forte@Sun.COM */
12287836SJohn.Forte@Sun.COM if (ncall_send(ncall, 0, NSC_SETVAL) == 0)
12297836SJohn.Forte@Sun.COM (void) ncall_read_reply(ncall, 1, &rc);
12307836SJohn.Forte@Sun.COM }
12317836SJohn.Forte@Sun.COM
12327836SJohn.Forte@Sun.COM ncall_free(ncall);
12337836SJohn.Forte@Sun.COM }
12347836SJohn.Forte@Sun.COM
12357836SJohn.Forte@Sun.COM nsc_kmem_free(rval, sizeof (*rval));
12367836SJohn.Forte@Sun.COM }
12377836SJohn.Forte@Sun.COM
12387836SJohn.Forte@Sun.COM out:
12397836SJohn.Forte@Sun.COM return (vp ? 1 : 0);
12407836SJohn.Forte@Sun.COM }
12417836SJohn.Forte@Sun.COM
12427836SJohn.Forte@Sun.COM
12437836SJohn.Forte@Sun.COM /* ARGSUSED */
12447836SJohn.Forte@Sun.COM
12457836SJohn.Forte@Sun.COM static void
r_nsc_setval(ncall_t * ncall,int * ap)12467836SJohn.Forte@Sun.COM r_nsc_setval(ncall_t *ncall, int *ap)
12477836SJohn.Forte@Sun.COM {
12487836SJohn.Forte@Sun.COM nsc_rval_t *rval;
12497836SJohn.Forte@Sun.COM int rc;
12507836SJohn.Forte@Sun.COM
12517836SJohn.Forte@Sun.COM rval = nsc_kmem_zalloc(sizeof (*rval), KM_SLEEP, _nsc_local_mem);
12527836SJohn.Forte@Sun.COM if (rval == NULL) {
12537836SJohn.Forte@Sun.COM ncall_reply(ncall, ENOMEM);
12547836SJohn.Forte@Sun.COM return;
12557836SJohn.Forte@Sun.COM }
12567836SJohn.Forte@Sun.COM
12577836SJohn.Forte@Sun.COM rc = ncall_get_data(ncall, rval, sizeof (*rval));
12587836SJohn.Forte@Sun.COM if (rc != 0) {
12597836SJohn.Forte@Sun.COM ncall_reply(ncall, EFAULT);
12607836SJohn.Forte@Sun.COM return;
12617836SJohn.Forte@Sun.COM }
12627836SJohn.Forte@Sun.COM
12637836SJohn.Forte@Sun.COM if (_nsc_setval(NULL, rval->path, rval->name, rval->value, FALSE))
12647836SJohn.Forte@Sun.COM rc = 0;
12657836SJohn.Forte@Sun.COM else
12667836SJohn.Forte@Sun.COM rc = ENOMEM;
12677836SJohn.Forte@Sun.COM
12687836SJohn.Forte@Sun.COM ncall_reply(ncall, rc);
12697836SJohn.Forte@Sun.COM nsc_kmem_free(rval, sizeof (*rval));
12707836SJohn.Forte@Sun.COM }
12717836SJohn.Forte@Sun.COM
12727836SJohn.Forte@Sun.COM
12737836SJohn.Forte@Sun.COM /* ARGSUSED */
12747836SJohn.Forte@Sun.COM
12757836SJohn.Forte@Sun.COM static void
r_nsc_setval_all(ncall_t * ncall,int * ap)12767836SJohn.Forte@Sun.COM r_nsc_setval_all(ncall_t *ncall, int *ap)
12777836SJohn.Forte@Sun.COM {
12787836SJohn.Forte@Sun.COM nsc_rval_t *in = NULL, *out = NULL;
12797836SJohn.Forte@Sun.COM nsc_devval_t *dv;
12807836SJohn.Forte@Sun.COM nsc_val_t *vp;
12817836SJohn.Forte@Sun.COM ncall_t *np;
12827836SJohn.Forte@Sun.COM uint64_t phash;
12837836SJohn.Forte@Sun.COM int rc;
12847836SJohn.Forte@Sun.COM
12857836SJohn.Forte@Sun.COM /* CONSTCOND */
12867836SJohn.Forte@Sun.COM ASSERT(sizeof (nsc_rval_t) <= NCALL_DATA_SZ);
12877836SJohn.Forte@Sun.COM
12887836SJohn.Forte@Sun.COM in = nsc_kmem_zalloc(sizeof (*in), KM_SLEEP, _nsc_local_mem);
12897836SJohn.Forte@Sun.COM out = nsc_kmem_zalloc(sizeof (*out), KM_SLEEP, _nsc_local_mem);
12907836SJohn.Forte@Sun.COM if (in == NULL || out == NULL) {
12917836SJohn.Forte@Sun.COM if (in != NULL) {
12927836SJohn.Forte@Sun.COM nsc_kmem_free(in, sizeof (*in));
12937836SJohn.Forte@Sun.COM in = NULL;
12947836SJohn.Forte@Sun.COM }
12957836SJohn.Forte@Sun.COM if (out != NULL) {
12967836SJohn.Forte@Sun.COM nsc_kmem_free(out, sizeof (*out));
12977836SJohn.Forte@Sun.COM out = NULL;
12987836SJohn.Forte@Sun.COM }
12997836SJohn.Forte@Sun.COM ncall_reply(ncall, ENOMEM);
13007836SJohn.Forte@Sun.COM }
13017836SJohn.Forte@Sun.COM
13027836SJohn.Forte@Sun.COM rc = ncall_get_data(ncall, in, sizeof (*in));
13037836SJohn.Forte@Sun.COM if (rc != 0) {
13047836SJohn.Forte@Sun.COM ncall_reply(ncall, EFAULT);
13057836SJohn.Forte@Sun.COM return;
13067836SJohn.Forte@Sun.COM }
13077836SJohn.Forte@Sun.COM
13087836SJohn.Forte@Sun.COM phash = nsc_strhash(in->path);
13097836SJohn.Forte@Sun.COM
13107836SJohn.Forte@Sun.COM (void) strncpy(out->path, in->path, sizeof (out->path));
13117836SJohn.Forte@Sun.COM
13127836SJohn.Forte@Sun.COM rc = ncall_alloc(ncall_mirror(ncall_self()), 0, 0, &np);
13137836SJohn.Forte@Sun.COM if (rc != 0) {
13147836SJohn.Forte@Sun.COM ncall_reply(ncall, ENOMEM);
13157836SJohn.Forte@Sun.COM return;
13167836SJohn.Forte@Sun.COM }
13177836SJohn.Forte@Sun.COM
13187836SJohn.Forte@Sun.COM mutex_enter(&_nsc_devval_lock);
13197836SJohn.Forte@Sun.COM
13207836SJohn.Forte@Sun.COM for (dv = _nsc_devval_top; dv; dv = dv->dv_next) {
13217836SJohn.Forte@Sun.COM if (dv->dv_phash == phash &&
13227836SJohn.Forte@Sun.COM strcmp(dv->dv_path, in->path) == 0)
13237836SJohn.Forte@Sun.COM break;
13247836SJohn.Forte@Sun.COM }
13257836SJohn.Forte@Sun.COM
13267836SJohn.Forte@Sun.COM if (dv) {
13277836SJohn.Forte@Sun.COM for (vp = dv->dv_values; vp; vp = vp->sv_next) {
13287836SJohn.Forte@Sun.COM if (strcmp(vp->sv_name, NSC_DEVMIN) == 0 ||
13297836SJohn.Forte@Sun.COM strcmp(vp->sv_name, NSC_DEVMAJ) == 0) {
13307836SJohn.Forte@Sun.COM /* ignore the implicit DevMin/DevMaj values */
13317836SJohn.Forte@Sun.COM continue;
13327836SJohn.Forte@Sun.COM }
13337836SJohn.Forte@Sun.COM
13347836SJohn.Forte@Sun.COM (void) strncpy(out->name, vp->sv_name,
13357836SJohn.Forte@Sun.COM sizeof (out->name));
13367836SJohn.Forte@Sun.COM out->value = vp->sv_value;
13377836SJohn.Forte@Sun.COM
13387836SJohn.Forte@Sun.COM rc = ncall_put_data(np, out, sizeof (*out));
13397836SJohn.Forte@Sun.COM if (rc == 0) {
13407836SJohn.Forte@Sun.COM /*
13417836SJohn.Forte@Sun.COM * Send synchronously and read a reply
13427836SJohn.Forte@Sun.COM * so that we know that the remote
13437836SJohn.Forte@Sun.COM * setval has completed before this
13447836SJohn.Forte@Sun.COM * function returns.
13457836SJohn.Forte@Sun.COM */
13467836SJohn.Forte@Sun.COM if (ncall_send(np, 0, NSC_SETVAL) == 0)
13477836SJohn.Forte@Sun.COM (void) ncall_read_reply(np, 1, &rc);
13487836SJohn.Forte@Sun.COM }
13497836SJohn.Forte@Sun.COM
13507836SJohn.Forte@Sun.COM ncall_reset(np);
13517836SJohn.Forte@Sun.COM }
13527836SJohn.Forte@Sun.COM
13537836SJohn.Forte@Sun.COM ncall_free(np);
13547836SJohn.Forte@Sun.COM rc = 0;
13557836SJohn.Forte@Sun.COM } else {
13567836SJohn.Forte@Sun.COM rc = ENODEV;
13577836SJohn.Forte@Sun.COM }
13587836SJohn.Forte@Sun.COM
13597836SJohn.Forte@Sun.COM mutex_exit(&_nsc_devval_lock);
13607836SJohn.Forte@Sun.COM
13617836SJohn.Forte@Sun.COM ncall_reply(ncall, rc);
13627836SJohn.Forte@Sun.COM
13637836SJohn.Forte@Sun.COM nsc_kmem_free(out, sizeof (*out));
13647836SJohn.Forte@Sun.COM nsc_kmem_free(in, sizeof (*in));
13657836SJohn.Forte@Sun.COM }
13667836SJohn.Forte@Sun.COM
13677836SJohn.Forte@Sun.COM
13687836SJohn.Forte@Sun.COM /*
13697836SJohn.Forte@Sun.COM * int
13707836SJohn.Forte@Sun.COM * nsc_setval (nsc_fd_t *fd, char *name, int val)
13717836SJohn.Forte@Sun.COM * Set value for device.
13727836SJohn.Forte@Sun.COM *
13737836SJohn.Forte@Sun.COM * Calling/Exit State:
13747836SJohn.Forte@Sun.COM * Returns 1 if the value has been set, otherwise 0.
13757836SJohn.Forte@Sun.COM * Must be called with the fd reserved.
13767836SJohn.Forte@Sun.COM *
13777836SJohn.Forte@Sun.COM * Description:
13787836SJohn.Forte@Sun.COM * Sets the specified global variable for the device
13797836SJohn.Forte@Sun.COM * to the value provided.
13807836SJohn.Forte@Sun.COM */
13817836SJohn.Forte@Sun.COM int
nsc_setval(nsc_fd_t * fd,char * name,int val)13827836SJohn.Forte@Sun.COM nsc_setval(nsc_fd_t *fd, char *name, int val)
13837836SJohn.Forte@Sun.COM {
13847836SJohn.Forte@Sun.COM if (!fd)
13857836SJohn.Forte@Sun.COM return (0);
13867836SJohn.Forte@Sun.COM
13877836SJohn.Forte@Sun.COM if (!nsc_held(fd))
13887836SJohn.Forte@Sun.COM return (0);
13897836SJohn.Forte@Sun.COM
13907836SJohn.Forte@Sun.COM return (_nsc_setval(fd->sf_dev, NULL, name, val, TRUE));
13917836SJohn.Forte@Sun.COM }
13927836SJohn.Forte@Sun.COM
13937836SJohn.Forte@Sun.COM
13947836SJohn.Forte@Sun.COM /*
13957836SJohn.Forte@Sun.COM * int
13967836SJohn.Forte@Sun.COM * nsc_getval (nsc_fd_t *fd, char *name, int *vp)
13977836SJohn.Forte@Sun.COM * Get value from device.
13987836SJohn.Forte@Sun.COM *
13997836SJohn.Forte@Sun.COM * Calling/Exit State:
14007836SJohn.Forte@Sun.COM * Returns 1 if the value has been found, otherwise 0.
14017836SJohn.Forte@Sun.COM * Must be called with the fd reserved, except for "DevMaj" / "DevMin".
14027836SJohn.Forte@Sun.COM *
14037836SJohn.Forte@Sun.COM * Description:
14047836SJohn.Forte@Sun.COM * Finds the value of the specified device variable for
14057836SJohn.Forte@Sun.COM * the device and returns it in the location pointed to
14067836SJohn.Forte@Sun.COM * by vp.
14077836SJohn.Forte@Sun.COM */
14087836SJohn.Forte@Sun.COM int
nsc_getval(nsc_fd_t * fd,char * name,int * vp)14097836SJohn.Forte@Sun.COM nsc_getval(nsc_fd_t *fd, char *name, int *vp)
14107836SJohn.Forte@Sun.COM {
14117836SJohn.Forte@Sun.COM nsc_devval_t *dv;
14127836SJohn.Forte@Sun.COM nsc_val_t *val;
14137836SJohn.Forte@Sun.COM
14147836SJohn.Forte@Sun.COM if (!fd)
14157836SJohn.Forte@Sun.COM return (0);
14167836SJohn.Forte@Sun.COM
14177836SJohn.Forte@Sun.COM /*
14187836SJohn.Forte@Sun.COM * Don't check for nsc_held() for the device number values
14197836SJohn.Forte@Sun.COM * since these are magically created and cannot change when
14207836SJohn.Forte@Sun.COM * the fd is not reserved.
14217836SJohn.Forte@Sun.COM */
14227836SJohn.Forte@Sun.COM
14237836SJohn.Forte@Sun.COM if (strcmp(name, NSC_DEVMAJ) != 0 &&
14247836SJohn.Forte@Sun.COM strcmp(name, NSC_DEVMIN) != 0 &&
14257836SJohn.Forte@Sun.COM !nsc_held(fd))
14267836SJohn.Forte@Sun.COM return (0);
14277836SJohn.Forte@Sun.COM
14287836SJohn.Forte@Sun.COM mutex_enter(&_nsc_devval_lock);
14297836SJohn.Forte@Sun.COM
14307836SJohn.Forte@Sun.COM dv = fd->sf_dev->nsc_values;
14317836SJohn.Forte@Sun.COM val = NULL;
14327836SJohn.Forte@Sun.COM
14337836SJohn.Forte@Sun.COM if (dv != NULL) {
14347836SJohn.Forte@Sun.COM for (val = dv->dv_values; val; val = val->sv_next) {
14357836SJohn.Forte@Sun.COM if (strcmp(val->sv_name, name) == 0) {
14367836SJohn.Forte@Sun.COM *vp = val->sv_value;
14377836SJohn.Forte@Sun.COM break;
14387836SJohn.Forte@Sun.COM }
14397836SJohn.Forte@Sun.COM }
14407836SJohn.Forte@Sun.COM }
14417836SJohn.Forte@Sun.COM
14427836SJohn.Forte@Sun.COM mutex_exit(&_nsc_devval_lock);
14437836SJohn.Forte@Sun.COM
14447836SJohn.Forte@Sun.COM return (val ? 1 : 0);
14457836SJohn.Forte@Sun.COM }
14467836SJohn.Forte@Sun.COM
14477836SJohn.Forte@Sun.COM
14487836SJohn.Forte@Sun.COM /*
14497836SJohn.Forte@Sun.COM * char *
14507836SJohn.Forte@Sun.COM * nsc_shared (nsc_fd_t *fd)
14517836SJohn.Forte@Sun.COM * Device is currently shared.
14527836SJohn.Forte@Sun.COM *
14537836SJohn.Forte@Sun.COM * Calling/Exit State:
14547836SJohn.Forte@Sun.COM * The device lock must be held across calls to this
14557836SJohn.Forte@Sun.COM * this function.
14567836SJohn.Forte@Sun.COM *
14577836SJohn.Forte@Sun.COM * Returns an indication of whether the device accessed
14587836SJohn.Forte@Sun.COM * by the file descriptor is currently referenced by more
14597836SJohn.Forte@Sun.COM * than one user.
14607836SJohn.Forte@Sun.COM *
14617836SJohn.Forte@Sun.COM * This is only intended for use in performance critical
14627836SJohn.Forte@Sun.COM * situations.
14637836SJohn.Forte@Sun.COM */
14647836SJohn.Forte@Sun.COM int
nsc_shared(fd)14657836SJohn.Forte@Sun.COM nsc_shared(fd)
14667836SJohn.Forte@Sun.COM nsc_fd_t *fd;
14677836SJohn.Forte@Sun.COM {
14687836SJohn.Forte@Sun.COM nsc_iodev_t *iodev;
14697836SJohn.Forte@Sun.COM int cnt = 0;
14707836SJohn.Forte@Sun.COM
14717836SJohn.Forte@Sun.COM if (!fd)
14727836SJohn.Forte@Sun.COM return (0);
14737836SJohn.Forte@Sun.COM if (!fd->sf_iodev)
14747836SJohn.Forte@Sun.COM return (1);
14757836SJohn.Forte@Sun.COM
14767836SJohn.Forte@Sun.COM for (iodev = fd->sf_dev->nsc_list; iodev; iodev = iodev->si_next)
14777836SJohn.Forte@Sun.COM for (fd = iodev->si_open; fd; fd = fd->sf_next)
14787836SJohn.Forte@Sun.COM if (!fd->sf_owner && cnt++)
14797836SJohn.Forte@Sun.COM return (1);
14807836SJohn.Forte@Sun.COM
14817836SJohn.Forte@Sun.COM return (0);
14827836SJohn.Forte@Sun.COM }
14837836SJohn.Forte@Sun.COM
14847836SJohn.Forte@Sun.COM
14857836SJohn.Forte@Sun.COM /*
14867836SJohn.Forte@Sun.COM * kmutex_t *
14877836SJohn.Forte@Sun.COM * nsc_lock_addr (nsc_fd_t *fd)
14887836SJohn.Forte@Sun.COM * Address of device lock.
14897836SJohn.Forte@Sun.COM *
14907836SJohn.Forte@Sun.COM * Calling/Exit State:
14917836SJohn.Forte@Sun.COM * Returns a pointer to the spin lock associated with the
14927836SJohn.Forte@Sun.COM * device.
14937836SJohn.Forte@Sun.COM *
14947836SJohn.Forte@Sun.COM * Description:
14957836SJohn.Forte@Sun.COM * This is only intended for use in performance critical
14967836SJohn.Forte@Sun.COM * situations in conjunction with nsc_reserve_lk.
14977836SJohn.Forte@Sun.COM */
14987836SJohn.Forte@Sun.COM kmutex_t *
nsc_lock_addr(fd)14997836SJohn.Forte@Sun.COM nsc_lock_addr(fd)
15007836SJohn.Forte@Sun.COM nsc_fd_t *fd;
15017836SJohn.Forte@Sun.COM {
15027836SJohn.Forte@Sun.COM return (&fd->sf_dev->nsc_lock);
15037836SJohn.Forte@Sun.COM }
15047836SJohn.Forte@Sun.COM
15057836SJohn.Forte@Sun.COM
15067836SJohn.Forte@Sun.COM /*
15077836SJohn.Forte@Sun.COM * int
15087836SJohn.Forte@Sun.COM * _nsc_call_io (long f, blind_t a, blind_t b, blind_t c)
15097836SJohn.Forte@Sun.COM * Call information function.
15107836SJohn.Forte@Sun.COM *
15117836SJohn.Forte@Sun.COM * Calling/Exit State:
15127836SJohn.Forte@Sun.COM * Returns result from function or 0 if not available.
15137836SJohn.Forte@Sun.COM * f represents the offset into the I/O structure at which
15147836SJohn.Forte@Sun.COM * the required function can be found and a, b, c are the
15157836SJohn.Forte@Sun.COM * desired arguments.
15167836SJohn.Forte@Sun.COM *
15177836SJohn.Forte@Sun.COM * Description:
15187836SJohn.Forte@Sun.COM * Calls the requested function for the first available
15197836SJohn.Forte@Sun.COM * cache interface.
15207836SJohn.Forte@Sun.COM */
15217836SJohn.Forte@Sun.COM int
_nsc_call_io(long f,blind_t a,blind_t b,blind_t c)15227836SJohn.Forte@Sun.COM _nsc_call_io(long f, blind_t a, blind_t b, blind_t c)
15237836SJohn.Forte@Sun.COM {
15247836SJohn.Forte@Sun.COM nsc_io_t *io;
15257836SJohn.Forte@Sun.COM int (*fn)();
15267836SJohn.Forte@Sun.COM int rc;
15277836SJohn.Forte@Sun.COM
15287836SJohn.Forte@Sun.COM io = _nsc_reserve_io(NULL, NSC_SDBC_ID);
15297836SJohn.Forte@Sun.COM if (!io)
15307836SJohn.Forte@Sun.COM io = _nsc_reserve_io(NULL, NSC_NULL);
15317836SJohn.Forte@Sun.COM
15327836SJohn.Forte@Sun.COM fn = (blindfn_t)(((long *)io)[f]);
15337836SJohn.Forte@Sun.COM rc = (*fn)(a, b, c);
15347836SJohn.Forte@Sun.COM
15357836SJohn.Forte@Sun.COM _nsc_release_io(io);
15367836SJohn.Forte@Sun.COM return (rc);
15377836SJohn.Forte@Sun.COM }
15387836SJohn.Forte@Sun.COM
15397836SJohn.Forte@Sun.COM
15407836SJohn.Forte@Sun.COM /*
15417836SJohn.Forte@Sun.COM * nsc_io_t *
15427836SJohn.Forte@Sun.COM * _nsc_reserve_io (char *, int type)
15437836SJohn.Forte@Sun.COM * Reserve I/O module.
15447836SJohn.Forte@Sun.COM *
15457836SJohn.Forte@Sun.COM * Calling/Exit State:
15467836SJohn.Forte@Sun.COM * Returns address of I/O structure matching specified
15477836SJohn.Forte@Sun.COM * type, or NULL.
15487836SJohn.Forte@Sun.COM *
15497836SJohn.Forte@Sun.COM * Description:
15507836SJohn.Forte@Sun.COM * Searches for an appropriate I/O module and increments
15517836SJohn.Forte@Sun.COM * the reference count to prevent it being unregistered.
15527836SJohn.Forte@Sun.COM */
15537836SJohn.Forte@Sun.COM nsc_io_t *
_nsc_reserve_io(path,type)15547836SJohn.Forte@Sun.COM _nsc_reserve_io(path, type)
15557836SJohn.Forte@Sun.COM char *path;
15567836SJohn.Forte@Sun.COM int type;
15577836SJohn.Forte@Sun.COM {
15587836SJohn.Forte@Sun.COM nsc_io_t *io;
15597836SJohn.Forte@Sun.COM
15607836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
15617836SJohn.Forte@Sun.COM
15627836SJohn.Forte@Sun.COM if ((io = _nsc_find_io(path, type, NULL)) != 0)
15637836SJohn.Forte@Sun.COM io->refcnt++;
15647836SJohn.Forte@Sun.COM
15657836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
15667836SJohn.Forte@Sun.COM return (io);
15677836SJohn.Forte@Sun.COM }
15687836SJohn.Forte@Sun.COM
15697836SJohn.Forte@Sun.COM
15707836SJohn.Forte@Sun.COM /*
15717836SJohn.Forte@Sun.COM * static nsc_io_t *
15727836SJohn.Forte@Sun.COM * _nsc_find_io (char *path, int type, int *changed)
15737836SJohn.Forte@Sun.COM * Find I/O module.
15747836SJohn.Forte@Sun.COM *
15757836SJohn.Forte@Sun.COM * Calling/Exit State:
15767836SJohn.Forte@Sun.COM * The _nsc_io_lock must be held across calls to
15777836SJohn.Forte@Sun.COM * this function.
15787836SJohn.Forte@Sun.COM *
15797836SJohn.Forte@Sun.COM * Returns address of I/O structure matching specified
15807836SJohn.Forte@Sun.COM * type, or NULL.
15817836SJohn.Forte@Sun.COM *
15827836SJohn.Forte@Sun.COM * 'changed' will be set to non-zero if there is a pending
15837836SJohn.Forte@Sun.COM * nsc_path_t that matches the criteria for the requested type.
15847836SJohn.Forte@Sun.COM * This allows nsctl to distinguish between multiple
15857836SJohn.Forte@Sun.COM * nsc_register_path's done by the same I/O provider.
15867836SJohn.Forte@Sun.COM *
15877836SJohn.Forte@Sun.COM * Description:
15887836SJohn.Forte@Sun.COM * Searches for an appropriate I/O module.
15897836SJohn.Forte@Sun.COM *
15907836SJohn.Forte@Sun.COM * 1. If <type> is a single module id find the specified I/O
15917836SJohn.Forte@Sun.COM * module by module id.
15927836SJohn.Forte@Sun.COM *
15937836SJohn.Forte@Sun.COM * 2. Find the highest module that provides any of the I/O types
15947836SJohn.Forte@Sun.COM * included in <type>, taking into account any modules
15957836SJohn.Forte@Sun.COM * registered via the nsc_register_path() interface if <path>
15967836SJohn.Forte@Sun.COM * is non-NULL.
15977836SJohn.Forte@Sun.COM *
15987836SJohn.Forte@Sun.COM * 3. Find an I/O module following the rules in (2), but whose
15997836SJohn.Forte@Sun.COM * module id is less than the id OR'd into <type>.
16007836SJohn.Forte@Sun.COM *
16017836SJohn.Forte@Sun.COM * If no module is found by the above algorithms and NSC_NULL was
16027836SJohn.Forte@Sun.COM * included in <type>, return the _nsc_null_io module. Otherwise
16037836SJohn.Forte@Sun.COM * return NULL.
16047836SJohn.Forte@Sun.COM */
16057836SJohn.Forte@Sun.COM static nsc_io_t *
_nsc_find_io(char * path,int type,int * changed)16067836SJohn.Forte@Sun.COM _nsc_find_io(char *path, int type, int *changed)
16077836SJohn.Forte@Sun.COM {
16087836SJohn.Forte@Sun.COM nsc_path_t *sp = NULL;
16097836SJohn.Forte@Sun.COM nsc_path_t *pp = NULL;
16107836SJohn.Forte@Sun.COM nsc_io_t *io;
16117836SJohn.Forte@Sun.COM
16127836SJohn.Forte@Sun.COM type &= NSC_TYPES;
16137836SJohn.Forte@Sun.COM
16147836SJohn.Forte@Sun.COM if (path) {
16157836SJohn.Forte@Sun.COM for (sp = _nsc_path_top; sp; sp = sp->sp_next) {
16167836SJohn.Forte@Sun.COM if ((type & NSC_ID) &&
16177836SJohn.Forte@Sun.COM sp->sp_io->id >= (type & NSC_IDS))
16187836SJohn.Forte@Sun.COM continue;
16197836SJohn.Forte@Sun.COM
16207836SJohn.Forte@Sun.COM if (sp->sp_pend || (type & sp->sp_type) == 0)
16217836SJohn.Forte@Sun.COM continue;
16227836SJohn.Forte@Sun.COM
16237836SJohn.Forte@Sun.COM if (nsc_strmatch(path, sp->sp_path))
16247836SJohn.Forte@Sun.COM break;
16257836SJohn.Forte@Sun.COM }
16267836SJohn.Forte@Sun.COM
16277836SJohn.Forte@Sun.COM if (sp) {
16287836SJohn.Forte@Sun.COM /* look for matching pending paths */
16297836SJohn.Forte@Sun.COM for (pp = _nsc_path_top; pp; pp = pp->sp_next) {
16307836SJohn.Forte@Sun.COM if (pp->sp_pend &&
16317836SJohn.Forte@Sun.COM (type & pp->sp_type) &&
16327836SJohn.Forte@Sun.COM nsc_strmatch(path, pp->sp_path)) {
16337836SJohn.Forte@Sun.COM break;
16347836SJohn.Forte@Sun.COM }
16357836SJohn.Forte@Sun.COM }
16367836SJohn.Forte@Sun.COM }
16377836SJohn.Forte@Sun.COM }
16387836SJohn.Forte@Sun.COM
16397836SJohn.Forte@Sun.COM for (io = _nsc_io_top; io; io = io->next) {
16407836SJohn.Forte@Sun.COM if (io->pend)
16417836SJohn.Forte@Sun.COM continue;
16427836SJohn.Forte@Sun.COM
16437836SJohn.Forte@Sun.COM if (type & NSC_ID) {
16447836SJohn.Forte@Sun.COM if ((type & ~NSC_IDS) == 0) {
16457836SJohn.Forte@Sun.COM if (io->id == type)
16467836SJohn.Forte@Sun.COM break;
16477836SJohn.Forte@Sun.COM continue;
16487836SJohn.Forte@Sun.COM }
16497836SJohn.Forte@Sun.COM
16507836SJohn.Forte@Sun.COM if (io->id >= (type & NSC_IDS))
16517836SJohn.Forte@Sun.COM continue;
16527836SJohn.Forte@Sun.COM }
16537836SJohn.Forte@Sun.COM
16547836SJohn.Forte@Sun.COM if (io->provide & type)
16557836SJohn.Forte@Sun.COM break;
16567836SJohn.Forte@Sun.COM }
16577836SJohn.Forte@Sun.COM
16587836SJohn.Forte@Sun.COM if (pp && (!io || pp->sp_io->id >= io->id)) {
16597836SJohn.Forte@Sun.COM /*
16607836SJohn.Forte@Sun.COM * Mark this as a path change.
16617836SJohn.Forte@Sun.COM */
16627836SJohn.Forte@Sun.COM if (changed) {
16637836SJohn.Forte@Sun.COM *changed = 1;
16647836SJohn.Forte@Sun.COM }
16657836SJohn.Forte@Sun.COM }
16667836SJohn.Forte@Sun.COM
16677836SJohn.Forte@Sun.COM if (sp && (!io || sp->sp_io->id >= io->id))
16687836SJohn.Forte@Sun.COM io = sp->sp_io;
16697836SJohn.Forte@Sun.COM
16707836SJohn.Forte@Sun.COM if (!io && !(type & NSC_NULL))
16717836SJohn.Forte@Sun.COM return (NULL);
16727836SJohn.Forte@Sun.COM
16737836SJohn.Forte@Sun.COM if (!io)
16747836SJohn.Forte@Sun.COM io = _nsc_null_io;
16757836SJohn.Forte@Sun.COM
16767836SJohn.Forte@Sun.COM return (io);
16777836SJohn.Forte@Sun.COM }
16787836SJohn.Forte@Sun.COM
16797836SJohn.Forte@Sun.COM
16807836SJohn.Forte@Sun.COM /*
16817836SJohn.Forte@Sun.COM * void
16827836SJohn.Forte@Sun.COM * _nsc_release_io (nsc_io_t *)
16837836SJohn.Forte@Sun.COM * Release I/O module.
16847836SJohn.Forte@Sun.COM *
16857836SJohn.Forte@Sun.COM * Description:
16867836SJohn.Forte@Sun.COM * Releases reference to I/O structure and wakes up
16877836SJohn.Forte@Sun.COM * anybody waiting on it.
16887836SJohn.Forte@Sun.COM */
16897836SJohn.Forte@Sun.COM void
_nsc_release_io(io)16907836SJohn.Forte@Sun.COM _nsc_release_io(io)
16917836SJohn.Forte@Sun.COM nsc_io_t *io;
16927836SJohn.Forte@Sun.COM {
16937836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
16947836SJohn.Forte@Sun.COM
16957836SJohn.Forte@Sun.COM io->refcnt--;
16967836SJohn.Forte@Sun.COM cv_broadcast(&io->cv);
16977836SJohn.Forte@Sun.COM
16987836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
16997836SJohn.Forte@Sun.COM }
17007836SJohn.Forte@Sun.COM
17017836SJohn.Forte@Sun.COM
17027836SJohn.Forte@Sun.COM /*
17037836SJohn.Forte@Sun.COM * static int
17047836SJohn.Forte@Sun.COM * _nsc_alloc_fd (char *path, int type, int flag, nsc_fd_t **fdp)
17057836SJohn.Forte@Sun.COM * Allocate file descriptor structure.
17067836SJohn.Forte@Sun.COM *
17077836SJohn.Forte@Sun.COM * Calling/Exit State:
17087836SJohn.Forte@Sun.COM * Stores address of file descriptor through fdp and
17097836SJohn.Forte@Sun.COM * returns 0 on success, otherwise returns error code.
17107836SJohn.Forte@Sun.COM *
17117836SJohn.Forte@Sun.COM * Description:
17127836SJohn.Forte@Sun.COM * A new file descriptor is allocated and linked in to
17137836SJohn.Forte@Sun.COM * the file descriptor chain which is protected by the
17147836SJohn.Forte@Sun.COM * device lock.
17157836SJohn.Forte@Sun.COM *
17167836SJohn.Forte@Sun.COM * On return the file descriptor must contain all the
17177836SJohn.Forte@Sun.COM * information necessary to perform an open. Details
17187836SJohn.Forte@Sun.COM * specific to user callbacks are not required yet.
17197836SJohn.Forte@Sun.COM */
17207836SJohn.Forte@Sun.COM static int
_nsc_alloc_fd(path,type,flag,fdp)17217836SJohn.Forte@Sun.COM _nsc_alloc_fd(path, type, flag, fdp)
17227836SJohn.Forte@Sun.COM char *path;
17237836SJohn.Forte@Sun.COM int type, flag;
17247836SJohn.Forte@Sun.COM nsc_fd_t **fdp;
17257836SJohn.Forte@Sun.COM {
17267836SJohn.Forte@Sun.COM nsc_dev_t *dev;
17277836SJohn.Forte@Sun.COM nsc_fd_t *fd;
17287836SJohn.Forte@Sun.COM int rc;
17297836SJohn.Forte@Sun.COM
17307836SJohn.Forte@Sun.COM if (!(fd = (nsc_fd_t *)nsc_kmem_zalloc(
17317836SJohn.Forte@Sun.COM sizeof (*fd), KM_SLEEP, _nsc_local_mem)))
17327836SJohn.Forte@Sun.COM return (ENOMEM);
17337836SJohn.Forte@Sun.COM
17347836SJohn.Forte@Sun.COM if ((rc = _nsc_alloc_dev(path, &dev)) != 0) {
17357836SJohn.Forte@Sun.COM nsc_kmem_free(fd, sizeof (*fd));
17367836SJohn.Forte@Sun.COM return (rc);
17377836SJohn.Forte@Sun.COM }
17387836SJohn.Forte@Sun.COM
17397836SJohn.Forte@Sun.COM mutex_enter(&dev->nsc_lock);
17407836SJohn.Forte@Sun.COM
17417836SJohn.Forte@Sun.COM fd->sf_type = type;
17427836SJohn.Forte@Sun.COM fd->sf_flag = flag;
17437836SJohn.Forte@Sun.COM fd->sf_dev = dev;
17447836SJohn.Forte@Sun.COM fd->sf_next = dev->nsc_close;
17457836SJohn.Forte@Sun.COM dev->nsc_close = fd;
17467836SJohn.Forte@Sun.COM
17477836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
17487836SJohn.Forte@Sun.COM
17497836SJohn.Forte@Sun.COM *fdp = fd;
17507836SJohn.Forte@Sun.COM return (0);
17517836SJohn.Forte@Sun.COM }
17527836SJohn.Forte@Sun.COM
17537836SJohn.Forte@Sun.COM
17547836SJohn.Forte@Sun.COM /*
17557836SJohn.Forte@Sun.COM * static int
17567836SJohn.Forte@Sun.COM * _nsc_free_fd (nsc_fd_t *)
17577836SJohn.Forte@Sun.COM * Free file descriptor.
17587836SJohn.Forte@Sun.COM *
17597836SJohn.Forte@Sun.COM * Description:
17607836SJohn.Forte@Sun.COM * The file descriptor is removed from the chain and free'd
17617836SJohn.Forte@Sun.COM * once pending activity has completed.
17627836SJohn.Forte@Sun.COM */
17637836SJohn.Forte@Sun.COM static void
_nsc_free_fd(fd)17647836SJohn.Forte@Sun.COM _nsc_free_fd(fd)
17657836SJohn.Forte@Sun.COM nsc_fd_t *fd;
17667836SJohn.Forte@Sun.COM {
17677836SJohn.Forte@Sun.COM nsc_dev_t *dev = fd->sf_dev;
17687836SJohn.Forte@Sun.COM nsc_fd_t **fdp;
17697836SJohn.Forte@Sun.COM
17707836SJohn.Forte@Sun.COM if (!fd)
17717836SJohn.Forte@Sun.COM return;
17727836SJohn.Forte@Sun.COM
17737836SJohn.Forte@Sun.COM mutex_enter(&dev->nsc_lock);
17747836SJohn.Forte@Sun.COM
17757836SJohn.Forte@Sun.COM for (fdp = &dev->nsc_close; *fdp; fdp = &(*fdp)->sf_next)
17767836SJohn.Forte@Sun.COM if (*fdp == fd) {
17777836SJohn.Forte@Sun.COM *fdp = fd->sf_next;
17787836SJohn.Forte@Sun.COM break;
17797836SJohn.Forte@Sun.COM }
17807836SJohn.Forte@Sun.COM
17817836SJohn.Forte@Sun.COM if (dev->nsc_wait || dev->nsc_refcnt <= 0)
17827836SJohn.Forte@Sun.COM cv_broadcast(&dev->nsc_cv);
17837836SJohn.Forte@Sun.COM
17847836SJohn.Forte@Sun.COM while (fd->sf_pend)
17857836SJohn.Forte@Sun.COM (void) _nsc_wait_dev(dev, 0);
17867836SJohn.Forte@Sun.COM
17877836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
17887836SJohn.Forte@Sun.COM
17897836SJohn.Forte@Sun.COM _nsc_free_dev(dev);
17907836SJohn.Forte@Sun.COM
17917836SJohn.Forte@Sun.COM nsc_kmem_free(fd, sizeof (*fd));
17927836SJohn.Forte@Sun.COM }
17937836SJohn.Forte@Sun.COM
17947836SJohn.Forte@Sun.COM
17957836SJohn.Forte@Sun.COM /*
17967836SJohn.Forte@Sun.COM * static void
17977836SJohn.Forte@Sun.COM * _nsc_relink_fd (nsc_fd_t *fd, nsc_fd_t **from,
17987836SJohn.Forte@Sun.COM * nsc_fd_t **to, nsc_iodev_t *iodev)
17997836SJohn.Forte@Sun.COM * Relink file descriptor.
18007836SJohn.Forte@Sun.COM *
18017836SJohn.Forte@Sun.COM * Description:
18027836SJohn.Forte@Sun.COM * Remove the file descriptor from the 'from' chain and
18037836SJohn.Forte@Sun.COM * add it to the 'to' chain. The busy flag in iodev is
18047836SJohn.Forte@Sun.COM * used to prevent modifications to the chain whilst a
18057836SJohn.Forte@Sun.COM * callback is in progress.
18067836SJohn.Forte@Sun.COM */
18077836SJohn.Forte@Sun.COM static void
_nsc_relink_fd(nsc_fd_t * fd,nsc_fd_t ** from,nsc_fd_t ** to,nsc_iodev_t * iodev)18087836SJohn.Forte@Sun.COM _nsc_relink_fd(nsc_fd_t *fd, nsc_fd_t **from, nsc_fd_t **to, nsc_iodev_t *iodev)
18097836SJohn.Forte@Sun.COM {
18107836SJohn.Forte@Sun.COM nsc_dev_t *dev = fd->sf_dev;
18117836SJohn.Forte@Sun.COM nsc_fd_t **fdp;
18127836SJohn.Forte@Sun.COM
18137836SJohn.Forte@Sun.COM mutex_enter(&dev->nsc_lock);
18147836SJohn.Forte@Sun.COM
18157836SJohn.Forte@Sun.COM while (iodev->si_busy)
18167836SJohn.Forte@Sun.COM (void) _nsc_wait_dev(dev, 0);
18177836SJohn.Forte@Sun.COM
18187836SJohn.Forte@Sun.COM for (fdp = from; *fdp; fdp = &(*fdp)->sf_next)
18197836SJohn.Forte@Sun.COM if (*fdp == fd) {
18207836SJohn.Forte@Sun.COM *fdp = fd->sf_next;
18217836SJohn.Forte@Sun.COM break;
18227836SJohn.Forte@Sun.COM }
18237836SJohn.Forte@Sun.COM
18247836SJohn.Forte@Sun.COM fd->sf_next = (*to);
18257836SJohn.Forte@Sun.COM (*to) = fd;
18267836SJohn.Forte@Sun.COM
18277836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
18287836SJohn.Forte@Sun.COM }
18297836SJohn.Forte@Sun.COM
18307836SJohn.Forte@Sun.COM
18317836SJohn.Forte@Sun.COM /*
18327836SJohn.Forte@Sun.COM * static int
18337836SJohn.Forte@Sun.COM * _nsc_alloc_iodev (nsc_dev_t *dev, int type, nsc_iodev_t **iodevp)
18347836SJohn.Forte@Sun.COM * Allocate I/O device structure.
18357836SJohn.Forte@Sun.COM *
18367836SJohn.Forte@Sun.COM * Calling/Exit State:
18377836SJohn.Forte@Sun.COM * Stores address of I/O device structure through iodevp
18387836SJohn.Forte@Sun.COM * and returns 0 on success, otherwise returns error code.
18397836SJohn.Forte@Sun.COM *
18407836SJohn.Forte@Sun.COM * Description:
18417836SJohn.Forte@Sun.COM * If an entry for the I/O device already exists increment
18427836SJohn.Forte@Sun.COM * the reference count and return the address, otherwise
18437836SJohn.Forte@Sun.COM * allocate a new structure.
18447836SJohn.Forte@Sun.COM *
18457836SJohn.Forte@Sun.COM * A new structure is allocated before scanning the chain
18467836SJohn.Forte@Sun.COM * to avoid calling the memory allocator with a spin lock
18477836SJohn.Forte@Sun.COM * held. If an entry is found the new structure is free'd.
18487836SJohn.Forte@Sun.COM *
18497836SJohn.Forte@Sun.COM * The I/O device chain is protected by the device lock.
18507836SJohn.Forte@Sun.COM */
18517836SJohn.Forte@Sun.COM static int
_nsc_alloc_iodev(dev,type,iodevp)18527836SJohn.Forte@Sun.COM _nsc_alloc_iodev(dev, type, iodevp)
18537836SJohn.Forte@Sun.COM nsc_dev_t *dev;
18547836SJohn.Forte@Sun.COM int type;
18557836SJohn.Forte@Sun.COM nsc_iodev_t **iodevp;
18567836SJohn.Forte@Sun.COM {
18577836SJohn.Forte@Sun.COM nsc_iodev_t *iodev, *ip;
18587836SJohn.Forte@Sun.COM nsc_io_t *io;
18597836SJohn.Forte@Sun.COM
18607836SJohn.Forte@Sun.COM if (!(iodev = (nsc_iodev_t *)nsc_kmem_zalloc(
18617836SJohn.Forte@Sun.COM sizeof (*iodev), KM_SLEEP, _nsc_local_mem)))
18627836SJohn.Forte@Sun.COM return (ENOMEM);
18637836SJohn.Forte@Sun.COM
18647836SJohn.Forte@Sun.COM mutex_init(&iodev->si_lock, NULL, MUTEX_DRIVER, NULL);
18657836SJohn.Forte@Sun.COM cv_init(&iodev->si_cv, NULL, CV_DRIVER, NULL);
18667836SJohn.Forte@Sun.COM
18677836SJohn.Forte@Sun.COM if (!(io = _nsc_reserve_io(dev->nsc_path, type))) {
18687836SJohn.Forte@Sun.COM mutex_destroy(&iodev->si_lock);
18697836SJohn.Forte@Sun.COM cv_destroy(&iodev->si_cv);
18707836SJohn.Forte@Sun.COM nsc_kmem_free(iodev, sizeof (*iodev));
18717836SJohn.Forte@Sun.COM return (ENXIO);
18727836SJohn.Forte@Sun.COM }
18737836SJohn.Forte@Sun.COM
18747836SJohn.Forte@Sun.COM iodev->si_refcnt++;
18757836SJohn.Forte@Sun.COM iodev->si_io = io;
18767836SJohn.Forte@Sun.COM iodev->si_dev = dev;
18777836SJohn.Forte@Sun.COM
18787836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
18797836SJohn.Forte@Sun.COM dev->nsc_refcnt++;
18807836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
18817836SJohn.Forte@Sun.COM
18827836SJohn.Forte@Sun.COM mutex_enter(&dev->nsc_lock);
18837836SJohn.Forte@Sun.COM
18847836SJohn.Forte@Sun.COM for (ip = dev->nsc_list; ip; ip = ip->si_next)
18857836SJohn.Forte@Sun.COM if (ip->si_io == io) {
18867836SJohn.Forte@Sun.COM ip->si_refcnt++;
18877836SJohn.Forte@Sun.COM break;
18887836SJohn.Forte@Sun.COM }
18897836SJohn.Forte@Sun.COM
18907836SJohn.Forte@Sun.COM if (!ip) {
18917836SJohn.Forte@Sun.COM iodev->si_next = dev->nsc_list;
18927836SJohn.Forte@Sun.COM dev->nsc_list = iodev;
18937836SJohn.Forte@Sun.COM }
18947836SJohn.Forte@Sun.COM
18957836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
18967836SJohn.Forte@Sun.COM
18977836SJohn.Forte@Sun.COM if (ip) {
18987836SJohn.Forte@Sun.COM _nsc_free_iodev(iodev);
18997836SJohn.Forte@Sun.COM iodev = ip;
19007836SJohn.Forte@Sun.COM }
19017836SJohn.Forte@Sun.COM
19027836SJohn.Forte@Sun.COM *iodevp = iodev;
19037836SJohn.Forte@Sun.COM return (0);
19047836SJohn.Forte@Sun.COM }
19057836SJohn.Forte@Sun.COM
19067836SJohn.Forte@Sun.COM
19077836SJohn.Forte@Sun.COM /*
19087836SJohn.Forte@Sun.COM * static int
19097836SJohn.Forte@Sun.COM * _nsc_free_iodev (nsc_iodev_t *iodev)
19107836SJohn.Forte@Sun.COM * Free I/O device structure.
19117836SJohn.Forte@Sun.COM *
19127836SJohn.Forte@Sun.COM * Description:
19137836SJohn.Forte@Sun.COM * Decrements the reference count of a previously allocated
19147836SJohn.Forte@Sun.COM * I/O device structure. If this is the last reference it
19157836SJohn.Forte@Sun.COM * is removed from the device chain and free'd once pending
19167836SJohn.Forte@Sun.COM * activity has completed.
19177836SJohn.Forte@Sun.COM */
19187836SJohn.Forte@Sun.COM static void
_nsc_free_iodev(nsc_iodev_t * iodev)19197836SJohn.Forte@Sun.COM _nsc_free_iodev(nsc_iodev_t *iodev)
19207836SJohn.Forte@Sun.COM {
19217836SJohn.Forte@Sun.COM nsc_iodev_t **ipp;
19227836SJohn.Forte@Sun.COM nsc_dev_t *dev;
19237836SJohn.Forte@Sun.COM
19247836SJohn.Forte@Sun.COM if (!iodev)
19257836SJohn.Forte@Sun.COM return;
19267836SJohn.Forte@Sun.COM
19277836SJohn.Forte@Sun.COM dev = iodev->si_dev;
19287836SJohn.Forte@Sun.COM
19297836SJohn.Forte@Sun.COM mutex_enter(&dev->nsc_lock);
19307836SJohn.Forte@Sun.COM
19317836SJohn.Forte@Sun.COM if (--iodev->si_refcnt > 0) {
19327836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
19337836SJohn.Forte@Sun.COM return;
19347836SJohn.Forte@Sun.COM }
19357836SJohn.Forte@Sun.COM
19367836SJohn.Forte@Sun.COM for (ipp = &dev->nsc_list; *ipp; ipp = &(*ipp)->si_next)
19377836SJohn.Forte@Sun.COM if (*ipp == iodev) {
19387836SJohn.Forte@Sun.COM *ipp = iodev->si_next;
19397836SJohn.Forte@Sun.COM break;
19407836SJohn.Forte@Sun.COM }
19417836SJohn.Forte@Sun.COM
19427836SJohn.Forte@Sun.COM if (dev->nsc_wait || dev->nsc_refcnt <= 0)
19437836SJohn.Forte@Sun.COM cv_broadcast(&dev->nsc_cv);
19447836SJohn.Forte@Sun.COM
19457836SJohn.Forte@Sun.COM while (iodev->si_pend || iodev->si_rpend || iodev->si_busy)
19467836SJohn.Forte@Sun.COM (void) _nsc_wait_dev(dev, 0);
19477836SJohn.Forte@Sun.COM
19487836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
19497836SJohn.Forte@Sun.COM
19507836SJohn.Forte@Sun.COM _nsc_release_io(iodev->si_io);
19517836SJohn.Forte@Sun.COM _nsc_free_dev(dev);
19527836SJohn.Forte@Sun.COM
19537836SJohn.Forte@Sun.COM mutex_destroy(&iodev->si_lock);
19547836SJohn.Forte@Sun.COM cv_destroy(&iodev->si_cv);
19557836SJohn.Forte@Sun.COM
19567836SJohn.Forte@Sun.COM nsc_kmem_free(iodev, sizeof (*iodev));
19577836SJohn.Forte@Sun.COM }
19587836SJohn.Forte@Sun.COM
19597836SJohn.Forte@Sun.COM
19607836SJohn.Forte@Sun.COM /*
19617836SJohn.Forte@Sun.COM * static int
19627836SJohn.Forte@Sun.COM * _nsc_alloc_dev (char *path, nsc_dev_t **devp)
19637836SJohn.Forte@Sun.COM * Allocate device structure.
19647836SJohn.Forte@Sun.COM *
19657836SJohn.Forte@Sun.COM * Calling/Exit State:
19667836SJohn.Forte@Sun.COM * Stores address of device structure through devp
19677836SJohn.Forte@Sun.COM * and returns 0 on success, otherwise returns error
19687836SJohn.Forte@Sun.COM * code.
19697836SJohn.Forte@Sun.COM *
19707836SJohn.Forte@Sun.COM * Description:
19717836SJohn.Forte@Sun.COM * If an entry for the device already exists increment
19727836SJohn.Forte@Sun.COM * the reference count and return the address, otherwise
19737836SJohn.Forte@Sun.COM * allocate a new structure.
19747836SJohn.Forte@Sun.COM *
19757836SJohn.Forte@Sun.COM * A new structure is allocated before scanning the device
19767836SJohn.Forte@Sun.COM * chain to avoid calling the memory allocator with a spin
19777836SJohn.Forte@Sun.COM * lock held. If the device is found the new structure is
19787836SJohn.Forte@Sun.COM * free'd.
19797836SJohn.Forte@Sun.COM *
19807836SJohn.Forte@Sun.COM * The device chain is protected by _nsc_io_lock.
19817836SJohn.Forte@Sun.COM */
19827836SJohn.Forte@Sun.COM static int
_nsc_alloc_dev(char * path,nsc_dev_t ** devp)19837836SJohn.Forte@Sun.COM _nsc_alloc_dev(char *path, nsc_dev_t **devp)
19847836SJohn.Forte@Sun.COM {
19857836SJohn.Forte@Sun.COM nsc_dev_t *dev, *dp, **ddp;
19867836SJohn.Forte@Sun.COM nsc_devval_t *dv;
19877836SJohn.Forte@Sun.COM nsc_rval_t *rval;
19887836SJohn.Forte@Sun.COM ncall_t *ncall;
19897836SJohn.Forte@Sun.COM int rc;
19907836SJohn.Forte@Sun.COM
19917836SJohn.Forte@Sun.COM if (!(dev = (nsc_dev_t *)nsc_kmem_zalloc(
19927836SJohn.Forte@Sun.COM sizeof (*dev), KM_SLEEP, _nsc_local_mem)))
19937836SJohn.Forte@Sun.COM return (ENOMEM);
19947836SJohn.Forte@Sun.COM
19957836SJohn.Forte@Sun.COM dev->nsc_refcnt++;
19967836SJohn.Forte@Sun.COM
19977836SJohn.Forte@Sun.COM mutex_init(&dev->nsc_lock, NULL, MUTEX_DRIVER, NULL);
19987836SJohn.Forte@Sun.COM cv_init(&dev->nsc_cv, NULL, CV_DRIVER, NULL);
19997836SJohn.Forte@Sun.COM
20007836SJohn.Forte@Sun.COM dev->nsc_phash = nsc_strhash(path);
20017836SJohn.Forte@Sun.COM dev->nsc_path = nsc_strdup(path);
20027836SJohn.Forte@Sun.COM
20037836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
20047836SJohn.Forte@Sun.COM
20057836SJohn.Forte@Sun.COM dev->nsc_next = _nsc_dev_pend;
20067836SJohn.Forte@Sun.COM _nsc_dev_pend = dev;
20077836SJohn.Forte@Sun.COM
20087836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
20097836SJohn.Forte@Sun.COM
20107836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
20117836SJohn.Forte@Sun.COM
20127836SJohn.Forte@Sun.COM for (dp = _nsc_dev_top; dp; dp = dp->nsc_next)
20137836SJohn.Forte@Sun.COM if (dp->nsc_phash == dev->nsc_phash &&
20147836SJohn.Forte@Sun.COM strcmp(dp->nsc_path, dev->nsc_path) == 0) {
20157836SJohn.Forte@Sun.COM dp->nsc_refcnt++;
20167836SJohn.Forte@Sun.COM break;
20177836SJohn.Forte@Sun.COM }
20187836SJohn.Forte@Sun.COM
20197836SJohn.Forte@Sun.COM if (!dp) {
20207836SJohn.Forte@Sun.COM for (ddp = &_nsc_dev_pend; *ddp; ddp = &(*ddp)->nsc_next)
20217836SJohn.Forte@Sun.COM if (*ddp == dev) {
20227836SJohn.Forte@Sun.COM *ddp = dev->nsc_next;
20237836SJohn.Forte@Sun.COM break;
20247836SJohn.Forte@Sun.COM }
20257836SJohn.Forte@Sun.COM
20267836SJohn.Forte@Sun.COM dev->nsc_next = _nsc_dev_top;
20277836SJohn.Forte@Sun.COM _nsc_dev_top = dev;
20287836SJohn.Forte@Sun.COM }
20297836SJohn.Forte@Sun.COM
20307836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
20317836SJohn.Forte@Sun.COM
20327836SJohn.Forte@Sun.COM if (dp) {
20337836SJohn.Forte@Sun.COM _nsc_free_dev(dev);
20347836SJohn.Forte@Sun.COM dev = dp;
20357836SJohn.Forte@Sun.COM }
20367836SJohn.Forte@Sun.COM
20377836SJohn.Forte@Sun.COM /*
20387836SJohn.Forte@Sun.COM * Try and find the device/values header for this device
20397836SJohn.Forte@Sun.COM * and link it back to the device structure.
20407836SJohn.Forte@Sun.COM */
20417836SJohn.Forte@Sun.COM
20427836SJohn.Forte@Sun.COM mutex_enter(&_nsc_devval_lock);
20437836SJohn.Forte@Sun.COM
20447836SJohn.Forte@Sun.COM if (dev->nsc_values == NULL) {
20457836SJohn.Forte@Sun.COM for (dv = _nsc_devval_top; dv; dv = dv->dv_next) {
20467836SJohn.Forte@Sun.COM if (dv->dv_phash == dev->nsc_phash &&
20477836SJohn.Forte@Sun.COM strcmp(dv->dv_path, dev->nsc_path) == 0) {
20487836SJohn.Forte@Sun.COM dev->nsc_values = dv;
20497836SJohn.Forte@Sun.COM break;
20507836SJohn.Forte@Sun.COM }
20517836SJohn.Forte@Sun.COM }
20527836SJohn.Forte@Sun.COM }
20537836SJohn.Forte@Sun.COM
20547836SJohn.Forte@Sun.COM mutex_exit(&_nsc_devval_lock);
20557836SJohn.Forte@Sun.COM
20567836SJohn.Forte@Sun.COM /*
20577836SJohn.Forte@Sun.COM * Refresh the device/values from the other node
20587836SJohn.Forte@Sun.COM */
20597836SJohn.Forte@Sun.COM
20607836SJohn.Forte@Sun.COM rval = nsc_kmem_zalloc(sizeof (*rval), KM_SLEEP, _nsc_local_mem);
20617836SJohn.Forte@Sun.COM if (rval == NULL) {
20627836SJohn.Forte@Sun.COM goto out;
20637836SJohn.Forte@Sun.COM }
20647836SJohn.Forte@Sun.COM
20657836SJohn.Forte@Sun.COM rc = ncall_alloc(ncall_mirror(ncall_self()), 0, 0, &ncall);
20667836SJohn.Forte@Sun.COM if (rc == 0) {
20677836SJohn.Forte@Sun.COM (void) strncpy(rval->path, path, sizeof (rval->path));
20687836SJohn.Forte@Sun.COM
20697836SJohn.Forte@Sun.COM rc = ncall_put_data(ncall, rval, sizeof (*rval));
20707836SJohn.Forte@Sun.COM if (rc == 0) {
20717836SJohn.Forte@Sun.COM /*
20727836SJohn.Forte@Sun.COM * Send synchronously and read a reply
20737836SJohn.Forte@Sun.COM * so that we know that the updates
20747836SJohn.Forte@Sun.COM * have completed before this
20757836SJohn.Forte@Sun.COM * function returns.
20767836SJohn.Forte@Sun.COM */
20777836SJohn.Forte@Sun.COM if (ncall_send(ncall, 0, NSC_SETVAL_ALL) == 0)
20787836SJohn.Forte@Sun.COM (void) ncall_read_reply(ncall, 1, &rc);
20797836SJohn.Forte@Sun.COM }
20807836SJohn.Forte@Sun.COM
20817836SJohn.Forte@Sun.COM ncall_free(ncall);
20827836SJohn.Forte@Sun.COM }
20837836SJohn.Forte@Sun.COM
20847836SJohn.Forte@Sun.COM nsc_kmem_free(rval, sizeof (*rval));
20857836SJohn.Forte@Sun.COM
20867836SJohn.Forte@Sun.COM out:
20877836SJohn.Forte@Sun.COM *devp = dev;
20887836SJohn.Forte@Sun.COM return (0);
20897836SJohn.Forte@Sun.COM }
20907836SJohn.Forte@Sun.COM
20917836SJohn.Forte@Sun.COM
20927836SJohn.Forte@Sun.COM /*
20937836SJohn.Forte@Sun.COM * static void
20947836SJohn.Forte@Sun.COM * _nsc_free_dev (nsc_dev_t *dev)
20957836SJohn.Forte@Sun.COM * Free device structure.
20967836SJohn.Forte@Sun.COM *
20977836SJohn.Forte@Sun.COM * Description:
20987836SJohn.Forte@Sun.COM * Decrements the reference count of a previously allocated
20997836SJohn.Forte@Sun.COM * device structure. If this is the last reference it is
21007836SJohn.Forte@Sun.COM * removed from the device chain and free'd once pending
21017836SJohn.Forte@Sun.COM * activity has completed.
21027836SJohn.Forte@Sun.COM *
21037836SJohn.Forte@Sun.COM * Whilst waiting for pending activity to cease the device is
21047836SJohn.Forte@Sun.COM * relinked onto the pending chain.
21057836SJohn.Forte@Sun.COM */
21067836SJohn.Forte@Sun.COM static void
_nsc_free_dev(dev)21077836SJohn.Forte@Sun.COM _nsc_free_dev(dev)
21087836SJohn.Forte@Sun.COM nsc_dev_t *dev;
21097836SJohn.Forte@Sun.COM {
21107836SJohn.Forte@Sun.COM nsc_dev_t **ddp;
21117836SJohn.Forte@Sun.COM
21127836SJohn.Forte@Sun.COM if (!dev)
21137836SJohn.Forte@Sun.COM return;
21147836SJohn.Forte@Sun.COM
21157836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
21167836SJohn.Forte@Sun.COM
21177836SJohn.Forte@Sun.COM if (--dev->nsc_refcnt > 0) {
21187836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
21197836SJohn.Forte@Sun.COM return;
21207836SJohn.Forte@Sun.COM }
21217836SJohn.Forte@Sun.COM
21227836SJohn.Forte@Sun.COM for (ddp = &_nsc_dev_top; *ddp; ddp = &(*ddp)->nsc_next)
21237836SJohn.Forte@Sun.COM if (*ddp == dev) {
21247836SJohn.Forte@Sun.COM *ddp = dev->nsc_next;
21257836SJohn.Forte@Sun.COM dev->nsc_next = _nsc_dev_pend;
21267836SJohn.Forte@Sun.COM _nsc_dev_pend = dev;
21277836SJohn.Forte@Sun.COM break;
21287836SJohn.Forte@Sun.COM }
21297836SJohn.Forte@Sun.COM
21307836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
21317836SJohn.Forte@Sun.COM
21327836SJohn.Forte@Sun.COM mutex_enter(&dev->nsc_lock);
21337836SJohn.Forte@Sun.COM
21347836SJohn.Forte@Sun.COM while (dev->nsc_pend || dev->nsc_rpend || dev->nsc_wait) {
21357836SJohn.Forte@Sun.COM cv_wait(&dev->nsc_cv, &dev->nsc_lock);
21367836SJohn.Forte@Sun.COM }
21377836SJohn.Forte@Sun.COM
21387836SJohn.Forte@Sun.COM mutex_exit(&dev->nsc_lock);
21397836SJohn.Forte@Sun.COM
21407836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
21417836SJohn.Forte@Sun.COM
21427836SJohn.Forte@Sun.COM for (ddp = &_nsc_dev_pend; *ddp; ddp = &(*ddp)->nsc_next)
21437836SJohn.Forte@Sun.COM if (*ddp == dev) {
21447836SJohn.Forte@Sun.COM *ddp = dev->nsc_next;
21457836SJohn.Forte@Sun.COM break;
21467836SJohn.Forte@Sun.COM }
21477836SJohn.Forte@Sun.COM
21487836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
21497836SJohn.Forte@Sun.COM
21507836SJohn.Forte@Sun.COM mutex_destroy(&dev->nsc_lock);
21517836SJohn.Forte@Sun.COM cv_destroy(&dev->nsc_cv);
21527836SJohn.Forte@Sun.COM nsc_strfree(dev->nsc_path);
21537836SJohn.Forte@Sun.COM
21547836SJohn.Forte@Sun.COM nsc_kmem_free(dev, sizeof (*dev));
21557836SJohn.Forte@Sun.COM }
21567836SJohn.Forte@Sun.COM
21577836SJohn.Forte@Sun.COM
21587836SJohn.Forte@Sun.COM /*
21597836SJohn.Forte@Sun.COM * static nsc_io_t *
21607836SJohn.Forte@Sun.COM * _nsc_alloc_io (int id, char *name, int flag)
21617836SJohn.Forte@Sun.COM * Allocate an I/O structure.
21627836SJohn.Forte@Sun.COM *
21637836SJohn.Forte@Sun.COM * Calling/Exit State:
21647836SJohn.Forte@Sun.COM * Returns the address of the I/O structure, or NULL.
21657836SJohn.Forte@Sun.COM */
21667836SJohn.Forte@Sun.COM static nsc_io_t *
_nsc_alloc_io(id,name,flag)21677836SJohn.Forte@Sun.COM _nsc_alloc_io(id, name, flag)
21687836SJohn.Forte@Sun.COM int id;
21697836SJohn.Forte@Sun.COM char *name;
21707836SJohn.Forte@Sun.COM int flag;
21717836SJohn.Forte@Sun.COM {
21727836SJohn.Forte@Sun.COM nsc_io_t *io;
21737836SJohn.Forte@Sun.COM
21747836SJohn.Forte@Sun.COM if (!(io = (nsc_io_t *)nsc_kmem_zalloc(
21757836SJohn.Forte@Sun.COM sizeof (*io), KM_NOSLEEP, _nsc_local_mem)))
21767836SJohn.Forte@Sun.COM return (NULL);
21777836SJohn.Forte@Sun.COM
21787836SJohn.Forte@Sun.COM cv_init(&io->cv, NULL, CV_DRIVER, NULL);
21797836SJohn.Forte@Sun.COM
21807836SJohn.Forte@Sun.COM io->id = id;
21817836SJohn.Forte@Sun.COM io->name = name;
21827836SJohn.Forte@Sun.COM io->flag = flag;
21837836SJohn.Forte@Sun.COM
21847836SJohn.Forte@Sun.COM return (io);
21857836SJohn.Forte@Sun.COM }
21867836SJohn.Forte@Sun.COM
21877836SJohn.Forte@Sun.COM
21887836SJohn.Forte@Sun.COM /*
21897836SJohn.Forte@Sun.COM * static void
21907836SJohn.Forte@Sun.COM * _nsc_free_io (int id, char *name, int flag)
21917836SJohn.Forte@Sun.COM * Free an I/O structure.
21927836SJohn.Forte@Sun.COM *
21937836SJohn.Forte@Sun.COM * Calling/Exit State:
21947836SJohn.Forte@Sun.COM * Free the I/O structure and remove it from the chain.
21957836SJohn.Forte@Sun.COM */
21967836SJohn.Forte@Sun.COM static void
_nsc_free_io(io)21977836SJohn.Forte@Sun.COM _nsc_free_io(io)
21987836SJohn.Forte@Sun.COM nsc_io_t *io;
21997836SJohn.Forte@Sun.COM {
22007836SJohn.Forte@Sun.COM nsc_io_t **iop;
22017836SJohn.Forte@Sun.COM
22027836SJohn.Forte@Sun.COM mutex_enter(&_nsc_io_lock);
22037836SJohn.Forte@Sun.COM
22047836SJohn.Forte@Sun.COM for (iop = &_nsc_io_top; *iop; iop = &(*iop)->next)
22057836SJohn.Forte@Sun.COM if (*iop == io)
22067836SJohn.Forte@Sun.COM break;
22077836SJohn.Forte@Sun.COM
22087836SJohn.Forte@Sun.COM if (*iop)
22097836SJohn.Forte@Sun.COM (*iop) = io->next;
22107836SJohn.Forte@Sun.COM
22117836SJohn.Forte@Sun.COM mutex_exit(&_nsc_io_lock);
22127836SJohn.Forte@Sun.COM
22137836SJohn.Forte@Sun.COM cv_destroy(&io->cv);
22147836SJohn.Forte@Sun.COM nsc_kmem_free(io, sizeof (*io));
22157836SJohn.Forte@Sun.COM }
2216