Updated PCI IDs to latest snapshot.
[tangerine.git] / arch / ppc-chrp / efika / kernel / kernel_init.c
blob6a9dad1adf9e21fb4a43b958ddb95351feffd68c
1 /*
2 * kernel_init.c
4 * Created on: Aug 19, 2008
5 * Author: misc
6 */
8 #define DEBUG 1
10 #include <aros/kernel.h>
11 #include <aros/symbolsets.h>
12 #include <exec/memory.h>
13 #include <exec/tasks.h>
14 #include <exec/alerts.h>
15 #include <exec/execbase.h>
16 #include <asm/io.h>
17 #include <asm/mpc5200b.h>
18 #include <proto/kernel.h>
19 #include <strings.h>
21 #include <proto/exec.h>
23 #include "exec_intern.h"
24 #include "etask.h"
26 #include "kernel_intern.h"
27 #include LC_LIBDEFS_FILE
28 #include "syscall.h"
29 #include "memory.h"
31 static void __attribute__((used)) kernel_cstart(struct TagItem *msg);
32 struct OFWNode *krnCopyOFWTree(struct OFWNode *orig);
33 int exec_main(struct TagItem *msg, void *entry);
35 asm(".section .aros.init,\"ax\"\n\t"
36 ".globl start\n\t"
37 ".type start,@function\n"
38 "start:\n\t"
40 "mr %r29,%r3\n\t" /* Keep it for later */
42 "li %r0,0x2000\n\t"
43 "mtmsr %r0\n\t" /* Disable address translation */
44 "sync; isync\n\t"
46 /* Set up BAT registers with a very simple map. */
47 /* IBAT0 virtual 0xff800000 into physical 0x07800000, size 8MB, read only, super only, cached */
48 "lis %r0, 0xff80; "
49 "ori %r0, %r0, 0x2 | 0xfc; "
50 "mtspr 528,%r0; " /* Clear all BAT entries */
51 "lis %r0, 0x0780;"
52 "ori %r0,%r0,0x01 | 0x10; "
53 "mtspr 529, %r0;"
55 /* IBAT1 virtual 0x07800000 into physical 0x07800000, size 8MB, read only, super only, cached */
56 "lis %r0, 0x0780; "
57 "ori %r0, %r0, 0x2 | 0xfc; "
58 "mtspr 530,%r0; " /* Clear all BAT entries */
59 "lis %r0, 0x0780;"
60 "ori %r0,%r0,0x01 | 0x10; "
61 "mtspr 531, %r0;"
63 /* Clear IBAT1 - IBAT7 */
64 "lis %r0, 0; "
65 "mtspr 532, %r0;"
66 "mtspr 533, %r0;"
67 "mtspr 534, %r0;"
68 "mtspr 535, %r0;"
70 "mtspr 560, %r0;"
71 "mtspr 561, %r0;"
72 "mtspr 562, %r0;"
73 "mtspr 563, %r0;"
74 "mtspr 564, %r0;"
75 "mtspr 565, %r0;"
76 "mtspr 566, %r0;"
77 "mtspr 567, %r0;"
79 /* DBAT0 virtual 0xff000000, physical 0x07000000, size 8MB, read write, super only, cached */
80 "lis %r0, 0xff00; "
81 "ori %r0, %r0, 0x2 | 0xfc; "
82 "mtspr 536,%r0; " /* Clear all BAT entries */
83 "lis %r0, 0x0700;"
84 "ori %r0,%r0,0x02 | 0x10; "
85 "mtspr 537, %r0;"
86 /* DBAT1 virtual 0xff800000, physical 0x07800000, size 8MB, read only, super only, cached */
87 "lis %r0, 0xff80; "
88 "ori %r0, %r0, 0x2 | 0xfc; "
89 "mtspr 538,%r0; " /* Clear all BAT entries */
90 "lis %r0, 0x0780;"
91 "ori %r0,%r0,0x01 | 0x10; "
92 "mtspr 539, %r0;"
93 /* DBAT2 virtual 0x00000000, physical 0x00000000, 128MB, read write, super only, cached */
94 "lis %r0, 0x0000; "
95 "ori %r0, %r0, 0x2 | 0x1ffc; "
96 "mtspr 540,%r0; " /* Clear all BAT entries */
97 "lis %r0, 0x0000;"
98 "ori %r0,%r0,0x02 | 0x10; "
99 "mtspr 541, %r0;"
100 /* DBAT3 virtual 0xf0000000, physical 0xf0000000, 128KB, read write, super only, not cached */
101 "lis %r0, 0xf000; "
102 "ori %r0, %r0, 0x3; "
103 "mtspr 542,%r0; "
104 "lis %r0, 0xf000;"
105 "ori %r0,%r0,0x0a | 0x20; "
106 "mtspr 543, %r0;"
108 /* Clear DBAT3 - DBAT7 */
109 "lis %r0, 0; "
111 "mtspr 568, %r0;"
112 "mtspr 569, %r0;"
113 "mtspr 570, %r0;"
114 "mtspr 571, %r0;"
115 "mtspr 572, %r0;"
116 "mtspr 573, %r0;"
117 "mtspr 574, %r0;"
118 "mtspr 575, %r0;"
120 "mttbl %r0; mttbu %r0; mttbl %r0;"
122 /* Enable address translation again. All accesses will be done through BAT registers */
123 "li %r0, 0x2030;"
124 "mtmsr %r0;sync;isync;"
126 "lis %r9,tmp_stack_end@ha\n\t" /* Use temporary stack while clearing BSS */
127 "lwz %r1,tmp_stack_end@l(%r9)\n\t"
128 "mr %r3,%r29\n\t"
129 "bl __clear_bss\n\t" /* Clear BSS */
131 "lis %r11,target_address@ha\n\t" /* Load the address of init code in C */
132 "mr %r3,%r29\n\t" /* restore the message */
133 "lwz %r11,target_address@l(%r11)\n\t"
134 "lis %r9,stack_end@ha\n\t" /* Use brand new stack to do evil things */
135 "mtctr %r11\n\t"
136 "lwz %r1,stack_end@l(%r9)\n\t"
138 "bctr\n\t" /* And start the game... */
140 ".string \"Native/CORE v3 (" __DATE__ ")\""
141 "\n\t.text\n\t"
144 static void __attribute__((used)) __clear_bss(struct TagItem *msg)
146 struct KernelBSS *bss;
148 bss =(struct KernelBSS *)krnGetTagData(KRN_KernelBss, 0, msg);
150 if (bss)
152 while (bss->addr && bss->len)
154 bzero(bss->addr, bss->len);
155 bss++;
160 static __attribute__((used,section(".data"),aligned(16))) union {
161 struct TagItem bootup_tags[64];
162 uint32_t tmp_stack[128];
163 } tmp_struct;
164 static const uint32_t *tmp_stack_end __attribute__((used, section(".text"))) = &tmp_struct.tmp_stack[124];
165 static uint32_t stack[STACK_SIZE] __attribute__((used,aligned(16)));
166 static uint32_t stack_super[STACK_SIZE] __attribute__((used,aligned(16)));
167 static const uint32_t *stack_end __attribute__((used, section(".text"))) = &stack[STACK_SIZE-4];
168 static const void *target_address __attribute__((used, section(".text"))) = (void*)kernel_cstart;
169 static uint8_t *mmu_dir;
170 static uint32_t *MBAR;
172 /* Variables which should go to the .data section */
173 static struct OFWNode *ofw_root_node __attribute__((used,section(".data"))) = NULL;
174 struct TagItem *BootMsg __attribute__((used,section(".data"))) = NULL;
175 static uint8_t *memlo __attribute__((used,section(".data"))) = NULL;
177 module_t *modlist;
178 uint32_t modlength;
180 static void __attribute__((used)) kernel_cstart(struct TagItem *msg)
182 D(bug("[KRN] EFika5200B Kernel build on %s\n", __DATE__));
183 struct TagItem *tmp = tmp_struct.bootup_tags;
184 struct TagItem *src = msg;
185 struct OFWNode *node;
187 wrspr(SPRG0, (uint32_t)&stack_super[STACK_SIZE-4]);
188 wrspr(SPRG4, 0);
189 wrspr(SPRG5, 0);
190 wrmsr(rdmsr() | MSR_FP);
192 /* MMU directory - 1MB is recommended size for systems with 128MB ram
193 * USE PHYSICAL ADDRESS HERE! */
194 mmu_dir = (uint8_t *)0x07000000;
196 D(bug("[KRN] BootMsg @ %p\n", msg));
198 if (msg == BootMsg)
200 D(bug("[KRN] Reboot detected\n"));
202 else
204 /* Set the memlo pointer right after MMU dir */
205 memlo = 0xff100000;
207 D(bug("[KRN] Copying TagList and data\n"));
209 while(msg->ti_Tag != TAG_DONE)
211 *tmp = *msg;
213 if (tmp->ti_Tag == KRN_CmdLine)
215 tmp->ti_Data = (intptr_t)memlo;
216 memlo += (strlen(msg->ti_Data) + 4) & ~3;
217 memcpy(tmp->ti_Data, msg->ti_Data, strlen(msg->ti_Data)+1);
218 D(bug("[KRN] CmdLine: '%s'\n", tmp->ti_Data));
220 else if (tmp->ti_Tag == KRN_KernelBss)
222 struct KernelBSS *bss_in, *bss_out;
224 bss_out = (struct KernelBSS *)memlo;
225 bss_in = msg->ti_Data;
227 tmp->ti_Data = (intptr_t)bss_out;
229 while(bss_in->addr && bss_in->len)
231 *bss_out++ = *bss_in++;
233 *bss_out++ = *bss_in++;
235 memlo = (uint8_t *)bss_out;
237 else if (tmp->ti_Tag == KRN_OpenFirmwareTree)
239 ofw_root_node = krnCopyOFWTree((struct OFWNode *)msg->ti_Data);
240 tmp->ti_Data = (intptr_t)ofw_root_node;
242 else if (tmp->ti_Tag == KRN_DebugInfo)
244 int i;
245 struct MinList *mlist = tmp->ti_Data;
247 D(bug("[KRN] DebugInfo at %08x\n", modlist));
249 module_t *mod = (module_t *)memlo;
251 ListLength(mlist, modlength);
252 modlist = mod;
254 memlo = &mod[modlength];
256 D(bug("[KRN] Bootstrap loaded debug info for %d modules\n", modlength));
258 /* Copy the module entries */
259 for (i=0; i < modlength; i++)
261 module_t *m = REMHEAD(mlist);
262 symbol_t *sym;
264 mod[i].m_lowest = m->m_lowest;
265 mod[i].m_highest = m->m_highest;
266 mod[i].m_str = NULL;
267 NEWLIST(&mod[i].m_symbols);
268 mod[i].m_name = (char *)memlo;
269 memlo += (strlen(m->m_name) + 4) & ~3;
270 strcpy(mod[i].m_name, m->m_name);
272 ForeachNode(&m->m_symbols, sym)
274 symbol_t *newsym = memlo;
275 memlo += sizeof(symbol_t);
277 newsym->s_name = memlo;
278 memlo += (strlen(sym->s_name)+4)&~3;
279 strcpy(newsym->s_name, sym->s_name);
281 newsym->s_lowest = sym->s_lowest;
282 newsym->s_highest = sym->s_highest;
284 ADDTAIL(&mod[i].m_symbols, newsym);
288 D(bug("[KRN] Debug info uses %d KB of memory\n", ((intptr_t)memlo - (intptr_t)mod) >> 10));
291 tmp++;
292 msg++;
294 *tmp = *msg;
296 memlo = (char *)(((intptr_t)memlo + 4095) & ~4095);
298 BootMsg = tmp_struct.bootup_tags;
301 intr_init();
302 mmu_init(mmu_dir, 0x100000);
305 * Find the "/builtin" node in ofw tree and read it's reg property. It is
306 * the only way to obtain the value of MBAR register (that is, location of
307 * the CPU in-chip peripherials
309 ForeachNode(&ofw_root_node->on_children, node)
311 if (!strcmp(node->on_name, "builtin"))
312 break;
315 if (node)
317 struct OFWProperty *prop = NULL;
319 ForeachNode(&node->on_properties, prop)
321 if (!strcmp(prop->op_name,"reg"))
322 break;
325 if (prop)
327 MBAR = *(uint32_t**)prop->op_value;
329 D(bug("[KRN] MBAR at %08x\n", MBAR));
333 /* Enable dynamic power management */
334 wrspr(1008, 0x0010c000);
335 D(bug("[KRN] HID0=%08x HID1=%08x\n", rdspr(1008), rdspr(1009)));
337 ictl_init(MBAR);
339 D(bug("[KRN] Mapping 00003000-06ffffff range for public use\n"));
340 mmu_map_area(0x00003000, 0x00003000, 0x06ffd000, (2 << 3) | 2); // PP = 10, WIMG = 0010
342 D(bug("[KRN] Mapping %08x-%08x range for MBAR\n", MBAR, MBAR + 0xc000 - 1));
343 mmu_map_area((uint64_t)MBAR & 0xffffffff, (uint64_t)MBAR & 0xffffffff, 0x0000c000, (5 << 3) | 2); // PP = 10, WIMG = 0101
345 D(bug("[KRN] Mapping %08x-%08x range for public read-only access\n", 0xff100000, memlo - 1));
346 mmu_map_area(0xff100000, 0x07100000, (intptr_t)memlo - 0xff100000, (2 << 3) | 1); // PP = 01, WIMG = 0010
348 uintptr_t krn_base = krnGetTagData(KRN_KernelBase, 0, BootMsg);
349 uintptr_t krn_lowest = krnGetTagData(KRN_KernelLowest, 0, BootMsg) & ~4095;
350 uintptr_t krn_highest = (krnGetTagData(KRN_KernelHighest, 0, BootMsg) + 4095) & ~4095;
352 D(bug("[KRN] Mapping %08x-%08x range for supervisor\n", memlo, (krn_lowest ^ 0xf8000000)-1));
353 mmu_map_area((uint32_t)memlo, (uint32_t)memlo ^ 0xf8000000, (krn_lowest ^ 0xf8000000) - (intptr_t)memlo, (2 << 3) | 0); // PP = 00, WIMG = 0010
355 D(bug("[KRN] Mapping %08x-%08x range for read-write\n", krn_lowest^0xf8000000, (krn_base ^ 0xf8000000)-1));
356 mmu_map_area((uint32_t)krn_lowest^0xf8000000, (uint32_t)krn_lowest, (krn_base - krn_lowest), (2 << 3) | 2); // PP = 10, WIMG = 0010
358 D(bug("[KRN] Mapping %08x-%08x range for read-only\n", krn_base^0xf8000000, (krn_highest ^ 0xf8000000)-1));
359 mmu_map_area((uint32_t)krn_base^0xf8000000, (uint32_t)krn_base, (krn_highest - krn_base), (2 << 3) | 3); // PP = 11, WIMG = 0010
361 D(bug("[KRN] Mapping %08x-%08x range for supervisor\n", krn_highest ^ 0xf8000000, 0xffffffff));
362 mmu_map_area((uint32_t)krn_highest^0xf8000000, (uint32_t)krn_highest, -(krn_highest^0xf8000000), (2 << 3) | 0); // PP = 00, WIMG = 0010
364 /* Prepare the MemHeader structure for this region */
365 struct MemHeader *mh = (struct MemHeader *)memlo;
366 mh->mh_First = (struct MemChunk *)((uint8_t *)mh + MEMHEADER_TOTAL);
367 mh->mh_Free = ((krn_lowest^0xf8000000) - MEMHEADER_TOTAL - (intptr_t)memlo) & ~(MEMCHUNK_TOTAL-1);
368 mh->mh_First->mc_Next = NULL;
369 mh->mh_First->mc_Bytes = mh->mh_Free;
371 D(bug("[KRN] Supervisor mem: %dKB free\n", mh->mh_Free >> 10));
373 exec_main(BootMsg, NULL);
375 goSuper();
376 D(bug("[KRN] Uhm? Nothing to do?\n[KRN] STOPPED\n"));
377 /* Dead end */
378 while(1) {
379 wrmsr(rdmsr() | MSR_EE);
380 wrmsr(rdmsr() | MSR_POW);
385 AROS_LH0I(struct TagItem *, KrnGetBootInfo,
386 struct KernelBase *, KernelBase, 10, Kernel)
388 AROS_LIBFUNC_INIT
390 return BootMsg;
392 AROS_LIBFUNC_EXIT
395 AROS_LH0(void *, KrnCreateContext,
396 struct KernelBase *, KernelBase, 10, Kernel)
398 AROS_LIBFUNC_INIT
400 context_t *ctx;
402 uint32_t oldmsr = goSuper();
404 ctx = Allocate(KernelBase->kb_SupervisorMem, sizeof(context_t));
405 bzero(ctx, sizeof(context_t));
407 wrmsr(oldmsr);
409 if (!ctx)
410 ctx = AllocMem(sizeof(context_t), MEMF_PUBLIC|MEMF_CLEAR);
412 return ctx;
414 AROS_LIBFUNC_EXIT
417 AROS_LH1(void, KrnDeleteContext,
418 AROS_LHA(void *, context, A0),
419 struct KernelBase *, KernelBase, 10, Kernel)
421 AROS_LIBFUNC_INIT
423 /* Was context in supervisor space? Deallocate it there :) */
424 if ((intptr_t)context & 0xf0000000)
426 uint32_t oldmsr = goSuper();
428 Deallocate(KernelBase->kb_SupervisorMem, context, sizeof(context_t));
430 wrmsr(oldmsr);
432 else
433 FreeMem(context, sizeof(context_t));
435 /* Was this context owning a FPU? Make FPU totally free then */
436 if (KernelBase->kb_FPUOwner == context)
437 KernelBase->kb_FPUOwner = NULL;
439 AROS_LIBFUNC_EXIT
443 struct OFWNode *krnCopyOFWTree(struct OFWNode *orig)
445 uint32_t node_length = sizeof(struct OFWNode) + strlen(orig->on_name) + 1;
446 struct OFWNode *new_node = (struct OFWNode *)memlo;
447 struct OFWNode *child;
448 struct OFWProperty *prop, *new_prop;
449 memlo += (node_length + 3) & ~3;
451 new_node->on_name = new_node->on_storage;
452 memcpy(new_node->on_name, orig->on_name, strlen(orig->on_name) + 1);
453 NEWLIST(&new_node->on_children);
454 NEWLIST(&new_node->on_properties);
456 ForeachNode(&orig->on_properties, prop)
458 uint32_t prop_name_length = strlen(prop->op_name) + 1;
459 uint32_t prop_length = sizeof(struct OFWProperty) + prop_name_length + prop->op_length;
461 new_prop = (struct OFWProperty *)memlo;
462 memlo += (prop_length + 3) & ~3;
464 new_prop->op_name = new_prop->op_storage;
465 new_prop->op_value = &new_prop->op_storage[prop_name_length];
466 new_prop->op_length = prop->op_length;
468 memcpy(new_prop->op_name, prop->op_name, strlen(prop->op_name)+1);
469 memcpy(new_prop->op_value, prop->op_value, prop->op_length);
471 ADDTAIL(&new_node->on_properties, new_prop);
474 ForeachNode(&orig->on_children, child)
475 ADDTAIL(&new_node->on_children, krnCopyOFWTree(child));
477 return new_node;
480 uint64_t tbu1;
481 uint64_t tbu2;
482 uint64_t last_calc;
483 uint64_t idle_time;
484 uint32_t cpu_usage;
485 struct Task *idle_task;
487 /* As soon as IdleTask gets CPU again, it records the current cycle count */
488 AROS_UFH1(void, idleCount,
489 AROS_UFHA(struct ExecBase *, SysBase, A6))
491 AROS_USERFUNC_INIT
493 tbu1 = mftbu();
494 SysBase->IdleCount++;
496 AROS_USERFUNC_EXIT
500 * When CPU time gets lost, the cycle count spent in idle task is summed
501 * with the total idle time
503 AROS_UFH1(void, idleOff,
504 AROS_UFHA(struct ExecBase *, SysBase, A6))
506 AROS_USERFUNC_INIT
508 tbu2 = mftbu();
509 idle_time += tbu2 - tbu1;
511 AROS_USERFUNC_EXIT
515 * Idle task on Efika does not do much. It enters supervisor mode, enables
516 * interrupts (so that it survived even in Disable()'d state) and then enters
517 * power save mode. Once woken up, a Reschedule is forced.
519 void idleTask(struct ExecBase *SysBase, struct KernelBase *KernelBase)
521 D(bug("[KRN] IdleTask entered\n"));
523 while(1)
525 if (0)
527 /* Superstate() done quickly */
528 int i;
529 uint32_t msr = goSuper();
530 uint32_t msr_sup = rdmsr() | MSR_EE | MSR_POW;
531 /* Enable external/decrementer interrupts */
532 asm volatile("sync");
533 /* Sleep! */
534 wrmsr(msr_sup);
535 /* Changing the POW bit needs a context synchronization now. */
536 asm volatile("isync");
538 /* CPU needs few cycles to enter sleep state */
539 for (i=0; i < 10; i++)
540 asm volatile("nop");
542 /* Userstate() */
543 wrmsr(msr);
544 /* And reschedule! */
545 KrnSchedule();
550 extern void *priv_KernelBase;
551 struct MemHeader KernelMemory;
553 void *(*__AllocMem)();
555 #define ExecAllocMem(bytesize, requirements) \
556 AROS_CALL2(void *, __AllocMem, \
557 AROS_LCA(ULONG, byteSize, D0), \
558 AROS_LCA(ULONG, requirements, D1), \
559 struct ExecBase *, SysBase)
561 AROS_LH2(APTR, AllocMem,
562 AROS_LHA(ULONG, byteSize, D0),
563 AROS_LHA(ULONG, requirements, D1),
564 struct ExecBase *, SysBase, 33, Kernel)
566 AROS_LIBFUNC_INIT
568 return ExecAllocMem(bytesize, requirements & ~MEMF_CHIP);
570 AROS_LIBFUNC_EXIT
574 static int Kernel_Init(LIBBASETYPEPTR LIBBASE)
576 int i;
577 struct ExecBase *SysBase = getSysBase();
578 int realchip = 0;
580 uintptr_t krn_lowest = (krnGetTagData(KRN_KernelLowest, 0, BootMsg) & ~4095) ^ 0xf8000000;
581 uintptr_t krn_highest = ((krnGetTagData(KRN_KernelHighest, 0, BootMsg) + 4095) & ~4095) ^ 0xf8000000;
582 char *cmd = krnGetTagData(KRN_CmdLine, 0, BootMsg);
584 KernelMemory.mh_Node.ln_Name = "Kernel";
585 KernelMemory.mh_Node.ln_Type = NT_MEMORY;
586 KernelMemory.mh_Node.ln_Pri = -128;
587 KernelMemory.mh_Attributes = MEMF_KICK;
588 KernelMemory.mh_First = NULL;
589 KernelMemory.mh_Free = 0;
590 KernelMemory.mh_Lower = krn_lowest;
591 KernelMemory.mh_Upper = krn_highest;
593 Forbid();
594 Enqueue(&SysBase->MemList, &KernelMemory.mh_Node);
595 Permit();
597 NEWLIST(&LIBBASE->kb_Modules);
598 NEWLIST(&LIBBASE->kb_DeadTasks);
600 /* Check whether the user passed realchip parameter. */
601 if (cmd)
603 while(cmd[0])
605 uint32_t temp = strcspn(cmd, " ");
607 if (strncmp(cmd, "realchip", 8) == 0)
609 realchip=1;
612 cmd = stpblk(cmd+temp);
617 * If no realchip parameter was given, the AllocMem function will be patched with a stub
618 * which *always* clears the MEMF_CHIP flag.
620 if (!realchip)
622 __AllocMem = SetFunction(SysBase, -33*LIB_VECTSIZE, AROS_SLIB_ENTRY(AllocMem, Kernel));
626 * Set the KernelBase into SPRG4. At this stage the SPRG5 should be already set by
627 * exec.library itself.
629 wrspr(SPRG4, LIBBASE);
631 LIBBASE->kb_FPUOwner = NULL;
633 D(bug("[KRN] Kernel resource post-exec init.\n"));
635 for (i=0; i < 21; i++)
636 NEWLIST(&LIBBASE->kb_Exceptions[i]);
638 for (i=0; i < 64; i++)
639 NEWLIST(&LIBBASE->kb_Interrupts[i]);
641 /* Prepare private memory block */
642 LIBBASE->kb_SupervisorMem = (struct MemHeader *)memlo;
645 * kernel.resource is ready to run. Enable external interrupts and leave
646 * supervisor mode
648 wrmsr(rdmsr() | (MSR_EE|MSR_FP));
649 D(bug("[KRN] Interrupts enabled\n"));
651 asm volatile("mtdec %0"::"r"(33000000/1000));
653 wrmsr(rdmsr() | (MSR_PR));
654 D(bug("[KRN] Entered user mode\n"));
656 priv_KernelBase = LIBBASE;
659 /* Add idle task now. */
660 struct Task *t;
661 struct MemList *ml;
662 uint8_t *s;
663 struct TagItem tags[] = {
664 { TASKTAG_ARG1, (IPTR)SysBase },
665 { TASKTAG_ARG2, (IPTR)LIBBASE },
666 { TAG_DONE, 0UL }};
668 /* Allocate MemEntry for this task and stack */
669 ml = (struct MemList *)AllocMem(sizeof(struct MemList)+sizeof(struct MemEntry),
670 MEMF_PUBLIC|MEMF_CLEAR);
671 t = (struct Task *) AllocMem(sizeof(struct Task), MEMF_CLEAR|MEMF_PUBLIC);
672 s = (uint8_t *) AllocMem(4096, MEMF_CLEAR|MEMF_PUBLIC);
674 if( !ml || !t || !s )
676 bug("ERROR: Cannot create Idle Task!\n");
677 Alert( AT_DeadEnd | AG_NoMemory | AN_ExecLib );
680 ml->ml_NumEntries = 2;
681 ml->ml_ME[0].me_Addr = t;
682 ml->ml_ME[0].me_Length = sizeof(struct Task);
683 ml->ml_ME[1].me_Addr = s;
684 ml->ml_ME[1].me_Length = 4096;
686 NEWLIST(&t->tc_MemEntry);
687 AddHead(&t->tc_MemEntry, &ml->ml_Node);
688 t->tc_SPLower = s;
689 t->tc_SPUpper = s + 4096 - SP_OFFSET;
690 #if AROS_STACK_GROWS_DOWNWARDS
691 t->tc_SPReg = (char *)t->tc_SPUpper - SP_OFFSET;
692 #else
693 t->tc_SPReg = (char *)t->tc_SPLower + SP_OFFSET;
694 #endif
696 t->tc_Node.ln_Name = "Idle Task";
697 t->tc_Node.ln_Pri = -128;
698 t->tc_Launch = &idleCount;
699 t->tc_Switch = &idleOff;
700 t->tc_Flags = TF_LAUNCH | TF_SWITCH;
701 NewAddTask(t, &idleTask, NULL, &tags);
702 idle_task = t;
705 return TRUE;
708 ADD2INITLIB(Kernel_Init, 0)