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