tprintf
[unix-history] / usr / src / sys / vax / uba / ut.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
5c0ca3ef 6 * @(#)ut.c 7.10 (Berkeley) %G%
da7c5cc6 7 */
b02cd1e9 8
7c6c07eb 9#include "tj.h"
b02cd1e9 10#if NUT > 0
b02cd1e9
BJ
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 */
ff360633
JB
19#include "param.h"
20#include "systm.h"
21#include "buf.h"
22#include "conf.h"
ff360633 23#include "file.h"
ff360633
JB
24#include "map.h"
25#include "ioctl.h"
26#include "mtio.h"
27#include "cmap.h"
28#include "uio.h"
29#include "kernel.h"
c457503f 30#include "syslog.h"
5c0ca3ef 31#include "tprintf.h"
b02cd1e9 32
c18e27ed 33#include "machine/pte.h"
896962b1 34#include "../vax/cpu.h"
ff360633
JB
35#include "ubareg.h"
36#include "ubavar.h"
37#include "utreg.h"
b02cd1e9 38
b02cd1e9
BJ
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];
407582e3 44int utprobe(), utslave(), utattach(), utdgo(), utintr(), uttimer();
b02cd1e9
BJ
45u_short utstd[] = { 0772440, 0 };
46struct uba_driver utdriver =
47 { utprobe, utslave, utattach, utdgo, utstd, "tj", tjdinfo, "ut", utminfo, 0 };
48
6b0f2767
SL
49#define MASKREG(reg) ((reg)&0xffff)
50
b02cd1e9
BJ
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 */
c36079e2 71 u_short sc_resid; /* residual from transfer */
b02cd1e9 72 u_short sc_dens; /* sticky selected density */
407582e3
BJ
73 daddr_t sc_timo; /* time until timeout expires */
74 short sc_tact; /* timeout is active flag */
5c0ca3ef 75 tpr_t sc_tpr; /* tprintf handle */
c457503f
MK
76 int sc_blks; /* number of I/O operations since open */
77 int sc_softerrs; /* number of soft I/O errors since open */
b02cd1e9
BJ
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 */
c36079e2
SL
87#define SERASE 5 /* erase inter-record gap */
88#define SERASED 6 /* erased inter-record gap */
b02cd1e9 89
89b8a44c 90/*ARGSUSED*/
b02cd1e9
BJ
91utprobe(reg)
92 caddr_t reg;
93{
94 register int br, cvec;
95#ifdef lint
96 br=0; cvec=br; br=cvec;
89b8a44c 97 utintr(0);
b02cd1e9 98#endif
c36079e2 99 /*
e090266d
BJ
100 * The SI documentation says you must set the RDY bit
101 * (even though it's read-only) to force an interrupt.
c36079e2 102 */
e090266d 103 ((struct utdevice *) reg)->utcs1 = UT_IE|UT_NOP|UT_RDY;
b02cd1e9 104 DELAY(10000);
9c0adba0 105 return (sizeof (struct utdevice));
b02cd1e9
BJ
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;
c376c8e7 137 int olddens, dens, error;
2311123d 138 register int s;
b02cd1e9 139
1e6047bb 140 if (tjunit >= NTJ || (ui = tjdinfo[tjunit]) == 0 || ui->ui_alive == 0)
7da157da 141 return (ENXIO);
1e6047bb
MK
142 if ((sc = &tj_softc[tjunit])->sc_openf)
143 return (EBUSY);
c457503f 144 sc->sc_openf = 1;
b02cd1e9 145 olddens = sc->sc_dens;
7da157da
BJ
146 dens = sc->sc_dens =
147 utdens[(minor(dev)&(T_1600BPI|T_6250BPI))>>3]|
148 PDP11FMT|(ui->ui_slave&07);
b02cd1e9
BJ
149get:
150 utcommand(dev, UT_SENSE, 1);
151 if (sc->sc_dsreg&UTDS_PIP) {
c376c8e7
MK
152 if (error = tsleep((caddr_t)&lbolt, (PZERO+1) | PCATCH,
153 devopn, 0))
154 return (error);
b02cd1e9
BJ
155 goto get;
156 }
157 sc->sc_dens = olddens;
158 if ((sc->sc_dsreg&UTDS_MOL) == 0) {
c457503f 159 sc->sc_openf = 0;
b02cd1e9 160 uprintf("tj%d: not online\n", tjunit);
7da157da 161 return (EIO);
b02cd1e9
BJ
162 }
163 if ((flag&FWRITE) && (sc->sc_dsreg&UTDS_WRL)) {
c457503f 164 sc->sc_openf = 0;
b02cd1e9 165 uprintf("tj%d: no write ring\n", tjunit);
7da157da 166 return (EIO);
b02cd1e9
BJ
167 }
168 if ((sc->sc_dsreg&UTDS_BOT) == 0 && (flag&FWRITE) &&
169 dens != sc->sc_dens) {
c457503f 170 sc->sc_openf = 0;
b02cd1e9 171 uprintf("tj%d: can't change density in mid-tape\n", tjunit);
7da157da 172 return (EIO);
b02cd1e9 173 }
b02cd1e9
BJ
174 sc->sc_blkno = (daddr_t)0;
175 sc->sc_nxrec = INF;
176 sc->sc_lastiow = 0;
c457503f
MK
177 sc->sc_blks = 0;
178 sc->sc_softerrs = 0;
b02cd1e9 179 sc->sc_dens = dens;
5c0ca3ef 180 sc->sc_tpr = tprintf_open();
c36079e2
SL
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;
8011f5df 185 s = splclock();
407582e3
BJ
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 }
2311123d 191 splx(s);
7da157da 192 return (0);
b02cd1e9
BJ
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);
c457503f
MK
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);
5c0ca3ef 211 tprintf_close(sc->sc_tpr);
b02cd1e9 212 sc->sc_openf = 0;
c376c8e7 213 return (0);
b02cd1e9
BJ
214}
215
216utcommand(dev, com, count)
217 dev_t dev;
218 int com, count;
219{
220 register struct buf *bp;
2311123d 221 register int s;
b02cd1e9
BJ
222
223 bp = &cutbuf[UTUNIT(dev)];
2311123d 224 s = spl5();
b02cd1e9
BJ
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;
2311123d 232 splx(s);
b02cd1e9
BJ
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;
5d4eae4d 255 int s;
b02cd1e9
BJ
256
257 /*
258 * Put transfer at end of unit queue
259 */
260 dp = &tjutab[tjunit];
261 bp->av_forw = NULL;
6c94015c 262 um = tjdinfo[tjunit]->ui_mi;
5d4eae4d 263 s = spl5();
b02cd1e9
BJ
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;
b02cd1e9
BJ
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 */
c36079e2 282 if (um->um_tab.b_state == 0)
b02cd1e9 283 utstart(um);
5d4eae4d 284 splx(s);
b02cd1e9
BJ
285}
286
287utstart(um)
288 register struct uba_ctlr *um;
289{
c36079e2 290 register struct utdevice *addr;
b02cd1e9
BJ
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 }
c36079e2 308 addr = (struct utdevice *)um->um_addr;
b02cd1e9
BJ
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 */
c36079e2
SL
313 addr->uttc = sc->sc_dens;
314 sc->sc_dsreg = addr->utds;
315 sc->sc_erreg = addr->uter;
6b0f2767 316 sc->sc_resid = MASKREG(addr->utfc);
b02cd1e9
BJ
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;
c36079e2 322 if (sc->sc_openf < 0 || (addr->utds&UTDS_MOL) == 0) {
b02cd1e9
BJ
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;
6b0f2767
SL
338 if (bp->b_command == UT_SFORW && (addr->utds & UTDS_EOT)) {
339 bp->b_resid = bp->b_bcount;
340 goto next;
341 }
b02cd1e9
BJ
342 /*
343 * Set next state; handle timeouts
344 */
407582e3 345 if (bp->b_command == UT_REW) {
c36079e2 346 um->um_tab.b_state = SREW;
407582e3
BJ
347 sc->sc_timo = 5*60;
348 } else {
c36079e2 349 um->um_tab.b_state = SCOM;
407582e3
BJ
350 sc->sc_timo = imin(imax(10*(int)-bp->b_repcnt,60),5*60);
351 }
b02cd1e9
BJ
352 /* NOTE: this depends on the ut command values */
353 if (bp->b_command >= UT_SFORW && bp->b_command <= UT_SREVF)
c36079e2 354 addr->utfc = -bp->b_repcnt;
b02cd1e9
BJ
355 goto dobpcmd;
356 }
357 /*
5d4eae4d
KB
358 * For raw I/O, save the current block
359 * number in case we have to retry.
b02cd1e9 360 */
5d4eae4d
KB
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 }
b02cd1e9 366 }
5d4eae4d
KB
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;
b02cd1e9 389 }
b02cd1e9
BJ
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 */
fb739082 396 if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) {
c36079e2
SL
397 addr->utwc = -(((bp->b_bcount)+1)>>1);
398 addr->utfc = -bp->b_bcount;
b02cd1e9
BJ
399 if ((bp->b_flags&B_READ) == 0) {
400 /*
401 * On write error retries erase the
c36079e2 402 * inter-record gap before rewriting.
b02cd1e9 403 */
c36079e2 404 if (um->um_tab.b_errcnt) {
c36079e2 405 if (um->um_tab.b_state != SERASED) {
64614526 406 um->um_tab.b_state = SERASE;
407582e3 407 sc->sc_timo = 60;
c36079e2
SL
408 addr->utcs1 = UT_ERASE|UT_IE|UT_GO;
409 return;
410 }
c36079e2 411 }
6b0f2767
SL
412 if (addr->utds & UTDS_EOT) {
413 bp->b_resid = bp->b_bcount;
414 um->um_tab.b_state = 0;
415 goto next;
416 }
c36079e2 417 um->um_cmd = UT_WCOM;
b02cd1e9
BJ
418 } else
419 um->um_cmd = UT_RCOM;
407582e3 420 sc->sc_timo = 60;
c36079e2 421 um->um_tab.b_state = SIO;
b02cd1e9
BJ
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 */
c36079e2 430 um->um_tab.b_state = SSEEK;
fb739082
SL
431 if (blkno < bdbtofsb(bp->b_blkno)) {
432 addr->utfc = blkno - bdbtofsb(bp->b_blkno);
b02cd1e9
BJ
433 bp->b_command = UT_SFORW;
434 } else {
fb739082 435 addr->utfc = bdbtofsb(bp->b_blkno) - blkno;
b02cd1e9
BJ
436 bp->b_command = UT_SREV;
437 }
407582e3 438 sc->sc_timo = imin(imax(10 * -addr->utfc, 60), 5*60);
b02cd1e9
BJ
439
440dobpcmd:
441 /*
442 * Perform the command setup in bp.
443 */
c36079e2 444 addr->utcs1 = bp->b_command|UT_IE|UT_GO;
b02cd1e9
BJ
445 return;
446next:
447 /*
448 * Advance to the next command in the slave queue,
449 * posting notice and releasing resources as needed.
450 */
b02cd1e9
BJ
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;
6b0f2767 469 addr->utcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300)|UT_IE|UT_GO;
b02cd1e9
BJ
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;
c36079e2 484 u_short tjunit, cs2, cs1;
b02cd1e9
BJ
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 */
da9ebd7c 496 sc->sc_timo = INF;
b02cd1e9
BJ
497 sc->sc_dsreg = addr->utds;
498 sc->sc_erreg = addr->uter;
6b0f2767 499 sc->sc_resid = MASKREG(addr->utfc);
c36079e2 500 if ((bp->b_flags&B_READ) == 0)
b02cd1e9 501 sc->sc_lastiow = 1;
c36079e2
SL
502 state = um->um_tab.b_state;
503 um->um_tab.b_state = 0;
b02cd1e9
BJ
504 /*
505 * Check for errors...
506 */
507 if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE)) {
64614526
BJ
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;
b02cd1e9 520 /*
6b0f2767
SL
521 * If we were reading at 1600 or 6250 bpi and the error
522 * was corrected, then don't consider this an error.
b02cd1e9 523 */
452f8154 524 if (sc->sc_erreg & UTER_COR && (bp->b_flags & B_READ) &&
6b0f2767 525 (addr->uttc & UTTC_DEN) != UT_NRZI) {
5c0ca3ef 526 tprintf(sc->sc_tpr,
6b0f2767
SL
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;
b02cd1e9 531 }
b02cd1e9
BJ
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 */
5d4eae4d 537 if ((bp->b_flags & (B_READ|B_RAW)) == (B_READ|B_RAW) &&
b02cd1e9 538 (sc->sc_erreg&UTER_FCE))
6b0f2767 539 sc->sc_erreg &= ~UTER_FCE;
aaff71ec 540 if (sc->sc_erreg == 0)
b02cd1e9 541 goto ignoreerr;
c36079e2 542 /*
6b0f2767
SL
543 * Fix up errors which occur due to backspacing
544 * "over" the front of the tape.
c36079e2 545 */
6b0f2767 546 if ((sc->sc_dsreg & UTDS_BOT) && bp->b_command == UT_SREV &&
c36079e2
SL
547 ((sc->sc_erreg &= ~(UTER_NEF|UTER_FCE)) == 0))
548 goto opdone;
b02cd1e9
BJ
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 }
6b0f2767
SL
558 }
559 /*
560 * Hard or non-I/O errors on non-raw tape
561 * cause it to close.
562 */
5d4eae4d 563 if ((bp->b_flags&B_RAW) == 0 && sc->sc_openf > 0)
6b0f2767 564 sc->sc_openf = -1;
b02cd1e9
BJ
565 /*
566 * Couldn't recover error.
567 */
5c0ca3ef 568 tprintf(sc->sc_tpr,
fe23e54e 569 "ut%d: hard error bn%d cs1=%b er=%b cs2=%b ds=%b\n",
c36079e2
SL
570 tjunit, bp->b_blkno, cs1, UT_BITS, sc->sc_erreg,
571 UTER_BITS, cs2, UTCS2_BITS, sc->sc_dsreg, UTDS_BITS);
b02cd1e9
BJ
572 bp->b_flags |= B_ERROR;
573 goto opdone;
574 }
6b0f2767 575
b02cd1e9 576ignoreerr:
6b0f2767
SL
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 }
b02cd1e9
BJ
603 /*
604 * Advance tape control FSM.
605 */
606 switch (state) {
607
608 case SIO: /* read/write increments tape block # */
609 sc->sc_blkno++;
c457503f
MK
610 sc->sc_blks++;
611 if (um->um_tab.b_errcnt)
612 sc->sc_softerrs++;
c36079e2 613 break;
b02cd1e9 614
6b0f2767 615 case SCOM: /* motion commands update current position */
b02cd1e9 616 if (bp == &cutbuf[UTUNIT(bp->b_dev)])
9418508d 617 switch ((int)bp->b_command) {
b02cd1e9
BJ
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;
6b0f2767
SL
626
627 case UT_REWOFFL:
628 addr->utcs1 = UT_CLEAR|UT_GO;
629 break;
b02cd1e9 630 }
c36079e2 631 break;
b02cd1e9
BJ
632
633 case SSEEK:
fb739082 634 sc->sc_blkno = bdbtofsb(bp->b_blkno);
b02cd1e9
BJ
635 goto opcont;
636
c36079e2
SL
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
b02cd1e9 649 default:
c36079e2 650 printf("bad state %d\n", state);
b02cd1e9
BJ
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;
c36079e2 660 dp->b_actf = bp->av_forw;
6b0f2767
SL
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);
b02cd1e9
BJ
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);
407582e3
BJ
691}
692
693/*
694 * Watchdog timer routine.
695 */
696uttimer(dev)
697 int dev;
698{
699 register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
afa0df56 700 register short x;
407582e3
BJ
701
702 if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) {
d6357dcf 703 printf("tj%d: lost interrupt\n", TJUNIT(dev));
407582e3 704 sc->sc_timo = INF;
afa0df56 705 x = spl5();
407582e3 706 utintr(UTUNIT(dev));
afa0df56 707 (void) splx(x);
407582e3
BJ
708 }
709 timeout(uttimer, (caddr_t)dev, 5*hz);
b02cd1e9
BJ
710}
711
b02cd1e9 712/*ARGSUSED*/
942f05a9 713utioctl(dev, cmd, data, flag)
b02cd1e9 714 dev_t dev;
942f05a9 715 caddr_t data;
b02cd1e9
BJ
716{
717 register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
718 register struct buf *bp = &cutbuf[UTUNIT(dev)];
719 register callcount;
64389b40 720 int fcount, error = 0;
942f05a9
SL
721 struct mtop *mtop;
722 struct mtget *mtget;
b02cd1e9
BJ
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:
942f05a9
SL
730 mtop = (struct mtop *)data;
731 switch(mtop->mt_op) {
b02cd1e9
BJ
732
733 case MTWEOF:
b02cd1e9
BJ
734 case MTFSF: case MTBSF:
735 case MTFSR: case MTBSR:
d8ec6d6b
SL
736 callcount = mtop->mt_count;
737 fcount = 1;
b02cd1e9
BJ
738 break;
739
740 case MTREW: case MTOFFL: case MTNOP:
741 callcount = 1;
742 fcount = 1;
743 break;
744
745 default:
7da157da 746 return (ENXIO);
b02cd1e9 747 }
7da157da
BJ
748 if (callcount <= 0 || fcount <= 0)
749 return (EINVAL);
b02cd1e9 750 while (--callcount >= 0) {
942f05a9 751 utcommand(dev, utops[mtop->mt_op], fcount);
b02cd1e9
BJ
752 if ((bp->b_flags&B_ERROR) || (sc->sc_dsreg&UTDS_BOT))
753 break;
754 }
64389b40
KS
755 if (bp->b_flags&B_ERROR)
756 if ((error = bp->b_error)==0)
757 return (EIO);
758 return (error);
b02cd1e9
BJ
759
760 case MTIOCGET:
942f05a9
SL
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;
7da157da 766 break;
b02cd1e9
BJ
767
768 default:
7da157da 769 return (ENXIO);
b02cd1e9 770 }
7da157da 771 return (0);
b02cd1e9
BJ
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);
c36079e2 787 um->um_tab.b_state = 0;
b02cd1e9
BJ
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);
96b997eb 791 um->um_ubinfo = 0;
b02cd1e9
BJ
792 }
793 ((struct utdevice *)(um->um_addr))->utcs1 = UT_CLEAR|UT_GO;
c36079e2 794 ((struct utdevice *)(um->um_addr))->utcs2 |= UTCS2_CLR;
b02cd1e9
BJ
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];
c36079e2 800 dp->b_state = 0;
b02cd1e9
BJ
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;
c36079e2 824 register struct utdevice *addr;
b02cd1e9
BJ
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;
89b8a44c 833 ubainit(up);
b02cd1e9 834 DELAY(1000000);
c36079e2 835 addr = (struct utdevice *)ui->ui_physaddr;
89b8a44c 836 utwait(addr);
c36079e2
SL
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;
b02cd1e9
BJ
844 while (num > 0) {
845 blk = num > DBSIZE ? DBSIZE : num;
c36079e2
SL
846 utdwrite(start, blk, addr, up);
847 if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE))
848 return(EIO);
b02cd1e9
BJ
849 start += blk;
850 num -= blk;
851 }
c36079e2
SL
852 uteof(addr);
853 uteof(addr);
854 utwait(addr);
855 if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE))
b02cd1e9 856 return(EIO);
c36079e2 857 addr->utcs1 = UT_REW|UT_GO;
b02cd1e9
BJ
858 return (0);
859}
860
c36079e2 861utdwrite(dbuf, num, addr, up)
b02cd1e9 862 register dbuf, num;
c36079e2 863 register struct utdevice *addr;
b02cd1e9
BJ
864 struct uba_regs *up;
865{
866 register struct pte *io;
867 register int npf;
868
c36079e2 869 utwait(addr);
b02cd1e9
BJ
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;
c36079e2
SL
875 addr->utwc = -((num*NBPG)>>1);
876 addr->utfc = -(num*NBPG);
877 addr->utba = 0;
878 addr->utcs1 = UT_WCOM|UT_GO;
b02cd1e9
BJ
879}
880
c36079e2
SL
881utwait(addr)
882 struct utdevice *addr;
b02cd1e9
BJ
883{
884 register s;
885
886 do
c36079e2 887 s = addr->utds;
b02cd1e9
BJ
888 while ((s&UTDS_DRY) == 0);
889}
890
c36079e2
SL
891uteof(addr)
892 struct utdevice *addr;
b02cd1e9
BJ
893{
894
c36079e2
SL
895 utwait(addr);
896 addr->utcs1 = UT_WEOF|UT_GO;
b02cd1e9
BJ
897}
898#endif