xref: /openbmc/qemu/pc-bios/s390-ccw/cio.h (revision e17e57e862faf6e1f372385c18dcf6d3fd31158e)
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  extern SubChannelId net_schid;
365  
366  int enable_mss_facility(void);
367  void enable_subchannel(SubChannelId schid);
368  uint16_t cu_type(SubChannelId schid);
369  int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data,
370                   uint16_t data_size);
371  int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt);
372  
373  /*
374   * Some S390 specific IO instructions as inline
375   */
376  
stsch_err(struct subchannel_id schid,struct schib * addr)377  static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
378  {
379      register struct subchannel_id reg1 asm ("1") = schid;
380      int ccode = -EIO;
381  
382      asm volatile(
383          "    stsch    0(%3)\n"
384          "0:  ipm    %0\n"
385          "    srl    %0,28\n"
386          "1:\n"
387          : "+d" (ccode), "=m" (*addr)
388          : "d" (reg1), "a" (addr)
389          : "cc");
390      return ccode;
391  }
392  
msch(struct subchannel_id schid,struct schib * addr)393  static inline int msch(struct subchannel_id schid, struct schib *addr)
394  {
395      register struct subchannel_id reg1 asm ("1") = schid;
396      int ccode;
397  
398      asm volatile(
399          "    msch    0(%2)\n"
400          "    ipm    %0\n"
401          "    srl    %0,28"
402          : "=d" (ccode)
403          : "d" (reg1), "a" (addr), "m" (*addr)
404          : "cc");
405      return ccode;
406  }
407  
msch_err(struct subchannel_id schid,struct schib * addr)408  static inline int msch_err(struct subchannel_id schid, struct schib *addr)
409  {
410      register struct subchannel_id reg1 asm ("1") = schid;
411      int ccode = -EIO;
412  
413      asm volatile(
414          "    msch    0(%2)\n"
415          "0:  ipm    %0\n"
416          "    srl    %0,28\n"
417          "1:\n"
418          : "+d" (ccode)
419          : "d" (reg1), "a" (addr), "m" (*addr)
420          : "cc");
421      return ccode;
422  }
423  
tsch(struct subchannel_id schid,struct irb * addr)424  static inline int tsch(struct subchannel_id schid, struct irb *addr)
425  {
426      register struct subchannel_id reg1 asm ("1") = schid;
427      int ccode;
428  
429      asm volatile(
430          "    tsch    0(%3)\n"
431          "    ipm    %0\n"
432          "    srl    %0,28"
433          : "=d" (ccode), "=m" (*addr)
434          : "d" (reg1), "a" (addr)
435          : "cc");
436      return ccode;
437  }
438  
ssch(struct subchannel_id schid,struct cmd_orb * addr)439  static inline int ssch(struct subchannel_id schid, struct cmd_orb *addr)
440  {
441      register struct subchannel_id reg1 asm("1") = schid;
442      int ccode = -EIO;
443  
444      asm volatile(
445          "    ssch    0(%2)\n"
446          "0:  ipm    %0\n"
447          "    srl    %0,28\n"
448          "1:\n"
449          : "+d" (ccode)
450          : "d" (reg1), "a" (addr), "m" (*addr)
451          : "cc", "memory");
452      return ccode;
453  }
454  
csch(struct subchannel_id schid)455  static inline int csch(struct subchannel_id schid)
456  {
457      register struct subchannel_id reg1 asm("1") = schid;
458      int ccode;
459  
460      asm volatile(
461          "    csch\n"
462          "    ipm    %0\n"
463          "    srl    %0,28"
464          : "=d" (ccode)
465          : "d" (reg1)
466          : "cc");
467      return ccode;
468  }
469  
tpi(struct tpi_info * addr)470  static inline int tpi(struct tpi_info *addr)
471  {
472      int ccode;
473  
474      asm volatile(
475          "    tpi    0(%2)\n"
476          "    ipm    %0\n"
477          "    srl    %0,28"
478          : "=d" (ccode), "=m" (*addr)
479          : "a" (addr)
480          : "cc");
481      return ccode;
482  }
483  
chsc(void * chsc_area)484  static inline int chsc(void *chsc_area)
485  {
486      typedef struct { char _[4096]; } addr_type;
487      int cc;
488  
489      asm volatile(
490          "    .insn    rre,0xb25f0000,%2,0\n"
491          "    ipm    %0\n"
492          "    srl    %0,28\n"
493          : "=d" (cc), "=m" (*(addr_type *) chsc_area)
494          : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
495          : "cc");
496      return cc;
497  }
498  
499  #endif /* CIO_H */
500