pcivar.h revision 163163
11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
31556Srgrimes * All rights reserved.
41556Srgrimes *
51556Srgrimes * Redistribution and use in source and binary forms, with or without
61556Srgrimes * modification, are permitted provided that the following conditions
71556Srgrimes * are met:
81556Srgrimes * 1. Redistributions of source code must retain the above copyright
91556Srgrimes *    notice unmodified, this list of conditions, and the following
101556Srgrimes *    disclaimer.
111556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
121556Srgrimes *    notice, this list of conditions and the following disclaimer in the
131556Srgrimes *    documentation and/or other materials provided with the distribution.
141556Srgrimes *
151556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
161556Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
171556Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
181556Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
191556Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
201556Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
211556Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
221556Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
231556Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
241556Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
251556Srgrimes *
261556Srgrimes * $FreeBSD: head/sys/dev/pci/pcivar.h 163163 2006-10-09 16:15:56Z jmg $
271556Srgrimes *
281556Srgrimes */
291556Srgrimes
301556Srgrimes#ifndef _PCIVAR_H_
311556Srgrimes#define _PCIVAR_H_
321556Srgrimes
331556Srgrimes#include <sys/queue.h>
3436150Scharnier
3536150Scharnier/* some PCI bus constants */
3636150Scharnier
371556Srgrimes#define PCI_BUSMAX	255	/* highest supported bus number */
3899110Sobrien#define PCI_SLOTMAX	31	/* highest supported slot number */
3999110Sobrien#define PCI_FUNCMAX	7	/* highest supported function number */
401556Srgrimes#define PCI_REGMAX	255	/* highest supported config register addr. */
4117987Speter
4217987Speter#define PCI_MAXMAPS_0	6	/* max. no. of memory/port maps */
4317987Speter#define PCI_MAXMAPS_1	2	/* max. no. of maps for PCI to PCI bridge */
4420425Ssteve#define PCI_MAXMAPS_2	1	/* max. no. of maps for CardBus bridge */
4517987Speter
4617987Speter/* pci_addr_t covers this system's PCI bus address space: 32 or 64 bit */
47100661Stjr
4817987Speter#ifdef PCI_A64
491556Srgrimestypedef uint64_t pci_addr_t;	/* uint64_t for system with 64bit addresses */
501556Srgrimes#else
511556Srgrimestypedef uint32_t pci_addr_t;	/* uint64_t for system with 64bit addresses */
521556Srgrimes#endif
531556Srgrimes
541556Srgrimes/* Interesting values for PCI power management */
551556Srgrimesstruct pcicfg_pp {
561556Srgrimes    uint16_t	pp_cap;		/* PCI power management capabilities */
571556Srgrimes    uint8_t	pp_status;	/* config space address of PCI power status reg */
581556Srgrimes    uint8_t	pp_pmcsr;	/* config space address of PMCSR reg */
591556Srgrimes    uint8_t	pp_data;	/* config space address of PCI power data reg */
601556Srgrimes};
6120425Ssteve
6217987Speterstruct vpd_readonly {
631556Srgrimes    char	keyword[2];
6417987Speter    char	*value;
6520425Ssteve};
66223060Sjilles
671556Srgrimesstruct vpd_write {
68213811Sobrien    char	keyword[2];
69213811Sobrien    char	*value;
70213811Sobrien    int 	start;
71213811Sobrien    int 	len;
72213811Sobrien};
73213811Sobrien
74213811Sobrienstruct pcicfg_vpd {
75213811Sobrien    uint8_t	vpd_reg;	/* base register, + 2 for addr, + 4 data */
761556Srgrimes    char	*vpd_ident;	/* string identifier */
77213760Sobrien    int 	vpd_rocnt;
78213760Sobrien    struct vpd_readonly *vpd_ros;
79213760Sobrien    int 	vpd_wcnt;
801556Srgrimes    struct vpd_write *vpd_w;
811556Srgrimes};
8297092Stjr
8317987Speter/* Interesting values for PCI MSI */
84201053Sjillesstruct pcicfg_msi {
85200956Sjilles    uint16_t	msi_ctrl;	/* Message Control */
861556Srgrimes    uint8_t	msi_msgnum;	/* Number of messages */
871556Srgrimes    uint16_t	msi_data;	/* Location of MSI data word */
88222154Sjilles};
89222154Sjilles
90222292Sjilles/* config header information common to all header types */
911556Srgrimestypedef struct pcicfg {
92100663Stjr    struct device *dev;		/* device which owns this */
93100664Stjr
94222154Sjilles    uint32_t	bar[PCI_MAXMAPS_0]; /* BARs */
9597092Stjr    uint32_t	bios;		/* BIOS mapping */
96222154Sjilles
97222154Sjilles    uint16_t	subvendor;	/* card vendor ID */
98222154Sjilles    uint16_t	subdevice;	/* card device ID, assigned by card vendor */
9997092Stjr    uint16_t	vendor;		/* chip vendor ID */
10097092Stjr    uint16_t	device;		/* chip device ID, assigned by chip vendor */
10197092Stjr
10297092Stjr    uint16_t	cmdreg;		/* disable/enable chip and PCI options */
10397092Stjr    uint16_t	statreg;	/* supported PCI features and error state */
10497092Stjr
10597092Stjr    uint8_t	baseclass;	/* chip PCI class */
10697092Stjr    uint8_t	subclass;	/* chip PCI subclass */
10797092Stjr    uint8_t	progif;		/* chip PCI programming interface */
10897092Stjr    uint8_t	revid;		/* chip revision ID */
10997092Stjr
11097092Stjr    uint8_t	hdrtype;	/* chip config header type */
11197092Stjr    uint8_t	cachelnsz;	/* cache line size in 4byte units */
11297092Stjr    uint8_t	intpin;		/* PCI interrupt pin */
11397092Stjr    uint8_t	intline;	/* interrupt line (IRQ for PC arch) */
11497092Stjr
11597092Stjr    uint8_t	mingnt;		/* min. useful bus grant time in 250ns units */
11697092Stjr    uint8_t	maxlat;		/* max. tolerated bus grant latency in 250ns */
1171556Srgrimes    uint8_t	lattimer;	/* latency timer in units of 30ns bus cycles */
1185234Sbde
1195234Sbde    uint8_t	mfdev;		/* multi-function device (from hdrtype reg) */
1201556Srgrimes    uint8_t	nummaps;	/* actual number of PCI maps used */
1211556Srgrimes
12212273Speter    uint8_t	bus;		/* config space bus address */
12312273Speter    uint8_t	slot;		/* config space slot address */
12412273Speter    uint8_t	func;		/* config space function number */
12512273Speter
1261556Srgrimes    struct pcicfg_pp pp;	/* pci power management */
127222381Sjilles    struct pcicfg_vpd vpd;	/* pci vital product data */
128222381Sjilles    struct pcicfg_msi msi;	/* pci msi */
129222381Sjilles} pcicfgregs;
130222381Sjilles
1311556Srgrimes/* additional type 1 device config header information (PCI to PCI bridge) */
1321556Srgrimes
13317987Speter#ifdef PCI_A64
1341556Srgrimes#define PCI_PPBMEMBASE(h,l)  ((((pci_addr_t)(h) << 32) + ((l)<<16)) & ~0xfffff)
1351556Srgrimes#define PCI_PPBMEMLIMIT(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) | 0xfffff)
1361556Srgrimes#else
1371556Srgrimes#define PCI_PPBMEMBASE(h,l)  (((l)<<16) & ~0xfffff)
13838886Stegge#define PCI_PPBMEMLIMIT(h,l) (((l)<<16) | 0xfffff)
139159551Sstefanf#endif /* PCI_A64 */
140159551Sstefanf
141159551Sstefanf#define PCI_PPBIOBASE(h,l)   ((((h)<<16) + ((l)<<8)) & ~0xfff)
1421556Srgrimes#define PCI_PPBIOLIMIT(h,l)  ((((h)<<16) + ((l)<<8)) | 0xfff)
143222154Sjilles
144222154Sjillestypedef struct {
145222154Sjilles    pci_addr_t	pmembase;	/* base address of prefetchable memory */
146222292Sjilles    pci_addr_t	pmemlimit;	/* topmost address of prefetchable memory */
147222292Sjilles    uint32_t	membase;	/* base address of memory window */
1481556Srgrimes    uint32_t	memlimit;	/* topmost address of memory window */
1491556Srgrimes    uint32_t	iobase;		/* base address of port window */
150222292Sjilles    uint32_t	iolimit;	/* topmost address of port window */
15117987Speter    uint16_t	secstat;	/* secondary bus status register */
15217987Speter    uint16_t	bridgectl;	/* bridge control register */
1531556Srgrimes    uint8_t	seclat;		/* CardBus latency timer */
1541556Srgrimes} pcih1cfgregs;
1551556Srgrimes
1561556Srgrimes/* additional type 2 device config header information (CardBus bridge) */
15797092Stjr
15820774Sstevetypedef struct {
1591556Srgrimes    uint32_t	membase0;	/* base address of memory window */
160213811Sobrien    uint32_t	memlimit0;	/* topmost address of memory window */
16197092Stjr    uint32_t	membase1;	/* base address of memory window */
16220425Ssteve    uint32_t	memlimit1;	/* topmost address of memory window */
163222154Sjilles    uint32_t	iobase0;	/* base address of port window */
16497092Stjr    uint32_t	iolimit0;	/* topmost address of port window */
16597092Stjr    uint32_t	iobase1;	/* base address of port window */
16697092Stjr    uint32_t	iolimit1;	/* topmost address of port window */
16797092Stjr    uint32_t	pccardif;	/* PC Card 16bit IF legacy more base addr. */
168222154Sjilles    uint16_t	secstat;	/* secondary bus status register */
16997092Stjr    uint16_t	bridgectl;	/* bridge control register */
17097092Stjr    uint8_t	seclat;		/* CardBus latency timer */
17197092Stjr} pcih2cfgregs;
17297092Stjr
17397092Stjrextern uint32_t pci_numdevs;
174222154Sjilles
17597092Stjr/* Only if the prerequisites are present */
17697092Stjr#if defined(_SYS_BUS_H_) && defined(_SYS_PCIIO_H_)
177213811Sobrienstruct pci_devinfo {
17897092Stjr        STAILQ_ENTRY(pci_devinfo) pci_links;
17997092Stjr	struct resource_list resources;
18038886Stegge	pcicfgregs		cfg;
18138886Stegge	struct pci_conf		conf;
18238886Stegge};
18338886Stegge#endif
18438886Stegge
18538886Stegge#ifdef _SYS_BUS_H_
18620425Ssteve
18738886Stegge#include "pci_if.h"
18838886Stegge
18938886Stegge/*
19038886Stegge * Define pci-specific resource flags for accessing memory via dense
19138886Stegge * or bwx memory spaces. These flags are ignored on i386.
19238886Stegge */
19338886Stegge#define PCI_RF_DENSE	0x10000
19438886Stegge#define PCI_RF_BWX	0x20000
19538886Stegge
19638886Steggeenum pci_device_ivars {
19738886Stegge    PCI_IVAR_SUBVENDOR,
19838886Stegge    PCI_IVAR_SUBDEVICE,
19938886Stegge    PCI_IVAR_VENDOR,
20038886Stegge    PCI_IVAR_DEVICE,
20138886Stegge    PCI_IVAR_DEVID,
20238886Stegge    PCI_IVAR_CLASS,
20338886Stegge    PCI_IVAR_SUBCLASS,
20438886Stegge    PCI_IVAR_PROGIF,
20538886Stegge    PCI_IVAR_REVID,
20638886Stegge    PCI_IVAR_INTPIN,
20738886Stegge    PCI_IVAR_IRQ,
208215783Sjilles    PCI_IVAR_BUS,
20938886Stegge    PCI_IVAR_SLOT,
21038886Stegge    PCI_IVAR_FUNCTION,
21138886Stegge    PCI_IVAR_ETHADDR,
21297092Stjr    PCI_IVAR_CMDREG,
21338886Stegge    PCI_IVAR_CACHELNSZ,
21438886Stegge    PCI_IVAR_MINGNT,
21538886Stegge    PCI_IVAR_MAXLAT,
21638886Stegge    PCI_IVAR_LATTIMER,
21738886Stegge};
2181556Srgrimes
219176521Sstefanf/*
2201556Srgrimes * Simplified accessors for pci devices
22197092Stjr */
2221556Srgrimes#define PCI_ACCESSOR(var, ivar, type)					\
223176521Sstefanf	__BUS_ACCESSOR(pci, var, PCI, ivar, type)
2241556Srgrimes
22597092StjrPCI_ACCESSOR(subvendor,		SUBVENDOR,	uint16_t)
2261556SrgrimesPCI_ACCESSOR(subdevice,		SUBDEVICE,	uint16_t)
2271556SrgrimesPCI_ACCESSOR(vendor,		VENDOR,		uint16_t)
228213811SobrienPCI_ACCESSOR(device,		DEVICE,		uint16_t)
22997092StjrPCI_ACCESSOR(devid,		DEVID,		uint32_t)
23097092StjrPCI_ACCESSOR(class,		CLASS,		uint8_t)
231176521SstefanfPCI_ACCESSOR(subclass,		SUBCLASS,	uint8_t)
232222154SjillesPCI_ACCESSOR(progif,		PROGIF,		uint8_t)
2331556SrgrimesPCI_ACCESSOR(revid,		REVID,		uint8_t)
23497092StjrPCI_ACCESSOR(intpin,		INTPIN,		uint8_t)
235215727SjillesPCI_ACCESSOR(irq,		IRQ,		uint8_t)
23697092StjrPCI_ACCESSOR(bus,		BUS,		uint8_t)
23797092StjrPCI_ACCESSOR(slot,		SLOT,		uint8_t)
23897092StjrPCI_ACCESSOR(function,		FUNCTION,	uint8_t)
239215727SjillesPCI_ACCESSOR(ether,		ETHADDR,	uint8_t *)
240222154SjillesPCI_ACCESSOR(cmdreg,		CMDREG,		uint8_t)
241216622SjillesPCI_ACCESSOR(cachelnsz,		CACHELNSZ,	uint8_t)
242222154SjillesPCI_ACCESSOR(mingnt,		MINGNT,		uint8_t)
243222154SjillesPCI_ACCESSOR(maxlat,		MAXLAT,		uint8_t)
244176521SstefanfPCI_ACCESSOR(lattimer,		LATTIMER,	uint8_t)
24597092Stjr
246222154Sjilles#undef PCI_ACCESSOR
24797092Stjr
24897092Stjr/*
2491556Srgrimes * Operations on configuration space.
2501556Srgrimes */
2511556Srgrimesstatic __inline uint32_t
2521556Srgrimespci_read_config(device_t dev, int reg, int width)
253213811Sobrien{
25490111Simp    return PCI_READ_CONFIG(device_get_parent(dev), dev, reg, width);
25520774Ssteve}
25625222Ssteve
2571556Srgrimesstatic __inline void
2581556Srgrimespci_write_config(device_t dev, int reg, uint32_t val, int width)
2591556Srgrimes{
2601556Srgrimes    PCI_WRITE_CONFIG(device_get_parent(dev), dev, reg, val, width);
2611556Srgrimes}
2621556Srgrimes
2631556Srgrimes/*
2641556Srgrimes * Ivars for pci bridges.
2651556Srgrimes */
2661556Srgrimes
2671556Srgrimes/*typedef enum pci_device_ivars pcib_device_ivars;*/
2681556Srgrimesenum pcib_device_ivars {
2691556Srgrimes	PCIB_IVAR_BUS
2701556Srgrimes};
2711556Srgrimes
2721556Srgrimes#define PCIB_ACCESSOR(var, ivar, type)					 \
2731556Srgrimes    __BUS_ACCESSOR(pcib, var, PCIB, ivar, type)
274213811Sobrien
275176521SstefanfPCIB_ACCESSOR(bus,		BUS,		uint32_t)
27620774Ssteve
2771556Srgrimes#undef PCIB_ACCESSOR
2781556Srgrimes
2791556Srgrimes/*
28038886Stegge * PCI interrupt validation.  Invalid interrupt values such as 0 or 128
28138886Stegge * on i386 or other platforms should be mapped out in the MD pcireadconf
28238886Stegge * code and not here, since the only MI invalid IRQ is 255.
28338886Stegge */
28438886Stegge#define PCI_INVALID_IRQ		255
285199631Sstefanf#define PCI_INTERRUPT_VALID(x)	((x) != PCI_INVALID_IRQ)
286199631Sstefanf
2871556Srgrimes/*
2881556Srgrimes * Convenience functions.
2891556Srgrimes *
2901556Srgrimes * These should be used in preference to manually manipulating
291215783Sjilles * configuration space.
292215783Sjilles */
2931556Srgrimesstatic __inline int
2941556Srgrimespci_enable_busmaster(device_t dev)
2951556Srgrimes{
2961556Srgrimes    return(PCI_ENABLE_BUSMASTER(device_get_parent(dev), dev));
2971556Srgrimes}
2981556Srgrimes
2991556Srgrimesstatic __inline int
300215783Sjillespci_disable_busmaster(device_t dev)
3011556Srgrimes{
3021556Srgrimes    return(PCI_DISABLE_BUSMASTER(device_get_parent(dev), dev));
3031556Srgrimes}
3041556Srgrimes
3051556Srgrimesstatic __inline int
306176521Sstefanfpci_enable_io(device_t dev, int space)
307176521Sstefanf{
308176521Sstefanf    return(PCI_ENABLE_IO(device_get_parent(dev), dev, space));
309176521Sstefanf}
310176521Sstefanf
311176521Sstefanfstatic __inline int
312176521Sstefanfpci_disable_io(device_t dev, int space)
313176521Sstefanf{
314213811Sobrien    return(PCI_DISABLE_IO(device_get_parent(dev), dev, space));
315176521Sstefanf}
316176521Sstefanf
317176521Sstefanfstatic __inline int
318176521Sstefanfpci_get_vpd_ident(device_t dev, const char **identptr)
31938886Stegge{
32038886Stegge    return(PCI_GET_VPD_IDENT(device_get_parent(dev), dev, identptr));
32138886Stegge}
322215727Sjilles
32386176Steggestatic __inline int
32486176Steggepci_get_vpd_readonly(device_t dev, const char *kw, const char **identptr)
3251556Srgrimes{
3261556Srgrimes    return(PCI_GET_VPD_READONLY(device_get_parent(dev), dev, kw, identptr));
3271556Srgrimes}
328100660Stjr
32917987Speter/*
330199631Sstefanf * Check if the address range falls within the VGA defined address range(s)
33197092Stjr */
3321556Srgrimesstatic __inline int
333100663Stjrpci_is_vga_ioport_range(u_long start, u_long end)
334100664Stjr{
33597092Stjr
33697092Stjr	return (((start >= 0x3b0 && end <= 0x3bb) ||
33797092Stjr	    (start >= 0x3c0 && end <= 0x3df)) ? 1 : 0);
33897092Stjr}
33997092Stjr
34097092Stjrstatic __inline int
34197092Stjrpci_is_vga_memory_range(u_long start, u_long end)
34297092Stjr{
34397092Stjr
34497092Stjr	return ((start >= 0xa0000 && end <= 0xbffff) ? 1 : 0);
34597092Stjr}
34697092Stjr
34797092Stjr/*
34897092Stjr * PCI power states are as defined by ACPI:
34997092Stjr *
3501556Srgrimes * D0	State in which device is on and running.  It is receiving full
35197092Stjr *	power from the system and delivering full functionality to the user.
35297092Stjr * D1	Class-specific low-power state in which device context may or may not
35338886Stegge *	be lost.  Buses in D1 cannot do anything to the bus that would force
35497092Stjr *	devices on that bus to lose context.
35597092Stjr * D2	Class-specific low-power state in which device context may or may
35697092Stjr *	not be lost.  Attains greater power savings than D1.  Buses in D2
35797092Stjr *	can cause devices on that bus to lose some context.  Devices in D2
358199631Sstefanf *	must be prepared for the bus to be in D2 or higher.
35997092Stjr * D3	State in which the device is off and not running.  Device context is
360199631Sstefanf *	lost.  Power can be removed from the device.
36197092Stjr */
36297092Stjr#define PCI_POWERSTATE_D0	0
36338886Stegge#define PCI_POWERSTATE_D1	1
36497092Stjr#define PCI_POWERSTATE_D2	2
36597092Stjr#define PCI_POWERSTATE_D3	3
36638886Stegge#define PCI_POWERSTATE_UNKNOWN	-1
3671556Srgrimes
368176521Sstefanfstatic __inline int
3691556Srgrimespci_set_powerstate(device_t dev, int state)
370213811Sobrien{
37190111Simp    return PCI_SET_POWERSTATE(device_get_parent(dev), dev, state);
37220425Ssteve}
373176521Sstefanf
37438886Steggestatic __inline int
3751556Srgrimespci_get_powerstate(device_t dev)
37638886Stegge{
377176521Sstefanf    return PCI_GET_POWERSTATE(device_get_parent(dev), dev);
378199631Sstefanf}
379176521Sstefanf
380176521Sstefanfstatic __inline int
381176521Sstefanfpci_find_extcap(device_t dev, int capability, int *capreg)
382176521Sstefanf{
383176521Sstefanf    return PCI_FIND_EXTCAP(device_get_parent(dev), dev, capability, capreg);
384176521Sstefanf}
385199631Sstefanf
386199631Sstefanfdevice_t pci_find_bsf(uint8_t, uint8_t, uint8_t);
387176521Sstefanfdevice_t pci_find_device(uint16_t, uint16_t);
388176521Sstefanf#endif	/* _SYS_BUS_H_ */
389176521Sstefanf
390213811Sobrien/*
391199631Sstefanf * cdev switch for control device, initialised in generic PCI code
392176521Sstefanf */
393199631Sstefanfextern struct cdevsw pcicdev;
394199631Sstefanf
39538886Stegge/*
396199631Sstefanf * List of all PCI devices, generation count for the list.
397199631Sstefanf */
398199631SstefanfSTAILQ_HEAD(devlist, pci_devinfo);
399176521Sstefanf
400199631Sstefanfextern struct devlist	pci_devq;
401199631Sstefanfextern uint32_t	pci_generation;
402199631Sstefanf
40338886Stegge#endif /* _PCIVAR_H_ */
404199631Sstefanf