revert between 56095 -> 55830 in arch
[AROS.git] / arch / ppc-chrp / efika / kernel / kernel_init.c
blobe6eeeba64dd458119fc20f9981a26a8492b940d9
1 /*
2 Copyright © 2008-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 1
8 #include <aros/kernel.h>
9 #include <aros/symbolsets.h>
10 #include <exec/memory.h>
11 #include <exec/tasks.h>
12 #include <exec/alerts.h>
13 #include <exec/execbase.h>
14 #include <asm/io.h>
15 #include <asm/mpc5200b.h>
16 #include <proto/kernel.h>
17 #include <strings.h>
19 #include <proto/exec.h>
21 #include "exec_intern.h"
22 #include "etask.h"
24 #include "kernel_intern.h"
25 #include LC_LIBDEFS_FILE
26 #include "syscall.h"
27 #include "memory.h"
29 static void __attribute__((used)) kernel_cstart(struct TagItem *msg);
30 struct OFWNode *krnCopyOFWTree(struct OFWNode *orig);
31 int exec_main(struct TagItem *msg, void *entry);
33 asm(".section .aros.init,\"ax\"\n\t"
34 ".globl start\n\t"
35 ".type start,@function\n"
36 "start:\n\t"
38 "mr %r29,%r3\n\t" /* Keep it for later */
40 "li %r0,0x2000\n\t"
41 "mtmsr %r0\n\t" /* Disable address translation */
42 "sync; isync\n\t"
44 /* Set up BAT registers with a very simple map. */
45 /* IBAT0 virtual 0xff800000 into physical 0x07800000, size 8MB, read only, super only, cached */
46 "lis %r0, 0xff80; "
47 "ori %r0, %r0, 0x2 | 0xfc; "
48 "mtspr 528,%r0; " /* Clear all BAT entries */
49 "lis %r0, 0x0780;"
50 "ori %r0,%r0,0x01 | 0x10; "
51 "mtspr 529, %r0;"
53 /* IBAT1 virtual 0x07800000 into physical 0x07800000, size 8MB, read only, super only, cached */
54 "lis %r0, 0x0780; "
55 "ori %r0, %r0, 0x2 | 0xfc; "
56 "mtspr 530,%r0; " /* Clear all BAT entries */
57 "lis %r0, 0x0780;"
58 "ori %r0,%r0,0x01 | 0x10; "
59 "mtspr 531, %r0;"
61 /* Clear IBAT1 - IBAT7 */
62 "lis %r0, 0; "
63 "mtspr 532, %r0;"
64 "mtspr 533, %r0;"
65 "mtspr 534, %r0;"
66 "mtspr 535, %r0;"
68 "mtspr 560, %r0;"
69 "mtspr 561, %r0;"
70 "mtspr 562, %r0;"
71 "mtspr 563, %r0;"
72 "mtspr 564, %r0;"
73 "mtspr 565, %r0;"
74 "mtspr 566, %r0;"
75 "mtspr 567, %r0;"
77 /* DBAT0 virtual 0xff000000, physical 0x07000000, size 8MB, read write, super only, cached */
78 "lis %r0, 0xff00; "
79 "ori %r0, %r0, 0x2 | 0xfc; "
80 "mtspr 536,%r0; " /* Clear all BAT entries */
81 "lis %r0, 0x0700;"
82 "ori %r0,%r0,0x02 | 0x10; "
83 "mtspr 537, %r0;"
84 /* DBAT1 virtual 0xff800000, physical 0x07800000, size 8MB, read only, super only, cached */
85 "lis %r0, 0xff80; "
86 "ori %r0, %r0, 0x2 | 0xfc; "
87 "mtspr 538,%r0; " /* Clear all BAT entries */
88 "lis %r0, 0x0780;"
89 "ori %r0,%r0,0x01 | 0x10; "
90 "mtspr 539, %r0;"
91 /* DBAT2 virtual 0x00000000, physical 0x00000000, 128MB, read write, super only, cached */
92 "lis %r0, 0x0000; "
93 "ori %r0, %r0, 0x2 | 0x1ffc; "
94 "mtspr 540,%r0; " /* Clear all BAT entries */
95 "lis %r0, 0x0000;"
96 "ori %r0,%r0,0x02 | 0x10; "
97 "mtspr 541, %r0;"
98 /* DBAT3 virtual 0xf0000000, physical 0xf0000000, 128KB, read write, super only, not cached */
99 "lis %r0, 0xf000; "
100 "ori %r0, %r0, 0x3; "
101 "mtspr 542,%r0; "
102 "lis %r0, 0xf000;"
103 "ori %r0,%r0,0x0a | 0x20; "
104 "mtspr 543, %r0;"
106 /* Clear DBAT3 - DBAT7 */
107 "lis %r0, 0; "
109 "mtspr 568, %r0;"
110 "mtspr 569, %r0;"
111 "mtspr 570, %r0;"
112 "mtspr 571, %r0;"
113 "mtspr 572, %r0;"
114 "mtspr 573, %r0;"
115 "mtspr 574, %r0;"
116 "mtspr 575, %r0;"
118 "mttbl %r0; mttbu %r0; mttbl %r0;"
120 /* Enable address translation again. All accesses will be done through BAT registers */
121 "li %r0, 0x2030;"
122 "mtmsr %r0;sync;isync;"
124 "lis %r9,tmp_stack_end@ha\n\t" /* Use temporary stack while clearing BSS */
125 "lwz %r1,tmp_stack_end@l(%r9)\n\t"
126 "mr %r3,%r29\n\t"
127 "bl __clear_bss\n\t" /* Clear BSS */
129 "lis %r11,target_address@ha\n\t" /* Load the address of init code in C */
130 "mr %r3,%r29\n\t" /* restore the message */
131 "lwz %r11,target_address@l(%r11)\n\t"
132 "lis %r9,stack_end@ha\n\t" /* Use brand new stack to do evil things */
133 "mtctr %r11\n\t"
134 "lwz %r1,stack_end@l(%r9)\n\t"
136 "bctr\n\t" /* And start the game... */
138 ".string \"Native/CORE v3 (" __DATE__ ")\""
139 "\n\t.text\n\t"
142 static void __attribute__((used)) __clear_bss(struct TagItem *msg)
144 struct KernelBSS *bss;
146 bss =(struct KernelBSS *)krnGetTagData(KRN_KernelBss, 0, msg);
148 if (bss)
150 while (bss->addr && bss->len)
152 memset(bss->addr, 0, bss->len);
153 bss++;
158 static __attribute__((used,section(".data"),aligned(16))) union {
159 struct TagItem bootup_tags[64];
160 uint32_t tmp_stack[128];
161 } tmp_struct;
162 static const uint32_t *tmp_stack_end __attribute__((used, section(".text"))) = &tmp_struct.tmp_stack[124];
163 static uint32_t stack[STACK_SIZE] __attribute__((used,aligned(16)));
164 static uint32_t stack_super[STACK_SIZE] __attribute__((used,aligned(16)));
165 static const uint32_t *stack_end __attribute__((used, section(".text"))) = &stack[STACK_SIZE-4];
166 static const void *target_address __attribute__((used, section(".text"))) = (void*)kernel_cstart;
167 static uint8_t *mmu_dir;
168 static uint32_t *MBAR;
170 /* Variables which should go to the .data section */
171 static struct OFWNode *ofw_root_node __attribute__((used,section(".data"))) = NULL;
172 struct TagItem *BootMsg __attribute__((used,section(".data"))) = NULL;
173 static uint8_t *memlo __attribute__((used,section(".data"))) = NULL;
175 module_t *modlist;
176 uint32_t modlength;
178 static void __attribute__((used)) kernel_cstart(struct TagItem *msg)
180 D(bug("[KRN] EFika5200B Kernel build on %s\n", __DATE__));
181 struct TagItem *tmp = tmp_struct.bootup_tags;
182 struct TagItem *src = msg;
183 struct OFWNode *node;
185 wrspr(SPRG0, (uint32_t)&stack_super[STACK_SIZE-4]);
186 wrspr(SPRG4, 0);
187 wrspr(SPRG5, 0);
188 wrmsr(rdmsr() | MSR_FP);
190 /* MMU directory - 1MB is recommended size for systems with 128MB ram
191 * USE PHYSICAL ADDRESS HERE! */
192 mmu_dir = (uint8_t *)0x07000000;
194 D(bug("[KRN] BootMsg @ %p\n", msg));
196 if (msg == BootMsg)
198 D(bug("[KRN] Reboot detected\n"));
200 else
202 /* Set the memlo pointer right after MMU dir */
203 memlo = 0xff100000;
205 D(bug("[KRN] Copying TagList and data\n"));
207 while(msg->ti_Tag != TAG_DONE)
209 *tmp = *msg;
211 if (tmp->ti_Tag == KRN_CmdLine)
213 tmp->ti_Data = (intptr_t)memlo;
214 memlo += (strlen(msg->ti_Data) + 4) & ~3;
215 memcpy(tmp->ti_Data, msg->ti_Data, strlen(msg->ti_Data)+1);
216 D(bug("[KRN] CmdLine: '%s'\n", tmp->ti_Data));
218 else if (tmp->ti_Tag == KRN_KernelBss)
220 struct KernelBSS *bss_in, *bss_out;
222 bss_out = (struct KernelBSS *)memlo;
223 bss_in = msg->ti_Data;
225 tmp->ti_Data = (intptr_t)bss_out;
227 while(bss_in->addr && bss_in->len)
229 *bss_out++ = *bss_in++;
231 *bss_out++ = *bss_in++;
233 memlo = (uint8_t *)bss_out;
235 else if (tmp->ti_Tag == KRN_OpenFirmwareTree)
237 ofw_root_node = krnCopyOFWTree((struct OFWNode *)msg->ti_Data);
238 tmp->ti_Data = (intptr_t)ofw_root_node;
240 else if (tmp->ti_Tag == KRN_DebugInfo)
242 int i;
243 struct MinList *mlist = tmp->ti_Data;
245 D(bug("[KRN] DebugInfo at %08x\n", modlist));
247 module_t *mod = (module_t *)memlo;
249 ListLength(mlist, modlength);
250 modlist = mod;
252 memlo = &mod[modlength];
254 D(bug("[KRN] Bootstrap loaded debug info for %d modules\n", modlength));
256 /* Copy the module entries */
257 for (i=0; i < modlength; i++)
259 module_t *m = REMHEAD(mlist);
260 symbol_t *sym;
262 mod[i].m_lowest = m->m_lowest;
263 mod[i].m_highest = m->m_highest;
264 mod[i].m_str = NULL;
265 NEWLIST(&mod[i].m_symbols);
266 mod[i].m_name = (char *)memlo;
267 memlo += (strlen(m->m_name) + 4) & ~3;
268 strcpy(mod[i].m_name, m->m_name);
270 ForeachNode(&m->m_symbols, sym)
272 symbol_t *newsym = memlo;
273 memlo += sizeof(symbol_t);
275 newsym->s_name = memlo;
276 memlo += (strlen(sym->s_name)+4)&~3;
277 strcpy(newsym->s_name, sym->s_name);
279 newsym->s_lowest = sym->s_lowest;
280 newsym->s_highest = sym->s_highest;
282 ADDTAIL(&mod[i].m_symbols, newsym);
286 D(bug("[KRN] Debug info uses %d KB of memory\n", ((intptr_t)memlo - (intptr_t)mod) >> 10));
289 tmp++;
290 msg++;
292 *tmp = *msg;
294 memlo = (char *)(((intptr_t)memlo + 4095) & ~4095);
296 BootMsg = tmp_struct.bootup_tags;
299 intr_init();
300 mmu_init(mmu_dir, 0x100000);
303 * Find the "/builtin" node in ofw tree and read it's reg property. It is
304 * the only way to obtain the value of MBAR register (that is, location of
305 * the CPU in-chip peripherials
307 ForeachNode(&ofw_root_node->on_children, node)
309 if (!strcmp(node->on_name, "builtin"))
310 break;
313 if (node)
315 struct OFWProperty *prop = NULL;
317 ForeachNode(&node->on_properties, prop)
319 if (!strcmp(prop->op_name,"reg"))
320 break;
323 if (prop)
325 MBAR = *(uint32_t**)prop->op_value;
327 D(bug("[KRN] MBAR at %08x\n", MBAR));
331 /* Enable dynamic power management */
332 wrspr(1008, 0x0010c000);
333 D(bug("[KRN] HID0=%08x HID1=%08x\n", rdspr(1008), rdspr(1009)));
335 ictl_init(MBAR);
337 D(bug("[KRN] Mapping 00003000-06ffffff range for public use\n"));
338 mmu_map_area(0x00003000, 0x00003000, 0x06ffd000, (2 << 3) | 2); // PP = 10, WIMG = 0010
340 D(bug("[KRN] Mapping %08x-%08x range for MBAR\n", MBAR, MBAR + 0xc000 - 1));
341 mmu_map_area((uint64_t)MBAR & 0xffffffff, (uint64_t)MBAR & 0xffffffff, 0x0000c000, (5 << 3) | 2); // PP = 10, WIMG = 0101
343 D(bug("[KRN] Mapping %08x-%08x range for public read-only access\n", 0xff100000, memlo - 1));
344 mmu_map_area(0xff100000, 0x07100000, (intptr_t)memlo - 0xff100000, (2 << 3) | 1); // PP = 01, WIMG = 0010
346 uintptr_t krn_base = krnGetTagData(KRN_KernelBase, 0, BootMsg);
347 uintptr_t krn_lowest = krnGetTagData(KRN_KernelLowest, 0, BootMsg) & ~4095;
348 uintptr_t krn_highest = (krnGetTagData(KRN_KernelHighest, 0, BootMsg) + 4095) & ~4095;
350 D(bug("[KRN] Mapping %08x-%08x range for supervisor\n", memlo, (krn_lowest ^ 0xf8000000)-1));
351 mmu_map_area((uint32_t)memlo, (uint32_t)memlo ^ 0xf8000000, (krn_lowest ^ 0xf8000000) - (intptr_t)memlo, (2 << 3) | 0); // PP = 00, WIMG = 0010
353 D(bug("[KRN] Mapping %08x-%08x range for read-write\n", krn_lowest^0xf8000000, (krn_base ^ 0xf8000000)-1));
354 mmu_map_area((uint32_t)krn_lowest^0xf8000000, (uint32_t)krn_lowest, (krn_base - krn_lowest), (2 << 3) | 2); // PP = 10, WIMG = 0010
356 D(bug("[KRN] Mapping %08x-%08x range for read-only\n", krn_base^0xf8000000, (krn_highest ^ 0xf8000000)-1));
357 mmu_map_area((uint32_t)krn_base^0xf8000000, (uint32_t)krn_base, (krn_highest - krn_base), (2 << 3) | 3); // PP = 11, WIMG = 0010
359 D(bug("[KRN] Mapping %08x-%08x range for supervisor\n", krn_highest ^ 0xf8000000, 0xffffffff));
360 mmu_map_area((uint32_t)krn_highest^0xf8000000, (uint32_t)krn_highest, -(krn_highest^0xf8000000), (2 << 3) | 0); // PP = 00, WIMG = 0010
362 /* Prepare the MemHeader structure for this region */
363 struct MemHeader *mh = (struct MemHeader *)memlo;
364 mh->mh_First = (struct MemChunk *)((uint8_t *)mh + MEMHEADER_TOTAL);
365 mh->mh_Free = ((krn_lowest^0xf8000000) - MEMHEADER_TOTAL - (intptr_t)memlo) & ~(MEMCHUNK_TOTAL-1);
366 mh->mh_First->mc_Next = NULL;
367 mh->mh_First->mc_Bytes = mh->mh_Free;
369 D(bug("[KRN] Supervisor mem: %dKB free\n", mh->mh_Free >> 10));
371 exec_main(BootMsg, NULL);
373 goSuper();
374 D(bug("[KRN] Uhm? Nothing to do?\n[KRN] STOPPED\n"));
375 /* Dead end */
376 while(1) {
377 wrmsr(rdmsr() | MSR_EE);
378 wrmsr(rdmsr() | MSR_POW);
383 AROS_LH0I(struct TagItem *, KrnGetBootInfo,
384 struct KernelBase *, KernelBase, 11, Kernel)
386 AROS_LIBFUNC_INIT
388 return BootMsg;
390 AROS_LIBFUNC_EXIT
393 AROS_LH0(void *, KrnCreateContext,
394 struct KernelBase *, KernelBase, 18, Kernel)
396 AROS_LIBFUNC_INIT
398 context_t *ctx;
400 uint32_t oldmsr = goSuper();
402 ctx = Allocate(KernelBase->kb_SupervisorMem, sizeof(context_t));
403 memset(ctx, 0, sizeof(context_t));
405 wrmsr(oldmsr);
407 if (!ctx)
408 ctx = AllocMem(sizeof(context_t), MEMF_PUBLIC|MEMF_CLEAR);
410 return ctx;
412 AROS_LIBFUNC_EXIT
415 AROS_LH1(void, KrnDeleteContext,
416 AROS_LHA(void *, context, A0),
417 struct KernelBase *, KernelBase, 19, Kernel)
419 AROS_LIBFUNC_INIT
421 /* Was context in supervisor space? Deallocate it there :) */
422 if ((intptr_t)context & 0xf0000000)
424 uint32_t oldmsr = goSuper();
426 Deallocate(KernelBase->kb_SupervisorMem, context, sizeof(context_t));
428 wrmsr(oldmsr);
430 else
431 FreeMem(context, sizeof(context_t));
433 /* Was this context owning a FPU? Make FPU totally free then */
434 if (KernelBase->kb_FPUOwner == context)
435 KernelBase->kb_FPUOwner = NULL;
437 AROS_LIBFUNC_EXIT
441 struct OFWNode *krnCopyOFWTree(struct OFWNode *orig)
443 uint32_t node_length = sizeof(struct OFWNode) + strlen(orig->on_name) + 1;
444 struct OFWNode *new_node = (struct OFWNode *)memlo;
445 struct OFWNode *child;
446 struct OFWProperty *prop, *new_prop;
447 memlo += (node_length + 3) & ~3;
449 new_node->on_name = new_node->on_storage;
450 memcpy(new_node->on_name, orig->on_name, strlen(orig->on_name) + 1);
451 NEWLIST(&new_node->on_children);
452 NEWLIST(&new_node->on_properties);
454 ForeachNode(&orig->on_properties, prop)
456 uint32_t prop_name_length = strlen(prop->op_name) + 1;
457 uint32_t prop_length = sizeof(struct OFWProperty) + prop_name_length + prop->op_length;
459 new_prop = (struct OFWProperty *)memlo;
460 memlo += (prop_length + 3) & ~3;
462 new_prop->op_name = new_prop->op_storage;
463 new_prop->op_value = &new_prop->op_storage[prop_name_length];
464 new_prop->op_length = prop->op_length;
466 memcpy(new_prop->op_name, prop->op_name, strlen(prop->op_name)+1);
467 memcpy(new_prop->op_value, prop->op_value, prop->op_length);
469 ADDTAIL(&new_node->on_properties, new_prop);
472 ForeachNode(&orig->on_children, child)
473 ADDTAIL(&new_node->on_children, krnCopyOFWTree(child));
475 return new_node;
478 uint64_t tbu1;
479 uint64_t tbu2;
480 uint64_t last_calc;
481 uint64_t idle_time;
482 uint32_t cpu_usage;
483 struct Task *idle_task;
485 /* As soon as IdleTask gets CPU again, it records the current cycle count */
486 AROS_UFH1(void, idleCount,
487 AROS_UFHA(struct ExecBase *, SysBase, A6))
489 AROS_USERFUNC_INIT
491 tbu1 = mftbu();
492 SysBase->IdleCount++;
494 AROS_USERFUNC_EXIT
498 * When CPU time gets lost, the cycle count spent in idle task is summed
499 * with the total idle time
501 AROS_UFH1(void, idleOff,
502 AROS_UFHA(struct ExecBase *, SysBase, A6))
504 AROS_USERFUNC_INIT
506 tbu2 = mftbu();
507 idle_time += tbu2 - tbu1;
509 AROS_USERFUNC_EXIT
513 * Idle task on Efika does not do much. It enters supervisor mode, enables
514 * interrupts (so that it survived even in Disable()'d state) and then enters
515 * power save mode. Once woken up, a Reschedule is forced.
517 void idleTask(struct ExecBase *SysBase, struct KernelBase *KernelBase)
519 D(bug("[KRN] IdleTask entered\n"));
521 while(1)
523 if (0)
525 /* Superstate() done quickly */
526 int i;
527 uint32_t msr = goSuper();
528 uint32_t msr_sup = rdmsr() | MSR_EE | MSR_POW;
529 /* Enable external/decrementer interrupts */
530 asm volatile("sync");
531 /* Sleep! */
532 wrmsr(msr_sup);
533 /* Changing the POW bit needs a context synchronization now. */
534 asm volatile("isync");
536 /* CPU needs few cycles to enter sleep state */
537 for (i=0; i < 10; i++)
538 asm volatile("nop");
540 /* Userstate() */
541 wrmsr(msr);
542 /* And reschedule! */
543 KrnSchedule();
548 struct MemHeader KernelMemory;
550 void *(*__AllocMem)();
552 #define ExecAllocMem(bytesize, requirements) \
553 AROS_CALL2(void *, __AllocMem, \
554 AROS_LCA(ULONG, byteSize, D0), \
555 AROS_LCA(ULONG, requirements, D1), \
556 struct ExecBase *, SysBase)
558 AROS_LH2(APTR, AllocMem,
559 AROS_LHA(ULONG, byteSize, D0),
560 AROS_LHA(ULONG, requirements, D1),
561 struct ExecBase *, SysBase, 33, Kernel)
563 AROS_LIBFUNC_INIT
565 return ExecAllocMem(bytesize, requirements & ~MEMF_CHIP);
567 AROS_LIBFUNC_EXIT
571 static int Kernel_Init(LIBBASETYPEPTR LIBBASE)
573 int i;
574 struct ExecBase *SysBase = getSysBase();
575 int realchip = 0;
577 uintptr_t krn_lowest = (krnGetTagData(KRN_KernelLowest, 0, BootMsg) & ~4095) ^ 0xf8000000;
578 uintptr_t krn_highest = ((krnGetTagData(KRN_KernelHighest, 0, BootMsg) + 4095) & ~4095) ^ 0xf8000000;
579 char *cmd = krnGetTagData(KRN_CmdLine, 0, BootMsg);
581 KernelMemory.mh_Node.ln_Name = "Kernel";
582 KernelMemory.mh_Node.ln_Type = NT_MEMORY;
583 KernelMemory.mh_Node.ln_Pri = -128;
584 KernelMemory.mh_Attributes = MEMF_KICK;
585 KernelMemory.mh_First = NULL;
586 KernelMemory.mh_Free = 0;
587 KernelMemory.mh_Lower = krn_lowest;
588 KernelMemory.mh_Upper = krn_highest;
590 Forbid();
591 Enqueue(&SysBase->MemList, &KernelMemory.mh_Node);
592 Permit();
594 NEWLIST(&LIBBASE->kb_Modules);
595 NEWLIST(&LIBBASE->kb_DeadTasks);
597 /* Check whether the user passed realchip parameter. */
598 if (cmd)
600 while(cmd[0])
602 uint32_t temp = strcspn(cmd, " ");
604 if (strncmp(cmd, "realchip", 8) == 0)
606 realchip=1;
609 cmd = stpblk(cmd+temp);
614 * If no realchip parameter was given, the AllocMem function will be patched with a stub
615 * which *always* clears the MEMF_CHIP flag.
617 if (!realchip)
619 __AllocMem = SetFunction(SysBase, -33*LIB_VECTSIZE, AROS_SLIB_ENTRY(AllocMem, Kernel, 33));
623 * Set the KernelBase into SPRG4. At this stage the SPRG5 should be already set by
624 * exec.library itself.
626 wrspr(SPRG4, LIBBASE);
628 LIBBASE->kb_FPUOwner = NULL;
630 D(bug("[KRN] Kernel resource post-exec init.\n"));
632 for (i=0; i < 21; i++)
633 NEWLIST(&LIBBASE->kb_Exceptions[i]);
635 for (i=0; i < 64; i++)
636 NEWLIST(&LIBBASE->kb_Interrupts[i]);
638 /* Prepare private memory block */
639 LIBBASE->kb_SupervisorMem = (struct MemHeader *)memlo;
642 * kernel.resource is ready to run. Enable external interrupts and leave
643 * supervisor mode
645 wrmsr(rdmsr() | (MSR_EE|MSR_FP));
646 D(bug("[KRN] Interrupts enabled\n"));
648 asm volatile("mtdec %0"::"r"(33000000/1000));
650 wrmsr(rdmsr() | (MSR_PR));
651 D(bug("[KRN] Entered user mode\n"));
654 /* Add idle task now. */
655 struct Task *t;
656 struct MemList *ml;
657 uint8_t *s;
658 struct TagItem tags[] = {
659 { TASKTAG_ARG1, (IPTR)SysBase },
660 { TASKTAG_ARG2, (IPTR)LIBBASE },
661 { TAG_DONE, 0UL }};
663 /* Allocate MemEntry for this task and stack */
664 ml = (struct MemList *)AllocMem(sizeof(struct MemList)+sizeof(struct MemEntry),
665 MEMF_PUBLIC|MEMF_CLEAR);
666 t = (struct Task *) AllocMem(sizeof(struct Task), MEMF_CLEAR|MEMF_PUBLIC);
667 s = (uint8_t *) AllocMem(4096, MEMF_CLEAR|MEMF_PUBLIC);
669 if( !ml || !t || !s )
671 bug("ERROR: Cannot create Idle Task!\n");
672 Alert( AT_DeadEnd | AG_NoMemory | AN_ExecLib );
675 ml->ml_NumEntries = 2;
676 ml->ml_ME[0].me_Addr = t;
677 ml->ml_ME[0].me_Length = sizeof(struct Task);
678 ml->ml_ME[1].me_Addr = s;
679 ml->ml_ME[1].me_Length = 4096;
681 NEWLIST(&t->tc_MemEntry);
682 AddHead(&t->tc_MemEntry, &ml->ml_Node);
683 t->tc_SPLower = s;
684 t->tc_SPUpper = s + 4096 - SP_OFFSET;
685 #if AROS_STACK_GROWS_DOWNWARDS
686 t->tc_SPReg = (char *)t->tc_SPUpper - SP_OFFSET;
687 #else
688 t->tc_SPReg = (char *)t->tc_SPLower + SP_OFFSET;
689 #endif
691 t->tc_Node.ln_Name = "Idle Task";
692 t->tc_Node.ln_Pri = -128;
693 t->tc_Launch = &idleCount;
694 t->tc_Switch = &idleOff;
695 t->tc_Flags = TF_LAUNCH | TF_SWITCH;
696 NewAddTask(t, &idleTask, NULL, &tags);
697 idle_task = t;
700 return TRUE;
703 ADD2INITLIB(Kernel_Init, 0)