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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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