Browse Source

[pci] Modularise PCI device support

Some operating environments require (or at least prefer) that we do
not perform our own PCI bus scan, but deal only with specified
devices.  Modularise the PCI core to allow for this.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
4f4c214621
2 changed files with 107 additions and 47 deletions
  1. 79
    47
      src/drivers/bus/pci.c
  2. 28
    0
      src/include/ipxe/pci.h

+ 79
- 47
src/drivers/bus/pci.c View File

164
 }
164
 }
165
 
165
 
166
 /**
166
 /**
167
- * Probe a PCI device
167
+ * Read PCI device configuration
168
  *
168
  *
169
  * @v pci		PCI device
169
  * @v pci		PCI device
170
  * @ret rc		Return status code
170
  * @ret rc		Return status code
171
+ */
172
+int pci_read_config ( struct pci_device *pci ) {
173
+	uint32_t tmp;
174
+
175
+	/* Check for physical device presence */
176
+	pci_read_config_dword ( pci, PCI_VENDOR_ID, &tmp );
177
+	if ( ( tmp == 0xffffffff ) || ( tmp == 0 ) )
178
+		return -ENODEV;
179
+
180
+	/* Populate struct pci_device */
181
+	pci->vendor = ( tmp & 0xffff );
182
+	pci->device = ( tmp >> 16 );
183
+	pci_read_config_dword ( pci, PCI_REVISION, &tmp );
184
+	pci->class = ( tmp >> 8 );
185
+	pci_read_config_byte ( pci, PCI_INTERRUPT_LINE, &pci->irq );
186
+	pci_read_bases ( pci );
187
+
188
+	/* Initialise generic device component */
189
+	snprintf ( pci->dev.name, sizeof ( pci->dev.name ),
190
+		   "PCI%02x:%02x.%x", PCI_BUS ( pci->busdevfn ),
191
+		   PCI_SLOT ( pci->busdevfn ), PCI_FUNC ( pci->busdevfn ) );
192
+	pci->dev.desc.bus_type = BUS_TYPE_PCI;
193
+	pci->dev.desc.location = pci->busdevfn;
194
+	pci->dev.desc.vendor = pci->vendor;
195
+	pci->dev.desc.device = pci->device;
196
+	pci->dev.desc.class = pci->class;
197
+	pci->dev.desc.ioaddr = pci->ioaddr;
198
+	pci->dev.desc.irq = pci->irq;
199
+	INIT_LIST_HEAD ( &pci->dev.siblings );
200
+	INIT_LIST_HEAD ( &pci->dev.children );
201
+
202
+	return 0;
203
+}
204
+
205
+/**
206
+ * Find driver for PCI device
171
  *
207
  *
172
- * Searches for a driver for the PCI device.  If a driver is found,
173
- * its probe() routine is called.
208
+ * @v pci		PCI device
209
+ * @ret rc		Return status code
174
  */
210
  */
