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