1: #
2:
3: /*
4: * TM tape driver
5: */
6:
7: #include "../h/param.h"
8: #include "../h/buf.h"
9: #include "../h/dir.h"
10: #include "../h/conf.h"
11: #include "../h/file.h"
12: #include "../h/user.h"
13:
14: struct device {
15: int tmer;
16: int tmcs;
17: int tmbc;
18: char *tmba;
19: int tmdb;
20: int tmrd;
21: };
22:
23: struct buf tmtab;
24: struct buf ctmbuf;
25: struct buf rtmbuf;
26:
27: char t_flags[8];
28: char t_openf[8];
29: daddr_t t_blkno[8];
30: daddr_t t_nxrec[8];
31:
32: #define TMADDR ((struct device *)0172520)
33:
34: #define GO 01
35: #define RCOM 02
36: #define WCOM 04
37: #define WEOF 06
38: #define NOP 0100
39: #define SFORW 010
40: #define SREV 012
41: #define WIRG 014
42: #define REW 016
43: #define DENS 060000 /* 9-channel */
44: #define IENABLE 0100
45: #define CRDY 0200
46: #define GAPSD 010000
47: #define TUR 1
48: #define HARD 0102200 /* ILC, EOT, NXM */
49: #define RLE 0100
50: #define EOF 0040000
51: #define WL 04
52:
53: #define SSEEK 1
54: #define SIO 2
55: #define SCOM 3
56:
57: #define T_WRITTEN 1
58:
59: tmopen(dev, flag)
60: {
61: register unit, ds;
62:
63: unit = minor(dev) & 0177;
64: if (t_openf[unit]) {
65: u.u_error = ENXIO;
66: return;
67: }
68: t_blkno[unit] = 0;
69: t_nxrec[unit] = 65535;
70: t_flags[unit] = 0;
71:
72: tmtab.b_flags |= B_TAPE;
73: ds = tcommand(dev, NOP);
74: if ((ds&TUR)==0) {
75: printf("mt%d off line\n",unit);
76: u.u_error = ENXIO;
77: }
78: if (flag && ds&WL) {
79: printf("mt%d needs write ring\n",unit);
80: u.u_error = ENXIO;
81: }
82: if (u.u_error==0)
83: t_openf[unit]++;
84: }
85:
86: tmclose(dev, flag)
87: dev_t dev;
88: int flag;
89: {
90:
91: if ( flag == FWRITE ||
92: ((flag&FWRITE) && (t_flags[minor(dev)&0177]&T_WRITTEN))) {
93: tcommand(dev, WEOF);
94: tcommand(dev, WEOF);
95: tcommand(dev, SREV);
96: }
97: if ((minor(dev)&0200) == 0)
98: tcommand(dev, REW);
99: t_openf[minor(dev)&077] = 0;
100: }
101:
102: tcommand(dev, com)
103: {
104: register struct buf *bp;
105:
106: bp = &ctmbuf;
107: spl5();
108: while (bp->b_flags&B_BUSY) {
109: bp->b_flags |= B_WANTED;
110: sleep((caddr_t)bp, PRIBIO);
111: }
112: bp->b_flags = B_BUSY|B_READ;
113: spl0();
114: bp->b_dev = dev;
115: bp->b_resid = com;
116: bp->b_blkno = 0;
117: tmstrategy(bp);
118: iowait(bp);
119: if (bp->b_flags&B_WANTED)
120: wakeup((caddr_t)bp);
121: bp->b_flags = 0;
122: return(bp->b_resid);
123: }
124:
125: tmstrategy(bp)
126: register struct buf *bp;
127: {
128: register daddr_t *p;
129:
130: if(bp->b_flags&B_PHYS)
131: mapalloc(bp);
132: if (bp != &ctmbuf) {
133: p = &t_nxrec[minor(bp->b_dev)&0177];
134: if (*p <= bp->b_blkno) {
135: if (*p < bp->b_blkno) {
136: bp->b_flags |= B_ERROR;
137: iodone(bp);
138: return;
139: }
140: if (bp->b_flags&B_READ) {
141: clrbuf(bp);
142: bp->b_resid = 0;
143: iodone(bp);
144: return;
145: }
146: }
147: if ((bp->b_flags&B_READ) == 0) {
148: t_flags[minor(bp->b_dev)&0177] |= T_WRITTEN;
149: *p = bp->b_blkno+1;
150: }
151: }
152: bp->av_forw = 0;
153: spl5();
154: if (tmtab.b_actf == NULL)
155: tmtab.b_actf = bp;
156: else
157: tmtab.b_actl->av_forw = bp;
158: tmtab.b_actl = bp;
159: if (tmtab.b_active == NULL)
160: tmstart();
161: spl0();
162: }
163:
164: tmstart()
165: {
166: register struct buf *bp;
167: register int com;
168: int unit;
169: register daddr_t *blkno;
170:
171: loop:
172: if ((bp = tmtab.b_actf) == 0)
173: return;
174: unit = minor(bp->b_dev)&0177;
175: blkno = &t_blkno[unit];
176: if (t_openf[unit] < 0 || (TMADDR->tmcs & CRDY) == NULL) {
177: bp->b_flags |= B_ERROR;
178: goto next;
179: }
180: if (bp == &ctmbuf) {
181: if (bp->b_resid == NOP) {
182: bp->b_resid = TMADDR->tmer;
183: goto next;
184: }
185: tmtab.b_active = SCOM;
186: TMADDR->tmcs = DENS|bp->b_resid|GO| (unit<<8) | IENABLE;
187: return;
188: }
189: com = (unit<<8) | ((bp->b_xmem & 03) << 4) | IENABLE|DENS;
190: if (*blkno != bp->b_blkno) {
191: tmtab.b_active = SSEEK;
192: if (*blkno < bp->b_blkno) {
193: com |= SFORW|GO;
194: TMADDR->tmbc = *blkno - bp->b_blkno;
195: } else {
196: if (bp->b_blkno == 0)
197: com |= REW|GO;
198: else {
199: com |= SREV|GO;
200: TMADDR->tmbc = bp->b_blkno - *blkno;
201: }
202: }
203: TMADDR->tmcs = com;
204: return;
205: }
206: tmtab.b_active = SIO;
207: TMADDR->tmbc = -bp->b_bcount;
208: TMADDR->tmba = bp->b_un.b_addr;
209: TMADDR->tmcs = com | ((bp->b_flags&B_READ)? RCOM|GO:
210: ((tmtab.b_errcnt)? WIRG|GO: WCOM|GO));
211: return;
212:
213: next:
214: tmtab.b_actf = bp->av_forw;
215: iodone(bp);
216: goto loop;
217: }
218:
219: tmintr()
220: {
221: register struct buf *bp;
222: register int unit;
223: int state;
224:
225: if ((bp = tmtab.b_actf) == NULL)
226: return;
227: unit = minor(bp->b_dev)&0177;
228: state = tmtab.b_active;
229: tmtab.b_active = 0;
230: if (TMADDR->tmcs < 0) { /* error bit */
231: while(TMADDR->tmrd & GAPSD) ; /* wait for gap shutdown */
232: if (TMADDR->tmer&EOF) {
233: t_nxrec[unit] = bp->b_blkno;
234: state = SCOM;
235: TMADDR->tmbc = -bp->b_bcount;
236: goto out;
237: }
238: if ((TMADDR->tmer&HARD) == 0 && TMADDR->tmer&RLE) {
239: state = SIO;
240: goto out;
241: }
242: if ((TMADDR->tmer&(HARD|EOF)) == NULL && state==SIO) {
243: if (++tmtab.b_errcnt < 2) {
244: t_blkno[unit]++;
245: tmtab.b_active = 0;
246: tmstart();
247: return;
248: }
249: } else
250: if (t_openf[unit]>0 && bp!=&rtmbuf &&
251: (TMADDR->tmer&EOF)==0 ) {
252: t_openf[unit] = -1;
253: deverror(bp, TMADDR->tmer, 0);
254: }
255: bp->b_flags |= B_ERROR;
256: state = SIO;
257: }
258: out:
259: switch ( state ) {
260: case SIO:
261: t_blkno[unit] += (bp->b_bcount>>BSHIFT);
262: case SCOM:
263: tmtab.b_errcnt = 0;
264: tmtab.b_actf = bp->av_forw;
265: bp->b_resid = -TMADDR->tmbc;
266: iodone(bp);
267: break;
268: case SSEEK:
269: t_blkno[unit] = bp->b_blkno;
270: break;
271: default:
272: return;
273: }
274: tmstart();
275: }
276:
277: tmread(dev)
278: {
279: tmphys(dev);
280: physio(tmstrategy, &rtmbuf, dev, B_READ);
281: }
282:
283: tmwrite(dev)
284: {
285: tmphys(dev);
286: physio(tmstrategy, &rtmbuf, dev, B_WRITE);
287: }
288:
289: tmphys(dev)
290: {
291: register unit;
292: daddr_t a;
293:
294: unit = minor(dev) & 0177;
295: if(unit < 8) {
296: a = u.u_offset >> 9;
297: t_blkno[unit] = a;
298: t_nxrec[unit] = a+1;
299: }
300: }
Defined functions
Defined variables
tmtab
defined in line
23; used 19 times
Defined struct's
Defined macros
CRDY
defined in line
45; used 1 times
DENS
defined in line
43; used 2 times
EOF
defined in line
50; used 3 times
GAPSD
defined in line
46; used 1 times
GO
defined in line
34; used 7 times
HARD
defined in line
48; used 2 times
NOP
defined in line
38; used 2 times
RCOM
defined in line
35; used 1 times
REW
defined in line
42; used 2 times
RLE
defined in line
49; used 1 times
SCOM
defined in line
55; used 2 times
SFORW
defined in line
39; used 1 times
SIO
defined in line
54; used 4 times
SREV
defined in line
40; used 2 times
SSEEK
defined in line
53; used 1 times
TMADDR
defined in line
32; used 19 times
TUR
defined in line
47; used 1 times
WCOM
defined in line
36; used 1 times
WEOF
defined in line
37; used 2 times
WIRG
defined in line
41; used 1 times
WL
defined in line
51; used 1 times