IORESOURCE_MEM IORESOURCE_IO

 

 

 

/* Get pci port io resources described by bar #pci_bar in uio resource n. */
static int
igbuio_pci_setup_ioport(struct pci_dev *dev, struct uio_info *info,
		int n, int pci_bar, const char *name)
{
	unsigned long addr, len;

	if (sizeof(info->port) / sizeof(info->port[0]) <= n)
		return -EINVAL;

	addr = pci_resource_start(dev, pci_bar);
	len = pci_resource_len(dev, pci_bar);
	if (addr == 0 || len == 0)
		return -EINVAL;

	info->port[n].name = name;
	info->port[n].start = addr;
	info->port[n].size = len;
	info->port[n].porttype = UIO_PORT_X86;

	return 0;
}




static int
igbuio_setup_bars(struct pci_dev *dev, struct uio_info *info)
{
    int i, iom, iop, ret;
    unsigned long flags;
    static const char *bar_names[PCI_STD_RESOURCE_END + 1]  = {
        "BAR0",
        "BAR1",
        "BAR2",
        "BAR3",
        "BAR4",
        "BAR5",
    };

    iom = 0;
    iop = 0;
        //遍历PCI设备的6个BAR
    for (i = 0; i < ARRAY_SIZE(bar_names); i++) {
                //PCI BAR空间不等于0且起始地址不等于0,认为为有效BAR
        if (pci_resource_len(dev, i) != 0 &&
                pci_resource_start(dev, i) != 0) {
                        //拿到BAR的标识,如果为0x00000200则为内存空间
            flags = pci_resource_flags(dev, i);
            if (flags & IORESOURCE_MEM) {
                                //对内存空间的PCI BAR进行映射
                ret = igbuio_pci_setup_iomem(dev, info, iom,
                                 i, bar_names[i]);
                if (ret != 0)
                    return ret;
                iom++;
                        //IO空间不再讨论范围内
            } else if (flags & IORESOURCE_IO) {
                ret = igbuio_pci_setup_ioport(dev, info, iop,
                                  i, bar_names[i]);
                if (ret != 0)
                    return ret;
                iop++;
            }
        }
    }

    return (iom != 0 || iop != 0) ? ret : -ENOENT;
}

//对内存BAR进行映射,以及填充数据结构
static int
igbuio_pci_setup_iomem(struct pci_dev *dev, struct uio_info *info,
               int n, int pci_bar, const char *name)
{
    unsigned long addr, len;
    void *internal_addr;

    if (n >= ARRAY_SIZE(info->mem))
        return -EINVAL;
        //拿到PCI BAR的起始地址
    addr = pci_resource_start(dev, pci_bar);
        //拿到PCI BAR的长度
    len = pci_resource_len(dev, pci_bar);
    if (addr == 0 || len == 0)
        return -1;
        //wc_activate为igb_uio.ko的参数,默认为0,会进入if条件
    if (wc_activate == 0) {
                //对PCI BAR进行ioremap,映射到内核空间,得到可以在内核空间映射后的PCI BAR地址,虽然没什么用,因为igb_uio完全不需要操作PCI设备,因此获得此地址意义不大
        internal_addr = ioremap(addr, len);
        if (internal_addr == NULL)
            return -1;
    } else {
        internal_addr = NULL;
    }
        //填充数据结构
    info->mem[n].name = name; //PCI  BAR名,例如BAR0、BAR1
    info->mem[n].addr = addr; //PCI BAR起始地址,物理地址
    info->mem[n].internal_addr = internal_addr; //经过ioremap映射后的PCI BAR,可以供内核空间访问
    info->mem[n].size = len; //PCI BAR长度
    info->mem[n].memtype = UIO_MEM_PHYS; //PCI BAR类型,为内存BAR
    return 0;
}

 

posted on 2020-09-12 22:51  tycoon3  阅读(679)  评论(0编辑  收藏  举报

导航