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