Browse Source

If preloaded device matches, use that rather than going via the UNDI

loader.
tags/v0.9.3
Michael Brown 17 years ago
parent
commit
f2f492a536
1 changed files with 46 additions and 21 deletions
  1. 46
    21
      src/arch/i386/drivers/net/undi.c

+ 46
- 21
src/arch/i386/drivers/net/undi.c View File

@@ -24,6 +24,7 @@
24 24
 #include <undirom.h>
25 25
 #include <undiload.h>
26 26
 #include <undinet.h>
27
+#include <undipreload.h>
27 28
 
28 29
 /** @file
29 30
  *
@@ -31,35 +32,44 @@
31 32
  *
32 33
  */
33 34
 
35
+/**
36
+ * Find UNDI ROM for PCI device
37
+ *
38
+ * @v pci		PCI device
39
+ * @ret undirom		UNDI ROM, or NULL
40
+ *
41
+ * Try to find a driver for this device.  Try an exact match on the
42
+ * ROM address first, then fall back to a vendor/device ID match only
43
+ */
44
+static struct undi_rom * undipci_find_rom ( struct pci_device *pci ) {
45
+	struct undi_rom *undirom;
46
+	unsigned long rombase;
47
+	
48
+	rombase = pci_bar_start ( pci, PCI_ROM_ADDRESS );
49
+	undirom = undirom_find_pci ( pci->vendor, pci->device, rombase );
50
+	if ( ! undirom )
51
+		undirom = undirom_find_pci ( pci->vendor, pci->device, 0 );
52
+	return undirom;
53
+}
54
+
34 55
 /**
35 56
  * Probe PCI device
36 57
  *
37
- * @v pci	PCI device
38
- * @v id	PCI ID
39
- * @ret rc	Return status code
58
+ * @v pci		PCI device
59
+ * @v id		PCI ID
60
+ * @ret rc		Return status code
40 61
  */
41 62
 static int undipci_probe ( struct pci_device *pci,
42 63
 			   const struct pci_device_id *id __unused ) {
43 64
 	struct undi_device *undi;
44 65
 	struct undi_rom *undirom;
45
-	unsigned long rombase;
66
+	unsigned int busdevfn = ( ( pci->bus << 8 ) | pci->devfn );
46 67
 	int rc;
47 68
 
48 69
 	/* Ignore non-network devices */
49 70
 	if ( PCI_BASE_CLASS ( pci->class ) != PCI_BASE_CLASS_NETWORK )
50 71
 		return -ENOTTY;
51 72
 
52
-	/* Try to find a driver for this device.  Try an exact match
53
-	 * on the ROM address first, then fall back to a vendor/device
54
-	 * ID match only
55
-	 */
56
-	rombase = pci_bar_start ( pci, PCI_ROM_ADDRESS );
57
-	undirom = undirom_find_pci ( pci->vendor, pci->device, rombase );
58
-	if ( ! undirom )
59
-		undirom = undirom_find_pci ( pci->vendor, pci->device, 0 );
60
-	if ( ! undirom )
61
-		return -ENODEV;
62
-
63 73
 	/* Allocate UNDI device structure */
64 74
 	undi = malloc ( sizeof ( *undi ) );
65 75
 	if ( ! undi )
@@ -67,16 +77,30 @@ static int undipci_probe ( struct pci_device *pci,
67 77
 	memset ( undi, 0, sizeof ( *undi ) );
68 78
 	pci_set_drvdata ( pci, undi );
69 79
 
80
+	/* Find/create our pixie */
81
+	if ( preloaded_undi.pci_busdevfn == busdevfn ) {
82
+		/* Claim preloaded UNDI device */
83
+		DBGC ( undi, "UNDI %p using preloaded UNDI device\n", undi );
84
+		memcpy ( undi, &preloaded_undi, sizeof ( *undi ) );
85
+		memset ( &preloaded_undi, 0, sizeof ( preloaded_undi ) );
86
+	} else {
87
+		/* Find UNDI ROM for PCI device */
88
+		if ( ! ( undirom = undipci_find_rom ( pci ) ) ) {
89
+			rc = -ENODEV;
90
+			goto err_find_rom;
91
+		}
92
+
93
+		/* Call UNDI ROM loader to create pixie */
94
+		if ( ( rc = undi_load_pci ( undi, undirom, pci->bus,
95
+					    pci->devfn ) ) != 0 )
96
+			goto err_load_pci;
97
+	}
98
+
70 99
 	/* Add to device hierarchy */
71 100
 	undi->dev.parent = &pci->dev;
72 101
 	INIT_LIST_HEAD ( &undi->dev.children );
73 102
 	list_add ( &undi->dev.siblings, &pci->dev.children );
74 103
 
75
-	/* Call UNDI ROM loader to create pixie */
76
-	if ( ( rc = undi_load_pci ( undi, undirom, pci->bus,
77
-				    pci->devfn ) ) != 0 )
78
-		goto err_load_pci;
79
-
80 104
 	/* Create network device */
81 105
 	if ( ( rc = undinet_probe ( undi ) ) != 0 )
82 106
 		goto err_undinet_probe;
@@ -85,8 +109,9 @@ static int undipci_probe ( struct pci_device *pci,
85 109
 
86 110
  err_undinet_probe:
87 111
 	undi_unload ( undi );
88
- err_load_pci:
89 112
 	list_del ( &undi->dev.siblings );
113
+ err_find_rom:
114
+ err_load_pci:
90 115
 	free ( undi );
91 116
 	pci_set_drvdata ( pci, NULL );
92 117
 	return rc;

Loading…
Cancel
Save