Browse Source

Strip down i386 PCI configuration space I/O to the bare minimum. A

typical build will now include 880 bytes of PCI support code, compared to
2327 bytes in Etherboot 5.4.

(There is a slight cost of around 5 extra bytes per access to a
non-constant config space address; this should be an overall win.
Driver-specific accesses will usually be to constant addresses, for
which there is no additional cost.)
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
6b6096d28b

+ 0
- 451
src/arch/i386/core/pci_io.c View File

@@ -1,451 +0,0 @@
1
-/*
2
-** Support for NE2000 PCI clones added David Monro June 1997
3
-** Generalised to other NICs by Ken Yap July 1997
4
-**
5
-** Most of this is taken from:
6
-**
7
-** /usr/src/linux/drivers/pci/pci.c
8
-** /usr/src/linux/include/linux/pci.h
9
-** /usr/src/linux/arch/i386/bios32.c
10
-** /usr/src/linux/include/linux/bios32.h
11
-** /usr/src/linux/drivers/net/ne.c
12
-*/
13
-#include "etherboot.h"
14
-#include <gpxe/init.h>
15
-#include <gpxe/pci.h>
16
-#include "pci_io.h"
17
-#ifdef KEEP_IT_REAL
18
-#include "realmode.h"
19
-#endif
20
-
21
-/* Macros for direct PCI access */
22
-#define CONFIG_ADDRESS	0xcf8
23
-#define CONFIG_DATA	0xcfc
24
-#define CONFIG_CMD( pci, where )					\
25
-	( 0x80000000 | ( pci->bus << 16 ) | ( pci->devfn << 8 ) |	\
26
-	  ( where & ~3 ) )
27
-
28
-/* Signatures for PCI BIOS */
29
-#define BIOS_SIG(a,b,c,d)	( ( a<<0 ) + ( b<<8 ) + ( c<<16 ) + ( d<<24 ) )
30
-#define PRINT_BIOS_SIG(x)	( (x) & 0xff ), ( ( (x)>>8 ) & 0xff ), \
31
-				( ( (x)>>16 ) & 0xff ),( ( (x)>>24 ) & 0xff )
32
-#define BIOS32_SIGNATURE	BIOS_SIG ( '_', '3', '2', '_' )
33
-#define PCI_SIGNATURE		BIOS_SIG ( 'P', 'C', 'I', ' ' )
34
-#define PCI_SERVICE		BIOS_SIG ( '$', 'P', 'C', 'I' )
35
-
36
-/* BIOS32 structure as found in PCI BIOS ROM */
37
-struct bios32 {
38
-	unsigned long signature;	/* _32_ */
39
-	unsigned long entry;		/* 32 bit physical address */
40
-	unsigned char revision;		/* Revision level, 0 */
41
-	unsigned char length;		/* Length in paragraphs */
42
-	unsigned char checksum;		/* Should byte sum to zero */
43
-	unsigned char reserved[5];	/* Must be zero */
44
-};
45
-
46
-/* Values returned by BIOS32 service directory */
47
-#define BIOS32_SERVICE_PRESENT		0x00
48
-#define BIOS32_SERVICE_NOT_PRESENT	0x80
49
-#define CF ( 1 << 0 )
50
-
51
-/* PCI BIOS entry point */
52
-#ifndef KEEP_IT_REAL
53
-static unsigned long pcibios32_entry;
54
-#endif
55
-static int have_pcibios;
56
-
57
-/* Macro for calling a 32-bit entry point with flat physical
58
- * addresses.  Use in a statement such as
59
- * __asm__ ( FLAT_FAR_CALL_ESI,
60
- *	     : "=S" ( discard, or real output ), <other output registers>
61
- *	     : "S" ( entry_point ), <other input registers> );
62
- * "=S" *must* be specified as an output, otherwise the compiler will
63
- * assume that it remains unaltered.
64
- */
65
-#define FLAT_FAR_CALL_ESI "call _virt_to_phys\n\t" \
66
-			  "pushl %%cs\n\t" \
67
-			  "call *%%esi\n\t" \
68
-			  "cli\n\t" \
69
-			  "cld\n\t" \
70
-			  "call _phys_to_virt\n\t"
71
-
72
-/*
73
- * Functions for accessing PCI configuration space directly with type
74
- * 1 accesses.
75
- *
76
- */
77
-
78
-static inline int pcidirect_read_config_byte ( struct pci_device *pci,
79
-					       unsigned int where,
80
-					       uint8_t *value ) {
81
-    outl ( CONFIG_CMD ( pci, where ), CONFIG_ADDRESS );
82
-    *value = inb ( CONFIG_DATA + ( where & 3 ) );
83
-    return 0;
84
-}
85
-
86
-static inline int pcidirect_read_config_word ( struct pci_device *pci,
87
-					       unsigned int where,
88
-					       uint16_t *value ) {
89
-    outl ( CONFIG_CMD ( pci, where ), CONFIG_ADDRESS );
90
-    *value = inw ( CONFIG_DATA + ( where & 2 ) );
91
-    return 0;
92
-}
93
-
94
-static inline int pcidirect_read_config_dword ( struct pci_device *pci,
95
-						unsigned int where,
96
-						uint32_t *value ) {
97
-    outl ( CONFIG_CMD ( pci, where ), CONFIG_ADDRESS );
98
-    *value = inl ( CONFIG_DATA );
99
-    return 0;
100
-}
101
-
102
-static inline int pcidirect_write_config_byte ( struct pci_device *pci,
103
-						unsigned int where,
104
-						uint8_t value ) {
105
-    outl ( CONFIG_CMD ( pci, where ), CONFIG_ADDRESS );
106
-    outb ( value, CONFIG_DATA + ( where & 3 ) );
107
-    return 0;
108
-}
109
-
110
-static inline int pcidirect_write_config_word ( struct pci_device *pci,
111
-						unsigned int where,
112
-						uint16_t value ) {
113
-    outl ( CONFIG_CMD ( pci, where ), CONFIG_ADDRESS );
114
-    outw ( value, CONFIG_DATA + ( where & 2 ) );
115
-    return 0;
116
-}
117
-
118
-static inline int pcidirect_write_config_dword ( struct pci_device *pci,
119
-						 unsigned int where,
120
-						 uint32_t value ) {
121
-    outl ( CONFIG_CMD ( pci, where ), CONFIG_ADDRESS );
122
-    outl ( value, CONFIG_DATA );
123
-    return 0;
124
-}
125
-
126
-/*
127
- * Functions for accessing PCI configuration space directly via the
128
- * PCI BIOS.
129
- *
130
- * Under -DKEEP_IT_REAL, we use INT 1A, otherwise we use the BIOS32
131
- * interface.
132
- */
133
-
134
-#ifdef KEEP_IT_REAL
135
-
136
-static void find_pcibios16 ( void ) {
137
-	uint16_t present;
138
-	uint32_t signature;
139
-	uint16_t flags;
140
-	uint16_t revision;
141
-	uint8_t max_bus;
142
-
143
-	/* PCI BIOS installation check */
144
-	REAL_EXEC ( rm_pcibios_check,
145
-		    "int $0x1a\n\t"
146
-		    "pushfw\n\t"
147
-		    "popw %%si\n\t",
148
-		    5,
149
-		    OUT_CONSTRAINTS ( "=a" ( present ), "=b" ( revision ),
150
-				      "=c" ( max_bus ), "=d" ( signature ),
151
-				      "=S" ( flags ) ),
152
-		    IN_CONSTRAINTS ( "a" ( ( PCIBIOS_PCI_FUNCTION_ID << 8 ) +
153
-					   PCIBIOS_PCI_BIOS_PRESENT ) ),
154
-		    CLOBBER ( "edi", "ebp" ) );
155
-
156
-	if ( ( flags & CF ) ||
157
-	     ( ( present >> 8 ) != 0 ) ||
158
-	     ( signature != PCI_SIGNATURE ) ) {
159
-		DBG ( "PCI BIOS installation check failed\n" );
160
-		return;
161
-	}
162
-
163
-	/* We have a PCI BIOS */
164
-	DBG ( "Found 16-bit PCI BIOS interface with %d buses\n", max_bus + 1 );
165
-	have_pcibios = 1;
166
-	pci_max_bus = max_bus;
167
-	return;
168
-}
169
-
170
-INIT_FN ( INIT_PCIBIOS, find_pcibios16, NULL, NULL );
171
-
172
-#define pcibios16_read_write( command, pci, where, value )		\
173
-	( {								\
174
-		uint32_t discard_b, discard_D;				\
175
-		uint16_t ret;						\
176
-									\
177
-		REAL_EXEC ( 999, /* need a local label */		\
178
-			    "int $0x1a\n\t"				\
179
-			    "jc 1f\n\t"					\
180
-			    "xorw %%ax, %%ax\n\t"			\
181
-			    "\n1:\n\t",					\
182
-			    5,						\
183
-			    OUT_CONSTRAINTS ( "=a" ( ret ),		\
184
-					      "=b" ( discard_b ),	\
185
-					      "=c" ( value ),		\
186
-					      "=D" ( discard_D ) ),	\
187
-			    IN_CONSTRAINTS ( "a" ( command +		\
188
-				    ( PCIBIOS_PCI_FUNCTION_ID << 8 ) ),	\
189
-					     "b" ( pci->busdevfn ),	\
190
-					     "c" ( value ),		\
191
-			    		     "D" ( where ) ),		\
192
-			    CLOBBER ( "edx", "esi", "ebp" ) );		\
193
-									\
194
-		( ret >> 8 );						\
195
-	} )
196
-#define pcibios_read_write pcibios16_read_write
197
-
198
-#else /* KEEP_IT_REAL */
199
-
200
-/*
201
- * Locate the BIOS32 service directory by scanning for a valid BIOS32
202
- * structure
203
- *
204
- */
205
-static struct bios32 * find_bios32 ( void ) {
206
-	uint32_t address;
207
-
208
-	/*
209
-	 * Follow the standard procedure for locating the BIOS32 Service
210
-	 * directory by scanning the permissible address range from
211
-	 * 0xe0000 through 0xfffff for a valid BIOS32 structure.
212
-	 *
213
-	 */
214
-	for ( address = 0xe0000 ; address < 0xffff0 ; address += 16 ) {
215
-		struct bios32 * candidate = phys_to_virt ( address );
216
-		unsigned int length, i;
217
-		unsigned char sum;
218
-
219
-		if ( candidate->signature != BIOS32_SIGNATURE )
220
-			continue;
221
-
222
-		length = candidate->length * 16;
223
-		if ( ! length )
224
-			continue;
225
-
226
-		for ( sum = 0, i = 0 ; i < length ; i++ )
227
-			sum += ( ( char * ) candidate ) [i];
228
-		if ( sum != 0 )
229
-			continue;
230
-
231
-		if ( candidate->revision != 0 ) {
232
-			DBG ( "unsupported BIOS32 revision %d at %#x\n",
233
-			      candidate->revision, address );
234
-			continue;
235
-		}
236
-
237
-		DBG ( "BIOS32 Service Directory structure at %#x\n", address );
238
-
239
-		return candidate;
240
-	}
241
-
242
-	return NULL;
243
-}
244
-
245
-/*
246
- * Look up a service in the BIOS32 service directory
247
- *
248
- */
249
-static unsigned long find_bios32_service ( struct bios32 * bios32,
250
-					   unsigned long service ) {
251
-	uint8_t return_code;
252
-	uint32_t address;
253
-	uint32_t length;
254
-	uint32_t entry;
255
-	uint32_t discard;
256
-
257
-	__asm__ ( FLAT_FAR_CALL_ESI
258
-		  : "=a" ( return_code ), "=b" ( address ),
259
-		    "=c" ( length ), "=d" ( entry ), "=S" ( discard )
260
-		  : "a" ( service ), "b" ( 0 ), "S" ( bios32->entry )
261
-		  : "edi", "ebp" );
262
-
263
-	switch ( return_code ) {
264
-	case BIOS32_SERVICE_PRESENT:
265
-		DBG ( "BIOS32 service %c%c%c%c present at %#x\n",
266
-		      PRINT_BIOS_SIG ( service ), ( address + entry ) );
267
-		return ( address + entry );
268
-	case BIOS32_SERVICE_NOT_PRESENT:
269
-		DBG ( "BIOS32 service %c%c%c%c : not present\n",
270
-		      PRINT_BIOS_SIG ( service ) );
271
-		return 0;
272
-	default: /* Shouldn't happen */
273
-		DBG ( "BIOS32 returned %#x for service %c%c%c%c!\n",
274
-		      return_code, PRINT_BIOS_SIG ( service ) );
275
-		return 0;
276
-	}
277
-}
278
-
279
-/*
280
- * Find the 32-bit PCI BIOS interface, if present.
281
- *
282
- */
283
-static void find_pcibios32 ( void ) {
284
-	struct bios32 *bios32;
285
-	uint32_t signature;
286
-	uint16_t present;
287
-	uint32_t flags;
288
-	uint16_t revision;
289
-	uint8_t max_bus;
290
-
291
-	/* Locate BIOS32 service directory */
292
-	bios32 = find_bios32 ();
293
-	if ( ! bios32 ) {
294
-		DBG ( "No BIOS32\n" );
295
-		return;
296
-	}
297
-
298
-	/* Locate PCI BIOS service */
299
-	pcibios32_entry = find_bios32_service ( bios32, PCI_SERVICE );
300
-	if ( ! pcibios32_entry ) {
301
-		DBG ( "No PCI BIOS\n" );
302
-		return;
303
-	}
304
-	
305
-	/* PCI BIOS installation check */
306
-	__asm__ ( FLAT_FAR_CALL_ESI
307
-		  "pushfl\n\t"
308
-		  "popl %%esi\n\t"
309
-		  : "=a" ( present ), "=b" ( revision ), "=c" ( max_bus ),
310
-		    "=d" ( signature ), "=S" ( flags )
311
-		  : "a" ( ( PCIBIOS_PCI_FUNCTION_ID << 8 )
312
-			  + PCIBIOS_PCI_BIOS_PRESENT ),
313
-		    "S" ( pcibios32_entry )
314
-		  : "edi", "ebp" );
315
-
316
-	if ( ( flags & CF ) ||
317
-	     ( ( present >> 8 ) != 0 ) ||
318
-	     ( signature != PCI_SIGNATURE ) ) {
319
-		DBG ( "PCI BIOS installation check failed\n" );
320
-		return;
321
-	}
322
-
323
-	/* We have a PCI BIOS */
324
-	DBG ( "Found 32-bit PCI BIOS interface at %#x with %d bus(es)\n",
325
-	      pcibios32_entry, max_bus + 1 );
326
-	have_pcibios = 1;
327
-	pci_max_bus = max_bus;
328
-	return;
329
-}
330
-
331
-INIT_FN ( INIT_PCIBIOS, find_pcibios32, NULL, NULL );
332
-
333
-#define pcibios32_read_write( command, pci, where, value )		\
334
-	( {								\
335
-		uint32_t discard_b, discard_D, discard_S;		\
336
-		uint16_t ret;						\
337
-									\
338
-		__asm__ ( FLAT_FAR_CALL_ESI				\
339
-			  "jc 1f\n\t"					\
340
-			  "xorl %%eax, %%eax\n\t"			\
341
-			  "\n1:\n\t"					\
342
-			  : "=a" ( ret ), "=b" ( discard_b ),		\
343
-			    "=c" ( value ),				\
344
-			    "=S" ( discard_S ), "=D" ( discard_D )	\
345
-			  : "a" ( ( PCIBIOS_PCI_FUNCTION_ID << 8 )	\
346
-				  + command ),			       	\
347
-			    "b" ( ( pci->bus << 8 ) | pci->devfn ),	\
348
-			    "c" ( value ), "D" ( where ),		\
349
-			    "S" ( pcibios32_entry )			\
350
-			  : "edx", "ebp" );				\
351
-									\
352
-		( ret >> 8 );						\
353
-	} )
354
-#define pcibios_read_write pcibios32_read_write
355
-
356
-#endif /* KEEP_IT_REAL */
357
-
358
-static inline int pcibios_read_config_byte ( struct pci_device *pci,
359
-					     unsigned int where,
360
-					     uint8_t *value ) {
361
-	return pcibios_read_write ( PCIBIOS_READ_CONFIG_BYTE,
362
-				    pci, where, *value );
363
-}
364
-
365
-static inline int pcibios_read_config_word ( struct pci_device *pci,
366
-					     unsigned int where,
367
-					     uint16_t *value ) {
368
-	return pcibios_read_write ( PCIBIOS_READ_CONFIG_WORD,
369
-				    pci, where, *value );
370
-}
371
-
372
-static inline int pcibios_read_config_dword ( struct pci_device *pci,
373
-					      unsigned int where,
374
-					      uint32_t *value ) {
375
-	return pcibios_read_write ( PCIBIOS_READ_CONFIG_DWORD,
376
-				    pci, where, *value );
377
-}
378
-
379
-static inline int pcibios_write_config_byte ( struct pci_device *pci,
380
-					      unsigned int where,
381
-					      uint8_t value ) {
382
-	return pcibios_read_write ( PCIBIOS_WRITE_CONFIG_BYTE,
383
-				    pci, where, value );
384
-}
385
-
386
-static inline int pcibios_write_config_word ( struct pci_device *pci,
387
-					      unsigned int where,
388
-					      uint16_t value ) {
389
-	return pcibios_read_write ( PCIBIOS_WRITE_CONFIG_WORD,
390
-				    pci, where, value );
391
-}
392
-
393
-static inline int pcibios_write_config_dword ( struct pci_device *pci,
394
-					       unsigned int where,
395
-					       uint32_t value ) {
396
-	return pcibios_read_write ( PCIBIOS_WRITE_CONFIG_DWORD,
397
-				    pci, where, value );
398
-}
399
-
400
-/*
401
- * Functions for accessing PCI configuration space via the PCI BIOS if
402
- * present, otherwise directly via type 1 accesses.
403
- *
404
- */
405
-
406
-int pci_read_config_byte ( struct pci_device *pci, unsigned int where,
407
-			   uint8_t *value ) {
408
-	return have_pcibios ?
409
-		pcibios_read_config_byte ( pci, where, value ) :
410
-		pcidirect_read_config_byte ( pci, where, value );
411
-}
412
-		
413
-int pci_read_config_word ( struct pci_device *pci, unsigned int where,
414
-			   uint16_t *value ) {
415
-	return have_pcibios ?
416
-		pcibios_read_config_word ( pci, where, value ) :
417
-		pcidirect_read_config_word ( pci, where, value );
418
-}
419
-		
420
-int pci_read_config_dword ( struct pci_device *pci, unsigned int where,
421
-			    uint32_t *value ) {
422
-	return have_pcibios ?
423
-		pcibios_read_config_dword ( pci, where, value ) :
424
-		pcidirect_read_config_dword ( pci, where, value );
425
-}
426
-		
427
-int pci_write_config_byte ( struct pci_device *pci, unsigned int where,
428
-			    uint8_t value ) {
429
-	return have_pcibios ?
430
-		pcibios_write_config_byte ( pci, where, value ) :
431
-		pcidirect_write_config_byte ( pci, where, value );
432
-}
433
-		
434
-int pci_write_config_word ( struct pci_device *pci, unsigned int where,
435
-			    uint16_t value ) {
436
-	return have_pcibios ?
437
-		pcibios_write_config_word ( pci, where, value ) :
438
-		pcidirect_write_config_word ( pci, where, value );
439
-}
440
-		
441
-int pci_write_config_dword ( struct pci_device *pci, unsigned int where,
442
-			     uint32_t value ) {
443
-	return have_pcibios ?
444
-		pcibios_write_config_dword ( pci, where, value ) :
445
-		pcidirect_write_config_dword ( pci, where, value );
446
-}
447
-
448
-unsigned long pci_bus_base ( struct pci_device *pci __unused ) {
449
-	/* architecturally this must be 0 */
450
-	return 0;
451
-}

