WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-ppc-devel

[XenPPC] [pushed][ppc] mpic and evtchn merge.

changeset:   9457:fd4dd4cdacbe
user:        jimix@xxxxxxxxxxxxxxxxxxxxx
date:        Fri Mar 24 17:50:52 2006 -0500
summary:     [ppc] mpic and evtchn merge.

diff -r 791d3b576ddf -r fd4dd4cdacbe xen/arch/ppc/external.c
--- a/xen/arch/ppc/external.c   Thu Mar 23 16:19:12 2006 -0500
+++ b/xen/arch/ppc/external.c   Fri Mar 24 17:50:52 2006 -0500
@@ -20,27 +20,51 @@
 #include <xen/types.h>
 #include <xen/sched.h>
 #include <xen/lib.h>
+#include <xen/event.h>
+#include <xen/irq.h>
 #include <public/xen.h>
 #include <asm/current.h>
 #include <asm/hardirq.h>
+#include <asm/mpic.h>
 
 #undef DEBUG
-
-static int pending_dom0_ee;
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+extern void do_IRQ(struct cpu_user_regs *regs);
+
+int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
+unsigned long io_apic_irqs;
+static struct mpic *mpic;
+static struct hw_interrupt_type hc_irq;
 
 /* deliver_ee: called with interrupts off when resuming every vcpu */
 void deliver_ee(struct cpu_user_regs *regs)
 {
-    const ulong srr_mask = ~(MSR_IR | MSR_DR | MSR_FE0 | MSR_PR |
-                                MSR_FE1 | MSR_EE | MSR_RI);
+    const ulong srr_mask = ~(MSR_IR | MSR_DR | MSR_FE0 | MSR_FE1 | MSR_EE |
+                             MSR_RI |
+                             MSR_BE | MSR_FP | MSR_PMM | MSR_PR | MSR_SE);
+
+
+    local_irq_disable();
 
     /* trigger exception only if we have a pending irq, we're resuming a guest
      * (not the hypervisor), the guest is dom0, and it has MSR:EE set. */
-    if ((!pending_dom0_ee)
-        || (regs->msr & MSR_HV)
-        || (current->domain->domain_id != 0)
-        || !(regs->msr & MSR_EE))
+    if (!event_pending(current)) {
+        if (current->vcpu_info->evtchn_upcall_pending) {
+            printk("0x%lx,0x%x\n", 
+                   current->vcpu_info->evtchn_upcall_pending,
+                   current->vcpu_info->evtchn_upcall_mask);
+            for (;;);
+        }
         return;
+    }
+    if (regs->msr & MSR_HV) return;
+    if (current->domain->domain_id != 0) return;
+    if (!(regs->msr & MSR_EE)) return;
 
     /* XXX OS error: EE was set but RI was not. We could trigger a machine
      * check, or kill the domain... for now just crash Xen so we notice. */
@@ -51,53 +75,222 @@ void deliver_ee(struct cpu_user_regs *re
     regs->srr1 = regs->msr & ~0x00000000783f0000;
     regs->pc = 0x500;
     regs->msr &= srr_mask;
-    regs->msr |= MSR_SF;
-
-#ifdef DEBUG
-    printk("<HV: pc=0x%lx, msr=0x%lx\n", regs->pc, regs->msr);
-#endif
-
-    pending_dom0_ee = 0;
+    regs->msr |= MSR_SF | MSR_ME;
+
+    DBG("<HV: pc=0x%lx, msr=0x%lx\n", regs->pc, regs->msr);
 }
 
 void do_external(struct cpu_user_regs *regs)
 {
-    shared_info_t *si;
-    ulong *irqp;
-    ulong *maskp;
-    uint64_t *selp;
-    int irqs;
-    int pend;
-    int cpu = 0;
-
-    /* currently dom0 gets all external interrupts */
-    si = dom0->shared_info;
-    irqp = si->evtchn_pending;
-    maskp = si->evtchn_mask;
-    irqs = sizeof (si->evtchn_pending) * 8;
-    selp = &si->vcpu_info[cpu].evtchn_pending_sel;
-
-#ifdef DEBUG
-    printk(">HV: pc=0x%lx, msr=0x%lx\n", regs->pc, regs->msr);
-#endif
-
-    /* probe the external interrupt controller */
-    pend = external_get_irq(irqp, maskp, selp, irqs);
-    if (!pend) {
-        int i;
-        /* interrupt occured but it was masked */
-        printk("%s all pending externals were masked\np: ", __func__);
-        for (i = 0; i < ARRAY_SIZE(si->evtchn_pending); i++) {
-            printk("0x%lx ",  si->evtchn_pending[i]);
-        }
-        printk("\nm: ");
-        for (i = 0; i < ARRAY_SIZE(si->evtchn_mask); i++) {
-            printk("0x%lx ", si->evtchn_mask[i]);
-        }
-        printk("\n");
-        return;
-    }
-
-    /* deliver all EEs to dom0 during resume */
-    pending_dom0_ee = 1;
-}
+    int vec;
+
+    local_irq_disable();
+
+    vec = mpic_get_one_irq(mpic, regs);
+
+    DBG("EE:0x%lx isrc: %d\n", regs->msr, vec);
+    if (vec != -1) {
+        regs->entry_vector = vec;
+        do_IRQ(regs);
+    }
+}
+
+static int xen_local_irq(unsigned int irq)
+{
+    irq_desc_t *desc;
+    unsigned int vector;
+
+    vector = irq_to_vector(irq);
+    desc = &irq_desc[vector];
+
+    return !(desc->status & IRQ_GUEST);
+}
+
+static unsigned int xen_startup_irq(unsigned int irq)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        return hc_irq.startup(irq);
+    }
+       return 0;
+}
+
+static void xen_shutdown_irq(unsigned int irq)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        hc_irq.shutdown(irq);
+    }
+}
+
+static void xen_enable_irq(unsigned int irq)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        hc_irq.enable(irq);
+    }
+}
+
+static void xen_disable_irq(unsigned int irq)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        hc_irq.disable(irq);
+    }
+}
+    
+static void xen_ack_irq(unsigned int irq)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        if (hc_irq.ack) hc_irq.ack(irq);
+    }
+}
+
+static void xen_end_irq(unsigned int irq)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        hc_irq.end(irq);
+    }
+}
+
+static void xen_set_affinity(unsigned int irq, cpumask_t mask)
+{
+    DBG("%s(%d)\n", __func__, irq);
+    if (xen_local_irq(irq)) {
+        if (hc_irq.set_affinity) hc_irq.set_affinity(irq, mask);
+    }
+}
+
+void init_IRQ(void)
+{
+    unsigned long opic_addr;
+    unsigned int isu_size;
+    unsigned int irq_offset;
+    unsigned int irq_count;
+    unsigned int ipi_offset;
+    unsigned char *senses;
+    unsigned int senses_count;
+
+    printk("%s: start\n", __func__);
+
+    io_apic_irqs = ~0;  /* all IRQs go through IOAPIC */
+       irq_vector[0] = FIRST_DEVICE_VECTOR;
+       vector_irq[FIRST_DEVICE_VECTOR] = 0;
+
+    /* should find this in the devtree:
+     * G5 is at 0xffc00000
+     * Maple is at 0xf8040000
+     */
+    opic_addr = 0xf8040000;
+    isu_size = 0;
+    irq_offset = 0;
+    irq_count = 128;
+    ipi_offset = 128;
+    senses = NULL;
+    senses_count = 0;
+
+    mpic = mpic_alloc(opic_addr,
+                      MPIC_PRIMARY | MPIC_BIG_ENDIAN |
+                      MPIC_BROKEN_U3 | MPIC_WANTS_RESET,
+                      isu_size, irq_offset, irq_count,
+                      ipi_offset, senses, senses_count, "Xen-U3-MPIC");
+
+       BUG_ON(mpic == NULL);
+       mpic_init(mpic);
+
+       hc_irq.startup = mpic->hc_irq.startup;
+       mpic->hc_irq.startup = xen_startup_irq;
+
+       hc_irq.enable = mpic->hc_irq.enable;
+       mpic->hc_irq.enable = xen_enable_irq;
+
+       hc_irq.disable = mpic->hc_irq.disable;
+       mpic->hc_irq.disable = xen_disable_irq;
+
+       hc_irq.shutdown = mpic->hc_irq.shutdown;
+       mpic->hc_irq.shutdown = xen_shutdown_irq;
+
+       hc_irq.ack = mpic->hc_irq.ack;
+       mpic->hc_irq.ack = xen_ack_irq;
+
+       hc_irq.end = mpic->hc_irq.end;
+       mpic->hc_irq.end = xen_end_irq;
+
+       hc_irq.set_affinity = mpic->hc_irq.set_affinity;
+       mpic->hc_irq.set_affinity = xen_set_affinity;
+
+    printk("%s: success\n", __func__);
+}
+
+void ack_APIC_irq(void) {
+    printk("%s: EOI the whole MPIC?\n", __func__);
+    for (;;);
+}
+
+void ack_bad_irq(unsigned int irq)
+{
+    printk("unexpected IRQ trap at vector %02x\n", irq);
+    /*
+     * Currently unexpected vectors happen only on SMP and APIC.
+     * We _must_ ack these because every local APIC has only N
+     * irq slots per priority level, and a 'hanging, unacked' IRQ
+     * holds up an irq slot - in excessive cases (when multiple
+     * unexpected vectors occur) that might lock up the APIC
+     * completely.
+     */
+    ack_APIC_irq();
+}
+
+void dump_ioapic_irq_info(void)
+{
+    printk("%s: can't dump yet\n", __func__);
+}
+
+/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
+u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = { FIRST_DEVICE_VECTOR , 0 };
+int assign_irq_vector(int irq)
+{
+    static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
+
+    BUG_ON(irq >= NR_IRQ_VECTORS);
+    if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
+        return IO_APIC_VECTOR(irq);
+next:
+    current_vector += 8;
+
+    /* Skip the hypercall vector. */
+    if (current_vector == HYPERCALL_VECTOR)
+        goto next;
+
+    /* Skip the Linux/BSD fast-trap vector. */
+    if (current_vector == FAST_TRAP)
+        goto next;
+
+    if (current_vector >= FIRST_SYSTEM_VECTOR) {
+        offset++;
+        if (!(offset%8))
+            return -ENOSPC;
+        current_vector = FIRST_DEVICE_VECTOR + offset;
+    }
+
+    vector_irq[current_vector] = irq;
+    if (irq != AUTO_ASSIGN)
+        IO_APIC_VECTOR(irq) = current_vector;
+
+    return current_vector;
+}
+
+int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval)
+{
+    BUG_ON(pval != pval);
+
+    return 0;
+}
+
+int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
+{
+    BUG_ON(val != val);
+    return 0;
+}
diff -r 791d3b576ddf -r fd4dd4cdacbe xen/arch/ppc/setup.c
--- a/xen/arch/ppc/setup.c      Thu Mar 23 16:19:12 2006 -0500
+++ b/xen/arch/ppc/setup.c      Fri Mar 24 17:50:52 2006 -0500
@@ -275,7 +275,6 @@ static void __init __start_xen(multiboot
         debugger_trap_immediate();
 #endif
 
-    external_init(0xf8040000, 0);
     start_of_day();
 
     /* Create initial domain 0. */
diff -r 791d3b576ddf -r fd4dd4cdacbe xen/drivers/char/console.c
--- a/xen/drivers/char/console.c        Thu Mar 23 16:19:12 2006 -0500
+++ b/xen/drivers/char/console.c        Fri Mar 24 17:50:52 2006 -0500
@@ -323,6 +323,7 @@ static long guest_console_write(GUEST_HA
 {
     char kbuf[128], *kptr;
     int kcount;
+    struct cpu_user_regs *regs = guest_cpu_user_regs();
 
     while ( count > 0 )
     {
diff -r 791d3b576ddf -r fd4dd4cdacbe xen/include/asm-ppc/io.h
--- a/xen/include/asm-ppc/io.h  Thu Mar 23 16:19:12 2006 -0500
+++ b/xen/include/asm-ppc/io.h  Fri Mar 24 17:50:52 2006 -0500
@@ -35,7 +35,7 @@ extern ulong isa_io_base;
 #define inl(port)       in_le32((void *)((ulong)(port) + isa_io_base))
 #define outl(val, port) out_le32((void *)((ulong)(port) + isa_io_base), val)
 
-#define ioremap(x,l) (x)
+#define ioremap(x,l) (void __iomem *)(x)
 #define readb(port) in_8((void *)(port))
 #define writeb(val, port) out_8((void *)(port), val)
 
@@ -49,6 +49,18 @@ extern unsigned in_le32(const volatile u
 extern unsigned in_le32(const volatile unsigned *addr);
 extern void out_le32(volatile unsigned *addr, int val);
 
+#define in_be8 in_8
+#define in_be16 in_16
+#define in_be32 in_32
+#define out_be8 out_8
+#define out_be16 out_16
+#define out_be32 out_32
+
+#define readw(port) in_le16((void *)(port))
+#define readl(port) in_le32((void *)(port))
+#define writew(val, port) out_le16((void *)(port), val)
+#define writel(val, port) out_le32((void *)(port), val)
+
 #define barrier() __asm__ __volatile__("": : :"memory")
 
 #endif
diff -r 791d3b576ddf -r fd4dd4cdacbe xen/include/asm-ppc/smp.h
--- a/xen/include/asm-ppc/smp.h Thu Mar 23 16:19:12 2006 -0500
+++ b/xen/include/asm-ppc/smp.h Fri Mar 24 17:50:52 2006 -0500
@@ -26,6 +26,8 @@ extern int smp_num_siblings;
 extern int smp_num_siblings;
 
 /* revisit when we support SMP */
+#define get_hard_smp_processor_id(i) i
+#define hard_smp_processor_id() 0
 #define raw_smp_processor_id() 0
 extern cpumask_t cpu_sibling_map[];
 extern cpumask_t cpu_core_map[];
diff -r 791d3b576ddf -r fd4dd4cdacbe xen/include/public/arch-ppc64.h
--- a/xen/include/public/arch-ppc64.h   Thu Mar 23 16:19:12 2006 -0500
+++ b/xen/include/public/arch-ppc64.h   Fri Mar 24 17:50:52 2006 -0500
@@ -74,7 +74,7 @@ typedef struct cpu_user_regs
     uint32_t fpscr;
     uint32_t cr;
     uint32_t xer;
-    uint32_t _pad;
+    uint32_t entry_vector;
 } cpu_user_regs_t;
 
 typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */ /* XXX timebase */
diff -r 791d3b576ddf -r fd4dd4cdacbe xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Thu Mar 23 16:19:12 2006 -0500
+++ b/xen/include/xen/sched.h   Fri Mar 24 17:50:52 2006 -0500
@@ -133,7 +133,7 @@ struct domain
      */
 #define NR_PIRQS 256 /* Put this somewhere sane! */
     u16              pirq_to_evtchn[NR_PIRQS];
-    u32              pirq_mask[NR_PIRQS/32];
+    unsigned long    pirq_mask[NR_PIRQS/BITS_PER_LONG];
 
     /* I/O capabilities (access to IRQs and memory-mapped I/O). */
     struct rangeset *iomem_caps;
diff -r 791d3b576ddf -r fd4dd4cdacbe xen/arch/ppc/mpic.c
--- /dev/null   Thu Jan  1 00:00:00 1970 +0000
+++ b/xen/arch/ppc/mpic.c       Fri Mar 24 17:50:52 2006 -0500
@@ -0,0 +1,1096 @@
+/* make this generic */
+
+#define le32_to_cpu(x) \
+({ \
+       __u32 __x = (x); \
+       ((__u32)( \
+               (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \
+               (((__u32)(__x) & (__u32)0x0000ff00UL) <<  8) | \
+               (((__u32)(__x) & (__u32)0x00ff0000UL) >>  8) | \
+               (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \
+})
+
+static inline void smp_message_recv(int msg, void /* struct pt_regs */ *regs)
+{
+    return;
+}
+
+#define alloc_bootmem(x) xmalloc_bytes(x)
+#define request_irq(irq, handler, f, devname, dev_id) \
+    panic("IPI requested: %d: %p: %s: %p\n", irq, handler, devname, dev_id)
+
+typedef int irqreturn_t;
+
+#define IRQ_NONE       (0)
+#define IRQ_HANDLED    (1)
+#define IRQ_RETVAL(x)  ((x) != 0)
+
+#define IRQ_SENSE_MASK         0x1
+#define IRQ_SENSE_LEVEL                0x1     /* interrupt on active level */
+#define IRQ_SENSE_EDGE         0x0     /* interrupt triggered by edge */
+
+#define IRQ_POLARITY_MASK      0x2
+#define IRQ_POLARITY_POSITIVE  0x2     /* high level or low->high edge */
+#define IRQ_POLARITY_NEGATIVE  0x0     /* low level or high->low edge */
+#define IRQ_LEVEL      64      /* IRQ level triggered */
+
+#define CONFIG_IRQ_ALL_CPUS 0
+#define distribute_irqs        CONFIG_IRQ_ALL_CPUS
+#define CONFIG_MPIC_BROKEN_U3
+
+#define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_FUNC(devfn) ((devfn) & 0x07)
+#define PCI_HEADER_TYPE                0x0e    /* 8 bits */
+#define PCI_VENDOR_ID          0x00    /* 16 bits */
+#define PCI_VENDOR_ID_AMD 0x1022
+#define PCI_CAPABILITY_LIST    0x34    /* Offset of first capability list 
entry */
+#define PCI_CAP_LIST_NEXT      1       /* Next capability in the list */
+#define PCI_CAP_LIST_ID                0       /* Capability ID */
+#define  PCI_CAP_ID_HT_IRQCONF 0x08    /* HyperTransport IRQ Configuration */
+#define PCI_STATUS             0x06    /* 16 bits */
+#define  PCI_STATUS_CAP_LIST   0x10    /* Support Capability List */
+
+
+/*
+ *  arch/powerpc/kernel/mpic.c
+ *
+ *  Driver for interrupt controllers following the OpenPIC standard, the
+ *  common implementation beeing IBM's MPIC. This driver also can deal
+ *  with various broken implementations of this HW.
+ *
+ *  Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#undef DEBUG
+#undef DEBUG_IPI
+#undef DEBUG_IRQ
+#undef DEBUG_LOW
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/kernel.h>
+#include <xen/init.h>
+#include <xen/irq.h>
+#include <xen/smp.h>
+//#include <linux/interrupt.h>
+//#include <linux/bootmem.h>
+#include <xen/spinlock.h>
+//#include <asm/pci.h>
+
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/io.h>
+//#include <asm/pgtable.h>
+//#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/mpic.h>
+#include <asm/smp.h>
+
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+static struct mpic *mpics;
+static struct mpic *mpic_primary;
+static DEFINE_SPINLOCK(mpic_lock);
+
+#ifdef CONFIG_PPC32    /* XXX for now */
+#ifdef CONFIG_IRQ_ALL_CPUS
+#define distribute_irqs        (1)
+#else
+#define distribute_irqs        (0)
+#endif
+#endif
+
+/*
+ * Register accessor functions
+ */
+
+
+static inline u32 _mpic_read(unsigned int be, volatile u32 __iomem *base,
+                           unsigned int reg)
+{
+       if (be)
+               return in_be32(base + (reg >> 2));
+       else
+               return in_le32(base + (reg >> 2));
+}
+
+static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base,
+                             unsigned int reg, u32 value)
+{
+       if (be)
+               out_be32(base + (reg >> 2), value);
+       else
+               out_le32(base + (reg >> 2), value);
+}
+
+static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi)
+{
+       unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0;
+       unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+
+       if (mpic->flags & MPIC_BROKEN_IPI)
+               be = !be;
+       return _mpic_read(be, mpic->gregs, offset);
+}
+
+static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 
value)
+{
+       unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10);
+
+       _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value);
+}
+
+static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
+{
+       unsigned int cpu = 0;
+
+       if (mpic->flags & MPIC_PRIMARY)
+               cpu = hard_smp_processor_id();
+
+       return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], 
reg);
+}
+
+static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 
value)
+{
+       unsigned int cpu = 0;
+
+       if (mpic->flags & MPIC_PRIMARY)
+               cpu = hard_smp_processor_id();
+
+       _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->cpuregs[cpu], reg, 
value);
+}
+
+static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, 
unsigned int reg)
+{
+       unsigned int    isu = src_no >> mpic->isu_shift;
+       unsigned int    idx = src_no & mpic->isu_mask;
+
+       return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
+                         reg + (idx * MPIC_IRQ_STRIDE));
+}
+
+static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
+                                  unsigned int reg, u32 value)
+{
+       unsigned int    isu = src_no >> mpic->isu_shift;
+       unsigned int    idx = src_no & mpic->isu_mask;
+
+       _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu],
+                   reg + (idx * MPIC_IRQ_STRIDE), value);
+}
+
+#define mpic_read(b,r)         _mpic_read(mpic->flags & 
MPIC_BIG_ENDIAN,(b),(r))
+#define mpic_write(b,r,v)      _mpic_write(mpic->flags & 
MPIC_BIG_ENDIAN,(b),(r),(v))
+#define mpic_ipi_read(i)       _mpic_ipi_read(mpic,(i))
+#define mpic_ipi_write(i,v)    _mpic_ipi_write(mpic,(i),(v))
+#define mpic_cpu_read(i)       _mpic_cpu_read(mpic,(i))
+#define mpic_cpu_write(i,v)    _mpic_cpu_write(mpic,(i),(v))
+#define mpic_irq_read(s,r)     _mpic_irq_read(mpic,(s),(r))
+#define mpic_irq_write(s,r,v)  _mpic_irq_write(mpic,(s),(r),(v))
+
+
+/*
+ * Low level utility functions
+ */
+
+
+
+/* Check if we have one of those nice broken MPICs with a flipped endian on
+ * reads from IPI registers
+ */
+static void __init mpic_test_broken_ipi(struct mpic *mpic)
+{
+       u32 r;
+
+       mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK);
+       r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0);
+
+       if (r == le32_to_cpu(MPIC_VECPRI_MASK)) {
+               printk(KERN_INFO "mpic: Detected reversed IPI registers\n");
+               mpic->flags |= MPIC_BROKEN_IPI;
+       }
+}
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+
+/* Test if an interrupt is sourced from HyperTransport (used on broken U3s)
+ * to force the edge setting on the MPIC and do the ack workaround.
+ */
+static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source)
+{
+       if (source >= 128 || !mpic->fixups)
+               return 0;
+       return mpic->fixups[source].base != NULL;
+}
+
+
+static inline void mpic_ht_end_irq(struct mpic *mpic, unsigned int source)
+{
+       struct mpic_irq_fixup *fixup = &mpic->fixups[source];
+
+       if (fixup->applebase) {
+               unsigned int soff = (fixup->index >> 3) & ~3;
+               unsigned int mask = 1U << (fixup->index & 0x1f);
+               writel(mask, fixup->applebase + soff);
+       } else {
+               spin_lock(&mpic->fixup_lock);
+               writeb(0x11 + 2 * fixup->index, fixup->base + 2);
+               writel(fixup->data, fixup->base + 4);
+               spin_unlock(&mpic->fixup_lock);
+       }
+}
+
+static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
+                                     unsigned int irqflags)
+{
+       struct mpic_irq_fixup *fixup = &mpic->fixups[source];
+       unsigned long flags;
+       u32 tmp;
+
+       if (fixup->base == NULL)
+               return;
+
+       DBG("startup_ht_interrupt(%u, %u) index: %d\n",
+           source, irqflags, fixup->index);
+       spin_lock_irqsave(&mpic->fixup_lock, flags);
+       /* Enable and configure */
+       writeb(0x10 + 2 * fixup->index, fixup->base + 2);
+       tmp = readl(fixup->base + 4);
+       tmp &= ~(0x23U);
+       if (irqflags & IRQ_LEVEL)
+               tmp |= 0x22;
+       writel(tmp, fixup->base + 4);
+       spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+}
+
+static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
+                                      unsigned int irqflags)
+{
+       struct mpic_irq_fixup *fixup = &mpic->fixups[source];
+       unsigned long flags;
+       u32 tmp;
+
+       if (fixup->base == NULL)
+               return;
+
+       DBG("shutdown_ht_interrupt(%u, %u)\n", source, irqflags);
+
+       /* Disable */
+       spin_lock_irqsave(&mpic->fixup_lock, flags);
+       writeb(0x10 + 2 * fixup->index, fixup->base + 2);
+       tmp = readl(fixup->base + 4);
+       tmp |= 1;
+       writel(tmp, fixup->base + 4);
+       spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+}
+
+static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
+                                   unsigned int devfn, u32 vdid)
+{
+       int i, irq, n;
+       u8 __iomem *base;
+       u32 tmp;
+       u8 pos;
+
+       for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
+            pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
+               u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
+               if (id == PCI_CAP_ID_HT_IRQCONF) {
+                       id = readb(devbase + pos + 3);
+                       if (id == 0x80)
+                               break;
+               }
+       }
+       if (pos == 0)
+               return;
+
+       base = devbase + pos;
+       writeb(0x01, base + 2);
+       n = (readl(base + 4) >> 16) & 0xff;
+
+       printk(KERN_INFO "mpic:   - HT:%02x.%x [0x%02x] vendor %04x device %04x"
+              " has %d irqs\n",
+              devfn >> 3, devfn & 0x7, pos, vdid & 0xffff, vdid >> 16, n + 1);
+
+       for (i = 0; i <= n; i++) {
+               writeb(0x10 + 2 * i, base + 2);
+               tmp = readl(base + 4);
+               irq = (tmp >> 16) & 0xff;
+               DBG("HT PIC index 0x%x, irq 0x%x, tmp: %08x\n", i, irq, tmp);
+               /* mask it , will be unmasked later */
+               tmp |= 0x1;
+               writel(tmp, base + 4);
+               mpic->fixups[irq].index = i;
+               mpic->fixups[irq].base = base;
+               /* Apple HT PIC has a non-standard way of doing EOIs */
+               if ((vdid & 0xffff) == 0x106b)
+                       mpic->fixups[irq].applebase = devbase + 0x60;
+               else
+                       mpic->fixups[irq].applebase = NULL;
+               writeb(0x11 + 2 * i, base + 2);
+               mpic->fixups[irq].data = readl(base + 4) | 0x80000000;
+       }
+}
+ 
+
+static void __init mpic_scan_ht_pics(struct mpic *mpic)
+{
+       unsigned int devfn;
+       u8 __iomem *cfgspace;
+
+       printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n");
+
+       /* Allocate fixups array */
+       mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup));
+       BUG_ON(mpic->fixups == NULL);
+       memset(mpic->fixups, 0, 128 * sizeof(struct mpic_irq_fixup));
+
+       /* Init spinlock */
+       spin_lock_init(&mpic->fixup_lock);
+
+       /* Map U3 config space. We assume all IO-APICs are on the primary bus
+        * so we only need to map 64kB.
+        */
+       cfgspace = ioremap(0xf2000000, 0x10000);
+       BUG_ON(cfgspace == NULL);
+
+       /* Now we scan all slots. We do a very quick scan, we read the header
+        * type, vendor ID and device ID only, that's plenty enough
+        */
+       for (devfn = 0; devfn < 0x100; devfn++) {
+               u8 __iomem *devbase = cfgspace + (devfn << 8);
+               u8 hdr_type = readb(devbase + PCI_HEADER_TYPE);
+               u32 l = readl(devbase + PCI_VENDOR_ID);
+               u16 s;
+
+               DBG("devfn %x, l: %x\n", devfn, l);
+
+               /* If no device, skip */
+               if (l == 0xffffffff || l == 0x00000000 ||
+                   l == 0x0000ffff || l == 0xffff0000)
+                       goto next;
+               /* Check if is supports capability lists */
+               s = readw(devbase + PCI_STATUS);
+               if (!(s & PCI_STATUS_CAP_LIST))
+                       goto next;
+
+               mpic_scan_ht_pic(mpic, devbase, devfn, l);
+
+       next:
+               /* next device, if function 0 */
+               if (PCI_FUNC(devfn) == 0 && (hdr_type & 0x80) == 0)
+                       devfn += 7;
+       }
+}
+
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+
+/* Find an mpic associated with a given linux interrupt */
+static struct mpic *mpic_find(unsigned int irq, unsigned int *is_ipi)
+{
+       struct mpic *mpic = mpics;
+
+       while(mpic) {
+               /* search IPIs first since they may override the main 
interrupts */
+               if (irq >= mpic->ipi_offset && irq < (mpic->ipi_offset + 4)) {
+                       if (is_ipi)
+                               *is_ipi = 1;
+                       return mpic;
+               }
+               if (irq >= mpic->irq_offset &&
+                   irq < (mpic->irq_offset + mpic->irq_count)) {
+                       if (is_ipi)
+                               *is_ipi = 0;
+                       return mpic;
+               }
+               mpic = mpic -> next;
+       }
+       return NULL;
+}
+
+/* Convert a cpu mask from logical to physical cpu numbers. */
+static inline u32 mpic_physmask(u32 cpumask)
+{
+       int i;
+       u32 mask = 0;
+
+       for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1)
+               mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
+       return mask;
+}
+
+#ifdef CONFIG_SMP
+/* Get the mpic structure from the IPI number */
+static inline struct mpic * mpic_from_ipi(unsigned int ipi)
+{
+       return container_of(irq_desc[ipi].handler, struct mpic, hc_ipi);
+}
+#endif
+
+/* Get the mpic structure from the irq number */
+static inline struct mpic * mpic_from_irq(unsigned int irq)
+{
+       return container_of(irq_desc[irq].handler, struct mpic, hc_irq);
+}
+
+/* Send an EOI */
+static inline void mpic_eoi(struct mpic *mpic)
+{
+       mpic_cpu_write(MPIC_CPU_EOI, 0);
+       (void)mpic_cpu_read(MPIC_CPU_WHOAMI);
+}
+
+#ifdef CONFIG_SMP
+static irqreturn_t mpic_ipi_action(int irq, void *dev_id, struct cpu_user_regs 
/* pt_regs  */ *regs)
+{
+       struct mpic *mpic = dev_id;
+
+       smp_message_recv(irq - mpic->ipi_offset, regs);
+       return IRQ_HANDLED;
+}
+#endif /* CONFIG_SMP */
+
+/*
+ * Linux descriptor level callbacks
+ */
+
+
+static void mpic_enable_irq(unsigned int irq)
+{
+       unsigned int loops = 100000;
+       struct mpic *mpic = mpic_from_irq(irq);
+       unsigned int src = irq - mpic->irq_offset;
+
+       DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
+
+       mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+                      mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) &
+                      ~MPIC_VECPRI_MASK);
+
+       /* make sure mask gets to controller before we return to user */
+       do {
+               if (!loops--) {
+                       printk(KERN_ERR "mpic_enable_irq timeout\n");
+                       break;
+               }
+       } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);    
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+       if (mpic->flags & MPIC_BROKEN_U3) {
+               unsigned int src = irq - mpic->irq_offset;
+               if (mpic_is_ht_interrupt(mpic, src) &&
+                   (irq_desc[irq].status & IRQ_LEVEL))
+                       mpic_ht_end_irq(mpic, src);
+       }
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+}
+
+static unsigned int mpic_startup_irq(unsigned int irq)
+{
+#ifdef CONFIG_MPIC_BROKEN_U3
+       struct mpic *mpic = mpic_from_irq(irq);
+       unsigned int src = irq - mpic->irq_offset;
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+       mpic_enable_irq(irq);
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+       if (mpic_is_ht_interrupt(mpic, src))
+               mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+       return 0;
+}
+
+static void mpic_disable_irq(unsigned int irq)
+{
+       unsigned int loops = 100000;
+       struct mpic *mpic = mpic_from_irq(irq);
+       unsigned int src = irq - mpic->irq_offset;
+
+       DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
+
+       mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI,
+                      mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) |
+                      MPIC_VECPRI_MASK);
+
+       /* make sure mask gets to controller before we return to user */
+       do {
+               if (!loops--) {
+                       printk(KERN_ERR "mpic_enable_irq timeout\n");
+                       break;
+               }
+       } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
+}
+
+static void mpic_shutdown_irq(unsigned int irq)
+{
+#ifdef CONFIG_MPIC_BROKEN_U3
+       struct mpic *mpic = mpic_from_irq(irq);
+       unsigned int src = irq - mpic->irq_offset;
+
+       if (mpic_is_ht_interrupt(mpic, src))
+               mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
+
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+       mpic_disable_irq(irq);
+}
+
+static void mpic_end_irq(unsigned int irq)
+{
+       struct mpic *mpic = mpic_from_irq(irq);
+
+#ifdef DEBUG_IRQ
+       DBG("%s: end_irq: %d\n", mpic->name, irq);
+#endif
+       /* We always EOI on end_irq() even for edge interrupts since that
+        * should only lower the priority, the MPIC should have properly
+        * latched another edge interrupt coming in anyway
+        */
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+       if (mpic->flags & MPIC_BROKEN_U3) {
+               unsigned int src = irq - mpic->irq_offset;
+               if (mpic_is_ht_interrupt(mpic, src) &&
+                   (irq_desc[irq].status & IRQ_LEVEL))
+                       mpic_ht_end_irq(mpic, src);
+       }
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+       mpic_eoi(mpic);
+}
+
+#ifdef CONFIG_SMP
+
+static void mpic_enable_ipi(unsigned int irq)
+{
+       struct mpic *mpic = mpic_from_ipi(irq);
+       unsigned int src = irq - mpic->ipi_offset;
+
+       DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
+       mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
+}
+
+static void mpic_disable_ipi(unsigned int irq)
+{
+       /* NEVER disable an IPI... that's just plain wrong! */
+}
+
+static void mpic_end_ipi(unsigned int irq)
+{
+       struct mpic *mpic = mpic_from_ipi(irq);
+
+       /*
+        * IPIs are marked IRQ_PER_CPU. This has the side effect of
+        * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
+        * applying to them. We EOI them late to avoid re-entering.
+        * We mark IPI's with SA_INTERRUPT as they must run with
+        * irqs disabled.
+        */
+       mpic_eoi(mpic);
+}
+
+#endif /* CONFIG_SMP */
+
+static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
+{
+       struct mpic *mpic = mpic_from_irq(irq);
+
+       cpumask_t tmp;
+
+       cpus_and(tmp, cpumask, cpu_online_map);
+
+       mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_DESTINATION,
+                      mpic_physmask(cpus_addr(tmp)[0]));       
+}
+
+
+/*
+ * Exported functions
+ */
+
+
+struct mpic * __init mpic_alloc(unsigned long phys_addr,
+                               unsigned int flags,
+                               unsigned int isu_size,
+                               unsigned int irq_offset,
+                               unsigned int irq_count,
+                               unsigned int ipi_offset,
+                               unsigned char *senses,
+                               unsigned int senses_count,
+                               const char *name)
+{
+       struct mpic     *mpic;
+       u32             reg;
+       const char      *vers;
+       int             i;
+
+       mpic = alloc_bootmem(sizeof(struct mpic));
+       if (mpic == NULL)
+               return NULL;
+       
+
+       memset(mpic, 0, sizeof(struct mpic));
+       mpic->name = name;
+
+       mpic->hc_irq.typename = name;
+       mpic->hc_irq.startup = mpic_startup_irq;
+       mpic->hc_irq.shutdown = mpic_shutdown_irq;
+       mpic->hc_irq.enable = mpic_enable_irq;
+       mpic->hc_irq.disable = mpic_disable_irq;
+       mpic->hc_irq.end = mpic_end_irq;
+       if (flags & MPIC_PRIMARY)
+               mpic->hc_irq.set_affinity = mpic_set_affinity;
+#ifdef CONFIG_SMP
+       mpic->hc_ipi.typename = name;
+       mpic->hc_ipi.enable = mpic_enable_ipi;
+       mpic->hc_ipi.disable = mpic_disable_ipi;
+       mpic->hc_ipi.end = mpic_end_ipi;
+#endif /* CONFIG_SMP */
+
+       mpic->flags = flags;
+       mpic->isu_size = isu_size;
+       mpic->irq_offset = irq_offset;
+       mpic->irq_count = irq_count;
+       mpic->ipi_offset = ipi_offset;
+       mpic->num_sources = 0; /* so far */
+       mpic->senses = senses;
+       mpic->senses_count = senses_count;
+
+       /* Map the global registers */
+       mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000);
+       mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2);
+       BUG_ON(mpic->gregs == NULL);
+
+       /* Reset */
+       if (flags & MPIC_WANTS_RESET) {
+               mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
+                          mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+                          | MPIC_GREG_GCONF_RESET);
+               while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+                      & MPIC_GREG_GCONF_RESET)
+                       mb();
+       }
+
+       /* Read feature register, calculate num CPUs and, for non-ISU
+        * MPICs, num sources as well. On ISU MPICs, sources are counted
+        * as ISUs are added
+        */
+       reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0);
+       mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK)
+                         >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1;
+       if (isu_size == 0)
+               mpic->num_sources = ((reg & MPIC_GREG_FEATURE_LAST_SRC_MASK)
+                                    >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
+
+       /* Map the per-CPU registers */
+       for (i = 0; i < mpic->num_cpus; i++) {
+               mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE +
+                                          i * MPIC_CPU_STRIDE, 0x1000);
+               BUG_ON(mpic->cpuregs[i] == NULL);
+       }
+
+       /* Initialize main ISU if none provided */
+       if (mpic->isu_size == 0) {
+               mpic->isu_size = mpic->num_sources;
+               mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE,
+                                       MPIC_IRQ_STRIDE * mpic->isu_size);
+               BUG_ON(mpic->isus[0] == NULL);
+       }
+       mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
+       mpic->isu_mask = (1 << mpic->isu_shift) - 1;
+
+       /* Display version */
+       switch (reg & MPIC_GREG_FEATURE_VERSION_MASK) {
+       case 1:
+               vers = "1.0";
+               break;
+       case 2:
+               vers = "1.2";
+               break;
+       case 3:
+               vers = "1.3";
+               break;
+       default:
+               vers = "<unknown>";
+               break;
+       }
+       printk(KERN_INFO "mpic: Setting up MPIC \"%s\" version %s at %lx, max 
%d CPUs\n",
+              name, vers, phys_addr, mpic->num_cpus);
+       printk(KERN_INFO "mpic: ISU size: %d, shift: %d, mask: %x\n", 
mpic->isu_size,
+              mpic->isu_shift, mpic->isu_mask);
+
+       mpic->next = mpics;
+       mpics = mpic;
+
+       if (flags & MPIC_PRIMARY)
+               mpic_primary = mpic;
+
+       return mpic;
+}
+
+void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
+                           unsigned long phys_addr)
+{
+       unsigned int isu_first = isu_num * mpic->isu_size;
+
+       BUG_ON(isu_num >= MPIC_MAX_ISU);
+
+       mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * 
mpic->isu_size);
+       if ((isu_first + mpic->isu_size) > mpic->num_sources)
+               mpic->num_sources = isu_first + mpic->isu_size;
+}
+
+void __init mpic_setup_cascade(unsigned int irq, mpic_cascade_t handler,
+                              void *data)
+{
+       struct mpic *mpic = mpic_find(irq, NULL);
+       unsigned long flags;
+
+       /* Synchronization here is a bit dodgy, so don't try to replace cascade
+        * interrupts on the fly too often ... but normally it's set up at boot.
+        */
+       spin_lock_irqsave(&mpic_lock, flags);
+       if (mpic->cascade)             
+               mpic_disable_irq(mpic->cascade_vec + mpic->irq_offset);
+       mpic->cascade = NULL;
+       wmb();
+       mpic->cascade_vec = irq - mpic->irq_offset;
+       mpic->cascade_data = data;
+       wmb();
+       mpic->cascade = handler;
+       mpic_enable_irq(irq);
+       spin_unlock_irqrestore(&mpic_lock, flags);
+}
+
+void __init mpic_init(struct mpic *mpic)
+{
+       int i;
+
+       BUG_ON(mpic->num_sources == 0);
+
+       printk(KERN_INFO "mpic: Initializing for %d sources\n", 
mpic->num_sources);
+
+       /* Set current processor priority to max */
+       mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+
+       /* Initialize timers: just disable them all */
+       for (i = 0; i < 4; i++) {
+               mpic_write(mpic->tmregs,
+                          i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0);
+               mpic_write(mpic->tmregs,
+                          i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI,
+                          MPIC_VECPRI_MASK |
+                          (MPIC_VEC_TIMER_0 + i));
+       }
+
+       /* Initialize IPIs to our reserved vectors and mark them disabled for 
now */
+       mpic_test_broken_ipi(mpic);
+       for (i = 0; i < 4; i++) {
+               mpic_ipi_write(i,
+                              MPIC_VECPRI_MASK |
+                              (10 << MPIC_VECPRI_PRIORITY_SHIFT) |
+                              (MPIC_VEC_IPI_0 + i));
+#ifdef CONFIG_SMP
+               if (!(mpic->flags & MPIC_PRIMARY))
+                       continue;
+               irq_desc[mpic->ipi_offset+i].status |= IRQ_PER_CPU;
+               irq_desc[mpic->ipi_offset+i].handler = &mpic->hc_ipi;
+#endif /* CONFIG_SMP */
+       }
+
+       /* Initialize interrupt sources */
+       if (mpic->irq_count == 0)
+               mpic->irq_count = mpic->num_sources;
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+       /* Do the HT PIC fixups on U3 broken mpic */
+       DBG("MPIC flags: %x\n", mpic->flags);
+       if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
+               mpic_scan_ht_pics(mpic);
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+       for (i = 0; i < mpic->num_sources; i++) {
+               /* start with vector = source number, and masked */
+               u32 vecpri = MPIC_VECPRI_MASK | i | (8 << 
MPIC_VECPRI_PRIORITY_SHIFT);
+               int level = 0;
+               
+               /* if it's an IPI, we skip it */
+               if ((mpic->irq_offset + i) >= (mpic->ipi_offset + i) &&
+                   (mpic->irq_offset + i) <  (mpic->ipi_offset + i + 4))
+                       continue;
+
+               /* do senses munging */
+               if (mpic->senses && i < mpic->senses_count) {
+                       if (mpic->senses[i] & IRQ_SENSE_LEVEL)
+                               vecpri |= MPIC_VECPRI_SENSE_LEVEL;
+                       if (mpic->senses[i] & IRQ_POLARITY_POSITIVE)
+                               vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+               } else
+                       vecpri |= MPIC_VECPRI_SENSE_LEVEL;
+
+               /* remember if it was a level interrupts */
+               level = (vecpri & MPIC_VECPRI_SENSE_LEVEL);
+
+               /* deal with broken U3 */
+               if (mpic->flags & MPIC_BROKEN_U3) {
+#ifdef CONFIG_MPIC_BROKEN_U3
+                       if (mpic_is_ht_interrupt(mpic, i)) {
+                               vecpri &= ~(MPIC_VECPRI_SENSE_MASK |
+                                           MPIC_VECPRI_POLARITY_MASK);
+                               vecpri |= MPIC_VECPRI_POLARITY_POSITIVE;
+                       }
+#else
+                       printk(KERN_ERR "mpic: BROKEN_U3 set, but CONFIG 
doesn't match\n");
+#endif
+               }
+               DBG("setup source %d, vecpri: %08x, level: %d\n", i, vecpri,
+                   (level != 0));
+
+               /* init hw */
+               mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri);
+               mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+                              1 << hard_smp_processor_id());
+
+               /* init linux descriptors */
+               if (i < mpic->irq_count) {
+                       irq_desc[mpic->irq_offset+i].status = level ? IRQ_LEVEL 
: 0;
+                       irq_desc[mpic->irq_offset+i].handler = &mpic->hc_irq;
+               }
+       }
+       
+       /* Init spurrious vector */
+       mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS);
+
+       /* Disable 8259 passthrough */
+       mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0,
+                  mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0)
+                  | MPIC_GREG_GCONF_8259_PTHROU_DIS);
+
+       /* Set current processor priority to 0 */
+       mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+}
+
+
+
+void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
+{
+       int is_ipi;
+       struct mpic *mpic = mpic_find(irq, &is_ipi);
+       unsigned long flags;
+       u32 reg;
+
+       spin_lock_irqsave(&mpic_lock, flags);
+       if (is_ipi) {
+               reg = mpic_ipi_read(irq - mpic->ipi_offset) &
+                       ~MPIC_VECPRI_PRIORITY_MASK;
+               mpic_ipi_write(irq - mpic->ipi_offset,
+                              reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
+       } else {
+               reg = mpic_irq_read(irq - mpic->irq_offset,MPIC_IRQ_VECTOR_PRI)
+                       & ~MPIC_VECPRI_PRIORITY_MASK;
+               mpic_irq_write(irq - mpic->irq_offset, MPIC_IRQ_VECTOR_PRI,
+                              reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
+       }
+       spin_unlock_irqrestore(&mpic_lock, flags);
+}
+
+unsigned int mpic_irq_get_priority(unsigned int irq)
+{
+       int is_ipi;
+       struct mpic *mpic = mpic_find(irq, &is_ipi);
+       unsigned long flags;
+       u32 reg;
+
+       spin_lock_irqsave(&mpic_lock, flags);
+       if (is_ipi)
+               reg = mpic_ipi_read(irq - mpic->ipi_offset);
+       else
+               reg = mpic_irq_read(irq - mpic->irq_offset, 
MPIC_IRQ_VECTOR_PRI);
+       spin_unlock_irqrestore(&mpic_lock, flags);
+       return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT;
+}
+
+void mpic_setup_this_cpu(void)
+{
+#ifdef CONFIG_SMP
+       struct mpic *mpic = mpic_primary;
+       unsigned long flags;
+       u32 msk = 1 << hard_smp_processor_id();
+       unsigned int i;
+
+       BUG_ON(mpic == NULL);
+
+       DBG("%s: setup_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
+
+       spin_lock_irqsave(&mpic_lock, flags);
+
+       /* let the mpic know we want intrs. default affinity is 0xffffffff
+        * until changed via /proc. That's how it's done on x86. If we want
+        * it differently, then we should make sure we also change the default
+        * values of irq_affinity in irq.c.
+        */
+       if (distribute_irqs) {
+               for (i = 0; i < mpic->num_sources ; i++)
+                       mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+                               mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk);
+       }
+
+       /* Set current processor priority to 0 */
+       mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
+
+       spin_unlock_irqrestore(&mpic_lock, flags);
+#endif /* CONFIG_SMP */
+}
+
+int mpic_cpu_get_priority(void)
+{
+       struct mpic *mpic = mpic_primary;
+
+       return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI);
+}
+
+void mpic_cpu_set_priority(int prio)
+{
+       struct mpic *mpic = mpic_primary;
+
+       prio &= MPIC_CPU_TASKPRI_MASK;
+       mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio);
+}
+
+/*
+ * XXX: someone who knows mpic should check this.
+ * do we need to eoi the ipi including for kexec cpu here (see xics comments)?
+ * or can we reset the mpic in the new kernel?
+ */
+void mpic_teardown_this_cpu(int secondary)
+{
+       struct mpic *mpic = mpic_primary;
+       unsigned long flags;
+       u32 msk = 1 << hard_smp_processor_id();
+       unsigned int i;
+
+       BUG_ON(mpic == NULL);
+
+       DBG("%s: teardown_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
+       spin_lock_irqsave(&mpic_lock, flags);
+
+       /* let the mpic know we don't want intrs.  */
+       for (i = 0; i < mpic->num_sources ; i++)
+               mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+                       mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk);
+
+       /* Set current processor priority to max */
+       mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+
+       spin_unlock_irqrestore(&mpic_lock, flags);
+}
+
+
+void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
+{
+       struct mpic *mpic = mpic_primary;
+
+       BUG_ON(mpic == NULL);
+
+#ifdef DEBUG_IPI
+       DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
+#endif
+
+       mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
+                      mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
+}
+
+int mpic_get_one_irq(struct mpic *mpic, struct cpu_user_regs /* pt_regs */ 
*regs)
+{
+       u32 irq;
+
+       irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
+#ifdef DEBUG_LOW
+       DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
+#endif
+       if (mpic->cascade && irq == mpic->cascade_vec) {
+#ifdef DEBUG_LOW
+               DBG("%s: cascading ...\n", mpic->name);
+#endif
+               irq = mpic->cascade(regs, mpic->cascade_data);
+               mpic_eoi(mpic);
+               return irq;
+       }
+       if (unlikely(irq == MPIC_VEC_SPURRIOUS))
+               return -1;
+       if (irq < MPIC_VEC_IPI_0) {
+#ifdef DEBUG_IRQ
+               DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset);
+#endif
+               return irq + mpic->irq_offset;
+       }
+#ifdef DEBUG_IPI
+               DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
+#endif
+       return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
+}
+
+int mpic_get_irq(struct cpu_user_regs /* pt_regs */ *regs)
+{
+       struct mpic *mpic = mpic_primary;
+
+       BUG_ON(mpic == NULL);
+
+       return mpic_get_one_irq(mpic, regs);
+}
+
+
+#ifdef CONFIG_SMP
+void mpic_request_ipis(void)
+{
+       struct mpic *mpic = mpic_primary;
+
+       BUG_ON(mpic == NULL);
+       
+       printk("requesting IPIs ... \n");
+
+       /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */
+       request_irq(mpic->ipi_offset+0, mpic_ipi_action, SA_INTERRUPT,
+                   "IPI0 (call function)", mpic);
+       request_irq(mpic->ipi_offset+1, mpic_ipi_action, SA_INTERRUPT,
+                  "IPI1 (reschedule)", mpic);
+       request_irq(mpic->ipi_offset+2, mpic_ipi_action, SA_INTERRUPT,
+                  "IPI2 (unused)", mpic);
+       request_irq(mpic->ipi_offset+3, mpic_ipi_action, SA_INTERRUPT,
+                  "IPI3 (debugger break)", mpic);
+
+       printk("IPIs requested... \n");
+}
+
+void smp_mpic_message_pass(int target, int msg)
+{
+       /* make sure we're sending something that translates to an IPI */
+       if ((unsigned int)msg > 3) {
+               printk("SMP %d: smp_message_pass: unknown msg %d\n",
+                      smp_processor_id(), msg);
+               return;
+       }
+       switch (target) {
+       case MSG_ALL:
+               mpic_send_ipi(msg, 0xffffffff);
+               break;
+       case MSG_ALL_BUT_SELF:
+               mpic_send_ipi(msg, 0xffffffff & ~(1 << smp_processor_id()));
+               break;
+       default:
+               mpic_send_ipi(msg, 1 << target);
+               break;
+       }
+}
+#endif /* CONFIG_SMP */
diff -r 791d3b576ddf -r fd4dd4cdacbe xen/include/asm-ppc/mpic.h
--- /dev/null   Thu Jan  1 00:00:00 1970 +0000
+++ b/xen/include/asm-ppc/mpic.h        Fri Mar 24 17:50:52 2006 -0500
@@ -0,0 +1,292 @@
+#ifndef _ASM_POWERPC_MPIC_H
+#define _ASM_POWERPC_MPIC_H
+//#ifdef __KERNEL__
+
+//#include <linux/irq.h>
+#include <xen/irq.h>
+
+/*
+ * Global registers
+ */
+
+#define MPIC_GREG_BASE                 0x01000
+
+#define MPIC_GREG_FEATURE_0            0x00000
+#define                MPIC_GREG_FEATURE_LAST_SRC_MASK         0x07ff0000
+#define                MPIC_GREG_FEATURE_LAST_SRC_SHIFT        16
+#define                MPIC_GREG_FEATURE_LAST_CPU_MASK         0x00001f00
+#define                MPIC_GREG_FEATURE_LAST_CPU_SHIFT        8
+#define                MPIC_GREG_FEATURE_VERSION_MASK          0xff
+#define MPIC_GREG_FEATURE_1            0x00010
+#define MPIC_GREG_GLOBAL_CONF_0                0x00020
+#define                MPIC_GREG_GCONF_RESET                   0x80000000
+#define                MPIC_GREG_GCONF_8259_PTHROU_DIS         0x20000000
+#define                MPIC_GREG_GCONF_BASE_MASK               0x000fffff
+#define MPIC_GREG_GLOBAL_CONF_1                0x00030
+#define MPIC_GREG_VENDOR_0             0x00040
+#define MPIC_GREG_VENDOR_1             0x00050
+#define MPIC_GREG_VENDOR_2             0x00060
+#define MPIC_GREG_VENDOR_3             0x00070
+#define MPIC_GREG_VENDOR_ID            0x00080
+#define        MPIC_GREG_VENDOR_ID_STEPPING_MASK       0x00ff0000
+#define        MPIC_GREG_VENDOR_ID_STEPPING_SHIFT      16
+#define        MPIC_GREG_VENDOR_ID_DEVICE_ID_MASK      0x0000ff00
+#define        MPIC_GREG_VENDOR_ID_DEVICE_ID_SHIFT     8
+#define        MPIC_GREG_VENDOR_ID_VENDOR_ID_MASK      0x000000ff
+#define MPIC_GREG_PROCESSOR_INIT       0x00090
+#define MPIC_GREG_IPI_VECTOR_PRI_0     0x000a0
+#define MPIC_GREG_IPI_VECTOR_PRI_1     0x000b0
+#define MPIC_GREG_IPI_VECTOR_PRI_2     0x000c0
+#define MPIC_GREG_IPI_VECTOR_PRI_3     0x000d0
+#define MPIC_GREG_SPURIOUS             0x000e0
+#define MPIC_GREG_TIMER_FREQ           0x000f0
+
+/*
+ *
+ * Timer registers
+ */
+#define MPIC_TIMER_BASE                        0x01100
+#define MPIC_TIMER_STRIDE              0x40
+
+#define MPIC_TIMER_CURRENT_CNT         0x00000
+#define MPIC_TIMER_BASE_CNT            0x00010
+#define MPIC_TIMER_VECTOR_PRI          0x00020
+#define MPIC_TIMER_DESTINATION         0x00030
+
+/*
+ * Per-Processor registers
+ */
+
+#define MPIC_CPU_THISBASE              0x00000
+#define MPIC_CPU_BASE                  0x20000
+#define MPIC_CPU_STRIDE                        0x01000
+
+#define MPIC_CPU_IPI_DISPATCH_0                0x00040
+#define MPIC_CPU_IPI_DISPATCH_1                0x00050
+#define MPIC_CPU_IPI_DISPATCH_2                0x00060
+#define MPIC_CPU_IPI_DISPATCH_3                0x00070
+#define MPIC_CPU_CURRENT_TASK_PRI      0x00080
+#define        MPIC_CPU_TASKPRI_MASK                   0x0000000f
+#define MPIC_CPU_WHOAMI                        0x00090
+#define        MPIC_CPU_WHOAMI_MASK                    0x0000001f
+#define MPIC_CPU_INTACK                        0x000a0
+#define MPIC_CPU_EOI                   0x000b0
+
+/*
+ * Per-source registers
+ */
+
+#define MPIC_IRQ_BASE                  0x10000
+#define MPIC_IRQ_STRIDE                        0x00020
+#define MPIC_IRQ_VECTOR_PRI            0x00000
+#define        MPIC_VECPRI_MASK                        0x80000000
+#define        MPIC_VECPRI_ACTIVITY                    0x40000000      /* Read 
Only */
+#define        MPIC_VECPRI_PRIORITY_MASK               0x000f0000
+#define        MPIC_VECPRI_PRIORITY_SHIFT              16
+#define        MPIC_VECPRI_VECTOR_MASK                 0x000007ff
+#define        MPIC_VECPRI_POLARITY_POSITIVE           0x00800000
+#define        MPIC_VECPRI_POLARITY_NEGATIVE           0x00000000
+#define        MPIC_VECPRI_POLARITY_MASK               0x00800000
+#define        MPIC_VECPRI_SENSE_LEVEL                 0x00400000
+#define        MPIC_VECPRI_SENSE_EDGE                  0x00000000
+#define        MPIC_VECPRI_SENSE_MASK                  0x00400000
+#define MPIC_IRQ_DESTINATION           0x00010
+
+#define MPIC_MAX_IRQ_SOURCES   2048
+#define MPIC_MAX_CPUS          32
+#define MPIC_MAX_ISU           32
+
+/*
+ * Special vector numbers (internal use only)
+ */
+#define MPIC_VEC_SPURRIOUS     255
+#define MPIC_VEC_IPI_3         254
+#define MPIC_VEC_IPI_2         253
+#define MPIC_VEC_IPI_1         252
+#define MPIC_VEC_IPI_0         251
+
+/* unused */
+#define MPIC_VEC_TIMER_3       250
+#define MPIC_VEC_TIMER_2       249
+#define MPIC_VEC_TIMER_1       248
+#define MPIC_VEC_TIMER_0       247
+
+/* Type definition of the cascade handler */
+typedef int (*mpic_cascade_t)(struct cpu_user_regs /* pt_regs */ *regs, void 
*data);
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+/* Fixup table entry */
+struct mpic_irq_fixup
+{
+       u8 __iomem      *base;
+       u8 __iomem      *applebase;
+       u32             data;
+       unsigned int    index;
+};
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+
+/* The instance data of a given MPIC */
+struct mpic
+{
+       /* The "linux" controller struct */
+       hw_irq_controller       hc_irq;
+#ifdef CONFIG_SMP
+       hw_irq_controller       hc_ipi;
+#endif
+       const char              *name;
+       /* Flags */
+       unsigned int            flags;
+       /* How many irq sources in a given ISU */
+       unsigned int            isu_size;
+       unsigned int            isu_shift;
+       unsigned int            isu_mask;
+       /* Offset of irq vector numbers */
+       unsigned int            irq_offset;     
+       unsigned int            irq_count;
+       /* Offset of ipi vector numbers */
+       unsigned int            ipi_offset;
+       /* Number of sources */
+       unsigned int            num_sources;
+       /* Number of CPUs */
+       unsigned int            num_cpus;
+       /* cascade handler */
+       mpic_cascade_t          cascade;
+       void                    *cascade_data;
+       unsigned int            cascade_vec;
+       /* senses array */
+       unsigned char           *senses;
+       unsigned int            senses_count;
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+       /* The fixup table */
+       struct mpic_irq_fixup   *fixups;
+       spinlock_t              fixup_lock;
+#endif
+
+       /* The various ioremap'ed bases */
+       volatile u32 __iomem    *gregs;
+       volatile u32 __iomem    *tmregs;
+       volatile u32 __iomem    *cpuregs[MPIC_MAX_CPUS];
+       volatile u32 __iomem    *isus[MPIC_MAX_ISU];
+
+       /* link */
+       struct mpic             *next;
+};
+
+/* This is the primary controller, only that one has IPIs and
+ * has afinity control. A non-primary MPIC always uses CPU0
+ * registers only
+ */
+#define MPIC_PRIMARY                   0x00000001
+/* Set this for a big-endian MPIC */
+#define MPIC_BIG_ENDIAN                        0x00000002
+/* Broken U3 MPIC */
+#define MPIC_BROKEN_U3                 0x00000004
+/* Broken IPI registers (autodetected) */
+#define MPIC_BROKEN_IPI                        0x00000008
+/* MPIC wants a reset */
+#define MPIC_WANTS_RESET               0x00000010
+
+/* Allocate the controller structure and setup the linux irq descs
+ * for the range if interrupts passed in. No HW initialization is
+ * actually performed.
+ * 
+ * @phys_addr: physial base address of the MPIC
+ * @flags:     flags, see constants above
+ * @isu_size:  number of interrupts in an ISU. Use 0 to use a
+ *              standard ISU-less setup (aka powermac)
+ * @irq_offset: first irq number to assign to this mpic
+ * @irq_count:  number of irqs to use with this mpic IRQ sources. Pass 0
+ *             to match the number of sources
+ * @ipi_offset: first irq number to assign to this mpic IPI sources,
+ *             used only on primary mpic
+ * @senses:    array of sense values
+ * @senses_num: number of entries in the array
+ *
+ * Note about the sense array. If none is passed, all interrupts are
+ * setup to be level negative unless MPIC_BROKEN_U3 is set in which
+ * case they are edge positive (and the array is ignored anyway).
+ * The values in the array start at the first source of the MPIC,
+ * that is senses[0] correspond to linux irq "irq_offset".
+ */
+extern struct mpic *mpic_alloc(unsigned long phys_addr,
+                              unsigned int flags,
+                              unsigned int isu_size,
+                              unsigned int irq_offset,
+                              unsigned int irq_count,
+                              unsigned int ipi_offset,
+                              unsigned char *senses,
+                              unsigned int senses_num,
+                              const char *name);
+
+/* Assign ISUs, to call before mpic_init()
+ *
+ * @mpic:      controller structure as returned by mpic_alloc()
+ * @isu_num:   ISU number
+ * @phys_addr: physical address of the ISU
+ */
+extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
+                           unsigned long phys_addr);
+
+/* Initialize the controller. After this has been called, none of the above
+ * should be called again for this mpic
+ */
+extern void mpic_init(struct mpic *mpic);
+
+/* Setup a cascade. Currently, only one cascade is supported this
+ * way, though you can always do a normal request_irq() and add
+ * other cascades this way. You should call this _after_ having
+ * added all the ISUs
+ *
+ * @irq_no:    "linux" irq number of the cascade (that is offset'ed vector)
+ * @handler:   cascade handler function
+ */
+extern void mpic_setup_cascade(unsigned int irq_no, mpic_cascade_t hanlder,
+                              void *data);
+
+/*
+ * All of the following functions must only be used after the
+ * ISUs have been assigned and the controller fully initialized
+ * with mpic_init()
+ */
+
+
+/* Change/Read the priority of an interrupt. Default is 8 for irqs and
+ * 10 for IPIs. You can call this on both IPIs and IRQ numbers, but the
+ * IPI number is then the offset'ed (linux irq number mapped to the IPI)
+ */
+extern void mpic_irq_set_priority(unsigned int irq, unsigned int pri);
+extern unsigned int mpic_irq_get_priority(unsigned int irq);
+
+/* Setup a non-boot CPU */
+extern void mpic_setup_this_cpu(void);
+
+/* Clean up for kexec (or cpu offline or ...) */
+extern void mpic_teardown_this_cpu(int secondary);
+
+/* Get the current cpu priority for this cpu (0..15) */
+extern int mpic_cpu_get_priority(void);
+
+/* Set the current cpu priority for this cpu */
+extern void mpic_cpu_set_priority(int prio);
+
+/* Request IPIs on primary mpic */
+extern void mpic_request_ipis(void);
+
+/* Send an IPI (non offseted number 0..3) */
+extern void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask);
+
+/* Send a message (IPI) to a given target (cpu number or MSG_*) */
+void smp_mpic_message_pass(int target, int msg);
+
+/* Fetch interrupt from a given mpic */
+extern int mpic_get_one_irq(struct mpic *mpic, struct cpu_user_regs /* pt_regs 
*/ *regs);
+/* This one gets to the primary mpic */
+extern int mpic_get_irq(struct cpu_user_regs /* pt_regs  */ *regs);
+
+/* global mpic for pSeries */
+extern struct mpic *pSeries_mpic;
+
+//#endif /* __KERNEL__ */
+#endif /* _ASM_POWERPC_MPIC_H */
diff -r 791d3b576ddf -r fd4dd4cdacbe xen/arch/ppc/external_mpic.c
--- a/xen/arch/ppc/external_mpic.c      Thu Mar 23 16:19:12 2006 -0500
+++ /dev/null   Thu Jan  1 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2005 Jimi Xenidis <jimix@xxxxxxxxxxxxxx>, IBM Corporation
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#include <xen/config.h>
-#include <xen/types.h>
-#include <xen/lib.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-
-#define MPIC_VEC_SPURRIOUS 0xff
-
-union emp_feature_reg {
-    u32 word;
-    struct {
-        u32 reserved_31_27 :5;
-        u32 num_IRQ        :11;
-        u32 reserved_16_13 :3;
-        u32 num_cpu        :5;
-        u32 version        :8;
-    } bits;
-};
-
-union emp_global_config_reg {
-    u32 word;
-    struct {
-        u32 reset          :1;
-        u32 reserved_30    :1;
-        u32 pass_through   :1;
-        u32 reserved_29_20 :9;
-        u32 base           :20;
-    } bits;
-};
-
-union emp_vendor_id_reg {
-    u32 word;
-    struct {
-        u32 reserved_31_24 :8;
-        u32 stepping       :8;
-        u32 device_id      :8;
-        u32 vendor_id      :8;
-    } bits;
-};
-
-union emp_int_ack {
-    u32 word;
-    struct {
-        u32 reserved_31_16 :16;
-        u32 reserved_16_11 :6;
-        u32 vector         :10;
-    } bits;
-};
-
-static ulong emp_le = 0;    /* 0 - BE, 1 - LE */
-
-static inline u32 read_reg(const u32 volatile *ptr)
-{
-    if (emp_le) {
-        return in_le32(ptr);
-    } else {
-        return in_32(ptr);
-    }
-}
-
-static inline void write_reg(u32 volatile *ptr, u32 val)
-{
-    if (emp_le) {
-        out_le32(ptr, val);
-    } else {
-        out_32(ptr, val);
-    }
-}
-
-struct openpic_global {
-    const u32 features;
-    const u8 __pad1[0x1c];
-
-    u32 config;
-    const u8 __pad2[0xc];
-
-    const u8 __vendor_specific[0x80 - 0x30];
-
-    u32 vendor_id;
-    const u8 __pad3[0xc];
-
-    u32 processor_init;
-    const u8 __pad4[0xc];
-
-    u32 ipi0_privec;
-    const u8 __pad5[0xc];
-
-    u32 ipi1_privec;
-    const u8 __pad6[0xc];
-
-    u32 ipi2_privec;
-    const u8 __pad7[0xc];
-
-    u32 ipi3_privec;
-    const u8 __pad8[0xc];
-
-    u32 spurious;
-    const u8 __pad9[0xc];
-};
-
-struct openpic_cpu {
-    const u8 __pad1[0x40];
-    struct {
-        u32 reg;
-        const u32 __pad[3];
-    } ipi_dispatch[4];
-
-    u32 task_priority;
-    const u8 __pad2[0xc];
-
-    u32 who_am_i;
-    const u8 __pad3[0xc];
-
-    u32 intr_ack;
-    const u8 __pad4[0xc];
-
-    u32 eoi;
-    const u8 __pad5[0xc];
-
-    const u8 __pad6[0x1000 - 0xc0];
-};
-
-struct openpic {
-    struct openpic_cpu local;
-    struct openpic_global global;
-    const u8 __pad1[0x20000 -
-                    sizeof (struct openpic_global) -
-                    sizeof (struct openpic_cpu)];
-    struct openpic_cpu cpu_specific[0x20];
-};
-
-/*
- * If the external_init() is never called then we assume little-endian
- * and the following location
- */
-static struct openpic *openpic = (typeof(openpic)) 0xffc00000;
-
-void external_init(ulong base, int little_endian)
-{
-    openpic = (typeof(openpic))base;
-    emp_le = little_endian;
-}
-
-/*
- * this checks the exceptions from the OpenPIC controler
- */
-static int external_get_one_irq(void)
-{
-    union emp_int_ack emp_vec;
-    int cpu = 0;
-    int port;
-
-    emp_vec.word = read_reg(&openpic->cpu_specific[cpu].intr_ack);
-    port = emp_vec.bits.vector;
-
-    if (port == MPIC_VEC_SPURRIOUS) {
-        port = -1;
-    }
-
-    return port;
-}
-
-/* fill in the bit for all external interrupts, if any port is
- * unmasked then return 1 */
-int external_get_irq(ulong *irqp, ulong *maskp, uint64_t *selp, int irqs)
-{
-    int port;
-    int pend = 0;
-    int sel;
-    int spurrious;
-
-    /* not sure if this is optimal (or even correct) but we will
-     * deliver even spurrious interrupts to dom0 */
-    spurrious = 1;
-    while((port = external_get_one_irq()) != -1) {
-        spurrious = 0;
-
-        if (port > irqs) {
-            panic("OpenPIC interrupt too large for bitop\n");
-        }
-        /* Xen always uses sychronized bitops */
-        set_bit(port, irqp);
-
-        sel = port / 8 / sizeof(ulong);
-        set_bit(sel, selp);
-
-        pend += !test_bit(port, maskp);
-    }
-    return pend + spurrious;
-}



_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel

<Prev in Thread] Current Thread [Next in Thread>