use tock_registers::{
    register_bitfields, register_structs,
    registers::{ReadOnly, ReadWrite},
};

register_bitfields! {
    u32,
    pub MACCR [
        /// * When set: MAC recognizes ARP requests, responds with ARP responses.
        /// * When clear: no additional ARP logic, frames are indicates as Type
        ///               frame in the RxStatus.
        ARPEN   OFFSET(31)  NUMBITS(1)  [],
        /// Source address insertion or replacement setting.
        SARC    OFFSET(28)  NUMBITS(3)  [],
        /// IP checksum offload.
        ///
        /// When set, enables IPv4 header checksum checking, IPv4, IPv6 TCP+UDP and ICMP
        /// payload checksum checking.
        IPC     OFFSET(27)  NUMBITS(1)  [],
        /// Inter-packet gap setting.
        IPG     OFFSET(24)  NUMBITS(1)  [],
        /// Giant packet size limit control enable.
        GPSCLE  OFFSET(23)  NUMBITS(1)  [],
        /// IEEE 802.3as support for 2K packets.
        S2KP    OFFSET(22)  NUMBITS(1)  [],
        /// CRC stripping for Type packets.
        CST     OFFSET(21)  NUMBITS(1)  [],
        /// Automatic pad or CRC stripping.
        ACS     OFFSET(20)  NUMBITS(1)  [],
        /// Watchdog disable.
        ///
        /// When set, disables the watchdog timer on the receiver. The MAC can receive packets
        /// of up to 16383 bytes.
        /// When clear, the MAC does not allow packets of more than 2048 bytes (or 10240 with
        /// JE).
        WD      OFFSET(19)  NUMBITS(1)  [],
        /// Packet burst enable.
        BE      OFFSET(18)  NUMBITS(1)  [],
        /// Jabber disable.
        ///
        /// When set, disables the jabber timer on the transmitter. The MAC can send packets of
        /// up to 16383 bytes.
        JD      OFFSET(17)  NUMBITS(1)  [],
        /// Jumbo packet enable.
        JE      OFFSET(16)  NUMBITS(1)  [],
        /// Port select
        PS      OFFSET(15)  NUMBITS(1)  [
            Ps1000Mbps = 0,
            Ps10Or100Mbps = 1,
        ],
        /// MAC speed
        FES     OFFSET(14)  NUMBITS(1)  [
            Fes10Mbps = 0,
            Fes100Mbps = 1,
        ],
        /// Duplex mode
        DM      OFFSET(13)  NUMBITS(1)  [
            HalfDuplex = 0,
            FullDuplex = 1,
        ],
        /// Loopback mode. When set, GMII output is looped back into input. The GMII RX clock
        /// input is required for the loopback to work, because the GMII TX clock is not
        /// looped back internally.
        LM      OFFSET(12)  NUMBITS(1)  [],
        /// Enable carrier-sense before transmission in Full-Duplex mode
        ECRSFD  OFFSET(11)  NUMBITS(1)  [],
        /// Disable receive own
        DO      OFFSET(10)  NUMBITS(1)  [],
        /// Disable carrier-sense during transmission
        DCRS    OFFSET(9)   NUMBITS(1)  [],
        /// Disable retry
        DR      OFFSET(8)   NUMBITS(1)  [],
        /// Backoff limit
        BL      OFFSET(5)   NUMBITS(2)  [
            /// k = min(n, 10)
            BackoffMin10    = 0,
            /// k = min(n, 8)
            BackoffMin8     = 1,
            /// k = min(n, 4)
            BackoffMin4     = 2,
            /// k = min(n, 1)
            BackoffMin1     = 3,
        ],
        /// Deferral check
        DC      OFFSET(4)   NUMBITS(1)  [],
        /// Preamble length
        PRELEN  OFFSET(2)   NUMBITS(2)  [
            Pre7b = 0,
            Pre5b = 1,
            Pre3b = 2,
        ],
        /// Transmitter enable
        TE      OFFSET(1)   NUMBITS(1)  [],
        /// Receiver enable
        RE      OFFSET(0)   NUMBITS(1)  [],
    ],

    pub MACPFR [
        /// Receive all. When set, the MAC receiver passes all received packets to the application,
        /// whether they pass the address filter or not.
        RA      OFFSET(31)  NUMBITS(1)  [],
        /// Drop Non-TCP/UDP over IP packets
        DNTU    OFFSET(21)  NUMBITS(1)  [],
        /// Layer 3 and 4 filter enable
        IPFE    OFFSET(20)  NUMBITS(1)  [],
        /// VLAN filter enable
        VTFE    OFFSET(16)  NUMBITS(1)  [],
        /// Hash or perfect filter
        HPF     OFFSET(10)  NUMBITS(1)  [],
        /// Source address filter
        SAF     OFFSET(9)   NUMBITS(1)  [],
        /// SA inverse filtering
        SAIF    OFFSET(8)   NUMBITS(1)  [],
        /// Pass control checks
        PCF     OFFSET(6)   NUMBITS(2)  [],
        /// Disable broadcast packets
        DBF     OFFSET(5)   NUMBITS(1)  [],
        /// Pass all multicast
        PM      OFFSET(4)   NUMBITS(1)  [],
        /// DA inverse filtering
        DAIF    OFFSET(3)   NUMBITS(1)  [],
        /// Hash multicast
        HMC     OFFSET(2)   NUMBITS(1)  [],
        /// Hash unicast
        HUC     OFFSET(1)   NUMBITS(1)  [],
        /// Promiscuous mode
        PR      OFFSET(0)   NUMBITS(1)  [],
    ],

    pub MACQ0TXFCR [
        /// Pause time
        PT      OFFSET(16)  NUMBITS(16) [],
        /// Disable zero-quanta pause
        DZPQ    OFFSET(7)   NUMBITS(1)  [],
        /// Pause low threshold
        PLT     OFFSET(4)   NUMBITS(3)  [],
        /// Transmit flow control enable
        TFE     OFFSET(1)   NUMBITS(1)  [],
        /// Flow control busy or backpressure activate
        FCB_BPA OFFSET(0)   NUMBITS(1)  [],
    ],

    pub MACRXFCR [
        /// Unicast packet detect
        UP      OFFSET(1)   NUMBITS(1)  [],
        /// Rx flow control enable
        RFE     OFFSET(0)   NUMBITS(1)  [],
    ],

    pub MACRXQC0R [
        /// Rx queue 1 enable
        RXQ1EN  OFFSET(2)   NUMBITS(2)  [
            Disable = 0b00,
            EnableAV = 0b01,
            Enable = 0b10,
        ],
        /// Rx queue 0 enable
        RXQ0EN  OFFSET(0)   NUMBITS(2)  [
            Disable = 0b00,
            EnableAV = 0b01,
            Enable = 0b10,
        ],
    ],

    pub MACISR [
        /// Rx status interrupt
        RXSTSIS     OFFSET(14)  NUMBITS(1)  [],
        /// Tx status interrupt
        TXSTSIS     OFFSET(13)  NUMBITS(1)  [],
        /// Timestamp interrupt
        TSIS        OFFSET(12)  NUMBITS(1)  [],
        /// MMC Tx interrupt
        MMCTXIS     OFFSET(10)  NUMBITS(1)  [],
        /// MMC Rx interrupt
        MMCRXIS     OFFSET(9)   NUMBITS(1)  [],
        /// MMC interrupt
        MMCIS       OFFSET(8)   NUMBITS(1)  [],
        /// LPI interrupt
        LPIIS       OFFSET(5)   NUMBITS(1)  [],
        /// PMT interrupt
        PMTIS       OFFSET(4)   NUMBITS(1)  [],
        /// PHY interrupt
        PHYIS       OFFSET(3)   NUMBITS(1)  [],
        /// RGMII interrupt
        RGSMIIIS    OFFSET(0)   NUMBITS(1)  [],
    ],

    pub MACIER [
        /// Rx status interrupt enable
        RXSTSIE     OFFSET(14)  NUMBITS(1)  [],
        /// Tx status interrupt enable
        TXSTSIE     OFFSET(13)  NUMBITS(1)  [],
        /// Timestamp interrupt enable
        TSIE        OFFSET(12)  NUMBITS(1)  [],
        /// LPI interrupt enable
        LPIIE       OFFSET(5)   NUMBITS(1)  [],
        /// PMT interrupt enable
        PMTIE       OFFSET(4)   NUMBITS(1)  [],
        /// PHY interrupt enable
        PHYIE       OFFSET(3)   NUMBITS(1)  [],
        /// RGMII interrupt enable
        RGSMIIIE    OFFSET(0)   NUMBITS(1)  [],
    ],

    pub MACPHYCSR [
        /// Link status
        LNKSTS      OFFSET(19)  NUMBITS(1)  [
            Down = 0,
            Up = 1,
        ],
        /// Link speed
        LNKSPEED    OFFSET(17)  NUMBITS(2)  [
            Speed2_5MHz = 0b00,
            Speed25MHz = 0b01,
            Speed125MHz = 0b10,
        ],
        /// Link mode
        LNKMOD      OFFSET(16)  NUMBITS(1)  [
            HalfDuplex = 0,
            FullDuplex = 1,
        ],
        /// Link up or down
        ///
        /// This bit indicates whether the link is up or down during transmission of configuration
        /// in the RGMII interface
        LUD         OFFSET(1)   NUMBITS(1)  [
            Down = 0,
            Up = 1,
        ],
        /// Transmit configuration in RGMII
        TC          OFFSET(0)   NUMBITS(1)  [],
    ],

    pub MACMDIOAR [
        /// Preamble suppress enable
        ///
        /// If set, SMA suppresses the 32-bit preamble and transmits MDIO frames with only 1
        /// preamble bit
        PSE     OFFSET(27)  NUMBITS(1)  [],
        /// Back to back transactions
        ///
        /// If set and the NTC has value greater than 0, the MAC informs the completion of a read
        /// or write command at the end of frame transfer. Must not be set with NTC=0.
        BTB     OFFSET(26)  NUMBITS(1)  [],
        /// Physical layer address
        ///
        /// In Clause 22, indicates a PHY device the MAC is addressing.
        PA      OFFSET(21)  NUMBITS(5)  [],
        /// Register/Device address
        ///
        /// In Clause 22, selects the PHY register
        RDA     OFFSET(16)  NUMBITS(5)  [],
        /// Number of trailing clocks
        NTC     OFFSET(12)  NUMBITS(3)  [],
        /// CSR clock range
        CR      OFFSET(8)   NUMBITS(4)  [
            CSR_20_TO_35_MHZ = 0b0010,
        ],
        /// Skip address packet
        ///
        /// If set, the SMA does not send the address packets before read, write or post-read
        /// increment address packets. Only valid with C45E set.
        SKAP    OFFSET(4)   NUMBITS(1)  [],
        /// GMII operation command
        GOC     OFFSET(2)   NUMBITS(2)  [
            Write = 0b01,
            C45EPostReadIncrement = 0b10,
            Read = 0b11
        ],
        /// Clause 45 PHY enable
        C45E    OFFSET(1)   NUMBITS(1)  [],
        /// GMII busy
        GB      OFFSET(0)   NUMBITS(1)  [],
    ],

    pub MACMDIODR [
        /// Register address
        ///
        /// Specifies the PHY register when used with Clause 45
        RA      OFFSET(16)  NUMBITS(16) [],
        /// GMII data
        GD      OFFSET(0)   NUMBITS(16) [],
    ],

    pub MACAiHR [
        /// MAC address enable bit. Should always be set to 1 for MAC address 0.
        AE      OFFSET(31)  NUMBITS(1)  [],
        ADDR5   OFFSET(8)   NUMBITS(8)  [],
        ADDR4   OFFSET(0)   NUMBITS(8)  [],
    ],
    pub MACAiLR [
        ADDR3   OFFSET(24)  NUMBITS(8)  [],
        ADDR2   OFFSET(16)  NUMBITS(8)  [],
        ADDR1   OFFSET(8)   NUMBITS(8)  [],
        ADDR0   OFFSET(0)   NUMBITS(8)  [],
    ],
}

