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