pcivar.h revision 164282
1139749Simp/*- 226159Sse * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 326159Sse * All rights reserved. 426159Sse * 526159Sse * Redistribution and use in source and binary forms, with or without 626159Sse * modification, are permitted provided that the following conditions 726159Sse * are met: 826159Sse * 1. Redistributions of source code must retain the above copyright 926159Sse * notice unmodified, this list of conditions, and the following 1026159Sse * disclaimer. 1126159Sse * 2. Redistributions in binary form must reproduce the above copyright 1226159Sse * notice, this list of conditions and the following disclaimer in the 1326159Sse * documentation and/or other materials provided with the distribution. 1426159Sse * 1526159Sse * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1626159Sse * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1726159Sse * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1826159Sse * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1926159Sse * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2026159Sse * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2126159Sse * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2226159Sse * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2326159Sse * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2426159Sse * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2526159Sse * 2650477Speter * $FreeBSD: head/sys/dev/pci/pcivar.h 164282 2006-11-14 17:54:55Z jhb $ 2726159Sse * 2826159Sse */ 296100Sse 3039231Sgibbs#ifndef _PCIVAR_H_ 3139231Sgibbs#define _PCIVAR_H_ 3239231Sgibbs 3339231Sgibbs#include <sys/queue.h> 3439231Sgibbs 3526159Sse/* some PCI bus constants */ 366767Sse 3726159Sse#define PCI_BUSMAX 255 /* highest supported bus number */ 3826159Sse#define PCI_SLOTMAX 31 /* highest supported slot number */ 3926159Sse#define PCI_FUNCMAX 7 /* highest supported function number */ 4026159Sse#define PCI_REGMAX 255 /* highest supported config register addr. */ 416100Sse 4226159Sse#define PCI_MAXMAPS_0 6 /* max. no. of memory/port maps */ 4326159Sse#define PCI_MAXMAPS_1 2 /* max. no. of maps for PCI to PCI bridge */ 4426159Sse#define PCI_MAXMAPS_2 1 /* max. no. of maps for CardBus bridge */ 456100Sse 46163805Simptypedef uint64_t pci_addr_t; 476100Sse 48120063Sscottl/* Interesting values for PCI power management */ 49120063Sscottlstruct pcicfg_pp { 50120063Sscottl uint16_t pp_cap; /* PCI power management capabilities */ 51120063Sscottl uint8_t pp_status; /* config space address of PCI power status reg */ 52120063Sscottl uint8_t pp_pmcsr; /* config space address of PMCSR reg */ 53120063Sscottl uint8_t pp_data; /* config space address of PCI power data reg */ 54120063Sscottl}; 55120063Sscottl 56163163Sjmgstruct vpd_readonly { 57163163Sjmg char keyword[2]; 58163163Sjmg char *value; 59163163Sjmg}; 60163163Sjmg 61163163Sjmgstruct vpd_write { 62163163Sjmg char keyword[2]; 63163163Sjmg char *value; 64163163Sjmg int start; 65163163Sjmg int len; 66163163Sjmg}; 67163163Sjmg 68163163Sjmgstruct pcicfg_vpd { 69163163Sjmg uint8_t vpd_reg; /* base register, + 2 for addr, + 4 data */ 70163163Sjmg char *vpd_ident; /* string identifier */ 71163163Sjmg int vpd_rocnt; 72163163Sjmg struct vpd_readonly *vpd_ros; 73163163Sjmg int vpd_wcnt; 74163163Sjmg struct vpd_write *vpd_w; 75163163Sjmg}; 76163163Sjmg 77120063Sscottl/* Interesting values for PCI MSI */ 78120063Sscottlstruct pcicfg_msi { 79120063Sscottl uint16_t msi_ctrl; /* Message Control */ 80164264Sjhb uint8_t msi_location; /* Offset of MSI capability registers. */ 81120063Sscottl uint8_t msi_msgnum; /* Number of messages */ 82164264Sjhb int msi_alloc; /* Number of allocated messages. */ 83164264Sjhb uint64_t msi_addr; /* Contents of address register. */ 84164264Sjhb uint16_t msi_data; /* Contents of data register. */ 85120063Sscottl}; 86120063Sscottl 87164282Sjhb/* Interesting values for PCI MSI-X */ 88164264Sjhbstruct pcicfg_msix { 89164264Sjhb uint16_t msix_ctrl; /* Message Control */ 90164282Sjhb uint8_t msix_location; /* Offset of MSI-X capability registers. */ 91164264Sjhb uint16_t msix_msgnum; /* Number of messages */ 92164264Sjhb int msix_alloc; /* Number of allocated messages. */ 93164264Sjhb uint8_t msix_table_bar; /* BAR containing vector table. */ 94164264Sjhb uint8_t msix_pba_bar; /* BAR containing PBA. */ 95164264Sjhb uint32_t msix_table_offset; 96164264Sjhb uint32_t msix_pba_offset; 97164264Sjhb struct resource *msix_table_res; /* Resource containing vector table. */ 98164264Sjhb struct resource *msix_pba_res; /* Resource containing PBA. */ 99164264Sjhb}; 100164264Sjhb 10126159Sse/* config header information common to all header types */ 10226159Ssetypedef struct pcicfg { 10345720Speter struct device *dev; /* device which owns this */ 1046100Sse 105128019Simp uint32_t bar[PCI_MAXMAPS_0]; /* BARs */ 106128019Simp uint32_t bios; /* BIOS mapping */ 107128019Simp 108119266Simp uint16_t subvendor; /* card vendor ID */ 109119266Simp uint16_t subdevice; /* card device ID, assigned by card vendor */ 110119266Simp uint16_t vendor; /* chip vendor ID */ 111119266Simp uint16_t device; /* chip device ID, assigned by chip vendor */ 1126100Sse 113119266Simp uint16_t cmdreg; /* disable/enable chip and PCI options */ 114119266Simp uint16_t statreg; /* supported PCI features and error state */ 1157233Sse 116119266Simp uint8_t baseclass; /* chip PCI class */ 117119266Simp uint8_t subclass; /* chip PCI subclass */ 118119266Simp uint8_t progif; /* chip PCI programming interface */ 119119266Simp uint8_t revid; /* chip revision ID */ 1206100Sse 121119266Simp uint8_t hdrtype; /* chip config header type */ 122119266Simp uint8_t cachelnsz; /* cache line size in 4byte units */ 123119266Simp uint8_t intpin; /* PCI interrupt pin */ 124119266Simp uint8_t intline; /* interrupt line (IRQ for PC arch) */ 1256100Sse 126119266Simp uint8_t mingnt; /* min. useful bus grant time in 250ns units */ 127119266Simp uint8_t maxlat; /* max. tolerated bus grant latency in 250ns */ 128119266Simp uint8_t lattimer; /* latency timer in units of 30ns bus cycles */ 1296100Sse 130119266Simp uint8_t mfdev; /* multi-function device (from hdrtype reg) */ 131119266Simp uint8_t nummaps; /* actual number of PCI maps used */ 1327233Sse 133119266Simp uint8_t bus; /* config space bus address */ 134119266Simp uint8_t slot; /* config space slot address */ 135119266Simp uint8_t func; /* config space function number */ 1367233Sse 137120063Sscottl struct pcicfg_pp pp; /* pci power management */ 138163163Sjmg struct pcicfg_vpd vpd; /* pci vital product data */ 139120063Sscottl struct pcicfg_msi msi; /* pci msi */ 140164264Sjhb struct pcicfg_msix msix; /* pci msi-x */ 14126159Sse} pcicfgregs; 1426100Sse 14326159Sse/* additional type 1 device config header information (PCI to PCI bridge) */ 1446100Sse 14526159Sse#define PCI_PPBMEMBASE(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) & ~0xfffff) 14626159Sse#define PCI_PPBMEMLIMIT(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) | 0xfffff) 14726159Sse#define PCI_PPBIOBASE(h,l) ((((h)<<16) + ((l)<<8)) & ~0xfff) 14826159Sse#define PCI_PPBIOLIMIT(h,l) ((((h)<<16) + ((l)<<8)) | 0xfff) 1497233Sse 15026159Ssetypedef struct { 15126159Sse pci_addr_t pmembase; /* base address of prefetchable memory */ 15226159Sse pci_addr_t pmemlimit; /* topmost address of prefetchable memory */ 153119266Simp uint32_t membase; /* base address of memory window */ 154119266Simp uint32_t memlimit; /* topmost address of memory window */ 155119266Simp uint32_t iobase; /* base address of port window */ 156119266Simp uint32_t iolimit; /* topmost address of port window */ 157119266Simp uint16_t secstat; /* secondary bus status register */ 158119266Simp uint16_t bridgectl; /* bridge control register */ 159119266Simp uint8_t seclat; /* CardBus latency timer */ 16026159Sse} pcih1cfgregs; 1616100Sse 16226159Sse/* additional type 2 device config header information (CardBus bridge) */ 16326159Sse 16426159Ssetypedef struct { 165119266Simp uint32_t membase0; /* base address of memory window */ 166119266Simp uint32_t memlimit0; /* topmost address of memory window */ 167119266Simp uint32_t membase1; /* base address of memory window */ 168119266Simp uint32_t memlimit1; /* topmost address of memory window */ 169119266Simp uint32_t iobase0; /* base address of port window */ 170119266Simp uint32_t iolimit0; /* topmost address of port window */ 171119266Simp uint32_t iobase1; /* base address of port window */ 172119266Simp uint32_t iolimit1; /* topmost address of port window */ 173119266Simp uint32_t pccardif; /* PC Card 16bit IF legacy more base addr. */ 174119266Simp uint16_t secstat; /* secondary bus status register */ 175119266Simp uint16_t bridgectl; /* bridge control register */ 176119266Simp uint8_t seclat; /* CardBus latency timer */ 17726159Sse} pcih2cfgregs; 17826159Sse 179119266Simpextern uint32_t pci_numdevs; 18039231Sgibbs 18161047Speter/* Only if the prerequisites are present */ 18261047Speter#if defined(_SYS_BUS_H_) && defined(_SYS_PCIIO_H_) 18361047Speterstruct pci_devinfo { 18461047Speter STAILQ_ENTRY(pci_devinfo) pci_links; 18561047Speter struct resource_list resources; 18661047Speter pcicfgregs cfg; 18761047Speter struct pci_conf conf; 18861047Speter}; 18961047Speter#endif 19039231Sgibbs 19145720Speter#ifdef _SYS_BUS_H_ 19245720Speter 19345720Speter#include "pci_if.h" 19445720Speter 19552243Sdfr/* 19652243Sdfr * Define pci-specific resource flags for accessing memory via dense 19752243Sdfr * or bwx memory spaces. These flags are ignored on i386. 19852243Sdfr */ 19952243Sdfr#define PCI_RF_DENSE 0x10000 20052243Sdfr#define PCI_RF_BWX 0x20000 20152243Sdfr 20245720Speterenum pci_device_ivars { 20369953Smsmith PCI_IVAR_SUBVENDOR, 20469953Smsmith PCI_IVAR_SUBDEVICE, 20569953Smsmith PCI_IVAR_VENDOR, 20669953Smsmith PCI_IVAR_DEVICE, 20769953Smsmith PCI_IVAR_DEVID, 20869953Smsmith PCI_IVAR_CLASS, 20969953Smsmith PCI_IVAR_SUBCLASS, 21069953Smsmith PCI_IVAR_PROGIF, 21169953Smsmith PCI_IVAR_REVID, 21269953Smsmith PCI_IVAR_INTPIN, 21369953Smsmith PCI_IVAR_IRQ, 21469953Smsmith PCI_IVAR_BUS, 21569953Smsmith PCI_IVAR_SLOT, 21669953Smsmith PCI_IVAR_FUNCTION, 217107300Simp PCI_IVAR_ETHADDR, 218149972Simp PCI_IVAR_CMDREG, 219149972Simp PCI_IVAR_CACHELNSZ, 220149972Simp PCI_IVAR_MINGNT, 221149972Simp PCI_IVAR_MAXLAT, 222149972Simp PCI_IVAR_LATTIMER, 22345720Speter}; 22445720Speter 22545720Speter/* 22645720Speter * Simplified accessors for pci devices 22745720Speter */ 228102145Smux#define PCI_ACCESSOR(var, ivar, type) \ 22988375Stmm __BUS_ACCESSOR(pci, var, PCI, ivar, type) 23045720Speter 231119266SimpPCI_ACCESSOR(subvendor, SUBVENDOR, uint16_t) 232119266SimpPCI_ACCESSOR(subdevice, SUBDEVICE, uint16_t) 233119266SimpPCI_ACCESSOR(vendor, VENDOR, uint16_t) 234119266SimpPCI_ACCESSOR(device, DEVICE, uint16_t) 235119266SimpPCI_ACCESSOR(devid, DEVID, uint32_t) 236119266SimpPCI_ACCESSOR(class, CLASS, uint8_t) 237119266SimpPCI_ACCESSOR(subclass, SUBCLASS, uint8_t) 238119266SimpPCI_ACCESSOR(progif, PROGIF, uint8_t) 239119266SimpPCI_ACCESSOR(revid, REVID, uint8_t) 240119266SimpPCI_ACCESSOR(intpin, INTPIN, uint8_t) 241119266SimpPCI_ACCESSOR(irq, IRQ, uint8_t) 242119266SimpPCI_ACCESSOR(bus, BUS, uint8_t) 243119266SimpPCI_ACCESSOR(slot, SLOT, uint8_t) 244119266SimpPCI_ACCESSOR(function, FUNCTION, uint8_t) 245119266SimpPCI_ACCESSOR(ether, ETHADDR, uint8_t *) 246149972SimpPCI_ACCESSOR(cmdreg, CMDREG, uint8_t) 247149972SimpPCI_ACCESSOR(cachelnsz, CACHELNSZ, uint8_t) 248149972SimpPCI_ACCESSOR(mingnt, MINGNT, uint8_t) 249149972SimpPCI_ACCESSOR(maxlat, MAXLAT, uint8_t) 250149972SimpPCI_ACCESSOR(lattimer, LATTIMER, uint8_t) 25145720Speter 25266416Speter#undef PCI_ACCESSOR 25366416Speter 25469953Smsmith/* 25569953Smsmith * Operations on configuration space. 25669953Smsmith */ 257119266Simpstatic __inline uint32_t 25845720Speterpci_read_config(device_t dev, int reg, int width) 25945720Speter{ 26045720Speter return PCI_READ_CONFIG(device_get_parent(dev), dev, reg, width); 26145720Speter} 26245720Speter 26345720Speterstatic __inline void 264119266Simppci_write_config(device_t dev, int reg, uint32_t val, int width) 26545720Speter{ 26645720Speter PCI_WRITE_CONFIG(device_get_parent(dev), dev, reg, val, width); 26745720Speter} 26845720Speter 26947339Sgallatin/* 27047339Sgallatin * Ivars for pci bridges. 27147339Sgallatin */ 27247339Sgallatin 27347339Sgallatin/*typedef enum pci_device_ivars pcib_device_ivars;*/ 27447339Sgallatinenum pcib_device_ivars { 27565176Sdfr PCIB_IVAR_BUS 27647339Sgallatin}; 27747339Sgallatin 278102144Smux#define PCIB_ACCESSOR(var, ivar, type) \ 279102144Smux __BUS_ACCESSOR(pcib, var, PCIB, ivar, type) 28047339Sgallatin 281119266SimpPCIB_ACCESSOR(bus, BUS, uint32_t) 28247339Sgallatin 28366416Speter#undef PCIB_ACCESSOR 28466416Speter 28569953Smsmith/* 28698017Simp * PCI interrupt validation. Invalid interrupt values such as 0 or 128 28798017Simp * on i386 or other platforms should be mapped out in the MD pcireadconf 28898017Simp * code and not here, since the only MI invalid IRQ is 255. 28990554Smsmith */ 29097695Simp#define PCI_INVALID_IRQ 255 29198017Simp#define PCI_INTERRUPT_VALID(x) ((x) != PCI_INVALID_IRQ) 29290554Smsmith 29390554Smsmith/* 29469953Smsmith * Convenience functions. 29569953Smsmith * 29669953Smsmith * These should be used in preference to manually manipulating 29769953Smsmith * configuration space. 29869953Smsmith */ 299113544Smdoddstatic __inline int 30073185Speterpci_enable_busmaster(device_t dev) 30173185Speter{ 302113544Smdodd return(PCI_ENABLE_BUSMASTER(device_get_parent(dev), dev)); 30373185Speter} 30445720Speter 305113544Smdoddstatic __inline int 30673185Speterpci_disable_busmaster(device_t dev) 30773185Speter{ 308113544Smdodd return(PCI_DISABLE_BUSMASTER(device_get_parent(dev), dev)); 30973185Speter} 31073185Speter 311113544Smdoddstatic __inline int 31273185Speterpci_enable_io(device_t dev, int space) 31373185Speter{ 314113544Smdodd return(PCI_ENABLE_IO(device_get_parent(dev), dev, space)); 31573185Speter} 31673185Speter 317113544Smdoddstatic __inline int 31873185Speterpci_disable_io(device_t dev, int space) 31973185Speter{ 320113544Smdodd return(PCI_DISABLE_IO(device_get_parent(dev), dev, space)); 32173185Speter} 32273185Speter 323163163Sjmgstatic __inline int 324163163Sjmgpci_get_vpd_ident(device_t dev, const char **identptr) 325163163Sjmg{ 326163163Sjmg return(PCI_GET_VPD_IDENT(device_get_parent(dev), dev, identptr)); 327163163Sjmg} 328163163Sjmg 329163163Sjmgstatic __inline int 330163163Sjmgpci_get_vpd_readonly(device_t dev, const char *kw, const char **identptr) 331163163Sjmg{ 332163163Sjmg return(PCI_GET_VPD_READONLY(device_get_parent(dev), dev, kw, identptr)); 333163163Sjmg} 334163163Sjmg 33569953Smsmith/* 336145651Smarcel * Check if the address range falls within the VGA defined address range(s) 337145651Smarcel */ 338145651Smarcelstatic __inline int 339145651Smarcelpci_is_vga_ioport_range(u_long start, u_long end) 340145651Smarcel{ 341145651Smarcel 342145651Smarcel return (((start >= 0x3b0 && end <= 0x3bb) || 343145651Smarcel (start >= 0x3c0 && end <= 0x3df)) ? 1 : 0); 344145651Smarcel} 345145651Smarcel 346145651Smarcelstatic __inline int 347145651Smarcelpci_is_vga_memory_range(u_long start, u_long end) 348145651Smarcel{ 349145651Smarcel 350145651Smarcel return ((start >= 0xa0000 && end <= 0xbffff) ? 1 : 0); 351145651Smarcel} 352145651Smarcel 353145651Smarcel/* 35469953Smsmith * PCI power states are as defined by ACPI: 35569953Smsmith * 35669953Smsmith * D0 State in which device is on and running. It is receiving full 35769953Smsmith * power from the system and delivering full functionality to the user. 35869953Smsmith * D1 Class-specific low-power state in which device context may or may not 35969953Smsmith * be lost. Buses in D1 cannot do anything to the bus that would force 360160964Syar * devices on that bus to lose context. 36169953Smsmith * D2 Class-specific low-power state in which device context may or may 36269953Smsmith * not be lost. Attains greater power savings than D1. Buses in D2 363160964Syar * can cause devices on that bus to lose some context. Devices in D2 36469953Smsmith * must be prepared for the bus to be in D2 or higher. 36569953Smsmith * D3 State in which the device is off and not running. Device context is 36669953Smsmith * lost. Power can be removed from the device. 36769953Smsmith */ 36869953Smsmith#define PCI_POWERSTATE_D0 0 36969953Smsmith#define PCI_POWERSTATE_D1 1 37069953Smsmith#define PCI_POWERSTATE_D2 2 37169953Smsmith#define PCI_POWERSTATE_D3 3 37269953Smsmith#define PCI_POWERSTATE_UNKNOWN -1 37326159Sse 37473185Speterstatic __inline int 37573185Speterpci_set_powerstate(device_t dev, int state) 37673185Speter{ 37773185Speter return PCI_SET_POWERSTATE(device_get_parent(dev), dev, state); 37873185Speter} 37958287Speter 38073185Speterstatic __inline int 38173185Speterpci_get_powerstate(device_t dev) 38273185Speter{ 38373185Speter return PCI_GET_POWERSTATE(device_get_parent(dev), dev); 38473185Speter} 38573185Speter 386153560Sjhbstatic __inline int 387153560Sjhbpci_find_extcap(device_t dev, int capability, int *capreg) 388153560Sjhb{ 389153560Sjhb return PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg); 390153560Sjhb} 391153560Sjhb 392164264Sjhbstatic __inline int 393164264Sjhbpci_alloc_msi(device_t dev, int *count) 394164264Sjhb{ 395164264Sjhb return (PCI_ALLOC_MSI(device_get_parent(dev), dev, count)); 396164264Sjhb} 397164264Sjhb 398164264Sjhbstatic __inline int 399164264Sjhbpci_release_msi(device_t dev) 400164264Sjhb{ 401164264Sjhb return (PCI_RELEASE_MSI(device_get_parent(dev), dev)); 402164264Sjhb} 403164264Sjhb 404164264Sjhbstatic __inline int 405164264Sjhbpci_msi_count(device_t dev) 406164264Sjhb{ 407164264Sjhb return (PCI_MSI_COUNT(device_get_parent(dev), dev)); 408164264Sjhb} 409164264Sjhb 410119266Simpdevice_t pci_find_bsf(uint8_t, uint8_t, uint8_t); 411119266Simpdevice_t pci_find_device(uint16_t, uint16_t); 412164264Sjhb 413164264Sjhb/* Used by MD code to program MSI and MSI-X registers. */ 414164264Sjhbvoid pci_enable_msi(device_t dev, uint64_t address, uint16_t data); 415164264Sjhbvoid pci_enable_msix(device_t dev, u_int index, uint64_t address, 416164264Sjhb uint32_t data); 417164264Sjhbvoid pci_mask_msix(device_t dev, u_int index); 418164264Sjhbint pci_pending_msix(device_t dev, u_int index); 419164264Sjhbvoid pci_unmask_msix(device_t dev, u_int index); 420164264Sjhb 42169953Smsmith#endif /* _SYS_BUS_H_ */ 42261047Speter 42369953Smsmith/* 42469953Smsmith * cdev switch for control device, initialised in generic PCI code 42569953Smsmith */ 42669953Smsmithextern struct cdevsw pcicdev; 42758287Speter 42869953Smsmith/* 42969953Smsmith * List of all PCI devices, generation count for the list. 43069953Smsmith */ 43188184SmdoddSTAILQ_HEAD(devlist, pci_devinfo); 43212453Sbde 43388184Smdoddextern struct devlist pci_devq; 434119266Simpextern uint32_t pci_generation; 43588184Smdodd 43639231Sgibbs#endif /* _PCIVAR_H_ */ 437