xref: /csrg-svn/sys/vax/uba/uba.c (revision 2423)
1 /*	uba.c	4.8	02/15/81	*/
2 
3 #include "../h/param.h"
4 #include "../h/systm.h"
5 #include "../h/cpu.h"
6 #include "../h/map.h"
7 #include "../h/pte.h"
8 #include "../h/buf.h"
9 #include "../h/uba.h"
10 #include "../h/dir.h"
11 #include "../h/user.h"
12 #include "../h/proc.h"
13 #include "../h/vm.h"
14 #include "../h/conf.h"
15 #include "../h/mtpr.h"
16 #include "../h/nexus.h"
17 
18 /*
19  * Allocate and setup UBA map registers, and bdp's
20  * Flags says whether bdp is needed, whether the caller can't
21  * wait (e.g. if the caller is at interrupt level).
22  *
23  * Return value (cruft):
24  *	Bits 0-8	Byte offset
25  *	Bits 9-17	Start map reg. no.
26  *	Bits 18-27	No. mapping reg's
27  *	Bits 28-31	BDP no.
28  */
29 ubasetup(uban, bp, flags)
30 	struct buf *bp;
31 {
32 	register struct uba_hd *uh = &uba_hd[uban];
33 	register int temp, i;
34 	int npf, reg, bdp;
35 	unsigned v;
36 	register struct pte *pte, *io;
37 	struct proc *rp;
38 	int a, o, ubinfo;
39 
40 	v = btop(bp->b_un.b_addr);
41 	o = (int)bp->b_un.b_addr & PGOFSET;
42 	npf = btoc(bp->b_bcount + o) + 1;
43 	a = spl6();
44 	while ((reg = malloc(uh->uh_map, npf)) == 0) {
45 		if (flags & UBA_CANTWAIT)
46 			return (0);
47 		uh->uh_mrwant++;
48 		sleep((caddr_t)uh->uh_map, PSWP);
49 	}
50 	reg--;
51 	bdp = 0;
52 	if (flags & UBA_NEEDBDP) {
53 		while ((bdp = ffs(uh->uh_bdpfree)) == 0) {
54 			if (flags & UBA_CANTWAIT) {
55 				mfree(uh->uh_map, npf, reg);
56 				return (0);
57 			}
58 			uh->uh_bdpwant++;
59 			sleep((caddr_t)uh->uh_map, PSWP);
60 		}
61 		uh->uh_bdpfree &= ~ (1<<bdp);
62 	}
63 	splx(a);
64 	ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o;
65 	io = &uh->uh_uba->uba_map[reg];
66 	temp = (bdp << 21) | UBA_MRV;
67 	rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
68 	if (bdp && (o & 01))
69 		temp |= UBA_BO;
70 	if (bp->b_flags & B_UAREA) {
71 		for (i = UPAGES - bp->b_bcount / NBPG; i < UPAGES; i++) {
72 			if (rp->p_addr[i].pg_pfnum == 0)
73 				panic("uba: zero upage");
74 			*(int *)io++ = rp->p_addr[i].pg_pfnum | temp;
75 		}
76 	} else if ((bp->b_flags & B_PHYS) == 0) {
77 		pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)];
78 		while (--npf != 0)
79 			*(int *)io++ = pte++->pg_pfnum | temp;
80 	} else {
81 		if (bp->b_flags & B_PAGET)
82 			pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
83 		else
84 			pte = vtopte(rp, v);
85 		while (--npf != 0) {
86 			if (pte->pg_pfnum == 0)
87 				panic("uba zero uentry");
88 			*(int *)io++ = pte++->pg_pfnum | temp;
89 		}
90 	}
91 	*(int *)io++ = 0;
92 	return (ubinfo);
93 }
94 
95 /*
96  * Non buffer unibus interface... set up a buffer and call ubasetup.
97  */
98 uballoc(uban, addr, bcnt, flags)
99 	caddr_t addr;
100 	unsigned short bcnt;
101 {
102 	struct buf ubabuf;
103 
104 	ubabuf.b_un.b_addr = addr;
105 	ubabuf.b_flags = B_BUSY;
106 	ubabuf.b_bcount = bcnt;
107 	/* that's all the fields ubasetup() needs */
108 	return (ubasetup(uban, &ubabuf, flags));
109 }
110 
111 /*
112  * Old ubafree(info) is now ubarelse(&info) to avoid races.
113  */
114 ubarelse(uban, amr)
115 	int *amr;
116 {
117 	register struct uba_hd *uh = &uba_hd[uban];
118 	register int bdp, reg, npf, a;
119 	int mr;
120 
121 	a = spl6();
122 	mr = *amr;
123 	if (mr == 0) {
124 		splx(a);
125 		return;
126 	}
127 	*amr = 0;
128 	bdp = (mr >> 28) & 0x0f;
129 	if (bdp) {
130 		switch (cpu)
131 		{
132 #if VAX780
133 		case VAX_780:
134 			uh->uh_uba->uba_dpr[bdp] |= UBA_BNE;
135 			break;
136 #endif
137 #if VAX750
138 		case VAX_750:
139 			uh->uh_uba->uba_dpr[bdp] |= UBA_PURGE|UBA_NXM|UBA_UCE;
140 			break;
141 #endif
142 		}
143 		uh->uh_bdpfree |= 1 << bdp;
144 		if (uh->uh_bdpwant) {
145 			uh->uh_bdpwant = 0;
146 			wakeup((caddr_t)uh->uh_map);
147 		}
148 	}
149 	npf = (mr >> 18) & 0x3ff;
150 	reg = ((mr >> 9) & 0x1ff) + 1;
151 	mfree(uh->uh_map, npf, reg);
152 	if (uh->uh_mrwant) {
153 		uh->uh_mrwant = 0;
154 		wakeup((caddr_t)uh->uh_map);
155 	}
156 	splx(a);
157 }
158 
159 #define	DELAY(N)	{ register int d; d = N; while (--d > 0); }
160 
161 ubareset(uban)
162 {
163 	register struct cdevsw *cdp;
164 	int s;
165 
166 	s = spl6();
167 	switch (cpu) {
168 #if VAX==780
169 	case VAX_780:
170 		printf("UBA RESET %d:", uban);
171 		ubainit(uba_hd[uban].uh_uba);
172 		break;
173 #endif
174 #if VAX==750
175 	case VAX_750:
176 		printf("UNIBUS INIT:");
177 		mtpr(IUR, 1);
178 		DELAY(100000);
179 		break;
180 #endif
181 	}
182 	for (cdp = cdevsw; cdp->d_open; cdp++)
183 		(*cdp->d_reset)(uban);
184 	printf("\n");
185 	splx(s);
186 }
187 
188 /* pointer rather than number so we can be called with virt and phys addrs */
189 ubainit(uba)
190 	register struct uba_regs *uba;
191 {
192 
193 	uba->uba_cr = UBA_ADINIT;
194 	uba->uba_cr = UBA_IFS|UBA_BRIE|UBA_USEFIE|UBA_SUEFIE;
195 	while ((uba->uba_cnfgr & UBA_UBIC) == 0)
196 		;
197 }
198 
199 #if VAX780
200 unhang()
201 {
202 	register int uban;
203 
204 	for (uban = 0; uban < numuba; uban++) {
205 		register struct uba_hd *uh = &uba_hd[uban];
206 		register struct uba_regs *up = uh->uh_uba;
207 
208 		if (up->uba_sr == 0)
209 			return;
210 		uh->uh_hangcnt++;
211 		if (uh->uh_hangcnt > 5*HZ) {
212 			uh->uh_hangcnt = 0;
213 			printf("HANG ");
214 			ubareset(uban);
215 		}
216 	}
217 }
218 
219 /* timeout routine to decrement ``i forgot to interrupt counts */
220 /* this prevents the counts from growing slowly, which isn't interesting */
221 ubawatch()
222 {
223 	register struct uba_hd *uh;
224 	register int uban;
225 
226 	for (uban = 0; uban < numuba; uban++) {
227 		uh = &uba_hd[uban];
228 		if (uh->uh_hangcnt)
229 			uh->uh_hangcnt--;
230 	}
231 }
232 
233 /* called from locore.s; parameters here (i.e. uvec) are value-result! */
234 /*ARGSUSED*/
235 ubaerror(uban, uh, xx, uvec, uba)
236 	register int uban;
237 	register struct uba_hd *uh;
238 	int uvec;
239 	register struct uba_regs *uba;
240 {
241 	register sr, s;
242 
243 	if (uvec == 0) {
244 		uh->uh_zvcnt++;
245 		if (uh->uh_zvcnt > 250000) {
246 			printf("ZERO VECTOR ");
247 			ubareset(uban);
248 		}
249 		uvec = 0;
250 		return;
251 	}
252 	if (uba->uba_cnfgr & NEX_CFGFLT) {
253 		printf("UBA%d SBI FAULT sr %x cnfgr %x\n",
254 		    uban, uba->uba_sr, uba->uba_cnfgr);
255 		ubareset(uban);
256 		uvec = 0;
257 		return;
258 	}
259 	sr = uba->uba_sr;
260 	s = spl7();
261 	printf("UBA%d ERROR SR %x FMER %x FUBAR %o\n",
262 	    uban, uba->uba_sr, uba->uba_fmer, uba->uba_fubar);
263 	splx(s);
264 	uba->uba_sr = sr;
265 	uvec &= UBA_DIV;
266 	return;
267 }
268 #endif
269