|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)idc.c 7.5 (Berkeley) 5/27/88
7: */
8:
9: #include "rb.h"
10: #if NIDC > 0
11: int idcdebug = 0;
12: #define printd if(idcdebug)printf
13: int idctrb[1000];
14: int *trp = idctrb;
15: #define trace(a,b) {*trp++ = *(int*)a; *trp++ = (int)b; if(trp>&idctrb[998])trp=idctrb;}
16: /*
17: * IDC (RB730) disk driver
18: *
19: * There can only ever be one IDC on a machine,
20: * and only on a VAX-11/730. We take advantage
21: * of that to simplify the driver.
22: *
23: * TODO:
24: * ecc
25: */
26: #include "param.h"
27: #include "systm.h"
28: #include "buf.h"
29: #include "conf.h"
30: #include "dir.h"
31: #include "user.h"
32: #include "map.h"
33: #include "vm.h"
34: #include "ioctl.h"
35: #include "disklabel.h"
36: #include "dkstat.h"
37: #include "cmap.h"
38: #include "dkbad.h"
39: #include "uio.h"
40: #include "kernel.h"
41: #include "syslog.h"
42:
43: #include "../machine/pte.h"
44: #include "../vax/cpu.h"
45: #include "ubareg.h"
46: #include "ubavar.h"
47: #include "idcreg.h"
48:
49: struct idc_softc {
50: int sc_bcnt; /* number of bytes to transfer */
51: int sc_resid; /* total number of bytes to transfer */
52: int sc_ubaddr; /* Unibus address of data */
53: short sc_unit; /* unit doing transfer */
54: short sc_softas; /* software attention summary bits */
55: union idc_dar {
56: long dar_l;
57: u_short dar_w[2];
58: u_char dar_b[4];
59: } sc_un; /* prototype disk address register */
60: } idc_softc;
61:
62: #define dar_dar dar_l /* the whole disk address */
63: #define dar_cyl dar_w[1] /* cylinder address */
64: #define dar_trk dar_b[1] /* track */
65: #define dar_sect dar_b[0] /* sector */
66: #define sc_dar sc_un.dar_dar
67: #define sc_cyl sc_un.dar_cyl
68: #define sc_trk sc_un.dar_trk
69: #define sc_sect sc_un.dar_sect
70:
71: #define idcunit(dev) (minor(dev) >> 3)
72:
73: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
74: struct size {
75: daddr_t nblocks;
76: int cyloff;
77: } rb02_sizes[8] ={
78: 15884, 0, /* A=cyl 0 thru 399 */
79: 4480, 400, /* B=cyl 400 thru 510 */
80: 20480, 0, /* C=cyl 0 thru 511 */
81: 0, 0,
82: 0, 0,
83: 0, 0,
84: 0, 0,
85: 0, 0,
86: }, rb80_sizes[8] ={
87: 15884, 0, /* A=cyl 0 thru 36 */
88: 33440, 37, /* B=cyl 37 thru 114 */
89: 242606, 0, /* C=cyl 0 thru 558 */
90: 0, 0,
91: 0, 0,
92: 0, 0,
93: 82080, 115, /* G=cyl 115 thru 304 */
94: 110143, 305, /* H=cyl 305 thru 558 */
95: };
96: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
97:
98: int idcprobe(), idcslave(), idcattach(), idcdgo(), idcintr();
99: struct uba_ctlr *idcminfo[NIDC];
100: struct uba_device *idcdinfo[NRB];
101:
102: u_short idcstd[] = { 0174400, 0};
103: struct uba_driver idcdriver =
104: { idcprobe, idcslave, idcattach, idcdgo, idcstd, "rb", idcdinfo, "idc", idcminfo, 0 };
105: struct buf idcutab[NRB];
106: union idc_dar idccyl[NRB];
107:
108: struct idcst {
109: short nbps;
110: short nsect;
111: short ntrak;
112: short nspc;
113: short ncyl;
114: struct size *sizes;
115: } idcst[] = {
116: 256, NRB02SECT, NRB02TRK, NRB02SECT*NRB02TRK, NRB02CYL, rb02_sizes,
117: 512, NRB80SECT, NRB80TRK, NRB80SECT*NRB80TRK, NRB80CYL, rb80_sizes,
118: };
119:
120: #define b_cylin b_resid
121:
122: int idcwstart, idcwticks, idcwatch();
123:
124: /*ARGSUSED*/
125: idcprobe(reg)
126: caddr_t reg;
127: {
128: register int br, cvec;
129: register struct idcdevice *idcaddr;
130:
131: #ifdef lint
132: br = 0; cvec = br; br = cvec;
133: #endif
134: idcaddr = (struct idcdevice *)((caddr_t)uba_hd[0].uh_uba + 0x200);
135: idcaddr->idccsr = IDC_ATTN|IDC_IE;
136: while ((idcaddr->idccsr & IDC_CRDY) == 0)
137: ;
138: idcaddr->idccsr = IDC_ATTN|IDC_CRDY;
139: return (sizeof (struct idcdevice));
140: }
141:
142: /*ARGSUSED*/
143: idcslave(ui, reg)
144: struct uba_device *ui;
145: caddr_t reg;
146: {
147: register struct idcdevice *idcaddr;
148: register int i;
149:
150: idcaddr = (struct idcdevice *)((caddr_t)uba_hd[0].uh_uba + 0x200);
151: ui->ui_type = 0;
152: idcaddr->idcmpr = IDCGS_GETSTAT;
153: idcaddr->idccsr = IDC_GETSTAT|(ui->ui_slave<<8);
154: (void) idcwait(idcaddr, 0);
155: i = idcaddr->idcmpr;
156: idcaddr->idccsr = IDC_CRDY|(1<<(ui->ui_slave+16));
157: (void) idcwait(idcaddr, 0);
158: /* read header to synchronize microcode */
159: idcaddr->idccsr = (ui->ui_slave<<8)|IDC_RHDR;
160: (void) idcwait(idcaddr, 0);
161: i = idcaddr->idcmpr; /* read header word 1 */
162: i = idcaddr->idcmpr; /* read header word 2 */
163: #ifdef lint
164: i = i;
165: #endif
166: if ((idcaddr->idccsr & (IDC_ERR|IDC_R80)) == IDC_R80)
167: ui->ui_type = 1;
168: else if ((idcaddr->idccsr & (IDC_DE|IDC_R80)) == 0)
169: /*
170: * RB02 may not have pack spun up, just look for drive error.
171: */
172: ui->ui_type = 0;
173: else
174: return (0);
175: return (1);
176: }
177:
178: idcattach(ui)
179: register struct uba_device *ui;
180: {
181:
182: /*
183: * Fix all addresses to correspond
184: * to the "real" IDC address.
185: */
186: ui->ui_mi->um_addr = ui->ui_addr = (caddr_t)uba_hd[0].uh_uba + 0x200;
187: ui->ui_physaddr = (caddr_t)uba_hd[0].uh_physuba + 0x200;
188: if (idcwstart == 0) {
189: timeout(idcwatch, (caddr_t)0, hz);
190: idcwstart++;
191: }
192: if (ui->ui_dk >= 0)
193: if (ui->ui_type)
194: dk_mspw[ui->ui_dk] = 1.0 / (60 * NRB80SECT * 256);
195: else
196: dk_mspw[ui->ui_dk] = 1.0 / (60 * NRB02SECT * 128);
197: idccyl[ui->ui_unit].dar_dar = -1;
198: ui->ui_flags = 0;
199: }
200:
201: idcopen(dev)
202: dev_t dev;
203: {
204: register int unit = idcunit(dev);
205: register struct uba_device *ui;
206:
207: if (unit >= NRB || (ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0)
208: return (ENXIO);
209: return (0);
210: }
211:
212: idcstrategy(bp)
213: register struct buf *bp;
214: {
215: register struct uba_device *ui;
216: register struct idcst *st;
217: register int unit;
218: register struct buf *dp;
219: int xunit = minor(bp->b_dev) & 07;
220: long bn, sz;
221:
222: sz = (bp->b_bcount+511) >> 9;
223: unit = idcunit(bp->b_dev);
224: if (unit >= NRB) {
225: bp->b_error = ENXIO;
226: goto bad;
227: }
228: ui = idcdinfo[unit];
229: if (ui == 0 || ui->ui_alive == 0) {
230: bp->b_error = ENXIO;
231: goto bad;
232: }
233: st = &idcst[ui->ui_type];
234: if (bp->b_blkno < 0 ||
235: (bn = bp->b_blkno)+sz > st->sizes[xunit].nblocks) {
236: if (bp->b_blkno == st->sizes[xunit].nblocks) {
237: bp->b_resid = bp->b_bcount;
238: goto done;
239: }
240: bp->b_error = EINVAL;
241: goto bad;
242: }
243: if (ui->ui_type == 0)
244: bn *= 2;
245: bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
246: (void) spl5();
247: trace("strt",bp);
248: dp = &idcutab[ui->ui_unit];
249: disksort(dp, bp);
250: if (dp->b_active == 0) {
251: trace("!act",dp);
252: (void) idcustart(ui);
253: bp = &ui->ui_mi->um_tab;
254: if (bp->b_actf && bp->b_active == 0)
255: (void) idcstart(ui->ui_mi);
256: }
257: (void) spl0();
258: return;
259:
260: bad:
261: bp->b_flags |= B_ERROR;
262: done:
263: iodone(bp);
264: return;
265: }
266:
267: idcustart(ui)
268: register struct uba_device *ui;
269: {
270: register struct buf *bp, *dp;
271: register struct uba_ctlr *um;
272: register struct idcdevice *idcaddr;
273: register struct idcst *st;
274: union idc_dar cyltrk;
275: daddr_t bn;
276: int unit;
277:
278: if (ui == 0)
279: return (0);
280: dk_busy &= ~(1<<ui->ui_dk);
281: dp = &idcutab[ui->ui_unit];
282: um = ui->ui_mi;
283: unit = ui->ui_slave;
284: trace("ust", dp);
285: idcaddr = (struct idcdevice *)um->um_addr;
286: if (um->um_tab.b_active) {
287: idc_softc.sc_softas |= 1<<unit;
288: trace("umac",idc_softc.sc_softas);
289: return (0);
290: }
291: if ((bp = dp->b_actf) == NULL) {
292: trace("!bp",0);
293: return (0);
294: }
295: if (dp->b_active) {
296: trace("dpac",dp->b_active);
297: goto done;
298: }
299: dp->b_active = 1;
300: /* CHECK DRIVE READY? */
301: bn = bp->b_blkno;
302: trace("seek", bn);
303: if (ui->ui_type == 0)
304: bn *= 2;
305: st = &idcst[ui->ui_type];
306: cyltrk.dar_cyl = bp->b_cylin;
307: cyltrk.dar_trk = (bn / st->nsect) % st->ntrak;
308: cyltrk.dar_sect = 0;
309: printd("idcustart, unit %d, cyltrk 0x%x\n", unit, cyltrk.dar_dar);
310: /*
311: * If on cylinder, no need to seek.
312: */
313: if (cyltrk.dar_dar == idccyl[ui->ui_unit].dar_dar)
314: goto done;
315: /*
316: * RB80 can change heads (tracks) just by loading
317: * the disk address register, perform optimization
318: * here instead of doing a full seek.
319: */
320: if (ui->ui_type && cyltrk.dar_cyl == idccyl[ui->ui_unit].dar_cyl) {
321: idcaddr->idccsr = IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8);
322: idcaddr->idcdar = cyltrk.dar_dar;
323: idccyl[ui->ui_unit].dar_dar = cyltrk.dar_dar;
324: goto done;
325: }
326: /*
327: * Need to do a full seek. Select the unit, clear
328: * its attention bit, set the command, load the
329: * disk address register, and then go.
330: */
331: idcaddr->idccsr =
332: IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8)|(1<<(unit+16));
333: idcaddr->idcdar = cyltrk.dar_dar;
334: idccyl[ui->ui_unit].dar_dar = cyltrk.dar_dar;
335: printd(" seek");
336: idcaddr->idccsr = IDC_IE|IDC_SEEK|(unit<<8);
337: if (ui->ui_dk >= 0) {
338: dk_busy |= 1<<ui->ui_dk;
339: dk_seek[ui->ui_dk]++;
340: }
341: /*
342: * RB80's initiate seeks very quickly. Wait for it
343: * to come ready rather than taking the interrupt.
344: */
345: if (ui->ui_type) {
346: if (idcwait(idcaddr, 10) == 0)
347: return (1);
348: idcaddr->idccsr &= ~IDC_ATTN;
349: /* has the seek completed? */
350: if (idcaddr->idccsr & IDC_DRDY) {
351: printd(", drdy");
352: idcaddr->idccsr =
353: IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8)|(1<<(unit+16));
354: goto done;
355: }
356: }
357: printd(", idccsr = 0x%x\n", idcaddr->idccsr);
358: return (1);
359: done:
360: if (dp->b_active != 2) {
361: trace("!=2",dp->b_active);
362: dp->b_forw = NULL;
363: if (um->um_tab.b_actf == NULL)
364: um->um_tab.b_actf = dp;
365: else {
366: trace("!NUL",um->um_tab.b_actl);
367: um->um_tab.b_actl->b_forw = dp;
368: }
369: um->um_tab.b_actl = dp;
370: dp->b_active = 2;
371: }
372: return (0);
373: }
374:
375: idcstart(um)
376: register struct uba_ctlr *um;
377: {
378: register struct buf *bp, *dp;
379: register struct uba_device *ui;
380: register struct idcdevice *idcaddr;
381: register struct idc_softc *sc;
382: struct idcst *st;
383: daddr_t bn;
384: int sn, tn, cmd;
385:
386: loop:
387: if ((dp = um->um_tab.b_actf) == NULL) {
388: trace("nodp",um);
389: return (0);
390: }
391: if ((bp = dp->b_actf) == NULL) {
392: trace("nobp", dp);
393: um->um_tab.b_actf = dp->b_forw;
394: goto loop;
395: }
396: um->um_tab.b_active = 1;
397: ui = idcdinfo[idcunit(bp->b_dev)];
398: bn = bp->b_blkno;
399: trace("star",bp);
400: if (ui->ui_type == 0)
401: bn *= 2;
402: sc = &idc_softc;
403: st = &idcst[ui->ui_type];
404: sn = bn%st->nspc;
405: tn = sn/st->nsect;
406: sn %= st->nsect;
407: sc->sc_sect = sn;
408: sc->sc_trk = tn;
409: sc->sc_cyl = bp->b_cylin;
410: idcaddr = (struct idcdevice *)ui->ui_addr;
411: printd("idcstart, unit %d, dar 0x%x", ui->ui_slave, sc->sc_dar);
412: if (bp->b_flags & B_READ)
413: cmd = IDC_IE|IDC_READ|(ui->ui_slave<<8);
414: else
415: cmd = IDC_IE|IDC_WRITE|(ui->ui_slave<<8);
416: idcaddr->idccsr = IDC_CRDY|cmd;
417: if ((idcaddr->idccsr&IDC_DRDY) == 0) {
418: printf("rb%d: not ready\n", idcunit(bp->b_dev));
419: um->um_tab.b_active = 0;
420: um->um_tab.b_errcnt = 0;
421: dp->b_actf = bp->av_forw;
422: dp->b_active = 0;
423: bp->b_flags |= B_ERROR;
424: iodone(bp);
425: goto loop;
426: }
427: idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
428: idccyl[ui->ui_unit].dar_sect = 0;
429: sn = (st->nsect - sn) * st->nbps;
430: if (sn > bp->b_bcount)
431: sn = bp->b_bcount;
432: sc->sc_bcnt = sn;
433: sc->sc_resid = bp->b_bcount;
434: sc->sc_unit = ui->ui_slave;
435: printd(", bcr 0x%x, cmd 0x%x\n", sn, cmd);
436: um->um_cmd = cmd;
437: (void) ubago(ui);
438: return (1);
439: }
440:
441: idcdgo(um)
442: register struct uba_ctlr *um;
443: {
444: register struct idcdevice *idcaddr = (struct idcdevice *)um->um_addr;
445: register struct idc_softc *sc = &idc_softc;
446:
447: /*
448: * VERY IMPORTANT: must load registers in this order.
449: */
450: idcaddr->idcbar = sc->sc_ubaddr = um->um_ubinfo&0x3ffff;
451: idcaddr->idcbcr = -sc->sc_bcnt;
452: idcaddr->idcdar = sc->sc_dar;
453: printd("idcdgo, ubinfo 0x%x, cmd 0x%x\n", um->um_ubinfo, um->um_cmd);
454: idcaddr->idccsr = um->um_cmd;
455: trace("go", um);
456: um->um_tab.b_active = 2;
457: /*** CLEAR SPURIOUS ATTN ON R80? ***/
458: }
459:
460: idcintr(idc)
461: int idc;
462: {
463: register struct uba_ctlr *um = idcminfo[idc];
464: register struct uba_device *ui;
465: register struct idcdevice *idcaddr = (struct idcdevice *)um->um_addr;
466: register struct idc_softc *sc = &idc_softc;
467: register struct buf *bp, *dp;
468: struct idcst *st;
469: int unit, as, er, cmd, ds = 0;
470:
471: printd("idcintr, idccsr 0x%x", idcaddr->idccsr);
472: top:
473: idcwticks = 0;
474: trace("intr", um->um_tab.b_active);
475: if (um->um_tab.b_active == 2) {
476: /*
477: * Process a data transfer complete interrupt.
478: */
479: um->um_tab.b_active = 1;
480: dp = um->um_tab.b_actf;
481: bp = dp->b_actf;
482: ui = idcdinfo[idcunit(bp->b_dev)];
483: unit = ui->ui_slave;
484: st = &idcst[ui->ui_type];
485: idcaddr->idccsr = IDC_IE|IDC_CRDY|(unit<<8);
486: if ((er = idcaddr->idccsr) & IDC_ERR) {
487: if (er & IDC_DE) {
488: idcaddr->idcmpr = IDCGS_GETSTAT;
489: idcaddr->idccsr = IDC_GETSTAT|(unit<<8);
490: (void) idcwait(idcaddr, 0);
491: ds = idcaddr->idcmpr;
492: idcaddr->idccsr =
493: IDC_IE|IDC_CRDY|(1<<(unit+16));
494: }
495: printd(", er 0x%x, ds 0x%x", er, ds);
496: if (ds & IDCDS_WL) {
497: printf("rb%d: write locked\n",
498: idcunit(bp->b_dev));
499: bp->b_flags |= B_ERROR;
500: } else if (++um->um_tab.b_errcnt > 28 || er&IDC_HARD) {
501: hard:
502: diskerr(bp, "rb", "hard error", LOG_PRINTF, -1,
503: (struct disklabel *)0);
504: printf(" csr=%b ds=%b\n", er, IDCCSR_BITS, ds,
505: ui->ui_type?IDCRB80DS_BITS:IDCRB02DS_BITS);
506: bp->b_flags |= B_ERROR;
507: } else if (er & IDC_DCK) {
508: switch ((int)(er & IDC_ECS)) {
509: case IDC_ECS_NONE:
510: break;
511: case IDC_ECS_SOFT:
512: idcecc(ui);
513: break;
514: case IDC_ECS_HARD:
515: default:
516: goto hard;
517: }
518: } else
519: /* recoverable error, set up for retry */
520: goto seek;
521: }
522: if ((sc->sc_resid -= sc->sc_bcnt) != 0) {
523: sc->sc_ubaddr += sc->sc_bcnt;
524: /*
525: * Current transfer is complete, have
526: * we overflowed to the next track?
527: */
528: if ((sc->sc_sect += sc->sc_bcnt/st->nbps) == st->nsect) {
529: sc->sc_sect = 0;
530: if (++sc->sc_trk == st->ntrak) {
531: sc->sc_trk = 0;
532: sc->sc_cyl++;
533: } else if (ui->ui_type) {
534: /*
535: * RB80 can change heads just by
536: * loading the disk address register.
537: */
538: idcaddr->idccsr = IDC_SEEK|IDC_CRDY|
539: IDC_IE|(unit<<8);
540: printd(", change to track 0x%x", sc->sc_dar);
541: idcaddr->idcdar = sc->sc_dar;
542: idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
543: idccyl[ui->ui_unit].dar_sect = 0;
544: goto cont;
545: }
546: /*
547: * Changing tracks on RB02 or cylinders
548: * on RB80, start a seek.
549: */
550: seek:
551: cmd = IDC_IE|IDC_SEEK|(unit<<8);
552: idcaddr->idccsr = cmd|IDC_CRDY;
553: idcaddr->idcdar = sc->sc_dar;
554: printd(", seek to 0x%x\n", sc->sc_dar);
555: idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
556: idccyl[ui->ui_unit].dar_sect = 0;
557: sc->sc_bcnt = 0;
558: idcaddr->idccsr = cmd;
559: if (ui->ui_type) {
560: if (idcwait(idcaddr, 10) == 0)
561: return;
562: idcaddr->idccsr &= ~IDC_ATTN;
563: if (idcaddr->idccsr & IDC_DRDY)
564: goto top;
565: }
566: } else {
567: /*
568: * Continue transfer on current track.
569: */
570: cont:
571: sc->sc_bcnt = (st->nsect-sc->sc_sect)*st->nbps;
572: if (sc->sc_bcnt > sc->sc_resid)
573: sc->sc_bcnt = sc->sc_resid;
574: if (bp->b_flags & B_READ)
575: cmd = IDC_IE|IDC_READ|(unit<<8);
576: else
577: cmd = IDC_IE|IDC_WRITE|(unit<<8);
578: idcaddr->idccsr = cmd|IDC_CRDY;
579: idcaddr->idcbar = sc->sc_ubaddr;
580: idcaddr->idcbcr = -sc->sc_bcnt;
581: idcaddr->idcdar = sc->sc_dar;
582: printd(", continue I/O 0x%x, 0x%x\n", sc->sc_dar, sc->sc_bcnt);
583: idcaddr->idccsr = cmd;
584: um->um_tab.b_active = 2;
585: }
586: return;
587: }
588: /*
589: * Entire transfer is done, clean up.
590: */
591: ubadone(um);
592: dk_busy &= ~(1 << ui->ui_dk);
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: trace("done", dp); trace(&um->um_tab.b_actf, dp->b_actf);
600: bp->b_resid = sc->sc_resid;
601: printd(", iodone, resid 0x%x\n", bp->b_resid);
602: iodone(bp);
603: if (dp->b_actf)
604: if (idcustart(ui))
605: return;
606: } else if (um->um_tab.b_active == 1) {
607: /*
608: * Got an interrupt while setting up for a command
609: * or doing a mid-transfer seek. Save any attentions
610: * for later and process a mid-transfer seek complete.
611: */
612: as = idcaddr->idccsr;
613: idcaddr->idccsr = IDC_IE|IDC_CRDY|(as&IDC_ATTN);
614: as = (as >> 16) & 0xf;
615: unit = sc->sc_unit;
616: sc->sc_softas |= as & ~(1<<unit);
617: if (as & (1<<unit)) {
618: printd(", seek1 complete");
619: um->um_tab.b_active = 2;
620: goto top;
621: }
622: printd(", as1 %o\n", as);
623: return;
624: }
625: /*
626: * Process any seek initiated or complete interrupts.
627: */
628: as = idcaddr->idccsr;
629: idcaddr->idccsr = IDC_IE|IDC_CRDY|(as&IDC_ATTN);
630: as = ((as >> 16) & 0xf) | sc->sc_softas;
631: sc->sc_softas = 0;
632: trace("as", as);
633: printd(", as %o", as);
634: for (unit = 0; unit < NRB; unit++)
635: if (as & (1<<unit)) {
636: as &= ~(1<<unit);
637: idcaddr->idccsr = IDC_IE|IDC_CRDY|(unit<<8);
638: ui = idcdinfo[unit];
639: if (ui) {
640: printd(", attn unit %d", unit);
641: if (idcaddr->idccsr & IDC_DRDY)
642: if (idcustart(ui)) {
643: sc->sc_softas = as;
644: return;
645: }
646: } else {
647: printd(", unsol. intr. unit %d", unit);
648: }
649: }
650: printd("\n");
651: if (um->um_tab.b_actf && um->um_tab.b_active == 0) {
652: trace("stum",um->um_tab.b_actf);
653: (void) idcstart(um);
654: }
655: }
656:
657: idcwait(addr, n)
658: register struct idcdevice *addr;
659: register int n;
660: {
661: register int i;
662:
663: while (--n && (addr->idccsr & IDC_CRDY) == 0)
664: for (i = 10; i; i--)
665: ;
666: return (n);
667: }
668:
669: idcecc(ui)
670: register struct uba_device *ui;
671: {
672: register struct idcdevice *idc = (struct idcdevice *)ui->ui_addr;
673: register struct buf *bp = idcutab[ui->ui_unit].b_actf;
674: register struct uba_ctlr *um = ui->ui_mi;
675: register int i;
676: struct uba_regs *ubp = ui->ui_hd->uh_uba;
677: int bit, byte, mask;
678: caddr_t addr;
679: int reg, npf, o;
680:
681: npf = btop(idc->idcbcr + idc_softc.sc_bcnt) - 1;;
682: reg = btop(idc_softc.sc_ubaddr) + npf;
683: o = (int)bp->b_un.b_addr & PGOFSET;
684: um->um_tab.b_active = 1; /* Either complete or continuing... */
685: diskerr(bp, "rb", "soft ecc", LOG_WARNING, npf, (struct disklabel *)0);
686: addlog("\n");
687: mask = idc->idceccpat;
688: i = idc->idceccpos - 1; /* -1 makes 0 origin */
689: bit = i&07;
690: i = (i&~07)>>3;
691: byte = i + o;
692: while (i < 512 && (int)ptob(npf)+i < idc_softc.sc_bcnt && bit > -11) {
693: /*
694: * should be:
695: * addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
696: * (byte & PGOFSET);
697: * but this generates an extzv which hangs the UNIBUS.
698: */
699: addr = ptob(*(int *)&ubp->uba_map[reg+btop(byte)]&0x1fffff)+
700: (byte & PGOFSET);
701: putmemc(addr, getmemc(addr)^(mask<<bit));
702: byte++;
703: i++;
704: bit -= 8;
705: }
706: idc_softc.sc_bcnt += idc->idcbcr;
707: um->um_tab.b_errcnt = 0; /* error has been corrected */
708: return;
709: }
710:
711: idcreset(uban)
712: int uban;
713: {
714: register struct uba_ctlr *um;
715: register struct uba_device *ui;
716: register unit;
717:
718: if ((um = idcminfo[0]) == 0 || um->um_ubanum != uban ||
719: um->um_alive == 0)
720: return;
721: printf(" idc0");
722: um->um_tab.b_active = 0;
723: um->um_tab.b_actf = um->um_tab.b_actl = 0;
724: if (um->um_ubinfo) {
725: printf("<%d>", (um->um_ubinfo>>28)&0xf);
726: um->um_ubinfo = 0;
727: }
728: for (unit = 0; unit < NRB; unit++) {
729: if ((ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0)
730: continue;
731: idcutab[unit].b_active = 0;
732: (void) idcustart(ui);
733: }
734: (void) idcstart(um);
735: }
736:
737: idcwatch()
738: {
739: register struct uba_ctlr *um;
740: register unit;
741:
742: timeout(idcwatch, (caddr_t)0, hz);
743: um = idcminfo[0];
744: if (um == 0 || um->um_alive == 0)
745: return;
746: if (um->um_tab.b_active == 0) {
747: for (unit = 0; unit < NRB; unit++)
748: if (idcutab[unit].b_active)
749: goto active;
750: idcwticks = 0;
751: return;
752: }
753: active:
754: idcwticks++;
755: if (idcwticks >= 20) {
756: idcwticks = 0;
757: printf("idc0: lost interrupt\n");
758: idcintr(0);
759: }
760: }
761:
762: /*ARGSUSED*/
763: idcdump(dev)
764: dev_t dev;
765: {
766: struct idcdevice *idcaddr;
767: char *start;
768: int num, blk, unit;
769: struct size *sizes;
770: register struct uba_regs *uba;
771: register struct uba_device *ui;
772: struct idcst *st;
773: union idc_dar dar;
774: int nspg;
775:
776: unit = idcunit(dev);
777: if (unit >= NRB)
778: return (ENXIO);
779: #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
780: ui = phys(struct uba_device *, idcdinfo[unit]);
781: if (ui->ui_alive == 0)
782: return (ENXIO);
783: uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
784: ubainit(uba);
785: idcaddr = (struct idcdevice *)ui->ui_physaddr;
786: if (idcwait(idcaddr, 100) == 0)
787: return (EFAULT);
788: /*
789: * Since we can only transfer one track at a time, and
790: * the rl02 has 256 byte sectors, all the calculations
791: * are done in terms of physical sectors (i.e. num and blk
792: * are in sectors not NBPG blocks.
793: */
794: st = phys(struct idcst *, &idcst[ui->ui_type]);
795: sizes = phys(struct size *, st->sizes);
796: if (dumplo < 0)
797: return (EINVAL);
798: if (dumplo + maxfree >= sizes[minor(dev)&07].nblocks)
799: num = sizes[minor(dev)&07].nblocks - dumplo;
800: nspg = NBPG / st->nbps;
801: num = num * nspg;
802: start = 0;
803:
804: while (num > 0) {
805: register struct pte *io;
806: register int i;
807: daddr_t bn;
808:
809: bn = (dumplo + btop(start)) * nspg;
810: dar.dar_cyl = bn / st->nspc + sizes[minor(dev)&07].cyloff;
811: bn %= st->nspc;
812: dar.dar_trk = bn / st->nsect;
813: dar.dar_sect = bn % st->nsect;
814: blk = st->nsect - dar.dar_sect;
815: if (num < blk)
816: blk = num;
817:
818: io = uba->uba_map;
819: for (i = 0; i < (blk + nspg - 1) / nspg; i++)
820: *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
821: *(int *)io = 0;
822:
823: idcaddr->idccsr = IDC_CRDY | IDC_SEEK | unit<<8;
824: if ((idcaddr->idccsr&IDC_DRDY) == 0)
825: return (EFAULT);
826: idcaddr->idcdar = dar.dar_dar;
827: idcaddr->idccsr = IDC_SEEK | unit << 8;
828: while ((idcaddr->idccsr & (IDC_CRDY|IDC_DRDY))
829: != (IDC_CRDY|IDC_DRDY))
830: ;
831: if (idcaddr->idccsr & IDC_ERR) {
832: printf("rb%d: seek, csr=%b\n",
833: unit, idcaddr->idccsr, IDCCSR_BITS);
834: return (EIO);
835: }
836:
837: idcaddr->idccsr = IDC_CRDY | IDC_WRITE | unit<<8;
838: if ((idcaddr->idccsr&IDC_DRDY) == 0)
839: return (EFAULT);
840: idcaddr->idcbar = 0; /* start addr 0 */
841: idcaddr->idcbcr = - (blk * st->nbps);
842: idcaddr->idcdar = dar.dar_dar;
843: idcaddr->idccsr = IDC_WRITE | unit << 8;
844: while ((idcaddr->idccsr & (IDC_CRDY|IDC_DRDY))
845: != (IDC_CRDY|IDC_DRDY))
846: ;
847: if (idcaddr->idccsr & IDC_ERR) {
848: printf("rb%d: write, csr=%b\n",
849: unit, idcaddr->idccsr, IDCCSR_BITS);
850: return (EIO);
851: }
852:
853: start += blk * st->nbps;
854: num -= blk;
855: }
856: return (0);
857: }
858:
859: idcsize(dev)
860: dev_t dev;
861: {
862: int unit = idcunit(dev);
863: struct uba_device *ui;
864: struct idcst *st;
865:
866: if (unit >= NRB || (ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0)
867: return (-1);
868: st = &idcst[ui->ui_type];
869: return (st->sizes[minor(dev) & 07].nblocks);
870: }
871: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.