Initial x86 port
diff --git a/arch/arm/crt0.S b/arch/arm/crt0.S
index 68dbc67..f567574 100644
--- a/arch/arm/crt0.S
+++ b/arch/arm/crt0.S
@@ -187,3 +187,14 @@
abort_stack:
.skip 1024
abort_stack_top:
+
+.rodata:
+.align 2
+
+/* define the heap end as read-only data containing the end defined in the
+ * linker script. other archs that use dynamic memory length discovery can make
+ * this read-write and update it during init.
+ */
+.global _heap_end
+_heap_end:
+ .int _end_of_ram
diff --git a/arch/x86/arch.c b/arch/x86/arch.c
new file mode 100644
index 0000000..99ca572
--- /dev/null
+++ b/arch/x86/arch.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <debug.h>
+#include <arch.h>
+#include <arch/ops.h>
+#include <arch/x86.h>
+#include <arch/x86/mmu.h>
+#include <arch/x86/descriptor.h>
+#include <platform.h>
+#include <sys/types.h>
+#include <string.h>
+
+static tss_t system_tss;
+
+void arch_early_init(void)
+{
+ x86_mmu_init();
+
+ platform_init_mmu_mappings();
+
+ /* enable caches here for now */
+ clear_in_cr0(X86_CR0_NW | X86_CR0_CD);
+
+ memset(&system_tss, 0, sizeof(tss_t));
+
+ system_tss.esp0 = 0;
+ system_tss.ss0 = DATA_SELECTOR;
+ system_tss.ss1 = 0;
+ system_tss.ss2 = 0;
+ system_tss.eflags = 0x00003002;
+ system_tss.bitmap = offsetof(tss_t, tss_bitmap);
+ system_tss.trace = 1; // trap on hardware task switch
+
+ set_global_desc(TSS_SELECTOR, &system_tss, sizeof(tss_t), 1, 0, 0, SEG_TYPE_TSS, 0, 0);
+
+ x86_ltr(TSS_SELECTOR);
+}
+
+void arch_init(void)
+{
+}
+
diff --git a/arch/x86/asm.S b/arch/x86/asm.S
new file mode 100644
index 0000000..4d7763c
--- /dev/null
+++ b/arch/x86/asm.S
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+
+
+ /* context switch frame is as follows:
+ * ulr
+ * usp
+ * lr
+ * r11
+ * r10
+ * r9
+ * r8
+ * r7
+ * r6
+ * r5
+ * r4
+ */
+/* x86_context_switch(addr_t *old_sp, addr_t new_sp) */
+FUNCTION(x86_context_switch)
+ /* TODO */
+ ret
diff --git a/arch/x86/cache-ops.S b/arch/x86/cache-ops.S
new file mode 100644
index 0000000..9ad7c71
--- /dev/null
+++ b/arch/x86/cache-ops.S
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+#include <arch/ops.h>
+#include <arch/defines.h>
+
+.text
+
+/* stubs */
+
+FUNCTION(arch_disable_cache)
+ ret
+
+FUNCTION(arch_enable_cache)
+ ret
+
+FUNCTION(arch_clean_cache_range)
+ ret
+
+FUNCTION(arch_clean_invalidate_cache_range)
+ ret
+
diff --git a/arch/x86/cache.c b/arch/x86/cache.c
new file mode 100644
index 0000000..b00d6cc
--- /dev/null
+++ b/arch/x86/cache.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
diff --git a/arch/x86/compile.mk b/arch/x86/compile.mk
new file mode 100644
index 0000000..271db17
--- /dev/null
+++ b/arch/x86/compile.mk
@@ -0,0 +1,16 @@
+
+$(BUILDDIR)/%.o: %.c $(SRCDEPS)
+ @$(MKDIR)
+ @echo compiling $<
+ $(NOECHO)$(CC) $(CFLAGS) --std=c99 $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+
+$(BUILDDIR)/%.o: %.cpp $(SRCDEPS)
+ @$(MKDIR)
+ @echo compiling $<
+ $(NOECHO)$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+
+$(BUILDDIR)/%.o: %.S $(SRCDEPS)
+ @$(MKDIR)
+ @echo compiling $<
+ $(NOECHO)$(CC) $(CFLAGS) $(ASMFLAGS) $(INCLUDES) -c $< -MD -MT $@ -MF $(@:%o=%d) -o $@
+
diff --git a/arch/x86/crt0.S b/arch/x86/crt0.S
new file mode 100644
index 0000000..9cc9ab0
--- /dev/null
+++ b/arch/x86/crt0.S
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* The magic number for the Multiboot header. */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* The flags for the Multiboot header. */
+#if defined(__ELF__) && 0
+#define MULTIBOOT_HEADER_FLAGS 0x00000002
+#else
+#define MULTIBOOT_HEADER_FLAGS 0x00010002
+#endif
+
+/* The magic number passed by a Multiboot-compliant boot loader. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+#define NUM_INT 0x31
+#define NUM_EXC 0x14
+
+.text
+.global _start
+_start:
+ jmp real_start
+
+.align 4
+
+multiboot_header:
+ /* magic */
+ .int MULTIBOOT_HEADER_MAGIC
+ /* flags */
+ .int MULTIBOOT_HEADER_FLAGS
+ /* checksum */
+ .int -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
+
+#if !defined(__ELF__) || 1
+ /* header_addr */
+ .int multiboot_header
+ /* load_addr */
+ .int _start
+ /* load_end_addr */
+ .int __bss_start
+ /* bss_end_addr */
+ .int __bss_end
+ /* entry_addr */
+ .int real_start
+#endif
+
+real_start:
+ cmpl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
+ jne 0f
+ movl %ebx, (_multiboot_info)
+0:
+ /* setup isr stub descriptors in the idt */
+ movl $_isr, %esi
+ movl $_idt, %edi
+ movl $NUM_INT, %ecx
+
+.Lloop:
+ movl %esi, %ebx
+ movw %bx, (%edi) /* low word in IDT(n).low */
+ shrl $16, %ebx
+ movw %bx, 6(%edi) /* high word in IDT(n).high */
+
+ addl $isr_stub_len, %esi/* index the next ISR stub */
+ addl $8, %edi /* index the next IDT entry */
+
+ loop .Lloop
+
+ lidt _idtr
+ xorl %eax, %eax
+ movl %eax, %cr3
+
+ lgdt _gdtr
+
+ movw $datasel, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %ss
+ movw %ax, %gs
+ movw %ax, %ss
+
+ movl $_kstack, %esp
+
+ /* zero the bss section */
+ movl $__bss_start, %edi /* starting address of the bss */
+ movl $__bss_end, %ecx /* find the length of the bss in bytes */
+ subl %edi, %ecx
+ shrl $2, %ecx /* convert to 32 bit words, since the bss is aligned anyway */
+2:
+ movl $0, (%edi)
+ addl $4, %edi
+ loop 2b
+
+ /* call the main module */
+ call kmain
+
+0: /* just sit around waiting for interrupts */
+ hlt /* interrupts will unhalt the processor */
+ pause
+ jmp 0b /* so jump back to halt to conserve power */
+
+/* interrupt service routine stubs */
+_isr:
+
+.set i, 0
+.rept NUM_INT
+
+.set isr_stub_start, .
+
+.if i == 8 || (i >= 10 && i <= 14) || i == 17
+ nop /* error code pushed by exception */
+ nop /* 2 nops are the same length as push byte */
+ pushl $i /* interrupt number */
+ jmp interrupt_common
+.else
+ pushl $0 /* fill in error code in iframe */
+ pushl $i /* interrupt number */
+ jmp interrupt_common
+.endif
+
+/* figure out the length of a single isr stub (usually 6 or 9 bytes) */
+.set isr_stub_len, . - isr_stub_start
+
+.set i, i + 1
+.endr
+
+/* annoying, but force AS to use the same (longer) encoding of jmp for all of the stubs */
+.fill 256
+
+interrupt_common:
+ pushl %gs /* save segment registers */
+ pushl %fs
+ pushl %es
+ pushl %ds
+ pusha /* save general purpose registers */
+ movl $datasel, %eax /* put known good value in segment registers */
+ movl %eax, %gs
+ movl %eax, %fs
+ movl %eax, %es
+ movl %eax, %ds
+ movl %esp, %eax /* store stack switch pivot. push esp has errata on some cpus, so use mov/push */
+ pushl %eax
+ movl %esp, %eax /* store pointer to iframe, using same method */
+ pushl %eax
+
+ incl critical_section_count
+
+ call platform_irq
+
+ cmpl $0,%eax
+ je 0f
+ call thread_preempt
+
+0:
+ decl critical_section_count
+
+ popl %eax /* drop pointer to iframe */
+ popl %eax /* restore task_esp, stack switch can occur here if task_esp is modified */
+ movl %eax, %esp
+ popa /* restore general purpose registers */
+ popl %ds /* restore segment registers */
+ popl %es
+ popl %fs
+ popl %gs
+ addl $8, %esp /* drop exception number and error code */
+ iret
+
+.data
+.align 4
+
+/* define the heap end as read-write data containing the default end of the
+ * heap. dynamic memory length discovery can update this value during init.
+ * other archs can define this statically based on the memory layout of the
+ * platform.
+ */
+.global _heap_end
+_heap_end:
+ .int 4096*1024 /* default to 4MB total */
+
+.global _multiboot_info
+_multiboot_info:
+ .int 0
+
+.global _gdtr
+_gdtr:
+ .short _gdt_end - _gdt - 1
+ .int _gdt
+
+.global _gdt
+_gdt:
+ .int 0
+ .int 0
+
+/* ring 0 descriptors */
+.set codesel, . - _gdt
+_code_gde:
+ .short 0xffff /* limit 15:00 */
+ .short 0x0000 /* base 15:00 */
+ .byte 0x00 /* base 23:16 */
+ .byte 0b10011010 /* P(1) DPL(00) S(1) 1 C(0) R(1) A(0) */
+ .byte 0b11001111 /* G(1) D(1) 0 0 limit 19:16 */
+ .byte 0x0 /* base 31:24 */
+
+.set datasel, . - _gdt
+_data_gde:
+ .short 0xffff /* limit 15:00 */
+ .short 0x0000 /* base 15:00 */
+ .byte 0x00 /* base 23:16 */
+ .byte 0b10010010 /* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
+ .byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
+ .byte 0x0 /* base 31:24 */
+
+.set videosel, . - _gdt
+_video_gde:
+ .short 0xffff /* limit 15:00 */
+ .short 0x8000 /* base 15:00 */
+ .byte 0x0b /* base 23:16 */
+ .byte 0b10010010 /* P(1) DPL(00) S(1) 0 E(0) W(1) A(0) */
+ .byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
+ .byte 0x0 /* base 31:24 */
+
+.if 1
+/* ring 3 descriptors */
+.set user_codesel, . - _gdt
+_user_code_gde:
+ .short 0xffff /* limit 15:00 */
+ .short 0x0000 /* base 15:00 */
+ .byte 0x00 /* base 23:16 */
+ .byte 0b11111010 /* P(1) DPL(11) S(1) 1 C(0) R(1) A(0) */
+ .byte 0b11001111 /* G(1) D(1) 0 0 limit 19:16 */
+ .byte 0x0 /* base 31:24 */
+
+.set user_datasel, . - _gdt
+_user_data_gde:
+ .short 0xffff /* limit 15:00 */
+ .short 0x0000 /* base 15:00 */
+ .byte 0x00 /* base 23:16 */
+ .byte 0b11110010 /* P(1) DPL(11) S(1) 0 E(0) W(1) A(0) */
+ .byte 0b11001111 /* G(1) B(1) 0 0 limit 19:16 */
+ .byte 0x0 /* base 31:24 */
+.endif
+
+/* TSS descriptor */
+.if 1
+.set tsssel, . - _gdt
+_tss_gde:
+ .short 0 /* limit 15:00 */
+ .short 0 /* base 15:00 */
+ .byte 0 /* base 23:16 */
+ .byte 0xe9 /* P(1) DPL(11) 0 10 B(0) 1 */
+ .byte 0x00 /* G(0) 0 0 AVL(0) limit 19:16 */
+ .short 0 /* base 31:24 */
+.endif
+
+.global _gdt_end
+_gdt_end:
+
+.global _idtr
+_idtr:
+ .short _idt_end - _idt - 1 /* IDT limit */
+ .int _idt
+
+/* interrupt descriptor table (IDT) */
+.global _idt
+_idt:
+
+.set i, 0
+.rept NUM_INT-1
+ .short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
+ .short codesel /* selector */
+ .byte 0
+ .byte 0x8e /* present, ring 0, 32-bit interrupt gate */
+ .short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */
+
+.set i, i + 1
+.endr
+
+/* syscall int (ring 3) */
+_idt30:
+ .short 0 /* low 16 bits of ISR offset (_isr#i & 0FFFFh) */
+ .short codesel /* selector */
+ .byte 0
+ .byte 0xee /* present, ring 3, 32-bit interrupt gate */
+ .short 0 /* high 16 bits of ISR offset (_isr#i / 65536) */
+
+.global _idt_end
+_idt_end:
+
+.bss
+.align 4096
+
+.global _kstack
+.fill 4096
+_kstack:
diff --git a/arch/x86/descriptor.c b/arch/x86/descriptor.c
new file mode 100644
index 0000000..27ee37e
--- /dev/null
+++ b/arch/x86/descriptor.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <compiler.h>
+#include <arch/x86/descriptor.h>
+
+/* not the best way to do this, but easy for now */
+typedef struct {
+ uint16_t limit_15_0;
+ uint16_t base_15_0;
+ uint8_t base_23_16;
+
+ uint8_t type : 4;
+ uint8_t s : 1;
+ uint8_t dpl : 2;
+ uint8_t p : 1;
+
+ uint8_t limit_19_16 : 4;
+ uint8_t avl : 1;
+ uint8_t reserved_0 : 1;
+ uint8_t d_b : 1;
+ uint8_t g : 1;
+
+ uint8_t base_31_24;
+} __PACKED seg_desc_t;
+
+extern seg_desc_t _gdt[];
+
+void set_global_desc(seg_sel_t sel, void *base, uint32_t limit,
+ uint8_t present, uint8_t ring, uint8_t sys, uint8_t type, uint8_t gran, uint8_t bits)
+{
+ // convert selector into index
+ uint16_t index = sel >> 3;
+
+ _gdt[index].limit_15_0 = limit & 0x0000ffff;
+ _gdt[index].limit_19_16 = (limit & 0x000f0000) >> 16;
+
+ _gdt[index].base_15_0 = ((uint32_t) base) & 0x0000ffff;
+ _gdt[index].base_23_16 = (((uint32_t) base) & 0x00ff0000) >> 16;
+ _gdt[index].base_31_24 = ((uint32_t) base) >> 24;
+
+ _gdt[index].type = type & 0x0f; // segment type
+ _gdt[index].p = present != 0; // present
+ _gdt[index].dpl = ring & 0x03; // descriptor privilege level
+ _gdt[index].g = gran != 0; // granularity
+ _gdt[index].s = sys != 0; // system / non-system
+ _gdt[index].d_b = bits != 0; // 16 / 32 bit
+}
diff --git a/arch/x86/faults.c b/arch/x86/faults.c
new file mode 100644
index 0000000..3d4c8d2
--- /dev/null
+++ b/arch/x86/faults.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <debug.h>
+#include <arch/x86.h>
+#include <kernel/thread.h>
+
+static void dump_fault_frame(struct x86_iframe *frame)
+{
+ dprintf(CRITICAL, " CS: %04x EIP: %08x EFL: %08x CR2: %08x\n",
+ frame->cs, frame->eip, frame->eflags, x86_get_cr2());
+ dprintf(CRITICAL, "EAX: %08x ECX: %08x EDX: %08x EBX: %08x\n",
+ frame->eax, frame->ecx, frame->edx, frame->ebx);
+ dprintf(CRITICAL, "ESP: %08x EBP: %08x ESI: %08x EDI: %08x\n",
+ frame->esp, frame->ebp, frame->esi, frame->edi);
+ dprintf(CRITICAL, " DS: %04x ES: %04x FS: %04x GS: %04x\n",
+ frame->ds, frame->es, frame->fs, frame->gs);
+
+ // dump the bottom of the current stack
+ addr_t stack = (addr_t) frame; //(addr_t) (((uint32_t *) frame) + (sizeof(struct x86_iframe) / sizeof(uint32_t) - 1));
+
+ if (stack != 0) {
+ dprintf(CRITICAL, "bottom of stack at 0x%08x:\n", (unsigned int)stack);
+ hexdump((void *)stack, 192);
+ }
+}
+
+static void exception_die(struct x86_iframe *frame, const char *msg)
+{
+ inc_critical_section();
+ dprintf(CRITICAL, msg);
+ dump_fault_frame(frame);
+
+ for (;;) {
+ x86_cli();
+ x86_hlt();
+ }
+}
+
+void x86_syscall_handler(struct x86_iframe *frame)
+{
+ exception_die(frame, "unhandled syscall, halting\n");
+}
+
+void x86_gpf_handler(struct x86_iframe *frame)
+{
+ exception_die(frame, "unhandled gpf, halting\n");
+}
+
+void x86_invop_handler(struct x86_iframe *frame)
+{
+ exception_die(frame, "unhandled invalid op, halting\n");
+}
+
+void x86_unhandled_exception(struct x86_iframe *frame)
+{
+ exception_die(frame, "unhandled exception, halting\n");
+}
diff --git a/arch/x86/include/arch/arch_thread.h b/arch/x86/include/arch/arch_thread.h
new file mode 100644
index 0000000..9347bcd
--- /dev/null
+++ b/arch/x86/include/arch/arch_thread.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __X86_ARCH_THREAD_H
+#define __X86_ARCH_THREAD_H
+
+struct arch_thread {
+ vaddr_t esp;
+
+ // TODO: fpu context
+};
+
+#endif
+
diff --git a/arch/x86/include/arch/defines.h b/arch/x86/include/arch/defines.h
new file mode 100644
index 0000000..814fcc9
--- /dev/null
+++ b/arch/x86/include/arch/defines.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_CPU_H
+#define __ARCH_CPU_H
+
+#define PAGE_SIZE 4096
+
+// TODO: define to resolve to platform setup discovered value
+#define CACHE_LINE 32
+
+#endif
+
diff --git a/arch/x86/include/arch/x86.h b/arch/x86/include/arch/x86.h
new file mode 100644
index 0000000..4cf65d9
--- /dev/null
+++ b/arch/x86/include/arch/x86.h
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_X86_H
+#define __ARCH_X86_H
+
+#include <compiler.h>
+#include <sys/types.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void x86_mmu_init(void);
+
+struct x86_iframe {
+ uint32_t pivot; // stack switch pivot
+ uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // pushed by common handler using pusha
+ uint32_t ds, es, fs, gs; // pushed by common handler
+ uint32_t vector; // pushed by stub
+ uint32_t err_code; // pushed by interrupt or stub
+ uint32_t eip, cs, eflags; // pushed by interrupt
+ uint32_t user_esp, user_ss; // pushed by interrupt if priv change occurs
+};
+
+/*
+ * x86 TSS structure
+ */
+typedef struct {
+ uint16_t backlink, __blh;
+ uint32_t esp0;
+ uint16_t ss0, __ss0h;
+ uint32_t esp1;
+ uint16_t ss1, __ss1h;
+ uint32_t esp2;
+ uint16_t ss2, __ss2h;
+ uint32_t cr3;
+ uint32_t eip;
+ uint32_t eflags;
+ uint32_t eax, ecx, edx, ebx;
+ uint32_t esp, ebp, esi, edi;
+ uint16_t es, __esh;
+ uint16_t cs, __csh;
+ uint16_t ss, __ssh;
+ uint16_t ds, __dsh;
+ uint16_t fs, __fsh;
+ uint16_t gs, __gsh;
+ uint16_t ldt, __ldth;
+ uint16_t trace, bitmap;
+
+ uint8_t tss_bitmap[8192];
+} __PACKED tss_t;
+
+#define X86_CR0_PE 0x00000001 /* protected mode enable */
+#define X86_CR0_MP 0x00000002 /* monitor coprocessor */
+#define X86_CR0_EM 0x00000004 /* emulation */
+#define X86_CR0_TS 0x00000008 /* task switched */
+#define X86_CR0_WP 0x00010000 /* supervisor write protect */
+#define X86_CR0_NW 0x20000000 /* not write-through */
+#define X86_CR0_CD 0x40000000 /* cache disable */
+#define X86_CR0_PG 0x80000000 /* enable paging */
+
+static inline void set_in_cr0(uint32_t mask) {
+ __asm__ __volatile__ (
+ "movl %%cr0,%%eax \n\t"
+ "orl %0,%%eax \n\t"
+ "movl %%eax,%%cr0 \n\t"
+ : : "irg" (mask)
+ :"ax");
+}
+
+static inline void clear_in_cr0(uint32_t mask) {
+ __asm__ __volatile__ (
+ "movl %%cr0, %%eax \n\t"
+ "andl %0, %%eax \n\t"
+ "movl %%eax, %%cr0 \n\t"
+ : : "irg" (~mask)
+ : "ax");
+}
+
+static inline void x86_clts(void) {__asm__ __volatile__ ("clts"); }
+static inline void x86_hlt(void) {__asm__ __volatile__ ("hlt"); }
+static inline void x86_sti(void) {__asm__ __volatile__ ("sti"); }
+static inline void x86_cli(void) {__asm__ __volatile__ ("cli"); }
+static inline void x86_ltr(uint16_t sel) {
+ __asm__ __volatile__ ("ltr %%ax" :: "a" (sel));
+}
+
+static inline uint32_t x86_get_cr2(void) {
+ uint32_t rv;
+
+ __asm__ __volatile__ (
+ "movl %%cr2, %0"
+ : "=r" (rv)
+ );
+
+ return rv;
+}
+
+#define rdtsc(low,high) \
+ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
+
+#define rdtscl(low) \
+ __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx")
+
+#define rdtscll(val) \
+ __asm__ __volatile__("rdtsc" : "=A" (val))
+
+static inline uint8_t inp(uint16_t _port) {
+ uint8_t rv;
+ __asm__ __volatile__ ("inb %1, %0"
+ : "=a" (rv)
+ : "d" (_port));
+ return(rv);
+}
+
+static inline uint16_t inpw (uint16_t _port) {
+ uint16_t rv;
+ __asm__ __volatile__ ("inw %1, %0"
+ : "=a" (rv)
+ : "d" (_port));
+ return(rv);
+}
+
+static inline uint32_t inpd(uint16_t _port) {
+ uint32_t rv;
+ __asm__ __volatile__ ("inl %1, %0"
+ : "=a" (rv)
+ : "d" (_port));
+ return(rv);
+}
+
+static inline void outp(uint16_t _port, uint8_t _data) {
+ __asm__ __volatile__ ("outb %1, %0"
+ :
+ : "d" (_port),
+ "a" (_data));
+}
+
+static inline void outpw(uint16_t _port, uint16_t _data) {
+ __asm__ __volatile__ ("outw %1, %0"
+ :
+ : "d" (_port),
+ "a" (_data));
+}
+
+static inline void outpd(uint16_t _port, uint32_t _data) {
+ __asm__ __volatile__ ("outl %1, %0"
+ :
+ : "d" (_port),
+ "a" (_data));
+}
+
+static inline void inprep(uint16_t _port, uint8_t *_buffer, uint32_t _reads) {
+ __asm__ __volatile__ ("pushal \n\t"
+ "pushfl \n\t"
+ "cli \n\t"
+ "cld \n\t"
+ "rep insb \n\t"
+ "popfl \n\t"
+ "popal"
+ :
+ : "d" (_port),
+ "D" (_buffer),
+ "c" (_reads));
+}
+
+static inline void outprep(uint16_t _port, uint8_t *_buffer, uint32_t _writes) {
+ __asm__ __volatile__ ("pushal \n\t"
+ "pushfl \n\t"
+ "cli \n\t"
+ "cld \n\t"
+ "rep outsb \n\t"
+ "popfl \n\t"
+ "popal"
+ :
+ : "d" (_port),
+ "S" (_buffer),
+ "c" (_writes));
+}
+
+static inline void inpwrep(uint16_t _port, uint16_t *_buffer, uint32_t _reads) {
+ __asm__ __volatile__ ("pushal \n\t"
+ "pushfl \n\t"
+ "cli \n\t"
+ "cld \n\t"
+ "rep insw \n\t"
+ "popfl \n\t"
+ "popal"
+ :
+ : "d" (_port),
+ "D" (_buffer),
+ "c" (_reads));
+}
+
+static inline void outpwrep(uint16_t _port, uint16_t *_buffer,
+ uint32_t _writes) {
+ __asm__ __volatile__ ("pushal \n\t"
+ "pushfl \n\t"
+ "cli \n\t"
+ "cld \n\t"
+ "rep outsw \n\t"
+ "popfl \n\t"
+ "popal"
+ :
+ : "d" (_port),
+ "S" (_buffer),
+ "c" (_writes));
+}
+
+static inline void inpdrep(uint16_t _port, uint32_t *_buffer,
+ uint32_t _reads) {
+ __asm__ __volatile__ ("pushal \n\t"
+ "pushfl \n\t"
+ "cli \n\t"
+ "cld \n\t"
+ "rep insl \n\t"
+ "popfl \n\t"
+ "popal"
+ :
+ : "d" (_port),
+ "D" (_buffer),
+ "c" (_reads));
+}
+
+static inline void outpdrep(uint16_t _port, uint32_t *_buffer,
+ uint32_t _writes) {
+ __asm__ __volatile__ ("pushal \n\t"
+ "pushfl \n\t"
+ "cli \n\t"
+ "cld \n\t"
+ "rep outsl \n\t"
+ "popfl \n\t"
+ "popal"
+ :
+ : "d" (_port),
+ "S" (_buffer),
+ "c" (_writes));
+}
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/arch/x86/include/arch/x86/descriptor.h b/arch/x86/include/arch/x86/descriptor.h
new file mode 100644
index 0000000..1b2580d
--- /dev/null
+++ b/arch/x86/include/arch/x86/descriptor.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_DESCRIPTOR_H
+#define __ARCH_DESCRIPTOR_H
+
+#include <sys/types.h>
+
+/*
+ * System Selectors
+ */
+#define CODE_SELECTOR 0x08
+#define DATA_SELECTOR 0x10
+#define VIDEO_SELECTOR 0x18
+#define TSS_SELECTOR 0x30
+
+#define USER_CODE_SELECTOR 0x23
+#define USER_DATA_SELECTOR 0x2b
+
+/*
+ * Descriptor Types
+ */
+#define SEG_TYPE_TSS 0x9
+#define SEG_TYPE_TSS_BUSY 0xb
+#define SEG_TYPE_TASK_GATE 0x5
+#define SEG_TYPE_INT_GATE 0xe // 32 bit
+#define SEG_TYPE_DATA_RW 0x2
+#define SEG_TYPE_CODE_RW 0xa
+
+typedef uint16_t seg_sel_t;
+
+void set_global_desc(seg_sel_t sel, void *base, uint32_t limit,
+ uint8_t present, uint8_t ring, uint8_t sys, uint8_t type, uint8_t gran, uint8_t bits);
+
+#endif
diff --git a/arch/x86/include/arch/x86/mmu.h b/arch/x86/include/arch/x86/mmu.h
new file mode 100644
index 0000000..719710c
--- /dev/null
+++ b/arch/x86/include/arch/x86/mmu.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2008 Travis Geiselbrecht
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_ARM_MMU_H
+#define __ARCH_ARM_MMU_H
+
+#include <sys/types.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void arm_mmu_init(void);
+
+#define MMU_FLAG_CACHED 0x1
+#define MMU_FLAG_BUFFERED 0x2
+#define MMU_FLAG_READWRITE 0x4
+void arm_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/arch/x86/include/arch/x86/ops.h b/arch/x86/include/arch/x86/ops.h
new file mode 100644
index 0000000..d2bbc24
--- /dev/null
+++ b/arch/x86/include/arch/x86/ops.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __ARCH_X86_OPS_H
+#define __ARHC_X86_OPS_H
+
+#if 0
+#include <compiler.h>
+
+#ifndef ASSEMBLY
+
+// override of some routines
+__GNU_INLINE __ALWAYS_INLINE extern inline void arch_enable_ints(void)
+{
+ __asm__ __volatile__ ("sti");
+}
+
+__GNU_INLINE __ALWAYS_INLINE extern inline void arch_disable_ints(void)
+{
+ __asm__ __volatile__ ("cli");
+}
+
+#endif
+#endif
+
+#endif
+
diff --git a/arch/x86/kernel.ld b/arch/x86/kernel.ld
new file mode 100644
index 0000000..1e3abba
--- /dev/null
+++ b/arch/x86/kernel.ld
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+ENTRY(_start)
+SECTIONS
+{
+ .text 0x0200000 : {
+ *(.text)
+ *(SORT(.text$*))
+ *(.gnu.linkonce.t.*)
+
+ __ctor_list = .;
+ *(SORT(.ctor*))
+ __ctor_end = .;
+ __dtor_list = .;
+ *(SORT(.dtor*))
+ __dtor_end = .;
+
+ . = ALIGN(4096);
+ }
+
+ __data_start = .;
+ .data : { *(.data .data.* .gnu.linkonce.d.*) }
+ .stab : { *(.stab) }
+ .stabst : { *(.stabstr) }
+
+ . = ALIGN(4096);
+ __data_end = .;
+
+ .rdata : {
+ *(.rdata)
+ *(SORT(.rdata$*))
+ *(.rodata*)
+ *(.gnu.linkonce.r.*)
+ __commands_start = .;
+ KEEP (*(.commands))
+ __commands_end = .;
+ . = ALIGN(4);
+ __apps_start = .;
+ KEEP (*(.apps))
+ __apps_end = .;
+
+ . = ALIGN(4096);
+ }
+
+ __bss_start = .;
+ .bss : {
+ *(.bss*)
+ *(.gnu.linkonce.b.*)
+ *(COMMON)
+
+ . = ALIGN(4096);
+ }
+ __bss_end = .;
+
+ /*. += 0x2000;
+ _kstack = .;
+ . += 0x1000;*/
+
+ _end = .;
+
+ /DISCARD/ : { *(.comment .note .eh_frame) }
+}
diff --git a/arch/x86/mmu.c b/arch/x86/mmu.c
new file mode 100644
index 0000000..6cefe67
--- /dev/null
+++ b/arch/x86/mmu.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <debug.h>
+#include <sys/types.h>
+#include <compiler.h>
+#include <arch.h>
+#include <arch/x86.h>
+#include <arch/x86/mmu.h>
+
+void x86_mmu_map_section(addr_t paddr, addr_t vaddr, uint flags)
+{
+ // TODO: stuff
+ //x86_invalidate_tlb();
+}
+
+void x86_mmu_init(void)
+{
+ // TODO: stuff
+}
+
+void arch_disable_mmu(void)
+{
+ // TODO: stuff
+}
diff --git a/arch/x86/ops.S b/arch/x86/ops.S
new file mode 100644
index 0000000..17c08ae
--- /dev/null
+++ b/arch/x86/ops.S
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+
+.text
+
+/* void arch_enable_ints(void); */
+FUNCTION(arch_enable_ints)
+ sti
+ ret
+
+/* void arch_disable_ints(void); */
+FUNCTION(arch_disable_ints)
+ cli
+ ret
+
+/* int atomic_swap(int *ptr, int val); */
+FUNCTION(atomic_swap)
+ movl 4(%esp), %edx
+ movl 8(%esp), %eax
+ xchgl %eax, (%edx)
+ ret
+
+/* int atomic_add(int *ptr, int val); */
+FUNCTION(atomic_add)
+ movl 4(%esp), %edx
+ movl 8(%esp), %eax
+ lock
+ xadd %eax, (%edx)
+ ret
+
+/* int atomic_and(int *ptr, int val); */
+FUNCTION(atomic_and)
+ movl 4(%esp), %edx
+ movl (%edx), %eax
+0:
+ movl %eax, %ecx
+ andl 8(%esp), %ecx
+ lock
+ cmpxchgl %ecx, (%edx)
+ jnz 1f /* static prediction: branch forward not taken */
+ ret
+1:
+ jmp 0b
+
+
+/* int atomic_or(int *ptr, int val); */
+FUNCTION(atomic_or)
+movl 4(%esp), %edx
+ movl (%edx), %eax
+0:
+ movl %eax, %ecx
+ orl 8(%esp), %ecx
+ lock
+ cmpxchgl %ecx, (%edx)
+ jnz 1f /* static prediction: branch forward not taken */
+ ret
+1:
+ jmp 0b
+
+/* void arch_idle(); */
+FUNCTION(arch_idle)
+ hlt
+ ret
+
+/* void arch_switch_stacks_and_call(addr_t call, addr_t stack) */
+FUNCTION(arch_switch_stacks_and_call)
+ movl 4(%esp), %eax
+ movl 8(%esp), %edx
+ movl %edx, %esp
+ call *%eax /* perhaps this should be a jmp? it's not used anywhere so I don't know. */
diff --git a/arch/x86/rules.mk b/arch/x86/rules.mk
new file mode 100644
index 0000000..943ccd8
--- /dev/null
+++ b/arch/x86/rules.mk
@@ -0,0 +1,35 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+INCLUDES += \
+ -I$(LOCAL_DIR)/include
+
+BOOTOBJS += \
+ $(LOCAL_DIR)/crt0.o
+
+OBJS += \
+ $(LOCAL_DIR)/arch.o \
+ $(LOCAL_DIR)/asm.o \
+ $(LOCAL_DIR)/cache.o \
+ $(LOCAL_DIR)/cache-ops.o \
+ $(LOCAL_DIR)/ops.o \
+ $(LOCAL_DIR)/thread.o \
+ $(LOCAL_DIR)/mmu.o \
+ $(LOCAL_DIR)/faults.o \
+ $(LOCAL_DIR)/descriptor.o
+
+# set the default toolchain to x86 elf and set a #define
+TOOLCHAIN_PREFIX ?= #x86-elf-
+
+LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(CFLAGS) -print-libgcc-file-name)
+#$(info LIBGCC = $(LIBGCC))
+
+# potentially generated files that should be cleaned out with clean make rule
+GENERATED += \
+ $(BUILDDIR)/kernel.ld
+
+# rules for generating the linker scripts
+
+$(BUILDDIR)/kernel.ld: $(LOCAL_DIR)/kernel.ld
+ @echo generating $@
+ @$(MKDIR)
+ $(NOECHO)cp $< $@
diff --git a/arch/x86/thread.c b/arch/x86/thread.c
new file mode 100644
index 0000000..f2c2f84
--- /dev/null
+++ b/arch/x86/thread.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <debug.h>
+#include <kernel/thread.h>
+#include <arch/x86.h>
+#include <arch/x86/descriptor.h>
+
+/*struct context_switch_frame {
+ uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
+ uint32_t ds, es, fs, gs;
+ uint32_t eip, cs, eflags;
+};*/
+struct context_switch_frame {
+ uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
+ uint32_t eflags;
+ uint32_t eip;
+};
+
+extern void x86_context_switch(addr_t *old_sp, addr_t new_sp);
+
+static void initial_thread_func(void) __NO_RETURN;
+static void initial_thread_func(void)
+{
+ int ret;
+
+// dprintf("initial_thread_func: thread %p calling %p with arg %p\n", current_thread, current_thread->entry, current_thread->arg);
+// dump_thread(current_thread);
+
+ /* exit the implicit critical section we're within */
+ exit_critical_section();
+
+ ret = current_thread->entry(current_thread->arg);
+
+// dprintf("initial_thread_func: thread %p exiting with %d\n", current_thread, ret);
+
+ thread_exit(ret);
+}
+
+void arch_thread_initialize(thread_t *t)
+{
+ // create a default stack frame on the stack
+ vaddr_t stack_top = (vaddr_t)t->stack + t->stack_size;
+
+ // make sure the top of the stack is 8 byte aligned for EABI compliance
+ stack_top = ROUNDDOWN(stack_top, 8);
+
+ struct context_switch_frame *frame = (struct context_switch_frame *)(stack_top);
+ frame--;
+
+ // fill it in
+ memset(frame, 0, sizeof(*frame));
+
+ frame->eip = (vaddr_t) &initial_thread_func;
+ frame->eflags = 0x3002; // IF = 0, NT = 0, IOPL = 3
+ //frame->cs = CODE_SELECTOR;
+ //frame->fs = DATA_SELECTOR;
+ //frame->gs = DATA_SELECTOR;
+ //frame->es = DATA_SELECTOR;
+ //frame->ds = DATA_SELECTOR;
+
+ // set the stack pointer
+ t->arch.esp = (vaddr_t)frame;
+}
+
+void arch_context_switch(thread_t *oldthread, thread_t *newthread)
+{
+ //dprintf(DEBUG, "arch_context_switch: old %p (%s), new %p (%s)\n", oldthread, oldthread->name, newthread, newthread->name);
+
+ __asm__ __volatile__ (
+ "pushl $1f \n\t"
+ "pushf \n\t"
+ "pusha \n\t"
+ "movl %%esp,(%%edx) \n\t"
+ "movl %%eax,%%esp \n\t"
+ "popa \n\t"
+ "popf \n\t"
+ "ret \n\t"
+ "1: \n\t"
+
+ :
+ : "d" (&oldthread->arch.esp), "a" (newthread->arch.esp)
+ );
+
+ /*__asm__ __volatile__ (
+ "pushf \n\t"
+ "pushl %%cs \n\t"
+ "pushl $1f \n\t"
+ "pushl %%gs \n\t"
+ "pushl %%fs \n\t"
+ "pushl %%es \n\t"
+ "pushl %%ds \n\t"
+ "pusha \n\t"
+ "movl %%esp,(%%edx) \n\t"
+ "movl %%eax,%%esp \n\t"
+ "popa \n\t"
+ "popl %%ds \n\t"
+ "popl %%es \n\t"
+ "popl %%fs \n\t"
+ "popl %%gs \n\t"
+ "iret \n\t"
+ "1: "
+ :
+ : "d" (&oldthread->arch.esp), "a" (newthread->arch.esp)
+ );*/
+}
+
diff --git a/include/endian.h b/include/endian.h
index 30623b2..34bef6e 100644
--- a/include/endian.h
+++ b/include/endian.h
@@ -40,6 +40,10 @@
#define BYTE_ORDER LITTLE_ENDIAN
#endif
+#if defined(__i386__) || defined(_X86_)
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif
+
#ifndef BYTE_ORDER
#error "need to get the BYTE_ORDER define from somewhere"
#endif
diff --git a/lib/heap/heap.c b/lib/heap/heap.c
index c67bc25..afcb975 100644
--- a/lib/heap/heap.c
+++ b/lib/heap/heap.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008 Travis Geiselbrecht
+ * Copyright (c) 2009 Corey Tabaka
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
@@ -45,10 +46,10 @@
extern int _end;
// end of memory
-extern int _end_of_ram;
+extern int _heap_end;
#define HEAP_START ((unsigned long)&_end)
-#define HEAP_LEN ((size_t)&_end_of_ram - (size_t)&_end)
+#define HEAP_LEN ((size_t)_heap_end - (size_t)&_end)
#endif
struct free_heap_chunk {
diff --git a/lib/libc/string/arch/x86/memcpy.S b/lib/libc/string/arch/x86/memcpy.S
new file mode 100644
index 0000000..a2a2a44
--- /dev/null
+++ b/lib/libc/string/arch/x86/memcpy.S
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+
+/* TODO: */
+
+.text
+.align 2
+
+/* void bcopy(const void *src, void *dest, size_t n); */
+FUNCTION(bcopy)
+ ret
+
+/* void *memcpy(void *dest, const void *src, size_t n); */
+FUNCTION(memmove)
+FUNCTION(memcpy)
+ ret
+
diff --git a/lib/libc/string/arch/x86/memset.S b/lib/libc/string/arch/x86/memset.S
new file mode 100644
index 0000000..b4bccc9
--- /dev/null
+++ b/lib/libc/string/arch/x86/memset.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <asm.h>
+
+/* TODO: */
+
+.text
+.align 2
+
+/* void bzero(void *s, size_t n); */
+FUNCTION(bzero)
+ ret
+
+/* void *memset(void *s, int c, size_t n); */
+FUNCTION(memset)
+ ret
+
diff --git a/lib/libc/string/arch/x86/rules.mk b/lib/libc/string/arch/x86/rules.mk
new file mode 100644
index 0000000..b3a5aa9
--- /dev/null
+++ b/lib/libc/string/arch/x86/rules.mk
@@ -0,0 +1,11 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ASM_STRING_OPS := #bcopy bzero memcpy memmove memset
+
+OBJS += \
+ #$(LOCAL_DIR)/memcpy.o \
+ #$(LOCAL_DIR)/memset.o
+
+# filter out the C implementation
+C_STRING_OPS := $(filter-out $(ASM_STRING_OPS),$(C_STRING_OPS))
+
diff --git a/platform/x86/console.c b/platform/x86/console.c
new file mode 100644
index 0000000..0ce5527
--- /dev/null
+++ b/platform/x86/console.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <arch/x86.h>
+#include <platform/x86.h>
+#include <platform/console.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+/* CGA values */
+#define CURSOR_START 0x0A
+#define CURSOR_END 0x0B
+#define VIDEO_ADDRESS_MSB 0x0C
+#define VIDEO_ADDRESS_LSB 0x0D
+#define CURSOR_POS_MSB 0x0E
+#define CURSOR_POS_LSB 0x0F
+
+/* curr settings */
+static unsigned char curr_x;
+static unsigned char curr_y;
+static unsigned char curr_start;
+static unsigned char curr_end;
+static unsigned char curr_attr;
+
+/* video page buffer */
+#define VPAGE_SIZE 2048
+#define PAGE_MAX 8
+
+static int active_page = 0;
+static int visual_page = 0;
+
+static int curs_x[PAGE_MAX];
+static int curs_y[PAGE_MAX];
+
+static struct {
+ int x1, y1, x2, y2;
+} view_window = {
+ 0, 0, 79, 24
+};
+
+void platform_init_console(void)
+{
+ curr_save();
+ window(0, 0, 79, 24);
+ clear();
+ place(0, 0);
+}
+
+void set_visual_page(int page)
+{
+ unsigned short page_offset = page*VPAGE_SIZE;
+ visual_page = page;
+
+ outp(CGA_INDEX_REG, VIDEO_ADDRESS_LSB);
+ outp(CGA_DATA_REG, page_offset & 0xFF);
+ outp(CGA_INDEX_REG, VIDEO_ADDRESS_MSB);
+ outp(CGA_DATA_REG, (page_offset >> 8) & 0xFF);
+}
+
+void set_active_page(int page)
+{
+ curs_x[active_page] = curr_x;
+ curs_y[active_page] = curr_y;
+ curr_x = curs_x[page];
+ curr_y = curs_y[page];
+ active_page = page;
+}
+
+int get_visual_page(void)
+{
+ return visual_page;
+}
+
+int get_active_page(void)
+{
+ return active_page;
+}
+
+void place(int x,int y)
+{
+ unsigned short cursor_word = x + y*80 + active_page*VPAGE_SIZE;
+
+ /*
+ * program CGA using index reg, then data reg
+ */
+ outp(CGA_INDEX_REG, CURSOR_POS_LSB);
+ outp(CGA_DATA_REG, cursor_word & 0xFF);
+ outp(CGA_INDEX_REG, CURSOR_POS_MSB);
+ outp(CGA_DATA_REG, (cursor_word >> 8) & 0xFF);
+
+ curr_x = x;
+ curr_y = y;
+}
+
+void cursor(int start,int end)
+{
+ outp(CGA_INDEX_REG, CURSOR_START);
+ outp(CGA_DATA_REG, start);
+ outp(CGA_INDEX_REG, CURSOR_END);
+ outp(CGA_DATA_REG, end);
+}
+
+void curr_save(void)
+{
+ /* grab some info from the bios data area (these should be defined in memmap.h */
+ curr_attr = *((unsigned char *)0xB8000 + 159);
+ curr_x = *((unsigned char *)0x00450);
+ curr_y = *((unsigned char *)0x00451);
+ curr_end = *((unsigned char *)0x00460);
+ curr_start = *((unsigned char *)0x00461);
+ active_page = visual_page = 0;
+}
+
+void curr_restore(void)
+{
+ *((unsigned char *)0x00450) = curr_x;
+ *((unsigned char *)0x00451) = curr_y;
+
+ place(curr_x, curr_y);
+ cursor(curr_start, curr_end);
+}
+
+void window(int x1, int y1, int x2, int y2) {
+ view_window.x1 = x1;
+ view_window.y1 = y1;
+ view_window.x2 = x2;
+ view_window.y2 = y2;
+
+ //place(x1, y1);
+}
+
+void _clear(char c,char attr,int x1,int y1,int x2,int y2)
+{
+ register int i,j;
+ unsigned short w = attr;
+
+ w <<= 8; w |= c;
+ for (i = x1; i <= x2; i++) {
+ for (j = y1; j <= y2; j++) {
+ *((unsigned short *)(0xB8000 + 2*i+160*j + 2*active_page*VPAGE_SIZE)) = w;
+ }
+ }
+
+ place(x1,y1);
+ curr_y = y1;
+ curr_x = x1;
+}
+
+void clear()
+{
+ _clear(' ', curr_attr, view_window.x1, view_window.y1, view_window.x2,
+ view_window.y2);
+}
+
+void _scroll(char attr, int x1, int y1, int x2, int y2)
+{
+ register int x,y;
+ unsigned short xattr = attr << 8,w;
+ unsigned char *v = (unsigned char *)(0xB8000 + active_page*(2*VPAGE_SIZE));
+
+ for (y = y1+1; y <= y2; y++) {
+ for (x = x1; x <= x2; x++) {
+ w = *((unsigned short *) (v + 2*(y*80+x)));
+ *((unsigned short *)(v + 2*((y-1)*80+x))) = w;
+ }
+ }
+
+ for (x = x1; x <= x2; x++) {
+ *((unsigned short *)(v + 2*((y-1)*80+x))) = xattr;
+ }
+}
+
+void scroll(void)
+{
+ _scroll(curr_attr, view_window.x1, view_window.y1, view_window.x2,
+ view_window.y2);
+}
+
+void cputc(char c)
+{
+ static unsigned short scan_x, x, y;
+ unsigned char *v = (unsigned char *)(0xB8000 + active_page*(2*VPAGE_SIZE));
+ x = curr_x;
+ y = curr_y;
+
+ switch (c) {
+ case '\t':
+ x += 8;
+ if (x >= view_window.x2+1) {
+ x = view_window.x1;
+ if (y == view_window.y2) {
+ scroll();
+ } else {
+ y++;
+ }
+ } else {
+ scan_x = 0;
+
+ while ((scan_x+8) < x) {
+ scan_x += 8;
+ }
+
+ x = scan_x;
+ }
+ break;
+
+ case '\n':
+ x = view_window.x1;
+ if (y == view_window.y2) {
+ scroll();
+ } else {
+ y++;
+ }
+ break;
+
+ case '\b':
+ x--;
+ *(v + 2*(x + y*80)) = ' ';
+ break;
+
+ default:
+ *(v + 2*(x + y*80)) = c;
+ x++;
+
+ if (x >= view_window.x2+1) {
+ x = view_window.x1;
+ if (y == view_window.y2) {
+ scroll();
+ } else {
+ y++;
+ }
+ }
+ }
+
+ place(x, y);
+}
+
+void cputs(char *s)
+{
+ char c;
+ while (*s != '\0') {
+ c = *s++;
+ cputc(c);
+ }
+}
+
+void puts_xy(int x,int y,char attr,char *s)
+{
+ unsigned char *v = (unsigned char *)(0xB8000 + (80*y+x)*2 + active_page*(2*VPAGE_SIZE));
+ while (*s != 0) {
+ *v = *s; s++; v++;
+ *v = attr; v++;
+ }
+}
+
+void putc_xy(int x, int y, char attr, char c)
+{
+ unsigned char *v = (unsigned char *)(0xB8000 + (80*y+x)*2 + active_page*(2*VPAGE_SIZE));
+ *v = c; v++;
+ *v = attr;
+}
+
+int printf_xy(int x, int y, char attr, char *fmt, ...)
+{
+ char cbuf[200];
+ va_list parms;
+ int result;
+
+ va_start(parms, fmt);
+ result = vsprintf(cbuf, fmt, parms);
+ va_end(parms);
+
+ puts_xy(x, y, attr, cbuf);
+
+ return result;
+}
diff --git a/platform/x86/debug.c b/platform/x86/debug.c
new file mode 100644
index 0000000..0bc4999
--- /dev/null
+++ b/platform/x86/debug.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <stdarg.h>
+#include <reg.h>
+#include <printf.h>
+#include <kernel/thread.h>
+#include <arch/x86.h>
+#include <platform/x86/memmap.h>
+#include <platform/console.h>
+#include <platform/keyboard.h>
+#include <platform/debug.h>
+
+void _dputc(char c)
+{
+ cputc(c);
+}
+
+int dgetc(char *c)
+{
+ return platform_read_key(c);
+}
+
+void debug_dump_regs(void)
+{
+}
+
+void platform_halt(void)
+{
+ for(;;) {
+ x86_cli();
+ x86_hlt();
+ }
+}
+
+void debug_dump_memory_bytes(void *mem, int len)
+{
+}
+
+void debug_dump_memory_halfwords(void *mem, int len)
+{
+}
+
+void debug_dump_memory_words(void *mem, int len)
+{
+}
+
+void debug_set_trace_level(int trace_type, int level)
+{
+}
+
+uint32_t debug_cycle_count()
+{
+ uint32_t timestamp;
+ rdtscl(timestamp);
+
+ return timestamp;
+}
diff --git a/platform/x86/include/platform/console.h b/platform/x86/include/platform/console.h
new file mode 100644
index 0000000..3a1b802
--- /dev/null
+++ b/platform/x86/include/platform/console.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_CONSOLE_H
+#define __PLATFORM_CONSOLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void platform_init_console(void);
+
+void set_visual_page(int page);
+void set_active_page(int page);
+
+int get_visual_page(void);
+int get_active_page(void);
+
+void place(int x,int y);
+void cursor(int start, int end);
+
+void _clear(char c, char attr, int x1, int y1, int x2, int y2);
+void clear(void);
+
+void _scroll(char attr, int x1, int y1, int x2, int y2);
+void scroll(void);
+
+void curr_save(void);
+void curr_restore(void);
+
+void cputc(char c);
+void cputs(char *s);
+
+void window(int x1, int y1, int x2, int y2);
+
+void putc_xy(int x, int y, char attr, char c);
+void puts_xy(int x, int y, char attr, char *s);
+
+int printf_xy(int x, int y, char attr, char *fmt, ...) __PRINTFLIKE(4, 5);
+
+#define CURSOR_BLOCK() cursor(0, 15);
+#define CURSOR_OFF() cursor(16, 16);
+#define CURSOR_STD() cursor(14, 15);
+
+/* text colors */
+#define BLACK 0
+#define BLUE 1
+#define GREEN 2
+#define CYAN 3
+#define RED 4
+#define MAGENTA 5
+#define BROWN 6
+#define LIGHTGRAY 7
+#define DARKGRAY 8
+#define LIGHTBLUE 9
+#define LIGHTGREEN 10
+#define LIGHTCYAN 11
+#define LIGHTRED 12
+#define LIGHTMAGENTA 13
+#define YELLOW 14
+#define WHITE 15
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/platform/x86/include/platform/keyboard.h b/platform/x86/include/platform/keyboard.h
new file mode 100644
index 0000000..5464995
--- /dev/null
+++ b/platform/x86/include/platform/keyboard.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_KEYBOARD_H
+#define __PLATFORM_KEYBOARD_H
+
+void platform_init_keyboard(void);
+
+int platform_read_key(char *c);
+
+#endif
diff --git a/platform/x86/include/platform/multiboot.h b/platform/x86/include/platform/multiboot.h
new file mode 100644
index 0000000..f5d3310
--- /dev/null
+++ b/platform/x86/include/platform/multiboot.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_MULTIBOOT_H
+#define __PLATFORM_MULTIBOOT_H
+
+#include <sys/types.h>
+
+/* magic number for multiboot header */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* flags for multiboot header */
+#ifdef __ELF__
+#define MULTIBOOT_HEADER_FLAGS 0x00000003
+#else
+#define MULTIBOOT_HEADER_FLAGS 0x00010003
+#endif
+
+/* magic number passed by multiboot-compliant boot loaders */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+#ifndef ASSEMBLY
+
+/* multiboot header */
+typedef struct multiboot_header
+{
+ uint32_t magic;
+ uint32_t flags;
+ uint32_t checksum;
+ uint32_t header_addr;
+ uint32_t load_addr;
+ uint32_t load_end_addr;
+ uint32_t bss_end_addr;
+ uint32_t entry_addr;
+} multiboot_header_t;
+
+/* symbol table for a.out */
+typedef struct aout_symbol_table
+{
+ uint32_t tabsize;
+ uint32_t strsize;
+ uint32_t addr;
+ uint32_t reserved;
+} aout_symbol_table_t;
+
+/* section header table for ELF */
+typedef struct elf_section_header_table
+{
+ uint32_t num;
+ uint32_t size;
+ uint32_t addr;
+ uint32_t shndx;
+} elf_section_header_table_t;
+
+/* multiboot info */
+typedef struct multiboot_info
+{
+ uint32_t flags;
+ uint32_t mem_lower;
+ uint32_t mem_upper;
+ uint32_t boot_device;
+ uint32_t cmdline;
+ uint32_t mods_count;
+ uint32_t mods_addr;
+ union
+ {
+ aout_symbol_table_t aout_sym;
+ elf_section_header_table_t elf_sec;
+ } u;
+ uint32_t mmap_length;
+ uint32_t mmap_addr;
+} multiboot_info_t;
+
+enum {
+ MB_INFO_MEM_SIZE = 0x001,
+ MB_INFO_BOOT_DEV = 0x002,
+ MB_INFO_CMD_LINE = 0x004,
+ MB_INFO_MODS = 0x008,
+ MB_INFO_SYMS = 0x010,
+ MB_INFO_MMAP = 0x020,
+ MB_INFO_DRIVES = 0x040,
+ MB_INFO_CONFIG = 0x080,
+ MB_INFO_BOOT_LOADER = 0x100,
+ MB_INFO_APM_TABLE = 0x200,
+ MB_INFO_VBE = 0x400,
+};
+
+/* module structure */
+typedef struct module
+{
+ uint32_t mod_start;
+ uint32_t mod_end;
+ uint32_t string;
+ uint32_t reserved;
+} module_t;
+
+/* memory map - be careful that the offset 0 is base_addr_low without size */
+typedef struct memory_map
+{
+ uint32_t size;
+ uint32_t base_addr_low;
+ uint32_t base_addr_high;
+ uint32_t length_low;
+ uint32_t length_high;
+ uint32_t type;
+} memory_map_t;
+
+/* memory map entry types */
+enum {
+ MB_MMAP_TYPE_AVAILABLE = 0x01,
+ MB_MMAP_TYPE_RESERVED = 0x02,
+ MB_MMAP_TYPE_ACPI_RECLAIM = 0x03,
+ MB_MMAP_TYPE_ACPI_NVS = 0x04,
+};
+
+#endif
+
+#endif
diff --git a/platform/x86/include/platform/x86.h b/platform/x86/include/platform/x86.h
new file mode 100644
index 0000000..e4a1db1
--- /dev/null
+++ b/platform/x86/include/platform/x86.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_X86_H
+#define __PLATFORM_X86_H
+
+#include <platform/x86/memmap.h>
+#include <platform/x86/iomap.h>
+
+/* NOTE: keep arch/x86/crt0.S in sync with these definitions */
+
+/* interrupts */
+#define INT_VECTORS 0x31
+
+/* defined interrupts */
+#define INT_BASE 0x20
+#define INT_PIT 0x20
+#define INT_KEYBOARD 0x21
+#define INT_PIC2 0x22
+
+#define INT_BASE2 0x28
+#define INT_CMOSRTC 0x28
+#define INT_PS2MOUSE 0x2c
+#define INT_IDE0 0x2e
+#define INT_IDE1 0x2f
+
+/* exceptions */
+#define INT_DIVIDE_0 0x00
+#define INT_DEBUG_EX 0x01
+#define INT_INVALID_OP 0x06
+#define INT_DEV_NA_EX 0x07
+
+/* faults */
+#define INT_STACK_FAULT 0x0c
+#define INT_GP_FAULT 0x0d
+#define INT_PAGE_FAULT 0x0e
+
+/* APIC vectors */
+#define INT_APIC_TIMER 0x22
+
+#define INT_SYSCALL 0x30
+
+/* PIC remap bases */
+#define PIC1_BASE 0x20
+#define PIC2_BASE 0x28
+
+#endif
+
diff --git a/platform/x86/include/platform/x86/iomap.h b/platform/x86/include/platform/x86/iomap.h
new file mode 100644
index 0000000..fe75964
--- /dev/null
+++ b/platform/x86/include/platform/x86/iomap.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __IOMAP_H
+#define __IOMAP_H
+
+/* i8253/i8254 programmable interval timer registers */
+#define I8253_CONTROL_REG 0x43
+#define I8253_DATA_REG 0x40
+
+/* i8042 keyboard controller registers */
+#define I8042_COMMAND_REG 0x64
+#define I8042_STATUS_REG 0x64
+#define I8042_DATA_REG 0x60
+
+/* CGA registers */
+#define CGA_INDEX_REG 0x3D4
+#define CGA_DATA_REG 0x3D5
+
+#endif
diff --git a/platform/x86/include/platform/x86/memmap.h b/platform/x86/include/platform/x86/memmap.h
new file mode 100644
index 0000000..ab39f35
--- /dev/null
+++ b/platform/x86/include/platform/x86/memmap.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __MEMMAP_H
+#define __MEMMAP_H
+
+/* some helpful macros */
+#define REG(x) ((volatile unsigned int *)(x))
+#define REG_H(x) ((volatile unsigned short *)(x))
+#define REG_B(x) ((volatile unsigned char *)(x))
+
+
+
+#if 0
+
+#define MEMBANK_SIZE (4*1024*1024)
+
+/* some helpful macros */
+#define REG(x) ((volatile unsigned int *)(x))
+#define REG_H(x) ((volatile unsigned short *)(x))
+#define REG_B(x) ((volatile unsigned char *)(x))
+
+/* memory map of our generic arm system */
+// XXX make more dynamic
+#define MAINMEM_BASE 0x0
+#define MAINMEM_SIZE (MEMBANK_SIZE)
+
+/* peripherals are all mapped here */
+#define PERIPHERAL_BASE (0xf0000000)
+
+/* system info */
+#define SYSINFO_REGS_BASE (PERIPHERAL_BASE)
+#define SYSINFO_REGS_SIZE MEMBANK_SIZE
+#define SYSINFO_FEATURES (SYSINFO_REGS_BASE + 0)
+#define SYSINFO_FEATURE_DISPLAY 0x00000001
+#define SYSINFO_FEATURE_CONSOLE 0x00000002
+#define SYSINFO_FEATURE_NETWORK 0x00000004
+
+ /* a write to this register latches the current emulator system time, so the next two regs can be read atomically */
+#define SYSINFO_TIME_LATCH (SYSINFO_REGS_BASE + 4)
+ /* gettimeofday() style time values */
+#define SYSINFO_TIME_SECS (SYSINFO_REGS_BASE + 8)
+#define SYSINFO_TIME_USECS (SYSINFO_REGS_BASE + 12)
+
+/* display */
+#define DISPLAY_BASE (SYSINFO_REGS_BASE + SYSINFO_REGS_SIZE)
+#define DISPLAY_SIZE MEMBANK_SIZE
+#define DISPLAY_FRAMEBUFFER DISPLAY_BASE
+#define DISPLAY_REGS_BASE (DISPLAY_BASE + DISPLAY_SIZE)
+#define DISPLAY_REGS_SIZE MEMBANK_SIZE
+ /* no display regs for now */
+
+/* console (keyboard controller */
+#define CONSOLE_REGS_BASE (DISPLAY_REGS_BASE + DISPLAY_REGS_SIZE)
+#define CONSOLE_REGS_SIZE MEMBANK_SIZE
+#define KYBD_STAT (CONSOLE_REGS_BASE + 0)
+#define KYBD_DATA (CONSOLE_REGS_BASE + 4)
+
+/* programmable timer */
+#define PIT_REGS_BASE (CONSOLE_REGS_BASE + CONSOLE_REGS_SIZE)
+#define PIT_REGS_SIZE MEMBANK_SIZE
+#define PIT_STATUS (PIT_REGS_BASE + 0) // status bit
+#define PIT_CLEAR (PIT_REGS_BASE + 4) // a nonzero write clears any pending timer
+#define PIT_CLEAR_INT (PIT_REGS_BASE + 8) // a nonzero write clears the pending interrupt
+#define PIT_INTERVAL (PIT_REGS_BASE + 12) // set the countdown interval, and what the interval is reset to if periodic
+#define PIT_START_ONESHOT (PIT_REGS_BASE + 16) // a nonzero write starts a oneshot countdown
+#define PIT_START_PERIODIC (PIT_REGS_BASE + 20) // a nonzero write starts a periodic countdown
+
+#define PIT_STATUS_ACTIVE 0x1
+#define PIT_STATUS_INT_PEND 0x2
+
+/* interrupt controller */
+#define PIC_REGS_BASE (PIT_REGS_BASE + PIT_REGS_SIZE)
+#define PIC_REGS_SIZE MEMBANK_SIZE
+
+ /* Current vector mask, read-only */
+#define PIC_MASK (PIC_REGS_BASE + 0)
+ /* Mask any of the 32 interrupt vectors by writing a 1 in the appropriate bit */
+#define PIC_MASK_LATCH (PIC_REGS_BASE + 4)
+ /* Unmask any of the 32 interrupt vectors by writing a 1 in the appropriate bit */
+#define PIC_UNMASK_LATCH (PIC_REGS_BASE + 8)
+ /* each bit corresponds to the current status of the interrupt line */
+#define PIC_STAT (PIC_REGS_BASE + 12)
+ /* one bit set for the highest priority non-masked active interrupt */
+#define PIC_CURRENT_BIT (PIC_REGS_BASE + 16)
+ /* holds the current interrupt number of the highest priority non-masked active interrupt,
+ * or 0xffffffff if no interrupt is active
+ */
+#define PIC_CURRENT_NUM (PIC_REGS_BASE + 20)
+
+ /* interrupt map */
+#define INT_PIT 0
+#define INT_KEYBOARD 1
+#define INT_NET 2
+#define PIC_MAX_INT 32
+
+/* debug interface */
+#define DEBUG_REGS_BASE (PIC_REGS_BASE + PIC_REGS_SIZE)
+#define DEBUG_REGS_SIZE MEMBANK_SIZE
+#define DEBUG_STDOUT (DEBUG_REGS_BASE + 0) /* writes to this register are sent through to stdout */
+#define DEBUG_STDIN (DEBUG_REGS_BASE + 0) /* reads from this register return the contents of stdin
+ * or -1 if no data is pending */
+#define DEBUG_REGDUMP (DEBUG_REGS_BASE + 4) /* writes to this register cause the emulator to dump registers */
+#define DEBUG_HALT (DEBUG_REGS_BASE + 8) /* writes to this register will halt the emulator */
+
+#define DEBUG_MEMDUMPADDR (DEBUG_REGS_BASE + 12) /* set the base address of memory to dump */
+#define DEBUG_MEMDUMPLEN (DEBUG_REGS_BASE + 16) /* set the length of memory to dump */
+#define DEBUG_MEMDUMP_BYTE (DEBUG_REGS_BASE + 20) /* trigger a memory dump in byte format */
+#define DEBUG_MEMDUMP_HALFWORD (DEBUG_REGS_BASE + 24) /* trigger a memory dump in halfword format */
+#define DEBUG_MEMDUMP_WORD (DEBUG_REGS_BASE + 28) /* trigger a memory dump in word format */
+
+/* lets you set the trace level of the various subsystems from within the emulator */
+/* only works on emulator builds that support dynamic trace levels */
+#define DEBUG_SET_TRACELEVEL_CPU (DEBUG_REGS_BASE + 32)
+#define DEBUG_SET_TRACELEVEL_UOP (DEBUG_REGS_BASE + 36)
+#define DEBUG_SET_TRACELEVEL_SYS (DEBUG_REGS_BASE + 40)
+#define DEBUG_SET_TRACELEVEL_MMU (DEBUG_REGS_BASE + 44)
+
+#define DEBUG_CYCLE_COUNT (DEBUG_REGS_BASE + 48)
+#define DEBUG_INS_COUNT (DEBUG_REGS_BASE + 52)
+
+/* network interface */
+#define NET_REGS_BASE (DEBUG_REGS_BASE + DEBUG_REGS_SIZE)
+#define NET_REGS_SIZE MEMBANK_SIZE
+
+#define NET_BUF_LEN 2048
+#define NET_IN_BUF_COUNT 32
+
+#define NET_HEAD (NET_REGS_BASE + 0) /* current next buffer the hardware will write to */
+#define NET_TAIL (NET_REGS_BASE + 4) /* currently selected input buffer */
+#define NET_SEND (NET_REGS_BASE + 8) /* writes to this register sends whatever is in the out buf */
+#define NET_SEND_LEN (NET_REGS_BASE + 12) /* length of packet to send */
+#define NET_OUT_BUF (NET_REGS_BASE + NET_BUF_LEN)
+
+#define NET_IN_BUF_LEN (NET_REGS_BASE + 16) /* length of the currently selected in buffer, via tail register */
+#define NET_IN_BUF (NET_REGS_BASE + NET_BUF_LEN*2)
+
+#endif // if 0
+
+#endif
diff --git a/platform/x86/interrupts.c b/platform/x86/interrupts.c
new file mode 100644
index 0000000..fa598d0
--- /dev/null
+++ b/platform/x86/interrupts.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <debug.h>
+#include <err.h>
+#include <reg.h>
+#include <kernel/thread.h>
+#include <platform/interrupts.h>
+#include <arch/ops.h>
+#include <arch/x86.h>
+#include "platform_p.h"
+#include <platform/x86.h>
+
+void x86_gpf_handler(struct x86_iframe *frame);
+void x86_invop_handler(struct x86_iframe *frame);
+void x86_unhandled_exception(struct x86_iframe *frame);
+
+#define PIC1 0x20
+#define PIC2 0xA0
+
+#define ICW1 0x11
+#define ICW4 0x01
+
+struct int_handler_struct {
+ int_handler handler;
+ void *arg;
+};
+
+static struct int_handler_struct int_handler_table[INT_VECTORS];
+
+/*
+ * Cached IRQ mask (enabled/disabled)
+ */
+static uint8_t irqMask[2];
+
+/*
+ * init the PICs and remap them
+ */
+static void map(uint32_t pic1, uint32_t pic2)
+{
+ /* send ICW1 */
+ outp(PIC1, ICW1);
+ outp(PIC2, ICW1);
+
+ /* send ICW2 */
+ outp(PIC1 + 1, pic1); /* remap */
+ outp(PIC2 + 1, pic2); /* pics */
+
+ /* send ICW3 */
+ outp(PIC1 + 1, 4); /* IRQ2 -> connection to slave */
+ outp(PIC2 + 1, 2);
+
+ /* send ICW4 */
+ outp(PIC1 + 1, 5);
+ outp(PIC2 + 1, 1);
+
+ /* disable all IRQs */
+ outp(PIC1 + 1, 0xff);
+ outp(PIC2 + 1, 0xff);
+
+ irqMask[0] = 0xff;
+ irqMask[1] = 0xff;
+}
+
+static void enable(unsigned int vector, bool enable)
+{
+ if (vector >= PIC1_BASE && vector < PIC1_BASE + 8) {
+ vector -= PIC1_BASE;
+
+ uint8_t bit = 1 << vector;
+
+ if (enable && (irqMask[0] & bit)) {
+ irqMask[0] = inp(PIC1 + 1);
+ irqMask[0] &= ~bit;
+ outp(PIC1 + 1, irqMask[0]);
+ irqMask[0] = inp(PIC1 + 1);
+ } else if (!enable && !(irqMask[0] & bit)) {
+ irqMask[0] = inp(PIC1 + 1);
+ irqMask[0] |= bit;
+ outp(PIC1 + 1, irqMask[0]);
+ irqMask[0] = inp(PIC1 + 1);
+ }
+ } else if (vector >= PIC2_BASE && vector < PIC2_BASE + 8) {
+ vector -= PIC2_BASE;
+
+ uint8_t bit = 1 << vector;
+
+ if (enable && (irqMask[1] & bit)) {
+ irqMask[1] = inp(PIC2 + 1);
+ irqMask[1] &= ~bit;
+ outp(PIC2 + 1, irqMask[1]);
+ irqMask[1] = inp(PIC2 + 1);
+ } else if (!enable && !(irqMask[1] & bit)) {
+ irqMask[1] = inp(PIC2 + 1);
+ irqMask[1] |= bit;
+ outp(PIC2 + 1, irqMask[1]);
+ irqMask[1] = inp(PIC2 + 1);
+ }
+
+ bit = 1 << (INT_PIC2 - PIC1_BASE);
+
+ if (irqMask[1] != 0xff && (irqMask[0] & bit)) {
+ irqMask[0] = inp(PIC1 + 1);
+ irqMask[0] &= ~bit;
+ outp(PIC1 + 1, irqMask[0]);
+ irqMask[0] = inp(PIC1 + 1);
+ } else if (irqMask[1] == 0 && !(irqMask[0] & bit)) {
+ irqMask[0] = inp(PIC1 + 1);
+ irqMask[0] |= bit;
+ outp(PIC1 + 1, irqMask[0]);
+ irqMask[0] = inp(PIC1 + 1);
+ }
+ } else {
+ //dprintf(DEBUG, "Invalid PIC interrupt: %02x\n", vector);
+ }
+}
+
+void issueEOI(unsigned int vector)
+{
+ if (vector >= PIC1_BASE && vector <= PIC1_BASE + 7) {
+ outp(PIC1, 0x20);
+ } else if (vector >= PIC2_BASE && vector <= PIC2_BASE + 7) {
+ outp(PIC2, 0x20);
+ outp(PIC1, 0x20); // must issue both for the second PIC
+ }
+}
+
+void platform_init_interrupts(void)
+{
+ // rebase the PIC out of the way of processor exceptions
+ map(PIC1_BASE, PIC2_BASE);
+}
+
+status_t mask_interrupt(unsigned int vector)
+{
+ if (vector >= INT_VECTORS)
+ return ERR_INVALID_ARGS;
+
+// dprintf(DEBUG, "%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+ enter_critical_section();
+
+ enable(vector, false);
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+
+void platform_mask_irqs(void)
+{
+ irqMask[0] = inp(PIC1 + 1);
+ irqMask[1] = inp(PIC2 + 1);
+
+ outp(PIC1 + 1, 0xff);
+ outp(PIC2 + 1, 0xff);
+
+ irqMask[0] = inp(PIC1 + 1);
+ irqMask[1] = inp(PIC2 + 1);
+}
+
+status_t unmask_interrupt(unsigned int vector)
+{
+ if (vector >= INT_VECTORS)
+ return ERR_INVALID_ARGS;
+
+// dprintf("%s: vector %d\n", __PRETTY_FUNCTION__, vector);
+
+ enter_critical_section();
+
+ enable(vector, true);
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+enum handler_return platform_irq(struct x86_iframe *frame)
+{
+ // get the current vector
+ unsigned int vector = frame->vector;
+
+#if THREAD_STATS
+ thread_stats.interrupts++;
+#endif
+
+ // deliver the interrupt
+ enum handler_return ret = INT_NO_RESCHEDULE;
+
+ switch (vector) {
+ case INT_GP_FAULT:
+ x86_gpf_handler(frame);
+ break;
+
+ case INT_INVALID_OP:
+ x86_invop_handler(frame);
+ break;
+
+ case INT_DIVIDE_0:
+ case INT_DEBUG_EX:
+ case INT_DEV_NA_EX:
+ case INT_PAGE_FAULT:
+ case INT_STACK_FAULT:
+ case 3:
+ x86_unhandled_exception(frame);
+ break;
+
+ default:
+ if (int_handler_table[vector].handler)
+ ret = int_handler_table[vector].handler(int_handler_table[vector].arg);
+ }
+
+ // ack the interrupt
+ issueEOI(vector);
+
+ return ret;
+}
+
+void register_int_handler(unsigned int vector, int_handler handler, void *arg)
+{
+ if (vector >= INT_VECTORS)
+ panic("register_int_handler: vector out of range %d\n", vector);
+
+ enter_critical_section();
+
+ int_handler_table[vector].arg = arg;
+ int_handler_table[vector].handler = handler;
+
+ exit_critical_section();
+}
+
+
diff --git a/platform/x86/keyboard.c b/platform/x86/keyboard.c
new file mode 100644
index 0000000..bb057b6
--- /dev/null
+++ b/platform/x86/keyboard.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <err.h>
+#include <reg.h>
+#include <debug.h>
+#include <kernel/thread.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/console.h>
+#include <platform/timer.h>
+#include <platform/x86.h>
+#include "platform_p.h"
+#include <arch/x86.h>
+
+static inline int i8042_read_data(void)
+{
+ return inp(I8042_DATA_REG);
+}
+
+static inline int i8042_read_status(void)
+{
+ return inp(I8042_STATUS_REG);
+}
+
+static inline void i8042_write_data(int val)
+{
+ outp(I8042_DATA_REG, val);
+}
+
+static inline void i8042_write_command(int val)
+{
+ outp(I8042_COMMAND_REG, val);
+}
+
+/*
+ * timeout in milliseconds
+ */
+#define I8042_CTL_TIMEOUT 500
+
+/*
+ * status register bits
+ */
+#define I8042_STR_PARITY 0x80
+#define I8042_STR_TIMEOUT 0x40
+#define I8042_STR_AUXDATA 0x20
+#define I8042_STR_KEYLOCK 0x10
+#define I8042_STR_CMDDAT 0x08
+#define I8042_STR_MUXERR 0x04
+#define I8042_STR_IBF 0x02
+#define I8042_STR_OBF 0x01
+
+/*
+ * control register bits
+ */
+#define I8042_CTR_KBDINT 0x01
+#define I8042_CTR_AUXINT 0x02
+#define I8042_CTR_IGNKEYLK 0x08
+#define I8042_CTR_KBDDIS 0x10
+#define I8042_CTR_AUXDIS 0x20
+#define I8042_CTR_XLATE 0x40
+
+/*
+ * commands
+ */
+#define I8042_CMD_CTL_RCTR 0x0120
+#define I8042_CMD_CTL_WCTR 0x1060
+#define I8042_CMD_CTL_TEST 0x01aa
+
+#define I8042_CMD_KBD_DIS 0x00ad
+#define I8042_CMD_KBD_EN 0x00ae
+#define I8042_CMD_KBD_TEST 0x01ab
+#define I8042_CMD_KBD_MODE 0x01f0
+
+/*
+ * used for flushing buffers. the i8042 internal buffer shoudn't exceed this.
+ */
+#define I8042_BUFFER_LENGTH 32
+
+static inline void delay(time_t delay) {
+ bigtime_t start = current_time();
+
+ while (start + delay > current_time());
+}
+
+/* scancodes we want to do something with that don't translate via table */
+#define SCANCODE_LSHIFT 0x2a
+#define SCANCODE_RSHIFT 0x36
+
+/* scancode translation tables */
+static const int KeyCodeSingleLower[] = {
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ -1, -1, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=','\b','\t', // 0
+ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']','\n', -1, 'a', 's', // 1
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`', -1,'\\', 'z', 'x', 'c', 'v', // 2
+ 'b', 'n', 'm', ',', '.', '/', -1, '*', -1, ' ', -1, -1, -1, -1, -1, -1, // 3
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 4
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 5
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 6
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 7
+};
+
+static const int KeyCodeMultiLower[] = {
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 1
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 2
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 3
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 4
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 5
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 6
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 7
+};
+
+static const int KeyCodeSingleUpper[] = {
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ -1, -1, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+','\b','\t', // 0
+ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}','\n', -1, 'A', 'S', // 1
+ 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', -1, '|', 'Z', 'X', 'C', 'V', // 2
+ 'B', 'N', 'M', '<', '>', '?', -1, '*', -1, ' ', -1, -1, -1, -1, -1, -1, // 3
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 4
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 5
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 6
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 7
+};
+
+static const int KeyCodeMultiUpper[] = {
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 1
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 2
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 3
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 4
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 5
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 6
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 7
+};
+
+/*
+ * state key flags
+ */
+static bool key_lshift;
+static bool key_rshift;
+
+/*
+ * key buffer
+ */
+#define KEY_BUFFER_LEN 10
+
+static uint8_t key_buffer[KEY_BUFFER_LEN];
+static int key_buffer_in_ptr, key_buffer_out_ptr;
+
+static int inq(uint8_t data) {
+ int temp;
+
+ temp = key_buffer_in_ptr + 1;
+ if (temp >= KEY_BUFFER_LEN) {
+ temp = 0;
+ }
+
+ // if in_ptr reaches out_ptr, the queue is full
+ if (temp == key_buffer_out_ptr) {
+ return -1;
+ }
+
+ key_buffer[key_buffer_in_ptr] = data;
+ key_buffer_in_ptr = temp;
+
+ return 0;
+}
+
+static int deq(void) {
+ int rv;
+
+ // if out_ptr reaches in_ptr, the queue is empty
+ if (key_buffer_out_ptr == key_buffer_in_ptr) {
+ return -1;
+ }
+
+ rv = key_buffer[key_buffer_out_ptr];
+ key_buffer_out_ptr++;
+
+ if (key_buffer_out_ptr >= KEY_BUFFER_LEN) {
+ key_buffer_out_ptr = 0;
+ }
+
+ return rv;
+}
+
+static void i8042_process_scode(uint8_t scode, unsigned int flags)
+{
+ static int lastCode = 0;
+ int keyCode;
+ uint8_t keyUpBit;
+
+ bool multi = lastCode == 0xe0;
+
+ // save the key up event bit
+ keyUpBit = scode & 0x80;
+ scode &= 0x7f;
+
+ if (scode == SCANCODE_LSHIFT) {
+ key_lshift = !keyUpBit;
+ }
+
+ if (scode == SCANCODE_RSHIFT) {
+ key_rshift = !keyUpBit;
+ }
+
+ if (key_lshift || key_rshift) {
+ keyCode = multi ? KeyCodeMultiUpper[scode] : KeyCodeSingleUpper[scode];
+ } else {
+ keyCode = multi ? KeyCodeMultiLower[scode] : KeyCodeSingleLower[scode];
+ }
+
+ /*printf_xy(71, 3, BLUE, "%02x%02x %c %c%c", multi ? lastCode : 0, scode,
+ keyCode != -1 ? (char) keyCode : ' ', key_lshift ? 'L' : ' ',
+ key_rshift ? 'R' : ' ');*/
+
+ if (keyCode != -1 && !keyUpBit) {
+ inq(keyCode);
+ }
+
+ // update the last received code
+ lastCode = scode;
+}
+
+static int i8042_wait_read(void)
+{
+ int i = 0;
+ while ((~i8042_read_status() & I8042_STR_OBF) && (i < I8042_CTL_TIMEOUT)) {
+ delay(1);
+ i++;
+ }
+ return -(i == I8042_CTL_TIMEOUT);
+}
+
+static int i8042_wait_write(void)
+{
+ int i = 0;
+ while ((i8042_read_status() & I8042_STR_IBF) && (i < I8042_CTL_TIMEOUT)) {
+ delay(1);
+ i++;
+ }
+ return -(i == I8042_CTL_TIMEOUT);
+}
+
+static int i8042_flush(void)
+{
+ unsigned char data;
+ int i = 0;
+
+ //enter_critical_section();
+
+ while ((i8042_read_status() & I8042_STR_OBF) && (i++ < I8042_BUFFER_LENGTH)) {
+ delay(1);
+ data = i8042_read_data();
+ }
+
+ //exit_critical_section();
+
+ return i;
+}
+
+static int i8042_command(uint8_t *param, int command)
+{
+ int retval = 0, i = 0;
+
+ //enter_critical_section();
+
+ retval = i8042_wait_write();
+ if (!retval) {
+ i8042_write_command(command & 0xff);
+ }
+
+ if (!retval) {
+ for (i = 0; i < ((command >> 12) & 0xf); i++) {
+ if ((retval = i8042_wait_write())) {
+ break;
+ }
+
+ i8042_write_data(param[i]);
+ }
+ }
+
+ if (!retval) {
+ for (i = 0; i < ((command & 0xf0) >> 8); i++) {
+ if ((retval = i8042_wait_read())) {
+ break;
+ }
+
+ if (i8042_read_status() & I8042_STR_AUXDATA) {
+ param[i] = ~i8042_read_data();
+ } else {
+ param[i] = i8042_read_data();
+ }
+ }
+ }
+
+ //exit_critical_section();
+
+ return retval;
+}
+
+static enum handler_return i8042_interrupt(void *arg)
+{
+ uint8_t str, data = 0;
+
+ //enter_critical_section();
+ str = i8042_read_status();
+ if (str & I8042_STR_OBF) {
+ data = i8042_read_data();
+ }
+ //exit_critical_section();
+
+ if (str & I8042_STR_OBF) {
+ i8042_process_scode(data,
+ ((str & I8042_STR_PARITY) ? I8042_STR_PARITY : 0) |
+ ((str & I8042_STR_TIMEOUT) ? I8042_STR_TIMEOUT : 0));
+ }
+
+ return INT_NO_RESCHEDULE;
+}
+
+int platform_read_key(char *c)
+{
+ int data;
+
+ enter_critical_section();
+ data = deq();
+
+ if (data != -1) {
+ *c = (char) data;
+ }
+ exit_critical_section();
+
+ return data == -1 ? -1 : 0;
+}
+
+void platform_init_keyboard(void)
+{
+ uint8_t ctr;
+
+ // clear in case of reinit
+ key_buffer_in_ptr = key_buffer_out_ptr = 0;
+
+ i8042_flush();
+
+ if (i8042_command(&ctr, I8042_CMD_CTL_RCTR)) {
+ dprintf(DEBUG, "Failed to read CTR while initializing i8042\n");
+ return;
+ }
+
+ // turn on translation
+ ctr |= I8042_CTR_XLATE;
+
+ // enable keyboard and keyboard irq
+ ctr &= ~I8042_CTR_KBDDIS;
+ ctr |= I8042_CTR_KBDINT;
+
+ if (i8042_command(&ctr, I8042_CMD_CTL_WCTR)) {
+ dprintf(DEBUG, "Failed to write CTR while initializing i8042\n");
+ return;
+ }
+
+ register_int_handler(INT_KEYBOARD, &i8042_interrupt, NULL);
+ unmask_interrupt(INT_KEYBOARD);
+
+ i8042_interrupt(NULL);
+}
diff --git a/platform/x86/platform.c b/platform/x86/platform.c
new file mode 100644
index 0000000..5d76237
--- /dev/null
+++ b/platform/x86/platform.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <err.h>
+#include <debug.h>
+#include <arch/x86/mmu.h>
+#include <platform.h>
+#include "platform_p.h"
+#include <platform/x86.h>
+#include <platform/multiboot.h>
+#include <platform/console.h>
+#include <platform/keyboard.h>
+
+extern multiboot_info_t *_multiboot_info;
+extern unsigned int _heap_end;
+
+void platform_init_mmu_mappings(void)
+{
+ /* do some memory map initialization */
+}
+
+
+void platform_init_multiboot_info(void)
+{
+ unsigned int i;
+
+ if (_multiboot_info) {
+ if (_multiboot_info->flags & MB_INFO_MEM_SIZE) {
+ _heap_end = _multiboot_info->mem_upper * 1024;
+ }
+
+ if (_multiboot_info->flags & MB_INFO_MMAP) {
+ memory_map_t *mmap = (memory_map_t *) (_multiboot_info->mmap_addr - 4);
+
+ dprintf(DEBUG, "mmap length: %u\n", _multiboot_info->mmap_length);
+
+ for (i=0; i < _multiboot_info->mmap_length / sizeof(memory_map_t); i++) {
+ dprintf(DEBUG, "base=%08x, length=%08x, type=%02x\n",
+ mmap[i].base_addr_low, mmap[i].length_low, mmap[i].type);
+
+ if (mmap[i].type == MB_MMAP_TYPE_AVAILABLE && mmap[i].base_addr_low >= _heap_end) {
+ _heap_end = mmap[i].base_addr_low + mmap[i].length_low;
+ } else if (mmap[i].type != MB_MMAP_TYPE_AVAILABLE && mmap[i].base_addr_low >= _heap_end) {
+ /*
+ * break on first memory hole above default heap end for now.
+ * later we can add facilities for adding free chunks to the
+ * heap for each segregated memory region.
+ */
+ break;
+ }
+ }
+ }
+ }
+}
+
+void platform_early_init(void)
+{
+ /* update the heap end so we can take advantage of more ram */
+ platform_init_multiboot_info();
+
+ /* get the text console working */
+ platform_init_console();
+
+ /* initialize the interrupt controller */
+ platform_init_interrupts();
+
+ /* initialize the timer */
+ platform_init_timer();
+}
+
+void platform_init(void)
+{
+ platform_init_keyboard();
+
+}
+
diff --git a/platform/x86/platform_p.h b/platform/x86/platform_p.h
new file mode 100644
index 0000000..b8c2d95
--- /dev/null
+++ b/platform/x86/platform_p.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef __PLATFORM_P_H
+#define __PLATFORM_P_H
+
+void platform_init_interrupts(void);
+void platform_init_timer(void);
+
+#endif
+
diff --git a/platform/x86/rules.mk b/platform/x86/rules.mk
new file mode 100644
index 0000000..bedf6c2
--- /dev/null
+++ b/platform/x86/rules.mk
@@ -0,0 +1,22 @@
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+ARCH := x86
+CPU := generic
+
+INCLUDES += \
+ -I$(LOCAL_DIR)/include
+
+OBJS += \
+ $(LOCAL_DIR)/interrupts.o \
+ $(LOCAL_DIR)/platform.o \
+ $(LOCAL_DIR)/timer.o \
+ $(LOCAL_DIR)/debug.o \
+ $(LOCAL_DIR)/console.o \
+ $(LOCAL_DIR)/keyboard.o
+
+MEMBASE := 0x0
+MEMSIZE := 0x400000 # 4MB
+
+LINKER_SCRIPT += \
+ $(BUILDDIR)/kernel.ld
+
diff --git a/platform/x86/timer.c b/platform/x86/timer.c
new file mode 100644
index 0000000..2684ab5
--- /dev/null
+++ b/platform/x86/timer.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2009 Corey Tabaka
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <sys/types.h>
+#include <err.h>
+#include <reg.h>
+#include <debug.h>
+#include <kernel/thread.h>
+#include <platform.h>
+#include <platform/interrupts.h>
+#include <platform/console.h>
+#include <platform/timer.h>
+#include <platform/x86.h>
+#include "platform_p.h"
+#include <arch/x86.h>
+
+static platform_timer_callback t_callback;
+static void *callback_arg;
+
+static uint64_t next_trigger_time;
+static uint64_t next_trigger_delta;
+
+static uint64_t timer_delta_time;
+static uint64_t timer_current_time;
+
+static uint16_t divisor;
+
+#define INTERNAL_FREQ 1193182ULL
+#define INTERNAL_FREQ_3X 3579546ULL
+
+status_t platform_set_periodic_timer(platform_timer_callback callback, void *arg, time_t interval)
+{
+ enter_critical_section();
+
+ t_callback = callback;
+ callback_arg = arg;
+
+ next_trigger_delta = (uint64_t) interval << 32;
+ next_trigger_time = timer_current_time + next_trigger_delta;
+
+ exit_critical_section();
+
+ return NO_ERROR;
+}
+
+time_t current_time(void)
+{
+ time_t time;
+
+ enter_critical_section();
+ time = (time_t) (timer_current_time >> 32);
+ exit_critical_section();
+
+ return time;
+}
+
+bigtime_t current_time_hires(void)
+{
+ bigtime_t time;
+
+ enter_critical_section();
+ time = (bigtime_t) ((timer_current_time >> 22) * 1000) >> 10;
+ exit_critical_section();
+
+ return time;
+}
+static enum handler_return os_timer_tick(void *arg)
+{
+ uint64_t delta;
+
+ timer_current_time += timer_delta_time;
+
+ time_t time = current_time();
+ //bigtime_t btime = current_time_hires();
+ //printf_xy(71, 0, WHITE, "%08u", (uint32_t) time);
+ //printf_xy(63, 1, WHITE, "%016llu", (uint64_t) btime);
+
+ if (t_callback && timer_current_time >= next_trigger_time) {
+ delta = timer_current_time - next_trigger_time;
+ next_trigger_time = timer_current_time + next_trigger_delta - delta;
+
+ return t_callback(callback_arg, time);
+ } else {
+ return INT_NO_RESCHEDULE;
+ }
+}
+
+static void set_pit_frequency(uint32_t frequency)
+{
+ uint32_t count, remainder;
+
+ /* figure out the correct divisor for the desired frequency */
+ if (frequency <= 18) {
+ count = 0xffff;
+ } else if (frequency >= INTERNAL_FREQ) {
+ count = 1;
+ } else {
+ count = INTERNAL_FREQ_3X / frequency;
+ remainder = INTERNAL_FREQ_3X % frequency;
+
+ if (remainder >= INTERNAL_FREQ_3X / 2) {
+ count += 1;
+ }
+
+ count /= 3;
+ remainder = count % 3;
+
+ if (remainder >= 1) {
+ count += 1;
+ }
+ }
+
+ divisor = count & 0xffff;
+
+ /*
+ * funky math that i don't feel like explaining. essentially 32.32 fixed
+ * point representation of the configured timer delta.
+ */
+ timer_delta_time = (3685982306ULL * count) >> 10;
+
+ //dprintf(DEBUG, "set_pit_frequency: dt=%016llx\n", timer_delta_time);
+ //dprintf(DEBUG, "set_pit_frequency: divisor=%04x\n", divisor);
+
+ /*
+ * setup the Programmable Interval Timer
+ * timer 0, mode 2, binary counter, LSB followed by MSB
+ */
+ outp(I8253_CONTROL_REG, 0x34);
+ outp(I8253_DATA_REG, divisor & 0xff); // LSB
+ outp(I8253_DATA_REG, divisor >> 8); // MSB
+}
+
+void platform_init_timer(void)
+{
+ timer_current_time = 0;
+
+ set_pit_frequency(1000); // ~1ms granularity
+
+ register_int_handler(INT_PIT, &os_timer_tick, NULL);
+ unmask_interrupt(INT_PIT);
+}
+
+void platform_halt_timers(void)
+{
+ mask_interrupt(INT_PIT);
+}
+
diff --git a/project/x86-test.mk b/project/x86-test.mk
new file mode 100644
index 0000000..4952260
--- /dev/null
+++ b/project/x86-test.mk
@@ -0,0 +1,18 @@
+# top level project rules for the x86-test project
+#
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+TARGET := x86
+#DEFINES += \
+# USE_UNDERSCORE=1
+MODULES += \
+ app/tests \
+ app/shell
+
+# extra rules to copy the x86.conf file to the build dir
+#$(BUILDDIR)/x86.conf: $(LOCAL_DIR)/x86.conf
+# @echo copy $< to $@
+# $(NOECHO)cp $< $@
+
+#EXTRA_BUILDDEPS += $(BUILDDIR)/x86.conf
+#GENERATED += $(BUILDDIR)/x86.conf
diff --git a/target/x86/rules.mk b/target/x86/rules.mk
new file mode 100644
index 0000000..3f9b072
--- /dev/null
+++ b/target/x86/rules.mk
@@ -0,0 +1,6 @@
+# mostly null target configuration for x86, since there's only one real
+# implementation.
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+PLATFORM := x86
+