+ 111
- 0
src/arch/i386/core/pcibios.c View File

@@ -0,0 +1,111 @@
1
+/*
2
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <stdint.h>
20
+#include <gpxe/pci.h>
21
+#include <pcibios.h>
22
+#include <realmode.h>
23
+
24
+/** @file
25
+ *
26
+ * PCI configuration space access via PCI BIOS
27
+ *
28
+ */
29
+
30
+/**
31
+ * Determine maximum PCI bus number within system
32
+ *
33
+ * @ret max_bus		Maximum bus number
34
+ */
35
+int pcibios_max_bus ( void ) {
36
+	int discard_a;
37
+	uint8_t max_bus;
38
+
39
+	REAL_EXEC ( rm_pcibios_check,
40
+		    "stc\n\t"
41
+		    "int $0x1a\n\t"
42
+		    "jnc 1f\n\t"
43
+		    "xorw %%cx, %%cx\n\t"
44
+		    "\n1:\n\t",
45
+		    2,
46
+		    OUT_CONSTRAINTS ( "=a" ( discard_a ), "=c" ( max_bus ) ),
47
+		    IN_CONSTRAINTS ( "a" ( PCIBIOS_INSTALLATION_CHECK >> 16 )),
48
+		    CLOBBER ( "ebx", "edx", "edi" ) );
49
+	
50
+	return max_bus;
51
+}
52
+
53
+/**
54
+ * Read configuration space via PCI BIOS
55
+ *
56
+ * @v pci	PCI device
57
+ * @v command	PCI BIOS command
58
+ * @v value	Value read
59
+ * @ret rc	Return status code
60
+ */
61
+int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){
62
+	int discard_b, discard_D;
63
+	int status;
64
+
65
+	REAL_EXEC ( rm_pcibios_read,
66
+		    "stc\n\t"
67
+		    "int $0x1a\n\t"
68
+		    "jnc 1f\n\t"
69
+		    "xorl %%eax, %%eax\n\t"
70
+		    "decl %%eax\n\t"
71
+		    "movl %%eax, %%ecx\n\t"
72
+		    "\n1:\n\t",
73
+		    4,
74
+		    OUT_CONSTRAINTS ( "=a" ( status ), "=b" ( discard_b ),
75
+				      "=c" ( *value ), "=D" ( discard_D ) ),
76
+		    IN_CONSTRAINTS ( "a" ( command >> 16 ),
77
+				     "b" ( ( pci->bus << 8 ) | pci->devfn ),
78
+				     "D" ( command ) ),
79
+		    CLOBBER ( "edx" ) );
80
+	
81
+	return ( ( status >> 8 ) & 0xff );
82
+}
83
+
84
+/**
85
+ * Write configuration space via PCI BIOS
86
+ *
87
+ * @v pci	PCI device
88
+ * @v command	PCI BIOS command
89
+ * @v value	Value to be written
90
+ * @ret rc	Return status code
91
+ */
92
+int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
93
+	int discard_b, discard_c, discard_D;
94
+	int status;
95
+
96
+	REAL_EXEC ( rm_pcibios_write,
97
+		    "stc\n\t"
98
+		    "int $0x1a\n\t"
99
+		    "jnc 1f\n\t"
100
+		    "movb $0xff, %%ah\n\t"
101
+		    "\n1:\n\t",
102
+		    4,
103
+		    OUT_CONSTRAINTS ( "=a" ( status ), "=b" ( discard_b ),
104
+				      "=c" ( discard_c ), "=D" ( discard_D ) ),
105
+		    IN_CONSTRAINTS ( "a" ( command >> 16 ),
106
+				     "b" ( ( pci->bus << 8 ) | pci->devfn ),
107
+				     "c" ( value ), "D" ( command ) ),
108
+		    CLOBBER ( "edx" ) );
109
+	
110
+	return ( ( status >> 8 ) & 0xff );
111
+}

