xref: /original-bsd/sys/vax/mba/mt.c (revision d19c88bc)
1 /*	mt.c	4.3	82/03/14	*/
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 #ifdef lint
81 	mtread(0); mtwrite(0); mtioctl(0, 0, 0, 0);
82 #endif
83 }
84 
85 mtslave(mi, ms)
86 	struct mba_device *mi;
87 	struct mba_slave *ms;
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[ms->ms_slave] = 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 = ms->ms_slave;
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 		u.u_error = ENXIO;
122 		return;
123 	}
124 	olddens = sc->sc_dens;
125 	dens = sc->sc_dens = (minor(dev)&H_6250BPI) ? MT_GCR : 0;
126 	mtcommand(dev, MT_SENSE, 1);
127 	sc->sc_dens = olddens;
128 	if ((sc->sc_dsreg & MTDS_ONL) == 0) {
129 		uprintf("mu%d: not online\n", muunit);
130 		u.u_error = EIO;
131 		return;
132 	}
133 	if ((flag&FWRITE) && (sc->sc_dsreg&MTDS_FPT)) {
134 		uprintf("mu%d: no write ring\n", muunit);
135 		u.u_error = EIO;
136 		return;
137 	}
138 	if ((sc->sc_dsreg & MTDS_BOT) == 0 && (flag&FWRITE) &&
139 	    dens != sc->sc_dens) {
140 		uprintf("mu%d: can't change density in mid-tape\n", muunit);
141 		u.u_error = EIO;
142 		return;
143 	}
144 	sc->sc_openf = 1;
145 	sc->sc_blkno = (daddr_t)0;
146 	sc->sc_nxrec = INF;
147 	sc->sc_flags = 0;
148 	sc->sc_dens = dens;
149 }
150 
151 mtclose(dev, flag)
152 	register dev_t dev;
153 	register flag;
154 {
155 	register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
156 
157 	if (flag == FWRITE || ((flag&FWRITE) && (sc->sc_flags&H_WRITTEN)))
158 		mtcommand(dev, MT_CLS|sc->sc_dens, 1);
159 	if ((minor(dev)&H_NOREWIND) == 0)
160 		mtcommand(dev, MT_REW, 0);
161 	sc->sc_openf = 0;
162 }
163 
164 mtcommand(dev, com, count)
165 	dev_t dev;
166 	int com, count;
167 {
168 	register struct buf *bp;
169 	register int s;
170 
171 	bp = &cmtbuf[MTUNIT(dev)];
172 	s = spl5();
173 	while (bp->b_flags&B_BUSY) {
174 		if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE))
175 			break;
176 		bp->b_flags |= B_WANTED;
177 		sleep((caddr_t)bp, PRIBIO);
178 	}
179 	bp->b_flags = B_BUSY|B_READ;
180 	splx(s);
181 	bp->b_dev = dev;
182 	bp->b_command = com;
183 	bp->b_repcnt = count;
184 	bp->b_blkno = 0;
185 	mtstrategy(bp);
186 	if (count == 0)
187 		return;
188 	iowait(bp);
189 	if (bp->b_flags&B_WANTED)
190 		wakeup((caddr_t)bp);
191 	bp->b_flags &= B_ERROR;
192 }
193 
194 mtstrategy(bp)
195 	register struct buf *bp;
196 {
197 	register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)];
198 	register struct buf *dp;
199 	register int s;
200 
201 	bp->av_forw = NULL;
202 	dp = &mi->mi_tab;
203 	s = spl5();
204 	if (dp->b_actf == NULL)
205 		dp->b_actf = bp;
206 	else
207 		dp->b_actl->av_forw = bp;
208 	dp->b_actl = bp;
209 	if (dp->b_active == 0)
210 		mbustart(mi);
211 	splx(s);
212 }
213 
214 mtustart(mi)
215 	register struct mba_device *mi;
216 {
217 	register struct mtdevice *mtaddr =
218 	    (struct mtdevice *)mi->mi_drv;
219 	register struct buf *bp = mi->mi_tab.b_actf;
220 	register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
221 	daddr_t blkno;
222 
223 	sc->sc_flags &= ~H_WRITTEN;
224 	if (sc->sc_openf < 0) {
225 		bp->b_flags |= B_ERROR;
226 		return (MBU_NEXT);
227 	}
228 	if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) {
229 		if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) {
230 			bp->b_flags |= B_ERROR;
231 			bp->b_error = ENXIO;
232 			return (MBU_NEXT);
233 		}
234 		if (dbtofsb(bp->b_blkno) == sc->sc_nxrec &&
235 		    bp->b_flags&B_READ) {
236 			bp->b_resid = bp->b_bcount;
237 			clrbuf(bp);
238 			return (MBU_NEXT);
239 		}
240 		if ((bp->b_flags&B_READ)==0)
241 			sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1;
242 	} else {
243 		mtaddr->mtncs[MUUNIT(bp->b_dev)] =
244 			(bp->b_repcnt<<8)|bp->b_command|MT_GO;
245 		return (MBU_STARTED);
246 	}
247 	if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) {
248 		if (mi->mi_tab.b_errcnt == 2) {
249 			mtaddr->mtca = MUUNIT(bp->b_dev);
250 		} else {
251 			mtaddr->mtbc = bp->b_bcount;
252 			mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev);
253 		}
254 		return (MBU_DODATA);
255 	}
256 	if (blkno < dbtofsb(bp->b_blkno))
257 		mtaddr->mtncs[MUUNIT(bp->b_dev)] =
258 		  (min((unsigned)(dbtofsb(bp->b_blkno) - blkno), 0377) << 8) |
259 			MT_SFORW|MT_GO;
260 	else
261 		mtaddr->mtncs[MUUNIT(bp->b_dev)] =
262 		  (min((unsigned)(blkno - dbtofsb(bp->b_blkno)), 0377) << 8) |
263 			MT_SREV|MT_GO;
264 	return (MBU_STARTED);
265 }
266 
267 mtstart(mi)
268 	register struct mba_device *mi;
269 {
270 	register struct buf *bp = mi->mi_tab.b_actf;
271 	register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
272 
273 	if (bp->b_flags & B_READ)
274 		if (mi->mi_tab.b_errcnt == 2)
275 			return(MT_READREV|MT_GO);
276 		else
277 			return(MT_READ|MT_GO);
278 	else
279 		return(MT_WRITE|sc->sc_dens|MT_GO);
280 }
281 
282 mtdtint(mi, mbsr)
283 	register struct mba_device *mi;
284 	int mbsr;
285 {
286 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
287 	register struct buf *bp = mi->mi_tab.b_actf;
288 	register struct mu_softc *sc;
289 
290 	/* I'M NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */
291 	if ((mtaddr->mtca&3) != MUUNIT(bp->b_dev)) {
292 		printf("mt: wrong unit!\n");
293 		mtaddr->mtca = MUUNIT(bp->b_dev);
294 	}
295 	sc = &mu_softc[MUUNIT(bp->b_dev)];
296 	sc->sc_erreg = mtaddr->mter;
297 	if((bp->b_flags & B_READ) == 0)
298 		sc->sc_flags |= H_WRITTEN;
299 	switch (sc->sc_erreg & MTER_INTCODE) {
300 	case MTER_DONE:
301 	case MTER_LONGREC:
302 		if (mi->mi_tab.b_errcnt != 2)
303 			sc->sc_blkno++;
304 		bp->b_resid = 0;
305 		break;
306 
307 	case MTER_NOTCAP:
308 		printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
309 		goto err;
310 
311 	case MTER_TM:
312 	case MTER_EOT:
313 		sc->sc_blkno++;
314 	err:
315 		bp->b_resid = bp->b_bcount;
316 		sc->sc_nxrec = dbtofsb(bp->b_blkno);
317 		break;
318 
319 	case MTER_SHRTREC:
320 		sc->sc_blkno++;
321 		if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
322 			bp->b_flags |= B_ERROR;
323 		if (mi->mi_tab.b_errcnt == 2)
324 			bp->b_bcount = bp->b_resid;	/* restore saved value */
325 		bp->b_resid = bp->b_bcount - mtaddr->mtbc;
326 		break;
327 
328 	case MTER_RDOPP:
329 		mi->mi_tab.b_errcnt = 2;	/* indicate "read opposite" */
330 		bp->b_resid = bp->b_bcount;	/* save it */
331 		bp->b_bcount = mtaddr->mtbc;	/* use this instead */
332 		return(MBD_RETRY);
333 
334 	case MTER_RETRY:
335 		mi->mi_tab.b_errcnt = 1;	/* indicate simple retry */
336 		return(MBD_RETRY);
337 
338 	case MTER_OFFLINE:
339 		if (sc->sc_openf > 0) {
340 			sc->sc_openf = -1;
341 			printf("mu%d: offline\n", MUUNIT(bp->b_dev));
342 		}
343 		bp->b_flags |= B_ERROR;
344 		break;
345 
346 	case MTER_FPT:
347 		printf("mu%d: no write ring\n", MUUNIT(bp->b_dev));
348 		bp->b_flags |= B_ERROR;
349 		break;
350 
351 	default:
352 		printf("mu%d: hard error bn%d mbsr=%b er=%x ds=%b\n",
353 		    MUUNIT(bp->b_dev), bp->b_blkno,
354 		    mbsr, mbsr_bits, sc->sc_erreg,
355 		    sc->sc_dsreg, mtds_bits);
356 		bp->b_flags |= B_ERROR;
357 		mtaddr->mtid = MTID_CLR;		/* reset the TM78 */
358 		DELAY(250);
359 		while ((mtaddr->mtid & MTID_RDY) == 0)	/* wait for it */
360 			;
361 		return (MBD_DONE);
362 	}
363 	/* CHECK FOR MBA ERROR WHEN NO OTHER ERROR INDICATED? */
364 	return (MBD_DONE);
365 }
366 
367 mtndtint(mi)
368 	register struct mba_device *mi;
369 {
370 	register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
371 	register struct buf *bp = mi->mi_tab.b_actf;
372 	register struct mu_softc *sc;
373 	int er, fc, unit;
374 
375 	unit = (mtaddr->mtner >> 8) & 3;
376 	er = MASKREG(mtaddr->mtner);
377 	/* WILL THIS OCCUR IF ANOTHER DRIVE COMES ONLINE? */
378 	if (bp == 0 || unit != MUUNIT(bp->b_dev)) {	/* consistency check */
379 		if ((er & MTER_INTCODE) != MTER_ONLINE)
380 			printf("mt: unit %d random interrupt\n", unit);
381 		return (MBN_SKIP);
382 	}
383 	if (bp == 0)
384 		return (MBN_SKIP);
385 	fc = (mtaddr->mtncs[unit] >> 8) & 0xff;
386 	sc = &mu_softc[unit];
387 	sc->sc_erreg = er;
388 	sc->sc_resid = fc;
389 	switch (er & MTER_INTCODE) {
390 	case MTER_DONE:
391 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
392 	done:
393 			if (bp->b_command == MT_SENSE)
394 				sc->sc_dsreg = MASKREG(mtaddr->mtds);
395 			bp->b_resid = fc;
396 			return (MBN_DONE);
397 		}
398 		/* this is UGLY!  (but is it correct?) */
399 		if ((fc = dbtofsb(bp->b_blkno) - sc->sc_blkno) < 0)
400 			sc->sc_blkno -= MIN(0377, -fc);
401 		else
402 			sc->sc_blkno += MIN(0377, fc);
403 		return (MBN_RETRY);
404 
405 	case MTER_RWDING:
406 		return (MBN_SKIP);	/* ignore "rewind started" interrupt */
407 
408 	case MTER_NOTCAP:
409 		printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
410 
411 	case MTER_TM:
412 	case MTER_EOT:
413 	case MTER_LEOT:
414 		if (sc->sc_blkno > dbtofsb(bp->b_blkno)) {
415 			sc->sc_nxrec = dbtofsb(bp->b_blkno) + fc;
416 			sc->sc_blkno = sc->sc_nxrec;
417 		} else {
418 			sc->sc_blkno = dbtofsb(bp->b_blkno) - fc;
419 			sc->sc_nxrec = sc->sc_blkno - 1;
420 		}
421 		return (MBN_RETRY);
422 
423 	case MTER_FPT:
424 		printf("mu%d: no write ring\n", MUUNIT(bp->b_dev));
425 		bp->b_flags |= B_ERROR;
426 		return (MBN_DONE);
427 
428 	case MTER_OFFLINE:
429 		if (sc->sc_openf > 0) {
430 			sc->sc_openf = -1;
431 			printf("mu%d: offline\n", MUUNIT(bp->b_dev));
432 		}
433 		bp->b_flags |= B_ERROR;
434 		return (MBN_DONE);
435 
436 	case MTER_BOT:
437 		if (bp == &cmtbuf[MTUNIT(bp->b_dev)])
438 			goto done;
439 		/* FALL THROUGH */
440 
441 	default:
442 		printf("mu%d: hard error bn%d er=%o ds=%b\n",
443 		    MUUNIT(bp->b_dev), bp->b_blkno,
444 		    sc->sc_erreg, sc->sc_dsreg, mtds_bits);
445 		mtaddr->mtid = MTID_CLR;		/* reset the TM78 */
446 		DELAY(250);
447 		while ((mtaddr->mtid & MTID_RDY) == 0)	/* wait for it */
448 			;
449 		bp->b_flags |= B_ERROR;
450 		return (MBN_DONE);
451 	}
452 	/* NOTREACHED */
453 }
454 
455 mtread(dev)
456 	dev_t dev;
457 {
458 
459 	mtphys(dev);
460 	if (u.u_error)
461 		return;
462 	physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys);
463 }
464 
465 mtwrite(dev)
466 {
467 
468 	mtphys(dev);
469 	if (u.u_error)
470 		return;
471 	physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys);
472 }
473 
474 mtphys(dev)
475 	dev_t dev;
476 {
477 	register int mtunit;
478 	register struct mu_softc *sc;
479 	register struct mba_device *mi;
480 	daddr_t a;
481 
482 	mtunit = MTUNIT(dev);
483 	if (mtunit >= NMT || (mi = mtinfo[mtunit]) == 0 || mi->mi_alive == 0) {
484 		u.u_error = ENXIO;
485 		return;
486 	}
487 	a = u.u_offset >> 9;
488 	sc = &mu_softc[MUUNIT(dev)];
489 	sc->sc_blkno = dbtofsb(a);
490 	sc->sc_nxrec = dbtofsb(a)+1;
491 }
492 
493 /*ARGSUSED*/
494 mtioctl(dev, cmd, addr, flag)
495 	dev_t dev;
496 	int cmd;
497 	caddr_t addr;
498 	int flag;
499 {
500 	register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
501 	register struct buf *bp = &cmtbuf[MTUNIT(dev)];
502 	register callcount;
503 	register int op;
504 	int fcount;
505 	struct mtop mtop;
506 	struct mtget mtget;
507 	/* we depend of the values and order of the MT codes here */
508 	static mtops[] =
509 	{MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE};
510 
511 	switch (cmd) {
512 		case MTIOCTOP:	/* tape operation */
513 		if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
514 			u.u_error = EFAULT;
515 			return;
516 		}
517 		switch(mtop.mt_op) {
518 		case MTWEOF:
519 			callcount = mtop.mt_count;
520 			fcount = 1;
521 			break;
522 		case MTFSF: case MTBSF:
523 			callcount = mtop.mt_count;
524 			fcount = 1;
525 			break;
526 		case MTFSR: case MTBSR:
527 			callcount = 1;
528 			fcount = mtop.mt_count;
529 			break;
530 		case MTREW: case MTOFFL:
531 			callcount = 1;
532 			fcount = 1;
533 			break;
534 		default:
535 			u.u_error = ENXIO;
536 			return;
537 		}
538 		if (callcount <= 0 || fcount <= 0) {
539 			u.u_error = ENXIO;
540 			return;
541 		}
542 		op = mtops[mtop.mt_op];
543 		if (op == MT_WTM)
544 			op |= sc->sc_dens;
545 		while (--callcount >= 0) {
546 			register int n;
547 
548 			do {
549 				n = MIN(fcount, 0xff);
550 				mtcommand(dev, op, n);
551 				fcount -= n;
552 			} while (fcount);
553 			if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) &&
554 			    bp->b_resid) {
555 				u.u_error = EIO;
556 				break;
557 			}
558 			if (bp->b_flags&B_ERROR)
559 				break;
560 		}
561 		geterror(bp);
562 		return;
563 	case MTIOCGET:
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 		if (copyout((caddr_t)&mtget, addr, sizeof(mtget)))
570 			u.u_error = EFAULT;
571 		return;
572 	default:
573 		u.u_error = ENXIO;
574 	}
575 }
576 
577 #define	DBSIZE	20
578 
579 mtdump()
580 {
581 	register struct mba_device *mi;
582 	register struct mba_regs *mp;
583 	register struct mtdevice *mtaddr;
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 = blk; num = num; start = 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