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