+ 38
- 0
src/arch/i386/core/pcidirect.c View File

@@ -0,0 +1,38 @@
1
+/*
2
+ * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <gpxe/pci.h>
20
+#include <pcidirect.h>
21
+
22
+/** @file
23
+ *
24
+ * PCI configuration space access via Type 1 accesses
25
+ *
26
+ */
27
+
28
+/**
29
+ * Prepare for Type 1 PCI configuration space access
30
+ *
31
+ * @v pci		PCI device
32
+ * @v where	Location within PCI configuration space
33
+ */
34
+void pcidirect_prepare ( struct pci_device *pci, int where ) {
35
+	outl ( ( 0x80000000 | ( pci->bus << 16 ) | ( pci->devfn << 8 ) |
36
+		 ( where & ~3 ) ), PCIDIRECT_CONFIG_ADDRESS );
37
+}
38
+

+ 33
- 18
src/arch/i386/include/pci_io.h View File

@@ -1,20 +1,35 @@
1
-#ifndef PCI_IO_H
2
-#define PCI_IO_H
1
+#ifndef _PCI_IO_H
2
+#define _PCI_IO_H
3 3
 
4
-/* %ah */
5
-#define PCIBIOS_PCI_FUNCTION_ID         ( 0xb1 )
6
-/* %al */
7
-#define PCIBIOS_PCI_BIOS_PRESENT        ( 0x01 )
8
-#define PCIBIOS_FIND_PCI_DEVICE         ( 0x02 )
9
-#define PCIBIOS_FIND_PCI_CLASS_CODE     ( 0x03 )
10
-#define PCIBIOS_GENERATE_SPECIAL_CYCLE  ( 0x06 )
11
-#define PCIBIOS_READ_CONFIG_BYTE        ( 0x08 )
12
-#define PCIBIOS_READ_CONFIG_WORD        ( 0x09 )
13
-#define PCIBIOS_READ_CONFIG_DWORD       ( 0x0a )
14
-#define PCIBIOS_WRITE_CONFIG_BYTE       ( 0x0b )
15
-#define PCIBIOS_WRITE_CONFIG_WORD       ( 0x0c )
16
-#define PCIBIOS_WRITE_CONFIG_DWORD      ( 0x0d )
17
-#define PCIBIOS_GET_IRQ_ROUTING_OPTIONS	( 0x0e )
18
-#define PCIBIOS_SET_PCI_IRQ		( 0x0f )
4
+#include <pcibios.h>
5
+#include <pcidirect.h>
19 6
 
