merge of 4.1b with 4.1c
[unix-history] / usr / src / sys / vax / mba / hp.c
CommitLineData
f13af4da 1/* hp.c 4.57 82/10/31 */
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"
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 */
04b9d53d 152};
b81fd3e8 153/* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
04b9d53d 154
b81fd3e8
BJ
155#define _hpSDIST 2
156#define _hpRDIST 3
157
158int hpSDIST = _hpSDIST;
159int hpRDIST = _hpRDIST;
160
822a683f
SL
161/*
162 * Table for converting Massbus drive types into
163 * indices into the partition tables. Slots are
164 * left for those drives devined from other means
165 * (e.g. SI, AMPEX, etc.).
166 */
167short hptypes[] = {
168#define HPDT_RM03 0
169 MBDT_RM03,
170#define HPDT_RM05 1
171 MBDT_RM05,
172#define HPDT_RP06 2
173 MBDT_RP06,
174#define HPDT_RM80 3
175 MBDT_RM80,
176#define HPDT_RP05 4
177 MBDT_RP05,
178#define HPDT_RP07 5
179 MBDT_RP07,
180#define HPDT_ML11A 6
181 MBDT_ML11A,
182#define HPDT_ML11B 7
183 MBDT_ML11B,
184#define HPDT_9775 8
185 -1,
186#define HPDT_9730 9
187 -1,
188#define HPDT_CAPRICORN 10
189 -1,
190#define HPDT_RM02 11
191 MBDT_RM02, /* beware, actually capricorn */
192 0
193};
4a4e3072
BJ
194struct mba_device *hpinfo[NHP];
195int hpattach(),hpustart(),hpstart(),hpdtint();
b81fd3e8 196struct mba_driver hpdriver =
4a4e3072
BJ
197 { hpattach, 0, hpustart, hpstart, hpdtint, 0,
198 hptypes, "hp", 0, hpinfo };
b81fd3e8
BJ
199
200struct hpst {
201 short nsect;
202 short ntrak;
203 short nspc;
204 short ncyl;
205 struct size *sizes;
206} hpst[] = {
b70e4030 207 32, 5, 32*5, 823, rm3_sizes, /* RM03 */
b81fd3e8 208 32, 19, 32*19, 823, rm5_sizes, /* RM05 */
b70e4030
BJ
209 22, 19, 22*19, 815, hp6_sizes, /* RP06 */
210 31, 14, 31*14, 559, rm80_sizes, /* RM80 */
211 22, 19, 22*19, 411, hp6_sizes, /* RP05 */
212 50, 32, 50*32, 630, hp7_sizes, /* RP07 */
b19f1d3a
BJ
213 1, 1, 1, 1, 0, /* ML11A */
214 1, 1, 1, 1, 0, /* ML11B */
822a683f
SL
215 32, 40, 32*40, 843, si9775_sizes, /* 9775 */
216 32, 10, 32*10, 823, si9730_sizes, /* 9730 */
217 32, 16, 32*16, 1024, hpam_sizes, /* AMPEX capricorn */
b81fd3e8
BJ
218};
219
804f6eab 220u_char hp_offset[16] = {
d565635a
BJ
221 HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
222 HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800,
223 HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
224 0, 0, 0, 0,
04b9d53d
BJ
225};
226
804f6eab 227struct buf rhpbuf[NHP];
616c2a83 228#ifndef NOBADSECT
b70e4030
BJ
229struct buf bhpbuf[NHP];
230struct dkbad hpbad[NHP];
231#endif
b19f1d3a 232/* SHOULD CONSOLIDATE ALL THIS STUFF INTO A STRUCTURE */
b70e4030 233char hpinit[NHP];
3dbaa9da 234char hprecal[NHP];
b19f1d3a
BJ
235char hphdr[NHP];
236daddr_t mlsize[NHP];
04b9d53d
BJ
237
238#define b_cylin b_resid
239
b19f1d3a
BJ
240/* #define ML11 0 to remove ML11 support */
241#define ML11 (hptypes[mi->mi_type] == MBDT_ML11A)
242#define RP06 (hptypes[mi->mi_type] <= MBDT_RP06)
243#define RM80 (hptypes[mi->mi_type] == MBDT_RM80)
244
04b9d53d
BJ
245#ifdef INTRLVE
246daddr_t dkblock();
247#endif
248
71236e46
BJ
249int hpseek;
250
4a4e3072
BJ
251/*ARGSUSED*/
252hpattach(mi, slave)
253 struct mba_device *mi;
71236e46 254{
822a683f
SL
255 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
256
257 switch (mi->mi_type) {
258
259 /*
260 * Model-byte processing for SI 9400 controllers.
261 * NB: Only deals with RM03 and RM05 emulations.
262 */
263 case HPDT_RM03:
264 case HPDT_RM05: {
265 register int hpsn;
266
267 hpsn = hpaddr->hpsn;
268 if ((hpsn & SIMB_LU) != mi->mi_drive)
269 break;
270 switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) {
271
272 case SI9775D:
273 printf("hp%d: si 9775 (direct)\n", mi->mi_unit);
274 mi->mi_type = HPDT_9775;
275 break;
276
277 case SI9730D:
278 printf("hp%d: si 9730 (direct)\n", mi->mi_unit);
279 mi->mi_type = HPDT_9730;
280 break;
281
282#ifdef CAD
dae6f30b
BJ
283 /*
284 * AMPEX 9300, SI Combination needs a have the drive cleared
285 * before we start. We do not know why, but tests show
286 * that the recalibrate fixes the problem.
287 */
822a683f
SL
288 case SI9766:
289 printf("hp%d: 9776/9300\n", mi->mi_unit);
290 mi->mi_type = HPDT_RM05;
dae6f30b
BJ
291 hpaddr->hpcs1 = HP_RECAL|HP_GO;
292 DELAY(100000);
822a683f
SL
293 break;
294
295 case SI9762:
296 printf("hp%d: 9762\n", mi->mi_unit);
297 mi->mi_type = HPDT_RM03;
298 break;
299#endif
300 }
301 break;
302 }
303
304 /*
305 * CAPRICORN KLUDGE...poke the holding register
306 * to find out the number of tracks. If it's 15
307 * we believe it's a Capricorn.
308 */
309 case HPDT_RM02:
310 hpaddr->hpcs1 = HP_NOP;
311 hpaddr->hphr = HPHR_MAXTRAK;
03765e4c 312 if ((hpaddr->hphr&0xffff) == 15) {
822a683f
SL
313 printf("hp%d: capricorn\n", mi->mi_unit);
314 mi->mi_type = HPDT_CAPRICORN;
315 }
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;
705c30ac 498 register int er1, er2;
e34bc1ef 499 int retry = 0;
b81fd3e8 500
616c2a83 501#ifndef NOBADSECT
b70e4030
BJ
502 if (bp->b_flags&B_BAD) {
503 if (hpecc(mi, CONT))
504 return(MBD_RESTARTED);
505 }
506#endif
a0eab615 507 if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
b70e4030 508#ifdef HPDEBUG
6ac24ecd 509 if (hpdebug) {
b70e4030
BJ
510 int dc = hpaddr->hpdc, da = hpaddr->hpda;
511
512 printf("hperr: bp %x cyl %d blk %d as %o ",
513 bp, bp->b_cylin, bp->b_blkno,
514 hpaddr->hpas&0xff);
515 printf("dc %x da %x\n",dc&0xffff, da&0xffff);
6ac24ecd
BJ
516 printf("errcnt %d ", mi->mi_tab.b_errcnt);
517 printf("mbsr=%b ", mbsr, mbsr_bits);
518 printf("er1=%b er2=%b\n",
519 hpaddr->hper1, HPER1_BITS,
520 hpaddr->hper2, HPER2_BITS);
521 DELAY(1000000);
522 }
b70e4030 523#endif
6cee54a8 524 er1 = hpaddr->hper1;
705c30ac
BJ
525 er2 = hpaddr->hper2;
526 if (er1 & HPER1_HCRC) {
6cee54a8 527 er1 &= ~(HPER1_HCE|HPER1_FER);
705c30ac
BJ
528 er2 &= ~HPER2_BSE;
529 }
6cee54a8 530 if (er1&HPER1_WLE) {
fd2cb420 531 printf("hp%d: write locked\n", dkunit(bp));
e34bc1ef 532 bp->b_flags |= B_ERROR;
6cee54a8 533 } else if ((er1&0xffff) == HPER1_FER && RP06 &&
b19f1d3a
BJ
534 hphdr[mi->mi_unit] == 0) {
535#ifndef NOBADSECT
536 if (hpecc(mi, BSE))
537 return(MBD_RESTARTED);
538 else
539#endif
540 goto hard;
e34bc1ef 541 } else if (++mi->mi_tab.b_errcnt > 27 ||
a0eab615 542 mbsr & MBSR_HARD ||
6cee54a8 543 er1 & HPER1_HARD ||
b19f1d3a 544 hphdr[mi->mi_unit] ||
705c30ac 545 (!ML11 && (er2 & HPER2_HARD))) {
b70e4030 546hard:
fd2cb420 547 harderr(bp, "hp");
e83ccfd7
BJ
548 if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
549 printf("mbsr=%b ", mbsr, mbsr_bits);
b70e4030 550 printf("er1=%b er2=%b",
e34bc1ef
BJ
551 hpaddr->hper1, HPER1_BITS,
552 hpaddr->hper2, HPER2_BITS);
b70e4030
BJ
553 if (hpaddr->hpmr)
554 printf(" mr=%o", hpaddr->hpmr&0xffff);
555 if (hpaddr->hpmr2)
556 printf(" mr2=%o", hpaddr->hpmr2&0xffff);
557 printf("\n");
b81fd3e8 558 bp->b_flags |= B_ERROR;
ec737306 559 hprecal[mi->mi_unit] = 0;
705c30ac 560 } else if ((er2 & HPER2_BSE) && !ML11) {
616c2a83 561#ifndef NOBADSECT
b70e4030
BJ
562 if (hpecc(mi, BSE))
563 return(MBD_RESTARTED);
564 else
565#endif
566 goto hard;
705c30ac 567 } else if (RM80 && er2&HPER2_SSE) {
b620b354 568 (void) hpecc(mi, SSE);
c9e9b65b 569 return (MBD_RESTARTED);
6cee54a8 570 } else if ((er1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) {
b70e4030 571 if (hpecc(mi, ECC))
e34bc1ef
BJ
572 return (MBD_RESTARTED);
573 /* else done */
574 } else
575 retry = 1;
576 hpaddr->hpcs1 = HP_DCLR|HP_GO;
b19f1d3a
BJ
577 if (ML11) {
578 if (mi->mi_tab.b_errcnt >= 16)
579 goto hard;
580 } else if ((mi->mi_tab.b_errcnt&07) == 4) {
e34bc1ef 581 hpaddr->hpcs1 = HP_RECAL|HP_GO;
b70e4030
BJ
582 hprecal[mi->mi_unit] = 1;
583 return(MBD_RESTARTED);
04b9d53d 584 }
e34bc1ef
BJ
585 if (retry)
586 return (MBD_RETRY);
587 }
b70e4030 588#ifdef HPDEBUG
6ac24ecd
BJ
589 else
590 if (hpdebug && hprecal[mi->mi_unit]) {
591 printf("recal %d ", hprecal[mi->mi_unit]);
592 printf("errcnt %d\n", mi->mi_tab.b_errcnt);
593 printf("mbsr=%b ", mbsr, mbsr_bits);
594 printf("er1=%b er2=%b\n",
595 hpaddr->hper1, HPER1_BITS,
596 hpaddr->hper2, HPER2_BITS);
597 }
b70e4030 598#endif
d565635a
BJ
599 switch (hprecal[mi->mi_unit]) {
600
601 case 1:
602 hpaddr->hpdc = bp->b_cylin;
603 hpaddr->hpcs1 = HP_SEEK|HP_GO;
b70e4030
BJ
604 hprecal[mi->mi_unit]++;
605 return (MBD_RESTARTED);
d565635a
BJ
606 case 2:
607 if (mi->mi_tab.b_errcnt < 16 ||
6ac24ecd 608 (bp->b_flags & B_READ) == 0)
d565635a
BJ
609 goto donerecal;
610 hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22;
611 hpaddr->hpcs1 = HP_OFFSET|HP_GO;
d565635a
BJ
612 hprecal[mi->mi_unit]++;
613 return (MBD_RESTARTED);
614 donerecal:
a6442a2f 615 case 3:
3dbaa9da
BJ
616 hprecal[mi->mi_unit] = 0;
617 return (MBD_RETRY);
618 }
b19f1d3a 619 hphdr[mi->mi_unit] = 0;
b81fd3e8 620 bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff;
aeecd470 621 if (mi->mi_tab.b_errcnt >= 16) {
d565635a
BJ
622 /*
623 * This is fast and occurs rarely; we don't
624 * bother with interrupts.
625 */
804f6eab 626 hpaddr->hpcs1 = HP_RTC|HP_GO;
d565635a 627 while (hpaddr->hpds & HPDS_PIP)
b81fd3e8
BJ
628 ;
629 mbclrattn(mi);
04b9d53d 630 }
b19f1d3a
BJ
631 if (!ML11) {
632 hpaddr->hpof = HPOF_FMT22;
633 hpaddr->hpcs1 = HP_RELEASE|HP_GO;
634 }
b81fd3e8 635 return (MBD_DONE);
04b9d53d
BJ
636}
637
deb8980a 638hpread(dev, uio)
804f6eab 639 dev_t dev;
deb8980a 640 struct uio *uio;
04b9d53d 641{
804f6eab 642 register int unit = minor(dev) >> 3;
04b9d53d 643
804f6eab 644 if (unit >= NHP)
23458a62
BJ
645 return (ENXIO);
646 return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio));
04b9d53d
BJ
647}
648
406ddcbe 649hpwrite(dev, uio)
804f6eab 650 dev_t dev;
406ddcbe 651 struct uio *uio;
04b9d53d 652{
804f6eab 653 register int unit = minor(dev) >> 3;
04b9d53d 654
804f6eab 655 if (unit >= NHP)
23458a62
BJ
656 return (ENXIO);
657 return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio));
04b9d53d
BJ
658}
659
b19f1d3a 660/*ARGSUSED*/
942f05a9 661hpioctl(dev, cmd, data, flag)
b19f1d3a
BJ
662 dev_t dev;
663 int cmd;
942f05a9 664 caddr_t data;
b19f1d3a
BJ
665 int flag;
666{
667
668 switch (cmd) {
942f05a9 669
b19f1d3a
BJ
670 case DKIOCHDR: /* do header read/write */
671 hphdr[minor(dev)>>3] = 1;
473a2e47 672 return (0);
b19f1d3a
BJ
673
674 default:
473a2e47 675 return (ENXIO);
b19f1d3a
BJ
676 }
677}
678
b70e4030 679hpecc(mi, flag)
4a4e3072 680 register struct mba_device *mi;
b70e4030 681 int flag;
04b9d53d 682{
b81fd3e8 683 register struct mba_regs *mbp = mi->mi_mba;
804f6eab 684 register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv;
b81fd3e8 685 register struct buf *bp = mi->mi_tab.b_actf;
b70e4030
BJ
686 register struct hpst *st = &hpst[mi->mi_type];
687 int npf, o;
b81fd3e8 688 int bn, cn, tn, sn;
fa1d69d6 689 int bcr;
80e7c811 690
fa1d69d6
BJ
691 bcr = mbp->mba_bcr & 0xffff;
692 if (bcr)
693 bcr |= 0xffff0000; /* sxt */
616c2a83 694#ifndef NOBADSECT
b70e4030
BJ
695 if (flag == CONT)
696 npf = bp->b_error;
697 else
698#endif
699 npf = btop(bcr + bp->b_bcount);
80e7c811 700 o = (int)bp->b_un.b_addr & PGOFSET;
80e7c811 701 bn = dkblock(bp);
80e7c811 702 cn = bp->b_cylin;
b70e4030 703 sn = bn%(st->nspc) + npf;
b81fd3e8
BJ
704 tn = sn/st->nsect;
705 sn %= st->nsect;
706 cn += tn/st->ntrak;
707 tn %= st->ntrak;
b70e4030
BJ
708 switch (flag) {
709 case ECC:
710 {
711 register int i;
712 caddr_t addr;
713 struct pte mpte;
714 int bit, byte, mask;
715
716 npf--; /* because block in error is previous block */
717 printf("hp%d%c: soft ecc sn%d\n", dkunit(bp),
718 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
719 mask = rp->hpec2&0xffff;
720 i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */
721 bit = i&07;
722 i = (i&~07)>>3;
723 byte = i + o;
724 while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
725 mpte = mbp->mba_map[npf+btop(byte)];
726 addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
727 putmemc(addr, getmemc(addr)^(mask<<bit));
728 byte++;
729 i++;
730 bit -= 8;
731 }
732 if (bcr == 0)
733 return (0);
089adc9d 734 npf++;
b70e4030
BJ
735 break;
736 }
737
738 case SSE:
739 rp->hpof |= HPOF_SSEI;
740 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
741 break;
742
616c2a83 743#ifndef NOBADSECT
b70e4030
BJ
744 case BSE:
745#ifdef HPBDEBUG
746 if (hpbdebug)
747 printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
748#endif
749 if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0)
750 return(0);
751 bp->b_flags |= B_BAD;
752 bp->b_error = npf + 1;
753 bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
754 cn = bn/st->nspc;
755 sn = bn%st->nspc;
756 tn = sn/st->nsect;
757 sn %= st->nsect;
758 mbp->mba_bcr = -512;
759#ifdef HPBDEBUG
760 if (hpbdebug)
761 printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
762#endif
763 break;
764
765 case CONT:
766#ifdef HPBDEBUG
767 if (hpbdebug)
768 printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
769#endif
770 npf = bp->b_error;
771 bp->b_flags &= ~B_BAD;
772 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
773 if ((mbp->mba_bcr & 0xffff) == 0)
774 return(0);
775 break;
776#endif
777 }
778 rp->hpcs1 = HP_DCLR|HP_GO;
8eb99b75 779 if (rp->hpof&HPOF_SSEI)
c9e9b65b 780 sn++;
80e7c811
BJ
781 rp->hpdc = cn;
782 rp->hpda = (tn<<8) + sn;
783 mbp->mba_sr = -1;
b70e4030
BJ
784 mbp->mba_var = (int)ptob(npf) + o;
785 rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO;
786 mi->mi_tab.b_errcnt = 0; /* error has been corrected */
80e7c811 787 return (1);
04b9d53d 788}
e3b4b145
BJ
789
790#define DBSIZE 20
791
792hpdump(dev)
793 dev_t dev;
794{
4a4e3072 795 register struct mba_device *mi;
b81fd3e8 796 register struct mba_regs *mba;
804f6eab 797 struct hpdevice *hpaddr;
e3b4b145 798 char *start;
b81fd3e8
BJ
799 int num, unit;
800 register struct hpst *st;
e3b4b145
BJ
801
802 num = maxfree;
803 start = 0;
804 unit = minor(dev) >> 3;
1b81ee79
BJ
805 if (unit >= NHP)
806 return (ENXIO);
b81fd3e8 807#define phys(a,b) ((b)((int)(a)&0x7fffffff))
4a4e3072 808 mi = phys(hpinfo[unit],struct mba_device *);
1b81ee79
BJ
809 if (mi == 0 || mi->mi_alive == 0)
810 return (ENXIO);
b81fd3e8 811 mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
a0eab615 812 mba->mba_cr = MBCR_INIT;
804f6eab 813 hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive];
d565635a 814 if ((hpaddr->hpds & HPDS_VV) == 0) {
804f6eab
BJ
815 hpaddr->hpcs1 = HP_DCLR|HP_GO;
816 hpaddr->hpcs1 = HP_PRESET|HP_GO;
d565635a 817 hpaddr->hpof = HPOF_FMT22;
e3b4b145 818 }
b81fd3e8 819 st = &hpst[mi->mi_type];
1b81ee79
BJ
820 if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks)
821 return (EINVAL);
e3b4b145 822 while (num > 0) {
b81fd3e8 823 register struct pte *hpte = mba->mba_map;
e3b4b145 824 register int i;
b81fd3e8 825 int blk, cn, sn, tn;
e3b4b145
BJ
826 daddr_t bn;
827
828 blk = num > DBSIZE ? DBSIZE : num;
829 bn = dumplo + btop(start);
b81fd3e8
BJ
830 cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff;
831 sn = bn%st->nspc;
832 tn = sn/st->nsect;
833 sn = sn%st->nsect;
e3b4b145
BJ
834 hpaddr->hpdc = cn;
835 hpaddr->hpda = (tn << 8) + sn;
836 for (i = 0; i < blk; i++)
837 *(int *)hpte++ = (btop(start)+i) | PG_V;
b81fd3e8
BJ
838 mba->mba_sr = -1;
839 mba->mba_bcr = -(blk*NBPG);
840 mba->mba_var = 0;
804f6eab 841 hpaddr->hpcs1 = HP_WCOM | HP_GO;
d565635a 842 while ((hpaddr->hpds & HPDS_DRY) == 0)
e3b4b145 843 ;
d565635a 844 if (hpaddr->hpds&HPDS_ERR)
1b81ee79 845 return (EIO);
e3b4b145
BJ
846 start += blk*NBPG;
847 num -= blk;
848 }
849 return (0);
850}
a5cc519e 851#endif