175
-static int pci_probe ( struct pci_device *pci ) {
211
+int pci_find_driver ( struct pci_device *pci ) {
176
 	struct pci_driver *driver;
212
 	struct pci_driver *driver;
177
 	struct pci_device_id *id;
213
 	struct pci_device_id *id;
178
 	unsigned int i;
214
 	unsigned int i;
179
-	int rc;
180
-
181
-	DBGC ( pci, PCI_FMT " is %04x:%04x mem %lx io %lx irq %d\n",
182
-	       PCI_ARGS ( pci ), pci->vendor, pci->device, pci->membase,
183
-	       pci->ioaddr, pci->irq );
184
 
215
 
185
 	for_each_table_entry ( driver, PCI_DRIVERS ) {
216
 	for_each_table_entry ( driver, PCI_DRIVERS ) {
186
 		for ( i = 0 ; i < driver->id_count ; i++ ) {
217
 		for ( i = 0 ; i < driver->id_count ; i++ ) {
191
 			if ( ( id->device != PCI_ANY_ID ) &&
222
 			if ( ( id->device != PCI_ANY_ID ) &&
192
 			     ( id->device != pci->device ) )
223
 			     ( id->device != pci->device ) )
193
 				continue;
224
 				continue;
194
-			pci->driver = driver;
195
-			pci->id = id;
196
-			DBGC ( pci, "...using driver %s\n", pci->id->name );
197
-			if ( ( rc = driver->probe ( pci ) ) != 0 ) {
198
-				DBGC ( pci, "......probe failed: %s\n",
199
-				       strerror ( rc ) );
200
-				continue;
201
-			}
202
-			DBGC ( pci, PCI_FMT " added\n", PCI_ARGS ( pci ) );
225
+			pci_set_driver ( pci, driver, id );
203
 			return 0;
226
 			return 0;
204
 		}
227
 		}
205
 	}
228
 	}
229
+	return -ENOENT;
230
+}
206
 
231
 
207
-	DBGC ( pci, "...no driver found\n" );
208
-	return -ENOTTY;
232
+/**
233
+ * Probe a PCI device
234
+ *
235
+ * @v pci		PCI device
236
+ * @ret rc		Return status code
237
+ *
238
+ * Searches for a driver for the PCI device.  If a driver is found,
239
+ * its probe() routine is called.
240
+ */
241
+int pci_probe ( struct pci_device *pci ) {
242
+	int rc;
243
+
244
+	DBGC ( pci, PCI_FMT " (%04x:%04x) has driver \"%s\"\n",
245
+	       PCI_ARGS ( pci ), pci->vendor, pci->device, pci->id->name );
246
+	DBGC ( pci, PCI_FMT " has mem %lx io %lx irq %d\n",
247
+	       PCI_ARGS ( pci ), pci->membase, pci->ioaddr, pci->irq );
248
+
249
+	if ( ( rc = pci->driver->probe ( pci ) ) != 0 ) {
250
+		DBGC ( pci, PCI_FMT " probe failed: %s\n",
251
+		       PCI_ARGS ( pci ), strerror ( rc ) );
252
+		return rc;
253
+	}
254
+
255
+	return 0;
209
 }
256
 }
210
 
257
 
211
 /**
258
 /**
213
  *
260
  *
214
  * @v pci		PCI device
261
  * @v pci		PCI device
215
  */
262
  */
216
-static void pci_remove ( struct pci_device *pci ) {
263
+void pci_remove ( struct pci_device *pci ) {
217
 	pci->driver->remove ( pci );
264
 	pci->driver->remove ( pci );
218
 	DBGC ( pci, PCI_FMT " removed\n", PCI_ARGS ( pci ) );
265
 	DBGC ( pci, PCI_FMT " removed\n", PCI_ARGS ( pci ) );
219
 }
266
 }
231
 	unsigned int num_bus;
278
 	unsigned int num_bus;
232
 	unsigned int busdevfn;
279
 	unsigned int busdevfn;
233
 	uint8_t hdrtype = 0;
280
 	uint8_t hdrtype = 0;
234
-	uint32_t tmp;
235
 	int rc;
281
 	int rc;
236
 
282
 
237
 	num_bus = pci_num_bus();
283
 	num_bus = pci_num_bus();
246
 			goto err;
292
 			goto err;
247
 		}
293
 		}
248
 		memset ( pci, 0, sizeof ( *pci ) );
294
 		memset ( pci, 0, sizeof ( *pci ) );
249
-		pci->busdevfn = busdevfn;
295
+		pci_init ( pci, busdevfn );
250
 			
296
 			
251
 		/* Skip all but the first function on
297
 		/* Skip all but the first function on
252
 		 * non-multifunction cards
298
 		 * non-multifunction cards
258
 			continue;
304
 			continue;
259
 		}
305
 		}
260
 
306
 
261
-		/* Check for physical device presence */
262
-		pci_read_config_dword ( pci, PCI_VENDOR_ID, &tmp );
263
-		if ( ( tmp == 0xffffffff ) || ( tmp == 0 ) )
307
+		/* Read device configuration */
308
+		if ( ( rc = pci_read_config ( pci ) ) != 0 )
264
 			continue;
309
 			continue;
