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
114struct pci_slot_match;
115
116struct 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 */
126extern int nvme_pci_init(void);
127
128/*
129 * Search a PCI device and grab it if found.
130 */
131extern struct pci_device *
132nvme_pci_device_probe(const struct pci_slot_match *slot);
133
134/*
135 * Reset a PCI device.
136 */
137extern int nvme_pci_device_reset(struct pci_device *dev);
138
139/*
140 * Get a device serial number.
141 */
142extern 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 */
149static 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 */
167static 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__
177int nvme_pcicfg_read8(struct pci_device *dev, uint8_t *value, uint32_t offset);
178int nvme_pcicfg_write8(struct pci_device *dev, uint8_t value, uint32_t offset);
179int nvme_pcicfg_read16(struct pci_device *dev, uint16_t *value, uint32_t offset);
180int nvme_pcicfg_write16(struct pci_device *dev, uint16_t value, uint32_t offset);
181int nvme_pcicfg_read32(struct pci_device *dev, uint32_t *value, uint32_t offset);
182int nvme_pcicfg_write32(struct pci_device *dev, uint32_t value, uint32_t offset);
183int nvme_pcicfg_map_bar(void *devhandle, unsigned int bar, bool read_only,
184	void **mapped_addr);
185int nvme_pcicfg_map_bar_write_combine(void *devhandle, unsigned int bar,
186	void **mapped_addr);
187int nvme_pcicfg_unmap_bar(void *devhandle, unsigned int bar, void *addr);
188void 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 */
194static 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 */
203static 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 */
212static 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 */
221static 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 */
230static 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 */
239static 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 */
248static 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 */
261static 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 */
276static 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 */
287static 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