This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / arch / ppc64 / kernel / iSeries_pci.c
1 #define PCIFR(...)
2 /*
3  * iSeries_pci.c
4  *
5  * Copyright (C) 2001 Allan Trautman, IBM Corporation
6  *
7  * iSeries specific routines for PCI.
8  * 
9  * Based on code from pci.c and iSeries_pci.c 32bit
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
24  */
25 #include <linux/kernel.h>
26 #include <linux/list.h> 
27 #include <linux/string.h>
28 #include <linux/init.h>
29 #include <linux/module.h>
30 #include <linux/ide.h>
31 #include <linux/pci.h>
32
33 #include <asm/io.h>
34 #include <asm/irq.h>
35 #include <asm/prom.h>
36 #include <asm/machdep.h>
37 #include <asm/pci-bridge.h>
38 #include <asm/ppcdebug.h>
39 #include <asm/naca.h>
40 #include <asm/iommu.h>
41
42 #include <asm/iSeries/HvCallPci.h>
43 #include <asm/iSeries/HvCallSm.h>
44 #include <asm/iSeries/HvCallXm.h>
45 #include <asm/iSeries/LparData.h>
46 #include <asm/iSeries/iSeries_irq.h>
47 #include <asm/iSeries/iSeries_pci.h>
48 #include <asm/iSeries/mf.h>
49
50 #include "iSeries_IoMmTable.h"
51 #include "pci.h"
52
53 extern int panic_timeout;
54
55 extern unsigned long iSeries_Base_Io_Memory;    
56
57 extern struct iommu_table *tceTables[256];
58 extern unsigned long io_page_mask;
59
60 extern void iSeries_MmIoTest(void);
61
62 /*
63  * Forward declares of prototypes. 
64  */
65 static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn);
66 static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb);
67 static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus,
68                 int IdSel);
69 static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus,
70                 struct HvCallPci_BridgeInfo *Info);
71
72 LIST_HEAD(iSeries_Global_Device_List);
73
74 static int DeviceCount;
75
76 /* Counters and control flags. */
77 static long Pci_Io_Read_Count;
78 static long Pci_Io_Write_Count;
79 #if 0
80 static long Pci_Cfg_Read_Count;
81 static long Pci_Cfg_Write_Count;
82 #endif
83 static long Pci_Error_Count;
84
85 static int Pci_Retry_Max = 3;   /* Only retry 3 times  */       
86 static int Pci_Error_Flag = 1;  /* Set Retry Error on. */
87
88 static struct pci_ops iSeries_pci_ops;
89
90 /*
91  * Log Error infor in Flight Recorder to system Console.
92  * Filter out the device not there errors.
93  * PCI: EADs Connect Failed 0x18.58.10 Rc: 0x00xx
94  * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx
95  * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx
96  */
97 static void pci_Log_Error(char *Error_Text, int Bus, int SubBus,
98                 int AgentId, int HvRc)
99 {
100         if (HvRc == 0x0302)
101                 return;
102
103         printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X",
104                Error_Text, Bus, SubBus, AgentId, HvRc);
105 }
106
107 /*
108  * build_device_node(u16 Bus, int SubBus, u8 DevFn)
109  */
110 static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus,
111                 HvSubBusNumber SubBus, int AgentId, int Function)
112 {
113         struct iSeries_Device_Node *node;
114
115         PPCDBG(PPCDBG_BUSWALK,
116                         "-build_device_node 0x%02X.%02X.%02X Function: %02X\n",
117                         Bus, SubBus, AgentId, Function);
118
119         node = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL);
120         if (node == NULL)
121                 return NULL;
122
123         memset(node, 0, sizeof(struct iSeries_Device_Node));
124         list_add_tail(&node->Device_List, &iSeries_Global_Device_List);
125 #if 0
126         node->DsaAddr = ((u64)Bus << 48) + ((u64)SubBus << 40) + ((u64)0x10 << 32);
127 #endif
128         node->DsaAddr.DsaAddr = 0;
129         node->DsaAddr.Dsa.busNumber = Bus;
130         node->DsaAddr.Dsa.subBusNumber = SubBus;
131         node->DsaAddr.Dsa.deviceId = 0x10;
132         node->AgentId = AgentId;
133         node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
134         node->IoRetry = 0;
135         iSeries_Get_Location_Code(node);
136         PCIFR("Device 0x%02X.%2X, Node:0x%p ", ISERIES_BUS(node),
137                         ISERIES_DEVFUN(node), node);
138         return node;
139 }
140
141 /*
142  * unsigned long __init find_and_init_phbs(void)
143  *
144  * Description:
145  *   This function checks for all possible system PCI host bridges that connect
146  *   PCI buses.  The system hypervisor is queried as to the guest partition
147  *   ownership status.  A pci_controller is built for any bus which is partially
148  *   owned or fully owned by this guest partition.
149  */
150 unsigned long __init find_and_init_phbs(void)
151 {
152         struct pci_controller *phb;
153         HvBusNumber bus;
154
155         PPCDBG(PPCDBG_BUSWALK, "find_and_init_phbs Entry\n");
156
157         /* Check all possible buses. */
158         for (bus = 0; bus < 256; bus++) {
159                 int ret = HvCallXm_testBus(bus);
160                 if (ret == 0) {
161                         printk("bus %d appears to exist\n", bus);
162                         phb = pci_alloc_pci_controller(phb_type_hypervisor);
163                         if (phb == NULL) {
164                                 PCIFR("Allocate pci_controller failed.");
165                                 return -1;
166                         }
167                         phb->pci_mem_offset = phb->local_number = bus;
168                         phb->first_busno = bus;
169                         phb->last_busno = bus;
170                         phb->ops = &iSeries_pci_ops;
171
172                         PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n",
173                                         phb, bus);
174                         PCIFR("Create iSeries PHB controller: %04X", bus);
175
176                         /* Find and connect the devices. */
177                         iSeries_Scan_PHBs_Slots(phb);
178                 }
179                 /*
180                  * Check for Unexpected Return code, a clue that something
181                  * has gone wrong.
182                  */
183                 else if (ret != 0x0301)
184                         printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X",
185                                bus, ret);
186         }
187         return 0;
188 }
189
190 /*
191  * iSeries_pcibios_init
192  *  
193  * Chance to initialize and structures or variable before PCI Bus walk.
194  */
195 void iSeries_pcibios_init(void)
196 {
197         PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Entry.\n"); 
198         iSeries_IoMmTable_Initialize();
199         find_and_init_phbs();
200         io_page_mask = -1;
201         /* pci_assign_all_busses = 0;           SFRXXX*/
202         PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Exit.\n"); 
203 }
204
205 /*
206  * iSeries_pci_final_fixup(void)  
207  */
208 void __init iSeries_pci_final_fixup(void)
209 {
210         struct pci_dev *pdev = NULL;
211         struct iSeries_Device_Node *node;
212         char Buffer[256];
213         int DeviceCount = 0;
214
215         PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n"); 
216
217         /* Fix up at the device node and pci_dev relationship */
218         mf_displaySrc(0xC9000100);
219
220         printk("pcibios_final_fixup\n");
221         while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))
222                         != NULL) {
223                 node = find_Device_Node(pdev->bus->number, pdev->devfn);
224                 printk("pci dev %p (%x.%x), node %p\n", pdev,
225                        pdev->bus->number, pdev->devfn, node);
226
227                 if (node != NULL) {
228                         ++DeviceCount;
229                         pdev->sysdata = (void *)node;
230                         node->PciDev = pdev;
231                         PPCDBG(PPCDBG_BUSWALK,
232                                         "pdev 0x%p <==> DevNode 0x%p\n",
233                                         pdev, node);
234                         iSeries_allocateDeviceBars(pdev);
235                         iSeries_Device_Information(pdev, Buffer,
236                                         sizeof(Buffer));
237                         printk("%d. %s\n", DeviceCount, Buffer);
238                         iommu_devnode_init(node);
239                 } else
240                         printk("PCI: Device Tree not found for 0x%016lX\n",
241                                         (unsigned long)pdev);
242                 pdev->irq = node->Irq;
243         }
244         iSeries_IoMmTable_Status();
245         iSeries_activate_IRQs();
246         mf_displaySrc(0xC9000200);
247 }
248
249 void pcibios_fixup_bus(struct pci_bus *PciBus)
250 {
251         PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup_bus(0x%04X) Entry.\n",
252                         PciBus->number); 
253 }
254
255 void pcibios_fixup_resources(struct pci_dev *pdev)
256 {
257         PPCDBG(PPCDBG_BUSWALK, "fixup_resources pdev %p\n", pdev);
258 }   
259
260 /*
261  * Loop through each node function to find usable EADs bridges.  
262  */
263 static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb)
264 {
265         struct HvCallPci_DeviceInfo *DevInfo;
266         HvBusNumber bus = Phb->local_number;    /* System Bus */        
267         const HvSubBusNumber SubBus = 0;        /* EADs is always 0. */
268         int HvRc = 0;
269         int IdSel;      
270         const int MaxAgents = 8;
271
272         DevInfo = (struct HvCallPci_DeviceInfo*)
273                 kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
274         if (DevInfo == NULL)
275                 return;
276
277         /*
278          * Probe for EADs Bridges      
279          */
280         for (IdSel = 1; IdSel < MaxAgents; ++IdSel) {
281                 HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel,
282                                 ISERIES_HV_ADDR(DevInfo),
283                                 sizeof(struct HvCallPci_DeviceInfo));
284                 if (HvRc == 0) {
285                         if (DevInfo->deviceType == HvCallPci_NodeDevice)
286                                 iSeries_Scan_EADs_Bridge(bus, SubBus, IdSel);
287                         else
288                                 printk("PCI: Invalid System Configuration(0x%02X)"
289                                        " for bus 0x%02x id 0x%02x.\n",
290                                        DevInfo->deviceType, bus, IdSel);
291                 }
292                 else
293                         pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc);
294         }
295         kfree(DevInfo);
296 }
297
298 static void iSeries_Scan_EADs_Bridge(HvBusNumber bus, HvSubBusNumber SubBus,
299                 int IdSel)
300 {
301         struct HvCallPci_BridgeInfo *BridgeInfo;
302         HvAgentId AgentId;
303         int Function;
304         int HvRc;
305
306         BridgeInfo = (struct HvCallPci_BridgeInfo *)
307                 kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL);
308         if (BridgeInfo == NULL)
309                 return;
310
311         /* Note: hvSubBus and irq is always be 0 at this level! */
312         for (Function = 0; Function < 8; ++Function) {
313                 AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
314                 HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0);
315                 if (HvRc == 0) {
316                         printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
317                                bus, IdSel, Function, AgentId);
318                         /*  Connect EADs: 0x18.00.12 = 0x00 */
319                         PPCDBG(PPCDBG_BUSWALK,
320                                         "PCI:Connect EADs: 0x%02X.%02X.%02X\n",
321                                         bus, SubBus, AgentId);
322                         HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId,
323                                         ISERIES_HV_ADDR(BridgeInfo),
324                                         sizeof(struct HvCallPci_BridgeInfo));
325                         if (HvRc == 0) {
326                                 printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n",
327                                         BridgeInfo->busUnitInfo.deviceType,
328                                         BridgeInfo->subBusNumber,
329                                         BridgeInfo->maxAgents,
330                                         BridgeInfo->maxSubBusNumber,
331                                         BridgeInfo->logicalSlotNumber);
332                                 PPCDBG(PPCDBG_BUSWALK,
333                                         "PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n",
334                                         BridgeInfo->busUnitInfo.deviceType,
335                                         BridgeInfo->subBusNumber,
336                                         BridgeInfo->maxAgents,
337                                         BridgeInfo->maxSubBusNumber,
338                                         BridgeInfo->logicalSlotNumber);
339
340                                 if (BridgeInfo->busUnitInfo.deviceType ==
341                                                 HvCallPci_BridgeDevice)  {
342                                         /* Scan_Bridge_Slot...: 0x18.00.12 */
343                                         iSeries_Scan_Bridge_Slot(bus, BridgeInfo);
344                                 } else
345                                         printk("PCI: Invalid Bridge Configuration(0x%02X)",
346                                                 BridgeInfo->busUnitInfo.deviceType);
347                         }
348                 } else if (HvRc != 0x000B)
349                         pci_Log_Error("EADs Connect",
350                                         bus, SubBus, AgentId, HvRc);
351         }
352         kfree(BridgeInfo);
353 }
354
355 /*
356  * This assumes that the node slot is always on the primary bus!
357  */
358 static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus,
359                 struct HvCallPci_BridgeInfo *BridgeInfo)
360 {
361         struct iSeries_Device_Node *node;
362         HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
363         u16 VendorId = 0;
364         int HvRc = 0;
365         u8 Irq = 0;
366         int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
367         int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
368         HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function);
369
370         /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */
371         Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel);
372         PPCDBG(PPCDBG_BUSWALK,
373                 "PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n",
374                 Bus, 0, EADsIdSel, Irq);
375
376         /*
377          * Connect all functions of any device found.  
378          */
379         for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
380                 for (Function = 0; Function < 8; ++Function) {
381                         HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
382                         HvRc = HvCallXm_connectBusUnit(Bus, SubBus,
383                                         AgentId, Irq);
384                         if (HvRc != 0) {
385                                 pci_Log_Error("Connect Bus Unit",
386                                               Bus, SubBus, AgentId, HvRc);
387                                 continue;
388                         }
389
390                         HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId,
391                                                       PCI_VENDOR_ID, &VendorId);
392                         if (HvRc != 0) {
393                                 pci_Log_Error("Read Vendor",
394                                               Bus, SubBus, AgentId, HvRc);
395                                 continue;
396                         }
397                         printk("read vendor ID: %x\n", VendorId);
398
399                         /* FoundDevice: 0x18.28.10 = 0x12AE */
400                         PPCDBG(PPCDBG_BUSWALK,
401                                "PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X, irq %d\n",
402                                Bus, SubBus, AgentId, VendorId, Irq);
403                         HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId,
404                                                       PCI_INTERRUPT_LINE, Irq);  
405                         if (HvRc != 0)
406                                 pci_Log_Error("PciCfgStore Irq Failed!",
407                                               Bus, SubBus, AgentId, HvRc);
408
409                         ++DeviceCount;
410                         node = build_device_node(Bus, SubBus, EADsIdSel, Function);
411                         node->Vendor = VendorId;
412                         node->Irq = Irq;
413                         node->LogicalSlot = BridgeInfo->logicalSlotNumber;
414
415                 } /* for (Function = 0; Function < 8; ++Function) */
416         } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */
417         return HvRc;
418 }
419
420 /*
421  * I/0 Memory copy MUST use mmio commands on iSeries
422  * To do; For performance, include the hv call directly
423  */
424 void iSeries_memset_io(volatile void __iomem *dest, char c, size_t Count)
425 {
426         u8 ByteValue = c;
427         long NumberOfBytes = Count;
428
429         while (NumberOfBytes > 0) {
430                 iSeries_Write_Byte(ByteValue, dest++);
431                 -- NumberOfBytes;
432         }
433 }
434 EXPORT_SYMBOL(iSeries_memset_io);
435
436 void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t count)
437 {
438         char *src = source;
439         long NumberOfBytes = count;
440
441         while (NumberOfBytes > 0) {
442                 iSeries_Write_Byte(*src++, dest++);
443                 -- NumberOfBytes;
444         }
445 }
446 EXPORT_SYMBOL(iSeries_memcpy_toio);
447
448 void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *src, size_t count)
449 {
450         char *dst = dest;
451         long NumberOfBytes = count;
452
453         while (NumberOfBytes > 0) {
454                 *dst++ = iSeries_Read_Byte(src++);
455                 -- NumberOfBytes;
456         }
457 }
458 EXPORT_SYMBOL(iSeries_memcpy_fromio);
459
460 /*
461  * Look down the chain to find the matching Device Device
462  */
463 static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn)
464 {
465         struct list_head *pos;
466
467         list_for_each(pos, &iSeries_Global_Device_List) {
468                 struct iSeries_Device_Node *node =
469                         list_entry(pos, struct iSeries_Device_Node, Device_List);
470
471                 if ((bus == ISERIES_BUS(node)) && (devfn == node->DevFn))
472                         return node;
473         }
474         return NULL;
475 }
476
477 #if 0
478 /*
479  * Returns the device node for the passed pci_dev
480  * Sanity Check Node PciDev to passed pci_dev
481  * If none is found, returns a NULL which the client must handle.
482  */
483 static struct iSeries_Device_Node *get_Device_Node(struct pci_dev *pdev)
484 {
485         struct iSeries_Device_Node *node;
486
487         node = pdev->sysdata;
488         if (node == NULL || node->PciDev != pdev)
489                 node = find_Device_Node(pdev->bus->number, pdev->devfn);
490         return node;
491 }
492 #endif
493
494 /*
495  * Config space read and write functions.
496  * For now at least, we look for the device node for the bus and devfn
497  * that we are asked to access.  It may be possible to translate the devfn
498  * to a subbus and deviceid more directly.
499  */
500 static u64 hv_cfg_read_func[4]  = {
501         HvCallPciConfigLoad8, HvCallPciConfigLoad16,
502         HvCallPciConfigLoad32, HvCallPciConfigLoad32
503 };
504
505 static u64 hv_cfg_write_func[4] = {
506         HvCallPciConfigStore8, HvCallPciConfigStore16,
507         HvCallPciConfigStore32, HvCallPciConfigStore32
508 };
509
510 /*
511  * Read PCI config space
512  */
513 static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn,
514                 int offset, int size, u32 *val)
515 {
516         struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn);
517         u64 fn;
518         struct HvCallPci_LoadReturn ret;
519
520         if (node == NULL)
521                 return PCIBIOS_DEVICE_NOT_FOUND;
522
523         fn = hv_cfg_read_func[(size - 1) & 3];
524         HvCall3Ret16(fn, &ret, node->DsaAddr.DsaAddr, offset, 0);
525
526         if (ret.rc != 0) {
527                 *val = ~0;
528                 return PCIBIOS_DEVICE_NOT_FOUND;        /* or something */
529         }
530
531         *val = ret.value;
532         return 0;
533 }
534
535 /*
536  * Write PCI config space
537  */
538
539 static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn,
540                 int offset, int size, u32 val)
541 {
542         struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn);
543         u64 fn;
544         u64 ret;
545
546         if (node == NULL)
547                 return PCIBIOS_DEVICE_NOT_FOUND;
548
549         fn = hv_cfg_write_func[(size - 1) & 3];
550         ret = HvCall4(fn, node->DsaAddr.DsaAddr, offset, val, 0);
551
552         if (ret != 0)
553                 return PCIBIOS_DEVICE_NOT_FOUND;
554
555         return 0;
556 }
557
558 static struct pci_ops iSeries_pci_ops = {
559         .read = iSeries_pci_read_config,
560         .write = iSeries_pci_write_config
561 };
562
563 /*
564  * Check Return Code
565  * -> On Failure, print and log information.
566  *    Increment Retry Count, if exceeds max, panic partition.
567  * -> If in retry, print and log success 
568  *
569  * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234
570  * PCI: Device 23.90 ReadL Retry( 1)
571  * PCI: Device 23.90 ReadL Retry Successful(1)
572  */
573 static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode,
574                 u64 ret)
575 {
576         if (ret != 0)  {
577                 ++Pci_Error_Count;
578                 ++DevNode->IoRetry;
579                 printk("PCI: %s: Device 0x%04X:%02X  I/O Error(%2d): 0x%04X\n",
580                                 TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn,
581                                 DevNode->IoRetry, (int)ret);
582                 /*
583                  * Bump the retry and check for retry count exceeded.
584                  * If, Exceeded, panic the system.
585                  */
586                 if ((DevNode->IoRetry > Pci_Retry_Max) &&
587                                 (Pci_Error_Flag > 0)) {
588                         mf_displaySrc(0xB6000103);
589                         panic_timeout = 0; 
590                         panic("PCI: Hardware I/O Error, SRC B6000103, "
591                                         "Automatic Reboot Disabled.\n");
592                 }
593                 return -1;      /* Retry Try */
594         }
595         /* If retry was in progress, log success and rest retry count */
596         if (DevNode->IoRetry > 0) {
597                 PCIFR("%s: Device 0x%04X:%02X Retry Successful(%2d).",
598                                 TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn,
599                                 DevNode->IoRetry);
600                 DevNode->IoRetry = 0;
601         }
602         return 0; 
603 }
604
605 /*
606  * Translate the I/O Address into a device node, bar, and bar offset.
607  * Note: Make sure the passed variable end up on the stack to avoid
608  * the exposure of being device global.
609  */
610 static inline struct iSeries_Device_Node *xlateIoMmAddress(const volatile void __iomem *IoAddress,
611                  u64 *dsaptr, u64 *BarOffsetPtr)
612 {
613         unsigned long OrigIoAddr;
614         unsigned long BaseIoAddr;
615         unsigned long TableIndex;
616         struct iSeries_Device_Node *DevNode;
617
618         OrigIoAddr = (unsigned long __force)IoAddress;
619         if ((OrigIoAddr < iSeries_Base_Io_Memory) ||
620                         (OrigIoAddr >= iSeries_Max_Io_Memory))
621                 return NULL;
622         BaseIoAddr = OrigIoAddr - iSeries_Base_Io_Memory;
623         TableIndex = BaseIoAddr / iSeries_IoMmTable_Entry_Size;
624         DevNode = iSeries_IoMmTable[TableIndex];
625
626         if (DevNode != NULL) {
627                 int barnum = iSeries_IoBarTable[TableIndex];
628                 *dsaptr = DevNode->DsaAddr.DsaAddr | (barnum << 24);
629                 *BarOffsetPtr = BaseIoAddr % iSeries_IoMmTable_Entry_Size;
630         } else
631                 panic("PCI: Invalid PCI IoAddress detected!\n");
632         return DevNode;
633 }
634
635 /*
636  * Read MM I/O Instructions for the iSeries
637  * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal
638  * else, data is returned in big Endian format.
639  *
640  * iSeries_Read_Byte = Read Byte  ( 8 bit)
641  * iSeries_Read_Word = Read Word  (16 bit)
642  * iSeries_Read_Long = Read Long  (32 bit)
643  */
644 u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
645 {
646         u64 BarOffset;
647         u64 dsa;
648         struct HvCallPci_LoadReturn ret;
649         struct iSeries_Device_Node *DevNode =
650                 xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
651
652         if (DevNode == NULL) {
653                 static unsigned long last_jiffies;
654                 static int num_printed;
655
656                 if ((jiffies - last_jiffies) > 60 * HZ) {
657                         last_jiffies = jiffies;
658                         num_printed = 0;
659                 }
660                 if (num_printed++ < 10)
661                         printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress);
662                 return 0xff;
663         }
664         do {
665                 ++Pci_Io_Read_Count;
666                 HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
667         } while (CheckReturnCode("RDB", DevNode, ret.rc) != 0);
668
669         return (u8)ret.value;
670 }
671 EXPORT_SYMBOL(iSeries_Read_Byte);
672
673 u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
674 {
675         u64 BarOffset;
676         u64 dsa;
677         struct HvCallPci_LoadReturn ret;
678         struct iSeries_Device_Node *DevNode =
679                 xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
680
681         if (DevNode == NULL) {
682                 static unsigned long last_jiffies;
683                 static int num_printed;
684
685                 if ((jiffies - last_jiffies) > 60 * HZ) {
686                         last_jiffies = jiffies;
687                         num_printed = 0;
688                 }
689                 if (num_printed++ < 10)
690                         printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress);
691                 return 0xffff;
692         }
693         do {
694                 ++Pci_Io_Read_Count;
695                 HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
696                                 BarOffset, 0);
697         } while (CheckReturnCode("RDW", DevNode, ret.rc) != 0);
698
699         return swab16((u16)ret.value);
700 }
701 EXPORT_SYMBOL(iSeries_Read_Word);
702
703 u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
704 {
705         u64 BarOffset;
706         u64 dsa;
707         struct HvCallPci_LoadReturn ret;
708         struct iSeries_Device_Node *DevNode =
709                 xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
710
711         if (DevNode == NULL) {
712                 static unsigned long last_jiffies;
713                 static int num_printed;
714
715                 if ((jiffies - last_jiffies) > 60 * HZ) {
716                         last_jiffies = jiffies;
717                         num_printed = 0;
718                 }
719                 if (num_printed++ < 10)
720                         printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress);
721                 return 0xffffffff;
722         }
723         do {
724                 ++Pci_Io_Read_Count;
725                 HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
726                                 BarOffset, 0);
727         } while (CheckReturnCode("RDL", DevNode, ret.rc) != 0);
728
729         return swab32((u32)ret.value);
730 }
731 EXPORT_SYMBOL(iSeries_Read_Long);
732
733 /*
734  * Write MM I/O Instructions for the iSeries
735  *
736  * iSeries_Write_Byte = Write Byte (8 bit)
737  * iSeries_Write_Word = Write Word(16 bit)
738  * iSeries_Write_Long = Write Long(32 bit)
739  */
740 void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
741 {
742         u64 BarOffset;
743         u64 dsa;
744         u64 rc;
745         struct iSeries_Device_Node *DevNode =
746                 xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
747
748         if (DevNode == NULL) {
749                 static unsigned long last_jiffies;
750                 static int num_printed;
751
752                 if ((jiffies - last_jiffies) > 60 * HZ) {
753                         last_jiffies = jiffies;
754                         num_printed = 0;
755                 }
756                 if (num_printed++ < 10)
757                         printk(KERN_ERR "iSeries_Write_Byte: invalid access at IO address %p\n", IoAddress);
758                 return;
759         }
760         do {
761                 ++Pci_Io_Write_Count;
762                 rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
763         } while (CheckReturnCode("WWB", DevNode, rc) != 0);
764 }
765 EXPORT_SYMBOL(iSeries_Write_Byte);
766
767 void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
768 {
769         u64 BarOffset;
770         u64 dsa;
771         u64 rc;
772         struct iSeries_Device_Node *DevNode =
773                 xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
774
775         if (DevNode == NULL) {
776                 static unsigned long last_jiffies;
777                 static int num_printed;
778
779                 if ((jiffies - last_jiffies) > 60 * HZ) {
780                         last_jiffies = jiffies;
781                         num_printed = 0;
782                 }
783                 if (num_printed++ < 10)
784                         printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress);
785                 return;
786         }
787         do {
788                 ++Pci_Io_Write_Count;
789                 rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
790         } while (CheckReturnCode("WWW", DevNode, rc) != 0);
791 }
792 EXPORT_SYMBOL(iSeries_Write_Word);
793
794 void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
795 {
796         u64 BarOffset;
797         u64 dsa;
798         u64 rc;
799         struct iSeries_Device_Node *DevNode =
800                 xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
801
802         if (DevNode == NULL) {
803                 static unsigned long last_jiffies;
804                 static int num_printed;
805
806                 if ((jiffies - last_jiffies) > 60 * HZ) {
807                         last_jiffies = jiffies;
808                         num_printed = 0;
809                 }
810                 if (num_printed++ < 10)
811                         printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress);
812                 return;
813         }
814         do {
815                 ++Pci_Io_Write_Count;
816                 rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
817         } while (CheckReturnCode("WWL", DevNode, rc) != 0);
818 }
819 EXPORT_SYMBOL(iSeries_Write_Long);