Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 3386 → Rev 4153

/branches/network/kernel/arch/ia32/src/ia32.c
1,5 → 1,7
/*
* Copyright (c) 2001-2004 Jakub Jermar
* Copyright (c) 2009 Jiri Svoboda
* Copyright (c) 2009 Martin Decky
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
38,9 → 40,12
 
#include <arch/pm.h>
 
#include <arch/drivers/ega.h>
#include <genarch/multiboot/multiboot.h>
#include <genarch/drivers/legacy/ia32/io.h>
#include <genarch/drivers/ega/ega.h>
#include <arch/drivers/vesa.h>
#include <genarch/kbd/i8042.h>
#include <genarch/drivers/i8042/i8042.h>
#include <genarch/kbrd/kbrd.h>
#include <arch/drivers/i8254.h>
#include <arch/drivers/i8259.h>
 
60,12 → 65,30
#include <proc/thread.h>
#include <syscall/syscall.h>
#include <console/console.h>
#include <ddi/device.h>
#include <sysinfo/sysinfo.h>
#include <arch/boot/boot.h>
 
#ifdef CONFIG_SMP
#include <arch/smp/apic.h>
#endif
 
/** Perform ia32-specific initialization before main_bsp() is called.
*
* @param signature Should contain the multiboot signature.
* @param mi Pointer to the multiboot information structure.
*/
void arch_pre_main(uint32_t signature, const multiboot_info_t *mi)
{
/* Parse multiboot information obtained from the bootloader. */
multiboot_info_parse(signature, mi);
#ifdef CONFIG_SMP
/* Copy AP bootstrap routines below 1 MB. */
memcpy((void *) AP_BOOT_OFFSET, (void *) BOOT_OFFSET,
(size_t) &_hardcoded_unmapped_size);
#endif
}
 
void arch_pre_mm_init(void)
{
pm_init();
87,13 → 110,17
/* hard clock */
i8254_init();
 
#ifdef CONFIG_FB
if (vesa_present())
if (vesa_present())
vesa_init();
else
#endif
ega_init(); /* video */
#ifdef CONFIG_EGA
ega_init(EGA_BASE, EGA_VIDEORAM); /* video */
#else
{}
#endif
/* Enable debugger */
debugger_init();
123,10 → 150,28
 
void arch_post_smp_init(void)
{
devno_t kbd = device_assign_devno();
devno_t mouse = device_assign_devno();
/* keyboard controller */
i8042_init(kbd, IRQ_KBD, mouse, IRQ_MOUSE);
#ifdef CONFIG_PC_KBD
/*
* Initialize the i8042 controller. Then initialize the keyboard
* module and connect it to i8042. Enable keyboard interrupts.
*/
indev_t *kbrdin = i8042_init((i8042_t *) I8042_BASE, IRQ_KBD);
if (kbrdin) {
kbrd_init(kbrdin);
trap_virtual_enable_irqs(1 << IRQ_KBD);
}
/*
* This is the necessary evil until the userspace driver is entirely
* self-sufficient.
*/
sysinfo_set_item_val("kbd", NULL, true);
sysinfo_set_item_val("kbd.inr", NULL, IRQ_KBD);
sysinfo_set_item_val("kbd.address.physical", NULL,
(uintptr_t) I8042_BASE);
sysinfo_set_item_val("kbd.address.kernel", NULL,
(uintptr_t) I8042_BASE);
#endif
}
 
void calibrate_delay_loop(void)
159,15 → 204,38
*/
void arch_grab_console(void)
{
i8042_grab();
#ifdef CONFIG_FB
if (vesa_present())
vesa_redraw();
else
#endif
#ifdef CONFIG_EGA
ega_redraw();
#else
{}
#endif
}
 
/** Return console to userspace
*
*/
void arch_release_console(void)
{
i8042_release();
}
 
/** Construct function pointer
*
* @param fptr function pointer structure
* @param addr function address
* @param caller calling function address
*
* @return address of the function pointer
*
*/
void *arch_construct_function(fncptr_t *fptr, void *addr, void *caller)
{
return addr;
}
 
/** @}
*/
/branches/network/kernel/arch/ia32/src/fpu_context.c
44,46 → 44,43
static void fpu_context_f_save(fpu_context_t *fctx)
{
asm volatile (
"fnsave %0"
: "=m"(*fctx)
);
"fnsave %[fctx]"
: [fctx] "=m" (*fctx)
);
}
 
static void fpu_context_f_restore(fpu_context_t *fctx)
{
asm volatile (
"frstor %0"
: "=m"(*fctx)
);
"frstor %[fctx]"
: [fctx] "=m" (*fctx)
);
}
 
static void fpu_context_fx_save(fpu_context_t *fctx)
{
asm volatile (
"fxsave %0"
: "=m"(*fctx)
);
"fxsave %[fctx]"
: [fctx] "=m" (*fctx)
);
}
 
static void fpu_context_fx_restore(fpu_context_t *fctx)
{
asm volatile (
"fxrstor %0"
: "=m"(*fctx)
);
"fxrstor %[fctx]"
: [fctx] "=m" (*fctx)
);
}
 
/*
Setup using fxsr instruction
*/
/* Setup using fxsr instruction */
void fpu_fxsr(void)
{
fpu_save=fpu_context_fx_save;
fpu_restore=fpu_context_fx_restore;
}
/*
Setup using not fxsr instruction
*/
 
/* Setup using not fxsr instruction */
void fpu_fsr(void)
{
fpu_save = fpu_context_f_save;
102,16 → 99,18
 
void fpu_init()
{
uint32_t help0 = 0, help1 = 0;
uint32_t help0 = 0;
uint32_t help1 = 0;
asm volatile (
"fninit;\n"
"stmxcsr %0\n"
"mov %0,%1;\n"
"or %2,%1;\n"
"mov %1,%0;\n"
"ldmxcsr %0;\n"
: "+m" (help0), "+r" (help1)
: "i" (0x1f80)
"fninit\n"
"stmxcsr %[help0]\n"
"mov %[help0], %[help1]\n"
"or %[magic], %[help1]\n"
"mov %[help1], %[help0]\n"
"ldmxcsr %[help0]\n"
: [help0] "+m" (help0), [help1] "+r" (help1)
: [magic] "i" (0x1f80)
);
}
 
/branches/network/kernel/arch/ia32/src/asm.S
147,6 → 147,46
popfl
.endm
 
/*
* The SYSENTER syscall mechanism can be used for syscalls with
* four or fewer arguments. To pass these four arguments, we
* use four registers: EDX, ECX, EBX, ESI. The syscall number
* is passed in EAX. We use EDI to remember the return address
* and EBP to remember the stack. The INT-based syscall mechanism
* can actually handle six arguments plus the syscall number
* entirely in registers.
*/
.global sysenter_handler
sysenter_handler:
sti
pushl %ebp # remember user stack
pushl %edi # remember return user address
 
pushl %gs # remember TLS
 
pushl %eax # syscall number
subl $8, %esp # unused sixth and fifth argument
pushl %esi # fourth argument
pushl %ebx # third argument
pushl %ecx # second argument
pushl %edx # first argument
 
movw $16, %ax
movw %ax, %ds
movw %ax, %es
 
cld
call syscall_handler
addl $28, %esp # remove arguments from stack
 
pop %gs # restore TLS
 
pop %edx # prepare return EIP for SYSEXIT
pop %ecx # prepare userspace ESP for SYSEXIT
 
sysexit # return to userspace
 
 
## Declare interrupt handlers
#
# Declare interrupt handlers for n interrupt
228,14 → 268,6
pushl %fs
pushl %gs
 
#ifdef CONFIG_DEBUG_ALLREGS
pushl %ebx
pushl %ebp
pushl %edi
pushl %esi
#else
subl $16, %esp
#endif
pushl %edx
pushl %ecx
pushl %eax
257,14 → 289,6
popl %eax
popl %ecx
popl %edx
#ifdef CONFIG_DEBUG_ALLREGS
popl %esi
popl %edi
popl %ebp
popl %ebx
#else
addl $16, %esp
#endif
popl %gs
popl %fs
/branches/network/kernel/arch/ia32/src/cpu/cpu.c
42,22 → 42,23
#include <fpu_context.h>
 
#include <arch/smp/apic.h>
#include <arch/syscall.h>
 
/*
* Identification of CPUs.
* Contains only non-MP-Specification specific SMP code.
*/
#define AMD_CPUID_EBX 0x68747541
#define AMD_CPUID_ECX 0x444d4163
#define AMD_CPUID_EDX 0x69746e65
#define AMD_CPUID_EBX 0x68747541
#define AMD_CPUID_ECX 0x444d4163
#define AMD_CPUID_EDX 0x69746e65
 
#define INTEL_CPUID_EBX 0x756e6547
#define INTEL_CPUID_ECX 0x6c65746e
#define INTEL_CPUID_EDX 0x49656e69
#define INTEL_CPUID_EBX 0x756e6547
#define INTEL_CPUID_ECX 0x6c65746e
#define INTEL_CPUID_EDX 0x49656e69
 
 
enum vendor {
VendorUnknown=0,
VendorUnknown = 0,
VendorAMD,
VendorIntel
};
64,19 → 65,17
 
static char *vendor_str[] = {
"Unknown Vendor",
"AuthenticAMD",
"GenuineIntel"
"AMD",
"Intel"
};
 
void fpu_disable(void)
{
asm volatile (
"mov %%cr0,%%eax;"
"or $8,%%eax;"
"mov %%eax,%%cr0;"
:
:
:"%eax"
"mov %%cr0, %%eax\n"
"or $8, %%eax\n"
"mov %%eax, %%cr0\n"
::: "%eax"
);
}
 
83,13 → 82,11
void fpu_enable(void)
{
asm volatile (
"mov %%cr0,%%eax;"
"and $0xffFFffF7,%%eax;"
"mov %%eax,%%cr0;"
:
:
:"%eax"
);
"mov %%cr0, %%eax\n"
"and $0xffFFffF7, %%eax\n"
"mov %%eax,%%cr0\n"
::: "%eax"
);
}
 
void cpu_arch_init(void)
101,11 → 98,11
CPU->arch.tss = tss_p;
CPU->arch.tss->iomap_base = &CPU->arch.tss->iomap[0] - ((uint8_t *) CPU->arch.tss);
 
CPU->fpu_owner = NULL;
 
cpuid(1, &info);
 
fi.word = info.cpuid_edx;
efi.word = info.cpuid_ecx;
112,17 → 109,20
if (fi.bits.fxsr)
fpu_fxsr();
else
fpu_fsr();
fpu_fsr();
if (fi.bits.sse) {
asm volatile (
"mov %%cr4,%0\n"
"or %1,%0\n"
"mov %0,%%cr4\n"
: "+r" (help)
: "i" (CR4_OSFXSR_MASK|(1<<10))
"mov %%cr4, %[help]\n"
"or %[mask], %[help]\n"
"mov %[help], %%cr4\n"
: [help] "+r" (help)
: [mask] "i" (CR4_OSFXSR_MASK | (1 << 10))
);
}
/* Setup fast SYSENTER/SYSEXIT syscalls */
syscall_setup_cpu();
}
 
void cpu_identify(void)
136,29 → 136,31
/*
* Check for AMD processor.
*/
if (info.cpuid_ebx==AMD_CPUID_EBX && info.cpuid_ecx==AMD_CPUID_ECX && info.cpuid_edx==AMD_CPUID_EDX) {
if ((info.cpuid_ebx == AMD_CPUID_EBX)
&& (info.cpuid_ecx == AMD_CPUID_ECX)
&& (info.cpuid_edx == AMD_CPUID_EDX))
CPU->arch.vendor = VendorAMD;
}
 
/*
* Check for Intel processor.
*/
if (info.cpuid_ebx==INTEL_CPUID_EBX && info.cpuid_ecx==INTEL_CPUID_ECX && info.cpuid_edx==INTEL_CPUID_EDX) {
if ((info.cpuid_ebx == INTEL_CPUID_EBX)
&& (info.cpuid_ecx == INTEL_CPUID_ECX)
&& (info.cpuid_edx == INTEL_CPUID_EDX))
CPU->arch.vendor = VendorIntel;
}
cpuid(1, &info);
CPU->arch.family = (info.cpuid_eax>>8)&0xf;
CPU->arch.model = (info.cpuid_eax>>4)&0xf;
CPU->arch.stepping = (info.cpuid_eax>>0)&0xf;
CPU->arch.family = (info.cpuid_eax >> 8) & 0x0f;
CPU->arch.model = (info.cpuid_eax >> 4) & 0x0f;
CPU->arch.stepping = (info.cpuid_eax >> 0) & 0x0f;
}
}
 
