xref: /minix3/minix/drivers/bus/pci/pci.c (revision fee60e45e67240c6c98101a60bf7abc705899333)
1433d6423SLionel Sambuc /*
2433d6423SLionel Sambuc pci.c
3433d6423SLionel Sambuc 
4433d6423SLionel Sambuc Configure devices on the PCI bus
5433d6423SLionel Sambuc 
6433d6423SLionel Sambuc Created:	Jan 2000 by Philip Homburg <philip@cs.vu.nl>
7433d6423SLionel Sambuc */
86e7bb628SLionel Sambuc #include <minix/acpi.h>
95d831176SLionel Sambuc #include <minix/chardriver.h>
105d831176SLionel Sambuc #include <minix/driver.h>
115d831176SLionel Sambuc #include <minix/param.h>
126e7bb628SLionel Sambuc #include <minix/rs.h>
136e7bb628SLionel Sambuc 
146e7bb628SLionel Sambuc #include <machine/pci.h>
15433d6423SLionel Sambuc #include <machine/pci_amd.h>
16433d6423SLionel Sambuc #include <machine/pci_intel.h>
17433d6423SLionel Sambuc #include <machine/pci_sis.h>
18433d6423SLionel Sambuc #include <machine/pci_via.h>
196e7bb628SLionel Sambuc #include <machine/vmparam.h>
20433d6423SLionel Sambuc 
210a6a1f1dSLionel Sambuc #include <dev/pci/pci_verbose.h>
220a6a1f1dSLionel Sambuc 
233641562fSLionel Sambuc #include <pci.h>
24433d6423SLionel Sambuc #include <stdlib.h>
25433d6423SLionel Sambuc #include <stdio.h>
266e7bb628SLionel Sambuc 
276e7bb628SLionel Sambuc #include "pci.h"
286e7bb628SLionel Sambuc 
290a6a1f1dSLionel Sambuc #define PCI_VENDORSTR_LEN	64
300a6a1f1dSLionel Sambuc #define PCI_PRODUCTSTR_LEN	64
310a6a1f1dSLionel Sambuc 
326e7bb628SLionel Sambuc #define irq_mode_pci(irq) ((void)0)
33433d6423SLionel Sambuc 
34433d6423SLionel Sambuc #define PBT_INTEL_HOST	 1
35433d6423SLionel Sambuc #define PBT_PCIBRIDGE	 2
36433d6423SLionel Sambuc #define PBT_CARDBUS	 3
37433d6423SLionel Sambuc 
38433d6423SLionel Sambuc #define BAM_NR		6	/* Number of base-address registers */
39433d6423SLionel Sambuc 
406e7bb628SLionel Sambuc struct pci_acl pci_acl[NR_DRIVERS];
41433d6423SLionel Sambuc 
42433d6423SLionel Sambuc static struct pcibus
43433d6423SLionel Sambuc {
44433d6423SLionel Sambuc 	int pb_type;
45433d6423SLionel Sambuc 	int pb_needinit;
46433d6423SLionel Sambuc 	int pb_isabridge_dev;
47433d6423SLionel Sambuc 	int pb_isabridge_type;
48433d6423SLionel Sambuc 
49433d6423SLionel Sambuc 	int pb_devind;
50433d6423SLionel Sambuc 	int pb_busnr;
51433d6423SLionel Sambuc 	u8_t (*pb_rreg8)(int busind, int devind, int port);
52433d6423SLionel Sambuc 	u16_t (*pb_rreg16)(int busind, int devind, int port);
53433d6423SLionel Sambuc 	u32_t (*pb_rreg32)(int busind, int devind, int port);
54433d6423SLionel Sambuc 	void (*pb_wreg8)(int busind, int devind, int port, u8_t value);
55433d6423SLionel Sambuc 	void (*pb_wreg16)(int busind, int devind, int port, u16_t value);
56433d6423SLionel Sambuc 	void (*pb_wreg32)(int busind, int devind, int port, u32_t value);
57433d6423SLionel Sambuc 	u16_t (*pb_rsts)(int busind);
58433d6423SLionel Sambuc 	void (*pb_wsts)(int busind, u16_t value);
59433d6423SLionel Sambuc } pcibus[NR_PCIBUS];
60433d6423SLionel Sambuc static int nr_pcibus= 0;
61433d6423SLionel Sambuc 
62433d6423SLionel Sambuc static struct pcidev
63433d6423SLionel Sambuc {
64433d6423SLionel Sambuc 	u8_t pd_busnr;
65433d6423SLionel Sambuc 	u8_t pd_dev;
66433d6423SLionel Sambuc 	u8_t pd_func;
67433d6423SLionel Sambuc 	u8_t pd_baseclass;
68433d6423SLionel Sambuc 	u8_t pd_subclass;
69433d6423SLionel Sambuc 	u8_t pd_infclass;
70433d6423SLionel Sambuc 	u16_t pd_vid;
71433d6423SLionel Sambuc 	u16_t pd_did;
72433d6423SLionel Sambuc 	u16_t pd_sub_vid;
73433d6423SLionel Sambuc 	u16_t pd_sub_did;
74433d6423SLionel Sambuc 	u8_t pd_ilr;
75433d6423SLionel Sambuc 
76433d6423SLionel Sambuc 	u8_t pd_inuse;
77433d6423SLionel Sambuc 	endpoint_t pd_proc;
78433d6423SLionel Sambuc 
79433d6423SLionel Sambuc 	struct bar
80433d6423SLionel Sambuc 	{
81433d6423SLionel Sambuc 		int pb_flags;
82433d6423SLionel Sambuc 		int pb_nr;
83433d6423SLionel Sambuc 		u32_t pb_base;
84433d6423SLionel Sambuc 		u32_t pb_size;
85433d6423SLionel Sambuc 	} pd_bar[BAM_NR];
86433d6423SLionel Sambuc 	int pd_bar_nr;
87433d6423SLionel Sambuc } pcidev[NR_PCIDEV];
88433d6423SLionel Sambuc 
89433d6423SLionel Sambuc /* pb_flags */
90433d6423SLionel Sambuc #define PBF_IO		1	/* I/O else memory */
91433d6423SLionel Sambuc #define PBF_INCOMPLETE	2	/* not allocated */
92433d6423SLionel Sambuc 
93433d6423SLionel Sambuc static int nr_pcidev= 0;
94433d6423SLionel Sambuc 
95433d6423SLionel Sambuc static struct machine machine;
96433d6423SLionel Sambuc 
97433d6423SLionel Sambuc /*===========================================================================*
98433d6423SLionel Sambuc  *			helper functions for I/O			     *
99433d6423SLionel Sambuc  *===========================================================================*/
1006e7bb628SLionel Sambuc static unsigned
pci_inb(u16_t port)1016e7bb628SLionel Sambuc pci_inb(u16_t port) {
102433d6423SLionel Sambuc 	u32_t value;
103433d6423SLionel Sambuc 	int s;
104433d6423SLionel Sambuc 	if ((s=sys_inb(port, &value)) !=OK)
105433d6423SLionel Sambuc 		printf("PCI: warning, sys_inb failed: %d\n", s);
106433d6423SLionel Sambuc 	return value;
107433d6423SLionel Sambuc }
1086e7bb628SLionel Sambuc 
1096e7bb628SLionel Sambuc static unsigned
pci_inw(u16_t port)1106e7bb628SLionel Sambuc pci_inw(u16_t port) {
111433d6423SLionel Sambuc 	u32_t value;
112433d6423SLionel Sambuc 	int s;
113433d6423SLionel Sambuc 	if ((s=sys_inw(port, &value)) !=OK)
114433d6423SLionel Sambuc 		printf("PCI: warning, sys_inw failed: %d\n", s);
115433d6423SLionel Sambuc 	return value;
116433d6423SLionel Sambuc }
1176e7bb628SLionel Sambuc 
1186e7bb628SLionel Sambuc static unsigned
pci_inl(u16_t port)1196e7bb628SLionel Sambuc pci_inl(u16_t port) {
120433d6423SLionel Sambuc 	u32_t value;
121433d6423SLionel Sambuc 	int s;
122433d6423SLionel Sambuc 	if ((s=sys_inl(port, &value)) !=OK)
123433d6423SLionel Sambuc 		printf("PCI: warning, sys_inl failed: %d\n", s);
124433d6423SLionel Sambuc 	return value;
125433d6423SLionel Sambuc }
1266e7bb628SLionel Sambuc 
1276e7bb628SLionel Sambuc static void
pci_outb(u16_t port,u8_t value)1286e7bb628SLionel Sambuc pci_outb(u16_t port, u8_t value) {
129433d6423SLionel Sambuc 	int s;
130433d6423SLionel Sambuc 	if ((s=sys_outb(port, value)) !=OK)
131433d6423SLionel Sambuc 		printf("PCI: warning, sys_outb failed: %d\n", s);
132433d6423SLionel Sambuc }
1336e7bb628SLionel Sambuc 
1346e7bb628SLionel Sambuc static void
pci_outw(u16_t port,u16_t value)1356e7bb628SLionel Sambuc pci_outw(u16_t port, u16_t value) {
136433d6423SLionel Sambuc 	int s;
137433d6423SLionel Sambuc 	if ((s=sys_outw(port, value)) !=OK)
138433d6423SLionel Sambuc 		printf("PCI: warning, sys_outw failed: %d\n", s);
139433d6423SLionel Sambuc }
1406e7bb628SLionel Sambuc 
1416e7bb628SLionel Sambuc static void
pci_outl(u16_t port,u32_t value)1426e7bb628SLionel Sambuc pci_outl(u16_t port, u32_t value) {
143433d6423SLionel Sambuc 	int s;
144433d6423SLionel Sambuc 	if ((s=sys_outl(port, value)) !=OK)
145433d6423SLionel Sambuc 		printf("PCI: warning, sys_outl failed: %d\n", s);
146433d6423SLionel Sambuc }
147433d6423SLionel Sambuc 
1486e7bb628SLionel Sambuc static u8_t
pcii_rreg8(int busind,int devind,int port)1496e7bb628SLionel Sambuc pcii_rreg8(int busind, int devind, int port)
150433d6423SLionel Sambuc {
1516e7bb628SLionel Sambuc 	u8_t v;
1526e7bb628SLionel Sambuc 	int s;
153433d6423SLionel Sambuc 
1546e7bb628SLionel Sambuc 	v= PCII_RREG8_(pcibus[busind].pb_busnr,
1556e7bb628SLionel Sambuc 		pcidev[devind].pd_dev, pcidev[devind].pd_func,
1566e7bb628SLionel Sambuc 		port);
1576e7bb628SLionel Sambuc 	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
1586e7bb628SLionel Sambuc 		printf("PCI: warning, sys_outl failed: %d\n", s);
159433d6423SLionel Sambuc #if 0
1606e7bb628SLionel Sambuc 	printf("pcii_rreg8(%d, %d, 0x%X): %d.%d.%d= 0x%X\n",
1616e7bb628SLionel Sambuc 		busind, devind, port,
1626e7bb628SLionel Sambuc 		pcibus[busind].pb_bus, pcidev[devind].pd_dev,
1636e7bb628SLionel Sambuc 		pcidev[devind].pd_func, v);
164433d6423SLionel Sambuc #endif
1656e7bb628SLionel Sambuc 	return v;
166433d6423SLionel Sambuc }
167433d6423SLionel Sambuc 
1686e7bb628SLionel Sambuc static u16_t
pcii_rreg16(int busind,int devind,int port)1696e7bb628SLionel Sambuc pcii_rreg16(int busind, int devind, int port)
170433d6423SLionel Sambuc {
1716e7bb628SLionel Sambuc 	u16_t v;
1726e7bb628SLionel Sambuc 	int s;
173433d6423SLionel Sambuc 
1746e7bb628SLionel Sambuc 	v= PCII_RREG16_(pcibus[busind].pb_busnr,
1756e7bb628SLionel Sambuc 		pcidev[devind].pd_dev, pcidev[devind].pd_func,
1766e7bb628SLionel Sambuc 		port);
1776e7bb628SLionel Sambuc 	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
1786e7bb628SLionel Sambuc 		printf("PCI: warning, sys_outl failed: %d\n", s);
179433d6423SLionel Sambuc #if 0
1806e7bb628SLionel Sambuc 	printf("pcii_rreg16(%d, %d, 0x%X): %d.%d.%d= 0x%X\n",
1816e7bb628SLionel Sambuc 		busind, devind, port,
1826e7bb628SLionel Sambuc 		pcibus[busind].pb_bus, pcidev[devind].pd_dev,
1836e7bb628SLionel Sambuc 		pcidev[devind].pd_func, v);
184433d6423SLionel Sambuc #endif
1856e7bb628SLionel Sambuc 	return v;
186433d6423SLionel Sambuc }
187433d6423SLionel Sambuc 
1886e7bb628SLionel Sambuc static u32_t
pcii_rreg32(int busind,int devind,int port)1896e7bb628SLionel Sambuc pcii_rreg32(int busind, int devind, int port)
190433d6423SLionel Sambuc {
1916e7bb628SLionel Sambuc 	u32_t v;
1926e7bb628SLionel Sambuc 	int s;
193433d6423SLionel Sambuc 
1946e7bb628SLionel Sambuc 	v= PCII_RREG32_(pcibus[busind].pb_busnr,
1956e7bb628SLionel Sambuc 		pcidev[devind].pd_dev, pcidev[devind].pd_func,
1966e7bb628SLionel Sambuc 		port);
1976e7bb628SLionel Sambuc 	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
1986e7bb628SLionel Sambuc 		printf("PCI: warning, sys_outl failed: %d\n", s);
199433d6423SLionel Sambuc #if 0
2006e7bb628SLionel Sambuc 	printf("pcii_rreg32(%d, %d, 0x%X): %d.%d.%d= 0x%X\n",
2016e7bb628SLionel Sambuc 		busind, devind, port,
2026e7bb628SLionel Sambuc 		pcibus[busind].pb_bus, pcidev[devind].pd_dev,
2036e7bb628SLionel Sambuc 		pcidev[devind].pd_func, v);
204433d6423SLionel Sambuc #endif
2056e7bb628SLionel Sambuc 	return v;
206433d6423SLionel Sambuc }
2076e7bb628SLionel Sambuc 
2086e7bb628SLionel Sambuc static void
pcii_wreg8(int busind,int devind,int port,u8_t value)2096e7bb628SLionel Sambuc pcii_wreg8(int busind, int devind, int port, u8_t value)
2106e7bb628SLionel Sambuc {
2116e7bb628SLionel Sambuc 	int s;
2126e7bb628SLionel Sambuc #if 0
2136e7bb628SLionel Sambuc 	printf("pcii_wreg8(%d, %d, 0x%X, 0x%X): %d.%d.%d\n",
2146e7bb628SLionel Sambuc 		busind, devind, port, value,
2156e7bb628SLionel Sambuc 		pcibus[busind].pb_bus, pcidev[devind].pd_dev,
2166e7bb628SLionel Sambuc 		pcidev[devind].pd_func);
2176e7bb628SLionel Sambuc #endif
2186e7bb628SLionel Sambuc 	PCII_WREG8_(pcibus[busind].pb_busnr,
2196e7bb628SLionel Sambuc 		pcidev[devind].pd_dev, pcidev[devind].pd_func,
2206e7bb628SLionel Sambuc 		port, value);
2216e7bb628SLionel Sambuc 	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
2226e7bb628SLionel Sambuc 		printf("PCI: warning, sys_outl failed: %d\n", s);
2236e7bb628SLionel Sambuc }
2246e7bb628SLionel Sambuc 
2256e7bb628SLionel Sambuc static void
pcii_wreg16(int busind,int devind,int port,u16_t value)2266e7bb628SLionel Sambuc pcii_wreg16(int busind, int devind, int port, u16_t value)
2276e7bb628SLionel Sambuc {
2286e7bb628SLionel Sambuc 	int s;
2296e7bb628SLionel Sambuc #if 0
2306e7bb628SLionel Sambuc 	printf("pcii_wreg16(%d, %d, 0x%X, 0x%X): %d.%d.%d\n",
2316e7bb628SLionel Sambuc 		busind, devind, port, value,
2326e7bb628SLionel Sambuc 		pcibus[busind].pb_bus, pcidev[devind].pd_dev,
2336e7bb628SLionel Sambuc 		pcidev[devind].pd_func);
2346e7bb628SLionel Sambuc #endif
2356e7bb628SLionel Sambuc 	PCII_WREG16_(pcibus[busind].pb_busnr,
2366e7bb628SLionel Sambuc 		pcidev[devind].pd_dev, pcidev[devind].pd_func,
2376e7bb628SLionel Sambuc 		port, value);
2386e7bb628SLionel Sambuc 	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
2396e7bb628SLionel Sambuc 		printf("PCI: warning, sys_outl failed: %d\n", s);
2406e7bb628SLionel Sambuc }
2416e7bb628SLionel Sambuc 
2426e7bb628SLionel Sambuc static void
pcii_wreg32(int busind,int devind,int port,u32_t value)2436e7bb628SLionel Sambuc pcii_wreg32(int busind, int devind, int port, u32_t value)
2446e7bb628SLionel Sambuc {
2456e7bb628SLionel Sambuc 	int s;
2466e7bb628SLionel Sambuc #if 0
2476e7bb628SLionel Sambuc 	printf("pcii_wreg32(%d, %d, 0x%X, 0x%X): %d.%d.%d\n",
2486e7bb628SLionel Sambuc 		busind, devind, port, value,
2496e7bb628SLionel Sambuc 		pcibus[busind].pb_busnr, pcidev[devind].pd_dev,
2506e7bb628SLionel Sambuc 		pcidev[devind].pd_func);
2516e7bb628SLionel Sambuc #endif
2526e7bb628SLionel Sambuc 	PCII_WREG32_(pcibus[busind].pb_busnr,
2536e7bb628SLionel Sambuc 		pcidev[devind].pd_dev, pcidev[devind].pd_func,
2546e7bb628SLionel Sambuc 		port, value);
2556e7bb628SLionel Sambuc 	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
2566e7bb628SLionel Sambuc 		printf("PCI: warning, sys_outl failed: %d\n",s);
257433d6423SLionel Sambuc }
258433d6423SLionel Sambuc 
259433d6423SLionel Sambuc /*===========================================================================*
2606e7bb628SLionel Sambuc  *				ntostr					     *
261433d6423SLionel Sambuc  *===========================================================================*/
2626e7bb628SLionel Sambuc static void
ntostr(unsigned int n,char ** str,const char * end)2636e7bb628SLionel Sambuc ntostr(unsigned int n, char **str, const char *end)
264433d6423SLionel Sambuc {
2656e7bb628SLionel Sambuc 	char tmpstr[20];
2666e7bb628SLionel Sambuc 	int i;
267433d6423SLionel Sambuc 
2686e7bb628SLionel Sambuc 	if (n == 0)
269433d6423SLionel Sambuc 	{
2706e7bb628SLionel Sambuc 		tmpstr[0]= '0';
2716e7bb628SLionel Sambuc 		i= 1;
272433d6423SLionel Sambuc 	}
273433d6423SLionel Sambuc 	else
274433d6423SLionel Sambuc 	{
2756e7bb628SLionel Sambuc 		for (i= 0; n; i++)
276433d6423SLionel Sambuc 		{
2776e7bb628SLionel Sambuc 			tmpstr[i]= '0' + (n%10);
2786e7bb628SLionel Sambuc 			n /= 10;
279433d6423SLionel Sambuc 		}
280433d6423SLionel Sambuc 	}
2816e7bb628SLionel Sambuc 	for (; i>0; i--)
282433d6423SLionel Sambuc 	{
2836e7bb628SLionel Sambuc 		if (*str == end)
284433d6423SLionel Sambuc 		{
2856e7bb628SLionel Sambuc 			break;
286433d6423SLionel Sambuc 		}
2876e7bb628SLionel Sambuc 		**str= tmpstr[i-1];
2886e7bb628SLionel Sambuc 		(*str)++;
289433d6423SLionel Sambuc 	}
2906e7bb628SLionel Sambuc 	if (*str == end)
2916e7bb628SLionel Sambuc 		(*str)[-1]= '\0';
2926e7bb628SLionel Sambuc 	else
2936e7bb628SLionel Sambuc 		**str= '\0';
294433d6423SLionel Sambuc }
295433d6423SLionel Sambuc 
296433d6423SLionel Sambuc /*===========================================================================*
2976e7bb628SLionel Sambuc  *				get_busind					     *
298433d6423SLionel Sambuc  *===========================================================================*/
2996e7bb628SLionel Sambuc static int
get_busind(int busnr)3006e7bb628SLionel Sambuc get_busind(int busnr)
301433d6423SLionel Sambuc {
302433d6423SLionel Sambuc 	int i;
303433d6423SLionel Sambuc 
3046e7bb628SLionel Sambuc 	for (i= 0; i<nr_pcibus; i++)
305433d6423SLionel Sambuc 	{
3066e7bb628SLionel Sambuc 		if (pcibus[i].pb_busnr == busnr)
3076e7bb628SLionel Sambuc 			return i;
308433d6423SLionel Sambuc 	}
3096e7bb628SLionel Sambuc 	panic("get_busind: can't find bus: %d", busnr);
310433d6423SLionel Sambuc }
311433d6423SLionel Sambuc 
312433d6423SLionel Sambuc /*===========================================================================*
3136e7bb628SLionel Sambuc  *			Unprotected helper functions			     *
314433d6423SLionel Sambuc  *===========================================================================*/
3156e7bb628SLionel Sambuc static u8_t
__pci_attr_r8(int devind,int port)3166e7bb628SLionel Sambuc __pci_attr_r8(int devind, int port)
317433d6423SLionel Sambuc {
318433d6423SLionel Sambuc 	int busnr, busind;
319433d6423SLionel Sambuc 
320433d6423SLionel Sambuc 	busnr= pcidev[devind].pd_busnr;
321433d6423SLionel Sambuc 	busind= get_busind(busnr);
322433d6423SLionel Sambuc 	return pcibus[busind].pb_rreg8(busind, devind, port);
323433d6423SLionel Sambuc }
324433d6423SLionel Sambuc 
3256e7bb628SLionel Sambuc static u16_t
__pci_attr_r16(int devind,int port)3266e7bb628SLionel Sambuc __pci_attr_r16(int devind, int port)
327433d6423SLionel Sambuc {
328433d6423SLionel Sambuc 	int busnr, busind;
329433d6423SLionel Sambuc 
330433d6423SLionel Sambuc 	busnr= pcidev[devind].pd_busnr;
331433d6423SLionel Sambuc 	busind= get_busind(busnr);
332433d6423SLionel Sambuc 	return pcibus[busind].pb_rreg16(busind, devind, port);
333433d6423SLionel Sambuc }
334433d6423SLionel Sambuc 
3356e7bb628SLionel Sambuc static u32_t
__pci_attr_r32(int devind,int port)3366e7bb628SLionel Sambuc __pci_attr_r32(int devind, int port)
337433d6423SLionel Sambuc {
338433d6423SLionel Sambuc 	int busnr, busind;
339433d6423SLionel Sambuc 
340433d6423SLionel Sambuc 	busnr= pcidev[devind].pd_busnr;
341433d6423SLionel Sambuc 	busind= get_busind(busnr);
342433d6423SLionel Sambuc 	return pcibus[busind].pb_rreg32(busind, devind, port);
343433d6423SLionel Sambuc }
344433d6423SLionel Sambuc 
3456e7bb628SLionel Sambuc static void
__pci_attr_w8(int devind,int port,u8_t value)3466e7bb628SLionel Sambuc __pci_attr_w8(int devind, int port, u8_t value)
347433d6423SLionel Sambuc {
348433d6423SLionel Sambuc 	int busnr, busind;
349433d6423SLionel Sambuc 
350433d6423SLionel Sambuc 	busnr= pcidev[devind].pd_busnr;
351433d6423SLionel Sambuc 	busind= get_busind(busnr);
352433d6423SLionel Sambuc 	pcibus[busind].pb_wreg8(busind, devind, port, value);
353433d6423SLionel Sambuc }
354433d6423SLionel Sambuc 
3556e7bb628SLionel Sambuc static void
__pci_attr_w16(int devind,int port,u16_t value)3566e7bb628SLionel Sambuc __pci_attr_w16(int devind, int port, u16_t value)
357433d6423SLionel Sambuc {
358433d6423SLionel Sambuc 	int busnr, busind;
359433d6423SLionel Sambuc 
360433d6423SLionel Sambuc 	busnr= pcidev[devind].pd_busnr;
361433d6423SLionel Sambuc 	busind= get_busind(busnr);
362433d6423SLionel Sambuc 	pcibus[busind].pb_wreg16(busind, devind, port, value);
363433d6423SLionel Sambuc }
364433d6423SLionel Sambuc 
3656e7bb628SLionel Sambuc static void
__pci_attr_w32(int devind,int port,u32_t value)3666e7bb628SLionel Sambuc __pci_attr_w32(int devind, int port, u32_t value)
367433d6423SLionel Sambuc {
368433d6423SLionel Sambuc 	int busnr, busind;
369433d6423SLionel Sambuc 
370433d6423SLionel Sambuc 	busnr= pcidev[devind].pd_busnr;
371433d6423SLionel Sambuc 	busind= get_busind(busnr);
372433d6423SLionel Sambuc 	pcibus[busind].pb_wreg32(busind, devind, port, value);
373433d6423SLionel Sambuc }
374433d6423SLionel Sambuc 
375433d6423SLionel Sambuc /*===========================================================================*
3766e7bb628SLionel Sambuc  *				helpers					     *
377433d6423SLionel Sambuc  *===========================================================================*/
3786e7bb628SLionel Sambuc static u16_t
pci_attr_rsts(int devind)3796e7bb628SLionel Sambuc pci_attr_rsts(int devind)
380433d6423SLionel Sambuc {
3816e7bb628SLionel Sambuc 	int busnr, busind;
382433d6423SLionel Sambuc 
3836e7bb628SLionel Sambuc 	busnr= pcidev[devind].pd_busnr;
3846e7bb628SLionel Sambuc 	busind= get_busind(busnr);
3856e7bb628SLionel Sambuc 	return pcibus[busind].pb_rsts(busind);
3866e7bb628SLionel Sambuc }
387433d6423SLionel Sambuc 
3886e7bb628SLionel Sambuc static void
pci_attr_wsts(int devind,u16_t value)3896e7bb628SLionel Sambuc pci_attr_wsts(int devind, u16_t value)
3906e7bb628SLionel Sambuc {
3916e7bb628SLionel Sambuc 	int busnr, busind;
3926e7bb628SLionel Sambuc 
3936e7bb628SLionel Sambuc 	busnr= pcidev[devind].pd_busnr;
3946e7bb628SLionel Sambuc 	busind= get_busind(busnr);
3956e7bb628SLionel Sambuc 	pcibus[busind].pb_wsts(busind, value);
3966e7bb628SLionel Sambuc }
3976e7bb628SLionel Sambuc 
3986e7bb628SLionel Sambuc static u16_t
pcii_rsts(int busind)3996e7bb628SLionel Sambuc pcii_rsts(int busind)
4006e7bb628SLionel Sambuc {
4016e7bb628SLionel Sambuc 	u16_t v;
4026e7bb628SLionel Sambuc 	int s;
4036e7bb628SLionel Sambuc 
4046e7bb628SLionel Sambuc 	v= PCII_RREG16_(pcibus[busind].pb_busnr, 0, 0, PCI_SR);
405433d6423SLionel Sambuc 	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
406433d6423SLionel Sambuc 		printf("PCI: warning, sys_outl failed: %d\n", s);
4076e7bb628SLionel Sambuc 	return v;
4086e7bb628SLionel Sambuc }
409433d6423SLionel Sambuc 
4106e7bb628SLionel Sambuc static void
pcii_wsts(int busind,u16_t value)4116e7bb628SLionel Sambuc pcii_wsts(int busind, u16_t value)
412433d6423SLionel Sambuc {
4136e7bb628SLionel Sambuc 	int s;
4146e7bb628SLionel Sambuc 	PCII_WREG16_(pcibus[busind].pb_busnr, 0, 0, PCI_SR, value);
4156e7bb628SLionel Sambuc 	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
4166e7bb628SLionel Sambuc 		printf("PCI: warning, sys_outl failed: %d\n", s);
417433d6423SLionel Sambuc }
418433d6423SLionel Sambuc 
4196e7bb628SLionel Sambuc static int
is_duplicate(u8_t busnr,u8_t dev,u8_t func)4206e7bb628SLionel Sambuc is_duplicate(u8_t busnr, u8_t dev, u8_t func)
421433d6423SLionel Sambuc {
422433d6423SLionel Sambuc 	int i;
423433d6423SLionel Sambuc 
424433d6423SLionel Sambuc 	for (i= 0; i<nr_pcidev; i++)
425433d6423SLionel Sambuc 	{
426433d6423SLionel Sambuc 		if (pcidev[i].pd_busnr == busnr &&
427433d6423SLionel Sambuc 			pcidev[i].pd_dev == dev &&
428433d6423SLionel Sambuc 			pcidev[i].pd_func == func)
429433d6423SLionel Sambuc 		{
430433d6423SLionel Sambuc 			return 1;
431433d6423SLionel Sambuc 		}
432433d6423SLionel Sambuc 	}
433433d6423SLionel Sambuc 	return 0;
434433d6423SLionel Sambuc }
435433d6423SLionel Sambuc 
4366e7bb628SLionel Sambuc static int
get_freebus(void)4376e7bb628SLionel Sambuc get_freebus(void)
4386e7bb628SLionel Sambuc {
4396e7bb628SLionel Sambuc 	int i, freebus;
4406e7bb628SLionel Sambuc 
4416e7bb628SLionel Sambuc 	freebus= 1;
4426e7bb628SLionel Sambuc 	for (i= 0; i<nr_pcibus; i++)
4436e7bb628SLionel Sambuc 	{
4446e7bb628SLionel Sambuc 		if (pcibus[i].pb_needinit)
4456e7bb628SLionel Sambuc 			continue;
4466e7bb628SLionel Sambuc 		if (pcibus[i].pb_type == PBT_INTEL_HOST)
4476e7bb628SLionel Sambuc 			continue;
4486e7bb628SLionel Sambuc 		if (pcibus[i].pb_busnr <= freebus)
4496e7bb628SLionel Sambuc 			freebus= pcibus[i].pb_busnr+1;
4506e7bb628SLionel Sambuc 		printf("get_freebus: should check suboridinate bus number\n");
4516e7bb628SLionel Sambuc 	}
4526e7bb628SLionel Sambuc 	return freebus;
4536e7bb628SLionel Sambuc }
4546e7bb628SLionel Sambuc 
4556e7bb628SLionel Sambuc static const char *
pci_vid_name(u16_t vid)4566e7bb628SLionel Sambuc pci_vid_name(u16_t vid)
4576e7bb628SLionel Sambuc {
4580a6a1f1dSLionel Sambuc 	static char vendor[PCI_VENDORSTR_LEN];
4590a6a1f1dSLionel Sambuc 	pci_findvendor(vendor, sizeof(vendor), vid);
4600a6a1f1dSLionel Sambuc 
4610a6a1f1dSLionel Sambuc 	return vendor;
4626e7bb628SLionel Sambuc }
4636e7bb628SLionel Sambuc 
4646e7bb628SLionel Sambuc 
4656e7bb628SLionel Sambuc static void
print_hyper_cap(int devind,u8_t capptr)4666e7bb628SLionel Sambuc print_hyper_cap(int devind, u8_t capptr)
4676e7bb628SLionel Sambuc {
4686e7bb628SLionel Sambuc 	u32_t v;
4696e7bb628SLionel Sambuc 	u16_t cmd;
4706e7bb628SLionel Sambuc 	int type0, type1;
4716e7bb628SLionel Sambuc 
4726e7bb628SLionel Sambuc 	printf("\n");
4736e7bb628SLionel Sambuc 	v= __pci_attr_r32(devind, capptr);
4746e7bb628SLionel Sambuc 	printf("print_hyper_cap: @0x%x, off 0 (cap):", capptr);
4756e7bb628SLionel Sambuc 	cmd= (v >> 16) & 0xffff;
4766e7bb628SLionel Sambuc #if 0
4776e7bb628SLionel Sambuc 	if (v & 0x10000)
4786e7bb628SLionel Sambuc 	{
4796e7bb628SLionel Sambuc 		printf(" WarmReset");
4806e7bb628SLionel Sambuc 		v &= ~0x10000;
4816e7bb628SLionel Sambuc 	}
4826e7bb628SLionel Sambuc 	if (v & 0x20000)
4836e7bb628SLionel Sambuc 	{
4846e7bb628SLionel Sambuc 		printf(" DblEnded");
4856e7bb628SLionel Sambuc 		v &= ~0x20000;
4866e7bb628SLionel Sambuc 	}
4876e7bb628SLionel Sambuc 	printf(" DevNum %d", (v & 0x7C0000) >> 18);
4886e7bb628SLionel Sambuc 	v &= ~0x7C0000;
4896e7bb628SLionel Sambuc #endif
4906e7bb628SLionel Sambuc 	type0= (cmd & 0xE000) >> 13;
4916e7bb628SLionel Sambuc 	type1= (cmd & 0xF800) >> 11;
4926e7bb628SLionel Sambuc 	if (type0 == 0 || type0 == 1)
4936e7bb628SLionel Sambuc 	{
4946e7bb628SLionel Sambuc 		printf("Capability Type: %s\n",
4956e7bb628SLionel Sambuc 			type0 == 0 ? "Slave or Primary Interface" :
4966e7bb628SLionel Sambuc 			"Host or Secondary Interface");
4976e7bb628SLionel Sambuc 		cmd &= ~0xE000;
4986e7bb628SLionel Sambuc 	}
4996e7bb628SLionel Sambuc 	else
5006e7bb628SLionel Sambuc 	{
5016e7bb628SLionel Sambuc 		printf(" Capability Type 0x%x", type1);
5026e7bb628SLionel Sambuc 		cmd &= ~0xF800;
5036e7bb628SLionel Sambuc 	}
5046e7bb628SLionel Sambuc 	if (cmd)
5056e7bb628SLionel Sambuc 		printf(" undecoded 0x%x\n", cmd);
5066e7bb628SLionel Sambuc 
5076e7bb628SLionel Sambuc #if 0
5086e7bb628SLionel Sambuc 	printf("print_hyper_cap: off 4 (ctl): 0x%x\n",
5096e7bb628SLionel Sambuc 		__pci_attr_r32(devind, capptr+4));
5106e7bb628SLionel Sambuc 	printf("print_hyper_cap: off 8 (freq/rev): 0x%x\n",
5116e7bb628SLionel Sambuc 		__pci_attr_r32(devind, capptr+8));
5126e7bb628SLionel Sambuc 	printf("print_hyper_cap: off 12 (cap): 0x%x\n",
5136e7bb628SLionel Sambuc 		__pci_attr_r32(devind, capptr+12));
5146e7bb628SLionel Sambuc 	printf("print_hyper_cap: off 16 (buf count): 0x%x\n",
5156e7bb628SLionel Sambuc 		__pci_attr_r32(devind, capptr+16));
5166e7bb628SLionel Sambuc 	v= __pci_attr_r32(devind, capptr+20);
5176e7bb628SLionel Sambuc 	printf("print_hyper_cap: @0x%x, off 20 (bus nr): ",
5186e7bb628SLionel Sambuc 		capptr+20);
5196e7bb628SLionel Sambuc 	printf("prim %d", v & 0xff);
5206e7bb628SLionel Sambuc 	printf(", sec %d", (v >> 8) & 0xff);
5216e7bb628SLionel Sambuc 	printf(", sub %d", (v >> 16) & 0xff);
5226e7bb628SLionel Sambuc 	if (v >> 24)
5236e7bb628SLionel Sambuc 		printf(", reserved %d", (v >> 24) & 0xff);
5246e7bb628SLionel Sambuc 	printf("\n");
5256e7bb628SLionel Sambuc 	printf("print_hyper_cap: off 24 (type): 0x%x\n",
5266e7bb628SLionel Sambuc 		__pci_attr_r32(devind, capptr+24));
5276e7bb628SLionel Sambuc #endif
5286e7bb628SLionel Sambuc }
5296e7bb628SLionel Sambuc 
5306e7bb628SLionel Sambuc static void
print_capabilities(int devind)5316e7bb628SLionel Sambuc print_capabilities(int devind)
5326e7bb628SLionel Sambuc {
5336e7bb628SLionel Sambuc 	u8_t status, capptr, type, next, subtype;
5346e7bb628SLionel Sambuc 	const char *str;
5356e7bb628SLionel Sambuc 
5366e7bb628SLionel Sambuc 	/* Check capabilities bit in the device status register */
5376e7bb628SLionel Sambuc 	status= __pci_attr_r16(devind, PCI_SR);
5386e7bb628SLionel Sambuc 	if (!(status & PSR_CAPPTR))
5396e7bb628SLionel Sambuc 		return;
5406e7bb628SLionel Sambuc 
5416e7bb628SLionel Sambuc 	capptr= (__pci_attr_r8(devind, PCI_CAPPTR) & PCI_CP_MASK);
5426e7bb628SLionel Sambuc 	while (capptr != 0)
5436e7bb628SLionel Sambuc 	{
5446e7bb628SLionel Sambuc 		type = __pci_attr_r8(devind, capptr+CAP_TYPE);
5456e7bb628SLionel Sambuc 		next= (__pci_attr_r8(devind, capptr+CAP_NEXT) & PCI_CP_MASK);
5466e7bb628SLionel Sambuc 		switch(type)
5476e7bb628SLionel Sambuc 		{
5486e7bb628SLionel Sambuc 		case 1: str= "PCI Power Management"; break;
5496e7bb628SLionel Sambuc 		case 2: str= "AGP"; break;
5506e7bb628SLionel Sambuc 		case 3: str= "Vital Product Data"; break;
5516e7bb628SLionel Sambuc 		case 4:	str= "Slot Identification"; break;
5526e7bb628SLionel Sambuc 		case 5: str= "Message Signaled Interrupts"; break;
5536e7bb628SLionel Sambuc 		case 6: str= "CompactPCI Hot Swap"; break;
5546e7bb628SLionel Sambuc 		case 8: str= "AMD HyperTransport"; break;
5556e7bb628SLionel Sambuc 		case 0xf: str= "Secure Device"; break;
5566e7bb628SLionel Sambuc 		default: str= "(unknown type)"; break;
5576e7bb628SLionel Sambuc 		}
5586e7bb628SLionel Sambuc 
5596e7bb628SLionel Sambuc 		printf(" @0x%x (0x%08x): capability type 0x%x: %s",
5606e7bb628SLionel Sambuc 			capptr, __pci_attr_r32(devind, capptr), type, str);
5616e7bb628SLionel Sambuc 		if (type == 0x08)
5626e7bb628SLionel Sambuc 			print_hyper_cap(devind, capptr);
5636e7bb628SLionel Sambuc 		else if (type == 0x0f)
5646e7bb628SLionel Sambuc 		{
5656e7bb628SLionel Sambuc 			subtype= (__pci_attr_r8(devind, capptr+2) & 0x07);
5666e7bb628SLionel Sambuc 			switch(subtype)
5676e7bb628SLionel Sambuc 			{
5686e7bb628SLionel Sambuc 			case 0: str= "Device Exclusion Vector"; break;
5696e7bb628SLionel Sambuc 			case 3: str= "IOMMU"; break;
5706e7bb628SLionel Sambuc 			default: str= "(unknown type)"; break;
5716e7bb628SLionel Sambuc 			}
5726e7bb628SLionel Sambuc 			printf(", sub type 0%o: %s", subtype, str);
5736e7bb628SLionel Sambuc 		}
5746e7bb628SLionel Sambuc 		printf("\n");
5756e7bb628SLionel Sambuc 		capptr= next;
5766e7bb628SLionel Sambuc 	}
5776e7bb628SLionel Sambuc }
5786e7bb628SLionel Sambuc 
5796e7bb628SLionel Sambuc /*===========================================================================*
5806e7bb628SLionel Sambuc  *				ISA Bridge Helpers			     *
5816e7bb628SLionel Sambuc  *===========================================================================*/
5826e7bb628SLionel Sambuc static void
update_bridge4dev_io(int devind,u32_t io_base,u32_t io_size)5836e7bb628SLionel Sambuc update_bridge4dev_io(int devind, u32_t io_base, u32_t io_size)
5846e7bb628SLionel Sambuc {
5856e7bb628SLionel Sambuc 	int busnr, busind, type, br_devind;
5866e7bb628SLionel Sambuc 	u16_t v16;
5876e7bb628SLionel Sambuc 
5886e7bb628SLionel Sambuc 	busnr= pcidev[devind].pd_busnr;
5896e7bb628SLionel Sambuc 	busind= get_busind(busnr);
5906e7bb628SLionel Sambuc 	type= pcibus[busind].pb_type;
5916e7bb628SLionel Sambuc 	if (type == PBT_INTEL_HOST)
5926e7bb628SLionel Sambuc 		return;	/* Nothing to do for host controller */
5936e7bb628SLionel Sambuc 	if (type == PBT_PCIBRIDGE)
5946e7bb628SLionel Sambuc 	{
5956e7bb628SLionel Sambuc 		printf(
5966e7bb628SLionel Sambuc 		"update_bridge4dev_io: not implemented for PCI bridges\n");
5976e7bb628SLionel Sambuc 		return;
5986e7bb628SLionel Sambuc 	}
5996e7bb628SLionel Sambuc 	if (type != PBT_CARDBUS)
6006e7bb628SLionel Sambuc 		panic("update_bridge4dev_io: strange bus type: %d", type);
6016e7bb628SLionel Sambuc 
6026e7bb628SLionel Sambuc 	if (debug)
6036e7bb628SLionel Sambuc 	{
6046e7bb628SLionel Sambuc 		printf("update_bridge4dev_io: adding 0x%x at 0x%x\n",
6056e7bb628SLionel Sambuc 			io_size, io_base);
6066e7bb628SLionel Sambuc 	}
6076e7bb628SLionel Sambuc 	br_devind= pcibus[busind].pb_devind;
6086e7bb628SLionel Sambuc 	__pci_attr_w32(br_devind, CBB_IOLIMIT_0, io_base+io_size-1);
6096e7bb628SLionel Sambuc 	__pci_attr_w32(br_devind, CBB_IOBASE_0, io_base);
6106e7bb628SLionel Sambuc 
6116e7bb628SLionel Sambuc 	/* Enable I/O access. Enable busmaster access as well. */
6126e7bb628SLionel Sambuc 	v16= __pci_attr_r16(devind, PCI_CR);
6136e7bb628SLionel Sambuc 	__pci_attr_w16(devind, PCI_CR, v16 | PCI_CR_IO_EN | PCI_CR_MAST_EN);
6146e7bb628SLionel Sambuc }
6156e7bb628SLionel Sambuc 
6166e7bb628SLionel Sambuc static int
do_piix(int devind)6176e7bb628SLionel Sambuc do_piix(int devind)
6186e7bb628SLionel Sambuc {
6196e7bb628SLionel Sambuc 	int i, s, irqrc, irq;
6206e7bb628SLionel Sambuc 	u32_t elcr1, elcr2, elcr;
6216e7bb628SLionel Sambuc 
6226e7bb628SLionel Sambuc #if DEBUG
6236e7bb628SLionel Sambuc 	printf("in piix\n");
6246e7bb628SLionel Sambuc #endif
6256e7bb628SLionel Sambuc 	if (OK != (s=sys_inb(PIIX_ELCR1, &elcr1)))
6266e7bb628SLionel Sambuc 		printf("Warning, sys_inb failed: %d\n", s);
6276e7bb628SLionel Sambuc 	if (OK != (s=sys_inb(PIIX_ELCR2, &elcr2)))
6286e7bb628SLionel Sambuc 		printf("Warning, sys_inb failed: %d\n", s);
6296e7bb628SLionel Sambuc 	elcr= elcr1 | (elcr2 << 8);
6306e7bb628SLionel Sambuc 	for (i= 0; i<4; i++)
6316e7bb628SLionel Sambuc 	{
6326e7bb628SLionel Sambuc 		irqrc= __pci_attr_r8(devind, PIIX_PIRQRCA+i);
6336e7bb628SLionel Sambuc 		if (irqrc & PIIX_IRQ_DI)
6346e7bb628SLionel Sambuc 		{
6356e7bb628SLionel Sambuc 			if (debug)
6366e7bb628SLionel Sambuc 				printf("INT%c: disabled\n", 'A'+i);
6376e7bb628SLionel Sambuc 		}
6386e7bb628SLionel Sambuc 		else
6396e7bb628SLionel Sambuc 		{
6406e7bb628SLionel Sambuc 			irq= irqrc & PIIX_IRQ_MASK;
6416e7bb628SLionel Sambuc 			if (debug)
6426e7bb628SLionel Sambuc 				printf("INT%c: %d\n", 'A'+i, irq);
6436e7bb628SLionel Sambuc 			if (!(elcr & (1 << irq)))
6446e7bb628SLionel Sambuc 			{
6456e7bb628SLionel Sambuc 				if (debug)
6466e7bb628SLionel Sambuc 				{
6476e7bb628SLionel Sambuc 					printf(
6486e7bb628SLionel Sambuc 				"(warning) IRQ %d is not level triggered\n",
6496e7bb628SLionel Sambuc 						irq);
6506e7bb628SLionel Sambuc 				}
6516e7bb628SLionel Sambuc 			}
6526e7bb628SLionel Sambuc 			irq_mode_pci(irq);
6536e7bb628SLionel Sambuc 		}
6546e7bb628SLionel Sambuc 	}
6556e7bb628SLionel Sambuc 	return 0;
6566e7bb628SLionel Sambuc }
6576e7bb628SLionel Sambuc 
6586e7bb628SLionel Sambuc static int
do_amd_isabr(int devind)6596e7bb628SLionel Sambuc do_amd_isabr(int devind)
6606e7bb628SLionel Sambuc {
6616e7bb628SLionel Sambuc 	int i, busnr, dev, func, xdevind, irq, edge;
6626e7bb628SLionel Sambuc 	u8_t levmask;
6636e7bb628SLionel Sambuc 	u16_t pciirq;
6646e7bb628SLionel Sambuc 
6656e7bb628SLionel Sambuc 	/* Find required function */
6666e7bb628SLionel Sambuc 	func= AMD_ISABR_FUNC;
6676e7bb628SLionel Sambuc 	busnr= pcidev[devind].pd_busnr;
6686e7bb628SLionel Sambuc 	dev= pcidev[devind].pd_dev;
6696e7bb628SLionel Sambuc 
6706e7bb628SLionel Sambuc 	/* Fake a device with the required function */
6716e7bb628SLionel Sambuc 	if (nr_pcidev >= NR_PCIDEV)
6726e7bb628SLionel Sambuc 		panic("too many PCI devices: %d", nr_pcidev);
6736e7bb628SLionel Sambuc 	xdevind= nr_pcidev;
6746e7bb628SLionel Sambuc 	pcidev[xdevind].pd_busnr= busnr;
6756e7bb628SLionel Sambuc 	pcidev[xdevind].pd_dev= dev;
6766e7bb628SLionel Sambuc 	pcidev[xdevind].pd_func= func;
6776e7bb628SLionel Sambuc 	pcidev[xdevind].pd_inuse= 1;
6786e7bb628SLionel Sambuc 	nr_pcidev++;
6796e7bb628SLionel Sambuc 
6806e7bb628SLionel Sambuc 	levmask= __pci_attr_r8(xdevind, AMD_ISABR_PCIIRQ_LEV);
6816e7bb628SLionel Sambuc 	pciirq= __pci_attr_r16(xdevind, AMD_ISABR_PCIIRQ_ROUTE);
6826e7bb628SLionel Sambuc 	for (i= 0; i<4; i++)
6836e7bb628SLionel Sambuc 	{
6846e7bb628SLionel Sambuc 		edge= (levmask >> i) & 1;
6856e7bb628SLionel Sambuc 		irq= (pciirq >> (4*i)) & 0xf;
6866e7bb628SLionel Sambuc 		if (!irq)
6876e7bb628SLionel Sambuc 		{
6886e7bb628SLionel Sambuc 			if (debug)
6896e7bb628SLionel Sambuc 				printf("INT%c: disabled\n", 'A'+i);
6906e7bb628SLionel Sambuc 		}
6916e7bb628SLionel Sambuc 		else
6926e7bb628SLionel Sambuc 		{
6936e7bb628SLionel Sambuc 			if (debug)
6946e7bb628SLionel Sambuc 				printf("INT%c: %d\n", 'A'+i, irq);
6956e7bb628SLionel Sambuc 			if (edge && debug)
6966e7bb628SLionel Sambuc 			{
6976e7bb628SLionel Sambuc 				printf(
6986e7bb628SLionel Sambuc 				"(warning) IRQ %d is not level triggered\n",
6996e7bb628SLionel Sambuc 					irq);
7006e7bb628SLionel Sambuc 			}
7016e7bb628SLionel Sambuc 			irq_mode_pci(irq);
7026e7bb628SLionel Sambuc 		}
7036e7bb628SLionel Sambuc 	}
7046e7bb628SLionel Sambuc 	nr_pcidev--;
7056e7bb628SLionel Sambuc 	return 0;
7066e7bb628SLionel Sambuc }
7076e7bb628SLionel Sambuc 
7086e7bb628SLionel Sambuc static int
do_sis_isabr(int devind)7096e7bb628SLionel Sambuc do_sis_isabr(int devind)
7106e7bb628SLionel Sambuc {
7116e7bb628SLionel Sambuc 	int i, irq;
7126e7bb628SLionel Sambuc 
7136e7bb628SLionel Sambuc 	irq= 0;	/* lint */
7146e7bb628SLionel Sambuc 	for (i= 0; i<4; i++)
7156e7bb628SLionel Sambuc 	{
7166e7bb628SLionel Sambuc 		irq= __pci_attr_r8(devind, SIS_ISABR_IRQ_A+i);
7176e7bb628SLionel Sambuc 		if (irq & SIS_IRQ_DISABLED)
7186e7bb628SLionel Sambuc 		{
7196e7bb628SLionel Sambuc 			if (debug)
7206e7bb628SLionel Sambuc 				printf("INT%c: disabled\n", 'A'+i);
7216e7bb628SLionel Sambuc 		}
7226e7bb628SLionel Sambuc 		else
7236e7bb628SLionel Sambuc 		{
7246e7bb628SLionel Sambuc 			irq &= SIS_IRQ_MASK;
7256e7bb628SLionel Sambuc 			if (debug)
7266e7bb628SLionel Sambuc 				printf("INT%c: %d\n", 'A'+i, irq);
7276e7bb628SLionel Sambuc 			irq_mode_pci(irq);
7286e7bb628SLionel Sambuc 		}
7296e7bb628SLionel Sambuc 	}
7306e7bb628SLionel Sambuc 	return 0;
7316e7bb628SLionel Sambuc }
7326e7bb628SLionel Sambuc 
7336e7bb628SLionel Sambuc static int
do_via_isabr(int devind)7346e7bb628SLionel Sambuc do_via_isabr(int devind)
7356e7bb628SLionel Sambuc {
7366e7bb628SLionel Sambuc 	int i, irq, edge;
7376e7bb628SLionel Sambuc 	u8_t levmask;
7386e7bb628SLionel Sambuc 
7396e7bb628SLionel Sambuc 	levmask= __pci_attr_r8(devind, VIA_ISABR_EL);
7406e7bb628SLionel Sambuc 	irq= 0;	/* lint */
7416e7bb628SLionel Sambuc 	edge= 0; /* lint */
7426e7bb628SLionel Sambuc 	for (i= 0; i<4; i++)
7436e7bb628SLionel Sambuc 	{
7446e7bb628SLionel Sambuc 		switch(i)
7456e7bb628SLionel Sambuc 		{
7466e7bb628SLionel Sambuc 		case 0:
7476e7bb628SLionel Sambuc 			edge= (levmask & VIA_ISABR_EL_INTA);
7486e7bb628SLionel Sambuc 			irq= __pci_attr_r8(devind, VIA_ISABR_IRQ_R2) >> 4;
7496e7bb628SLionel Sambuc 			break;
7506e7bb628SLionel Sambuc 		case 1:
7516e7bb628SLionel Sambuc 			edge= (levmask & VIA_ISABR_EL_INTB);
7526e7bb628SLionel Sambuc 			irq= __pci_attr_r8(devind, VIA_ISABR_IRQ_R2);
7536e7bb628SLionel Sambuc 			break;
7546e7bb628SLionel Sambuc 		case 2:
7556e7bb628SLionel Sambuc 			edge= (levmask & VIA_ISABR_EL_INTC);
7566e7bb628SLionel Sambuc 			irq= __pci_attr_r8(devind, VIA_ISABR_IRQ_R3) >> 4;
7576e7bb628SLionel Sambuc 			break;
7586e7bb628SLionel Sambuc 		case 3:
7596e7bb628SLionel Sambuc 			edge= (levmask & VIA_ISABR_EL_INTD);
7606e7bb628SLionel Sambuc 			irq= __pci_attr_r8(devind, VIA_ISABR_IRQ_R1) >> 4;
7616e7bb628SLionel Sambuc 			break;
7626e7bb628SLionel Sambuc 		default:
7636e7bb628SLionel Sambuc 			panic("PCI: VIA ISA Bridge IRQ Detection Failed");
7646e7bb628SLionel Sambuc 		}
7656e7bb628SLionel Sambuc 		irq &= 0xf;
7666e7bb628SLionel Sambuc 		if (!irq)
7676e7bb628SLionel Sambuc 		{
7686e7bb628SLionel Sambuc 			if (debug)
7696e7bb628SLionel Sambuc 				printf("INT%c: disabled\n", 'A'+i);
7706e7bb628SLionel Sambuc 		}
7716e7bb628SLionel Sambuc 		else
7726e7bb628SLionel Sambuc 		{
7736e7bb628SLionel Sambuc 			if (debug)
7746e7bb628SLionel Sambuc 				printf("INT%c: %d\n", 'A'+i, irq);
7756e7bb628SLionel Sambuc 			if (edge && debug)
7766e7bb628SLionel Sambuc 			{
7776e7bb628SLionel Sambuc 				printf(
7786e7bb628SLionel Sambuc 				"(warning) IRQ %d is not level triggered\n",
7796e7bb628SLionel Sambuc 					irq);
7806e7bb628SLionel Sambuc 			}
7816e7bb628SLionel Sambuc 			irq_mode_pci(irq);
7826e7bb628SLionel Sambuc 		}
7836e7bb628SLionel Sambuc 	}
7846e7bb628SLionel Sambuc 	return 0;
7856e7bb628SLionel Sambuc }
7866e7bb628SLionel Sambuc 
7876e7bb628SLionel Sambuc static int
do_isabridge(int busind)7886e7bb628SLionel Sambuc do_isabridge(int busind)
7896e7bb628SLionel Sambuc {
7906e7bb628SLionel Sambuc 	int i, j, r, type, busnr, unknown_bridge, bridge_dev;
7916e7bb628SLionel Sambuc 	u16_t vid, did;
7926e7bb628SLionel Sambuc 	u32_t t3;
7936e7bb628SLionel Sambuc 	const char *dstr;
7946e7bb628SLionel Sambuc 
7956e7bb628SLionel Sambuc 	unknown_bridge= -1;
7966e7bb628SLionel Sambuc 	bridge_dev= -1;
7976e7bb628SLionel Sambuc 	j= 0;	/* lint */
7986e7bb628SLionel Sambuc 	vid= did= 0;	/* lint */
7996e7bb628SLionel Sambuc 	busnr= pcibus[busind].pb_busnr;
8006e7bb628SLionel Sambuc 	for (i= 0; i< nr_pcidev; i++)
8016e7bb628SLionel Sambuc 	{
8026e7bb628SLionel Sambuc 		if (pcidev[i].pd_busnr != busnr)
8036e7bb628SLionel Sambuc 			continue;
8046e7bb628SLionel Sambuc 		t3= ((pcidev[i].pd_baseclass << 16) |
8056e7bb628SLionel Sambuc 			(pcidev[i].pd_subclass << 8) | pcidev[i].pd_infclass);
8066e7bb628SLionel Sambuc 		if (t3 == PCI_T3_ISA)
8076e7bb628SLionel Sambuc 		{
8086e7bb628SLionel Sambuc 			/* ISA bridge. Report if no supported bridge is
8096e7bb628SLionel Sambuc 			 * found.
8106e7bb628SLionel Sambuc 			 */
8116e7bb628SLionel Sambuc 			unknown_bridge= i;
8126e7bb628SLionel Sambuc 		}
8136e7bb628SLionel Sambuc 
8146e7bb628SLionel Sambuc 		vid= pcidev[i].pd_vid;
8156e7bb628SLionel Sambuc 		did= pcidev[i].pd_did;
8166e7bb628SLionel Sambuc 		for (j= 0; pci_isabridge[j].vid != 0; j++)
8176e7bb628SLionel Sambuc 		{
8186e7bb628SLionel Sambuc 			if (pci_isabridge[j].vid != vid)
8196e7bb628SLionel Sambuc 				continue;
8206e7bb628SLionel Sambuc 			if (pci_isabridge[j].did != did)
8216e7bb628SLionel Sambuc 				continue;
8226e7bb628SLionel Sambuc 			if (pci_isabridge[j].checkclass &&
8236e7bb628SLionel Sambuc 				unknown_bridge != i)
8246e7bb628SLionel Sambuc 			{
8256e7bb628SLionel Sambuc 				/* This part of multifunction device is
8266e7bb628SLionel Sambuc 				 * not the bridge.
8276e7bb628SLionel Sambuc 				 */
8286e7bb628SLionel Sambuc 				continue;
8296e7bb628SLionel Sambuc 			}
8306e7bb628SLionel Sambuc 			break;
8316e7bb628SLionel Sambuc 		}
8326e7bb628SLionel Sambuc 		if (pci_isabridge[j].vid)
8336e7bb628SLionel Sambuc 		{
8346e7bb628SLionel Sambuc 			bridge_dev= i;
8356e7bb628SLionel Sambuc 			break;
8366e7bb628SLionel Sambuc 		}
8376e7bb628SLionel Sambuc 	}
8386e7bb628SLionel Sambuc 
8396e7bb628SLionel Sambuc 	if (bridge_dev != -1)
8406e7bb628SLionel Sambuc 	{
8416e7bb628SLionel Sambuc 		dstr= _pci_dev_name(vid, did);
8426e7bb628SLionel Sambuc 		if (!dstr)
8436e7bb628SLionel Sambuc 			dstr= "unknown device";
8446e7bb628SLionel Sambuc 		if (debug)
8456e7bb628SLionel Sambuc 		{
8466e7bb628SLionel Sambuc 			printf("found ISA bridge (%04X:%04X) %s\n",
8476e7bb628SLionel Sambuc 				vid, did, dstr);
8486e7bb628SLionel Sambuc 		}
8496e7bb628SLionel Sambuc 		pcibus[busind].pb_isabridge_dev= bridge_dev;
8506e7bb628SLionel Sambuc 		type= pci_isabridge[j].type;
8516e7bb628SLionel Sambuc 		pcibus[busind].pb_isabridge_type= type;
8526e7bb628SLionel Sambuc 		switch(type)
8536e7bb628SLionel Sambuc 		{
8546e7bb628SLionel Sambuc 		case PCI_IB_PIIX:
8556e7bb628SLionel Sambuc 			r= do_piix(bridge_dev);
8566e7bb628SLionel Sambuc 			break;
8576e7bb628SLionel Sambuc 		case PCI_IB_VIA:
8586e7bb628SLionel Sambuc 			r= do_via_isabr(bridge_dev);
8596e7bb628SLionel Sambuc 			break;
8606e7bb628SLionel Sambuc 		case PCI_IB_AMD:
8616e7bb628SLionel Sambuc 			r= do_amd_isabr(bridge_dev);
8626e7bb628SLionel Sambuc 			break;
8636e7bb628SLionel Sambuc 		case PCI_IB_SIS:
8646e7bb628SLionel Sambuc 			r= do_sis_isabr(bridge_dev);
8656e7bb628SLionel Sambuc 			break;
8666e7bb628SLionel Sambuc 		default:
8676e7bb628SLionel Sambuc 			panic("unknown ISA bridge type: %d", type);
8686e7bb628SLionel Sambuc 		}
8696e7bb628SLionel Sambuc 		return r;
8706e7bb628SLionel Sambuc 	}
8716e7bb628SLionel Sambuc 
8726e7bb628SLionel Sambuc 	if (unknown_bridge == -1)
8736e7bb628SLionel Sambuc 	{
8746e7bb628SLionel Sambuc 		if (debug)
8756e7bb628SLionel Sambuc 		{
8766e7bb628SLionel Sambuc 			printf("(warning) no ISA bridge found on bus %d\n",
8776e7bb628SLionel Sambuc 				busind);
8786e7bb628SLionel Sambuc 		}
8796e7bb628SLionel Sambuc 		return 0;
8806e7bb628SLionel Sambuc 	}
8816e7bb628SLionel Sambuc 	if (debug)
8826e7bb628SLionel Sambuc 	{
8836e7bb628SLionel Sambuc 		printf(
8846e7bb628SLionel Sambuc 		"(warning) unsupported ISA bridge %04X:%04X for bus %d\n",
8856e7bb628SLionel Sambuc 			pcidev[unknown_bridge].pd_vid,
8866e7bb628SLionel Sambuc 			pcidev[unknown_bridge].pd_did, busind);
8876e7bb628SLionel Sambuc 	}
8886e7bb628SLionel Sambuc 	return 0;
8896e7bb628SLionel Sambuc }
8906e7bb628SLionel Sambuc 
8916e7bb628SLionel Sambuc static int
derive_irq(struct pcidev * dev,int pin)8926e7bb628SLionel Sambuc derive_irq(struct pcidev * dev, int pin)
893433d6423SLionel Sambuc {
894433d6423SLionel Sambuc 	struct pcidev * parent_bridge;
895433d6423SLionel Sambuc 	int slot;
896433d6423SLionel Sambuc 
897433d6423SLionel Sambuc 	parent_bridge = &pcidev[pcibus[get_busind(dev->pd_busnr)].pb_devind];
898433d6423SLionel Sambuc 
899433d6423SLionel Sambuc 	/*
900433d6423SLionel Sambuc 	 * We don't support PCI-Express, no ARI, decode the slot of the device
901433d6423SLionel Sambuc 	 * and mangle the pin as the device is behind a bridge
902433d6423SLionel Sambuc 	 */
903433d6423SLionel Sambuc 	slot = ((dev->pd_func) >> 3) & 0x1f;
904433d6423SLionel Sambuc 
905433d6423SLionel Sambuc 	return acpi_get_irq(parent_bridge->pd_busnr,
906433d6423SLionel Sambuc 			parent_bridge->pd_dev, (pin + slot) % 4);
907433d6423SLionel Sambuc }
908433d6423SLionel Sambuc 
9096e7bb628SLionel Sambuc static void
record_irq(int devind)9106e7bb628SLionel Sambuc record_irq(int devind)
911433d6423SLionel Sambuc {
912433d6423SLionel Sambuc 	int ilr, ipr, busnr, busind, cb_devind;
913433d6423SLionel Sambuc 
9146e7bb628SLionel Sambuc 	ilr= __pci_attr_r8(devind, PCI_ILR);
9156e7bb628SLionel Sambuc 	ipr= __pci_attr_r8(devind, PCI_IPR);
916433d6423SLionel Sambuc 
917433d6423SLionel Sambuc 	if (ipr && machine.apic_enabled) {
918433d6423SLionel Sambuc 		int irq;
919433d6423SLionel Sambuc 
920433d6423SLionel Sambuc 		irq = acpi_get_irq(pcidev[devind].pd_busnr,
921433d6423SLionel Sambuc 				pcidev[devind].pd_dev, ipr - 1);
922433d6423SLionel Sambuc 
923433d6423SLionel Sambuc 		if (irq < 0)
924433d6423SLionel Sambuc 			irq = derive_irq(&pcidev[devind], ipr - 1);
925433d6423SLionel Sambuc 
926433d6423SLionel Sambuc 		if (irq >= 0) {
927433d6423SLionel Sambuc 			ilr = irq;
9286e7bb628SLionel Sambuc 			__pci_attr_w8(devind, PCI_ILR, ilr);
929433d6423SLionel Sambuc 			if (debug)
930433d6423SLionel Sambuc 				printf("PCI: ACPI IRQ %d for "
931433d6423SLionel Sambuc 						"device %d.%d.%d INT%c\n",
932433d6423SLionel Sambuc 						irq,
933433d6423SLionel Sambuc 						pcidev[devind].pd_busnr,
934433d6423SLionel Sambuc 						pcidev[devind].pd_dev,
935433d6423SLionel Sambuc 						pcidev[devind].pd_func,
936433d6423SLionel Sambuc 						'A' + ipr-1);
937433d6423SLionel Sambuc 		}
938433d6423SLionel Sambuc 		else if (debug) {
939433d6423SLionel Sambuc 			printf("PCI: no ACPI IRQ routing for "
940433d6423SLionel Sambuc 					"device %d.%d.%d INT%c\n",
941433d6423SLionel Sambuc 					pcidev[devind].pd_busnr,
942433d6423SLionel Sambuc 					pcidev[devind].pd_dev,
943433d6423SLionel Sambuc 					pcidev[devind].pd_func,
944433d6423SLionel Sambuc 					'A' + ipr-1);
945433d6423SLionel Sambuc 		}
946433d6423SLionel Sambuc 	}
947433d6423SLionel Sambuc 
948433d6423SLionel Sambuc 	if (ilr == 0)
949433d6423SLionel Sambuc 	{
950433d6423SLionel Sambuc 		static int first= 1;
951433d6423SLionel Sambuc 		if (ipr && first && debug)
952433d6423SLionel Sambuc 		{
953433d6423SLionel Sambuc 			first= 0;
954433d6423SLionel Sambuc 			printf("PCI: strange, BIOS assigned IRQ0\n");
955433d6423SLionel Sambuc 		}
956433d6423SLionel Sambuc 		ilr= PCI_ILR_UNKNOWN;
957433d6423SLionel Sambuc 	}
958433d6423SLionel Sambuc 	pcidev[devind].pd_ilr= ilr;
959433d6423SLionel Sambuc 	if (ilr == PCI_ILR_UNKNOWN && !ipr)
960433d6423SLionel Sambuc 	{
961433d6423SLionel Sambuc 	}
962433d6423SLionel Sambuc 	else if (ilr != PCI_ILR_UNKNOWN && ipr)
963433d6423SLionel Sambuc 	{
964433d6423SLionel Sambuc 		if (debug)
965433d6423SLionel Sambuc 			printf("\tIRQ %d for INT%c\n", ilr, 'A' + ipr-1);
966433d6423SLionel Sambuc 	}
967433d6423SLionel Sambuc 	else if (ilr != PCI_ILR_UNKNOWN)
968433d6423SLionel Sambuc 	{
969433d6423SLionel Sambuc 		printf(
970433d6423SLionel Sambuc 	"PCI: IRQ %d is assigned, but device %d.%d.%d does not need it\n",
971433d6423SLionel Sambuc 			ilr, pcidev[devind].pd_busnr, pcidev[devind].pd_dev,
972433d6423SLionel Sambuc 			pcidev[devind].pd_func);
973433d6423SLionel Sambuc 	}
974433d6423SLionel Sambuc 	else
975433d6423SLionel Sambuc 	{
976433d6423SLionel Sambuc 		/* Check for cardbus devices */
977433d6423SLionel Sambuc 		busnr= pcidev[devind].pd_busnr;
978433d6423SLionel Sambuc 		busind= get_busind(busnr);
979433d6423SLionel Sambuc 		if (pcibus[busind].pb_type == PBT_CARDBUS)
980433d6423SLionel Sambuc 		{
981433d6423SLionel Sambuc 			cb_devind= pcibus[busind].pb_devind;
982433d6423SLionel Sambuc 			ilr= pcidev[cb_devind].pd_ilr;
983433d6423SLionel Sambuc 			if (ilr != PCI_ILR_UNKNOWN)
984433d6423SLionel Sambuc 			{
985433d6423SLionel Sambuc 				if (debug)
986433d6423SLionel Sambuc 				{
987433d6423SLionel Sambuc 					printf(
988433d6423SLionel Sambuc 					"assigning IRQ %d to Cardbus device\n",
989433d6423SLionel Sambuc 						ilr);
990433d6423SLionel Sambuc 				}
9916e7bb628SLionel Sambuc 				__pci_attr_w8(devind, PCI_ILR, ilr);
992433d6423SLionel Sambuc 				pcidev[devind].pd_ilr= ilr;
993433d6423SLionel Sambuc 				return;
994433d6423SLionel Sambuc 			}
995433d6423SLionel Sambuc 		}
996433d6423SLionel Sambuc 		if(debug) {
997433d6423SLionel Sambuc 			printf(
998433d6423SLionel Sambuc 		"PCI: device %d.%d.%d uses INT%c but is not assigned any IRQ\n",
999433d6423SLionel Sambuc 			pcidev[devind].pd_busnr, pcidev[devind].pd_dev,
1000433d6423SLionel Sambuc 			pcidev[devind].pd_func, 'A' + ipr-1);
1001433d6423SLionel Sambuc 		}
1002433d6423SLionel Sambuc 	}
1003433d6423SLionel Sambuc }
1004433d6423SLionel Sambuc 
1005433d6423SLionel Sambuc /*===========================================================================*
10066e7bb628SLionel Sambuc  *				BAR helpers				     *
1007433d6423SLionel Sambuc  *===========================================================================*/
10086e7bb628SLionel Sambuc static int
record_bar(int devind,int bar_nr,int last)10096e7bb628SLionel Sambuc record_bar(int devind, int bar_nr, int last)
10106e7bb628SLionel Sambuc {
10116e7bb628SLionel Sambuc 	int reg, prefetch, type, dev_bar_nr, width;
10126e7bb628SLionel Sambuc 	u32_t bar, bar2;
10136e7bb628SLionel Sambuc 	u16_t cmd;
10146e7bb628SLionel Sambuc 
10156e7bb628SLionel Sambuc 	/* Start by assuming that this is a 32-bit bar, taking up one DWORD. */
10166e7bb628SLionel Sambuc 	width = 1;
10176e7bb628SLionel Sambuc 
10186e7bb628SLionel Sambuc 	reg= PCI_BAR+4*bar_nr;
10196e7bb628SLionel Sambuc 
10206e7bb628SLionel Sambuc 	bar= __pci_attr_r32(devind, reg);
10216e7bb628SLionel Sambuc 	if (bar & PCI_BAR_IO)
10226e7bb628SLionel Sambuc 	{
10236e7bb628SLionel Sambuc 		/* Disable I/O access before probing for BAR's size */
10246e7bb628SLionel Sambuc 		cmd = __pci_attr_r16(devind, PCI_CR);
10256e7bb628SLionel Sambuc 		__pci_attr_w16(devind, PCI_CR, cmd & ~PCI_CR_IO_EN);
10266e7bb628SLionel Sambuc 
10276e7bb628SLionel Sambuc 		/* Probe BAR's size */
10286e7bb628SLionel Sambuc 		__pci_attr_w32(devind, reg, 0xffffffff);
10296e7bb628SLionel Sambuc 		bar2= __pci_attr_r32(devind, reg);
10306e7bb628SLionel Sambuc 
10316e7bb628SLionel Sambuc 		/* Restore original state */
10326e7bb628SLionel Sambuc 		__pci_attr_w32(devind, reg, bar);
10336e7bb628SLionel Sambuc 		__pci_attr_w16(devind, PCI_CR, cmd);
10346e7bb628SLionel Sambuc 
10356e7bb628SLionel Sambuc 		bar &= PCI_BAR_IO_MASK;		/* Clear non-address bits */
10366e7bb628SLionel Sambuc 		bar2 &= PCI_BAR_IO_MASK;
10376e7bb628SLionel Sambuc 		bar2= (~bar2 & 0xffff)+1;
10386e7bb628SLionel Sambuc 		if (debug)
10396e7bb628SLionel Sambuc 		{
10406e7bb628SLionel Sambuc 			printf("\tbar_%d: %d bytes at 0x%x I/O\n",
10416e7bb628SLionel Sambuc 				bar_nr, bar2, bar);
10426e7bb628SLionel Sambuc 		}
10436e7bb628SLionel Sambuc 
10446e7bb628SLionel Sambuc 		dev_bar_nr= pcidev[devind].pd_bar_nr++;
10456e7bb628SLionel Sambuc 		pcidev[devind].pd_bar[dev_bar_nr].pb_flags= PBF_IO;
10466e7bb628SLionel Sambuc 		pcidev[devind].pd_bar[dev_bar_nr].pb_base= bar;
10476e7bb628SLionel Sambuc 		pcidev[devind].pd_bar[dev_bar_nr].pb_size= bar2;
10486e7bb628SLionel Sambuc 		pcidev[devind].pd_bar[dev_bar_nr].pb_nr= bar_nr;
10496e7bb628SLionel Sambuc 		if (bar == 0)
10506e7bb628SLionel Sambuc 		{
10516e7bb628SLionel Sambuc 			pcidev[devind].pd_bar[dev_bar_nr].pb_flags |=
10526e7bb628SLionel Sambuc 				PBF_INCOMPLETE;
10536e7bb628SLionel Sambuc 		}
10546e7bb628SLionel Sambuc 	}
10556e7bb628SLionel Sambuc 	else
10566e7bb628SLionel Sambuc 	{
10576e7bb628SLionel Sambuc 		type= (bar & PCI_BAR_TYPE);
10586e7bb628SLionel Sambuc 
10596e7bb628SLionel Sambuc 		switch(type) {
10606e7bb628SLionel Sambuc 		case PCI_TYPE_32:
10616e7bb628SLionel Sambuc 		case PCI_TYPE_32_1M:
10626e7bb628SLionel Sambuc 			break;
10636e7bb628SLionel Sambuc 
10646e7bb628SLionel Sambuc 		case PCI_TYPE_64:
10656e7bb628SLionel Sambuc 			/* A 64-bit BAR takes up two consecutive DWORDs. */
10666e7bb628SLionel Sambuc 			if (last)
10676e7bb628SLionel Sambuc 			{
10686e7bb628SLionel Sambuc 				printf("PCI: device %d.%d.%d BAR %d extends"
10696e7bb628SLionel Sambuc 					" beyond designated area\n",
10706e7bb628SLionel Sambuc 					pcidev[devind].pd_busnr,
10716e7bb628SLionel Sambuc 					pcidev[devind].pd_dev,
10726e7bb628SLionel Sambuc 					pcidev[devind].pd_func, bar_nr);
10736e7bb628SLionel Sambuc 
10746e7bb628SLionel Sambuc 				return width;
10756e7bb628SLionel Sambuc 			}
10766e7bb628SLionel Sambuc 			width++;
10776e7bb628SLionel Sambuc 
10786e7bb628SLionel Sambuc 			bar2= __pci_attr_r32(devind, reg+4);
10796e7bb628SLionel Sambuc 
10806e7bb628SLionel Sambuc 			/* If the upper 32 bits of the BAR are not zero, the
10816e7bb628SLionel Sambuc 			 * memory is inaccessible to us; ignore the BAR.
10826e7bb628SLionel Sambuc 			 */
10836e7bb628SLionel Sambuc 			if (bar2 != 0)
10846e7bb628SLionel Sambuc 			{
10856e7bb628SLionel Sambuc 				if (debug)
10866e7bb628SLionel Sambuc 				{
10876e7bb628SLionel Sambuc 					printf("\tbar_%d: (64-bit BAR with"
10886e7bb628SLionel Sambuc 						" high bits set)\n", bar_nr);
10896e7bb628SLionel Sambuc 				}
10906e7bb628SLionel Sambuc 
10916e7bb628SLionel Sambuc 				return width;
10926e7bb628SLionel Sambuc 			}
10936e7bb628SLionel Sambuc 
10946e7bb628SLionel Sambuc 			break;
10956e7bb628SLionel Sambuc 
10966e7bb628SLionel Sambuc 		default:
10976e7bb628SLionel Sambuc 			/* Ignore the BAR. */
10986e7bb628SLionel Sambuc 			if (debug)
10996e7bb628SLionel Sambuc 			{
11006e7bb628SLionel Sambuc 				printf("\tbar_%d: (unknown type %x)\n",
11016e7bb628SLionel Sambuc 					bar_nr, type);
11026e7bb628SLionel Sambuc 			}
11036e7bb628SLionel Sambuc 
11046e7bb628SLionel Sambuc 			return width;
11056e7bb628SLionel Sambuc 		}
11066e7bb628SLionel Sambuc 
11076e7bb628SLionel Sambuc 		/* Disable mem access before probing for BAR's size */
11086e7bb628SLionel Sambuc 		cmd = __pci_attr_r16(devind, PCI_CR);
11096e7bb628SLionel Sambuc 		__pci_attr_w16(devind, PCI_CR, cmd & ~PCI_CR_MEM_EN);
11106e7bb628SLionel Sambuc 
11116e7bb628SLionel Sambuc 		/* Probe BAR's size */
11126e7bb628SLionel Sambuc 		__pci_attr_w32(devind, reg, 0xffffffff);
11136e7bb628SLionel Sambuc 		bar2= __pci_attr_r32(devind, reg);
11146e7bb628SLionel Sambuc 
11156e7bb628SLionel Sambuc 		/* Restore original values */
11166e7bb628SLionel Sambuc 		__pci_attr_w32(devind, reg, bar);
11176e7bb628SLionel Sambuc 		__pci_attr_w16(devind, PCI_CR, cmd);
11186e7bb628SLionel Sambuc 
11196e7bb628SLionel Sambuc 		if (bar2 == 0)
11206e7bb628SLionel Sambuc 			return width;	/* Reg. is not implemented */
11216e7bb628SLionel Sambuc 
11226e7bb628SLionel Sambuc 		prefetch= !!(bar & PCI_BAR_PREFETCH);
11236e7bb628SLionel Sambuc 		bar &= PCI_BAR_MEM_MASK;	/* Clear non-address bits */
11246e7bb628SLionel Sambuc 		bar2 &= PCI_BAR_MEM_MASK;
11256e7bb628SLionel Sambuc 		bar2= (~bar2)+1;
11266e7bb628SLionel Sambuc 		if (debug)
11276e7bb628SLionel Sambuc 		{
11286e7bb628SLionel Sambuc 			printf("\tbar_%d: 0x%x bytes at 0x%x%s memory%s\n",
11296e7bb628SLionel Sambuc 				bar_nr, bar2, bar,
11306e7bb628SLionel Sambuc 				prefetch ? " prefetchable" : "",
11316e7bb628SLionel Sambuc 				type == PCI_TYPE_64 ? ", 64-bit" : "");
11326e7bb628SLionel Sambuc 		}
11336e7bb628SLionel Sambuc 
11346e7bb628SLionel Sambuc 		dev_bar_nr= pcidev[devind].pd_bar_nr++;
11356e7bb628SLionel Sambuc 		pcidev[devind].pd_bar[dev_bar_nr].pb_flags= 0;
11366e7bb628SLionel Sambuc 		pcidev[devind].pd_bar[dev_bar_nr].pb_base= bar;
11376e7bb628SLionel Sambuc 		pcidev[devind].pd_bar[dev_bar_nr].pb_size= bar2;
11386e7bb628SLionel Sambuc 		pcidev[devind].pd_bar[dev_bar_nr].pb_nr= bar_nr;
11396e7bb628SLionel Sambuc 		if (bar == 0)
11406e7bb628SLionel Sambuc 		{
11416e7bb628SLionel Sambuc 			pcidev[devind].pd_bar[dev_bar_nr].pb_flags |=
11426e7bb628SLionel Sambuc 				PBF_INCOMPLETE;
11436e7bb628SLionel Sambuc 		}
11446e7bb628SLionel Sambuc 	}
11456e7bb628SLionel Sambuc 
11466e7bb628SLionel Sambuc 	return width;
11476e7bb628SLionel Sambuc }
11486e7bb628SLionel Sambuc 
11496e7bb628SLionel Sambuc static void
record_bars(int devind,int last_reg)11506e7bb628SLionel Sambuc record_bars(int devind, int last_reg)
11516e7bb628SLionel Sambuc {
11526e7bb628SLionel Sambuc 	int i, reg, width;
11536e7bb628SLionel Sambuc 
11546e7bb628SLionel Sambuc 	for (i= 0, reg= PCI_BAR; reg <= last_reg; i += width, reg += 4 * width)
11556e7bb628SLionel Sambuc 	{
11566e7bb628SLionel Sambuc 		width = record_bar(devind, i, reg == last_reg);
11576e7bb628SLionel Sambuc 	}
11586e7bb628SLionel Sambuc }
11596e7bb628SLionel Sambuc 
11606e7bb628SLionel Sambuc static void
record_bars_normal(int devind)11616e7bb628SLionel Sambuc record_bars_normal(int devind)
1162433d6423SLionel Sambuc {
1163433d6423SLionel Sambuc 	int i, j, clear_01, clear_23, pb_nr;
1164433d6423SLionel Sambuc 
1165433d6423SLionel Sambuc 	/* The BAR area of normal devices is six DWORDs in size. */
1166433d6423SLionel Sambuc 	record_bars(devind, PCI_BAR_6);
1167433d6423SLionel Sambuc 
1168433d6423SLionel Sambuc 	/* Special case code for IDE controllers in compatibility mode */
1169433d6423SLionel Sambuc 	if (pcidev[devind].pd_baseclass == PCI_BCR_MASS_STORAGE &&
1170433d6423SLionel Sambuc 		pcidev[devind].pd_subclass == PCI_MS_IDE)
1171433d6423SLionel Sambuc 	{
1172433d6423SLionel Sambuc 		/* IDE device */
1173433d6423SLionel Sambuc 		clear_01= 0;
1174433d6423SLionel Sambuc 		clear_23= 0;
1175433d6423SLionel Sambuc 		if (!(pcidev[devind].pd_infclass & PCI_IDE_PRI_NATIVE))
1176433d6423SLionel Sambuc 		{
1177433d6423SLionel Sambuc 			if (debug)
1178433d6423SLionel Sambuc 			{
1179433d6423SLionel Sambuc 				printf(
1180433d6423SLionel Sambuc 	"primary channel is not in native mode, clearing BARs 0 and 1\n");
1181433d6423SLionel Sambuc 			}
1182433d6423SLionel Sambuc 			clear_01= 1;
1183433d6423SLionel Sambuc 		}
1184433d6423SLionel Sambuc 		if (!(pcidev[devind].pd_infclass & PCI_IDE_SEC_NATIVE))
1185433d6423SLionel Sambuc 		{
1186433d6423SLionel Sambuc 			if (debug)
1187433d6423SLionel Sambuc 			{
1188433d6423SLionel Sambuc 				printf(
1189433d6423SLionel Sambuc 	"secondary channel is not in native mode, clearing BARs 2 and 3\n");
1190433d6423SLionel Sambuc 			}
1191433d6423SLionel Sambuc 			clear_23= 1;
1192433d6423SLionel Sambuc 		}
1193433d6423SLionel Sambuc 
1194433d6423SLionel Sambuc 		j= 0;
1195433d6423SLionel Sambuc 		for (i= 0; i<pcidev[devind].pd_bar_nr; i++)
1196433d6423SLionel Sambuc 		{
1197433d6423SLionel Sambuc 			pb_nr= pcidev[devind].pd_bar[i].pb_nr;
1198433d6423SLionel Sambuc 			if ((pb_nr == 0 || pb_nr == 1) && clear_01)
1199433d6423SLionel Sambuc 			{
1200433d6423SLionel Sambuc 				if (debug) printf("skipping bar %d\n", pb_nr);
1201433d6423SLionel Sambuc 				continue;	/* Skip */
1202433d6423SLionel Sambuc 			}
1203433d6423SLionel Sambuc 			if ((pb_nr == 2 || pb_nr == 3) && clear_23)
1204433d6423SLionel Sambuc 			{
1205433d6423SLionel Sambuc 				if (debug) printf("skipping bar %d\n", pb_nr);
1206433d6423SLionel Sambuc 				continue;	/* Skip */
1207433d6423SLionel Sambuc 			}
1208433d6423SLionel Sambuc 			if (i == j)
1209433d6423SLionel Sambuc 			{
1210433d6423SLionel Sambuc 				j++;
1211433d6423SLionel Sambuc 				continue;	/* No need to copy */
1212433d6423SLionel Sambuc 			}
1213433d6423SLionel Sambuc 			pcidev[devind].pd_bar[j]=
1214433d6423SLionel Sambuc 				pcidev[devind].pd_bar[i];
1215433d6423SLionel Sambuc 			j++;
1216433d6423SLionel Sambuc 		}
1217433d6423SLionel Sambuc 		pcidev[devind].pd_bar_nr= j;
1218433d6423SLionel Sambuc 	}
1219433d6423SLionel Sambuc }
1220433d6423SLionel Sambuc 
12216e7bb628SLionel Sambuc static void
record_bars_bridge(int devind)12226e7bb628SLionel Sambuc record_bars_bridge(int devind)
1223433d6423SLionel Sambuc {
1224433d6423SLionel Sambuc 	u32_t base, limit, size;
1225433d6423SLionel Sambuc 
1226433d6423SLionel Sambuc 	/* The generic BAR area of PCI-to-PCI bridges is two DWORDs in size.
1227433d6423SLionel Sambuc 	 * It may contain up to two 32-bit BARs, or one 64-bit BAR.
1228433d6423SLionel Sambuc 	 */
1229433d6423SLionel Sambuc 	record_bars(devind, PCI_BAR_2);
1230433d6423SLionel Sambuc 
12316e7bb628SLionel Sambuc 	base= ((__pci_attr_r8(devind, PPB_IOBASE) & PPB_IOB_MASK) << 8) |
12326e7bb628SLionel Sambuc 		(__pci_attr_r16(devind, PPB_IOBASEU16) << 16);
1233433d6423SLionel Sambuc 	limit= 0xff |
12346e7bb628SLionel Sambuc 		((__pci_attr_r8(devind, PPB_IOLIMIT) & PPB_IOL_MASK) << 8) |
1235433d6423SLionel Sambuc 		((~PPB_IOL_MASK & 0xff) << 8) |
12366e7bb628SLionel Sambuc 		(__pci_attr_r16(devind, PPB_IOLIMITU16) << 16);
1237433d6423SLionel Sambuc 	size= limit-base + 1;
1238433d6423SLionel Sambuc 	if (debug)
1239433d6423SLionel Sambuc 	{
1240433d6423SLionel Sambuc 		printf("\tI/O window: base 0x%x, limit 0x%x, size %d\n",
1241433d6423SLionel Sambuc 			base, limit, size);
1242433d6423SLionel Sambuc 	}
1243433d6423SLionel Sambuc 
12446e7bb628SLionel Sambuc 	base= ((__pci_attr_r16(devind, PPB_MEMBASE) & PPB_MEMB_MASK) << 16);
1245433d6423SLionel Sambuc 	limit= 0xffff |
12466e7bb628SLionel Sambuc 		((__pci_attr_r16(devind, PPB_MEMLIMIT) & PPB_MEML_MASK) << 16) |
1247433d6423SLionel Sambuc 		((~PPB_MEML_MASK & 0xffff) << 16);
1248433d6423SLionel Sambuc 	size= limit-base + 1;
1249433d6423SLionel Sambuc 	if (debug)
1250433d6423SLionel Sambuc 	{
1251433d6423SLionel Sambuc 		printf("\tMemory window: base 0x%x, limit 0x%x, size 0x%x\n",
1252433d6423SLionel Sambuc 			base, limit, size);
1253433d6423SLionel Sambuc 	}
1254433d6423SLionel Sambuc 
1255433d6423SLionel Sambuc 	/* Ignore the upper 32 bits */
12566e7bb628SLionel Sambuc 	base= ((__pci_attr_r16(devind, PPB_PFMEMBASE) & PPB_PFMEMB_MASK) << 16);
1257433d6423SLionel Sambuc 	limit= 0xffff |
12586e7bb628SLionel Sambuc 		((__pci_attr_r16(devind, PPB_PFMEMLIMIT) &
1259433d6423SLionel Sambuc 			PPB_PFMEML_MASK) << 16) |
1260433d6423SLionel Sambuc 		((~PPB_PFMEML_MASK & 0xffff) << 16);
1261433d6423SLionel Sambuc 	size= limit-base + 1;
1262433d6423SLionel Sambuc 	if (debug)
1263433d6423SLionel Sambuc 	{
1264433d6423SLionel Sambuc 		printf(
1265433d6423SLionel Sambuc 	"\tPrefetchable memory window: base 0x%x, limit 0x%x, size 0x%x\n",
1266433d6423SLionel Sambuc 			base, limit, size);
1267433d6423SLionel Sambuc 	}
1268433d6423SLionel Sambuc }
1269433d6423SLionel Sambuc 
12706e7bb628SLionel Sambuc static void
record_bars_cardbus(int devind)12716e7bb628SLionel Sambuc record_bars_cardbus(int devind)
1272433d6423SLionel Sambuc {
1273433d6423SLionel Sambuc 	u32_t base, limit, size;
1274433d6423SLionel Sambuc 
1275433d6423SLionel Sambuc 	/* The generic BAR area of CardBus devices is one DWORD in size. */
1276433d6423SLionel Sambuc 	record_bars(devind, PCI_BAR);
1277433d6423SLionel Sambuc 
12786e7bb628SLionel Sambuc 	base= __pci_attr_r32(devind, CBB_MEMBASE_0);
12796e7bb628SLionel Sambuc 	limit= __pci_attr_r32(devind, CBB_MEMLIMIT_0) |
1280433d6423SLionel Sambuc 		(~CBB_MEML_MASK & 0xffffffff);
1281433d6423SLionel Sambuc 	size= limit-base + 1;
1282433d6423SLionel Sambuc 	if (debug)
1283433d6423SLionel Sambuc 	{
1284433d6423SLionel Sambuc 		printf("\tMemory window 0: base 0x%x, limit 0x%x, size %d\n",
1285433d6423SLionel Sambuc 			base, limit, size);
1286433d6423SLionel Sambuc 	}
1287433d6423SLionel Sambuc 
12886e7bb628SLionel Sambuc 	base= __pci_attr_r32(devind, CBB_MEMBASE_1);
12896e7bb628SLionel Sambuc 	limit= __pci_attr_r32(devind, CBB_MEMLIMIT_1) |
1290433d6423SLionel Sambuc 		(~CBB_MEML_MASK & 0xffffffff);
1291433d6423SLionel Sambuc 	size= limit-base + 1;
1292433d6423SLionel Sambuc 	if (debug)
1293433d6423SLionel Sambuc 	{
1294433d6423SLionel Sambuc 		printf("\tMemory window 1: base 0x%x, limit 0x%x, size %d\n",
1295433d6423SLionel Sambuc 			base, limit, size);
1296433d6423SLionel Sambuc 	}
1297433d6423SLionel Sambuc 
12986e7bb628SLionel Sambuc 	base= __pci_attr_r32(devind, CBB_IOBASE_0);
12996e7bb628SLionel Sambuc 	limit= __pci_attr_r32(devind, CBB_IOLIMIT_0) |
1300433d6423SLionel Sambuc 		(~CBB_IOL_MASK & 0xffffffff);
1301433d6423SLionel Sambuc 	size= limit-base + 1;
1302433d6423SLionel Sambuc 	if (debug)
1303433d6423SLionel Sambuc 	{
1304433d6423SLionel Sambuc 		printf("\tI/O window 0: base 0x%x, limit 0x%x, size %d\n",
1305433d6423SLionel Sambuc 			base, limit, size);
1306433d6423SLionel Sambuc 	}
1307433d6423SLionel Sambuc 
13086e7bb628SLionel Sambuc 	base= __pci_attr_r32(devind, CBB_IOBASE_1);
13096e7bb628SLionel Sambuc 	limit= __pci_attr_r32(devind, CBB_IOLIMIT_1) |
1310433d6423SLionel Sambuc 		(~CBB_IOL_MASK & 0xffffffff);
1311433d6423SLionel Sambuc 	size= limit-base + 1;
1312433d6423SLionel Sambuc 	if (debug)
1313433d6423SLionel Sambuc 	{
1314433d6423SLionel Sambuc 		printf("\tI/O window 1: base 0x%x, limit 0x%x, size %d\n",
1315433d6423SLionel Sambuc 			base, limit, size);
1316433d6423SLionel Sambuc 	}
1317433d6423SLionel Sambuc }
1318433d6423SLionel Sambuc 
13196e7bb628SLionel Sambuc static void
complete_bars(void)13206e7bb628SLionel Sambuc complete_bars(void)
1321433d6423SLionel Sambuc {
1322433d6423SLionel Sambuc 	int i, j, bar_nr, reg;
1323433d6423SLionel Sambuc 	u32_t memgap_low, memgap_high, iogap_low, iogap_high, io_high,
1324433d6423SLionel Sambuc 		base, size, v32, diff1, diff2;
1325433d6423SLionel Sambuc 	kinfo_t kinfo;
1326433d6423SLionel Sambuc 
1327433d6423SLionel Sambuc 	if(OK != sys_getkinfo(&kinfo))
1328433d6423SLionel Sambuc 		panic("can't get kinfo");
1329433d6423SLionel Sambuc 
1330433d6423SLionel Sambuc 	/* Set memgap_low to just above physical memory */
1331433d6423SLionel Sambuc 	memgap_low= kinfo.mem_high_phys;
1332433d6423SLionel Sambuc 	memgap_high= 0xfe000000;	/* Leave space for the CPU (APIC) */
1333433d6423SLionel Sambuc 
1334433d6423SLionel Sambuc 	if (debug)
1335433d6423SLionel Sambuc 	{
1336433d6423SLionel Sambuc 		printf("complete_bars: initial gap: [0x%x .. 0x%x>\n",
1337433d6423SLionel Sambuc 			memgap_low, memgap_high);
1338433d6423SLionel Sambuc 	}
1339433d6423SLionel Sambuc 
1340433d6423SLionel Sambuc 	/* Find the lowest memory base */
1341433d6423SLionel Sambuc 	for (i= 0; i<nr_pcidev; i++)
1342433d6423SLionel Sambuc 	{
1343433d6423SLionel Sambuc 		for (j= 0; j<pcidev[i].pd_bar_nr; j++)
1344433d6423SLionel Sambuc 		{
1345433d6423SLionel Sambuc 			if (pcidev[i].pd_bar[j].pb_flags & PBF_IO)
1346433d6423SLionel Sambuc 				continue;
1347433d6423SLionel Sambuc 			if (pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE)
1348433d6423SLionel Sambuc 				continue;
1349433d6423SLionel Sambuc 			base= pcidev[i].pd_bar[j].pb_base;
1350433d6423SLionel Sambuc 			size= pcidev[i].pd_bar[j].pb_size;
1351433d6423SLionel Sambuc 
1352433d6423SLionel Sambuc 			if (base >= memgap_high)
1353433d6423SLionel Sambuc 				continue;	/* Not in the gap */
1354433d6423SLionel Sambuc 			if (base+size <= memgap_low)
1355433d6423SLionel Sambuc 				continue;	/* Not in the gap */
1356433d6423SLionel Sambuc 
1357433d6423SLionel Sambuc 			/* Reduce the gap by the smallest amount */
1358433d6423SLionel Sambuc 			diff1= base+size-memgap_low;
1359433d6423SLionel Sambuc 			diff2= memgap_high-base;
1360433d6423SLionel Sambuc 
1361433d6423SLionel Sambuc 			if (diff1 < diff2)
1362433d6423SLionel Sambuc 				memgap_low= base+size;
1363433d6423SLionel Sambuc 			else
1364433d6423SLionel Sambuc 				memgap_high= base;
1365433d6423SLionel Sambuc 		}
1366433d6423SLionel Sambuc 	}
1367433d6423SLionel Sambuc 
1368433d6423SLionel Sambuc 	if (debug)
1369433d6423SLionel Sambuc 	{
1370433d6423SLionel Sambuc 		printf("complete_bars: intermediate gap: [0x%x .. 0x%x>\n",
1371433d6423SLionel Sambuc 			memgap_low, memgap_high);
1372433d6423SLionel Sambuc 	}
1373433d6423SLionel Sambuc 
1374433d6423SLionel Sambuc 	/* Should check main memory size */
1375433d6423SLionel Sambuc 	if (memgap_high < memgap_low)
1376433d6423SLionel Sambuc 	{
1377433d6423SLionel Sambuc 		printf("PCI: bad memory gap: [0x%x .. 0x%x>\n",
1378433d6423SLionel Sambuc 			memgap_low, memgap_high);
1379433d6423SLionel Sambuc 		panic(NULL);
1380433d6423SLionel Sambuc 	}
1381433d6423SLionel Sambuc 
1382433d6423SLionel Sambuc 	iogap_high= 0x10000;
1383433d6423SLionel Sambuc 	iogap_low= 0x400;
1384433d6423SLionel Sambuc 
1385433d6423SLionel Sambuc 	/* Find the free I/O space */
1386433d6423SLionel Sambuc 	for (i= 0; i<nr_pcidev; i++)
1387433d6423SLionel Sambuc 	{
1388433d6423SLionel Sambuc 		for (j= 0; j<pcidev[i].pd_bar_nr; j++)
1389433d6423SLionel Sambuc 		{
1390433d6423SLionel Sambuc 			if (!(pcidev[i].pd_bar[j].pb_flags & PBF_IO))
1391433d6423SLionel Sambuc 				continue;
1392433d6423SLionel Sambuc 			if (pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE)
1393433d6423SLionel Sambuc 				continue;
1394433d6423SLionel Sambuc 			base= pcidev[i].pd_bar[j].pb_base;
1395433d6423SLionel Sambuc 			size= pcidev[i].pd_bar[j].pb_size;
1396433d6423SLionel Sambuc 			if (base >= iogap_high)
1397433d6423SLionel Sambuc 				continue;
1398433d6423SLionel Sambuc 			if (base+size <= iogap_low)
1399433d6423SLionel Sambuc 				continue;
1400433d6423SLionel Sambuc #if 0
1401433d6423SLionel Sambuc 			if (debug)
1402433d6423SLionel Sambuc 			{
1403433d6423SLionel Sambuc 				printf(
1404433d6423SLionel Sambuc 		"pci device %d (%04x:%04x), bar %d: base 0x%x, size 0x%x\n",
1405433d6423SLionel Sambuc 					i, pcidev[i].pd_vid, pcidev[i].pd_did,
1406433d6423SLionel Sambuc 					j, base, size);
1407433d6423SLionel Sambuc 			}
1408433d6423SLionel Sambuc #endif
1409433d6423SLionel Sambuc 			if (base+size-iogap_low < iogap_high-base)
1410433d6423SLionel Sambuc 				iogap_low= base+size;
1411433d6423SLionel Sambuc 			else
1412433d6423SLionel Sambuc 				iogap_high= base;
1413433d6423SLionel Sambuc 		}
1414433d6423SLionel Sambuc 	}
1415433d6423SLionel Sambuc 
1416433d6423SLionel Sambuc 	if (iogap_high < iogap_low)
1417433d6423SLionel Sambuc 	{
1418433d6423SLionel Sambuc 		if (debug)
1419433d6423SLionel Sambuc 		{
1420433d6423SLionel Sambuc 			printf("iogap_high too low, should panic\n");
1421433d6423SLionel Sambuc 		}
1422433d6423SLionel Sambuc 		else
1423433d6423SLionel Sambuc 			panic("iogap_high too low: %d", iogap_high);
1424433d6423SLionel Sambuc 	}
1425433d6423SLionel Sambuc 	if (debug)
1426433d6423SLionel Sambuc 		printf("I/O range = [0x%x..0x%x>\n", iogap_low, iogap_high);
1427433d6423SLionel Sambuc 
1428433d6423SLionel Sambuc 	for (i= 0; i<nr_pcidev; i++)
1429433d6423SLionel Sambuc 	{
1430433d6423SLionel Sambuc 		for (j= 0; j<pcidev[i].pd_bar_nr; j++)
1431433d6423SLionel Sambuc 		{
1432433d6423SLionel Sambuc 			if (pcidev[i].pd_bar[j].pb_flags & PBF_IO)
1433433d6423SLionel Sambuc 				continue;
1434433d6423SLionel Sambuc 			if (!(pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE))
1435433d6423SLionel Sambuc 				continue;
1436433d6423SLionel Sambuc 			size= pcidev[i].pd_bar[j].pb_size;
1437433d6423SLionel Sambuc 			if (size < PAGE_SIZE)
1438433d6423SLionel Sambuc 				size= PAGE_SIZE;
1439433d6423SLionel Sambuc 			base= memgap_high-size;
1440433d6423SLionel Sambuc 			base &= ~(u32_t)(size-1);
1441433d6423SLionel Sambuc 			if (base < memgap_low)
1442433d6423SLionel Sambuc 				panic("memory base too low: %d", base);
1443433d6423SLionel Sambuc 			memgap_high= base;
1444433d6423SLionel Sambuc 			bar_nr= pcidev[i].pd_bar[j].pb_nr;
1445433d6423SLionel Sambuc 			reg= PCI_BAR + 4*bar_nr;
14466e7bb628SLionel Sambuc 			v32= __pci_attr_r32(i, reg);
14476e7bb628SLionel Sambuc 			__pci_attr_w32(i, reg, v32 | base);
1448433d6423SLionel Sambuc 			if (debug)
1449433d6423SLionel Sambuc 			{
1450433d6423SLionel Sambuc 				printf(
1451433d6423SLionel Sambuc 		"complete_bars: allocated 0x%x size %d to %d.%d.%d, bar_%d\n",
1452433d6423SLionel Sambuc 					base, size, pcidev[i].pd_busnr,
1453433d6423SLionel Sambuc 					pcidev[i].pd_dev, pcidev[i].pd_func,
1454433d6423SLionel Sambuc 					bar_nr);
1455433d6423SLionel Sambuc 			}
1456433d6423SLionel Sambuc 			pcidev[i].pd_bar[j].pb_base= base;
1457433d6423SLionel Sambuc 			pcidev[i].pd_bar[j].pb_flags &= ~PBF_INCOMPLETE;
1458433d6423SLionel Sambuc 		}
1459433d6423SLionel Sambuc 
1460433d6423SLionel Sambuc 		io_high= iogap_high;
1461433d6423SLionel Sambuc 		for (j= 0; j<pcidev[i].pd_bar_nr; j++)
1462433d6423SLionel Sambuc 		{
1463433d6423SLionel Sambuc 			if (!(pcidev[i].pd_bar[j].pb_flags & PBF_IO))
1464433d6423SLionel Sambuc 				continue;
1465433d6423SLionel Sambuc 			if (!(pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE))
1466433d6423SLionel Sambuc 				continue;
1467433d6423SLionel Sambuc 			size= pcidev[i].pd_bar[j].pb_size;
1468433d6423SLionel Sambuc 			base= iogap_high-size;
1469433d6423SLionel Sambuc 			base &= ~(u32_t)(size-1);
1470433d6423SLionel Sambuc 
1471433d6423SLionel Sambuc 			/* Assume that ISA compatibility is required. Only
1472433d6423SLionel Sambuc 			 * use the lowest 256 bytes out of every 1024 bytes.
1473433d6423SLionel Sambuc 			 */
1474433d6423SLionel Sambuc 			base &= 0xfcff;
1475433d6423SLionel Sambuc 
1476433d6423SLionel Sambuc 			if (base < iogap_low)
14777171c232Srlfnb 				printf("I/O base too low: %d", base);
1478433d6423SLionel Sambuc 
1479433d6423SLionel Sambuc 			iogap_high= base;
1480433d6423SLionel Sambuc 			bar_nr= pcidev[i].pd_bar[j].pb_nr;
1481433d6423SLionel Sambuc 			reg= PCI_BAR + 4*bar_nr;
14826e7bb628SLionel Sambuc 			v32= __pci_attr_r32(i, reg);
14836e7bb628SLionel Sambuc 			__pci_attr_w32(i, reg, v32 | base);
1484433d6423SLionel Sambuc 			if (debug)
1485433d6423SLionel Sambuc 			{
1486433d6423SLionel Sambuc 				printf(
1487433d6423SLionel Sambuc 		"complete_bars: allocated 0x%x size %d to %d.%d.%d, bar_%d\n",
1488433d6423SLionel Sambuc 					base, size, pcidev[i].pd_busnr,
1489433d6423SLionel Sambuc 					pcidev[i].pd_dev, pcidev[i].pd_func,
1490433d6423SLionel Sambuc 					bar_nr);
1491433d6423SLionel Sambuc 			}
1492433d6423SLionel Sambuc 			pcidev[i].pd_bar[j].pb_base= base;
1493433d6423SLionel Sambuc 			pcidev[i].pd_bar[j].pb_flags &= ~PBF_INCOMPLETE;
1494433d6423SLionel Sambuc 
1495433d6423SLionel Sambuc 		}
1496433d6423SLionel Sambuc 		if (iogap_high != io_high)
1497433d6423SLionel Sambuc 		{
1498433d6423SLionel Sambuc 			update_bridge4dev_io(i, iogap_high,
1499433d6423SLionel Sambuc 				io_high-iogap_high);
1500433d6423SLionel Sambuc 		}
1501433d6423SLionel Sambuc 	}
1502433d6423SLionel Sambuc 
1503433d6423SLionel Sambuc 	for (i= 0; i<nr_pcidev; i++)
1504433d6423SLionel Sambuc 	{
1505433d6423SLionel Sambuc 		for (j= 0; j<pcidev[i].pd_bar_nr; j++)
1506433d6423SLionel Sambuc 		{
1507433d6423SLionel Sambuc 			if (!(pcidev[i].pd_bar[j].pb_flags & PBF_INCOMPLETE))
1508433d6423SLionel Sambuc 				continue;
1509433d6423SLionel Sambuc 			printf("should allocate resources for device %d\n", i);
1510433d6423SLionel Sambuc 		}
1511433d6423SLionel Sambuc 	}
1512433d6423SLionel Sambuc 	return;
1513433d6423SLionel Sambuc }
1514433d6423SLionel Sambuc 
1515433d6423SLionel Sambuc /*===========================================================================*
15166e7bb628SLionel Sambuc  *				PCI Bridge Helpers			     *
1517433d6423SLionel Sambuc  *===========================================================================*/
15186e7bb628SLionel Sambuc static void
probe_bus(int busind)15196e7bb628SLionel Sambuc probe_bus(int busind)
1520433d6423SLionel Sambuc {
15210a6a1f1dSLionel Sambuc 	uint32_t dev, func;
15220a6a1f1dSLionel Sambuc #if 0
15230a6a1f1dSLionel Sambuc 	uint32_t t3;
15240a6a1f1dSLionel Sambuc #endif
15256e7bb628SLionel Sambuc 	u16_t vid, did, sts, sub_vid, sub_did;
15266e7bb628SLionel Sambuc 	u8_t headt;
15276e7bb628SLionel Sambuc 	u8_t baseclass, subclass, infclass;
15286e7bb628SLionel Sambuc 	int devind, busnr;
15296e7bb628SLionel Sambuc 	const char *s, *dstr;
1530433d6423SLionel Sambuc 
15316e7bb628SLionel Sambuc 	if (debug)
15326e7bb628SLionel Sambuc 		printf("probe_bus(%d)\n", busind);
15336e7bb628SLionel Sambuc 	if (nr_pcidev >= NR_PCIDEV)
15346e7bb628SLionel Sambuc 		panic("too many PCI devices: %d", nr_pcidev);
15356e7bb628SLionel Sambuc 	devind= nr_pcidev;
15366e7bb628SLionel Sambuc 
15376e7bb628SLionel Sambuc 	busnr= pcibus[busind].pb_busnr;
15386e7bb628SLionel Sambuc 	for (dev= 0; dev<32; dev++)
15396e7bb628SLionel Sambuc 	{
15406e7bb628SLionel Sambuc 
15416e7bb628SLionel Sambuc 		for (func= 0; func < 8; func++)
15426e7bb628SLionel Sambuc 		{
15436e7bb628SLionel Sambuc 			pcidev[devind].pd_busnr= busnr;
15446e7bb628SLionel Sambuc 			pcidev[devind].pd_dev= dev;
15456e7bb628SLionel Sambuc 			pcidev[devind].pd_func= func;
15466e7bb628SLionel Sambuc 
15476e7bb628SLionel Sambuc 			pci_attr_wsts(devind,
15486e7bb628SLionel Sambuc 				PSR_SSE|PSR_RMAS|PSR_RTAS);
15496e7bb628SLionel Sambuc 			vid= __pci_attr_r16(devind, PCI_VID);
15506e7bb628SLionel Sambuc 			did= __pci_attr_r16(devind, PCI_DID);
15516e7bb628SLionel Sambuc 			headt= __pci_attr_r8(devind, PCI_HEADT);
15526e7bb628SLionel Sambuc 			sts= pci_attr_rsts(devind);
15536e7bb628SLionel Sambuc 
15546e7bb628SLionel Sambuc #if 0
15556e7bb628SLionel Sambuc 			printf("vid 0x%x, did 0x%x, headt 0x%x, sts 0x%x\n",
15566e7bb628SLionel Sambuc 				vid, did, headt, sts);
15576e7bb628SLionel Sambuc #endif
15586e7bb628SLionel Sambuc 
15596e7bb628SLionel Sambuc 			if (vid == NO_VID && did == NO_VID)
15606e7bb628SLionel Sambuc 			{
15616e7bb628SLionel Sambuc 				if (func == 0)
15626e7bb628SLionel Sambuc 					break;	/* Nothing here */
15636e7bb628SLionel Sambuc 
15646e7bb628SLionel Sambuc 				/* Scan all functions of a multifunction
15656e7bb628SLionel Sambuc 				 * device.
15666e7bb628SLionel Sambuc 				 */
15676e7bb628SLionel Sambuc 				continue;
15686e7bb628SLionel Sambuc 			}
15696e7bb628SLionel Sambuc 
15706e7bb628SLionel Sambuc 			if (sts & (PSR_SSE|PSR_RMAS|PSR_RTAS))
15716e7bb628SLionel Sambuc 			{
15726e7bb628SLionel Sambuc 				static int warned = 0;
15736e7bb628SLionel Sambuc 
15746e7bb628SLionel Sambuc 				if(!warned) {
15756e7bb628SLionel Sambuc 					printf(
15766e7bb628SLionel Sambuc 	"PCI: ignoring bad value 0x%x in sts for QEMU\n",
15776e7bb628SLionel Sambuc 	sts & (PSR_SSE|PSR_RMAS|PSR_RTAS));
15786e7bb628SLionel Sambuc 					warned = 1;
15796e7bb628SLionel Sambuc 				}
15806e7bb628SLionel Sambuc 			}
15816e7bb628SLionel Sambuc 
15826e7bb628SLionel Sambuc 			sub_vid= __pci_attr_r16(devind, PCI_SUBVID);
15836e7bb628SLionel Sambuc 			sub_did= __pci_attr_r16(devind, PCI_SUBDID);
15846e7bb628SLionel Sambuc 
15856e7bb628SLionel Sambuc 			dstr= _pci_dev_name(vid, did);
15866e7bb628SLionel Sambuc 			if (debug)
15876e7bb628SLionel Sambuc 			{
15886e7bb628SLionel Sambuc 				if (dstr)
15896e7bb628SLionel Sambuc 				{
15906e7bb628SLionel Sambuc 					printf("%d.%lu.%lu: %s (%04X:%04X)\n",
15916e7bb628SLionel Sambuc 						busnr, (unsigned long)dev,
15926e7bb628SLionel Sambuc 						(unsigned long)func, dstr,
15936e7bb628SLionel Sambuc 						vid, did);
15946e7bb628SLionel Sambuc 				}
15956e7bb628SLionel Sambuc 				else
1596433d6423SLionel Sambuc 				{
1597433d6423SLionel Sambuc 					printf(
15986e7bb628SLionel Sambuc 		"%d.%lu.%lu: Unknown device, vendor %04X (%s), device %04X\n",
15996e7bb628SLionel Sambuc 						busnr, (unsigned long)dev,
16006e7bb628SLionel Sambuc 						(unsigned long)func, vid,
16016e7bb628SLionel Sambuc 						pci_vid_name(vid), did);
1602433d6423SLionel Sambuc 				}
16036e7bb628SLionel Sambuc 				printf("Device index: %d\n", devind);
16046e7bb628SLionel Sambuc 				printf("Subsystem: Vid 0x%x, did 0x%x\n",
16056e7bb628SLionel Sambuc 					sub_vid, sub_did);
16066e7bb628SLionel Sambuc 			}
1607433d6423SLionel Sambuc 
16086e7bb628SLionel Sambuc 			baseclass= __pci_attr_r8(devind, PCI_BCR);
16096e7bb628SLionel Sambuc 			subclass= __pci_attr_r8(devind, PCI_SCR);
16106e7bb628SLionel Sambuc 			infclass= __pci_attr_r8(devind, PCI_PIFR);
16113641562fSLionel Sambuc 			s=  pci_subclass_name(baseclass << 24 | subclass << 16);
16126e7bb628SLionel Sambuc 			if (!s)
16133641562fSLionel Sambuc 				s= pci_baseclass_name(baseclass << 24);
16146e7bb628SLionel Sambuc 			{
16156e7bb628SLionel Sambuc 				if (!s)
16166e7bb628SLionel Sambuc 					s= "(unknown class)";
16176e7bb628SLionel Sambuc 			}
1618433d6423SLionel Sambuc 			if (debug)
1619433d6423SLionel Sambuc 			{
16206e7bb628SLionel Sambuc 				printf("\tclass %s (%X/%X/%X)\n", s,
16216e7bb628SLionel Sambuc 					baseclass, subclass, infclass);
1622433d6423SLionel Sambuc 			}
1623433d6423SLionel Sambuc 
16246e7bb628SLionel Sambuc 			if (is_duplicate(busnr, dev, func))
1625433d6423SLionel Sambuc 			{
16266e7bb628SLionel Sambuc 				printf("\tduplicate!\n");
16276e7bb628SLionel Sambuc 				if (func == 0 && !(headt & PHT_MULTIFUNC))
1628433d6423SLionel Sambuc 					break;
16296e7bb628SLionel Sambuc 				continue;
1630433d6423SLionel Sambuc 			}
1631433d6423SLionel Sambuc 
16326e7bb628SLionel Sambuc 			devind= nr_pcidev;
16336e7bb628SLionel Sambuc 			nr_pcidev++;
16346e7bb628SLionel Sambuc 			pcidev[devind].pd_baseclass= baseclass;
16356e7bb628SLionel Sambuc 			pcidev[devind].pd_subclass= subclass;
16366e7bb628SLionel Sambuc 			pcidev[devind].pd_infclass= infclass;
16376e7bb628SLionel Sambuc 			pcidev[devind].pd_vid= vid;
16386e7bb628SLionel Sambuc 			pcidev[devind].pd_did= did;
16396e7bb628SLionel Sambuc 			pcidev[devind].pd_sub_vid= sub_vid;
16406e7bb628SLionel Sambuc 			pcidev[devind].pd_sub_did= sub_did;
16416e7bb628SLionel Sambuc 			pcidev[devind].pd_inuse= 0;
16426e7bb628SLionel Sambuc 			pcidev[devind].pd_bar_nr= 0;
16436e7bb628SLionel Sambuc 			record_irq(devind);
16446e7bb628SLionel Sambuc 			switch(headt & PHT_MASK)
1645433d6423SLionel Sambuc 			{
16466e7bb628SLionel Sambuc 			case PHT_NORMAL:
16476e7bb628SLionel Sambuc 				record_bars_normal(devind);
1648433d6423SLionel Sambuc 				break;
16496e7bb628SLionel Sambuc 			case PHT_BRIDGE:
16506e7bb628SLionel Sambuc 				record_bars_bridge(devind);
1651433d6423SLionel Sambuc 				break;
16526e7bb628SLionel Sambuc 			case PHT_CARDBUS:
16536e7bb628SLionel Sambuc 				record_bars_cardbus(devind);
1654433d6423SLionel Sambuc 				break;
1655433d6423SLionel Sambuc 			default:
16566e7bb628SLionel Sambuc 				printf("\t%d.%d.%d: unknown header type %d\n",
16576e7bb628SLionel Sambuc 					busind, dev, func,
16586e7bb628SLionel Sambuc 					headt & PHT_MASK);
16596e7bb628SLionel Sambuc 				break;
1660433d6423SLionel Sambuc 			}
16616e7bb628SLionel Sambuc 			if (debug)
16626e7bb628SLionel Sambuc 				print_capabilities(devind);
16636e7bb628SLionel Sambuc 
16646e7bb628SLionel Sambuc #if 0
16650a6a1f1dSLionel Sambuc 			t3= ((baseclass << 16) | (subclass << 8) | infclass);
16666e7bb628SLionel Sambuc 			if (t3 == PCI_T3_VGA || t3 == PCI_T3_VGA_OLD)
16676e7bb628SLionel Sambuc 				report_vga(devind);
16686e7bb628SLionel Sambuc #endif
16696e7bb628SLionel Sambuc 
16706e7bb628SLionel Sambuc 			if (nr_pcidev >= NR_PCIDEV)
16716e7bb628SLionel Sambuc 				panic("too many PCI devices: %d", nr_pcidev);
16726e7bb628SLionel Sambuc 			devind= nr_pcidev;
16736e7bb628SLionel Sambuc 
16746e7bb628SLionel Sambuc 			if (func == 0 && !(headt & PHT_MULTIFUNC))
16756e7bb628SLionel Sambuc 				break;
16766e7bb628SLionel Sambuc 		}
16776e7bb628SLionel Sambuc 	}
1678433d6423SLionel Sambuc }
1679433d6423SLionel Sambuc 
16806e7bb628SLionel Sambuc 
16816e7bb628SLionel Sambuc static u16_t
pcibr_std_rsts(int busind)16826e7bb628SLionel Sambuc pcibr_std_rsts(int busind)
1683433d6423SLionel Sambuc {
16846e7bb628SLionel Sambuc 	int devind;
16856e7bb628SLionel Sambuc 
16866e7bb628SLionel Sambuc 	devind= pcibus[busind].pb_devind;
16876e7bb628SLionel Sambuc 	return __pci_attr_r16(devind, PPB_SSTS);
1688433d6423SLionel Sambuc }
16896e7bb628SLionel Sambuc 
16906e7bb628SLionel Sambuc static void
pcibr_std_wsts(int busind,u16_t value)16916e7bb628SLionel Sambuc pcibr_std_wsts(int busind, u16_t value)
16926e7bb628SLionel Sambuc {
16936e7bb628SLionel Sambuc 	int devind;
16946e7bb628SLionel Sambuc 	devind= pcibus[busind].pb_devind;
16956e7bb628SLionel Sambuc 
16966e7bb628SLionel Sambuc #if 0
16976e7bb628SLionel Sambuc 	printf("pcibr_std_wsts(%d, 0x%X), devind= %d\n",
16986e7bb628SLionel Sambuc 		busind, value, devind);
16996e7bb628SLionel Sambuc #endif
17006e7bb628SLionel Sambuc 	__pci_attr_w16(devind, PPB_SSTS, value);
17016e7bb628SLionel Sambuc }
17026e7bb628SLionel Sambuc 
17036e7bb628SLionel Sambuc static u16_t
pcibr_cb_rsts(int busind)17046e7bb628SLionel Sambuc pcibr_cb_rsts(int busind)
17056e7bb628SLionel Sambuc {
17066e7bb628SLionel Sambuc 	int devind;
17076e7bb628SLionel Sambuc 	devind= pcibus[busind].pb_devind;
17086e7bb628SLionel Sambuc 
17096e7bb628SLionel Sambuc 	return __pci_attr_r16(devind, CBB_SSTS);
17106e7bb628SLionel Sambuc }
17116e7bb628SLionel Sambuc 
17126e7bb628SLionel Sambuc static void
pcibr_cb_wsts(int busind,u16_t value)17136e7bb628SLionel Sambuc pcibr_cb_wsts(int busind, u16_t value)
17146e7bb628SLionel Sambuc {
17156e7bb628SLionel Sambuc 	int devind;
17166e7bb628SLionel Sambuc 	devind= pcibus[busind].pb_devind;
17176e7bb628SLionel Sambuc 
17186e7bb628SLionel Sambuc #if 0
17196e7bb628SLionel Sambuc 	printf("pcibr_cb_wsts(%d, 0x%X), devind= %d\n",
17206e7bb628SLionel Sambuc 		busind, value, devind);
17216e7bb628SLionel Sambuc #endif
17226e7bb628SLionel Sambuc 	__pci_attr_w16(devind, CBB_SSTS, value);
17236e7bb628SLionel Sambuc }
17246e7bb628SLionel Sambuc 
17256e7bb628SLionel Sambuc static u16_t
pcibr_via_rsts(int busind)17266e7bb628SLionel Sambuc pcibr_via_rsts(int busind)
17276e7bb628SLionel Sambuc {
1728433d6423SLionel Sambuc 	return 0;
1729433d6423SLionel Sambuc }
17306e7bb628SLionel Sambuc 
17316e7bb628SLionel Sambuc static void
pcibr_via_wsts(int busind,u16_t value)17326e7bb628SLionel Sambuc pcibr_via_wsts(int busind, u16_t value)
17336e7bb628SLionel Sambuc {
17340a6a1f1dSLionel Sambuc #if 0
17356e7bb628SLionel Sambuc 	int devind;
17366e7bb628SLionel Sambuc 	devind= pcibus[busind].pb_devind;
17376e7bb628SLionel Sambuc 
17386e7bb628SLionel Sambuc 	printf("pcibr_via_wsts(%d, 0x%X), devind= %d (not implemented)\n",
17396e7bb628SLionel Sambuc 		busind, value, devind);
17406e7bb628SLionel Sambuc #endif
17416e7bb628SLionel Sambuc }
17426e7bb628SLionel Sambuc 
17436e7bb628SLionel Sambuc static void
complete_bridges(void)17446e7bb628SLionel Sambuc complete_bridges(void)
17456e7bb628SLionel Sambuc {
17466e7bb628SLionel Sambuc 	int i, freebus, devind, prim_busnr;
17476e7bb628SLionel Sambuc 
17486e7bb628SLionel Sambuc 	for (i= 0; i<nr_pcibus; i++)
17496e7bb628SLionel Sambuc 	{
17506e7bb628SLionel Sambuc 		if (!pcibus[i].pb_needinit)
17516e7bb628SLionel Sambuc 			continue;
17526e7bb628SLionel Sambuc 		printf("should allocate bus number for bus %d\n", i);
17536e7bb628SLionel Sambuc 		freebus= get_freebus();
17546e7bb628SLionel Sambuc 		printf("got bus number %d\n", freebus);
17556e7bb628SLionel Sambuc 
17566e7bb628SLionel Sambuc 		devind= pcibus[i].pb_devind;
17576e7bb628SLionel Sambuc 
17586e7bb628SLionel Sambuc 		prim_busnr= pcidev[devind].pd_busnr;
17596e7bb628SLionel Sambuc 		if (prim_busnr != 0)
1760433d6423SLionel Sambuc 		{
1761433d6423SLionel Sambuc 			printf(
17626e7bb628SLionel Sambuc 	"complete_bridge: updating subordinate bus number not implemented\n");
1763433d6423SLionel Sambuc 		}
17646e7bb628SLionel Sambuc 
17656e7bb628SLionel Sambuc 		pcibus[i].pb_needinit= 0;
17666e7bb628SLionel Sambuc 		pcibus[i].pb_busnr= freebus;
17676e7bb628SLionel Sambuc 
17686e7bb628SLionel Sambuc 		printf("devind = %d\n", devind);
17696e7bb628SLionel Sambuc 		printf("prim_busnr= %d\n", prim_busnr);
17706e7bb628SLionel Sambuc 
17716e7bb628SLionel Sambuc 		__pci_attr_w8(devind, PPB_PRIMBN, prim_busnr);
17726e7bb628SLionel Sambuc 		__pci_attr_w8(devind, PPB_SECBN, freebus);
17736e7bb628SLionel Sambuc 		__pci_attr_w8(devind, PPB_SUBORDBN, freebus);
17746e7bb628SLionel Sambuc 
17756e7bb628SLionel Sambuc 		printf("CR = 0x%x\n", __pci_attr_r16(devind, PCI_CR));
17766e7bb628SLionel Sambuc 		printf("SECBLT = 0x%x\n", __pci_attr_r8(devind, PPB_SECBLT));
17776e7bb628SLionel Sambuc 		printf("BRIDGECTRL = 0x%x\n",
17786e7bb628SLionel Sambuc 			__pci_attr_r16(devind, PPB_BRIDGECTRL));
17796e7bb628SLionel Sambuc 	}
1780433d6423SLionel Sambuc }
1781433d6423SLionel Sambuc 
17826e7bb628SLionel Sambuc static void
do_pcibridge(int busind)17836e7bb628SLionel Sambuc do_pcibridge(int busind)
1784433d6423SLionel Sambuc {
17853641562fSLionel Sambuc 	int devind, busnr;
1786433d6423SLionel Sambuc 	int ind, type;
1787433d6423SLionel Sambuc 	u16_t vid, did;
1788433d6423SLionel Sambuc 	u8_t sbusn, baseclass, subclass, infclass, headt;
1789433d6423SLionel Sambuc 	u32_t t3;
1790433d6423SLionel Sambuc 
1791433d6423SLionel Sambuc 	vid= did= 0;	/* lint */
1792433d6423SLionel Sambuc 	busnr= pcibus[busind].pb_busnr;
1793433d6423SLionel Sambuc 	for (devind= 0; devind< nr_pcidev; devind++)
1794433d6423SLionel Sambuc 	{
1795433d6423SLionel Sambuc 		if (pcidev[devind].pd_busnr != busnr)
1796433d6423SLionel Sambuc 		{
1797433d6423SLionel Sambuc #if 0
1798433d6423SLionel Sambuc 			printf("wrong bus\n");
1799433d6423SLionel Sambuc #endif
1800433d6423SLionel Sambuc 			continue;
1801433d6423SLionel Sambuc 		}
1802433d6423SLionel Sambuc 
1803433d6423SLionel Sambuc 		vid= pcidev[devind].pd_vid;
1804433d6423SLionel Sambuc 		did= pcidev[devind].pd_did;
18053641562fSLionel Sambuc 		/* LSC: The table is empty, so always true...
18063641562fSLionel Sambuc 		if (pci_pcibridge[i].vid == 0) */
1807433d6423SLionel Sambuc 		{
18086e7bb628SLionel Sambuc 			headt= __pci_attr_r8(devind, PCI_HEADT);
1809433d6423SLionel Sambuc 			type= 0;
1810433d6423SLionel Sambuc 			if ((headt & PHT_MASK) == PHT_BRIDGE)
1811433d6423SLionel Sambuc 				type= PCI_PPB_STD;
1812433d6423SLionel Sambuc 			else if ((headt & PHT_MASK) == PHT_CARDBUS)
1813433d6423SLionel Sambuc 				type= PCI_PPB_CB;
1814433d6423SLionel Sambuc 			else
1815433d6423SLionel Sambuc 			{
1816433d6423SLionel Sambuc #if 0
1817433d6423SLionel Sambuc 				printf("not a bridge\n");
1818433d6423SLionel Sambuc #endif
1819433d6423SLionel Sambuc 				continue;	/* Not a bridge */
1820433d6423SLionel Sambuc 			}
1821433d6423SLionel Sambuc 
18226e7bb628SLionel Sambuc 			baseclass= __pci_attr_r8(devind, PCI_BCR);
18236e7bb628SLionel Sambuc 			subclass= __pci_attr_r8(devind, PCI_SCR);
18246e7bb628SLionel Sambuc 			infclass= __pci_attr_r8(devind, PCI_PIFR);
1825433d6423SLionel Sambuc 			t3= ((baseclass << 16) | (subclass << 8) | infclass);
1826433d6423SLionel Sambuc 			if (type == PCI_PPB_STD &&
1827433d6423SLionel Sambuc 				t3 != PCI_T3_PCI2PCI &&
1828433d6423SLionel Sambuc 				t3 != PCI_T3_PCI2PCI_SUBTR)
1829433d6423SLionel Sambuc 			{
1830433d6423SLionel Sambuc 				printf(
1831433d6423SLionel Sambuc "Unknown PCI class %02x/%02x/%02x for PCI-to-PCI bridge, device %04X:%04X\n",
1832433d6423SLionel Sambuc 					baseclass, subclass, infclass,
1833433d6423SLionel Sambuc 					vid, did);
1834433d6423SLionel Sambuc 				continue;
1835433d6423SLionel Sambuc 			}
1836433d6423SLionel Sambuc 			if (type == PCI_PPB_CB &&
1837433d6423SLionel Sambuc 				t3 != PCI_T3_CARDBUS)
1838433d6423SLionel Sambuc 			{
1839433d6423SLionel Sambuc 				printf(
1840433d6423SLionel Sambuc "Unknown PCI class %02x/%02x/%02x for Cardbus bridge, device %04X:%04X\n",
1841433d6423SLionel Sambuc 					baseclass, subclass, infclass,
1842433d6423SLionel Sambuc 					vid, did);
1843433d6423SLionel Sambuc 				continue;
1844433d6423SLionel Sambuc 			}
1845433d6423SLionel Sambuc 		}
1846433d6423SLionel Sambuc 
1847433d6423SLionel Sambuc 		if (debug)
1848433d6423SLionel Sambuc 		{
1849433d6423SLionel Sambuc 			printf("%u.%u.%u: PCI-to-PCI bridge: %04X:%04X\n",
1850433d6423SLionel Sambuc 				pcidev[devind].pd_busnr,
1851433d6423SLionel Sambuc 				pcidev[devind].pd_dev,
1852433d6423SLionel Sambuc 				pcidev[devind].pd_func, vid, did);
1853433d6423SLionel Sambuc 		}
1854433d6423SLionel Sambuc 
1855433d6423SLionel Sambuc 		/* Assume that the BIOS initialized the secondary bus
1856433d6423SLionel Sambuc 		 * number.
1857433d6423SLionel Sambuc 		 */
18586e7bb628SLionel Sambuc 		sbusn= __pci_attr_r8(devind, PPB_SECBN);
1859433d6423SLionel Sambuc 
1860433d6423SLionel Sambuc 		if (nr_pcibus >= NR_PCIBUS)
1861433d6423SLionel Sambuc 			panic("too many PCI busses: %d", nr_pcibus);
1862433d6423SLionel Sambuc 		ind= nr_pcibus;
1863433d6423SLionel Sambuc 		nr_pcibus++;
1864433d6423SLionel Sambuc 		pcibus[ind].pb_type= PBT_PCIBRIDGE;
1865433d6423SLionel Sambuc 		pcibus[ind].pb_needinit= 1;
1866433d6423SLionel Sambuc 		pcibus[ind].pb_isabridge_dev= -1;
1867433d6423SLionel Sambuc 		pcibus[ind].pb_isabridge_type= 0;
1868433d6423SLionel Sambuc 		pcibus[ind].pb_devind= devind;
1869433d6423SLionel Sambuc 		pcibus[ind].pb_busnr= sbusn;
1870433d6423SLionel Sambuc 		pcibus[ind].pb_rreg8= pcibus[busind].pb_rreg8;
1871433d6423SLionel Sambuc 		pcibus[ind].pb_rreg16= pcibus[busind].pb_rreg16;
1872433d6423SLionel Sambuc 		pcibus[ind].pb_rreg32= pcibus[busind].pb_rreg32;
1873433d6423SLionel Sambuc 		pcibus[ind].pb_wreg8= pcibus[busind].pb_wreg8;
1874433d6423SLionel Sambuc 		pcibus[ind].pb_wreg16= pcibus[busind].pb_wreg16;
1875433d6423SLionel Sambuc 		pcibus[ind].pb_wreg32= pcibus[busind].pb_wreg32;
1876433d6423SLionel Sambuc 		switch(type)
1877433d6423SLionel Sambuc 		{
1878433d6423SLionel Sambuc 		case PCI_PPB_STD:
1879433d6423SLionel Sambuc 			pcibus[ind].pb_rsts= pcibr_std_rsts;
1880433d6423SLionel Sambuc 			pcibus[ind].pb_wsts= pcibr_std_wsts;
1881433d6423SLionel Sambuc 			break;
1882433d6423SLionel Sambuc 		case PCI_PPB_CB:
1883433d6423SLionel Sambuc 			pcibus[ind].pb_type= PBT_CARDBUS;
1884433d6423SLionel Sambuc 			pcibus[ind].pb_rsts= pcibr_cb_rsts;
1885433d6423SLionel Sambuc 			pcibus[ind].pb_wsts= pcibr_cb_wsts;
1886433d6423SLionel Sambuc 			break;
1887433d6423SLionel Sambuc 		case PCI_AGPB_VIA:
1888433d6423SLionel Sambuc 			pcibus[ind].pb_rsts= pcibr_via_rsts;
1889433d6423SLionel Sambuc 			pcibus[ind].pb_wsts= pcibr_via_wsts;
1890433d6423SLionel Sambuc 			break;
1891433d6423SLionel Sambuc 		default:
1892433d6423SLionel Sambuc 			panic("unknown PCI-PCI bridge type: %d", type);
1893433d6423SLionel Sambuc 		}
1894433d6423SLionel Sambuc 
1895433d6423SLionel Sambuc 		if (machine.apic_enabled)
1896433d6423SLionel Sambuc 			acpi_map_bridge(pcidev[devind].pd_busnr,
1897433d6423SLionel Sambuc 					pcidev[devind].pd_dev, sbusn);
1898433d6423SLionel Sambuc 
1899433d6423SLionel Sambuc 		if (debug)
1900433d6423SLionel Sambuc 		{
1901433d6423SLionel Sambuc 			printf(
1902433d6423SLionel Sambuc 			"bus(table) = %d, bus(sec) = %d, bus(subord) = %d\n",
19036e7bb628SLionel Sambuc 				ind, sbusn, __pci_attr_r8(devind, PPB_SUBORDBN));
1904433d6423SLionel Sambuc 		}
1905433d6423SLionel Sambuc 		if (sbusn == 0)
1906433d6423SLionel Sambuc 		{
1907433d6423SLionel Sambuc 			printf("Secondary bus number not initialized\n");
1908433d6423SLionel Sambuc 			continue;
1909433d6423SLionel Sambuc 		}
1910433d6423SLionel Sambuc 		pcibus[ind].pb_needinit= 0;
1911433d6423SLionel Sambuc 
1912433d6423SLionel Sambuc 		probe_bus(ind);
1913433d6423SLionel Sambuc 
1914433d6423SLionel Sambuc 		/* Look for PCI bridges */
1915433d6423SLionel Sambuc 		do_pcibridge(ind);
1916433d6423SLionel Sambuc 	}
1917433d6423SLionel Sambuc }
1918433d6423SLionel Sambuc 
1919433d6423SLionel Sambuc /*===========================================================================*
19206e7bb628SLionel Sambuc  *				pci_intel_init				     *
1921433d6423SLionel Sambuc  *===========================================================================*/
19226e7bb628SLionel Sambuc static void
pci_intel_init(void)19230a6a1f1dSLionel Sambuc pci_intel_init(void)
1924433d6423SLionel Sambuc {
19256e7bb628SLionel Sambuc 	/* Try to detect a know PCI controller. Read the Vendor ID and
19266e7bb628SLionel Sambuc 	 * the Device ID for function 0 of device 0.
19276e7bb628SLionel Sambuc 	 * Two times the value 0xffff suggests a system without a (compatible)
19286e7bb628SLionel Sambuc 	 * PCI controller.
19296e7bb628SLionel Sambuc 	 */
19306e7bb628SLionel Sambuc 	u32_t bus, dev, func;
19316e7bb628SLionel Sambuc 	u16_t vid, did;
19326e7bb628SLionel Sambuc 	int s, i, r, busind, busnr;
19336e7bb628SLionel Sambuc 	const char *dstr;
1934433d6423SLionel Sambuc 
19356e7bb628SLionel Sambuc 	bus= 0;
19366e7bb628SLionel Sambuc 	dev= 0;
19376e7bb628SLionel Sambuc 	func= 0;
19386e7bb628SLionel Sambuc 
19396e7bb628SLionel Sambuc 	vid= PCII_RREG16_(bus, dev, func, PCI_VID);
19406e7bb628SLionel Sambuc 	did= PCII_RREG16_(bus, dev, func, PCI_DID);
19416e7bb628SLionel Sambuc 	if (OK != (s=sys_outl(PCII_CONFADD, PCII_UNSEL)))
19426e7bb628SLionel Sambuc 		printf("PCI: warning, sys_outl failed: %d\n", s);
19436e7bb628SLionel Sambuc 
19446e7bb628SLionel Sambuc 	if (nr_pcibus >= NR_PCIBUS)
19456e7bb628SLionel Sambuc 		panic("too many PCI busses: %d", nr_pcibus);
19466e7bb628SLionel Sambuc 	busind= nr_pcibus;
19476e7bb628SLionel Sambuc 	nr_pcibus++;
19486e7bb628SLionel Sambuc 	pcibus[busind].pb_type= PBT_INTEL_HOST;
19496e7bb628SLionel Sambuc 	pcibus[busind].pb_needinit= 0;
19506e7bb628SLionel Sambuc 	pcibus[busind].pb_isabridge_dev= -1;
19516e7bb628SLionel Sambuc 	pcibus[busind].pb_isabridge_type= 0;
19526e7bb628SLionel Sambuc 	pcibus[busind].pb_devind= -1;
19536e7bb628SLionel Sambuc 	pcibus[busind].pb_busnr= 0;
19546e7bb628SLionel Sambuc 	pcibus[busind].pb_rreg8= pcii_rreg8;
19556e7bb628SLionel Sambuc 	pcibus[busind].pb_rreg16= pcii_rreg16;
19566e7bb628SLionel Sambuc 	pcibus[busind].pb_rreg32= pcii_rreg32;
19576e7bb628SLionel Sambuc 	pcibus[busind].pb_wreg8= pcii_wreg8;
19586e7bb628SLionel Sambuc 	pcibus[busind].pb_wreg16= pcii_wreg16;
19596e7bb628SLionel Sambuc 	pcibus[busind].pb_wreg32= pcii_wreg32;
19606e7bb628SLionel Sambuc 	pcibus[busind].pb_rsts= pcii_rsts;
19616e7bb628SLionel Sambuc 	pcibus[busind].pb_wsts= pcii_wsts;
19626e7bb628SLionel Sambuc 
19636e7bb628SLionel Sambuc 	dstr= _pci_dev_name(vid, did);
19646e7bb628SLionel Sambuc 	if (!dstr)
19656e7bb628SLionel Sambuc 		dstr= "unknown device";
1966433d6423SLionel Sambuc 	if (debug)
1967433d6423SLionel Sambuc 	{
19686e7bb628SLionel Sambuc 		printf("pci_intel_init: %s (%04X:%04X)\n",
19696e7bb628SLionel Sambuc 			dstr, vid, did);
1970433d6423SLionel Sambuc 	}
1971433d6423SLionel Sambuc 
19726e7bb628SLionel Sambuc 	probe_bus(busind);
1973433d6423SLionel Sambuc 
19746e7bb628SLionel Sambuc 	r= do_isabridge(busind);
19756e7bb628SLionel Sambuc 	if (r != OK)
19766e7bb628SLionel Sambuc 	{
19776e7bb628SLionel Sambuc 		busnr= pcibus[busind].pb_busnr;
1978433d6423SLionel Sambuc 
19796e7bb628SLionel Sambuc 		/* Disable all devices for this bus */
19806e7bb628SLionel Sambuc 		for (i= 0; i<nr_pcidev; i++)
1981433d6423SLionel Sambuc 		{
19826e7bb628SLionel Sambuc 			if (pcidev[i].pd_busnr != busnr)
19836e7bb628SLionel Sambuc 				continue;
19846e7bb628SLionel Sambuc 			pcidev[i].pd_inuse= 1;
1985433d6423SLionel Sambuc 		}
19866e7bb628SLionel Sambuc 		return;
1987433d6423SLionel Sambuc 	}
1988433d6423SLionel Sambuc 
19896e7bb628SLionel Sambuc 	/* Look for PCI bridges */
19906e7bb628SLionel Sambuc 	do_pcibridge(busind);
1991433d6423SLionel Sambuc 
19926e7bb628SLionel Sambuc 	/* Allocate bus numbers for uninitialized bridges */
19936e7bb628SLionel Sambuc 	complete_bridges();
1994433d6423SLionel Sambuc 
19956e7bb628SLionel Sambuc 	/* Allocate I/O and memory resources for uninitialized devices */
19966e7bb628SLionel Sambuc 	complete_bars();
1997433d6423SLionel Sambuc }
1998433d6423SLionel Sambuc 
1999433d6423SLionel Sambuc #if 0
2000433d6423SLionel Sambuc /*===========================================================================*
2001433d6423SLionel Sambuc  *				report_vga				     *
2002433d6423SLionel Sambuc  *===========================================================================*/
20036e7bb628SLionel Sambuc static void
20046e7bb628SLionel Sambuc report_vga(int devind)
2005433d6423SLionel Sambuc {
2006433d6423SLionel Sambuc 	/* Report the amount of video memory. This is needed by the X11R6
2007433d6423SLionel Sambuc 	 * postinstall script to chmem the X server. Hopefully this can be
2008433d6423SLionel Sambuc 	 * removed when we get virtual memory.
2009433d6423SLionel Sambuc 	 */
2010433d6423SLionel Sambuc 	size_t amount, size;
2011433d6423SLionel Sambuc 	int i;
2012433d6423SLionel Sambuc 
2013433d6423SLionel Sambuc 	amount= 0;
2014433d6423SLionel Sambuc 	for (i= 0; i<pcidev[devind].pd_bar_nr; i++)
2015433d6423SLionel Sambuc 	{
2016433d6423SLionel Sambuc 		if (pcidev[devind].pd_bar[i].pb_flags & PBF_IO)
2017433d6423SLionel Sambuc 			continue;
2018433d6423SLionel Sambuc 		size= pcidev[devind].pd_bar[i].pb_size;
2019433d6423SLionel Sambuc 		if (size < amount)
2020433d6423SLionel Sambuc 			continue;
2021433d6423SLionel Sambuc 		amount= size;
2022433d6423SLionel Sambuc 	}
2023433d6423SLionel Sambuc 	if (size != 0)
2024433d6423SLionel Sambuc 	{
2025433d6423SLionel Sambuc 		printf("PCI: video memory for device at %d.%d.%d: %d bytes\n",
2026433d6423SLionel Sambuc 			pcidev[devind].pd_busnr,
2027433d6423SLionel Sambuc 			pcidev[devind].pd_dev,
2028433d6423SLionel Sambuc 			pcidev[devind].pd_func,
2029433d6423SLionel Sambuc 			amount);
2030433d6423SLionel Sambuc 	}
2031433d6423SLionel Sambuc }
2032433d6423SLionel Sambuc #endif
2033433d6423SLionel Sambuc 
2034433d6423SLionel Sambuc 
2035433d6423SLionel Sambuc /*===========================================================================*
2036433d6423SLionel Sambuc  *				visible					     *
2037433d6423SLionel Sambuc  *===========================================================================*/
20386e7bb628SLionel Sambuc static int
visible(struct rs_pci * aclp,int devind)20396e7bb628SLionel Sambuc visible(struct rs_pci *aclp, int devind)
2040433d6423SLionel Sambuc {
2041433d6423SLionel Sambuc 	u16_t acl_sub_vid, acl_sub_did;
2042433d6423SLionel Sambuc 	int i;
2043433d6423SLionel Sambuc 	u32_t class_id;
2044433d6423SLionel Sambuc 
2045433d6423SLionel Sambuc 	if (!aclp)
2046433d6423SLionel Sambuc 		return TRUE;	/* Should be changed when ACLs become
2047433d6423SLionel Sambuc 				 * mandatory. Do note that procfs relies
2048433d6423SLionel Sambuc 				 * on being able to see all devices.
2049433d6423SLionel Sambuc 				 */
2050433d6423SLionel Sambuc 	/* Check whether the caller is allowed to get this device. */
2051433d6423SLionel Sambuc 	for (i= 0; i<aclp->rsp_nr_device; i++)
2052433d6423SLionel Sambuc 	{
2053433d6423SLionel Sambuc 		acl_sub_vid = aclp->rsp_device[i].sub_vid;
2054433d6423SLionel Sambuc 		acl_sub_did = aclp->rsp_device[i].sub_did;
2055433d6423SLionel Sambuc 		if (aclp->rsp_device[i].vid == pcidev[devind].pd_vid &&
2056433d6423SLionel Sambuc 			aclp->rsp_device[i].did == pcidev[devind].pd_did &&
2057433d6423SLionel Sambuc 			(acl_sub_vid == NO_SUB_VID ||
2058433d6423SLionel Sambuc 			acl_sub_vid == pcidev[devind].pd_sub_vid) &&
2059433d6423SLionel Sambuc 			(acl_sub_did == NO_SUB_DID ||
2060433d6423SLionel Sambuc 			acl_sub_did == pcidev[devind].pd_sub_did))
2061433d6423SLionel Sambuc 		{
2062433d6423SLionel Sambuc 			return TRUE;
2063433d6423SLionel Sambuc 		}
2064433d6423SLionel Sambuc 	}
2065433d6423SLionel Sambuc 	if (!aclp->rsp_nr_class)
2066433d6423SLionel Sambuc 		return FALSE;
2067433d6423SLionel Sambuc 
2068433d6423SLionel Sambuc 	class_id= (pcidev[devind].pd_baseclass << 16) |
2069433d6423SLionel Sambuc 		(pcidev[devind].pd_subclass << 8) |
2070433d6423SLionel Sambuc 		pcidev[devind].pd_infclass;
2071433d6423SLionel Sambuc 	for (i= 0; i<aclp->rsp_nr_class; i++)
2072433d6423SLionel Sambuc 	{
2073433d6423SLionel Sambuc 		if (aclp->rsp_class[i].pciclass ==
2074433d6423SLionel Sambuc 			(class_id & aclp->rsp_class[i].mask))
2075433d6423SLionel Sambuc 		{
2076433d6423SLionel Sambuc 			return TRUE;
2077433d6423SLionel Sambuc 		}
2078433d6423SLionel Sambuc 	}
2079433d6423SLionel Sambuc 
2080433d6423SLionel Sambuc 	return FALSE;
2081433d6423SLionel Sambuc }
2082433d6423SLionel Sambuc 
2083433d6423SLionel Sambuc /*===========================================================================*
20846e7bb628SLionel Sambuc  *				sef_cb_init_fresh			     *
2085433d6423SLionel Sambuc  *===========================================================================*/
20866e7bb628SLionel Sambuc int
sef_cb_init(int type,sef_init_info_t * info)20875d831176SLionel Sambuc sef_cb_init(int type, sef_init_info_t *info)
2088433d6423SLionel Sambuc {
20895d831176SLionel Sambuc 	/* Initialize the driver. */
20905d831176SLionel Sambuc 	int do_announce_driver = -1;
20915d831176SLionel Sambuc 
20926e7bb628SLionel Sambuc 	long v;
20936e7bb628SLionel Sambuc 	int i, r;
20946e7bb628SLionel Sambuc 	struct rprocpub rprocpub[NR_BOOT_PROCS];
2095433d6423SLionel Sambuc 
20966e7bb628SLionel Sambuc 	v= 0;
20976e7bb628SLionel Sambuc 	env_parse("pci_debug", "d", 0, &v, 0, 1);
20986e7bb628SLionel Sambuc 	debug= v;
20996e7bb628SLionel Sambuc 
21006e7bb628SLionel Sambuc 	if (sys_getmachine(&machine)) {
21016e7bb628SLionel Sambuc 		printf("PCI: no machine\n");
21026e7bb628SLionel Sambuc 		return ENODEV;
21036e7bb628SLionel Sambuc 	}
21046e7bb628SLionel Sambuc 	if (machine.apic_enabled &&
2105*fee60e45Srlfnb 			acpi_init() != OK) {
21066e7bb628SLionel Sambuc 		panic("PCI: Cannot use APIC mode without ACPI!\n");
21076e7bb628SLionel Sambuc 	}
21086e7bb628SLionel Sambuc 
21096e7bb628SLionel Sambuc 	/* Only Intel (compatible) PCI controllers are supported at the
21106e7bb628SLionel Sambuc 	 * moment.
21116e7bb628SLionel Sambuc 	 */
21126e7bb628SLionel Sambuc 	pci_intel_init();
21136e7bb628SLionel Sambuc 
21146e7bb628SLionel Sambuc 	/* Map all the services in the boot image. */
21156e7bb628SLionel Sambuc 	if ((r = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
21166e7bb628SLionel Sambuc 		(vir_bytes) rprocpub, sizeof(rprocpub))) != OK) {
21176e7bb628SLionel Sambuc 		panic("sys_safecopyfrom failed: %d", r);
21186e7bb628SLionel Sambuc 	}
21196e7bb628SLionel Sambuc 	for(i=0;i < NR_BOOT_PROCS;i++) {
21206e7bb628SLionel Sambuc 		if (rprocpub[i].in_use) {
21216e7bb628SLionel Sambuc 			if ((r = map_service(&rprocpub[i])) != OK) {
21226e7bb628SLionel Sambuc 				panic("unable to map service: %d", r);
21236e7bb628SLionel Sambuc 			}
21246e7bb628SLionel Sambuc 		}
21256e7bb628SLionel Sambuc 	}
21266e7bb628SLionel Sambuc 
21275d831176SLionel Sambuc 	switch(type) {
21285d831176SLionel Sambuc 	case SEF_INIT_FRESH:
21295d831176SLionel Sambuc 	case SEF_INIT_RESTART:
21305d831176SLionel Sambuc 		do_announce_driver = TRUE;
21315d831176SLionel Sambuc 		break;
21325d831176SLionel Sambuc 	case SEF_INIT_LU:
21335d831176SLionel Sambuc 		do_announce_driver = FALSE;
21345d831176SLionel Sambuc 		break;
21355d831176SLionel Sambuc 	default:
21365d831176SLionel Sambuc 		panic("Unknown type of restart");
21375d831176SLionel Sambuc 		break;
21385d831176SLionel Sambuc 	}
21395d831176SLionel Sambuc 
21405d831176SLionel Sambuc 	/* Announce we are up when necessary. */
21415d831176SLionel Sambuc 	if (TRUE == do_announce_driver) {
21425d831176SLionel Sambuc 		chardriver_announce();
21435d831176SLionel Sambuc 	}
21445d831176SLionel Sambuc 
21455d831176SLionel Sambuc 	/* Initialization completed successfully. */
21465d831176SLionel Sambuc 	return OK;
21476e7bb628SLionel Sambuc }
21486e7bb628SLionel Sambuc 
21496e7bb628SLionel Sambuc /*===========================================================================*
21506e7bb628SLionel Sambuc  *		               map_service                                   *
21516e7bb628SLionel Sambuc  *===========================================================================*/
21526e7bb628SLionel Sambuc int
map_service(struct rprocpub * rpub)21536e7bb628SLionel Sambuc map_service(struct rprocpub *rpub)
21546e7bb628SLionel Sambuc {
21556e7bb628SLionel Sambuc /* Map a new service by registering a new acl entry if required. */
21566e7bb628SLionel Sambuc 	int i;
21576e7bb628SLionel Sambuc 
21586e7bb628SLionel Sambuc 	/* Stop right now if no pci device or class is found. */
21596e7bb628SLionel Sambuc 	if(rpub->pci_acl.rsp_nr_device == 0
21606e7bb628SLionel Sambuc 		&& rpub->pci_acl.rsp_nr_class == 0) {
21616e7bb628SLionel Sambuc 		return(OK);
21626e7bb628SLionel Sambuc 	}
21636e7bb628SLionel Sambuc 
21646e7bb628SLionel Sambuc 	/* Find a free acl slot. */
21656e7bb628SLionel Sambuc 	for (i= 0; i<NR_DRIVERS; i++)
21666e7bb628SLionel Sambuc 	{
21676e7bb628SLionel Sambuc 		if (!pci_acl[i].inuse)
21686e7bb628SLionel Sambuc 			break;
21696e7bb628SLionel Sambuc 	}
21706e7bb628SLionel Sambuc 	if (i >= NR_DRIVERS)
21716e7bb628SLionel Sambuc 	{
21726e7bb628SLionel Sambuc 		printf("PCI: map_service: table is full\n");
21736e7bb628SLionel Sambuc 		return ENOMEM;
21746e7bb628SLionel Sambuc 	}
21756e7bb628SLionel Sambuc 
21766e7bb628SLionel Sambuc 	/* Initialize acl slot. */
21776e7bb628SLionel Sambuc 	pci_acl[i].inuse = 1;
21786e7bb628SLionel Sambuc 	pci_acl[i].acl = rpub->pci_acl;
21796e7bb628SLionel Sambuc 
21805d831176SLionel Sambuc 	return OK;
21816e7bb628SLionel Sambuc }
21826e7bb628SLionel Sambuc 
21836e7bb628SLionel Sambuc /*===========================================================================*
21846e7bb628SLionel Sambuc  *				_pci_find_dev				     *
21856e7bb628SLionel Sambuc  *===========================================================================*/
21866e7bb628SLionel Sambuc int
_pci_find_dev(u8_t bus,u8_t dev,u8_t func,int * devindp)21876e7bb628SLionel Sambuc _pci_find_dev(u8_t bus, u8_t dev, u8_t func, int *devindp)
21886e7bb628SLionel Sambuc {
21896e7bb628SLionel Sambuc 	int devind;
21906e7bb628SLionel Sambuc 
21916e7bb628SLionel Sambuc 	for (devind= 0; devind < nr_pcidev; devind++)
21926e7bb628SLionel Sambuc 	{
21936e7bb628SLionel Sambuc 		if (pcidev[devind].pd_busnr == bus &&
21946e7bb628SLionel Sambuc 			pcidev[devind].pd_dev == dev &&
21956e7bb628SLionel Sambuc 			pcidev[devind].pd_func == func)
21966e7bb628SLionel Sambuc 		{
21976e7bb628SLionel Sambuc 			break;
21986e7bb628SLionel Sambuc 		}
21996e7bb628SLionel Sambuc 	}
22005d831176SLionel Sambuc 
22016e7bb628SLionel Sambuc 	if (devind >= nr_pcidev)
22026e7bb628SLionel Sambuc 		return 0;
22035d831176SLionel Sambuc 
22046e7bb628SLionel Sambuc 	*devindp= devind;
22055d831176SLionel Sambuc 
22066e7bb628SLionel Sambuc 	return 1;
22076e7bb628SLionel Sambuc }
22086e7bb628SLionel Sambuc 
22096e7bb628SLionel Sambuc /*===========================================================================*
22106e7bb628SLionel Sambuc  *				_pci_first_dev				     *
22116e7bb628SLionel Sambuc  *===========================================================================*/
22126e7bb628SLionel Sambuc int
_pci_first_dev(struct rs_pci * aclp,int * devindp,u16_t * vidp,u16_t * didp)22136e7bb628SLionel Sambuc _pci_first_dev(struct rs_pci *aclp, int *devindp, u16_t *vidp,
22146e7bb628SLionel Sambuc 	u16_t *didp)
2215433d6423SLionel Sambuc {
22166e7bb628SLionel Sambuc 	int devind;
22176e7bb628SLionel Sambuc 
22186e7bb628SLionel Sambuc 	for (devind= 0; devind < nr_pcidev; devind++)
22196e7bb628SLionel Sambuc 	{
22206e7bb628SLionel Sambuc 		if (!visible(aclp, devind))
22216e7bb628SLionel Sambuc 			continue;
22226e7bb628SLionel Sambuc 		break;
22236e7bb628SLionel Sambuc 	}
22246e7bb628SLionel Sambuc 	if (devind >= nr_pcidev)
22256e7bb628SLionel Sambuc 		return 0;
22266e7bb628SLionel Sambuc 	*devindp= devind;
22276e7bb628SLionel Sambuc 	*vidp= pcidev[devind].pd_vid;
22286e7bb628SLionel Sambuc 	*didp= pcidev[devind].pd_did;
22296e7bb628SLionel Sambuc 	return 1;
22306e7bb628SLionel Sambuc }
22316e7bb628SLionel Sambuc 
22326e7bb628SLionel Sambuc /*===========================================================================*
22336e7bb628SLionel Sambuc  *				_pci_next_dev				     *
22346e7bb628SLionel Sambuc  *===========================================================================*/
22356e7bb628SLionel Sambuc int
_pci_next_dev(struct rs_pci * aclp,int * devindp,u16_t * vidp,u16_t * didp)22366e7bb628SLionel Sambuc _pci_next_dev(struct rs_pci *aclp, int *devindp, u16_t *vidp, u16_t *didp)
22376e7bb628SLionel Sambuc {
22386e7bb628SLionel Sambuc 	int devind;
22396e7bb628SLionel Sambuc 
22406e7bb628SLionel Sambuc 	for (devind= *devindp+1; devind < nr_pcidev; devind++)
22416e7bb628SLionel Sambuc 	{
22426e7bb628SLionel Sambuc 		if (!visible(aclp, devind))
22436e7bb628SLionel Sambuc 			continue;
22446e7bb628SLionel Sambuc 		break;
22456e7bb628SLionel Sambuc 	}
22466e7bb628SLionel Sambuc 	if (devind >= nr_pcidev)
22476e7bb628SLionel Sambuc 		return 0;
22486e7bb628SLionel Sambuc 	*devindp= devind;
22496e7bb628SLionel Sambuc 	*vidp= pcidev[devind].pd_vid;
22506e7bb628SLionel Sambuc 	*didp= pcidev[devind].pd_did;
22516e7bb628SLionel Sambuc 	return 1;
22526e7bb628SLionel Sambuc }
22536e7bb628SLionel Sambuc 
22546e7bb628SLionel Sambuc /*===========================================================================*
22555d831176SLionel Sambuc  *				_pci_grant_access			     *
22566e7bb628SLionel Sambuc  *===========================================================================*/
22576e7bb628SLionel Sambuc int
_pci_grant_access(int devind,endpoint_t proc)22585d831176SLionel Sambuc _pci_grant_access(int devind, endpoint_t proc)
22596e7bb628SLionel Sambuc {
22605d831176SLionel Sambuc 	int i, ilr;
22615d831176SLionel Sambuc 	int r = OK;
22626e7bb628SLionel Sambuc 	struct io_range ior;
22636e7bb628SLionel Sambuc 	struct minix_mem_range mr;
22646e7bb628SLionel Sambuc 
22656e7bb628SLionel Sambuc 	for (i= 0; i<pcidev[devind].pd_bar_nr; i++)
22666e7bb628SLionel Sambuc 	{
22676e7bb628SLionel Sambuc 		if (pcidev[devind].pd_bar[i].pb_flags & PBF_INCOMPLETE)
22686e7bb628SLionel Sambuc 		{
22696e7bb628SLionel Sambuc 			printf("pci_reserve_a: BAR %d is incomplete\n", i);
22706e7bb628SLionel Sambuc 			continue;
22716e7bb628SLionel Sambuc 		}
22726e7bb628SLionel Sambuc 		if (pcidev[devind].pd_bar[i].pb_flags & PBF_IO)
22736e7bb628SLionel Sambuc 		{
22746e7bb628SLionel Sambuc 			ior.ior_base= pcidev[devind].pd_bar[i].pb_base;
22756e7bb628SLionel Sambuc 			ior.ior_limit= ior.ior_base +
22766e7bb628SLionel Sambuc 				pcidev[devind].pd_bar[i].pb_size-1;
22776e7bb628SLionel Sambuc 
22786e7bb628SLionel Sambuc 			if(debug) {
22796e7bb628SLionel Sambuc 				printf(
22806e7bb628SLionel Sambuc 		"pci_reserve_a: for proc %d, adding I/O range [0x%x..0x%x]\n",
22816e7bb628SLionel Sambuc 		proc, ior.ior_base, ior.ior_limit);
22826e7bb628SLionel Sambuc 			}
22836e7bb628SLionel Sambuc 			r= sys_privctl(proc, SYS_PRIV_ADD_IO, &ior);
22846e7bb628SLionel Sambuc 			if (r != OK)
22856e7bb628SLionel Sambuc 			{
22866e7bb628SLionel Sambuc 				printf("sys_privctl failed for proc %d: %d\n",
22876e7bb628SLionel Sambuc 					proc, r);
22886e7bb628SLionel Sambuc 			}
2289433d6423SLionel Sambuc 		}
2290433d6423SLionel Sambuc 		else
2291433d6423SLionel Sambuc 		{
22926e7bb628SLionel Sambuc 			mr.mr_base= pcidev[devind].pd_bar[i].pb_base;
22936e7bb628SLionel Sambuc 			mr.mr_limit= mr.mr_base +
22946e7bb628SLionel Sambuc 				pcidev[devind].pd_bar[i].pb_size-1;
2295433d6423SLionel Sambuc 
22966e7bb628SLionel Sambuc 			r= sys_privctl(proc, SYS_PRIV_ADD_MEM, &mr);
22976e7bb628SLionel Sambuc 			if (r != OK)
22986e7bb628SLionel Sambuc 			{
22996e7bb628SLionel Sambuc 				printf("sys_privctl failed for proc %d: %d\n",
23006e7bb628SLionel Sambuc 					proc, r);
23016e7bb628SLionel Sambuc 			}
23026e7bb628SLionel Sambuc 		}
23036e7bb628SLionel Sambuc 	}
23046e7bb628SLionel Sambuc 	ilr= pcidev[devind].pd_ilr;
23056e7bb628SLionel Sambuc 	if (ilr != PCI_ILR_UNKNOWN)
23066e7bb628SLionel Sambuc 	{
23076e7bb628SLionel Sambuc 		if(debug) printf("pci_reserve_a: adding IRQ %d\n", ilr);
23086e7bb628SLionel Sambuc 		r= sys_privctl(proc, SYS_PRIV_ADD_IRQ, &ilr);
23096e7bb628SLionel Sambuc 		if (r != OK)
23106e7bb628SLionel Sambuc 		{
23116e7bb628SLionel Sambuc 			printf("sys_privctl failed for proc %d: %d\n",
23126e7bb628SLionel Sambuc 				proc, r);
23136e7bb628SLionel Sambuc 		}
2314433d6423SLionel Sambuc 	}
2315433d6423SLionel Sambuc 
23165d831176SLionel Sambuc 	return r;
23175d831176SLionel Sambuc }
23185d831176SLionel Sambuc 
23195d831176SLionel Sambuc /*===========================================================================*
23205d831176SLionel Sambuc  *				_pci_reserve				     *
23215d831176SLionel Sambuc  *===========================================================================*/
23225d831176SLionel Sambuc int
_pci_reserve(int devind,endpoint_t proc,struct rs_pci * aclp)23235d831176SLionel Sambuc _pci_reserve(int devind, endpoint_t proc, struct rs_pci *aclp)
23245d831176SLionel Sambuc {
23255d831176SLionel Sambuc 	if (devind < 0 || devind >= nr_pcidev)
23265d831176SLionel Sambuc 	{
23275d831176SLionel Sambuc 		printf("pci_reserve_a: bad devind: %d\n", devind);
23285d831176SLionel Sambuc 		return EINVAL;
23295d831176SLionel Sambuc 	}
23305d831176SLionel Sambuc 	if (!visible(aclp, devind))
23315d831176SLionel Sambuc 	{
23325d831176SLionel Sambuc 		printf("pci_reserve_a: %u is not allowed to reserve %d\n",
23335d831176SLionel Sambuc 			proc, devind);
23345d831176SLionel Sambuc 		return EPERM;
23355d831176SLionel Sambuc 	}
23365d831176SLionel Sambuc 
23375d831176SLionel Sambuc 	if(pcidev[devind].pd_inuse && pcidev[devind].pd_proc != proc)
23385d831176SLionel Sambuc 		return EBUSY;
23395d831176SLionel Sambuc 
23405d831176SLionel Sambuc 	pcidev[devind].pd_inuse= 1;
23415d831176SLionel Sambuc 	pcidev[devind].pd_proc= proc;
23425d831176SLionel Sambuc 
23435d831176SLionel Sambuc 	return  _pci_grant_access(devind, proc);
23446e7bb628SLionel Sambuc }
23456e7bb628SLionel Sambuc 
23466e7bb628SLionel Sambuc /*===========================================================================*
23476e7bb628SLionel Sambuc  *				_pci_release				     *
23486e7bb628SLionel Sambuc  *===========================================================================*/
23496e7bb628SLionel Sambuc void
_pci_release(endpoint_t proc)23506e7bb628SLionel Sambuc _pci_release(endpoint_t proc)
23516e7bb628SLionel Sambuc {
23526e7bb628SLionel Sambuc 	int i;
23536e7bb628SLionel Sambuc 
23546e7bb628SLionel Sambuc 	for (i= 0; i<nr_pcidev; i++)
23556e7bb628SLionel Sambuc 	{
23566e7bb628SLionel Sambuc 		if (!pcidev[i].pd_inuse)
23576e7bb628SLionel Sambuc 			continue;
23586e7bb628SLionel Sambuc 		if (pcidev[i].pd_proc != proc)
23596e7bb628SLionel Sambuc 			continue;
23606e7bb628SLionel Sambuc 		pcidev[i].pd_inuse= 0;
23616e7bb628SLionel Sambuc 	}
23626e7bb628SLionel Sambuc }
23636e7bb628SLionel Sambuc 
23646e7bb628SLionel Sambuc /*===========================================================================*
23656e7bb628SLionel Sambuc  *				_pci_ids				     *
23666e7bb628SLionel Sambuc  *===========================================================================*/
23676e7bb628SLionel Sambuc int
_pci_ids(int devind,u16_t * vidp,u16_t * didp)23686e7bb628SLionel Sambuc _pci_ids(int devind, u16_t *vidp, u16_t *didp)
23696e7bb628SLionel Sambuc {
23706e7bb628SLionel Sambuc 	if (devind < 0 || devind >= nr_pcidev)
23716e7bb628SLionel Sambuc 		return EINVAL;
23726e7bb628SLionel Sambuc 
23736e7bb628SLionel Sambuc 	*vidp= pcidev[devind].pd_vid;
23746e7bb628SLionel Sambuc 	*didp= pcidev[devind].pd_did;
23756e7bb628SLionel Sambuc 	return OK;
23766e7bb628SLionel Sambuc }
23776e7bb628SLionel Sambuc 
23786e7bb628SLionel Sambuc /*===========================================================================*
23796e7bb628SLionel Sambuc  *				_pci_rescan_bus				     *
23806e7bb628SLionel Sambuc  *===========================================================================*/
23816e7bb628SLionel Sambuc void
_pci_rescan_bus(u8_t busnr)23826e7bb628SLionel Sambuc _pci_rescan_bus(u8_t busnr)
23836e7bb628SLionel Sambuc {
23846e7bb628SLionel Sambuc 	int busind;
23856e7bb628SLionel Sambuc 
23866e7bb628SLionel Sambuc 	busind= get_busind(busnr);
23876e7bb628SLionel Sambuc 	probe_bus(busind);
23886e7bb628SLionel Sambuc 
23896e7bb628SLionel Sambuc 	/* Allocate bus numbers for uninitialized bridges */
23906e7bb628SLionel Sambuc 	complete_bridges();
23916e7bb628SLionel Sambuc 
23926e7bb628SLionel Sambuc 	/* Allocate I/O and memory resources for uninitialized devices */
23936e7bb628SLionel Sambuc 	complete_bars();
23946e7bb628SLionel Sambuc }
23956e7bb628SLionel Sambuc 
23966e7bb628SLionel Sambuc /*===========================================================================*
23976e7bb628SLionel Sambuc  *				_pci_slot_name				     *
23986e7bb628SLionel Sambuc  *===========================================================================*/
23996e7bb628SLionel Sambuc int
_pci_slot_name(int devind,char ** cpp)24006e7bb628SLionel Sambuc _pci_slot_name(int devind, char **cpp)
24016e7bb628SLionel Sambuc {
24026e7bb628SLionel Sambuc 	static char label[]= "ddd.ddd.ddd.ddd";
24036e7bb628SLionel Sambuc 	char *end;
24046e7bb628SLionel Sambuc 	char *p;
24056e7bb628SLionel Sambuc 
24066e7bb628SLionel Sambuc 	if (devind < 0 || devind >= nr_pcidev)
24076e7bb628SLionel Sambuc 		return EINVAL;
24086e7bb628SLionel Sambuc 
24096e7bb628SLionel Sambuc 	p= label;
24106e7bb628SLionel Sambuc 	end= label+sizeof(label);
24116e7bb628SLionel Sambuc 
24126e7bb628SLionel Sambuc 	/* FIXME: domain nb is always 0 on 32bit system, but we should
24136e7bb628SLionel Sambuc 	 *        retrieve it properly, somehow. */
24146e7bb628SLionel Sambuc 	ntostr(0, &p, end);
24156e7bb628SLionel Sambuc 	*p++= '.';
24166e7bb628SLionel Sambuc 
24176e7bb628SLionel Sambuc 	ntostr(pcidev[devind].pd_busnr, &p, end);
24186e7bb628SLionel Sambuc 	*p++= '.';
24196e7bb628SLionel Sambuc 
24206e7bb628SLionel Sambuc 	ntostr(pcidev[devind].pd_dev, &p, end);
24216e7bb628SLionel Sambuc 	*p++= '.';
24226e7bb628SLionel Sambuc 
24236e7bb628SLionel Sambuc 	ntostr(pcidev[devind].pd_func, &p, end);
24246e7bb628SLionel Sambuc 
24256e7bb628SLionel Sambuc 	*cpp= label;
24266e7bb628SLionel Sambuc 	return OK;
24276e7bb628SLionel Sambuc }
24286e7bb628SLionel Sambuc 
24296e7bb628SLionel Sambuc /*===========================================================================*
24306e7bb628SLionel Sambuc  *				_pci_dev_name				     *
24316e7bb628SLionel Sambuc  *===========================================================================*/
24326e7bb628SLionel Sambuc const char *
_pci_dev_name(u16_t vid,u16_t did)24336e7bb628SLionel Sambuc _pci_dev_name(u16_t vid, u16_t did)
24346e7bb628SLionel Sambuc {
24350a6a1f1dSLionel Sambuc 	static char product[PCI_PRODUCTSTR_LEN];
24360a6a1f1dSLionel Sambuc 	pci_findproduct(product, sizeof(product), vid, did);
24370a6a1f1dSLionel Sambuc 	return product;
24386e7bb628SLionel Sambuc }
24396e7bb628SLionel Sambuc 
24406e7bb628SLionel Sambuc /*===========================================================================*
24416e7bb628SLionel Sambuc  *				_pci_get_bar				     *
24426e7bb628SLionel Sambuc  *===========================================================================*/
24436e7bb628SLionel Sambuc int
_pci_get_bar(int devind,int port,u32_t * base,u32_t * size,int * ioflag)24446e7bb628SLionel Sambuc _pci_get_bar(int devind, int port, u32_t *base, u32_t *size,
24456e7bb628SLionel Sambuc 	int *ioflag)
24466e7bb628SLionel Sambuc {
24476e7bb628SLionel Sambuc 	int i, reg;
24486e7bb628SLionel Sambuc 
24496e7bb628SLionel Sambuc 	if (devind < 0 || devind >= nr_pcidev)
24506e7bb628SLionel Sambuc 		return EINVAL;
24516e7bb628SLionel Sambuc 
24526e7bb628SLionel Sambuc 	for (i= 0; i < pcidev[devind].pd_bar_nr; i++)
24536e7bb628SLionel Sambuc 	{
24546e7bb628SLionel Sambuc 		reg= PCI_BAR+4*pcidev[devind].pd_bar[i].pb_nr;
24556e7bb628SLionel Sambuc 
24566e7bb628SLionel Sambuc 		if (reg == port)
24576e7bb628SLionel Sambuc 		{
24586e7bb628SLionel Sambuc 			if (pcidev[devind].pd_bar[i].pb_flags & PBF_INCOMPLETE)
24596e7bb628SLionel Sambuc 				return EINVAL;
24606e7bb628SLionel Sambuc 
24616e7bb628SLionel Sambuc 			*base= pcidev[devind].pd_bar[i].pb_base;
24626e7bb628SLionel Sambuc 			*size= pcidev[devind].pd_bar[i].pb_size;
24636e7bb628SLionel Sambuc 			*ioflag=
24646e7bb628SLionel Sambuc 				!!(pcidev[devind].pd_bar[i].pb_flags & PBF_IO);
24656e7bb628SLionel Sambuc 			return OK;
24666e7bb628SLionel Sambuc 		}
24676e7bb628SLionel Sambuc 	}
24686e7bb628SLionel Sambuc 	return EINVAL;
24696e7bb628SLionel Sambuc }
24706e7bb628SLionel Sambuc 
24716e7bb628SLionel Sambuc /*===========================================================================*
24726e7bb628SLionel Sambuc  *				_pci_attr_r8				     *
24736e7bb628SLionel Sambuc  *===========================================================================*/
24746e7bb628SLionel Sambuc int
_pci_attr_r8(int devind,int port,u8_t * vp)24756e7bb628SLionel Sambuc _pci_attr_r8(int devind, int port, u8_t *vp)
24766e7bb628SLionel Sambuc {
24776e7bb628SLionel Sambuc 	if (devind < 0 || devind >= nr_pcidev)
24786e7bb628SLionel Sambuc 		return EINVAL;
24796e7bb628SLionel Sambuc 	if (port < 0 || port > 256-1)
24806e7bb628SLionel Sambuc 		return EINVAL;
24816e7bb628SLionel Sambuc 
24826e7bb628SLionel Sambuc 	*vp= __pci_attr_r8(devind, port);
24836e7bb628SLionel Sambuc 	return OK;
24846e7bb628SLionel Sambuc }
24856e7bb628SLionel Sambuc 
24866e7bb628SLionel Sambuc /*===========================================================================*
24876e7bb628SLionel Sambuc  *				_pci_attr_r16				     *
24886e7bb628SLionel Sambuc  *===========================================================================*/
24896e7bb628SLionel Sambuc int
_pci_attr_r16(int devind,int port,u16_t * vp)24906e7bb628SLionel Sambuc _pci_attr_r16(int devind, int port, u16_t *vp)
24916e7bb628SLionel Sambuc {
24926e7bb628SLionel Sambuc 	if (devind < 0 || devind >= nr_pcidev)
24936e7bb628SLionel Sambuc 		return EINVAL;
24946e7bb628SLionel Sambuc 	if (port < 0 || port > 256-2)
24956e7bb628SLionel Sambuc 		return EINVAL;
24966e7bb628SLionel Sambuc 
24976e7bb628SLionel Sambuc 	*vp= __pci_attr_r16(devind, port);
24986e7bb628SLionel Sambuc 	return OK;
24996e7bb628SLionel Sambuc }
25006e7bb628SLionel Sambuc 
25016e7bb628SLionel Sambuc /*===========================================================================*
25026e7bb628SLionel Sambuc  *				_pci_attr_r32				     *
25036e7bb628SLionel Sambuc  *===========================================================================*/
25046e7bb628SLionel Sambuc int
_pci_attr_r32(int devind,int port,u32_t * vp)25056e7bb628SLionel Sambuc _pci_attr_r32(int devind, int port, u32_t *vp)
25066e7bb628SLionel Sambuc {
25076e7bb628SLionel Sambuc 	if (devind < 0 || devind >= nr_pcidev)
25086e7bb628SLionel Sambuc 		return EINVAL;
25096e7bb628SLionel Sambuc 	if (port < 0 || port > 256-4)
25106e7bb628SLionel Sambuc 		return EINVAL;
25116e7bb628SLionel Sambuc 
25126e7bb628SLionel Sambuc 	*vp= __pci_attr_r32(devind, port);
25136e7bb628SLionel Sambuc 	return OK;
25146e7bb628SLionel Sambuc }
25156e7bb628SLionel Sambuc 
25166e7bb628SLionel Sambuc /*===========================================================================*
25176e7bb628SLionel Sambuc  *				_pci_attr_w8				     *
25186e7bb628SLionel Sambuc  *===========================================================================*/
25196e7bb628SLionel Sambuc int
_pci_attr_w8(int devind,int port,u8_t value)25206e7bb628SLionel Sambuc _pci_attr_w8(int devind, int port, u8_t value)
25216e7bb628SLionel Sambuc {
25226e7bb628SLionel Sambuc 	if (devind < 0 || devind >= nr_pcidev)
25236e7bb628SLionel Sambuc 		return EINVAL;
25246e7bb628SLionel Sambuc 	if (port < 0 || port > 256-1)
25256e7bb628SLionel Sambuc 		return EINVAL;
25266e7bb628SLionel Sambuc 
25276e7bb628SLionel Sambuc 	__pci_attr_w8(devind, port, value);
25286e7bb628SLionel Sambuc 	return OK;
25296e7bb628SLionel Sambuc }
25306e7bb628SLionel Sambuc 
25316e7bb628SLionel Sambuc /*===========================================================================*
25326e7bb628SLionel Sambuc  *				_pci_attr_w16				     *
25336e7bb628SLionel Sambuc  *===========================================================================*/
25346e7bb628SLionel Sambuc int
_pci_attr_w16(int devind,int port,u16_t value)25356e7bb628SLionel Sambuc _pci_attr_w16(int devind, int port, u16_t value)
25366e7bb628SLionel Sambuc {
25376e7bb628SLionel Sambuc 	if (devind < 0 || devind >= nr_pcidev)
25386e7bb628SLionel Sambuc 		return EINVAL;
25396e7bb628SLionel Sambuc 	if (port < 0 || port > 256-2)
25406e7bb628SLionel Sambuc 		return EINVAL;
25416e7bb628SLionel Sambuc 
25426e7bb628SLionel Sambuc 	__pci_attr_w16(devind, port, value);
25436e7bb628SLionel Sambuc 	return OK;
25446e7bb628SLionel Sambuc }
25456e7bb628SLionel Sambuc 
25466e7bb628SLionel Sambuc /*===========================================================================*
25476e7bb628SLionel Sambuc  *				_pci_attr_w32				     *
25486e7bb628SLionel Sambuc  *===========================================================================*/
25496e7bb628SLionel Sambuc int
_pci_attr_w32(int devind,int port,u32_t value)25506e7bb628SLionel Sambuc _pci_attr_w32(int devind, int port, u32_t value)
25516e7bb628SLionel Sambuc {
25526e7bb628SLionel Sambuc 	if (devind < 0 || devind >= nr_pcidev)
25536e7bb628SLionel Sambuc 		return EINVAL;
25546e7bb628SLionel Sambuc 	if (port < 0 || port > 256-4)
25556e7bb628SLionel Sambuc 		return EINVAL;
25566e7bb628SLionel Sambuc 
25576e7bb628SLionel Sambuc 	__pci_attr_w32(devind, port, value);
25586e7bb628SLionel Sambuc 	return OK;
25596e7bb628SLionel Sambuc }
2560