SCO OpenServer
scsi_usercmd(D3osdi)
scsi_usercmd, scsi_usercmd_build, scsi_usercmd_fill --
process user-level requests issued with the SCSIUSERCMD and SCSIUSERCMD2 ioctls
Synopsis
#include <sys/nbufdev.h>
#include <sys/scsicmd.h>
scsi_usercmd_build (req_p, cfg_p, scsicmd, devbuf)
REQ_IO *req_p;
DEVCFG *cfg_p;
struct scsicmd *scsicmd; /* supplied SCSI command */
struct ndevbuf *db; /* supplied devbuf */
scsi_usercmd_fill (req_p, cfg_p, scsicmd, devbuf)
REQ_IO *req_p;
DEVCFG *cfg_p;
struct scsicmd *scsicmd; /* supplied SCSI command */
struct ndevbuf *db; /* supplied devbuf */
Description
The
scsi_usercmd( )
functions are used in SCSI peripheral drivers
to process user-level requests issued with the
SCSIUSERCMD and SCSIUSERCMD2 ioctls.
Note that no sense data information can be returned
with these functions.
This makes this interface unsuitable
for writing a "user-level" driver
for a new SCSI device.
The interface should be used only
for occasional device-specific commands
for which no sense data is needed.
Arguments
req_p-
Pointer to a
scsi_io_req(D4osdi)
structure.
cfg_p-
Pointer to a
scsi_dev_cfg(D4osdi)
structure.
cfg_p-
Pointer to a scsicmd structure.
db-
Pointer to an ndevbuf structure.
Return values
scsi_usercmd_build( )
and
scsi_usercmd_fill( )
return 0 on success.
On failure, they return -1
and sets u.u_errno to one of the following:
EPERM-
Calling process is not superuser
(setuid root is required).
EINVAL-
Invalid opcode or data length.
EFAULT-
Invalid data pointer
or failure to transfer user data to CDB.
ENOMEM-
Could not allocate enough contiguous memory
for the CDB.
Usage
This functionality is coded in
the SCSI peripheral driver's
ioctl(D2osdi)
routine.
The typical calling sequence is:
-
Call
copyin(D3oddi)
to copy the SCSI command in from user space.
-
Call
scsi_usercmd_build( )
to create a REQ_IO structure
and allocate the required memory for the
scsi_cdb(D4osdi)
structure that is passed in with the
ioctl( )
call.
-
Call the
_entry(D2osdi)
entry point routine and pass the newly-created
REQ_IO structure to stage the command in the driver.
-
Issue the
sleep(D3oddi)
function to wait for the command to be processed.
-
Issue the
scsi_usercmd_fill( )
function to copy the requested data
from kernel buffers to user space.
-
Call
copyout(D3oddi)
to copy the updated scsi_cdb structure
back out to user space.
The
scsi_usercmd( )
is only a stub that is provided
for backward compatibility.
It should not be called.
Context and synchronization
User
context
Hardware applicability
All
Version applicability
scsi_usercmd-
osdi:
2, 3, 4, 5
scsi_usercmd_build and scsi_usercmd_fill-
osdi:
3, 4, 5
Differences between versions
The
scsi_usercmd( )
function was supported on earlier releases
of SCO systems.
A stub is provided for backward compatibility,
but drivers that run on SCO OpenServer
should be written to use the
scsi_usercmd_build( )
and
scsi_usercmd_fill( )
functions instead.
scsi_usercmd( )
is a stub and always sets
u.u_errno
to an appropriate value.
References
scsi_io_req(D4osdi),
scsi(HW) ,
``OSDI SCSI driver interface version for SCO OpenServer 5'' in HDK Technical Reference
Examples
The following example from a SCSI peripheral driver
for a hard disk illustrates how to use these functions
to code the SCSIUSERCMD case of the driver's
ioctl(D2osdi)
routine.
case SCSIUSERCMD: /* do a disk-related scsi cmd */
s = lockb5(&mydk_p->cilock);
while (!(req_p = mydk_getreqblk(unit)))
sleep(&mydk_needreq[unit], PRIBIO);
unlockb(&mydk_p->cilock, s);
req_p->io_intr = mydkintr;
req_p->jq = unit;
if (mydk_p->info.do_tagged)
req_p->hacmd = SCSI_TAG_SIMPLE;
else
req_p->hacmd = 0;
if ( copyin( addr, &scsicmd, sizeof(scsicmd) ) == -1 ) {
u.u_error = EFAULT;
mydk_freereq(req_p);
break;
}
if ( scsi_usercmd_build( req_p, cfg_p, &scsicmd, &scsi_db ) ){
mydk_freereq(req_p);
u.u_error = EFAULT;
break;
}
/*
* now submit the command
*/
if ((*cfg_p->adapter_entry)(req_p) != 0) {
mydk_freereq(req_p);
u.u_error = ENXIO;
break;
}
s = lockb5(&mydk_p->cilock);
while( req_p->internal ) {
sleep( req_p, PRIBIO );
}
unlockb( &mydk_p->cilock, s );
if ( req_p->host_sts || req_p->target_sts ) {
u.u_error = EIO;
}
/*
* copy any resulting data back to the user
*/
if ( scsi_usercmd_fill( req_p, cfg_p, &scsicmd, &scsi_db ) ) {
mydk_freereq(req_p);
u.u_error = EFAULT;
break;
}
if ( copyout( &scsicmd, addr, sizeof(scsicmd) ) == -1 ) {
u.u_error = EFAULT;
mydk_freereq(req_p);
break;
}
mydk_freereq(req_p);
break;
19 June 2005
© 2005 The SCO Group, Inc. All rights reserved.
OpenServer 5 HDK - June 2005