xref: /csrg-svn/sys/vax/uba/uba.c (revision 2423)
1*2423Skre /*	uba.c	4.8	02/15/81	*/
240Sbill 
340Sbill #include "../h/param.h"
42395Swnj #include "../h/systm.h"
52395Swnj #include "../h/cpu.h"
640Sbill #include "../h/map.h"
740Sbill #include "../h/pte.h"
82395Swnj #include "../h/buf.h"
940Sbill #include "../h/uba.h"
1040Sbill #include "../h/dir.h"
1140Sbill #include "../h/user.h"
1240Sbill #include "../h/proc.h"
1340Sbill #include "../h/vm.h"
14284Sbill #include "../h/conf.h"
151901Swnj #include "../h/mtpr.h"
162395Swnj #include "../h/nexus.h"
1740Sbill 
1840Sbill /*
192395Swnj  * Allocate and setup UBA map registers, and bdp's
202395Swnj  * Flags says whether bdp is needed, whether the caller can't
212395Swnj  * wait (e.g. if the caller is at interrupt level).
2240Sbill  *
232395Swnj  * Return value (cruft):
2440Sbill  *	Bits 0-8	Byte offset
2540Sbill  *	Bits 9-17	Start map reg. no.
2640Sbill  *	Bits 18-27	No. mapping reg's
2740Sbill  *	Bits 28-31	BDP no.
2840Sbill  */
292395Swnj ubasetup(uban, bp, flags)
302395Swnj 	struct buf *bp;
3140Sbill {
322395Swnj 	register struct uba_hd *uh = &uba_hd[uban];
3340Sbill 	register int temp, i;
3440Sbill 	int npf, reg, bdp;
3540Sbill 	unsigned v;
3640Sbill 	register struct pte *pte, *io;
3740Sbill 	struct proc *rp;
3840Sbill 	int a, o, ubinfo;
3940Sbill 
4040Sbill 	v = btop(bp->b_un.b_addr);
4140Sbill 	o = (int)bp->b_un.b_addr & PGOFSET;
4240Sbill 	npf = btoc(bp->b_bcount + o) + 1;
4340Sbill 	a = spl6();
442395Swnj 	while ((reg = malloc(uh->uh_map, npf)) == 0) {
452395Swnj 		if (flags & UBA_CANTWAIT)
462395Swnj 			return (0);
472395Swnj 		uh->uh_mrwant++;
482395Swnj 		sleep((caddr_t)uh->uh_map, PSWP);
4940Sbill 	}
5040Sbill 	reg--;
5140Sbill 	bdp = 0;
522395Swnj 	if (flags & UBA_NEEDBDP) {
532395Swnj 		while ((bdp = ffs(uh->uh_bdpfree)) == 0) {
542395Swnj 			if (flags & UBA_CANTWAIT) {
552395Swnj 				mfree(uh->uh_map, npf, reg);
562395Swnj 				return (0);
572395Swnj 			}
582395Swnj 			uh->uh_bdpwant++;
592395Swnj 			sleep((caddr_t)uh->uh_map, PSWP);
6040Sbill 		}
612395Swnj 		uh->uh_bdpfree &= ~ (1<<bdp);
622395Swnj 	}
6340Sbill 	splx(a);
6440Sbill 	ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o;
652395Swnj 	io = &uh->uh_uba->uba_map[reg];
662395Swnj 	temp = (bdp << 21) | UBA_MRV;
6740Sbill 	rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
6840Sbill 	if (bdp && (o & 01))
692395Swnj 		temp |= UBA_BO;
7040Sbill 	if (bp->b_flags & B_UAREA) {
7140Sbill 		for (i = UPAGES - bp->b_bcount / NBPG; i < UPAGES; i++) {
7240Sbill 			if (rp->p_addr[i].pg_pfnum == 0)
7340Sbill 				panic("uba: zero upage");
7440Sbill 			*(int *)io++ = rp->p_addr[i].pg_pfnum | temp;
7540Sbill 		}
7640Sbill 	} else if ((bp->b_flags & B_PHYS) == 0) {
77728Sbill 		pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)];
7840Sbill 		while (--npf != 0)
79728Sbill 			*(int *)io++ = pte++->pg_pfnum | temp;
8040Sbill 	} else {
8140Sbill 		if (bp->b_flags & B_PAGET)
8240Sbill 			pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
8340Sbill 		else
8440Sbill 			pte = vtopte(rp, v);
8540Sbill 		while (--npf != 0) {
8640Sbill 			if (pte->pg_pfnum == 0)
8740Sbill 				panic("uba zero uentry");
8840Sbill 			*(int *)io++ = pte++->pg_pfnum | temp;
8940Sbill 		}
9040Sbill 	}
9140Sbill 	*(int *)io++ = 0;
9240Sbill 	return (ubinfo);
9340Sbill }
9440Sbill 
9540Sbill /*
9640Sbill  * Non buffer unibus interface... set up a buffer and call ubasetup.
9740Sbill  */
982395Swnj uballoc(uban, addr, bcnt, flags)
9940Sbill 	caddr_t addr;
10040Sbill 	unsigned short bcnt;
10140Sbill {
102883Sbill 	struct buf ubabuf;
10340Sbill 
10440Sbill 	ubabuf.b_un.b_addr = addr;
10540Sbill 	ubabuf.b_flags = B_BUSY;
10640Sbill 	ubabuf.b_bcount = bcnt;
107883Sbill 	/* that's all the fields ubasetup() needs */
1082395Swnj 	return (ubasetup(uban, &ubabuf, flags));
10940Sbill }
11040Sbill 
1112053Swnj /*
1122053Swnj  * Old ubafree(info) is now ubarelse(&info) to avoid races.
1132053Swnj  */
1142395Swnj ubarelse(uban, amr)
1152053Swnj 	int *amr;
11640Sbill {
1172395Swnj 	register struct uba_hd *uh = &uba_hd[uban];
11840Sbill 	register int bdp, reg, npf, a;
1192053Swnj 	int mr;
12040Sbill 
12140Sbill 	a = spl6();
1222053Swnj 	mr = *amr;
1232053Swnj 	if (mr == 0) {
1242053Swnj 		splx(a);
1252053Swnj 		return;
1262053Swnj 	}
1272067Swnj 	*amr = 0;
12840Sbill 	bdp = (mr >> 28) & 0x0f;
12940Sbill 	if (bdp) {
130*2423Skre 		switch (cpu)
131*2423Skre 		{
132*2423Skre #if VAX780
133*2423Skre 		case VAX_780:
134*2423Skre 			uh->uh_uba->uba_dpr[bdp] |= UBA_BNE;
135*2423Skre 			break;
136*2423Skre #endif
137*2423Skre #if VAX750
138*2423Skre 		case VAX_750:
139*2423Skre 			uh->uh_uba->uba_dpr[bdp] |= UBA_PURGE|UBA_NXM|UBA_UCE;
140*2423Skre 			break;
141*2423Skre #endif
142*2423Skre 		}
1432395Swnj 		uh->uh_bdpfree |= 1 << bdp;
1442395Swnj 		if (uh->uh_bdpwant) {
1452395Swnj 			uh->uh_bdpwant = 0;
1462395Swnj 			wakeup((caddr_t)uh->uh_map);
14740Sbill 		}
14840Sbill 	}
14940Sbill 	npf = (mr >> 18) & 0x3ff;
15040Sbill 	reg = ((mr >> 9) & 0x1ff) + 1;
1512395Swnj 	mfree(uh->uh_map, npf, reg);
1522395Swnj 	if (uh->uh_mrwant) {
1532395Swnj 		uh->uh_mrwant = 0;
1542395Swnj 		wakeup((caddr_t)uh->uh_map);
15540Sbill 	}
15640Sbill 	splx(a);
15740Sbill }
15840Sbill 
159284Sbill #define	DELAY(N)	{ register int d; d = N; while (--d > 0); }
160284Sbill 
1612395Swnj ubareset(uban)
162284Sbill {
163284Sbill 	register struct cdevsw *cdp;
1641781Sbill 	int s;
165284Sbill 
166302Sbill 	s = spl6();
1672395Swnj 	switch (cpu) {
1681901Swnj #if VAX==780
1692395Swnj 	case VAX_780:
1702395Swnj 		printf("UBA RESET %d:", uban);
1712395Swnj 		ubainit(uba_hd[uban].uh_uba);
1722395Swnj 		break;
1731901Swnj #endif
1741901Swnj #if VAX==750
1752395Swnj 	case VAX_750:
1762395Swnj 		printf("UNIBUS INIT:");
1772395Swnj 		mtpr(IUR, 1);
1782395Swnj 		DELAY(100000);
1792395Swnj 		break;
1801901Swnj #endif
1812395Swnj 	}
182284Sbill 	for (cdp = cdevsw; cdp->d_open; cdp++)
1832395Swnj 		(*cdp->d_reset)(uban);
184284Sbill 	printf("\n");
185302Sbill 	splx(s);
186284Sbill }
1872395Swnj 
1882395Swnj /* pointer rather than number so we can be called with virt and phys addrs */
189*2423Skre ubainit(uba)
190*2423Skre 	register struct uba_regs *uba;
1912395Swnj {
1922395Swnj 
193*2423Skre 	uba->uba_cr = UBA_ADINIT;
194*2423Skre 	uba->uba_cr = UBA_IFS|UBA_BRIE|UBA_USEFIE|UBA_SUEFIE;
195*2423Skre 	while ((uba->uba_cnfgr & UBA_UBIC) == 0)
1962395Swnj 		;
1972395Swnj }
1982395Swnj 
1992395Swnj #if VAX780
2002395Swnj unhang()
2012395Swnj {
2022395Swnj 	register int uban;
2032395Swnj 
2042395Swnj 	for (uban = 0; uban < numuba; uban++) {
2052395Swnj 		register struct uba_hd *uh = &uba_hd[uban];
2062395Swnj 		register struct uba_regs *up = uh->uh_uba;
2072395Swnj 
2082395Swnj 		if (up->uba_sr == 0)
2092395Swnj 			return;
2102395Swnj 		uh->uh_hangcnt++;
2112395Swnj 		if (uh->uh_hangcnt > 5*HZ) {
2122395Swnj 			uh->uh_hangcnt = 0;
2132395Swnj 			printf("HANG ");
2142395Swnj 			ubareset(uban);
2152395Swnj 		}
2162395Swnj 	}
2172395Swnj }
2182395Swnj 
2192395Swnj /* timeout routine to decrement ``i forgot to interrupt counts */
2202395Swnj /* this prevents the counts from growing slowly, which isn't interesting */
2212395Swnj ubawatch()
2222395Swnj {
2232395Swnj 	register struct uba_hd *uh;
2242395Swnj 	register int uban;
2252395Swnj 
2262395Swnj 	for (uban = 0; uban < numuba; uban++) {
2272395Swnj 		uh = &uba_hd[uban];
2282395Swnj 		if (uh->uh_hangcnt)
2292395Swnj 			uh->uh_hangcnt--;
2302395Swnj 	}
2312395Swnj }
2322395Swnj 
2332395Swnj /* called from locore.s; parameters here (i.e. uvec) are value-result! */
234*2423Skre /*ARGSUSED*/
2352395Swnj ubaerror(uban, uh, xx, uvec, uba)
2362395Swnj 	register int uban;
2372395Swnj 	register struct uba_hd *uh;
2382395Swnj 	int uvec;
2392395Swnj 	register struct uba_regs *uba;
2402395Swnj {
2412395Swnj 	register sr, s;
2422395Swnj 
2432395Swnj 	if (uvec == 0) {
2442395Swnj 		uh->uh_zvcnt++;
2452395Swnj 		if (uh->uh_zvcnt > 250000) {
2462395Swnj 			printf("ZERO VECTOR ");
2472395Swnj 			ubareset(uban);
2482395Swnj 		}
2492395Swnj 		uvec = 0;
2502395Swnj 		return;
2512395Swnj 	}
2522395Swnj 	if (uba->uba_cnfgr & NEX_CFGFLT) {
2532395Swnj 		printf("UBA%d SBI FAULT sr %x cnfgr %x\n",
2542395Swnj 		    uban, uba->uba_sr, uba->uba_cnfgr);
2552395Swnj 		ubareset(uban);
2562395Swnj 		uvec = 0;
2572395Swnj 		return;
2582395Swnj 	}
2592395Swnj 	sr = uba->uba_sr;
2602395Swnj 	s = spl7();
2612395Swnj 	printf("UBA%d ERROR SR %x FMER %x FUBAR %o\n",
262*2423Skre 	    uban, uba->uba_sr, uba->uba_fmer, uba->uba_fubar);
2632395Swnj 	splx(s);
2642395Swnj 	uba->uba_sr = sr;
2652395Swnj 	uvec &= UBA_DIV;
2662395Swnj 	return;
2672395Swnj }
2682395Swnj #endif
269