FreeBSD/Linux Kernel Cross Reference
sys/alphapc/arch164.c
1 /*
2 * EB164 and similar
3 * CPU: 21164
4 * Core Logic: 21172 CIA or 21174 PYXIS
5 */
6 #include "u.h"
7 #include "../port/lib.h"
8 #include "mem.h"
9 #include "dat.h"
10 #include "fns.h"
11 #include "io.h"
12
13 static ulong *core;
14 static ulong *wind;
15
16 static ulong windsave[16];
17 static ulong coresave[1];
18
19 ulong iobase0;
20 ulong iobase1;
21 #define iobase(p) (iobase0+(p))
22
23 static int
24 ident(void)
25 {
26 return 0; /* bug! */
27 }
28
29 static uvlong* sgmap;
30
31 static void
32 sginit(void)
33 {
34 ulong pa;
35 uvlong *pte;
36
37 sgmap = xspanalloc(BY2PG, BY2PG, 0);
38 memset(sgmap, 0, BY2PG);
39
40 /*
41 * Prepare scatter-gather map for 0-8MB.
42 */
43 pte = sgmap;
44 for(pa = 0; pa < 8*1024*1024; pa += BY2PG)
45 *pte++ = ((pa>>PGSHIFT)<<1)|1;
46
47 /*
48 * Set up a map for ISA DMA accesses to physical memory.
49 * Addresses presented by an ISA device between ISAWINDOW
50 * and ISAWINDOW+8MB will be translated to between 0 and
51 * 0+8MB of physical memory.
52 */
53 wind[0x400/4] = ISAWINDOW|2|1; /* window base */
54 wind[0x440/4] = 0x00700000; /* window mask */
55 wind[0x480/4] = PADDR(sgmap)>>2; /* <33:10> of sg map */
56
57 wind[0x100/4] = 3; /* invalidate tlb cache */
58 }
59
60 static void *
61 kmapio(ulong space, ulong offset, int size)
62 {
63 return kmapv(((uvlong)space<<32LL)|offset, size);
64 }
65
66 static void
67 coreinit(void)
68 {
69 int i;
70
71 core = kmapio(0x87, 0x40000000, 0x10000);
72 wind = kmapio(0x87, 0x60000000, 0x1000);
73
74 iobase0 = (ulong)kmapio(0x89, 0, 0x20000);
75
76 /* hae_io = core[0x440/4];
77 iobase1 = (ulong)kmapio(0x89, hae_io, 0x10000); */
78
79 /* save critical parts of hardware memory mapping */
80 for (i = 4; i < 8; i++) {
81 windsave[4*(i-4)+0] = wind[(i*0x100+0x00)/4];
82 windsave[4*(i-4)+1] = wind[(i*0x100+0x40)/4];
83 windsave[4*(i-4)+2] = wind[(i*0x100+0x80)/4];
84 }
85 coresave[0] = core[0x140/4];
86
87 /* disable windows */
88 wind[0x400/4] = 0;
89 wind[0x500/4] = 0;
90 wind[0x600/4] = 0;
91 wind[0x700/4] = 0;
92
93 sginit();
94
95 /*
96 * Set up a map for PCI DMA accesses to physical memory.
97 * Addresses presented by a PCI device between PCIWINDOW
98 * and PCIWINDOW+1GB will be translated to between 0 and
99 * 0+1GB of physical memory.
100 */
101 wind[0x500/4] = PCIWINDOW|1;
102 wind[0x540/4] = 0x3ff00000;
103 wind[0x580/4] = 0;
104
105 /* clear error state */
106 core[0x8200/4] = 0x7ff;
107
108 /* set config: byte/word enable, no monster window, etc. */
109 core[0x140/4] = 0x21;
110
111 /* turn off mcheck on master abort. now we can probe PCI space. */
112 core[0x8280/4] &= ~(1<<7);
113
114 /* set up interrupts. */
115 i8259init();
116 cserve(52, 4); /* enable SIO interrupt */
117 }
118
119 void
120 ciaerror(void)
121 {
122 print("cia error 0x%luX\n", core[0x8200/4]);
123 }
124
125 static void
126 corehello(void)
127 {
128 print("cpu%d: CIA revision %ld; cnfg %lux cntrl %lux\n",
129 0, /* BUG */
130 core[0x80/4] & 0x7f, core[0x140/4], core[0x100/4]);
131 print("cpu%d: HAE_IO %lux\n", 0, core[0x440/4]);
132 print("\n");
133 }
134
135 static void
136 coredetach(void)
137 {
138 int i;
139
140 for (i = 4; i < 8; i++) {
141 wind[(i*0x100+0x00)/4] = windsave[4*(i-4)+0];
142 wind[(i*0x100+0x40)/4] = windsave[4*(i-4)+1];
143 wind[(i*0x100+0x80)/4] = windsave[4*(i-4)+2];
144 }
145 core[0x140/4] = coresave[0];
146 /* for (i = 0; i < 4; i++)
147 if (i != 4)
148 cserve(53, i); /* disable interrupts */
149 }
150
151 static Lock pcicfgl;
152 static ulong pcimap[256];
153
154 static void*
155 pcicfg2117x(int tbdf, int rno)
156 {
157 int space, bus;
158 ulong base;
159
160 bus = BUSBNO(tbdf);
161 lock(&pcicfgl);
162 base = pcimap[bus];
163 if (base == 0) {
164 if(bus)
165 space = 0x8B;
166 else
167 space = 0x8A;
168 pcimap[bus] = base = (ulong)kmapio(space, MKBUS(0, bus, 0, 0), (1<<16));
169 }
170 unlock(&pcicfgl);
171 return (void*)(base + BUSDF(tbdf) + rno);
172 }
173
174 static void*
175 pcimem2117x(int addr, int len)
176 {
177 return kmapio(0x88, addr, len);
178 }
179
180 static int
181 intrenable164(Vctl *v)
182 {
183 int vec, irq;
184
185 irq = v->irq;
186 if(irq > MaxIrqPIC) {
187 print("intrenable: irq %d out of range\n", v->irq);
188 return -1;
189 }
190 if(BUSTYPE(v->tbdf) == BusPCI) {
191 vec = irq+VectorPCI;
192 cserve(52, irq);
193 }
194 else {
195 vec = irq+VectorPIC;
196 if(i8259enable(irq, v->tbdf, v) == -1)
197 return -1;
198 }
199 return vec;
200 }
201
202 /*
203 * I have a function pointer in PCArch for every one of these, because on
204 * some Alphas we have to use sparse mode, but on others we can use
205 * MOVB et al. Additionally, the PC164 documentation threatened us
206 * with the lie that the SIO is in region B, but everything else in region A.
207 * This turned out not to be the case. Given the cost of this solution, it
208 * may be better just to use sparse mode for I/O space on all platforms.
209 */
210 int
211 inb2117x(int port)
212 {
213 mb();
214 return *(uchar*)(iobase(port));
215 }
216
217 ushort
218 ins2117x(int port)
219 {
220 mb();
221 return *(ushort*)(iobase(port));
222 }
223
224 ulong
225 inl2117x(int port)
226 {
227 mb();
228 return *(ulong*)(iobase(port));
229 }
230
231 void
232 outb2117x(int port, int val)
233 {
234 mb();
235 *(uchar*)(iobase(port)) = val;
236 mb();
237 }
238
239 void
240 outs2117x(int port, ushort val)
241 {
242 mb();
243 *(ushort*)(iobase(port)) = val;
244 mb();
245 }
246
247 void
248 outl2117x(int port, ulong val)
249 {
250 mb();
251 *(ulong*)(iobase(port)) = val;
252 mb();
253 }
254
255 void
256 insb2117x(int port, void *buf, int len)
257 {
258 int i;
259 uchar *p, *q;
260
261 p = (uchar*)iobase(port);
262 q = buf;
263 for(i = 0; i < len; i++){
264 mb();
265 *q++ = *p;
266 }
267 }
268
269 void
270 inss2117x(int port, void *buf, int len)
271 {
272 int i;
273 ushort *p, *q;
274
275 p = (ushort*)iobase(port);
276 q = buf;
277 for(i = 0; i < len; i++){
278 mb();
279 *q++ = *p;
280 }
281 }
282
283 void
284 insl2117x(int port, void *buf, int len)
285 {
286 int i;
287 ulong *p, *q;
288
289 p = (ulong*)iobase(port);
290 q = buf;
291 for(i = 0; i < len; i++){
292 mb();
293 *q++ = *p;
294 }
295 }
296
297 void
298 outsb2117x(int port, void *buf, int len)
299 {
300 int i;
301 uchar *p, *q;
302
303 p = (uchar*)iobase(port);
304 q = buf;
305 for(i = 0; i < len; i++){
306 mb();
307 *p = *q++;
308 }
309 }
310
311 void
312 outss2117x(int port, void *buf, int len)
313 {
314 int i;
315 ushort *p, *q;
316
317 p = (ushort*)iobase(port);
318 q = buf;
319 for(i = 0; i < len; i++){
320 mb();
321 *p = *q++;
322 }
323 }
324
325 void
326 outsl2117x(int port, void *buf, int len)
327 {
328 int i;
329 ulong *p, *q;
330
331 p = (ulong*)iobase(port);
332 q = buf;
333 for(i = 0; i < len; i++){
334 mb();
335 *p = *q++;
336 }
337 }
338
339 PCArch arch164 = {
340 "EB164",
341 ident,
342 coreinit,
343 corehello,
344 coredetach,
345 pcicfg2117x,
346 pcimem2117x,
347 intrenable164,
348 nil,
349 nil,
350
351 inb2117x,
352 ins2117x,
353 inl2117x,
354 outb2117x,
355 outs2117x,
356 outl2117x,
357 insb2117x,
358 inss2117x,
359 insl2117x,
360 outsb2117x,
361 outss2117x,
362 outsl2117x,
363 };
Cache object: 17f5682c287379ff66313402c045b815
|