2005-03-14 Joel Sherrill <joel@OARcorp.com>

* pci/pci.c, pci/pci.h, pci/pcifinddevice.c: Continue PCI API
	unification. All use pci_find_device(). Also reformat to remove tabs.
This commit is contained in:
Joel Sherrill
2005-03-14 21:43:30 +00:00
parent 48e329fbd6
commit 0943f48db1
4 changed files with 471 additions and 464 deletions

View File

@@ -1,3 +1,8 @@
2005-03-14 Joel Sherrill <joel@OARcorp.com>
* pci/pci.c, pci/pci.h, pci/pcifinddevice.c: Continue PCI API
unification. All use pci_find_device(). Also reformat to remove tabs.
2005-03-04 Joel Sherrill <joel@OARcorp.com> 2005-03-04 Joel Sherrill <joel@OARcorp.com>
* pci/pci.c, pci/pcifinddevice.c, startup/bspstart.c: Make PCI * pci/pci.c, pci/pcifinddevice.c, startup/bspstart.c: Make PCI

View File

@@ -25,17 +25,17 @@
/* allow for overriding these definitions */ /* allow for overriding these definitions */
#ifndef PCI_CONFIG_ADDR #ifndef PCI_CONFIG_ADDR
#define PCI_CONFIG_ADDR 0xcf8 #define PCI_CONFIG_ADDR 0xcf8
#endif #endif
#ifndef PCI_CONFIG_DATA #ifndef PCI_CONFIG_DATA
#define PCI_CONFIG_DATA 0xcfc #define PCI_CONFIG_DATA 0xcfc
#endif #endif
#define PCI_INVALID_VENDORDEVICEID 0xffffffff #define PCI_INVALID_VENDORDEVICEID 0xffffffff
#define PCI_MULTI_FUNCTION 0x80 #define PCI_MULTI_FUNCTION 0x80
/* define a shortcut */ /* define a shortcut */
#define pci BSP_pci_configuration #define pci BSP_pci_configuration
/* /*
* Bit encode for PCI_CONFIG_HEADER_TYPE register * Bit encode for PCI_CONFIG_HEADER_TYPE register
@@ -43,181 +43,243 @@
unsigned char ucMaxPCIBus; unsigned char ucMaxPCIBus;
static int static int
indirect_pci_read_config_byte(unsigned char bus, unsigned char slot, indirect_pci_read_config_byte(
unsigned char function, unsigned char bus,
unsigned char offset, unsigned char *val) { unsigned char slot,
out_be32((unsigned int*) pci.pci_config_addr, unsigned char function,
0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24)); unsigned char offset,
*val = in_8(pci.pci_config_data + (offset&3)); unsigned char *val
return PCIBIOS_SUCCESSFUL; ) {
out_be32((unsigned int*) pci.pci_config_addr,
0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24));
*val = in_8(pci.pci_config_data + (offset&3));
return PCIBIOS_SUCCESSFUL;
} }
static int static int
indirect_pci_read_config_word(unsigned char bus, unsigned char slot, indirect_pci_read_config_word(
unsigned char function, unsigned char bus,
unsigned char offset, unsigned short *val) { unsigned char slot,
*val = 0xffff; unsigned char function,
if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; unsigned char offset,
out_be32((unsigned int*) pci.pci_config_addr, unsigned short *val
0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24)); ) {
*val = in_le16((volatile unsigned short *)(pci.pci_config_data + (offset&3))); *val = 0xffff;
return PCIBIOS_SUCCESSFUL; if (offset&1)
return PCIBIOS_BAD_REGISTER_NUMBER;
out_be32((unsigned int*) pci.pci_config_addr,
0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24));
*val = in_le16((volatile unsigned short *)(pci.pci_config_data + (offset&3)));
return PCIBIOS_SUCCESSFUL;
} }
static int static int
indirect_pci_read_config_dword(unsigned char bus, unsigned char slot, indirect_pci_read_config_dword(
unsigned char function, unsigned char bus,
unsigned char offset, unsigned int *val) { unsigned char slot,
*val = 0xffffffff; unsigned char function,
if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; unsigned char offset,
out_be32((unsigned int*) pci.pci_config_addr, unsigned int *val
0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|(offset<<24)); ) {
*val = in_le32((volatile unsigned int *)pci.pci_config_data); *val = 0xffffffff;
return PCIBIOS_SUCCESSFUL; if (offset&3)
return PCIBIOS_BAD_REGISTER_NUMBER;
out_be32((unsigned int*) pci.pci_config_addr,
0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|(offset<<24));
*val = in_le32((volatile unsigned int *)pci.pci_config_data);
return PCIBIOS_SUCCESSFUL;
} }
static int static int
indirect_pci_write_config_byte(unsigned char bus, unsigned char slot, indirect_pci_write_config_byte(
unsigned char function, unsigned char bus,
unsigned char offset, unsigned char val) { unsigned char slot,
out_be32((unsigned int*) pci.pci_config_addr, unsigned char function,
0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24)); unsigned char offset,
out_8(pci.pci_config_data + (offset&3), val); unsigned char val
return PCIBIOS_SUCCESSFUL; ) {
out_be32((unsigned int*) pci.pci_config_addr,
0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24));
out_8(pci.pci_config_data + (offset&3), val);
return PCIBIOS_SUCCESSFUL;
} }
static int static int
indirect_pci_write_config_word(unsigned char bus, unsigned char slot, indirect_pci_write_config_word(
unsigned char function, unsigned char bus,
unsigned char offset, unsigned short val) { unsigned char slot,
if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; unsigned char function,
out_be32((unsigned int*) pci.pci_config_addr, unsigned char offset,
0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24)); unsigned short val
out_le16((volatile unsigned short *)(pci.pci_config_data + (offset&3)), val); ) {
return PCIBIOS_SUCCESSFUL; if (offset&1)
return PCIBIOS_BAD_REGISTER_NUMBER;
out_be32((unsigned int*) pci.pci_config_addr,
0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|((offset&~3)<<24));
out_le16((volatile unsigned short *)(pci.pci_config_data + (offset&3)), val);
return PCIBIOS_SUCCESSFUL;
} }
static int static int
indirect_pci_write_config_dword(unsigned char bus, unsigned char slot, indirect_pci_write_config_dword(
unsigned char function, unsigned char bus,
unsigned char offset, unsigned int val) { unsigned char slot,
if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; unsigned char function,
out_be32((unsigned int*) pci.pci_config_addr, unsigned char offset,
0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|(offset<<24)); unsigned int val
out_le32((volatile unsigned int *)pci.pci_config_data, val); ) {
return PCIBIOS_SUCCESSFUL; if (offset&3)
return PCIBIOS_BAD_REGISTER_NUMBER;
out_be32((unsigned int*) pci.pci_config_addr,
0x80|(bus<<8)|(PCI_DEVFN(slot,function)<<16)|(offset<<24));
out_le32((volatile unsigned int *)pci.pci_config_data, val);
return PCIBIOS_SUCCESSFUL;
} }
const pci_config_access_functions pci_indirect_functions = { const pci_config_access_functions pci_indirect_functions = {
indirect_pci_read_config_byte, indirect_pci_read_config_byte,
indirect_pci_read_config_word, indirect_pci_read_config_word,
indirect_pci_read_config_dword, indirect_pci_read_config_dword,
indirect_pci_write_config_byte, indirect_pci_write_config_byte,
indirect_pci_write_config_word, indirect_pci_write_config_word,
indirect_pci_write_config_dword indirect_pci_write_config_dword
}; };
pci_config BSP_pci_configuration = {(volatile unsigned char*)PCI_CONFIG_ADDR, pci_config BSP_pci_configuration = {
(volatile unsigned char*)PCI_CONFIG_DATA, (volatile unsigned char*)PCI_CONFIG_ADDR,
&pci_indirect_functions}; (volatile unsigned char*)PCI_CONFIG_DATA,
&pci_indirect_functions
};
static int static int
direct_pci_read_config_byte(unsigned char bus, unsigned char slot, direct_pci_read_config_byte(
unsigned char function, unsigned char bus,
unsigned char offset, unsigned char *val) { unsigned char slot,
if (bus != 0 || (1<<slot & 0xff8007fe)) { unsigned char function,
*val=0xff; unsigned char offset,
return PCIBIOS_DEVICE_NOT_FOUND; unsigned char *val
} ) {
*val=in_8(pci.pci_config_data + ((1<<slot)&~1) if (bus != 0 || (1<<slot & 0xff8007fe)) {
+ (function<<8) + offset); *val=0xff;
return PCIBIOS_SUCCESSFUL; return PCIBIOS_DEVICE_NOT_FOUND;
}
*val=in_8(pci.pci_config_data + ((1<<slot)&~1)
+ (function<<8) + offset);
return PCIBIOS_SUCCESSFUL;
} }
static int static int
direct_pci_read_config_word(unsigned char bus, unsigned char slot, direct_pci_read_config_word(
unsigned char function, unsigned char bus,
unsigned char offset, unsigned short *val) { unsigned char slot,
*val = 0xffff; unsigned char function,
if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; unsigned char offset,
if (bus != 0 || (1<<slot & 0xff8007fe)) { unsigned short *val
return PCIBIOS_DEVICE_NOT_FOUND; ) {
} *val = 0xffff;
*val=in_le16((volatile unsigned short *) if (offset&1)
(pci.pci_config_data + ((1<<slot)&~1) return PCIBIOS_BAD_REGISTER_NUMBER;
+ (function<<8) + offset)); if (bus != 0 || (1<<slot & 0xff8007fe))
return PCIBIOS_SUCCESSFUL; return PCIBIOS_DEVICE_NOT_FOUND;
*val=in_le16((volatile unsigned short *)
(pci.pci_config_data + ((1<<slot)&~1)
+ (function<<8) + offset));
return PCIBIOS_SUCCESSFUL;
} }
static int static int
direct_pci_read_config_dword(unsigned char bus, unsigned char slot, direct_pci_read_config_dword(
unsigned char function, unsigned char bus,
unsigned char offset, unsigned int *val) { unsigned char slot,
*val = 0xffffffff; unsigned char function,
if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; unsigned char offset,
if (bus != 0 || (1<<slot & 0xff8007fe)) { unsigned int *val
return PCIBIOS_DEVICE_NOT_FOUND; ) {
} *val = 0xffffffff;
*val=in_le32((volatile unsigned int *) if (offset&3)
(pci.pci_config_data + ((1<<slot)&~1) return PCIBIOS_BAD_REGISTER_NUMBER;
+ (function<<8) + offset)); if (bus != 0 || (1<<slot & 0xff8007fe))
return PCIBIOS_SUCCESSFUL; return PCIBIOS_DEVICE_NOT_FOUND;
*val=in_le32((volatile unsigned int *)
(pci.pci_config_data + ((1<<slot)&~1)
+ (function<<8) + offset));
return PCIBIOS_SUCCESSFUL;
} }
static int static int
direct_pci_write_config_byte(unsigned char bus, unsigned char slot, direct_pci_write_config_byte(
unsigned char function, unsigned char bus,
unsigned char offset, unsigned char val) { unsigned char slot,
if (bus != 0 || (1<<slot & 0xff8007fe)) { unsigned char function,
return PCIBIOS_DEVICE_NOT_FOUND; unsigned char offset,
} unsigned char val
out_8(pci.pci_config_data + ((1<<slot)&~1) ) {
+ (function<<8) + offset, if (bus != 0 || (1<<slot & 0xff8007fe))
val); return PCIBIOS_DEVICE_NOT_FOUND;
return PCIBIOS_SUCCESSFUL;
out_8(pci.pci_config_data + ((1<<slot)&~1)
+ (function<<8) + offset,
val);
return PCIBIOS_SUCCESSFUL;
} }
static int static int
direct_pci_write_config_word(unsigned char bus, unsigned char slot, direct_pci_write_config_word(
unsigned char function, unsigned char bus,
unsigned char offset, unsigned short val) { unsigned char slot,
if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; unsigned char function,
if (bus != 0 || (1<<slot & 0xff8007fe)) { unsigned char offset,
return PCIBIOS_DEVICE_NOT_FOUND; unsigned short val
} ) {
out_le16((volatile unsigned short *) if (offset&1)
(pci.pci_config_data + ((1<<slot)&~1) return PCIBIOS_BAD_REGISTER_NUMBER;
+ (function<<8) + offset), if (bus != 0 || (1<<slot & 0xff8007fe))
val); return PCIBIOS_DEVICE_NOT_FOUND;
return PCIBIOS_SUCCESSFUL;
out_le16((volatile unsigned short *)
(pci.pci_config_data + ((1<<slot)&~1)
+ (function<<8) + offset),
val);
return PCIBIOS_SUCCESSFUL;
} }
static int static int
direct_pci_write_config_dword(unsigned char bus, unsigned char slot, direct_pci_write_config_dword(
unsigned char function, unsigned char bus,
unsigned char offset, unsigned int val) { unsigned char slot,
if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; unsigned char function,
if (bus != 0 || (1<<slot & 0xff8007fe)) { unsigned char offset,
return PCIBIOS_DEVICE_NOT_FOUND; unsigned int val
} ) {
out_le32((volatile unsigned int *) if (offset&3)
(pci.pci_config_data + ((1<<slot)&~1) return PCIBIOS_BAD_REGISTER_NUMBER;
+ (function<<8) + offset), if (bus != 0 || (1<<slot & 0xff8007fe))
val); return PCIBIOS_DEVICE_NOT_FOUND;
return PCIBIOS_SUCCESSFUL;
out_le32((volatile unsigned int *)
(pci.pci_config_data + ((1<<slot)&~1)
+ (function<<8) + offset),
val);
return PCIBIOS_SUCCESSFUL;
} }
const pci_config_access_functions pci_direct_functions = { const pci_config_access_functions pci_direct_functions = {
direct_pci_read_config_byte, direct_pci_read_config_byte,
direct_pci_read_config_word, direct_pci_read_config_word,
direct_pci_read_config_dword, direct_pci_read_config_dword,
direct_pci_write_config_byte, direct_pci_write_config_byte,
direct_pci_write_config_word, direct_pci_write_config_word,
direct_pci_write_config_dword direct_pci_write_config_dword
}; };
#define PRINT_MSG() \ #define PRINT_MSG() \
printk("pci : Device %d:%02x routed to interrupt_line %d\n", pbus, pslot, int_name ) printk("pci : Device %d:%02x routed to interrupt_line %d\n", \
pbus, pslot, int_name )
/* /*
** Validate a test interrupt name and print a warning if its not one of ** Validate a test interrupt name and print a warning if its not one of
@@ -229,299 +291,271 @@ static int test_intname(
int pslot, int pslot,
int int_pin, int int_pin,
int int_name int int_name
) ) {
{ int j, k;
int j, k; int _nopin= -1, _noname= -1;
int _nopin= -1, _noname= -1;
for(j=0; row->pin_route[j].pin > -1; j++) for (j=0; row->pin_route[j].pin > -1; j++) {
{ if ( row->pin_route[j].pin == int_pin ) {
if( row->pin_route[j].pin == int_pin ) _nopin = 0;
{
_nopin = 0;
for(k=0; k<4 && row->pin_route[j].int_name[k] > -1; k++ ) for (k=0; k<4 && row->pin_route[j].int_name[k] > -1; k++ ) {
{ if ( row->pin_route[j].int_name[k] == int_name ) {
if( row->pin_route[j].int_name[k] == int_name ){ _noname=0; break; } _noname=0; break;
} }
break;
}
} }
break;
}
}
if( _nopin ) if ( _nopin ) {
{ printk("pci : Device %d:%02x supplied a bogus interrupt_pin %d\n",
printk("pci : Device %d:%02x supplied a bogus interrupt_pin %d\n", pbus, pslot, int_pin ); pbus, pslot, int_pin );
return -1; return -1;
} } else {
else if ( _noname )
{ printk("pci : Device %d:%02x supplied a suspicious interrupt_line %d,"
if( _noname ) " using it anyway\n", pbus, pslot, int_name );
printk("pci : Device %d:%02x supplied a suspicious interrupt_line %d, using it anyway\n", pbus, pslot, int_name ); }
} return 0;
return 0;
} }
struct pcibridge struct pcibridge
{ {
int bus,slot; int bus;
int slot;
}; };
static int FindPCIbridge( int mybus, struct pcibridge *pb ) static int FindPCIbridge( int mybus, struct pcibridge *pb )
{ {
int pbus, pslot; int pbus, pslot;
uint8_t bussec, buspri; uint8_t bussec, buspri;
uint16_t devid, vendorid, dclass; uint16_t devid, vendorid, dclass;
for(pbus=0; pbus< BusCountPCI(); pbus++) for(pbus=0; pbus< BusCountPCI(); pbus++) {
{ for(pslot=0; pslot< PCI_MAX_DEVICES; pslot++) {
for(pslot=0; pslot< PCI_MAX_DEVICES; pslot++) pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid);
{ if ( devid == 0xffff ) continue;
pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid);
if( devid == 0xffff ) continue;
pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &vendorid); pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &vendorid);
if( vendorid == 0xffff ) continue; if ( vendorid == 0xffff ) continue;
pci_read_config_word(pbus, pslot, 0, PCI_CLASS_DEVICE, &dclass); pci_read_config_word(pbus, pslot, 0, PCI_CLASS_DEVICE, &dclass);
if( dclass == PCI_CLASS_BRIDGE_PCI ) if ( dclass == PCI_CLASS_BRIDGE_PCI ) {
{ pci_read_config_byte(pbus, pslot, 0, PCI_PRIMARY_BUS, &buspri);
pci_read_config_byte(pbus, pslot, 0, PCI_PRIMARY_BUS, &buspri); pci_read_config_byte(pbus, pslot, 0, PCI_SECONDARY_BUS, &bussec);
pci_read_config_byte(pbus, pslot, 0, PCI_SECONDARY_BUS, &bussec);
#if 0 #if 0
printk("pci : Found bridge at %d:%d, mybus %d, pribus %d, secbus %d ", pbus, pslot, mybus, buspri, bussec ); printk("pci : Found bridge at %d:%d, mybus %d, pribus %d, secbus %d ",
pbus, pslot, mybus, buspri, bussec );
#endif #endif
if( bussec == mybus ) if ( bussec == mybus ) {
{
#if 0 #if 0
printk("match\n"); printk("match\n");
#endif #endif
/* found our nearest bridge going towards the root */ /* found our nearest bridge going towards the root */
pb->bus = pbus; pb->bus = pbus;
pb->slot = pslot; pb->slot = pslot;
return 0; return 0;
} }
#if 0 #if 0
printk("no match\n"); printk("no match\n");
#endif #endif
}
} }
}
} }
return -1; return -1;
} }
void FixupPCI( const struct _int_map *bspmap, int (*swizzler)(int,int) ) void FixupPCI( const struct _int_map *bspmap, int (*swizzler)(int,int) )
{ {
unsigned char cvalue; unsigned char cvalue;
uint16_t devid; uint16_t devid;
int ismatch, i, j, pbus, pslot, int_pin, int_name; int ismatch, i, j, pbus, pslot, int_pin, int_name;
/* /*
** If the device has a non-zero INTERRUPT_PIN, assign a bsp-specific * If the device has a non-zero INTERRUPT_PIN, assign a bsp-specific
** INTERRUPT_NAME if one isn't already in place. Then, drivers can * INTERRUPT_NAME if one isn't already in place. Then, drivers can
** trivially use INTERRUPT_NAME to hook up with devices. * trivially use INTERRUPT_NAME to hook up with devices.
*/ */
for(pbus=0; pbus< BusCountPCI(); pbus++) for (pbus=0; pbus< BusCountPCI(); pbus++) {
{ for (pslot=0; pslot< PCI_MAX_DEVICES; pslot++) {
for(pslot=0; pslot< PCI_MAX_DEVICES; pslot++) pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid);
{ if ( devid == 0xffff ) continue;
pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid);
if( devid == 0xffff ) continue;
/* got a device */ /* got a device */
pci_read_config_byte( pbus, pslot, 0, PCI_INTERRUPT_PIN, &cvalue); pci_read_config_byte( pbus, pslot, 0, PCI_INTERRUPT_PIN, &cvalue);
int_pin = cvalue; int_pin = cvalue;
pci_read_config_byte( pbus, pslot, 0, PCI_INTERRUPT_LINE, &cvalue); pci_read_config_byte( pbus, pslot, 0, PCI_INTERRUPT_LINE, &cvalue);
int_name = cvalue; int_name = cvalue;
/* printk("pci : device %d:%02x devid %04x, intpin %d, intline %d\n", pbus, pslot, devid, int_pin, int_name ); */ /* printk("pci : device %d:%02x devid %04x, intpin %d, intline %d\n",
pbus, pslot, devid, int_pin, int_name ); */
#if 0 #if 0
{ {
unsigned short cmd,stat; unsigned short cmd,stat;
unsigned char lat, seclat, csize; unsigned char lat, seclat, csize;
pci_read_config_word(pbus,pslot,0,PCI_COMMAND, &cmd ); pci_read_config_word(pbus,pslot,0,PCI_COMMAND, &cmd );
pci_read_config_word(pbus,pslot,0,PCI_STATUS, &stat ); pci_read_config_word(pbus,pslot,0,PCI_STATUS, &stat );
pci_read_config_byte(pbus,pslot,0,PCI_LATENCY_TIMER, &lat ); pci_read_config_byte(pbus,pslot,0,PCI_LATENCY_TIMER, &lat );
pci_read_config_byte(pbus,pslot,0,PCI_SEC_LATENCY_TIMER, &seclat ); pci_read_config_byte(pbus,pslot,0,PCI_SEC_LATENCY_TIMER, &seclat );
pci_read_config_byte(pbus,pslot,0,PCI_CACHE_LINE_SIZE, &csize ); pci_read_config_byte(pbus,pslot,0,PCI_CACHE_LINE_SIZE, &csize );
printk("pci : device %d:%02x cmd %04X, stat %04X, latency %d, sec_latency %d, clsize %d\n", pbus, pslot, printk("pci : device %d:%02x cmd %04X, stat %04X, latency %d, "
cmd, " sec_latency %d, clsize %d\n", pbus, pslot, cmd, stat,
stat, lat, seclat, csize);
lat, }
seclat,
csize);
}
#endif #endif
if( int_pin > 0 ) if ( int_pin > 0 ) {
{ ismatch = 0;
ismatch = 0;
/* /*
** first run thru the bspmap table and see if we have an explicit configuration * first run thru the bspmap table and see if we have an
*/ * explicit configuration
for(i=0; bspmap[i].bus > -1; i++) */
{ for (i=0; bspmap[i].bus > -1; i++) {
if( bspmap[i].bus == pbus && bspmap[i].slot == pslot ) if ( bspmap[i].bus == pbus && bspmap[i].slot == pslot ) {
{ ismatch = -1;
ismatch = -1; /* we have a record in the table that gives specific
/* we have a record in the table that gives specific * pins and interrupts for devices in this slot */
* pins and interrupts for devices in this slot */ if ( int_name == 255 ) {
if( int_name == 255 ) /* find the vector associated with whatever pin the
{ * device gives us
/* find the vector associated with whatever pin the device gives us */ */
for( int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++ ) for ( int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++ ) {
{ if ( bspmap[i].pin_route[j].pin == int_pin ) {
if( bspmap[i].pin_route[j].pin == int_pin ) int_name = bspmap[i].pin_route[j].int_name[0];
{
int_name = bspmap[i].pin_route[j].int_name[0];
break;
}
}
if( int_name == -1 )
{
printk("pci : Unable to resolve device %d:%d w/ swizzled int pin %i to an interrupt_line.\n", pbus, pslot, int_pin );
}
else
{
PRINT_MSG();
pci_write_config_byte(pbus,pslot,0,PCI_INTERRUPT_LINE,(cvalue= int_name, cvalue));
}
}
else
{
test_intname( &bspmap[i],pbus,pslot,int_pin,int_name);
}
break; break;
} }
}
if ( int_name == -1 ) {
printk("pci : Unable to resolve device %d:%d w/ swizzled int "
"pin %i to an interrupt_line.\n", pbus, pslot, int_pin );
} else {
PRINT_MSG();
pci_write_config_byte( pbus,pslot,0,
PCI_INTERRUPT_LINE,(cvalue= int_name, cvalue));
}
} else {
test_intname( &bspmap[i],pbus,pslot,int_pin,int_name);
}
break;
}
}
if ( !ismatch ) {
/*
* no match, which means we're on a bus someplace. Work
* backwards from it to one of our defined busses,
* swizzling thru each bridge on the way.
*/
/* keep pbus, pslot pointed to the device being
* configured while we track down the bridges using
* tbus,tslot. We keep searching the routing table because
* we may end up finding our bridge in it
*/
int tbus= pbus, tslot= pslot;
for (;;) {
for (i=0; bspmap[i].bus > -1; i++) {
if ( bspmap[i].bus == tbus &&
(bspmap[i].slot == tslot || bspmap[i].slot == -1) ) {
ismatch = -1;
/* found a record for this bus, so swizzle the
* int_pin which we then use to find the
* interrupt_name.
*/
if ( int_name == 255 ) {
/*
* FIXME. I can't believe this little hack
* is right. It does not yield an error in
* convienently simple situations.
*/
if ( tbus ) int_pin = (*swizzler)(tslot,int_pin);
/*
* int_pin points to the interrupt channel
* this card ends up delivering interrupts
* on. Find the int_name servicing it.
*/
for (int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++){
if ( bspmap[i].pin_route[j].pin == int_pin ) {
int_name = bspmap[i].pin_route[j].int_name[0];
break;
}
}
if ( int_name == -1 ) {
printk("pci : Unable to resolve device %d:%d w/ swizzled "
"int pin %i to an interrupt_line.\n",
pbus, pslot, int_pin );
} else {
PRINT_MSG();
pci_write_config_byte(pbus,pslot,0,
PCI_INTERRUPT_LINE,(cvalue=int_name, cvalue));
}
} else {
test_intname(&bspmap[i],pbus,pslot,int_pin,int_name);
}
goto donesearch;
}
} }
if( !ismatch ) if ( !ismatch ) {
{ struct pcibridge pb;
/*
** no match, which means we're on a bus someplace. Work /*
** backwards from it to one of our defined busses, * Haven't found our bus in the int map, so work
** swizzling thru each bridge on the way. * upwards thru the bridges till we find it.
*/ */
/* keep pbus, pslot pointed to the device being if ( FindPCIbridge( tbus, &pb )== 0 ) {
configured while we track down the bridges using int_pin = (*swizzler)(tslot,int_pin);
tbus,tslot. We keep searching the routing table because
we may end up finding our bridge in it */
int tbus= pbus, tslot= pslot; /* our next bridge up is on pb.bus, pb.slot- now
* instead of pointing to the device we're
* trying to configure, we move from bridge to
* bridge.
*/
for(;;) tbus = pb.bus;
{ tslot = pb.slot;
} else {
for(i=0; bspmap[i].bus > -1; i++) printk("pci : No bridge from bus %i towards root found\n",
{ tbus );
if( bspmap[i].bus == tbus && (bspmap[i].slot == tslot || bspmap[i].slot == -1) ) goto donesearch;
{ }
ismatch = -1;
/* found a record for this bus, so swizzle the
* int_pin which we then use to find the
* interrupt_name.
*/
if( int_name == 255 )
{
/*
** FIXME. I can't believe this little hack
** is right. It does not yield an error in
** convienently simple situations.
*/
if( tbus ) int_pin = (*swizzler)(tslot,int_pin);
/*
** int_pin points to the interrupt channel
** this card ends up delivering interrupts
** on. Find the int_name servicing it.
*/
for( int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++ )
{
if( bspmap[i].pin_route[j].pin == int_pin )
{
int_name = bspmap[i].pin_route[j].int_name[0];
break;
}
}
if( int_name == -1 )
{
printk("pci : Unable to resolve device %d:%d w/ swizzled int pin %i to an interrupt_line.\n", pbus, pslot, int_pin );
}
else
{
PRINT_MSG();
pci_write_config_byte(pbus,pslot,0,PCI_INTERRUPT_LINE,(cvalue= int_name, cvalue));
}
}
else
{
test_intname(&bspmap[i],pbus,pslot,int_pin,int_name);
}
goto donesearch;
}
}
if( !ismatch )
{
struct pcibridge pb;
/*
** Haven't found our bus in the int map, so work
** upwards thru the bridges till we find it.
*/
if( FindPCIbridge( tbus, &pb )== 0 )
{
int_pin = (*swizzler)(tslot,int_pin);
/* our next bridge up is on pb.bus, pb.slot- now
** instead of pointing to the device we're
** trying to configure, we move from bridge to
** bridge.
*/
tbus = pb.bus;
tslot = pb.slot;
}
else
{
printk("pci : No bridge from bus %i towards root found\n", tbus );
goto donesearch;
}
}
}
} }
donesearch: }
}
donesearch:
if( !ismatch && int_pin != 0 && int_name == 255 ) if ( !ismatch && int_pin != 0 && int_name == 255 ) {
{ printk("pci : Unable to match device %d:%d with an int "
printk("pci : Unable to match device %d:%d with an int routing table entry\n", pbus, pslot ); "routing table entry\n", pbus, pslot );
} }
}
} }
}
} }
} }
/* /*
* This routine determines the maximum bus number in the system * This routine determines the maximum bus number in the system
*/ */
void pci_initialize() int pci_initialize()
{ {
extern void detect_host_bridge(); extern void detect_host_bridge();
unsigned char ucSlotNumber, ucFnNumber, ucNumFuncs; unsigned char ucSlotNumber, ucFnNumber, ucNumFuncs;
@@ -534,66 +568,41 @@ void pci_initialize()
/* /*
* Scan PCI bus 0 looking for PCI-PCI bridges * Scan PCI bus 0 looking for PCI-PCI bridges
*/ */
for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) { for (ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
(void)pci_read_config_dword(0, pci_read_config_dword(0, ucSlotNumber, 0, PCI_VENDOR_ID, &ulDeviceID);
ucSlotNumber, if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
0, /* This slot is empty */
PCI_VENDOR_ID,
&ulDeviceID);
if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
/*
* This slot is empty
*/
continue; continue;
} }
(void)pci_read_config_byte(0, pci_read_config_byte(0, ucSlotNumber, 0, PCI_HEADER_TYPE, &ucHeader);
ucSlotNumber, if (ucHeader&PCI_MULTI_FUNCTION) {
0,
PCI_HEADER_TYPE,
&ucHeader);
if(ucHeader&PCI_MULTI_FUNCTION) {
ucNumFuncs=PCI_MAX_FUNCTIONS; ucNumFuncs=PCI_MAX_FUNCTIONS;
} } else {
else {
ucNumFuncs=1; ucNumFuncs=1;
} }
for(ucFnNumber=0;ucFnNumber<ucNumFuncs;ucFnNumber++) { for (ucFnNumber=0;ucFnNumber<ucNumFuncs;ucFnNumber++) {
(void)pci_read_config_dword(0, pci_read_config_dword(0, ucSlotNumber, ucFnNumber,
ucSlotNumber, PCI_VENDOR_ID, &ulDeviceID);
ucFnNumber, if (ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
PCI_VENDOR_ID, /* This slot/function is empty */
&ulDeviceID); continue;
if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
/*
* This slot/function is empty
*/
continue;
} }
/* /* This slot/function has a device fitted. */
* This slot/function has a device fitted. pci_read_config_dword(0, ucSlotNumber, ucFnNumber,
*/ PCI_CLASS_REVISION, &ulClass);
(void)pci_read_config_dword(0,
ucSlotNumber,
ucFnNumber,
PCI_CLASS_REVISION,
&ulClass);
ulClass >>= 16; ulClass >>= 16;
if (ulClass == PCI_CLASS_BRIDGE_PCI) { if (ulClass == PCI_CLASS_BRIDGE_PCI) {
/* /* We have found a PCI-PCI bridge */
* We have found a PCI-PCI bridge pci_read_config_byte(0, ucSlotNumber, ucFnNumber,
*/ PCI_SUBORDINATE_BUS, &ucMaxSubordinate);
(void)pci_read_config_byte(0, if (ucMaxSubordinate>ucMaxPCIBus) {
ucSlotNumber, ucMaxPCIBus=ucMaxSubordinate;
ucFnNumber, }
PCI_SUBORDINATE_BUS, }
&ucMaxSubordinate); }
if(ucMaxSubordinate>ucMaxPCIBus) { }
ucMaxPCIBus=ucMaxSubordinate; return PCIB_ERR_SUCCESS;
}
}
}
}
} }
/* /*
@@ -601,5 +610,5 @@ void pci_initialize()
*/ */
unsigned char BusCountPCI() unsigned char BusCountPCI()
{ {
return(ucMaxPCIBus+1); return (ucMaxPCIBus+1);
} }

