Support rastport clipping rectangle for layerless rastports
[tangerine.git] / rom / exec / exec_init.c
blobac34745eebfadf634c9bb0c338ec9313b743d52f
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: exec.library resident and initialization.
6 Lang: english
7 */
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
33 #include <sigcore.h>
34 #include <stdlib.h>
35 #undef timeval
37 #include "exec_util.h"
38 #include "etask.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 =
48 RTC_MATCHWORD,
49 (struct Resident *)&Exec_resident,
50 (APTR)&LIBEND,
51 RTF_SINGLETASK,
52 VERSION_NUMBER,
53 NT_LIBRARY,
54 105,
55 (STRPTR)name,
56 (STRPTR)&version[6],
57 &GM_UNIQUENAME(init)
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;
69 #endif
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.
76 #undef kprintf
77 #undef rkprintf
78 #undef vkprintf
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)
108 /* IntServer:
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
116 to replace it...
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))
125 AROS_USERFUNC_INIT
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)
137 break;
140 AROS_USERFUNC_EXIT
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 */
161 AROS_USERFUNC_INIT
163 #if AROS_NESTING_SUPERVISOR
164 Disable();
165 #endif
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;
184 else
185 SysBase->AttnResched |= 0x80;
188 #if AROS_NESTING_SUPERVISOR
189 Enable();
190 #endif
192 /* This make the int handler continue with the rest of the ints. */
193 return 0;
195 AROS_USERFUNC_EXIT
196 } /* Dispatcher */
197 #endif
200 AROS_UFH1(void, idleCount,
201 AROS_UFHA(struct ExecBase *, SysBase, A6))
203 AROS_USERFUNC_INIT
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++;
209 AROS_USERFUNC_EXIT
212 extern ULONG SoftIntDispatch();
214 #ifdef AROS_CREATE_ROM
215 # define sysBase SysBase
216 #endif
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)
224 AROS_USERFUNC_INIT
226 #ifndef AROS_CREATE_ROM
227 SysBase = sysBase;
228 #endif
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.
241 struct Task *t;
242 struct MemList *ml;
244 ml = (struct MemList *)AllocMem(sizeof(struct MemList), MEMF_PUBLIC|MEMF_CLEAR);
245 t = (struct Task *) AllocMem(sizeof(struct Process), MEMF_PUBLIC|MEMF_CLEAR);
247 if( !ml || !t )
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),
276 MEMF_ANY|MEMF_CLEAR
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;
303 /* Add idle task */
304 struct Task *t;
305 struct MemList *ml;
306 UBYTE *s;
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);
328 t->tc_SPLower = s;
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 */
344 int i;
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);
352 if( is == NULL )
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;
360 is->is_Data = sil;
361 NEWLIST((struct List *)sil);
362 SetIntVector(i,is);
364 else
366 struct Interrupt * is;
367 switch(i)
369 case INTB_SOFTINT:
370 is = AllocMem(sizeof(struct Interrupt), MEMF_CLEAR|MEMF_PUBLIC);
371 if (NULL == is)
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";
379 is->is_Data = NULL;
380 is->is_Code = (void *)SoftIntDispatch;
381 SetIntVector(i,is);
382 break;
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);
392 if(!is)
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);
400 #endif
402 /* We now start up the interrupts */
403 Enable();
405 //#if DEBUG
406 debugmem();
407 //#endif
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. */
417 return NULL;
418 AROS_USERFUNC_EXIT
421 #ifdef sysBase
422 #undef sysBase
423 #endif
425 AROS_PLH1(struct ExecBase *, open,
426 AROS_LHA(ULONG, version, D0),
427 struct ExecBase *, SysBase, 1, Exec)
429 AROS_LIBFUNC_INIT
431 /* I have one more opener. */
432 SysBase->LibNode.lib_OpenCnt++;
433 return SysBase;
434 AROS_LIBFUNC_EXIT
437 AROS_PLH0(BPTR, close,
438 struct ExecBase *, SysBase, 2, Exec)
440 AROS_LIBFUNC_INIT
442 /* I have one fewer opener. */
443 SysBase->LibNode.lib_OpenCnt--;
444 return 0;
445 AROS_LIBFUNC_EXIT