📄 pci.c
字号:
/* * pci.c - Low-Level PCI Access in IA-64 * * Derived from bios32.c of i386 tree. * Copyright (C) 2002, 2003 Hewlett-Packard Co * David Mosberger-Tang <davidm@hpl.hp.com> * Bjorn Helgaas <bjorn_helgaas@hp.com> * * Note: Above list of copyright holders is incomplete... */#include <linux/config.h>#include <linux/acpi.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/smp_lock.h>#include <linux/spinlock.h>#include <asm/machvec.h>#include <asm/mca.h>#include <asm/page.h>#include <asm/segment.h>#include <asm/system.h>#include <asm/io.h>#include <asm/sal.h>#ifdef CONFIG_SMP# include <asm/smp.h>#endif#include <asm/irq.h>#undef DEBUG#define DEBUG#ifdef DEBUG#define DBG(x...) printk(x)#else#define DBG(x...)#endifstruct pci_fixup pcibios_fixups[1];struct pci_ops *pci_root_ops;int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value);int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value);/* * Low-level SAL-based PCI configuration access functions. Note that SAL * calls are already serialized (via sal_lock), so we don't need another * synchronization mechanism here. */#define PCI_SAL_ADDRESS(seg, bus, dev, fn, reg) \ ((u64)(seg << 24) | (u64)(bus << 16) | \ (u64)(dev << 11) | (u64)(fn << 8) | (u64)(reg))static intpci_sal_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value){ int result = 0; u64 data = 0; if (!value || (seg > 255) || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) return -EINVAL; result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(seg, bus, dev, fn, reg), len, &data); *value = (u32) data; return result;}static intpci_sal_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value){ if ((seg > 255) || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) return -EINVAL; return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(seg, bus, dev, fn, reg), len, value);}static intpci_sal_read_config_byte (struct pci_dev *dev, int where, u8 *value){ int result = 0; u32 data = 0; if (!value) return -EINVAL; result = pci_sal_read(PCI_SEGMENT(dev), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 1, &data); *value = (u8) data; return result;}static intpci_sal_read_config_word (struct pci_dev *dev, int where, u16 *value){ int result = 0; u32 data = 0; if (!value) return -EINVAL; result = pci_sal_read(PCI_SEGMENT(dev), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 2, &data); *value = (u16) data; return result;}static intpci_sal_read_config_dword (struct pci_dev *dev, int where, u32 *value){ if (!value) return -EINVAL; return pci_sal_read(PCI_SEGMENT(dev), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 4, value);}static intpci_sal_write_config_byte (struct pci_dev *dev, int where, u8 value){ return pci_sal_write(PCI_SEGMENT(dev), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 1, value);}static intpci_sal_write_config_word (struct pci_dev *dev, int where, u16 value){ return pci_sal_write(PCI_SEGMENT(dev), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 2, value);}static intpci_sal_write_config_dword (struct pci_dev *dev, int where, u32 value){ return pci_sal_write(PCI_SEGMENT(dev), dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn), where, 4, value);}struct pci_ops pci_sal_ops = { pci_sal_read_config_byte, pci_sal_read_config_word, pci_sal_read_config_dword, pci_sal_write_config_byte, pci_sal_write_config_word, pci_sal_write_config_dword};/* * Initialization. Uses the SAL interface */static struct pci_controller *alloc_pci_controller (int seg){ struct pci_controller *controller; controller = kmalloc(sizeof(*controller), GFP_KERNEL); if (!controller) return NULL; memset(controller, 0, sizeof(*controller)); controller->segment = seg; return controller;}static struct pci_bus *scan_root_bus (int bus, struct pci_ops *ops, void *sysdata){ struct pci_bus *b; /* * We know this is a new root bus we haven't seen before, so * scan it, even if we've seen the same bus number in a different * segment. */ b = kmalloc(sizeof(*b), GFP_KERNEL); if (!b) return NULL; memset(b, 0, sizeof(*b)); INIT_LIST_HEAD(&b->children); INIT_LIST_HEAD(&b->devices); list_add_tail(&b->node, &pci_root_buses); b->number = b->secondary = bus; b->resource[0] = &ioport_resource; b->resource[1] = &iomem_resource; b->sysdata = sysdata; b->ops = ops; b->subordinate = pci_do_scan_bus(b); return b;}static intalloc_resource (char *name, struct resource *root, unsigned long start, unsigned long end, unsigned long flags){ struct resource *res; res = kmalloc(sizeof(*res), GFP_KERNEL); if (!res) return -ENOMEM; memset(res, 0, sizeof(*res)); res->name = name; res->start = start; res->end = end; res->flags = flags; if (request_resource(root, res)) return -EBUSY; return 0;}static u64add_io_space (struct acpi_resource_address64 *addr){ u64 offset; int sparse = 0; int i; if (addr->address_translation_offset == 0) return IO_SPACE_BASE(0); /* part of legacy IO space */ if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) sparse = 1; offset = (u64) ioremap(addr->address_translation_offset, 0); for (i = 0; i < num_io_spaces; i++) if (io_space[i].mmio_base == offset && io_space[i].sparse == sparse) return IO_SPACE_BASE(i); if (num_io_spaces == MAX_IO_SPACES) { printk("Too many IO port spaces\n"); return ~0; } i = num_io_spaces++; io_space[i].mmio_base = offset; io_space[i].sparse = sparse; return IO_SPACE_BASE(i);}static acpi_statuscount_window (struct acpi_resource *resource, void *data){ unsigned int *windows = (unsigned int *) data; struct acpi_resource_address64 addr; acpi_status status; status = acpi_resource_to_address64(resource, &addr); if (ACPI_SUCCESS(status)) if (addr.resource_type == ACPI_MEMORY_RANGE || addr.resource_type == ACPI_IO_RANGE) (*windows)++; return AE_OK;}struct pci_root_info { struct pci_controller *controller; char *name;};static acpi_statusadd_window (struct acpi_resource *res, void *data){ struct pci_root_info *info = (struct pci_root_info *) data; struct pci_window *window; struct acpi_resource_address64 addr; acpi_status status; unsigned long flags, offset = 0; struct resource *root; status = acpi_resource_to_address64(res, &addr); if (ACPI_SUCCESS(status)) { if (!addr.address_length) return AE_OK; if (addr.resource_type == ACPI_MEMORY_RANGE) { flags = IORESOURCE_MEM; root = &iomem_resource; offset = addr.address_translation_offset; } else if (addr.resource_type == ACPI_IO_RANGE) { flags = IORESOURCE_IO; root = &ioport_resource; offset = add_io_space(&addr); if (offset == ~0) return AE_OK; } else return AE_OK; window = &info->controller->window[info->controller->windows++]; window->resource.flags |= flags; window->resource.start = addr.min_address_range; window->resource.end = addr.max_address_range; window->offset = offset; if (alloc_resource(info->name, root, addr.min_address_range + offset,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -