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