1 | #ifdef CONFIG_PCI
|
---|
2 |
|
---|
3 | /*
|
---|
4 | * This program is free software; you can redistribute it and/or
|
---|
5 | * modify it under the terms of the GNU General Public License as
|
---|
6 | * published by the Free Software Foundation; either version 2, or (at
|
---|
7 | * your option) any later version.
|
---|
8 | */
|
---|
9 |
|
---|
10 | #include <etherboot.h>
|
---|
11 | #include <pci.h>
|
---|
12 | #include <lib.h>
|
---|
13 |
|
---|
14 | #define DEBUG_THIS DEBUG_PCI
|
---|
15 |
|
---|
16 | #include <debug.h>
|
---|
17 |
|
---|
18 | struct pci_device *dev_list;
|
---|
19 | int n_devs;
|
---|
20 |
|
---|
21 | static void pci_scan_bus(void)
|
---|
22 | {
|
---|
23 |
|
---|
24 | unsigned int first_bus, first_devfn;
|
---|
25 | unsigned int devfn, bus, buses;
|
---|
26 |
|
---|
27 | uint32_t class;
|
---|
28 | uint16_t vendor, dev_id;
|
---|
29 | uint8_t hdr_type;
|
---|
30 |
|
---|
31 |
|
---|
32 | first_bus = 0;
|
---|
33 | first_devfn = 0;
|
---|
34 |
|
---|
35 | buses=256;
|
---|
36 | for (bus = first_bus; bus < buses; ++bus) {
|
---|
37 | for (devfn = first_devfn; devfn < 0xff; ++devfn) {
|
---|
38 |
|
---|
39 | #if 1
|
---|
40 | if (PCI_FUNC(devfn) == 0)
|
---|
41 | pcibios_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type);
|
---|
42 | else if (!(hdr_type & 0x80)) /* not a multi-function device */
|
---|
43 | continue;
|
---|
44 | #endif
|
---|
45 |
|
---|
46 | pcibios_read_config_word(bus,devfn, PCI_VENDOR_ID, &vendor);
|
---|
47 | if (vendor==0xffff || vendor==0)
|
---|
48 | continue;
|
---|
49 |
|
---|
50 | if (dev_list) {
|
---|
51 | dev_list[n_devs].bus = bus;
|
---|
52 | dev_list[n_devs].devfn = devfn;
|
---|
53 | dev_list[n_devs].vendor = vendor;
|
---|
54 |
|
---|
55 | pcibios_read_config_word(bus,devfn, PCI_DEVICE_ID, &dev_id);
|
---|
56 | dev_list[n_devs].dev_id = dev_id;
|
---|
57 |
|
---|
58 | pcibios_read_config_dword(bus,devfn, PCI_CLASS_REVISION, &class);
|
---|
59 | dev_list[n_devs].class = class;
|
---|
60 |
|
---|
61 | }
|
---|
62 | n_devs++;
|
---|
63 | }
|
---|
64 | first_devfn = 0;
|
---|
65 | }
|
---|
66 | first_bus = 0;
|
---|
67 |
|
---|
68 | }
|
---|
69 | #define DEBUG 0
|
---|
70 |
|
---|
71 | void pci_init(void)
|
---|
72 | {
|
---|
73 | /* Count devices */
|
---|
74 | dev_list = 0;
|
---|
75 | n_devs = 0;
|
---|
76 | debug("Scanning PCI: ");
|
---|
77 | pci_scan_bus();
|
---|
78 | debug("found %d devices\n", n_devs);
|
---|
79 |
|
---|
80 | /* Make the list */
|
---|
81 | dev_list = allot(n_devs * sizeof(struct pci_device));
|
---|
82 | n_devs = 0;
|
---|
83 | pci_scan_bus();
|
---|
84 | #if DEBUG
|
---|
85 | {
|
---|
86 | int i;
|
---|
87 | for (i = 0; i < n_devs; i++) {
|
---|
88 | printf("%02x:%02x.%x %04x:%04x %04x %02x\n",
|
---|
89 | dev_list[i].bus,
|
---|
90 | PCI_SLOT(dev_list[i].devfn),
|
---|
91 | PCI_FUNC(dev_list[i].devfn),
|
---|
92 | dev_list[i].vendor,
|
---|
93 | dev_list[i].dev_id,((dev_list[i].class)>>16),
|
---|
94 | ((dev_list[i].class)>>8 & 0xff));
|
---|
95 | }
|
---|
96 | }
|
---|
97 | #endif
|
---|
98 | }
|
---|
99 |
|
---|
100 | struct pci_device *pci_find_device_2(int vendor, int device, int devclass, int devclass2, int prog_if, int index)
|
---|
101 | {
|
---|
102 | int i;
|
---|
103 |
|
---|
104 | for (i=0; i<n_devs; i++) {
|
---|
105 | if (vendor < 0 || vendor==dev_list[i].vendor)
|
---|
106 | if (device < 0 || device==dev_list[i].dev_id)
|
---|
107 | if (devclass < 0 || devclass==((dev_list[i].class)>>16) || devclass2==((dev_list[i].class)>>16))
|
---|
108 | if (prog_if < 0 || prog_if==((dev_list[i].class)>>8 & 0xff)) {
|
---|
109 | if (index == 0)
|
---|
110 | return &dev_list[i];
|
---|
111 | index--;
|
---|
112 | }
|
---|
113 | }
|
---|
114 |
|
---|
115 | return NULL;
|
---|
116 | }
|
---|
117 |
|
---|
118 |
|
---|
119 | struct pci_device *pci_find_device(int vendor, int device, int devclass, int prog_if, int index)
|
---|
120 | {
|
---|
121 | return pci_find_device_2(vendor, device, devclass, devclass, prog_if, index);
|
---|
122 | }
|
---|
123 |
|
---|
124 | #endif
|
---|