Solaris 8 uscsi does not work with /dev/sg device (SCSI generic)

Solaris 8 uscsi does not work with /dev/sg device (SCSI generic)

Post by Phillip » Wed, 06 Nov 2002 12:56:43



Hi,

With the attached program I'm trying to send a USCSI command to tape
library robot arm. I'm sending the USCSI command - "identify
yourself". It works fine with a disk device but not with an sg device:

# ./probeforsgen /dev/rdsk/c0t0d0s2
Disk:   FUJITSU  MAB3091S SUN9.0G 2107 9908K52616
# ./probeforsgen /dev/sg/c4t6l0
ioctl error on /dev/sg/c4t6l0
ioctl: Inappropriate ioctl for device
# ls -l /dev/sg/c4t6l0
lrwxrwxrwx   1 root     other         43 Mar  9  2001 /dev/sg/c4t6l0

Would you know what's gone wrong? I seen various newsgroup
conversation indicating that this should work OK. Thanks for any help.

The program is as follows:
#include <stdio.h>
#include <string.h>

#include <sys/param.h>
#include <values.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/scsi/generic/mode.h>
#include <sys/scsi/generic/commands.h>
#include <sys/scsi/generic/status.h>
#include <sys/scsi/impl/types.h>
#include <sys/scsi/impl/uscsi.h>
#include <sys/systeminfo.h>
#include <sys/scsi/impl/types.h>
#include <sys/scsi/impl/uscsi.h>

#define bzero(b,l) memset(b,0,l)
extern int errno;

/*
 * Names of SCSI commands
 */
#define SCSI_COMMAND_COUNT 10
static struct scsi_command_name {
        u_char command;
        char *name;

Quote:} scsi_command_names[] = {

        SCMD_FORMAT,            "format",
        SCMD_READ,              "read",
        SCMD_WRITE,             "write",
        SCMD_READ|SCMD_GROUP1,  "read",
        SCMD_WRITE|SCMD_GROUP1, "write",
        SCMD_INQUIRY,           "inquiry",
        SCMD_MODE_SELECT,       "mode select",
        SCMD_MODE_SENSE,        "mode sense",
        SCMD_REASSIGN_BLOCK,    "reassign block",
        SCMD_READ_DEFECT_LIST,  "read defect list"
Quote:};

#define DUMMY_SCSI_STATUS          0xff
#define MIN_REQUEST_SENSE_LEN      18
#define DISK_STAT_NOTREADY         0x02

/*
* Look up the command name from command code
*/
char *scsi_get_command_name(cmd)
u_int cmd;
{
  int i;
  int found=0;

  for (i==0;i<SCSI_COMMAND_COUNT;++i) {
    if (scsi_command_names[i].command==cmd) {found=1;break;};
  };
  if (found) {return(scsi_command_names[i].name);}
  else       {return("unknown");};

Quote:}

char *scsi_dtype(dtype)
u_int dtype;
{
        switch(dtype){
        case DTYPE_DIRECT:      return("Disk");
        case DTYPE_SEQUENTIAL:  return("Tape");
        case DTYPE_PRINTER:     return("Printer");
        case DTYPE_PROCESSOR:   return("Processor");
        case DTYPE_WORM:        return("WORM Drive");
        case DTYPE_RODIRECT:    return("CD-ROM");
        case DTYPE_SCANNER:     return("Scanner");
        case DTYPE_OPTICAL:     return("Optical Disk");
        case DTYPE_CHANGER:     return("Changer");
        case DTYPE_COMM:        return("Comm");
        default:                return("Unknown");
        }

Quote:}

