2005-04-17 02:20:36 +04:00
/*
* Transport specific attributes .
*
* Copyright ( c ) 2003 Silicon Graphics , Inc . All rights reserved .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# ifndef SCSI_TRANSPORT_H
# define SCSI_TRANSPORT_H
# include <linux/transport_class.h>
2008-09-14 16:55:09 +04:00
# include <linux/blkdev.h>
2005-05-25 01:57:31 +04:00
# include <scsi/scsi_host.h>
2007-02-16 12:46:25 +03:00
# include <scsi/scsi_device.h>
2005-04-17 02:20:36 +04:00
struct scsi_transport_template {
/* the attribute containers */
struct transport_container host_attrs ;
struct transport_container target_attrs ;
struct transport_container device_attrs ;
2005-06-11 06:24:30 +04:00
/*
2006-01-13 21:04:00 +03:00
* If set , called from sysfs and legacy procfs rescanning code .
2005-06-11 06:24:30 +04:00
*/
2006-01-13 21:04:00 +03:00
int ( * user_scan ) ( struct Scsi_Host * , uint , uint , uint ) ;
2005-06-11 06:24:30 +04:00
2005-04-17 02:20:36 +04:00
/* The size of the specific transport attribute structure (a
* space of this size will be left at the end of the
* scsi_ * structure */
int device_size ;
2005-05-25 01:57:31 +04:00
int device_private_offset ;
2005-04-17 02:20:36 +04:00
int target_size ;
2005-05-25 01:57:31 +04:00
int target_private_offset ;
2005-04-17 02:20:36 +04:00
int host_size ;
2005-05-25 01:57:31 +04:00
/* no private offset for the host; there's an alternative mechanism */
2005-04-17 02:20:36 +04:00
/*
* True if the transport wants to use a host - based work - queue
*/
unsigned int create_work_queue : 1 ;
2006-03-13 16:28:57 +03:00
2006-04-01 21:21:04 +04:00
/*
* Allows a transport to override the default error handler .
*/
void ( * eh_strategy_handler ) ( struct Scsi_Host * ) ;
2006-03-13 16:28:57 +03:00
/*
* This is an optional routine that allows the transport to become
* involved when a scsi io timer fires . The return value tells the
* timer routine how to finish the io timeout handling :
* EH_HANDLED : I fixed the error , please complete the command
* EH_RESET_TIMER : I need more time , reset the timer and
* begin counting again
* EH_NOT_HANDLED Begin normal error recovery
*/
2008-09-14 16:55:09 +04:00
enum blk_eh_timer_return ( * eh_timed_out ) ( struct scsi_cmnd * ) ;
2007-07-11 10:08:17 +04:00
/*
* Used as callback for the completion of i_t_nexus request
* for target drivers .
*/
int ( * it_nexus_response ) ( struct Scsi_Host * , u64 , int ) ;
2007-07-11 10:08:22 +04:00
/*
* Used as callback for the completion of task management
* request for target drivers .
*/
int ( * tsk_mgmt_response ) ( struct Scsi_Host * , u64 , u64 , int ) ;
2005-04-17 02:20:36 +04:00
} ;
# define transport_class_to_shost(tc) \
2008-02-22 02:13:36 +03:00
dev_to_shost ( ( tc ) - > parent )
2005-04-17 02:20:36 +04:00
2005-05-25 01:57:31 +04:00
/* Private area maintenance. The driver requested allocations come
* directly after the transport class allocations ( if any ) . The idea
* is that you * must * call these only once . The code assumes that the
* initial values are the ones the transport specific code requires */
static inline void
scsi_transport_reserve_target ( struct scsi_transport_template * t , int space )
{
BUG_ON ( t - > target_private_offset ! = 0 ) ;
t - > target_private_offset = ALIGN ( t - > target_size , sizeof ( void * ) ) ;
t - > target_size = t - > target_private_offset + space ;
}
static inline void
scsi_transport_reserve_device ( struct scsi_transport_template * t , int space )
{
BUG_ON ( t - > device_private_offset ! = 0 ) ;
t - > device_private_offset = ALIGN ( t - > device_size , sizeof ( void * ) ) ;
t - > device_size = t - > device_private_offset + space ;
}
static inline void *
scsi_transport_target_data ( struct scsi_target * starget )
{
struct Scsi_Host * shost = dev_to_shost ( & starget - > dev ) ;
return ( u8 * ) starget - > starget_data
+ shost - > transportt - > target_private_offset ;
}
static inline void *
scsi_transport_device_data ( struct scsi_device * sdev )
{
struct Scsi_Host * shost = sdev - > host ;
return ( u8 * ) sdev - > sdev_data
+ shost - > transportt - > device_private_offset ;
}
2005-04-17 02:20:36 +04:00
# endif /* SCSI_TRANSPORT_H */