2 * (C) Copyright 2007-2011 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * This file is released under the GPLv2. See the COPYING file for more
15 static int d3390_snprintf(struct device
*dev
, char* buf
, int len
)
17 return snprintf(buf
, len
, "%10d CYL ", dev
->eckd
.cyls
);
20 static inline unsigned int ceil_quot(unsigned int d1
, unsigned int d2
)
22 return (d1
+ (d2
- 1)) / d2
;
25 static inline int d3390_recs_per_track(int kl
, int dl
)
29 dn
= ceil_quot(dl
+ 6, 232) + 1;
31 kn
= ceil_quot(kl
+ 6, 232) + 1;
32 return 1729 / (10 + 9 + ceil_quot(kl
+ 6 * kn
, 34) +
33 9 + ceil_quot(dl
+ 6 * dn
, 34));
35 return 1729 / (10 + 9 + ceil_quot(dl
+ 6 * dn
, 34));
38 static int d3390_reg(struct device
*dev
)
46 case 0x02: /* 3390, 3390-1 */
47 case 0x06: /* 3390-2 */
48 case 0x0a: /* 3390-3 */
49 case 0x0c: /* 3390-9, 3390-27, 3390-J, 3390-54, 3390-JJ */
56 * Set up IO op for Read Device Characteristics
61 memset(&ioop
.orb
, 0, sizeof(struct orb
));
63 ioop
.orb
.addr
= ADDR31(&ccw
);
66 memset(&ccw
, 0, sizeof(struct ccw
));
67 ccw
.cmd
= 0x64; /* RDC */
68 ccw
.flags
= CCW_FLAG_SLI
;
70 ccw
.addr
= ADDR31(buf
);
75 ret
= submit_io(dev
, &ioop
, CAN_LOOP
);
79 dev
->eckd
.cyls
= (buf
[12] << 8) |
81 dev
->eckd
.tracks
= (buf
[14] << 8) |
83 dev
->eckd
.recs
= d3390_recs_per_track(0, 4096);
84 dev
->eckd
.sectors
= buf
[16];
85 dev
->eckd
.len
= (buf
[18] << 8) |
88 dev
->eckd
.formula
= buf
[22];
89 if (dev
->eckd
.formula
== 1) {
90 dev
->eckd
.f1
= buf
[23];
91 dev
->eckd
.f2
= (buf
[24] << 8) |
93 dev
->eckd
.f3
= (buf
[26] << 8) |
97 } else if (dev
->eckd
.formula
== 2) {
98 dev
->eckd
.f1
= buf
[23];
99 dev
->eckd
.f2
= buf
[24];
100 dev
->eckd
.f3
= buf
[25];
101 dev
->eckd
.f4
= buf
[26];
102 dev
->eckd
.f5
= buf
[27];
109 static int d3390_read(struct device
*dev
, u8
*buf
, int lba
)
118 int rpt
= dev
->eckd
.recs
;
119 int rpc
= dev
->eckd
.tracks
* rpt
;
126 hh
= (lba
% rpc
) / rpt
;
127 r
= (lba
% rpc
) % rpt
;
136 memset(&ioop
.orb
, 0, sizeof(struct orb
));
138 ioop
.orb
.addr
= ADDR31(ccw
);
141 memset(ccw
, 0, sizeof(ccw
));
145 ccw
[0].flags
= CCW_FLAG_CC
| CCW_FLAG_SLI
;
147 ccw
[0].addr
= ADDR31(seek_data
);
149 seek_data
[0] = 0; /* zero */
150 seek_data
[1] = 0; /* zero */
151 seek_data
[2] = cc
>> 8; /* Cc */
152 seek_data
[3] = cc
& 0xff; /* cC */
153 seek_data
[4] = hh
>> 8; /* Hh */
154 seek_data
[5] = hh
& 0xff; /* hH */
158 ccw
[1].flags
= CCW_FLAG_CC
| CCW_FLAG_SLI
;
160 ccw
[1].addr
= ADDR31(search_data
);
162 search_data
[0] = cc
>> 8;
163 search_data
[1] = cc
& 0xff;
164 search_data
[2] = hh
>> 8;
165 search_data
[3] = hh
& 0xff;
172 ccw
[2].addr
= ADDR31(&ccw
[1]);
178 ccw
[3].addr
= ADDR31(buf
);
183 ret
= submit_io(dev
, &ioop
, CAN_SLEEP
);
187 static struct device_type d3390
= {
188 .types
= LIST_HEAD_INIT(d3390
.types
),
192 .snprintf
= d3390_snprintf
,
200 /******************************************************************************/
202 static int d9336_snprintf(struct device
*dev
, char* buf
, int len
)
204 return snprintf(buf
, len
, "%10d BLK ", dev
->fba
.blks
);
207 static int d9336_reg(struct device
*dev
)
215 case 0x00: /* 9336-10 */
216 case 0x10: /* 9336-20 */
223 * Set up IO op for Read Device Characteristics
228 memset(&ioop
.orb
, 0, sizeof(struct orb
));
230 ioop
.orb
.addr
= ADDR31(&ccw
);
233 memset(&ccw
, 0, sizeof(struct ccw
));
234 ccw
.cmd
= 0x64; /* RDC */
235 ccw
.flags
= CCW_FLAG_SLI
;
237 ccw
.addr
= ADDR31(buf
);
242 ret
= submit_io(dev
, &ioop
, CAN_LOOP
);
246 dev
->fba
.blk_size
= (buf
[4] << 8) | buf
[5];
247 dev
->fba
.bpg
= (buf
[6] << 24) |
251 dev
->fba
.bpp
= (buf
[10] << 24) |
255 dev
->fba
.blks
= (buf
[14] << 24) |
263 static struct device_type d9336
= {
264 .types
= LIST_HEAD_INIT(d9336
.types
),
268 .snprintf
= d9336_snprintf
,
273 int register_driver_dasd(void)
277 ret
= register_device_type(&d3390
);
281 return register_device_type(&d9336
);