eth_igb/
lib.rs

1#![no_std]
2
3use core::{ops::Deref, ptr::NonNull};
4
5use alloc::vec::Vec;
6use dma_api::{DVec, Direction};
7use log::debug;
8pub use mac::{MacAddr6, MacStatus};
9pub use trait_ffi::impl_extern_trait;
10
11pub use crate::err::DError;
12use crate::ring::DEFAULT_RING_SIZE;
13
14extern crate alloc;
15
16mod err;
17mod mac;
18#[macro_use]
19pub mod osal;
20mod descriptor;
21mod phy;
22mod ring;
23
24pub use futures::{Stream, StreamExt};
25pub use ring::{RxPacket, RxRing, TxRing};
26
27pub struct Request {
28    buff: DVec<u8>,
29}
30
31impl Request {
32    fn new(buff: Vec<u8>, dir: Direction) -> Self {
33        let buff = DVec::from_vec(buff, dir);
34        Self { buff }
35    }
36    pub fn new_rx(buff: Vec<u8>) -> Self {
37        Self::new(buff, Direction::FromDevice)
38    }
39
40    pub fn new_tx(buff: Vec<u8>) -> Self {
41        Self::new(buff, Direction::ToDevice)
42    }
43
44    pub fn bus_addr(&self) -> u64 {
45        self.buff.bus_addr()
46    }
47}
48
49impl Deref for Request {
50    type Target = [u8];
51
52    fn deref(&self) -> &Self::Target {
53        self.buff.as_ref()
54    }
55}
56
57pub struct Igb {
58    mac: mac::Mac,
59    phy: phy::Phy,
60    _rx_ring_addrs: [usize; 16],
61    _tx_ring_addrs: [usize; 16],
62}
63
64impl Igb {
65    pub fn new(iobase: NonNull<u8>) -> Result<Self, DError> {
66        let mac = mac::Mac::new(iobase);
67        let phy = phy::Phy::new(mac);
68
69        Ok(Self {
70            mac,
71            phy,
72            _rx_ring_addrs: [0; 16],
73            _tx_ring_addrs: [0; 16],
74        })
75    }
76
77    pub fn open(&mut self) -> Result<(), DError> {
78        self.mac.disable_interrupts();
79
80        self.mac.reset()?;
81
82        self.mac.disable_interrupts();
83
84        debug!("reset done");
85
86        let link_mode = self.mac.link_mode().unwrap();
87        debug!("link mode: {link_mode:?}");
88        self.phy.power_up()?;
89
90        self.setup_phy_and_the_link()?;
91
92        self.mac.set_link_up();
93
94        self.phy.wait_for_auto_negotiation_complete()?;
95        debug!("Auto-negotiation complete");
96        self.config_fc_after_link_up()?;
97
98        self.init_stat();
99
100        self.mac.enable_interrupts();
101
102        self.mac.enable_rx();
103        self.mac.enable_tx();
104
105        Ok(())
106    }
107
108    pub fn new_ring(&mut self) -> Result<(TxRing, RxRing), DError> {
109        let tx_ring = TxRing::new(0, self.mac.iobase(), DEFAULT_RING_SIZE)?;
110        let rx_ring = RxRing::new(0, self.mac.iobase(), DEFAULT_RING_SIZE)?;
111
112        Ok((tx_ring, rx_ring))
113    }
114
115    fn config_fc_after_link_up(&mut self) -> Result<(), DError> {
116        // TODO 参考 drivers/net/ethernet/intel/igb/e1000_mac.c
117        // igb_config_fc_after_link_up
118        Ok(())
119    }
120
121    fn setup_phy_and_the_link(&mut self) -> Result<(), DError> {
122        self.phy.power_up()?;
123        debug!("PHY powered up");
124        self.phy.enable_auto_negotiation()?;
125
126        Ok(())
127    }
128
129    pub fn read_mac(&self) -> MacAddr6 {
130        self.mac.read_mac().into()
131    }
132
133    pub fn check_vid_did(vid: u16, did: u16) -> bool {
134        // This is a placeholder for actual VID/DID checking logic.
135        // In a real implementation, this would check the device's
136        // vendor ID and device ID against the provided values.
137        vid == 0x8086 && [0x10C9, 0x1533].contains(&did)
138    }
139
140    pub fn status(&self) -> MacStatus {
141        self.mac.status()
142    }
143
144    pub fn enable_loopback(&mut self) {
145        self.mac.enable_loopback();
146    }
147
148    pub fn disable_loopback(&mut self) {
149        self.mac.disable_loopback();
150    }
151
152    fn init_stat(&mut self) {
153        //TODO
154    }
155
156    /// # Safety
157    /// This function should only be called from the interrupt handler.
158    /// It will handle the interrupt by acknowledging
159    pub unsafe fn handle_interrupt(&mut self) {
160        let msg = self.mac.interrupts_ack();
161        debug!("Interrupt message: {msg:?}");
162        if msg.queue_idx & 0x1 != 0 {
163            // let rx_ring = unsafe { &mut *(self.rx_ring_addrs[0] as *mut Ring<AdvRxDesc>) };
164            // rx_ring.clean();
165        }
166    }
167
168    pub fn irq_mode_legacy(&mut self) {
169        self.mac.configure_legacy_mode();
170    }
171}
172
173#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
174pub enum Speed {
175    Mb10,
176    Mb100,
177    Mb1000,
178}