void cpu_print_report(cpu_t* m)
void cpu_print_report(cpu_t* cpu)
{
printf("cpu%d: (%s family=%d model=%d stepping=%d) %dMHz\n",
m->id, vendor_str[m->arch.vendor], m->arch.family, m->arch.model, m->arch.stepping,
m->frequency_mhz);
printf("cpu%u: (%s family=%u model=%u stepping=%u) %" PRIu16 " MHz\n",
cpu->id, vendor_str[cpu->arch.vendor], cpu->arch.family,
cpu->arch.model, cpu->arch.stepping, cpu->frequency_mhz);
}
 
/** @}
/branches/network/kernel/arch/ia32/src/syscall.c
0,0 → 1,53
/*
* Copyright (c) 2008 Jakub Jermar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
* @{
*/
/** @file
*/
 
#include <arch/syscall.h>
#include <arch/cpu.h>
#include <arch/asm.h>
#include <arch/types.h>
#include <arch/pm.h>
 
/** Enable & setup support for SYSENTER/SYSEXIT */
void syscall_setup_cpu(void)
{
extern void sysenter_handler(void);
 
/* set kernel mode CS selector */
write_msr(IA32_MSR_SYSENTER_CS, gdtselector(KTEXT_DES));
/* set kernel mode entry point */
write_msr(IA32_MSR_SYSENTER_EIP, (uint32_t) sysenter_handler);
}
 
/** @}
*/
/branches/network/kernel/arch/ia32/src/pm.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
112,7 → 112,7
 
void tss_initialize(tss_t *t)
{
memsetb(t, sizeof(struct tss), 0);
memsetb(t, sizeof(tss_t), 0);
}
 
/*
127,7 → 127,7
d = &idt[i];
 
d->unused = 0;
d->selector = selector(KTEXT_DES);
d->selector = gdtselector(KTEXT_DES);
 
d->access = AR_PRESENT | AR_INTERRUPT; /* masking interrupt */
 
154,7 → 154,7
"and $0xffff8fff, %%eax\n"
"push %%eax\n"
"popfl\n"
: : : "eax"
::: "eax"
);
}
 
165,7 → 165,7
"mov %%cr0, %%eax\n"
"and $0xfffbffff, %%eax\n"
"mov %%eax, %%cr0\n"
: : : "eax"
::: "eax"
);
}
 
198,7 → 198,7
else {
tss_p = (tss_t *) malloc(sizeof(tss_t), FRAME_ATOMIC);
if (!tss_p)
panic("could not allocate TSS\n");
panic("Cannot allocate TSS.");
}
 
tss_initialize(tss_p);
214,7 → 214,7
* As of this moment, the current CPU has its own GDT pointing
* to its own TSS. We just need to load the TR register.
*/
tr_load(selector(TSS_DES));
tr_load(gdtselector(TSS_DES));
clean_IOPL_NT_flags(); /* Disable I/O on nonprivileged levels and clear NT flag. */
clean_AM_flag(); /* Disable alignment check */
/branches/network/kernel/arch/ia32/src/smp/smp.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
75,12 → 75,12
l_apic_address = (uintptr_t) frame_alloc(ONE_FRAME,
FRAME_ATOMIC | FRAME_KA);
if (!l_apic_address)
panic("cannot allocate address for l_apic\n");
panic("Cannot allocate address for l_apic.");
 
io_apic_address = (uintptr_t) frame_alloc(ONE_FRAME,
FRAME_ATOMIC | FRAME_KA);
if (!io_apic_address)
panic("cannot allocate address for io_apic\n");
panic("Cannot allocate address for io_apic.");
 
