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