Hi there,

I'm using the generic scsi driver with the  /dev/sg? interface.
I need that in order to get information about the failing of the internal CIRC
and L2 decoder. To my knowledge the information is accessible via the sense
buffer after executing read commands, for example.
Up to now i'm not able to do this properly. 
I hope there are some people out there who can help me with this.

The code  goes like this, the problem here is that the READ(10) command 
is exectuted without any warnings even if there's no CD in the drive!
What do I have to do?
And additionally it doesn't mock about any bad CD's!
So what I'm doing wrong ?
Any help is appreciated and thanks in advance!

 Kay

-------
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdarg.h>
#include <scsi/sg.h>
#include <linux/cdrom.h>
#include <malloc.h>
#include <signal.h>
#define TESTUNITREADY_CMD 0
#define TESTUNITREADY_CMDLEN 6
#define ADD_SENSECODE 12
#define ADD_SC_QUALIFIER 13
#define NO_MEDIA_SC 0x3a
#define NO_MEDIA_SCQ 0x00
#define SCSI_OFF sizeof(struct sg_header)

static int handle_SCSI_cmd(unsigned cmd_len, /* command length */
                           unsigned in_size, /* input data size */
                           unsigned char *i_buff, /* input buffer */
                           unsigned out_size, /* output data size */
                           unsigned char *o_buff /* output buffer */
                           )
{
        int status = 0;
        struct sg_header *sg_hd;

        INFO(2,("in handle_SCSI_cmd\n"));
            /* safety checks */
        if (!cmd_len) return -1; /* need a cmd_len != 0 */
        if (!i_buff) return -1; /* need an input buffer != NULL */
#ifdef SG_BIG_BUFF
        if (OFF + cmd_len + in_size > SG_BIG_BUFF) return -1;
        if (OFF + out_size > SG_BIG_BUFF) return -1;
#else
        if (OFF + cmd_len + in_size > 4096) return -1;
        if (OFF + out_size > 4096) return -1;
#endif
        
        if (!o_buff) out_size = 0; /* no output buffer, no output size */
        
            /* generic SCSI device header construction */
        sg_hd = (struct sg_header *) i_buff;
        sg_hd->reply_len   = OFF + out_size;
        sg_hd->twelve_byte = cmd_len == 12;
        sg_hd->result = 0;
#if     0
        sg_hd->pack_len    = OFF + cmd_len + in_size; /* not necessary */
        sg_hd->pack_id;         /* not used */
        sg_hd->other_flags;     /* not used */
#endif
        
            /* send command */
        sigprocmask ( SIG_BLOCK, &sigset, NULL );
        status = write( fd, i_buff, OFF + cmd_len + in_size );

        

        if ( status < 0 || status != OFF + cmd_len + in_size ||
             sg_hd->result )
        {
                    /* some error happened */
                fprintf( stderr, "write(generic) result = 0x%x cmd = 0x%x\n",
                         sg_hd->result, i_buff[OFF] );
                perror("");
                sigprocmask ( SIG_UNBLOCK, &sigset, NULL );
                return status;
        }
  
        if (!o_buff) o_buff = i_buff; /* buffer pointer check */
  
            /* retrieve result */
        status = read( fd, o_buff, OFF + out_size);

        if ( status < 0 || status != OFF + out_size || sg_hd->result )
        {
                    /* some error happened */
                fprintf( stderr, "read(generic) status = 0x%x, result = 0x%x, "
                         "cmd = 0x%x\n",
                         status, sg_hd->result, o_buff[OFF] );
                fprintf( stderr, "read(generic) sense "
                         "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
                         sg_hd->sense_buffer[0],         sg_hd->sense_buffer[1],
                         sg_hd->sense_buffer[2],         sg_hd->sense_buffer[3],
                         sg_hd->sense_buffer[4],         sg_hd->sense_buffer[5],
                         sg_hd->sense_buffer[6],         sg_hd->sense_buffer[7],
                         sg_hd->sense_buffer[8],         sg_hd->sense_buffer[9],
                         sg_hd->sense_buffer[10],        sg_hd->sense_buffer[11],
                         sg_hd->sense_buffer[12],        sg_hd->sense_buffer[13],
                         sg_hd->sense_buffer[14],        sg_hd->sense_buffer[15]);
                if (status < 0)
                        perror("");
        }
        sigprocmask ( SIG_UNBLOCK, &sigset, NULL );
            /* Look if we got what we expected to get */
        if (status == OFF + out_size) status = 0; /* got them all */
  
        return status;          /* 0 means no error */
}

