Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
[pandora-kernel.git] / drivers / s390 / cio / io_sch.h
1 #ifndef S390_IO_SCH_H
2 #define S390_IO_SCH_H
3
4 #include <linux/types.h>
5 #include <asm/schid.h>
6 #include <asm/ccwdev.h>
7 #include "css.h"
8
9 /*
10  * command-mode operation request block
11  */
12 struct cmd_orb {
13         u32 intparm;    /* interruption parameter */
14         u32 key  : 4;   /* flags, like key, suspend control, etc. */
15         u32 spnd : 1;   /* suspend control */
16         u32 res1 : 1;   /* reserved */
17         u32 mod  : 1;   /* modification control */
18         u32 sync : 1;   /* synchronize control */
19         u32 fmt  : 1;   /* format control */
20         u32 pfch : 1;   /* prefetch control */
21         u32 isic : 1;   /* initial-status-interruption control */
22         u32 alcc : 1;   /* address-limit-checking control */
23         u32 ssic : 1;   /* suppress-suspended-interr. control */
24         u32 res2 : 1;   /* reserved */
25         u32 c64  : 1;   /* IDAW/QDIO 64 bit control  */
26         u32 i2k  : 1;   /* IDAW 2/4kB block size control */
27         u32 lpm  : 8;   /* logical path mask */
28         u32 ils  : 1;   /* incorrect length */
29         u32 zero : 6;   /* reserved zeros */
30         u32 orbx : 1;   /* ORB extension control */
31         u32 cpa;        /* channel program address */
32 }  __attribute__ ((packed, aligned(4)));
33
34 /*
35  * transport-mode operation request block
36  */
37 struct tm_orb {
38         u32 intparm;
39         u32 key:4;
40         u32 :9;
41         u32 b:1;
42         u32 :2;
43         u32 lpm:8;
44         u32 :7;
45         u32 x:1;
46         u32 tcw;
47         u32 prio:8;
48         u32 :8;
49         u32 rsvpgm:8;
50         u32 :8;
51         u32 :32;
52         u32 :32;
53         u32 :32;
54         u32 :32;
55 }  __attribute__ ((packed, aligned(4)));
56
57 union orb {
58         struct cmd_orb cmd;
59         struct tm_orb tm;
60 }  __attribute__ ((packed, aligned(4)));
61
62 struct io_subchannel_private {
63         union orb orb;          /* operation request block */
64         struct ccw1 sense_ccw;  /* static ccw for sense command */
65 } __attribute__ ((aligned(8)));
66
67 #define to_io_private(n) ((struct io_subchannel_private *)n->private)
68 #define sch_get_cdev(n) (dev_get_drvdata(&n->dev))
69 #define sch_set_cdev(n, c) (dev_set_drvdata(&n->dev, c))
70
71 #define MAX_CIWS 8
72
73 /*
74  * Possible status values for a CCW request's I/O.
75  */
76 enum io_status {
77         IO_DONE,
78         IO_RUNNING,
79         IO_STATUS_ERROR,
80         IO_PATH_ERROR,
81         IO_REJECTED,
82         IO_KILLED
83 };
84
85 /**
86  * ccw_request - Internal CCW request.
87  * @cp: channel program to start
88  * @timeout: maximum allowable time in jiffies between start I/O and interrupt
89  * @maxretries: number of retries per I/O operation and path
90  * @lpm: mask of paths to use
91  * @check: optional callback that determines if results are final
92  * @filter: optional callback to adjust request status based on IRB data
93  * @callback: final callback
94  * @data: user-defined pointer passed to all callbacks
95  * @singlepath: if set, use only one path from @lpm per start I/O
96  * @cancel: non-zero if request was cancelled
97  * @done: non-zero if request was finished
98  * @mask: current path mask
99  * @retries: current number of retries
100  * @drc: delayed return code
101  */
102 struct ccw_request {
103         struct ccw1 *cp;
104         unsigned long timeout;
105         u16 maxretries;
106         u8 lpm;
107         int (*check)(struct ccw_device *, void *);
108         enum io_status (*filter)(struct ccw_device *, void *, struct irb *,
109                                  enum io_status);
110         void (*callback)(struct ccw_device *, void *, int);
111         void *data;
112         unsigned int singlepath:1;
113         /* These fields are used internally. */
114         unsigned int cancel:1;
115         unsigned int done:1;
116         u16 mask;
117         u16 retries;
118         int drc;
119 } __attribute__((packed));
120
121 /*
122  * sense-id response buffer layout
123  */
124 struct senseid {
125         /* common part */
126         u8  reserved;   /* always 0x'FF' */
127         u16 cu_type;    /* control unit type */
128         u8  cu_model;   /* control unit model */
129         u16 dev_type;   /* device type */
130         u8  dev_model;  /* device model */
131         u8  unused;     /* padding byte */
132         /* extended part */
133         struct ciw ciw[MAX_CIWS];       /* variable # of CIWs */
134 }  __attribute__ ((packed, aligned(4)));
135
136 enum cdev_todo {
137         CDEV_TODO_NOTHING,
138         CDEV_TODO_ENABLE_CMF,
139         CDEV_TODO_REBIND,
140         CDEV_TODO_REGISTER,
141         CDEV_TODO_UNREG,
142         CDEV_TODO_UNREG_EVAL,
143 };
144
145 struct ccw_device_private {
146         struct ccw_device *cdev;
147         struct subchannel *sch;
148         int state;              /* device state */
149         atomic_t onoff;
150         struct ccw_dev_id dev_id;       /* device id */
151         struct subchannel_id schid;     /* subchannel number */
152         struct ccw_request req;         /* internal I/O request */
153         int iretry;
154         u8 pgid_valid_mask;             /* mask of valid PGIDs */
155         u8 pgid_todo_mask;              /* mask of PGIDs to be adjusted */
156         struct {
157                 unsigned int fast:1;    /* post with "channel end" */
158                 unsigned int repall:1;  /* report every interrupt status */
159                 unsigned int pgroup:1;  /* do path grouping */
160                 unsigned int force:1;   /* allow forced online */
161                 unsigned int mpath:1;   /* do multipathing */
162         } __attribute__ ((packed)) options;
163         struct {
164                 unsigned int esid:1;        /* Ext. SenseID supported by HW */
165                 unsigned int dosense:1;     /* delayed SENSE required */
166                 unsigned int doverify:1;    /* delayed path verification */
167                 unsigned int donotify:1;    /* call notify function */
168                 unsigned int recog_done:1;  /* dev. recog. complete */
169                 unsigned int fake_irb:1;    /* deliver faked irb */
170                 unsigned int resuming:1;    /* recognition while resume */
171                 unsigned int pgroup:1;      /* pathgroup is set up */
172                 unsigned int mpath:1;       /* multipathing is set up */
173                 unsigned int initialized:1; /* set if initial reference held */
174         } __attribute__((packed)) flags;
175         unsigned long intparm;  /* user interruption parameter */
176         struct qdio_irq *qdio_data;
177         struct irb irb;         /* device status */
178         struct senseid senseid; /* SenseID info */
179         struct pgid pgid[8];    /* path group IDs per chpid*/
180         struct ccw1 iccws[2];   /* ccws for SNID/SID/SPGID commands */
181         struct work_struct todo_work;
182         enum cdev_todo todo;
183         wait_queue_head_t wait_q;
184         struct timer_list timer;
185         void *cmb;                      /* measurement information */
186         struct list_head cmb_list;      /* list of measured devices */
187         u64 cmb_start_time;             /* clock value of cmb reset */
188         void *cmb_wait;                 /* deferred cmb enable/disable */
189 };
190
191 static inline int ssch(struct subchannel_id schid, union orb *addr)
192 {
193         register struct subchannel_id reg1 asm("1") = schid;
194         int ccode = -EIO;
195
196         asm volatile(
197                 "       ssch    0(%2)\n"
198                 "0:     ipm     %0\n"
199                 "       srl     %0,28\n"
200                 "1:\n"
201                 EX_TABLE(0b, 1b)
202                 : "+d" (ccode)
203                 : "d" (reg1), "a" (addr), "m" (*addr)
204                 : "cc", "memory");
205         return ccode;
206 }
207
208 static inline int rsch(struct subchannel_id schid)
209 {
210         register struct subchannel_id reg1 asm("1") = schid;
211         int ccode;
212
213         asm volatile(
214                 "       rsch\n"
215                 "       ipm     %0\n"
216                 "       srl     %0,28"
217                 : "=d" (ccode)
218                 : "d" (reg1)
219                 : "cc", "memory");
220         return ccode;
221 }
222
223 static inline int csch(struct subchannel_id schid)
224 {
225         register struct subchannel_id reg1 asm("1") = schid;
226         int ccode;
227
228         asm volatile(
229                 "       csch\n"
230                 "       ipm     %0\n"
231                 "       srl     %0,28"
232                 : "=d" (ccode)
233                 : "d" (reg1)
234                 : "cc");
235         return ccode;
236 }
237
238 static inline int hsch(struct subchannel_id schid)
239 {
240         register struct subchannel_id reg1 asm("1") = schid;
241         int ccode;
242
243         asm volatile(
244                 "       hsch\n"
245                 "       ipm     %0\n"
246                 "       srl     %0,28"
247                 : "=d" (ccode)
248                 : "d" (reg1)
249                 : "cc");
250         return ccode;
251 }
252
253 static inline int xsch(struct subchannel_id schid)
254 {
255         register struct subchannel_id reg1 asm("1") = schid;
256         int ccode;
257
258         asm volatile(
259                 "       .insn   rre,0xb2760000,%1,0\n"
260                 "       ipm     %0\n"
261                 "       srl     %0,28"
262                 : "=d" (ccode)
263                 : "d" (reg1)
264                 : "cc");
265         return ccode;
266 }
267
268 #endif