if (config.cpu_count > 1) {
page_mapping_insert(AS_KERNEL, l_apic_address,
122,8 → 122,8
* Save 0xa to address 0xf of the CMOS RAM.
* BIOS will not do the POST after the INIT signal.
*/
outb(0x70, 0xf);
outb(0x71, 0xa);
pio_write_8((ioport8_t *)0x70, 0xf);
pio_write_8((ioport8_t *)0x71, 0xa);
 
pic_disable_irqs(0xffff);
apic_init();
131,8 → 131,8
uint8_t apic = l_apic_id();
 
for (i = 0; i < ops->cpu_count(); i++) {
struct descriptor *gdt_new;
descriptor_t *gdt_new;
/*
* Skip processors marked unusable.
*/
154,14 → 154,19
/*
* Prepare new GDT for CPU in question.
*/
gdt_new = (struct descriptor *) malloc(GDT_ITEMS *
sizeof(struct descriptor), FRAME_ATOMIC | FRAME_LOW_4_GiB);
/* XXX Flag FRAME_LOW_4_GiB was removed temporarily,
* it needs to be replaced by a generic fuctionality of
* the memory subsystem
*/
gdt_new = (descriptor_t *) malloc(GDT_ITEMS *
sizeof(descriptor_t), FRAME_ATOMIC);
if (!gdt_new)
panic("couldn't allocate memory for GDT\n");
panic("Cannot allocate memory for GDT.");
 
memcpy(gdt_new, gdt, GDT_ITEMS * sizeof(struct descriptor));
memsetb(&gdt_new[TSS_DES], sizeof(struct descriptor), 0);
protected_ap_gdtr.limit = GDT_ITEMS * sizeof(struct descriptor);
memcpy(gdt_new, gdt, GDT_ITEMS * sizeof(descriptor_t));
memsetb(&gdt_new[TSS_DES], sizeof(descriptor_t), 0);
protected_ap_gdtr.limit = GDT_ITEMS * sizeof(descriptor_t);
protected_ap_gdtr.base = KA2PA((uintptr_t) gdt_new);
gdtr.base = (uintptr_t) gdt_new;
 
/branches/network/kernel/arch/ia32/src/smp/apic.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
132,12 → 132,12
#endif
}
 
static irq_ownership_t l_apic_timer_claim(void)
static irq_ownership_t l_apic_timer_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
static void l_apic_timer_irq_handler(irq_t *irq, void *arg __attribute__((unused)), ...)
static void l_apic_timer_irq_handler(irq_t *irq)
{
/*
* Holding a spinlock could prevent clock() from preempting
/branches/network/kernel/arch/ia32/src/ddi/ddi.c
156,7 → 156,7
* type must be changed to describe inactive TSS.
*/
gdt_p[TSS_DES].access = AR_PRESENT | AR_TSS | DPL_KERNEL;
tr_load(selector(TSS_DES));
tr_load(gdtselector(TSS_DES));
/*
* Update the generation count so that faults caused by
/branches/network/kernel/arch/ia32/src/boot/vga323.pal
1,256 → 1,256
.byte 0x3f, 0x3f, 0x3f, 0x00
.byte 0x36, 0x3f, 0x3f, 0x00
.byte 0x2d, 0x3f, 0x3f, 0x00
.byte 0x24, 0x3f, 0x3f, 0x00
.byte 0x1b, 0x3f, 0x3f, 0x00
.byte 0x12, 0x3f, 0x3f, 0x00
.byte 0x09, 0x3f, 0x3f, 0x00
.byte 0x00, 0x3f, 0x3f, 0x00
.byte 0x3f, 0x2a, 0x3f, 0x00
.byte 0x36, 0x2a, 0x3f, 0x00
.byte 0x2d, 0x2a, 0x3f, 0x00
.byte 0x24, 0x2a, 0x3f, 0x00
.byte 0x1b, 0x2a, 0x3f, 0x00
.byte 0x12, 0x2a, 0x3f, 0x00
.byte 0x09, 0x2a, 0x3f, 0x00
.byte 0x00, 0x2a, 0x3f, 0x00
.byte 0x3f, 0x15, 0x3f, 0x00
.byte 0x36, 0x15, 0x3f, 0x00
.byte 0x2d, 0x15, 0x3f, 0x00
.byte 0x24, 0x15, 0x3f, 0x00
.byte 0x1b, 0x15, 0x3f, 0x00
.byte 0x12, 0x15, 0x3f, 0x00
.byte 0x09, 0x15, 0x3f, 0x00
.byte 0x00, 0x15, 0x3f, 0x00
.byte 0x3f, 0x00, 0x3f, 0x00
.byte 0x36, 0x00, 0x3f, 0x00
.byte 0x2d, 0x00, 0x3f, 0x00
.byte 0x24, 0x00, 0x3f, 0x00
.byte 0x1b, 0x00, 0x3f, 0x00
.byte 0x12, 0x00, 0x3f, 0x00
.byte 0x09, 0x00, 0x3f, 0x00
.byte 0x00, 0x00, 0x3f, 0x00
.byte 0x3f, 0x3f, 0x36, 0x00
.byte 0x36, 0x3f, 0x36, 0x00
.byte 0x2d, 0x3f, 0x36, 0x00
.byte 0x24, 0x3f, 0x36, 0x00
.byte 0x1b, 0x3f, 0x36, 0x00
.byte 0x12, 0x3f, 0x36, 0x00
.byte 0x09, 0x3f, 0x36, 0x00
.byte 0x00, 0x3f, 0x36, 0x00
.byte 0x3f, 0x2a, 0x36, 0x00
.byte 0x36, 0x2a, 0x36, 0x00
.byte 0x2d, 0x2a, 0x36, 0x00
.byte 0x24, 0x2a, 0x36, 0x00
.byte 0x1b, 0x2a, 0x36, 0x00
.byte 0x12, 0x2a, 0x36, 0x00
.byte 0x09, 0x2a, 0x36, 0x00
.byte 0x00, 0x2a, 0x36, 0x00
.byte 0x3f, 0x15, 0x36, 0x00
.byte 0x36, 0x15, 0x36, 0x00
.byte 0x2d, 0x15, 0x36, 0x00
.byte 0x24, 0x15, 0x36, 0x00
.byte 0x1b, 0x15, 0x36, 0x00
.byte 0x12, 0x15, 0x36, 0x00
.byte 0x09, 0x15, 0x36, 0x00
.byte 0x00, 0x15, 0x36, 0x00
.byte 0x3f, 0x00, 0x36, 0x00
.byte 0x36, 0x00, 0x36, 0x00
.byte 0x2d, 0x00, 0x36, 0x00
.byte 0x24, 0x00, 0x36, 0x00
.byte 0x1b, 0x00, 0x36, 0x00
.byte 0x12, 0x00, 0x36, 0x00
.byte 0x09, 0x00, 0x36, 0x00
.byte 0x00, 0x00, 0x36, 0x00
.byte 0x3f, 0x3f, 0x2d, 0x00
.byte 0x36, 0x3f, 0x2d, 0x00
.byte 0x2d, 0x3f, 0x2d, 0x00
.byte 0x24, 0x3f, 0x2d, 0x00
.byte 0x1b, 0x3f, 0x2d, 0x00
.byte 0x12, 0x3f, 0x2d, 0x00
.byte 0x09, 0x3f, 0x2d, 0x00
.byte 0x00, 0x3f, 0x2d, 0x00
.byte 0x3f, 0x2a, 0x2d, 0x00
.byte 0x36, 0x2a, 0x2d, 0x00
.byte 0x2d, 0x2a, 0x2d, 0x00
.byte 0x24, 0x2a, 0x2d, 0x00
.byte 0x1b, 0x2a, 0x2d, 0x00
.byte 0x12, 0x2a, 0x2d, 0x00
.byte 0x09, 0x2a, 0x2d, 0x00
.byte 0x00, 0x2a, 0x2d, 0x00
.byte 0x3f, 0x15, 0x2d, 0x00
.byte 0x36, 0x15, 0x2d, 0x00
.byte 0x2d, 0x15, 0x2d, 0x00
.byte 0x24, 0x15, 0x2d, 0x00
.byte 0x1b, 0x15, 0x2d, 0x00
.byte 0x12, 0x15, 0x2d, 0x00
.byte 0x09, 0x15, 0x2d, 0x00
.byte 0x00, 0x15, 0x2d, 0x00
.byte 0x3f, 0x00, 0x2d, 0x00
.byte 0x36, 0x00, 0x2d, 0x00
.byte 0x2d, 0x00, 0x2d, 0x00
.byte 0x24, 0x00, 0x2d, 0x00
.byte 0x1b, 0x00, 0x2d, 0x00
.byte 0x12, 0x00, 0x2d, 0x00
.byte 0x09, 0x00, 0x2d, 0x00
.byte 0x00, 0x00, 0x2d, 0x00
.byte 0x3f, 0x3f, 0x24, 0x00
.byte 0x36, 0x3f, 0x24, 0x00
.byte 0x2d, 0x3f, 0x24, 0x00
.byte 0x24, 0x3f, 0x24, 0x00
.byte 0x1b, 0x3f, 0x24, 0x00
.byte 0x12, 0x3f, 0x24, 0x00
.byte 0x09, 0x3f, 0x24, 0x00
.byte 0x00, 0x3f, 0x24, 0x00
.byte 0x3f, 0x2a, 0x24, 0x00
.byte 0x36, 0x2a, 0x24, 0x00
.byte 0x2d, 0x2a, 0x24, 0x00
.byte 0x24, 0x2a, 0x24, 0x00
.byte 0x1b, 0x2a, 0x24, 0x00
.byte 0x12, 0x2a, 0x24, 0x00
.byte 0x09, 0x2a, 0x24, 0x00
.byte 0x00, 0x2a, 0x24, 0x00
.byte 0x3f, 0x15, 0x24, 0x00
.byte 0x36, 0x15, 0x24, 0x00
.byte 0x2d, 0x15, 0x24, 0x00
.byte 0x24, 0x15, 0x24, 0x00
.byte 0x1b, 0x15, 0x24, 0x00
.byte 0x12, 0x15, 0x24, 0x00
.byte 0x09, 0x15, 0x24, 0x00
.byte 0x00, 0x15, 0x24, 0x00
.byte 0x3f, 0x00, 0x24, 0x00
.byte 0x36, 0x00, 0x24, 0x00
.byte 0x2d, 0x00, 0x24, 0x00
.byte 0x24, 0x00, 0x24, 0x00
.byte 0x1b, 0x00, 0x24, 0x00
.byte 0x12, 0x00, 0x24, 0x00
.byte 0x09, 0x00, 0x24, 0x00
.byte 0x00, 0x00, 0x24, 0x00
.byte 0x3f, 0x3f, 0x1b, 0x00
.byte 0x36, 0x3f, 0x1b, 0x00
.byte 0x2d, 0x3f, 0x1b, 0x00
.byte 0x24, 0x3f, 0x1b, 0x00
.byte 0x1b, 0x3f, 0x1b, 0x00
.byte 0x12, 0x3f, 0x1b, 0x00
.byte 0x09, 0x3f, 0x1b, 0x00
.byte 0x00, 0x3f, 0x1b, 0x00
.byte 0x3f, 0x2a, 0x1b, 0x00
.byte 0x36, 0x2a, 0x1b, 0x00
.byte 0x2d, 0x2a, 0x1b, 0x00
.byte 0x24, 0x2a, 0x1b, 0x00
.byte 0x1b, 0x2a, 0x1b, 0x00
.byte 0x12, 0x2a, 0x1b, 0x00
.byte 0x09, 0x2a, 0x1b, 0x00
.byte 0x00, 0x2a, 0x1b, 0x00
.byte 0x3f, 0x15, 0x1b, 0x00
.byte 0x36, 0x15, 0x1b, 0x00
.byte 0x2d, 0x15, 0x1b, 0x00
.byte 0x24, 0x15, 0x1b, 0x00
.byte 0x1b, 0x15, 0x1b, 0x00
.byte 0x12, 0x15, 0x1b, 0x00
.byte 0x09, 0x15, 0x1b, 0x00
.byte 0x00, 0x15, 0x1b, 0x00
.byte 0x3f, 0x00, 0x1b, 0x00
.byte 0x36, 0x00, 0x1b, 0x00
.byte 0x2d, 0x00, 0x1b, 0x00
.byte 0x24, 0x00, 0x1b, 0x00
.byte 0x1b, 0x00, 0x1b, 0x00
.byte 0x12, 0x00, 0x1b, 0x00
.byte 0x09, 0x00, 0x1b, 0x00
.byte 0x00, 0x00, 0x1b, 0x00
.byte 0x3f, 0x3f, 0x12, 0x00
.byte 0x36, 0x3f, 0x12, 0x00
.byte 0x2d, 0x3f, 0x12, 0x00
.byte 0x24, 0x3f, 0x12, 0x00
.byte 0x1b, 0x3f, 0x12, 0x00
.byte 0x12, 0x3f, 0x12, 0x00
.byte 0x09, 0x3f, 0x12, 0x00
.byte 0x00, 0x3f, 0x12, 0x00
.byte 0x3f, 0x2a, 0x12, 0x00
.byte 0x36, 0x2a, 0x12, 0x00
.byte 0x2d, 0x2a, 0x12, 0x00
.byte 0x24, 0x2a, 0x12, 0x00
.byte 0x1b, 0x2a, 0x12, 0x00
.byte 0x12, 0x2a, 0x12, 0x00
.byte 0x09, 0x2a, 0x12, 0x00
.byte 0x00, 0x2a, 0x12, 0x00
.byte 0x3f, 0x15, 0x12, 0x00
.byte 0x36, 0x15, 0x12, 0x00
.byte 0x2d, 0x15, 0x12, 0x00
.byte 0x24, 0x15, 0x12, 0x00
.byte 0x1b, 0x15, 0x12, 0x00
.byte 0x12, 0x15, 0x12, 0x00
.byte 0x09, 0x15, 0x12, 0x00
.byte 0x00, 0x15, 0x12, 0x00
.byte 0x3f, 0x00, 0x12, 0x00
.byte 0x36, 0x00, 0x12, 0x00
.byte 0x2d, 0x00, 0x12, 0x00
.byte 0x24, 0x00, 0x12, 0x00
.byte 0x1b, 0x00, 0x12, 0x00
.byte 0x12, 0x00, 0x12, 0x00
.byte 0x09, 0x00, 0x12, 0x00
.byte 0x00, 0x00, 0x12, 0x00
.byte 0x3f, 0x3f, 0x09, 0x00
.byte 0x36, 0x3f, 0x09, 0x00
.byte 0x2d, 0x3f, 0x09, 0x00
.byte 0x24, 0x3f, 0x09, 0x00
.byte 0x1b, 0x3f, 0x09, 0x00
.byte 0x12, 0x3f, 0x09, 0x00
.byte 0x09, 0x3f, 0x09, 0x00
.byte 0x00, 0x3f, 0x09, 0x00
.byte 0x3f, 0x2a, 0x09, 0x00
.byte 0x36, 0x2a, 0x09, 0x00
.byte 0x2d, 0x2a, 0x09, 0x00
.byte 0x24, 0x2a, 0x09, 0x00
.byte 0x1b, 0x2a, 0x09, 0x00
.byte 0x12, 0x2a, 0x09, 0x00
.byte 0x09, 0x2a, 0x09, 0x00
.byte 0x00, 0x2a, 0x09, 0x00
.byte 0x3f, 0x15, 0x09, 0x00
.byte 0x36, 0x15, 0x09, 0x00
.byte 0x2d, 0x15, 0x09, 0x00
.byte 0x24, 0x15, 0x09, 0x00
.byte 0x1b, 0x15, 0x09, 0x00
.byte 0x12, 0x15, 0x09, 0x00
.byte 0x09, 0x15, 0x09, 0x00
.byte 0x00, 0x15, 0x09, 0x00
.byte 0x3f, 0x00, 0x09, 0x00
.byte 0x36, 0x00, 0x09, 0x00
.byte 0x2d, 0x00, 0x09, 0x00
.byte 0x24, 0x00, 0x09, 0x00
.byte 0x1b, 0x00, 0x09, 0x00
.byte 0x12, 0x00, 0x09, 0x00
.byte 0x09, 0x00, 0x09, 0x00
.byte 0x00, 0x00, 0x09, 0x00
.byte 0x3f, 0x3f, 0x00, 0x00
.byte 0x36, 0x3f, 0x00, 0x00
.byte 0x2d, 0x3f, 0x00, 0x00
.byte 0x24, 0x3f, 0x00, 0x00
.byte 0x1b, 0x3f, 0x00, 0x00
.byte 0x12, 0x3f, 0x00, 0x00
.byte 0x09, 0x3f, 0x00, 0x00
.byte 0x00, 0x3f, 0x00, 0x00
.byte 0x3f, 0x2a, 0x00, 0x00
.byte 0x36, 0x2a, 0x00, 0x00
.byte 0x2d, 0x2a, 0x00, 0x00
.byte 0x24, 0x2a, 0x00, 0x00
.byte 0x1b, 0x2a, 0x00, 0x00
.byte 0x12, 0x2a, 0x00, 0x00
.byte 0x09, 0x2a, 0x00, 0x00
.byte 0x00, 0x2a, 0x00, 0x00
.byte 0x3f, 0x15, 0x00, 0x00
.byte 0x36, 0x15, 0x00, 0x00
.byte 0x2d, 0x15, 0x00, 0x00
.byte 0x24, 0x15, 0x00, 0x00
.byte 0x1b, 0x15, 0x00, 0x00
.byte 0x12, 0x15, 0x00, 0x00
.byte 0x09, 0x15, 0x00, 0x00
.byte 0x00, 0x15, 0x00, 0x00
.byte 0x3f, 0x00, 0x00, 0x00
.byte 0x36, 0x00, 0x00, 0x00
.byte 0x2d, 0x00, 0x00, 0x00
.byte 0x24, 0x00, 0x00, 0x00
.byte 0x1b, 0x00, 0x00, 0x00
.byte 0x12, 0x00, 0x00, 0x00
.byte 0x09, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00
.byte 0x09, 0x00, 0x00, 0x00
.byte 0x12, 0x00, 0x00, 0x00
.byte 0x1b, 0x00, 0x00, 0x00
.byte 0x24, 0x00, 0x00, 0x00
.byte 0x2d, 0x00, 0x00, 0x00
.byte 0x36, 0x00, 0x00, 0x00
.byte 0x3f, 0x00, 0x00, 0x00
.byte 0x00, 0x15, 0x00, 0x00
.byte 0x09, 0x15, 0x00, 0x00
.byte 0x12, 0x15, 0x00, 0x00
.byte 0x1b, 0x15, 0x00, 0x00
.byte 0x24, 0x15, 0x00, 0x00
.byte 0x2d, 0x15, 0x00, 0x00
.byte 0x36, 0x15, 0x00, 0x00
.byte 0x3f, 0x15, 0x00, 0x00
.byte 0x00, 0x2a, 0x00, 0x00
.byte 0x09, 0x2a, 0x00, 0x00
.byte 0x12, 0x2a, 0x00, 0x00
.byte 0x1b, 0x2a, 0x00, 0x00
.byte 0x24, 0x2a, 0x00, 0x00
.byte 0x2d, 0x2a, 0x00, 0x00
.byte 0x36, 0x2a, 0x00, 0x00
.byte 0x3f, 0x2a, 0x00, 0x00
.byte 0x00, 0x3f, 0x00, 0x00
.byte 0x09, 0x3f, 0x00, 0x00
.byte 0x12, 0x3f, 0x00, 0x00
.byte 0x1b, 0x3f, 0x00, 0x00
.byte 0x24, 0x3f, 0x00, 0x00
.byte 0x2d, 0x3f, 0x00, 0x00
.byte 0x36, 0x3f, 0x00, 0x00
.byte 0x3f, 0x3f, 0x00, 0x00
.byte 0x00, 0x00, 0x09, 0x00
.byte 0x09, 0x00, 0x09, 0x00
.byte 0x12, 0x00, 0x09, 0x00
.byte 0x1b, 0x00, 0x09, 0x00
.byte 0x24, 0x00, 0x09, 0x00
.byte 0x2d, 0x00, 0x09, 0x00
.byte 0x36, 0x00, 0x09, 0x00
.byte 0x3f, 0x00, 0x09, 0x00
.byte 0x00, 0x15, 0x09, 0x00
.byte 0x09, 0x15, 0x09, 0x00
.byte 0x12, 0x15, 0x09, 0x00
.byte 0x1b, 0x15, 0x09, 0x00
.byte 0x24, 0x15, 0x09, 0x00
.byte 0x2d, 0x15, 0x09, 0x00
.byte 0x36, 0x15, 0x09, 0x00
.byte 0x3f, 0x15, 0x09, 0x00
.byte 0x00, 0x2a, 0x09, 0x00
.byte 0x09, 0x2a, 0x09, 0x00
.byte 0x12, 0x2a, 0x09, 0x00
.byte 0x1b, 0x2a, 0x09, 0x00
.byte 0x24, 0x2a, 0x09, 0x00
.byte 0x2d, 0x2a, 0x09, 0x00
.byte 0x36, 0x2a, 0x09, 0x00
.byte 0x3f, 0x2a, 0x09, 0x00
.byte 0x00, 0x3f, 0x09, 0x00
.byte 0x09, 0x3f, 0x09, 0x00
.byte 0x12, 0x3f, 0x09, 0x00
.byte 0x1b, 0x3f, 0x09, 0x00
.byte 0x24, 0x3f, 0x09, 0x00
.byte 0x2d, 0x3f, 0x09, 0x00
.byte 0x36, 0x3f, 0x09, 0x00
.byte 0x3f, 0x3f, 0x09, 0x00
.byte 0x00, 0x00, 0x12, 0x00
.byte 0x09, 0x00, 0x12, 0x00
.byte 0x12, 0x00, 0x12, 0x00
.byte 0x1b, 0x00, 0x12, 0x00
.byte 0x24, 0x00, 0x12, 0x00
.byte 0x2d, 0x00, 0x12, 0x00
.byte 0x36, 0x00, 0x12, 0x00
.byte 0x3f, 0x00, 0x12, 0x00
.byte 0x00, 0x15, 0x12, 0x00
.byte 0x09, 0x15, 0x12, 0x00
.byte 0x12, 0x15, 0x12, 0x00
.byte 0x1b, 0x15, 0x12, 0x00
.byte 0x24, 0x15, 0x12, 0x00
.byte 0x2d, 0x15, 0x12, 0x00
.byte 0x36, 0x15, 0x12, 0x00
.byte 0x3f, 0x15, 0x12, 0x00
.byte 0x00, 0x2a, 0x12, 0x00
.byte 0x09, 0x2a, 0x12, 0x00
.byte 0x12, 0x2a, 0x12, 0x00
.byte 0x1b, 0x2a, 0x12, 0x00
.byte 0x24, 0x2a, 0x12, 0x00
.byte 0x2d, 0x2a, 0x12, 0x00
.byte 0x36, 0x2a, 0x12, 0x00
.byte 0x3f, 0x2a, 0x12, 0x00
.byte 0x00, 0x3f, 0x12, 0x00
.byte 0x09, 0x3f, 0x12, 0x00
.byte 0x12, 0x3f, 0x12, 0x00
.byte 0x1b, 0x3f, 0x12, 0x00
.byte 0x24, 0x3f, 0x12, 0x00
.byte 0x2d, 0x3f, 0x12, 0x00
.byte 0x36, 0x3f, 0x12, 0x00
.byte 0x3f, 0x3f, 0x12, 0x00
.byte 0x00, 0x00, 0x1b, 0x00
.byte 0x09, 0x00, 0x1b, 0x00
.byte 0x12, 0x00, 0x1b, 0x00
.byte 0x1b, 0x00, 0x1b, 0x00
.byte 0x24, 0x00, 0x1b, 0x00
.byte 0x2d, 0x00, 0x1b, 0x00
.byte 0x36, 0x00, 0x1b, 0x00
.byte 0x3f, 0x00, 0x1b, 0x00
.byte 0x00, 0x15, 0x1b, 0x00
.byte 0x09, 0x15, 0x1b, 0x00
.byte 0x12, 0x15, 0x1b, 0x00
.byte 0x1b, 0x15, 0x1b, 0x00
.byte 0x24, 0x15, 0x1b, 0x00
.byte 0x2d, 0x15, 0x1b, 0x00
.byte 0x36, 0x15, 0x1b, 0x00
.byte 0x3f, 0x15, 0x1b, 0x00
.byte 0x00, 0x2a, 0x1b, 0x00
.byte 0x09, 0x2a, 0x1b, 0x00
.byte 0x12, 0x2a, 0x1b, 0x00
.byte 0x1b, 0x2a, 0x1b, 0x00
.byte 0x24, 0x2a, 0x1b, 0x00
.byte 0x2d, 0x2a, 0x1b, 0x00
.byte 0x36, 0x2a, 0x1b, 0x00
.byte 0x3f, 0x2a, 0x1b, 0x00
.byte 0x00, 0x3f, 0x1b, 0x00
.byte 0x09, 0x3f, 0x1b, 0x00
.byte 0x12, 0x3f, 0x1b, 0x00
.byte 0x1b, 0x3f, 0x1b, 0x00
.byte 0x24, 0x3f, 0x1b, 0x00
.byte 0x2d, 0x3f, 0x1b, 0x00
.byte 0x36, 0x3f, 0x1b, 0x00
.byte 0x3f, 0x3f, 0x1b, 0x00
.byte 0x00, 0x00, 0x24, 0x00
.byte 0x09, 0x00, 0x24, 0x00
.byte 0x12, 0x00, 0x24, 0x00
.byte 0x1b, 0x00, 0x24, 0x00
.byte 0x24, 0x00, 0x24, 0x00
.byte 0x2d, 0x00, 0x24, 0x00
.byte 0x36, 0x00, 0x24, 0x00
.byte 0x3f, 0x00, 0x24, 0x00
.byte 0x00, 0x15, 0x24, 0x00
.byte 0x09, 0x15, 0x24, 0x00
.byte 0x12, 0x15, 0x24, 0x00
.byte 0x1b, 0x15, 0x24, 0x00
.byte 0x24, 0x15, 0x24, 0x00
.byte 0x2d, 0x15, 0x24, 0x00
.byte 0x36, 0x15, 0x24, 0x00
.byte 0x3f, 0x15, 0x24, 0x00
.byte 0x00, 0x2a, 0x24, 0x00
.byte 0x09, 0x2a, 0x24, 0x00
.byte 0x12, 0x2a, 0x24, 0x00
.byte 0x1b, 0x2a, 0x24, 0x00
.byte 0x24, 0x2a, 0x24, 0x00
.byte 0x2d, 0x2a, 0x24, 0x00
.byte 0x36, 0x2a, 0x24, 0x00
.byte 0x3f, 0x2a, 0x24, 0x00
.byte 0x00, 0x3f, 0x24, 0x00
.byte 0x09, 0x3f, 0x24, 0x00
.byte 0x12, 0x3f, 0x24, 0x00
.byte 0x1b, 0x3f, 0x24, 0x00
.byte 0x24, 0x3f, 0x24, 0x00
.byte 0x2d, 0x3f, 0x24, 0x00
.byte 0x36, 0x3f, 0x24, 0x00
.byte 0x3f, 0x3f, 0x24, 0x00
.byte 0x00, 0x00, 0x2d, 0x00
.byte 0x09, 0x00, 0x2d, 0x00
.byte 0x12, 0x00, 0x2d, 0x00
.byte 0x1b, 0x00, 0x2d, 0x00
.byte 0x24, 0x00, 0x2d, 0x00
.byte 0x2d, 0x00, 0x2d, 0x00
.byte 0x36, 0x00, 0x2d, 0x00
.byte 0x3f, 0x00, 0x2d, 0x00
.byte 0x00, 0x15, 0x2d, 0x00
.byte 0x09, 0x15, 0x2d, 0x00
.byte 0x12, 0x15, 0x2d, 0x00
.byte 0x1b, 0x15, 0x2d, 0x00
.byte 0x24, 0x15, 0x2d, 0x00
.byte 0x2d, 0x15, 0x2d, 0x00
.byte 0x36, 0x15, 0x2d, 0x00
.byte 0x3f, 0x15, 0x2d, 0x00
.byte 0x00, 0x2a, 0x2d, 0x00
.byte 0x09, 0x2a, 0x2d, 0x00
.byte 0x12, 0x2a, 0x2d, 0x00
.byte 0x1b, 0x2a, 0x2d, 0x00
.byte 0x24, 0x2a, 0x2d, 0x00
.byte 0x2d, 0x2a, 0x2d, 0x00
.byte 0x36, 0x2a, 0x2d, 0x00
.byte 0x3f, 0x2a, 0x2d, 0x00
.byte 0x00, 0x3f, 0x2d, 0x00
.byte 0x09, 0x3f, 0x2d, 0x00
.byte 0x12, 0x3f, 0x2d, 0x00
.byte 0x1b, 0x3f, 0x2d, 0x00
.byte 0x24, 0x3f, 0x2d, 0x00
.byte 0x2d, 0x3f, 0x2d, 0x00
.byte 0x36, 0x3f, 0x2d, 0x00
.byte 0x3f, 0x3f, 0x2d, 0x00
.byte 0x00, 0x00, 0x36, 0x00
.byte 0x09, 0x00, 0x36, 0x00
.byte 0x12, 0x00, 0x36, 0x00
.byte 0x1b, 0x00, 0x36, 0x00
.byte 0x24, 0x00, 0x36, 0x00
.byte 0x2d, 0x00, 0x36, 0x00
.byte 0x36, 0x00, 0x36, 0x00
.byte 0x3f, 0x00, 0x36, 0x00
.byte 0x00, 0x15, 0x36, 0x00
.byte 0x09, 0x15, 0x36, 0x00
.byte 0x12, 0x15, 0x36, 0x00
.byte 0x1b, 0x15, 0x36, 0x00
.byte 0x24, 0x15, 0x36, 0x00
.byte 0x2d, 0x15, 0x36, 0x00
.byte 0x36, 0x15, 0x36, 0x00
.byte 0x3f, 0x15, 0x36, 0x00
.byte 0x00, 0x2a, 0x36, 0x00
.byte 0x09, 0x2a, 0x36, 0x00
.byte 0x12, 0x2a, 0x36, 0x00
.byte 0x1b, 0x2a, 0x36, 0x00
.byte 0x24, 0x2a, 0x36, 0x00
.byte 0x2d, 0x2a, 0x36, 0x00
.byte 0x36, 0x2a, 0x36, 0x00
.byte 0x3f, 0x2a, 0x36, 0x00
.byte 0x00, 0x3f, 0x36, 0x00
.byte 0x09, 0x3f, 0x36, 0x00
.byte 0x12, 0x3f, 0x36, 0x00
.byte 0x1b, 0x3f, 0x36, 0x00
.byte 0x24, 0x3f, 0x36, 0x00
.byte 0x2d, 0x3f, 0x36, 0x00
.byte 0x36, 0x3f, 0x36, 0x00
.byte 0x3f, 0x3f, 0x36, 0x00
.byte 0x00, 0x00, 0x3f, 0x00
.byte 0x09, 0x00, 0x3f, 0x00
.byte 0x12, 0x00, 0x3f, 0x00
.byte 0x1b, 0x00, 0x3f, 0x00
.byte 0x24, 0x00, 0x3f, 0x00
.byte 0x2d, 0x00, 0x3f, 0x00
.byte 0x36, 0x00, 0x3f, 0x00
.byte 0x3f, 0x00, 0x3f, 0x00
.byte 0x00, 0x15, 0x3f, 0x00
.byte 0x09, 0x15, 0x3f, 0x00
.byte 0x12, 0x15, 0x3f, 0x00
.byte 0x1b, 0x15, 0x3f, 0x00
.byte 0x24, 0x15, 0x3f, 0x00
.byte 0x2d, 0x15, 0x3f, 0x00
.byte 0x36, 0x15, 0x3f, 0x00
.byte 0x3f, 0x15, 0x3f, 0x00
.byte 0x00, 0x2a, 0x3f, 0x00
.byte 0x09, 0x2a, 0x3f, 0x00
.byte 0x12, 0x2a, 0x3f, 0x00
.byte 0x1b, 0x2a, 0x3f, 0x00
.byte 0x24, 0x2a, 0x3f, 0x00
.byte 0x2d, 0x2a, 0x3f, 0x00
.byte 0x36, 0x2a, 0x3f, 0x00
.byte 0x3f, 0x2a, 0x3f, 0x00
.byte 0x00, 0x3f, 0x3f, 0x00
.byte 0x09, 0x3f, 0x3f, 0x00
.byte 0x12, 0x3f, 0x3f, 0x00
.byte 0x1b, 0x3f, 0x3f, 0x00
.byte 0x24, 0x3f, 0x3f, 0x00
.byte 0x2d, 0x3f, 0x3f, 0x00
.byte 0x36, 0x3f, 0x3f, 0x00
.byte 0x3f, 0x3f, 0x3f, 0x00
/branches/network/kernel/arch/ia32/src/boot/vesa_ret.inc
0,0 → 1,12
.code32
vesa_init_protected:
movw $gdtselector(KDATA_DES), %cx
movw %cx, %es
movw %cx, %fs
movw %cx, %gs
movw %cx, %ds # kernel data + stack
movw %cx, %ss
movl $START_STACK, %esp # initialize stack pointer
jmpl $gdtselector(KTEXT_DES), $vesa_meeting_point
/branches/network/kernel/arch/ia32/src/boot/boot.S
42,178 → 42,63
multiboot_header:
.long MULTIBOOT_HEADER_MAGIC
.long MULTIBOOT_HEADER_FLAGS
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum
.long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum
.long multiboot_header
.long unmapped_ktext_start
.long 0
.long 0
.long multiboot_image_start
 
multiboot_image_start:
cld
movl $START_STACK, %esp # initialize stack pointer
lgdt KA2PA(bootstrap_gdtr) # initialize Global Descriptor Table register
 
movw $selector(KDATA_DES), %cx
movl $START_STACK, %esp # initialize stack pointer
lgdt KA2PA(bootstrap_gdtr) # initialize Global Descriptor Table register
movw $gdtselector(KDATA_DES), %cx
movw %cx, %es
movw %cx, %fs
movw %cx, %gs
movw %cx, %ds # kernel data + stack
movw %cx, %ds # kernel data + stack
movw %cx, %ss
jmpl $selector(KTEXT_DES), $multiboot_meeting_point
jmpl $gdtselector(KTEXT_DES), $multiboot_meeting_point
multiboot_meeting_point:
movl %eax, grub_eax # save parameters from GRUB
movl %eax, grub_eax # save parameters from GRUB
movl %ebx, grub_ebx
xorl %eax, %eax
cpuid
cmp $0x0, %eax # any function > 0?
xorl %eax, %eax
cpuid
cmp $0x0, %eax # any function > 0?
jbe pse_unsupported
movl $0x1, %eax # Basic function code 1
movl $0x1, %eax # basic function code 1
cpuid
bt $3, %edx # Test if PSE is supported
bt $3, %edx # test if PSE is supported
jc pse_supported
 
pse_unsupported:
movl $pse_msg, %esi
jmp error_halt
pse_supported:
#ifdef CONFIG_FB
mov $vesa_init, %esi
mov $VESA_INIT_SEGMENT << 4, %edi
mov $e_vesa_init - vesa_init, %ecx
rep movsb
 
mov $VESA_INIT_SEGMENT << 4, %edi
jmpl *%edi
#include "vesa_prot.inc"
 
# map kernel and turn paging on
call map_kernel
vesa_meeting_point:
# call arch_pre_main(grub_eax, grub_ebx)
pushl grub_ebx
pushl grub_eax
call arch_pre_main
mov %esi, KA2PA(vesa_ph_addr)
mov %di, KA2PA(vesa_height)
shr $16, %edi
mov %di, KA2PA(vesa_width)
mov %bx, KA2PA(vesa_scanline)
shr $16, %ebx
mov %bx, KA2PA(vesa_bpp)
#endif
call main_bsp
call map_kernel # map kernel and turn paging on
movl grub_eax, %eax
movl grub_ebx, %ebx
cmpl $MULTIBOOT_LOADER_MAGIC, %eax # compare GRUB signature
je valid_boot
xorl %ecx, %ecx # no memory map available
movl %ecx, e820counter
jmp invalid_boot
valid_boot:
movl (%ebx), %eax # ebx = physical address of struct multiboot_info
bt $3, %eax # mbi->flags[3] (mods_count, mods_addr valid)
jc mods_valid
xorl %ecx, %ecx
movl %ecx, init
jmp mods_end
mods_valid:
movl 20(%ebx), %ecx # mbi->mods_count
movl %ecx, init
cmpl $0, %ecx
je mods_end
movl 24(%ebx), %esi # mbi->mods_addr
movl $init, %edi
mods_loop:
movl 0(%esi), %edx # mods->mod_start
addl $0x80000000, %edx
movl %edx, 4(%edi)
movl 4(%esi), %edx
subl 0(%esi), %edx # mods->mod_end - mods->mod_start
movl %edx, 8(%edi)
addl $16, %esi
addl $8 , %edi
loop mods_loop
mods_end:
bt $6, %eax # mbi->flags[6] (mmap_length, mmap_addr valid)
jc mmap_valid
xorl %edx, %edx
jmp mmap_invalid
mmap_valid:
movl 44(%ebx), %ecx # mbi->mmap_length
movl 48(%ebx), %esi # mbi->mmap_addr
movl $e820table, %edi
xorl %edx, %edx
mmap_loop:
cmpl $0, %ecx
jle mmap_end
movl 4(%esi), %eax # mmap->base_addr_low
movl %eax, (%edi)
movl 8(%esi), %eax # mmap->base_addr_high
movl %eax, 4(%edi)
movl 12(%esi), %eax # mmap->length_low
movl %eax, 8(%edi)
movl 16(%esi), %eax # mmap->length_high
movl %eax, 12(%edi)
movl 20(%esi), %eax # mmap->type
movl %eax, 16(%edi)
movl (%esi), %eax # mmap->size
addl $0x4, %eax
addl %eax, %esi
subl %eax, %ecx
addl $MEMMAP_E820_RECORD_SIZE, %edi
incl %edx
jmp mmap_loop
mmap_end:
mmap_invalid:
movl %edx, e820counter
invalid_boot:
#ifdef CONFIG_SMP
# copy AP bootstrap routines below 1 MB
movl $BOOT_OFFSET, %esi
movl $AP_BOOT_OFFSET, %edi
movl $_hardcoded_unmapped_size, %ecx
rep movsb
#endif
 
call main_bsp # never returns
 
# not reached
cli
hlt
hlt0:
hlt
jmp hlt0
 
.global map_kernel
map_kernel:
222,8 → 107,8
# For simplicity, we map the entire 4G space.
#
movl %cr4, %ecx
orl $(1 << 4), %ecx # turn PSE on
andl $(~(1 << 5)), %ecx # turn PAE off
orl $(1 << 4), %ecx # turn PSE on
andl $(~(1 << 5)), %ecx # turn PAE off
movl %ecx, %cr4
movl $(page_directory + 0), %esi
230,30 → 115,31
movl $(page_directory + 2048), %edi
xorl %ecx, %ecx
xorl %ebx, %ebx
0:
movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
orl %ebx, %eax
movl %eax, (%esi, %ecx, 4) # mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
movl %eax, (%edi, %ecx, 4) # mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
addl $(4 * 1024 * 1024), %ebx
 
incl %ecx
cmpl $512, %ecx
jl 0b
 
floop:
movl $((1 << 7) | (1 << 1) | (1 << 0)), %eax
orl %ebx, %eax
movl %eax, (%esi, %ecx, 4) # mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
movl %eax, (%edi, %ecx, 4) # mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M
addl $(4 * 1024 * 1024), %ebx
incl %ecx
cmpl $512, %ecx
jl floop
movl %esi, %cr3
movl %cr0, %ebx
orl $(1 << 31), %ebx # turn paging on
orl $(1 << 31), %ebx # turn paging on
movl %ebx, %cr0
ret
 
# Print string from %esi to EGA display (in red) and halt
error_halt:
movl $0xb8000, %edi # base of EGA text mode memory
movl $0xb8000, %edi # base of EGA text mode memory
xorl %eax, %eax
movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
movb $0xe, %al
outb %al, %dx
261,7 → 147,7
inb %dx, %al
shl $8, %ax
movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
movb $0xf, %al
outb %al, %dx
270,7 → 156,9
cmp $1920, %ax
jbe cursor_ok
movw $1920, %ax # sanity check for the cursor on the last line
movw $1920, %ax # sanity check for the cursor on the last line
cursor_ok:
movw %ax, %bx
277,7 → 165,7
shl $1, %eax
addl %eax, %edi
movw $0x0c00, %ax # black background, light red foreground
movw $0x0c00, %ax # black background, light red foreground
ploop:
lodsb
284,11 → 172,11
cmp $0, %al
je ploop_end
stosw
inc %bx
inc %bx
jmp ploop
ploop_end:
movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
movb $0xe, %al
outb %al, %dx
296,7 → 184,7
movb %bh, %al
outb %al, %dx
movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
movb $0xf, %al
outb %al, %dx
303,240 → 191,14
movw $0x3d5, %dx
movb %bl, %al
outb %al, %dx
cli
hlt
hlt1:
hlt
jmp hlt1
 
#ifdef CONFIG_FB
vesa_init:
jmp $selector(VESA_INIT_DES), $vesa_init_real - vesa_init
.code16
vesa_init_real:
mov %cr0, %eax
and $~1, %eax
mov %eax, %cr0
jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
vesa_init_real2:
mov $VESA_INIT_SEGMENT, %bx
mov %bx, %es
mov %bx, %fs
mov %bx, %gs
mov %bx, %ds
mov %bx, %ss
movl %esp, %eax
movl $0x0000fffc, %esp
movl $0x0000fffc, %ebp
pushl %eax
#define VESA_INFO_SIZE 1024
#include "vesa_real.inc"
 
#define VESA_MODE_ATTRIBUTES_OFFSET 0
#define VESA_MODE_LIST_PTR_OFFSET 14
#define VESA_MODE_SCANLINE_OFFSET 16
#define VESA_MODE_WIDTH_OFFSET 18
#define VESA_MODE_HEIGHT_OFFSET 20
#define VESA_MODE_BPP_OFFSET 25
#define VESA_MODE_PHADDR_OFFSET 40
 
#define VESA_END_OF_MODES 0xffff
 
#define VESA_OK 0x4f
 
#define VESA_GET_INFO 0x4f00
#define VESA_GET_MODE_INFO 0x4f01
#define VESA_SET_MODE 0x4f02
#define VESA_SET_PALETTE 0x4f09
 
#if CONFIG_VESA_BPP == 24
#define CONFIG_VESA_BPP_VARIANT 32
#endif
 
mov $VESA_GET_INFO, %ax
mov $e_vesa_init - vesa_init, %di
push %di
int $0x10
pop %di
cmp $VESA_OK, %al
jnz 0f
mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
mov %si, %gs
mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
add $VESA_INFO_SIZE, %di
 
1:# Try next mode
mov %gs:(%si), %cx
cmp $VESA_END_OF_MODES, %cx
jz 0f
inc %si
inc %si
push %cx
push %di
push %si
mov $VESA_GET_MODE_INFO, %ax
int $0x10
pop %si
pop %di
pop %cx
cmp $VESA_OK, %al
jnz 0f
mov $CONFIG_VESA_WIDTH, %ax
cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
jnz 1b
mov $CONFIG_VESA_HEIGHT, %ax
cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
jnz 1b
mov $CONFIG_VESA_BPP, %al
cmp VESA_MODE_BPP_OFFSET(%di), %al
 
#ifdef CONFIG_VESA_BPP_VARIANT
jz 2f
mov $CONFIG_VESA_BPP_VARIANT, %al
cmp VESA_MODE_BPP_OFFSET(%di), %al
#endif
jnz 1b
 
2:
mov %cx, %bx
or $0xc000, %bx
push %di
mov $VESA_SET_MODE, %ax
int $0x10
pop %di
cmp $VESA_OK, %al
jnz 0f
 
#if CONFIG_VESA_BPP == 8
# Set 3:2:3 VGA palette
mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
push %di
mov $vga323 - vesa_init, %di
mov $0x100, %ecx
bt $5, %ax # Test if VGA compatible registers are present
jnc vga_compat
# Try VESA routine to set palette
mov $VESA_SET_PALETTE, %ax
xor %bl, %bl
xor %dx, %dx
int $0x10
jmp vga_not_compat
vga_compat:
# Try VGA registers to set palette
movw $0x3c6, %dx # Set palette mask
movb $0xff, %al
outb %al, %dx
movw $0x3c8, %dx # First index to set
xor %al, %al
outb %al, %dx
movw $0x3c9, %dx # Data port
vga_loop:
movb %es:2(%di), %al
outb %al, %dx
movb %es:1(%di), %al
outb %al, %dx
movb %es:(%di), %al
outb %al, %dx
addw $4, %di
loop vga_loop
vga_not_compat:
pop %di
#endif
mov VESA_MODE_PHADDR_OFFSET(%di), %esi
mov VESA_MODE_WIDTH_OFFSET(%di), %ax
shl $16, %eax
mov VESA_MODE_HEIGHT_OFFSET(%di), %ax
mov VESA_MODE_BPP_OFFSET(%di), %bl
xor %bh, %bh
shl $16, %ebx
mov VESA_MODE_SCANLINE_OFFSET(%di), %bx
mov %eax, %edi
8:
mov %cr0, %eax
or $1, %eax
mov %eax, %cr0
jmp 9f
9:
ljmpl $selector(KTEXT_DES), $(vesa_init_protect - vesa_init + VESA_INIT_SEGMENT << 4)
 
0:# No prefered mode found
mov $0x111, %cx
push %di
push %cx
mov $VESA_GET_MODE_INFO, %ax
int $0x10
pop %cx
pop %di
cmp $VESA_OK, %al
jnz 1f
jz 2b # Force relative jump
1:
mov $0x0003, %ax
int $0x10
mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA
xor %ax, %ax
jz 8b # Force relative jump
 
vga323:
#include "vga323.pal"
 
.code32
vesa_init_protect:
movw $selector(KDATA_DES), %cx
movw %cx, %es
movw %cx, %fs
movw %cx, %gs
movw %cx, %ds # kernel data + stack
movw %cx, %ss
movl $START_STACK, %esp # initialize stack pointer
 
jmpl $selector(KTEXT_DES), $vesa_meeting_point
 
.align 4
e_vesa_init:
#endif
 
.section K_DATA_START, "aw", @progbits
 
.align 4096
/branches/network/kernel/arch/ia32/src/boot/vesa_real.inc
0,0 → 1,373
#ifdef CONFIG_FB
 
#include <macros.h>
 
#define VESA_INFO_SIZE 1024
 
#define VESA_MODE_ATTRIBUTES_OFFSET 0
#define VESA_MODE_LIST_PTR_OFFSET 14
#define VESA_MODE_SCANLINE_OFFSET 16
#define VESA_MODE_WIDTH_OFFSET 18
#define VESA_MODE_HEIGHT_OFFSET 20
#define VESA_MODE_BPP_OFFSET 25
#define VESA_MODE_RED_MASK_OFFSET 31
#define VESA_MODE_RED_POS_OFFSET 32
#define VESA_MODE_GREEN_MASK_OFFSET 33
#define VESA_MODE_GREEN_POS_OFFSET 34
#define VESA_MODE_BLUE_MASK_OFFSET 35
#define VESA_MODE_BLUE_POS_OFFSET 36
#define VESA_MODE_PHADDR_OFFSET 40
 
#define VESA_END_OF_MODES 0xffff
 
#define VESA_OK 0x4f
 
#define VESA_GET_INFO 0x4f00
#define VESA_GET_MODE_INFO 0x4f01
#define VESA_SET_MODE 0x4f02
#define VESA_SET_PALETTE 0x4f09
 
.code32
vesa_init:
jmp $gdtselector(VESA_INIT_DES), $vesa_init_real - vesa_init
.code16
vesa_init_real:
mov %cr0, %eax
and $~1, %eax
mov %eax, %cr0
jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
vesa_init_real2:
mov $VESA_INIT_SEGMENT, %bx
mov %bx, %es
mov %bx, %fs
mov %bx, %gs
mov %bx, %ds
mov %bx, %ss
movl %esp, %eax
movl $0x0000fffc, %esp
movl $0x0000fffc, %ebp
pushl %eax
# parse default mode string
mov $default_mode - vesa_init, %di
xor %eax, %eax
xor %ebx, %ebx
mov $8, %ecx
parse_width:
mov (%di), %al
# check for digit
cmp $'0', %al
jb parse_width_done
cmp $'9', %al
ja parse_width_done
sub $'0', %al
# multiply default_width by 10 and add digit
mov default_width - vesa_init, %bx
lea (%ebx, %ebx, 4), %ebx
shl $1, %ebx
add %ax, %bx
mov %bx, default_width - vesa_init
inc %di
loop parse_width
parse_width_done:
mov (%di), %al
cmp $0, %al
jz parse_done
inc %di
mov $8, %ecx
parse_height:
mov (%di), %al
# check for digit
cmp $'0', %al
jb parse_height_done
cmp $'9', %al
ja parse_height_done
sub $'0', %al
# multiply default_height by 10 and add digit
mov default_height - vesa_init, %bx
lea (%ebx, %ebx, 4), %ebx
shl $1, %ebx
add %ax, %bx
mov %bx, default_height - vesa_init
inc %di
loop parse_height
parse_height_done:
mov (%di), %al
cmp $0, %al
jz parse_done
inc %di
mov $4, %ecx
parse_bpp:
mov (%di), %al
# check for digit
cmp $'0', %al
jb parse_bpp_done
cmp $'9', %al
ja parse_bpp_done
sub $'0', %al
# multiply default_bpp by 10 and add digit
mov default_bpp - vesa_init, %bx
lea (%ebx, %ebx, 4), %ebx
shl $1, %ebx
add %ax, %bx
mov %bx, default_bpp - vesa_init
inc %di
loop parse_bpp
parse_bpp_done:
parse_done:
mov $VESA_GET_INFO, %ax
mov $e_vesa_init - vesa_init, %di
push %di
int $0x10
pop %di
cmp $VESA_OK, %al
jnz no_mode
mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
mov %si, %gs
mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
add $VESA_INFO_SIZE, %di
next_mode:
# try next mode
mov %gs:(%si), %cx
cmp $VESA_END_OF_MODES, %cx
je no_mode
inc %si
inc %si
push %cx
push %di
push %si
mov $VESA_GET_MODE_INFO, %ax
int $0x10
pop %si
pop %di
pop %cx
cmp $VESA_OK, %al
jne no_mode
# check for proper attributes (supported, color, graphics, linear framebuffer)
mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
and $0x99, %ax
cmp $0x99, %ax
jne next_mode
# check for proper resolution
mov default_width - vesa_init, %ax
cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
jne next_mode
mov default_height - vesa_init, %ax
cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
jne next_mode
# check for proper bpp
mov default_bpp - vesa_init, %al
cmp VESA_MODE_BPP_OFFSET(%di), %al
je set_mode
mov $24, %al
cmp default_bpp - vesa_init, %al
jne next_mode
# for 24 bpp modes accept also 32 bit bpp
mov $32, %al
cmp VESA_MODE_BPP_OFFSET(%di), %al
jne next_mode
set_mode:
mov %cx, %bx
or $0xc000, %bx
push %di
mov $VESA_SET_MODE, %ax
int $0x10
pop %di
cmp $VESA_OK, %al
jnz no_mode
# set 3:2:3 VGA palette
mov VESA_MODE_BPP_OFFSET(%di), %al
cmp $8, %al
jnz vga_not_set
mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
push %di
mov $vga323 - vesa_init, %di
mov $0x100, %ecx
bt $5, %ax # test if VGA compatible registers are present
jnc vga_compat
# try VESA routine to set palette
mov $VESA_SET_PALETTE, %ax
xor %bl, %bl
xor %dx, %dx
int $0x10
cmp $0x00, %ah
je vga_not_compat
vga_compat:
# try VGA registers to set palette
movw $0x3c6, %dx # set palette mask
movb $0xff, %al
outb %al, %dx
movw $0x3c8, %dx # first index to set
xor %al, %al
outb %al, %dx
movw $0x3c9, %dx # data port
vga_loop:
movb %es:2(%di), %al
outb %al, %dx
movb %es:1(%di), %al
outb %al, %dx
movb %es:(%di), %al
outb %al, %dx
addw $4, %di
loop vga_loop
vga_not_compat:
pop %di
vga_not_set:
# store mode parameters
# eax = bpp[8] scanline[16]
# ebx = width[16] height[16]
# edx = red_mask[8] red_pos[8] green_mask[8] green_pos[8]
# esi = blue_mask[8] blue_pos[8]
# edi = linear frame buffer
mov VESA_MODE_BPP_OFFSET(%di), %al
xor %ah, %ah
shl $16, %eax
mov VESA_MODE_SCANLINE_OFFSET(%di), %ax
mov VESA_MODE_WIDTH_OFFSET(%di), %bx
shl $16, %ebx
mov VESA_MODE_HEIGHT_OFFSET(%di), %bx
mov VESA_MODE_BLUE_MASK_OFFSET(%di), %dl
shl $8, %edx
mov VESA_MODE_BLUE_POS_OFFSET(%di), %dl
mov %edx, %esi
mov VESA_MODE_RED_MASK_OFFSET(%di), %dl
shl $8, %edx
mov VESA_MODE_RED_POS_OFFSET(%di), %dl
shl $8, %edx
mov VESA_MODE_GREEN_MASK_OFFSET(%di), %dl
shl $8, %edx
mov VESA_MODE_GREEN_POS_OFFSET(%di), %dl
mov VESA_MODE_PHADDR_OFFSET(%di), %edi
vesa_leave_real:
mov %cr0, %ecx
or $1, %ecx
mov %ecx, %cr0
jmp vesa_leave_real2
vesa_leave_real2:
ljmpl $gdtselector(KTEXT32_DES), $(vesa_init_protected - vesa_init + VESA_INIT_SEGMENT << 4)
no_mode:
# no prefered mode found
mov $0x111, %cx
push %di
push %cx
mov $VESA_GET_MODE_INFO, %ax
int $0x10
pop %cx
pop %di
cmp $VESA_OK, %al
jnz text_mode
jz set_mode # force relative jump
text_mode:
# reset to EGA text mode (because of problems with VESA)
mov $0x0003, %ax
int $0x10
mov $0xffffffff, %edi
xor %ax, %ax
jz vesa_leave_real # force relative jump
 
vga323:
#include "vga323.pal"
 
default_width:
.word 0
 
default_height:
.word 0
 
default_bpp:
.byte 0
 
default_mode:
.ascii STRING(CONFIG_VESA_MODE)
.ascii "-"
.asciz STRING(CONFIG_VESA_BPP)
.fill 24
 
#include "vesa_ret.inc"
 
.align 4
e_vesa_init:
#endif
/branches/network/kernel/arch/ia32/src/boot/vesa_prot.inc
0,0 → 1,107
#ifdef CONFIG_FB
 
#define MULTIBOOT_LOADER_MAGIC 0x2BADB002
#define MBINFO_BIT_CMDLINE 2
#define MBINFO_OFFSET_CMDLINE 16
 
# copy real mode VESA initialization code
mov $vesa_init, %esi
mov $VESA_INIT_SEGMENT << 4, %edi
mov $e_vesa_init - vesa_init, %ecx
rep movsb
# check for GRUB command line
mov grub_eax, %eax
cmp $MULTIBOOT_LOADER_MAGIC, %eax
jne no_cmdline
mov grub_ebx, %ebx
mov (%ebx), %eax
bt $MBINFO_BIT_CMDLINE, %eax
jnc no_cmdline
# skip the kernel path in command line
mov MBINFO_OFFSET_CMDLINE(%ebx), %esi
skip_loop:
lodsb
cmp $0, %al
je no_cmdline
cmp $' ', %al
je skip_loop_done
jmp skip_loop
skip_loop_done:
space_loop:
mov (%esi), %al
cmp $0, %al
je no_cmdline
cmp $' ', %al
jne space_loop_done
inc %esi
jmp space_loop
space_loop_done:
# copy at most 23 characters from command line
mov $VESA_INIT_SEGMENT << 4, %edi
add $default_mode - vesa_init, %edi
mov $23, %ecx
cmd_loop:
lodsb
stosb
cmp $0, %al
je cmd_loop_done
loop cmd_loop
cmd_loop_done:
# zero termination
xor %eax, %eax
stosb
no_cmdline:
# jump to the real mode
mov $VESA_INIT_SEGMENT << 4, %edi
jmpl *%edi
vesa_meeting_point:
# returned back to protected mode
mov %ax, KA2PA(vesa_scanline)
shr $16, %eax
mov %ax, KA2PA(vesa_bpp)
mov %bx, KA2PA(vesa_height)
shr $16, %ebx
mov %bx, KA2PA(vesa_width)
mov %dl, KA2PA(vesa_green_pos)
shr $8, %edx
mov %dl, KA2PA(vesa_green_mask)
shr $8, %edx
mov %dl, KA2PA(vesa_red_pos)
shr $8, %edx
mov %dl, KA2PA(vesa_red_mask)
mov %esi, %edx
mov %dl, KA2PA(vesa_blue_pos)
shr $8, %edx
mov %dl, KA2PA(vesa_blue_mask)
mov %edi, KA2PA(vesa_ph_addr)
#endif
/branches/network/kernel/arch/ia32/src/proc/scheduler.c
38,7 → 38,6
#include <proc/thread.h>
#include <arch.h>
#include <arch/context.h> /* SP_DELTA */
#include <arch/debugger.h>
#include <arch/pm.h>
#include <arch/asm.h>
#include <arch/ddi/ddi.h>
58,21 → 57,18
*/
void before_thread_runs_arch(void)
{
CPU->arch.tss->esp0 = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE -
uintptr_t kstk = (uintptr_t) &THREAD->kstack[THREAD_STACK_SIZE -
SP_DELTA];
CPU->arch.tss->ss0 = selector(KDATA_DES);
 
/* Set kernel stack for CP3 -> CPL0 switch via SYSENTER */
write_msr(IA32_MSR_SYSENTER_ESP, kstk);
/* Set kernel stack for CPL3 -> CPL0 switch via interrupt */
CPU->arch.tss->esp0 = kstk;
CPU->arch.tss->ss0 = gdtselector(KDATA_DES);
/* Set up TLS in GS register */
set_tls_desc(THREAD->arch.tls);
 
#ifdef CONFIG_DEBUG_AS_WATCHPOINT
/* Set watchpoint on AS to ensure that nobody sets it to zero */
if (CPU->id < BKPOINTS_MAX) {
the_t *the = THE;
breakpoint_add(&((the_t *) the->thread->kstack)->as,
BKPOINT_WRITE | BKPOINT_CHECK_ZERO, the->cpu->id);
}
#endif
}
 
void after_thread_ran_arch(void)
/branches/network/kernel/arch/ia32/src/mm/tlb.c
67,5 → 67,13
invlpg(page + i * PAGE_SIZE);
}
 
void tlb_arch_init(void)
{
}
 
void tlb_print(void)
{
}
 
/** @}
*/
/branches/network/kernel/arch/ia32/src/mm/frame.c
54,26 → 54,57
static void init_e820_memory(pfn_t minconf)
{
unsigned int i;
pfn_t start, conf;
size_t size;
 
for (i = 0; i < e820counter; i++) {
uint64_t base = e820table[i].base_address;
uint64_t size = e820table[i].size;
#ifdef __32_BITS__
/* Ignore physical memory above 4 GB */
if ((base >> 32) != 0)
continue;
/* Clip regions above 4 GB */
if (((base + size) >> 32) != 0)
size = 0xffffffff - base;
#endif
pfn_t pfn;
count_t count;
if (e820table[i].type == MEMMAP_MEMORY_AVAILABLE) {
start = ADDR2PFN(ALIGN_UP(e820table[i].base_address, FRAME_SIZE));
size = SIZE2FRAMES(ALIGN_DOWN(e820table[i].size, FRAME_SIZE));
/* To be safe, make available zone possibly smaller */
pfn = ADDR2PFN(ALIGN_UP(base, FRAME_SIZE));
count = SIZE2FRAMES(ALIGN_DOWN(size, FRAME_SIZE));
if ((minconf < start) || (minconf >= start + size))
conf = start;
pfn_t conf;
if ((minconf < pfn) || (minconf >= pfn + count))
conf = pfn;
else
conf = minconf;
zone_create(start, size, conf, 0);
zone_create(pfn, count, conf, ZONE_AVAILABLE);
if (last_frame < ALIGN_UP(e820table[i].base_address +
e820table[i].size, FRAME_SIZE))
last_frame =
ALIGN_UP(e820table[i].base_address + e820table[i].size, FRAME_SIZE);
}
// XXX this has to be removed
if (last_frame < ALIGN_UP(base + size, FRAME_SIZE))
last_frame = ALIGN_UP(base + size, FRAME_SIZE);
}
if (e820table[i].type == MEMMAP_MEMORY_RESERVED) {
/* To be safe, make reserved zone possibly larger */
pfn = ADDR2PFN(ALIGN_DOWN(base, FRAME_SIZE));
count = SIZE2FRAMES(ALIGN_UP(size, FRAME_SIZE));
zone_create(pfn, count, 0, ZONE_RESERVED);
}
if (e820table[i].type == MEMMAP_MEMORY_ACPI) {
/* To be safe, make firmware zone possibly larger */
pfn = ADDR2PFN(ALIGN_DOWN(base, (uintptr_t) FRAME_SIZE));
count = SIZE2FRAMES(ALIGN_UP(size, (uintptr_t) FRAME_SIZE));
zone_create(pfn, count, 0, ZONE_FIRMWARE);
}
}
}
 
113,16 → 144,14
if (config.cpu_active == 1) {
minconf = 1;
#ifdef CONFIG_SMP
minconf = max(minconf,
ADDR2PFN(AP_BOOT_OFFSET + hardcoded_unmapped_ktext_size +
hardcoded_unmapped_kdata_size));
#endif
#ifdef CONFIG_SIMICS_FIX
minconf = max(minconf, ADDR2PFN(0x10000));
#endif
init_e820_memory(minconf);
 
/* Reserve frame 0 (BIOS data) */
frame_mark_unavailable(0, 1);
131,12 → 160,7
frame_mark_unavailable(AP_BOOT_OFFSET >> FRAME_WIDTH,
(hardcoded_unmapped_ktext_size +
hardcoded_unmapped_kdata_size) >> FRAME_WIDTH);
#ifdef CONFIG_SIMICS_FIX
/* Don't know why, but these addresses help */
frame_mark_unavailable(0xd000 >> FRAME_WIDTH, 3);
#endif
#endif
}
}
 
