2005-04-16 15:20:36 -07:00
/*
* linux / drivers / acorn / scsi / scsi . h
*
* Copyright ( C ) 2002 Russell King
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* Commonly used scsi driver functions .
*/
2005-09-17 17:55:31 +10:00
# include <linux/scatterlist.h>
2005-04-16 15:20:36 -07:00
# define BELT_AND_BRACES
/*
* The scatter - gather list handling . This contains all
* the yucky stuff that needs to be fixed properly .
*/
2005-10-31 18:31:56 +01:00
static inline int copy_SCp_to_sg ( struct scatterlist * sg , struct scsi_pointer * SCp , int max )
2005-04-16 15:20:36 -07:00
{
int bufs = SCp - > buffers_residual ;
BUG_ON ( bufs + 1 > max ) ;
2005-09-17 17:55:31 +10:00
sg_set_buf ( sg , SCp - > ptr , SCp - > this_residual ) ;
2005-04-16 15:20:36 -07:00
if ( bufs )
memcpy ( sg + 1 , SCp - > buffer + 1 ,
sizeof ( struct scatterlist ) * bufs ) ;
return bufs + 1 ;
}
2005-10-31 18:31:56 +01:00
static inline int next_SCp ( struct scsi_pointer * SCp )
2005-04-16 15:20:36 -07:00
{
int ret = SCp - > buffers_residual ;
if ( ret ) {
SCp - > buffer + + ;
SCp - > buffers_residual - - ;
SCp - > ptr = ( char * )
( page_address ( SCp - > buffer - > page ) +
SCp - > buffer - > offset ) ;
SCp - > this_residual = SCp - > buffer - > length ;
} else {
SCp - > ptr = NULL ;
SCp - > this_residual = 0 ;
}
return ret ;
}
2005-10-31 18:31:56 +01:00
static inline unsigned char get_next_SCp_byte ( struct scsi_pointer * SCp )
2005-04-16 15:20:36 -07:00
{
char c = * SCp - > ptr ;
SCp - > ptr + = 1 ;
SCp - > this_residual - = 1 ;
return c ;
}
2005-10-31 18:31:56 +01:00
static inline void put_next_SCp_byte ( struct scsi_pointer * SCp , unsigned char c )
2005-04-16 15:20:36 -07:00
{
* SCp - > ptr = c ;
SCp - > ptr + = 1 ;
SCp - > this_residual - = 1 ;
}
static inline void init_SCp ( Scsi_Cmnd * SCpnt )
{
memset ( & SCpnt - > SCp , 0 , sizeof ( struct scsi_pointer ) ) ;
if ( SCpnt - > use_sg ) {
unsigned long len = 0 ;
int buf ;
SCpnt - > SCp . buffer = ( struct scatterlist * ) SCpnt - > buffer ;
SCpnt - > SCp . buffers_residual = SCpnt - > use_sg - 1 ;
SCpnt - > SCp . ptr = ( char * )
( page_address ( SCpnt - > SCp . buffer - > page ) +
SCpnt - > SCp . buffer - > offset ) ;
SCpnt - > SCp . this_residual = SCpnt - > SCp . buffer - > length ;
# ifdef BELT_AND_BRACES
/*
* Calculate correct buffer length . Some commands
* come in with the wrong request_bufflen .
*/
for ( buf = 0 ; buf < = SCpnt - > SCp . buffers_residual ; buf + + )
len + = SCpnt - > SCp . buffer [ buf ] . length ;
if ( SCpnt - > request_bufflen ! = len )
printk ( KERN_WARNING " scsi%d.%c: bad request buffer "
" length %d, should be %ld \n " , SCpnt - > device - > host - > host_no ,
' 0 ' + SCpnt - > device - > id , SCpnt - > request_bufflen , len ) ;
SCpnt - > request_bufflen = len ;
# endif
} else {
SCpnt - > SCp . ptr = ( unsigned char * ) SCpnt - > request_buffer ;
SCpnt - > SCp . this_residual = SCpnt - > request_bufflen ;
}
/*
* If the upper SCSI layers pass a buffer , but zero length ,
* we aren ' t interested in the buffer pointer .
*/
if ( SCpnt - > SCp . this_residual = = 0 & & SCpnt - > SCp . ptr ) {
#if 0 //def BELT_AND_BRACES
printk ( KERN_WARNING " scsi%d.%c: zero length buffer passed for "
" command " , SCpnt - > host - > host_no , ' 0 ' + SCpnt - > target ) ;
2005-04-03 14:53:59 -05:00
__scsi_print_command ( SCpnt - > cmnd ) ;
2005-04-16 15:20:36 -07:00
# endif
SCpnt - > SCp . ptr = NULL ;
}
}