start adding smoltcp/ethernet support
This commit is contained in:
parent
61ffe06343
commit
b8fdf1008b
@ -10,13 +10,13 @@ use embedded_hal::{delay::DelayNs, digital::StatefulOutputPin};
|
||||
use embedded_io::Write;
|
||||
use log::{error, info, warn};
|
||||
use zynq7000_hal::{
|
||||
BootMode,
|
||||
clocks::Clocks,
|
||||
gic::{GicConfigurator, GicInterruptHelper, Interrupt},
|
||||
gpio::{mio, Flex, Output, PinState},
|
||||
gpio::{Flex, Output, PinState, mio},
|
||||
gtc::Gtc,
|
||||
time::Hertz,
|
||||
uart::{ClkConfigRaw, Uart, UartConfig},
|
||||
BootMode,
|
||||
};
|
||||
|
||||
use zynq7000::PsPeripherals;
|
||||
|
@ -14,6 +14,7 @@ categories = ["embedded", "no-std", "hardware-support"]
|
||||
cortex-ar = { git = "https://github.com/rust-embedded/cortex-ar", branch = "main" }
|
||||
zynq7000 = { path = "../zynq7000" }
|
||||
|
||||
bitbybit = "1.3"
|
||||
arbitrary-int = "1.3"
|
||||
thiserror = { version = "2", default-features = false }
|
||||
num_enum = { version = "0.7", default-features = false }
|
||||
|
72
zynq7000-hal/src/eth/mod.rs
Normal file
72
zynq7000-hal/src/eth/mod.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use arbitrary_int::{u2, u3, u13, u30};
|
||||
|
||||
/// RX buffer descriptor.
|
||||
///
|
||||
/// The user should declare an array of this structure inside uncached memory.
|
||||
///
|
||||
/// These descriptors are shared between software and hardware and contain information
|
||||
/// related to frame reception.
|
||||
pub struct RxBufDescr {
|
||||
/// The first word of the descriptor.
|
||||
pub word0: RxBufDescrWord0,
|
||||
/// The second word of the descriptor.
|
||||
pub word1: RxBufDescrWord1,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Ownership {
|
||||
Hardware = 0,
|
||||
Software = 1,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct RxBufDescrWord0 {
|
||||
/// The full reception address with the last two bits cleared.
|
||||
#[bits(2..=31, rw)]
|
||||
addr: u30,
|
||||
#[bit(1, rw)]
|
||||
wrap: bool,
|
||||
#[bit(1, rw)]
|
||||
ownership: Ownership,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct RxBufDescrWord1 {
|
||||
#[bit(31, r)]
|
||||
broadcast_detect: bool,
|
||||
#[bit(30, r)]
|
||||
multicast_hash: bool,
|
||||
#[bit(29, r)]
|
||||
unicast_hash: bool,
|
||||
#[bit(27, r)]
|
||||
specific_addr_match: bool,
|
||||
/// Specifies which of the 4 specific address registers was matched.
|
||||
#[bits(25..=26, r)]
|
||||
specific_addr_match_info: u2,
|
||||
#[bit(24, r)]
|
||||
type_id_match_or_snap_info: bool,
|
||||
#[bits(22..=23, r)]
|
||||
type_id_match_info_or_chksum_status: u2,
|
||||
#[bit(21, r)]
|
||||
vlan_tag_detected: bool,
|
||||
#[bit(20, r)]
|
||||
priority_tag_detected: bool,
|
||||
#[bits(17..=19, r)]
|
||||
vlan_prio: u3,
|
||||
#[bit(16, r)]
|
||||
cfi_bit: bool,
|
||||
#[bit(15, r)]
|
||||
end_of_frame: bool,
|
||||
#[bit(14, r)]
|
||||
start_of_frame: bool,
|
||||
/// Relevant when FCS errors are not ignored.
|
||||
/// 0: Frame has good FCS, 1: Frame has bad FCS, but was copied to memory as the ignore FCS
|
||||
/// functionality was enabled.
|
||||
#[bit(13, r)]
|
||||
fcs_status: bool,
|
||||
#[bits(0..=12, r)]
|
||||
rx_len: u13,
|
||||
}
|
@ -4,7 +4,7 @@ use zynq7000::gpio::{Gpio, MaskedOutput, MmioGpio};
|
||||
|
||||
use crate::slcr::Slcr;
|
||||
|
||||
use super::{mio::MuxConf, PinIsOutputOnly};
|
||||
use super::{PinIsOutputOnly, mio::MuxConf};
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum PinOffset {
|
||||
|
@ -172,7 +172,8 @@ impl Flex {
|
||||
|
||||
pub fn configure_as_output_open_drain(&mut self, level: PinState, with_internal_pullup: bool) {
|
||||
self.mode = PinMode::OutputOpenDrain;
|
||||
self.ll.configure_as_output_open_drain(level, with_internal_pullup);
|
||||
self.ll
|
||||
.configure_as_output_open_drain(level, with_internal_pullup);
|
||||
}
|
||||
|
||||
/// If the pin is configured as an input pin, this function does nothing.
|
||||
|
@ -13,6 +13,7 @@ use slcr::Slcr;
|
||||
use zynq7000::slcr::LevelShifterReg;
|
||||
|
||||
pub mod clocks;
|
||||
pub mod eth;
|
||||
pub mod gic;
|
||||
pub mod gpio;
|
||||
pub mod gtc;
|
||||
|
580
zynq7000/src/eth.rs
Normal file
580
zynq7000/src/eth.rs
Normal file
@ -0,0 +1,580 @@
|
||||
use arbitrary_int::{u2, u5};
|
||||
|
||||
pub const GEM_0_BASE_ADDR: usize = 0xE000_B000;
|
||||
pub const GEM_1_BASE_ADDR: usize = 0xE000_C000;
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug)]
|
||||
pub struct NetworkControl {
|
||||
#[bit(18, w)]
|
||||
flush_next_rx_dpram_pkt: bool,
|
||||
#[bit(17, w)]
|
||||
tx_pfc_pri_pause_frame: bool,
|
||||
#[bit(16, w)]
|
||||
enable_pfc_pri_pause_rx: bool,
|
||||
#[bit(12, w)]
|
||||
zero_pause_tx: bool,
|
||||
#[bit(11, w)]
|
||||
pause_tx: bool,
|
||||
#[bit(10, w)]
|
||||
stop_tx: bool,
|
||||
#[bit(9, w)]
|
||||
start_tx: bool,
|
||||
#[bit(8, rw)]
|
||||
back_pressure: bool,
|
||||
#[bit(7, rw)]
|
||||
statistics_write_enable: bool,
|
||||
#[bit(6, w)]
|
||||
increment_statistics: bool,
|
||||
#[bit(5, w)]
|
||||
clear_statistics: bool,
|
||||
#[bit(4, rw)]
|
||||
management_port_enable: bool,
|
||||
#[bit(3, rw)]
|
||||
tx_enable: bool,
|
||||
#[bit(2, rw)]
|
||||
rx_enable: bool,
|
||||
#[bit(1, rw)]
|
||||
loopback_local: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum SpeedMode {
|
||||
Low10Mbps = 0,
|
||||
High100Mbps = 1,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum PcsSelect {
|
||||
GmiiMii = 0,
|
||||
Tbi = 1,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u3, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum MdcClkDiv {
|
||||
Div8 = 0,
|
||||
Div16 = 1,
|
||||
Div32 = 2,
|
||||
Div48 = 3,
|
||||
Div64 = 4,
|
||||
Div96 = 5,
|
||||
Div128 = 6,
|
||||
Div224 = 7,
|
||||
}
|
||||
|
||||
impl MdcClkDiv {
|
||||
pub fn divisor(&self) -> usize {
|
||||
match self {
|
||||
MdcClkDiv::Div8 => 8,
|
||||
MdcClkDiv::Div16 => 16,
|
||||
MdcClkDiv::Div32 => 32,
|
||||
MdcClkDiv::Div48 => 48,
|
||||
MdcClkDiv::Div64 => 64,
|
||||
MdcClkDiv::Div96 => 96,
|
||||
MdcClkDiv::Div128 => 128,
|
||||
MdcClkDiv::Div224 => 224,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug)]
|
||||
pub struct NetworkConfig {
|
||||
#[bit(30, rw)]
|
||||
ignore_ipg_rx_error: bool,
|
||||
#[bit(29, rw)]
|
||||
allow_bad_preamble: bool,
|
||||
#[bit(28, rw)]
|
||||
ipg_stretch_enable: bool,
|
||||
#[bit(27, rw)]
|
||||
sgmii_enable: bool,
|
||||
#[bit(26, rw)]
|
||||
ignore_rx_fcs: bool,
|
||||
#[bit(25, rw)]
|
||||
half_duplex_rx_enable: bool,
|
||||
#[bit(24, rw)]
|
||||
rx_checksum_enable: bool,
|
||||
#[bit(23, rw)]
|
||||
disable_copy_pause_frames: bool,
|
||||
/// Zynq defines this as 0b00 for 32-bit AMBA AHB data bus width.
|
||||
#[bits(21..=22, r)]
|
||||
dbus_width: u2,
|
||||
#[bits(18..=20, rw)]
|
||||
mdc_clk_div: MdcClkDiv,
|
||||
#[bit(17, rw)]
|
||||
fcs_removal: bool,
|
||||
#[bit(16, rw)]
|
||||
length_field_error_discard: bool,
|
||||
#[bits(14..=15, rw)]
|
||||
rx_buf_offset: u2,
|
||||
#[bit(13, rw)]
|
||||
pause_enable: bool,
|
||||
#[bit(12, rw)]
|
||||
retry_test_enable: bool,
|
||||
#[bit(11, rw)]
|
||||
pcs_select: PcsSelect,
|
||||
#[bit(10, rw)]
|
||||
gigabit_enable: bool,
|
||||
#[bit(9, rw)]
|
||||
ext_addr_match_enable: bool,
|
||||
#[bit(8, rw)]
|
||||
rx_enable_1536: bool,
|
||||
#[bit(7, rw)]
|
||||
unicast_hash_enable: bool,
|
||||
#[bit(6, rw)]
|
||||
multicast_hash_enable: bool,
|
||||
#[bit(5, rw)]
|
||||
no_broadcast: bool,
|
||||
#[bit(4, rw)]
|
||||
copy_all_frames: bool,
|
||||
#[bit(2, rw)]
|
||||
discard_non_vlan: bool,
|
||||
#[bit(1, rw)]
|
||||
full_duplex: bool,
|
||||
#[bit(0, rw)]
|
||||
speed_mode: SpeedMode,
|
||||
}
|
||||
|
||||
/// PHY management status information.
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug)]
|
||||
pub struct NetworkStatus {
|
||||
#[bit(6, r)]
|
||||
pfc_pri_pause_neg: bool,
|
||||
#[bit(5, r)]
|
||||
pcs_autoneg_pause_tx_res: bool,
|
||||
#[bit(4, r)]
|
||||
pcs_autoneg_pause_rx_res: bool,
|
||||
#[bit(3, r)]
|
||||
pcs_autoneg_dup_res: bool,
|
||||
#[bit(2, r)]
|
||||
phy_mgmt_idle: bool,
|
||||
#[bit(1, r)]
|
||||
mdio_in: bool,
|
||||
#[bit(0, r)]
|
||||
pcs_link_state: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum BurstLength {
|
||||
Single,
|
||||
#[default]
|
||||
Incr4,
|
||||
Incr8,
|
||||
Incr16,
|
||||
}
|
||||
|
||||
impl BurstLength {
|
||||
pub const fn reg_value(&self) -> u5 {
|
||||
u5::new(match self {
|
||||
BurstLength::Single => 0b1,
|
||||
BurstLength::Incr4 => 0b100,
|
||||
BurstLength::Incr8 => 0b1000,
|
||||
BurstLength::Incr16 => 0b10000,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum AhbEndianess {
|
||||
Little = 0,
|
||||
Big = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct DmaRxBufSize(u8);
|
||||
|
||||
impl DmaRxBufSize {
|
||||
pub const fn new_with_raw_value(size: u8) -> Self {
|
||||
Self(size)
|
||||
}
|
||||
|
||||
pub const fn new(size: u8) -> Option<Self> {
|
||||
if size == 0 {
|
||||
return None;
|
||||
}
|
||||
Some(Self(size))
|
||||
}
|
||||
|
||||
pub const fn raw_value(&self) -> u8 {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub const fn size_in_bytes(&self) -> usize {
|
||||
self.0 as usize * 64
|
||||
}
|
||||
|
||||
pub const fn reg_value(&self) -> u8 {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug)]
|
||||
pub struct DmaConfig {
|
||||
#[bit(24, rw)]
|
||||
discard_when_ahb_full: bool,
|
||||
/// DMA receive buffer size in AHB system memory.
|
||||
#[bits(16..=23, rw)]
|
||||
dma_rx_ahb_buf_size_sel: DmaRxBufSize,
|
||||
#[bit(11, rw)]
|
||||
chksum_offload_enable: bool,
|
||||
/// Select size for packet buffer SRAM. Should be set to 1 to use the full configurable address
|
||||
/// space of 4 kB for the packet buffer.
|
||||
#[bit(10, rw)]
|
||||
tx_packet_buf_size_sel: bool,
|
||||
/// Select size for packet buffer SRAM. Should be set to 0b11 to use the full configurable
|
||||
/// address space of 8 kB for the packet buffer.
|
||||
#[bits(8..=9, rw)]
|
||||
rx_packet_buf_size_sel: u2,
|
||||
/// Default value is 0x1 (big endian)
|
||||
#[bit(7, rw)]
|
||||
endian_swap_packet_data: AhbEndianess,
|
||||
#[bit(6, rw)]
|
||||
endian_swap_mgmt_descriptor: AhbEndianess,
|
||||
#[bits(0..=4, rw)]
|
||||
burst_length: u5,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug)]
|
||||
pub struct TxStatus {
|
||||
#[bit(8, rw)]
|
||||
hresp_not_ok: bool,
|
||||
#[bit(7, rw)]
|
||||
late_collision: bool,
|
||||
#[bit(6, rw)]
|
||||
tx_underrun: bool,
|
||||
#[bit(5, rw)]
|
||||
tx_complete: bool,
|
||||
#[bit(4, rw)]
|
||||
tx_frame_corruption_ahb_error: bool,
|
||||
#[bit(3, r)]
|
||||
tx_go: bool,
|
||||
#[bit(2, rw)]
|
||||
retry_limit_reached: bool,
|
||||
#[bit(1, rw)]
|
||||
collision: bool,
|
||||
#[bit(0, rw)]
|
||||
read_when_used: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug)]
|
||||
pub struct RxStatus {
|
||||
#[bit(3, rw)]
|
||||
hresp_not_ok: bool,
|
||||
#[bit(2, rw)]
|
||||
rx_overrun: bool,
|
||||
#[bit(1, rw)]
|
||||
frame_received: bool,
|
||||
#[bit(0, rw)]
|
||||
buf_not_available: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug)]
|
||||
pub struct InterruptStatus {
|
||||
#[bit(26, rw)]
|
||||
tsu_sec_incr: bool,
|
||||
/// Marked N/A in datasheet.
|
||||
#[bit(17, rw)]
|
||||
partner_pg_rx: bool,
|
||||
/// Marked N/A in datasheet.
|
||||
#[bit(16, rw)]
|
||||
auto_negotiation_complete: bool,
|
||||
#[bit(15, rw)]
|
||||
external_interrupt: bool,
|
||||
#[bit(14, rw)]
|
||||
pause_transmitted: bool,
|
||||
#[bit(13, rw)]
|
||||
pause_time_zero: bool,
|
||||
#[bit(12, rw)]
|
||||
pause_with_non_zero_quantum: bool,
|
||||
#[bit(11, rw)]
|
||||
hresp_not_ok: bool,
|
||||
#[bit(10, rw)]
|
||||
rx_overrun: bool,
|
||||
/// Marked N/A in datasheet.
|
||||
#[bit(9, rw)]
|
||||
link_changed: bool,
|
||||
#[bit(7, r)]
|
||||
tx_complete: bool,
|
||||
/// Cleared on read.
|
||||
#[bit(6, r)]
|
||||
tx_frame_corruption_ahb_error: bool,
|
||||
#[bit(5, rw)]
|
||||
retry_limit_reached: bool,
|
||||
#[bit(3, rw)]
|
||||
tx_descr_read_when_used: bool,
|
||||
#[bit(2, rw)]
|
||||
rx_descr_read_when_used: bool,
|
||||
#[bit(1, rw)]
|
||||
frame_received: bool,
|
||||
#[bit(0, rw)]
|
||||
mgmt_frame_sent: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug)]
|
||||
pub struct InterruptControl {
|
||||
#[bit(26, w)]
|
||||
tsu_sec_incr: bool,
|
||||
/// Marked N/A in datasheet.
|
||||
#[bit(17, w)]
|
||||
partner_pg_rx: bool,
|
||||
/// Marked N/A in datasheet.
|
||||
#[bit(16, w)]
|
||||
auto_negotiation_complete: bool,
|
||||
#[bit(15, w)]
|
||||
external_interrupt: bool,
|
||||
#[bit(14, w)]
|
||||
pause_transmitted: bool,
|
||||
#[bit(13, w)]
|
||||
pause_time_zero: bool,
|
||||
#[bit(12, w)]
|
||||
pause_with_non_zero_quantum: bool,
|
||||
#[bit(11, w)]
|
||||
hresp_not_ok: bool,
|
||||
#[bit(10, w)]
|
||||
rx_overrun: bool,
|
||||
/// Marked N/A in datasheet.
|
||||
#[bit(9, w)]
|
||||
link_changed: bool,
|
||||
#[bit(7, w)]
|
||||
tx_complete: bool,
|
||||
/// Cleared on read.
|
||||
#[bit(6, w)]
|
||||
tx_frame_corruption_ahb_error: bool,
|
||||
#[bit(5, w)]
|
||||
retry_limit_reached: bool,
|
||||
#[bit(3, w)]
|
||||
tx_descr_read_when_used: bool,
|
||||
#[bit(2, w)]
|
||||
rx_descr_read_when_used: bool,
|
||||
#[bit(1, w)]
|
||||
frame_received: bool,
|
||||
#[bit(0, w)]
|
||||
mgmt_frame_sent: bool,
|
||||
}
|
||||
|
||||
#[bitbybit::bitenum(u2, exhaustive = false)]
|
||||
pub enum PhyOperation {
|
||||
Read = 0b10,
|
||||
Write = 0b01,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug)]
|
||||
pub struct PhyMaintenance {
|
||||
/// Must be 1 for Clause 22 operations.
|
||||
#[bit(30, rw)]
|
||||
clause_22: bool,
|
||||
#[bits(28..=29, rw)]
|
||||
op: Option<PhyOperation>,
|
||||
#[bits(23..=27, rw)]
|
||||
phy_addr: u5,
|
||||
#[bits(18..=22, rw)]
|
||||
reg_addr: u5,
|
||||
#[bits(16..=17, rw)]
|
||||
must_be_10: u2,
|
||||
#[bits(0..=15, rw)]
|
||||
data_mask: u16,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug)]
|
||||
pub struct PauseQuantum {
|
||||
#[bits(0..=15, rw)]
|
||||
value: u16,
|
||||
}
|
||||
|
||||
#[bitbybit::bitfield(u32)]
|
||||
#[derive(Debug)]
|
||||
pub struct MatchRegister {
|
||||
#[bit(31, rw)]
|
||||
copy_enable: bool,
|
||||
#[bits(0..=15, rw)]
|
||||
type_id: u16,
|
||||
}
|
||||
|
||||
/// Gigabit Ethernet Controller (GEM) registers for Zynq-7000
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct Ethernet {
|
||||
net_ctrl: NetworkControl,
|
||||
net_cfg: NetworkConfig,
|
||||
#[mmio(PureRead)]
|
||||
net_status: NetworkStatus,
|
||||
_reserved0: u32,
|
||||
dma_cfg: DmaConfig,
|
||||
tx_status: TxStatus,
|
||||
rx_buf_queue_base_addr: u32,
|
||||
tx_buf_queue_base_addr: u32,
|
||||
rx_status: RxStatus,
|
||||
interrupt_status: InterruptStatus,
|
||||
interrupt_enable: InterruptControl,
|
||||
interrupt_disable: InterruptControl,
|
||||
interrupt_mask: InterruptStatus,
|
||||
phy_maintenance: PhyMaintenance,
|
||||
#[mmio(PureRead)]
|
||||
rx_pause_quantum: PauseQuantum,
|
||||
tx_pause_quantum: PauseQuantum,
|
||||
_reserved1: [u32; 0x10],
|
||||
hash_low: u32,
|
||||
hash_high: u32,
|
||||
addr1_low: u32,
|
||||
addr1_high: u32,
|
||||
addr2_low: u32,
|
||||
addr2_high: u32,
|
||||
addr3_low: u32,
|
||||
addr3_high: u32,
|
||||
addr4_low: u32,
|
||||
addr4_high: u32,
|
||||
match_reg: [MatchRegister; 4],
|
||||
wake_on_lan: u32,
|
||||
ipg_stretch: u32,
|
||||
stacked_vlan: u32,
|
||||
tx_pfc: u32,
|
||||
addr1_mask_low: u32,
|
||||
addr1_mask_high: u32,
|
||||
_reserved2: [u32; 0x0B],
|
||||
/// Should be 0x20118.
|
||||
#[mmio(PureRead)]
|
||||
module_id: u32,
|
||||
#[mmio(inner)]
|
||||
statistics: Statistics,
|
||||
_reserved3: [u32; 0x34],
|
||||
#[mmio(PureRead)]
|
||||
design_cfg_2: u32,
|
||||
#[mmio(PureRead)]
|
||||
design_cfg_3: u32,
|
||||
#[mmio(PureRead)]
|
||||
design_cfg_4: u32,
|
||||
#[mmio(PureRead)]
|
||||
design_cfg_5: u32,
|
||||
}
|
||||
|
||||
static_assertions::const_assert_eq!(core::mem::size_of::<Ethernet>(), 0x294);
|
||||
|
||||
/// GEM statistics registers
|
||||
#[derive(derive_mmio::Mmio)]
|
||||
#[repr(C)]
|
||||
pub struct Statistics {
|
||||
#[mmio(PureRead)]
|
||||
tx_octets_low: u32,
|
||||
#[mmio(PureRead)]
|
||||
tx_octets_high: u32,
|
||||
#[mmio(PureRead)]
|
||||
tx_count: u32,
|
||||
#[mmio(PureRead)]
|
||||
tx_broadcast: u32,
|
||||
#[mmio(PureRead)]
|
||||
tx_multicast: u32,
|
||||
#[mmio(PureRead)]
|
||||
tx_pause: u32,
|
||||
#[mmio(PureRead)]
|
||||
tx_64_bits: u32,
|
||||
#[mmio(PureRead)]
|
||||
tx_65_to_127_bits: u32,
|
||||
#[mmio(PureRead)]
|
||||
tx_128_to_255_bits: u32,
|
||||
#[mmio(PureRead)]
|
||||
tx_256_to_511_bits: u32,
|
||||
#[mmio(PureRead)]
|
||||
tx_512_to_1023_bits: u32,
|
||||
#[mmio(PureRead)]
|
||||
tx_1024_to_1518_bits: u32,
|
||||
_reserved0: u32,
|
||||
#[mmio(PureRead)]
|
||||
tx_underruns: u32,
|
||||
#[mmio(PureRead)]
|
||||
single_collision_frames: u32,
|
||||
#[mmio(PureRead)]
|
||||
multi_collision_frames: u32,
|
||||
#[mmio(PureRead)]
|
||||
excessive_collisions: u32,
|
||||
#[mmio(PureRead)]
|
||||
late_collisions: u32,
|
||||
#[mmio(PureRead)]
|
||||
deferred_tx: u32,
|
||||
#[mmio(PureRead)]
|
||||
carrier_sense_errors: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_octets_low: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_octets_high: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_count: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_broadcast: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_multicast: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_pause: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_64_bits: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_65_to_127_bits: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_128_to_255_bits: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_256_to_511_bits: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_512_to_1023_bits: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_1024_to_1518_bits: u32,
|
||||
_reserved1: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_undersize: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_oversize: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_jabber: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_frame_check_sequence_errors: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_length_field_errors: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_symbol_errors: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_alignment_errors: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_resource_errors: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_overrun_errors: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_ip_header_checksum_errors: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_tcp_checksum_errors: u32,
|
||||
#[mmio(PureRead)]
|
||||
rx_udp_checksum_errors: u32,
|
||||
}
|
||||
|
||||
impl Ethernet {
|
||||
/// Create a new Gigabit Ethernet MMIO instance for GEM 0 at address [GEM_0_BASE_ADDR].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed_0() -> MmioEthernet<'static> {
|
||||
unsafe { Self::new_mmio_at(GEM_0_BASE_ADDR) }
|
||||
}
|
||||
|
||||
/// Create a new Gigabit Ethernet MMIO instance for GEM 1 at address [GEM_1_BASE_ADDR].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This API can be used to potentially create a driver to the same peripheral structure
|
||||
/// from multiple threads. The user must ensure that concurrent accesses are safe and do not
|
||||
/// interfere with each other.
|
||||
pub const unsafe fn new_mmio_fixed_1() -> MmioEthernet<'static> {
|
||||
unsafe { Self::new_mmio_at(GEM_1_BASE_ADDR) }
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ extern crate std;
|
||||
|
||||
pub const MPCORE_BASE_ADDR: usize = 0xF8F0_0000;
|
||||
|
||||
pub mod eth;
|
||||
pub mod gic;
|
||||
pub mod gpio;
|
||||
pub mod gtc;
|
||||
|
Loading…
x
Reference in New Issue
Block a user