1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 // clang-format off
8 
9 #include <endian.h>
10 #include <stdbool.h>
11 #include <stdint.h>
12 #include <zircon/compiler.h>
13 #include <zircon/types.h>
14 
15 __BEGIN_CDECLS;
16 
17 /*
18  * PCI configuration space offsets
19  */
20 #define PCI_CONFIG_VENDOR_ID        0x00
21 #define PCI_CONFIG_DEVICE_ID        0x02
22 #define PCI_CONFIG_COMMAND          0x04
23 #define PCI_CONFIG_STATUS           0x06
24 #define PCI_CONFIG_REVISION_ID      0x08
25 #define PCI_CONFIG_CLASS_CODE       0x09
26 #define PCI_CONFIG_CLASS_CODE_INTR  0x09
27 #define PCI_CONFIG_CLASS_CODE_SUB   0x0a
28 #define PCI_CONFIG_CLASS_CODE_BASE  0x0b
29 #define PCI_CONFIG_CACHE_LINE_SIZE  0x0c
30 #define PCI_CONFIG_LATENCY_TIMER    0x0d
31 #define PCI_CONFIG_HEADER_TYPE      0x0e
32 #define PCI_CONFIG_BIST             0x0f
33 #define PCI_CONFIG_BASE_ADDRESSES   0x10
34 #define PCI_CONFIG_CARDBUS_CIS_PTR  0x28
35 #define PCI_CONFIG_SUBSYS_VENDOR_ID 0x2c
36 #define PCI_CONFIG_SUBSYS_ID        0x2e
37 #define PCI_CONFIG_EXP_ROM_ADDRESS  0x30
38 #define PCI_CONFIG_CAPABILITIES     0x34
39 #define PCI_CONFIG_INTERRUPT_LINE   0x3c
40 #define PCI_CONFIG_INTERRUPT_PIN    0x3d
41 #define PCI_CONFIG_MIN_GRANT        0x3e
42 #define PCI_CONFIG_MAX_LATENCY      0x3f
43 
44 /*
45  * PCI header type register bits
46  */
47 #define PCI_HEADER_TYPE_MASK        0x7f
48 #define PCI_HEADER_TYPE_MULTI_FN    0x80
49 
50 /*
51  * PCI header types
52  */
53 #define PCI_HEADER_TYPE_STANDARD    0x00
54 #define PCI_HEADER_TYPE_PCI_BRIDGE  0x01
55 #define PCI_HEADER_TYPE_CARD_BUS    0x02
56 
57 /*
58  * PCI command register bits
59  */
60 #define PCI_COMMAND_IO_EN           0x0001
61 #define PCI_COMMAND_MEM_EN          0x0002
62 #define PCI_COMMAND_BUS_MASTER_EN   0x0004
63 #define PCI_COMMAND_SPECIAL_EN      0x0008
64 #define PCI_COMMAND_MEM_WR_INV_EN   0x0010
65 #define PCI_COMMAND_PAL_SNOOP_EN    0x0020
66 #define PCI_COMMAND_PERR_RESP_EN    0x0040
67 #define PCI_COMMAND_AD_STEP_EN      0x0080
68 #define PCI_COMMAND_SERR_EN         0x0100
69 #define PCI_COMMAND_FAST_B2B_EN     0x0200
70 
71 /*
72  * PCI status register bits
73  */
74 #define PCI_STATUS_INTERRUPT        0x0008
75 #define PCI_STATUS_NEW_CAPS         0x0010
76 #define PCI_STATUS_66_MHZ           0x0020
77 #define PCI_STATUS_FAST_B2B         0x0080
78 #define PCI_STATUS_MSTR_PERR        0x0100
79 #define PCI_STATUS_DEVSEL_MASK      0x0600
80 #define PCI_STATUS_TARG_ABORT_SIG   0x0800
81 #define PCI_STATUS_TARG_ABORT_RCV   0x1000
82 #define PCI_STATUS_MSTR_ABORT_RCV   0x2000
83 #define PCI_STATUS_SERR_SIG         0x4000
84 #define PCI_STATUS_PERR             0x8000
85 
86 #define PCI_MAX_BAR_COUNT           6u
87 
88 #define PCI_CLASS_LEGACY_DEVICE     0x00
89 #define PCI_CLASS_MASS_STORAGE      0x01
90 #define PCI_CLASS_NETWORK           0x02
91 #define PCI_CLASS_DISPLAY           0x03
92 #define PCI_CLASS_MULTIMEDIA        0x04
93 #define PCI_CLASS_MEMORY            0x05
94 #define PCI_CLASS_BRIDGE            0x06
95 #define PCI_CLASS_SIMPLE_COMM       0x07
96 #define PCI_CLASS_BASE_PERIPH       0x08
97 #define PCI_CLASS_INPUT             0x09
98 #define PCI_CLASS_DOCK              0x0A
99 #define PCI_CLASS_PROCESSOR         0x0B
100 #define PCI_CLASS_SERIAL_BUS        0x0C
101 #define PCI_CLASS_WIRELESS          0x0D
102 #define PCI_CLASS_INTELLIGENT_IO    0x0E
103 #define PCI_CLASS_SATELLITE_COMM    0x0F
104 #define PCI_CLASS_ENCRYPTION        0x10
105 #define PCI_CLASS_DATA_ACQ          0x11
106 #define PCI_CLASS_UNDEFINED         0x99
107 
108 // Subclasses by category
109 // Mass storage
110 #define PCI_SUBCLASS_SCSI           0x00
111 #define PCI_SUBCLASS_IDE            0x01
112 #define PCI_SUBCLASS_FLOPPY_DISK    0x02
113 #define PCI_SUBCLASS_IPI_BUS        0x03
114 #define PCI_SUBCLASS_RAID_BUS       0x04
115 #define PCI_SUBCLASS_ATA            0x05
116 #define PCI_SUBCLASS_SATA           0x06
117 #define PCI_SUBCLASS_SERIAL_SCSI    0x07
118 #define PCI_SUBCLASS_NVMEM          0x08
119 #define PCI_SUBCLASS_MASS_STORAGE   0x80
120 // Network
121 #define PCI_SUBCLASS_ETHERNET       0x00
122 #define PCI_SUBCLASS_TOKEN_RING     0x01
123 #define PCI_SUBCLASS_FDDI           0x02
124 #define PCI_SUBCLASS_ATM            0x03
125 #define PCI_SUBCLASS_ISDN           0x04
126 #define PCI_SUBCLASS_WORLDFIP       0x05
127 #define PCI_SUBCLASS_PICMG          0x06
128 #define PCI_SUBCLASS_INFINIBAND     0x07
129 #define PCI_SUBCLASS_FABRIC         0x08
130 #define PCI_SUBCLASS_NETWORK        0x80
131 // Display
132 #define PCI_SUBCLASS_VGA            0x00
133 #define PCI_SUBCLASS_XGA            0x01
134 #define PCI_SUBCLASS_3D             0x02
135 #define PCI_SUBCLASS_DISPLAY        0x80
136 // Multimedia
137 #define PCI_SUBCLASS_VIDEO_CTRL     0x00
138 #define PCI_SUBCLASS_AUDIO_CTRL     0x01
139 #define PCI_SUBCLASS_TELEPHONY      0x02
140 #define PCI_SUBCLASS_AUDIO_DEVICE   0x03
141 #define PCI_SUBCLASS_MULTIMEDIA     0x80
142 // Memory
143 #define PCI_SUBCLASS_RAM            0x00
144 #define PCI_SUBCLASS_FLASH          0x01
145 #define PCI_SUBCLASS_MEMORY         0x80
146 // Bridge
147 #define PCI_SUBCLASS_HOST           0x00
148 #define PCI_SUBCLASS_ISA            0x01
149 #define PCI_SUBCLASS_EISA           0x02
150 #define PCI_SUBCLASS_MICROCHANNEL   0x03
151 #define PCI_SUBCLASS_PCI            0x04
152 #define PCI_SUBCLASS_PCMCIA         0x05
153 #define PCI_SUBCLASS_NUBUS          0x06
154 #define PCI_SUBCLASS_CARDBUS        0x07
155 #define PCI_SUBCLASS_RACEWAY        0x08
156 #define PCI_SUBCLASS_PCI_TO_PCI     0x09
157 #define PCI_SUBCLASS_INFI_PCI_HOST  0x0A
158 #define PCI_SUBCLASS_BRIDGE         0x80
159 // Communication
160 #define PCI_SUBCLASS_SERIAL         0x00
161 #define PCI_SUBCLASS_PARALLEL       0x01
162 #define PCI_SUBCLASS_MULTI_SERIAL   0x02
163 #define PCI_SUBCLASS_MODEM          0x03
164 #define PCI_SUBCLASS_GPIB_CTRL      0x04
165 #define PCI_SUBCLASS_SMARDT_CARD    0x05
166 #define PCI_SUBCLASS_COMMUNICATION  0x80
167 // Generic
168 #define PCI_SUBCLASS_PIC            0x00
169 #define PCI_SUBCLASS_DMA            0x01
170 #define PCI_SUBCLASS_TIMER          0x02
171 #define PCI_SUBCLASS_RTC            0x03
172 #define PCI_SUBCLASS_PCI_HOTPLUG    0x04
173 #define PCI_SUBCLASS_SD_HOST        0x05
174 #define PCI_SUBCLASS_IOMMU          0x06
175 #define PCI_SUBCLASS_SYSTEM_PERIPH  0x80
176 
177 typedef struct {
178     uint16_t vendor_id;
179     uint16_t device_id;
180     uint16_t command;
181     uint16_t status;
182     uint8_t revision_id_0;
183     uint8_t program_interface;
184     uint8_t sub_class;
185     uint8_t base_class;
186     uint8_t cache_line_size;
187     uint8_t latency_timer;
188     uint8_t header_type;
189     uint8_t bist;
190     uint32_t base_addresses[6];
191     uint32_t cardbus_cis_ptr;
192     uint16_t subsystem_vendor_id;
193     uint16_t subsystem_id;
194     uint32_t expansion_rom_address;
195     uint8_t capabilities_ptr;
196     uint8_t reserved_0[3];
197     uint32_t reserved_1;
198     uint8_t interrupt_line;
199     uint8_t interrupt_pin;
200     uint8_t min_grant;
201     uint8_t max_latency;
202 } __PACKED pci_config_t;
203 
204 /*
205  * Endian independent PCIe register access helpers.
206  */
pcie_read8(const volatile uint8_t * reg)207 static inline uint8_t  pcie_read8 (const volatile uint8_t*  reg) { return *reg; }
pcie_read16(const volatile uint16_t * reg)208 static inline uint16_t pcie_read16(const volatile uint16_t* reg) { return le16toh(*reg); }
pcie_read32(const volatile uint32_t * reg)209 static inline uint32_t pcie_read32(const volatile uint32_t* reg) { return le32toh(*reg); }
210 
pcie_write8(volatile uint8_t * reg,uint8_t val)211 static inline void pcie_write8 (volatile uint8_t*  reg, uint8_t  val) { *reg = val; }
pcie_write16(volatile uint16_t * reg,uint16_t val)212 static inline void pcie_write16(volatile uint16_t* reg, uint16_t val) { *reg = htole16(val); }
pcie_write32(volatile uint32_t * reg,uint32_t val)213 static inline void pcie_write32(volatile uint32_t* reg, uint32_t val) { *reg = htole32(val); }
214 
215 __END_CDECLS;
216