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