|
|
1.1 root 1: /* hp.c 4.41 81/07/09 */
2:
3: #ifdef HPDEBUG
4: int hpdebug;
5: #endif
6: #ifdef HPBDEBUG
7: int hpbdebug;
8: #endif
9:
10: #include "hp.h"
11: #if NHP > 0
12: /*
13: * HP disk driver for RP0x+RMxx
14: *
15: * TODO:
16: * check RM80 skip sector handling when ECC's occur later
17: * check offset recovery handling
18: * see if DCLR and/or RELEASE set attention status
19: * print bits of mr && mr2 symbolically
20: */
21:
22: #include "../h/param.h"
23: #include "../h/systm.h"
24: #include "../h/dk.h"
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"
30: #include "../h/pte.h"
31: #include "../h/mbareg.h"
32: #include "../h/mbavar.h"
33: #include "../h/mtpr.h"
34: #include "../h/vm.h"
35: #include "../h/cmap.h"
36: #include "../h/dkbad.h"
37:
38: #include "../h/hpreg.h"
39:
40: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
41: struct size {
42: daddr_t nblocks;
43: int cyloff;
44: } hp6_sizes[8] = {
45: 15884, 0, /* A=cyl 0 thru 37 */
46: 33440, 38, /* B=cyl 38 thru 117 */
47: 340670, 0, /* C=cyl 0 thru 814 */
48: 0, 0,
49: 0, 0,
50: 0, 0,
51: #ifndef NOBADSECT
52: 291280, 118, /* G=cyl 118 thru 814 */
53: #else
54: 291346, 118,
55: #endif
56: 0, 0,
57: }, rm3_sizes[8] = {
58: 15884, 0, /* A=cyl 0 thru 99 */
59: 33440, 100, /* B=cyl 100 thru 309 */
60: 131680, 0, /* C=cyl 0 thru 822 */
61: 0, 0,
62: 0, 0,
63: 0, 0,
64: #ifndef NOBADSECT
65: 81984, 310, /* G=cyl 310 thru 822 */
66: #else
67: 82080, 310,
68: #endif
69: 0, 0,
70: }, rm5_sizes[8] = {
71: 15884, 0, /* A=cyl 0 thru 26 */
72: 33440, 27, /* B=cyl 27 thru 81 */
73: 500384, 0, /* C=cyl 0 thru 822 */
74: 15884, 562, /* D=cyl 562 thru 588 */
75: 55936, 589, /* E=cyl 589 thru 680 */
76: #ifndef NOBADSECT
77: 86240, 681, /* F=cyl 681 thru 822 */
78: 158592, 562, /* G=cyl 562 thru 822 */
79: #else
80: 86636, 681,
81: 158688, 562,
82: #endif
83: 291346, 82, /* H=cyl 82 thru 561 */
84: }, rm80_sizes[8] = {
85: 15884, 0, /* A=cyl 0 thru 36 */
86: 33440, 37, /* B=cyl 37 thru 114 */
87: 242606, 0, /* C=cyl 0 thru 558 */
88: 0, 0,
89: 0, 0,
90: 0, 0,
91: 82080, 115, /* G=cyl 115 thru 304 */
92: 110143, 305, /* H=cyl 305 thru 558 */
93: }, hp7_sizes[8] = {
94: 15844, 0, /* A=cyl 0 thru 9 */
95: 64000, 10, /* B=cyl 10 thru 49 */
96: 1008000,0, /* C=cyl 0 thru 629 */
97: 15884, 330, /* D=cyl 330 thru 339 */
98: 256000, 340, /* E=cyl 340 thru 499 */
99: 207850, 500, /* F=cyl 500 thru 629 */
100: 479850, 330, /* G=cyl 330 thru 629 */
101: 448000, 50, /* H=cyl 50 thru 329 */
102: };
103: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
104:
105: #define _hpSDIST 2
106: #define _hpRDIST 3
107:
108: int hpSDIST = _hpSDIST;
109: int hpRDIST = _hpRDIST;
110:
111: short hptypes[] =
112: { MBDT_RM03, MBDT_RM05, MBDT_RP06, MBDT_RM80, MBDT_RP05, MBDT_RP07, 0 };
113: struct mba_device *hpinfo[NHP];
114: int hpattach(),hpustart(),hpstart(),hpdtint();
115: struct mba_driver hpdriver =
116: { hpattach, 0, hpustart, hpstart, hpdtint, 0,
117: hptypes, "hp", 0, hpinfo };
118:
119: struct hpst {
120: short nsect;
121: short ntrak;
122: short nspc;
123: short ncyl;
124: struct size *sizes;
125: } hpst[] = {
126: 32, 5, 32*5, 823, rm3_sizes, /* RM03 */
127: 32, 19, 32*19, 823, rm5_sizes, /* RM05 */
128: 22, 19, 22*19, 815, hp6_sizes, /* RP06 */
129: 31, 14, 31*14, 559, rm80_sizes, /* RM80 */
130: 22, 19, 22*19, 411, hp6_sizes, /* RP05 */
131: 50, 32, 50*32, 630, hp7_sizes, /* RP07 */
132: };
133:
134: u_char hp_offset[16] = {
135: HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
136: HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800,
137: HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
138: 0, 0, 0, 0,
139: };
140:
141: struct buf rhpbuf[NHP];
142: #ifndef NOBADSECT
143: struct buf bhpbuf[NHP];
144: struct dkbad hpbad[NHP];
145: #endif
146: char hpinit[NHP];
147: char hprecal[NHP];
148:
149: #define b_cylin b_resid
150:
151: #ifdef INTRLVE
152: daddr_t dkblock();
153: #endif
154:
155: int hpseek;
156:
157: /*ARGSUSED*/
158: hpattach(mi, slave)
159: struct mba_device *mi;
160: {
161: register struct hpst *st = &hpst[mi->mi_type];
162:
163: if (mi->mi_dk >= 0)
164: dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256);
165: }
166:
167: hpstrategy(bp)
168: register struct buf *bp;
169: {
170: register struct mba_device *mi;
171: register struct hpst *st;
172: register int unit;
173: long sz, bn;
174: int xunit = minor(bp->b_dev) & 07;
175:
176: sz = bp->b_bcount;
177: sz = (sz+511) >> 9;
178: unit = dkunit(bp);
179: if (unit >= NHP)
180: goto bad;
181: mi = hpinfo[unit];
182: if (mi == 0 || mi->mi_alive == 0)
183: goto bad;
184: st = &hpst[mi->mi_type];
185: if (bp->b_blkno < 0 ||
186: (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
187: goto bad;
188: bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
189: (void) spl5();
190: disksort(&mi->mi_tab, bp);
191: if (mi->mi_tab.b_active == 0)
192: mbustart(mi);
193: (void) spl0();
194: return;
195:
196: bad:
197: bp->b_flags |= B_ERROR;
198: iodone(bp);
199: return;
200: }
201:
202: hpustart(mi)
203: register struct mba_device *mi;
204: {
205: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
206: register struct buf *bp = mi->mi_tab.b_actf;
207: register struct hpst *st = &hpst[mi->mi_type];
208: daddr_t bn;
209: int sn, dist;
210:
211: hpaddr->hpcs1 = 0;
212: if ((hpaddr->hpcs1&HP_DVA) == 0)
213: return (MBU_BUSY);
214: if ((hpaddr->hpds & HPDS_VV) == 0 || hpinit[mi->mi_unit] == 0) {
215: #ifndef NOBADSECT
216: struct buf *bbp = &bhpbuf[mi->mi_unit];
217: #endif
218:
219: hpinit[mi->mi_unit] = 1;
220: hpaddr->hpcs1 = HP_DCLR|HP_GO;
221: if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive))
222: printf("DCLR attn\n");
223: hpaddr->hpcs1 = HP_PRESET|HP_GO;
224: hpaddr->hpof = HPOF_FMT22;
225: mbclrattn(mi);
226: #ifndef NOBADSECT
227: bbp->b_flags = B_READ|B_BUSY;
228: bbp->b_dev = bp->b_dev;
229: bbp->b_bcount = 512;
230: bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit];
231: bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
232: bbp->b_cylin = st->ncyl - 1;
233: mi->mi_tab.b_actf = bbp;
234: bbp->av_forw = bp;
235: bp = bbp;
236: #endif
237: }
238: if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1)
239: return (MBU_DODATA);
240: if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY)
241: return (MBU_DODATA);
242: bn = dkblock(bp);
243: sn = bn%st->nspc;
244: sn = (sn+st->nsect-hpSDIST)%st->nsect;
245: if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) {
246: if (hpseek)
247: return (MBU_DODATA);
248: dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1;
249: if (dist < 0)
250: dist += st->nsect;
251: if (dist > st->nsect - hpRDIST)
252: return (MBU_DODATA);
253: } else
254: hpaddr->hpdc = bp->b_cylin;
255: if (hpseek)
256: hpaddr->hpcs1 = HP_SEEK|HP_GO;
257: else {
258: hpaddr->hpda = sn;
259: hpaddr->hpcs1 = HP_SEARCH|HP_GO;
260: }
261: return (MBU_STARTED);
262: }
263:
264: hpstart(mi)
265: register struct mba_device *mi;
266: {
267: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
268: register struct buf *bp = mi->mi_tab.b_actf;
269: register struct hpst *st = &hpst[mi->mi_type];
270: daddr_t bn;
271: int sn, tn;
272:
273: bn = dkblock(bp);
274: sn = bn%st->nspc;
275: tn = sn/st->nsect;
276: sn %= st->nsect;
277: hpaddr->hpdc = bp->b_cylin;
278: hpaddr->hpda = (tn << 8) + sn;
279: return(0);
280: }
281:
282: hpdtint(mi, mbsr)
283: register struct mba_device *mi;
284: int mbsr;
285: {
286: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
287: register struct buf *bp = mi->mi_tab.b_actf;
288: int retry = 0;
289:
290: #ifndef NOBADSECT
291: if (bp->b_flags&B_BAD) {
292: if (hpecc(mi, CONT))
293: return(MBD_RESTARTED);
294: }
295: #endif
296: if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
297: #ifdef HPDEBUG
298: if (hpdebug) {
299: int dc = hpaddr->hpdc, da = hpaddr->hpda;
300:
301: printf("hperr: bp %x cyl %d blk %d as %o ",
302: bp, bp->b_cylin, bp->b_blkno,
303: hpaddr->hpas&0xff);
304: printf("dc %x da %x\n",dc&0xffff, da&0xffff);
305: printf("errcnt %d ", mi->mi_tab.b_errcnt);
306: printf("mbsr=%b ", mbsr, mbsr_bits);
307: printf("er1=%b er2=%b\n",
308: hpaddr->hper1, HPER1_BITS,
309: hpaddr->hper2, HPER2_BITS);
310: DELAY(1000000);
311: }
312: #endif
313: if (hpaddr->hper1&HPER1_WLE) {
314: printf("hp%d: write locked\n", dkunit(bp));
315: bp->b_flags |= B_ERROR;
316: } else if (++mi->mi_tab.b_errcnt > 27 ||
317: mbsr & MBSR_HARD ||
318: hpaddr->hper1 & HPER1_HARD ||
319: hpaddr->hper2 & HPER2_HARD) {
320: hard:
321: harderr(bp, "hp");
322: if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
323: printf("mbsr=%b ", mbsr, mbsr_bits);
324: printf("er1=%b er2=%b",
325: hpaddr->hper1, HPER1_BITS,
326: hpaddr->hper2, HPER2_BITS);
327: if (hpaddr->hpmr)
328: printf(" mr=%o", hpaddr->hpmr&0xffff);
329: if (hpaddr->hpmr2)
330: printf(" mr2=%o", hpaddr->hpmr2&0xffff);
331: printf("\n");
332: bp->b_flags |= B_ERROR;
333: hprecal[mi->mi_unit] = 0;
334: } else if (hpaddr->hper2 & HPER2_BSE) {
335: #ifndef NOBADSECT
336: if (hpecc(mi, BSE))
337: return(MBD_RESTARTED);
338: else
339: #endif
340: goto hard;
341: } else if (hptypes[mi->mi_type] == MBDT_RM80 &&
342: hpaddr->hper2&HPER2_SSE) {
343: (void) hpecc(mi, SSE);
344: return (MBD_RESTARTED);
345: } else if ((hpaddr->hper1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) {
346: if (hpecc(mi, ECC))
347: return (MBD_RESTARTED);
348: /* else done */
349: } else
350: retry = 1;
351: hpaddr->hpcs1 = HP_DCLR|HP_GO;
352: if ((mi->mi_tab.b_errcnt&07) == 4) {
353: hpaddr->hpcs1 = HP_RECAL|HP_GO;
354: hprecal[mi->mi_unit] = 1;
355: return(MBD_RESTARTED);
356: }
357: if (retry)
358: return (MBD_RETRY);
359: }
360: #ifdef HPDEBUG
361: else
362: if (hpdebug && hprecal[mi->mi_unit]) {
363: printf("recal %d ", hprecal[mi->mi_unit]);
364: printf("errcnt %d\n", mi->mi_tab.b_errcnt);
365: printf("mbsr=%b ", mbsr, mbsr_bits);
366: printf("er1=%b er2=%b\n",
367: hpaddr->hper1, HPER1_BITS,
368: hpaddr->hper2, HPER2_BITS);
369: }
370: #endif
371: switch (hprecal[mi->mi_unit]) {
372:
373: case 1:
374: hpaddr->hpdc = bp->b_cylin;
375: hpaddr->hpcs1 = HP_SEEK|HP_GO;
376: hprecal[mi->mi_unit]++;
377: return (MBD_RESTARTED);
378: case 2:
379: if (mi->mi_tab.b_errcnt < 16 ||
380: (bp->b_flags & B_READ) == 0)
381: goto donerecal;
382: hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22;
383: hpaddr->hpcs1 = HP_OFFSET|HP_GO;
384: hprecal[mi->mi_unit]++;
385: return (MBD_RESTARTED);
386: donerecal:
387: case 3:
388: hprecal[mi->mi_unit] = 0;
389: return (MBD_RETRY);
390: }
391: bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff;
392: if (mi->mi_tab.b_errcnt >= 16) {
393: /*
394: * This is fast and occurs rarely; we don't
395: * bother with interrupts.
396: */
397: hpaddr->hpcs1 = HP_RTC|HP_GO;
398: while (hpaddr->hpds & HPDS_PIP)
399: ;
400: mbclrattn(mi);
401: }
402: hpaddr->hpof = HPOF_FMT22;
403: hpaddr->hpcs1 = HP_RELEASE|HP_GO;
404: return (MBD_DONE);
405: }
406:
407: hpread(dev)
408: dev_t dev;
409: {
410: register int unit = minor(dev) >> 3;
411:
412: if (unit >= NHP)
413: u.u_error = ENXIO;
414: else
415: physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys);
416: }
417:
418: hpwrite(dev)
419: dev_t dev;
420: {
421: register int unit = minor(dev) >> 3;
422:
423: if (unit >= NHP)
424: u.u_error = ENXIO;
425: else
426: physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys);
427: }
428:
429: hpecc(mi, flag)
430: register struct mba_device *mi;
431: int flag;
432: {
433: register struct mba_regs *mbp = mi->mi_mba;
434: register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv;
435: register struct buf *bp = mi->mi_tab.b_actf;
436: register struct hpst *st = &hpst[mi->mi_type];
437: int npf, o;
438: int bn, cn, tn, sn;
439: int bcr;
440:
441: bcr = mbp->mba_bcr & 0xffff;
442: if (bcr)
443: bcr |= 0xffff0000; /* sxt */
444: #ifndef NOBADSECT
445: if (flag == CONT)
446: npf = bp->b_error;
447: else
448: #endif
449: npf = btop(bcr + bp->b_bcount);
450: o = (int)bp->b_un.b_addr & PGOFSET;
451: bn = dkblock(bp);
452: cn = bp->b_cylin;
453: sn = bn%(st->nspc) + npf;
454: tn = sn/st->nsect;
455: sn %= st->nsect;
456: cn += tn/st->ntrak;
457: tn %= st->ntrak;
458: switch (flag) {
459: case ECC:
460: {
461: register int i;
462: caddr_t addr;
463: struct pte mpte;
464: int bit, byte, mask;
465:
466: npf--; /* because block in error is previous block */
467: printf("hp%d%c: soft ecc sn%d\n", dkunit(bp),
468: 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
469: mask = rp->hpec2&0xffff;
470: i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */
471: bit = i&07;
472: i = (i&~07)>>3;
473: byte = i + o;
474: while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
475: mpte = mbp->mba_map[npf+btop(byte)];
476: addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
477: putmemc(addr, getmemc(addr)^(mask<<bit));
478: byte++;
479: i++;
480: bit -= 8;
481: }
482: if (bcr == 0)
483: return (0);
484: npf++;
485: break;
486: }
487:
488: case SSE:
489: rp->hpof |= HPOF_SSEI;
490: mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
491: break;
492:
493: #ifndef NOBADSECT
494: case BSE:
495: #ifdef HPBDEBUG
496: if (hpbdebug)
497: printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
498: #endif
499: if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0)
500: return(0);
501: bp->b_flags |= B_BAD;
502: bp->b_error = npf + 1;
503: bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
504: cn = bn/st->nspc;
505: sn = bn%st->nspc;
506: tn = sn/st->nsect;
507: sn %= st->nsect;
508: mbp->mba_bcr = -512;
509: #ifdef HPBDEBUG
510: if (hpbdebug)
511: printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
512: #endif
513: break;
514:
515: case CONT:
516: #ifdef HPBDEBUG
517: if (hpbdebug)
518: printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
519: #endif
520: npf = bp->b_error;
521: bp->b_flags &= ~B_BAD;
522: mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
523: if ((mbp->mba_bcr & 0xffff) == 0)
524: return(0);
525: break;
526: #endif
527: }
528: rp->hpcs1 = HP_DCLR|HP_GO;
529: if (rp->hpof&HPOF_SSEI)
530: sn++;
531: rp->hpdc = cn;
532: rp->hpda = (tn<<8) + sn;
533: mbp->mba_sr = -1;
534: mbp->mba_var = (int)ptob(npf) + o;
535: rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO;
536: mi->mi_tab.b_errcnt = 0; /* error has been corrected */
537: return (1);
538: }
539:
540: #define DBSIZE 20
541:
542: hpdump(dev)
543: dev_t dev;
544: {
545: register struct mba_device *mi;
546: register struct mba_regs *mba;
547: struct hpdevice *hpaddr;
548: char *start;
549: int num, unit;
550: register struct hpst *st;
551:
552: num = maxfree;
553: start = 0;
554: unit = minor(dev) >> 3;
555: if (unit >= NHP)
556: return (ENXIO);
557: #define phys(a,b) ((b)((int)(a)&0x7fffffff))
558: mi = phys(hpinfo[unit],struct mba_device *);
559: if (mi == 0 || mi->mi_alive == 0)
560: return (ENXIO);
561: mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
562: mba->mba_cr = MBCR_INIT;
563: hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive];
564: if ((hpaddr->hpds & HPDS_VV) == 0) {
565: hpaddr->hpcs1 = HP_DCLR|HP_GO;
566: hpaddr->hpcs1 = HP_PRESET|HP_GO;
567: hpaddr->hpof = HPOF_FMT22;
568: }
569: st = &hpst[mi->mi_type];
570: if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks)
571: return (EINVAL);
572: while (num > 0) {
573: register struct pte *hpte = mba->mba_map;
574: register int i;
575: int blk, cn, sn, tn;
576: daddr_t bn;
577:
578: blk = num > DBSIZE ? DBSIZE : num;
579: bn = dumplo + btop(start);
580: cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff;
581: sn = bn%st->nspc;
582: tn = sn/st->nsect;
583: sn = sn%st->nsect;
584: hpaddr->hpdc = cn;
585: hpaddr->hpda = (tn << 8) + sn;
586: for (i = 0; i < blk; i++)
587: *(int *)hpte++ = (btop(start)+i) | PG_V;
588: mba->mba_sr = -1;
589: mba->mba_bcr = -(blk*NBPG);
590: mba->mba_var = 0;
591: hpaddr->hpcs1 = HP_WCOM | HP_GO;
592: while ((hpaddr->hpds & HPDS_DRY) == 0)
593: ;
594: if (hpaddr->hpds&HPDS_ERR)
595: return (EIO);
596: start += blk*NBPG;
597: num -= blk;
598: }
599: return (0);
600: }
601: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.