📄 iseries_pci.c
字号:
++DeviceCount; PciDev->sysdata = (void*)DeviceNode; DeviceNode->PciDev = PciDev; PPCDBG(PPCDBG_BUSWALK,"PciDev 0x%p <==> DevNode 0x%p\n",PciDev,DeviceNode ); iSeries_allocateDeviceBars(PciDev); PPCDBGCALL(PPCDBG_BUSWALK,dumpPci_Dev(PciDev) ); iSeries_Device_Information(PciDev,Buffer, sizeof(Buffer) ); printk("%d. %s\n",DeviceCount,Buffer); create_pci_bus_tce_table((unsigned long)DeviceNode); } else { printk("PCI: Device Tree not found for 0x%016lX\n",(unsigned long)PciDev); } } iSeries_IoMmTable_Status(); iSeries_activate_IRQs(); mf_displaySrc(0xC9000200);}/*********************************************************************** * iSeries_pcibios_fixup_bus(int Bus) * ***********************************************************************/void iSeries_pcibios_fixup_bus(struct pci_bus* PciBus){ PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_fixup_bus(0x%04X) Entry.\n",PciBus->number); }/*********************************************************************** * fixup_resources(struct pci_dev *dev) * ***********************************************************************/void fixup_resources(struct pci_dev *PciDev){ PPCDBG(PPCDBG_BUSWALK,"fixup_resources PciDev %p\n",PciDev);} /********************************************************************************* Loop through each node function to find usable EADs bridges. *********************************************************************************/void iSeries_Scan_PHBs_Slots(struct pci_controller* Phb){ struct HvCallPci_DeviceInfo* DevInfo; HvBusNumber Bus = Phb->local_number; /* System Bus */ HvSubBusNumber SubBus = 0; /* EADs is always 0. */ int HvRc = 0; int IdSel = 1; int MaxAgents = 8; DevInfo = (struct HvCallPci_DeviceInfo*)kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); if(DevInfo == NULL) return; /******************************************************************************** * Probe for EADs Bridges ********************************************************************************/ for (IdSel=1; IdSel < MaxAgents; ++IdSel) { HvRc = HvCallPci_getDeviceInfo(Bus, SubBus, IdSel,REALADDR(DevInfo), sizeof(struct HvCallPci_DeviceInfo)); if (HvRc == 0) { if(DevInfo->deviceType == HvCallPci_NodeDevice) { iSeries_Scan_EADs_Bridge(Bus, SubBus, IdSel); } else printk("PCI: Invalid System Configuration(0x%02X.\n",DevInfo->deviceType); } else pci_Log_Error("getDeviceInfo",Bus, SubBus, IdSel,HvRc); } kfree(DevInfo);}/********************************************************************************* *********************************************************************************/void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel){ struct HvCallPci_BridgeInfo* BridgeInfo; HvAgentId AgentId; int Function; int HvRc; BridgeInfo = (struct HvCallPci_BridgeInfo*)kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL); if(BridgeInfo == NULL) return; /********************************************************************* * Note: hvSubBus and irq is always be 0 at this level! *********************************************************************/ for (Function=0; Function < 8; ++Function) { AgentId = ISERIES_PCI_AGENTID(IdSel, Function); HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, 0); if (HvRc == 0) { /* Connect EADs: 0x18.00.12 = 0x00 */ PPCDBG(PPCDBG_BUSWALK,"PCI:Connect EADs: 0x%02X.%02X.%02X\n",Bus, SubBus, AgentId); PCIFR( "Connect EADs: 0x%02X.%02X.%02X", Bus, SubBus, AgentId); HvRc = HvCallPci_getBusUnitInfo(Bus, SubBus, AgentId, REALADDR(BridgeInfo), sizeof(struct HvCallPci_BridgeInfo)); if (HvRc == 0) { PPCDBG(PPCDBG_BUSWALK,"PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n", BridgeInfo->busUnitInfo.deviceType, BridgeInfo->subBusNumber, BridgeInfo->maxAgents, BridgeInfo->maxSubBusNumber, BridgeInfo->logicalSlotNumber); PCIFR( "BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X", BridgeInfo->busUnitInfo.deviceType, BridgeInfo->subBusNumber, BridgeInfo->maxAgents, BridgeInfo->maxSubBusNumber, BridgeInfo->logicalSlotNumber); if (BridgeInfo->busUnitInfo.deviceType == HvCallPci_BridgeDevice) { /* Scan_Bridge_Slot...: 0x18.00.12 */ iSeries_Scan_Bridge_Slot(Bus,BridgeInfo); } else printk("PCI: Invalid Bridge Configuration(0x%02X)",BridgeInfo->busUnitInfo.deviceType); } } else if(HvRc != 0x000B) pci_Log_Error("EADs Connect",Bus,SubBus,AgentId,HvRc); } kfree(BridgeInfo);}/********************************************************************************* * This assumes that the node slot is always on the primary bus!**********************************************************************************/int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo* BridgeInfo){ struct iSeries_Device_Node* DeviceNode; HvSubBusNumber SubBus = BridgeInfo->subBusNumber; u16 VendorId = 0; int HvRc = 0; u8 Irq = 0; int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus); int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus); HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function); HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function); int FirstSlotId = 0; /**********************************************************/ /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ /**********************************************************/ Irq = iSeries_allocate_IRQ(Bus, 0, AgentId); iSeries_assign_IRQ(Irq, Bus, 0, AgentId); PPCDBG(PPCDBG_BUSWALK,"PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n",Bus, 0, AgentId, Irq ); /**************************************************************************** * Connect all functions of any device found. ****************************************************************************/ for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) { for (Function = 0; Function < 8; ++Function) { AgentId = ISERIES_PCI_AGENTID(IdSel, Function); HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, Irq); if( HvRc == 0) { HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, PCI_VENDOR_ID, &VendorId); if( HvRc == 0) { /**********************************************************/ /* FoundDevice: 0x18.28.10 = 0x12AE */ /**********************************************************/ PPCDBG(PPCDBG_BUSWALK,"PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X\n", Bus, SubBus, AgentId, VendorId); HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, PCI_INTERRUPT_LINE, Irq); if( HvRc != 0) { pci_Log_Error("PciCfgStore Irq Failed!",Bus,SubBus,AgentId,HvRc); } ++DeviceCount; DeviceNode = build_device_node(Bus, SubBus, EADsIdSel, Function); DeviceNode->Vendor = VendorId; DeviceNode->Irq = Irq; DeviceNode->LogicalSlot = BridgeInfo->logicalSlotNumber; PCIFR("Device(%4d): 0x%02X.%02X.%02X 0x%02X 0x%04X", DeviceCount,Bus, SubBus, AgentId, DeviceNode->LogicalSlot,DeviceNode->Vendor); /*********************************************************** * On the first device/function, assign irq to slot ***********************************************************/ if(Function == 0) { FirstSlotId = AgentId; // AHT iSeries_assign_IRQ(Irq, Bus, SubBus, AgentId); } } else pci_Log_Error("Read Vendor",Bus,SubBus,AgentId,HvRc); } else pci_Log_Error("Connect Bus Unit",Bus,SubBus, AgentId,HvRc); } /* for (Function = 0; Function < 8; ++Function) */ } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */ return HvRc;}/************************************************************************//* I/0 Memory copy MUST use mmio commands on iSeries *//* To do; For performance, include the hv call directly *//************************************************************************/void* iSeries_memset(void* dest, char c, size_t Count){ u8 ByteValue = c; long NumberOfBytes = Count; char* IoBuffer = dest; while(NumberOfBytes > 0) { iSeries_Write_Byte( ByteValue, (void*)IoBuffer ); ++IoBuffer; -- NumberOfBytes; } return dest;} void* iSeries_memcpy_toio(void *dest, void *source, size_t count){ char *dst = dest; char *src = source; long NumberOfBytes = count; while(NumberOfBytes > 0) { iSeries_Write_Byte(*src++, (void*)dst++); -- NumberOfBytes; } return dest;}void* iSeries_memcpy_fromio(void *dest, void *source, size_t count){ char *dst = dest; char *src = source; long NumberOfBytes = count; while(NumberOfBytes > 0) { *dst++ = iSeries_Read_Byte( (void*)src++); -- NumberOfBytes; } return dest;}/********************************************************************************** * Look down the chain to find the matching Device Device **********************************************************************************/struct iSeries_Device_Node* find_Device_Node(struct pci_dev* PciDev){ struct list_head* Device_Node_Ptr = iSeries_Global_Device_List.next; int Bus = PciDev->bus->number; int DevFn = PciDev->devfn; while(Device_Node_Ptr != &iSeries_Global_Device_List) { struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)Device_Node_Ptr; if(Bus == ISERIES_BUS(DevNode) && DevFn == DevNode->DevFn) { return DevNode; } Device_Node_Ptr = Device_Node_Ptr->next; } return NULL;}/******************************************************************//* Returns the device node for the passed pci_dev *//* Sanity Check Node PciDev to passed pci_dev *//* If none is found, returns a NULL which the client must handle. *//******************************************************************/struct iSeries_Device_Node* get_Device_Node(struct pci_dev* PciDev){ struct iSeries_Device_Node* Node; Node = (struct iSeries_Device_Node*)PciDev->sysdata; if(Node == NULL ) { Node = find_Device_Node(PciDev); } else if(Node->PciDev != PciDev) { Node = find_Device_Node(PciDev); } return Node;}/********************************************************************************** * * Read PCI Config Space Code * **********************************************************************************//** BYTE *************************************************************************/int iSeries_Node_read_config_byte(struct iSeries_Device_Node* DevNode, int Offset, u8* ReadValue){ u8 ReadData; if(DevNode == NULL) { return 0x301; } ++Pci_Cfg_Read_Count; DevNode->ReturnCode = HvCallPci_configLoad8(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, Offset,&ReadData); if(Pci_Trace_Flag == 1) { PCIFR("RCB: 0x%04X.%02X 0x%04X = 0x%02X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,ReadData); } if(DevNode->ReturnCode != 0 ) { printk("PCI: RCB: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); PCIFR( "RCB: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); } *ReadValue = ReadData; return DevNode->ReturnCode;}/** WORD *************************************************************************/int iSeries_Node_read_config_word(struct iSeries_Device_Node* DevNode, int Offset, u16* ReadValue){ u16 ReadData; if(DevNode == NULL) { return 0x301; } ++Pci_Cfg_Read_Count; DevNode->ReturnCode = HvCallPci_configLoad16(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, Offset,&ReadData); if(Pci_Trace_Flag == 1) { PCIFR("RCW: 0x%04X.%02X 0x%04X = 0x%04X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,ReadData); } if(DevNode->ReturnCode != 0 ) { printk("PCI: RCW: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); PCIFR( "RCW: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); } *ReadValue = ReadData;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -