revert between 56095 -> 55830 in arch
[AROS.git] / arch / .unmaintained / ppc-native / boot / ppc_boot.c
blob4bc8a42a596db7020ad2c38feae33833cf78cea1
1 /****************************************************************************
2 * ppc_boot.c -- This program initializes the PPC on a Phase5 PowerUp board
3 * and boots the kernel.
5 * Copyright 1997, 1998 by Jesper Skov (jskov@cygnus.co.uk)
6 ***************************************************************************/
8 #define SYMBOL_NAME_STR(X) #X
10 #define INTENA 0xdff09a
11 #define INTREQ 0xdff09c
12 #define DMACON 0xdff096
14 #define CHIP_PTR (0xfff00)
16 #define REG_SHADOW (0xf60018)
17 #define REGSHADOW_SETRESET (0x80)
18 #define REGSHADOW_SHADOW (0x01)
20 #define REG_INTREG (0xf60028)
21 #define REGINTREG_SETRESET (0x80)
22 #define REGINTREG_INTMASTER (0x01)
24 #define REG_IPLEMU (0xf60030)
25 #define REGIPLEMU_SETRESET (0x80)
26 #define REGIPLEMU_DISABLEINT (0x40)
29 #define REG_INTLVL (0xf60038)
30 #define REGINTLVL_SETRESET (0x80)
31 #define REGINTLVL_LVL7 (0x40)
36 #include <exec/types.h>
37 #include <exec/nodes.h>
38 #include <exec/lists.h>
39 #include <exec/memory.h>
40 #include <powerup/ppclib/interface.h>
41 #include <powerup/gcclib/powerup_protos.h>
42 #include <powerup/ppclib/tasks.h>
44 void goSupervisor(void);
45 void relocate(void);
46 extern char relocateEnd;
48 void progress_init (void);
49 void progress (char);
51 unsigned int main(void)
53 int i;
54 unsigned long *s, *d;
55 unsigned long ptr;
57 register unsigned long r0 __asm("r0");
58 register unsigned long r3 __asm("r3");
60 progress_init ();
62 /* Wait for signal from m68k. */
63 progress ('W');
65 void *PPCPort;
67 if (PPCPort=(void*) PPCGetTaskAttr(PPCTASKTAG_MSGPORT))
69 progress ('w'); /* Wait */
70 PPCWaitPort(PPCPort);
71 progress ('r'); /* Received */
72 } else {
73 progress ('X');
74 for (;;);
77 progress ('!');
79 /* Start Shutdown. */
80 progress ('S');
82 progress ('d'); /* Disable IRQs. */
83 *(unsigned short*) INTENA = 0x7fff;
84 __asm __volatile ("eieio");
85 progress ('d'); /* (Stall for a bit.) */
86 *(unsigned short*) INTREQ = 0x7fff;
87 __asm __volatile ("eieio");
88 progress ('d'); /* Disable DMA. */
89 *(unsigned short*) DMACON = 0x03ff;
92 progress ('s'); /* Get the PR bit set. */
93 goSupervisor();
95 progress ('e'); /* Disable exception handling. */
96 __asm __volatile (
97 "mfmsr 4 \n\t"
98 "lis 3,0 \n\t"
99 "ori 3,3,0x8000 \n\t" /* MSR_EE */
100 "andc 4,4,3 \n\t"
101 "isync \n\t"
102 "mtmsr 4 \n\t"
103 "sync \n\t"
104 ::: "r3", "r4");
106 progress ('i'); /* Disable interrupt logic. */
107 *(unsigned char*) REG_IPLEMU = REGIPLEMU_SETRESET | REGIPLEMU_DISABLEINT;
108 __asm __volatile ("eieio;sync");
111 progress ('i'); /* Change interrupt master. */
112 *(unsigned char*) REG_INTREG = REGINTREG_INTMASTER;
113 __asm __volatile ("eieio;sync;");
115 progress ('w'); /* Give the m68k a wedgie. */
116 *(unsigned char*) REG_INTLVL = REGINTLVL_LVL7;
117 __asm __volatile ("eieio;sync");
118 progress ('?');
120 /* Stall a bit to allow the m68k to disable its MMU. */
122 int i;
123 for (i = 0; i < 30000; i++);
125 progress ('!'); /* Done! PPC owns the Amiga. */
127 progress ('1');
128 PPCCacheFlushAll();
129 __asm __volatile (
130 /* Disable caches. */
131 "mfspr 4,1008 \n\t" /* HID0 */
132 "lis 3,0 \n\t"
133 "ori 3,3,0xc000 \n\t" /* HID0_ICE|HID0_DCE */
134 "andc 4,4,3 \n\t"
135 "sync \n\t"
136 "isync \n\t"
137 "mtspr 1008,4 \n\t" /* HID0 */
138 /* Invalidate caches. */
139 "mfspr 4,1008 \n\t" /* HID0 */
140 "lis 3,4 \n\t"
141 "ori 3,3,0x0c00 \n\t" /* HID0_ICFI|HID0_DCFI */
142 "or 3,3,4 \n\t"
143 "isync \n\t"
144 "sync \n\t"
145 "mtspr 1008,3 \n\t" /* HID0 */
146 "mtspr 1008,4 \n\t" /* HID0 */
147 "isync \n\t"
148 /* Disable address translation and interrupts. */
149 "mfmsr 4 \n\t"
150 "lis 3,0 \n\t"
151 "ori 3,3,0x0030 \n\t" /* MSR_IR|MSR_DR */
152 "andc 4,4,3 \n\t"
153 "sync \n\t"
154 "isync \n\t"
155 "mtmsr 4 \n\t"
156 "isync \n\t"
157 /* Put BATs in a safe state. (Enable bits are in the Upper word) */
158 "li 3,0 \n\t"
159 "mtspr 528,3 \n\t" /* IBAT0U */
160 "mtspr 530,3 \n\t" /* IBAT1U */
161 "mtspr 532,3 \n\t" /* IBAT2U */
162 "mtspr 534,3 \n\t" /* IBAT3U */
163 "mtspr 536,3 \n\t" /* DBAT0U */
164 "mtspr 538,3 \n\t" /* DBAT1U */
165 "mtspr 540,3 \n\t" /* DBAT2U */
166 "mtspr 542,3 \n\t" /* DBAT3U */
167 /* Clear segment registers. */
168 "mtsr 0,3 \n\t"
169 "mtsr 1,3 \n\t"
170 "mtsr 2,3 \n\t"
171 "mtsr 3,3 \n\t"
172 "mtsr 4,3 \n\t"
173 "mtsr 5,3 \n\t"
174 "mtsr 6,3 \n\t"
175 "mtsr 7,3 \n\t"
176 "mtsr 8,3 \n\t"
177 "mtsr 9,3 \n\t"
178 "mtsr 10,3 \n\t"
179 "mtsr 11,3 \n\t"
180 "mtsr 12,3 \n\t"
181 "mtsr 13,3 \n\t"
182 "mtsr 14,3 \n\t"
183 "mtsr 15,3 \n\t"
184 /* Clear SDR1 & ASR. */
185 "mtspr 25,3 \n\t" /* SDR1 */
186 "mtspr 280,3 \n\t" /* ASR */
187 "isync \n\t"
188 ::: "r3", "r4");
190 progress ('2');
192 #if 0
194 /* I don't know if this works so it is disabled until someone with a
195 blizzard verifies the effect. mm/init.c will need to be adjusted
196 if this code is activated (init makes presumptions about
197 shadowing based on memory size). */
198 unsigned char* reg_shadow = (unsigned char*) REG_SHADOW;
199 *reg_shadow = (REGSHADOW_SETRESET | REGSHADOW_SHADOW);
201 #endif
203 progress ('3');
206 const unsigned long *info;
207 /* Get info-ptr from CHIP_PTR. */
208 info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
210 /* Relocate code to memory just above info. */
211 ptr = (unsigned long)info + 0x0200;
212 ptr = ptr + 4 - (ptr % 4);
214 s = (unsigned long*) &relocate;
215 d = (unsigned long*) ptr;
216 for(i = (((unsigned long)&relocateEnd) - ((unsigned long)s))/4;
217 i >= 0; i--){
218 *d = *s;
219 d++;
220 s++;
223 progress ('4');
225 /* Jump to relocated code. */
226 __asm __volatile (
227 /* Change stack. */
228 "mr 1,%0 \n\t"
229 "mtlr %1 \n\t"
230 "blr \n\t"
231 : /* no outputs */
232 : "r" (info[8]), "r" (ptr)
233 /* no return */);
237 /* fake a noreturn */
238 for (;;);
241 void relocate(void)
243 const unsigned long *info;
244 unsigned char *s, *d, *e;
246 progress ('5');
248 /* Get info-ptr from CHIP_PTR. */
249 info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
251 /* Verify checksum. */
252 if (info[7])
254 int i = (info[2] + info[3]) / 4;
255 unsigned char* k_p = (unsigned char*) info[0];
256 unsigned long kcs = 0;
258 while (i--)
260 unsigned long w = 0;
262 w |= *k_p++;
263 w <<= 8;
264 w |= *k_p++;
265 w <<= 8;
266 w |= *k_p++;
267 w <<= 8;
268 w |= *k_p++;
271 kcs = kcs ^ i;
272 kcs = kcs ^ w;
274 progress ('C');
275 progress ('1');
276 if (info[7] == kcs)
277 progress ('+');
278 else
279 progress ('-');
282 /* Copy kernel to memstart */
283 s = (unsigned char *) info[0];
284 d = (unsigned char *) info[1];
285 e = (unsigned char *) (info[1] + info[2] + info[3]);
286 while(d != e){
287 *d = *s;
288 s++;
289 d++;
292 progress ('6');
294 /* Verify checksum. */
295 if (info[7])
297 int i = (info[2] + info[3]) / 4;
298 unsigned char* k_p = (unsigned char*) info[1];
299 unsigned long kcs = 0;
301 while (i--)
303 unsigned long w = 0;
305 w |= *k_p++;
306 w <<= 8;
307 w |= *k_p++;
308 w <<= 8;
309 w |= *k_p++;
310 w <<= 8;
311 w |= *k_p++;
314 kcs = kcs ^ i;
315 kcs = kcs ^ w;
317 progress ('C');
318 progress ('2');
319 if (info[7] == kcs)
320 progress ('+');
321 else
322 progress ('-');
325 /* Copy ramdisk to memory end. */
326 d = (unsigned char *) info[1] + info[5];
327 e = d - info[4];
328 s = s + info[4];
329 while(d != e){
330 s--;
331 d--;
332 *d = *s;
335 progress ('7');
337 #if 1 /* obsolete -- keep it for a while for backwards compatibility */
338 /* Let 0xfff00000 contain sum used for VTOP/PTOV in head.S. */
339 /* Also put it at kernel start since kernel copies the vectors
340 * to their proper location after modifying a few instructions.
342 #define KERNELBASE 0xC0000000
343 *((unsigned long *)0xfff00000) = info[1] - KERNELBASE;
344 *((unsigned long *) info[1]) = info[1] - KERNELBASE;
345 #endif
347 progress ('K');
349 register unsigned long r3 __asm("r3");
350 register unsigned long r4 __asm("r4");
351 register unsigned long r5 __asm("r5");
353 /* Make it easy to identify APUS in identify_machine. */
354 r3 = 0x61707573;
357 /* Memory start address. */
358 r4 = info[1];
360 /* Jump to kernel start. */
361 r5 = info[1] + 0xc;
362 __asm __volatile (
363 "mtlr 5 \n\t"
364 "blr \n\t"
365 : /* no outputs */
366 : "r" (r3), "r" (r4), "r" (r5));
369 /* fake a noreturn */
370 for (;;);
373 /* Play that jive... */
374 extern char setPR, setPRend;
375 void goSupervisor(void)
377 unsigned long *s, *d;
378 int len = ((int) &setPRend - (int) &setPR) / 4;
380 /* Copy code to TRAP entry */
381 d = (unsigned long*) 0xfff00700;
382 s = (unsigned long*) &setPR;
383 for(;len > 0;len--){
384 *d = *s;
385 d++;
386 s++;
389 PPCCacheFlushAll();
391 /* Execute code */
392 __asm__ (
393 "trap \n\t"
397 void progress_init (void)
399 const unsigned long *info;
400 unsigned long *mesg_base;
401 unsigned long* p;
402 info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
403 mesg_base = (unsigned long*) info[6];
404 p = mesg_base;
406 *p++ = 'SAVE';
407 *p++ = 'BOOT';
408 *p++ = (unsigned long) mesg_base;
409 *p++ = 0;
413 void progress (char c)
415 const unsigned long *info;
416 char progress_state;
417 char* progress_ptr;
418 unsigned long* mesg_base;
419 info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
421 mesg_base = (unsigned long*) info[6];
423 progress_ptr = mesg_base[3] + (char*)&mesg_base[4];
424 *progress_ptr = c;
425 mesg_base[3]++;
428 asm(
429 ".text\n"
430 ".align 4\n"
431 SYMBOL_NAME_STR(setPR) ":
432 /* Increase the return EA so we get to the next instruction */
433 mtsprg 1,1
434 mfsrr0 1
435 addi 1,1,4
436 mtsrr0 1
437 mfsprg 1,1
438 /* Fiddle the PR bit */
439 mfsrr1 0
440 rlwinm 0,0,0,18,16
441 mtsrr1 0
444 SYMBOL_NAME_STR(setPRend) ":
447 asm(
448 ".text\n"
449 ".align 4\n"
450 SYMBOL_NAME_STR(relocateEnd) ":