2008-01-26 14:10:43 +01:00
# ifndef S390_IO_SCH_H
# define S390_IO_SCH_H
2009-12-07 12:51:25 +01:00
# include <linux/types.h>
2008-07-14 09:59:05 +02:00
# include <asm/schid.h>
2009-12-07 12:51:25 +01:00
# include <asm/ccwdev.h>
# include "css.h"
2008-01-26 14:10:43 +01:00
/*
2008-07-14 09:58:51 +02:00
* command - mode operation request block
2008-01-26 14:10:43 +01:00
*/
2008-07-14 09:58:51 +02:00
struct cmd_orb {
2008-01-26 14:10:43 +01:00
u32 intparm ; /* interruption parameter */
u32 key : 4 ; /* flags, like key, suspend control, etc. */
u32 spnd : 1 ; /* suspend control */
u32 res1 : 1 ; /* reserved */
u32 mod : 1 ; /* modification control */
u32 sync : 1 ; /* synchronize control */
u32 fmt : 1 ; /* format control */
u32 pfch : 1 ; /* prefetch control */
u32 isic : 1 ; /* initial-status-interruption control */
u32 alcc : 1 ; /* address-limit-checking control */
u32 ssic : 1 ; /* suppress-suspended-interr. control */
u32 res2 : 1 ; /* reserved */
u32 c64 : 1 ; /* IDAW/QDIO 64 bit control */
u32 i2k : 1 ; /* IDAW 2/4kB block size control */
u32 lpm : 8 ; /* logical path mask */
u32 ils : 1 ; /* incorrect length */
u32 zero : 6 ; /* reserved zeros */
u32 orbx : 1 ; /* ORB extension control */
u32 cpa ; /* channel program address */
} __attribute__ ( ( packed , aligned ( 4 ) ) ) ;
2008-07-14 09:58:51 +02:00
/*
* transport - mode operation request block
*/
struct tm_orb {
u32 intparm ;
u32 key : 4 ;
u32 : 9 ;
u32 b : 1 ;
u32 : 2 ;
u32 lpm : 8 ;
u32 : 7 ;
u32 x : 1 ;
u32 tcw ;
u32 prio : 8 ;
u32 : 8 ;
u32 rsvpgm : 8 ;
u32 : 8 ;
u32 : 32 ;
u32 : 32 ;
u32 : 32 ;
u32 : 32 ;
} __attribute__ ( ( packed , aligned ( 4 ) ) ) ;
union orb {
struct cmd_orb cmd ;
struct tm_orb tm ;
} __attribute__ ( ( packed , aligned ( 4 ) ) ) ;
2008-01-26 14:10:43 +01:00
struct io_subchannel_private {
2008-07-14 09:58:51 +02:00
union orb orb ; /* operation request block */
2008-01-26 14:10:43 +01:00
struct ccw1 sense_ccw ; /* static ccw for sense command */
} __attribute__ ( ( aligned ( 8 ) ) ) ;
# define to_io_private(n) ((struct io_subchannel_private *)n->private)
2008-01-26 14:10:46 +01:00
# define sch_get_cdev(n) (dev_get_drvdata(&n->dev))
# define sch_set_cdev(n, c) (dev_set_drvdata(&n->dev, c))
2008-01-26 14:10:43 +01:00
# define MAX_CIWS 8
2009-12-07 12:51:25 +01:00
/*
* Possible status values for a CCW request ' s I / O .
*/
enum io_status {
IO_DONE ,
IO_RUNNING ,
IO_STATUS_ERROR ,
IO_PATH_ERROR ,
IO_REJECTED ,
IO_KILLED
} ;
/**
* ccw_request - Internal CCW request .
* @ cp : channel program to start
* @ timeout : maximum allowable time in jiffies between start I / O and interrupt
* @ maxretries : number of retries per I / O operation and path
* @ lpm : mask of paths to use
* @ check : optional callback that determines if results are final
* @ filter : optional callback to adjust request status based on IRB data
* @ callback : final callback
* @ data : user - defined pointer passed to all callbacks
* @ mask : current path mask
* @ retries : current number of retries
* @ drc : delayed return code
* @ cancel : non - zero if request was cancelled
* @ done : non - zero if request was finished
*/
struct ccw_request {
struct ccw1 * cp ;
unsigned long timeout ;
u16 maxretries ;
u8 lpm ;
int ( * check ) ( struct ccw_device * , void * ) ;
enum io_status ( * filter ) ( struct ccw_device * , void * , struct irb * ,
enum io_status ) ;
void ( * callback ) ( struct ccw_device * , void * , int ) ;
void * data ;
/* These fields are used internally. */
2009-12-07 12:51:40 +01:00
u16 mask ;
2009-12-07 12:51:25 +01:00
u16 retries ;
int drc ;
int cancel : 1 ;
int done : 1 ;
} __attribute__ ( ( packed ) ) ;
2008-01-26 14:10:43 +01:00
/*
* sense - id response buffer layout
*/
struct senseid {
/* common part */
u8 reserved ; /* always 0x'FF' */
u16 cu_type ; /* control unit type */
u8 cu_model ; /* control unit model */
u16 dev_type ; /* device type */
u8 dev_model ; /* device model */
u8 unused ; /* padding byte */
/* extended part */
struct ciw ciw [ MAX_CIWS ] ; /* variable # of CIWs */
} __attribute__ ( ( packed , aligned ( 4 ) ) ) ;
2009-12-07 12:51:19 +01:00
enum cdev_todo {
CDEV_TODO_NOTHING ,
CDEV_TODO_ENABLE_CMF ,
CDEV_TODO_REBIND ,
CDEV_TODO_REGISTER ,
CDEV_TODO_UNREG ,
CDEV_TODO_UNREG_EVAL ,
} ;
2008-01-26 14:10:43 +01:00
struct ccw_device_private {
struct ccw_device * cdev ;
struct subchannel * sch ;
int state ; /* device state */
atomic_t onoff ;
struct ccw_dev_id dev_id ; /* device id */
struct subchannel_id schid ; /* subchannel number */
2009-12-07 12:51:25 +01:00
struct ccw_request req ; /* internal I/O request */
2009-12-07 12:51:27 +01:00
int iretry ;
u8 pgid_valid_mask ; /* mask of valid PGIDs */
2009-12-18 17:43:23 +01:00
u8 pgid_todo_mask ; /* mask of PGIDs to be adjusted */
2008-01-26 14:10:43 +01:00
struct {
unsigned int fast : 1 ; /* post with "channel end" */
unsigned int repall : 1 ; /* report every interrupt status */
unsigned int pgroup : 1 ; /* do path grouping */
unsigned int force : 1 ; /* allow forced online */
2009-12-07 12:51:30 +01:00
unsigned int mpath : 1 ; /* do multipathing */
2008-01-26 14:10:43 +01:00
} __attribute__ ( ( packed ) ) options ;
struct {
unsigned int esid : 1 ; /* Ext. SenseID supported by HW */
unsigned int dosense : 1 ; /* delayed SENSE required */
unsigned int doverify : 1 ; /* delayed path verification */
unsigned int donotify : 1 ; /* call notify function */
unsigned int recog_done : 1 ; /* dev. recog. complete */
unsigned int fake_irb : 1 ; /* deliver faked irb */
2009-06-16 10:30:20 +02:00
unsigned int resuming : 1 ; /* recognition while resume */
2009-12-07 12:51:30 +01:00
unsigned int pgroup : 1 ; /* pathgroup is set up */
unsigned int mpath : 1 ; /* multipathing is set up */
2009-12-07 12:51:34 +01:00
unsigned int initialized : 1 ; /* set if initial reference held */
2008-01-26 14:10:43 +01:00
} __attribute__ ( ( packed ) ) flags ;
unsigned long intparm ; /* user interruption parameter */
struct qdio_irq * qdio_data ;
struct irb irb ; /* device status */
struct senseid senseid ; /* SenseID info */
struct pgid pgid [ 8 ] ; /* path group IDs per chpid*/
struct ccw1 iccws [ 2 ] ; /* ccws for SNID/SID/SPGID commands */
2009-12-07 12:51:19 +01:00
struct work_struct todo_work ;
enum cdev_todo todo ;
2008-01-26 14:10:43 +01:00
wait_queue_head_t wait_q ;
struct timer_list timer ;
void * cmb ; /* measurement information */
struct list_head cmb_list ; /* list of measured devices */
u64 cmb_start_time ; /* clock value of cmb reset */
void * cmb_wait ; /* deferred cmb enable/disable */
} ;
2008-10-10 21:33:15 +02:00
static inline int ssch ( struct subchannel_id schid , union orb * addr )
2008-01-26 14:10:43 +01:00
{
register struct subchannel_id reg1 asm ( " 1 " ) = schid ;
2008-07-14 09:58:51 +02:00
int ccode = - EIO ;
2008-01-26 14:10:43 +01:00
asm volatile (
" ssch 0(%2) \n "
2008-07-14 09:58:51 +02:00
" 0: ipm %0 \n "
" srl %0,28 \n "
" 1: \n "
EX_TABLE ( 0 b , 1 b )
2008-10-10 21:33:15 +02:00
: " +d " ( ccode )
: " d " ( reg1 ) , " a " ( addr ) , " m " ( * addr )
: " cc " , " memory " ) ;
2008-01-26 14:10:43 +01:00
return ccode ;
}
static inline int rsch ( struct subchannel_id schid )
{
register struct subchannel_id reg1 asm ( " 1 " ) = schid ;
int ccode ;
asm volatile (
" rsch \n "
" ipm %0 \n "
" srl %0,28 "
2008-10-10 21:33:15 +02:00
: " =d " ( ccode )
: " d " ( reg1 )
: " cc " , " memory " ) ;
2008-01-26 14:10:43 +01:00
return ccode ;
}
static inline int csch ( struct subchannel_id schid )
{
register struct subchannel_id reg1 asm ( " 1 " ) = schid ;
int ccode ;
asm volatile (
" csch \n "
" ipm %0 \n "
" srl %0,28 "
2008-10-10 21:33:15 +02:00
: " =d " ( ccode )
: " d " ( reg1 )
: " cc " ) ;
2008-01-26 14:10:43 +01:00
return ccode ;
}
static inline int hsch ( struct subchannel_id schid )
{
register struct subchannel_id reg1 asm ( " 1 " ) = schid ;
int ccode ;
asm volatile (
" hsch \n "
" ipm %0 \n "
" srl %0,28 "
2008-10-10 21:33:15 +02:00
: " =d " ( ccode )
: " d " ( reg1 )
: " cc " ) ;
2008-01-26 14:10:43 +01:00
return ccode ;
}
static inline int xsch ( struct subchannel_id schid )
{
register struct subchannel_id reg1 asm ( " 1 " ) = schid ;
int ccode ;
asm volatile (
" .insn rre,0xb2760000,%1,0 \n "
" ipm %0 \n "
" srl %0,28 "
2008-10-10 21:33:15 +02:00
: " =d " ( ccode )
: " d " ( reg1 )
: " cc " ) ;
2008-01-26 14:10:43 +01:00
return ccode ;
}
# endif