physio returns errors
[unix-history] / usr / src / sys / vax / mba / hp.c
CommitLineData
23458a62 1/* hp.c 4.54 82/09/12 */
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"
942f05a9 37#include "../h/ioctl.h"
b19f1d3a 38#include "../h/dkio.h"
deb8980a 39#include "../h/uio.h"
04b9d53d 40
b81fd3e8 41#include "../h/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
04b9d53d 343hpstrategy(bp)
b81fd3e8 344 register struct buf *bp;
04b9d53d 345{
4a4e3072 346 register struct mba_device *mi;
b81fd3e8
BJ
347 register struct hpst *st;
348 register int unit;
04b9d53d 349 long sz, bn;
b81fd3e8 350 int xunit = minor(bp->b_dev) & 07;
530d0032 351 int s;
04b9d53d 352
04b9d53d
BJ
353 sz = bp->b_bcount;
354 sz = (sz+511) >> 9;
355 unit = dkunit(bp);
b81fd3e8
BJ
356 if (unit >= NHP)
357 goto bad;
358 mi = hpinfo[unit];
3f3a34c3 359 if (mi == 0 || mi->mi_alive == 0)
b81fd3e8
BJ
360 goto bad;
361 st = &hpst[mi->mi_type];
b19f1d3a
BJ
362 if (ML11) {
363 if (bp->b_blkno < 0 ||
364 dkblock(bp)+sz > mlsize[mi->mi_unit])
365 goto bad;
366 bp->b_cylin = 0;
367 } else {
368 if (bp->b_blkno < 0 ||
369 (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
370 goto bad;
371 bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
372 }
530d0032 373 s = spl5();
b81fd3e8
BJ
374 disksort(&mi->mi_tab, bp);
375 if (mi->mi_tab.b_active == 0)
376 mbustart(mi);
530d0032 377 splx(s);
b81fd3e8
BJ
378 return;
379
380bad:
381 bp->b_flags |= B_ERROR;
382 iodone(bp);
383 return;
04b9d53d
BJ
384}
385
b81fd3e8 386hpustart(mi)
4a4e3072 387 register struct mba_device *mi;
04b9d53d 388{
804f6eab 389 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
b81fd3e8 390 register struct buf *bp = mi->mi_tab.b_actf;
b70e4030 391 register struct hpst *st = &hpst[mi->mi_type];
04b9d53d 392 daddr_t bn;
a0eab615 393 int sn, dist;
04b9d53d 394
b70e4030 395 hpaddr->hpcs1 = 0;
804f6eab 396 if ((hpaddr->hpcs1&HP_DVA) == 0)
b81fd3e8 397 return (MBU_BUSY);
b70e4030 398 if ((hpaddr->hpds & HPDS_VV) == 0 || hpinit[mi->mi_unit] == 0) {
616c2a83 399#ifndef NOBADSECT
b70e4030
BJ
400 struct buf *bbp = &bhpbuf[mi->mi_unit];
401#endif
402
403 hpinit[mi->mi_unit] = 1;
804f6eab 404 hpaddr->hpcs1 = HP_DCLR|HP_GO;
27a897a2
BJ
405 if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive))
406 printf("DCLR attn\n");
804f6eab 407 hpaddr->hpcs1 = HP_PRESET|HP_GO;
b19f1d3a
BJ
408 if (!ML11)
409 hpaddr->hpof = HPOF_FMT22;
27a897a2 410 mbclrattn(mi);
616c2a83 411#ifndef NOBADSECT
b19f1d3a
BJ
412 if (!ML11) {
413 bbp->b_flags = B_READ|B_BUSY;
414 bbp->b_dev = bp->b_dev;
415 bbp->b_bcount = 512;
416 bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit];
417 bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
418 bbp->b_cylin = st->ncyl - 1;
419 mi->mi_tab.b_actf = bbp;
420 bbp->av_forw = bp;
421 bp = bbp;
422 }
b70e4030 423#endif
04b9d53d 424 }
71236e46 425 if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1)
b81fd3e8 426 return (MBU_DODATA);
b19f1d3a
BJ
427 if (ML11)
428 return (MBU_DODATA);
d565635a 429 if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY)
b81fd3e8 430 return (MBU_DODATA);
3f3a34c3
BJ
431 bn = dkblock(bp);
432 sn = bn%st->nspc;
433 sn = (sn+st->nsect-hpSDIST)%st->nsect;
b81fd3e8 434 if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) {
71236e46 435 if (hpseek)
b81fd3e8 436 return (MBU_DODATA);
b81fd3e8
BJ
437 dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1;
438 if (dist < 0)
439 dist += st->nsect;
440 if (dist > st->nsect - hpRDIST)
441 return (MBU_DODATA);
0801d37f
BJ
442 } else
443 hpaddr->hpdc = bp->b_cylin;
71236e46 444 if (hpseek)
804f6eab 445 hpaddr->hpcs1 = HP_SEEK|HP_GO;
41888f16
BJ
446 else {
447 hpaddr->hpda = sn;
804f6eab 448 hpaddr->hpcs1 = HP_SEARCH|HP_GO;
41888f16 449 }
b81fd3e8 450 return (MBU_STARTED);
04b9d53d
BJ
451}
452
b81fd3e8 453hpstart(mi)
4a4e3072 454 register struct mba_device *mi;
04b9d53d 455{
804f6eab 456 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
b81fd3e8
BJ
457 register struct buf *bp = mi->mi_tab.b_actf;
458 register struct hpst *st = &hpst[mi->mi_type];
04b9d53d 459 daddr_t bn;
b81fd3e8 460 int sn, tn;
04b9d53d 461
04b9d53d 462 bn = dkblock(bp);
b19f1d3a
BJ
463 if (ML11)
464 hpaddr->hpda = bn;
465 else {
466 sn = bn%st->nspc;
467 tn = sn/st->nsect;
468 sn %= st->nsect;
469 hpaddr->hpdc = bp->b_cylin;
470 hpaddr->hpda = (tn << 8) + sn;
471 }
472 if (hphdr[mi->mi_unit]) {
473 if (bp->b_flags & B_READ)
474 return (HP_RHDR|HP_GO);
475 else
476 return (HP_WHDR|HP_GO);
477 }
478 return (0);
04b9d53d
BJ
479}
480
a0eab615 481hpdtint(mi, mbsr)
4a4e3072 482 register struct mba_device *mi;
a0eab615 483 int mbsr;
04b9d53d 484{
804f6eab 485 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
b81fd3e8 486 register struct buf *bp = mi->mi_tab.b_actf;
705c30ac 487 register int er1, er2;
e34bc1ef 488 int retry = 0;
b81fd3e8 489
616c2a83 490#ifndef NOBADSECT
b70e4030
BJ
491 if (bp->b_flags&B_BAD) {
492 if (hpecc(mi, CONT))
493 return(MBD_RESTARTED);
494 }
495#endif
a0eab615 496 if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
b70e4030 497#ifdef HPDEBUG
6ac24ecd 498 if (hpdebug) {
b70e4030
BJ
499 int dc = hpaddr->hpdc, da = hpaddr->hpda;
500
501 printf("hperr: bp %x cyl %d blk %d as %o ",
502 bp, bp->b_cylin, bp->b_blkno,
503 hpaddr->hpas&0xff);
504 printf("dc %x da %x\n",dc&0xffff, da&0xffff);
6ac24ecd
BJ
505 printf("errcnt %d ", mi->mi_tab.b_errcnt);
506 printf("mbsr=%b ", mbsr, mbsr_bits);
507 printf("er1=%b er2=%b\n",
508 hpaddr->hper1, HPER1_BITS,
509 hpaddr->hper2, HPER2_BITS);
510 DELAY(1000000);
511 }
b70e4030 512#endif
6cee54a8 513 er1 = hpaddr->hper1;
705c30ac
BJ
514 er2 = hpaddr->hper2;
515 if (er1 & HPER1_HCRC) {
6cee54a8 516 er1 &= ~(HPER1_HCE|HPER1_FER);
705c30ac
BJ
517 er2 &= ~HPER2_BSE;
518 }
6cee54a8 519 if (er1&HPER1_WLE) {
fd2cb420 520 printf("hp%d: write locked\n", dkunit(bp));
e34bc1ef 521 bp->b_flags |= B_ERROR;
6cee54a8 522 } else if ((er1&0xffff) == HPER1_FER && RP06 &&
b19f1d3a
BJ
523 hphdr[mi->mi_unit] == 0) {
524#ifndef NOBADSECT
525 if (hpecc(mi, BSE))
526 return(MBD_RESTARTED);
527 else
528#endif
529 goto hard;
e34bc1ef 530 } else if (++mi->mi_tab.b_errcnt > 27 ||
a0eab615 531 mbsr & MBSR_HARD ||
6cee54a8 532 er1 & HPER1_HARD ||
b19f1d3a 533 hphdr[mi->mi_unit] ||
705c30ac 534 (!ML11 && (er2 & HPER2_HARD))) {
b70e4030 535hard:
fd2cb420 536 harderr(bp, "hp");
e83ccfd7
BJ
537 if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
538 printf("mbsr=%b ", mbsr, mbsr_bits);
b70e4030 539 printf("er1=%b er2=%b",
e34bc1ef
BJ
540 hpaddr->hper1, HPER1_BITS,
541 hpaddr->hper2, HPER2_BITS);
b70e4030
BJ
542 if (hpaddr->hpmr)
543 printf(" mr=%o", hpaddr->hpmr&0xffff);
544 if (hpaddr->hpmr2)
545 printf(" mr2=%o", hpaddr->hpmr2&0xffff);
546 printf("\n");
b81fd3e8 547 bp->b_flags |= B_ERROR;
ec737306 548 hprecal[mi->mi_unit] = 0;
705c30ac 549 } else if ((er2 & HPER2_BSE) && !ML11) {
616c2a83 550#ifndef NOBADSECT
b70e4030
BJ
551 if (hpecc(mi, BSE))
552 return(MBD_RESTARTED);
553 else
554#endif
555 goto hard;
705c30ac 556 } else if (RM80 && er2&HPER2_SSE) {
b620b354 557 (void) hpecc(mi, SSE);
c9e9b65b 558 return (MBD_RESTARTED);
6cee54a8 559 } else if ((er1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) {
b70e4030 560 if (hpecc(mi, ECC))
e34bc1ef
BJ
561 return (MBD_RESTARTED);
562 /* else done */
563 } else
564 retry = 1;
565 hpaddr->hpcs1 = HP_DCLR|HP_GO;
b19f1d3a
BJ
566 if (ML11) {
567 if (mi->mi_tab.b_errcnt >= 16)
568 goto hard;
569 } else if ((mi->mi_tab.b_errcnt&07) == 4) {
e34bc1ef 570 hpaddr->hpcs1 = HP_RECAL|HP_GO;
b70e4030
BJ
571 hprecal[mi->mi_unit] = 1;
572 return(MBD_RESTARTED);
04b9d53d 573 }
e34bc1ef
BJ
574 if (retry)
575 return (MBD_RETRY);
576 }
b70e4030 577#ifdef HPDEBUG
6ac24ecd
BJ
578 else
579 if (hpdebug && hprecal[mi->mi_unit]) {
580 printf("recal %d ", hprecal[mi->mi_unit]);
581 printf("errcnt %d\n", mi->mi_tab.b_errcnt);
582 printf("mbsr=%b ", mbsr, mbsr_bits);
583 printf("er1=%b er2=%b\n",
584 hpaddr->hper1, HPER1_BITS,
585 hpaddr->hper2, HPER2_BITS);
586 }
b70e4030 587#endif
d565635a
BJ
588 switch (hprecal[mi->mi_unit]) {
589
590 case 1:
591 hpaddr->hpdc = bp->b_cylin;
592 hpaddr->hpcs1 = HP_SEEK|HP_GO;
b70e4030
BJ
593 hprecal[mi->mi_unit]++;
594 return (MBD_RESTARTED);
d565635a
BJ
595 case 2:
596 if (mi->mi_tab.b_errcnt < 16 ||
6ac24ecd 597 (bp->b_flags & B_READ) == 0)
d565635a
BJ
598 goto donerecal;
599 hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22;
600 hpaddr->hpcs1 = HP_OFFSET|HP_GO;
d565635a
BJ
601 hprecal[mi->mi_unit]++;
602 return (MBD_RESTARTED);
603 donerecal:
a6442a2f 604 case 3:
3dbaa9da
BJ
605 hprecal[mi->mi_unit] = 0;
606 return (MBD_RETRY);
607 }
b19f1d3a 608 hphdr[mi->mi_unit] = 0;
b81fd3e8 609 bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff;
aeecd470 610 if (mi->mi_tab.b_errcnt >= 16) {
d565635a
BJ
611 /*
612 * This is fast and occurs rarely; we don't
613 * bother with interrupts.
614 */
804f6eab 615 hpaddr->hpcs1 = HP_RTC|HP_GO;
d565635a 616 while (hpaddr->hpds & HPDS_PIP)
b81fd3e8
BJ
617 ;
618 mbclrattn(mi);
04b9d53d 619 }
b19f1d3a
BJ
620 if (!ML11) {
621 hpaddr->hpof = HPOF_FMT22;
622 hpaddr->hpcs1 = HP_RELEASE|HP_GO;
623 }
b81fd3e8 624 return (MBD_DONE);
04b9d53d
BJ
625}
626
deb8980a 627hpread(dev, uio)
804f6eab 628 dev_t dev;
deb8980a 629 struct uio *uio;
04b9d53d 630{
804f6eab 631 register int unit = minor(dev) >> 3;
04b9d53d 632
804f6eab 633 if (unit >= NHP)
23458a62
BJ
634 return (ENXIO);
635 return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio));
04b9d53d
BJ
636}
637
406ddcbe 638hpwrite(dev, uio)
804f6eab 639 dev_t dev;
406ddcbe 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_WRITE, minphys, uio));
04b9d53d
BJ
647}
648
b19f1d3a 649/*ARGSUSED*/
942f05a9 650hpioctl(dev, cmd, data, flag)
b19f1d3a
BJ
651 dev_t dev;
652 int cmd;
942f05a9 653 caddr_t data;
b19f1d3a
BJ
654 int flag;
655{
656
657 switch (cmd) {
942f05a9 658
b19f1d3a
BJ
659 case DKIOCHDR: /* do header read/write */
660 hphdr[minor(dev)>>3] = 1;
661 return;
662
663 default:
664 u.u_error = ENXIO;
665 }
666}
667
b70e4030 668hpecc(mi, flag)
4a4e3072 669 register struct mba_device *mi;
b70e4030 670 int flag;
04b9d53d 671{
b81fd3e8 672 register struct mba_regs *mbp = mi->mi_mba;
804f6eab 673 register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv;
b81fd3e8 674 register struct buf *bp = mi->mi_tab.b_actf;
b70e4030
BJ
675 register struct hpst *st = &hpst[mi->mi_type];
676 int npf, o;
b81fd3e8 677 int bn, cn, tn, sn;
fa1d69d6 678 int bcr;
80e7c811 679
fa1d69d6
BJ
680 bcr = mbp->mba_bcr & 0xffff;
681 if (bcr)
682 bcr |= 0xffff0000; /* sxt */
616c2a83 683#ifndef NOBADSECT
b70e4030
BJ
684 if (flag == CONT)
685 npf = bp->b_error;
686 else
687#endif
688 npf = btop(bcr + bp->b_bcount);
80e7c811 689 o = (int)bp->b_un.b_addr & PGOFSET;
80e7c811 690 bn = dkblock(bp);
80e7c811 691 cn = bp->b_cylin;
b70e4030 692 sn = bn%(st->nspc) + npf;
b81fd3e8
BJ
693 tn = sn/st->nsect;
694 sn %= st->nsect;
695 cn += tn/st->ntrak;
696 tn %= st->ntrak;
b70e4030
BJ
697 switch (flag) {
698 case ECC:
699 {
700 register int i;
701 caddr_t addr;
702 struct pte mpte;
703 int bit, byte, mask;
704
705 npf--; /* because block in error is previous block */
706 printf("hp%d%c: soft ecc sn%d\n", dkunit(bp),
707 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
708 mask = rp->hpec2&0xffff;
709 i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */
710 bit = i&07;
711 i = (i&~07)>>3;
712 byte = i + o;
713 while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
714 mpte = mbp->mba_map[npf+btop(byte)];
715 addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
716 putmemc(addr, getmemc(addr)^(mask<<bit));
717 byte++;
718 i++;
719 bit -= 8;
720 }
721 if (bcr == 0)
722 return (0);
089adc9d 723 npf++;
b70e4030
BJ
724 break;
725 }
726
727 case SSE:
728 rp->hpof |= HPOF_SSEI;
729 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
730 break;
731
616c2a83 732#ifndef NOBADSECT
b70e4030
BJ
733 case BSE:
734#ifdef HPBDEBUG
735 if (hpbdebug)
736 printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
737#endif
738 if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0)
739 return(0);
740 bp->b_flags |= B_BAD;
741 bp->b_error = npf + 1;
742 bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
743 cn = bn/st->nspc;
744 sn = bn%st->nspc;
745 tn = sn/st->nsect;
746 sn %= st->nsect;
747 mbp->mba_bcr = -512;
748#ifdef HPBDEBUG
749 if (hpbdebug)
750 printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
751#endif
752 break;
753
754 case CONT:
755#ifdef HPBDEBUG
756 if (hpbdebug)
757 printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
758#endif
759 npf = bp->b_error;
760 bp->b_flags &= ~B_BAD;
761 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
762 if ((mbp->mba_bcr & 0xffff) == 0)
763 return(0);
764 break;
765#endif
766 }
767 rp->hpcs1 = HP_DCLR|HP_GO;
8eb99b75 768 if (rp->hpof&HPOF_SSEI)
c9e9b65b 769 sn++;
80e7c811
BJ
770 rp->hpdc = cn;
771 rp->hpda = (tn<<8) + sn;
772 mbp->mba_sr = -1;
b70e4030
BJ
773 mbp->mba_var = (int)ptob(npf) + o;
774 rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO;
775 mi->mi_tab.b_errcnt = 0; /* error has been corrected */
80e7c811 776 return (1);
04b9d53d 777}
e3b4b145
BJ
778
779#define DBSIZE 20
780
781hpdump(dev)
782 dev_t dev;
783{
4a4e3072 784 register struct mba_device *mi;
b81fd3e8 785 register struct mba_regs *mba;
804f6eab 786 struct hpdevice *hpaddr;
e3b4b145 787 char *start;
b81fd3e8
BJ
788 int num, unit;
789 register struct hpst *st;
e3b4b145
BJ
790
791 num = maxfree;
792 start = 0;
793 unit = minor(dev) >> 3;
1b81ee79
BJ
794 if (unit >= NHP)
795 return (ENXIO);
b81fd3e8 796#define phys(a,b) ((b)((int)(a)&0x7fffffff))
4a4e3072 797 mi = phys(hpinfo[unit],struct mba_device *);
1b81ee79
BJ
798 if (mi == 0 || mi->mi_alive == 0)
799 return (ENXIO);
b81fd3e8 800 mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
a0eab615 801 mba->mba_cr = MBCR_INIT;
804f6eab 802 hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive];
d565635a 803 if ((hpaddr->hpds & HPDS_VV) == 0) {
804f6eab
BJ
804 hpaddr->hpcs1 = HP_DCLR|HP_GO;
805 hpaddr->hpcs1 = HP_PRESET|HP_GO;
d565635a 806 hpaddr->hpof = HPOF_FMT22;
e3b4b145 807 }
b81fd3e8 808 st = &hpst[mi->mi_type];
1b81ee79
BJ
809 if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks)
810 return (EINVAL);
e3b4b145 811 while (num > 0) {
b81fd3e8 812 register struct pte *hpte = mba->mba_map;
e3b4b145 813 register int i;
b81fd3e8 814 int blk, cn, sn, tn;
e3b4b145
BJ
815 daddr_t bn;
816
817 blk = num > DBSIZE ? DBSIZE : num;
818 bn = dumplo + btop(start);
b81fd3e8
BJ
819 cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff;
820 sn = bn%st->nspc;
821 tn = sn/st->nsect;
822 sn = sn%st->nsect;
e3b4b145
BJ
823 hpaddr->hpdc = cn;
824 hpaddr->hpda = (tn << 8) + sn;
825 for (i = 0; i < blk; i++)
826 *(int *)hpte++ = (btop(start)+i) | PG_V;
b81fd3e8
BJ
827 mba->mba_sr = -1;
828 mba->mba_bcr = -(blk*NBPG);
829 mba->mba_var = 0;
804f6eab 830 hpaddr->hpcs1 = HP_WCOM | HP_GO;
d565635a 831 while ((hpaddr->hpds & HPDS_DRY) == 0)
e3b4b145 832 ;
d565635a 833 if (hpaddr->hpds&HPDS_ERR)
1b81ee79 834 return (EIO);
e3b4b145
BJ
835 start += blk*NBPG;
836 num -= blk;
837 }
838 return (0);
839}
a5cc519e 840#endif