classmate-laptop: add support for Classmate PC ACPI devices
[safe/jmp/linux-2.6] / 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  * @mask: current path mask
96  * @retries: current number of retries
97  * @drc: delayed return code
98  * @cancel: non-zero if request was cancelled
99  * @done: non-zero if request was finished
100  */
101 struct ccw_request {
102         struct ccw1 *cp;
103         unsigned long timeout;
104         u16 maxretries;
105         u8 lpm;
106         int (*check)(struct ccw_device *, void *);
107         enum io_status (*filter)(struct ccw_device *, void *, struct irb *,
108                                  enum io_status);
109         void (*callback)(struct ccw_device *, void *, int);
110         void *data;
111         /* These fields are used internally. */
112         u16 mask;
113         u16 retries;
114         int drc;
115         int cancel:1;
116         int done:1;
117 } __attribute__((packed));
118
119 /*
120  * sense-id response buffer layout
121  */
122 struct senseid {
123         /* common part */
124         u8  reserved;   /* always 0x'FF' */
125         u16 cu_type;    /* control unit type */
126         u8  cu_model;   /* control unit model */
127         u16 dev_type;   /* device type */
128         u8  dev_model;  /* device model */
129         u8  unused;     /* padding byte */
130         /* extended part */
131         struct ciw ciw[MAX_CIWS];       /* variable # of CIWs */
132 }  __attribute__ ((packed, aligned(4)));
133
134 enum cdev_todo {
135         CDEV_TODO_NOTHING,
136         CDEV_TODO_ENABLE_CMF,
137         CDEV_TODO_REBIND,
138         CDEV_TODO_REGISTER,
139         CDEV_TODO_UNREG,
140         CDEV_TODO_UNREG_EVAL,
141 };
142
143 struct ccw_device_private {
144         struct ccw_device *cdev;
145         struct subchannel *sch;
146         int state;              /* device state */
147         atomic_t onoff;
148         struct ccw_dev_id dev_id;       /* device id */
149         struct subchannel_id schid;     /* subchannel number */
150         struct ccw_request req;         /* internal I/O request */
151         int iretry;
152         u8 pgid_valid_mask;             /* mask of valid PGIDs */
153         struct {
154                 unsigned int fast:1;    /* post with "channel end" */
155                 unsigned int repall:1;  /* report every interrupt status */
156                 unsigned int pgroup:1;  /* do path grouping */
157                 unsigned int force:1;   /* allow forced online */
158                 unsigned int mpath:1;   /* do multipathing */
159         } __attribute__ ((packed)) options;
160         struct {
161                 unsigned int esid:1;        /* Ext. SenseID supported by HW */
162                 unsigned int dosense:1;     /* delayed SENSE required */
163                 unsigned int doverify:1;    /* delayed path verification */
164                 unsigned int donotify:1;    /* call notify function */
165                 unsigned int recog_done:1;  /* dev. recog. complete */
166                 unsigned int fake_irb:1;    /* deliver faked irb */
167                 unsigned int resuming:1;    /* recognition while resume */
168                 unsigned int pgroup:1;      /* pathgroup is set up */
169                 unsigned int mpath:1;       /* multipathing is set up */
170                 unsigned int initialized:1; /* set if initial reference held */
171         } __attribute__((packed)) flags;
172         unsigned long intparm;  /* user interruption parameter */
173         struct qdio_irq *qdio_data;
174         struct irb irb;         /* device status */
175         struct senseid senseid; /* SenseID info */
176         struct pgid pgid[8];    /* path group IDs per chpid*/
177         struct ccw1 iccws[2];   /* ccws for SNID/SID/SPGID commands */
178         struct work_struct todo_work;
179         enum cdev_todo todo;
180         wait_queue_head_t wait_q;
181         struct timer_list timer;
182         void *cmb;                      /* measurement information */
183         struct list_head cmb_list;      /* list of measured devices */
184         u64 cmb_start_time;             /* clock value of cmb reset */
185         void *cmb_wait;                 /* deferred cmb enable/disable */
186 };
187
188 static inline int ssch(struct subchannel_id schid, union orb *addr)
189 {
190         register struct subchannel_id reg1 asm("1") = schid;
191         int ccode = -EIO;
192
193         asm volatile(
194                 "       ssch    0(%2)\n"
195                 "0:     ipm     %0\n"
196                 "       srl     %0,28\n"
197                 "1:\n"
198                 EX_TABLE(0b, 1b)
199                 : "+d" (ccode)
200                 : "d" (reg1), "a" (addr), "m" (*addr)
201                 : "cc", "memory");
202         return ccode;
203 }
204
205 static inline int rsch(struct subchannel_id schid)
206 {
207         register struct subchannel_id reg1 asm("1") = schid;
208         int ccode;
209
210         asm volatile(
211                 "       rsch\n"
212                 "       ipm     %0\n"
213                 "       srl     %0,28"
214                 : "=d" (ccode)
215                 : "d" (reg1)
216                 : "cc", "memory");
217         return ccode;
218 }
219
220 static inline int csch(struct subchannel_id schid)
221 {
222         register struct subchannel_id reg1 asm("1") = schid;
223         int ccode;
224
225         asm volatile(
226                 "       csch\n"
227                 "       ipm     %0\n"
228                 "       srl     %0,28"
229                 : "=d" (ccode)
230                 : "d" (reg1)
231                 : "cc");
232         return ccode;
233 }
234
235 static inline int hsch(struct subchannel_id schid)
236 {
237         register struct subchannel_id reg1 asm("1") = schid;
238         int ccode;
239
240         asm volatile(
241                 "       hsch\n"
242                 "       ipm     %0\n"
243                 "       srl     %0,28"
244                 : "=d" (ccode)
245                 : "d" (reg1)
246                 : "cc");
247         return ccode;
248 }
249
250 static inline int xsch(struct subchannel_id schid)
251 {
252         register struct subchannel_id reg1 asm("1") = schid;
253         int ccode;
254
255         asm volatile(
256                 "       .insn   rre,0xb2760000,%1,0\n"
257                 "       ipm     %0\n"
258                 "       srl     %0,28"
259                 : "=d" (ccode)
260                 : "d" (reg1)
261                 : "cc");
262         return ccode;
263 }
264
265 #endif