/branches/network/kernel/arch/ia32/src/mm/page.c
53,7 → 53,7
{
uintptr_t cur;
int flags;
 
if (config.cpu_active == 1) {
page_mapping_operations = &pt_mapping_operations;
66,12 → 66,12
flags |= PAGE_GLOBAL;
page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags);
}
 
exc_register(14, "page_fault", (iroutine) page_fault);
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
} else
write_cr3((uintptr_t) AS_KERNEL->genarch.page_table);
 
paging_on();
}
 
79,7 → 79,7
uintptr_t hw_map(uintptr_t physaddr, size_t size)
{
if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
panic("Unable to map physical memory %p (%d bytes)", physaddr, size)
panic("Unable to map physical memory %p (%d bytes).", physaddr, size)
uintptr_t virtaddr = PA2KA(last_frame);
pfn_t i;
101,8 → 101,8
page = read_cr2();
if (istate->error_word & PFERR_CODE_RSVD)
panic("Reserved bit set in page directory.\n");
 
panic("Reserved bit set in page directory.");
if (istate->error_word & PFERR_CODE_RW)
access = PF_ACCESS_WRITE;
else
109,11 → 109,11
access = PF_ACCESS_READ;
if (as_page_fault(page, access, istate) == AS_PF_FAULT) {
fault_if_from_uspace(istate, "Page fault: %#x", page);
fault_if_from_uspace(istate, "Page fault: %#x.", page);
decode_istate(istate);
printf("page fault address: %#lx\n", page);
panic("page fault\n");
panic("Page fault.");
}
}
 
