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 **********************************************************************************/
pci_Log_Error(char * Error_Text,int Bus,int SubBus,int AgentId,int HvRc)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 **********************************************************************************/
dumpDevice_Node(struct iSeries_Device_Node * DevNode)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 **********************************************************************************/
list_device_nodes(void)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 ***********************************************************************/
build_device_node(HvBusNumber Bus,HvSubBusNumber SubBus,int AgentId,int Function)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 *****************************************************************************/
pci_alloc_pci_controllerX(char * model,enum phb_types controller_type)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 ****************************************************************************/
find_and_init_phbs(void)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 ***********************************************************************/
iSeries_pcibios_init(void)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 ***********************************************************************/
iSeries_pcibios_fixup(void)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 ***********************************************************************/
iSeries_pcibios_fixup_bus(struct pci_bus * PciBus)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 ***********************************************************************/
fixup_resources(struct pci_dev * PciDev)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 *********************************************************************************/
iSeries_Scan_PHBs_Slots(struct pci_controller * Phb)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 *********************************************************************************/
iSeries_Scan_EADs_Bridge(HvBusNumber Bus,HvSubBusNumber SubBus,int IdSel)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 *********************************************************************************/
iSeries_Scan_Bridge_Slot(HvBusNumber Bus,struct HvCallPci_BridgeInfo * BridgeInfo)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 /************************************************************************/
iSeries_memset_io(void * dest,char c,size_t Count)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 }
iSeries_memcpy_toio(void * dest,void * source,size_t count)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 }
iSeries_memcpy_fromio(void * dest,void * source,size_t count)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 **********************************************************************************/
find_Device_Node(struct pci_dev * PciDev)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 /******************************************************************/
get_Device_Node(struct pci_dev * PciDev)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 *************************************************************************/
iSeries_Node_read_config_byte(struct iSeries_Device_Node * DevNode,int Offset,u8 * ReadValue)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 *************************************************************************/
iSeries_Node_read_config_word(struct iSeries_Device_Node * DevNode,int Offset,u16 * ReadValue)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 *************************************************************************/
iSeries_Node_read_config_dword(struct iSeries_Device_Node * DevNode,int Offset,u32 * ReadValue)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 }
iSeries_pci_read_config_byte(struct pci_dev * PciDev,int Offset,u8 * ReadValue)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 }
iSeries_pci_read_config_word(struct pci_dev * PciDev,int Offset,u16 * ReadValue)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 }
iSeries_pci_read_config_dword(struct pci_dev * PciDev,int Offset,u32 * ReadValue)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 *************************************************************************/
iSeries_Node_write_config_byte(struct iSeries_Device_Node * DevNode,int Offset,u8 WriteData)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 *************************************************************************/
iSeries_Node_write_config_word(struct iSeries_Device_Node * DevNode,int Offset,u16 WriteData)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 *************************************************************************/
iSeries_Node_write_config_dword(struct iSeries_Device_Node * DevNode,int Offset,u32 WriteData)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 }
iSeries_pci_write_config_byte(struct pci_dev * PciDev,int Offset,u8 WriteValue)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 }
iSeries_pci_write_config_word(struct pci_dev * PciDev,int Offset,u16 WriteValue)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 }
iSeries_pci_write_config_dword(struct pci_dev * PciDev,int Offset,u32 WriteValue)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 ************************************************************************/
logPciError(char * ErrorTxt,void * IoAddress,struct iSeries_Device_Node * DevNode,u64 RtnCode)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 ************************************************************************/
pciRetrySuccessful(struct iSeries_Device_Node * DevNode)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 /************************************************************************/
iSeries_Read_Byte(void * IoAddress)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;
iSeries_Read_Word(void * IoAddress)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 }
iSeries_Read_Long(void * IoAddress)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 /************************************************************************/
iSeries_Write_Byte(u8 Data,void * IoAddress)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 }
iSeries_Write_Word(u16 Data,void * IoAddress)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 }
iSeries_Write_Long(u32 Data,void * IoAddress)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
iSeries_pcibios_init_early(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 /************************************************************************/
pci_set_reset(struct pci_dev * PciDev,int State)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 }
986