2019-06-04 11:11:33 +03:00
/* SPDX-License-Identifier: GPL-2.0-only */
2005-04-17 02:20:36 +04:00
/*
* Copyright ( C ) 2002 Russell King
*
2022-02-18 22:50:37 +03:00
* Commonly used functions by the ARM SCSI - II drivers .
2005-04-17 02:20:36 +04:00
*/
2005-09-17 11:55:31 +04:00
# include <linux/scatterlist.h>
2005-04-17 02:20:36 +04:00
# define BELT_AND_BRACES
2022-02-18 22:50:38 +03:00
struct arm_cmd_priv {
struct scsi_pointer scsi_pointer ;
} ;
static inline struct scsi_pointer * arm_scsi_pointer ( struct scsi_cmnd * cmd )
{
struct arm_cmd_priv * acmd = scsi_cmd_priv ( cmd ) ;
return & acmd - > scsi_pointer ;
}
2005-04-17 02:20:36 +04:00
/*
* The scatter - gather list handling . This contains all
* the yucky stuff that needs to be fixed properly .
*/
2007-09-09 22:31:21 +04:00
/*
* copy_SCp_to_sg ( ) Assumes contiguous allocation at @ sg of at - most @ max
* entries of uninitialized memory . SCp is from scsi - ml and has a valid
* ( possibly chained ) sg - list
*/
2005-10-31 20:31:56 +03:00
static inline int copy_SCp_to_sg ( struct scatterlist * sg , struct scsi_pointer * SCp , int max )
2005-04-17 02:20:36 +04:00
{
int bufs = SCp - > buffers_residual ;
2007-09-09 22:31:21 +04:00
/* FIXME: It should be easy for drivers to loop on copy_SCp_to_sg().
* and to remove this BUG_ON . Use min ( ) in - its - place
*/
2005-04-17 02:20:36 +04:00
BUG_ON ( bufs + 1 > max ) ;
2005-09-17 11:55:31 +04:00
sg_set_buf ( sg , SCp - > ptr , SCp - > this_residual ) ;
2005-04-17 02:20:36 +04:00
2007-09-09 22:31:21 +04:00
if ( bufs ) {
struct scatterlist * src_sg ;
unsigned i ;
for_each_sg ( sg_next ( SCp - > buffer ) , src_sg , bufs , i )
* ( + + sg ) = * src_sg ;
sg_mark_end ( sg ) ;
}
2005-04-17 02:20:36 +04:00
return bufs + 1 ;
}
2005-10-31 20:31:56 +03:00
static inline int next_SCp ( struct scsi_pointer * SCp )
2005-04-17 02:20:36 +04:00
{
int ret = SCp - > buffers_residual ;
if ( ret ) {
2007-09-09 22:31:21 +04:00
SCp - > buffer = sg_next ( SCp - > buffer ) ;
2005-04-17 02:20:36 +04:00
SCp - > buffers_residual - - ;
2007-10-26 20:47:34 +04:00
SCp - > ptr = sg_virt ( SCp - > buffer ) ;
2005-04-17 02:20:36 +04:00
SCp - > this_residual = SCp - > buffer - > length ;
} else {
SCp - > ptr = NULL ;
SCp - > this_residual = 0 ;
}
return ret ;
}
2005-10-31 20:31:56 +03:00
static inline unsigned char get_next_SCp_byte ( struct scsi_pointer * SCp )
2005-04-17 02:20:36 +04:00
{
char c = * SCp - > ptr ;
SCp - > ptr + = 1 ;
SCp - > this_residual - = 1 ;
return c ;
}
2005-10-31 20:31:56 +03:00
static inline void put_next_SCp_byte ( struct scsi_pointer * SCp , unsigned char c )
2005-04-17 02:20:36 +04:00
{
* SCp - > ptr = c ;
SCp - > ptr + = 1 ;
SCp - > this_residual - = 1 ;
}
2006-10-01 15:18:37 +04:00
static inline void init_SCp ( struct scsi_cmnd * SCpnt )
2005-04-17 02:20:36 +04:00
{
2022-02-18 22:50:38 +03:00
struct scsi_pointer * scsi_pointer = arm_scsi_pointer ( SCpnt ) ;
memset ( scsi_pointer , 0 , sizeof ( struct scsi_pointer ) ) ;
2005-04-17 02:20:36 +04:00
2007-09-09 22:31:21 +04:00
if ( scsi_bufflen ( SCpnt ) ) {
2005-04-17 02:20:36 +04:00
unsigned long len = 0 ;
2022-02-18 22:50:38 +03:00
scsi_pointer - > buffer = scsi_sglist ( SCpnt ) ;
scsi_pointer - > buffers_residual = scsi_sg_count ( SCpnt ) - 1 ;
scsi_pointer - > ptr = sg_virt ( scsi_pointer - > buffer ) ;
scsi_pointer - > this_residual = scsi_pointer - > buffer - > length ;
scsi_pointer - > phase = scsi_bufflen ( SCpnt ) ;
2005-04-17 02:20:36 +04:00
# ifdef BELT_AND_BRACES
2007-09-09 22:31:21 +04:00
{ /*
* Calculate correct buffer length . Some commands
* come in with the wrong scsi_bufflen .
*/
struct scatterlist * sg ;
unsigned i , sg_count = scsi_sg_count ( SCpnt ) ;
scsi_for_each_sg ( SCpnt , sg , sg_count , i )
len + = sg - > length ;
if ( scsi_bufflen ( SCpnt ) ! = 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 ,
scsi_bufflen ( SCpnt ) , len ) ;
/*
* FIXME : Totaly naive fixup . We should abort
* with error
*/
2022-02-18 22:50:38 +03:00
scsi_pointer - > phase =
2007-09-09 22:31:21 +04:00
min_t ( unsigned long , len ,
scsi_bufflen ( SCpnt ) ) ;
}
}
2005-04-17 02:20:36 +04:00
# endif
} else {
2022-02-18 22:50:38 +03:00
scsi_pointer - > ptr = NULL ;
scsi_pointer - > this_residual = 0 ;
scsi_pointer - > phase = 0 ;
2005-04-17 02:20:36 +04:00
}
}