xref: /csrg-svn/sys/vax/uba/uba.c (revision 2395)
1 /*	uba.c	4.7	02/10/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 		uh->uh_uba->uba_dpr[bdp] |= UBA_BNE;
131 		uh->uh_bdpfree |= 1 << bdp;
132 		if (uh->uh_bdpwant) {
133 			uh->uh_bdpwant = 0;
134 			wakeup((caddr_t)uh->uh_map);
135 		}
136 	}
137 	npf = (mr >> 18) & 0x3ff;
138 	reg = ((mr >> 9) & 0x1ff) + 1;
139 	mfree(uh->uh_map, npf, reg);
140 	if (uh->uh_mrwant) {
141 		uh->uh_mrwant = 0;
142 		wakeup((caddr_t)uh->uh_map);
143 	}
144 	splx(a);
145 }
146 
147 #define	DELAY(N)	{ register int d; d = N; while (--d > 0); }
148 
149 ubareset(uban)
150 {
151 	struct uba_regs *up;
152 	register struct cdevsw *cdp;
153 	int s;
154 
155 	s = spl6();
156 	switch (cpu) {
157 #if VAX==780
158 	case VAX_780:
159 		printf("UBA RESET %d:", uban);
160 		ubainit(uba_hd[uban].uh_uba);
161 		break;
162 #endif
163 #if VAX==750
164 	case VAX_750:
165 		printf("UNIBUS INIT:");
166 		mtpr(IUR, 1);
167 		DELAY(100000);
168 		break;
169 #endif
170 	}
171 	for (cdp = cdevsw; cdp->d_open; cdp++)
172 		(*cdp->d_reset)(uban);
173 	printf("\n");
174 	splx(s);
175 }
176 
177 /* pointer rather than number so we can be called with virt and phys addrs */
178 ubainit(up)
179 	register struct uba_regs *up;
180 {
181 
182 	up->uba_cr = UBA_ADINIT;
183 	up->uba_cr = UBA_IFS|UBA_BRIE|UBA_USEFIE|UBA_SUEFIE;
184 	while ((up->uba_cnfgr & UBA_UBIC) == 0)
185 		;
186 }
187 
188 #if VAX780
189 unhang()
190 {
191 	register int uban;
192 
193 	for (uban = 0; uban < numuba; uban++) {
194 		register struct uba_hd *uh = &uba_hd[uban];
195 		register struct uba_regs *up = uh->uh_uba;
196 
197 		if (up->uba_sr == 0)
198 			return;
199 		uh->uh_hangcnt++;
200 		if (uh->uh_hangcnt > 5*HZ) {
201 			uh->uh_hangcnt = 0;
202 			printf("HANG ");
203 			ubareset(uban);
204 		}
205 	}
206 }
207 
208 /* timeout routine to decrement ``i forgot to interrupt counts */
209 /* this prevents the counts from growing slowly, which isn't interesting */
210 ubawatch()
211 {
212 	register struct uba_hd *uh;
213 	register int uban;
214 
215 	for (uban = 0; uban < numuba; uban++) {
216 		uh = &uba_hd[uban];
217 		if (uh->uh_hangcnt)
218 			uh->uh_hangcnt--;
219 	}
220 }
221 
222 /* called from locore.s; parameters here (i.e. uvec) are value-result! */
223 ubaerror(uban, uh, xx, uvec, uba)
224 	register int uban;
225 	register struct uba_hd *uh;
226 	int uvec;
227 	register struct uba_regs *uba;
228 {
229 	register sr, s;
230 
231 	if (uvec == 0) {
232 		uh->uh_zvcnt++;
233 		if (uh->uh_zvcnt > 250000) {
234 			printf("ZERO VECTOR ");
235 			ubareset(uban);
236 		}
237 		uvec = 0;
238 		return;
239 	}
240 	if (uba->uba_cnfgr & NEX_CFGFLT) {
241 		printf("UBA%d SBI FAULT sr %x cnfgr %x\n",
242 		    uban, uba->uba_sr, uba->uba_cnfgr);
243 		ubareset(uban);
244 		uvec = 0;
245 		return;
246 	}
247 	sr = uba->uba_sr;
248 	s = spl7();
249 	printf("UBA%d ERROR SR %x FMER %x FUBAR %o\n",
250 	    uba->uba_sr, uba->uba_fmer, uba->uba_fubar);
251 	splx(s);
252 	uba->uba_sr = sr;
253 	uvec &= UBA_DIV;
254 	return;
255 }
256 #endif
257