main(argc, argv)
int argc;
char *argv[];
{
#define SCSIBUFLEN 256
#define SENSEBUFLEN 256

char diskname[257];
int disk;

struct uscsi_cmd cmd;
union scsi_cdb cdb;
struct scsi_inquiry *inq;
char iobuff[SCSIBUFLEN];
char sensebuff[SENSEBUFLEN];
struct scsi_extended_sense *ses;
int seslen;
int status;

 if (argc!=2) {
   printf("Usage: %s <device>\n",argv[0]);
   exit(1);
 };
 strcpy(diskname,argv[1]);
 if ((disk=open(diskname,O_RDONLY))==-1) {
   perror("Disk drive cannot be openned");
   exit(1);
  }

  inq = (struct scsi_inquiry *)iobuff;

  /* set up SCSI inquiry command */
  bzero(&cdb, sizeof(cdb));
  bzero(inq, sizeof(inq));
  cdb.scc_cmd = SCMD_INQUIRY;
  FORMG0COUNT(&cdb, (u_char)inq);
  cmd.uscsi_cdb=(caddr_t)&cdb;
  cmd.uscsi_cdblen=CDB_GROUP0; /* SCSI Group 0 cmd */
  cmd.uscsi_bufaddr=(caddr_t)inq;
  cmd.uscsi_buflen=SCSIBUFLEN;
  cmd.uscsi_flags=USCSI_DIAGNOSE|USCSI_SILENT|USCSI_ISOLATE|USCSI_READ;
  cmd.uscsi_timeout=30;

  status=ioctl(disk, USCSICMD, &cmd);

  /* OK */
  if ((status==0) && (cmd.uscsi_status==0)) {
    printf("%s:\t", scsi_dtype(inq->inq_dtype));
    printf("%-8.8s %-16.16s %-4.4s %12.12s\n", inq->inq_vid,
            inq->inq_pid, inq->inq_revision, inq->inq_serial);
    close(disk);
    exit(0);
    exit(0);
  };
  /* Disk not available - busy formatting*/
  if (status==-1 && errno==EAGAIN) {
    printf("%s is not available - possibly formatting\n",diskname);
    close(disk);
    exit(1);
  };
  if ((cmd.uscsi_status & STATUS_MASK)==STATUS_RESERVATION_CONFLICT) {
    printf("%s is not available - possibly formatting\n",diskname);
    close(disk);
    exit(1);
  };

  /* Disk physically removed or not responding */
  if ((status==-1) && (cmd.uscsi_status==0) && (errno == EIO)) {
    printf("%s is not responding\n",diskname);
    close(disk);
    exit(1);
  };
 printf("ioctl error on %s\n",diskname);
 perror("ioctl");
 close(disk);

Quote:}

 
 
 

Solaris 8 uscsi does not work with /dev/sg device (SCSI generic)

Post by Quan » Thu, 07 Nov 2002 07:11:55


p...@qantas.com.au (Phillip Wu) wrote in message <news:943cec75.0211041956.5825e567@posting.google.com>...
> Hi,

> With the attached program I'm trying to send a USCSI command to tape
> library robot arm. I'm sending the USCSI command - "identify
> yourself". It works fine with a disk device but not with an sg device:

Phillip,

Try this little test that I wrote a while back, which seems to work for me.
I use something like:

a.out /dev/rst11                      for the tape device
a.out /dev/scsi/changer/c1t4d1        for the changer

--
Quang

#include <sys/scsi/scsi.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>

/*-----------------------------------------------------------------------------
 * Define the types
 *---------------------------------------------------------------------------*/
typedef unsigned long           Dword;
typedef unsigned long           Error;
typedef unsigned char           Byte;
typedef void                    Void;

/*-----------------------------------------------------------------------------
 * Define the command scopes
 *---------------------------------------------------------------------------*/
#define Local                   static Error
#define Private                 Error
#define Public                  Error

/*-----------------------------------------------------------------------------
 *
 * @NAME
 *      LclHexDump
 *
 * @SCOPE
 *      Local
 *
 * @DESCRIPTION
 *      This function will do the hex dump.
 *
 * @PARAMETERS
 *      @IN    
 *      @IN    
 *
 *---------------------------------------------------------------------------*/

Local LclHexDump(Byte *data, Dword len)
        {
        int i, j;
        char c;

        /*---------------------------------------------------------------------
         * Dump the bytes
         *-------------------------------------------------------------------*/
        for (i = 0; i < len; i += 8)
                {
                /*-------------------------------------------------------------
                 * Format the address
                 *-----------------------------------------------------------*/
                printf("0x%04x: ", i);

                /*-------------------------------------------------------------
                 * Format the hex data
                 *-----------------------------------------------------------*/
                for (j = 0; j < 8 && i+j < len; j++)
                        {
                        printf("%02x ", (Dword) data[i+j] & 0x0ff);
                        }

                /*-------------------------------------------------------------
                 * Give an extra space after the hex data
                 *-----------------------------------------------------------*/
                printf("  ");

                /*-------------------------------------------------------------
                 * Format the ascii data
                 *-----------------------------------------------------------*/
                for (j = 0; j < 8 && i+j < len; j++)
                        {
                        c = data[i+j];
                        if (isprint(c))
                                printf("%c ", c);
                        else
                                printf(". ");
                        }

                /*-------------------------------------------------------------
                 * Next line
                 *-----------------------------------------------------------*/
                printf("\n");
                }
        return 0;
        }

