2006-09-26 12:52:41 +04:00
# include <linux/kernel.h>
2006-09-26 12:52:41 +04:00
# include <linux/pci.h>
2006-09-26 12:52:41 +04:00
# include <asm/pci-direct.h>
# include <asm/io.h>
2008-12-27 16:02:28 +03:00
# include <asm/pci_x86.h>
2006-09-26 12:52:41 +04:00
/* Direct PCI access. This is used for PCI accesses in early boot before
the PCI subsystem works . */
u32 read_pci_config ( u8 bus , u8 slot , u8 func , u8 offset )
{
u32 v ;
outl ( 0x80000000 | ( bus < < 16 ) | ( slot < < 11 ) | ( func < < 8 ) | offset , 0xcf8 ) ;
v = inl ( 0xcfc ) ;
return v ;
}
u8 read_pci_config_byte ( u8 bus , u8 slot , u8 func , u8 offset )
{
u8 v ;
outl ( 0x80000000 | ( bus < < 16 ) | ( slot < < 11 ) | ( func < < 8 ) | offset , 0xcf8 ) ;
v = inb ( 0xcfc + ( offset & 3 ) ) ;
return v ;
}
u16 read_pci_config_16 ( u8 bus , u8 slot , u8 func , u8 offset )
{
u16 v ;
outl ( 0x80000000 | ( bus < < 16 ) | ( slot < < 11 ) | ( func < < 8 ) | offset , 0xcf8 ) ;
v = inw ( 0xcfc + ( offset & 2 ) ) ;
return v ;
}
void write_pci_config ( u8 bus , u8 slot , u8 func , u8 offset ,
u32 val )
{
outl ( 0x80000000 | ( bus < < 16 ) | ( slot < < 11 ) | ( func < < 8 ) | offset , 0xcf8 ) ;
outl ( val , 0xcfc ) ;
}
2006-09-26 12:52:41 +04:00
2006-12-07 04:14:10 +03:00
void write_pci_config_byte ( u8 bus , u8 slot , u8 func , u8 offset , u8 val )
{
outl ( 0x80000000 | ( bus < < 16 ) | ( slot < < 11 ) | ( func < < 8 ) | offset , 0xcf8 ) ;
2008-05-23 01:35:21 +04:00
outb ( val , 0xcfc + ( offset & 3 ) ) ;
}
void write_pci_config_16 ( u8 bus , u8 slot , u8 func , u8 offset , u16 val )
{
outl ( 0x80000000 | ( bus < < 16 ) | ( slot < < 11 ) | ( func < < 8 ) | offset , 0xcf8 ) ;
outw ( val , 0xcfc + ( offset & 2 ) ) ;
2006-12-07 04:14:10 +03:00
}
2006-09-26 12:52:41 +04:00
int early_pci_allowed ( void )
{
return ( pci_probe & ( PCI_PROBE_CONF1 | PCI_PROBE_NOEARLY ) ) = =
PCI_PROBE_CONF1 ;
}
2008-05-23 01:35:11 +04:00
void early_dump_pci_device ( u8 bus , u8 slot , u8 func )
{
int i ;
int j ;
u32 val ;
2009-01-14 20:04:30 +03:00
printk ( KERN_INFO " pci 0000:%02x:%02x.%d config space: " ,
bus , slot , func ) ;
2008-05-23 01:35:11 +04:00
for ( i = 0 ; i < 256 ; i + = 4 ) {
if ( ! ( i & 0x0f ) )
2009-01-14 20:04:30 +03:00
printk ( " \n %02x: " , i ) ;
2008-05-23 01:35:11 +04:00
val = read_pci_config ( bus , slot , func , i ) ;
for ( j = 0 ; j < 4 ; j + + ) {
printk ( " %02x " , val & 0xff ) ;
val > > = 8 ;
}
}
printk ( " \n " ) ;
}
void early_dump_pci_devices ( void )
{
unsigned bus , slot , func ;
if ( ! early_pci_allowed ( ) )
return ;
for ( bus = 0 ; bus < 256 ; bus + + ) {
for ( slot = 0 ; slot < 32 ; slot + + ) {
for ( func = 0 ; func < 8 ; func + + ) {
u32 class ;
u8 type ;
2009-01-14 20:04:25 +03:00
2008-05-23 01:35:11 +04:00
class = read_pci_config ( bus , slot , func ,
PCI_CLASS_REVISION ) ;
if ( class = = 0xffffffff )
2009-01-14 20:04:25 +03:00
continue ;
2008-05-23 01:35:11 +04:00
early_dump_pci_device ( bus , slot , func ) ;
2009-01-14 20:04:25 +03:00
if ( func = = 0 ) {
type = read_pci_config_byte ( bus , slot ,
func ,
2008-05-23 01:35:11 +04:00
PCI_HEADER_TYPE ) ;
2009-01-14 20:04:25 +03:00
if ( ! ( type & 0x80 ) )
break ;
}
2008-05-23 01:35:11 +04:00
}
}
}
}