added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / arch / x86_64-pc / exec / exec_init.c
blob1c8691956d54e228ceb30207a49c5cea3248ea73
1 #include <inttypes.h>
2 #include <utility/tagitem.h>
3 #include <exec/resident.h>
4 #include <exec/nodes.h>
5 #include <exec/execbase.h>
6 #include <exec/memory.h>
7 #include <dos/bptr.h>
8 #include <dos/dosextens.h>
10 #include <aros/arossupportbase.h>
11 #include <aros/libcall.h>
12 #include <aros/asmcall.h>
13 #include <aros/debug.h>
14 #include <aros/kernel.h>
16 #include <asm/cpu.h>
17 #include <asm/segments.h>
19 #include <hardware/intbits.h>
20 #include <hardware/custom.h>
22 #include <proto/exec.h>
23 #include <proto/kernel.h>
25 #include <string.h>
26 #include <stdio.h>
28 #include "../bootstrap/multiboot.h"
30 #include "etask.h"
31 #include "exec_intern.h"
32 #include "exec_util.h"
34 #define __text __attribute__((section(".text")))
35 #define __no_ret __attribute__((noreturn))
36 #define __packed __attribute__((packed))
38 extern struct Library * PrepareAROSSupportBase (void);
39 extern const APTR LIBFUNCTABLE[] __text;
40 extern const APTR Exec_FuncTable[] __text;
41 void exec_DefaultTaskExit();
42 extern ULONG Exec_MakeFunctions(APTR, APTR, APTR, APTR);
43 IPTR **exec_RomTagScanner(struct TagItem *msg);
44 int exec_main(struct TagItem *msg, void *entry);
46 AROS_UFP5(void, SoftIntDispatch,
47 AROS_UFPA(ULONG, intReady, D1),
48 AROS_UFPA(struct Custom *, custom, A0),
49 AROS_UFPA(IPTR, intData, A1),
50 AROS_UFPA(IPTR, intCode, A5),
51 AROS_UFPA(struct ExecBase *, SysBase, A6));
53 AROS_UFP5S(void, IntServer,
54 AROS_UFPA(ULONG, intMask, D0),
55 AROS_UFPA(struct Custom *, custom, A0),
56 AROS_UFPA(struct List *, intList, A1),
57 AROS_UFPA(APTR, intCode, A5),
58 AROS_UFPA(struct ExecBase *, SysBase, A6));
61 struct TagItem *krnNextTagItem(const struct TagItem **tagListPtr);
62 struct TagItem *krnFindTagItem(Tag tagValue, const struct TagItem *tagList);
63 IPTR krnGetTagData(Tag tagValue, intptr_t defaultVal, const struct TagItem *tagList);
66 * First, we will define exec.library (global) to make it usable outside this
67 * file.
69 const char exec_name[] = "exec.library";
71 /* Now ID string as it will be used in a minute in resident structure. */
72 const char exec_idstring[] = "$VER: exec 41.11 (16.12.2000)\r\n";
74 /* We would need also version and revision fields placed somewhere here. */
75 const short exec_Version = 41;
76 const short exec_Revision = 11;
78 const struct __text Resident Exec_resident =
80 RTC_MATCHWORD, /* Magic value used to find resident */
81 &Exec_resident, /* Points to Resident itself */
82 &Exec_resident+1, /* Where could we find next Resident? */
83 0, /* There are no flags!! */
84 41, /* Version */
85 NT_LIBRARY, /* Type */
86 126, /* Very high startup priority. */
87 (STRPTR)exec_name, /* Pointer to name string */
88 (STRPTR)exec_idstring, /* Ditto */
89 exec_main /* Library initializer (for exec this value is irrelevant since we've jumped there at the begining to bring the system up */
92 void scr_RawPutChars(char *, int);
93 void clr();
94 void vesa_init(int width, int height, int depth, void *base);
96 char tab[512];
97 #ifdef rkprintf
98 #undef rkprintf
99 #endif
100 #define rkprintf(x...) scr_RawPutChars(tab, snprintf(tab, 510, x))
102 void _aros_not_implemented(char *string) {}
104 const char exec_chipname[] = "Chip Memory";
105 const char exec_fastname[] = "Fast Memory";
109 The MMU pages and directories. They are stored at fixed location and may be either reused in the
110 64-bit kernel, or replaced by it. Four PDE directories (PDE2M structures) are enough to map whole
111 4GB address space.
113 static struct PML4E PML4[512] __attribute__((used,aligned(4096)));
114 static struct PDPE PDP[512] __attribute__((used,aligned(4096)));
115 static struct PDE2M PDE[4][512] __attribute__((used,aligned(4096)));
117 void exec_InsertMemory(struct TagItem *msg, uintptr_t lower, uintptr_t upper)
119 struct ExecBase *SysBase = TLS_GET(SysBase); //*(struct ExecBase **)4UL;
121 uintptr_t kernLow = krnGetTagData(KRN_KernelLowest, 0, msg);
122 uintptr_t kernHigh = krnGetTagData(KRN_KernelHighest, 0, msg);
124 if (lower >= 0x100000000L)
125 return;
127 if (upper >= 0x100000000L)
128 upper = 0xffffffff;
130 /* Scenario 1: Kernel area outside the affected area. */
131 if (kernHigh < lower || kernLow > upper)
133 rkprintf("[exec] Adding %012p - %012p\n", lower, upper);
135 if (lower < 0x01000000)
136 AddMemList(upper-lower+1,
137 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL | MEMF_24BITDMA,
138 -10,
139 (APTR)lower,
140 (STRPTR)exec_chipname);
141 else
142 AddMemList(upper-lower+1,
143 MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL,
145 (APTR)lower,
146 (STRPTR)exec_fastname);
149 /* Scenario 2: Kernel area completely inside the memory region */
150 else if (kernLow >= (lower+sizeof(struct MemHeader)+sizeof(struct MemChunk)) && kernHigh <= upper)
152 rkprintf("[exec] Adding %012p - %012p\n", lower, upper);
154 if (lower < 0x01000000)
155 AddMemList(upper-lower+1,
156 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL | MEMF_24BITDMA,
157 -10,
158 (APTR)lower,
159 (STRPTR)exec_chipname);
160 else
161 AddMemList(upper-lower+1,
162 MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL,
164 (APTR)lower,
165 (STRPTR)exec_fastname);
166 rkprintf("[exec] rejecting %012p - %012p\n", kernLow, kernHigh);
167 AllocAbs(kernHigh-kernLow+1, kernLow);
169 /* Scenario 3: Kernel in lower portion of memory region */
170 else if (kernLow <= (lower+sizeof(struct MemHeader)+sizeof(struct MemChunk)) && kernHigh <= upper)
172 lower = (kernHigh + 4095) & ~4095;
173 rkprintf("[exec] Adding %012p - %012p\n", lower, upper);
175 if (lower < 0x01000000)
176 AddMemList(upper-lower+1,
177 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL | MEMF_24BITDMA,
178 -10,
179 (APTR)lower,
180 (STRPTR)exec_chipname);
181 else
182 AddMemList(upper-lower+1,
183 MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL,
185 (APTR)lower,
186 (STRPTR)exec_fastname);
188 /* Scenario 3: Kernel in upper portion of memory region */
189 else if (kernLow >= (lower+sizeof(struct MemHeader)+sizeof(struct MemChunk)) && kernHigh >= upper)
191 upper = kernLow & ~4095;
192 rkprintf("[exec] Adding %012p - %012p\n", lower, upper);
194 if (lower < 0x01000000)
195 AddMemList(upper-lower+1,
196 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL | MEMF_24BITDMA,
197 -10,
198 (APTR)lower,
199 (STRPTR)exec_chipname);
200 else
201 AddMemList(upper-lower+1,
202 MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL,
204 (APTR)lower,
205 (STRPTR)exec_fastname);
209 int exec_main(struct TagItem *msg, void *entry)
211 struct ExecBase *SysBase;
212 int i;
213 struct vbe_mode *mode;
215 if ((mode=krnGetTagData(KRN_VBEModeInfo, 0, msg)))
217 vesa_init(mode->x_resolution, mode->y_resolution,
218 mode->bits_per_pixel, (void*)mode->phys_base);
221 clr();
222 rkprintf("[exec] AROS64 - The AROS Research OS, 64-bit version\n[exec] Compiled %s\n",__DATE__);
224 /* Prepare the exec base */
226 ULONG negsize = LIB_VECTSIZE; /* size of vector table */
227 void **fp = Exec_FuncTable; //LIBFUNCTABLE; /* pointer to a function in the table */
229 rkprintf("[exec] Preparing the ExecBase...\n");
231 /* Calculate the size of the vector table */
232 while (*fp++ != (APTR) -1) negsize += LIB_VECTSIZE;
233 SysBase = (struct ExecBase *)(0x1000 + negsize);
235 rkprintf("[exec] Clearing ExecBase\n");
237 /* How about clearing most of ExecBase structure? */
238 bzero(&SysBase->IntVects[0], sizeof(struct ExecBase) - offsetof(struct ExecBase, IntVects[0]));
240 SysBase->KickMemPtr = NULL;
241 SysBase->KickTagPtr = NULL;
242 SysBase->KickCheckSum = NULL;
244 /* How about clearing most of ExecBase structure? */
245 bzero(&SysBase->IntVects[0], sizeof(struct ExecBase) - offsetof(struct ExecBase, IntVects[0]));
248 * Now everything is prepared to store ExecBase at the location 4UL and set
249 * it complement in ExecBase structure
252 rkprintf("[exec] Initializing library...\n");
254 //*(struct ExecBase **)4 = SysBase;
255 SysBase->ChkBase = ~(ULONG)SysBase;
257 /* Store sysbase in TLS */
258 TLS_SET(SysBase, SysBase);
260 /* Set up system stack */
261 // tss->ssp = (extmem) ? extmem : locmem; /* Either in FAST or in CHIP */
262 // SysBase->SysStkUpper = (APTR)stack_end;
263 // SysBase->SysStkLower = (APTR)&stack[0]; /* 64KB of system stack */
265 /* Store memory configuration */
266 SysBase->MaxLocMem = (IPTR)0; //locmem;
267 SysBase->MaxExtMem = (APTR)0; //extmem;
270 * Initialize exec lists. This is done through information table which consist
271 * of offset from begining of ExecBase and type of the list.
273 NEWLIST(&SysBase->MemList);
274 SysBase->MemList.lh_Type = NT_MEMORY;
275 NEWLIST(&SysBase->ResourceList);
276 SysBase->ResourceList.lh_Type = NT_RESOURCE;
277 NEWLIST(&SysBase->DeviceList);
278 SysBase->DeviceList.lh_Type = NT_DEVICE;
279 NEWLIST(&SysBase->LibList);
280 SysBase->LibList.lh_Type = NT_LIBRARY;
281 NEWLIST(&SysBase->PortList);
282 SysBase->PortList.lh_Type = NT_MSGPORT;
283 NEWLIST(&SysBase->TaskReady);
284 SysBase->TaskReady.lh_Type = NT_TASK;
285 NEWLIST(&SysBase->TaskWait);
286 SysBase->TaskWait.lh_Type = NT_TASK;
287 NEWLIST(&SysBase->IntrList);
288 SysBase->IntrList.lh_Type = NT_INTERRUPT;
289 NEWLIST(&SysBase->SemaphoreList);
290 SysBase->SemaphoreList.lh_Type = NT_SIGNALSEM;
291 NEWLIST(&SysBase->ex_MemHandlers);
293 for (i=0; i<5; i++)
295 NEWLIST(&SysBase->SoftInts[i].sh_List);
296 SysBase->SoftInts[i].sh_List.lh_Type = NT_SOFTINT;
300 * Exec.library initializer. Prepares exec.library for future use. All
301 * lists have to be initialized, some values from ROM are copied.
304 SysBase->TaskTrapCode = NULL; //exec_DefaultTrap;
305 SysBase->TaskExceptCode = NULL; //exec_DefaultTrap;
306 SysBase->TaskExitCode = exec_DefaultTaskExit;
307 SysBase->TaskSigAlloc = 0x0000ffff;
308 SysBase->TaskTrapAlloc = 0x8000;
310 /* Prepare values for execBase (like name, type, pri and other) */
312 SysBase->LibNode.lib_Node.ln_Type = NT_LIBRARY;
313 SysBase->LibNode.lib_Node.ln_Pri = 0;
314 SysBase->LibNode.lib_Node.ln_Name = (char *)exec_name;
315 SysBase->LibNode.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
316 SysBase->LibNode.lib_PosSize = sizeof(struct ExecBase);
317 SysBase->LibNode.lib_OpenCnt = 1;
318 SysBase->LibNode.lib_IdString = (char *)exec_idstring;
319 SysBase->LibNode.lib_Version = exec_Version;
320 SysBase->LibNode.lib_Revision = exec_Revision;
322 SysBase->Quantum = 4;
323 SysBase->VBlankFrequency = 50;
324 SysBase->PowerSupplyFrequency = 1;
326 /* Build the jumptable */
327 SysBase->LibNode.lib_NegSize =
328 Exec_MakeFunctions(SysBase, Exec_FuncTable, NULL, SysBase);
330 SumLibrary((struct Library *)SysBase);
332 rkprintf("[exec] Adding memory\n");
333 struct mb_mmap *mmap;
334 uint32_t len = krnGetTagData(KRN_MMAPLength, 0, msg);
336 if (len)
338 mmap = (struct mb_mmap *)(krnGetTagData(KRN_MMAPAddress, 0, msg));
340 while(len >= sizeof(struct mb_mmap))
342 if (mmap->type == MMAP_TYPE_RAM)
344 uintptr_t addr = (mmap->addr_low | ((intptr_t)mmap->addr_high << 32));
345 uintptr_t size = (mmap->len_low | ((intptr_t)mmap->len_high << 32));
346 uintptr_t tmp;
348 #warning TODO: Add proper handling of the memory above 4GB!
351 if (addr < (uintptr_t)SysBase)
353 tmp = ((uintptr_t)SysBase +sizeof(struct ExecBase)+ 4095) & ~4095;
354 size -= (tmp-addr);
355 addr = tmp;
357 rkprintf("[exec] %012p - %012p\n", addr, addr+size-1);
359 if (addr < 0x01000000 && (addr+size) <= 0x01000000)
361 exec_InsertMemory(msg, addr, addr+size-1);
363 else if (addr < 0x01000000 && (addr+size) > 0x01000000)
365 exec_InsertMemory(msg, addr, 0x00ffffff);
366 exec_InsertMemory(msg, 0x01000000, addr+size-1);
368 else
370 exec_InsertMemory(msg, addr, addr+size-1);
374 len -= mmap->size+4;
375 mmap = (struct mb_mmap *)(mmap->size + (IPTR)mmap+4);
380 SumLibrary((struct Library *)SysBase);
382 Enqueue(&SysBase->LibList,&SysBase->LibNode.lib_Node);
384 SysBase->DebugAROSBase = PrepareAROSSupportBase();
386 rkprintf("[exec] ExecBase=%012p\n", SysBase);
388 for (i=0; i<16; i++)
390 if( (1<<i) & (INTF_PORTS|INTF_COPER|INTF_VERTB|INTF_EXTER|INTF_SETCLR))
392 struct Interrupt *is;
393 struct SoftIntList *sil;
394 is = AllocMem
396 sizeof(struct Interrupt) + sizeof(struct SoftIntList),
397 MEMF_CLEAR | MEMF_PUBLIC
399 if( is == NULL )
401 rkprintf("[exec] ERROR: Cannot install Interrupt Servers!\n");
403 sil = (struct SoftIntList *)((struct Interrupt *)is + 1);
405 is->is_Code = &IntServer;
406 is->is_Data = sil;
407 NEWLIST((struct List *)sil);
408 SetIntVector(i,is);
410 else
412 struct Interrupt *is;
413 switch (i)
415 case INTB_SOFTINT :
416 is = AllocMem
418 sizeof(struct Interrupt),
419 MEMF_CLEAR | MEMF_PUBLIC
421 if (is == NULL)
423 rkprintf("[exec] Error: Cannot install Interrupt Servers!\n");
424 // Alert(AT_DeadEnd | AN_IntrMem);
426 is->is_Node.ln_Type = NT_SOFTINT; //INTERRUPT;
427 is->is_Node.ln_Pri = 0;
428 is->is_Node.ln_Name = "SW Interrupt Dispatcher";
429 is->is_Data = NULL;
430 is->is_Code = (void *)SoftIntDispatch;
431 SetIntVector(i,is);
432 break;
437 /* Enable interrupts and set int disable level to -1 */
438 asm("sti");
439 SysBase->TDNestCnt = -1;
440 SysBase->IDNestCnt = -1;
442 /* Now it's time to calculate exec checksum. It will be used
443 * in future to distinguish whether we'd had proper execBase
444 * before restart */
446 UWORD sum=0, *ptr = &SysBase->SoftVer;
447 int i=((IPTR)&SysBase->IntVects[0] - (IPTR)&SysBase->SoftVer) / 2,
450 /* Calculate sum for every static part from SoftVer to ChkSum */
451 for (j=0;j < i;j++)
453 sum+=*(ptr++);
456 SysBase->ChkSum = ~sum;
459 rkprintf("[exec] Creating the very first task...\n");
461 /* Create boot task. Sigh, we actually create a Process sized Task,
462 since DOS needs to call things which think it has a Process and
463 we don't want to overwrite memory with something strange do we?
465 We do this until at least we can boot dos more cleanly.
468 struct Task *t;
469 struct MemList *ml;
471 ml = (struct MemList *)AllocMem(sizeof(struct MemList), MEMF_PUBLIC|MEMF_CLEAR);
472 t = (struct Task *) AllocMem(sizeof(struct Process), MEMF_PUBLIC|MEMF_CLEAR);
474 if( !ml || !t )
476 rkprintf("[exec] ERROR: Cannot create Boot Task!\n");
478 ml->ml_NumEntries = 1;
479 ml->ml_ME[0].me_Addr = t;
480 ml->ml_ME[0].me_Length = sizeof(struct Process);
482 NEWLIST(&t->tc_MemEntry);
483 NEWLIST(&((struct Process *)t)->pr_MsgPort.mp_MsgList);
485 /* It's the boot process that RunCommand()s the boot shell, so we
486 must have this list initialized */
487 NEWLIST((struct List *)&((struct Process *)t)->pr_LocalVars);
489 AddHead(&t->tc_MemEntry,&ml->ml_Node);
491 t->tc_Node.ln_Name = exec_name;
492 t->tc_Node.ln_Pri = 0;
493 t->tc_Node.ln_Type = NT_TASK;
494 t->tc_State = TS_RUN;
495 t->tc_SigAlloc = 0xFFFF;
496 t->tc_SPLower = 0; /* This is the system's stack */
497 t->tc_SPUpper = (APTR)~0UL;
498 t->tc_Flags |= TF_ETASK;
500 if (t->tc_Flags & TF_ETASK)
502 t->tc_UnionETask.tc_ETask = AllocTaskMem(t, sizeof(struct IntETask), MEMF_ANY|MEMF_CLEAR);
504 if (!t->tc_UnionETask.tc_ETask)
506 rkprintf("[exec] Not enough memory for first task\n");
509 GetIntETask(t)->iet_Context = AllocTaskMem(t
510 , SIZEOF_ALL_REGISTERS
511 , MEMF_PUBLIC|MEMF_CLEAR
514 if (!GetIntETask(t)->iet_Context)
516 rkprintf("[exec] Not enough memory for first task\n");
520 SysBase->ThisTask = t;
523 rkprintf("[exec] Done. SysBase->ThisTask = 0x%012p\n[exec] Leaving supervisor mode\n", SysBase->ThisTask);
525 asm volatile (
526 "mov %[user_ds],%%ds\n\t" // Load DS and ES
527 "mov %[user_ds],%%es\n\t"
528 "mov %%rsp,%%r12\n\t"
529 "pushq %[ds]\n\t" // SS
530 "pushq %%r12\n\t" // rSP
531 "pushq $0x3002\n\t" // rFLANGS
532 "pushq %[cs]\n\t" // CS
533 "pushq $1f\n\t iretq\n 1:"
534 ::[user_ds]"r"(USER_DS),[ds]"i"(USER_DS),[cs]"i"(USER_CS):"r12");
535 rkprintf("[exec] Done?! Still here?\n");
537 SysBase->TDNestCnt++;
538 Permit();
540 /* Scan for valid RomTags */
541 SysBase->ResModules = exec_RomTagScanner(msg);
545 rkprintf("[exec] InitCode(RTF_SINGLETASK)\n");
546 InitCode(RTF_SINGLETASK, 0);
548 rkprintf("[exec] InitCode(RTF_COLDSTART)\n");
549 InitCode(RTF_COLDSTART, 0);
552 rkprintf("[exec] I should never get here...\n");
553 while(1) asm volatile("nop");
554 return 0;
558 void exec_DefaultTaskExit()
560 struct ExecBase *SysBase = TLS_GET(SysBase); //*(struct ExecBase **)4UL;
561 RemTask(SysBase->ThisTask);
565 AROS_LH1(struct ExecBase *, open,
566 AROS_LHA(ULONG, version, D0),
567 struct ExecBase *, SysBase, 1, Exec)
569 AROS_LIBFUNC_INIT
571 /* I have one more opener. */
572 SysBase->LibNode.lib_OpenCnt++;
573 return SysBase;
575 AROS_LIBFUNC_EXIT
578 AROS_LH0(BPTR, close,
579 struct ExecBase *, SysBase, 2, Exec)
581 AROS_LIBFUNC_INIT
583 /* I have one fewer opener. */
584 SysBase->LibNode.lib_OpenCnt--;
585 return 0;
586 AROS_LIBFUNC_EXIT
589 AROS_LH0I(int, null,
590 struct ExecBase *, SysBase, 4, Exec)
592 AROS_LIBFUNC_INIT
593 return 0;
594 AROS_LIBFUNC_EXIT
598 * RomTag scanner.
600 * This function scans kernel for existing Resident modules. If two modules
601 * with the same name are found, the one with higher version or priority wins.
603 * After building list of kernel modules, the KickTagPtr and KickMemPtr are
604 * checksummed. If checksum is proper and all memory pointed in KickMemPtr may
605 * be allocated, then all modules from KickTagPtr are added to RT list
607 * Afterwards the proper RomTagList is created (see InitCode() for details) and
608 * memory after list and nodes is freed.
611 struct rt_node
613 struct Node node;
614 struct Resident *module;
617 IPTR **exec_RomTagScanner(struct TagItem *msg)
619 struct ExecBase *SysBase = TLS_GET(SysBase); //*(struct ExecBase **)4UL;
621 struct List rtList; /* List of modules */
622 UWORD *ptr = (UWORD*)krnGetTagData(KRN_KernelLowest, 0, msg); /* Start looking here */
623 UWORD *maxptr = (UWORD*)krnGetTagData(KRN_KernelHighest, 0, msg);
624 struct Resident *res; /* module found */
626 int i;
627 IPTR **RomTag;
629 /* Initialize list */
630 NEWLIST(&rtList);
632 rkprintf("[exec] Resident modules (addr: pri version name):\n");
634 /* Look in whole kernel for resident modules */
637 /* Do we have RTC_MATCHWORD? */
638 if (*ptr == RTC_MATCHWORD)
640 /* Yes, assume we have Resident */
641 res = (struct Resident *)ptr;
643 /* Does rt_MatchTag point to Resident? */
644 if (res == res->rt_MatchTag)
646 /* Yes, it is Resident module */
647 struct rt_node *node;
649 /* Check if there is module with such name already */
650 node = (struct rt_node*)FindName(&rtList, res->rt_Name);
651 if (node)
653 /* Yes, there was such module. It it had lower pri then replace it */
654 if (node->node.ln_Pri <= res->rt_Pri)
656 /* If they have the same Pri but new one has higher Version, replace */
657 if ((node->node.ln_Pri == res->rt_Pri) &&
658 (node->module->rt_Version < res->rt_Version))
660 node->node.ln_Pri = res->rt_Pri;
661 node->module = res;
665 else
667 /* New module. Allocate some memory for it */
668 node = (struct rt_node *)
669 AllocMem(sizeof(struct rt_node),MEMF_PUBLIC|MEMF_CLEAR);
671 if (node)
673 node->node.ln_Name = res->rt_Name;
674 node->node.ln_Pri = res->rt_Pri;
675 node->module = res;
677 Enqueue(&rtList,(struct Node*)node);
680 ptr+=sizeof(struct Resident)/sizeof(UWORD);
681 continue;
685 /* Get next address... */
686 ptr++;
687 } while (ptr < maxptr);
690 * By now we have valid (and sorted) list of kernel resident modules.
692 * Now, we will have to analyze used-defined RomTags (via KickTagPtr and
693 * KickMemPtr)
695 #warning "TODO: Implement external modules!"
697 * Everything is done now. Allocate buffer for normal RomTag and convert
698 * list to RomTag
701 ListLength(&rtList,i); /* Get length of the list */
703 RomTag = AllocMem((i+1)*sizeof(IPTR),MEMF_PUBLIC | MEMF_CLEAR);
705 if (RomTag)
707 int j;
708 struct rt_node *n;
710 for (j=0; j<i; j++)
712 n = (struct rt_node *)RemHead(&rtList);
713 rkprintf("[exec] + 0x%012lx: %4d %3d \"%s\"\n",
714 n->module,
715 n->node.ln_Pri,
716 n->module->rt_Version,
717 n->node.ln_Name);
718 RomTag[j] = (IPTR*)n->module;
719 FreeMem(n, sizeof(struct rt_node));
721 RomTag[i] = 0;
724 return RomTag;
730 We temporarily redefine kprintf() so we use the real version in case
731 we have one of these two fn's called before AROSSupportBase is ready.
734 #undef kprintf
735 #undef rkprintf
736 #undef vkprintf
738 #define kprintf(x...)
739 #define rkprintf(x...)
740 #define vkprintf(x...)
742 struct Library * PrepareAROSSupportBase(void)
744 struct ExecBase *SysBase = TLS_GET(SysBase); //*(struct ExecBase **)4UL;
746 struct AROSSupportBase *AROSSupportBase =
747 AllocMem(sizeof(struct AROSSupportBase), MEMF_CLEAR);
749 AROSSupportBase->kprintf = (void *)kprintf;
750 AROSSupportBase->rkprintf = (void *)rkprintf;
751 AROSSupportBase->vkprintf = (void *)vkprintf;
753 NEWLIST(&AROSSupportBase->AllocMemList);
755 #warning "FIXME Add code to read in the debug options"
757 return (struct Library *)AROSSupportBase;
760 /* IntServer:
761 This interrupt handler will send an interrupt to a series of queued
762 interrupt servers. Servers should return D0 != 0 (Z clear) if they
763 believe the interrupt was for them, and no further interrupts will
764 be called. This will only check the value in D0 for non-m68k systems,
765 however it SHOULD check the Z-flag on 68k systems.
767 Hmm, in that case I would have to separate it from this file in order
768 to replace it...
770 AROS_UFH5S(void, IntServer,
771 AROS_UFHA(ULONG, intMask, D0),
772 AROS_UFHA(struct Custom *, custom, A0),
773 AROS_UFHA(struct List *, intList, A1),
774 AROS_UFHA(APTR, intCode, A5),
775 AROS_UFHA(struct ExecBase *, SysBase, A6))
777 AROS_USERFUNC_INIT
779 struct Interrupt * irq;
781 ForeachNode(intList, irq)
783 if( AROS_UFC4(int, irq->is_Code,
784 AROS_UFCA(struct Custom *, custom, A0),
785 AROS_UFCA(APTR, irq->is_Data, A1),
786 AROS_UFCA(APTR, irq->is_Code, A5),
787 AROS_UFCA(struct ExecBase *, SysBase, A6)
789 break;
792 AROS_USERFUNC_EXIT