register_structs! {
    pub MacRegs {
        /// Operating mode configuration register
        ///
        /// Reset value: 0x0000 8000
        ///
        /// Established the operating mode of the MAC.
        (0x000 => pub MACCR: ReadWrite<u32, MACCR::Register>),
        /// Extended operating mode configuration register
        ///
        /// XXX
        (0x004 => pub MACECR: ReadWrite<u32>),
        /// Packet filtering control register
        (0x008 => pub MACPFR: ReadWrite<u32, MACPFR::Register>),
        /// Watchdog timeout register
        (0x00C => pub MACWTR: ReadWrite<u32>),
        /// Hash table 0 register
        (0x010 => pub MACHT0R: ReadWrite<u32>),
        /// Hash table 1 register
        (0x014 => pub MACHT1R: ReadWrite<u32>),
        (0x018 => _0),
        /// VLAN tag register
        (0x050 => pub MACVTR: ReadWrite<u32>),
        (0x054 => _1),
        /// VLAN hash table register
        (0x058 => pub MACVHTR: ReadWrite<u32>),
        (0x05C => _2),
        /// VLAN inclusion register
        (0x060 => pub MACVIR: ReadWrite<u32>),
        /// Inner VLAN inclusion register
        (0x064 => pub MACIVIR: ReadWrite<u32>),
        (0x068 => _3),
        /// Tx queue 0 flow control register
        (0x070 => pub MACQ0TXFCR: ReadWrite<u32, MACQ0TXFCR::Register>),
        (0x074 => _4),
        /// Rx flow control register
        (0x090 => pub MACRXFCR: ReadWrite<u32, MACRXFCR::Register>),
        /// Rx queue control register
        (0x094 => pub MACRXQCR: ReadWrite<u32>),
        (0x098 => _5),
        /// Rx queue control 0 register
        (0x0A0 => pub MACRXQC0R: ReadWrite<u32, MACRXQC0R::Register>),
        /// Rx queue control 1 register
        (0x0A4 => pub MACRXQC1R: ReadWrite<u32>),
        /// Rx queue control 2 register
        (0x0A8 => pub MACRXQC2R: ReadWrite<u32>),
        (0x0AC => _6),
        /// Interrupt status register
        (0x0B0 => pub MACISR: ReadWrite<u32, MACISR::Register>),
        /// Interrupt enable register
        (0x0B4 => pub MACIER: ReadWrite<u32, MACIER::Register>),
        /// Rx/Tx status register
        (0x0B8 => pub MACRXTXSR: ReadWrite<u32>),
        (0x0BC => _7),
        /// PMT control status register
        (0x0C0 => pub MACPCSR: ReadWrite<u32>),
        /// Remote wakeup packet filter register
        (0x0C4 => pub MACRWKPFR: ReadWrite<u32>),
        (0x0C8 => _8),
        /// LPI control and status register
        (0x0D0 => pub MACLCSR: ReadWrite<u32>),
        /// LPI timers control register
        (0x0D4 => pub MACLTCR: ReadWrite<u32>),
        /// Tx LPI entry timer
        (0x0D8 => pub MACLETR: ReadWrite<u32>),
        /// One-microsecond-tick counter register
        (0x0DC => pub MAC1USTCR: ReadWrite<u32>),
        (0x0E0 => _9),
        /// PHYIF control and status register
        (0x0F8 => pub MACPHYCSR: ReadWrite<u32, MACPHYCSR::Register>),
        (0x0FC => _10),
        /// Version register
        (0x110 => pub MACVR: ReadOnly<u32>),
        /// Debug register
        (0x114 => pub MACDR: ReadOnly<u32>),
        (0x118 => _11),
        /// HW feature 0 register
        (0x11C => pub MACHWF0R: ReadWrite<u32>),
        /// HW feature 1 register
        (0x120 => pub MACHWF1R: ReadWrite<u32>),
        /// HW feature 2 register
        (0x124 => pub MACHWF2R: ReadWrite<u32>),
        /// HW feature 3 register
        (0x128 => pub MACHWF3R: ReadWrite<u32>),
        (0x12C => _12),
        /// MDIO address register
        (0x200 => pub MACMDIOAR: ReadWrite<u32, MACMDIOAR::Register>),
        /// MDIO data register
        (0x204 => pub MACMDIODR: ReadWrite<u32, MACMDIODR::Register>),
        (0x208 => _13),
        /// ARP address register
        (0x210 => pub MACARPAR: ReadWrite<u32>),
        (0x214 => _14),
        /// CSR software control register
        (0x230 => pub MACCSRSWCR: ReadWrite<u32>),
        (0x234 => _15),
        /// MAC address 0 high register
        (0x300 => pub MACA0HR: ReadWrite<u32, MACAiHR::Register>),
        /// MAC address 0 low register
        (0x304 => pub MACA0LR: ReadWrite<u32, MACAiLR::Register>),
        /// MAC address 1 high register
        (0x308 => pub MACA1HR: ReadWrite<u32>),
        /// MAC address 1 low register
        (0x30C => pub MACA1LR: ReadWrite<u32>),
        /// MAC address 2 high register
        (0x310 => pub MACA2HR: ReadWrite<u32>),
        /// MAC address 2 low register
        (0x314 => pub MACA2LR: ReadWrite<u32>),
        /// MAC address 3 high register
        (0x318 => pub MACA3HR: ReadWrite<u32>),
        /// MAC address 3 low register
        (0x31C => pub MACA3LR: ReadWrite<u32>),
        (0x320 => _16),
        /// MMC control register
        (0x700 => pub MMC_CONTROL: ReadWrite<u32>),
        /// MMC Rx interrupt register
        (0x704 => pub MMC_RX_INTERRUPT: ReadWrite<u32>),
        /// MMC Tx interrupt register
        (0x708 => pub MMC_TX_INTERRUPT: ReadWrite<u32>),
        /// MMC Rx interrupt mask register
        (0x70C => pub MMC_RX_INTERRUPT_MASK: ReadWrite<u32>),
        /// MMC Tx interrupt mask register
        (0x710 => pub MMC_TX_INTERRUPT_MASK: ReadWrite<u32>),
        (0x714 => _17),
        (0xC00 => @END),
    }
}
