|
|
1.1 root 1: /* uba.c 4.42 82/03/31 */
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/vm.h"
10: #include "../h/ubareg.h"
11: #include "../h/ubavar.h"
12: #include "../h/dir.h"
13: #include "../h/user.h"
14: #include "../h/proc.h"
15: #include "../h/conf.h"
16: #include "../h/mtpr.h"
17: #include "../h/nexus.h"
18: #include "../h/dk.h"
19: #include "../h/trace.h"
20:
21: #if VAX780
22: char ubasr_bits[] = UBASR_BITS;
23: #endif
24:
25: /*
26: * Do transfer on device argument. The controller
27: * and uba involved are implied by the device.
28: * We queue for resource wait in the uba code if necessary.
29: * We return 1 if the transfer was started, 0 if it was not.
30: * If you call this routine with the head of the queue for a
31: * UBA, it will automatically remove the device from the UBA
32: * queue before it returns. If some other device is given
33: * as argument, it will be added to the request queue if the
34: * request cannot be started immediately. This means that
35: * passing a device which is on the queue but not at the head
36: * of the request queue is likely to be a disaster.
37: */
38: ubago(ui)
39: register struct uba_device *ui;
40: {
41: register struct uba_ctlr *um = ui->ui_mi;
42: register struct uba_hd *uh;
43: register int s, unit;
44:
45: uh = &uba_hd[um->um_ubanum];
46: s = spl6();
47: if (um->um_driver->ud_xclu && uh->uh_users > 0 || uh->uh_xclu)
48: goto rwait;
49: /* if(uh->uh_users < 0)
50: printf ("(1) uh_users = %d\n", uh->uh_users); */
51: if(um->um_tab.b_actf == NULL) {
52: panic("null ptr in ubago\n");
53: splx(s);
54: return;
55: }
56: um->um_ubinfo = ubasetup(um->um_ubanum, um->um_tab.b_actf->b_actf,
57: UBA_NEEDBDP|UBA_CANTWAIT);
58: if (um->um_ubinfo == 0)
59: goto rwait;
60: uh->uh_users++;
61: trace(TR_BDPOFF, -1, uh->uh_users); /* overloaded lazy */
62: if (um->um_driver->ud_xclu)
63: uh->uh_xclu = 1;
64: splx(s);
65: if (ui->ui_dk >= 0) {
66: unit = ui->ui_dk;
67: dk_busy |= 1<<unit;
68: dk_xfer[unit]++;
69: dk_wds[unit] += um->um_tab.b_actf->b_actf->b_bcount>>6;
70: }
71: if (uh->uh_actf == ui)
72: uh->uh_actf = ui->ui_forw;
73: /* if(uh->uh_users <= 0)
74: printf ("(2) uh_users = %d\n", uh->uh_users); */
75: (*um->um_driver->ud_dgo)(um);
76: return (1);
77: rwait:
78: trace(TR_BDPOFF, -3, uh->uh_users);
79: if (uh->uh_actf != ui) {
80: ui->ui_forw = NULL;
81: if (uh->uh_actf == NULL)
82: uh->uh_actf = ui;
83: else
84: uh->uh_actl->ui_forw = ui;
85: uh->uh_actl = ui;
86: }
87: splx(s);
88: return (0);
89: }
90:
91: ubadone(um)
92: register struct uba_ctlr *um;
93: {
94: register struct uba_hd *uh = &uba_hd[um->um_ubanum];
95:
96: if (um->um_driver->ud_xclu)
97: uh->uh_xclu = 0;
98: uh->uh_users--;
99: trace(TR_BDPOFF, -2, uh->uh_users); /* overloaded lazy */
100: /* if(uh->uh_users < 0)
101: printf ("(3) uh_users = %d\n", uh->uh_users); */
102: ubarelse(um->um_ubanum, &um->um_ubinfo);
103: }
104:
105: /*
106: * Allocate and setup UBA map registers, and bdp's
107: * Flags says whether bdp is needed, whether the caller can't
108: * wait (e.g. if the caller is at interrupt level).
109: *
110: * Return value:
111: * Bits 0-8 Byte offset
112: * Bits 9-17 Start map reg. no.
113: * Bits 18-27 No. mapping reg's
114: * Bits 28-31 BDP no.
115: */
116: ubasetup(uban, bp, flags)
117: struct buf *bp;
118: {
119: register struct uba_hd *uh = &uba_hd[uban];
120: register int temp, i;
121: int npf, reg, bdp;
122: unsigned v;
123: register struct pte *pte, *io;
124: struct proc *rp;
125: int a, o, ubinfo;
126:
127: #if VAX7ZZ
128: if (cpu == VAX_7ZZ)
129: flags &= ~UBA_NEEDBDP;
130: #endif
131: v = btop(bp->b_un.b_addr);
132: o = (int)bp->b_un.b_addr & PGOFSET;
133: npf = btoc(bp->b_bcount + o) + 1;
134: a = spl6();
135: while ((reg = rmalloc(uh->uh_map, npf)) == 0) {
136: if (flags & UBA_CANTWAIT) {
137: splx(a);
138: return (0);
139: }
140: uh->uh_mrwant++;
141: sleep((caddr_t)uh->uh_map, PSWP);
142: }
143: bdp = 0;
144: if (flags & UBA_NEEDBDP) {
145: while ((bdp = ffs(uh->uh_bdpfree)) == 0) {
146: if (flags & UBA_CANTWAIT) {
147: rmfree(uh->uh_map, npf, reg);
148: splx(a);
149: return (0);
150: }
151: uh->uh_bdpwant++;
152: sleep((caddr_t)uh->uh_map, PSWP);
153: }
154: uh->uh_bdpfree &= ~(1 << (bdp-1));
155: } else if (flags & UBA_HAVEBDP)
156: bdp = (flags >> 28) & 0xf;
157: else if(flags & UBA_WANTBDP) {
158: bdp = ffs(uh->uh_bdpfree);
159: if(bdp)
160: uh->uh_bdpfree &= ~(1 << (bdp-1));
161: }
162: trace(TR_BDPON, uh->uh_bdpfree, flags);
163: splx(a);
164: reg--;
165: ubinfo = (bdp << 28) | (npf << 18) | (reg << 9) | o;
166: temp = (bdp << 21) | UBAMR_MRV;
167: if (bdp && (o & 01))
168: temp |= UBAMR_BO;
169: rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
170: if ((bp->b_flags & B_PHYS) == 0)
171: pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)];
172: else if (bp->b_flags & B_UAREA)
173: pte = &rp->p_addr[v];
174: else if (bp->b_flags & B_PAGET)
175: pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
176: else
177: pte = vtopte(rp, v);
178: io = &uh->uh_uba->uba_map[reg];
179: while (--npf != 0) {
180: if (pte->pg_pfnum == 0)
181: panic("uba zero uentry");
182: *(int *)io++ = pte++->pg_pfnum | temp;
183: }
184: *(int *)io++ = 0;
185: return (ubinfo);
186: }
187:
188: /*
189: * Non buffer setup interface... set up a buffer and call ubasetup.
190: */
191: uballoc(uban, addr, bcnt, flags)
192: int uban;
193: caddr_t addr;
194: int bcnt, flags;
195: {
196: struct buf ubabuf;
197:
198: ubabuf.b_un.b_addr = addr;
199: ubabuf.b_flags = B_BUSY;
200: ubabuf.b_bcount = bcnt;
201: /* that's all the fields ubasetup() needs */
202: return (ubasetup(uban, &ubabuf, flags));
203: }
204:
205: /*
206: * Release resources on uba uban, and then unblock resource waiters.
207: * The map register parameter is by value since we need to block
208: * against uba resets on 11/780's.
209: */
210: ubarelse(uban, amr)
211: int *amr;
212: {
213: register struct uba_hd *uh = &uba_hd[uban];
214: register int bdp, reg, npf, s;
215: int mr;
216:
217: /*
218: * Carefully see if we should release the space, since
219: * it may be released asynchronously at uba reset time.
220: */
221: s = spl6();
222: mr = *amr;
223: if (mr == 0) {
224: /*
225: * A ubareset() occurred before we got around
226: * to releasing the space... no need to bother.
227: */
228: splx(s);
229: return;
230: }
231: *amr = 0;
232: splx(s); /* let interrupts in, we're safe for a while */
233: bdp = (mr >> 28) & 0x0f;
234: if (bdp) {
235: switch (cpu) {
236: #if VAX780
237: case VAX_780:
238: uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;
239: break;
240: #endif
241: #if VAX750
242: case VAX_750:
243: uh->uh_uba->uba_dpr[bdp] |=
244: UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;
245: break;
246: #endif
247: }
248: uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */
249: trace(TR_BDPOFF, uh->uh_bdpfree, 0);
250: if (uh->uh_bdpwant) {
251: uh->uh_bdpwant = 0;
252: wakeup((caddr_t)uh->uh_map);
253: }
254: }
255: /*
256: * Put back the registers in the resource map.
257: * The map code must not be reentered, so we do this
258: * at high ipl.
259: */
260: npf = (mr >> 18) & 0x3ff;
261: reg = ((mr >> 9) & 0x1ff) + 1;
262: s = spl6();
263: rmfree(uh->uh_map, npf, reg);
264: splx(s);
265:
266: /*
267: * Wakeup sleepers for map registers,
268: * and also, if there are processes blocked in dgo(),
269: * give them a chance at the UNIBUS.
270: */
271: if (uh->uh_mrwant) {
272: uh->uh_mrwant = 0;
273: wakeup((caddr_t)uh->uh_map);
274: }
275: while (uh->uh_actf && ubago(uh->uh_actf))
276: ;
277: }
278:
279: #define PRGTIM 10 /* time to spin for bdp flush on comet */
280:
281: ubapurge(um)
282: register struct uba_ctlr *um;
283: {
284: register struct uba_hd *uh = um->um_hd;
285: register int bdp = (um->um_ubinfo >> 28) & 0x0f;
286: register int i;
287: register int *reg;
288:
289: switch (cpu) {
290: #if VAX780
291: case VAX_780:
292: uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;
293: break;
294: #endif
295: #if VAX750
296: case VAX_750:
297: reg = &uh->uh_uba->uba_dpr[bdp];
298: *reg |= UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;
299: for (i = PRGTIM; i > 0; i--)
300: if ((*reg & UBADPR_PURGE) == 0)
301: break;
302: if (i <= 0)
303: printf("uba%d bdp%d stuck\n", um->um_ubanum, bdp);
304: if (*reg & UBADPR_ERROR)
305: printf("uba%d bdp%d error %x\n", um->um_ubanum,
306: bdp, *reg);
307: break;
308: #endif
309: }
310: }
311:
312: /*
313: * Generate a reset on uba number uban. Then
314: * call each device in the character device table,
315: * giving it a chance to clean up so as to be able to continue.
316: */
317: ubareset(uban)
318: int uban;
319: {
320: register struct cdevsw *cdp;
321: register struct uba_hd *uh = &uba_hd[uban];
322: int s;
323:
324: s = spl6();
325: uh->uh_users = 0;
326: uh->uh_zvcnt = 0;
327: uh->uh_xclu = 0;
328: uh->uh_hangcnt = 0;
329: uh->uh_actf = uh->uh_actl = 0;
330: uh->uh_bdpwant = 0;
331: uh->uh_mrwant = 0;
332: wakeup((caddr_t)&uh->uh_bdpwant);
333: wakeup((caddr_t)&uh->uh_mrwant);
334: printf("uba%d: reset", uban);
335: ubainit(uh->uh_uba);
336: for (cdp = cdevsw; cdp->d_open; cdp++)
337: (*cdp->d_reset)(uban);
338: #ifdef INET
339: ifubareset(uban);
340: #endif
341: printf("\n");
342: splx(s);
343: }
344:
345: /*
346: * Init a uba. This is called with a pointer
347: * rather than a virtual address since it is called
348: * by code which runs with memory mapping disabled.
349: * In these cases we really don't need the interrupts
350: * enabled, but since we run with ipl high, we don't care
351: * if they are, they will never happen anyways.
352: */
353: ubainit(uba)
354: register struct uba_regs *uba;
355: {
356:
357: switch (cpu) {
358: #if VAX780
359: case VAX_780:
360: uba->uba_cr = UBACR_ADINIT;
361: uba->uba_cr = UBACR_IFS|UBACR_BRIE|UBACR_USEFIE|UBACR_SUEFIE;
362: while ((uba->uba_cnfgr & UBACNFGR_UBIC) == 0)
363: ;
364: break;
365: #endif
366: #if VAX750
367: case VAX_750:
368: #endif
369: #if VAX7ZZ
370: case VAX_7ZZ:
371: #endif
372: #if defined(VAX750) || defined(VAX7ZZ)
373: mtpr(IUR, 0);
374: /* give devices time to recover from power fail */
375: /* THIS IS PROBABLY UNNECESSARY */
376: DELAY(500000);
377: /* END PROBABLY UNNECESSARY */
378: break;
379: #endif
380: }
381: }
382:
383: #if VAX780
384: /*
385: * Check to make sure the UNIBUS adaptor is not hung,
386: * with an interrupt in the register to be presented,
387: * but not presenting it for an extended period (5 seconds).
388: */
389: unhang()
390: {
391: register int uban;
392:
393: for (uban = 0; uban < numuba; uban++) {
394: register struct uba_hd *uh = &uba_hd[uban];
395: register struct uba_regs *up = uh->uh_uba;
396:
397: if (up->uba_sr == 0)
398: return;
399: up->uba_sr = UBASR_CRD|UBASR_LEB;
400: uh->uh_hangcnt++;
401: if (uh->uh_hangcnt > 5*hz) {
402: uh->uh_hangcnt = 0;
403: printf("uba%d: hung\n", uban);
404: ubareset(uban);
405: }
406: }
407: }
408:
409: /*
410: * This is a timeout routine which decrements the ``i forgot to
411: * interrupt'' counts, on an 11/780. This prevents slowly growing
412: * counts from causing a UBA reset since we are interested only
413: * in hang situations.
414: */
415: ubawatch()
416: {
417: register struct uba_hd *uh;
418: register int uban;
419:
420: if (panicstr)
421: return;
422: for (uban = 0; uban < numuba; uban++) {
423: uh = &uba_hd[uban];
424: if (uh->uh_hangcnt)
425: uh->uh_hangcnt--;
426: }
427: }
428:
429: int ubawedgecnt = 10;
430: int ubacrazy = 500;
431: /*
432: * This routine is called by the locore code to
433: * process a UBA error on an 11/780. The arguments are passed
434: * on the stack, and value-result (through some trickery).
435: * In particular, the uvec argument is used for further
436: * uba processing so the result aspect of it is very important.
437: * It must not be declared register.
438: */
439: /*ARGSUSED*/
440: ubaerror(uban, uh, xx, uvec, uba)
441: register int uban;
442: register struct uba_hd *uh;
443: int uvec;
444: register struct uba_regs *uba;
445: {
446: register sr, s;
447:
448: if (uvec == 0) {
449: uh->uh_zvcnt++;
450: if (uh->uh_zvcnt > 250000) {
451: printf("uba%d: too many zero vectors\n");
452: ubareset(uban);
453: }
454: uvec = 0;
455: return;
456: }
457: if (uba->uba_cnfgr & NEX_CFGFLT) {
458: printf("uba%d: sbi fault sr=%b cnfgr=%b\n",
459: uban, uba->uba_sr, ubasr_bits,
460: uba->uba_cnfgr, NEXFLT_BITS);
461: ubareset(uban);
462: uvec = 0;
463: return;
464: }
465: sr = uba->uba_sr;
466: s = spl7();
467: printf("uba%d: uba error sr=%b fmer=%x fubar=%o\n",
468: uban, uba->uba_sr, ubasr_bits, uba->uba_fmer, 4*uba->uba_fubar);
469: splx(s);
470: uba->uba_sr = sr;
471: uvec &= UBABRRVR_DIV;
472: if (++uh->uh_errcnt % ubawedgecnt == 0) {
473: if (uh->uh_errcnt > ubacrazy)
474: panic("uba crazy");
475: printf("ERROR LIMIT ");
476: ubareset(uban);
477: uvec = 0;
478: return;
479: }
480: return;
481: }
482: #endif
483:
484: #if defined(CHAOS)
485: /*
486: * This routine allows remapping of previously
487: * allocated UNIBUS bdp and map resources
488: * onto different memory addresses.
489: * It should only be used by routines which need
490: * small fixed length mappings for long periods of time
491: * (like the ARPANET ACC IMP interface).
492: * It only maps kernel addresses.
493: */
494: ubaremap(uban, ubinfo, addr)
495: int uban;
496: register unsigned ubinfo;
497: caddr_t addr;
498: {
499: register struct uba_hd *uh = &uba_hd[uban];
500: register struct pte *pte, *io;
501: register int temp, bdp;
502: int npf, o;
503:
504: o = (int)addr & PGOFSET;
505: bdp = (ubinfo >> 28) & 0xf;
506: npf = (ubinfo >> 18) & 0x3ff;
507: io = &uh->uh_uba->uba_map[(ubinfo >> 9) & 0x1ff];
508: temp = (bdp << 21) | UBAMR_MRV;
509:
510: /*
511: * If using buffered data path initiate purge
512: * of old data and set byte offset bit if next
513: * transfer will be from odd address.
514: */
515: if (bdp) {
516: switch (cpu) {
517: #if VAX780
518: case VAX_780:
519: uh->uh_uba->uba_dpr[bdp] |= UBADPR_BNE;
520: break;
521: #endif
522: #if VAX750
523: case VAX_750:
524: uh->uh_uba->uba_dpr[bdp] |=
525: UBADPR_PURGE|UBADPR_NXM|UBADPR_UCE;
526: break;
527: #endif
528: }
529: if (o & 1)
530: temp |= UBAMR_BO;
531: }
532:
533: /*
534: * Set up the map registers, leaving an invalid reg
535: * at the end to guard against wild unibus transfers.
536: */
537: pte = &Sysmap[btop(((int)addr)&0x7fffffff)];
538: while (--npf != 0)
539: *(int *)io++ = pte++->pg_pfnum | temp;
540: *(int *)io = 0;
541:
542: /*
543: * Return effective UNIBUS address.
544: */
545: return ((ubinfo & ~PGOFSET) | o);
546: }
547: #endif defined(CHAOS)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.