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);
}
} }
/* /*
......
This diff is collapsed.
...@@ -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