|
|
1.1 root 1: /* ht.c 3.5 7/29/80 */
2:
3: /*
4: * TJU16 tape driver
5: * IOCTRL calls added - Ken Birman
6: */
7:
8: #include "../ch/param.h"
9: #include "../ch/systm.h"
10: #include "../ch/buf.h"
11: #include "../ch/conf.h"
12: #include "../ch/dir.h"
13: #include "../ch/user.h"
14: #include "../ch/file.h"
15: #include "../ch/map.h"
16: #include "../ch/pte.h"
17: #include "../ch/mba.h"
18:
19: struct device
20: {
21: int htcs1;
22: int htds;
23: int hter;
24: int htmr;
25: int htas;
26: int htfc;
27: int htdt;
28: int htck;
29: int htsn;
30: int httc;
31: };
32:
33: struct buf httab;
34: struct buf rhtbuf;
35: struct buf chtbuf;
36:
37: #define NUNIT 1
38: #define BUNIT 2
39: #define INF 1000000
40:
41: char h_openf[NUNIT];
42: daddr_t h_blkno[NUNIT];
43: char h_flags[NUNIT];
44: daddr_t h_nxrec[NUNIT];
45:
46: #define HTMBA MBA1
47: #define HTMBANUM 1
48:
49: #define GO 01
50: #define WCOM 060
51: #define RCOM 070
52: #define NOP 0
53: #define WEOF 026
54: #define SFORW 030
55: #define SREV 032
56: #define ERASE 024
57: #define REW 06
58: #define DCLR 010
59: #define P800 01700 /* 800 + pdp11 mode */
60: #define P1600 02300 /* 1600 + pdp11 mode */
61: #define IENABLE 0100
62: #define RDY 0200
63: #define TM 04
64: #define DRY 0200
65: #define EOT 02000
66: #define CS 02000
67: #define COR 0100000
68: #define PES 040
69: #define WRL 04000
70: #define MOL 010000
71: #define ERR 040000
72: #define FCE 01000
73: #define TRE 040000
74: #define HARD 064023 /* UNS|OPI|NEF|FMT|RMR|ILR|ILF */
75:
76: #define SIO 1
77: #define SSFOR 2
78: #define SSREV 3
79: #define SRETRY 4
80: #define SCOM 5
81: #define SOK 6
82:
83: #define b_repcnt b_bcount /* Command repetition counter */
84: #define b_command b_resid /* Command to do */
85: #define b_status b_resid /* Status after a tcommand */
86:
87:
88: #define H_WRITTEN 1
89:
90: htopen(dev, flag)
91: {
92: register unit, ds;
93:
94: if ((mbaact&(1<<HTMBANUM)) == 0)
95: mbainit(HTMBANUM);
96: httab.b_flags |= B_TAPE;
97: unit = minor(dev) & 03;
98: if (unit >= NUNIT || h_openf[unit]) {
99: u.u_error = ENXIO;
100: return;
101: }
102: h_blkno[unit] = 0;
103: h_nxrec[unit] = INF;
104: h_flags[unit] = 0;
105: ds = hcommand(dev, NOP, 1);
106: if ((ds&MOL)==0 || (flag && (ds&WRL)))
107: u.u_error = ENXIO;
108: if (u.u_error==0)
109: h_openf[unit]++;
110: }
111:
112: htclose(dev, flag)
113: {
114: register int unit;
115:
116: unit = minor(dev) & 03;
117: if (flag == FWRITE || ((flag&FWRITE) && (h_flags[unit]&H_WRITTEN))) {
118: (void) hcommand(dev, WEOF, 2);
119: (void) hcommand(dev, SREV, 1);
120: }
121: if((minor(dev)&4) == 0) /* no 4 -> rewind */
122: (void) hcommand(dev, REW, 1);
123: h_openf[unit] = 0;
124: }
125:
126: hcommand(dev, com, cnt)
127: {
128: register struct buf *bp;
129:
130: bp = &chtbuf;
131: (void) spl5();
132: while(bp->b_flags&B_BUSY) {
133: bp->b_flags |= B_WANTED;
134: sleep((caddr_t)bp, PRIBIO);
135: }
136: (void) spl0();
137: bp->b_dev = dev;
138: bp->b_command = com;
139: bp->b_repcnt = -cnt;
140: bp->b_blkno = 0;
141: bp->b_flags = B_BUSY|B_READ;
142: htstrategy(bp);
143: iowait(bp);
144: if(bp->b_flags&B_WANTED)
145: wakeup((caddr_t)bp);
146: bp->b_flags = 0;
147: return(bp->b_status);
148: }
149:
150: htstrategy(bp)
151: register struct buf *bp;
152: {
153: register daddr_t *p;
154:
155: if(bp != &chtbuf) {
156: p = &h_nxrec[minor(bp->b_dev)&03];
157: if(dbtofsb(bp->b_blkno) > *p) {
158: bp->b_flags |= B_ERROR;
159: bp->b_error = ENXIO;
160: iodone(bp);
161: return;
162: }
163: if(dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) {
164: bp->b_resid = bp->b_bcount;
165: clrbuf(bp);
166: iodone(bp);
167: return;
168: }
169: if ((bp->b_flags&B_READ)==0) {
170: *p = dbtofsb(bp->b_blkno) + 1;
171: h_flags[minor(bp->b_dev)&03] |= H_WRITTEN;
172: }
173: }
174: bp->av_forw = NULL;
175: (void) spl5();
176: if (httab.b_actf == NULL)
177: httab.b_actf = bp;
178: else
179: httab.b_actl->av_forw = bp;
180: httab.b_actl = bp;
181: if (httab.b_active==0)
182: htstart();
183: (void) spl0();
184: }
185:
186: htstart()
187: {
188: register struct buf *bp;
189: register unit, den;
190: daddr_t blkno;
191: register struct device *htp = mbadev(HTMBA,0);
192:
193: loop:
194: if ((bp = httab.b_actf) == NULL)
195: return;
196: unit = minor(bp->b_dev);
197: den = P800 | (unit&03);
198: if(unit >= 8)
199: den = P1600 | (unit&03);
200: if((htp->httc&03777) != den)
201: htp->httc = den;
202: unit &= 03;
203: blkno = h_blkno[unit];
204: if (bp == &chtbuf) {
205: if (bp->b_command==NOP) {
206: bp->b_status = htp->htds & 0xffff;
207: goto next;
208: }
209: httab.b_active = SCOM;
210: if(bp->b_command == SREV || bp->b_command == SFORW)
211: htp->htfc = bp->b_repcnt;
212: else
213: htp->htfc = 0;
214: htp->htcs1 = bp->b_command|GO;
215: return;
216: }
217: if (h_openf[unit] < 0 || dbtofsb(bp->b_blkno) > h_nxrec[unit])
218: goto abort;
219: if (blkno == dbtofsb(bp->b_blkno)) {
220: httab.b_active = SIO;
221: htp->htfc = -bp->b_bcount;
222: mbastart(bp, (int *)htp);
223: } else {
224: if (blkno < dbtofsb(bp->b_blkno)) {
225: httab.b_active = SSFOR;
226: htp->htfc = blkno - dbtofsb(bp->b_blkno);
227: htp->htcs1 = SFORW|GO;
228: } else {
229: httab.b_active = SSREV;
230: htp->htfc = dbtofsb(bp->b_blkno) - blkno;
231: htp->htcs1 = SREV|GO;
232: }
233: }
234: return;
235:
236: abort:
237: bp->b_flags |= B_ERROR;
238:
239: next:
240: httab.b_actf = bp->av_forw;
241: iodone(bp);
242: goto loop;
243: }
244:
245: /*ARGSUSED*/
246: htintr(mbastat, as)
247: {
248: register struct buf *bp;
249: register int unit, state;
250: int err;
251: register struct device *htp = mbadev(HTMBA,0);
252:
253: if ((bp = httab.b_actf)==NULL)
254: return;
255: unit = minor(bp->b_dev) & 03;
256: state = httab.b_active;
257: httab.b_active = 0;
258: if (htp->htds&(ERR|EOT|TM) || mbastat & MBAEBITS) {
259: err = htp->hter & 0xffff;
260: if ((mbastat & MBAEBITS) || (err&HARD))
261: state = 0;
262: if (bp == &rhtbuf)
263: err &= ~FCE;
264: if ((bp->b_flags&B_READ) && (htp->htds&PES))
265: err &= ~(CS|COR);
266: if(htp->htds&EOT || (htp->htds&MOL)==0) {
267: if(h_openf[unit])
268: h_openf[unit] = -1;
269: }
270: else if(htp->htds&TM) {
271: htp->htfc = 0;
272: h_nxrec[unit] = dbtofsb(bp->b_blkno);
273: state = SOK;
274: }
275: else if(state && err == 0)
276: state = SOK;
277: if(httab.b_errcnt > 4)
278: deverror(bp, htp->hter, mbastat);
279: HTMBA->mba_cr &= ~MBAIE;
280: htp->htcs1 = DCLR|GO;
281: HTMBA->mba_cr |= MBAIE;
282: if (state==SIO && ++httab.b_errcnt < 10) {
283: httab.b_active = SRETRY;
284: h_blkno[unit]++;
285: htp->htfc = -1;
286: htp->htcs1 = SREV|GO;
287: return;
288: }
289: if (state!=SOK) {
290: bp->b_flags |= B_ERROR;
291: state = SIO;
292: }
293: } else if (htp->htcs1 < 0) { /* SC */
294: if(htp->htds & ERR) {
295: HTMBA->mba_cr &= ~MBAIE;
296: htp->htcs1 = DCLR|GO;
297: HTMBA->mba_cr |= MBAIE;
298: }
299: }
300: switch(state) {
301: case SIO:
302: case SOK:
303: h_blkno[unit]++;
304:
305: case SCOM:
306: if(bp == &chtbuf)
307: if(bp->b_command == SFORW || bp->b_command == SREV)
308: {
309: if(bp->b_command == REW)
310: h_blkno[unit] -= -bp->b_repcnt;
311: else
312: h_blkno[unit] += -bp->b_repcnt;
313: } else if(++bp->b_repcnt)
314: break;
315:
316: httab.b_errcnt = 0;
317: httab.b_actf = bp->av_forw;
318: bp->b_resid = - (htp->htfc & 0xffff);
319: if (bp->b_flags & B_READ)
320: bp->b_resid += bp->b_bcount;
321: iodone(bp);
322: break;
323:
324: case SRETRY:
325: if((bp->b_flags&B_READ)==0) {
326: httab.b_active = SSFOR;
327: htp->htcs1 = ERASE|GO;
328: return;
329: }
330:
331: case SSFOR:
332: case SSREV:
333: #define blk dbtofsb(bp->b_blkno)
334: if(htp->htds & TM) {
335: if(state == SSREV) {
336: h_nxrec[unit] = blk - (htp->htfc&0xffff);
337: h_blkno[unit] = h_nxrec[unit];
338: } else {
339: h_nxrec[unit] = blk + (htp->htfc&0xffff) - 1;
340: h_blkno[unit] = blk + (htp->htfc & 0xffff);
341: }
342: } else
343: h_blkno[unit] = blk;
344: break;
345:
346: default:
347: return;
348: }
349: htstart();
350: }
351:
352: htread(dev)
353: {
354: htphys(dev);
355: physio(htstrategy, &rhtbuf, dev, B_READ, minphys);
356: }
357:
358: htwrite(dev)
359: {
360: htphys(dev);
361: physio(htstrategy, &rhtbuf, dev, B_WRITE, minphys);
362: }
363:
364: htphys(dev)
365: {
366: register unit;
367: daddr_t a;
368:
369: unit = minor(dev) & 03;
370: if(unit < NUNIT) {
371: a = u.u_offset >> 9;
372: h_blkno[unit] = dbtofsb(a);
373: h_nxrec[unit] = dbtofsb(a)+1;
374: }
375: }
376:
377: # define NHTIOCTRL (sizeof htiolist)
378:
379: char htiolist[] =
380: {
381: SFORW, /* 0 = skip forward */
382: SREV, /* 1 = skip reverse */
383: WEOF, /* 2 = Write EOF */
384: REW, /* 3 = rewind */
385: 0, /* 4 = skip forward file */
386: 0 /* 5 = skip reverse file */
387: };
388:
389: htioctrl(dev, cmd, arg, flag)
390: register dev_t dev;
391: register int cmd, flag, arg;
392: {
393: register ioctr;
394:
395: if((unsigned)cmd >= NHTIOCTRL || arg <= 0)
396: u.u_error = ENXIO;
397: else
398: {
399: if(cmd > 3)
400: {
401: /* Skip forward/reverse file(s) */
402: cmd -= 3;
403: ioctr = arg;
404: arg = -1;
405: }
406: else
407: ioctr = 1;
408: do
409: (void) hcommand(dev, htiolist[cmd], arg);
410: while(--ioctr);
411: }
412: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.