[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.