diff --git a/Cargo.toml b/Cargo.toml index 5777b91819..8c019f29ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,7 @@ acpi = [] smp = ["include-transformed"] fsgsbase = [] trace = [] +rtl8139 = ["tcp", "pci"] tcp = [ "smoltcp", ] diff --git a/src/arch/x86_64/kernel/mmio.rs b/src/arch/x86_64/kernel/mmio.rs index ce87f15a74..f3cdda926a 100644 --- a/src/arch/x86_64/kernel/mmio.rs +++ b/src/arch/x86_64/kernel/mmio.rs @@ -9,7 +9,6 @@ use crate::arch::x86_64::mm::paging::{ }; use crate::arch::x86_64::mm::{paging, PhysAddr}; use crate::drivers::net::virtio_net::VirtioNetDriver; -use crate::drivers::net::NetworkInterface; use crate::drivers::virtio::transport::mmio as mmio_virtio; use crate::drivers::virtio::transport::mmio::{DevId, MmioRegisterLayout, VirtioDriver}; @@ -27,7 +26,7 @@ pub(crate) enum MmioDriver { impl MmioDriver { #[allow(unreachable_patterns)] - fn get_network_driver(&self) -> Option<&InterruptTicketMutex> { + fn get_network_driver(&self) -> Option<&InterruptTicketMutex> { match self { Self::VirtioNet(drv) => Some(drv), _ => None, @@ -122,11 +121,11 @@ pub(crate) fn register_driver(drv: MmioDriver) { } } -pub fn get_network_driver() -> Option<&'static InterruptTicketMutex> { +pub(crate) fn get_network_driver() -> Option<&'static InterruptTicketMutex> { unsafe { MMIO_DRIVERS.iter().find_map(|drv| drv.get_network_driver()) } } -pub fn init_drivers() { +pub(crate) fn init_drivers() { // virtio: MMIO Device Discovery without_interrupts(|| { if let Ok(mmio) = detect_network() { diff --git a/src/drivers/mod.rs b/src/drivers/mod.rs index 6593a545d6..5d80091191 100644 --- a/src/drivers/mod.rs +++ b/src/drivers/mod.rs @@ -12,14 +12,14 @@ pub mod virtio; pub mod error { use core::fmt; - #[cfg(all(feature = "pci", not(target_arch = "aarch64")))] + #[cfg(feature = "rtl8139")] use crate::drivers::net::rtl8139::RTL8139Error; use crate::drivers::virtio::error::VirtioError; #[derive(Debug)] pub enum DriverError { InitVirtioDevFail(VirtioError), - #[cfg(all(feature = "pci", not(target_arch = "aarch64")))] + #[cfg(feature = "rtl8139")] InitRTL8139DevFail(RTL8139Error), } @@ -29,7 +29,7 @@ pub mod error { } } - #[cfg(all(feature = "pci", not(target_arch = "aarch64")))] + #[cfg(feature = "rtl8139")] impl From for DriverError { fn from(err: RTL8139Error) -> Self { DriverError::InitRTL8139DevFail(err) @@ -42,7 +42,7 @@ pub mod error { DriverError::InitVirtioDevFail(ref err) => { write!(f, "Virtio driver failed: {err:?}") } - #[cfg(all(feature = "pci", not(target_arch = "aarch64")))] + #[cfg(feature = "rtl8139")] DriverError::InitRTL8139DevFail(ref err) => { write!(f, "RTL8139 driver failed: {err:?}") } diff --git a/src/drivers/net/mod.rs b/src/drivers/net/mod.rs index 1edc188535..d14e5d6573 100644 --- a/src/drivers/net/mod.rs +++ b/src/drivers/net/mod.rs @@ -1,9 +1,10 @@ -#[cfg(all(feature = "pci", not(target_arch = "aarch64")))] +#[cfg(feature = "rtl8139")] pub mod rtl8139; -#[cfg(not(feature = "pci"))] +#[cfg(all(not(feature = "pci"), not(feature = "rtl8139")))] pub mod virtio_mmio; +#[cfg(not(feature = "rtl8139"))] pub mod virtio_net; -#[cfg(feature = "pci")] +#[cfg(all(feature = "pci", not(feature = "rtl8139")))] pub mod virtio_pci; #[cfg(target_arch = "x86_64")] @@ -18,25 +19,22 @@ use crate::arch::kernel::mmio as hardware; use crate::arch::scheduler::State; #[cfg(feature = "pci")] use crate::drivers::pci as hardware; +use crate::executor::device::{RxToken, TxToken}; /// A trait for accessing the network interface -pub trait NetworkInterface { +pub(crate) trait NetworkDriver { /// Returns the mac address of the device. fn get_mac_address(&self) -> [u8; 6]; /// Returns the current MTU of the device. fn get_mtu(&self) -> u16; - /// Get buffer to create a TX packet - /// - /// This returns ownership of the TX buffer. - fn get_tx_buffer(&mut self, len: usize) -> Result<(*mut u8, usize), ()>; - /// Frees the TX buffer (takes ownership) - fn free_tx_buffer(&self, token: usize); - /// Send TC packets (takes TX buffer ownership) - fn send_tx_buffer(&mut self, tkn_handle: usize, len: usize) -> Result<(), ()>; + /// Get buffer with the received packet + fn receive_packet(&mut self) -> Option<(RxToken, TxToken)>; + /// Send packet with the size `len` + fn send_packet(&mut self, len: usize, f: F) -> R + where + F: FnOnce(&mut [u8]) -> R; /// Check if a packet is available fn has_packet(&self) -> bool; - /// Get RX buffer with an received packet - fn receive_rx_buffer(&mut self, buffer: &mut [u8]) -> Result; /// Enable / disable the polling mode of the network interface fn set_polling_mode(&mut self, value: bool); /// Handle interrupt and check if a packet is available diff --git a/src/drivers/net/rtl8139.rs b/src/drivers/net/rtl8139.rs index e2aec79155..8a6bed8706 100644 --- a/src/drivers/net/rtl8139.rs +++ b/src/drivers/net/rtl8139.rs @@ -14,8 +14,9 @@ use crate::arch::mm::paging::virt_to_phys; use crate::arch::mm::VirtAddr; use crate::arch::pci::PciConfigRegion; use crate::drivers::error::DriverError; -use crate::drivers::net::{network_irqhandler, NetworkInterface}; +use crate::drivers::net::{network_irqhandler, NetworkDriver}; use crate::drivers::pci::{PciCommand, PciDevice}; +use crate::executor::device::{RxToken, TxToken}; /// size of the receive buffer const RX_BUF_LEN: usize = 8192; @@ -213,7 +214,7 @@ pub(crate) struct RTL8139Driver { polling_mode_counter: u32, } -impl NetworkInterface for RTL8139Driver { +impl NetworkDriver for RTL8139Driver { /// Returns the MAC address of the network interface fn get_mac_address(&self) -> [u8; 6] { self.mac @@ -224,37 +225,32 @@ impl NetworkInterface for RTL8139Driver { self.mtu } - fn get_tx_buffer(&mut self, len: usize) -> Result<(*mut u8, usize), ()> { + /// Send packet with the size `len` + fn send_packet(&mut self, len: usize, f: F) -> R + where + F: FnOnce(&mut [u8]) -> R, + { let id = self.tx_counter % NO_TX_BUFFERS; if self.tx_in_use[id] || len > TX_BUF_LEN { - trace!("Unable to get TX buffer"); - Err(()) + panic!("Unable to get TX buffer"); } else { self.tx_in_use[id] = true; self.tx_counter += 1; - Ok(( - self.txbuffer[id * TX_BUF_LEN..][..TX_BUF_LEN].as_mut_ptr(), - id, - )) - } - } + let buffer = &mut self.txbuffer[id * TX_BUF_LEN..][..len]; + let result = f(buffer); - fn free_tx_buffer(&self, _token: usize) { - // get_tx_buffer did not allocate - } + // send the packet + unsafe { + outl( + self.iobase + TSD0 + (4 * id as u16), + len.try_into().unwrap(), + ); //|0x3A0000); + } - fn send_tx_buffer(&mut self, id: usize, len: usize) -> Result<(), ()> { - // send the packet - unsafe { - outl( - self.iobase + TSD0 + (4 * id as u16), - len.try_into().unwrap(), - ); //|0x3A0000); + result } - - Ok(()) } fn has_packet(&self) -> bool { @@ -271,7 +267,8 @@ impl NetworkInterface for RTL8139Driver { false } - fn receive_rx_buffer(&mut self, buffer: &mut [u8]) -> Result { + /// Get buffer with the received packet + fn receive_packet(&mut self) -> Option<(RxToken, TxToken)> { let cmd = unsafe { inb(self.iobase + CR) }; if (cmd & CR_BUFE) != CR_BUFE { @@ -284,29 +281,27 @@ impl NetworkInterface for RTL8139Driver { // do we reach the end of the receive buffers? // in this case, we conact the two slices to one vec - if pos + length as usize > RX_BUF_LEN { - buffer[..RX_BUF_LEN - pos].copy_from_slice(&self.rxbuffer[pos..RX_BUF_LEN]); - buffer[RX_BUF_LEN - pos..usize::from(length)].copy_from_slice( - &self.rxbuffer[0..usize::from(length) - (RX_BUF_LEN - pos)], - ); + let vec_data = if pos + length as usize > RX_BUF_LEN { + let first = &self.rxbuffer[pos..RX_BUF_LEN]; + let second = &self.rxbuffer[..length as usize - first.len()]; + [first, second].concat() } else { - buffer[..length.into()] - .copy_from_slice(&self.rxbuffer[pos..pos + usize::from(length)]); + (self.rxbuffer[pos..][..length.into()]).to_vec() }; self.consume_current_buffer(); - Ok(length.into()) + Some((RxToken::new(vec_data), TxToken::new())) } else { - error!( + warn!( "RTL8192: invalid header {:#x}, rx_pos {}\n", header, self.rxpos ); - Err(()) + None } } else { - Err(()) + None } } diff --git a/src/drivers/net/virtio_net.rs b/src/drivers/net/virtio_net.rs index fc7ed5dd94..357443ddef 100644 --- a/src/drivers/net/virtio_net.rs +++ b/src/drivers/net/virtio_net.rs @@ -2,7 +2,6 @@ //! //! The module contains ... -use alloc::boxed::Box; use alloc::collections::VecDeque; use alloc::rc::Rc; use alloc::vec::Vec; @@ -22,7 +21,7 @@ use crate::config::VIRTIO_MAX_QUEUE_SIZE; use crate::drivers::net::virtio_mmio::NetDevCfgRaw; #[cfg(feature = "pci")] use crate::drivers::net::virtio_pci::NetDevCfgRaw; -use crate::drivers::net::NetworkInterface; +use crate::drivers::net::NetworkDriver; #[cfg(not(feature = "pci"))] use crate::drivers::virtio::transport::mmio::{ComCfg, IsrStatus, NotifCfg}; #[cfg(feature = "pci")] @@ -30,6 +29,7 @@ use crate::drivers::virtio::transport::pci::{ComCfg, IsrStatus, NotifCfg}; use crate::drivers::virtio::virtqueue::{ BuffSpec, BufferToken, Bytes, Transfer, Virtq, VqIndex, VqSize, VqType, }; +use crate::executor::device::{RxToken, TxToken}; pub const ETH_HDR: usize = 14usize; @@ -528,7 +528,7 @@ pub(crate) struct VirtioNetDriver { pub(super) mtu: u16, } -impl NetworkInterface for VirtioNetDriver { +impl NetworkDriver for VirtioNetDriver { /// Returns the mac address of the device. /// If VIRTIO_NET_F_MAC is not set, the function panics currently! fn get_mac_address(&self) -> [u8; 6] { @@ -544,110 +544,89 @@ impl NetworkInterface for VirtioNetDriver { self.mtu } - /// Provides the "user-space" with a pointer to usable memory. - /// - /// Therefore the driver checks if a free BufferToken is in its TxQueues struct. - /// If one is found, the function does return a pointer to the memory area, where - /// the "user-space" can write to and a raw pointer to the token in order to provide - /// it to the queue after the "user-space" driver has written to the buffer. - /// - /// If not BufferToken is found the functions returns an error. - fn get_tx_buffer(&mut self, len: usize) -> Result<(*mut u8, usize), ()> { - // Adding virtio header size to length. - let len = len + core::mem::size_of::(); - - match self.send_vqs.get_tkn(len) { - Some((mut buff_tkn, _vq_index)) => { - let (send_ptrs, _) = buff_tkn.raw_ptrs(); - // Currently we have single Buffers in the TxQueue of size: MTU + ETH_HDR + VIRTIO_NET_HDR - // see TxQueue.add() - let (buff_ptr, _) = send_ptrs.unwrap()[0]; - - // Do not show user-space memory for VirtioNetHdr. - let buff_ptr = unsafe { - buff_ptr.offset(isize::try_from(core::mem::size_of::()).unwrap()) - }; - - Ok((buff_ptr, Box::into_raw(Box::new(buff_tkn)) as usize)) - } - None => Err(()), - } + fn has_packet(&self) -> bool { + self.recv_vqs.poll(); + !self.recv_vqs.poll_queue.borrow().is_empty() } - fn free_tx_buffer(&self, token: usize) { - unsafe { drop(Box::from_raw(token as *mut BufferToken)) } - } + /// Provides smoltcp a slice to copy the IP packet and transfer the packet + /// to the send queue. + fn send_packet(&mut self, len: usize, f: F) -> R + where + F: FnOnce(&mut [u8]) -> R, + { + if let Some((mut buff_tkn, _vq_index)) = self + .send_vqs + .get_tkn(len + core::mem::size_of::()) + { + let (send_ptrs, _) = buff_tkn.raw_ptrs(); + // Currently we have single Buffers in the TxQueue of size: MTU + ETH_HDR + VIRTIO_NET_HDR + // see TxQueue.add() + let (buff_ptr, _) = send_ptrs.unwrap()[0]; + + // Do not show smoltcp the memory region for VirtioNetHdr. + let header = unsafe { &mut *(buff_ptr as *mut VirtioNetHdr) }; + *header = Default::default(); + let buff_ptr = unsafe { + buff_ptr.offset(isize::try_from(core::mem::size_of::()).unwrap()) + }; - fn send_tx_buffer(&mut self, tkn_handle: usize, _len: usize) -> Result<(), ()> { - // This does not result in a new assignment, or in a drop of the BufferToken, which - // would be dangerous, as the memory is freed then. - let mut tkn = *unsafe { Box::from_raw(tkn_handle as *mut BufferToken) }; - - // If a checksum isn't necessary, we have inform the host within the header - // see Virtio specification 5.1.6.2 - if !self.with_checksums() { - unsafe { - let (send_ptrs, _) = tkn.raw_ptrs(); - let (addr, _) = send_ptrs.unwrap()[0]; - let header = addr as *mut VirtioNetHdr; - let type_ = u16::from_be( - *(addr.offset( - (12 + core::mem::size_of::()) - .try_into() - .unwrap(), - ) as *const u16), - ); + let buf_slice: &'static mut [u8] = + unsafe { core::slice::from_raw_parts_mut(buff_ptr, len) }; + let result = f(buf_slice); + + // If a checksum isn't necessary, we have inform the host within the header + // see Virtio specification 5.1.6.2 + if !self.with_checksums() { + let type_ = unsafe { u16::from_be(*(buff_ptr.offset(12) as *const u16)) }; - *header = Default::default(); match type_ { 0x0800 /* IPv4 */ => { - let protocol = *(addr.offset((14+9+core::mem::size_of::()).try_into().unwrap()) as *const u8); + let protocol = unsafe { *(buff_ptr.offset((14+9).try_into().unwrap()) as *const u8) }; if protocol == 6 /* TCP */ { - (*header).flags = NetHdrFlag::VIRTIO_NET_HDR_F_NEEDS_CSUM; - (*header).csum_start = 14+20; - (*header).csum_offset = 16; + header.flags = NetHdrFlag::VIRTIO_NET_HDR_F_NEEDS_CSUM; + header.csum_start = 14+20; + header.csum_offset = 16; } else if protocol == 17 /* UDP */ { - (*header).flags = NetHdrFlag::VIRTIO_NET_HDR_F_NEEDS_CSUM; - (*header).csum_start = 14+20; - (*header).csum_offset = 6; + header.flags = NetHdrFlag::VIRTIO_NET_HDR_F_NEEDS_CSUM; + header.csum_start = 14+20; + header.csum_offset = 6; } }, 0x86DD /* IPv6 */ => { - let protocol = *(addr.offset((14+9+core::mem::size_of::()).try_into().unwrap()) as *const u8); + let protocol = unsafe { *(buff_ptr.offset((14+9).try_into().unwrap()) as *const u8) }; if protocol == 6 /* TCP */ { - (*header).flags = NetHdrFlag::VIRTIO_NET_HDR_F_NEEDS_CSUM; - (*header).csum_start = 14+40; - (*header).csum_offset = 16; + header.flags = NetHdrFlag::VIRTIO_NET_HDR_F_NEEDS_CSUM; + header.csum_start = 14+40; + header.csum_offset = 16; } else if protocol == 17 /* UDP */ { - (*header).flags = NetHdrFlag::VIRTIO_NET_HDR_F_NEEDS_CSUM; - (*header).csum_start = 14+40; - (*header).csum_offset = 6; + header.flags = NetHdrFlag::VIRTIO_NET_HDR_F_NEEDS_CSUM; + header.csum_start = 14+40; + header.csum_offset = 6; } }, _ => {}, } } - } - - tkn.provide() - .dispatch_await(Rc::clone(&self.send_vqs.poll_queue), false); - Ok(()) - } + buff_tkn + .provide() + .dispatch_await(Rc::clone(&self.send_vqs.poll_queue), false); - fn has_packet(&self) -> bool { - self.recv_vqs.poll(); - !self.recv_vqs.poll_queue.borrow().is_empty() + result + } else { + panic!("Unable to get token for send queue"); + } } - fn receive_rx_buffer(&mut self, buffer: &mut [u8]) -> Result { + fn receive_packet(&mut self) -> Option<(RxToken, TxToken)> { match self.recv_vqs.get_next() { Some(transfer) => { let transfer = match RxQueues::post_processing(transfer) { Ok(trf) => trf, Err(vnet_err) => { - error!("Post processing failed. Err: {:?}", vnet_err); - return Err(()); + warn!("Post processing failed. Err: {:?}", vnet_err); + return None; } }; @@ -671,15 +650,14 @@ impl NetworkInterface for VirtioNetDriver { // so this is fine. let recv_ref = (recv_payload as *const [u8]) as *mut [u8]; let ref_data: &'static mut [u8] = unsafe { &mut *(recv_ref) }; - let len = ref_data.len(); - buffer[..len].copy_from_slice(ref_data); + let vec_data = ref_data.to_vec(); transfer .reuse() .unwrap() .provide() .dispatch_await(Rc::clone(&self.recv_vqs.poll_queue), false); - Ok(len) + Some((RxToken::new(vec_data), TxToken::new())) } else if recv_data.len() == 1 { let packet = recv_data.pop().unwrap(); /*let header = unsafe { @@ -699,15 +677,14 @@ impl NetworkInterface for VirtioNetDriver { packet.len() - mem::size_of::(), ) }; - let len = ref_data.len(); - buffer[..len].copy_from_slice(ref_data); + let vec_data = ref_data.to_vec(); transfer .reuse() .unwrap() .provide() .dispatch_await(Rc::clone(&self.recv_vqs.poll_queue), false); - Ok(len) + Some((RxToken::new(vec_data), TxToken::new())) } else { error!("Empty transfer, or with wrong buffer layout. Reusing and returning error to user-space network driver..."); transfer @@ -718,10 +695,10 @@ impl NetworkInterface for VirtioNetDriver { .provide() .dispatch_await(Rc::clone(&self.recv_vqs.poll_queue), false); - Err(()) + None } } - None => Err(()), + None => None, } } diff --git a/src/drivers/pci.rs b/src/drivers/pci.rs index 1bda7a9def..b57987b6c4 100644 --- a/src/drivers/pci.rs +++ b/src/drivers/pci.rs @@ -13,10 +13,10 @@ use pci_types::{ use crate::arch::mm::{PhysAddr, VirtAddr}; use crate::arch::pci::PciConfigRegion; use crate::drivers::fs::virtio_fs::VirtioFsDriver; -#[cfg(not(target_arch = "aarch64"))] +#[cfg(feature = "rtl8139")] use crate::drivers::net::rtl8139::{self, RTL8139Driver}; +#[cfg(not(feature = "rtl8139"))] use crate::drivers::net::virtio_net::VirtioNetDriver; -use crate::drivers::net::NetworkInterface; use crate::drivers::virtio::transport::pci as pci_virtio; use crate::drivers::virtio::transport::pci::VirtioDriver; @@ -456,16 +456,24 @@ pub(crate) fn print_information() { #[allow(clippy::large_enum_variant)] pub(crate) enum PciDriver { VirtioFs(InterruptTicketMutex), + #[cfg(not(feature = "rtl8139"))] VirtioNet(InterruptTicketMutex), - #[cfg(not(target_arch = "aarch64"))] + #[cfg(feature = "rtl8139")] RTL8139Net(InterruptTicketMutex), } impl PciDriver { - fn get_network_driver(&self) -> Option<&InterruptTicketMutex> { + #[cfg(not(feature = "rtl8139"))] + fn get_network_driver(&self) -> Option<&InterruptTicketMutex> { match self { Self::VirtioNet(drv) => Some(drv), - #[cfg(not(target_arch = "aarch64"))] + _ => None, + } + } + + #[cfg(feature = "rtl8139")] + fn get_network_driver(&self) -> Option<&InterruptTicketMutex> { + match self { Self::RTL8139Net(drv) => Some(drv), _ => None, } @@ -485,7 +493,13 @@ pub(crate) fn register_driver(drv: PciDriver) { } } -pub(crate) fn get_network_driver() -> Option<&'static InterruptTicketMutex> { +#[cfg(not(feature = "rtl8139"))] +pub(crate) fn get_network_driver() -> Option<&'static InterruptTicketMutex> { + unsafe { PCI_DRIVERS.iter().find_map(|drv| drv.get_network_driver()) } +} + +#[cfg(feature = "rtl8139")] +pub(crate) fn get_network_driver() -> Option<&'static InterruptTicketMutex> { unsafe { PCI_DRIVERS.iter().find_map(|drv| drv.get_network_driver()) } } @@ -498,8 +512,6 @@ pub(crate) fn get_filesystem_driver() -> Option<&'static InterruptTicketMutex { - nic_available = true; register_driver(PciDriver::VirtioNet(InterruptTicketMutex::new(drv))) } Ok(VirtioDriver::FileSystem(drv)) => { @@ -525,24 +537,21 @@ pub(crate) fn init_drivers() { } } - // do we already found a network interface? - #[cfg(not(target_arch = "aarch64"))] - if !nic_available { - // Searching for Realtek RTL8139, which is supported by Qemu - for adapter in unsafe { - PCI_DEVICES.iter().filter(|x| { - let (vendor_id, device_id) = x.id(); - vendor_id == 0x10ec && (0x8138..=0x8139).contains(&device_id) - }) - } { - info!( - "Found Realtek network device with device id {:#x}", - adapter.device_id() - ); - - if let Ok(drv) = rtl8139::init_device(adapter) { - register_driver(PciDriver::RTL8139Net(InterruptTicketMutex::new(drv))) - } + // Searching for Realtek RTL8139, which is supported by Qemu + #[cfg(feature = "rtl8139")] + for adapter in unsafe { + PCI_DEVICES.iter().filter(|x| { + let (vendor_id, device_id) = x.id(); + vendor_id == 0x10ec && (0x8138..=0x8139).contains(&device_id) + }) + } { + info!( + "Found Realtek network device with device id {:#x}", + adapter.device_id() + ); + + if let Ok(drv) = rtl8139::init_device(adapter) { + register_driver(PciDriver::RTL8139Net(InterruptTicketMutex::new(drv))) } } }); diff --git a/src/drivers/virtio/mod.rs b/src/drivers/virtio/mod.rs index a700166404..de61306ffd 100644 --- a/src/drivers/virtio/mod.rs +++ b/src/drivers/virtio/mod.rs @@ -10,6 +10,7 @@ pub mod error { #[cfg(feature = "pci")] pub use crate::drivers::fs::virtio_fs::error::VirtioFsError; + #[cfg(not(feature = "rtl8139"))] pub use crate::drivers::net::virtio_net::error::VirtioNetError; #[cfg(feature = "pci")] use crate::drivers::pci::error::PciError; @@ -19,6 +20,7 @@ pub mod error { #[cfg(feature = "pci")] FromPci(PciError), DevNotSupported(u16), + #[cfg(not(feature = "rtl8139"))] NetDriver(VirtioNetError), #[cfg(feature = "pci")] FsDriver(VirtioFsError), @@ -40,6 +42,7 @@ pub mod error { PciError::NoVirtioCaps(id) => write!(f, "Driver failed to initialize device with id: {id:#x}. Reason: No Virtio capabilities were found."), }, VirtioError::DevNotSupported(id) => write!(f, "Device with id {id:#x} not supported."), + #[cfg(not(feature = "rtl8139"))] VirtioError::NetDriver(net_error) => match net_error { VirtioNetError::General => write!(f, "Virtio network driver failed due to unknown reasons!"), VirtioNetError::NoDevCfg(id) => write!(f, "Virtio network driver failed, for device {id:x}, due to a missing or malformed device config!"), diff --git a/src/drivers/virtio/transport/pci.rs b/src/drivers/virtio/transport/pci.rs index cbc875cec7..8af5c41ec1 100644 --- a/src/drivers/virtio/transport/pci.rs +++ b/src/drivers/virtio/transport/pci.rs @@ -8,13 +8,16 @@ use core::intrinsics::unaligned_volatile_store; use core::mem; use core::result::Result; +#[cfg(not(feature = "rtl8139"))] use crate::arch::kernel::interrupts::*; use crate::arch::memory_barrier; use crate::arch::mm::PhysAddr; use crate::arch::pci::PciConfigRegion; use crate::drivers::error::DriverError; use crate::drivers::fs::virtio_fs::VirtioFsDriver; +#[cfg(not(feature = "rtl8139"))] use crate::drivers::net::network_irqhandler; +#[cfg(not(feature = "rtl8139"))] use crate::drivers::net::virtio_net::VirtioNetDriver; use crate::drivers::pci::error::PciError; use crate::drivers::pci::{DeviceHeader, Masks, PciDevice}; @@ -1249,6 +1252,7 @@ pub(crate) fn init_device( VirtioError::DevNotSupported(device_id), )) } + #[cfg(not(feature = "rtl8139"))] DevId::VIRTIO_DEV_ID_NET => match VirtioNetDriver::init(device) { Ok(virt_net_drv) => { info!("Virtio network driver initialized."); @@ -1295,6 +1299,7 @@ pub(crate) fn init_device( match virt_drv { Ok(drv) => { match &drv { + #[cfg(not(feature = "rtl8139"))] VirtioDriver::Network(_) => { let irq = device.get_irq().unwrap(); info!("Install virtio interrupt handler at line {}", irq); @@ -1312,6 +1317,7 @@ pub(crate) fn init_device( } pub(crate) enum VirtioDriver { + #[cfg(not(feature = "rtl8139"))] Network(VirtioNetDriver), FileSystem(VirtioFsDriver), } diff --git a/src/env.rs b/src/env.rs index 5ca1667b8b..5a1e4efd23 100644 --- a/src/env.rs +++ b/src/env.rs @@ -108,6 +108,7 @@ pub fn freq() -> Option { CLI.get().unwrap().freq } +#[allow(dead_code)] pub fn var(key: &str) -> Option<&String> { CLI.get().unwrap().env_vars.get(key) } diff --git a/src/executor/device.rs b/src/executor/device.rs index 45a1c91c04..189af4d6d0 100644 --- a/src/executor/device.rs +++ b/src/executor/device.rs @@ -1,6 +1,5 @@ use alloc::boxed::Box; use alloc::vec::Vec; -use core::slice; #[cfg(not(feature = "dhcpv4"))] use core::str::FromStr; @@ -17,6 +16,7 @@ use super::network::{NetworkInterface, NetworkState}; use crate::arch; #[cfg(not(feature = "pci"))] use crate::arch::kernel::mmio as hardware; +use crate::drivers::net::NetworkDriver; #[cfg(feature = "pci")] use crate::drivers::pci as hardware; @@ -177,15 +177,8 @@ impl Device for HermitNet { } fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { - let mut buffer = vec![0; self.mtu.into()]; if let Some(driver) = hardware::get_network_driver() { - match driver.lock().receive_rx_buffer(&mut buffer[..]) { - Ok(size) => { - buffer.resize(size, 0); - Some((RxToken::new(buffer), TxToken::new())) - } - _ => None, - } + driver.lock().receive_packet() } else { None } @@ -196,6 +189,9 @@ impl Device for HermitNet { } } +// Unique handle to identify the RxToken +pub(crate) type RxHandle = usize; + #[doc(hidden)] pub(crate) struct RxToken { buffer: Vec, @@ -230,18 +226,9 @@ impl phy::TxToken for TxToken { where F: FnOnce(&mut [u8]) -> R, { - let (tx_buffer, handle) = hardware::get_network_driver() - .unwrap() - .lock() - .get_tx_buffer(len) - .unwrap(); - let tx_slice: &'static mut [u8] = unsafe { slice::from_raw_parts_mut(tx_buffer, len) }; - let result = f(tx_slice); hardware::get_network_driver() .unwrap() .lock() - .send_tx_buffer(handle, len) - .expect("Unable to send TX buffer"); - result + .send_packet(len, f) } } diff --git a/src/executor/mod.rs b/src/executor/mod.rs index d8eaf7ca51..0f84b413cb 100644 --- a/src/executor/mod.rs +++ b/src/executor/mod.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] #[cfg(feature = "tcp")] -mod device; +pub(crate) mod device; #[cfg(feature = "tcp")] pub(crate) mod network; pub(crate) mod task; diff --git a/src/executor/network.rs b/src/executor/network.rs index b3b771bfac..ba45b6dd09 100644 --- a/src/executor/network.rs +++ b/src/executor/network.rs @@ -18,6 +18,8 @@ use smoltcp::wire::{IpCidr, Ipv4Address, Ipv4Cidr}; use crate::arch::core_local::*; use crate::arch::{self, interrupts}; +#[cfg(feature = "pci")] +use crate::drivers::net::NetworkDriver; use crate::executor::device::HermitNet; use crate::executor::{spawn, TaskNotify};