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);
46 extern char relocateEnd
;
48 void progress_init (void);
51 unsigned int main(void)
57 register unsigned long r0
__asm("r0");
58 register unsigned long r3
__asm("r3");
62 /* Wait for signal from m68k. */
67 if (PPCPort
=(void*) PPCGetTaskAttr(PPCTASKTAG_MSGPORT
))
69 progress ('w'); /* Wait */
71 progress ('r'); /* Received */
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. */
95 progress ('e'); /* Disable exception handling. */
99 "ori 3,3,0x8000 \n\t" /* MSR_EE */
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");
120 /* Stall a bit to allow the m68k to disable its MMU. */
123 for (i
= 0; i
< 30000; i
++);
125 progress ('!'); /* Done! PPC owns the Amiga. */
130 /* Disable caches. */
131 "mfspr 4,1008 \n\t" /* HID0 */
133 "ori 3,3,0xc000 \n\t" /* HID0_ICE|HID0_DCE */
137 "mtspr 1008,4 \n\t" /* HID0 */
138 /* Invalidate caches. */
139 "mfspr 4,1008 \n\t" /* HID0 */
141 "ori 3,3,0x0c00 \n\t" /* HID0_ICFI|HID0_DCFI */
145 "mtspr 1008,3 \n\t" /* HID0 */
146 "mtspr 1008,4 \n\t" /* HID0 */
148 /* Disable address translation and interrupts. */
151 "ori 3,3,0x0030 \n\t" /* MSR_IR|MSR_DR */
157 /* Put BATs in a safe state. (Enable bits are in the Upper word) */
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. */
184 /* Clear SDR1 & ASR. */
185 "mtspr 25,3 \n\t" /* SDR1 */
186 "mtspr 280,3 \n\t" /* ASR */
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
);
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;
225 /* Jump to relocated code. */
232 : "r" (info
[8]), "r" (ptr
)
237 /* fake a noreturn */
243 const unsigned long *info
;
244 unsigned char *s
, *d
, *e
;
248 /* Get info-ptr from CHIP_PTR. */
249 info
= (const unsigned long*) *((unsigned long*) CHIP_PTR
);
251 /* Verify checksum. */
254 int i
= (info
[2] + info
[3]) / 4;
255 unsigned char* k_p
= (unsigned char*) info
[0];
256 unsigned long kcs
= 0;
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]);
294 /* Verify checksum. */
297 int i
= (info
[2] + info
[3]) / 4;
298 unsigned char* k_p
= (unsigned char*) info
[1];
299 unsigned long kcs
= 0;
325 /* Copy ramdisk to memory end. */
326 d
= (unsigned char *) info
[1] + info
[5];
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
;
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. */
357 /* Memory start address. */
360 /* Jump to kernel start. */
366 : "r" (r3
), "r" (r4
), "r" (r5
));
369 /* fake a noreturn */
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
;
397 void progress_init (void)
399 const unsigned long *info
;
400 unsigned long *mesg_base
;
402 info
= (const unsigned long*) *((unsigned long*) CHIP_PTR
);
403 mesg_base
= (unsigned long*) info
[6];
408 *p
++ = (unsigned long) mesg_base
;
413 void progress (char c
)
415 const unsigned long *info
;
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];
431 SYMBOL_NAME_STR(setPR
) ":
432 /* Increase the return EA so we get to the next instruction */
438 /* Fiddle the PR bit */
444 SYMBOL_NAME_STR(setPRend
) ":
450 SYMBOL_NAME_STR(relocateEnd
) ":