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