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