Skip to content

Commit

Permalink
Merge pull request #1164 from hermit-os/mmio-fix
Browse files Browse the repository at this point in the history
fix(x86_64): virtio-net-device (MMIO)
  • Loading branch information
mkroening authored May 2, 2024
2 parents 61be02b + 681bbe0 commit 9bbf71b
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 21 deletions.
15 changes: 8 additions & 7 deletions src/arch/x86_64/kernel/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use crate::env;

pub const MAGIC_VALUE: u32 = 0x74726976;

pub const MMIO_START: usize = 0x00000000c0000000;
pub const MMIO_END: usize = 0x00000000c0000fff;
const IRQ_NUMBER: u8 = 12;
pub const MMIO_START: usize = 0x00000000feb00000;
pub const MMIO_END: usize = 0x00000000feb0ffff;
const IRQ_NUMBER: u8 = 23;

static mut MMIO_DRIVERS: Vec<MmioDriver> = Vec::new();

Expand Down Expand Up @@ -182,8 +182,6 @@ fn guess_device() -> Result<(&'static mut MmioRegisterLayout, u8), &'static str>
BasePageSize::SIZE as usize,
);

//mmio.print_information();

return Ok((mmio, IRQ_NUMBER));
}

Expand Down Expand Up @@ -223,8 +221,11 @@ pub(crate) fn init_drivers() {
"Found MMIO device, but we guess the interrupt number {}!",
irq
);
if let Ok(VirtioDriver::Network(drv)) = mmio_virtio::init_device(mmio, irq) {
register_driver(MmioDriver::VirtioNet(InterruptTicketMutex::new(drv)))
match mmio_virtio::init_device(mmio, irq) {
Ok(VirtioDriver::Network(drv)) => {
register_driver(MmioDriver::VirtioNet(InterruptTicketMutex::new(drv)))
}
Err(err) => error!("Could not initialize virtio-mmio device: {err}"),
}
} else {
warn!("Unable to find mmio device");
Expand Down
48 changes: 34 additions & 14 deletions src/drivers/virtio/transport/mmio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,16 @@ impl ComCfg {

/// Returns the device status field.
pub fn dev_status(&self) -> u8 {
unsafe { read_volatile(&self.com_cfg.status).bits() }
unsafe { read_volatile(&self.com_cfg.status).try_into().unwrap() }
}

/// Resets the device status field to zero.
pub fn reset_dev(&mut self) {
unsafe {
write_volatile(&mut self.com_cfg.status, DeviceStatus::empty());
write_volatile(
&mut self.com_cfg.status,
DeviceStatus::empty().bits().into(),
);
}
}

Expand All @@ -157,25 +160,33 @@ impl ComCfg {
/// A driver MAY use the device again after a proper reset of the device.
pub fn set_failed(&mut self) {
unsafe {
write_volatile(&mut self.com_cfg.status, DeviceStatus::FAILED);
write_volatile(&mut self.com_cfg.status, DeviceStatus::FAILED.bits().into());
}
}

/// Sets the ACKNOWLEDGE bit in the device status field. This indicates, the
/// OS has notived the device
pub fn ack_dev(&mut self) {
unsafe {
let status = read_volatile(&self.com_cfg.status);
write_volatile(&mut self.com_cfg.status, status | DeviceStatus::ACKNOWLEDGE);
let status =
DeviceStatus::from_bits(read_volatile(&self.com_cfg.status) as u8).unwrap();
write_volatile(
&mut self.com_cfg.status,
(status | DeviceStatus::ACKNOWLEDGE).bits().into(),
);
}
}

/// Sets the DRIVER bit in the device status field. This indicates, the OS
/// know how to run this device.
pub fn set_drv(&mut self) {
unsafe {
let status = read_volatile(&self.com_cfg.status);
write_volatile(&mut self.com_cfg.status, status | DeviceStatus::DRIVER);
let status =
DeviceStatus::from_bits(read_volatile(&self.com_cfg.status) as u8).unwrap();
write_volatile(
&mut self.com_cfg.status,
(status | DeviceStatus::DRIVER).bits().into(),
);
}
}

Expand All @@ -184,8 +195,12 @@ impl ComCfg {
/// Drivers MUST NOT accept new features after this step.
pub fn features_ok(&mut self) {
unsafe {
let status = read_volatile(&self.com_cfg.status);
write_volatile(&mut self.com_cfg.status, status | DeviceStatus::FEATURES_OK);
let status =
DeviceStatus::from_bits(read_volatile(&self.com_cfg.status) as u8).unwrap();
write_volatile(
&mut self.com_cfg.status,
(status | DeviceStatus::FEATURES_OK).bits().into(),
);
}
}

Expand All @@ -197,7 +212,8 @@ impl ComCfg {
/// otherwise, the device does not support our subset of features and the device is unusable.
pub fn check_features(&self) -> bool {
unsafe {
let status = read_volatile(&self.com_cfg.status);
let status =
DeviceStatus::from_bits(read_volatile(&self.com_cfg.status) as u8).unwrap();
status.contains(DeviceStatus::FEATURES_OK)
}
}
Expand All @@ -207,8 +223,12 @@ impl ComCfg {
/// After this call, the device is "live"!
pub fn drv_ok(&mut self) {
unsafe {
let status = read_volatile(&self.com_cfg.status);
write_volatile(&mut self.com_cfg.status, status | DeviceStatus::DRIVER_OK);
let status =
DeviceStatus::from_bits(read_volatile(&self.com_cfg.status) as u8).unwrap();
write_volatile(
&mut self.com_cfg.status,
(status | DeviceStatus::DRIVER_OK).bits().into(),
);
}
}

Expand Down Expand Up @@ -428,8 +448,8 @@ pub struct MmioRegisterLayout {
interrupt_ack: u32,
_reserved4: [u32; 2],

status: DeviceStatus,
_reserved5: [u8; 15],
status: u32,
_reserved5: [u32; 3],

queue_desc_low: u32, // non-legacy only
queue_desc_high: u32, // non-legacy only
Expand Down

0 comments on commit 9bbf71b

Please sign in to comment.