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