Commit c4f34fde authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: Get native PCI going on iSeries, from Paul Mackerras

From: Anton Blanchard <anton@samba.org>

Get native PCI going on iSeries, from Paul Mackerras
parent 0385d58f
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/ppcdebug.h> #include <asm/ppcdebug.h>
#include <asm/flight_recorder.h>
#include <asm/iSeries/HvCallPci.h> #include <asm/iSeries/HvCallPci.h>
#include <asm/iSeries/iSeries_pci.h> #include <asm/iSeries/iSeries_pci.h>
......
...@@ -153,7 +153,7 @@ int device_Location(struct pci_dev *PciDev, char *BufPtr) ...@@ -153,7 +153,7 @@ int device_Location(struct pci_dev *PciDev, char *BufPtr)
struct iSeries_Device_Node *DevNode = struct iSeries_Device_Node *DevNode =
(struct iSeries_Device_Node *)PciDev->sysdata; (struct iSeries_Device_Node *)PciDev->sysdata;
return sprintf(BufPtr, "PCI: Bus%3d, AgentId%3d, Vendor %04X, Location %s", return sprintf(BufPtr, "PCI: Bus%3d, AgentId%3d, Vendor %04X, Location %s",
DevNode->DsaAddr.busNumber, DevNode->AgentId, DevNode->DsaAddr.Dsa.busNumber, DevNode->AgentId,
DevNode->Vendor, DevNode->Location); DevNode->Vendor, DevNode->Location);
} }
......
...@@ -55,45 +55,13 @@ static hw_irq_controller iSeries_IRQ_handler = { ...@@ -55,45 +55,13 @@ static hw_irq_controller iSeries_IRQ_handler = {
.end = iSeries_end_IRQ .end = iSeries_end_IRQ
}; };
struct iSeries_irqEntry {
u32 dsa;
struct iSeries_irqEntry* next;
};
struct iSeries_irqAnchor {
u8 valid : 1;
u8 reserved : 7;
u16 entryCount;
struct iSeries_irqEntry* head;
};
static struct iSeries_irqAnchor iSeries_irqMap[NR_IRQS];
#if 0
static void iSeries_init_irqMap(int irq);
#endif
void iSeries_init_irq_desc(irq_desc_t *desc) void iSeries_init_irq_desc(irq_desc_t *desc)
{ {
desc->handler = &iSeries_IRQ_handler;
} }
/* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c */ /* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c */
void __init iSeries_init_IRQ(void) void __init iSeries_init_IRQ(void)
{ {
#if 0
int i;
irq_desc_t *desc;
for (i = 0; i < NR_IRQS; i++) {
desc = get_irq_desc(i);
desc->handler = &iSeries_IRQ_handler;
desc->status = 0;
desc->status |= IRQ_DISABLED;
desc->depth = 1;
iSeries_init_irqMap(i);
}
#endif
/* Register PCI event handler and open an event path */ /* Register PCI event handler and open an event path */
PPCDBG(PPCDBG_BUSWALK, PPCDBG(PPCDBG_BUSWALK,
"Register PCI event handler and open an event path\n"); "Register PCI event handler and open an event path\n");
...@@ -101,35 +69,24 @@ void __init iSeries_init_IRQ(void) ...@@ -101,35 +69,24 @@ void __init iSeries_init_IRQ(void)
return; return;
} }
#if 0
/*
* Called by iSeries_init_IRQ
* Prevent IRQs 0 and 255 from being used. IRQ 0 appears in
* uninitialized devices. IRQ 255 appears in the PCI interrupt
* line register if a PCI error occurs,
*/
static void __init iSeries_init_irqMap(int irq)
{
iSeries_irqMap[irq].valid = ((irq == 0) || (irq == 255)) ? 0 : 1;
iSeries_irqMap[irq].entryCount = 0;
iSeries_irqMap[irq].head = NULL;
}
#endif
/* /*
* This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
* It calculates the irq value for the slot. * It calculates the irq value for the slot.
* Note that subBusNumber is always 0 (at the moment at least).
*/ */
int __init iSeries_allocate_IRQ(HvBusNumber busNumber, int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
HvSubBusNumber subBusNumber, HvAgentId deviceId) HvSubBusNumber subBusNumber, HvAgentId deviceId)
{ {
u8 idsel = (deviceId >> 4); u8 idsel = (deviceId >> 4);
u8 function = deviceId & 0x0F; u8 function = deviceId & 7;
return ((((busNumber - 1) * 16 + (idsel - 1) * 8 return ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function + 1;
+ function) * 9 / 8) % 253) + 2;
} }
#define IRQ_TO_BUS(irq) (((((irq) - 1) >> 6) & 0xff) + 1)
#define IRQ_TO_IDSEL(irq) (((((irq) - 1) >> 3) & 7) + 1)
#define IRQ_TO_FUNC(irq) (((irq) - 1) & 7)
/* /*
* This is called out of iSeries_scan_slot to assign the EADS slot * This is called out of iSeries_scan_slot to assign the EADS slot
* to its IRQ number * to its IRQ number
...@@ -137,66 +94,33 @@ int __init iSeries_allocate_IRQ(HvBusNumber busNumber, ...@@ -137,66 +94,33 @@ int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
int __init iSeries_assign_IRQ(int irq, HvBusNumber busNumber, int __init iSeries_assign_IRQ(int irq, HvBusNumber busNumber,
HvSubBusNumber subBusNumber, HvAgentId deviceId) HvSubBusNumber subBusNumber, HvAgentId deviceId)
{ {
int rc; irq_desc_t *desc = get_real_irq_desc(irq);
u32 dsa = (busNumber << 16) | (subBusNumber << 8) | deviceId;
struct iSeries_irqEntry *newEntry;
unsigned long flags;
irq_desc_t *desc = get_irq_desc(irq);
if ((irq < 0) || (irq >= NR_IRQS)) if (desc == NULL)
return -1; return -1;
desc->handler = &iSeries_IRQ_handler;
newEntry = kmalloc(sizeof(*newEntry), GFP_KERNEL); return 0;
if (newEntry == NULL)
return -ENOMEM;
newEntry->dsa = dsa;
newEntry->next = NULL;
/*
* Probably not necessary to lock the irq since allocation is only
* done during buswalk, but it should not hurt anything except a
* little performance to be smp safe.
*/
spin_lock_irqsave(&desc->lock, flags);
if (iSeries_irqMap[irq].valid) {
/* Push the new element onto the irq stack */
newEntry->next = iSeries_irqMap[irq].head;
iSeries_irqMap[irq].head = newEntry;
++iSeries_irqMap[irq].entryCount;
rc = 0;
PPCDBG(PPCDBG_BUSWALK, "iSeries_assign_IRQ 0x%04X.%02X.%02X = 0x%04X\n",
busNumber, subBusNumber, deviceId, irq);
} else {
printk("PCI: Something is wrong with the iSeries_irqMap.\n");
kfree(newEntry);
rc = -1;
}
spin_unlock_irqrestore(&desc->lock, flags);
return rc;
} }
/* This is called by iSeries_activate_IRQs */ /* This is called by iSeries_activate_IRQs */
static unsigned int iSeries_startup_IRQ(unsigned int irq) static unsigned int iSeries_startup_IRQ(unsigned int irq)
{ {
struct iSeries_irqEntry *entry; u32 bus, deviceId, function, mask;
u32 bus, subBus, deviceId, function, mask; const u32 subBus = 0;
for (entry = iSeries_irqMap[irq].head; entry != NULL; bus = IRQ_TO_BUS(irq);
entry = entry->next) { function = IRQ_TO_FUNC(irq);
bus = (entry->dsa >> 16) & 0xFFFF; deviceId = (IRQ_TO_IDSEL(irq) << 4) + function;
subBus = (entry->dsa >> 8) & 0xFF;
deviceId = entry->dsa & 0xFF; /* Link the IRQ number to the bridge */
function = deviceId & 0x0F; HvCallXm_connectBusUnit(bus, subBus, deviceId, irq);
/* Link the IRQ number to the bridge */
HvCallXm_connectBusUnit(bus, subBus, deviceId, irq); /* Unmask bridge interrupts in the FISR */
/* Unmask bridge interrupts in the FISR */ mask = 0x01010000 << function;
mask = 0x01010000 << function; HvCallPci_unmaskFisr(bus, subBus, deviceId, mask);
HvCallPci_unmaskFisr(bus, subBus, deviceId, mask); PPCDBG(PPCDBG_BUSWALK, "iSeries_activate_IRQ 0x%02X.%02X.%02X Irq:0x%02X\n",
PPCDBG(PPCDBG_BUSWALK, "iSeries_activate_IRQ 0x%02X.%02X.%02X Irq:0x%02X\n",
bus, subBus, deviceId, irq); bus, subBus, deviceId, irq);
}
return 0; return 0;
} }
...@@ -223,22 +147,20 @@ void __init iSeries_activate_IRQs() ...@@ -223,22 +147,20 @@ void __init iSeries_activate_IRQs()
/* this is not called anywhere currently */ /* this is not called anywhere currently */
static void iSeries_shutdown_IRQ(unsigned int irq) static void iSeries_shutdown_IRQ(unsigned int irq)
{ {
struct iSeries_irqEntry *entry; u32 bus, deviceId, function, mask;
u32 bus, subBus, deviceId, function, mask; const u32 subBus = 0;
/* irq should be locked by the caller */ /* irq should be locked by the caller */
bus = IRQ_TO_BUS(irq);
function = IRQ_TO_FUNC(irq);
deviceId = (IRQ_TO_IDSEL(irq) << 4) + function;
/* Invalidate the IRQ number in the bridge */
HvCallXm_connectBusUnit(bus, subBus, deviceId, 0);
for (entry = iSeries_irqMap[irq].head; entry; entry = entry->next) { /* Mask bridge interrupts in the FISR */
bus = (entry->dsa >> 16) & 0xFFFF; mask = 0x01010000 << function;
subBus = (entry->dsa >> 8) & 0xFF; HvCallPci_maskFisr(bus, subBus, deviceId, mask);
deviceId = entry->dsa & 0xFF;
function = deviceId & 0x0F;
/* Invalidate the IRQ number in the bridge */
HvCallXm_connectBusUnit(bus, subBus, deviceId, 0);
/* Mask bridge interrupts in the FISR */
mask = 0x01010000 << function;
HvCallPci_maskFisr(bus, subBus, deviceId, mask);
}
} }
/* /*
...@@ -247,21 +169,19 @@ static void iSeries_shutdown_IRQ(unsigned int irq) ...@@ -247,21 +169,19 @@ static void iSeries_shutdown_IRQ(unsigned int irq)
*/ */
static void iSeries_disable_IRQ(unsigned int irq) static void iSeries_disable_IRQ(unsigned int irq)
{ {
struct iSeries_irqEntry *entry; u32 bus, deviceId, function, mask;
u32 bus, subBus, deviceId, mask; const u32 subBus = 0;
/* The IRQ has already been locked by the caller */ /* The IRQ has already been locked by the caller */
for (entry = iSeries_irqMap[irq].head; entry; entry = entry->next) { bus = IRQ_TO_BUS(irq);
bus = (entry->dsa >> 16) & 0xFFFF; function = IRQ_TO_FUNC(irq);
subBus = (entry->dsa >> 8) & 0xFF; deviceId = (IRQ_TO_IDSEL(irq) << 4) + function;
deviceId = entry->dsa & 0xFF;
/* Mask secondary INTA */ /* Mask secondary INTA */
mask = 0x80000000; mask = 0x80000000;
HvCallPci_maskInterrupts(bus, subBus, deviceId, mask); HvCallPci_maskInterrupts(bus, subBus, deviceId, mask);
PPCDBG(PPCDBG_BUSWALK, PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
"iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n", bus, subBus, deviceId, irq);
bus, subBus, deviceId, irq);
}
} }
/* /*
...@@ -270,21 +190,19 @@ static void iSeries_disable_IRQ(unsigned int irq) ...@@ -270,21 +190,19 @@ static void iSeries_disable_IRQ(unsigned int irq)
*/ */
static void iSeries_enable_IRQ(unsigned int irq) static void iSeries_enable_IRQ(unsigned int irq)
{ {
struct iSeries_irqEntry *entry; u32 bus, deviceId, function, mask;
u32 bus, subBus, deviceId, mask; const u32 subBus = 0;
/* The IRQ has already been locked by the caller */ /* The IRQ has already been locked by the caller */
for (entry = iSeries_irqMap[irq].head; entry; entry = entry->next) { bus = IRQ_TO_BUS(irq);
bus = (entry->dsa >> 16) & 0xFFFF; function = IRQ_TO_FUNC(irq);
subBus = (entry->dsa >> 8) & 0xFF; deviceId = (IRQ_TO_IDSEL(irq) << 4) + function;
deviceId = entry->dsa & 0xFF;
/* Unmask secondary INTA */ /* Unmask secondary INTA */
mask = 0x80000000; mask = 0x80000000;
HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask); HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
PPCDBG(PPCDBG_BUSWALK, PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
"iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n", bus, subBus, deviceId, irq);
bus, subBus, deviceId, irq);
}
} }
/* /*
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#include <asm/ppcdebug.h> #include <asm/ppcdebug.h>
#include <asm/naca.h> #include <asm/naca.h>
#include <asm/flight_recorder.h>
#include <asm/pci_dma.h> #include <asm/pci_dma.h>
#include <asm/iSeries/HvCallPci.h> #include <asm/iSeries/HvCallPci.h>
...@@ -50,16 +49,10 @@ ...@@ -50,16 +49,10 @@
#include "iSeries_IoMmTable.h" #include "iSeries_IoMmTable.h"
#include "pci.h" #include "pci.h"
extern struct pci_controller *hose_head;
extern struct pci_controller **hose_tail;
extern int global_phb_number;
extern int panic_timeout; extern int panic_timeout;
extern struct device_node *allnodes;
extern unsigned long iSeries_Base_Io_Memory; extern unsigned long iSeries_Base_Io_Memory;
extern struct pci_ops iSeries_pci_ops;
extern struct flightRecorder *PciFr;
extern struct TceTable *tceTables[256]; extern struct TceTable *tceTables[256];
extern void iSeries_MmIoTest(void); extern void iSeries_MmIoTest(void);
...@@ -67,8 +60,7 @@ extern void iSeries_MmIoTest(void); ...@@ -67,8 +60,7 @@ extern void iSeries_MmIoTest(void);
/* /*
* Forward declares of prototypes. * Forward declares of prototypes.
*/ */
static struct iSeries_Device_Node *find_Device_Node(struct pci_dev *PciDev); static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn);
unsigned long find_and_init_phbs(void);
static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb); static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb);
static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus,
int IdSel); int IdSel);
...@@ -90,7 +82,8 @@ static long Pci_Error_Count; ...@@ -90,7 +82,8 @@ static long Pci_Error_Count;
static int Pci_Retry_Max = 3; /* Only retry 3 times */ static int Pci_Retry_Max = 3; /* Only retry 3 times */
static int Pci_Error_Flag = 1; /* Set Retry Error on. */ static int Pci_Error_Flag = 1; /* Set Retry Error on. */
static int Pci_Trace_Flag;
static struct pci_ops iSeries_pci_ops;
/* /*
* Log Error infor in Flight Recorder to system Console. * Log Error infor in Flight Recorder to system Console.
...@@ -102,14 +95,11 @@ static int Pci_Trace_Flag; ...@@ -102,14 +95,11 @@ static int Pci_Trace_Flag;
static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, static void pci_Log_Error(char *Error_Text, int Bus, int SubBus,
int AgentId, int HvRc) int AgentId, int HvRc)
{ {
if (HvRc != 0x0302) { if (HvRc == 0x0302)
char ErrorString[128]; return;
sprintf(ErrorString, "%s Failed: 0x%02X.%02X.%02X Rc: 0x%04X", printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X",
Error_Text, Bus, SubBus, AgentId, HvRc); Error_Text, Bus, SubBus, AgentId, HvRc);
PCIFR(ErrorString);
printk("PCI: %s\n", ErrorString);
}
} }
#if 0 #if 0
...@@ -159,95 +149,68 @@ static void list_device_nodes(void) ...@@ -159,95 +149,68 @@ static void list_device_nodes(void)
static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus, static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus,
HvSubBusNumber SubBus, int AgentId, int Function) HvSubBusNumber SubBus, int AgentId, int Function)
{ {
struct iSeries_Device_Node *DeviceNode; struct iSeries_Device_Node *node;
PPCDBG(PPCDBG_BUSWALK, PPCDBG(PPCDBG_BUSWALK,
"-build_device_node 0x%02X.%02X.%02X Function: %02X\n", "-build_device_node 0x%02X.%02X.%02X Function: %02X\n",
Bus, SubBus, AgentId, Function); Bus, SubBus, AgentId, Function);
DeviceNode = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL); node = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL);
if (DeviceNode == NULL) if (node == NULL)
return NULL;
memset(DeviceNode, 0, sizeof(struct iSeries_Device_Node));
list_add_tail(&DeviceNode->Device_List, &iSeries_Global_Device_List);
/* DeviceNode->DsaAddr =
((u64)Bus << 48) + ((u64)SubBus << 40) + ((u64)0x10 << 32); */
ISERIES_BUS(DeviceNode) = Bus;
ISERIES_SUBBUS(DeviceNode) = SubBus;
DeviceNode->DsaAddr.deviceId = 0x10;
DeviceNode->DsaAddr.barNumber = 0;
DeviceNode->AgentId = AgentId;
DeviceNode->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
DeviceNode->IoRetry = 0;
iSeries_Get_Location_Code(DeviceNode);
PCIFR("Device 0x%02X.%2X, Node:0x%p ", ISERIES_BUS(DeviceNode),
ISERIES_DEVFUN(DeviceNode), DeviceNode);
return DeviceNode;
}
/*
* Allocate pci_controller(phb) initialized common variables.
*/
static struct pci_controller *pci_alloc_pci_controllerX(char *model,
enum phb_types controller_type)
{
struct pci_controller *hose;
hose = (struct pci_controller *)kmalloc(sizeof(struct pci_controller),
GFP_KERNEL);
if (hose == NULL)
return NULL; return NULL;
memset(hose, 0, sizeof(struct pci_controller)); memset(node, 0, sizeof(struct iSeries_Device_Node));
if (strlen(model) < 8) list_add_tail(&node->Device_List, &iSeries_Global_Device_List);
strcpy(hose->what, model); #if 0
else node->DsaAddr = ((u64)Bus << 48) + ((u64)SubBus << 40) + ((u64)0x10 << 32);
memcpy(hose->what, model, 7); #endif
hose->type = controller_type; node->DsaAddr.DsaAddr = 0;
hose->global_number = global_phb_number; node->DsaAddr.Dsa.busNumber = Bus;
global_phb_number++; node->DsaAddr.Dsa.subBusNumber = SubBus;
node->DsaAddr.Dsa.deviceId = 0x10;
*hose_tail = hose; node->AgentId = AgentId;
hose_tail = &hose->next; node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
return hose; node->IoRetry = 0;
iSeries_Get_Location_Code(node);
PCIFR("Device 0x%02X.%2X, Node:0x%p ", ISERIES_BUS(node),
ISERIES_DEVFUN(node), node);
return node;
} }
/* /*
* unsigned int __init find_and_init_phbs(void) * unsigned long __init find_and_init_phbs(void)
* *
* Description: * Description:
* This function checks for all possible system PCI host bridges that connect * This function checks for all possible system PCI host bridges that connect
* PCI buses. The system hypervisor is queried as to the guest partition * PCI buses. The system hypervisor is queried as to the guest partition
* ownership status. A pci_controller is build for any bus which is partially * ownership status. A pci_controller is built for any bus which is partially
* owned or fully owned by this guest partition. * owned or fully owned by this guest partition.
*/ */
unsigned long __init find_and_init_phbs(void) unsigned long __init find_and_init_phbs(void)
{ {
struct pci_controller *phb; struct pci_controller *phb;
HvBusNumber BusNumber; HvBusNumber bus;
PPCDBG(PPCDBG_BUSWALK, "find_and_init_phbs Entry\n"); PPCDBG(PPCDBG_BUSWALK, "find_and_init_phbs Entry\n");
/* Check all possible buses. */ /* Check all possible buses. */
for (BusNumber = 0; BusNumber < 256; BusNumber++) { for (bus = 0; bus < 256; bus++) {
int RtnCode = HvCallXm_testBus(BusNumber); int ret = HvCallXm_testBus(bus);
if (RtnCode == 0) { if (ret == 0) {
phb = pci_alloc_pci_controllerX("PHB HV", printk("bus %d appears to exist\n", bus);
phb_type_hypervisor); phb = pci_alloc_pci_controller(phb_type_hypervisor);
if (phb == NULL) { if (phb == NULL) {
printk("PCI: Allocate pci_controller failed.\n");
PCIFR("Allocate pci_controller failed."); PCIFR("Allocate pci_controller failed.");
return -1; return -1;
} }
phb->pci_mem_offset = phb->local_number = BusNumber; phb->pci_mem_offset = phb->local_number = bus;
phb->first_busno = BusNumber; phb->first_busno = bus;
phb->last_busno = BusNumber; phb->last_busno = bus;
phb->ops = &iSeries_pci_ops; phb->ops = &iSeries_pci_ops;
PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n", PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n",
phb, BusNumber); phb, bus);
PCIFR("Create iSeries PHB controller: %04X", BusNumber); PCIFR("Create iSeries PHB controller: %04X", bus);
/* Find and connect the devices. */ /* Find and connect the devices. */
iSeries_Scan_PHBs_Slots(phb); iSeries_Scan_PHBs_Slots(phb);
...@@ -256,9 +219,9 @@ unsigned long __init find_and_init_phbs(void) ...@@ -256,9 +219,9 @@ unsigned long __init find_and_init_phbs(void)
* Check for Unexpected Return code, a clue that something * Check for Unexpected Return code, a clue that something
* has gone wrong. * has gone wrong.
*/ */
else if (RtnCode != 0x0301) else if (ret != 0x0301)
PCIFR("Unexpected Return on Probe(0x%04X): 0x%04X", printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X",
BusNumber, RtnCode); bus, ret);
} }
return 0; return 0;
} }
...@@ -267,17 +230,6 @@ unsigned long __init find_and_init_phbs(void) ...@@ -267,17 +230,6 @@ unsigned long __init find_and_init_phbs(void)
* iSeries_pcibios_init * iSeries_pcibios_init
* *
* Chance to initialize and structures or variable before PCI Bus walk. * Chance to initialize and structures or variable before PCI Bus walk.
*
* <4>buswalk [swapper : iSeries_pcibios_init Entry.
* <4>buswalk [swapper : IoMmTable Initialized 0xC00000000034BD30
* <4>buswalk [swapper : find_and_init_phbs Entry
* <4>buswalk [swapper : Create iSeries pci_controller:(0xC00000001F5C7000), Bus 0x0017
* <4>buswalk [swapper : Connect EADs: 0x17.00.12 = 0x00
* <4>buswalk [swapper : iSeries_assign_IRQ 0x0017.00.12 = 0x0091
* <4>buswalk [swapper : - allocate and assign IRQ 0x17.00.12 = 0x91
* <4>buswalk [swapper : - FoundDevice: 0x17.28.10 = 0x12AE
* <4>buswalk [swapper : - build_device_node 0x17.28.12
* <4>buswalk [swapper : iSeries_pcibios_init Exit.
*/ */
void iSeries_pcibios_init(void) void iSeries_pcibios_init(void)
{ {
...@@ -293,8 +245,8 @@ void iSeries_pcibios_init(void) ...@@ -293,8 +245,8 @@ void iSeries_pcibios_init(void)
*/ */
void __init pcibios_final_fixup(void) void __init pcibios_final_fixup(void)
{ {
struct pci_dev *PciDev = NULL; struct pci_dev *pdev = NULL;
struct iSeries_Device_Node *DeviceNode; struct iSeries_Device_Node *node;
char Buffer[256]; char Buffer[256];
int DeviceCount = 0; int DeviceCount = 0;
...@@ -303,24 +255,28 @@ void __init pcibios_final_fixup(void) ...@@ -303,24 +255,28 @@ void __init pcibios_final_fixup(void)
/* Fix up at the device node and pci_dev relationship */ /* Fix up at the device node and pci_dev relationship */
mf_displaySrc(0xC9000100); mf_displaySrc(0xC9000100);
while ((PciDev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, PciDev)) printk("pcibios_final_fixup\n");
while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))
!= NULL) { != NULL) {
DeviceNode = find_Device_Node(PciDev); node = find_Device_Node(pdev->bus->number, pdev->devfn);
if (DeviceNode != NULL) { printk("pci dev %p (%x.%x), node %p\n", pdev,
pdev->bus->number, pdev->devfn, node);
if (node != NULL) {
++DeviceCount; ++DeviceCount;
PciDev->sysdata = (void *)DeviceNode; pdev->sysdata = (void *)node;
DeviceNode->PciDev = PciDev; node->PciDev = pdev;
PPCDBG(PPCDBG_BUSWALK, PPCDBG(PPCDBG_BUSWALK,
"PciDev 0x%p <==> DevNode 0x%p\n", "pdev 0x%p <==> DevNode 0x%p\n",
PciDev, DeviceNode); pdev, node);
iSeries_allocateDeviceBars(PciDev); iSeries_allocateDeviceBars(pdev);
iSeries_Device_Information(PciDev, Buffer, iSeries_Device_Information(pdev, Buffer,
sizeof(Buffer)); sizeof(Buffer));
printk("%d. %s\n", DeviceCount, Buffer); printk("%d. %s\n", DeviceCount, Buffer);
create_pci_bus_tce_table((unsigned long)DeviceNode); create_pci_bus_tce_table((unsigned long)node);
} else } else
printk("PCI: Device Tree not found for 0x%016lX\n", printk("PCI: Device Tree not found for 0x%016lX\n",
(unsigned long)PciDev); (unsigned long)pdev);
} }
iSeries_IoMmTable_Status(); iSeries_IoMmTable_Status();
iSeries_activate_IRQs(); iSeries_activate_IRQs();
...@@ -333,9 +289,9 @@ void pcibios_fixup_bus(struct pci_bus *PciBus) ...@@ -333,9 +289,9 @@ void pcibios_fixup_bus(struct pci_bus *PciBus)
PciBus->number); PciBus->number);
} }
void pcibios_fixup_resources(struct pci_dev *PciDev) void pcibios_fixup_resources(struct pci_dev *pdev)
{ {
PPCDBG(PPCDBG_BUSWALK, "fixup_resources PciDev %p\n", PciDev); PPCDBG(PPCDBG_BUSWALK, "fixup_resources pdev %p\n", pdev);
} }
/* /*
...@@ -344,11 +300,11 @@ void pcibios_fixup_resources(struct pci_dev *PciDev) ...@@ -344,11 +300,11 @@ void pcibios_fixup_resources(struct pci_dev *PciDev)
static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb) static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb)
{ {
struct HvCallPci_DeviceInfo *DevInfo; struct HvCallPci_DeviceInfo *DevInfo;
HvBusNumber Bus = Phb->local_number; /* System Bus */ HvBusNumber bus = Phb->local_number; /* System Bus */
HvSubBusNumber SubBus = 0; /* EADs is always 0. */ const HvSubBusNumber SubBus = 0; /* EADs is always 0. */
int HvRc = 0; int HvRc = 0;
int IdSel = 1; int IdSel;
int MaxAgents = 8; const int MaxAgents = 8;
DevInfo = (struct HvCallPci_DeviceInfo*) DevInfo = (struct HvCallPci_DeviceInfo*)
kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
...@@ -358,24 +314,25 @@ static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb) ...@@ -358,24 +314,25 @@ static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb)
/* /*
* Probe for EADs Bridges * Probe for EADs Bridges
*/ */
for (IdSel=1; IdSel < MaxAgents; ++IdSel) { for (IdSel = 1; IdSel < MaxAgents; ++IdSel) {
HvRc = HvCallPci_getDeviceInfo(Bus, SubBus, IdSel, HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel,
REALADDR(DevInfo), REALADDR(DevInfo),
sizeof(struct HvCallPci_DeviceInfo)); sizeof(struct HvCallPci_DeviceInfo));
if (HvRc == 0) { if (HvRc == 0) {
if (DevInfo->deviceType == HvCallPci_NodeDevice) if (DevInfo->deviceType == HvCallPci_NodeDevice)
iSeries_Scan_EADs_Bridge(Bus, SubBus, IdSel); iSeries_Scan_EADs_Bridge(bus, SubBus, IdSel);
else else
printk("PCI: Invalid System Configuration(0x%02X.\n", printk("PCI: Invalid System Configuration(0x%02X)"
DevInfo->deviceType); " for bus 0x%02x id 0x%02x.\n",
DevInfo->deviceType, bus, IdSel);
} }
else else
pci_Log_Error("getDeviceInfo",Bus, SubBus, IdSel,HvRc); pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc);
} }
kfree(DevInfo); kfree(DevInfo);
} }
static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, static void iSeries_Scan_EADs_Bridge(HvBusNumber bus, HvSubBusNumber SubBus,
int IdSel) int IdSel)
{ {
struct HvCallPci_BridgeInfo *BridgeInfo; struct HvCallPci_BridgeInfo *BridgeInfo;
...@@ -391,26 +348,26 @@ static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, ...@@ -391,26 +348,26 @@ static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus,
/* Note: hvSubBus and irq is always be 0 at this level! */ /* Note: hvSubBus and irq is always be 0 at this level! */
for (Function = 0; Function < 8; ++Function) { for (Function = 0; Function < 8; ++Function) {
AgentId = ISERIES_PCI_AGENTID(IdSel, Function); AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, 0); HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0);
if (HvRc == 0) { if (HvRc == 0) {
printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
bus, IdSel, Function, AgentId);
/* Connect EADs: 0x18.00.12 = 0x00 */ /* Connect EADs: 0x18.00.12 = 0x00 */
PPCDBG(PPCDBG_BUSWALK, PPCDBG(PPCDBG_BUSWALK,
"PCI:Connect EADs: 0x%02X.%02X.%02X\n", "PCI:Connect EADs: 0x%02X.%02X.%02X\n",
Bus, SubBus, AgentId); bus, SubBus, AgentId);
PCIFR("Connect EADs: 0x%02X.%02X.%02X", HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId,
Bus, SubBus, AgentId);
HvRc = HvCallPci_getBusUnitInfo(Bus, SubBus, AgentId,
REALADDR(BridgeInfo), REALADDR(BridgeInfo),
sizeof(struct HvCallPci_BridgeInfo)); sizeof(struct HvCallPci_BridgeInfo));
if (HvRc == 0) { if (HvRc == 0) {
PPCDBG(PPCDBG_BUSWALK, printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n",
"PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n",
BridgeInfo->busUnitInfo.deviceType, BridgeInfo->busUnitInfo.deviceType,
BridgeInfo->subBusNumber, BridgeInfo->subBusNumber,
BridgeInfo->maxAgents, BridgeInfo->maxAgents,
BridgeInfo->maxSubBusNumber, BridgeInfo->maxSubBusNumber,
BridgeInfo->logicalSlotNumber); BridgeInfo->logicalSlotNumber);
PCIFR("BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X", PPCDBG(PPCDBG_BUSWALK,
"PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n",
BridgeInfo->busUnitInfo.deviceType, BridgeInfo->busUnitInfo.deviceType,
BridgeInfo->subBusNumber, BridgeInfo->subBusNumber,
BridgeInfo->maxAgents, BridgeInfo->maxAgents,
...@@ -420,16 +377,14 @@ static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, ...@@ -420,16 +377,14 @@ static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus,
if (BridgeInfo->busUnitInfo.deviceType == if (BridgeInfo->busUnitInfo.deviceType ==
HvCallPci_BridgeDevice) { HvCallPci_BridgeDevice) {
/* Scan_Bridge_Slot...: 0x18.00.12 */ /* Scan_Bridge_Slot...: 0x18.00.12 */
iSeries_Scan_Bridge_Slot(Bus, iSeries_Scan_Bridge_Slot(bus, BridgeInfo);
BridgeInfo);
} else } else
printk("PCI: Invalid Bridge Configuration(0x%02X)", printk("PCI: Invalid Bridge Configuration(0x%02X)",
BridgeInfo->busUnitInfo.deviceType); BridgeInfo->busUnitInfo.deviceType);
} }
} } else if (HvRc != 0x000B)
else if (HvRc != 0x000B)
pci_Log_Error("EADs Connect", pci_Log_Error("EADs Connect",
Bus, SubBus, AgentId, HvRc); bus, SubBus, AgentId, HvRc);
} }
kfree(BridgeInfo); kfree(BridgeInfo);
} }
...@@ -440,20 +395,18 @@ static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, ...@@ -440,20 +395,18 @@ static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus,
static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus,
struct HvCallPci_BridgeInfo *BridgeInfo) struct HvCallPci_BridgeInfo *BridgeInfo)
{ {
struct iSeries_Device_Node *DeviceNode; struct iSeries_Device_Node *node;
HvSubBusNumber SubBus = BridgeInfo->subBusNumber; HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
u16 VendorId = 0; u16 VendorId = 0;
int HvRc = 0; int HvRc = 0;
u8 Irq = 0; u8 Irq = 0;
int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus); int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus); int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function); HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function);
int FirstSlotId = 0;
/* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */
Irq = iSeries_allocate_IRQ(Bus, 0, AgentId); Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel);
iSeries_assign_IRQ(Irq, Bus, 0, AgentId); iSeries_assign_IRQ(Irq, Bus, 0, EADsIdSel);
PPCDBG(PPCDBG_BUSWALK, PPCDBG(PPCDBG_BUSWALK,
"PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n", "PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n",
Bus, 0, AgentId, Irq); Bus, 0, AgentId, Irq);
...@@ -463,53 +416,42 @@ static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, ...@@ -463,53 +416,42 @@ static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus,
*/ */
for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) { for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
for (Function = 0; Function < 8; ++Function) { for (Function = 0; Function < 8; ++Function) {
AgentId = ISERIES_PCI_AGENTID(IdSel, Function); HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
HvRc = HvCallXm_connectBusUnit(Bus, SubBus, HvRc = HvCallXm_connectBusUnit(Bus, SubBus,
AgentId, Irq); AgentId, Irq);
if (HvRc == 0) { if (HvRc != 0) {
HvRc = HvCallPci_configLoad16(Bus, SubBus,
AgentId, PCI_VENDOR_ID,
&VendorId);
if (HvRc == 0) {
/* FoundDevice: 0x18.28.10 = 0x12AE */
PPCDBG(PPCDBG_BUSWALK,
"PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X\n",
Bus, SubBus, AgentId, VendorId);
HvRc = HvCallPci_configStore8(Bus,
SubBus, AgentId,
PCI_INTERRUPT_LINE, Irq);
if (HvRc != 0)
pci_Log_Error("PciCfgStore Irq Failed!",
Bus, SubBus,
AgentId, HvRc);
++DeviceCount;
DeviceNode = build_device_node(Bus,
SubBus, EADsIdSel,
Function);
DeviceNode->Vendor = VendorId;
DeviceNode->Irq = Irq;
DeviceNode->LogicalSlot =
BridgeInfo->logicalSlotNumber;
PCIFR("Device(%4d): 0x%02X.%02X.%02X 0x%02X 0x%04X",
DeviceCount, Bus, SubBus,
AgentId,
DeviceNode->LogicalSlot,DeviceNode->Vendor);
/*
* On the first device/function,
* assign irq to slot
*/
if (Function == 0) {
FirstSlotId = AgentId;
/* AHT iSeries_assign_IRQ(Irq,
Bus, SubBus, AgentId); */
}
} else
pci_Log_Error("Read Vendor",
Bus, SubBus, AgentId, HvRc);
} else
pci_Log_Error("Connect Bus Unit", pci_Log_Error("Connect Bus Unit",
Bus, SubBus, AgentId, HvRc); Bus, SubBus, AgentId, HvRc);
continue;
}
printk("connected bus unit at bus %d subbus 0x%x agentid 0x%x (idsel=%d func=%d)\n",
Bus, SubBus, AgentId, IdSel, Function);
HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId,
PCI_VENDOR_ID, &VendorId);
if (HvRc != 0) {
pci_Log_Error("Read Vendor",
Bus, SubBus, AgentId, HvRc);
continue;
}
printk("read vendor ID: %x\n", VendorId);
/* FoundDevice: 0x18.28.10 = 0x12AE */
PPCDBG(PPCDBG_BUSWALK,
"PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X\n",
Bus, SubBus, AgentId, VendorId);
HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId,
PCI_INTERRUPT_LINE, Irq);
if (HvRc != 0)
pci_Log_Error("PciCfgStore Irq Failed!",
Bus, SubBus, AgentId, HvRc);
++DeviceCount;
node = build_device_node(Bus, SubBus, EADsIdSel, Function);
node->Vendor = VendorId;
node->Irq = Irq;
node->LogicalSlot = BridgeInfo->logicalSlotNumber;
} /* for (Function = 0; Function < 8; ++Function) */ } /* for (Function = 0; Function < 8; ++Function) */
} /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */ } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */
return HvRc; return HvRc;
...@@ -562,19 +504,16 @@ void *iSeries_memcpy_fromio(void *dest, void *source, size_t count) ...@@ -562,19 +504,16 @@ void *iSeries_memcpy_fromio(void *dest, void *source, size_t count)
/* /*
* Look down the chain to find the matching Device Device * Look down the chain to find the matching Device Device
*/ */
static struct iSeries_Device_Node *find_Device_Node(struct pci_dev *PciDev) static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn)
{ {
struct list_head *Device_Node_Ptr = iSeries_Global_Device_List.next; struct list_head *pos;
int Bus = PciDev->bus->number;
int DevFn = PciDev->devfn;
while (Device_Node_Ptr != &iSeries_Global_Device_List) { list_for_each(pos, &iSeries_Global_Device_List) {
struct iSeries_Device_Node *DevNode = struct iSeries_Device_Node *node =
(struct iSeries_Device_Node*)Device_Node_Ptr; list_entry(pos, struct iSeries_Device_Node, Device_List);
if ((Bus == ISERIES_BUS(DevNode)) && (DevFn == DevNode->DevFn)) if ((bus == ISERIES_BUS(node)) && (devfn == node->DevFn))
return DevNode; return node;
Device_Node_Ptr = Device_Node_Ptr->next;
} }
return NULL; return NULL;
} }
...@@ -585,90 +524,82 @@ static struct iSeries_Device_Node *find_Device_Node(struct pci_dev *PciDev) ...@@ -585,90 +524,82 @@ static struct iSeries_Device_Node *find_Device_Node(struct pci_dev *PciDev)
* Sanity Check Node PciDev to passed pci_dev * Sanity Check Node PciDev to passed pci_dev
* If none is found, returns a NULL which the client must handle. * If none is found, returns a NULL which the client must handle.
*/ */
static struct iSeries_Device_Node *get_Device_Node(struct pci_dev *PciDev) static struct iSeries_Device_Node *get_Device_Node(struct pci_dev *pdev)
{ {
struct iSeries_Device_Node *Node; struct iSeries_Device_Node *node;
Node = (struct iSeries_Device_Node *)PciDev->sysdata; node = pdev->sysdata;
if (Node == NULL) if (node == NULL || node->PciDev != pdev)
Node = find_Device_Node(PciDev); node = find_Device_Node(pdev->bus->number, pdev->devfn);
else if (Node->PciDev != PciDev) return node;
Node = find_Device_Node(PciDev);
return Node;
} }
#endif #endif
/* /*
* Read PCI Config Space Code * Config space read and write functions.
* For now at least, we look for the device node for the bus and devfn
* that we are asked to access. It may be possible to translate the devfn
* to a subbus and deviceid more directly.
*/ */
#if 0 static u64 hv_cfg_read_func[4] = {
/** BYTE ********************************************************************/ HvCallPciConfigLoad8, HvCallPciConfigLoad16,
int iSeries_Node_read_config_byte(struct iSeries_Device_Node* DevNode, int Offset, u8* ReadValue) HvCallPciConfigLoad32, HvCallPciConfigLoad32
{ };
u8 ReadData;
if(DevNode == NULL) { return 0x301; }
++Pci_Cfg_Read_Count;
DevNode->ReturnCode = HvCallPci_configLoad8(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10,
Offset,&ReadData);
if(Pci_Trace_Flag == 1) {
PCIFR("RCB: 0x%04X.%02X 0x%04X = 0x%02X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,ReadData);
}
if(DevNode->ReturnCode != 0 ) {
printk("PCI: RCB: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
PCIFR( "RCB: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
}
*ReadValue = ReadData;
return DevNode->ReturnCode;
}
int iSeries_pci_read_config_byte(struct pci_dev* PciDev, int Offset, u8* ReadValue) { static u64 hv_cfg_write_func[4] = {
struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); HvCallPciConfigStore8, HvCallPciConfigStore16,
if(DevNode == NULL) return 0x0301; HvCallPciConfigStore32, HvCallPciConfigStore32
return iSeries_Node_read_config_byte( DevNode ,Offset,ReadValue); };
}
#endif
/*
* Read PCI config space
*/
static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn, static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn,
int offset, int size, u32 *val) int offset, int size, u32 *val)
{ {
return PCIBIOS_DEVICE_NOT_FOUND; struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn);
} u64 fn;
struct HvCallPci_LoadReturn ret;
/* if (node == NULL)
* Write PCI Config Space return PCIBIOS_DEVICE_NOT_FOUND;
*/
#if 0 fn = hv_cfg_read_func[(size - 1) & 3];
/** BYTE ********************************************************************/ HvCall3Ret16(fn, &ret, node->DsaAddr.DsaAddr, offset, 0);
int iSeries_Node_write_config_byte(struct iSeries_Device_Node* DevNode, int Offset, u8 WriteData)
{ if (ret.rc != 0) {
++Pci_Cfg_Write_Count; *val = ~0;
DevNode->ReturnCode = HvCallPci_configStore8(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, return PCIBIOS_DEVICE_NOT_FOUND; /* or something */
Offset,WriteData);
if(Pci_Trace_Flag == 1) {
PCIFR("WCB: 0x%04X.%02X 0x%04X = 0x%02X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,WriteData);
}
if(DevNode->ReturnCode != 0 ) {
printk("PCI: WCB: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
PCIFR( "WCB: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode);
} }
return DevNode->ReturnCode;
}
int iSeries_pci_write_config_byte( struct pci_dev* PciDev,int Offset, u8 WriteValue) *val = ret.value;
{ return 0;
struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev);
if(DevNode == NULL) return 0x0301;
return iSeries_Node_write_config_byte( DevNode,Offset,WriteValue);
} }
#endif
/*
* Write PCI config space
*/
static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn, static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn,
int offset, int size, u32 val) int offset, int size, u32 val)
{ {
return PCIBIOS_DEVICE_NOT_FOUND; struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn);
u64 fn;
u64 ret;
if (node == NULL)
return PCIBIOS_DEVICE_NOT_FOUND;
fn = hv_cfg_write_func[(size - 1) & 3];
ret = HvCall4(fn, node->DsaAddr.DsaAddr, offset, val, 0);
if (ret != 0)
return PCIBIOS_DEVICE_NOT_FOUND;
return 0;
} }
struct pci_ops iSeries_pci_ops = { static struct pci_ops iSeries_pci_ops = {
.read = iSeries_pci_read_config, .read = iSeries_pci_read_config,
.write = iSeries_pci_write_config .write = iSeries_pci_write_config
}; };
...@@ -683,18 +614,15 @@ struct pci_ops iSeries_pci_ops = { ...@@ -683,18 +614,15 @@ struct pci_ops iSeries_pci_ops = {
* PCI: Device 23.90 ReadL Retry( 1) * PCI: Device 23.90 ReadL Retry( 1)
* PCI: Device 23.90 ReadL Retry Successful(1) * PCI: Device 23.90 ReadL Retry Successful(1)
*/ */
int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode,
u64 RtnCode) u64 ret)
{ {
if (RtnCode != 0) { if (ret != 0) {
++Pci_Error_Count; ++Pci_Error_Count;
++DevNode->IoRetry; ++DevNode->IoRetry;
PCIFR("%s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X",
TextHdr, ISERIES_BUS(DevNode), DevNode->DevFn,
DevNode->IoRetry, (int)RtnCode);
printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n",
TextHdr, ISERIES_BUS(DevNode), DevNode->DevFn, TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn,
DevNode->IoRetry, (int)RtnCode); DevNode->IoRetry, (int)ret);
/* /*
* Bump the retry and check for retry count exceeded. * Bump the retry and check for retry count exceeded.
* If, Exceeded, panic the system. * If, Exceeded, panic the system.
...@@ -711,7 +639,7 @@ int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, ...@@ -711,7 +639,7 @@ int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode,
/* If retry was in progress, log success and rest retry count */ /* If retry was in progress, log success and rest retry count */
if (DevNode->IoRetry > 0) { if (DevNode->IoRetry > 0) {
PCIFR("%s: Device 0x%04X:%02X Retry Successful(%2d).", PCIFR("%s: Device 0x%04X:%02X Retry Successful(%2d).",
TextHdr, ISERIES_BUS(DevNode), DevNode->DevFn, TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn,
DevNode->IoRetry); DevNode->IoRetry);
DevNode->IoRetry = 0; DevNode->IoRetry = 0;
} }
...@@ -724,16 +652,16 @@ int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, ...@@ -724,16 +652,16 @@ int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode,
* the exposure of being device global. * the exposure of being device global.
*/ */
static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress, static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress,
union HvDsaMap *DsaPtr, u64 *BarOffsetPtr) u64 *dsaptr, u64 *BarOffsetPtr)
{ {
unsigned long BaseIoAddr = unsigned long BaseIoAddr =
(unsigned long)IoAddress - iSeries_Base_Io_Memory; (unsigned long)IoAddress - iSeries_Base_Io_Memory;
long TableIndex = BaseIoAddr / iSeries_IoMmTable_Entry_Size; long TableIndex = BaseIoAddr / iSeries_IoMmTable_Entry_Size;
struct iSeries_Device_Node *DevNode = *(iSeries_IoMmTable + TableIndex); struct iSeries_Device_Node *DevNode = iSeries_IoMmTable[TableIndex];
if (DevNode != NULL) { if (DevNode != NULL) {
DsaPtr->DsaAddr = ISERIES_DSA(DevNode); int barnum = iSeries_IoBarTable[TableIndex];
DsaPtr->Dsa.barNumber = *(iSeries_IoBarTable + TableIndex); *dsaptr = DevNode->DsaAddr.DsaAddr | (barnum << 24);
*BarOffsetPtr = BaseIoAddr % iSeries_IoMmTable_Entry_Size; *BarOffsetPtr = BaseIoAddr % iSeries_IoMmTable_Entry_Size;
} else } else
panic("PCI: Invalid PCI IoAddress detected!\n"); panic("PCI: Invalid PCI IoAddress detected!\n");
...@@ -752,61 +680,51 @@ static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress, ...@@ -752,61 +680,51 @@ static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress,
u8 iSeries_Read_Byte(void *IoAddress) u8 iSeries_Read_Byte(void *IoAddress)
{ {
u64 BarOffset; u64 BarOffset;
union HvDsaMap DsaData; u64 dsa;
struct HvCallPci_LoadReturn Return; struct HvCallPci_LoadReturn ret;
struct iSeries_Device_Node *DevNode = struct iSeries_Device_Node *DevNode =
xlateIoMmAddress(IoAddress, &DsaData, &BarOffset); xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
do { do {
++Pci_Io_Read_Count; ++Pci_Io_Read_Count;
HvCall3Ret16(HvCallPciBarLoad8, &Return, DsaData.DsaAddr, HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
BarOffset, 0); } while (CheckReturnCode("RDB", DevNode, ret.rc) != 0);
} while (CheckReturnCode("RDB", DevNode, Return.rc) != 0);
if (Pci_Trace_Flag == 1) return (u8)ret.value;
PCIFR("RDB: IoAddress 0x%p = 0x%02X", IoAddress,
(u8)Return.value);
return (u8)Return.value;
} }
u16 iSeries_Read_Word(void *IoAddress) u16 iSeries_Read_Word(void *IoAddress)
{ {
u64 BarOffset; u64 BarOffset;
union HvDsaMap DsaData; u64 dsa;
struct HvCallPci_LoadReturn Return; struct HvCallPci_LoadReturn ret;
struct iSeries_Device_Node *DevNode = struct iSeries_Device_Node *DevNode =
xlateIoMmAddress(IoAddress, &DsaData, &BarOffset); xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
do { do {
++Pci_Io_Read_Count; ++Pci_Io_Read_Count;
HvCall3Ret16(HvCallPciBarLoad16, &Return, DsaData.DsaAddr, HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
BarOffset, 0); BarOffset, 0);
} while (CheckReturnCode("RDW", DevNode, Return.rc) != 0); } while (CheckReturnCode("RDW", DevNode, ret.rc) != 0);
if (Pci_Trace_Flag == 1) return swab16((u16)ret.value);
PCIFR("RDW: IoAddress 0x%p = 0x%04X", IoAddress,
swab16((u16)Return.value));
return swab16((u16)Return.value);
} }
u32 iSeries_Read_Long(void *IoAddress) u32 iSeries_Read_Long(void *IoAddress)
{ {
u64 BarOffset; u64 BarOffset;
union HvDsaMap DsaData; u64 dsa;
struct HvCallPci_LoadReturn Return; struct HvCallPci_LoadReturn ret;
struct iSeries_Device_Node *DevNode = struct iSeries_Device_Node *DevNode =
xlateIoMmAddress(IoAddress, &DsaData, &BarOffset); xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
do { do {
++Pci_Io_Read_Count; ++Pci_Io_Read_Count;
HvCall3Ret16(HvCallPciBarLoad32, &Return, DsaData.DsaAddr, HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
BarOffset, 0); BarOffset, 0);
} while (CheckReturnCode("RDL", DevNode, Return.rc) != 0); } while (CheckReturnCode("RDL", DevNode, ret.rc) != 0);
if (Pci_Trace_Flag == 1) return swab32((u32)ret.value);
PCIFR("RDL: IoAddress 0x%p = 0x%04X", IoAddress,
swab32((u32)Return.value));
return swab32((u32)Return.value);
} }
/* /*
...@@ -816,55 +734,46 @@ u32 iSeries_Read_Long(void *IoAddress) ...@@ -816,55 +734,46 @@ u32 iSeries_Read_Long(void *IoAddress)
* iSeries_Write_Word = Write Word(16 bit) * iSeries_Write_Word = Write Word(16 bit)
* iSeries_Write_Long = Write Long(32 bit) * iSeries_Write_Long = Write Long(32 bit)
*/ */
void iSeries_Write_Byte(u8 Data, void *IoAddress) void iSeries_Write_Byte(u8 data, void *IoAddress)
{ {
u64 BarOffset; u64 BarOffset;
union HvDsaMap DsaData; u64 dsa;
struct HvCallPci_LoadReturn Return; u64 rc;
struct iSeries_Device_Node *DevNode = struct iSeries_Device_Node *DevNode =
xlateIoMmAddress(IoAddress, &DsaData, &BarOffset); xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
do { do {
++Pci_Io_Write_Count; ++Pci_Io_Write_Count;
Return.rc = HvCall4(HvCallPciBarStore8, DsaData.DsaAddr, rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
BarOffset, Data, 0); } while (CheckReturnCode("WWB", DevNode, rc) != 0);
} while (CheckReturnCode("WWB", DevNode, Return.rc) != 0);
if (Pci_Trace_Flag == 1)
PCIFR("WWB: IoAddress 0x%p = 0x%02X", IoAddress, Data);
} }
void iSeries_Write_Word(u16 Data, void *IoAddress) void iSeries_Write_Word(u16 data, void *IoAddress)
{ {
u64 BarOffset; u64 BarOffset;
union HvDsaMap DsaData; u64 dsa;
struct HvCallPci_LoadReturn Return; u64 rc;
struct iSeries_Device_Node *DevNode = struct iSeries_Device_Node *DevNode =
xlateIoMmAddress(IoAddress, &DsaData, &BarOffset); xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
do { do {
++Pci_Io_Write_Count; ++Pci_Io_Write_Count;
Return.rc = HvCall4(HvCallPciBarStore16, DsaData.DsaAddr, rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
BarOffset, swab16(Data), 0); } while (CheckReturnCode("WWW", DevNode, rc) != 0);
} while (CheckReturnCode("WWW", DevNode, Return.rc) != 0);
if (Pci_Trace_Flag == 1)
PCIFR("WWW: IoAddress 0x%p = 0x%04X", IoAddress, Data);
} }
void iSeries_Write_Long(u32 Data, void *IoAddress) void iSeries_Write_Long(u32 data, void *IoAddress)
{ {
u64 BarOffset; u64 BarOffset;
union HvDsaMap DsaData; u64 dsa;
struct HvCallPci_LoadReturn Return; u64 rc;
struct iSeries_Device_Node *DevNode = struct iSeries_Device_Node *DevNode =
xlateIoMmAddress(IoAddress, &DsaData, &BarOffset); xlateIoMmAddress(IoAddress, &dsa, &BarOffset);
do { do {
++Pci_Io_Write_Count; ++Pci_Io_Write_Count;
Return.rc = HvCall4(HvCallPciBarStore32, DsaData.DsaAddr, rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
BarOffset, swab32(Data), 0); } while (CheckReturnCode("WWL", DevNode, rc) != 0);
} while (CheckReturnCode("WWL", DevNode, Return.rc) != 0);
if (Pci_Trace_Flag == 1)
PCIFR("WWL: IoAddress 0x%p = 0x%08X", IoAddress, Data);
} }
void pcibios_name_device(struct pci_dev *dev) void pcibios_name_device(struct pci_dev *dev)
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include <asm/iSeries/HvCallPci.h> #include <asm/iSeries/HvCallPci.h>
#include <asm/iSeries/HvTypes.h> #include <asm/iSeries/HvTypes.h>
#include <asm/iSeries/mf.h> #include <asm/iSeries/mf.h>
#include <asm/flight_recorder.h>
#include <asm/pci.h> #include <asm/pci.h>
#include <asm/iSeries/iSeries_pci.h> #include <asm/iSeries/iSeries_pci.h>
......
...@@ -589,7 +589,9 @@ int do_IRQ(struct pt_regs *regs) ...@@ -589,7 +589,9 @@ int do_IRQ(struct pt_regs *regs)
return 1; /* lets ret_from_int know we can do checks */ return 1; /* lets ret_from_int know we can do checks */
} }
#else /* CONFIG_PPC_ISERIES */ #else /* CONFIG_PPC_ISERIES */
int do_IRQ(struct pt_regs *regs) int do_IRQ(struct pt_regs *regs)
{ {
int irq, first = 1; int irq, first = 1;
......
...@@ -224,7 +224,11 @@ pci_alloc_pci_controller(enum phb_types controller_type) ...@@ -224,7 +224,11 @@ pci_alloc_pci_controller(enum phb_types controller_type)
struct pci_controller *hose; struct pci_controller *hose;
char *model; char *model;
#ifdef CONFIG_PPC_ISERIES
hose = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
#else
hose = (struct pci_controller *)alloc_bootmem(sizeof(struct pci_controller)); hose = (struct pci_controller *)alloc_bootmem(sizeof(struct pci_controller));
#endif
if(hose == NULL) { if(hose == NULL) {
printk(KERN_ERR "PCI: Allocate pci_controller failed.\n"); printk(KERN_ERR "PCI: Allocate pci_controller failed.\n");
return NULL; return NULL;
...@@ -232,6 +236,11 @@ pci_alloc_pci_controller(enum phb_types controller_type) ...@@ -232,6 +236,11 @@ pci_alloc_pci_controller(enum phb_types controller_type)
memset(hose, 0, sizeof(struct pci_controller)); memset(hose, 0, sizeof(struct pci_controller));
switch(controller_type) { switch(controller_type) {
#ifdef CONFIG_PPC_ISERIES
case phb_type_hypervisor:
model = "PHB HV";
break;
#endif
case phb_type_python: case phb_type_python:
model = "PHB PY"; model = "PHB PY";
break; break;
...@@ -311,6 +320,7 @@ static int __init pcibios_init(void) ...@@ -311,6 +320,7 @@ static int __init pcibios_init(void)
hose->last_busno = bus->subordinate; hose->last_busno = bus->subordinate;
} }
#ifndef CONFIG_PPC_ISERIES
if (pci_probe_only) if (pci_probe_only)
pcibios_claim_of_setup(); pcibios_claim_of_setup();
else else
...@@ -318,6 +328,7 @@ static int __init pcibios_init(void) ...@@ -318,6 +328,7 @@ static int __init pcibios_init(void)
pci_assign_unassigned_resources() is able to work pci_assign_unassigned_resources() is able to work
correctly with [partially] allocated PCI tree. */ correctly with [partially] allocated PCI tree. */
pci_assign_unassigned_resources(); pci_assign_unassigned_resources();
#endif
/* Call machine dependent fixup */ /* Call machine dependent fixup */
pcibios_final_fixup(); pcibios_final_fixup();
...@@ -375,9 +386,13 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) ...@@ -375,9 +386,13 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
*/ */
int pci_domain_nr(struct pci_bus *bus) int pci_domain_nr(struct pci_bus *bus)
{ {
#ifdef CONFIG_PPC_ISERIES
return 0;
#else
struct pci_controller *hose = PCI_GET_PHB_PTR(bus); struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
return hose->global_number; return hose->global_number;
#endif
} }
EXPORT_SYMBOL(pci_domain_nr); EXPORT_SYMBOL(pci_domain_nr);
...@@ -385,11 +400,13 @@ EXPORT_SYMBOL(pci_domain_nr); ...@@ -385,11 +400,13 @@ EXPORT_SYMBOL(pci_domain_nr);
/* Set the name of the bus as it appears in /proc/bus/pci */ /* Set the name of the bus as it appears in /proc/bus/pci */
int pci_name_bus(char *name, struct pci_bus *bus) int pci_name_bus(char *name, struct pci_bus *bus)
{ {
#ifndef CONFIG_PPC_ISERIES
struct pci_controller *hose = PCI_GET_PHB_PTR(bus); struct pci_controller *hose = PCI_GET_PHB_PTR(bus);
if (hose->buid) if (hose->buid)
sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number); sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
else else
#endif
sprintf(name, "%02x", bus->number); sprintf(name, "%02x", bus->number);
return 0; return 0;
......
/************************************************************************/ /************************************************************************/
/* Provides the Hypervisor PCI calls for iSeries Linux Parition. */ /* Provides the Hypervisor PCI calls for iSeries Linux Parition. */
/* Copyright (C) 20yy <Wayne G Holm> <IBM Corporation> */ /* Copyright (C) 2001 <Wayne G Holm> <IBM Corporation> */
/* */ /* */
/* This program is free software; you can redistribute it and/or modify */ /* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */ /* it under the terms of the GNU General Public License as published by */
...@@ -21,40 +21,25 @@ ...@@ -21,40 +21,25 @@
/* Change Activity: */ /* Change Activity: */
/* Created, Jan 9, 2001 */ /* Created, Jan 9, 2001 */
/************************************************************************/ /************************************************************************/
//============================================================================
// Header File Id
// Name______________: HvCallPci.H
//
// Description_______:
//
// This file contains the "hypervisor call" interface which is used to
// drive the hypervisor from SLIC.
//
//============================================================================
#ifndef _HVCALLPCI_H #ifndef _HVCALLPCI_H
#define _HVCALLPCI_H #define _HVCALLPCI_H
//-------------------------------------------------------------------
// Forward declarations
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// Standard Includes
//-------------------------------------------------------------------
#include <asm/iSeries/HvCallSc.h> #include <asm/iSeries/HvCallSc.h>
#include <asm/iSeries/HvTypes.h> #include <asm/iSeries/HvTypes.h>
//----------------------------------------------------------------------------- /*
// Constants * DSA == Direct Select Address
//----------------------------------------------------------------------------- * this struct must be 64 bits in total
*/
struct HvCallPci_DsaAddr { // make sure this struct size is 64-bits total struct HvCallPci_DsaAddr {
u16 busNumber; u16 busNumber; /* PHB index? */
u8 subBusNumber; u8 subBusNumber; /* PCI bus number? */
u8 deviceId; u8 deviceId; /* device and function? */
u8 barNumber; u8 barNumber;
u8 reserved[3]; u8 reserved[3];
}; };
union HvDsaMap { union HvDsaMap {
u64 DsaAddr; u64 DsaAddr;
struct HvCallPci_DsaAddr Dsa; struct HvCallPci_DsaAddr Dsa;
...@@ -65,12 +50,13 @@ struct HvCallPci_LoadReturn { ...@@ -65,12 +50,13 @@ struct HvCallPci_LoadReturn {
u64 value; u64 value;
}; };
enum HvCallPci_DeviceType {HvCallPci_NodeDevice = 1, enum HvCallPci_DeviceType {
HvCallPci_SpDevice = 2, HvCallPci_NodeDevice = 1,
HvCallPci_IopDevice = 3, HvCallPci_SpDevice = 2,
HvCallPci_BridgeDevice = 4, HvCallPci_IopDevice = 3,
HvCallPci_MultiFunctionDevice = 5, HvCallPci_BridgeDevice = 4,
HvCallPci_IoaDevice = 6 HvCallPci_MultiFunctionDevice = 5,
HvCallPci_IoaDevice = 6
}; };
...@@ -138,9 +124,9 @@ enum HvCallPci_VpdType { ...@@ -138,9 +124,9 @@ enum HvCallPci_VpdType {
#define HvCallPciGetBusUnitInfo HvCallPci + 50 #define HvCallPciGetBusUnitInfo HvCallPci + 50
//============================================================================ //============================================================================
static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber, static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber,
u8 deviceId, u32 offset, u8 deviceId, u32 offset,
u8 *value) u8 *value)
{ {
struct HvCallPci_DsaAddr dsa; struct HvCallPci_DsaAddr dsa;
struct HvCallPci_LoadReturn retVal; struct HvCallPci_LoadReturn retVal;
...@@ -160,9 +146,9 @@ static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber, ...@@ -160,9 +146,9 @@ static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber,
return retVal.rc; return retVal.rc;
} }
//============================================================================ //============================================================================
static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber, static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber,
u8 deviceId, u32 offset, u8 deviceId, u32 offset,
u16 *value) u16 *value)
{ {
struct HvCallPci_DsaAddr dsa; struct HvCallPci_DsaAddr dsa;
struct HvCallPci_LoadReturn retVal; struct HvCallPci_LoadReturn retVal;
......
#ifndef _ISERIES_64_PCI_H #ifndef _ISERIES_64_PCI_H
#define _ISERIES_64_PCI_H #define _ISERIES_64_PCI_H
/************************************************************************/ /************************************************************************/
/* File iSeries_pci.h created by Allan Trautman on Tue Feb 20, 2001. */ /* File iSeries_pci.h created by Allan Trautman on Tue Feb 20, 2001. */
/************************************************************************/ /************************************************************************/
/* Define some useful macros for the iSeries pci routines. */ /* Define some useful macros for the iSeries pci routines. */
/* Copyright (C) 20yy Allan H Trautman, IBM Corporation */ /* Copyright (C) 2001 Allan H Trautman, IBM Corporation */
/* */ /* */
/* This program is free software; you can redistribute it and/or modify */ /* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */ /* it under the terms of the GNU General Public License as published by */
...@@ -28,77 +29,81 @@ ...@@ -28,77 +29,81 @@
/* Ported to ppc64, May 25, 2001 */ /* Ported to ppc64, May 25, 2001 */
/* End Change Activity */ /* End Change Activity */
/************************************************************************/ /************************************************************************/
#include <asm/iSeries/HvCallPci.h> #include <asm/iSeries/HvCallPci.h>
struct pci_dev; /* For Forward Reference */ struct pci_dev; /* For Forward Reference */
struct iSeries_Device_Node; struct iSeries_Device_Node;
/************************************************************************/ /************************************************************************/
/* Gets iSeries Bus, SubBus, of DevFn using pci_dev* structure */ /* Gets iSeries Bus, SubBus, DevFn using iSeries_Device_Node structure */
/************************************************************************/ /************************************************************************/
#define ISERIES_BUS(DevPtr) DevPtr->DsaAddr.busNumber
#define ISERIES_SUBBUS(DevPtr) DevPtr->DsaAddr.subBusNumber #define ISERIES_BUS(DevPtr) DevPtr->DsaAddr.Dsa.busNumber
#define ISERIES_DEVICE(DevPtr) DevPtr->DsaAddr.deviceId #define ISERIES_SUBBUS(DevPtr) DevPtr->DsaAddr.Dsa.subBusNumber
#define ISERIES_DEVFUN(DevPtr) DevPtr->DevFn #define ISERIES_DEVICE(DevPtr) DevPtr->DsaAddr.Dsa.deviceId
#define ISERIES_DSA(DevPtr) (*(u64*)&DevPtr->DsaAddr) #define ISERIES_DSA(DevPtr) DevPtr->DsaAddr.DsaAddr
#define ISERIES_DEVFUN(DevPtr) DevPtr->DevFn
#define ISERIES_DEVNODE(PciDev) ((struct iSeries_Device_Node*)PciDev->sysdata) #define ISERIES_DEVNODE(PciDev) ((struct iSeries_Device_Node*)PciDev->sysdata)
#define EADsMaxAgents 7 #define EADsMaxAgents 7
/************************************************************************************/
/* Decodes Linux DevFn to iSeries DevFn, bridge device, or function. */ /************************************************************************/
/* For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h */ /* Decodes Linux DevFn to iSeries DevFn, bridge device, or function. */
/************************************************************************************/ /* For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h */
#define ISERIES_DECODE_DEVFN(linuxdevfn) (((linuxdevfn & 0x71) << 1) | (linuxdevfn & 0x07)) /************************************************************************/
#define ISERIES_DECODE_DEVICE(linuxdevfn) (((linuxdevfn & 0x38) >> 3) |(((linuxdevfn & 0x40) >> 2) + 0x10))
#define ISERIES_DECODE_FUNCTION(linuxdevfn) (linuxdevfn & 0x07)
#define ISERIES_PCI_AGENTID(idsel,func) ((idsel & 0x0F) << 4) | (func & 0x07) #define ISERIES_PCI_AGENTID(idsel,func) ((idsel & 0x0F) << 4) | (func & 0x07)
#define ISERIES_ENCODE_DEVICE(agentid) ((0x10) | ((agentid&0x20)>>2) | (agentid&07))
#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7) #define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7)
#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7) #define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7)
#define ISERIES_ENCODE_DEVICE(agentid) ((0x10) | ((agentid&0x20)>>2) | (agentid&07)) /*
/************************************************************************************/ * N.B. the ISERIES_DECODE_* macros are not used anywhere, and I think
/* Converts Virtual Address to Real Address for Hypervisor calls */ * the 0x71 (at least) must be wrong - 0x78 maybe? -- paulus.
/************************************************************************************/ */
#define REALADDR(virtaddr) (0x8000000000000000 | (virt_to_absolute((u64)virtaddr) )) #define ISERIES_DECODE_DEVFN(linuxdevfn) (((linuxdevfn & 0x71) << 1) | (linuxdevfn & 0x07))
#define ISERIES_DECODE_DEVICE(linuxdevfn) (((linuxdevfn & 0x38) >> 3) |(((linuxdevfn & 0x40) >> 2) + 0x10))
#define ISERIES_DECODE_FUNCTION(linuxdevfn) (linuxdevfn & 0x07)
/************************************************************************************/ /************************************************************************/
/* Define TRUE and FALSE Values for Al */ /* Converts Virtual Address to Real Address for Hypervisor calls */
/************************************************************************************/ /************************************************************************/
#ifndef TRUE
#define TRUE 1 #define REALADDR(virtaddr) (0x8000000000000000 | (virt_to_absolute((u64)virtaddr) ))
#endif
#ifndef FALSE
#define FALSE 0
#endif
/************************************************************************/ /************************************************************************/
/* iSeries Device Information */ /* iSeries Device Information */
/************************************************************************/ /************************************************************************/
struct iSeries_Device_Node { struct iSeries_Device_Node {
struct list_head Device_List; /* Must be first for cast to wo*/ struct list_head Device_List;
struct pci_dev* PciDev; /* Pointer to pci_dev structure*/ struct pci_dev* PciDev; /* Pointer to pci_dev structure*/
struct HvCallPci_DsaAddr DsaAddr;/* Direct Select Address */ union HvDsaMap DsaAddr; /* Direct Select Address */
/* busNumber,subBusNumber, */ /* busNumber,subBusNumber, */
/* deviceId, barNumber */ /* deviceId, barNumber */
HvAgentId AgentId; /* Hypervisor DevFn */ HvAgentId AgentId; /* Hypervisor DevFn */
int DevFn; /* Linux devfn */ int DevFn; /* Linux devfn */
int BarOffset; int BarOffset;
int Irq; /* Assigned IRQ */ int Irq; /* Assigned IRQ */
int ReturnCode; /* Return Code Holder */ int ReturnCode; /* Return Code Holder */
int IoRetry; /* Current Retry Count */ int IoRetry; /* Current Retry Count */
int Flags; /* Possible flags(disable/bist)*/ int Flags; /* Possible flags(disable/bist)*/
u16 Vendor; /* Vendor ID */ u16 Vendor; /* Vendor ID */
u8 LogicalSlot; /* Hv Slot Index for Tces */ u8 LogicalSlot; /* Hv Slot Index for Tces */
struct TceTable* DevTceTable; /* Device TCE Table */ struct TceTable* DevTceTable; /* Device TCE Table */
u8 PhbId; /* Phb Card is on. */ u8 PhbId; /* Phb Card is on. */
u16 Board; /* Board Number */ u16 Board; /* Board Number */
u8 FrameId; /* iSeries spcn Frame Id */ u8 FrameId; /* iSeries spcn Frame Id */
char CardLocation[4];/* Char format of planar vpd */ char CardLocation[4];/* Char format of planar vpd */
char Location[20]; /* Frame 1, Card C10 */ char Location[20]; /* Frame 1, Card C10 */
}; };
/************************************************************************/ /************************************************************************/
/* Location Data extracted from the VPD list and device info. */ /* Location Data extracted from the VPD list and device info. */
/************************************************************************/ /************************************************************************/
struct LocationDataStruct { /* Location data structure for device */ struct LocationDataStruct { /* Location data structure for device */
u16 Bus; /* iSeries Bus Number 0x00*/ u16 Bus; /* iSeries Bus Number 0x00*/
u16 Board; /* iSeries Board 0x02*/ u16 Board; /* iSeries Board 0x02*/
...@@ -108,17 +113,14 @@ struct LocationDataStruct { /* Location data structure for device */ ...@@ -108,17 +113,14 @@ struct LocationDataStruct { /* Location data structure for device */
u8 Card; u8 Card;
char CardLocation[4]; char CardLocation[4];
}; };
typedef struct LocationDataStruct LocationData; typedef struct LocationDataStruct LocationData;
#define LOCATION_DATA_SIZE 48 #define LOCATION_DATA_SIZE 48
/************************************************************************/
/* Flight Recorder tracing */
/************************************************************************/
extern int iSeries_Set_PciTraceFlag(int TraceFlag);
extern int iSeries_Get_PciTraceFlag(void);
/************************************************************************/ /************************************************************************/
/* Functions */ /* Functions */
/************************************************************************/ /************************************************************************/
extern LocationData* iSeries_GetLocationData(struct pci_dev* PciDev); extern LocationData* iSeries_GetLocationData(struct pci_dev* PciDev);
extern int iSeries_Device_Information(struct pci_dev*,char*, int); extern int iSeries_Device_Information(struct pci_dev*,char*, int);
extern void iSeries_Get_Location_Code(struct iSeries_Device_Node*); extern void iSeries_Get_Location_Code(struct iSeries_Device_Node*);
......
...@@ -41,11 +41,6 @@ static inline unsigned long virt_irq_to_real(unsigned long virt_irq) { ...@@ -41,11 +41,6 @@ static inline unsigned long virt_irq_to_real(unsigned long virt_irq) {
return virt_irq_to_real_map[virt_irq]; return virt_irq_to_real_map[virt_irq];
} }
/*
* This gets called from serial.c, which is now used on
* powermacs as well as prep/chrp boxes.
* Prep and chrp both have cascaded 8259 PICs.
*/
static __inline__ int irq_canonicalize(int irq) static __inline__ int irq_canonicalize(int irq)
{ {
return irq; return irq;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment