eth_igb/
mac.rs

1use core::{fmt::Debug, ptr::NonNull, time::Duration};
2
3use log::error;
4use mbarrier::mb;
5use tock_registers::{interfaces::*, register_bitfields, register_structs, registers::*};
6
7use crate::{DError, Speed, osal::wait_for};
8
9register_structs! {
10    pub MacRegister {
11        (0x0 => ctrl: ReadWrite<u32, CTRL::Register>),
12        (0x4 => _rsv1),
13        (0x8 => status: ReadOnly<u32, STATUS::Register>),
14        (0xC => _rsv2),
15        (0x18 => ctrl_ext: ReadWrite<u32, CTRL_EXT::Register>),
16        (0x1c => _rsv3),
17        (0x20 => mdic: ReadWrite<u32, MDIC::Register>),
18        (0x24 => _rsv4),
19        (0xc0 => icr: ReadWrite<u32, ICR::Register>),
20        (0xc4 => _rsv13),
21        (0xd0 => ims: ReadWrite<u32, IMS::Register>),
22        (0xd4 => _rsv14),
23        (0xd8 => imc: ReadWrite<u32, IMC::Register>),
24        (0xdc => _rsv15),
25        (0x100 => pub rctl: ReadWrite<u32, RCTL::Register>),
26        (0x104 => _rsv7),
27        (0x400 => tctl: ReadWrite<u32, TCTL::Register>),
28        (0x404 => _rsv12),
29        (0x1514 => gpie: ReadWrite<u32, GPIE::Register>),
30        (0x1518 => _rsv16),
31        (0x1524 => eims: ReadWrite<u32>),
32        (0x1528 => eimc: ReadWrite<u32>),
33        (0x152c => eiac: ReadWrite<u32>),
34        (0x1530 => eiam: ReadWrite<u32>),
35        (0x1534 => _rsv5),
36        (0x1580 => eicr: ReadWrite<u32>),
37        (0x1584 => _rsv6),
38        (0x5400 => ralh_0_15: [ReadWrite<u32>; 32]),
39        (0x5480 => _rsv8),
40        (0x54e0 => ralh_16_23: [ReadWrite<u32>;32]),
41        (0x5560 => _rsv9),
42        (0x5B50 => swsm: ReadWrite<u32, SWSM::Register>),
43        (0x5B54 => fwsm: ReadWrite<u32>),
44        (0x5B58 => _rsv10),
45        (0x5B5C => sw_fw_sync: ReadWrite<u32>),
46        (0x5B60 => _rsv11),
47
48        // The end of the struct is marked as follows.
49        (0xEFFF => @END),
50    }
51}
52
53register_bitfields! [
54    // First parameter is the register width. Can be u8, u16, u32, or u64.
55    u32,
56
57    CTRL [
58        FD OFFSET(0) NUMBITS(1)[
59            HalfDuplex = 0,
60            FullDuplex = 1,
61        ],
62        SLU OFFSET(6) NUMBITS(1)[],
63        SPEED OFFSET(8) NUMBITS(2)[
64            Speed10 = 0,
65            Speed100 = 1,
66            Speed1000 = 0b10,
67        ],
68        FRCSPD OFFSET(11) NUMBITS(1)[],
69        FRCDPLX OFFSET(12) NUMBITS(1)[],
70        RST OFFSET(26) NUMBITS(1)[
71            Normal = 0,
72            Reset = 1,
73        ],
74        PHY_RST OFFSET(31) NUMBITS(1)[],
75    ],
76    STATUS [
77        FD OFFSET(0) NUMBITS(1)[
78            HalfDuplex = 0,
79            FullDuplex = 1,
80        ],
81        LU OFFSET(1) NUMBITS(1)[],
82        SPEED OFFSET(6) NUMBITS(2)[
83            Speed10 = 0,
84            Speed100 = 1,
85            Speed1000 = 0b10,
86        ],
87         PHYRA OFFSET(10) NUMBITS(1)[],
88    ],
89    pub CTRL_EXT [
90        LINK_MODE OFFSET(22) NUMBITS(2)[
91            DircetCooper = 0,
92            SGMII = 0b10,
93            InternalSerdes = 0b11,
94        ],
95    ],
96    MDIC [
97        DATA OFFSET(0) NUMBITS(16)[],
98        REGADDR OFFSET(16) NUMBITS(5)[],
99        PHY_ADDR OFFSET(21) NUMBITS(5)[],
100        OP OFFSET(26) NUMBITS(2)[
101            Write = 0b1,
102            Read = 0b10,
103        ],
104        READY OFFSET(28) NUMBITS(1)[],
105        I OFFSET(29) NUMBITS(1)[],
106        E OFFSET(30) NUMBITS(1)[
107            NoError = 0,
108            Error = 1,
109        ],
110        Destination OFFSET(31) NUMBITS(1)[
111            Internal = 0,
112            External = 1,
113        ]
114    ],
115
116    SWSM [
117        SMBI OFFSET(0) NUMBITS(1)[],
118        SWESMBI OFFSET(1) NUMBITS(1)[],
119        WMNG OFFSET(2) NUMBITS(1)[],
120        EEUR OFFSET(3) NUMBITS(1)[],
121    ],
122
123    SW_FW_SYNC [
124        SW_EEP_SM OFFSET(0) NUMBITS(1)[],
125        SW_PHY_SM0 OFFSET(1) NUMBITS(1)[],
126        SW_PHY_SM1 OFFSET(2) NUMBITS(1)[],
127        SW_MAC_CSR_SM OFFSET(3) NUMBITS(1)[],
128        SW_FLASH_SM OFFSET(4) NUMBITS(1)[],
129
130        FW_EEP_SM OFFSET(16) NUMBITS(1)[],
131        FW_PHY_SM0 OFFSET(17) NUMBITS(1)[],
132        FW_PHY_SM1 OFFSET(18) NUMBITS(1)[],
133        FW_MAC_CSR_SM OFFSET(19) NUMBITS(1)[],
134        FW_FLASH_SM OFFSET(20) NUMBITS(1)[],
135    ],
136
137    pub RCTL [
138        RXEN OFFSET(1) NUMBITS(1)[
139            Disabled = 0,
140            Enabled = 1,
141        ],
142        SBP OFFSET(2) NUMBITS(1)[
143            DoNotStore = 0,
144            Store = 1,
145        ],
146        UPE OFFSET(3) NUMBITS(1)[
147            Disabled = 0,
148            Enabled = 1,
149        ],
150        MPE OFFSET(4) NUMBITS(1)[
151            Disabled = 0,
152            Enabled = 1,
153        ],
154        LPE OFFSET(5) NUMBITS(1)[
155            Disabled = 0,
156            Enabled = 1,
157        ],
158        LBM OFFSET(6) NUMBITS(2)[
159            Normal = 0b00,
160            MacLoopback = 0b01,
161            Reserved = 0b11,
162        ],
163        MO OFFSET(12) NUMBITS(2)[
164            Bits47_36 = 0b00,
165            Bits46_35 = 0b01,
166            Bits45_34 = 0b10,
167            Bits43_32 = 0b11,
168        ],
169        BAM OFFSET(15) NUMBITS(1)[
170            Ignore = 0,
171            Accept = 1,
172        ],
173        BSIZE OFFSET(16) NUMBITS(2)[
174            Bytes2048 = 0b00,
175            Bytes1024 = 0b01,
176            Bytes512 = 0b10,
177            Bytes256 = 0b11,
178        ],
179        VFE OFFSET(18) NUMBITS(1)[
180            Disabled = 0,
181            Enabled = 1,
182        ],
183        CFIEN OFFSET(19) NUMBITS(1)[
184            Disabled = 0,
185            Enabled = 1,
186        ],
187        CFI OFFSET(20) NUMBITS(1)[
188            Accept = 0,
189            Discard = 1,
190        ],
191        PSP OFFSET(21) NUMBITS(1)[],
192        DPF OFFSET(22) NUMBITS(1)[
193            Forward = 0,
194            Discard = 1,
195        ],
196        PMCF OFFSET(23) NUMBITS(1)[
197            Pass = 0,
198            Filter = 1,
199        ],
200        SECRC OFFSET(26) NUMBITS(1)[
201            DoNotStrip = 0,
202            Strip = 1,
203        ],
204    ],
205
206    // Transmit Control Register - TCTL (0x400)
207    TCTL [
208        EN OFFSET(1) NUMBITS(1)[
209            Disabled = 0,
210            Enabled = 1,
211        ],
212        PSP OFFSET(3) NUMBITS(1)[
213            Disabled = 0,
214            Enabled = 1,
215        ],
216        CT OFFSET(4) NUMBITS(8)[],
217        COLD OFFSET(12) NUMBITS(10)[],
218        SWXOFF OFFSET(22) NUMBITS(1)[],
219        RTLC OFFSET(24) NUMBITS(1)[],
220        NRTU OFFSET(25) NUMBITS(1)[],
221        MULR OFFSET(28) NUMBITS(1)[],
222    ],
223
224    // Extended Interrupt Cause Register - EICR (0x01580)
225    EICR [
226        // Non MSI-X mode (GPIE.Multiple_MSIX = 0)
227        RxTxQ OFFSET(0) NUMBITS(16)[],
228        Reserved1 OFFSET(16) NUMBITS(14)[],
229        TCP_Timer OFFSET(30) NUMBITS(1)[],
230        Other_Cause OFFSET(31) NUMBITS(1)[],
231    ],
232
233    // Extended Interrupt Cause Register - EICR MSI-X mode
234    EICR_MSIX [
235        // MSI-X mode (GPIE.Multiple_MSIX = 1)
236        MSIX OFFSET(0) NUMBITS(25)[],
237        Reserved OFFSET(25) NUMBITS(7)[],
238    ],
239
240    // Extended Interrupt Mask Set/Read - EIMS (0x01524)
241    EIMS [
242        // Non MSI-X mode (GPIE.Multiple_MSIX = 0)
243        RxTxQ OFFSET(0) NUMBITS(16)[],
244        Reserved1 OFFSET(16) NUMBITS(14)[],
245        TCP_Timer OFFSET(30) NUMBITS(1)[],
246        Other_Cause OFFSET(31) NUMBITS(1)[],
247    ],
248
249    // Extended Interrupt Mask Set/Read - EIMS MSI-X mode
250    EIMS_MSIX [
251        // MSI-X mode (GPIE.Multiple_MSIX = 1)
252        MSIX OFFSET(0) NUMBITS(25)[],
253        Reserved OFFSET(25) NUMBITS(7)[],
254    ],
255
256    // Legacy Interrupt Cause Register - ICR (0x000C0)
257    ICR [
258        TXDW OFFSET(0) NUMBITS(1)[],   // Transmit Descriptor Written Back
259        TXQE OFFSET(1) NUMBITS(1)[],   // Transmit Queue Empty
260        LSC OFFSET(2) NUMBITS(1)[],    // Link Status Change
261        RXSEQ OFFSET(3) NUMBITS(1)[],  // Receive Sequence Error
262        RXDMT0 OFFSET(4) NUMBITS(1)[], // Receive Descriptor Minimum Threshold Reached
263        RXO OFFSET(6) NUMBITS(1)[],    // Receiver Overrun
264        RXT0 OFFSET(7) NUMBITS(1)[],   // Receiver Timer Interrupt
265        MDAC OFFSET(9) NUMBITS(1)[],   // MDI/O Access Complete
266        RXCFG OFFSET(10) NUMBITS(1)[], // Receiving /C/ ordered sets
267        GPI_EN0 OFFSET(11) NUMBITS(1)[], // General Purpose Interrupt Enable 0
268        GPI_EN1 OFFSET(12) NUMBITS(1)[], // General Purpose Interrupt Enable 1
269        GPI_EN2 OFFSET(13) NUMBITS(1)[], // General Purpose Interrupt Enable 2
270        GPI_EN3 OFFSET(14) NUMBITS(1)[], // General Purpose Interrupt Enable 3
271        TXD_LOW OFFSET(15) NUMBITS(1)[], // Transmit Descriptor Low Threshold Hit
272        SRPD OFFSET(16) NUMBITS(1)[],  // Small Receive Packet Detected
273        ACK OFFSET(17) NUMBITS(1)[],   // Receive ACK Frame
274        MNG OFFSET(18) NUMBITS(1)[],   // Management Bus Interrupt
275        DOCK OFFSET(19) NUMBITS(1)[],  // Dock/Undock Status Change
276        INT_ASSERTED OFFSET(31) NUMBITS(1)[], // Interrupt Asserted
277    ],
278
279    // Legacy Interrupt Mask Set/Read - IMS (0x000D0)
280    IMS [
281        TXDW OFFSET(0) NUMBITS(1)[],   // Transmit Descriptor Written Back
282        TXQE OFFSET(1) NUMBITS(1)[],   // Transmit Queue Empty
283        LSC OFFSET(2) NUMBITS(1)[],    // Link Status Change
284        RXSEQ OFFSET(3) NUMBITS(1)[],  // Receive Sequence Error
285        RXDMT0 OFFSET(4) NUMBITS(1)[], // Receive Descriptor Minimum Threshold Reached
286        RXO OFFSET(6) NUMBITS(1)[],    // Receiver Overrun
287        RXT0 OFFSET(7) NUMBITS(1)[],   // Receiver Timer Interrupt
288        MDAC OFFSET(9) NUMBITS(1)[],   // MDI/O Access Complete
289        RXCFG OFFSET(10) NUMBITS(1)[], // Receiving /C/ ordered sets
290        GPI_EN0 OFFSET(11) NUMBITS(1)[], // General Purpose Interrupt Enable 0
291        GPI_EN1 OFFSET(12) NUMBITS(1)[], // General Purpose Interrupt Enable 1
292        GPI_EN2 OFFSET(13) NUMBITS(1)[], // General Purpose Interrupt Enable 2
293        GPI_EN3 OFFSET(14) NUMBITS(1)[], // General Purpose Interrupt Enable 3
294        TXD_LOW OFFSET(15) NUMBITS(1)[], // Transmit Descriptor Low Threshold Hit
295        SRPD OFFSET(16) NUMBITS(1)[],  // Small Receive Packet Detected
296        ACK OFFSET(17) NUMBITS(1)[],   // Receive ACK Frame
297        MNG OFFSET(18) NUMBITS(1)[],   // Management Bus Interrupt
298        DOCK OFFSET(19) NUMBITS(1)[],  // Dock/Undock Status Change
299    ],
300
301    // Legacy Interrupt Mask Clear - IMC (0x000D8)
302    IMC [
303        TXDW OFFSET(0) NUMBITS(1)[],   // Transmit Descriptor Written Back
304        TXQE OFFSET(1) NUMBITS(1)[],   // Transmit Queue Empty
305        LSC OFFSET(2) NUMBITS(1)[],    // Link Status Change
306        RXSEQ OFFSET(3) NUMBITS(1)[],  // Receive Sequence Error
307        RXDMT0 OFFSET(4) NUMBITS(1)[], // Receive Descriptor Minimum Threshold Reached
308        RXO OFFSET(6) NUMBITS(1)[],    // Receiver Overrun
309        RXT0 OFFSET(7) NUMBITS(1)[],   // Receiver Timer Interrupt
310        MDAC OFFSET(9) NUMBITS(1)[],   // MDI/O Access Complete
311        RXCFG OFFSET(10) NUMBITS(1)[], // Receiving /C/ ordered sets
312        GPI_EN0 OFFSET(11) NUMBITS(1)[], // General Purpose Interrupt Enable 0
313        GPI_EN1 OFFSET(12) NUMBITS(1)[], // General Purpose Interrupt Enable 1
314        GPI_EN2 OFFSET(13) NUMBITS(1)[], // General Purpose Interrupt Enable 2
315        GPI_EN3 OFFSET(14) NUMBITS(1)[], // General Purpose Interrupt Enable 3
316        TXD_LOW OFFSET(15) NUMBITS(1)[], // Transmit Descriptor Low Threshold Hit
317        SRPD OFFSET(16) NUMBITS(1)[],  // Small Receive Packet Detected
318        ACK OFFSET(17) NUMBITS(1)[],   // Receive ACK Frame
319        MNG OFFSET(18) NUMBITS(1)[],   // Management Bus Interrupt
320        DOCK OFFSET(19) NUMBITS(1)[],  // Dock/Undock Status Change
321    ],
322
323    // General Purpose Interrupt Enable - GPIE (0x1514)
324    GPIE [
325        NSICR OFFSET(0) NUMBITS(1)[
326            Normal = 0,
327            ClearOnRead = 1,
328        ],
329        Multiple_MSIX OFFSET(4) NUMBITS(1)[
330            SingleVector = 0,
331            MultipleVectors = 1,
332        ],
333        LL_Interval OFFSET(7) NUMBITS(5)[],  // Low Latency Credits Increment Rate (bits 11:7)
334        EIAME OFFSET(30) NUMBITS(1)[
335            Disabled = 0,
336            Enabled = 1,
337        ],
338        PBA_Support OFFSET(31) NUMBITS(1)[
339            Legacy = 0,
340            MSIX = 1,
341        ],
342    ],
343];
344
345#[derive(Clone, Copy)]
346pub struct Mac {
347    reg: NonNull<MacRegister>,
348}
349
350impl Mac {
351    pub fn new(iobase: NonNull<u8>) -> Self {
352        Self { reg: iobase.cast() }
353    }
354
355    pub fn iobase<T>(&self) -> NonNull<T> {
356        self.reg.cast()
357    }
358
359    pub fn write_mdic(&self, phys_addr: u32, offset: u32, data: u16) -> Result<(), DError> {
360        self.reg().mdic.write(
361            MDIC::REGADDR.val(offset)
362                + MDIC::PHY_ADDR.val(phys_addr)
363                + MDIC::DATA.val(data as _)
364                + MDIC::OP::Write,
365        );
366        mb();
367
368        loop {
369            let mdic = self.reg().mdic.extract();
370
371            if mdic.is_set(MDIC::READY) {
372                break;
373            }
374            if mdic.is_set(MDIC::E) {
375                error!("MDIC read error");
376                return Err(DError::Unknown("MDIC read error"));
377            }
378        }
379
380        Ok(())
381    }
382
383    pub fn read_mdic(&self, phys_addr: u32, offset: u32) -> Result<u16, DError> {
384        self.reg()
385            .mdic
386            .write(MDIC::REGADDR.val(offset) + MDIC::PHY_ADDR.val(phys_addr) + MDIC::OP::Read);
387        mb();
388        loop {
389            let mdic = self.reg().mdic.extract();
390            if mdic.is_set(MDIC::READY) {
391                return Ok(mdic.read(MDIC::DATA) as _);
392            }
393            if mdic.is_set(MDIC::E) {
394                error!("MDIC read error");
395                return Err(DError::Unknown("MDIC read error"));
396            }
397        }
398    }
399
400    pub fn disable_interrupts(&mut self) {
401        self.reg_mut().eimc.set(u32::MAX);
402        self.clear_interrupts();
403    }
404
405    pub fn enable_interrupts(&mut self) {
406        self.reg_mut().eims.set(u32::MAX);
407    }
408
409    /// Enable legacy interrupts
410    pub fn enable_legacy_interrupts(&mut self) {
411        // Enable common legacy interrupts
412        self.reg_mut().ims.write(
413            IMS::TXDW::SET
414                + IMS::TXQE::SET
415                + IMS::LSC::SET
416                + IMS::RXDMT0::SET
417                + IMS::RXO::SET
418                + IMS::RXT0::SET
419                + IMS::MDAC::SET,
420        );
421    }
422
423    /// Disable legacy interrupts
424    pub fn disable_legacy_interrupts(&mut self) {
425        // Disable all legacy interrupts
426        self.reg_mut().imc.write(
427            IMC::TXDW::SET
428                + IMC::TXQE::SET
429                + IMC::LSC::SET
430                + IMC::RXSEQ::SET
431                + IMC::RXDMT0::SET
432                + IMC::RXO::SET
433                + IMC::RXT0::SET
434                + IMC::MDAC::SET
435                + IMC::RXCFG::SET
436                + IMC::GPI_EN0::SET
437                + IMC::GPI_EN1::SET
438                + IMC::GPI_EN2::SET
439                + IMC::GPI_EN3::SET
440                + IMC::TXD_LOW::SET
441                + IMC::SRPD::SET
442                + IMC::ACK::SET
443                + IMC::MNG::SET
444                + IMC::DOCK::SET,
445        );
446    }
447
448    /// Read and clear legacy interrupt cause
449    pub fn legacy_interrupts_ack(&mut self) -> LegacyIrqMsg {
450        let icr = self.reg().icr.get();
451        let ims = self.reg().ims.get();
452        let status = icr & ims;
453
454        LegacyIrqMsg {
455            txdw: status & ICR::TXDW.mask != 0,
456            txqe: status & ICR::TXQE.mask != 0,
457            lsc: status & ICR::LSC.mask != 0,
458            rxseq: status & ICR::RXSEQ.mask != 0,
459            rxdmt0: status & ICR::RXDMT0.mask != 0,
460            rxo: status & ICR::RXO.mask != 0,
461            rxt0: status & ICR::RXT0.mask != 0,
462            mdac: status & ICR::MDAC.mask != 0,
463            rxcfg: status & ICR::RXCFG.mask != 0,
464            asserted: status & ICR::INT_ASSERTED.mask != 0,
465        }
466    }
467
468    pub fn interrupts_ack(&mut self) -> IrqMsg {
469        let eicr = self.reg().eicr.get();
470        let eims = self.reg().eims.get();
471        let status = eicr & eims;
472        let tcp_timer = status & EICR::TCP_Timer.mask != 0;
473        let other = status & EICR::Other_Cause.mask != 0;
474        let queue_idx = (status & EICR::RxTxQ.mask) as u16;
475        IrqMsg {
476            queue_idx,
477            tcp_timer,
478            other,
479        }
480    }
481
482    pub fn link_mode(&self) -> Option<LinkMode> {
483        Some(
484            match self.reg().ctrl_ext.read_as_enum(CTRL_EXT::LINK_MODE) {
485                Some(CTRL_EXT::LINK_MODE::Value::DircetCooper) => LinkMode::DirectCooper,
486                Some(CTRL_EXT::LINK_MODE::Value::SGMII) => LinkMode::Sgmii,
487                Some(CTRL_EXT::LINK_MODE::Value::InternalSerdes) => LinkMode::InternalSerdes,
488                None => return None,
489            },
490        )
491    }
492
493    /// Clear all interrupt masks for all queues.
494    pub fn clear_interrupts(&mut self) {
495        // Clear interrupt mask
496        self.reg_mut().eimc.set(u32::MAX);
497        self.reg().eicr.get();
498    }
499
500    pub fn reset(&mut self) -> Result<(), DError> {
501        self.reg_mut()
502            .ctrl
503            .modify(CTRL::RST::Reset + CTRL::PHY_RST::SET);
504        wait_for(
505            || self.reg().ctrl.matches_any(&[CTRL::RST::Normal]),
506            Duration::from_millis(1),
507            Some(1000),
508        )
509    }
510
511    pub fn set_link_up(&mut self) {
512        self.reg_mut().ctrl.modify(CTRL::SLU::SET + CTRL::FD::SET);
513    }
514
515    pub fn reg(&self) -> &MacRegister {
516        unsafe { self.reg.as_ref() }
517    }
518    pub fn reg_mut(&mut self) -> &mut MacRegister {
519        unsafe { self.reg.as_mut() }
520    }
521
522    pub fn read_mac(&self) -> [u8; 6] {
523        let low = self.ral(0);
524        let high = self.rah(0);
525
526        [
527            (low & 0xff) as u8,
528            ((low >> 8) & 0xff) as u8,
529            ((low >> 16) & 0xff) as u8,
530            (low >> 24) as u8,
531            (high & 0xff) as u8,
532            ((high >> 8) & 0xff) as u8,
533        ]
534    }
535
536    pub fn disable_rx(&mut self) {
537        self.reg_mut().rctl.modify(RCTL::RXEN::Disabled);
538    }
539
540    pub fn enable_rx(&mut self) {
541        self.reg_mut().rctl.modify(RCTL::RXEN::Enabled);
542    }
543
544    pub fn enable_tx(&mut self) {
545        self.reg_mut().tctl.modify(TCTL::EN::Enabled);
546    }
547
548    pub fn enable_loopback(&mut self) {
549        self.reg_mut().rctl.modify(RCTL::LBM::MacLoopback);
550    }
551
552    pub fn disable_loopback(&mut self) {
553        self.reg_mut().rctl.modify(RCTL::LBM::Normal);
554    }
555
556    /// Configure GPIE register for MSI-X mode
557    pub fn configure_msix_mode(&mut self) {
558        self.reg_mut().gpie.write(
559            GPIE::Multiple_MSIX::MultipleVectors + GPIE::EIAME::Enabled + GPIE::PBA_Support::MSIX,
560        );
561    }
562
563    /// Configure GPIE register for legacy/MSI mode
564    pub fn configure_legacy_mode(&mut self) {
565        self.reg_mut().gpie.write(
566            GPIE::Multiple_MSIX::SingleVector + GPIE::EIAME::Disabled + GPIE::PBA_Support::Legacy,
567        );
568    }
569
570    /// Set non-selective interrupt clear on read
571    pub fn set_nsicr(&mut self, enable: bool) {
572        if enable {
573            self.reg_mut().gpie.modify(GPIE::NSICR::ClearOnRead);
574        } else {
575            self.reg_mut().gpie.modify(GPIE::NSICR::Normal);
576        }
577    }
578
579    /// Set Low Latency Credits Increment Rate
580    pub fn set_ll_interval(&mut self, interval: u8) {
581        // interval is in 4μs increments, valid values 0-31
582        let val = (interval as u32) & 0x1F;
583        self.reg_mut().gpie.modify(GPIE::LL_Interval.val(val));
584    }
585
586    fn ral(&self, i: usize) -> u32 {
587        if i <= 15 {
588            self.reg().ralh_0_15[i * 2].get()
589        } else {
590            self.reg().ralh_16_23[i * 2].get()
591        }
592    }
593
594    fn rah(&self, i: usize) -> u32 {
595        if i <= 15 {
596            self.reg().ralh_0_15[i * 2 + 1].get()
597        } else {
598            self.reg().ralh_16_23[i * 2 + 1].get()
599        }
600    }
601
602    pub fn status(&self) -> MacStatus {
603        let status = self.reg().status.extract();
604        let speed = match status.read_as_enum(STATUS::SPEED) {
605            Some(STATUS::SPEED::Value::Speed1000) => Speed::Mb1000,
606            Some(STATUS::SPEED::Value::Speed100) => Speed::Mb100,
607            _ => Speed::Mb10,
608        };
609        let full_duplex = status.is_set(STATUS::FD);
610        let link_up = status.is_set(STATUS::LU);
611        let phy_reset_asserted = status.is_set(STATUS::PHYRA);
612
613        MacStatus {
614            full_duplex,
615            link_up,
616            speed,
617            phy_reset_asserted,
618        }
619    }
620}
621
622#[derive(Debug, Clone)]
623pub struct IrqMsg {
624    pub queue_idx: u16,
625    pub tcp_timer: bool,
626    pub other: bool,
627}
628
629#[derive(Debug, Clone)]
630pub struct LegacyIrqMsg {
631    pub txdw: bool,     // Transmit Descriptor Written Back
632    pub txqe: bool,     // Transmit Queue Empty
633    pub lsc: bool,      // Link Status Change
634    pub rxseq: bool,    // Receive Sequence Error
635    pub rxdmt0: bool,   // Receive Descriptor Minimum Threshold Reached
636    pub rxo: bool,      // Receiver Overrun
637    pub rxt0: bool,     // Receiver Timer Interrupt
638    pub mdac: bool,     // MDI/O Access Complete
639    pub rxcfg: bool,    // Receiving /C/ ordered sets
640    pub asserted: bool, // Interrupt Asserted
641}
642
643#[derive(Clone, Copy, PartialEq, Eq)]
644#[repr(transparent)]
645pub struct MacAddr6([u8; 6]);
646
647impl MacAddr6 {
648    pub fn new(bytes: [u8; 6]) -> Self {
649        MacAddr6(bytes)
650    }
651
652    pub fn bytes(&self) -> [u8; 6] {
653        self.0
654    }
655}
656
657impl Debug for MacAddr6 {
658    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
659        write!(
660            f,
661            "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
662            self.0[0], self.0[1], self.0[2], self.0[3], self.0[4], self.0[5]
663        )
664    }
665}
666
667impl From<[u8; 6]> for MacAddr6 {
668    fn from(addr: [u8; 6]) -> Self {
669        MacAddr6(addr)
670    }
671}
672
673impl From<MacAddr6> for [u8; 6] {
674    fn from(addr: MacAddr6) -> Self {
675        addr.0
676    }
677}
678
679#[derive(Debug, Clone)]
680pub struct MacStatus {
681    pub full_duplex: bool,
682    pub link_up: bool,
683    pub speed: Speed,
684    pub phy_reset_asserted: bool,
685}
686
687#[derive(Debug, Clone, Copy, PartialEq, Eq)]
688pub enum LinkMode {
689    DirectCooper,
690    Sgmii,
691    InternalSerdes,
692}