|
|
1.1 root 1: /* mt.c 1.2 81/10/27 */
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(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(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(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(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(bp->b_blkno))
253: mtaddr->mtncs[MUUNIT(bp->b_dev)] =
254: (min(dbtofsb(bp->b_blkno) - blkno, 0377)<<8)| MT_SFORW|MT_GO;
255: else
256: mtaddr->mtncs[MUUNIT(bp->b_dev)] =
257: (min(blkno - dbtofsb(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(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: printf("mt: unit %d random interrupt\n", unit);
375: return (MBN_SKIP);
376: }
377: if (bp == 0)
378: return (MBN_SKIP);
379: fc = (mtaddr->mtncs[unit] >> 8) & 0xff;
380: sc = &mu_softc[unit];
381: sc->sc_erreg = er;
382: sc->sc_resid = fc;
383: switch (er & MTER_INTCODE) {
384: case MTER_DONE:
385: if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
386: done:
387: if (bp->b_command == MT_SENSE)
388: sc->sc_dsreg = MASKREG(mtaddr->mtds);
389: bp->b_resid = fc;
390: return (MBN_DONE);
391: }
392: /* this is UGLY! (but is it correct?) */
393: if ((fc = dbtofsb(bp->b_blkno) - sc->sc_blkno) < 0)
394: sc->sc_blkno -= min(0377, -fc);
395: else
396: sc->sc_blkno += min(0377, fc);
397: return (MBN_RETRY);
398:
399: case MTER_RWDING:
400: return (MBN_SKIP); /* ignore "rewind started" interrupt */
401:
402: case MTER_NOTCAP:
403: printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
404:
405: case MTER_TM:
406: case MTER_EOT:
407: case MTER_LEOT:
408: if (sc->sc_blkno > dbtofsb(bp->b_blkno)) {
409: sc->sc_nxrec = dbtofsb(bp->b_blkno) + fc;
410: sc->sc_blkno = sc->sc_nxrec;
411: } else {
412: sc->sc_blkno = dbtofsb(bp->b_blkno) - fc;
413: sc->sc_nxrec = sc->sc_blkno - 1;
414: }
415: return (MBN_RETRY);
416:
417: case MTER_FPT:
418: printf("mu%d: no write ring\n", MUUNIT(bp->b_dev));
419: bp->b_flags |= B_ERROR;
420: return (MBN_DONE);
421:
422: case MTER_OFFLINE:
423: if (sc->sc_openf > 0) {
424: sc->sc_openf = -1;
425: printf("mu%d: offline\n", MUUNIT(bp->b_dev));
426: }
427: bp->b_flags |= B_ERROR;
428: return (MBN_DONE);
429:
430: case MTER_BOT:
431: if (bp == &cmtbuf[MTUNIT(bp->b_dev)])
432: goto done;
433: /* FALL THROUGH */
434:
435: default:
436: printf("mu%d: hard error bn%d er=%o ds=%b\n",
437: MUUNIT(bp->b_dev), bp->b_blkno,
438: sc->sc_erreg, sc->sc_dsreg, mtds_bits);
439: mtaddr->mtid = MTID_CLR; /* reset the TM78 */
440: DELAY(250);
441: while ((mtaddr->mtid & MTID_RDY) == 0) /* wait for it */
442: ;
443: bp->b_flags |= B_ERROR;
444: return (MBN_DONE);
445: }
446: /* NOTREACHED */
447: }
448:
449: mtread(dev)
450: dev_t dev;
451: {
452:
453: mtphys(dev);
454: if (u.u_error)
455: return;
456: physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys);
457: }
458:
459: mtwrite(dev)
460: {
461:
462: mtphys(dev);
463: if (u.u_error)
464: return;
465: physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys);
466: }
467:
468: mtphys(dev)
469: dev_t dev;
470: {
471: register int mtunit;
472: register struct mu_softc *sc;
473: register struct mba_device *mi;
474: daddr_t a;
475:
476: mtunit = MTUNIT(dev);
477: if (mtunit >= NMT || (mi = mtinfo[mtunit]) == 0 || mi->mi_alive == 0) {
478: u.u_error = ENXIO;
479: return;
480: }
481: a = u.u_offset >> 9;
482: sc = &mu_softc[MUUNIT(dev)];
483: sc->sc_blkno = dbtofsb(a);
484: sc->sc_nxrec = dbtofsb(a)+1;
485: }
486:
487: /*ARGSUSED*/
488: mtioctl(dev, cmd, addr, flag)
489: dev_t dev;
490: int cmd;
491: caddr_t addr;
492: int flag;
493: {
494: register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
495: register struct buf *bp = &cmtbuf[MTUNIT(dev)];
496: register callcount;
497: register int n, op;
498: int fcount;
499: struct mtop mtop;
500: struct mtget mtget;
501: /* we depend of the values and order of the MT codes here */
502: static mtops[] =
503: {MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE};
504:
505: switch (cmd) {
506: case MTIOCTOP: /* tape operation */
507: if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
508: u.u_error = EFAULT;
509: return;
510: }
511: switch(mtop.mt_op) {
512: case MTWEOF:
513: callcount = mtop.mt_count;
514: fcount = 1;
515: break;
516: case MTFSF: case MTBSF:
517: callcount = mtop.mt_count;
518: fcount = 1;
519: break;
520: case MTFSR: case MTBSR:
521: callcount = 1;
522: fcount = mtop.mt_count;
523: break;
524: case MTREW: case MTOFFL:
525: callcount = 1;
526: fcount = 1;
527: break;
528: default:
529: u.u_error = ENXIO;
530: return;
531: }
532: if (callcount <= 0 || fcount <= 0) {
533: u.u_error = ENXIO;
534: return;
535: }
536: op = mtops[mtop.mt_op];
537: if (op == MT_WTM)
538: op |= sc->sc_dens;
539: while (--callcount >= 0) {
540: register int n;
541:
542: do {
543: n = min(fcount, 0xff);
544: mtcommand(dev, op, n);
545: fcount -= n;
546: } while (fcount);
547: if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) &&
548: bp->b_resid) {
549: u.u_error = EIO;
550: break;
551: }
552: if (bp->b_flags&B_ERROR)
553: break;
554: }
555: geterror(bp);
556: return;
557: case MTIOCGET:
558: mtget.mt_erreg = sc->sc_erreg;
559: mtget.mt_resid = sc->sc_resid;
560: mtcommand(dev, MT_SENSE, 1); /* update drive status */
561: mtget.mt_dsreg = sc->sc_dsreg;
562: mtget.mt_type = MT_ISMT;
563: if (copyout((caddr_t)&mtget, addr, sizeof(mtget)))
564: u.u_error = EFAULT;
565: return;
566: default:
567: u.u_error = ENXIO;
568: }
569: }
570:
571: #define DBSIZE 20
572:
573: mtdump()
574: {
575: register struct mba_device *mi;
576: register struct mba_regs *mp;
577: register struct mtdevice *mtaddr;
578: int blk, num;
579: int start;
580:
581: start = 0;
582: num = maxfree;
583: #define phys(a,b) ((b)((int)(a)&0x7fffffff))
584: if (mtinfo[0] == 0)
585: return (ENXIO);
586: mi = phys(mtinfo[0], struct mba_device *);
587: mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
588: mp->mba_cr = MBCR_IE;
589: mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive];
590: #ifdef notyet
591: mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI;
592: mtaddr->mtcs1 = MT_DCLR|MT_GO;
593: while (num > 0) {
594: blk = num > DBSIZE ? DBSIZE : num;
595: mtdwrite(start, blk, mtaddr, mp);
596: start += blk;
597: num -= blk;
598: }
599: mteof(mtaddr);
600: mteof(mtaddr);
601: mtwait(mtaddr);
602: if (mtaddr->mtds&MTDS_ERR)
603: return (EIO);
604: mtaddr->mtcs1 = MT_REW|MT_GO;
605: return (0);
606: }
607:
608: mtdwrite(dbuf, num, mtaddr, mp)
609: register dbuf, num;
610: register struct mtdevice *mtaddr;
611: struct mba_regs *mp;
612: {
613: register struct pte *io;
614: register int i;
615:
616: mtwait(mtaddr);
617: io = mp->mba_map;
618: for (i = 0; i < num; i++)
619: *(int *)io++ = dbuf++ | PG_V;
620: mtaddr->mtfc = -(num*NBPG);
621: mp->mba_sr = -1;
622: mp->mba_bcr = -(num*NBPG);
623: mp->mba_var = 0;
624: mtaddr->mtcs1 = MT_WCOM|MT_GO;
625: }
626:
627: mtwait(mtaddr)
628: struct mtdevice *mtaddr;
629: {
630: register s;
631:
632: do
633: s = mtaddr->mtds;
634: while ((s & MTDS_DRY) == 0);
635: }
636:
637: mteof(mtaddr)
638: struct mtdevice *mtaddr;
639: {
640:
641: mtwait(mtaddr);
642: mtaddr->mtcs1 = MT_WEOF|MT_GO;
643: #endif notyet
644: }
645: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.