]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/alphapc/arch164.c
merge
[plan9front.git] / sys / src / 9 / 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 };