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