Commit | Line | Data |
---|---|---|
ba783028 | 1 | /* hp.c 4.64 83/02/10 */ |
b70e4030 BJ |
2 | |
3 | #ifdef HPDEBUG | |
6ac24ecd | 4 | int hpdebug; |
b70e4030 BJ |
5 | #endif |
6 | #ifdef HPBDEBUG | |
7 | int hpbdebug; | |
8 | #endif | |
04b9d53d | 9 | |
66b4fb09 | 10 | #include "hp.h" |
a5cc519e | 11 | #if NHP > 0 |
04b9d53d | 12 | /* |
b19f1d3a | 13 | * HP disk driver for RP0x+RMxx+ML11 |
1b81ee79 BJ |
14 | * |
15 | * TODO: | |
b70e4030 | 16 | * check RM80 skip sector handling when ECC's occur later |
d565635a | 17 | * check offset recovery handling |
b70e4030 BJ |
18 | * see if DCLR and/or RELEASE set attention status |
19 | * print bits of mr && mr2 symbolically | |
04b9d53d | 20 | */ |
961945a8 | 21 | #include "../machine/pte.h" |
04b9d53d BJ |
22 | |
23 | #include "../h/param.h" | |
24 | #include "../h/systm.h" | |
41888f16 | 25 | #include "../h/dk.h" |
04b9d53d BJ |
26 | #include "../h/buf.h" |
27 | #include "../h/conf.h" | |
28 | #include "../h/dir.h" | |
29 | #include "../h/user.h" | |
30 | #include "../h/map.h" | |
c895c266 | 31 | #include "../vax/mtpr.h" |
80e7c811 | 32 | #include "../h/vm.h" |
e3b4b145 | 33 | #include "../h/cmap.h" |
b70e4030 | 34 | #include "../h/dkbad.h" |
942f05a9 | 35 | #include "../h/ioctl.h" |
deb8980a | 36 | #include "../h/uio.h" |
04b9d53d | 37 | |
f13af4da | 38 | #include "../vax/dkio.h" |
c895c266 BJ |
39 | #include "../vaxmba/mbareg.h" |
40 | #include "../vaxmba/mbavar.h" | |
41 | #include "../vaxmba/hpreg.h" | |
04b9d53d | 42 | |
b81fd3e8 BJ |
43 | /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ |
44 | struct size { | |
04b9d53d BJ |
45 | daddr_t nblocks; |
46 | int cyloff; | |
b70e4030 | 47 | } hp6_sizes[8] = { |
5c777efe BJ |
48 | 15884, 0, /* A=cyl 0 thru 37 */ |
49 | 33440, 38, /* B=cyl 38 thru 117 */ | |
50 | 340670, 0, /* C=cyl 0 thru 814 */ | |
04b9d53d | 51 | 0, 0, |
04b9d53d BJ |
52 | 0, 0, |
53 | 0, 0, | |
e897671e | 54 | 291280, 118, /* G=cyl 118 thru 814 */ |
04b9d53d | 55 | 0, 0, |
b70e4030 | 56 | }, rm3_sizes[8] = { |
5c777efe BJ |
57 | 15884, 0, /* A=cyl 0 thru 99 */ |
58 | 33440, 100, /* B=cyl 100 thru 309 */ | |
59 | 131680, 0, /* C=cyl 0 thru 822 */ | |
6edc8b46 | 60 | 0, 0, |
04b9d53d BJ |
61 | 0, 0, |
62 | 0, 0, | |
e897671e | 63 | 81984, 310, /* G=cyl 310 thru 822 */ |
04b9d53d | 64 | 0, 0, |
5c777efe BJ |
65 | }, rm5_sizes[8] = { |
66 | 15884, 0, /* A=cyl 0 thru 26 */ | |
67 | 33440, 27, /* B=cyl 27 thru 81 */ | |
e83ccfd7 | 68 | 500384, 0, /* C=cyl 0 thru 822 */ |
5c777efe BJ |
69 | 15884, 562, /* D=cyl 562 thru 588 */ |
70 | 55936, 589, /* E=cyl 589 thru 680 */ | |
e897671e BJ |
71 | 86240, 681, /* F=cyl 681 thru 822 */ |
72 | 158592, 562, /* G=cyl 562 thru 822 */ | |
5c777efe | 73 | 291346, 82, /* H=cyl 82 thru 561 */ |
b81fd3e8 BJ |
74 | }, rm80_sizes[8] = { |
75 | 15884, 0, /* A=cyl 0 thru 36 */ | |
76 | 33440, 37, /* B=cyl 37 thru 114 */ | |
77 | 242606, 0, /* C=cyl 0 thru 558 */ | |
78 | 0, 0, | |
79 | 0, 0, | |
80 | 0, 0, | |
81 | 82080, 115, /* G=cyl 115 thru 304 */ | |
e897671e | 82 | 110143, 305, /* H=cyl 305 thru 558 */ |
b70e4030 | 83 | }, hp7_sizes[8] = { |
822a683f | 84 | 15884, 0, /* A=cyl 0 thru 9 */ |
b70e4030 BJ |
85 | 64000, 10, /* B=cyl 10 thru 49 */ |
86 | 1008000,0, /* C=cyl 0 thru 629 */ | |
87 | 15884, 330, /* D=cyl 330 thru 339 */ | |
88 | 256000, 340, /* E=cyl 340 thru 499 */ | |
e897671e BJ |
89 | 207850, 500, /* F=cyl 500 thru 629 */ |
90 | 479850, 330, /* G=cyl 330 thru 629 */ | |
b70e4030 | 91 | 448000, 50, /* H=cyl 50 thru 329 */ |
822a683f | 92 | }, si9775_sizes[8] = { |
ba783028 SL |
93 | 16640, 0, /* A=cyl 0 thru 12 */ |
94 | 34560, 13, /* B=cyl 13 thru 39 */ | |
95 | 1079040, 0, /* C=cyl 0 thru 842 */ | |
96 | 0, 0, | |
97 | 0, 0, | |
98 | 0, 0, | |
99 | 513280, 40, /* G=cyl 40 thru 440 */ | |
822a683f SL |
100 | 513280, 441, /* H=cyl 441 thru 841 */ |
101 | }, si9730_sizes[8] = { | |
102 | 15884, 0, /* A=cyl 0 thru 49 */ | |
103 | 33440, 50, /* B=cyl 50 thru 154 */ | |
104 | 263360, 0, /* C=cyl 0 thru 822 */ | |
105 | 0, 0, | |
106 | 0, 0, | |
107 | 0, 0, | |
108 | 0, 0, | |
822a683f | 109 | 213664, 155, /* H=cyl 155 thru 822 */ |
822a683f SL |
110 | }, hpam_sizes[8] = { |
111 | 15884, 0, /* A=cyl 0 thru 31 */ | |
112 | 33440, 32, /* B=cyl 32 thru 97 */ | |
113 | 524288, 0, /* C=cyl 0 thru 1023 */ | |
114 | 27786, 668, | |
115 | 27786, 723, | |
116 | 125440, 778, | |
117 | 181760, 668, /* G=cyl 668 thru 1022 */ | |
118 | 291346, 98, /* H=cyl 98 thru 667 */ | |
e74d4c15 SL |
119 | }, hpfj_sizes[8] = { |
120 | 15884, 0, /* A=cyl 0 thru 18 */ | |
121 | 33440, 19, /* B=cyl 19 thru 58 */ | |
7ca1a4fe | 122 | 724120, 0, /* C=cyl 0 thru 841 */ |
e74d4c15 SL |
123 | 0, 0, |
124 | 0, 0, | |
125 | 0, 0, | |
126 | 381711, 398, /* G=cyl 398 thru 841 */ | |
127 | 291346, 59, /* H=cyl 59 thru 397 */ | |
2be84ab1 SL |
128 | }, hpfj48_sizes[8] = { |
129 | 15884, 0, /* A=cyl 0 thru 16 */ | |
130 | 33440, 17, /* B=cyl 17 thru 52 */ | |
131 | 808176, 0, /* C=cyl 0 thru 841 */ | |
132 | 0, 0, | |
133 | 0, 0, | |
134 | 0, 0, | |
135 | 465456, 357, /* G=cyl 357 thru 841 */ | |
136 | 291346, 53, /* H=cyl 52 thru 356 */ | |
04b9d53d | 137 | }; |
b81fd3e8 | 138 | /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ |
04b9d53d | 139 | |
b81fd3e8 BJ |
140 | #define _hpSDIST 2 |
141 | #define _hpRDIST 3 | |
142 | ||
143 | int hpSDIST = _hpSDIST; | |
144 | int hpRDIST = _hpRDIST; | |
145 | ||
822a683f SL |
146 | /* |
147 | * Table for converting Massbus drive types into | |
148 | * indices into the partition tables. Slots are | |
149 | * left for those drives devined from other means | |
150 | * (e.g. SI, AMPEX, etc.). | |
151 | */ | |
152 | short hptypes[] = { | |
153 | #define HPDT_RM03 0 | |
154 | MBDT_RM03, | |
155 | #define HPDT_RM05 1 | |
156 | MBDT_RM05, | |
157 | #define HPDT_RP06 2 | |
158 | MBDT_RP06, | |
159 | #define HPDT_RM80 3 | |
160 | MBDT_RM80, | |
161 | #define HPDT_RP05 4 | |
162 | MBDT_RP05, | |
163 | #define HPDT_RP07 5 | |
164 | MBDT_RP07, | |
165 | #define HPDT_ML11A 6 | |
166 | MBDT_ML11A, | |
167 | #define HPDT_ML11B 7 | |
168 | MBDT_ML11B, | |
169 | #define HPDT_9775 8 | |
170 | -1, | |
171 | #define HPDT_9730 9 | |
172 | -1, | |
173 | #define HPDT_CAPRICORN 10 | |
174 | -1, | |
e74d4c15 SL |
175 | #define HPDT_EAGLE 11 |
176 | -1, | |
2be84ab1 SL |
177 | #define HPDT_EAGLE48 12 |
178 | -1, | |
179 | #define HPDT_RM02 13 | |
e74d4c15 | 180 | MBDT_RM02, /* beware, actually capricorn or eagle */ |
822a683f SL |
181 | 0 |
182 | }; | |
4a4e3072 BJ |
183 | struct mba_device *hpinfo[NHP]; |
184 | int hpattach(),hpustart(),hpstart(),hpdtint(); | |
b81fd3e8 | 185 | struct mba_driver hpdriver = |
4a4e3072 BJ |
186 | { hpattach, 0, hpustart, hpstart, hpdtint, 0, |
187 | hptypes, "hp", 0, hpinfo }; | |
b81fd3e8 BJ |
188 | |
189 | struct hpst { | |
190 | short nsect; | |
191 | short ntrak; | |
192 | short nspc; | |
193 | short ncyl; | |
194 | struct size *sizes; | |
195 | } hpst[] = { | |
b70e4030 | 196 | 32, 5, 32*5, 823, rm3_sizes, /* RM03 */ |
b81fd3e8 | 197 | 32, 19, 32*19, 823, rm5_sizes, /* RM05 */ |
b70e4030 BJ |
198 | 22, 19, 22*19, 815, hp6_sizes, /* RP06 */ |
199 | 31, 14, 31*14, 559, rm80_sizes, /* RM80 */ | |
200 | 22, 19, 22*19, 411, hp6_sizes, /* RP05 */ | |
201 | 50, 32, 50*32, 630, hp7_sizes, /* RP07 */ | |
b19f1d3a BJ |
202 | 1, 1, 1, 1, 0, /* ML11A */ |
203 | 1, 1, 1, 1, 0, /* ML11B */ | |
822a683f SL |
204 | 32, 40, 32*40, 843, si9775_sizes, /* 9775 */ |
205 | 32, 10, 32*10, 823, si9730_sizes, /* 9730 */ | |
206 | 32, 16, 32*16, 1024, hpam_sizes, /* AMPEX capricorn */ | |
7ca1a4fe | 207 | 43, 20, 43*20, 842, hpfj_sizes, /* Fujitsu EAGLE */ |
2be84ab1 | 208 | 48, 20, 48*20, 842, hpfj48_sizes, /* 48 sector EAGLE */ |
b81fd3e8 BJ |
209 | }; |
210 | ||
804f6eab | 211 | u_char hp_offset[16] = { |
d565635a BJ |
212 | HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, |
213 | HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, | |
214 | HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, | |
215 | 0, 0, 0, 0, | |
04b9d53d BJ |
216 | }; |
217 | ||
804f6eab | 218 | struct buf rhpbuf[NHP]; |
b70e4030 BJ |
219 | struct buf bhpbuf[NHP]; |
220 | struct dkbad hpbad[NHP]; | |
b19f1d3a | 221 | /* SHOULD CONSOLIDATE ALL THIS STUFF INTO A STRUCTURE */ |
b70e4030 | 222 | char hpinit[NHP]; |
3dbaa9da | 223 | char hprecal[NHP]; |
b19f1d3a BJ |
224 | char hphdr[NHP]; |
225 | daddr_t mlsize[NHP]; | |
04b9d53d BJ |
226 | |
227 | #define b_cylin b_resid | |
228 | ||
b19f1d3a BJ |
229 | /* #define ML11 0 to remove ML11 support */ |
230 | #define ML11 (hptypes[mi->mi_type] == MBDT_ML11A) | |
231 | #define RP06 (hptypes[mi->mi_type] <= MBDT_RP06) | |
232 | #define RM80 (hptypes[mi->mi_type] == MBDT_RM80) | |
233 | ||
04b9d53d BJ |
234 | #ifdef INTRLVE |
235 | daddr_t dkblock(); | |
236 | #endif | |
237 | ||
71236e46 BJ |
238 | int hpseek; |
239 | ||
4a4e3072 BJ |
240 | /*ARGSUSED*/ |
241 | hpattach(mi, slave) | |
2be84ab1 | 242 | register struct mba_device *mi; |
71236e46 | 243 | { |
822a683f | 244 | |
2be84ab1 SL |
245 | mi->mi_type = hpmaptype(mi); |
246 | if (!ML11 && mi->mi_dk >= 0) { | |
247 | struct hpst *st = &hpst[mi->mi_type]; | |
248 | ||
249 | dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256); | |
250 | } | |
251 | } | |
252 | ||
253 | /* | |
254 | * Map apparent MASSBUS drive type into manufacturer | |
255 | * specific configuration. For SI controllers this is done | |
256 | * based on codes in the serial number register. For | |
257 | * EMULEX controllers, the track and sector attributes are | |
258 | * used when the drive type is an RM02 (not supported by DEC). | |
259 | */ | |
260 | hpmaptype(mi) | |
261 | register struct mba_device *mi; | |
262 | { | |
263 | register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; | |
264 | register int type = mi->mi_type; | |
822a683f SL |
265 | |
266 | /* | |
267 | * Model-byte processing for SI 9400 controllers. | |
268 | * NB: Only deals with RM03 and RM05 emulations. | |
269 | */ | |
2be84ab1 SL |
270 | if (type == HPDT_RM03 || type == HPDT_RM05) { |
271 | int hpsn = hpaddr->hpsn; | |
822a683f | 272 | |
822a683f | 273 | if ((hpsn & SIMB_LU) != mi->mi_drive) |
2be84ab1 | 274 | return (type); |
822a683f SL |
275 | switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) { |
276 | ||
277 | case SI9775D: | |
278 | printf("hp%d: si 9775 (direct)\n", mi->mi_unit); | |
2be84ab1 | 279 | type = HPDT_9775; |
822a683f SL |
280 | break; |
281 | ||
282 | case SI9730D: | |
283 | printf("hp%d: si 9730 (direct)\n", mi->mi_unit); | |
2be84ab1 | 284 | type = HPDT_9730; |
822a683f SL |
285 | break; |
286 | ||
dae6f30b | 287 | /* |
2be84ab1 SL |
288 | * AMPEX 9300, SI Combination needs a have the |
289 | * drive cleared before we start. We do not know | |
290 | * why, but tests show that the recalibrate fixes | |
291 | * the problem. | |
dae6f30b | 292 | */ |
822a683f SL |
293 | case SI9766: |
294 | printf("hp%d: 9776/9300\n", mi->mi_unit); | |
2be84ab1 | 295 | type = HPDT_RM05; |
dae6f30b BJ |
296 | hpaddr->hpcs1 = HP_RECAL|HP_GO; |
297 | DELAY(100000); | |
822a683f SL |
298 | break; |
299 | ||
300 | case SI9762: | |
301 | printf("hp%d: 9762\n", mi->mi_unit); | |
2be84ab1 | 302 | type = HPDT_RM03; |
822a683f | 303 | break; |
822a683f | 304 | } |
2be84ab1 SL |
305 | return (type); |
306 | } | |
822a683f SL |
307 | |
308 | /* | |
2be84ab1 | 309 | * EMULEX SC750 or SC780. Poke the holding register. |
822a683f | 310 | */ |
2be84ab1 SL |
311 | if (type == HPDT_RM02) { |
312 | int ntracks, nsectors; | |
313 | ||
822a683f SL |
314 | hpaddr->hpcs1 = HP_NOP; |
315 | hpaddr->hphr = HPHR_MAXTRAK; | |
7ca1a4fe SL |
316 | ntracks = (hpaddr->hphr & 0xffff) + 1; |
317 | if (ntracks == 16) { | |
822a683f | 318 | printf("hp%d: capricorn\n", mi->mi_unit); |
2be84ab1 SL |
319 | type = HPDT_CAPRICORN; |
320 | goto done; | |
321 | } | |
322 | if (ntracks != 20) { | |
7ca1a4fe | 323 | printf("hp%d: ntracks %d: unknown device\n", ntracks); |
2be84ab1 SL |
324 | goto done; |
325 | } | |
326 | hpaddr->hpcs1 = HP_NOP; | |
327 | hpaddr->hphr = HPHR_MAXSECT; | |
328 | nsectors = (hpaddr->hphr & 0xffff) + 1; | |
329 | printf("hp%d: ", mi->mi_unit); | |
330 | if (nsectors == 43) | |
331 | type = HPDT_EAGLE; | |
332 | else { | |
333 | type = HPDT_EAGLE48; | |
334 | printf("modified "); | |
335 | } | |
336 | printf("eagle\n"); | |
337 | done: | |
822a683f | 338 | hpaddr->hpcs1 = HP_DCLR|HP_GO; |
2be84ab1 SL |
339 | return (type); |
340 | } | |
822a683f | 341 | |
2be84ab1 SL |
342 | /* |
343 | * Map all ML11's to the same type. Also calculate | |
344 | * transfer rates based on device characteristics. | |
345 | */ | |
346 | if (type == HPDT_ML11A || type == HPDT_ML11B) { | |
b19f1d3a BJ |
347 | register int trt, sz; |
348 | ||
349 | sz = hpaddr->hpmr & HPMR_SZ; | |
350 | if ((hpaddr->hpmr & HPMR_ARRTYP) == 0) | |
351 | sz >>= 2; | |
352 | mlsize[mi->mi_unit] = sz; | |
353 | if (mi->mi_dk >= 0) { | |
354 | trt = (hpaddr->hpmr & HPMR_TRT) >> 8; | |
355 | dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt)); | |
356 | } | |
2be84ab1 | 357 | type = HPDT_ML11A; |
b19f1d3a | 358 | } |
2be84ab1 | 359 | return (type); |
71236e46 BJ |
360 | } |
361 | ||
473a2e47 BJ |
362 | hpopen(dev) |
363 | dev_t dev; | |
364 | { | |
365 | register int unit = minor(dev) >> 3; | |
366 | register struct mba_device *mi; | |
367 | ||
368 | if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0) | |
369 | return (ENXIO); | |
370 | return (0); | |
371 | } | |
372 | ||
04b9d53d | 373 | hpstrategy(bp) |
b81fd3e8 | 374 | register struct buf *bp; |
04b9d53d | 375 | { |
4a4e3072 | 376 | register struct mba_device *mi; |
b81fd3e8 BJ |
377 | register struct hpst *st; |
378 | register int unit; | |
04b9d53d | 379 | long sz, bn; |
b81fd3e8 | 380 | int xunit = minor(bp->b_dev) & 07; |
530d0032 | 381 | int s; |
04b9d53d | 382 | |
04b9d53d BJ |
383 | sz = bp->b_bcount; |
384 | sz = (sz+511) >> 9; | |
385 | unit = dkunit(bp); | |
b81fd3e8 BJ |
386 | if (unit >= NHP) |
387 | goto bad; | |
388 | mi = hpinfo[unit]; | |
3f3a34c3 | 389 | if (mi == 0 || mi->mi_alive == 0) |
b81fd3e8 BJ |
390 | goto bad; |
391 | st = &hpst[mi->mi_type]; | |
b19f1d3a BJ |
392 | if (ML11) { |
393 | if (bp->b_blkno < 0 || | |
394 | dkblock(bp)+sz > mlsize[mi->mi_unit]) | |
395 | goto bad; | |
396 | bp->b_cylin = 0; | |
397 | } else { | |
398 | if (bp->b_blkno < 0 || | |
399 | (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) | |
400 | goto bad; | |
401 | bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; | |
402 | } | |
530d0032 | 403 | s = spl5(); |
b81fd3e8 BJ |
404 | disksort(&mi->mi_tab, bp); |
405 | if (mi->mi_tab.b_active == 0) | |
406 | mbustart(mi); | |
530d0032 | 407 | splx(s); |
b81fd3e8 BJ |
408 | return; |
409 | ||
410 | bad: | |
411 | bp->b_flags |= B_ERROR; | |
412 | iodone(bp); | |
413 | return; | |
04b9d53d BJ |
414 | } |
415 | ||
b81fd3e8 | 416 | hpustart(mi) |
4a4e3072 | 417 | register struct mba_device *mi; |
04b9d53d | 418 | { |
804f6eab | 419 | register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; |
b81fd3e8 | 420 | register struct buf *bp = mi->mi_tab.b_actf; |
b70e4030 | 421 | register struct hpst *st = &hpst[mi->mi_type]; |
04b9d53d | 422 | daddr_t bn; |
a0eab615 | 423 | int sn, dist; |
04b9d53d | 424 | |
b70e4030 | 425 | hpaddr->hpcs1 = 0; |
804f6eab | 426 | if ((hpaddr->hpcs1&HP_DVA) == 0) |
b81fd3e8 | 427 | return (MBU_BUSY); |
b70e4030 | 428 | if ((hpaddr->hpds & HPDS_VV) == 0 || hpinit[mi->mi_unit] == 0) { |
b70e4030 | 429 | struct buf *bbp = &bhpbuf[mi->mi_unit]; |
b70e4030 BJ |
430 | |
431 | hpinit[mi->mi_unit] = 1; | |
804f6eab | 432 | hpaddr->hpcs1 = HP_DCLR|HP_GO; |
27a897a2 BJ |
433 | if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive)) |
434 | printf("DCLR attn\n"); | |
804f6eab | 435 | hpaddr->hpcs1 = HP_PRESET|HP_GO; |
b19f1d3a BJ |
436 | if (!ML11) |
437 | hpaddr->hpof = HPOF_FMT22; | |
27a897a2 | 438 | mbclrattn(mi); |
b19f1d3a BJ |
439 | if (!ML11) { |
440 | bbp->b_flags = B_READ|B_BUSY; | |
441 | bbp->b_dev = bp->b_dev; | |
442 | bbp->b_bcount = 512; | |
443 | bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit]; | |
444 | bbp->b_blkno = st->ncyl*st->nspc - st->nsect; | |
445 | bbp->b_cylin = st->ncyl - 1; | |
446 | mi->mi_tab.b_actf = bbp; | |
447 | bbp->av_forw = bp; | |
448 | bp = bbp; | |
449 | } | |
04b9d53d | 450 | } |
71236e46 | 451 | if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) |
b81fd3e8 | 452 | return (MBU_DODATA); |
b19f1d3a BJ |
453 | if (ML11) |
454 | return (MBU_DODATA); | |
d565635a | 455 | if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY) |
b81fd3e8 | 456 | return (MBU_DODATA); |
3f3a34c3 BJ |
457 | bn = dkblock(bp); |
458 | sn = bn%st->nspc; | |
459 | sn = (sn+st->nsect-hpSDIST)%st->nsect; | |
b81fd3e8 | 460 | if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) { |
71236e46 | 461 | if (hpseek) |
b81fd3e8 | 462 | return (MBU_DODATA); |
b81fd3e8 BJ |
463 | dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1; |
464 | if (dist < 0) | |
465 | dist += st->nsect; | |
466 | if (dist > st->nsect - hpRDIST) | |
467 | return (MBU_DODATA); | |
0801d37f BJ |
468 | } else |
469 | hpaddr->hpdc = bp->b_cylin; | |
71236e46 | 470 | if (hpseek) |
804f6eab | 471 | hpaddr->hpcs1 = HP_SEEK|HP_GO; |
41888f16 BJ |
472 | else { |
473 | hpaddr->hpda = sn; | |
804f6eab | 474 | hpaddr->hpcs1 = HP_SEARCH|HP_GO; |
41888f16 | 475 | } |
b81fd3e8 | 476 | return (MBU_STARTED); |
04b9d53d BJ |
477 | } |
478 | ||
b81fd3e8 | 479 | hpstart(mi) |
4a4e3072 | 480 | register struct mba_device *mi; |
04b9d53d | 481 | { |
804f6eab | 482 | register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; |
b81fd3e8 BJ |
483 | register struct buf *bp = mi->mi_tab.b_actf; |
484 | register struct hpst *st = &hpst[mi->mi_type]; | |
04b9d53d | 485 | daddr_t bn; |
b81fd3e8 | 486 | int sn, tn; |
04b9d53d | 487 | |
04b9d53d | 488 | bn = dkblock(bp); |
b19f1d3a BJ |
489 | if (ML11) |
490 | hpaddr->hpda = bn; | |
491 | else { | |
492 | sn = bn%st->nspc; | |
493 | tn = sn/st->nsect; | |
494 | sn %= st->nsect; | |
495 | hpaddr->hpdc = bp->b_cylin; | |
496 | hpaddr->hpda = (tn << 8) + sn; | |
497 | } | |
498 | if (hphdr[mi->mi_unit]) { | |
499 | if (bp->b_flags & B_READ) | |
500 | return (HP_RHDR|HP_GO); | |
501 | else | |
502 | return (HP_WHDR|HP_GO); | |
503 | } | |
504 | return (0); | |
04b9d53d BJ |
505 | } |
506 | ||
a0eab615 | 507 | hpdtint(mi, mbsr) |
4a4e3072 | 508 | register struct mba_device *mi; |
a0eab615 | 509 | int mbsr; |
04b9d53d | 510 | { |
804f6eab | 511 | register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; |
b81fd3e8 | 512 | register struct buf *bp = mi->mi_tab.b_actf; |
49d28f6f | 513 | register struct hpst *st = &hpst[mi->mi_type]; |
705c30ac | 514 | register int er1, er2; |
e34bc1ef | 515 | int retry = 0; |
b81fd3e8 | 516 | |
b70e4030 BJ |
517 | if (bp->b_flags&B_BAD) { |
518 | if (hpecc(mi, CONT)) | |
519 | return(MBD_RESTARTED); | |
520 | } | |
a0eab615 | 521 | if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) { |
b70e4030 | 522 | #ifdef HPDEBUG |
6ac24ecd | 523 | if (hpdebug) { |
b70e4030 BJ |
524 | int dc = hpaddr->hpdc, da = hpaddr->hpda; |
525 | ||
526 | printf("hperr: bp %x cyl %d blk %d as %o ", | |
527 | bp, bp->b_cylin, bp->b_blkno, | |
528 | hpaddr->hpas&0xff); | |
529 | printf("dc %x da %x\n",dc&0xffff, da&0xffff); | |
6ac24ecd BJ |
530 | printf("errcnt %d ", mi->mi_tab.b_errcnt); |
531 | printf("mbsr=%b ", mbsr, mbsr_bits); | |
532 | printf("er1=%b er2=%b\n", | |
533 | hpaddr->hper1, HPER1_BITS, | |
534 | hpaddr->hper2, HPER2_BITS); | |
535 | DELAY(1000000); | |
536 | } | |
b70e4030 | 537 | #endif |
6cee54a8 | 538 | er1 = hpaddr->hper1; |
705c30ac BJ |
539 | er2 = hpaddr->hper2; |
540 | if (er1 & HPER1_HCRC) { | |
6cee54a8 | 541 | er1 &= ~(HPER1_HCE|HPER1_FER); |
705c30ac BJ |
542 | er2 &= ~HPER2_BSE; |
543 | } | |
6cee54a8 | 544 | if (er1&HPER1_WLE) { |
fd2cb420 | 545 | printf("hp%d: write locked\n", dkunit(bp)); |
e34bc1ef | 546 | bp->b_flags |= B_ERROR; |
6cee54a8 | 547 | } else if ((er1&0xffff) == HPER1_FER && RP06 && |
b19f1d3a | 548 | hphdr[mi->mi_unit] == 0) { |
b19f1d3a BJ |
549 | if (hpecc(mi, BSE)) |
550 | return(MBD_RESTARTED); | |
551 | else | |
b19f1d3a | 552 | goto hard; |
e34bc1ef | 553 | } else if (++mi->mi_tab.b_errcnt > 27 || |
a0eab615 | 554 | mbsr & MBSR_HARD || |
6cee54a8 | 555 | er1 & HPER1_HARD || |
b19f1d3a | 556 | hphdr[mi->mi_unit] || |
705c30ac | 557 | (!ML11 && (er2 & HPER2_HARD))) { |
b70e4030 | 558 | hard: |
49d28f6f HS |
559 | if (ML11) |
560 | bp->b_blkno = hpaddr->hpda&0xffff; | |
561 | else | |
562 | bp->b_blkno = (hpaddr->hpdc*st->nspc)&0xffff + | |
563 | ((hpaddr->hpda>>8)&0xffff)*st->nsect + | |
564 | (hpaddr->hpda&0x1f); | |
fd2cb420 | 565 | harderr(bp, "hp"); |
e83ccfd7 BJ |
566 | if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC))) |
567 | printf("mbsr=%b ", mbsr, mbsr_bits); | |
b70e4030 | 568 | printf("er1=%b er2=%b", |
e34bc1ef BJ |
569 | hpaddr->hper1, HPER1_BITS, |
570 | hpaddr->hper2, HPER2_BITS); | |
b70e4030 BJ |
571 | if (hpaddr->hpmr) |
572 | printf(" mr=%o", hpaddr->hpmr&0xffff); | |
573 | if (hpaddr->hpmr2) | |
574 | printf(" mr2=%o", hpaddr->hpmr2&0xffff); | |
575 | printf("\n"); | |
b81fd3e8 | 576 | bp->b_flags |= B_ERROR; |
49d28f6f | 577 | retry = 0; |
ec737306 | 578 | hprecal[mi->mi_unit] = 0; |
705c30ac | 579 | } else if ((er2 & HPER2_BSE) && !ML11) { |
b70e4030 BJ |
580 | if (hpecc(mi, BSE)) |
581 | return(MBD_RESTARTED); | |
582 | else | |
b70e4030 | 583 | goto hard; |
705c30ac | 584 | } else if (RM80 && er2&HPER2_SSE) { |
b620b354 | 585 | (void) hpecc(mi, SSE); |
c9e9b65b | 586 | return (MBD_RESTARTED); |
6cee54a8 | 587 | } else if ((er1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) { |
b70e4030 | 588 | if (hpecc(mi, ECC)) |
e34bc1ef BJ |
589 | return (MBD_RESTARTED); |
590 | /* else done */ | |
591 | } else | |
592 | retry = 1; | |
593 | hpaddr->hpcs1 = HP_DCLR|HP_GO; | |
b19f1d3a BJ |
594 | if (ML11) { |
595 | if (mi->mi_tab.b_errcnt >= 16) | |
596 | goto hard; | |
597 | } else if ((mi->mi_tab.b_errcnt&07) == 4) { | |
e34bc1ef | 598 | hpaddr->hpcs1 = HP_RECAL|HP_GO; |
b70e4030 BJ |
599 | hprecal[mi->mi_unit] = 1; |
600 | return(MBD_RESTARTED); | |
04b9d53d | 601 | } |
e34bc1ef BJ |
602 | if (retry) |
603 | return (MBD_RETRY); | |
604 | } | |
b70e4030 | 605 | #ifdef HPDEBUG |
6ac24ecd BJ |
606 | else |
607 | if (hpdebug && hprecal[mi->mi_unit]) { | |
608 | printf("recal %d ", hprecal[mi->mi_unit]); | |
609 | printf("errcnt %d\n", mi->mi_tab.b_errcnt); | |
610 | printf("mbsr=%b ", mbsr, mbsr_bits); | |
611 | printf("er1=%b er2=%b\n", | |
612 | hpaddr->hper1, HPER1_BITS, | |
613 | hpaddr->hper2, HPER2_BITS); | |
614 | } | |
b70e4030 | 615 | #endif |
d565635a BJ |
616 | switch (hprecal[mi->mi_unit]) { |
617 | ||
618 | case 1: | |
619 | hpaddr->hpdc = bp->b_cylin; | |
620 | hpaddr->hpcs1 = HP_SEEK|HP_GO; | |
b70e4030 BJ |
621 | hprecal[mi->mi_unit]++; |
622 | return (MBD_RESTARTED); | |
d565635a BJ |
623 | case 2: |
624 | if (mi->mi_tab.b_errcnt < 16 || | |
6ac24ecd | 625 | (bp->b_flags & B_READ) == 0) |
d565635a BJ |
626 | goto donerecal; |
627 | hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22; | |
628 | hpaddr->hpcs1 = HP_OFFSET|HP_GO; | |
d565635a BJ |
629 | hprecal[mi->mi_unit]++; |
630 | return (MBD_RESTARTED); | |
631 | donerecal: | |
a6442a2f | 632 | case 3: |
3dbaa9da BJ |
633 | hprecal[mi->mi_unit] = 0; |
634 | return (MBD_RETRY); | |
635 | } | |
b19f1d3a | 636 | hphdr[mi->mi_unit] = 0; |
b81fd3e8 | 637 | bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff; |
aeecd470 | 638 | if (mi->mi_tab.b_errcnt >= 16) { |
d565635a BJ |
639 | /* |
640 | * This is fast and occurs rarely; we don't | |
641 | * bother with interrupts. | |
642 | */ | |
804f6eab | 643 | hpaddr->hpcs1 = HP_RTC|HP_GO; |
d565635a | 644 | while (hpaddr->hpds & HPDS_PIP) |
b81fd3e8 BJ |
645 | ; |
646 | mbclrattn(mi); | |
04b9d53d | 647 | } |
b19f1d3a BJ |
648 | if (!ML11) { |
649 | hpaddr->hpof = HPOF_FMT22; | |
650 | hpaddr->hpcs1 = HP_RELEASE|HP_GO; | |
651 | } | |
b81fd3e8 | 652 | return (MBD_DONE); |
04b9d53d BJ |
653 | } |
654 | ||
deb8980a | 655 | hpread(dev, uio) |
804f6eab | 656 | dev_t dev; |
deb8980a | 657 | struct uio *uio; |
04b9d53d | 658 | { |
804f6eab | 659 | register int unit = minor(dev) >> 3; |
04b9d53d | 660 | |
804f6eab | 661 | if (unit >= NHP) |
23458a62 BJ |
662 | return (ENXIO); |
663 | return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio)); | |
04b9d53d BJ |
664 | } |
665 | ||
406ddcbe | 666 | hpwrite(dev, uio) |
804f6eab | 667 | dev_t dev; |
406ddcbe | 668 | struct uio *uio; |
04b9d53d | 669 | { |
804f6eab | 670 | register int unit = minor(dev) >> 3; |
04b9d53d | 671 | |
804f6eab | 672 | if (unit >= NHP) |
23458a62 BJ |
673 | return (ENXIO); |
674 | return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio)); | |
04b9d53d BJ |
675 | } |
676 | ||
b19f1d3a | 677 | /*ARGSUSED*/ |
942f05a9 | 678 | hpioctl(dev, cmd, data, flag) |
b19f1d3a BJ |
679 | dev_t dev; |
680 | int cmd; | |
942f05a9 | 681 | caddr_t data; |
b19f1d3a BJ |
682 | int flag; |
683 | { | |
684 | ||
685 | switch (cmd) { | |
942f05a9 | 686 | |
b19f1d3a BJ |
687 | case DKIOCHDR: /* do header read/write */ |
688 | hphdr[minor(dev)>>3] = 1; | |
473a2e47 | 689 | return (0); |
b19f1d3a BJ |
690 | |
691 | default: | |
473a2e47 | 692 | return (ENXIO); |
b19f1d3a BJ |
693 | } |
694 | } | |
695 | ||
b70e4030 | 696 | hpecc(mi, flag) |
4a4e3072 | 697 | register struct mba_device *mi; |
b70e4030 | 698 | int flag; |
04b9d53d | 699 | { |
b81fd3e8 | 700 | register struct mba_regs *mbp = mi->mi_mba; |
804f6eab | 701 | register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv; |
b81fd3e8 | 702 | register struct buf *bp = mi->mi_tab.b_actf; |
b70e4030 BJ |
703 | register struct hpst *st = &hpst[mi->mi_type]; |
704 | int npf, o; | |
b81fd3e8 | 705 | int bn, cn, tn, sn; |
fa1d69d6 | 706 | int bcr; |
80e7c811 | 707 | |
fa1d69d6 BJ |
708 | bcr = mbp->mba_bcr & 0xffff; |
709 | if (bcr) | |
710 | bcr |= 0xffff0000; /* sxt */ | |
b70e4030 BJ |
711 | if (flag == CONT) |
712 | npf = bp->b_error; | |
713 | else | |
b70e4030 | 714 | npf = btop(bcr + bp->b_bcount); |
80e7c811 | 715 | o = (int)bp->b_un.b_addr & PGOFSET; |
80e7c811 | 716 | bn = dkblock(bp); |
80e7c811 | 717 | cn = bp->b_cylin; |
b70e4030 | 718 | sn = bn%(st->nspc) + npf; |
b81fd3e8 BJ |
719 | tn = sn/st->nsect; |
720 | sn %= st->nsect; | |
721 | cn += tn/st->ntrak; | |
722 | tn %= st->ntrak; | |
b70e4030 | 723 | switch (flag) { |
ba783028 | 724 | case ECC: { |
b70e4030 BJ |
725 | register int i; |
726 | caddr_t addr; | |
727 | struct pte mpte; | |
728 | int bit, byte, mask; | |
729 | ||
730 | npf--; /* because block in error is previous block */ | |
731 | printf("hp%d%c: soft ecc sn%d\n", dkunit(bp), | |
732 | 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); | |
733 | mask = rp->hpec2&0xffff; | |
734 | i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */ | |
735 | bit = i&07; | |
736 | i = (i&~07)>>3; | |
737 | byte = i + o; | |
738 | while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { | |
739 | mpte = mbp->mba_map[npf+btop(byte)]; | |
740 | addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); | |
741 | putmemc(addr, getmemc(addr)^(mask<<bit)); | |
742 | byte++; | |
743 | i++; | |
744 | bit -= 8; | |
745 | } | |
746 | if (bcr == 0) | |
747 | return (0); | |
089adc9d | 748 | npf++; |
b70e4030 BJ |
749 | break; |
750 | } | |
751 | ||
752 | case SSE: | |
753 | rp->hpof |= HPOF_SSEI; | |
754 | mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); | |
755 | break; | |
756 | ||
b70e4030 BJ |
757 | case BSE: |
758 | #ifdef HPBDEBUG | |
759 | if (hpbdebug) | |
760 | printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); | |
761 | #endif | |
762 | if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0) | |
763 | return(0); | |
764 | bp->b_flags |= B_BAD; | |
765 | bp->b_error = npf + 1; | |
766 | bn = st->ncyl*st->nspc - st->nsect - 1 - bn; | |
767 | cn = bn/st->nspc; | |
768 | sn = bn%st->nspc; | |
769 | tn = sn/st->nsect; | |
770 | sn %= st->nsect; | |
771 | mbp->mba_bcr = -512; | |
772 | #ifdef HPBDEBUG | |
773 | if (hpbdebug) | |
774 | printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); | |
775 | #endif | |
776 | break; | |
777 | ||
778 | case CONT: | |
779 | #ifdef HPBDEBUG | |
780 | if (hpbdebug) | |
781 | printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); | |
782 | #endif | |
783 | npf = bp->b_error; | |
784 | bp->b_flags &= ~B_BAD; | |
785 | mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); | |
786 | if ((mbp->mba_bcr & 0xffff) == 0) | |
787 | return(0); | |
788 | break; | |
b70e4030 BJ |
789 | } |
790 | rp->hpcs1 = HP_DCLR|HP_GO; | |
8eb99b75 | 791 | if (rp->hpof&HPOF_SSEI) |
c9e9b65b | 792 | sn++; |
80e7c811 BJ |
793 | rp->hpdc = cn; |
794 | rp->hpda = (tn<<8) + sn; | |
795 | mbp->mba_sr = -1; | |
b70e4030 BJ |
796 | mbp->mba_var = (int)ptob(npf) + o; |
797 | rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO; | |
798 | mi->mi_tab.b_errcnt = 0; /* error has been corrected */ | |
80e7c811 | 799 | return (1); |
04b9d53d | 800 | } |
e3b4b145 BJ |
801 | |
802 | #define DBSIZE 20 | |
803 | ||
804 | hpdump(dev) | |
805 | dev_t dev; | |
806 | { | |
4a4e3072 | 807 | register struct mba_device *mi; |
b81fd3e8 | 808 | register struct mba_regs *mba; |
804f6eab | 809 | struct hpdevice *hpaddr; |
e3b4b145 | 810 | char *start; |
b81fd3e8 BJ |
811 | int num, unit; |
812 | register struct hpst *st; | |
e3b4b145 BJ |
813 | |
814 | num = maxfree; | |
815 | start = 0; | |
816 | unit = minor(dev) >> 3; | |
1b81ee79 BJ |
817 | if (unit >= NHP) |
818 | return (ENXIO); | |
b81fd3e8 | 819 | #define phys(a,b) ((b)((int)(a)&0x7fffffff)) |
4a4e3072 | 820 | mi = phys(hpinfo[unit],struct mba_device *); |
1b81ee79 BJ |
821 | if (mi == 0 || mi->mi_alive == 0) |
822 | return (ENXIO); | |
b81fd3e8 | 823 | mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; |
a0eab615 | 824 | mba->mba_cr = MBCR_INIT; |
804f6eab | 825 | hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive]; |
d565635a | 826 | if ((hpaddr->hpds & HPDS_VV) == 0) { |
804f6eab BJ |
827 | hpaddr->hpcs1 = HP_DCLR|HP_GO; |
828 | hpaddr->hpcs1 = HP_PRESET|HP_GO; | |
d565635a | 829 | hpaddr->hpof = HPOF_FMT22; |
e3b4b145 | 830 | } |
b81fd3e8 | 831 | st = &hpst[mi->mi_type]; |
1b81ee79 BJ |
832 | if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks) |
833 | return (EINVAL); | |
e3b4b145 | 834 | while (num > 0) { |
b81fd3e8 | 835 | register struct pte *hpte = mba->mba_map; |
e3b4b145 | 836 | register int i; |
b81fd3e8 | 837 | int blk, cn, sn, tn; |
e3b4b145 BJ |
838 | daddr_t bn; |
839 | ||
840 | blk = num > DBSIZE ? DBSIZE : num; | |
841 | bn = dumplo + btop(start); | |
b81fd3e8 BJ |
842 | cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff; |
843 | sn = bn%st->nspc; | |
844 | tn = sn/st->nsect; | |
845 | sn = sn%st->nsect; | |
e3b4b145 BJ |
846 | hpaddr->hpdc = cn; |
847 | hpaddr->hpda = (tn << 8) + sn; | |
848 | for (i = 0; i < blk; i++) | |
849 | *(int *)hpte++ = (btop(start)+i) | PG_V; | |
b81fd3e8 BJ |
850 | mba->mba_sr = -1; |
851 | mba->mba_bcr = -(blk*NBPG); | |
852 | mba->mba_var = 0; | |
804f6eab | 853 | hpaddr->hpcs1 = HP_WCOM | HP_GO; |
d565635a | 854 | while ((hpaddr->hpds & HPDS_DRY) == 0) |
e3b4b145 | 855 | ; |
d565635a | 856 | if (hpaddr->hpds&HPDS_ERR) |
1b81ee79 | 857 | return (EIO); |
e3b4b145 BJ |
858 | start += blk*NBPG; |
859 | num -= blk; | |
860 | } | |
861 | return (0); | |
862 | } | |
a5cc519e | 863 | #endif |