- 论坛徽章:
- 36
|
在arch/i386/pci/direct.c中定义了访问PCI配置空间的方法,这个直接对端口进行读写,应该是比较低层的实现
- /*
- * direct.c - Low-level direct PCI config space access
- */
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/dmi.h>
- #include "pci.h"
- /*
- * Functions for accessing PCI configuration space with type 1 accesses
- */
- #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
- (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
- 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 > 255)) {
- *value = -1;
- return -EINVAL;
- }
- 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;
- }
- spin_unlock_irqrestore(&pci_config_lock, flags);
- return 0;
- }
- int pci_conf1_write(unsigned int seg, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 value)
- {
- unsigned long flags;
- if ((bus > 255) || (devfn > 255) || (reg > 255))
- return -EINVAL;
- spin_lock_irqsave(&pci_config_lock, flags);
- outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
- switch (len) {
- case 1:
- outb((u8)value, 0xCFC + (reg & 3));
- break;
- case 2:
- outw((u16)value, 0xCFC + (reg & 2));
- break;
- case 4:
- outl((u32)value, 0xCFC);
- break;
- }
- spin_unlock_irqrestore(&pci_config_lock, flags);
- return 0;
- }
- #undef PCI_CONF1_ADDRESS
- struct pci_raw_ops pci_direct_conf1 = {
- .read = pci_conf1_read,
- .write = pci_conf1_write,
- };
- /*
- * Functions for accessing PCI configuration space with type 2 accesses
- */
- #define PCI_CONF2_ADDRESS(dev, reg) (u16)(0xC000 | (dev << 8) | reg)
- static int pci_conf2_read(unsigned int seg, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 *value)
- {
- unsigned long flags;
- int dev, fn;
- if ((bus > 255) || (devfn > 255) || (reg > 255)) {
- *value = -1;
- return -EINVAL;
- }
- dev = PCI_SLOT(devfn);
- fn = PCI_FUNC(devfn);
- if (dev & 0x10)
- return PCIBIOS_DEVICE_NOT_FOUND;
- spin_lock_irqsave(&pci_config_lock, flags);
- outb((u8)(0xF0 | (fn << 1)), 0xCF8);
- outb((u8)bus, 0xCFA);
- switch (len) {
- case 1:
- *value = inb(PCI_CONF2_ADDRESS(dev, reg));
- break;
- case 2:
- *value = inw(PCI_CONF2_ADDRESS(dev, reg));
- break;
- case 4:
- *value = inl(PCI_CONF2_ADDRESS(dev, reg));
- break;
- }
- outb(0, 0xCF8);
- spin_unlock_irqrestore(&pci_config_lock, flags);
- return 0;
- }
- static int pci_conf2_write(unsigned int seg, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 value)
- {
- unsigned long flags;
- int dev, fn;
- if ((bus > 255) || (devfn > 255) || (reg > 255))
- return -EINVAL;
- dev = PCI_SLOT(devfn);
- fn = PCI_FUNC(devfn);
- if (dev & 0x10)
- return PCIBIOS_DEVICE_NOT_FOUND;
- spin_lock_irqsave(&pci_config_lock, flags);
- outb((u8)(0xF0 | (fn << 1)), 0xCF8);
- outb((u8)bus, 0xCFA);
- switch (len) {
- case 1:
- outb((u8)value, PCI_CONF2_ADDRESS(dev, reg));
- break;
- case 2:
- outw((u16)value, PCI_CONF2_ADDRESS(dev, reg));
- break;
- case 4:
- outl((u32)value, PCI_CONF2_ADDRESS(dev, reg));
- break;
- }
- outb(0, 0xCF8);
- spin_unlock_irqrestore(&pci_config_lock, flags);
- return 0;
- }
- #undef PCI_CONF2_ADDRESS
- static struct pci_raw_ops pci_direct_conf2 = {
- .read = pci_conf2_read,
- .write = pci_conf2_write,
- };
复制代码 |
|