/*-----------------------------------------------------------------------------
 *
 * @NAME
 *      main
 *
 * @SCOPE
 *      int
 *
 * @DESCRIPTION
 *      This is the main function.
 *
 * @PARAMETERS
 *      @IN    
 *      @IN    
 *
 *---------------------------------------------------------------------------*/

int main(int argc, char **argv)
        {
        int fd;
        char *device;
        struct uscsi_cmd cmd;
        Byte ioBuffer[256];
        Byte senseData[256];
        Byte cdb[16];
        Byte *data;
        Dword total;
        Dword x;
        Error ccode;

        /*---------------------------------------------------------------------
         * Check for arguments
         *-------------------------------------------------------------------*/
        if (argc < 2)
                device = "/dev/rst11";
        else
                device = argv[1];

        /*---------------------------------------------------------------------
         * Open the scsi device
         *-------------------------------------------------------------------*/
        if ((fd = open(device, O_RDWR | O_NDELAY)) < 0)
                {
                perror("open");
                return 1;
                }

        /*---------------------------------------------------------------------
         * Clear the structures
         *-------------------------------------------------------------------*/
        memset(ioBuffer, 0, sizeof(ioBuffer));
        memset(senseData, 0, sizeof(senseData));

        /*---------------------------------------------------------------------
         * Set up the inquiry command
         *-------------------------------------------------------------------*/
        memset(cdb, 0, sizeof(cdb));
        cdb[0] = 0x12;
        cdb[4] = 100;

        /*---------------------------------------------------------------------
         * Set up the uscsi command
         *-------------------------------------------------------------------*/
        memset(&cmd, 0, sizeof(cmd));
        cmd.uscsi_flags         = USCSI_READ;
        cmd.uscsi_bufaddr       = (caddr_t) ioBuffer;
        cmd.uscsi_buflen        = sizeof(ioBuffer);
        cmd.uscsi_timeout       = 10;
        cmd.uscsi_cdb           = (caddr_t) cdb;
        cmd.uscsi_cdblen        = 6;
        cmd.uscsi_rqbuf         = (caddr_t) senseData;
        cmd.uscsi_rqlen         = sizeof(senseData);

        /*---------------------------------------------------------------------
         * Print the message
         *-------------------------------------------------------------------*/
        printf("Sending ioctl command\n");

        /*---------------------------------------------------------------------
         * Send the uscsi command
         *-------------------------------------------------------------------*/
        if (ioctl(fd, USCSICMD, &cmd) < 0)
                printf("ioctl(USCSICMD) failed: %ld\n", errno);

        /*---------------------------------------------------------------------
         * Print the scsi status code
         *-------------------------------------------------------------------*/
        printf("uscsi_status = %ld\n", cmd.uscsi_status);

        /*---------------------------------------------------------------------
         * Hex dump the results
         *-------------------------------------------------------------------*/
        LclHexDump(ioBuffer, sizeof(ioBuffer));

        /*---------------------------------------------------------------------
         * Allocate some space
         *-------------------------------------------------------------------*/
        data = (Byte *) malloc(32*1024);

        /*---------------------------------------------------------------------
         * New line
         *-------------------------------------------------------------------*/
        printf("\n");
        total = 40;

        /*---------------------------------------------------------------------
         * Write some data to the tape
         *-------------------------------------------------------------------*/
        for (x = 1; x <= total; x++)
                {
/*              printf("\rWriting data block %ld of %ld...", x, total);
                if (write(fd, data, 32*1024) < 0)
                        break;
*/
                }

        /*---------------------------------------------------------------------
         * Free the space
         *-------------------------------------------------------------------*/
        free(data);
        printf("\n");

        /*---------------------------------------------------------------------
         * Close the file handle
         *-------------------------------------------------------------------*/
        close(fd);
        return 0;
        }