Files
chrg/rt-thread/components/drivers/include/drivers/pci.h
T
2025-08-16 22:58:22 +08:00

608 lines
20 KiB
C

/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-08-25 GuEe-GUI first version
*/
#ifndef __PCI_H__
#define __PCI_H__
#include <rtdef.h>
#include <bitmap.h>
#include <ioremap.h>
#include <drivers/ofw.h>
#include <drivers/pic.h>
#include <drivers/core/dm.h>
#include <drivers/core/driver.h>
#include "../../pci/pci_ids.h"
#include "../../pci/pci_regs.h"
#define RT_PCI_INTX_PIN_MAX 4
#define RT_PCI_BAR_NR_MAX 6
#define RT_PCI_DEVICE_MAX 32
#define RT_PCI_FUNCTION_MAX 8
#define RT_PCI_FIND_CAP_TTL 48
/*
* 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 RT_PCI_DEVID(bus, devfn) ((((rt_uint16_t)(bus)) << 8) | (devfn))
#define RT_PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
#define RT_PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
#define RT_PCI_FUNC(devfn) ((devfn) & 0x07)
#define PCIE_LINK_STATE_L0S RT_BIT(0)
#define PCIE_LINK_STATE_L1 RT_BIT(1)
#define PCIE_LINK_STATE_CLKPM RT_BIT(2)
#define PCIE_LINK_STATE_L1_1 RT_BIT(3)
#define PCIE_LINK_STATE_L1_2 RT_BIT(4)
#define PCIE_LINK_STATE_L1_1_PCIPM RT_BIT(5)
#define PCIE_LINK_STATE_L1_2_PCIPM RT_BIT(6)
#define PCIE_LINK_STATE_ALL \
( \
PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | \
PCIE_LINK_STATE_CLKPM | \
PCIE_LINK_STATE_L1_1 | PCIE_LINK_STATE_L1_2 | \
PCIE_LINK_STATE_L1_1_PCIPM | PCIE_LINK_STATE_L1_2_PCIPM \
)
struct rt_pci_bus_region
{
rt_uint64_t phy_addr;
rt_uint64_t cpu_addr;
rt_uint64_t size;
rt_uint64_t bus_start;
#define PCI_BUS_REGION_F_NONE 0xffffffff /* PCI no memory */
#define PCI_BUS_REGION_F_MEM 0x00000000 /* PCI memory space */
#define PCI_BUS_REGION_F_IO 0x00000001 /* PCI IO space */
#define PCI_BUS_REGION_F_PREFETCH 0x00000008 /* Prefetchable PCI memory */
rt_ubase_t flags;
};
struct rt_pci_bus_resource
{
rt_ubase_t base;
rt_size_t size;
rt_ubase_t flags;
};
/*
* PCI topology:
*
* +-----+-----+ +-------------+ PCI Bus 0 +------------+ PCI Bus 1
* | RAM | CPU |---------| Host Bridge |--------+-----| PCI Bridge |-----+
* +-----+-----+ +-------------+ | +------------+ | +-------------+
* | +----| End Point 2 |
* +-------------+ +-------------+ | +-------------+ | +-------------+
* | End Point 5 |----+ | End Point 0 |-------+ | End Point 3 |----+
* +-------------+ | +-------------+ | +-------------+ |
* | | |
* +-------------+ | +-------------+ | +-------------+ | +-------------+
* | End Point 6 |----+----| ISA Bridge |-------+-----| End Point 1 | +----| End Point 4 |
* +-------------+ +-------------+ | +-------------+ +-------------+
* |
* +------+ +----------------+ |
* | Port |---------| CardBus Bridge |----+
* +------+ +----------------+
*/
struct rt_pci_bus;
struct rt_pci_device_id
{
#define PCI_ANY_ID (~0)
#define RT_PCI_DEVICE_ID(vend, dev) \
.vendor = (vend), \
.device = (dev), \
.subsystem_vendor = PCI_ANY_ID, \
.subsystem_device = PCI_ANY_ID
#define RT_PCI_DEVICE_CLASS(dev_class, dev_class_mask) \
.vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
.subsystem_vendor = PCI_ANY_ID, \
.subsystem_device = PCI_ANY_ID, \
.class = (dev_class), .class_mask = (dev_class_mask),
rt_uint32_t vendor, device; /* Vendor and device ID or PCI_ANY_ID */
rt_uint32_t subsystem_vendor; /* Subsystem ID's or PCI_ANY_ID */
rt_uint32_t subsystem_device; /* Subsystem ID's or PCI_ANY_ID */
rt_uint32_t class, class_mask; /* (class, subclass, prog-if) triplet */
const void *data;
};
struct rt_pci_device
{
struct rt_device parent;
const char *name;
rt_list_t list;
struct rt_pci_bus *bus;
struct rt_pci_bus *subbus; /* In PCI-to-PCI bridge, 'End Point' or 'Port' is NULL */
const struct rt_pci_device_id *id;
rt_uint32_t devfn; /* Encoded device & function index */
rt_uint16_t vendor;
rt_uint16_t device;
rt_uint16_t subsystem_vendor;
rt_uint16_t subsystem_device;
rt_uint32_t class; /* 3 bytes: (base, sub, prog-if) */
rt_uint8_t revision;
rt_uint8_t hdr_type;
rt_uint8_t max_latency;
rt_uint8_t min_grantl;
rt_uint8_t int_pin;
rt_uint8_t int_line;
rt_uint16_t exp_flags;
rt_uint32_t cfg_size;
void *sysdata;
int irq;
rt_uint8_t pin;
struct rt_pic *intx_pic;
rt_bool_t pm_enabled;
struct rt_pci_bus_resource resource[RT_PCI_BAR_NR_MAX];
struct rt_pci_bus_resource rom;
rt_uint8_t pme_cap;
rt_uint8_t msi_cap;
rt_uint8_t msix_cap;
rt_uint8_t pcie_cap;
rt_uint8_t busmaster:1; /* Is the bus master */
rt_uint8_t multi_function:1; /* Multi-function device */
rt_uint8_t ari_enabled:1; /* Alternative Routing-ID Interpretation */
rt_uint8_t no_msi:1; /* May not use MSI */
rt_uint8_t no_64bit_msi:1; /* May only use 32-bit MSIs */
rt_uint8_t msi_enabled:1; /* MSI enable */
rt_uint8_t msix_enabled:1; /* MSIx enable */
rt_uint8_t broken_intx_masking:1; /* INTx masking can't be used */
rt_uint8_t pme_support:5; /* Bitmask of states from which PME# can be generated */
#ifdef RT_PCI_MSI
void *msix_base;
struct rt_pic *msi_pic;
rt_list_t msi_desc_nodes;
struct rt_spinlock msi_lock;
#endif
};
struct rt_pci_host_bridge
{
struct rt_device parent;
rt_uint32_t domain;
struct rt_pci_bus *root_bus;
const struct rt_pci_ops *ops;
const struct rt_pci_ops *child_ops;
rt_uint32_t bus_range[2];
rt_size_t bus_regions_nr;
struct rt_pci_bus_region *bus_regions;
rt_size_t dma_regions_nr;
struct rt_pci_bus_region *dma_regions;
rt_uint8_t (*irq_slot)(struct rt_pci_device *pdev, rt_uint8_t *pinp);
int (*irq_map)(struct rt_pci_device *pdev, rt_uint8_t slot, rt_uint8_t pin);
void *sysdata;
rt_uint8_t priv[0];
};
#define rt_device_to_pci_host_bridge(dev) rt_container_of(dev, struct rt_pci_host_bridge, parent)
struct rt_pci_ops
{
rt_err_t (*add)(struct rt_pci_bus *bus);
rt_err_t (*remove)(struct rt_pci_bus *bus);
void *(*map)(struct rt_pci_bus *bus, rt_uint32_t devfn, int reg);
rt_err_t (*read)(struct rt_pci_bus *bus,
rt_uint32_t devfn, int reg, int width, rt_uint32_t *value);
rt_err_t (*write)(struct rt_pci_bus *bus,
rt_uint32_t devfn, int reg, int width, rt_uint32_t value);
};
struct rt_pci_bus
{
rt_list_t list;
rt_list_t children_nodes;
rt_list_t devices_nodes;
struct rt_pci_bus *parent;
union
{
/* In PCI-to-PCI bridge, parent is not NULL */
struct rt_pci_device *self;
/* In Host bridge, this is Root bus ('PCI Bus 0') */
struct rt_pci_host_bridge *host_bridge;
};
const struct rt_pci_ops *ops;
char name[48];
char number;
struct rt_spinlock lock;
void *sysdata;
};
struct rt_pci_driver
{
struct rt_driver parent;
const char *name;
const struct rt_pci_device_id *ids;
rt_err_t (*probe)(struct rt_pci_device *pdev);
rt_err_t (*remove)(struct rt_pci_device *pdev);
rt_err_t (*shutdown)(struct rt_pci_device *pdev);
};
struct rt_pci_msix_entry
{
int irq;
int index;
};
enum rt_pci_power
{
RT_PCI_D0,
RT_PCI_D1,
RT_PCI_D2,
RT_PCI_D3HOT,
RT_PCI_D3COLD,
RT_PCI_PME_MAX,
};
void rt_pci_pme_init(struct rt_pci_device *pdev);
void rt_pci_pme_active(struct rt_pci_device *pdev, rt_bool_t enable);
rt_err_t rt_pci_enable_wake(struct rt_pci_device *pci_dev,
enum rt_pci_power state, rt_bool_t enable);
rt_inline rt_bool_t rt_pci_pme_capable(struct rt_pci_device *pdev,
enum rt_pci_power state)
{
if (!pdev->pme_cap)
{
return RT_FALSE;
}
return !!(pdev->pme_support & (1 << state));
}
void rt_pci_msi_init(struct rt_pci_device *pdev);
void rt_pci_msix_init(struct rt_pci_device *pdev);
void rt_pci_set_master(struct rt_pci_device *pdev);
void rt_pci_clear_master(struct rt_pci_device *pdev);
struct rt_pci_host_bridge *rt_pci_host_bridge_alloc(rt_size_t priv_size);
rt_err_t rt_pci_host_bridge_free(struct rt_pci_host_bridge *);
rt_err_t rt_pci_host_bridge_init(struct rt_pci_host_bridge *host_bridge);
rt_err_t rt_pci_host_bridge_probe(struct rt_pci_host_bridge *host_bridge);
struct rt_pci_device *rt_pci_alloc_device(struct rt_pci_bus *bus);
struct rt_pci_device *rt_pci_scan_single_device(struct rt_pci_bus *bus, rt_uint32_t devfn);
rt_err_t rt_pci_setup_device(struct rt_pci_device *pdev);
rt_size_t rt_pci_scan_slot(struct rt_pci_bus *bus, rt_uint32_t devfn);
rt_uint32_t rt_pci_scan_child_buses(struct rt_pci_bus *bus, rt_size_t buses);
rt_uint32_t rt_pci_scan_child_bus(struct rt_pci_bus *bus);
rt_err_t rt_pci_host_bridge_register(struct rt_pci_host_bridge *host_bridge);
rt_err_t rt_pci_scan_root_bus_bridge(struct rt_pci_host_bridge *host_bridge);
rt_err_t rt_pci_host_bridge_remove(struct rt_pci_host_bridge *host_bridge);
rt_err_t rt_pci_bus_remove(struct rt_pci_bus *bus);
rt_err_t rt_pci_device_remove(struct rt_pci_device *pdev);
rt_uint32_t rt_pci_domain(struct rt_pci_device *pdev);
rt_uint8_t rt_pci_bus_find_capability(struct rt_pci_bus *bus, rt_uint32_t devfn, int cap);
rt_uint8_t rt_pci_find_capability(struct rt_pci_device *pdev, int cap);
rt_uint8_t rt_pci_find_next_capability(struct rt_pci_device *pdev, rt_uint8_t pos, int cap);
rt_uint16_t rt_pci_find_ext_capability(struct rt_pci_device *pdev, int cap);
rt_uint16_t rt_pci_find_ext_next_capability(struct rt_pci_device *pdev, rt_uint16_t pos, int cap);
struct rt_pci_bus *rt_pci_find_root_bus(struct rt_pci_bus *bus);
struct rt_pci_host_bridge *rt_pci_find_host_bridge(struct rt_pci_bus *bus);
rt_inline rt_uint16_t rt_pci_dev_id(struct rt_pci_device *pdev)
{
return RT_PCI_DEVID(pdev->bus->number, pdev->devfn);
}
rt_inline rt_bool_t rt_pci_is_root_bus(struct rt_pci_bus *bus)
{
return bus->parent ? RT_FALSE : RT_TRUE;
}
rt_inline rt_bool_t rt_pci_is_bridge(struct rt_pci_device *pdev)
{
return pdev->hdr_type == PCIM_HDRTYPE_BRIDGE ||
pdev->hdr_type == PCIM_HDRTYPE_CARDBUS;
}
rt_inline rt_bool_t rt_pci_is_pcie(struct rt_pci_device *pdev)
{
return !!pdev->pcie_cap;
}
#define rt_pci_foreach_bridge(pdev, bus) \
rt_list_for_each_entry(pdev, &bus->devices_nodes, list) \
if (rt_pci_is_bridge(pdev))
rt_err_t rt_pci_bus_read_config_u8(struct rt_pci_bus *bus,
rt_uint32_t devfn, int pos, rt_uint8_t *value);
rt_err_t rt_pci_bus_read_config_u16(struct rt_pci_bus *bus,
rt_uint32_t devfn, int pos, rt_uint16_t *value);
rt_err_t rt_pci_bus_read_config_u32(struct rt_pci_bus *bus,
rt_uint32_t devfn, int pos, rt_uint32_t *value);
rt_err_t rt_pci_bus_write_config_u8(struct rt_pci_bus *bus,
rt_uint32_t devfn, int reg, rt_uint8_t value);
rt_err_t rt_pci_bus_write_config_u16(struct rt_pci_bus *bus,
rt_uint32_t devfn, int reg, rt_uint16_t value);
rt_err_t rt_pci_bus_write_config_u32(struct rt_pci_bus *bus,
rt_uint32_t devfn, int reg, rt_uint32_t value);
rt_err_t rt_pci_bus_read_config_uxx(struct rt_pci_bus *bus,
rt_uint32_t devfn, int reg, int width, rt_uint32_t *value);
rt_err_t rt_pci_bus_write_config_uxx(struct rt_pci_bus *bus,
rt_uint32_t devfn, int reg, int width, rt_uint32_t value);
rt_err_t rt_pci_bus_read_config_generic_u32(struct rt_pci_bus *bus,
rt_uint32_t devfn, int reg, int width, rt_uint32_t *value);
rt_err_t rt_pci_bus_write_config_generic_u32(struct rt_pci_bus *bus,
rt_uint32_t devfn, int reg, int width, rt_uint32_t value);
rt_inline rt_err_t rt_pci_read_config_u8(const struct rt_pci_device *pdev,
int reg, rt_uint8_t *value)
{
return rt_pci_bus_read_config_u8(pdev->bus, pdev->devfn, reg, value);
}
rt_inline rt_err_t rt_pci_read_config_u16(const struct rt_pci_device *pdev,
int reg, rt_uint16_t *value)
{
return rt_pci_bus_read_config_u16(pdev->bus, pdev->devfn, reg, value);
}
rt_inline rt_err_t rt_pci_read_config_u32(const struct rt_pci_device *pdev,
int reg, rt_uint32_t *value)
{
return rt_pci_bus_read_config_u32(pdev->bus, pdev->devfn, reg, value);
}
rt_inline rt_err_t rt_pci_write_config_u8(const struct rt_pci_device *pdev,
int reg, rt_uint8_t value)
{
return rt_pci_bus_write_config_u8(pdev->bus, pdev->devfn, reg, value);
}
rt_inline rt_err_t rt_pci_write_config_u16(const struct rt_pci_device *pdev,
int reg, rt_uint16_t value)
{
return rt_pci_bus_write_config_u16(pdev->bus, pdev->devfn, reg, value);
}
rt_inline rt_err_t rt_pci_write_config_u32(const struct rt_pci_device *pdev,
int reg, rt_uint32_t value)
{
return rt_pci_bus_write_config_u32(pdev->bus, pdev->devfn, reg, value);
}
#ifdef RT_USING_OFW
int rt_pci_ofw_irq_parse_and_map(struct rt_pci_device *pdev,
rt_uint8_t slot, rt_uint8_t pin);
rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np,
struct rt_pci_host_bridge *host_bridge);
rt_err_t rt_pci_ofw_host_bridge_init(struct rt_ofw_node *dev_np,
struct rt_pci_host_bridge *host_bridge);
rt_err_t rt_pci_ofw_bus_init(struct rt_pci_bus *bus);
rt_err_t rt_pci_ofw_bus_free(struct rt_pci_bus *bus);
rt_err_t rt_pci_ofw_device_init(struct rt_pci_device *pdev);
rt_err_t rt_pci_ofw_device_free(struct rt_pci_device *pdev);
#else
rt_inline rt_err_t rt_pci_ofw_host_bridge_init(struct rt_ofw_node *dev_np,
struct rt_pci_host_bridge *host_bridge)
{
return RT_EOK;
}
rt_inline rt_err_t rt_pci_ofw_bus_init(struct rt_pci_bus *bus)
{
return RT_EOK;
}
rt_inline rt_err_t rt_pci_ofw_bus_free(struct rt_pci_bus *bus)
{
return RT_EOK;
}
rt_inline rt_err_t rt_pci_ofw_device_init(struct rt_pci_device *pdev)
{
return RT_EOK;
}
rt_inline rt_err_t rt_pci_ofw_device_free(struct rt_pci_device *pdev)
{
return RT_EOK;
}
rt_inline int rt_pci_ofw_irq_parse_and_map(struct rt_pci_device *pdev,
rt_uint8_t slot, rt_uint8_t pin)
{
return -1;
}
rt_inline rt_err_t rt_pci_ofw_parse_ranges(struct rt_ofw_node *dev_np,
struct rt_pci_host_bridge *host_bridge)
{
return -RT_ENOSYS;
}
#endif /* RT_USING_OFW */
rt_inline void *rt_pci_iomap(struct rt_pci_device *pdev, int bar_idx)
{
struct rt_pci_bus_resource *res = &pdev->resource[bar_idx];
RT_ASSERT(bar_idx < RT_ARRAY_SIZE(pdev->resource));
return rt_ioremap((void *)res->base, res->size);
}
rt_uint8_t rt_pci_irq_intx(struct rt_pci_device *pdev, rt_uint8_t pin);
rt_uint8_t rt_pci_irq_slot(struct rt_pci_device *pdev, rt_uint8_t *pinp);
void rt_pci_assign_irq(struct rt_pci_device *pdev);
void rt_pci_intx(struct rt_pci_device *pdev, rt_bool_t enable);
rt_bool_t rt_pci_check_and_mask_intx(struct rt_pci_device *pdev);
rt_bool_t rt_pci_check_and_unmask_intx(struct rt_pci_device *pdev);
void rt_pci_irq_mask(struct rt_pci_device *pdev);
void rt_pci_irq_unmask(struct rt_pci_device *pdev);
#define RT_PCI_IRQ_F_LEGACY RT_BIT(0) /* Allow legacy interrupts */
#define RT_PCI_IRQ_F_MSI RT_BIT(1) /* Allow MSI interrupts */
#define RT_PCI_IRQ_F_MSIX RT_BIT(2) /* Allow MSI-X interrupts */
#define RT_PCI_IRQ_F_AFFINITY RT_BIT(3) /* Auto-assign affinity */
#define RT_PCI_IRQ_F_ALL_TYPES (RT_PCI_IRQ_F_LEGACY | RT_PCI_IRQ_F_MSI | RT_PCI_IRQ_F_MSIX)
#ifdef RT_PCI_MSI
rt_ssize_t rt_pci_alloc_vector(struct rt_pci_device *pdev, int min, int max,
rt_uint32_t flags, RT_IRQ_AFFINITY_DECLARE((*affinities)));
void rt_pci_free_vector(struct rt_pci_device *pdev);
rt_ssize_t rt_pci_msi_vector_count(struct rt_pci_device *pdev);
rt_err_t rt_pci_msi_disable(struct rt_pci_device *pdev);
rt_ssize_t rt_pci_msi_enable_range_affinity(struct rt_pci_device *pdev,
int min, int max, RT_IRQ_AFFINITY_DECLARE((*affinities)));
rt_ssize_t rt_pci_msix_vector_count(struct rt_pci_device *pdev);
rt_err_t rt_pci_msix_disable(struct rt_pci_device *pdev);
rt_ssize_t rt_pci_msix_enable_range_affinity(struct rt_pci_device *pdev,
struct rt_pci_msix_entry *entries, int min, int max,
RT_IRQ_AFFINITY_DECLARE((*affinities)));
#else
rt_inline rt_ssize_t rt_pci_alloc_vector(struct rt_pci_device *pdev, int min, int max,
rt_uint32_t flags, RT_IRQ_AFFINITY_DECLARE((*affinities)))
{
return -RT_ENOSYS;
}
rt_inline void rt_pci_free_vector(struct rt_pci_device *pdev)
{
return;
}
rt_inline rt_ssize_t rt_pci_msi_vector_count(struct rt_pci_device *pdev)
{
return 0;
}
rt_inline rt_err_t rt_pci_msi_disable(struct rt_pci_device *pdev)
{
return RT_EOK;
}
rt_inline rt_ssize_t rt_pci_msi_enable_range_affinity(struct rt_pci_device *pdev,
int min, int max, RT_IRQ_AFFINITY_DECLARE((*affinities)))
{
return -RT_ENOSYS;
}
rt_inline rt_ssize_t rt_pci_msix_vector_count(struct rt_pci_device *pdev)
{
return 0;
}
rt_inline rt_err_t rt_pci_msix_disable(struct rt_pci_device *pdev)
{
return RT_EOK;
}
rt_inline rt_ssize_t rt_pci_msix_enable_range_affinity(struct rt_pci_device *pdev,
struct rt_pci_msix_entry *entries, int min, int max,
RT_IRQ_AFFINITY_DECLARE((*affinities)))
{
return -RT_ENOSYS;
}
#endif /* RT_PCI_MSI */
rt_inline void rt_pci_msix_entry_index_linear(struct rt_pci_msix_entry *entries,
rt_size_t nvectors)
{
for (int i = 0; i < nvectors; ++i)
{
entries[i].index = i;
}
}
rt_inline rt_ssize_t rt_pci_msi_enable_range(struct rt_pci_device *pdev,
int min, int max)
{
return rt_pci_msi_enable_range_affinity(pdev, min, max, RT_NULL);
}
rt_inline rt_err_t rt_pci_msi_enable(struct rt_pci_device *pdev)
{
rt_ssize_t res = rt_pci_msi_enable_range(pdev, 1, 1);
return res == 1 ? res : RT_EOK;
}
rt_inline rt_ssize_t rt_pci_msix_enable_range(struct rt_pci_device *pdev,
struct rt_pci_msix_entry *entries, int min, int max)
{
return rt_pci_msix_enable_range_affinity(pdev, entries, min, max, RT_NULL);
}
rt_inline rt_ssize_t rt_pci_msix_enable(struct rt_pci_device *pdev,
struct rt_pci_msix_entry *entries, int count)
{
return rt_pci_msix_enable_range(pdev, entries, count, count);
}
rt_err_t rt_pci_region_setup(struct rt_pci_host_bridge *host_bridge);
struct rt_pci_bus_region *rt_pci_region_alloc(struct rt_pci_host_bridge *host_bridge,
void **out_addr, rt_size_t size, rt_ubase_t flags, rt_bool_t mem64);
rt_err_t rt_pci_device_alloc_resource(struct rt_pci_host_bridge *host_bridge,
struct rt_pci_device *pdev);
void rt_pci_enum_device(struct rt_pci_bus *bus,
rt_bool_t (callback(struct rt_pci_device *, void *)), void *data);
const struct rt_pci_device_id *rt_pci_match_id(struct rt_pci_device *pdev,
const struct rt_pci_device_id *id);
const struct rt_pci_device_id *rt_pci_match_ids(struct rt_pci_device *pdev,
const struct rt_pci_device_id *ids);
rt_err_t rt_pci_driver_register(struct rt_pci_driver *pdrv);
rt_err_t rt_pci_device_register(struct rt_pci_device *pdev);
struct rt_pci_bus_resource *rt_pci_find_bar(struct rt_pci_device* pdev,rt_ubase_t flags,int index);
#define RT_PCI_DRIVER_EXPORT(driver) RT_DRIVER_EXPORT(driver, pci, BUILIN)
extern struct rt_spinlock rt_pci_lock;
#endif /* __PCI_H__ */