|
|
1.1 root 1: /*
2: * unibus adapter routines for DW780
3: */
4:
5: #include "sys/param.h"
6: #include "sys/ubaddr.h"
7: #include "sys/nexus.h"
8: #include "sys/nxaddr.h"
9: #include "sys/map.h"
10: #include "sys/uba.h"
11: #include "sys/pte.h"
12: #include "sys/vmparam.h"
13:
14: extern struct uba uba[];
15: extern long ubavoff[];
16: extern long *ubavreg[];
17: extern long ubazvec[];
18: extern struct nxaddr ubaaddr[];
19: extern int ubacnt;
20:
21: /*
22: * 0x2000 bytes of nexus space, followed by the address window
23: */
24:
25: #define NMAP 496
26: #define NBDP 15
27:
28: struct ubadev {
29: long cnfgr; /* configuration register */
30: long uacr; /* adapter control */
31: long uasr; /* adapter status */
32: long dcr; /* diag stuff */
33: long fmer; /* failed map entry */
34: long fubar; /* failed unibus addr */
35: long junk0[2];
36: long bufsel[4];
37: long brrvr[4]; /* vectors for each BR */
38: long dpr[16]; /* data path registers */
39: long junk1[0x1e0];
40: long mreg[512]; /* unibus map registers; last 16 unused */
41: long junk2[0x400];
42: char ubspace[NXWSIZE];
43: };
44:
45: /*
46: * bits in uacr
47: */
48: #define ADINIT 0x1 /* adapter init */
49: #define CNFIE 0x4 /* config IE */
50: #define SUEFIE 0x8 /* SBI to UNIBUS error IE */
51: #define USEFIE 0x10 /* UNIBUS to SBI error IE */
52: #define BRIE 0x20 /* BR interrupt enable */
53: #define IFS 0x40 /* pass UNIBUS interrupts to SBI */
54:
55: #define UBAIE (IFS|BRIE|USEFIE|SUEFIE|CNFIE)
56:
57: /*
58: * bits in cnfgr
59: */
60: #define PARFLT 0x80000000 /* SBI Parity Fault */
61: #define WSQFLT 0x40000000 /* SBI Write Sequence Fault */
62: #define URDFLT 0x20000000 /* SBI Unexpected Read Fault */
63: #define ISQFLT 0x10000000 /* SBI Interlock Sequence Fault */
64: #define MXTFLT 0x8000000 /* SBI Multiple Transmitter Fault */
65: #define XMTFLT 0x4000000 /* UBA is transmit faulter */
66: #define UBIC 0x10000 /* init complete */
67:
68: #define CFGFLT (PARFLT|WSQFLT|URDFLT|ISQFLT|MXTFLT|XMTFLT)
69:
70: /*
71: * bits in uasr
72: */
73: #define DPPE 0x20 /* Data Path Parity Error */
74: #define IVMR 0x10 /* Invalid Map Register */
75: #define MRPF 0x8 /* Map Register Parity Failure */
76: #define UBSSYNTO 0x1 /* unibus SSYN timeout */
77:
78: #define BADMAP (MRPF|IVMR|DPPE) /* bits indicating mapping reg problem */
79:
80: /*
81: * bits in the data path register
82: */
83:
84: #define BNE 0x80000000 /* purge datapath */
85: #define BTE 0x40000000 /* bdp transfer error */
86:
87: /*
88: * bits in map register
89: */
90:
91: #define MPAGE 0x7ffff /* physical page number */
92: #define BO 0x2000000 /* offset address by one */
93: #define MRV 0x80000000 /* map register valid */
94: #define PSHIFT 21 /* shift data path number this much */
95:
96: #define INITTIME 50000 /* time to stall waiting for UNIBUS init */
97: /* 25ms nominal; 50000 for VAX-11/785 */
98:
99: /*
100: * return the register address for a unibus device
101: */
102:
103: caddr_t
104: ubaddr(up)
105: register struct ubaddr *up;
106: {
107: register struct uba *ub;
108:
109: if (up->ubno < 0 || up->ubno > ubacnt) {
110: printf("bad ubano %d\n", up->ubno);
111: return (0);
112: }
113: ub = &uba[up->ubno];
114: if ((ub->flags & UBINIT) == 0)
115: if (ubstart(up->ubno) == 0)
116: return (0);
117: return ((caddr_t)&ub->addr->ubspace[up->uboff]);
118: }
119:
120: /*
121: * init the unibus adapter
122: */
123:
124: ubstart(u)
125: int u;
126: {
127: register struct uba *ub;
128:
129: ub = &uba[u];
130: if ((ub->addr = (struct ubadev *)nxaddr(&ubaaddr[u])) == 0)
131: return (0);
132: if (badaddr(&ub->addr->cnfgr, sizeof(long))) {
133: printf("ub%d not responding\n", u);
134: return (0);
135: }
136: rminit(ub->map, UBNMAP, NMAP-1, 1); /* NMAP-1 because can't alloc 0 */
137: ub->path = ((1<<NBDP)-1)<<1;
138: if (ubmstart(u) == 0)
139: return (0);
140: ubinit(u);
141: ub->flags |= UBINIT;
142: return (1);
143: }
144:
145: /*
146: * init the unibus adapter hardware
147: */
148:
149: ubinit(u)
150: int u;
151: {
152: register struct uba *ub;
153: register struct ubadev *up;
154: register int i;
155: register long *p;
156:
157: ub = &uba[u];
158: up = ub->addr;
159: up->uacr = ADINIT;
160: for (i = 0; i < INITTIME; i++)
161: if (up->cnfgr & UBIC)
162: break;
163: if ((up->cnfgr & UBIC) == 0) {
164: printf("ub%d not ready\n", u);
165: return (0);
166: }
167: ubavoff[u] = ubaaddr[u].voff;
168: ubavreg[u] = &up->brrvr[0];
169: up->cnfgr = up->cnfgr; /* clear power-up latches */
170: up->uacr = UBAIE;
171: for (i = 0, p = ub->addr->mreg; i < NMAP; i++)
172: *p++ = 0;
173: ubminit(u);
174: return (1);
175: }
176:
177: /*
178: * determine whether a particular address,
179: * which happens to be in UNIBUS space,
180: * exists
181: */
182: ubbadaddr(u, a, s)
183: int u, s;
184: caddr_t a;
185: {
186: register int p;
187: register struct ubadev *up;
188:
189: if (u < 0 || u >= ubacnt)
190: return (1);
191: up = uba[u].addr;
192: p = spl7();
193: /* perhaps disable SBI-to-UNIBUS interrupts? */
194: up->uasr = up->uasr; /* clear errors */
195: s = badaddr(a, s);
196: if (up->uasr & UBSSYNTO) /* or perhaps any error? */
197: s = 1;
198: up->uasr = up->uasr; /* clear errors again */
199: splx(p);
200: return (s);
201: }
202:
203: /*
204: * get/put a single byte to a particular unibus address
205: * intended for use by ECC code
206: * work it out from first principles,
207: * because UNIBUS adapter may loop and hang otherwise
208: */
209:
210: static long
211: ubphys(ubno, addr)
212: unsigned int ubno;
213: uaddr_t addr;
214: {
215: register struct uba *ub;
216: register int pg;
217: register long m;
218:
219: if (ubno >= ubacnt)
220: panic("ubphys");
221: ub = &uba[ubno];
222: if (ub->addr == NULL)
223: panic("ubphys");
224: pg = addr / NBPG;
225: if (pg >= NMAP)
226: return (-1); /* addr too big */
227: m = ub->addr->mreg[pg];
228: if ((m & MRV) == 0)
229: return (-1); /* invalid */
230: return ((m & MPAGE) * NBPG + addr % NBPG);
231: }
232:
233: int
234: ubgetc(ubno, addr)
235: unsigned int ubno;
236: uaddr_t addr;
237: {
238: register long phys;
239:
240: phys = ubphys(ubno, addr);
241: if (phys < 0)
242: return (-1);
243: return (phgetc(phys));
244: }
245:
246: int
247: ubputc(ubno, addr, c)
248: unsigned int ubno;
249: uaddr_t addr;
250: char c;
251: {
252: register long phys;
253:
254: phys = ubphys(ubno, addr);
255: if (phys < 0)
256: return (-1);
257: return (phputc(phys, c));
258: }
259:
260: /*
261: * unibus adapter interrupts
262: * here only on non-device interrupts:
263: * passive release, or adapter has something to say
264: *
265: * -- assertion:
266: * to get here, we must read the BRRVR,
267: * which means ubavreg is set up,
268: * which means uba.addr is set up
269: */
270:
271: uba0int(u, vec)
272: int u;
273: {
274: register struct ubadev *up;
275: long cnfgr, uasr, fubar, fmer;
276:
277: if (vec == 0) { /* passive release */
278: ubazvec[u]++;
279: return;
280: }
281: up = uba[u].addr;
282: cnfgr = up->cnfgr;
283: uasr = up->uasr;
284: fubar = up->fubar<<2;
285: fmer = up->fmer;
286: up->uasr = uasr;
287: up->cnfgr = cnfgr;
288: if (cnfgr & CFGFLT) { /* does this really happen? */
289: printf("ub%d: SBI fault cnfgr%x sr%x\n", u, cnfgr, uasr);
290: return;
291: }
292: printf("ub%d: cfg%x sr%x fubar %o\n", u, cnfgr, uasr, fubar);
293: if (uasr & BADMAP)
294: printf("fmer %x\n", fmer);
295: }
296:
297: /*
298: * allocate a buffered data path
299: * return the ddp if none available
300: */
301: int ubnopath;
302:
303: int
304: ubmapath(u)
305: int u;
306: {
307: register struct uba *ub;
308: register int path;
309: register int s;
310:
311: ub = &uba[u];
312: s = spl6();
313: for (path = NBDP; path > 0; path--)
314: if (ub->path & (1<<path)) {
315: ub->path &=~ (1<<path);
316: break;
317: }
318: splx(s);
319: if (path == 0)
320: ubnopath++;
321: return (path);
322: }
323:
324: ubmflush(u, path)
325: int u;
326: int path;
327: {
328: register long *reg;
329:
330: if (path == 0)
331: return;
332: reg = &uba[u].addr->dpr[path];
333: *reg |= BNE;
334: DELAY(2);
335: if (*reg & BTE) {
336: printf("ub%d bdp%d err %x\n", u, path, *reg);
337: *reg = *reg;
338: }
339: }
340:
341: /*
342: * fill in a piece of unibus map
343: * return the address of the base
344: */
345:
346: uaddr_t
347: ubmsetmap(u, p, nreg, um)
348: int u;
349: register struct pte *p;
350: register int nreg;
351: ubm_t um;
352: {
353: register long *m;
354: register long x;
355:
356: m = &uba[u].addr->mreg[ubmfirst(um)];
357: x = (ubmpath(um)<<PSHIFT)|MRV;
358: if (nreg > ubmsize(um)-1)
359: panic("ubmsetmap");
360: while (--nreg >= 0)
361: *m++ = p++->pg_pfnum | x;
362: *m = 0;
363: return (ctob(ubmfirst(um)));
364: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.