]>
Commit | Line | Data |
---|---|---|
1e17c2c1 AG |
1 | /* |
2 | * Channel IO definitions | |
3 | * | |
4 | * Copyright (c) 2013 Alexander Graf <[email protected]> | |
5 | * | |
6 | * Inspired by various s390 headers in Linux 3.9. | |
7 | * | |
8 | * This work is licensed under the terms of the GNU GPL, version 2 or (at | |
9 | * your option) any later version. See the COPYING file in the top-level | |
10 | * directory. | |
11 | */ | |
12 | ||
13 | #ifndef CIO_H | |
14 | #define CIO_H | |
15 | ||
16 | /* | |
17 | * path management control word | |
18 | */ | |
19 | struct pmcw { | |
20 | __u32 intparm; /* interruption parameter */ | |
21 | __u32 qf : 1; /* qdio facility */ | |
22 | __u32 w : 1; | |
23 | __u32 isc : 3; /* interruption sublass */ | |
24 | __u32 res5 : 3; /* reserved zeros */ | |
25 | __u32 ena : 1; /* enabled */ | |
26 | __u32 lm : 2; /* limit mode */ | |
27 | __u32 mme : 2; /* measurement-mode enable */ | |
28 | __u32 mp : 1; /* multipath mode */ | |
29 | __u32 tf : 1; /* timing facility */ | |
30 | __u32 dnv : 1; /* device number valid */ | |
31 | __u32 dev : 16; /* device number */ | |
32 | __u8 lpm; /* logical path mask */ | |
33 | __u8 pnom; /* path not operational mask */ | |
34 | __u8 lpum; /* last path used mask */ | |
35 | __u8 pim; /* path installed mask */ | |
36 | __u16 mbi; /* measurement-block index */ | |
37 | __u8 pom; /* path operational mask */ | |
38 | __u8 pam; /* path available mask */ | |
39 | __u8 chpid[8]; /* CHPID 0-7 (if available) */ | |
40 | __u32 unused1 : 8; /* reserved zeros */ | |
41 | __u32 st : 3; /* subchannel type */ | |
42 | __u32 unused2 : 18; /* reserved zeros */ | |
43 | __u32 mbfc : 1; /* measurement block format control */ | |
44 | __u32 xmwme : 1; /* extended measurement word mode enable */ | |
45 | __u32 csense : 1; /* concurrent sense; can be enabled ...*/ | |
46 | /* ... per MSCH, however, if facility */ | |
47 | /* ... is not installed, this results */ | |
48 | /* ... in an operand exception. */ | |
49 | } __attribute__ ((packed)); | |
50 | ||
51 | /* Target SCHIB configuration. */ | |
52 | struct schib_config { | |
53 | __u64 mba; | |
54 | __u32 intparm; | |
55 | __u16 mbi; | |
56 | __u32 isc:3; | |
57 | __u32 ena:1; | |
58 | __u32 mme:2; | |
59 | __u32 mp:1; | |
60 | __u32 csense:1; | |
61 | __u32 mbfc:1; | |
62 | } __attribute__ ((packed)); | |
63 | ||
64 | struct scsw { | |
65 | __u16 flags; | |
66 | __u16 ctrl; | |
67 | __u32 cpa; | |
68 | __u8 dstat; | |
69 | __u8 cstat; | |
70 | __u16 count; | |
71 | } __attribute__ ((packed)); | |
72 | ||
73 | #define SCSW_FCTL_CLEAR_FUNC 0x1000 | |
74 | #define SCSW_FCTL_HALT_FUNC 0x2000 | |
75 | #define SCSW_FCTL_START_FUNC 0x4000 | |
76 | ||
77 | /* | |
78 | * subchannel information block | |
79 | */ | |
80 | struct schib { | |
81 | struct pmcw pmcw; /* path management control word */ | |
82 | struct scsw scsw; /* subchannel status word */ | |
83 | __u64 mba; /* measurement block address */ | |
84 | __u8 mda[4]; /* model dependent area */ | |
85 | } __attribute__ ((packed,aligned(4))); | |
86 | ||
87 | struct subchannel_id { | |
88 | __u32 cssid : 8; | |
89 | __u32 : 4; | |
90 | __u32 m : 1; | |
91 | __u32 ssid : 2; | |
92 | __u32 one : 1; | |
93 | __u32 sch_no : 16; | |
94 | } __attribute__ ((packed, aligned(4))); | |
95 | ||
c8cda874 DD |
96 | struct chsc_header { |
97 | __u16 length; | |
98 | __u16 code; | |
99 | } __attribute__((packed)); | |
100 | ||
101 | struct chsc_area_sda { | |
102 | struct chsc_header request; | |
103 | __u8 reserved1:4; | |
104 | __u8 format:4; | |
105 | __u8 reserved2; | |
106 | __u16 operation_code; | |
107 | __u32 reserved3; | |
108 | __u32 reserved4; | |
109 | __u32 operation_data_area[252]; | |
110 | struct chsc_header response; | |
111 | __u32 reserved5:4; | |
112 | __u32 format2:4; | |
113 | __u32 reserved6:24; | |
114 | } __attribute__((packed)); | |
115 | ||
1e17c2c1 AG |
116 | /* |
117 | * TPI info structure | |
118 | */ | |
119 | struct tpi_info { | |
120 | struct subchannel_id schid; | |
121 | __u32 intparm; /* interruption parameter */ | |
122 | __u32 adapter_IO : 1; | |
123 | __u32 reserved2 : 1; | |
124 | __u32 isc : 3; | |
125 | __u32 reserved3 : 12; | |
126 | __u32 int_type : 3; | |
127 | __u32 reserved4 : 12; | |
128 | } __attribute__ ((packed)); | |
129 | ||
130 | /* channel command word (type 1) */ | |
131 | struct ccw1 { | |
132 | __u8 cmd_code; | |
133 | __u8 flags; | |
134 | __u16 count; | |
135 | __u32 cda; | |
3a1e4561 | 136 | } __attribute__ ((packed, aligned(8))); |
1e17c2c1 AG |
137 | |
138 | #define CCW_FLAG_DC 0x80 | |
139 | #define CCW_FLAG_CC 0x40 | |
140 | #define CCW_FLAG_SLI 0x20 | |
141 | #define CCW_FLAG_SKIP 0x10 | |
142 | #define CCW_FLAG_PCI 0x08 | |
143 | #define CCW_FLAG_IDA 0x04 | |
144 | #define CCW_FLAG_SUSPEND 0x02 | |
145 | ||
146 | #define CCW_CMD_NOOP 0x03 | |
147 | #define CCW_CMD_BASIC_SENSE 0x04 | |
148 | #define CCW_CMD_TIC 0x08 | |
149 | #define CCW_CMD_SENSE_ID 0xe4 | |
150 | ||
151 | #define CCW_CMD_SET_VQ 0x13 | |
152 | #define CCW_CMD_VDEV_RESET 0x33 | |
153 | #define CCW_CMD_READ_FEAT 0x12 | |
154 | #define CCW_CMD_WRITE_FEAT 0x11 | |
155 | #define CCW_CMD_READ_CONF 0x22 | |
156 | #define CCW_CMD_WRITE_CONF 0x21 | |
157 | #define CCW_CMD_WRITE_STATUS 0x31 | |
158 | #define CCW_CMD_SET_IND 0x43 | |
159 | #define CCW_CMD_SET_CONF_IND 0x53 | |
160 | #define CCW_CMD_READ_VQ_CONF 0x32 | |
161 | ||
162 | /* | |
163 | * Command-mode operation request block | |
164 | */ | |
165 | struct cmd_orb { | |
166 | __u32 intparm; /* interruption parameter */ | |
167 | __u32 key:4; /* flags, like key, suspend control, etc. */ | |
168 | __u32 spnd:1; /* suspend control */ | |
169 | __u32 res1:1; /* reserved */ | |
170 | __u32 mod:1; /* modification control */ | |
171 | __u32 sync:1; /* synchronize control */ | |
172 | __u32 fmt:1; /* format control */ | |
173 | __u32 pfch:1; /* prefetch control */ | |
174 | __u32 isic:1; /* initial-status-interruption control */ | |
175 | __u32 alcc:1; /* address-limit-checking control */ | |
176 | __u32 ssic:1; /* suppress-suspended-interr. control */ | |
177 | __u32 res2:1; /* reserved */ | |
178 | __u32 c64:1; /* IDAW/QDIO 64 bit control */ | |
179 | __u32 i2k:1; /* IDAW 2/4kB block size control */ | |
180 | __u32 lpm:8; /* logical path mask */ | |
181 | __u32 ils:1; /* incorrect length */ | |
182 | __u32 zero:6; /* reserved zeros */ | |
183 | __u32 orbx:1; /* ORB extension control */ | |
184 | __u32 cpa; /* channel program address */ | |
185 | } __attribute__ ((packed, aligned(4))); | |
186 | ||
187 | struct ciw { | |
188 | __u8 type; | |
189 | __u8 command; | |
190 | __u16 count; | |
191 | }; | |
192 | ||
193 | /* | |
194 | * sense-id response buffer layout | |
195 | */ | |
196 | struct senseid { | |
197 | /* common part */ | |
198 | __u8 reserved; /* always 0x'FF' */ | |
199 | __u16 cu_type; /* control unit type */ | |
200 | __u8 cu_model; /* control unit model */ | |
201 | __u16 dev_type; /* device type */ | |
202 | __u8 dev_model; /* device model */ | |
203 | __u8 unused; /* padding byte */ | |
204 | /* extended part */ | |
205 | struct ciw ciw[62]; | |
206 | } __attribute__ ((packed, aligned(4))); | |
207 | ||
208 | /* interruption response block */ | |
209 | struct irb { | |
210 | struct scsw scsw; | |
211 | __u32 esw[5]; | |
212 | __u32 ecw[8]; | |
213 | __u32 emw[8]; | |
214 | } __attribute__ ((packed, aligned(4))); | |
215 | ||
216 | /* | |
217 | * Some S390 specific IO instructions as inline | |
218 | */ | |
219 | ||
220 | static inline int stsch_err(struct subchannel_id schid, struct schib *addr) | |
221 | { | |
222 | register struct subchannel_id reg1 asm ("1") = schid; | |
223 | int ccode = -EIO; | |
224 | ||
225 | asm volatile( | |
226 | " stsch 0(%3)\n" | |
227 | "0: ipm %0\n" | |
228 | " srl %0,28\n" | |
229 | "1:\n" | |
230 | : "+d" (ccode), "=m" (*addr) | |
231 | : "d" (reg1), "a" (addr) | |
232 | : "cc"); | |
233 | return ccode; | |
234 | } | |
235 | ||
236 | static inline int msch(struct subchannel_id schid, struct schib *addr) | |
237 | { | |
238 | register struct subchannel_id reg1 asm ("1") = schid; | |
239 | int ccode; | |
240 | ||
241 | asm volatile( | |
242 | " msch 0(%2)\n" | |
243 | " ipm %0\n" | |
244 | " srl %0,28" | |
245 | : "=d" (ccode) | |
246 | : "d" (reg1), "a" (addr), "m" (*addr) | |
247 | : "cc"); | |
248 | return ccode; | |
249 | } | |
250 | ||
251 | static inline int msch_err(struct subchannel_id schid, struct schib *addr) | |
252 | { | |
253 | register struct subchannel_id reg1 asm ("1") = schid; | |
254 | int ccode = -EIO; | |
255 | ||
256 | asm volatile( | |
257 | " msch 0(%2)\n" | |
258 | "0: ipm %0\n" | |
259 | " srl %0,28\n" | |
260 | "1:\n" | |
261 | : "+d" (ccode) | |
262 | : "d" (reg1), "a" (addr), "m" (*addr) | |
263 | : "cc"); | |
264 | return ccode; | |
265 | } | |
266 | ||
267 | static inline int tsch(struct subchannel_id schid, struct irb *addr) | |
268 | { | |
269 | register struct subchannel_id reg1 asm ("1") = schid; | |
270 | int ccode; | |
271 | ||
272 | asm volatile( | |
273 | " tsch 0(%3)\n" | |
274 | " ipm %0\n" | |
275 | " srl %0,28" | |
276 | : "=d" (ccode), "=m" (*addr) | |
277 | : "d" (reg1), "a" (addr) | |
278 | : "cc"); | |
279 | return ccode; | |
280 | } | |
281 | ||
282 | static inline int ssch(struct subchannel_id schid, struct cmd_orb *addr) | |
283 | { | |
284 | register struct subchannel_id reg1 asm("1") = schid; | |
285 | int ccode = -EIO; | |
286 | ||
287 | asm volatile( | |
288 | " ssch 0(%2)\n" | |
289 | "0: ipm %0\n" | |
290 | " srl %0,28\n" | |
291 | "1:\n" | |
292 | : "+d" (ccode) | |
293 | : "d" (reg1), "a" (addr), "m" (*addr) | |
294 | : "cc", "memory"); | |
295 | return ccode; | |
296 | } | |
297 | ||
298 | static inline int csch(struct subchannel_id schid) | |
299 | { | |
300 | register struct subchannel_id reg1 asm("1") = schid; | |
301 | int ccode; | |
302 | ||
303 | asm volatile( | |
304 | " csch\n" | |
305 | " ipm %0\n" | |
306 | " srl %0,28" | |
307 | : "=d" (ccode) | |
308 | : "d" (reg1) | |
309 | : "cc"); | |
310 | return ccode; | |
311 | } | |
312 | ||
313 | static inline int tpi(struct tpi_info *addr) | |
314 | { | |
315 | int ccode; | |
316 | ||
317 | asm volatile( | |
318 | " tpi 0(%2)\n" | |
319 | " ipm %0\n" | |
320 | " srl %0,28" | |
321 | : "=d" (ccode), "=m" (*addr) | |
322 | : "a" (addr) | |
323 | : "cc"); | |
324 | return ccode; | |
325 | } | |
326 | ||
327 | static inline int chsc(void *chsc_area) | |
328 | { | |
329 | typedef struct { char _[4096]; } addr_type; | |
330 | int cc; | |
331 | ||
332 | asm volatile( | |
333 | " .insn rre,0xb25f0000,%2,0\n" | |
334 | " ipm %0\n" | |
335 | " srl %0,28\n" | |
336 | : "=d" (cc), "=m" (*(addr_type *) chsc_area) | |
337 | : "d" (chsc_area), "m" (*(addr_type *) chsc_area) | |
338 | : "cc"); | |
339 | return cc; | |
340 | } | |
341 | ||
342 | #endif /* CIO_H */ |