From: Matthew Wilcox <willy@debian.org>

Patch 3.  ia64 support for extended config space.

- Add the new parameter 'type' to ia64_sal_pci_config_{read,write}

- Change callers to match.

- Don't check `value' for NULL -- drivers/pci/access.c guarantees it isn't.

- Make pci_sal_ops static.

- Add pci_sal_ext_ops.

- Introduce pci_set_sal_ops() as an arch_initcall to ensure it gets set
  before we walk the ACPI namespace to discover PCI root bridges


---

 25-akpm/arch/ia64/pci/pci.c    |   57 ++++++++++++++++++++++++++++++++++++-----
 25-akpm/include/asm-ia64/sal.h |    8 ++---
 2 files changed, 55 insertions(+), 10 deletions(-)

diff -puN arch/ia64/pci/pci.c~sal-support arch/ia64/pci/pci.c
--- 25/arch/ia64/pci/pci.c~sal-support	Fri Feb 27 15:21:48 2004
+++ 25-akpm/arch/ia64/pci/pci.c	Fri Feb 27 15:21:48 2004
@@ -57,17 +57,16 @@ struct pci_fixup pcibios_fixups[1];
 	((u64)(seg << 24) | (u64)(bus << 16) | \
 	 (u64)(devfn << 8) | (u64)(reg))
 
-
 static int
 pci_sal_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
 {
 	int result = 0;
 	u64 data = 0;
 
-	if (!value || (seg > 255) || (bus > 255) || (devfn > 255) || (reg > 255))
+	if ((seg > 255) || (bus > 255) || (devfn > 255) || (reg > 255))
 		return -EINVAL;
 
-	result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(seg, bus, devfn, reg), len, &data);
+	result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(seg, bus, devfn, reg), 0, len, &data);
 
 	*value = (u32) data;
 
@@ -80,15 +79,61 @@ pci_sal_write (int seg, int bus, int dev
 	if ((seg > 255) || (bus > 255) || (devfn > 255) || (reg > 255))
 		return -EINVAL;
 
-	return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(seg, bus, devfn, reg), len, value);
+	return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(seg, bus, devfn, reg), 0, len, value);
 }
 
-struct pci_raw_ops pci_sal_ops = {
+static struct pci_raw_ops pci_sal_ops = {
 	.read = 	pci_sal_read,
 	.write =	pci_sal_write
 };
 
-struct pci_raw_ops *raw_pci_ops = &pci_sal_ops;	/* default to SAL */
+/* SAL 3.2 adds support for extended config space. */
+
+#define PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg) \
+	((u64)(seg << 28) | (u64)(bus << 20) | \
+	 (u64)(devfn << 12) | (u64)(reg))
+
+static int
+pci_sal_ext_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
+{
+	int result = 0;
+	u64 data = 0;
+
+	if ((seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
+		return -EINVAL;
+
+	result = ia64_sal_pci_config_read(PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg), 1, len, &data);
+
+	*value = (u32) data;
+
+	return result;
+}
+
+static int
+pci_sal_ext_write (int seg, int bus, int devfn, int reg, int len, u32 value)
+{
+	if ((seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
+		return -EINVAL;
+
+	return ia64_sal_pci_config_write(PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg), 1, len, value);
+}
+
+static struct pci_raw_ops pci_sal_ext_ops = {
+	.read = 	pci_sal_ext_read,
+	.write =	pci_sal_ext_write
+};
+
+struct pci_raw_ops *raw_pci_ops = &pci_sal_ops;	/* default to SAL < 3.2 */
+
+static int __init pci_set_sal_ops(void)
+{
+	if (sal_check_revision(3, 2)) {
+		raw_pci_ops = &pci_sal_ext_ops;
+	}
+	return 0;
+}
+
+arch_initcall(pci_set_sal_ops);
 
 
 static int
diff -puN include/asm-ia64/sal.h~sal-support include/asm-ia64/sal.h
--- 25/include/asm-ia64/sal.h~sal-support	Fri Feb 27 15:21:48 2004
+++ 25-akpm/include/asm-ia64/sal.h	Fri Feb 27 15:21:48 2004
@@ -741,10 +741,10 @@ ia64_sal_mc_set_params (u64 param_type, 
 
 /* Read from PCI configuration space */
 static inline s64
-ia64_sal_pci_config_read (u64 pci_config_addr, u64 size, u64 *value)
+ia64_sal_pci_config_read (u64 pci_config_addr, int type, u64 size, u64 *value)
 {
 	struct ia64_sal_retval isrv;
-	SAL_CALL(isrv, SAL_PCI_CONFIG_READ, pci_config_addr, size, 0, 0, 0, 0, 0);
+	SAL_CALL(isrv, SAL_PCI_CONFIG_READ, pci_config_addr, size, type, 0, 0, 0, 0);
 	if (value)
 		*value = isrv.v0;
 	return isrv.status;
@@ -752,11 +752,11 @@ ia64_sal_pci_config_read (u64 pci_config
 
 /* Write to PCI configuration space */
 static inline s64
-ia64_sal_pci_config_write (u64 pci_config_addr, u64 size, u64 value)
+ia64_sal_pci_config_write (u64 pci_config_addr, int type, u64 size, u64 value)
 {
 	struct ia64_sal_retval isrv;
 	SAL_CALL(isrv, SAL_PCI_CONFIG_WRITE, pci_config_addr, size, value,
-	         0, 0, 0, 0);
+	         type, 0, 0, 0);
 	return isrv.status;
 }
 

_