📄 iseries_pci.c
字号:
/* * iSeries_pci.c * * Copyright (C) 2001 Allan Trautman, IBM Corporation * * iSeries specific routines for PCI. * * Based on code from pci.c and iSeries_pci.c 32bit * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <linux/config.h>#include <linux/kernel.h>#include <linux/list.h> #include <linux/string.h>#include <linux/init.h>#include <linux/ide.h>#include <linux/pci.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/prom.h>#include <asm/machdep.h>#include <asm/pci-bridge.h>#include <asm/ppcdebug.h>#include <asm/naca.h>#include <asm/flight_recorder.h>#include <asm/pci_dma.h>#include <asm/iSeries/HvCallPci.h>#include <asm/iSeries/HvCallSm.h>#include <asm/iSeries/HvCallXm.h>#include <asm/iSeries/LparData.h>#include <asm/iSeries/iSeries_irq.h>#include <asm/iSeries/iSeries_pci.h>#include <asm/iSeries/mf.h>#include "iSeries_IoMmTable.h"#include "pci.h"extern struct pci_controller* hose_head;extern struct pci_controller** hose_tail;extern int global_phb_number;extern int panic_timeout;extern struct device_node *allnodes;extern unsigned long phb_tce_table_init(struct pci_controller *phb);extern unsigned long iSeries_Base_Io_Memory; extern struct pci_ops iSeries_pci_ops;extern struct flightRecorder* PciFr;extern struct TceTable* tceTables[256];/******************************************************************* * Counters and control flags. *******************************************************************/extern long Pci_Io_Read_Count;extern long Pci_Io_Write_Count;extern long Pci_Cfg_Read_Count;extern long Pci_Cfg_Write_Count;extern long Pci_Error_Count;extern int Pci_Retry_Max; extern int Pci_Error_Flag;extern int Pci_Trace_Flag;extern void iSeries_MmIoTest(void);/******************************************************************* * Forward declares of prototypes. *******************************************************************/struct iSeries_Device_Node* find_Device_Node(struct pci_dev* PciDev);struct iSeries_Device_Node* get_Device_Node(struct pci_dev* PciDev);unsigned long find_and_init_phbs(void);void fixup_resources(struct pci_dev *dev);void iSeries_pcibios_fixup(void);struct pci_controller* alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words) ;void iSeries_Scan_PHBs_Slots(struct pci_controller* Phb);void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo* Info);void list_device_nodes(void);struct pci_dev;extern struct list_head iSeries_Global_Device_List;int DeviceCount = 0;/********************************************************************************** * Log Error infor in Flight Recorder to system Console. * Filter out the device not there errors. * PCI: EADs Connect Failed 0x18.58.10 Rc: 0x00xx * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx **********************************************************************************/void pci_Log_Error(char* Error_Text, int Bus, int SubBus, int AgentId, int HvRc){ if( HvRc != 0x0302) { char ErrorString[128]; sprintf(ErrorString,"%s Failed: 0x%02X.%02X.%02X Rc: 0x%04X",Error_Text,Bus,SubBus,AgentId,HvRc); PCIFR(ErrorString); printk("PCI: %s\n",ErrorString); }}/********************************************************************************** * Dump the iSeries Temp Device Node *<4>buswalk [swapper : - DeviceNode: 0xC000000000634300 *<4>00. Device Node = 0xC000000000634300 *<4> - PciDev = 0x0000000000000000 *<4> - tDevice = 0x 17:01.00 0x1022 00 *<4> 4. Device Node = 0xC000000000634480 *<4> - PciDev = 0x0000000000000000 *<4> - Device = 0x 18:38.16 Irq:0xA7 Vendor:0x1014 Flags:0x00 *<4> - Devfn = 0xB0: 22.18 **********************************************************************************/void dumpDevice_Node(struct iSeries_Device_Node* DevNode){ udbg_printf("Device Node = 0x%p\n",DevNode); udbg_printf(" - PciDev = 0x%p\n",DevNode->PciDev); udbg_printf(" - Device = 0x%4X:%02X.%02X (0x%02X)\n", ISERIES_BUS(DevNode), ISERIES_SUBBUS(DevNode), DevNode->AgentId, DevNode->DevFn); udbg_printf(" - LSlot = 0x%02X\n",DevNode->LogicalSlot); udbg_printf(" - TceTable = 0x%p\n ",DevNode->DevTceTable); udbg_printf(" - DSA = 0x%04X\n",ISERIES_DSA(DevNode)>>32 ); udbg_printf(" = Irq:0x%02X Vendor:0x%04X Flags:0x%02X\n", DevNode->Irq, DevNode->Vendor, DevNode->Flags ); udbg_printf(" - Location = %s\n",DevNode->CardLocation);}/********************************************************************************** * Walk down the device node chain **********************************************************************************/void list_device_nodes(void){ struct list_head* Device_Node_Ptr = iSeries_Global_Device_List.next; while(Device_Node_Ptr != &iSeries_Global_Device_List) { dumpDevice_Node( (struct iSeries_Device_Node*)Device_Node_Ptr ); Device_Node_Ptr = Device_Node_Ptr->next; }} /*********************************************************************** * build_device_node(u16 Bus, int SubBus, u8 DevFn) * ***********************************************************************/struct iSeries_Device_Node* build_device_node(HvBusNumber Bus, HvSubBusNumber SubBus, int AgentId, int Function){ struct iSeries_Device_Node* DeviceNode; PPCDBG(PPCDBG_BUSWALK,"-build_device_node 0x%02X.%02X.%02X Function: %02X\n",Bus,SubBus,AgentId, Function); DeviceNode = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL); if(DeviceNode == NULL) return NULL; memset(DeviceNode,0,sizeof(struct iSeries_Device_Node) ); list_add_tail(&DeviceNode->Device_List,&iSeries_Global_Device_List); /*DeviceNode->DsaAddr = ((u64)Bus<<48)+((u64)SubBus<<40)+((u64)0x10<<32); */ ISERIES_BUS(DeviceNode) = Bus; ISERIES_SUBBUS(DeviceNode) = SubBus; DeviceNode->DsaAddr.deviceId = 0x10; DeviceNode->DsaAddr.barNumber = 0; DeviceNode->AgentId = AgentId; DeviceNode->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId),Function ); DeviceNode->IoRetry = 0; iSeries_Get_Location_Code(DeviceNode); PCIFR("Device 0x%02X.%2X, Node:0x%p ",ISERIES_BUS(DeviceNode),ISERIES_DEVFUN(DeviceNode),DeviceNode); return DeviceNode;}/***************************************************************************** * Allocate pci_controller(phb) initialized common variables. * *****************************************************************************/struct pci_controller* pci_alloc_pci_controllerX(char *model, enum phb_types controller_type){ struct pci_controller *hose; hose = (struct pci_controller*)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); if(hose == NULL) return NULL; memset(hose, 0, sizeof(struct pci_controller)); if(strlen(model) < 8) strcpy(hose->what,model); else memcpy(hose->what,model,7); hose->type = controller_type; hose->global_number = global_phb_number; global_phb_number++; *hose_tail = hose; hose_tail = &hose->next; return hose;}/**************************************************************************** * * unsigned int __init find_and_init_phbs(void) * * Description: * This function checks for all possible system PCI host bridges that connect * PCI buses. The system hypervisor is queried as to the guest partition * ownership status. A pci_controller is build for any bus which is partially * owned or fully owned by this guest partition. ****************************************************************************/unsigned long __init find_and_init_phbs(void){ struct pci_controller* phb; HvBusNumber BusNumber; PPCDBG(PPCDBG_BUSWALK,"find_and_init_phbs Entry\n"); /* Check all possible buses. */ for (BusNumber = 0; BusNumber < 256; BusNumber++) { int RtnCode = HvCallXm_testBus(BusNumber); if (RtnCode == 0) { phb = pci_alloc_pci_controllerX("PHB HV", phb_type_hypervisor); if(phb == NULL) { printk("PCI: Allocate pci_controller failed.\n"); PCIFR( "Allocate pci_controller failed."); return -1; } phb->pci_mem_offset = phb->local_number = BusNumber; phb->first_busno = BusNumber; phb->last_busno = BusNumber; phb->ops = &iSeries_pci_ops; PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n",phb,BusNumber); PCIFR("Create iSeries PHB controller: %04X",BusNumber); /***************************************************/ /* Find and connect the devices. */ /***************************************************/ iSeries_Scan_PHBs_Slots(phb); } /* Check for Unexpected Return code, a clue that something */ /* has gone wrong. */ else if(RtnCode != 0x0301) { PCIFR("Unexpected Return on Probe(0x%04X): 0x%04X",BusNumber,RtnCode); } } return 0;}/*********************************************************************** * ppc64_pcibios_init * * Chance to initialize and structures or variable before PCI Bus walk. * *<4>buswalk [swapper : iSeries_pcibios_init Entry. *<4>buswalk [swapper : IoMmTable Initialized 0xC00000000034BD30 *<4>buswalk [swapper : find_and_init_phbs Entry *<4>buswalk [swapper : Create iSeries pci_controller:(0xC00000001F5C7000), Bus 0x0017 *<4>buswalk [swapper : Connect EADs: 0x17.00.12 = 0x00 *<4>buswalk [swapper : iSeries_assign_IRQ 0x0017.00.12 = 0x0091 *<4>buswalk [swapper : - allocate and assign IRQ 0x17.00.12 = 0x91 *<4>buswalk [swapper : - FoundDevice: 0x17.28.10 = 0x12AE *<4>buswalk [swapper : - build_device_node 0x17.28.12 *<4>buswalk [swapper : iSeries_pcibios_init Exit. ***********************************************************************/void iSeries_pcibios_init(void){ PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_init Entry.\n"); iSeries_IoMmTable_Initialize(); find_and_init_phbs(); pci_assign_all_busses = 0; PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_init Exit.\n"); }/*********************************************************************** * iSeries_pcibios_fixup(void) ***********************************************************************/void __init iSeries_pcibios_fixup(void){ struct pci_dev* PciDev; struct iSeries_Device_Node* DeviceNode; char Buffer[256]; int DeviceCount = 0; PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_fixup Entry.\n"); /******************************************************/ /* Fix up at the device node and pci_dev relationship */ /******************************************************/ mf_displaySrc(0xC9000100); pci_for_each_dev(PciDev) { DeviceNode = find_Device_Node(PciDev); if(DeviceNode != NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -