[parisc-linux-cvs] Re: 2.6.7-rc2-pa2 PA8800/ZX1 support

Grant Grundler grundler at parisc-linux.org
Fri Jun 4 14:19:55 MDT 2004


On Fri, Jun 04, 2004 at 01:36:54PM -0600, Grant Grundler wrote:
> 	.              : Makefile 
> 	arch/parisc/kernel: firmware.c hardware.c inventory.c irq.c 
> 	                    processor.c setup.c 
> 	drivers/parisc : iommu-helpers.h iosapic.c lba_pci.c sba_iommu.c 
> 	include/asm-parisc: hardware.h pdc.h pdcpat.h 
> 
> Log message:
> 2.6.7-rc2-pa2 pa8800 support
> boots on c8000 with NFS Root.
> Summary of changes will be posted on parisc-linux-cvs mailing list.

BTW, I also verified 32-bit c3k builds+boot on c3k.

TODO:
o verify a500 still builds/boots as well.
o enable AGP - C8000 has an AGP slot and ATI r300 FireGL card installed
  (I committed code to "discover" the AGP controller)
o install a harddisk and test LSI U320 controller (53c1030)
o test Si680 IDE controller (DVD drive is installed)
o test USB...5 USB ports on this beasty.
o Memory Hole! ZX1 memory map has 1GB of RAM < 4GB address.
  I have 2GB installed and only 1GB is visible.
o implement "OS Bypass" for 64-bit PCI/PCI-X devices in sba.
  (ia64 SBA already has this support - parisc will be similar)

I currently have no plan on backporting this mess to 2.4.
If someone wants to do that and test it on a500 or rp34xx,
I'll test on the C8000 (yeah SMP!) I've got here and commit.

BTW, thanks to Naresh Kumar Inna (HP India) for doing most of
the initial pa8800/zx1 work and providing that.
I've massacred what he gave me but used his work as a reference.

[ BTW, Naresh, where it still looks like your code, please provide
   a patch to include your copyright notice in the header of the file. ]


Here's the summary followed by the actual patch:

o add ZX1 and related Hvers/Svers to hardware list (discovery)
o add PDC PAT cfg space accessors to LBA support.
  ie use PAT PDC calls to walk PCI busses.
o fix EOI handling in iosapic.c - use the "Global Vector" and NOT
  the irqline value. This is broken HW design IMHO and I'll
  explain in a followup mail why.
  WARN: shared IRQ lines on existing Astro platforms are broken.
        Fortunately we almost never share IRQ lines.
        One line change to fix it.
o add ZX1 IOMMU support (non-zero IOVA space) was the biggest change

Additional cleanups I was too impatient to submit seperately:

o remove gsc_* usage from iosapic.c since nothing is GSC bus related
o move PAT PDC support/declarations from pdc.h to pdcpat.h
o remove extraneous cpu_irq_ops declaration (not used) in irq.c
o replace __LP64__ usage with CONFIG_PARISC64 in lba_pci.c

I'm pretty sure I have all the key changes listed. If someone
needs more detail than above and it's not obvious from the
patch (or code), please ask.

thanks,
grant


Index: Makefile
===================================================================
RCS file: /var/cvs/linux-2.6/Makefile,v
retrieving revision 1.203
diff -u -p -r1.203 Makefile
--- Makefile	1 Jun 2004 20:03:20 -0000	1.203
+++ Makefile	4 Jun 2004 06:27:02 -0000
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 7
-EXTRAVERSION =-rc2-pa1
+EXTRAVERSION =-rc2-pa2
 NAME=Zonked Quokka
 
 # *DOCUMENTATION*
Index: arch/parisc/kernel/firmware.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/firmware.c,v
retrieving revision 1.7
diff -u -p -r1.7 firmware.c
--- arch/parisc/kernel/firmware.c	4 May 2004 01:30:19 -0000	1.7
+++ arch/parisc/kernel/firmware.c	4 Jun 2004 06:27:04 -0000
@@ -65,6 +65,7 @@
 
 #include <asm/page.h>
 #include <asm/pdc.h>
+#include <asm/pdcpat.h>
 #include <asm/system.h>
 #include <asm/processor.h>	/* for boot_cpu_data */
 
@@ -1142,6 +1143,49 @@ int pdc_pat_pd_get_addr_map(unsigned lon
 			      __pa(pdc_result2), count, offset);
 	*actual_len = pdc_result[0];
 	memcpy(mem_addr, pdc_result2, *actual_len);
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+/**
+ * pdc_pat_io_pci_cfg_read - Read PCI configuration space.
+ * @pci_addr: PCI configuration space address for which the read request is being made.
+ * @pci_size: Size of read in bytes. Valid values are 1, 2, and 4. 
+ * @mem_addr: Pointer to return memory buffer.
+ *
+ */
+int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *mem_addr)
+{
+	int retval;
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_READ,
+					__pa(pdc_result), pci_addr, pci_size);
+	switch(pci_size) {
+		case 1: *(u8 *) mem_addr =  (u8)  pdc_result[0];
+		case 2: *(u16 *)mem_addr =  (u16) pdc_result[0];
+		case 4: *(u32 *)mem_addr =  (u32) pdc_result[0];
+	}
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+/**
+ * pdc_pat_io_pci_cfg_write - Retrieve information about memory address ranges.
+ * @pci_addr: PCI configuration space address for which the write  request is being made.
+ * @pci_size: Size of write in bytes. Valid values are 1, 2, and 4. 
+ * @value: Pointer to 1, 2, or 4 byte value in low order end of argument to be 
+ *         written to PCI Config space.
+ *
+ */
+int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_PCI_CONFIG_WRITE,
+				pci_addr, pci_size, val);
 	spin_unlock_irq(&pdc_lock);
 
 	return retval;
Index: arch/parisc/kernel/hardware.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/hardware.c,v
retrieving revision 1.4
diff -u -p -r1.4 hardware.c
--- arch/parisc/kernel/hardware.c	14 Apr 2004 06:18:39 -0000	1.4
+++ arch/parisc/kernel/hardware.c	4 Jun 2004 06:27:04 -0000
@@ -263,6 +263,17 @@ static struct hp_hardware hp_hardware_li
 	{HPHW_NPROC,0x67E,0x4,0x81,"Hitachi Tiny 80"},
 	{HPHW_NPROC,0x67F,0x4,0x81,"Hitachi Tiny 64"},
 	{HPHW_NPROC,0x700,0x4,0x91,"NEC Aska Processor"},
+	{HPHW_NPROC,0x880,0x4,0x91,"Orca Mako"},
+	{HPHW_NPROC,0x881,0x4,0x91,"Everest Mako"},
+	{HPHW_NPROC,0x882,0x4,0x91,"Rainier/Medel Mako Slow"},
+	{HPHW_NPROC,0x883,0x4,0x91,"Rainier/Medel Mako Fast"},
+	{HPHW_NPROC,0x884,0x4,0x91,"Mt. Hamilton"},
+	{HPHW_NPROC,0x885,0x4,0x91,"Mt. Hamilton DC-"},
+	{HPHW_NPROC,0x886,0x4,0x91,"Storm Peak Slow DC-"},
+	{HPHW_NPROC,0x887,0x4,0x91,"Storm Peak Slow"},
+	{HPHW_NPROC,0x888,0x4,0x91,"Storm Peak Fast DC-"},
+	{HPHW_NPROC,0x889,0x4,0x91,"Storm Peak Fast"},
+	{HPHW_NPROC,0x88A,0x4,0x91,"Crestone Peak"},
 	{HPHW_A_DIRECT, 0x004, 0x0000D, 0x00, "Arrakis MUX"}, 
 	{HPHW_A_DIRECT, 0x005, 0x0000D, 0x00, "Dyun Kiuh MUX"}, 
 	{HPHW_A_DIRECT, 0x006, 0x0000D, 0x00, "Baat Kiuh AP/MUX (40299B)"}, 
@@ -535,14 +546,17 @@ static struct hp_hardware hp_hardware_li
 	{HPHW_BCPORT, 0x800, 0x0000C, 0x10, "DEW BC Merced Port"}, 
 	{HPHW_BCPORT, 0x801, 0x0000C, 0x10, "SMC Bus Interface Merced Bus0"}, 
 	{HPHW_BCPORT, 0x802, 0x0000C, 0x10, "SMC Bus INterface Merced Bus1"}, 
-	{HPHW_BCPORT, 0x803, 0x0000C, 0x10, "IKE I/O Bus Converter Merced Port"}, 
-	{HPHW_BCPORT, 0x781, 0x0000C, 0x00, "IKE I/O Bus Converter Ropes Port"}, 
-	{HPHW_BCPORT, 0x804, 0x0000C, 0x10, "REO I/O Bus Converter Merced Port"}, 
-	{HPHW_BCPORT, 0x782, 0x0000C, 0x00, "REO I/O Bus Converter Ropes Port"}, 
+	{HPHW_BCPORT, 0x803, 0x0000C, 0x10, "IKE I/O BC Merced Port"}, 
+	{HPHW_BCPORT, 0x781, 0x0000C, 0x00, "IKE I/O BC Ropes Port"}, 
+	{HPHW_BCPORT, 0x804, 0x0000C, 0x10, "REO I/O BC Merced Port"}, 
+	{HPHW_BCPORT, 0x782, 0x0000C, 0x00, "REO I/O BC Ropes Port"}, 
+	{HPHW_BCPORT, 0x784, 0x0000C, 0x00, "Pluto I/O BC Ropes Port"}, 
 	{HPHW_BRIDGE, 0x680, 0x0000A, 0x00, "Dino PCI Bridge"}, 
 	{HPHW_BRIDGE, 0x682, 0x0000A, 0x00, "Cujo PCI Bridge"}, 
 	{HPHW_BRIDGE, 0x782, 0x0000A, 0x00, "Elroy PCI Bridge"}, 
 	{HPHW_BRIDGE, 0x583, 0x000A5, 0x00, "Saga PCI Bridge"}, 
+	{HPHW_BRIDGE, 0x783, 0x0000A, 0x00, "Mercury PCI Bridge"}, 
+	{HPHW_BRIDGE, 0x784, 0x0000A, 0x00, "Quicksilver AGP Bridge"}, 
 	{HPHW_B_DMA, 0x004, 0x00018, 0x00, "Parallel I/O"}, 
 	{HPHW_B_DMA, 0x004, 0x00019, 0x00, "Parallel RDB"}, 
 	{HPHW_B_DMA, 0x004, 0x00020, 0x80, "MID_BUS PSI"}, 
@@ -1181,15 +1195,18 @@ static struct hp_hardware hp_hardware_li
 	{HPHW_IOA, 0x581, 0x0000B, 0x10, "Uturn-IOA BC Runway Port"},
 	{HPHW_IOA, 0x582, 0x0000B, 0x10, "Astro BC Runway Port"},
 	{HPHW_IOA, 0x700, 0x0000B, 0x00, "NEC-IOS BC System Bus Port"},
+	{HPHW_IOA, 0x880, 0x0000C, 0x10, "Pluto BC McKinley Port"},
 	{HPHW_MEMORY, 0x002, 0x00008, 0x00, "MID_BUS"}, 
 	{HPHW_MEMORY, 0x063, 0x00009, 0x00, "712/132 L2 Upgrade"}, 
 	{HPHW_MEMORY, 0x064, 0x00009, 0x00, "712/160 L2 Upgrade"}, 
 	{HPHW_MEMORY, 0x065, 0x00009, 0x00, "715/132 L2 Upgrade"}, 
 	{HPHW_MEMORY, 0x066, 0x00009, 0x00, "715/160 L2 Upgrade"},
+	{HPHW_MEMORY, 0x0AF, 0x00009, 0x00, "Everest Mako Memory"},
 	{HPHW_OTHER, 0x004, 0x00030, 0x00, "Master"}, 
 	{HPHW_OTHER, 0x004, 0x00034, 0x00, "Slave"}, 
 	{HPHW_OTHER, 0x004, 0x00038, 0x00, "EDU"}, 
 	{HPHW_OTHER, 0x004, 0x00049, 0x00, "LGB Control"}, 
+	{HPHW_MC, 0x004, 0x000C0, 0x00, "BMC IPMI Mgmt Ctlr"}, 
 	{HPHW_FAULTY, 0, }  /* Special Marker for last entry */
 };
 
@@ -1290,7 +1307,7 @@ char *cpu_name_version[][2] = {
 	[pcxw]	{ "PA8500 (PCX-W)",	"2.0" },
 	[pcxw_]	{ "PA8600 (PCX-W+)",	"2.0" },
 	[pcxw2]	{ "PA8700 (PCX-W2)",	"2.0" },
-	[mako]	{ "PA8800 (MAKO)",	"2.0" }
+	[mako]	{ "PA8800 (Mako)",	"2.0" }
 };
 
 const char * __init
