Updated PCI IDs to latest snapshot.
[tangerine.git] / arch / i386-pc / exec / exec_init.c
blobd0db74c47817d0a67f04cf6d0c77120f98a14391
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Early bootup section
6 Lang: english
7 */
9 /*
10 AROS MemoryMap:
12 First 4KB of RAM (page 0x0000-0x0FFF) are READ ONLY!
14 +------------+-----------+-------------------------------------------------+
15 | address | length | description |
16 +------------+-----------+-------------------------------------------------+
17 | System page. Read only! Addresses undefined here are not allowed!!!! |
18 +------------------------+-------------------------------------------------+
19 | 0x00000004 | 0x0000004 | ExecBase pointer. |
20 | 0x00000020 | 0x0000020 | CPU information |
21 | 0x00000040 | 0x0000068 | TSS structure. Do not use! |
22 | 0x000000a8 | 0x0000004 | INT server! cached_irq_mask |
23 | 0x000000ac | 0x0000004 | INT server! io_apic_irqs |
24 | 0x00000100 | 0x0000800 | 256 interrupt vectors |
25 | 0x00000900 | 0x0000040 | Global Descriptor Table |<---- needs changed! - must have space for GDT x No CPUs (NicJA)
26 | 0x00000940 | 0x0000001 | INT server! softblock |
27 | 0x00000a00 | 0x0000200 | INT server! irq_desc[] |
28 +------------+-----------+-------------------------------------------------+
29 | 0x00001000 | 0x0001000 | MultiBoot information |
30 | 0x00002000 | ......... | System RAM |
31 | .......... | ......... | Temporary stack frame for bootup process |
32 ......0x0009e000 0x0001000 SMP Trampoline (NicJA)
33 | 0x000a0000 | 0x0060000 | Data reserved for BIOS, VGA and some MMIO cards |
34 ......0x000f7070 ACPI<-
35 1MB| 0x00100000 | ......... | AROS KERNEL |
36 | .......... | ......... | System RAM divided into DMA and rest. |
37 +------------+-----------+-------------------------------------------------+
38 0fef7f80
39 WARNING!
41 AROS Kernel will not be placed in first 1MB of ram anymore. Instead it
42 will be either somewhere in DMA memory (eg at 2nd MByte), at the end of
43 available memory or placed at Virtual address. Don't trust its position.
45 When ROM module called from loader, the ExecBase should be cleared.
47 This file has been completely rewritten from assembler source!
51 #include <exec/resident.h>
52 #include <exec/types.h>
53 #include <exec/nodes.h>
54 #include <exec/execbase.h>
55 #include <exec/memory.h>
56 #include <hardware/intbits.h>
57 #include <asm/segments.h>
58 #include <asm/linkage.h>
59 #include <asm/ptrace.h>
60 #include <dos/dosextens.h>
62 #include <aros/arossupportbase.h>
63 #include <aros/asmcall.h>
64 #include <aros/config.h>
66 #ifndef DEBUG
67 # define DEBUG 1
68 #endif
70 #include <aros/debug.h>
71 #include <aros/multiboot.h>
73 #include <hardware/custom.h>
75 #include <proto/exec.h>
77 #include <stddef.h>
78 #include <stdio.h>
79 #include <string.h>
81 #include LC_LIBDEFS_FILE
83 #include "etask.h"
84 #include "exec_util.h"
85 #include "traps.h"
86 #include "vesa.h"
88 #define SMP_SUPPORT 0
90 #if SMP_SUPPORT
91 extern void prepare_primary_cpu(struct ExecBase *SysBase); /* FUNCTION FROM "cpu.resource"!!!!!!! */
92 #endif
94 /* As long as we don't have CPU detection routine, assume FPU to be present */
96 #define ASSUME_FPU 1
99 * Some macro definitions. __text will place given structure in .text section.
100 * __no_ret will force function type to be no-return function. __packed will
101 * force any structure to be non-aligned (we don't need alignment in native
102 * AROS).
105 #define __text __attribute__((section(".text")))
106 #define __no_ret __attribute__((noreturn))
107 #define __packed __attribute__((packed))
109 #define rdcr(reg) \
110 ({ long val; asm volatile("mov %%" #reg ",%0":"=r"(val)); val; })
112 #define wrcr(reg, val) \
113 do { asm volatile("mov %0,%%" #reg::"r"(val)); } while(0)
115 #define cpuid(num, eax, ebx, ecx, edx) \
116 do { asm volatile("cpuid":"=a"(eax),"=b"(ebx),"=c"(ecx),"=d"(edx):"a"(num)); } while(0)
120 * Some declarations
122 void exec_init() __no_ret; /* init NEVER returns */
123 void exec_cinit() __no_ret; /* c-style init NEVER returns */
124 int exec_check_base();
125 void exec_DefaultTrap();
126 void exec_DefaultTaskExit();
127 //void exec_CheckCPU();
128 int exec_RamCheck_fast();
129 int exec_RamCheck_dma();
130 unsigned char setupVesa(struct multiboot *mbinfo);
133 asmlinkage void Exec_SystemCall(struct pt_regs);
134 ULONG **exec_RomTagScanner();
135 void irqSetup(void);
137 extern const UBYTE LIBEND __text; /* Somewhere in library */
138 extern ULONG _edata,_end; /* They are standard for ELF */
139 extern const APTR LIBFUNCTABLE[] __text;
141 extern struct Library * PrepareAROSSupportBase (void);
142 extern ULONG SoftIntDispatch();
143 extern void Exec_SerialRawIOInit();
144 extern void Exec_SerialRawPutChar(UBYTE chr);
146 extern void Exec_Switch_FPU();
147 extern void Exec_PrepareContext_FPU();
148 extern void Exec_Dispatch_FPU();
150 extern void Exec_Switch_SSE();
151 extern void Exec_PrepareContext_SSE();
152 extern void Exec_Dispatch_SSE();
154 extern ULONG Exec_MakeFunctions(APTR, APTR, APTR, APTR);
156 AROS_UFP5S(void, IntServer,
157 AROS_UFPA(ULONG, intMask, D0),
158 AROS_UFPA(struct Custom *, custom, A0),
159 AROS_UFPA(struct List *, intList, A1),
160 AROS_UFPA(APTR, intCode, A5),
161 AROS_UFPA(struct ExecBase *, SysBase, A6));
163 #undef memcpy
164 #define memcpy(_d, _s, _len) \
166 int len = _len; \
167 while (len) \
169 ((char *)_d)[len-1] = ((char *)_s)[len-1];\
170 len--; \
175 /* Temporary information */
177 #if 1
179 void clr();
180 void scr_RawPutChars(char *, int);
182 char tab[127];
184 #ifdef rkprintf
185 # undef rkprintf
186 #endif
187 #define rkprintf(x...) scr_RawPutChars(tab, snprintf(tab,126, x))
189 #else
191 #define clr() /* eps */
192 #define rkprintf(x...) /* eps */
194 #endif
197 * Make SysBase global. This way we will have no problems with all crapy modules
198 * which rely on global SysBase. They will get what they want - they will access
199 * it :)
202 asm( ".globl aros_intern\n\t"
203 ".globl SysBase \n\t"
204 ".set aros_intern,0\n\t"
205 ".set SysBase,4 ");
208 * Here the history starts. We are already in flat, 32bit mode. All protections
209 * are off, CPU is working in Supervisor level (CPL0). This state can be emu-
210 * lated by ColdReboot() routine as it may freely use Supervisor()
212 * kernel_startup can be executed only from CPL0 without vmm. Interrupts should
213 * be disabled.
215 * Note that kernel_startup is declared as entry symbol for output ELF file.
218 asm( ".globl kernel_startup \n\t"
219 ".type kernel_startup,@function\n"
220 "kernel_startup: jmp exec_init");
222 const char exec_core[] __text = "Native/CORE v2.0.1";
225 * First, we will define exec.library (global) to make it usable outside this
226 * file.
228 const char exec_name[] __text = "exec.library";
230 /* Now ID string as it will be used in a minute in resident structure. */
231 const char exec_idstring[] __text = "$VER: exec 41.11 (16.12.2000)\r\n";
233 /* We would need also version and revision fields placed somewhere here. */
234 const short exec_Version __text = 41;
235 const short exec_Revision __text = 11;
238 * The RomTag structure. It has to be placed inside .text block as there will
239 * be no public RomTagList. In future we may change RTC_MATCHWORD to be machine
240 * specific.
242 const struct Resident Exec_resident __text=
244 RTC_MATCHWORD, /* Magic value used to find resident */
245 &Exec_resident, /* Points to Resident itself */
246 &LIBEND, /* Where could we find next Resident? */
247 0, /* There are no flags!! */
248 41, /* Version */
249 NT_LIBRARY, /* Type */
250 126, /* Very high startup priority. */
251 (char *)exec_name, /* Pointer to name string */
252 (char *)exec_idstring, /* Ditto */
253 exec_init /* Library initializer (for exec this value is irrelevant since we've jumped there at the begining to bring the system up */
256 struct view { unsigned char sign; unsigned char attr; };
259 * Init the exec.library and as well whole system. This routine has to prepare
260 * all needed structures, GDT and IDT tables, TSS structure and many other.
262 * We have to use asm creature because there is no stack at the moment
264 asm("\nexec_init: \n\t"
265 "movl $0x93000,%esp\n\t" /* Start with setting up a temporary stack */
266 "pushl %ebx \n\t" /* Then store the MultiBoot info pointer */
267 "pushl %eax \n\t" /* Store multiboot magic cookie */
268 "pushl $0x0 \n\t" /* And fake a C code call */
270 "cld \n\t" /* At the startup it's very important */
271 "cli \n\t" /* to lock all interrupts. Both on the */
272 "movb $-1,%al \n\t" /* CPU side and hardware side. We don't */
273 "outb %al,$0x21 \n\t" /* have proper structures in RAM yet. */
274 "outb %al,$0xa1 \n\n\t"
276 "jmp exec_cinit"); /* Jump to C function :))) */
279 * This routine is used by kernel to change all colors on the screen according
280 * to R,G,B values passed here
282 void exec_SetColors(char r, char g, char b)
284 int i;
285 short reg = 0x3c8; /* IO reg to control PEL */
287 asm("movb $0,%%al\n\t" /* Start with color 0 */
288 "outb %%al,%w0\n\t"
289 : /* no output */
290 : "Nd"(reg));
292 reg++; /* Here we have to put R, G, B */
294 for (i=0; i<256; i++) /* Set whole palette */
296 asm("outb %b0,%w1"::"a"(r),"Nd"(reg));
297 asm("outb %b0,%w1"::"a"(g),"Nd"(reg));
298 asm("outb %b0,%w1"::"a"(b),"Nd"(reg));
299 asm("nop \n\t"
300 "nop \n\t"
301 "nop \n\t"
302 "nop");
307 * Mixed stuff used to control TSS/GDT/IDT stuff. This is strictly machine
308 * specific
311 asm(".globl TSS\n\t" /* Make this three global in case one would */
312 ".globl SSP\n\t" /* decide to use them directly */
313 ".globl EIP\n\t"
314 ".set TSS, 0x00000040\n\t" /* See Memory Map at the top of the file */
315 ".set SSP, 0x00000044\n\t"
316 ".set EIP, 0x00000060");
319 * Two defines used to keep control over interrupt server
322 asm(".globl cached_irq_mask\n\t"
323 ".globl io_apic_irqs\n\t"
324 ".globl softblock\n\t"
325 ".globl irq_desc\n\t"
326 ".set cached_irq_mask, 0x000000a8\n\t"
327 ".set io_apic_irqs, 0x000000ac\n\t"
328 ".set softblock, 0x00000940\n\t"
329 ".set irq_desc, 0x00000a00");
332 * TaskStateStructure, defined only in matter of making life (setup)
333 * more human-readable
335 struct _tss {
336 ULONG link, /* link to previous task - UNUSED */
337 ssp, /* Supervisor Stack Pointer */
338 ssp_seg, /* SSP descriptor */
339 t0,t1, /* Stack for CPL1 code - USE IN FUTURE */
340 t2,t3, /* Stack for CPL2 code - UNUSED */
341 cr3, /* used in paging */
342 eip, /* Instruction pointer */
343 eflags, /* Flags for given task */
344 r0,r1,r2,r3, /* 8 general purpouse registers */
345 r4,r5,r6,r7,
346 es,cs,ss,ds,fs,gs, /* segment descriptors */
347 ldt; /* LocalDescriptorTable - UNUSED */
348 UWORD trap,iomap; /* trap flag and iomap pointer */
352 * Nice macro used for setting given gate to specified type.
353 * dpl is used to control access of this gate - setting to something
354 * lower than 3 makes gate impossible to use from User Mode
356 #define set_gate(gate_addr,type,dpl,addr) \
357 do { \
358 int __d0, __d1; \
359 __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
360 "movw %4,%%dx\n\t" \
361 "movl %%eax,%0\n\t" \
362 "movl %%edx,%1" \
363 :"=m" (*((long *) (gate_addr))), \
364 "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
365 :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
366 "3" ((char *) (addr)),"2" (KERNEL_CS << 16)); \
367 } while (0)
369 /* Empty interrupt. Used for short while */
370 void exec_DummyInt();
371 asm("\nexec_DummyInt: iret");
374 * RO copy of GlobalDescriptorTable. It's easyier to copy this table than
375 * to generate completely new one
377 const struct {UWORD l1, l2, l3, l4;}
378 GDT_Table[] __text = {
379 { 0x0000, 0x0000, 0x0000, 0x0000 },
380 { 0xffff, 0x0000, 0x9a00, 0x00cf },
381 { 0xffff, 0x0000, 0x9200, 0x00cf },
382 { 0xffff, 0x0000, 0xfa00, 0x00cf },
383 { 0xffff, 0x0000, 0xf200, 0x00cf },
384 { 0x0000, 0x0000, 0x0000, 0x0000 },
385 { 0x0067, 0x0040, 0x8900, 0x0000 },
386 { 0x0000, 0x0000, 0x0000, 0x0000 }};
388 /* Two magic registers pointing to Global Descriptor Table and Interrupt
389 * Descriptor Table */
390 const struct
392 UWORD l1 __packed;
393 ULONG l3 __packed;
395 GDT_reg __text = {0x3f, 0x900},
396 IDT_reg __text = {0x7ff, 0x100};
398 const char exec_chipname[] __text = "Chip Memory";
399 const char exec_fastname[] __text = "Fast Memory";
402 * C/ASM mixed initialization routine. Here the real game begins...
404 void exec_cinit(unsigned long magic, unsigned long addr)
406 struct ExecBase *ExecBase;
407 struct multiboot *mbinfo;
408 struct arosmb *arosmb;
410 ULONG locmem, extmem;
412 APTR KickMemPtr,
413 KickTagPtr,
414 KickCheckSum;
416 struct _tss *tss = (struct _tss *)0x40; /* Dummy pointer making life easier */
417 long long *idt = (long long *)0x100; /* Ditto */
419 int i; /* Whatever? Counter? Erm... */
421 // exec_SetColors(0x10,0x10,0x10); /* Set screen to almost black */
423 /* Check whether we have .bss block */
424 if ((int)&_end - (int)&_edata)
427 * Damn! We have to GET RID OF THIS!!! But now the only thing I can do
428 * is clearing it. GRUB have done it already but we have to repeat that
429 * (it may NEED that as it might be ColdReboot())
431 bzero(&_edata,(int)&_end-(int)&_edata);
434 clr();
435 rkprintf("AROS - The AROS Research OS\nCompiled %s\n\n",__DATE__);
437 /* MultiBoot
438 * This messy bit here will store away useful information we receive from
439 * the bootloader. It will happen when we are loaded, and not on when we
440 * are here from ColdReboot().
441 * This is just the first stage of it. Later this information will be extracted
442 * by bootloader.resource, but we do this here anyway. Both to keep the info
443 * safe, and also since we will use some of it in here.
445 arosmb = (struct arosmb *)0x1000;
446 if (magic == 0x2badb002)
448 mbinfo = (struct multiboot *)addr;
449 if (mbinfo->flags & MB_FLAGS_CMDLINE)
450 arosmb->vbe_palette_width = setupVesa(mbinfo);
451 rkprintf("Copying multiboot information into storage\n");
452 arosmb->magic = MBRAM_VALID;
453 arosmb->flags = 0L;
454 if (mbinfo->flags & MB_FLAGS_MEM)
456 arosmb->flags |= MB_FLAGS_MEM;
457 arosmb->mem_lower = mbinfo->mem_lower;
458 arosmb->mem_upper = mbinfo->mem_upper;
460 if (mbinfo->flags & MB_FLAGS_LDRNAME)
462 arosmb->flags |= MB_FLAGS_LDRNAME;
463 snprintf(arosmb->ldrname,29,"%s",mbinfo->loader_name);
465 if (mbinfo->flags & MB_FLAGS_CMDLINE)
467 arosmb->flags |= MB_FLAGS_CMDLINE;
468 snprintf(arosmb->cmdline,199,"%s",mbinfo->cmdline);
470 if (mbinfo->flags & MB_FLAGS_MMAP)
472 arosmb->flags |= MB_FLAGS_MMAP;
473 arosmb->mmap_addr = (struct mb_mmap *)((ULONG)(0x1000 + sizeof(struct arosmb)));
474 arosmb->mmap_len = mbinfo->mmap_length;
475 memcpy((void *)arosmb->mmap_addr,(void *)mbinfo->mmap_addr,mbinfo->mmap_length);
477 if (mbinfo->flags & MB_FLAGS_DRIVES)
479 if (mbinfo->drives_length > 0)
481 arosmb->flags |= MB_FLAGS_DRIVES;
482 arosmb->drives_addr = ((ULONG)(arosmb->mmap_addr + arosmb->mmap_len));
483 arosmb->drives_len = mbinfo->drives_length;
484 memcpy((void *)arosmb->drives_addr,(void *)mbinfo->drives_addr,mbinfo->drives_length);
487 if (mbinfo->flags & MB_FLAGS_GFX)
489 arosmb->flags |= MB_FLAGS_GFX;
490 arosmb->vbe_mode = mbinfo->vbe_mode;
491 memcpy((void *)&arosmb->vmi,(void *)mbinfo->vbe_mode_info,sizeof(struct vbe_mode));
492 memcpy((void *)&arosmb->vci,(void *)mbinfo->vbe_control_info,sizeof(struct vbe_controller));
495 rkprintf("Done\n");
497 #warning "TODO: WE MUST PARSE THE BIOS MEMORY MAP HERE AND PROTECT NECESSARY STRUCTS (i.e ACPI stores its data in the last few meg of physical ram..)"
499 rkprintf("Clearing system area...");
502 * Well, if we all in clearing moode, then it's the best occasion to clear
503 * some areas in AROS private 4KB ram area. Hmmm. If there would occur any
504 * interrupt at this moment, AROS would be really dead as it is going to
505 * destroy its private stuff (which is really needed to make CPU operate
506 * properly)
508 bzero((void *)8, 4096-8);
511 * Feel better? Now! Quick. We will have to build new tables for our CPU to
512 * make it work nicely.
514 tss->ssp = 0x00090000; /* temporary Supervisor Stack Pointer */
515 tss->ssp_seg = KERNEL_DS; /* SSP segment descriptor */
516 tss->cs = USER_CS;
517 tss->ds = USER_DS;
518 tss->es = USER_DS;
519 tss->ss = USER_DS;
520 tss->iomap = 104;
522 /* Restore IDT structure. */
523 for (i=0; i<256; i++)
525 /* Feed all vectors with dummy interrupt */
526 set_gate(idt + i, 14, 0, exec_DummyInt);
530 * Fix Global Descriptor Table. Because I'm too lazy I'll just copy one from
531 * here. I've already prepared such a nice one :)
533 memcpy((void *)0x900, &GDT_Table, 64);
536 * As we prepared all necessary stuff, we can hopefully load GDT and LDT
537 * into CPU. We may also play a bit with TSS
539 asm("lgdt %0\n\t"
540 "lidt %1"
542 :"m"(GDT_reg),"m"(IDT_reg));
544 asm("mov %0,%%ds\n\t" /* Now it's high time to set segment */
545 "mov %0,%%es\n\t" /* registers (segment descriptors). */
546 "mov %0,%%ss\n\t" /* AROS uses only %CS %SS %DS and %ES */
547 "mov %1,%%fs\n\t" /* %FS and %GS are set to 0 so we can */
548 "mov %1,%%gs" /* generate GP if someone uses them. */
550 :"a"(KERNEL_DS),"b"(0));
552 asm("ltr %%ax"::"ax"(0x30));
554 rkprintf("OK\nSystem restored\n");
557 * Wew have to do some stuff from setup.S due to remove of it.
559 * Remap IRQs. We really HAVE TO do that because IBM did it in a very bad
560 * way - they've ignored what Intel said about interrupts. See intel manual
561 * for further information.
562 * For now all irq's are placed in range 0x20 - 0x30 as vectors 0x00 - 0x1f
563 * are reserved by Intel
565 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x11),"i"(0x20)); /* Initialization sequence for 8259A-1 */
566 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x11),"i"(0xa0)); /* Initialization sequence for 8259A-2 */
567 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x20),"i"(0x21)); /* IRQs at 0x20 - 0x27 */
568 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x28),"i"(0xa1)); /* IRQs at 0x28 - 0x2f */
569 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x04),"i"(0x21)); /* 8259A-1 is master */
570 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x02),"i"(0xa1)); /* 8259A-2 is slave */
571 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x01),"i"(0x21)); /* 8086 mode for both */
572 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0x01),"i"(0xa1));
573 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0xff),"i"(0x21)); /* Enable cascade int */
574 asm("outb %b0,%b1\n\tcall delay"::"a"((char)0xff),"i"(0xa1)); /* Mask all interrupts */
576 rkprintf("Interrupts redirected\n");
579 * Check for valid ExecBase. This is quite important part, because this way
580 * we may determine whether to clear and reconfigure memory or whether we
581 * already know everything and may continue further initialisation.
583 if (!exec_check_base())
585 ULONG negsize = 0; /* size of vector table */
586 void **fp = LIBFUNCTABLE; /* pointer to a function in the table */
588 rkprintf("Reallocating ExecBase...");
590 * If we managed to reach this point, it means that there was no ExecBase in
591 * the memory. That means that we have to calculate amount of memory available.
593 * We will guess ExecBase pointer by taking the lowest possible address and
594 * substrating from it the offset of lowet vector used by Exec. This way the ExecBase
595 * Will be placed in the lowes address possible with fitting all functions :)
598 /* Calculate the size of the vector table */
599 while (*fp++ != (VOID *) -1) negsize += LIB_VECTSIZE;
601 ExecBase = (struct ExecBase *) 0x00002000; /* Got ExecBase at the lowest possible addr */
602 ExecBase += negsize; /* Substract lowest vector so jumpable would fit */
604 /* Check whether we have some FAST memory,
605 * If not, then use calculated ExecBase */
606 if ((extmem = exec_RamCheck_fast(arosmb)))
608 rkprintf("%x Fastmem\n",extmem);
609 /* We have found some FAST memory. Let's use it for ExecBase */
610 ExecBase = (struct ExecBase *) 0x01000000;
611 ExecBase += negsize;
613 /* Now we will clear FAST memory. */
614 /* Disabled due to taking to much time on P4 machines */
615 rkprintf("Clearing FastMem...");
617 /************* NICJA - Fix this code so that only unused meory is flushed, and protect certain ares - ie acpi */
619 /* Ogun - Disable cruddy attempt to save ACPI data for now */
620 //bzero((void *)0x01000000, extmem - 0x01000000 - 0x500000);
621 bzero((void *)0x01000000, extmem - 0x01000000);
625 * Now, the FAST memory is cleared, the ExecBase is reserved. We have only to
626 * determine how much CHIP memory do we have.
629 locmem = exec_RamCheck_dma(arosmb);
630 rkprintf("%x Chipmem\n",locmem);
632 rkprintf("OK\nExecBase=%p\n", ExecBase);
634 /* Clear chip ram. Do it carefully as we have kernel somewhere in chip! */
637 * NOTE:
638 * We will leave area 0x90000 - 0xa0000 uncleared as there is
639 * temporary system stack!
641 rkprintf("Clearing ChipMem...\n");
643 bzero((void *)0x2000, 0x90000-0x2000);
644 bzero(&_end, locmem -(ULONG)&_end);
646 else
648 ExecBase = *(struct ExecBase **)4UL;
650 locmem = ExecBase->MaxLocMem;
651 extmem = (ULONG)ExecBase->MaxExtMem;
653 rkprintf("Got old ExecBase = %p\n",ExecBase);
656 * We happend to be here with local ExecBase properly set as well as
657 * local locmem and extmem
660 // exec_SetColors(0x20,0x20,0x20);
662 /* Store this values as they may point to interesting stuff */
663 KickMemPtr = ExecBase->KickMemPtr;
664 KickTagPtr = ExecBase->KickTagPtr;
665 KickCheckSum = ExecBase->KickCheckSum;
667 rkprintf("Clearing ExecBase\n");
669 /* How about clearing most of ExecBase structure? */
670 bzero(&ExecBase->IntVects[0], sizeof(struct ExecBase) - offsetof(struct ExecBase, IntVects[0]));
672 ExecBase->KickMemPtr = KickMemPtr;
673 ExecBase->KickTagPtr = KickTagPtr;
674 ExecBase->KickCheckSum = KickCheckSum;
677 * Now everything is prepared to store ExecBase at the location 4UL and set
678 * it complement in ExecBase structure
681 rkprintf("Initializing library...");
683 *(struct ExecBase **)4 = ExecBase;
684 ExecBase->ChkBase = ~(ULONG)ExecBase;
686 /* Set up system stack */
687 tss->ssp = (extmem) ? extmem : locmem; /* Either in FAST or in CHIP */
688 ExecBase->SysStkUpper = (APTR)tss->ssp;
689 ExecBase->SysStkLower = (APTR)tss->ssp - 0x10000; /* 64KB of system stack */
691 /* Store memory configuration */
692 ExecBase->MaxLocMem = (IPTR)locmem;
693 ExecBase->MaxExtMem = (APTR)extmem;
695 #warning "TODO: Write first step of alert.hook here!!!"
698 * Initialize exec lists. This is done through information table which consist
699 * of offset from begining of ExecBase and type of the list.
701 NEWLIST(&ExecBase->MemList);
702 ExecBase->MemList.lh_Type = NT_MEMORY;
703 NEWLIST(&ExecBase->ResourceList);
704 ExecBase->ResourceList.lh_Type = NT_RESOURCE;
705 NEWLIST(&ExecBase->DeviceList);
706 ExecBase->DeviceList.lh_Type = NT_DEVICE;
707 NEWLIST(&ExecBase->LibList);
708 ExecBase->LibList.lh_Type = NT_LIBRARY;
709 NEWLIST(&ExecBase->PortList);
710 ExecBase->PortList.lh_Type = NT_MSGPORT;
711 NEWLIST(&ExecBase->TaskReady);
712 ExecBase->TaskReady.lh_Type = NT_TASK;
713 NEWLIST(&ExecBase->TaskWait);
714 ExecBase->TaskWait.lh_Type = NT_TASK;
715 NEWLIST(&ExecBase->IntrList);
716 ExecBase->IntrList.lh_Type = NT_INTERRUPT;
717 NEWLIST(&ExecBase->SemaphoreList);
718 ExecBase->SemaphoreList.lh_Type = NT_SIGNALSEM;
719 NEWLIST(&ExecBase->ex_MemHandlers);
721 for (i=0; i<5; i++)
723 NEWLIST(&ExecBase->SoftInts[i].sh_List);
724 ExecBase->SoftInts[i].sh_List.lh_Type = NT_SOFTINT;
728 * Exec.library initializer. Prepares exec.library for future use. All
729 * lists have to be initialized, some values from ROM are copied.
732 ExecBase->TaskTrapCode = exec_DefaultTrap;
733 ExecBase->TaskExceptCode = exec_DefaultTrap;
734 ExecBase->TaskExitCode = exec_DefaultTaskExit;
735 ExecBase->TaskSigAlloc = 0x0000ffff;
736 ExecBase->TaskTrapAlloc = 0x8000;
738 /* Prepare values for execBase (like name, type, pri and other) */
740 ExecBase->LibNode.lib_Node.ln_Type = NT_LIBRARY;
741 ExecBase->LibNode.lib_Node.ln_Pri = 0;
742 ExecBase->LibNode.lib_Node.ln_Name = (char *)exec_name;
743 ExecBase->LibNode.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
744 ExecBase->LibNode.lib_PosSize = sizeof(struct ExecBase);
745 ExecBase->LibNode.lib_OpenCnt = 1;
746 ExecBase->LibNode.lib_IdString = (char *)exec_idstring;
747 ExecBase->LibNode.lib_Version = exec_Version;
748 ExecBase->LibNode.lib_Revision = exec_Revision;
750 ExecBase->Quantum = 4;
751 ExecBase->VBlankFrequency = 50;
752 ExecBase->PowerSupplyFrequency = 1;
754 rkprintf("OK\nBuilding JumpTable...");
756 /* Build the jumptable */
757 ExecBase->LibNode.lib_NegSize =
758 Exec_MakeFunctions(ExecBase, LIBFUNCTABLE, NULL, ExecBase);
760 rkprintf("OK\n");
762 /* Add FAST memory at 0x01000000 to free memory lists */
763 if (extmem)
765 ULONG base = ((ULONG)ExecBase + sizeof(struct ExecBase) + 15) & ~15;
767 AddMemList(extmem - (base + 0x10000),
768 MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL,
770 (APTR)base,
771 (STRPTR)exec_fastname);
773 AddMemList(locmem - 0x2000,
774 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL | MEMF_24BITDMA,
775 -10,
776 (APTR)0x2000,
777 (STRPTR)exec_chipname);
779 rkprintf("Chip Memory : %luMB\nFast Memory : %luMB\n",
780 locmem >> 20, (extmem - locmem) >> 20);
782 else
784 ULONG base = ((ULONG)ExecBase + sizeof(struct ExecBase) + 15) & ~15;
785 AddMemList(locmem - (base + 0x10000),
786 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL | MEMF_24BITDMA,
787 -10,
788 (APTR)base,
789 (STRPTR)exec_chipname);
791 rkprintf("Chip Memory : %luMB\n", locmem >> 20);
794 rkprintf("Memory added\n");
796 /* Protect kernel and RO data from beeing allocated by software */
797 AllocAbs((ULONG)&_end - 0x000a0000, (APTR)0x000a0000);
799 /* Protect bootup stack from being allocated */
800 AllocAbs(0x3000,0x90000);
802 rkprintf("Kernel protected\n");
804 rkprintf("Adding \"exec.library\"...");
806 /* Add exec.library to system library list */
807 SumLibrary((struct Library *)SysBase);
808 Enqueue(&SysBase->LibList,&SysBase->LibNode.lib_Node);
810 rkprintf("OK\n");
812 ExecBase->DebugAROSBase = PrepareAROSSupportBase();
814 #if SMP_SUPPORT
815 /* Early Boot CPU preperation.. */
816 prepare_primary_cpu( ExecBase );
817 #endif
819 rkprintf( "[CPU] Primary CPU Probed ..\n" );
821 for (i=0; i<16; i++)
823 if( (1<<i) & (INTF_PORTS|INTF_COPER|INTF_VERTB|INTF_EXTER|INTF_SETCLR))
825 struct Interrupt *is;
826 struct SoftIntList *sil;
827 is = AllocMem
829 sizeof(struct Interrupt) + sizeof(struct SoftIntList),
830 MEMF_CLEAR | MEMF_PUBLIC
832 if( is == NULL )
834 rkprintf("ERROR: Cannot install Interrupt Servers!\n");
836 sil = (struct SoftIntList *)((struct Interrupt *)is + 1);
838 is->is_Code = &IntServer;
839 is->is_Data = sil;
840 NEWLIST((struct List *)sil);
841 SetIntVector(i,is);
843 else
845 struct Interrupt *is;
846 switch (i)
848 case INTB_SOFTINT :
849 is = AllocMem
851 sizeof(struct Interrupt),
852 MEMF_CLEAR | MEMF_PUBLIC
854 if (is == NULL)
856 rkprintf("Error: Cannot install Interrupt Servers!\n");
857 // Alert(AT_DeadEnd | AN_IntrMem);
859 is->is_Node.ln_Type = NT_SOFTINT; //INTERRUPT;
860 is->is_Node.ln_Pri = 0;
861 is->is_Node.ln_Name = "SW Interrupt Dispatcher";
862 is->is_Data = NULL;
863 is->is_Code = (void *)SoftIntDispatch;
864 SetIntVector(i,is);
865 break;
870 #warning "TODO: Write CPU detailed detection scheme. Patch proper functions??"
872 Init_Traps();
873 irqSetup();
874 rkprintf("IRQ services initialized\n");
876 /* Create user interrupt used to enter supervisor mode */
877 set_gate(idt + 0x80, 14, 3, Exec_SystemCall);
879 /* Enable interrupts and set int disable level to -1 */
880 asm("sti");
881 ExecBase->TDNestCnt = -1;
882 ExecBase->IDNestCnt = -1;
884 /* Now it's time to calculate exec checksum. It will be used
885 * in future to distinguish whether we'd had proper execBase
886 * before restart */
888 UWORD sum=0, *ptr = &ExecBase->SoftVer;
889 int i=((int)&ExecBase->IntVects[0] - (int)&ExecBase->SoftVer) / 2,
892 /* Calculate sum for every static part from SoftVer to ChkSum */
893 for (j=0;j < i;j++)
895 sum+=*(ptr++);
898 ExecBase->ChkSum = ~sum;
901 rkprintf("Creating the very first task...");
903 /* Create boot task. Sigh, we actually create a Process sized Task,
904 since DOS needs to call things which think it has a Process and
905 we don't want to overwrite memory with something strange do we?
907 We do this until at least we can boot dos more cleanly.
910 struct Task *t;
911 struct MemList *ml;
913 ml = (struct MemList *)AllocMem(sizeof(struct MemList), MEMF_PUBLIC|MEMF_CLEAR);
914 t = (struct Task *) AllocMem(sizeof(struct Process), MEMF_PUBLIC|MEMF_CLEAR);
916 if( !ml || !t )
918 rkprintf("ERROR: Cannot create Boot Task!\n");
920 ml->ml_NumEntries = 1;
921 ml->ml_ME[0].me_Addr = t;
922 ml->ml_ME[0].me_Length = sizeof(struct Process);
924 NEWLIST(&t->tc_MemEntry);
925 NEWLIST(&((struct Process *)t)->pr_MsgPort.mp_MsgList);
927 /* It's the boot process that RunCommand()s the boot shell, so we
928 must have this list initialized */
929 NEWLIST((struct List *)&((struct Process *)t)->pr_LocalVars);
931 AddHead(&t->tc_MemEntry,&ml->ml_Node);
933 t->tc_Node.ln_Name = exec_name;
934 t->tc_Node.ln_Pri = 0;
935 t->tc_Node.ln_Type = NT_TASK;
936 t->tc_State = TS_RUN;
937 t->tc_SigAlloc = 0xFFFF;
938 t->tc_SPLower = 0; /* This is the system's stack */
939 t->tc_SPUpper = (APTR)~0UL;
940 t->tc_Flags |= TF_ETASK;
942 if (t->tc_Flags & TF_ETASK)
944 t->tc_UnionETask.tc_ETask = AllocVec
946 sizeof(struct IntETask),
947 MEMF_ANY|MEMF_CLEAR
950 if (!t->tc_UnionETask.tc_ETask)
952 rkprintf("Not enough memory for first task\n");
955 /* Initialise the ETask data. */
956 InitETask(t, t->tc_UnionETask.tc_ETask);
958 GetIntETask(t)->iet_Context = AllocTaskMem(t
959 , SIZEOF_ALL_REGISTERS
960 , MEMF_PUBLIC|MEMF_CLEAR
963 if (!GetIntETask(t)->iet_Context)
965 rkprintf("Not enough memory for first task\n");
969 ExecBase->ThisTask = t;
972 rkprintf("Done\n");
975 Check whether the CPU supports SSE and FXSAVE.
977 Dirty check, without use of any defines and human readable constants. The
978 cpuid instruction with %eax=1 will return some essential cpu informations in %edx back,
979 including:
980 - bit 24: CPU does support FXSAVE and FXRSTOR for MMX/FPU/SSE context saving and restoring
981 - bit 25: CPU supports SSE
982 - bit 26: CPU supports SSE2
985 ULONG v1,v2,v3,v4;
986 cpuid(1, v1,v2,v3,v4);
988 rkprintf("cpuid 1 = %08x %08x %08x %08x\n", v1, v2, v3, v4);
990 if (v4 & (1 << 24))
992 rkprintf("The CPU supports FXSAVE and FXRSTOR. Good.\n");
993 rkprintf("CPU Supports ");
995 switch ((v4 >> 25) & 3)
997 case 3:
998 case 2:
999 rkprintf("SSE2 ");
1000 case 1:
1001 rkprintf("SSE\n");
1002 /* Patch exec with SSE-aware CPU context functions */
1003 SetFunction(&ExecBase->LibNode, -6*LIB_VECTSIZE, AROS_SLIB_ENTRY(PrepareContext_SSE, Exec));
1004 SetFunction(&ExecBase->LibNode, -9*LIB_VECTSIZE, AROS_SLIB_ENTRY(Switch_SSE, Exec));
1005 SetFunction(&ExecBase->LibNode, -10*LIB_VECTSIZE, AROS_SLIB_ENTRY(Dispatch_SSE, Exec));
1006 /* tell the CPU that we will support SSE */
1007 wrcr(cr4, rdcr(cr4) | (3 << 9));
1008 /* Clear the EM and MP flags of CR0 */
1009 wrcr(cr0, rdcr(cr0) & ~6);
1010 rkprintf("SSE enabled.\n");
1011 break;
1013 default:
1015 Ha! Bloody PentiumII does supports MMX/FPU/SSE saving instructions,
1016 but it does not support SSE
1018 rkprintf("no SSE. Sorry :)\n");
1019 break;
1022 else
1024 #if ASSUME_FPU
1025 SetFunction(&ExecBase->LibNode, -6*LIB_VECTSIZE, AROS_SLIB_ENTRY(PrepareContext_FPU, Exec));
1026 SetFunction(&ExecBase->LibNode, -9*LIB_VECTSIZE, AROS_SLIB_ENTRY(Switch_FPU, Exec));
1027 SetFunction(&ExecBase->LibNode, -10*LIB_VECTSIZE, AROS_SLIB_ENTRY(Dispatch_FPU, Exec));
1029 rkprintf("FPU enabled.\n");
1030 #endif
1034 rkprintf("Jumping out from Supervisor mode...");
1036 #if 0
1038 asm("mov %0,%%ds\n\t" /* User DS */
1039 "mov %0,%%es\n\t" /* User ES */
1040 "movl %%esp,%%ebx\n\t" /* Hold the esp value before pushing! */
1041 "pushl %0\n\t" /* User SS */
1042 "pushl %%ebx\n\t" /* Stack frame */
1043 "pushl $0x3002\n\t" /* IOPL:3 */
1044 "pushl %1\n\t" /* User CS */
1045 "pushl $1f\n\t" /* Entry address */
1046 "iret\n" /* Go down to the user mode */
1047 "1:\tsti" /* Enable interrupts */
1049 : "eax"(USER_DS),"ecx"(USER_CS));
1050 #else
1051 # define _stringify(x) #x
1052 # define stringify(x) _stringify(x)
1054 asm("movl $" stringify(USER_DS) ",%%eax\n\t"
1055 "mov %%eax,%%ds\n\t" /* User DS */
1056 "mov %%eax,%%es\n\t" /* User ES */
1057 "movl %%esp,%%ebx\n\t" /* Hold the esp value before pushing! */
1058 "pushl %%eax\n\t" /* User SS */
1059 "pushl %%ebx\n\t" /* Stack frame */
1060 "pushl $0x3002\n\t" /* IOPL:3 */
1061 "pushl $" stringify(USER_CS) "\n\t" /* User CS */
1062 "pushl $1f\n\t" /* Entry address */
1063 "iret\n" /* Go down to the user mode */
1064 "1:\tsti":::"eax","ebx"); /* Enable interrupts */
1066 # undef stringify
1067 # undef _stringify
1068 #endif
1070 rkprintf("Done\n");
1072 ExecBase->TDNestCnt++;
1073 Permit();
1074 #if (AROS_SERIAL_DEBUG >0)
1075 SetFunction(&ExecBase->LibNode, -84*LIB_VECTSIZE, AROS_SLIB_ENTRY(SerialRawIOInit, Exec));
1076 SetFunction(&ExecBase->LibNode, -86*LIB_VECTSIZE, AROS_SLIB_ENTRY(SerialRawPutChar, Exec));
1077 RawIOInit();
1078 #endif
1081 /* Scan for valid RomTags */
1082 ExecBase->ResModules = exec_RomTagScanner();
1084 if (ExecBase->CoolCapture)
1086 void (*p)() = ExecBase->CoolCapture;
1087 (*p)();
1090 InitCode(RTF_SINGLETASK, 0);
1091 InitCode(RTF_COLDSTART, 0);
1094 * We suppose that at this point dos.library has already taken over.
1095 * The last thing to do is to call WarmCapture vector. After that this
1096 * task has completely nothing to do so it may execute Debug() in
1097 * forever loop
1100 if (ExecBase->WarmCapture)
1102 void (*p)() = ExecBase->WarmCapture;
1103 (*p)();
1106 do { Debug(0); } while(1);
1109 /* Small delay routine used by exec_cinit initializer */
1110 asm("\ndelay:\t.short 0x00eb\n\tret");
1112 /* Exec default trap routine */
1113 asm("\nexec_DefaultTrap:\n\t"
1114 "pushl 4\n\t"
1115 "pushl $0\n\t"
1116 "pushl $0\n\t"
1117 "jmp Exec_Alert");
1119 #warning "TODO: We should use info from BIOS here."
1120 int exec_RamCheck_dma(struct arosmb *arosmb)
1122 ULONG volatile *ptr,tmp;
1124 ptr = (ULONG *)(((int)&_end + 0x0FFF) &~0x0FFF);
1126 if(arosmb->flags & MB_FLAGS_MEM)
1128 /* If there is upper memory, assume that lower is 1MB. Dirty hack++ */
1129 if(arosmb->mem_upper)
1131 if ((arosmb->mem_upper<<10) & 0xff000000)
1133 /* More than 16MB in total, return 16 */
1134 return 16<<20;
1136 /* Lower 16MB is marked as DMA memory */
1137 tmp = (arosmb->mem_upper * 1024) & 0x00ffffff;
1138 tmp += 0x100000;
1139 return tmp;
1141 else
1143 /* No upper memory, return only lower mem.
1144 * Most likely fatal, can't see aros working with less than one MB of ram */
1145 return (arosmb->mem_lower * 1024);
1148 /* No memory info from bios, do a scan */
1151 tmp = *ptr;
1152 *ptr = 0xdeadbeef;
1153 if (*ptr != 0xdeadbeef)
1154 break;
1155 *ptr = tmp;
1156 ptr += 4;
1157 } while ((int)ptr < 0x01000000);
1159 return (int)ptr;
1162 int exec_RamCheck_fast(struct arosmb *arosmb)
1164 ULONG volatile *ptr, tmp;
1166 ptr = (ULONG *)0x01000000;
1168 if(arosmb->flags & MB_FLAGS_MEM)
1170 /* If less than 15MB upper, no fastmem here */
1171 if ((arosmb->mem_upper * 1024) <= 0xF00000)
1173 return 0;
1175 /* Found memory, so we need to do some quick math */
1176 tmp = (arosmb->mem_upper * 1024) + 0x100000;
1177 return tmp;
1179 /* No memory info from bios, do a scan */
1182 tmp = *ptr;
1183 *ptr = 0xdeadbeef;
1184 if (*ptr != 0xdeadbeef)
1185 break;
1186 *ptr = tmp;
1187 ptr += 4;
1188 } while(1);
1190 return ((int)ptr > 0x01000000) ? (int)ptr : 0;
1193 void exec_DefaultTaskExit()
1195 struct ExecBase *SysBase = *(struct ExecBase **)4UL;
1196 RemTask(SysBase->ThisTask);
1200 * Check for valid ExecBase
1202 int exec_check_base()
1204 /* Get ExecBase from 0x00000004 */
1205 struct ExecBase *ExecBase=*(struct ExecBase **)4UL;
1207 /* Attempt first test. If ExecBase is not aligned to 4 byte boundary then
1208 * it is not proper ExecBase */
1209 if (!((ULONG)ExecBase & 0x3))
1212 * Assume for a while, that it is ExecBase indeed. Check complement of
1213 * this pointer, which is stored in ExecBase->ChkBase
1215 if (!~((LONG)ExecBase + ExecBase->ChkBase))
1218 * Still here? Nice, let's check one more thing. Static part of
1219 * ExecBase has its checksum calculated. Verify it please...
1221 UWORD sum=0, *ptr = &ExecBase->SoftVer;
1222 int i=((int)&ExecBase->IntVects[0] - (int)&ExecBase->SoftVer) / 2,
1225 /* Calculate sum for every static part from SoftVer to ChkSum */
1226 for (j=0;j < i;j++)
1228 sum+=*(ptr++);
1231 /* Do we have proper checksum? */
1232 if (!~sum)
1234 /* Well well, almost sure that we have ExecBase here. Hey, it's
1235 * time to execute ColdCapture code! */
1236 void (*p)() = ExecBase->ColdCapture;
1238 /* Only if there is ColdCapture code... */
1239 if (p)
1241 ExecBase->ColdCapture = NULL;
1242 (*p)();
1246 * Let's check ExecBase last time. Compare library version and
1247 * revision vs ones stored deep in the core. If they will differ
1248 * then ExecBase is damaged
1251 if ((ExecBase->LibNode.lib_Version == exec_Version) &&
1252 (ExecBase->LibNode.lib_Revision == exec_Revision))
1255 * Really last thing. Check MaxLocMem and MaxExtMem fields
1256 * in ExecBase. First cannot be grater than 16MB and smaller
1257 * than 2MB, second, if is not zero then has to be grater
1258 * than 16MB
1261 if ((ExecBase->MaxLocMem >= 0x00200000) &&
1262 (ExecBase->MaxLocMem <= 0x01000000))
1264 if (ExecBase->MaxExtMem && ((ULONG)ExecBase->MaxExtMem < 0x01000000))
1266 return 0;
1268 return 1;
1274 return 0;
1277 void _aros_not_implemented()
1282 * RomTag scanner.
1284 * This function scans kernel for existing Resident modules. If two modules
1285 * with the same name are found, the one with higher version or priority wins.
1287 * After building list of kernel modules, the KickTagPtr and KickMemPtr are
1288 * checksummed. If checksum is proper and all memory pointed in KickMemPtr may
1289 * be allocated, then all modules from KickTagPtr are added to RT list
1291 * Afterwards the proper RomTagList is created (see InitCode() for details) and
1292 * memory after list and nodes is freed.
1295 struct rt_node
1297 struct Node node;
1298 struct Resident *module;
1301 ULONG **exec_RomTagScanner()
1303 struct ExecBase *SysBase = *(struct ExecBase **)4UL;
1305 struct List rtList; /* List of modules */
1306 UWORD *ptr = (UWORD*)0x00100000; /* Start looking here */
1308 struct Resident *res; /* module found */
1310 int i;
1311 ULONG **RomTag;
1313 /* Initialize list */
1314 NEWLIST(&rtList);
1316 kprintf("Resident modules (addr: pri version name):\n");
1318 /* Look in whole kernel for resident modules */
1321 /* Do we have RTC_MATCHWORD? */
1322 if (*ptr == RTC_MATCHWORD)
1324 /* Yes, assume we have Resident */
1325 res = (struct Resident *)ptr;
1327 /* Does rt_MatchTag point to Resident? */
1328 if (res == res->rt_MatchTag)
1330 /* Yes, it is Resident module */
1331 struct rt_node *node;
1333 /* Check if there is module with such name already */
1334 node = (struct rt_node*)FindName(&rtList, res->rt_Name);
1335 if (node)
1337 /* Yes, there was such module. It it had lower pri then replace it */
1338 if (node->node.ln_Pri <= res->rt_Pri)
1340 /* If they have the same Pri but new one has higher Version, replace */
1341 if ((node->node.ln_Pri == res->rt_Pri) &&
1342 (node->module->rt_Version < res->rt_Version))
1344 node->node.ln_Pri = res->rt_Pri;
1345 node->module = res;
1349 else
1351 /* New module. Allocate some memory for it */
1352 node = (struct rt_node *)
1353 AllocMem(sizeof(struct rt_node),MEMF_PUBLIC|MEMF_CLEAR);
1355 if (node)
1357 node->node.ln_Name = res->rt_Name;
1358 node->node.ln_Pri = res->rt_Pri;
1359 node->module = res;
1361 Enqueue(&rtList,(struct Node*)node);
1365 /* Get address of EndOfResident from RomTag but only when it's
1366 * higher then present one - this avoids strange locks when
1367 * not all modules have Resident structure in .text section */
1368 ptr = ((ULONG)res->rt_EndSkip > (ULONG)ptr) ? (UWORD *)res->rt_EndSkip : ptr + 2;
1369 if ((ULONG)ptr & 0x01)
1370 ptr = (UWORD *)((ULONG)ptr+1);
1371 continue;
1375 /* Get next address... */
1376 ptr++;
1377 } while (ptr < (UWORD*)&_end);
1380 * By now we have valid (and sorted) list of kernel resident modules.
1382 * Now, we will have to analyze used-defined RomTags (via KickTagPtr and
1383 * KickMemPtr)
1385 #warning "TODO: Implement external modules!"
1388 * Everything is done now. Allocate buffer for normal RomTag and convert
1389 * list to RomTag
1392 ListLength(&rtList,i); /* Get length of the list */
1394 RomTag = AllocMem((i+1)*4,MEMF_PUBLIC | MEMF_CLEAR);
1396 if (RomTag)
1398 int j;
1399 struct rt_node *n;
1401 for (j=0; j<i; j++)
1403 n = (struct rt_node *)RemHead(&rtList);
1404 kprintf("+ 0x%08.8lx: %4d %3d \"%s\"\n",
1405 n->module,
1406 n->node.ln_Pri,
1407 n->module->rt_Version,
1408 n->node.ln_Name);
1409 RomTag[j] = (ULONG*)n->module;
1411 FreeMem(n, sizeof(struct rt_node));
1413 RomTag[i] = 0;
1416 return RomTag;
1419 struct vbe_controller my_vbe_control;
1420 struct vbe_mode my_vbe_mode;
1422 unsigned char setupVesa(struct multiboot *mbinfo)
1424 char *str = mbinfo->cmdline;
1425 char *vesa = strstr(str, "vesa=");
1426 short r;
1427 unsigned char palwidth = 0;
1429 if (vesa)
1431 long x=0, y=0, d=0;
1432 long mode, setmode;
1433 unsigned long vesa_size = (unsigned long)&_binary_vesa_size;
1434 void *vesa_start = &_binary_vesa_start;
1435 vesa+=5;
1437 while (*vesa && *vesa != ',' && *vesa != 'x' && *vesa != ' ')
1439 x = x*10 + *vesa++ - '0';
1441 vesa++;
1442 while (*vesa && *vesa != ',' && *vesa != 'x' && *vesa != ' ')
1444 y = y*10 + *vesa++ - '0';
1446 vesa++;
1447 while (*vesa && *vesa != ',' && *vesa != 'x' && *vesa != ' ')
1449 d = d*10 + *vesa++ - '0';
1452 rkprintf("[VESA] module (@ %p) size=%d\n", &_binary_vesa_start, &_binary_vesa_size);
1453 memcpy((void *)0x1000, vesa_start, vesa_size);
1454 rkprintf("[VESA] Module installed\n");
1456 rkprintf("[VESA] BestModeMatch for %dx%dx%d = ",x,y,d);
1457 mode = findMode(x,y,d);
1459 getModeInfo(mode);
1461 rkprintf("%x\n",mode);
1462 if (modeinfo->mode_attributes & 0x80)
1463 setmode = mode | 0x4000;
1464 else
1465 setmode = mode;
1466 r = setVbeMode(setmode);
1467 if (r == 0x004f) {
1468 rkprintf("\x03");
1469 if (controllerinfo->capabilities & 0x01)
1470 paletteWidth(0x0800, &palwidth);
1471 else
1472 palwidth = 6;
1473 memcpy(&my_vbe_mode, modeinfo, sizeof(struct vbe_mode));
1474 memcpy(&my_vbe_control, controllerinfo, sizeof(struct vbe_controller));
1475 mbinfo->vbe_mode_info = (ULONG)&my_vbe_mode;
1476 mbinfo->vbe_control_info = (ULONG)&my_vbe_control;
1477 mbinfo->flags |= MB_FLAGS_GFX;
1478 mbinfo->vbe_mode = mode;
1479 } else
1480 rkprintf("[VESA] mode setting error: 0x%04X\n", r);
1482 return palwidth;
1485 AROS_LH1(struct ExecBase *, open,
1486 AROS_LHA(ULONG, version, D0),
1487 struct ExecBase *, SysBase, 1, Exec)
1489 AROS_LIBFUNC_INIT
1491 /* I have one more opener. */
1492 SysBase->LibNode.lib_OpenCnt++;
1493 return SysBase;
1494 AROS_LIBFUNC_EXIT
1497 AROS_LH0(BPTR, close,
1498 struct ExecBase *, SysBase, 2, Exec)
1500 AROS_LIBFUNC_INIT
1502 /* I have one fewer opener. */
1503 SysBase->LibNode.lib_OpenCnt--;
1504 return 0;
1505 AROS_LIBFUNC_EXIT
1508 AROS_LH0I(int, null,
1509 struct ExecBase *, SysBase, 4, Exec)
1511 AROS_LIBFUNC_INIT
1512 return 0;
1513 AROS_LIBFUNC_EXIT
1517 We temporarily redefine kprintf() so we use the real version in case
1518 we have one of these two fn's called before AROSSupportBase is ready.
1521 #undef kprintf
1522 #undef rkprintf
1523 #undef vkprintf
1525 #define kprintf(x...)
1526 #define rkprintf(x...)
1527 #define vkprintf(x...)
1529 struct Library * PrepareAROSSupportBase(void)
1531 struct AROSSupportBase *AROSSupportBase =
1532 AllocMem(sizeof(struct AROSSupportBase), MEMF_CLEAR);
1534 AROSSupportBase->kprintf = (void *)kprintf;
1535 AROSSupportBase->rkprintf = (void *)rkprintf;
1536 AROSSupportBase->vkprintf = (void *)vkprintf;
1538 NEWLIST(&AROSSupportBase->AllocMemList);
1540 #warning "FIXME Add code to read in the debug options"
1542 return (struct Library *)AROSSupportBase;
1545 /* IntServer:
1546 This interrupt handler will send an interrupt to a series of queued
1547 interrupt servers. Servers should return D0 != 0 (Z clear) if they
1548 believe the interrupt was for them, and no further interrupts will
1549 be called. This will only check the value in D0 for non-m68k systems,
1550 however it SHOULD check the Z-flag on 68k systems.
1552 Hmm, in that case I would have to separate it from this file in order
1553 to replace it...
1555 AROS_UFH5S(void, IntServer,
1556 AROS_UFHA(ULONG, intMask, D0),
1557 AROS_UFHA(struct Custom *, custom, A0),
1558 AROS_UFHA(struct List *, intList, A1),
1559 AROS_UFHA(APTR, intCode, A5),
1560 AROS_UFHA(struct ExecBase *, SysBase, A6))
1562 AROS_USERFUNC_INIT
1564 struct Interrupt * irq;
1566 ForeachNode(intList, irq)
1568 if( AROS_UFC4(int, irq->is_Code,
1569 AROS_UFCA(struct Custom *, custom, A0),
1570 AROS_UFCA(APTR, irq->is_Data, A1),
1571 AROS_UFCA(APTR, irq->is_Code, A5),
1572 AROS_UFCA(struct ExecBase *, SysBase, A6)
1574 break;
1577 AROS_USERFUNC_EXIT