DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
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:

  1. Call copyin(D3oddi) to copy the SCSI command in from user space.

  2. 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.

  3. Call the _entry(D2osdi) entry point routine and pass the newly-created REQ_IO structure to stage the command in the driver.

  4. Issue the sleep(D3oddi) function to wait for the command to be processed.

  5. Issue the scsi_usercmd_fill( ) function to copy the requested data from kernel buffers to user space.

  6. 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