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