20
-#endif /* PCI_IO_H */
7
+/** @file
8
+ *
9
+ * i386 PCI configuration space access
10
+ *
11
+ * We have two methods of PCI configuration space access: the PCI BIOS
12
+ * and direct Type 1 accesses.  Selecting between them is via the
13
+ * compile-time switch -DCONFIG_PCI_DIRECT.
14
+ *
15
+ */
16
+
17
+#if CONFIG_PCI_DIRECT
18
+#define pci_max_bus		pcidirect_max_bus
19
+#define pci_read_config_byte	pcidirect_read_config_byte
20
+#define pci_read_config_word	pcidirect_read_config_word
21
+#define pci_read_config_dword	pcidirect_read_config_dword
22
+#define pci_write_config_byte	pcidirect_write_config_byte
23
+#define pci_write_config_word	pcidirect_write_config_word
24
+#define pci_write_config_dword	pcidirect_write_config_dword
25
+#else /* CONFIG_PCI_DIRECT */
26
+#define pci_max_bus		pcibios_max_bus
27
+#define pci_read_config_byte	pcibios_read_config_byte
28
+#define pci_read_config_word	pcibios_read_config_word
29
+#define pci_read_config_dword	pcibios_read_config_dword
30
+#define pci_write_config_byte	pcibios_write_config_byte
31
+#define pci_write_config_word	pcibios_write_config_word
32
+#define pci_write_config_dword	pcibios_write_config_dword
33
+#endif /* CONFIG_PCI_DIRECT */
34
+
35
+#endif /* _PCI_IO_H */

