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