|
|
1.1 root 1: /* %M% %I% %E% */
2:
3: #include "mu.h"
4: #if NMT > 0
5: /*
6: * TM78/TU78 tape driver
7: *
8: * Behavior in complex error situations is uncertain...
9: *
10: * TODO:
11: * test error recovery
12: * add odd byte count kludge from VMS driver
13: * write dump routine
14: */
15: #include "../h/param.h"
16: #include "../h/systm.h"
17: #include "../h/buf.h"
18: #include "../h/conf.h"
19: #include "../h/dir.h"
20: #include "../h/file.h"
21: #include "../h/user.h"
22: #include "../h/map.h"
23: #include "../h/pte.h"
24: #include "../h/mbareg.h"
25: #include "../h/mbavar.h"
26: #include "../h/mtio.h"
27: #include "../h/ioctl.h"
28: #include "../h/cmap.h"
29: #include "../h/cpu.h"
30:
31: #include "../h/mtreg.h"
32:
33: struct buf rmtbuf[NMT];
34: struct buf cmtbuf[NMT];
35:
36: short mttypes[] =
37: { MBDT_TU78, 0 };
38: struct mba_device *mtinfo[NMT];
39: int mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint();
40: struct mba_driver mtdriver =
41: { mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint,
42: mttypes, "mt", "mu", mtinfo };
43:
44: #define MASKREG(r) ((r) & 0xffff)
45:
46: /* bits in minor device */
47: #define MUUNIT(dev) (minor(dev)&03)
48: #define H_NOREWIND 04
49: #define H_6250BPI 08
50:
51: #define MTUNIT(dev) (mutomt[MUUNIT(dev)])
52:
53: #define INF (daddr_t)1000000L /* a block number that wont exist */
54:
55: struct mu_softc {
56: char sc_openf;
57: char sc_flags;
58: daddr_t sc_blkno;
59: daddr_t sc_nxrec;
60: u_short sc_erreg;
61: u_short sc_dsreg;
62: short sc_resid;
63: short sc_dens;
64: struct mba_device *sc_mi;
65: int sc_slave;
66: } mu_softc[NMU];
67: short mutomt[NMU];
68:
69: /*
70: * Bits for sc_flags.
71: */
72: #define H_WRITTEN 1 /* last operation was a write */
73:
74: char mtds_bits[] = MTDS_BITS;
75:
76: /*ARGSUSED*/
77: mtattach(mi)
78: struct mba_device *mi;
79: {
80:
81: }
82:
83: mtslave(mi, ms)
84: struct mba_device *mi;
85: struct mba_slave *ms;
86: {
87: register struct mu_softc *sc = &mu_softc[ms->ms_unit];
88: register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
89: int s = spl7(), rtn = 0;
90:
91: mtaddr->mtas = -1;
92: mtaddr->mtncs[ms->ms_slave] = MT_SENSE|MT_GO;
93: while (mtaddr->mtas == 0)
94: ;
95: if ((mtaddr->mtner & MTER_INTCODE) == MTER_DONE &&
96: (mtaddr->mtds & MTDS_PRES)) {
97: sc->sc_mi = mi;
98: sc->sc_slave = ms->ms_slave;
99: mutomt[ms->ms_unit] = mi->mi_unit;
100: rtn = 1;
101: }
102: mtaddr->mtas = mtaddr->mtas;
103: splx(s);
104: return (rtn);
105: }
106:
107: mtopen(dev, flag)
108: dev_t dev;
109: int flag;
110: {
111: register int muunit;
112: register struct mba_device *mi;
113: register struct mu_softc *sc;
114: int olddens, dens;
115:
116: muunit = MUUNIT(dev);
117: if (muunit >= NMU || (sc = &mu_softc[muunit])->sc_openf ||
118: (mi = mtinfo[MTUNIT(dev)]) == 0 || mi->mi_alive == 0) {
119: u.u_error = ENXIO;
120: return;
121: }
122: olddens = sc->sc_dens;
123: dens = sc->sc_dens = (minor(dev)&H_6250BPI) ? MT_GCR : 0;
124: mtcommand(dev, MT_SENSE, 1);
125: sc->sc_dens = olddens;
126: if ((sc->sc_dsreg & MTDS_ONL) == 0) {
127: uprintf("mu%d: not online\n", muunit);
128: u.u_error = EIO;
129: return;
130: }
131: if ((flag&FWRITE) && (sc->sc_dsreg&MTDS_FPT)) {
132: uprintf("mu%d: no write ring\n", muunit);
133: u.u_error = EIO;
134: return;
135: }
136: if ((sc->sc_dsreg & MTDS_BOT) == 0 && (flag&FWRITE) &&
137: dens != sc->sc_dens) {
138: uprintf("mu%d: can't change density in mid-tape\n", muunit);
139: u.u_error = EIO;
140: return;
141: }
142: sc->sc_openf = 1;
143: sc->sc_blkno = (daddr_t)0;
144: sc->sc_nxrec = INF;
145: sc->sc_flags = 0;
146: sc->sc_dens = dens;
147: }
148:
149: mtclose(dev, flag)
150: register dev_t dev;
151: register flag;
152: {
153: register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
154:
155: if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN)))
156: mtcommand(dev, MT_CLS|sc->sc_dens, 1);
157: if ((minor(dev)&H_NOREWIND) == 0)
158: mtcommand(dev, MT_REW, 0);
159: sc->sc_openf = 0;
160: }
161:
162: mtcommand(dev, com, count)
163: dev_t dev;
164: int com, count;
165: {
166: register struct buf *bp;
167:
168: bp = &cmtbuf[MTUNIT(dev)];
169: (void) spl5();
170: while (bp->b_flags&B_BUSY) {
171: if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE))
172: break;
173: bp->b_flags |= B_WANTED;
174: sleep((caddr_t)bp, PRIBIO);
175: }
176: bp->b_flags = B_BUSY|B_READ;
177: (void) spl0();
178: bp->b_dev = dev;
179: bp->b_command = com;
180: bp->b_repcnt = count;
181: bp->b_blkno = 0;
182: mtstrategy(bp);
183: if (count == 0)
184: return;
185: iowait(bp);
186: if (bp->b_flags&B_WANTED)
187: wakeup((caddr_t)bp);
188: bp->b_flags &= B_ERROR;
189: }
190:
191: mtstrategy(bp)
192: register struct buf *bp;
193: {
194: register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)];
195: register struct buf *dp;
196:
197: bp->av_forw = NULL;
198: dp = &mi->mi_tab;
199: (void) spl5();
200: if (dp->b_actf == NULL)
201: dp->b_actf = bp;
202: else
203: dp->b_actl->av_forw = bp;
204: dp->b_actl = bp;
205: if (dp->b_active == 0)
206: mbustart(mi);
207: (void) spl0();
208: }
209:
210: mtustart(mi)
211: register struct mba_device *mi;
212: {
213: register struct mtdevice *mtaddr =
214: (struct mtdevice *)mi->mi_drv;
215: register struct buf *bp = mi->mi_tab.b_actf;
216: register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
217: daddr_t blkno;
218:
219: sc->sc_flags &= ~H_WRITTEN;
220: if (sc->sc_openf < 0) {
221: bp->b_flags |= B_ERROR;
222: return (MBU_NEXT);
223: }
224: if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) {
225: if (dbtofsb(0,bp->b_blkno) > sc->sc_nxrec) {
226: bp->b_flags |= B_ERROR;
227: bp->b_error = ENXIO;
228: return (MBU_NEXT);
229: }
230: if (dbtofsb(0,bp->b_blkno) == sc->sc_nxrec &&
231: bp->b_flags&B_READ) {
232: bp->b_resid = bp->b_bcount;
233: clrbuf(bp);
234: return (MBU_NEXT);
235: }
236: if ((bp->b_flags&B_READ)==0)
237: sc->sc_nxrec = dbtofsb(0,bp->b_blkno) + 1;
238: } else {
239: mtaddr->mtncs[MUUNIT(bp->b_dev)] =
240: (bp->b_repcnt<<8)|bp->b_command|MT_GO;
241: return (MBU_STARTED);
242: }
243: if ((blkno = sc->sc_blkno) == dbtofsb(0,bp->b_blkno)) {
244: if (mi->mi_tab.b_errcnt == 2) {
245: mtaddr->mtca = MUUNIT(bp->b_dev);
246: } else {
247: mtaddr->mtbc = bp->b_bcount;
248: mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev);
249: }
250: return (MBU_DODATA);
251: }
252: if (blkno < dbtofsb(0,bp->b_blkno))
253: mtaddr->mtncs[MUUNIT(bp->b_dev)] =
254: (min(dbtofsb(0,bp->b_blkno) - blkno, 0377)<<8)| MT_SFORW|MT_GO;
255: else
256: mtaddr->mtncs[MUUNIT(bp->b_dev)] =
257: (min(blkno - dbtofsb(0,bp->b_blkno), 0377)<<8)| MT_SREV|MT_GO;
258: return (MBU_STARTED);
259: }
260:
261: mtstart(mi)
262: register struct mba_device *mi;
263: {
264: register struct buf *bp = mi->mi_tab.b_actf;
265: register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
266:
267: if (bp->b_flags & B_READ)
268: if (mi->mi_tab.b_errcnt == 2)
269: return(MT_READREV|MT_GO);
270: else
271: return(MT_READ|MT_GO);
272: else
273: return(MT_WRITE|sc->sc_dens|MT_GO);
274: }
275:
276: mtdtint(mi, mbsr)
277: register struct mba_device *mi;
278: int mbsr;
279: {
280: register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
281: register struct buf *bp = mi->mi_tab.b_actf;
282: register struct mu_softc *sc;
283:
284: /* I'M NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */
285: if ((mtaddr->mtca&3) != MUUNIT(bp->b_dev)) {
286: printf("mt: wrong unit!\n");
287: mtaddr->mtca = MUUNIT(bp->b_dev);
288: }
289: sc = &mu_softc[MUUNIT(bp->b_dev)];
290: sc->sc_erreg = mtaddr->mter;
291: if((bp->b_flags & B_READ) == 0)
292: sc->sc_flags |= H_WRITTEN;
293: switch (sc->sc_erreg & MTER_INTCODE) {
294: case MTER_DONE:
295: case MTER_LONGREC:
296: if (mi->mi_tab.b_errcnt != 2)
297: sc->sc_blkno++;
298: bp->b_resid = 0;
299: break;
300:
301: case MTER_NOTCAP:
302: printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
303: goto err;
304:
305: case MTER_TM:
306: case MTER_EOT:
307: sc->sc_blkno++;
308: err:
309: bp->b_resid = bp->b_bcount;
310: sc->sc_nxrec = dbtofsb(0,bp->b_blkno);
311: break;
312:
313: case MTER_SHRTREC:
314: sc->sc_blkno++;
315: if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
316: bp->b_flags |= B_ERROR;
317: if (mi->mi_tab.b_errcnt == 2)
318: bp->b_bcount = bp->b_resid; /* restore saved value */
319: bp->b_resid = bp->b_bcount - mtaddr->mtbc;
320: break;
321:
322: case MTER_RDOPP:
323: mi->mi_tab.b_errcnt = 2; /* indicate "read opposite" */
324: bp->b_resid = bp->b_bcount; /* save it */
325: bp->b_bcount = mtaddr->mtbc; /* use this instead */
326: return(MBD_RETRY);
327:
328: case MTER_RETRY:
329: mi->mi_tab.b_errcnt = 1; /* indicate simple retry */
330: return(MBD_RETRY);
331:
332: case MTER_OFFLINE:
333: if (sc->sc_openf > 0) {
334: sc->sc_openf = -1;
335: printf("mu%d: offline\n", MUUNIT(bp->b_dev));
336: }
337: bp->b_flags |= B_ERROR;
338: break;
339:
340: case MTER_FPT:
341: printf("mu%d: no write ring\n", MUUNIT(bp->b_dev));
342: bp->b_flags |= B_ERROR;
343: break;
344:
345: default:
346: printf("mu%d: hard error bn%d mbsr=%b er=%x ds=%b\n",
347: MUUNIT(bp->b_dev), bp->b_blkno,
348: mbsr, mbsr_bits, sc->sc_erreg,
349: sc->sc_dsreg, mtds_bits);
350: bp->b_flags |= B_ERROR;
351: mtaddr->mtid = MTID_CLR; /* reset the TM78 */
352: DELAY(250);
353: while ((mtaddr->mtid & MTID_RDY) == 0) /* wait for it */
354: ;
355: return (MBD_DONE);
356: }
357: /* CHECK FOR MBA ERROR WHEN NO OTHER ERROR INDICATED? */
358: return (MBD_DONE);
359: }
360:
361: mtndtint(mi)
362: register struct mba_device *mi;
363: {
364: register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
365: register struct buf *bp = mi->mi_tab.b_actf;
366: register struct mu_softc *sc;
367: int er, fc, unit;
368:
369: unit = (mtaddr->mtner >> 8) & 3;
370: er = MASKREG(mtaddr->mtner);
371: /* WILL THIS OCCUR IF ANOTHER DRIVE COMES ONLINE? */
372: if (bp == 0 || unit != MUUNIT(bp->b_dev)) { /* consistency check */
373: if ((er & MTER_INTCODE) != MTER_ONLINE) {
374: static time_t lastmsg;
375: if (time > lastmsg + 180) {
376: printf("mt: unit %d random interrupt\n", unit);
377: lastmsg = time;
378: }
379: return (MBN_SKIP);
380: }
381: }
382: if (bp == 0)
383: return (MBN_SKIP);
384: fc = (mtaddr->mtncs[unit] >> 8) & 0xff;
385: sc = &mu_softc[unit];
386: sc->sc_erreg = er;
387: sc->sc_resid = fc;
388: switch (er & MTER_INTCODE) {
389: case MTER_DONE:
390: if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
391: done:
392: if (bp->b_command == MT_SENSE)
393: sc->sc_dsreg = MASKREG(mtaddr->mtds);
394: bp->b_resid = fc;
395: return (MBN_DONE);
396: }
397: /* this is UGLY! (but is it correct?) */
398: if ((fc = dbtofsb(0,bp->b_blkno) - sc->sc_blkno) < 0)
399: sc->sc_blkno -= min(0377, -fc);
400: else
401: sc->sc_blkno += min(0377, fc);
402: return (MBN_RETRY);
403:
404: case MTER_RWDING:
405: return (MBN_SKIP); /* ignore "rewind started" interrupt */
406:
407: case MTER_NOTCAP:
408: printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
409:
410: case MTER_TM:
411: case MTER_EOT:
412: case MTER_LEOT:
413: if (sc->sc_blkno > dbtofsb(0,bp->b_blkno)) {
414: sc->sc_nxrec = dbtofsb(0,bp->b_blkno) + fc;
415: sc->sc_blkno = sc->sc_nxrec;
416: } else {
417: sc->sc_blkno = dbtofsb(0,bp->b_blkno) - fc;
418: sc->sc_nxrec = sc->sc_blkno - 1;
419: }
420: return (MBN_RETRY);
421:
422: case MTER_FPT:
423: printf("mu%d: no write ring\n", MUUNIT(bp->b_dev));
424: bp->b_flags |= B_ERROR;
425: return (MBN_DONE);
426:
427: case MTER_OFFLINE:
428: if (sc->sc_openf > 0) {
429: sc->sc_openf = -1;
430: printf("mu%d: offline\n", MUUNIT(bp->b_dev));
431: }
432: bp->b_flags |= B_ERROR;
433: return (MBN_DONE);
434:
435: case MTER_BOT:
436: if (bp == &cmtbuf[MTUNIT(bp->b_dev)])
437: goto done;
438: /* FALL THROUGH */
439:
440: default:
441: printf("mu%d: hard error bn%d er=%o ds=%b\n",
442: MUUNIT(bp->b_dev), bp->b_blkno,
443: sc->sc_erreg, sc->sc_dsreg, mtds_bits);
444: mtaddr->mtid = MTID_CLR; /* reset the TM78 */
445: DELAY(250);
446: while ((mtaddr->mtid & MTID_RDY) == 0) /* wait for it */
447: ;
448: bp->b_flags |= B_ERROR;
449: return (MBN_DONE);
450: }
451: /* NOTREACHED */
452: }
453:
454: mtread(dev)
455: dev_t dev;
456: {
457:
458: mtphys(dev);
459: if (u.u_error)
460: return;
461: physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys);
462: }
463:
464: mtwrite(dev)
465: {
466:
467: mtphys(dev);
468: if (u.u_error)
469: return;
470: physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys);
471: }
472:
473: mtphys(dev)
474: dev_t dev;
475: {
476: register int mtunit;
477: register struct mu_softc *sc;
478: register struct mba_device *mi;
479: daddr_t a;
480:
481: mtunit = MTUNIT(dev);
482: if (mtunit >= NMT || (mi = mtinfo[mtunit]) == 0 || mi->mi_alive == 0) {
483: u.u_error = ENXIO;
484: return;
485: }
486: a = u.u_offset >> 9;
487: sc = &mu_softc[MUUNIT(dev)];
488: sc->sc_blkno = dbtofsb(0,a);
489: sc->sc_nxrec = dbtofsb(0,a)+1;
490: }
491:
492: /*ARGSUSED*/
493: mtioctl(dev, cmd, addr, flag)
494: dev_t dev;
495: int cmd;
496: caddr_t addr;
497: int flag;
498: {
499: register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
500: register struct buf *bp = &cmtbuf[MTUNIT(dev)];
501: register callcount;
502: register int n, op;
503: int fcount;
504: struct mtop mtop;
505: struct mtget mtget;
506: /* we depend of the values and order of the MT codes here */
507: static mtops[] =
508: {MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE};
509:
510: switch (cmd) {
511: case MTIOCTOP: /* tape operation */
512: if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
513: u.u_error = EFAULT;
514: return;
515: }
516: switch(mtop.mt_op) {
517: case MTWEOF:
518: callcount = mtop.mt_count;
519: fcount = 1;
520: break;
521: case MTFSF: case MTBSF:
522: callcount = mtop.mt_count;
523: fcount = 1;
524: break;
525: case MTFSR: case MTBSR:
526: callcount = 1;
527: fcount = mtop.mt_count;
528: break;
529: case MTREW: case MTOFFL:
530: callcount = 1;
531: fcount = 1;
532: break;
533: default:
534: u.u_error = ENXIO;
535: return;
536: }
537: if (callcount <= 0 || fcount <= 0) {
538: u.u_error = ENXIO;
539: return;
540: }
541: op = mtops[mtop.mt_op];
542: if (op == MT_WTM)
543: op |= sc->sc_dens;
544: while (--callcount >= 0) {
545: register int n;
546:
547: do {
548: n = min(fcount, 0xff);
549: mtcommand(dev, op, n);
550: fcount -= n;
551: } while (fcount);
552: if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) &&
553: bp->b_resid) {
554: u.u_error = EIO;
555: break;
556: }
557: if (bp->b_flags&B_ERROR)
558: break;
559: }
560: geterror(bp);
561: return;
562: case MTIOCGET:
563: mtget.mt_erreg = sc->sc_erreg;
564: mtget.mt_resid = sc->sc_resid;
565: mtcommand(dev, MT_SENSE, 1); /* update drive status */
566: mtget.mt_dsreg = sc->sc_dsreg;
567: mtget.mt_type = MT_ISMT;
568: if (copyout((caddr_t)&mtget, addr, sizeof(mtget)))
569: u.u_error = EFAULT;
570: return;
571: default:
572: u.u_error = ENXIO;
573: }
574: }
575:
576: #define DBSIZE 20
577:
578: mtdump()
579: {
580: register struct mba_device *mi;
581: register struct mba_regs *mp;
582: register struct mtdevice *mtaddr;
583: int blk, num;
584: int start;
585:
586: start = 0;
587: num = maxfree;
588: #define phys(a,b) ((b)((int)(a)&0x7fffffff))
589: if (mtinfo[0] == 0)
590: return (ENXIO);
591: mi = phys(mtinfo[0], struct mba_device *);
592: mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
593: mp->mba_cr = MBCR_IE;
594: mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive];
595: #ifdef notyet
596: mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI;
597: mtaddr->mtcs1 = MT_DCLR|MT_GO;
598: while (num > 0) {
599: blk = num > DBSIZE ? DBSIZE : num;
600: mtdwrite(start, blk, mtaddr, mp);
601: start += blk;
602: num -= blk;
603: }
604: mteof(mtaddr);
605: mteof(mtaddr);
606: mtwait(mtaddr);
607: if (mtaddr->mtds&MTDS_ERR)
608: return (EIO);
609: mtaddr->mtcs1 = MT_REW|MT_GO;
610: return (0);
611: }
612:
613: mtdwrite(dbuf, num, mtaddr, mp)
614: register dbuf, num;
615: register struct mtdevice *mtaddr;
616: struct mba_regs *mp;
617: {
618: register struct pte *io;
619: register int i;
620:
621: mtwait(mtaddr);
622: io = mp->mba_map;
623: for (i = 0; i < num; i++)
624: *(int *)io++ = dbuf++ | PG_V;
625: mtaddr->mtfc = -(num*NBPG);
626: mp->mba_sr = -1;
627: mp->mba_bcr = -(num*NBPG);
628: mp->mba_var = 0;
629: mtaddr->mtcs1 = MT_WCOM|MT_GO;
630: }
631:
632: mtwait(mtaddr)
633: struct mtdevice *mtaddr;
634: {
635: register s;
636:
637: do
638: s = mtaddr->mtds;
639: while ((s & MTDS_DRY) == 0);
640: }
641:
642: mteof(mtaddr)
643: struct mtdevice *mtaddr;
644: {
645:
646: mtwait(mtaddr);
647: mtaddr->mtcs1 = MT_WEOF|MT_GO;
648: #endif notyet
649: }
650: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.