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
76          */
77         for (i = 0; i < 150000; i++);
79         /* Reset everything but the CPU, then restart
80          * at the ROM exception vector
81          */
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]);
104         }
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;
140         
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
153  */
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,
193         };
194         const struct KernelBSS kbss[2] = {
195                 {
196                         .addr = &_bss,
197                         .len = &_bss_end - &_bss,
198                 }, {
199                         .addr = 0,
200                         .len = 0,
201                 }
202         };
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
212          */
213         DebugInit();
214         DebugPuts("[reset]\n");
216         /* Fill exception table with a stub that will
217          * reset the ROM
218          */
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
234          */
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.
264          */
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();