aboutsummaryrefslogtreecommitdiff
path: root/kernel/include/drivers/pcie.h
blob: 83d182f7dfe85fd8108fd38213954aa862d437e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#pragma once

#include <util/list.h>

#define PCI_NUM_BUSES 256
#define PCI_NUM_DEVICES_PER_BUS 32
#define PCI_NUM_FUNCTIONS_PER_DEVICE 8
#define PCI_DEVICE_FUNCTION_SIZE 4096
#define PCI_CAPABILITY_PTR_MASK (0b11111100)
#define PCI_MSI_CAPABILITY_ID 0x5

// Intel Vol 3A 10.11.1
//#define MSI_BASE_ADDRESS 0x0FEE0000
#define MSI_ADDRESS_FOR(destination) \
    ((uint32_t)((0x0FEE << 20) | ((destination) << 12) | (0b1100)))
#define MSI_DATA_FOR(vector) ((uint16_t)(0b00000001 << 8) | (vector))

typedef struct pci_capability
{
    uint8_t id;
    uint8_t next_cap;
    uint16_t control;
} packed pci_capability_t;

typedef struct msi_capability
{
    uint8_t id;
    uint8_t next_cap;
    struct
    {
        uint8_t msie : 1; // MSI Enable
        uint8_t mmc : 3;  // Multiple Message Capable
        uint8_t mme : 3;  // Multiple Message Enable
        uint8_t c64 : 1;  // 64 Bit Address Capable
        uint8_t _reserved;
    } control;
    union {
        struct
        {
            uint32_t addr;
            uint16_t data;
        } ad32;
        struct
        {
            uint64_t addr;
            uint16_t data;
        } ad64;
    } address_data;
} packed msi_capability_t;

typedef union pcie_device {
    struct
    {
        char data[PCI_DEVICE_FUNCTION_SIZE];
    } raw;
    struct
    {
        uint16_t vendor_id;
        uint16_t device_id;
        uint16_t command;
        uint16_t status;
        uint8_t revision_id;
        uint8_t prog_if;
        uint8_t subclass;
        uint8_t class;
        uint8_t cache_line_size;
        uint8_t latency_type;
        uint8_t header_type;
        uint8_t bist;
        uint32_t bar[6];
        uint32_t cardbus_cis_pointer;
        uint16_t subsystem_vendor_id;
        uint16_t subsystem_id;
        uint32_t expansion_rom_base_addr;
        uint8_t capabilities_ptr;
        uint8_t _reserved1[7];
        uint8_t interrupt_line;
        uint8_t interrupt_pin;
        uint8_t min_grant;
        uint8_t max_latency;
        pci_capability_t pm_capability;
        uint16_t pmcsr;
        uint8_t bse;
        uint8_t data;
        pci_capability_t msi_capability;
        uint64_t message_address;
        uint16_t message_data;
        uint8_t _reserved2[2];
        pci_capability_t pe_capability;
        uint32_t pcie_device_capabilities;
        uint16_t device_control;
        uint16_t device_status;
        uint32_t pcie_link_capabilities;
        uint16_t link_control;
        uint16_t link_status;
    } standard;
} packed pcie_device_t;

#define PCI_LOOKUP_WILDCARD 0xff

typedef struct pcie_device_wrapper
{
    uint8_t class;
    uint8_t subclass;
    uint8_t interface;
    pcie_device_t *dev;
    list_link_t link;
} pcie_device_wrapper_t;

void pci_init(void);

pcie_device_t *pcie_lookup(uint8_t class, uint8_t subclass, uint8_t interface);