xref: /csrg-svn/sys/vax/mba/ht.c (revision 420)
1*420Sbill /*	ht.c	3.5	07/29/80	*/
222Sbill 
322Sbill /*
422Sbill  * TJU16 tape driver
522Sbill  */
622Sbill 
722Sbill #include "../h/param.h"
822Sbill #include "../h/systm.h"
922Sbill #include "../h/buf.h"
1022Sbill #include "../h/conf.h"
1122Sbill #include "../h/dir.h"
1222Sbill #include "../h/file.h"
1322Sbill #include "../h/user.h"
1422Sbill #include "../h/map.h"
15*420Sbill #include "../h/pte.h"
1622Sbill #include "../h/mba.h"
1722Sbill 
1822Sbill struct	device
1922Sbill {
2022Sbill 	int	htcs1;
2122Sbill 	int	htds;
2222Sbill 	int	hter;
2322Sbill 	int	htmr;
2422Sbill 	int	htas;
2522Sbill 	int	htfc;
2622Sbill 	int	htdt;
2722Sbill 	int	htck;
2822Sbill 	int	htsn;
2922Sbill 	int	httc;
3022Sbill };
3122Sbill 
3222Sbill struct	buf	httab;
3322Sbill struct	buf	rhtbuf;
3422Sbill struct	buf	chtbuf;
3522Sbill 
3622Sbill #define	NUNIT	1
3722Sbill #define	BUNIT	2
3822Sbill #define	INF	1000000
3922Sbill 
4022Sbill char	h_openf[NUNIT];
4122Sbill daddr_t	h_blkno[NUNIT];
4222Sbill char	h_flags[NUNIT];
4322Sbill daddr_t	h_nxrec[NUNIT];
4422Sbill 
45*420Sbill #define	HTMBA		MBA1
46*420Sbill #define	HTMBANUM	1
4722Sbill 
4822Sbill #define	GO	01
4922Sbill #define	WCOM	060
5022Sbill #define	RCOM	070
5122Sbill #define	NOP	0
5222Sbill #define	WEOF	026
5322Sbill #define	SFORW	030
5422Sbill #define	SREV	032
5522Sbill #define	ERASE	024
5622Sbill #define	REW	06
5722Sbill #define	DCLR	010
5822Sbill #define	P800	01700		/* 800 + pdp11 mode */
5922Sbill #define	P1600	02300		/* 1600 + pdp11 mode */
6022Sbill #define	IENABLE	0100
6122Sbill #define	RDY	0200
6222Sbill #define	TM	04
6322Sbill #define	DRY	0200
6422Sbill #define	EOT	02000
6522Sbill #define	CS	02000
6622Sbill #define	COR	0100000
6722Sbill #define	PES	040
6822Sbill #define	WRL	04000
6922Sbill #define	MOL	010000
7022Sbill #define	ERR	040000
7122Sbill #define	FCE	01000
7222Sbill #define	TRE	040000
7322Sbill #define	HARD	064023	/* UNS|OPI|NEF|FMT|RMR|ILR|ILF */
7422Sbill 
7522Sbill #define	SIO	1
7622Sbill #define	SSFOR	2
7722Sbill #define	SSREV	3
7822Sbill #define	SRETRY	4
7922Sbill #define	SCOM	5
8022Sbill #define	SOK	6
8122Sbill 
8222Sbill #define	H_WRITTEN 1
8322Sbill 
8422Sbill htopen(dev, flag)
8522Sbill {
8622Sbill 	register unit, ds;
8722Sbill 
88*420Sbill 	if ((mbaact&(1<<HTMBANUM)) == 0)
89*420Sbill 		mbainit(HTMBANUM);
9022Sbill 	httab.b_flags |= B_TAPE;
9122Sbill 	unit = minor(dev) & 03;
9222Sbill 	if (unit >= NUNIT || h_openf[unit]) {
9322Sbill 		u.u_error = ENXIO;
9422Sbill 		return;
9522Sbill 	}
9622Sbill 	h_blkno[unit] = 0;
9722Sbill 	h_nxrec[unit] = INF;
9822Sbill 	h_flags[unit] = 0;
9922Sbill 	ds = hcommand(dev, NOP);
10022Sbill 	if ((ds&MOL)==0 || (flag && (ds&WRL)))
10122Sbill 		u.u_error = ENXIO;
10222Sbill 	if (u.u_error==0)
10322Sbill 		h_openf[unit]++;
10422Sbill }
10522Sbill 
10622Sbill htclose(dev, flag)
10722Sbill {
10822Sbill 	register int unit;
10922Sbill 
11022Sbill 	unit = minor(dev) & 03;
11122Sbill 	if (flag == FWRITE || ((flag&FWRITE) && (h_flags[unit]&H_WRITTEN))) {
112128Sbill 		(void) hcommand(dev, WEOF);
113128Sbill 		(void) hcommand(dev, WEOF);
114128Sbill 		(void) hcommand(dev, SREV);
11522Sbill 	}
11622Sbill 	if((minor(dev)&4) == 0) /* no 4 -> rewind */
117128Sbill 		(void) hcommand(dev, REW);
11822Sbill 	h_openf[unit] = 0;
11922Sbill }
12022Sbill 
12122Sbill hcommand(dev, com)
12222Sbill {
12322Sbill 	register struct buf *bp;
12422Sbill 
12522Sbill 	bp = &chtbuf;
126128Sbill 	(void) spl5();
12722Sbill 	while(bp->b_flags&B_BUSY) {
12822Sbill 		bp->b_flags |= B_WANTED;
12922Sbill 		sleep((caddr_t)bp, PRIBIO);
13022Sbill 	}
131128Sbill 	(void) spl0();
13222Sbill 	bp->b_dev = dev;
13322Sbill 	bp->b_resid = com;
13422Sbill 	bp->b_blkno = 0;
13522Sbill 	bp->b_flags = B_BUSY|B_READ;
13622Sbill 	htstrategy(bp);
13722Sbill 	iowait(bp);
13822Sbill 	if(bp->b_flags&B_WANTED)
13922Sbill 		wakeup((caddr_t)bp);
14022Sbill 	bp->b_flags = 0;
14122Sbill 	return(bp->b_resid);
14222Sbill }
14322Sbill 
14422Sbill htstrategy(bp)
14522Sbill register struct buf *bp;
14622Sbill {
14722Sbill 	register daddr_t *p;
14822Sbill 
14922Sbill 	if(bp != &chtbuf) {
15022Sbill 		p = &h_nxrec[minor(bp->b_dev)&03];
15122Sbill 		if(dbtofsb(bp->b_blkno) > *p) {
15222Sbill 			bp->b_flags |= B_ERROR;
15322Sbill 			bp->b_error = ENXIO;
15422Sbill 			iodone(bp);
15522Sbill 			return;
15622Sbill 		}
15722Sbill 		if(dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) {
15822Sbill 			bp->b_resid = bp->b_bcount;
15922Sbill 			clrbuf(bp);
16022Sbill 			iodone(bp);
16122Sbill 			return;
16222Sbill 		}
16322Sbill 		if ((bp->b_flags&B_READ)==0) {
16422Sbill 			*p = dbtofsb(bp->b_blkno) + 1;
16522Sbill 			h_flags[minor(bp->b_dev)&03] |=  H_WRITTEN;
16622Sbill 		}
16722Sbill 	}
16822Sbill 	bp->av_forw = NULL;
169128Sbill 	(void) spl5();
17022Sbill 	if (httab.b_actf == NULL)
17122Sbill 		httab.b_actf = bp;
17222Sbill 	else
17322Sbill 		httab.b_actl->av_forw = bp;
17422Sbill 	httab.b_actl = bp;
17522Sbill 	if (httab.b_active==0)
17622Sbill 		htstart();
177128Sbill 	(void) spl0();
17822Sbill }
17922Sbill 
18022Sbill htstart()
18122Sbill {
18222Sbill 	register struct buf *bp;
18322Sbill 	register unit, den;
18422Sbill 	daddr_t blkno;
185*420Sbill 	register struct device *htp = mbadev(HTMBA,0);
18622Sbill 
18722Sbill     loop:
18822Sbill 	if ((bp = httab.b_actf) == NULL)
18922Sbill 		return;
19022Sbill 	unit = minor(bp->b_dev);
19122Sbill 	den = P800 | (unit&03);
19222Sbill 	if(unit >= 8)
19322Sbill 		den = P1600 | (unit&03);
194*420Sbill 	if((htp->httc&03777) != den)
195*420Sbill 		htp->httc = den;
19622Sbill 	unit &= 03;
19722Sbill 	blkno = h_blkno[unit];
19822Sbill 	if (bp == &chtbuf) {
19922Sbill 		if (bp->b_resid==NOP) {
200*420Sbill 			bp->b_resid = htp->htds & 0xffff;
20122Sbill 			goto next;
20222Sbill 		}
20322Sbill 		httab.b_active = SCOM;
204*420Sbill 		htp->htfc = 0;
205*420Sbill 		htp->htcs1 = bp->b_resid|GO;
20622Sbill 		return;
20722Sbill 	}
20822Sbill 	if (h_openf[unit] < 0 || dbtofsb(bp->b_blkno) > h_nxrec[unit])
20922Sbill 		goto abort;
21022Sbill 	if (blkno == dbtofsb(bp->b_blkno)) {
21122Sbill 		httab.b_active = SIO;
212*420Sbill 		htp->htfc = -bp->b_bcount;
213*420Sbill 		mbastart(bp, (int *)htp);
21422Sbill 	} else {
21522Sbill 		if (blkno < dbtofsb(bp->b_blkno)) {
21622Sbill 			httab.b_active = SSFOR;
217*420Sbill 			htp->htfc = blkno - dbtofsb(bp->b_blkno);
218*420Sbill 			htp->htcs1 = SFORW|GO;
21922Sbill 		} else {
22022Sbill 			httab.b_active = SSREV;
221*420Sbill 			htp->htfc = dbtofsb(bp->b_blkno) - blkno;
222*420Sbill 			htp->htcs1 = SREV|GO;
22322Sbill 		}
22422Sbill 	}
22522Sbill 	return;
22622Sbill 
22722Sbill     abort:
22822Sbill 	bp->b_flags |= B_ERROR;
22922Sbill 
23022Sbill     next:
23122Sbill 	httab.b_actf = bp->av_forw;
23222Sbill 	iodone(bp);
23322Sbill 	goto loop;
23422Sbill }
23522Sbill 
23622Sbill /*ARGSUSED*/
23722Sbill htintr(mbastat, as)
23822Sbill {
23922Sbill 	register struct buf *bp;
24022Sbill 	register int unit, state;
24122Sbill 	int err;
242*420Sbill 	register struct device *htp = mbadev(HTMBA,0);
24322Sbill 
24422Sbill 	if ((bp = httab.b_actf)==NULL)
24522Sbill 		return;
24622Sbill 	unit = minor(bp->b_dev) & 03;
24722Sbill 	state = httab.b_active;
24822Sbill 	httab.b_active = 0;
249*420Sbill 	if (htp->htds&(ERR|EOT|TM) || mbastat & MBAEBITS) {
250*420Sbill 		err = htp->hter & 0xffff;
25122Sbill 		if ((mbastat & MBAEBITS) || (err&HARD))
25222Sbill 			state = 0;
25322Sbill 		if (bp == &rhtbuf)
25422Sbill 			err &= ~FCE;
255*420Sbill 		if ((bp->b_flags&B_READ) && (htp->htds&PES))
25622Sbill 			err &= ~(CS|COR);
257*420Sbill 		if(htp->htds&EOT || (htp->htds&MOL)==0) {
25822Sbill 			if(h_openf[unit])
25922Sbill 				h_openf[unit] = -1;
26022Sbill 		}
261*420Sbill 		else if(htp->htds&TM) {
262*420Sbill 			htp->htfc = 0;
26322Sbill 			h_nxrec[unit] = dbtofsb(bp->b_blkno);
26422Sbill 			state = SOK;
26522Sbill 		}
26622Sbill 		else if(state && err == 0)
26722Sbill 			state = SOK;
26822Sbill 		if(httab.b_errcnt > 4)
269*420Sbill 			deverror(bp, htp->hter, mbastat);
270*420Sbill 		HTMBA->mba_cr &= ~MBAIE;
271*420Sbill 		htp->htcs1 = DCLR|GO;
272*420Sbill 		HTMBA->mba_cr |= MBAIE;
27322Sbill 		if (state==SIO && ++httab.b_errcnt < 10) {
27422Sbill 			httab.b_active = SRETRY;
27522Sbill 			h_blkno[unit]++;
276*420Sbill 			htp->htfc = -1;
277*420Sbill 			htp->htcs1 = SREV|GO;
27822Sbill 			return;
27922Sbill 		}
28022Sbill 		if (state!=SOK) {
28122Sbill 			bp->b_flags |= B_ERROR;
28222Sbill 			state = SIO;
28322Sbill 		}
284*420Sbill 	} else if (htp->htcs1 < 0) {	/* SC */
285*420Sbill 		if(htp->htds & ERR) {
286*420Sbill 			HTMBA->mba_cr &= ~MBAIE;
287*420Sbill 			htp->htcs1 = DCLR|GO;
288*420Sbill 			HTMBA->mba_cr |= MBAIE;
28922Sbill 		}
29022Sbill 	}
29122Sbill 	switch(state) {
29222Sbill 	case SIO:
29322Sbill 	case SOK:
29422Sbill 		h_blkno[unit]++;
29522Sbill 
29622Sbill 	case SCOM:
29722Sbill 		httab.b_errcnt = 0;
29822Sbill 		httab.b_actf = bp->av_forw;
299*420Sbill 		bp->b_resid = - (htp->htfc & 0xffff);
30022Sbill 		if (bp->b_flags & B_READ)
30122Sbill 			bp->b_resid += bp->b_bcount;
30222Sbill 		iodone(bp);
30322Sbill 		break;
30422Sbill 
30522Sbill 	case SRETRY:
30622Sbill 		if((bp->b_flags&B_READ)==0) {
30722Sbill 			httab.b_active = SSFOR;
308*420Sbill 			htp->htcs1 = ERASE|GO;
30922Sbill 			return;
31022Sbill 		}
31122Sbill 
31222Sbill 	case SSFOR:
31322Sbill 	case SSREV:
314220Sbill #define blk dbtofsb(bp->b_blkno)
315*420Sbill 		if(htp->htds & TM) {
31622Sbill 			if(state == SSREV) {
317*420Sbill 				h_nxrec[unit] = blk - (htp->htfc&0xffff);
31822Sbill 				h_blkno[unit] = h_nxrec[unit];
31922Sbill 			} else {
320*420Sbill 				h_nxrec[unit] = blk + (htp->htfc&0xffff) - 1;
321*420Sbill 				h_blkno[unit] = blk + (htp->htfc & 0xffff);
32222Sbill 			}
32322Sbill 		} else
324220Sbill 			h_blkno[unit] = blk;
32522Sbill 		break;
32622Sbill 
32722Sbill 	default:
32822Sbill 		return;
32922Sbill 	}
33022Sbill 	htstart();
33122Sbill }
33222Sbill 
33322Sbill htread(dev)
33422Sbill {
33522Sbill 	htphys(dev);
33622Sbill 	physio(htstrategy, &rhtbuf, dev, B_READ, minphys);
33722Sbill }
33822Sbill 
33922Sbill htwrite(dev)
34022Sbill {
34122Sbill 	htphys(dev);
34222Sbill 	physio(htstrategy, &rhtbuf, dev, B_WRITE, minphys);
34322Sbill }
34422Sbill 
34522Sbill htphys(dev)
34622Sbill {
34722Sbill 	register unit;
34822Sbill 	daddr_t a;
34922Sbill 
35022Sbill 	unit = minor(dev) & 03;
35122Sbill 	if(unit < NUNIT) {
35222Sbill 		a = u.u_offset >> 9;
35322Sbill 		h_blkno[unit] = dbtofsb(a);
35422Sbill 		h_nxrec[unit] = dbtofsb(a)+1;
35522Sbill 	}
35622Sbill }
357