|
|
1.1 root 1: /* hp.c 4.1 11/9/80 */
2:
3: #include "../conf/hp.h"
4: #if NHP > 0
5: /*
6: * RP06/RM03/RM05 disk driver
7: */
8:
9: #include "../h/param.h"
10: #include "../h/systm.h"
11: #include "../h/dk.h"
12: #include "../h/buf.h"
13: #include "../h/conf.h"
14: #include "../h/dir.h"
15: #include "../h/user.h"
16: #include "../h/map.h"
17: #include "../h/pte.h"
18: #include "../h/mba.h"
19: #include "../h/mtpr.h"
20: #include "../h/vm.h"
21:
22: struct device
23: {
24: int hpcs1; /* control and Status register 1 */
25: int hpds; /* Drive Status */
26: int hper1; /* Error register 1 */
27: int hpmr; /* Maintenance */
28: int hpas; /* Attention Summary */
29: int hpda; /* Desired address register */
30: int hpdt; /* Drive type */
31: int hpla; /* Look ahead */
32: int hpsn; /* serial number */
33: int hpof; /* Offset register */
34: int hpdc; /* Desired Cylinder address register */
35: int hpcc; /* Current Cylinder */
36: int hper2; /* Error register 2 */
37: int hper3; /* Error register 3 */
38: int hpec1; /* Burst error bit position */
39: int hpec2; /* Burst error bit pattern */
40: };
41:
42: #define RP 022
43: #define RM 024
44: #define RM5 027
45: #define NSECT 22
46: #define NTRAC 19
47: #define NRMSECT 32
48: #define NRMTRAC 5
49:
50: #define _hpSDIST 2
51: #define _hpRDIST 3
52:
53: int hpSDIST = _hpSDIST;
54: int hpRDIST = _hpRDIST;
55: int hpseek;
56:
57: struct size
58: {
59: daddr_t nblocks;
60: int cyloff;
61: } hp_sizes[8] =
62: {
63: 15884, 0, /* A=cyl 0 thru 37 */
64: 33440, 38, /* B=cyl 38 thru 117 */
65: 340670, 0, /* C=cyl 0 thru 814 */
66: 0, 0,
67: 0, 0,
68: 0, 0,
69: 291346, 118, /* G=cyl 118 thru 814 */
70: 0, 0,
71: }, rm_sizes[8] = {
72: 15884, 0, /* A=cyl 0 thru 99 */
73: 33440, 100, /* B=cyl 100 thru 309 */
74: 131680, 0, /* C=cyl 0 thru 822 */
75: 0, 0,
76: 0, 0,
77: 0, 0,
78: 82080, 310, /* G=cyl 310 thru 822 */
79: 0, 0,
80: }, rm5_sizes[8] = {
81: 15884, 0, /* A=cyl 0 thru 26 */
82: 33440, 27, /* B=cyl 27 thru 81 */
83: 500992, 0, /* C=cyl 0 thru 823 */
84: 15884, 562, /* D=cyl 562 thru 588 */
85: 55936, 589, /* E=cyl 589 thru 680 */
86: 86944, 681, /* F=cyl 681 thru 823 */
87: 159296, 562, /* G=cyl 562 thru 823 */
88: 291346, 82, /* H=cyl 82 thru 561 */
89: };
90:
91: #define P400 020
92: #define M400 0220
93: #define P800 040
94: #define M800 0240
95: #define P1200 060
96: #define M1200 0260
97: int hp_offset[16] =
98: {
99: P400, M400, P400, M400,
100: P800, M800, P800, M800,
101: P1200, M1200, P1200, M1200,
102: 0, 0, 0, 0,
103: };
104:
105: struct buf hptab;
106: struct buf rhpbuf;
107: struct buf hputab[NHP];
108: char hp_type[NHP]; /* drive type */
109:
110: #define GO 01
111: #define PRESET 020
112: #define RTC 016
113: #define OFFSET 014
114: #define SEEK 04
115: #define SEARCH 030
116: #define RECAL 06
117: #define DCLR 010
118: #define WCOM 060
119: #define RCOM 070
120:
121: #define IE 0100
122: #define PIP 020000
123: #define DRY 0200
124: #define ERR 040000
125: #define TRE 040000
126: #define DCK 0100000
127: #define WLE 04000
128: #define ECH 0100
129: #define VV 0100
130: #define DPR 0400
131: #define MOL 010000
132: #define FMT22 010000
133:
134: #define b_cylin b_resid
135:
136: #ifdef INTRLVE
137: daddr_t dkblock();
138: #endif
139:
140: hpstrategy(bp)
141: register struct buf *bp;
142: {
143: register struct buf *dp;
144: register unit, xunit, nspc;
145: long sz, bn;
146: struct size *sizes;
147:
148: if ((mbaact&(1<<HPMBANUM)) == 0)
149: mbainit(HPMBANUM);
150: xunit = minor(bp->b_dev) & 077;
151: sz = bp->b_bcount;
152: sz = (sz+511) >> 9;
153: unit = dkunit(bp);
154: if (hp_type[unit] == 0) {
155: struct device *hpaddr;
156: double mspw;
157:
158: /* determine device type */
159: hpaddr = mbadev(HPMBA, unit);
160:
161: /* record transfer rate (these are guesstimates secs/word) */
162: switch (hp_type[unit] = hpaddr->hpdt) {
163: case RM: mspw = .0000019728; break;
164: case RM5: mspw = .0000020345; break;
165: case RP: mspw = .0000029592; break;
166: }
167: if (DK_N + unit <= DK_NMAX)
168: dk_mspw[DK_N+unit] = mspw;
169: }
170: switch (hp_type[unit]) {
171:
172: case RM:
173: sizes = rm_sizes;
174: nspc = NRMSECT*NRMTRAC;
175: break;
176: case RM5:
177: sizes = rm5_sizes;
178: nspc = NRMSECT*NTRAC;
179: break;
180: case RP:
181: sizes = hp_sizes;
182: nspc = NSECT*NTRAC;
183: break;
184: default:
185: printf("hp: unknown device type 0%o\n", hp_type[unit]);
186: u.u_error = ENXIO;
187: unit = NHP+1; /* force error */
188: }
189: if (unit >= NHP ||
190: bp->b_blkno < 0 ||
191: (bn = dkblock(bp))+sz > sizes[xunit&07].nblocks) {
192: bp->b_flags |= B_ERROR;
193: iodone(bp);
194: return;
195: }
196: bp->b_cylin = bn/nspc + sizes[xunit&07].cyloff;
197: dp = &hputab[unit];
198: (void) spl5();
199: disksort(dp, bp);
200: if (dp->b_active == 0) {
201: hpustart(unit);
202: if(hptab.b_active == 0)
203: hpstart();
204: }
205: (void) spl0();
206: }
207:
208: hpustart(unit)
209: register unit;
210: {
211: register struct buf *bp, *dp;
212: register struct device *hpaddr;
213: daddr_t bn;
214: int sn, cn, csn;
215:
216: ((struct mba_regs *)HPMBA)->mba_cr |= MBAIE;
217: hpaddr = mbadev(HPMBA, 0);
218: hpaddr->hpas = 1<<unit;
219:
220: if(unit >= NHP)
221: return;
222: if (unit+DK_N <= DK_NMAX)
223: dk_busy &= ~(1<<(unit+DK_N));
224: dp = &hputab[unit];
225: if((bp=dp->b_actf) == NULL)
226: return;
227: hpaddr = mbadev(HPMBA, unit);
228: if((hpaddr->hpds & VV) == 0) {
229: hpaddr->hpcs1 = PRESET|GO;
230: hpaddr->hpof = FMT22;
231: }
232: if(dp->b_active)
233: goto done;
234: dp->b_active++;
235: if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL))
236: goto done;
237:
238: bn = dkblock(bp);
239: cn = bp->b_cylin;
240: switch (hp_type[unit]) {
241:
242: case RM:
243: sn = bn%(NRMSECT*NRMTRAC);
244: sn = (sn+NRMSECT-hpSDIST)%NRMSECT;
245: break;
246: case RM5:
247: sn = bn%(NRMSECT*NTRAC);
248: sn = (sn+NRMSECT-hpSDIST)%NRMSECT;
249: break;
250: case RP:
251: sn = bn%(NSECT*NTRAC);
252: sn = (sn+NSECT-hpSDIST)%NSECT;
253: break;
254: default:
255: panic("hpustart");
256: }
257:
258: if(cn - (hpaddr->hpdc & 0xffff))
259: goto search;
260: else if (hpseek)
261: goto done;
262: csn = ((hpaddr->hpla & 0xffff)>>6) - sn + 1;
263: if(csn < 0)
264: csn += NSECT;
265: if(csn > NSECT-hpRDIST)
266: goto done;
267:
268: search:
269: hpaddr->hpdc = cn;
270: if (hpseek)
271: hpaddr->hpcs1 = SEEK|GO;
272: else {
273: hpaddr->hpda = sn;
274: hpaddr->hpcs1 = SEARCH|GO;
275: }
276: unit += DK_N;
277: if (unit <= DK_NMAX) {
278: dk_busy |= 1<<unit;
279: dk_seek[unit]++;
280: }
281: return;
282:
283: done:
284: dp->b_forw = NULL;
285: if(hptab.b_actf == NULL)
286: hptab.b_actf = dp;
287: else
288: hptab.b_actl->b_forw = dp;
289: hptab.b_actl = dp;
290: }
291:
292: hpstart()
293: {
294: register struct buf *bp, *dp;
295: register unit;
296: register struct device *hpaddr;
297: daddr_t bn;
298: int dn, sn, tn, cn, nspc, ns;
299:
300: loop:
301: if ((dp = hptab.b_actf) == NULL)
302: return;
303: if ((bp = dp->b_actf) == NULL) {
304: hptab.b_actf = dp->b_forw;
305: goto loop;
306: }
307: hptab.b_active++;
308: unit = minor(bp->b_dev) & 077;
309: dn = dkunit(bp);
310: bn = dkblock(bp);
311: switch (hp_type[dn]) {
312: case RM:
313: nspc = NRMSECT*NRMTRAC;
314: ns = NRMSECT;
315: cn = rm_sizes[unit&07].cyloff;
316: break;
317: case RM5:
318: nspc = NRMSECT*NTRAC;
319: ns = NRMSECT;
320: cn = rm5_sizes[unit&07].cyloff;
321: break;
322: case RP:
323: nspc = NSECT*NTRAC;
324: ns = NSECT;
325: cn = hp_sizes[unit&07].cyloff;
326: break;
327: default:
328: panic("hpstart");
329: }
330: cn += bn/nspc;
331: sn = bn%nspc;
332: tn = sn/ns;
333: sn = sn%ns;
334:
335: hpaddr = mbadev(HPMBA, dn);
336: if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) {
337: hptab.b_active = 0;
338: hptab.b_errcnt = 0;
339: dp->b_actf = bp->av_forw;
340: bp->b_flags |= B_ERROR;
341: iodone(bp);
342: goto loop;
343: }
344: if(hptab.b_errcnt >= 16 && (bp->b_flags&B_WRITE) == 0) {
345: hpaddr->hpof = hp_offset[hptab.b_errcnt & 017] | FMT22;
346: HPMBA->mba_cr &= ~MBAIE;
347: hpaddr->hpcs1 = OFFSET|GO;
348: while(hpaddr->hpds & PIP)
349: ;
350: HPMBA->mba_cr |= MBAIE;
351: }
352: hpaddr->hpdc = cn;
353: hpaddr->hpda = (tn << 8) + sn;
354: mbastart(bp, (int *)hpaddr);
355:
356: unit = dn+DK_N;
357: if (unit <= DK_NMAX) {
358: dk_busy |= 1<<unit;
359: dk_xfer[unit]++;
360: dk_wds[unit] += bp->b_bcount>>6;
361: }
362: }
363:
364: hpintr(mbastat, as)
365: {
366: register struct buf *bp, *dp;
367: register unit;
368: register struct device *hpaddr;
369:
370: if(hptab.b_active) {
371: dp = hptab.b_actf;
372: bp = dp->b_actf;
373: unit = dkunit(bp);
374: if (DK_N+unit <= DK_NMAX)
375: dk_busy &= ~(1<<(DK_N+unit));
376: hpaddr = mbadev(HPMBA, unit);
377: if (hpaddr->hpds & ERR || mbastat & MBAEBITS) {
378: while((hpaddr->hpds & DRY) == 0)
379: ;
380: if(++hptab.b_errcnt > 28 || hpaddr->hper1&WLE)
381: bp->b_flags |= B_ERROR;
382: else
383: hptab.b_active = 0;
384: if(hptab.b_errcnt > 27)
385: deverror(bp, mbastat, hpaddr->hper1);
386: if ((hpaddr->hper1&0xffff) == DCK) {
387: if (hpecc(hpaddr, bp))
388: return;
389: }
390: hpaddr->hpcs1 = DCLR|GO;
391: if((hptab.b_errcnt&07) == 4) {
392: HPMBA->mba_cr &= ~MBAIE;
393: hpaddr->hpcs1 = RECAL|GO;
394: while(hpaddr->hpds & PIP)
395: ;
396: HPMBA->mba_cr |= MBAIE;
397: }
398: }
399: if(hptab.b_active) {
400: if(hptab.b_errcnt) {
401: HPMBA->mba_cr &= ~MBAIE;
402: hpaddr->hpcs1 = RTC|GO;
403: while(hpaddr->hpds & PIP)
404: ;
405: HPMBA->mba_cr |= MBAIE;
406: }
407: hptab.b_active = 0;
408: hptab.b_errcnt = 0;
409: hptab.b_actf = dp->b_forw;
410: dp->b_active = 0;
411: dp->b_errcnt = 0;
412: dp->b_actf = bp->av_forw;
413: bp->b_resid = -HPMBA->mba_bcr & 0xffff;
414: iodone(bp);
415: if(dp->b_actf)
416: hpustart(unit);
417: }
418: as &= ~(1<<unit);
419: } else {
420: if(as == 0)
421: HPMBA->mba_cr |= MBAIE;
422: }
423: for(unit=0; unit<NHP; unit++)
424: if(as & (1<<unit))
425: hpustart(unit);
426: hpstart();
427: }
428:
429: hpread(dev)
430: {
431:
432: physio(hpstrategy, &rhpbuf, dev, B_READ, minphys);
433: }
434:
435: hpwrite(dev)
436: {
437:
438: physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys);
439: }
440:
441: hpecc(rp, bp)
442: register struct device *rp;
443: register struct buf *bp;
444: {
445: struct mba_regs *mbp = HPMBA;
446: register int i;
447: caddr_t addr;
448: int reg, bit, byte, npf, mask, o;
449: int dn, bn, cn, tn, sn, ns, nt;
450: extern char buffers[NBUF][BSIZE];
451: struct pte mpte;
452: int bcr;
453:
454: /*
455: * Npf is the number of sectors transferred before the sector
456: * containing the ECC error, and reg is the MBA register
457: * mapping (the first part of)the transfer.
458: * O is offset within a memory page of the first byte transferred.
459: */
460: bcr = mbp->mba_bcr & 0xffff;
461: if (bcr)
462: bcr |= 0xffff0000; /* sxt */
463: npf = btop(bcr + bp->b_bcount) - 1;
464: reg = npf;
465: o = (int)bp->b_un.b_addr & PGOFSET;
466: printf("%D ", bp->b_blkno + npf);
467: prdev("ECC", bp->b_dev);
468: mask = rp->hpec2&0xffff;
469: if (mask == 0) {
470: rp->hpof = FMT22;
471: return (0);
472: }
473:
474: /*
475: * Compute the byte and bit position of the error.
476: * The variable i is the byte offset in the transfer,
477: * the variable byte is the offset from a page boundary
478: * in main memory.
479: */
480: i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */
481: bit = i&07;
482: i = (i&~07)>>3;
483: byte = i + o;
484: /*
485: * Correct while possible bits remain of mask. Since mask
486: * contains 11 bits, we continue while the bit offset is > -11.
487: * Also watch out for end of this block and the end of the whole
488: * transfer.
489: */
490: while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
491: mpte = mbp->mba_map[reg+btop(byte)];
492: addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
493: putmemc(addr, getmemc(addr)^(mask<<bit));
494: byte++;
495: i++;
496: bit -= 8;
497: }
498: hptab.b_active++; /* Either complete or continuing */
499: if (bcr == 0)
500: return (0);
501: /*
502: * Have to continue the transfer... clear the drive,
503: * and compute the position where the transfer is to continue.
504: * We have completed npf+1 sectores of the transfer already;
505: * restart at offset o of next sector (i.e. in MBA register reg+1).
506: */
507: rp->hpcs1 = DCLR|GO;
508: dn = dkunit(bp);
509: bn = dkblock(bp);
510: switch (hp_type[dn]) {
511:
512: case RM:
513: ns = NRMSECT; nt = NRMTRAC; break;
514: case RM5:
515: ns = NRMSECT; nt = NTRAC; break;
516: case RP:
517: ns = NSECT; nt = NTRAC; break;
518: default:
519: panic("hpecc");
520: }
521: cn = bp->b_cylin;
522: sn = bn%(ns*nt) + npf + 1;
523: tn = sn/ns;
524: sn %= ns;
525: cn += tn/nt;
526: tn %= nt;
527: rp->hpdc = cn;
528: rp->hpda = (tn<<8) + sn;
529: mbp->mba_sr = -1;
530: mbp->mba_var = (int)ptob(reg+1) + o;
531: rp->hpcs1 = RCOM|GO;
532: return (1);
533: }
534: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.