dpdk ioport mmap

初始化分析

一个设备驱动要实现的功能根据实际需要可能千差万别,但是究其本质来说无非两件事情:一个是内存的操作,另外一个就是中断的处理。Igb_uio驱动和igb驱动都是网卡这个PCI设备的驱动,相同点就是要使能PCI设备,分配内存等,不同的就在于对内存和中断的处理方式的差异。

下面看下igb_uio驱动与igb驱动相比的probe函数的不同之处:

◆记录设备的资源

igb_uio模块遍历此PCI设备BAR空间,对应于类型为存储器空间IORESOURCE_MEM的BAR,将其物理地址、大小等信息保存到uio_info结构的mem数组中之中;类型为寄存器空间IORESOURCE_IO的BAR,将其物理地址、大小等信息保存到uio_info结构的port数组中。

从上图可知,此网卡PCI设备有三个BAR空间,BAR0类型为存储器空间,物理地址为0xfbd00000,大小为128K;BAR2类型为寄存器空间,物理地址为0xb000,大小为32字节;BAR3类型为存储器空间,物理地址为0xfbd40000,大小为16K。

Igb驱动也会遍历BAR空间,但是它不会记录空间的物理地址,而是调用ioremap函数将物理地址映射为虚拟地址,驱动在内核态读写操作映射出来的虚拟地址。

/** IO resource type: */
#define IORESOURCE_IO 0x00000100
#define IORESOURCE_MEM 0x00000200

 424 pci_uio_ioport_map(struct rte_pci_device *dev, int bar,
    425                    struct rte_pci_ioport *p)
    426 {
    427         FILE *f;
    428         char buf[BUFSIZ];
    429         char filename[PATH_MAX];
    430         uint64_t phys_addr, end_addr, flags;
    431         int fd, i;
    432         void *addr;
    433 
    434         /* open and read addresses of the corresponding resource in sysfs */
    435         snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource",
    436                 rte_pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,
    437                 dev->addr.devid, dev->addr.function);
    438         f = fopen(filename, "r");
    439         if (f == NULL) {
    440                 RTE_LOG(ERR, EAL, "Cannot open sysfs resource: %s
",
    441                         strerror(errno));
    442                 return -1;
    443         }
    444         for (i = 0; i < bar + 1; i++) {
    445                 if (fgets(buf, sizeof(buf), f) == NULL) {
    446                         RTE_LOG(ERR, EAL, "Cannot read sysfs resource
");
    447                         goto error;
    448                 }
    449         }
    450         if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr,
    451                         &end_addr, &flags) < 0)
    452                 goto error;
    453         if ((flags & IORESOURCE_IO) == 0) {
454                 RTE_LOG(ERR, EAL, "BAR %d is not an IO resource
", bar);
    455                 goto error;
    456         }
    457         snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT "/resource%d",
    458                 rte_pci_get_sysfs_path(), dev->addr.domain, dev->addr.bus,
    459                 dev->addr.devid, dev->addr.function, bar);
    460 
    461         /* mmap the pci resource */
    462         fd = open(filename, O_RDWR);
    463         if (fd < 0) {
    464                 RTE_LOG(ERR, EAL, "Cannot open %s: %s
", filename,
    465                         strerror(errno));
    466                 goto error;
    467         }
    468         addr = mmap(NULL, end_addr + 1, PROT_READ | PROT_WRITE,
    469                 MAP_SHARED, fd, 0);
    470         close(fd);
    471         if (addr == MAP_FAILED) {
    472                 RTE_LOG(ERR, EAL, "Cannot mmap IO port resource: %s
",
    473                         strerror(errno));
    474                 goto error;
    475         }
    476 
    477         /* strangely, the base address is mmap addr + phys_addr */
    478         p->base = (uintptr_t)addr + phys_addr;
    479         p->len = end_addr + 1;
    480         RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%"PRIx64"
", p->base);
    481         fclose(f);
    482 
    483         return 0;
484 
    485 error:
    486         fclose(f);
    487         return -1;
    488 }

rte_pci_ioport_map

read & write

原文地址:https://www.cnblogs.com/dream397/p/13632686.html