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