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,23 +164,54 @@ void adjust_pci_device ( struct pci_device *pci ) {
164 164
 }
165 165
 
166 166
 /**
167
- * Probe a PCI device
167
+ * Read PCI device configuration
168 168
  *
169 169
  * @v pci		PCI device
170 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 212
 	struct pci_driver *driver;
177 213
 	struct pci_device_id *id;
178 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 216
 	for_each_table_entry ( driver, PCI_DRIVERS ) {
186 217
 		for ( i = 0 ; i < driver->id_count ; i++ ) {
@@ -191,21 +222,37 @@ static int pci_probe ( struct pci_device *pci ) {
191 222
 			if ( ( id->device != PCI_ANY_ID ) &&
192 223
 			     ( id->device != pci->device ) )
193 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 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,7 +260,7 @@ static int pci_probe ( struct pci_device *pci ) {
213 260
  *
214 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 264
 	pci->driver->remove ( pci );
218 265
 	DBGC ( pci, PCI_FMT " removed\n", PCI_ARGS ( pci ) );
219 266
 }
@@ -231,7 +278,6 @@ static int pcibus_probe ( struct root_device *rootdev ) {
231 278
 	unsigned int num_bus;
232 279
 	unsigned int busdevfn;
233 280
 	uint8_t hdrtype = 0;
234
-	uint32_t tmp;
235 281
 	int rc;
236 282
 
237 283
 	num_bus = pci_num_bus();
@@ -246,7 +292,7 @@ static int pcibus_probe ( struct root_device *rootdev ) {
246 292
 			goto err;
247 293
 		}
248 294
 		memset ( pci, 0, sizeof ( *pci ) );
249
-		pci->busdevfn = busdevfn;
295
+		pci_init ( pci, busdevfn );
250 296
 			
251 297
 		/* Skip all but the first function on
252 298
 		 * non-multifunction cards
@@ -258,37 +304,23 @@ static int pcibus_probe ( struct root_device *rootdev ) {
258 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 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 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 319
 		pci->dev.parent = &rootdev->dev;
287 320
 		list_add ( &pci->dev.siblings, &rootdev->dev.children);
288
-		INIT_LIST_HEAD ( &pci->dev.children );
289 321
 
290 322
 		/* Look for a driver */
291
-		if ( pci_probe ( pci ) == 0 ) {
323
+		if ( ( rc = pci_probe ( pci ) ) == 0 ) {
292 324
 			/* pcidev registered, we can drop our ref */
293 325
 			pci = NULL;
294 326
 		} else {

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

@@ -381,9 +381,37 @@ struct pci_driver {
381 381
 extern void adjust_pci_device ( struct pci_device *pci );
382 382
 extern unsigned long pci_bar_start ( struct pci_device *pci,
383 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 388
 extern int pci_find_capability ( struct pci_device *pci, int capability );
385 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 416
  * Set PCI driver-private data
389 417
  *

Loading…
Cancel
Save