eth: model rx/tx state with type parameters

This commit is contained in:
Astro 2019-06-09 20:10:41 +02:00
parent 74bd81f87f
commit f07a541c99
2 changed files with 54 additions and 16 deletions

View File

@ -3,15 +3,16 @@ use crate::slcr;
pub mod phy; pub mod phy;
mod regs; mod regs;
mod rx; pub mod rx;
mod tx; pub mod tx;
pub struct Eth<'rx> { pub struct Eth<RX, TX> {
regs: &'static mut regs::RegisterBlock, regs: &'static mut regs::RegisterBlock,
rx: Option<rx::DescList<'rx>>, rx: RX,
tx: TX,
} }
impl<'rx> Eth<'rx> { impl Eth<(), ()> {
pub fn default(macaddr: [u8; 6]) -> Self { pub fn default(macaddr: [u8; 6]) -> Self {
slcr::RegisterBlock::unlocked(|slcr| { slcr::RegisterBlock::unlocked(|slcr| {
// MDIO // MDIO
@ -140,20 +141,42 @@ impl<'rx> Eth<'rx> {
}); });
let regs = regs::RegisterBlock::gem0(); let regs = regs::RegisterBlock::gem0();
let rx = None; Self::from_regs(regs, macaddr)
let mut eth = Eth { regs, rx }.init();
eth.configure(macaddr);
eth
} }
pub fn gem1(macaddr: [u8; 6]) -> Self { pub fn gem1(macaddr: [u8; 6]) -> Self {
slcr::RegisterBlock::unlocked(|slcr| {
// Enable gem1 ref clock
slcr.gem1_rclk_ctrl.write(
slcr::RclkCtrl::zeroed()
.clkact(true)
);
// 0x0050_0801: 8, 5: 100 Mb/s
slcr.gem1_clk_ctrl.write(
slcr::ClkCtrl::zeroed()
.clkact(true)
.srcsel(slcr::PllSource::IoPll)
.divisor(8)
.divisor1(5)
);
});
let regs = regs::RegisterBlock::gem1(); let regs = regs::RegisterBlock::gem1();
let rx = None; Self::from_regs(regs, macaddr)
let mut eth = Eth { regs, rx }.init(); }
fn from_regs(regs: &'static mut regs::RegisterBlock, macaddr: [u8; 6]) -> Self {
let mut eth = Eth {
regs,
rx: (),
tx: (),
}.init();
eth.configure(macaddr); eth.configure(macaddr);
eth eth
} }
}
impl<RX, TX> Eth<RX, TX> {
fn init(mut self) -> Self { fn init(mut self) -> Self {
// Clear the Network Control register. // Clear the Network Control register.
self.regs.net_ctrl.write(regs::NetCtrl::zeroed()); self.regs.net_ctrl.write(regs::NetCtrl::zeroed());
@ -274,14 +297,19 @@ impl<'rx> Eth<'rx> {
); );
} }
pub fn start_rx(&mut self, rx_buffers: [&'rx mut [u8]; rx::DESCS]) { pub fn start_rx<'rx>(self, rx_buffers: [&'rx mut [u8]; rx::DESCS]) -> Eth<rx::DescList<'rx>, TX> {
self.rx = Some(rx::DescList::new(rx_buffers)); let new_self = Eth {
let list_addr = self.rx.as_ref().unwrap() as *const _ as u32; regs: self.regs,
rx: rx::DescList::new(rx_buffers),
tx: self.tx,
};
let list_addr = &new_self.rx as *const _ as u32;
assert!(list_addr & 0b11 == 0); assert!(list_addr & 0b11 == 0);
self.regs.rx_qbar.write( new_self.regs.rx_qbar.write(
regs::RxQbar::zeroed() regs::RxQbar::zeroed()
.rx_q_baseaddr(list_addr >> 2) .rx_q_baseaddr(list_addr >> 2)
); );
new_self
} }
fn wait_phy_idle(&self) { fn wait_phy_idle(&self) {
@ -289,7 +317,7 @@ impl<'rx> Eth<'rx> {
} }
} }
impl<'rx> phy::PhyAccess for Eth<'rx> { impl<RX, TX> phy::PhyAccess for Eth<RX, TX> {
fn read_phy(&mut self, addr: u8, reg: u8) -> u16 { fn read_phy(&mut self, addr: u8, reg: u8) -> u16 {
self.wait_phy_idle(); self.wait_phy_idle();
self.regs.phy_maint.write( self.regs.phy_maint.write(

View File

@ -6,6 +6,7 @@
#![feature(compiler_builtins_lib)] #![feature(compiler_builtins_lib)]
use core::fmt::Write; use core::fmt::Write;
use core::mem::uninitialized;
use r0::zero_bss; use r0::zero_bss;
use compiler_builtins as _; use compiler_builtins as _;
@ -92,6 +93,15 @@ fn main() {
} }
while !uart.tx_fifo_empty() {} while !uart.tx_fifo_empty() {}
let mut rx_buffers = [[0u8; 1536]; eth::rx::DESCS];
let mut rx_buffer_ptrs: [&mut [u8]; eth::rx::DESCS] = unsafe {
uninitialized()
};
for (i, (ptr, buf)) in rx_buffer_ptrs.iter_mut().zip(rx_buffers.iter_mut()).enumerate() {
*ptr = buf;
}
let mut eth = eth.start_rx(rx_buffer_ptrs);
loop {} loop {}
panic!("End"); panic!("End");
} }