|
|
|
@ -10,10 +10,8 @@ use smoltcp::phy::{self, DeviceCapabilities};
|
|
|
|
|
use smoltcp::time::Instant;
|
|
|
|
|
use smoltcp::wire::*;
|
|
|
|
|
use smoltcp::Result;
|
|
|
|
|
use bitflags::*;
|
|
|
|
|
|
|
|
|
|
use rcore_memory::PAGE_SIZE;
|
|
|
|
|
|
|
|
|
|
use crate::drivers::provider::Provider;
|
|
|
|
|
use crate::net::SOCKETS;
|
|
|
|
|
use crate::sync::SpinNoIrqLock as Mutex;
|
|
|
|
|
|
|
|
|
@ -32,8 +30,28 @@ const AXI_STREAM_FIFO_RLR: *mut u32 = phys_to_virt(0x64A0_0024) as *mut u32;
|
|
|
|
|
const AXI_STREAM_FIFO_TDR: *mut u32 = phys_to_virt(0x64A0_002C) as *mut u32;
|
|
|
|
|
const AXI_STREAM_FIFO_RDR: *mut u32 = phys_to_virt(0x64A0_0030) as *mut u32;
|
|
|
|
|
|
|
|
|
|
const ENABLED_PORTS: u8 = 2;
|
|
|
|
|
|
|
|
|
|
bitflags! {
|
|
|
|
|
struct AXIStreamFifoInterrupt : u32 {
|
|
|
|
|
const RECV_EMPTY = 1 << 19;
|
|
|
|
|
const RECV_FULL = 1 << 20;
|
|
|
|
|
const TRAN_EMPTY = 1 << 21;
|
|
|
|
|
const TRAN_FULL = 1 << 22;
|
|
|
|
|
const RECV_RESET = 1 << 23;
|
|
|
|
|
const TRAN_RESET = 1 << 24;
|
|
|
|
|
const TRAN_SIZE_ERR = 1 << 25;
|
|
|
|
|
const RECV_COMPLETE = 1 << 26;
|
|
|
|
|
const TRAN_COMPLETE = 1 << 27;
|
|
|
|
|
const TRAN_PACKET_OVERRUN_ERR = 1 << 28;
|
|
|
|
|
const RECV_PACKET_UNDERRUN_ERR = 1 << 29;
|
|
|
|
|
const RECV_PACKET_OVERRUN_READ_ERR = 1 << 30;
|
|
|
|
|
const RECV_PACKET_UNDERRUN_READ_ERR = 1 << 31;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct Router {
|
|
|
|
|
buffer: Vec<Vec<u8>>,
|
|
|
|
|
buffer: [Vec<Vec<u8>>; ENABLED_PORTS as usize],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Router {
|
|
|
|
@ -41,13 +59,13 @@ impl Router {
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn receive_available(&self) -> bool {
|
|
|
|
|
self.buffer.len() > 0
|
|
|
|
|
fn receive_available(&self, port: u8) -> bool {
|
|
|
|
|
self.buffer[port as usize].len() > 0
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct RouterDriver(Arc<Mutex<Router>>);
|
|
|
|
|
pub struct RouterDriver(Arc<Mutex<Router>>, u8);
|
|
|
|
|
|
|
|
|
|
pub struct RouterRxToken(RouterDriver);
|
|
|
|
|
pub struct RouterTxToken(RouterDriver);
|
|
|
|
@ -58,7 +76,7 @@ impl<'a> phy::Device<'a> for RouterDriver {
|
|
|
|
|
|
|
|
|
|
fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
|
|
|
|
|
let driver = self.0.lock();
|
|
|
|
|
if driver.transmit_available() && driver.receive_available() {
|
|
|
|
|
if driver.transmit_available() && driver.receive_available(self.1) {
|
|
|
|
|
// potential racing
|
|
|
|
|
Some((RouterRxToken(self.clone()), RouterTxToken(self.clone())))
|
|
|
|
|
} else {
|
|
|
|
@ -89,7 +107,7 @@ impl phy::RxToken for RouterRxToken {
|
|
|
|
|
F: FnOnce(&[u8]) -> Result<R>,
|
|
|
|
|
{
|
|
|
|
|
let mut router = (self.0).0.lock();
|
|
|
|
|
let buffer = router.buffer.pop().unwrap();
|
|
|
|
|
let buffer = router.buffer[(self.0).1 as usize].pop().unwrap();
|
|
|
|
|
f(&buffer)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -105,10 +123,11 @@ impl phy::TxToken for RouterTxToken {
|
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
AXI_STREAM_FIFO_TDR.write_volatile(2);
|
|
|
|
|
AXI_STREAM_FIFO_TDFD.write_volatile((self.0).1 as u32);
|
|
|
|
|
for byte in buffer {
|
|
|
|
|
AXI_STREAM_FIFO_TDFD.write_volatile(byte as u32);
|
|
|
|
|
}
|
|
|
|
|
AXI_STREAM_FIFO_TLR.write((len * 4) as u32);
|
|
|
|
|
AXI_STREAM_FIFO_TLR.write(((len + 1) * 4) as u32);
|
|
|
|
|
}
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
@ -126,7 +145,7 @@ impl Driver for RouterInterface {
|
|
|
|
|
let isr = unsafe { AXI_STREAM_FIFO_ISR.read_volatile() };
|
|
|
|
|
|
|
|
|
|
if isr > 0 {
|
|
|
|
|
debug!("handle router interrupt {:b}", isr);
|
|
|
|
|
debug!("handle router interrupt {:?}", AXIStreamFifoInterrupt::from_bits_truncate(isr));
|
|
|
|
|
unsafe {
|
|
|
|
|
AXI_STREAM_FIFO_ISR.write(isr);
|
|
|
|
|
let rdfo = AXI_STREAM_FIFO_RDFO.read_volatile();
|
|
|
|
@ -134,11 +153,12 @@ impl Driver for RouterInterface {
|
|
|
|
|
let mut buffer = Vec::new();
|
|
|
|
|
let rlr = AXI_STREAM_FIFO_RLR.read_volatile();
|
|
|
|
|
let rdr = AXI_STREAM_FIFO_RDR.read_volatile();
|
|
|
|
|
for i in 0..rdfo {
|
|
|
|
|
let port = AXI_STREAM_FIFO_RDFD.read_volatile();
|
|
|
|
|
for i in 1..rdfo {
|
|
|
|
|
buffer.push(AXI_STREAM_FIFO_RDFD.read_volatile() as u8);
|
|
|
|
|
}
|
|
|
|
|
debug!("got packet of length {}", rdfo);
|
|
|
|
|
driver.buffer.push(buffer);
|
|
|
|
|
debug!("got packet of length {} port {}", rdfo, port);
|
|
|
|
|
driver.buffer[port as usize].push(buffer);
|
|
|
|
|
}
|
|
|
|
|
drop(driver);
|
|
|
|
|
|
|
|
|
@ -183,7 +203,7 @@ impl Driver for RouterInterface {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn router_init() -> Arc<RouterInterface> {
|
|
|
|
|
pub fn router_init() {
|
|
|
|
|
unsafe {
|
|
|
|
|
// reset tx fifo
|
|
|
|
|
AXI_STREAM_FIFO_TDFR.write_volatile(0xA5);
|
|
|
|
@ -191,13 +211,13 @@ pub fn router_init() -> Arc<RouterInterface> {
|
|
|
|
|
AXI_STREAM_FIFO_RDFR.write_volatile(0xA5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let ethernet_addr = EthernetAddress::from_bytes(&[2, 2, 3, 3, 0, 0]);
|
|
|
|
|
for i in 0..ENABLED_PORTS {
|
|
|
|
|
let ethernet_addr = EthernetAddress::from_bytes(&[2, 2, 3, 3, 0, i]);
|
|
|
|
|
|
|
|
|
|
let net_driver = RouterDriver(Arc::new(Mutex::new(Router { buffer: Vec::new() })));
|
|
|
|
|
let net_driver = RouterDriver(Arc::new(Mutex::new(Router { buffer: [Vec::new(), Vec::new()] })), i);
|
|
|
|
|
|
|
|
|
|
let ip_addrs = [
|
|
|
|
|
IpCidr::new(IpAddress::v4(10, 0, 0, 1), 24),
|
|
|
|
|
IpCidr::new(IpAddress::v4(10, 0, 1, 1), 24),
|
|
|
|
|
IpCidr::new(IpAddress::v4(10, 0, i, 1), 24),
|
|
|
|
|
];
|
|
|
|
|
let neighbor_cache = NeighborCache::new(BTreeMap::new());
|
|
|
|
|
let routes = Routes::new(BTreeMap::new());
|
|
|
|
@ -208,7 +228,7 @@ pub fn router_init() -> Arc<RouterInterface> {
|
|
|
|
|
.routes(routes)
|
|
|
|
|
.finalize();
|
|
|
|
|
|
|
|
|
|
info!("router interface up");
|
|
|
|
|
info!("router interface up #{}", i);
|
|
|
|
|
|
|
|
|
|
let router_iface = RouterInterface {
|
|
|
|
|
iface: Mutex::new(iface),
|
|
|
|
@ -218,11 +238,10 @@ pub fn router_init() -> Arc<RouterInterface> {
|
|
|
|
|
let driver = Arc::new(router_iface);
|
|
|
|
|
DRIVERS.write().push(driver.clone());
|
|
|
|
|
NET_DRIVERS.write().push(driver.clone());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Enable Receive Complete Interrupt
|
|
|
|
|
unsafe {
|
|
|
|
|
AXI_STREAM_FIFO_IER.write_volatile(1 << 26);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
driver
|
|
|
|
|
}
|
|
|
|
|