簡體   English   中英

讀取內存映射的 IO 寄存器如何(來自數據表)並在 mmap 中使用它們

[英]reading Memory-Mapped IO registers How to (from datasheet) and using them in mmap

我有帶有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 ,例如0x00008STATUS:Device Status Register =from datasheet

但是 mmap() 的 errno 在 mmap 調用后具有值22:EINVAL 表示無效的論點。 也許我從數據表中讀取的偏移值可能必須以其他方式解釋。

我在以太網設備的 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 以太網設備的數據包。 因為我是設備編程的新手。

Resource0 是資源列表,剩余的 Resource1.. ResourceN 是寄存器所在的實際 memory 區域。 (參考: https://techpubs.jurassic.nl/manuals/linux/developer/REACTLINUX_PG/sgi_html/ch07.html

偏移量是區域內的偏移量,而不是區域的偏移量。

所以你通常會 map 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 參數切出物理 memory 並安全使用它......


另一種方法是在 '/dev/mem' 上使用 mmap 使用fe400000上方的偏移量)無論如何,您將需要這個用於物理 memory 訪問(並且您需要確保您的 kernel 已編譯用於訪問 - 一些鎖定的內核不是)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM