1*8044SWilliam.Kucharski@Sun.COM
2*8044SWilliam.Kucharski@Sun.COM /*
3*8044SWilliam.Kucharski@Sun.COM * This program is free software; you can redistribute it and/or
4*8044SWilliam.Kucharski@Sun.COM * modify it under the terms of the GNU General Public License as
5*8044SWilliam.Kucharski@Sun.COM * published by the Free Software Foundation; either version 2, or (at
6*8044SWilliam.Kucharski@Sun.COM * your option) any later version.
7*8044SWilliam.Kucharski@Sun.COM */
8*8044SWilliam.Kucharski@Sun.COM
9*8044SWilliam.Kucharski@Sun.COM #include "grub.h"
10*8044SWilliam.Kucharski@Sun.COM #include "pci.h"
11*8044SWilliam.Kucharski@Sun.COM
12*8044SWilliam.Kucharski@Sun.COM unsigned long virt_offset = 0;
virt_to_phys(volatile const void * virt_addr)13*8044SWilliam.Kucharski@Sun.COM unsigned long virt_to_phys(volatile const void *virt_addr)
14*8044SWilliam.Kucharski@Sun.COM {
15*8044SWilliam.Kucharski@Sun.COM return ((unsigned long)virt_addr) + virt_offset;
16*8044SWilliam.Kucharski@Sun.COM }
17*8044SWilliam.Kucharski@Sun.COM
phys_to_virt(unsigned long phys_addr)18*8044SWilliam.Kucharski@Sun.COM void *phys_to_virt(unsigned long phys_addr)
19*8044SWilliam.Kucharski@Sun.COM {
20*8044SWilliam.Kucharski@Sun.COM return (void *)(phys_addr - virt_offset);
21*8044SWilliam.Kucharski@Sun.COM }
22*8044SWilliam.Kucharski@Sun.COM
23*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_3C595
24*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver t595_driver;
25*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_3C595 */
26*8044SWilliam.Kucharski@Sun.COM
27*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_3C90X
28*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver a3c90x_driver;
29*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_3C90X */
30*8044SWilliam.Kucharski@Sun.COM
31*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_DAVICOM
32*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver davicom_driver;
33*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_DAVICOM */
34*8044SWilliam.Kucharski@Sun.COM
35*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_E1000
36*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver e1000_driver;
37*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_E1000 */
38*8044SWilliam.Kucharski@Sun.COM
39*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_EEPRO100
40*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver eepro100_driver;
41*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_EEPRO100 */
42*8044SWilliam.Kucharski@Sun.COM
43*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_EPIC100
44*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver epic100_driver;
45*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_EPIC100 */
46*8044SWilliam.Kucharski@Sun.COM
47*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_FORCEDETH
48*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver forcedeth_driver;
49*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_FORCEDETH */
50*8044SWilliam.Kucharski@Sun.COM
51*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_NATSEMI
52*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver natsemi_driver;
53*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_NATSEMI */
54*8044SWilliam.Kucharski@Sun.COM
55*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_NS83820
56*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver ns83820_driver;
57*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_NS83820 */
58*8044SWilliam.Kucharski@Sun.COM
59*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_NS8390
60*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver nepci_driver;
61*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_NS8390 */
62*8044SWilliam.Kucharski@Sun.COM
63*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_PCNET32
64*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver pcnet32_driver;
65*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_PCNET32 */
66*8044SWilliam.Kucharski@Sun.COM
67*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_PNIC
68*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver pnic_driver;
69*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_PNIC */
70*8044SWilliam.Kucharski@Sun.COM
71*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_RTL8139
72*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver rtl8139_driver;
73*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_RTL8139 */
74*8044SWilliam.Kucharski@Sun.COM
75*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_SIS900
76*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver sis900_driver;
77*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver sis_bridge_driver;
78*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_SIS900 */
79*8044SWilliam.Kucharski@Sun.COM
80*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_SUNDANCE
81*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver sundance_driver;
82*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_SUNDANCE */
83*8044SWilliam.Kucharski@Sun.COM
84*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_TG3
85*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver tg3_driver;
86*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_TG3 */
87*8044SWilliam.Kucharski@Sun.COM
88*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_TLAN
89*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver tlan_driver;
90*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_TLAN */
91*8044SWilliam.Kucharski@Sun.COM
92*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_TULIP
93*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver tulip_driver;
94*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_TULIP */
95*8044SWilliam.Kucharski@Sun.COM
96*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_UNDI
97*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver undi_driver;
98*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_UNDI */
99*8044SWilliam.Kucharski@Sun.COM
100*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_VIA_RHINE
101*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver rhine_driver;
102*8044SWilliam.Kucharski@Sun.COM #endif/* INCLUDE_VIA_RHINE */
103*8044SWilliam.Kucharski@Sun.COM
104*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_W89C840
105*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver w89c840_driver;
106*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_W89C840 */
107*8044SWilliam.Kucharski@Sun.COM
108*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_R8169
109*8044SWilliam.Kucharski@Sun.COM extern struct pci_driver r8169_driver;
110*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_R8169 */
111*8044SWilliam.Kucharski@Sun.COM
112*8044SWilliam.Kucharski@Sun.COM static const struct pci_driver *pci_drivers[] = {
113*8044SWilliam.Kucharski@Sun.COM
114*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_3C595
115*8044SWilliam.Kucharski@Sun.COM &t595_driver,
116*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_3C595 */
117*8044SWilliam.Kucharski@Sun.COM
118*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_3C90X
119*8044SWilliam.Kucharski@Sun.COM &a3c90x_driver,
120*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_3C90X */
121*8044SWilliam.Kucharski@Sun.COM
122*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_DAVICOM
123*8044SWilliam.Kucharski@Sun.COM &davicom_driver,
124*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_DAVICOM */
125*8044SWilliam.Kucharski@Sun.COM
126*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_E1000
127*8044SWilliam.Kucharski@Sun.COM &e1000_driver,
128*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_E1000 */
129*8044SWilliam.Kucharski@Sun.COM
130*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_EEPRO100
131*8044SWilliam.Kucharski@Sun.COM &eepro100_driver,
132*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_EEPRO100 */
133*8044SWilliam.Kucharski@Sun.COM
134*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_EPIC100
135*8044SWilliam.Kucharski@Sun.COM &epic100_driver,
136*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_EPIC100 */
137*8044SWilliam.Kucharski@Sun.COM
138*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_FORCEDETH
139*8044SWilliam.Kucharski@Sun.COM &forcedeth_driver,
140*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_FORCEDETH */
141*8044SWilliam.Kucharski@Sun.COM
142*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_NATSEMI
143*8044SWilliam.Kucharski@Sun.COM &natsemi_driver,
144*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_NATSEMI */
145*8044SWilliam.Kucharski@Sun.COM
146*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_NS83820
147*8044SWilliam.Kucharski@Sun.COM &ns83820_driver,
148*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_NS83820 */
149*8044SWilliam.Kucharski@Sun.COM
150*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_NS8390
151*8044SWilliam.Kucharski@Sun.COM &nepci_driver,
152*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_NS8390 */
153*8044SWilliam.Kucharski@Sun.COM
154*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_PCNET32
155*8044SWilliam.Kucharski@Sun.COM &pcnet32_driver,
156*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_PCNET32 */
157*8044SWilliam.Kucharski@Sun.COM
158*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_PNIC
159*8044SWilliam.Kucharski@Sun.COM &pnic_driver,
160*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_PNIC */
161*8044SWilliam.Kucharski@Sun.COM
162*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_RTL8139
163*8044SWilliam.Kucharski@Sun.COM &rtl8139_driver,
164*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_RTL8139 */
165*8044SWilliam.Kucharski@Sun.COM
166*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_SIS900
167*8044SWilliam.Kucharski@Sun.COM &sis900_driver,
168*8044SWilliam.Kucharski@Sun.COM &sis_bridge_driver,
169*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_SIS900 */
170*8044SWilliam.Kucharski@Sun.COM
171*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_SUNDANCE
172*8044SWilliam.Kucharski@Sun.COM &sundance_driver,
173*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_SUNDANCE */
174*8044SWilliam.Kucharski@Sun.COM
175*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_TG3
176*8044SWilliam.Kucharski@Sun.COM & tg3_driver,
177*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_TG3 */
178*8044SWilliam.Kucharski@Sun.COM
179*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_TLAN
180*8044SWilliam.Kucharski@Sun.COM &tlan_driver,
181*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_TLAN */
182*8044SWilliam.Kucharski@Sun.COM
183*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_TULIP
184*8044SWilliam.Kucharski@Sun.COM & tulip_driver,
185*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_TULIP */
186*8044SWilliam.Kucharski@Sun.COM
187*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_VIA_RHINE
188*8044SWilliam.Kucharski@Sun.COM &rhine_driver,
189*8044SWilliam.Kucharski@Sun.COM #endif/* INCLUDE_VIA_RHINE */
190*8044SWilliam.Kucharski@Sun.COM
191*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_W89C840
192*8044SWilliam.Kucharski@Sun.COM &w89c840_driver,
193*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_W89C840 */
194*8044SWilliam.Kucharski@Sun.COM
195*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_R8169
196*8044SWilliam.Kucharski@Sun.COM &r8169_driver,
197*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_R8169 */
198*8044SWilliam.Kucharski@Sun.COM
199*8044SWilliam.Kucharski@Sun.COM /* We must be the last one */
200*8044SWilliam.Kucharski@Sun.COM #ifdef INCLUDE_UNDI
201*8044SWilliam.Kucharski@Sun.COM &undi_driver,
202*8044SWilliam.Kucharski@Sun.COM #endif /* INCLUDE_UNDI */
203*8044SWilliam.Kucharski@Sun.COM
204*8044SWilliam.Kucharski@Sun.COM 0
205*8044SWilliam.Kucharski@Sun.COM };
206*8044SWilliam.Kucharski@Sun.COM
scan_drivers(int type,uint32_t class,uint16_t vendor,uint16_t device,const struct pci_driver * last_driver,struct pci_device * dev)207*8044SWilliam.Kucharski@Sun.COM static void scan_drivers(
208*8044SWilliam.Kucharski@Sun.COM int type,
209*8044SWilliam.Kucharski@Sun.COM uint32_t class, uint16_t vendor, uint16_t device,
210*8044SWilliam.Kucharski@Sun.COM const struct pci_driver *last_driver, struct pci_device *dev)
211*8044SWilliam.Kucharski@Sun.COM {
212*8044SWilliam.Kucharski@Sun.COM const struct pci_driver *skip_driver = last_driver;
213*8044SWilliam.Kucharski@Sun.COM /* Assume there is only one match of the correct type */
214*8044SWilliam.Kucharski@Sun.COM const struct pci_driver *driver;
215*8044SWilliam.Kucharski@Sun.COM int i, j;
216*8044SWilliam.Kucharski@Sun.COM
217*8044SWilliam.Kucharski@Sun.COM for(j = 0; pci_drivers[j] != 0; j++){
218*8044SWilliam.Kucharski@Sun.COM driver = pci_drivers[j];
219*8044SWilliam.Kucharski@Sun.COM if (driver->type != type)
220*8044SWilliam.Kucharski@Sun.COM continue;
221*8044SWilliam.Kucharski@Sun.COM if (skip_driver) {
222*8044SWilliam.Kucharski@Sun.COM if (skip_driver == driver)
223*8044SWilliam.Kucharski@Sun.COM skip_driver = 0;
224*8044SWilliam.Kucharski@Sun.COM continue;
225*8044SWilliam.Kucharski@Sun.COM }
226*8044SWilliam.Kucharski@Sun.COM for(i = 0; i < driver->id_count; i++) {
227*8044SWilliam.Kucharski@Sun.COM if ((vendor == driver->ids[i].vendor) &&
228*8044SWilliam.Kucharski@Sun.COM (device == driver->ids[i].dev_id)) {
229*8044SWilliam.Kucharski@Sun.COM
230*8044SWilliam.Kucharski@Sun.COM dev->driver = driver;
231*8044SWilliam.Kucharski@Sun.COM dev->name = driver->ids[i].name;
232*8044SWilliam.Kucharski@Sun.COM
233*8044SWilliam.Kucharski@Sun.COM goto out;
234*8044SWilliam.Kucharski@Sun.COM }
235*8044SWilliam.Kucharski@Sun.COM }
236*8044SWilliam.Kucharski@Sun.COM }
237*8044SWilliam.Kucharski@Sun.COM if (!class) {
238*8044SWilliam.Kucharski@Sun.COM goto out;
239*8044SWilliam.Kucharski@Sun.COM }
240*8044SWilliam.Kucharski@Sun.COM for(j = 0; pci_drivers[j] != 0; j++){
241*8044SWilliam.Kucharski@Sun.COM driver = pci_drivers[j];
242*8044SWilliam.Kucharski@Sun.COM if (driver->type != type)
243*8044SWilliam.Kucharski@Sun.COM continue;
244*8044SWilliam.Kucharski@Sun.COM if (skip_driver) {
245*8044SWilliam.Kucharski@Sun.COM if (skip_driver == driver)
246*8044SWilliam.Kucharski@Sun.COM skip_driver = 0;
247*8044SWilliam.Kucharski@Sun.COM continue;
248*8044SWilliam.Kucharski@Sun.COM }
249*8044SWilliam.Kucharski@Sun.COM if (last_driver == driver)
250*8044SWilliam.Kucharski@Sun.COM continue;
251*8044SWilliam.Kucharski@Sun.COM if ((class >> 8) == driver->class) {
252*8044SWilliam.Kucharski@Sun.COM dev->driver = driver;
253*8044SWilliam.Kucharski@Sun.COM dev->name = driver->name;
254*8044SWilliam.Kucharski@Sun.COM goto out;
255*8044SWilliam.Kucharski@Sun.COM }
256*8044SWilliam.Kucharski@Sun.COM }
257*8044SWilliam.Kucharski@Sun.COM out:
258*8044SWilliam.Kucharski@Sun.COM return;
259*8044SWilliam.Kucharski@Sun.COM }
260*8044SWilliam.Kucharski@Sun.COM
scan_pci_bus(int type,struct pci_device * dev)261*8044SWilliam.Kucharski@Sun.COM void scan_pci_bus(int type, struct pci_device *dev)
262*8044SWilliam.Kucharski@Sun.COM {
263*8044SWilliam.Kucharski@Sun.COM unsigned int first_bus, first_devfn;
264*8044SWilliam.Kucharski@Sun.COM const struct pci_driver *first_driver;
265*8044SWilliam.Kucharski@Sun.COM unsigned int devfn, bus, buses;
266*8044SWilliam.Kucharski@Sun.COM unsigned char hdr_type = 0;
267*8044SWilliam.Kucharski@Sun.COM uint32_t class;
268*8044SWilliam.Kucharski@Sun.COM uint16_t vendor, device;
269*8044SWilliam.Kucharski@Sun.COM uint32_t l, membase, ioaddr, romaddr;
270*8044SWilliam.Kucharski@Sun.COM int reg;
271*8044SWilliam.Kucharski@Sun.COM
272*8044SWilliam.Kucharski@Sun.COM EnterFunction("scan_pci_bus");
273*8044SWilliam.Kucharski@Sun.COM first_bus = 0;
274*8044SWilliam.Kucharski@Sun.COM first_devfn = 0;
275*8044SWilliam.Kucharski@Sun.COM first_driver = 0;
276*8044SWilliam.Kucharski@Sun.COM if (dev->driver) {
277*8044SWilliam.Kucharski@Sun.COM first_driver = dev->driver;
278*8044SWilliam.Kucharski@Sun.COM first_bus = dev->bus;
279*8044SWilliam.Kucharski@Sun.COM first_devfn = dev->devfn;
280*8044SWilliam.Kucharski@Sun.COM /* Re read the header type on a restart */
281*8044SWilliam.Kucharski@Sun.COM pcibios_read_config_byte(first_bus, first_devfn & ~0x7,
282*8044SWilliam.Kucharski@Sun.COM PCI_HEADER_TYPE, &hdr_type);
283*8044SWilliam.Kucharski@Sun.COM dev->driver = 0;
284*8044SWilliam.Kucharski@Sun.COM dev->bus = 0;
285*8044SWilliam.Kucharski@Sun.COM dev->devfn = 0;
286*8044SWilliam.Kucharski@Sun.COM }
287*8044SWilliam.Kucharski@Sun.COM
288*8044SWilliam.Kucharski@Sun.COM /* Scan all PCI buses, until we find our card.
289*8044SWilliam.Kucharski@Sun.COM * We could be smart only scan the required buses but that
290*8044SWilliam.Kucharski@Sun.COM * is error prone, and tricky.
291*8044SWilliam.Kucharski@Sun.COM * By scanning all possible pci buses in order we should find
292*8044SWilliam.Kucharski@Sun.COM * our card eventually.
293*8044SWilliam.Kucharski@Sun.COM */
294*8044SWilliam.Kucharski@Sun.COM buses=256;
295*8044SWilliam.Kucharski@Sun.COM for (bus = first_bus; bus < buses; ++bus) {
296*8044SWilliam.Kucharski@Sun.COM for (devfn = first_devfn; devfn < 0xff; ++devfn, first_driver = 0) {
297*8044SWilliam.Kucharski@Sun.COM if (PCI_FUNC (devfn) == 0)
298*8044SWilliam.Kucharski@Sun.COM pcibios_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type);
299*8044SWilliam.Kucharski@Sun.COM else if (!(hdr_type & 0x80)) /* not a multi-function device */
300*8044SWilliam.Kucharski@Sun.COM continue;
301*8044SWilliam.Kucharski@Sun.COM pcibios_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l);
302*8044SWilliam.Kucharski@Sun.COM /* some broken boards return 0 if a slot is empty: */
303*8044SWilliam.Kucharski@Sun.COM if (l == 0xffffffff || l == 0x00000000) {
304*8044SWilliam.Kucharski@Sun.COM continue;
305*8044SWilliam.Kucharski@Sun.COM }
306*8044SWilliam.Kucharski@Sun.COM vendor = l & 0xffff;
307*8044SWilliam.Kucharski@Sun.COM device = (l >> 16) & 0xffff;
308*8044SWilliam.Kucharski@Sun.COM
309*8044SWilliam.Kucharski@Sun.COM pcibios_read_config_dword(bus, devfn, PCI_REVISION, &l);
310*8044SWilliam.Kucharski@Sun.COM class = (l >> 8) & 0xffffff;
311*8044SWilliam.Kucharski@Sun.COM #if DEBUG
312*8044SWilliam.Kucharski@Sun.COM {
313*8044SWilliam.Kucharski@Sun.COM int i;
314*8044SWilliam.Kucharski@Sun.COM printf("%hhx:%hhx.%hhx [%hX/%hX] ---- ",
315*8044SWilliam.Kucharski@Sun.COM bus, PCI_SLOT(devfn), PCI_FUNC(devfn),
316*8044SWilliam.Kucharski@Sun.COM vendor, device);
317*8044SWilliam.Kucharski@Sun.COM #if DEBUG > 1
318*8044SWilliam.Kucharski@Sun.COM for(i = 0; i < 256; i++) {
319*8044SWilliam.Kucharski@Sun.COM unsigned char byte;
320*8044SWilliam.Kucharski@Sun.COM if ((i & 0xf) == 0) {
321*8044SWilliam.Kucharski@Sun.COM printf("%hhx: ", i);
322*8044SWilliam.Kucharski@Sun.COM }
323*8044SWilliam.Kucharski@Sun.COM pcibios_read_config_byte(bus, devfn, i, &byte);
324*8044SWilliam.Kucharski@Sun.COM printf("%hhx ", byte);
325*8044SWilliam.Kucharski@Sun.COM if ((i & 0xf) == 0xf) {
326*8044SWilliam.Kucharski@Sun.COM printf("\n");
327*8044SWilliam.Kucharski@Sun.COM }
328*8044SWilliam.Kucharski@Sun.COM }
329*8044SWilliam.Kucharski@Sun.COM #endif
330*8044SWilliam.Kucharski@Sun.COM
331*8044SWilliam.Kucharski@Sun.COM }
332*8044SWilliam.Kucharski@Sun.COM #endif
333*8044SWilliam.Kucharski@Sun.COM scan_drivers(type, class, vendor, device, first_driver, dev);
334*8044SWilliam.Kucharski@Sun.COM if (!dev->driver){
335*8044SWilliam.Kucharski@Sun.COM #if DEBUG
336*8044SWilliam.Kucharski@Sun.COM printf("No driver fit.\n");
337*8044SWilliam.Kucharski@Sun.COM #endif
338*8044SWilliam.Kucharski@Sun.COM continue;
339*8044SWilliam.Kucharski@Sun.COM }
340*8044SWilliam.Kucharski@Sun.COM #if DEBUG
341*8044SWilliam.Kucharski@Sun.COM printf("Get Driver:\n");
342*8044SWilliam.Kucharski@Sun.COM #endif
343*8044SWilliam.Kucharski@Sun.COM dev->devfn = devfn;
344*8044SWilliam.Kucharski@Sun.COM dev->bus = bus;
345*8044SWilliam.Kucharski@Sun.COM dev->class = class;
346*8044SWilliam.Kucharski@Sun.COM dev->vendor = vendor;
347*8044SWilliam.Kucharski@Sun.COM dev->dev_id = device;
348*8044SWilliam.Kucharski@Sun.COM
349*8044SWilliam.Kucharski@Sun.COM
350*8044SWilliam.Kucharski@Sun.COM /* Get the ROM base address */
351*8044SWilliam.Kucharski@Sun.COM pcibios_read_config_dword(bus, devfn,
352*8044SWilliam.Kucharski@Sun.COM PCI_ROM_ADDRESS, &romaddr);
353*8044SWilliam.Kucharski@Sun.COM romaddr >>= 10;
354*8044SWilliam.Kucharski@Sun.COM dev->romaddr = romaddr;
355*8044SWilliam.Kucharski@Sun.COM
356*8044SWilliam.Kucharski@Sun.COM /* Get the ``membase'' */
357*8044SWilliam.Kucharski@Sun.COM pcibios_read_config_dword(bus, devfn,
358*8044SWilliam.Kucharski@Sun.COM PCI_BASE_ADDRESS_1, &membase);
359*8044SWilliam.Kucharski@Sun.COM dev->membase = membase;
360*8044SWilliam.Kucharski@Sun.COM
361*8044SWilliam.Kucharski@Sun.COM /* Get the ``ioaddr'' */
362*8044SWilliam.Kucharski@Sun.COM for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
363*8044SWilliam.Kucharski@Sun.COM pcibios_read_config_dword(bus, devfn, reg, &ioaddr);
364*8044SWilliam.Kucharski@Sun.COM if ((ioaddr & PCI_BASE_ADDRESS_IO_MASK) == 0 || (ioaddr & PCI_BASE_ADDRESS_SPACE_IO) == 0)
365*8044SWilliam.Kucharski@Sun.COM continue;
366*8044SWilliam.Kucharski@Sun.COM
367*8044SWilliam.Kucharski@Sun.COM
368*8044SWilliam.Kucharski@Sun.COM /* Strip the I/O address out of the returned value */
369*8044SWilliam.Kucharski@Sun.COM ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
370*8044SWilliam.Kucharski@Sun.COM
371*8044SWilliam.Kucharski@Sun.COM /* Take the first one or the one that matches in boot ROM address */
372*8044SWilliam.Kucharski@Sun.COM dev->ioaddr = ioaddr;
373*8044SWilliam.Kucharski@Sun.COM }
374*8044SWilliam.Kucharski@Sun.COM #if DEBUG > 2
375*8044SWilliam.Kucharski@Sun.COM printf("Found %s ROM address %#hx\n",
376*8044SWilliam.Kucharski@Sun.COM dev->name, romaddr);
377*8044SWilliam.Kucharski@Sun.COM #endif
378*8044SWilliam.Kucharski@Sun.COM LeaveFunction("scan_pci_bus");
379*8044SWilliam.Kucharski@Sun.COM return;
380*8044SWilliam.Kucharski@Sun.COM }
381*8044SWilliam.Kucharski@Sun.COM first_devfn = 0;
382*8044SWilliam.Kucharski@Sun.COM }
383*8044SWilliam.Kucharski@Sun.COM first_bus = 0;
384*8044SWilliam.Kucharski@Sun.COM LeaveFunction("scan_pci_bus");
385*8044SWilliam.Kucharski@Sun.COM }
386*8044SWilliam.Kucharski@Sun.COM
387*8044SWilliam.Kucharski@Sun.COM
388*8044SWilliam.Kucharski@Sun.COM
389*8044SWilliam.Kucharski@Sun.COM /*
390*8044SWilliam.Kucharski@Sun.COM * Set device to be a busmaster in case BIOS neglected to do so.
391*8044SWilliam.Kucharski@Sun.COM * Also adjust PCI latency timer to a reasonable value, 32.
392*8044SWilliam.Kucharski@Sun.COM */
adjust_pci_device(struct pci_device * p)393*8044SWilliam.Kucharski@Sun.COM void adjust_pci_device(struct pci_device *p)
394*8044SWilliam.Kucharski@Sun.COM {
395*8044SWilliam.Kucharski@Sun.COM unsigned short new_command, pci_command;
396*8044SWilliam.Kucharski@Sun.COM unsigned char pci_latency;
397*8044SWilliam.Kucharski@Sun.COM
398*8044SWilliam.Kucharski@Sun.COM pcibios_read_config_word(p->bus, p->devfn, PCI_COMMAND, &pci_command);
399*8044SWilliam.Kucharski@Sun.COM new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
400*8044SWilliam.Kucharski@Sun.COM if (pci_command != new_command) {
401*8044SWilliam.Kucharski@Sun.COM #if DEBUG > 0
402*8044SWilliam.Kucharski@Sun.COM printf(
403*8044SWilliam.Kucharski@Sun.COM "The PCI BIOS has not enabled this device!\n"
404*8044SWilliam.Kucharski@Sun.COM "Updating PCI command %hX->%hX. pci_bus %hhX pci_device_fn %hhX\n",
405*8044SWilliam.Kucharski@Sun.COM pci_command, new_command, p->bus, p->devfn);
406*8044SWilliam.Kucharski@Sun.COM #endif
407*8044SWilliam.Kucharski@Sun.COM pcibios_write_config_word(p->bus, p->devfn, PCI_COMMAND, new_command);
408*8044SWilliam.Kucharski@Sun.COM }
409*8044SWilliam.Kucharski@Sun.COM pcibios_read_config_byte(p->bus, p->devfn, PCI_LATENCY_TIMER, &pci_latency);
410*8044SWilliam.Kucharski@Sun.COM if (pci_latency < 32) {
411*8044SWilliam.Kucharski@Sun.COM #if DEBUG > 0
412*8044SWilliam.Kucharski@Sun.COM printf("PCI latency timer (CFLT) is unreasonably low at %d. Setting to 32 clocks.\n",
413*8044SWilliam.Kucharski@Sun.COM pci_latency);
414*8044SWilliam.Kucharski@Sun.COM #endif
415*8044SWilliam.Kucharski@Sun.COM pcibios_write_config_byte(p->bus, p->devfn, PCI_LATENCY_TIMER, 32);
416*8044SWilliam.Kucharski@Sun.COM }
417*8044SWilliam.Kucharski@Sun.COM }
418*8044SWilliam.Kucharski@Sun.COM
419*8044SWilliam.Kucharski@Sun.COM /*
420*8044SWilliam.Kucharski@Sun.COM * Find the start of a pci resource.
421*8044SWilliam.Kucharski@Sun.COM */
pci_bar_start(struct pci_device * dev,unsigned int index)422*8044SWilliam.Kucharski@Sun.COM unsigned long pci_bar_start(struct pci_device *dev, unsigned int index)
423*8044SWilliam.Kucharski@Sun.COM {
424*8044SWilliam.Kucharski@Sun.COM uint32_t lo, hi;
425*8044SWilliam.Kucharski@Sun.COM unsigned long bar;
426*8044SWilliam.Kucharski@Sun.COM pci_read_config_dword(dev, index, &lo);
427*8044SWilliam.Kucharski@Sun.COM if (lo & PCI_BASE_ADDRESS_SPACE_IO) {
428*8044SWilliam.Kucharski@Sun.COM bar = lo & PCI_BASE_ADDRESS_IO_MASK;
429*8044SWilliam.Kucharski@Sun.COM } else {
430*8044SWilliam.Kucharski@Sun.COM bar = 0;
431*8044SWilliam.Kucharski@Sun.COM if ((lo & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
432*8044SWilliam.Kucharski@Sun.COM pci_read_config_dword(dev, index + 4, &hi);
433*8044SWilliam.Kucharski@Sun.COM if (hi) {
434*8044SWilliam.Kucharski@Sun.COM if (sizeof(unsigned long) > sizeof(uint32_t)) {
435*8044SWilliam.Kucharski@Sun.COM /* It's REALLY interesting:-) */
436*8044SWilliam.Kucharski@Sun.COM bar = (uint64_t)hi << 32;
437*8044SWilliam.Kucharski@Sun.COM }
438*8044SWilliam.Kucharski@Sun.COM else {
439*8044SWilliam.Kucharski@Sun.COM printf("Unhandled 64bit BAR\n");
440*8044SWilliam.Kucharski@Sun.COM return -1UL;
441*8044SWilliam.Kucharski@Sun.COM }
442*8044SWilliam.Kucharski@Sun.COM }
443*8044SWilliam.Kucharski@Sun.COM }
444*8044SWilliam.Kucharski@Sun.COM bar |= lo & PCI_BASE_ADDRESS_MEM_MASK;
445*8044SWilliam.Kucharski@Sun.COM }
446*8044SWilliam.Kucharski@Sun.COM return bar + pcibios_bus_base(dev->bus);
447*8044SWilliam.Kucharski@Sun.COM }
448*8044SWilliam.Kucharski@Sun.COM
449*8044SWilliam.Kucharski@Sun.COM /*
450*8044SWilliam.Kucharski@Sun.COM * Find the size of a pci resource.
451*8044SWilliam.Kucharski@Sun.COM */
pci_bar_size(struct pci_device * dev,unsigned int bar)452*8044SWilliam.Kucharski@Sun.COM unsigned long pci_bar_size(struct pci_device *dev, unsigned int bar)
453*8044SWilliam.Kucharski@Sun.COM {
454*8044SWilliam.Kucharski@Sun.COM uint32_t start, size;
455*8044SWilliam.Kucharski@Sun.COM /* Save the original bar */
456*8044SWilliam.Kucharski@Sun.COM pci_read_config_dword(dev, bar, &start);
457*8044SWilliam.Kucharski@Sun.COM /* Compute which bits can be set */
458*8044SWilliam.Kucharski@Sun.COM pci_write_config_dword(dev, bar, ~0);
459*8044SWilliam.Kucharski@Sun.COM pci_read_config_dword(dev, bar, &size);
460*8044SWilliam.Kucharski@Sun.COM /* Restore the original size */
461*8044SWilliam.Kucharski@Sun.COM pci_write_config_dword(dev, bar, start);
462*8044SWilliam.Kucharski@Sun.COM /* Find the significant bits */
463*8044SWilliam.Kucharski@Sun.COM if (start & PCI_BASE_ADDRESS_SPACE_IO) {
464*8044SWilliam.Kucharski@Sun.COM size &= PCI_BASE_ADDRESS_IO_MASK;
465*8044SWilliam.Kucharski@Sun.COM } else {
466*8044SWilliam.Kucharski@Sun.COM size &= PCI_BASE_ADDRESS_MEM_MASK;
467*8044SWilliam.Kucharski@Sun.COM }
468*8044SWilliam.Kucharski@Sun.COM /* Find the lowest bit set */
469*8044SWilliam.Kucharski@Sun.COM size = size & ~(size - 1);
470*8044SWilliam.Kucharski@Sun.COM return size;
471*8044SWilliam.Kucharski@Sun.COM }
472*8044SWilliam.Kucharski@Sun.COM
473*8044SWilliam.Kucharski@Sun.COM /**
474*8044SWilliam.Kucharski@Sun.COM * pci_find_capability - query for devices' capabilities
475*8044SWilliam.Kucharski@Sun.COM * @dev: PCI device to query
476*8044SWilliam.Kucharski@Sun.COM * @cap: capability code
477*8044SWilliam.Kucharski@Sun.COM *
478*8044SWilliam.Kucharski@Sun.COM * Tell if a device supports a given PCI capability.
479*8044SWilliam.Kucharski@Sun.COM * Returns the address of the requested capability structure within the
480*8044SWilliam.Kucharski@Sun.COM * device's PCI configuration space or 0 in case the device does not
481*8044SWilliam.Kucharski@Sun.COM * support it. Possible values for @cap:
482*8044SWilliam.Kucharski@Sun.COM *
483*8044SWilliam.Kucharski@Sun.COM * %PCI_CAP_ID_PM Power Management
484*8044SWilliam.Kucharski@Sun.COM *
485*8044SWilliam.Kucharski@Sun.COM * %PCI_CAP_ID_AGP Accelerated Graphics Port
486*8044SWilliam.Kucharski@Sun.COM *
487*8044SWilliam.Kucharski@Sun.COM * %PCI_CAP_ID_VPD Vital Product Data
488*8044SWilliam.Kucharski@Sun.COM *
489*8044SWilliam.Kucharski@Sun.COM * %PCI_CAP_ID_SLOTID Slot Identification
490*8044SWilliam.Kucharski@Sun.COM *
491*8044SWilliam.Kucharski@Sun.COM * %PCI_CAP_ID_MSI Message Signalled Interrupts
492*8044SWilliam.Kucharski@Sun.COM *
493*8044SWilliam.Kucharski@Sun.COM * %PCI_CAP_ID_CHSWP CompactPCI HotSwap
494*8044SWilliam.Kucharski@Sun.COM */
pci_find_capability(struct pci_device * dev,int cap)495*8044SWilliam.Kucharski@Sun.COM int pci_find_capability(struct pci_device *dev, int cap)
496*8044SWilliam.Kucharski@Sun.COM {
497*8044SWilliam.Kucharski@Sun.COM uint16_t status;
498*8044SWilliam.Kucharski@Sun.COM uint8_t pos, id;
499*8044SWilliam.Kucharski@Sun.COM uint8_t hdr_type;
500*8044SWilliam.Kucharski@Sun.COM int ttl = 48;
501*8044SWilliam.Kucharski@Sun.COM
502*8044SWilliam.Kucharski@Sun.COM pci_read_config_word(dev, PCI_STATUS, &status);
503*8044SWilliam.Kucharski@Sun.COM if (!(status & PCI_STATUS_CAP_LIST))
504*8044SWilliam.Kucharski@Sun.COM return 0;
505*8044SWilliam.Kucharski@Sun.COM pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type);
506*8044SWilliam.Kucharski@Sun.COM switch (hdr_type & 0x7F) {
507*8044SWilliam.Kucharski@Sun.COM case PCI_HEADER_TYPE_NORMAL:
508*8044SWilliam.Kucharski@Sun.COM case PCI_HEADER_TYPE_BRIDGE:
509*8044SWilliam.Kucharski@Sun.COM default:
510*8044SWilliam.Kucharski@Sun.COM pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &pos);
511*8044SWilliam.Kucharski@Sun.COM break;
512*8044SWilliam.Kucharski@Sun.COM case PCI_HEADER_TYPE_CARDBUS:
513*8044SWilliam.Kucharski@Sun.COM pci_read_config_byte(dev, PCI_CB_CAPABILITY_LIST, &pos);
514*8044SWilliam.Kucharski@Sun.COM break;
515*8044SWilliam.Kucharski@Sun.COM }
516*8044SWilliam.Kucharski@Sun.COM while (ttl-- && pos >= 0x40) {
517*8044SWilliam.Kucharski@Sun.COM pos &= ~3;
518*8044SWilliam.Kucharski@Sun.COM pci_read_config_byte(dev, pos + PCI_CAP_LIST_ID, &id);
519*8044SWilliam.Kucharski@Sun.COM #if DEBUG > 0
520*8044SWilliam.Kucharski@Sun.COM printf("Capability: %d\n", id);
521*8044SWilliam.Kucharski@Sun.COM #endif
522*8044SWilliam.Kucharski@Sun.COM if (id == 0xff)
523*8044SWilliam.Kucharski@Sun.COM break;
524*8044SWilliam.Kucharski@Sun.COM if (id == cap)
525*8044SWilliam.Kucharski@Sun.COM return pos;
526*8044SWilliam.Kucharski@Sun.COM pci_read_config_byte(dev, pos + PCI_CAP_LIST_NEXT, &pos);
527*8044SWilliam.Kucharski@Sun.COM }
528*8044SWilliam.Kucharski@Sun.COM return 0;
529*8044SWilliam.Kucharski@Sun.COM }
530*8044SWilliam.Kucharski@Sun.COM
531