📄 iseries_pci.c
字号:
return DevNode->ReturnCode;}/** DWORD *************************************************************************/int iSeries_Node_read_config_dword(struct iSeries_Device_Node* DevNode, int Offset, u32* ReadValue){ u32 ReadData; if(DevNode == NULL) { return 0x301; } ++Pci_Cfg_Read_Count; DevNode->ReturnCode = HvCallPci_configLoad32(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, Offset,&ReadData); if(Pci_Trace_Flag == 1) { PCIFR("RCL: 0x%04X.%02X 0x%04X = 0x%08X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,ReadData); } if(DevNode->ReturnCode != 0 ) { printk("PCI: RCL: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); PCIFR( "RCL: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); } *ReadValue = ReadData; return DevNode->ReturnCode;}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){ ++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); } return DevNode->ReturnCode;}/** WORD *************************************************************************/int iSeries_Node_write_config_word(struct iSeries_Device_Node* DevNode, int Offset, u16 WriteData){ ++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); } return DevNode->ReturnCode;}/** DWORD *************************************************************************/int iSeries_Node_write_config_dword(struct iSeries_Device_Node* DevNode, int Offset, u32 WriteData){ ++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); } return DevNode->ReturnCode;}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 };/************************************************************************ * Check Return Code * -> On Failure, print and log information. * Increment Retry Count, if exceeds max, panic partition. * -> If in retry, print and log success ************************************************************************ * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234 * PCI: Device 23.90 ReadL Retry( 1) * PCI: Device 23.90 ReadL Retry Successful(1) ************************************************************************/int CheckReturnCode(char* TextHdr, struct iSeries_Device_Node* DevNode, u64 RtnCode){ if(RtnCode != 0) { ++Pci_Error_Count; ++DevNode->IoRetry; PCIFR( "%s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X", TextHdr,ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->IoRetry,(int)RtnCode); printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", TextHdr,ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->IoRetry,(int)RtnCode); /*******************************************************/ /* 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"); } return -1; /* Retry Try */ } /******************************************************************** * If retry was in progress, log success and rest retry count * *********************************************************************/ else if(DevNode->IoRetry > 0) { PCIFR("%s: Device 0x%04X:%02X Retry Successful(%2d).", TextHdr,ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->IoRetry); DevNode->IoRetry = 0; return 0; } return 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. *//************************************************************************/static inline struct iSeries_Device_Node* xlateIoMmAddress(void* IoAddress, union HvDsaMap* DsaPtr, u64* BarOffsetPtr) { 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) { DsaPtr->DsaAddr = ISERIES_DSA(DevNode); DsaPtr->Dsa.barNumber = *(iSeries_IoBarTable+TableIndex); *BarOffsetPtr = BaseIoAddr % iSeries_IoMmTable_Entry_Size; } else { panic("PCI: Invalid PCI IoAddress detected!\n"); } return DevNode;}/************************************************************************//* 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){ u64 BarOffset; union HvDsaMap DsaData; struct HvCallPci_LoadReturn Return; struct iSeries_Device_Node* DevNode = xlateIoMmAddress(IoAddress,&DsaData,&BarOffset); do { ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad8, &Return, DsaData.DsaAddr,BarOffset, 0); } while (CheckReturnCode("RDB",DevNode, Return.rc) != 0); if(Pci_Trace_Flag == 1) PCIFR("RDB: IoAddress 0x%p = 0x%02X",IoAddress, (u8)Return.value); return (u8)Return.value;}u16 iSeries_Read_Word(void* IoAddress){ u64 BarOffset; union HvDsaMap DsaData; struct HvCallPci_LoadReturn Return; struct iSeries_Device_Node* DevNode = xlateIoMmAddress(IoAddress,&DsaData,&BarOffset); do { ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad16,&Return, DsaData.DsaAddr,BarOffset, 0); } while (CheckReturnCode("RDW",DevNode, Return.rc) != 0); if(Pci_Trace_Flag == 1) PCIFR("RDW: IoAddress 0x%p = 0x%04X",IoAddress, swab16((u16)Return.value)); return swab16((u16)Return.value);}u32 iSeries_Read_Long(void* IoAddress){ u64 BarOffset; union HvDsaMap DsaData; struct HvCallPci_LoadReturn Return; struct iSeries_Device_Node* DevNode = xlateIoMmAddress(IoAddress,&DsaData,&BarOffset); do { ++Pci_Io_Read_Count; HvCall3Ret16(HvCallPciBarLoad32,&Return, DsaData.DsaAddr,BarOffset, 0); } while (CheckReturnCode("RDL",DevNode, Return.rc) != 0); if(Pci_Trace_Flag == 1) PCIFR("RDL: IoAddress 0x%p = 0x%04X",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){ u64 BarOffset; union HvDsaMap DsaData; struct HvCallPci_LoadReturn Return; struct iSeries_Device_Node* DevNode = xlateIoMmAddress(IoAddress,&DsaData,&BarOffset); do { ++Pci_Io_Write_Count; Return.rc = HvCall4(HvCallPciBarStore8, DsaData.DsaAddr,BarOffset, Data, 0); } while (CheckReturnCode("WWB",DevNode, Return.rc) != 0); if(Pci_Trace_Flag == 1) PCIFR("WWB: IoAddress 0x%p = 0x%02X",IoAddress,Data);}void iSeries_Write_Word(u16 Data, void* IoAddress){ u64 BarOffset; union HvDsaMap DsaData; struct HvCallPci_LoadReturn Return; struct iSeries_Device_Node* DevNode = xlateIoMmAddress(IoAddress,&DsaData,&BarOffset); do { ++Pci_Io_Write_Count; Return.rc = HvCall4(HvCallPciBarStore16,DsaData.DsaAddr,BarOffset, swab16(Data), 0); } while (CheckReturnCode("WWW",DevNode, Return.rc) != 0); if(Pci_Trace_Flag == 1) PCIFR("WWW: IoAddress 0x%p = 0x%04X",IoAddress,Data);}void iSeries_Write_Long(u32 Data, void* IoAddress){ u64 BarOffset; union HvDsaMap DsaData; struct HvCallPci_LoadReturn Return; struct iSeries_Device_Node* DevNode = xlateIoMmAddress(IoAddress,&DsaData,&BarOffset); do { ++Pci_Io_Write_Count; Return.rc = HvCall4(HvCallPciBarStore32,DsaData.DsaAddr,BarOffset, swab32(Data), 0); } while (CheckReturnCode("WWL",DevNode, Return.rc) != 0); 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 + -