查看PCIE设备的BAR
通过cpu spc查看PCIE配置寄存器存放信息,可以看到在**0x80000000L偏移10h处便是映射的内存地址**:
这个地址有多种方法查看,在RU下可以通过F6直接打开对应设备的寄存器基地址查看,也可以通过编程IO方式查看,主要是要知道base address + bus + dev +fun。再根据addr = Ox80000000 L | (bus<<16) | (dev<<11) | (fun<<8)|offset 计算。
RU下查看
通过打印pci的配置空间查看
在ubuntu下可以通过命令查看pcie设备内存映射的地址
lspci -vv
访问I211的控制寄存器、状态寄存器等
读取某一个PCIe设备(比如网卡)的控制寄存器、状态寄存器。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>#define I211_BAR0_ADDR 0xf7500000
#define I211_BAR0_SIZE (128 * 1024) // 128KB// I211寄存器偏移
#define I211_REG_CTRL 0x0000 // Device Control
#define I211_REG_STATUS 0x0008 // Device Status
#define I211_REG_EERD 0x0014 // EEPROM Read
#define I211_REG_ICR 0x00C0 // Interrupt Cause Read
#define I211_REG_MAC_L 0x5400 // MAC地址低32位
#define I211_REG_MAC_H 0x5404 // MAC地址高16位// 寄存器访问
uint32_t read_reg32(volatile void *base, uint32_t offset) {return *(volatile uint32_t*)((uint8_t*)base + offset);
}void write_reg32(volatile void *base, uint32_t offset, uint32_t value) {*(volatile uint32_t*)((uint8_t*)base + offset) = value;
}int main() {int fd;void *base_addr;// 打开物理内存fd = open("/dev/mem", O_RDWR | O_SYNC);if (fd == -1) {printf("Error opening /dev/mem: %s\n", strerror(errno));return -1;}// 映射BAR0地址空间base_addr = mmap(NULL, I211_BAR0_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, I211_BAR0_ADDR);if (base_addr == MAP_FAILED) {printf("Error mapping memory: %s\n", strerror(errno));close(fd);return -1;}// 读取控制寄存器uint32_t ctrl = read_reg32(base_addr, I211_REG_CTRL);printf("Control Register (0x%04X): 0x%08X\n", I211_REG_CTRL, ctrl);// 读取状态寄存器uint32_t status = read_reg32(base_addr, I211_REG_STATUS);printf("Status Register (0x%04X): 0x%08X\n", I211_REG_STATUS, status);// 读取MAC地址uint32_t mac_l = read_reg32(base_addr, I211_REG_MAC_L);uint32_t mac_h = read_reg32(base_addr, I211_REG_MAC_H);printf("MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\n",(uint8_t)(mac_l),(uint8_t)(mac_l >> 8),(uint8_t)(mac_l >> 16),(uint8_t)(mac_l >> 24),(uint8_t)(mac_h),(uint8_t)(mac_h >> 8));// 清理munmap(base_addr, I211_BAR0_SIZE);close(fd);return 0;
}
编译运行
gcc -o GetNetInfo GetNetInfo.c
./GetNetInfo