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