View File

@@ -32,14 +32,4 @@ struct _int_map
void FixupPCI( const struct _int_map *, int (*swizzler)(int,int) ); void FixupPCI( const struct _int_map *, int (*swizzler)(int,int) );
/* scan for a specific device */
/* find a particular PCI device
* (currently, only bus0 is scanned for device/fun0)
*
* RETURNS: zero on success, bus/dev/fun in *pbus / *pdev / *pfun
*/
int
BSP_pciFindDevice(unsigned short vendorid, unsigned short deviceid,
int instance, int *pbus, int *pdev, int *pfun);
#endif /* BSP_POWERPC_PCI_H */ #endif /* BSP_POWERPC_PCI_H */

View File

@@ -7,51 +7,54 @@
* $Id$ * $Id$
*/ */
#define PCI_INVALID_VENDORDEVICEID 0xffffffff #define PCI_INVALID_VENDORDEVICEID 0xffffffff
#define PCI_MULTI_FUNCTION 0x80 #define PCI_MULTI_FUNCTION 0x80
#include <bsp/pci.h> #include <bsp/pci.h>
#include <rtems/bspIo.h> #include <rtems/bspIo.h>
int int
pci_find_by_devid( unsigned short vendorid, unsigned short deviceid, pci_find_device(
int instance, int *pbus, int *pdev, int *pfun ) unsigned short vendorid,
{ unsigned short deviceid,
int instance,
int *pbus,
int *pdev,
int *pfun
) {
unsigned int d; unsigned int d;
unsigned short s; unsigned short s;
unsigned char bus,dev,fun,hd; unsigned char bus,dev,fun,hd;
for (bus=0; bus<BusCountPCI(); bus++) { for (bus=0; bus<BusCountPCI(); bus++) {
for (dev=0; dev<PCI_MAX_DEVICES; dev++) { for (dev=0; dev<PCI_MAX_DEVICES; dev++) {
pci_read_config_byte(bus,dev,0, PCI_HEADER_TYPE, &hd); pci_read_config_byte(bus,dev,0, PCI_HEADER_TYPE, &hd);
hd = (hd & PCI_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1); hd = (hd & PCI_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1);
for (fun=0; fun<hd; fun++) { for (fun=0; fun<hd; fun++) {
/* /*
* The last devfn id/slot is special; must skip it * The last devfn id/slot is special; must skip it
*/ */
if (PCI_MAX_DEVICES-1==dev && PCI_MAX_FUNCTIONS-1 == fun) if (PCI_MAX_DEVICES-1==dev && PCI_MAX_FUNCTIONS-1 == fun)
break; break;
(void)pci_read_config_dword(bus,dev,fun,PCI_VENDOR_ID,&d); (void)pci_read_config_dword(bus,dev,fun,PCI_VENDOR_ID,&d);
if (PCI_INVALID_VENDORDEVICEID == d) if (PCI_INVALID_VENDORDEVICEID == d)
continue; continue;
#ifdef PCI_DEBUG #ifdef PCI_DEBUG
printk("pci_find_by_devid: found 0x%08x at %d/%d/%d\n",d,bus,dev,fun); printk("pci_find_by_devid: found 0x%08x at %d/%d/%d\n",d,bus,dev,fun);
#endif #endif
(void) pci_read_config_word(bus,dev,fun,PCI_VENDOR_ID,&s); (void) pci_read_config_word(bus,dev,fun,PCI_VENDOR_ID,&s);
if (vendorid != s) if (vendorid != s)
continue; continue;
(void) pci_read_config_word(bus,dev,fun,PCI_DEVICE_ID,&s); (void) pci_read_config_word(bus,dev,fun,PCI_DEVICE_ID,&s);
if (deviceid == s) { if (deviceid == s) {
if (instance--) continue; if (instance--) continue;
*pbus=bus; *pdev=dev; *pfun=fun; *pbus=bus; *pdev=dev; *pfun=fun;
return 0; return 0;
} }
}
} }
} }
return -1; }
return -1;
} }
/* eof */