|
|
1.1 root 1: /*
2: * stuff for dealing with bi nodes (io nexus) on nautilus
3: *
4: * iospace is an array of struct nexus (registers + window space),
5: * followed by three pages of special registers:
6: * NBIA0, NBIA1, and the memory controller
7: */
8:
9: #include "sys/param.h"
10: #include "sys/nexus.h"
11: #include "sys/biaddr.h"
12: #include "sys/biic.h"
13: #include "sys/pte.h"
14:
15: static int nexcnt;
16: char *iospace; /* array of struct nexus, plus some stuff */
17: struct nbia {
18: long csr0;
19: long csr1;
20: };
21: static struct nbia *nbia[2];
22: long *mcrcsr;
23:
24: static int nexreg(), nexwind(), biainit(), bibinit(), nbiavec();
25:
26: /*
27: * how much address space
28: * is needed for nexus space?
29: * needed when allocating system page table
30: * the fudge factor of 3: 2 pages for NBIAs, one for the memory controller
31: */
32:
33: mchiopsize()
34: {
35: register int i;
36:
37: for (i = 0; nextab[i].bus >= 0; i++)
38: ;
39: nexcnt = i;
40: return (i * sizeof(struct nexus) + 3 * NBPG);
41: }
42:
43: /*
44: * map appropriate parts of nexus space into kernel space
45: * called early on, before memory mapping is set up
46: * argument is the first relevant spt entry
47: */
48:
49: mchiopinit(pt)
50: struct pte *pt;
51: {
52: register long *p;
53: register int i, n;
54: register int b;
55:
56: p = (long *)pt;
57: for (i = 0; i < nexcnt; i++) {
58: b = nexreg(&nextab[i]);
59: for (n = 0; n < btoc(NXSIZE); n++)
60: if (b)
61: *p++ = PG_V|PG_KW|(b+n);
62: else
63: *p++ = 0;
64: b = nexwind(&nextab[i], 0);
65: for (n = 0; n < btoc(NXWSIZE); n++)
66: if (b)
67: *p++ = PG_V|PG_KW|(b+n);
68: else
69: *p++ = 0;
70: }
71: /*
72: * map the remainder to NMI adapters
73: */
74: *p++ = PG_KW|PG_V|(0x20080000/NBPG); /* NBIA 0 */
75: *p++ = PG_KW|PG_V|(0x24080000/NBPG); /* NBIA 1 */
76: *p++ = PG_KW|PG_V|(0x3e000000/NBPG); /* memory */
77: mcrcsr = (long *)(iospace + nexcnt * sizeof(struct nexus) + 2 * NBPG);
78: }
79:
80: static
81: nexreg(n)
82: register struct nextab *n;
83: {
84: if (n->bus >= 4 || n->adp >= 16)
85: return(0);
86: return (btoc(0x20000000 + (n->bus * 0x2000000) + (n->adp * NXSIZE)));
87: }
88:
89: /*
90: * `loc' requests local address within that BI
91: * the local address is what we put in sadr/eadr
92: * the global one is what we put in the page table
93: */
94: static
95: nexwind(n, loc)
96: register struct nextab *n;
97: {
98: register long addr;
99:
100: addr = 0x20400000 + (n->adp * NXWSIZE);
101: if (loc == 0)
102: addr += (n->bus * 0x2000000);
103: return (btoc(addr));
104: }
105:
106: /*
107: * generic VAXBI routines
108: */
109:
110: extern int biacnt;
111: extern char bianode[];
112: extern struct biaddr biaaddr[];
113:
114: #define NNUM 017 /* node to receive interrupts */
115: #define NOK 0200 /* this node has been initialized */
116:
117: #define DB88 0x106 /* DB88 device type */
118: #define NBIE 0x200000 /* NBIA interrupt enable */
119: #define NBINIT 0x1 /* NBIA CSR1 init */
120:
121: #define NBIASTALL 1000000
122:
123: /*
124: * return the address of a node's registers
125: * make sure the adapter has been initialized
126: */
127:
128: caddr_t
129: biaddr(bi)
130: register struct biaddr *bi;
131: {
132: register int a;
133:
134: if (bi->nexus < 0 || bi->nexus >= nexcnt)
135: return (0);
136: a = nextab[bi->nexus].bus;
137: if (a != bi->adno)
138: printf("nx%d adno%d bus%d\n", bi->nexus, bi->adno, a);
139: if ((bianode[a] & NOK) == 0 && biainit(a) == 0)
140: return (0);
141: return ((caddr_t)(iospace + bi->nexus * sizeof(struct nexus)));
142: }
143: /*
144: * set certain magic numbers in the BIIC:
145: * interrupt destination and map
146: * call after node reset stuff is all done,
147: * lest the numbers disappear
148: *
149: * can't NRST or look at BROKE here,
150: * as conventions vary too much among devices
151: */
152:
153: int
154: biinit(bi, mapwin)
155: struct biaddr *bi;
156: int mapwin;
157: {
158: register struct biic *bp;
159: long wind;
160:
161: if ((bp = (struct biic *)biaddr(bi)) == NULL)
162: panic("biinit");
163: bp->biintr = 1<<(bianode[bi->adno] & NNUM);
164: if (mapwin == 0) {
165: bp->bieadr = 0;
166: bp->bisadr = 0;
167: } else {
168: wind = ctob(nexwind(&nextab[bi->nexus], 1));
169: bp->bieadr = wind + NXWSIZE;
170: bp->bisadr = wind;
171: }
172: }
173:
174: /*
175: * init an NBIA
176: * and both the DB88s on this NBIA, if need be
177: */
178:
179: static int
180: biainit(a)
181: register int a;
182: {
183: register caddr_t cp;
184: register int v;
185: register struct nbia *np;
186:
187: if (a >= biacnt)
188: return (0);
189: if (nbia[0] == 0) {
190: cp = iospace + (nexcnt * sizeof(struct nexus));
191: nbia[0] = (struct nbia *)cp;
192: nbia[1] = (struct nbia *)(cp + NBPG);
193: }
194: np = ((a & 02) == 0) ? nbia[0] : nbia[1];
195: if (badaddr(&np->csr0, sizeof(long))) {
196: printf("nbia for bi%d not responding\n", a);
197: return (0);
198: }
199: np->csr1 |= NBINIT;
200: for (v = 0; v < NBIASTALL; v++)
201: ;
202: if ((v = nbiavec(a & ~1)) == 0)
203: return (0);
204: bibinit(a & ~1); /* the even one */
205: bibinit(a | 1); /* the odd one */
206: v &= 0x7c00; /* just the useful bits of vector */
207: np->csr0 = np->csr0; /* clear error complaints */
208: np->csr1 = np->csr1;
209: np->csr0 = v|NBIE;
210: setnmi((a & 02) ? 1 : 0);
211: return ((bianode[a] & NOK) != 0);
212: }
213:
214: /*
215: * init one DB88
216: */
217:
218: static
219: bibinit(a)
220: register int a;
221: {
222: register struct biic *bp;
223: register struct biaddr *bi;
224:
225: if (a >= biacnt || biaaddr[a].nexus < 0)
226: return;
227: bi = &biaaddr[a];
228: if (bi->nexus < 0 || bi->nexus >= nexcnt)
229: return;
230: bp = (struct biic *)(iospace + bi->nexus * sizeof(struct nexus));
231: bp->bitype = (bp->bitype & 0xffff0000)|DB88;
232: bp->bisadr = 0;
233: bp->bieadr = 0x20000000; /* all non-IO space */
234: bp->bieir = EIBR7|bi->vec;
235: bp->bicsr |= BIBROKE|BIHEIE|BISEIE; /* write BROKE to clear it */
236: bp->biber = bp->biber;
237: bp->bibci |= BCINTREN|BCRTOEN;
238: bp->biintr = 1<<(bp->bicsr & BINODEID);
239: if ((bp->bitype & 0xffff) != DB88)
240: return; /* oops */
241: bianode[a] = NOK|(bp->bicsr & BINODEID);
242: }
243:
244: /*
245: * figure out the vector offset for the nbia
246: * annoying sanity checks on the pair of DB88s
247: */
248:
249: static int
250: nbiavec(a)
251: register int a;
252: {
253: register struct biaddr *o, *e;
254: register int err;
255:
256: e = &biaaddr[a];
257: o = &biaaddr[a+1];
258: err = 0;
259: if (a+1 < biacnt && e->nexus >= 0 && o->nexus >= 0)
260: if (o->ovec != e->ovec+0x200)
261: err++;
262: if (e->nexus >= 0 && (e->ovec & 0x200) != 0)
263: err++;
264: if (a+1 < biacnt && o->nexus >= 0 && (o->ovec & 0x200) == 0)
265: err++;
266: if (err)
267: printf("bi%d bi%d: fix the damned vectors\n", a, a+1);
268: /*
269: * now for the vector
270: */
271: if (e->nexus >= 0)
272: return (e->ovec);
273: if (a+1 < biacnt && o->nexus >= 0)
274: return (o->ovec - 0x200);
275: return (0);
276: }
277:
278: /*
279: * here on nbia interrupt
280: * -- bi or nbi parity error, bi powerup
281: * figure out how to ignore the latter
282: */
283:
284: nbiaintr(dev)
285: int dev;
286: {
287: register struct nbia *np;
288: register long csr0, csr1;
289:
290: np = nbia[dev];
291: csr0 = np->csr0;
292: csr1 = np->csr1;
293: np->csr0 = csr0; /* clear interrupt conditions */
294: np->csr1 = csr1;
295: printf("nbi%d intr csr0 %x csr1 %x\n", dev, csr0, csr1);
296: }
297:
298: /*
299: * here on nbib error interrupt
300: */
301:
302: bia0int(dev)
303: register int dev;
304: {
305: register struct biic *bp;
306: register long biber, bicsr;
307:
308: if (dev >= biacnt || biaaddr[dev].nexus < 0 || biaaddr[dev].nexus >= nexcnt)
309: return;
310: bp = (struct biic *)(iospace + biaaddr[dev].nexus * sizeof(struct nexus));
311: bicsr = bp->bicsr;
312: biber = bp->biber;
313: bp->biber = biber; /* clear latches */
314: if ((biber & (BIHES|BISES)) == 0)
315: return;
316: if (cknofault())
317: return;
318: printf("bi%d: csr %x ber %x\n", dev, bicsr, biber);
319: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.