Belarusian
[AROS.git] / rom / exec / exec_init.c
blobc1b55f608a47ef53a078d7754997f03268e31da5
1 /*
2 Copyright © 1995-2010, 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 <proto/kernel.h>
31 #include <clib/macros.h> /* need ABS() */
33 #include "exec_intern.h"
34 #include "exec_util.h"
35 #include "etask.h"
36 #include LC_LIBDEFS_FILE
38 static const UBYTE name[];
39 static const UBYTE version[];
40 extern const char LIBEND;
41 AROS_UFP3(LIBBASETYPEPTR, GM_UNIQUENAME(init),
42 AROS_UFPA(ULONG, dummy, D0),
43 AROS_UFPA(BPTR, segList, A0),
44 AROS_UFPA(struct ExecBase *, sysBase, A6));
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);
66 We temporarily redefine kprintf() so we use the real version in case
67 we have one of these two fn's called before AROSSupportBase is ready.
70 #undef kprintf
71 #undef rkprintf
72 #undef vkprintf
73 struct Library * PrepareAROSSupportBase (struct ExecBase * SysBase)
75 struct AROSSupportBase * AROSSupportBase;
76 AROSSupportBase = AllocMem(sizeof(struct AROSSupportBase), MEMF_CLEAR);
77 AROSSupportBase->kprintf = (void *)kprintf;
78 AROSSupportBase->rkprintf = (void *)rkprintf;
79 AROSSupportBase->vkprintf = (void *)vkprintf;
80 NEWLIST(&AROSSupportBase->AllocMemList);
82 /* FIXME: Add code to read in the debug options */
84 return (struct Library *)AROSSupportBase;
87 void _aros_not_implemented(char *X)
89 kprintf("Unsupported function at offset -0x%h in %s\n",
90 ABS(*(WORD *)((&X)[-1]-2)),
91 ((struct Library *)(&X)[-2])->lib_Node.ln_Name);
93 #define kprintf (((struct AROSSupportBase *)(SysBase->DebugAROSBase))->kprintf)
94 #define rkprintf (((struct AROSSupportBase *)(SysBase->DebugAROSBase))->rkprintf)
95 #define vkprintf (((struct AROSSupportBase *)(SysBase->DebugAROSBase))->vkprintf)
97 /* IntServer:
98 This interrupt handler will send an interrupt to a series of queued
99 interrupt servers. Servers should return D0 != 0 (Z clear) if they
100 believe the interrupt was for them, and no further interrupts will
101 be called. This will only check the value in D0 for non-m68k systems,
102 however it SHOULD check the Z-flag on 68k systems.
104 Hmm, in that case I would have to separate it from this file in order
105 to replace it...
107 AROS_UFH5S(void, IntServer,
108 AROS_UFHA(ULONG, intMask, D0),
109 AROS_UFHA(struct Custom *, custom, A0),
110 AROS_UFHA(struct List *, intList, A1),
111 AROS_UFHA(APTR, intCode, A5),
112 AROS_UFHA(struct ExecBase *, SysBase, A6))
114 AROS_USERFUNC_INIT
116 struct Interrupt * irq;
118 ForeachNode(intList, irq)
120 if( AROS_UFC4(int, irq->is_Code,
121 AROS_UFCA(struct Custom *, custom, A0),
122 AROS_UFCA(APTR, irq->is_Data, A1),
123 AROS_UFCA(APTR, irq->is_Code, A5),
124 AROS_UFCA(struct ExecBase *, SysBase, A6)
126 break;
129 AROS_USERFUNC_EXIT
132 /* VBlankServer. The same as general purpose IntServer but also counts task's quantum */
133 AROS_UFH5S(void, VBlankServer,
134 AROS_UFHA(ULONG, intMask, D1),
135 AROS_UFHA(struct Custom *, custom, A0),
136 AROS_UFHA(struct List *, intList, A1),
137 AROS_UFHA(APTR, intCode, A5),
138 AROS_UFHA(struct ExecBase *, SysBase, A6))
140 AROS_USERFUNC_INIT
142 struct Interrupt *irq;
144 /* First decrease Elapsed time for current task */
145 if (SysBase->Elapsed && (--SysBase->Elapsed == 0))
147 SysBase->SysFlags |= SFF_QuantumOver;
148 SysBase->AttnResched |= ARF_AttnSwitch;
151 ForeachNode(intList, irq)
153 if( AROS_UFC4(int, irq->is_Code,
154 AROS_UFCA(struct Custom *, custom, A0),
155 AROS_UFCA(APTR, irq->is_Data, A1),
156 AROS_UFCA(APTR, irq->is_Code, A5),
157 AROS_UFCA(struct ExecBase *, SysBase, A6)
159 break;
162 AROS_USERFUNC_EXIT
165 extern ULONG SoftIntDispatch();
167 AROS_UFH3(LIBBASETYPEPTR, GM_UNIQUENAME(init),
168 AROS_UFHA(ULONG, dummy, D0),
169 AROS_UFHA(BPTR, segList, A0),
170 AROS_UFHA(struct ExecBase *, sysBase, A6)
173 AROS_USERFUNC_INIT
175 struct Task *t;
176 struct MemList *ml;
177 int i, j;
178 UWORD sum;
179 UWORD *ptr;
181 SysBase = sysBase;
182 KernelBase = OpenResource("kernel.resource");
183 if (!KernelBase)
184 return NULL;
186 /* We print the notice here because kprintf() works only after KernelBase is set up */
187 if (PrivExecBase(SysBase)->IntFlags & EXECF_MungWall)
188 bug("[exec] Mungwall enabled\n");
191 Create boot task. Sigh, we actually create a Process sized Task,
192 since DOS needs to call things which think it has a Process and
193 we don't want to overwrite memory with something strange do we?
195 We do this until at least we can boot dos more cleanly.
198 ml = (struct MemList *)AllocMem(sizeof(struct MemList), MEMF_PUBLIC|MEMF_CLEAR);
199 t = (struct Task *) AllocMem(sizeof(struct Process), MEMF_PUBLIC|MEMF_CLEAR);
200 if( !ml || !t ) {
201 kprintf("ERROR: Cannot create Boot Task!\n");
202 Alert( AT_DeadEnd | AG_NoMemory | AN_ExecLib );
205 ml->ml_NumEntries = 1;
206 ml->ml_ME[0].me_Addr = t;
207 ml->ml_ME[0].me_Length = sizeof(struct Process);
209 NEWLIST(&t->tc_MemEntry);
210 NEWLIST(&((struct Process *)t)->pr_MsgPort.mp_MsgList);
212 /* It's the boot process that RunCommand()s the boot shell, so we
213 must have this list initialized */
214 NEWLIST((struct List *)&((struct Process *)t)->pr_LocalVars);
216 AddHead(&t->tc_MemEntry,&ml->ml_Node);
218 t->tc_Node.ln_Name = "Boot Task";
219 t->tc_Node.ln_Type = NT_TASK;
220 t->tc_Node.ln_Pri = 0;
221 t->tc_State = TS_RUN;
222 t->tc_SigAlloc = 0xFFFF;
223 t->tc_SPLower = 0; /* This is the system's stack */
224 t->tc_SPUpper = (APTR)~0UL;
225 t->tc_Flags |= TF_ETASK;
227 t->tc_UnionETask.tc_ETask = AllocVec(sizeof(struct IntETask), MEMF_ANY|MEMF_CLEAR);
228 if (!t->tc_UnionETask.tc_ETask) {
229 kprintf("Not enough memory for first task\n");
230 Alert( AT_DeadEnd | AG_NoMemory | AN_ExecLib );
233 /* Initialise the ETask data. */
234 InitETask(t, t->tc_UnionETask.tc_ETask);
236 GetIntETask(t)->iet_Context = KrnCreateContext();
237 if (!GetIntETask(t)->iet_Context) {
238 kprintf("Not enough memory for first task\n");
239 Alert( AT_DeadEnd | AG_NoMemory | AN_ExecLib );
242 sysBase->ThisTask = t;
243 sysBase->Elapsed = sysBase->Quantum;
245 /* Install the interrupt servers */
246 for(i=0; i < 16; i++)
248 struct Interrupt *is;
250 if( (1<<i) & (INTF_PORTS|INTF_COPER|INTF_VERTB|INTF_EXTER|INTF_SETCLR))
252 struct SoftIntList *sil;
254 is = AllocMem(sizeof(struct Interrupt) + sizeof(struct SoftIntList), MEMF_CLEAR|MEMF_PUBLIC);
255 if (is == NULL) {
256 kprintf("ERROR: Cannot install Interrupt Servers!\n");
257 Alert( AT_DeadEnd | AN_IntrMem );
260 sil = (struct SoftIntList *)((struct Interrupt *)is + 1);
262 if (i == INTB_VERTB)
263 is->is_Code = &VBlankServer;
264 else
265 is->is_Code = &IntServer;
266 is->is_Data = sil;
267 NEWLIST((struct List *)sil);
268 SetIntVector(i,is);
270 else
272 struct Interrupt * is;
274 switch(i) {
275 case INTB_SOFTINT:
276 is = AllocMem(sizeof(struct Interrupt), MEMF_CLEAR|MEMF_PUBLIC);
277 if (NULL == is) {
278 kprintf("Error: Cannot install SoftInt Handler!\n");
279 Alert( AT_DeadEnd | AN_IntrMem );
282 is->is_Node.ln_Type = NT_INTERRUPT;
283 is->is_Node.ln_Pri = 0;
284 is->is_Node.ln_Name = "SW Interrupt Dispatcher";
285 is->is_Data = NULL;
286 is->is_Code = (void *)SoftIntDispatch;
287 SetIntVector(i,is);
288 break;
293 /* We now start up the interrupts */
294 Permit();
295 Enable();
297 /* Now it's time to calculate exec checksum. It will be used
298 * in future to distinguish whether we'd had proper execBase
299 * before restart */
300 sum=0;
301 ptr = &SysBase->SoftVer;
303 i=((IPTR)&SysBase->IntVects[0] - (IPTR)&SysBase->SoftVer) / 2;
305 /* Calculate sum for every static part from SoftVer to ChkSum */
306 for (j = 0; j < i; j++)
307 sum+=*(ptr++);
309 SysBase->ChkSum = ~sum;
311 D(debugmem());
313 /* This will cause everything else to run. This call will not return.
314 This is because it eventually falls into strap, which will call
315 the bootcode, which itself is not supposed to return. It is up
316 to the DOS (whatever it is) to Permit(); RemTask(NULL);
318 InitCode(RTF_COLDSTART, 0);
320 /* There had better be some kind of task waiting to run. */
321 return NULL;
323 AROS_USERFUNC_EXIT
326 AROS_PLH1(struct ExecBase *, open,
327 AROS_LHA(ULONG, version, D0),
328 struct ExecBase *, SysBase, 1, Exec)
330 AROS_LIBFUNC_INIT
332 /* I have one more opener. */
333 SysBase->LibNode.lib_OpenCnt++;
334 return SysBase;
335 AROS_LIBFUNC_EXIT
338 AROS_PLH0(BPTR, close,
339 struct ExecBase *, SysBase, 2, Exec)
341 AROS_LIBFUNC_INIT
343 /* I have one fewer opener. */
344 SysBase->LibNode.lib_OpenCnt--;
345 return 0;
346 AROS_LIBFUNC_EXIT