dmd.c revision cee0fb94c0d4227de0a00efc162fb2739844b641
/*
* 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.
*/
/* _init, _info, and _fini */
/* prop_op, and ddi_prop_op */
/* ddi_create_minor_node */
/* this driver */
/* this driver also used by cb_ops, */
/* ddi_get_instance, and ddi_prop_op */
/* this driver also used by cb_ops, */
/* ddi_create_minor_node, */
/* ddi_get_instance, and ddi_prop_op */
#include <sys/int_types.h>
#include <mms_dmd.h>
#include <dmd_impl.h>
typedef struct dmd_sym {
char *dmd_sym;
int dmd_code;
} dmd_sym_t;
static dmd_sym_t dmd_scsi_cmd_tab[] = {
"test unit ready", SCMD_TEST_UNIT_READY,
"request sense", SCMD_REQUEST_SENSE,
"read", SCMD_READ,
"write", SCMD_WRITE,
"inquiry", SCMD_INQUIRY,
"mode select", SCMD_MODE_SELECT,
"reserve", SCMD_RESERVE,
"release", SCMD_RELEASE,
"mode sense", SCMD_MODE_SENSE,
"rewind", SCMD_REWIND,
"read block limit", SCMD_READ_BLKLIM,
"write tapemark", SCMD_WRITE_FILE_MARK,
"space", SCMD_SPACE,
"erase", SCMD_ERASE,
"mode sense", SCMD_MODE_SENSE,
"load", SCMD_LOAD,
"persistent reserve in", SCMD_PRIN,
"persistent reserve out", SCMD_PROUT,
"locate", SCMD_LOCATE,
"read position", SCMD_READ_POSITION,
"report density", SCMD_REPORT_DENSITIES,
"log select", SCMD_LOG_SELECT_G1,
"log sense", SCMD_LOG_SENSE_G1,
NULL, 0,
};
static dmd_sym_t dmd_mtop_tab[] = {
"MTSEEK", MTSEEK,
"MTTELL", MTTELL,
"MTWEOF", MTWEOF,
"MTFSF", MTFSF,
"MTBSF", MTBSF,
"MTFSR", MTFSR,
"MTBSR", MTBSR,
"MTREW", MTREW,
"MTOFFL", MTOFFL,
"MTNOP", MTNOP,
"MTRETEN", MTRETEN,
"MTERASE", MTERASE,
"MTEOM", MTEOM,
"MTNBSF", MTNBSF,
"MTSRSZ", MTSRSZ,
"MTGRSZ", MTGRSZ,
"MTLOAD", MTLOAD,
NULL, 0, /* Must be last entry */
};
static dmd_sym_t dmd_ioctl_tab[] = {
"MTIOCTOP", MTIOCTOP,
"MTIOCGET", MTIOCGET,
"MTIOCGETDRIVETYPE", MTIOCGETDRIVETYPE,
"MTIOCPERSISTENT", MTIOCPERSISTENT,
"MTIOCPERSISTENTSTATUS", MTIOCPERSISTENTSTATUS,
"MTIOCLRERR", MTIOCLRERR,
"MTIOCGUARANTEEDORDER", MTIOCGUARANTEEDORDER,
"MTIOCRESERVE", MTIOCRESERVE,
"MTIOCRELEASE", MTIOCRELEASE,
"MTIOCFORCERESERVE", MTIOCFORCERESERVE,
"MTIOCGETERROR", MTIOCGETERROR,
"MTIOCSTATE", MTIOCSTATE,
"MTIOCREADIGNOREILI", MTIOCREADIGNOREILI,
"MTIOCREADIGNOREEOFS", MTIOCREADIGNOREEOFS,
"MTIOCSHORTFMK", MTIOCSHORTFMK,
"MTIOCGETPOS", MTIOCGETPOS,
"MTIOCRESTPOS", MTIOCRESTPOS,
"MTIOCLTOP", MTIOCLTOP,
NULL, 0,
};
/*
* dmd.conf
* name="dmd" parent="pseudo" ;
*/
static void *dmd_soft_statep;
static dmd_stat_t *dmd_stat_p;
static int dmd_next_ord = DMD_FIRST_DEV_ORDINAL;
#ifdef MMSDEBUG
static int dmd_debug = 1;
#else
static int dmd_debug = 0;
#endif
/*
* State variables
*/
/* NOT_READY. Set to */
/* READY after the */
/* watcher device is */
/* opened */
static kmutex_t dmd_state_mutex;
static int dmd_busy = 0;
static kmutex_t dmd_busy_mutex;
void **resultp);
int *rvalp);
int mode);
int mode);
/* cb_ops structure */
static struct cb_ops dmd_cb_ops = {
nodev, /* no strategy - nodev returns ENXIO */
nodev, /* no print */
nodev, /* no dump */
dmd_ioctl, /* no ioctl */
nodev, /* no devmap */
nodev, /* no mmap */
nodev, /* no segmap */
nochpoll, /* returns ENXIO for non-pollable devices */
NULL, /* streamtab struct; if not NULL, all above */
/* fields are ignored */
CB_REV, /* cb_ops revision number */
nodev, /* no aread */
nodev /* no awrite */
};
/* dev_ops structure */
static struct dev_ops dmd_dev_ops = {
0, /* reference count */
nulldev, /* no identify - nulldev returns 0 */
nulldev, /* no probe */
nodev, /* no reset - nodev returns ENXIO */
nodev /* no power */
};
/* modldrv structure */
&mod_driverops, /* Type of module. This is a driver. */
"MMS Drive Manager Driver (dmd)", /* Name of the module. */
};
/* modlinkage structure */
static struct modlinkage ml = {
&md,
};
/* dev_info structure */
dmd_inst_to_minor(int inst)
{
/*
* wcr and stat device
*/
if (inst <= 1) {
return (inst);
}
/*
* Drive manager device
*/
if ((inst & 1) == 0) {
}
/*
* Target device
*/
}
int
{
/*
* Watcher device
*/
if (minor == 0) {
return (0);
}
/*
* Stat device
*/
if (minor == 1) {
return (1);
}
/*
* Drive manager device
*/
if (minor <= 0xff) {
}
/*
* Target device
*/
}
static char *
{
}
}
return ("UNKNOWN");
}
static int
{
char scsi_cmd;
#ifdef _MULTI_DATAMODEL
/*
* For use when a 32 bit app makes a call into a
* 64 bit ioctl
*/
struct uscsi_cmd32 us32;
#endif /* _MULTI_DATAMODEL */
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32:
sizeof (struct uscsi_cmd32), flag)) {
return (EFAULT);
}
break;
case DDI_MODEL_NONE:
return (EFAULT);
}
break;
}
#else /* ! _MULTI_DATAMODEL */
return (EFAULT);
}
#endif /* _MULTI_DATAMODEL */
/*
* Copy the command code from scsi_cmd
*/
return (EFAULT);
}
return (0);
}
static int
{
#ifdef _MULTI_DATAMODEL
/*
* For use when a 32 bit app makes a call into a
* 64 bit ioctl
*/
struct mtop32 mtop_32_for_64;
#endif /* _MULTI_DATAMODEL */
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32:
return (EFAULT);
}
break;
case DDI_MODEL_NONE:
return (EFAULT);
}
break;
}
#else /* ! _MULTI_DATAMODEL */
return (EFAULT);
}
#endif /* _MULTI_DATAMODEL */
return (0);
}
static int
{
#ifdef _MULTI_DATAMODEL
/*
* For use when a 32 bit app makes a call into a
* 64 bit ioctl
*/
struct mtlop mtlop_32_for_64;
#endif /* _MULTI_DATAMODEL */
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32:
return (EFAULT);
}
break;
case DDI_MODEL_NONE:
flag)) {
return (EFAULT);
}
break;
}
#else /* ! _MULTI_DATAMODEL */
return (EFAULT);
}
#endif /* _MULTI_DATAMODEL */
return (0);
}
static int
{
#ifdef _MULTI_DATAMODEL
/*
* For use when a 32 bit app makes a call into a
* 64 bit ioctl
*/
struct mtop32 mtop_32_for_64;
#endif /* _MULTI_DATAMODEL */
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32:
return (EFAULT);
}
break;
case DDI_MODEL_NONE:
flag)) {
return (EFAULT);
}
break;
}
#else /* ! _MULTI_DATAMODEL */
return (EFAULT);
}
#endif /* _MULTI_DATAMODEL */
return (0);
}
static int
{
return (EFAULT);
}
return (0);
}
/* Loadable module configuration entry points */
int
_init(void)
{
int rc = 0;
sizeof (dmd_soft_state_t), 0)) {
return (rc);
}
}
dmd_busy = 0;
return (rc);
}
int
{
int rc;
}
return (rc);
}
int
_fini(void)
{
int rc = 0;
return (rc);
}
return (rc);
}
/* Device autoconfiguration entry points */
static int
{
int inst;
int rc = 0;
int i;
/*
* Only work on instance 0. Ignore all other instances.
*/
if (inst != 0) {
return (DDI_FAILURE);
}
switch (cmd) {
case DDI_ATTACH:
/*
* Create the watcher device
*/
if (rc) {
return (DDI_FAILURE);
}
/*
* Create the stat device - instance 1
*/
if (rc) {
return (DDI_FAILURE);
}
for (i = 0; i < DMD_MAX_STAT; i++) {
}
return (DDI_SUCCESS);
default:
inst));
return (DDI_FAILURE);
}
}
static int
{
int inst;
switch (cmd) {
case DDI_DETACH:
"can't get state struct\n");
return (DDI_FAILURE);
}
if (wcr->wcr_proc_ref) {
}
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
}
static int
/* LINTED: dip not used */
void **resultp)
{
switch (cmd) {
case DDI_INFO_DEVT2DEVINFO:
} else {
}
return (DDI_SUCCESS);
} else {
return (DDI_FAILURE);
}
case DDI_INFO_DEVT2INSTANCE:
return (DDI_SUCCESS);
default:
return (DDI_FAILURE);
}
}
static int
{
}
/* User context entry points */
static int
{
int rc = 0;
return (ENXIO);
}
if (dmd_state != DMD_NOT_READY) {
return (ENXIO);
}
if (rc == 0) {
dmd_busy = 0;
}
} else {
/*
* Do not allow new opens if the driver is not ready.
*/
"driver not ready",
return (ENXIO);
}
DMD_BUSY();
} else { /* an app open */
}
DMD_UNBUSY();
}
return (rc);
}
static int
{
/*
* Process wcr open
*/
"[%d:%d] dmd_open_wcr: watcher already opened "
return (EBUSY);
}
return (0);
}
static int
{
int i;
/* Add openpid to pid table */
for (i = 0; i < DMD_MAX_STAT; i++) {
dmd_stat_opens[i] = pid;
break;
}
}
if (i == DMD_MAX_STAT) { /* too many opened */
return (EBUSY);
}
return (0);
}
static int
{
int rc = 0;
/*
* Check to see if there is a watcher.
* If no watcher, error
*/
if (dmd_wcr_p->wcr_cur_pid == 0) {
/* No watcher */
return (ENXIO);
}
goto done;
}
if (drm->drm_shr_pid) {
/*
* Only one process can open a drive manager
*/
"[%d:%d] dmd_open_drm: dm %d already opened by process %d",
goto done;
}
if (drm->drm_shr_tdv_pid == 0) {
/* tdv not opened by app */
}
"waiting for tdv close from pid %d",
}
done:
return (rc);
}
static int
{
int rc = 0;
"Opening target device, dev = %lx\n",
"Mismatched dev: tdv_minor %x, "
return (ENXIO);
}
/*
* Must have been bound to to a target device to open
*/
return (ENXIO);
}
if (drm->drm_shr_tdv_pid != 0) {
"target dev already opened "
return (EBUSY);
}
/*
* Init file I/O counts
*/
tdv->tdv_rdbytes = 0;
tdv->tdv_wrbytes = 0;
tdv->tdv_blkcnt = 0;
return (ENXIO);
}
/*
* Signal the drive manager
*/
/*
* Signal failed, assume open success and
* tell drive manager to close
*/
DMD_INC_OPENS(); /* increase open count */
"[%d:%d] dmd_open_tdv: signal failed, signal for "
return (rc);
}
drm->drm_shr_tdv_pid = 0;
if (rc == 0) {
/* Open success */
DMD_INC_OPENS(); /* increase open count */
}
return (rc);
}
static int
/* LINTED: need all arguments */
{
int rc = 0;
"minor = %x\n",
return (ENXIO);
}
if (rc == 0) {
}
} else {
DMD_BUSY();
} else {
}
DMD_UNBUSY();
}
return (0);
}
static int
{
int i;
for (i = DMD_FIRST_DEV_ORDINAL; i < dmd_next_ord; i++) {
continue;
}
if (drm->drm_shr_pid) {
/*
* Signal drive manager
*/
"sending SIGTERM to dm process %d\n",
SIGTERM);
}
}
}
return (0);
}
static int
{
int i;
for (i = 0; i < DMD_MAX_STAT; i++) {
if (dmd_stat_opens[i] == pid) {
break;
}
}
return (0);
}
static int
{
"Closing DM device, minor = %d, tdv_pid = %d\n",
/*
* Resume any outstanding request sent to DM
*/
drm->drm_shr_flags &=
}
if (drm->drm_shr_proc_ref) {
}
/*
* Close connection to target driver
*/
if (drm->drm_shr_tdv_pid != 0) {
"tdv still opened by %d\n",
}
return (0);
}
static void
{
int rval;
int rc = 0;
static uchar_t preempt_cmd[] =
{ 0x5f, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 24, 0x00 };
{ 0x5f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 24, 0x00 };
/*
* Register the key
*/
/*
* register PRSV key
*/
/* LINTED: Null effect */
if (rc != 0) {
"PRSV register returns %d",
}
/*
* Preempt to remove key
*/
/* LINTED: Null effect */
if (rc != 0) {
"PRSV preempt returns %d",
}
/*
*/
if (rc != 0) {
"MTIOCRELEASE error: %d",
}
}
static int
{
int xmutex = 0; /* don't do mutex_exit */
"Closing target device, minor = %x\n",
/*
* Use tryenter because this may be called dmd_open_tdv if the
* open request failed.
*/
/* got the mutex */
}
/*
* If no handle to target driver, then we have no associated DM
*/
/*
* Tell current DM to get ready
*/
if (drm->drm_shr_pid != 0) {
"Can't signal DM %d",
}
}
} else {
(void) dmd_signal_drm(drm);
}
drm->drm_shr_tdv_pid = 0;
if (xmutex) {
}
return (0);
}
static int
{
int rc = 0;
/*
*/
"read not supported for watcher and stat devices",
return (ENOTSUP);
}
"Can't get state, minor %d",
return (ENXIO);
}
DMD_BUSY();
} else {
/*
* tdv read
*/
}
DMD_UNBUSY();
return (rc);
}
static int
{
int rc = 0;
/*
* Only allow the process which opened the device
*/
DMD_UNBUSY();
return (EACCES);
}
if (rc != 0) {
}
return (rc);
}
static int
{
int rc = 0;
int reqtype = 0;
/* waiting for me to close */
goto done;
}
goto done;
}
/*
* Check for MMS mode
*/
/*
* Not in MMS mode, no processing by drive manager
*/
/* Fatal error, no movement cmds */
goto done;
} else {
/*
* For fixed mode, I/O size must be multiple
* of max blksize.
* For variable mode, I/O size must be <= max blksize.
*/
"[%d:%d] dmd_read_tdv: "
"read size (%lld) "
"not multiple of "
"max size (%d)",
(long long)iovlen,
goto done;
}
} else {
"read size (%lld) "
"greater than max size (%d)",
goto done;
}
}
/*
* In MMS mode, need drive manager processing
*/
/* Notify read only works once */
sizeof (drm_request_t));
if (rc == 0) {
}
}
if (rc == 0) {
if (resid > 0) {
"Read returns: "
"len = %lld, resid = %lld, rc = %d\n",
}
/*
*/
tdv->tdv_blkcnt +=
/* Read a block */
tdv->tdv_blkcnt++;
}
/*
* Signal drive manager if in MMS mode
*/
if (rc == 0 &&
/*
* If ldi_read returns 0 and did not
* read any bytes, then we must have
* read a tapemark.
*/
} else if (rc != 0) {
}
if (reqtype != 0) {
/* Notify DM */
sizeof (drm_request_t));
/* Read new status */
if (rc == 0) {
}
}
}
}
done:
if (rc != 0) {
}
return (rc);
}
static int
{
int rc = 0;
return (ENOTSUP);
}
return (ENXIO);
}
DMD_BUSY();
} else {
}
DMD_UNBUSY();
return (rc);
}
static int
{
int rc = 0;
/*
* Only allow the process which opened the device
*/
return (EACCES);
}
if (rc != 0) {
}
return (rc);
}
static int
{
int rc = 0;
int reqtype;
/* waiting for me to close */
goto done;
}
goto done;
}
/*
* Check for MMS mode
*/
/*
* Not in MMS mode, no processing by drive manager
*/
goto done;
} else {
/*
* For fixed mode, I/O size must be multiple
* of max blksize.
* For variable mode, I/O size must be <= max blksize.
*/
"[%d:%d] dmd_write_tdv: "
"write size (%lld) "
"not multiple of "
(long long)iovlen,
goto done;
}
} else {
"write size (%lld) "
(long long)iovlen,
goto done;
}
}
/*
* MMS mode, need drive manager processing
*/
/* Notify write only works once */
sizeof (drm_request_t));
/* Read new status */
if (rc == 0) {
}
}
if (rc == 0) {
"Write returns: "
/*
*/
tdv->tdv_blkcnt +=
} else {
tdv->tdv_blkcnt++;
}
reqtype = 0;
if (rc == 0 &&
/*
* ldi_write returns 0 and did not write
* any bytes.
*/
} else if (rc != 0) {
"[%d:%d] dmd_write_tdv: "
}
if (reqtype != 0) {
/* Notify DM */
sizeof (drm_request_t));
/* Read new status */
if (rc == 0) {
}
}
}
}
done:
if (rc != 0) {
}
return (rc);
}
static int
{
int rc = 0;
return (ENXIO);
}
} else {
DMD_BUSY();
} else {
}
DMD_UNBUSY();
}
return (rc);
}
static int
{
int newinst; /* for the new device */
char devname[20];
int rc = 0;
/*
* Only allow the process which opened the device
*/
return (EACCES);
}
switch (cmd) {
case WCR_ADD_DEV:
/*
* Configure a drive manager and its target device
* arg - ordinal of device.
*/
/*
* Validate the ordinal
*/
"WCR_ADD_DEV, "
goto done;
} else if (ord < dmd_next_ord) {
"WCR_ADD_DEV, "
"Can't get state structure, inst = %d",
goto done;
}
/*
* Ensure that the device is not bound
*/
goto done;
}
rc = 0;
goto done;
}
/*
* Dm and target devices have their own soft state.
*/
goto done;
}
/*
* Create the target device soft state
*/
goto done;
}
dmd_next_ord++;
break;
default:
goto done;
}
done:
if (rc != 0) {
}
return (rc);
}
static int
dev_info_t **rdip)
{
} else {
}
return (ENOMEM);
}
return (ENXIO);
}
} else {
}
return (ENXIO);
}
}
/*
* If not target device, create the device
*/
DDI_PSEUDO, 0) != DDI_SUCCESS) {
"Can't create minor node %d",
return (ENXIO);
}
}
return (0);
}
static int
{
int rc = 0;
int num;
switch (cmd) {
case DMD_STAT_NDEV:
"[%d:%d] dmd_ioctl_stat: ioctl DMD_STAT_NDEV\n",
/*
* Return number of devices. arg must be (uint32_t *)
*/
mode)) {
goto done;
}
break;
case DMD_STAT_INFO:
"ioctl DMD_STAT_INFO\n",
goto done;
}
break;
case DMD_STAT_CLEAR:
"ioctl DMD_STAT_CLEAR\n",
break;
}
done:
if (rc != 0) {
}
return (rc);
}
static int
{
char *cp;
int num;
return (EFAULT);
}
}
return (EFAULT);
}
return (ENXIO);
}
} else {
}
mode)) {
return (EFAULT);
}
}
return (0);
}
static void
{
}
}
static void
{
}
}
}
}
static void
{
}
}
static int
{
int rc = 0;
char tmp[10];
int scsicmd;
char *cp;
/*
* Save ioctl mode for later use
*/
/*
* Only allow the process which opened the device
*/
goto done;
}
switch (cmd) {
case DRM_BIND_DEV :
/*
* Bind a real dev to target dev
*/
"DRM_BIND_DEV ioctl\n",
/*
* Error if waiting for tdv to close
*/
"[%d:%d] dmd_ioctl_drm: waiting for tdv close",
goto done;
}
/*
* Proceed if target dev is not busy
*/
if (drm->drm_shr_lhdl) {
/* already bound */
goto done;
}
"[%d:%d] dmd_ioctl_drm: copyin error",
goto done;
}
break;
case DRM_REBIND_DEV :
/*
* Rebind a target dev
*/
"[%d:%d] dmd_ioctl_drm: DRM_REBIND_DEV ioctl\n",
/*
* Error if waiting for tdv to close
*/
"[%d:%d] dmd_ioctl_drm: waiting for pid %d "
"to close",
goto done;
}
/*
* Proceed if target dev is bound
*/
/* Not bound */
"[%d:%d] dmd_ioctl_drm: "
"no handle to target device",
goto done;
}
"copyin error",
goto done;
}
break;
case DRM_REQUEST :
goto done;
}
sizeof (drm_request_t), mode)) {
"copyout error",
goto done;
}
break;
case DRM_RESUME :
sizeof (drm_reply_t), 0)) {
goto done;
}
}
break;
case DRM_MMS_MODE :
if (drm->drm_shr_tdv_pid != 0) {
/* Can't set MMS mode after file is opened by user */
goto done;
}
if ((int)arg > 0) {
} else {
}
break;
case DRM_BLKSIZE :
"DRM_BLKSIZE ioctl\n",
sizeof (drm_blksize_t), 0)) {
goto done;
}
} else {
}
"max blksize = %lld\n",
break;
case DRM_TARG_MINOR :
"DRM_BLKSIZE ioctl\n",
"target minor = %x\n",
break;
case DRM_DM_READY :
"DRM_DM_READY ioctl: %s\n",
if (arg != 0) {
} else {
}
break;
case DRM_PROBE_DEV :
"DRM_PROBE_DEV ioctl\n",
sizeof (drm_probe_dev_t), 0)) {
goto done;
}
break;
case USCSICMD :
return (rc);
}
}
if (rc != 0) {
}
break;
case DRM_PRSV_KEY :
"DRM_PRSV_KEY ioctl\n",
goto done;
}
break;
case DRM_DISALLOWED_CMDS :
"DRM_DISALLOWED_CMDS "
mode);
break;
case DRM_DISALLOWED_IOCTLS :
"DRM_DISALLOWED_IOCTLS "
mode);
break;
case DRM_TDV_PID :
goto done;
}
break;
default:
goto done;
}
}
goto done;
}
}
} else {
"UNKNOWN 0x%2x", cmd);
}
}
break;
}
done:
if (rc != 0) {
}
return (rc);
}
static int
{
int rc = 0;
char tmp[10];
char *cp;
goto done;
}
switch (cmd) {
/*
* Check for supported ioctl for both MMS and RAW modes
*/
case MMS_BLK_LIMIT :
break;
case MMS_GET_POS :
break;
case MMS_LOCATE :
break;
case MMS_GET_CAPACITY :
break;
case MMS_UPDATE_CAPACITY :
break;
case MMS_GET_DENSITY :
break;
case MMS_SET_DENSITY :
break;
case USCSICMD :
/*
* Only some SCSI commands allowed by the DM are supported.
*/
break;
default :
goto done;
}
}
goto done;
}
}
} else {
"0x%2x", cmd);
}
}
/*
* Only forward allowed ioctl to target driver
*/
"ioctl %s not allowed "
goto done;
}
/*
* Not in MMS mode, pass to target driver
*/
mode, /* drm->drm_ioctl_mode, */
rvalp);
"ldi_ioctl %s "
break;
} else {
/*
* In MMS mode, notify drive manager
*/
switch (cmd) {
case MTIOCTOP :
break;
case MTIOCLTOP :
break;
case MTIOCGET :
break;
case MTIOCGETPOS :
break;
case MTIOCRESTPOS :
break;
case MTIOCLRERR :
break;
default:
mode, /* drm->drm_ioctl_mode, */
rvalp);
"ldi_ioctl %s returns %d\n",
break;
}
}
}
done:
if (rc != 0) {
}
return (rc);
}
static int
{
return (EFAULT);
}
return (0);
}
static int
{
int scsi_cmd;
int rc = 0;
char *cp;
char tmp[10];
return (rc);
}
}
/*
* Only cmds that are allowed are forwarded to ST
*/
mode, /* drm->drm_ioctl_mode, */
rvalp);
} else {
/* Command not allowed */
}
return (rc);
}
static int
{
int i;
/* Unset ino */
drm->drm_probe_dev = 0;
} else {
/*
* Set ino - make sure no other DM has set the same ino.
* If another DM has set the same ino, then return EBUSY.
*/
for (i = DMD_FIRST_DEV_ORDINAL; i < dmd_next_ord; i++) {
continue;
}
continue;
}
if (dm->drm_shr_pid) {
/* Only check opened DM's */
return (EBUSY);
}
}
}
/*
* No other DM has set the same ino
*/
}
return (0);
}
static int
{
int rc = 0;
if (rc == 0) {
}
return (rc);
}
static int
{
int rc = 0;
if (rc == 0) {
}
return (rc);
}
static int
{
int rc = 0;
#ifdef _MULTI_DATAMODEL
/*
* For use when a 32 bit app makes a call into a
* 64 bit ioctl
*/
struct mtget32 mtg_local32;
#endif /* _MULTI_DATAMODEL */
struct mtget mtget_local;
if (rc == 0) {
}
if (rc != 0) {
return (rc);
}
}
#ifdef _MULTI_DATAMODEL
case DDI_MODEL_ILP32:
/*
* Convert 64 bit back to 32 bit before doing
* copyout. This is what the ILP32 app expects.
*/
}
}
break;
case DDI_MODEL_NONE:
}
break;
}
#else /* ! _MULTI_DATAMODE */
}
#endif /* _MULTI_DATAMODE */
return (rc);
}
static int
{
int rc = 0;
if (rc == 0) {
}
if (rc != 0) {
return (rc);
}
}
return (rc);
}
static int
{
int rc = 0;
}
if (rc == 0) {
}
if (rc != 0) {
return (rc);
}
return (rc);
}
static int
{
int rc = 0;
if (rc == 0) {
}
if (rc != 0) {
return (rc);
}
}
return (rc);
}
static int
{
int rc = 0;
return (EFAULT);
}
if (rc == 0) {
}
return (rc);
}
static int
{
int rc = 0;
if (rc == 0) {
}
if (rc != 0) {
return (rc);
}
}
return (rc);
}
static int
{
int rc = 0;
if (rc == 0) {
}
return (rc);
}
static int
int mode)
{
int rc = 0;
if (rc == 0) {
sizeof (mms_density_t), mode)) {
}
}
return (rc);
}
static int
{
int rc = 0;
return (EFAULT);
}
if (rc == 0) {
}
return (rc);
}
static int
{
int rc = 0;
if (rc == 0) {
}
if (rc != 0) {
return (rc);
}
}
return (rc);
}
static int
{
int rc = 0;
if (rc == 0) {
}
return (rc);
}
/*
* Some utility functions
*/
static int
{
/*
* Do layer open of the target device
*/
int rc = 0;
if (rc) {
"can't get ldi ident, "
goto out;
}
drm->drm_shr_li);
if (rc) {
"can't ldi open, "
goto out;
}
} else {
}
out:
return (rc);
}
static int
{
int rc = 0;
"ldi close error: "
"rc = %d: will continue to release ldi",
}
}
return (rc);
}
static int
{
int minor;
int rc = 0;
if (drm->drm_targ_dev != 0) {
return (EBUSY);
}
if (rc) {
drm->drm_targ_dev = 0;
return (rc);
}
/*
* Target dev is ready
*/
return (0);
}
/*
* Signal drive manager and wait for resume
*/
static int
{
int rc = 0;
/*
* Must hold drm->drm_shr_mutex on entry
*/
if (drm->drm_shr_pid == 0) {
return (ENXIO);
}
/* Only one outstanding request allowed */
return (EBUSY);
}
}
}
}
"Can't signal drive manager %d",
drm->drm_shr_flags &=
return (ENXIO);
}
/*
* Wait for DM to get request
*/
cur_ticks = ddi_get_lbolt();
/* Seconds to wait for DM */
if (rc == -1) {
/* timedout */
"Timedout waiting for DM "
drm->drm_shr_flags &=
return (ETIMEDOUT);
}
}
/*
* Wait for resume
*/
"Waiting for drive manager to resume\n",
}
/* Request resumed */
}
}
}
}
tdv->tdv_rdbytes = 0;
tdv->tdv_wrbytes = 0;
tdv->tdv_blkcnt = 0;
return (0);
}