debugging code for NXM problem added
[unix-history] / usr / src / sys / vax / uba / uba.c
CommitLineData
ec28fe15 1/* uba.c 4.29 81/04/03 */
c14fd247
BJ
2
3#include "../h/param.h"
3f3a34c3
BJ
4#include "../h/systm.h"
5#include "../h/cpu.h"
c14fd247
BJ
6#include "../h/map.h"
7#include "../h/pte.h"
c14fd247 8#include "../h/buf.h"
b7333467 9#include "../h/vm.h"
5ab42896
BJ
10#include "../h/ubareg.h"
11#include "../h/ubavar.h"
c14fd247
BJ
12#include "../h/dir.h"
13#include "../h/user.h"
14#include "../h/proc.h"
2e74ef16 15#include "../h/conf.h"
868a6a95 16#include "../h/mtpr.h"
3f3a34c3 17#include "../h/nexus.h"
b7333467
BJ
18#include "../h/dk.h"
19
5af3f3f7
BJ
20#if VAX780
21char ubasr_bits[] = UBASR_BITS;
22#endif
23
b7333467
BJ
24/*
25 * Do transfer on device argument. The controller
26 * and uba involved are implied by the device.
27 * We queue for resource wait in the uba code if necessary.
28 * We return 1 if the transfer was started, 0 if it was not.
29 * If you call this routine with the head of the queue for a
30 * UBA, it will automatically remove the device from the UBA
31 * queue before it returns. If some other device is given
32 * as argument, it will be added to the request queue if the
33 * request cannot be started immediately. This means that
34 * passing a device which is on the queue but not at the head
35 * of the request queue is likely to be a disaster.
36 */
37ubago(ui)
5ab42896 38 register struct uba_device *ui;
b7333467 39{
5ab42896 40 register struct uba_ctlr *um = ui->ui_mi;
b7333467
BJ
41 register struct uba_hd *uh;
42 register int s, unit;
43
44 uh = &uba_hd[um->um_ubanum];
45 s = spl6();
28ca05a9 46 if (um->um_driver->ud_xclu && uh->uh_users > 0 || uh->uh_xclu)
0801d37f 47 goto rwait;
b7333467
BJ
48 um->um_ubinfo = ubasetup(um->um_ubanum, um->um_tab.b_actf->b_actf,
49 UBA_NEEDBDP|UBA_CANTWAIT);
0801d37f
BJ
50 if (um->um_ubinfo == 0)
51 goto rwait;
0801d37f 52 uh->uh_users++;
28ca05a9 53 if (um->um_driver->ud_xclu)
0801d37f 54 uh->uh_xclu = 1;
b7333467
BJ
55 splx(s);
56 if (ui->ui_dk >= 0) {
57 unit = ui->ui_dk;
58 dk_busy |= 1<<unit;
59 }
60 if (uh->uh_actf == ui)
61 uh->uh_actf = ui->ui_forw;
62 (*um->um_driver->ud_dgo)(um);
63 if (ui->ui_dk >= 0) {
64 dk_xfer[unit]++;
0ef92e61 65 dk_wds[unit] += um->um_tab.b_actf->b_actf->b_bcount>>6;
b7333467
BJ
66 }
67 return (1);
0801d37f
BJ
68rwait:
69 if (uh->uh_actf != ui) {
70 ui->ui_forw = NULL;
71 if (uh->uh_actf == NULL)
72 uh->uh_actf = ui;
73 else
74 uh->uh_actl->ui_forw = ui;
75 uh->uh_actl = ui;
76 }
77 splx(s);
78 return (0);
79}
80
81ubadone(um)
5ab42896 82 register struct uba_ctlr *um;
0801d37f
BJ
83{
84 register struct uba_hd *uh = &uba_hd[um->um_ubanum];
85
28ca05a9 86 if (um->um_driver->ud_xclu)
0801d37f
BJ
87 uh->uh_xclu = 0;
88 uh->uh_users--;
0801d37f 89 ubarelse(um->um_ubanum, &um->um_ubinfo);
b7333467 90}
c14fd247
BJ
91
92/*
3f3a34c3
BJ
93 * Allocate and setup UBA map registers, and bdp's
94 * Flags says whether bdp is needed, whether the caller can't
95 * wait (e.g. if the caller is at interrupt level).
c14fd247 96 *
b7333467 97 * Return value:
c14fd247
BJ
98 * Bits 0-8 Byte offset
99 * Bits 9-17 Start map reg. no.
100 * Bits 18-27 No. mapping reg's
101 * Bits 28-31 BDP no.
102 */
3f3a34c3
BJ
103ubasetup(uban, bp, flags)
104 struct buf *bp;
c14fd247 105{
3f3a34c3 106 register struct uba_hd *uh = &uba_hd[uban];
c14fd247
BJ
107 register int temp, i;
108 int npf, reg, bdp;
109 unsigned v;
110 register struct pte *pte, *io;
111 struct proc *rp;
112 int a, o, ubinfo;
113
a3812a04
BJ
114#if VAX730
115 if (cpu == VAX_730)
116 flags &= ~UBA_NEEDBDP;
117#endif
c14fd247
BJ
118 v = btop(bp->b_un.b_addr);
119 o = (int)bp->b_un.b_addr & PGOFSET;
120 npf = btoc(bp->b_bcount + o) + 1;
121 a = spl6();
c84ff1f9 122 while ((reg = rmalloc(uh->uh_map, npf)) == 0) {
3f3a34c3
BJ
123 if (flags & UBA_CANTWAIT)
124 return (0);
125 uh->uh_mrwant++;
126 sleep((caddr_t)uh->uh_map, PSWP);
c14fd247 127 }
c14fd247 128 bdp = 0;
3f3a34c3
BJ
129 if (flags & UBA_NEEDBDP) {
130 while ((bdp = ffs(uh->uh_bdpfree)) == 0) {
131 if (flags & UBA_CANTWAIT) {
c84ff1f9 132 rmfree(uh->uh_map, npf, reg);
3f3a34c3
BJ
133 return (0);
134 }
135 uh->uh_bdpwant++;
136 sleep((caddr_t)uh->uh_map, PSWP);
c14fd247 137 }
658110d5 138 uh->uh_bdpfree &= ~(1 << (bdp-1));
3f3a34c3 139 }
c14fd247 140 splx(a);
658110d5 141 reg--;
c14fd247 142 ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o;
3f3a34c3 143 io = &uh->uh_uba->uba_map[reg];
5ab42896 144 temp = (bdp << 21) | UBAMR_MRV;
c14fd247
BJ
145 rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
146 if (bdp && (o & 01))
5ab42896 147 temp |= UBAMR_BO;
c14fd247
BJ
148 if (bp->b_flags & B_UAREA) {
149 for (i = UPAGES - bp->b_bcount / NBPG; i < UPAGES; i++) {
150 if (rp->p_addr[i].pg_pfnum == 0)
151 panic("uba: zero upage");
152 *(int *)io++ = rp->p_addr[i].pg_pfnum | temp;
153 }
154 } else if ((bp->b_flags & B_PHYS) == 0) {
da1392b6 155 pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)];
c14fd247 156 while (--npf != 0)
da1392b6 157 *(int *)io++ = pte++->pg_pfnum | temp;
c14fd247
BJ
158 } else {
159 if (bp->b_flags & B_PAGET)
160 pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
161 else
162 pte = vtopte(rp, v);
163 while (--npf != 0) {
164 if (pte->pg_pfnum == 0)
165 panic("uba zero uentry");
166 *(int *)io++ = pte++->pg_pfnum | temp;
167 }
168 }
169 *(int *)io++ = 0;
170 return (ubinfo);
171}
172
c14fd247 173/*
b7333467 174 * Non buffer setup interface... set up a buffer and call ubasetup.
c14fd247 175 */
3f3a34c3 176uballoc(uban, addr, bcnt, flags)
a0eab615 177 int uban;
c14fd247 178 caddr_t addr;
a0eab615 179 int bcnt, flags;
c14fd247 180{
89e0f717 181 struct buf ubabuf;
c14fd247 182
c14fd247
BJ
183 ubabuf.b_un.b_addr = addr;
184 ubabuf.b_flags = B_BUSY;
185 ubabuf.b_bcount = bcnt;
89e0f717 186 /* that's all the fields ubasetup() needs */
3f3a34c3 187 return (ubasetup(uban, &ubabuf, flags));
c14fd247
BJ
188}
189
b28deaf8 190/*
b7333467
BJ
191 * Release resources on uba uban, and then unblock resource waiters.
192 * The map register parameter is by value since we need to block
193 * against uba resets on 11/780's.
b28deaf8 194 */
3f3a34c3 195ubarelse(uban, amr)
b28deaf8 196 int *amr;
c14fd247 197{
3f3a34c3 198 register struct uba_hd *uh = &uba_hd[uban];
b7333467 199 register int bdp, reg, npf, s;
b28deaf8 200 int mr;
c14fd247 201
b7333467
BJ
202 /*
203 * Carefully see if we should release the space, since
204 * it may be released asynchronously at uba reset time.
205 */
206 s = spl6();
b28deaf8
BJ
207 mr = *amr;
208 if (mr == 0) {
b7333467
BJ
209 /*
210 * A ubareset() occurred before we got around
211 * to releasing the space... no need to bother.
212 */
213 splx(s);
b28deaf8
BJ
214 return;
215 }
88149598 216 *amr = 0;
b7333467 217 splx(s); /* let interrupts in, we're safe for a while */
c14fd247
BJ
218 bdp = (mr >> 28) & 0x0f;
219 if (bdp) {
27bf6b55 220 switch (cpu) {
5aa9d5ea
RE
221#if VAX780
222 case VAX_780:
5ab42896 223 uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;
5aa9d5ea
RE
224 break;
225#endif
226#if VAX750
227 case VAX_750:
5ab42896
BJ
228 uh->uh_uba->uba_dpr[bdp] |=
229 UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;
5aa9d5ea
RE
230 break;
231#endif
232 }
b7333467 233 uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */
3f3a34c3
BJ
234 if (uh->uh_bdpwant) {
235 uh->uh_bdpwant = 0;
236 wakeup((caddr_t)uh->uh_map);
c14fd247
BJ
237 }
238 }
b7333467
BJ
239 /*
240 * Put back the registers in the resource map.
241 * The map code must not be reentered, so we do this
242 * at high ipl.
243 */
c14fd247
BJ
244 npf = (mr >> 18) & 0x3ff;
245 reg = ((mr >> 9) & 0x1ff) + 1;
b7333467 246 s = spl6();
c84ff1f9 247 rmfree(uh->uh_map, npf, reg);
b7333467
BJ
248 splx(s);
249
250 /*
251 * Wakeup sleepers for map registers,
252 * and also, if there are processes blocked in dgo(),
253 * give them a chance at the UNIBUS.
254 */
3f3a34c3
BJ
255 if (uh->uh_mrwant) {
256 uh->uh_mrwant = 0;
257 wakeup((caddr_t)uh->uh_map);
c14fd247 258 }
b7333467
BJ
259 while (uh->uh_actf && ubago(uh->uh_actf))
260 ;
c14fd247
BJ
261}
262
27bf6b55 263ubapurge(um)
5ab42896 264 register struct uba_ctlr *um;
27bf6b55
BJ
265{
266 register struct uba_hd *uh = um->um_hd;
267 register int bdp = (um->um_ubinfo >> 28) & 0x0f;
268
269 switch (cpu) {
270#if VAX780
271 case VAX_780:
5ab42896 272 uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;
27bf6b55
BJ
273 break;
274#endif
275#if VAX750
276 case VAX_750:
5ab42896 277 uh->uh_uba->uba_dpr[bdp] |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;
27bf6b55
BJ
278 break;
279#endif
280 }
281}
282
b7333467
BJ
283/*
284 * Generate a reset on uba number uban. Then
285 * call each device in the character device table,
286 * giving it a chance to clean up so as to be able to continue.
287 */
3f3a34c3 288ubareset(uban)
b7333467 289 int uban;
2e74ef16 290{
2e74ef16 291 register struct cdevsw *cdp;
a3cb8f60 292 register struct uba_hd *uh = &uba_hd[uban];
49c84d3f 293 int s;
2e74ef16 294
4ea0bfc4 295 s = spl6();
a3cb8f60
BJ
296 uh->uh_users = 0;
297 uh->uh_zvcnt = 0;
298 uh->uh_xclu = 0;
299 uh->uh_hangcnt = 0;
300 uh->uh_actf = uh->uh_actl = 0;
301 uh->uh_bdpwant = 0;
302 uh->uh_mrwant = 0;
303 wakeup((caddr_t)&uh->uh_bdpwant);
304 wakeup((caddr_t)&uh->uh_mrwant);
5ab42896
BJ
305 printf("uba%d: reset", uban);
306 ubainit(uh->uh_uba);
2e74ef16 307 for (cdp = cdevsw; cdp->d_open; cdp++)
3f3a34c3 308 (*cdp->d_reset)(uban);
2e74ef16 309 printf("\n");
4ea0bfc4 310 splx(s);
2e74ef16 311}
3f3a34c3 312
b7333467
BJ
313/*
314 * Init a uba. This is called with a pointer
315 * rather than a virtual address since it is called
316 * by code which runs with memory mapping disabled.
317 * In these cases we really don't need the interrupts
318 * enabled, but since we run with ipl high, we don't care
319 * if they are, they will never happen anyways.
320 */
5aa9d5ea
RE
321ubainit(uba)
322 register struct uba_regs *uba;
3f3a34c3
BJ
323{
324
5ab42896
BJ
325 switch (cpu) {
326#if VAX780
d2f165e5 327 case VAX_780:
5ab42896
BJ
328 uba->uba_cr = UBACR_ADINIT;
329 uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE;
330 while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0)
331 ;
332 break;
333#endif
334#if VAX750
d2f165e5 335 case VAX_750:
a3812a04
BJ
336#endif
337#if VAX730
338 case VAX_730:
fed9edca
BJ
339#endif
340#if defined(VAX750) || defined(VAX730)
341 mtpr(IUR, 0);
342 /* give devices time to recover from power fail */
343/* THIS IS PROBABLY UNNECESSARY */
344 DELAY(500000);
345/* END PROBABLY UNNECESSARY */
5ab42896
BJ
346 break;
347#endif
348 }
3f3a34c3
BJ
349}
350
5ab42896 351#if VAX780
b7333467
BJ
352/*
353 * Check to make sure the UNIBUS adaptor is not hung,
354 * with an interrupt in the register to be presented,
355 * but not presenting it for an extended period (5 seconds).
356 */
3f3a34c3
BJ
357unhang()
358{
359 register int uban;
360
361 for (uban = 0; uban < numuba; uban++) {
362 register struct uba_hd *uh = &uba_hd[uban];
363 register struct uba_regs *up = uh->uh_uba;
364
365 if (up->uba_sr == 0)
366 return;
367 uh->uh_hangcnt++;
7780575a 368 if (uh->uh_hangcnt > 5*hz) {
3f3a34c3 369 uh->uh_hangcnt = 0;
5af3f3f7 370 printf("uba%d: hung\n", uban);
3f3a34c3
BJ
371 ubareset(uban);
372 }
373 }
374}
375
b7333467
BJ
376/*
377 * This is a timeout routine which decrements the ``i forgot to
378 * interrupt'' counts, on an 11/780. This prevents slowly growing
379 * counts from causing a UBA reset since we are interested only
380 * in hang situations.
381 */
3f3a34c3
BJ
382ubawatch()
383{
384 register struct uba_hd *uh;
385 register int uban;
386
c84ff1f9
BJ
387 if (panicstr)
388 return;
3f3a34c3
BJ
389 for (uban = 0; uban < numuba; uban++) {
390 uh = &uba_hd[uban];
391 if (uh->uh_hangcnt)
392 uh->uh_hangcnt--;
393 }
394}
395
b7333467
BJ
396/*
397 * This routine is called by the locore code to
398 * process a UBA error on an 11/780. The arguments are passed
399 * on the stack, and value-result (through some trickery).
400 * In particular, the uvec argument is used for further
401 * uba processing so the result aspect of it is very important.
402 * It must not be declared register.
403 */
5aa9d5ea 404/*ARGSUSED*/
3f3a34c3
BJ
405ubaerror(uban, uh, xx, uvec, uba)
406 register int uban;
407 register struct uba_hd *uh;
408 int uvec;
409 register struct uba_regs *uba;
410{
411 register sr, s;
412
413 if (uvec == 0) {
414 uh->uh_zvcnt++;
415 if (uh->uh_zvcnt > 250000) {
5af3f3f7 416 printf("uba%d: too many zero vectors\n");
3f3a34c3
BJ
417 ubareset(uban);
418 }
419 uvec = 0;
420 return;
421 }
422 if (uba->uba_cnfgr & NEX_CFGFLT) {
5af3f3f7
BJ
423 printf("uba%d: sbi fault sr=%b cnfgr=%b\n",
424 uban, uba->uba_sr, ubasr_bits,
d2f165e5 425 uba->uba_cnfgr, NEXFLT_BITS);
3f3a34c3
BJ
426 ubareset(uban);
427 uvec = 0;
428 return;
429 }
430 sr = uba->uba_sr;
431 s = spl7();
ec28fe15
BJ
432 printf("uba%d: uba error sr=%b fmer=%x fubar=%o\n",
433 uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar);
3f3a34c3
BJ
434 splx(s);
435 uba->uba_sr = sr;
5ab42896 436 uvec &= UBABRRVR_DIV;
3f3a34c3
BJ
437 return;
438}
439#endif