Index: arch/parisc/kernel/inventory.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/inventory.c,v
retrieving revision 1.4
diff -u -p -r1.4 inventory.c
--- arch/parisc/kernel/inventory.c	21 Dec 2003 13:08:45 -0000	1.4
+++ arch/parisc/kernel/inventory.c	4 Jun 2004 06:27:04 -0000
@@ -26,6 +26,7 @@
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/pdc.h>
+#include <asm/pdcpat.h>
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/parisc-device.h>
Index: arch/parisc/kernel/irq.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/irq.c,v
retrieving revision 1.12
diff -u -p -r1.12 irq.c
--- arch/parisc/kernel/irq.c	7 Jan 2004 21:30:08 -0000	1.12
+++ arch/parisc/kernel/irq.c	4 Jun 2004 06:27:04 -0000
@@ -121,12 +121,6 @@ struct irqaction cpu_irq_actions[IRQ_PER
 #endif
 };
 
-struct irq_region_ops cpu_irq_ops = {
-	.disable_irq	= disable_cpu_irq,
-	.enable_irq	= enable_cpu_irq,
-	.mask_irq	= unmask_cpu_irq,
-	.unmask_irq	= unmask_cpu_irq
-};
 
 struct irq_region cpu0_irq_region = {
 	.ops	= {
@@ -200,8 +194,8 @@ void enable_irq(int irq)
 {
 	struct irq_region *region;
 
-	DBG_IRQ(irq, ("enable_irq(%d) %d+%d eiem 0x%lx\n", irq,
-				IRQ_REGION(irq), IRQ_OFFSET(irq), cpu_eiem));
+	DBG_IRQ(irq, ("enable_irq(%d) %d+%d EIRR 0x%lx EIEM 0x%lx\n", irq,
+				IRQ_REGION(irq), IRQ_OFFSET(irq), mfctl(23), mfctl(15)));
 	irq = irq_canonicalize(irq);
 	region = irq_region[IRQ_REGION(irq)];
 
@@ -390,7 +384,7 @@ void do_irq(struct irqaction *action, in
 	irq_enter();
 	++kstat_cpu(cpu).irqs[irq];
 
-	DBG_IRQ(irq, ("do_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq)));
+	DBG_IRQ(irq, ("do_irq(%d) %d+%d eiem 0x%lx\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq), cpu_eiem));
 
 	for (; action; action = action->next) {
 #ifdef PARISC_IRQ_CR16_COUNTS
@@ -460,7 +454,7 @@ void do_cpu_irq_mask(struct pt_regs *reg
 
 #ifdef DEBUG_IRQ
 		if (eirr_val != (1UL << MAX_CPU_IRQ))
-			printk(KERN_DEBUG "do_cpu_irq_mask  %x\n", eirr_val);
+			printk(KERN_DEBUG "do_cpu_irq_mask  0x%x & 0x%x\n", eirr_val, cpu_eiem);
 #endif
 
 		/* Work our way from MSb to LSb...same order we alloc EIRs */
@@ -865,7 +859,7 @@ EXPORT_SYMBOL(probe_irq_mask);
 void __init init_IRQ(void)
 {
 	local_irq_disable();	/* PARANOID - should already be disabled */
-	mtctl(-1L, 23);		/* EIRR : clear all pending external intr */
+	mtctl(~0UL, 23);	/* EIRR : clear all pending external intr */
 #ifdef CONFIG_SMP
 	if (!cpu_eiem)
 		cpu_eiem = EIEM_MASK(IPI_IRQ) | EIEM_MASK(TIMER_IRQ);
Index: arch/parisc/kernel/processor.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/processor.c,v
retrieving revision 1.5
diff -u -p -r1.5 processor.c
--- arch/parisc/kernel/processor.c	9 May 2004 18:34:17 -0000	1.5
+++ arch/parisc/kernel/processor.c	4 Jun 2004 06:27:04 -0000
@@ -39,6 +39,7 @@
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/pdc.h>
+#include <asm/pdcpat.h>
 #include <asm/irq.h>		/* for struct irq_region */
 #include <asm/parisc-device.h>
 
Index: arch/parisc/kernel/setup.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/setup.c,v
retrieving revision 1.5
diff -u -p -r1.5 setup.c
--- arch/parisc/kernel/setup.c	4 May 2004 01:30:19 -0000	1.5
+++ arch/parisc/kernel/setup.c	4 Jun 2004 06:27:04 -0000
@@ -52,6 +52,8 @@ char	command_line[COMMAND_LINE_SIZE];
 /* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
 struct proc_dir_entry * proc_runway_root = NULL;
 struct proc_dir_entry * proc_gsc_root = NULL;
+struct proc_dir_entry * proc_mckinley_root = NULL;
+
 
 void __init setup_cmdline(char **cmdline_p)
 {
@@ -207,10 +209,15 @@ static void __init parisc_proc_mkdir(voi
         case pcxw:
         case pcxw_:
         case pcxw2:
-	case mako:	/* XXX : this is really mckinley bus */
                 if (NULL == proc_runway_root)
                 {
                         proc_runway_root = proc_mkdir("bus/runway", 0);
+                }
+                break;
+	case mako:
+                if (NULL == proc_mckinley_root)
+                {
+                        proc_mckinley_root = proc_mkdir("bus/mckinley", 0);
                 }
                 break;
 	default:
Index: drivers/parisc/iommu-helpers.h
===================================================================
RCS file: /var/cvs/linux-2.6/drivers/parisc/iommu-helpers.h,v
retrieving revision 1.2
diff -u -p -r1.2 iommu-helpers.h
--- drivers/parisc/iommu-helpers.h	12 Mar 2004 16:37:31 -0000	1.2
+++ drivers/parisc/iommu-helpers.h	4 Jun 2004 06:27:06 -0000
@@ -49,7 +49,15 @@ iommu_fill_pdir(struct ioc *ioc, struct 
 			sg_dma_len(startsg) = 0;
 			dma_offset = (unsigned long) pide & ~IOVP_MASK;
 			n_mappings++;
+#if defined(__LP64__) && !defined(CONFIG_PDC_NARROW)
+			/* Pluto IOMMU IO Virt Address is not zero based */
+			sg_dma_address(dma_sg) = pide | ioc->ibase;
+#else
+			/* SBA, ccio, and dino are zero based.
+			 * Trying to save a few CPU cycles for most users.
+			 */
 			sg_dma_address(dma_sg) = pide;
+#endif
 			pdirp = &(ioc->pdir_base[pide >> IOVP_SHIFT]);
 			prefetchw(pdirp);
 		}
Index: drivers/parisc/iosapic.c
===================================================================
RCS file: /var/cvs/linux-2.6/drivers/parisc/iosapic.c,v
retrieving revision 1.5
diff -u -p -r1.5 iosapic.c
--- drivers/parisc/iosapic.c	21 Dec 2003 13:13:11 -0000	1.5
+++ drivers/parisc/iosapic.c	4 Jun 2004 06:27:08 -0000
@@ -169,10 +169,11 @@
 
 #include <asm/byteorder.h>	/* get in-line asm for swab */
 #include <asm/pdc.h>
+#include <asm/pdcpat.h>
 #include <asm/page.h>
 #include <asm/segment.h>
 #include <asm/system.h>
-#include <asm/io.h>		/* gsc_read/write functions */
+#include <asm/io.h>		/* read/write functions */
 #ifdef CONFIG_SUPERIO
 #include <asm/superio.h>
 #endif
@@ -223,19 +224,7 @@ assert_failed (char *a, char *f, int l)
 #endif
 
 
-#define READ_U8(addr)  gsc_readb(addr)
-#define READ_U16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
-#define READ_U32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
-#define READ_REG16(addr) gsc_readw((u16 *) (addr))
-#define READ_REG32(addr) gsc_readl((u32 *) (addr))
-#define WRITE_U8(value, addr) gsc_writeb(value, addr)
-#define WRITE_U16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
-#define WRITE_U32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
-#define WRITE_REG16(value, addr) gsc_writew(value, (u16 *) (addr))
-#define WRITE_REG32(value, addr) gsc_writel(value, (u32 *) (addr))
-
-
-#define IOSAPIC_REG_SELECT              0
+#define IOSAPIC_REG_SELECT              0x00
 #define IOSAPIC_REG_WINDOW              0x10
 #define IOSAPIC_REG_EOI                 0x40
 
@@ -245,7 +234,6 @@ assert_failed (char *a, char *f, int l)
 #define IOSAPIC_IRDT_ENTRY_HI(idx)	(0x11+(idx)*2)
 
 /*
-** FIXME: revisit which GFP flags we should really be using.
 **     GFP_KERNEL includes __GFP_WAIT flag and that may not
 **     be acceptable. Since this is boot time, we shouldn't have
 **     to wait ever and this code should (will?) never get called
@@ -260,16 +248,13 @@ assert_failed (char *a, char *f, int l)
 #define	IOSAPIC_UNLOCK(lck)	spin_unlock_irqrestore(lck, irqflags)
 
 
-#define IOSAPIC_VERSION_MASK            0x000000ff
-#define IOSAPIC_VERSION_SHIFT           0x0
-#define	IOSAPIC_VERSION(ver)				\
-		(int) ((ver & IOSAPIC_VERSION_MASK) >> IOSAPIC_VERSION_SHIFT)
+#define IOSAPIC_VERSION_MASK	0x000000ff
+#define	IOSAPIC_VERSION(ver)	((int) (ver & IOSAPIC_VERSION_MASK))
 
 #define IOSAPIC_MAX_ENTRY_MASK          0x00ff0000
-
 #define IOSAPIC_MAX_ENTRY_SHIFT         0x10
-#define	IOSAPIC_IRDT_MAX_ENTRY(ver)			\
-		(int) ((ver&IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT)
+#define	IOSAPIC_IRDT_MAX_ENTRY(ver)	\
+	(int) (((ver) & IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT)
 
 /* bits in the "low" I/O Sapic IRdT entry */
 #define IOSAPIC_IRDT_ENABLE       0x10000
@@ -281,9 +266,6 @@ assert_failed (char *a, char *f, int l)
 #define IOSAPIC_IRDT_ID_EID_SHIFT              0x10
 
 
-
-#define	IOSAPIC_EOI(eoi_addr, eoi_data) gsc_writel(eoi_data, eoi_addr)
-
 static struct iosapic_info *iosapic_list;
 static spinlock_t iosapic_lock;
 static int iosapic_count;
@@ -403,14 +385,14 @@ iosapic_load_irt(unsigned long cell_num,
 	struct irt_entry *p = table;
 	int i;
 
-	printk(KERN_DEBUG MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
-	printk(KERN_DEBUG MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
+	printk(MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
+	printk(MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
 		table,
 		num_entries,
 		(int) sizeof(struct irt_entry));
 
 	for (i = 0 ; i < num_entries ; i++, p++) {
-		printk(KERN_DEBUG MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
+		printk(MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
 		p->entry_type, p->entry_length, p->interrupt_type,
 		p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id,
 		p->src_seg_id, p->dest_iosapic_intin,
@@ -608,22 +590,26 @@ iosapic_xlate_pin(struct iosapic_info *i
 static irqreturn_t
 iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
-	struct vector_info *vi = (struct vector_info *)dev_id;
+	struct vector_info *vi = (struct vector_info *) dev_id;
 	extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
 	int irq_num = vi->iosapic->isi_region->data.irqbase + vi->irqline;
 
-	DBG("iosapic_interrupt(): irq %d line %d eoi %p\n",
-		irq, vi->irqline, vi->eoi_addr);
+	DBG("iosapic_interrupt(): irq %d line %d eoi 0x%p 0x%x\n",
+		irq, vi->irqline, vi->eoi_addr, vi->eoi_data);
+
+	/* Do NOT need to mask/unmask IRQ. processor is already masked. */
 
-/* FIXME: Need to mask/unmask? processor IRQ is already masked... */
 	do_irq(&vi->iosapic->isi_region->action[vi->irqline], irq_num, regs);
 
 	/*
+	** PARISC only supports PCI devices below I/O SAPIC.
 	** PCI only supports level triggered in order to share IRQ lines.
-	** I/O SAPIC must always issue EOI.
+	** ergo I/O SAPIC must always issue EOI on parisc.
+	**
+	** i386/ia64 support ISA devices and have to deal with
+	** edge-triggered interrupts too.
 	*/
-	IOSAPIC_EOI(vi->eoi_addr, vi->eoi_data);
-
+	__raw_writel(vi->eoi_data, vi->eoi_addr);
 	return IRQ_HANDLED;
 }
 
@@ -715,8 +701,7 @@ iosapic_fixup_irq(void *isi_obj, struct 
 	ASSERT(tmp == 0);
 
 	vi->eoi_addr = (u32 *) (isi->isi_hpa + IOSAPIC_REG_EOI);
-	vi->eoi_data = cpu_to_le32(vi->irqline);
-
+	vi->eoi_data = cpu_to_le32(vi->txn_data);
 	ASSERT(NULL != isi->isi_region);
 
 	DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n",
@@ -734,12 +719,12 @@ iosapic_rd_irt_entry(struct vector_info 
 	u8 idx = vi->irqline;
 
 	/* point the window register to the lower word */
-	WRITE_U32(IOSAPIC_IRDT_ENTRY(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
-	*dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+	writel(IOSAPIC_IRDT_ENTRY(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
+	*dp0 = readl(isp->isi_hpa+IOSAPIC_REG_WINDOW);
 
 	/* point the window register to the higher word */
-	WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
-	*dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+	writel(IOSAPIC_IRDT_ENTRY_HI(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
+	*dp1 = readl(isp->isi_hpa+IOSAPIC_REG_WINDOW);
 }
 
 
@@ -750,24 +735,24 @@ iosapic_wr_irt_entry(struct vector_info 
 
 	ASSERT(NULL != isp);
 	ASSERT(0 != isp->isi_hpa);
-	DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p WINDOW %p  0x%x 0x%x\n",
+	DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p 0x%x 0x%x\n",
 		vi->irqline,
-		isp->isi_hpa, isp->isi_hpa+IOSAPIC_REG_WINDOW,
+		isp->isi_hpa,
 		dp0, dp1);
 
 	/* point the window register to the lower word */
-	WRITE_U32(IOSAPIC_IRDT_ENTRY(vi->irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
-	WRITE_U32( dp0, isp->isi_hpa+IOSAPIC_REG_WINDOW);
+	writel(IOSAPIC_IRDT_ENTRY(vi->irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
+	writel( dp0, isp->isi_hpa+IOSAPIC_REG_WINDOW);
 
 	/* Read the window register to flush the writes down to HW  */
-	dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+	dp0 = readl(isp->isi_hpa+IOSAPIC_REG_WINDOW);
 
 	/* point the window register to the higher word */
-	WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(vi->irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
-	WRITE_U32( dp1, isp->isi_hpa+IOSAPIC_REG_WINDOW);
+	writel(IOSAPIC_IRDT_ENTRY_HI(vi->irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
+	writel( dp1, isp->isi_hpa+IOSAPIC_REG_WINDOW);
 
 	/* Read the window register to flush the writes down to HW  */
-	dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+	dp1 = readl(isp->isi_hpa+IOSAPIC_REG_WINDOW);
 }
 
 
@@ -882,12 +867,12 @@ iosapic_enable_irq(void *dev, int irq)
 	iosapic_set_irt_data(vi, &d0, &d1);
 	iosapic_wr_irt_entry(vi, d0, d1);
 
-
 #ifdef DEBUG_IOSAPIC_IRT
 {
 	u32 *t = (u32 *) ((ulong) vi->eoi_addr & ~0xffUL);
 	printk("iosapic_enable_irq(): regs %p", vi->eoi_addr);
-	while (t < vi->eoi_addr) printk(" %x", READ_U32(t++));
+	for ( ; t < vi->eoi_addr; t++)
+		printk(" %x", readl(t));
 	printk("\n");
 }
 
@@ -897,10 +882,10 @@ printk("iosapic_enable_irq(): sel ");
 
 	for (d0=0x10; d0<0x1e; d0++) {
 		/* point the window register to the lower word */
-		WRITE_U32(d0, isp->isi_hpa+IOSAPIC_REG_SELECT);
+		writel(d0, isp->isi_hpa+IOSAPIC_REG_SELECT);
 
 		/* read the word */
-		d1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
+		d1 = readl(isp->isi_hpa+IOSAPIC_REG_WINDOW);
 		printk(" %x", d1);
 	}
 }
@@ -908,13 +893,12 @@ printk("\n");
 #endif
 
 	/*
-	** KLUGE: IRQ should not be asserted when Drivers enabling their IRQ.
-	**        PCI supports level triggered in order to share IRQ lines.
-	**
-	** Issueing I/O SAPIC an EOI causes an interrupt iff IRQ line is
-	** asserted.
+	** Issueing I/O SAPIC an EOI causes an interrupt IFF IRQ line is
+	** asserted.  IRQ generally should not be asserted when a driver
+	** enables their IRQ. It can lead to "interesting" race conditions
+	** in the driver initialization sequence.
 	*/
-	IOSAPIC_EOI(vi->eoi_addr, vi->eoi_data);
+	__raw_writel(vi->eoi_data, vi->eoi_addr);
 }
 
 
@@ -950,10 +934,10 @@ iosapic_rd_version(struct iosapic_info *
 	ASSERT(isi->isi_hpa);
 
 	/* point window to the version register */
-	WRITE_U32(IOSAPIC_REG_VERSION, isi->isi_hpa+IOSAPIC_REG_SELECT);
+	writel(IOSAPIC_REG_VERSION, isi->isi_hpa+IOSAPIC_REG_SELECT);
 
 	/* now read the version register */
-	return (READ_U32(isi->isi_hpa+IOSAPIC_REG_WINDOW));
+	return (readl(isi->isi_hpa+IOSAPIC_REG_WINDOW));
 }
 
 
Index: drivers/parisc/lba_pci.c
===================================================================
RCS file: /var/cvs/linux-2.6/drivers/parisc/lba_pci.c,v
retrieving revision 1.11
diff -u -p -r1.11 lba_pci.c
--- drivers/parisc/lba_pci.c	30 May 2004 18:57:23 -0000	1.11
+++ drivers/parisc/lba_pci.c	4 Jun 2004 06:27:08 -0000
@@ -42,6 +42,7 @@
 #include <asm/byteorder.h>
 #include <asm/irq.h>		/* for struct irq_region support */
 #include <asm/pdc.h>
+#include <asm/pdcpat.h>
 #include <asm/page.h>
 #include <asm/segment.h>
 #include <asm/system.h>
@@ -171,6 +172,8 @@
 #define LBA_HINT_CFG	0x0310
 #define LBA_HINT_BASE	0x0380	/* 14 registers at every 8 bytes. */
 
+#define LBA_BUS_MODE	0x0620
+
 /* ERROR regs are needed for config cycle kluges */
 #define LBA_ERROR_CONFIG 0x0680
 #define     LBA_SMART_MODE 0x20
@@ -180,12 +183,31 @@
 #define LBA_IOSAPIC_BASE	0x800 /* Offset of IRQ logic */
 
 /* non-postable I/O port space, densely packed */
-#ifdef __LP64__
+#ifdef CONFIG_PARISC64
 #define LBA_ASTRO_PORT_BASE	(0xfffffffffee00000UL)
 #else
 #define LBA_ASTRO_PORT_BASE	(0xfee00000UL)
 #endif
 
+#define ELROY_HVERS	0x782
+#define MERCURY_HVERS	0x783
+#define QUICKSILVER_HVERS	0x784
+
+static inline int IS_ELROY(struct parisc_device *d)
+{
+	return (d->id.hversion == ELROY_HVERS);
+}
+
+static inline int IS_MERCURY(struct parisc_device *d)
+{
+	return (d->id.hversion == MERCURY_HVERS);
+}
+
+static inline int IS_QUICKSILVER(struct parisc_device *d)
+{
+	return (d->id.hversion == QUICKSILVER_HVERS);
+}
+
 
 /*
 ** lba_device: Per instance Elroy data structure
@@ -196,7 +218,7 @@ struct lba_device {
 	spinlock_t	lba_lock;
 	void		*iosapic_obj;
 
-#ifdef __LP64__
+#ifdef CONFIG_PARISC64
 	unsigned long	iop_base;    /* PA_VIEW - for IO port accessor funcs */
 #endif
 
@@ -300,11 +322,6 @@ lba_device_present( u8 bus, u8 dfn, stru
 {
 	u8 first_bus = d->hba.hba_bus->secondary;
 	u8 last_sub_bus = d->hba.hba_bus->subordinate;
-#if 0
-/* FIXME - see below in this function */
-        u8 dev = PCI_SLOT(dfn);
-        u8 func = PCI_FUNC(dfn);
-#endif
 
 	ASSERT(bus >= first_bus);
 	ASSERT(bus <= last_sub_bus);
@@ -318,19 +335,7 @@ lba_device_present( u8 bus, u8 dfn, stru
 	    return(FALSE);
 	}
 
-#if 0
-/*
-** FIXME: Need to implement code to fill the devices bitmap based
-** on contents of the local pci_bus tree "data base".
-** pci_register_ops() walks the bus for us and builds the tree.
-** For now, always do the config cycle.
-*/
-	bus -= first_bus;
-
-	return (((d->devices[bus][dev]) >> func) & 0x1);
-#else
 	return TRUE;
-#endif
 }
 
 
@@ -515,6 +520,43 @@ lba_rd_cfg(struct lba_device *d, u32 tok
 	return(data);
 }
 
+#ifdef CONFIG_PARISC64
+#define pat_cfg_addr(bus, devfn, addr) (((bus) << 16) | ((devfn) << 8) | (addr))
+
+static int pat_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
+{
+	int tok = pat_cfg_addr(bus->number, devfn, pos);
+	u32 tmp;
+	int ret = pdc_pat_io_pci_cfg_read(tok, size, &tmp);
+
+	DBG_CFG("%s(%d:%d.%d+0x%02x) -> 0x%x %d\n", __FUNCTION__, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), pos, tmp, ret);
+
+	switch (size) {
+		case 1: *data = (u8)  tmp; return (tmp == (u8)  ~0);
+		case 2: *data = (u16) tmp; return (tmp == (u16) ~0);
+		case 4: *data = (u32) tmp; return (tmp == (u32) ~0);
+	}
+	*data = ~0;
+	return (ret);
+}
+
+static int pat_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
+{
+	int tok = pat_cfg_addr(bus->number, devfn, pos);
+	int ret = pdc_pat_io_pci_cfg_write(tok, size, data);
+
+	DBG_CFG("%s(%d:%d.%d+0x%02x, 0x%lx/%d)\n", __FUNCTION__, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), pos, data, size);
+	return (ret);
+}
+
+static struct pci_ops pat_cfg_ops = {
+	.read =		pat_cfg_read,
+	.write =	pat_cfg_write,
+};
+#else
+/* keep the compiler from complaining about undeclared variables */
+#define pat_cfg_ops lba_cfg_ops
+#endif
 
 static int lba_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
 {
@@ -622,6 +664,7 @@ static int lba_cfg_write(struct pci_bus 
 	}
 
 	DBG_CFG("%s(%x+%2x) = 0x%x (c)\n", __FUNCTION__, tok, pos, data);
+
 	/* Basic Algorithm */
 	LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
 	switch(size) {
@@ -651,7 +694,7 @@ lba_bios_init(void)
 }
 
 
-#ifdef __LP64__
+#ifdef CONFIG_PARISC64
 
 /*
 ** Determine if a device is already configured.
@@ -689,6 +732,8 @@ lba_claim_dev_resources(struct pci_dev *
 		}
 	}
 }
+#else
+#define lba_claim_dev_resources(dev)
 #endif
 
 
@@ -746,7 +791,7 @@ lba_fixup_bus(struct pci_bus *bus)
 			lba_dump_res(&iomem_resource, 2);
 		}
 
-#ifdef __LP64__
+#ifdef CONFIG_PARISC64
 		if (ldev->hba.gmmio_space.flags) {
 			err = request_resource(&iomem_resource, &(ldev->hba.gmmio_space));
 			if (err < 0) {
@@ -804,12 +849,10 @@ lba_fixup_bus(struct pci_bus *bus)
 		bus->bridge_ctl &= ~(status & PCI_STATUS_FAST_BACK);
 #endif
 
-#ifdef __LP64__
 		if (is_pdc_pat()) {
 			/* Claim resources for PDC's devices */
 			lba_claim_dev_resources(dev);
 		}
-#endif
 
                 /*
 		** P2PB's have no IRQs. ignore them.
@@ -937,7 +980,7 @@ static struct pci_port_ops lba_astro_por
 };
 
 
-#ifdef __LP64__
+#ifdef CONFIG_PARISC64
 #define PIOP_TO_GMMIO(lba, addr) \
 	((lba)->iop_base + (((addr)&0xFFFC)<<10) + ((addr)&3))
 
@@ -1105,7 +1148,11 @@ lba_pat_resources(struct parisc_device *
 		}
 	}
 }
-#endif	/* __LP64__ */
+#else
+/* keep compiler from complaining about missing declarations */
+#define lba_pat_port_ops lba_astro_port_ops
+#define lba_pat_resources(pa_dev, lba_dev)
+#endif	/* CONFIG_PARISC64 */
 
 
 static void
@@ -1115,7 +1162,7 @@ lba_legacy_resources(struct parisc_devic
 	unsigned long rsize;
 	int lba_num;
 
-#ifdef __LP64__
+#ifdef CONFIG_PARISC64
 	/*
 	** Sign extend all BAR values on "legacy" platforms.
 	** "Sprockets" PDC (Forte/Allegro) initializes everything
@@ -1249,7 +1296,7 @@ lba_hw_init(struct lba_device *d)
 	printk("\n");
 #endif	/* DEBUG_LBA_PAT */
 
-#ifdef __LP64__
+#ifdef CONFIG_PARISC64
 /*
  * FIXME add support for PDC_PAT_IO "Get slot status" - OLAR support
  * Only N-Class and up can really make use of Get slot status.
@@ -1329,7 +1376,7 @@ lba_common_init(struct lba_device *lba_d
 ** have work to do.
 */
 static int __init
-lba_driver_callback(struct parisc_device *dev)
+lba_driver_probe(struct parisc_device *dev)
 {
 	struct lba_device *lba_dev;
 	struct pci_bus *lba_bus;
@@ -1339,25 +1386,36 @@ lba_driver_callback(struct parisc_device
 
 	/* Read HW Rev First */
 	func_class = READ_REG32(dev->hpa + LBA_FCLASS);
-	func_class &= 0xf;
 
-	switch (func_class) {
-	case 0:	version = "TR1.0"; break;
-	case 1:	version = "TR2.0"; break;
-	case 2:	version = "TR2.1"; break;
-	case 3:	version = "TR2.2"; break;
-	case 4:	version = "TR3.0"; break;
-	case 5:	version = "TR4.0"; break;
-	default: version = "TR4+";
-	}
+	if (IS_ELROY(dev)) {	
+		func_class &= 0xf;
+		switch (func_class) {
+		case 0:	version = "TR1.0"; break;
+		case 1:	version = "TR2.0"; break;
+		case 2:	version = "TR2.1"; break;
+		case 3:	version = "TR2.2"; break;
+		case 4:	version = "TR3.0"; break;
+		case 5:	version = "TR4.0"; break;
+		default: version = "TR4+";
+		}
+		printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
+			MODULE_NAME, version, func_class & 0xf, dev->hpa);
 
-	printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
-		MODULE_NAME, version, func_class & 0xf, dev->hpa);
+		/* Just in case we find some prototypes... */
+	} else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) {
+		func_class &= 0xff;
+		version = kmalloc(6, GFP_KERNEL);
+		sprintf(version,"TR%d.%d",(func_class >> 4),(func_class & 0xf));
+		/* We could use one printk for both and have it outside,
+                 * but for the mask for func_class.
+                 */ 
+		printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
+			MODULE_NAME, version, func_class & 0xff, dev->hpa);
+	}
 
-	/* Just in case we find some prototypes... */
 	if (func_class < 2) {
-		printk(KERN_WARNING "Can't support LBA older than TR2.1 "
-			"- continuing under adversity.\n");
+		printk(KERN_WARNING "Can't support LBA older than TR2.1"
+				" - continuing under adversity.\n");
 	}
 
 	/*
@@ -1400,16 +1458,12 @@ lba_driver_callback(struct parisc_device
 
 	/* ---------- Third : setup I/O Port and MMIO resources  --------- */
 
-#ifdef __LP64__
 	if (is_pdc_pat()) {
 		/* PDC PAT firmware uses PIOP region of GMMIO space. */
 		pci_port = &lba_pat_port_ops;
-
 		/* Go ask PDC PAT what resources this LBA has */
 		lba_pat_resources(dev, lba_dev);
-	} else
-#endif
-	{
+	} else {
 		/* Sprockets PDC uses NPIOP region */
 		pci_port = &lba_astro_port_ops;
 
@@ -1424,9 +1478,9 @@ lba_driver_callback(struct parisc_device
 	dev->dev.platform_data = lba_dev;
 	lba_bus = lba_dev->hba.hba_bus =
 		pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start,
-				      &lba_cfg_ops, NULL);
+				is_pdc_pat() ? &pat_cfg_ops : &lba_cfg_ops,
+				NULL);
 
-#ifdef __LP64__
 	if (is_pdc_pat()) {
 		/* assign resources to un-initialized devices */
 		DBG_PAT("LBA pci_bus_assign_resources()\n");
@@ -1439,7 +1493,6 @@ lba_driver_callback(struct parisc_device
 		lba_dump_res(&lba_dev->hba.lmmio_space, 2);
 #endif
 	}
-#endif
 
 	/*
 	** Once PCI register ops has walked the bus, access to config
@@ -1455,14 +1508,16 @@ lba_driver_callback(struct parisc_device
 }
 
 static struct parisc_device_id lba_tbl[] = {
-	{ HPHW_BRIDGE, HVERSION_REV_ANY_ID, 0x782, 0xa },
+	{ HPHW_BRIDGE, HVERSION_REV_ANY_ID, ELROY_HVERS, 0xa },
+	{ HPHW_BRIDGE, HVERSION_REV_ANY_ID, MERCURY_HVERS, 0xa },
+	{ HPHW_BRIDGE, HVERSION_REV_ANY_ID, QUICKSILVER_HVERS, 0xa },
 	{ 0, }
 };
 
 static struct parisc_driver lba_driver = {
 	.name =		MODULE_NAME,
 	.id_table =	lba_tbl,
-	.probe =	lba_driver_callback,
+	.probe =	lba_driver_probe,
 };
 
 /*
Index: drivers/parisc/sba_iommu.c
===================================================================
RCS file: /var/cvs/linux-2.6/drivers/parisc/sba_iommu.c,v
retrieving revision 1.10
diff -u -p -r1.10 sba_iommu.c
--- drivers/parisc/sba_iommu.c	30 May 2004 18:57:23 -0000	1.10
+++ drivers/parisc/sba_iommu.c	4 Jun 2004 06:27:08 -0000
@@ -38,8 +38,13 @@
 #include <linux/proc_fs.h>
 #include <asm/runway.h>		/* for proc_runway_root */
 #include <asm/pdc.h>		/* for PDC_MODEL_* */
+#include <asm/pdcpat.h>		/* for is_pdc_pat() */
 #include <asm/parisc-device.h>
 
+
+/* declared in arch/parisc/kernel/setup.c */
+extern struct proc_dir_entry * proc_mckinley_root;
+
 #define MODULE_NAME "SBA"
 
 #ifdef CONFIG_PROC_FS
@@ -61,8 +66,6 @@
 #undef DEBUG_LARGE_SG_ENTRIES
 #undef DEBUG_DMB_TRAP
 
-#define SBA_INLINE	__inline__
-
 #ifdef DEBUG_SBA_INIT
 #define DBG_INIT(x...)	printk(x)
 #else
@@ -101,6 +104,14 @@
 #endif
 
 
+#if defined(__LP64__) && !defined(CONFIG_PDC_NARROW)
+/* "low end" PA8800 machines use ZX1 chipset */
+#define ZX1_SUPPORT
+#endif
+
+#define SBA_INLINE	__inline__
+
+
 /*
 ** The number of pdir entries to "free" before issueing
 ** a read to PCOM register to flush out PCOM writes.
@@ -124,6 +135,9 @@
 #define REOG_MERCED_PORT	0x805
 #define REOG_ROPES_PORT		0x783
 
+#define PLUTO_MCKINLEY_PORT	0x880
+#define PLUTO_ROPES_PORT	0x784
+
 #define SBA_FUNC_ID	0x0000	/* function id */
 #define SBA_FCLASS	0x0008	/* function class, bist, header, rev... */
 
@@ -133,12 +147,17 @@
 #define IS_IKE(id) \
 (((id)->hversion == IKE_MERCED_PORT) || ((id)->hversion == IKE_ROPES_PORT))
 
+#define IS_PLUTO(id) \
+(((id)->hversion == PLUTO_MCKINLEY_PORT) || ((id)->hversion == PLUTO_ROPES_PORT))
+
 #define SBA_FUNC_SIZE 4096   /* SBA configuration function reg set */
 
 #define ASTRO_IOC_OFFSET 0x20000
 /* Ike's IOC's occupy functions 2 and 3 (not 0 and 1) */
 #define IKE_IOC_OFFSET(p) ((p+2)*SBA_FUNC_SIZE)
 
+#define PLUTO_IOC_OFFSET 0x1000
+
 #define IOC_CTRL          0x8	/* IOC_CTRL offset */
 #define IOC_CTRL_TC       (1 << 0) /* TOC Enable */
 #define IOC_CTRL_CE       (1 << 1) /* Coalesce Enable */
@@ -146,7 +165,7 @@
 #define IOC_CTRL_RM       (1 << 8) /* Real Mode */
 #define IOC_CTRL_NC       (1 << 9) /* Non Coherent Mode */
 
-#define MAX_IOC		2	/* per Ike. Astro only has 1 */
+#define MAX_IOC		2	/* per Ike. Pluto/Astro only have 1. */
 
 
 /*
@@ -182,7 +201,9 @@
 #define IOC_TCNFG	0x318
 #define IOC_PDIR_BASE	0x320
 
-#define IOC_IOVA_SPACE_BASE	0	/* IOVA ranges start at 0 */
+/* AGP GART driver looks for this */
+#define SBA_IOMMU_COOKIE    0x0000badbadc0ffeeUL
+
 
 /*
 ** IOC supports 4/8/16/64KB page sizes (see TCNFG register)
@@ -193,9 +214,7 @@
 ** page since the Virtual Coherence Index has to be generated
 ** and updated for each page.
 **
-** IOVP_SIZE could only be greater than PAGE_SIZE if we are
-** confident the drivers really only touch the next physical
-** page iff that driver instance owns it.
+** PAGE_SIZE could be greater than IOVP_SIZE. But not the inverse.
 */
 #define IOVP_SIZE	PAGE_SIZE
 #define IOVP_SHIFT	PAGE_SHIFT
@@ -219,13 +238,20 @@ struct ioc {
 	unsigned long	ioc_hpa;	/* I/O MMU base address */
 	char	*res_map;	/* resource map, bit == pdir entry */
 	u64	*pdir_base;	/* physical base address */
-
+	unsigned long	ibase;	/* pdir IOV Space base - shared w/lba_pci */
+	unsigned long	imask;	/* pdir IOV Space mask - shared w/lba_pci */
+#ifdef ZX1_SUPPORT
+	unsigned long	iovp_mask;	/* help convert IOVA to IOVP */
+#endif
 	unsigned long	*res_hint;	/* next avail IOVP - circular search */
 	spinlock_t	res_lock;
-	unsigned long	hint_mask_pdir;	/* bits used for DMA hints */
 	unsigned int	res_bitshift;	/* from the LEFT! */
 	unsigned int	res_size;	/* size of resource map in bytes */
+#if SBA_HINT_SUPPORT
+/* FIXME : DMA HINTs not used */
+	unsigned long	hint_mask_pdir;	/* bits used for DMA hints */
 	unsigned int	hint_shift_pdir;
+#endif
 #if DELAYED_RESOURCE_CNT > 0
 	int saved_cnt;
 	struct sba_dma_pair {
@@ -251,8 +277,6 @@ struct ioc {
 
 	/* STUFF We don't need in performance path */
 	unsigned int	pdir_size;	/* in bytes, determined by IOV Space size */
-	unsigned long	ibase;		/* pdir IOV Space base - shared w/lba_pci */
-	unsigned long	imask;		/* pdir IOV Space mask - shared w/lba_pci */
 };
 
 struct sba_device {
@@ -286,6 +310,9 @@ static unsigned long piranha_bad_128k = 
 /* Looks nice and keeps the compiler happy */
 #define SBA_DEV(d) ((struct sba_device *) (d))
 
+#if SBA_AGP_SUPPORT
+static int reserve_sba_gart = 1;
+#endif
 
 #define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1))
 
@@ -345,12 +372,15 @@ static void
 sba_dump_tlb(unsigned long hpa)
 {
 	DBG_INIT("IO TLB at 0x%lx\n", hpa);
-	DBG_INIT("IOC_IBASE    : %Lx\n", READ_REG64(hpa+IOC_IBASE));
-	DBG_INIT("IOC_IMASK    : %Lx\n", READ_REG64(hpa+IOC_IMASK));
-	DBG_INIT("IOC_TCNFG    : %Lx\n", READ_REG64(hpa+IOC_TCNFG));
-	DBG_INIT("IOC_PDIR_BASE: %Lx\n", READ_REG64(hpa+IOC_PDIR_BASE));
+	DBG_INIT("IOC_IBASE    : 0x%Lx\n", READ_REG64(hpa+IOC_IBASE));
+	DBG_INIT("IOC_IMASK    : 0x%Lx\n", READ_REG64(hpa+IOC_IMASK));
+	DBG_INIT("IOC_TCNFG    : 0x%Lx\n", READ_REG64(hpa+IOC_TCNFG));
+	DBG_INIT("IOC_PDIR_BASE: 0x%Lx\n", READ_REG64(hpa+IOC_PDIR_BASE));
 	DBG_INIT("\n");
 }
+#else
+#define sba_dump_ranges(x)
+#define sba_dump_tlb(x)
 #endif
 
 
@@ -470,13 +500,18 @@ sba_dump_sg( struct ioc *ioc, struct sca
 #define PAGES_PER_RANGE 1	/* could increase this to 4 or 8 if needed */
 
 /* Convert from IOVP to IOVA and vice versa. */
-#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((iovp) | (offset) | ((hint_reg)<<(ioc->hint_shift_pdir)))
-#define SBA_IOVP(ioc,iova) ((iova) & ioc->hint_mask_pdir)
 
-/* FIXME : review these macros to verify correctness and usage */
+#ifdef ZX1_SUPPORT
+/* Pluto (aka ZX1) boxes need to set or clear the ibase bits appropriately */
+#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset))
+#define SBA_IOVP(ioc,iova) ((iova) & (ioc)->iovp_mask)
+#else
+/* only support Astro and ancestors. Saves a few cycles in key places */
+#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((iovp) | (offset))
+#define SBA_IOVP(ioc,iova) (iova)
+#endif
+
 #define PDIR_INDEX(iovp)   ((iovp)>>IOVP_SHIFT)
-#define MKIOVP(dma_hint,pide)  (dma_addr_t)((long)(dma_hint) | ((long)(pide) << IOVP_SHIFT))
-#define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset)
 
 #define RESMAP_MASK(n)    (~0UL << (BITS_PER_LONG - (n)))
 #define RESMAP_IDX_MASK   (sizeof(unsigned long) - 1)
@@ -673,8 +708,9 @@ sba_free_range(struct ioc *ioc, dma_addr
 *
 ***************************************************************/
 
+#if SBA_HINT_SUPPORT
 #define SBA_DMA_HINT(ioc, val) ((val) << (ioc)->hint_shift_pdir)
-
+#endif
 
 typedef unsigned long space_t;
 #define KERNEL_SPACE 0
@@ -689,25 +725,33 @@ typedef unsigned long space_t;
  *
  * Given a virtual address (vba, arg2) and space id, (sid, arg1)
  * sba_io_pdir_entry() loads the I/O PDIR entry pointed to by
- * pdir_ptr (arg0). Each IO Pdir entry consists of 8 bytes as
- * shown below (MSB == bit 0):
+ * pdir_ptr (arg0). 
+ * Using the bass-ackwards HP bit numbering, Each IO Pdir entry
+ * for Astro/Ike looks like:
+ *
  *
  *  0                    19                                 51   55       63
  * +-+---------------------+----------------------------------+----+--------+
  * |V|        U            |            PPN[43:12]            | U  |   VI   |
  * +-+---------------------+----------------------------------+----+--------+
  *
- *  V  == Valid Bit
+ * Pluto is basically identical, supports fewer physical address bits:
+ *
+ *  0                       23                              51   55       63
+ * +-+------------------------+-------------------------------+----+--------+
+ * |V|        U               |         PPN[39:12]            | U  |   VI   |
+ * +-+------------------------+-------------------------------+----+--------+
+ *
+ *  V  == Valid Bit  (Most Significant Bit is bit 0)
  *  U  == Unused
  * PPN == Physical Page Number
  * VI  == Virtual Index (aka Coherent Index)
  *
- * The physical address fields are filled with the results of the LPA
- * instruction.  The virtual index field is filled with the results of
- * of the LCI (Load Coherence Index) instruction.  The 8 bits used for
- * the virtual index are bits 12:19 of the value returned by LCI.
+ * LPA instruction output is put into PPN field.
+ * LCI (Load Coherence Index) instruction provides the "VI" bits.
  *
- * We need to pre-swap the bytes since PCX-W is Big Endian.
+ * We pre-swap the bytes since PCX-W is Big Endian and the
+ * IOMMU uses little endian for the pdir.
  */
 
 
@@ -812,7 +856,7 @@ sba_mark_invalid(struct ioc *ioc, dma_ad
 		} while (byte_cnt > 0);
 	}
 
-	WRITE_REG(iovp, ioc->ioc_hpa+IOC_PCOM);
+	WRITE_REG( SBA_IOVA(ioc, iovp, 0, 0), ioc->ioc_hpa+IOC_PCOM);
 }
 
 /**
@@ -880,7 +924,7 @@ sba_map_single(struct device *dev, void 
 	pide = sba_alloc_range(ioc, size);
 	iovp = (dma_addr_t) pide << IOVP_SHIFT;
 
-	DBG_RUN("%s() 0x%p -> 0x%lx",
+	DBG_RUN("%s() 0x%p -> 0x%lx\n",
 		__FUNCTION__, addr, (long) iovp | offset);
 
 	pdir_start = &(ioc->pdir_base[pide]);
@@ -889,7 +933,7 @@ sba_map_single(struct device *dev, void 
 		ASSERT(((u8 *)pdir_start)[7] == 0); /* verify availability */
 		sba_io_pdir_entry(pdir_start, KERNEL_SPACE, (unsigned long) addr, 0);
 
-		DBG_RUN(" pdir 0x%p %02x%02x%02x%02x%02x%02x%02x%02x\n",
+		DBG_RUN("	pdir 0x%p %02x%02x%02x%02x%02x%02x%02x%02x\n",
 			pdir_start,
 			(u8) (((u8 *) pdir_start)[7]),
 			(u8) (((u8 *) pdir_start)[6]),
@@ -953,14 +997,18 @@ sba_unmap_single(struct device *dev, dma
 	ioc->usingle_pages += size >> IOVP_SHIFT;
 #endif
 
+	sba_mark_invalid(ioc, iova, size);
+
 #if DELAYED_RESOURCE_CNT > 0
+	/* Delaying when we re-use a IO Pdir entry reduces the number
+	 * of MMIO reads needed to flush writes to the PCOM register.
+	 */
 	d = &(ioc->saved[ioc->saved_cnt]);
 	d->iova = iova;
 	d->size = size;
 	if (++(ioc->saved_cnt) >= DELAYED_RESOURCE_CNT) {
 		int cnt = ioc->saved_cnt;
 		while (cnt--) {
-			sba_mark_invalid(ioc, d->iova, d->size);
 			sba_free_range(ioc, d->iova, d->size);
 			d--;
 		}
@@ -968,7 +1016,6 @@ sba_unmap_single(struct device *dev, dma
 		READ_REG(ioc->ioc_hpa+IOC_PCOM);	/* flush purges */
 	}
 #else /* DELAYED_RESOURCE_CNT == 0 */
-	sba_mark_invalid(ioc, iova, size);
 	sba_free_range(ioc, iova, size);
 	READ_REG(ioc->ioc_hpa+IOC_PCOM);	/* flush purges */
 #endif /* DELAYED_RESOURCE_CNT == 0 */
@@ -1333,6 +1380,142 @@ sba_alloc_pdir(unsigned int pdir_size)
 	return (void *) pdir_base;
 }
 
+static void
+sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
+{
+        /* lba_set_iregs() is in arch/parisc/kernel/lba_pci.c */
+        extern void lba_set_iregs(struct parisc_device *, u32, u32);
+
+	u32 iova_space_mask;
+	u32 iova_space_size;
+	int iov_order, tcnfg;
+	struct parisc_device *lba;
+#if SBA_AGP_SUPPORT
+	int agp_found = 0;
+#endif
+	/*
+	** Firmware programs the base and size of a "safe IOVA space"
+	** (one that doesn't overlap memory or LMMIO space) in the
+	** IBASE and IMASK registers.
+	*/
+	ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE);
+	iova_space_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1;
+
+	if ((ioc->ibase < 0xfed00000UL) && ((ioc->ibase + iova_space_size) > 0xfee00000UL)) {
+		printk("WARNING: IOV space overlaps local config and interrupt message, truncating\n");
+		iova_space_size /= 2;
+	}
+
+	/*
+	** iov_order is always based on a 1GB IOVA space since we want to
+	** turn on the other half for AGP GART.
+	*/
+	iov_order = get_order(iova_space_size >> (IOVP_SHIFT - PAGE_SHIFT));
+	ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64);
+
+	DBG_INIT("%s() hpa 0x%lx IOV %dMB (%d bits)\n",
+		__FUNCTION__, ioc->ioc_hpa, iova_space_size >> 20,
+		iov_order + PAGE_SHIFT);
+
+	ioc->pdir_base = (void *) __get_free_pages(GFP_KERNEL,
+						   get_order(ioc->pdir_size));
+	if (!ioc->pdir_base)
+		panic("Couldn't allocate I/O Page Table\n");
+
+	memset(ioc->pdir_base, 0, ioc->pdir_size);
+
+	DBG_INIT("%s() pdir %p size %x\n",
+			__FUNCTION__, ioc->pdir_base, ioc->pdir_size);
+
+#if SBA_HINT_SUPPORT
+	ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
+	ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
+
+	DBG_INIT("	hint_shift_pdir %x hint_mask_pdir %lx\n",
+		ioc->hint_shift_pdir, ioc->hint_mask_pdir);
+#endif
+
+	ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base);
+	WRITE_REG(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE);
+
+	/* build IMASK for IOC and Elroy */
+	iova_space_mask =  0xffffffff;
+	iova_space_mask <<= (iov_order + PAGE_SHIFT);
+	ioc->imask = iova_space_mask;
+#ifdef ZX1_SUPPORT
+	ioc->iovp_mask = ~(iova_space_mask + PAGE_SIZE - 1);
+#endif
+	sba_dump_tlb(ioc->ioc_hpa);
+
+	/*
+	** setup Mercury IBASE/IMASK registers as well.
+	*/
+	for (lba = sba->child; lba; lba = lba->sibling) {
+		int rope_num = (lba->hpa >> 13) & 0xf;
+		if (rope_num >> 3 == ioc_num)
+			lba_set_iregs(lba, ioc->ibase, ioc->imask);
+	}
+
+	WRITE_REG(ioc->imask, ioc->ioc_hpa + IOC_IMASK);
+
+#ifdef __LP64__
+	/*
+	** Setting the upper bits makes checking for bypass addresses
+	** a little faster later on.
+	*/
+	ioc->imask |= 0xFFFFFFFF00000000UL;
+#endif
+
+	/* Set I/O PDIR Page size to system page size */
+	switch (PAGE_SHIFT) {
+		case 12: tcnfg = 0; break;	/*  4K */
+		case 13: tcnfg = 1; break;	/*  8K */
+		case 14: tcnfg = 2; break;	/* 16K */
+		case 16: tcnfg = 3; break;	/* 64K */
+		default:
+			panic(__FILE__ "Unsupported system page size %d",
+				1 << PAGE_SHIFT);
+			break;
+	}
+	WRITE_REG(tcnfg, ioc->ioc_hpa + IOC_TCNFG);
+
+	/*
+	** Program the IOC's ibase and enable IOVA translation
+	** Bit zero == enable bit.
+	*/
+	WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa + IOC_IBASE);
+
+	/*
+	** Clear I/O TLB of any possible entries.
+	** (Yes. This is a bit paranoid...but so what)
+	*/
+	WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM);
+
+#if SBA_AGP_SUPPORT
+	/*
+	** If an AGP device is present, only use half of the IOV space
+	** for PCI DMA.  Unfortunately we can't know ahead of time
+	** whether GART support will actually be used, for now we
+	** can just key on any AGP device found in the system.
+	** We program the next pdir index after we stop w/ a key for
+	** the GART code to handshake on.
+	*/
+	device=NULL;
+	for (lba = sba->child; lba; lba = lba->sibling) {
+		if (IS_QUICKSILVER(lba))
+			break;
+	}
+
+	if (lba) {
+		DBG_INIT("%s: Reserving half of IOVA space for AGP GART support\n", __FUNCTION__);
+		ioc->pdir_size /= 2;
+		((u64 *)ioc->pdir_base)[PDIR_INDEX(iova_space_size/2)] = SBA_IOMMU_COOKIE;
+	} else {
+		DBG_INIT("%s: No GART needed - no AGP controller found\n", __FUNCTION__);
+	}
+#endif /* 0 */
+
+}
 
 static void
 sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
@@ -1393,15 +1576,19 @@ sba_ioc_init(struct parisc_device *sba, 
 		__FUNCTION__, ioc->ioc_hpa, (int) (physmem>>20),
 		iova_space_size>>20, iov_order + PAGE_SHIFT, pdir_size);
 
+	ioc->pdir_base = sba_alloc_pdir(pdir_size);
+
+	DBG_INIT("%s() pdir %p size %x\n",
+			__FUNCTION__, ioc->pdir_base, pdir_size);
+
+#if SBA_HINT_SUPPORT
 	/* FIXME : DMA HINTs not used */
 	ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
 	ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
 
-	ioc->pdir_base = sba_alloc_pdir(pdir_size);
-
-	DBG_INIT("%s() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n",
-		__FUNCTION__, ioc->pdir_base, pdir_size,
-		ioc->hint_shift_pdir, ioc->hint_mask_pdir);
+	DBG_INIT("	hint_shift_pdir %x hint_mask_pdir %lx\n",
+			ioc->hint_shift_pdir, ioc->hint_mask_pdir);
+#endif
 
 	ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base);
 	WRITE_REG64(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE);
@@ -1414,8 +1601,11 @@ sba_ioc_init(struct parisc_device *sba, 
 	** On C3000 w/512MB mem, HP-UX 10.20 reports:
 	**     ibase=0, imask=0xFE000000, size=0x2000000.
 	*/
-	ioc->ibase = IOC_IOVA_SPACE_BASE | 1;	/* bit 0 == enable bit */
+	ioc->ibase = 0;
 	ioc->imask = iova_space_mask;	/* save it */
+#ifdef ZX1_SUPPORT
+	ioc->iovp_mask = ~(iova_space_mask + PAGE_SIZE - 1);
+#endif
 
 	DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n",
 		__FUNCTION__, ioc->ibase, ioc->imask);
@@ -1438,7 +1628,7 @@ sba_ioc_init(struct parisc_device *sba, 
 	/*
 	** Program the IOC's ibase and enable IOVA translation
 	*/
-	WRITE_REG(ioc->ibase, ioc->ioc_hpa+IOC_IBASE);
+	WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa+IOC_IBASE);
 	WRITE_REG(ioc->imask, ioc->ioc_hpa+IOC_IMASK);
 
 	/* Set I/O PDIR Page size to 4K */
@@ -1450,6 +1640,8 @@ sba_ioc_init(struct parisc_device *sba, 
 	*/
 	WRITE_REG(0 | 31, ioc->ioc_hpa+IOC_PCOM);
 
+	ioc->ibase = 0; /* used by SBA_IOVA and related macros */	
+
 	DBG_INIT("%s() DONE\n", __FUNCTION__);
 }
 
@@ -1488,23 +1680,32 @@ sba_hw_init(struct sba_device *sba_dev)
 		*/
 	}
 
-	ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL);
-	DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->",
-		__FUNCTION__, sba_dev->sba_hpa, ioc_ctl);
-	ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC | IOC_CTRL_CE);
-	ioc_ctl |= IOC_CTRL_TC;	/* Astro: firmware enables this */
+	if (!IS_PLUTO(sba_dev->iodc)) {
+		ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL);
+		DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->",
+			__FUNCTION__, sba_dev->sba_hpa, ioc_ctl);
+		ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC | IOC_CTRL_CE);
+		ioc_ctl |= IOC_CTRL_TC;	/* Astro: firmware enables this */
 
-	WRITE_REG(ioc_ctl, sba_dev->sba_hpa+IOC_CTRL);
+		WRITE_REG(ioc_ctl, sba_dev->sba_hpa+IOC_CTRL);
 
 #ifdef DEBUG_SBA_INIT
-	ioc_ctl = READ_REG64(sba_dev->sba_hpa+IOC_CTRL);
-	DBG_INIT(" 0x%Lx\n", ioc_ctl);
+		ioc_ctl = READ_REG64(sba_dev->sba_hpa+IOC_CTRL);
+		DBG_INIT(" 0x%Lx\n", ioc_ctl);
 #endif
+	} /* if !PLUTO */
 
 	if (IS_ASTRO(sba_dev->iodc)) {
 		/* PAT_PDC (L-class) also reports the same goofy base */
 		sba_dev->ioc[0].ioc_hpa = ASTRO_IOC_OFFSET;
 		num_ioc = 1;
+	} else if (IS_PLUTO(sba_dev->iodc)) {
+		/* We use a negative value for IOC HPA so it gets 
+                 * corrected when we add it with IKE's IOC offset.
+		 * Doesnt look clean, but fewer code. 
+                 */
+		sba_dev->ioc[0].ioc_hpa = -PLUTO_IOC_OFFSET;
+		num_ioc = 1;
 	} else {
 		sba_dev->ioc[0].ioc_hpa = sba_dev->ioc[1].ioc_hpa = 0;
 		num_ioc = 2;
@@ -1529,7 +1730,11 @@ sba_hw_init(struct sba_device *sba_dev)
 		/* flush out the writes */
 		READ_REG(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
 
-		sba_ioc_init(sba_dev->dev, &(sba_dev->ioc[i]), i);
+		if (IS_PLUTO(sba_dev->iodc)) {
+			sba_ioc_init_pluto(sba_dev->dev, &(sba_dev->ioc[i]), i);
+		} else {
+			sba_ioc_init(sba_dev->dev, &(sba_dev->ioc[i]), i);
+		}
 	}
 }
 
@@ -1721,12 +1926,17 @@ static struct parisc_device_id sba_tbl[]
 	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_MERCED_PORT, 0xc },
 	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, REO_MERCED_PORT, 0xc },
 	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, REOG_MERCED_PORT, 0xc },
+	{ HPHW_IOA, HVERSION_REV_ANY_ID, PLUTO_MCKINLEY_PORT, 0xc },
 /* These two entries commented out because we don't find them in a
  * buswalk yet.  If/when we do, they would cause us to think we had
  * many more SBAs then we really do.
  *	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, ASTRO_ROPES_PORT, 0xc },
  *	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_ROPES_PORT, 0xc },
  */
+/* We shall also comment out Pluto Ropes Port since bus walk doesnt
+ * report it yet. 
+ *	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, PLUTO_ROPES_PORT, 0xc },
+ */
 	{ 0, }
 };
 
@@ -1751,9 +1961,7 @@ sba_driver_callback(struct parisc_device
 	int i;
 	char *version;
 
-#ifdef DEBUG_SBA_INIT
 	sba_dump_ranges(dev->hpa);
-#endif
 
 	/* Read HW Rev First */
 	func_class = READ_REG(dev->hpa + SBA_FCLASS);
@@ -1770,13 +1978,16 @@ sba_driver_callback(struct parisc_device
 		version = astro_rev;
 
 	} else if (IS_IKE(&dev->id)) {
-		static char ike_rev[]="Ike rev ?";
-
+		static char ike_rev[] = "Ike rev ?";
 		ike_rev[8] = '0' + (char) (func_class & 0xff);
 		version = ike_rev;
+	} else if (IS_PLUTO(&dev->id)) {
+		static char pluto_rev[]="Pluto ?.?";
+		pluto_rev[6] = '0' + (char) ((func_class & 0xf0) >> 4); 
+		pluto_rev[8] = '0' + (char) (func_class & 0x0f); 
+		version = pluto_rev;
 	} else {
-		static char reo_rev[]="REO rev ?";
-
+		static char reo_rev[] = "REO rev ?";
 		reo_rev[8] = '0' + (char) (func_class & 0xff);
 		version = reo_rev;
 	}
@@ -1784,18 +1995,14 @@ sba_driver_callback(struct parisc_device
 	if (!global_ioc_cnt) {
 		global_ioc_cnt = count_parisc_driver(&sba_driver);
 
-		/* Only Astro has one IOC per SBA */
-		if (!IS_ASTRO(&dev->id))
+		/* Astro and Pluto have one IOC per SBA */
+		if ((!IS_ASTRO(&dev->id)) || (!IS_PLUTO(&dev->id)))
 			global_ioc_cnt *= 2;
 	}
 
 	printk(KERN_INFO "%s found %s at 0x%lx\n",
 		MODULE_NAME, version, dev->hpa);
 
-#ifdef DEBUG_SBA_INIT
-	sba_dump_tlb(dev->hpa);
-#endif
-
 	sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
 	if (NULL == sba_dev) {
 		printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n");
@@ -1825,6 +2032,8 @@ sba_driver_callback(struct parisc_device
 		create_proc_info_entry("Astro", 0, proc_runway_root, sba_proc_info);
 	} else if (IS_IKE(&dev->id)) {
 		create_proc_info_entry("Ike", 0, proc_runway_root, sba_proc_info);
+	} else if (IS_PLUTO(&dev->id)) {
+		create_proc_info_entry("Pluto", 0, proc_mckinley_root, sba_proc_info);
 	} else {
 		create_proc_info_entry("Reo", 0, proc_runway_root, sba_proc_info);
 	}
Index: include/asm-parisc/hardware.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/hardware.h,v
retrieving revision 1.2
diff -u -p -r1.2 hardware.h
--- include/asm-parisc/hardware.h	14 Apr 2004 06:18:40 -0000	1.2
+++ include/asm-parisc/hardware.h	4 Jun 2004 06:27:09 -0000
@@ -97,6 +97,7 @@ struct bc_module {
 #define HPHW_IOA       12
 #define HPHW_BRIDGE    13
 #define HPHW_FABRIC    14
+#define HPHW_MC	       15
 #define HPHW_FAULTY    31
 
 
Index: include/asm-parisc/pdc.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/pdc.h,v
retrieving revision 1.6
diff -u -p -r1.6 pdc.h
--- include/asm-parisc/pdc.h	9 May 2004 18:34:17 -0000	1.6
+++ include/asm-parisc/pdc.h	4 Jun 2004 06:27:09 -0000
@@ -297,175 +297,6 @@ typedef struct {
 #define OSTAT_RUN		6
 #define OSTAT_ON		7
 
-#ifdef __LP64__
-/* PDC PAT CELL */
-#define PDC_PAT_CELL	64L		/* Interface for gaining and 
-					 * manipulating cell state within PD */
-#define PDC_PAT_CELL_GET_NUMBER	   0L	/* Return Cell number		*/
-#define PDC_PAT_CELL_GET_INFO      1L	/* Returns info about Cell	*/
-#define PDC_PAT_CELL_MODULE        2L	/* Returns info about Module	*/
-#define PDC_PAT_CELL_SET_ATTENTION 9L	/* Set Cell Attention indicator	*/
-#define PDC_PAT_CELL_NUMBER_TO_LOC 10L	/* Cell Number -> Location	*/
-#define PDC_PAT_CELL_WALK_FABRIC   11L	/* Walk the Fabric		*/
-#define PDC_PAT_CELL_GET_RDT_SIZE  12L	/* Return Route Distance Table Sizes */
-#define PDC_PAT_CELL_GET_RDT       13L	/* Return Route Distance Tables	*/
-#define PDC_PAT_CELL_GET_LOCAL_PDH_SZ  14L /* Read Local PDH Buffer Size*/
-#define PDC_PAT_CELL_SET_LOCAL_PDH     15L /* Write Local PDH Buffer	*/
-#define PDC_PAT_CELL_GET_REMOTE_PDH_SZ 16L /* Return Remote PDH Buffer Size */
-#define PDC_PAT_CELL_GET_REMOTE_PDH    17L /* Read Remote PDH Buffer	*/
-#define PDC_PAT_CELL_GET_DBG_INFO  128L	/* Return DBG Buffer Info	*/
-#define PDC_PAT_CELL_CHANGE_ALIAS  129L	/* Change Non-Equivalent Alias Checking */
-
-/*
-** Arg to PDC_PAT_CELL_MODULE memaddr[4]
-**
-** Addresses on the Merced Bus != all Runway Bus addresses.
-** This is intended for programming SBA/LBA chips range registers.
-*/
-#define IO_VIEW			0UL
-#define PA_VIEW			1UL
-
-/* PDC_PAT_CELL_MODULE entity type values */
-#define PAT_ENTITY_CA		0	/* central agent	*/
-#define PAT_ENTITY_PROC		1	/* processor		*/
-#define PAT_ENTITY_MEM		2	/* memory controller	*/
-#define PAT_ENTITY_SBA		3	/* system bus adapter	*/
-#define PAT_ENTITY_LBA		4	/* local bus adapter	*/
-#define PAT_ENTITY_PBC		5	/* processor bus converter */
-#define PAT_ENTITY_XBC		6	/* crossbar fabric connect */
-#define PAT_ENTITY_RC		7	/* fabric interconnect	*/
-
-/* PDC_PAT_CELL_MODULE address range type values */
-#define PAT_PBNUM		0	/* PCI Bus Number	*/
-#define PAT_LMMIO		1	/* < 4G MMIO Space	*/
-#define PAT_GMMIO		2	/* > 4G MMIO Space	*/
-#define PAT_NPIOP		3	/* Non Postable I/O Port Space */
-#define PAT_PIOP		4	/* Postable I/O Port Space */
-#define PAT_AHPA		5	/* Additional HPA Space	*/
-#define PAT_UFO			6	/* HPA Space (UFO for Mariposa) */
-#define PAT_GNIP		7	/* GNI Reserved Space	*/
-
-
-/* PDC PAT CHASSIS LOG */
-#define PDC_PAT_CHASSIS_LOG	65L	/* Platform logging & forward
-					 ** progress functions	*/
-#define PDC_PAT_CHASSIS_WRITE_LOG	0L /* Write Log Entry	*/
-#define PDC_PAT_CHASSIS_READ_LOG	1L /* Read  Log Entry	*/
-
-
-/* PDC PAT CPU  */
-#define PDC_PAT_CPU		67L	/* Interface to CPU configuration
-					 * within the protection domain */
-#define PDC_PAT_CPU_INFO		0L /* Return CPU config info	*/
-#define PDC_PAT_CPU_DELETE		1L /* Delete CPU		*/
-#define PDC_PAT_CPU_ADD			2L /* Add    CPU		*/
-#define PDC_PAT_CPU_GET_NUMBER		3L /* Return CPU Number		*/
-#define PDC_PAT_CPU_GET_HPA		4L /* Return CPU HPA		*/
-#define PDC_PAT_CPU_STOP            	5L /* Stop   CPU		*/
-#define PDC_PAT_CPU_RENDEZVOUS      	6L /* Rendezvous CPU		*/
-#define PDC_PAT_CPU_GET_CLOCK_INFO  	7L /* Return CPU Clock info	*/
-#define PDC_PAT_CPU_GET_RENDEZVOUS_STATE 8L /* Return Rendezvous State	*/
-#define PDC_PAT_CPU_PLUNGE_FABRIC	128L /* Plunge Fabric		*/
-#define PDC_PAT_CPU_UPDATE_CACHE_CLEANSING 129L /* Manipulate Cache 
-                                                 * Cleansing Mode	*/
-
-/*  PDC PAT EVENT */
-#define PDC_PAT_EVENT		68L	/* Interface to Platform Events */
-#define PDC_PAT_EVENT_GET_CAPS		0L /* Get Capabilities		*/
-#define PDC_PAT_EVENT_SET_MODE		1L /* Set Notification Mode	*/
-#define PDC_PAT_EVENT_SCAN		2L /* Scan Event		*/
-#define PDC_PAT_EVENT_HANDLE		3L /* Handle Event		*/
-#define PDC_PAT_EVENT_GET_NB_CALL	4L /* Get Non-Blocking call Args*/
-
-/*  PDC PAT HPMC */
-#define PDC_PAT_HPMC		70L	/* Cause processor to go into spin
-					 ** loop, and wait for wake up from
-					 ** Monarch Processor		*/
-#define PDC_PAT_HPMC_RENDEZ_CPU		0L /* go into spin loop		*/
-#define PDC_PAT_HPMC_SET_PARAMS		1L /* Allows OS to specify intr which PDC 
-                                        * will use to interrupt OS during machine
-                                        * check rendezvous		*/
-
-/* parameters for PDC_PAT_HPMC_SET_PARAMS */
-#define HPMC_SET_PARAMS_INTR		1L /* Rendezvous Interrupt	*/
-#define HPMC_SET_PARAMS_WAKE		2L /* Wake up processor		*/
-
-/*  PDC PAT IO */
-#define PDC_PAT_IO		71L	/* On-line services for I/O modules */
-#define PDC_PAT_IO_GET_SLOT_STATUS	 5L /* Get Slot Status Info	*/
-#define PDC_PAT_IO_GET_LOC_FROM_HARDWARE 6L /* Get Physical Location from */
-                                            /* Hardware Path		*/
-#define PDC_PAT_IO_GET_HARDWARE_FROM_LOC 7L /* Get Hardware Path from 
-                                             * Physical Location	*/
-#define PDC_PAT_IO_GET_PCI_CONFIG_FROM_HW 11L /* Get PCI Configuration
-                                               * Address from Hardware Path */
-#define PDC_PAT_IO_GET_HW_FROM_PCI_CONFIG 12L /* Get Hardware Path 
-                                               * from PCI Configuration Address */
-#define PDC_PAT_IO_READ_HOST_BRIDGE_INFO  13L /* Read Host Bridge State Info */
-#define PDC_PAT_IO_CLEAR_HOST_BRIDGE_INFO 14L /* Clear Host Bridge State Info*/
-#define PDC_PAT_IO_GET_PCI_ROUTING_TABLE_SIZE 15L /* Get PCI INT Routing Table 
-                                                   * Size		*/
-#define PDC_PAT_IO_GET_PCI_ROUTING_TABLE  16L /* Get PCI INT Routing Table */
-#define PDC_PAT_IO_GET_HINT_TABLE_SIZE    17L /* Get Hint Table Size	*/
-#define PDC_PAT_IO_GET_HINT_TABLE	18L /* Get Hint Table		*/
-#define PDC_PAT_IO_PCI_CONFIG_READ	19L /* PCI Config Read		*/
-#define PDC_PAT_IO_PCI_CONFIG_WRITE	20L /* PCI Config Write		*/
-#define PDC_PAT_IO_GET_NUM_IO_SLOTS	21L /* Get Number of I/O Bay Slots in 
-                                       		  * Cabinet		*/
-#define PDC_PAT_IO_GET_LOC_IO_SLOTS	22L /* Get Physical Location of I/O */
-                                   	    /* Bay Slots in Cabinet	*/
-#define PDC_PAT_IO_BAY_STATUS_INFO	28L /* Get I/O Bay Slot Status Info */
-#define PDC_PAT_IO_GET_PROC_VIEW	29L /* Get Processor view of IO address */
-#define PDC_PAT_IO_PROG_SBA_DIR_RANGE	30L /* Program directed range	*/
-
-/* PDC PAT MEM */
-#define PDC_PAT_MEM		72L  /* Manage memory page deallocation */
-#define PDC_PAT_MEM_PD_INFO     	0L /* Return PDT info for PD	*/
-#define PDC_PAT_MEM_PD_CLEAR    	1L /* Clear PDT for PD		*/
-#define PDC_PAT_MEM_PD_READ     	2L /* Read PDT entries for PD	*/
-#define PDC_PAT_MEM_PD_RESET    	3L /* Reset clear bit for PD	*/
-#define PDC_PAT_MEM_CELL_INFO   	5L /* Return PDT info For Cell	*/
-#define PDC_PAT_MEM_CELL_CLEAR  	6L /* Clear PDT For Cell	*/
-#define PDC_PAT_MEM_CELL_READ   	7L /* Read PDT entries For Cell	*/
-#define PDC_PAT_MEM_CELL_RESET  	8L /* Reset clear bit For Cell	*/
-#define PDC_PAT_MEM_SETGM	  	9L /* Set Golden Memory value	*/
-#define PDC_PAT_MEM_ADD_PAGE    	10L /* ADDs a page to the cell	*/
-#define PDC_PAT_MEM_ADDRESS     	11L /* Get Physical Location From*/
-					    /* Memory Address		*/
-#define PDC_PAT_MEM_GET_TXT_SIZE   	12L /* Get Formatted Text Size	*/
-#define PDC_PAT_MEM_GET_PD_TXT     	13L /* Get PD Formatted Text	*/
-#define PDC_PAT_MEM_GET_CELL_TXT   	14L /* Get Cell Formatted Text	*/
-#define PDC_PAT_MEM_RD_STATE_INFO  	15L /* Read Mem Module State Info*/
-#define PDC_PAT_MEM_CLR_STATE_INFO 	16L /*Clear Mem Module State Info*/
-#define PDC_PAT_MEM_CLEAN_RANGE    	128L /*Clean Mem in specific range*/
-#define PDC_PAT_MEM_GET_TBL_SIZE   	131L /* Get Memory Table Size	*/
-#define PDC_PAT_MEM_GET_TBL        	132L /* Get Memory Table	*/
-
-/* PDC PAT NVOLATILE */
-#define PDC_PAT_NVOLATILE	73L	   /* Access Non-Volatile Memory*/
-#define PDC_PAT_NVOLATILE_READ		0L /* Read Non-Volatile Memory	*/
-#define PDC_PAT_NVOLATILE_WRITE		1L /* Write Non-Volatile Memory	*/
-#define PDC_PAT_NVOLATILE_GET_SIZE	2L /* Return size of NVM	*/
-#define PDC_PAT_NVOLATILE_VERIFY	3L /* Verify contents of NVM	*/
-#define PDC_PAT_NVOLATILE_INIT		4L /* Initialize NVM		*/
-
-/* PDC PAT PD */
-#define PDC_PAT_PD		74L	    /* Protection Domain Info	*/
-#define PDC_PAT_PD_GET_ADDR_MAP		0L  /* Get Address Map		*/
-
-/* PDC_PAT_PD_GET_ADDR_MAP entry types */
-#define PAT_MEMORY_DESCRIPTOR		1
-
-/* PDC_PAT_PD_GET_ADDR_MAP memory types */
-#define PAT_MEMTYPE_MEMORY		0
-#define PAT_MEMTYPE_FIRMWARE		4
-
-/* PDC_PAT_PD_GET_ADDR_MAP memory usage */
-#define PAT_MEMUSE_GENERAL		0
-#define PAT_MEMUSE_GI			128
-#define PAT_MEMUSE_GNI			129
-#endif /* __LP64__ */
-
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -478,12 +309,6 @@ extern int pdc_type;
 #define PDC_TYPE_SYSTEM_MAP	 1 /* 32-bit, but supports PDC_SYSTEM_MAP */
 #define PDC_TYPE_SNAKE		 2 /* Doesn't support SYSTEM_MAP */
 
-#ifdef CONFIG_PARISC64
-#define is_pdc_pat()    (PDC_TYPE_PAT == pdc_type)
-#else
-#define is_pdc_pat()    (0)
-#endif
-
 struct pdc_chassis_info {       /* for PDC_CHASSIS_INFO */
 	unsigned long actcnt;   /* actual number of bytes returned */
 	unsigned long maxcnt;   /* maximum number of bytes that could be returned */
@@ -674,40 +499,6 @@ struct pdc_tod {
 	unsigned long tod_usec;
 };
 
-#ifdef __LP64__
-struct pdc_pat_cell_num {
-	unsigned long cell_num;
-	unsigned long cell_loc;
-};
-
-struct pdc_pat_cpu_num {
-	unsigned long cpu_num;
-	unsigned long cpu_loc;
-};
-
-struct pdc_pat_pd_addr_map_entry {
-	unsigned char entry_type;       /* 1 = Memory Descriptor Entry Type */
-	unsigned char reserve1[5];
-	unsigned char memory_type;
-	unsigned char memory_usage;
-	unsigned long paddr;
-	unsigned int  pages;            /* Length in 4K pages */
-	unsigned int  reserve2;
-	unsigned long cell_map;
-};
-
-/* FIXME: mod[508] should really be a union of the various mod components */
-struct pdc_pat_cell_mod_maddr_block {	/* PDC_PAT_CELL_MODULE */
-	unsigned long cba;              /* function 0 configuration space address */
-	unsigned long mod_info;         /* module information */
-	unsigned long mod_location;     /* physical location of the module */
-	struct hardware_path mod_path;	/* hardware path */
-	unsigned long mod[508];		/* PAT cell module components */
-};
-
-typedef struct pdc_pat_cell_mod_maddr_block pdc_pat_cell_mod_maddr_block_t;
-#endif /* __LP64__ */
-
 /* architected results from PDC_PIM/transfer hpmc on a PA1.1 machine */
 
 struct pdc_hpmc_pim_11 { /* PDC_PIM */
@@ -968,52 +759,6 @@ void pdc_emergency_unlock(void);
 int pdc_sti_call(unsigned long func, unsigned long flags,
                  unsigned long inptr, unsigned long outputr,
                  unsigned long glob_cfg);
-
-#ifdef __LP64__
-int pdc_pat_chassis_send_log(unsigned long status, unsigned long data);
-int pdc_pat_cell_get_number(struct pdc_pat_cell_num *cell_info);
-int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod,
-			unsigned long view_type, void *mem_addr);
-int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa);
-int pdc_pat_get_irt_size(unsigned long *num_entries, unsigned long cell_num);
-int pdc_pat_get_irt(void *r_addr, unsigned long cell_num);
-int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr, 
-			    unsigned long count, unsigned long offset);
-
-/********************************************************************
-* PDC_PAT_CELL[Return Cell Module] memaddr[0] conf_base_addr
-* ----------------------------------------------------------
-* Bit  0 to 51 - conf_base_addr
-* Bit 52 to 62 - reserved
-* Bit       63 - endianess bit
-********************************************************************/
-#define PAT_GET_CBA(value) ((value) & 0xfffffffffffff000UL)
-
-/********************************************************************
-* PDC_PAT_CELL[Return Cell Module] memaddr[1] mod_info
-* ----------------------------------------------------
-* Bit  0 to  7 - entity type
-*    0 = central agent,            1 = processor,
-*    2 = memory controller,        3 = system bus adapter,
-*    4 = local bus adapter,        5 = processor bus converter,
-*    6 = crossbar fabric connect,  7 = fabric interconnect,
-*    8 to 254 reserved,            255 = unknown.
-* Bit  8 to 15 - DVI
-* Bit 16 to 23 - IOC functions
-* Bit 24 to 39 - reserved
-* Bit 40 to 63 - mod_pages
-*    number of 4K pages a module occupies starting at conf_base_addr
-********************************************************************/
-#define PAT_GET_ENTITY(value)	(((value) >> 56) & 0xffUL)
-#define PAT_GET_DVI(value)	(((value) >> 48) & 0xffUL)
-#define PAT_GET_IOC(value)	(((value) >> 40) & 0xffUL)
-#define PAT_GET_MOD_PAGES(value)(((value) & 0xffffffUL)
-
-#else /* !__LP64__ */
-/* No PAT support for 32-bit kernels...sorry */
-#define pdc_pat_get_irt_size(num_entries, cell_numn)	PDC_BAD_PROC
-#define pdc_pat_get_irt(r_addr, cell_num)	PDC_BAD_PROC
-#endif /* !__LP64__ */
 
 extern void pdc_init(void);
 
Index: include/asm-parisc/pdcpat.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/pdcpat.h,v
retrieving revision 1.1
diff -u -p -r1.1 pdcpat.h
--- include/asm-parisc/pdcpat.h	29 Jul 2003 17:02:04 -0000	1.1
+++ include/asm-parisc/pdcpat.h	4 Jun 2004 06:27:09 -0000
@@ -6,12 +6,11 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (c) Hewlett Packard (Paul Bame <bame at puffin.external.hp.com>)
- * Copyright 2000 (c) Grant Grundler <grundler at puffin.external.hp.com>
+ * Copyright 2000 (c) Hewlett Packard (Paul Bame <bame()spam.parisc-linux.org>)
+ * Copyright 2000,2004 (c) Grant Grundler <grundler()nahspam.parisc-linux.org>
  */
 
 
-/* PDC PAT CELL */
 #define PDC_PAT_CELL           	64L   /* Interface for gaining and 
                                          * manipulatin g cell state within PD */
 #define PDC_PAT_CELL_GET_NUMBER    0L   /* Return Cell number */
@@ -60,17 +59,17 @@
 #define PAT_GNIP            7         /* GNI Reserved Space */
 
 
-/* PDC PAT CHASSIS LOG */
 
-#define PDC_PAT_CHASSIS_LOG		65L /* Platform logging & forward
-					    ** progress functions */
+/* PDC PAT CHASSIS LOG -- Platform logging & forward progress functions */
+
+#define PDC_PAT_CHASSIS_LOG		65L
 #define PDC_PAT_CHASSIS_WRITE_LOG    	0L /* Write Log Entry */
 #define PDC_PAT_CHASSIS_READ_LOG     	1L /* Read  Log Entry */
 
-/* PDC PAT CPU  */
 
-#define PDC_PAT_CPU                	67L /* Interface to CPU configuration
-                                        	* within the protection domain */
+/* PDC PAT CPU  -- CPU configuration within the protection domain */
+
+#define PDC_PAT_CPU                	67L
 #define PDC_PAT_CPU_INFO            	0L /* Return CPU config info */
 #define PDC_PAT_CPU_DELETE          	1L /* Delete CPU */
 #define PDC_PAT_CPU_ADD             	2L /* Add    CPU */
@@ -83,32 +82,33 @@
 #define PDC_PAT_CPU_PLUNGE_FABRIC 	128L /* Plunge Fabric */
 #define PDC_PAT_CPU_UPDATE_CACHE_CLEANSING 129L /* Manipulate Cache 
                                                  * Cleansing Mode */
-/*  PDC PAT EVENT */
+/*  PDC PAT EVENT -- Platform Events */
 
-#define PDC_PAT_EVENT              	68L /* Interface to Platform Events */
+#define PDC_PAT_EVENT              	68L
 #define PDC_PAT_EVENT_GET_CAPS     	0L /* Get Capabilities */
 #define PDC_PAT_EVENT_SET_MODE     	1L /* Set Notification Mode */
 #define PDC_PAT_EVENT_SCAN         	2L /* Scan Event */
 #define PDC_PAT_EVENT_HANDLE       	3L /* Handle Event */
 #define PDC_PAT_EVENT_GET_NB_CALL  	4L /* Get Non-Blocking call Args */
 
-/*  PDC PAT HPMC */
+/*  PDC PAT HPMC -- Cause processor to go into spin loop, and wait
+ *  			for wake up from Monarch Processor.
+ */
 
-#define PDC_PAT_HPMC               70L /* Cause processor to go into spin
-				       ** loop, and wait for wake up from
-				       ** Monarch Processor */
+#define PDC_PAT_HPMC               70L
 #define PDC_PAT_HPMC_RENDEZ_CPU     0L /* go into spin loop */
 #define PDC_PAT_HPMC_SET_PARAMS     1L /* Allows OS to specify intr which PDC 
-                                        * will use to interrupt OS during machine
-                                        * check rendezvous */
+                                        * will use to interrupt OS during
+                                        * machine check rendezvous */
 
 /* parameters for PDC_PAT_HPMC_SET_PARAMS: */
 #define HPMC_SET_PARAMS_INTR 	    1L /* Rendezvous Interrupt */
 #define HPMC_SET_PARAMS_WAKE 	    2L /* Wake up processor */
 
-/*  PDC PAT IO */
 
-#define PDC_PAT_IO                  71L /* On-line services for I/O modules */
+/*  PDC PAT IO  -- On-line services for I/O modules */
+
+#define PDC_PAT_IO                  71L
 #define PDC_PAT_IO_GET_SLOT_STATUS   	5L /* Get Slot Status Info*/
 #define PDC_PAT_IO_GET_LOC_FROM_HARDWARE 6L /* Get Physical Location from */
                                             /* Hardware Path */
@@ -135,9 +135,10 @@
 #define PDC_PAT_IO_GET_PROC_VIEW        29L /* Get Processor view of IO address */
 #define PDC_PAT_IO_PROG_SBA_DIR_RANGE   30L /* Program directed range */
 
-/* PDC PAT MEM */
 
-#define PDC_PAT_MEM             	72L /* Manage memory page deallocation */
+/* PDC PAT MEM  -- Manage memory page deallocation */
+
+#define PDC_PAT_MEM            72L
 #define PDC_PAT_MEM_PD_INFO     	0L /* Return PDT info for PD       */
 #define PDC_PAT_MEM_PD_CLEAR    	1L /* Clear PDT for PD             */
 #define PDC_PAT_MEM_PD_READ     	2L /* Read PDT entries for PD      */
@@ -159,18 +160,99 @@
 #define PDC_PAT_MEM_GET_TBL_SIZE   	131L /* Get Memory Table Size     */
 #define PDC_PAT_MEM_GET_TBL        	132L /* Get Memory Table          */
 
-/* PDC PAT NVOLATILE */
 
-#define PDC_PAT_NVOLATILE          	73L /* Access Non-Volatile Memory */
-#define PDC_PAT_NVOLATILE_READ      	0L /* Read Non-Volatile Memory   */
-#define PDC_PAT_NVOLATILE_WRITE     	1L /* Write Non-Volatile Memory  */
-#define PDC_PAT_NVOLATILE_GET_SIZE  	2L /* Return size of NVM         */
-#define PDC_PAT_NVOLATILE_VERIFY    	3L /* Verify contents of NVM     */
-#define PDC_PAT_NVOLATILE_INIT      	4L /* Initialize NVM             */
+/* PDC PAT NVOLATILE  --  Access Non-Volatile Memory */
+
+#define PDC_PAT_NVOLATILE	73L
+#define PDC_PAT_NVOLATILE_READ		0L /* Read Non-Volatile Memory   */
+#define PDC_PAT_NVOLATILE_WRITE		1L /* Write Non-Volatile Memory  */
+#define PDC_PAT_NVOLATILE_GET_SIZE	2L /* Return size of NVM         */
+#define PDC_PAT_NVOLATILE_VERIFY	3L /* Verify contents of NVM     */
+#define PDC_PAT_NVOLATILE_INIT		4L /* Initialize NVM             */
+
+/* PDC PAT PD */
+#define PDC_PAT_PD		74L         /* Protection Domain Info   */
+#define PDC_PAT_PD_GET_ADDR_MAP		0L  /* Get Address Map          */
+
+/* PDC_PAT_PD_GET_ADDR_MAP entry types */
+#define PAT_MEMORY_DESCRIPTOR		1   
+
+/* PDC_PAT_PD_GET_ADDR_MAP memory types */
+#define PAT_MEMTYPE_MEMORY		0
+#define PAT_MEMTYPE_FIRMWARE		4
+
+/* PDC_PAT_PD_GET_ADDR_MAP memory usage */
+#define PAT_MEMUSE_GENERAL		0
+#define PAT_MEMUSE_GI			128
+#define PAT_MEMUSE_GNI			129
+
 
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
+#ifdef CONFIG_PARISC64
+#define is_pdc_pat()	(PDC_TYPE_PAT == pdc_type)
+extern int pdc_pat_get_irt_size(unsigned long *num_entries, unsigned long cell_num);
+extern int pdc_pat_get_irt(void *r_addr, unsigned long cell_num);
+#else	/* ! CONFIG_PARISC64 */
+/* No PAT support for 32-bit kernels...sorry */
+#define is_pdc_pat()	(0)
+#define pdc_pat_get_irt_size(num_entries, cell_numn)	PDC_BAD_PROC
+#define pdc_pat_get_irt(r_addr, cell_num)		PDC_BAD_PROC
+#endif	/* ! CONFIG_PARISC64 */
+
+
+struct pdc_pat_cell_num {
+	unsigned long cell_num;
+	unsigned long cell_loc;
+};
+
+struct pdc_pat_cpu_num {
+	unsigned long cpu_num;
+	unsigned long cpu_loc;
+};
+
+struct pdc_pat_pd_addr_map_entry {
+	unsigned char entry_type;       /* 1 = Memory Descriptor Entry Type */
+	unsigned char reserve1[5];
+	unsigned char memory_type;
+	unsigned char memory_usage;
+	unsigned long paddr;
+	unsigned int  pages;            /* Length in 4K pages */
+	unsigned int  reserve2;
+	unsigned long cell_map;
+};
+
+/********************************************************************
+* PDC_PAT_CELL[Return Cell Module] memaddr[0] conf_base_addr
+* ----------------------------------------------------------
+* Bit  0 to 51 - conf_base_addr
+* Bit 52 to 62 - reserved
+* Bit       63 - endianess bit
+********************************************************************/
+#define PAT_GET_CBA(value) ((value) & 0xfffffffffffff000UL)
+
+/********************************************************************
+* PDC_PAT_CELL[Return Cell Module] memaddr[1] mod_info
+* ----------------------------------------------------
+* Bit  0 to  7 - entity type
+*    0 = central agent,            1 = processor,
+*    2 = memory controller,        3 = system bus adapter,
+*    4 = local bus adapter,        5 = processor bus converter,
+*    6 = crossbar fabric connect,  7 = fabric interconnect,
+*    8 to 254 reserved,            255 = unknown.
+* Bit  8 to 15 - DVI
+* Bit 16 to 23 - IOC functions
+* Bit 24 to 39 - reserved
+* Bit 40 to 63 - mod_pages
+*    number of 4K pages a module occupies starting at conf_base_addr
+********************************************************************/
+#define PAT_GET_ENTITY(value)	(((value) >> 56) & 0xffUL)
+#define PAT_GET_DVI(value)	(((value) >> 48) & 0xffUL)
+#define PAT_GET_IOC(value)	(((value) >> 40) & 0xffUL)
+#define PAT_GET_MOD_PAGES(value)(((value) & 0xffffffUL)
+
+
 /*
 ** PDC_PAT_CELL_GET_INFO return block
 */
@@ -202,16 +284,24 @@ struct pdc_pat_cell_mod_maddr_block {	/*
 typedef struct pdc_pat_cell_mod_maddr_block pdc_pat_cell_mod_maddr_block_t;
 
 
-extern int pdc_pat_cell_get_number(void *);
-extern int pdc_pat_cell_module(void *, unsigned long, unsigned long, unsigned long, void *);
+extern int pdc_pat_chassis_send_log(unsigned long status, unsigned long data);
+extern int pdc_pat_cell_get_number(struct pdc_pat_cell_num *cell_info);
+extern int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod, unsigned long view_type, void *mem_addr);
 extern int pdc_pat_cell_num_to_loc(void *, unsigned long);
 
+extern int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa);
+
+extern int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr, unsigned long count, unsigned long offset);
+
+
+extern int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *val); 
+extern int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val); 
+
+
 /* Flag to indicate this is a PAT box...don't use this unless you
 ** really have to...it might go away some day.
 */
-#ifdef __LP64__
 extern int pdc_pat;     /* arch/parisc/kernel/inventory.c */
-#endif
 
 /********************************************************************
 * PDC_PAT_CELL[Return Cell Module] memaddr[0] conf_base_addr


More information about the parisc-linux-cvs mailing list