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