|
|
1.1 root 1: /*
2: * TM78/TU78 tape driver
3: *
4: * TODO:
5: * multiple drives per formatter might work, but are untested
6: */
7: #include "sys/param.h"
8: #include "sys/buf.h"
9: #include "sys/conf.h"
10: #include "sys/file.h"
11: #include "sys/user.h"
12: #include "sys/mbaddr.h"
13: #include "sys/mbsts.h"
14: #include "sys/subaddr.h"
15: #include "sys/mtio.h"
16: #include "sys/tu78.h"
17:
18: /*
19: * hardware stuff
20: */
21:
22: struct device {
23: int mtcs; /* control/status */
24: int mter; /* error */
25: int mtca; /* command address, rec cnt, skp cnt */
26: int mtmr1; /* maint */
27: int mtas; /* attention summary */
28: int mtbc; /* byte count */
29: int mtdt; /* drive type */
30: int mtds; /* drive status */
31: int mtsn; /* serial number */
32: int mtmr2; /* maint */
33: int mtmr3; /* maint */
34: int mtner; /* non-data transfer error */
35: int mtncs[TM78DRIVES]; /* non-data transfer command */
36: int mtia; /* internal address */
37: int mtid; /* internal data */
38: };
39:
40: /* mtcs */
41: #define MT_GO 000001 /* go bit */
42: #define MT_GCR 000002 /* make generic ops GCR ops */
43: #define MT_UNLOAD 000004 /* unload tape */
44: #define MT_REW 000006 /* rewind */
45: #define MT_SENSE 000010 /* sense */
46: #define MT_WTM 000014 /* generic write tape mark */
47: #define MT_SFORW 000020 /* space forward record */
48: #define MT_SREV 000022 /* space reverse record */
49: #define MT_SFORWF 000024 /* space forward file */
50: #define MT_SREVF 000026 /* space reverse file */
51: #define MT_CLS 000040 /* generic close file */
52: #define MT_WRITE 000060 /* generic write */
53: #define MT_READ 000070 /* read forward */
54: #define MT_READREV 000076 /* read reverse */
55:
56: /* mtds */
57: #define MTDS_PRES 0040000 /* tape unit has power */
58: #define MTDS_ONL 0020000 /* online */
59: #define MTDS_PE 0004000 /* tape set for phase encoded */
60: #define MTDS_BOT 0002000 /* tape at BOT */
61: #define MTDS_FPT 0000400 /* write protected */
62: #define MTDS_AVAIL 0000200 /* unit available */
63:
64: /* mtncs */
65: #define MT_COFF 8 /* bits to shift count */
66: #define MTNCS_COUNT(c) (((c)>>MT_COFF)&0377) /* repeat count */
67: #define MAXCOUNT 0377
68:
69: /* mter */
70: #define MTER_INTCODE(e) ((int)(e)&0377) /* interrupt code */
71: #define MTER_DPR 0400 /* drive (formatter) present */
72: #define MTER_UNIT(e) (((e)>>8)&03) /* interrupting unit in mtner */
73:
74: /* interrupt codes */
75: #define MTER_DONE 001 /* operation complete */
76: #define MTER_TM 002 /* unexpected tape mark */
77: #define MTER_BOT 003 /* unexpected BOT detected */
78: #define MTER_EOT 004 /* tape positioned beyond EOT */
79: #define MTER_LEOT 005 /* unexpected LEOT detected */
80: #define MTER_NOOP 006 /* no-op completed */
81: #define MTER_RWDING 007 /* rewinding */
82: #define MTER_FPT 010 /* write protect error */
83: #define MTER_NOTRDY 011 /* not ready */
84: #define MTER_NOTAVL 012 /* not available */
85: #define MTER_OFFLINE 013 /* offline */
86: #define MTER_NONEX 014 /* unit does not exist */
87: #define MTER_NOTCAP 015 /* not capable */
88: #define MTER_ONLINE 017 /* tape came online */
89: #define MTER_LONGREC 020 /* long tape record */
90: #define MTER_SHRTREC 021 /* short tape record */
91: #define MTER_RETRY 022 /* retry */
92: #define MTER_RDOPP 023 /* read opposite */
93: #define MTER_UNREAD 024 /* unreadable */
94: #define MTER_ERROR 025 /* error */
95: #define MTER_EOTERR 026 /* EOT error */
96: #define MTER_BADTAPE 027 /* tape position lost */
97: #define MTER_TMFLTA 030 /* TM fault A */
98: #define MTER_TUFLTA 031 /* TU fault A */
99: #define MTER_TMFLTB 032 /* TM fault B */
100: #define MTER_MBFLT 034 /* Massbus fault */
101: #define MTER_KEYFAIL 077 /* keypad entry error */
102:
103: /* mtid */
104: #define MTID_RDY 0100000 /* controller ready */
105: #define MTID_CLR 0040000 /* controller clear */
106:
107: #define MTTIMEOUT 10000 /* loop limit for controller test */
108:
109: /*
110: * system stuff
111: */
112:
113: int tu78open(), tu78close(), tu78read(), tu78write(), tu78ioctl(), tu78strategy();
114: struct cdevsw tu78cdev = cdinit(tu78open, tu78close, tu78read, tu78write, tu78ioctl);
115: struct bdevsw tu78bdev = bdinit(tu78open, tu78close, tu78strategy, B_TAPE);
116:
117: /*
118: * per-formatter stuff
119: */
120:
121: extern int tm78cnt;
122: extern struct tm78 tm78[];
123: extern struct mbaddr tm78addr[];
124:
125: #define T_BUSY 01 /* controller busy */
126: #define NOUNIT 0377 /* no slave expected */
127:
128: /*
129: * per-drive stuff
130: */
131:
132: extern int tu78cnt;
133: extern struct tu78 tu78[];
134: extern struct subaddr tu78addr[];
135: extern struct buf rtu78buf[];
136: extern struct buf ctu78buf[];
137:
138: /*
139: * bits in minor device
140: */
141: #define TUUNIT(dev) (minor(dev)&03)
142: #define H_NOREWIND 04
143: #define H_6250BPI 010
144:
145: /*
146: * sc_flags
147: */
148: #define H_BUSY 01 /* software drive busy */
149: #define H_EOT 02 /* saw physical end-of-tape */
150: #define H_WRITTEN 04 /* last operation was a write */
151: #define H_ERASED 010 /* last write retry was an erase gap */
152: #define H_OPEN 020 /* device open */
153: #define H_OFFLINE 040 /* device went offline; no io till close */
154: #define H_WONLY 0100 /* write-only */
155:
156: /*
157: * scaling for block magtape blocks
158: */
159: #define INF 1000000L /* a block number that won't exist */
160: #define TBLOCK 2 /* tape blocks per b_blkno block */
161: #define TBSIZE 1024
162: #define TBSHIFT 10
163:
164: /*
165: * overloads in struct buf; for tu78cmd
166: */
167: #define b_repcnt b_bcount
168: #define b_command b_resid
169:
170: tu78open(dev, flag)
171: dev_t dev;
172: int flag;
173: {
174: register int tuunit;
175: register struct tu78 *sc;
176: register struct subaddr *sa;
177: int dens;
178:
179: tuunit = TUUNIT(dev);
180: if (tuunit >= tu78cnt || (sc = &tu78[tuunit])->sc_flags & H_OPEN) {
181: u.u_error = ENXIO;
182: return;
183: }
184: sc->sc_flags |= H_OPEN;
185: sa = &tu78addr[tuunit];
186: if (tm78init(sa->ctl, sa->unit, tuunit) == 0) {
187: sc->sc_flags &=~ H_OPEN;
188: u.u_error = ENXIO;
189: return;
190: }
191: sc->sc_ctl = &tm78[sa->ctl];
192: sc->sc_dens = minor(dev) & H_6250BPI ? MT_GCR : 0;
193: sc->sc_slave = sa->unit;
194: sc->sc_flags &=~ H_OFFLINE; /* so we can sense */
195: tu78cmd(dev, MT_SENSE, 1L);
196: if ((sc->sc_dsreg & MTDS_PRES) == 0) { /* what's the right test? */
197: printf("tu78 %d absent\n", tuunit);
198: sc->sc_flags &=~ H_OPEN;
199: u.u_error = ENODEV;
200: return;
201: }
202: if ((sc->sc_dsreg & MTDS_ONL) == 0) {
203: sc->sc_flags &=~ H_OPEN;
204: u.u_error = EIO;
205: return;
206: }
207: if ((flag&FWRITE) && (sc->sc_dsreg&MTDS_FPT)) {
208: sc->sc_flags &=~ H_OPEN;
209: u.u_error = EIO;
210: return;
211: }
212: if ((sc->sc_dsreg & MTDS_BOT) == 0 && flag&FWRITE) {
213: dens = sc->sc_dsreg & MTDS_PE ? 0 : MT_GCR;
214: if (sc->sc_dens != dens) {
215: sc->sc_flags &=~ H_OPEN;
216: u.u_error = EIO;
217: return;
218: }
219: }
220: sc->sc_blkno = 0;
221: sc->sc_nxrec = INF;
222: if ((flag & (FREAD|FWRITE)) == FWRITE)
223: sc->sc_flags |= H_WONLY; /* stop block dev readahead */
224: }
225:
226: tm78init(ctl, slave, dev)
227: register int ctl;
228: int slave, dev;
229: {
230: register struct tm78 *cc;
231: register int i;
232:
233: if (ctl < 0 || slave < 0 || ctl >= tm78cnt || slave >= TM78DRIVES)
234: return (0);
235: cc = &tm78[ctl];
236: cc->cc_drives[slave] = dev;
237: if (cc->cc_mbaddr)
238: return (1);
239: if ((cc->cc_addr = (struct device *)mbaddr(&tm78addr[ctl])) == 0
240: || badaddr(&cc->cc_addr->mtcs, sizeof(long))
241: || (cc->cc_addr->mter & MTER_DPR) == 0) {
242: printf("tm78 %d absent\n", ctl);
243: return (0);
244: }
245: for (i = 0; i < TM78DRIVES; i++)
246: if (i != slave)
247: cc->cc_drives[i] = NOUNIT;
248: if (tm78reset(ctl) == 0)
249: return (0);
250: cc->cc_mbaddr = &tm78addr[ctl];
251: return (1);
252: }
253:
254: /*
255: * reset the formatter
256: * initially or after some awful error
257: */
258: tm78reset(ctl)
259: int ctl;
260: {
261: register struct tm78 *cc;
262: register struct device *tmaddr;
263: register struct tu78 *sc;
264: register struct buf *bp;
265: register int i;
266:
267: cc = &tm78[ctl];
268: tmaddr = cc->cc_addr;
269: tmaddr->mtid = MTID_CLR;
270: while ((sc = cc->cc_actf) != NULL) {
271: cc->cc_actf = sc->sc_next;
272: while ((bp = sc->sc_actf) != NULL) {
273: sc->sc_actf = bp->av_forw;
274: bp->b_flags |= B_ERROR;
275: iodone(bp);
276: }
277: sc->sc_flags &=~ H_BUSY;
278: }
279: cc->cc_flags &=~ T_BUSY;
280: DELAY(200);
281: for (i = 0; i < MTTIMEOUT; i++) {
282: if (tmaddr->mtid & MTID_RDY)
283: return (1); /* done */
284: DELAY(50); /* wait a bit more */
285: }
286: printf("tm78 %d: never ready\n", ctl);
287: return (0);
288: }
289:
290: tu78close(dev)
291: register dev_t dev;
292: {
293: register struct tu78 *sc = &tu78[TUUNIT(dev)];
294:
295: if (sc->sc_flags & (H_WONLY|H_WRITTEN))
296: tu78cmd(dev, MT_CLS|sc->sc_dens, 1L);
297: if ((minor(dev)&H_NOREWIND) == 0)
298: tu78cmd(dev, MT_REW, 0L);
299: sc->sc_flags &= H_BUSY;
300: }
301:
302: tu78cmd(dev, com, count)
303: dev_t dev;
304: int com;
305: register daddr_t count;
306: {
307: register struct buf *bp;
308: register int some;
309:
310: bp = &ctu78buf[TUUNIT(dev)];
311: (void) spl5();
312: while (bp->b_flags&B_BUSY) {
313: if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE))
314: break;
315: bp->b_flags |= B_WANTED;
316: sleep((caddr_t)bp, PRIBIO);
317: }
318: bp->b_flags = B_BUSY|B_READ;
319: (void) spl0();
320: bp->b_dev = dev;
321: bp->b_command = com;
322: bp->b_blkno = 0;
323: do {
324: if (count <= MAXCOUNT)
325: some = count;
326: else
327: some = MAXCOUNT;
328: bp->b_repcnt = some;
329: tu78strategy(bp);
330: if (count == 0) {
331: if (bp->b_flags & B_DONE)
332: geterror(bp);
333: return; /* sic */
334: }
335: iowait(bp);
336: } while (u.u_error == 0 && (count -= some) > 0);
337: if (bp->b_flags&B_WANTED)
338: wakeup((caddr_t)bp);
339: bp->b_flags &=~ B_BUSY;
340: }
341:
342: tu78strategy(bp)
343: register struct buf *bp;
344: {
345: register struct tu78 *sc;
346:
347: sc = &tu78[TUUNIT(bp->b_dev)];
348: bp->av_forw = NULL;
349: (void) spl5();
350: if (sc->sc_actf == NULL)
351: sc->sc_actf = bp;
352: else
353: sc->sc_actl->av_forw = bp;
354: sc->sc_actl = bp;
355: if ((sc->sc_flags & H_BUSY) == 0)
356: tu78start(sc);
357: if (sc->sc_ctl->cc_actf && (sc->sc_ctl->cc_flags & T_BUSY) == 0)
358: tm78start(sc->sc_ctl);
359: (void) spl0();
360: }
361:
362: tu78start(sc)
363: register struct tu78 *sc;
364: {
365: register struct buf *bp;
366: register struct device *tmaddr;
367: register struct tm78 *cc;
368: register daddr_t bno;
369: register int cmd, dist;
370:
371: cc = sc->sc_ctl;
372: loop:
373: if ((bp = sc->sc_actf) == 0)
374: return;
375: tmaddr = cc->cc_addr;
376: sc->sc_flags &= ~H_WRITTEN;
377: if (sc->sc_flags & H_OFFLINE) {
378: bp->b_flags |= B_ERROR;
379: goto done;
380: }
381: /*
382: * command, start it
383: */
384: if (bp == &ctu78buf[TUUNIT(bp->b_dev)]) {
385: sc->sc_flags |= H_BUSY;
386: cmd = bp->b_command|MT_GO;
387: cmd |= bp->b_repcnt << MT_COFF;
388: #if BABBLE
389: printf("cmd %o\n", cmd);
390: #endif
391: tmaddr->mtncs[sc->sc_slave] = cmd;
392: return;
393: }
394: /*
395: * transfer, see if position needed (wretched block magtape)
396: */
397: bno = bp->b_blkno/TBLOCK;
398: if (bno > sc->sc_nxrec) {
399: bp->b_error = ENXIO;
400: bp->b_flags |= B_ERROR;
401: goto done;
402: }
403: if (bp->b_flags & B_READ /* at EOF, or really just writing? */
404: && (bno == sc->sc_nxrec || sc->sc_flags & H_WONLY)) {
405: bp->b_resid = bp->b_bcount;
406: goto done;
407: }
408: if ((bp->b_flags&B_READ)==0)
409: sc->sc_nxrec = bno + 1;
410: if (sc->sc_blkno != bno) { /* need position */
411: sc->sc_flags |= H_BUSY;
412: if (sc->sc_blkno < bno) {
413: sc->sc_flags &=~ H_EOT;
414: dist = bno - sc->sc_blkno;
415: cmd = MT_SREV;
416: } else {
417: dist = sc->sc_blkno - bno;
418: cmd = MT_SFORW;
419: }
420: if (dist > MAXCOUNT)
421: dist = MAXCOUNT;
422: tmaddr->mtncs[sc->sc_slave] = (dist<<MT_COFF)|cmd|MT_GO;
423: return;
424: }
425: /*
426: * time for a transfer
427: */
428: if ((bp->b_flags&B_READ) == 0 && sc->sc_flags & H_EOT) {
429: bp->b_resid = bp->b_bcount;
430: done:
431: sc->sc_actf = bp->av_forw;
432: iodone(bp);
433: goto loop;
434: }
435: cc = sc->sc_ctl;
436: sc->sc_next = NULL;
437: if (cc->cc_actf == NULL)
438: cc->cc_actf = sc;
439: else
440: cc->cc_actl->sc_next = sc;
441: cc->cc_actl = sc;
442: sc->sc_flags |= H_BUSY;
443: }
444:
445: tm78start(cc)
446: register struct tm78 *cc;
447: {
448: register struct tu78 *sc;
449: int tm78xfer();
450:
451: if ((sc = cc->cc_actf) == NULL)
452: return;
453: if (sc->sc_actf == NULL)
454: panic("tm78start");
455: cc->cc_flags |= T_BUSY;
456: mbstart(cc->cc_mbaddr, sc->sc_actf, tm78xfer);
457: }
458:
459: tm78xfer(bp)
460: register struct buf *bp;
461: {
462: register struct tu78 *sc;
463: register struct device *tmaddr;
464:
465: sc = &tu78[TUUNIT(bp->b_dev)];
466: tmaddr = sc->sc_ctl->cc_addr;
467: tmaddr->mtca = sc->sc_slave;
468: tmaddr->mtbc = bp->b_bcount;
469: #if BABBLE
470: printf("xfer go\n");
471: #endif
472: if (bp->b_flags & B_READ)
473: tmaddr->mtcs = MT_READ|MT_GO;
474: else
475: tmaddr->mtcs = MT_WRITE|sc->sc_dens|MT_GO;
476: }
477:
478: /*
479: * massbus interrupt
480: * if a transfer was pending, assume it finished;
481: * if attn set, something else finished too
482: */
483: tm780int(ctl, mbsr, mbbc, attn)
484: int ctl, mbsr, mbbc, attn;
485: {
486: register struct tm78 *cc;
487:
488: cc = &tm78[ctl];
489: if (cc->cc_addr == NULL) {
490: printf("tm78 %d: stray intr\n", ctl);
491: return;
492: }
493: if (attn)
494: tu78attn(ctl, mbsr, attn);
495: if (cc->cc_flags & T_BUSY)
496: tu78dtint(ctl, mbsr);
497: if (cc->cc_actf)
498: tm78start(cc);
499: }
500:
501: /*
502: * here with an attention:
503: * a boring interrupt, a disaster, or a command finished
504: * don't clear the attn until we've read the registers
505: */
506:
507: tu78attn(ctl, mbsr, attn)
508: int ctl, mbsr, attn;
509: {
510: register struct tm78 *cc;
511: register struct tu78 *sc;
512: register struct buf *bp;
513: register struct device *tmaddr;
514: register int unit;
515: daddr_t bno;
516: register int i;
517: register long rt; /* register temp to avoid compiler botches */
518:
519: cc = &tm78[ctl];
520: tmaddr = cc->cc_addr;
521: rt = tmaddr->mtner;
522: i = MTER_UNIT(rt);
523: #if BABBLE
524: printf("attn er%o ds%o cs%o\n", tmaddr->mtner&0xffff, tmaddr->mtds&0xffff, tmaddr->mtncs[i]&0xffff);
525: #endif
526: switch (MTER_INTCODE(rt)) {
527: case MTER_ONLINE:
528: case MTER_RWDING:
529: tmaddr->mtas = attn;
530: return; /* boring */
531:
532: case MTER_MBFLT:
533: case MTER_TMFLTB:
534: printf("tm78 %d fault er%o mbsr%o\n", ctl, tmaddr->mtner, mbsr);
535: tm78reset(ctl);
536: tmaddr->mtas = attn;
537: return;
538: }
539: if ((unit = cc->cc_drives[i]) == NOUNIT) {
540: printf("tm78 %d unit %d stray intr er%o\n", ctl, i, tmaddr->mtner);
541: tmaddr->mtas = attn;
542: return;
543: }
544: sc = &tu78[unit];
545: rt = tmaddr->mtds; sc->sc_dsreg = rt;
546: rt = tmaddr->mtner; sc->sc_erreg = rt;
547: rt = tmaddr->mtncs[i]; sc->sc_resid = MTNCS_COUNT(rt);
548: tmaddr->mtas = attn;
549: if ((bp = sc->sc_actf) == NULL) {
550: printf("tu78 %d: odd intr er%o\n", unit, sc->sc_erreg);
551: return;
552: }
553: switch (MTER_INTCODE(sc->sc_erreg)) {
554: case MTER_EOT:
555: sc->sc_flags |= H_EOT;
556: /* fall through */
557: case MTER_TM:
558: case MTER_LEOT:
559: case MTER_BOT:
560: case MTER_NOOP:
561: case MTER_DONE:
562: /*
563: * this was a block magtape seek,
564: * or we're closing (so sc_blkno is boring),
565: * or it's raw magtape (ditto)
566: */
567: bno = bp->b_blkno / TBLOCK;
568: if (sc->sc_blkno > bno)
569: sc->sc_blkno += sc->sc_resid;
570: else
571: sc->sc_blkno -= sc->sc_resid;
572: if (sc->sc_flags & H_EOT)
573: sc->sc_nxrec = sc->sc_blkno;
574: if (bp != &ctu78buf[unit])
575: sc->sc_flags &=~ H_BUSY; /* done with seek */
576: break;
577:
578: case MTER_NOTAVL:
579: case MTER_OFFLINE:
580: case MTER_NONEX:
581: if (sc->sc_flags & H_OPEN)
582: sc->sc_flags |= H_OFFLINE;
583: bp->b_error = ENXIO;
584: bp->b_flags |= B_ERROR;
585: break;
586:
587: default:
588: printf("tu78 %d: hard error bn%d er%o mbsr%o\n",
589: unit, bp->b_blkno, sc->sc_erreg, mbsr);
590: bp->b_flags |= B_ERROR;
591: break;
592: }
593: if (sc->sc_flags & H_BUSY) {
594: sc->sc_actf = bp->av_forw;
595: iodone(bp);
596: sc->sc_flags &=~ H_BUSY;
597: }
598: if (sc->sc_actf)
599: tu78start(sc);
600: }
601:
602: tu78dtint(ctl, mbsr)
603: int ctl, mbsr;
604: {
605: register struct tm78 *cc;
606: register struct tu78 *sc;
607: register struct buf *bp;
608: register struct device *tmaddr;
609: register int rt; /* reg temp to avoid compiler botches */
610:
611: cc = &tm78[ctl];
612: tmaddr = cc->cc_addr;
613: if ((sc = cc->cc_actf) == NULL
614: || (bp = sc->sc_actf) == NULL)
615: panic("tu78dtint");
616: rt = tmaddr->mtbc; sc->sc_resid = rt;
617: rt = tmaddr->mter; sc->sc_erreg = rt;
618: #if BABBLE
619: printf("dtint er%o bc%o mbs%o\n", sc->sc_erreg, sc->sc_resid, mbsr);
620: #endif
621: if (mbsr & MBSR_HARD) {
622: printf("tu78 %d: mb error er%o mbsr%o\n",
623: TUUNIT(bp->b_dev), sc->sc_erreg, mbsr);
624: bp->b_flags |= B_ERROR;
625: } else switch (MTER_INTCODE(sc->sc_erreg)) {
626: case MTER_MBFLT:
627: case MTER_TMFLTB:
628: printf("tm78 %d fault er%o mbsr%o\n", ctl, sc->sc_erreg, mbsr);
629: tm78reset(ctl);
630: return;
631:
632: case MTER_EOT:
633: sc->sc_flags |= H_EOT;
634: /* fall through */
635: case MTER_LEOT:
636: case MTER_TM:
637: bp->b_resid = bp->b_bcount;
638: sc->sc_nxrec = sc->sc_blkno;
639: break;
640:
641: case MTER_LONGREC:
642: sc->sc_blkno++;
643: bp->b_error = ENOMEM;
644: bp->b_flags |= B_ERROR;
645: break;
646:
647: case MTER_SHRTREC:
648: if (bp != &rtu78buf[TUUNIT(bp->b_dev)]) /* block tape */
649: bp->b_flags |= B_ERROR;
650: /* fall in */
651: case MTER_DONE:
652: bp->b_resid = bp->b_bcount - sc->sc_resid;
653: sc->sc_blkno++;
654: break;
655:
656: case MTER_RETRY:
657: cc->cc_flags &=~ T_BUSY;
658: break;
659:
660: case MTER_NOTAVL:
661: case MTER_OFFLINE:
662: case MTER_NONEX:
663: if (sc->sc_flags & H_OPEN)
664: sc->sc_flags |= H_OFFLINE;
665: bp->b_error = ENXIO;
666: bp->b_flags |= B_ERROR;
667: break;
668:
669: case MTER_NOTCAP:
670: case MTER_BADTAPE:
671: if (sc->sc_flags & H_OPEN)
672: sc->sc_flags |= H_OFFLINE; /* really position lost */
673: /* fall through */
674: default:
675: printf("tu78 %d: hard error bn%d er%o mbsr%o\n",
676: TUUNIT(bp->b_dev), bp->b_blkno, sc->sc_erreg, mbsr);
677: sc->sc_blkno++;
678: bp->b_flags |= B_ERROR;
679: break;
680: }
681: if (cc->cc_flags & T_BUSY) {
682: cc->cc_actf = sc->sc_next;
683: sc->sc_actf = bp->av_forw;
684: iodone(bp);
685: sc->sc_flags &=~ H_BUSY;
686: if (sc->sc_actf)
687: tu78start(sc);
688: cc->cc_flags &=~ T_BUSY;
689: }
690: }
691:
692: tu78read(dev)
693: dev_t dev;
694: {
695:
696: tu78phys(dev);
697: physio(tu78strategy, &rtu78buf[TUUNIT(dev)], dev, B_READ, minphys);
698: }
699:
700: tu78write(dev)
701: dev_t dev;
702: {
703:
704: tu78phys(dev);
705: physio(tu78strategy, &rtu78buf[TUUNIT(dev)], dev, B_WRITE, minphys);
706: }
707:
708: tu78phys(dev)
709: dev_t dev;
710: {
711: register struct tu78 *sc;
712:
713: sc = &tu78[TUUNIT(dev)];
714: sc->sc_blkno = Lshift(u.u_offset, TBSHIFT);
715: sc->sc_nxrec = sc->sc_blkno + 1;
716: }
717:
718: tu78ioctl(dev, cmd, addr, flag)
719: dev_t dev;
720: int cmd;
721: caddr_t addr;
722: int flag;
723: {
724: struct mtop mtop;
725:
726: switch (cmd) {
727: case MTIOCTOP: /* tape operation */
728: if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
729: u.u_error = EFAULT;
730: return;
731: }
732: if (mtop.mt_count == 0)
733: mtop.mt_count = 1;
734: switch(mtop.mt_op) {
735: case MTWEOF:
736: tu78cmd(dev, MT_WTM|tu78[TUUNIT(dev)].sc_dens, mtop.mt_count);
737: break;
738:
739: case MTFSF:
740: tu78cmd(dev, MT_SFORWF, mtop.mt_count);
741: break;
742:
743: case MTBSF:
744: tu78cmd(dev, MT_SREVF, mtop.mt_count);
745: break;
746:
747: case MTFSR:
748: tu78cmd(dev, MT_SFORW, mtop.mt_count);
749: break;
750:
751: case MTBSR:
752: tu78cmd(dev, MT_SREV, mtop.mt_count);
753: break;
754:
755: case MTREW:
756: tu78cmd(dev, MT_REW, 1L);
757: break;
758:
759: case MTOFFL:
760: tu78cmd(dev, MT_UNLOAD, 1L);
761: break;
762:
763: default:
764: u.u_error = ENXIO;
765: break;
766: }
767: return;
768:
769: default:
770: u.u_error = ENXIO;
771: return;
772: }
773: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.