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