Fix MMIO read issue

This commit is contained in:
Hsy-Intel 2024-10-16 15:01:22 +00:00 committed by Tate, Hongliang Tian
parent 998869d57e
commit b7d101b98c
3 changed files with 62 additions and 31 deletions

View File

@ -32,7 +32,7 @@ bitflags! {
/// The properties of input device.
///
/// Ref: Linux input-event-codes.h
pub struct InputProp : u8{
pub struct InputProp : u8 {
/// Needs a pointer
const POINTER = 1 << 0;
/// Direct input devices
@ -112,15 +112,15 @@ impl InputDevice {
callbacks: RwLock::new(Vec::new()),
});
let mut raw_name: [u8; 128] = [0; 128];
device.query_config_select(InputConfigSelect::IdName, 0, &mut raw_name);
let name = String::from_utf8(raw_name.to_vec()).unwrap();
let name = device.query_config_id_name();
info!("Virtio input device name:{}", name);
let mut prop: [u8; 128] = [0; 128];
device.query_config_select(InputConfigSelect::PropBits, 0, &mut prop);
let input_prop = InputProp::from_bits(prop[0]).unwrap();
debug!("input device prop:{:?}", input_prop);
let input_prop = device.query_config_prop_bits();
if let Some(prop) = input_prop {
debug!("input device prop: {:?}", prop);
} else {
debug!("input device has no properties or the properties is not defined");
}
let mut transport = device.transport.disable_irq().lock();
fn config_space_change(_: &TrapFrame) {
@ -167,25 +167,45 @@ impl InputDevice {
}
}
/// Query a specific piece of information by `select` and `subsel`, and write
/// result to `out`, return the result size.
pub fn query_config_select(&self, select: InputConfigSelect, subsel: u8, out: &mut [u8]) -> u8 {
pub fn query_config_id_name(&self) -> String {
let size = self.select_config(InputConfigSelect::IdName, 0);
let out = {
// TODO: Add a general API to read this byte-by-byte.
let mut out = Vec::with_capacity(size);
let mut data_ptr = field_ptr!(&self.config, VirtioInputConfig, data).cast::<u8>();
for _ in 0..size {
out.push(data_ptr.read_once().unwrap());
data_ptr.byte_add(1);
}
out
};
String::from_utf8(out).unwrap()
}
pub fn query_config_prop_bits(&self) -> Option<InputProp> {
let size = self.select_config(InputConfigSelect::PropBits, 0);
if size == 0 {
return None;
}
assert!(size == 1);
let data_ptr = field_ptr!(&self.config, VirtioInputConfig, data);
InputProp::from_bits(data_ptr.cast::<u8>().read_once().unwrap())
}
/// Query a specific piece of information by `select` and `subsel`, return the result size.
fn select_config(&self, select: InputConfigSelect, subsel: u8) -> usize {
field_ptr!(&self.config, VirtioInputConfig, select)
.write_once(&(select as u8))
.unwrap();
field_ptr!(&self.config, VirtioInputConfig, subsel)
.write_once(&subsel)
.unwrap();
let size = field_ptr!(&self.config, VirtioInputConfig, size)
field_ptr!(&self.config, VirtioInputConfig, size)
.read_once()
.unwrap();
let data: [u8; 128] = field_ptr!(&self.config, VirtioInputConfig, data)
// FIXME: It is impossible to call `read_once` on `[u8; 128]`. What's the proper way to
// read this field out?
.read()
.unwrap();
out[..size as usize].copy_from_slice(&data[..size as usize]);
size
.unwrap() as usize
}
fn handle_irq(&self) {

View File

@ -38,24 +38,26 @@ pub static DEVICE_NAME: &str = "Virtio-Input";
#[repr(u8)]
#[derive(Debug, Clone, Copy)]
pub enum InputConfigSelect {
/// Returns the name of the device, in u.string. subsel is zero.
/// Invalid configuration selection.
Unset = 0x00,
/// Returns the name of the device, subsel is zero.
IdName = 0x01,
/// Returns the serial number of the device, in u.string. subsel is zero.
/// Returns the serial number of the device, subsel is zero.
IdSerial = 0x02,
/// Returns ID information of the device, in u.ids. subsel is zero.
/// Returns ID information of the device, subsel is zero.
IdDevids = 0x03,
/// Returns input properties of the device, in u.bitmap. subsel is zero.
/// Returns input properties of the device, subsel is zero.
/// Individual bits in the bitmap correspond to INPUT_PROP_* constants used
/// by the underlying evdev implementation.
PropBits = 0x10,
/// subsel specifies the event type using EV_* constants in the underlying
/// evdev implementation. If size is non-zero the event type is supported
/// and a bitmap of supported event codes is returned in u.bitmap. Individual
/// and a bitmap of supported event codes is returned. Individual
/// bits in the bitmap correspond to implementation-defined input event codes,
/// for example keys or pointing device axes.
EvBits = 0x11,
/// subsel specifies the absolute axis using ABS_* constants in the underlying
/// evdev implementation. Information about the axis will be returned in u.abs.
/// evdev implementation. Information about the axis will be returned.
AbsInfo = 0x12,
}
@ -92,7 +94,7 @@ struct AbsInfo {
#[repr(C)]
#[derive(Debug, Copy, Clone, Pod)]
struct DevIDs {
struct DevIds {
bustype: u16,
vendor: u16,
product: u16,

View File

@ -3,7 +3,7 @@
use aster_network::EthernetAddr;
use aster_util::{field_ptr, safe_ptr::SafePtr};
use bitflags::bitflags;
use ostd::{io_mem::IoMem, Pod};
use ostd::{io_mem::IoMem, offset_of, Pod};
use crate::transport::VirtioTransport;
@ -78,10 +78,19 @@ impl VirtioNetConfig {
}
pub(super) fn read(this: &SafePtr<Self, IoMem>) -> ostd::prelude::Result<Self> {
// TODO: Add a general API to read this byte-by-byte.
let mac_data = {
let mut mac_data: [u8; 6] = [0; 6];
let mut mac_ptr = field_ptr!(this, Self, mac).cast::<u8>();
for byte in &mut mac_data {
*byte = mac_ptr.read_once().unwrap();
mac_ptr.byte_add(1);
}
mac_data
};
Ok(Self {
// FIXME: It is impossible to call `read_once` on `EthernetAddr`. What's the proper way
// to read this field out?
mac: field_ptr!(this, Self, mac).read()?,
mac: aster_network::EthernetAddr(mac_data),
status: field_ptr!(this, Self, status).read_once()?,
max_virtqueue_pairs: field_ptr!(this, Self, max_virtqueue_pairs).read_once()?,
mtu: field_ptr!(this, Self, mtu).read_once()?,