xref: /csrg-svn/sys/vax/uba/tm.c (revision 2928)
1 /*	tm.c	4.22	03/06/81	*/
2 
3 #include "te.h"
4 #if NTM > 0
5 int	tmgapsdcnt;		/* DEBUG */
6 /*
7  * TM11/TE10 tape driver
8  *
9  * Todo:
10  *	Test driver with more than one slave
11  *	Test reset code
12  *	Do rewinds without hanging in driver
13  */
14 #define	DELAY(N)		{ register int d = N; while (--d > 0); }
15 #include "../h/param.h"
16 #include "../h/buf.h"
17 #include "../h/dir.h"
18 #include "../h/conf.h"
19 #include "../h/user.h"
20 #include "../h/file.h"
21 #include "../h/map.h"
22 #include "../h/pte.h"
23 #include "../h/vm.h"
24 #include "../h/uba.h"
25 #include "../h/mtio.h"
26 #include "../h/ioctl.h"
27 #include "../h/cmap.h"
28 #include "../h/cpu.h"
29 
30 #include "../h/tmreg.h"
31 
32 struct	buf	ctmbuf[NTE];
33 struct	buf	rtmbuf[NTE];
34 
35 int	tmprobe(), tmslave(), tmattach(), tmdgo(), tmintr();
36 struct	uba_minfo *tmminfo[NTM];
37 struct	uba_dinfo *tmdinfo[NTE];
38 struct	buf tmutab[NTE];
39 #ifdef notyet
40 struct	uba_dinfo *tmip[NTM][4];
41 #endif
42 u_short	tmstd[] = { 0772520, 0 };
43 struct	uba_driver tmdriver =
44  { tmprobe, tmslave, tmattach, tmdgo, tmstd, "te", tmdinfo, "tm", tmminfo, 0 };
45 
46 /* bits in minor device */
47 #define	TMUNIT(dev)	(minor(dev)&03)
48 #define	T_NOREWIND	04
49 #define	T_1600BPI	08
50 
51 #define	INF	(daddr_t)1000000L
52 
53 /*
54  * Software state per tape transport.
55  */
56 struct	tm_softc {
57 	char	sc_openf;	/* lock against multiple opens */
58 	char	sc_lastiow;	/* last op was a write */
59 	daddr_t	sc_blkno;	/* block number, for block device tape */
60 	daddr_t	sc_nxrec;	/* desired block position */
61 	u_short	sc_erreg;	/* copy of last erreg */
62 	u_short	sc_dsreg;	/* copy of last dsreg */
63 	short	sc_resid;	/* copy of last bc */
64 #ifdef notdef
65 	short	sc_lastcmd;	/* last command to handle direction changes */
66 #endif
67 } tm_softc[NTM];
68 
69 /*
70  * States for um->um_tab.b_active, the
71  * per controller state flag.
72  */
73 #define	SSEEK	1		/* seeking */
74 #define	SIO	2		/* doing seq i/o */
75 #define	SCOM	3		/* sending control command */
76 #define	SREW	4		/* sending a drive rewind */
77 
78 /* WE CURRENTLY HANDLE REWINDS PRIMITIVELY, BUSYING OUT THE CONTROLLER */
79 /* DURING THE REWIND... IF WE EVER GET TWO TRANSPORTS, WE CAN DEBUG MORE */
80 /* SOPHISTICATED LOGIC... THIS SIMPLE CODE AT LEAST MAY WORK. */
81 
82 /*
83  * Determine if there is a controller for
84  * a tm at address reg.  Our goal is to make the
85  * device interrupt.
86  */
87 tmprobe(reg)
88 	caddr_t reg;
89 {
90 	register int br, cvec;
91 
92 #ifdef lint
93 	br = 0; br = cvec; cvec = br;
94 #endif
95 	((struct device *)reg)->tmcs = TM_IE;
96 	/*
97 	 * If this is a tm11, it ought to have interrupted
98 	 * by now, if it isn't (ie: it is a ts04) then we just
99 	 * hope that it didn't interrupt, so autoconf will ignore it.
100 	 * Just in case, we will reference one
101 	 * of the more distant registers, and hope for a machine
102 	 * check, or similar disaster if this is a ts.
103 	 *
104 	 * Note: on an 11/780, badaddr will just generate
105 	 * a uba error for a ts; but our caller will notice that
106 	 * so we won't check for it.
107 	 */
108 	if (badaddr(&((struct device *)reg)->tmrd, 2))
109 		return (0);
110 	return (1);
111 }
112 
113 /*
114  * Due to a design flaw, we cannot ascertain if the tape
115  * exists or not unless it is on line - ie: unless a tape is
116  * mounted. This is too servere a restriction to bear,
117  * so all units are assumed to exist.
118  */
119 /*ARGSUSED*/
120 tmslave(ui, reg)
121 	struct uba_dinfo *ui;
122 	caddr_t reg;
123 {
124 
125 	return (1);
126 }
127 
128 /*
129  * Record attachment of the unit to the controller port.
130  */
131 /*ARGSUSED*/
132 tmattach(ui)
133 	struct uba_dinfo *ui;
134 {
135 
136 #ifdef notyet
137 	tmip[ui->ui_ctlr][ui->ui_slave] = ui;
138 #endif
139 }
140 
141 /*
142  * Open the device.  Tapes are unique open
143  * devices, so we refuse if it is already open.
144  * We also check that a tape is available, and
145  * don't block waiting here.
146  */
147 tmopen(dev, flag)
148 	dev_t dev;
149 	int flag;
150 {
151 	register int unit;
152 	register struct uba_dinfo *ui;
153 	register struct tm_softc *sc;
154 
155 	unit = TMUNIT(dev);
156 	if (unit>=NTE || (sc = &tm_softc[unit])->sc_openf ||
157 	    (ui = tmdinfo[unit]) == 0 || ui->ui_alive == 0) {
158 		u.u_error = ENXIO;
159 		return;
160 	}
161 	tmcommand(dev, TM_SENSE, 1);
162 	if ((sc->sc_erreg&(TM_SELR|TM_TUR)) != (TM_SELR|TM_TUR) ||
163 	    (flag&(FREAD|FWRITE)) == FWRITE && sc->sc_erreg&TM_WRL) {
164 		u.u_error = EIO;
165 		return;
166 	}
167 	sc->sc_openf = 1;
168 	sc->sc_blkno = (daddr_t)0;
169 	sc->sc_nxrec = INF;
170 	sc->sc_lastiow = 0;
171 }
172 
173 /*
174  * Close tape device.
175  *
176  * If tape was open for writing or last operation was
177  * a write, then write two EOF's and backspace over the last one.
178  * Unless this is a non-rewinding special file, rewind the tape.
179  * Make the tape available to others.
180  */
181 tmclose(dev, flag)
182 	register dev_t dev;
183 	register flag;
184 {
185 	register struct tm_softc *sc = &tm_softc[TMUNIT(dev)];
186 
187 	if (flag == FWRITE || (flag&FWRITE) && sc->sc_lastiow) {
188 		tmcommand(dev, TM_WEOF, 1);
189 		tmcommand(dev, TM_WEOF, 1);
190 		tmcommand(dev, TM_SREV, 1);
191 	}
192 	if ((minor(dev)&T_NOREWIND) == 0)
193 		tmcommand(dev, TM_REW, 1);
194 	sc->sc_openf = 0;
195 }
196 
197 /*
198  * Execute a command on the tape drive
199  * a specified number of times.
200  */
201 tmcommand(dev, com, count)
202 	dev_t dev;
203 	int com, count;
204 {
205 	register struct buf *bp;
206 
207 	bp = &ctmbuf[TMUNIT(dev)];
208 	(void) spl5();
209 	while (bp->b_flags&B_BUSY) {
210 		bp->b_flags |= B_WANTED;
211 		sleep((caddr_t)bp, PRIBIO);
212 	}
213 	bp->b_flags = B_BUSY|B_READ;
214 	(void) spl0();
215 	bp->b_dev = dev;
216 	bp->b_repcnt = -count;
217 	bp->b_command = com;
218 	bp->b_blkno = 0;
219 	tmstrategy(bp);
220 	iowait(bp);
221 	if (bp->b_flags&B_WANTED)
222 		wakeup((caddr_t)bp);
223 	bp->b_flags &= B_ERROR;
224 }
225 
226 /*
227  * Decipher a tape operation and do what is needed
228  * to see that it happens.
229  */
230 tmstrategy(bp)
231 	register struct buf *bp;
232 {
233 	int unit = TMUNIT(bp->b_dev);
234 	register struct uba_minfo *um;
235 	register struct buf *dp;
236 	register struct tm_softc *sc = &tm_softc[unit];
237 
238 	/*
239 	 * Put transfer at end of unit queue
240 	 */
241 	dp = &tmutab[unit];
242 	bp->av_forw = NULL;
243 	(void) spl5();
244 	if (dp->b_actf == NULL) {
245 		dp->b_actf = bp;
246 		/*
247 		 * Transport not already active...
248 		 * put at end of controller queue.
249 		 */
250 		dp->b_forw = NULL;
251 		um = tmdinfo[unit]->ui_mi;
252 		if (um->um_tab.b_actf == NULL)
253 			um->um_tab.b_actf = dp;
254 		else
255 			um->um_tab.b_actl->b_forw = dp;
256 		um->um_tab.b_actl = dp;
257 	} else
258 		dp->b_actl->av_forw = bp;
259 	dp->b_actl = bp;
260 	/*
261 	 * If the controller is not busy, get
262 	 * it going.
263 	 */
264 	if (um->um_tab.b_active == 0)
265 		tmstart(um);
266 	(void) spl0();
267 }
268 
269 /*
270  * Start activity on a tm controller.
271  */
272 tmstart(um)
273 	register struct uba_minfo *um;
274 {
275 	register struct buf *bp, *dp;
276 	register struct device *addr = (struct device *)um->um_addr;
277 	register struct tm_softc *sc;
278 	register struct uba_dinfo *ui;
279 	int unit, cmd;
280 	daddr_t blkno;
281 
282 	/*
283 	 * Look for an idle transport on the controller.
284 	 */
285 loop:
286 	if ((dp = um->um_tab.b_actf) == NULL)
287 		return;
288 	if ((bp = dp->b_actf) == NULL) {
289 		um->um_tab.b_actf = dp->b_forw;
290 		goto loop;
291 	}
292 	unit = TMUNIT(bp->b_dev);
293 	ui = tmdinfo[unit];
294 	/*
295 	 * Record pre-transfer status (e.g. for TM_SENSE)
296 	 */
297 	sc = &tm_softc[unit];
298 	addr = (struct device *)um->um_addr;
299 	addr->tmcs = (ui->ui_slave << 8);
300 	sc->sc_dsreg = addr->tmcs;
301 	sc->sc_erreg = addr->tmer;
302 	sc->sc_resid = addr->tmbc;
303 	/*
304 	 * Default is that last command was NOT a write command;
305 	 * if we do a write command we will notice this in tmintr().
306 	 */
307 	sc->sc_lastiow = 1;
308 	if (sc->sc_openf < 0 || (addr->tmcs&TM_CUR) == 0) {
309 		/*
310 		 * Have had a hard error on this (non-raw) tape,
311 		 * or the tape unit is now unavailable (e.g. taken off
312 		 * line).
313 		 */
314 		bp->b_flags |= B_ERROR;
315 		goto next;
316 	}
317 	/*
318 	 * If operation is not a control operation,
319 	 * check for boundary conditions.
320 	 */
321 	if (bp != &ctmbuf[unit]) {
322 		if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) {
323 			bp->b_flags |= B_ERROR;
324 			bp->b_error = ENXIO;		/* past EOF */
325 			goto next;
326 		}
327 		if (dbtofsb(bp->b_blkno) == sc->sc_nxrec &&
328 		    bp->b_flags&B_READ) {
329 			bp->b_resid = bp->b_bcount;
330 			clrbuf(bp);			/* at EOF */
331 			goto next;
332 		}
333 		if ((bp->b_flags&B_READ) == 0)
334 			/* write sets EOF */
335 			sc->sc_nxrec = dbtofsb(bp->b_blkno) + 1;
336 	}
337 	/*
338 	 * Set up the command, and then if this is a mt ioctl,
339 	 * do the operation using, for TM_SFORW and TM_SREV, the specified
340 	 * operation count.
341 	 */
342 	cmd = TM_IE | TM_GO | (ui->ui_slave << 8);
343 	if ((minor(bp->b_dev) & T_1600BPI) == 0)
344 		cmd |= TM_D800;
345 	if (bp == &ctmbuf[unit]) {
346 		if (bp->b_command == TM_SENSE)
347 			goto next;
348 		um->um_tab.b_active =
349 		    bp->b_command == TM_REW ? SREW : SCOM;
350 		if (bp->b_command == TM_SFORW || bp->b_command == TM_SREV)
351 			addr->tmbc = bp->b_repcnt;
352 		goto dobpcmd;
353 	}
354 	/*
355 	 * If the data transfer command is in the correct place,
356 	 * set up all the registers except the csr, and give
357 	 * control over to the UNIBUS adapter routines, to
358 	 * wait for resources to start the i/o.
359 	 */
360 	if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) {
361 		addr->tmbc = -bp->b_bcount;
362 		if ((bp->b_flags&B_READ) == 0) {
363 			if (um->um_tab.b_errcnt)
364 				cmd |= TM_WIRG;
365 			else
366 				cmd |= TM_WCOM;
367 		} else
368 			cmd |= TM_RCOM;
369 		um->um_tab.b_active = SIO;
370 		um->um_cmd = cmd;
371 #ifdef notdef
372 		if (tmreverseop(sc->sc_lastcmd))
373 			while (addr->tmer & TM_SDWN)
374 				tmgapsdcnt++;
375 		sc->sc_lastcmd = TM_RCOM;		/* will serve */
376 #endif
377 		ubago(ui);
378 		return;
379 	}
380 	/*
381 	 * Block tape positioned incorrectly;
382 	 * seek forwards or backwards to the correct spot.
383 	 */
384 	um->um_tab.b_active = SSEEK;
385 	if (blkno < dbtofsb(bp->b_blkno)) {
386 		bp->b_command = TM_SFORW;
387 		addr->tmbc = blkno - dbtofsb(bp->b_blkno);
388 	} else {
389 		bp->b_command = TM_SREV;
390 		addr->tmbc = dbtofsb(bp->b_blkno) - blkno;
391 	}
392 dobpcmd:
393 #ifdef notdef
394 	if (tmreverseop(sc->sc_lastcmd) != tmreverseop(bp->b_command))
395 		while (addr->tmer & TM_SDWN)
396 			tmgapsdcnt++;
397 	sc->sc_lastcmd = bp->b_command;
398 #endif
399 	addr->tmcs = (cmd | bp->b_command);
400 	return;
401 
402 next:
403 	/*
404 	 * Done with this operation due to error or
405 	 * the fact that it doesn't do anything.
406 	 * Release UBA resources (if any), dequeue
407 	 * the transfer and continue processing this slave.
408 	 */
409 	if (um->um_ubinfo)
410 		ubadone(um);
411 	um->um_tab.b_errcnt = 0;
412 	dp->b_actf = bp->av_forw;
413 	iodone(bp);
414 	goto loop;
415 }
416 
417 /*
418  * The UNIBUS resources we needed have been
419  * allocated to us; start the device.
420  */
421 tmdgo(um)
422 	register struct uba_minfo *um;
423 {
424 	register struct device *addr = (struct device *)um->um_addr;
425 
426 	addr->tmba = um->um_ubinfo;
427 	addr->tmcs = um->um_cmd | ((um->um_ubinfo >> 12) & 0x30);
428 }
429 
430 /*
431  * Tm interrupt routine.
432  */
433 /*ARGSUSED*/
434 tmintr(tm11)
435 	int tm11;
436 {
437 	struct buf *dp;
438 	register struct buf *bp;
439 	register struct uba_minfo *um = tmminfo[tm11];
440 	register struct device *addr = (struct device *)tmdinfo[tm11]->ui_addr;
441 	register struct tm_softc *sc;
442 	int unit;
443 	register state;
444 
445 	/*
446 	 * If last command was a rewind, and tape is still
447 	 * rewinding, wait for the rewind complete interrupt.
448 	 */
449 	if (um->um_tab.b_active == SREW) {
450 		um->um_tab.b_active = SCOM;
451 		if (addr->tmer&TM_RWS)
452 			return;
453 	}
454 	/*
455 	 * An operation completed... record status
456 	 */
457 	if ((dp = um->um_tab.b_actf) == NULL)
458 		return;
459 	bp = dp->b_actf;
460 	unit = TMUNIT(bp->b_dev);
461 	sc = &tm_softc[unit];
462 	sc->sc_dsreg = addr->tmcs;
463 	sc->sc_erreg = addr->tmer;
464 	sc->sc_resid = addr->tmbc;
465 	if ((bp->b_flags & B_READ) == 0)
466 		sc->sc_lastiow = 1;
467 	state = um->um_tab.b_active;
468 	um->um_tab.b_active = 0;
469 	/*
470 	 * Check for errors.
471 	 */
472 	if (addr->tmcs&TM_ERR) {
473 		while (addr->tmer & TM_SDWN)
474 			;			/* await settle down */
475 		/*
476 		 * If we hit the end of the tape update our position.
477 		 */
478 		if (addr->tmer&TM_EOF) {
479 			tmseteof(bp);		/* set blkno and nxrec */
480 			state = SCOM;		/* force completion */
481 			/*
482 			 * Stuff bc so it will be unstuffed correctly
483 			 * later to get resid.
484 			 */
485 			addr->tmbc = -bp->b_bcount;
486 			goto opdone;
487 		}
488 		/*
489 		 * If we were reading and the only error was that the
490 		 * record was to long, then we don't consider this an error.
491 		 */
492 		if ((bp->b_flags&B_READ) &&
493 		    (addr->tmer&(TM_HARD|TM_SOFT)) == TM_RLE)
494 			goto ignoreerr;
495 		/*
496 		 * If error is not hard, and this was an i/o operation
497 		 * retry up to 8 times.
498 		 */
499 		if ((addr->tmer&TM_HARD)==0 && state==SIO) {
500 			if (++um->um_tab.b_errcnt < 7) {
501 				sc->sc_blkno++;
502 				ubadone(um);
503 				goto opcont;
504 			}
505 		} else
506 			/*
507 			 * Hard or non-i/o errors on non-raw tape
508 			 * cause it to close.
509 			 */
510 			if (sc->sc_openf>0 && bp != &rtmbuf[unit])
511 				sc->sc_openf = -1;
512 		/*
513 		 * Couldn't recover error
514 		 */
515 		printf("te%d: hard error bn%d er=%b\n", minor(bp->b_dev)&03,
516 		    bp->b_blkno, sc->sc_erreg, TMEREG_BITS);
517 		bp->b_flags |= B_ERROR;
518 		goto opdone;
519 	}
520 	/*
521 	 * Advance tape control FSM.
522 	 */
523 ignoreerr:
524 	switch (state) {
525 
526 	case SIO:
527 		/*
528 		 * Read/write increments tape block number
529 		 */
530 		sc->sc_blkno++;
531 		goto opdone;
532 
533 	case SCOM:
534 		/*
535 		 * Unless special operation, op completed.
536 		 */
537 		if (bp != &ctmbuf[unit])
538 			goto opdone;
539 		/*
540 		 * Operation on block device...
541 		 * iterate operations which don't repeat
542 		 * for themselves in the hardware; for forward/
543 		 * backward space record update the current position.
544 		 */
545 		switch (bp->b_command) {
546 
547 		case TM_SFORW:
548 			sc->sc_blkno -= bp->b_repcnt;
549 			goto opdone;
550 
551 		case TM_SREV:
552 			sc->sc_blkno += bp->b_repcnt;
553 			goto opdone;
554 
555 		default:
556 			if (++bp->b_repcnt < 0)
557 				goto opcont;
558 			goto opdone;
559 		}
560 
561 	case SSEEK:
562 		sc->sc_blkno = dbtofsb(bp->b_blkno);
563 		goto opcont;
564 
565 	default:
566 		panic("tmintr");
567 	}
568 opdone:
569 	/*
570 	 * Reset error count and remove
571 	 * from device queue.
572 	 */
573 	um->um_tab.b_errcnt = 0;
574 	dp->b_actf = bp->av_forw;
575 	bp->b_resid = -addr->tmbc;
576 	ubadone(um);
577 	iodone(bp);
578 	/*
579 	 * Circulate slave to end of controller
580 	 * queue to give other slaves a chance.
581 	 */
582 	um->um_tab.b_actf = dp->b_forw;
583 	if (dp->b_actf) {
584 		dp->b_forw = NULL;
585 		if (um->um_tab.b_actf == NULL)
586 			um->um_tab.b_actf = dp;
587 		else
588 			um->um_tab.b_actl->b_forw = dp;
589 		um->um_tab.b_actl = dp;
590 	}
591 	if (um->um_tab.b_actf == 0)
592 		return;
593 opcont:
594 	tmstart(um);
595 }
596 
597 tmseteof(bp)
598 	register struct buf *bp;
599 {
600 	register int unit = TMUNIT(bp->b_dev);
601 	register struct device *addr =
602 	    (struct device *)tmdinfo[unit]->ui_addr;
603 	register struct tm_softc *sc = &tm_softc[unit];
604 
605 	if (bp == &ctmbuf[unit]) {
606 		if (sc->sc_blkno > dbtofsb(bp->b_blkno)) {
607 			/* reversing */
608 			sc->sc_nxrec = dbtofsb(bp->b_blkno) - addr->tmbc;
609 			sc->sc_blkno = sc->sc_nxrec;
610 		} else {
611 			/* spacing forward */
612 			sc->sc_blkno = dbtofsb(bp->b_blkno) + addr->tmbc;
613 			sc->sc_nxrec = sc->sc_blkno - 1;
614 		}
615 		return;
616 	}
617 	/* eof on read */
618 	sc->sc_nxrec = dbtofsb(bp->b_blkno);
619 }
620 
621 tmread(dev)
622 	dev_t dev;
623 {
624 
625 	tmphys(dev);
626 	physio(tmstrategy, &rtmbuf[TMUNIT(dev)], dev, B_READ, minphys);
627 }
628 
629 tmwrite(dev)
630 	dev_t dev;
631 {
632 
633 	tmphys(dev);
634 	physio(tmstrategy, &rtmbuf[TMUNIT(dev)], dev, B_WRITE, minphys);
635 }
636 
637 tmphys(dev)
638 	dev_t dev;
639 {
640 	register daddr_t a;
641 	register struct tm_softc *sc = &tm_softc[TMUNIT(dev)];
642 
643 	a = dbtofsb(u.u_offset >> 9);
644 	sc->sc_blkno = a;
645 	sc->sc_nxrec = a + 1;
646 }
647 
648 tmreset(uban)
649 	int uban;
650 {
651 	register struct uba_minfo *um;
652 	register tm11, unit;
653 	register struct uba_dinfo *ui;
654 	register struct buf *dp;
655 
656 	for (tm11 = 0; tm11 < NTM; tm11++) {
657 		if ((um = tmminfo[tm11]) == 0 || um->um_alive == 0 ||
658 		   um->um_ubanum != uban)
659 			continue;
660 		printf(" tm%d", tm11);
661 		um->um_tab.b_active = 0;
662 		um->um_tab.b_actf = um->um_tab.b_actl = 0;
663 		if (um->um_ubinfo) {
664 			printf("<%d>", (um->um_ubinfo>>28)&0xf);
665 			ubadone(um);
666 		}
667 		((struct device *)(um->um_addr))->tmcs = TM_DCLR;
668 		for (unit = 0; unit < NTE; unit++) {
669 			if ((ui = tmdinfo[unit]) == 0)
670 				continue;
671 			if (ui->ui_alive == 0)
672 				continue;
673 			dp = &tmutab[unit];
674 			dp->b_active = 0;
675 			dp->b_forw = 0;
676 			if (um->um_tab.b_actf == NULL)
677 				um->um_tab.b_actf = dp;
678 			else
679 				um->um_tab.b_actl->b_forw = dp;
680 			um->um_tab.b_actl = dp;
681 			tm_softc[unit].sc_openf = -1;
682 		}
683 		tmstart(um);
684 	}
685 }
686 
687 /*ARGSUSED*/
688 tmioctl(dev, cmd, addr, flag)
689 	caddr_t addr;
690 	dev_t dev;
691 {
692 	int unit = TMUNIT(dev);
693 	register struct tm_softc *sc = &tm_softc[unit];
694 	register struct buf *bp = &ctmbuf[unit];
695 	register callcount;
696 	int fcount;
697 	struct mtop mtop;
698 	struct mtget mtget;
699 	/* we depend of the values and order of the MT codes here */
700 	static tmops[] =
701 	   {TM_WEOF,TM_SFORW,TM_SREV,TM_SFORW,TM_SREV,TM_REW,TM_OFFL,TM_SENSE};
702 
703 	switch (cmd) {
704 		case MTIOCTOP:	/* tape operation */
705 		if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
706 			u.u_error = EFAULT;
707 			return;
708 		}
709 		switch(mtop.mt_op) {
710 		case MTWEOF:
711 			callcount = mtop.mt_count;
712 			fcount = 1;
713 			break;
714 		case MTFSF: case MTBSF:
715 			callcount = mtop.mt_count;
716 			fcount = INF;
717 			break;
718 		case MTFSR: case MTBSR:
719 			callcount = 1;
720 			fcount = mtop.mt_count;
721 			break;
722 		case MTREW: case MTOFFL: case MTNOP:
723 			callcount = 1;
724 			fcount = 1;
725 			break;
726 		default:
727 			u.u_error = ENXIO;
728 			return;
729 		}
730 		if (callcount <= 0 || fcount <= 0) {
731 			u.u_error = ENXIO;
732 			return;
733 		}
734 		while (--callcount >= 0) {
735 			tmcommand(dev, tmops[mtop.mt_op], fcount);
736 			if ((mtop.mt_op == MTFSR || mtop.mt_op == MTBSR) &&
737 			    bp->b_resid) {
738 				u.u_error = EIO;
739 				break;
740 			}
741 			if ((bp->b_flags&B_ERROR) || sc->sc_erreg&TM_BOT)
742 				break;
743 		}
744 		geterror(bp);
745 		return;
746 	case MTIOCGET:
747 		mtget.mt_dsreg = sc->sc_dsreg;
748 		mtget.mt_erreg = sc->sc_erreg;
749 		mtget.mt_resid = sc->sc_resid;
750 		if (copyout((caddr_t)&mtget, addr, sizeof(mtget)))
751 			u.u_error = EFAULT;
752 		return;
753 	default:
754 		u.u_error = ENXIO;
755 	}
756 }
757 
758 #define	DBSIZE	20
759 
760 tmdump()
761 {
762 	register struct uba_dinfo *ui;
763 	register struct uba_regs *up;
764 	register struct device *addr;
765 	int blk, num;
766 	int start;
767 
768 	start = 0;
769 	num = maxfree;
770 #define	phys(a,b)	((b)((int)(a)&0x7fffffff))
771 	if (tmdinfo[0] == 0)
772 		return (ENXIO);
773 	ui = phys(tmdinfo[0], struct uba_dinfo *);
774 	up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba;
775 #if VAX780
776 	if (cpu == VAX_780)
777 		ubainit(up);
778 #endif
779 	DELAY(1000000);
780 	addr = (struct device *)ui->ui_physaddr;
781 	tmwait(addr);
782 	addr->tmcs = TM_DCLR | TM_GO;
783 	while (num > 0) {
784 		blk = num > DBSIZE ? DBSIZE : num;
785 		tmdwrite(start, blk, addr, up);
786 		start += blk;
787 		num -= blk;
788 	}
789 	tmeof(addr);
790 	tmeof(addr);
791 	tmwait(addr);
792 	if (addr->tmcs&TM_ERR)
793 		return (EIO);
794 	addr->tmcs = TM_REW | TM_GO;
795 	tmwait(addr);
796 	return (0);
797 }
798 
799 tmdwrite(dbuf, num, addr, up)
800 	register dbuf, num;
801 	register struct device *addr;
802 	struct uba_regs *up;
803 {
804 	register struct pte *io;
805 	register int npf;
806 
807 	tmwait(addr);
808 	io = up->uba_map;
809 	npf = num+1;
810 	while (--npf != 0)
811 		 *(int *)io++ = (dbuf++ | (1<<UBA_DPSHIFT) | UBA_MRV);
812 	*(int *)io = 0;
813 	addr->tmbc = -(num*NBPG);
814 	addr->tmba = 0;
815 	addr->tmcs = TM_WCOM | TM_GO;
816 }
817 
818 tmwait(addr)
819 	register struct device *addr;
820 {
821 	register s;
822 
823 	do
824 		s = addr->tmcs;
825 	while ((s & TM_CUR) == 0);
826 }
827 
828 tmeof(addr)
829 	struct device *addr;
830 {
831 
832 	tmwait(addr);
833 	addr->tmcs = TM_WEOF | TM_GO;
834 }
835 #endif
836