Initial rcore router device support

master
Jiajie Chen 6 years ago
parent ef9a038ef5
commit 5932372750

@ -100,6 +100,13 @@
compatible = "xlnx,xps-intc-1.00.a"; compatible = "xlnx,xps-intc-1.00.a";
reg = <0x61200000 0x1000>; reg = <0x61200000 0x1000>;
interrupt-parent = <&L10>; interrupt-parent = <&L10>;
interrupts = <0>;
};
router: router@64A00000 {
compatible = "rcore,router";
reg = <0x64A00000 0x1000>;
interrupt-parent = <&L10>;
interrupts = <1>; interrupts = <1>;
}; };
}; };

@ -1,19 +1,22 @@
use super::consts::KERNEL_OFFSET; use super::consts::KERNEL_OFFSET;
use crate::memory::active_table;
use rcore_memory::paging::PageTable;
/// Mask all external interrupt except serial. /// Mask all external interrupt except serial.
pub unsafe fn init_external_interrupt() { pub unsafe fn init_external_interrupt() {
const HART0_S_MODE_INTERRUPT_ENABLES: *mut u64 = (KERNEL_OFFSET + 0x0C00_2080) as *mut u64; const HART0_S_MODE_INTERRUPT_ENABLES: *mut u64 = (KERNEL_OFFSET + 0x0C00_2080) as *mut u64;
// enable all external interrupts
HART0_S_MODE_INTERRUPT_ENABLES.write_volatile(0xf); HART0_S_MODE_INTERRUPT_ENABLES.write_volatile(0xf);
// mask interrupts first // mask interrupts first
const AXI_INTC_IER: *mut u32 = (KERNEL_OFFSET + 0x1900_0008) as *mut u32; const AXI_INTC_IER: *mut u32 = (KERNEL_OFFSET + 0x1810_0008) as *mut u32;
AXI_INTC_IER.write_volatile(0x0); AXI_INTC_IER.write_volatile(0x0);
// acknowledge all interrupts // acknowledge all interrupts
const AXI_INTC_IAR: *mut u32 = (KERNEL_OFFSET + 0x1900_000C) as *mut u32; const AXI_INTC_IAR: *mut u32 = (KERNEL_OFFSET + 0x1810_000C) as *mut u32;
AXI_INTC_IAR.write_volatile(0xffffffff); AXI_INTC_IAR.write_volatile(0xffffffff);
const AXI_INTC_MER: *mut u32 = (KERNEL_OFFSET + 0x1900_001C) as *mut u32; const AXI_INTC_MER: *mut u32 = (KERNEL_OFFSET + 0x1810_001C) as *mut u32;
// Hardware Interrupt enable | Enable irq output // Hardware Interrupt enable | Enable irq output
AXI_INTC_MER.write_volatile(0b11); AXI_INTC_MER.write_volatile(0b11);
@ -32,7 +35,7 @@ pub unsafe fn handle_external_interrupt() {
HART0_S_MODE_INTERRUPT_CLAIM_COMPLETE.write_volatile(source); HART0_S_MODE_INTERRUPT_CLAIM_COMPLETE.write_volatile(source);
// acknowledge all interrupts // acknowledge all interrupts
const AXI_INTC_IAR: *mut u32 = (KERNEL_OFFSET + 0x1900_000C) as *mut u32; const AXI_INTC_IAR: *mut u32 = (KERNEL_OFFSET + 0x1810_000C) as *mut u32;
AXI_INTC_IAR.write_volatile(0xffffffff); AXI_INTC_IAR.write_volatile(0xffffffff);
} }
@ -42,4 +45,4 @@ pub unsafe fn enable_serial_interrupt() {
// Intr enable | rx reset | tx reset // Intr enable | rx reset | tx reset
const UART_IE: u32 = 0x13; const UART_IE: u32 = 0x13;
SERIAL_BASE.add(UART_CTRL_REG).write_volatile(UART_IE); SERIAL_BASE.add(UART_CTRL_REG).write_volatile(UART_IE);
} }

