all partitions leave space for bad sectors
[unix-history] / usr / src / sys / vax / mba / hp.c
CommitLineData
ba783028 1/* hp.c 4.64 83/02/10 */
b70e4030
BJ
2
3#ifdef HPDEBUG
6ac24ecd 4int hpdebug;
b70e4030
BJ
5#endif
6#ifdef HPBDEBUG
7int 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 */
44struct 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
143int hpSDIST = _hpSDIST;
144int 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 */
152short 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
183struct mba_device *hpinfo[NHP];
184int hpattach(),hpustart(),hpstart(),hpdtint();
b81fd3e8 185struct mba_driver hpdriver =
4a4e3072
BJ
186 { hpattach, 0, hpustart, hpstart, hpdtint, 0,
187 hptypes, "hp", 0, hpinfo };
b81fd3e8
BJ
188
189struct 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 211u_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 218struct buf rhpbuf[NHP];
b70e4030
BJ
219struct buf bhpbuf[NHP];
220struct dkbad hpbad[NHP];
b19f1d3a 221/* SHOULD CONSOLIDATE ALL THIS STUFF INTO A STRUCTURE */
b70e4030 222char hpinit[NHP];
3dbaa9da 223char hprecal[NHP];
b19f1d3a
BJ
224char hphdr[NHP];
225daddr_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
235daddr_t dkblock();
236#endif
237
71236e46
BJ
238int hpseek;
239
4a4e3072
BJ
240/*ARGSUSED*/
241hpattach(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 */
260hpmaptype(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");
337done:
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
362hpopen(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 373hpstrategy(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
410bad:
411 bp->b_flags |= B_ERROR;
412 iodone(bp);
413 return;
04b9d53d
BJ
414}
415
b81fd3e8 416hpustart(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 479hpstart(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 507hpdtint(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 558hard:
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 655hpread(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 666hpwrite(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 678hpioctl(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 696hpecc(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
804hpdump(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