xref: /csrg-svn/sys/vax/mba/ht.c (revision 1917)
1*1917Swnj /*	ht.c	4.3	12/17/80	*/
222Sbill 
31563Sbill #include "../conf/ht.h"
41563Sbill #if NHT > 0
522Sbill /*
622Sbill  * TJU16 tape driver
722Sbill  */
822Sbill 
922Sbill #include "../h/param.h"
1022Sbill #include "../h/systm.h"
1122Sbill #include "../h/buf.h"
1222Sbill #include "../h/conf.h"
1322Sbill #include "../h/dir.h"
1422Sbill #include "../h/file.h"
1522Sbill #include "../h/user.h"
1622Sbill #include "../h/map.h"
17420Sbill #include "../h/pte.h"
1822Sbill #include "../h/mba.h"
19*1917Swnj #include "../h/vm.h"
20*1917Swnj #include "../h/cmap.h"
2122Sbill 
2222Sbill struct	device
2322Sbill {
2422Sbill 	int	htcs1;
2522Sbill 	int	htds;
2622Sbill 	int	hter;
2722Sbill 	int	htmr;
2822Sbill 	int	htas;
2922Sbill 	int	htfc;
3022Sbill 	int	htdt;
3122Sbill 	int	htck;
3222Sbill 	int	htsn;
3322Sbill 	int	httc;
3422Sbill };
3522Sbill 
3622Sbill struct	buf	httab;
3722Sbill struct	buf	rhtbuf;
3822Sbill struct	buf	chtbuf;
3922Sbill 
4022Sbill #define	INF	1000000
4122Sbill 
421563Sbill char	h_openf[NHT];
431563Sbill daddr_t	h_blkno[NHT];
441563Sbill char	h_flags[NHT];
451563Sbill daddr_t	h_nxrec[NHT];
4622Sbill 
4722Sbill #define	GO	01
4822Sbill #define	WCOM	060
4922Sbill #define	RCOM	070
5022Sbill #define	NOP	0
5122Sbill #define	WEOF	026
5222Sbill #define	SFORW	030
5322Sbill #define	SREV	032
5422Sbill #define	ERASE	024
5522Sbill #define	REW	06
5622Sbill #define	DCLR	010
5722Sbill #define	P800	01700		/* 800 + pdp11 mode */
5822Sbill #define	P1600	02300		/* 1600 + pdp11 mode */
5922Sbill #define	IENABLE	0100
6022Sbill #define	RDY	0200
6122Sbill #define	TM	04
6222Sbill #define	DRY	0200
6322Sbill #define	EOT	02000
6422Sbill #define	CS	02000
6522Sbill #define	COR	0100000
6622Sbill #define	PES	040
6722Sbill #define	WRL	04000
6822Sbill #define	MOL	010000
6922Sbill #define	ERR	040000
7022Sbill #define	FCE	01000
7122Sbill #define	TRE	040000
7222Sbill #define	HARD	064023	/* UNS|OPI|NEF|FMT|RMR|ILR|ILF */
7322Sbill 
7422Sbill #define	SIO	1
7522Sbill #define	SSFOR	2
7622Sbill #define	SSREV	3
7722Sbill #define	SRETRY	4
7822Sbill #define	SCOM	5
7922Sbill #define	SOK	6
8022Sbill 
8122Sbill #define	H_WRITTEN 1
8222Sbill 
8322Sbill htopen(dev, flag)
8422Sbill {
8522Sbill 	register unit, ds;
8622Sbill 
87420Sbill 	if ((mbaact&(1<<HTMBANUM)) == 0)
88420Sbill 		mbainit(HTMBANUM);
8922Sbill 	httab.b_flags |= B_TAPE;
9022Sbill 	unit = minor(dev) & 03;
911563Sbill 	if (unit >= NHT || h_openf[unit]) {
9222Sbill 		u.u_error = ENXIO;
9322Sbill 		return;
9422Sbill 	}
9522Sbill 	h_blkno[unit] = 0;
9622Sbill 	h_nxrec[unit] = INF;
9722Sbill 	h_flags[unit] = 0;
9822Sbill 	ds = hcommand(dev, NOP);
9922Sbill 	if ((ds&MOL)==0 || (flag && (ds&WRL)))
10022Sbill 		u.u_error = ENXIO;
10122Sbill 	if (u.u_error==0)
10222Sbill 		h_openf[unit]++;
10322Sbill }
10422Sbill 
10522Sbill htclose(dev, flag)
10622Sbill {
10722Sbill 	register int unit;
10822Sbill 
10922Sbill 	unit = minor(dev) & 03;
11022Sbill 	if (flag == FWRITE || ((flag&FWRITE) && (h_flags[unit]&H_WRITTEN))) {
111128Sbill 		(void) hcommand(dev, WEOF);
112128Sbill 		(void) hcommand(dev, WEOF);
113128Sbill 		(void) hcommand(dev, SREV);
11422Sbill 	}
11522Sbill 	if((minor(dev)&4) == 0) /* no 4 -> rewind */
116128Sbill 		(void) hcommand(dev, REW);
11722Sbill 	h_openf[unit] = 0;
11822Sbill }
11922Sbill 
12022Sbill hcommand(dev, com)
12122Sbill {
12222Sbill 	register struct buf *bp;
12322Sbill 
12422Sbill 	bp = &chtbuf;
125128Sbill 	(void) spl5();
12622Sbill 	while(bp->b_flags&B_BUSY) {
12722Sbill 		bp->b_flags |= B_WANTED;
12822Sbill 		sleep((caddr_t)bp, PRIBIO);
12922Sbill 	}
130128Sbill 	(void) spl0();
13122Sbill 	bp->b_dev = dev;
13222Sbill 	bp->b_resid = com;
13322Sbill 	bp->b_blkno = 0;
13422Sbill 	bp->b_flags = B_BUSY|B_READ;
13522Sbill 	htstrategy(bp);
13622Sbill 	iowait(bp);
13722Sbill 	if(bp->b_flags&B_WANTED)
13822Sbill 		wakeup((caddr_t)bp);
13922Sbill 	bp->b_flags = 0;
14022Sbill 	return(bp->b_resid);
14122Sbill }
14222Sbill 
14322Sbill htstrategy(bp)
14422Sbill register struct buf *bp;
14522Sbill {
14622Sbill 	register daddr_t *p;
14722Sbill 
14822Sbill 	if(bp != &chtbuf) {
14922Sbill 		p = &h_nxrec[minor(bp->b_dev)&03];
15022Sbill 		if(dbtofsb(bp->b_blkno) > *p) {
15122Sbill 			bp->b_flags |= B_ERROR;
15222Sbill 			bp->b_error = ENXIO;
15322Sbill 			iodone(bp);
15422Sbill 			return;
15522Sbill 		}
15622Sbill 		if(dbtofsb(bp->b_blkno) == *p && bp->b_flags&B_READ) {
15722Sbill 			bp->b_resid = bp->b_bcount;
15822Sbill 			clrbuf(bp);
15922Sbill 			iodone(bp);
16022Sbill 			return;
16122Sbill 		}
16222Sbill 		if ((bp->b_flags&B_READ)==0) {
16322Sbill 			*p = dbtofsb(bp->b_blkno) + 1;
16422Sbill 			h_flags[minor(bp->b_dev)&03] |=  H_WRITTEN;
16522Sbill 		}
16622Sbill 	}
16722Sbill 	bp->av_forw = NULL;
168128Sbill 	(void) spl5();
16922Sbill 	if (httab.b_actf == NULL)
17022Sbill 		httab.b_actf = bp;
17122Sbill 	else
17222Sbill 		httab.b_actl->av_forw = bp;
17322Sbill 	httab.b_actl = bp;
17422Sbill 	if (httab.b_active==0)
17522Sbill 		htstart();
176128Sbill 	(void) spl0();
17722Sbill }
17822Sbill 
17922Sbill htstart()
18022Sbill {
18122Sbill 	register struct buf *bp;
18222Sbill 	register unit, den;
18322Sbill 	daddr_t blkno;
184420Sbill 	register struct device *htp = mbadev(HTMBA,0);
18522Sbill 
18622Sbill     loop:
18722Sbill 	if ((bp = httab.b_actf) == NULL)
18822Sbill 		return;
18922Sbill 	unit = minor(bp->b_dev);
19022Sbill 	den = P800 | (unit&03);
19122Sbill 	if(unit >= 8)
19222Sbill 		den = P1600 | (unit&03);
193420Sbill 	if((htp->httc&03777) != den)
194420Sbill 		htp->httc = den;
19522Sbill 	unit &= 03;
19622Sbill 	blkno = h_blkno[unit];
19722Sbill 	if (bp == &chtbuf) {
19822Sbill 		if (bp->b_resid==NOP) {
199420Sbill 			bp->b_resid = htp->htds & 0xffff;
20022Sbill 			goto next;
20122Sbill 		}
20222Sbill 		httab.b_active = SCOM;
203420Sbill 		htp->htfc = 0;
204420Sbill 		htp->htcs1 = bp->b_resid|GO;
20522Sbill 		return;
20622Sbill 	}
20722Sbill 	if (h_openf[unit] < 0 || dbtofsb(bp->b_blkno) > h_nxrec[unit])
20822Sbill 		goto abort;
20922Sbill 	if (blkno == dbtofsb(bp->b_blkno)) {
21022Sbill 		httab.b_active = SIO;
211420Sbill 		htp->htfc = -bp->b_bcount;
212420Sbill 		mbastart(bp, (int *)htp);
21322Sbill 	} else {
21422Sbill 		if (blkno < dbtofsb(bp->b_blkno)) {
21522Sbill 			httab.b_active = SSFOR;
216420Sbill 			htp->htfc = blkno - dbtofsb(bp->b_blkno);
217420Sbill 			htp->htcs1 = SFORW|GO;
21822Sbill 		} else {
21922Sbill 			httab.b_active = SSREV;
220420Sbill 			htp->htfc = dbtofsb(bp->b_blkno) - blkno;
221420Sbill 			htp->htcs1 = SREV|GO;
22222Sbill 		}
22322Sbill 	}
22422Sbill 	return;
22522Sbill 
22622Sbill     abort:
22722Sbill 	bp->b_flags |= B_ERROR;
22822Sbill 
22922Sbill     next:
23022Sbill 	httab.b_actf = bp->av_forw;
23122Sbill 	iodone(bp);
23222Sbill 	goto loop;
23322Sbill }
23422Sbill 
23522Sbill /*ARGSUSED*/
23622Sbill htintr(mbastat, as)
23722Sbill {
23822Sbill 	register struct buf *bp;
23922Sbill 	register int unit, state;
24022Sbill 	int err;
241420Sbill 	register struct device *htp = mbadev(HTMBA,0);
24222Sbill 
24322Sbill 	if ((bp = httab.b_actf)==NULL)
24422Sbill 		return;
24522Sbill 	unit = minor(bp->b_dev) & 03;
24622Sbill 	state = httab.b_active;
24722Sbill 	httab.b_active = 0;
248420Sbill 	if (htp->htds&(ERR|EOT|TM) || mbastat & MBAEBITS) {
249420Sbill 		err = htp->hter & 0xffff;
25022Sbill 		if ((mbastat & MBAEBITS) || (err&HARD))
25122Sbill 			state = 0;
25222Sbill 		if (bp == &rhtbuf)
25322Sbill 			err &= ~FCE;
254420Sbill 		if ((bp->b_flags&B_READ) && (htp->htds&PES))
25522Sbill 			err &= ~(CS|COR);
256420Sbill 		if(htp->htds&EOT || (htp->htds&MOL)==0) {
25722Sbill 			if(h_openf[unit])
25822Sbill 				h_openf[unit] = -1;
25922Sbill 		}
260420Sbill 		else if(htp->htds&TM) {
261420Sbill 			htp->htfc = 0;
26222Sbill 			h_nxrec[unit] = dbtofsb(bp->b_blkno);
26322Sbill 			state = SOK;
26422Sbill 		}
26522Sbill 		else if(state && err == 0)
26622Sbill 			state = SOK;
26722Sbill 		if(httab.b_errcnt > 4)
268420Sbill 			deverror(bp, htp->hter, mbastat);
269420Sbill 		HTMBA->mba_cr &= ~MBAIE;
270420Sbill 		htp->htcs1 = DCLR|GO;
271420Sbill 		HTMBA->mba_cr |= MBAIE;
27222Sbill 		if (state==SIO && ++httab.b_errcnt < 10) {
27322Sbill 			httab.b_active = SRETRY;
27422Sbill 			h_blkno[unit]++;
275420Sbill 			htp->htfc = -1;
276420Sbill 			htp->htcs1 = SREV|GO;
27722Sbill 			return;
27822Sbill 		}
27922Sbill 		if (state!=SOK) {
28022Sbill 			bp->b_flags |= B_ERROR;
28122Sbill 			state = SIO;
28222Sbill 		}
283420Sbill 	} else if (htp->htcs1 < 0) {	/* SC */
284420Sbill 		if(htp->htds & ERR) {
285420Sbill 			HTMBA->mba_cr &= ~MBAIE;
286420Sbill 			htp->htcs1 = DCLR|GO;
287420Sbill 			HTMBA->mba_cr |= MBAIE;
28822Sbill 		}
28922Sbill 	}
29022Sbill 	switch(state) {
29122Sbill 	case SIO:
29222Sbill 	case SOK:
29322Sbill 		h_blkno[unit]++;
29422Sbill 
29522Sbill 	case SCOM:
29622Sbill 		httab.b_errcnt = 0;
29722Sbill 		httab.b_actf = bp->av_forw;
298420Sbill 		bp->b_resid = - (htp->htfc & 0xffff);
29922Sbill 		if (bp->b_flags & B_READ)
30022Sbill 			bp->b_resid += bp->b_bcount;
30122Sbill 		iodone(bp);
30222Sbill 		break;
30322Sbill 
30422Sbill 	case SRETRY:
30522Sbill 		if((bp->b_flags&B_READ)==0) {
30622Sbill 			httab.b_active = SSFOR;
307420Sbill 			htp->htcs1 = ERASE|GO;
30822Sbill 			return;
30922Sbill 		}
31022Sbill 
31122Sbill 	case SSFOR:
31222Sbill 	case SSREV:
313220Sbill #define blk dbtofsb(bp->b_blkno)
314420Sbill 		if(htp->htds & TM) {
31522Sbill 			if(state == SSREV) {
316420Sbill 				h_nxrec[unit] = blk - (htp->htfc&0xffff);
31722Sbill 				h_blkno[unit] = h_nxrec[unit];
31822Sbill 			} else {
319420Sbill 				h_nxrec[unit] = blk + (htp->htfc&0xffff) - 1;
320420Sbill 				h_blkno[unit] = blk + (htp->htfc & 0xffff);
32122Sbill 			}
32222Sbill 		} else
323220Sbill 			h_blkno[unit] = blk;
32422Sbill 		break;
325*1917Swnj #undef blk
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;
3511563Sbill 	if(unit < NHT) {
35222Sbill 		a = u.u_offset >> 9;
35322Sbill 		h_blkno[unit] = dbtofsb(a);
35422Sbill 		h_nxrec[unit] = dbtofsb(a)+1;
35522Sbill 	}
35622Sbill }
357*1917Swnj 
358*1917Swnj #define	HTADDR	((struct device *)(HTPHYSMBA + 0x400))
359*1917Swnj #define	HTMAP ((struct pte *) (HTPHYSMBA + 0x800))
360*1917Swnj 
361*1917Swnj #define	DBSIZE	20
362*1917Swnj 
363*1917Swnj twall(start, num)
364*1917Swnj 	char *start;
365*1917Swnj 	int num;
366*1917Swnj {
367*1917Swnj 	int blk;
368*1917Swnj 
369*1917Swnj 	HTADDR->httc = P800;	/* set 800 bpi mode */
370*1917Swnj 	HTADDR->htcs1 = DCLR | GO;
371*1917Swnj 	while (num > 0) {
372*1917Swnj 		blk = num > DBSIZE ? DBSIZE : num;
373*1917Swnj 		twrite(start, blk);
374*1917Swnj 		start += blk*NBPG;
375*1917Swnj 		num -= blk;
376*1917Swnj 	}
377*1917Swnj }
378*1917Swnj 
379*1917Swnj twrite(buf, num)
380*1917Swnj char *buf;
381*1917Swnj {
382*1917Swnj 	register struct pte *hpte = HTMAP;
383*1917Swnj 	register int i;
384*1917Swnj 
385*1917Swnj 	twait();
386*1917Swnj 	HTADDR->htfc = -(num*NBPG);
387*1917Swnj 	for (i = 0; i < num; i++)
388*1917Swnj 		*(int *)hpte++ = (btop(buf)+i) | PG_V;
389*1917Swnj 	((struct mba_regs *)PHYSMBA1)->mba_sr = -1;
390*1917Swnj 	((struct mba_regs *)PHYSMBA1)->mba_bcr = -(num*NBPG);
391*1917Swnj 	((struct mba_regs *)PHYSMBA1)->mba_var = 0;
392*1917Swnj 	HTADDR->htcs1 = WCOM | GO;
393*1917Swnj }
394*1917Swnj 
395*1917Swnj twait()
396*1917Swnj {
397*1917Swnj 	register s;
398*1917Swnj 
399*1917Swnj 	do
400*1917Swnj 		s = HTADDR->htds;
401*1917Swnj 	while ((s & RDY) == 0);
402*1917Swnj }
403*1917Swnj 
404*1917Swnj rewind()
405*1917Swnj {
406*1917Swnj 
407*1917Swnj 	twait();
408*1917Swnj 	HTADDR->htcs1 = REW | GO;
409*1917Swnj }
410*1917Swnj 
411*1917Swnj teof()
412*1917Swnj {
413*1917Swnj 
414*1917Swnj 	twait();
415*1917Swnj 	HTADDR->htcs1 = WEOF | GO;
416*1917Swnj }
4171563Sbill #endif
418