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