cleanup
[linux-2.4.21-pre4.git] / arch / ppc64 / kernel / iSeries_pci.c
1 /*
2  * iSeries_pci.c
3  *
4  * Copyright (C) 2001 Allan Trautman, IBM Corporation
5  *
6  * iSeries specific routines for PCI.
7  * 
8  * Based on code from pci.c and iSeries_pci.c 32bit
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23  */
24 #include <linux/config.h>
25 #include <linux/kernel.h>
26 #include <linux/list.h> 
27 #include <linux/string.h>
28 #include <linux/init.h>
29 #include <linux/ide.h>
30 #include <linux/pci.h>
31 #include <linux/rtc.h>
32 #include <linux/time.h>
33
34 #include <asm/io.h>
35 #include <asm/irq.h>
36 #include <asm/prom.h>
37 #include <asm/machdep.h>
38 #include <asm/pci-bridge.h>
39 #include <asm/ppcdebug.h>
40 #include <asm/naca.h>
41 #include <asm/flight_recorder.h>
42 #include <asm/hardirq.h>
43 #include <asm/time.h>
44 #include <asm/pci_dma.h>
45
46 #include <asm/iSeries/HvCallPci.h>
47 #include <asm/iSeries/HvCallSm.h>
48 #include <asm/iSeries/HvCallXm.h>
49 #include <asm/iSeries/LparData.h>
50 #include <asm/iSeries/iSeries_irq.h>
51 #include <asm/iSeries/iSeries_pci.h>
52 #include <asm/iSeries/mf.h>
53
54 #include "iSeries_IoMmTable.h"
55 #include "pci.h"
56
57 extern struct pci_controller* hose_head;
58 extern struct pci_controller** hose_tail;
59 extern int    global_phb_number;
60 extern int    panic_timeout;
61
62 extern struct device_node *allnodes;
63 extern unsigned long phb_tce_table_init(struct pci_controller *phb);
64 extern unsigned long iSeries_Base_Io_Memory;    
65
66 extern struct pci_ops iSeries_pci_ops;
67 extern struct flightRecorder* PciFr;
68 extern struct TceTable* tceTables[256];
69
70 /*******************************************************************
71  * Counters and control flags. 
72  *******************************************************************/
73 extern long   Pci_Io_Read_Count;
74 extern long   Pci_Io_Write_Count;
75 extern long   Pci_Cfg_Read_Count;
76 extern long   Pci_Cfg_Write_Count;
77 extern long   Pci_Error_Count;
78
79 extern int    Pci_Retry_Max;    
80 extern int    Pci_Error_Flag;
81 extern int    Pci_Trace_Flag;
82
83 /*******************************************************************
84  * Forward declares of prototypes. 
85  *******************************************************************/
86 struct iSeries_Device_Node* find_Device_Node(struct pci_dev* PciDev);
87 struct iSeries_Device_Node* get_Device_Node(struct pci_dev* PciDev);
88
89 unsigned long find_and_init_phbs(void);
90 void          fixup_resources(struct pci_dev *dev);
91 void          iSeries_pcibios_fixup(void);
92 struct        pci_controller* alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words) ;
93
94 void  iSeries_Scan_PHBs_Slots(struct pci_controller* Phb);
95 void  iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);
96 int   iSeries_Scan_Bridge_Slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo* Info);
97 void  list_device_nodes(void);
98
99 struct pci_dev;
100
101 extern struct list_head iSeries_Global_Device_List;
102
103 int DeviceCount = 0;
104
105 /**********************************************************************************
106  * Log Error infor in Flight Recorder to system Console.
107  * Filter out the device not there errors.
108  * PCI: EADs Connect Failed 0x18.58.10 Rc: 0x00xx
109  * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx
110  * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx
111  **********************************************************************************/
112 void  pci_Log_Error(char* Error_Text, int Bus, int SubBus, int AgentId, int HvRc)
113 {
114         if( HvRc != 0x0302) { 
115                 char ErrorString[128];
116                 sprintf(ErrorString,"%s Failed: 0x%02X.%02X.%02X Rc: 0x%04X",Error_Text,Bus,SubBus,AgentId,HvRc);
117                 PCIFR(ErrorString);
118                 printk("PCI: %s\n",ErrorString);
119         }
120 }
121
122 /**********************************************************************************
123  * Dump the iSeries Temp Device Node 
124  *<4>buswalk [swapper : - DeviceNode: 0xC000000000634300
125  *<4>00. Device Node   = 0xC000000000634300
126  *<4>    - PciDev      = 0x0000000000000000
127  *<4>    - tDevice     = 0x  17:01.00  0x1022 00
128  *<4>  4. Device Node = 0xC000000000634480
129  *<4>     - PciDev    = 0x0000000000000000
130  *<4>     - Device    = 0x  18:38.16 Irq:0xA7 Vendor:0x1014  Flags:0x00
131  *<4>     - Devfn     = 0xB0: 22.18
132  **********************************************************************************/
133 void dumpDevice_Node(struct iSeries_Device_Node* DevNode)
134 {
135         udbg_printf("Device Node      = 0x%p\n",DevNode);
136         udbg_printf("     - PciDev    = 0x%p\n",DevNode->PciDev);
137         udbg_printf("     - Device    = 0x%4X:%02X.%02X (0x%02X)\n",
138                     ISERIES_BUS(DevNode),
139                     ISERIES_SUBBUS(DevNode),
140                     DevNode->AgentId,
141                     DevNode->DevFn);
142         udbg_printf("     - LSlot     = 0x%02X\n",DevNode->LogicalSlot);
143         udbg_printf("     - TceTable  = 0x%p\n  ",DevNode->DevTceTable);
144
145         udbg_printf("     - DSA       = 0x%04X\n",ISERIES_DSA(DevNode)>>32 );
146
147         udbg_printf("                 = Irq:0x%02X Vendor:0x%04X  Flags:0x%02X\n",
148                     DevNode->Irq,
149                     DevNode->Vendor,
150                     DevNode->Flags );
151         udbg_printf("     - Location  = %s\n",DevNode->CardLocation);
152
153
154 }
155 /**********************************************************************************
156  * Walk down the device node chain 
157  **********************************************************************************/
158 void  list_device_nodes(void)
159 {
160         struct list_head* Device_Node_Ptr = iSeries_Global_Device_List.next;
161         while(Device_Node_Ptr != &iSeries_Global_Device_List) {
162                 dumpDevice_Node( (struct iSeries_Device_Node*)Device_Node_Ptr );
163                 Device_Node_Ptr = Device_Node_Ptr->next;
164         }
165 }
166         
167
168 /***********************************************************************
169  * build_device_node(u16 Bus, int SubBus, u8 DevFn)
170  *
171  ***********************************************************************/
172 struct iSeries_Device_Node* build_device_node(HvBusNumber Bus, HvSubBusNumber  SubBus, int AgentId, int Function)
173 {
174         struct iSeries_Device_Node*  DeviceNode;
175
176         PPCDBG(PPCDBG_BUSWALK,"-build_device_node 0x%02X.%02X.%02X Function: %02X\n",Bus,SubBus,AgentId, Function);
177
178         DeviceNode = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL);
179         if(DeviceNode == NULL) return NULL;
180
181         memset(DeviceNode,0,sizeof(struct iSeries_Device_Node) );
182         list_add_tail(&DeviceNode->Device_List,&iSeries_Global_Device_List);
183         /*DeviceNode->DsaAddr      = ((u64)Bus<<48)+((u64)SubBus<<40)+((u64)0x10<<32); */
184         ISERIES_BUS(DeviceNode)       = Bus;
185         ISERIES_SUBBUS(DeviceNode)    = SubBus;
186         DeviceNode->DsaAddr.deviceId  = 0x10;
187         DeviceNode->DsaAddr.barNumber = 0;
188         DeviceNode->AgentId           = AgentId;
189         DeviceNode->DevFn             = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId),Function );
190         DeviceNode->IoRetry           = 0;
191         iSeries_Get_Location_Code(DeviceNode);
192         PCIFR("Device 0x%02X.%2X, Node:0x%p ",ISERIES_BUS(DeviceNode),ISERIES_DEVFUN(DeviceNode),DeviceNode);
193         return DeviceNode;
194 }
195 /****************************************************************************
196
197 * Allocate pci_controller(phb) initialized common variables. 
198
199 *****************************************************************************/
200 struct pci_controller* pci_alloc_pci_controllerX(char *model, enum phb_types controller_type)
201 {
202         struct pci_controller *hose;
203         hose = (struct pci_controller*)kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
204         if(hose == NULL) return NULL;
205
206         memset(hose, 0, sizeof(struct pci_controller));
207         if(strlen(model) < 8) strcpy(hose->what,model);
208         else                  memcpy(hose->what,model,7);
209         hose->type = controller_type;
210         hose->global_number = global_phb_number;
211         global_phb_number++;
212
213         *hose_tail = hose;
214         hose_tail = &hose->next;
215         return hose;
216 }
217
218 /****************************************************************************
219  *
220  * unsigned int __init find_and_init_phbs(void)
221  *
222  * Description:
223  *   This function checks for all possible system PCI host bridges that connect
224  *   PCI buses.  The system hypervisor is queried as to the guest partition
225  *   ownership status.  A pci_controller is build for any bus which is partially
226  *   owned or fully owned by this guest partition.
227  ****************************************************************************/
228 unsigned long __init find_and_init_phbs(void)
229 {
230         struct      pci_controller* phb;
231         HvBusNumber BusNumber;
232
233         PPCDBG(PPCDBG_BUSWALK,"find_and_init_phbs Entry\n");
234
235         /* Check all possible buses. */
236         for (BusNumber = 0; BusNumber < 256; BusNumber++) {
237                 int RtnCode = HvCallXm_testBus(BusNumber);
238                 if (RtnCode == 0) {
239                         phb = pci_alloc_pci_controllerX("PHB HV", phb_type_hypervisor);
240                         if(phb == NULL) {
241                                 printk("PCI: Allocate pci_controller failed.\n");
242                                 PCIFR(      "Allocate pci_controller failed.");
243                                 return -1;
244                         }
245                         phb->pci_mem_offset = phb->local_number = BusNumber;
246                         phb->first_busno  = BusNumber;
247                         phb->last_busno   = BusNumber;
248                         phb->ops          = &iSeries_pci_ops;
249
250                         PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n",phb,BusNumber);
251                         PCIFR("Create iSeries PHB controller: %04X",BusNumber);
252
253                         /***************************************************/
254                         /* Find and connect the devices.                   */
255                         /***************************************************/
256                         iSeries_Scan_PHBs_Slots(phb);
257                 }
258                 /* Check for Unexpected Return code, a clue that something */
259                 /* has gone wrong.                                         */
260                 else if(RtnCode != 0x0301) {
261                         PCIFR("Unexpected Return on Probe(0x%04X): 0x%04X",BusNumber,RtnCode);
262                 }
263
264         }
265         return 0;
266 }
267 /*********************************************************************** 
268  * ppc64_pcibios_init
269  *  
270  * Chance to initialize and structures or variable before PCI Bus walk.
271  *  
272  *<4>buswalk [swapper : iSeries_pcibios_init Entry.
273  *<4>buswalk [swapper : IoMmTable Initialized 0xC00000000034BD30
274  *<4>buswalk [swapper : find_and_init_phbs Entry
275  *<4>buswalk [swapper : Create iSeries pci_controller:(0xC00000001F5C7000), Bus 0x0017
276  *<4>buswalk [swapper : Connect EADs: 0x17.00.12 = 0x00
277  *<4>buswalk [swapper : iSeries_assign_IRQ   0x0017.00.12 = 0x0091
278  *<4>buswalk [swapper : - allocate and assign IRQ 0x17.00.12 = 0x91
279  *<4>buswalk [swapper : - FoundDevice: 0x17.28.10 = 0x12AE
280  *<4>buswalk [swapper : - build_device_node 0x17.28.12
281  *<4>buswalk [swapper : iSeries_pcibios_init Exit.
282  ***********************************************************************/
283 void iSeries_pcibios_init(void)
284 {
285         PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_init Entry.\n"); 
286
287         iSeries_IoMmTable_Initialize();
288
289         find_and_init_phbs();
290
291         pci_assign_all_busses = 0;
292         PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_init Exit.\n"); 
293 }
294 /***********************************************************************
295  * iSeries_pcibios_fixup(void)  
296  ***********************************************************************/
297 void __init iSeries_pcibios_fixup(void)
298 {
299         struct pci_dev* PciDev;
300         struct iSeries_Device_Node* DeviceNode;
301         char   Buffer[256];
302         int    DeviceCount = 0;
303
304         PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_fixup Entry.\n"); 
305         /******************************************************/
306         /* Fix up at the device node and pci_dev relationship */
307         /******************************************************/
308         mf_displaySrc(0xC9000100);
309
310         pci_for_each_dev(PciDev) {
311                 DeviceNode = find_Device_Node(PciDev);
312                 if(DeviceNode != NULL) {
313                         ++DeviceCount;
314                         PciDev->sysdata    = (void*)DeviceNode;
315                         DeviceNode->PciDev = PciDev;
316
317                         PPCDBG(PPCDBG_BUSWALK,"PciDev 0x%p <==> DevNode 0x%p\n",PciDev,DeviceNode );
318
319                         iSeries_allocateDeviceBars(PciDev);
320
321                         PPCDBGCALL(PPCDBG_BUSWALK,dumpPci_Dev(PciDev) );
322
323                         iSeries_Device_Information(PciDev,Buffer, sizeof(Buffer) );
324                         printk("%d. %s\n",DeviceCount,Buffer);
325
326                         create_pci_bus_tce_table((unsigned long)DeviceNode);
327                 } else {
328                         printk("PCI: Device Tree not found for 0x%016lX\n",(unsigned long)PciDev);
329                 }
330         }
331         iSeries_IoMmTable_Status();
332
333         iSeries_activate_IRQs();
334
335         mf_displaySrc(0xC9000200);
336 }
337
338 /***********************************************************************
339  * iSeries_pcibios_fixup_bus(int Bus)
340  *
341  ***********************************************************************/
342 void iSeries_pcibios_fixup_bus(struct pci_bus* PciBus)
343 {
344         PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_fixup_bus(0x%04X) Entry.\n",PciBus->number); 
345
346 }
347
348
349 /***********************************************************************
350  * fixup_resources(struct pci_dev *dev) 
351  *      
352  ***********************************************************************/
353 void fixup_resources(struct pci_dev *PciDev)
354 {
355         PPCDBG(PPCDBG_BUSWALK,"fixup_resources PciDev %p\n",PciDev);
356 }   
357
358
359 /********************************************************************************
360 * Loop through each node function to find usable EADs bridges.  
361 *********************************************************************************/
362 void  iSeries_Scan_PHBs_Slots(struct pci_controller* Phb)
363 {
364         struct HvCallPci_DeviceInfo* DevInfo;
365         HvBusNumber    Bus       = Phb->local_number;       /* System Bus        */     
366         HvSubBusNumber SubBus    = 0;                       /* EADs is always 0. */
367         int            HvRc      = 0;
368         int            IdSel     = 1;   
369         int            MaxAgents = 8;
370
371         DevInfo    = (struct HvCallPci_DeviceInfo*)kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
372         if(DevInfo == NULL) return;
373
374         /********************************************************************************
375          * Probe for EADs Bridges      
376          ********************************************************************************/
377         for (IdSel=1; IdSel < MaxAgents; ++IdSel) {
378                 HvRc = HvCallPci_getDeviceInfo(Bus, SubBus, IdSel,REALADDR(DevInfo), sizeof(struct HvCallPci_DeviceInfo));
379                 if (HvRc == 0) {
380                         if(DevInfo->deviceType == HvCallPci_NodeDevice) {
381                                 iSeries_Scan_EADs_Bridge(Bus, SubBus, IdSel);
382                         }
383                         else {
384                                 printk("PCI: Invalid System Configuration(0x%02X).\n",DevInfo->deviceType);
385                                 PCIFR(      "Invalid System Configuration(0x%02X).",  DevInfo->deviceType);
386                         }
387                 }
388                 else pci_Log_Error("getDeviceInfo",Bus, SubBus, IdSel,HvRc);
389         }
390         kfree(DevInfo);
391 }
392
393 /********************************************************************************
394
395 *********************************************************************************/
396 void  iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel)
397 {
398         struct HvCallPci_BridgeInfo* BridgeInfo;
399         HvAgentId      AgentId;
400         int            Function;
401         int            HvRc;
402
403         BridgeInfo = (struct HvCallPci_BridgeInfo*)kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL);
404         if(BridgeInfo == NULL) return;
405
406         /*********************************************************************
407          * Note: hvSubBus and irq is always be 0 at this level!
408          *********************************************************************/
409         for (Function=0; Function < 8; ++Function) {
410                 AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
411                 HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, 0);
412                 if (HvRc == 0) {
413                         /*  Connect EADs: 0x18.00.12 = 0x00 */
414                         PPCDBG(PPCDBG_BUSWALK,"PCI:Connect EADs: 0x%02X.%02X.%02X\n",Bus, SubBus, AgentId);
415                         PCIFR(                    "Connect EADs: 0x%02X.%02X.%02X",  Bus, SubBus, AgentId);
416                         HvRc = HvCallPci_getBusUnitInfo(Bus, SubBus, AgentId, 
417                                                         REALADDR(BridgeInfo), sizeof(struct HvCallPci_BridgeInfo));
418                         if (HvRc == 0) {
419                                 PPCDBG(PPCDBG_BUSWALK,"PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n",
420                                        BridgeInfo->busUnitInfo.deviceType,
421                                        BridgeInfo->subBusNumber,
422                                        BridgeInfo->maxAgents,
423                                        BridgeInfo->maxSubBusNumber,
424                                        BridgeInfo->logicalSlotNumber);
425                                 PCIFR(                     "BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X",
426                                        BridgeInfo->busUnitInfo.deviceType,
427                                        BridgeInfo->subBusNumber,
428                                        BridgeInfo->maxAgents,
429                                        BridgeInfo->maxSubBusNumber,
430                                        BridgeInfo->logicalSlotNumber);
431
432                                 if (BridgeInfo->busUnitInfo.deviceType == HvCallPci_BridgeDevice)  {
433                                         /* Scan_Bridge_Slot...: 0x18.00.12 */
434                                         iSeries_Scan_Bridge_Slot(Bus,BridgeInfo);
435                                 }
436                                 else printk("PCI: Invalid Bridge Configuration(0x%02X)",BridgeInfo->busUnitInfo.deviceType);
437                         }
438                 }
439                 else if(HvRc != 0x000B) pci_Log_Error("EADs Connect",Bus,SubBus,AgentId,HvRc);
440         }
441         kfree(BridgeInfo);
442 }
443
444 /********************************************************************************
445
446 * This assumes that the node slot is always on the primary bus!
447 *
448 *********************************************************************************/
449 int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo* BridgeInfo)
450 {
451         struct iSeries_Device_Node* DeviceNode;
452         HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
453         u16       VendorId    = 0;
454         int       HvRc        = 0;
455         u8        Irq         = 0;
456         int       IdSel       = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
457         int       Function    = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
458         HvAgentId AgentId     = ISERIES_PCI_AGENTID(IdSel, Function);
459         HvAgentId EADsIdSel   = ISERIES_PCI_AGENTID(IdSel, Function);
460         int       FirstSlotId = 0;      
461
462         /**********************************************************/
463         /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3)                */
464         /**********************************************************/
465         Irq   = iSeries_allocate_IRQ(Bus, 0, AgentId);
466         iSeries_assign_IRQ(Irq, Bus, 0, AgentId);
467         PPCDBG(PPCDBG_BUSWALK,"PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n",Bus, 0, AgentId, Irq );
468
469         /****************************************************************************
470          * Connect all functions of any device found.  
471          ****************************************************************************/
472         for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
473                 for (Function = 0; Function < 8; ++Function) {
474                         AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
475                         HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, Irq);
476                         if( HvRc == 0) {
477                                 HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, PCI_VENDOR_ID, &VendorId);
478                                 if( HvRc == 0) {
479                                         /**********************************************************/
480                                         /* FoundDevice: 0x18.28.10 = 0x12AE                       */
481                                         /**********************************************************/
482                                         PPCDBG(PPCDBG_BUSWALK,"PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X\n",
483                                                                                Bus, SubBus, AgentId, VendorId);
484
485                                         HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, PCI_INTERRUPT_LINE, Irq);  
486                                         if( HvRc != 0) {
487                                                 pci_Log_Error("PciCfgStore Irq Failed!",Bus,SubBus,AgentId,HvRc);
488                                         }
489
490                                         ++DeviceCount;
491                                         DeviceNode = build_device_node(Bus, SubBus, EADsIdSel, Function);
492                                         DeviceNode->Vendor      = VendorId;
493                                         DeviceNode->Irq         = Irq;
494                                         DeviceNode->LogicalSlot = BridgeInfo->logicalSlotNumber;
495                                         PCIFR("Device(%4d): 0x%02X.%02X.%02X 0x%02X 0x%04X",
496                                               DeviceCount,Bus, SubBus, AgentId,
497                                               DeviceNode->LogicalSlot,DeviceNode->Vendor);
498
499                                         /***********************************************************
500                                          * On the first device/function, assign irq to slot
501                                          ***********************************************************/
502                                         if(Function == 0) { 
503                                                 FirstSlotId = AgentId;
504                                                 // AHT iSeries_assign_IRQ(Irq, Bus, SubBus, AgentId);
505                                         }
506                                 }
507                                 else pci_Log_Error("Read Vendor",Bus,SubBus,AgentId,HvRc);
508                         }
509                         else pci_Log_Error("Connect Bus Unit",Bus,SubBus, AgentId,HvRc);
510                 } /* for (Function = 0; Function < 8; ++Function) */
511         } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */
512         return HvRc;
513 }
514 /************************************************************************/
515 /* I/0 Memory copy MUST use mmio commands on iSeries                    */
516 /* To do; For performance, include the hv call directly                 */
517 /************************************************************************/
518 void* iSeries_memset_io(void* dest, char c, size_t Count)
519 {
520         u8    ByteValue     = c;
521         long  NumberOfBytes = Count;
522         char* IoBuffer      = dest;
523         while(NumberOfBytes > 0) {
524                 iSeries_Write_Byte( ByteValue, (void*)IoBuffer );
525                 ++IoBuffer;
526                 -- NumberOfBytes;
527         }
528         return dest;
529 }       
530 void* iSeries_memcpy_toio(void *dest, void *source, size_t count)
531 {
532         char *dst           = dest;
533         char *src           = source;
534         long  NumberOfBytes = count;
535         while(NumberOfBytes > 0) {
536                 iSeries_Write_Byte(*src++, (void*)dst++);
537                 -- NumberOfBytes;
538         }
539         return dest;
540 }
541 void* iSeries_memcpy_fromio(void *dest, void *source, size_t count)
542 {
543         char *dst = dest;
544         char *src = source;
545         long  NumberOfBytes = count;
546         while(NumberOfBytes > 0) {
547                 *dst++ = iSeries_Read_Byte( (void*)src++);
548                 -- NumberOfBytes;
549         }
550         return dest;
551 }
552 /**********************************************************************************
553  * Look down the chain to find the matching Device Device
554  **********************************************************************************/
555 struct iSeries_Device_Node* find_Device_Node(struct pci_dev* PciDev)
556 {
557         struct list_head* Device_Node_Ptr = iSeries_Global_Device_List.next;
558         int Bus   = PciDev->bus->number;
559         int DevFn = PciDev->devfn;
560         
561         while(Device_Node_Ptr != &iSeries_Global_Device_List) { 
562                 struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)Device_Node_Ptr;
563                 if(Bus == ISERIES_BUS(DevNode) && DevFn == DevNode->DevFn) {
564                         return DevNode;
565                 }
566                 Device_Node_Ptr = Device_Node_Ptr->next;
567         }
568         return NULL;
569 }
570 /******************************************************************/
571 /* Returns the device node for the passed pci_dev                 */
572 /* Sanity Check Node PciDev to passed pci_dev                     */
573 /* If none is found, returns a NULL which the client must handle. */
574 /******************************************************************/
575 struct iSeries_Device_Node* get_Device_Node(struct pci_dev* PciDev)
576 {
577         struct iSeries_Device_Node* Node;
578         Node = (struct iSeries_Device_Node*)PciDev->sysdata;
579         if(Node == NULL ) {
580                 Node = find_Device_Node(PciDev);
581         }
582         else if(Node->PciDev != PciDev) { 
583                 Node = find_Device_Node(PciDev);
584         }
585         return Node;
586 }
587 /******************************************************************/
588 /* Set and reset Device Node Lock                                 */
589 /******************************************************************/
590 #define setIoLock() \
591     unsigned long IrqFlags; \
592     spin_lock_irqsave(&DevNode->IoLock, IrqFlags ); 
593
594 #define resetIoLock() \
595     int RtnCode = DevNode->ReturnCode; \
596     spin_unlock_irqrestore( &DevNode->IoLock, IrqFlags ); \
597     return RtnCode;
598
599 /**********************************************************************************
600  *
601  * Read PCI Config Space Code 
602  *
603  **********************************************************************************/
604 /** BYTE  *************************************************************************/
605 int iSeries_Node_read_config_byte(struct iSeries_Device_Node* DevNode, int Offset, u8* ReadValue)
606 {
607         u8  ReadData;
608         setIoLock();
609         ++Pci_Cfg_Read_Count;
610         DevNode->ReturnCode = HvCallPci_configLoad8(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10,
611                                                         Offset,&ReadData);
612         if(Pci_Trace_Flag == 1) {
613                 PCIFR("RCB: 0x%04X.%02X 0x%04X = 0x%02X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,ReadData);
614         }
615         if(DevNode->ReturnCode != 0 ) { 
616                 printk("PCI: RCB: 0x%04X.%02X  Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
617                 PCIFR(      "RCB: 0x%04X.%02X  Error: 0x%04X",  ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
618         }
619         *ReadValue = ReadData;
620         resetIoLock();
621 }
622 /** WORD  *************************************************************************/
623 int iSeries_Node_read_config_word(struct iSeries_Device_Node* DevNode, int Offset, u16* ReadValue)
624 {
625         u16  ReadData; 
626         setIoLock();
627         ++Pci_Cfg_Read_Count;
628         DevNode->ReturnCode = HvCallPci_configLoad16(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10,
629                                                         Offset,&ReadData);
630         if(Pci_Trace_Flag == 1) {
631                 PCIFR("RCW: 0x%04X.%02X 0x%04X = 0x%04X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,ReadData);
632         }
633         if(DevNode->ReturnCode != 0 ) { 
634                 printk("PCI: RCW: 0x%04X.%02X  Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
635                 PCIFR(      "RCW: 0x%04X.%02X  Error: 0x%04X",  ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
636
637         }
638         *ReadValue = ReadData;
639         resetIoLock();
640 }
641 /** DWORD *************************************************************************/
642 int iSeries_Node_read_config_dword(struct iSeries_Device_Node* DevNode, int Offset, u32* ReadValue)
643 {
644         u32  ReadData; 
645         setIoLock();
646         ++Pci_Cfg_Read_Count;
647         DevNode->ReturnCode = HvCallPci_configLoad32(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10,
648                                                         Offset,&ReadData);
649         if(Pci_Trace_Flag == 1) {
650                 PCIFR("RCL: 0x%04X.%02X 0x%04X = 0x%08X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,ReadData);
651         }
652         if(DevNode->ReturnCode != 0 ) { 
653                 printk("PCI: RCL: 0x%04X.%02X  Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
654                 PCIFR(      "RCL: 0x%04X.%02X  Error: 0x%04X",  ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
655         }
656         *ReadValue = ReadData;
657         resetIoLock();
658 }
659 int iSeries_pci_read_config_byte(struct pci_dev* PciDev, int Offset, u8* ReadValue) { 
660         struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev);
661         if(DevNode == NULL) return 0x0301;
662         return iSeries_Node_read_config_byte( DevNode ,Offset,ReadValue);
663 }
664 int iSeries_pci_read_config_word(struct pci_dev* PciDev, int Offset, u16* ReadValue) { 
665         struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev);
666         if(DevNode == NULL) return 0x0301;
667         return iSeries_Node_read_config_word( DevNode ,Offset,ReadValue );
668 }
669 int iSeries_pci_read_config_dword(struct pci_dev* PciDev, int Offset, u32* ReadValue) { 
670         struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev);
671         if(DevNode == NULL) return 0x0301;
672         return iSeries_Node_read_config_dword(DevNode ,Offset,ReadValue  );
673 }
674 /**********************************************************************************/
675 /*                                                                                */
676 /* Write PCI Config Space                                                         */
677 /*                                                                                */
678 /** BYTE  *************************************************************************/
679 int iSeries_Node_write_config_byte(struct iSeries_Device_Node* DevNode, int Offset, u8 WriteData)
680 {
681         setIoLock();
682         ++Pci_Cfg_Write_Count;
683         DevNode->ReturnCode = HvCallPci_configStore8(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10,
684                                                           Offset,WriteData);
685         if(Pci_Trace_Flag == 1) {
686                 PCIFR("WCB: 0x%04X.%02X 0x%04X = 0x%02X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,WriteData);
687         }
688         if(DevNode->ReturnCode != 0 ) { 
689                 printk("PCI: WCB: 0x%04X.%02X  Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
690                 PCIFR(      "WCB: 0x%04X.%02X  Error: 0x%04X",  ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
691         }
692         resetIoLock();
693 }
694 /** WORD  *************************************************************************/
695 int iSeries_Node_write_config_word(struct iSeries_Device_Node* DevNode, int Offset, u16 WriteData)
696 {
697         setIoLock();
698         ++Pci_Cfg_Write_Count;
699         DevNode->ReturnCode = HvCallPci_configStore16(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10,
700                                                           Offset,WriteData);
701         if(Pci_Trace_Flag == 1) {
702                 PCIFR("WCW: 0x%04X.%02X 0x%04X = 0x%04X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,WriteData);
703         }
704         if(DevNode->ReturnCode != 0 ) { 
705                 printk("PCI: WCW: 0x%04X.%02X  Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
706                 PCIFR(      "WCW: 0x%04X.%02X  Error: 0x%04X",  ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
707         }
708         resetIoLock();
709 }
710 /** DWORD *************************************************************************/
711 int iSeries_Node_write_config_dword(struct iSeries_Device_Node* DevNode, int Offset, u32 WriteData)
712 {
713         setIoLock();
714         ++Pci_Cfg_Write_Count;
715         DevNode->ReturnCode = HvCallPci_configStore32(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10,
716                                                           Offset,WriteData);
717         if(Pci_Trace_Flag == 1) {
718                 PCIFR("WCL: 0x%04X.%02X 0x%04X = 0x%08X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,WriteData);
719         }
720         if(DevNode->ReturnCode != 0 ) { 
721                 printk("PCI: WCL: 0x%04X.%02X  Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
722                 PCIFR(      "WCL: 0x%04X.%02X  Error: 0x%04X",  ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
723         }
724         resetIoLock();
725 }
726 int iSeries_pci_write_config_byte( struct pci_dev* PciDev,int Offset, u8 WriteValue)
727 {
728         struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev);
729         if(DevNode == NULL) return 0x0301;
730         return iSeries_Node_write_config_byte( DevNode,Offset,WriteValue);
731 }
732 int iSeries_pci_write_config_word( struct pci_dev* PciDev,int Offset,u16 WriteValue)
733 {
734         struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev);
735         if(DevNode == NULL) return 0x0301;
736         return iSeries_Node_write_config_word( DevNode,Offset,WriteValue);
737 }
738 int iSeries_pci_write_config_dword(struct pci_dev* PciDev,int Offset,u32 WriteValue)
739 {
740         struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev);
741         if(DevNode == NULL) return 0x0301;
742         return iSeries_Node_write_config_dword(DevNode,Offset,WriteValue);
743 }
744
745 /************************************************************************/
746 /* Branch Table                                                         */
747 /************************************************************************/
748 struct pci_ops iSeries_pci_ops = {
749         iSeries_pci_read_config_byte,
750         iSeries_pci_read_config_word,
751         iSeries_pci_read_config_dword,
752         iSeries_pci_write_config_byte,
753         iSeries_pci_write_config_word,
754         iSeries_pci_write_config_dword 
755 };
756
757 /************************************************************************
758  * Log Pci Error and check Retry Count 
759  * -> On Failure, print and log information.
760  *    Increment Retry Count, if exceeds max, panic partition.
761  * -> If in retry, print and log success
762  ************************************************************************/
763 void logPciError(char* ErrorTxt, void* IoAddress, struct iSeries_Device_Node* DevNode, u64 RtnCode)
764 {
765         ++DevNode->IoRetry;
766         ++Pci_Error_Count;
767
768         PCIFR("%s: I/O Error(%1d/%1d):0x%04X  IoAddress:0x%p  Device:0x%04X:%02X",  
769               ErrorTxt, DevNode->IoRetry, in_interrupt(), RtnCode, IoAddress, ISERIES_BUS(DevNode),DevNode->AgentId);
770         /*******************************************************/
771         /* Filter out EADs freeze and alignment errors         */
772         /*******************************************************/
773         if(RtnCode == 0x0102) {
774                 PCIFR("EADS Freeze error.......Panic........");
775                 mf_displaySrc(0xB6000103);
776                 panic_timeout = 0; 
777                 panic("PCI: EADs Freeze error SRC B6000103\n");
778         }
779         else if(RtnCode == 0x0241) {
780                 PCIFR("MMIO Alignment error: 0x%p",IoAddress);
781                 mf_displaySrc(0xB6000103);
782                 panic_timeout = 0; 
783                 panic("PCI: MMIO Alignment error. SRC B6000103\n");
784         }
785         /*******************************************************/
786         /* Bump the retry and check for retry count exceeded.  */
787         /* If, Exceeded, panic the system.                     */           
788         /*******************************************************/
789         if(DevNode->IoRetry > Pci_Retry_Max && Pci_Error_Flag != 0 ) {
790                 mf_displaySrc(0xB6000103);
791                 panic_timeout = 0; 
792                 panic("PCI: Hardware I/O Error, SRC B6000103, Automatic Reboot Disabled.\n");
793         }
794         /**************************************************************/
795         /* Wait x ms before retrying I/O to give I/O time to recover. */
796         /* Retry wait delay logic.                                    */
797         /* - On first retry, no delay, maybe just glitch.             */
798         /* - On successify retries, vary the delay to avoid being in a*/
799         /*   repetitive timing window.                                */ 
800         /**************************************************************/
801         if(DevNode->IoRetry > 0) {
802                 udelay(DevNode->IoRetry * 50);
803         }
804 }
805
806 /************************************************************************
807  * Retry was successful
808  ************************************************************************/
809 void  pciRetrySuccessful(struct iSeries_Device_Node* DevNode)
810 {
811         struct  timeval  TimeClock;
812         struct  rtc_time CurTime;
813         do_gettimeofday(&TimeClock);
814         to_tm(TimeClock.tv_sec, &CurTime);
815
816         PCIFR("Retry Successful(%2d) on Device 0x%04X:%02X at %02d.%02d.%02d",
817               DevNode->IoRetry,ISERIES_BUS(DevNode),DevNode->AgentId,
818               CurTime.tm_hour,CurTime.tm_min,CurTime.tm_sec);
819
820         DevNode->IoRetry = 0;
821 }
822
823 /************************************************************************/
824 /* Translate the I/O Address into a device node, bar, and bar offset.   */
825 /* Note: Make sure the passed variable end up on the stack to avoid     */
826 /* the exposure of being device global.                                 */
827 /* The Device Node is Lock to block other I/O to device.                */
828 /************************************************************************/
829 #define setUpMmIo(IoAddress,Type) \
830 unsigned long   IrqFlags; \
831 struct HvCallPci_LoadReturn Return; \
832 union HvDsaMap  DsaData;  \
833 u64             BarOffset;\
834 unsigned long BaseIoAddr = (unsigned long)IoAddress-iSeries_Base_Io_Memory; \
835 long          TableIndex = (BaseIoAddr/iSeries_IoMmTable_Entry_Size);       \
836 struct iSeries_Device_Node* DevNode = *(iSeries_IoMmTable+TableIndex);      \
837 if(DevNode != NULL) { \
838     DsaData.DsaAddr       = ISERIES_DSA(DevNode); \
839     DsaData.Dsa.barNumber = *(iSeries_IoBarTable+TableIndex); \
840     BarOffset             = BaseIoAddr % iSeries_IoMmTable_Entry_Size; \
841     ++Pci_Io_##Type##_Count; \
842     spin_lock_irqsave(&DevNode->IoLock, IrqFlags ); \
843 } \
844 else panic("PCI: Invalid PCI IoAddress detected 0x%p!\n",IoAddress);
845 /************************************************************************/
846 /* Read MM I/O Instructions for the iSeries                             */
847 /* On MM I/O error, all ones are returned and iSeries_pci_IoError is cal*/
848 /* else, data is returned in big Endian format.                         */
849 /************************************************************************/
850 /* iSeries_Read_Byte = Read Byte  ( 8 bit)                              */
851 /* iSeries_Read_Word = Read Word  (16 bit)                              */
852 /* iSeries_Read_Long = Read Long  (32 bit)                              */
853 /************************************************************************/
854 u8  iSeries_Read_Byte(void* IoAddress)
855 {
856         setUpMmIo(IoAddress,Read);
857         do {
858                 HvCall3Ret16(HvCallPciBarLoad8, &Return, DsaData.DsaAddr,BarOffset, 0);
859                 if(Return.rc != 0 ) {
860                         logPciError("RDB",IoAddress, DevNode, Return.rc);
861                 }
862                 else if ( DevNode->IoRetry > 0) {
863                         pciRetrySuccessful(DevNode);
864                 }
865         } while (Return.rc != 0);
866         spin_unlock_irqrestore(&DevNode->IoLock, IrqFlags ); 
867         if(Pci_Trace_Flag == 1 ) PCIFR("RDB: IoAddress 0x%p = 0x%02X",IoAddress, (u8)Return.value);
868         return (u8)Return.value;
869 }
870 int Retry_Test = 0;
871 u16  iSeries_Read_Word(void* IoAddress)
872 {
873         setUpMmIo(IoAddress,Read);
874         do {
875                 HvCall3Ret16(HvCallPciBarLoad16,&Return, DsaData.DsaAddr,BarOffset, 0);
876
877                 if(Return.rc != 0 ) {
878                         logPciError("RDW",IoAddress, DevNode, Return.rc);
879                 }
880                 else if ( DevNode->IoRetry > 0) {
881                         pciRetrySuccessful(DevNode);
882                 }
883         } while (Return.rc != 0);
884         spin_unlock_irqrestore(&DevNode->IoLock, IrqFlags ); 
885         if(Pci_Trace_Flag == 1 ) PCIFR("RDW: IoAddress 0x%p = 0x%04X",IoAddress, (u16)Return.value);
886         return swab16((u16)Return.value);
887 }
888 u32  iSeries_Read_Long(void* IoAddress)
889 {
890         setUpMmIo(IoAddress,Read);
891         do {
892                 HvCall3Ret16(HvCallPciBarLoad32,&Return, DsaData.DsaAddr,BarOffset, 0);
893
894                 if(Return.rc != 0 ) {
895                         logPciError("RDL",IoAddress, DevNode, Return.rc);
896                 }
897                 else if ( DevNode->IoRetry > 0) {
898                         pciRetrySuccessful(DevNode);
899                 }
900         } while (Return.rc != 0);
901         spin_unlock_irqrestore(&DevNode->IoLock, IrqFlags ); 
902         if(Pci_Trace_Flag == 1 ) PCIFR("RDL: IoAddress 0x%p = 0x%08X",IoAddress, swab32((u32)Return.value));
903         return swab32((u32)Return.value);
904 }
905 /************************************************************************/
906 /* Write MM I/O Instructions for the iSeries                            */
907 /************************************************************************/
908 /* iSeries_Write_Byte = Write Byte (8 bit)                              */
909 /* iSeries_Write_Word = Write Word(16 bit)                              */
910 /* iSeries_Write_Long = Write Long(32 bit)                              */
911 /************************************************************************/
912 void iSeries_Write_Byte(u8 Data, void* IoAddress)
913 {
914         setUpMmIo(IoAddress,Write);
915         do {
916                 Return.rc = HvCall4(HvCallPciBarStore8, DsaData.DsaAddr,BarOffset, Data, 0);
917                 if(Return.rc != 0 ) {
918                         logPciError("WWB",IoAddress, DevNode, Return.rc);
919                 }
920                 else if ( DevNode->IoRetry > 0) {
921                         pciRetrySuccessful(DevNode);
922                 }
923         } while (Return.rc != 0);
924         spin_unlock_irqrestore(&DevNode->IoLock, IrqFlags ); 
925         if(Pci_Trace_Flag == 1) PCIFR("WWB: IoAddress 0x%p = 0x%02X",IoAddress,Data);
926 }
927 void iSeries_Write_Word(u16 Data, void* IoAddress)
928 {
929         setUpMmIo(IoAddress,Write);
930         do {
931                 Return.rc = HvCall4(HvCallPciBarStore16,DsaData.DsaAddr,BarOffset, swab16(Data), 0);
932                 if(Return.rc != 0 ) {
933                         logPciError("WWW",IoAddress, DevNode, Return.rc);
934                 }
935                 else if ( DevNode->IoRetry > 0) {
936                         pciRetrySuccessful(DevNode);
937                 }
938         } while (Return.rc != 0);
939         spin_unlock_irqrestore(&DevNode->IoLock, IrqFlags ); 
940         if(Pci_Trace_Flag == 1) PCIFR("WWW: IoAddress 0x%p = 0x%04X",IoAddress,Data);
941 }
942 void iSeries_Write_Long(u32 Data, void* IoAddress)
943 {
944         setUpMmIo(IoAddress,Write);
945         do {
946                 Return.rc = HvCall4(HvCallPciBarStore32,DsaData.DsaAddr,BarOffset, swab32(Data), 0);
947                 if(Return.rc != 0 ) {
948                         logPciError("WWL",IoAddress, DevNode, Return.rc);
949                 }
950                 else if ( DevNode->IoRetry > 0) {
951                         pciRetrySuccessful(DevNode);
952                 }
953         } while (Return.rc != 0);
954         spin_unlock_irqrestore(&DevNode->IoLock, IrqFlags ); 
955         if(Pci_Trace_Flag == 1) PCIFR("WWL: IoAddress 0x%p = 0x%08X",IoAddress, Data);
956 }
957 /*
958  * This is called very early before the page table is setup.
959  * There are warnings here because of type mismatches.. Okay for now. AHT
960  */
961 void 
962 iSeries_pcibios_init_early(void)
963 {
964         //ppc_md.pcibios_read_config_byte   = iSeries_Node_read_config_byte;
965         //ppc_md.pcibios_read_config_word   = iSeries_Node_read_config_word;
966         //ppc_md.pcibios_read_config_dword  = iSeries_Node_read_config_dword;
967         //ppc_md.pcibios_write_config_byte  = iSeries_Node_write_config_byte;
968         //ppc_md.pcibios_write_config_word  = iSeries_Node_write_config_word;
969         //ppc_md.pcibios_write_config_dword = iSeries_Node_write_config_dword;
970 }
971
972 /************************************************************************/
973 /* Set the slot reset line to the state passed in.                      */
974 /* This is the platform specific for code for the pci_reset_device      */
975 /* function.                                                            */
976 /************************************************************************/
977 int pci_set_reset(struct pci_dev* PciDev, int State) {
978         struct iSeries_Device_Node* DeviceNode = (struct iSeries_Device_Node*)PciDev->sysdata;
979         if (DeviceNode == NULL) { 
980                 printk("PCI: Pci Reset Failed, Device Node not found for pci_dev %p\n",PciDev);
981                 return -1;
982         }
983         DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),0x00,DeviceNode->AgentId,State);
984         return DeviceNode->ReturnCode;
985 }