|
|
1.1 root 1: /* up.c 3.28 10/21/80 */
2:
3: #include "../conf/up.h"
4: /*
5: * UNIBUS disk driver with overlapped seeks and ECC recovery.
6: *
7: * This driver works marginally on an Emulex SC-11B controller with rev
8: * level J microcode, defining:
9: * int olducode = 1;
10: * to force CPU stalling delays.
11: *
12: * It has worked with no delays and no problems on a prototype
13: * SC-21 controller. Emulex intends to upgrade all SC-11s on VAXes to SC-21s.
14: * You should get a SC-21 to replace any SC-11 on a VAX.
15: *
16: * SC-11B Controller switch settings:
17: * SW1-1 5/19 surfaces (off, 19 surfaces on Ampex 9300)
18: * SW1-2 chksum enable (off, checksum disabled)
19: * SW1-3 volume select (off, 815 cylinders)
20: * SW1-4 sector select (on, 32 sectors)
21: * SW1-5 unused (off)
22: * SW1-6 port select (on, single port)
23: * SW1-7 npr delay (off, disable)
24: * SW1-8 ecc test mode (off, disable)
25: * and top mounted switches:
26: * SW2-1 extend opcodes (off=open, disable)
27: * SW2-2 extend diag (off=open, disable)
28: * SW2-3 4 wd dma burst (on=closed, enable)
29: * SW2-4 unused (off=open)
30: */
31:
32: #include "../h/param.h"
33: #include "../h/systm.h"
34: #include "../h/dk.h"
35: #include "../h/buf.h"
36: #include "../h/conf.h"
37: #include "../h/dir.h"
38: #include "../h/user.h"
39: #include "../h/map.h"
40: #include "../h/pte.h"
41: #include "../h/mba.h"
42: #include "../h/mtpr.h"
43: #include "../h/uba.h"
44: #include "../h/vm.h"
45:
46: #define ushort unsigned short
47:
48: struct device
49: {
50: ushort upcs1; /* control and status register 1 */
51: short upwc; /* word count register */
52: ushort upba; /* UNIBUS address register */
53: ushort upda; /* desired address register */
54: ushort upcs2; /* control and status register 2 */
55: ushort upds; /* drive Status */
56: ushort uper1; /* error register 1 */
57: ushort upas; /* attention summary */
58: ushort upla; /* look ahead */
59: ushort updb; /* data buffer */
60: ushort upmr; /* maintenance */
61: ushort updt; /* drive type */
62: ushort upsn; /* serial number */
63: ushort upof; /* offset register */
64: ushort updc; /* desired cylinder address register */
65: ushort upcc; /* current cylinder */
66: ushort uper2; /* error register 2 */
67: ushort uper3; /* error register 3 */
68: ushort upec1; /* burst error bit position */
69: ushort upec2; /* burst error bit pattern */
70: };
71:
72: /*
73: * Software extension to the upas register, so we can
74: * postpone starting SEARCH commands until the controller
75: * is not transferring.
76: */
77: int upsoftas;
78:
79: /*
80: * If upseek then we don't issue SEARCH commands but rather just
81: * settle for a SEEK to the correct cylinder.
82: */
83: int upseek;
84:
85: #define NSECT 32
86: #define NTRAC 19
87:
88: /*
89: * Constants controlling on-cylinder SEARCH usage.
90: *
91: * upSDIST/2 msec time needed to start transfer
92: * upRDIST/2 msec tolerable rotational latency when on-cylinder
93: *
94: * If we are no closer than upSDIST sectors and no further than upSDIST+upRDIST
95: * and in the driver then we take it as it is. Otherwise we do a SEARCH
96: * requesting an interrupt upSDIST sectors in advance.
97: */
98: #define _upSDIST 2 /* 1.0 msec */
99: #define _upRDIST 4 /* 2.0 msec */
100:
101: int upSDIST = _upSDIST;
102: int upRDIST = _upRDIST;
103:
104: /*
105: * To fill a 300M drive:
106: * A is designed to be used as a root.
107: * B is suitable for a swap area.
108: * H is the primary storage area.
109: * On systems with RP06'es, we normally use only 291346 blocks of the H
110: * area, and use DEF or G to cover the rest of the drive. The C system
111: * covers the whole drive and can be used for pack-pack copying.
112: */
113: struct size
114: {
115: daddr_t nblocks;
116: int cyloff;
117: } up_sizes[8] = {
118: 15884, 0, /* A=cyl 0 thru 26 */
119: 33440, 27, /* B=cyl 27 thru 81 */
120: 495520, 0, /* C=cyl 0 thru 814 */
121: 15884, 562, /* D=cyl 562 thru 588 */
122: 55936, 589, /* E=cyl 589 thru 680 */
123: 81472, 681, /* F=cyl 681 thru 814 */
124: 153824, 562, /* G=cyl 562 thru 814 */
125: 445664, 82, /* H=cyl 82 thru 814 */
126: /* Later, and more safely for H area...
127: 291346, 82, /* H=cyl 82 thru 561 */
128: };
129:
130: /*
131: * The following defines are used in offset positioning
132: * when trying to recover disk errors, with the constants being
133: * +/- microinches. Note that header compare inhibit (HCI) is not
134: * tried (this makes sense only during read, in any case.)
135: *
136: * NOT ALL OF THESE ARE IMPLEMENTED ON 9300!?!
137: */
138: #define P400 020
139: #define M400 0220
140: #define P800 040
141: #define M800 0240
142: #define P1200 060
143: #define M1200 0260
144: #define HCI 020000
145:
146: int up_offset[16] =
147: {
148: P400, M400, P400, M400,
149: P800, M800, P800, M800,
150: P1200, M1200, P1200, M1200,
151: 0, 0, 0, 0,
152: };
153:
154: /*
155: * Each drive has a table uputab[i]. On this table are sorted the
156: * pending requests implementing an elevator algorithm (see dsort.c.)
157: * In the upustart() routine, each drive is independently advanced
158: * until it is on the desired cylinder for the next transfer and near
159: * the desired sector. The drive is then chained onto the uptab
160: * table, and the transfer is initiated by the upstart() routine.
161: * When the transfer is completed the driver reinvokes the upustart()
162: * routine to set up the next transfer.
163: */
164: struct buf uptab;
165: struct buf uputab[NUP];
166:
167: struct buf rupbuf; /* Buffer for raw i/o */
168:
169: /* Drive commands, placed in upcs1 */
170: #define GO 01 /* Go bit, set in all commands */
171: #define PRESET 020 /* Preset drive at init or after errors */
172: #define OFFSET 014 /* Offset heads to try to recover error */
173: #define RTC 016 /* Return to center-line after OFFSET */
174: #define SEARCH 030 /* Search for cylinder+sector */
175: #define SEEK 04 /* Seek to cylinder */
176: #define RECAL 06 /* Recalibrate, needed after seek error */
177: #define DCLR 010 /* Drive clear, after error */
178: #define WCOM 060 /* Write */
179: #define RCOM 070 /* Read */
180:
181: /* Other bits of upcs1 */
182: #define IE 0100 /* Controller wide interrupt enable */
183: #define TRE 040000 /* Transfer error */
184: #define RDY 0200 /* Transfer terminated */
185:
186: /* Drive status bits of upds */
187: #define PIP 020000 /* Positioning in progress */
188: #define ERR 040000 /* Error has occurred, DCLR necessary */
189: #define VV 0100 /* Volume is valid, set by PRESET */
190: #define DPR 0400 /* Drive has been preset */
191: #define MOL 010000 /* Drive is online, heads loaded, etc */
192: #define DRY 0200 /* Drive ready */
193:
194: /* Bits of upcs2 */
195: #define CLR 040 /* Controller clear */
196: /* Bits of uper1 */
197: #define DCK 0100000 /* Ecc error occurred */
198: #define ECH 0100 /* Ecc error was unrecoverable */
199: #define WLE 04000 /* Attempt to write read-only drive */
200:
201: /* Bits of upof; the offset bits above are also in this register */
202: #define FMT22 010000 /* 16 bits/word, must be always set */
203:
204: #define b_cylin b_resid
205:
206: int up_ubinfo; /* Information about UBA usage saved here */
207: /*
208: * The EMULEX controller balks if accessed quickly after
209: * certain operations. With rev J delays seem to be needed only
210: * when selecting a new unit, and in drive initialization type
211: * like PRESET and DCLR. The following variables control the delay
212: * DELAY(n) is approximately n usec.
213: */
214: int olducode = 1;
215: int idelay = 500; /* Delay after PRESET or DCLR */
216: int osdelay = 150; /* Old delay after selecting drive in upcs2 */
217: int ordelay = 100; /* Old delay after SEARCH */
218: int oasdel = 100; /* Old delay after clearing bit in upas */
219: int nsdelay = 25;
220:
221: #define DELAY(N) { register int d; d = N; while (--d > 0); }
222:
223: int nwaitcs2; /* How many sdelay loops ? */
224: int neasycs2; /* How many sdelay loops not needed ? */
225:
226: int up_wticks; /* Ticks waiting for interrupt */
227: int upwstart; /* Have started guardian */
228: int upwatch();
229:
230: #ifdef INTRLVE
231: daddr_t dkblock();
232: #endif
233:
234: /*
235: * Queue an i/o request for a drive, checking first that it is in range.
236: *
237: * A unit start is issued if the drive is inactive, causing
238: * a SEARCH for the correct cylinder/sector. If the drive is
239: * already nearly on the money and the controller is not transferring
240: * we kick it to start the transfer.
241: */
242: upstrategy(bp)
243: register struct buf *bp;
244: {
245: register struct buf *dp;
246: register unit, xunit;
247: long sz, bn;
248:
249: if (upwstart == 0) {
250: timeout((caddr_t)upwatch, 0, HZ);
251: upwstart++;
252: }
253: xunit = minor(bp->b_dev) & 077;
254: sz = bp->b_bcount;
255: sz = (sz+511) >> 9; /* transfer size in 512 byte sectors */
256: unit = dkunit(bp);
257: if (unit >= NUP ||
258: bp->b_blkno < 0 ||
259: (bn = dkblock(bp))+sz > up_sizes[xunit&07].nblocks) {
260: bp->b_flags |= B_ERROR;
261: iodone(bp);
262: return;
263: }
264: if (DK_N+unit <= DK_NMAX)
265: dk_mspw[DK_N+unit] = .0000020345;
266: bp->b_cylin = bn/(NSECT*NTRAC) + up_sizes[xunit&07].cyloff;
267: dp = &uputab[unit];
268: (void) spl5();
269: disksort(dp, bp);
270: if (dp->b_active == 0) {
271: (void) upustart(unit);
272: if (uptab.b_actf && uptab.b_active == 0)
273: (void) upstart();
274: }
275: (void) spl0();
276: }
277:
278: /*
279: * Start activity on specified drive; called when drive is inactive
280: * and new transfer request arrives and also when upas indicates that
281: * a SEARCH command is complete.
282: */
283: upustart(unit)
284: register unit;
285: {
286: register struct buf *bp, *dp;
287: register struct device *upaddr = UPADDR;
288: daddr_t bn;
289: int sn, cn, csn;
290: int didie = 0;
291:
292: /*
293: * Other drivers tend to say something like
294: * upaddr->upcs1 = IE;
295: * upaddr->upas = 1<<unit;
296: * here, but the SC-11B will cancel a command which
297: * happens to be sitting in the cs1 if you clear the go
298: * bit by storing there (so the first is not safe),
299: * and it also does not like being bothered with operations
300: * such as clearing upas when a transfer is active (as
301: * it may well be.)
302: *
303: * Thus we keep careful track of when we re-enable IE
304: * after an interrupt and do it only if we didn't issue
305: * a command which re-enabled it as a matter of course.
306: * We clear bits in upas in the interrupt routine, when
307: * no transfers are active.
308: */
309: if (unit >= NUP)
310: goto out;
311: if (unit+DK_N <= DK_NMAX)
312: dk_busy &= ~(1<<(unit+DK_N));
313: dp = &uputab[unit];
314: if ((bp = dp->b_actf) == NULL)
315: goto out;
316: /*
317: * The SC-11B doesn't start SEARCH commands when transfers are
318: * in progress. In fact, it tends to get confused when given
319: * SEARCH'es during transfers, generating interrupts with neither
320: * RDY nor a bit in the upas register. Thus we defer
321: * until an interrupt when a transfer is pending.
322: */
323: if (uptab.b_active) {
324: upsoftas |= 1<<unit;
325: return (0);
326: }
327: if (dp->b_active)
328: goto done;
329: dp->b_active = 1;
330: if ((upaddr->upcs2 & 07) != unit) {
331: upaddr->upcs2 = unit;
332: DELAY(olducode ? osdelay : nsdelay);
333: nwaitcs2++;
334: } else
335: neasycs2++;
336: /*
337: * If we have changed packs or just initialized,
338: * then the volume will not be valid; if so, clear
339: * the drive, preset it and put in 16bit/word mode.
340: */
341: if ((upaddr->upds & VV) == 0) {
342: upaddr->upcs1 = IE|DCLR|GO;
343: DELAY(idelay);
344: upaddr->upcs1 = IE|PRESET|GO;
345: DELAY(idelay);
346: upaddr->upof = FMT22;
347: didie = 1;
348: }
349: if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL))
350: goto done;
351: /*
352: * Do enough of the disk address decoding to determine
353: * which cylinder and sector the request is on.
354: * If we are on the correct cylinder and the desired sector
355: * lies between upSDIST and upSDIST+upRDIST sectors ahead of us, then
356: * we don't bother to SEARCH but just begin the transfer asap.
357: * Otherwise ask for a interrupt upSDIST sectors ahead.
358: */
359: bn = dkblock(bp);
360: cn = bp->b_cylin;
361: sn = bn%(NSECT*NTRAC);
362: sn = (sn+NSECT-upSDIST)%NSECT;
363:
364: if (cn - upaddr->updc)
365: goto search; /* Not on-cylinder */
366: else if (upseek)
367: goto done; /* Ok just to be on-cylinder */
368: csn = (upaddr->upla>>6) - sn - 1;
369: if (csn < 0)
370: csn += NSECT;
371: if (csn > NSECT-upRDIST)
372: goto done;
373:
374: search:
375: upaddr->updc = cn;
376: if (upseek)
377: upaddr->upcs1 = IE|SEEK|GO;
378: else {
379: upaddr->upda = sn;
380: upaddr->upcs1 = IE|SEARCH|GO;
381: }
382: didie = 1;
383: /*
384: * Mark this unit busy.
385: */
386: unit += DK_N;
387: if (unit <= DK_NMAX) {
388: dk_busy |= 1<<unit;
389: dk_seek[unit]++;
390: }
391: if (olducode)
392: DELAY(ordelay);
393: goto out;
394:
395: done:
396: /*
397: * This unit is ready to go so
398: * link it onto the chain of ready disks.
399: */
400: dp->b_forw = NULL;
401: if (uptab.b_actf == NULL)
402: uptab.b_actf = dp;
403: else
404: uptab.b_actl->b_forw = dp;
405: uptab.b_actl = dp;
406:
407: out:
408: return (didie);
409: }
410:
411: /*
412: * Start a transfer; call from top level at spl5() or on interrupt.
413: */
414: upstart()
415: {
416: register struct buf *bp, *dp;
417: register unit;
418: register struct device *upaddr;
419: daddr_t bn;
420: int dn, sn, tn, cn, cmd;
421:
422: loop:
423: /*
424: * Pick a drive off the queue of ready drives, and
425: * perform the first transfer on its queue.
426: *
427: * Looping here is completely for the sake of drives which
428: * are not present and on-line, for which we completely clear the
429: * request queue.
430: */
431: if ((dp = uptab.b_actf) == NULL)
432: return (0);
433: if ((bp = dp->b_actf) == NULL) {
434: uptab.b_actf = dp->b_forw;
435: goto loop;
436: }
437: /*
438: * Mark the controller busy, and multi-part disk address.
439: * Select the unit on which the i/o is to take place.
440: */
441: uptab.b_active++;
442: unit = minor(bp->b_dev) & 077;
443: dn = dkunit(bp);
444: bn = dkblock(bp);
445: cn = up_sizes[unit&07].cyloff;
446: cn += bn/(NSECT*NTRAC);
447: sn = bn%(NSECT*NTRAC);
448: tn = sn/NSECT;
449: sn %= NSECT;
450: upaddr = UPADDR;
451: if ((upaddr->upcs2 & 07) != dn) {
452: upaddr->upcs2 = dn;
453: /* DELAY(sdelay); Provided by ubasetup() */
454: nwaitcs2++;
455: } else
456: neasycs2++;
457: up_ubinfo = ubasetup(bp, 1); /* Providing delay */
458: /*
459: * If drive is not present and on-line, then
460: * get rid of this with an error and loop to get
461: * rid of the rest of its queued requests.
462: * (Then on to any other ready drives.)
463: */
464: if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) {
465: printf("!DPR || !MOL, unit %d, ds %o", dn, upaddr->upds);
466: if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) {
467: printf("-- hard\n");
468: uptab.b_active = 0;
469: uptab.b_errcnt = 0;
470: dp->b_actf = bp->av_forw;
471: dp->b_active = 0;
472: bp->b_flags |= B_ERROR;
473: iodone(bp);
474: /* A funny place to do this ... */
475: ubafree(up_ubinfo), up_ubinfo = 0;
476: goto loop;
477: }
478: printf("-- came back\n");
479: }
480: /*
481: * If this is a retry, then with the 16'th retry we
482: * begin to try offsetting the heads to recover the data.
483: */
484: if (uptab.b_errcnt >= 16 && (bp->b_flags&B_WRITE) == 0) {
485: upaddr->upof = up_offset[uptab.b_errcnt & 017] | FMT22;
486: upaddr->upcs1 = IE|OFFSET|GO;
487: DELAY(idelay);
488: while (upaddr->upds & PIP)
489: DELAY(25);
490: }
491: /*
492: * Now set up the transfer, retrieving the high
493: * 2 bits of the UNIBUS address from the information
494: * returned by ubasetup() for the cs1 register bits 8 and 9.
495: */
496: upaddr->updc = cn;
497: upaddr->upda = (tn << 8) + sn;
498: upaddr->upba = up_ubinfo;
499: upaddr->upwc = -bp->b_bcount / sizeof (short);
500: cmd = (up_ubinfo >> 8) & 0x300;
501: if (bp->b_flags & B_READ)
502: cmd |= IE|RCOM|GO;
503: else
504: cmd |= IE|WCOM|GO;
505: upaddr->upcs1 = cmd;
506: /*
507: * This is a controller busy situation.
508: * Record in dk slot NUP+DK_N (after last drive)
509: * unless there aren't that many slots reserved for
510: * us in which case we record this as a drive busy
511: * (if there is room for that).
512: */
513: unit = dn+DK_N;
514: if (unit <= DK_NMAX) {
515: dk_busy |= 1<<unit;
516: dk_xfer[unit]++;
517: dk_wds[unit] += bp->b_bcount>>6;
518: }
519: return (1);
520: }
521:
522: /*
523: * Handle a device interrupt.
524: *
525: * If the transferring drive needs attention, service it
526: * retrying on error or beginning next transfer.
527: * Service all other ready drives, calling ustart to transfer
528: * their blocks to the ready queue in uptab, and then restart
529: * the controller if there is anything to do.
530: */
531: upintr()
532: {
533: register struct buf *bp, *dp;
534: register unit;
535: register struct device *upaddr = UPADDR;
536: int as = upaddr->upas & 0377;
537: int oupsoftas;
538: int needie = 1;
539:
540: (void) spl6();
541: up_wticks = 0;
542: if (uptab.b_active) {
543: /*
544: * The drive is transferring, thus the hardware
545: * (say the designers) will only interrupt when the transfer
546: * completes; check for it anyways.
547: */
548: if ((upaddr->upcs1 & RDY) == 0) {
549: printf("!RDY: cs1 %o, ds %o, wc %d\n", upaddr->upcs1,
550: upaddr->upds, upaddr->upwc);
551: printf("as=%d act %d %d %d\n", as, uptab.b_active,
552: uputab[0].b_active, uputab[1].b_active);
553: }
554: /*
555: * Mark drive not busy, and check for an
556: * error condition which may have resulted from the transfer.
557: */
558: dp = uptab.b_actf;
559: bp = dp->b_actf;
560: unit = dkunit(bp);
561: if (DK_N+unit <= DK_NMAX)
562: dk_busy &= ~(1<<(DK_N+unit));
563: if ((upaddr->upcs2 & 07) != unit) {
564: upaddr->upcs2 = unit;
565: DELAY(olducode ? osdelay : nsdelay);
566: nwaitcs2++;
567: } else
568: neasycs2++;
569: if ((upaddr->upds&ERR) || (upaddr->upcs1&TRE)) {
570: /*
571: * An error occurred, indeed. Select this unit
572: * to get at the drive status (a SEARCH may have
573: * intervened to change the selected unit), and
574: * wait for the command which caused the interrupt
575: * to complete (DRY).
576: */
577: while ((upaddr->upds & DRY) == 0)
578: DELAY(25);
579: /*
580: * After 28 retries (16 w/o servo offsets, and then
581: * 12 with servo offsets), or if we encountered
582: * an error because the drive is write-protected,
583: * give up. Print an error message on the last 2
584: * retries before a hard failure.
585: */
586: if (++uptab.b_errcnt > 28 || upaddr->uper1&WLE)
587: bp->b_flags |= B_ERROR;
588: else
589: uptab.b_active = 0; /* To force retry */
590: if (uptab.b_errcnt > 27)
591: deverror(bp, upaddr->upcs2, upaddr->uper1);
592: /*
593: * If this was a correctible ECC error, let upecc
594: * do the dirty work to correct it. If upecc
595: * starts another READ for the rest of the data
596: * then it returns 1 (having set uptab.b_active).
597: * Otherwise we are done and fall through to
598: * finish up.
599: */
600: if ((upaddr->uper1&(DCK|ECH))==DCK && upecc(upaddr, bp))
601: return;
602: /*
603: * Clear the drive and, every 4 retries, recalibrate
604: * to hopefully help clear up seek positioning problems.
605: */
606: upaddr->upcs1 = TRE|IE|DCLR|GO;
607: DELAY(idelay);
608: needie = 0;
609: if ((uptab.b_errcnt&07) == 4) {
610: upaddr->upcs1 = RECAL|GO|IE;
611: DELAY(idelay);
612: while(upaddr->upds & PIP)
613: DELAY(25);
614: }
615: }
616: /*
617: * If we are still noted as active, then no
618: * (further) retries are necessary.
619: *
620: * Make sure the correct unit is selected,
621: * return it to centerline if necessary, and mark
622: * this i/o complete, starting the next transfer
623: * on this drive with the upustart routine (if any).
624: */
625: if (uptab.b_active) {
626: if (uptab.b_errcnt >= 16) {
627: upaddr->upcs1 = RTC|GO|IE;
628: DELAY(idelay);
629: while (upaddr->upds & PIP)
630: DELAY(25);
631: needie = 0;
632: }
633: uptab.b_active = 0;
634: uptab.b_errcnt = 0;
635: uptab.b_actf = dp->b_forw;
636: dp->b_active = 0;
637: dp->b_errcnt = 0;
638: dp->b_actf = bp->av_forw;
639: bp->b_resid = (-upaddr->upwc * sizeof(short));
640: if (bp->b_resid)
641: printf("resid %d ds %o er? %o %o %o\n",
642: bp->b_resid, upaddr->upds,
643: upaddr->uper1, upaddr->uper2, upaddr->uper3);
644: iodone(bp);
645: if(dp->b_actf)
646: if (upustart(unit))
647: needie = 0;
648: }
649: as &= ~(1<<unit);
650: upsoftas &= ~(1<<unit);
651: ubafree(up_ubinfo), up_ubinfo = 0;
652: } else {
653: if (upaddr->upcs1 & TRE) {
654: upaddr->upcs1 = TRE;
655: DELAY(idelay);
656: }
657: }
658: /*
659: * If we have a unit with an outstanding SEARCH,
660: * and the hardware indicates the unit requires attention,
661: * the bring the drive to the ready queue.
662: * Finally, if the controller is not transferring
663: * start it if any drives are now ready to transfer.
664: */
665: as |= upsoftas;
666: oupsoftas = upsoftas;
667: upsoftas = 0;
668: for (unit = 0; unit < NUP; unit++)
669: if ((as|oupsoftas) & (1<<unit)) {
670: if (as & (1<<unit)) {
671: upaddr->upas = 1<<unit;
672: if (olducode)
673: DELAY(oasdel);
674: }
675: if (upustart(unit))
676: needie = 0;
677: }
678: if (uptab.b_actf && uptab.b_active == 0)
679: if (upstart())
680: needie = 0;
681: out:
682: if (needie)
683: upaddr->upcs1 = IE;
684: }
685:
686: upread(dev)
687: {
688:
689: physio(upstrategy, &rupbuf, dev, B_READ, minphys);
690: }
691:
692: upwrite(dev)
693: {
694:
695: physio(upstrategy, &rupbuf, dev, B_WRITE, minphys);
696: }
697:
698: /*
699: * Correct an ECC error, and restart the i/o to complete
700: * the transfer if necessary. This is quite complicated because
701: * the transfer may be going to an odd memory address base and/or
702: * across a page boundary.
703: */
704: upecc(up, bp)
705: register struct device *up;
706: register struct buf *bp;
707: {
708: struct uba_regs *ubp = (struct uba_regs *)UBA0;
709: register int i;
710: caddr_t addr;
711: int reg, bit, byte, npf, mask, o, cmd, ubaddr;
712: int bn, cn, tn, sn;
713:
714: /*
715: * Npf is the number of sectors transferred before the sector
716: * containing the ECC error, and reg is the UBA register
717: * mapping (the first part of) the transfer.
718: * O is offset within a memory page of the first byte transferred.
719: */
720: npf = btop((up->upwc * sizeof(short)) + bp->b_bcount) - 1;
721: reg = btop(up_ubinfo&0x3ffff) + npf;
722: o = (int)bp->b_un.b_addr & PGOFSET;
723: printf("%D ", bp->b_blkno+npf);
724: prdev("ECC", bp->b_dev);
725: mask = up->upec2;
726: if (mask == 0) {
727: up->upof = FMT22; /* == RTC ???? */
728: DELAY(idelay);
729: return (0);
730: }
731: /*
732: * Flush the buffered data path, and compute the
733: * byte and bit position of the error. The variable i
734: * is the byte offset in the transfer, the variable byte
735: * is the offset from a page boundary in main memory.
736: */
737: ubp->uba_dpr[(up_ubinfo>>28)&0x0f] |= BNE;
738: i = up->upec1 - 1; /* -1 makes 0 origin */
739: bit = i&07;
740: i = (i&~07)>>3;
741: byte = i + o;
742: /*
743: * Correct while possible bits remain of mask. Since mask
744: * contains 11 bits, we continue while the bit offset is > -11.
745: * Also watch out for end of this block and the end of the whole
746: * transfer.
747: */
748: while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
749: addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
750: (byte & PGOFSET);
751: putmemc(addr, getmemc(addr)^(mask<<bit));
752: byte++;
753: i++;
754: bit -= 8;
755: }
756: uptab.b_active++; /* Either complete or continuing... */
757: if (up->upwc == 0)
758: return (0);
759: /*
760: * Have to continue the transfer... clear the drive,
761: * and compute the position where the transfer is to continue.
762: * We have completed npf+1 sectors of the transfer already;
763: * restart at offset o of next sector (i.e. in UBA register reg+1).
764: */
765: up->upcs1 = TRE|IE|DCLR|GO;
766: DELAY(idelay);
767: bn = dkblock(bp);
768: cn = bp->b_cylin;
769: sn = bn%(NSECT*NTRAC) + npf + 1;
770: tn = sn/NSECT;
771: sn %= NSECT;
772: cn += tn/NTRAC;
773: tn %= NTRAC;
774: up->updc = cn;
775: up->upda = (tn << 8) | sn;
776: ubaddr = (int)ptob(reg+1) + o;
777: up->upba = ubaddr;
778: cmd = (ubaddr >> 8) & 0x300;
779: cmd |= IE|GO|RCOM;
780: up->upcs1 = cmd;
781: return (1);
782: }
783:
784: /*
785: * Reset driver after UBA init.
786: * Cancel software state of all pending transfers
787: * and restart all units and the controller.
788: */
789: upreset()
790: {
791: int unit;
792:
793: printf(" up");
794: uptab.b_active = 0;
795: uptab.b_actf = uptab.b_actl = 0;
796: if (up_ubinfo) {
797: printf("<%d>", (up_ubinfo>>28)&0xf);
798: ubafree(up_ubinfo), up_ubinfo = 0;
799: }
800: UPADDR->upcs2 = CLR; /* clear controller */
801: DELAY(idelay);
802: for (unit = 0; unit < NUP; unit++) {
803: uputab[unit].b_active = 0;
804: (void) upustart(unit);
805: }
806: (void) upstart();
807: }
808:
809: /*
810: * Wake up every second and if an interrupt is pending
811: * but nothing has happened increment a counter.
812: * If nothing happens for 20 seconds, reset the controller
813: * and begin anew.
814: */
815: upwatch()
816: {
817: int i;
818:
819: timeout((caddr_t)upwatch, 0, HZ);
820: if (uptab.b_active == 0) {
821: for (i = 0; i < NUP; i++)
822: if (uputab[i].b_active)
823: goto active;
824: up_wticks = 0; /* idling */
825: return;
826: }
827: active:
828: up_wticks++;
829: if (up_wticks >= 20) {
830: up_wticks = 0;
831: printf("LOST INTERRUPT RESET");
832: upreset();
833: printf("\n");
834: }
835: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.