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