+ 122
- 0
src/arch/i386/include/pcibios.h View File

@@ -0,0 +1,122 @@
1
+#ifndef _PCIBIOS_H
2
+#define _PCIBIOS_H
3
+
4
+#include <stdint.h>
5
+
6
+/** @file
7
+ *
8
+ * PCI configuration space access via PCI BIOS
9
+ *
10
+ */
11
+
12
+struct pci_device;
13
+
14
+#define PCIBIOS_INSTALLATION_CHECK	0xb1010000
15
+#define PCIBIOS_READ_CONFIG_BYTE	0xb1080000
16
+#define PCIBIOS_READ_CONFIG_WORD	0xb1090000
17
+#define PCIBIOS_READ_CONFIG_DWORD	0xb10a0000
18
+#define PCIBIOS_WRITE_CONFIG_BYTE	0xb10b0000
19
+#define PCIBIOS_WRITE_CONFIG_WORD	0xb10c0000
20
+#define PCIBIOS_WRITE_CONFIG_DWORD	0xb10d0000
21
+
22
+extern int pcibios_max_bus ( void );
23
+extern int pcibios_read ( struct pci_device *pci, uint32_t command,
24
+			  uint32_t *value );
25
+extern int pcibios_write ( struct pci_device *pci, uint32_t command,
26
+			   uint32_t value );
27
+
28
+/**
29
+ * Read byte from PCI configuration space via PCI BIOS
30
+ *
31
+ * @v pci	PCI device
32
+ * @v where	Location within PCI configuration space
33
+ * @v value	Value read
34
+ * @ret rc	Return status code
35
+ */
36
+static inline __attribute__ (( always_inline )) int
37
+pcibios_read_config_byte ( struct pci_device *pci, unsigned int where,
38
+			   uint8_t *value ) {
39
+	uint32_t tmp;
40
+	int rc;
41
+
42
+	rc = pcibios_read ( pci, PCIBIOS_READ_CONFIG_BYTE | where, &tmp );
43
+	*value = tmp;
44
+	return rc;
45
+}
46
+
47
+/**
48
+ * Read word from PCI configuration space via PCI BIOS
49
+ *
50
+ * @v pci	PCI device
51
+ * @v where	Location within PCI configuration space
52
+ * @v value	Value read
53
+ * @ret rc	Return status code
54
+ */
55
+static inline __attribute__ (( always_inline )) int
56
+pcibios_read_config_word ( struct pci_device *pci, unsigned int where,
57
+			   uint16_t *value ) {
58
+	uint32_t tmp;
59
+	int rc;
60
+
61
+	rc = pcibios_read ( pci, PCIBIOS_READ_CONFIG_WORD | where, &tmp );
62
+	*value = tmp;
63
+	return rc;
64
+}
65
+
66
+/**
67
+ * Read dword from PCI configuration space via PCI BIOS
68
+ *
69
+ * @v pci	PCI device
70
+ * @v where	Location within PCI configuration space
71
+ * @v value	Value read
72
+ * @ret rc	Return status code
73
+ */
74
+static inline __attribute__ (( always_inline )) int
75
+pcibios_read_config_dword ( struct pci_device *pci, unsigned int where,
76
+			    uint32_t *value ) {
77
+	return pcibios_read ( pci, PCIBIOS_READ_CONFIG_DWORD | where, value );
78
+}
79
+
80
+/**
81
+ * Write byte to PCI configuration space via PCI BIOS
82
+ *
83
+ * @v pci	PCI device
84
+ * @v where	Location within PCI configuration space
85
+ * @v value	Value to be written
86
+ * @ret rc	Return status code
87
+ */
88
+static inline __attribute__ (( always_inline )) int
89
+pcibios_write_config_byte ( struct pci_device *pci, unsigned int where,
90
+			    uint8_t value ) {
91
+	return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_BYTE | where, value );
92
+}
93
+
94
+/**
95
+ * Write word to PCI configuration space via PCI BIOS
96
+ *
97
+ * @v pci	PCI device
98
+ * @v where	Location within PCI configuration space
99
+ * @v value	Value to be written
100
+ * @ret rc	Return status code
101
+ */
102
+static inline __attribute__ (( always_inline )) int
103
+pcibios_write_config_word ( struct pci_device *pci, unsigned int where,
104
+			    uint16_t value ) {
105
+	return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_BYTE | where, value );
106
+}
107
+
108
+/**
109
+ * Write dword to PCI configuration space via PCI BIOS
110
+ *
111
+ * @v pci	PCI device
112
+ * @v where	Location within PCI configuration space
113
+ * @v value	Value to be written
114
+ * @ret rc	Return status code
115
+ */
116
+static inline __attribute__ (( always_inline )) int
117
+pcibios_write_config_dword ( struct pci_device *pci, unsigned int where,
118
+			     uint32_t value ) {
119
+	return pcibios_write ( pci, PCIBIOS_WRITE_CONFIG_BYTE | where, value );
120
+}
121
+
122
+#endif /* _PCIBIOS_H */

