📄 scsiglue.c
字号:
typedef union usb_stor_scsi_sense_hdr_u Usb_Stor_Scsi_Sense_Hdr_u;struct usb_stor_scsi_sense_hdr_10{ __u8* dataLengthMSB; __u8* dataLengthLSB; __u8* mediumType; __u8* devSpecParms; __u8* reserved1; __u8* reserved2; __u8* blkDescLengthMSB; __u8* blkDescLengthLSB;};typedef struct usb_stor_scsi_sense_hdr_10 Usb_Stor_Scsi_Sense_Hdr_10;union usb_stor_scsi_sense_hdr_10_u{ Usb_Stor_Scsi_Sense_Hdr_10 hdr; __u8* array[USB_STOR_SCSI_SENSE_10_HDRSZ];};typedef union usb_stor_scsi_sense_hdr_10_u Usb_Stor_Scsi_Sense_Hdr_10_u;void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* , Usb_Stor_Scsi_Sense_Hdr_u*, Usb_Stor_Scsi_Sense_Hdr_10_u*, int* );int usb_stor_scsiSense10to6( Scsi_Cmnd* the10 ){ __u8 *buffer=0; int outputBufferSize = 0; int length=0; struct scatterlist *sg = 0; int i=0, j=0, element=0; Usb_Stor_Scsi_Sense_Hdr_u the6Locations; Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations; int sb=0,si=0,db=0,di=0; int sgLength=0; US_DEBUGP("-- converting 10 byte sense data to 6 byte\n"); the10->cmnd[0] = the10->cmnd[0] & 0xBF; /* Determine buffer locations */ usb_stor_scsiSenseParseBuffer( the10, &the6Locations, &the10Locations, &length ); /* Work out minimum buffer to output */ outputBufferSize = *the10Locations.hdr.dataLengthLSB; outputBufferSize += USB_STOR_SCSI_SENSE_HDRSZ; /* Check to see if we need to trucate the output */ if ( outputBufferSize > length ) { printk( KERN_WARNING USB_STORAGE "Had to truncate MODE_SENSE_10 buffer into MODE_SENSE.\n" ); printk( KERN_WARNING USB_STORAGE "outputBufferSize is %d and length is %d.\n", outputBufferSize, length ); } outputBufferSize = length; /* Data length */ if ( *the10Locations.hdr.dataLengthMSB != 0 ) /* MSB must be zero */ { printk( KERN_WARNING USB_STORAGE "Command will be truncated to fit in SENSE6 buffer.\n" ); *the6Locations.hdr.dataLength = 0xff; } else { *the6Locations.hdr.dataLength = *the10Locations.hdr.dataLengthLSB; } /* Medium type and DevSpecific parms */ *the6Locations.hdr.mediumType = *the10Locations.hdr.mediumType; *the6Locations.hdr.devSpecParms = *the10Locations.hdr.devSpecParms; /* Block descriptor length */ if ( *the10Locations.hdr.blkDescLengthMSB != 0 ) /* MSB must be zero */ { printk( KERN_WARNING USB_STORAGE "Command will be truncated to fit in SENSE6 buffer.\n" ); *the6Locations.hdr.blkDescLength = 0xff; } else { *the6Locations.hdr.blkDescLength = *the10Locations.hdr.blkDescLengthLSB; } if ( the10->use_sg == 0 ) { buffer = the10->request_buffer; /* Copy the rest of the data */ memmove( &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]), &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), outputBufferSize - USB_STOR_SCSI_SENSE_HDRSZ ); /* initialise last bytes left in buffer due to smaller header */ memset( &(buffer[outputBufferSize -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ)]), 0, USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ ); } else { sg = (struct scatterlist *) the10->request_buffer; /* scan through this scatterlist and figure out starting positions */ for ( i=0; i < the10->use_sg; i++) { sgLength = sg[i].length; for ( j=0; j<sgLength; j++ ) { /* get to end of header */ if ( element == USB_STOR_SCSI_SENSE_HDRSZ ) { db=i; di=j; } if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ ) { sb=i; si=j; /* we've found both sets now, exit loops */ j=sgLength; i=the10->use_sg; } element++; } } /* Now we know where to start the copy from */ element = USB_STOR_SCSI_SENSE_HDRSZ; while ( element < outputBufferSize -(USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) ) { /* check limits */ if ( sb >= the10->use_sg || si >= sg[sb].length || db >= the10->use_sg || di >= sg[db].length ) { printk( KERN_ERR USB_STORAGE "Buffer overrun averted, this shouldn't happen!\n" ); break; } /* copy one byte */ sg[db].address[di] = sg[sb].address[si]; /* get next destination */ if ( sg[db].length-1 == di ) { db++; di=0; } else { di++; } /* get next source */ if ( sg[sb].length-1 == si ) { sb++; si=0; } else { si++; } element++; } /* zero the remaining bytes */ while ( element < outputBufferSize ) { /* check limits */ if ( db >= the10->use_sg || di >= sg[db].length ) { printk( KERN_ERR USB_STORAGE "Buffer overrun averted, this shouldn't happen!\n" ); break; } sg[db].address[di] = 0; /* get next destination */ if ( sg[db].length-1 == di ) { db++; di=0; } else { di++; } element++; } } /* All done any everything was fine */ return 0;}int usb_stor_scsiSense6to10( Scsi_Cmnd* the6 ){ /* will be used to store part of buffer */ __u8 tempBuffer[USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ], *buffer=0; int outputBufferSize = 0; int length=0; struct scatterlist *sg = 0; int i=0, j=0, element=0; Usb_Stor_Scsi_Sense_Hdr_u the6Locations; Usb_Stor_Scsi_Sense_Hdr_10_u the10Locations; int sb=0,si=0,db=0,di=0; int lsb=0,lsi=0,ldb=0,ldi=0; US_DEBUGP("-- converting 6 byte sense data to 10 byte\n"); the6->cmnd[0] = the6->cmnd[0] | 0x40; /* Determine buffer locations */ usb_stor_scsiSenseParseBuffer( the6, &the6Locations, &the10Locations, &length ); /* Work out minimum buffer to output */ outputBufferSize = *the6Locations.hdr.dataLength; outputBufferSize += USB_STOR_SCSI_SENSE_10_HDRSZ; /* Check to see if we need to trucate the output */ if ( outputBufferSize > length ) { printk( KERN_WARNING USB_STORAGE "Had to truncate MODE_SENSE into MODE_SENSE_10 buffer.\n" ); printk( KERN_WARNING USB_STORAGE "outputBufferSize is %d and length is %d.\n", outputBufferSize, length ); } outputBufferSize = length; /* Block descriptor length - save these before overwriting */ tempBuffer[2] = *the10Locations.hdr.blkDescLengthMSB; tempBuffer[3] = *the10Locations.hdr.blkDescLengthLSB; *the10Locations.hdr.blkDescLengthLSB = *the6Locations.hdr.blkDescLength; *the10Locations.hdr.blkDescLengthMSB = 0; /* reserved - save these before overwriting */ tempBuffer[0] = *the10Locations.hdr.reserved1; tempBuffer[1] = *the10Locations.hdr.reserved2; *the10Locations.hdr.reserved1 = *the10Locations.hdr.reserved2 = 0; /* Medium type and DevSpecific parms */ *the10Locations.hdr.devSpecParms = *the6Locations.hdr.devSpecParms; *the10Locations.hdr.mediumType = *the6Locations.hdr.mediumType; /* Data length */ *the10Locations.hdr.dataLengthLSB = *the6Locations.hdr.dataLength; *the10Locations.hdr.dataLengthMSB = 0; if ( !the6->use_sg ) { buffer = the6->request_buffer; /* Copy the rest of the data */ memmove( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), &(buffer[USB_STOR_SCSI_SENSE_HDRSZ]), outputBufferSize-USB_STOR_SCSI_SENSE_10_HDRSZ ); /* Put the first four bytes (after header) in place */ memcpy( &(buffer[USB_STOR_SCSI_SENSE_10_HDRSZ]), tempBuffer, USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ ); } else { sg = (struct scatterlist *) the6->request_buffer; /* scan through this scatterlist and figure out ending positions */ for ( i=0; i < the6->use_sg; i++) { for ( j=0; j<sg[i].length; j++ ) { /* get to end of header */ if ( element == USB_STOR_SCSI_SENSE_HDRSZ ) { ldb=i; ldi=j; } if ( element == USB_STOR_SCSI_SENSE_10_HDRSZ ) { lsb=i; lsi=j; /* we've found both sets now, exit loops */ j=sg[i].length; i=the6->use_sg; break; } element++; } } /* scan through this scatterlist and figure out starting positions */ element = length-1; /* destination is the last element */ db=the6->use_sg-1; di=sg[db].length-1; for ( i=the6->use_sg-1; i >= 0; i--) { for ( j=sg[i].length-1; j>=0; j-- ) { /* get to end of header and find source for copy */ if ( element == length - 1 - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ) ) { sb=i; si=j; /* we've found both sets now, exit loops */ j=-1; i=-1; } element--; } } /* Now we know where to start the copy from */ element = length-1 - (USB_STOR_SCSI_SENSE_10_HDRSZ-USB_STOR_SCSI_SENSE_HDRSZ); while ( element >= USB_STOR_SCSI_SENSE_10_HDRSZ ) { /* check limits */ if ( ( sb <= lsb && si < lsi ) || ( db <= ldb && di < ldi ) ) { printk( KERN_ERR USB_STORAGE "Buffer overrun averted, this shouldn't happen!\n" ); break; } /* copy one byte */ sg[db].address[di] = sg[sb].address[si]; /* get next destination */ if ( di == 0 ) { db--; di=sg[db].length-1; } else { di--; } /* get next source */ if ( si == 0 ) { sb--; si=sg[sb].length-1; } else { si--; } element--; } /* copy the remaining four bytes */ while ( element >= USB_STOR_SCSI_SENSE_HDRSZ ) { /* check limits */ if ( db <= ldb && di < ldi ) { printk( KERN_ERR USB_STORAGE "Buffer overrun averted, this shouldn't happen!\n" ); break; } sg[db].address[di] = tempBuffer[element-USB_STOR_SCSI_SENSE_HDRSZ]; /* get next destination */ if ( di == 0 ) { db--; di=sg[db].length-1; } else { di--; } element--; } } /* All done and everything was fine */ return 0;}void usb_stor_scsiSenseParseBuffer( Scsi_Cmnd* srb, Usb_Stor_Scsi_Sense_Hdr_u* the6, Usb_Stor_Scsi_Sense_Hdr_10_u* the10, int* length_p ){ int i = 0, j=0, element=0; struct scatterlist *sg = 0; int length = 0; __u8* buffer=0; /* are we scatter-gathering? */ if ( srb->use_sg != 0 ) { /* loop over all the scatter gather structures and * get pointer to the data members in the headers * (also work out the length while we're here) */ sg = (struct scatterlist *) srb->request_buffer; for (i = 0; i < srb->use_sg; i++) { length += sg[i].length; /* We only do the inner loop for the headers */ if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) { /* scan through this scatterlist */ for ( j=0; j<sg[i].length; j++ ) { if ( element < USB_STOR_SCSI_SENSE_HDRSZ ) { /* fill in the pointers for both header types */ the6->array[element] = &(sg[i].address[j]); the10->array[element] = &(sg[i].address[j]); } else if ( element < USB_STOR_SCSI_SENSE_10_HDRSZ ) { /* only the longer headers still cares now */ the10->array[element] = &(sg[i].address[j]); } /* increase element counter */ element++; } } } } else { length = srb->request_bufflen; buffer = srb->request_buffer; if ( length < USB_STOR_SCSI_SENSE_10_HDRSZ ) printk( KERN_ERR USB_STORAGE "Buffer length smaller than header!!" ); for( i=0; i<USB_STOR_SCSI_SENSE_10_HDRSZ; i++ ) { if ( i < USB_STOR_SCSI_SENSE_HDRSZ ) { the6->array[i] = &(buffer[i]); the10->array[i] = &(buffer[i]); } else { the10->array[i] = &(buffer[i]); } } } /* Set value of length passed in */ *length_p = length;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -