-
Notifications
You must be signed in to change notification settings - Fork 122
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
222 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
module mouse | ||
|
||
import resource | ||
import stat | ||
import fs | ||
import file | ||
import event | ||
import event.eventstruct | ||
import klock | ||
import katomic | ||
import errno | ||
import x86.kio | ||
import x86.apic | ||
import x86.idt | ||
|
||
@[inline] | ||
fn wait(t int) { | ||
mut timeout := 100000; | ||
|
||
if t == 0 { | ||
for ; timeout != 0; timeout-- { | ||
if kio.port_in<u8>(0x64) & (1 << 0) != 0 { | ||
return | ||
} | ||
} | ||
} else { | ||
for ; timeout != 0; timeout-- { | ||
if kio.port_in<u8>(0x64) & (1 << 1) == 0 { | ||
return | ||
} | ||
} | ||
} | ||
} | ||
|
||
@[inline] | ||
fn write(val u8) { | ||
wait(1) | ||
kio.port_out<u8>(0x64, 0xd4) | ||
wait(1) | ||
kio.port_out<u8>(0x60, val) | ||
} | ||
|
||
@[inline] | ||
fn read() u8 { | ||
wait(0) | ||
return kio.port_in<u8>(0x60) | ||
} | ||
|
||
struct MousePacket { | ||
pub mut: | ||
flags u8 | ||
x_mov u32 | ||
y_mov u32 | ||
} | ||
|
||
struct Mouse { | ||
pub mut: | ||
stat stat.Stat | ||
refcount int | ||
l klock.Lock | ||
event eventstruct.Event | ||
status int | ||
can_mmap bool | ||
|
||
packet_avl bool | ||
packet MousePacket | ||
} | ||
|
||
fn (mut this Mouse) mmap(page u64, flags int) voidptr { | ||
panic('') | ||
} | ||
|
||
fn (mut this Mouse) read(_handle voidptr, buf voidptr, loc u64, count u64) ?i64 { | ||
if count != sizeof(MousePacket) { | ||
errno.set(errno.einval) | ||
return none | ||
} | ||
|
||
handle := unsafe { &file.Handle(_handle) } | ||
|
||
mouse_res.l.acquire() | ||
|
||
for mouse_res.packet_avl == false { | ||
mouse_res.l.release() | ||
|
||
if handle.flags & resource.o_nonblock != 0 { | ||
errno.set(errno.ewouldblock) | ||
return none | ||
} | ||
|
||
mut events := [&mouse_res.event] | ||
event.await(mut events, true) or {} | ||
|
||
mouse_res.l.acquire() | ||
} | ||
|
||
unsafe { | ||
C.memcpy(buf, &mouse_res.packet, sizeof(MousePacket)) | ||
} | ||
mouse_res.packet_avl = false | ||
|
||
mouse_res.status &= ~int(file.pollin) | ||
|
||
mouse_res.l.release() | ||
|
||
return sizeof(MousePacket) | ||
} | ||
|
||
fn (mut this Mouse) write(handle voidptr, buf voidptr, loc u64, count u64) ?i64 { | ||
return i64(count) | ||
} | ||
|
||
fn (mut this Mouse) ioctl(handle voidptr, request u64, argp voidptr) ?int { | ||
return resource.default_ioctl(handle, request, argp) | ||
} | ||
|
||
fn (mut this Mouse) unref(handle voidptr) ? { | ||
katomic.dec(this.refcount) | ||
} | ||
|
||
fn (mut this Mouse) link(handle voidptr) ? { | ||
katomic.inc(this.stat.nlink) | ||
} | ||
|
||
fn (mut this Mouse) unlink(handle voidptr) ? { | ||
katomic.dec(this.stat.nlink) | ||
} | ||
|
||
fn (mut this Mouse) grow(handle voidptr, new_size u64) ? { | ||
} | ||
|
||
__global ( | ||
mouse_res Mouse | ||
ps2_mouse_vector u8 | ||
) | ||
|
||
fn handler() { | ||
mut handler_cycle := 0 | ||
mut current_packet := MousePacket{} | ||
mut discard_packet := false | ||
|
||
for { | ||
mut events := [&int_events[ps2_mouse_vector]] | ||
event.await(mut events, true) or {} | ||
|
||
// we will get some spurious packets at the beginning and they will screw | ||
// up the alignment of the handler cycle so just ignore everything in | ||
// the first 250 milliseconds after boot | ||
if monotonic_clock.tv_sec == 0 && monotonic_clock.tv_nsec < 250000000 { | ||
kio.port_in<u8>(0x60) | ||
} | ||
|
||
match handler_cycle { | ||
0 { | ||
current_packet.flags = read() | ||
handler_cycle++ | ||
if current_packet.flags & (1 << 6) != 0 || current_packet.flags & (1 << 7) != 0 { | ||
discard_packet = true | ||
} | ||
if current_packet.flags & (1 << 3) == 0 { | ||
discard_packet = true | ||
} | ||
continue | ||
} | ||
1 { | ||
current_packet.x_mov = read() | ||
handler_cycle++ | ||
continue | ||
} | ||
2 { | ||
current_packet.y_mov = read() | ||
handler_cycle = 0 | ||
|
||
if discard_packet { | ||
discard_packet = false | ||
continue | ||
} | ||
} | ||
else {} | ||
} | ||
|
||
if current_packet.flags & (1 << 4) != 0 { | ||
current_packet.x_mov = u32(i8(u8(current_packet.x_mov))) | ||
} | ||
if current_packet.flags & (1 << 5) != 0 { | ||
current_packet.y_mov = u32(i8(u8(current_packet.y_mov))) | ||
} | ||
|
||
mouse_res.l.acquire() | ||
mouse_res.packet = current_packet | ||
mouse_res.packet_avl = true | ||
mouse_res.l.release() | ||
|
||
mouse_res.status |= file.pollin | ||
event.trigger(mut mouse_res.event, false) | ||
} | ||
} | ||
|
||
pub fn initialise() { | ||
write(0xf6) | ||
read() | ||
|
||
write(0xf4) | ||
read() | ||
|
||
mouse_res.stat.size = 0 | ||
mouse_res.stat.blocks = 0 | ||
mouse_res.stat.blksize = 512; | ||
mouse_res.stat.rdev = resource.create_dev_id() | ||
mouse_res.stat.mode = 0o644 | stat.ifchr | ||
|
||
mouse_res.status |= file.pollout | ||
|
||
fs.devtmpfs_add_device(&mouse_res, 'mouse') | ||
|
||
ps2_mouse_vector = idt.allocate_vector() | ||
apic.io_apic_set_irq_redirect(cpu_locals[0].lapic_id, ps2_mouse_vector, 12, true) | ||
|
||
spawn handler() | ||
} |