+ 126
- 0
src/arch/i386/include/pcidirect.h View File

@@ -0,0 +1,126 @@
1
+#ifndef _PCIDIRECT_H
2
+#define _PCIDIRECT_H
3
+
4
+#include <stdint.h>
5
+#include <io.h>
6
+
7
+/** @file
8
+ *
9
+ * PCI configuration space access via Type 1 accesses
10
+ *
11
+ */
12
+
13
+#define PCIDIRECT_CONFIG_ADDRESS	0xcf8
14
+#define PCIDIRECT_CONFIG_DATA		0xcfc
15
+
16
+struct pci_device;
17
+
18
+extern void pcidirect_prepare ( struct pci_device *pci, int where );
19
+
20
+/**
21
+ * Determine maximum PCI bus number within system
22
+ *
23
+ * @ret max_bus		Maximum bus number
24
+ */
25
+static inline int pcidirect_max_bus ( void ) {
26
+	/* No way to work this out via Type 1 accesses */
27
+	return 0xff;
28
+}
29
+
30
+/**
31
+ * Read byte from PCI configuration space via Type 1 access
32
+ *
33
+ * @v pci	PCI device
34
+ * @v where	Location within PCI configuration space
35
+ * @v value	Value read
36
+ * @ret rc	Return status code
37
+ */
38
+static inline __attribute__ (( always_inline )) int
39
+pcidirect_read_config_byte ( struct pci_device *pci, unsigned int where,
40
+			     uint8_t *value ) {
41
+	pcidirect_prepare ( pci, where );
42
+	*value = inb ( PCIDIRECT_CONFIG_DATA + ( where & 3 ) );
43
+	return 0;
44
+}
45
+
46
+/**
47
+ * Read word from PCI configuration space via Type 1 access
48
+ *
49
+ * @v pci	PCI device
50
+ * @v where	Location within PCI configuration space
51
+ * @v value	Value read
52
+ * @ret rc	Return status code
53
+ */
54
+static inline __attribute__ (( always_inline )) int
55
+pcidirect_read_config_word ( struct pci_device *pci, unsigned int where,
56
+			     uint16_t *value ) {
57
+	pcidirect_prepare ( pci, where );
58
+	*value = inw ( PCIDIRECT_CONFIG_DATA + ( where & 2 ) );
59
+	return 0;
60
+}
61
+
62
+/**
63
+ * Read dword from PCI configuration space via Type 1 access
64
+ *
65
+ * @v pci	PCI device
66
+ * @v where	Location within PCI configuration space
67
+ * @v value	Value read
68
+ * @ret rc	Return status code
69
+ */
70
+static inline __attribute__ (( always_inline )) int
71
+pcidirect_read_config_dword ( struct pci_device *pci, unsigned int where,
72
+			      uint32_t *value ) {
73
+	pcidirect_prepare ( pci, where );
74
+	*value = inl ( PCIDIRECT_CONFIG_DATA + where );
75
+	return 0;
76
+}
77
+
78
+/**
79
+ * Write byte to PCI configuration space via Type 1 access
80
+ *
81
+ * @v pci	PCI device
82
+ * @v where	Location within PCI configuration space
83
+ * @v value	Value to be written
84
+ * @ret rc	Return status code
85
+ */
86
+static inline __attribute__ (( always_inline )) int
87
+pcidirect_write_config_byte ( struct pci_device *pci, unsigned int where,
88
+			      uint8_t value ) {
89
+	pcidirect_prepare ( pci, where );
90
+	outb ( value, PCIDIRECT_CONFIG_DATA + ( where & 3 ) );
91
+	return 0;
92
+}
93
+
94
+/**
95
+ * Write word to PCI configuration space via Type 1 access
96
+ *
97
+ * @v pci	PCI device
98
+ * @v where	Location within PCI configuration space
99
+ * @v value	Value to be written
100
+ * @ret rc	Return status code
101
+ */
102
+static inline __attribute__ (( always_inline )) int
103
+pcidirect_write_config_word ( struct pci_device *pci, unsigned int where,
104
+			      uint16_t value ) {
105
+	pcidirect_prepare ( pci, where );
106
+	outb ( value, PCIDIRECT_CONFIG_DATA + ( where & 2 ) );
107
+	return 0;
108
+}
109
+
110
+/**
111
+ * Write dword to PCI configuration space via Type 1 access
112
+ *
113
+ * @v pci	PCI device
114
+ * @v where	Location within PCI configuration space
115
+ * @v value	Value to be written
116
+ * @ret rc	Return status code
117
+ */
118
+static inline __attribute__ (( always_inline )) int
119
+pcidirect_write_config_dword ( struct pci_device *pci, unsigned int where,
120
+			       uint32_t value ) {
121
+	pcidirect_prepare ( pci, where );
122
+	outb ( value, PCIDIRECT_CONFIG_DATA + where );
123
+	return 0;
124
+}
125
+
126
+#endif /* _PCIDIRECT_H */