265
-			
266
-		/* Populate struct pci_device */
267
-		pci->vendor = ( tmp & 0xffff );
268
-		pci->device = ( tmp >> 16 );
269
-		pci_read_config_dword ( pci, PCI_REVISION, &tmp );
270
-		pci->class = ( tmp >> 8 );
271
-		pci_read_config_byte ( pci, PCI_INTERRUPT_LINE,
272
-				       &pci->irq );
273
-		pci_read_bases ( pci );
310
+
311
+		/* Look for a driver */
312
+		if ( ( rc = pci_find_driver ( pci ) ) != 0 ) {
313
+			DBGC ( pci, PCI_FMT " (%04x:%04x) has no driver\n",
314
+			       PCI_ARGS ( pci ), pci->vendor, pci->device );
315
+			continue;
316
+		}
274
 
317
 
275
 		/* Add to device hierarchy */
318
 		/* Add to device hierarchy */
276
-		snprintf ( pci->dev.name, sizeof ( pci->dev.name ),
277
-			   "PCI%02x:%02x.%x", PCI_BUS ( busdevfn ),
278
-			   PCI_SLOT ( busdevfn ), PCI_FUNC ( busdevfn ) );
279
-		pci->dev.desc.bus_type = BUS_TYPE_PCI;
280
-		pci->dev.desc.location = pci->busdevfn;
281
-		pci->dev.desc.vendor = pci->vendor;
282
-		pci->dev.desc.device = pci->device;
283
-		pci->dev.desc.class = pci->class;
284
-		pci->dev.desc.ioaddr = pci->ioaddr;
285
-		pci->dev.desc.irq = pci->irq;
286
 		pci->dev.parent = &rootdev->dev;
319
 		pci->dev.parent = &rootdev->dev;
287
 		list_add ( &pci->dev.siblings, &rootdev->dev.children);
320
 		list_add ( &pci->dev.siblings, &rootdev->dev.children);
288
-		INIT_LIST_HEAD ( &pci->dev.children );
289
 
321
 
290
 		/* Look for a driver */
322
 		/* Look for a driver */
291
-		if ( pci_probe ( pci ) == 0 ) {
323
+		if ( ( rc = pci_probe ( pci ) ) == 0 ) {
292
 			/* pcidev registered, we can drop our ref */
324
 			/* pcidev registered, we can drop our ref */
293
 			pci = NULL;
325
 			pci = NULL;
294
 		} else {
326
 		} else {

+ 28
- 0
src/include/ipxe/pci.h View File

381
 extern void adjust_pci_device ( struct pci_device *pci );
381
 extern void adjust_pci_device ( struct pci_device *pci );
382
 extern unsigned long pci_bar_start ( struct pci_device *pci,
382
 extern unsigned long pci_bar_start ( struct pci_device *pci,
383
 				     unsigned int reg );
383
 				     unsigned int reg );
384
+extern int pci_read_config ( struct pci_device *pci );
385
+extern int pci_find_driver ( struct pci_device *pci );
386
+extern int pci_probe ( struct pci_device *pci );
387
+extern void pci_remove ( struct pci_device *pci );
384
 extern int pci_find_capability ( struct pci_device *pci, int capability );
388
 extern int pci_find_capability ( struct pci_device *pci, int capability );
385
 extern unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg );
389
 extern unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg );
386
 
390
 
391
+/**
392
+ * Initialise PCI device
393
+ *
394
+ * @v pci		PCI device
395
+ * @v busdevfn		PCI bus:dev.fn address
396
+ */
397
+static inline void pci_init ( struct pci_device *pci, unsigned int busdevfn ) {
398
+	pci->busdevfn = busdevfn;
399
+}
400
+
401
+/**
402
+ * Set PCI driver
403
+ *
404
+ * @v pci		PCI device
405
+ * @v driver		PCI driver
406
+ * @v id		PCI device ID
407
+ */
408
+static inline void pci_set_driver ( struct pci_device *pci,
409
+				    struct pci_driver *driver,
410
+				    struct pci_device_id *id ) {
411
+	pci->driver = driver;
412
+	pci->id = id;
413
+}
414
+
387
 /**
415
 /**
388
  * Set PCI driver-private data
416
  * Set PCI driver-private data
389
  *
417
  *

Loading…
Cancel
Save