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