xref: /qemu/pc-bios/s390-ccw/cio.h (revision c8cda8748eceeeb06f1952e7e765a0919103644d)
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  */
801e17c2c1SAlexander Graf 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 */
851e17c2c1SAlexander Graf } __attribute__ ((packed,aligned(4)));
861e17c2c1SAlexander Graf 
871e17c2c1SAlexander Graf 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;
941e17c2c1SAlexander Graf } __attribute__ ((packed, aligned(4)));
951e17c2c1SAlexander Graf 
96*c8cda874SDominik Dingel struct chsc_header {
97*c8cda874SDominik Dingel     __u16 length;
98*c8cda874SDominik Dingel     __u16 code;
99*c8cda874SDominik Dingel } __attribute__((packed));
100*c8cda874SDominik Dingel 
101*c8cda874SDominik Dingel struct chsc_area_sda {
102*c8cda874SDominik Dingel     struct chsc_header request;
103*c8cda874SDominik Dingel     __u8 reserved1:4;
104*c8cda874SDominik Dingel     __u8 format:4;
105*c8cda874SDominik Dingel     __u8 reserved2;
106*c8cda874SDominik Dingel     __u16 operation_code;
107*c8cda874SDominik Dingel     __u32 reserved3;
108*c8cda874SDominik Dingel     __u32 reserved4;
109*c8cda874SDominik Dingel     __u32 operation_data_area[252];
110*c8cda874SDominik Dingel     struct chsc_header response;
111*c8cda874SDominik Dingel     __u32 reserved5:4;
112*c8cda874SDominik Dingel     __u32 format2:4;
113*c8cda874SDominik Dingel     __u32 reserved6:24;
114*c8cda874SDominik Dingel } __attribute__((packed));
115*c8cda874SDominik 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;
1281e17c2c1SAlexander Graf } __attribute__ ((packed));
1291e17c2c1SAlexander Graf 
1301e17c2c1SAlexander Graf /* channel command word (type 1) */
1311e17c2c1SAlexander Graf struct ccw1 {
1321e17c2c1SAlexander Graf     __u8 cmd_code;
1331e17c2c1SAlexander Graf     __u8 flags;
1341e17c2c1SAlexander Graf     __u16 count;
1351e17c2c1SAlexander Graf     __u32 cda;
1361e17c2c1SAlexander Graf } __attribute__ ((packed));
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  */
1651e17c2c1SAlexander Graf 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 */
1851e17c2c1SAlexander Graf }  __attribute__ ((packed, aligned(4)));
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  */
1961e17c2c1SAlexander Graf 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];
2061e17c2c1SAlexander Graf }  __attribute__ ((packed, aligned(4)));
2071e17c2c1SAlexander Graf 
2081e17c2c1SAlexander Graf /* interruption response block */
2091e17c2c1SAlexander Graf struct irb {
2101e17c2c1SAlexander Graf     struct scsw scsw;
2111e17c2c1SAlexander Graf     __u32 esw[5];
2121e17c2c1SAlexander Graf     __u32 ecw[8];
2131e17c2c1SAlexander Graf     __u32 emw[8];
2141e17c2c1SAlexander Graf }  __attribute__ ((packed, aligned(4)));
2151e17c2c1SAlexander Graf 
2161e17c2c1SAlexander Graf /*
2171e17c2c1SAlexander Graf  * Some S390 specific IO instructions as inline
2181e17c2c1SAlexander Graf  */
2191e17c2c1SAlexander Graf 
2201e17c2c1SAlexander Graf static inline int stsch_err(struct subchannel_id schid, struct schib *addr)
2211e17c2c1SAlexander Graf {
2221e17c2c1SAlexander Graf     register struct subchannel_id reg1 asm ("1") = schid;
2231e17c2c1SAlexander Graf     int ccode = -EIO;
2241e17c2c1SAlexander Graf 
2251e17c2c1SAlexander Graf     asm volatile(
2261e17c2c1SAlexander Graf         "    stsch    0(%3)\n"
2271e17c2c1SAlexander Graf         "0:  ipm    %0\n"
2281e17c2c1SAlexander Graf         "    srl    %0,28\n"
2291e17c2c1SAlexander Graf         "1:\n"
2301e17c2c1SAlexander Graf         : "+d" (ccode), "=m" (*addr)
2311e17c2c1SAlexander Graf         : "d" (reg1), "a" (addr)
2321e17c2c1SAlexander Graf         : "cc");
2331e17c2c1SAlexander Graf     return ccode;
2341e17c2c1SAlexander Graf }
2351e17c2c1SAlexander Graf 
2361e17c2c1SAlexander Graf static inline int msch(struct subchannel_id schid, struct schib *addr)
2371e17c2c1SAlexander Graf {
2381e17c2c1SAlexander Graf     register struct subchannel_id reg1 asm ("1") = schid;
2391e17c2c1SAlexander Graf     int ccode;
2401e17c2c1SAlexander Graf 
2411e17c2c1SAlexander Graf     asm volatile(
2421e17c2c1SAlexander Graf         "    msch    0(%2)\n"
2431e17c2c1SAlexander Graf         "    ipm    %0\n"
2441e17c2c1SAlexander Graf         "    srl    %0,28"
2451e17c2c1SAlexander Graf         : "=d" (ccode)
2461e17c2c1SAlexander Graf         : "d" (reg1), "a" (addr), "m" (*addr)
2471e17c2c1SAlexander Graf         : "cc");
2481e17c2c1SAlexander Graf     return ccode;
2491e17c2c1SAlexander Graf }
2501e17c2c1SAlexander Graf 
2511e17c2c1SAlexander Graf static inline int msch_err(struct subchannel_id schid, struct schib *addr)
2521e17c2c1SAlexander Graf {
2531e17c2c1SAlexander Graf     register struct subchannel_id reg1 asm ("1") = schid;
2541e17c2c1SAlexander Graf     int ccode = -EIO;
2551e17c2c1SAlexander Graf 
2561e17c2c1SAlexander Graf     asm volatile(
2571e17c2c1SAlexander Graf         "    msch    0(%2)\n"
2581e17c2c1SAlexander Graf         "0:  ipm    %0\n"
2591e17c2c1SAlexander Graf         "    srl    %0,28\n"
2601e17c2c1SAlexander Graf         "1:\n"
2611e17c2c1SAlexander Graf         : "+d" (ccode)
2621e17c2c1SAlexander Graf         : "d" (reg1), "a" (addr), "m" (*addr)
2631e17c2c1SAlexander Graf         : "cc");
2641e17c2c1SAlexander Graf     return ccode;
2651e17c2c1SAlexander Graf }
2661e17c2c1SAlexander Graf 
2671e17c2c1SAlexander Graf static inline int tsch(struct subchannel_id schid, struct irb *addr)
2681e17c2c1SAlexander Graf {
2691e17c2c1SAlexander Graf     register struct subchannel_id reg1 asm ("1") = schid;
2701e17c2c1SAlexander Graf     int ccode;
2711e17c2c1SAlexander Graf 
2721e17c2c1SAlexander Graf     asm volatile(
2731e17c2c1SAlexander Graf         "    tsch    0(%3)\n"
2741e17c2c1SAlexander Graf         "    ipm    %0\n"
2751e17c2c1SAlexander Graf         "    srl    %0,28"
2761e17c2c1SAlexander Graf         : "=d" (ccode), "=m" (*addr)
2771e17c2c1SAlexander Graf         : "d" (reg1), "a" (addr)
2781e17c2c1SAlexander Graf         : "cc");
2791e17c2c1SAlexander Graf     return ccode;
2801e17c2c1SAlexander Graf }
2811e17c2c1SAlexander Graf 
2821e17c2c1SAlexander Graf static inline int ssch(struct subchannel_id schid, struct cmd_orb *addr)
2831e17c2c1SAlexander Graf {
2841e17c2c1SAlexander Graf     register struct subchannel_id reg1 asm("1") = schid;
2851e17c2c1SAlexander Graf     int ccode = -EIO;
2861e17c2c1SAlexander Graf 
2871e17c2c1SAlexander Graf     asm volatile(
2881e17c2c1SAlexander Graf         "    ssch    0(%2)\n"
2891e17c2c1SAlexander Graf         "0:  ipm    %0\n"
2901e17c2c1SAlexander Graf         "    srl    %0,28\n"
2911e17c2c1SAlexander Graf         "1:\n"
2921e17c2c1SAlexander Graf         : "+d" (ccode)
2931e17c2c1SAlexander Graf         : "d" (reg1), "a" (addr), "m" (*addr)
2941e17c2c1SAlexander Graf         : "cc", "memory");
2951e17c2c1SAlexander Graf     return ccode;
2961e17c2c1SAlexander Graf }
2971e17c2c1SAlexander Graf 
2981e17c2c1SAlexander Graf static inline int csch(struct subchannel_id schid)
2991e17c2c1SAlexander Graf {
3001e17c2c1SAlexander Graf     register struct subchannel_id reg1 asm("1") = schid;
3011e17c2c1SAlexander Graf     int ccode;
3021e17c2c1SAlexander Graf 
3031e17c2c1SAlexander Graf     asm volatile(
3041e17c2c1SAlexander Graf         "    csch\n"
3051e17c2c1SAlexander Graf         "    ipm    %0\n"
3061e17c2c1SAlexander Graf         "    srl    %0,28"
3071e17c2c1SAlexander Graf         : "=d" (ccode)
3081e17c2c1SAlexander Graf         : "d" (reg1)
3091e17c2c1SAlexander Graf         : "cc");
3101e17c2c1SAlexander Graf     return ccode;
3111e17c2c1SAlexander Graf }
3121e17c2c1SAlexander Graf 
3131e17c2c1SAlexander Graf static inline int tpi(struct tpi_info *addr)
3141e17c2c1SAlexander Graf {
3151e17c2c1SAlexander Graf     int ccode;
3161e17c2c1SAlexander Graf 
3171e17c2c1SAlexander Graf     asm volatile(
3181e17c2c1SAlexander Graf         "    tpi    0(%2)\n"
3191e17c2c1SAlexander Graf         "    ipm    %0\n"
3201e17c2c1SAlexander Graf         "    srl    %0,28"
3211e17c2c1SAlexander Graf         : "=d" (ccode), "=m" (*addr)
3221e17c2c1SAlexander Graf         : "a" (addr)
3231e17c2c1SAlexander Graf         : "cc");
3241e17c2c1SAlexander Graf     return ccode;
3251e17c2c1SAlexander Graf }
3261e17c2c1SAlexander Graf 
3271e17c2c1SAlexander Graf static inline int chsc(void *chsc_area)
3281e17c2c1SAlexander Graf {
3291e17c2c1SAlexander Graf     typedef struct { char _[4096]; } addr_type;
3301e17c2c1SAlexander Graf     int cc;
3311e17c2c1SAlexander Graf 
3321e17c2c1SAlexander Graf     asm volatile(
3331e17c2c1SAlexander Graf         "    .insn    rre,0xb25f0000,%2,0\n"
3341e17c2c1SAlexander Graf         "    ipm    %0\n"
3351e17c2c1SAlexander Graf         "    srl    %0,28\n"
3361e17c2c1SAlexander Graf         : "=d" (cc), "=m" (*(addr_type *) chsc_area)
3371e17c2c1SAlexander Graf         : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
3381e17c2c1SAlexander Graf         : "cc");
3391e17c2c1SAlexander Graf     return cc;
3401e17c2c1SAlexander Graf }
3411e17c2c1SAlexander Graf 
3421e17c2c1SAlexander Graf #endif /* CIO_H */
343