diff --git a/src/eth/mod.rs b/src/eth/mod.rs new file mode 100644 index 00000000..910da875 --- /dev/null +++ b/src/eth/mod.rs @@ -0,0 +1,84 @@ +use crate::regs::*; + +mod regs; + +pub struct Eth { + regs: &'static regs::RegisterBlock, +} + +impl Eth { + pub fn gem0() -> Self { + let regs = unsafe { regs::RegisterBlock::gem0() }; + Eth { regs }.init() + } + + pub fn gem1() -> Self { + let regs = unsafe { regs::RegisterBlock::gem1() }; + Eth { regs }.init() + } + + fn init(self) -> Self { + // Clear the Network Control register. + self.regs.net_ctrl.write(regs::NetCtrl::zeroed()); + self.regs.net_ctrl.write(regs::NetCtrl::zeroed().clear_stat_regs(true)); + // Clear the Status registers. + self.regs.rx_status.write( + regs::RxStatus::zeroed() + .buffer_not_avail(true) + .frame_recd(true) + .rx_overrun(true) + .hresp_not_ok(true) + ); + self.regs.tx_status.write( + regs::TxStatus::zeroed() + .used_bit_read(true) + .collision(true) + .retry_limit_exceeded(true) + .tx_go(true) + .tx_corr_ahb_err(true) + .tx_complete(true) + .tx_under_run(true) + .late_collision(true) + .hresp_not_ok(true) + ); + // Disable all interrupts. + self.regs.intr_dis.write( + regs::IntrDis::zeroed() + .mgmt_done(true) + .rx_complete(true) + .rx_used_read(true) + .tx_used_read(true) + .tx_underrun(true) + .retry_ex_late_collisn(true) + .tx_corrupt_ahb_err(true) + .tx_complete(true) + .link_chng(true) + .rx_overrun(true) + .hresp_not_ok(true) + .pause_nonzeroq(true) + .pause_zero(true) + .pause_tx(true) + .ex_intr(true) + .autoneg_complete(true) + .partner_pg_rx(true) + .delay_req_rx(true) + .sync_rx(true) + .delay_req_tx(true) + .sync_tx(true) + .pdelay_req_rx(true) + .pdelay_resp_rx(true) + .pdelay_req_tx(true) + .pdelay_resp_tx(true) + .tsu_sec_incr(true) + ); + // Clear the buffer queues. + self.regs.rx_qbar.write( + regs::RxQbar::zeroed() + ); + self.regs.tx_qbar.write( + regs::TxQbar::zeroed() + ); + + self + } +} diff --git a/src/eth/regs.rs b/src/eth/regs.rs new file mode 100644 index 00000000..8de487e0 --- /dev/null +++ b/src/eth/regs.rs @@ -0,0 +1,176 @@ +use volatile_register::{RO, WO, RW}; + +use crate::{register, register_bit, register_bits, regs::*}; + +#[repr(C)] +pub struct RegisterBlock { + pub net_ctrl: NetCtrl, + pub net_cfg: RW, + pub net_status: RO, + pub unused0: RO, + pub dma_cfg: RW, + pub tx_status: TxStatus, + pub rx_qbar: RxQbar, + pub tx_qbar: TxQbar, + pub rx_status: RxStatus, + pub intr_status: RW, + pub intr_en: WO, + pub intr_dis: IntrDis, + pub intr_mask: RW, + pub phy_maint: RW, + pub rx_pauseq: RO, + pub tx_pauseq: RW, + pub unused1: [RO; 16], + pub hash_bot: RW, + pub hash_top: RW, + pub spec_addr1_bot: RW, + pub spec_addr1_top: RW, + pub spec_addr2_bot: RW, + pub spec_addr2_top: RW, + pub spec_addr3_bot: RW, + pub spec_addr3_top: RW, + pub spec_addr4_bot: RW, + pub spec_addr4_top: RW, + pub type_id_match1: RW, + pub type_id_match2: RW, + pub type_id_match3: RW, + pub type_id_match4: RW, + pub wake_on_lan: RW, + pub ipg_stretch: RW, + pub stacked_vlan: RW, + pub tx_pfc_pause: RW, + pub spec_addr1_mask_bot: RW, + pub spec_addr1_mask_top: RW, + pub unused2: [RO; 11], + pub module_id: RO, + pub octets_tx_bot: RO, + pub octets_tx_top: RO, + pub frames_tx: RO, + pub broadcast_frames_tx: RO, + pub multi_frames_tx: RO, + pub pause_frames_tx: RO, + pub frames_64b_tx: RO, + pub frames_65to127b_tx: RO, + pub frames_128to255b_tx: RO, + pub frames_256to511b_tx: RO, + pub frames_512to1023b_tx: RO, + pub frames_1024to1518b_tx: RO, + pub tx_under_runs: RO, + pub unused3: RO, + pub single_collisn_frames: RO, + pub multi_collisn_frames: RO, + pub excessive_collisns: RO, + pub late_collisns: RO, + pub deferred_tx_frames: RO, + pub carrier_sense_errs: RO, + pub octets_rx_bot: RO, + pub octets_rx_top: RO, + pub frames_rx: RO, + pub bdcast_fames_rx: RO, + pub multi_frames_rx: RO, + pub pause_rx: RO, + pub frames_64b_rx: RO, + pub frames_65to127b_rx: RO, + pub frames_128to255b_rx: RO, + pub frames_256to511b_rx: RO, + pub frames_512to1023b_rx: RO, + pub frames_1024to1518b_rx: RO, + pub unused4: RO, + pub undersz_rx: RO, + pub oversz_rx: RO, + pub jab_rx: RO, + pub fcs_errors: RO, + pub length_field_errors: RO, + pub rx_symbol_errors: RO, + pub align_errors: RO, + pub rx_resource_errors: RO, + pub rx_overrun_errors: RO, + pub ip_hdr_csum_errors: RO, + pub tcp_csum_errors: RO, + pub udp_csum_errors: RO, + pub unused5: [RO; 5], + pub timer_strobe_s: RW, + pub timer_strobe_ns: RW, + pub timer_s: RW, + pub timer_ns: RW, + pub timer_adjust: RW, + pub timer_incr: RW, + pub ptp_tx_s: RO, + pub ptp_tx_ns: RO, + pub ptp_rx_s: RO, + pub ptp_rx_ns: RO, + pub ptp_peer_tx_s: RO, + pub ptp_peer_tx_ns: RO, + pub ptp_peer_rx_s: RO, + pub ptp_peer_rx_ns: RO, + pub unused6: [RO; 33], + pub design_cfg2: RO, + pub design_cfg3: RO, + pub design_cfg4: RO, + pub design_cfg5: RO, +} + +impl RegisterBlock { + const GEM0: *mut Self = 0xE000B000 as *mut _; + const GEM1: *mut Self = 0xE000C000 as *mut _; + + pub fn gem0() -> &'static mut Self { + unsafe { &mut *Self::GEM0 } + } + + pub fn gem1() -> &'static mut Self { + unsafe { &mut *Self::GEM1 } + } +} + +register!(net_ctrl, NetCtrl, RW, u32); +register_bit!(net_ctrl, clear_stat_regs, 5); + +register!(tx_status, TxStatus, RW, u32); +register_bit!(tx_status, used_bit_read, 0); +register_bit!(tx_status, collision, 1); +register_bit!(tx_status, retry_limit_exceeded, 2); +register_bit!(tx_status, tx_go, 3); +register_bit!(tx_status, tx_corr_ahb_err, 4); +register_bit!(tx_status, tx_complete, 5); +register_bit!(tx_status, tx_under_run, 6); +register_bit!(tx_status, late_collision, 7); +register_bit!(tx_status, hresp_not_ok, 8); + +register!(rx_status, RxStatus, RW, u32); +register_bit!(rx_status, buffer_not_avail, 0); +register_bit!(rx_status, frame_recd, 1); +register_bit!(rx_status, rx_overrun, 2); +register_bit!(rx_status, hresp_not_ok, 3); + +register!(rx_qbar, RxQbar, RW, u32); + +register!(tx_qbar, TxQbar, RW, u32); + +register!(intr_dis, IntrDis, WO, u32); +register_bit!(intr_dis, mgmt_done, 0); +register_bit!(intr_dis, rx_complete, 1); +register_bit!(intr_dis, rx_used_read, 2); +register_bit!(intr_dis, tx_used_read, 3); +register_bit!(intr_dis, tx_underrun, 4); +register_bit!(intr_dis, retry_ex_late_collisn, 5); +register_bit!(intr_dis, tx_corrupt_ahb_err, 6); +register_bit!(intr_dis, tx_complete, 7); +register_bit!(intr_dis, link_chng, 9); +register_bit!(intr_dis, rx_overrun, 10); +register_bit!(intr_dis, hresp_not_ok, 11); +register_bit!(intr_dis, pause_nonzeroq, 12); +register_bit!(intr_dis, pause_zero, 13); +register_bit!(intr_dis, pause_tx, 14); +register_bit!(intr_dis, ex_intr, 15); +register_bit!(intr_dis, autoneg_complete, 16); +register_bit!(intr_dis, partner_pg_rx, 17); +register_bit!(intr_dis, delay_req_rx, 18); +register_bit!(intr_dis, sync_rx, 19); +register_bit!(intr_dis, delay_req_tx, 20); +register_bit!(intr_dis, sync_tx, 21); +register_bit!(intr_dis, pdelay_req_rx, 22); +register_bit!(intr_dis, pdelay_resp_rx, 23); +register_bit!(intr_dis, pdelay_req_tx, 24); +register_bit!(intr_dis, pdelay_resp_tx, 25); +register_bit!(intr_dis, tsu_sec_incr, 26); diff --git a/src/main.rs b/src/main.rs index f2ea2124..5302a180 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ mod cortex_a9; mod slcr; mod uart; use uart::Uart; +mod eth; extern "C" { static mut __bss_start: u32; @@ -48,4 +49,8 @@ pub unsafe extern "C" fn _boot_cores() -> ! { fn main() { let mut uart = Uart::uart0(); writeln!(uart, "Hello World\r").unwrap(); + + let eth = eth::Eth::gem0(); + loop { + } }