@ -154,12 +154,21 @@ fn remap_the_kernel(dtb: usize) {
// map AXI INTC for Rocket Chip // map AXI INTC for Rocket Chip
#[cfg(feature = "board_rocket_chip")] #[cfg(feature = "board_rocket_chip")]
ms.push( ms.push(
KERNEL_OFFSET + 0x19000000, KERNEL_OFFSET + 0x18100000,
KERNEL_OFFSET + 0x19000000 + PAGE_SIZE, KERNEL_OFFSET + 0x18100000 + PAGE_SIZE,
MemoryAttr::default(), MemoryAttr::default(),
Linear::new(-(KERNEL_OFFSET as isize + 0x19000000 - 0x61200000)), Linear::new(-(KERNEL_OFFSET as isize + 0x18100000 - 0x61200000)),
"axi_intc", "axi_intc",
); );
// map AXI4-Stream Data FIFO for Rocket Chip
#[cfg(feature = "board_rocket_chip")]
ms.push(
KERNEL_OFFSET + 0x18200000,
KERNEL_OFFSET + 0x18200000 + PAGE_SIZE,
MemoryAttr::default(),
Linear::new(-(KERNEL_OFFSET as isize + 0x18200000 - 0x64A00000)),
"router",
);
unsafe { unsafe {
ms.activate(); ms.activate();
} }

@ -4,6 +4,7 @@ use core::slice;
use device_tree::{DeviceTree, Node}; use device_tree::{DeviceTree, Node};
use super::bus::virtio_mmio::virtio_probe; use super::bus::virtio_mmio::virtio_probe;
use super::net::router::router_init;
use super::CMDLINE; use super::CMDLINE;
const DEVICE_TREE_MAGIC: u32 = 0xd00dfeed; const DEVICE_TREE_MAGIC: u32 = 0xd00dfeed;
@ -14,6 +15,9 @@ fn walk_dt_node(dt: &Node) {
if compatible == "virtio,mmio" { if compatible == "virtio,mmio" {
virtio_probe(dt); virtio_probe(dt);
} }
if compatible == "rcore,router" {
router_init();
}
// TODO: initial other devices (16650, etc.) // TODO: initial other devices (16650, etc.)
} }
if let Ok(bootargs) = dt.prop_str("bootargs") { if let Ok(bootargs) = dt.prop_str("bootargs") {

@ -1,3 +1,4 @@
pub mod e1000; pub mod e1000;
pub mod ixgbe; pub mod ixgbe;
pub mod virtio_net; pub mod virtio_net;
pub mod router;

@ -0,0 +1,198 @@
//! 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 rcore_memory::PAGE_SIZE;
use crate::drivers::provider::Provider;
use crate::net::SOCKETS;
use crate::sync::SpinNoIrqLock as Mutex;
use super::super::{DeviceType, Driver, DRIVERS, NET_DRIVERS, SOCKET_ACTIVITY};
use crate::consts::{KERNEL_OFFSET, MEMORY_END, MEMORY_OFFSET};
const AXI_STREAM_FIFO_ISR: *mut u32 = (KERNEL_OFFSET + 0x1820_0000) as *mut u32;
const AXI_STREAM_FIFO_IER: *mut u32 = (KERNEL_OFFSET + 0x1820_0004) as *mut u32;
const AXI_STREAM_FIFO_RDFR: *mut u32 = (KERNEL_OFFSET + 0x1820_0018) as *mut u32;
const AXI_STREAM_FIFO_RDFO: *mut u32 = (KERNEL_OFFSET + 0x1820_001C) as *mut u32;
const AXI_STREAM_FIFO_RDFD: *mut u32 = (KERNEL_OFFSET + 0x1820_0020) as *mut u32;
const AXI_STREAM_FIFO_RLR: *mut u32 = (KERNEL_OFFSET + 0x1820_0024) as *mut u32;
const AXI_STREAM_FIFO_RDR: *mut u32 = (KERNEL_OFFSET + 0x1820_0030) as *mut u32;
pub struct Router {
buffer: Vec<Vec<u8>>
}
impl Router {
fn transmit_available(&self) -> bool {
false
}
fn receive_available(&self) -> bool {
false
}
}
#[derive(Clone)]
pub struct RouterDriver(Arc<Mutex<Router>>);
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() {
// potential racing
Some((
RouterRxToken(self.clone()),
RouterTxToken(self.clone()),
))
} else {
None
}
}
fn transmit(&'a mut self) -> Option<Self::TxToken> {
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<R, F>(self, _timestamp: Instant, f: F) -> Result<R>
where
F: FnOnce(&[u8]) -> Result<R>,
{
unimplemented!()
}
}
impl phy::TxToken for RouterTxToken {
fn consume<R, F>(self, _timestamp: Instant, len: usize, f: F) -> Result<R>
where
F: FnOnce(&mut [u8]) -> Result<R>,
{
unimplemented!()
}
}
pub struct RouterInterface {
iface: Mutex<EthernetInterface<'static, 'static, 'static, RouterDriver>>,
driver: RouterDriver,
}
impl Driver for RouterInterface {
fn try_handle_interrupt(&self, _irq: Option<u32>) -> bool {
let mut driver = self.driver.0.lock();
let isr = unsafe {
AXI_STREAM_FIFO_ISR.read_volatile()
};
if isr > 0 {
info!("handle router interrupt {:b}", 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();
for i in 0..rdfo {
buffer.push(AXI_STREAM_FIFO_RDFD.read_volatile() as u8);
}
info!("got packet of length {}", rdfo);
driver.buffer.push(buffer);
}
}
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<Ipv4Address> {
unimplemented!()
}
fn poll(&self) {
unimplemented!()
}
}
pub fn router_init(
) -> Arc<RouterInterface> {
let ethernet_addr = EthernetAddress::from_bytes(&[2, 2, 3, 3, 0, 0]);
let net_driver = RouterDriver(Arc::new(Mutex::new(Router {
buffer: Vec::new()
})));
let ip_addrs = [IpCidr::new(IpAddress::v4(10, 0, 0, 1), 24), IpCidr::new(IpAddress::v4(10, 0, 1, 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");
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());
const AXI_STREAM_FIFO_IER: *mut u32 = (KERNEL_OFFSET + 0x1820_0004) as *mut u32;
// Enable Receive Complete Interrupt
unsafe {
AXI_STREAM_FIFO_IER.write_volatile(1 << 26);
}
driver
}
Loading…
Cancel
Save