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