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