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