loader: remove shouting from ORB's variable name
[hvf.git] / cp / drivers / dasd.c
blobc1eebc2d231a820797206bb681b6e0e3eaf79e98
1 /*
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
5 * details.
6 */
8 #include <device.h>
9 #include <console.h>
10 #include <list.h>
11 #include <io.h>
12 #include <sched.h>
13 #include <vsprintf.h>
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)
27 int dn, kn;
29 dn = ceil_quot(dl + 6, 232) + 1;
30 if (kl) {
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));
34 } else
35 return 1729 / (10 + 9 + ceil_quot(dl + 6 * dn, 34));
38 static int d3390_reg(struct device *dev)
40 struct io_op ioop;
41 struct ccw ccw;
42 int ret;
43 u8 buf[64];
45 switch(dev->model) {
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 */
50 break;
51 default:
52 return -ENOENT;
56 * Set up IO op for Read Device Characteristics
58 ioop.handler = NULL;
59 ioop.dtor = NULL;
61 memset(&ioop.orb, 0, sizeof(struct orb));
62 ioop.orb.lpm = 0xff;
63 ioop.orb.addr = ADDR31(&ccw);
64 ioop.orb.f = 1;
66 memset(&ccw, 0, sizeof(struct ccw));
67 ccw.cmd = 0x64; /* RDC */
68 ccw.flags = CCW_FLAG_SLI;
69 ccw.count = 64;
70 ccw.addr = ADDR31(buf);
73 * issue RDC
75 ret = submit_io(dev, &ioop, CAN_LOOP);
76 if (ret)
77 return ret;
79 dev->eckd.cyls = (buf[12] << 8) |
80 buf[13];
81 dev->eckd.tracks = (buf[14] << 8) |
82 buf[15];
83 dev->eckd.recs = d3390_recs_per_track(0, 4096);
84 dev->eckd.sectors = buf[16];
85 dev->eckd.len = (buf[18] << 8) |
86 buf[19];
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) |
92 buf[25];
93 dev->eckd.f3 = (buf[26] << 8) |
94 buf[27];
95 dev->eckd.f4 = 0;
96 dev->eckd.f5 = 0;
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];
103 } else
104 return -EINVAL;
106 return 0;
109 static int d3390_read(struct device *dev, u8 *buf, int lba)
111 struct io_op ioop;
112 struct ccw ccw[4];
113 u8 seek_data[6];
114 u8 search_data[5];
115 int ret;
117 u16 cc, hh, r;
118 int rpt = dev->eckd.recs;
119 int rpc = dev->eckd.tracks * rpt;
121 if (lba < 1)
122 return -EINVAL;
124 lba--;
125 cc = lba / rpc;
126 hh = (lba % rpc) / rpt;
127 r = (lba % rpc) % rpt;
128 r++;
131 * Set up IO op
133 ioop.handler = NULL;
134 ioop.dtor = NULL;
136 memset(&ioop.orb, 0, sizeof(struct orb));
137 ioop.orb.lpm = 0xff;
138 ioop.orb.addr = ADDR31(ccw);
139 ioop.orb.f = 1;
141 memset(ccw, 0, sizeof(ccw));
143 /* SEEK */
144 ccw[0].cmd = 0x07;
145 ccw[0].flags = CCW_FLAG_CC | CCW_FLAG_SLI;
146 ccw[0].count = 6;
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 */
156 /* SEARCH */
157 ccw[1].cmd = 0x31;
158 ccw[1].flags = CCW_FLAG_CC | CCW_FLAG_SLI;
159 ccw[1].count = 5;
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;
166 search_data[4] = r;
168 /* TIC */
169 ccw[2].cmd = 0x08;
170 ccw[2].flags = 0;
171 ccw[2].count = 0;
172 ccw[2].addr = ADDR31(&ccw[1]);
174 /* READ DATA */
175 ccw[3].cmd = 0x86;
176 ccw[3].flags = 0;
177 ccw[3].count = 4096;
178 ccw[3].addr = ADDR31(buf);
181 * issue IO
183 ret = submit_io(dev, &ioop, CAN_SLEEP);
184 return ret;
187 static struct device_type d3390 = {
188 .types = LIST_HEAD_INIT(d3390.types),
189 .reg = d3390_reg,
190 .interrupt = NULL,
191 .enable = NULL,
192 .snprintf = d3390_snprintf,
194 .read = d3390_read,
196 .type = 0x3390,
197 .all_models = true,
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)
209 struct io_op ioop;
210 struct ccw ccw;
211 int ret;
212 u8 buf[64];
214 switch(dev->model) {
215 case 0x00: /* 9336-10 */
216 case 0x10: /* 9336-20 */
217 break;
218 default:
219 return -ENOENT;
223 * Set up IO op for Read Device Characteristics
225 ioop.handler = NULL;
226 ioop.dtor = NULL;
228 memset(&ioop.orb, 0, sizeof(struct orb));
229 ioop.orb.lpm = 0xff;
230 ioop.orb.addr = ADDR31(&ccw);
231 ioop.orb.f = 1;
233 memset(&ccw, 0, sizeof(struct ccw));
234 ccw.cmd = 0x64; /* RDC */
235 ccw.flags = CCW_FLAG_SLI;
236 ccw.count = 64;
237 ccw.addr = ADDR31(buf);
240 * issue RDC
242 ret = submit_io(dev, &ioop, CAN_LOOP);
243 if (ret)
244 return ret;
246 dev->fba.blk_size = (buf[4] << 8) | buf[5];
247 dev->fba.bpg = (buf[6] << 24) |
248 (buf[7] << 16) |
249 (buf[8] << 8) |
250 buf[9];
251 dev->fba.bpp = (buf[10] << 24) |
252 (buf[11] << 16) |
253 (buf[12] << 8) |
254 buf[13];
255 dev->fba.blks= (buf[14] << 24) |
256 (buf[15] << 16) |
257 (buf[16] << 8) |
258 buf[17];
260 return 0;
263 static struct device_type d9336 = {
264 .types = LIST_HEAD_INIT(d9336.types),
265 .reg = d9336_reg,
266 .interrupt = NULL,
267 .enable = NULL,
268 .snprintf = d9336_snprintf,
269 .type = 0x9336,
270 .all_models = true,
273 int register_driver_dasd(void)
275 int ret;
277 ret = register_device_type(&d3390);
278 if (ret)
279 return ret;
281 return register_device_type(&d9336);