1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Functions for assembling fcx enabled I/O control blocks. 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright IBM Corp. 2008 6*4882a593Smuzhiyun * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com> 7*4882a593Smuzhiyun */ 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun #ifndef _ASM_S390_FCX_H 10*4882a593Smuzhiyun #define _ASM_S390_FCX_H 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun #include <linux/types.h> 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun #define TCW_FORMAT_DEFAULT 0 15*4882a593Smuzhiyun #define TCW_TIDAW_FORMAT_DEFAULT 0 16*4882a593Smuzhiyun #define TCW_FLAGS_INPUT_TIDA (1 << (23 - 5)) 17*4882a593Smuzhiyun #define TCW_FLAGS_TCCB_TIDA (1 << (23 - 6)) 18*4882a593Smuzhiyun #define TCW_FLAGS_OUTPUT_TIDA (1 << (23 - 7)) 19*4882a593Smuzhiyun #define TCW_FLAGS_TIDAW_FORMAT(x) ((x) & 3) << (23 - 9) 20*4882a593Smuzhiyun #define TCW_FLAGS_GET_TIDAW_FORMAT(x) (((x) >> (23 - 9)) & 3) 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun /** 23*4882a593Smuzhiyun * struct tcw - Transport Control Word (TCW) 24*4882a593Smuzhiyun * @format: TCW format 25*4882a593Smuzhiyun * @flags: TCW flags 26*4882a593Smuzhiyun * @tccbl: Transport-Command-Control-Block Length 27*4882a593Smuzhiyun * @r: Read Operations 28*4882a593Smuzhiyun * @w: Write Operations 29*4882a593Smuzhiyun * @output: Output-Data Address 30*4882a593Smuzhiyun * @input: Input-Data Address 31*4882a593Smuzhiyun * @tsb: Transport-Status-Block Address 32*4882a593Smuzhiyun * @tccb: Transport-Command-Control-Block Address 33*4882a593Smuzhiyun * @output_count: Output Count 34*4882a593Smuzhiyun * @input_count: Input Count 35*4882a593Smuzhiyun * @intrg: Interrogate TCW Address 36*4882a593Smuzhiyun */ 37*4882a593Smuzhiyun struct tcw { 38*4882a593Smuzhiyun u32 format:2; 39*4882a593Smuzhiyun u32 :6; 40*4882a593Smuzhiyun u32 flags:24; 41*4882a593Smuzhiyun u32 :8; 42*4882a593Smuzhiyun u32 tccbl:6; 43*4882a593Smuzhiyun u32 r:1; 44*4882a593Smuzhiyun u32 w:1; 45*4882a593Smuzhiyun u32 :16; 46*4882a593Smuzhiyun u64 output; 47*4882a593Smuzhiyun u64 input; 48*4882a593Smuzhiyun u64 tsb; 49*4882a593Smuzhiyun u64 tccb; 50*4882a593Smuzhiyun u32 output_count; 51*4882a593Smuzhiyun u32 input_count; 52*4882a593Smuzhiyun u32 :32; 53*4882a593Smuzhiyun u32 :32; 54*4882a593Smuzhiyun u32 :32; 55*4882a593Smuzhiyun u32 intrg; 56*4882a593Smuzhiyun } __attribute__ ((packed, aligned(64))); 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun #define TIDAW_FLAGS_LAST (1 << (7 - 0)) 59*4882a593Smuzhiyun #define TIDAW_FLAGS_SKIP (1 << (7 - 1)) 60*4882a593Smuzhiyun #define TIDAW_FLAGS_DATA_INT (1 << (7 - 2)) 61*4882a593Smuzhiyun #define TIDAW_FLAGS_TTIC (1 << (7 - 3)) 62*4882a593Smuzhiyun #define TIDAW_FLAGS_INSERT_CBC (1 << (7 - 4)) 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun /** 65*4882a593Smuzhiyun * struct tidaw - Transport-Indirect-Addressing Word (TIDAW) 66*4882a593Smuzhiyun * @flags: TIDAW flags. Can be an arithmetic OR of the following constants: 67*4882a593Smuzhiyun * %TIDAW_FLAGS_LAST, %TIDAW_FLAGS_SKIP, %TIDAW_FLAGS_DATA_INT, 68*4882a593Smuzhiyun * %TIDAW_FLAGS_TTIC, %TIDAW_FLAGS_INSERT_CBC 69*4882a593Smuzhiyun * @count: Count 70*4882a593Smuzhiyun * @addr: Address 71*4882a593Smuzhiyun */ 72*4882a593Smuzhiyun struct tidaw { 73*4882a593Smuzhiyun u32 flags:8; 74*4882a593Smuzhiyun u32 :24; 75*4882a593Smuzhiyun u32 count; 76*4882a593Smuzhiyun u64 addr; 77*4882a593Smuzhiyun } __attribute__ ((packed, aligned(16))); 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun /** 80*4882a593Smuzhiyun * struct tsa_iostat - I/O-Status Transport-Status Area (IO-Stat TSA) 81*4882a593Smuzhiyun * @dev_time: Device Time 82*4882a593Smuzhiyun * @def_time: Defer Time 83*4882a593Smuzhiyun * @queue_time: Queue Time 84*4882a593Smuzhiyun * @dev_busy_time: Device-Busy Time 85*4882a593Smuzhiyun * @dev_act_time: Device-Active-Only Time 86*4882a593Smuzhiyun * @sense: Sense Data (if present) 87*4882a593Smuzhiyun */ 88*4882a593Smuzhiyun struct tsa_iostat { 89*4882a593Smuzhiyun u32 dev_time; 90*4882a593Smuzhiyun u32 def_time; 91*4882a593Smuzhiyun u32 queue_time; 92*4882a593Smuzhiyun u32 dev_busy_time; 93*4882a593Smuzhiyun u32 dev_act_time; 94*4882a593Smuzhiyun u8 sense[32]; 95*4882a593Smuzhiyun } __attribute__ ((packed)); 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun /** 98*4882a593Smuzhiyun * struct tsa_ddpcs - Device-Detected-Program-Check Transport-Status Area (DDPC TSA) 99*4882a593Smuzhiyun * @rc: Reason Code 100*4882a593Smuzhiyun * @rcq: Reason Code Qualifier 101*4882a593Smuzhiyun * @sense: Sense Data (if present) 102*4882a593Smuzhiyun */ 103*4882a593Smuzhiyun struct tsa_ddpc { 104*4882a593Smuzhiyun u32 :24; 105*4882a593Smuzhiyun u32 rc:8; 106*4882a593Smuzhiyun u8 rcq[16]; 107*4882a593Smuzhiyun u8 sense[32]; 108*4882a593Smuzhiyun } __attribute__ ((packed)); 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun #define TSA_INTRG_FLAGS_CU_STATE_VALID (1 << (7 - 0)) 111*4882a593Smuzhiyun #define TSA_INTRG_FLAGS_DEV_STATE_VALID (1 << (7 - 1)) 112*4882a593Smuzhiyun #define TSA_INTRG_FLAGS_OP_STATE_VALID (1 << (7 - 2)) 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun /** 115*4882a593Smuzhiyun * struct tsa_intrg - Interrogate Transport-Status Area (Intrg. TSA) 116*4882a593Smuzhiyun * @format: Format 117*4882a593Smuzhiyun * @flags: Flags. Can be an arithmetic OR of the following constants: 118*4882a593Smuzhiyun * %TSA_INTRG_FLAGS_CU_STATE_VALID, %TSA_INTRG_FLAGS_DEV_STATE_VALID, 119*4882a593Smuzhiyun * %TSA_INTRG_FLAGS_OP_STATE_VALID 120*4882a593Smuzhiyun * @cu_state: Controle-Unit State 121*4882a593Smuzhiyun * @dev_state: Device State 122*4882a593Smuzhiyun * @op_state: Operation State 123*4882a593Smuzhiyun * @sd_info: State-Dependent Information 124*4882a593Smuzhiyun * @dl_id: Device-Level Identifier 125*4882a593Smuzhiyun * @dd_data: Device-Dependent Data 126*4882a593Smuzhiyun */ 127*4882a593Smuzhiyun struct tsa_intrg { 128*4882a593Smuzhiyun u32 format:8; 129*4882a593Smuzhiyun u32 flags:8; 130*4882a593Smuzhiyun u32 cu_state:8; 131*4882a593Smuzhiyun u32 dev_state:8; 132*4882a593Smuzhiyun u32 op_state:8; 133*4882a593Smuzhiyun u32 :24; 134*4882a593Smuzhiyun u8 sd_info[12]; 135*4882a593Smuzhiyun u32 dl_id; 136*4882a593Smuzhiyun u8 dd_data[28]; 137*4882a593Smuzhiyun } __attribute__ ((packed)); 138*4882a593Smuzhiyun 139*4882a593Smuzhiyun #define TSB_FORMAT_NONE 0 140*4882a593Smuzhiyun #define TSB_FORMAT_IOSTAT 1 141*4882a593Smuzhiyun #define TSB_FORMAT_DDPC 2 142*4882a593Smuzhiyun #define TSB_FORMAT_INTRG 3 143*4882a593Smuzhiyun 144*4882a593Smuzhiyun #define TSB_FLAGS_DCW_OFFSET_VALID (1 << (7 - 0)) 145*4882a593Smuzhiyun #define TSB_FLAGS_COUNT_VALID (1 << (7 - 1)) 146*4882a593Smuzhiyun #define TSB_FLAGS_CACHE_MISS (1 << (7 - 2)) 147*4882a593Smuzhiyun #define TSB_FLAGS_TIME_VALID (1 << (7 - 3)) 148*4882a593Smuzhiyun #define TSB_FLAGS_FORMAT(x) ((x) & 7) 149*4882a593Smuzhiyun #define TSB_FORMAT(t) ((t)->flags & 7) 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun /** 152*4882a593Smuzhiyun * struct tsb - Transport-Status Block (TSB) 153*4882a593Smuzhiyun * @length: Length 154*4882a593Smuzhiyun * @flags: Flags. Can be an arithmetic OR of the following constants: 155*4882a593Smuzhiyun * %TSB_FLAGS_DCW_OFFSET_VALID, %TSB_FLAGS_COUNT_VALID, %TSB_FLAGS_CACHE_MISS, 156*4882a593Smuzhiyun * %TSB_FLAGS_TIME_VALID 157*4882a593Smuzhiyun * @dcw_offset: DCW Offset 158*4882a593Smuzhiyun * @count: Count 159*4882a593Smuzhiyun * @tsa: Transport-Status-Area 160*4882a593Smuzhiyun */ 161*4882a593Smuzhiyun struct tsb { 162*4882a593Smuzhiyun u32 length:8; 163*4882a593Smuzhiyun u32 flags:8; 164*4882a593Smuzhiyun u32 dcw_offset:16; 165*4882a593Smuzhiyun u32 count; 166*4882a593Smuzhiyun u32 :32; 167*4882a593Smuzhiyun union { 168*4882a593Smuzhiyun struct tsa_iostat iostat; 169*4882a593Smuzhiyun struct tsa_ddpc ddpc; 170*4882a593Smuzhiyun struct tsa_intrg intrg; 171*4882a593Smuzhiyun } __attribute__ ((packed)) tsa; 172*4882a593Smuzhiyun } __attribute__ ((packed, aligned(8))); 173*4882a593Smuzhiyun 174*4882a593Smuzhiyun #define DCW_INTRG_FORMAT_DEFAULT 0 175*4882a593Smuzhiyun 176*4882a593Smuzhiyun #define DCW_INTRG_RC_UNSPECIFIED 0 177*4882a593Smuzhiyun #define DCW_INTRG_RC_TIMEOUT 1 178*4882a593Smuzhiyun 179*4882a593Smuzhiyun #define DCW_INTRG_RCQ_UNSPECIFIED 0 180*4882a593Smuzhiyun #define DCW_INTRG_RCQ_PRIMARY 1 181*4882a593Smuzhiyun #define DCW_INTRG_RCQ_SECONDARY 2 182*4882a593Smuzhiyun 183*4882a593Smuzhiyun #define DCW_INTRG_FLAGS_MPM (1 << (7 - 0)) 184*4882a593Smuzhiyun #define DCW_INTRG_FLAGS_PPR (1 << (7 - 1)) 185*4882a593Smuzhiyun #define DCW_INTRG_FLAGS_CRIT (1 << (7 - 2)) 186*4882a593Smuzhiyun 187*4882a593Smuzhiyun /** 188*4882a593Smuzhiyun * struct dcw_intrg_data - Interrogate DCW data 189*4882a593Smuzhiyun * @format: Format. Should be %DCW_INTRG_FORMAT_DEFAULT 190*4882a593Smuzhiyun * @rc: Reason Code. Can be one of %DCW_INTRG_RC_UNSPECIFIED, 191*4882a593Smuzhiyun * %DCW_INTRG_RC_TIMEOUT 192*4882a593Smuzhiyun * @rcq: Reason Code Qualifier: Can be one of %DCW_INTRG_RCQ_UNSPECIFIED, 193*4882a593Smuzhiyun * %DCW_INTRG_RCQ_PRIMARY, %DCW_INTRG_RCQ_SECONDARY 194*4882a593Smuzhiyun * @lpm: Logical-Path Mask 195*4882a593Smuzhiyun * @pam: Path-Available Mask 196*4882a593Smuzhiyun * @pim: Path-Installed Mask 197*4882a593Smuzhiyun * @timeout: Timeout 198*4882a593Smuzhiyun * @flags: Flags. Can be an arithmetic OR of %DCW_INTRG_FLAGS_MPM, 199*4882a593Smuzhiyun * %DCW_INTRG_FLAGS_PPR, %DCW_INTRG_FLAGS_CRIT 200*4882a593Smuzhiyun * @time: Time 201*4882a593Smuzhiyun * @prog_id: Program Identifier 202*4882a593Smuzhiyun * @prog_data: Program-Dependent Data 203*4882a593Smuzhiyun */ 204*4882a593Smuzhiyun struct dcw_intrg_data { 205*4882a593Smuzhiyun u32 format:8; 206*4882a593Smuzhiyun u32 rc:8; 207*4882a593Smuzhiyun u32 rcq:8; 208*4882a593Smuzhiyun u32 lpm:8; 209*4882a593Smuzhiyun u32 pam:8; 210*4882a593Smuzhiyun u32 pim:8; 211*4882a593Smuzhiyun u32 timeout:16; 212*4882a593Smuzhiyun u32 flags:8; 213*4882a593Smuzhiyun u32 :24; 214*4882a593Smuzhiyun u32 :32; 215*4882a593Smuzhiyun u64 time; 216*4882a593Smuzhiyun u64 prog_id; 217*4882a593Smuzhiyun u8 prog_data[0]; 218*4882a593Smuzhiyun } __attribute__ ((packed)); 219*4882a593Smuzhiyun 220*4882a593Smuzhiyun #define DCW_FLAGS_CC (1 << (7 - 1)) 221*4882a593Smuzhiyun 222*4882a593Smuzhiyun #define DCW_CMD_WRITE 0x01 223*4882a593Smuzhiyun #define DCW_CMD_READ 0x02 224*4882a593Smuzhiyun #define DCW_CMD_CONTROL 0x03 225*4882a593Smuzhiyun #define DCW_CMD_SENSE 0x04 226*4882a593Smuzhiyun #define DCW_CMD_SENSE_ID 0xe4 227*4882a593Smuzhiyun #define DCW_CMD_INTRG 0x40 228*4882a593Smuzhiyun 229*4882a593Smuzhiyun /** 230*4882a593Smuzhiyun * struct dcw - Device-Command Word (DCW) 231*4882a593Smuzhiyun * @cmd: Command Code. Can be one of %DCW_CMD_WRITE, %DCW_CMD_READ, 232*4882a593Smuzhiyun * %DCW_CMD_CONTROL, %DCW_CMD_SENSE, %DCW_CMD_SENSE_ID, %DCW_CMD_INTRG 233*4882a593Smuzhiyun * @flags: Flags. Can be an arithmetic OR of %DCW_FLAGS_CC 234*4882a593Smuzhiyun * @cd_count: Control-Data Count 235*4882a593Smuzhiyun * @count: Count 236*4882a593Smuzhiyun * @cd: Control Data 237*4882a593Smuzhiyun */ 238*4882a593Smuzhiyun struct dcw { 239*4882a593Smuzhiyun u32 cmd:8; 240*4882a593Smuzhiyun u32 flags:8; 241*4882a593Smuzhiyun u32 :8; 242*4882a593Smuzhiyun u32 cd_count:8; 243*4882a593Smuzhiyun u32 count; 244*4882a593Smuzhiyun u8 cd[0]; 245*4882a593Smuzhiyun } __attribute__ ((packed)); 246*4882a593Smuzhiyun 247*4882a593Smuzhiyun #define TCCB_FORMAT_DEFAULT 0x7f 248*4882a593Smuzhiyun #define TCCB_MAX_DCW 30 249*4882a593Smuzhiyun #define TCCB_MAX_SIZE (sizeof(struct tccb_tcah) + \ 250*4882a593Smuzhiyun TCCB_MAX_DCW * sizeof(struct dcw) + \ 251*4882a593Smuzhiyun sizeof(struct tccb_tcat)) 252*4882a593Smuzhiyun #define TCCB_SAC_DEFAULT 0x1ffe 253*4882a593Smuzhiyun #define TCCB_SAC_INTRG 0x1fff 254*4882a593Smuzhiyun 255*4882a593Smuzhiyun /** 256*4882a593Smuzhiyun * struct tccb_tcah - Transport-Command-Area Header (TCAH) 257*4882a593Smuzhiyun * @format: Format. Should be %TCCB_FORMAT_DEFAULT 258*4882a593Smuzhiyun * @tcal: Transport-Command-Area Length 259*4882a593Smuzhiyun * @sac: Service-Action Code. Can be one of %TCCB_SAC_DEFAULT, %TCCB_SAC_INTRG 260*4882a593Smuzhiyun * @prio: Priority 261*4882a593Smuzhiyun */ 262*4882a593Smuzhiyun struct tccb_tcah { 263*4882a593Smuzhiyun u32 format:8; 264*4882a593Smuzhiyun u32 :24; 265*4882a593Smuzhiyun u32 :24; 266*4882a593Smuzhiyun u32 tcal:8; 267*4882a593Smuzhiyun u32 sac:16; 268*4882a593Smuzhiyun u32 :8; 269*4882a593Smuzhiyun u32 prio:8; 270*4882a593Smuzhiyun u32 :32; 271*4882a593Smuzhiyun } __attribute__ ((packed)); 272*4882a593Smuzhiyun 273*4882a593Smuzhiyun /** 274*4882a593Smuzhiyun * struct tccb_tcat - Transport-Command-Area Trailer (TCAT) 275*4882a593Smuzhiyun * @count: Transport Count 276*4882a593Smuzhiyun */ 277*4882a593Smuzhiyun struct tccb_tcat { 278*4882a593Smuzhiyun u32 :32; 279*4882a593Smuzhiyun u32 count; 280*4882a593Smuzhiyun } __attribute__ ((packed)); 281*4882a593Smuzhiyun 282*4882a593Smuzhiyun /** 283*4882a593Smuzhiyun * struct tccb - (partial) Transport-Command-Control Block (TCCB) 284*4882a593Smuzhiyun * @tcah: TCAH 285*4882a593Smuzhiyun * @tca: Transport-Command Area 286*4882a593Smuzhiyun */ 287*4882a593Smuzhiyun struct tccb { 288*4882a593Smuzhiyun struct tccb_tcah tcah; 289*4882a593Smuzhiyun u8 tca[0]; 290*4882a593Smuzhiyun } __attribute__ ((packed, aligned(8))); 291*4882a593Smuzhiyun 292*4882a593Smuzhiyun struct tcw *tcw_get_intrg(struct tcw *tcw); 293*4882a593Smuzhiyun void *tcw_get_data(struct tcw *tcw); 294*4882a593Smuzhiyun struct tccb *tcw_get_tccb(struct tcw *tcw); 295*4882a593Smuzhiyun struct tsb *tcw_get_tsb(struct tcw *tcw); 296*4882a593Smuzhiyun 297*4882a593Smuzhiyun void tcw_init(struct tcw *tcw, int r, int w); 298*4882a593Smuzhiyun void tcw_finalize(struct tcw *tcw, int num_tidaws); 299*4882a593Smuzhiyun 300*4882a593Smuzhiyun void tcw_set_intrg(struct tcw *tcw, struct tcw *intrg_tcw); 301*4882a593Smuzhiyun void tcw_set_data(struct tcw *tcw, void *data, int use_tidal); 302*4882a593Smuzhiyun void tcw_set_tccb(struct tcw *tcw, struct tccb *tccb); 303*4882a593Smuzhiyun void tcw_set_tsb(struct tcw *tcw, struct tsb *tsb); 304*4882a593Smuzhiyun 305*4882a593Smuzhiyun void tccb_init(struct tccb *tccb, size_t tccb_size, u32 sac); 306*4882a593Smuzhiyun void tsb_init(struct tsb *tsb); 307*4882a593Smuzhiyun struct dcw *tccb_add_dcw(struct tccb *tccb, size_t tccb_size, u8 cmd, u8 flags, 308*4882a593Smuzhiyun void *cd, u8 cd_count, u32 count); 309*4882a593Smuzhiyun struct tidaw *tcw_add_tidaw(struct tcw *tcw, int num_tidaws, u8 flags, 310*4882a593Smuzhiyun void *addr, u32 count); 311*4882a593Smuzhiyun 312*4882a593Smuzhiyun #endif /* _ASM_S390_FCX_H */ 313