Browse Source

New PCI scan functions now work.

tags/v0.9.3
Michael Brown 19 years ago
parent
commit
707720c4e5
1 changed files with 114 additions and 77 deletions
  1. 114
    77
      src/drivers/bus/pci.c

+ 114
- 77
src/drivers/bus/pci.c View File

@@ -1,6 +1,9 @@
1 1
 #include "etherboot.h"
2
+#include "dev.h"
2 3
 #include "pci.h"
3 4
 
5
+#define DEBUG_PCI
6
+
4 7
 #undef DBG
5 8
 #ifdef DEBUG_PCI
6 9
 #define DBG(...) printf ( __VA_ARGS__ )
@@ -34,17 +37,24 @@ static int fill_pci_device ( struct pci_device *pci ) {
34 37
 	/* Check that we're not a duplicate function on a
35 38
 	 * non-multifunction device.
36 39
 	 */
37
-	if ( PCI_FUNC ( pci->devfn ) != 0 ) {
40
+	if ( PCI_FUNC ( pci->busdevfn ) != 0 ) {
41
+		uint16_t save_busdevfn = pci->busdevfn;
38 42
 		uint8_t header_type;
43
+
44
+		pci->busdevfn &= ~PCI_FUNC ( 0xffff );
39 45
 		pci_read_config_byte ( pci, PCI_HEADER_TYPE, &header_type );
46
+		pci->busdevfn = save_busdevfn;
47
+
40 48
 		if ( ! ( header_type & 0x80 ) ) {
41 49
 			return 0;
42 50
 		}
43 51
 	}
44 52
 	
45 53
 	/* Get device class */
46
-	pci_read_config_dword ( pci, PCI_REVISION, &l );
47
-	pci->class = ( l >> 8 ) & 0xffffff;
54
+	pci_read_config_word ( pci, PCI_SUBCLASS_CODE, &pci->class );
55
+
56
+	/* Get revision */
57
+	pci_read_config_byte ( pci, PCI_REVISION, &pci->revision );
48 58
 
49 59
 	/* Get the "membase" */
50 60
 	pci_read_config_dword ( pci, PCI_BASE_ADDRESS_1, &pci->membase );
@@ -68,9 +78,41 @@ static int fill_pci_device ( struct pci_device *pci ) {
68 78
 		pci_read_config_byte ( pci, PCI_INTERRUPT_LINE, &pci->irq );
69 79
 	}
70 80
 
81
+	DBG ( "%hhx:%hhx.%d Class %hx: %hx:%hx (rev %hhx)\n",
82
+	      PCI_BUS ( pci->busdevfn ), PCI_DEV ( pci->busdevfn ),
83
+	      PCI_FUNC ( pci->busdevfn ), pci->class, pci->vendor, pci->dev_id,
84
+	      pci->revision );
85
+
71 86
 	return 1;
72 87
 }
73 88
 
89
+/*
90
+ * Set device to be a busmaster in case BIOS neglected to do so.  Also
91
+ * adjust PCI latency timer to a reasonable value, 32.
92
+ */
93
+static void adjust_pci_device ( struct pci_device *pci ) {
94
+	unsigned short	new_command, pci_command;
95
+	unsigned char	pci_latency;
96
+
97
+	pci_read_config_word ( pci, PCI_COMMAND, &pci_command );
98
+	new_command = pci_command | PCI_COMMAND_MASTER | PCI_COMMAND_IO;
99
+	if ( pci_command != new_command ) {
100
+		DBG ( "%hhx:%hhx.%d : PCI BIOS has not enabled this device! "
101
+		      "Updating PCI command %hX->%hX\n",
102
+		      PCI_BUS ( pci->busdevfn ), PCI_DEV ( pci->busdevfn ),
103
+		      PCI_FUNC ( pci->busdevfn ), pci_command, new_command );
104
+		pci_write_config_word ( pci, PCI_COMMAND, new_command );
105
+	}
106
+	pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency);
107
+	if ( pci_latency < 32 ) {
108
+		DBG ( "%hhx:%hhx.%d : PCI latency timer (CFLT) "
109
+		      "is unreasonably low at %d. Setting to 32 clocks.\n",
110
+		      PCI_BUS ( pci->busdevfn ), PCI_DEV ( pci->busdevfn ),
111
+		      PCI_FUNC ( pci->busdevfn ), pci_latency );
112
+		pci_write_config_byte ( pci, PCI_LATENCY_TIMER, 32);
113
+	}
114
+}
115
+
74 116
 /*
75 117
  * Set PCI device to use.
76 118
  *
@@ -79,101 +121,96 @@ static int fill_pci_device ( struct pci_device *pci ) {
79 121
  * was physically located.
80 122
  *
81 123
  */
