|
|
1.1 root 1: /*
2: * unibus adapter routines for VAX-11/750
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 struct nxaddr ubaaddr[];
16: extern int ubacnt;
17:
18: /*
19: * `registers', such as they are,
20: * for the comet unibus
21: * 0x2000 bytes of nexus space, followed by the address window
22: */
23:
24: #define NMAP 496
25: #define NBDP 3
26:
27: struct ubadev {
28: long junk0[0x10];
29: long dpr[16]; /* data path registers */
30: long junk1[0x1e0];
31: long mreg[512]; /* unibus map registers; last 16 unused */
32: long junk2[0x400];
33: char ubspace[NXWSIZE];
34: };
35:
36: /*
37: * bits in the data path register
38: */
39:
40: #define PURGE 0x1 /* purge datapath */
41: #define DPERR 0x80000000 /* any datapath error */
42:
43: /*
44: * bits in map register
45: */
46:
47: #define MPAGE 0x3fff /* physical page number -- small on comet */
48: #define BO 0x2000000 /* offset address by one */
49: #define MRV 0x80000000 /* map register valid */
50: #define PSHIFT 21 /* shift data path number this much */
51:
52: /*
53: * return the register address for a unibus device
54: */
55:
56: caddr_t
57: ubaddr(up)
58: register struct ubaddr *up;
59: {
60: register struct uba *ub;
61:
62: if (up->ubno < 0 || up->ubno > ubacnt) {
63: printf("bad ubano %d\n", up->ubno);
64: return (0);
65: }
66: ub = &uba[up->ubno];
67: if ((ub->flags & UBINIT) == 0)
68: if (ubstart(up->ubno) == 0)
69: return (0);
70: return ((caddr_t)&ub->addr->ubspace[up->uboff]);
71: }
72:
73: /*
74: * init the unibus adapter
75: */
76:
77: ubstart(u)
78: int u;
79: {
80: register struct uba *ub;
81:
82: ub = &uba[u];
83: if ((ub->addr = (struct ubadev *)nxaddr(&ubaaddr[u])) == 0)
84: return (0);
85: if (badaddr(&ub->addr->dpr[1], sizeof(long))) {
86: printf("ub%d not responding\n", u);
87: return (0);
88: }
89: rminit(ub->map, UBNMAP, NMAP-1, 1); /* NMAP-1 because can't alloc 0 */
90: ub->path = ((1<<NBDP)-1)<<1;
91: if (ubmstart(u) == 0)
92: return (0);
93: ubinit(u);
94: ub->flags |= UBINIT;
95: return (1);
96: }
97:
98: /*
99: * init the unibus adapter hardware
100: */
101:
102: ubinit(u)
103: int u;
104: {
105: register struct uba *ub;
106: register int i;
107: register long *p;
108:
109: ub = &uba[u];
110: for (i = 0, p = ub->addr->mreg; i < NMAP; i++)
111: *p++ = 0;
112: ubminit(u);
113: }
114:
115: /*
116: * determine whether a particular address,
117: * which happens to be in UNIBUS space,
118: * exists
119: * -- on comet, you just get a machine check on error
120: */
121: ubbadaddr(u, a, s)
122: int u, s;
123: caddr_t a;
124: {
125:
126: return (badaddr(a, s));
127: }
128:
129: /*
130: * get/put a single byte to a particular unibus address
131: * intended for use by ECC code
132: * work it out from first principles,
133: * because UNIBUS adapter may loop and hang otherwise
134: */
135:
136: static long
137: ubphys(ubno, addr)
138: unsigned int ubno;
139: uaddr_t addr;
140: {
141: register struct uba *ub;
142: register int pg;
143: register long m;
144:
145: if (ubno >= ubacnt)
146: panic("ubphys");
147: ub = &uba[ubno];
148: if (ub->addr == NULL)
149: panic("ubphys");
150: pg = addr / NBPG;
151: if (pg >= NMAP)
152: return (-1); /* addr too big */
153: m = ub->addr->mreg[pg];
154: if ((m & MRV) == 0)
155: return (-1); /* invalid */
156: return ((m & MPAGE) * NBPG + addr % NBPG);
157: }
158:
159: int
160: ubgetc(ubno, addr)
161: unsigned int ubno;
162: uaddr_t addr;
163: {
164: register long phys;
165:
166: phys = ubphys(ubno, addr);
167: if (phys < 0)
168: return (-1);
169: return (phgetc(phys));
170: }
171:
172: int
173: ubputc(ubno, addr, c)
174: unsigned int ubno;
175: uaddr_t addr;
176: char c;
177: {
178: register long phys;
179:
180: phys = ubphys(ubno, addr);
181: if (phys < 0)
182: return (-1);
183: return (phputc(phys, c));
184: }
185:
186: /*
187: * unibus adapter interrupts;
188: * on the comet, these are always wrong
189: */
190:
191: uba0int(dev)
192: int dev;
193: {
194: printf("uba%d stray intr\n", dev);
195: }
196:
197: /*
198: * allocate a buffered data path
199: * return the ddp if none available
200: */
201: int ubnopath;
202:
203: int
204: ubmapath(u)
205: int u;
206: {
207: register struct uba *ub;
208: register int path;
209: register int s;
210:
211: ub = &uba[u];
212: s = spl6();
213: for (path = NBDP; path > 0; path--)
214: if (ub->path & (1<<path)) {
215: ub->path &=~ (1<<path);
216: break;
217: }
218: splx(s);
219: if (path == 0)
220: ubnopath++;
221: return (path);
222: }
223:
224: /*
225: * flush (in hardware) a bdp
226: */
227: #define PRGTIM 10
228:
229: ubmflush(u, path)
230: int u;
231: int path;
232: {
233: register long *reg;
234: register int i;
235:
236: if (path == 0)
237: return;
238: reg = &uba[u].addr->dpr[path];
239: *reg = PURGE;
240: for (i = PRGTIM; i > 0; --i)
241: if ((*reg & PURGE) == 0)
242: break;
243: if (i <= 0)
244: printf("uba%d bdp%d stuck %x\n", u, path, *reg);
245: if (*reg & DPERR) {
246: printf("uba%d bdp%d err %x\n", u, path, *reg);
247: *reg = *reg;
248: }
249: }
250:
251: /*
252: * fill in a piece of unibus map
253: * return the address of the base
254: */
255:
256: uaddr_t
257: ubmsetmap(u, p, nreg, um)
258: int u;
259: register struct pte *p;
260: register int nreg;
261: ubm_t um;
262: {
263: register long *m;
264: register long x;
265:
266: m = &uba[u].addr->mreg[ubmfirst(um)];
267: x = (ubmpath(um)<<PSHIFT)|MRV;
268: if (nreg > ubmsize(um)-1)
269: panic("ubmsetmap");
270: while (--nreg >= 0)
271: *m++ = p++->pg_pfnum | x;
272: return (ctob(ubmfirst(um)));
273: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.