pci.h revision 310252
133965Sjdp/*- 278828Sobrien * Copyright (c) 2010 Isilon Systems, Inc. 333965Sjdp * Copyright (c) 2010 iX Systems, Inc. 433965Sjdp * Copyright (c) 2010 Panasas, Inc. 533965Sjdp * Copyright (c) 2013-2016 Mellanox Technologies, Ltd. 633965Sjdp * All rights reserved. 733965Sjdp * 833965Sjdp * Redistribution and use in source and binary forms, with or without 933965Sjdp * modification, are permitted provided that the following conditions 1033965Sjdp * are met: 1133965Sjdp * 1. Redistributions of source code must retain the above copyright 1233965Sjdp * notice unmodified, this list of conditions, and the following 1333965Sjdp * disclaimer. 1433965Sjdp * 2. Redistributions in binary form must reproduce the above copyright 1533965Sjdp * notice, this list of conditions and the following disclaimer in the 1633965Sjdp * documentation and/or other materials provided with the distribution. 1733965Sjdp * 1833965Sjdp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1933965Sjdp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2033965Sjdp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2133965Sjdp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2233965Sjdp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2333965Sjdp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2433965Sjdp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2533965Sjdp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2633965Sjdp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2733965Sjdp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2833965Sjdp * 2933965Sjdp * $FreeBSD: stable/11/sys/compat/linuxkpi/common/include/linux/pci.h 310252 2016-12-19 09:49:16Z hselasky $ 3033965Sjdp */ 3133965Sjdp#ifndef _LINUX_PCI_H_ 3233965Sjdp#define _LINUX_PCI_H_ 3333965Sjdp 3433965Sjdp#define CONFIG_PCI_MSI 3533965Sjdp 3633965Sjdp#include <linux/types.h> 3733965Sjdp 3833965Sjdp#include <sys/param.h> 3933965Sjdp#include <sys/bus.h> 4033965Sjdp#include <sys/pciio.h> 4133965Sjdp#include <sys/rman.h> 4233965Sjdp#include <dev/pci/pcivar.h> 4333965Sjdp#include <dev/pci/pcireg.h> 4433965Sjdp#include <dev/pci/pci_private.h> 4533965Sjdp 4633965Sjdp#include <machine/resource.h> 4733965Sjdp 4833965Sjdp#include <linux/list.h> 4933965Sjdp#include <linux/dmapool.h> 5033965Sjdp#include <linux/dma-mapping.h> 5133965Sjdp#include <linux/compiler.h> 5233965Sjdp#include <linux/errno.h> 5333965Sjdp#include <asm/atomic.h> 5433965Sjdp#include <linux/device.h> 5533965Sjdp 5633965Sjdpstruct pci_device_id { 5733965Sjdp uint32_t vendor; 5833965Sjdp uint32_t device; 5933965Sjdp uint32_t subvendor; 6033965Sjdp uint32_t subdevice; 6133965Sjdp uint32_t class_mask; 6233965Sjdp uintptr_t driver_data; 6333965Sjdp}; 6433965Sjdp 6533965Sjdp#define MODULE_DEVICE_TABLE(bus, table) 6633965Sjdp#define PCI_ANY_ID (-1) 6733965Sjdp#define PCI_VENDOR_ID_APPLE 0x106b 6833965Sjdp#define PCI_VENDOR_ID_ASUSTEK 0x1043 6933965Sjdp#define PCI_VENDOR_ID_ATI 0x1002 7033965Sjdp#define PCI_VENDOR_ID_DELL 0x1028 7133965Sjdp#define PCI_VENDOR_ID_HP 0x103c 7233965Sjdp#define PCI_VENDOR_ID_IBM 0x1014 7333965Sjdp#define PCI_VENDOR_ID_INTEL 0x8086 7433965Sjdp#define PCI_VENDOR_ID_MELLANOX 0x15b3 7533965Sjdp#define PCI_VENDOR_ID_SERVERWORKS 0x1166 7633965Sjdp#define PCI_VENDOR_ID_SONY 0x104d 7733965Sjdp#define PCI_VENDOR_ID_TOPSPIN 0x1867 7833965Sjdp#define PCI_VENDOR_ID_VIA 0x1106 7933965Sjdp#define PCI_DEVICE_ID_MELLANOX_TAVOR 0x5a44 8033965Sjdp#define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE 0x5a46 8133965Sjdp#define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278 8233965Sjdp#define PCI_DEVICE_ID_MELLANOX_ARBEL 0x6282 8333965Sjdp#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c 8433965Sjdp#define PCI_DEVICE_ID_MELLANOX_SINAI 0x6274 8533965Sjdp 8633965Sjdp#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) 8733965Sjdp#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) 8833965Sjdp#define PCI_FUNC(devfn) ((devfn) & 0x07) 8933965Sjdp 9033965Sjdp#define PCI_VDEVICE(_vendor, _device) \ 9133965Sjdp .vendor = PCI_VENDOR_ID_##_vendor, .device = (_device), \ 9233965Sjdp .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID 9333965Sjdp#define PCI_DEVICE(_vendor, _device) \ 9433965Sjdp .vendor = (_vendor), .device = (_device), \ 9533965Sjdp .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID 9633965Sjdp 9733965Sjdp#define to_pci_dev(n) container_of(n, struct pci_dev, dev) 9833965Sjdp 9933965Sjdp#define PCI_VENDOR_ID PCIR_DEVVENDOR 10033965Sjdp#define PCI_COMMAND PCIR_COMMAND 10133965Sjdp#define PCI_EXP_DEVCTL PCIER_DEVICE_CTL /* Device Control */ 10233965Sjdp#define PCI_EXP_LNKCTL PCIER_LINK_CTL /* Link Control */ 10333965Sjdp#define PCI_EXP_FLAGS_TYPE PCIEM_FLAGS_TYPE /* Device/Port type */ 10433965Sjdp#define PCI_EXP_DEVCAP PCIER_DEVICE_CAP /* Device capabilities */ 10533965Sjdp#define PCI_EXP_DEVSTA PCIER_DEVICE_STA /* Device Status */ 10633965Sjdp#define PCI_EXP_LNKCAP PCIER_LINK_CAP /* Link Capabilities */ 10733965Sjdp#define PCI_EXP_LNKSTA PCIER_LINK_STA /* Link Status */ 10833965Sjdp#define PCI_EXP_SLTCAP PCIER_SLOT_CAP /* Slot Capabilities */ 10933965Sjdp#define PCI_EXP_SLTCTL PCIER_SLOT_CTL /* Slot Control */ 11033965Sjdp#define PCI_EXP_SLTSTA PCIER_SLOT_STA /* Slot Status */ 11133965Sjdp#define PCI_EXP_RTCTL PCIER_ROOT_CTL /* Root Control */ 11233965Sjdp#define PCI_EXP_RTCAP PCIER_ROOT_CAP /* Root Capabilities */ 11333965Sjdp#define PCI_EXP_RTSTA PCIER_ROOT_STA /* Root Status */ 11433965Sjdp#define PCI_EXP_DEVCAP2 PCIER_DEVICE_CAP2 /* Device Capabilities 2 */ 11533965Sjdp#define PCI_EXP_DEVCTL2 PCIER_DEVICE_CTL2 /* Device Control 2 */ 11633965Sjdp#define PCI_EXP_LNKCAP2 PCIER_LINK_CAP2 /* Link Capabilities 2 */ 11777298Sobrien#define PCI_EXP_LNKCTL2 PCIER_LINK_CTL2 /* Link Control 2 */ 11877298Sobrien#define PCI_EXP_LNKSTA2 PCIER_LINK_STA2 /* Link Status 2 */ 11977298Sobrien#define PCI_EXP_FLAGS PCIER_FLAGS /* Capabilities register */ 12077298Sobrien#define PCI_EXP_FLAGS_VERS PCIEM_FLAGS_VERSION /* Capability version */ 12133965Sjdp#define PCI_EXP_TYPE_ROOT_PORT PCIEM_TYPE_ROOT_PORT /* Root Port */ 12277298Sobrien#define PCI_EXP_TYPE_ENDPOINT PCIEM_TYPE_ENDPOINT /* Express Endpoint */ 12377298Sobrien#define PCI_EXP_TYPE_LEG_END PCIEM_TYPE_LEGACY_ENDPOINT /* Legacy Endpoint */ 12477298Sobrien#define PCI_EXP_TYPE_DOWNSTREAM PCIEM_TYPE_DOWNSTREAM_PORT /* Downstream Port */ 12577298Sobrien#define PCI_EXP_FLAGS_SLOT PCIEM_FLAGS_SLOT /* Slot implemented */ 12677298Sobrien#define PCI_EXP_TYPE_RC_EC PCIEM_TYPE_ROOT_EC /* Root Complex Event Collector */ 12777298Sobrien#define PCI_EXP_LNKCAP_SLS_2_5GB 0x01 /* Supported Link Speed 2.5GT/s */ 12833965Sjdp#define PCI_EXP_LNKCAP_SLS_5_0GB 0x02 /* Supported Link Speed 5.0GT/s */ 12933965Sjdp#define PCI_EXP_LNKCAP_MLW 0x03f0 /* Maximum Link Width */ 13033965Sjdp#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x02 /* Supported Link Speed 2.5GT/s */ 13133965Sjdp#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x04 /* Supported Link Speed 5.0GT/s */ 13233965Sjdp#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x08 /* Supported Link Speed 8.0GT/s */ 13377298Sobrien 13477298Sobrien#define PCI_EXP_LNKCTL_HAWD PCIEM_LINK_CTL_HAWD 13577298Sobrien#define PCI_EXP_LNKCAP_CLKPM 0x00040000 13677298Sobrien#define PCI_EXP_DEVSTA_TRPND 0x0020 13777298Sobrien 13877298Sobrien#define IORESOURCE_MEM (1 << SYS_RES_MEMORY) 13977298Sobrien#define IORESOURCE_IO (1 << SYS_RES_IOPORT) 14077298Sobrien#define IORESOURCE_IRQ (1 << SYS_RES_IRQ) 14177298Sobrien 14277298Sobrienenum pci_bus_speed { 14377298Sobrien PCI_SPEED_UNKNOWN = -1, 14433965Sjdp PCIE_SPEED_2_5GT, 14533965Sjdp PCIE_SPEED_5_0GT, 14633965Sjdp PCIE_SPEED_8_0GT, 14733965Sjdp}; 14833965Sjdp 14977298Sobrienenum pcie_link_width { 15033965Sjdp PCIE_LNK_WIDTH_UNKNOWN = 0xFF, 15133965Sjdp}; 15233965Sjdp 15333965Sjdptypedef int pci_power_t; 15433965Sjdp 15533965Sjdp#define PCI_D0 PCI_POWERSTATE_D0 15633965Sjdp#define PCI_D1 PCI_POWERSTATE_D1 15733965Sjdp#define PCI_D2 PCI_POWERSTATE_D2 15833965Sjdp#define PCI_D3hot PCI_POWERSTATE_D3 15933965Sjdp#define PCI_D3cold 4 16077298Sobrien 16133965Sjdp#define PCI_POWER_ERROR PCI_POWERSTATE_UNKNOWN 16277298Sobrien 16333965Sjdpstruct pci_dev; 16477298Sobrien 16533965Sjdpstruct pci_driver { 16677298Sobrien struct list_head links; 16733965Sjdp char *name; 16877298Sobrien const struct pci_device_id *id_table; 16933965Sjdp int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); 17077298Sobrien void (*remove)(struct pci_dev *dev); 17133965Sjdp int (*suspend) (struct pci_dev *dev, pm_message_t state); /* Device suspended */ 17277298Sobrien int (*resume) (struct pci_dev *dev); /* Device woken up */ 17333965Sjdp void (*shutdown) (struct pci_dev *dev); /* Device shutdown */ 17433965Sjdp driver_t driver; 17533965Sjdp devclass_t bsdclass; 17633965Sjdp const struct pci_error_handlers *err_handler; 17733965Sjdp}; 17833965Sjdp 17933965Sjdpextern struct list_head pci_drivers; 18033965Sjdpextern struct list_head pci_devices; 18177298Sobrienextern spinlock_t pci_lock; 18233965Sjdp 18333965Sjdp#define __devexit_p(x) x 18433965Sjdp 18533965Sjdpstruct pci_dev { 18633965Sjdp struct device dev; 18733965Sjdp struct list_head links; 18833965Sjdp struct pci_driver *pdrv; 18933965Sjdp uint64_t dma_mask; 19033965Sjdp uint16_t device; 19133965Sjdp uint16_t vendor; 19233965Sjdp unsigned int irq; 19333965Sjdp unsigned int devfn; 19433965Sjdp u8 revision; 19533965Sjdp}; 19633965Sjdp 19733965Sjdpstatic inline struct resource_list_entry * 19833965Sjdplinux_pci_get_rle(struct pci_dev *pdev, int type, int rid) 19933965Sjdp{ 20033965Sjdp struct pci_devinfo *dinfo; 20133965Sjdp struct resource_list *rl; 20233965Sjdp 20333965Sjdp dinfo = device_get_ivars(pdev->dev.bsddev); 20433965Sjdp rl = &dinfo->resources; 20533965Sjdp return resource_list_find(rl, type, rid); 20633965Sjdp} 20733965Sjdp 20877298Sobrienstatic inline struct resource_list_entry * 20933965Sjdplinux_pci_get_bar(struct pci_dev *pdev, int bar) 21033965Sjdp{ 21133965Sjdp struct resource_list_entry *rle; 21233965Sjdp 21333965Sjdp bar = PCIR_BAR(bar); 21433965Sjdp if ((rle = linux_pci_get_rle(pdev, SYS_RES_MEMORY, bar)) == NULL) 21533965Sjdp rle = linux_pci_get_rle(pdev, SYS_RES_IOPORT, bar); 21633965Sjdp return (rle); 21733965Sjdp} 21833965Sjdp 21933965Sjdpstatic inline struct device * 22033965Sjdplinux_pci_find_irq_dev(unsigned int irq) 22133965Sjdp{ 22233965Sjdp struct pci_dev *pdev; 22333965Sjdp 22433965Sjdp spin_lock(&pci_lock); 22533965Sjdp list_for_each_entry(pdev, &pci_devices, links) { 22633965Sjdp if (irq == pdev->dev.irq) 22733965Sjdp break; 22833965Sjdp if (irq >= pdev->dev.msix && irq < pdev->dev.msix_max) 22933965Sjdp break; 23033965Sjdp } 23133965Sjdp spin_unlock(&pci_lock); 23233965Sjdp if (pdev) 23333965Sjdp return &pdev->dev; 23433965Sjdp return (NULL); 23533965Sjdp} 23633965Sjdp 23733965Sjdpstatic inline unsigned long 23833965Sjdppci_resource_start(struct pci_dev *pdev, int bar) 23933965Sjdp{ 24033965Sjdp struct resource_list_entry *rle; 24133965Sjdp 24233965Sjdp if ((rle = linux_pci_get_bar(pdev, bar)) == NULL) 24333965Sjdp return (0); 24433965Sjdp return rle->start; 24533965Sjdp} 24633965Sjdp 24733965Sjdpstatic inline unsigned long 24833965Sjdppci_resource_len(struct pci_dev *pdev, int bar) 24933965Sjdp{ 25033965Sjdp struct resource_list_entry *rle; 25177298Sobrien 25233965Sjdp if ((rle = linux_pci_get_bar(pdev, bar)) == NULL) 25333965Sjdp return (0); 25433965Sjdp return rle->count; 25533965Sjdp} 25633965Sjdp 25733965Sjdpstatic inline int 25833965Sjdppci_resource_type(struct pci_dev *pdev, int bar) 25933965Sjdp{ 26033965Sjdp struct pci_map *pm; 26133965Sjdp 26233965Sjdp pm = pci_find_bar(pdev->dev.bsddev, PCIR_BAR(bar)); 26333965Sjdp if (!pm) 26433965Sjdp return (-1); 26533965Sjdp 26633965Sjdp if (PCI_BAR_IO(pm->pm_value)) 26733965Sjdp return (SYS_RES_IOPORT); 26833965Sjdp else 26933965Sjdp return (SYS_RES_MEMORY); 27033965Sjdp} 27133965Sjdp 27277298Sobrien/* 27377298Sobrien * All drivers just seem to want to inspect the type not flags. 27477298Sobrien */ 27533965Sjdpstatic inline int 27633965Sjdppci_resource_flags(struct pci_dev *pdev, int bar) 27733965Sjdp{ 27833965Sjdp int type; 27933965Sjdp 28033965Sjdp type = pci_resource_type(pdev, bar); 28133965Sjdp if (type < 0) 28277298Sobrien return (0); 28333965Sjdp return (1 << type); 28433965Sjdp} 28533965Sjdp 28677298Sobrienstatic inline const char * 28733965Sjdppci_name(struct pci_dev *d) 28833965Sjdp{ 28933965Sjdp 29033965Sjdp return device_get_desc(d->dev.bsddev); 29133965Sjdp} 29233965Sjdp 29333965Sjdpstatic inline void * 29433965Sjdppci_get_drvdata(struct pci_dev *pdev) 29533965Sjdp{ 29633965Sjdp 29777298Sobrien return dev_get_drvdata(&pdev->dev); 29833965Sjdp} 29933965Sjdp 30033965Sjdpstatic inline void 30133965Sjdppci_set_drvdata(struct pci_dev *pdev, void *data) 30233965Sjdp{ 30377298Sobrien 30477298Sobrien dev_set_drvdata(&pdev->dev, data); 30533965Sjdp} 30633965Sjdp 30733965Sjdpstatic inline int 30877298Sobrienpci_enable_device(struct pci_dev *pdev) 30977298Sobrien{ 31077298Sobrien 31177298Sobrien pci_enable_io(pdev->dev.bsddev, SYS_RES_IOPORT); 31233965Sjdp pci_enable_io(pdev->dev.bsddev, SYS_RES_MEMORY); 31333965Sjdp return (0); 31433965Sjdp} 31533965Sjdp 31633965Sjdpstatic inline void 31733965Sjdppci_disable_device(struct pci_dev *pdev) 31833965Sjdp{ 31977298Sobrien} 32033965Sjdp 32133965Sjdpstatic inline int 32233965Sjdppci_set_master(struct pci_dev *pdev) 32333965Sjdp{ 32433965Sjdp 32533965Sjdp pci_enable_busmaster(pdev->dev.bsddev); 32633965Sjdp return (0); 32777298Sobrien} 32833965Sjdp 32933965Sjdpstatic inline int 33033965Sjdppci_set_power_state(struct pci_dev *pdev, int state) 33133965Sjdp{ 33233965Sjdp 33333965Sjdp pci_set_powerstate(pdev->dev.bsddev, state); 33433965Sjdp return (0); 33533965Sjdp} 33633965Sjdp 33733965Sjdpstatic inline int 33833965Sjdppci_clear_master(struct pci_dev *pdev) 33933965Sjdp{ 34033965Sjdp 34133965Sjdp pci_disable_busmaster(pdev->dev.bsddev); 34233965Sjdp return (0); 34333965Sjdp} 34433965Sjdp 34533965Sjdpstatic inline int 34677298Sobrienpci_request_region(struct pci_dev *pdev, int bar, const char *res_name) 34733965Sjdp{ 34833965Sjdp int rid; 34933965Sjdp int type; 35060484Sobrien 35133965Sjdp type = pci_resource_type(pdev, bar); 35233965Sjdp if (type < 0) 35333965Sjdp return (-ENODEV); 35433965Sjdp rid = PCIR_BAR(bar); 35533965Sjdp if (bus_alloc_resource_any(pdev->dev.bsddev, type, &rid, 35633965Sjdp RF_ACTIVE) == NULL) 35777298Sobrien return (-EINVAL); 35833965Sjdp return (0); 35933965Sjdp} 36033965Sjdp 36133965Sjdpstatic inline void 36233965Sjdppci_release_region(struct pci_dev *pdev, int bar) 36333965Sjdp{ 36433965Sjdp struct resource_list_entry *rle; 36533965Sjdp 36633965Sjdp if ((rle = linux_pci_get_bar(pdev, bar)) == NULL) 36733965Sjdp return; 36833965Sjdp bus_release_resource(pdev->dev.bsddev, rle->type, rle->rid, rle->res); 36933965Sjdp} 37033965Sjdp 37133965Sjdpstatic inline void 37233965Sjdppci_release_regions(struct pci_dev *pdev) 37333965Sjdp{ 37433965Sjdp int i; 37533965Sjdp 37633965Sjdp for (i = 0; i <= PCIR_MAX_BAR_0; i++) 37733965Sjdp pci_release_region(pdev, i); 37833965Sjdp} 37933965Sjdp 38033965Sjdpstatic inline int 38133965Sjdppci_request_regions(struct pci_dev *pdev, const char *res_name) 38233965Sjdp{ 38333965Sjdp int error; 38433965Sjdp int i; 38533965Sjdp 38633965Sjdp for (i = 0; i <= PCIR_MAX_BAR_0; i++) { 38733965Sjdp error = pci_request_region(pdev, i, res_name); 38833965Sjdp if (error && error != -ENODEV) { 38933965Sjdp pci_release_regions(pdev); 39033965Sjdp return (error); 39133965Sjdp } 39233965Sjdp } 39333965Sjdp return (0); 39433965Sjdp} 39533965Sjdp 39633965Sjdpstatic inline void 39733965Sjdppci_disable_msix(struct pci_dev *pdev) 39833965Sjdp{ 39933965Sjdp 40033965Sjdp pci_release_msi(pdev->dev.bsddev); 40177298Sobrien} 40233965Sjdp 40333965Sjdpstatic inline bus_addr_t 40433965Sjdppci_bus_address(struct pci_dev *pdev, int bar) 40533965Sjdp{ 40633965Sjdp 40733965Sjdp return (pci_resource_start(pdev, bar)); 40833965Sjdp} 40933965Sjdp 41033965Sjdp#define PCI_CAP_ID_EXP PCIY_EXPRESS 41133965Sjdp#define PCI_CAP_ID_PCIX PCIY_PCIX 41233965Sjdp#define PCI_CAP_ID_AGP PCIY_AGP 41333965Sjdp#define PCI_CAP_ID_PM PCIY_PMG 41433965Sjdp 41533965Sjdp#define PCI_EXP_DEVCTL PCIER_DEVICE_CTL 41633965Sjdp#define PCI_EXP_DEVCTL_PAYLOAD PCIEM_CTL_MAX_PAYLOAD 41733965Sjdp#define PCI_EXP_DEVCTL_READRQ PCIEM_CTL_MAX_READ_REQUEST 41833965Sjdp#define PCI_EXP_LNKCTL PCIER_LINK_CTL 41933965Sjdp#define PCI_EXP_LNKSTA PCIER_LINK_STA 42033965Sjdp 42133965Sjdpstatic inline int 42233965Sjdppci_find_capability(struct pci_dev *pdev, int capid) 42333965Sjdp{ 42433965Sjdp int reg; 42533965Sjdp 42633965Sjdp if (pci_find_cap(pdev->dev.bsddev, capid, ®)) 42733965Sjdp return (0); 42833965Sjdp return (reg); 42933965Sjdp} 43033965Sjdp 43133965Sjdpstatic inline int pci_pcie_cap(struct pci_dev *dev) 43233965Sjdp{ 43333965Sjdp return pci_find_capability(dev, PCI_CAP_ID_EXP); 43433965Sjdp} 43533965Sjdp 43633965Sjdp 43733965Sjdpstatic inline int 43833965Sjdppci_read_config_byte(struct pci_dev *pdev, int where, u8 *val) 43933965Sjdp{ 44033965Sjdp 44133965Sjdp *val = (u8)pci_read_config(pdev->dev.bsddev, where, 1); 44233965Sjdp return (0); 44333965Sjdp} 44433965Sjdp 44533965Sjdpstatic inline int 44633965Sjdppci_read_config_word(struct pci_dev *pdev, int where, u16 *val) 44733965Sjdp{ 44833965Sjdp 44933965Sjdp *val = (u16)pci_read_config(pdev->dev.bsddev, where, 2); 45060484Sobrien return (0); 45160484Sobrien} 45233965Sjdp 45333965Sjdpstatic inline int 45433965Sjdppci_read_config_dword(struct pci_dev *pdev, int where, u32 *val) 45560484Sobrien{ 45633965Sjdp 45760484Sobrien *val = (u32)pci_read_config(pdev->dev.bsddev, where, 4); 45860484Sobrien return (0); 45960484Sobrien} 46060484Sobrien 46160484Sobrienstatic inline int 46260484Sobrienpci_write_config_byte(struct pci_dev *pdev, int where, u8 val) 46360484Sobrien{ 46433965Sjdp 46533965Sjdp pci_write_config(pdev->dev.bsddev, where, val, 1); 46633965Sjdp return (0); 46733965Sjdp} 46833965Sjdp 46933965Sjdpstatic inline int 47033965Sjdppci_write_config_word(struct pci_dev *pdev, int where, u16 val) 47133965Sjdp{ 47233965Sjdp 47333965Sjdp pci_write_config(pdev->dev.bsddev, where, val, 2); 47433965Sjdp return (0); 47533965Sjdp} 47633965Sjdp 47733965Sjdpstatic inline int 47833965Sjdppci_write_config_dword(struct pci_dev *pdev, int where, u32 val) 47933965Sjdp{ 48033965Sjdp 48160484Sobrien pci_write_config(pdev->dev.bsddev, where, val, 4); 48260484Sobrien return (0); 48360484Sobrien} 48433965Sjdp 48533965Sjdpextern int pci_register_driver(struct pci_driver *pdrv); 48633965Sjdpextern void pci_unregister_driver(struct pci_driver *pdrv); 48733965Sjdp 48860484Sobrienstruct msix_entry { 48960484Sobrien int entry; 49060484Sobrien int vector; 49160484Sobrien}; 49233965Sjdp 49333965Sjdp/* 49433965Sjdp * Enable msix, positive errors indicate actual number of available 49533965Sjdp * vectors. Negative errors are failures. 49633965Sjdp * 49733965Sjdp * NB: define added to prevent this definition of pci_enable_msix from 49833965Sjdp * clashing with the native FreeBSD version. 49977298Sobrien */ 50033965Sjdp#define pci_enable_msix linux_pci_enable_msix 50133965Sjdpstatic inline int 50233965Sjdppci_enable_msix(struct pci_dev *pdev, struct msix_entry *entries, int nreq) 50378828Sobrien{ 50433965Sjdp struct resource_list_entry *rle; 50533965Sjdp int error; 50633965Sjdp int avail; 50733965Sjdp int i; 50833965Sjdp 50933965Sjdp avail = pci_msix_count(pdev->dev.bsddev); 51033965Sjdp if (avail < nreq) { 51133965Sjdp if (avail == 0) 51233965Sjdp return -EINVAL; 51333965Sjdp return avail; 51433965Sjdp } 51533965Sjdp avail = nreq; 51633965Sjdp if ((error = -pci_alloc_msix(pdev->dev.bsddev, &avail)) != 0) 51733965Sjdp return error; 51833965Sjdp /* 51977298Sobrien * Handle case where "pci_alloc_msix()" may allocate less 52033965Sjdp * interrupts than available and return with no error: 52133965Sjdp */ 52233965Sjdp if (avail < nreq) { 52377298Sobrien pci_release_msi(pdev->dev.bsddev); 52433965Sjdp return avail; 52533965Sjdp } 52633965Sjdp rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 1); 52733965Sjdp pdev->dev.msix = rle->start; 52833965Sjdp pdev->dev.msix_max = rle->start + avail; 52933965Sjdp for (i = 0; i < nreq; i++) 53033965Sjdp entries[i].vector = pdev->dev.msix + i; 53133965Sjdp return (0); 53233965Sjdp} 53333965Sjdp 53433965Sjdp#define pci_enable_msix_range linux_pci_enable_msix_range 53533965Sjdpstatic inline int 53633965Sjdppci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, 53733965Sjdp int minvec, int maxvec) 53833965Sjdp{ 53933965Sjdp int nvec = maxvec; 54033965Sjdp int rc; 54133965Sjdp 54233965Sjdp if (maxvec < minvec) 54333965Sjdp return (-ERANGE); 54433965Sjdp 54533965Sjdp do { 54633965Sjdp rc = pci_enable_msix(dev, entries, nvec); 54733965Sjdp if (rc < 0) { 54833965Sjdp return (rc); 54933965Sjdp } else if (rc > 0) { 55033965Sjdp if (rc < minvec) 55133965Sjdp return (-ENOSPC); 55233965Sjdp nvec = rc; 55333965Sjdp } 55433965Sjdp } while (rc); 55533965Sjdp return (nvec); 55633965Sjdp} 55733965Sjdp 55833965Sjdpstatic inline int pci_channel_offline(struct pci_dev *pdev) 55933965Sjdp{ 56033965Sjdp return false; 56133965Sjdp} 56233965Sjdp 56333965Sjdpstatic inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) 56433965Sjdp{ 56577298Sobrien return -ENODEV; 56633965Sjdp} 56733965Sjdpstatic inline void pci_disable_sriov(struct pci_dev *dev) 56833965Sjdp{ 56933965Sjdp} 57033965Sjdp 57133965Sjdp#define DEFINE_PCI_DEVICE_TABLE(_table) \ 57233965Sjdp const struct pci_device_id _table[] __devinitdata 57333965Sjdp 57433965Sjdp 57533965Sjdp/* XXX This should not be necessary. */ 57633965Sjdp#define pcix_set_mmrbc(d, v) 0 57733965Sjdp#define pcix_get_max_mmrbc(d) 0 57833965Sjdp#define pcie_set_readrq(d, v) 0 57933965Sjdp 58033965Sjdp#define PCI_DMA_BIDIRECTIONAL 0 58133965Sjdp#define PCI_DMA_TODEVICE 1 58233965Sjdp#define PCI_DMA_FROMDEVICE 2 58333965Sjdp#define PCI_DMA_NONE 3 58433965Sjdp 58533965Sjdp#define pci_pool dma_pool 58633965Sjdp#define pci_pool_destroy(...) dma_pool_destroy(__VA_ARGS__) 58733965Sjdp#define pci_pool_alloc(...) dma_pool_alloc(__VA_ARGS__) 58833965Sjdp#define pci_pool_free(...) dma_pool_free(__VA_ARGS__) 58933965Sjdp#define pci_pool_create(_name, _pdev, _size, _align, _alloc) \ 59033965Sjdp dma_pool_create(_name, &(_pdev)->dev, _size, _align, _alloc) 59133965Sjdp#define pci_free_consistent(_hwdev, _size, _vaddr, _dma_handle) \ 59233965Sjdp dma_free_coherent((_hwdev) == NULL ? NULL : &(_hwdev)->dev, \ 59333965Sjdp _size, _vaddr, _dma_handle) 59433965Sjdp#define pci_map_sg(_hwdev, _sg, _nents, _dir) \ 59577298Sobrien dma_map_sg((_hwdev) == NULL ? NULL : &(_hwdev->dev), \ 59633965Sjdp _sg, _nents, (enum dma_data_direction)_dir) 59733965Sjdp#define pci_map_single(_hwdev, _ptr, _size, _dir) \ 59833965Sjdp dma_map_single((_hwdev) == NULL ? NULL : &(_hwdev->dev), \ 59933965Sjdp (_ptr), (_size), (enum dma_data_direction)_dir) 60033965Sjdp#define pci_unmap_single(_hwdev, _addr, _size, _dir) \ 60133965Sjdp dma_unmap_single((_hwdev) == NULL ? NULL : &(_hwdev)->dev, \ 60233965Sjdp _addr, _size, (enum dma_data_direction)_dir) 60377298Sobrien#define pci_unmap_sg(_hwdev, _sg, _nents, _dir) \ 60433965Sjdp dma_unmap_sg((_hwdev) == NULL ? NULL : &(_hwdev)->dev, \ 60533965Sjdp _sg, _nents, (enum dma_data_direction)_dir) 60633965Sjdp#define pci_map_page(_hwdev, _page, _offset, _size, _dir) \ 60733965Sjdp dma_map_page((_hwdev) == NULL ? NULL : &(_hwdev)->dev, _page,\ 60833965Sjdp _offset, _size, (enum dma_data_direction)_dir) 60977298Sobrien#define pci_unmap_page(_hwdev, _dma_address, _size, _dir) \ 61033965Sjdp dma_unmap_page((_hwdev) == NULL ? NULL : &(_hwdev)->dev, \ 61133965Sjdp _dma_address, _size, (enum dma_data_direction)_dir) 61277298Sobrien#define pci_set_dma_mask(_pdev, mask) dma_set_mask(&(_pdev)->dev, (mask)) 61377298Sobrien#define pci_dma_mapping_error(_pdev, _dma_addr) \ 61433965Sjdp dma_mapping_error(&(_pdev)->dev, _dma_addr) 61533965Sjdp#define pci_set_consistent_dma_mask(_pdev, _mask) \ 61633965Sjdp dma_set_coherent_mask(&(_pdev)->dev, (_mask)) 61733965Sjdp#define DECLARE_PCI_UNMAP_ADDR(x) DEFINE_DMA_UNMAP_ADDR(x); 61877298Sobrien#define DECLARE_PCI_UNMAP_LEN(x) DEFINE_DMA_UNMAP_LEN(x); 61933965Sjdp#define pci_unmap_addr dma_unmap_addr 62077298Sobrien#define pci_unmap_addr_set dma_unmap_addr_set 62133965Sjdp#define pci_unmap_len dma_unmap_len 62233965Sjdp#define pci_unmap_len_set dma_unmap_len_set 62333965Sjdp 62433965Sjdptypedef unsigned int __bitwise pci_channel_state_t; 62533965Sjdptypedef unsigned int __bitwise pci_ers_result_t; 62633965Sjdp 62733965Sjdpenum pci_channel_state { 62833965Sjdp pci_channel_io_normal = 1, 62933965Sjdp pci_channel_io_frozen = 2, 63077298Sobrien pci_channel_io_perm_failure = 3, 63133965Sjdp}; 63233965Sjdp 63333965Sjdpenum pci_ers_result { 63433965Sjdp PCI_ERS_RESULT_NONE = 1, 63560484Sobrien PCI_ERS_RESULT_CAN_RECOVER = 2, 63633965Sjdp PCI_ERS_RESULT_NEED_RESET = 3, 63733965Sjdp PCI_ERS_RESULT_DISCONNECT = 4, 63877298Sobrien PCI_ERS_RESULT_RECOVERED = 5, 63977298Sobrien}; 64077298Sobrien 64133965Sjdp 64260484Sobrien/* PCI bus error event callbacks */ 64333965Sjdpstruct pci_error_handlers { 64433965Sjdp pci_ers_result_t (*error_detected)(struct pci_dev *dev, 64533965Sjdp enum pci_channel_state error); 64633965Sjdp pci_ers_result_t (*mmio_enabled)(struct pci_dev *dev); 64733965Sjdp pci_ers_result_t (*link_reset)(struct pci_dev *dev); 64877298Sobrien pci_ers_result_t (*slot_reset)(struct pci_dev *dev); 64933965Sjdp void (*resume)(struct pci_dev *dev); 65033965Sjdp}; 65133965Sjdp 65233965Sjdp/* FreeBSD does not support SRIOV - yet */ 65333965Sjdpstatic inline struct pci_dev *pci_physfn(struct pci_dev *dev) 65433965Sjdp{ 65533965Sjdp return dev; 65633965Sjdp} 65733965Sjdp 65833965Sjdpstatic inline bool pci_is_pcie(struct pci_dev *dev) 65933965Sjdp{ 66077298Sobrien return !!pci_pcie_cap(dev); 66133965Sjdp} 66233965Sjdp 66333965Sjdpstatic inline u16 pcie_flags_reg(struct pci_dev *dev) 66433965Sjdp{ 66533965Sjdp int pos; 66633965Sjdp u16 reg16; 66733965Sjdp 66833965Sjdp pos = pci_find_capability(dev, PCI_CAP_ID_EXP); 66933965Sjdp if (!pos) 67033965Sjdp return 0; 67133965Sjdp 67233965Sjdp pci_read_config_word(dev, pos + PCI_EXP_FLAGS, ®16); 67333965Sjdp 67433965Sjdp return reg16; 67533965Sjdp} 67633965Sjdp 67733965Sjdp 67833965Sjdpstatic inline int pci_pcie_type(struct pci_dev *dev) 67933965Sjdp{ 68033965Sjdp return (pcie_flags_reg(dev) & PCI_EXP_FLAGS_TYPE) >> 4; 68177298Sobrien} 68233965Sjdp 68333965Sjdpstatic inline int pcie_cap_version(struct pci_dev *dev) 68433965Sjdp{ 68533965Sjdp return pcie_flags_reg(dev) & PCI_EXP_FLAGS_VERS; 68633965Sjdp} 68733965Sjdp 68833965Sjdpstatic inline bool pcie_cap_has_lnkctl(struct pci_dev *dev) 68933965Sjdp{ 69033965Sjdp int type = pci_pcie_type(dev); 69133965Sjdp 69233965Sjdp return pcie_cap_version(dev) > 1 || 69333965Sjdp type == PCI_EXP_TYPE_ROOT_PORT || 69433965Sjdp type == PCI_EXP_TYPE_ENDPOINT || 69533965Sjdp type == PCI_EXP_TYPE_LEG_END; 69633965Sjdp} 69733965Sjdp 69833965Sjdpstatic inline bool pcie_cap_has_devctl(const struct pci_dev *dev) 69933965Sjdp{ 70033965Sjdp return true; 70133965Sjdp} 70233965Sjdp 70333965Sjdpstatic inline bool pcie_cap_has_sltctl(struct pci_dev *dev) 70433965Sjdp{ 70577298Sobrien int type = pci_pcie_type(dev); 70633965Sjdp 70733965Sjdp return pcie_cap_version(dev) > 1 || 70833965Sjdp type == PCI_EXP_TYPE_ROOT_PORT || 70933965Sjdp (type == PCI_EXP_TYPE_DOWNSTREAM && 71033965Sjdp pcie_flags_reg(dev) & PCI_EXP_FLAGS_SLOT); 71133965Sjdp} 71233965Sjdp 71333965Sjdpstatic inline bool pcie_cap_has_rtctl(struct pci_dev *dev) 71433965Sjdp{ 71533965Sjdp int type = pci_pcie_type(dev); 71633965Sjdp 71733965Sjdp return pcie_cap_version(dev) > 1 || 71833965Sjdp type == PCI_EXP_TYPE_ROOT_PORT || 71933965Sjdp type == PCI_EXP_TYPE_RC_EC; 72033965Sjdp} 72133965Sjdp 72233965Sjdpstatic bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos) 72333965Sjdp{ 72433965Sjdp if (!pci_is_pcie(dev)) 72560484Sobrien return false; 72633965Sjdp 72733965Sjdp switch (pos) { 72833965Sjdp case PCI_EXP_FLAGS_TYPE: 72933965Sjdp return true; 73033965Sjdp case PCI_EXP_DEVCAP: 73160484Sobrien case PCI_EXP_DEVCTL: 73233965Sjdp case PCI_EXP_DEVSTA: 73333965Sjdp return pcie_cap_has_devctl(dev); 73433965Sjdp case PCI_EXP_LNKCAP: 73533965Sjdp case PCI_EXP_LNKCTL: 73633965Sjdp case PCI_EXP_LNKSTA: 73760484Sobrien return pcie_cap_has_lnkctl(dev); 73860484Sobrien case PCI_EXP_SLTCAP: 73933965Sjdp case PCI_EXP_SLTCTL: 74033965Sjdp case PCI_EXP_SLTSTA: 74133965Sjdp return pcie_cap_has_sltctl(dev); 74233965Sjdp case PCI_EXP_RTCTL: 74333965Sjdp case PCI_EXP_RTCAP: 74433965Sjdp case PCI_EXP_RTSTA: 74533965Sjdp return pcie_cap_has_rtctl(dev); 74633965Sjdp case PCI_EXP_DEVCAP2: 74733965Sjdp case PCI_EXP_DEVCTL2: 74833965Sjdp case PCI_EXP_LNKCAP2: 74933965Sjdp case PCI_EXP_LNKCTL2: 75033965Sjdp case PCI_EXP_LNKSTA2: 75133965Sjdp return pcie_cap_version(dev) > 1; 75233965Sjdp default: 75333965Sjdp return false; 75433965Sjdp } 75533965Sjdp} 75633965Sjdp 75733965Sjdpstatic inline int 75833965Sjdppcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *dst) 75933965Sjdp{ 76033965Sjdp if (pos & 3) 76133965Sjdp return -EINVAL; 76277298Sobrien 76333965Sjdp if (!pcie_capability_reg_implemented(dev, pos)) 76433965Sjdp return -EINVAL; 76533965Sjdp 76633965Sjdp return pci_read_config_dword(dev, pci_pcie_cap(dev) + pos, dst); 76733965Sjdp} 76833965Sjdp 76933965Sjdpstatic inline int 77033965Sjdppcie_capability_read_word(struct pci_dev *dev, int pos, u16 *dst) 77133965Sjdp{ 77233965Sjdp if (pos & 3) 77333965Sjdp return -EINVAL; 77433965Sjdp 77533965Sjdp if (!pcie_capability_reg_implemented(dev, pos)) 77633965Sjdp return -EINVAL; 77733965Sjdp 77833965Sjdp return pci_read_config_word(dev, pci_pcie_cap(dev) + pos, dst); 77933965Sjdp} 78033965Sjdp 78133965Sjdpstatic inline int 78233965Sjdppcie_capability_write_word(struct pci_dev *dev, int pos, u16 val) 78333965Sjdp{ 78477298Sobrien if (pos & 1) 78533965Sjdp return -EINVAL; 78633965Sjdp 78733965Sjdp if (!pcie_capability_reg_implemented(dev, pos)) 78833965Sjdp return 0; 78933965Sjdp 79033965Sjdp return pci_write_config_word(dev, pci_pcie_cap(dev) + pos, val); 79133965Sjdp} 79233965Sjdp 79333965Sjdpstatic inline int pcie_get_minimum_link(struct pci_dev *dev, 79477298Sobrien enum pci_bus_speed *speed, enum pcie_link_width *width) 79533965Sjdp{ 79633965Sjdp *speed = PCI_SPEED_UNKNOWN; 79733965Sjdp *width = PCIE_LNK_WIDTH_UNKNOWN; 79833965Sjdp return (0); 79933965Sjdp} 80033965Sjdp 80160484Sobrienstatic inline int 80260484Sobrienpci_num_vf(struct pci_dev *dev) 80333965Sjdp{ 80433965Sjdp return (0); 80533965Sjdp} 80633965Sjdp 80733965Sjdp#endif /* _LINUX_PCI_H_ */ 80833965Sjdp