|
@@ -1,7 +1,7 @@
|
|
use core::mem::{size_of, MaybeUninit};
|
|
use core::mem::{size_of, MaybeUninit};
|
|
|
|
|
|
use super::*;
|
|
use super::*;
|
|
-use crate::transport::{mmio::VirtIOHeader, Transport};
|
|
|
|
|
|
+use crate::transport::Transport;
|
|
use bitflags::*;
|
|
use bitflags::*;
|
|
use core::hint::spin_loop;
|
|
use core::hint::spin_loop;
|
|
use log::*;
|
|
use log::*;
|
|
@@ -14,35 +14,35 @@ use volatile::{ReadOnly, Volatile};
|
|
/// Empty buffers are placed in one virtqueue for receiving packets, and
|
|
/// Empty buffers are placed in one virtqueue for receiving packets, and
|
|
/// outgoing packets are enqueued into another for transmission in that order.
|
|
/// outgoing packets are enqueued into another for transmission in that order.
|
|
/// A third command queue is used to control advanced filtering features.
|
|
/// A third command queue is used to control advanced filtering features.
|
|
-pub struct VirtIONet<'a, H: Hal> {
|
|
|
|
- header: &'static mut VirtIOHeader,
|
|
|
|
|
|
+pub struct VirtIONet<'a, H: Hal, T: Transport> {
|
|
|
|
+ transport: &'a mut T,
|
|
mac: EthernetAddress,
|
|
mac: EthernetAddress,
|
|
recv_queue: VirtQueue<'a, H>,
|
|
recv_queue: VirtQueue<'a, H>,
|
|
send_queue: VirtQueue<'a, H>,
|
|
send_queue: VirtQueue<'a, H>,
|
|
}
|
|
}
|
|
|
|
|
|
-impl<H: Hal> VirtIONet<'_, H> {
|
|
|
|
|
|
+impl<'a, H: Hal, T: Transport> VirtIONet<'a, H, T> {
|
|
/// Create a new VirtIO-Net driver.
|
|
/// Create a new VirtIO-Net driver.
|
|
- pub fn new(header: &'static mut VirtIOHeader) -> Result<Self> {
|
|
|
|
- header.begin_init(|features| {
|
|
|
|
|
|
+ pub fn new(transport: &'a mut T) -> Result<Self> {
|
|
|
|
+ transport.begin_init(|features| {
|
|
let features = Features::from_bits_truncate(features);
|
|
let features = Features::from_bits_truncate(features);
|
|
info!("Device features {:?}", features);
|
|
info!("Device features {:?}", features);
|
|
let supported_features = Features::MAC | Features::STATUS;
|
|
let supported_features = Features::MAC | Features::STATUS;
|
|
(features & supported_features).bits()
|
|
(features & supported_features).bits()
|
|
});
|
|
});
|
|
// read configuration space
|
|
// read configuration space
|
|
- let config = unsafe { &mut *(header.config_space() as *mut Config) };
|
|
|
|
|
|
+ let config = unsafe { &mut *(transport.config_space() as *mut Config) };
|
|
let mac = config.mac.read();
|
|
let mac = config.mac.read();
|
|
debug!("Got MAC={:?}, status={:?}", mac, config.status.read());
|
|
debug!("Got MAC={:?}, status={:?}", mac, config.status.read());
|
|
|
|
|
|
let queue_num = 2; // for simplicity
|
|
let queue_num = 2; // for simplicity
|
|
- let recv_queue = VirtQueue::new(header, QUEUE_RECEIVE, queue_num)?;
|
|
|
|
- let send_queue = VirtQueue::new(header, QUEUE_TRANSMIT, queue_num)?;
|
|
|
|
|
|
+ let recv_queue = VirtQueue::new(transport, QUEUE_RECEIVE, queue_num)?;
|
|
|
|
+ let send_queue = VirtQueue::new(transport, QUEUE_TRANSMIT, queue_num)?;
|
|
|
|
|
|
- header.finish_init();
|
|
|
|
|
|
+ transport.finish_init();
|
|
|
|
|
|
Ok(VirtIONet {
|
|
Ok(VirtIONet {
|
|
- header,
|
|
|
|
|
|
+ transport,
|
|
mac,
|
|
mac,
|
|
recv_queue,
|
|
recv_queue,
|
|
send_queue,
|
|
send_queue,
|
|
@@ -51,7 +51,7 @@ impl<H: Hal> VirtIONet<'_, H> {
|
|
|
|
|
|
/// Acknowledge interrupt.
|
|
/// Acknowledge interrupt.
|
|
pub fn ack_interrupt(&mut self) -> bool {
|
|
pub fn ack_interrupt(&mut self) -> bool {
|
|
- self.header.ack_interrupt()
|
|
|
|
|
|
+ self.transport.ack_interrupt()
|
|
}
|
|
}
|
|
|
|
|
|
/// Get MAC address.
|
|
/// Get MAC address.
|
|
@@ -74,7 +74,7 @@ impl<H: Hal> VirtIONet<'_, H> {
|
|
let mut header = MaybeUninit::<Header>::uninit();
|
|
let mut header = MaybeUninit::<Header>::uninit();
|
|
let header_buf = unsafe { (*header.as_mut_ptr()).as_buf_mut() };
|
|
let header_buf = unsafe { (*header.as_mut_ptr()).as_buf_mut() };
|
|
self.recv_queue.add(&[], &[header_buf, buf])?;
|
|
self.recv_queue.add(&[], &[header_buf, buf])?;
|
|
- self.header.notify(QUEUE_RECEIVE as u32);
|
|
|
|
|
|
+ self.transport.notify(QUEUE_RECEIVE as u32);
|
|
while !self.recv_queue.can_pop() {
|
|
while !self.recv_queue.can_pop() {
|
|
spin_loop();
|
|
spin_loop();
|
|
}
|
|
}
|
|
@@ -88,7 +88,7 @@ impl<H: Hal> VirtIONet<'_, H> {
|
|
pub fn send(&mut self, buf: &[u8]) -> Result {
|
|
pub fn send(&mut self, buf: &[u8]) -> Result {
|
|
let header = unsafe { MaybeUninit::<Header>::zeroed().assume_init() };
|
|
let header = unsafe { MaybeUninit::<Header>::zeroed().assume_init() };
|
|
self.send_queue.add(&[header.as_buf(), buf], &[])?;
|
|
self.send_queue.add(&[header.as_buf(), buf], &[])?;
|
|
- self.header.notify(QUEUE_TRANSMIT as u32);
|
|
|
|
|
|
+ self.transport.notify(QUEUE_TRANSMIT as u32);
|
|
while !self.send_queue.can_pop() {
|
|
while !self.send_queue.can_pop() {
|
|
spin_loop();
|
|
spin_loop();
|
|
}
|
|
}
|