ka43.c revision 1.20 1 /* $NetBSD: ka43.c,v 1.20 2000/03/13 23:52:34 soren Exp $ */
2 /*
3 * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Ludd by Bertram Barth.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed at Ludd, University of
19 * Lule}, Sweden and its contributors.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/device.h>
38 #include <sys/kernel.h>
39 #include <sys/systm.h>
40
41 #include <vm/vm.h>
42 #include <vm/vm_kern.h>
43
44 #include <machine/pte.h>
45 #include <machine/cpu.h>
46 #include <machine/mtpr.h>
47 #include <machine/sid.h>
48 #include <machine/pmap.h>
49 #include <machine/nexus.h>
50 #include <machine/uvax.h>
51 #include <machine/vsbus.h>
52 #include <machine/ka43.h>
53 #include <machine/clock.h>
54
55 static void ka43_conf __P((void));
56 static void ka43_steal_pages __P((void));
57
58 static int ka43_mchk __P((caddr_t));
59 static void ka43_memerr __P((void));
60 #if 0
61 static void ka43_clear_errors __P((void));
62 #endif
63 static int ka43_cache_init __P((void)); /* "int mapen" as argument? */
64 static int ka43_cache_reset __P((void));
65 static int ka43_cache_enable __P((void));
66 static int ka43_cache_disable __P((void));
67 static int ka43_cache_invalidate __P((void));
68 static void ka43_halt __P((void));
69 static void ka43_reboot __P((int));
70 static void ka43_clrf __P((void));
71
72
73 struct cpu_dep ka43_calls = {
74 ka43_steal_pages,
75 ka43_mchk,
76 ka43_memerr,
77 ka43_conf,
78 chip_clkread,
79 chip_clkwrite,
80 7, /* 7.6 VUP */
81 2, /* SCB pages */
82 ka43_halt,
83 ka43_reboot,
84 ka43_clrf,
85 };
86
87 /*
88 * ka43_steal_pages() is called with MMU disabled, after that call MMU gets
89 * enabled. Thus we initialize these four pointers with physical addresses,
90 * but before leving ka43_steal_pages() we reset them to virtual addresses.
91 */
92 static volatile struct ka43_cpu *ka43_cpu = (void*)KA43_CPU_BASE;
93 static volatile u_int *ka43_creg = (void*)KA43_CH2_CREG;
94 static volatile u_int *ka43_ctag = (void*)KA43_CT2_BASE;
95
96 #define KA43_MC_RESTART 0x00008000 /* Restart possible*/
97 #define KA43_PSL_FPDONE 0x00010000 /* First Part Done */
98
99 struct ka43_mcframe { /* Format of RigelMAX machine check frame: */
100 int mc43_bcnt; /* byte count, always 24 (0x18) */
101 int mc43_code; /* machine check type code and restart bit */
102 int mc43_addr; /* most recent (faulting?) virtual address */
103 int mc43_viba; /* contents of VIBA register */
104 int mc43_sisr; /* ICCS bit 6 and SISR bits 15:0 */
105 int mc43_istate; /* internal state */
106 int mc43_sc; /* shift count register */
107 int mc43_pc; /* trapped PC */
108 int mc43_psl; /* trapped PSL */
109 };
110
111 static char *ka43_mctype[] = {
112 "no error (0)", /* Code 0: No error */
113 "FPA: protocol error", /* Code 1-5: FPA errors */
114 "FPA: illegal opcode",
115 "FPA: operand parity error",
116 "FPA: unknown status",
117 "FPA: result parity error",
118 "unused (6)", /* Code 6-7: Unused */
119 "unused (7)",
120 "MMU error (TLB miss)", /* Code 8-9: MMU errors */
121 "MMU error (TLB hit)",
122 "HW interrupt at unused IPL", /* Code 10: Interrupt error */
123 "MOVCx impossible state", /* Code 11-13: Microcode errors */
124 "undefined trap code (i-box)",
125 "undefined control store address",
126 "unused (14)", /* Code 14-15: Unused */
127 "unused (15)",
128 "PC tag or data parity error", /* Code 16: Cache error */
129 "data bus parity error", /* Code 17: Read error */
130 "data bus error (NXM)", /* Code 18: Write error */
131 "undefined data bus state", /* Code 19: Bus error */
132 };
133 #define MC43_MAX 19
134
135 static int ka43_error_count = 0;
136
137 int
138 ka43_mchk(addr)
139 caddr_t addr;
140 {
141 register struct ka43_mcframe *mcf = (void*)addr;
142
143 mtpr(0x00, PR_MCESR); /* Acknowledge the machine check */
144 printf("machine check %d (0x%x)\n", mcf->mc43_code, mcf->mc43_code);
145 printf("reason: %s\n", ka43_mctype[mcf->mc43_code & 0xff]);
146 if (++ka43_error_count > 10) {
147 printf("error_count exceeded: %d\n", ka43_error_count);
148 return (-1);
149 }
150
151 /*
152 * If either the Restart flag is set or the First-Part-Done flag
153 * is set, and the TRAP2 (double error) bit is not set, then the
154 * error is recoverable.
155 */
156 if (mfpr(PR_PCSTS) & KA43_PCS_TRAP2) {
157 printf("TRAP2 (double error) in ka43_mchk.\n");
158 panic("unrecoverable state in ka43_mchk.\n");
159 return (-1);
160 }
161 if ((mcf->mc43_code & KA43_MC_RESTART) ||
162 (mcf->mc43_psl & KA43_PSL_FPDONE)) {
163 printf("ka43_mchk: recovering from machine-check.\n");
164 ka43_cache_reset(); /* reset caches */
165 return (0); /* go on; */
166 }
167
168 /*
169 * Unknown error state, panic/halt the machine!
170 */
171 printf("ka43_mchk: unknown error state!\n");
172 return (-1);
173 }
174
175 void
176 ka43_memerr()
177 {
178 /*
179 * Don\'t know what to do here. So just print some messages
180 * and try to go on...
181 */
182 printf("memory error!\n");
183 printf("primary cache status: %b\n", mfpr(PR_PCSTS), KA43_PCSTS_BITS);
184 printf("secondary cache status: %b\n", *ka43_creg, KA43_SESR_BITS);
185 }
186
187 int
188 ka43_cache_init()
189 {
190 return (ka43_cache_reset());
191 }
192
193 #if 0
194 void
195 ka43_clear_errors()
196 {
197 int val = *ka43_creg;
198 val |= KA43_SESR_SERR | KA43_SESR_LERR | KA43_SESR_CERR;
199 *ka43_creg = val;
200 }
201 #endif
202
203 int
204 ka43_cache_reset()
205 {
206 /*
207 * resetting primary and secondary caches is done in three steps:
208 * 1. disable both caches
209 * 2. manually clear secondary cache
210 * 3. enable both caches
211 */
212 ka43_cache_disable();
213 ka43_cache_invalidate();
214 ka43_cache_enable();
215
216 printf("primary cache status: %b\n", mfpr(PR_PCSTS), KA43_PCSTS_BITS);
217 printf("secondary cache status: %b\n", *ka43_creg, KA43_SESR_BITS);
218
219 return (0);
220 }
221
222 int
223 ka43_cache_disable()
224 {
225 int val;
226
227 /*
228 * first disable primary cache and clear error flags
229 */
230 mtpr(KA43_PCS_REFRESH, PR_PCSTS); /* disable primary cache */
231 val = mfpr(PR_PCSTS);
232 mtpr(val, PR_PCSTS); /* clear error flags */
233
234 /*
235 * now disable secondary cache and clear error flags
236 */
237 val = *ka43_creg & ~KA43_SESR_CENB; /* BICL !!! */
238 *ka43_creg = val; /* disable secondary cache */
239 val = KA43_SESR_SERR | KA43_SESR_LERR | KA43_SESR_CERR;
240 *ka43_creg = val; /* clear error flags */
241
242 return (0);
243 }
244
245 int
246 ka43_cache_invalidate()
247 {
248 int i, val;
249
250 val = KA43_PCTAG_PARITY; /* clear valid flag, set parity bit */
251 for (i = 0; i < 256; i++) { /* 256 Quadword entries */
252 mtpr(i*8, PR_PCIDX); /* write index of tag */
253 mtpr(val, PR_PCTAG); /* write value into tag */
254 }
255 val = KA43_PCS_FLUSH | KA43_PCS_REFRESH;
256 mtpr(val, PR_PCSTS); /* flush primary cache */
257
258 /*
259 * Rigel\'s secondary cache doesn\'t implement a valid-flag.
260 * Thus we initialize all entries with out-of-range/dummy
261 * addresses which will never be referenced (ie. never hit).
262 * After enabling cache we also access 128K of memory starting
263 * at 0x00 so that secondary cache will be filled with these
264 * valid addresses...
265 */
266 val = 0xff;
267 /* if (memory > 28 MB) val = 0x55; */
268 for (i = 0; i < KA43_CT2_SIZE; i+= 4) { /* Quadword entries ?? */
269 ka43_ctag[i/4] = val; /* reset upper and lower */
270 }
271
272 return (0);
273 }
274
275
276 int
277 ka43_cache_enable()
278 {
279 volatile char *membase = (void*)0x80000000; /* physical 0x00 */
280 int i, val;
281
282 val = KA43_PCS_FLUSH | KA43_PCS_REFRESH;
283 mtpr(val, PR_PCSTS); /* flush primary cache */
284
285 /*
286 * now we enable secondary cache and access first 128K of memory
287 * so that secondary cache gets really initialized and holds
288 * valid addresses/data...
289 */
290 *ka43_creg = KA43_SESR_CENB; /* enable secondary cache */
291 for (i=0; i<128*1024; i++) {
292 val += membase[i]; /* some dummy operation... */
293 }
294
295 val = KA43_PCS_ENABLE | KA43_PCS_REFRESH;
296 mtpr(val, PR_PCSTS); /* enable primary cache */
297
298 return (0);
299 }
300
301 void
302 ka43_conf()
303 {
304 printf("cpu: KA43\n");
305 ka43_cpu = (void *)vax_map_physmem(VS_REGS, 1);
306
307 ka43_creg = (void *)vax_map_physmem(KA43_CH2_CREG, 1);
308 ka43_ctag = (void *)vax_map_physmem(KA43_CT2_BASE,
309 (KA43_CT2_SIZE/VAX_NBPG));
310
311 /*
312 * ka43_conf() gets called with MMU enabled, now it's save to
313 * init/reset the caches.
314 */
315 ka43_cache_init();
316
317 clk_adrshift = 1; /* Addressed at long's... */
318 clk_tweak = 2; /* ...and shift two */
319 clk_page = (short *)vax_map_physmem(VS_CLOCK, 1);
320 }
321
322
323 /*
324 * The interface for communication with the LANCE ethernet controller
325 * is setup in the xxx_steal_pages() routine. We decrease highest
326 * available address by 64K and use this area as communication buffer.
327 */
328
329 void
330 ka43_steal_pages()
331 {
332 int val;
333
334
335 /*
336 * if LANCE\'s io-buffer is above 16 MB, then the appropriate flag
337 * in the parity control register has to be set (it works as an
338 * additional address bit). In any case, don\'t enable CPEN and
339 * DPEN in the PARCTL register, somewhow they are internally managed
340 * by the RIGEL chip itself!?!
341 */
342 val = ka43_cpu->parctl & 0x03; /* read the old value */
343 ka43_cpu->parctl = val; /* and write new value */
344 }
345
346 static void
347 ka43_clrf()
348 {
349 struct ka43_clock *clk = (void *)clk_page;
350
351 /*
352 * Clear restart and boot in progress flags in the CPMBX.
353 */
354 clk->cpmbx = (clk->cpmbx & ~0xf0);
355 }
356
357 static void
358 ka43_halt()
359 {
360 asm("movl $0xc, (%0)"::"r"((int)clk_page + 0x38)); /* Don't ask */
361 asm("halt");
362 }
363
364 static void
365 ka43_reboot(arg)
366 int arg;
367 {
368 asm("movl $0xc, (%0)"::"r"((int)clk_page + 0x38)); /* Don't ask */
369 asm("halt");
370 }
371
372