diff options
Diffstat (limited to 'include/linux/pci.h')
-rw-r--r-- | include/linux/pci.h | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/include/linux/pci.h b/include/linux/pci.h new file mode 100644 index 0000000000..6caed01c99 --- /dev/null +++ b/include/linux/pci.h @@ -0,0 +1,297 @@ +/* + * pci.h + * + * PCI defines and function prototypes + * Copyright 1994, Drew Eckhardt + * Copyright 1997--1999 Martin Mares <mj@ucw.cz> + * + * For more information, please consult the following manuals (look at + * http://www.pcisig.com/ for how to get them): + * + * PCI BIOS Specification + * PCI Local Bus Specification + * PCI to PCI Bridge Specification + * PCI System Design Guide + */ +#ifndef LINUX_PCI_H +#define LINUX_PCI_H + +#include <linux/mod_devicetable.h> + +#include <linux/pci_regs.h> +#include <linux/types.h> +#include <linux/ioport.h> +#include <linux/list.h> +#include <linux/compiler.h> +#include <driver.h> +#include <errno.h> +#include <io.h> + +#include <linux/pci_ids.h> + + +/* + * The PCI interface treats multi-function devices as independent + * devices. The slot/function address of each device is encoded + * in a single byte as follows: + * + * 7:3 = slot + * 2:0 = function + */ +#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) +#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) +#define PCI_FUNC(devfn) ((devfn) & 0x07) + +/* + * For PCI devices, the region numbers are assigned this way: + */ +enum { + /* #0-5: standard PCI resources */ + PCI_STD_RESOURCES, + PCI_STD_RESOURCE_END = 5, + + /* #6: expansion ROM resource */ + PCI_ROM_RESOURCE, + + /* device specific resources */ +#ifdef CONFIG_PCI_IOV + PCI_IOV_RESOURCES, + PCI_IOV_RESOURCE_END = PCI_IOV_RESOURCES + PCI_SRIOV_NUM_BARS - 1, +#endif + + /* resources assigned to buses behind the bridge */ +#define PCI_BRIDGE_RESOURCE_NUM 4 + + PCI_BRIDGE_RESOURCES, + PCI_BRIDGE_RESOURCE_END = PCI_BRIDGE_RESOURCES + + PCI_BRIDGE_RESOURCE_NUM - 1, + + /* total resources associated with a PCI device */ + PCI_NUM_RESOURCES, + + /* preserve this for compatibility */ + DEVICE_COUNT_RESOURCE = PCI_NUM_RESOURCES, +}; + +/* + * Error values that may be returned by PCI functions. + */ +#define PCIBIOS_SUCCESSFUL 0x00 +#define PCIBIOS_FUNC_NOT_SUPPORTED 0x81 +#define PCIBIOS_BAD_VENDOR_ID 0x83 +#define PCIBIOS_DEVICE_NOT_FOUND 0x86 +#define PCIBIOS_BAD_REGISTER_NUMBER 0x87 +#define PCIBIOS_SET_FAILED 0x88 +#define PCIBIOS_BUFFER_TOO_SMALL 0x89 + +/* + * The pci_dev structure is used to describe PCI devices. + */ +struct pci_dev { + struct list_head bus_list; /* node in per-bus list */ + struct pci_bus *bus; /* bus this device is on */ + struct pci_bus *subordinate; /* bus this device bridges to */ + + void *sysdata; /* hook for sys-specific extension */ + struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */ + struct pci_slot *slot; /* Physical slot this device is in */ + + struct device_d dev; + + unsigned int devfn; /* encoded device & function index */ + unsigned short vendor; + unsigned short device; + unsigned short subsystem_vendor; + unsigned short subsystem_device; + unsigned int class; /* 3 bytes: (base,sub,prog-if) */ + u8 revision; /* PCI revision, low byte of class word */ + u8 hdr_type; /* PCI header type (`multi' flag masked out) */ + + struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */ + + /* Base registers for this device, can be adjusted by + * pcibios_fixup() as necessary. + */ + unsigned long base_address[6]; + unsigned long rom_address; +}; +#define to_pci_dev(dev) container_of(dev, struct pci_dev, dev) + +struct pci_bus { + struct list_head node; /* node in list of buses */ + struct list_head children; /* list of child buses */ + struct list_head devices; /* list of devices on this bus */ + struct list_head slots; /* list of slots on this bus */ + struct resource *resource[PCI_BRIDGE_RESOURCE_NUM]; + struct list_head resources; /* address space routed to this bus */ + + struct pci_ops *ops; /* configuration access functions */ + void *sysdata; /* hook for sys-specific extension */ + struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */ + + unsigned char number; /* bus number */ + unsigned char primary; /* number of primary bridge */ + unsigned char secondary; /* number of secondary bridge */ + unsigned char subordinate; /* max number of subordinate buses */ + + char name[48]; +}; + +/* Low-level architecture-dependent routines */ + +struct pci_ops { + int (*read)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val); + int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val); + + /* return memory address for pci resource */ + int (*res_start)(struct pci_bus *bus, resource_size_t res_addr); +}; + +extern struct pci_ops *pci_ops; + +/* + * Each pci channel is a top-level PCI bus seem by CPU. A machine with + * multiple PCI channels may have multiple PCI host controllers or a + * single controller supporting multiple channels. + */ +struct pci_controller { + struct pci_controller *next; + struct pci_bus *bus; + + struct pci_ops *pci_ops; + struct resource *mem_resource; + unsigned long mem_offset; + struct resource *io_resource; + unsigned long io_offset; + unsigned long io_map_base; + + unsigned int index; + + /* Optional access methods for reading/writing the bus number + of the PCI controller */ + int (*get_busno)(void); + void (*set_busno)(int busno); +}; + +struct pci_driver { + struct list_head node; + const char *name; + const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */ + int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ + void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ + struct driver_d driver; +}; + +#define to_pci_driver(drv) container_of(drv, struct pci_driver, driver) + +/* these helpers provide future and backwards compatibility + * for accessing popular PCI BAR info */ +#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) + +/** + * DEFINE_PCI_DEVICE_TABLE - macro used to describe a pci device table + * @_table: device table name + * + * This macro is used to create a struct pci_device_id array (a device table) + * in a generic manner. + */ +#define DEFINE_PCI_DEVICE_TABLE(_table) \ + const struct pci_device_id _table[] + +/** + * PCI_DEVICE - macro used to describe a specific pci device + * @vend: the 16 bit PCI Vendor ID + * @dev: the 16 bit PCI Device ID + * + * This macro is used to create a struct pci_device_id that matches a + * specific device. The subvendor and subdevice fields will be set to + * PCI_ANY_ID. + */ +#define PCI_DEVICE(vend, dev) \ + .vendor = (vend), .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID + +/** + * PCI_DEVICE_CLASS - macro used to describe a specific pci device class + * @dev_class: the class, subclass, prog-if triple for this device + * @dev_class_mask: the class mask for this device + * + * This macro is used to create a struct pci_device_id that matches a + * specific PCI class. The vendor, device, subvendor, and subdevice + * fields will be set to PCI_ANY_ID. + */ +#define PCI_DEVICE_CLASS(dev_class, dev_class_mask) \ + .class = (dev_class), .class_mask = (dev_class_mask), \ + .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID + +/** + * PCI_VDEVICE - macro used to describe a specific pci device in short form + * @vend: the vendor name + * @dev: the 16 bit PCI Device ID + * + * This macro is used to create a struct pci_device_id that matches a + * specific PCI device. The subvendor, and subdevice fields will be set + * to PCI_ANY_ID. The macro allows the next field to follow as the device + * private data. + */ + +#define PCI_VDEVICE(vend, dev) \ + .vendor = PCI_VENDOR_ID_##vend, .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0 + +int pci_register_driver(struct pci_driver *pdrv); +int pci_register_device(struct pci_dev *pdev); + +extern struct list_head pci_root_buses; /* list of all known PCI buses */ + +extern unsigned int pci_scan_bus(struct pci_bus *bus); +extern void register_pci_controller(struct pci_controller *hose); + +int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn, + int where, u8 *val); +int pci_bus_read_config_word(struct pci_bus *bus, unsigned int devfn, + int where, u16 *val); +int pci_bus_read_config_dword(struct pci_bus *bus, unsigned int devfn, + int where, u32 *val); +int pci_bus_write_config_byte(struct pci_bus *bus, unsigned int devfn, + int where, u8 val); +int pci_bus_write_config_word(struct pci_bus *bus, unsigned int devfn, + int where, u16 val); +int pci_bus_write_config_dword(struct pci_bus *bus, unsigned int devfn, + int where, u32 val); + +static inline int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val) +{ + return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val); +} +static inline int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val) +{ + return pci_bus_read_config_word(dev->bus, dev->devfn, where, val); +} +static inline int pci_read_config_dword(const struct pci_dev *dev, int where, + u32 *val) +{ + return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val); +} +static inline int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val) +{ + return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val); +} +static inline int pci_write_config_word(const struct pci_dev *dev, int where, u16 val) +{ + return pci_bus_write_config_word(dev->bus, dev->devfn, where, val); +} +static inline int pci_write_config_dword(const struct pci_dev *dev, int where, + u32 val) +{ + return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val); +} + +void pci_set_master(struct pci_dev *dev); +void pci_clear_master(struct pci_dev *dev); +int pci_enable_device(struct pci_dev *dev); + +extern void __iomem *pci_iomap(struct pci_dev *dev, int bar); + +#endif /* LINUX_PCI_H */ |