eth-intel 0.1.3

Intel e1000 ethernet driver
Documentation
#![no_std]
#![no_main]
#![feature(used_with_arg)]

extern crate bare_test;

#[bare_test::tests]
mod tests {
    use bare_test::{
        os::{
            mem::{dma::kernel_dma_op, mmio::kernel_mmio_op},
            platform::{PlatformDescriptor, get_platform_descriptor},
        },
        *,
    };
    use eth_intel::E1000;
    use fdt_edit::{Fdt, NodeType, PciSpace};
    use pcie::{
        CommandRegister, PciMem32, PciMem64, PcieController, PcieGeneric, enumerate_by_controller,
    };

    #[test]
    #[timeout = 10000]
    fn ping_test() {
        println!("ping_test: e1000 discovery start");
        let nic = get_e1000().expect("no e1000 found on pci bus");
        bare_test::net::ping::run_ping_test(nic);
        println!("ping_test: completed");
    }

    fn get_e1000() -> Option<E1000> {
        let PlatformDescriptor::DeviceTree(dtb) = get_platform_descriptor() else {
            panic!("device tree not found");
        };

        let fdt = Fdt::from_bytes(dtb.as_slice()).unwrap();
        let (pcie_name, pcie) = match fdt
            .find_compatible(&["pci-host-ecam-generic"])
            .into_iter()
            .next()
            .unwrap()
        {
            node @ NodeType::Pci(_) => {
                let name = node.name();
                match node {
                    NodeType::Pci(pci) => (name, pci),
                    _ => unreachable!(),
                }
            }
            _ => panic!("pci host bridge not found"),
        };

        println!("pcie: {}", pcie_name);

        let reg = pcie.regs().into_iter().next().expect("pcie reg missing");
        let reg_size = reg.size.expect("pcie reg size missing");

        let mut controller = PcieController::new(
            PcieGeneric::new(reg.address as usize, reg_size as usize, kernel_mmio_op()).unwrap(),
        );

        for range in pcie.ranges().unwrap() {
            match range.space {
                PciSpace::Memory32 => {
                    controller.set_mem32(
                        PciMem32 {
                            address: range.cpu_address as _,
                            size: range.size as _,
                        },
                        range.prefetchable,
                    );
                }
                PciSpace::Memory64 => {
                    controller.set_mem64(
                        PciMem64 {
                            address: range.cpu_address as _,
                            size: range.size as _,
                        },
                        range.prefetchable,
                    );
                }
                _ => {}
            }
        }

        for mut ep in enumerate_by_controller(&mut controller, None) {
            println!("{}", ep);
            if E1000::check_vid_did(ep.vendor_id(), ep.device_id()) {
                let bar = ep.bar_mmio(0).expect("bar0");
                ep.update_command(|mut cmd| {
                    cmd.insert(CommandRegister::BUS_MASTER_ENABLE | CommandRegister::MEMORY_ENABLE);
                    cmd
                });

                return Some(
                    E1000::new(
                        bar.start as u64,
                        bar.count(),
                        u64::MAX,
                        kernel_dma_op(),
                        kernel_mmio_op(),
                    )
                    .expect("create e1000"),
                );
            }
        }

        None
    }
}