⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scsiglue.c

📁 LINUX下USB驱动程序的开发
💻 C
📖 第 1 页 / 共 2 页
字号:
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 + -