+ 4
- 11
src/drivers/bus/pci.c View File

@@ -38,15 +38,6 @@ static struct pci_driver pci_drivers_end[0] __table_end ( pci_drivers );
38 38
 
39 39
 static void pcibus_remove ( struct root_device *rootdev );
40 40
 
41
-/**
42
- * Maximum PCI bus number
43
- *
44
- * Architecture-specific code may know how many buses we have, in
45
- * which case it can overwrite this value.
46
- *
47
- */
48
-unsigned int pci_max_bus = 0xff;
49
-
50 41
 /**
51 42
  * Read PCI BAR
52 43
  *
@@ -242,13 +233,15 @@ static void unregister_pcidev ( struct pci_device *pci ) {
242 233
  */
243 234
 static int pcibus_probe ( struct root_device *rootdev ) {
244 235
 	struct pci_device *pci = NULL;
236
+	unsigned int max_bus;
245 237
 	unsigned int bus;
246 238
 	unsigned int devfn;
247
-	uint8_t hdrtype;
239
+	uint8_t hdrtype = 0;
248 240
 	uint32_t tmp;
249 241
 	int rc;
250 242
 
251
-	for ( bus = 0 ; bus <= pci_max_bus ; bus++ ) {
243
+	max_bus = pci_max_bus();
244
+	for ( bus = 0 ; bus <= max_bus ; bus++ ) {
252 245
 		for ( devfn = 0 ; devfn <= 0xff ; devfn++ ) {
253 246
 
254 247
 			/* Allocate struct pci_device */

+ 1
- 13
src/include/gpxe/pci.h View File

@@ -19,6 +19,7 @@
19 19
 #include <stdint.h>
20 20
 #include <gpxe/device.h>
21 21
 #include <gpxe/tables.h>
22
+#include <pci_io.h>
22 23
 #include "pci_ids.h"
23 24
 
24 25
 /*
@@ -318,19 +319,6 @@ struct pci_driver {
318 319
 	.name = _name,						\
319 320
 }
320 321
 
321
-extern unsigned int pci_max_bus;
322
-extern int pci_read_config_byte	( struct pci_device *pci, unsigned int where,
323
-				  uint8_t *value );
324
-extern int pci_write_config_byte ( struct pci_device *pci, unsigned int where,
325
-				   uint8_t value );
326
-extern int pci_read_config_word ( struct pci_device *pci, unsigned int where,
327
-				  uint16_t *value );
328
-extern int pci_write_config_word ( struct pci_device *pci, unsigned int where,
329
-				   uint16_t value );
330
-extern int pci_read_config_dword ( struct pci_device *pci, unsigned int where,
331
-				   uint32_t *value );
332
-extern int pci_write_config_dword ( struct pci_device *pci, unsigned int where,
333
-				    uint32_t value );
334 322
 extern void adjust_pci_device ( struct pci_device *pci );
335 323
 extern unsigned long pci_bar_start ( struct pci_device *pci,
336 324
 				     unsigned int reg );

Loading…
Cancel
Save