Compare commits
47 commits
Author | SHA1 | Date | |
---|---|---|---|
|
7ead8809c2 | ||
|
5be0da8735 | ||
|
895135e97d | ||
|
5db7237341 | ||
|
4b28810372 | ||
|
32e0e9fde1 | ||
|
04dd9a9700 | ||
|
82382d2a99 | ||
|
5659ae1d0a | ||
|
e21bb03912 | ||
|
75db10c339 | ||
|
4560c19652 | ||
|
96dc726c35 | ||
|
c9601fae4a | ||
|
6ec5af6df5 | ||
|
49d00313e2 | ||
|
0e27f57bc6 | ||
|
68f5d64dad | ||
|
3d699d9db8 | ||
|
27376bc101 | ||
|
1eca77abaf | ||
|
7f4f0218d0 | ||
|
8ad1f12ebd | ||
|
c0a4c88c41 | ||
|
6ddc199b6a | ||
|
5a3ffbb1ec | ||
|
eae328afdb | ||
|
8cca5c8d1b | ||
|
9e0ed8a5d7 | ||
|
8a78faecdf | ||
|
6dc17daa09 | ||
|
15b3fde6e6 | ||
|
98c3fa059f | ||
|
5cb3b956d9 | ||
|
afddfea8fb | ||
|
0db997b435 | ||
|
31b3d5e5ba | ||
|
89cd1eec9c | ||
|
8aac85e9cf | ||
|
73c9b633c4 | ||
|
f1598a044e | ||
|
dc43529c7b | ||
|
6475e1bc26 | ||
|
e6bdce0240 | ||
|
a623e62e8c | ||
|
da12a5155c | ||
|
0a863bc1f9 |
kernel/src/holeybytes
sysdata
libraries/stn/src
programs
ps2_driver
ps2_driver_retired
rtc_driver/src
test/src/tests/stn/assets
|
@ -1,5 +1,7 @@
|
|||
//! Environment call handling routines
|
||||
|
||||
use core::arch::asm;
|
||||
|
||||
use {alloc::boxed::Box, core::cell::LazyCell, hbvm::mem::Address};
|
||||
|
||||
use crate::{
|
||||
|
@ -288,6 +290,20 @@ pub fn handler(thr: &mut ExecThread, pid: &usize) {
|
|||
.buffer_subscribe(*pid, buffer_id);
|
||||
}
|
||||
}
|
||||
8 => {
|
||||
// Disable/enable interrupts.
|
||||
// TODO: This is the quickest dirtiest hack to ever exist.
|
||||
let state = thr.vm.registers[3].cast::<u8>();
|
||||
if state == 0 {
|
||||
debug!("Interrupts disabled.");
|
||||
unsafe {asm!("cli");};
|
||||
}
|
||||
else
|
||||
{
|
||||
debug!("Interrupts enabled.");
|
||||
unsafe {asm!("sti");};
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
log::error!("Syscall unknown {:?}{:?}", ecall_number, thr.vm.registers);
|
||||
}
|
||||
|
|
|
@ -5,3 +5,15 @@ $subscribe_to_interrupt := fn(interrupt_number: u8): bool {
|
|||
$sleep_until_interrupt := fn(interrupt_number: u8): void {
|
||||
@eca(6, interrupt_number)
|
||||
}
|
||||
|
||||
//InterruptGuard := struct {}
|
||||
|
||||
// Disables recieving interrupts..
|
||||
$disable_interrupts := fn(): void {
|
||||
@eca(8, false)
|
||||
}
|
||||
|
||||
// Enables recieving interrupts..
|
||||
$enable_interrupts := fn(): void {
|
||||
@eca(8, true)
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
# Unified PS/2 Driver
|
||||
|
||||
Te entire thing is held together inspite
|
||||
|
||||
## !!Assumptions!!
|
||||
Anyone who works on this should work to keep this list as small as possible/remove as many of these as possible.
|
||||
- Bit 5 of the response form 0x64 indicates which port the data is coming from. (Not true on all systems)
|
||||
- A parity or timeout error never occurs.
|
||||
- PS/2 controller exists.
|
||||
- Both PS/2 ports being broken doesn't need handling.
|
||||
- One PS/2 port being broken doesn't need special attention.
|
||||
- PS/2 controller doesn't need to perform a self-check.
|
||||
- These DeviceIDs never exist:
|
||||
- 0xFFFD
|
||||
- 0xFFFE
|
||||
- 0xFFFF
|
||||
- 0x01xx
|
||||
- 0x03xx
|
||||
- 0x04xx
|
||||
- Literally all PS/2 keyboards can be handeled the exact same way. We have the capability for detecting different keyboard types, I just don't bother with it because that would litreally take months to get working.
|
||||
- The device doesn't send any data while we're waiting for an `ACK`.
|
||||
|
||||
Supporting mice in the keyboard port and vice versa was a ***bad*** idea, but I do not regret it because it means we're "superior" to real world operating systems.
|
|
@ -1,101 +0,0 @@
|
|||
.{memory, log} := @use("stn");
|
||||
.{bit0, bit1, bit5, bit6, bit7} := @use("bits.hb");
|
||||
.{Port, PORT_AT_STARTUP} := @use("port.hb")
|
||||
|
||||
port1 := @as(Port, PORT_AT_STARTUP)
|
||||
port2 := @as(Port, PORT_AT_STARTUP)
|
||||
|
||||
//wiki.osdev.org/"8042"_PS/2_Controller#PS/2_Controller_IO_Ports
|
||||
$CONTROLLER_PORT := 0x64
|
||||
$DATA_PORT := 0x60
|
||||
|
||||
$disable_port1 := fn(): void memory.outb(CONTROLLER_PORT, 0xAD)
|
||||
$enable_port1 := fn(): void memory.outb(CONTROLLER_PORT, 0xAE)
|
||||
$disable_port2 := fn(): void memory.outb(CONTROLLER_PORT, 0xA7)
|
||||
$enable_port2 := fn(): void memory.outb(CONTROLLER_PORT, 0xA8)
|
||||
|
||||
test_port1 := fn(): bool {
|
||||
memory.outb(CONTROLLER_PORT, 0xAB)
|
||||
loop if has_input(get_info()) break
|
||||
input := get_input()
|
||||
return input == 0x0
|
||||
}
|
||||
|
||||
test_port2 := fn(): bool {
|
||||
memory.outb(CONTROLLER_PORT, 0xA9)
|
||||
loop if has_input(get_info()) break
|
||||
input := get_input()
|
||||
return input == 0x0
|
||||
}
|
||||
|
||||
get_config_byte := fn(): u8 {
|
||||
memory.outb(CONTROLLER_PORT, 0x20)
|
||||
loop if has_input(get_info()) break
|
||||
return get_input()
|
||||
}
|
||||
|
||||
Info := struct {d: u8}
|
||||
|
||||
$get_info := fn(): Info return .(memory.inb(CONTROLLER_PORT))
|
||||
//inline when can
|
||||
has_input := fn(info: Info): bool return bit0(info.d)
|
||||
can_send := fn(info: Info): bool return bit1(info.d) == false
|
||||
timed_out := fn(info: Info): bool return bit6(info.d)
|
||||
check_parity := fn(info: Info): bool return bit7(info.d)
|
||||
get_port := fn(info: Info): ^Port {
|
||||
if bit5(info.d) {
|
||||
return &port2
|
||||
} else {
|
||||
return &port1
|
||||
}
|
||||
}
|
||||
|
||||
//T
|
||||
port2_ptr := &port2
|
||||
send_byte := fn(port: ^Port, byte: u8): void {
|
||||
if port == port2_ptr {
|
||||
memory.outb(CONTROLLER_PORT, 0xD4)
|
||||
}
|
||||
loop if can_send(get_info()) break
|
||||
memory.outb(DATA_PORT, byte)
|
||||
}
|
||||
|
||||
$get_input := fn(): u8 return memory.inb(DATA_PORT)
|
||||
$write_out := fn(data: u8): void memory.outb(DATA_PORT, data)
|
||||
|
||||
flush_input := fn(): void {
|
||||
loop if has_input(get_info()) == false break else get_info()
|
||||
}
|
||||
|
||||
init := fn(): void {
|
||||
disable_port1()
|
||||
disable_port2()
|
||||
//Disables ports to make sure that they won't interfere with the setup process.
|
||||
|
||||
flush_input()
|
||||
|
||||
enable_port2()
|
||||
port2.exists = bit5(@inline(get_config_byte)) == false
|
||||
disable_port2()
|
||||
|
||||
flush_input()
|
||||
|
||||
port1.exists = test_port1()
|
||||
|
||||
if port2.exists {
|
||||
port2.exists = test_port2()
|
||||
}
|
||||
|
||||
if (port1.exists | port2.exists) == false {
|
||||
log.error("No ports detected! No input will be processed! Cannot handle this!")
|
||||
}
|
||||
|
||||
if port1.exists {
|
||||
log.info("Port 1 exists.")
|
||||
enable_port1()
|
||||
}
|
||||
if port2.exists {
|
||||
log.info("Port 2 exists.")
|
||||
enable_port2()
|
||||
}
|
||||
}
|
|
@ -1,150 +1,5 @@
|
|||
.{memory, log, buffer, string} := @use("stn");
|
||||
.{MouseEvent} := @use("lib:intouch").events;
|
||||
.{bit0, bit1, bit2, bit3, bit4} := @use("bits.hb")
|
||||
devices := @use("devices.hb")
|
||||
controller := @use("controller.hb");
|
||||
.{Info, Port} := controller
|
||||
mouse := @use("mouse.hb")
|
||||
|
||||
mouse_buffer := 0
|
||||
keyboard_buffer := 0
|
||||
info := Info.(0)
|
||||
|
||||
send_command := fn(port: ^Port, byte: u8): void {
|
||||
tries := 3
|
||||
loop if tries == 0 break else {
|
||||
controller.send_byte(port, byte)
|
||||
loop {
|
||||
info = controller.get_info()
|
||||
if controller.has_input(info) == false {
|
||||
continue
|
||||
}
|
||||
input := controller.get_input()
|
||||
if controller.get_port(info) != port {
|
||||
if check_complete(port) == false {
|
||||
port.packet[port.packet_length] = input
|
||||
port.packet_length += 1
|
||||
}
|
||||
continue
|
||||
}
|
||||
if input == 0xFA {
|
||||
return
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
tries -= 1
|
||||
}
|
||||
}
|
||||
|
||||
enable_streaming := fn(port: ^Port): void {
|
||||
@inline(send_command, port, 0xF4)
|
||||
}
|
||||
|
||||
process := fn(port: ^controller.Port): void {
|
||||
if port.device.value < devices.MOUSE_5_BUTTON.value {
|
||||
event := MouseEvent.(0, 0, false, false, false)
|
||||
|
||||
event.left = bit0(port.packet[0])
|
||||
event.right = bit1(port.packet[0])
|
||||
event.middle = bit2(port.packet[0])
|
||||
|
||||
event.x_change = @intcast(port.packet[1])
|
||||
event.y_change = @intcast(port.packet[2])
|
||||
|
||||
buffer.write(MouseEvent, mouse_buffer, &event)
|
||||
} else if port.device == devices.MOUSE_INIT_1 {
|
||||
port.device.value = port.packet[0]
|
||||
if port.device != devices.MOUSE_SCROLLWHEEL {
|
||||
enable_streaming(port)
|
||||
return
|
||||
}
|
||||
port.device = devices.MOUSE_INIT_2
|
||||
} else if port.device == devices.MOUSE_INIT_2 {
|
||||
port.device.value = port.packet[0]
|
||||
} else if port.device == devices.NO_DEVICE {
|
||||
if port.packet_length == 1 {
|
||||
port.device.value = port.packet[0]
|
||||
enable_streaming(port)
|
||||
//TODO: Upgrade mouse.
|
||||
} else {
|
||||
port.device.value = port.packet[1] | port.packet[0] << 8
|
||||
enable_streaming(port)
|
||||
}
|
||||
log.info("Identified device!")
|
||||
log.print(port.device.value, .{radix: 16})
|
||||
} else {
|
||||
log.info("KEY PRESSED")
|
||||
}
|
||||
}
|
||||
|
||||
check_complete := fn(port: ^controller.Port): bool {
|
||||
last_value := port.packet[port.packet_length - 1]
|
||||
if port.device == devices.NO_DEVICE {
|
||||
if last_value == 0 | last_value == 3 | last_value == 4 {
|
||||
return true
|
||||
} else if port.packet_length == 2 {
|
||||
return true
|
||||
}
|
||||
} else if port.device == devices.MOUSE_3_BUTTON {
|
||||
if port.packet_length == 3 return true
|
||||
} else if port.device == devices.MOUSE_SCROLLWHEEL | port.device == devices.MOUSE_5_BUTTON {
|
||||
if port.packet_length == 4 return true
|
||||
} else {
|
||||
if port.packet[0] == 0xE1 {
|
||||
if port.packet_length == 6 {
|
||||
return true
|
||||
}
|
||||
} else if port.packet[0] != 0xE0 {
|
||||
return true
|
||||
} else if port.packet_length == 2 & port.packet[1] != 0x2A & port.packet[1] != 0xB7 {
|
||||
return true
|
||||
} else if port.packet_length == 4 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Port := @use("port.hb").Port;
|
||||
|
||||
main := fn(): void {
|
||||
mouse_buffer = buffer.create("PS/2 Mouse")
|
||||
|
||||
controller.init()
|
||||
|
||||
if controller.port1.exists {
|
||||
//log.info("Port 1 exists.")
|
||||
controller.send_byte(@bitcast(0), 0xF4)
|
||||
}
|
||||
if controller.port2.exists {
|
||||
//controller.send_byte(&controller.port2, 0xF4)
|
||||
}
|
||||
|
||||
loop {
|
||||
info = controller.get_info()
|
||||
|
||||
if controller.timed_out(info) {
|
||||
log.error("Timeout error! Cannot handle these!")
|
||||
}
|
||||
if controller.check_parity(info) {
|
||||
log.error("Parity error! Cannot handle these!")
|
||||
}
|
||||
/*
|
||||
if controller.has_input(info) {
|
||||
port := controller.get_port(info)
|
||||
if port.packet_length > 0 & check_complete(port) {
|
||||
process(port)
|
||||
}
|
||||
input := controller.get_input()
|
||||
/*if input == 0xAA & port.can_hot_plug {
|
||||
port.device = devices.NO_DEVICE
|
||||
controller.send_byte(port, 0xF4)
|
||||
}*/
|
||||
port.packet[port.packet_length] = input
|
||||
port.packet_length += 1
|
||||
if check_complete(port) {
|
||||
process(port)
|
||||
port.packet_length = 0
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
|
@ -1,21 +1,52 @@
|
|||
.{DeviceID, NO_DEVICE} := @use("devices.hb")
|
||||
log := @use("stn:log")
|
||||
|
||||
State := struct {s: u8}
|
||||
$Recive := State.(0)
|
||||
$Reboot := State.(1)
|
||||
|
||||
Port := packed struct {
|
||||
exists: bool,
|
||||
device: DeviceID,
|
||||
packet: [8]u8,
|
||||
packet_length: u8,
|
||||
can_hot_plug: bool,
|
||||
|
||||
Uninitialized := struct {
|
||||
|
||||
}
|
||||
|
||||
$PORT_AT_STARTUP := Port.(
|
||||
true,
|
||||
NO_DEVICE,
|
||||
.[0, 0, 0, 0, 0, 0, 0, 0],
|
||||
0,
|
||||
true,
|
||||
)
|
||||
ThreeButtonMouse := struct {
|
||||
|
||||
}
|
||||
|
||||
ScrollMouse := struct {
|
||||
|
||||
}
|
||||
|
||||
FiveButtonMouse := struct {
|
||||
|
||||
}
|
||||
|
||||
Keyboard := struct {
|
||||
|
||||
}
|
||||
|
||||
DeviceType := enum {
|
||||
None,
|
||||
Uninitialized,
|
||||
ThreeButtonMouse,
|
||||
ScrollMouse,
|
||||
FiveButtonMouse,
|
||||
Keyboard,
|
||||
}
|
||||
|
||||
Port := struct {
|
||||
device_type: DeviceType,
|
||||
_: union {
|
||||
uninitialized: Uninitialized,
|
||||
three_button_mouse: ThreeButtonMouse,
|
||||
scroll_mouse: ScrollMouse,
|
||||
five_button_mouse: FiveButtonMouse,
|
||||
keyboard: Keyboard,
|
||||
},
|
||||
recive_byte := fn(self: Self, byte: u8): void {
|
||||
match self.device_type {
|
||||
.Uninitialized => @inline(self._.uninitialized.recive_byte, byte)
|
||||
.ThreeButtonMouse => @inline(self._.three_button_mouse.recive_byte, byte)
|
||||
.ScrollMouse => @inline(self._.scroll_mouse.recive_byte, byte)
|
||||
.FiveButtonMouse => @inline(self._.five_button_mouse.recive_byte, byte)
|
||||
.Keyboard => @inline(self._.keyboard.recive_byt, byte)
|
||||
}
|
||||
},
|
||||
}
|
23
sysdata/programs/ps2_driver_retired/README.md
Normal file
23
sysdata/programs/ps2_driver_retired/README.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Unified PS/2 Driver
|
||||
|
||||
Te entire thing is held together inspite
|
||||
|
||||
## !!Assumptions!!
|
||||
Anyone who works on this should work to keep this list as small as possible/remove as many of these as possible.
|
||||
- Bit 5 of the response form 0x64 indicates which port the data is coming from. (Not true on all systems)
|
||||
- A parity or timeout error never occurs.
|
||||
- PS/2 controller exists.
|
||||
- Both PS/2 ports being broken doesn't need handling.
|
||||
- One PS/2 port being broken doesn't need special attention.
|
||||
- PS/2 controller doesn't need to perform a self-check.
|
||||
- These DeviceIDs never exist:
|
||||
- 0xFFFD
|
||||
- 0xFFFE
|
||||
- 0xFFFF
|
||||
- 0x01xx
|
||||
- 0x03xx
|
||||
- 0x04xx
|
||||
- Literally all PS/2 keyboards can be handeled the exact same way. We have the capability for detecting different keyboard types, I just don't bother with it because that would litreally take months to get working.
|
||||
- The device doesn't send any data while we're waiting for an `ACK`.
|
||||
|
||||
Supporting mice in the keyboard port and vice versa was a ***bad*** idea, but I do not regret it because it means we're "superior" to real world operating systems.
|
11
sysdata/programs/ps2_driver_retired/meta.toml
Normal file
11
sysdata/programs/ps2_driver_retired/meta.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "ps2_driver"
|
||||
authors = ["Peony"]
|
||||
|
||||
[dependants.libraries]
|
||||
|
||||
[dependants.binaries]
|
||||
hblang.version = "1.0.0"
|
||||
|
||||
[build]
|
||||
command = "hblang src/main.hb"
|
101
sysdata/programs/ps2_driver_retired/src/controller.hb
Normal file
101
sysdata/programs/ps2_driver_retired/src/controller.hb
Normal file
|
@ -0,0 +1,101 @@
|
|||
.{memory, log} := @use("stn");
|
||||
.{bit0, bit1, bit5, bit6, bit7} := @use("bits.hb");
|
||||
.{Port, PORT_AT_STARTUP} := @use("port.hb")
|
||||
|
||||
port1 := @as(Port, PORT_AT_STARTUP)
|
||||
port2 := @as(Port, PORT_AT_STARTUP)
|
||||
|
||||
//wiki.osdev.org/"8042"_PS/2_Controller#PS/2_Controller_IO_Ports
|
||||
$CONTROLLER_PORT := 0x64
|
||||
$DATA_PORT := 0x60
|
||||
|
||||
//These are implementations of a few simple controller commands.
|
||||
$disable_port1 := fn(): void memory.outb(CONTROLLER_PORT, 0xAD)
|
||||
$enable_port1 := fn(): void memory.outb(CONTROLLER_PORT, 0xAE)
|
||||
$disable_port2 := fn(): void memory.outb(CONTROLLER_PORT, 0xA7)
|
||||
$enable_port2 := fn(): void memory.outb(CONTROLLER_PORT, 0xA8)
|
||||
|
||||
test_port1 := fn(): bool {
|
||||
memory.outb(CONTROLLER_PORT, 0xAB)
|
||||
loop if has_input(get_info()) break
|
||||
input := get_input()
|
||||
return input == 0x0
|
||||
}
|
||||
|
||||
test_port2 := fn(): bool {
|
||||
memory.outb(CONTROLLER_PORT, 0xA9)
|
||||
loop if has_input(get_info()) break
|
||||
input := get_input()
|
||||
return input == 0x0
|
||||
}
|
||||
|
||||
get_config_byte := fn(): u8 {
|
||||
memory.outb(CONTROLLER_PORT, 0x20)
|
||||
loop if has_input(get_info()) break
|
||||
return get_input()
|
||||
}
|
||||
|
||||
Info := struct {d: u8}
|
||||
|
||||
$get_info := fn(): Info return .(memory.inb(CONTROLLER_PORT))
|
||||
//inline when can
|
||||
has_input := fn(info: Info): bool return bit0(info.d)
|
||||
can_send := fn(info: Info): bool return bit1(info.d) == false
|
||||
timed_out := fn(info: Info): bool return bit6(info.d)
|
||||
check_parity := fn(info: Info): bool return bit7(info.d)
|
||||
get_port := fn(info: Info): ^Port {
|
||||
if bit5(info.d) {
|
||||
return &port2
|
||||
} else {
|
||||
return &port1
|
||||
}
|
||||
}
|
||||
|
||||
port2_ptr := &port2
|
||||
send_byte := fn(port: ^Port, byte: u8): void {
|
||||
if port == port2_ptr {
|
||||
memory.outb(CONTROLLER_PORT, 0xD4)
|
||||
}
|
||||
loop if can_send(get_info()) break
|
||||
memory.outb(DATA_PORT, byte)
|
||||
}
|
||||
|
||||
$get_input := fn(): u8 return memory.inb(DATA_PORT)
|
||||
$write_out := fn(data: u8): void memory.outb(DATA_PORT, data)
|
||||
|
||||
flush_input := fn(): void {
|
||||
loop if has_input(get_info()) == false break else get_info()
|
||||
}
|
||||
|
||||
init := fn(): void {
|
||||
disable_port1()
|
||||
disable_port2()
|
||||
//Disables ports to make sure that they won't interfere with the setup process.
|
||||
|
||||
flush_input()
|
||||
|
||||
enable_port2()
|
||||
port2.exists = bit5(@inline(get_config_byte)) == false
|
||||
disable_port2()
|
||||
|
||||
flush_input()
|
||||
|
||||
port1.exists = test_port1()
|
||||
|
||||
if port2.exists {
|
||||
port2.exists = test_port2()
|
||||
}
|
||||
|
||||
if (port1.exists | port2.exists) == false {
|
||||
log.error("No ports detected! No input will be processed! Cannot handle this!")
|
||||
}
|
||||
|
||||
if port1.exists {
|
||||
log.info("Port 1 exists.")
|
||||
enable_port1()
|
||||
}
|
||||
if port2.exists {
|
||||
log.info("Port 2 exists.")
|
||||
enable_port2()
|
||||
}
|
||||
}
|
150
sysdata/programs/ps2_driver_retired/src/main.hb
Normal file
150
sysdata/programs/ps2_driver_retired/src/main.hb
Normal file
|
@ -0,0 +1,150 @@
|
|||
.{memory, log, buffer, string} := @use("stn");
|
||||
.{MouseEvent} := @use("lib:intouch").events;
|
||||
.{bit0, bit1, bit2, bit3, bit4} := @use("bits.hb")
|
||||
devices := @use("devices.hb")
|
||||
controller := @use("controller.hb");
|
||||
.{Info, Port} := controller
|
||||
mouse := @use("mouse.hb")
|
||||
|
||||
mouse_buffer := 0
|
||||
keyboard_buffer := 0
|
||||
info := Info.(0)
|
||||
|
||||
send_command := fn(port: ^Port, byte: u8): void {
|
||||
tries := 3
|
||||
loop if tries == 0 break else {
|
||||
controller.send_byte(port, byte)
|
||||
loop {
|
||||
info = controller.get_info()
|
||||
if controller.has_input(info) == false {
|
||||
continue
|
||||
}
|
||||
input := controller.get_input()
|
||||
if controller.get_port(info) != port {
|
||||
if check_complete(port) == false {
|
||||
port.packet[port.packet_length] = input
|
||||
port.packet_length += 1
|
||||
}
|
||||
continue
|
||||
}
|
||||
if input == 0xFA {
|
||||
return
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
tries -= 1
|
||||
}
|
||||
}
|
||||
|
||||
enable_streaming := fn(port: ^Port): void {
|
||||
@inline(send_command, port, 0xF4)
|
||||
}
|
||||
|
||||
process := fn(port: ^controller.Port): void {
|
||||
if port.device.value < devices.MOUSE_5_BUTTON.value {
|
||||
event := MouseEvent.(0, 0, false, false, false)
|
||||
|
||||
event.left = bit0(port.packet[0])
|
||||
event.right = bit1(port.packet[0])
|
||||
event.middle = bit2(port.packet[0])
|
||||
|
||||
event.x_change = @intcast(port.packet[1])
|
||||
event.y_change = @intcast(port.packet[2])
|
||||
|
||||
buffer.write(MouseEvent, mouse_buffer, &event)
|
||||
} else if port.device == devices.MOUSE_INIT_1 {
|
||||
port.device.value = port.packet[0]
|
||||
if port.device != devices.MOUSE_SCROLLWHEEL {
|
||||
enable_streaming(port)
|
||||
return
|
||||
}
|
||||
port.device = devices.MOUSE_INIT_2
|
||||
} else if port.device == devices.MOUSE_INIT_2 {
|
||||
port.device.value = port.packet[0]
|
||||
} else if port.device == devices.NO_DEVICE {
|
||||
if port.packet_length == 1 {
|
||||
port.device.value = port.packet[0]
|
||||
enable_streaming(port)
|
||||
//TODO: Upgrade mouse.
|
||||
} else {
|
||||
port.device.value = port.packet[1] | port.packet[0] << 8
|
||||
enable_streaming(port)
|
||||
}
|
||||
log.info("Identified device!")
|
||||
log.print(port.device.value, .{radix: 16})
|
||||
} else {
|
||||
log.info("KEY PRESSED")
|
||||
}
|
||||
}
|
||||
|
||||
check_complete := fn(port: ^controller.Port): bool {
|
||||
last_value := port.packet[port.packet_length - 1]
|
||||
if port.device == devices.NO_DEVICE {
|
||||
if last_value == 0 | last_value == 3 | last_value == 4 {
|
||||
return true
|
||||
} else if port.packet_length == 2 {
|
||||
return true
|
||||
}
|
||||
} else if port.device == devices.MOUSE_3_BUTTON {
|
||||
if port.packet_length == 3 return true
|
||||
} else if port.device == devices.MOUSE_SCROLLWHEEL | port.device == devices.MOUSE_5_BUTTON {
|
||||
if port.packet_length == 4 return true
|
||||
} else {
|
||||
if port.packet[0] == 0xE1 {
|
||||
if port.packet_length == 6 {
|
||||
return true
|
||||
}
|
||||
} else if port.packet[0] != 0xE0 {
|
||||
return true
|
||||
} else if port.packet_length == 2 & port.packet[1] != 0x2A & port.packet[1] != 0xB7 {
|
||||
return true
|
||||
} else if port.packet_length == 4 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
main := fn(): void {
|
||||
mouse_buffer = buffer.create("PS/2 Mouse")
|
||||
|
||||
controller.init()
|
||||
|
||||
if controller.port1.exists {
|
||||
//log.info("Port 1 exists.")
|
||||
controller.send_byte(@bitcast(0), 0xF4)
|
||||
}
|
||||
if controller.port2.exists {
|
||||
//controller.send_byte(&controller.port2, 0xF4)
|
||||
}
|
||||
|
||||
loop {
|
||||
info = controller.get_info()
|
||||
|
||||
if controller.timed_out(info) {
|
||||
log.error("Timeout error! Cannot handle these!")
|
||||
}
|
||||
if controller.check_parity(info) {
|
||||
log.error("Parity error! Cannot handle these!")
|
||||
}
|
||||
/*
|
||||
if controller.has_input(info) {
|
||||
port := controller.get_port(info)
|
||||
if port.packet_length > 0 & check_complete(port) {
|
||||
process(port)
|
||||
}
|
||||
input := controller.get_input()
|
||||
/*if input == 0xAA & port.can_hot_plug {
|
||||
port.device = devices.NO_DEVICE
|
||||
controller.send_byte(port, 0xF4)
|
||||
}*/
|
||||
port.packet[port.packet_length] = input
|
||||
port.packet_length += 1
|
||||
if check_complete(port) {
|
||||
process(port)
|
||||
port.packet_length = 0
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
21
sysdata/programs/ps2_driver_retired/src/port.hb
Normal file
21
sysdata/programs/ps2_driver_retired/src/port.hb
Normal file
|
@ -0,0 +1,21 @@
|
|||
.{DeviceID, NO_DEVICE} := @use("devices.hb")
|
||||
|
||||
State := struct {s: u8}
|
||||
$Recive := State.(0)
|
||||
$Reboot := State.(1)
|
||||
|
||||
Port := packed struct {
|
||||
exists: bool,
|
||||
device: DeviceID,
|
||||
packet: [8]u8,
|
||||
packet_length: u8,
|
||||
can_hot_plug: bool,
|
||||
}
|
||||
|
||||
$PORT_AT_STARTUP := Port.(
|
||||
true,
|
||||
NO_DEVICE,
|
||||
.[0, 0, 0, 0, 0, 0, 0, 0],
|
||||
0,
|
||||
true,
|
||||
)
|
|
@ -1,12 +1,89 @@
|
|||
stn := @use("stn");
|
||||
.{sleep, log, memory} := stn
|
||||
|
||||
main := fn(): int {
|
||||
loop {
|
||||
log.info("BEFORE")
|
||||
sleep.sleep_until_interrupt(8)
|
||||
log.info("AFTER")
|
||||
$decode_bcd := fn(value: u8): u8 {
|
||||
return (value & 0xF) + ((value & 0xF0) >> 4) * 10
|
||||
}
|
||||
|
||||
read_register := fn(register: u8): u8 {
|
||||
memory.outb(0x70, register | 0x80)
|
||||
return memory.inb(0x71)
|
||||
}
|
||||
|
||||
$MONTH_TABLE := uint.[
|
||||
267840000,
|
||||
0,
|
||||
267840000,
|
||||
259200000,
|
||||
267840000,
|
||||
259200000,
|
||||
267840000,
|
||||
267840000,
|
||||
259200000,
|
||||
267840000,
|
||||
259200000,
|
||||
267840000,
|
||||
]
|
||||
|
||||
fetch_time := fn(): uint {
|
||||
sleep.disable_interrupts()
|
||||
|
||||
format := read_register(0xB)
|
||||
|
||||
second := read_register(0x0)
|
||||
minute := read_register(0x2)
|
||||
hour := read_register(0x4)
|
||||
week := read_register(0x6)
|
||||
day := read_register(0x7)
|
||||
month := read_register(0x8)
|
||||
year := read_register(0x9)
|
||||
|
||||
century := @as(u8, 0x20)
|
||||
if (format & 4) == 4 {
|
||||
century = 20
|
||||
}
|
||||
if read_register(0x6C) != 0 {
|
||||
century = read_register(0x32)
|
||||
}
|
||||
|
||||
return 0
|
||||
sleep.enable_interrupts()
|
||||
|
||||
if (format & 4) != 4 {
|
||||
second = decode_bcd(second)
|
||||
minute = decode_bcd(minute)
|
||||
hour = decode_bcd(hour & 0b1111111)
|
||||
day = decode_bcd(day)
|
||||
month = decode_bcd(month)
|
||||
year = decode_bcd(year)
|
||||
century = decode_bcd(century)
|
||||
}
|
||||
|
||||
if (format & 2) != 2 & (hour & 0x80) == 0x80 {
|
||||
hour = hour & 0b1111111 + 12
|
||||
}
|
||||
|
||||
log.printf("{}-{}-{} at {}:{}:{}", .(@as(u16, year) + @as(u16, century) * 100, month, day, hour, minute, second), .{})
|
||||
|
||||
delta_epoch := @as(uint, year) + @as(uint, century) * 100 - 1970
|
||||
result := (second + (minute + @as(uint, hour) * 60) * 60) * 100 + delta_epoch * 3155692608
|
||||
test_month := 1
|
||||
loop if test_month == month break else {
|
||||
if test_month == 2 {
|
||||
if year % 4 == 0 & year % 100 != 0 | year % 400 == 0 {
|
||||
result += 250560000
|
||||
} else {
|
||||
result += 241920000
|
||||
}
|
||||
} else {
|
||||
result += MONTH_TABLE[test_month]
|
||||
}
|
||||
test_month += 1
|
||||
}
|
||||
result += @as(uint, day - 1) * 8640000
|
||||
|
||||
return result / 100
|
||||
}
|
||||
|
||||
main := fn(): void {
|
||||
log.print(fetch_time(), .{})
|
||||
}
|
48
sysdata/programs/rtc_driver/src/main_legacy.hb
Normal file
48
sysdata/programs/rtc_driver/src/main_legacy.hb
Normal file
|
@ -0,0 +1,48 @@
|
|||
stn := @use("stn");
|
||||
.{sleep, log, memory} := stn
|
||||
|
||||
microseconds := @as(u32, 0)
|
||||
seconds := @as(uint, 0)
|
||||
|
||||
padding := fn(): void {
|
||||
iter := 0
|
||||
loop if iter == 0xFFFF break else iter += 1
|
||||
}
|
||||
|
||||
read_register := fn(register: u8): u8 {
|
||||
memory.outb(0x70, register)
|
||||
padding()
|
||||
return memory.inb(0x71)
|
||||
}
|
||||
|
||||
write_register := fn(register: u8, value: u8): void {
|
||||
memory.outb(0x70, register)
|
||||
padding()
|
||||
memory.outb(0x71, value)
|
||||
}
|
||||
|
||||
main := fn(): void {
|
||||
sleep.disable_interrupts()
|
||||
|
||||
reg_a := read_register(0x8A)
|
||||
write_register(0x8A, 3 | 0xF0 & reg_a)
|
||||
|
||||
log.print(read_register(0x86), log.fmt.FormatOptions.(2, 10, log.LogLevel.Info))
|
||||
|
||||
reg_b := read_register(0x8B)
|
||||
write_register(0xB, 0x40 | reg_b)
|
||||
|
||||
sleep.enable_interrupts()
|
||||
|
||||
loop {
|
||||
sleep.sleep_until_interrupt(8)
|
||||
read_register(0xC)
|
||||
|
||||
microseconds += 122
|
||||
if microseconds >= 1000000 {
|
||||
microseconds -= 1000000
|
||||
seconds += 1
|
||||
}
|
||||
log.print(seconds, log.fmt.FormatOptions.(2, 10, log.LogLevel.Info))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
.{log, sleep} := @use("stn")
|
||||
|
||||
main := fn(): void {
|
||||
log.info("Hello, World!")
|
||||
// fake interrupt, sleep forever
|
||||
sleep.sleep_until_interrupt(100)
|
||||
}
|
|
@ -50,8 +50,11 @@ resolution = "1024x768x24"
|
|||
# [boot.limine.ableos.modules.angels_halo]
|
||||
# path = "boot:///angels_halo.hbf"
|
||||
|
||||
[boot.limine.ableos.modules.test]
|
||||
path = "boot:///test.hbf"
|
||||
# [boot.limine.ableos.modules.test]
|
||||
# path = "boot:///test.hbf"
|
||||
|
||||
# [boot.limine.ableos.modules.vfsaur]
|
||||
# path = "boot:///vfsaur.hbf"
|
||||
|
||||
[boot.limine.ableos.modules.rtc_driver]
|
||||
path = "boot:///rtc_driver.hbf"
|
Loading…
Reference in a new issue