📄 iseries_pci.c
字号:
int iSeries_pci_read_config_byte(struct pci_dev* PciDev, int Offset, u8* ReadValue) { struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); if(DevNode == NULL) return 0x0301; return iSeries_Node_read_config_byte( DevNode ,Offset,ReadValue);}int iSeries_pci_read_config_word(struct pci_dev* PciDev, int Offset, u16* ReadValue) { struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); if(DevNode == NULL) return 0x0301; return iSeries_Node_read_config_word( DevNode ,Offset,ReadValue );}int iSeries_pci_read_config_dword(struct pci_dev* PciDev, int Offset, u32* ReadValue) { struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); if(DevNode == NULL) return 0x0301; return iSeries_Node_read_config_dword(DevNode ,Offset,ReadValue );}/**********************************************************************************//* *//* Write PCI Config Space *//* *//** BYTE *************************************************************************/int iSeries_Node_write_config_byte(struct iSeries_Device_Node* DevNode, int Offset, u8 WriteData){ setIoLock(); ++Pci_Cfg_Write_Count; DevNode->ReturnCode = HvCallPci_configStore8(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, Offset,WriteData); if(Pci_Trace_Flag == 1) { PCIFR("WCB: 0x%04X.%02X 0x%04X = 0x%02X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,WriteData); } if(DevNode->ReturnCode != 0 ) { printk("PCI: WCB: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); PCIFR( "WCB: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); } resetIoLock();}/** WORD *************************************************************************/int iSeries_Node_write_config_word(struct iSeries_Device_Node* DevNode, int Offset, u16 WriteData){ setIoLock(); ++Pci_Cfg_Write_Count; DevNode->ReturnCode = HvCallPci_configStore16(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, Offset,WriteData); if(Pci_Trace_Flag == 1) { PCIFR("WCW: 0x%04X.%02X 0x%04X = 0x%04X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,WriteData); } if(DevNode->ReturnCode != 0 ) { printk("PCI: WCW: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); PCIFR( "WCW: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); } resetIoLock();}/** DWORD *************************************************************************/int iSeries_Node_write_config_dword(struct iSeries_Device_Node* DevNode, int Offset, u32 WriteData){ setIoLock(); ++Pci_Cfg_Write_Count; DevNode->ReturnCode = HvCallPci_configStore32(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, Offset,WriteData); if(Pci_Trace_Flag == 1) { PCIFR("WCL: 0x%04X.%02X 0x%04X = 0x%08X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,WriteData); } if(DevNode->ReturnCode != 0 ) { printk("PCI: WCL: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); PCIFR( "WCL: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); } resetIoLock();}int iSeries_pci_write_config_byte( struct pci_dev* PciDev,int Offset, u8 WriteValue){ struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); if(DevNode == NULL) return 0x0301; return iSeries_Node_write_config_byte( DevNode,Offset,WriteValue);}int iSeries_pci_write_config_word( struct pci_dev* PciDev,int Offset,u16 WriteValue){ struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); if(DevNode == NULL) return 0x0301; return iSeries_Node_write_config_word( DevNode,Offset,WriteValue);}int iSeries_pci_write_config_dword(struct pci_dev* PciDev,int Offset,u32 WriteValue){ struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); if(DevNode == NULL) return 0x0301; return iSeries_Node_write_config_dword(DevNode,Offset,WriteValue);}/************************************************************************//* Branch Table *//************************************************************************/struct pci_ops iSeries_pci_ops = { iSeries_pci_read_config_byte, iSeries_pci_read_config_word, iSeries_pci_read_config_dword, iSeries_pci_write_config_byte, iSeries_pci_write_config_word, iSeries_pci_write_config_dword };/************************************************************************ * Log Pci Error and check Retry Count * -> On Failure, print and log information. * Increment Retry Count, if exceeds max, panic partition. * -> If in retry, print and log success ************************************************************************/void logPciError(char* ErrorTxt, void* IoAddress, struct iSeries_Device_Node* DevNode, u64 RtnCode){ ++DevNode->IoRetry; ++Pci_Error_Count; PCIFR("%s: I/O Error(%1d/%1d):0x%04X IoAddress:0x%p Device:0x%04X:%02X", ErrorTxt, DevNode->IoRetry, in_interrupt(), RtnCode, IoAddress, ISERIES_BUS(DevNode),DevNode->AgentId); /*******************************************************/ /* Filter out EADs freeze and alignment errors */ /*******************************************************/ if(RtnCode == 0x0102) { PCIFR("EADS Freeze error.......Panic........"); mf_displaySrc(0xB6000103); panic_timeout = 0; panic("PCI: EADs Freeze error SRC B6000103\n"); } else if(RtnCode == 0x0241) { PCIFR("MMIO Alignment error: 0x%p",IoAddress); mf_displaySrc(0xB6000103); panic_timeout = 0; panic("PCI: MMIO Alignment error. SRC B6000103\n"); } /*******************************************************/ /* Bump the retry and check for retry count exceeded. */ /* If, Exceeded, panic the system. */ /*******************************************************/ if(DevNode->IoRetry > Pci_Retry_Max && Pci_Error_Flag != 0 ) { mf_displaySrc(0xB6000103); panic_timeout = 0; panic("PCI: Hardware I/O Error, SRC B6000103, Automatic Reboot Disabled.\n"); } /**************************************************************/ /* Wait x ms before retrying I/O to give I/O time to recover. */ /* Retry wait delay logic. */ /* - On first retry, no delay, maybe just glitch. */ /* - On successify retries, vary the delay to avoid being in a*/ /* repetitive timing window. */ /**************************************************************/ if(DevNode->IoRetry > 0) { udelay(DevNode->IoRetry * 50); }}/************************************************************************ * Retry was successful ************************************************************************/void pciRetrySuccessful(struct iSeries_Device_Node* DevNode){ struct timeval TimeClock; struct rtc_time CurTime; do_gettimeofday(&TimeClock); to_tm(TimeClock.tv_sec, &CurTime); PCIFR("Retry Successful(%2d) on Device 0x%04X:%02X at %02d.%02d.%02d", DevNode->IoRetry,ISERIES_BUS(DevNode),DevNode->AgentId, CurTime.tm_hour,CurTime.tm_min,CurTime.tm_sec); DevNode->IoRetry = 0;}/************************************************************************//* Translate the I/O Address into a device node, bar, and bar offset. *//* Note: Make sure the passed variable end up on the stack to avoid *//* the exposure of being device global. *//* The Device Node is Lock to block other I/O to device. *//************************************************************************/#define setUpMmIo(IoAddress,Type) \unsigned long IrqFlags; \struct HvCallPci_LoadReturn Return; \union HvDsaMap DsaData; \u64 BarOffset;\unsigned long BaseIoAddr = (unsigned long)IoAddress-iSeries_Base_Io_Memory; \long TableIndex = (BaseIoAddr/iSeries_IoMmTable_Entry_Size); \struct iSeries_Device_Node* DevNode = *(iSeries_IoMmTable+TableIndex); \if(DevNode != NULL) { \ DsaData.DsaAddr = ISERIES_DSA(DevNode); \ DsaData.Dsa.barNumber = *(iSeries_IoBarTable+TableIndex); \ BarOffset = BaseIoAddr % iSeries_IoMmTable_Entry_Size; \ ++Pci_Io_##Type##_Count; \ spin_lock_irqsave(&DevNode->IoLock, IrqFlags ); \} \else panic("PCI: Invalid PCI IoAddress detected 0x%p!\n",IoAddress);/************************************************************************//* Read MM I/O Instructions for the iSeries *//* On MM I/O error, all ones are returned and iSeries_pci_IoError is cal*//* else, data is returned in big Endian format. *//************************************************************************//* iSeries_Read_Byte = Read Byte ( 8 bit) *//* iSeries_Read_Word = Read Word (16 bit) *//* iSeries_Read_Long = Read Long (32 bit) *//************************************************************************/u8 iSeries_Read_Byte(void* IoAddress){ setUpMmIo(IoAddress,Read); do { HvCall3Ret16(HvCallPciBarLoad8, &Return, DsaData.DsaAddr,BarOffset, 0); if(Return.rc != 0 ) { logPciError("RDB",IoAddress, DevNode, Return.rc); } else if ( DevNode->IoRetry > 0) { pciRetrySuccessful(DevNode); } } while (Return.rc != 0); spin_unlock_irqrestore(&DevNode->IoLock, IrqFlags ); if(Pci_Trace_Flag == 1 ) PCIFR("RDB: IoAddress 0x%p = 0x%02X",IoAddress, (u8)Return.value); return (u8)Return.value;}int Retry_Test = 0;u16 iSeries_Read_Word(void* IoAddress){ setUpMmIo(IoAddress,Read); do { HvCall3Ret16(HvCallPciBarLoad16,&Return, DsaData.DsaAddr,BarOffset, 0); if(Return.rc != 0 ) { logPciError("RDW",IoAddress, DevNode, Return.rc); } else if ( DevNode->IoRetry > 0) { pciRetrySuccessful(DevNode); } } while (Return.rc != 0); spin_unlock_irqrestore(&DevNode->IoLock, IrqFlags ); if(Pci_Trace_Flag == 1 ) PCIFR("RDW: IoAddress 0x%p = 0x%04X",IoAddress, (u16)Return.value); return swab16((u16)Return.value);}u32 iSeries_Read_Long(void* IoAddress){ setUpMmIo(IoAddress,Read); do { HvCall3Ret16(HvCallPciBarLoad32,&Return, DsaData.DsaAddr,BarOffset, 0); if(Return.rc != 0 ) { logPciError("RDL",IoAddress, DevNode, Return.rc); } else if ( DevNode->IoRetry > 0) { pciRetrySuccessful(DevNode); } } while (Return.rc != 0); spin_unlock_irqrestore(&DevNode->IoLock, IrqFlags ); if(Pci_Trace_Flag == 1 ) PCIFR("RDL: IoAddress 0x%p = 0x%08X",IoAddress, swab32((u32)Return.value)); return swab32((u32)Return.value);}/************************************************************************//* Write MM I/O Instructions for the iSeries *//************************************************************************//* iSeries_Write_Byte = Write Byte (8 bit) *//* iSeries_Write_Word = Write Word(16 bit) *//* iSeries_Write_Long = Write Long(32 bit) *//************************************************************************/void iSeries_Write_Byte(u8 Data, void* IoAddress){ setUpMmIo(IoAddress,Write); do { Return.rc = HvCall4(HvCallPciBarStore8, DsaData.DsaAddr,BarOffset, Data, 0); if(Return.rc != 0 ) { logPciError("WWB",IoAddress, DevNode, Return.rc); } else if ( DevNode->IoRetry > 0) { pciRetrySuccessful(DevNode); } } while (Return.rc != 0); spin_unlock_irqrestore(&DevNode->IoLock, IrqFlags ); if(Pci_Trace_Flag == 1) PCIFR("WWB: IoAddress 0x%p = 0x%02X",IoAddress,Data);}void iSeries_Write_Word(u16 Data, void* IoAddress){ setUpMmIo(IoAddress,Write); do { Return.rc = HvCall4(HvCallPciBarStore16,DsaData.DsaAddr,BarOffset, swab16(Data), 0); if(Return.rc != 0 ) { logPciError("WWW",IoAddress, DevNode, Return.rc); } else if ( DevNode->IoRetry > 0) { pciRetrySuccessful(DevNode); } } while (Return.rc != 0); spin_unlock_irqrestore(&DevNode->IoLock, IrqFlags ); if(Pci_Trace_Flag == 1) PCIFR("WWW: IoAddress 0x%p = 0x%04X",IoAddress,Data);}void iSeries_Write_Long(u32 Data, void* IoAddress){ setUpMmIo(IoAddress,Write); do { Return.rc = HvCall4(HvCallPciBarStore32,DsaData.DsaAddr,BarOffset, swab32(Data), 0); if(Return.rc != 0 ) { logPciError("WWL",IoAddress, DevNode, Return.rc); } else if ( DevNode->IoRetry > 0) { pciRetrySuccessful(DevNode); } } while (Return.rc != 0); spin_unlock_irqrestore(&DevNode->IoLock, IrqFlags ); if(Pci_Trace_Flag == 1) PCIFR("WWL: IoAddress 0x%p = 0x%08X",IoAddress, Data);}/* * This is called very early before the page table is setup. * There are warnings here because of type mismatches.. Okay for now. AHT */void iSeries_pcibios_init_early(void){ //ppc_md.pcibios_read_config_byte = iSeries_Node_read_config_byte; //ppc_md.pcibios_read_config_word = iSeries_Node_read_config_word; //ppc_md.pcibios_read_config_dword = iSeries_Node_read_config_dword; //ppc_md.pcibios_write_config_byte = iSeries_Node_write_config_byte; //ppc_md.pcibios_write_config_word = iSeries_Node_write_config_word; //ppc_md.pcibios_write_config_dword = iSeries_Node_write_config_dword;}/************************************************************************//* Set the slot reset line to the state passed in. *//* This is the platform specific for code for the pci_reset_device *//* function. *//************************************************************************/int pci_set_reset(struct pci_dev* PciDev, int State) { struct iSeries_Device_Node* DeviceNode = (struct iSeries_Device_Node*)PciDev->sysdata; if (DeviceNode == NULL) { printk("PCI: Pci Reset Failed, Device Node not found for pci_dev %p\n",PciDev); return -1; } DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),0x00,DeviceNode->AgentId,State); return DeviceNode->ReturnCode;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -