summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile55
-rw-r--r--boot/Makefile10
-rw-r--r--boot/load.S254
-rw-r--r--driver/Makefile6
-rw-r--r--driver/console.c61
-rw-r--r--driver/console_old.S14
-rw-r--r--driver/dma.c31
-rw-r--r--driver/floppy.c214
-rw-r--r--driver/keyboard.c268
-rw-r--r--include/asm/boot.h9
-rw-r--r--include/asm/interrupt.h1
-rw-r--r--include/console.h6
-rw-r--r--include/dma.h47
-rw-r--r--include/floppy.h30
-rw-r--r--include/keyboard.h35
-rw-r--r--include/system.h21
-rw-r--r--include/timer.h5
-rw-r--r--system/Makefile6
-rw-r--r--system/ansi.S74
-rw-r--r--system/hex.c31
-rw-r--r--system/interrupt.S320
-rw-r--r--system/kernel.c115
-rw-r--r--system/timer.c9
23 files changed, 1622 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..6cecf3e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,55 @@
+VERSION = 0.01 pre-alpha
+
+
+KERNEL_FILES = boot/boot.o system/system.o driver/driver.o
+
+SPECIAL_FILES = include/asm/version.h
+
+
+kernel : version WINX
+ @echo
+ @echo WINX $(VERSION) compiled
+ @echo
+
+WINX : Makefile $(KERNEL_FILES)
+ @echo
+ @echo Linking kernel...
+ @ld -Ttext 0x0 -entry start -s --oformat binary -o WINX $(KERNEL_FILES)
+
+floppy : WINX
+ @echo
+ @echo Insert a blank 1.44 Mb floppy into drive 0
+ @echo "Press <Enter> to continue, <^C> to abort..."
+ @read
+ @dd if=WINX of=/dev/fd0 bs=512
+ @echo
+ @echo Done.
+ @echo
+
+clean :
+ @echo
+ @echo Cleanup...
+ @rm -f $(KERNEL_FILES) $(SPECIAL_FILES) $(BOOT_FILES) $(SYSTEM_FILES) $(DRIVER_FILES)
+ @echo OK
+ @echo
+
+
+%.o : %.S
+ @echo Compiling $<
+ @cpp $< -I include | as -o $*.o
+
+%.o : %.c
+ @echo Compiling $<
+ @gcc -I include -c -O3 -fno-zero-initialized-in-bss -o $*.o $<
+
+
+version : include/asm/version.h
+ @if ([ '$(shell cat "include/asm/version.h")' != '#define WINX_VERSION "$(VERSION)"' ]) then \
+ echo "#define WINX_VERSION \"$(VERSION)\"" > include/asm/version.h; fi
+
+include/asm/version.h:
+ @touch "include/asm/version.h"
+
+include boot/Makefile
+include system/Makefile
+include driver/Makefile
diff --git a/boot/Makefile b/boot/Makefile
new file mode 100644
index 0000000..2fc7d3d
--- /dev/null
+++ b/boot/Makefile
@@ -0,0 +1,10 @@
+BOOT_FILES = boot/load.o
+
+boot/boot.o : $(BOOT_FILES)
+ @echo Linking $*.o
+ @ld -r -o $*.o $(BOOT_FILES)
+ @echo
+
+boot/load.o : boot/load.S include/asm/version.h
+ @echo Compiling boot/load.S
+ @cpp boot/load.S -I include | as -o $*.o
diff --git a/boot/load.S b/boot/load.S
new file mode 100644
index 0000000..f7a6ba0
--- /dev/null
+++ b/boot/load.S
@@ -0,0 +1,254 @@
+/* boot.S - main bootup file */
+
+#include <asm/boot.h>
+#include <asm/version.h>
+
+GDT_SIZE = (gdt_end - gdt)
+IDT_SIZE = (idt_end - idt)
+KERNEL_TRACKS = ((KERNEL_BLOCKS+DISK_SECTORS_PER_TRACK-1)/DISK_SECTORS_PER_TRACK)
+
+
+.text
+
+.code16
+
+.global start
+
+start:
+
+xor %ax,%ax
+int $0x13
+
+# Load kernel
+
+mov $0x0001,%cx
+xor %dh,%dh
+xor %bx,%bx
+mov $0x50,%ax
+mov %ax,%es
+
+load_kernel_loop:
+
+mov $0x02,%ah
+mov $DISK_SECTORS_PER_TRACK,%al
+
+push %dx
+int $0x13
+pop %dx
+
+jc error
+
+mov %es,%ax
+add $(0x20*DISK_SECTORS_PER_TRACK),%ax
+mov %ax,%es
+
+
+add %dh,%ch
+or %dh,%dh
+jnz head0
+inc %dh
+jmp head1
+head0:
+xor %dh,%dh
+head1:
+cmp $(KERNEL_TRACKS/2),%ch
+jb load_kernel_loop
+
+ljmp $0x50, $load
+
+load:
+
+cli
+
+mov %cs,%ax
+mov %ax,%ds
+
+mov $0x01,%ah
+mov $0b0010000000000000,%cx
+int $0x10
+
+mov $0x36,%al
+out %al,$0x43
+mov $0x9B,%al
+out %al,$0x40
+mov $0x2E,%al
+out %al,$0x40
+
+key_ready:
+in $0x64,%al
+and $0b00000010,%al
+jnz key_ready
+mov $0xED,%al
+out %al,$0x60
+key_ready2:
+in $0x64,%al
+and $0b00000010,%al
+jnz key_ready2
+xor %al,%al
+out %al,$0x60
+
+mov $0b00010001,%al
+out %al,$0x20
+out %al,$0xA0
+
+mov $0x20,%al
+out %al,$0x21
+
+mov $0x28,%al
+out %al,$0xA1
+
+mov $0b00000100,%al
+out %al,$0x21
+
+mov $0b00000010,%al
+out %al,$0xA1
+
+mov $0b00000001,%al
+out %al,$0x21
+out %al,$0xA1
+
+lgdt gdt_struct
+
+lidt idt_struct
+
+mov %cr0,%eax
+or $1,%eax
+mov %eax,%cr0
+
+.byte 0xea
+.word pmode
+.word 8
+
+pmode:
+
+.code32
+
+mov $16,%ax
+mov %ax,%ds
+
+mov $24,%ax
+mov %ax,%ss
+mov $0x1FFF,%esp
+
+sti
+
+cld
+
+pushl $'\f'
+call print_char
+addl $4,%esp
+
+pushl $0b00001111
+pushl $verstring
+call print_attr
+addl $8,%esp
+
+#call init_floppy
+
+#call test
+
+done:
+xor %edx,%edx
+call kb_read_keycode
+or %eax,%eax
+jz done
+or %edx,%edx
+jz done
+and $0b10000000,%al
+jnz done
+pushl %edx
+call print_char
+addl $4,%esp
+call floppy_proc
+jmp done
+
+error: jmp error
+
+
+.org 0x1FE
+
+.word 0xAA55
+
+.org 0x200
+
+.data
+
+gdt:
+
+.word 0, 0, 0, 0 # dummy
+.word 0xFFFF, KERNEL_START, 0x9A00, 0x00CF # kernel code, 4 GB, code exec/read, 386 Segment
+.word 0xFFFF, KERNEL_START, 0x9200, 0x00CF # kernel data, 4 GB, data read/write, 386 Segment
+.word 0x2000, 0x8000, 0x9200, 0 # kernel stack, 8192 Bytes, data read/write, base address 0x8000
+.word 4000, 0x8000, 0x920B, 0 # VRAM, 4000 Bytes, data read/write, base address 0xB8000
+.word 0x0500, 0, 0x9200, 0 # BIOS data, 0x500 Bytes, data read/write, base address 0
+
+gdt_end:
+
+
+idt:
+
+.word EXC_DIV_ERROR, CODE_SEL, 0x8E00, 0
+.word EXC_DEBUG, CODE_SEL, 0x8E00, 0
+.word EXC_NMI, CODE_SEL, 0x8E00, 0
+.word EXC_BREAKPOINT, CODE_SEL, 0x8E00, 0
+.word EXC_INTO_OVERFLOW, CODE_SEL, 0x8E00, 0
+.word EXC_BOUND_OVERFLOW, CODE_SEL, 0x8E00, 0
+.word EXC_INVAL_OPCODE, CODE_SEL, 0x8E00, 0
+.word EXC_NO_COPROCESSOR, CODE_SEL, 0x8E00, 0
+.word EXC_DOUBLE_EXCEPTION, CODE_SEL, 0x8E00, 0
+.word EXC_COPROC_PROT_ERROR, CODE_SEL, 0x8E00, 0
+.word EXC_INVAL_TSS, CODE_SEL, 0x8E00, 0
+.word EXC_SEG_NOT_PRESENT, CODE_SEL, 0x8E00, 0
+.word EXC_STACK_FAULT, CODE_SEL, 0x8E00, 0
+.word EXC_GEN_PROT_VIOLATION, CODE_SEL, 0x8E00, 0
+.word EXC_PAGE_FAULT, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_COPROCESSOR_ERROR, CODE_SEL, 0x8E00, 0
+.word EXC_ALIGN_ERROR, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+.word EXC_RESERVED, CODE_SEL, 0x8E00, 0
+
+.word IRQ0, CODE_SEL, 0x8E00, 0
+.word IRQ1, CODE_SEL, 0x8E00, 0
+.word IRQ2, CODE_SEL, 0x8E00, 0
+.word IRQ3, CODE_SEL, 0x8E00, 0
+.word IRQ4, CODE_SEL, 0x8E00, 0
+.word IRQ5, CODE_SEL, 0x8E00, 0
+.word IRQ6, CODE_SEL, 0x8E00, 0
+.word IRQ7, CODE_SEL, 0x8E00, 0
+.word IRQ8, CODE_SEL, 0x8E00, 0
+.word IRQ9, CODE_SEL, 0x8E00, 0
+.word IRQ10, CODE_SEL, 0x8E00, 0
+.word IRQ11, CODE_SEL, 0x8E00, 0
+.word IRQ12, CODE_SEL, 0x8E00, 0
+.word IRQ13, CODE_SEL, 0x8E00, 0
+.word IRQ14, CODE_SEL, 0x8E00, 0
+.word IRQ15, CODE_SEL, 0x8E00, 0
+
+idt_end:
+
+
+gdt_struct:
+
+.word GDT_SIZE # gdt size
+.long (KERNEL_START+gdt) # gdt base address
+
+
+idt_struct:
+
+.word IDT_SIZE
+.long (KERNEL_START+idt)
+
+verstring: .ascii "WINX " WINX_VERSION "\r\n\0"
diff --git a/driver/Makefile b/driver/Makefile
new file mode 100644
index 0000000..12d5789
--- /dev/null
+++ b/driver/Makefile
@@ -0,0 +1,6 @@
+DRIVER_FILES = driver/console.o driver/keyboard.o driver/floppy.o driver/dma.o
+
+driver/driver.o : $(DRIVER_FILES)
+ @echo Linking $*.o
+ @ld -r -o $*.o $(DRIVER_FILES)
+ @echo
diff --git a/driver/console.c b/driver/console.c
new file mode 100644
index 0000000..79f277c
--- /dev/null
+++ b/driver/console.c
@@ -0,0 +1,61 @@
+/* console_cur.c - console functions */
+
+#include <system.h>
+#include <console.h>
+
+unsigned char console_flags = 0;
+unsigned short console_cur_pos = 0;
+unsigned char console_std_attr = 0x07;
+unsigned char console_akt_char_attr = 0;
+unsigned char cur_blink_counter = 0;
+
+
+void console_cursor_on() {
+ if(console_flags & FLAG_BLINK_ON) {console_flags &= ~FLAG_BLINK_ON; console_cur_blink();}
+}
+
+void console_cursor_off() {
+ if(console_flags & FLAG_BLINK_ON) {console_cur_blink(); console_flags |= FLAG_BLINK_ON;}
+}
+
+void console_cur_blink() {
+ if(console_flags & FLAG_BLINK_ON) {
+ console_flags &= ~FLAG_BLINK_ON;
+ asm (
+ "push %es\n"
+ "push %ebx\n"
+ "mov $32,%ax\n"
+ "mov %ax,%es\n"
+ "xor %ebx,%ebx\n"
+ "mov console_cur_pos,%bx\n"
+ "shl $1,%ebx\n"
+ "inc %ebx\n"
+ "mov console_akt_char_attr,%al\n"
+ "mov %al,%es:(%ebx)\n"
+ "pop %ebx\n"
+ "pop %es"
+ );
+ }
+
+ else {
+ console_flags |= FLAG_BLINK_ON;
+ asm (
+ "push %es\n"
+ "push %ebx\n"
+ "mov $32,%ax\n"
+ "mov %ax,%es\n"
+ "xor %ebx,%ebx\n"
+ "mov console_cur_pos,%bx\n"
+ "shl $1,%ebx\n"
+ "inc %ebx\n"
+ "mov console_std_attr,%al\n"
+ "rol $4,%al\n"
+ "and $0b01110111,%al\n"
+ "mov %es:(%ebx),%ah\n"
+ "mov %ah,console_akt_char_attr\n"
+ "mov %al,%es:(%ebx)\n"
+ "pop %ebx\n"
+ "pop %es"
+ );
+ }
+}
diff --git a/driver/console_old.S b/driver/console_old.S
new file mode 100644
index 0000000..9e105c9
--- /dev/null
+++ b/driver/console_old.S
@@ -0,0 +1,14 @@
+.data
+
+.global console_cur_pos, console_std_attr, console_akt_char_attr, cur_blink_counter, console_flags
+
+console_cur_pos: .word 0
+console_std_attr: .byte 0b00000111
+console_akt_char_attr: .byte 0
+
+cur_blink_counter: .byte 0
+
+
+.global CUR_BLINK
+
+CUR_BLINK = 50
diff --git a/driver/dma.c b/driver/dma.c
new file mode 100644
index 0000000..dc48de2
--- /dev/null
+++ b/driver/dma.c
@@ -0,0 +1,31 @@
+/* dma.c - DMA functions */
+
+#include <system.h>
+#include <dma.h>
+
+void dma_enable(unsigned char dma_nr) {
+ OUT_PORT(dma_nr & 3, PORT_DMA_MASK);
+}
+
+void dma_disable(unsigned char dma_nr) {
+ OUT_PORT((dma_nr & 3) | 4, PORT_DMA_MASK);
+}
+
+void dma_set_base_addr(unsigned char dma_nr, void *addr) {
+ OUT_PORT((unsigned long)addr & 0xFF, (dma_nr & 3)*2);
+ OUT_PORT(((unsigned long)addr >> 8) & 0xFF, (dma_nr & 3)*2);
+ OUT_PORT(((unsigned long)addr >> 16) & 0xFF, dma_page_ports[dma_nr & 3]);
+}
+
+void dma_set_word_count(unsigned char dma_nr, unsigned short words) {
+ OUT_PORT(words & 0xFF, ((dma_nr & 3)*2)+1);
+ OUT_PORT((words >> 8) & 0xFF, ((dma_nr & 3)*2)+1);
+}
+
+void dma_set_mode(unsigned char dma_nr, unsigned char mode) {
+ OUT_PORT(mode | (dma_nr & 3), PORT_DMA_MODE);
+}
+
+void dma_clear_ff() {
+ OUT_PORT(0, PORT_DMA_FF);
+}
diff --git a/driver/floppy.c b/driver/floppy.c
new file mode 100644
index 0000000..6b5d2d9
--- /dev/null
+++ b/driver/floppy.c
@@ -0,0 +1,214 @@
+/* floppy.c - floppy disk driver */
+
+#include <system.h>
+#include <floppy.h>
+#include <dma.h>
+#include <timer.h>
+
+
+unsigned char floppy_flags = 0;
+unsigned char floppy_num_drives = 0;
+unsigned char floppy_drive_type;
+unsigned char floppy_state = FLOPPY_STATE_IDLE;
+unsigned char floppy_waiting = 0;
+unsigned char floppy_requests = 0;
+unsigned char ST0, ST1, ST2, ST3;
+
+struct floppy_request request;
+
+
+static inline void send_floppy_byte(unsigned char byte) {
+ unsigned char status;
+ do IN_PORT_PP(PORT_FLOPPY_STATUS, status); while((status & 0xC0) != 0x80);
+ OUT_PORT(byte, PORT_FLOPPY_COMMAND_DATA);
+}
+
+static inline unsigned char recv_floppy_byte() {
+ unsigned char status;
+ do IN_PORT_PP(PORT_FLOPPY_STATUS, status); while((status & 0xD0) != 0xD0);
+ IN_PORT_PP(PORT_FLOPPY_COMMAND_DATA, status);
+ return status;
+}
+
+static inline void recalibrate(unsigned char drive) {
+ floppy_state = FLOPPY_STATE_RECALIBRATE;
+ floppy_waiting = 1;
+ send_floppy_byte(0x07);
+ send_floppy_byte(drive);
+}
+
+void test() {
+ read_floppy_sectors(0, 0, 0, 1, 1);
+}
+
+void init_floppy() {
+ unsigned short info;
+ unsigned char i;
+
+
+ //Kill motor
+ OUT_PORT(0x0C, PORT_FLOPPY_DOR);
+
+ //List drives
+ asm(
+ "mov $0x28,%%ax\n"
+ "mov %%ax,%%fs\n"
+ "mov %%fs:0x0410,%0"
+ : "=a" (info)
+ );
+
+ if(info & 1) {
+ floppy_num_drives = ((info >> 6) & 3) + 1;
+ if(floppy_num_drives > 2) floppy_num_drives = 2;
+ if(floppy_num_drives == 1) print("1 floppy drive found\r\n");
+ else print("2 floppy drives found\r\n");
+ }
+ else {
+ print(" No floppy drives found...\r\n");
+ return;
+ }
+
+
+ OUT_PORT(0x10, 0x70);
+ IN_PORT(0x71, floppy_drive_type);
+
+ if((floppy_drive_type >> 4) & 0x0F) {
+ print(" fd0: ");
+ if(((floppy_drive_type >> 4) & 0x0F) > 5) print("unknown");
+ else print(floppy_drive_types[(floppy_drive_type >> 4) & 0x0F]);
+ print("\r\n");
+ }
+
+ if(floppy_drive_type & 0x0F) {
+ print(" fd1: ");
+ if((floppy_drive_type & 0x0F) > 5) print("unknown");
+ else print(floppy_drive_types[floppy_drive_type & 0x0F]);
+ print("\r\n");
+ }
+
+ // configure
+
+ /*OUT_PORT(0x13, PORT_FLOPPY_COMMAND_DATA);
+ OUT_PORT(0, PORT_FLOPPY_COMMAND_DATA);
+ OUT_PORT(0x1F, PORT_FLOPPY_COMMAND_DATA);
+ OUT_PORT(0, PORT_FLOPPY_COMMAND_DATA);
+
+ // specify
+
+ OUT_PORT(0x03, PORT_FLOPPY_COMMAND_DATA);
+ OUT_PORT(0xCF, PORT_FLOPPY_COMMAND_DATA);
+ OUT_PORT(0x06, PORT_FLOPPY_COMMAND_DATA);*/
+}
+
+int read_floppy_sectors(unsigned char drive, unsigned char cylinder, unsigned char head, unsigned char sector, unsigned char sector_count) {
+ unsigned char i;
+
+ // test parameters
+ if(drive != 0 && drive != 1) return 1;
+ else if((drive == 0) && (((floppy_drive_type >> 4) & 0x0F) != 4)) return 2;
+ else if((drive == 1) && ((floppy_drive_type & 0x0F) != 4)) return 2;
+
+ if(!sector_count) return 3;
+
+ if(floppy_state == FLOPPY_STATE_IDLE) {
+
+ //Activate drive motor
+ OUT_PORT((1 << (4 + drive)) | 0x0C, PORT_FLOPPY_DOR);
+
+ print("TEST\n");
+
+ sleep(5000);
+
+ print("TEST\n");
+
+ //Recalibrate
+ //recalibrate(drive);
+ }
+
+ return 0;
+}
+
+void floppy_proc() {
+ unsigned char i;
+
+ /*IN_PORT(PORT_FLOPPY_STATUS, i);
+ print_hex_byte(i);*/
+ //dma_clear_ff();
+ //IN_PORT(0x04, i);
+ //print_hex_byte(i);
+ //IN_PORT(0x04, i);
+ //print_hex_byte(i);
+ /*IN_PORT(0x81, i);
+ print_hex_byte(i);*/
+ //IN_PORT(0x05, i);
+ //print_hex_byte(i);
+ /*IN_PORT(0x05, i);
+ print_hex_byte(i);*/
+
+ if(floppy_waiting) return;
+
+ if(floppy_state == FLOPPY_STATE_RECALIBRATE) {
+ floppy_state = FLOPPY_STATE_READ;
+ floppy_waiting = 1;
+
+ dma_disable(2);
+ dma_clear_ff();
+ dma_set_mode(2, DMA_MODE_SINGLE | DMA_MODE_READ | DMA_MODE_INC_ADDR);
+ dma_set_base_addr(2, (void*)0x200000);
+ dma_set_word_count(2, 0xFFFF);
+ dma_enable(2);
+
+ send_floppy_byte(0xE6);
+ send_floppy_byte(0x00);
+ send_floppy_byte(0x00);
+ send_floppy_byte(0x00);
+ send_floppy_byte(0x02);
+ send_floppy_byte(0x02);
+ send_floppy_byte(0x01);
+ send_floppy_byte(0x1B);
+ send_floppy_byte(0xFF);
+ }
+}
+
+void floppy_IRQ() {
+ //floppy_waiting = 0;
+ switch(floppy_state) {
+ case FLOPPY_STATE_RECALIBRATE:
+ print("Recalibrate FDC interrupt\n");
+ //IN_PORT(PORT_FLOPPY_STATUS, i);
+ //print_hex_byte(i);
+ //floppy_state = FLOPPY_STATE_READ;
+ //floppy_waiting = 0;
+ send_floppy_byte(0x08);
+ //print_hex_byte(recv_floppy_byte());
+ //print_hex_byte(recv_floppy_byte());
+ ST0 = recv_floppy_byte();
+ ST1 = recv_floppy_byte();
+
+ /*dma_disable(2);
+ dma_clear_ff();
+ dma_set_mode(2, DMA_MODE_SINGLE | DMA_MODE_READ | DMA_MODE_INC_ADDR);
+ dma_set_base_addr(2, (void*)0x100000);
+ dma_set_word_count(2, 512);
+ dma_enable(2);
+
+ send_floppy_byte(0xE6);
+ send_floppy_byte(0x00);
+ send_floppy_byte(0x00);
+ send_floppy_byte(0x00);
+ send_floppy_byte(0x01);
+ send_floppy_byte(0x02);
+ send_floppy_byte(0x01);
+ send_floppy_byte(0x1B);
+ send_floppy_byte(0xFF);*/
+
+ break;
+ case FLOPPY_STATE_READ:
+ print("Read FDC interrupt\n");
+ floppy_state = FLOPPY_STATE_IDLE;
+ print_hex_long(*(unsigned long*)0x1FFB00);
+ break;
+ default:
+ print("Unexpected FDC interrupt!\n");
+ }
+}
diff --git a/driver/keyboard.c b/driver/keyboard.c
new file mode 100644
index 0000000..26a12f0
--- /dev/null
+++ b/driver/keyboard.c
@@ -0,0 +1,268 @@
+/* keyboard.c - keyboard functions */
+
+#include <system.h>
+#include <keyboard.h>
+#include <console.h>
+
+unsigned short keyflags = 0;
+unsigned short key_extended_buffer;
+unsigned char keybuffer[256];
+unsigned char keybuffer_pointer = 0, keybuffer_count = 0;
+
+unsigned char keydata[128] = {
+ 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0xDF, '\'', '\b', '\t',
+ 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 0xFC, '+', '\n', 0, 'a', 's',
+ 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0xF6, 0xE4, '^', 0, '#', 'y', 'x', 'c', 'v',
+ 'b', 'n', 'm', ',', '.', '-', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0x0B, 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '<', 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+unsigned char keydata_shift[128] = {
+ 0, 0, '!', '"', 0xA7, '$', '%', '&', '/', '(', ')', '=', '?', '`', '\b', '\t',
+ 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', 'O', 'P', 0xDC, '*', '\n', 0, 'A', 'S',
+ 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0xD6, 0xC4, 0xB0, 0, '\'', 'Y', 'X', 'C', 'V',
+ 'B', 'N', 'M', ';', ':', '_', 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0x0B, 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '>', 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+unsigned char keydata_extended[128] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\n', 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, '/', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0x0B, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+unsigned char keydata_altgr[128] = {
+ 0, 0, 0, 0xB2, 0xB3, 0, 0, 0, '{', '[', ']', '}', '\\', 0, '\b', '\t',
+ '@', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '~', '\n', 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0xB5, 0, 0, 0, 0, '*', 0, ' ', 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0x0B, 0, 0, '-', 0, 0, 0, '+', 0,
+ 0, 0, 0, 0, 0, 0, '|', 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+unsigned char keydata_numlock[13] = {
+ '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', ','
+};
+
+
+void update_leds() {
+ register unsigned char al asm("%al");
+ do {
+ asm (
+ "in $0x64,%al\n"
+ "and $0b00000010,%al\n"
+ );
+ } while (al);
+ asm (
+ "mov $0xED,%al\n"
+ "out %al,$0x60\n"
+ );
+ do {
+ asm (
+ "in $0x64,%al\n"
+ "and $0b00000010,%al\n"
+ );
+ } while (al);
+ asm (
+ "mov %0,%%eax\n"
+ "and $0b11100000,%%al\n"
+ "shr $5,%%al\n"
+ "out %%al,$0x60\n"
+ : : "m" (keyflags)
+ );
+}
+
+
+void kb_write_keycode() {
+
+ unsigned char keycode;
+ unsigned long fullcode;
+ unsigned char ansicode = 0;
+
+ unsigned char *keytable = keydata;
+
+ asm ("mov %%al,%0" : "=m" (keycode));
+
+ fullcode = (keycode & KEY_CODE);
+
+ if(keycode==ACKNOWLEDGE_CODE) return;
+
+ else if(keycode==EXTENDED0_CODE) {keyflags |= FLAG_EXTENDED_KEY; key_extended_buffer = EXTENDED0_CODE;}
+
+ else if(keycode==EXTENDED1_CODE) {keyflags |= FLAG_EXTENDED_KEY; key_extended_buffer = EXTENDED1_CODE;}
+
+ else {
+
+ if(keyflags & FLAG_EXTENDED_KEY) {
+ if(key_extended_buffer==EXTENDED0_CODE) {
+ fullcode = ((keycode & KEY_CODE) | (EXTENDED0_CODE << 8));
+ keyflags &= ~FLAG_EXTENDED_KEY;
+ }
+ else if(key_extended_buffer==EXTENDED1_CODE) {
+ fullcode = ((keycode & KEY_CODE) | (EXTENDED1_CODE << 8));
+ key_extended_buffer = fullcode;
+ }
+ else {
+ fullcode = ((keycode & KEY_CODE) | (((unsigned long)key_extended_buffer) << 8));
+ keyflags &= ~FLAG_EXTENDED_KEY;
+ }
+ }
+
+
+ if(keycode & KEY_RELEASE) {
+ switch(fullcode) {
+ case NUMLOCK_CODE:
+ keyflags &= ~FLAG_NUMLOCK_PRESSED;
+ break;
+ case SCROLLLOCK_CODE:
+ keyflags &= ~FLAG_SCROLLLOCK_PRESSED;
+ break;
+ case CAPSLOCK_CODE:
+ keyflags &= ~FLAG_CAPSLOCK_PRESSED;
+ break;
+ case LSHIFT_CODE:
+ keyflags &= ~FLAG_LSHIFT_PRESSED;
+ break;
+ case RSHIFT_CODE:
+ keyflags &= ~FLAG_RSHIFT_PRESSED;
+ break;
+ case LALT_CODE:
+ keyflags &= ~FLAG_LALT_PRESSED;
+ break;
+ case RALT_CODE:
+ keyflags &= ~FLAG_RALT_PRESSED;
+ break;
+ case LCTRL_CODE:
+ keyflags &= ~FLAG_LCTRL_PRESSED;
+ break;
+ case RCTRL_CODE:
+ keyflags &= ~FLAG_RCTRL_PRESSED;
+ break;
+ default:
+ if((keyflags & FLAG_NUMLOCK_ACTIVE) && (0x47 <= (fullcode & ~KEY_RELEASE)) && ((fullcode & ~KEY_RELEASE) <= 0x53))
+ ansicode = keydata_numlock[(keycode & KEY_CODE) - 0x47];
+ else {
+ if((fullcode & (EXTENDED0_CODE << 8)) == (EXTENDED0_CODE << 8)) keytable = keydata_extended;
+ else if(keyflags & FLAG_RALT_PRESSED) keytable = keydata_altgr;
+ else if((keyflags & FLAG_LALT_PRESSED)/* && ((keyflags & FLAG_RCTRL_PRESSED)
+ || (keyflags & FLAG_LCTRL_PRESSED))*/) keytable = keydata_altgr;
+ else if(keyflags & (FLAG_LSHIFT_PRESSED | FLAG_RSHIFT_PRESSED | FLAG_CAPSLOCK_ACTIVE))
+ keytable = keydata_shift;
+ ansicode = keytable[keycode & KEY_CODE];
+ }
+ }
+ }
+ else {
+ switch(fullcode) {
+ case NUMLOCK_CODE:
+ if(keyflags & FLAG_NUMLOCK_PRESSED) return;
+ else {
+ keyflags |= FLAG_NUMLOCK_PRESSED;
+ if(keyflags & FLAG_NUMLOCK_ACTIVE) keyflags &= ~FLAG_NUMLOCK_ACTIVE;
+ else keyflags |= FLAG_NUMLOCK_ACTIVE;
+ update_leds();
+ }
+ break;
+ case SCROLLLOCK_CODE:
+ if(keyflags & FLAG_SCROLLLOCK_PRESSED) return;
+ else {
+ keyflags |= FLAG_SCROLLLOCK_PRESSED;
+ if(keyflags & FLAG_SCROLLLOCK_ACTIVE) keyflags &= ~FLAG_SCROLLLOCK_ACTIVE;
+ else keyflags |= FLAG_SCROLLLOCK_ACTIVE;
+ update_leds();
+ }
+ break;
+ case CAPSLOCK_CODE:
+ if(keyflags & FLAG_CAPSLOCK_PRESSED) return;
+ else {
+ keyflags |= FLAG_CAPSLOCK_PRESSED;
+ if(keyflags & FLAG_CAPSLOCK_ACTIVE) keyflags &= ~FLAG_CAPSLOCK_ACTIVE;
+ else keyflags |= FLAG_CAPSLOCK_ACTIVE;
+ update_leds();
+ }
+ break;
+ case LSHIFT_CODE:
+ keyflags |= FLAG_LSHIFT_PRESSED;
+ break;
+ case RSHIFT_CODE:
+ keyflags |= FLAG_RSHIFT_PRESSED;
+ break;
+ case LALT_CODE:
+ keyflags |= FLAG_LALT_PRESSED;
+ break;
+ case RALT_CODE:
+ keyflags |= FLAG_RALT_PRESSED;
+ break;
+ case LCTRL_CODE:
+ keyflags |= FLAG_LCTRL_PRESSED;
+ break;
+ case RCTRL_CODE:
+ keyflags |= FLAG_RCTRL_PRESSED;
+ break;
+ default:
+ if((keyflags & FLAG_NUMLOCK_ACTIVE) && (0x47 <= fullcode) && (fullcode <= 0x53))
+ ansicode = keydata_numlock[keycode - 0x47];
+ else {
+ if((fullcode & (EXTENDED0_CODE << 8)) == (EXTENDED0_CODE << 8)) keytable = keydata_extended;
+ else if(keyflags & FLAG_RALT_PRESSED) keytable = keydata_altgr;
+ else if(keyflags & (FLAG_LSHIFT_PRESSED | FLAG_RSHIFT_PRESSED | FLAG_CAPSLOCK_ACTIVE))
+ keytable = keydata_shift;
+ ansicode = keytable[keycode];
+ }
+ }
+ }
+ }
+ if(keyflags & FLAG_BUFFER_FULL) return;
+ keybuffer[(keybuffer_pointer + keybuffer_count++) & 0xFF] = keycode;
+ keybuffer[(keybuffer_pointer + keybuffer_count++) & 0xFF] = ansicode;
+ if(keybuffer_count==0) keyflags |= FLAG_BUFFER_FULL;
+}
+
+
+void kb_read_keycode() {
+ unsigned long keycode = 0;
+ unsigned char ansicode = 0;
+
+ if((keybuffer_count != 0) || (keyflags & FLAG_BUFFER_FULL)) {
+ keycode = keybuffer[keybuffer_pointer++];
+ ansicode = keybuffer[keybuffer_pointer++];
+ keybuffer_count-=2;
+ keyflags &= ~FLAG_BUFFER_FULL;
+ if(keycode == EXTENDED0_CODE) {
+ if(keybuffer_count != 0) {
+ keycode <<= 8;
+ keycode |= keybuffer[keybuffer_pointer++];
+ ansicode = keybuffer[keybuffer_pointer++];
+ keybuffer_count-=2;
+ }
+ }
+ else if(keycode == EXTENDED1_CODE) {
+ if(keybuffer_count != 0) {
+ keycode <<= 8;
+ keycode |= keybuffer[keybuffer_pointer++];
+ ansicode = keybuffer[keybuffer_pointer++];
+ keybuffer_count-=2;
+ if(keybuffer_count != 0) {
+ keycode <<= 8;
+ keycode |= keybuffer[keybuffer_pointer++];
+ ansicode = keybuffer[keybuffer_pointer++];
+ keybuffer_count-=2;
+ }
+ }
+ }
+ }
+ asm ("mov %0,%%eax; mov %1,%%dl" : : "m" (keycode), "m" (ansicode));
+}
diff --git a/include/asm/boot.h b/include/asm/boot.h
new file mode 100644
index 0000000..690f698
--- /dev/null
+++ b/include/asm/boot.h
@@ -0,0 +1,9 @@
+#define KERNEL_START 0x500
+#define KERNEL_BLOCKS 24
+#define DISK_SECTORS_PER_TRACK 18
+
+#define CODE_SEL 0x08
+#define DATA_SEL 0x10
+#define STACK_SEL 0x18
+#define VRAM_SEL 0x20
+#define BIOS_SEL 0x28
diff --git a/include/asm/interrupt.h b/include/asm/interrupt.h
new file mode 100644
index 0000000..c6924a7
--- /dev/null
+++ b/include/asm/interrupt.h
@@ -0,0 +1 @@
+#define CUR_BLINK 50
diff --git a/include/console.h b/include/console.h
new file mode 100644
index 0000000..707fe3c
--- /dev/null
+++ b/include/console.h
@@ -0,0 +1,6 @@
+void console_cur_blink();
+void console_cursor_on();
+void console_cursor_off();
+
+
+#define FLAG_BLINK_ON 0x01
diff --git a/include/dma.h b/include/dma.h
new file mode 100644
index 0000000..3c45f7a
--- /dev/null
+++ b/include/dma.h
@@ -0,0 +1,47 @@
+#define PORT_DMA_BASE_ADDR0 0x00
+#define PORT_DMA_WORD_COUNT0 0x01
+#define PORT_DMA_BASE_ADDR1 0x02
+#define PORT_DMA_WORD_COUNT1 0x03
+#define PORT_DMA_BASE_ADDR2 0x04
+#define PORT_DMA_WORD_COUNT2 0x05
+#define PORT_DMA_BASE_ADDR3 0x06
+#define PORT_DMA_WORD_COUNT3 0x07
+
+#define PORT_DMA_COMMAND 0x08
+#define PORT_DMA_WRITE_REQUEST 0x09
+#define PORT_DMA_MASK 0x0A
+#define PORT_DMA_MODE 0x0B
+#define PORT_DMA_FF 0x0C
+
+#define PORT_DMA_PAGE0 0x87
+#define PORT_DMA_PAGE1 0x83
+#define PORT_DMA_PAGE2 0x81
+#define PORT_DMA_PAGE3 0x82
+
+#define DMA_MODE_DEMAND 0x00
+#define DMA_MODE_SINGLE 0x40
+#define DMA_MODE_BLOCK 0x80
+#define DMA_MODE_CASCADE 0xC0
+
+#define DMA_MODE_VERIFY 0x00
+#define DMA_MODE_READ 0x04
+#define DMA_MODE_WRITE 0x08
+
+#define DMA_MODE_INC_ADDR 0x00
+#define DMA_MODE_DEC_ADDR 0x20
+
+
+static unsigned char dma_page_ports[4] = {
+ PORT_DMA_PAGE0,
+ PORT_DMA_PAGE1,
+ PORT_DMA_PAGE2,
+ PORT_DMA_PAGE3
+};
+
+
+void dma_enable(unsigned char dma_nr);
+void dma_disable(unsigned char dma_nr);
+void dma_set_base_addr(unsigned char dma_nr, void *addr);
+void dma_set_word_count(unsigned char dma_nr, unsigned short words);
+void dma_set_mode(unsigned char dma_nr, unsigned char mode);
+void dma_clear_ff();
diff --git a/include/floppy.h b/include/floppy.h
new file mode 100644
index 0000000..8d526ef
--- /dev/null
+++ b/include/floppy.h
@@ -0,0 +1,30 @@
+#define PORT_FLOPPY_DOR 0x03F2
+#define PORT_FLOPPY_TAPE_DRIVE 0x03F3
+#define PORT_FLOPPY_SELECT_DATA_RATE 0x03F4
+#define PORT_FLOPPY_STATUS 0x03F4
+#define PORT_FLOPPY_COMMAND_DATA 0x03F5
+#define PORT_FLOPPY_DIR 0x03F7
+
+#define FLOPPY_STATE_IDLE 0
+#define FLOPPY_STATE_RECALIBRATE 1
+#define FLOPPY_STATE_SEEK 2
+#define FLOPPY_STATE_READ 3
+
+
+struct floppy_request {
+ unsigned char command;
+ unsigned char drive;
+ unsigned char cylinder;
+ unsigned char head;
+ unsigned char sector;
+ unsigned char sector_count;
+ void *buffer;
+};
+
+
+static unsigned char floppy_drive_types[6][8] = {"none", "360 KB", "1.2 MB", "720 KB", "1.44 MB", "2.88 MB"};
+
+
+void init_floppy();
+int read_floppy_sectors(unsigned char drive, unsigned char cylinder, unsigned char head, unsigned char sector, unsigned char sector_count);
+void floppy_IRQ();
diff --git a/include/keyboard.h b/include/keyboard.h
new file mode 100644
index 0000000..45c3c35
--- /dev/null
+++ b/include/keyboard.h
@@ -0,0 +1,35 @@
+#define LSHIFT_CODE 0x2A
+#define RSHIFT_CODE 0x36
+#define NUMLOCK_CODE 0x45
+#define SCROLLLOCK_CODE 0x46
+#define CAPSLOCK_CODE 0x3A
+#define ACKNOWLEDGE_CODE 0xFA
+#define EXTENDED0_CODE 0xE0
+#define EXTENDED1_CODE 0xE1
+#define LALT_CODE 0x38
+#define RALT_CODE 0xE038
+#define PAUSE_CODE 0x00E11D45
+#define LCTRL_CODE 0x1D
+#define RCTRL_CODE 0xE01D
+
+#define FLAG_BUFFER_FULL (1 << 0)
+#define FLAG_EXTENDED_KEY (1 << 1)
+#define FLAG_SCROLLLOCK_PRESSED (1 << 2)
+#define FLAG_NUMLOCK_PRESSED (1 << 3)
+#define FLAG_CAPSLOCK_PRESSED (1 << 4)
+#define FLAG_SCROLLLOCK_ACTIVE (1 << 5)
+#define FLAG_NUMLOCK_ACTIVE (1 << 6)
+#define FLAG_CAPSLOCK_ACTIVE (1 << 7)
+#define FLAG_LSHIFT_PRESSED (1 << 8)
+#define FLAG_RSHIFT_PRESSED (1 << 9)
+#define FLAG_LALT_PRESSED (1 << 10)
+#define FLAG_RALT_PRESSED (1 << 11)
+#define FLAG_LCTRL_PRESSED (1 << 12)
+#define FLAG_RCTRL_PRESSED (1 << 13)
+
+#define KEY_RELEASE 0x80
+#define KEY_CODE 0x7F
+
+
+void kb_write_keycode();
+void kb_read_keycode();
diff --git a/include/system.h b/include/system.h
new file mode 100644
index 0000000..9440d6b
--- /dev/null
+++ b/include/system.h
@@ -0,0 +1,21 @@
+#define IN_PORT(p,b) asm("in %1,%0" : "=a" ((unsigned char)(b)) : "d" ((unsigned short)(p)) )
+#define IN_PORT_P(p,b) asm("in %1,%0;in $0x80,%%al" : "=a" ((unsigned char)(b)) : "d" ((unsigned short)(p)) )
+#define IN_PORT_PP(p,b) asm("in %1,%0;in $0x80,%%al;in $0x80,%%al;in $0x80,%%al;in $0x80,%%al" \
+ : "=a" ((unsigned char)(b)) : "d" ((unsigned short)(p)) )
+#define OUT_PORT(b,p) asm("out %0,%1" : : "a" ((unsigned char)(b)), "d" ((unsigned short)(p)) )
+#define OUT_PORT_P(b,p) asm("out %0,%1;in $0x80,%%al" : : "a" ((unsigned char)(b)), "d" ((unsigned short)(p)) )
+#define OUT_PORT_PP(b,p) asm("out %0,%1;in $0x80,%%al;in $0x80,%%al;in $0x80,%%al;in $0x80,%%al" \
+ : : "a" ((unsigned char)(b)), "d" ((unsigned short)(p)) )
+
+#define ANSI2ASCII(x) asm ("mov %0,%%dl;call ansi2ascii;mov %%dl,%0\n" : "+m" (x))
+#define ASCII2ANSI(x) asm ("mov %0,%%dl;call ascii2ansi;mov %%dl,%0\n" : "+m" (x))
+
+
+void print(unsigned char * text);
+void print_attr(unsigned char * text, unsigned char attr);
+void print_char(unsigned char text);
+void print_char_attr(unsigned char text, unsigned char attr);
+
+void print_hex_byte(unsigned char hex);
+void print_hex_word(unsigned short hex);
+void print_hex_long(unsigned long hex);
diff --git a/include/timer.h b/include/timer.h
new file mode 100644
index 0000000..cfe05fc
--- /dev/null
+++ b/include/timer.h
@@ -0,0 +1,5 @@
+typedef struct _TIMER {
+ unsigned long time;
+} TIMER;
+
+void sleep(unsigned long ms);
diff --git a/system/Makefile b/system/Makefile
new file mode 100644
index 0000000..ade470d
--- /dev/null
+++ b/system/Makefile
@@ -0,0 +1,6 @@
+SYSTEM_FILES = system/kernel.o system/interrupt.o system/ansi.o system/hex.o system/timer.o
+
+system/system.o : $(SYSTEM_FILES)
+ @echo Linking $*.o
+ @ld -r -o $*.o $(SYSTEM_FILES)
+ @echo
diff --git a/system/ansi.S b/system/ansi.S
new file mode 100644
index 0000000..d1b5f55
--- /dev/null
+++ b/system/ansi.S
@@ -0,0 +1,74 @@
+/* ansi.S - ANSI conversion functions */
+
+.text
+
+.global ansi2ascii, ascii2ansi
+
+ascii2ansi:
+ push %eax
+ push %ds
+ mov $16,%ax
+ mov %ax,%ds
+ xor %eax,%eax
+ mov %dl,%al
+ add $ascii2ansi_tab,%eax
+ mov (%eax),%dl
+ pop %ds
+ pop %eax
+ ret
+
+
+ansi2ascii:
+ push %eax
+ push %ds
+ mov $16,%ax
+ mov %ax,%ds
+ xor %eax,%eax
+ mov %dl,%al
+ add $ansi2ascii_tab,%eax
+ mov (%eax),%dl
+ pop %ds
+ pop %eax
+ ret
+
+
+.data
+
+ansi2ascii_tab:
+
+.byte 0, ' ', ' ', ' ', ' ', ' ', ' ', 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, ' ', ' '
+.byte ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
+.byte ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/'
+.byte '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?'
+.byte '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'
+.byte 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_'
+.byte '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'
+.byte 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', ' '
+.byte ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
+.byte ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
+.byte ' ', 0xAD, 0x9B, 0x9C, ' ', 0x9D, 0x7C, 0x15, ' ', ' ', 0xA6, 0xAE, 0xAA, 0x2D, ' ', ' '
+.byte 0xF8, 0xF1, 0xFD, ' ', 0x27, 0xE6, 0x14, 0xF9, ' ', ' ', 0xA7, 0xAF, 0xAC, 0xAB, ' ', 0xA8
+.byte ' ', ' ', ' ', ' ', 0x8E, 0x8F, 0x92, 0x80, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
+.byte ' ', 0xA5, ' ', ' ', ' ', ' ', 0x99, ' ', ' ', ' ', ' ', ' ', 0x9A, ' ', ' ', 0xE1
+.byte 0x85, 0xA0, 0x83, ' ', 0x84, 0x86, 0x91, 0x87, 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1, 0x8C, 0x8B
+.byte ' ', 0xA4, 0x95, 0xA2, 0x93, ' ', 0x94, ' ', ' ', 0x97, 0xA3, 0x96, 0x81, ' ', ' ', 0x98
+
+
+ascii2ansi_tab:
+
+.byte 0, ' ', ' ', ' ', ' ', ' ', ' ', 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, ' ', '*'
+.byte ' ', ' ', ' ', '!', '¶', '§', '_', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
+.byte ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/'
+.byte '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?'
+.byte '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'
+.byte 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_'
+.byte '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'
+.byte 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', ' '
+.byte 'Ç', 'ü', 'é', 'â', 'ä', 'à', 'å', 'ç', 'ê', 'ë', 'è', 'ï', 'î', 'ì', 'Ä', 'Å'
+.byte 'É', 'æ', 'Æ', 'ô', 'ö', 'ò', 'û', 'ù', 'ÿ', 'Ö', 'Ü', '¢', '£', '¥', ' ', ' '
+.byte 'á', 'í', 'ó', 'ú', 'ñ', 'Ñ', 'ª', 'º', '¿', ' ', '¬', '½', '¼', '¡', '«', '»'
+.byte ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
+.byte ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
+.byte ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
+.byte ' ', ' ', ' ', ' ', ' ', ' ', 'µ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
+.byte ' ', '±', ' ', ' ', ' ', ' ', '÷', ' ', '°', '·', ' ', ' ', ' ', '²', '·', ' '
diff --git a/system/hex.c b/system/hex.c
new file mode 100644
index 0000000..4374063
--- /dev/null
+++ b/system/hex.c
@@ -0,0 +1,31 @@
+/* hex.c - hexdecimal print functions */
+
+#include <system.h>
+
+
+extern unsigned char console_std_attr;
+
+static char hex_values[16] = "0123456789ABCDEF";
+
+void print_hex_byte(unsigned char hex) {
+ print_char(hex_values[(hex >> 4) & 0x0F]);
+ print_char(hex_values[hex & 0x0F]);
+}
+
+void print_hex_word(unsigned short hex) {
+ print_char(hex_values[(hex >> 12) & 0x0F]);
+ print_char(hex_values[(hex >> 8) & 0x0F]);
+ print_char(hex_values[(hex >> 4) & 0x0F]);
+ print_char(hex_values[hex & 0x0F]);
+}
+
+void print_hex_long(unsigned long hex) {
+ print_char(hex_values[(hex >> 28) & 0x0F]);
+ print_char(hex_values[(hex >> 24) & 0x0F]);
+ print_char(hex_values[(hex >> 20) & 0x0F]);
+ print_char(hex_values[(hex >> 16) & 0x0F]);
+ print_char(hex_values[(hex >> 12) & 0x0F]);
+ print_char(hex_values[(hex >> 8) & 0x0F]);
+ print_char(hex_values[(hex >> 4) & 0x0F]);
+ print_char(hex_values[hex & 0x0F]);
+}
diff --git a/system/interrupt.S b/system/interrupt.S
new file mode 100644
index 0000000..3791ce2
--- /dev/null
+++ b/system/interrupt.S
@@ -0,0 +1,320 @@
+/* interrupt.S - interrupt handlers */
+
+#include <asm/interrupt.h>
+
+.text
+
+.global EXC_DIV_ERROR, EXC_DEBUG, EXC_NMI, EXC_BREAKPOINT
+.global EXC_INTO_OVERFLOW, EXC_BOUND_OVERFLOW, EXC_INVAL_OPCODE, EXC_NO_COPROCESSOR
+.global EXC_DOUBLE_EXCEPTION, EXC_COPROC_PROT_ERROR, EXC_INVAL_TSS, EXC_SEG_NOT_PRESENT
+.global EXC_STACK_FAULT, EXC_GEN_PROT_VIOLATION, EXC_PAGE_FAULT, EXC_RESERVED
+.global EXC_COPROCESSOR_ERROR, EXC_ALIGN_ERROR
+
+EXC_DIV_ERROR:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_div_error_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_DEBUG:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_debug_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_NMI:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_nmi_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_BREAKPOINT:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_breakpoint_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_INTO_OVERFLOW:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_into_overflow_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_BOUND_OVERFLOW:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_bound_overflow_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_INVAL_OPCODE:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_inval_opcode_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_NO_COPROCESSOR:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_no_coprocessor_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_DOUBLE_EXCEPTION:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_double_exception_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_COPROC_PROT_ERROR:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_coproc_prot_error_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_INVAL_TSS:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_inval_tss_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_SEG_NOT_PRESENT:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_seg_not_present_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_STACK_FAULT:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_stack_fault_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_GEN_PROT_VIOLATION:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_gen_prot_violation_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_PAGE_FAULT:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_page_fault_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_RESERVED:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_reserved_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_COPROCESSOR_ERROR:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_coprocessor_error_str
+ call print
+ addl $4,%esp
+ jmp looping
+
+EXC_ALIGN_ERROR:
+ mov $16,%ax
+ mov %ax,%ds
+ pushl $exc_align_error_str
+ call print
+ addl $4,%esp
+
+looping: jmp looping
+
+
+.data
+
+exc_div_error_str: .asciz "EXCEPTION: DIVIDE ERROR\r\n"
+exc_debug_str: .asciz "EXCEPTION: DEBUG EXCEPTION\r\n"
+exc_nmi_str: .asciz "EXCEPTION: NON-MASKABLE INTERRUPT\r\n"
+exc_breakpoint_str: .asciz "EXCEPTION: BREAKPOINT\r\n"
+exc_into_overflow_str: .asciz "EXCEPTION: OVERFLOW (INTO)\r\n"
+exc_bound_overflow_str: .asciz "EXCEPTION: OVERFLOW (BOUND)\r\n"
+exc_inval_opcode_str: .asciz "EXCEPTION: INVALID OPCODE\r\n"
+exc_no_coprocessor_str: .asciz "EXCEPTION: NO COPROCESSOR\r\n"
+exc_double_exception_str: .asciz "EXCEPTION: DOUBLE EXCEPTION\r\n"
+exc_coproc_prot_error_str: .asciz "EXCEPTION: COPROCESSOR PROTECTION ERROR\r\n"
+exc_inval_tss_str: .asciz "EXCEPTION: INVALID TSS SEGMENT\r\n"
+exc_seg_not_present_str: .asciz "EXCEPTION: SEGMENT NOT PRESENT\r\n"
+exc_stack_fault_str: .asciz "EXCEPTION: STACK FAULT\r\n"
+exc_gen_prot_violation_str: .asciz "EXCEPTION: GENERAL PROTECTION VIOLATION\r\n"
+exc_page_fault_str: .asciz "EXCEPTION: PAGE FAULT\r\n"
+exc_reserved_str: .asciz "EXCEPTION: UNKNOWN ERROR\r\n"
+exc_coprocessor_error_str: .asciz "EXCEPTION: COPROCESSOR ERROR\r\n"
+exc_align_error_str: .asciz "EXCEPTION: ALIGNMENT ERROR\r\n"
+
+
+.text
+
+.global IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, IRQ8, IRQ9, IRQ10, IRQ11, IRQ12, IRQ13, IRQ14, IRQ15
+
+IRQ0:
+ pusha
+ pushf
+ incb cur_blink_counter
+ cmpb $CUR_BLINK,cur_blink_counter
+ jb no_blink
+ subb $CUR_BLINK,cur_blink_counter
+ call console_cur_blink
+no_blink:
+ cmpl $0,timers
+ je no_timer
+ decl timers
+no_timer:
+ mov $0x20, %al
+ out %al, $0x20
+ popf
+ popa
+ iret
+
+IRQ1:
+ push %ax
+ push %ds
+ push %edx
+ mov $16,%ax
+ mov %ax,%ds
+ in $0x60,%al
+ call kb_write_keycode
+ mov $0x20, %al
+ out %al, $0x20
+ pop %edx
+ pop %ds
+ pop %ax
+ iret
+
+IRQ2:
+ push %ax
+ mov $0x20, %al
+ out %al, $0x20
+ pop %ax
+ iret
+
+IRQ3:
+ push %ax
+ mov $0x20, %al
+ out %al, $0x20
+ pop %ax
+ iret
+
+IRQ4:
+ push %ax
+ mov $0x20, %al
+ out %al, $0x20
+ pop %ax
+ iret
+
+IRQ5:
+ push %ax
+ mov $0x20, %al
+ out %al, $0x20
+ pop %ax
+ iret
+
+IRQ6:
+ #push %ax
+ pushf
+ pusha
+ call floppy_IRQ
+ mov $0x20, %al
+ out %al, $0x20
+ #pop %ax
+ popa
+ popf
+ iret
+
+IRQ7:
+ push %ax
+ mov $0x20, %al
+ out %al, $0x20
+ pop %ax
+ iret
+
+IRQ8:
+ push %ax
+ mov $0x20, %al
+ out %al, $0xA0
+ pop %ax
+ iret
+
+IRQ9:
+ push %ax
+ mov $0x20, %al
+ out %al, $0xA0
+ pop %ax
+ iret
+
+IRQ10:
+ push %ax
+ mov $0x20, %al
+ out %al, $0xA0
+ pop %ax
+ iret
+
+IRQ11:
+ push %ax
+ mov $0x20, %al
+ out %al, $0xA0
+ pop %ax
+ iret
+
+IRQ12:
+ push %ax
+ mov $0x20, %al
+ out %al, $0xA0
+ pop %ax
+ iret
+
+IRQ13:
+ push %ax
+ mov $0x20, %al
+ out %al, $0xA0
+ pop %ax
+ iret
+
+IRQ14:
+ push %ax
+ mov $0x20, %al
+ out %al, $0xA0
+ pop %ax
+ iret
+
+IRQ15:
+ push %ax
+ mov $0x20, %al
+ out %al, $0xA0
+ pop %ax
+ iret
diff --git a/system/kernel.c b/system/kernel.c
new file mode 100644
index 0000000..e8ad3a9
--- /dev/null
+++ b/system/kernel.c
@@ -0,0 +1,115 @@
+/* kernel.c - kernel functions */
+
+#include <system.h>
+#include <console.h>
+
+
+extern unsigned char console_std_attr;
+extern unsigned short console_cur_pos;
+extern unsigned char console_flags;
+
+unsigned char numprint = 0;
+
+#define PRINT_ON if(numprint == 0) { \
+ asm("cli");\
+ console_cursor_off();\
+ }\
+ numprint++
+
+#define PRINT_OFF numprint--;\
+ if(numprint == 0) {\
+ console_cursor_on();\
+ asm("sti");\
+ }
+
+
+void print(unsigned char * text) {
+ print_attr(text, console_std_attr);
+}
+
+void print_attr(unsigned char * text, unsigned char attr) {
+ PRINT_ON;
+ while(*text) {
+ print_char_attr(*text, attr);
+ text++;
+ }
+ PRINT_OFF;
+}
+
+void print_char(unsigned char text) {
+ print_char_attr(text, console_std_attr);
+}
+
+void print_char_attr(unsigned char text, unsigned char attr) {
+ PRINT_ON;
+ switch(text) {
+ case 0x08: // backspace
+ if(console_cur_pos) console_cur_pos--;
+ break;
+ case 0x09: // tab
+ console_cur_pos += (8 - (console_cur_pos % 8));
+ break;
+ case 0x0A: // new line
+ console_cur_pos += (80 - (console_cur_pos % 80));
+ break;
+ case 0x0B: // home
+ case 0x0C: // form feed
+ console_cur_pos = 0;
+ asm(
+ "cld\n"
+ "mov $32,%%ax\n"
+ "mov %%ax,%%es\n"
+ "xor %%edi,%%edi\n"
+ "mov %0,%%ah\n"
+ "mov $0x20,%%al\n"
+ "mov $2000,%%ecx\n"
+ "rep stosw"
+ : : "m" (attr)
+ );
+ break;
+ case 0x0D: // carriage return
+ console_cur_pos -= (console_cur_pos % 80);
+ break;
+ default:
+ ANSI2ASCII(text);
+ asm(
+ "cld\n"
+ "mov $32,%%ax\n"
+ "mov %%ax,%%es\n"
+ "xor %%eax,%%eax\n"
+ "mov %0,%%ax\n"
+ "shl $1,%%eax\n"
+ "mov %%eax,%%edi\n"
+ "mov %1,%%al\n"
+ "mov %2,%%ah\n"
+ "stosw"
+ : : "m" (console_cur_pos), "m" (text), "m" (attr)
+ );
+ console_cur_pos++;
+ }
+ // scroll
+ if(console_cur_pos >= 2000) {
+ console_cur_pos -= 80;
+ asm(
+ "cld\n"
+ "push %%ds\n"
+
+ "mov $32,%%ax\n"
+ "mov %%ax,%%ds\n"
+ "mov %%ax,%%es\n"
+ "mov $1920,%%ecx\n"
+ "mov $160,%%esi\n"
+ "xor %%edi,%%edi\n"
+ "rep movsw\n"
+
+ "mov $80,%%cx\n"
+ "mov %%cs:%0,%%ah\n"
+ "mov $0x20,%%al\n"
+ "rep stosw\n"
+
+ "pop %%ds"
+ : : "m" (console_std_attr)
+ );
+ }
+ PRINT_OFF;
+}
diff --git a/system/timer.c b/system/timer.c
new file mode 100644
index 0000000..847cfb0
--- /dev/null
+++ b/system/timer.c
@@ -0,0 +1,9 @@
+#include <timer.h>
+#include <system.h>
+
+TIMER timers = {0};
+
+void sleep(unsigned long ms) {
+ timers.time = (ms + 9)/10;
+ while(timers.time) asm("incl %0; decl %0" : "+m" (timers.time));
+}