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