xref: /openbmc/qemu/pc-bios/s390-ccw/cio.h (revision 4c46fe2e)
1 /*
2  * Channel IO definitions
3  *
4  * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
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 subclass */
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 /* Function Control */
74 #define SCSW_FCTL_START_FUNC 0x4000
75 #define SCSW_FCTL_HALT_FUNC 0x2000
76 #define SCSW_FCTL_CLEAR_FUNC 0x1000
77 
78 /* Activity Control */
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 /* Status Control */
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 /* SCSW Device Status Flags */
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 /* SCSW Subchannel Status Flags */
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  * subchannel information block
116  */
117 typedef struct schib {
118     struct pmcw pmcw;     /* path management control word */
119     struct scsw scsw;     /* subchannel status word */
120     u64 mba;              /* measurement block address */
121     u8 mda[4];            /* model dependent area */
122 } __attribute__ ((packed, aligned(4))) Schib;
123 
124 typedef struct subchannel_id {
125     union {
126         struct {
127             u16 cssid:8;
128             u16 reserved:4;
129             u16 m:1;
130             u16 ssid:2;
131             u16 one:1;
132         };
133         u16 sch_id;
134     };
135     u16 sch_no;
136 } __attribute__ ((packed, aligned(4))) SubChannelId;
137 
138 struct chsc_header {
139     u16 length;
140     u16 code;
141 } __attribute__((packed));
142 
143 typedef struct chsc_area_sda {
144     struct chsc_header request;
145     u8 reserved1:4;
146     u8 format:4;
147     u8 reserved2;
148     u16 operation_code;
149     u32 reserved3;
150     u32 reserved4;
151     u32 operation_data_area[252];
152     struct chsc_header response;
153     u32 reserved5:4;
154     u32 format2:4;
155     u32 reserved6:24;
156 } __attribute__((packed)) ChscAreaSda;
157 
158 /*
159  * TPI info structure
160  */
161 struct tpi_info {
162     struct subchannel_id schid;
163     u32 intparm;      /* interruption parameter */
164     u32 adapter_IO:1;
165     u32 reserved2:1;
166     u32 isc:3;
167     u32 reserved3:12;
168     u32 int_type:3;
169     u32 reserved4:12;
170 } __attribute__ ((packed, aligned(4)));
171 
172 /* channel command word (format 0) */
173 typedef struct ccw0 {
174     u8 cmd_code;
175     u32 cda:24;
176     u32 chainData:1;
177     u32 chain:1;
178     u32 sli:1;
179     u32 skip:1;
180     u32 pci:1;
181     u32 ida:1;
182     u32 suspend:1;
183     u32 mida:1;
184     u8 reserved;
185     u16 count;
186 } __attribute__ ((packed, aligned(8))) Ccw0;
187 
188 /* channel command word (format 1) */
189 typedef struct ccw1 {
190     u8 cmd_code;
191     u8 flags;
192     u16 count;
193     u32 cda;
194 } __attribute__ ((packed, aligned(8))) Ccw1;
195 
196 /* do_cio() CCW formats */
197 #define CCW_FMT0                 0x00
198 #define CCW_FMT1                 0x01
199 
200 #define CCW_FLAG_DC              0x80
201 #define CCW_FLAG_CC              0x40
202 #define CCW_FLAG_SLI             0x20
203 #define CCW_FLAG_SKIP            0x10
204 #define CCW_FLAG_PCI             0x08
205 #define CCW_FLAG_IDA             0x04
206 #define CCW_FLAG_SUSPEND         0x02
207 
208 /* Common CCW commands */
209 #define CCW_CMD_READ_IPL         0x02
210 #define CCW_CMD_NOOP             0x03
211 #define CCW_CMD_BASIC_SENSE      0x04
212 #define CCW_CMD_TIC              0x08
213 #define CCW_CMD_SENSE_ID         0xe4
214 
215 /* Virtio CCW commands */
216 #define CCW_CMD_SET_VQ           0x13
217 #define CCW_CMD_VDEV_RESET       0x33
218 #define CCW_CMD_READ_FEAT        0x12
219 #define CCW_CMD_WRITE_FEAT       0x11
220 #define CCW_CMD_READ_CONF        0x22
221 #define CCW_CMD_WRITE_CONF       0x21
222 #define CCW_CMD_WRITE_STATUS     0x31
223 #define CCW_CMD_SET_IND          0x43
224 #define CCW_CMD_SET_CONF_IND     0x53
225 #define CCW_CMD_READ_VQ_CONF     0x32
226 
227 /* DASD CCW commands */
228 #define CCW_CMD_DASD_READ             0x06
229 #define CCW_CMD_DASD_SEEK             0x07
230 #define CCW_CMD_DASD_SEARCH_ID_EQ     0x31
231 #define CCW_CMD_DASD_READ_MT          0x86
232 
233 /*
234  * Command-mode operation request block
235  */
236 typedef struct cmd_orb {
237     u32 intparm;    /* interruption parameter */
238     u32 key:4;      /* flags, like key, suspend control, etc. */
239     u32 spnd:1;     /* suspend control */
240     u32 res1:1;     /* reserved */
241     u32 mod:1;      /* modification control */
242     u32 sync:1;     /* synchronize control */
243     u32 fmt:1;      /* format control */
244     u32 pfch:1;     /* prefetch control */
245     u32 isic:1;     /* initial-status-interruption control */
246     u32 alcc:1;     /* address-limit-checking control */
247     u32 ssic:1;     /* suppress-suspended-interr. control */
248     u32 res2:1;     /* reserved */
249     u32 c64:1;      /* IDAW/QDIO 64 bit control  */
250     u32 i2k:1;      /* IDAW 2/4kB block size control */
251     u32 lpm:8;      /* logical path mask */
252     u32 ils:1;      /* incorrect length */
253     u32 zero:6;     /* reserved zeros */
254     u32 orbx:1;     /* ORB extension control */
255     u32 cpa;        /* channel program address */
256 }  __attribute__ ((packed, aligned(4))) CmdOrb;
257 
258 struct ciw {
259     u8 type;
260     u8 command;
261     u16 count;
262 };
263 
264 #define CU_TYPE_UNKNOWN         0x0000
265 #define CU_TYPE_DASD_2107       0x2107
266 #define CU_TYPE_VIRTIO          0x3832
267 #define CU_TYPE_DASD_3990       0x3990
268 
269 /*
270  * sense-id response buffer layout
271  */
272 typedef struct senseid {
273     /* common part */
274     u8  reserved;   /* always 0x'FF' */
275     u16 cu_type;    /* control unit type */
276     u8  cu_model;   /* control unit model */
277     u16 dev_type;   /* device type */
278     u8  dev_model;  /* device model */
279     u8  unused;     /* padding byte */
280     /* extended part */
281     struct ciw ciw[62];
282 }  __attribute__ ((packed, aligned(4))) SenseId;
283 
284 /*
285  * architected values for first sense byte - common_status. Bits 0-5 of this
286  * field are common to all device types.
287  */
288 #define SNS_STAT0_CMD_REJECT         0x80
289 #define SNS_STAT0_INTERVENTION_REQ   0x40
290 #define SNS_STAT0_BUS_OUT_CHECK      0x20
291 #define SNS_STAT0_EQUIPMENT_CHECK    0x10
292 #define SNS_STAT0_DATA_CHECK         0x08
293 #define SNS_STAT0_OVERRUN            0x04
294 #define SNS_STAT0_INCOMPL_DOMAIN     0x01
295 
296 /* ECKD DASD status[0] byte */
297 #define SNS_STAT1_PERM_ERR           0x80
298 #define SNS_STAT1_INV_TRACK_FORMAT   0x40
299 #define SNS_STAT1_EOC                0x20
300 #define SNS_STAT1_MESSAGE_TO_OPER    0x10
301 #define SNS_STAT1_NO_REC_FOUND       0x08
302 #define SNS_STAT1_FILE_PROTECTED     0x04
303 #define SNS_STAT1_WRITE_INHIBITED    0x02
304 #define SNS_STAT1_IMPRECISE_END      0x01
305 
306 /* ECKD DASD status[1] byte */
307 #define SNS_STAT2_REQ_INH_WRITE      0x80
308 #define SNS_STAT2_CORRECTABLE        0x40
309 #define SNS_STAT2_FIRST_LOG_ERR      0x20
310 #define SNS_STAT2_ENV_DATA_PRESENT   0x10
311 #define SNS_STAT2_IMPRECISE_END      0x04
312 
313 /* ECKD DASD 24-byte Sense fmt_msg codes */
314 #define SENSE24_FMT_PROG_SYS    0x0
315 #define SENSE24_FMT_EQUIPMENT   0x2
316 #define SENSE24_FMT_CONTROLLER  0x3
317 #define SENSE24_FMT_MISC        0xF
318 
319 /* basic sense response buffer layout */
320 typedef struct SenseDataEckdDasd {
321     uint8_t common_status;
322     uint8_t status[2];
323     uint8_t res_count;
324     uint8_t phys_drive_id;
325     uint8_t low_cyl_addr;
326     uint8_t head_high_cyl_addr;
327     uint8_t fmt_msg;
328     uint64_t fmt_dependent_info[2];
329     uint8_t reserved;
330     uint8_t program_action_code;
331     uint16_t config_info;
332     uint8_t mcode_hicyl;
333     uint8_t cyl_head_addr[3];
334 }  __attribute__ ((packed, aligned(4))) SenseDataEckdDasd;
335 
336 #define ECKD_SENSE24_GET_FMT(sd)     (sd->fmt_msg & 0xF0 >> 4)
337 #define ECKD_SENSE24_GET_MSG(sd)     (sd->fmt_msg & 0x0F)
338 
339 #define unit_check(irb)         ((irb)->scsw.dstat & SCSW_DSTAT_UCHK)
340 #define iface_ctrl_check(irb)   ((irb)->scsw.cstat & SCSW_CSTAT_ICCHK)
341 
342 /* interruption response block */
343 typedef struct irb {
344     struct scsw scsw;
345     u32 esw[5];
346     u32 ecw[8];
347     u32 emw[8];
348 }  __attribute__ ((packed, aligned(4))) Irb;
349 
350 /* Used for SEEK ccw commands */
351 typedef struct CcwSeekData {
352     uint16_t reserved;
353     uint16_t cyl;
354     uint16_t head;
355 } __attribute__((packed)) CcwSeekData;
356 
357 /* Used for SEARCH ID ccw commands */
358 typedef struct CcwSearchIdData {
359     uint16_t cyl;
360     uint16_t head;
361     uint8_t record;
362 } __attribute__((packed)) CcwSearchIdData;
363 
364 int enable_mss_facility(void);
365 void enable_subchannel(SubChannelId schid);
366 uint16_t cu_type(SubChannelId schid);
367 int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
368                  uint16_t data_size);
369 int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt);
370 
371 /*
372  * Some S390 specific IO instructions as inline
373  */
374 
375 static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
376 {
377     register struct subchannel_id reg1 asm ("1") = schid;
378     int ccode = -EIO;
379 
380     asm volatile(
381         "    stsch    0(%3)\n"
382         "0:  ipm    %0\n"
383         "    srl    %0,28\n"
384         "1:\n"
385         : "+d" (ccode), "=m" (*addr)
386         : "d" (reg1), "a" (addr)
387         : "cc");
388     return ccode;
389 }
390 
391 static inline int msch(struct subchannel_id schid, struct schib *addr)
392 {
393     register struct subchannel_id reg1 asm ("1") = schid;
394     int ccode;
395 
396     asm volatile(
397         "    msch    0(%2)\n"
398         "    ipm    %0\n"
399         "    srl    %0,28"
400         : "=d" (ccode)
401         : "d" (reg1), "a" (addr), "m" (*addr)
402         : "cc");
403     return ccode;
404 }
405 
406 static inline int msch_err(struct subchannel_id schid, struct schib *addr)
407 {
408     register struct subchannel_id reg1 asm ("1") = schid;
409     int ccode = -EIO;
410 
411     asm volatile(
412         "    msch    0(%2)\n"
413         "0:  ipm    %0\n"
414         "    srl    %0,28\n"
415         "1:\n"
416         : "+d" (ccode)
417         : "d" (reg1), "a" (addr), "m" (*addr)
418         : "cc");
419     return ccode;
420 }
421 
422 static inline int tsch(struct subchannel_id schid, struct irb *addr)
423 {
424     register struct subchannel_id reg1 asm ("1") = schid;
425     int ccode;
426 
427     asm volatile(
428         "    tsch    0(%3)\n"
429         "    ipm    %0\n"
430         "    srl    %0,28"
431         : "=d" (ccode), "=m" (*addr)
432         : "d" (reg1), "a" (addr)
433         : "cc");
434     return ccode;
435 }
436 
437 static inline int ssch(struct subchannel_id schid, struct cmd_orb *addr)
438 {
439     register struct subchannel_id reg1 asm("1") = schid;
440     int ccode = -EIO;
441 
442     asm volatile(
443         "    ssch    0(%2)\n"
444         "0:  ipm    %0\n"
445         "    srl    %0,28\n"
446         "1:\n"
447         : "+d" (ccode)
448         : "d" (reg1), "a" (addr), "m" (*addr)
449         : "cc", "memory");
450     return ccode;
451 }
452 
453 static inline int csch(struct subchannel_id schid)
454 {
455     register struct subchannel_id reg1 asm("1") = schid;
456     int ccode;
457 
458     asm volatile(
459         "    csch\n"
460         "    ipm    %0\n"
461         "    srl    %0,28"
462         : "=d" (ccode)
463         : "d" (reg1)
464         : "cc");
465     return ccode;
466 }
467 
468 static inline int tpi(struct tpi_info *addr)
469 {
470     int ccode;
471 
472     asm volatile(
473         "    tpi    0(%2)\n"
474         "    ipm    %0\n"
475         "    srl    %0,28"
476         : "=d" (ccode), "=m" (*addr)
477         : "a" (addr)
478         : "cc");
479     return ccode;
480 }
481 
482 static inline int chsc(void *chsc_area)
483 {
484     typedef struct { char _[4096]; } addr_type;
485     int cc;
486 
487     asm volatile(
488         "    .insn    rre,0xb25f0000,%2,0\n"
489         "    ipm    %0\n"
490         "    srl    %0,28\n"
491         : "=d" (cc), "=m" (*(addr_type *) chsc_area)
492         : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
493         : "cc");
494     return cc;
495 }
496 
497 #endif /* CIO_H */
498