/branches/network/kernel/arch/ia32/src/userspace.c
26,7 → 26,7
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/** @file
47,10 → 47,8
*/
void userspace(uspace_arg_t *kernel_uarg)
{
ipl_t ipl;
 
ipl = interrupts_disable();
 
ipl_t ipl = interrupts_disable();
asm volatile (
/*
* Clear nested task flag.
60,35 → 58,33
"and $0xffffbfff, %%eax\n"
"push %%eax\n"
"popfl\n"
 
/* Set up GS register (TLS) */
"movl %6, %%gs\n"
 
"pushl %0\n"
"pushl %1\n"
"pushl %2\n"
"pushl %3\n"
"pushl %4\n"
"movl %5, %%eax\n"
 
"movl %[tls_des], %%gs\n"
"pushl %[udata_des]\n"
"pushl %[stack_size]\n"
"pushl %[ipl]\n"
"pushl %[utext_des]\n"
"pushl %[entry]\n"
"movl %[uarg], %%eax\n"
/* %ebx is defined to hold pcb_ptr - set it to 0 */
"xorl %%ebx, %%ebx\n"
 
"xorl %%ebx, %%ebx\n"
"iret\n"
:
: "i" (selector(UDATA_DES) | PL_USER),
"r" ((uint8_t *) kernel_uarg->uspace_stack +
THREAD_STACK_SIZE),
"r" (ipl),
"i" (selector(UTEXT_DES) | PL_USER),
"r" (kernel_uarg->uspace_entry),
"r" (kernel_uarg->uspace_uarg),
"r" (selector(TLS_DES))
:
: [udata_des] "i" (gdtselector(UDATA_DES) | PL_USER),
[stack_size] "r" ((uint8_t *) kernel_uarg->uspace_stack + THREAD_STACK_SIZE),
[ipl] "r" (ipl),
[utext_des] "i" (gdtselector(UTEXT_DES) | PL_USER),
[entry] "r" (kernel_uarg->uspace_entry),
[uarg] "r" (kernel_uarg->uspace_uarg),
[tls_des] "r" (gdtselector(TLS_DES))
: "eax");
/* Unreachable */
for(;;)
;
while (1);
}
 
