xref: /original-bsd/sys/vax/mba/mt.c (revision c43e4352)
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
656