|
|
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.3 (Berkeley) 5/6/88
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 "dir.h"
24: #include "file.h"
25: #include "user.h"
26: #include "map.h"
27: #include "ioctl.h"
28: #include "mtio.h"
29: #include "cmap.h"
30: #include "uio.h"
31: #include "kernel.h"
32: #include "tty.h"
33: #include "syslog.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: struct tty *sc_ttyp; /* record user's tty for errors */
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;
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: sleep((caddr_t)&lbolt, PZERO+1);
155: goto get;
156: }
157: sc->sc_dens = olddens;
158: if ((sc->sc_dsreg&UTDS_MOL) == 0) {
159: sc->sc_openf = 0;
160: uprintf("tj%d: not online\n", tjunit);
161: return (EIO);
162: }
163: if ((flag&FWRITE) && (sc->sc_dsreg&UTDS_WRL)) {
164: sc->sc_openf = 0;
165: uprintf("tj%d: no write ring\n", tjunit);
166: return (EIO);
167: }
168: if ((sc->sc_dsreg&UTDS_BOT) == 0 && (flag&FWRITE) &&
169: dens != sc->sc_dens) {
170: sc->sc_openf = 0;
171: uprintf("tj%d: can't change density in mid-tape\n", tjunit);
172: return (EIO);
173: }
174: sc->sc_blkno = (daddr_t)0;
175: sc->sc_nxrec = INF;
176: sc->sc_lastiow = 0;
177: sc->sc_blks = 0;
178: sc->sc_softerrs = 0;
179: sc->sc_dens = dens;
180: sc->sc_ttyp = u.u_ttyp;
181: /*
182: * For 6250 bpi take exclusive use of the UNIBUS.
183: */
184: ui->ui_driver->ud_xclu = (dens&(T_1600BPI|T_6250BPI)) == T_6250BPI;
185: s = splclock();
186: if (sc->sc_tact == 0) {
187: sc->sc_timo = INF;
188: sc->sc_tact = 1;
189: timeout(uttimer, (caddr_t)dev, 5*hz);
190: }
191: splx(s);
192: return (0);
193: }
194:
195: utclose(dev, flag)
196: register dev_t dev;
197: register flag;
198: {
199: register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
200:
201: if (flag == FWRITE || ((flag&FWRITE) && sc->sc_lastiow)) {
202: utcommand(dev, UT_WEOF, 1);
203: utcommand(dev, UT_WEOF, 1);
204: utcommand(dev, UT_SREV, 1);
205: }
206: if ((minor(dev)&T_NOREWIND) == 0)
207: utcommand(dev, UT_REW, 0);
208: if (sc->sc_blks > 100 && sc->sc_softerrs > sc->sc_blks / 100)
209: log(LOG_INFO, "tj%d: %d soft errors in %d blocks\n",
210: TJUNIT(dev), sc->sc_softerrs, sc->sc_blks);
211: sc->sc_openf = 0;
212: }
213:
214: utcommand(dev, com, count)
215: dev_t dev;
216: int com, count;
217: {
218: register struct buf *bp;
219: register int s;
220:
221: bp = &cutbuf[UTUNIT(dev)];
222: s = spl5();
223: while (bp->b_flags&B_BUSY) {
224: if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE))
225: break;
226: bp->b_flags |= B_WANTED;
227: sleep((caddr_t)bp, PRIBIO);
228: }
229: bp->b_flags = B_BUSY|B_READ;
230: splx(s);
231: bp->b_dev = dev;
232: bp->b_command = com;
233: bp->b_repcnt = count;
234: bp->b_blkno = 0;
235: utstrategy(bp);
236: if (count == 0)
237: return;
238: iowait(bp);
239: if (bp->b_flags&B_WANTED)
240: wakeup((caddr_t)bp);
241: bp->b_flags &= B_ERROR;
242: }
243:
244: /*
245: * Queue a tape operation.
246: */
247: utstrategy(bp)
248: register struct buf *bp;
249: {
250: int tjunit = TJUNIT(bp->b_dev);
251: register struct uba_ctlr *um;
252: register struct buf *dp;
253: int s;
254:
255: /*
256: * Put transfer at end of unit queue
257: */
258: dp = &tjutab[tjunit];
259: bp->av_forw = NULL;
260: um = tjdinfo[tjunit]->ui_mi;
261: s = spl5();
262: if (dp->b_actf == NULL) {
263: dp->b_actf = bp;
264: /*
265: * Transport not active, so...
266: * put at end of controller queue
267: */
268: dp->b_forw = NULL;
269: if (um->um_tab.b_actf == NULL)
270: um->um_tab.b_actf = dp;
271: else
272: um->um_tab.b_actl->b_forw = dp;
273: um->um_tab.b_actl = dp;
274: } else
275: dp->b_actl->av_forw = bp;
276: dp->b_actl = bp;
277: /*
278: * If the controller is not busy, set it going.
279: */
280: if (um->um_tab.b_state == 0)
281: utstart(um);
282: splx(s);
283: }
284:
285: utstart(um)
286: register struct uba_ctlr *um;
287: {
288: register struct utdevice *addr;
289: register struct buf *bp, *dp;
290: register struct tj_softc *sc;
291: struct uba_device *ui;
292: int tjunit;
293: daddr_t blkno;
294:
295: loop:
296: /*
297: * Scan controller queue looking for units with
298: * transaction queues to dispatch
299: */
300: if ((dp = um->um_tab.b_actf) == NULL)
301: return;
302: if ((bp = dp->b_actf) == NULL) {
303: um->um_tab.b_actf = dp->b_forw;
304: goto loop;
305: }
306: addr = (struct utdevice *)um->um_addr;
307: tjunit = TJUNIT(bp->b_dev);
308: ui = tjdinfo[tjunit];
309: sc = &tj_softc[tjunit];
310: /* note slave select, density, and format were merged on open */
311: addr->uttc = sc->sc_dens;
312: sc->sc_dsreg = addr->utds;
313: sc->sc_erreg = addr->uter;
314: sc->sc_resid = MASKREG(addr->utfc);
315: /*
316: * Default is that last command was NOT a write command;
317: * if we do a write command we will notice this in utintr().
318: */
319: sc->sc_lastiow = 0;
320: if (sc->sc_openf < 0 || (addr->utds&UTDS_MOL) == 0) {
321: /*
322: * Have had a hard error on a non-raw tape
323: * or the tape unit is now unavailable
324: * (e.g. taken off line).
325: */
326: bp->b_flags |= B_ERROR;
327: goto next;
328: }
329: if (bp == &cutbuf[UTUNIT(bp->b_dev)]) {
330: /*
331: * Execute a control operation with the specified
332: * count.
333: */
334: if (bp->b_command == UT_SENSE)
335: goto next;
336: if (bp->b_command == UT_SFORW && (addr->utds & UTDS_EOT)) {
337: bp->b_resid = bp->b_bcount;
338: goto next;
339: }
340: /*
341: * Set next state; handle timeouts
342: */
343: if (bp->b_command == UT_REW) {
344: um->um_tab.b_state = SREW;
345: sc->sc_timo = 5*60;
346: } else {
347: um->um_tab.b_state = SCOM;
348: sc->sc_timo = imin(imax(10*(int)-bp->b_repcnt,60),5*60);
349: }
350: /* NOTE: this depends on the ut command values */
351: if (bp->b_command >= UT_SFORW && bp->b_command <= UT_SREVF)
352: addr->utfc = -bp->b_repcnt;
353: goto dobpcmd;
354: }
355: /*
356: * For raw I/O, save the current block
357: * number in case we have to retry.
358: */
359: if (bp->b_flags & B_RAW) {
360: if (um->um_tab.b_errcnt == 0) {
361: sc->sc_blkno = bdbtofsb(bp->b_blkno);
362: sc->sc_nxrec = sc->sc_blkno + 1;
363: }
364: }
365: else {
366: /*
367: * Handle boundary cases for operation
368: * on non-raw tapes.
369: */
370: if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) {
371: /* can't read past end of file */
372: bp->b_flags |= B_ERROR;
373: bp->b_error = ENXIO;
374: goto next;
375: }
376: if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec &&
377: (bp->b_flags&B_READ)) {
378: /*
379: * Reading at end of file returns 0 bytes.
380: */
381: bp->b_resid = bp->b_bcount;
382: clrbuf(bp);
383: goto next;
384: }
385: if ((bp->b_flags&B_READ) == 0)
386: sc->sc_nxrec = bdbtofsb(bp->b_blkno) + 1;
387: }
388: /*
389: * If the tape is correctly positioned, set up all the
390: * registers but the csr, and give control over to the
391: * UNIBUS adaptor routines, to wait for resources to
392: * start I/O.
393: */
394: if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) {
395: addr->utwc = -(((bp->b_bcount)+1)>>1);
396: addr->utfc = -bp->b_bcount;
397: if ((bp->b_flags&B_READ) == 0) {
398: /*
399: * On write error retries erase the
400: * inter-record gap before rewriting.
401: */
402: if (um->um_tab.b_errcnt) {
403: if (um->um_tab.b_state != SERASED) {
404: um->um_tab.b_state = SERASE;
405: sc->sc_timo = 60;
406: addr->utcs1 = UT_ERASE|UT_IE|UT_GO;
407: return;
408: }
409: }
410: if (addr->utds & UTDS_EOT) {
411: bp->b_resid = bp->b_bcount;
412: um->um_tab.b_state = 0;
413: goto next;
414: }
415: um->um_cmd = UT_WCOM;
416: } else
417: um->um_cmd = UT_RCOM;
418: sc->sc_timo = 60;
419: um->um_tab.b_state = SIO;
420: (void) ubago(ui);
421: return;
422: }
423: /*
424: * Tape positioned incorrectly; seek forwards or
425: * backwards to the correct spot. This happens for
426: * raw tapes only on error retries.
427: */
428: um->um_tab.b_state = SSEEK;
429: if (blkno < bdbtofsb(bp->b_blkno)) {
430: addr->utfc = blkno - bdbtofsb(bp->b_blkno);
431: bp->b_command = UT_SFORW;
432: } else {
433: addr->utfc = bdbtofsb(bp->b_blkno) - blkno;
434: bp->b_command = UT_SREV;
435: }
436: sc->sc_timo = imin(imax(10 * -addr->utfc, 60), 5*60);
437:
438: dobpcmd:
439: /*
440: * Perform the command setup in bp.
441: */
442: addr->utcs1 = bp->b_command|UT_IE|UT_GO;
443: return;
444: next:
445: /*
446: * Advance to the next command in the slave queue,
447: * posting notice and releasing resources as needed.
448: */
449: if (um->um_ubinfo)
450: ubadone(um);
451: um->um_tab.b_errcnt = 0;
452: dp->b_actf = bp->av_forw;
453: iodone(bp);
454: goto loop;
455: }
456:
457: /*
458: * Start operation on controller --
459: * UNIBUS resources have been allocated.
460: */
461: utdgo(um)
462: register struct uba_ctlr *um;
463: {
464: register struct utdevice *addr = (struct utdevice *)um->um_addr;
465:
466: addr->utba = (u_short) um->um_ubinfo;
467: addr->utcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300)|UT_IE|UT_GO;
468: }
469:
470: /*
471: * Ut interrupt handler
472: */
473: /*ARGSUSED*/
474: utintr(ut11)
475: int ut11;
476: {
477: struct buf *dp;
478: register struct buf *bp;
479: register struct uba_ctlr *um = utminfo[ut11];
480: register struct utdevice *addr;
481: register struct tj_softc *sc;
482: u_short tjunit, cs2, cs1;
483: register state;
484:
485: if ((dp = um->um_tab.b_actf) == NULL)
486: return;
487: bp = dp->b_actf;
488: tjunit = TJUNIT(bp->b_dev);
489: addr = (struct utdevice *)tjdinfo[tjunit]->ui_addr;
490: sc = &tj_softc[tjunit];
491: /*
492: * Record status...
493: */
494: sc->sc_timo = INF;
495: sc->sc_dsreg = addr->utds;
496: sc->sc_erreg = addr->uter;
497: sc->sc_resid = MASKREG(addr->utfc);
498: if ((bp->b_flags&B_READ) == 0)
499: sc->sc_lastiow = 1;
500: state = um->um_tab.b_state;
501: um->um_tab.b_state = 0;
502: /*
503: * Check for errors...
504: */
505: if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE)) {
506: /*
507: * To clear the ERR bit, we must issue a drive clear
508: * command, and to clear the TRE bit we must set the
509: * controller clear bit.
510: */
511: cs2 = addr->utcs2;
512: if ((cs1 = addr->utcs1)&UT_TRE)
513: addr->utcs2 |= UTCS2_CLR;
514: /* is this dangerous ?? */
515: while ((addr->utcs1&UT_RDY) == 0)
516: ;
517: addr->utcs1 = UT_CLEAR|UT_GO;
518: /*
519: * If we were reading at 1600 or 6250 bpi and the error
520: * was corrected, then don't consider this an error.
521: */
522: if (sc->sc_erreg & UTER_COR && (bp->b_flags & B_READ) &&
523: (addr->uttc & UTTC_DEN) != UT_NRZI) {
524: tprintf(sc->sc_ttyp,
525: "ut%d: soft error bn%d cs1=%b er=%b cs2=%b ds=%b\n",
526: tjunit, bp->b_blkno, cs1, UT_BITS, sc->sc_erreg,
527: UTER_BITS, cs2, UTCS2_BITS, sc->sc_dsreg, UTDS_BITS);
528: sc->sc_erreg &= ~UTER_COR;
529: }
530: /*
531: * If we were reading from a raw tape and the only error
532: * was that the record was too long, then we don't consider
533: * this an error.
534: */
535: if ((bp->b_flags & (B_READ|B_RAW)) == (B_READ|B_RAW) &&
536: (sc->sc_erreg&UTER_FCE))
537: sc->sc_erreg &= ~UTER_FCE;
538: if (sc->sc_erreg == 0)
539: goto ignoreerr;
540: /*
541: * Fix up errors which occur due to backspacing
542: * "over" the front of the tape.
543: */
544: if ((sc->sc_dsreg & UTDS_BOT) && bp->b_command == UT_SREV &&
545: ((sc->sc_erreg &= ~(UTER_NEF|UTER_FCE)) == 0))
546: goto opdone;
547: /*
548: * Retry soft errors up to 8 times
549: */
550: if ((sc->sc_erreg&UTER_HARD) == 0 && state == SIO) {
551: if (++um->um_tab.b_errcnt < 7) {
552: sc->sc_blkno++;
553: ubadone(um);
554: goto opcont;
555: }
556: }
557: /*
558: * Hard or non-I/O errors on non-raw tape
559: * cause it to close.
560: */
561: if ((bp->b_flags&B_RAW) == 0 && sc->sc_openf > 0)
562: sc->sc_openf = -1;
563: /*
564: * Couldn't recover error.
565: */
566: tprintf(sc->sc_ttyp,
567: "ut%d: hard error bn%d cs1=%b er=%b cs2=%b ds=%b\n",
568: tjunit, bp->b_blkno, cs1, UT_BITS, sc->sc_erreg,
569: UTER_BITS, cs2, UTCS2_BITS, sc->sc_dsreg, UTDS_BITS);
570: bp->b_flags |= B_ERROR;
571: goto opdone;
572: }
573:
574: ignoreerr:
575: /*
576: * If we hit a tape mark update our position.
577: */
578: if (sc->sc_dsreg & UTDS_TM && bp->b_flags & B_READ) {
579: /*
580: * Set blkno and nxrec
581: */
582: if (bp == &cutbuf[UTUNIT(bp->b_dev)]) {
583: if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) {
584: sc->sc_nxrec =
585: bdbtofsb(bp->b_blkno) - addr->utfc;
586: sc->sc_blkno = sc->sc_nxrec;
587: } else {
588: sc->sc_blkno =
589: bdbtofsb(bp->b_blkno) + addr->utfc;
590: sc->sc_nxrec = sc->sc_blkno-1;
591: }
592: } else
593: sc->sc_nxrec = bdbtofsb(bp->b_blkno);
594: /*
595: * Note: if we get a tape mark on a read, the
596: * frame count register will be zero, so b_resid
597: * will be calculated correctly below.
598: */
599: goto opdone;
600: }
601: /*
602: * Advance tape control FSM.
603: */
604: switch (state) {
605:
606: case SIO: /* read/write increments tape block # */
607: sc->sc_blkno++;
608: sc->sc_blks++;
609: if (um->um_tab.b_errcnt)
610: sc->sc_softerrs++;
611: break;
612:
613: case SCOM: /* motion commands update current position */
614: if (bp == &cutbuf[UTUNIT(bp->b_dev)])
615: switch ((int)bp->b_command) {
616:
617: case UT_SFORW:
618: sc->sc_blkno -= bp->b_repcnt;
619: break;
620:
621: case UT_SREV:
622: sc->sc_blkno += bp->b_repcnt;
623: break;
624:
625: case UT_REWOFFL:
626: addr->utcs1 = UT_CLEAR|UT_GO;
627: break;
628: }
629: break;
630:
631: case SSEEK:
632: sc->sc_blkno = bdbtofsb(bp->b_blkno);
633: goto opcont;
634:
635: case SERASE:
636: /*
637: * Completed erase of the inter-record gap due to a
638: * write error; now retry the write operation.
639: */
640: um->um_tab.b_state = SERASED;
641: goto opcont;
642:
643: case SREW: /* clear attention bit */
644: addr->utcs1 = UT_CLEAR|UT_GO;
645: break;
646:
647: default:
648: printf("bad state %d\n", state);
649: panic("utintr");
650: }
651:
652: opdone:
653: /*
654: * Reset error count and remove
655: * from device queue
656: */
657: um->um_tab.b_errcnt = 0;
658: dp->b_actf = bp->av_forw;
659: /*
660: * For read command, frame count register contains
661: * actual length of tape record. Otherwise, it
662: * holds negative residual count.
663: */
664: if (state == SIO && um->um_cmd == UT_RCOM) {
665: bp->b_resid = 0;
666: if (bp->b_bcount > MASKREG(addr->utfc))
667: bp->b_resid = bp->b_bcount - MASKREG(addr->utfc);
668: } else
669: bp->b_resid = MASKREG(-addr->utfc);
670: ubadone(um);
671: iodone(bp);
672: /*
673: * Circulate slave to end of controller queue
674: * to give other slaves a chance
675: */
676: um->um_tab.b_actf = dp->b_forw;
677: if (dp->b_actf) {
678: dp->b_forw = NULL;
679: if (um->um_tab.b_actf == NULL)
680: um->um_tab.b_actf = dp;
681: else
682: um->um_tab.b_actl->b_forw = dp;
683: um->um_tab.b_actl = dp;
684: }
685: if (um->um_tab.b_actf == 0)
686: return;
687: opcont:
688: utstart(um);
689: }
690:
691: /*
692: * Watchdog timer routine.
693: */
694: uttimer(dev)
695: int dev;
696: {
697: register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
698: register short x;
699:
700: if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) {
701: printf("tj%d: lost interrupt\n", TJUNIT(dev));
702: sc->sc_timo = INF;
703: x = spl5();
704: utintr(UTUNIT(dev));
705: (void) splx(x);
706: }
707: timeout(uttimer, (caddr_t)dev, 5*hz);
708: }
709:
710: /*ARGSUSED*/
711: utioctl(dev, cmd, data, flag)
712: dev_t dev;
713: caddr_t data;
714: {
715: register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
716: register struct buf *bp = &cutbuf[UTUNIT(dev)];
717: register callcount;
718: int fcount;
719: struct mtop *mtop;
720: struct mtget *mtget;
721: /* we depend of the values and order of the MT codes here */
722: static utops[] =
723: {UT_WEOF,UT_SFORWF,UT_SREVF,UT_SFORW,UT_SREV,UT_REW,UT_REWOFFL,UT_SENSE};
724:
725: switch (cmd) {
726:
727: case MTIOCTOP:
728: mtop = (struct mtop *)data;
729: switch(mtop->mt_op) {
730:
731: case MTWEOF:
732: case MTFSF: case MTBSF:
733: case MTFSR: case MTBSR:
734: callcount = mtop->mt_count;
735: fcount = 1;
736: break;
737:
738: case MTREW: case MTOFFL: case MTNOP:
739: callcount = 1;
740: fcount = 1;
741: break;
742:
743: default:
744: return (ENXIO);
745: }
746: if (callcount <= 0 || fcount <= 0)
747: return (EINVAL);
748: while (--callcount >= 0) {
749: utcommand(dev, utops[mtop->mt_op], fcount);
750: if ((bp->b_flags&B_ERROR) || (sc->sc_dsreg&UTDS_BOT))
751: break;
752: }
753: return (geterror(bp));
754:
755: case MTIOCGET:
756: mtget = (struct mtget *)data;
757: mtget->mt_dsreg = sc->sc_dsreg;
758: mtget->mt_erreg = sc->sc_erreg;
759: mtget->mt_resid = sc->sc_resid;
760: mtget->mt_type = MT_ISUT;
761: break;
762:
763: default:
764: return (ENXIO);
765: }
766: return (0);
767: }
768:
769: utreset(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);
782: um->um_tab.b_state = 0;
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: um->um_ubinfo = 0;
787: }
788: ((struct utdevice *)(um->um_addr))->utcs1 = UT_CLEAR|UT_GO;
789: ((struct utdevice *)(um->um_addr))->utcs2 |= UTCS2_CLR;
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];
795: dp->b_state = 0;
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:
815: utdump()
816: {
817: register struct uba_device *ui;
818: register struct uba_regs *up;
819: register struct utdevice *addr;
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;
828: ubainit(up);
829: DELAY(1000000);
830: addr = (struct utdevice *)ui->ui_physaddr;
831: utwait(addr);
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;
839: while (num > 0) {
840: blk = num > DBSIZE ? DBSIZE : num;
841: utdwrite(start, blk, addr, up);
842: if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE))
843: return(EIO);
844: start += blk;
845: num -= blk;
846: }
847: uteof(addr);
848: uteof(addr);
849: utwait(addr);
850: if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE))
851: return(EIO);
852: addr->utcs1 = UT_REW|UT_GO;
853: return (0);
854: }
855:
856: utdwrite(dbuf, num, addr, up)
857: register dbuf, num;
858: register struct utdevice *addr;
859: struct uba_regs *up;
860: {
861: register struct pte *io;
862: register int npf;
863:
864: utwait(addr);
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;
870: addr->utwc = -((num*NBPG)>>1);
871: addr->utfc = -(num*NBPG);
872: addr->utba = 0;
873: addr->utcs1 = UT_WCOM|UT_GO;
874: }
875:
876: utwait(addr)
877: struct utdevice *addr;
878: {
879: register s;
880:
881: do
882: s = addr->utds;
883: while ((s&UTDS_DRY) == 0);
884: }
885:
886: uteof(addr)
887: struct utdevice *addr;
888: {
889:
890: utwait(addr);
891: addr->utcs1 = UT_WEOF|UT_GO;
892: }
893: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.