This source file includes following definitions.
- tcw_get_intrg
- tcw_get_data
- tcw_get_tccb
- tcw_get_tsb
- tcw_init
- tca_size
- calc_dcw_count
- calc_cbc_size
- tcw_finalize
- tcw_set_intrg
- tcw_set_data
- tcw_set_tccb
- tcw_set_tsb
- tccb_init
- tsb_init
- tccb_add_dcw
- tcw_add_tidaw
1
2
3
4
5
6
7
8
9 #include <linux/kernel.h>
10 #include <linux/types.h>
11 #include <linux/string.h>
12 #include <linux/errno.h>
13 #include <linux/err.h>
14 #include <linux/module.h>
15 #include <asm/fcx.h>
16 #include "cio.h"
17
18
19
20
21
22
23
24
25 struct tcw *tcw_get_intrg(struct tcw *tcw)
26 {
27 return (struct tcw *) ((addr_t) tcw->intrg);
28 }
29 EXPORT_SYMBOL(tcw_get_intrg);
30
31
32
33
34
35
36
37
38
39 void *tcw_get_data(struct tcw *tcw)
40 {
41 if (tcw->r)
42 return (void *) ((addr_t) tcw->input);
43 if (tcw->w)
44 return (void *) ((addr_t) tcw->output);
45 return NULL;
46 }
47 EXPORT_SYMBOL(tcw_get_data);
48
49
50
51
52
53
54
55 struct tccb *tcw_get_tccb(struct tcw *tcw)
56 {
57 return (struct tccb *) ((addr_t) tcw->tccb);
58 }
59 EXPORT_SYMBOL(tcw_get_tccb);
60
61
62
63
64
65
66
67 struct tsb *tcw_get_tsb(struct tcw *tcw)
68 {
69 return (struct tsb *) ((addr_t) tcw->tsb);
70 }
71 EXPORT_SYMBOL(tcw_get_tsb);
72
73
74
75
76
77
78
79
80
81
82 void tcw_init(struct tcw *tcw, int r, int w)
83 {
84 memset(tcw, 0, sizeof(struct tcw));
85 tcw->format = TCW_FORMAT_DEFAULT;
86 tcw->flags = TCW_FLAGS_TIDAW_FORMAT(TCW_TIDAW_FORMAT_DEFAULT);
87 if (r)
88 tcw->r = 1;
89 if (w)
90 tcw->w = 1;
91 }
92 EXPORT_SYMBOL(tcw_init);
93
94 static inline size_t tca_size(struct tccb *tccb)
95 {
96 return tccb->tcah.tcal - 12;
97 }
98
99 static u32 calc_dcw_count(struct tccb *tccb)
100 {
101 int offset;
102 struct dcw *dcw;
103 u32 count = 0;
104 size_t size;
105
106 size = tca_size(tccb);
107 for (offset = 0; offset < size;) {
108 dcw = (struct dcw *) &tccb->tca[offset];
109 count += dcw->count;
110 if (!(dcw->flags & DCW_FLAGS_CC))
111 break;
112 offset += sizeof(struct dcw) + ALIGN((int) dcw->cd_count, 4);
113 }
114 return count;
115 }
116
117 static u32 calc_cbc_size(struct tidaw *tidaw, int num)
118 {
119 int i;
120 u32 cbc_data;
121 u32 cbc_count = 0;
122 u64 data_count = 0;
123
124 for (i = 0; i < num; i++) {
125 if (tidaw[i].flags & TIDAW_FLAGS_LAST)
126 break;
127
128
129
130 data_count += tidaw[i].count;
131 if (tidaw[i].flags & TIDAW_FLAGS_INSERT_CBC) {
132 cbc_data = 4 + ALIGN(data_count, 4) - data_count;
133 cbc_count += cbc_data;
134 data_count += cbc_data;
135 }
136 }
137 return cbc_count;
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 void tcw_finalize(struct tcw *tcw, int num_tidaws)
154 {
155 struct tidaw *tidaw;
156 struct tccb *tccb;
157 struct tccb_tcat *tcat;
158 u32 count;
159
160
161 tidaw = tcw_get_data(tcw);
162 if (num_tidaws > 0)
163 tidaw[num_tidaws - 1].flags |= TIDAW_FLAGS_LAST;
164
165 tccb = tcw_get_tccb(tcw);
166 tcat = (struct tccb_tcat *) &tccb->tca[tca_size(tccb)];
167 memset(tcat, 0, sizeof(*tcat));
168
169 count = calc_dcw_count(tccb);
170 if (tcw->w && (tcw->flags & TCW_FLAGS_OUTPUT_TIDA))
171 count += calc_cbc_size(tidaw, num_tidaws);
172 if (tcw->r)
173 tcw->input_count = count;
174 else if (tcw->w)
175 tcw->output_count = count;
176 tcat->count = ALIGN(count, 4) + 4;
177
178 tcw->tccbl = (sizeof(struct tccb) + tca_size(tccb) +
179 sizeof(struct tccb_tcat) - 20) >> 2;
180 }
181 EXPORT_SYMBOL(tcw_finalize);
182
183
184
185
186
187
188
189
190 void tcw_set_intrg(struct tcw *tcw, struct tcw *intrg_tcw)
191 {
192 tcw->intrg = (u32) ((addr_t) intrg_tcw);
193 }
194 EXPORT_SYMBOL(tcw_set_intrg);
195
196
197
198
199
200
201
202
203
204
205
206
207 void tcw_set_data(struct tcw *tcw, void *data, int use_tidal)
208 {
209 if (tcw->r) {
210 tcw->input = (u64) ((addr_t) data);
211 if (use_tidal)
212 tcw->flags |= TCW_FLAGS_INPUT_TIDA;
213 } else if (tcw->w) {
214 tcw->output = (u64) ((addr_t) data);
215 if (use_tidal)
216 tcw->flags |= TCW_FLAGS_OUTPUT_TIDA;
217 }
218 }
219 EXPORT_SYMBOL(tcw_set_data);
220
221
222
223
224
225
226
227
228 void tcw_set_tccb(struct tcw *tcw, struct tccb *tccb)
229 {
230 tcw->tccb = (u64) ((addr_t) tccb);
231 }
232 EXPORT_SYMBOL(tcw_set_tccb);
233
234
235
236
237
238
239
240
241 void tcw_set_tsb(struct tcw *tcw, struct tsb *tsb)
242 {
243 tcw->tsb = (u64) ((addr_t) tsb);
244 }
245 EXPORT_SYMBOL(tcw_set_tsb);
246
247
248
249
250
251
252
253
254
255
256 void tccb_init(struct tccb *tccb, size_t size, u32 sac)
257 {
258 memset(tccb, 0, size);
259 tccb->tcah.format = TCCB_FORMAT_DEFAULT;
260 tccb->tcah.sac = sac;
261 tccb->tcah.tcal = 12;
262 }
263 EXPORT_SYMBOL(tccb_init);
264
265
266
267
268
269
270
271 void tsb_init(struct tsb *tsb)
272 {
273 memset(tsb, 0, sizeof(*tsb));
274 }
275 EXPORT_SYMBOL(tsb_init);
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295 struct dcw *tccb_add_dcw(struct tccb *tccb, size_t tccb_size, u8 cmd, u8 flags,
296 void *cd, u8 cd_count, u32 count)
297 {
298 struct dcw *dcw;
299 int size;
300 int tca_offset;
301
302
303 tca_offset = tca_size(tccb);
304 size = ALIGN(sizeof(struct dcw) + cd_count, 4);
305 if (sizeof(struct tccb_tcah) + tca_offset + size +
306 sizeof(struct tccb_tcat) > tccb_size)
307 return ERR_PTR(-ENOSPC);
308
309 dcw = (struct dcw *) &tccb->tca[tca_offset];
310 memset(dcw, 0, size);
311 dcw->cmd = cmd;
312 dcw->flags = flags;
313 dcw->count = count;
314 dcw->cd_count = cd_count;
315 if (cd)
316 memcpy(&dcw->cd[0], cd, cd_count);
317 tccb->tcah.tcal += size;
318 return dcw;
319 }
320 EXPORT_SYMBOL(tccb_add_dcw);
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338 struct tidaw *tcw_add_tidaw(struct tcw *tcw, int num_tidaws, u8 flags,
339 void *addr, u32 count)
340 {
341 struct tidaw *tidaw;
342
343
344 tidaw = ((struct tidaw *) tcw_get_data(tcw)) + num_tidaws;
345 memset(tidaw, 0, sizeof(struct tidaw));
346 tidaw->flags = flags;
347 tidaw->count = count;
348 tidaw->addr = (u64) ((addr_t) addr);
349 return tidaw;
350 }
351 EXPORT_SYMBOL(tcw_add_tidaw);