Adds starting processes via multiboot modules. Removes built-in module. Splits main.cu in main.cu and keyboard.cu.
This commit is contained in:
parent
6599c6c306
commit
ebb537d5e1
9 changed files with 618 additions and 582 deletions
27
Depfile
27
Depfile
|
@ -2,9 +2,11 @@
|
||||||
Artifact=kernel
|
Artifact=kernel
|
||||||
TempDir=obj
|
TempDir=obj
|
||||||
SourceDir=asm src csl
|
SourceDir=asm src csl
|
||||||
AdditionalObjects=obj/main.o
|
AdditionalObjects=
|
||||||
ExternalObjects=conductance/|*.o
|
ExternalObjects=conductance/|*.o
|
||||||
|
|
||||||
|
AdditionalDependencies=obj/main.in obj/keyboard.in
|
||||||
|
|
||||||
LexUseCpp
|
LexUseCpp
|
||||||
YaccUseCpp
|
YaccUseCpp
|
||||||
|
|
||||||
|
@ -28,25 +30,28 @@ LDFLAGS=-nostdlib -fno-builtin -Tkernel.ld
|
||||||
|
|
||||||
TOOLS=/home/felix/projects/Electronics/build-Electronics-Clang-Debug/bin
|
TOOLS=/home/felix/projects/Electronics/build-Electronics-Clang-Debug/bin
|
||||||
|
|
||||||
obj/main.o: scripts/main.cu
|
obj/main.in: scripts/main.cu
|
||||||
$(TOOLS)/copper \
|
$(TOOLS)/copper \
|
||||||
scripts/main.cu > \
|
scripts/main.cu > \
|
||||||
scripts/main.cu.spark
|
scripts/main.cu.spark
|
||||||
$(TOOLS)/spark \
|
$(TOOLS)/spark \
|
||||||
scripts/main.cu.spark \
|
scripts/main.cu.spark \
|
||||||
obj/main.in
|
obj/main.in
|
||||||
objcopy -B i386 -I binary -O elf32-i386 \
|
|
||||||
obj/main.in obj/main.o
|
obj/keyboard.in: scripts/keyboard.cu
|
||||||
objcopy \
|
$(TOOLS)/copper \
|
||||||
--redefine-sym _binary_obj_main_in_start=mainscript_start \
|
scripts/keyboard.cu > \
|
||||||
--redefine-sym _binary_obj_main_in_end=mainscript_end \
|
scripts/keyboard.cu.spark
|
||||||
--redefine-sym _binary_obj_main_in_size=mainscript_size \
|
$(TOOLS)/spark \
|
||||||
obj/main.o
|
scripts/keyboard.cu.spark \
|
||||||
|
obj/keyboard.in
|
||||||
|
|
||||||
|
QEMUFLAGS=-serial stdio -kernel kernel -initrd obj/main.in,obj/keyboard.in
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run:
|
run:
|
||||||
qemu-system-i386 -serial stdio -kernel kernel
|
qemu-system-i386 $(QEMUFLAGS)
|
||||||
|
|
||||||
.PHONY: debug
|
.PHONY: debug
|
||||||
debug:
|
debug:
|
||||||
qemu-system-i386 -s -S -serial stdio -kernel kernel
|
qemu-system-i386 -s -S $(QEMUFLAGS)
|
||||||
|
|
35
Makefile
35
Makefile
|
@ -14,7 +14,7 @@ TEMPLE = mono temple.exe
|
||||||
SRCS_AS = asm/dynamic.S asm/intr_common_handler.S asm/multiboot.S asm/start.S
|
SRCS_AS = asm/dynamic.S asm/intr_common_handler.S asm/multiboot.S asm/start.S
|
||||||
SRCS_CC = src/console.c src/init.c src/interrupts.c src/malloc.c src/pmm.c src/serial.c src/stdlib.c src/timer.c src/vmm.c
|
SRCS_CC = src/console.c src/init.c src/interrupts.c src/malloc.c src/pmm.c src/serial.c src/stdlib.c src/timer.c src/vmm.c
|
||||||
SRCS_CXX = src/cplusplus.cpp src/vm.cpp csl/casts.cpp csl/cpustatetype.cpp csl/io.cpp
|
SRCS_CXX = src/cplusplus.cpp src/vm.cpp csl/casts.cpp csl/cpustatetype.cpp csl/io.cpp
|
||||||
OBJS = obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o obj/main.o
|
OBJS = obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o
|
||||||
|
|
||||||
# Flags
|
# Flags
|
||||||
FLAGS = -g -Wall -Wextra -m32 -DCIRCUIT_OS -Dnullptr=0 -D__cdecl="__attribute__((cdecl))" -mno-sse -mno-sse2 -mno-mmx -I/home/felix/projects/Electronics/Electronics/Conductance -I/home/felix/projects/Electronics/Electronics/Tools
|
FLAGS = -g -Wall -Wextra -m32 -DCIRCUIT_OS -Dnullptr=0 -D__cdecl="__attribute__((cdecl))" -mno-sse -mno-sse2 -mno-mmx -I/home/felix/projects/Electronics/Electronics/Conductance -I/home/felix/projects/Electronics/Electronics/Tools
|
||||||
|
@ -28,10 +28,10 @@ all: kernel
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
$(RM) obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o obj/main.o
|
$(RM) obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o
|
||||||
|
|
||||||
kernel: obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o obj/main.o conductance/assembly.o conductance/compoundtype.o conductance/instructions.o conductance/process.o conductance/string.o conductance/thread.o conductance/virtualmachine.o conductance/vmpointertype.o conductance/vmprimitivetype.o conductance/vmtype.o conductance/vmvalue.o conductance/vmvoidtype.o
|
kernel: obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o conductance/assembly.o conductance/compoundtype.o conductance/instructions.o conductance/process.o conductance/string.o conductance/thread.o conductance/virtualmachine.o conductance/vmpointertype.o conductance/vmprimitivetype.o conductance/vmtype.o conductance/vmvalue.o conductance/vmvoidtype.o obj/main.in obj/keyboard.in
|
||||||
$(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o obj/main.o conductance/assembly.o conductance/compoundtype.o conductance/instructions.o conductance/process.o conductance/string.o conductance/thread.o conductance/virtualmachine.o conductance/vmpointertype.o conductance/vmprimitivetype.o conductance/vmtype.o conductance/vmvalue.o conductance/vmvoidtype.o
|
$(LD) $(FLAGS) $(LDFLAGS) -o $@ obj/dynamic.o obj/intr_common_handler.o obj/multiboot.o obj/start.o obj/console.o obj/init.o obj/interrupts.o obj/malloc.o obj/pmm.o obj/serial.o obj/stdlib.o obj/timer.o obj/vmm.o obj/cplusplus.o obj/vm.o obj/casts.o obj/cpustatetype.o obj/io.o conductance/assembly.o conductance/compoundtype.o conductance/instructions.o conductance/process.o conductance/string.o conductance/thread.o conductance/virtualmachine.o conductance/vmpointertype.o conductance/vmprimitivetype.o conductance/vmtype.o conductance/vmvalue.o conductance/vmvoidtype.o
|
||||||
|
|
||||||
# src/console.c
|
# src/console.c
|
||||||
obj/console.o: src/console.c include/console.h include/kstdlib.h \
|
obj/console.o: src/console.c include/console.h include/kstdlib.h \
|
||||||
|
@ -92,8 +92,8 @@ obj/cplusplus.o: src/cplusplus.cpp include/kstdlib.h include/varargs.h \
|
||||||
# src/vm.cpp
|
# src/vm.cpp
|
||||||
obj/vm.o: src/vm.cpp include/kstdlib.h include/varargs.h include/config.h \
|
obj/vm.o: src/vm.cpp include/kstdlib.h include/varargs.h include/config.h \
|
||||||
include/malloc.h include/timer.h include/dynamic.h include/console.h \
|
include/malloc.h include/timer.h include/dynamic.h include/console.h \
|
||||||
include/interrupts.h include/cpustate.h src/../csl/cpustatetype.hpp \
|
include/multiboot.h include/interrupts.h include/cpustate.h \
|
||||||
src/../csl/io.hpp src/../csl/casts.hpp
|
src/../csl/cpustatetype.hpp src/../csl/io.hpp src/../csl/casts.hpp
|
||||||
$(CXX) -iquoteobj $(FLAGS) $(CXXFLAGS) -o $@ -c src/vm.cpp
|
$(CXX) -iquoteobj $(FLAGS) $(CXXFLAGS) -o $@ -c src/vm.cpp
|
||||||
|
|
||||||
# csl/casts.cpp
|
# csl/casts.cpp
|
||||||
|
@ -129,25 +129,28 @@ obj/start.o: asm/start.S
|
||||||
|
|
||||||
TOOLS=/home/felix/projects/Electronics/build-Electronics-Clang-Debug/bin
|
TOOLS=/home/felix/projects/Electronics/build-Electronics-Clang-Debug/bin
|
||||||
|
|
||||||
obj/main.o: scripts/main.cu
|
obj/main.in: scripts/main.cu
|
||||||
$(TOOLS)/copper \
|
$(TOOLS)/copper \
|
||||||
scripts/main.cu > \
|
scripts/main.cu > \
|
||||||
scripts/main.cu.spark
|
scripts/main.cu.spark
|
||||||
$(TOOLS)/spark \
|
$(TOOLS)/spark \
|
||||||
scripts/main.cu.spark \
|
scripts/main.cu.spark \
|
||||||
obj/main.in
|
obj/main.in
|
||||||
objcopy -B i386 -I binary -O elf32-i386 \
|
|
||||||
obj/main.in obj/main.o
|
obj/keyboard.in: scripts/keyboard.cu
|
||||||
objcopy \
|
$(TOOLS)/copper \
|
||||||
--redefine-sym _binary_obj_main_in_start=mainscript_start \
|
scripts/keyboard.cu > \
|
||||||
--redefine-sym _binary_obj_main_in_end=mainscript_end \
|
scripts/keyboard.cu.spark
|
||||||
--redefine-sym _binary_obj_main_in_size=mainscript_size \
|
$(TOOLS)/spark \
|
||||||
obj/main.o
|
scripts/keyboard.cu.spark \
|
||||||
|
obj/keyboard.in
|
||||||
|
|
||||||
|
QEMUFLAGS=-serial stdio -kernel kernel -initrd obj/main.in,obj/keyboard.in
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run:
|
run:
|
||||||
qemu-system-i386 -serial stdio -kernel kernel
|
qemu-system-i386 $(QEMUFLAGS)
|
||||||
|
|
||||||
.PHONY: debug
|
.PHONY: debug
|
||||||
debug:
|
debug:
|
||||||
qemu-system-i386 -s -S -serial stdio -kernel kernel
|
qemu-system-i386 -s -S $(QEMUFLAGS)
|
||||||
|
|
154
scripts/keyboard.cu
Normal file
154
scripts/keyboard.cu
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
|
||||||
|
.asmtype DRIVER
|
||||||
|
.name KEYBOARDDRIVER
|
||||||
|
|
||||||
|
NATIVE print(...);
|
||||||
|
|
||||||
|
NATIVE outb(port : UINT16, value : UINT8);
|
||||||
|
NATIVE inb(port : UINT16) → UINT8;
|
||||||
|
|
||||||
|
NATIVE toInt32(…) → INT32;
|
||||||
|
NATIVE toUInt16(…) → UINT16;
|
||||||
|
|
||||||
|
TYPE CpuState IS
|
||||||
|
eax : UINT32;
|
||||||
|
ebx : UINT32;
|
||||||
|
ecx : UINT32;
|
||||||
|
END
|
||||||
|
|
||||||
|
PRI sendCommand(cmd : UINT8)
|
||||||
|
BEGIN
|
||||||
|
# Warten bis die Tastatur bereit ist, und der Befehlspuffer leer ist
|
||||||
|
WHILE (inb(100u16) & 2u8) =/= 0u8 DO
|
||||||
|
|
||||||
|
END
|
||||||
|
outb(toUInt16(96), cmd);
|
||||||
|
END
|
||||||
|
|
||||||
|
PRI initKeyboard()
|
||||||
|
BEGIN
|
||||||
|
# Tastaturpuffer leeren
|
||||||
|
WHILE (inb(100u16) & 1u8) =/= 0u8 DO
|
||||||
|
inb(96u16);
|
||||||
|
END
|
||||||
|
|
||||||
|
# Tastatur aktivieren
|
||||||
|
# sendCommand(244u8);
|
||||||
|
END
|
||||||
|
|
||||||
|
PRI handleKeyPress(keycode : INT, released : BOOL)
|
||||||
|
BEGIN
|
||||||
|
IF released = FALSE THEN
|
||||||
|
print("[keycode=", keycode, "]\n");
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
PUB main() | i : INT
|
||||||
|
BEGIN
|
||||||
|
print("Initialize keyboard...\n");
|
||||||
|
initKeyboard();
|
||||||
|
END
|
||||||
|
|
||||||
|
# Status-Variablen fuer das Behandeln von e0- und e1-Scancodes
|
||||||
|
VAR e0Code : BOOL;
|
||||||
|
|
||||||
|
# Wird auf 1 gesetzt, sobald e1 gelesen wurde, und auf 2, sobald das erste
|
||||||
|
# Datenbyte gelesen wurde
|
||||||
|
VAR e1Code : INT;
|
||||||
|
|
||||||
|
VAR e1Prev : UINT16;
|
||||||
|
|
||||||
|
PRI translateKeyCode(extend : INT, scancode : INT) → keycode : INT
|
||||||
|
BEGIN
|
||||||
|
print("[extend=", extend, ",scancode=", scancode, "]\n");
|
||||||
|
0 → keycode;
|
||||||
|
IF extend = 0 THEN
|
||||||
|
# LOTS OF CODE HERE. Maybe optimize this? :P
|
||||||
|
IF scancode = 10 THEN 1 → keycode; RETURN; END
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
PRI handleKeyboardIRQ() | scancode : UINT8, keycode : INT, breakcode : BOOL
|
||||||
|
BEGIN
|
||||||
|
0 → keycode;
|
||||||
|
FALSE → breakcode;
|
||||||
|
inb(96u16) → scancode;
|
||||||
|
|
||||||
|
# Um einen Breakcode handelt es sich, wenn das oberste Bit gesetzt ist und
|
||||||
|
# es kein e0 oder e1 fuer einen Extended-scancode ist
|
||||||
|
IF ((scancode & 0x80u8) =/= 0u8) & ((e1Code =/= 0) | (scancode =/= 0xE1u8)) & (e0Code | (scancode =/= 0xE0u8)) THEN
|
||||||
|
TRUE → breakcode;
|
||||||
|
(scancode & 127u8) → scancode;
|
||||||
|
END
|
||||||
|
|
||||||
|
# print("[scancode=", scancode, ",breakcode=", breakcode, "]");
|
||||||
|
|
||||||
|
IF e0Code THEN
|
||||||
|
# Fake shift abfangen und ignorieren
|
||||||
|
IF (scancode = 0x2Au8) | (scancode = 0x36u8) THEN
|
||||||
|
FALSE → e0Code;
|
||||||
|
RETURN;
|
||||||
|
END
|
||||||
|
|
||||||
|
translateKeyCode(1, toInt32(scancode)) → keycode;
|
||||||
|
FALSE → e0Code;
|
||||||
|
ELSE
|
||||||
|
IF e1Code = 2 THEN
|
||||||
|
# Fertiger e1-Scancode
|
||||||
|
# Zweiten Scancode in hoeherwertiges Byte packen
|
||||||
|
(e1Prev | toUInt16(scancode * 256u8)) → e1Prev;
|
||||||
|
translateKeyCode(2, toInt32(e1Prev)) → keycode;
|
||||||
|
0 → e1Code;
|
||||||
|
ELSE
|
||||||
|
IF e1Code = 1 THEN
|
||||||
|
# Erstes Byte fuer e1-Scancode
|
||||||
|
toUInt16(scancode) → e1Prev;
|
||||||
|
2 → e1Code;
|
||||||
|
ELSE
|
||||||
|
IF scancode = 0xE0u8 THEN
|
||||||
|
TRUE → e0Code;
|
||||||
|
ELSE
|
||||||
|
IF scancode = 0xE1u8 THEN
|
||||||
|
1 → e1Code;
|
||||||
|
ELSE
|
||||||
|
translateKeyCode(0, toInt32(scancode)) → keycode;
|
||||||
|
END
|
||||||
|
END
|
||||||
|
END
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
IF keycode =/= 0 THEN
|
||||||
|
handleKeyPress(keycode, breakcode);
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
PUB irq(id : INT, data : CpuState)
|
||||||
|
BEGIN
|
||||||
|
# print("irq:", id, ", ", data.eax, " ", data.ebx, "\n");
|
||||||
|
IF id = 33 THEN
|
||||||
|
handleKeyboardIRQ();
|
||||||
|
END
|
||||||
|
~data;
|
||||||
|
END
|
||||||
|
|
||||||
|
#!
|
||||||
|
Was noch gemacht werden muss, bis der Tastatur-Treiber funktionieren könnte:
|
||||||
|
☑ Support für beliebige Typen in Copper
|
||||||
|
☑ Pushen von Typen != INT
|
||||||
|
☑ erweiterung von pushi um typcode (u?int(8|16|32), bool)
|
||||||
|
☑ erweiterung von pushr um typcode
|
||||||
|
☑ Simple type checks in Copper
|
||||||
|
☑ Custom types in Copper
|
||||||
|
☑ Native function calls in Copper
|
||||||
|
☑ Bitwise Operations
|
||||||
|
☑ outb und inb
|
||||||
|
☑ NEW/DELETE
|
||||||
|
☑ [TYPE] →
|
||||||
|
☑ ~()
|
||||||
|
☑ hex literals für Copper
|
||||||
|
☑ 'RETURN' für Copper
|
||||||
|
Was noch gemacht werden muss, bis der Tastatur-Treiber schön aussieht:
|
||||||
|
☐ ELSE-IF
|
||||||
|
☐ ARRAYS
|
||||||
|
!#
|
313
scripts/keyboard.cu.spark
Normal file
313
scripts/keyboard.cu.spark
Normal file
|
@ -0,0 +1,313 @@
|
||||||
|
; =============================================
|
||||||
|
; compiled with Copper 1.0
|
||||||
|
; 2015-10-16 13:36:11
|
||||||
|
; =============================================
|
||||||
|
|
||||||
|
.asmtype DRIVER
|
||||||
|
.name KEYBOARDDRIVER
|
||||||
|
; native method: print(…)
|
||||||
|
; native method: outb(…)
|
||||||
|
; native method: inb(…) → UINT8
|
||||||
|
; native method: toInt32(…) → INT32
|
||||||
|
; native method: toUInt16(…) → UINT16
|
||||||
|
.type CpuState {
|
||||||
|
eax : UINT32;
|
||||||
|
ebx : UINT32;
|
||||||
|
ecx : UINT32;
|
||||||
|
}
|
||||||
|
.global e0Code BOOL
|
||||||
|
.global e1Code INT32
|
||||||
|
.global e1Prev UINT16
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; 0, sendCommand
|
||||||
|
sendCommand:
|
||||||
|
pushnil ; return value
|
||||||
|
_private_0:
|
||||||
|
pushi 4 100
|
||||||
|
callnr inb 1
|
||||||
|
pushi 3 2
|
||||||
|
op2 12
|
||||||
|
pushi 3 0
|
||||||
|
op2 6
|
||||||
|
jmp_if_not _private_1
|
||||||
|
jmp _private_0
|
||||||
|
_private_1:
|
||||||
|
|
||||||
|
load -1
|
||||||
|
pushi 2 96
|
||||||
|
callnr toUInt16 1
|
||||||
|
calln outb 2
|
||||||
|
|
||||||
|
ret
|
||||||
|
; end of sendCommand
|
||||||
|
|
||||||
|
; 0, initKeyboard
|
||||||
|
initKeyboard:
|
||||||
|
pushnil ; return value
|
||||||
|
_private_2:
|
||||||
|
pushi 4 100
|
||||||
|
callnr inb 1
|
||||||
|
pushi 3 1
|
||||||
|
op2 12
|
||||||
|
pushi 3 0
|
||||||
|
op2 6
|
||||||
|
jmp_if_not _private_3
|
||||||
|
pushi 4 96
|
||||||
|
calln inb 1
|
||||||
|
|
||||||
|
jmp _private_2
|
||||||
|
_private_3:
|
||||||
|
|
||||||
|
ret
|
||||||
|
; end of initKeyboard
|
||||||
|
|
||||||
|
; 0, handleKeyPress
|
||||||
|
handleKeyPress:
|
||||||
|
pushnil ; return value
|
||||||
|
load -2
|
||||||
|
pushi 6 0
|
||||||
|
op2 5
|
||||||
|
jmp_if_not _private_4
|
||||||
|
pusht "]\n"
|
||||||
|
load -1
|
||||||
|
pusht "[keycode="
|
||||||
|
calln print 3
|
||||||
|
|
||||||
|
_private_4:
|
||||||
|
|
||||||
|
ret
|
||||||
|
; end of handleKeyPress
|
||||||
|
|
||||||
|
; 1, main
|
||||||
|
.export main
|
||||||
|
main:
|
||||||
|
pushnil ; return value
|
||||||
|
pushnil ; i:INT32
|
||||||
|
pusht "Initialize keyboard...\n"
|
||||||
|
calln print 1
|
||||||
|
|
||||||
|
call initKeyboard 0
|
||||||
|
|
||||||
|
ret
|
||||||
|
; end of main
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; 0, translateKeyCode
|
||||||
|
translateKeyCode:
|
||||||
|
pushnil ; return value
|
||||||
|
pusht "]\n"
|
||||||
|
load -2
|
||||||
|
pusht ",scancode="
|
||||||
|
load -1
|
||||||
|
pusht "[extend="
|
||||||
|
calln print 5
|
||||||
|
|
||||||
|
pushi 2 0
|
||||||
|
store 0
|
||||||
|
|
||||||
|
load -1
|
||||||
|
pushi 2 0
|
||||||
|
op2 5
|
||||||
|
jmp_if_not _private_5
|
||||||
|
load -2
|
||||||
|
pushi 2 10
|
||||||
|
op2 5
|
||||||
|
jmp_if_not _private_6
|
||||||
|
pushi 2 1
|
||||||
|
store 0
|
||||||
|
|
||||||
|
load 0
|
||||||
|
retr
|
||||||
|
|
||||||
|
_private_6:
|
||||||
|
|
||||||
|
_private_5:
|
||||||
|
|
||||||
|
load 0
|
||||||
|
retr
|
||||||
|
; end of translateKeyCode
|
||||||
|
|
||||||
|
; 0, handleKeyboardIRQ
|
||||||
|
handleKeyboardIRQ:
|
||||||
|
pushnil ; return value
|
||||||
|
pushnil ; scancode:UINT8
|
||||||
|
pushnil ; keycode:INT32
|
||||||
|
pushnil ; breakcode:BOOL
|
||||||
|
pushi 2 0
|
||||||
|
store 2
|
||||||
|
|
||||||
|
pushi 6 0
|
||||||
|
store 3
|
||||||
|
|
||||||
|
pushi 4 96
|
||||||
|
callnr inb 1
|
||||||
|
store 1
|
||||||
|
|
||||||
|
load 1
|
||||||
|
pushi 3 128
|
||||||
|
op2 12
|
||||||
|
pushi 3 0
|
||||||
|
op2 6
|
||||||
|
loadg e1Code
|
||||||
|
pushi 2 0
|
||||||
|
op2 6
|
||||||
|
load 1
|
||||||
|
pushi 3 225
|
||||||
|
op2 6
|
||||||
|
op2 11
|
||||||
|
loadg e0Code
|
||||||
|
load 1
|
||||||
|
pushi 3 224
|
||||||
|
op2 6
|
||||||
|
op2 11
|
||||||
|
op2 12
|
||||||
|
op2 12
|
||||||
|
jmp_if_not _private_7
|
||||||
|
pushi 6 1
|
||||||
|
store 3
|
||||||
|
|
||||||
|
load 1
|
||||||
|
pushi 3 127
|
||||||
|
op2 12
|
||||||
|
store 1
|
||||||
|
|
||||||
|
_private_7:
|
||||||
|
|
||||||
|
loadg e0Code
|
||||||
|
jmp_if_not _private_8
|
||||||
|
load 1
|
||||||
|
pushi 3 42
|
||||||
|
op2 5
|
||||||
|
load 1
|
||||||
|
pushi 3 54
|
||||||
|
op2 5
|
||||||
|
op2 11
|
||||||
|
jmp_if_not _private_10
|
||||||
|
pushi 6 0
|
||||||
|
storeg e0Code
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
_private_10:
|
||||||
|
|
||||||
|
load 1
|
||||||
|
callnr toInt32 1
|
||||||
|
pushi 2 1
|
||||||
|
callr translateKeyCode 2
|
||||||
|
store 2
|
||||||
|
|
||||||
|
pushi 6 0
|
||||||
|
storeg e0Code
|
||||||
|
|
||||||
|
jmp _private_9
|
||||||
|
_private_8:
|
||||||
|
loadg e1Code
|
||||||
|
pushi 2 2
|
||||||
|
op2 5
|
||||||
|
jmp_if_not _private_11
|
||||||
|
loadg e1Prev
|
||||||
|
load 1
|
||||||
|
pushi 3 256
|
||||||
|
op2 2
|
||||||
|
callnr toUInt16 1
|
||||||
|
op2 11
|
||||||
|
storeg e1Prev
|
||||||
|
|
||||||
|
loadg e1Prev
|
||||||
|
callnr toInt32 1
|
||||||
|
pushi 2 2
|
||||||
|
callr translateKeyCode 2
|
||||||
|
store 2
|
||||||
|
|
||||||
|
pushi 2 0
|
||||||
|
storeg e1Code
|
||||||
|
|
||||||
|
jmp _private_12
|
||||||
|
_private_11:
|
||||||
|
loadg e1Code
|
||||||
|
pushi 2 1
|
||||||
|
op2 5
|
||||||
|
jmp_if_not _private_13
|
||||||
|
load 1
|
||||||
|
callnr toUInt16 1
|
||||||
|
storeg e1Prev
|
||||||
|
|
||||||
|
pushi 2 2
|
||||||
|
storeg e1Code
|
||||||
|
|
||||||
|
jmp _private_14
|
||||||
|
_private_13:
|
||||||
|
load 1
|
||||||
|
pushi 3 224
|
||||||
|
op2 5
|
||||||
|
jmp_if_not _private_15
|
||||||
|
pushi 6 1
|
||||||
|
storeg e0Code
|
||||||
|
|
||||||
|
jmp _private_16
|
||||||
|
_private_15:
|
||||||
|
load 1
|
||||||
|
pushi 3 225
|
||||||
|
op2 5
|
||||||
|
jmp_if_not _private_17
|
||||||
|
pushi 2 1
|
||||||
|
storeg e1Code
|
||||||
|
|
||||||
|
jmp _private_18
|
||||||
|
_private_17:
|
||||||
|
load 1
|
||||||
|
callnr toInt32 1
|
||||||
|
pushi 2 0
|
||||||
|
callr translateKeyCode 2
|
||||||
|
store 2
|
||||||
|
|
||||||
|
_private_18:
|
||||||
|
|
||||||
|
_private_16:
|
||||||
|
|
||||||
|
_private_14:
|
||||||
|
|
||||||
|
_private_12:
|
||||||
|
|
||||||
|
_private_9:
|
||||||
|
|
||||||
|
load 2
|
||||||
|
pushi 2 0
|
||||||
|
op2 6
|
||||||
|
jmp_if_not _private_19
|
||||||
|
load 3
|
||||||
|
load 2
|
||||||
|
call handleKeyPress 2
|
||||||
|
|
||||||
|
_private_19:
|
||||||
|
|
||||||
|
ret
|
||||||
|
; end of handleKeyboardIRQ
|
||||||
|
|
||||||
|
; 1, irq
|
||||||
|
.export irq
|
||||||
|
irq:
|
||||||
|
pushnil ; return value
|
||||||
|
load -1
|
||||||
|
pushi 2 33
|
||||||
|
op2 5
|
||||||
|
jmp_if_not _private_20
|
||||||
|
call handleKeyboardIRQ 0
|
||||||
|
|
||||||
|
_private_20:
|
||||||
|
|
||||||
|
load -2
|
||||||
|
destruct
|
||||||
|
|
||||||
|
ret
|
||||||
|
; end of irq
|
||||||
|
|
157
scripts/main.cu
157
scripts/main.cu
|
@ -2,58 +2,8 @@ NATIVE print(...);
|
||||||
|
|
||||||
NATIVE shutdown();
|
NATIVE shutdown();
|
||||||
|
|
||||||
NATIVE outb(port : UINT16, value : UINT8);
|
|
||||||
NATIVE inb(port : UINT16) → UINT8;
|
|
||||||
|
|
||||||
NATIVE toInt8(…) → INT8;
|
|
||||||
NATIVE toInt16(…) → INT16;
|
|
||||||
NATIVE toInt32(…) → INT32;
|
|
||||||
|
|
||||||
NATIVE toUInt8(…) → UINT8;
|
|
||||||
NATIVE toUInt16(…) → UINT16;
|
|
||||||
NATIVE toUInt32(…) → UINT32;
|
|
||||||
|
|
||||||
# NATIVE toBool(…) → BOOL;
|
|
||||||
# NATIVE toText(…) → TEXT;
|
|
||||||
|
|
||||||
TYPE CpuState IS
|
|
||||||
eax : UINT32;
|
|
||||||
ebx : UINT32;
|
|
||||||
ecx : UINT32;
|
|
||||||
END
|
|
||||||
|
|
||||||
PRI sendCommand(cmd : UINT8)
|
|
||||||
BEGIN
|
|
||||||
# Warten bis die Tastatur bereit ist, und der Befehlspuffer leer ist
|
|
||||||
WHILE (inb(100u16) & 2u8) =/= 0u8 DO
|
|
||||||
|
|
||||||
END
|
|
||||||
outb(toUInt16(96), cmd);
|
|
||||||
END
|
|
||||||
|
|
||||||
PRI initKeyboard()
|
|
||||||
BEGIN
|
|
||||||
# Tastaturpuffer leeren
|
|
||||||
WHILE (inb(100u16) & 1u8) =/= 0u8 DO
|
|
||||||
inb(96u16);
|
|
||||||
END
|
|
||||||
|
|
||||||
# Tastatur aktivieren
|
|
||||||
# sendCommand(244u8);
|
|
||||||
END
|
|
||||||
|
|
||||||
PRI handleKeyPress(keycode : INT, released : BOOL)
|
|
||||||
BEGIN
|
|
||||||
IF released = FALSE THEN
|
|
||||||
print("[keycode=", keycode, "]\n");
|
|
||||||
END
|
|
||||||
END
|
|
||||||
|
|
||||||
PUB main() | i : INT
|
PUB main() | i : INT
|
||||||
BEGIN
|
BEGIN
|
||||||
print("Initialize keyboard...\n");
|
|
||||||
initKeyboard();
|
|
||||||
|
|
||||||
print("Hello World!\n");
|
print("Hello World!\n");
|
||||||
1 → i;
|
1 → i;
|
||||||
WHILE i <= 5 DO
|
WHILE i <= 5 DO
|
||||||
|
@ -61,110 +11,3 @@ BEGIN
|
||||||
(i + 1) → i;
|
(i + 1) → i;
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
|
||||||
# Status-Variablen fuer das Behandeln von e0- und e1-Scancodes
|
|
||||||
VAR e0Code : BOOL;
|
|
||||||
# Wird auf 1 gesetzt, sobald e1 gelesen wurde, und auf 2, sobald das erste
|
|
||||||
# Datenbyte gelesen wurde
|
|
||||||
VAR e1Code : INT;
|
|
||||||
VAR e1Prev : UINT16;
|
|
||||||
|
|
||||||
PRI translateKeyCode(extend : INT, scancode : INT) → keycode : INT
|
|
||||||
BEGIN
|
|
||||||
print("[extend=", extend, ",scancode=", scancode, "]\n");
|
|
||||||
0 → keycode;
|
|
||||||
IF extend = 0 THEN
|
|
||||||
# LOTS OF CODE HERE. Maybe optimize this? :P
|
|
||||||
IF scancode = 10 THEN 1 → keycode; RETURN; END
|
|
||||||
END
|
|
||||||
END
|
|
||||||
|
|
||||||
PRI handleKeyboardIRQ() | scancode : UINT8, keycode : INT, breakcode : BOOL
|
|
||||||
BEGIN
|
|
||||||
0 → keycode;
|
|
||||||
FALSE → breakcode;
|
|
||||||
inb(96u16) → scancode;
|
|
||||||
|
|
||||||
# Um einen Breakcode handelt es sich, wenn das oberste Bit gesetzt ist und
|
|
||||||
# es kein e0 oder e1 fuer einen Extended-scancode ist
|
|
||||||
IF ((scancode & 0x80u8) =/= 0u8) & ((e1Code =/= 0) | (scancode =/= 0xE1u8)) & (e0Code | (scancode =/= 0xE0u8)) THEN
|
|
||||||
TRUE → breakcode;
|
|
||||||
(scancode & 127u8) → scancode;
|
|
||||||
END
|
|
||||||
|
|
||||||
IF scancode = 0x01u8 THEN
|
|
||||||
shutdown();
|
|
||||||
RETURN;
|
|
||||||
END
|
|
||||||
|
|
||||||
# print("[scancode=", scancode, ",breakcode=", breakcode, "]");
|
|
||||||
|
|
||||||
IF e0Code THEN
|
|
||||||
# Fake shift abfangen und ignorieren
|
|
||||||
IF (scancode = 0x2Au8) | (scancode = 0x36u8) THEN
|
|
||||||
FALSE → e0Code;
|
|
||||||
RETURN;
|
|
||||||
END
|
|
||||||
|
|
||||||
translateKeyCode(1, toInt32(scancode)) → keycode;
|
|
||||||
FALSE → e0Code;
|
|
||||||
ELSE
|
|
||||||
IF e1Code = 2 THEN
|
|
||||||
# Fertiger e1-Scancode
|
|
||||||
# Zweiten Scancode in hoeherwertiges Byte packen
|
|
||||||
(e1Prev | toUInt16(scancode * 256u8)) → e1Prev;
|
|
||||||
translateKeyCode(2, toInt32(e1Prev)) → keycode;
|
|
||||||
0 → e1Code;
|
|
||||||
ELSE
|
|
||||||
IF e1Code = 1 THEN
|
|
||||||
# Erstes Byte fuer e1-Scancode
|
|
||||||
toUInt16(scancode) → e1Prev;
|
|
||||||
2 → e1Code;
|
|
||||||
ELSE
|
|
||||||
IF scancode = 0xE0u8 THEN
|
|
||||||
TRUE → e0Code;
|
|
||||||
ELSE
|
|
||||||
IF scancode = 0xE1u8 THEN
|
|
||||||
1 → e1Code;
|
|
||||||
ELSE
|
|
||||||
translateKeyCode(0, toInt32(scancode)) → keycode;
|
|
||||||
END
|
|
||||||
END
|
|
||||||
END
|
|
||||||
END
|
|
||||||
END
|
|
||||||
|
|
||||||
IF keycode =/= 0 THEN
|
|
||||||
handleKeyPress(keycode, breakcode);
|
|
||||||
END
|
|
||||||
END
|
|
||||||
|
|
||||||
PUB irq(id : INT, data : CpuState)
|
|
||||||
BEGIN
|
|
||||||
# print("irq:", id, ", ", data.eax, " ", data.ebx, "\n");
|
|
||||||
IF id = 33 THEN
|
|
||||||
handleKeyboardIRQ();
|
|
||||||
END
|
|
||||||
~data;
|
|
||||||
END
|
|
||||||
|
|
||||||
#!
|
|
||||||
Was noch gemacht werden muss, bis der Tastatur-Treiber funktionieren könnte:
|
|
||||||
☑ Support für beliebige Typen in Copper
|
|
||||||
☑ Pushen von Typen != INT
|
|
||||||
☑ erweiterung von pushi um typcode (u?int(8|16|32), bool)
|
|
||||||
☑ erweiterung von pushr um typcode
|
|
||||||
☑ Simple type checks in Copper
|
|
||||||
☑ Custom types in Copper
|
|
||||||
☑ Native function calls in Copper
|
|
||||||
☑ Bitwise Operations
|
|
||||||
☑ outb und inb
|
|
||||||
☑ NEW/DELETE
|
|
||||||
☑ [TYPE] →
|
|
||||||
☑ ~()
|
|
||||||
☑ hex literals für Copper
|
|
||||||
☑ 'RETURN' für Copper
|
|
||||||
Was noch gemacht werden muss, bis der Tastatur-Treiber schön aussieht:
|
|
||||||
☐ ELSE-IF
|
|
||||||
☐ ARRAYS
|
|
||||||
!#
|
|
||||||
|
|
|
@ -1,117 +1,28 @@
|
||||||
; =============================================
|
; =============================================
|
||||||
; compiled with Copper 1.0
|
; compiled with Copper 1.0
|
||||||
; 2015-10-14 21:08:00
|
; 2015-10-16 13:32:19
|
||||||
; =============================================
|
; =============================================
|
||||||
|
|
||||||
; native method: print(…)
|
; native method: print(…)
|
||||||
; native method: shutdown(…)
|
; native method: shutdown(…)
|
||||||
; native method: outb(…)
|
|
||||||
; native method: inb(…) → UINT8
|
|
||||||
; native method: toInt8(…) → INT8
|
|
||||||
; native method: toInt16(…) → INT16
|
|
||||||
; native method: toInt32(…) → INT32
|
|
||||||
; native method: toUInt8(…) → UINT8
|
|
||||||
; native method: toUInt16(…) → UINT16
|
|
||||||
; native method: toUInt32(…) → UINT32
|
|
||||||
.type CpuState {
|
|
||||||
eax : UINT32;
|
|
||||||
ebx : UINT32;
|
|
||||||
ecx : UINT32;
|
|
||||||
}
|
|
||||||
.global e0Code BOOL
|
|
||||||
.global e1Code INT32
|
|
||||||
.global e1Prev UINT16
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; 0, sendCommand
|
|
||||||
sendCommand:
|
|
||||||
pushnil ; return value
|
|
||||||
_private_0:
|
|
||||||
pushi 4 100
|
|
||||||
callnr inb 1
|
|
||||||
pushi 3 2
|
|
||||||
op2 12
|
|
||||||
pushi 3 0
|
|
||||||
op2 6
|
|
||||||
jmp_if_not _private_1
|
|
||||||
jmp _private_0
|
|
||||||
_private_1:
|
|
||||||
|
|
||||||
load -1
|
|
||||||
pushi 2 96
|
|
||||||
callnr toUInt16 1
|
|
||||||
calln outb 2
|
|
||||||
|
|
||||||
ret
|
|
||||||
; end of sendCommand
|
|
||||||
|
|
||||||
; 0, initKeyboard
|
|
||||||
initKeyboard:
|
|
||||||
pushnil ; return value
|
|
||||||
_private_2:
|
|
||||||
pushi 4 100
|
|
||||||
callnr inb 1
|
|
||||||
pushi 3 1
|
|
||||||
op2 12
|
|
||||||
pushi 3 0
|
|
||||||
op2 6
|
|
||||||
jmp_if_not _private_3
|
|
||||||
pushi 4 96
|
|
||||||
calln inb 1
|
|
||||||
|
|
||||||
jmp _private_2
|
|
||||||
_private_3:
|
|
||||||
|
|
||||||
ret
|
|
||||||
; end of initKeyboard
|
|
||||||
|
|
||||||
; 0, handleKeyPress
|
|
||||||
handleKeyPress:
|
|
||||||
pushnil ; return value
|
|
||||||
load -2
|
|
||||||
pushi 6 0
|
|
||||||
op2 5
|
|
||||||
jmp_if_not _private_4
|
|
||||||
pusht "]\n"
|
|
||||||
load -1
|
|
||||||
pusht "[keycode="
|
|
||||||
calln print 3
|
|
||||||
|
|
||||||
_private_4:
|
|
||||||
|
|
||||||
ret
|
|
||||||
; end of handleKeyPress
|
|
||||||
|
|
||||||
; 1, main
|
; 1, main
|
||||||
.export main
|
.export main
|
||||||
main:
|
main:
|
||||||
pushnil ; return value
|
pushnil ; return value
|
||||||
pushnil ; i:INT32
|
pushnil ; i:INT32
|
||||||
pusht "Initialize keyboard...\n"
|
|
||||||
calln print 1
|
|
||||||
|
|
||||||
call initKeyboard 0
|
|
||||||
|
|
||||||
pusht "Hello World!\n"
|
pusht "Hello World!\n"
|
||||||
calln print 1
|
calln print 1
|
||||||
|
|
||||||
pushi 2 1
|
pushi 2 1
|
||||||
store 1
|
store 1
|
||||||
|
|
||||||
_private_5:
|
_private_0:
|
||||||
load 1
|
load 1
|
||||||
pushi 2 5
|
pushi 2 5
|
||||||
op2 8
|
op2 8
|
||||||
jmp_if_not _private_6
|
jmp_if_not _private_1
|
||||||
pusht "\n"
|
pusht "\n"
|
||||||
load 1
|
load 1
|
||||||
calln print 2
|
calln print 2
|
||||||
|
@ -121,232 +32,9 @@ _private_5:
|
||||||
op2 0
|
op2 0
|
||||||
store 1
|
store 1
|
||||||
|
|
||||||
jmp _private_5
|
jmp _private_0
|
||||||
_private_6:
|
_private_1:
|
||||||
|
|
||||||
ret
|
ret
|
||||||
; end of main
|
; end of main
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; 0, translateKeyCode
|
|
||||||
translateKeyCode:
|
|
||||||
pushnil ; return value
|
|
||||||
pusht "]\n"
|
|
||||||
load -2
|
|
||||||
pusht ",scancode="
|
|
||||||
load -1
|
|
||||||
pusht "[extend="
|
|
||||||
calln print 5
|
|
||||||
|
|
||||||
pushi 2 0
|
|
||||||
store 0
|
|
||||||
|
|
||||||
load -1
|
|
||||||
pushi 2 0
|
|
||||||
op2 5
|
|
||||||
jmp_if_not _private_7
|
|
||||||
load -2
|
|
||||||
pushi 2 10
|
|
||||||
op2 5
|
|
||||||
jmp_if_not _private_8
|
|
||||||
pushi 2 1
|
|
||||||
store 0
|
|
||||||
|
|
||||||
load 0
|
|
||||||
retr
|
|
||||||
|
|
||||||
_private_8:
|
|
||||||
|
|
||||||
_private_7:
|
|
||||||
|
|
||||||
load 0
|
|
||||||
retr
|
|
||||||
; end of translateKeyCode
|
|
||||||
|
|
||||||
; 0, handleKeyboardIRQ
|
|
||||||
handleKeyboardIRQ:
|
|
||||||
pushnil ; return value
|
|
||||||
pushnil ; scancode:UINT8
|
|
||||||
pushnil ; keycode:INT32
|
|
||||||
pushnil ; breakcode:BOOL
|
|
||||||
pushi 2 0
|
|
||||||
store 2
|
|
||||||
|
|
||||||
pushi 6 0
|
|
||||||
store 3
|
|
||||||
|
|
||||||
pushi 4 96
|
|
||||||
callnr inb 1
|
|
||||||
store 1
|
|
||||||
|
|
||||||
load 1
|
|
||||||
pushi 3 128
|
|
||||||
op2 12
|
|
||||||
pushi 3 0
|
|
||||||
op2 6
|
|
||||||
loadg e1Code
|
|
||||||
pushi 2 0
|
|
||||||
op2 6
|
|
||||||
load 1
|
|
||||||
pushi 3 225
|
|
||||||
op2 6
|
|
||||||
op2 11
|
|
||||||
loadg e0Code
|
|
||||||
load 1
|
|
||||||
pushi 3 224
|
|
||||||
op2 6
|
|
||||||
op2 11
|
|
||||||
op2 12
|
|
||||||
op2 12
|
|
||||||
jmp_if_not _private_9
|
|
||||||
pushi 6 1
|
|
||||||
store 3
|
|
||||||
|
|
||||||
load 1
|
|
||||||
pushi 3 127
|
|
||||||
op2 12
|
|
||||||
store 1
|
|
||||||
|
|
||||||
_private_9:
|
|
||||||
|
|
||||||
load 1
|
|
||||||
pushi 3 1
|
|
||||||
op2 5
|
|
||||||
jmp_if_not _private_10
|
|
||||||
calln shutdown 0
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
_private_10:
|
|
||||||
|
|
||||||
loadg e0Code
|
|
||||||
jmp_if_not _private_11
|
|
||||||
load 1
|
|
||||||
pushi 3 42
|
|
||||||
op2 5
|
|
||||||
load 1
|
|
||||||
pushi 3 54
|
|
||||||
op2 5
|
|
||||||
op2 11
|
|
||||||
jmp_if_not _private_13
|
|
||||||
pushi 6 0
|
|
||||||
storeg e0Code
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
_private_13:
|
|
||||||
|
|
||||||
load 1
|
|
||||||
callnr toInt32 1
|
|
||||||
pushi 2 1
|
|
||||||
callr translateKeyCode 2
|
|
||||||
store 2
|
|
||||||
|
|
||||||
pushi 6 0
|
|
||||||
storeg e0Code
|
|
||||||
|
|
||||||
jmp _private_12
|
|
||||||
_private_11:
|
|
||||||
loadg e1Code
|
|
||||||
pushi 2 2
|
|
||||||
op2 5
|
|
||||||
jmp_if_not _private_14
|
|
||||||
loadg e1Prev
|
|
||||||
load 1
|
|
||||||
pushi 3 256
|
|
||||||
op2 2
|
|
||||||
callnr toUInt16 1
|
|
||||||
op2 11
|
|
||||||
storeg e1Prev
|
|
||||||
|
|
||||||
loadg e1Prev
|
|
||||||
callnr toInt32 1
|
|
||||||
pushi 2 2
|
|
||||||
callr translateKeyCode 2
|
|
||||||
store 2
|
|
||||||
|
|
||||||
pushi 2 0
|
|
||||||
storeg e1Code
|
|
||||||
|
|
||||||
jmp _private_15
|
|
||||||
_private_14:
|
|
||||||
loadg e1Code
|
|
||||||
pushi 2 1
|
|
||||||
op2 5
|
|
||||||
jmp_if_not _private_16
|
|
||||||
load 1
|
|
||||||
callnr toUInt16 1
|
|
||||||
storeg e1Prev
|
|
||||||
|
|
||||||
pushi 2 2
|
|
||||||
storeg e1Code
|
|
||||||
|
|
||||||
jmp _private_17
|
|
||||||
_private_16:
|
|
||||||
load 1
|
|
||||||
pushi 3 224
|
|
||||||
op2 5
|
|
||||||
jmp_if_not _private_18
|
|
||||||
pushi 6 1
|
|
||||||
storeg e0Code
|
|
||||||
|
|
||||||
jmp _private_19
|
|
||||||
_private_18:
|
|
||||||
load 1
|
|
||||||
pushi 3 225
|
|
||||||
op2 5
|
|
||||||
jmp_if_not _private_20
|
|
||||||
pushi 2 1
|
|
||||||
storeg e1Code
|
|
||||||
|
|
||||||
jmp _private_21
|
|
||||||
_private_20:
|
|
||||||
load 1
|
|
||||||
callnr toInt32 1
|
|
||||||
pushi 2 0
|
|
||||||
callr translateKeyCode 2
|
|
||||||
store 2
|
|
||||||
|
|
||||||
_private_21:
|
|
||||||
|
|
||||||
_private_19:
|
|
||||||
|
|
||||||
_private_17:
|
|
||||||
|
|
||||||
_private_15:
|
|
||||||
|
|
||||||
_private_12:
|
|
||||||
|
|
||||||
load 2
|
|
||||||
pushi 2 0
|
|
||||||
op2 6
|
|
||||||
jmp_if_not _private_22
|
|
||||||
load 3
|
|
||||||
load 2
|
|
||||||
call handleKeyPress 2
|
|
||||||
|
|
||||||
_private_22:
|
|
||||||
|
|
||||||
ret
|
|
||||||
; end of handleKeyboardIRQ
|
|
||||||
|
|
||||||
; 1, irq
|
|
||||||
.export irq
|
|
||||||
irq:
|
|
||||||
pushnil ; return value
|
|
||||||
load -1
|
|
||||||
pushi 2 33
|
|
||||||
op2 5
|
|
||||||
jmp_if_not _private_23
|
|
||||||
call handleKeyboardIRQ 0
|
|
||||||
|
|
||||||
_private_23:
|
|
||||||
|
|
||||||
load -2
|
|
||||||
destruct
|
|
||||||
|
|
||||||
ret
|
|
||||||
; end of irq
|
|
||||||
|
|
||||||
|
|
44
src/init.c
44
src/init.c
|
@ -8,6 +8,13 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
|
|
||||||
|
static void halt()
|
||||||
|
{
|
||||||
|
while(1) {
|
||||||
|
__asm__ volatile ("cli; hlt;");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void die(const char *msg)
|
void die(const char *msg)
|
||||||
{
|
{
|
||||||
die_extra(msg, "");
|
die_extra(msg, "");
|
||||||
|
@ -23,10 +30,7 @@ void die_extra(const char *msg, const char *extra)
|
||||||
kputs(extra);
|
kputs(extra);
|
||||||
kputc('\'');
|
kputc('\'');
|
||||||
}
|
}
|
||||||
while(1)
|
halt();
|
||||||
{
|
|
||||||
__asm__ volatile ("cli; hlt;");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern size_t mallocCount;
|
extern size_t mallocCount;
|
||||||
|
@ -93,42 +97,42 @@ static void debug_test()
|
||||||
|
|
||||||
static void dumpMB(const MultibootStructure *mbHeader)
|
static void dumpMB(const MultibootStructure *mbHeader)
|
||||||
{
|
{
|
||||||
kputs("Multiboot Information:\n");
|
serial_printf(SERIAL_COM1, "Multiboot Information:\n");
|
||||||
if(mbHeader->flags & MB_MEMSIZE)
|
if(mbHeader->flags & MB_MEMSIZE)
|
||||||
{
|
{
|
||||||
kprintf("Lower Memory: %d kB\n", mbHeader->memLower);
|
serial_printf(SERIAL_COM1, " Lower Memory: %d kB\n", mbHeader->memLower);
|
||||||
kprintf("Upper Memory: %d kB\n", mbHeader->memUpper);
|
serial_printf(SERIAL_COM1, " Upper Memory: %d kB\n", mbHeader->memUpper);
|
||||||
}
|
}
|
||||||
// TODO: MB_BOOTDEVICE
|
// TODO: MB_BOOTDEVICE
|
||||||
if(mbHeader->flags & MB_COMMANDLINE)
|
if(mbHeader->flags & MB_COMMANDLINE)
|
||||||
{
|
{
|
||||||
kprintf("Commandline: %s\n", (const char*)mbHeader->commandline);
|
serial_printf(SERIAL_COM1, " Commandline: %s\n", (const char*)mbHeader->commandline);
|
||||||
}
|
}
|
||||||
if(mbHeader->flags & MB_MODULES)
|
if(mbHeader->flags & MB_MODULES)
|
||||||
{
|
{
|
||||||
const MultibootModule *mod = (const MultibootModule *)mbHeader->modules;
|
const MultibootModule *mod = (const MultibootModule *)mbHeader->modules;
|
||||||
for(size_t i = 0; i < mbHeader->moduleCount; i++)
|
for(size_t i = 0; i < mbHeader->moduleCount; i++)
|
||||||
{
|
{
|
||||||
kprintf("Module %s [%d - %d]\n", (const char*)mod[i].name, mod[i].start, mod[i].end);
|
serial_printf(SERIAL_COM1, " Module %s [%d - %d]\n", (const char*)mod[i].name, mod[i].start, mod[i].end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(mbHeader->flags & MB_SYMS_AOUT)
|
if(mbHeader->flags & MB_SYMS_AOUT)
|
||||||
{
|
{
|
||||||
kputs("Kernel File Format: a.out\n");
|
serial_printf(SERIAL_COM1, " Kernel File Format: a.out\n");
|
||||||
}
|
}
|
||||||
if(mbHeader->flags & MB_SYMS_ELF)
|
if(mbHeader->flags & MB_SYMS_ELF)
|
||||||
{
|
{
|
||||||
kputs("Kernel File Format: ELF\n");
|
serial_printf(SERIAL_COM1, " Kernel File Format: ELF\n");
|
||||||
}
|
}
|
||||||
if(mbHeader->flags & MB_MEMORYMAP)
|
if(mbHeader->flags & MB_MEMORYMAP)
|
||||||
{
|
{
|
||||||
uintptr_t it = mbHeader->memoryMap;
|
uintptr_t it = mbHeader->memoryMap;
|
||||||
kprintf("Memory Map: %d entries\n", mbHeader->memoryMapLength);
|
serial_printf(SERIAL_COM1, " Memory Map: %d entries\n", mbHeader->memoryMapLength);
|
||||||
for(size_t i = 0; i < mbHeader->memoryMapLength; i++)
|
for(size_t i = 0; i < mbHeader->memoryMapLength; i++)
|
||||||
{
|
{
|
||||||
const MultibootMemoryMap *mmap = (const MultibootMemoryMap *)it;
|
const MultibootMemoryMap *mmap = (const MultibootMemoryMap *)it;
|
||||||
if(mmap->type == 1)
|
if(mmap->type == 1)
|
||||||
kprintf("Memory Map: [%d + %d] %s\n", (uint32_t)mmap->base, (uint32_t)mmap->length, mmap->type == 1 ? "free" : "preserved");
|
serial_printf(SERIAL_COM1, " Memory Map: [%d + %d] %s\n", (uint32_t)mmap->base, (uint32_t)mmap->length, mmap->type == 1 ? "free" : "preserved");
|
||||||
it += mmap->entry_size + 4; // Stupid offset :P
|
it += mmap->entry_size + 4; // Stupid offset :P
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +140,7 @@ static void dumpMB(const MultibootStructure *mbHeader)
|
||||||
// TODO: MB_CONFIG_TABLE
|
// TODO: MB_CONFIG_TABLE
|
||||||
if(mbHeader->flags & MB_BOOTLOADER_NAME)
|
if(mbHeader->flags & MB_BOOTLOADER_NAME)
|
||||||
{
|
{
|
||||||
kprintf("Bootloader Name: %s\n", (const char*)mbHeader->bootLoaderName);
|
serial_printf(SERIAL_COM1, " Bootloader Name: %s\n", (const char*)mbHeader->bootLoaderName);
|
||||||
}
|
}
|
||||||
// TODO: MB_APS_TABLE
|
// TODO: MB_APS_TABLE
|
||||||
}
|
}
|
||||||
|
@ -152,7 +156,7 @@ void putsuccess()
|
||||||
kputs("[success]");
|
kputs("[success]");
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void vm_start();
|
extern void vm_start(const MultibootStructure *mbHeader);
|
||||||
|
|
||||||
void init(const MultibootStructure *mbHeader)
|
void init(const MultibootStructure *mbHeader)
|
||||||
{
|
{
|
||||||
|
@ -166,7 +170,11 @@ void init(const MultibootStructure *mbHeader)
|
||||||
serial_init(SERIAL_COM1, 9600, SERIAL_PARITY_NONE, 8);
|
serial_init(SERIAL_COM1, 9600, SERIAL_PARITY_NONE, 8);
|
||||||
serial_write_str(SERIAL_COM1, "Debug Console Ready\n");
|
serial_write_str(SERIAL_COM1, "Debug Console Ready\n");
|
||||||
|
|
||||||
//dumpMB(mbHeader);
|
dumpMB(mbHeader);
|
||||||
|
|
||||||
|
if(((mbHeader->flags & MB_MODULES) == 0) || (mbHeader->moduleCount == 0)) {
|
||||||
|
die_extra("BootProcessFailed", "No initial OS modules found.");
|
||||||
|
}
|
||||||
|
|
||||||
kputs("Initialize physical memory management: ");
|
kputs("Initialize physical memory management: ");
|
||||||
pmm_init(mbHeader);
|
pmm_init(mbHeader);
|
||||||
|
@ -210,7 +218,7 @@ void init(const MultibootStructure *mbHeader)
|
||||||
|
|
||||||
kputs("\n");
|
kputs("\n");
|
||||||
|
|
||||||
vm_start();
|
vm_start(mbHeader);
|
||||||
|
|
||||||
irq_disable();
|
irq_disable();
|
||||||
|
|
||||||
|
@ -222,7 +230,7 @@ void init(const MultibootStructure *mbHeader)
|
||||||
malloc_print_list(0);
|
malloc_print_list(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while(1);
|
halt();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
|
|
145
src/vm.cpp
145
src/vm.cpp
|
@ -2,6 +2,7 @@
|
||||||
#include <timer.h>
|
#include <timer.h>
|
||||||
#include <dynamic.h>
|
#include <dynamic.h>
|
||||||
#include <console.h>
|
#include <console.h>
|
||||||
|
#include <multiboot.h>
|
||||||
|
|
||||||
#include <virtualmachine.hpp>
|
#include <virtualmachine.hpp>
|
||||||
#include <vmtype.hpp>
|
#include <vmtype.hpp>
|
||||||
|
@ -13,16 +14,6 @@
|
||||||
#include "../csl/io.hpp"
|
#include "../csl/io.hpp"
|
||||||
#include "../csl/casts.hpp"
|
#include "../csl/casts.hpp"
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
extern const char mainscript_start;
|
|
||||||
extern const char mainscript_end;
|
|
||||||
extern const char mainscript_size;
|
|
||||||
|
|
||||||
extern const char firstrun_start;
|
|
||||||
extern const char firstrun_end;
|
|
||||||
extern const char firstrun_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void printVMValue(const VMValue &value)
|
void printVMValue(const VMValue &value)
|
||||||
{
|
{
|
||||||
switch(value.type().type()) {
|
switch(value.type().type()) {
|
||||||
|
@ -62,15 +53,6 @@ struct dtortest {
|
||||||
~dtortest() { free(mem); kprintf("[free]"); }
|
~dtortest() { free(mem); kprintf("[free]"); }
|
||||||
} ;// object;
|
} ;// object;
|
||||||
|
|
||||||
|
|
||||||
struct {
|
|
||||||
const char *ptr;
|
|
||||||
uint32_t size;
|
|
||||||
} mainAssembly {
|
|
||||||
&mainscript_start,
|
|
||||||
(uint32_t)&mainscript_size
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IrqList {
|
struct IrqList {
|
||||||
static const size_t length = 64;
|
static const size_t length = 64;
|
||||||
volatile uint32_t read;
|
volatile uint32_t read;
|
||||||
|
@ -127,7 +109,7 @@ ExceptionCode shutdown(VMValue &, const VMArray &)
|
||||||
|
|
||||||
int ReferenceCounted::counter = 0;
|
int ReferenceCounted::counter = 0;
|
||||||
|
|
||||||
extern "C" void vm_start()
|
extern "C" void vm_start(const MultibootStructure *mbHeader)
|
||||||
{
|
{
|
||||||
// intr_set_handler(0x20, vm_handle_interrupt);
|
// intr_set_handler(0x20, vm_handle_interrupt);
|
||||||
intr_set_handler(0x21, vm_handle_interrupt);
|
intr_set_handler(0x21, vm_handle_interrupt);
|
||||||
|
@ -148,26 +130,83 @@ extern "C" void vm_start()
|
||||||
machine.import("toUInt16") = csl::toUInt16;
|
machine.import("toUInt16") = csl::toUInt16;
|
||||||
machine.import("toUInt32") = csl::toUInt32;
|
machine.import("toUInt32") = csl::toUInt32;
|
||||||
|
|
||||||
Assembly *assembly = machine.load(mainAssembly.ptr, mainAssembly.size);
|
using DriverProcess = ker::Pair<Process*,uint32_t>;
|
||||||
if(assembly == nullptr) {
|
ker::Vector<DriverProcess> drivers;
|
||||||
kprintf("failed to load assembly :(\n");
|
|
||||||
return;
|
const MultibootModule *mod = (const MultibootModule *)mbHeader->modules;
|
||||||
|
for(size_t i = 0; i < mbHeader->moduleCount; i++)
|
||||||
|
{
|
||||||
|
kprintf("Loading Module '%s'...\n", (const char*)mod[i].name);
|
||||||
|
|
||||||
|
size_t len = mod[i].end - mod[i].start;
|
||||||
|
|
||||||
|
Assembly *assembly = machine.load(reinterpret_cast<void*>(mod[i].start), len);
|
||||||
|
if(assembly == nullptr) {
|
||||||
|
die("Failed to load assembly.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch(assembly->type())
|
||||||
|
{
|
||||||
|
case AssemblyType::Library:
|
||||||
|
{
|
||||||
|
// Assemblies don't need special treatment
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AssemblyType::Executable:
|
||||||
|
{
|
||||||
|
Process *program = machine.createProcess(assembly, false);
|
||||||
|
if(program == nullptr) {
|
||||||
|
die("Failed to create process.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
program->release();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AssemblyType::Service:
|
||||||
|
{
|
||||||
|
Process *program = machine.createProcess(assembly, true);
|
||||||
|
if(program == nullptr) {
|
||||||
|
die("Failed to create service process.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
program->release();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AssemblyType::Driver:
|
||||||
|
{
|
||||||
|
Process *program = machine.createProcess(assembly, true);
|
||||||
|
if(program == nullptr) {
|
||||||
|
die("Failed to create driver process.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(assembly->exports().contains("irq")) {
|
||||||
|
drivers.append({ program, assembly->exports()["irq"] });
|
||||||
|
} else {
|
||||||
|
program->release();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
die("OS.UnknownAssemblyType");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assembly->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
Process *irqService = machine.createProcess(assembly, true);
|
|
||||||
if(irqService == nullptr) {
|
|
||||||
kprintf("Failed to create process.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread *mainThread = irqService->mainThread();
|
|
||||||
|
|
||||||
uint32_t irqRoutine = irqService->assembly()->exports()["irq"];
|
|
||||||
|
|
||||||
bool osIsFailed = false;
|
|
||||||
|
|
||||||
while((shutdownRequested == false) && machine.step())
|
while((shutdownRequested == false) && machine.step())
|
||||||
{
|
{
|
||||||
|
// Remove all terminated drivers
|
||||||
|
for(size_t i = 0; i < drivers.length(); ) {
|
||||||
|
if(drivers[i].first->isRunning()) {
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
drivers[i].first->release();
|
||||||
|
drivers.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check for IRQ requests
|
// check for IRQ requests
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -182,14 +221,14 @@ extern "C" void vm_start()
|
||||||
|
|
||||||
CpuState *cpu = &irqFiFo.items[irqFiFo.read];
|
CpuState *cpu = &irqFiFo.items[irqFiFo.read];
|
||||||
|
|
||||||
//*
|
for(const auto &driver : drivers) {
|
||||||
Thread *thread = irqService->createThread(irqRoutine);
|
Thread *thread = driver.first->createThread(driver.second);
|
||||||
thread->start({
|
thread->start({
|
||||||
VMValue::Int32(cpu->intr),
|
VMValue::Int32(cpu->intr),
|
||||||
csl::createCpuState(cpu)
|
csl::createCpuState(cpu)
|
||||||
});
|
});
|
||||||
thread->release();
|
thread->release();
|
||||||
// */
|
}
|
||||||
irqFiFo.read += 1;
|
irqFiFo.read += 1;
|
||||||
|
|
||||||
irq_disable();
|
irq_disable();
|
||||||
|
@ -200,25 +239,7 @@ extern "C" void vm_start()
|
||||||
}
|
}
|
||||||
irq_enable();
|
irq_enable();
|
||||||
} while(true);
|
} while(true);
|
||||||
|
|
||||||
if(mainThread->isRunning() == false) {
|
|
||||||
if(osIsFailed == false) {
|
|
||||||
osIsFailed = true;
|
|
||||||
|
|
||||||
kprintf("OS failed with: %s\n", execptionName(mainThread->exception()));
|
|
||||||
|
|
||||||
// shutdownRequested = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mainThread->release();
|
|
||||||
mainThread = nullptr;
|
|
||||||
|
|
||||||
irqService->release();
|
|
||||||
irqService = nullptr;
|
|
||||||
|
|
||||||
assembly->release();
|
|
||||||
assembly = nullptr;
|
|
||||||
}
|
}
|
||||||
kprintf("\n");
|
kprintf("\n");
|
||||||
kprintf("unreleased objects: %d\n", ReferenceCounted::counter);
|
kprintf("unreleased objects: %d\n", ReferenceCounted::counter);
|
||||||
|
|
|
@ -59,7 +59,8 @@ DISTFILES += \
|
||||||
asm/dynamic.S \
|
asm/dynamic.S \
|
||||||
README.md \
|
README.md \
|
||||||
scripts/main.spark \
|
scripts/main.spark \
|
||||||
scripts/main.cu
|
scripts/main.cu \
|
||||||
|
scripts/keyboard.cu
|
||||||
|
|
||||||
INCLUDEPATH += include
|
INCLUDEPATH += include
|
||||||
DEPENDPATH += include
|
DEPENDPATH += include
|
||||||
|
|
Loading…
Reference in a new issue