2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: exec.library resident and initialization.
9 #include <exec/types.h>
10 #include <exec/lists.h>
11 #include <exec/execbase.h>
12 #include <exec/interrupts.h>
13 #include <exec/resident.h>
14 #include <exec/memory.h>
15 #include <exec/alerts.h>
16 #include <exec/tasks.h>
17 #include <hardware/intbits.h>
18 #include <hardware/custom.h>
19 #include <dos/dosextens.h>
21 #include <aros/system.h>
22 #include <aros/arossupportbase.h>
23 #include <aros/asmcall.h>
24 #include <aros/config.h>
26 #include <aros/debug.h>
28 #include <proto/arossupport.h>
29 #include <proto/exec.h>
30 #include <clib/macros.h> /* need ABS() */
32 #define timeval sys_timeval
37 #include "exec_util.h"
39 #include LC_LIBDEFS_FILE
41 static const UBYTE name
[];
42 static const UBYTE version
[];
43 extern const char LIBEND
;
44 struct ExecBase
*GM_UNIQUENAME(init
)();
46 const struct Resident Exec_resident
=
49 (struct Resident
*)&Exec_resident
,
60 static const UBYTE name
[] = MOD_NAME_STRING
;
61 static const UBYTE version
[] = VERSION_STRING
;
63 extern void debugmem(void);
64 extern void idleTask(struct ExecBase
*);
66 /**************** GLOBAL SYSBASE ***************/
67 #ifndef AROS_CREATE_ROM
68 struct ExecBase
* SysBase
= NULL
;
72 We temporarily redefine kprintf() so we use the real version in case
73 we have one of these two fn's called before AROSSupportBase is ready.
79 struct Library
* PrepareAROSSupportBase (struct ExecBase
* SysBase
)
81 struct AROSSupportBase
* AROSSupportBase
;
82 AROSSupportBase
= AllocMem(sizeof(struct AROSSupportBase
), MEMF_CLEAR
);
83 AROSSupportBase
->kprintf
= (void *)kprintf
;
84 AROSSupportBase
->rkprintf
= (void *)rkprintf
;
85 AROSSupportBase
->vkprintf
= (void *)vkprintf
;
86 NEWLIST(&AROSSupportBase
->AllocMemList
);
88 #warning FIXME Add code to read in the debug options
90 return (struct Library
*)AROSSupportBase
;
93 void AROSSupportBase_SetStdOut (struct AROSSupportBase
* AROSSupportBase
, void * stdout
)
95 AROSSupportBase
->StdOut
= stdout
;
98 void _aros_not_implemented(char *X
)
100 kprintf("Unsupported function at offset -0x%h in %s\n",
101 ABS(*(WORD
*)((&X
)[-1]-2)),
102 ((struct Library
*)(&X
)[-2])->lib_Node
.ln_Name
);
104 #define kprintf (((struct AROSSupportBase *)(SysBase->DebugAROSBase))->kprintf)
105 #define rkprintf (((struct AROSSupportBase *)(SysBase->DebugAROSBase))->rkprintf)
106 #define vkprintf (((struct AROSSupportBase *)(SysBase->DebugAROSBase))->vkprintf)
109 This interrupt handler will send an interrupt to a series of queued
110 interrupt servers. Servers should return D0 != 0 (Z clear) if they
111 believe the interrupt was for them, and no further interrupts will
112 be called. This will only check the value in D0 for non-m68k systems,
113 however it SHOULD check the Z-flag on 68k systems.
115 Hmm, in that case I would have to separate it from this file in order
118 AROS_UFH5S(void, IntServer
,
119 AROS_UFHA(ULONG
, intMask
, D0
),
120 AROS_UFHA(struct Custom
*, custom
, A0
),
121 AROS_UFHA(struct List
*, intList
, A1
),
122 AROS_UFHA(APTR
, intCode
, A5
),
123 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
127 struct Interrupt
* irq
;
129 ForeachNode(intList
, irq
)
131 if( AROS_UFC4(int, irq
->is_Code
,
132 AROS_UFCA(struct Custom
*, custom
, A0
),
133 AROS_UFCA(APTR
, irq
->is_Data
, A1
),
134 AROS_UFCA(APTR
, irq
->is_Code
, A5
),
135 AROS_UFCA(struct ExecBase
*, SysBase
, A6
)
144 #ifndef HAS_OWN_DISPATCHER
146 * Some implementations might bring along their own dispatcher
147 * and they will have to implement it somewhere else
148 * and also add it to the system at another place.
150 AROS_UFH4(int, Dispatcher
,
151 AROS_UFHA(struct Custom
*, custom
, A0
),
152 AROS_UFHA(APTR
, is_Data
, A1
),
153 AROS_UFHA(APTR
, is_Code
, A5
),
154 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
156 /* Check if a task switch is necessary */
157 /* 1. There has to be another task in the ready-list */
158 /* 2. The first task in the ready list hast to have the
159 same or higher priority than the currently active task */
163 #if AROS_NESTING_SUPERVISOR
167 if( SysBase
->TaskReady
.lh_Head
->ln_Succ
!= NULL
&&
168 ((BYTE
)SysBase
->ThisTask
->tc_Node
.ln_Pri
<=
169 (BYTE
)((struct Task
*)SysBase
->TaskReady
.lh_Head
)->tc_Node
.ln_Pri
)
172 /* Check if task switch is possible */
173 if( SysBase
->TDNestCnt
< 0 )
175 if( SysBase
->ThisTask
->tc_State
== TS_RUN
)
177 SysBase
->ThisTask
->tc_State
= TS_READY
;
178 Reschedule(SysBase
->ThisTask
);
179 SysBase
->AttnResched
|= 0x8000;
181 else if( SysBase
->ThisTask
->tc_State
== TS_REMOVED
)
182 SysBase
->AttnResched
|= 0x8000;
185 SysBase
->AttnResched
|= 0x80;
188 #if AROS_NESTING_SUPERVISOR
192 /* This make the int handler continue with the rest of the ints. */
200 AROS_UFH1(void, idleCount
,
201 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
204 /* This keeps track of how many times the idle task becomes active.
205 Apart from also testing the tc_Launch vector, it also keeps a
206 count of how many times we've gone idle since startup.
208 SysBase
->IdleCount
++;
212 extern ULONG
SoftIntDispatch();
214 #ifdef AROS_CREATE_ROM
215 # define sysBase SysBase
218 AROS_UFH3(LIBBASETYPEPTR
, GM_UNIQUENAME(init
),
219 AROS_UFHA(ULONG
, dummy
, D0
),
220 AROS_UFHA(BPTR
, segList
, A0
),
221 AROS_UFHA(struct ExecBase
*, sysBase
, A6
)
226 #ifndef AROS_CREATE_ROM
230 #warning FIXME: hack to avoid crash in timer_init.c:118
231 sysBase
->VBlankFrequency
= 50;
234 Create boot task. Sigh, we actually create a Process sized Task,
235 since DOS needs to call things which think it has a Process and
236 we don't want to overwrite memory with something strange do we?
238 We do this until at least we can boot dos more cleanly.
244 ml
= (struct MemList
*)AllocMem(sizeof(struct MemList
), MEMF_PUBLIC
|MEMF_CLEAR
);
245 t
= (struct Task
*) AllocMem(sizeof(struct Process
), MEMF_PUBLIC
|MEMF_CLEAR
);
249 kprintf("ERROR: Cannot create Boot Task!\n");
250 Alert( AT_DeadEnd
| AG_NoMemory
| AN_ExecLib
);
252 ml
->ml_NumEntries
= 1;
253 ml
->ml_ME
[0].me_Addr
= t
;
254 ml
->ml_ME
[0].me_Length
= sizeof(struct Process
);
256 NEWLIST(&t
->tc_MemEntry
);
257 NEWLIST(&((struct Process
*)t
)->pr_MsgPort
.mp_MsgList
);
259 /* It's the boot process that RunCommand()s the boot shell, so we
260 must have this list initialized */
261 NEWLIST((struct List
*)&((struct Process
*)t
)->pr_LocalVars
);
263 AddHead(&t
->tc_MemEntry
,&ml
->ml_Node
);
265 t
->tc_Node
.ln_Name
= "Boot Task";
266 t
->tc_Node
.ln_Pri
= 0;
267 t
->tc_State
= TS_RUN
;
268 t
->tc_SigAlloc
= 0xFFFF;
269 t
->tc_SPLower
= 0; /* This is the system's stack */
270 t
->tc_SPUpper
= (APTR
)~0UL;
271 t
->tc_Flags
|= TF_ETASK
;
273 t
->tc_UnionETask
.tc_ETask
= AllocVec
275 sizeof(struct IntETask
),
279 if (!t
->tc_UnionETask
.tc_ETask
)
281 kprintf("Not enough memory for first task\n");
282 Alert( AT_DeadEnd
| AG_NoMemory
| AN_ExecLib
);
285 /* Initialise the ETask data. */
286 InitETask(t
, t
->tc_UnionETask
.tc_ETask
);
288 GetIntETask(t
)->iet_Context
= AllocTaskMem(t
289 , SIZEOF_ALL_REGISTERS
290 , MEMF_PUBLIC
|MEMF_CLEAR
293 if (!GetIntETask(t
)->iet_Context
)
295 kprintf("Not enough memory for first task\n");
296 Alert( AT_DeadEnd
| AG_NoMemory
| AN_ExecLib
);
299 sysBase
->ThisTask
= t
;
308 /* Allocate MemEntry for this task and stack */
309 ml
= (struct MemList
*)AllocMem(sizeof(struct MemList
)+sizeof(struct MemEntry
),
310 MEMF_PUBLIC
|MEMF_CLEAR
);
311 t
= (struct Task
*) AllocMem(sizeof(struct Task
), MEMF_CLEAR
|MEMF_PUBLIC
);
312 s
= (UBYTE
*) AllocMem(AROS_STACKSIZE
, MEMF_CLEAR
|MEMF_PUBLIC
);
314 if( !ml
|| !t
|| !s
)
316 kprintf("ERROR: Cannot create Idle Task!\n");
317 Alert( AT_DeadEnd
| AG_NoMemory
| AN_ExecLib
);
320 ml
->ml_NumEntries
= 2;
321 ml
->ml_ME
[0].me_Addr
= t
;
322 ml
->ml_ME
[0].me_Length
= sizeof(struct Task
);
323 ml
->ml_ME
[1].me_Addr
= s
;
324 ml
->ml_ME
[1].me_Length
= AROS_STACKSIZE
;
326 NEWLIST(&t
->tc_MemEntry
);
327 AddHead(&t
->tc_MemEntry
, &ml
->ml_Node
);
329 t
->tc_SPUpper
= s
+ AROS_STACKSIZE
;
331 /* Pass SysBase in on the stack */
332 t
->tc_SPReg
= &(((struct ExecBase
*)(s
+ AROS_STACKSIZE
))[-1]);
333 *((struct ExecBase
**)t
->tc_SPReg
) = sysBase
;
335 t
->tc_Node
.ln_Name
= "Idle Task";
336 t
->tc_Node
.ln_Pri
= -128;
337 t
->tc_Launch
= &idleCount
;
338 t
->tc_Flags
= TF_LAUNCH
;
339 AddTask(t
, &idleTask
, NULL
);
343 /* Install the interrupt servers */
345 for(i
=0; i
< 16; i
++)
346 if( (1<<i
) & (INTF_PORTS
|INTF_COPER
|INTF_VERTB
|INTF_EXTER
|INTF_SETCLR
))
348 struct Interrupt
*is
;
349 struct SoftIntList
*sil
;
350 is
= AllocMem(sizeof(struct Interrupt
) + sizeof(struct SoftIntList
),
351 MEMF_CLEAR
|MEMF_PUBLIC
);
354 kprintf("ERROR: Cannot install Interrupt Servers!\n");
355 Alert( AT_DeadEnd
| AN_IntrMem
);
357 sil
= (struct SoftIntList
*)((struct Interrupt
*)is
+ 1);
359 is
->is_Code
= &IntServer
;
361 NEWLIST((struct List
*)sil
);
366 struct Interrupt
* is
;
370 is
= AllocMem(sizeof(struct Interrupt
), MEMF_CLEAR
|MEMF_PUBLIC
);
373 kprintf("Error: Cannot install Interrupt Handler!\n");
374 Alert( AT_DeadEnd
| AN_IntrMem
);
376 is
->is_Node
.ln_Type
= NT_INTERRUPT
;
377 is
->is_Node
.ln_Pri
= 0;
378 is
->is_Node
.ln_Name
= "SW Interrupt Dispatcher";
380 is
->is_Code
= (void *)SoftIntDispatch
;
387 #ifndef HAS_OWN_DISPATCHER
389 /* Install the task dispatcher */
390 struct Interrupt
*is
;
391 is
= (struct Interrupt
*)AllocMem(sizeof(struct Interrupt
), MEMF_CLEAR
|MEMF_PUBLIC
);
394 kprintf("ERROR: Cannot install Task Dispatcher!\n");
395 Alert( AT_DeadEnd
| AN_IntrMem
);
397 is
->is_Code
= (void (*)())&Dispatcher
;
398 AddIntServer(INTB_VERTB
,is
);
402 /* We now start up the interrupts */
409 /* This will cause everything else to run. This call will not return.
410 This is because it eventually falls into strap, which will call
411 the bootcode, which itself is not supposed to return. It is up
412 to the DOS (whatever it is) to Permit(); RemTask(NULL);
414 InitCode(RTF_COLDSTART
, 0);
416 /* There had better be some kind of task waiting to run. */
425 AROS_PLH1(struct ExecBase
*, open
,
426 AROS_LHA(ULONG
, version
, D0
),
427 struct ExecBase
*, SysBase
, 1, Exec
)
431 /* I have one more opener. */
432 SysBase
->LibNode
.lib_OpenCnt
++;
437 AROS_PLH0(BPTR
, close
,
438 struct ExecBase
*, SysBase
, 2, Exec
)
442 /* I have one fewer opener. */
443 SysBase
->LibNode
.lib_OpenCnt
--;