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