2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Early bootup section
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 +------------+-----------+-------------------------------------------------+
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>
70 #include <aros/debug.h>
71 #include <aros/multiboot.h>
73 #include <hardware/custom.h>
75 #include <proto/exec.h>
81 #include LC_LIBDEFS_FILE
84 #include "exec_util.h"
91 extern void prepare_primary_cpu(struct ExecBase
*SysBase
); /* FUNCTION FROM "cpu.resource"!!!!!!! */
94 /* As long as we don't have CPU detection routine, assume FPU to be present */
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
105 #define __text __attribute__((section(".text")))
106 #define __no_ret __attribute__((noreturn))
107 #define __packed __attribute__((packed))
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)
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();
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
));
164 #define memcpy(_d, _s, _len) \
169 ((char *)_d)[len-1] = ((char *)_s)[len-1];\
175 /* Temporary information */
180 void scr_RawPutChars(char *, int);
187 #define rkprintf(x...) scr_RawPutChars(tab, snprintf(tab,126, x))
191 #define clr() /* eps */
192 #define rkprintf(x...) /* eps */
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
202 asm( ".globl aros_intern\n\t"
203 ".globl SysBase \n\t"
204 ".set aros_intern,0\n\t"
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
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
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
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!! */
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
)
285 short reg
= 0x3c8; /* IO reg to control PEL */
287 asm("movb $0,%%al\n\t" /* Start with color 0 */
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
));
307 * Mixed stuff used to control TSS/GDT/IDT stuff. This is strictly machine
311 asm(".globl TSS\n\t" /* Make this three global in case one would */
312 ".globl SSP\n\t" /* decide to use them directly */
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
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 */
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) \
359 __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
361 "movl %%eax,%0\n\t" \
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)); \
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 */
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
;
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
);
435 rkprintf("AROS - The AROS Research OS\nCompiled %s\n\n",__DATE__
);
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
;
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
));
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
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 */
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
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;
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! */
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
);
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
);
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
);
762 /* Add FAST memory at 0x01000000 to free memory lists */
765 ULONG base
= ((ULONG
)ExecBase
+ sizeof(struct ExecBase
) + 15) & ~15;
767 AddMemList(extmem
- (base
+ 0x10000),
768 MEMF_FAST
| MEMF_PUBLIC
| MEMF_KICK
| MEMF_LOCAL
,
771 (STRPTR
)exec_fastname
);
773 AddMemList(locmem
- 0x2000,
774 MEMF_CHIP
| MEMF_PUBLIC
| MEMF_KICK
| MEMF_LOCAL
| MEMF_24BITDMA
,
777 (STRPTR
)exec_chipname
);
779 rkprintf("Chip Memory : %luMB\nFast Memory : %luMB\n",
780 locmem
>> 20, (extmem
- locmem
) >> 20);
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
,
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
);
812 ExecBase
->DebugAROSBase
= PrepareAROSSupportBase();
815 /* Early Boot CPU preperation.. */
816 prepare_primary_cpu( ExecBase
);
819 rkprintf( "[CPU] Primary CPU Probed ..\n" );
823 if( (1<<i
) & (INTF_PORTS
|INTF_COPER
|INTF_VERTB
|INTF_EXTER
|INTF_SETCLR
))
825 struct Interrupt
*is
;
826 struct SoftIntList
*sil
;
829 sizeof(struct Interrupt
) + sizeof(struct SoftIntList
),
830 MEMF_CLEAR
| MEMF_PUBLIC
834 rkprintf("ERROR: Cannot install Interrupt Servers!\n");
836 sil
= (struct SoftIntList
*)((struct Interrupt
*)is
+ 1);
838 is
->is_Code
= &IntServer
;
840 NEWLIST((struct List
*)sil
);
845 struct Interrupt
*is
;
851 sizeof(struct Interrupt
),
852 MEMF_CLEAR
| MEMF_PUBLIC
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";
863 is
->is_Code
= (void *)SoftIntDispatch
;
870 #warning "TODO: Write CPU detailed detection scheme. Patch proper functions??"
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 */
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
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 */
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.
913 ml
= (struct MemList
*)AllocMem(sizeof(struct MemList
), MEMF_PUBLIC
|MEMF_CLEAR
);
914 t
= (struct Task
*) AllocMem(sizeof(struct Process
), MEMF_PUBLIC
|MEMF_CLEAR
);
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
= AllocTaskMem(t
, sizeof(struct IntETask
), MEMF_ANY
|MEMF_CLEAR
);
946 if (!t
->tc_UnionETask
.tc_ETask
)
948 rkprintf("Not enough memory for first task\n");
951 GetIntETask(t
)->iet_Context
= AllocTaskMem(t
952 , SIZEOF_ALL_REGISTERS
953 , MEMF_PUBLIC
|MEMF_CLEAR
956 if (!GetIntETask(t
)->iet_Context
)
958 rkprintf("Not enough memory for first task\n");
962 ExecBase
->ThisTask
= t
;
968 Check whether the CPU supports SSE and FXSAVE.
970 Dirty check, without use of any defines and human readable constants. The
971 cpuid instruction with %eax=1 will return some essential cpu informations in %edx back,
973 - bit 24: CPU does support FXSAVE and FXRSTOR for MMX/FPU/SSE context saving and restoring
974 - bit 25: CPU supports SSE
975 - bit 26: CPU supports SSE2
979 cpuid(1, v1
,v2
,v3
,v4
);
981 rkprintf("cpuid 1 = %08x %08x %08x %08x\n", v1
, v2
, v3
, v4
);
985 rkprintf("The CPU supports FXSAVE and FXRSTOR. Good.\n");
986 rkprintf("CPU Supports ");
988 switch ((v4
>> 25) & 3)
995 /* Patch exec with SSE-aware CPU context functions */
996 SetFunction(&ExecBase
->LibNode
, -6*LIB_VECTSIZE
, AROS_SLIB_ENTRY(PrepareContext_SSE
, Exec
));
997 SetFunction(&ExecBase
->LibNode
, -9*LIB_VECTSIZE
, AROS_SLIB_ENTRY(Switch_SSE
, Exec
));
998 SetFunction(&ExecBase
->LibNode
, -10*LIB_VECTSIZE
, AROS_SLIB_ENTRY(Dispatch_SSE
, Exec
));
999 /* tell the CPU that we will support SSE */
1000 wrcr(cr4
, rdcr(cr4
) | (3 << 9));
1001 /* Clear the EM and MP flags of CR0 */
1002 wrcr(cr0
, rdcr(cr0
) & ~6);
1003 rkprintf("SSE enabled.\n");
1008 Ha! Bloody PentiumII does supports MMX/FPU/SSE saving instructions,
1009 but it does not support SSE
1011 rkprintf("no SSE. Sorry :)\n");
1018 SetFunction(&ExecBase
->LibNode
, -6*LIB_VECTSIZE
, AROS_SLIB_ENTRY(PrepareContext_FPU
, Exec
));
1019 SetFunction(&ExecBase
->LibNode
, -9*LIB_VECTSIZE
, AROS_SLIB_ENTRY(Switch_FPU
, Exec
));
1020 SetFunction(&ExecBase
->LibNode
, -10*LIB_VECTSIZE
, AROS_SLIB_ENTRY(Dispatch_FPU
, Exec
));
1022 rkprintf("FPU enabled.\n");
1027 rkprintf("Jumping out from Supervisor mode...");
1031 asm("mov %0,%%ds\n\t" /* User DS */
1032 "mov %0,%%es\n\t" /* User ES */
1033 "movl %%esp,%%ebx\n\t" /* Hold the esp value before pushing! */
1034 "pushl %0\n\t" /* User SS */
1035 "pushl %%ebx\n\t" /* Stack frame */
1036 "pushl $0x3002\n\t" /* IOPL:3 */
1037 "pushl %1\n\t" /* User CS */
1038 "pushl $1f\n\t" /* Entry address */
1039 "iret\n" /* Go down to the user mode */
1040 "1:\tsti" /* Enable interrupts */
1042 : "eax"(USER_DS
),"ecx"(USER_CS
));
1044 # define _stringify(x) #x
1045 # define stringify(x) _stringify(x)
1047 asm("movl $" stringify(USER_DS
) ",%%eax\n\t"
1048 "mov %%eax,%%ds\n\t" /* User DS */
1049 "mov %%eax,%%es\n\t" /* User ES */
1050 "movl %%esp,%%ebx\n\t" /* Hold the esp value before pushing! */
1051 "pushl %%eax\n\t" /* User SS */
1052 "pushl %%ebx\n\t" /* Stack frame */
1053 "pushl $0x3002\n\t" /* IOPL:3 */
1054 "pushl $" stringify(USER_CS
) "\n\t" /* User CS */
1055 "pushl $1f\n\t" /* Entry address */
1056 "iret\n" /* Go down to the user mode */
1057 "1:\tsti":::"eax","ebx"); /* Enable interrupts */
1065 ExecBase
->TDNestCnt
++;
1067 #if (AROS_SERIAL_DEBUG >0)
1068 SetFunction(&ExecBase
->LibNode
, -84*LIB_VECTSIZE
, AROS_SLIB_ENTRY(SerialRawIOInit
, Exec
));
1069 SetFunction(&ExecBase
->LibNode
, -86*LIB_VECTSIZE
, AROS_SLIB_ENTRY(SerialRawPutChar
, Exec
));
1074 /* Scan for valid RomTags */
1075 ExecBase
->ResModules
= exec_RomTagScanner();
1077 if (ExecBase
->CoolCapture
)
1079 void (*p
)() = ExecBase
->CoolCapture
;
1083 InitCode(RTF_SINGLETASK
, 0);
1084 InitCode(RTF_COLDSTART
, 0);
1087 * We suppose that at this point dos.library has already taken over.
1088 * The last thing to do is to call WarmCapture vector. After that this
1089 * task has completely nothing to do so it may execute Debug() in
1093 if (ExecBase
->WarmCapture
)
1095 void (*p
)() = ExecBase
->WarmCapture
;
1099 do { Debug(0); } while(1);
1102 /* Small delay routine used by exec_cinit initializer */
1103 asm("\ndelay:\t.short 0x00eb\n\tret");
1105 /* Exec default trap routine */
1106 asm("\nexec_DefaultTrap:\n\t"
1112 #warning "TODO: We should use info from BIOS here."
1113 int exec_RamCheck_dma(struct arosmb
*arosmb
)
1115 ULONG
volatile *ptr
,tmp
;
1117 ptr
= (ULONG
*)(((int)&_end
+ 4095) &~4095);
1119 if(arosmb
->flags
& MB_FLAGS_MEM
)
1121 /* If there is upper memory, assume that lower is 1MB. Dirty hack++ */
1122 if(arosmb
->mem_upper
)
1124 if ((arosmb
->mem_upper
<<10) & 0xff000000)
1126 /* More than 16MB in total, return 16 */
1129 /* Lower 16MB is marked as DMA memory */
1130 tmp
= (arosmb
->mem_upper
*1024) & 0x00ffffff;
1136 /* No upper memory, return only lower mem.
1137 * Most likely fatal, can't see aros working with less than one MB of ram */
1138 return (arosmb
->mem_lower
*1024);
1141 /* No memory info from bios, do a scan */
1146 if (*ptr
!= 0xdeadbeef)
1150 } while ((int)ptr
< 0x01000000);
1155 int exec_RamCheck_fast(struct arosmb
*arosmb
)
1157 ULONG
volatile *ptr
, tmp
;
1159 ptr
= (ULONG
*)0x01000000;
1161 if(arosmb
->flags
& MB_FLAGS_MEM
)
1163 /* If less than 15MB upper, no fastmem here */
1164 if (arosmb
->mem_upper
<= 15*1024)
1168 /* Found memory, so we need to do some quick math */
1169 tmp
= (arosmb
->mem_upper
*1024)+1048576;
1172 /* No memory info from bios, do a scan */
1177 if (*ptr
!= 0xdeadbeef)
1183 return ((int)ptr
> 0x01000000) ? (int)ptr
: 0;
1186 void exec_DefaultTaskExit()
1188 struct ExecBase
*SysBase
= *(struct ExecBase
**)4UL;
1189 RemTask(SysBase
->ThisTask
);
1193 * Check for valid ExecBase
1195 int exec_check_base()
1197 /* Get ExecBase from 0x00000004 */
1198 struct ExecBase
*ExecBase
=*(struct ExecBase
**)4UL;
1200 /* Attempt first test. If ExecBase is not aligned to 4 byte boundary then
1201 * it is not proper ExecBase */
1202 if (!((ULONG
)ExecBase
& 0x3))
1205 * Assume for a while, that it is ExecBase indeed. Check complement of
1206 * this pointer, which is stored in ExecBase->ChkBase
1208 if (!~((LONG
)ExecBase
+ ExecBase
->ChkBase
))
1211 * Still here? Nice, let's check one more thing. Static part of
1212 * ExecBase has its checksum calculated. Verify it please...
1214 UWORD sum
=0, *ptr
= &ExecBase
->SoftVer
;
1215 int i
=((int)&ExecBase
->IntVects
[0] - (int)&ExecBase
->SoftVer
) / 2,
1218 /* Calculate sum for every static part from SoftVer to ChkSum */
1224 /* Do we have proper checksum? */
1227 /* Well well, almost sure that we have ExecBase here. Hey, it's
1228 * time to execute ColdCapture code! */
1229 void (*p
)() = ExecBase
->ColdCapture
;
1231 /* Only if there is ColdCapture code... */
1234 ExecBase
->ColdCapture
= NULL
;
1239 * Let's check ExecBase last time. Compare library version and
1240 * revision vs ones stored deep in the core. If they will differ
1241 * then ExecBase is damaged
1244 if ((ExecBase
->LibNode
.lib_Version
== exec_Version
) &&
1245 (ExecBase
->LibNode
.lib_Revision
== exec_Revision
))
1248 * Really last thing. Check MaxLocMem and MaxExtMem fields
1249 * in ExecBase. First cannot be grater than 16MB and smaller
1250 * than 2MB, second, if is not zero then has to be grater
1254 if ((ExecBase
->MaxLocMem
>= 0x00200000) &&
1255 (ExecBase
->MaxLocMem
<= 0x01000000))
1257 if (ExecBase
->MaxExtMem
&& ((ULONG
)ExecBase
->MaxExtMem
< 0x01000000))
1270 void _aros_not_implemented()
1277 * This function scans kernel for existing Resident modules. If two modules
1278 * with the same name are found, the one with higher version or priority wins.
1280 * After building list of kernel modules, the KickTagPtr and KickMemPtr are
1281 * checksummed. If checksum is proper and all memory pointed in KickMemPtr may
1282 * be allocated, then all modules from KickTagPtr are added to RT list
1284 * Afterwards the proper RomTagList is created (see InitCode() for details) and
1285 * memory after list and nodes is freed.
1291 struct Resident
*module
;
1294 ULONG
**exec_RomTagScanner()
1296 struct ExecBase
*SysBase
= *(struct ExecBase
**)4UL;
1298 struct List rtList
; /* List of modules */
1299 UWORD
*ptr
= (UWORD
*)0x00100000; /* Start looking here */
1301 struct Resident
*res
; /* module found */
1306 /* Initialize list */
1309 kprintf("Resident modules (addr: pri version name):\n");
1311 /* Look in whole kernel for resident modules */
1314 /* Do we have RTC_MATCHWORD? */
1315 if (*ptr
== RTC_MATCHWORD
)
1317 /* Yes, assume we have Resident */
1318 res
= (struct Resident
*)ptr
;
1320 /* Does rt_MatchTag point to Resident? */
1321 if (res
== res
->rt_MatchTag
)
1323 /* Yes, it is Resident module */
1324 struct rt_node
*node
;
1326 /* Check if there is module with such name already */
1327 node
= (struct rt_node
*)FindName(&rtList
, res
->rt_Name
);
1330 /* Yes, there was such module. It it had lower pri then replace it */
1331 if (node
->node
.ln_Pri
<= res
->rt_Pri
)
1333 /* If they have the same Pri but new one has higher Version, replace */
1334 if ((node
->node
.ln_Pri
== res
->rt_Pri
) &&
1335 (node
->module
->rt_Version
< res
->rt_Version
))
1337 node
->node
.ln_Pri
= res
->rt_Pri
;
1344 /* New module. Allocate some memory for it */
1345 node
= (struct rt_node
*)
1346 AllocMem(sizeof(struct rt_node
),MEMF_PUBLIC
|MEMF_CLEAR
);
1350 node
->node
.ln_Name
= res
->rt_Name
;
1351 node
->node
.ln_Pri
= res
->rt_Pri
;
1354 Enqueue(&rtList
,(struct Node
*)node
);
1358 /* Get address of EndOfResident from RomTag but only when it's
1359 * higher then present one - this avoids strange locks when
1360 * not all modules have Resident structure in .text section */
1361 ptr
= ((ULONG
)res
->rt_EndSkip
> (ULONG
)ptr
) ? (UWORD
*)res
->rt_EndSkip
: ptr
+ 2;
1362 if ((ULONG
)ptr
& 0x01)
1363 ptr
= (UWORD
*)((ULONG
)ptr
+1);
1368 /* Get next address... */
1370 } while (ptr
< (UWORD
*)&_end
);
1373 * By now we have valid (and sorted) list of kernel resident modules.
1375 * Now, we will have to analyze used-defined RomTags (via KickTagPtr and
1378 #warning "TODO: Implement external modules!"
1381 * Everything is done now. Allocate buffer for normal RomTag and convert
1385 ListLength(&rtList
,i
); /* Get length of the list */
1387 RomTag
= AllocMem((i
+1)*4,MEMF_PUBLIC
| MEMF_CLEAR
);
1396 n
= (struct rt_node
*)RemHead(&rtList
);
1397 kprintf("+ 0x%08.8lx: %4d %3d \"%s\"\n",
1400 n
->module
->rt_Version
,
1402 RomTag
[j
] = (ULONG
*)n
->module
;
1404 FreeMem(n
, sizeof(struct rt_node
));
1412 struct vbe_controller my_vbe_control
;
1413 struct vbe_mode my_vbe_mode
;
1415 unsigned char setupVesa(struct multiboot
*mbinfo
)
1417 char *str
= mbinfo
->cmdline
;
1418 char *vesa
= strstr(str
, "vesa=");
1420 unsigned char palwidth
= 0;
1426 unsigned long vesa_size
= (unsigned long)&_binary_vesa_size
;
1427 void *vesa_start
= &_binary_vesa_start
;
1430 while (*vesa
&& *vesa
!= ',' && *vesa
!= 'x' && *vesa
!= ' ')
1432 x
= x
*10 + *vesa
++ - '0';
1435 while (*vesa
&& *vesa
!= ',' && *vesa
!= 'x' && *vesa
!= ' ')
1437 y
= y
*10 + *vesa
++ - '0';
1440 while (*vesa
&& *vesa
!= ',' && *vesa
!= 'x' && *vesa
!= ' ')
1442 d
= d
*10 + *vesa
++ - '0';
1445 rkprintf("[VESA] module (@ %p) size=%d\n", &_binary_vesa_start
, &_binary_vesa_size
);
1446 memcpy((void *)0x1000, vesa_start
, vesa_size
);
1447 rkprintf("[VESA] Module installed\n");
1449 rkprintf("[VESA] BestModeMatch for %dx%dx%d = ",x
,y
,d
);
1450 mode
= findMode(x
,y
,d
);
1454 rkprintf("%x\n",mode
);
1455 if (modeinfo
->mode_attributes
& 0x80)
1456 setmode
= mode
| 0x4000;
1459 r
= setVbeMode(setmode
);
1462 if (controllerinfo
->capabilities
& 0x01)
1463 paletteWidth(0x0800, &palwidth
);
1466 memcpy(&my_vbe_mode
, modeinfo
, sizeof(struct vbe_mode
));
1467 memcpy(&my_vbe_control
, controllerinfo
, sizeof(struct vbe_controller
));
1468 mbinfo
->vbe_mode_info
= (ULONG
)&my_vbe_mode
;
1469 mbinfo
->vbe_control_info
= (ULONG
)&my_vbe_control
;
1470 mbinfo
->flags
|= MB_FLAGS_GFX
;
1471 mbinfo
->vbe_mode
= mode
;
1473 rkprintf("[VESA] mode setting error: 0x%04X\n", r
);
1478 AROS_LH1(struct ExecBase
*, open
,
1479 AROS_LHA(ULONG
, version
, D0
),
1480 struct ExecBase
*, SysBase
, 1, Exec
)
1484 /* I have one more opener. */
1485 SysBase
->LibNode
.lib_OpenCnt
++;
1490 AROS_LH0(BPTR
, close
,
1491 struct ExecBase
*, SysBase
, 2, Exec
)
1495 /* I have one fewer opener. */
1496 SysBase
->LibNode
.lib_OpenCnt
--;
1501 AROS_LH0I(int, null
,
1502 struct ExecBase
*, SysBase
, 4, Exec
)
1510 We temporarily redefine kprintf() so we use the real version in case
1511 we have one of these two fn's called before AROSSupportBase is ready.
1518 #define kprintf(x...)
1519 #define rkprintf(x...)
1520 #define vkprintf(x...)
1522 struct Library
* PrepareAROSSupportBase(void)
1524 struct AROSSupportBase
*AROSSupportBase
=
1525 AllocMem(sizeof(struct AROSSupportBase
), MEMF_CLEAR
);
1527 AROSSupportBase
->kprintf
= (void *)kprintf
;
1528 AROSSupportBase
->rkprintf
= (void *)rkprintf
;
1529 AROSSupportBase
->vkprintf
= (void *)vkprintf
;
1531 NEWLIST(&AROSSupportBase
->AllocMemList
);
1533 #warning "FIXME Add code to read in the debug options"
1535 return (struct Library
*)AROSSupportBase
;
1539 This interrupt handler will send an interrupt to a series of queued
1540 interrupt servers. Servers should return D0 != 0 (Z clear) if they
1541 believe the interrupt was for them, and no further interrupts will
1542 be called. This will only check the value in D0 for non-m68k systems,
1543 however it SHOULD check the Z-flag on 68k systems.
1545 Hmm, in that case I would have to separate it from this file in order
1548 AROS_UFH5S(void, IntServer
,
1549 AROS_UFHA(ULONG
, intMask
, D0
),
1550 AROS_UFHA(struct Custom
*, custom
, A0
),
1551 AROS_UFHA(struct List
*, intList
, A1
),
1552 AROS_UFHA(APTR
, intCode
, A5
),
1553 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
1557 struct Interrupt
* irq
;
1559 ForeachNode(intList
, irq
)
1561 if( AROS_UFC4(int, irq
->is_Code
,
1562 AROS_UFCA(struct Custom
*, custom
, A0
),
1563 AROS_UFCA(APTR
, irq
->is_Data
, A1
),
1564 AROS_UFCA(APTR
, irq
->is_Code
, A5
),
1565 AROS_UFCA(struct ExecBase
*, SysBase
, A6
)