|
|
1.1 root 1: /* up.c 4.39 81/05/11 */
2:
3: #include "up.h"
4: #if NSC > 0
5: /*
6: * UNIBUS disk driver with overlapped seeks and ECC recovery.
7: *
8: * TODO:
9: * Add bad sector forwarding code
10: * Check that offset recovery code works
11: */
12:
13: #include "../h/param.h"
14: #include "../h/systm.h"
15: #include "../h/cpu.h"
16: #include "../h/nexus.h"
17: #include "../h/dk.h"
18: #include "../h/buf.h"
19: #include "../h/conf.h"
20: #include "../h/dir.h"
21: #include "../h/user.h"
22: #include "../h/map.h"
23: #include "../h/pte.h"
24: #include "../h/mtpr.h"
25: #include "../h/vm.h"
26: #include "../h/ubavar.h"
27: #include "../h/ubareg.h"
28: #include "../h/cmap.h"
29: #include "../h/trace.h"
30:
31: #include "../h/upreg.h"
32:
33: #define NDRIVE 8 /* max drives returned by ATTN bits */
34:
35: struct up_softc {
36: int sc_softas;
37: int sc_ndrive;
38: int sc_wticks;
39: int sc_recal;
40: } up_softc[NSC];
41:
42: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
43: struct size
44: {
45: daddr_t nblocks;
46: int cyloff;
47: } up_sizes[8] = {
48: 15884, 0, /* A=cyl 0 thru 26 */
49: 33440, 27, /* B=cyl 27 thru 81 */
50: 495520, 0, /* C=cyl 0 thru 814 */
51: 15884, 562, /* D=cyl 562 thru 588 */
52: 55936, 589, /* E=cyl 589 thru 680 */
53: #ifndef NOBADSECT
54: 81376, 681, /* F=cyl 681 thru 814 */
55: 153728, 562, /* G=cyl 562 thru 814 */
56: #else
57: 81472, 681,
58: 153824, 562,
59: #endif
60: 291346, 82, /* H=cyl 82 thru 561 */
61: }, fj_sizes[8] = {
62: 10240, 0, /* A=cyl 0 thru 31 */
63: 20480, 32, /* B=cyl 32 thru 95 */
64: 232640, 96, /* C=cyl 96 thru 822 */
65: 0, 0,
66: 0, 0,
67: 0, 0,
68: 0, 0,
69: #ifndef NOBADSECT
70: 0, 0, /* H=cyl 155 thru 822 */
71: #else
72: 0, 0,
73: #endif
74: }, fj3_sizes[8] = {
75: 10240, 0, /* A=cyl 0 thru 19 */
76: 20480, 20, /* B=cyl 20 thru 59 */
77: 246784, 60, /* C=cyl 60 thru 541 */
78: 246784, 542, /* D=cyl 542 thru 1024 */
79: 0, 0,
80: 0, 0,
81: 0, 0,
82: #ifndef NOBADSECT
83: 0, 0, /* H=cyl 155 thru 822 */
84: #else
85: 0, 0,
86: #endif
87: }, cd_sizes[8] = {
88: 10240, 0, /* A=cyl 0 thru 63 */
89: 20480, 64, /* B=cyl 64 thru 191 */
90: 100960, 192, /* C=cyl 192 thru 822 */
91: 0, 0,
92: 0, 0,
93: 0, 0,
94: 0, 0,
95: #ifndef NOBADSECT
96: 100960, 0, /* H=cyl 0 thru 630 */
97: #else
98: 100960, 0,
99: #endif
100: }, fj1_sizes[8] = {
101: 1024, 0, /* cyl 0 through 3 */
102: 0, 0,
103: 0, 0,
104: 0, 0,
105: 0, 0,
106: 0, 0,
107: 0, 0,
108: 0, 0,
109: };
110: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
111:
112: #define _upSDIST 3 /* empirical */
113: #define _upRDIST 4 /* 2.0 msec */
114:
115: int upSDIST = _upSDIST;
116: int upRDIST = _upRDIST;
117:
118: int upprobe(), upslave(), upattach(), updgo(), upintr();
119: struct uba_ctlr *upminfo[NSC];
120: struct uba_device *updinfo[NUP];
121: struct uba_device *upip[NSC][NDRIVE];
122:
123: u_short upstd[] = { 0776700, 0774400, 0776300, 0 };
124: struct uba_driver scdriver =
125: { upprobe, upslave, upattach, updgo, upstd, "up", updinfo, "sc", upminfo };
126: struct buf uputab[NUP];
127:
128: struct upst {
129: short nsect;
130: short ntrak;
131: short nspc;
132: short ncyl;
133: struct size *sizes;
134: } upst[] = {
135: 32, 19, 32*19, 823, up_sizes, /* 9300/cdc */
136: /* 9300 actually has 815 cylinders... */
137: 32, 10, 32*10, 823, fj_sizes, /* fujitsu 160m */
138: 32, 5, 32*5, 631, cd_sizes, /* CDC 76 MB */
139: 32, 8, 32*8, 4, fj1_sizes, /* Fixed part of FJ */
140: 32, 16, 32*16, 1024, fj3_sizes, /* fujitsu 330m */
141: };
142:
143: u_char up_offset[16] = {
144: UPOF_P400, UPOF_M400, UPOF_P400, UPOF_M400,
145: UPOF_P800, UPOF_M800, UPOF_P800, UPOF_M800,
146: UPOF_P1200, UPOF_M1200, UPOF_P1200, UPOF_M1200,
147: 0, 0, 0, 0
148: };
149:
150: struct buf rupbuf[NUP];
151:
152: #define b_cylin b_resid
153:
154: #ifdef INTRLVE
155: daddr_t dkblock();
156: #endif
157:
158: int upwstart, upwatch(); /* Have started guardian */
159: int upseek;
160: int upwaitdry;
161:
162: /*ARGSUSED*/
163: upprobe(reg)
164: caddr_t reg;
165: {
166: register int br, cvec;
167:
168: #ifdef lint
169: br = 0; cvec = br; br = cvec;
170: #endif
171: ((struct updevice *)reg)->upcs1 = UP_IE|UP_RDY;
172: DELAY(10);
173: ((struct updevice *)reg)->upcs1 = 0;
174: return (1);
175: }
176:
177: upslave(ui, reg)
178: struct uba_device *ui;
179: caddr_t reg;
180: {
181: register struct updevice *upaddr = (struct updevice *)reg;
182:
183: upaddr->upcs1 = 0; /* conservative */
184: upaddr->upcs2 = ui->ui_slave;
185: if (upaddr->upcs2&UPCS2_NED) {
186: upaddr->upcs1 = UP_DCLR|UP_GO;
187: return (0);
188: }
189: return (1);
190: }
191:
192: upattach(ui)
193: register struct uba_device *ui;
194: {
195: register struct updevice *upaddr;
196: register maxtrak;
197:
198: if (upwstart == 0) {
199: timeout(upwatch, (caddr_t)0, hz);
200: upwstart++;
201: }
202: if (ui->ui_dk >= 0)
203: dk_mspw[ui->ui_dk] = .0000020345;
204: upip[ui->ui_ctlr][ui->ui_slave] = ui;
205: up_softc[ui->ui_ctlr].sc_ndrive++;
206: upaddr = (struct updevice *)ui->ui_addr;
207: upaddr->upcs1 = 0;
208: upaddr->upcs2 = ui->ui_slave;
209: upaddr->uphr = UPHR_MAXTRAK;
210: maxtrak = upaddr->uphr;
211: if (maxtrak == 9)
212: ui->ui_type = 1; /* fujitsu hack */
213: else if (maxtrak == 15)
214: ui->ui_type = 4; /* fuji 330m hack */
215: else if (maxtrak == 4)
216: ui->ui_type = 2; /* CDC 76MB hack */
217: else if (maxtrak == 19)
218: ui->ui_type = 0; /* CDC 300 MB hack */
219: else if (maxtrak == 7)
220: ui->ui_type = 3; /* Fixed Fujitsu hack */
221: else {
222: printf("%d tracks\n", maxtrak);
223: printf("Can't identify drive %d\n", ui->ui_slave);
224: ui->ui_alive = 0;
225: }
226: if (ui->ui_type==1 && ui->ui_slave>=4)
227: ui->ui_type = 3; /* the real hack */
228: upaddr->upcs2 = UPCS2_CLR;
229: upaddr->uphr = UPHR_MAXCYL;
230: upaddr->uphr = UPHR_MAXSECT;
231: printf("type%d\n", ui->ui_type);
232: }
233:
234: upstrategy(bp)
235: register struct buf *bp;
236: {
237: register struct uba_device *ui;
238: register struct upst *st;
239: register int unit;
240: register struct buf *dp;
241: int xunit = minor(bp->b_dev) & 07;
242: long bn, sz;
243: int s;
244:
245: sz = (bp->b_bcount+511) >> 9;
246: unit = dkunit(bp);
247: if (unit >= NUP)
248: goto bad;
249: ui = updinfo[unit];
250: if (ui == 0 || ui->ui_alive == 0)
251: goto bad;
252: st = &upst[ui->ui_type];
253: if (bp->b_blkno < 0 ||
254: (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
255: goto bad;
256: bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
257: s = spl5();
258: dp = &uputab[ui->ui_unit];
259: disksort(dp, bp);
260: if (dp->b_active == 0) {
261: (void) upustart(ui);
262: bp = &ui->ui_mi->um_tab;
263: if (bp->b_actf && bp->b_active == 0)
264: (void) upstart(ui->ui_mi);
265: }
266: splx(s);
267: return;
268:
269: bad:
270: bp->b_flags |= B_ERROR;
271: iodone(bp);
272: return;
273: }
274:
275: /*
276: * Unit start routine.
277: * Seek the drive to be where the data is
278: * and then generate another interrupt
279: * to actually start the transfer.
280: * If there is only one drive on the controller,
281: * or we are very close to the data, don't
282: * bother with the search. If called after
283: * searching once, don't bother to look where
284: * we are, just queue for transfer (to avoid
285: * positioning forever without transferrring.)
286: */
287: upustart(ui)
288: register struct uba_device *ui;
289: {
290: register struct buf *bp, *dp;
291: register struct uba_ctlr *um;
292: register struct updevice *upaddr;
293: register struct upst *st;
294: daddr_t bn;
295: int sn, csn;
296: /*
297: * The SC21 cancels commands if you just say
298: * cs1 = UP_IE
299: * so we are cautious about handling of cs1.
300: * Also don't bother to clear as bits other than in upintr().
301: */
302: int didie = 0;
303:
304: if (ui == 0)
305: return (0);
306: um = ui->ui_mi;
307: dk_busy &= ~(1<<ui->ui_dk);
308: dp = &uputab[ui->ui_unit];
309: if ((bp = dp->b_actf) == NULL)
310: goto out;
311: /*
312: * If the controller is active, just remember
313: * that this device would like to be positioned...
314: * if we tried to position now we would confuse the SC21.
315: */
316: if (um->um_tab.b_active) {
317: up_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave;
318: return (0);
319: }
320: /*
321: * If we have already positioned this drive,
322: * then just put it on the ready queue.
323: */
324: if (dp->b_active)
325: goto done;
326: dp->b_active = 1;
327: upaddr = (struct updevice *)um->um_addr;
328: upaddr->upcs2 = ui->ui_slave;
329: /*
330: * If drive has just come up,
331: * setup the pack.
332: */
333: if ((upaddr->upds & UPDS_VV) == 0) {
334: /* SHOULD WARN SYSTEM THAT THIS HAPPENED */
335: trace(TR_UBGO, UP_IE|UP_DCLR|UP_GO, 2);
336: upaddr->upcs1 = UP_IE|UP_DCLR|UP_GO;
337: trace(TR_UBGO, UP_IE|UP_PRESET|UP_GO, 3);
338: upaddr->upcs1 = UP_IE|UP_PRESET|UP_GO;
339: upaddr->upof = UPOF_FMT22;
340: didie = 1;
341: }
342: /*
343: * If drive is offline, forget about positioning.
344: */
345: if ((upaddr->upds & (UPDS_DPR|UPDS_MOL)) != (UPDS_DPR|UPDS_MOL))
346: goto done;
347: /*
348: * If there is only one drive,
349: * dont bother searching.
350: */
351: #ifdef NOUPSEEK
352: goto done; /* maybe this will save us from the rwait bug */
353: #endif
354: if (up_softc[um->um_ctlr].sc_ndrive == 1)
355: goto done;
356: /*
357: * Figure out where this transfer is going to
358: * and see if we are close enough to justify not searching.
359: */
360: st = &upst[ui->ui_type];
361: bn = dkblock(bp);
362: sn = bn%st->nspc;
363: sn = (sn + st->nsect - upSDIST) % st->nsect;
364: if (bp->b_cylin - 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 += st->nsect;
371: if (csn > st->nsect - upRDIST)
372: goto done;
373: search:
374: upaddr->updc = bp->b_cylin;
375: /*
376: * Not on cylinder at correct position,
377: * seek/search.
378: */
379: if (upseek) {
380: trace(TR_UBGO, UP_IE|UP_SEEK|UP_GO, dkunit(bp));
381: upaddr->upcs1 = UP_IE|UP_SEEK|UP_GO;
382: }
383: else {
384: upaddr->upda = sn;
385: trace(TR_UBGO, UP_IE|UP_SEARCH|UP_GO, dkunit(bp));
386: upaddr->upcs1 = UP_IE|UP_SEARCH|UP_GO;
387: }
388: didie = 1;
389: /*
390: * Mark unit busy for iostat.
391: */
392: if (ui->ui_dk >= 0) {
393: dk_busy |= 1<<ui->ui_dk;
394: dk_seek[ui->ui_dk]++;
395: }
396: goto out;
397: done:
398: /*
399: * Device is ready to go.
400: * Put it on the ready queue for the controller
401: * (unless its already there.)
402: */
403: if (dp->b_active != 2) {
404: dp->b_forw = NULL;
405: if (um->um_tab.b_actf == NULL)
406: um->um_tab.b_actf = dp;
407: else
408: um->um_tab.b_actl->b_forw = dp;
409: um->um_tab.b_actl = dp;
410: dp->b_active = 2;
411: }
412: out:
413: return (didie);
414: }
415:
416: /*
417: * Start up a transfer on a drive.
418: */
419: upstart(um)
420: register struct uba_ctlr *um;
421: {
422: register struct buf *bp, *dp;
423: register struct uba_device *ui;
424: register struct updevice *upaddr;
425: struct upst *st;
426: daddr_t bn;
427: int dn, sn, tn, cmd, waitdry;
428:
429: loop:
430: /*
431: * Pull a request off the controller queue
432: */
433: if ((dp = um->um_tab.b_actf) == NULL)
434: return (0);
435: if ((bp = dp->b_actf) == NULL) {
436: um->um_tab.b_actf = dp->b_forw;
437: goto loop;
438: }
439: /*
440: * Mark controller busy, and
441: * determine destination of this request.
442: */
443: um->um_tab.b_active++;
444: ui = updinfo[dkunit(bp)];
445: bn = dkblock(bp);
446: dn = ui->ui_slave;
447: st = &upst[ui->ui_type];
448: sn = bn%st->nspc;
449: tn = sn/st->nsect;
450: sn %= st->nsect;
451: upaddr = (struct updevice *)ui->ui_addr;
452: /*
453: * Select drive if not selected already.
454: */
455: if ((upaddr->upcs2&07) != dn)
456: upaddr->upcs2 = dn;
457: /*
458: * Check that it is ready and online
459: */
460: waitdry = 0;
461: while ((upaddr->upds&UPDS_DRY) == 0) {
462: if (++waitdry > 512)
463: break;
464: upwaitdry++;
465: }
466: if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {
467: printf("up%d: not ready", dkunit(bp));
468: if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {
469: printf("\n");
470: um->um_tab.b_active = 0;
471: um->um_tab.b_errcnt = 0;
472: dp->b_actf = bp->av_forw;
473: dp->b_active = 0;
474: bp->b_flags |= B_ERROR;
475: iodone(bp);
476: goto loop;
477: }
478: /*
479: * Oh, well, sometimes this
480: * happens, for reasons unknown.
481: */
482: printf(" (flakey)\n");
483: }
484: /*
485: * Setup for the transfer, and get in the
486: * UNIBUS adaptor queue.
487: */
488: upaddr->updc = bp->b_cylin;
489: upaddr->upda = (tn << 8) + sn;
490: upaddr->upwc = -bp->b_bcount / sizeof (short);
491: if (bp->b_flags & B_READ)
492: cmd = UP_IE|UP_RCOM|UP_GO;
493: else
494: cmd = UP_IE|UP_WCOM|UP_GO;
495: um->um_cmd = cmd;
496: (void) ubago(ui);
497: return (1);
498: }
499:
500: /*
501: * Now all ready to go, stuff the registers.
502: */
503: updgo(um)
504: struct uba_ctlr *um;
505: {
506: register struct updevice *upaddr = (struct updevice *)um->um_addr;
507:
508: trace(TR_UBGO, um->um_cmd, 0);
509: upaddr->upba = um->um_ubinfo;
510: upaddr->upcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);
511: }
512:
513: /*
514: * Handle a disk interrupt.
515: */
516: upintr(sc21)
517: register sc21;
518: {
519: register struct buf *bp, *dp;
520: register struct uba_ctlr *um = upminfo[sc21];
521: register struct uba_device *ui;
522: register struct updevice *upaddr = (struct updevice *)um->um_addr;
523: register unit;
524: struct up_softc *sc = &up_softc[um->um_ctlr];
525: int as = (upaddr->upas & 0377) | sc->sc_softas;
526: int needie = 1, waitdry;
527:
528: struct uba_hd *uh; /* pjw debugging */
529:
530: trace(TR_UBINT, um->um_tab.b_active << 6 + as, uba_hd[0].uh_users);
531: sc->sc_wticks = 0;
532: sc->sc_softas = 0;
533: /*
534: * If controller wasn't transferring, then this is an
535: * interrupt for attention status on seeking drives.
536: * Just service them.
537: */
538: if (um->um_tab.b_active == 0) {
539: if (upaddr->upcs1 & UP_TRE)
540: upaddr->upcs1 = UP_TRE;
541: goto doattn;
542: }
543: /*
544: * Get device and block structures, and a pointer
545: * to the uba_device for the drive. Select the drive.
546: */
547:
548: dp = um->um_tab.b_actf;
549: bp = dp->b_actf;
550: ui = updinfo[dkunit(bp)];
551: dk_busy &= ~(1 << ui->ui_dk);
552: if ((upaddr->upcs2&07) != ui->ui_slave)
553: upaddr->upcs2 = ui->ui_slave;
554: /*
555: * Check for and process errors on
556: * either the drive or the controller.
557: */
558: if ((upaddr->upds&UPDS_ERR) || (upaddr->upcs1&UP_TRE)) {
559: waitdry = 0;
560: while ((upaddr->upds & UPDS_DRY) == 0) {
561: if (++waitdry > 512)
562: break;
563: upwaitdry++;
564: }
565: if (upaddr->uper1&UPER1_WLE) {
566: /*
567: * Give up on write locked devices
568: * immediately.
569: */
570: printf("up%d: write locked\n", dkunit(bp));
571: bp->b_flags |= B_ERROR;
572: } else if (++um->um_tab.b_errcnt > 27) {
573: /*
574: * After 28 retries (16 without offset, and
575: * 12 with offset positioning) give up.
576: */
577: harderr(bp, "up");
578: printf("cs2=%b er1=%b er2=%b\n",
579: upaddr->upcs2, UPCS2_BITS,
580: upaddr->uper1, UPER1_BITS,
581: upaddr->uper2, UPER2_BITS);
582: bp->b_flags |= B_ERROR;
583: } else {
584: /*
585: * Retriable error.
586: * If a soft ecc, correct it (continuing
587: * by returning if necessary.
588: * Otherwise fall through and retry the transfer
589: */
590: um->um_tab.b_active = 0; /* force retry */
591: if ((upaddr->uper1&(UPER1_DCK|UPER1_ECH))==UPER1_DCK)
592: if (upecc(ui))
593: return;
594: }
595: /*
596: * Clear drive error and, every eight attempts,
597: * (starting with the fourth)
598: * recalibrate to clear the slate.
599: */
600: trace(TR_UBGO, UP_TRE|UP_IE|UP_DCLR|UP_GO, 6);
601: upaddr->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;
602: needie = 0;
603: if ((um->um_tab.b_errcnt&07) == 4 && um->um_tab.b_active == 0) {
604: trace(TR_UBGO, UP_RECAL|UP_IE|UP_GO, 7);
605: upaddr->upcs1 = UP_RECAL|UP_IE|UP_GO;
606: sc->sc_recal = 0;
607: goto nextrecal;
608: }
609: }
610: /*
611: * Advance recalibration finite state machine
612: * if recalibrate in progress, through
613: * RECAL
614: * SEEK
615: * OFFSET (optional)
616: * RETRY
617: */
618: switch (sc->sc_recal) {
619:
620: case 1:
621: upaddr->updc = bp->b_cylin;
622: upaddr->upcs1 = UP_SEEK|UP_IE|UP_GO;
623: goto nextrecal;
624: case 2:
625: if (um->um_tab.b_errcnt < 16 || (bp->b_flags&B_READ) == 0)
626: goto donerecal;
627: upaddr->upof = up_offset[um->um_tab.b_errcnt & 017] | UPOF_FMT22;
628: trace(TR_UBGO, UP_IE|UP_OFFSET|UP_GO, 8);
629: upaddr->upcs1 = UP_IE|UP_OFFSET|UP_GO;
630: goto nextrecal;
631: nextrecal:
632: sc->sc_recal++;
633: um->um_tab.b_active = 1;
634: return;
635: donerecal:
636: case 3:
637: sc->sc_recal = 0;
638: um->um_tab.b_active = 0;
639: break;
640: }
641: /*
642: * If still ``active'', then don't need any more retries.
643: */
644: if (um->um_tab.b_active) {
645: /*
646: * If we were offset positioning,
647: * return to centerline.
648: */
649: if (um->um_tab.b_errcnt >= 16) {
650: upaddr->upof = UPOF_FMT22;
651: trace(TR_UBGO, UP_RTC|UP_GO|UP_IE, 9);
652: upaddr->upcs1 = UP_RTC|UP_GO|UP_IE;
653: while (upaddr->upds & UPDS_PIP)
654: DELAY(25);
655: needie = 0;
656: }
657: um->um_tab.b_active = 0;
658: um->um_tab.b_errcnt = 0;
659: um->um_tab.b_actf = dp->b_forw;
660: dp->b_active = 0;
661: dp->b_errcnt = 0;
662: dp->b_actf = bp->av_forw;
663: bp->b_resid = (-upaddr->upwc * sizeof(short));
664: iodone(bp);
665: /*
666: * If this unit has more work to do,
667: * then start it up right away.
668: */
669: if (dp->b_actf)
670: if (upustart(ui))
671: needie = 0;
672: }
673: as &= ~(1<<ui->ui_slave);
674: /*
675: * Release unibus resources and flush data paths.
676: */
677: ubadone(um);
678: doattn:
679: /*
680: * Process other units which need attention.
681: * For each unit which needs attention, call
682: * the unit start routine to place the slave
683: * on the controller device queue.
684: */
685: while (unit = ffs(as)) {
686: unit--; /* was 1 origin */
687: as &= ~(1<<unit);
688: upaddr->upas = 1<<unit;
689: if (unit < NDRIVE)
690: if (upustart(upip[sc21][unit]))
691: needie = 0;
692: }
693: /*
694: * If the controller is not transferring, but
695: * there are devices ready to transfer, start
696: * the controller.
697: */
698: if (um->um_tab.b_actf && um->um_tab.b_active == 0)
699: if (upstart(um))
700: needie = 0;
701: if (needie) {
702: trace(TR_UBGO, UP_IE, 10);
703: upaddr->upcs1 = UP_IE;
704: }
705: }
706:
707: upread(dev)
708: dev_t dev;
709: {
710: register int unit = minor(dev) >> 3;
711:
712: if (unit >= NUP)
713: u.u_error = ENXIO;
714: else
715: physio(upstrategy, &rupbuf[unit], dev, B_READ, minphys);
716: }
717:
718: upwrite(dev)
719: dev_t dev;
720: {
721: register int unit = minor(dev) >> 3;
722:
723: if (unit >= NUP)
724: u.u_error = ENXIO;
725: else
726: physio(upstrategy, &rupbuf[unit], dev, B_WRITE, minphys);
727: }
728:
729: /*
730: * Correct an ECC error, and restart the i/o to complete
731: * the transfer if necessary. This is quite complicated because
732: * the transfer may be going to an odd memory address base and/or
733: * across a page boundary.
734: */
735: upecc(ui)
736: register struct uba_device *ui;
737: {
738: register struct updevice *up = (struct updevice *)ui->ui_addr;
739: register struct buf *bp = uputab[ui->ui_unit].b_actf;
740: register struct uba_ctlr *um = ui->ui_mi;
741: register struct upst *st;
742: struct uba_regs *ubp = ui->ui_hd->uh_uba;
743: register int i;
744: caddr_t addr;
745: int reg, bit, byte, npf, mask, o, cmd, ubaddr;
746: int bn, cn, tn, sn;
747:
748: /*
749: * Npf is the number of sectors transferred before the sector
750: * containing the ECC error, and reg is the UBA register
751: * mapping (the first part of) the transfer.
752: * O is offset within a memory page of the first byte transferred.
753: */
754: npf = btop((up->upwc * sizeof(short)) + bp->b_bcount) - 1;
755: reg = btop(um->um_ubinfo&0x3ffff) + npf;
756: o = (int)bp->b_un.b_addr & PGOFSET;
757: printf("up%d%c: soft ecc sn%d\n", dkunit(bp),
758: 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
759: mask = up->upec2;
760: #ifdef UPECCDEBUG
761: printf("npf %d reg %x o %d mask %o pos %d\n", npf, reg, o, mask,
762: up->upec1);
763: #endif
764: /*
765: * Flush the buffered data path, and compute the
766: * byte and bit position of the error. The variable i
767: * is the byte offset in the transfer, the variable byte
768: * is the offset from a page boundary in main memory.
769: */
770: ubapurge(um);
771: i = up->upec1 - 1; /* -1 makes 0 origin */
772: bit = i&07;
773: i = (i&~07)>>3;
774: byte = i + o;
775: /*
776: * Correct while possible bits remain of mask. Since mask
777: * contains 11 bits, we continue while the bit offset is > -11.
778: * Also watch out for end of this block and the end of the whole
779: * transfer.
780: */
781: while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
782: addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
783: (byte & PGOFSET);
784: #ifdef UPECCDEBUG
785: printf("addr %x map reg %x\n",
786: addr, *(int *)(&ubp->uba_map[reg+btop(byte)]));
787: printf("old: %x, ", getmemc(addr));
788: #endif
789: putmemc(addr, getmemc(addr)^(mask<<bit));
790: #ifdef UPECCDEBUG
791: printf("new: %x\n", getmemc(addr));
792: #endif
793: byte++;
794: i++;
795: bit -= 8;
796: }
797: um->um_tab.b_active++; /* Either complete or continuing... */
798: if (up->upwc == 0)
799: return (0);
800: /*
801: * Have to continue the transfer... clear the drive,
802: * and compute the position where the transfer is to continue.
803: * We have completed npf+1 sectors of the transfer already;
804: * restart at offset o of next sector (i.e. in UBA register reg+1).
805: */
806: #ifdef notdef
807: up->uper1 = 0;
808: up->upcs1 |= UP_GO;
809: #else
810: up->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;
811: bn = dkblock(bp);
812: st = &upst[ui->ui_type];
813: cn = bp->b_cylin;
814: sn = bn%st->nspc + npf + 1;
815: tn = sn/st->nsect;
816: sn %= st->nsect;
817: cn += tn/st->ntrak;
818: tn %= st->ntrak;
819: up->updc = cn;
820: up->upda = (tn << 8) | sn;
821: ubaddr = (int)ptob(reg+1) + o;
822: up->upba = ubaddr;
823: cmd = (ubaddr >> 8) & 0x300;
824: cmd |= UP_IE|UP_GO|UP_RCOM;
825: up->upcs1 = cmd;
826: #endif
827: return (1);
828: }
829:
830: /*
831: * Reset driver after UBA init.
832: * Cancel software state of all pending transfers
833: * and restart all units and the controller.
834: */
835: upreset(uban)
836: int uban;
837: {
838: register struct uba_ctlr *um;
839: register struct uba_device *ui;
840: register sc21, unit;
841:
842: for (sc21 = 0; sc21 < NSC; sc21++) {
843: if ((um = upminfo[sc21]) == 0 || um->um_ubanum != uban ||
844: um->um_alive == 0)
845: continue;
846: printf(" sc%d", sc21);
847: um->um_tab.b_active = 0;
848: um->um_tab.b_actf = um->um_tab.b_actl = 0;
849: up_softc[sc21].sc_recal = 0;
850: if (um->um_ubinfo) {
851: printf("<%d>", (um->um_ubinfo>>28)&0xf);
852: ubadone(um);
853: }
854: ((struct updevice *)(um->um_addr))->upcs2 = UPCS2_CLR;
855: for (unit = 0; unit < NUP; unit++) {
856: if ((ui = updinfo[unit]) == 0)
857: continue;
858: if (ui->ui_alive == 0 || ui->ui_mi != um)
859: continue;
860: uputab[unit].b_active = 0;
861: (void) upustart(ui);
862: }
863: (void) upstart(um);
864: }
865: }
866:
867: /*
868: * Wake up every second and if an interrupt is pending
869: * but nothing has happened increment a counter.
870: * If nothing happens for 20 seconds, reset the UNIBUS
871: * and begin anew.
872: */
873: upwatch()
874: {
875: register struct uba_ctlr *um;
876: register sc21, unit;
877: register struct up_softc *sc;
878: static int badcount[NSC];
879:
880: timeout(upwatch, (caddr_t)0, hz);
881: for (sc21 = 0; sc21 < NSC; sc21++) {
882: um = upminfo[sc21];
883: if (um == 0 || um->um_alive == 0)
884: continue;
885: sc = &up_softc[sc21];
886: if (um->um_tab.b_active == 0) {
887: for (unit = 0; unit < NUP; unit++)
888: if (uputab[unit].b_active &&
889: updinfo[unit]->ui_mi == um)
890: goto active;
891: sc->sc_wticks = 0;
892: badcount[sc21] = 0;
893: continue;
894: }
895: active:
896: sc->sc_wticks++;
897: if (sc->sc_wticks >= 20) {
898: sc->sc_wticks = 0;
899: printf("sc%d: lost interrupt\n", sc21);
900: ubareset(um->um_ubanum);
901: if(badcount[sc21]++ > 5) {
902: printf("lost interrupts forever\n");
903: boot(1 /* no dump */, 0 /* try syncing */);
904: }
905: }
906: }
907: }
908:
909: #define DBSIZE 20
910:
911: updump(dev)
912: dev_t dev;
913: {
914: struct updevice *upaddr;
915: char *start;
916: int num, blk, unit;
917: struct size *sizes;
918: register struct uba_regs *uba;
919: register struct uba_device *ui;
920: register short *rp;
921: struct upst *st;
922:
923: unit = minor(dev) >> 3;
924: if (unit >= NUP)
925: return (ENXIO);
926: #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
927: ui = phys(struct uba_device *, updinfo[unit]);
928: if (ui->ui_alive == 0)
929: return (ENXIO);
930: uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
931: ubainit(uba);
932: upaddr = (struct updevice *)ui->ui_physaddr;
933: DELAY(2000000);
934: num = maxfree;
935: start = 0;
936: upaddr->upcs2 = unit;
937: DELAY(100);
938: if ((upaddr->upcs1&UP_DVA) == 0)
939: return (EFAULT);
940: if ((upaddr->upds & UPDS_VV) == 0) {
941: upaddr->upcs1 = UP_DCLR|UP_GO;
942: upaddr->upcs1 = UP_PRESET|UP_GO;
943: upaddr->upof = UPOF_FMT22;
944: }
945: if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY)
946: return (EFAULT);
947: st = &upst[ui->ui_type];
948: sizes = phys(struct size *, st->sizes);
949: if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
950: return (EINVAL);
951: while (num > 0) {
952: register struct pte *io;
953: register int i;
954: int cn, sn, tn;
955: daddr_t bn;
956:
957: blk = num > DBSIZE ? DBSIZE : num;
958: io = uba->uba_map;
959: for (i = 0; i < blk; i++)
960: *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
961: *(int *)io = 0;
962: bn = dumplo + btop(start);
963: cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
964: sn = bn%st->nspc;
965: tn = sn/st->nsect;
966: sn = sn%st->nsect;
967: upaddr->updc = cn;
968: rp = (short *) &upaddr->upda;
969: *rp = (tn << 8) + sn;
970: *--rp = 0;
971: *--rp = -blk*NBPG / sizeof (short);
972: *--rp = UP_GO|UP_WCOM;
973: do {
974: DELAY(25);
975: } while ((upaddr->upcs1 & UP_RDY) == 0);
976: if (upaddr->upds&UPDS_ERR)
977: return (EIO);
978: start += blk*NBPG;
979: num -= blk;
980: }
981: return (0);
982: }
983: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.