1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation. All rights reserved.
5 * Copyright (c) 2017, Western Digital Corporation or its affiliates.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #ifndef __NVME_PCI_H__
35 #define __NVME_PCI_H__
36
37 #include "nvme_common.h"
38
39 #ifndef __HAIKU__
40 #include <pciaccess.h>
41 #endif
42
43 #define NVME_PCI_PATH_MAX 256
44 #define NVME_PCI_CFG_SIZE 256
45 #define NVME_PCI_EXT_CAP_ID_SN 0x03
46
47 #define NVME_PCI_ANY_ID 0xffff
48 #define NVME_PCI_VID_INTEL 0x8086
49 #define NVME_PCI_VID_MEMBLAZE 0x1c5f
50
51 /*
52 * PCI class code for NVMe devices.
53 *
54 * Base class code 01h: mass storage
55 * Subclass code 08h: non-volatile memory
56 * Programming interface 02h: NVM Express
57 */
58 #define NVME_PCI_CLASS 0x010802
59
60 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_SNB0 0x3c20
61 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_SNB1 0x3c21
62 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_SNB2 0x3c22
63 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_SNB3 0x3c23
64 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_SNB4 0x3c24
65 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_SNB5 0x3c25
66 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_SNB6 0x3c26
67 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_SNB7 0x3c27
68 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_SNB8 0x3c2e
69 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_SNB9 0x3c2f
70
71 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_IVB0 0x0e20
72 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_IVB1 0x0e21
73 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_IVB2 0x0e22
74 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_IVB3 0x0e23
75 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_IVB4 0x0e24
76 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_IVB5 0x0e25
77 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_IVB6 0x0e26
78 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_IVB7 0x0e27
79 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_IVB8 0x0e2e
80 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_IVB9 0x0e2f
81
82 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_HSW0 0x2f20
83 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_HSW1 0x2f21
84 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_HSW2 0x2f22
85 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_HSW3 0x2f23
86 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_HSW4 0x2f24
87 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_HSW5 0x2f25
88 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_HSW6 0x2f26
89 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_HSW7 0x2f27
90 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_HSW8 0x2f2e
91 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_HSW9 0x2f2f
92
93 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BWD0 0x0C50
94 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BWD1 0x0C51
95 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BWD2 0x0C52
96 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BWD3 0x0C53
97
98 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDXDE0 0x6f50
99 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDXDE1 0x6f51
100 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDXDE2 0x6f52
101 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDXDE3 0x6f53
102
103 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDX0 0x6f20
104 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDX1 0x6f21
105 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDX2 0x6f22
106 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDX3 0x6f23
107 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDX4 0x6f24
108 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDX5 0x6f25
109 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDX6 0x6f26
110 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDX7 0x6f27
111 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDX8 0x6f2e
112 #define NVME_PCI_DEVICE_ID_INTEL_IOAT_BDX9 0x6f2f
113
114 struct pci_slot_match;
115
116 struct pci_id {
117 uint16_t vendor_id;
118 uint16_t device_id;
119 uint16_t subvendor_id;
120 uint16_t subdevice_id;
121 };
122
123 /*
124 * Initialize PCI subsystem.
125 */
126 extern int nvme_pci_init(void);
127
128 /*
129 * Search a PCI device and grab it if found.
130 */
131 extern struct pci_device *
132 nvme_pci_device_probe(const struct pci_slot_match *slot);
133
134 /*
135 * Reset a PCI device.
136 */
137 extern int nvme_pci_device_reset(struct pci_device *dev);
138
139 /*
140 * Get a device serial number.
141 */
142 extern int nvme_pci_device_get_serial_number(struct pci_device *dev,
143 char *sn, size_t len);
144
145 /*
146 * Compare two devices.
147 * Return 0 if the devices are the same, 1 otherwise.
148 */
nvme_pci_dev_cmp(struct pci_device * pci_dev1,struct pci_device * pci_dev2)149 static inline int nvme_pci_dev_cmp(struct pci_device *pci_dev1,
150 struct pci_device *pci_dev2)
151 {
152 if (pci_dev1 == pci_dev2)
153 return 0;
154
155 if (pci_dev1->domain == pci_dev2->domain &&
156 pci_dev1->bus == pci_dev2->bus &&
157 pci_dev1->dev == pci_dev2->dev &&
158 pci_dev1->func == pci_dev2->func)
159 return 0;
160
161 return 1;
162 }
163
164 /*
165 * Get a device PCI ID.
166 */
nvme_pci_get_pci_id(struct pci_device * pci_dev,struct pci_id * pci_id)167 static inline void nvme_pci_get_pci_id(struct pci_device *pci_dev,
168 struct pci_id *pci_id)
169 {
170 pci_id->vendor_id = pci_dev->vendor_id;
171 pci_id->device_id = pci_dev->device_id;
172 pci_id->subvendor_id = pci_dev->subvendor_id;
173 pci_id->subdevice_id = pci_dev->subdevice_id;
174 }
175
176 #ifdef __HAIKU__
177 int nvme_pcicfg_read8(struct pci_device *dev, uint8_t *value, uint32_t offset);
178 int nvme_pcicfg_write8(struct pci_device *dev, uint8_t value, uint32_t offset);
179 int nvme_pcicfg_read16(struct pci_device *dev, uint16_t *value, uint32_t offset);
180 int nvme_pcicfg_write16(struct pci_device *dev, uint16_t value, uint32_t offset);
181 int nvme_pcicfg_read32(struct pci_device *dev, uint32_t *value, uint32_t offset);
182 int nvme_pcicfg_write32(struct pci_device *dev, uint32_t value, uint32_t offset);
183 int nvme_pcicfg_map_bar(void *devhandle, unsigned int bar, bool read_only,
184 void **mapped_addr);
185 int nvme_pcicfg_map_bar_write_combine(void *devhandle, unsigned int bar,
186 void **mapped_addr);
187 int nvme_pcicfg_unmap_bar(void *devhandle, unsigned int bar, void *addr);
188 void nvme_pcicfg_get_bar_addr_len(void *devhandle, unsigned int bar,
189 uint64_t *addr, uint64_t *size);
190 #else
191 /*
192 * Read a device config register.
193 */
nvme_pcicfg_read8(struct pci_device * dev,uint8_t * value,uint32_t offset)194 static inline int nvme_pcicfg_read8(struct pci_device *dev,
195 uint8_t *value, uint32_t offset)
196 {
197 return pci_device_cfg_read_u8(dev, value, offset);
198 }
199
200 /*
201 * Write a device config register.
202 */
nvme_pcicfg_write8(struct pci_device * dev,uint8_t value,uint32_t offset)203 static inline int nvme_pcicfg_write8(struct pci_device *dev,
204 uint8_t value, uint32_t offset)
205 {
206 return pci_device_cfg_write_u8(dev, value, offset);
207 }
208
209 /*
210 * Read a device config register.
211 */
nvme_pcicfg_read16(struct pci_device * dev,uint16_t * value,uint32_t offset)212 static inline int nvme_pcicfg_read16(struct pci_device *dev,
213 uint16_t *value, uint32_t offset)
214 {
215 return pci_device_cfg_read_u16(dev, value, offset);
216 }
217
218 /*
219 * Write a device config register.
220 */
nvme_pcicfg_write16(struct pci_device * dev,uint16_t value,uint32_t offset)221 static inline int nvme_pcicfg_write16(struct pci_device *dev,
222 uint16_t value, uint32_t offset)
223 {
224 return pci_device_cfg_write_u16(dev, value, offset);
225 }
226
227 /*
228 * Read a device config register.
229 */
nvme_pcicfg_read32(struct pci_device * dev,uint32_t * value,uint32_t offset)230 static inline int nvme_pcicfg_read32(struct pci_device *dev,
231 uint32_t *value, uint32_t offset)
232 {
233 return pci_device_cfg_read_u32(dev, value, offset);
234 }
235
236 /*
237 * Write a device config register.
238 */
nvme_pcicfg_write32(struct pci_device * dev,uint32_t value,uint32_t offset)239 static inline int nvme_pcicfg_write32(struct pci_device *dev,
240 uint32_t value, uint32_t offset)
241 {
242 return pci_device_cfg_write_u32(dev, value, offset);
243 }
244
245 /*
246 * Map a device PCI BAR.
247 */
nvme_pcicfg_map_bar(void * devhandle,unsigned int bar,bool read_only,void ** mapped_addr)248 static inline int nvme_pcicfg_map_bar(void *devhandle, unsigned int bar,
249 bool read_only, void **mapped_addr)
250 {
251 struct pci_device *dev = devhandle;
252 uint32_t flags = (read_only ? 0 : PCI_DEV_MAP_FLAG_WRITABLE);
253
254 return pci_device_map_range(dev, dev->regions[bar].base_addr,
255 dev->regions[bar].size, flags, mapped_addr);
256 }
257
258 /*
259 * Map a device PCI BAR (write combine).
260 */
nvme_pcicfg_map_bar_write_combine(void * devhandle,unsigned int bar,void ** mapped_addr)261 static inline int nvme_pcicfg_map_bar_write_combine(void *devhandle,
262 unsigned int bar,
263 void **mapped_addr)
264 {
265 struct pci_device *dev = devhandle;
266 uint32_t flags = PCI_DEV_MAP_FLAG_WRITABLE |
267 PCI_DEV_MAP_FLAG_WRITE_COMBINE;
268
269 return pci_device_map_range(dev, dev->regions[bar].base_addr,
270 dev->regions[bar].size, flags, mapped_addr);
271 }
272
273 /*
274 * Unmap a device PCI BAR.
275 */
nvme_pcicfg_unmap_bar(void * devhandle,unsigned int bar,void * addr)276 static inline int nvme_pcicfg_unmap_bar(void *devhandle, unsigned int bar,
277 void *addr)
278 {
279 struct pci_device *dev = devhandle;
280
281 return pci_device_unmap_range(dev, addr, dev->regions[bar].size);
282 }
283
284 /*
285 * Get a device PCI BAR address and length.
286 */
nvme_pcicfg_get_bar_addr_len(void * devhandle,unsigned int bar,uint64_t * addr,uint64_t * size)287 static inline void nvme_pcicfg_get_bar_addr_len(void *devhandle,
288 unsigned int bar,
289 uint64_t *addr, uint64_t *size)
290 {
291 struct pci_device *dev = devhandle;
292
293 *addr = (uint64_t)dev->regions[bar].base_addr;
294 *size = (uint64_t)dev->regions[bar].size;
295 }
296 #endif
297
298 #endif /* __NVME_PCI_H__ */
299