|
|
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.1 (Berkeley) 6/5/86
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 "../machine/pte.h"
27:
28: #include "param.h"
29: #include "systm.h"
30: #include "buf.h"
31: #include "conf.h"
32: #include "dir.h"
33: #include "user.h"
34: #include "map.h"
35: #include "vm.h"
36: #include "dk.h"
37: #include "cmap.h"
38: #include "dkbad.h"
39: #include "uio.h"
40: #include "kernel.h"
41: #include "syslog.h"
42:
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: struct buf ridcbuf[NRB];
120:
121: #define b_cylin b_resid
122:
123: int idcwstart, idcwticks, idcwatch();
124:
125: /*ARGSUSED*/
126: idcprobe(reg)
127: caddr_t reg;
128: {
129: register int br, cvec;
130: register struct idcdevice *idcaddr;
131:
132: #ifdef lint
133: br = 0; cvec = br; br = cvec;
134: #endif
135: idcaddr = (struct idcdevice *)((caddr_t)uba_hd[0].uh_uba + 0x200);
136: idcaddr->idccsr = IDC_ATTN|IDC_IE;
137: while ((idcaddr->idccsr & IDC_CRDY) == 0)
138: ;
139: idcaddr->idccsr = IDC_ATTN|IDC_CRDY;
140: return (sizeof (struct idcdevice));
141: }
142:
143: /*ARGSUSED*/
144: idcslave(ui, reg)
145: struct uba_device *ui;
146: caddr_t reg;
147: {
148: register struct idcdevice *idcaddr;
149: register int i;
150:
151: idcaddr = (struct idcdevice *)((caddr_t)uba_hd[0].uh_uba + 0x200);
152: ui->ui_type = 0;
153: idcaddr->idcmpr = IDCGS_GETSTAT;
154: idcaddr->idccsr = IDC_GETSTAT|(ui->ui_slave<<8);
155: (void) idcwait(idcaddr, 0);
156: i = idcaddr->idcmpr;
157: idcaddr->idccsr = IDC_CRDY|(1<<(ui->ui_slave+16));
158: (void) idcwait(idcaddr, 0);
159: /* read header to synchronize microcode */
160: idcaddr->idccsr = (ui->ui_slave<<8)|IDC_RHDR;
161: (void) idcwait(idcaddr, 0);
162: i = idcaddr->idcmpr; /* read header word 1 */
163: i = idcaddr->idcmpr; /* read header word 2 */
164: #ifdef lint
165: i = i;
166: #endif
167: if ((idcaddr->idccsr & (IDC_ERR|IDC_R80)) == IDC_R80)
168: ui->ui_type = 1;
169: else if ((idcaddr->idccsr & (IDC_DE|IDC_R80)) == 0)
170: /*
171: * RB02 may not have pack spun up, just look for drive error.
172: */
173: ui->ui_type = 0;
174: else
175: return (0);
176: return (1);
177: }
178:
179: idcattach(ui)
180: register struct uba_device *ui;
181: {
182:
183: /*
184: * Fix all addresses to correspond
185: * to the "real" IDC address.
186: */
187: ui->ui_mi->um_addr = ui->ui_addr = (caddr_t)uba_hd[0].uh_uba + 0x200;
188: ui->ui_physaddr = (caddr_t)uba_hd[0].uh_physuba + 0x200;
189: if (idcwstart == 0) {
190: timeout(idcwatch, (caddr_t)0, hz);
191: idcwstart++;
192: }
193: if (ui->ui_dk >= 0)
194: if (ui->ui_type)
195: dk_mspw[ui->ui_dk] = 1.0 / (60 * NRB80SECT * 256);
196: else
197: dk_mspw[ui->ui_dk] = 1.0 / (60 * NRB02SECT * 128);
198: idccyl[ui->ui_unit].dar_dar = -1;
199: ui->ui_flags = 0;
200: }
201:
202: idcopen(dev)
203: dev_t dev;
204: {
205: register int unit = idcunit(dev);
206: register struct uba_device *ui;
207:
208: if (unit >= NRB || (ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0)
209: return (ENXIO);
210: return (0);
211: }
212:
213: idcstrategy(bp)
214: register struct buf *bp;
215: {
216: register struct uba_device *ui;
217: register struct idcst *st;
218: register int unit;
219: register struct buf *dp;
220: int xunit = minor(bp->b_dev) & 07;
221: long bn, sz;
222:
223: sz = (bp->b_bcount+511) >> 9;
224: unit = idcunit(bp->b_dev);
225: if (unit >= NRB) {
226: bp->b_error = ENXIO;
227: goto bad;
228: }
229: ui = idcdinfo[unit];
230: if (ui == 0 || ui->ui_alive == 0) {
231: bp->b_error = ENXIO;
232: goto bad;
233: }
234: st = &idcst[ui->ui_type];
235: if (bp->b_blkno < 0 ||
236: (bn = bp->b_blkno)+sz > st->sizes[xunit].nblocks) {
237: if (bp->b_blkno == st->sizes[xunit].nblocks) {
238: bp->b_resid = bp->b_bcount;
239: goto done;
240: }
241: bp->b_error = EINVAL;
242: goto bad;
243: }
244: if (ui->ui_type == 0)
245: bn *= 2;
246: bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
247: (void) spl5();
248: trace("strt",bp);
249: dp = &idcutab[ui->ui_unit];
250: disksort(dp, bp);
251: if (dp->b_active == 0) {
252: trace("!act",dp);
253: (void) idcustart(ui);
254: bp = &ui->ui_mi->um_tab;
255: if (bp->b_actf && bp->b_active == 0)
256: (void) idcstart(ui->ui_mi);
257: }
258: (void) spl0();
259: return;
260:
261: bad:
262: bp->b_flags |= B_ERROR;
263: done:
264: iodone(bp);
265: return;
266: }
267:
268: idcustart(ui)
269: register struct uba_device *ui;
270: {
271: register struct buf *bp, *dp;
272: register struct uba_ctlr *um;
273: register struct idcdevice *idcaddr;
274: register struct idcst *st;
275: union idc_dar cyltrk;
276: daddr_t bn;
277: int unit;
278:
279: if (ui == 0)
280: return (0);
281: dk_busy &= ~(1<<ui->ui_dk);
282: dp = &idcutab[ui->ui_unit];
283: um = ui->ui_mi;
284: unit = ui->ui_slave;
285: trace("ust", dp);
286: idcaddr = (struct idcdevice *)um->um_addr;
287: if (um->um_tab.b_active) {
288: idc_softc.sc_softas |= 1<<unit;
289: trace("umac",idc_softc.sc_softas);
290: return (0);
291: }
292: if ((bp = dp->b_actf) == NULL) {
293: trace("!bp",0);
294: return (0);
295: }
296: if (dp->b_active) {
297: trace("dpac",dp->b_active);
298: goto done;
299: }
300: dp->b_active = 1;
301: /* CHECK DRIVE READY? */
302: bn = bp->b_blkno;
303: trace("seek", bn);
304: if (ui->ui_type == 0)
305: bn *= 2;
306: st = &idcst[ui->ui_type];
307: cyltrk.dar_cyl = bp->b_cylin;
308: cyltrk.dar_trk = (bn / st->nsect) % st->ntrak;
309: cyltrk.dar_sect = 0;
310: printd("idcustart, unit %d, cyltrk 0x%x\n", unit, cyltrk.dar_dar);
311: /*
312: * If on cylinder, no need to seek.
313: */
314: if (cyltrk.dar_dar == idccyl[ui->ui_unit].dar_dar)
315: goto done;
316: /*
317: * RB80 can change heads (tracks) just by loading
318: * the disk address register, perform optimization
319: * here instead of doing a full seek.
320: */
321: if (ui->ui_type && cyltrk.dar_cyl == idccyl[ui->ui_unit].dar_cyl) {
322: idcaddr->idccsr = IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8);
323: idcaddr->idcdar = cyltrk.dar_dar;
324: idccyl[ui->ui_unit].dar_dar = cyltrk.dar_dar;
325: goto done;
326: }
327: /*
328: * Need to do a full seek. Select the unit, clear
329: * its attention bit, set the command, load the
330: * disk address register, and then go.
331: */
332: idcaddr->idccsr =
333: IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8)|(1<<(unit+16));
334: idcaddr->idcdar = cyltrk.dar_dar;
335: idccyl[ui->ui_unit].dar_dar = cyltrk.dar_dar;
336: printd(" seek");
337: idcaddr->idccsr = IDC_IE|IDC_SEEK|(unit<<8);
338: if (ui->ui_dk >= 0) {
339: dk_busy |= 1<<ui->ui_dk;
340: dk_seek[ui->ui_dk]++;
341: }
342: /*
343: * RB80's initiate seeks very quickly. Wait for it
344: * to come ready rather than taking the interrupt.
345: */
346: if (ui->ui_type) {
347: if (idcwait(idcaddr, 10) == 0)
348: return (1);
349: idcaddr->idccsr &= ~IDC_ATTN;
350: /* has the seek completed? */
351: if (idcaddr->idccsr & IDC_DRDY) {
352: printd(", drdy");
353: idcaddr->idccsr =
354: IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8)|(1<<(unit+16));
355: goto done;
356: }
357: }
358: printd(", idccsr = 0x%x\n", idcaddr->idccsr);
359: return (1);
360: done:
361: if (dp->b_active != 2) {
362: trace("!=2",dp->b_active);
363: dp->b_forw = NULL;
364: if (um->um_tab.b_actf == NULL)
365: um->um_tab.b_actf = dp;
366: else {
367: trace("!NUL",um->um_tab.b_actl);
368: um->um_tab.b_actl->b_forw = dp;
369: }
370: um->um_tab.b_actl = dp;
371: dp->b_active = 2;
372: }
373: return (0);
374: }
375:
376: idcstart(um)
377: register struct uba_ctlr *um;
378: {
379: register struct buf *bp, *dp;
380: register struct uba_device *ui;
381: register struct idcdevice *idcaddr;
382: register struct idc_softc *sc;
383: struct idcst *st;
384: daddr_t bn;
385: int sn, tn, cmd;
386:
387: loop:
388: if ((dp = um->um_tab.b_actf) == NULL) {
389: trace("nodp",um);
390: return (0);
391: }
392: if ((bp = dp->b_actf) == NULL) {
393: trace("nobp", dp);
394: um->um_tab.b_actf = dp->b_forw;
395: goto loop;
396: }
397: um->um_tab.b_active = 1;
398: ui = idcdinfo[idcunit(bp->b_dev)];
399: bn = bp->b_blkno;
400: trace("star",bp);
401: if (ui->ui_type == 0)
402: bn *= 2;
403: sc = &idc_softc;
404: st = &idcst[ui->ui_type];
405: sn = bn%st->nspc;
406: tn = sn/st->nsect;
407: sn %= st->nsect;
408: sc->sc_sect = sn;
409: sc->sc_trk = tn;
410: sc->sc_cyl = bp->b_cylin;
411: idcaddr = (struct idcdevice *)ui->ui_addr;
412: printd("idcstart, unit %d, dar 0x%x", ui->ui_slave, sc->sc_dar);
413: if (bp->b_flags & B_READ)
414: cmd = IDC_IE|IDC_READ|(ui->ui_slave<<8);
415: else
416: cmd = IDC_IE|IDC_WRITE|(ui->ui_slave<<8);
417: idcaddr->idccsr = IDC_CRDY|cmd;
418: if ((idcaddr->idccsr&IDC_DRDY) == 0) {
419: printf("rb%d: not ready\n", idcunit(bp->b_dev));
420: um->um_tab.b_active = 0;
421: um->um_tab.b_errcnt = 0;
422: dp->b_actf = bp->av_forw;
423: dp->b_active = 0;
424: bp->b_flags |= B_ERROR;
425: iodone(bp);
426: goto loop;
427: }
428: idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
429: idccyl[ui->ui_unit].dar_sect = 0;
430: sn = (st->nsect - sn) * st->nbps;
431: if (sn > bp->b_bcount)
432: sn = bp->b_bcount;
433: sc->sc_bcnt = sn;
434: sc->sc_resid = bp->b_bcount;
435: sc->sc_unit = ui->ui_slave;
436: printd(", bcr 0x%x, cmd 0x%x\n", sn, cmd);
437: um->um_cmd = cmd;
438: (void) ubago(ui);
439: return (1);
440: }
441:
442: idcdgo(um)
443: register struct uba_ctlr *um;
444: {
445: register struct idcdevice *idcaddr = (struct idcdevice *)um->um_addr;
446: register struct idc_softc *sc = &idc_softc;
447:
448: /*
449: * VERY IMPORTANT: must load registers in this order.
450: */
451: idcaddr->idcbar = sc->sc_ubaddr = um->um_ubinfo&0x3ffff;
452: idcaddr->idcbcr = -sc->sc_bcnt;
453: idcaddr->idcdar = sc->sc_dar;
454: printd("idcdgo, ubinfo 0x%x, cmd 0x%x\n", um->um_ubinfo, um->um_cmd);
455: idcaddr->idccsr = um->um_cmd;
456: trace("go", um);
457: um->um_tab.b_active = 2;
458: /*** CLEAR SPURIOUS ATTN ON R80? ***/
459: }
460:
461: idcintr(idc)
462: int idc;
463: {
464: register struct uba_ctlr *um = idcminfo[idc];
465: register struct uba_device *ui;
466: register struct idcdevice *idcaddr = (struct idcdevice *)um->um_addr;
467: register struct idc_softc *sc = &idc_softc;
468: register struct buf *bp, *dp;
469: struct idcst *st;
470: int unit, as, er, cmd, ds = 0;
471:
472: printd("idcintr, idccsr 0x%x", idcaddr->idccsr);
473: top:
474: idcwticks = 0;
475: trace("intr", um->um_tab.b_active);
476: if (um->um_tab.b_active == 2) {
477: /*
478: * Process a data transfer complete interrupt.
479: */
480: um->um_tab.b_active = 1;
481: dp = um->um_tab.b_actf;
482: bp = dp->b_actf;
483: ui = idcdinfo[idcunit(bp->b_dev)];
484: unit = ui->ui_slave;
485: st = &idcst[ui->ui_type];
486: idcaddr->idccsr = IDC_IE|IDC_CRDY|(unit<<8);
487: if ((er = idcaddr->idccsr) & IDC_ERR) {
488: if (er & IDC_DE) {
489: idcaddr->idcmpr = IDCGS_GETSTAT;
490: idcaddr->idccsr = IDC_GETSTAT|(unit<<8);
491: (void) idcwait(idcaddr, 0);
492: ds = idcaddr->idcmpr;
493: idcaddr->idccsr =
494: IDC_IE|IDC_CRDY|(1<<(unit+16));
495: }
496: printd(", er 0x%x, ds 0x%x", er, ds);
497: if (ds & IDCDS_WL) {
498: printf("rb%d: write locked\n",
499: idcunit(bp->b_dev));
500: bp->b_flags |= B_ERROR;
501: } else if (++um->um_tab.b_errcnt > 28 || er&IDC_HARD) {
502: hard:
503: harderr(bp, "rb");
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: idcread(dev, uio)
670: dev_t dev;
671: struct uio *uio;
672: {
673: register int unit = idcunit(dev);
674:
675: if (unit >= NRB)
676: return (ENXIO);
677: return (physio(idcstrategy, &ridcbuf[unit], dev, B_READ, minphys, uio));
678: }
679:
680: idcwrite(dev, uio)
681: dev_t dev;
682: struct uio *uio;
683: {
684: register int unit = idcunit(dev);
685:
686: if (unit >= NRB)
687: return (ENXIO);
688: return (physio(idcstrategy, &ridcbuf[unit], dev, B_WRITE, minphys, uio));
689: }
690:
691: idcecc(ui)
692: register struct uba_device *ui;
693: {
694: register struct idcdevice *idc = (struct idcdevice *)ui->ui_addr;
695: register struct buf *bp = idcutab[ui->ui_unit].b_actf;
696: register struct uba_ctlr *um = ui->ui_mi;
697: register struct idcst *st;
698: register int i;
699: struct uba_regs *ubp = ui->ui_hd->uh_uba;
700: int bit, byte, mask;
701: caddr_t addr;
702: int reg, npf, o;
703: int cn, tn, sn;
704:
705: npf = btop(idc->idcbcr + idc_softc.sc_bcnt) - 1;;
706: reg = btop(idc_softc.sc_ubaddr) + npf;
707: o = (int)bp->b_un.b_addr & PGOFSET;
708: st = &idcst[ui->ui_type];
709: cn = idc_softc.sc_cyl;
710: tn = idc_softc.sc_trk;
711: sn = idc_softc.sc_sect;
712: um->um_tab.b_active = 1; /* Either complete or continuing... */
713: log(LOG_WARNING, "rb%d%c: soft ecc sn%d\n", idcunit(bp->b_dev),
714: 'a'+(minor(bp->b_dev)&07),
715: (cn*st->ntrak + tn) * st->nsect + sn + npf);
716: mask = idc->idceccpat;
717: i = idc->idceccpos - 1; /* -1 makes 0 origin */
718: bit = i&07;
719: i = (i&~07)>>3;
720: byte = i + o;
721: while (i < 512 && (int)ptob(npf)+i < idc_softc.sc_bcnt && bit > -11) {
722: /*
723: * should be:
724: * addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
725: * (byte & PGOFSET);
726: * but this generates an extzv which hangs the UNIBUS.
727: */
728: addr = ptob(*(int *)&ubp->uba_map[reg+btop(byte)]&0x1fffff)+
729: (byte & PGOFSET);
730: putmemc(addr, getmemc(addr)^(mask<<bit));
731: byte++;
732: i++;
733: bit -= 8;
734: }
735: idc_softc.sc_bcnt += idc->idcbcr;
736: um->um_tab.b_errcnt = 0; /* error has been corrected */
737: return;
738: }
739:
740: idcreset(uban)
741: int uban;
742: {
743: register struct uba_ctlr *um;
744: register struct uba_device *ui;
745: register unit;
746:
747: if ((um = idcminfo[0]) == 0 || um->um_ubanum != uban ||
748: um->um_alive == 0)
749: return;
750: printf(" idc0");
751: um->um_tab.b_active = 0;
752: um->um_tab.b_actf = um->um_tab.b_actl = 0;
753: if (um->um_ubinfo) {
754: printf("<%d>", (um->um_ubinfo>>28)&0xf);
755: um->um_ubinfo = 0;
756: }
757: for (unit = 0; unit < NRB; unit++) {
758: if ((ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0)
759: continue;
760: idcutab[unit].b_active = 0;
761: (void) idcustart(ui);
762: }
763: (void) idcstart(um);
764: }
765:
766: idcwatch()
767: {
768: register struct uba_ctlr *um;
769: register unit;
770:
771: timeout(idcwatch, (caddr_t)0, hz);
772: um = idcminfo[0];
773: if (um == 0 || um->um_alive == 0)
774: return;
775: if (um->um_tab.b_active == 0) {
776: for (unit = 0; unit < NRB; unit++)
777: if (idcutab[unit].b_active)
778: goto active;
779: idcwticks = 0;
780: return;
781: }
782: active:
783: idcwticks++;
784: if (idcwticks >= 20) {
785: idcwticks = 0;
786: printf("idc0: lost interrupt\n");
787: idcintr(0);
788: }
789: }
790:
791: /*ARGSUSED*/
792: idcdump(dev)
793: dev_t dev;
794: {
795: struct idcdevice *idcaddr;
796: char *start;
797: int num, blk, unit;
798: struct size *sizes;
799: register struct uba_regs *uba;
800: register struct uba_device *ui;
801: struct idcst *st;
802: union idc_dar dar;
803: int nspg;
804:
805: unit = idcunit(dev);
806: if (unit >= NRB)
807: return (ENXIO);
808: #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
809: ui = phys(struct uba_device *, idcdinfo[unit]);
810: if (ui->ui_alive == 0)
811: return (ENXIO);
812: uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
813: ubainit(uba);
814: idcaddr = (struct idcdevice *)ui->ui_physaddr;
815: if (idcwait(idcaddr, 100) == 0)
816: return (EFAULT);
817: /*
818: * Since we can only transfer one track at a time, and
819: * the rl02 has 256 byte sectors, all the calculations
820: * are done in terms of physical sectors (i.e. num and blk
821: * are in sectors not NBPG blocks.
822: */
823: st = phys(struct idcst *, &idcst[ui->ui_type]);
824: sizes = phys(struct size *, st->sizes);
825: if (dumplo < 0)
826: return (EINVAL);
827: if (dumplo + maxfree >= sizes[minor(dev)&07].nblocks)
828: num = sizes[minor(dev)&07].nblocks - dumplo;
829: nspg = NBPG / st->nbps;
830: num = num * nspg;
831: start = 0;
832:
833: while (num > 0) {
834: register struct pte *io;
835: register int i;
836: daddr_t bn;
837:
838: bn = (dumplo + btop(start)) * nspg;
839: dar.dar_cyl = bn / st->nspc + sizes[minor(dev)&07].cyloff;
840: bn %= st->nspc;
841: dar.dar_trk = bn / st->nsect;
842: dar.dar_sect = bn % st->nsect;
843: blk = st->nsect - dar.dar_sect;
844: if (num < blk)
845: blk = num;
846:
847: io = uba->uba_map;
848: for (i = 0; i < (blk + nspg - 1) / nspg; i++)
849: *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
850: *(int *)io = 0;
851:
852: idcaddr->idccsr = IDC_CRDY | IDC_SEEK | unit<<8;
853: if ((idcaddr->idccsr&IDC_DRDY) == 0)
854: return (EFAULT);
855: idcaddr->idcdar = dar.dar_dar;
856: idcaddr->idccsr = IDC_SEEK | unit << 8;
857: while ((idcaddr->idccsr & (IDC_CRDY|IDC_DRDY))
858: != (IDC_CRDY|IDC_DRDY))
859: ;
860: if (idcaddr->idccsr & IDC_ERR) {
861: printf("rb%d: seek, csr=%b\n",
862: unit, idcaddr->idccsr, IDCCSR_BITS);
863: return (EIO);
864: }
865:
866: idcaddr->idccsr = IDC_CRDY | IDC_WRITE | unit<<8;
867: if ((idcaddr->idccsr&IDC_DRDY) == 0)
868: return (EFAULT);
869: idcaddr->idcbar = 0; /* start addr 0 */
870: idcaddr->idcbcr = - (blk * st->nbps);
871: idcaddr->idcdar = dar.dar_dar;
872: idcaddr->idccsr = IDC_WRITE | unit << 8;
873: while ((idcaddr->idccsr & (IDC_CRDY|IDC_DRDY))
874: != (IDC_CRDY|IDC_DRDY))
875: ;
876: if (idcaddr->idccsr & IDC_ERR) {
877: printf("rb%d: write, csr=%b\n",
878: unit, idcaddr->idccsr, IDCCSR_BITS);
879: return (EIO);
880: }
881:
882: start += blk * st->nbps;
883: num -= blk;
884: }
885: return (0);
886: }
887:
888: idcsize(dev)
889: dev_t dev;
890: {
891: int unit = idcunit(dev);
892: struct uba_device *ui;
893: struct idcst *st;
894:
895: if (unit >= NRB || (ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0)
896: return (-1);
897: st = &idcst[ui->ui_type];
898: return (st->sizes[minor(dev) & 07].nblocks);
899: }
900: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.