/** @}
/branches/network/kernel/arch/ia32/src/interrupt.c
44,7 → 44,6
#include <mm/tlb.h>
#include <mm/as.h>
#include <arch.h>
#include <symtab.h>
#include <proc/thread.h>
#include <proc/task.h>
#include <synch/spinlock.h>
52,6 → 51,7
#include <ipc/sysipc.h>
#include <interrupt.h>
#include <ddi/irq.h>
#include <symtab.h>
 
/*
* Interrupt and exception dispatching.
63,10 → 63,9
 
void decode_istate(istate_t *istate)
{
char *symbol = get_symtab_entry(istate->eip);
char *symbol;
 
if (!symbol)
symbol = "";
symbol = symtab_fmt_name_lookup(istate->eip);
 
if (CPU)
printf("----------------EXCEPTION OCCURED (cpu%u)----------------\n", CPU->id);
77,9 → 76,6
printf("ERROR_WORD=%#lx\n", istate->error_word);
printf("%%cs=%#lx,flags=%#lx\n", istate->cs, istate->eflags);
printf("%%eax=%#lx, %%ecx=%#lx, %%edx=%#lx, %%esp=%p\n", istate->eax, istate->ecx, istate->edx, &istate->stack[0]);
#ifdef CONFIG_DEBUG_ALLREGS
printf("%%esi=%#lx, %%edi=%#lx, %%ebp=%#lx, %%ebx=%#lx\n", istate->esi, istate->edi, istate->ebp, istate->ebx);
#endif
printf("stack: %#lx, %#lx, %#lx, %#lx\n", istate->stack[0], istate->stack[1], istate->stack[2], istate->stack[3]);
printf(" %#lx, %#lx, %#lx, %#lx\n", istate->stack[4], istate->stack[5], istate->stack[6], istate->stack[7]);
}
89,16 → 85,16
if (eoi_function)
eoi_function();
else
panic("no eoi_function\n");
panic("No eoi_function.");
 
}
 
static void null_interrupt(int n, istate_t *istate)
{
fault_if_from_uspace(istate, "unserviced interrupt: %d", n);
fault_if_from_uspace(istate, "Unserviced interrupt: %d.", n);
 
decode_istate(istate);
panic("unserviced interrupt: %d\n", n);
panic("Unserviced interrupt: %d.", n);
}
 
/** General Protection Fault. */
122,19 → 118,19
io_perm_bitmap_install();
return;
}
fault_if_from_uspace(istate, "general protection fault");
fault_if_from_uspace(istate, "General protection fault.");
}
 
