|
@@ -171,8 +171,20 @@ void adjust_pci_device ( struct pci_device *pci ) {
|
171
|
171
|
* @ret rc Return status code
|
172
|
172
|
*/
|
173
|
173
|
int pci_read_config ( struct pci_device *pci ) {
|
|
174
|
+ uint16_t busdevfn;
|
|
175
|
+ uint8_t hdrtype;
|
174
|
176
|
uint32_t tmp;
|
175
|
177
|
|
|
178
|
+ /* Ignore all but the first function on non-multifunction devices */
|
|
179
|
+ if ( PCI_FUNC ( pci->busdevfn ) != 0 ) {
|
|
180
|
+ busdevfn = pci->busdevfn;
|
|
181
|
+ pci->busdevfn = PCI_FIRST_FUNC ( pci->busdevfn );
|
|
182
|
+ pci_read_config_byte ( pci, PCI_HEADER_TYPE, &hdrtype );
|
|
183
|
+ pci->busdevfn = busdevfn;
|
|
184
|
+ if ( ! ( hdrtype & 0x80 ) )
|
|
185
|
+ return -ENODEV;
|
|
186
|
+ }
|
|
187
|
+
|
176
|
188
|
/* Check for physical device presence */
|
177
|
189
|
pci_read_config_dword ( pci, PCI_VENDOR_ID, &tmp );
|
178
|
190
|
if ( ( tmp == 0xffffffff ) || ( tmp == 0 ) )
|
|
@@ -203,6 +215,32 @@ int pci_read_config ( struct pci_device *pci ) {
|
203
|
215
|
return 0;
|
204
|
216
|
}
|
205
|
217
|
|
|
218
|
+/**
|
|
219
|
+ * Find next device on PCI bus
|
|
220
|
+ *
|
|
221
|
+ * @v pci PCI device to fill in
|
|
222
|
+ * @v busdevfn Starting bus:dev.fn address
|
|
223
|
+ * @ret busdevfn Bus:dev.fn address of next PCI device, or negative error
|
|
224
|
+ */
|
|
225
|
+int pci_find_next ( struct pci_device *pci, unsigned int busdevfn ) {
|
|
226
|
+ static unsigned int end;
|
|
227
|
+ int rc;
|
|
228
|
+
|
|
229
|
+ /* Determine number of PCI buses */
|
|
230
|
+ if ( ! end )
|
|
231
|
+ end = PCI_BUSDEVFN ( pci_num_bus(), 0, 0 );
|
|
232
|
+
|
|
233
|
+ /* Find next PCI device, if any */
|
|
234
|
+ for ( ; busdevfn < end ; busdevfn++ ) {
|
|
235
|
+ memset ( pci, 0, sizeof ( *pci ) );
|
|
236
|
+ pci_init ( pci, busdevfn );
|
|
237
|
+ if ( ( rc = pci_read_config ( pci ) ) == 0 )
|
|
238
|
+ return busdevfn;
|
|
239
|
+ }
|
|
240
|
+
|
|
241
|
+ return -ENODEV;
|
|
242
|
+}
|
|
243
|
+
|
206
|
244
|
/**
|
207
|
245
|
* Find driver for PCI device
|
208
|
246
|
*
|
|
@@ -276,14 +314,10 @@ void pci_remove ( struct pci_device *pci ) {
|
276
|
314
|
*/
|
277
|
315
|
static int pcibus_probe ( struct root_device *rootdev ) {
|
278
|
316
|
struct pci_device *pci = NULL;
|
279
|
|
- unsigned int num_bus;
|
280
|
|
- unsigned int busdevfn;
|
281
|
|
- uint8_t hdrtype = 0;
|
|
317
|
+ int busdevfn = 0;
|
282
|
318
|
int rc;
|
283
|
319
|
|
284
|
|
- num_bus = pci_num_bus();
|
285
|
|
- for ( busdevfn = 0 ; busdevfn < PCI_BUSDEVFN ( num_bus, 0, 0 ) ;
|
286
|
|
- busdevfn++ ) {
|
|
320
|
+ for ( busdevfn = 0 ; 1 ; busdevfn++ ) {
|
287
|
321
|
|
288
|
322
|
/* Allocate struct pci_device */
|
289
|
323
|
if ( ! pci )
|
|
@@ -292,22 +326,11 @@ static int pcibus_probe ( struct root_device *rootdev ) {
|
292
|
326
|
rc = -ENOMEM;
|
293
|
327
|
goto err;
|
294
|
328
|
}
|
295
|
|
- memset ( pci, 0, sizeof ( *pci ) );
|
296
|
|
- pci_init ( pci, busdevfn );
|
297
|
|
-
|
298
|
|
- /* Skip all but the first function on
|
299
|
|
- * non-multifunction cards
|
300
|
|
- */
|
301
|
|
- if ( PCI_FUNC ( busdevfn ) == 0 ) {
|
302
|
|
- pci_read_config_byte ( pci, PCI_HEADER_TYPE,
|
303
|
|
- &hdrtype );
|
304
|
|
- } else if ( ! ( hdrtype & 0x80 ) ) {
|
305
|
|
- continue;
|
306
|
|
- }
|
307
|
329
|
|
308
|
|
- /* Read device configuration */
|
309
|
|
- if ( ( rc = pci_read_config ( pci ) ) != 0 )
|
310
|
|
- continue;
|
|
330
|
+ /* Find next PCI device, if any */
|
|
331
|
+ busdevfn = pci_find_next ( pci, busdevfn );
|
|
332
|
+ if ( busdevfn < 0 )
|
|
333
|
+ break;
|
311
|
334
|
|
312
|
335
|
/* Look for a driver */
|
313
|
336
|
if ( ( rc = pci_find_driver ( pci ) ) != 0 ) {
|