lint
[unix-history] / usr / src / sys / vax / uba / ut.c
CommitLineData
89b8a44c 1/* ut.c 4.9 81/11/18 */
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
89b8a44c 87#if 0
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;
132
133 if (tjunit >= NTJ || (sc = &tj_softc[tjunit])->sc_openf ||
134 (ui = tjdinfo[tjunit]) == 0 || ui->ui_alive == 0) {
135 u.u_error = ENXIO;
136 return;
137 }
138 olddens = sc->sc_dens;
139 dens = sc->sc_dens = utdens[(minor(dev)&(T_1600BPI|T_6250BPI))>>3]|
140 PDP11FMT|(ui->ui_slave&07);
141get:
142 utcommand(dev, UT_SENSE, 1);
143 if (sc->sc_dsreg&UTDS_PIP) {
144 sleep((caddr_t) &lbolt, PZERO+1);
145 goto get;
146 }
147 sc->sc_dens = olddens;
148 if ((sc->sc_dsreg&UTDS_MOL) == 0) {
149 uprintf("tj%d: not online\n", tjunit);
150 u.u_error = EIO;
151 return;
152 }
153 if ((flag&FWRITE) && (sc->sc_dsreg&UTDS_WRL)) {
154 uprintf("tj%d: no write ring\n", tjunit);
155 u.u_error = EIO;
156 return;
157 }
158 if ((sc->sc_dsreg&UTDS_BOT) == 0 && (flag&FWRITE) &&
159 dens != sc->sc_dens) {
160 uprintf("tj%d: can't change density in mid-tape\n", tjunit);
161 u.u_error = EIO;
162 return;
163 }
164 sc->sc_openf = 1;
165 sc->sc_blkno = (daddr_t)0;
166 sc->sc_nxrec = INF;
167 sc->sc_lastiow = 0;
168 sc->sc_dens = dens;
c36079e2
SL
169 /*
170 * For 6250 bpi take exclusive use of the UNIBUS.
171 */
172 ui->ui_driver->ud_xclu = (dens&(T_1600BPI|T_6250BPI)) == T_6250BPI;
407582e3
BJ
173 (void) spl6();
174 if (sc->sc_tact == 0) {
175 sc->sc_timo = INF;
176 sc->sc_tact = 1;
177 timeout(uttimer, (caddr_t)dev, 5*hz);
178 }
179 (void) spl0();
b02cd1e9
BJ
180}
181
182utclose(dev, flag)
183 register dev_t dev;
184 register flag;
185{
186 register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
187
188 if (flag == FWRITE || ((flag&FWRITE) && sc->sc_lastiow)) {
189 utcommand(dev, UT_WEOF, 1);
190 utcommand(dev, UT_WEOF, 1);
191 utcommand(dev, UT_SREV, 1);
192 }
193 if ((minor(dev)&T_NOREWIND) == 0)
194 utcommand(dev, UT_REW, 0);
195 sc->sc_openf = 0;
196}
197
198utcommand(dev, com, count)
199 dev_t dev;
200 int com, count;
201{
202 register struct buf *bp;
203
204 bp = &cutbuf[UTUNIT(dev)];
205 (void) spl5();
206 while (bp->b_flags&B_BUSY) {
207 if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE))
208 break;
209 bp->b_flags |= B_WANTED;
210 sleep((caddr_t)bp, PRIBIO);
211 }
212 bp->b_flags = B_BUSY|B_READ;
213 (void) spl0();
214 bp->b_dev = dev;
215 bp->b_command = com;
216 bp->b_repcnt = count;
217 bp->b_blkno = 0;
218 utstrategy(bp);
219 if (count == 0)
220 return;
221 iowait(bp);
222 if (bp->b_flags&B_WANTED)
223 wakeup((caddr_t)bp);
224 bp->b_flags &= B_ERROR;
225}
226
227/*
228 * Queue a tape operation.
229 */
230utstrategy(bp)
231 register struct buf *bp;
232{
233 int tjunit = TJUNIT(bp->b_dev);
234 register struct uba_ctlr *um;
235 register struct buf *dp;
236
237 /*
238 * Put transfer at end of unit queue
239 */
240 dp = &tjutab[tjunit];
241 bp->av_forw = NULL;
242 (void) spl5();
243 if (dp->b_actf == NULL) {
244 dp->b_actf = bp;
245 /*
246 * Transport not active, so...
247 * put at end of controller queue
248 */
249 dp->b_forw = NULL;
250 um = tjdinfo[tjunit]->ui_mi;
251 if (um->um_tab.b_actf == NULL)
252 um->um_tab.b_actf = dp;
253 else
254 um->um_tab.b_actl->b_forw = dp;
255 um->um_tab.b_actl = dp;
256 } else
257 dp->b_actl->av_forw = bp;
258 dp->b_actl = bp;
259 /*
260 * If the controller is not busy, set it going.
261 */
c36079e2 262 if (um->um_tab.b_state == 0)
b02cd1e9
BJ
263 utstart(um);
264 (void) spl0();
265}
266
267utstart(um)
268 register struct uba_ctlr *um;
269{
c36079e2 270 register struct utdevice *addr;
b02cd1e9
BJ
271 register struct buf *bp, *dp;
272 register struct tj_softc *sc;
273 struct uba_device *ui;
274 int tjunit;
275 daddr_t blkno;
276
277loop:
278 /*
279 * Scan controller queue looking for units with
280 * transaction queues to dispatch
281 */
282 if ((dp = um->um_tab.b_actf) == NULL)
283 return;
284 if ((bp = dp->b_actf) == NULL) {
285 um->um_tab.b_actf = dp->b_forw;
286 goto loop;
287 }
c36079e2 288 addr = (struct utdevice *)um->um_addr;
b02cd1e9
BJ
289 tjunit = TJUNIT(bp->b_dev);
290 ui = tjdinfo[tjunit];
291 sc = &tj_softc[tjunit];
292 /* note slave select, density, and format were merged on open */
c36079e2
SL
293 addr->uttc = sc->sc_dens;
294 sc->sc_dsreg = addr->utds;
295 sc->sc_erreg = addr->uter;
296 /* watch this, sports fans */
297 sc->sc_resid = bp->b_flags&B_READ ?
298 bp->b_bcount - ((-addr->utfc)&0xffff) : -addr->utwc<<1;
b02cd1e9
BJ
299 /*
300 * Default is that last command was NOT a write command;
301 * if we do a write command we will notice this in utintr().
302 */
303 sc->sc_lastiow = 0;
c36079e2 304 if (sc->sc_openf < 0 || (addr->utds&UTDS_MOL) == 0) {
b02cd1e9
BJ
305 /*
306 * Have had a hard error on a non-raw tape
307 * or the tape unit is now unavailable
308 * (e.g. taken off line).
309 */
310 bp->b_flags |= B_ERROR;
311 goto next;
312 }
313 if (bp == &cutbuf[UTUNIT(bp->b_dev)]) {
314 /*
315 * Execute a control operation with the specified
316 * count.
317 */
318 if (bp->b_command == UT_SENSE)
319 goto next;
320 /*
321 * Set next state; handle timeouts
322 */
407582e3 323 if (bp->b_command == UT_REW) {
c36079e2 324 um->um_tab.b_state = SREW;
407582e3
BJ
325 sc->sc_timo = 5*60;
326 } else {
c36079e2 327 um->um_tab.b_state = SCOM;
407582e3
BJ
328 sc->sc_timo = imin(imax(10*(int)-bp->b_repcnt,60),5*60);
329 }
b02cd1e9
BJ
330 /* NOTE: this depends on the ut command values */
331 if (bp->b_command >= UT_SFORW && bp->b_command <= UT_SREVF)
c36079e2 332 addr->utfc = -bp->b_repcnt;
b02cd1e9
BJ
333 goto dobpcmd;
334 }
335 /*
336 * The following checks boundary conditions for operations
337 * on non-raw tapes. On raw tapes the initialization of
338 * sc->sc_nxrec by utphys causes them to be skipped normally
339 * (except in the case of retries).
340 */
341 if (dbtofsb(bp->b_blkno) > sc->sc_nxrec) {
342 /* can't read past end of file */
343 bp->b_flags |= B_ERROR;
344 bp->b_error = ENXIO;
345 goto next;
346 }
347 if (dbtofsb(bp->b_blkno) == sc->sc_nxrec && (bp->b_flags&B_READ)) {
348 /* read at eof returns 0 count */
349 bp->b_resid = bp->b_bcount;
350 clrbuf(bp);
351 goto next;
352 }
353 if ((bp->b_flags&B_READ) == 0)
354 sc->sc_nxrec = dbtofsb(bp->b_blkno)+1;
355 /*
356 * If the tape is correctly positioned, set up all the
357 * registers but the csr, and give control over to the
358 * UNIBUS adaptor routines, to wait for resources to
359 * start I/O.
360 */
361 if ((blkno = sc->sc_blkno) == dbtofsb(bp->b_blkno)) {
c36079e2
SL
362 addr->utwc = -(((bp->b_bcount)+1)>>1);
363 addr->utfc = -bp->b_bcount;
b02cd1e9
BJ
364 if ((bp->b_flags&B_READ) == 0) {
365 /*
366 * On write error retries erase the
c36079e2 367 * inter-record gap before rewriting.
b02cd1e9 368 */
c36079e2 369 if (um->um_tab.b_errcnt) {
c36079e2 370 if (um->um_tab.b_state != SERASED) {
64614526 371 um->um_tab.b_state = SERASE;
407582e3 372 sc->sc_timo = 60;
c36079e2
SL
373 addr->utcs1 = UT_ERASE|UT_IE|UT_GO;
374 return;
375 }
c36079e2
SL
376 }
377 um->um_cmd = UT_WCOM;
b02cd1e9
BJ
378 } else
379 um->um_cmd = UT_RCOM;
407582e3 380 sc->sc_timo = 60;
c36079e2 381 um->um_tab.b_state = SIO;
b02cd1e9
BJ
382 (void) ubago(ui);
383 return;
384 }
385 /*
386 * Tape positioned incorrectly; seek forwards or
387 * backwards to the correct spot. This happens for
388 * raw tapes only on error retries.
389 */
c36079e2 390 um->um_tab.b_state = SSEEK;
b02cd1e9 391 if (blkno < dbtofsb(bp->b_blkno)) {
c36079e2 392 addr->utfc = blkno - dbtofsb(bp->b_blkno);
b02cd1e9
BJ
393 bp->b_command = UT_SFORW;
394 } else {
c36079e2 395 addr->utfc = dbtofsb(bp->b_blkno) - blkno;
b02cd1e9
BJ
396 bp->b_command = UT_SREV;
397 }
407582e3 398 sc->sc_timo = imin(imax(10 * -addr->utfc, 60), 5*60);
b02cd1e9
BJ
399
400dobpcmd:
401 /*
402 * Perform the command setup in bp.
403 */
c36079e2 404 addr->utcs1 = bp->b_command|UT_IE|UT_GO;
b02cd1e9
BJ
405 return;
406next:
407 /*
408 * Advance to the next command in the slave queue,
409 * posting notice and releasing resources as needed.
410 */
b02cd1e9
BJ
411 if (um->um_ubinfo)
412 ubadone(um);
413 um->um_tab.b_errcnt = 0;
414 dp->b_actf = bp->av_forw;
415 iodone(bp);
416 goto loop;
417}
418
419/*
420 * Start operation on controller --
421 * UNIBUS resources have been allocated.
422 */
423utdgo(um)
424 register struct uba_ctlr *um;
425{
426 register struct utdevice *addr = (struct utdevice *)um->um_addr;
427
428 addr->utba = (u_short) um->um_ubinfo;
429 addr->utcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x30)|UT_IE|UT_GO;
b02cd1e9
BJ
430}
431
432/*
433 * Ut interrupt handler
434 */
435/*ARGSUSED*/
436utintr(ut11)
437 int ut11;
438{
439 struct buf *dp;
440 register struct buf *bp;
441 register struct uba_ctlr *um = utminfo[ut11];
442 register struct utdevice *addr;
443 register struct tj_softc *sc;
c36079e2 444 u_short tjunit, cs2, cs1;
b02cd1e9
BJ
445 register state;
446
447 if ((dp = um->um_tab.b_actf) == NULL)
448 return;
449 bp = dp->b_actf;
450 tjunit = TJUNIT(bp->b_dev);
451 addr = (struct utdevice *)tjdinfo[tjunit]->ui_addr;
452 sc = &tj_softc[tjunit];
453 /*
454 * Record status...
455 */
da9ebd7c 456 sc->sc_timo = INF;
b02cd1e9
BJ
457 sc->sc_dsreg = addr->utds;
458 sc->sc_erreg = addr->uter;
c36079e2
SL
459 sc->sc_resid = bp->b_flags&B_READ ?
460 bp->b_bcount - (-addr->utfc)&0xffff : -addr->utwc<<1;
c36079e2 461 if ((bp->b_flags&B_READ) == 0)
b02cd1e9 462 sc->sc_lastiow = 1;
c36079e2
SL
463 state = um->um_tab.b_state;
464 um->um_tab.b_state = 0;
b02cd1e9
BJ
465 /*
466 * Check for errors...
467 */
468 if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE)) {
64614526
BJ
469 /*
470 * To clear the ERR bit, we must issue a drive clear
471 * command, and to clear the TRE bit we must set the
472 * controller clear bit.
473 */
474 cs2 = addr->utcs2;
475 if ((cs1 = addr->utcs1)&UT_TRE)
476 addr->utcs2 |= UTCS2_CLR;
477 /* is this dangerous ?? */
478 while ((addr->utcs1&UT_RDY) == 0)
479 ;
480 addr->utcs1 = UT_CLEAR|UT_GO;
b02cd1e9 481 /*
c36079e2 482 * If we hit a tape mark or EOT update our position.
b02cd1e9 483 */
64614526 484 if (sc->sc_dsreg&(UTDS_TM|UTDS_EOT)) {
b02cd1e9 485 /*
64614526 486 * Set blkno and nxrec
b02cd1e9
BJ
487 */
488 if (bp == &cutbuf[UTUNIT(bp->b_dev)]) {
489 if (sc->sc_blkno > dbtofsb(bp->b_blkno)) {
b02cd1e9
BJ
490 sc->sc_nxrec =
491 dbtofsb(bp->b_blkno) - addr->utfc;
492 sc->sc_blkno = sc->sc_nxrec;
493 } else {
b02cd1e9
BJ
494 sc->sc_blkno =
495 dbtofsb(bp->b_blkno) + addr->utfc;
496 sc->sc_nxrec = sc->sc_blkno-1;
497 }
c36079e2 498 } else
b02cd1e9
BJ
499 sc->sc_nxrec = dbtofsb(bp->b_blkno);
500 state = SCOM; /* force completion */
b02cd1e9 501 /*
c36079e2
SL
502 * Stuff so we can unstuff later
503 * to get the residual.
b02cd1e9 504 */
c36079e2 505 addr->utwc = (-bp->b_bcount)>>1;
b02cd1e9 506 addr->utfc = -bp->b_bcount;
c36079e2
SL
507 if (sc->sc_dsreg&UTDS_EOT)
508 goto harderror;
b02cd1e9
BJ
509 goto opdone;
510 }
b02cd1e9
BJ
511 /*
512 * If we were reading from a raw tape and the only error
513 * was that the record was too long, then we don't consider
514 * this an error.
515 */
516 if (bp == &rutbuf[UTUNIT(bp->b_dev)] && (bp->b_flags&B_READ) &&
517 (sc->sc_erreg&UTER_FCE))
518 goto ignoreerr;
c36079e2
SL
519 /*
520 * Fix up errors which occur due to backspacing "over" the
521 * front of the tape.
522 */
523 if ((sc->sc_dsreg&UTDS_BOT) &&
524 (bp->b_command == UT_SREV || bp->b_command == UT_SREV) &&
525 ((sc->sc_erreg &= ~(UTER_NEF|UTER_FCE)) == 0))
526 goto opdone;
b02cd1e9
BJ
527 /*
528 * Retry soft errors up to 8 times
529 */
530 if ((sc->sc_erreg&UTER_HARD) == 0 && state == SIO) {
531 if (++um->um_tab.b_errcnt < 7) {
532 sc->sc_blkno++;
533 ubadone(um);
534 goto opcont;
535 }
536 } else
c36079e2 537harderror:
b02cd1e9
BJ
538 /*
539 * Hard or non-I/O errors on non-raw tape
c36079e2
SL
540 * cause it to close; also, reading off the
541 * end of the tape.
b02cd1e9 542 */
c36079e2
SL
543 if (sc->sc_openf > 0 &&
544 bp != &rutbuf[UTUNIT(bp->b_dev)] ||
545 sc->sc_dsreg&UTDS_EOT)
b02cd1e9
BJ
546 sc->sc_openf = -1;
547 /*
548 * Couldn't recover error.
549 */
c36079e2
SL
550 printf("ut%d: hard error bn%d cs1=%b er=%b cs2=%b ds=%b\n",
551 tjunit, bp->b_blkno, cs1, UT_BITS, sc->sc_erreg,
552 UTER_BITS, cs2, UTCS2_BITS, sc->sc_dsreg, UTDS_BITS);
b02cd1e9
BJ
553 bp->b_flags |= B_ERROR;
554 goto opdone;
555 }
556ignoreerr:
557 /*
558 * Advance tape control FSM.
559 */
560 switch (state) {
561
562 case SIO: /* read/write increments tape block # */
563 sc->sc_blkno++;
c36079e2 564 break;
b02cd1e9
BJ
565
566 case SCOM: /* forw/rev space updates current position */
567 if (bp == &cutbuf[UTUNIT(bp->b_dev)])
568 switch (bp->b_command) {
569
570 case UT_SFORW:
571 sc->sc_blkno -= bp->b_repcnt;
572 break;
573
574 case UT_SREV:
575 sc->sc_blkno += bp->b_repcnt;
576 break;
577 }
c36079e2 578 break;
b02cd1e9
BJ
579
580 case SSEEK:
581 sc->sc_blkno = dbtofsb(bp->b_blkno);
582 goto opcont;
583
c36079e2
SL
584 case SERASE:
585 /*
586 * Completed erase of the inter-record gap due to a
587 * write error; now retry the write operation.
588 */
589 um->um_tab.b_state = SERASED;
590 goto opcont;
591
592 case SREW: /* clear attention bit */
593 addr->utcs1 = UT_CLEAR|UT_GO;
594 break;
595
b02cd1e9 596 default:
c36079e2 597 printf("bad state %d\n", state);
b02cd1e9
BJ
598 panic("utintr");
599 }
600
601opdone:
602 /*
603 * Reset error count and remove
604 * from device queue
605 */
606 um->um_tab.b_errcnt = 0;
c36079e2
SL
607 dp->b_actf = bp->av_forw;
608 bp->b_resid = bp->b_command&B_READ ?
609 bp->b_bcount - ((-addr->utfc)&0xffff) : -addr->utwc<<1;
b02cd1e9
BJ
610 ubadone(um);
611 iodone(bp);
612 /*
613 * Circulate slave to end of controller queue
614 * to give other slaves a chance
615 */
616 um->um_tab.b_actf = dp->b_forw;
617 if (dp->b_actf) {
618 dp->b_forw = NULL;
619 if (um->um_tab.b_actf == NULL)
620 um->um_tab.b_actf = dp;
621 else
622 um->um_tab.b_actl->b_forw = dp;
623 um->um_tab.b_actl = dp;
624 }
625 if (um->um_tab.b_actf == 0)
626 return;
627opcont:
628 utstart(um);
407582e3
BJ
629}
630
631/*
632 * Watchdog timer routine.
633 */
634uttimer(dev)
635 int dev;
636{
637 register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
afa0df56 638 register short x;
407582e3
BJ
639
640 if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) {
d6357dcf 641 printf("tj%d: lost interrupt\n", TJUNIT(dev));
407582e3 642 sc->sc_timo = INF;
afa0df56 643 x = spl5();
407582e3 644 utintr(UTUNIT(dev));
afa0df56 645 (void) splx(x);
407582e3
BJ
646 }
647 timeout(uttimer, (caddr_t)dev, 5*hz);
b02cd1e9
BJ
648}
649
650/*
651 * Raw interface for a read
652 */
653utread(dev)
654 dev_t dev;
655{
656 utphys(dev);
657 if (u.u_error)
658 return;
659 physio(utstrategy, &rutbuf[UTUNIT(dev)], dev, B_READ, minphys);
660}
661
662/*
663 * Raw interface for a write
664 */
665utwrite(dev)
666{
667 utphys(dev);
668 if (u.u_error)
669 return;
670 physio(utstrategy, &rutbuf[UTUNIT(dev)], dev, B_WRITE, minphys);
671}
672
673/*
674 * Check for valid device number dev and update our notion
675 * of where we are on the tape
676 */
677utphys(dev)
678 dev_t dev;
679{
680 register int tjunit = TJUNIT(dev);
681 register struct tj_softc *sc;
682 register struct uba_device *ui;
b02cd1e9
BJ
683
684 if (tjunit >= NTJ || (ui=tjdinfo[tjunit]) == 0 || ui->ui_alive == 0) {
685 u.u_error = ENXIO;
686 return;
687 }
b02cd1e9 688 sc = &tj_softc[tjunit];
c36079e2
SL
689 sc->sc_blkno = dbtofsb(u.u_offset>>9);
690 sc->sc_nxrec = sc->sc_blkno+1;
b02cd1e9
BJ
691}
692
693/*ARGSUSED*/
694utioctl(dev, cmd, addr, flag)
695 dev_t dev;
696 caddr_t addr;
697{
698 register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
699 register struct buf *bp = &cutbuf[UTUNIT(dev)];
700 register callcount;
701 int fcount;
702 struct mtop mtop;
703 struct mtget mtget;
704 /* we depend of the values and order of the MT codes here */
705 static utops[] =
706 {UT_WEOF,UT_SFORWF,UT_SREVF,UT_SFORW,UT_SREV,UT_REW,UT_REWOFFL,UT_SENSE};
707
708 switch (cmd) {
709
710 case MTIOCTOP:
711 if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
712 u.u_error = EFAULT;
713 return;
714 }
715 switch(mtop.mt_op) {
716
717 case MTWEOF:
718 callcount = mtop.mt_count;
719 fcount = 1;
720 break;
721
722 case MTFSF: case MTBSF:
723 case MTFSR: case MTBSR:
724 callcount = 1;
725 fcount = mtop.mt_count;
726 break;
727
728 case MTREW: case MTOFFL: case MTNOP:
729 callcount = 1;
730 fcount = 1;
731 break;
732
733 default:
734 u.u_error = ENXIO;
735 return;
736 }
737 if (callcount <= 0 || fcount <= 0) {
738 u.u_error = ENXIO;
739 return;
740 }
741 while (--callcount >= 0) {
742 utcommand(dev, utops[mtop.mt_op], fcount);
c36079e2
SL
743 /* note this depends on the mtop values */
744 if ((mtop.mt_op >= MTFSF || mtop.mt_op <= MTBSR) &&
b02cd1e9
BJ
745 bp->b_resid) {
746 u.u_error = EIO;
747 break;
748 }
749 if ((bp->b_flags&B_ERROR) || (sc->sc_dsreg&UTDS_BOT))
750 break;
751 }
752 geterror(bp);
753 return;
754
755 case MTIOCGET:
756 mtget.mt_dsreg = sc->sc_dsreg;
757 mtget.mt_erreg = sc->sc_erreg;
758 mtget.mt_resid = sc->sc_resid;
759 mtget.mt_type = MT_ISUT;
760 if (copyout((caddr_t)&mtget, addr, sizeof(mtget)))
761 u.u_error = EFAULT;
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