arch/m68k-amiga/boot: Actually check for 68000vs68010
[AROS.git] / arch / m68k-amiga / boot / start.c
blob92b2484a8a4148b08c7f52badd907b21ae5028e4
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: m68k-amiga bootstrap to exec.
6 Lang: english
7 */
9 #include <aros/kernel.h>
10 #include <exec/resident.h>
11 #include <exec/execbase.h>
12 #include <exec/memory.h>
13 #include <proto/exec.h>
15 #include "exec_intern.h"
16 #include "kernel_romtags.h"
18 #include "amiga_hwreg.h"
19 #include "amiga_irq.h"
21 extern const struct Resident Exec_resident;
23 extern void __clear_bss(const struct KernelBSS *bss);
25 #define RGB(r,g,b) ((((r) & 0xf) << 8) | (((g) & 0xf) << 4) | (((b) & 0xf) << 0))
27 #define CODE_ROM_CHECK RGB( 4, 4, 4)
28 #define CODE_RAM_CHECK RGB( 9, 9, 9)
29 #define CODE_EXEC_CHECK RGB( 9, 0, 9)
30 #define CODE_TRAP_FAIL RGB(12, 12, 0)
32 static void Exec_ScreenCode(UWORD code)
34 reg_w(BPLCON0, 0x0200);
35 reg_w(BPL1DAT, 0x0000);
36 reg_w(COLOR00, code);
39 void DebugInit()
41 /* Set the debug UART to 9600 */
42 reg_w(SERPER, SERPER_BAUD(SERPER_BASE_PAL, 9600));
45 int DebugPutChar(register int chr)
47 while ((reg_r(SERDATR) & SERDATR_TBE) == 0);
49 /* Output a char to the debug UART */
50 reg_w(SERDAT, SERDAT_STP8 | SERDAT_DB8(chr));
52 return 1;
55 int DebugGetChar(void)
57 while ((reg_r(SERDATR) & SERDATR_RBF) == 0);
59 return SERDATR_DB8_of(reg_r(SERDATR));
62 #ifdef USE_GDBSTUB
63 #define mc68020
64 #include "m68k-gdbstub.c"
65 #endif
67 static __attribute__((interrupt)) void Exec_FatalException(void)
69 volatile int i;
71 Exec_ScreenCode(CODE_TRAP_FAIL);
73 /* FIXME: Idle loop delay
74 * We should really wait for a number of
75 * verical retrace intervals
77 for (i = 0; i < 150000; i++);
79 /* Reset everything but the CPU, then restart
80 * at the ROM exception vector
82 asm("reset\n"
83 "move.l #4,%a0\n"
84 "jmp (%a0)\n");
87 static void DebugPuts(register const char *buff)
89 for (; *buff != 0; buff++)
90 DebugPutChar(*buff);
93 extern void *_ram_start;
94 #define MEM_START ((ULONG)(&_ram_start))
95 #define MEM_SIZE (0x00200000-MEM_START)
97 void DebugPutHex(const char *what, ULONG val)
99 int i;
100 DebugPuts(what);
101 DebugPuts(": ");
102 for (i = 0; i < 8; i ++) {
103 DebugPutChar("0123456789abcdef"[(val >> (28 - (i * 4))) & 0xf]);
105 DebugPutChar('\n');
108 extern void __attribute__((interrupt)) Exec_Supervisor_Trap (void);
110 void __attribute__((interrupt)) cpu_detect_trap(void);
111 asm (
112 " .text\n"
113 " .globl cpu_detect_trap\n"
114 "cpu_detect_trap:\n"
115 " addq.l #2,%sp@(2)\n"
116 " move.w %sr,%d0\n"
117 " rte\n"
120 /* Detect 68000 vs 68010/68020 */
121 ULONG cpu_detect(void)
123 volatile APTR *trap = (NULL + 8);
124 APTR old_trap6;
125 UWORD ret;
127 old_trap6 = trap[6];
128 trap[6] = cpu_detect_trap;
129 asm volatile (
130 "move.w %%sr,%%d0\n"
131 "move.w %%d0,%0\n"
132 : "=m" (ret) : : "%d0" );
133 trap[6] = old_trap6;
135 if (ret & 0x2000)
136 return AFF_68010;
137 else
138 return 0;
141 #if (AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT)
143 * Create a call stub like so:
144 * foo:
145 * movem.l %d0-%d1/%a0-%a1,%sp@-
146 * 0x48e7 0xc0c0
147 * jsr AROS_SLIB_ENTRY(funcname, libname)
148 * 0x4eb9 .... ....
149 * movem.l %sp@+,%d0-%d1/%d0-%a1
150 * 0x4cdf 0x0303
151 * rts
152 * 0x4e75
154 #define PRESERVE_ALL(lib, libname, funcname, funcid) \
155 do { \
156 UWORD *asmcall; \
157 IPTR func = (IPTR)__AROS_GETVECADDR(lib, funcid); \
158 asmcall = AllocMem(8 * sizeof(UWORD), MEMF_PUBLIC); \
159 /* NOTE: 'asmcall' will intentionally never be freed */ \
160 asmcall[0] = 0x48e7; \
161 asmcall[1] = 0xc0c0; \
162 asmcall[2] = 0x4eb9; \
163 asmcall[3] = (func >> 16) & 0xffff; \
164 asmcall[4] = (func >> 0) & 0xffff; \
165 asmcall[5] = 0x4cdf; \
166 asmcall[6] = 0x0303; \
167 asmcall[7] = 0x4e75; \
168 /* Insert into the library's jumptable */ \
169 __AROS_SETVECADDR(lib, funcid, asmcall); \
170 } while (0)
171 #else
172 /* Not needed on EABI */
173 #define PRESERVE_ALL(lib, libname, funcname, funcid) do { } while (0)
174 #endif
176 void start(void)
178 extern void *_bss;
179 extern void *_bss_end;
180 extern void *_ss_stack_upper;
181 extern void *_ss_stack_lower;
182 APTR *tmp;
183 int i;
184 UWORD *kickrom[] = {
185 (UWORD *)0x00f80000,
186 (UWORD *)0x01000000,
187 (UWORD *)0x00f00000,
188 (UWORD *)0x00f80000,
189 (UWORD *)0x00e00000,
190 (UWORD *)0x00e80000,
191 (UWORD *)~0,
192 (UWORD *)~0,
194 const struct KernelBSS kbss[2] = {
196 .addr = &_bss,
197 .len = &_bss_end - &_bss,
198 }, {
199 .addr = 0,
200 .len = 0,
204 struct ExecBase *sysBase;
205 struct MemChunk *mc;
206 struct MemHeader ChipRAM;
207 struct MemHeader *mh = &ChipRAM;
209 *((APTR *)(NULL + 0x4)) = NULL;
211 /* Let the world know we exist
213 DebugInit();
214 DebugPuts("[reset]\n");
216 /* Fill exception table with a stub that will
217 * reset the ROM
219 tmp = (APTR *)(NULL + 0x8);
220 for (i = 0; i < 46; i++)
221 tmp[i] = Exec_FatalException;
223 /* Clear the BSS */
224 __clear_bss(&kbss[0]);
225 DebugPuts("[bss clear]\n");
227 #ifdef USE_GDBSTUB
228 /* Must be after the BSS clear! */
229 gdbstub();
230 #endif
232 /* Set privilige violation trap - we
233 * need this to support the Exec/Supervisor call
235 tmp[6] = Exec_Supervisor_Trap;
237 Exec_ScreenCode(CODE_RAM_CHECK);
239 DebugPuts("[prep SysBase]\n");
240 Exec_ScreenCode(CODE_EXEC_CHECK);
241 mc = (struct MemChunk *)(NULL + MEM_START);
242 mc->mc_Next = NULL;
243 mc->mc_Bytes = MEM_SIZE;
245 mh->mh_Node.ln_Succ = NULL;
246 mh->mh_Node.ln_Pred = NULL;
247 mh->mh_Node.ln_Type = NT_MEMORY;
248 mh->mh_Node.ln_Name = "chip memory";
249 mh->mh_Node.ln_Pri = -5;
250 mh->mh_Attributes = MEMF_CHIP | MEMF_PUBLIC | MEMF_LOCAL | MEMF_24BITDMA | MEMF_KICK;
251 mh->mh_First = mc;
252 mh->mh_Lower = (APTR)mc;
253 mh->mh_Upper = ((APTR)mc) + mc->mc_Bytes;
254 mh->mh_Free = mc->mc_Bytes;
255 sysBase = PrepareExecBase(mh, NULL, NULL);
256 DebugPutHex("PrepareExecBase [ret]",(ULONG)sysBase);
257 *((APTR *)(NULL + 0x4)) = sysBase;
258 DebugPuts("[init SysBase]\n");
260 /* Fix up functions that need 'preserves all registers'
261 * semantics. This AllocMem()s a little wrapper routine
262 * that pushes the %d0-%d1/%a0-%a1 registers before
263 * calling the routine.
265 #ifdef THESE_ARE_KNOWN_SAFE_ASM_ROUTINES
266 PERSERVE_ALL(SysBase, Exec, Disable, 20);
267 PERSERVE_ALL(SysBase, Exec, Enable, 21);
268 PRESERVE_ALL(SysBase, Exec, Forbid, 22);
269 #endif
270 PRESERVE_ALL(SysBase, Exec, Permit, 23);
271 PRESERVE_ALL(SysBase, Exec, ObtainSemaphore, 94);
272 PRESERVE_ALL(SysBase, Exec, ReleaseSemaphore, 95);
273 PRESERVE_ALL(SysBase, Exec, ObtainSemaphoreShared, 113);
276 sysBase->SysStkUpper = (APTR)(&_ss_stack_upper)-1;
277 sysBase->SysStkLower = (APTR)&_ss_stack_lower;
279 /* Determine CPU model */
280 sysBase->AttnFlags |= cpu_detect();
282 /* Initialize IRQ subsystem */
283 AmigaIRQInit(sysBase);
285 /* Scan for all other ROM Tags */
286 sysBase->ResModules = krnRomTagScanner(sysBase, kickrom);
287 DebugPuts("[start] InitCode(RTF_SINGLETASK, 0)\n");
288 InitCode(RTF_SINGLETASK, 0);
290 /* We shouldn't get here */
291 DebugPuts("[DOS Task failed to start]\n");
292 for (;;)
293 breakpoint();