1

我有英特尔系统Ethernet controller: Intel Corporation 82579LM Gigabit Network Connection (Lewisville) (rev 04)。我已经下载了数据表,如数据表Intel ® 82579 Gigabit Ethernet PHY

现在我正在读取 pci 以太网设备的 resource0,例如

    if((fd = open("/sys/bus/pci/devices/0000:00:19.0/resource1", O_RDWR | O_SYNC)) == -1) {
        perror("Error: open error");
    }

    int map_size = 4096UL;
    ...
    map_base = mmap(0,4096UL , PROT_READ, MAP_SHARED, fd, Register_Values_From_Datasheet);

我有 x86-64 位系统。卡利 Linux 5.7。所以我 Register_Values_From_Datasheet从上面替换数据表中的寄存器偏移值,例如0x00008for STATUS:Device Status Register=from datasheet

22:EINVAL但 mmap() 的 errno在 mmap 调用后具有价值。表示无效的论点。也许我从数据表中读取的偏移值可能必须以其他方式解释。

我在以太网设备的 sys/bus/pci/devices/0000:00:19.0 中的资源文件是这样的

        0x00000000fe400000 0x00000000fe41ffff 0x0000000000040200
        0x00000000fe427000 0x00000000fe427fff 0x0000000000040200
        0x000000000000f060 0x000000000000f07f 0x0000000000040101
        0x0000000000000000 0x0000000000000000 0x0000000000000000
        0x0000000000000000 0x0000000000000000 0x0000000000000000
        0x0000000000000000 0x0000000000000000 0x0000000000000000
        0x0000000000000000 0x0000000000000000 0x0000000000000000
        0x0000000000000000 0x0000000000000000 0x0000000000000000
        0x0000000000000000 0x0000000000000000 0x0000000000000000
        0x0000000000000000 0x0000000000000000 0x0000000000000000
        0x0000000000000000 0x0000000000000000 0x0000000000000000
        0x0000000000000000 0x0000000000000000 0x0000000000000000
        0x0000000000000000 0x0000000000000000 0x0000000000000000

从上面的资源文本文件(resource0)转储显示我的内存映射 IO 从 0x00000000fe400000 开始。所以我认为应该是 mmap (return (void*)=&0x00000000fe400000)= 的返回地址,但我得到类似的东西0xffffffff,errno 是 22。任何人都可以指导我正确的方向来解释偏移量需要如何解释从数据表。此外,通常需要访问哪些寄存器才能获取 pci 以太网设备的数据包。因为我是设备编程的新手。

4

1 回答 1

1

Resource0 是资源列表,剩余的 Resource1 .. ResourceN 是寄存器所在的实际内存区域。(参考:https ://techpubs.jurassic.nl/manuals/linux/developer/REACTLINUX_PG/sgi_html/ch07.html )

偏移量是区域内的偏移量,而不是区域的偏移量。

因此,您通常会映射 region1 的整个空间 - 在您的情况下为 128KB,因为:0x00000000fe41ffff - 0x00000000fe400000 . (您也可以检查 /proc/iomem 进行确认)

map_base = mmap(0,32*4096UL , PROT_READ, MAP_SHARED, fd, 0); 

编辑:mmap 的签名是:

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

如果您指定超过文件大小的长度或偏移量,您会得到 EINVAL:来自 Linux 手册页:

EINVAL We don't like addr, length, or offset (e.g., they are too large, or not aligned on a page boundary).

您可能最终会将 map_base 转换为 uint32_t 数组(如果所有寄存器都是 32 位)并使用: map_base_as_int[8/4]索引到寄存器空间。

第一个障碍是获取只读数据(例如,MAC 地址等)。

一旦您真正想要发送和接收数据包,您将需要物理地址 - DPDK 代码处理这个(以相当复杂的方式),但是您可以使用 GRUB 参数切出物理内存并安全地使用它......


另一种方法是使用上面的偏移量在'/dev/mem'上使用mmap fe400000)无论如何你以后都需要它来访问物理内存(并且你需要确保你的内核是为访问而编译的——一些锁定的内核是't)

于 2021-01-08T15:36:27.983 回答