82
-void set_pci_device ( uint8_t bus, uint8_t devfn ) {
83
-	current.bus = bus;
84
-	current.devfn = devfn;
124
+void set_pci_device ( uint16_t busdevfn ) {
125
+	current.busdevfn = busdevfn;
85 126
 	used_current = 0;
86 127
 }
87 128
 
88 129
 /*
89 130
  * Find a PCI device matching the specified driver
90 131
  *
132
+ * If "dev" is non-NULL, the struct dev will be filled in with any
133
+ * relevant information.
134
+ *
91 135
  */
92
-struct pci_device * find_pci_device ( struct pci_driver *driver ) {
136
+struct pci_device * find_pci_device ( struct pci_driver *driver,
137
+				      struct dev *dev ) {
93 138
 	int i;
94 139
 
95 140
 	/* Iterate through all possible PCI bus:dev.fn combinations,
96 141
 	 * starting where we left off.
97 142
 	 */
98
-	for ( ; current.bus <= 0xff ; current.bus++ ) {
99
-		for ( ; current.devfn <= 0xff ; current.devfn++ ) {
100
-
101
-			/* If we've already used this device, skip it */
102
-			if ( used_current ) {
103
-				used_current = 0;
104
-				continue;
105
-			}
106
-
107
-			/* Fill in device parameters, if device present */
108
-			if ( ! fill_pci_device ( &current ) ) {
109
-				continue;
110
-			}
143
+	for ( ; current.busdevfn <= 0xffff ; current.busdevfn++ ) {
144
+		/* If we've already used this device, skip it */
145
+		if ( used_current ) {
146
+			used_current = 0;
147
+			continue;
148
+		}
149
+		
150
+		/* Fill in device parameters, if device present */
151
+		if ( ! fill_pci_device ( &current ) ) {
152
+			continue;
153
+		}
154
+		
155
+		/* Fix up PCI device */
156
+		adjust_pci_device ( &current );
157
+		
158
+		/* Fill in dev structure, if present */
159
+		if ( dev ) {
160
+			dev->name = driver->name;
161
+			dev->devid.vendor_id = current.vendor;
162
+			dev->devid.device_id = current.dev_id;
163
+			dev->devid.bus_type = PCI_BUS_TYPE;
164
+		}
111 165
 
112
-			/* If driver has a class, and class matches, use it */
113
-			if ( driver->class && 
114
-			     ( driver->class == current.class ) ) {
115
-				current.name = driver->name;
166
+		/* If driver has a class, and class matches, use it */
167
+		if ( driver->class && 
168
+		     ( driver->class == current.class ) ) {
169
+			DBG ( "Driver %s matches class %hx\n",
170
+			      driver->name, driver->class );
171
+			used_current = 1;
172
+			return &current;
173
+		}
174
+		
175
+		/* If any of driver's IDs match, use it */
176
+		for ( i = 0 ; i < driver->id_count; i++ ) {
177
+			struct pci_id *id = &driver->ids[i];
178
+			
179
+			if ( ( current.vendor == id->vendor ) &&
180
+			     ( current.dev_id == id->dev_id ) ) {
181
+				DBG ( "Device %s (driver %s) matches "
182
+				      "ID %hx:%hx\n", id->name, driver->name,
183
+				      id->vendor, id->dev_id );
184
+				if ( dev )
185
+					dev->name = id->name;
116 186
 				used_current = 1;
117 187
 				return &current;
118 188
 			}
119
-
120
-			/* If any of driver's IDs match, use it */
121
-			for ( i = 0 ; i < driver->id_count; i++ ) {
122
-				struct pci_id *id = &driver->ids[i];
123
-
124
-				if ( ( current.vendor == id->vendor ) &&
125
-				     ( current.dev_id == id->dev_id ) ) {
126
-					current.name = id->name;
127
-					used_current = 1;
128
-					return &current;
129
-				}
130
-			}
131 189
 		}
190
+
191
+		DBG ( "No match in driver %s\n", driver->name );
132 192
 	}
193
+
133 194
 	/* No device found */
134 195
 	memset ( &current, 0, sizeof ( current ) );
135 196
 	return NULL;
136 197
 }
137 198
 
138
-/*
139
- * Set device to be a busmaster in case BIOS neglected to do so.  Also
140
- * adjust PCI latency timer to a reasonable value, 32.
141
- */
142
-void adjust_pci_device ( struct pci_device *dev ) {
143
-	unsigned short	new_command, pci_command;
144
-	unsigned char	pci_latency;
145
-
146
-	pci_read_config_word ( dev, PCI_COMMAND, &pci_command );
147
-	new_command = pci_command | PCI_COMMAND_MASTER | PCI_COMMAND_IO;
148
-	if ( pci_command != new_command ) {
149
-		DBG ( "The PCI BIOS has not enabled this device!\n"
150
-		      "Updating PCI command %hX->%hX. bus %hhX dev_fn %hhX\n",
151
-		      pci_command, new_command, p->bus, p->devfn );
152
-		pci_write_config_word ( dev, PCI_COMMAND, new_command );
153
-	}
154
-	pci_read_config_byte ( dev, PCI_LATENCY_TIMER, &pci_latency);
155
-	if ( pci_latency < 32 ) {
156
-		DBG ( "PCI latency timer (CFLT) is unreasonably low at %d. "
157
-		      "Setting to 32 clocks.\n", pci_latency );
158
-		pci_write_config_byte ( dev, PCI_LATENCY_TIMER, 32);
159
-	}
160
-}
161
-
162 199
 /*
163 200
  * Find the start of a pci resource.
164 201
  */
165
-unsigned long pci_bar_start ( struct pci_device *dev, unsigned int index ) {
202
+unsigned long pci_bar_start ( struct pci_device *pci, unsigned int index ) {
166 203
 	uint32_t lo, hi;
167 204
 	unsigned long bar;
168 205
 
169
-	pci_read_config_dword ( dev, index, &lo );
206
+	pci_read_config_dword ( pci, index, &lo );
170 207
 	if ( lo & PCI_BASE_ADDRESS_SPACE_IO ) {
171 208
 		bar = lo & PCI_BASE_ADDRESS_IO_MASK;
172 209
 	} else {
173 210
 		bar = 0;
174 211
 		if ( ( lo & PCI_BASE_ADDRESS_MEM_TYPE_MASK ) ==
175 212
 		     PCI_BASE_ADDRESS_MEM_TYPE_64) {
176
-			pci_read_config_dword ( dev, index + 4, &hi );
213
+			pci_read_config_dword ( pci, index + 4, &hi );
177 214
 			if ( hi ) {
178 215
 #if ULONG_MAX > 0xffffffff
179 216
 					bar = hi;
@@ -186,22 +223,22 @@ unsigned long pci_bar_start ( struct pci_device *dev, unsigned int index ) {
186 223
 		}
187 224
 		bar |= lo & PCI_BASE_ADDRESS_MEM_MASK;
188 225
 	}
189
-	return bar + pcibios_bus_base ( dev->bus );
226
+	return bar + pci_bus_base ( pci );
190 227
 }
191 228
 
192 229
 /*
193 230
  * Find the size of a pci resource.
194 231
  */
195
-unsigned long pci_bar_size ( struct pci_device *dev, unsigned int bar ) {
232
+unsigned long pci_bar_size ( struct pci_device *pci, unsigned int bar ) {
196 233
 	uint32_t start, size;
197 234
 
198 235
 	/* Save the original bar */
199
-	pci_read_config_dword ( dev, bar, &start );
236
+	pci_read_config_dword ( pci, bar, &start );
200 237
 	/* Compute which bits can be set */
201
-	pci_write_config_dword ( dev, bar, ~0 );
202
-	pci_read_config_dword ( dev, bar, &size );
238
+	pci_write_config_dword ( pci, bar, ~0 );
239
+	pci_read_config_dword ( pci, bar, &size );
203 240
 	/* Restore the original size */
204
-	pci_write_config_dword ( dev, bar, start );
241
+	pci_write_config_dword ( pci, bar, start );
205 242
 	/* Find the significant bits */
206 243
 	if ( start & PCI_BASE_ADDRESS_SPACE_IO ) {
207 244
 		size &= PCI_BASE_ADDRESS_IO_MASK;
@@ -215,7 +252,7 @@ unsigned long pci_bar_size ( struct pci_device *dev, unsigned int bar ) {
215 252
 
216 253
 /**
217 254
  * pci_find_capability - query for devices' capabilities 
218
- * @dev: PCI device to query
255
+ * @pci: PCI device to query
219 256
  * @cap: capability code
220 257
  *
221 258
  * Tell if a device supports a given PCI capability.
@@ -235,36 +272,36 @@ unsigned long pci_bar_size ( struct pci_device *dev, unsigned int bar ) {
235 272
  *
236 273
  *  %PCI_CAP_ID_CHSWP        CompactPCI HotSwap 
237 274
  */
238
-int pci_find_capability ( struct pci_device *dev, int cap ) {
275
+int pci_find_capability ( struct pci_device *pci, int cap ) {
239 276
 	uint16_t status;
240 277
 	uint8_t pos, id;
241 278
 	uint8_t hdr_type;
242 279
 	int ttl = 48;
243 280
 
244
-	pci_read_config_word ( dev, PCI_STATUS, &status );
281
+	pci_read_config_word ( pci, PCI_STATUS, &status );
245 282
 	if ( ! ( status & PCI_STATUS_CAP_LIST ) )
246 283
 		return 0;
247 284
 
248
-	pci_read_config_byte ( dev, PCI_HEADER_TYPE, &hdr_type );
285
+	pci_read_config_byte ( pci, PCI_HEADER_TYPE, &hdr_type );
249 286
 	switch ( hdr_type & 0x7F ) {
250 287
 	case PCI_HEADER_TYPE_NORMAL:
251 288
 	case PCI_HEADER_TYPE_BRIDGE:
252 289
 	default:
253
-		pci_read_config_byte ( dev, PCI_CAPABILITY_LIST, &pos );
290
+		pci_read_config_byte ( pci, PCI_CAPABILITY_LIST, &pos );
254 291
 		break;
255 292
 	case PCI_HEADER_TYPE_CARDBUS:
256
-		pci_read_config_byte ( dev, PCI_CB_CAPABILITY_LIST, &pos );
293
+		pci_read_config_byte ( pci, PCI_CB_CAPABILITY_LIST, &pos );
257 294
 		break;
258 295
 	}
259 296
 	while ( ttl-- && pos >= 0x40 ) {
260 297
 		pos &= ~3;
261
-		pci_read_config_byte ( dev, pos + PCI_CAP_LIST_ID, &id );
298
+		pci_read_config_byte ( pci, pos + PCI_CAP_LIST_ID, &id );
262 299
 		DBG ( "Capability: %d\n", id );
263 300
 		if ( id == 0xff )
264 301
 			break;
265 302
 		if ( id == cap )
266 303
 			return pos;
267
-		pci_read_config_byte ( dev, pos + PCI_CAP_LIST_NEXT, &pos );
304
+		pci_read_config_byte ( pci, pos + PCI_CAP_LIST_NEXT, &pos );
268 305
 	}
269 306
 	return 0;
270 307
 }

Loading…
Cancel
Save