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