PCI总线---深入理解PCI总线

补充:

PCI/PCIe基础——配置空间:

http://blog.csdn.net/jiangwei0512/article/details/51603525


8.1 深入理解PCI总线

8.1.1 PCI设备工作原理

8.1.2 PCI总线域

8.1.3 PCI资源管理

        为了管理PCI设备的I/O端口 和 I/O 内存, 内核定义了一个resource 结构:

代表I/O端口的resource :

struct resource ioport_resource = {
	.name	= "PCI IO",
	.start	= 0,
	.end	= IO_SPACE_LIMIT,
	.flags	= IORESOURCE_IO,
};

        ioport_resource起始地址为 0 ,结束地址 0xffff , 这个变量定义了全部的I/O端口地址空间,每个PCI设备新加入系统,都要检查它的配置空间的I/O端口的结束地址是否大于0xffff ,和现存的设备是否冲突,是否可以插入I/O端口地址空间。

I/O内存的resource结构:

struct resource iomem_resource = {
	.name	= "PCI mem",
	.start	= 0,
	.end	= -1,
	.flags	= IORESOURCE_MEM,
};
EXPORT_SYMBOL(iomem_resource);

        I/O内存需要映射到 主机内存地址空间,所以结束地址为-1。 当PCI设备加入系统的时候,检查它的配置空间的I/O内存和其他设备是否冲突,是否可以插入I/O内存地址空间。


8.1.4 PCI配置空间读取和设置

        第3章,PCI设备的读取通过I/O指令读一个特殊的I/O端口空间来完成。内核提供了一个pci_raw_ops 结构来控制配置空间的读写。这个结构的读写和函数通常被设置为pci_confl_read函数 和 pci_confl_write 函数,通过它们执行对PCI配置空间的读写。

/include/linux/pci.h

struct pci_raw_ops {
	int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
						int reg, int len, u32 *val);
	int (*write)(unsigned int domain, unsigned int bus, unsigned int devfn,
						int reg, int len, u32 val);
};

        read 和 write 函数指针的调用进行读写操作;

分析pci_confl_read函数对PCI配置空间的读取过程如下所示:

static int pci_conf1_read(unsigned int seg, unsigned int bus,
			  unsigned int devfn, int reg, int len, u32 *value)
{
	unsigned long flags;

	if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
		*value = -1;
		return -EINVAL;
	}

	raw_spin_lock_irqsave(&pci_config_lock, flags);

	outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);

	switch (len) {
	case 1:
		*value = inb(0xCFC + (reg & 3));
		break;
	case 2:
		*value = inw(0xCFC + (reg & 2));
		break;
	case 4:
		*value = inl(0xCFC);
		break;
	}

	raw_spin_unlock_irqrestore(&pci_config_lock, flags);

	return 0;
}

        pci_conf1_read函数首先往I/O端口 0xCF8 写入一个PCI地址,然后从I/O端口 0xCFC读取该地址的配置信息。




你可能感兴趣的:(PCI总线---深入理解PCI总线)