akaros/kern/arch/x86/pci.h
<<
>>
Prefs
   1/* Copyright (c) 2009, 2010 The Regents of the University of California
   2 * See LICENSE for details.
   3 *
   4 * Barret Rhoden <brho@cs.berkeley.edu>
   5 * Original by Paul Pearce <pearce@eecs.berkeley.edu> */
   6
   7#pragma once
   8
   9#include <ros/common.h>
  10#include <sys/queue.h>
  11#include <atomic.h>
  12#include <arch/pci_regs.h>
  13
  14#define pci_debug(...)  printk(__VA_ARGS__)
  15
  16#define PCI_CONFIG_ADDR     0xCF8
  17#define PCI_CONFIG_DATA     0xCFC
  18#define INVALID_VENDOR_ID   0xFFFF
  19
  20/* TODO: gut this (when the IOAPIC is fixed) */
  21#define INVALID_BUS                     0xFFFF
  22
  23#define PCI_NOINT                       0x00
  24#define PCI_INTA                        0x01
  25#define PCI_INTB                        0x02
  26#define PCI_INTC                        0x03
  27#define PCI_INTD                        0x04
  28
  29/* PCI Register Config Space */
  30#define PCI_DEV_VEND_REG        0x00    /* for the 32 bit read of dev/vend */
  31#define PCI_VENDID_REG          0x00
  32#define PCI_DEVID_REG           0x02
  33#define PCI_CMD_REG             0x04
  34#define PCI_STATUS_REG          0x06
  35#define PCI_REVID_REG           0x08
  36#define PCI_PROGIF_REG          0x09
  37#define PCI_SUBCLASS_REG        0x0a
  38#define PCI_CLASS_REG           0x0b
  39#define PCI_CLSZ_REG            0x0c
  40#define PCI_LATTIM_REG          0x0d
  41#define PCI_HEADER_REG          0x0e
  42#define PCI_BIST_REG            0x0f
  43/* Config space for header type 0x00  (Standard) */
  44#define PCI_BAR0_STD            0x10
  45#define PCI_BAR1_STD            0x14
  46#define PCI_BAR2_STD            0x18
  47#define PCI_BAR3_STD            0x1c
  48#define PCI_BAR4_STD            0x20
  49#define PCI_BAR5_STD            0x24
  50#define PCI_BAR_OFF             0x04
  51#define PCI_CARDBUS_STD         0x28
  52#define PCI_SUBSYSVEN_STD       0x2c
  53#define PCI_SUBSYSID_STD        0x2e
  54#define PCI_EXPROM_STD          0x30
  55#define PCI_CAPAB_STD           0x34
  56#define PCI_IRQLINE_STD         0x3c
  57#define PCI_IRQPIN_STD          0x3d
  58#define PCI_MINGRNT_STD         0x3e
  59#define PCI_MAXLAT_STD          0x3f
  60/* Config space for header type 0x01 (PCI-PCI bridge) */
  61/* None of these have been used, so if you use them, check them against
  62 * http://wiki.osdev.org/PCI#PCI_Device_Structure */
  63#define PCI_BAR0_BR             0x10
  64#define PCI_BAR1_BR             0x14
  65#define PCI_BUS1_BR             0x18
  66#define PCI_BUS2_BR             0x19
  67#define PCI_SUBBUS_BR           0x1a
  68#define PCI_LATTIM2_BR          0x1b
  69#define PCI_IOBASE_BR           0x1c
  70#define PCI_IOLIM_BR            0x1d
  71#define PCI_STATUS2_BR          0x1e
  72#define PCI_MEMBASE_BR          0x20
  73#define PCI_MEMLIM_BR           0x22
  74#define PCI_PREMEMBASE_BR       0x24
  75#define PCI_PREMEMLIM_BR        0x26
  76#define PCI_PREBASEUP32_BR      0x28
  77#define PCI_PRELIMUP32_BR       0x2c
  78#define PCI_IOBASEUP16_BR       0x30
  79#define PCI_IOLIMUP16_BR        0x32
  80#define PCI_CAPAB_BR            0x34
  81#define PCI_EXPROM_BR           0x38
  82#define PCI_IRQLINE_BR          0x3c
  83#define PCI_IRQPIN_BR           0x3d
  84#define PCI_BDGCTL_BR           0x3e
  85/* Config space for header type 0x02 (PCI-Cardbus bridge) */
  86/* None of these have been used, so if you use them, check them against
  87 * http://wiki.osdev.org/PCI#PCI_Device_Structure */
  88#define PCI_SOC_BASE_CB         0x10
  89#define PCI_OFF_CAP_CB          0x14
  90#define PCI_SEC_STAT_CB         0x16
  91#define PCI_BUS_NR_CB           0x18
  92#define PCI_CARDBUS_NR_CB       0x19
  93#define PCI_SUBBUS_NR_CB        0x1a
  94#define PCI_CARD_LAT_CB         0x1b
  95#define PCI_MEM_BASE0_CB        0x1c
  96#define PCI_MEM_LIMIT0_CB       0x20
  97#define PCI_MEM_BASE1_CB        0x24
  98#define PCI_MEM_LIMIT1_CB       0x28
  99#define PCI_IO_BASE0_CB         0x2c
 100#define PCI_IO_LIMIT0_CB        0x30
 101#define PCI_IO_BASE1_CB         0x34
 102#define PCI_IO_LIMIT1_CB        0x38
 103#define PCI_IRQLINE_CB          0x3c
 104#define PCI_IRQPIN_CB           0x3d
 105#define PCI_BDGCTL_CB           0x3e
 106#define PCI_SUBDEVID_CB         0x40
 107#define PCI_SUBVENID_CB         0x42
 108#define PCI_16BIT_CB            0x44
 109
 110/* Command Register Flags */
 111#define PCI_CMD_IO_SPC          (1 << 0)
 112#define PCI_CMD_MEM_SPC         (1 << 1)
 113#define PCI_CMD_BUS_MAS         (1 << 2)
 114#define PCI_CMD_SPC_CYC         (1 << 3)
 115#define PCI_CMD_WR_EN           (1 << 4)
 116#define PCI_CMD_VGA             (1 << 5)
 117#define PCI_CMD_PAR_ERR         (1 << 6)
 118/* #define PCI_CMD_XXX          (1 << 7) Reserved */
 119#define PCI_CMD_SERR            (1 << 8)
 120#define PCI_CMD_FAST_EN         (1 << 9)
 121#define PCI_CMD_IRQ_DIS         (1 << 10)
 122
 123/* Status Register Flags (Bits 9 and 10 are one field) */
 124/* Bits 0, 1, and 2 are reserved */
 125#define PCI_ST_IRQ_STAT         (1 << 3)
 126#define PCI_ST_CAP_LIST         (1 << 4)
 127#define PCI_ST_66MHZ            (1 << 5)
 128/* #define PCI_CMD_XXX          (1 << 6)  Reserved */
 129#define PCI_ST_FAST_CAP         (1 << 7)
 130#define PCI_ST_MASPAR_ERR       (1 << 8)
 131#define PCI_ST_DEVSEL_TIM       (3 << 9)        /* 2 bits */
 132#define PCI_ST_SIG_TAR_ABRT     (1 << 11)
 133#define PCI_ST_REC_TAR_ABRT     (1 << 12)
 134#define PCI_ST_REC_MAS_ABRT     (1 << 13)
 135#define PCI_ST_SIG_SYS_ERR      (1 << 14)
 136#define PCI_ST_PAR_ERR          (1 << 15)
 137
 138/* BARS: Base Address Registers */
 139#define PCI_BAR_IO              0x1     /* 1 == IO, 0 == Mem */
 140#define PCI_BAR_IO_MASK         0xfffffffc
 141#define PCI_BAR_MEM_MASK        0xfffffff0
 142#define PCI_MEMBAR_TYPE         (3 << 1)
 143#define PCI_MEMBAR_32BIT        0x0
 144#define PCI_MEMBAR_RESV         0x2     /* type 0x1 shifted to MEMBAR_TYPE */
 145#define PCI_MEMBAR_64BIT        0x4     /* type 0x2 shifted to MEMBAR_TYPE */
 146
 147#define PCI_MAX_BUS             256
 148#define PCI_MAX_DEV             32
 149#define PCI_MAX_FUNC            8
 150
 151// Run the PCI Code to loop over the PCI BARs. For now we don't use the BARs,
 152// dont check em.
 153#define CHECK_BARS              0
 154
 155#define MAX_PCI_BAR             6
 156
 157/* Nothing yet, but this helps with Linux drivers. */
 158struct device {
 159};
 160
 161struct pci_bar {
 162        uint32_t                        raw_bar;
 163        uint32_t                        pio_base;
 164        uint32_t                        mmio_base32;
 165        uint64_t                        mmio_base64;
 166        uint32_t                        mmio_sz;
 167};
 168
 169struct pci_device {
 170        STAILQ_ENTRY(pci_device)        all_dev; /* list of all devices */
 171        SLIST_ENTRY(pci_device)         irq_dev; /* list of all devs on irq */
 172        char                            name[9];
 173        spinlock_t                      lock;
 174        uintptr_t                       mmio_cfg;
 175        void                            *dev_data; /* device private pointer */
 176        struct iommu                    *iommu; /* ptr to controlling iommu */
 177        struct device                   device;
 178        bool                            in_use; /* prevent double discovery */
 179        int                             domain; /* legacy size was 16-bits */
 180        uint8_t                         bus;
 181        uint8_t                         dev;
 182        uint8_t                         func;
 183        uint16_t                        dev_id;
 184        uint16_t                        ven_id;
 185        uint8_t                         irqline;
 186        uint8_t                         irqpin;
 187        char                            *header_type;
 188        uint8_t                         class;
 189        uint8_t                         subclass;
 190        uint8_t                         progif;
 191        bool                            msi_ready;
 192        uint32_t                        msi_msg_addr_hi;
 193        uint32_t                        msi_msg_addr_lo;
 194        uint32_t                        msi_msg_data;
 195        uint8_t                         nr_bars;
 196        struct pci_bar                  bar[MAX_PCI_BAR];
 197        uint32_t                        caps[PCI_CAP_ID_MAX + 1];
 198        uintptr_t                       msix_tbl_paddr;
 199        uintptr_t                       msix_tbl_vaddr;
 200        uintptr_t                       msix_pba_paddr;
 201        uintptr_t                       msix_pba_vaddr;
 202        unsigned int                    msix_nr_vec;
 203        bool                            msix_ready;
 204        TAILQ_ENTRY(pci_device)         proc_link; /* for device passthru */
 205        struct proc                     *proc_owner;
 206};
 207
 208struct msix_entry {
 209        uint32_t addr_lo, addr_hi, data, vector;
 210};
 211
 212struct msix_irq_vector {
 213        struct pci_device               *pcidev;
 214        struct msix_entry               *entry;
 215        uint32_t                        addr_lo;
 216        uint32_t                        addr_hi;
 217        uint32_t                        data;
 218};
 219
 220/* List of all discovered devices */
 221TAILQ_HEAD(pcidev_tq, pci_device);
 222STAILQ_HEAD(pcidev_stailq, pci_device);
 223extern struct pcidev_stailq pci_devices;
 224
 225/* Sync rules for PCI: once a device is added to the list, it is never removed,
 226 * and its read-only fields can be accessed at any time.  There is no need for
 227 * refcnts or things like that.
 228 *
 229 * The device list is built early on when we're single threaded, so I'm not
 230 * bothering with locks for that yet.  Append-only, singly-linked-list reads
 231 * don't need a lock either.
 232 *
 233 * Other per-device accesses (like read-modify-writes to config space or MSI
 234 * fields) require the device's lock.  If we ever want to unplug, we'll probably
 235 * work out an RCU-like scheme for the pci_devices list.
 236 *
 237 * Note this is in addition to the config space global locking done by every
 238 * pci_read or write call. */
 239
 240void pci_init(void);
 241void pcidev_print_info(struct pci_device *pcidev, int verbosity);
 242uint32_t pci_config_addr(uint8_t bus, uint8_t dev, uint8_t func, uint32_t reg);
 243
 244uint32_t pcidev_read32(struct pci_device *pcidev, uint32_t offset);
 245void pcidev_write32(struct pci_device *pcidev, uint32_t offset, uint32_t value);
 246uint16_t pcidev_read16(struct pci_device *pcidev, uint32_t offset);
 247void pcidev_write16(struct pci_device *pcidev, uint32_t offset, uint16_t value);
 248uint8_t pcidev_read8(struct pci_device *pcidev, uint32_t offset);
 249void pcidev_write8(struct pci_device *pcidev, uint32_t offset, uint8_t value);
 250
 251/* Other common PCI functions */
 252void pci_set_bus_master(struct pci_device *pcidev);
 253void pci_clr_bus_master(struct pci_device *pcidev);
 254struct pci_device *pci_match_tbdf(int tbdf);
 255uintptr_t pci_get_membar(struct pci_device *pcidev, int bir);
 256uintptr_t pci_get_iobar(struct pci_device *pcidev, int bir);
 257uint32_t pci_get_membar_sz(struct pci_device *pcidev, int bir);
 258uint16_t pci_get_vendor(struct pci_device *pcidev);
 259uint16_t pci_get_device(struct pci_device *pcidev);
 260uint16_t pci_get_subvendor(struct pci_device *pcidev);
 261uint16_t pci_get_subdevice(struct pci_device *pcidev);
 262void pci_dump_config(struct pci_device *pcidev, size_t len);
 263int pci_find_cap(struct pci_device *pcidev, uint8_t cap_id, uint32_t *cap_reg);
 264unsigned int pci_to_tbdf(struct pci_device *pcidev);
 265uintptr_t pci_map_membar(struct pci_device *dev, int bir);
 266int pci_set_cacheline_size(struct pci_device *dev);
 267int pci_set_mwi(struct pci_device *dev);
 268void pci_clear_mwi(struct pci_device *dev);
 269static inline void pci_set_drvdata(struct pci_device *pcidev, void *data);
 270static inline void *pci_get_drvdata(struct pci_device *pcidev);
 271
 272/* MSI functions, msi.c */
 273int pci_msi_enable(struct pci_device *p, uint64_t vec);
 274int pci_msix_init(struct pci_device *p);
 275struct msix_irq_vector *pci_msix_enable(struct pci_device *p, uint64_t vec);
 276void pci_msi_mask(struct pci_device *p);
 277void pci_msi_unmask(struct pci_device *p);
 278void pci_msi_route(struct pci_device *p, int dest);
 279void pci_msix_mask_vector(struct msix_irq_vector *linkage);
 280void pci_msix_unmask_vector(struct msix_irq_vector *linkage);
 281void pci_msix_route_vector(struct msix_irq_vector *linkage, int dest);
 282
 283/* TODO: this is quite the Hacke */
 284#define explode_tbdf(tbdf) {pcidev.bus = tbdf >> 16;\
 285                pcidev.dev = (tbdf>>11)&0x1f;\
 286                pcidev.func = (tbdf>>8)&3;}
 287
 288static inline void pci_set_drvdata(struct pci_device *pcidev, void *data)
 289{
 290        pcidev->dev_data = data;
 291}
 292
 293static inline void *pci_get_drvdata(struct pci_device *pcidev)
 294{
 295        return pcidev->dev_data;
 296}
 297