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