blob: 85c70a7280a73a1f0ecb5d505d007837036902b4 [file] [log] [blame] [edit]
/* Copyright (c) 2009, 2010 The Regents of the University of California
* See LICENSE for details.
*
* Barret Rhoden <brho@cs.berkeley.edu>
* Original by Paul Pearce <pearce@eecs.berkeley.edu> */
#ifndef ROS_ARCH_PCI_H
#define ROS_ARCH_PCI_H
#include <ros/common.h>
#include <sys/queue.h>
#define pci_debug(...) printk(__VA_ARGS__)
#define PCI_CONFIG_ADDR 0xCF8
#define PCI_CONFIG_DATA 0xCFC
#define INVALID_VENDOR_ID 0xFFFF
/* TODO: gut this (when the IOAPIC is fixed) */
#define INVALID_BUS 0xFFFF
#define PCI_NOINT 0x00
#define PCI_INTA 0x01
#define PCI_INTB 0x02
#define PCI_INTC 0x03
#define PCI_INTD 0x04
/* PCI Register Config Space */
#define PCI_DEV_VEND_REG 0x00 /* for the 32 bit read of dev/vend */
#define PCI_VENDID_REG 0x00
#define PCI_DEVID_REG 0x02
#define PCI_CMD_REG 0x04
#define PCI_STATUS_REG 0x06
#define PCI_REVID_REG 0x08
#define PCI_PROGIF_REG 0x09
#define PCI_SUBCLASS_REG 0x0a
#define PCI_CLASS_REG 0x0b
#define PCI_CLSZ_REG 0x0c
#define PCI_LATTIM_REG 0x0d
#define PCI_HEADER_REG 0x0e
#define PCI_BIST_REG 0x0f
/* Config space for header type 0x00 (Standard) */
#define PCI_BAR0_STD 0x10
#define PCI_BAR1_STD 0x14
#define PCI_BAR2_STD 0x18
#define PCI_BAR3_STD 0x1c
#define PCI_BAR4_STD 0x20
#define PCI_BAR5_STD 0x24
#define PCI_BAR_OFF 0x04
#define PCI_CARDBUS_STD 0x28
#define PCI_SUBSYSVEN_STD 0x2c
#define PCI_SUBSYSID_STD 0x2e
#define PCI_EXPROM_STD 0x30
#define PCI_CAPAB_STD 0x34
#define PCI_IRQLINE_STD 0x3c
#define PCI_IRQPIN_STD 0x3d
#define PCI_MINGRNT_STD 0x3e
#define PCI_MAXLAT_STD 0x3f
/* Config space for header type 0x01 (PCI-PCI bridge) */
/* None of these have been used, so if you use them, check them against
* http://wiki.osdev.org/PCI#PCI_Device_Structure */
#define PCI_BAR0_BR 0x10
#define PCI_BAR1_BR 0x14
#define PCI_BUS1_BR 0x18
#define PCI_BUS2_BR 0x19
#define PCI_SUBBUS_BR 0x1a
#define PCI_LATTIM2_BR 0x1b
#define PCI_IOBASE_BR 0x1c
#define PCI_IOLIM_BR 0x1d
#define PCI_STATUS2_BR 0x1e
#define PCI_MEMBASE_BR 0x20
#define PCI_MEMLIM_BR 0x22
#define PCI_PREMEMBASE_BR 0x24
#define PCI_PREMEMLIM_BR 0x26
#define PCI_PREBASEUP32_BR 0x28
#define PCI_PRELIMUP32_BR 0x2c
#define PCI_IOBASEUP16_BR 0x30
#define PCI_IOLIMUP16_BR 0x32
#define PCI_CAPAB_BR 0x34
#define PCI_EXPROM_BR 0x38
#define PCI_IRQLINE_BR 0x3c
#define PCI_IRQPIN_BR 0x3d
#define PCI_BDGCTL_BR 0x3e
/* Config space for header type 0x02 (PCI-Cardbus bridge) */
/* None of these have been used, so if you use them, check them against
* http://wiki.osdev.org/PCI#PCI_Device_Structure */
#define PCI_SOC_BASE_CB 0x10
#define PCI_OFF_CAP_CB 0x14
#define PCI_SEC_STAT_CB 0x16
#define PCI_BUS_NR_CB 0x18
#define PCI_CARDBUS_NR_CB 0x19
#define PCI_SUBBUS_NR_CB 0x1a
#define PCI_CARD_LAT_CB 0x1b
#define PCI_MEM_BASE0_CB 0x1c
#define PCI_MEM_LIMIT0_CB 0x20
#define PCI_MEM_BASE1_CB 0x24
#define PCI_MEM_LIMIT1_CB 0x28
#define PCI_IO_BASE0_CB 0x2c
#define PCI_IO_LIMIT0_CB 0x30
#define PCI_IO_BASE1_CB 0x34
#define PCI_IO_LIMIT1_CB 0x38
#define PCI_IRQLINE_CB 0x3c
#define PCI_IRQPIN_CB 0x3d
#define PCI_BDGCTL_CB 0x3e
#define PCI_SUBDEVID_CB 0x40
#define PCI_SUBVENID_CB 0x42
#define PCI_16BIT_CB 0x44
/* Command Register Flags */
#define PCI_CMD_IO_SPC (1 << 0)
#define PCI_CMD_MEM_SPC (1 << 1)
#define PCI_CMD_BUS_MAS (1 << 2)
#define PCI_CMD_SPC_CYC (1 << 3)
#define PCI_CMD_WR_EN (1 << 4)
#define PCI_CMD_VGA (1 << 5)
#define PCI_CMD_PAR_ERR (1 << 6)
/* #define PCI_CMD_XXX (1 << 7) Reserved */
#define PCI_CMD_SERR (1 << 8)
#define PCI_CMD_FAST_EN (1 << 9)
#define PCI_CMD_IRQ_DIS (1 << 10)
/* Status Register Flags (Bits 9 and 10 are one field) */
/* Bits 0, 1, and 2 are reserved */
#define PCI_ST_IRQ_STAT (1 << 3)
#define PCI_ST_CAP_LIST (1 << 4)
#define PCI_ST_66MHZ (1 << 5)
/* #define PCI_CMD_XXX (1 << 6) Reserved */
#define PCI_ST_FAST_CAP (1 << 7)
#define PCI_ST_MASPAR_ERR (1 << 8)
#define PCI_ST_DEVSEL_TIM (3 << 9) /* 2 bits */
#define PCI_ST_SIG_TAR_ABRT (1 << 11)
#define PCI_ST_REC_TAR_ABRT (1 << 12)
#define PCI_ST_REC_MAS_ABRT (1 << 13)
#define PCI_ST_SIG_SYS_ERR (1 << 14)
#define PCI_ST_PAR_ERR (1 << 15)
/* BARS: Base Address Registers */
#define PCI_BAR_IO 0x1 /* 1 == IO, 0 == Mem */
#define PCI_BAR_IO_MASK 0xfffffffc
#define PCI_BAR_MEM_MASK 0xfffffff0
#define PCI_MEMBAR_TYPE (3 << 1)
#define PCI_MEMBAR_32BIT 0x0
#define PCI_MEMBAR_RESV 0x2 /* type 0x1 shifted to MEMBAR_TYPE */
#define PCI_MEMBAR_64BIT 0x4 /* type 0x2 shifted to MEMBAR_TYPE */
#define PCI_MAX_BUS 256
#define PCI_MAX_DEV 32
#define PCI_MAX_FUNC 8
// Run the PCI Code to loop over the PCI BARs. For now we don't use the BARs,
// dont check em.
#define CHECK_BARS 0
#define MAX_PCI_BAR 6
struct pci_bar {
uint32_t raw_bar;
uint32_t pio_base;
uint32_t mmio_base32;
uint64_t mmio_base64;
uint32_t mmio_sz;
};
/* Struct for some meager contents of a PCI device */
struct pci_device {
STAILQ_ENTRY(pci_device) all_dev; /* list of all devices */
SLIST_ENTRY(pci_device) irq_dev; /* list of all devs off an irq */
bool in_use; /* prevent double discovery */
uint8_t bus;
uint8_t dev;
uint8_t func;
uint16_t dev_id;
uint16_t ven_id;
uint8_t irqline;
uint8_t irqpin;
char *header_type;
uint8_t class;
uint8_t subclass;
uint8_t progif;
uint8_t nr_bars;
struct pci_bar bar[MAX_PCI_BAR];
};
/* List of all discovered devices */
STAILQ_HEAD(pcidev_stailq, pci_device);
SLIST_HEAD(pcidev_slist, pci_device);
extern struct pcidev_stailq pci_devices;
void pci_init(void);
void pcidev_print_info(struct pci_device *pcidev, int verbosity);
uint32_t pci_config_addr(uint8_t bus, uint8_t dev, uint8_t func, uint8_t reg);
/* Read and write helpers (Eventually, we should have these be statics, since no
* device should touch PCI config space). */
uint32_t pci_read32(uint8_t bus, uint8_t dev, uint8_t func, uint8_t offset);
void pci_write32(uint8_t bus, uint8_t dev, uint8_t func, uint8_t offset,
uint32_t value);
uint32_t pcidev_read32(struct pci_device *pcidev, uint8_t offset);
void pcidev_write32(struct pci_device *pcidev, uint8_t offset, uint32_t value);
uint16_t pcidev_read16(struct pci_device *pcidev, uint8_t offset);
void pcidev_write16(struct pci_device *pcidev, uint8_t offset, uint16_t value);
uint8_t pcidev_read8(struct pci_device *pcidev, uint8_t offset);
void pcidev_write8(struct pci_device *pcidev, uint8_t offset, uint8_t value);
/* BAR helpers, some more helpful than others. */
uint32_t pci_membar_get_sz(struct pci_device *pcidev, int bar);
uint32_t pci_getbar(struct pci_device *pcidev, unsigned int bar);
bool pci_is_iobar(uint32_t bar);
bool pci_is_membar32(uint32_t bar);
bool pci_is_membar64(uint32_t bar);
uint32_t pci_getmembar32(uint32_t bar);
uint32_t pci_getiobar32(uint32_t bar);
/* Other common PCI functions */
void pci_set_bus_master(struct pci_device *pcidev);
#endif /* ROS_ARCH_PCI_H */