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>
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>
21 #include "exec_util.h"
23 #include "exec_intern.h"
27 #include "../kernel/kernel_intern.h"
29 D(extern void debugmem(void));
31 void exec_main(struct TagItem
*msg
, void *entry
);
32 extern CONST_APTR Exec_FuncTable
[];
33 extern ULONG
Exec_15_MakeFunctions(APTR
, CONST_APTR
, CONST_APTR
, struct ExecBase
*);
34 void exec_DefaultTaskExit();
35 IPTR
**exec_RomTagScanner(struct TagItem
*msg
);
36 extern struct Library
* PrepareAROSSupportBase (void);
38 AROS_UFP5(void, SoftIntDispatch
,
39 AROS_UFPA(ULONG
, intReady
, D1
),
40 AROS_UFPA(struct Custom
*, custom
, A0
),
41 AROS_UFPA(IPTR
, intData
, A1
),
42 AROS_UFPA(IPTR
, intCode
, A5
),
43 AROS_UFPA(struct ExecBase
*, SysBase
, A6
));
45 AROS_UFP5S(void, IntServer
,
46 AROS_UFPA(ULONG
, intMask
, D0
),
47 AROS_UFPA(struct Custom
*, custom
, A0
),
48 AROS_UFPA(struct List
*, intList
, A1
),
49 AROS_UFPA(APTR
, intCode
, A5
),
50 AROS_UFPA(struct ExecBase
*, SysBase
, A6
));
52 const char exec_name
[] = "exec.library";
53 const char exec_idstring
[] = "$VER: exec 41.11 (16.12.2000)\r\n";
54 const char exec_chipname
[] = "Chip Memory";
55 const char exec_fastname
[] = "Fast Memory";
57 const short exec_Version
= 41;
58 const short exec_Revision
= 11;
60 const struct __attribute__((section(".text"))) Resident Exec_resident
=
62 RTC_MATCHWORD
, /* Magic value used to find resident */
63 &Exec_resident
, /* Points to Resident itself */
64 (APTR
)&Exec_resident
+1, /* Where could we find next Resident? */
65 0, /* There are no flags!! */
67 NT_LIBRARY
, /* Type */
68 126, /* Very high startup priority. */
69 (STRPTR
)exec_name
, /* Pointer to name string */
70 (STRPTR
)exec_idstring
, /* Ditto */
71 exec_main
/* Library initializer (for exec this value is irrelevant since we've jumped there at the begining to bring the system up */
74 static uint32_t exec_SelectMbs(uint32_t bcr
)
76 switch (bcr
& SDRAM_SDSZ_MASK
)
78 case SDRAM_SDSZ_256MB
: return 256;
79 case SDRAM_SDSZ_128MB
: return 128;
80 case SDRAM_SDSZ_64MB
: return 64;
81 case SDRAM_SDSZ_32MB
: return 32;
82 case SDRAM_SDSZ_16MB
: return 16;
83 case SDRAM_SDSZ_8MB
: return 8;
89 /* Detect and report amount of available memory in mega bytes via device control register bus */
90 static uint32_t exec_GetMemory()
93 wrdcr(SDRAM0_CFGADDR
, SDRAM0_B0CR
);
94 mem
= exec_SelectMbs(rddcr(SDRAM0_CFGDATA
));
95 //D(bug("[exec] B0CR %08x %uM\n", rddcr(SDRAM0_CFGDATA), mem));
97 wrdcr(SDRAM0_CFGADDR
, SDRAM0_B1CR
);
98 mem
+= exec_SelectMbs(rddcr(SDRAM0_CFGDATA
));
99 //D(bug("[exec] B1CR %08x %uM\n", rddcr(SDRAM0_CFGDATA), mem));
101 wrdcr(SDRAM0_CFGADDR
, SDRAM0_B2CR
);
102 mem
+= exec_SelectMbs(rddcr(SDRAM0_CFGDATA
));
103 //D(bug("[exec] B2CR %08x %uM\n", rddcr(SDRAM0_CFGDATA), mem));
105 wrdcr(SDRAM0_CFGADDR
, SDRAM0_B3CR
);
106 mem
+= exec_SelectMbs(rddcr(SDRAM0_CFGDATA
));
107 //D(bug("[exec] B3CR %08x %uM\n", rddcr(SDRAM0_CFGDATA), mem));
112 void exec_main(struct TagItem
*msg
, void *entry
)
114 struct ExecBase
*SysBase
= NULL
;
115 uintptr_t lowmem
= 0;
119 D(bug("[exec] AROS for Sam440 - The AROS Research OS\n"));
121 /* Prepare the exec base */
123 ULONG negsize
= LIB_VECTSIZE
; /* size of vector table */
124 CONST_APTR
*fp
= Exec_FuncTable
; /* pointer to a function in the table */
126 D(bug("[exec] Preparing the ExecBase...\n"));
128 /* Calculate the size of the vector table */
129 while (*fp
++ != (APTR
) -1) negsize
+= LIB_VECTSIZE
;
131 /* Align the offset for SysBase to the cache line */
132 negsize
= (negsize
+ 31) & ~31;
134 /* Get the lowest usable memory location */
135 lowmem
= (krnGetTagData(KRN_KernelHighest
, 0, msg
) + 0xffff) & 0xffff0000;
137 /* And now let's have the SysBase */
138 SysBase
= (struct ExecBase
*)(lowmem
+ negsize
);
139 wrspr(SPRG5
, SysBase
);
140 lowmem
= (lowmem
+ negsize
+ sizeof(struct IntExecBase
) + 4095) & ~4095;
142 D(bug("[exec] ExecBase at %08x\n", SysBase
));
144 D(bug("[exec] Clearing ExecBase\n"));
146 /* How about clearing most of ExecBase structure? */
147 bzero(&SysBase
->IntVects
[0], sizeof(struct IntExecBase
) - offsetof(struct ExecBase
, IntVects
[0]));
149 SysBase
->KickMemPtr
= NULL
;
150 SysBase
->KickTagPtr
= NULL
;
151 SysBase
->KickCheckSum
= NULL
;
154 * Now everything is prepared to store ExecBase at the location 4UL and set
155 * it complement in ExecBase structure
158 D(bug("[exec] Initializing library...\n"));
160 SysBase
->ChkBase
= ~(ULONG
)SysBase
;
162 /* Store memory configuration */
163 SysBase
->MaxLocMem
= (IPTR
)0; //locmem;
164 SysBase
->MaxExtMem
= (APTR
)0; //extmem;
167 * Initialize exec lists. This is done through information table which consist
168 * of offset from begining of ExecBase and type of the list.
170 NEWLIST(&SysBase
->MemList
);
171 SysBase
->MemList
.lh_Type
= NT_MEMORY
;
172 NEWLIST(&SysBase
->ResourceList
);
173 SysBase
->ResourceList
.lh_Type
= NT_RESOURCE
;
174 NEWLIST(&SysBase
->DeviceList
);
175 SysBase
->DeviceList
.lh_Type
= NT_DEVICE
;
176 NEWLIST(&SysBase
->LibList
);
177 SysBase
->LibList
.lh_Type
= NT_LIBRARY
;
178 NEWLIST(&SysBase
->PortList
);
179 SysBase
->PortList
.lh_Type
= NT_MSGPORT
;
180 NEWLIST(&SysBase
->TaskReady
);
181 SysBase
->TaskReady
.lh_Type
= NT_TASK
;
182 NEWLIST(&SysBase
->TaskWait
);
183 SysBase
->TaskWait
.lh_Type
= NT_TASK
;
184 NEWLIST(&SysBase
->IntrList
);
185 SysBase
->IntrList
.lh_Type
= NT_INTERRUPT
;
186 NEWLIST(&SysBase
->SemaphoreList
);
187 SysBase
->SemaphoreList
.lh_Type
= NT_SIGNALSEM
;
188 NEWLIST(&SysBase
->ex_MemHandlers
);
192 NEWLIST(&SysBase
->SoftInts
[i
].sh_List
);
193 SysBase
->SoftInts
[i
].sh_List
.lh_Type
= NT_SOFTINT
;
197 * Exec.library initializer. Prepares exec.library for future use. All
198 * lists have to be initialized, some values from ROM are copied.
201 SysBase
->TaskTrapCode
= NULL
; //exec_DefaultTrap;
202 SysBase
->TaskExceptCode
= NULL
; //exec_DefaultTrap;
203 SysBase
->TaskExitCode
= exec_DefaultTaskExit
;
204 SysBase
->TaskSigAlloc
= 0x0000ffff;
205 SysBase
->TaskTrapAlloc
= 0x8000;
207 /* Prepare values for execBase (like name, type, pri and other) */
209 SysBase
->LibNode
.lib_Node
.ln_Type
= NT_LIBRARY
;
210 SysBase
->LibNode
.lib_Node
.ln_Pri
= 0;
211 SysBase
->LibNode
.lib_Node
.ln_Name
= (char *)exec_name
;
212 SysBase
->LibNode
.lib_Flags
= LIBF_CHANGED
| LIBF_SUMUSED
;
213 SysBase
->LibNode
.lib_PosSize
= sizeof(struct IntExecBase
);
214 SysBase
->LibNode
.lib_OpenCnt
= 1;
215 SysBase
->LibNode
.lib_IdString
= (char *)exec_idstring
;
216 SysBase
->LibNode
.lib_Version
= exec_Version
;
217 SysBase
->LibNode
.lib_Revision
= exec_Revision
;
219 SysBase
->Quantum
= 4;
220 SysBase
->VBlankFrequency
= 50;
221 SysBase
->PowerSupplyFrequency
= 1;
223 NEWLIST(&PrivExecBase(SysBase
)->ResetHandlers
);
224 NEWLIST(&PrivExecBase(SysBase
)->AllocMemList
);
226 #if AROS_MUNGWALL_DEBUG
228 * TODO: implement command line parsing instead of this awkward hack
229 * Or, even better, merge this init code with arch-independent one
231 PrivExecBase(SysBase
)->IntFlags
= EXECF_MungWall
;
234 /* Build the jumptable */
235 SysBase
->LibNode
.lib_NegSize
=
236 Exec_15_MakeFunctions(SysBase
, Exec_FuncTable
, NULL
, SysBase
);
238 SumLibrary((struct Library
*)SysBase
);
240 InitSemaphore(&PrivExecBase(SysBase
)->MemListSem
);
241 InitSemaphore(&PrivExecBase(SysBase
)->LowMemSem
);
243 mem
= exec_GetMemory();
244 D(bug("[exec] Adding memory (%uM)\n", mem
));
246 AddMemList(0x01000000 - lowmem
,
247 MEMF_CHIP
| MEMF_PUBLIC
| MEMF_KICK
| MEMF_LOCAL
| MEMF_24BITDMA
,
250 (STRPTR
)exec_chipname
);
252 AddMemList((mem
- 16) * 1024*1024,
253 MEMF_FAST
| MEMF_PUBLIC
| MEMF_KICK
| MEMF_LOCAL
,
256 (STRPTR
)exec_fastname
);
258 SumLibrary((struct Library
*)SysBase
);
260 Enqueue(&SysBase
->LibList
,&SysBase
->LibNode
.lib_Node
);
262 SysBase
->DebugAROSBase
= PrepareAROSSupportBase();
264 /* Scan for valid RomTags */
265 SysBase
->ResModules
= exec_RomTagScanner(msg
);
267 D(bug("[exec] InitCode(RTF_SINGLETASK)\n"));
268 InitCode(RTF_SINGLETASK
, 0);
270 PrivExecBase(SysBase
)->KernelBase
= OpenResource("kernel.resource");
271 PrivExecBase(SysBase
)->PageSize
= MEMCHUNK_TOTAL
;
273 /* Install the interrupt servers */
276 if( (1<<i
) & (INTF_PORTS
|INTF_COPER
|INTF_VERTB
|INTF_EXTER
|INTF_SETCLR
))
278 struct Interrupt
*is
;
279 struct SoftIntList
*sil
;
282 sizeof(struct Interrupt
) + sizeof(struct SoftIntList
),
283 MEMF_CLEAR
| MEMF_PUBLIC
287 D(bug("[exec] ERROR: Cannot install Interrupt Servers!\n"));
289 sil
= (struct SoftIntList
*)((struct Interrupt
*)is
+ 1);
291 is
->is_Code
= &IntServer
;
293 NEWLIST((struct List
*)sil
);
298 struct Interrupt
*is
;
304 sizeof(struct Interrupt
),
305 MEMF_CLEAR
| MEMF_PUBLIC
309 D(bug("[exec] Error: Cannot install Interrupt Servers!\n"));
310 // Alert(AT_DeadEnd | AN_IntrMem);
312 is
->is_Node
.ln_Type
= NT_SOFTINT
; //INTERRUPT;
313 is
->is_Node
.ln_Pri
= 0;
314 is
->is_Node
.ln_Name
= "SW Interrupt Dispatcher";
316 is
->is_Code
= (void *)SoftIntDispatch
;
323 /* Now it's time to calculate exec checksum. It will be used
324 * in future to distinguish whether we'd had proper execBase
327 UWORD sum
=0, *ptr
= &SysBase
->SoftVer
;
328 int i
=((IPTR
)&SysBase
->IntVects
[0] - (IPTR
)&SysBase
->SoftVer
) / 2,
331 /* Calculate sum for every static part from SoftVer to ChkSum */
337 SysBase
->ChkSum
= ~sum
;
340 /* Create boot task. Sigh, we actually create a Process sized Task,
341 since DOS needs to call things which think it has a Process and
342 we don't want to overwrite memory with something strange do we?
344 We do this until at least we can boot dos more cleanly.
350 ml
= (struct MemList
*)AllocMem(sizeof(struct MemList
), MEMF_PUBLIC
|MEMF_CLEAR
);
351 t
= (struct Task
*) AllocMem(sizeof(struct Process
), MEMF_PUBLIC
|MEMF_CLEAR
);
355 D(bug("[exec] ERROR: Cannot create Boot Task!\n"));
357 ml
->ml_NumEntries
= 1;
358 ml
->ml_ME
[0].me_Addr
= t
;
359 ml
->ml_ME
[0].me_Length
= sizeof(struct Process
);
361 NEWLIST(&t
->tc_MemEntry
);
362 NEWLIST(&((struct Process
*)t
)->pr_MsgPort
.mp_MsgList
);
364 /* It's the boot process that RunCommand()s the boot shell, so we
365 must have this list initialized */
366 NEWLIST((struct List
*)&((struct Process
*)t
)->pr_LocalVars
);
368 AddHead(&t
->tc_MemEntry
,&ml
->ml_Node
);
370 t
->tc_Node
.ln_Name
= (char *)exec_name
;
371 t
->tc_Node
.ln_Pri
= 0;
372 t
->tc_Node
.ln_Type
= NT_TASK
;
373 t
->tc_State
= TS_RUN
;
374 t
->tc_SigAlloc
= 0xFFFF;
375 t
->tc_SPLower
= 0; /* This is the system's stack */
376 t
->tc_SPUpper
= (APTR
)~0UL;
377 t
->tc_Flags
|= TF_ETASK
;
379 if (t
->tc_Flags
& TF_ETASK
)
381 t
->tc_UnionETask
.tc_ETask
= AllocVec
383 sizeof(struct IntETask
),
387 if (!t
->tc_UnionETask
.tc_ETask
)
389 D(bug("[exec] Not enough memory for first task\n"));
392 /* Initialise the ETask data. */
393 InitETask(t
, t
->tc_UnionETask
.tc_ETask
);
395 GetIntETask(t
)->iet_Context
= AllocMem(SIZEOF_ALL_REGISTERS
396 , MEMF_PUBLIC
|MEMF_CLEAR
399 if (!GetIntETask(t
)->iet_Context
)
401 D(bug("[exec] Not enough memory for first task\n"));
405 SysBase
->ThisTask
= t
;
408 D(bug("[exec] Done. SysBase->ThisTask = %08p\n", SysBase
->ThisTask
));
410 /* We now start up the interrupts */
416 D(bug("[exec] InitCode(RTF_COLDSTART)\n"));
417 InitCode(RTF_COLDSTART
, 0);
419 D(bug("[exec] I should never get here...\n"));
426 * This function scans kernel for existing Resident modules. If two modules
427 * with the same name are found, the one with higher version or priority wins.
429 * After building list of kernel modules, the KickTagPtr and KickMemPtr are
430 * checksummed. If checksum is proper and all memory pointed in KickMemPtr may
431 * be allocated, then all modules from KickTagPtr are added to RT list
433 * Afterwards the proper RomTagList is created (see InitCode() for details) and
434 * memory after list and nodes is freed.
440 struct Resident
*module
;
444 void exec_DefaultTaskExit()
446 struct ExecBase
*SysBase
= getSysBase();
447 RemTask(SysBase
->ThisTask
);
450 IPTR
**exec_RomTagScanner(struct TagItem
*msg
)
452 struct ExecBase
*SysBase
= getSysBase();
454 struct List rtList
; /* List of modules */
455 UWORD
*ptr
= (UWORD
*)(krnGetTagData(KRN_KernelLowest
, 0, msg
) + 0xff000000); /* Start looking here */
456 UWORD
*maxptr
= (UWORD
*)(krnGetTagData(KRN_KernelHighest
, 0, msg
) + 0xff000000);
457 struct Resident
*res
; /* module found */
462 /* Initialize list */
465 D(bug("[exec] Resident modules (addr: pri version name):\n"));
467 /* Look in whole kernel for resident modules */
470 /* Do we have RTC_MATCHWORD? */
471 if (*ptr
== RTC_MATCHWORD
)
473 /* Yes, assume we have Resident */
474 res
= (struct Resident
*)ptr
;
476 /* Does rt_MatchTag point to Resident? */
477 if (res
== res
->rt_MatchTag
)
479 /* Yes, it is Resident module */
480 struct rt_node
*node
;
482 /* Check if there is module with such name already */
483 node
= (struct rt_node
*)FindName(&rtList
, res
->rt_Name
);
486 /* Yes, there was such module. It it had lower pri then replace it */
487 if (node
->node
.ln_Pri
<= res
->rt_Pri
)
489 /* If they have the same Pri but new one has higher Version, replace */
490 if ((node
->node
.ln_Pri
== res
->rt_Pri
) &&
491 (node
->module
->rt_Version
< res
->rt_Version
))
493 node
->node
.ln_Pri
= res
->rt_Pri
;
500 /* New module. Allocate some memory for it */
501 node
= (struct rt_node
*)
502 AllocMem(sizeof(struct rt_node
),MEMF_PUBLIC
|MEMF_CLEAR
);
506 node
->node
.ln_Name
= (char *)res
->rt_Name
;
507 node
->node
.ln_Pri
= res
->rt_Pri
;
510 Enqueue(&rtList
,(struct Node
*)node
);
513 ptr
+=sizeof(struct Resident
)/sizeof(UWORD
);
518 /* Get next address... */
520 } while (ptr
< maxptr
);
523 * By now we have valid (and sorted) list of kernel resident modules.
525 * Now, we will have to analyze used-defined RomTags (via KickTagPtr and
528 #warning "TODO: Implement external modules!"
530 * Everything is done now. Allocate buffer for normal RomTag and convert
534 ListLength(&rtList
,i
); /* Get length of the list */
536 RomTag
= AllocMem((i
+1)*sizeof(IPTR
),MEMF_PUBLIC
| MEMF_CLEAR
);
545 n
= (struct rt_node
*)RemHead(&rtList
);
546 D(bug("[exec] + 0x%08lx: %4d %3d \"%s\"\n",
549 n
->module
->rt_Version
,
551 RomTag
[j
] = (IPTR
*)n
->module
;
552 FreeMem(n
, sizeof(struct rt_node
));
560 AROS_LH1(struct ExecBase
*, open
,
561 AROS_LHA(ULONG
, version
, D0
),
562 struct ExecBase
*, SysBase
, 1, Exec
)
566 /* I have one more opener. */
567 SysBase
->LibNode
.lib_OpenCnt
++;
573 AROS_LH0(BPTR
, close
,
574 struct ExecBase
*, SysBase
, 2, Exec
)
578 /* I have one fewer opener. */
579 SysBase
->LibNode
.lib_OpenCnt
--;
585 struct ExecBase
*, SysBase
, 4, Exec
)
593 We temporarily redefine kprintf() so we use the real version in case
594 we have one of these two fn's called before AROSSupportBase is ready.
602 static int __kprintf(const UBYTE
*fmt
, ...)
606 void *KernelBase
= getKernelBase();
611 result
= KrnBug(fmt
, ap
);
617 static int __vkprintf(const UBYTE
*fmt
, va_list args
)
619 void *KernelBase
= getKernelBase();
622 return KrnBug(fmt
, args
);
627 static int __rkprintf(const STRPTR mainSystem
, const STRPTR subSystem
, int level
, const UBYTE
*fmt
, ...)
631 void *KernelBase
= getKernelBase();
636 result
= KrnBug(fmt
, ap
);
642 struct Library
* PrepareAROSSupportBase(void)
644 struct ExecBase
*SysBase
= getSysBase();
646 struct AROSSupportBase
*AROSSupportBase
=
647 AllocMem(sizeof(struct AROSSupportBase
), MEMF_CLEAR
);
649 AROSSupportBase
->kprintf
= (void *)__kprintf
;
650 AROSSupportBase
->rkprintf
= (void *)__rkprintf
;
651 AROSSupportBase
->vkprintf
= (void *)__vkprintf
;
653 return (struct Library
*)AROSSupportBase
;
657 This interrupt handler will send an interrupt to a series of queued
658 interrupt servers. Servers should return D0 != 0 (Z clear) if they
659 believe the interrupt was for them, and no further interrupts will
660 be called. This will only check the value in D0 for non-m68k systems,
661 however it SHOULD check the Z-flag on 68k systems.
663 Hmm, in that case I would have to separate it from this file in order
666 AROS_UFH5S(void, IntServer
,
667 AROS_UFHA(ULONG
, intMask
, D0
),
668 AROS_UFHA(struct Custom
*, custom
, A0
),
669 AROS_UFHA(struct List
*, intList
, A1
),
670 AROS_UFHA(APTR
, intCode
, A5
),
671 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
675 struct Interrupt
* irq
;
677 ForeachNode(intList
, irq
)
679 if( AROS_UFC4(int, irq
->is_Code
,
680 AROS_UFCA(struct Custom
*, custom
, A0
),
681 AROS_UFCA(APTR
, irq
->is_Data
, A1
),
682 AROS_UFCA(APTR
, irq
->is_Code
, A5
),
683 AROS_UFCA(struct ExecBase
*, SysBase
, A6
)
691 void _aros_not_implemented(char *string
) {}