/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#define __NSC_GEN__
#include "nsc_dev.h"
#include "../nsctl.h"
#ifdef DS_DDICT
#include "../contract.h"
#endif
static int _nsc_attach_fd(nsc_fd_t *, int);
static int _nsc_detach_owner(nsc_fd_t *, int);
static int _nsc_fd_fn(nsc_fd_t *, int (*)(), int, int);
static int _nsc_attach_iodev(nsc_iodev_t *, int);
static int _nsc_attach_dev(nsc_dev_t *, int);
int *, int *, int, int, nsc_iodev_t *);
/*
* void
* _nsc_init_resv (void)
* Initialise reserve mechanism.
*
* Called at initialisation time to allocate necessary
* data structures.
*/
void
{
}
/*
* void
* _nsc_deinit_resv (void)
* De-initialise reserve mechanism.
*
* Called at unload time to de-allocate resources.
*/
void
{
}
/*
* int
* nsc_attach (nsc_fd_t *fd, int flag)
* Force attach of file descriptor.
*
* Returns 0 if the attach succeeds, otherwise
* returns an error code.
*
* Description:
* Tries to attach the file descriptor by reserving
* and then releasing it. This is intended purely as
* a performance aid since there is no guarantee that
* the file descriptor will remain attached upon
* return.
*/
int
int flag;
{
int rc;
if (rc == 0)
return (rc);
}
/*
* int
* nsc_reserve (nsc_fd_t *fd, int flag)
* Reserve file descriptor.
*
* Returns 0 if the reserve succeeds, otherwise
* returns an error code.
*
* Description:
* Reserves the file descriptor for either NSC_READ or
* NSC_WRITE access. If neither is specified the mode
* with which the file was opened will be used. Trying
* to reserve a read only file in write mode will cause
* EACCES to be returned.
*
* If NSC_NOBLOCK is specifed and the reserve cannot be
* completed immediately, EAGAIN will be returned.
*
* If NSC_NOWAIT is set and the device is busy, EAGAIN
* will be returned.
*
* If NSC_TRY is set and the device is already reserved
* EAGAIN will be returned.
*
* If NSC_PCATCH is specified and a signal is received,
* the reserve will be terminated and EINTR returned.
*
* If NSC_MULTI is set then multiple reserves of the
* same type are permitted for the file descriptor.
*/
int
int flag;
{
return (EACCES);
break;
}
return (rc);
}
/*
* int
* nsc_reserve_lk (nsc_fd_t *fd)
* Reserve locked file descriptor.
*
* The device lock must be held across calls to
* this function.
*
* Must be preceeded by a successful call to nsc_avail.
*
* Description:
* Reserves the file descriptor using the mode specified
* when the file was opened. This is only intended for
* use in performance critical situations.
*/
void
{
}
/*
* int
* nsc_avail (nsc_fd_t *fd)
* Test if file descriptor is available.
*
* The device lock must be held across calls to
* this function.
*
* Returns true if the file descriptor is available to
* be reserved using the mode specified when the file
* was opened.
*
* Description:
* This is only intended for use in performance critical
* situations in conjunction with nsc_reserve_lk.
*/
int
{
int rw;
return (0);
return (0);
return (0);
}
/*
* int
* nsc_held (nsc_fd_t *fd)
* Test if file descriptor is reserved.
*
* Returns true if the file descriptor is currently
* reserved.
*/
int
{
}
/*
* int
* nsc_waiting (nsc_fd_t *fd)
* Test if another client is waiting for this device.
*
* Must be called with the file descriptor reserved.
* Returns true if another thread is waiting to reserve this device.
*
* Description:
* This is only intended for use in performance critical
* situations and inherently returns historical information.
*/
int
{
return (FALSE);
}
/*
* int
* nsc_release_lk (nsc_fd_t *fd)
* Release locked file descriptor.
*
* The device lock must be held across calls to
* this function.
*
* Returns true if another node is waiting for the
* device and a call to nsc_detach should be made.
*
* Description:
* Releases the file descriptor. This is only intended
* for use in performance critical situations in
* conjunction with nsc_reserve_lk.
*/
int
{
fd->sf_reserve = 0;
}
/*
* int
* nsc_release (nsc_fd_t *fd)
* Release file descriptor.
*
* Description:
* Releases the file descriptor. If another node
* is waiting for the device it will be completely
* detached before returning.
*/
void
{
int rc;
return;
}
break;
}
}
/*
* int
* nsc_detach (nsc_fd_t *fd, int flag)
* Detach device from node.
*
* Returns 0 if the reserve succeeds, otherwise
* returns an error code.
*
* Description:
* Detaches the device from the current node. If flag
* specifies read access then flush is called in preference
* to detach.
*
* If NSC_NOBLOCK is specifed and the detach cannot be
* completed immediately, EAGAIN will be returned.
*
* If NSC_TRY is set and the device is reserved, EAGAIN
* will be returned.
*
* If NSC_NOWAIT is set and the device is busy, EAGAIN
* will be returned.
*
* If NSC_PCATCH is specified and a signal is received,
* the reserve will be terminated and EINTR returned.
*
* If NSC_DEFER is set and the device is reserved, then
* the detach will be done on release.
*/
int
int flag;
{
int rc;
if (!fd)
return (0);
break;
return (rc);
}
/*
* static int
* _nsc_attach_fd (nsc_fd_t *fd, int flag)
* Attach file descriptor.
*
* The device lock must be held across calls to
* this function.
*
* Returns 0 if the attach succeeds without releasing
* the device lock, otherwise returns an error code.
*
* Description:
* Attach the specified file descriptor. Other file
* descriptors for the same I/O device will be flushed
* or detached first as necessary.
*/
static int
int flag;
{
return (rc);
return (rc);
return (0);
if (fd->sf_reserve) {
return (EAGAIN);
}
return (0);
return (rc);
}
}
return (0);
}
/*
* int
* _nsc_detach_fd (nsc_fd_t *fd, int flag)
* Detach file descriptor.
*
* The device lock must be held across calls to
* this function.
*
* Returns 0 if the detach succeeds without releasing
* the device lock, otherwise returns an error code.
*
* Description:
* Detach the specified file descriptor. If flag
* specifies read access then flush is called in
* preference to detach.
*/
int
int flag;
{
int rc;
return (0);
return (0);
return (rc);
if (fd->sf_reserve) {
return (EAGAIN);
}
}
}
/*
* static int
* _nsc_detach_owner (nsc_fd_t *fd, int flag)
* Detach owner of file descriptor.
*
* The device lock must be held across calls to
* this function.
*
* Returns 0 if the detach succeeds without releasing
* the device lock, otherwise returns an error code.
*
* Description:
* Detach the owner of the specified file descriptor.
* Wherever possible this is done without releasing
* the current device lock.
*/
static int
int flag;
{
int try;
int rc;
return (rc);
}
(flag | NSC_NOBLOCK))) {
return (0);
}
if (flag & NSC_NOBLOCK) {
if (try != 0)
return (EAGAIN);
}
if (try == 0)
}
/*
* static int
* _nsc_fd_fn (nsc_fd_t *fd, int (*fn)(), int a, int flag)
*
* The device lock must be held across calls to
* this function.
*
* Returns an error code if the operation failed,
* otherwise returns ERESTART to indicate that the
* device state has changed.
*
* Description:
* Sets up the active I/O module and calls the
* specified function.
*/
static int
{
int rc;
return (rc);
}
/*
* static int
* _nsc_attach_iodev (nsc_iodev_t *iodev, int flag)
* Attach I/O device.
*
* The device lock must be held across calls to
* this function.
*
* Returns 0 if the attach succeeds without releasing
* the device lock, otherwise returns an error code.
*
* Description:
* Attach the specified I/O device. Other I/O devices
* for the same device will be flushed or detached first
* as necessary.
*
* It is assumed that any valid cache descriptor for
* this device can be used to attach the I/O device.
*/
static int
int flag;
{
return (0);
return (rc);
}
"nsctl: _nsc_attach_iodev: %p no fds",
(void *)iodev);
}
}
return (0);
}
/*
* int
* _nsc_detach_iodev (nsc_iodev_t *iodev, nsc_fd_t *keep, int flag)
* Detach I/O device.
*
* The device lock must be held across calls to
* this function.
*
* Returns 0 if the detach succeeds without releasing
* the device lock, otherwise returns an error code.
*
* Description:
* Detach the specified I/O device except for file
* descriptor keep. If flag specifies read access then
* flush is called in preference to detach.
*
* It is assumed that any valid cache descriptor for
* this device can be used to detach the I/O device.
*/
int
{
return (0);
return (0);
continue;
return (rc);
}
}
if (keep)
return (0);
"nsctl: _nsc_detach_iodev: %p no fds", (void *)iodev);
}
}
/*
* static int
* _nsc_attach_dev (nsc_dev_t *dev, int flag)
* Attach device to node.
*
* The device lock must be held across calls to
* this function.
*
* Returns 0 if the attach succeeds without releasing
* the device lock, otherwise returns an error code.
*
* Description:
* Attach the device to the current node.
*/
static int
int flag;
{
return (EAGAIN);
}
return (0);
}
/*
* int
* _nsc_detach_dev (nsc_dev_t *dev, nsc_iodev_t *keep, int flag)
* Detach device.
*
* The device lock must be held across calls to
* this function.
*
* Returns 0 if the detach succeeds without releasing
* the device lock, otherwise returns an error code.
*
* Description:
* Detach the device except for I/O descriptor keep.
* If flag specifies read access then flush is called
* in preference to detach. If appropriate the device
* will be released for use by another node.
*
* All I/O devices are detached regardless of the
* current owner as a sanity check.
*/
int
{
int rc = 0;
return (EAGAIN);
}
continue;
continue;
break;
}
return (rc);
return (rc);
return (rc);
}
/*
* static int
* _nsc_call_dev (nsc_dev_t *dev, blindfn_t fn, blind_t arg,
* *int *ap, int *pp, int a, int flag, nsc_iodev_t *iodev)
*
* The device lock must be held across calls to this
* this function.
*
* Returns an error code if the operation failed,
* otherwise returns ERESTART to indicate that the
* device state has changed.
*
* The flags pointed to by ap are updated to reflect
* availability based upon argument a. The pending
* flag pointed to by pp is set whilst the operation
* is in progress.
*
* Description:
* Marks the device busy, temporarily releases the
* device lock and calls the specified function with
* the given argument.
*
* If a detach is being performed then clear _NSC_ATTACH
* first to prevent pinned data callbacks. If the detach
* fails then clear _NSC_PINNED and indicate that a flush
* is required by setting NSC_READ.
*/
static int
{
if (flag & NSC_NOBLOCK)
return (EAGAIN);
if (!a && v)
*pp = (a) ? a : _NSC_DETACH;
*pp = 0;
}
if (rc) {
if (!a && v)
a = (v & ~_NSC_PINNED) | NSC_READ;
else if (v & _NSC_ATTACH)
a = v;
else
a = 0;
}
*ap = a;
}
/*
* int
* _nsc_wait_dev (nsc_dev_t *dev, int flag)
* Wait for device state to change.
*
* Must be called with the device lock held.
* Returns EAGAIN if NSC_NOBLOCK or NSC_NOWAIT is set,
* or EINTR if the wait was interrupted, otherwise
* returns ERESTART to indicate that the device state
* has changed.
*
* Description:
* Waits for the device state to change before resuming.
*
* Remarks:
* If the reference count on the device has dropped to
* zero then cv_broadcast is called to wakeup _nsc_free_dev.
*/
int
int flag;
{
return (EAGAIN);
if (flag & NSC_PCATCH)
else
if (dev->nsc_refcnt <= 0)
}
/*
* void
* _nsc_wake_dev (nsc_dev_t *dev, int *valp)
* Decrement value and wakeup device.
*
* The device lock must be held across calls to
* this function.
*
* Description:
* Decrements the indicated value and if appropriate
* wakes up anybody waiting on the device.
*/
void
int *valp;
{
if (--(*valp))
return;
}