only bring in as many sdl things as are strictly necessary
[tangerine.git] / arch / ppc-sam440 / exec / exec_init.c
blob85a7a5345692cee1e0ad24db7a6113c44195d604
1 #include <asm/amcc440.h>
2 #include <aros/libcall.h>
3 #include <aros/asmcall.h>
4 #include <aros/arossupportbase.h>
5 #include <exec/execbase.h>
6 #include <exec/types.h>
7 #include <exec/resident.h>
8 #include <dos/bptr.h>
9 #include <dos/dosextens.h>
10 #include <hardware/custom.h>
11 #include <hardware/intbits.h>
13 #include <proto/exec.h>
14 #include <proto/kernel.h>
16 #include <stdarg.h>
17 #include <strings.h>
18 #include <inttypes.h>
20 #include "etask.h"
21 #include "exec_intern.h"
22 #include "exec_util.h"
24 #include "../kernel/kernel_intern.h"
26 int exec_main(struct TagItem *msg, void *entry);
27 extern const APTR Exec_FuncTable[];
28 extern ULONG Exec_MakeFunctions(APTR, APTR, APTR, APTR);
29 void exec_DefaultTaskExit();
30 IPTR **exec_RomTagScanner(struct TagItem *msg);
31 extern struct Library * PrepareAROSSupportBase (void);
33 AROS_UFP5(void, SoftIntDispatch,
34 AROS_UFPA(ULONG, intReady, D1),
35 AROS_UFPA(struct Custom *, custom, A0),
36 AROS_UFPA(IPTR, intData, A1),
37 AROS_UFPA(IPTR, intCode, A5),
38 AROS_UFPA(struct ExecBase *, SysBase, A6));
40 AROS_UFP5S(void, IntServer,
41 AROS_UFPA(ULONG, intMask, D0),
42 AROS_UFPA(struct Custom *, custom, A0),
43 AROS_UFPA(struct List *, intList, A1),
44 AROS_UFPA(APTR, intCode, A5),
45 AROS_UFPA(struct ExecBase *, SysBase, A6));
47 const char exec_name[] = "exec.library";
48 const char exec_idstring[] = "$VER: exec 41.11 (16.12.2000)\r\n";
49 const char exec_chipname[] = "Chip Memory";
50 const char exec_fastname[] = "Fast Memory";
52 const short exec_Version = 41;
53 const short exec_Revision = 11;
55 const struct __attribute__((section(".text"))) Resident Exec_resident =
57 RTC_MATCHWORD, /* Magic value used to find resident */
58 &Exec_resident, /* Points to Resident itself */
59 &Exec_resident+1, /* Where could we find next Resident? */
60 0, /* There are no flags!! */
61 41, /* Version */
62 NT_LIBRARY, /* Type */
63 126, /* Very high startup priority. */
64 (STRPTR)exec_name, /* Pointer to name string */
65 (STRPTR)exec_idstring, /* Ditto */
66 exec_main /* Library initializer (for exec this value is irrelevant since we've jumped there at the begining to bring the system up */
69 int exec_main(struct TagItem *msg, void *entry)
71 struct ExecBase *SysBase = NULL;
72 uintptr_t lowmem = 0;
73 int i;
75 D(bug("[exec] AROS for Sam440 - The AROS Research OS\n"));
77 /* Prepare the exec base */
79 ULONG negsize = LIB_VECTSIZE; /* size of vector table */
80 void **fp = Exec_FuncTable; //LIBFUNCTABLE; /* pointer to a function in the table */
82 D(bug("[exec] Preparing the ExecBase...\n"));
84 /* Calculate the size of the vector table */
85 while (*fp++ != (APTR) -1) negsize += LIB_VECTSIZE;
87 /* Align the offset for SysBase to the cache line */
88 negsize = (negsize + 31) & ~31;
90 /* Get the lowest usable memory location */
91 lowmem = (krnGetTagData(KRN_KernelHighest, 0, msg) + 0xffff) & 0xffff0000;
93 /* And now let's have the SysBase */
94 SysBase = (struct ExecBase *)(lowmem + negsize);
95 wrspr(SPRG5, SysBase);
96 lowmem = (lowmem + negsize + sizeof(struct ExecBase) + 4095) & ~4095;
98 D(bug("[exec] ExecBase at %08x\n", SysBase));
100 D(bug("[exec] Clearing ExecBase\n"));
102 /* How about clearing most of ExecBase structure? */
103 bzero(&SysBase->IntVects[0], sizeof(struct ExecBase) - offsetof(struct ExecBase, IntVects[0]));
105 SysBase->KickMemPtr = NULL;
106 SysBase->KickTagPtr = NULL;
107 SysBase->KickCheckSum = NULL;
110 * Now everything is prepared to store ExecBase at the location 4UL and set
111 * it complement in ExecBase structure
114 D(bug("[exec] Initializing library...\n"));
116 SysBase->ChkBase = ~(ULONG)SysBase;
118 /* Store memory configuration */
119 SysBase->MaxLocMem = (IPTR)0; //locmem;
120 SysBase->MaxExtMem = (APTR)0; //extmem;
123 * Initialize exec lists. This is done through information table which consist
124 * of offset from begining of ExecBase and type of the list.
126 NEWLIST(&SysBase->MemList);
127 SysBase->MemList.lh_Type = NT_MEMORY;
128 NEWLIST(&SysBase->ResourceList);
129 SysBase->ResourceList.lh_Type = NT_RESOURCE;
130 NEWLIST(&SysBase->DeviceList);
131 SysBase->DeviceList.lh_Type = NT_DEVICE;
132 NEWLIST(&SysBase->LibList);
133 SysBase->LibList.lh_Type = NT_LIBRARY;
134 NEWLIST(&SysBase->PortList);
135 SysBase->PortList.lh_Type = NT_MSGPORT;
136 NEWLIST(&SysBase->TaskReady);
137 SysBase->TaskReady.lh_Type = NT_TASK;
138 NEWLIST(&SysBase->TaskWait);
139 SysBase->TaskWait.lh_Type = NT_TASK;
140 NEWLIST(&SysBase->IntrList);
141 SysBase->IntrList.lh_Type = NT_INTERRUPT;
142 NEWLIST(&SysBase->SemaphoreList);
143 SysBase->SemaphoreList.lh_Type = NT_SIGNALSEM;
144 NEWLIST(&SysBase->ex_MemHandlers);
146 for (i=0; i<5; i++)
148 NEWLIST(&SysBase->SoftInts[i].sh_List);
149 SysBase->SoftInts[i].sh_List.lh_Type = NT_SOFTINT;
153 * Exec.library initializer. Prepares exec.library for future use. All
154 * lists have to be initialized, some values from ROM are copied.
157 SysBase->TaskTrapCode = NULL; //exec_DefaultTrap;
158 SysBase->TaskExceptCode = NULL; //exec_DefaultTrap;
159 SysBase->TaskExitCode = exec_DefaultTaskExit;
160 SysBase->TaskSigAlloc = 0x0000ffff;
161 SysBase->TaskTrapAlloc = 0x8000;
163 /* Prepare values for execBase (like name, type, pri and other) */
165 SysBase->LibNode.lib_Node.ln_Type = NT_LIBRARY;
166 SysBase->LibNode.lib_Node.ln_Pri = 0;
167 SysBase->LibNode.lib_Node.ln_Name = (char *)exec_name;
168 SysBase->LibNode.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
169 SysBase->LibNode.lib_PosSize = sizeof(struct ExecBase);
170 SysBase->LibNode.lib_OpenCnt = 1;
171 SysBase->LibNode.lib_IdString = (char *)exec_idstring;
172 SysBase->LibNode.lib_Version = exec_Version;
173 SysBase->LibNode.lib_Revision = exec_Revision;
175 SysBase->Quantum = 4;
176 SysBase->VBlankFrequency = 50;
177 SysBase->PowerSupplyFrequency = 1;
179 /* Build the jumptable */
180 SysBase->LibNode.lib_NegSize =
181 Exec_MakeFunctions(SysBase, Exec_FuncTable, NULL, SysBase);
183 SumLibrary((struct Library *)SysBase);
185 D(bug("[exec] Adding memory\n"));
187 AddMemList(0x01000000 - lowmem,
188 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL | MEMF_24BITDMA,
189 -10,
190 (APTR)lowmem,
191 (STRPTR)exec_chipname);
193 AddMemList((512 - 16) * 1024*1024,
194 MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL,
196 (APTR)0x01000000,
197 (STRPTR)exec_fastname);
199 SumLibrary((struct Library *)SysBase);
201 Enqueue(&SysBase->LibList,&SysBase->LibNode.lib_Node);
203 SysBase->DebugAROSBase = PrepareAROSSupportBase();
205 for (i=0; i<16; i++)
207 if( (1<<i) & (INTF_PORTS|INTF_COPER|INTF_VERTB|INTF_EXTER|INTF_SETCLR))
209 struct Interrupt *is;
210 struct SoftIntList *sil;
211 is = AllocMem
213 sizeof(struct Interrupt) + sizeof(struct SoftIntList),
214 MEMF_CLEAR | MEMF_PUBLIC
216 if( is == NULL )
218 D(bug("[exec] ERROR: Cannot install Interrupt Servers!\n"));
220 sil = (struct SoftIntList *)((struct Interrupt *)is + 1);
222 is->is_Code = &IntServer;
223 is->is_Data = sil;
224 NEWLIST((struct List *)sil);
225 SetIntVector(i,is);
227 else
229 struct Interrupt *is;
230 switch (i)
232 case INTB_SOFTINT :
233 is = AllocMem
235 sizeof(struct Interrupt),
236 MEMF_CLEAR | MEMF_PUBLIC
238 if (is == NULL)
240 D(bug("[exec] Error: Cannot install Interrupt Servers!\n"));
241 // Alert(AT_DeadEnd | AN_IntrMem);
243 is->is_Node.ln_Type = NT_SOFTINT; //INTERRUPT;
244 is->is_Node.ln_Pri = 0;
245 is->is_Node.ln_Name = "SW Interrupt Dispatcher";
246 is->is_Data = NULL;
247 is->is_Code = (void *)SoftIntDispatch;
248 SetIntVector(i,is);
249 break;
254 /* Set int disable level to -1 */
255 SysBase->TDNestCnt = -1;
256 SysBase->IDNestCnt = -1;
258 /* Now it's time to calculate exec checksum. It will be used
259 * in future to distinguish whether we'd had proper execBase
260 * before restart */
262 UWORD sum=0, *ptr = &SysBase->SoftVer;
263 int i=((IPTR)&SysBase->IntVects[0] - (IPTR)&SysBase->SoftVer) / 2,
266 /* Calculate sum for every static part from SoftVer to ChkSum */
267 for (j=0;j < i;j++)
269 sum+=*(ptr++);
272 SysBase->ChkSum = ~sum;
275 /* Create boot task. Sigh, we actually create a Process sized Task,
276 since DOS needs to call things which think it has a Process and
277 we don't want to overwrite memory with something strange do we?
279 We do this until at least we can boot dos more cleanly.
282 struct Task *t;
283 struct MemList *ml;
285 ml = (struct MemList *)AllocMem(sizeof(struct MemList), MEMF_PUBLIC|MEMF_CLEAR);
286 t = (struct Task *) AllocMem(sizeof(struct Process), MEMF_PUBLIC|MEMF_CLEAR);
288 if( !ml || !t )
290 D(bug("[exec] ERROR: Cannot create Boot Task!\n"));
292 ml->ml_NumEntries = 1;
293 ml->ml_ME[0].me_Addr = t;
294 ml->ml_ME[0].me_Length = sizeof(struct Process);
296 NEWLIST(&t->tc_MemEntry);
297 NEWLIST(&((struct Process *)t)->pr_MsgPort.mp_MsgList);
299 /* It's the boot process that RunCommand()s the boot shell, so we
300 must have this list initialized */
301 NEWLIST((struct List *)&((struct Process *)t)->pr_LocalVars);
303 AddHead(&t->tc_MemEntry,&ml->ml_Node);
305 t->tc_Node.ln_Name = exec_name;
306 t->tc_Node.ln_Pri = 0;
307 t->tc_Node.ln_Type = NT_TASK;
308 t->tc_State = TS_RUN;
309 t->tc_SigAlloc = 0xFFFF;
310 t->tc_SPLower = 0; /* This is the system's stack */
311 t->tc_SPUpper = (APTR)~0UL;
312 t->tc_Flags |= TF_ETASK;
314 if (t->tc_Flags & TF_ETASK)
316 t->tc_UnionETask.tc_ETask = AllocVec
318 sizeof(struct IntETask),
319 MEMF_ANY|MEMF_CLEAR
322 if (!t->tc_UnionETask.tc_ETask)
324 D(bug("[exec] Not enough memory for first task\n"));
327 /* Initialise the ETask data. */
328 InitETask(t, t->tc_UnionETask.tc_ETask);
330 GetIntETask(t)->iet_Context = AllocTaskMem(t
331 , SIZEOF_ALL_REGISTERS
332 , MEMF_PUBLIC|MEMF_CLEAR
335 if (!GetIntETask(t)->iet_Context)
337 D(bug("[exec] Not enough memory for first task\n"));
341 SysBase->ThisTask = t;
344 D(bug("[exec] Done. SysBase->ThisTask = %08p\n", SysBase->ThisTask));
346 SysBase->TDNestCnt++;
348 /* Scan for valid RomTags */
349 SysBase->ResModules = exec_RomTagScanner(msg);
351 D(bug("[exec] InitCode(RTF_SINGLETASK)\n"));
352 InitCode(RTF_SINGLETASK, 0);
354 D(bug("[exec] InitCode(RTF_COLDSTART)\n"));
355 InitCode(RTF_COLDSTART, 0);
357 D(bug("[exec] I should never get here...\n"));
362 * RomTag scanner.
364 * This function scans kernel for existing Resident modules. If two modules
365 * with the same name are found, the one with higher version or priority wins.
367 * After building list of kernel modules, the KickTagPtr and KickMemPtr are
368 * checksummed. If checksum is proper and all memory pointed in KickMemPtr may
369 * be allocated, then all modules from KickTagPtr are added to RT list
371 * Afterwards the proper RomTagList is created (see InitCode() for details) and
372 * memory after list and nodes is freed.
375 struct rt_node
377 struct Node node;
378 struct Resident *module;
382 void exec_DefaultTaskExit()
384 struct ExecBase *SysBase = getSysBase();
385 RemTask(SysBase->ThisTask);
388 IPTR **exec_RomTagScanner(struct TagItem *msg)
390 struct ExecBase *SysBase = getSysBase();
392 struct List rtList; /* List of modules */
393 UWORD *ptr = (UWORD*)(krnGetTagData(KRN_KernelLowest, 0, msg) + 0xff000000); /* Start looking here */
394 UWORD *maxptr = (UWORD*)(krnGetTagData(KRN_KernelHighest, 0, msg) + 0xff000000);
395 struct Resident *res; /* module found */
397 int i;
398 IPTR **RomTag;
400 /* Initialize list */
401 NEWLIST(&rtList);
403 D(bug("[exec] Resident modules (addr: pri version name):\n"));
405 /* Look in whole kernel for resident modules */
408 /* Do we have RTC_MATCHWORD? */
409 if (*ptr == RTC_MATCHWORD)
411 /* Yes, assume we have Resident */
412 res = (struct Resident *)ptr;
414 /* Does rt_MatchTag point to Resident? */
415 if (res == res->rt_MatchTag)
417 /* Yes, it is Resident module */
418 struct rt_node *node;
420 /* Check if there is module with such name already */
421 node = (struct rt_node*)FindName(&rtList, res->rt_Name);
422 if (node)
424 /* Yes, there was such module. It it had lower pri then replace it */
425 if (node->node.ln_Pri <= res->rt_Pri)
427 /* If they have the same Pri but new one has higher Version, replace */
428 if ((node->node.ln_Pri == res->rt_Pri) &&
429 (node->module->rt_Version < res->rt_Version))
431 node->node.ln_Pri = res->rt_Pri;
432 node->module = res;
436 else
438 /* New module. Allocate some memory for it */
439 node = (struct rt_node *)
440 AllocMem(sizeof(struct rt_node),MEMF_PUBLIC|MEMF_CLEAR);
442 if (node)
444 node->node.ln_Name = res->rt_Name;
445 node->node.ln_Pri = res->rt_Pri;
446 node->module = res;
448 Enqueue(&rtList,(struct Node*)node);
451 ptr+=sizeof(struct Resident)/sizeof(UWORD);
452 continue;
456 /* Get next address... */
457 ptr++;
458 } while (ptr < maxptr);
461 * By now we have valid (and sorted) list of kernel resident modules.
463 * Now, we will have to analyze used-defined RomTags (via KickTagPtr and
464 * KickMemPtr)
466 #warning "TODO: Implement external modules!"
468 * Everything is done now. Allocate buffer for normal RomTag and convert
469 * list to RomTag
472 ListLength(&rtList,i); /* Get length of the list */
474 RomTag = AllocMem((i+1)*sizeof(IPTR),MEMF_PUBLIC | MEMF_CLEAR);
476 if (RomTag)
478 int j;
479 struct rt_node *n;
481 for (j=0; j<i; j++)
483 n = (struct rt_node *)RemHead(&rtList);
484 D(bug("[exec] + 0x%08lx: %4d %3d \"%s\"\n",
485 n->module,
486 n->node.ln_Pri,
487 n->module->rt_Version,
488 n->node.ln_Name));
489 RomTag[j] = (IPTR*)n->module;
490 FreeMem(n, sizeof(struct rt_node));
492 RomTag[i] = 0;
495 return RomTag;
498 AROS_LH1(struct ExecBase *, open,
499 AROS_LHA(ULONG, version, D0),
500 struct ExecBase *, SysBase, 1, Exec)
502 AROS_LIBFUNC_INIT
504 /* I have one more opener. */
505 SysBase->LibNode.lib_OpenCnt++;
506 return SysBase;
508 AROS_LIBFUNC_EXIT
511 AROS_LH0(BPTR, close,
512 struct ExecBase *, SysBase, 2, Exec)
514 AROS_LIBFUNC_INIT
516 /* I have one fewer opener. */
517 SysBase->LibNode.lib_OpenCnt--;
518 return 0;
519 AROS_LIBFUNC_EXIT
522 AROS_LH0I(int, null,
523 struct ExecBase *, SysBase, 4, Exec)
525 AROS_LIBFUNC_INIT
526 return 0;
527 AROS_LIBFUNC_EXIT
531 We temporarily redefine kprintf() so we use the real version in case
532 we have one of these two fn's called before AROSSupportBase is ready.
535 #undef kprintf
536 #undef rkprintf
537 #undef vkprintf
539 static int __kprintf(const UBYTE *fmt, ...)
541 va_list ap;
542 int result = 0;
543 void *KernelBase = getKernelBase();
545 if (KernelBase)
547 va_start(ap,fmt);
548 result = KrnBug(fmt, ap);
549 va_end(ap);
551 return result;
554 static int __vkprintf(const UBYTE *fmt, va_list args)
556 void *KernelBase = getKernelBase();
558 if (KernelBase)
559 return KrnBug(fmt, args);
560 else
561 return 0;
564 static int __rkprintf(const STRPTR mainSystem, const STRPTR subSystem, int level, const UBYTE *fmt, ...)
566 va_list ap;
567 int result = 0;
568 void *KernelBase = getKernelBase();
570 if (KernelBase)
572 va_start(ap,fmt);
573 result = KrnBug(fmt, ap);
574 va_end(ap);
576 return result;
579 struct Library * PrepareAROSSupportBase(void)
581 struct ExecBase *SysBase = getSysBase(); //*(struct ExecBase **)4UL;
583 struct AROSSupportBase *AROSSupportBase =
584 AllocMem(sizeof(struct AROSSupportBase), MEMF_CLEAR);
586 AROSSupportBase->kprintf = (void *)__kprintf;
587 AROSSupportBase->rkprintf = (void *)__rkprintf;
588 AROSSupportBase->vkprintf = (void *)__vkprintf;
590 NEWLIST(&AROSSupportBase->AllocMemList);
592 #warning "FIXME Add code to read in the debug options"
594 return (struct Library *)AROSSupportBase;
597 /* IntServer:
598 This interrupt handler will send an interrupt to a series of queued
599 interrupt servers. Servers should return D0 != 0 (Z clear) if they
600 believe the interrupt was for them, and no further interrupts will
601 be called. This will only check the value in D0 for non-m68k systems,
602 however it SHOULD check the Z-flag on 68k systems.
604 Hmm, in that case I would have to separate it from this file in order
605 to replace it...
607 AROS_UFH5S(void, IntServer,
608 AROS_UFHA(ULONG, intMask, D0),
609 AROS_UFHA(struct Custom *, custom, A0),
610 AROS_UFHA(struct List *, intList, A1),
611 AROS_UFHA(APTR, intCode, A5),
612 AROS_UFHA(struct ExecBase *, SysBase, A6))
614 AROS_USERFUNC_INIT
616 struct Interrupt * irq;
618 ForeachNode(intList, irq)
620 if( AROS_UFC4(int, irq->is_Code,
621 AROS_UFCA(struct Custom *, custom, A0),
622 AROS_UFCA(APTR, irq->is_Data, A1),
623 AROS_UFCA(APTR, irq->is_Code, A5),
624 AROS_UFCA(struct ExecBase *, SysBase, A6)
626 break;
629 AROS_USERFUNC_EXIT
632 void _aros_not_implemented(char *string) {}