Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
s390
cio
fcx.c
Go to the documentation of this file.
1
/*
2
* Functions for assembling fcx enabled I/O control blocks.
3
*
4
* Copyright IBM Corp. 2008
5
* Author(s): Peter Oberparleiter <
[email protected]
>
6
*/
7
8
#include <linux/kernel.h>
9
#include <linux/types.h>
10
#include <linux/string.h>
11
#include <linux/errno.h>
12
#include <
linux/err.h
>
13
#include <linux/module.h>
14
#include <
asm/fcx.h
>
15
#include "
cio.h
"
16
24
struct
tcw
*
tcw_get_intrg
(
struct
tcw
*
tcw
)
25
{
26
return
(
struct
tcw *) ((
addr_t
) tcw->
intrg
);
27
}
28
EXPORT_SYMBOL
(
tcw_get_intrg
);
29
38
void
*
tcw_get_data
(
struct
tcw
*
tcw
)
39
{
40
if
(tcw->
r
)
41
return
(
void
*) ((
addr_t
) tcw->
input
);
42
if
(tcw->
w
)
43
return
(
void
*) ((
addr_t
) tcw->
output
);
44
return
NULL
;
45
}
46
EXPORT_SYMBOL
(
tcw_get_data
);
47
54
struct
tccb
*
tcw_get_tccb
(
struct
tcw
*
tcw
)
55
{
56
return
(
struct
tccb
*) ((
addr_t
) tcw->
tccb
);
57
}
58
EXPORT_SYMBOL
(
tcw_get_tccb
);
59
66
struct
tsb
*
tcw_get_tsb
(
struct
tcw
*
tcw
)
67
{
68
return
(
struct
tsb
*) ((
addr_t
) tcw->
tsb
);
69
}
70
EXPORT_SYMBOL
(
tcw_get_tsb
);
71
81
void
tcw_init
(
struct
tcw
*
tcw
,
int
r
,
int
w
)
82
{
83
memset
(tcw, 0,
sizeof
(
struct
tcw));
84
tcw->
format
=
TCW_FORMAT_DEFAULT
;
85
tcw->
flags
=
TCW_FLAGS_TIDAW_FORMAT
(
TCW_TIDAW_FORMAT_DEFAULT
);
86
if
(r)
87
tcw->
r
= 1;
88
if
(w)
89
tcw->
w
= 1;
90
}
91
EXPORT_SYMBOL
(
tcw_init
);
92
93
static
inline
size_t
tca_size(
struct
tccb
*
tccb
)
94
{
95
return
tccb->
tcah
.tcal - 12;
96
}
97
98
static
u32
calc_dcw_count(
struct
tccb
*
tccb
)
99
{
100
int
offset
;
101
struct
dcw
*
dcw
;
102
u32
count
= 0;
103
size_t
size
;
104
105
size = tca_size(tccb);
106
for
(offset = 0; offset <
size
;) {
107
dcw = (
struct
dcw *) &tccb->
tca
[offset];
108
count += dcw->
count
;
109
if
(!(dcw->
flags
&
DCW_FLAGS_CC
))
110
break
;
111
offset +=
sizeof
(
struct
dcw) +
ALIGN
((
int
) dcw->
cd_count
, 4);
112
}
113
return
count
;
114
}
115
116
static
u32
calc_cbc_size(
struct
tidaw
*
tidaw
,
int
num)
117
{
118
int
i
;
119
u32
cbc_data;
120
u32
cbc_count = 0;
121
u64
data_count
= 0;
122
123
for
(i = 0; i < num; i++) {
124
if
(tidaw[i].
flags
&
TIDAW_FLAGS_LAST
)
125
break
;
126
/* TODO: find out if padding applies to total of data
127
* transferred or data transferred by this tidaw. Assumption:
128
* applies to total. */
129
data_count += tidaw[
i
].
count
;
130
if
(tidaw[i].
flags
&
TIDAW_FLAGS_INSERT_CBC
) {
131
cbc_data = 4 +
ALIGN
(data_count, 4) -
data_count
;
132
cbc_count += cbc_data;
133
data_count += cbc_data;
134
}
135
}
136
return
cbc_count;
137
}
138
152
void
tcw_finalize
(
struct
tcw
*
tcw
,
int
num_tidaws)
153
{
154
struct
tidaw *tidaw;
155
struct
tccb *
tccb
;
156
struct
tccb_tcat
*tcat;
157
u32
count
;
158
159
/* Terminate tidaw list. */
160
tidaw =
tcw_get_data
(tcw);
161
if
(num_tidaws > 0)
162
tidaw[num_tidaws - 1].
flags
|=
TIDAW_FLAGS_LAST
;
163
/* Add tcat to tccb. */
164
tccb =
tcw_get_tccb
(tcw);
165
tcat = (
struct
tccb_tcat
*) &tccb->
tca
[tca_size(tccb)];
166
memset
(tcat, 0,
sizeof
(*tcat));
167
/* Calculate tcw input/output count and tcat transport count. */
168
count = calc_dcw_count(tccb);
169
if
(tcw->
w
&& (tcw->
flags
&
TCW_FLAGS_OUTPUT_TIDA
))
170
count += calc_cbc_size(tidaw, num_tidaws);
171
if
(tcw->
r
)
172
tcw->
input_count
=
count
;
173
else
if
(tcw->
w
)
174
tcw->
output_count
=
count
;
175
tcat->
count
=
ALIGN
(count, 4) + 4;
176
/* Calculate tccbl. */
177
tcw->
tccbl
= (
sizeof
(
struct
tccb) + tca_size(tccb) +
178
sizeof(struct tccb_tcat) - 20) >> 2;
179
}
180
EXPORT_SYMBOL
(
tcw_finalize
);
181
189
void
tcw_set_intrg
(
struct
tcw
*
tcw
,
struct
tcw *intrg_tcw)
190
{
191
tcw->
intrg
= (
u32
) ((
addr_t
) intrg_tcw);
192
}
193
EXPORT_SYMBOL
(
tcw_set_intrg
);
194
206
void
tcw_set_data
(
struct
tcw
*
tcw
,
void
*
data
,
int
use_tidal)
207
{
208
if
(tcw->
r
) {
209
tcw->
input
= (
u64
) ((
addr_t
)
data
);
210
if
(use_tidal)
211
tcw->
flags
|=
TCW_FLAGS_INPUT_TIDA
;
212
}
else
if
(tcw->
w
) {
213
tcw->
output
= (
u64
) ((
addr_t
)
data
);
214
if
(use_tidal)
215
tcw->
flags
|=
TCW_FLAGS_OUTPUT_TIDA
;
216
}
217
}
218
EXPORT_SYMBOL
(
tcw_set_data
);
219
227
void
tcw_set_tccb
(
struct
tcw
*
tcw
,
struct
tccb *tccb)
228
{
229
tcw->
tccb
= (
u64
) ((
addr_t
)
tccb
);
230
}
231
EXPORT_SYMBOL
(
tcw_set_tccb
);
232
240
void
tcw_set_tsb
(
struct
tcw
*
tcw
,
struct
tsb
*
tsb
)
241
{
242
tcw->
tsb
= (
u64
) ((
addr_t
)
tsb
);
243
}
244
EXPORT_SYMBOL
(
tcw_set_tsb
);
245
255
void
tccb_init
(
struct
tccb *tccb,
size_t
size,
u32
sac
)
256
{
257
memset
(tccb, 0, size);
258
tccb->
tcah
.format =
TCCB_FORMAT_DEFAULT
;
259
tccb->
tcah
.sac =
sac
;
260
tccb->
tcah
.tcal = 12;
261
}
262
EXPORT_SYMBOL
(
tccb_init
);
263
270
void
tsb_init
(
struct
tsb
*
tsb
)
271
{
272
memset
(tsb, 0,
sizeof
(*tsb));
273
}
274
EXPORT_SYMBOL
(
tsb_init
);
275
294
struct
dcw *
tccb_add_dcw
(
struct
tccb *tccb,
size_t
tccb_size,
u8
cmd
,
u8
flags
,
295
void
*
cd
,
u8
cd_count
,
u32
count)
296
{
297
struct
dcw *dcw;
298
int
size
;
299
int
tca_offset;
300
301
/* Check for space. */
302
tca_offset = tca_size(tccb);
303
size =
ALIGN
(
sizeof
(
struct
dcw) + cd_count, 4);
304
if
(
sizeof
(
struct
tccb_tcah
) + tca_offset + size +
305
sizeof
(
struct
tccb_tcat
) > tccb_size)
306
return
ERR_PTR(-
ENOSPC
);
307
/* Add dcw to tca. */
308
dcw = (
struct
dcw *) &tccb->
tca
[tca_offset];
309
memset
(dcw, 0, size);
310
dcw->
cmd
=
cmd
;
311
dcw->
flags
=
flags
;
312
dcw->
count
=
count
;
313
dcw->
cd_count
=
cd_count
;
314
if
(cd)
315
memcpy
(&dcw->
cd
[0], cd, cd_count);
316
tccb->
tcah
.tcal +=
size
;
317
return
dcw;
318
}
319
EXPORT_SYMBOL
(
tccb_add_dcw
);
320
337
struct
tidaw *
tcw_add_tidaw
(
struct
tcw
*
tcw
,
int
num_tidaws,
u8
flags
,
338
void
*
addr
,
u32
count)
339
{
340
struct
tidaw *tidaw;
341
342
/* Add tidaw to tidaw-list. */
343
tidaw = ((
struct
tidaw *)
tcw_get_data
(tcw)) + num_tidaws;
344
memset
(tidaw, 0,
sizeof
(
struct
tidaw));
345
tidaw->
flags
=
flags
;
346
tidaw->
count
=
count
;
347
tidaw->
addr
= (
u64
) ((
addr_t
)
addr
);
348
return
tidaw;
349
}
350
EXPORT_SYMBOL
(
tcw_add_tidaw
);
Generated on Thu Jan 10 2013 14:17:52 for Linux Kernel by
1.8.2