mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Fix MMIO read issue
This commit is contained in:
parent
998869d57e
commit
b7d101b98c
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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()?,
|
||||
|
Loading…
x
Reference in New Issue
Block a user