1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef CIO_H
14#define CIO_H
15
16
17
18
19struct pmcw {
20 __u32 intparm;
21 __u32 qf:1;
22 __u32 w:1;
23 __u32 isc:3;
24 __u32 res5:3;
25 __u32 ena:1;
26 __u32 lm:2;
27 __u32 mme:2;
28 __u32 mp:1;
29 __u32 tf:1;
30 __u32 dnv:1;
31 __u32 dev:16;
32 __u8 lpm;
33 __u8 pnom;
34 __u8 lpum;
35 __u8 pim;
36 __u16 mbi;
37 __u8 pom;
38 __u8 pam;
39 __u8 chpid[8];
40 __u32 unused1:8;
41 __u32 st:3;
42 __u32 unused2:18;
43 __u32 mbfc:1;
44 __u32 xmwme:1;
45 __u32 csense:1;
46
47
48
49} __attribute__ ((packed));
50
51
52struct 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
64struct scsw {
65 __u16 flags;
66 __u16 ctrl;
67 __u32 cpa;
68 __u8 dstat;
69 __u8 cstat;
70 __u16 count;
71} __attribute__ ((packed));
72
73
74#define SCSW_FCTL_START_FUNC 0x4000
75#define SCSW_FCTL_HALT_FUNC 0x2000
76#define SCSW_FCTL_CLEAR_FUNC 0x1000
77
78
79#define SCSW_ACTL_RESUME_PEND 0x0800
80#define SCSW_ACTL_START_PEND 0x0400
81#define SCSW_ACTL_HALT_PEND 0x0200
82#define SCSW_ACTL_CLEAR_PEND 0x0100
83#define SCSW_ACTL_CH_ACTIVE 0x0080
84#define SCSW_ACTL_DEV_ACTIVE 0x0040
85#define SCSW_ACTL_SUSPENDED 0x0020
86
87
88#define SCSW_SCTL_ALERT 0x0010
89#define SCSW_SCTL_INTERMED 0x0008
90#define SCSW_SCTL_PRIMARY 0x0004
91#define SCSW_SCTL_SECONDARY 0x0002
92#define SCSW_SCTL_STATUS_PEND 0x0001
93
94
95#define SCSW_DSTAT_ATTN 0x80
96#define SCSW_DSTAT_STATMOD 0x40
97#define SCSW_DSTAT_CUEND 0x20
98#define SCSW_DSTAT_BUSY 0x10
99#define SCSW_DSTAT_CHEND 0x08
100#define SCSW_DSTAT_DEVEND 0x04
101#define SCSW_DSTAT_UCHK 0x02
102#define SCSW_DSTAT_UEXCP 0x01
103
104
105#define SCSW_CSTAT_PCINT 0x80
106#define SCSW_CSTAT_BADLEN 0x40
107#define SCSW_CSTAT_PROGCHK 0x20
108#define SCSW_CSTAT_PROTCHK 0x10
109#define SCSW_CSTAT_CHDCHK 0x08
110#define SCSW_CSTAT_CHCCHK 0x04
111#define SCSW_CSTAT_ICCHK 0x02
112#define SCSW_CSTAT_CHAINCHK 0x01
113
114
115
116
117typedef struct schib {
118 struct pmcw pmcw;
119 struct scsw scsw;
120 __u64 mba;
121 __u8 mda[4];
122} __attribute__ ((packed, aligned(4))) Schib;
123
124typedef struct subchannel_id {
125 __u32 cssid:8;
126 __u32:4;
127 __u32 m:1;
128 __u32 ssid:2;
129 __u32 one:1;
130 __u32 sch_no:16;
131} __attribute__ ((packed, aligned(4))) SubChannelId;
132
133struct chsc_header {
134 __u16 length;
135 __u16 code;
136} __attribute__((packed));
137
138typedef struct chsc_area_sda {
139 struct chsc_header request;
140 __u8 reserved1:4;
141 __u8 format:4;
142 __u8 reserved2;
143 __u16 operation_code;
144 __u32 reserved3;
145 __u32 reserved4;
146 __u32 operation_data_area[252];
147 struct chsc_header response;
148 __u32 reserved5:4;
149 __u32 format2:4;
150 __u32 reserved6:24;
151} __attribute__((packed)) ChscAreaSda;
152
153
154
155
156struct tpi_info {
157 struct subchannel_id schid;
158 __u32 intparm;
159 __u32 adapter_IO:1;
160 __u32 reserved2:1;
161 __u32 isc:3;
162 __u32 reserved3:12;
163 __u32 int_type:3;
164 __u32 reserved4:12;
165} __attribute__ ((packed, aligned(4)));
166
167
168typedef struct ccw0 {
169 __u8 cmd_code;
170 __u32 cda:24;
171 __u32 chainData:1;
172 __u32 chain:1;
173 __u32 sli:1;
174 __u32 skip:1;
175 __u32 pci:1;
176 __u32 ida:1;
177 __u32 suspend:1;
178 __u32 mida:1;
179 __u8 reserved;
180 __u16 count;
181} __attribute__ ((packed, aligned(8))) Ccw0;
182
183
184typedef struct ccw1 {
185 __u8 cmd_code;
186 __u8 flags;
187 __u16 count;
188 __u32 cda;
189} __attribute__ ((packed, aligned(8))) Ccw1;
190
191
192#define CCW_FMT0 0x00
193#define CCW_FMT1 0x01
194
195#define CCW_FLAG_DC 0x80
196#define CCW_FLAG_CC 0x40
197#define CCW_FLAG_SLI 0x20
198#define CCW_FLAG_SKIP 0x10
199#define CCW_FLAG_PCI 0x08
200#define CCW_FLAG_IDA 0x04
201#define CCW_FLAG_SUSPEND 0x02
202
203
204#define CCW_CMD_READ_IPL 0x02
205#define CCW_CMD_NOOP 0x03
206#define CCW_CMD_BASIC_SENSE 0x04
207#define CCW_CMD_TIC 0x08
208#define CCW_CMD_SENSE_ID 0xe4
209
210
211#define CCW_CMD_SET_VQ 0x13
212#define CCW_CMD_VDEV_RESET 0x33
213#define CCW_CMD_READ_FEAT 0x12
214#define CCW_CMD_WRITE_FEAT 0x11
215#define CCW_CMD_READ_CONF 0x22
216#define CCW_CMD_WRITE_CONF 0x21
217#define CCW_CMD_WRITE_STATUS 0x31
218#define CCW_CMD_SET_IND 0x43
219#define CCW_CMD_SET_CONF_IND 0x53
220#define CCW_CMD_READ_VQ_CONF 0x32
221
222
223#define CCW_CMD_DASD_READ 0x06
224#define CCW_CMD_DASD_SEEK 0x07
225#define CCW_CMD_DASD_SEARCH_ID_EQ 0x31
226#define CCW_CMD_DASD_READ_MT 0x86
227
228
229
230
231typedef struct cmd_orb {
232 __u32 intparm;
233 __u32 key:4;
234 __u32 spnd:1;
235 __u32 res1:1;
236 __u32 mod:1;
237 __u32 sync:1;
238 __u32 fmt:1;
239 __u32 pfch:1;
240 __u32 isic:1;
241 __u32 alcc:1;
242 __u32 ssic:1;
243 __u32 res2:1;
244 __u32 c64:1;
245 __u32 i2k:1;
246 __u32 lpm:8;
247 __u32 ils:1;
248 __u32 zero:6;
249 __u32 orbx:1;
250 __u32 cpa;
251} __attribute__ ((packed, aligned(4))) CmdOrb;
252
253struct ciw {
254 __u8 type;
255 __u8 command;
256 __u16 count;
257};
258
259#define CU_TYPE_UNKNOWN 0x0000
260#define CU_TYPE_DASD_2107 0x2107
261#define CU_TYPE_VIRTIO 0x3832
262#define CU_TYPE_DASD_3990 0x3990
263
264
265
266
267typedef struct senseid {
268
269 __u8 reserved;
270 __u16 cu_type;
271 __u8 cu_model;
272 __u16 dev_type;
273 __u8 dev_model;
274 __u8 unused;
275
276 struct ciw ciw[62];
277} __attribute__ ((packed, aligned(4))) SenseId;
278
279
280
281
282
283#define SNS_STAT0_CMD_REJECT 0x80
284#define SNS_STAT0_INTERVENTION_REQ 0x40
285#define SNS_STAT0_BUS_OUT_CHECK 0x20
286#define SNS_STAT0_EQUIPMENT_CHECK 0x10
287#define SNS_STAT0_DATA_CHECK 0x08
288#define SNS_STAT0_OVERRUN 0x04
289#define SNS_STAT0_INCOMPL_DOMAIN 0x01
290
291
292#define SNS_STAT1_PERM_ERR 0x80
293#define SNS_STAT1_INV_TRACK_FORMAT 0x40
294#define SNS_STAT1_EOC 0x20
295#define SNS_STAT1_MESSAGE_TO_OPER 0x10
296#define SNS_STAT1_NO_REC_FOUND 0x08
297#define SNS_STAT1_FILE_PROTECTED 0x04
298#define SNS_STAT1_WRITE_INHIBITED 0x02
299#define SNS_STAT1_IMPRECISE_END 0x01
300
301
302#define SNS_STAT2_REQ_INH_WRITE 0x80
303#define SNS_STAT2_CORRECTABLE 0x40
304#define SNS_STAT2_FIRST_LOG_ERR 0x20
305#define SNS_STAT2_ENV_DATA_PRESENT 0x10
306#define SNS_STAT2_IMPRECISE_END 0x04
307
308
309#define SENSE24_FMT_PROG_SYS 0x0
310#define SENSE24_FMT_EQUIPMENT 0x2
311#define SENSE24_FMT_CONTROLLER 0x3
312#define SENSE24_FMT_MISC 0xF
313
314
315typedef struct SenseDataEckdDasd {
316 uint8_t common_status;
317 uint8_t status[2];
318 uint8_t res_count;
319 uint8_t phys_drive_id;
320 uint8_t low_cyl_addr;
321 uint8_t head_high_cyl_addr;
322 uint8_t fmt_msg;
323 uint64_t fmt_dependent_info[2];
324 uint8_t reserved;
325 uint8_t program_action_code;
326 uint16_t config_info;
327 uint8_t mcode_hicyl;
328 uint8_t cyl_head_addr[3];
329} __attribute__ ((packed, aligned(4))) SenseDataEckdDasd;
330
331#define ECKD_SENSE24_GET_FMT(sd) (sd->fmt_msg & 0xF0 >> 4)
332#define ECKD_SENSE24_GET_MSG(sd) (sd->fmt_msg & 0x0F)
333
334#define unit_check(irb) ((irb)->scsw.dstat & SCSW_DSTAT_UCHK)
335#define iface_ctrl_check(irb) ((irb)->scsw.cstat & SCSW_CSTAT_ICCHK)
336
337
338typedef struct irb {
339 struct scsw scsw;
340 __u32 esw[5];
341 __u32 ecw[8];
342 __u32 emw[8];
343} __attribute__ ((packed, aligned(4))) Irb;
344
345
346typedef struct CcwSeekData {
347 uint16_t reserved;
348 uint16_t cyl;
349 uint16_t head;
350} __attribute__((packed)) CcwSeekData;
351
352
353typedef struct CcwSearchIdData {
354 uint16_t cyl;
355 uint16_t head;
356 uint8_t record;
357} __attribute__((packed)) CcwSearchIdData;
358
359int enable_mss_facility(void);
360void enable_subchannel(SubChannelId schid);
361uint16_t cu_type(SubChannelId schid);
362int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
363 uint16_t data_size);
364int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt);
365
366
367
368
369
370static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
371{
372 register struct subchannel_id reg1 asm ("1") = schid;
373 int ccode = -EIO;
374
375 asm volatile(
376 " stsch 0(%3)\n"
377 "0: ipm %0\n"
378 " srl %0,28\n"
379 "1:\n"
380 : "+d" (ccode), "=m" (*addr)
381 : "d" (reg1), "a" (addr)
382 : "cc");
383 return ccode;
384}
385
386static inline int msch(struct subchannel_id schid, struct schib *addr)
387{
388 register struct subchannel_id reg1 asm ("1") = schid;
389 int ccode;
390
391 asm volatile(
392 " msch 0(%2)\n"
393 " ipm %0\n"
394 " srl %0,28"
395 : "=d" (ccode)
396 : "d" (reg1), "a" (addr), "m" (*addr)
397 : "cc");
398 return ccode;
399}
400
401static inline int msch_err(struct subchannel_id schid, struct schib *addr)
402{
403 register struct subchannel_id reg1 asm ("1") = schid;
404 int ccode = -EIO;
405
406 asm volatile(
407 " msch 0(%2)\n"
408 "0: ipm %0\n"
409 " srl %0,28\n"
410 "1:\n"
411 : "+d" (ccode)
412 : "d" (reg1), "a" (addr), "m" (*addr)
413 : "cc");
414 return ccode;
415}
416
417static inline int tsch(struct subchannel_id schid, struct irb *addr)
418{
419 register struct subchannel_id reg1 asm ("1") = schid;
420 int ccode;
421
422 asm volatile(
423 " tsch 0(%3)\n"
424 " ipm %0\n"
425 " srl %0,28"
426 : "=d" (ccode), "=m" (*addr)
427 : "d" (reg1), "a" (addr)
428 : "cc");
429 return ccode;
430}
431
432static inline int ssch(struct subchannel_id schid, struct cmd_orb *addr)
433{
434 register struct subchannel_id reg1 asm("1") = schid;
435 int ccode = -EIO;
436
437 asm volatile(
438 " ssch 0(%2)\n"
439 "0: ipm %0\n"
440 " srl %0,28\n"
441 "1:\n"
442 : "+d" (ccode)
443 : "d" (reg1), "a" (addr), "m" (*addr)
444 : "cc", "memory");
445 return ccode;
446}
447
448static inline int csch(struct subchannel_id schid)
449{
450 register struct subchannel_id reg1 asm("1") = schid;
451 int ccode;
452
453 asm volatile(
454 " csch\n"
455 " ipm %0\n"
456 " srl %0,28"
457 : "=d" (ccode)
458 : "d" (reg1)
459 : "cc");
460 return ccode;
461}
462
463static inline int tpi(struct tpi_info *addr)
464{
465 int ccode;
466
467 asm volatile(
468 " tpi 0(%2)\n"
469 " ipm %0\n"
470 " srl %0,28"
471 : "=d" (ccode), "=m" (*addr)
472 : "a" (addr)
473 : "cc");
474 return ccode;
475}
476
477static inline int chsc(void *chsc_area)
478{
479 typedef struct { char _[4096]; } addr_type;
480 int cc;
481
482 asm volatile(
483 " .insn rre,0xb25f0000,%2,0\n"
484 " ipm %0\n"
485 " srl %0,28\n"
486 : "=d" (cc), "=m" (*(addr_type *) chsc_area)
487 : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
488 : "cc");
489 return cc;
490}
491
492#endif
493