xref: /qemu/pc-bios/s390-ccw/cio.h (revision 120d04103e3f870d0fcd2a23c2ada0a4a4f036cc)
11e17c2c1SAlexander Graf /*
21e17c2c1SAlexander Graf  * Channel IO definitions
31e17c2c1SAlexander Graf  *
41e17c2c1SAlexander Graf  * Copyright (c) 2013 Alexander Graf <agraf@suse.de>
51e17c2c1SAlexander Graf  *
61e17c2c1SAlexander Graf  * Inspired by various s390 headers in Linux 3.9.
71e17c2c1SAlexander Graf  *
81e17c2c1SAlexander Graf  * This work is licensed under the terms of the GNU GPL, version 2 or (at
91e17c2c1SAlexander Graf  * your option) any later version. See the COPYING file in the top-level
101e17c2c1SAlexander Graf  * directory.
111e17c2c1SAlexander Graf  */
121e17c2c1SAlexander Graf 
131e17c2c1SAlexander Graf #ifndef CIO_H
141e17c2c1SAlexander Graf #define CIO_H
151e17c2c1SAlexander Graf 
161e17c2c1SAlexander Graf /*
171e17c2c1SAlexander Graf  * path management control word
181e17c2c1SAlexander Graf  */
191e17c2c1SAlexander Graf struct pmcw {
201e17c2c1SAlexander Graf     __u32 intparm;      /* interruption parameter */
211e17c2c1SAlexander Graf     __u32 qf:1;         /* qdio facility */
221e17c2c1SAlexander Graf     __u32 w:1;
231e17c2c1SAlexander Graf     __u32 isc:3;        /* interruption sublass */
241e17c2c1SAlexander Graf     __u32 res5:3;       /* reserved zeros */
251e17c2c1SAlexander Graf     __u32 ena:1;        /* enabled */
261e17c2c1SAlexander Graf     __u32 lm:2;         /* limit mode */
271e17c2c1SAlexander Graf     __u32 mme:2;        /* measurement-mode enable */
281e17c2c1SAlexander Graf     __u32 mp:1;         /* multipath mode */
291e17c2c1SAlexander Graf     __u32 tf:1;         /* timing facility */
301e17c2c1SAlexander Graf     __u32 dnv:1;        /* device number valid */
311e17c2c1SAlexander Graf     __u32 dev:16;       /* device number */
321e17c2c1SAlexander Graf     __u8  lpm;          /* logical path mask */
331e17c2c1SAlexander Graf     __u8  pnom;         /* path not operational mask */
341e17c2c1SAlexander Graf     __u8  lpum;         /* last path used mask */
351e17c2c1SAlexander Graf     __u8  pim;          /* path installed mask */
361e17c2c1SAlexander Graf     __u16 mbi;          /* measurement-block index */
371e17c2c1SAlexander Graf     __u8  pom;          /* path operational mask */
381e17c2c1SAlexander Graf     __u8  pam;          /* path available mask */
391e17c2c1SAlexander Graf     __u8  chpid[8];     /* CHPID 0-7 (if available) */
401e17c2c1SAlexander Graf     __u32 unused1:8;    /* reserved zeros */
411e17c2c1SAlexander Graf     __u32 st:3;         /* subchannel type */
421e17c2c1SAlexander Graf     __u32 unused2:18;   /* reserved zeros */
431e17c2c1SAlexander Graf     __u32 mbfc:1;       /* measurement block format control */
441e17c2c1SAlexander Graf     __u32 xmwme:1;      /* extended measurement word mode enable */
451e17c2c1SAlexander Graf     __u32 csense:1;     /* concurrent sense; can be enabled ...*/
461e17c2c1SAlexander Graf                         /*  ... per MSCH, however, if facility */
471e17c2c1SAlexander Graf                         /*  ... is not installed, this results */
481e17c2c1SAlexander Graf                         /*  ... in an operand exception.       */
491e17c2c1SAlexander Graf } __attribute__ ((packed));
501e17c2c1SAlexander Graf 
511e17c2c1SAlexander Graf /* Target SCHIB configuration. */
521e17c2c1SAlexander Graf struct schib_config {
531e17c2c1SAlexander Graf     __u64 mba;
541e17c2c1SAlexander Graf     __u32 intparm;
551e17c2c1SAlexander Graf     __u16 mbi;
561e17c2c1SAlexander Graf     __u32 isc:3;
571e17c2c1SAlexander Graf     __u32 ena:1;
581e17c2c1SAlexander Graf     __u32 mme:2;
591e17c2c1SAlexander Graf     __u32 mp:1;
601e17c2c1SAlexander Graf     __u32 csense:1;
611e17c2c1SAlexander Graf     __u32 mbfc:1;
621e17c2c1SAlexander Graf } __attribute__ ((packed));
631e17c2c1SAlexander Graf 
641e17c2c1SAlexander Graf struct scsw {
651e17c2c1SAlexander Graf     __u16 flags;
661e17c2c1SAlexander Graf     __u16 ctrl;
671e17c2c1SAlexander Graf     __u32 cpa;
681e17c2c1SAlexander Graf     __u8 dstat;
691e17c2c1SAlexander Graf     __u8 cstat;
701e17c2c1SAlexander Graf     __u16 count;
711e17c2c1SAlexander Graf } __attribute__ ((packed));
721e17c2c1SAlexander Graf 
731e17c2c1SAlexander Graf #define SCSW_FCTL_CLEAR_FUNC 0x1000
741e17c2c1SAlexander Graf #define SCSW_FCTL_HALT_FUNC 0x2000
751e17c2c1SAlexander Graf #define SCSW_FCTL_START_FUNC 0x4000
761e17c2c1SAlexander Graf 
771e17c2c1SAlexander Graf /*
781e17c2c1SAlexander Graf  * subchannel information block
791e17c2c1SAlexander Graf  */
80d96c5db7SJason J. Herne typedef struct schib {
811e17c2c1SAlexander Graf     struct pmcw pmcw;     /* path management control word */
821e17c2c1SAlexander Graf     struct scsw scsw;     /* subchannel status word */
831e17c2c1SAlexander Graf     __u64 mba;            /* measurement block address */
841e17c2c1SAlexander Graf     __u8 mda[4];          /* model dependent area */
85d96c5db7SJason J. Herne } __attribute__ ((packed, aligned(4))) Schib;
861e17c2c1SAlexander Graf 
87d96c5db7SJason J. Herne typedef struct subchannel_id {
881e17c2c1SAlexander Graf         __u32 cssid:8;
891e17c2c1SAlexander Graf         __u32:4;
901e17c2c1SAlexander Graf         __u32 m:1;
911e17c2c1SAlexander Graf         __u32 ssid:2;
921e17c2c1SAlexander Graf         __u32 one:1;
931e17c2c1SAlexander Graf         __u32 sch_no:16;
94d96c5db7SJason J. Herne } __attribute__ ((packed, aligned(4))) SubChannelId;
951e17c2c1SAlexander Graf 
96c8cda874SDominik Dingel struct chsc_header {
97c8cda874SDominik Dingel     __u16 length;
98c8cda874SDominik Dingel     __u16 code;
99c8cda874SDominik Dingel } __attribute__((packed));
100c8cda874SDominik Dingel 
101d96c5db7SJason J. Herne typedef struct chsc_area_sda {
102c8cda874SDominik Dingel     struct chsc_header request;
103c8cda874SDominik Dingel     __u8 reserved1:4;
104c8cda874SDominik Dingel     __u8 format:4;
105c8cda874SDominik Dingel     __u8 reserved2;
106c8cda874SDominik Dingel     __u16 operation_code;
107c8cda874SDominik Dingel     __u32 reserved3;
108c8cda874SDominik Dingel     __u32 reserved4;
109c8cda874SDominik Dingel     __u32 operation_data_area[252];
110c8cda874SDominik Dingel     struct chsc_header response;
111c8cda874SDominik Dingel     __u32 reserved5:4;
112c8cda874SDominik Dingel     __u32 format2:4;
113c8cda874SDominik Dingel     __u32 reserved6:24;
114d96c5db7SJason J. Herne } __attribute__((packed)) ChscAreaSda;
115c8cda874SDominik Dingel 
1161e17c2c1SAlexander Graf /*
1171e17c2c1SAlexander Graf  * TPI info structure
1181e17c2c1SAlexander Graf  */
1191e17c2c1SAlexander Graf struct tpi_info {
1201e17c2c1SAlexander Graf     struct subchannel_id schid;
1211e17c2c1SAlexander Graf     __u32 intparm;      /* interruption parameter */
1221e17c2c1SAlexander Graf     __u32 adapter_IO:1;
1231e17c2c1SAlexander Graf     __u32 reserved2:1;
1241e17c2c1SAlexander Graf     __u32 isc:3;
1251e17c2c1SAlexander Graf     __u32 reserved3:12;
1261e17c2c1SAlexander Graf     __u32 int_type:3;
1271e17c2c1SAlexander Graf     __u32 reserved4:12;
128a6e4385dSThomas Huth } __attribute__ ((packed, aligned(4)));
1291e17c2c1SAlexander Graf 
1301e17c2c1SAlexander Graf /* channel command word (type 1) */
131d96c5db7SJason J. Herne typedef struct ccw1 {
1321e17c2c1SAlexander Graf     __u8 cmd_code;
1331e17c2c1SAlexander Graf     __u8 flags;
1341e17c2c1SAlexander Graf     __u16 count;
1351e17c2c1SAlexander Graf     __u32 cda;
136d96c5db7SJason J. Herne } __attribute__ ((packed, aligned(8))) Ccw1;
1371e17c2c1SAlexander Graf 
1381e17c2c1SAlexander Graf #define CCW_FLAG_DC              0x80
1391e17c2c1SAlexander Graf #define CCW_FLAG_CC              0x40
1401e17c2c1SAlexander Graf #define CCW_FLAG_SLI             0x20
1411e17c2c1SAlexander Graf #define CCW_FLAG_SKIP            0x10
1421e17c2c1SAlexander Graf #define CCW_FLAG_PCI             0x08
1431e17c2c1SAlexander Graf #define CCW_FLAG_IDA             0x04
1441e17c2c1SAlexander Graf #define CCW_FLAG_SUSPEND         0x02
1451e17c2c1SAlexander Graf 
1461e17c2c1SAlexander Graf #define CCW_CMD_NOOP             0x03
1471e17c2c1SAlexander Graf #define CCW_CMD_BASIC_SENSE      0x04
1481e17c2c1SAlexander Graf #define CCW_CMD_TIC              0x08
1491e17c2c1SAlexander Graf #define CCW_CMD_SENSE_ID         0xe4
1501e17c2c1SAlexander Graf 
1511e17c2c1SAlexander Graf #define CCW_CMD_SET_VQ           0x13
1521e17c2c1SAlexander Graf #define CCW_CMD_VDEV_RESET       0x33
1531e17c2c1SAlexander Graf #define CCW_CMD_READ_FEAT        0x12
1541e17c2c1SAlexander Graf #define CCW_CMD_WRITE_FEAT       0x11
1551e17c2c1SAlexander Graf #define CCW_CMD_READ_CONF        0x22
1561e17c2c1SAlexander Graf #define CCW_CMD_WRITE_CONF       0x21
1571e17c2c1SAlexander Graf #define CCW_CMD_WRITE_STATUS     0x31
1581e17c2c1SAlexander Graf #define CCW_CMD_SET_IND          0x43
1591e17c2c1SAlexander Graf #define CCW_CMD_SET_CONF_IND     0x53
1601e17c2c1SAlexander Graf #define CCW_CMD_READ_VQ_CONF     0x32
1611e17c2c1SAlexander Graf 
1621e17c2c1SAlexander Graf /*
1631e17c2c1SAlexander Graf  * Command-mode operation request block
1641e17c2c1SAlexander Graf  */
165d96c5db7SJason J. Herne typedef struct cmd_orb {
1661e17c2c1SAlexander Graf     __u32 intparm;    /* interruption parameter */
1671e17c2c1SAlexander Graf     __u32 key:4;      /* flags, like key, suspend control, etc. */
1681e17c2c1SAlexander Graf     __u32 spnd:1;     /* suspend control */
1691e17c2c1SAlexander Graf     __u32 res1:1;     /* reserved */
1701e17c2c1SAlexander Graf     __u32 mod:1;      /* modification control */
1711e17c2c1SAlexander Graf     __u32 sync:1;     /* synchronize control */
1721e17c2c1SAlexander Graf     __u32 fmt:1;      /* format control */
1731e17c2c1SAlexander Graf     __u32 pfch:1;     /* prefetch control */
1741e17c2c1SAlexander Graf     __u32 isic:1;     /* initial-status-interruption control */
1751e17c2c1SAlexander Graf     __u32 alcc:1;     /* address-limit-checking control */
1761e17c2c1SAlexander Graf     __u32 ssic:1;     /* suppress-suspended-interr. control */
1771e17c2c1SAlexander Graf     __u32 res2:1;     /* reserved */
1781e17c2c1SAlexander Graf     __u32 c64:1;      /* IDAW/QDIO 64 bit control  */
1791e17c2c1SAlexander Graf     __u32 i2k:1;      /* IDAW 2/4kB block size control */
1801e17c2c1SAlexander Graf     __u32 lpm:8;      /* logical path mask */
1811e17c2c1SAlexander Graf     __u32 ils:1;      /* incorrect length */
1821e17c2c1SAlexander Graf     __u32 zero:6;     /* reserved zeros */
1831e17c2c1SAlexander Graf     __u32 orbx:1;     /* ORB extension control */
1841e17c2c1SAlexander Graf     __u32 cpa;    /* channel program address */
185d96c5db7SJason J. Herne }  __attribute__ ((packed, aligned(4))) CmdOrb;
1861e17c2c1SAlexander Graf 
1871e17c2c1SAlexander Graf struct ciw {
1881e17c2c1SAlexander Graf     __u8 type;
1891e17c2c1SAlexander Graf     __u8 command;
1901e17c2c1SAlexander Graf     __u16 count;
1911e17c2c1SAlexander Graf };
1921e17c2c1SAlexander Graf 
1931e17c2c1SAlexander Graf /*
1941e17c2c1SAlexander Graf  * sense-id response buffer layout
1951e17c2c1SAlexander Graf  */
196d96c5db7SJason J. Herne typedef struct senseid {
1971e17c2c1SAlexander Graf     /* common part */
1981e17c2c1SAlexander Graf     __u8  reserved;   /* always 0x'FF' */
1991e17c2c1SAlexander Graf     __u16 cu_type;    /* control unit type */
2001e17c2c1SAlexander Graf     __u8  cu_model;   /* control unit model */
2011e17c2c1SAlexander Graf     __u16 dev_type;   /* device type */
2021e17c2c1SAlexander Graf     __u8  dev_model;  /* device model */
2031e17c2c1SAlexander Graf     __u8  unused;     /* padding byte */
2041e17c2c1SAlexander Graf     /* extended part */
2051e17c2c1SAlexander Graf     struct ciw ciw[62];
206d96c5db7SJason J. Herne }  __attribute__ ((packed, aligned(4))) SenseId;
2071e17c2c1SAlexander Graf 
2081e17c2c1SAlexander Graf /* interruption response block */
209d96c5db7SJason J. Herne typedef struct irb {
2101e17c2c1SAlexander Graf     struct scsw scsw;
2111e17c2c1SAlexander Graf     __u32 esw[5];
2121e17c2c1SAlexander Graf     __u32 ecw[8];
2131e17c2c1SAlexander Graf     __u32 emw[8];
214d96c5db7SJason J. Herne }  __attribute__ ((packed, aligned(4))) Irb;
2151e17c2c1SAlexander Graf 
216*120d0410SJason J. Herne int enable_mss_facility(void);
217*120d0410SJason J. Herne void enable_subchannel(SubChannelId schid);
218*120d0410SJason J. Herne 
2191e17c2c1SAlexander Graf /*
2201e17c2c1SAlexander Graf  * Some S390 specific IO instructions as inline
2211e17c2c1SAlexander Graf  */
2221e17c2c1SAlexander Graf 
2231e17c2c1SAlexander Graf static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
2241e17c2c1SAlexander Graf {
2251e17c2c1SAlexander Graf     register struct subchannel_id reg1 asm ("1") = schid;
2261e17c2c1SAlexander Graf     int ccode = -EIO;
2271e17c2c1SAlexander Graf 
2281e17c2c1SAlexander Graf     asm volatile(
2291e17c2c1SAlexander Graf         "    stsch    0(%3)\n"
2301e17c2c1SAlexander Graf         "0:  ipm    %0\n"
2311e17c2c1SAlexander Graf         "    srl    %0,28\n"
2321e17c2c1SAlexander Graf         "1:\n"
2331e17c2c1SAlexander Graf         : "+d" (ccode), "=m" (*addr)
2341e17c2c1SAlexander Graf         : "d" (reg1), "a" (addr)
2351e17c2c1SAlexander Graf         : "cc");
2361e17c2c1SAlexander Graf     return ccode;
2371e17c2c1SAlexander Graf }
2381e17c2c1SAlexander Graf 
2391e17c2c1SAlexander Graf static inline int msch(struct subchannel_id schid, struct schib *addr)
2401e17c2c1SAlexander Graf {
2411e17c2c1SAlexander Graf     register struct subchannel_id reg1 asm ("1") = schid;
2421e17c2c1SAlexander Graf     int ccode;
2431e17c2c1SAlexander Graf 
2441e17c2c1SAlexander Graf     asm volatile(
2451e17c2c1SAlexander Graf         "    msch    0(%2)\n"
2461e17c2c1SAlexander Graf         "    ipm    %0\n"
2471e17c2c1SAlexander Graf         "    srl    %0,28"
2481e17c2c1SAlexander Graf         : "=d" (ccode)
2491e17c2c1SAlexander Graf         : "d" (reg1), "a" (addr), "m" (*addr)
2501e17c2c1SAlexander Graf         : "cc");
2511e17c2c1SAlexander Graf     return ccode;
2521e17c2c1SAlexander Graf }
2531e17c2c1SAlexander Graf 
2541e17c2c1SAlexander Graf static inline int msch_err(struct subchannel_id schid, struct schib *addr)
2551e17c2c1SAlexander Graf {
2561e17c2c1SAlexander Graf     register struct subchannel_id reg1 asm ("1") = schid;
2571e17c2c1SAlexander Graf     int ccode = -EIO;
2581e17c2c1SAlexander Graf 
2591e17c2c1SAlexander Graf     asm volatile(
2601e17c2c1SAlexander Graf         "    msch    0(%2)\n"
2611e17c2c1SAlexander Graf         "0:  ipm    %0\n"
2621e17c2c1SAlexander Graf         "    srl    %0,28\n"
2631e17c2c1SAlexander Graf         "1:\n"
2641e17c2c1SAlexander Graf         : "+d" (ccode)
2651e17c2c1SAlexander Graf         : "d" (reg1), "a" (addr), "m" (*addr)
2661e17c2c1SAlexander Graf         : "cc");
2671e17c2c1SAlexander Graf     return ccode;
2681e17c2c1SAlexander Graf }
2691e17c2c1SAlexander Graf 
2701e17c2c1SAlexander Graf static inline int tsch(struct subchannel_id schid, struct irb *addr)
2711e17c2c1SAlexander Graf {
2721e17c2c1SAlexander Graf     register struct subchannel_id reg1 asm ("1") = schid;
2731e17c2c1SAlexander Graf     int ccode;
2741e17c2c1SAlexander Graf 
2751e17c2c1SAlexander Graf     asm volatile(
2761e17c2c1SAlexander Graf         "    tsch    0(%3)\n"
2771e17c2c1SAlexander Graf         "    ipm    %0\n"
2781e17c2c1SAlexander Graf         "    srl    %0,28"
2791e17c2c1SAlexander Graf         : "=d" (ccode), "=m" (*addr)
2801e17c2c1SAlexander Graf         : "d" (reg1), "a" (addr)
2811e17c2c1SAlexander Graf         : "cc");
2821e17c2c1SAlexander Graf     return ccode;
2831e17c2c1SAlexander Graf }
2841e17c2c1SAlexander Graf 
2851e17c2c1SAlexander Graf static inline int ssch(struct subchannel_id schid, struct cmd_orb *addr)
2861e17c2c1SAlexander Graf {
2871e17c2c1SAlexander Graf     register struct subchannel_id reg1 asm("1") = schid;
2881e17c2c1SAlexander Graf     int ccode = -EIO;
2891e17c2c1SAlexander Graf 
2901e17c2c1SAlexander Graf     asm volatile(
2911e17c2c1SAlexander Graf         "    ssch    0(%2)\n"
2921e17c2c1SAlexander Graf         "0:  ipm    %0\n"
2931e17c2c1SAlexander Graf         "    srl    %0,28\n"
2941e17c2c1SAlexander Graf         "1:\n"
2951e17c2c1SAlexander Graf         : "+d" (ccode)
2961e17c2c1SAlexander Graf         : "d" (reg1), "a" (addr), "m" (*addr)
2971e17c2c1SAlexander Graf         : "cc", "memory");
2981e17c2c1SAlexander Graf     return ccode;
2991e17c2c1SAlexander Graf }
3001e17c2c1SAlexander Graf 
3011e17c2c1SAlexander Graf static inline int csch(struct subchannel_id schid)
3021e17c2c1SAlexander Graf {
3031e17c2c1SAlexander Graf     register struct subchannel_id reg1 asm("1") = schid;
3041e17c2c1SAlexander Graf     int ccode;
3051e17c2c1SAlexander Graf 
3061e17c2c1SAlexander Graf     asm volatile(
3071e17c2c1SAlexander Graf         "    csch\n"
3081e17c2c1SAlexander Graf         "    ipm    %0\n"
3091e17c2c1SAlexander Graf         "    srl    %0,28"
3101e17c2c1SAlexander Graf         : "=d" (ccode)
3111e17c2c1SAlexander Graf         : "d" (reg1)
3121e17c2c1SAlexander Graf         : "cc");
3131e17c2c1SAlexander Graf     return ccode;
3141e17c2c1SAlexander Graf }
3151e17c2c1SAlexander Graf 
3161e17c2c1SAlexander Graf static inline int tpi(struct tpi_info *addr)
3171e17c2c1SAlexander Graf {
3181e17c2c1SAlexander Graf     int ccode;
3191e17c2c1SAlexander Graf 
3201e17c2c1SAlexander Graf     asm volatile(
3211e17c2c1SAlexander Graf         "    tpi    0(%2)\n"
3221e17c2c1SAlexander Graf         "    ipm    %0\n"
3231e17c2c1SAlexander Graf         "    srl    %0,28"
3241e17c2c1SAlexander Graf         : "=d" (ccode), "=m" (*addr)
3251e17c2c1SAlexander Graf         : "a" (addr)
3261e17c2c1SAlexander Graf         : "cc");
3271e17c2c1SAlexander Graf     return ccode;
3281e17c2c1SAlexander Graf }
3291e17c2c1SAlexander Graf 
3301e17c2c1SAlexander Graf static inline int chsc(void *chsc_area)
3311e17c2c1SAlexander Graf {
3321e17c2c1SAlexander Graf     typedef struct { char _[4096]; } addr_type;
3331e17c2c1SAlexander Graf     int cc;
3341e17c2c1SAlexander Graf 
3351e17c2c1SAlexander Graf     asm volatile(
3361e17c2c1SAlexander Graf         "    .insn    rre,0xb25f0000,%2,0\n"
3371e17c2c1SAlexander Graf         "    ipm    %0\n"
3381e17c2c1SAlexander Graf         "    srl    %0,28\n"
3391e17c2c1SAlexander Graf         : "=d" (cc), "=m" (*(addr_type *) chsc_area)
3401e17c2c1SAlexander Graf         : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
3411e17c2c1SAlexander Graf         : "cc");
3421e17c2c1SAlexander Graf     return cc;
3431e17c2c1SAlexander Graf }
3441e17c2c1SAlexander Graf 
3451e17c2c1SAlexander Graf #endif /* CIO_H */
346