xref: /csrg-svn/sys/vax/uba/ut.c (revision 4877)
1 /*	ut.c	4.8	81/11/13	*/
2 
3 #include "tj.h"
4 #if NUT > 0
5 /*
6  * System Industries Model 9700 Tape Drive
7  *   emulates a TU45 on the UNIBUS
8  *
9  * TODO:
10  *	check out attention processing
11  *	try reset code and dump code
12  */
13 #include "../h/param.h"
14 #include "../h/systm.h"
15 #include "../h/buf.h"
16 #include "../h/conf.h"
17 #include "../h/dir.h"
18 #include "../h/file.h"
19 #include "../h/user.h"
20 #include "../h/map.h"
21 #include "../h/pte.h"
22 #include "../h/ubareg.h"
23 #include "../h/ubavar.h"
24 #include "../h/mtio.h"
25 #include "../h/ioctl.h"
26 #include "../h/cmap.h"
27 #include "../h/cpu.h"
28 
29 #include "../h/utreg.h"
30 
31 struct	buf	rutbuf[NUT];	/* bufs for raw i/o */
32 struct	buf	cutbuf[NUT];	/* bufs for control operations */
33 struct	buf	tjutab[NTJ];	/* bufs for slave queue headers */
34 
35 struct uba_ctlr *utminfo[NUT];
36 struct uba_device *tjdinfo[NTJ];
37 int utprobe(), utslave(), utattach(), utdgo(), utintr(), uttimer();
38 u_short utstd[] = { 0772440, 0 };
39 struct uba_driver utdriver =
40   { utprobe, utslave, utattach, utdgo, utstd, "tj", tjdinfo, "ut", utminfo, 0 };
41 
42 /* bits in minor device */
43 #define	TJUNIT(dev)	(minor(dev)&03)
44 #define	T_NOREWIND	04
45 #define	T_1600BPI	010
46 #define	T_6250BPI	020
47 short	utdens[] = { UT_NRZI, UT_PE, UT_GCR, UT_NRZI };
48 
49 /* slave to controller mapping table */
50 short	tjtout[NTJ];
51 #define UTUNIT(dev)	(tjtout[TJUNIT(dev)])
52 
53 #define	INF	(daddr_t)1000000L	/* a block number that wont exist */
54 
55 struct	tj_softc {
56 	char	sc_openf;	/* exclusive open */
57 	char	sc_lastiow;	/* last I/O operation was a write */
58 	daddr_t	sc_blkno;	/* next block to transfer */
59 	daddr_t	sc_nxrec;	/* next record on tape */
60 	u_short	sc_erreg;	/* image of uter */
61 	u_short	sc_dsreg;	/* image of utds */
62 	u_short	sc_resid;	/* residual from transfer */
63 	u_short	sc_dens;	/* sticky selected density */
64 	daddr_t	sc_timo;	/* time until timeout expires */
65 	short	sc_tact;	/* timeout is active flag */
66 } tj_softc[NTJ];
67 
68 /*
69  * Internal per/slave states found in sc_state
70  */
71 #define	SSEEK		1	/* seeking */
72 #define	SIO		2	/* doing sequential I/O */
73 #define	SCOM		3	/* sending a control command */
74 #define	SREW		4	/* doing a rewind op */
75 #define	SERASE		5	/* erase inter-record gap */
76 #define	SERASED		6	/* erased inter-record gap */
77 
78 utprobe(reg)
79 	caddr_t reg;
80 {
81 	register int br, cvec;
82 #ifdef lint
83 	br=0; cvec=br; br=cvec;
84 #endif
85 	/*
86 	 * It appears the controller won't interrupt unless the
87 	 * slave is off-line...this is as bad as the TS-11.
88 	 */
89 #ifdef notdef
90 	((struct utdevice *) reg)->utcs1 = UT_IE|UT_NOP|UT_GO;
91 	DELAY(10000);
92 	((struct utdevice *) reg)->utcs1 = UT_CLEAR|UT_GO;
93 #else
94 	br = 0x15;
95 	cvec = 0164;
96 	return(1);
97 #endif
98 }
99 
100 /*ARGSUSED*/
101 utslave(ui, reg)
102 	struct uba_device *ui;
103 	caddr_t reg;
104 {
105 	/*
106 	 * A real TU45 would support the slave present bit
107 	 * int the drive type register, but this thing doesn't,
108 	 * so there's no way to determine if a slave is present or not.
109 	 */
110 	 return(1);
111 }
112 
113 utattach(ui)
114 	struct uba_device *ui;
115 {
116 	tjtout[ui->ui_unit] = ui->ui_mi->um_ctlr;
117 }
118 
119 /*
120  * Open the device with exclusive access.
121  */
122 utopen(dev, flag)
123 	dev_t dev;
124 	int flag;
125 {
126 	register int tjunit = TJUNIT(dev);
127 	register struct uba_device *ui;
128 	register struct tj_softc *sc;
129 	int olddens, dens;
130 
131 	if (tjunit >= NTJ || (sc = &tj_softc[tjunit])->sc_openf ||
132 	    (ui = tjdinfo[tjunit]) == 0 || ui->ui_alive == 0) {
133 		u.u_error = ENXIO;
134 		return;
135 	}
136 	olddens = sc->sc_dens;
137 	dens = sc->sc_dens = utdens[(minor(dev)&(T_1600BPI|T_6250BPI))>>3]|
138 				PDP11FMT|(ui->ui_slave&07);
139 get:
140 	utcommand(dev, UT_SENSE, 1);
141 	if (sc->sc_dsreg&UTDS_PIP) {
142 		sleep((caddr_t) &lbolt, PZERO+1);
143 		goto get;
144 	}
145 	sc->sc_dens = olddens;
146 	if ((sc->sc_dsreg&UTDS_MOL) == 0) {
147 		uprintf("tj%d: not online\n", tjunit);
148 		u.u_error = EIO;
149 		return;
150 	}
151 	if ((flag&FWRITE) && (sc->sc_dsreg&UTDS_WRL)) {
152 		uprintf("tj%d: no write ring\n", tjunit);
153 		u.u_error = EIO;
154 		return;
155 	}
156 	if ((sc->sc_dsreg&UTDS_BOT) == 0 && (flag&FWRITE) &&
157 	    dens != sc->sc_dens) {
158 		uprintf("tj%d: can't change density in mid-tape\n", tjunit);
159 		u.u_error = EIO;
160 		return;
161 	}
162 	sc->sc_openf = 1;
163 	sc->sc_blkno = (daddr_t)0;
164 	sc->sc_nxrec = INF;
165 	sc->sc_lastiow = 0;
166 	sc->sc_dens = dens;
167 	/*
168 	 * For 6250 bpi take exclusive use of the UNIBUS.
169 	 */
170 	ui->ui_driver->ud_xclu = (dens&(T_1600BPI|T_6250BPI)) == T_6250BPI;
171 	(void) spl6();
172 	if (sc->sc_tact == 0) {
173 		sc->sc_timo = INF;
174 		sc->sc_tact = 1;
175 		timeout(uttimer, (caddr_t)dev, 5*hz);
176 	}
177 	(void) spl0();
178 }
179 
180 utclose(dev, flag)
181 	register dev_t dev;
182 	register flag;
183 {
184 	register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
185 
186 	if (flag == FWRITE || ((flag&FWRITE) && sc->sc_lastiow)) {
187 		utcommand(dev, UT_WEOF, 1);
188 		utcommand(dev, UT_WEOF, 1);
189 		utcommand(dev, UT_SREV, 1);
190 	}
191 	if ((minor(dev)&T_NOREWIND) == 0)
192 		utcommand(dev, UT_REW, 0);
193 	sc->sc_openf = 0;
194 }
195 
196 utcommand(dev, com, count)
197 	dev_t dev;
198 	int com, count;
199 {
200 	register struct buf *bp;
201 
202 	bp = &cutbuf[UTUNIT(dev)];
203 	(void) spl5();
204 	while (bp->b_flags&B_BUSY) {
205 		if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE))
206 			break;
207 		bp->b_flags |= B_WANTED;
208 		sleep((caddr_t)bp, PRIBIO);
209 	}
210 	bp->b_flags = B_BUSY|B_READ;
211 	(void) spl0();
212 	bp->b_dev = dev;
213 	bp->b_command = com;
214 	bp->b_repcnt = count;
215 	bp->b_blkno = 0;
216 	utstrategy(bp);
217 	if (count == 0)
218 		return;
219 	iowait(bp);
220 	if (bp->b_flags&B_WANTED)
221 		wakeup((caddr_t)bp);
222 	bp->b_flags &= B_ERROR;
223 }
224 
225 /*
226  * Queue a tape operation.
227  */
228 utstrategy(bp)
229 	register struct buf *bp;
230 {
231 	int tjunit = TJUNIT(bp->b_dev);
232 	register struct uba_ctlr *um;
233 	register struct buf *dp;
234 
235 	/*
236 	 * Put transfer at end of unit queue
237 	 */
238 	dp = &tjutab[tjunit];
239 	bp->av_forw = NULL;
240 	(void) spl5();
241 	if (dp->b_actf == NULL) {
242 		dp->b_actf = bp;
243 		/*
244 		 * Transport not active, so...
245 		 * put at end of controller queue
246 		 */
247 		dp->b_forw = NULL;
248 		um = tjdinfo[tjunit]->ui_mi;
249 		if (um->um_tab.b_actf == NULL)
250 			um->um_tab.b_actf = dp;
251 		else
252 			um->um_tab.b_actl->b_forw = dp;
253 		um->um_tab.b_actl = dp;
254 	} else
255 		dp->b_actl->av_forw = bp;
256 	dp->b_actl = bp;
257 	/*
258 	 * If the controller is not busy, set it going.
259 	 */
260 	if (um->um_tab.b_state == 0)
261 		utstart(um);
262 	(void) spl0();
263 }
264 
265 utstart(um)
266 	register struct uba_ctlr *um;
267 {
268 	register struct utdevice *addr;
269 	register struct buf *bp, *dp;
270 	register struct tj_softc *sc;
271 	struct uba_device *ui;
272 	int tjunit;
273 	daddr_t blkno;
274 
275 loop:
276 	/*
277 	 * Scan controller queue looking for units with
278 	 * transaction queues to dispatch
279 	 */
280 	if ((dp = um->um_tab.b_actf) == NULL)
281 		return;
282 	if ((bp = dp->b_actf) == NULL) {
283 		um->um_tab.b_actf = dp->b_forw;
284 		goto loop;
285 	}
286 	addr = (struct utdevice *)um->um_addr;
287 	tjunit = TJUNIT(bp->b_dev);
288 	ui = tjdinfo[tjunit];
289 	sc = &tj_softc[tjunit];
290 	/* note slave select, density, and format were merged on open */
291 	addr->uttc = sc->sc_dens;
292 	sc->sc_dsreg = addr->utds;
293 	sc->sc_erreg = addr->uter;
294 	/* watch this, sports fans */
295 	sc->sc_resid = bp->b_flags&B_READ ?
296 		bp->b_bcount - ((-addr->utfc)&0xffff) : -addr->utwc<<1;
297 	/*
298 	 * Default is that last command was NOT a write command;
299 	 * if we do a write command we will notice this in utintr().
300 	 */
301 	sc->sc_lastiow = 0;
302 	if (sc->sc_openf < 0 || (addr->utds&UTDS_MOL) == 0) {
303 		/*
304 		 * Have had a hard error on a non-raw tape
305 		 * or the tape unit is now unavailable
306 		 * (e.g. taken off line).
307 		 */
308 		bp->b_flags |= B_ERROR;
309 		goto next;
310 	}
311 	if (bp == &cutbuf[UTUNIT(bp->b_dev)]) {
312 		/*
313 		 * Execute a control operation with the specified
314 		 * count.
315 		 */
316 		if (bp->b_command == UT_SENSE)
317 			goto next;
318 		/*
319 		 * Set next state; handle timeouts
320 		 */
321 		if (bp->b_command == UT_REW) {
322 			um->um_tab.b_state = SREW;
323 			sc->sc_timo = 5*60;
324 		} else {
325 			um->um_tab.b_state = SCOM;
326 			sc->sc_timo = imin(imax(10*(int)-bp->b_repcnt,60),5*60);
327 		}
328 		/* NOTE: this depends on the ut command values */
329 		if (bp->b_command >= UT_SFORW && bp->b_command <= UT_SREVF)
330 			addr->utfc = -bp->b_repcnt;
331 		goto dobpcmd;
332 	}
333 	/*
334 	 * The following checks boundary conditions for operations
335 	 * on non-raw tapes.  On raw tapes the initialization of
336 	 * sc->sc_nxrec by utphys causes them to be skipped normally
337 	 * (except in the case of retries).
338 	 */
339 	if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) {
340 		/* can't read past end of file */
341 		bp->b_flags |= B_ERROR;
342 		bp->b_error = ENXIO;
343 		goto next;
344 	}
345 	if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && (bp->b_flags&B_READ)) {
346 		/* read at eof returns 0 count */
347 		bp->b_resid = bp->b_bcount;
348 		clrbuf(bp);
349 		goto next;
350 	}
351 	if ((bp->b_flags&B_READ) == 0)
352 		sc->sc_nxrec = dbtofsb(bp->b_blkno)+1;
353 	/*
354 	 * If the tape is correctly positioned, set up all the
355 	 * registers but the csr, and give control over to the
356 	 * UNIBUS adaptor routines, to wait for resources to
357 	 * start I/O.
358 	 */
359 	if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) {
360 		addr->utwc = -(((bp->b_bcount)+1)>>1);
361 		addr->utfc = -bp->b_bcount;
362 		if ((bp->b_flags&B_READ) == 0) {
363 			/*
364 			 * On write error retries erase the
365 			 * inter-record gap before rewriting.
366 			 */
367 			if (um->um_tab.b_errcnt) {
368 				if (um->um_tab.b_state != SERASED) {
369 					um->um_tab.b_state = SERASE;
370 					sc->sc_timo = 60;
371 					addr->utcs1 = UT_ERASE|UT_IE|UT_GO;
372 					return;
373 				}
374 			}
375 			um->um_cmd = UT_WCOM;
376 		} else
377 			um->um_cmd = UT_RCOM;
378 		sc->sc_timo = 60;
379 		um->um_tab.b_state = SIO;
380 		(void) ubago(ui);
381 		return;
382 	}
383 	/*
384 	 * Tape positioned incorrectly; seek forwards or
385 	 * backwards to the correct spot.  This happens for
386 	 * raw tapes only on error retries.
387 	 */
388 	um->um_tab.b_state = SSEEK;
389 	if (blkno < dbtofsb(bp->b_blkno)) {
390 		addr->utfc = blkno - dbtofsb(bp->b_blkno);
391 		bp->b_command = UT_SFORW;
392 	} else {
393 		addr->utfc = dbtofsb(bp->b_blkno) - blkno;
394 		bp->b_command = UT_SREV;
395 	}
396 	sc->sc_timo = imin(imax(10 * -addr->utfc, 60), 5*60);
397 
398 dobpcmd:
399 	/*
400 	 * Perform the command setup in bp.
401 	 */
402 	addr->utcs1 = bp->b_command|UT_IE|UT_GO;
403 	return;
404 next:
405 	/*
406 	 * Advance to the next command in the slave queue,
407 	 * posting notice and releasing resources as needed.
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  * Start operation on controller --
419  * UNIBUS resources have been allocated.
420  */
421 utdgo(um)
422 	register struct uba_ctlr *um;
423 {
424 	register struct utdevice *addr = (struct utdevice *)um->um_addr;
425 
426 	addr->utba = (u_short) um->um_ubinfo;
427 	addr->utcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x30)|UT_IE|UT_GO;
428 }
429 
430 /*
431  * Ut interrupt handler
432  */
433 /*ARGSUSED*/
434 utintr(ut11)
435 	int ut11;
436 {
437 	struct buf *dp;
438 	register struct buf *bp;
439 	register struct uba_ctlr *um = utminfo[ut11];
440 	register struct utdevice *addr;
441 	register struct tj_softc *sc;
442 	u_short tjunit, cs2, cs1;
443 	register state;
444 
445 	if ((dp = um->um_tab.b_actf) == NULL)
446 		return;
447 	bp = dp->b_actf;
448 	tjunit = TJUNIT(bp->b_dev);
449 	addr = (struct utdevice *)tjdinfo[tjunit]->ui_addr;
450 	sc = &tj_softc[tjunit];
451 	/*
452 	 * Record status...
453 	 */
454 	sc->sc_timo = INF;
455 	sc->sc_dsreg = addr->utds;
456 	sc->sc_erreg = addr->uter;
457 	sc->sc_resid = bp->b_flags&B_READ ?
458 		bp->b_bcount - (-addr->utfc)&0xffff : -addr->utwc<<1;
459 	if ((bp->b_flags&B_READ) == 0)
460 		sc->sc_lastiow = 1;
461 	state = um->um_tab.b_state;
462 	um->um_tab.b_state = 0;
463 	/*
464 	 * Check for errors...
465 	 */
466 	if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE)) {
467 		/*
468 		 * To clear the ERR bit, we must issue a drive clear
469 		 * command, and to clear the TRE bit we must set the
470 		 * controller clear bit.
471 		 */
472 		cs2 = addr->utcs2;
473 		if ((cs1 = addr->utcs1)&UT_TRE)
474 			addr->utcs2 |= UTCS2_CLR;
475 		/* is this dangerous ?? */
476 		while ((addr->utcs1&UT_RDY) == 0)
477 			;
478 		addr->utcs1 = UT_CLEAR|UT_GO;
479 		/*
480 		 * If we hit a tape mark or EOT update our position.
481 		 */
482 		if (sc->sc_dsreg&(UTDS_TM|UTDS_EOT)) {
483 			/*
484 			 * Set blkno and nxrec
485 			 */
486 			if (bp == &cutbuf[UTUNIT(bp->b_dev)]) {
487 				if (sc->sc_blkno > dbtofsb(bp->b_blkno)) {
488 					sc->sc_nxrec =
489 					      dbtofsb(bp->b_blkno) - addr->utfc;
490 					sc->sc_blkno = sc->sc_nxrec;
491 				} else {
492 					sc->sc_blkno =
493 					      dbtofsb(bp->b_blkno) + addr->utfc;
494 					sc->sc_nxrec = sc->sc_blkno-1;
495 				}
496 			} else
497 				sc->sc_nxrec = dbtofsb(bp->b_blkno);
498 			state = SCOM;		/* force completion */
499 			/*
500 			 * Stuff so we can unstuff later
501 			 * to get the residual.
502 			 */
503 			addr->utwc = (-bp->b_bcount)>>1;
504 			addr->utfc = -bp->b_bcount;
505 			if (sc->sc_dsreg&UTDS_EOT)
506 				goto harderror;
507 			goto opdone;
508 		}
509 		/*
510 		 * If we were reading from a raw tape and the only error
511 		 * was that the record was too long, then we don't consider
512 		 * this an error.
513 		 */
514 		if (bp == &rutbuf[UTUNIT(bp->b_dev)] && (bp->b_flags&B_READ) &&
515 		    (sc->sc_erreg&UTER_FCE))
516 			goto ignoreerr;
517 		/*
518 		 * Fix up errors which occur due to backspacing "over" the
519 		 * front of the tape.
520 		 */
521 		if ((sc->sc_dsreg&UTDS_BOT) &&
522 		    (bp->b_command == UT_SREV || bp->b_command == UT_SREV) &&
523 		    ((sc->sc_erreg &= ~(UTER_NEF|UTER_FCE)) == 0))
524 			goto opdone;
525 		/*
526 		 * Retry soft errors up to 8 times
527 		 */
528 		if ((sc->sc_erreg&UTER_HARD) == 0 && state == SIO) {
529 			if (++um->um_tab.b_errcnt < 7) {
530 				sc->sc_blkno++;
531 				ubadone(um);
532 				goto opcont;
533 			}
534 		} else
535 harderror:
536 			/*
537 			 * Hard or non-I/O errors on non-raw tape
538 			 * cause it to close; also, reading off the
539 			 * end of the tape.
540 			 */
541 			if (sc->sc_openf > 0 &&
542 			    bp != &rutbuf[UTUNIT(bp->b_dev)] ||
543 			    sc->sc_dsreg&UTDS_EOT)
544 				sc->sc_openf = -1;
545 		/*
546 		 * Couldn't recover error.
547 		 */
548 		printf("ut%d: hard error bn%d cs1=%b er=%b cs2=%b ds=%b\n",
549 			tjunit, bp->b_blkno, cs1, UT_BITS, sc->sc_erreg,
550 			UTER_BITS, cs2, UTCS2_BITS, sc->sc_dsreg, UTDS_BITS);
551 		bp->b_flags |= B_ERROR;
552 		goto opdone;
553 	}
554 ignoreerr:
555 	/*
556 	 * Advance tape control FSM.
557 	 */
558 	switch (state) {
559 
560 	case SIO:		/* read/write increments tape block # */
561 		sc->sc_blkno++;
562 		break;
563 
564 	case SCOM:		/* forw/rev space updates current position */
565 		if (bp == &cutbuf[UTUNIT(bp->b_dev)])
566 		switch (bp->b_command) {
567 
568 		case UT_SFORW:
569 			sc->sc_blkno -= bp->b_repcnt;
570 			break;
571 
572 		case UT_SREV:
573 			sc->sc_blkno += bp->b_repcnt;
574 			break;
575 		}
576 		break;
577 
578 	case SSEEK:
579 		sc->sc_blkno = dbtofsb(bp->b_blkno);
580 		goto opcont;
581 
582 	case SERASE:
583 		/*
584 		 * Completed erase of the inter-record gap due to a
585 		 * write error; now retry the write operation.
586 		 */
587 		um->um_tab.b_state = SERASED;
588 		goto opcont;
589 
590 	case SREW:			/* clear attention bit */
591 		addr->utcs1 = UT_CLEAR|UT_GO;
592 		break;
593 
594 	default:
595 		printf("bad state %d\n", state);
596 		panic("utintr");
597 	}
598 
599 opdone:
600 	/*
601 	 * Reset error count and remove
602 	 * from device queue
603 	 */
604 	um->um_tab.b_errcnt = 0;
605 	dp->b_actf = bp->av_forw;
606 	bp->b_resid = bp->b_command&B_READ ?
607 		bp->b_bcount - ((-addr->utfc)&0xffff) : -addr->utwc<<1;
608 	ubadone(um);
609 	iodone(bp);
610 	/*
611 	 * Circulate slave to end of controller queue
612 	 * to give other slaves a chance
613 	 */
614 	um->um_tab.b_actf = dp->b_forw;
615 	if (dp->b_actf) {
616 		dp->b_forw = NULL;
617 		if (um->um_tab.b_actf == NULL)
618 			um->um_tab.b_actf = dp;
619 		else
620 			um->um_tab.b_actl->b_forw = dp;
621 		um->um_tab.b_actl = dp;
622 	}
623 	if (um->um_tab.b_actf == 0)
624 		return;
625 opcont:
626 	utstart(um);
627 }
628 
629 /*
630  * Watchdog timer routine.
631  */
632 uttimer(dev)
633 	int dev;
634 {
635 	register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
636 	register short x;
637 
638 	if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) {
639 		printf("tj%d: lost interrupt\n", TJUNIT(dev));
640 		sc->sc_timo = INF;
641 		x = spl5();
642 		utintr(UTUNIT(dev));
643 		(void) splx(x);
644 	}
645 	timeout(uttimer, (caddr_t)dev, 5*hz);
646 }
647 
648 /*
649  * Raw interface for a read
650  */
651 utread(dev)
652 	dev_t dev;
653 {
654 	utphys(dev);
655 	if (u.u_error)
656 		return;
657 	physio(utstrategy, &rutbuf[UTUNIT(dev)], dev, B_READ, minphys);
658 }
659 
660 /*
661  * Raw interface for a write
662  */
663 utwrite(dev)
664 {
665 	utphys(dev);
666 	if (u.u_error)
667 		return;
668 	physio(utstrategy, &rutbuf[UTUNIT(dev)], dev, B_WRITE, minphys);
669 }
670 
671 /*
672  * Check for valid device number dev and update our notion
673  * of where we are on the tape
674  */
675 utphys(dev)
676 	dev_t dev;
677 {
678 	register int tjunit = TJUNIT(dev);
679 	register struct tj_softc *sc;
680 	register struct uba_device *ui;
681 
682 	if (tjunit >= NTJ || (ui=tjdinfo[tjunit]) == 0 || ui->ui_alive == 0) {
683 		u.u_error = ENXIO;
684 		return;
685 	}
686 	sc = &tj_softc[tjunit];
687 	sc->sc_blkno = dbtofsb(u.u_offset>>9);
688 	sc->sc_nxrec = sc->sc_blkno+1;
689 }
690 
691 /*ARGSUSED*/
692 utioctl(dev, cmd, addr, flag)
693 	dev_t dev;
694 	caddr_t addr;
695 {
696 	register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
697 	register struct buf *bp = &cutbuf[UTUNIT(dev)];
698 	register callcount;
699 	int fcount;
700 	struct mtop mtop;
701 	struct mtget mtget;
702 	/* we depend of the values and order of the MT codes here */
703 	static utops[] =
704       {UT_WEOF,UT_SFORWF,UT_SREVF,UT_SFORW,UT_SREV,UT_REW,UT_REWOFFL,UT_SENSE};
705 
706 	switch (cmd) {
707 
708 	case MTIOCTOP:
709 		if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
710 			u.u_error = EFAULT;
711 			return;
712 		}
713 		switch(mtop.mt_op) {
714 
715 		case MTWEOF:
716 			callcount = mtop.mt_count;
717 			fcount = 1;
718 			break;
719 
720 		case MTFSF: case MTBSF:
721 		case MTFSR: case MTBSR:
722 			callcount = 1;
723 			fcount = mtop.mt_count;
724 			break;
725 
726 		case MTREW: case MTOFFL: case MTNOP:
727 			callcount = 1;
728 			fcount = 1;
729 			break;
730 
731 		default:
732 			u.u_error = ENXIO;
733 			return;
734 		}
735 		if (callcount <= 0 || fcount <= 0) {
736 			u.u_error = ENXIO;
737 			return;
738 		}
739 		while (--callcount >= 0) {
740 			utcommand(dev, utops[mtop.mt_op], fcount);
741 			/* note this depends on the mtop values */
742 			if ((mtop.mt_op >= MTFSF || mtop.mt_op <= MTBSR) &&
743 			    bp->b_resid) {
744 				u.u_error = EIO;
745 				break;
746 			}
747 			if ((bp->b_flags&B_ERROR) || (sc->sc_dsreg&UTDS_BOT))
748 				break;
749 		}
750 		geterror(bp);
751 		return;
752 
753 	case MTIOCGET:
754 		mtget.mt_dsreg = sc->sc_dsreg;
755 		mtget.mt_erreg = sc->sc_erreg;
756 		mtget.mt_resid = sc->sc_resid;
757 		mtget.mt_type = MT_ISUT;
758 		if (copyout((caddr_t)&mtget, addr, sizeof(mtget)))
759 			u.u_error = EFAULT;
760 		return;
761 
762 	default:
763 		u.u_error = ENXIO;
764 	}
765 }
766 
767 utreset(uban)
768 	int uban;
769 {
770 	register struct uba_ctlr *um;
771 	register ut11, tjunit;
772 	register struct uba_device *ui;
773 	register struct buf *dp;
774 
775 	for (ut11 = 0; ut11 < NUT; ut11++) {
776 		if ((um = utminfo[ut11]) == 0 || um->um_alive == 0 ||
777 		   um->um_ubanum != uban)
778 			continue;
779 		printf(" ut%d", ut11);
780 		um->um_tab.b_state = 0;
781 		um->um_tab.b_actf = um->um_tab.b_actl = 0;
782 		if (um->um_ubinfo) {
783 			printf("<%d>", (um->um_ubinfo>>28)&0xf);
784 			ubadone(um);
785 		}
786 		((struct utdevice *)(um->um_addr))->utcs1 = UT_CLEAR|UT_GO;
787 		((struct utdevice *)(um->um_addr))->utcs2 |= UTCS2_CLR;
788 		for (tjunit = 0; tjunit < NTJ; tjunit++) {
789 			if ((ui = tjdinfo[tjunit]) == 0 || ui->ui_mi != um ||
790 			    ui->ui_alive == 0)
791 				continue;
792 			dp = &tjutab[tjunit];
793 			dp->b_state = 0;
794 			dp->b_forw = 0;
795 			if (um->um_tab.b_actf == NULL)
796 				um->um_tab.b_actf = dp;
797 			else
798 				um->um_tab.b_actl->b_forw = dp;
799 			um->um_tab.b_actl = dp;
800 			if (tj_softc[tjunit].sc_openf > 0)
801 				tj_softc[tjunit].sc_openf = -1;
802 		}
803 		utstart(um);
804 	}
805 }
806 
807 /*
808  * Do a stand-alone core dump to tape --
809  * from here down, routines are used only in dump context
810  */
811 #define	DBSIZE	20
812 
813 utdump()
814 {
815 	register struct uba_device *ui;
816 	register struct uba_regs *up;
817 	register struct utdevice *addr;
818 	int blk, num = maxfree;
819 	int start = 0;
820 
821 #define	phys(a,b)		((b)((int)(a)&0x7fffffff))
822 	if (tjdinfo[0] == 0)
823 		return (ENXIO);
824 	ui = phys(tjdinfo[0], struct uba_device *);
825 	up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba;
826 	ubainit();
827 	DELAY(1000000);
828 	utwait(addr);
829 	addr = (struct utdevice *)ui->ui_physaddr;
830 	/*
831 	 * Be sure to set the appropriate density here.  We use
832 	 * 6250, but maybe it should be done at 1600 to insure the
833 	 * tape can be read by most any other tape drive available.
834 	 */
835 	addr->uttc = UT_GCR|PDP11FMT;	/* implicit slave 0 or-ed in */
836 	addr->utcs1 = UT_CLEAR|UT_GO;
837 	while (num > 0) {
838 		blk = num > DBSIZE ? DBSIZE : num;
839 		utdwrite(start, blk, addr, up);
840 		if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE))
841 			return(EIO);
842 		start += blk;
843 		num -= blk;
844 	}
845 	uteof(addr);
846 	uteof(addr);
847 	utwait(addr);
848 	if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE))
849 		return(EIO);
850 	addr->utcs1 = UT_REW|UT_GO;
851 	return (0);
852 }
853 
854 utdwrite(dbuf, num, addr, up)
855 	register dbuf, num;
856 	register struct utdevice *addr;
857 	struct uba_regs *up;
858 {
859 	register struct pte *io;
860 	register int npf;
861 
862 	utwait(addr);
863 	io = up->uba_map;
864 	npf = num + 1;
865 	while (--npf != 0)
866 		*(int *)io++ = (dbuf++ | (1<<UBAMR_DPSHIFT) | UBAMR_MRV);
867 	*(int *)io = 0;
868 	addr->utwc = -((num*NBPG)>>1);
869 	addr->utfc = -(num*NBPG);
870 	addr->utba = 0;
871 	addr->utcs1 = UT_WCOM|UT_GO;
872 }
873 
874 utwait(addr)
875 	struct utdevice *addr;
876 {
877 	register s;
878 
879 	do
880 		s = addr->utds;
881 	while ((s&UTDS_DRY) == 0);
882 }
883 
884 uteof(addr)
885 	struct utdevice *addr;
886 {
887 
888 	utwait(addr);
889 	addr->utcs1 = UT_WEOF|UT_GO;
890 }
891 #endif
892