This source file includes following definitions.
- pci_bus_check
- pci_bus_assign
- pci_bus_fixup
- pcibus_print_devid
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/device.h>
37
38 #include <machine/bus.h>
39
40 #include <dev/pci/pcireg.h>
41 #include <dev/pci/pcivar.h>
42 #include <dev/pci/pcidevs.h>
43 #include <dev/pci/ppbreg.h>
44
45 #include <i386/pci/pcibiosvar.h>
46
47 int pci_bus_check(pci_chipset_tag_t, int);
48 int pci_bus_assign(pci_chipset_tag_t, int);
49 void pcibus_print_devid(pci_chipset_tag_t, pcitag_t);
50
51 int
52 pci_bus_check(pci_chipset_tag_t pc, int bus)
53 {
54 int device, maxdevs, function, nfuncs, bus_max, bus_sub;
55 const struct pci_quirkdata *qd;
56 pcireg_t reg;
57 pcitag_t tag;
58
59 bus_max = bus;
60
61 maxdevs = pci_bus_maxdevs(pc, bus);
62 for (device = 0; device < maxdevs; device++) {
63 tag = pci_make_tag(pc, bus, device, 0);
64 reg = pci_conf_read(pc, tag, PCI_ID_REG);
65
66
67 if (bus_max == 255)
68 break;
69
70
71 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID)
72 continue;
73
74 if (PCI_VENDOR(reg) == 0)
75 continue;
76
77 qd = pci_lookup_quirkdata(PCI_VENDOR(reg), PCI_PRODUCT(reg));
78
79 reg = pci_conf_read(pc, tag, PCI_BHLC_REG);
80 if (PCI_HDRTYPE_MULTIFN(reg) ||
81 (qd != NULL &&
82 (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
83 nfuncs = 8;
84 else
85 nfuncs = 1;
86
87 for (function = 0; function < nfuncs; function++) {
88 tag = pci_make_tag(pc, bus, device, function);
89 reg = pci_conf_read(pc, tag, PCI_ID_REG);
90
91
92 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID)
93 continue;
94
95 if (PCI_VENDOR(reg) == 0)
96 continue;
97
98 reg = pci_conf_read(pc, tag, PCI_CLASS_REG);
99 if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE &&
100 (PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI ||
101 PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_CARDBUS)) {
102
103 reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
104 if (PPB_BUSINFO_PRIMARY(reg) != bus) {
105 if (pcibios_flags & PCIBIOS_VERBOSE) {
106 pcibus_print_devid(pc, tag);
107 printf("Mismatched primary bus: "
108 "primary %d, secondary %d, "
109 "subordinate %d\n",
110 PPB_BUSINFO_PRIMARY(reg),
111 PPB_BUSINFO_SECONDARY(reg),
112 PPB_BUSINFO_SUBORDINATE(reg));
113 }
114 return (-1);
115 }
116 if (PPB_BUSINFO_SECONDARY(reg) <= bus) {
117 if (pcibios_flags & PCIBIOS_VERBOSE) {
118 pcibus_print_devid(pc, tag);
119 printf("Incorrect secondary bus: "
120 "primary %d, secondary %d, "
121 "subordinate %d\n",
122 PPB_BUSINFO_PRIMARY(reg),
123 PPB_BUSINFO_SECONDARY(reg),
124 PPB_BUSINFO_SUBORDINATE(reg));
125 }
126 return (-1);
127 }
128
129
130 bus_sub = pci_bus_check(pc,
131 PPB_BUSINFO_SECONDARY(reg));
132 if (bus_sub == -1)
133 return (-1);
134
135 if (PPB_BUSINFO_SUBORDINATE(reg) < bus_sub) {
136 if (pcibios_flags & PCIBIOS_VERBOSE) {
137 pcibus_print_devid(pc, tag);
138 printf("Incorrect subordinate bus %d: "
139 "primary %d, secondary %d, "
140 "subordinate %d\n", bus_sub,
141 PPB_BUSINFO_PRIMARY(reg),
142 PPB_BUSINFO_SECONDARY(reg),
143 PPB_BUSINFO_SUBORDINATE(reg));
144 }
145 return (-1);
146 }
147
148 bus_max = (bus_sub > bus_max) ?
149 bus_sub : bus_max;
150 }
151 }
152 }
153
154 return (bus_max);
155 }
156
157 int
158 pci_bus_assign(pci_chipset_tag_t pc, int bus)
159 {
160 static int bridge_cnt;
161 int bridge, device, maxdevs, function, nfuncs, bus_max, bus_sub;
162 const struct pci_quirkdata *qd;
163 pcireg_t reg;
164 pcitag_t tag;
165
166 bus_max = bus;
167
168 maxdevs = pci_bus_maxdevs(pc, bus);
169 for (device = 0; device < maxdevs; device++) {
170 tag = pci_make_tag(pc, bus, device, 0);
171 reg = pci_conf_read(pc, tag, PCI_ID_REG);
172
173
174 if (bus_max == 255)
175 break;
176
177
178 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID)
179 continue;
180
181 if (PCI_VENDOR(reg) == 0)
182 continue;
183
184 qd = pci_lookup_quirkdata(PCI_VENDOR(reg), PCI_PRODUCT(reg));
185
186 reg = pci_conf_read(pc, tag, PCI_BHLC_REG);
187 if (PCI_HDRTYPE_MULTIFN(reg) ||
188 (qd != NULL &&
189 (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
190 nfuncs = 8;
191 else
192 nfuncs = 1;
193
194 for (function = 0; function < nfuncs; function++) {
195 tag = pci_make_tag(pc, bus, device, function);
196 reg = pci_conf_read(pc, tag, PCI_ID_REG);
197
198
199 if (PCI_VENDOR(reg) == PCI_VENDOR_INVALID)
200 continue;
201
202 if (PCI_VENDOR(reg) == 0)
203 continue;
204
205 reg = pci_conf_read(pc, tag, PCI_CLASS_REG);
206 if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE &&
207 (PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI ||
208 PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_CARDBUS)) {
209
210 bus_max++;
211
212 reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
213 reg &= 0xff000000;
214 reg |= bus | (bus_max << 8) | (0xff << 16);
215 pci_conf_write(pc, tag, PPB_REG_BUSINFO, reg);
216
217
218 bus_sub = pci_bus_assign(pc, bus_max);
219
220
221 reg &= 0xff000000;
222 reg |= bus | (bus_max << 8) | (bus_sub << 16);
223 pci_conf_write(pc, tag, PPB_REG_BUSINFO, reg);
224
225 if (pcibios_flags & PCIBIOS_VERBOSE) {
226
227 bridge = bridge_cnt++;
228
229 printf("PCI bridge %d: primary %d, "
230 "secondary %d, subordinate %d\n",
231 bridge, bus, bus_max, bus_sub);
232 }
233
234
235 bus_max = (bus_sub > bus_max) ?
236 bus_sub : bus_max;
237 }
238 }
239 }
240
241 return (bus_max);
242 }
243
244 int
245 pci_bus_fixup(pci_chipset_tag_t pc, int bus)
246 {
247 int bus_max;
248
249 bus_max = pci_bus_check(pc, bus);
250 if (bus_max != -1)
251 return (bus_max);
252
253 if (pcibios_flags & PCIBIOS_VERBOSE)
254 printf("PCI bus renumbering needed\n");
255 return pci_bus_assign(pc, bus);
256 }
257
258 void
259 pcibus_print_devid(pci_chipset_tag_t pc, pcitag_t tag)
260 {
261 int bus, device, function;
262 pcireg_t id;
263
264 id = pci_conf_read(pc, tag, PCI_ID_REG);
265 pci_decompose_tag(pc, tag, &bus, &device, &function);
266 printf("%03d:%02d:%d %04x:%04x\n", bus, device, function,
267 PCI_VENDOR(id), PCI_PRODUCT(id));
268 }