📄 pci.c
字号:
/* * pci.c : this file contains basic PCI Io functions. * * Copyright (C) 1999 valette@crf.canon.fr * * This code is heavily inspired by the public specification of STREAM V2 * that can be found at : * * <http://www.chorus.com/Documentation/index.html> by following * the STREAM API Specification Document link. * * The license and distribution terms for this file may be * found in found in the file LICENSE in this distribution or at * http://www.rtems.com/license/LICENSE. * * $Id: pci.c,v 1.2.4.4 2004/11/10 22:15:01 joel Exp $ * * Till Straumann, <strauman@slac.stanford.edu>, 1/2002 * - separated bridge detection code out of this file */#include <libcpu/io.h>#include <bsp/pci.h>#include <rtems/bspIo.h>/* allow for overriding these definitions */#ifndef PCI_CONFIG_ADDR#define PCI_CONFIG_ADDR 0xcf8#endif#ifndef PCI_CONFIG_DATA#define PCI_CONFIG_DATA 0xcfc#endif#define PCI_INVALID_VENDORDEVICEID 0xffffffff#define PCI_MULTI_FUNCTION 0x80/* define a shortcut */#define pci BSP_pci_configuration/* * Bit encode for PCI_CONFIG_HEADER_TYPE register */unsigned char ucMaxPCIBus;static intindirect_pci_read_config_byte(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned char *val) { 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 intindirect_pci_read_config_word(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned short *val) { *val = 0xffff; 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 intindirect_pci_read_config_dword(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned int *val) { *val = 0xffffffff; 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 intindirect_pci_write_config_byte(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned char val) { 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 intindirect_pci_write_config_word(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned short val) { 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 intindirect_pci_write_config_dword(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned int val) { 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 = { indirect_pci_read_config_byte, indirect_pci_read_config_word, indirect_pci_read_config_dword, indirect_pci_write_config_byte, indirect_pci_write_config_word, indirect_pci_write_config_dword};pci_config BSP_pci_configuration = {(volatile unsigned char*)PCI_CONFIG_ADDR, (volatile unsigned char*)PCI_CONFIG_DATA, &pci_indirect_functions};static intdirect_pci_read_config_byte(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned char *val) { if (bus != 0 || (1<<slot & 0xff8007fe)) { *val=0xff; return PCIBIOS_DEVICE_NOT_FOUND; } *val=in_8(pci.pci_config_data + ((1<<slot)&~1) + (function<<8) + offset); return PCIBIOS_SUCCESSFUL;}static intdirect_pci_read_config_word(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned short *val) { *val = 0xffff; if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; if (bus != 0 || (1<<slot & 0xff8007fe)) { 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 intdirect_pci_read_config_dword(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned int *val) { *val = 0xffffffff; if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; if (bus != 0 || (1<<slot & 0xff8007fe)) { 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 intdirect_pci_write_config_byte(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned char val) { if (bus != 0 || (1<<slot & 0xff8007fe)) { return PCIBIOS_DEVICE_NOT_FOUND; } out_8(pci.pci_config_data + ((1<<slot)&~1) + (function<<8) + offset, val); return PCIBIOS_SUCCESSFUL;}static intdirect_pci_write_config_word(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned short val) { if (offset&1) return PCIBIOS_BAD_REGISTER_NUMBER; if (bus != 0 || (1<<slot & 0xff8007fe)) { return PCIBIOS_DEVICE_NOT_FOUND; } out_le16((volatile unsigned short *) (pci.pci_config_data + ((1<<slot)&~1) + (function<<8) + offset), val); return PCIBIOS_SUCCESSFUL;}static intdirect_pci_write_config_dword(unsigned char bus, unsigned char slot, unsigned char function, unsigned char offset, unsigned int val) { if (offset&3) return PCIBIOS_BAD_REGISTER_NUMBER; if (bus != 0 || (1<<slot & 0xff8007fe)) { return PCIBIOS_DEVICE_NOT_FOUND; } 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 = { direct_pci_read_config_byte, direct_pci_read_config_word, direct_pci_read_config_dword, direct_pci_write_config_byte, direct_pci_write_config_word, direct_pci_write_config_dword};#define PRINT_MSG() \ 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** the names defined in the routing record.*/static int test_intname( const struct _int_map *row, int pbus, int pslot, int int_pin, int int_name){ int j, k; int _nopin= -1, _noname= -1; for(j=0; row->pin_route[j].pin > -1; j++) { if( row->pin_route[j].pin == int_pin ) { _nopin = 0; for(k=0; k<4 && row->pin_route[j].int_name[k] > -1; k++ ) { if( row->pin_route[j].int_name[k] == int_name ){ _noname=0; break; } } break; } } if( _nopin ) { printk("pci : Device %d:%02x supplied a bogus interrupt_pin %d\n", pbus, pslot, int_pin ); return -1; } else { if( _noname ) printk("pci : Device %d:%02x supplied a suspicious interrupt_line %d, using it anyway\n", pbus, pslot, int_name ); } return 0;}struct pcibridge{ int bus,slot;};static int FindPCIbridge( int mybus, struct pcibridge *pb ){ int pbus, pslot; unsigned8 bussec, buspri; unsigned16 devid, vendorid, dclass; for(pbus=0; pbus< BusCountPCI(); pbus++) { 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, &vendorid); if( vendorid == 0xffff ) continue; pci_read_config_word(pbus, pslot, 0, PCI_CLASS_DEVICE, &dclass); 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_SECONDARY_BUS, &bussec);#if 0 printk("pci : Found bridge at %d:%d, mybus %d, pribus %d, secbus %d ", pbus, pslot, mybus, buspri, bussec );#endif if( bussec == mybus ) {#if 0 printk("match\n");#endif /* found our nearest bridge going towards the root */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -