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 is not called anywhere currently */ static void iseries_shutdown_IRQ(unsigned int irq) { u32 bus, dev_id, function, mask; const u32 sub_bus = 0; unsigned int rirq = (unsigned int)irq_map[irq].hwirq; /* irq should be locked by the caller */ bus = REAL_IRQ_TO_BUS(rirq); function = REAL_IRQ_TO_FUNC(rirq); dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; /* Invalidate the IRQ number in the bridge */ HvCallXm_connectBusUnit(bus, sub_bus, dev_id, 0); /* Mask bridge interrupts in the FISR */ mask = 0x01010000 << function; HvCallPci_maskFisr(bus, sub_bus, dev_id, mask); }
/* This is called by iseries_activate_IRQs */ static unsigned int iseries_startup_IRQ(unsigned int irq) { u32 bus, dev_id, function, mask; const u32 sub_bus = 0; unsigned int rirq = (unsigned int)irq_map[irq].hwirq; bus = REAL_IRQ_TO_BUS(rirq); function = REAL_IRQ_TO_FUNC(rirq); dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function; /* Link the IRQ number to the bridge */ HvCallXm_connectBusUnit(bus, sub_bus, dev_id, irq); /* Unmask bridge interrupts in the FISR */ mask = 0x01010000 << function; HvCallPci_unmaskFisr(bus, sub_bus, dev_id, mask); iseries_enable_IRQ(irq); return 0; }
/******************************************************************************** * * 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; }