|
|
1.1 root 1: /*
2: * TM03/TE16 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/te16.h"
17:
18: /*
19: * hardware stuff
20: */
21: struct device {
22: int htcs1; /* control status */
23: int htds; /* drive status */
24: int hter; /* error */
25: int htmr; /* maintenance */
26: int htas; /* attention status */
27: int htfc; /* frame count */
28: int htdt; /* drive type */
29: int htck; /* nrzi check (crc) error character */
30: int htsn; /* serial number */
31: int httc; /* tape control */
32: };
33:
34: /* htcs1 */
35: #define HT_GO 000001 /* go bit */
36: #define HT_REWOFFL 000002 /* rewind offline */
37: #define HT_REW 000006 /* rewind */
38: #define HT_DCLR 000010 /* drive clear */
39: #define HT_ERASE 000024 /* erase */
40: #define HT_WEOF 000026 /* write tape mark */
41: #define HT_SFORW 000030 /* space forward */
42: #define HT_SREV 000032 /* space reverse */
43: #define HT_WCOM 000060 /* write forward */
44: #define HT_RCOM 000070 /* read forward */
45:
46: /* htds */
47: #define HTDS_ATA 0100000 /* attention active */
48: #define HTDS_ERR 0040000 /* composite error */
49: #define HTDS_MOL 0010000 /* medium on line */
50: #define HTDS_WRL 0004000 /* write lock */
51: #define HTDS_EOT 0002000 /* end of tape */
52: #define HTDS_DPR 0000400 /* drive present (always 1) */
53: #define HTDS_DRY 0000200 /* drive ready */
54: #define HTDS_SSC 0000100 /* slace status changed */
55: #define HTDS_PES 0000040 /* phase-encoded status */
56: #define HTDS_TM 0000004 /* tape mark */
57: #define HTDS_BOT 0000002 /* beginning of tape */
58: #define HTDS_SLA 0000001 /* slave attention */
59:
60: /* hter */
61: #define HTER_CORCRC 0100000 /* correctible data or ecc */
62: #define HTER_UNS 0040000 /* unsafe */
63: #define HTER_OPI 0020000 /* operation incomplete */
64: #define HTER_DTE 0010000 /* drive timing error */
65: #define HTER_NEF 0004000 /* non-executable function */
66: #define HTER_CSITM 0002000 /* correctable skew/illegal tape mark */
67: #define HTER_FCE 0001000 /* frame count error */
68: #define HTER_NSG 0000400 /* non-standard gap */
69: #define HTER_PEFLRC 0000200 /* format error or lrc error */
70: #define HTER_DPAR 0000040 /* data parity error */
71: #define HTER_FMT 0000020 /* format error */
72: #define HTER_CPAR 0000010 /* control bus parity error */
73: #define HTER_RMR 0000004 /* register modification refused */
74: #define HTER_ILR 0000002 /* illegal register */
75: #define HTER_ILF 0000001 /* illegal function */
76: #define HTER_HARD \
77: (HTER_UNS|HTER_OPI|HTER_NEF|HTER_DPAR|HTER_FMT|HTER_CPAR| \
78: HTER_RMR|HTER_ILR|HTER_ILF)
79:
80: /* htdt */
81: #define HTDT_SPR 0002000 /* slave present */
82:
83: /* httc */
84: #define HTTC_800BPI 0001400 /* in bits 8-10, dens=1600 */
85: #define HTTC_1600BPI 0002000 /* in bits 8-10, dens=800 */
86: #define HTTC_PDP11 0000300 /* in bits 4-7, pdp11 normal format */
87:
88: /*
89: * system stuff
90: */
91:
92: int te16open(), te16close(), te16read(), te16write(), te16ioctl(), te16strategy();
93: struct cdevsw te16cdev = cdinit(te16open, te16close, te16read, te16write, te16ioctl);
94: struct bdevsw te16bdev = bdinit(te16open, te16close, te16strategy, B_TAPE);
95:
96: /*
97: * per-formatter stuff
98: */
99:
100: extern int tm03cnt;
101: extern struct tm03 tm03[];
102: extern struct mbaddr tm03addr[];
103:
104: #define T_BUSY 01 /* controller busy */
105: #define NOUNIT 0377 /* no unit expected */
106:
107: /*
108: * per-drive stuff
109: */
110:
111: extern int te16cnt;
112: extern struct te16 te16[];
113: extern struct subaddr te16addr[];
114: extern struct buf rte16buf[];
115: extern struct buf cte16buf[];
116:
117: /*
118: * bits in minor device
119: */
120: #define TEUNIT(dev) (minor(dev)&03)
121: #define H_NOREWIND 04
122: #define H_1600BPI 010
123:
124: /*
125: * sc_flags
126: */
127: #define H_BUSY 01 /* software drive busy */
128: #define H_CMD 02 /* hardware command pending */
129: #define H_WRITTEN 04 /* last operation was a write */
130: #define H_ERASED 010 /* last write retry was an erase gap */
131: #define H_OPEN 020 /* device open */
132: #define H_OFFLINE 040 /* device went offline; no io till close */
133: #define H_WONLY 0100 /* write-only */
134:
135: /*
136: * scaling for block magtape blocks
137: */
138: #define INF 1000000L /* a block number that won't exist */
139: #define TBLOCK 2 /* tape blocks per b_blkno block */
140: #define TBSIZE 1024
141: #define TBSHIFT 10
142:
143: /*
144: * overloads in struct buf; for te16cmd
145: */
146: #define b_repcnt b_bcount
147: #define b_command b_resid
148:
149: te16open(dev, flag)
150: dev_t dev;
151: int flag;
152: {
153: register int teunit;
154: register struct te16 *sc;
155: register struct subaddr *sa;
156: register struct device *htaddr;
157: register int dt;
158:
159: teunit = TEUNIT(dev);
160: if (teunit >= te16cnt || (sc = &te16[teunit])->sc_flags & H_OPEN) {
161: u.u_error = ENXIO;
162: return;
163: }
164: sc->sc_flags |= H_OPEN;
165: sa = &te16addr[teunit];
166: if (tm03init(sa->ctl, sa->unit, teunit) == 0) {
167: sc->sc_flags &=~ H_OPEN;
168: u.u_error = ENXIO;
169: return;
170: }
171: sc->sc_ctl = &tm03[sa->ctl];
172: htaddr = sc->sc_ctl->cc_addr;
173: sc->sc_dens = ((minor(dev)&H_1600BPI)?HTTC_1600BPI:HTTC_800BPI)|HTTC_PDP11|sa->unit;
174: spl5();
175: htaddr->httc = sc->sc_dens;
176: /* delay here? */
177: dt = htaddr->htdt;
178: sc->sc_dsreg = htaddr->htds;
179: spl0();
180: if ((dt & HTDT_SPR) == 0) {
181: printf("te16 %d absent\n", teunit);
182: sc->sc_flags &=~ H_OPEN;
183: u.u_error = ENODEV;
184: return;
185: }
186: if ((sc->sc_dsreg & HTDS_MOL) == 0) {
187: sc->sc_flags &=~ H_OPEN;
188: u.u_error = EIO;
189: return;
190: }
191: if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) {
192: sc->sc_flags &=~ H_OPEN;
193: u.u_error = EIO;
194: return;
195: }
196: if ((sc->sc_dsreg & HTDS_BOT) == 0 && flag&FWRITE
197: && ((minor(dev) & H_1600BPI) != 0) != ((sc->sc_dsreg & HTDS_PES) != 0)) {
198: sc->sc_flags &=~ H_OPEN;
199: u.u_error = EIO;
200: return;
201: }
202: sc->sc_blkno = 0;
203: sc->sc_nxrec = INF;
204: if ((flag & (FREAD|FWRITE)) == FWRITE)
205: sc->sc_flags |= H_WONLY; /* stop block dev readahead */
206: }
207:
208: tm03init(ctl, slave, dev)
209: register int ctl;
210: int slave, dev;
211: {
212: register struct tm03 *cc;
213: register int i;
214:
215: if (ctl < 0 || slave < 0 || ctl >= tm03cnt || slave >= TM03DRIVES)
216: return (0);
217: cc = &tm03[ctl];
218: cc->cc_drives[slave] = dev;
219: if (cc->cc_addr)
220: return (1);
221: if ((cc->cc_addr = (struct device *)mbaddr(&tm03addr[ctl])) == 0
222: || badaddr(&cc->cc_addr->htcs1, sizeof(long))
223: || (cc->cc_addr->htds & HTDS_DPR) == 0) {
224: printf("tm03 %d absent\n", ctl);
225: return (0);
226: }
227: cc->cc_mbaddr = &tm03addr[ctl];
228: for (i = 0; i < TM03DRIVES; i++)
229: if (i != slave)
230: cc->cc_drives[i] = NOUNIT;
231: /* any reset worth doing? */
232: return (1);
233: }
234:
235: te16close(dev)
236: register dev_t dev;
237: {
238: register struct te16 *sc = &te16[TEUNIT(dev)];
239:
240: if (sc->sc_flags & (H_WONLY|H_WRITTEN)) {
241: te16cmd(dev, HT_WEOF, 1);
242: te16cmd(dev, HT_WEOF, 1);
243: te16cmd(dev, HT_SREV, 1);
244: }
245: if ((minor(dev)&H_NOREWIND) == 0)
246: te16cmd(dev, HT_REW, 0);
247: sc->sc_flags &= H_CMD|H_BUSY;
248: }
249:
250: te16cmd(dev, com, count)
251: dev_t dev;
252: int com, count;
253: {
254: register struct buf *bp;
255:
256: bp = &cte16buf[TEUNIT(dev)];
257: (void) spl5();
258: while (bp->b_flags&B_BUSY) {
259: if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE))
260: break;
261: bp->b_flags |= B_WANTED;
262: sleep((caddr_t)bp, PRIBIO);
263: }
264: bp->b_flags = B_BUSY|B_READ;
265: (void) spl0();
266: bp->b_dev = dev;
267: bp->b_command = com;
268: bp->b_repcnt = count;
269: bp->b_blkno = 0;
270: te16strategy(bp);
271: if (count == 0) {
272: if (bp->b_flags & B_DONE)
273: geterror(bp);
274: return;
275: }
276: iowait(bp);
277: if (bp->b_flags&B_WANTED)
278: wakeup((caddr_t)bp);
279: bp->b_flags &=~ B_BUSY;
280: }
281:
282: te16strategy(bp)
283: register struct buf *bp;
284: {
285: register struct te16 *sc;
286:
287: sc = &te16[TEUNIT(bp->b_dev)];
288: bp->av_forw = NULL;
289: (void) spl5();
290: if (sc->sc_actf == NULL)
291: sc->sc_actf = bp;
292: else
293: sc->sc_actl->av_forw = bp;
294: sc->sc_actl = bp;
295: if ((sc->sc_flags & H_BUSY) == 0)
296: te16start(sc);
297: if (sc->sc_ctl->cc_actf && (sc->sc_ctl->cc_flags & T_BUSY) == 0)
298: tm03start(sc->sc_ctl);
299: (void) spl0();
300: }
301:
302: te16start(sc)
303: register struct te16 *sc;
304: {
305: register struct buf *bp;
306: register struct device *htaddr;
307: register struct tm03 *cc;
308: register daddr_t bno;
309:
310: cc = sc->sc_ctl;
311: loop:
312: if ((bp = sc->sc_actf) == 0)
313: return;
314: htaddr = cc->cc_addr;
315: htaddr->httc = sc->sc_dens;
316: if (htaddr->htds & HTDS_SSC)
317: htaddr->htcs1 = HT_DCLR|HT_GO;
318: sc->sc_dsreg = htaddr->htds;
319: sc->sc_erreg = htaddr->hter;
320: sc->sc_resid = htaddr->htfc;
321: sc->sc_flags &= ~H_WRITTEN;
322: if ((htaddr->htdt & HTDT_SPR) == 0 || (htaddr->htds & HTDS_MOL) == 0)
323: if (sc->sc_flags & H_OPEN)
324: sc->sc_flags |= H_OFFLINE;
325: if (sc->sc_flags & H_OFFLINE) {
326: bp->b_flags |= B_ERROR;
327: goto done;
328: }
329: /*
330: * command, start it
331: */
332: if (bp == &cte16buf[TEUNIT(bp->b_dev)]) {
333: sc->sc_flags |= H_BUSY|H_CMD;
334: htaddr->htfc = -bp->b_bcount;
335: htaddr->htcs1 = bp->b_command|HT_GO;
336: return;
337: }
338: /*
339: * transfer, see if position needed (wretched block magtape)
340: */
341: bno = bp->b_blkno/TBLOCK;
342: if (bno > sc->sc_nxrec) {
343: bp->b_error = ENXIO;
344: bp->b_flags |= B_ERROR;
345: goto done;
346: }
347: if (bp->b_flags & B_READ /* at EOF, or really just writing? */
348: && (bno == sc->sc_nxrec || sc->sc_flags & H_WONLY)) {
349: bp->b_resid = bp->b_bcount;
350: goto done;
351: }
352: if ((bp->b_flags&B_READ)==0)
353: sc->sc_nxrec = bno + 1;
354: if (sc->sc_blkno != bno) { /* need position */
355: sc->sc_flags |= H_BUSY|H_CMD;
356: if (sc->sc_blkno < bno) {
357: htaddr->htfc = sc->sc_blkno - bno;
358: htaddr->htcs1 = HT_SFORW|HT_GO;
359: } else {
360: htaddr->htfc = bno - sc->sc_blkno;
361: htaddr->htcs1 = HT_SREV|HT_GO;
362: }
363: return;
364: }
365: /*
366: * special pleading for `erase gap' write error recovery
367: * -- is this in the right place? why bother?
368: */
369: if ((bp->b_flags&B_READ) == 0) {
370: if (cc->cc_errcnt) {
371: if ((sc->sc_flags & H_ERASED) == 0) {
372: sc->sc_flags |= H_ERASED|H_BUSY|H_CMD;
373: htaddr->htcs1 = HT_ERASE|HT_GO;
374: return;
375: }
376: sc->sc_flags &= ~H_ERASED;
377: }
378: if (htaddr->htds & HTDS_EOT) { /* oops */
379: bp->b_resid = bp->b_bcount;
380: done:
381: sc->sc_actf = bp->av_forw;
382: iodone(bp);
383: goto loop;
384: }
385: }
386: /*
387: * time for a transfer
388: */
389: cc = sc->sc_ctl;
390: sc->sc_next = NULL;
391: if (cc->cc_actf == NULL)
392: cc->cc_actf = sc;
393: else
394: cc->cc_actl->sc_next = sc;
395: cc->cc_actl = sc;
396: sc->sc_flags |= H_BUSY;
397: }
398:
399: tm03start(cc)
400: register struct tm03 *cc;
401: {
402: register struct te16 *sc;
403: int tm03xfer();
404:
405: if ((sc = cc->cc_actf) == NULL)
406: return;
407: if (sc->sc_actf == NULL)
408: panic("tm03start");
409: cc->cc_flags |= T_BUSY;
410: mbstart(cc->cc_mbaddr, sc->sc_actf, tm03xfer);
411: }
412:
413: tm03xfer(bp)
414: register struct buf *bp;
415: {
416: register struct te16 *sc;
417: register struct device *htaddr;
418:
419: sc = &te16[TEUNIT(bp->b_dev)];
420: htaddr = sc->sc_ctl->cc_addr;
421: htaddr->httc = sc->sc_dens;
422: htaddr->htfc = -bp->b_bcount;
423: sc->sc_flags |= H_CMD;
424: if (bp->b_flags & B_READ)
425: htaddr->htcs1 = HT_RCOM|HT_GO;
426: else
427: htaddr->htcs1 = HT_WCOM|HT_GO;
428: }
429:
430: /*
431: * massbus interrupt
432: * if a transfer was pending, assume it finished;
433: * if attn set, something else finished too
434: *
435: * the loop to see which drives wanted attention is somewhat doubtful
436: * and has not been tested with multiple drives
437: */
438: tm030int(ctl, mbsr, mbbc, attn)
439: int ctl, mbsr, mbbc, attn;
440: {
441: register struct tm03 *cc;
442: register struct device *htaddr;
443: register struct te16 *sc;
444: register int i;
445:
446: cc = &tm03[ctl];
447: if ((htaddr = cc->cc_addr) == NULL) {
448: printf("tm03 %d: stray intr\n", ctl);
449: return;
450: }
451: htaddr->htas = attn; /* before we do anything */
452: if (cc->cc_flags & T_BUSY)
453: te16dtint(cc, mbsr);
454: if (attn) {
455: for (i = 0; i < TM03DRIVES; i++) {
456: if (cc->cc_drives[i] == NOUNIT)
457: continue;
458: sc = &te16[cc->cc_drives[i]];
459: htaddr->httc = sc->sc_dens; /* select drive */
460: if ((sc->sc_flags & H_CMD) == 0) {
461: sc->sc_dsreg = htaddr->htds; /* for BOT detection */
462: wakeup((caddr_t)sc);
463: if (htaddr->htds & HTDS_SSC)
464: htaddr->htcs1 = HT_DCLR|HT_GO;
465: continue;
466: }
467: if ((htaddr->htds & HTDS_DRY) == 0)
468: continue;
469: te16attn(sc);
470: }
471: }
472: if (cc->cc_actf)
473: tm03start(cc);
474: }
475:
476: /*
477: * error recovery is somewhat doubtful
478: * particular specialties:
479: * - short reads show up as frame count errors,
480: * so ignore them for the raw device
481: * - reading at tape mark seems to produce a frame count error too
482: * - quietly ignore CRC errors the drive corrected
483: */
484: te16dtint(cc, mbsr)
485: register struct tm03 *cc;
486: int mbsr;
487: {
488: register struct device *htaddr;
489: register struct buf *bp;
490: register struct te16 *sc;
491: int ds, er, mbs;
492:
493: htaddr = cc->cc_addr;
494: if ((sc = cc->cc_actf) == NULL)
495: panic("te16dtint");
496: sc->sc_flags &=~ H_CMD;
497: bp = sc->sc_actf;
498: ds = sc->sc_dsreg = htaddr->htds;
499: er = sc->sc_erreg = htaddr->hter;
500: sc->sc_resid = htaddr->htfc;
501: #if BABBLE
502: printf("dt: ds%o er%o fc%o mbs%o\n", ds, er, sc->sc_resid, mbsr);
503: printf("bp: bn%d bc%d fl%o\n", bp->b_blkno, bp->b_bcount, bp->b_flags);
504: #endif
505: mbs = mbsr;
506: if (er)
507: htaddr->htcs1 = HT_DCLR|HT_GO;
508: sc->sc_blkno++;
509: if((bp->b_flags & B_READ) == 0)
510: sc->sc_flags |= H_WRITTEN;
511: if (bp == &rte16buf[TEUNIT(bp->b_dev)] || ds & HTDS_TM) {
512: if (er & HTER_FCE) {
513: er &=~ HTER_FCE;
514: mbs &=~ (MBSR_DTABT|MBSR_MBEXC);
515: }
516: }
517: if (er & HTER_HARD || (ds & HTDS_MOL) == 0 || mbs & MBSR_EBITS)
518: bp->b_flags |= B_ERROR;
519: else if (er) { /* soft error */
520: if (++cc->cc_errcnt >= 7)
521: bp->b_flags |= B_ERROR;
522: else
523: cc->cc_flags &=~ T_BUSY;
524: }
525: if (bp->b_flags & B_ERROR)
526: printf("te16 %d: hard error bn%d mbsr=%o er=%o ds=%o\n",
527: TEUNIT(bp->b_dev), bp->b_blkno/TBLOCK, mbsr, sc->sc_erreg, sc->sc_dsreg);
528: if ((bp->b_flags & B_READ) == 0)
529: bp->b_resid = -sc->sc_resid;
530: else {
531: if (ds & HTDS_TM) {
532: bp->b_resid = bp->b_bcount;
533: sc->sc_nxrec = bp->b_blkno/TBLOCK;
534: } else if (sc->sc_resid > bp->b_bcount) {
535: bp->b_flags |= B_ERROR;
536: bp->b_error = ENOMEM;
537: } else
538: bp->b_resid = bp->b_bcount - sc->sc_resid;
539: }
540: if (cc->cc_flags & T_BUSY) { /* we decided we were finished */
541: sc->sc_actf = bp->av_forw;
542: iodone(bp);
543: cc->cc_actf = sc->sc_next;
544: cc->cc_errcnt = 0;
545: cc->cc_flags &=~ T_BUSY;
546: }
547: sc->sc_flags &=~ H_BUSY;
548: if (sc->sc_actf)
549: te16start(sc);
550: }
551:
552: te16attn(sc)
553: register struct te16 *sc;
554: {
555: register struct device *htaddr;
556: register struct buf *bp;
557: register struct tm03 *cc;
558: register int er, ds;
559: daddr_t bno;
560:
561: sc->sc_flags &=~ H_CMD;
562: cc = sc->sc_ctl;
563: htaddr = cc->cc_addr;
564: ds = sc->sc_dsreg = htaddr->htds;
565: er = sc->sc_erreg = htaddr->hter;
566: sc->sc_resid = htaddr->htfc;
567: if (er)
568: htaddr->htcs1 = HT_DCLR|HT_GO;
569: wakeup((caddr_t)sc);
570: if ((bp = sc->sc_actf) == 0)
571: return;
572: #if BABBLE
573: printf("at: ds%o er%o fc%o\n", sc->sc_dsreg, sc->sc_erreg, sc->sc_resid);
574: printf("bp: bn%d bc%d fl%o cm%o\n", bp->b_blkno, bp->b_bcount, bp->b_flags, bp->b_command);
575: #endif
576: bno = bp->b_blkno/TBLOCK;
577: if (bp == &cte16buf[TEUNIT(bp->b_dev)]) {
578: switch ((int)bp->b_command) {
579: case HT_REWOFFL:
580: /* offline is on purpose; don't do anything special */
581: ds |= HTDS_MOL;
582: break;
583: case HT_SREV:
584: /* if backspace file hit bot, its not an error */
585: if (er == (HTER_NEF|HTER_FCE) && ds&HTDS_BOT
586: && bp->b_repcnt == INF)
587: er &= ~HTER_NEF;
588: break;
589: }
590: er &= ~HTER_FCE;
591: if (er == 0)
592: ds &= ~HTDS_ERR;
593: }
594: if ((ds & (HTDS_ERR|HTDS_MOL)) != HTDS_MOL) {
595: if ((ds & HTDS_MOL) == 0 && sc->sc_flags & H_OPEN)
596: sc->sc_flags |= H_OFFLINE;
597: printf("te16 %d: hard error bn%d er%o ds%o\n",
598: TEUNIT(bp->b_dev), bno, sc->sc_erreg, sc->sc_dsreg);
599: bp->b_flags |= B_ERROR;
600: }
601: if (bp == &cte16buf[TEUNIT(bp->b_dev)])
602: bp->b_resid = -sc->sc_resid;
603: else
604: sc->sc_flags &=~ H_BUSY; /* done seeking, now xfer */
605: if ((ds & HTDS_TM) == 0)
606: sc->sc_blkno = bno;
607: else if (sc->sc_blkno > bno) {
608: sc->sc_nxrec = bno - sc->sc_resid;
609: sc->sc_blkno = sc->sc_nxrec;
610: } else {
611: sc->sc_blkno = bno + sc->sc_resid;
612: sc->sc_nxrec = sc->sc_blkno - 1;
613: }
614: if (sc->sc_flags & H_BUSY) {
615: sc->sc_actf = bp->av_forw;
616: iodone(bp);
617: sc->sc_flags &=~ H_BUSY;
618: }
619: if (sc->sc_actf)
620: te16start(sc);
621: }
622:
623: te16read(dev)
624: dev_t dev;
625: {
626:
627: te16phys(dev);
628: physio(te16strategy, &rte16buf[TEUNIT(dev)], dev, B_READ, minphys);
629: }
630:
631: te16write(dev)
632: dev_t dev;
633: {
634:
635: te16phys(dev);
636: physio(te16strategy, &rte16buf[TEUNIT(dev)], dev, B_WRITE, minphys);
637: }
638:
639: te16phys(dev)
640: dev_t dev;
641: {
642: register struct te16 *sc;
643:
644: sc = &te16[TEUNIT(dev)];
645: sc->sc_blkno = Lshift(u.u_offset, TBSHIFT);
646: sc->sc_nxrec = sc->sc_blkno + 1;
647: }
648:
649: /*ARGSUSED*/
650: te16ioctl(dev, cmd, addr, flag)
651: dev_t dev;
652: int cmd;
653: caddr_t addr;
654: int flag;
655: {
656: register struct te16 *sc = &te16[TEUNIT(dev)];
657: register struct buf *bp = &cte16buf[TEUNIT(dev)];
658: register callcount;
659: int fcount, htcmd;
660: struct mtop mtop;
661:
662: switch (cmd) {
663: case MTIOCTOP:
664: if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
665: u.u_error = EFAULT;
666: return;
667: }
668: if (mtop.mt_count <= 0) {
669: u.u_error = ENXIO;
670: return;
671: }
672: switch(mtop.mt_op) {
673: case MTWEOF:
674: htcmd = HT_WEOF;
675: callcount = mtop.mt_count;
676: fcount = 1;
677: break;
678: case MTFSF: case MTBSF:
679: htcmd = (mtop.mt_op == MTFSF) ? HT_SFORW : HT_SREV;
680: callcount = mtop.mt_count;
681: fcount = INF;
682: break;
683: case MTFSR: case MTBSR:
684: htcmd = (mtop.mt_op == MTFSF) ? HT_SFORW : HT_SREV;
685: callcount = 1;
686: fcount = mtop.mt_count;
687: break;
688: case MTREW: case MTOFFL:
689: te16cmd(dev, HT_REW, 1);
690: if (mtop.mt_op == MTREW)
691: return;
692: spl5();
693: while ((sc->sc_dsreg & HTDS_BOT) == 0)
694: sleep((caddr_t)sc, PZERO);
695: spl0();
696: te16cmd(dev, HT_REWOFFL, 0);
697: return;
698: default:
699: u.u_error = ENXIO;
700: return;
701: }
702: while (--callcount >= 0) {
703: te16cmd(dev, htcmd, fcount);
704: if (bp->b_resid
705: && (mtop.mt_op == MTFSR || mtop.mt_op == MTBSR)) {
706: u.u_error = EIO;
707: break;
708: }
709: if (u.u_error || sc->sc_dsreg&HTDS_BOT)
710: break;
711: }
712: return;
713:
714: default:
715: u.u_error = ENXIO;
716: return;
717: }
718: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.