Merge pull request 'feature/nikocs/keyboard' (#2) from feature/nikocs/keyboard into develop
Reviewed-on: #2
This commit is contained in:
commit
0ee0cd2ddd
4 changed files with 415 additions and 4 deletions
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
storage_device="${1}"
|
storage_device="${1}"
|
||||||
|
|
||||||
qemu-system-riscv32 -machine virt -bios none -drive if=none,format=raw,file="${storage_device}",id=disk1 -device virtio-blk-device,drive=disk1 -display sdl -device virtio-gpu-device -serial stdio -m 10M -device loader,cpu-num=0,file=target/riscv32imac-unknown-none-elf/release/lbos -monitor telnet:127.0.0.1:1235,server,nowait -d guest_errors,unimp
|
qemu-system-riscv32 -machine virt -bios none -drive if=none,format=raw,file="${storage_device}",id=disk1 -device virtio-blk-device,drive=disk1 -display sdl -device virtio-gpu-device -device virtio-keyboard-device -serial stdio -m 10M -device loader,cpu-num=0,file=target/riscv32imac-unknown-none-elf/release/lbos -monitor telnet:127.0.0.1:1235,server,nowait -d guest_errors,unimp
|
||||||
|
|
@ -60,9 +60,13 @@ SECTIONS {
|
||||||
PROVIDE(_heap_size = _MEM_END - _heap_start);
|
PROVIDE(_heap_size = _MEM_END - _heap_start);
|
||||||
|
|
||||||
PROVIDE(_virtio_queue_1_start = ORIGIN(virtqueues));
|
PROVIDE(_virtio_queue_1_start = ORIGIN(virtqueues));
|
||||||
PROVIDE(_virtio_queue_1_end = _virtio_queue_1_start + 0x10000);
|
PROVIDE(_virtio_queue_1_end = _virtio_queue_1_start + 0x2000);
|
||||||
PROVIDE(_virtio_queue_2_start = _virtio_queue_1_end);
|
PROVIDE(_virtio_queue_2_start = _virtio_queue_1_end);
|
||||||
PROVIDE(_virtio_queue_2_end = _virtio_queue_2_start + 0x10000);
|
PROVIDE(_virtio_queue_2_end = _virtio_queue_2_start + 0x2000);
|
||||||
|
PROVIDE(_virtio_queue_3_start = _virtio_queue_2_end);
|
||||||
|
PROVIDE(_virtio_queue_3_end = _virtio_queue_3_start + 0x2000);
|
||||||
|
PROVIDE(_virtio_queue_4_start = _virtio_queue_3_end);
|
||||||
|
PROVIDE(_virtio_queue_4_end = _virtio_queue_4_start + 0x2000);
|
||||||
|
|
||||||
PROVIDE(_framebuffer_start = ORIGIN(framebuffer));
|
PROVIDE(_framebuffer_start = ORIGIN(framebuffer));
|
||||||
}
|
}
|
||||||
379
src/dev/virtio/input.rs
Normal file
379
src/dev/virtio/input.rs
Normal file
|
|
@ -0,0 +1,379 @@
|
||||||
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use crate::dev::virtio::{
|
||||||
|
Descriptor, VIRTIO_DESC_F_WRITE, VIRTIO_MMIO_GUEST_FEATURES, VIRTIO_MMIO_GUEST_PAGE_SIZE,
|
||||||
|
VIRTIO_MMIO_QUEUE_NUM, VIRTIO_MMIO_QUEUE_NUM_MAX, VIRTIO_MMIO_QUEUE_PFN, VIRTIO_MMIO_QUEUE_SEL,
|
||||||
|
VIRTIO_MMIO_STATUS, VIRTIO_MMIO_STATUS_ACKNOWLEDGE, VIRTIO_MMIO_STATUS_DRIVER,
|
||||||
|
VIRTIO_MMIO_STATUS_DRIVER_OK, VIRTIO_MMIO_STATUS_FAILED, VIRTIO_MMIO_STATUS_FEATURES_OK,
|
||||||
|
VIRTIO_QUEUE_SIZE, VirtQueue,
|
||||||
|
};
|
||||||
|
use crate::trafficcontrol::TrafficControl;
|
||||||
|
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn _virtio_queue_3_start();
|
||||||
|
fn _virtio_queue_4_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const VIRTIO_INPUT_EVENT_TYPE_KEYBOARD: u16 = 1;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Event {
|
||||||
|
pub event_type: u16,
|
||||||
|
pub code: u16,
|
||||||
|
pub value: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const VIRTIO_INPUT_EVENTBUFFER_SIZE: usize = 8;
|
||||||
|
|
||||||
|
pub struct VirtIoInputDevice {
|
||||||
|
pub addr: usize,
|
||||||
|
pub queue: usize,
|
||||||
|
pub idx: u16,
|
||||||
|
pub ack_used_idx: u16,
|
||||||
|
pub status_queue: usize,
|
||||||
|
pub status_queue_idx: u16,
|
||||||
|
pub status_queue_ack_used_idx: u16,
|
||||||
|
pub event_buffer: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum VirtIoInputDeviceError {
|
||||||
|
FeatureSetMismatch,
|
||||||
|
QueueSetupFailed,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VirtIoInputDevice {
|
||||||
|
pub fn new_and_init(
|
||||||
|
tc: &mut TrafficControl,
|
||||||
|
addr: usize,
|
||||||
|
) -> Result<Self, VirtIoInputDeviceError> {
|
||||||
|
// reset device (write 0 to status)
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_STATUS) as *mut u32).write_volatile(0);
|
||||||
|
}
|
||||||
|
// set ack bit
|
||||||
|
let mut status = VIRTIO_MMIO_STATUS_ACKNOWLEDGE;
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_STATUS) as *mut u32).write_volatile(status);
|
||||||
|
}
|
||||||
|
// set driver bit
|
||||||
|
status |= VIRTIO_MMIO_STATUS_DRIVER;
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_STATUS) as *mut u32).write_volatile(status);
|
||||||
|
}
|
||||||
|
// send feature set
|
||||||
|
let guest_features = 0; // todo: configure properly
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_GUEST_FEATURES) as *mut u32).write_volatile(guest_features);
|
||||||
|
}
|
||||||
|
status |= VIRTIO_MMIO_STATUS_FEATURES_OK;
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_STATUS) as *mut u32).write_volatile(status);
|
||||||
|
}
|
||||||
|
// make sure features ok is still set, otherwise failed
|
||||||
|
if unsafe { ((addr + VIRTIO_MMIO_STATUS) as *const u32).read_volatile() }
|
||||||
|
& VIRTIO_MMIO_STATUS_FEATURES_OK
|
||||||
|
== 0
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_STATUS) as *mut u32).write_volatile(VIRTIO_MMIO_STATUS_FAILED);
|
||||||
|
}
|
||||||
|
return Err(VirtIoInputDeviceError::FeatureSetMismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup event queue
|
||||||
|
let queue_max_by_device =
|
||||||
|
unsafe { ((addr + VIRTIO_MMIO_QUEUE_NUM_MAX) as *const u32).read_volatile() };
|
||||||
|
if queue_max_by_device < VIRTIO_QUEUE_SIZE as _ {
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_STATUS) as *mut u32).write_volatile(VIRTIO_MMIO_STATUS_FAILED);
|
||||||
|
}
|
||||||
|
return Err(VirtIoInputDeviceError::QueueSetupFailed);
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_QUEUE_NUM) as *mut u32).write_volatile(VIRTIO_QUEUE_SIZE as _);
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_QUEUE_SEL) as *mut u32).write_volatile(0);
|
||||||
|
}
|
||||||
|
let event_queue_ptr = _virtio_queue_3_start as usize;
|
||||||
|
// zero out queue
|
||||||
|
for i in 0..size_of::<VirtQueue>() {
|
||||||
|
unsafe {
|
||||||
|
((event_queue_ptr + i) as *mut u8).write_volatile(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_GUEST_PAGE_SIZE) as *mut u32).write_volatile(4096);
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_QUEUE_PFN) as *mut u32)
|
||||||
|
.write_volatile(event_queue_ptr as u32 / 4096);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup status queue
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_QUEUE_SEL) as *mut u32).write_volatile(1);
|
||||||
|
}
|
||||||
|
let status_queue_ptr = _virtio_queue_4_start as usize;
|
||||||
|
// zero out queue
|
||||||
|
for i in 0..size_of::<VirtQueue>() {
|
||||||
|
unsafe {
|
||||||
|
((status_queue_ptr + i) as *mut u8).write_volatile(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_GUEST_PAGE_SIZE) as *mut u32).write_volatile(4096);
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_QUEUE_PFN) as *mut u32)
|
||||||
|
.write_volatile(status_queue_ptr as u32 / 4096);
|
||||||
|
}
|
||||||
|
|
||||||
|
// all done!
|
||||||
|
status |= VIRTIO_MMIO_STATUS_DRIVER_OK;
|
||||||
|
unsafe {
|
||||||
|
((addr + VIRTIO_MMIO_STATUS) as *mut u32).write_volatile(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
let event_buffer_ptr = unsafe {
|
||||||
|
tc.memory_manager
|
||||||
|
.as_mut()
|
||||||
|
.unwrap_unchecked()
|
||||||
|
.alloc_n_blocks((size_of::<Event>() * VIRTIO_INPUT_EVENTBUFFER_SIZE).div_ceil(512))
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut input = VirtIoInputDevice {
|
||||||
|
addr,
|
||||||
|
queue: event_queue_ptr,
|
||||||
|
idx: 0,
|
||||||
|
ack_used_idx: 0,
|
||||||
|
status_queue: status_queue_ptr,
|
||||||
|
status_queue_idx: 0,
|
||||||
|
status_queue_ack_used_idx: 0,
|
||||||
|
event_buffer: event_buffer_ptr as usize,
|
||||||
|
};
|
||||||
|
for i in 0..VIRTIO_INPUT_EVENTBUFFER_SIZE {
|
||||||
|
input.fill_event(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill_event(&mut self, eventi: usize) {
|
||||||
|
let desc = Descriptor {
|
||||||
|
addr: self.event_buffer as u64 + (eventi * size_of::<Event>()) as u64,
|
||||||
|
len: size_of::<Event>() as u32,
|
||||||
|
flags: VIRTIO_DESC_F_WRITE,
|
||||||
|
next: 0,
|
||||||
|
};
|
||||||
|
let head = self.idx;
|
||||||
|
let queue = unsafe { &mut (*(self.queue as *mut VirtQueue)) };
|
||||||
|
queue.desc[self.idx as usize] = desc;
|
||||||
|
self.idx = (self.idx + 1) % VIRTIO_QUEUE_SIZE as u16;
|
||||||
|
queue.avail.ring[queue.avail.idx as usize % VIRTIO_QUEUE_SIZE] = head;
|
||||||
|
queue.avail.idx = queue.avail.idx.wrapping_add(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pending(&mut self, tc: &mut TrafficControl) {
|
||||||
|
// event queue
|
||||||
|
let queue = unsafe { &(*(self.queue as *mut VirtQueue)) };
|
||||||
|
while self.ack_used_idx != queue.used.idx {
|
||||||
|
let elem = &queue.used.ring[self.ack_used_idx as usize % VIRTIO_QUEUE_SIZE];
|
||||||
|
self.ack_used_idx = self.ack_used_idx.wrapping_add(1);
|
||||||
|
let desc = &queue.desc[elem.id as usize];
|
||||||
|
let event = unsafe { &*(desc.addr as *const Event) };
|
||||||
|
self.fill_event(elem.id as usize);
|
||||||
|
|
||||||
|
match event.event_type {
|
||||||
|
x if x == VIRTIO_INPUT_EVENT_TYPE_KEYBOARD => {
|
||||||
|
let keycode = event.code;
|
||||||
|
let down = event.value == 1;
|
||||||
|
|
||||||
|
// first, handle shift todo: handle more control characters
|
||||||
|
if keycode == LinuxKeycode::LeftShift as u16 || keycode == LinuxKeycode::RightShift as u16 {
|
||||||
|
UPPERCASE.store(down, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// next, handle ascii characters
|
||||||
|
if !down { // write on UP
|
||||||
|
let ascii = KEYMAP_ASCII.iter().find_map(|(a, b)| {
|
||||||
|
if keycode == *a as u16 {
|
||||||
|
Some(*b)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if let Some(mut ascii) = ascii {
|
||||||
|
if UPPERCASE.load(Ordering::Relaxed) {
|
||||||
|
if ascii.is_ascii_alphabetic() {
|
||||||
|
ascii = ascii.to_ascii_uppercase();
|
||||||
|
} else {
|
||||||
|
// todo: handle other characters
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tc.write_inbuf(ascii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// status queue
|
||||||
|
let queue = unsafe { &(*(self.status_queue as *mut VirtQueue)) };
|
||||||
|
while self.status_queue_ack_used_idx != queue.used.idx {
|
||||||
|
let elem =
|
||||||
|
&queue.used.ring[self.status_queue_ack_used_idx as usize % VIRTIO_QUEUE_SIZE];
|
||||||
|
let desc = &queue.desc[elem.id as usize];
|
||||||
|
let event = unsafe { &*(desc.addr as *const Event) };
|
||||||
|
self.status_queue_ack_used_idx = self.status_queue_ack_used_idx.wrapping_add(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static UPPERCASE: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
|
// linux keycodes
|
||||||
|
#[repr(u16)]
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum LinuxKeycode {
|
||||||
|
ESC = 1,
|
||||||
|
Key1 = 2,
|
||||||
|
Key2 = 3,
|
||||||
|
Key3 = 4,
|
||||||
|
Key4 = 5,
|
||||||
|
Key5 = 6,
|
||||||
|
Key6 = 7,
|
||||||
|
Key7 = 8,
|
||||||
|
Key8 = 9,
|
||||||
|
Key9 = 10,
|
||||||
|
Key0 = 11,
|
||||||
|
Minus = 12,
|
||||||
|
Equal = 13,
|
||||||
|
Backspace = 14,
|
||||||
|
Tab = 15,
|
||||||
|
Q = 16,
|
||||||
|
W = 17,
|
||||||
|
E = 18,
|
||||||
|
R = 19,
|
||||||
|
T = 20,
|
||||||
|
Y = 21,
|
||||||
|
U = 22,
|
||||||
|
I = 23,
|
||||||
|
O = 24,
|
||||||
|
P = 25,
|
||||||
|
LeftBracket = 26,
|
||||||
|
RightBracket = 27,
|
||||||
|
Enter = 28,
|
||||||
|
LeftControl = 29,
|
||||||
|
A = 30,
|
||||||
|
S = 31,
|
||||||
|
D = 32,
|
||||||
|
F = 33,
|
||||||
|
G = 34,
|
||||||
|
H = 35,
|
||||||
|
J = 36,
|
||||||
|
K = 37,
|
||||||
|
L = 38,
|
||||||
|
Semicolon = 39,
|
||||||
|
Apostrophe = 40,
|
||||||
|
Grave = 41,
|
||||||
|
LeftShift = 42,
|
||||||
|
Backslash = 43,
|
||||||
|
Z = 44,
|
||||||
|
X = 45,
|
||||||
|
C = 46,
|
||||||
|
V = 47,
|
||||||
|
B = 48,
|
||||||
|
N = 49,
|
||||||
|
M = 50,
|
||||||
|
Comma = 51,
|
||||||
|
Dot = 52,
|
||||||
|
Slash = 53,
|
||||||
|
RightShift = 54,
|
||||||
|
KPAsterisk = 55,
|
||||||
|
LeftAlt = 56,
|
||||||
|
Space = 57,
|
||||||
|
CapsLock = 58,
|
||||||
|
F1 = 59,
|
||||||
|
F2 = 60,
|
||||||
|
F3 = 61,
|
||||||
|
F4 = 62,
|
||||||
|
F5 = 63,
|
||||||
|
F6 = 64,
|
||||||
|
F7 = 65,
|
||||||
|
F8 = 66,
|
||||||
|
F9 = 67,
|
||||||
|
F10 = 68,
|
||||||
|
NumLock = 69,
|
||||||
|
ScrollLock = 70,
|
||||||
|
KP7 = 71,
|
||||||
|
KP8 = 72,
|
||||||
|
KP9 = 73,
|
||||||
|
KPMinus = 74,
|
||||||
|
KP4 = 75,
|
||||||
|
KP5 = 76,
|
||||||
|
KP6 = 77,
|
||||||
|
KPPlus = 78,
|
||||||
|
KP1 = 79,
|
||||||
|
KP2 = 80,
|
||||||
|
KP3 = 81,
|
||||||
|
KP0 = 82,
|
||||||
|
KPDot = 83,
|
||||||
|
}
|
||||||
|
|
||||||
|
// keys that do not map directly are handled outside of this
|
||||||
|
const KEYMAP_ASCII: &[(LinuxKeycode, u8)] = &[
|
||||||
|
(LinuxKeycode::ESC, 0x1B),
|
||||||
|
(LinuxKeycode::Key1, b'1'),
|
||||||
|
(LinuxKeycode::Key2, b'2'),
|
||||||
|
(LinuxKeycode::Key3, b'3'),
|
||||||
|
(LinuxKeycode::Key4, b'4'),
|
||||||
|
(LinuxKeycode::Key5, b'5'),
|
||||||
|
(LinuxKeycode::Key6, b'6'),
|
||||||
|
(LinuxKeycode::Key7, b'7'),
|
||||||
|
(LinuxKeycode::Key8, b'8'),
|
||||||
|
(LinuxKeycode::Key9, b'9'),
|
||||||
|
(LinuxKeycode::Key0, b'0'),
|
||||||
|
(LinuxKeycode::Minus, b'-'),
|
||||||
|
(LinuxKeycode::Equal, b'='),
|
||||||
|
(LinuxKeycode::Backspace, 0x7F),
|
||||||
|
(LinuxKeycode::Tab, 0x9),
|
||||||
|
(LinuxKeycode::Q, b'q'),
|
||||||
|
(LinuxKeycode::W, b'w'),
|
||||||
|
(LinuxKeycode::E, b'e'),
|
||||||
|
(LinuxKeycode::R, b'r'),
|
||||||
|
(LinuxKeycode::T, b't'),
|
||||||
|
(LinuxKeycode::Y, b'y'),
|
||||||
|
(LinuxKeycode::U, b'u'),
|
||||||
|
(LinuxKeycode::I, b'i'),
|
||||||
|
(LinuxKeycode::O, b'o'),
|
||||||
|
(LinuxKeycode::P, b'p'),
|
||||||
|
(LinuxKeycode::LeftBracket, b'['),
|
||||||
|
(LinuxKeycode::RightBracket, b']'),
|
||||||
|
(LinuxKeycode::Enter, b'\r'),
|
||||||
|
(LinuxKeycode::A, b'a'),
|
||||||
|
(LinuxKeycode::S, b's'),
|
||||||
|
(LinuxKeycode::D, b'd'),
|
||||||
|
(LinuxKeycode::F, b'f'),
|
||||||
|
(LinuxKeycode::G, b'g'),
|
||||||
|
(LinuxKeycode::H, b'h'),
|
||||||
|
(LinuxKeycode::J, b'j'),
|
||||||
|
(LinuxKeycode::K, b'k'),
|
||||||
|
(LinuxKeycode::L, b'l'),
|
||||||
|
(LinuxKeycode::Semicolon, b';'),
|
||||||
|
(LinuxKeycode::Apostrophe, b'\''),
|
||||||
|
(LinuxKeycode::Grave, b'`'),
|
||||||
|
(LinuxKeycode::Backslash, b'\\'),
|
||||||
|
(LinuxKeycode::Z, b'z'),
|
||||||
|
(LinuxKeycode::X, b'x'),
|
||||||
|
(LinuxKeycode::C, b'c'),
|
||||||
|
(LinuxKeycode::V, b'v'),
|
||||||
|
(LinuxKeycode::B, b'b'),
|
||||||
|
(LinuxKeycode::N, b'n'),
|
||||||
|
(LinuxKeycode::M, b'm'),
|
||||||
|
(LinuxKeycode::Comma, b','),
|
||||||
|
(LinuxKeycode::Dot, b'.'),
|
||||||
|
(LinuxKeycode::Slash, b'/'),
|
||||||
|
(LinuxKeycode::KPAsterisk, b'*'),
|
||||||
|
(LinuxKeycode::Space, b' '),
|
||||||
|
];
|
||||||
|
|
@ -5,6 +5,7 @@ use core::sync::atomic::Ordering;
|
||||||
use crate::dev::{FRAMEBUFFER_ADDR, FRAMEBUFFER_BPP};
|
use crate::dev::{FRAMEBUFFER_ADDR, FRAMEBUFFER_BPP};
|
||||||
use crate::dev::virtio::block::{VirtIoBlockDevice, VirtIoBlockDeviceError};
|
use crate::dev::virtio::block::{VirtIoBlockDevice, VirtIoBlockDeviceError};
|
||||||
use crate::dev::virtio::gpu::{VirtIoGpuDevice, VirtIoGpuDeviceError};
|
use crate::dev::virtio::gpu::{VirtIoGpuDevice, VirtIoGpuDeviceError};
|
||||||
|
use crate::dev::virtio::input::{VirtIoInputDevice, VirtIoInputDeviceError};
|
||||||
use crate::rough_panic;
|
use crate::rough_panic;
|
||||||
use crate::spinlock::Spinlock;
|
use crate::spinlock::Spinlock;
|
||||||
use crate::strprint::twodigit;
|
use crate::strprint::twodigit;
|
||||||
|
|
@ -12,6 +13,7 @@ use crate::trafficcontrol::{TrafficControl};
|
||||||
|
|
||||||
mod block;
|
mod block;
|
||||||
mod gpu;
|
mod gpu;
|
||||||
|
mod input;
|
||||||
|
|
||||||
pub const VIRTIO_MMIO_START: usize = 0x1000_1000;
|
pub const VIRTIO_MMIO_START: usize = 0x1000_1000;
|
||||||
pub const VIRTIO_MMIO_END: usize = 0x1000_8000;
|
pub const VIRTIO_MMIO_END: usize = 0x1000_8000;
|
||||||
|
|
@ -46,6 +48,7 @@ pub static VIRTIO_GPU_DEVICE: Spinlock<Option<u8>> = Spinlock::new(None);
|
||||||
pub enum VirtIoDevice {
|
pub enum VirtIoDevice {
|
||||||
BlockDevice(VirtIoBlockDevice),
|
BlockDevice(VirtIoBlockDevice),
|
||||||
GPUDevice(VirtIoGpuDevice),
|
GPUDevice(VirtIoGpuDevice),
|
||||||
|
InputDevice(VirtIoInputDevice),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
@ -159,6 +162,29 @@ pub fn probe_virtio_devices(tc: &mut TrafficControl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18 => {
|
||||||
|
// input device
|
||||||
|
let input_device = VirtIoInputDevice::new_and_init(tc, addr);
|
||||||
|
if let Ok(input_device) = input_device {
|
||||||
|
devices[i] = Some(VirtIoDevice::InputDevice(input_device));
|
||||||
|
if let Some(serial_port) = &serial_port {
|
||||||
|
serial_port.putstr("virtio input device found\n");
|
||||||
|
}
|
||||||
|
} else if let Err(e) = input_device {
|
||||||
|
match e {
|
||||||
|
VirtIoInputDeviceError::FeatureSetMismatch => {
|
||||||
|
if let Some(serial_port) = &serial_port {
|
||||||
|
serial_port.putstr("virtio input device feature mismatch\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VirtIoInputDeviceError::QueueSetupFailed => {
|
||||||
|
if let Some(serial_port) = &serial_port {
|
||||||
|
serial_port.putstr("virtio input device queue setup failed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
x => {
|
x => {
|
||||||
if let Some(serial_port) = &serial_port {
|
if let Some(serial_port) = &serial_port {
|
||||||
serial_port.putstr("unsupported device type ");
|
serial_port.putstr("unsupported device type ");
|
||||||
|
|
@ -187,7 +213,6 @@ pub fn handle_interrupt(interrupt: u32, tc: &mut TrafficControl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VirtIoDevice::GPUDevice(gpudev) => {
|
VirtIoDevice::GPUDevice(gpudev) => {
|
||||||
return;
|
|
||||||
let gpu = {
|
let gpu = {
|
||||||
let lock = VIRTIO_GPU_DEVICE.lock();
|
let lock = VIRTIO_GPU_DEVICE.lock();
|
||||||
*lock
|
*lock
|
||||||
|
|
@ -198,6 +223,9 @@ pub fn handle_interrupt(interrupt: u32, tc: &mut TrafficControl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
VirtIoDevice::InputDevice(inputdev) => {
|
||||||
|
inputdev.pending(tc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue