#include "types.h" // u32
-typedef struct PCIDevice {
- u8 bus;
- u8 devfn;
-} PCIDevice;
+#define PCI_ROM_SLOT 6
+#define PCI_NUM_REGIONS 7
-static inline PCIDevice pci_bd(u8 bus, u8 devfn) {
- struct PCIDevice d = {bus, devfn};
- return d;
-}
-static inline u16 pci_to_bdf(PCIDevice d) {
- return (d.bus << 8) | d.devfn;
-}
static inline u8 pci_bdf_to_bus(u16 bdf) {
return bdf >> 8;
}
+static inline u8 pci_bdf_to_devfn(u16 bdf) {
+ return bdf & 0xff;
+}
+static inline u16 pci_bdf_to_busdev(u16 bdf) {
+ return bdf & ~0x07;
+}
static inline u8 pci_bdf_to_dev(u16 bdf) {
return (bdf >> 3) & 0x1f;
}
static inline u8 pci_bdf_to_fn(u16 bdf) {
return bdf & 0x07;
}
+static inline u16 pci_to_bdf(int bus, int dev, int fn) {
+ return (bus<<8) | (dev<<3) | fn;
+}
+static inline u16 pci_bus_devfn_to_bdf(int bus, u16 devfn) {
+ return (bus << 8) | devfn;
+}
-void pci_config_writel(PCIDevice d, u32 addr, u32 val);
-void pci_config_writew(PCIDevice d, u32 addr, u16 val);
-void pci_config_writeb(PCIDevice d, u32 addr, u8 val);
-u32 pci_config_readl(PCIDevice d, u32 addr);
-u16 pci_config_readw(PCIDevice d, u32 addr);
-u8 pci_config_readb(PCIDevice d, u32 addr);
+void pci_config_writel(u16 bdf, u32 addr, u32 val);
+void pci_config_writew(u16 bdf, u32 addr, u16 val);
+void pci_config_writeb(u16 bdf, u32 addr, u8 val);
+u32 pci_config_readl(u16 bdf, u32 addr);
+u16 pci_config_readw(u16 bdf, u32 addr);
+u8 pci_config_readb(u16 bdf, u32 addr);
+void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
+
+struct pci_device *pci_find_device(u16 vendid, u16 devid);
+struct pci_device *pci_find_class(u16 classid);
+
+struct pci_device {
+ u16 bdf;
+ u8 rootbus;
+ struct pci_device *next;
+ struct pci_device *parent;
+
+ // Configuration space device information
+ u16 vendor, device;
+ u16 class;
+ u8 prog_if, revision;
+ u8 header_type;
+ u8 secondary_bus;
+ struct {
+ u32 addr;
+ u32 size;
+ int is64;
+ } bars[PCI_NUM_REGIONS];
+
+ // Local information on device.
+ int have_driver;
+};
+extern struct pci_device *PCIDevices;
+extern int MaxPCIBus;
+int pci_probe_host(void);
+void pci_probe_devices(void);
+static inline u32 pci_classprog(struct pci_device *pci) {
+ return (pci->class << 8) | pci->prog_if;
+}
-int pci_find_device(u16 vendid, u16 devid, int index, PCIDevice *dev);
-int pci_find_classprog(u32 classprog, int index, PCIDevice *dev);
-int pci_find_class(u16 classid, int index, PCIDevice *dev);
+#define foreachpci(PCI) \
+ for (PCI=PCIDevices; PCI; PCI=PCI->next)
+
+int pci_next(int bdf, int bus);
+#define foreachbdf(BDF, BUS) \
+ for (BDF=pci_next(pci_bus_devfn_to_bdf((BUS), 0)-1, (BUS)) \
+ ; BDF >= 0 \
+ ; BDF=pci_next(BDF, (BUS)))
+
+#define PCI_ANY_ID (~0)
+struct pci_device_id {
+ u32 vendid;
+ u32 devid;
+ u32 class;
+ u32 class_mask;
+ void (*func)(struct pci_device *pci, void *arg);
+};
+
+#define PCI_DEVICE(vendor_id, device_id, init_func) \
+ { \
+ .vendid = (vendor_id), \
+ .devid = (device_id), \
+ .class = PCI_ANY_ID, \
+ .class_mask = 0, \
+ .func = (init_func) \
+ }
+
+#define PCI_DEVICE_CLASS(vendor_id, device_id, class_code, init_func) \
+ { \
+ .vendid = (vendor_id), \
+ .devid = (device_id), \
+ .class = (class_code), \
+ .class_mask = ~0, \
+ .func = (init_func) \
+ }
+
+#define PCI_DEVICE_END \
+ { \
+ .vendid = 0, \
+ }
+
+int pci_init_device(const struct pci_device_id *ids
+ , struct pci_device *pci, void *arg);
+struct pci_device *pci_find_init_device(const struct pci_device_id *ids
+ , void *arg);
+void pci_reboot(void);
+
+// helper functions to access pci mmio bars from real mode
+u32 pci_readl(u32 addr);
+void pci_writel(u32 addr, u32 val);
// pirtable.c
-void create_pirtable();
-
-
-/****************************************************************
- * PCI definitions
- ****************************************************************/
-
-#define PCI_VENDOR_ID 0x00 /* 16 bits */
-#define PCI_DEVICE_ID 0x02 /* 16 bits */
-#define PCI_COMMAND 0x04 /* 16 bits */
-#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
-#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
-#define PCI_CLASS_PROG 0x09
-#define PCI_CLASS_DEVICE 0x0a /* Device class */
-#define PCI_BASE_ADDR_0 0x10
-#define PCI_BASE_ADDR_1 0x14
-#define PCI_BASE_ADDR_2 0x18
-#define PCI_BASE_ADDR_3 0x1c
-#define PCI_BASE_ADDR_4 0x20
-#define PCI_BASE_ADDR_5 0x24
-#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
-#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
-#define PCI_MIN_GNT 0x3e /* 8 bits */
-#define PCI_MAX_LAT 0x3f /* 8 bits */
+void create_pirtable(void);
/****************************************************************
* PIR table
****************************************************************/
+extern u16 PirOffset;
+
struct link_info {
u8 link;
u16 bitmap;