xref: /haiku/src/add-ons/kernel/drivers/disk/nvme/libnvme/nvme_pci.h (revision af4a03df24c7d171cab14019f0c53a6804b79554)
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