use alloc::vec;
use super::net_buf::{RxBuffer, TxBuffer};
use super::{EthernetAddress, VirtIONetRaw};
use crate::transport::InterruptStatus;
use crate::{Error, Result, hal::Hal, transport::Transport};
pub struct VirtIONet<H: Hal, T: Transport, const QUEUE_SIZE: usize> {
inner: VirtIONetRaw<H, T, QUEUE_SIZE>,
rx_buffers: [Option<RxBuffer>; QUEUE_SIZE],
}
impl<H: Hal, T: Transport, const QUEUE_SIZE: usize> VirtIONet<H, T, QUEUE_SIZE> {
pub fn new(transport: T, buf_len: usize) -> Result<Self> {
let mut inner = VirtIONetRaw::new(transport)?;
const NONE_BUF: Option<RxBuffer> = None;
let mut rx_buffers = [NONE_BUF; QUEUE_SIZE];
for (i, rx_buf_place) in rx_buffers.iter_mut().enumerate() {
let mut rx_buf = RxBuffer::new(i, buf_len, inner.legacy_header);
let token = unsafe { inner.receive_begin(rx_buf.as_bytes_mut())? };
assert_eq!(token, i as u16);
*rx_buf_place = Some(rx_buf);
}
Ok(VirtIONet { inner, rx_buffers })
}
pub fn ack_interrupt(&mut self) -> InterruptStatus {
self.inner.ack_interrupt()
}
pub fn disable_interrupts(&mut self) {
self.inner.disable_interrupts()
}
pub fn enable_interrupts(&mut self) {
self.inner.enable_interrupts()
}
pub fn mac_address(&self) -> EthernetAddress {
self.inner.mac_address()
}
pub fn can_send(&self) -> bool {
self.inner.can_send()
}
pub fn can_recv(&self) -> bool {
self.inner.poll_receive().is_some()
}
pub fn receive(&mut self) -> Result<RxBuffer> {
if let Some(token) = self.inner.poll_receive() {
let mut rx_buf = self.rx_buffers[token as usize]
.take()
.ok_or(Error::WrongToken)?;
if token != rx_buf.idx {
return Err(Error::WrongToken);
}
let (_hdr_len, pkt_len) =
unsafe { self.inner.receive_complete(token, rx_buf.as_bytes_mut())? };
rx_buf.set_packet_len(pkt_len);
Ok(rx_buf)
} else {
Err(Error::NotReady)
}
}
pub fn recycle_rx_buffer(&mut self, mut rx_buf: RxBuffer) -> Result {
let new_token = unsafe { self.inner.receive_begin(rx_buf.as_bytes_mut()) }?;
if self.rx_buffers[new_token as usize].is_some() {
return Err(Error::WrongToken);
}
rx_buf.idx = new_token;
self.rx_buffers[new_token as usize] = Some(rx_buf);
Ok(())
}
pub fn new_tx_buffer(&self, buf_len: usize) -> TxBuffer {
TxBuffer(vec![0; buf_len])
}
pub fn send(&mut self, tx_buf: TxBuffer) -> Result {
self.inner.send(tx_buf.packet())
}
}