int TestForMedium ( void )
{
            /* request READY status */
        static unsigned char cmdblk [TESTUNITREADY_CMDLEN] = {
                TESTUNITREADY_CMD, /* command */
                0, /* lun/reserved */
                0, /* reserved */
                0, /* reserved */
                0, /* reserved */
                0};/* control */
        int ret;

        INFO(2,("\ndoing TESTUNITREADY command:\n\n"));
        
        memcpy( cmd + SCSI_OFF, cmdblk, sizeof(cmdblk) );
    
            /*
             * +------------------+
             * | struct sg_header | <- cmd
             * +------------------+
             * | copy of cmdblk   | <- cmd + SCSI_OFF
             * +------------------+
             */
    
        if (ret = handle_SCSI_cmd(sizeof(cmdblk), 0, cmd,
                            0, NULL))
        {
                fprintf (stderr, "Test unit ready failed\n");
                exit(2);
        }

        INFO(4,("handleSCSI returned %d\n",ret));      
    
        return
                *(((struct sg_header*)cmd)->sense_buffer +ADD_SENSECODE) !=
                NO_MEDIA_SC ||
                *(((struct sg_header*)cmd)->sense_buffer +ADD_SC_QUALIFIER) !=
                NO_MEDIA_SCQ;
}

static void ReadStandard (unsigned char *p, long lSector, unsigned long SectorBurstVal 
)
{
            /* READ10, flags, block1 msb, block2, block3, block4 lsb, reserved, 
               transfer len msb, transfer len lsb, block addressing mode */
        static unsigned char cmdblk [10] = {0x28, 0, 0, 0, 0, 0, 0, 0, 1, 0};
        
        unsigned char *cmd0 = cmd + OFF;
        int count = 3,ret;
        memcpy( cmd + OFF, cmdblk, sizeof(cmdblk) );
        
        cmd0[1] |= (1<<3);  /* set FUA (Force Unit Bit) */
        cmd0[1] |= (1<<4);   /* DPO bit as well */
         
        
        cmd0[3] = (unsigned char)((lSector >> 16) & 0xFF);
        cmd0[4] = (unsigned char)((lSector >> 8) & 0xFF);
        cmd0[5] = (unsigned char)(lSector & 0xFF);
        
        cmd0 [8] = (unsigned char)SectorBurstVal;
        cmd0 [7] = (unsigned short int) SectorBurstVal;
        cmd0[7] = 0xff; cmd0[8]= 0xff;
        
        while (count && (ret = handle_SCSI_cmd(sizeof(cmdblk), 0, cmd, SectorBurstVal 
* CD_FRAMESIZE_RAW, p - OFF )))
        {
                count--;
                if (ret==-1) printf("handle_SCSI_cmd returned -1\n") ;
                
        }
      
        if (!count)
                FatalError ("Read CD-ROM10 failed\n");
}

void main( int argc, char *argv[] )
{
        char Device[32];
        unsigned char * rinc, *readoutdata;
        unsigned char m4,m10,m11;
        int n;
        
        if (argc!=2)
        {
                fprintf(stderr,"usage: scsi_control <device>\n\n");
                exit(1);
        }
        
        strcpy( Device, argv[1] );
        fd = open(Device, O_RDWR);
        if (fd < 0)
        {
                perror("open");
                exit(1);
        }

        if (!TestForMedium()) {
                printf("device is unloaded\n");
        } else {
                printf("device is loaded\n");
        }

        readoutdata = (unsigned char*) malloc(FRAMES*CD_FRAMESIZE_RAW + OFF );
        bzero (readoutdata, sizeof(readoutdata) );

        for (n=0;;n++) {
              
                ReadStandard(readoutdata+OFF,n*100,FRAMES);
        }
        
        
}





-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]

Reply via email to