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