Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / arch / i386-darwin / exec / exec_init.c
blob4b70ccf7a52027c93a88e9a84aaf55e570d9eef6
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 kprintf("[Exec_init] sysBase=%p\n",sysBase);
228 #ifndef AROS_CREATE_ROM
229 SysBase = sysBase;
230 #endif
232 #warning FIXME: hack to avoid crash in timer_init.c:118
233 sysBase->VBlankFrequency = 50;
236 Create boot task. Sigh, we actually create a Process sized Task,
237 since DOS needs to call things which think it has a Process and
238 we don't want to overwrite memory with something strange do we?
240 We do this until at least we can boot dos more cleanly.
242 kprintf("[Exec_init] creating boot task\n");
244 struct Task *t;
245 struct MemList *ml;
247 ml = (struct MemList *)AllocMem(sizeof(struct MemList), MEMF_PUBLIC|MEMF_CLEAR);
248 t = (struct Task *) AllocMem(sizeof(struct Process), MEMF_PUBLIC|MEMF_CLEAR);
250 if( !ml || !t )
252 kprintf("[Exec_init] ERROR: Cannot create Boot Task!\n");
253 Alert( AT_DeadEnd | AG_NoMemory | AN_ExecLib );
255 ml->ml_NumEntries = 1;
256 ml->ml_ME[0].me_Addr = t;
257 ml->ml_ME[0].me_Length = sizeof(struct Process);
259 NEWLIST(&t->tc_MemEntry);
261 NEWLIST(&((struct Process *)t)->pr_MsgPort.mp_MsgList);
263 /* It's the boot process that RunCommand()s the boot shell, so we
264 must have this list initialized */
265 NEWLIST((struct List *)&((struct Process *)t)->pr_LocalVars);
266 AddHead(&t->tc_MemEntry,&ml->ml_Node);
268 t->tc_Node.ln_Name = "Boot Task";
269 t->tc_Node.ln_Pri = 0;
270 t->tc_State = TS_RUN;
271 t->tc_SigAlloc = 0xFFFF;
272 t->tc_SPLower = 0; /* This is the system's stack */
273 t->tc_SPUpper = (APTR)~0UL;
274 t->tc_Flags |= TF_ETASK;
276 t->tc_UnionETask.tc_ETask = AllocVec
278 sizeof(struct IntETask),
279 MEMF_ANY|MEMF_CLEAR
282 if (!t->tc_UnionETask.tc_ETask)
284 kprintf("Not enough memory for first task\n");
285 Alert( AT_DeadEnd | AG_NoMemory | AN_ExecLib );
288 kprintf("[Exec_init] preparing boot task\n");
290 /* Initialise the ETask data. */
291 InitETask(t, t->tc_UnionETask.tc_ETask);
293 GetIntETask(t)->iet_Context = AllocTaskMem(t
294 , SIZEOF_ALL_REGISTERS
295 , MEMF_PUBLIC|MEMF_CLEAR
298 if (!GetIntETask(t)->iet_Context)
300 kprintf("Not enough memory for first task\n");
301 Alert( AT_DeadEnd | AG_NoMemory | AN_ExecLib );
304 sysBase->ThisTask = t;
307 kprintf("[Exec_init] creating idle task\n");
309 /* Add idle task */
310 struct Task *t;
311 struct MemList *ml;
312 UBYTE *s;
314 /* Allocate MemEntry for this task and stack */
315 ml = (struct MemList *)AllocMem(sizeof(struct MemList)+sizeof(struct MemEntry),
316 MEMF_PUBLIC|MEMF_CLEAR);
317 t = (struct Task *) AllocMem(sizeof(struct Task), MEMF_CLEAR|MEMF_PUBLIC);
318 s = (UBYTE *) AllocMem(AROS_STACKSIZE, MEMF_CLEAR|MEMF_PUBLIC);
320 if( !ml || !t || !s )
322 kprintf("ERROR: Cannot create Idle Task!\n");
323 Alert( AT_DeadEnd | AG_NoMemory | AN_ExecLib );
326 ml->ml_NumEntries = 2;
327 ml->ml_ME[0].me_Addr = t;
328 ml->ml_ME[0].me_Length = sizeof(struct Task);
329 ml->ml_ME[1].me_Addr = s;
330 ml->ml_ME[1].me_Length = AROS_STACKSIZE;
332 NEWLIST(&t->tc_MemEntry);
333 AddHead(&t->tc_MemEntry, &ml->ml_Node);
334 t->tc_SPLower = s;
335 t->tc_SPUpper = s + AROS_STACKSIZE;
337 /* Pass SysBase in on the stack */
338 t->tc_SPReg = &(((struct ExecBase *)(s + AROS_STACKSIZE))[-1]);
339 *((struct ExecBase **)t->tc_SPReg) = sysBase;
341 t->tc_Node.ln_Name = "Idle Task";
342 t->tc_Node.ln_Pri = -128;
343 t->tc_Launch = &idleCount;
344 t->tc_Flags = TF_LAUNCH;
345 AddTask(t, &idleTask, NULL);
348 kprintf("[Exec_init] installing interupt servers\n");
350 /* Install the interrupt servers */
351 int i;
352 for(i=0; i < 16; i++)
353 if( (1<<i) & (INTF_PORTS|INTF_COPER|INTF_VERTB|INTF_EXTER|INTF_SETCLR))
355 struct Interrupt *is;
356 struct SoftIntList *sil;
357 is = AllocMem(sizeof(struct Interrupt) + sizeof(struct SoftIntList),
358 MEMF_CLEAR|MEMF_PUBLIC);
359 if( is == NULL )
361 kprintf("ERROR: Cannot install Interrupt Servers!\n");
362 Alert( AT_DeadEnd | AN_IntrMem );
364 sil = (struct SoftIntList *)((struct Interrupt *)is + 1);
366 is->is_Code = &IntServer;
367 is->is_Data = sil;
368 NEWLIST((struct List *)sil);
369 SetIntVector(i,is);
371 else
373 struct Interrupt * is;
374 switch(i)
376 case INTB_SOFTINT:
377 is = AllocMem(sizeof(struct Interrupt), MEMF_CLEAR|MEMF_PUBLIC);
378 if (NULL == is)
380 kprintf("Error: Cannot install Interrupt Handler!\n");
381 Alert( AT_DeadEnd | AN_IntrMem );
383 is->is_Node.ln_Type = NT_INTERRUPT;
384 is->is_Node.ln_Pri = 0;
385 is->is_Node.ln_Name = "SW Interrupt Dispatcher";
386 is->is_Data = NULL;
387 is->is_Code = (void *)SoftIntDispatch;
388 SetIntVector(i,is);
389 break;
394 #ifndef HAS_OWN_DISPATCHER
395 kprintf("[Exec_init] installing dispatcher\n");
397 /* Install the task dispatcher */
398 struct Interrupt *is;
399 is = (struct Interrupt *)AllocMem(sizeof(struct Interrupt), MEMF_CLEAR|MEMF_PUBLIC);
400 if(!is)
402 kprintf("[Exec_init] ERROR: Cannot install Task Dispatcher!\n");
403 Alert( AT_DeadEnd | AN_IntrMem );
405 is->is_Code = (void (*)())&Dispatcher;
406 AddIntServer(INTB_VERTB,is);
408 #endif
410 /* We now start up the interrupts */
411 kprintf("[Exec_init] enabling interrupts\n");
412 Enable();
414 //#if DEBUG
415 debugmem();
416 //#endif
418 /* This will cause everything else to run. This call will not return.
419 This is because it eventually falls into strap, which will call
420 the bootcode, which itself is not supposed to return. It is up
421 to the DOS (whatever it is) to Permit(); RemTask(NULL);
423 kprintf("[Exec_init] initiating coldstart\n");
424 InitCode(RTF_COLDSTART, 0);
426 /* There had better be some kind of task waiting to run. */
427 return NULL;
428 AROS_USERFUNC_EXIT
431 #ifdef sysBase
432 #undef sysBase
433 #endif
435 AROS_PLH1(struct ExecBase *, open,
436 AROS_LHA(ULONG, version, D0),
437 struct ExecBase *, SysBase, 1, Exec)
439 AROS_LIBFUNC_INIT
441 /* I have one more opener. */
442 SysBase->LibNode.lib_OpenCnt++;
443 return SysBase;
444 AROS_LIBFUNC_EXIT
447 AROS_PLH0(BPTR, close,
448 struct ExecBase *, SysBase, 2, Exec)
450 AROS_LIBFUNC_INIT
452 /* I have one fewer opener. */
453 SysBase->LibNode.lib_OpenCnt--;
454 return 0;
455 AROS_LIBFUNC_EXIT