|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)hp.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: #ifdef HPDEBUG
10: int hpdebug;
11: #endif
12: #ifdef HPBDEBUG
13: int hpbdebug;
14: #endif
15:
16: #include "hp.h"
17: #if NHP > 0
18: /*
19: * HP disk driver for RP0x+RMxx+ML11
20: *
21: * TODO:
22: * see if DCLR and/or RELEASE set attention status
23: */
24: #include "../machine/pte.h"
25:
26: #include "param.h"
27: #include "systm.h"
28: #include "dk.h"
29: #include "buf.h"
30: #include "conf.h"
31: #include "dir.h"
32: #include "user.h"
33: #include "map.h"
34: #include "../vax/mtpr.h"
35: #include "vm.h"
36: #include "cmap.h"
37: #include "dkbad.h"
38: #include "ioctl.h"
39: #include "uio.h"
40: #include "syslog.h"
41:
42: #include "../vax/dkio.h"
43: #include "mbareg.h"
44: #include "mbavar.h"
45: #include "hpreg.h"
46:
47: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
48: struct size {
49: daddr_t nblocks;
50: int cyloff;
51: } rp06_sizes[8] = {
52: 15884, 0, /* A=cyl 0 thru 37 */
53: 33440, 38, /* B=cyl 38 thru 117 */
54: 340670, 0, /* C=cyl 0 thru 814 */
55: 15884, 118, /* D=cyl 118 thru 155 */
56: 55936, 156, /* E=cyl 156 thru 289 */
57: 219384, 290, /* F=cyl 290 thru 814 */
58: 291280, 118, /* G=cyl 118 thru 814 */
59: 0, 0,
60: }, rp05_sizes[8] = {
61: 15884, 0, /* A=cyl 0 thru 37 */
62: 33440, 38, /* B=cyl 38 thru 117 */
63: 171798, 0, /* C=cyl 0 thru 410 */
64: 15884, 118, /* D=cyl 118 thru 155 */
65: 55936, 156, /* E=cyl 156 thru 289 */
66: 50512, 290, /* F=cyl 290 thru 410 */
67: 122408, 118, /* G=cyl 118 thru 410 */
68: 0, 0,
69: }, rm03_sizes[8] = {
70: 15884, 0, /* A=cyl 0 thru 99 */
71: 33440, 100, /* B=cyl 100 thru 308 */
72: 131680, 0, /* C=cyl 0 thru 822 */
73: 15884, 309, /* D=cyl 309 thru 408 */
74: 55936, 409, /* E=cyl 409 thru 758 */
75: 10144, 759, /* F=cyl 759 thru 822 */
76: 82144, 309, /* G=cyl 309 thru 822 */
77: 0, 0,
78: }, rm05_sizes[8] = {
79: 15884, 0, /* A=cyl 0 thru 26 */
80: 33440, 27, /* B=cyl 27 thru 81 */
81: 500384, 0, /* C=cyl 0 thru 822 */
82: 15884, 562, /* D=cyl 562 thru 588 */
83: 55936, 589, /* E=cyl 589 thru 680 */
84: 86240, 681, /* F=cyl 681 thru 822 */
85: 158592, 562, /* G=cyl 562 thru 822 */
86: 291346, 82, /* H=cyl 82 thru 561 */
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: 15884, 115, /* D=cyl 115 thru 151 */
92: 55936, 152, /* E=cyl 152 thru 280 */
93: 120559, 281, /* F=cyl 281 thru 558 */
94: 192603, 115, /* G=cyl 115 thru 558 */
95: 0, 0,
96: }, rp07_sizes[8] = {
97: 15884, 0, /* A=cyl 0 thru 9 */
98: 66880, 10, /* B=cyl 10 thru 51 */
99: 1008000, 0, /* C=cyl 0 thru 629 */
100: 15884, 235, /* D=cyl 235 thru 244 */
101: 307200, 245, /* E=cyl 245 thru 436 */
102: 308650, 437, /* F=cyl 437 thru 629 */
103: 631850, 235, /* G=cyl 235 thru 629 */
104: 291346, 52, /* H=cyl 52 thru 234 */
105: }, cdc9775_sizes[8] = {
106: 15884, 0, /* A=cyl 0 thru 12 */
107: 66880, 13, /* B=cyl 13 thru 65 */
108: 1077760, 0, /* C=cyl 0 thru 841 */
109: 15884, 294, /* D=cyl 294 thru 306 */
110: 307200, 307, /* E=cyl 307 thru 546 */
111: 377440, 547, /* F=cyl 547 thru 841 */
112: 701280, 294, /* G=cyl 294 thru 841 */
113: 291346, 66, /* H=cyl 66 thru 293 */
114: }, cdc9730_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: 15884, 155, /* D=cyl 155 thru 204 */
119: 55936, 205, /* E=cyl 205 thru 379 */
120: 141664, 380, /* F=cyl 380 thru 822 */
121: 213664, 155, /* G=cyl 155 thru 822 */
122: 0, 0,
123: }, capricorn_sizes[8] = {
124: 15884, 0, /* A=cyl 0 thru 31 */
125: 33440, 32, /* B=cyl 32 thru 97 */
126: 524288, 0, /* C=cyl 0 thru 1023 */
127: 15884, 668, /* D=cyl 668 thru 699 */
128: 55936, 700, /* E=cyl 700 thru 809 */
129: 109472, 810, /* F=cyl 810 thru 1023 */
130: 182176, 668, /* G=cyl 668 thru 1023 */
131: 291346, 98, /* H=cyl 98 thru 667 */
132: }, eagle_sizes[8] = {
133: 15884, 0, /* A=cyl 0 thru 16 */
134: 66880, 17, /* B=cyl 17 thru 86 */
135: 808320, 0, /* C=cyl 0 thru 841 */
136: 15884, 391, /* D=cyl 391 thru 407 */
137: 307200, 408, /* E=cyl 408 thru 727 */
138: 109296, 728, /* F=cyl 728 thru 841 */
139: 432816, 391, /* G=cyl 391 thru 841 */
140: 291346, 87, /* H=cyl 87 thru 390 */
141: }, ampex_sizes[8] = {
142: 15884, 0, /* A=cyl 0 thru 26 */
143: 33440, 27, /* B=cyl 27 thru 81 */
144: 495520, 0, /* C=cyl 0 thru 814 */
145: 15884, 562, /* D=cyl 562 thru 588 */
146: 55936, 589, /* E=cyl 589 thru 680 */
147: 81312, 681, /* F=cyl 681 thru 814 */
148: 153664, 562, /* G=cyl 562 thru 814 */
149: 291346, 82, /* H=cyl 82 thru 561 */
150: }, fj2361_sizes[8] = {
151: 15884, 0, /* A=cyl 0 thru 12 */
152: 66880, 13, /* B=cyl 13 thru 65 */
153: 1077760, 0, /* C=cyl 0 thru 841 */
154: 15884, 294, /* D=cyl 294 thru 306 */
155: 307200, 307, /* E=cyl 307 thru 546 */
156: 377408, 547, /* F=cyl 547 thru 841 */
157: 701248, 294, /* G=cyl 294 thru 841 */
158: 291346, 66, /* H=cyl 66 thru 293 */
159: };
160: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
161:
162: /*
163: * Table for converting Massbus drive types into
164: * indices into the partition tables. Slots are
165: * left for those drives divined from other means
166: * (e.g. SI, AMPEX, etc.).
167: */
168: short hptypes[] = {
169: #define HPDT_RM03 0
170: MBDT_RM03,
171: #define HPDT_RM05 1
172: MBDT_RM05,
173: #define HPDT_RP06 2
174: MBDT_RP06,
175: #define HPDT_RM80 3
176: MBDT_RM80,
177: #define HPDT_RP04 4
178: MBDT_RP04,
179: #define HPDT_RP05 5
180: MBDT_RP05,
181: #define HPDT_RP07 6
182: MBDT_RP07,
183: #define HPDT_ML11A 7
184: MBDT_ML11A,
185: #define HPDT_ML11B 8
186: MBDT_ML11B,
187: #define HPDT_9775 9
188: -1,
189: #define HPDT_9730 10
190: -1,
191: #define HPDT_CAPRICORN 11
192: -1,
193: #define HPDT_EAGLE 12
194: -1,
195: #define HPDT_9300 13
196: -1,
197: #define HPDT_RM02 14
198: MBDT_RM02, /* beware, actually mapped */
199: #define HPDT_2361 15
200: -1,
201: 0
202: };
203: struct mba_device *hpinfo[NHP];
204: int hpattach(),hpustart(),hpstart(),hpdtint();
205: struct mba_driver hpdriver =
206: { hpattach, 0, hpustart, hpstart, hpdtint, 0,
207: hptypes, "hp", 0, hpinfo };
208:
209: /*
210: * These variable are all measured in sectors.
211: * Sdist is how much to "lead" in the search for a desired sector
212: * (i.e. if want N, search for N-sdist.)
213: * Maxdist and mindist define the region right before our desired sector within
214: * which we don't bother searching. We don't search when we are already less
215: * then maxdist and more than mindist sectors "before" our desired sector.
216: * Maxdist should be >= sdist.
217: *
218: * Beware, sdist, mindist and maxdist are not well tuned
219: * for many of the drives listed in this table.
220: * Try patching things with something i/o intensive
221: * running and watch iostat.
222: */
223: struct hpst {
224: short nsect; /* # sectors/track */
225: short ntrak; /* # tracks/cylinder */
226: short nspc; /* # sector/cylinders */
227: short ncyl; /* # cylinders */
228: struct size *sizes; /* partition tables */
229: short sdist; /* seek distance metric */
230: short maxdist; /* boundaries of non-searched area */
231: short mindist; /* preceding the target sector */
232: char *name; /* name of disk type */
233: } hpst[] = {
234: { 32, 5, 32*5, 823, rm03_sizes, 7, 4, 1, "RM03" },
235: { 32, 19, 32*19, 823, rm05_sizes, 7, 4, 1, "RM05" },
236: { 22,19, 22*19, 815, rp06_sizes, 7, 4, 1, "RP06"},
237: { 31, 14, 31*14, 559, rm80_sizes, 7, 4, 1, "RM80"},
238: { 22, 19, 22*19, 411, rp05_sizes, 7, 4, 1, "RP04"},
239: { 22, 19, 22*19, 411, rp05_sizes, 7, 4, 1, "RP05"},
240: { 50, 32, 50*32, 630, rp07_sizes, 15, 8, 3, "RP07"},
241: { 1, 1, 1, 1, 0, 0, 0, 0, "ML11A"},
242: { 1, 1, 1, 1, 0, 0, 0, 0, "ML11B" },
243: { 32, 40, 32*40, 843, cdc9775_sizes, 7, 4, 1, "9775" },
244: { 32, 10, 32*10, 823, cdc9730_sizes, 7, 4, 1, "9730-160" },
245: { 32, 16, 32*16, 1024, capricorn_sizes,10,4, 3, "capricorn" },
246: { 48, 20, 48*20, 842, eagle_sizes, 15, 8, 3, "eagle" },
247: { 32, 19, 32*19, 815, ampex_sizes, 7, 4, 1, "9300" },
248: { 64, 20, 64*20, 842, fj2361_sizes, 15, 8, 3, "2361" },
249: };
250:
251: u_char hp_offset[16] = {
252: HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
253: HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800,
254: HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
255: 0, 0, 0, 0,
256: };
257:
258: struct buf rhpbuf[NHP];
259: struct buf bhpbuf[NHP];
260: struct dkbad hpbad[NHP];
261:
262: struct hpsoftc {
263: u_char sc_hpinit; /* drive initialized */
264: u_char sc_recal; /* recalibrate state */
265: u_char sc_hdr; /* next i/o includes header */
266: u_char sc_doseeks; /* perform explicit seeks */
267: daddr_t sc_mlsize; /* ML11 size */
268: int sc_blkdone; /* amount sucessfully transfered */
269: daddr_t sc_badbn; /* replacement block number */
270: } hpsoftc[NHP];
271:
272: #define b_cylin b_resid
273:
274: /* #define ML11 0 to remove ML11 support */
275: #define ML11 (hptypes[mi->mi_type] == MBDT_ML11A)
276: #define RP06 (hptypes[mi->mi_type] <= MBDT_RP06)
277: #define RM80 (hptypes[mi->mi_type] == MBDT_RM80)
278:
279: #define hpunit(dev) (minor(dev) >> 3)
280: #define MASKREG(reg) ((reg)&0xffff)
281: #ifdef lint
282: #define HPWAIT(mi, addr) (hpwait(mi))
283: #else
284: #define HPWAIT(mi, addr) (((addr)->hpds & HPDS_DRY) || hpwait(mi))
285: #endif
286:
287: /*ARGSUSED*/
288: hpattach(mi, slave)
289: register struct mba_device *mi;
290: {
291:
292: mi->mi_type = hpmaptype(mi);
293: if (!ML11 && mi->mi_dk >= 0) {
294: struct hpst *st = &hpst[mi->mi_type];
295:
296: dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256);
297: }
298: }
299:
300: /*
301: * Map apparent MASSBUS drive type into manufacturer
302: * specific configuration. For SI controllers this is done
303: * based on codes in the serial number register. For
304: * EMULEX controllers, the track and sector attributes are
305: * used when the drive type is an RM02 (not supported by DEC).
306: */
307: hpmaptype(mi)
308: register struct mba_device *mi;
309: {
310: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
311: register int type = mi->mi_type;
312:
313: /*
314: * Model-byte processing for SI controllers.
315: * NB: Only deals with RM03 and RM05 emulations.
316: */
317: if (type == HPDT_RM03 || type == HPDT_RM05) {
318: int hpsn = hpaddr->hpsn;
319:
320: if ((hpsn & SIMB_LU) != mi->mi_drive)
321: return (type);
322: switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) {
323:
324: case SI9775D:
325: printf("hp%d: 9775 (direct)\n", mi->mi_unit);
326: type = HPDT_9775;
327: break;
328:
329: case SI9730D:
330: printf("hp%d: 9730 (direct)\n", mi->mi_unit);
331: type = HPDT_9730;
332: break;
333:
334: case SI9766:
335: printf("hp%d: 9766\n", mi->mi_unit);
336: type = HPDT_RM05;
337: break;
338:
339: case SI9762:
340: printf("hp%d: 9762\n", mi->mi_unit);
341: type = HPDT_RM03;
342: break;
343:
344: case SICAPD:
345: printf("hp%d: capricorn\n", mi->mi_unit);
346: type = HPDT_CAPRICORN;
347: break;
348:
349: case SI9751D:
350: printf("hp%d: eagle\n", mi->mi_unit);
351: type = HPDT_EAGLE;
352: break;
353: }
354: return (type);
355: }
356:
357: /*
358: * EMULEX SC750 or SC780. Poke the holding register.
359: */
360: if (type == HPDT_RM02) {
361: int nsectors, ntracks, ncyl;
362:
363: hpaddr->hpof = HPOF_FMT22;
364: mbclrattn(mi);
365: hpaddr->hpcs1 = HP_NOP;
366: hpaddr->hphr = HPHR_MAXTRAK;
367: ntracks = MASKREG(hpaddr->hphr) + 1;
368: DELAY(100);
369: hpaddr->hpcs1 = HP_NOP;
370: hpaddr->hphr = HPHR_MAXSECT;
371: nsectors = MASKREG(hpaddr->hphr) + 1;
372: DELAY(100);
373: hpaddr->hpcs1 = HP_NOP;
374: hpaddr->hphr = HPHR_MAXCYL;
375: ncyl = MASKREG(hpaddr->hphr) + 1;
376: for (type = 0; hptypes[type] != 0; type++)
377: if (hpst[type].nsect == nsectors &&
378: hpst[type].ntrak == ntracks &&
379: hpst[type].ncyl == ncyl)
380: break;
381:
382: if (hptypes[type] == 0) {
383: printf("hp%d: %d sectors, %d tracks, %d cylinders: unknown device\n",
384: mi->mi_unit, nsectors, ntracks, ncyl);
385: type = HPDT_RM02;
386: }
387: printf("hp%d: %s\n", mi->mi_unit, hpst[type].name);
388: hpaddr->hpcs1 = HP_DCLR|HP_GO;
389: mbclrattn(mi); /* conservative */
390: return (type);
391: }
392:
393: /*
394: * Map all ML11's to the same type. Also calculate
395: * transfer rates based on device characteristics.
396: */
397: if (type == HPDT_ML11A || type == HPDT_ML11B) {
398: register struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
399: register int trt;
400:
401: sc->sc_mlsize = hpaddr->hpmr & HPMR_SZ;
402: if ((hpaddr->hpmr & HPMR_ARRTYP) == 0)
403: sc->sc_mlsize >>= 2;
404: if (mi->mi_dk >= 0) {
405: trt = (hpaddr->hpmr & HPMR_TRT) >> 8;
406: dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt));
407: }
408: type = HPDT_ML11A;
409: }
410: return (type);
411: }
412:
413: hpopen(dev)
414: dev_t dev;
415: {
416: register int unit = hpunit(dev);
417: register struct mba_device *mi;
418:
419: if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0)
420: return (ENXIO);
421: return (0);
422: }
423:
424: hpstrategy(bp)
425: register struct buf *bp;
426: {
427: register struct mba_device *mi;
428: register struct hpst *st;
429: register int unit;
430: long sz;
431: int xunit = minor(bp->b_dev) & 07;
432: int s;
433:
434: sz = bp->b_bcount;
435: sz = (sz+511) >> 9;
436: unit = hpunit(bp->b_dev);
437: if (unit >= NHP) {
438: bp->b_error = ENXIO;
439: goto bad;
440: }
441: mi = hpinfo[unit];
442: if (mi == 0 || mi->mi_alive == 0) {
443: bp->b_error = ENXIO;
444: goto bad;
445: }
446: st = &hpst[mi->mi_type];
447: if (ML11) {
448: struct hpsoftc *sc = &hpsoftc[unit];
449:
450: if (bp->b_blkno < 0 ||
451: bp->b_blkno+sz > sc->sc_mlsize) {
452: if (bp->b_blkno == sc->sc_mlsize) {
453: bp->b_resid = bp->b_bcount;
454: goto done;
455: }
456: bp->b_error = EINVAL;
457: goto bad;
458: }
459: bp->b_cylin = 0;
460: } else {
461: if (bp->b_blkno < 0 ||
462: bp->b_blkno+sz > st->sizes[xunit].nblocks) {
463: if (bp->b_blkno == st->sizes[xunit].nblocks) {
464: bp->b_resid = bp->b_bcount;
465: goto done;
466: }
467: bp->b_error = EINVAL;
468: goto bad;
469: }
470: bp->b_cylin = bp->b_blkno/st->nspc + st->sizes[xunit].cyloff;
471: }
472: s = spl5();
473: disksort(&mi->mi_tab, bp);
474: if (mi->mi_tab.b_active == 0)
475: mbustart(mi);
476: splx(s);
477: return;
478:
479: bad:
480: bp->b_flags |= B_ERROR;
481: done:
482: iodone(bp);
483: return;
484: }
485:
486: hpustart(mi)
487: register struct mba_device *mi;
488: {
489: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
490: register struct buf *bp = mi->mi_tab.b_actf;
491: register struct hpst *st;
492: struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
493: daddr_t bn;
494: int sn, tn, dist;
495:
496: st = &hpst[mi->mi_type];
497: hpaddr->hpcs1 = 0;
498: if ((hpaddr->hpcs1&HP_DVA) == 0)
499: return (MBU_BUSY);
500:
501: switch (sc->sc_recal) {
502:
503: case 1:
504: (void)HPWAIT(mi, hpaddr);
505: hpaddr->hpdc = bp->b_cylin;
506: hpaddr->hpcs1 = HP_SEEK|HP_GO;
507: sc->sc_recal++;
508: return (MBU_STARTED);
509: case 2:
510: break;
511: }
512: sc->sc_recal = 0;
513: if ((hpaddr->hpds & HPDS_VV) == 0 || !sc->sc_hpinit) {
514: struct buf *bbp = &bhpbuf[mi->mi_unit];
515:
516: sc->sc_hpinit = 1;
517: hpaddr->hpcs1 = HP_DCLR|HP_GO;
518: if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive))
519: printf("DCLR attn\n");
520: hpaddr->hpcs1 = HP_PRESET|HP_GO;
521: if (!ML11)
522: hpaddr->hpof = HPOF_FMT22;
523: mbclrattn(mi);
524: if (!ML11) {
525: bbp->b_flags = B_READ|B_BUSY;
526: bbp->b_dev = bp->b_dev;
527: bbp->b_bcount = 512;
528: bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit];
529: bbp->b_blkno = st->ncyl*st->nspc - st->nsect;
530: bbp->b_cylin = st->ncyl - 1;
531: mi->mi_tab.b_actf = bbp;
532: bbp->av_forw = bp;
533: bp = bbp;
534: }
535: }
536: if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) {
537: if (mi->mi_tab.b_errcnt >= 16 && (bp->b_flags & B_READ)) {
538: hpaddr->hpof =
539: hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22;
540: hpaddr->hpcs1 = HP_OFFSET|HP_GO;
541: (void)HPWAIT(mi, hpaddr);
542: mbclrattn(mi);
543: }
544: return (MBU_DODATA);
545: }
546: if (ML11)
547: return (MBU_DODATA);
548: if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY)
549: return (MBU_DODATA);
550: bn = bp->b_blkno;
551: sn = bn % st->nspc;
552: tn = sn / st->nsect;
553: sn = sn % st->nsect;
554: if (bp->b_cylin == MASKREG(hpaddr->hpdc)) {
555: if (sc->sc_doseeks)
556: return (MBU_DODATA);
557: dist = sn - (MASKREG(hpaddr->hpla) >> 6) - 1;
558: if (dist < 0)
559: dist += st->nsect;
560: if (dist > st->maxdist || dist < st->mindist)
561: return (MBU_DODATA);
562: } else
563: hpaddr->hpdc = bp->b_cylin;
564: if (sc->sc_doseeks)
565: hpaddr->hpcs1 = HP_SEEK|HP_GO;
566: else {
567: sn = (sn + st->nsect - st->sdist) % st->nsect;
568: hpaddr->hpda = (tn << 8) + sn;
569: hpaddr->hpcs1 = HP_SEARCH|HP_GO;
570: }
571: return (MBU_STARTED);
572: }
573:
574: hpstart(mi)
575: register struct mba_device *mi;
576: {
577: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
578: register struct buf *bp = mi->mi_tab.b_actf;
579: register struct hpst *st = &hpst[mi->mi_type];
580: struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
581: daddr_t bn;
582: int sn, tn, cn;
583:
584: if (ML11)
585: hpaddr->hpda = bp->b_blkno + sc->sc_blkdone;
586: else {
587: if (bp->b_flags & B_BAD) {
588: bn = sc->sc_badbn;
589: cn = bn / st->nspc;
590: } else {
591: bn = bp->b_blkno;
592: cn = bp->b_cylin;
593: }
594: sn = bn % st->nspc;
595: if ((bp->b_flags & B_BAD) == 0)
596: sn += sc->sc_blkdone;
597: tn = sn / st->nsect;
598: sn %= st->nsect;
599: cn += tn / st->ntrak;
600: tn %= st->ntrak;
601: hpaddr->hpda = (tn << 8) + sn;
602: hpaddr->hpdc = cn;
603: }
604: mi->mi_tab.b_bdone = dbtob(sc->sc_blkdone);
605: if (sc->sc_hdr) {
606: if (bp->b_flags & B_READ)
607: return (HP_RHDR|HP_GO);
608: else
609: return (HP_WHDR|HP_GO);
610: }
611: return (0);
612: }
613:
614: hpdtint(mi, mbsr)
615: register struct mba_device *mi;
616: int mbsr;
617: {
618: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
619: register struct buf *bp = mi->mi_tab.b_actf;
620: register int er1, er2;
621: struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
622: int retry = 0;
623: int npf;
624: daddr_t bn;
625: int bcr;
626:
627: bcr = MASKREG(-mi->mi_mba->mba_bcr);
628: if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) {
629: er1 = hpaddr->hper1;
630: er2 = hpaddr->hper2;
631: if (bp->b_flags & B_BAD) {
632: npf = bp->b_error;
633: bn = sc->sc_badbn;
634: } else {
635: npf = btop(bp->b_bcount - bcr);
636: if (er1 & (HPER1_DCK | HPER1_ECH))
637: npf--;
638: bn = bp->b_blkno + npf;
639: }
640: if (HPWAIT(mi, hpaddr) == 0)
641: goto hard;
642: #ifdef HPDEBUG
643: if (hpdebug) {
644: int dc = hpaddr->hpdc, da = hpaddr->hpda;
645:
646: log(LOG_DEBUG,
647: "hperr: bp %x cyl %d blk %d blkdone %d as %o dc %x da %x\n",
648: bp, bp->b_cylin, bn, sc->sc_blkdone,
649: hpaddr->hpas&0xff, MASKREG(dc), MASKREG(da));
650: log(LOG_DEBUG,
651: "errcnt %d mbsr=%b er1=%b er2=%b bcr -%d\n",
652: mi->mi_tab.b_errcnt, mbsr, mbsr_bits,
653: MASKREG(er1), HPER1_BITS,
654: MASKREG(er2), HPER2_BITS, bcr);
655: }
656: #endif
657: if (er1 & HPER1_HCRC) {
658: er1 &= ~(HPER1_HCE|HPER1_FER);
659: er2 &= ~HPER2_BSE;
660: }
661: if (er1 & HPER1_WLE) {
662: log(LOG_WARNING, "hp%d: write locked\n",
663: hpunit(bp->b_dev));
664: bp->b_flags |= B_ERROR;
665: } else if (sc->sc_hdr) {
666: goto hard;
667: } else if (RM80 && er2&HPER2_SSE) {
668: (void) hpecc(mi, SSE);
669: return (MBD_RESTARTED);
670: } else if ((er2 & HPER2_BSE) && !ML11) {
671: if (hpecc(mi, BSE))
672: return (MBD_RESTARTED);
673: goto hard;
674: } else if (MASKREG(er1) == HPER1_FER && RP06) {
675: if (hpecc(mi, BSE))
676: return (MBD_RESTARTED);
677: goto hard;
678: } else if ((er1 & (HPER1_DCK | HPER1_ECH)) == HPER1_DCK &&
679: mi->mi_tab.b_errcnt >= 3) {
680: if (hpecc(mi, ECC))
681: return (MBD_RESTARTED);
682: /*
683: * ECC corrected. Only log retries below
684: * if we got errors other than soft ECC
685: * (as indicated by additional retries).
686: */
687: if (mi->mi_tab.b_errcnt == 3)
688: mi->mi_tab.b_errcnt = 0;
689: } else if ((er1 & HPER1_HCRC) && !ML11 && hpecc(mi, BSE)) {
690: /*
691: * HCRC means the header is screwed up and the sector
692: * might well exist in the bad sector table,
693: * better check....
694: */
695: return (MBD_RESTARTED);
696: } else if (++mi->mi_tab.b_errcnt > 27 ||
697: (ML11 && mi->mi_tab.b_errcnt > 15) ||
698: mbsr & MBSR_HARD ||
699: er1 & HPER1_HARD ||
700: (!ML11 && (er2 & HPER2_HARD))) {
701: hard:
702: bp->b_blkno = bn; /* XXX */
703: harderr(bp, "hp");
704: if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC)))
705: printf("mbsr=%b ", mbsr, mbsr_bits);
706: printf("er1=%b er2=%b",
707: MASKREG(hpaddr->hper1), HPER1_BITS,
708: MASKREG(hpaddr->hper2), HPER2_BITS);
709: if (sc->sc_hdr)
710: printf(" (hdr i/o)");
711: printf("\n");
712: bp->b_flags |= B_ERROR;
713: bp->b_flags &= ~B_BAD;
714: } else
715: retry = 1;
716: hpaddr->hpcs1 = HP_DCLR|HP_GO;
717: if (retry && (mi->mi_tab.b_errcnt & 07) == 4) {
718: hpaddr->hpcs1 = HP_RECAL|HP_GO;
719: sc->sc_recal = 1;
720: return (MBD_REPOSITION);
721: }
722: }
723: #ifdef HPDEBUG
724: else
725: if (hpdebug && sc->sc_recal) {
726: log(LOG_DEBUG,
727: "recal %d errcnt %d mbsr=%b er1=%b er2=%b\n",
728: sc->sc_recal, mi->mi_tab.b_errcnt, mbsr, mbsr_bits,
729: hpaddr->hper1, HPER1_BITS,
730: hpaddr->hper2, HPER2_BITS);
731: }
732: #endif
733: (void)HPWAIT(mi, hpaddr);
734: if (retry)
735: return (MBD_RETRY);
736: if (mi->mi_tab.b_errcnt >= 16) {
737: /*
738: * This is fast and occurs rarely; we don't
739: * bother with interrupts.
740: */
741: hpaddr->hpcs1 = HP_RTC|HP_GO;
742: (void)HPWAIT(mi, hpaddr);
743: mbclrattn(mi);
744: }
745: if (mi->mi_tab.b_errcnt && (bp->b_flags & B_ERROR) == 0)
746: log(LOG_INFO, "hp%d%c: %d retries %sing sn%d\n",
747: hpunit(bp->b_dev), 'a'+(minor(bp->b_dev)&07),
748: mi->mi_tab.b_errcnt,
749: (bp->b_flags & B_READ) ? "read" : "writ",
750: (bp->b_flags & B_BAD) ?
751: sc->sc_badbn : bp->b_blkno + sc->sc_blkdone);
752: if ((bp->b_flags & B_BAD) && hpecc(mi, CONT))
753: return (MBD_RESTARTED);
754: sc->sc_hdr = 0;
755: sc->sc_blkdone = 0;
756: bp->b_resid = bcr;
757: if (!ML11) {
758: hpaddr->hpof = HPOF_FMT22;
759: hpaddr->hpcs1 = HP_RELEASE|HP_GO;
760: }
761: return (MBD_DONE);
762: }
763:
764: /*
765: * Wait (for a bit) for a drive to come ready;
766: * returns nonzero on success.
767: */
768: hpwait(mi)
769: register struct mba_device *mi;
770: {
771: register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv;
772: register i = 100000;
773:
774: while ((hpaddr->hpds & HPDS_DRY) == 0 && --i)
775: DELAY(10);
776: if (i == 0)
777: printf("hp%d: intr, not ready\n", mi->mi_unit);
778: return (i);
779: }
780:
781: hpread(dev, uio)
782: dev_t dev;
783: struct uio *uio;
784: {
785: register int unit = hpunit(dev);
786:
787: if (unit >= NHP)
788: return (ENXIO);
789: return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio));
790: }
791:
792: hpwrite(dev, uio)
793: dev_t dev;
794: struct uio *uio;
795: {
796: register int unit = hpunit(dev);
797:
798: if (unit >= NHP)
799: return (ENXIO);
800: return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio));
801: }
802:
803: /*ARGSUSED*/
804: hpioctl(dev, cmd, data, flag)
805: dev_t dev;
806: int cmd;
807: caddr_t data;
808: int flag;
809: {
810:
811: switch (cmd) {
812:
813: case DKIOCHDR: /* do header read/write */
814: hpsoftc[hpunit(dev)].sc_hdr = 1;
815: return (0);
816:
817: default:
818: return (ENXIO);
819: }
820: }
821:
822: hpecc(mi, flag)
823: register struct mba_device *mi;
824: int flag;
825: {
826: register struct mba_regs *mbp = mi->mi_mba;
827: register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv;
828: register struct buf *bp = mi->mi_tab.b_actf;
829: register struct hpst *st = &hpst[mi->mi_type];
830: struct hpsoftc *sc = &hpsoftc[mi->mi_unit];
831: int npf, o;
832: int bn, cn, tn, sn;
833: int bcr;
834:
835: bcr = MASKREG(-mbp->mba_bcr);
836: if (bp->b_flags & B_BAD)
837: npf = bp->b_error;
838: else {
839: npf = bp->b_bcount - bcr;
840: /*
841: * Watch out for fractional sector at end of transfer;
842: * want to round up if finished, otherwise round down.
843: */
844: if (bcr == 0)
845: npf += 511;
846: npf = btodb(npf);
847: }
848: o = (int)bp->b_un.b_addr & PGOFSET;
849: bn = bp->b_blkno;
850: cn = bp->b_cylin;
851: sn = bn%(st->nspc) + npf;
852: tn = sn/st->nsect;
853: sn %= st->nsect;
854: cn += tn/st->ntrak;
855: tn %= st->ntrak;
856: bn += npf;
857: switch (flag) {
858: case ECC: {
859: register int i;
860: caddr_t addr;
861: struct pte mpte;
862: int bit, byte, mask;
863:
864: npf--; /* because block in error is previous block */
865: bn--;
866: if (bp->b_flags & B_BAD)
867: bn = sc->sc_badbn;
868: log(LOG_WARNING, "hp%d%c: soft ecc sn%d\n", hpunit(bp->b_dev),
869: 'a'+(minor(bp->b_dev)&07), bn);
870: mask = MASKREG(rp->hpec2);
871: i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */
872: bit = i&07;
873: i = (i&~07)>>3;
874: byte = i + o;
875: while (i < 512 && (int)dbtob(npf)+i < bp->b_bcount && bit > -11) {
876: mpte = mbp->mba_map[npf+btop(byte)];
877: addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
878: putmemc(addr, getmemc(addr)^(mask<<bit));
879: byte++;
880: i++;
881: bit -= 8;
882: }
883: if (bcr == 0)
884: return (0);
885: npf++;
886: break;
887: }
888:
889: case SSE:
890: rp->hpof |= HPOF_SSEI;
891: if (bp->b_flags & B_BAD) {
892: bn = sc->sc_badbn;
893: goto fixregs;
894: }
895: mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
896: break;
897:
898: case BSE:
899: if (rp->hpof & HPOF_SSEI)
900: sn++;
901: #ifdef HPBDEBUG
902: if (hpbdebug)
903: log(LOG_DEBUG, "hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn);
904: #endif
905: if (bp->b_flags & B_BAD)
906: return (0);
907: if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0)
908: return (0);
909: bp->b_flags |= B_BAD;
910: bp->b_error = npf + 1;
911: rp->hpof &= ~HPOF_SSEI;
912: bn = st->ncyl*st->nspc - st->nsect - 1 - bn;
913: sc->sc_badbn = bn;
914: fixregs:
915: cn = bn/st->nspc;
916: sn = bn%st->nspc;
917: tn = sn/st->nsect;
918: sn %= st->nsect;
919: bcr = bp->b_bcount - (int)ptob(npf);
920: bcr = MIN(bcr, 512);
921: mbp->mba_bcr = -bcr;
922: #ifdef HPBDEBUG
923: if (hpbdebug)
924: log(LOG_DEBUG, "revector to cn %d tn %d sn %d\n", cn, tn, sn);
925: #endif
926: break;
927:
928: case CONT:
929: #ifdef HPBDEBUG
930: if (hpbdebug)
931: log(LOG_DEBUG, "hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn);
932: #endif
933: bp->b_flags &= ~B_BAD;
934: if ((int)ptob(npf) >= bp->b_bcount)
935: return (0);
936: mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf));
937: break;
938: }
939: rp->hpcs1 = HP_DCLR|HP_GO;
940: if (rp->hpof & HPOF_SSEI)
941: sn++;
942: rp->hpdc = cn;
943: rp->hpda = (tn<<8) + sn;
944: mbp->mba_sr = -1;
945: mbp->mba_var = (int)ptob(npf) + o;
946: rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO;
947: mi->mi_tab.b_errcnt = 0; /* error has been corrected */
948: sc->sc_blkdone = npf;
949: return (1);
950: }
951:
952: #define DBSIZE 20
953:
954: hpdump(dev)
955: dev_t dev;
956: {
957: register struct mba_device *mi;
958: register struct mba_regs *mba;
959: struct hpdevice *hpaddr;
960: char *start;
961: int num, unit;
962: register struct hpst *st;
963:
964: num = maxfree;
965: start = 0;
966: unit = hpunit(dev);
967: if (unit >= NHP)
968: return (ENXIO);
969: #define phys(a,b) ((b)((int)(a)&0x7fffffff))
970: mi = phys(hpinfo[unit],struct mba_device *);
971: if (mi == 0 || mi->mi_alive == 0)
972: return (ENXIO);
973: mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
974: mba->mba_cr = MBCR_INIT;
975: hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive];
976: if ((hpaddr->hpds & HPDS_VV) == 0) {
977: hpaddr->hpcs1 = HP_DCLR|HP_GO;
978: hpaddr->hpcs1 = HP_PRESET|HP_GO;
979: hpaddr->hpof = HPOF_FMT22;
980: }
981: st = &hpst[mi->mi_type];
982: if (dumplo < 0)
983: return (EINVAL);
984: if (dumplo + num >= st->sizes[minor(dev)&07].nblocks)
985: num = st->sizes[minor(dev)&07].nblocks - dumplo;
986: while (num > 0) {
987: register struct pte *hpte = mba->mba_map;
988: register int i;
989: int blk, cn, sn, tn;
990: daddr_t bn;
991:
992: blk = num > DBSIZE ? DBSIZE : num;
993: bn = dumplo + btop(start);
994: cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff;
995: sn = bn%st->nspc;
996: tn = sn/st->nsect;
997: sn = sn%st->nsect;
998: hpaddr->hpdc = cn;
999: hpaddr->hpda = (tn << 8) + sn;
1000: for (i = 0; i < blk; i++)
1001: *(int *)hpte++ = (btop(start)+i) | PG_V;
1002: mba->mba_sr = -1;
1003: mba->mba_bcr = -(blk*NBPG);
1004: mba->mba_var = 0;
1005: hpaddr->hpcs1 = HP_WCOM | HP_GO;
1006: while ((hpaddr->hpds & HPDS_DRY) == 0)
1007: DELAY(10);
1008: if (hpaddr->hpds&HPDS_ERR)
1009: return (EIO);
1010: start += blk*NBPG;
1011: num -= blk;
1012: }
1013: return (0);
1014: }
1015:
1016: hpsize(dev)
1017: dev_t dev;
1018: {
1019: int unit = hpunit(dev);
1020: struct mba_device *mi;
1021: struct hpst *st;
1022:
1023: if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0)
1024: return (-1);
1025: st = &hpst[mi->mi_type];
1026: return ((int)st->sizes[minor(dev) & 07].nblocks);
1027: }
1028: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.