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