decode_istate(istate);
panic("general protection fault\n");
panic("General protection fault.");
}
 
static void ss_fault(int n __attribute__((unused)), istate_t *istate)
{
fault_if_from_uspace(istate, "stack fault");
fault_if_from_uspace(istate, "Stack fault.");
 
decode_istate(istate);
panic("stack fault\n");
panic("Stack fault.");
}
 
static void simd_fp_exception(int n __attribute__((unused)), istate_t *istate)
141,15 → 137,15
{
uint32_t mxcsr;
asm (
"stmxcsr %0;\n"
: "=m" (mxcsr)
"stmxcsr %[mxcsr]\n"
: [mxcsr] "=m" (mxcsr)
);
fault_if_from_uspace(istate, "SIMD FP exception(19), MXCSR: %#zx",
fault_if_from_uspace(istate, "SIMD FP exception(19), MXCSR: %#zx.",
(unative_t) mxcsr);
 
decode_istate(istate);
printf("MXCSR: %#lx\n", mxcsr);
panic("SIMD FP exception(19)\n");
panic("SIMD FP exception(19).");
}
 
static void nm_fault(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
157,8 → 153,8
#ifdef CONFIG_FPU_LAZY
scheduler_fpu_lazy_request();
#else
fault_if_from_uspace(istate, "fpu fault");
panic("fpu fault");
fault_if_from_uspace(istate, "FPU fault.");
panic("FPU fault.");
#endif
}
 
191,7 → 187,7
trap_virtual_eoi();
ack = true;
}
irq->handler(irq, irq->arg);
irq->handler(irq);
spinlock_unlock(&irq->lock);
} else {
/*
233,7 → 229,7
if (enable_irqs_function)
enable_irqs_function(irqmask);
else
panic("no enable_irqs_function\n");
panic("No enable_irqs_function.");
}
 
void trap_virtual_disable_irqs(uint16_t irqmask)
241,7 → 237,7
if (disable_irqs_function)
disable_irqs_function(irqmask);
else
panic("no disable_irqs_function\n");
panic("No disable_irqs_function.");
}
 
/** @}
/branches/network/kernel/arch/ia32/src/drivers/ega.c
File deleted
/branches/network/kernel/arch/ia32/src/drivers/vesa.c
56,12 → 56,20
uint16_t vesa_bpp;
uint16_t vesa_scanline;
 
uint8_t vesa_red_mask;
uint8_t vesa_red_pos;
 
uint8_t vesa_green_mask;
uint8_t vesa_green_pos;
 
uint8_t vesa_blue_mask;
uint8_t vesa_blue_pos;
 
int vesa_present(void)
{
if (vesa_width != 0xffff)
if ((vesa_width != 0xffff) && (vesa_height != 0xffff))
return true;
if (vesa_height != 0xffff)
return true;
return false;
}
 
74,7 → 82,12
visual = VISUAL_INDIRECT_8;
break;
case 16:
visual = VISUAL_RGB_5_6_5;
if ((vesa_red_mask == 5) && (vesa_red_pos == 10)
&& (vesa_green_mask == 5) && (vesa_green_pos == 5)
&& (vesa_blue_mask == 5) && (vesa_blue_pos == 0))
visual = VISUAL_RGB_5_5_5;
else
visual = VISUAL_RGB_5_6_5;
break;
case 24:
visual = VISUAL_RGB_8_8_8;
83,12 → 96,25
visual = VISUAL_RGB_0_8_8_8;
break;
default:
panic("Unsupported bits per pixel");
panic("Unsupported bits per pixel.");
}
fb_init(vesa_ph_addr, vesa_width, vesa_height, vesa_scanline, visual);
fb_properties_t vesa_props = {
.addr = vesa_ph_addr,
.offset = 0,
.x = vesa_width,
.y = vesa_height,
.scan = vesa_scanline,
.visual = visual,
};
fb_init(&vesa_props);
}
 
void vesa_redraw(void)
{
fb_redraw();
}
 
#endif
 
/** @}
/branches/network/kernel/arch/ia32/src/drivers/i8259.c
49,28 → 49,28
void i8259_init(void)
{
/* ICW1: this is ICW1, ICW4 to follow */
outb(PIC_PIC0PORT1, PIC_ICW1 | PIC_NEEDICW4);
pio_write_8(PIC_PIC0PORT1, PIC_ICW1 | PIC_NEEDICW4);
 
/* ICW2: IRQ 0 maps to INT IRQBASE */
outb(PIC_PIC0PORT2, IVT_IRQBASE);
pio_write_8(PIC_PIC0PORT2, IVT_IRQBASE);
 
/* ICW3: pic1 using IRQ IRQ_PIC1 */
outb(PIC_PIC0PORT2, 1 << IRQ_PIC1);
pio_write_8(PIC_PIC0PORT2, 1 << IRQ_PIC1);
 
/* ICW4: i8086 mode */
outb(PIC_PIC0PORT2, 1);
pio_write_8(PIC_PIC0PORT2, 1);
 
/* ICW1: ICW1, ICW4 to follow */
outb(PIC_PIC1PORT1, PIC_ICW1 | PIC_NEEDICW4);
pio_write_8(PIC_PIC1PORT1, PIC_ICW1 | PIC_NEEDICW4);
 
/* ICW2: IRQ 8 maps to INT (IVT_IRQBASE + 8) */
outb(PIC_PIC1PORT2, IVT_IRQBASE + 8);
pio_write_8(PIC_PIC1PORT2, IVT_IRQBASE + 8);
 
/* ICW3: pic1 is known as IRQ_PIC1 */
outb(PIC_PIC1PORT2, IRQ_PIC1);
pio_write_8(PIC_PIC1PORT2, IRQ_PIC1);
 
/* ICW4: i8086 mode */
outb(PIC_PIC1PORT2, 1);
pio_write_8(PIC_PIC1PORT2, 1);
 
/*
* Register interrupt handler for the PIC spurious interrupt.
94,12 → 94,12
uint8_t x;
 
if (irqmask & 0xff) {
x = inb(PIC_PIC0PORT2);
outb(PIC_PIC0PORT2, (uint8_t) (x & (~(irqmask & 0xff))));
x = pio_read_8(PIC_PIC0PORT2);
pio_write_8(PIC_PIC0PORT2, (uint8_t) (x & (~(irqmask & 0xff))));
}
if (irqmask >> 8) {
x = inb(PIC_PIC1PORT2);
outb(PIC_PIC1PORT2, (uint8_t) (x & (~(irqmask >> 8))));
x = pio_read_8(PIC_PIC1PORT2);
pio_write_8(PIC_PIC1PORT2, (uint8_t) (x & (~(irqmask >> 8))));
}
}
 
108,19 → 108,19
uint8_t x;
 
if (irqmask & 0xff) {
x = inb(PIC_PIC0PORT2);
outb(PIC_PIC0PORT2, (uint8_t) (x | (irqmask & 0xff)));
x = pio_read_8(PIC_PIC0PORT2);
pio_write_8(PIC_PIC0PORT2, (uint8_t) (x | (irqmask & 0xff)));
}
if (irqmask >> 8) {
x = inb(PIC_PIC1PORT2);
outb(PIC_PIC1PORT2, (uint8_t) (x | (irqmask >> 8)));
x = pio_read_8(PIC_PIC1PORT2);
pio_write_8(PIC_PIC1PORT2, (uint8_t) (x | (irqmask >> 8)));
}
}
 
void pic_eoi(void)
{
outb(0x20, 0x20);
outb(0xa0, 0x20);
pio_write_8((ioport8_t *)0x20, 0x20);
pio_write_8((ioport8_t *)0xa0, 0x20);
}
 
void pic_spurious(int n __attribute__((unused)), istate_t *istate __attribute__((unused)))
/branches/network/kernel/arch/ia32/src/drivers/i8254.c
26,12 → 26,12
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
 
/** @addtogroup ia32
/** @addtogroup ia32
* @{
*/
/**
* @file
* @brief i8254 chip driver.
* @brief i8254 chip driver.
*
* Low level time functions.
*/
53,8 → 53,8
#include <ddi/irq.h>
#include <ddi/device.h>
 
#define CLK_PORT1 0x40
#define CLK_PORT4 0x43
#define CLK_PORT1 ((ioport8_t *)0x40)
#define CLK_PORT4 ((ioport8_t *)0x43)
 
#define CLK_CONST 1193180
#define MAGIC_NUMBER 1194
61,12 → 61,12
 
static irq_t i8254_irq;
 
static irq_ownership_t i8254_claim(void)
static irq_ownership_t i8254_claim(irq_t *irq)
{
return IRQ_ACCEPT;
}
 
static void i8254_irq_handler(irq_t *irq, void *arg __attribute__((unused)), ...)
static void i8254_irq_handler(irq_t *irq)
{
/*
* This IRQ is responsible for kernel preemption.
94,10 → 94,10
 
void i8254_normal_operation(void)
{
outb(CLK_PORT4, 0x36);
pio_write_8(CLK_PORT4, 0x36);
pic_disable_irqs(1 << IRQ_CLK);
outb(CLK_PORT1, (CLK_CONST / HZ) & 0xf);
outb(CLK_PORT1, (CLK_CONST / HZ) >> 8);
pio_write_8(CLK_PORT1, (CLK_CONST / HZ) & 0xf);
pio_write_8(CLK_PORT1, (CLK_CONST / HZ) >> 8);
pic_enable_irqs(1 << IRQ_CLK);
}
 
114,36 → 114,36
* One-shot timer. Count-down from 0xffff at 1193180Hz
* MAGIC_NUMBER is the magic value for 1ms.
*/
outb(CLK_PORT4, 0x30);
outb(CLK_PORT1, 0xff);
outb(CLK_PORT1, 0xff);
pio_write_8(CLK_PORT4, 0x30);
pio_write_8(CLK_PORT1, 0xff);
pio_write_8(CLK_PORT1, 0xff);
 
do {
/* will read both status and count */
outb(CLK_PORT4, 0xc2);
not_ok = (uint8_t) ((inb(CLK_PORT1) >> 6) & 1);
t1 = inb(CLK_PORT1);
t1 |= inb(CLK_PORT1) << 8;
pio_write_8(CLK_PORT4, 0xc2);
not_ok = (uint8_t) ((pio_read_8(CLK_PORT1) >> 6) & 1);
t1 = pio_read_8(CLK_PORT1);
t1 |= pio_read_8(CLK_PORT1) << 8;
} while (not_ok);
 
asm_delay_loop(LOOPS);
 
outb(CLK_PORT4, 0xd2);
t2 = inb(CLK_PORT1);
t2 |= inb(CLK_PORT1) << 8;
pio_write_8(CLK_PORT4, 0xd2);
t2 = pio_read_8(CLK_PORT1);
t2 |= pio_read_8(CLK_PORT1) << 8;
 
/*
* We want to determine the overhead of the calibrating mechanism.
*/
outb(CLK_PORT4, 0xd2);
o1 = inb(CLK_PORT1);
o1 |= inb(CLK_PORT1) << 8;
pio_write_8(CLK_PORT4, 0xd2);
o1 = pio_read_8(CLK_PORT1);
o1 |= pio_read_8(CLK_PORT1) << 8;
 
asm_fake_loop(LOOPS);
 
outb(CLK_PORT4, 0xd2);
o2 = inb(CLK_PORT1);
o2 |= inb(CLK_PORT1) << 8;
pio_write_8(CLK_PORT4, 0xd2);
o2 = pio_read_8(CLK_PORT1);
o2 |= pio_read_8(CLK_PORT1) << 8;
 
CPU->delay_loop_const =
((MAGIC_NUMBER * LOOPS) / 1000) / ((t1 - t2) - (o1 - o2)) +