//! rCore Router Driver use alloc::collections::BTreeMap; use alloc::string::String; use alloc::sync::Arc; use alloc::vec::Vec; use smoltcp::iface::*; use smoltcp::phy::{self, DeviceCapabilities}; use smoltcp::time::Instant; use smoltcp::wire::*; use smoltcp::Result; use bitflags::*; use crate::net::SOCKETS; use crate::sync::SpinNoIrqLock as Mutex; use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY}; use crate::memory::phys_to_virt; const AXI_STREAM_FIFO_ISR: *mut u32 = phys_to_virt(0x64A0_0000) as *mut u32; const AXI_STREAM_FIFO_IER: *mut u32 = phys_to_virt(0x64A0_0004) as *mut u32; const AXI_STREAM_FIFO_TDFR: *mut u32 = phys_to_virt(0x64A0_0008) as *mut u32; const AXI_STREAM_FIFO_TDFD: *mut u32 = phys_to_virt(0x64A0_0010) as *mut u32; const AXI_STREAM_FIFO_TLR: *mut u32 = phys_to_virt(0x64A0_0014) as *mut u32; const AXI_STREAM_FIFO_RDFR: *mut u32 = phys_to_virt(0x64A0_0018) as *mut u32; const AXI_STREAM_FIFO_RDFO: *mut u32 = phys_to_virt(0x64A0_001C) as *mut u32; const AXI_STREAM_FIFO_RDFD: *mut u32 = phys_to_virt(0x64A0_0020) as *mut u32; 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>; ENABLED_PORTS as usize], } impl Router { fn transmit_available(&self) -> bool { true } fn receive_available(&self, port: u8) -> bool { self.buffer[port as usize].len() > 0 } } #[derive(Clone)] pub struct RouterDriver(Arc>, u8); pub struct RouterRxToken(RouterDriver); pub struct RouterTxToken(RouterDriver); impl<'a> phy::Device<'a> for RouterDriver { type RxToken = RouterRxToken; type TxToken = RouterTxToken; fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> { let driver = self.0.lock(); if driver.transmit_available() && driver.receive_available(self.1) { // potential racing Some((RouterRxToken(self.clone()), RouterTxToken(self.clone()))) } else { None } } fn transmit(&'a mut self) -> Option { let driver = self.0.lock(); if driver.transmit_available() { Some(RouterTxToken(self.clone())) } else { None } } fn capabilities(&self) -> DeviceCapabilities { let mut caps = DeviceCapabilities::default(); caps.max_transmission_unit = 1536; caps.max_burst_size = Some(1); caps } } impl phy::RxToken for RouterRxToken { fn consume(self, _timestamp: Instant, f: F) -> Result where F: FnOnce(&[u8]) -> Result, { let mut router = (self.0).0.lock(); let buffer = router.buffer[(self.0).1 as usize].pop().unwrap(); f(&buffer) } } impl phy::TxToken for RouterTxToken { fn consume(self, _timestamp: Instant, len: usize, f: F) -> Result where F: FnOnce(&mut [u8]) -> Result, { let mut buffer = vec![0; len]; let res = f(&mut buffer); debug!("out buf {}", len); 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 + 1) * 4) as u32); } res } } pub struct RouterInterface { iface: Mutex>, driver: RouterDriver, } impl Driver for RouterInterface { fn try_handle_interrupt(&self, _irq: Option) -> bool { let mut driver = self.driver.0.lock(); let isr = unsafe { AXI_STREAM_FIFO_ISR.read_volatile() }; if isr > 0 { debug!("handle router interrupt {:?}", AXIStreamFifoInterrupt::from_bits_truncate(isr)); unsafe { AXI_STREAM_FIFO_ISR.write(isr); let rdfo = AXI_STREAM_FIFO_RDFO.read_volatile(); if rdfo > 0 { let mut buffer = Vec::new(); let rlr = AXI_STREAM_FIFO_RLR.read_volatile(); let rdr = AXI_STREAM_FIFO_RDR.read_volatile(); 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 {} port {}", rdfo, port); driver.buffer[port as usize].push(buffer); } drop(driver); let timestamp = Instant::from_millis(crate::trap::uptime_msec() as i64); let mut sockets = SOCKETS.lock(); match self.iface.lock().poll(&mut sockets, timestamp) { Ok(_) => { SOCKET_ACTIVITY.notify_all(); } Err(err) => { debug!("poll got err {}", err); } } } return true; } return false; } fn device_type(&self) -> DeviceType { DeviceType::Net } fn get_id(&self) -> String { format!("router") } fn get_mac(&self) -> EthernetAddress { unimplemented!() } fn get_ifname(&self) -> String { format!("router") } fn ipv4_address(&self) -> Option { unimplemented!() } fn poll(&self) { unimplemented!() } } pub fn router_init() { unsafe { // reset tx fifo AXI_STREAM_FIFO_TDFR.write_volatile(0xA5); // reset rx fifo AXI_STREAM_FIFO_RDFR.write_volatile(0xA5); } 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(), Vec::new()] })), i); let ip_addrs = [ IpCidr::new(IpAddress::v4(10, 0, i, 1), 24), ]; let neighbor_cache = NeighborCache::new(BTreeMap::new()); let routes = Routes::new(BTreeMap::new()); let iface = EthernetInterfaceBuilder::new(net_driver.clone()) .ethernet_addr(ethernet_addr) .ip_addrs(ip_addrs) .neighbor_cache(neighbor_cache) .routes(routes) .finalize(); info!("router interface up #{}", i); let router_iface = RouterInterface { iface: Mutex::new(iface), driver: net_driver, }; 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); } }