pcivar.h revision 45720
1160814Ssimon/*
2160814Ssimon * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
3160814Ssimon * All rights reserved.
4160814Ssimon *
5160814Ssimon * Redistribution and use in source and binary forms, with or without
6160814Ssimon * modification, are permitted provided that the following conditions
7160814Ssimon * are met:
8160814Ssimon * 1. Redistributions of source code must retain the above copyright
9160814Ssimon *    notice unmodified, this list of conditions, and the following
10160814Ssimon *    disclaimer.
11160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
12160814Ssimon *    notice, this list of conditions and the following disclaimer in the
13160814Ssimon *    documentation and/or other materials provided with the distribution.
14160814Ssimon *
15160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16160814Ssimon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17160814Ssimon * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18160814Ssimon * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19160814Ssimon * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21160814Ssimon * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22160814Ssimon * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23160814Ssimon * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24160814Ssimon * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25160814Ssimon *
26160814Ssimon * $Id: pcivar.h,v 1.25 1999/01/19 23:29:20 se Exp $
27160814Ssimon *
28160814Ssimon */
29160814Ssimon
30160814Ssimon#ifndef _PCIVAR_H_
31160814Ssimon#define _PCIVAR_H_
32160814Ssimon
33160814Ssimon#ifndef PCI_COMPAT
34160814Ssimon#define PCI_COMPAT
35160814Ssimon#endif
36160814Ssimon
37160814Ssimon#include <pci/pci_ioctl.h> /* XXX KDM */
38160814Ssimon#include <sys/queue.h>
39160814Ssimon
40160814Ssimon/* some PCI bus constants */
41160814Ssimon
42160814Ssimon#define PCI_BUSMAX	255	/* highest supported bus number */
43160814Ssimon#define PCI_SLOTMAX	31	/* highest supported slot number */
44160814Ssimon#define PCI_FUNCMAX	7	/* highest supported function number */
45160814Ssimon#define PCI_REGMAX	255	/* highest supported config register addr. */
46160814Ssimon
47160814Ssimon#define PCI_MAXMAPS_0	6	/* max. no. of memory/port maps */
48160814Ssimon#define PCI_MAXMAPS_1	2	/* max. no. of maps for PCI to PCI bridge */
49160814Ssimon#define PCI_MAXMAPS_2	1	/* max. no. of maps for CardBus bridge */
50160814Ssimon
51160814Ssimon/* pci_addr_t covers this system's PCI bus address space: 32 or 64 bit */
52160814Ssimon
53160814Ssimon#ifdef PCI_A64
54160814Ssimontypedef u_int64_t pci_addr_t;	/* u_int64_t for system with 64bit addresses */
55160814Ssimon#else
56160814Ssimontypedef u_int32_t pci_addr_t;	/* u_int64_t for system with 64bit addresses */
57160814Ssimon#endif
58160814Ssimon
59160814Ssimon/* map register information */
60160814Ssimon
61160814Ssimontypedef struct {
62160814Ssimon    u_int32_t	base;
63160814Ssimon    u_int8_t	type;
64160814Ssimon#define PCI_MAPMEM	0x01	/* memory map */
65160814Ssimon#define PCI_MAPMEMP	0x02	/* prefetchable memory map */
66160814Ssimon#define PCI_MAPPORT	0x04	/* port map */
67160814Ssimon    u_int8_t	ln2size;
68160814Ssimon    u_int8_t	ln2range;
69160814Ssimon    u_int8_t	reg;		/* offset of map register in config space */
70160814Ssimon/*    u_int8_t	dummy;*/
71160814Ssimon    struct resource *res;	/* handle from resource manager */
72160814Ssimon} pcimap;
73160814Ssimon
74160814Ssimon/* config header information common to all header types */
75160814Ssimon
76160814Ssimontypedef struct pcicfg {
77160814Ssimon    struct device *dev;		/* device which owns this */
78160814Ssimon    pcimap	*map;		/* pointer to array of PCI maps */
79160814Ssimon    void	*hdrspec;	/* pointer to header type specific data */
80160814Ssimon    struct resource *irqres;	/* resource descriptor for interrupt mapping */
81160814Ssimon
82160814Ssimon    u_int16_t	subvendor;	/* card vendor ID */
83160814Ssimon    u_int16_t	subdevice;	/* card device ID, assigned by card vendor */
84160814Ssimon    u_int16_t	vendor;		/* chip vendor ID */
85160814Ssimon    u_int16_t	device;		/* chip device ID, assigned by chip vendor */
86160814Ssimon
87160814Ssimon    u_int16_t	cmdreg;		/* disable/enable chip and PCI options */
88160814Ssimon    u_int16_t	statreg;	/* supported PCI features and error state */
89160814Ssimon
90160814Ssimon    u_int8_t	baseclass;	/* chip PCI class */
91160814Ssimon    u_int8_t	subclass;	/* chip PCI subclass */
92160814Ssimon    u_int8_t	progif;		/* chip PCI programming interface */
93160814Ssimon    u_int8_t	revid;		/* chip revision ID */
94160814Ssimon
95160814Ssimon    u_int8_t	hdrtype;	/* chip config header type */
96160814Ssimon    u_int8_t	cachelnsz;	/* cache line size in 4byte units */
97160814Ssimon    u_int8_t	intpin;		/* PCI interrupt pin */
98160814Ssimon    u_int8_t	intline;	/* interrupt line (IRQ for PC arch) */
99160814Ssimon
100160814Ssimon    u_int8_t	mingnt;		/* min. useful bus grant time in 250ns units */
101160814Ssimon    u_int8_t	maxlat;		/* max. tolerated bus grant latency in 250ns */
102160814Ssimon    u_int8_t	lattimer;	/* latency timer in units of 30ns bus cycles */
103160814Ssimon
104160814Ssimon    u_int8_t	mfdev;		/* multi-function device (from hdrtype reg) */
105160814Ssimon    u_int8_t	nummaps;	/* actual number of PCI maps used */
106160814Ssimon
107160814Ssimon    u_int8_t	bus;		/* config space bus address */
108160814Ssimon    u_int8_t	slot;		/* config space slot address */
109160814Ssimon    u_int8_t	func;		/* config space function number */
110160814Ssimon
111160814Ssimon    u_int8_t	secondarybus;	/* bus on secondary side of bridge, if any */
112160814Ssimon    u_int8_t	subordinatebus;	/* topmost bus number behind bridge, if any */
113160814Ssimon} pcicfgregs;
114160814Ssimon
115160814Ssimon/* additional type 1 device config header information (PCI to PCI bridge) */
116160814Ssimon
117160814Ssimon#ifdef PCI_A64
118160814Ssimon#define PCI_PPBMEMBASE(h,l)  ((((pci_addr_t)(h) << 32) + ((l)<<16)) & ~0xfffff)
119160814Ssimon#define PCI_PPBMEMLIMIT(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) | 0xfffff)
120160814Ssimon#else
121160814Ssimon#define PCI_PPBMEMBASE(h,l)  (((l)<<16) & ~0xfffff)
122160814Ssimon#define PCI_PPBMEMLIMIT(h,l) (((l)<<16) | 0xfffff)
123160814Ssimon#endif /* PCI_A64 */
124160814Ssimon
125160814Ssimon#define PCI_PPBIOBASE(h,l)   ((((h)<<16) + ((l)<<8)) & ~0xfff)
126160814Ssimon#define PCI_PPBIOLIMIT(h,l)  ((((h)<<16) + ((l)<<8)) | 0xfff)
127160814Ssimon
128160814Ssimontypedef struct {
129160814Ssimon    pci_addr_t	pmembase;	/* base address of prefetchable memory */
130160814Ssimon    pci_addr_t	pmemlimit;	/* topmost address of prefetchable memory */
131160814Ssimon    u_int32_t	membase;	/* base address of memory window */
132160814Ssimon    u_int32_t	memlimit;	/* topmost address of memory window */
133160814Ssimon    u_int32_t	iobase;		/* base address of port window */
134160814Ssimon    u_int32_t	iolimit;	/* topmost address of port window */
135160814Ssimon    u_int16_t	secstat;	/* secondary bus status register */
136160814Ssimon    u_int16_t	bridgectl;	/* bridge control register */
137160814Ssimon    u_int8_t	seclat;		/* CardBus latency timer */
138160814Ssimon} pcih1cfgregs;
139160814Ssimon
140160814Ssimon/* additional type 2 device config header information (CardBus bridge) */
141160814Ssimon
142160814Ssimontypedef struct {
143160814Ssimon    u_int32_t	membase0;	/* base address of memory window */
144160814Ssimon    u_int32_t	memlimit0;	/* topmost address of memory window */
145160814Ssimon    u_int32_t	membase1;	/* base address of memory window */
146160814Ssimon    u_int32_t	memlimit1;	/* topmost address of memory window */
147160814Ssimon    u_int32_t	iobase0;	/* base address of port window */
148160814Ssimon    u_int32_t	iolimit0;	/* topmost address of port window */
149160814Ssimon    u_int32_t	iobase1;	/* base address of port window */
150160814Ssimon    u_int32_t	iolimit1;	/* topmost address of port window */
151160814Ssimon    u_int32_t	pccardif;	/* PC Card 16bit IF legacy more base addr. */
152160814Ssimon    u_int16_t	secstat;	/* secondary bus status register */
153160814Ssimon    u_int16_t	bridgectl;	/* bridge control register */
154160814Ssimon    u_int8_t	seclat;		/* CardBus latency timer */
155160814Ssimon} pcih2cfgregs;
156160814Ssimon
157160814Ssimon/* PCI bus attach definitions (there could be multiple PCI bus *trees* ... */
158160814Ssimon
159160814Ssimontypedef struct pciattach {
160160814Ssimon    int		unit;
161160814Ssimon    int		pcibushigh;
162160814Ssimon    struct pciattach *next;
163160814Ssimon} pciattach;
164160814Ssimon
165160814Ssimonstruct pci_devinfo {
166160814Ssimon    	STAILQ_ENTRY(pci_devinfo) pci_links;
167160814Ssimon	struct pci_device	*device;  /* should this be ifdefed? */
168160814Ssimon	pcicfgregs		cfg;
169160814Ssimon	struct pci_conf		conf;
170160814Ssimon};
171160814Ssimon
172160814Ssimonextern u_int32_t pci_numdevs;
173160814Ssimon
174160814Ssimon
175160814Ssimon/* externally visible functions */
176160814Ssimon
177160814Ssimonint pci_probe (pciattach *attach);
178160814Ssimonvoid pci_drvattach(struct pci_devinfo *dinfo);
179160814Ssimon
180160814Ssimon/* low level PCI config register functions provided by pcibus.c */
181160814Ssimon
182160814Ssimonint pci_cfgopen (void);
183160814Ssimonint pci_cfgread (pcicfgregs *cfg, int reg, int bytes);
184160814Ssimonvoid pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes);
185160814Ssimon#ifdef __alpha__
186160814Ssimonvm_offset_t pci_cvt_to_dense (vm_offset_t);
187160814Ssimonvm_offset_t pci_cvt_to_bwx (vm_offset_t);
188160814Ssimon#endif /* __alpha__ */
189160814Ssimon
190160814Ssimon#ifdef _SYS_BUS_H_
191160814Ssimon
192160814Ssimon#include "pci_if.h"
193160814Ssimon
194160814Ssimonenum pci_device_ivars {
195160814Ssimon	PCI_IVAR_SUBVENDOR,
196160814Ssimon	PCI_IVAR_SUBDEVICE,
197160814Ssimon	PCI_IVAR_VENDOR,
198160814Ssimon	PCI_IVAR_DEVICE,
199160814Ssimon	PCI_IVAR_DEVID,
200160814Ssimon	PCI_IVAR_CLASS,
201160814Ssimon	PCI_IVAR_SUBCLASS,
202160814Ssimon	PCI_IVAR_PROGIF,
203160814Ssimon	PCI_IVAR_REVID,
204160814Ssimon	PCI_IVAR_INTPIN,
205160814Ssimon	PCI_IVAR_IRQ,
206160814Ssimon	PCI_IVAR_BUS,
207160814Ssimon	PCI_IVAR_SLOT,
208160814Ssimon	PCI_IVAR_FUNCTION,
209160814Ssimon	PCI_IVAR_SECONDARYBUS,
210160814Ssimon	PCI_IVAR_SUBORDINATEBUS,
211160814Ssimon};
212160814Ssimon
213160814Ssimon/*
214160814Ssimon * Simplified accessors for pci devices
215160814Ssimon */
216160814Ssimon#define PCI_ACCESSOR(A, B, T)						\
217160814Ssimon									\
218160814Ssimonstatic __inline T pci_get_ ## A(device_t dev)				\
219160814Ssimon{									\
220160814Ssimon	uintptr_t v;							\
221160814Ssimon	BUS_READ_IVAR(device_get_parent(dev), dev, PCI_IVAR_ ## B, &v);	\
222160814Ssimon	return (T) v;							\
223160814Ssimon}									\
224160814Ssimon									\
225160814Ssimonstatic __inline void pci_set_ ## A(device_t dev, T t)			\
226160814Ssimon{									\
227160814Ssimon	u_long v = (u_long) t;						\
228160814Ssimon	BUS_WRITE_IVAR(device_get_parent(dev), dev, PCI_IVAR_ ## B, v);	\
229160814Ssimon}
230160814Ssimon
231160814SsimonPCI_ACCESSOR(subvendor,		SUBVENDOR,	u_int16_t)
232160814SsimonPCI_ACCESSOR(subdevice,		SUBDEVICE,	u_int16_t)
233160814SsimonPCI_ACCESSOR(vendor,		VENDOR,		u_int16_t)
234160814SsimonPCI_ACCESSOR(device,		DEVICE,		u_int16_t)
235160814SsimonPCI_ACCESSOR(devid,		DEVID,		u_int32_t)
236160814SsimonPCI_ACCESSOR(class,		CLASS,		u_int8_t)
237160814SsimonPCI_ACCESSOR(subclass,		SUBCLASS,	u_int8_t)
238160814SsimonPCI_ACCESSOR(progif,		PROGIF,		u_int8_t)
239160814SsimonPCI_ACCESSOR(revid,		REVID,		u_int8_t)
240160814SsimonPCI_ACCESSOR(intpin,		INTPIN,		u_int8_t)
241160814SsimonPCI_ACCESSOR(irq,		IRQ,		u_int8_t)
242160814SsimonPCI_ACCESSOR(bus,		BUS,		u_int8_t)
243160814SsimonPCI_ACCESSOR(slot,		SLOT,		u_int8_t)
244160814SsimonPCI_ACCESSOR(function,		FUNCTION,	u_int8_t)
245160814SsimonPCI_ACCESSOR(secondarybus,	SECONDARYBUS,	u_int8_t)
246160814SsimonPCI_ACCESSOR(subordinatebus,	SUBORDINATEBUS,	u_int8_t)
247160814Ssimon
248160814Ssimonstatic __inline u_int32_t
249160814Ssimonpci_read_config(device_t dev, int reg, int width)
250160814Ssimon{
251160814Ssimon    return PCI_READ_CONFIG(device_get_parent(dev), dev, reg, width);
252160814Ssimon}
253160814Ssimon
254160814Ssimonstatic __inline void
255160814Ssimonpci_write_config(device_t dev, int reg, u_int32_t val, int width)
256160814Ssimon{
257160814Ssimon    PCI_WRITE_CONFIG(device_get_parent(dev), dev, reg, val, width);
258160814Ssimon}
259160814Ssimon
260160814Ssimon#endif
261160814Ssimon
262/* for compatibility to FreeBSD-2.2 version of PCI code */
263
264#ifdef PCI_COMPAT
265
266typedef pcicfgregs *pcici_t;
267typedef unsigned pcidi_t;
268typedef void pci_inthand_t(void *arg);
269
270#define pci_max_burst_len (3)
271
272/* just copied from old PCI code for now ... */
273
274extern struct linker_set pcidevice_set;
275extern int pci_mechanism;
276
277struct pci_device {
278    char*    pd_name;
279    const char*  (*pd_probe ) (pcici_t tag, pcidi_t type);
280    void   (*pd_attach) (pcici_t tag, int     unit);
281    u_long  *pd_count;
282    int    (*pd_shutdown) (int, int);
283};
284
285struct pci_lkm {
286	struct pci_device *dvp;
287	struct pci_lkm	*next;
288};
289
290#ifdef __i386__
291typedef u_short pci_port_t;
292#else
293typedef u_int pci_port_t;
294#endif
295
296u_long pci_conf_read (pcici_t tag, u_long reg);
297void pci_conf_write (pcici_t tag, u_long reg, u_long data);
298void pci_configure (void);
299int pci_map_port (pcici_t tag, u_long reg, pci_port_t* pa);
300int pci_map_mem (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa);
301int pci_map_dense (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa);
302int pci_map_bwx (pcici_t tag, u_long reg, vm_offset_t* va, vm_offset_t* pa);
303int pci_map_int (pcici_t tag, pci_inthand_t *handler, void *arg,
304		 intrmask_t *maskptr);
305int pci_map_int_right(pcici_t cfg, pci_inthand_t *handler, void *arg,
306		      intrmask_t *maskptr, u_int flags);
307int pci_unmap_int (pcici_t tag);
308int pci_register_lkm (struct pci_device *dvp, int if_revision);
309
310#endif /* PCI_COMPAT */
311#endif /* _PCIVAR_H_ */
312