## Automatically generated incremental diff
## From:   linux-2.4.23-pre3
## To:     linux-2.4.23-pre4
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.4.23-pre3/Documentation/Configure.help linux-2.4.23-pre4/Documentation/Configure.help
--- linux-2.4.23-pre3/Documentation/Configure.help	2003-09-12 12:44:31.000000000 -0700
+++ linux-2.4.23-pre4/Documentation/Configure.help	2003-09-12 12:44:34.000000000 -0700
@@ -5486,6 +5486,17 @@
   is at
   <http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
 
+Mach64 Generic LCD support
+CONFIG_FB_ATY_GENERIC_LCD
+  Enabling this option enables the Atyfb driver to drive LCD panels. It
+  will autodetect the resulution and format of your display and emulate
+  other resolutions using the hardware stretcher on the chip.
+  Say Y here if you have computer with a Rage LT Pro, Rage Mobility M1,
+  Rage XC or Rage XL chip and a laptop LCD display or any other LCD display
+  that needs to be digitally driven. It is not necessary to enable this
+  option if you are using an LCD display with a normal VGA connector,
+  but it won't hurt if you do.
+
 ATI Radeon display support
 CONFIG_FB_RADEON
   Choose this option if you want to use an ATI Radeon graphics card as
@@ -27070,12 +27081,31 @@
   and restore instructions.  It's useful for tracking down spinlock
   problems, but slow!  If you're unsure, select N.
 
-Early printk support (requires VGA!)
+Early printk support
 CONFIG_IA64_EARLY_PRINTK
-  Selecting this option uses the VGA screen for printk() output before
-  the consoles are initialised.  It is useful for debugging problems
-  early in the boot process, but only if you have a VGA screen
-  attached.  If you're unsure, select N.
+  Selecting this option uses a UART or VGA screen (or both) for
+  printk() output before the consoles are initialised.  It is useful
+  for debugging problems early in the boot process, but only if you
+  have a serial terminal or a VGA screen attached.  If you're unsure,
+  select N.
+
+Early printk on serial port
+CONFIG_IA64_EARLY_PRINTK_UART
+  Select this option to use a serial port for early printk() output.
+  You must also select either CONFIG_IA64_EARLY_PRINTK_UART_BASE or
+  CONFIG_SERIAL_HCDP.  If you select CONFIG_SERIAL_HCDP, early
+  printk() output will appear on the first console device described by
+  the HCDP.  If you set CONFIG_IA64_EARLY_PRINTK_UART_BASE, the HCDP
+  will be ignored.
+
+UART base address
+CONFIG_IA64_EARLY_PRINTK_UART_BASE
+  The physical MMIO address of the UART to use for early printk().
+  This overrides any UART located using the EFI HCDP table.
+
+Early printk on VGA
+CONFIG_IA64_EARLY_PRINTK_VGA
+  Select this option to use VGA for early printk() output.
 
 Print possible IA64 hazards to console
 CONFIG_IA64_PRINT_HAZARDS
diff -urN linux-2.4.23-pre3/Makefile linux-2.4.23-pre4/Makefile
--- linux-2.4.23-pre3/Makefile	2003-09-12 12:44:31.000000000 -0700
+++ linux-2.4.23-pre4/Makefile	2003-09-12 12:44:34.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 23
-EXTRAVERSION = -pre2
+EXTRAVERSION = -pre4
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.23-pre3/arch/ia64/Makefile linux-2.4.23-pre4/arch/ia64/Makefile
--- linux-2.4.23-pre3/arch/ia64/Makefile	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/Makefile	2003-09-12 12:44:34.000000000 -0700
@@ -17,13 +17,31 @@
 AFLAGS_KERNEL := -mconstant-gp
 EXTRA	=
 
-CFLAGS := $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f10-f15,f32-f127 \
+CFLAGS := $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \
 	  -falign-functions=32
 # -ffunction-sections
 CFLAGS_KERNEL := -mconstant-gp
 
 GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')
 
+CHECK_GAS_FOR_HINT=arch/ia64/scripts/check_gas_for_hint.o
+MAKE_GAS_HINT_TEST=arch/ia64/scripts/make_gas_hint_test
+
+ifneq (, $(shell ls $(CHECK_GAS_FOR_HINT)))
+$(shell rm $(CHECK_GAS_FOR_HINT))
+endif
+
+CHECK_GAS_CMD:=($(CC) $(MAKE_GAS_HINT_TEST).c -o $(MAKE_GAS_HINT_TEST) && $(MAKE_GAS_HINT_TEST) | $(CC) -c -o $(CHECK_GAS_FOR_HINT) -x assembler -; rm -f $(MAKE_GAS_HINT_TEST))>&/dev/null
+$(shell $(CHECK_GAS_CMD))
+ifneq (, $(shell ls $(CHECK_GAS_FOR_HINT)))
+#Newer version of binutil is detected and "hint" instruction is in the kernel
+$(warning Warning: Found binutils that supports hint instruction)
+FLAGS := $(AFLAGS) -DGAS_HAS_HINT_INSN
+CFLAGS := $(CFLAGS) -DGAS_HAS_HINT_INSN
+else
+$(warning Warning: Please use binutil version 2.14.90.0.4.1 or higher to get the support of hint instruction in kernel.) 
+endif
+
 ifneq ($(GCC_VERSION),2)
 	CFLAGS += -frename-registers --param max-inline-insns=5000
 endif
@@ -136,7 +154,7 @@
 	arch/ia64/scripts/unwcheck.sh vmlinux
 
 archmrproper:
-	rm -f arch/$(ARCH)/vmlinux.lds
+	rm -f arch/$(ARCH)/vmlinux.lds vmlinux-tmp vmlinux.gz
 	@$(MAKE) -C arch/$(ARCH)/tools mrproper
 
 archdep:
diff -urN linux-2.4.23-pre3/arch/ia64/config.in linux-2.4.23-pre4/arch/ia64/config.in
--- linux-2.4.23-pre3/arch/ia64/config.in	2003-09-12 12:44:32.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/config.in	2003-09-12 12:44:34.000000000 -0700
@@ -35,7 +35,6 @@
 	 DIG-compliant		CONFIG_IA64_DIG			\
 	 HP-simulator		CONFIG_IA64_HP_SIM		\
 	 HP-zx1			CONFIG_IA64_HP_ZX1		\
-	 SGI-SN1		CONFIG_IA64_SGI_SN1		\
 	 SGI-SN2		CONFIG_IA64_SGI_SN2" generic
 
 if [ "$CONFIG_ITANIUM" = "y" ]; then
@@ -54,11 +53,7 @@
 if [ "$CONFIG_ITANIUM" = "y" ]; then
 	define_bool CONFIG_IA64_BRL_EMU y
 	bool '  Enable Itanium B-step specific code' CONFIG_ITANIUM_BSTEP_SPECIFIC
-	if [ "$CONFIG_IA64_SGI_SN1" = "y" ]; then
-	  define_int CONFIG_IA64_L1_CACHE_SHIFT 7 # align cache-sensitive data to 128 bytes
-	else
-	  define_int CONFIG_IA64_L1_CACHE_SHIFT 6 # align cache-sensitive data to 64 bytes
-	fi
+	define_int CONFIG_IA64_L1_CACHE_SHIFT 6 # align cache-sensitive data to 64 bytes
 fi
 
 if [ "$CONFIG_MCKINLEY" = "y" ]; then
@@ -66,17 +61,20 @@
 fi
 
 if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_DIG" = "y" -o "$CONFIG_IA64_HP_ZX1" = "y" ]; then
+	bool '  Enable NUMA support' CONFIG_NUMA
+	if [ "$CONFIG_NUMA" = "y" ]; then
+	  define_bool CONFIG_DISCONTIGMEM y
+	fi
 	bool '  Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA
 	define_bool CONFIG_PM y
 fi
 
-if [ "$CONFIG_IA64_SGI_SN1" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ]; then
+if [ "$CONFIG_IA64_SGI_SN2" = "y" ]; then
 	define_bool CONFIG_IA64_SGI_SN y
 	bool '  Enable extra debugging code' CONFIG_IA64_SGI_SN_DEBUG
 	bool '  Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN_SIM
-	bool '  Enable autotest (llsc). Option to run cache test instead of booting' \
-			CONFIG_IA64_SGI_AUTOTEST
 	bool '  Enable protocol mode for the L1 console' CONFIG_SERIAL_SGI_L1_PROTOCOL
+	define_bool CONFIG_HWGFS_FS y
 	define_bool CONFIG_DISCONTIGMEM y
 	define_bool CONFIG_IA64_MCA y
 	define_bool CONFIG_NUMA y
@@ -86,6 +84,7 @@
 
 define_bool CONFIG_KCORE_ELF y	# On IA-64, we always want an ELF /proc/kcore.
 
+bool 'Use PAL_HALT_LIGHT in idle loop' CONFIG_IA64_PAL_IDLE
 bool 'SMP support' CONFIG_SMP
 if [ "$CONFIG_SMP" = "y" ]; then
    int  'Maximum number of CPUs (2-32)' CONFIG_NR_CPUS 32
diff -urN linux-2.4.23-pre3/arch/ia64/configs/dig linux-2.4.23-pre4/arch/ia64/configs/dig
--- linux-2.4.23-pre3/arch/ia64/configs/dig	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/configs/dig	2003-09-12 12:44:34.000000000 -0700
@@ -38,6 +38,7 @@
 CONFIG_IA64_BRL_EMU=y
 # CONFIG_ITANIUM_BSTEP_SPECIFIC is not set
 CONFIG_IA64_L1_CACHE_SHIFT=6
+# CONFIG_NUMA is not set
 CONFIG_IA64_MCA=y
 CONFIG_PM=y
 CONFIG_KCORE_ELF=y
@@ -49,6 +50,7 @@
 # CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
+# CONFIG_IA64_PAL_IDLE is not set
 CONFIG_SMP=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_PERFMON=y
@@ -270,7 +272,6 @@
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
 # CONFIG_PDC202XX_BURST is not set
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_PDC202XX_FORCE is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_SVWKS is not set
@@ -329,6 +330,9 @@
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set
 # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
@@ -406,6 +410,7 @@
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
 # CONFIG_CS89x0 is not set
 CONFIG_TULIP=y
 # CONFIG_TULIP_MWI is not set
@@ -445,6 +450,7 @@
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
 # CONFIG_MYRI_SBUS is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
@@ -656,6 +662,7 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -665,6 +672,7 @@
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BEFS_DEBUG is not set
 # CONFIG_BFS_FS is not set
@@ -715,6 +723,7 @@
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
@@ -916,6 +925,7 @@
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_CATC is not set
+# CONFIG_USB_AX8817X is not set
 # CONFIG_USB_CDCETHER is not set
 # CONFIG_USB_USBNET is not set
 
@@ -939,8 +949,14 @@
 # CONFIG_USB_LCD is not set
 
 #
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
 # Library routines
 #
+# CONFIG_CRC32 is not set
 # CONFIG_ZLIB_INFLATE is not set
 # CONFIG_ZLIB_DEFLATE is not set
 
diff -urN linux-2.4.23-pre3/arch/ia64/configs/generic linux-2.4.23-pre4/arch/ia64/configs/generic
--- linux-2.4.23-pre3/arch/ia64/configs/generic	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/configs/generic	2003-09-12 12:44:34.000000000 -0700
@@ -38,6 +38,7 @@
 CONFIG_IA64_BRL_EMU=y
 # CONFIG_ITANIUM_BSTEP_SPECIFIC is not set
 CONFIG_IA64_L1_CACHE_SHIFT=6
+# CONFIG_NUMA is not set
 CONFIG_IA64_MCA=y
 CONFIG_PM=y
 CONFIG_KCORE_ELF=y
@@ -49,6 +50,7 @@
 # CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
+# CONFIG_IA64_PAL_IDLE is not set
 CONFIG_SMP=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_PERFMON=y
@@ -270,7 +272,6 @@
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
 # CONFIG_PDC202XX_BURST is not set
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_PDC202XX_FORCE is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_SVWKS is not set
@@ -329,6 +330,9 @@
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set
 # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
@@ -411,6 +415,7 @@
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
 # CONFIG_CS89x0 is not set
 CONFIG_TULIP=y
 # CONFIG_TULIP_MWI is not set
@@ -450,6 +455,7 @@
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
 # CONFIG_MYRI_SBUS is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
@@ -661,6 +667,7 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -670,6 +677,7 @@
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BEFS_DEBUG is not set
 # CONFIG_BFS_FS is not set
@@ -720,6 +728,7 @@
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
@@ -921,6 +930,7 @@
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_CATC is not set
+# CONFIG_USB_AX8817X is not set
 # CONFIG_USB_CDCETHER is not set
 # CONFIG_USB_USBNET is not set
 
@@ -944,8 +954,14 @@
 # CONFIG_USB_LCD is not set
 
 #
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
 # Library routines
 #
+# CONFIG_CRC32 is not set
 # CONFIG_ZLIB_INFLATE is not set
 # CONFIG_ZLIB_DEFLATE is not set
 
diff -urN linux-2.4.23-pre3/arch/ia64/configs/numa linux-2.4.23-pre4/arch/ia64/configs/numa
--- linux-2.4.23-pre3/arch/ia64/configs/numa	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/configs/numa	2003-09-12 12:44:34.000000000 -0700
@@ -0,0 +1,998 @@
+#
+# Automatically generated make config: don't edit
+#
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+# CONFIG_KMOD is not set
+
+#
+# General setup
+#
+CONFIG_IA64=y
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+# CONFIG_SBUS is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_ITANIUM=y
+# CONFIG_MCKINLEY is not set
+CONFIG_IA64_GENERIC=y
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_HP_SIM is not set
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_SGI_SN1 is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+CONFIG_IA64_BRL_EMU=y
+# CONFIG_ITANIUM_BSTEP_SPECIFIC is not set
+CONFIG_IA64_L1_CACHE_SHIFT=6
+CONFIG_NUMA=y
+CONFIG_DISCONTIGMEM=y
+CONFIG_IA64_MCA=y
+CONFIG_PM=y
+CONFIG_KCORE_ELF=y
+CONFIG_FORCE_MAX_ZONEORDER=19
+CONFIG_HUGETLB_PAGE=y
+# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set
+CONFIG_HUGETLB_PAGE_SIZE_16MB=y
+# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
+# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
+CONFIG_IA64_PAL_IDLE=y
+CONFIG_SMP=y
+CONFIG_IA32_SUPPORT=y
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+CONFIG_EFI_VARS=y
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_ACPI=y
+CONFIG_ACPI_EFI=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_KERNEL_CONFIG=y
+
+#
+# ACPI Support
+#
+CONFIG_ACPI_PCI=y
+CONFIG_ACPI=y
+CONFIG_ACPI_EFI=y
+CONFIG_ACPI_BOOT=y
+CONFIG_ACPI_BUS=y
+CONFIG_ACPI_INTERPRETER=y
+CONFIG_ACPI_POWER=y
+CONFIG_ACPI_SYSTEM=y
+# CONFIG_ACPI_BUTTON is not set
+# CONFIG_ACPI_FAN is not set
+# CONFIG_ACPI_PROCESSOR is not set
+# CONFIG_ACPI_THERMAL is not set
+CONFIG_ACPI_NUMA=y
+# CONFIG_ACPI_DEBUG is not set
+CONFIG_PCI=y
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+CONFIG_FILTER=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_CISS_SCSI_TAPE is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_STATS is not set
+
+#
+# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Fusion MPT device support
+#
+CONFIG_FUSION=y
+CONFIG_FUSION_BOOT=y
+CONFIG_FUSION_MAX_SGE=40
+# CONFIG_FUSION_ISENSE is not set
+# CONFIG_FUSION_CTL is not set
+# CONFIG_FUSION_LAN is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_IDEDISK_STROKE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_BLK_DEV_GENERIC is not set
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_PCI_WIP is not set
+# CONFIG_BLK_DEV_ADMA100 is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_AMD74XX_OVERRIDE is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_HPT34X_AUTODMA is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_PDC202XX_BURST is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_DMA_NONPCI is not set
+CONFIG_BLK_DEV_IDE_MODES=y
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_ATARAID_SII is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_SR_EXTRA_DEVS=2
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_DEBUG_QUEUES=y
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AACRAID is not set
+CONFIG_SCSI_AIC7XXX=y
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
+CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+CONFIG_SCSI_SYM53C8XX=y
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
+# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+CONFIG_SCSI_QLOGIC_1280=y
+# CONFIG_SCSI_QLOGIC_QLA2100 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_SUNLANCE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_CS89x0 is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PIO is not set
+# CONFIG_E100 is not set
+# CONFIG_LNE390 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_SUNDANCE_MMIO is not set
+# CONFIG_TLAN is not set
+# CONFIG_TC35815 is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_RHINE_MMIO is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+CONFIG_TIGON3=y
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Input core support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_SERIAL_HCDP=y
+CONFIG_SERIAL_ACPI=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+# CONFIG_MK712_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_INPUT_NS558 is not set
+# CONFIG_INPUT_LIGHTNING is not set
+# CONFIG_INPUT_PCIGAME is not set
+# CONFIG_INPUT_CS461X is not set
+# CONFIG_INPUT_EMU10K1 is not set
+CONFIG_INPUT_SERIO=y
+CONFIG_INPUT_SERPORT=y
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_ANALOG is not set
+# CONFIG_INPUT_A3D is not set
+# CONFIG_INPUT_ADI is not set
+# CONFIG_INPUT_COBRA is not set
+# CONFIG_INPUT_GF2K is not set
+# CONFIG_INPUT_GRIP is not set
+# CONFIG_INPUT_INTERACT is not set
+# CONFIG_INPUT_TMDC is not set
+# CONFIG_INPUT_SIDEWINDER is not set
+# CONFIG_INPUT_IFORCE_USB is not set
+# CONFIG_INPUT_IFORCE_232 is not set
+# CONFIG_INPUT_WARRIOR is not set
+# CONFIG_INPUT_MAGELLAN is not set
+# CONFIG_INPUT_SPACEORB is not set
+# CONFIG_INPUT_SPACEBALL is not set
+# CONFIG_INPUT_STINGER is not set
+# CONFIG_INPUT_DB9 is not set
+# CONFIG_INPUT_GAMECON is not set
+# CONFIG_INPUT_TURBOGRAFX is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_IPMI_PANIC_EVENT is not set
+# CONFIG_IPMI_DEVICE_INTERFACE is not set
+# CONFIG_IPMI_KCS is not set
+# CONFIG_IPMI_WATCHDOG is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_SCx200_GPIO is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_AMD_PM768 is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+CONFIG_EFI_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+CONFIG_AGP=y
+# CONFIG_AGP_INTEL is not set
+# CONFIG_AGP_I810 is not set
+# CONFIG_AGP_VIA is not set
+# CONFIG_AGP_AMD is not set
+# CONFIG_AGP_AMD_8151 is not set
+# CONFIG_AGP_SIS is not set
+# CONFIG_AGP_ALI is not set
+# CONFIG_AGP_SWORKS is not set
+CONFIG_AGP_I460=y
+CONFIG_AGP_HP_ZX1=y
+CONFIG_DRM=y
+# CONFIG_DRM_OLD is not set
+
+#
+# DRM 4.1 drivers
+#
+CONFIG_DRM_NEW=y
+# CONFIG_DRM_TDFX is not set
+CONFIG_DRM_R128=y
+CONFIG_DRM_RADEON=y
+# CONFIG_DRM_I810 is not set
+# CONFIG_DRM_I810_XFREE_41 is not set
+# CONFIG_DRM_I830 is not set
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_SIS is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+
+#
+# Video For Linux
+#
+CONFIG_VIDEO_PROC_FS=y
+# CONFIG_I2C_PARPORT is not set
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_ZORAN_BUZ is not set
+# CONFIG_VIDEO_ZORAN_DC10 is not set
+# CONFIG_VIDEO_ZORAN_LML33 is not set
+# CONFIG_VIDEO_ZR36120 is not set
+# CONFIG_VIDEO_MEYE is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_JBD=y
+CONFIG_JBD_DEBUG=y
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_UMSDOS_FS is not set
+CONFIG_VFAT_FS=y
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_TMPFS is not set
+CONFIG_RAMFS=y
+CONFIG_HUGETLBFS=y
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_JFS_DEBUG is not set
+# CONFIG_JFS_STATISTICS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_TCP is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+# CONFIG_ZISOFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Console drivers
+#
+CONFIG_VGA_CONSOLE=y
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+# CONFIG_SOUND_ALI5455 is not set
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_MIDI_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+CONFIG_SOUND_CS4281=y
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_MIDI_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+
+#
+# USB support
+#
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_UHCI=y
+# CONFIG_USB_UHCI_ALT is not set
+CONFIG_USB_OHCI=y
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_MIDI is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+CONFIG_USB_HID=y
+CONFIG_USB_HIDINPUT=y
+CONFIG_USB_HIDDEV=y
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_AX8817X is not set
+# CONFIG_USB_CDCETHER is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_TIGL is not set
+# CONFIG_USB_BRLVGER is not set
+# CONFIG_USB_LCD is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+# CONFIG_ZLIB_INFLATE is not set
+# CONFIG_ZLIB_DEFLATE is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BLUEZ is not set
+
+#
+# Simulated drivers
+#
+# CONFIG_HP_SIMETH is not set
+# CONFIG_HP_SIMSERIAL is not set
+# CONFIG_HP_SIMSCSI is not set
+
+#
+# Kernel hacking
+#
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_IA64_PRINT_HAZARDS=y
+# CONFIG_DISABLE_VHPT is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_IA64_EARLY_PRINTK=y
+CONFIG_IA64_EARLY_PRINTK_UART=y
+CONFIG_IA64_EARLY_PRINTK_UART_BASE=0
+# CONFIG_IA64_EARLY_PRINTK_VGA is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
diff -urN linux-2.4.23-pre3/arch/ia64/configs/ski linux-2.4.23-pre4/arch/ia64/configs/ski
--- linux-2.4.23-pre3/arch/ia64/configs/ski	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/configs/ski	2003-09-12 12:44:34.000000000 -0700
@@ -47,6 +47,7 @@
 # CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
+CONFIG_IA64_PAL_IDLE=y
 CONFIG_SMP=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_PERFMON=y
@@ -152,12 +153,9 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AACRAID is not set
-CONFIG_SCSI_AIC7XXX=y
-CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
-CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+# CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
@@ -311,6 +309,7 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -320,6 +319,7 @@
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BEFS_DEBUG is not set
 # CONFIG_BFS_FS is not set
@@ -370,6 +370,7 @@
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
diff -urN linux-2.4.23-pre3/arch/ia64/configs/zx1 linux-2.4.23-pre4/arch/ia64/configs/zx1
--- linux-2.4.23-pre3/arch/ia64/configs/zx1	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/configs/zx1	2003-09-12 12:44:34.000000000 -0700
@@ -37,6 +37,7 @@
 CONFIG_IA64_PAGE_SIZE_16KB=y
 # CONFIG_IA64_PAGE_SIZE_64KB is not set
 CONFIG_IA64_L1_CACHE_SHIFT=7
+# CONFIG_NUMA is not set
 CONFIG_IA64_MCA=y
 CONFIG_PM=y
 CONFIG_KCORE_ELF=y
@@ -50,6 +51,7 @@
 # CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
+CONFIG_IA64_PAL_IDLE=y
 CONFIG_SMP=y
 CONFIG_IA32_SUPPORT=y
 CONFIG_PERFMON=y
@@ -271,7 +273,6 @@
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
 # CONFIG_PDC202XX_BURST is not set
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_PDC202XX_FORCE is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_SVWKS is not set
@@ -330,6 +331,9 @@
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set
 # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
@@ -407,6 +411,7 @@
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
 # CONFIG_CS89x0 is not set
 CONFIG_TULIP=y
 # CONFIG_TULIP_MWI is not set
@@ -446,6 +451,7 @@
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
 # CONFIG_MYRI_SBUS is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
@@ -657,6 +663,7 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -666,6 +673,7 @@
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BEFS_DEBUG is not set
 # CONFIG_BFS_FS is not set
@@ -716,6 +724,7 @@
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
@@ -917,6 +926,7 @@
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_CATC is not set
+# CONFIG_USB_AX8817X is not set
 # CONFIG_USB_CDCETHER is not set
 # CONFIG_USB_USBNET is not set
 
@@ -940,8 +950,14 @@
 # CONFIG_USB_LCD is not set
 
 #
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
 # Library routines
 #
+# CONFIG_CRC32 is not set
 # CONFIG_ZLIB_INFLATE is not set
 # CONFIG_ZLIB_DEFLATE is not set
 
diff -urN linux-2.4.23-pre3/arch/ia64/defconfig linux-2.4.23-pre4/arch/ia64/defconfig
--- linux-2.4.23-pre3/arch/ia64/defconfig	2003-09-12 12:44:32.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/defconfig	2003-09-12 12:44:34.000000000 -0700
@@ -38,6 +38,7 @@
 CONFIG_IA64_BRL_EMU=y
 # CONFIG_ITANIUM_BSTEP_SPECIFIC is not set
 CONFIG_IA64_L1_CACHE_SHIFT=6
+# CONFIG_NUMA is not set
 CONFIG_IA64_MCA=y
 CONFIG_PM=y
 CONFIG_KCORE_ELF=y
@@ -49,6 +50,7 @@
 # CONFIG_HUGETLB_PAGE_SIZE_4MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
 # CONFIG_HUGETLB_PAGE_SIZE_256KB is not set
+# CONFIG_IA64_PAL_IDLE is not set
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 CONFIG_IA32_SUPPORT=y
@@ -271,7 +273,6 @@
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
 # CONFIG_PDC202XX_BURST is not set
 # CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_PDC202XX_FORCE is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_SVWKS is not set
@@ -330,6 +331,9 @@
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set
 # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
@@ -412,6 +416,7 @@
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
 # CONFIG_CS89x0 is not set
 CONFIG_TULIP=y
 # CONFIG_TULIP_MWI is not set
@@ -451,6 +456,7 @@
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
 CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
 # CONFIG_MYRI_SBUS is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
@@ -662,6 +668,7 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -671,6 +678,7 @@
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BEFS_DEBUG is not set
 # CONFIG_BFS_FS is not set
@@ -721,6 +729,7 @@
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
@@ -922,6 +931,7 @@
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_KAWETH is not set
 # CONFIG_USB_CATC is not set
+# CONFIG_USB_AX8817X is not set
 # CONFIG_USB_CDCETHER is not set
 # CONFIG_USB_USBNET is not set
 
@@ -945,8 +955,14 @@
 # CONFIG_USB_LCD is not set
 
 #
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
 # Library routines
 #
+# CONFIG_CRC32 is not set
 # CONFIG_ZLIB_INFLATE is not set
 # CONFIG_ZLIB_DEFLATE is not set
 
diff -urN linux-2.4.23-pre3/arch/ia64/hp/common/sba_iommu.c linux-2.4.23-pre4/arch/ia64/hp/common/sba_iommu.c
--- linux-2.4.23-pre3/arch/ia64/hp/common/sba_iommu.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/hp/common/sba_iommu.c	2003-09-12 12:44:34.000000000 -0700
@@ -1895,22 +1895,26 @@
 	struct ioc *ioc;
 	acpi_status status;
 	u64 hpa, length;
-	acpi_device_info dev_info;
+	struct acpi_buffer buffer;
+	struct acpi_device_info *dev_info;
 
 	status = acpi_hp_csr_space(device->handle, &hpa, &length);
 	if (ACPI_FAILURE(status))
 		return 1;
 
-	status = acpi_get_object_info(device->handle, &dev_info);
+	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+	status = acpi_get_object_info(device->handle, &buffer);
 	if (ACPI_FAILURE(status))
 		return 1;
+	dev_info = buffer.pointer;
 
 	/*
 	 * For HWP0001, only SBA appears in ACPI namespace.  It encloses the PCI
 	 * root bridges, and its CSR space includes the IOC function.
 	 */
-	if (strncmp("HWP0001", dev_info.hardware_id, 7) == 0)
+	if (strncmp("HWP0001", dev_info->hardware_id.value, 7) == 0)
 		hpa += ZX1_IOC_OFFSET;
+	ACPI_MEM_FREE(dev_info);
 
 	ioc = ioc_init(hpa, device->handle);
 	if (!ioc)
diff -urN linux-2.4.23-pre3/arch/ia64/hp/zx1/hpzx1_misc.c linux-2.4.23-pre4/arch/ia64/hp/zx1/hpzx1_misc.c
--- linux-2.4.23-pre3/arch/ia64/hp/zx1/hpzx1_misc.c	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/hp/zx1/hpzx1_misc.c	2003-09-12 12:44:34.000000000 -0700
@@ -210,7 +210,7 @@
 {
 	u64 csr_base = 0, csr_length = 0;
 	acpi_status status;
-	NATIVE_UINT busnum;
+	acpi_native_uint busnum;
 	char *name = context;
 	char fullname[32];
 
diff -urN linux-2.4.23-pre3/arch/ia64/ia32/ia32_signal.c linux-2.4.23-pre4/arch/ia64/ia32/ia32_signal.c
--- linux-2.4.23-pre3/arch/ia64/ia32/ia32_signal.c	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/ia32/ia32_signal.c	2003-09-12 12:44:34.000000000 -0700
@@ -171,8 +171,10 @@
  *    datasel    ar.fdr(32:47)
  *
  *    _st[(0+TOS)%8]   f8
- *    _st[(1+TOS)%8]   f9                    (f8, f9 from ptregs)
- *      : :            :                     (f10..f15 from live reg)
+ *    _st[(1+TOS)%8]   f9
+ *    _st[(2+TOS)%8]   f10
+ *    _st[(3+TOS)%8]   f11                   (f8..f11 from ptregs)
+ *      : :            :                     (f12..f15 from live reg)
  *      : :            :
  *    _st[(7+TOS)%8]   f15                   TOS=sw.top(bits11:13)
  *
@@ -254,8 +256,8 @@
 	__put_user( 0, &save->magic); //#define X86_FXSR_MAGIC   0x0000
 
 	/*
-	 * save f8 and f9  from pt_regs
-	 * save f10..f15 from live register set
+	 * save f8..f11  from pt_regs
+	 * save f12..f15 from live register set
 	 */
 	/*
 	 *  Find the location where f8 has to go in fp reg stack.  This depends on
@@ -270,11 +272,11 @@
 	copy_to_user(&save->_st[(0+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
 	ia64f2ia32f(fpregp, &ptp->f9);
 	copy_to_user(&save->_st[(1+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
-
-	__stfe(fpregp, 10);
+	ia64f2ia32f(fpregp, &ptp->f10);
 	copy_to_user(&save->_st[(2+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
-	__stfe(fpregp, 11);
+	ia64f2ia32f(fpregp, &ptp->f11);
 	copy_to_user(&save->_st[(3+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
+
 	__stfe(fpregp, 12);
 	copy_to_user(&save->_st[(4+fr8_st_map)&0x7], fpregp, sizeof(struct _fpreg_ia32));
 	__stfe(fpregp, 13);
@@ -386,8 +388,8 @@
 	asm volatile ( "mov ar.fdr=%0;" :: "r"(fdr));
 
 	/*
-	 * restore f8, f9 onto pt_regs
-	 * restore f10..f15 onto live registers
+	 * restore f8..f11 onto pt_regs
+	 * restore f12..f15 onto live registers
 	 */
 	/*
 	 *  Find the location where f8 has to go in fp reg stack.  This depends on
@@ -403,11 +405,11 @@
 	ia32f2ia64f(&ptp->f8, fpregp);
 	copy_from_user(fpregp, &save->_st[(1+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
 	ia32f2ia64f(&ptp->f9, fpregp);
-
 	copy_from_user(fpregp, &save->_st[(2+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
-	__ldfe(10, fpregp);
+	ia32f2ia64f(&ptp->f10, fpregp);
 	copy_from_user(fpregp, &save->_st[(3+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
-	__ldfe(11, fpregp);
+	ia32f2ia64f(&ptp->f11, fpregp);
+
 	copy_from_user(fpregp, &save->_st[(4+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
 	__ldfe(12, fpregp);
 	copy_from_user(fpregp, &save->_st[(5+fr8_st_map)&0x7], sizeof(struct _fpreg_ia32));
@@ -739,11 +741,11 @@
 
 #define COPY(ia64x, ia32x)	err |= __get_user(regs->ia64x, &sc->ia32x)
 
-#define copyseg_gs(tmp)		(regs->r16 |= (unsigned long) tmp << 48)
-#define copyseg_fs(tmp)		(regs->r16 |= (unsigned long) tmp << 32)
+#define copyseg_gs(tmp)		(regs->r16 |= (unsigned long) (tmp) << 48)
+#define copyseg_fs(tmp)		(regs->r16 |= (unsigned long) (tmp) << 32)
 #define copyseg_cs(tmp)		(regs->r17 |= tmp)
-#define copyseg_ss(tmp)		(regs->r17 |= (unsigned long) tmp << 16)
-#define copyseg_es(tmp)		(regs->r16 |= (unsigned long) tmp << 16)
+#define copyseg_ss(tmp)		(regs->r17 |= (unsigned long) (tmp) << 16)
+#define copyseg_es(tmp)		(regs->r16 |= (unsigned long) (tmp) << 16)
 #define copyseg_ds(tmp)		(regs->r16 |= tmp)
 
 #define COPY_SEG(seg)					\
diff -urN linux-2.4.23-pre3/arch/ia64/ia32/ia32_support.c linux-2.4.23-pre4/arch/ia64/ia32/ia32_support.c
--- linux-2.4.23-pre3/arch/ia64/ia32/ia32_support.c	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/ia32/ia32_support.c	2003-09-12 12:44:34.000000000 -0700
@@ -60,30 +60,26 @@
 	regs->r27 = load_desc(regs->r16 >>  0);		/* DSD */
 	regs->r28 = load_desc(regs->r16 >> 32);		/* FSD */
 	regs->r29 = load_desc(regs->r16 >> 48);		/* GSD */
-	task->thread.csd = load_desc(regs->r17 >>  0);	/* CSD */
-	task->thread.ssd = load_desc(regs->r17 >> 16);	/* SSD */
+	regs->ar_csd = load_desc(regs->r17 >>  0);	/* CSD */
+	regs->ar_ssd = load_desc(regs->r17 >> 16);	/* SSD */
 }
 
 void
 ia32_save_state (struct task_struct *t)
 {
-	unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd;
+	unsigned long eflag, fsr, fcr, fir, fdr;
 
 	asm ("mov %0=ar.eflag;"
 	     "mov %1=ar.fsr;"
 	     "mov %2=ar.fcr;"
 	     "mov %3=ar.fir;"
 	     "mov %4=ar.fdr;"
-	     "mov %5=ar.csd;"
-	     "mov %6=ar.ssd;"
-	     : "=r"(eflag), "=r"(fsr), "=r"(fcr), "=r"(fir), "=r"(fdr), "=r"(csd), "=r"(ssd));
+	     : "=r"(eflag), "=r"(fsr), "=r"(fcr), "=r"(fir), "=r"(fdr));
 	t->thread.eflag = eflag;
 	t->thread.fsr = fsr;
 	t->thread.fcr = fcr;
 	t->thread.fir = fir;
 	t->thread.fdr = fdr;
-	t->thread.csd = csd;
-	t->thread.ssd = ssd;
 	ia64_set_kr(IA64_KR_IO_BASE, t->thread.old_iob);
 	ia64_set_kr(IA64_KR_TSSD, t->thread.old_k1);
 }
@@ -91,7 +87,7 @@
 void
 ia32_load_state (struct task_struct *t)
 {
-	unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd, tssd;
+	unsigned long eflag, fsr, fcr, fir, fdr, tssd;
 	struct pt_regs *regs = ia64_task_regs(t);
 	int nr = smp_processor_id();	/* LDT and TSS depend on CPU number: */
 
@@ -100,8 +96,6 @@
 	fcr = t->thread.fcr;
 	fir = t->thread.fir;
 	fdr = t->thread.fdr;
-	csd = t->thread.csd;
-	ssd = t->thread.ssd;
 	tssd = load_desc(_TSS(nr));					/* TSSD */
 
 	asm volatile ("mov ar.eflag=%0;"
@@ -109,9 +103,7 @@
 		      "mov ar.fcr=%2;"
 		      "mov ar.fir=%3;"
 		      "mov ar.fdr=%4;"
-		      "mov ar.csd=%5;"
-		      "mov ar.ssd=%6;"
-		      :: "r"(eflag), "r"(fsr), "r"(fcr), "r"(fir), "r"(fdr), "r"(csd), "r"(ssd));
+		      :: "r"(eflag), "r"(fsr), "r"(fcr), "r"(fir), "r"(fdr));
 	current->thread.old_iob = ia64_get_kr(IA64_KR_IO_BASE);
 	current->thread.old_k1 = ia64_get_kr(IA64_KR_TSSD);
 	ia64_set_kr(IA64_KR_IO_BASE, IA32_IOBASE);
diff -urN linux-2.4.23-pre3/arch/ia64/ia32/sys_ia32.c linux-2.4.23-pre4/arch/ia64/ia32/sys_ia32.c
--- linux-2.4.23-pre3/arch/ia64/ia32/sys_ia32.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/ia32/sys_ia32.c	2003-09-12 12:44:34.000000000 -0700
@@ -38,6 +38,7 @@
 #include <linux/smb_mount.h>
 #include <linux/ncp_fs.h>
 #include <linux/quota.h>
+#include <linux/quotacompat.h>
 #include <linux/module.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
@@ -165,9 +166,9 @@
 		current->thread.map_base  = old_map_base;
 		current->thread.task_size = old_task_size;
 		set_fs(USER_DS);	/* establish new task-size as the address-limit */
-	  out:
-		kfree(av);
 	}
+  out:
+	kfree(av);
 	return r;
 }
 
@@ -2147,7 +2148,6 @@
 #define SEMOP		 1
 #define SEMGET		 2
 #define SEMCTL		 3
-#define SEMTIMEDOP	 4
 #define MSGSND		11
 #define MSGRCV		12
 #define MSGGET		13
@@ -2579,17 +2579,6 @@
 	return err;
 }
 
-static long
-semtimedop32(int semid, struct sembuf *tsems, int nsems,
-	     const struct timespec32 *timeout32)
-{
-	struct timespec t;
-	if (get_user (t.tv_sec, &timeout32->tv_sec) ||
-	    get_user (t.tv_nsec, &timeout32->tv_nsec))
-		return -EFAULT;
-	return sys_semtimedop(semid, tsems, nsems, &t);
-}
-
 asmlinkage long
 sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
 {
@@ -2601,11 +2590,7 @@
 	switch (call) {
 	      case SEMOP:
 		/* struct sembuf is the same on 32 and 64bit :)) */
-		return sys_semtimedop(first, (struct sembuf *)AA(ptr), second,
-				      NULL);
-	      case SEMTIMEDOP:
-		return semtimedop32(first, (struct sembuf *)AA(ptr), second, 
-				    (const struct timespec32 *)AA(fifth));
+		return sys_semop(first, (struct sembuf *)AA(ptr), second);
 	      case SEMGET:
 		return sys_semget(first, second, third);
 	      case SEMCTL:
@@ -2903,12 +2888,16 @@
 		ia64f2ia32f(f, &ptp->f9);
 		break;
 	      case 2:
+		ia64f2ia32f(f, &ptp->f10);
+		break;
 	      case 3:
+		ia64f2ia32f(f, &ptp->f11);
+		break;
 	      case 4:
 	      case 5:
 	      case 6:
 	      case 7:
-		ia64f2ia32f(f, &swp->f10 + (regno - 2));
+		ia64f2ia32f(f, &swp->f12 + (regno - 4));
 		break;
 	}
 	copy_to_user(reg, f, sizeof(*reg));
@@ -2929,12 +2918,16 @@
 		copy_from_user(&ptp->f9, reg, sizeof(*reg));
 		break;
 	      case 2:
+		copy_from_user(&ptp->f10, reg, sizeof(*reg));
+		break;
 	      case 3:
+		copy_from_user(&ptp->f11, reg, sizeof(*reg));
+		break;
 	      case 4:
 	      case 5:
 	      case 6:
 	      case 7:
-		copy_from_user(&swp->f10 + (regno - 2), reg, sizeof(*reg));
+		copy_from_user(&swp->f12 + (regno - 4), reg, sizeof(*reg));
 		break;
 	}
 	return;
@@ -3635,9 +3628,11 @@
 			return -EFAULT;
 		old_fs = get_fs();
 		set_fs(KERNEL_DS);
-		ret = sys_fcntl(fd, cmd, (unsigned long) &f);
+		ret = sys_fcntl(fd, (cmd == F_GETLK64) ? F_GETLK :
+			((cmd == F_SETLK64) ? F_SETLK : F_SETLKW),
+			(unsigned long) &f);
 		set_fs(old_fs);
-		if (cmd == F_GETLK && ia32_put_flock(&f, arg))
+		if (cmd == F_GETLK64 && ia32_put_flock(&f, arg))
 			return -EFAULT;
 		break;
 
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/Makefile linux-2.4.23-pre4/arch/ia64/kernel/Makefile
--- linux-2.4.23-pre3/arch/ia64/kernel/Makefile	2002-11-28 15:53:09.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/kernel/Makefile	2003-09-12 12:44:34.000000000 -0700
@@ -17,6 +17,7 @@
 	 machvec.o pal.o process.o perfmon.o ptrace.o sal.o salinfo.o semaphore.o setup.o	 \
 	 signal.o sys_ia64.o traps.o time.o unaligned.o unwind.o
 obj-$(CONFIG_IA64_GENERIC) += iosapic.o
+obj-$(CONFIG_IA64_SGI_SN2) += iosapic.o
 obj-$(CONFIG_IA64_HP_ZX1) += iosapic.o
 obj-$(CONFIG_IA64_DIG) += iosapic.o
 obj-$(CONFIG_IA64_PALINFO) += palinfo.o
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/acpi.c linux-2.4.23-pre4/arch/ia64/kernel/acpi.c
--- linux-2.4.23-pre3/arch/ia64/kernel/acpi.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/acpi.c	2003-09-12 12:44:34.000000000 -0700
@@ -8,6 +8,9 @@
  *  Copyright (C) 2000 Intel Corp.
  *  Copyright (C) 2000,2001 J.I. Lee <jung-ik.lee@intel.com>
  *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
+ *  Copyright (C) 2001 Jenna Hall <jenna.s.hall@intel.com>
+ *  Copyright (C) 2001 Takayoshi Kochi <t-kouchi@cq.jp.nec.com>
+ *  Copyright (C) 2002 Erich Focht <efocht@ess.nec.de>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
@@ -38,11 +41,14 @@
 #include <linux/irq.h>
 #include <linux/acpi.h>
 #include <linux/efi.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
 #include <asm/io.h>
 #include <asm/iosapic.h>
 #include <asm/machvec.h>
 #include <asm/page.h>
 #include <asm/system.h>
+#include <asm/numa.h>
 
 
 #define PREFIX			"ACPI: "
@@ -59,6 +65,8 @@
 
 unsigned char acpi_kbd_controller_present = 1;
 
+int acpi_disabled __initdata;	/* XXX this shouldn't be needed---we can't boot without ACPI! */
+
 const char *
 acpi_get_sysname (void)
 {
@@ -90,6 +98,9 @@
 	if (!strcmp(hdr->oem_id, "HP")) {
 		return "hpzx1";
 	}
+	else if (!strcmp(hdr->oem_id, "SGI")) {
+		return "sn2";
+	}
 
 	return "dig";
 #else
@@ -97,8 +108,6 @@
 	return "hpsim";
 # elif defined (CONFIG_IA64_HP_ZX1)
 	return "hpzx1";
-# elif defined (CONFIG_IA64_SGI_SN1)
-	return "sn1";
 # elif defined (CONFIG_IA64_SGI_SN2)
 	return "sn2";
 # elif defined (CONFIG_IA64_DIG)
@@ -123,17 +132,17 @@
 };
 
 acpi_status
-acpi_vendor_resource_match(acpi_resource *resource, void *context)
+acpi_vendor_resource_match (struct acpi_resource *resource, void *context)
 {
 	struct acpi_vendor_info *info = (struct acpi_vendor_info *) context;
-	acpi_resource_vendor *vendor;
+	struct acpi_resource_vendor *vendor;
 	struct acpi_vendor_descriptor *descriptor;
 	u32 length;
 
 	if (resource->id != ACPI_RSTYPE_VENDOR)
 		return AE_OK;
 
-	vendor = (acpi_resource_vendor *) &resource->data;
+	vendor = (struct acpi_resource_vendor *) &resource->data;
 	descriptor = (struct acpi_vendor_descriptor *) vendor->reserved;
 	if (vendor->length <= sizeof(*info->descriptor) ||
 	    descriptor->guid_id != info->descriptor->guid_id ||
@@ -151,7 +160,7 @@
 }
 
 acpi_status
-acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor *id,
+acpi_find_vendor_resource (acpi_handle obj, struct acpi_vendor_descriptor *id,
 		u8 **data, u32 *length)
 {
 	struct acpi_vendor_info info;
@@ -174,12 +183,11 @@
 };
 
 acpi_status
-acpi_hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
+acpi_hp_csr_space (acpi_handle obj, u64 *csr_base, u64 *csr_length)
 {
 	acpi_status status;
 	u8 *data;
 	u32 length;
-	int i;
 
 	status = acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length);
 
@@ -200,7 +208,9 @@
 #define ACPI_MAX_PLATFORM_INTERRUPTS	256
 
 /* Array to record platform interrupt vectors for generic interrupt routing. */
-int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = { [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1 };
+int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = {
+	[0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1
+};
 
 enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC;
 
@@ -214,7 +224,7 @@
 	int vector = -1;
 
 	if (int_type < ACPI_MAX_PLATFORM_INTERRUPTS) {
-		/* correctable platform error interrupt */
+		/* corrected platform error interrupt */
 		vector = platform_intr_list[int_type];
 	} else
 		printk(KERN_ERR "acpi_request_vector(): invalid interrupt type\n");
@@ -252,7 +262,6 @@
 		iounmap((void *) ipi_base_addr);
 		ipi_base_addr = (unsigned long) ioremap(lapic->address, 0);
 	}
-
 	return 0;
 }
 
@@ -261,7 +270,6 @@
 acpi_parse_lsapic (acpi_table_entry_header *header)
 {
 	struct acpi_table_lsapic *lsapic;
-	int phys_id;
 
 	lsapic = (struct acpi_table_lsapic *) header;
 	if (!lsapic)
@@ -269,30 +277,21 @@
 
 	acpi_table_print_madt_entry(header);
 
-	phys_id = (lsapic->id << 8) | lsapic->eid;
-
-	if (total_cpus == NR_CPUS) {
-		printk(KERN_ERR PREFIX "Ignoring CPU (0x%04x) (NR_CPUS == %d)\n",
-			phys_id, NR_CPUS);
-		return 0;
-	}
-
-	printk(KERN_INFO "CPU %d (0x%04x)", total_cpus, phys_id);
+	printk(KERN_INFO "CPU %d (0x%04x)", total_cpus, (lsapic->id << 8) | lsapic->eid);
 
-	if (lsapic->flags.enabled) {
-		available_cpus++;
+	if (!lsapic->flags.enabled)
+		printk(" disabled");
+	else if (available_cpus >= NR_CPUS)
+		printk(" ignored (increase NR_CPUS)");
+	else {
 		printk(" enabled");
 #ifdef CONFIG_SMP
-		smp_boot_data.cpu_phys_id[total_cpus] = phys_id;
-		if (hard_smp_processor_id() == smp_boot_data.cpu_phys_id[total_cpus])
+		smp_boot_data.cpu_phys_id[available_cpus] = (lsapic->id << 8) | lsapic->eid;
+		if (hard_smp_processor_id()
+		    == (unsigned int) smp_boot_data.cpu_phys_id[available_cpus])
 			printk(" (BSP)");
 #endif
-	}
-	else {
-		printk(" disabled");
-#ifdef CONFIG_SMP
-		smp_boot_data.cpu_phys_id[total_cpus] = -1;
-#endif
+		++available_cpus;
 	}
 
 	printk("\n");
@@ -314,7 +313,6 @@
 	acpi_table_print_madt_entry(header);
 
 	/* TBD: Support lapic_nmi entries */
-
 	return 0;
 }
 
@@ -405,7 +403,6 @@
 	acpi_table_print_madt_entry(header);
 
 	/* TBD: Support nimsrc entries */
-
 	return 0;
 }
 
@@ -437,22 +434,209 @@
 }
 
 
+#ifdef CONFIG_ACPI_NUMA
+
+#define PXM_FLAG_LEN ((MAX_PXM_DOMAINS + 1)/32)
+
+static int __initdata srat_num_cpus;			/* number of cpus */
+static u32 __initdata pxm_flag[PXM_FLAG_LEN];
+#define pxm_bit_set(bit)	(set_bit(bit,(void *)pxm_flag))
+#define pxm_bit_test(bit)	(test_bit(bit,(void *)pxm_flag))
+/* maps to convert between proximity domain and logical node ID */
+int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
+int __initdata nid_to_pxm_map[NR_NODES];
+struct acpi_table_slit __initdata *slit_table;
+
+/*
+ * ACPI 2.0 SLIT (System Locality Information Table)
+ * http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf
+ */
+void __init
+acpi_numa_slit_init (struct acpi_table_slit *slit)
+{
+	u32 len;
+
+	len = sizeof(struct acpi_table_header) + 8
+		+ slit->localities * slit->localities;
+	if (slit->header.length != len) {
+		printk("KERN_INFO ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
+		      len, slit->header.length);
+		memset(numa_slit, 10, sizeof(numa_slit));
+		return;
+	}
+	slit_table = slit;
+}
+
+void __init
+acpi_numa_processor_affinity_init (struct acpi_table_processor_affinity *pa)
+{
+	/* record this node in proximity bitmap */
+	pxm_bit_set(pa->proximity_domain);
+
+	node_cpuid[srat_num_cpus].phys_id = (pa->apic_id << 8) | (pa->lsapic_eid);
+	/* nid should be overridden as logical node id later */
+	node_cpuid[srat_num_cpus].nid = pa->proximity_domain;
+	srat_num_cpus++;
+}
+
+void __init
+acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma)
+{
+	unsigned long paddr, size, hole_size, min_hole_size;
+	u8 pxm;
+	struct node_memblk_s *p, *q, *pend;
+
+	pxm = ma->proximity_domain;
+
+	/* fill node memory chunk structure */
+	paddr = ma->base_addr_hi;
+	paddr = (paddr << 32) | ma->base_addr_lo;
+	size = ma->length_hi;
+	size = (size << 32) | ma->length_lo;
+
+	if (num_memblks >= NR_MEMBLKS) {
+		printk(KERN_ERR "Too many mem chunks in SRAT. Ignoring %ld MBytes at %lx\n",
+			size/(1024*1024), paddr);
+		return;
+	}
+
+	/* Ignore disabled entries */
+	if (!ma->flags.enabled)
+		return;
+
+	/*
+	 * When the chunk is not the first one in the node, check distance
+	 * from the other chunks. When the hole is too huge ignore the chunk.
+	 * This restriction should be removed when multiple chunks per node
+	 * is supported.
+	 */
+	pend = &node_memblk[num_memblks];
+	min_hole_size = 0;
+	for (p = &node_memblk[0]; p < pend; p++) {
+		if (p->nid != pxm)
+			continue;
+		if (p->start_paddr < paddr)
+			hole_size = paddr - (p->start_paddr + p->size);
+		else
+			hole_size = p->start_paddr - (paddr + size);
+
+		if (!min_hole_size || hole_size < min_hole_size)
+			min_hole_size = hole_size;
+	}
+
+#if 0	/* test */
+	if (min_hole_size) {
+		if (min_hole_size > size) {
+			printk(KERN_ERR "Too huge memory hole. Ignoring %ld MBytes at %lx\n",
+				size/(1024*1024), paddr);
+			return;
+		}
+	}
+#endif
+
+	/* record this node in proximity bitmap */
+	pxm_bit_set(pxm);
+
+	/* Insertion sort based on base address */
+	pend = &node_memblk[num_memblks];
+	for (p = &node_memblk[0]; p < pend; p++) {
+		if (paddr < p->start_paddr)
+			break;
+	}
+	if (p < pend) {
+		for (q = pend; q >= p; q--)
+			*(q + 1) = *q;
+	}
+	p->start_paddr = paddr;
+	p->size = size;
+	p->nid = pxm;
+	num_memblks++;
+}
+
+void __init
+acpi_numa_arch_fixup(void)
+{
+	int i, j, node_from, node_to;
+
+	if (srat_num_cpus == 0) {
+		node_cpuid[0].phys_id = hard_smp_processor_id();
+		return;
+	}
+
+	/* calculate total number of nodes in system from PXM bitmap */
+	numnodes = 0;		/* init total nodes in system */
+
+	memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map));
+	memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map));
+	for (i = 0; i < MAX_PXM_DOMAINS; i++) {
+		if (pxm_bit_test(i)) {
+			pxm_to_nid_map[i] = numnodes;
+			nid_to_pxm_map[numnodes++] = i;
+		}
+	}
+
+	/* set logical node id in memory chunk structure */
+	for (i = 0; i < num_memblks; i++)
+		node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid];
+
+	/* assign memory bank numbers for each chunk on each node */
+	for (i = 0; i < numnodes; i++) {
+		int bank;
+
+		bank = 0;
+		for (j = 0; j < num_memblks; j++)
+			if (node_memblk[j].nid == i)
+				node_memblk[j].bank = bank++;
+	}
+
+	/* set logical node id in cpu structure */
+	for (i = 0; i < srat_num_cpus; i++)
+		node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid];
+
+	printk(KERN_INFO "Number of logical nodes in system = %d\n", numnodes);
+	printk(KERN_INFO "Number of memory chunks in system = %d\n", num_memblks);
+
+	if (!slit_table) return;
+	memset(numa_slit, -1, sizeof(numa_slit));
+	for (i=0; i<slit_table->localities; i++) {
+		if (!pxm_bit_test(i))
+			continue;
+		node_from = pxm_to_nid_map[i];
+		for (j=0; j<slit_table->localities; j++) {
+			if (!pxm_bit_test(j))
+				continue;
+			node_to = pxm_to_nid_map[j];
+			node_distance(node_from, node_to) = 
+				slit_table->entry[i*slit_table->localities + j];
+		}
+	}
+
+#ifdef SLIT_DEBUG
+	printk(KERN_DEBUG "ACPI 2.0 SLIT locality table:\n");
+	for (i = 0; i < numnodes; i++) {
+		for (j = 0; j < numnodes; j++)
+			printk(KERN_DEBUG "%03d ", node_distance(i,j));
+		printk("\n");
+	}
+#endif
+}
+#endif /* CONFIG_ACPI_NUMA */
+
 static int __init
 acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
 {
 	struct acpi_table_header *fadt_header;
-	fadt_descriptor_rev2 *fadt;
+	struct fadt_descriptor_rev2 *fadt;
 	u32 sci_irq;
 
 	if (!phys_addr || !size)
 		return -EINVAL;
 
 	fadt_header = (struct acpi_table_header *) __va(phys_addr);
-
 	if (fadt_header->revision != 3)
 		return -ENODEV;		/* Only deal with ACPI 2.0 FADT */
 
-	fadt = (fadt_descriptor_rev2 *) fadt_header;
+	fadt = (struct fadt_descriptor_rev2 *) fadt_header;
 
 	if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER))
 		acpi_kbd_controller_present = 0;
@@ -479,20 +663,13 @@
 		rsdp_phys = __pa(efi.acpi20);
 	else if (efi.acpi)
 		printk(KERN_WARNING PREFIX "v1.0/r0.71 tables no longer supported\n");
-
 	return rsdp_phys;
 }
 
 
 int __init
-acpi_boot_init (char *cmdline)
+acpi_boot_init (void)
 {
-	int result;
-
-	/* Initialize the ACPI boot-time table parser */
-	result = acpi_table_init(cmdline);
-	if (result)
-		return result;
 
 	/*
 	 * MADT
@@ -509,65 +686,76 @@
 
 	/* Local APIC */
 
-	if (acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR,
-				  acpi_parse_lapic_addr_ovr) < 0)
+	if (acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr) < 0)
 		printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
 
-	if (acpi_table_parse_madt(ACPI_MADT_LSAPIC,
-				  acpi_parse_lsapic) < 1)
+	if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_parse_lsapic) < 1)
 		printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries\n");
 
-	if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI,
-				  acpi_parse_lapic_nmi) < 0)
+	if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi) < 0)
 		printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
 
 	/* I/O APIC */
 
-	if (acpi_table_parse_madt(ACPI_MADT_IOSAPIC,
-				  acpi_parse_iosapic) < 1)
-		printk(KERN_ERR PREFIX "Error parsing MADT - no IOAPIC entries\n");
+	if (acpi_table_parse_madt(ACPI_MADT_IOSAPIC, acpi_parse_iosapic) < 1)
+		printk(KERN_ERR PREFIX "Error parsing MADT - no IOSAPIC entries\n");
 
 	/* System-Level Interrupt Routing */
 
-	if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC,
-				  acpi_parse_plat_int_src) < 0)
+	if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC, acpi_parse_plat_int_src) < 0)
 		printk(KERN_ERR PREFIX "Error parsing platform interrupt source entry\n");
 
-	if (acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR,
-				  acpi_parse_int_src_ovr) < 0)
+	if (acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr) < 0)
 		printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
 
-	if (acpi_table_parse_madt(ACPI_MADT_NMI_SRC,
-				  acpi_parse_nmi_src) < 0)
+	if (acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src) < 0)
 		printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
-skip_madt:
+  skip_madt:
 
 	/*
-	 * The FADT table contains an SCI_INT line, by which the system
+	 * FADT says whether a legacy keyboard controller is present.
+	 * The FADT also contains an SCI_INT line, by which the system
 	 * gets interrupts such as power and sleep buttons.  If it's not
 	 * on a Legacy interrupt, it needs to be setup.
 	 */
-	if (acpi_table_parse(ACPI_FACP, acpi_parse_fadt) < 1)
+	if (acpi_table_parse(ACPI_FADT, acpi_parse_fadt) < 1)
 		printk(KERN_ERR PREFIX "Can't find FADT\n");
 
 #ifdef CONFIG_SMP
 	if (available_cpus == 0) {
 		printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n");
+		printk(KERN_INFO "CPU 0 (0x%04x)", hard_smp_processor_id());
+		smp_boot_data.cpu_phys_id[available_cpus] = hard_smp_processor_id();
 		available_cpus = 1; /* We've got at least one of these, no? */
 	}
-	smp_boot_data.cpu_count = total_cpus;
+	smp_boot_data.cpu_count = available_cpus;
+
+	smp_build_cpu_map();
+# ifdef CONFIG_NUMA
+	/* If the platform did not have an SRAT table, initialize the
+	 * node_cpuid table from the smp_boot_data array. All cpus
+	 * will be on node 0.
+	 */
+	if (srat_num_cpus == 0) {
+		int cpu, i=1;
+		for (cpu=0; cpu<smp_boot_data.cpu_count; cpu++)
+			if (smp_boot_data.cpu_phys_id[cpu] != hard_smp_processor_id())
+				node_cpuid[i++].phys_id = smp_boot_data.cpu_phys_id[cpu];
+	}
+	build_cpu_to_node_map();
+# endif
+
 #endif
 	/* Make boot-up look pretty */
 	printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
 	return 0;
 }
 
+/*
+ * PCI Interrupt Routing
+ */
 
-/* --------------------------------------------------------------------------
-                             PCI Interrupt Routing
-   -------------------------------------------------------------------------- */
 #ifdef CONFIG_PCI
-
 int __init
 acpi_get_prt (struct pci_vector_struct **vectors, int *count)
 {
@@ -609,7 +797,8 @@
 	*count = acpi_prt.count;
 	return 0;
 }
-#endif
+#endif /* CONFIG_PCI */
+
 /* Assume IA64 always use I/O SAPIC */
 
 int __init
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/efi.c linux-2.4.23-pre4/arch/ia64/kernel/efi.c
--- linux-2.4.23-pre3/arch/ia64/kernel/efi.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/efi.c	2003-09-12 12:44:34.000000000 -0700
@@ -46,7 +46,7 @@
  * prior to creating their own entries under /proc/efi.
  */
 #ifdef CONFIG_PROC_FS
-struct proc_dir_entry *efi_dir = NULL;
+struct proc_dir_entry *efi_dir;
 #endif
 
 static unsigned long mem_limit = ~0UL;
@@ -324,7 +324,7 @@
 				check_md = q;
 
 				if (check_md->attribute & EFI_MEMORY_WB)
-					trim_bottom(md, granule_addr);
+					trim_bottom(check_md, granule_addr);
 
 				if (check_md->phys_addr < granule_addr)
 					continue;
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/efi_stub.S linux-2.4.23-pre4/arch/ia64/kernel/efi_stub.S
--- linux-2.4.23-pre3/arch/ia64/kernel/efi_stub.S	2002-11-28 15:53:09.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/kernel/efi_stub.S	2003-09-12 12:44:34.000000000 -0700
@@ -62,7 +62,7 @@
 	mov b6=r2
 	;;
 	andcm r16=loc3,r16		// get psr with IT, DT, and RT bits cleared
-	br.call.sptk.many rp=ia64_switch_mode
+	br.call.sptk.many rp=ia64_switch_mode_phys
 .ret0:	mov out4=in5
 	mov out0=in1
 	mov out1=in2
@@ -73,7 +73,7 @@
 	br.call.sptk.many rp=b6		// call the EFI function
 .ret1:	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
 	mov r16=loc3
-	br.call.sptk.many rp=ia64_switch_mode // return to virtual mode
+	br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
 .ret2:	mov ar.rsc=loc4			// restore RSE configuration
 	mov ar.pfs=loc1
 	mov rp=loc0
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/efivars.c linux-2.4.23-pre4/arch/ia64/kernel/efivars.c
--- linux-2.4.23-pre3/arch/ia64/kernel/efivars.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/efivars.c	2003-09-12 12:44:34.000000000 -0700
@@ -119,7 +119,7 @@
 */
 static spinlock_t efivars_lock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(efivar_list);
-static struct proc_dir_entry *efi_vars_dir = NULL;
+static struct proc_dir_entry *efi_vars_dir;
 
 #define efivar_entry(n) list_entry(n, efivar_entry_t, list)
 
@@ -138,8 +138,7 @@
 static inline unsigned long
 utf8_strsize(efi_char16_t *data, unsigned long maxlength)
 {
-	return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) *
-		sizeof(efi_char16_t);
+	return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
 }
 
 
@@ -169,8 +168,7 @@
 			 efi_char16_t *variable_name,
 			 efi_guid_t *vendor_guid)
 {
-	int i, short_name_size = variable_name_size /
-		sizeof(efi_char16_t) + 38;
+	int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38;
 	char *short_name;
 	efivar_entry_t *new_efivar;
 
@@ -191,7 +189,7 @@
 
 	/* Convert Unicode to normal chars (assume top bits are 0),
 	   ala UTF-8 */
-	for (i=0; i<variable_name_size / sizeof(efi_char16_t); i++) {
+	for (i=0; i< (int) (variable_name_size / sizeof(efi_char16_t)); i++) {
 		short_name[i] = variable_name[i] & 0xFF;
 	}
 
@@ -290,7 +288,7 @@
 	}
 	if (copy_from_user(var_data, buffer, size)) {
 		MOD_DEC_USE_COUNT;
-                kfree(var_data);
+		kfree(var_data);
 		return -EFAULT;
 	}
 
@@ -433,7 +431,7 @@
 	   to do this.
 	*/
 	if (!efi_dir)
-                efi_dir = proc_mkdir("efi", NULL);
+		efi_dir = proc_mkdir("efi", NULL);
 
 	efi_systab_entry = create_proc_entry("systab", S_IRUSR | S_IRGRP, efi_dir);
 	if (efi_systab_entry)
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/entry.S linux-2.4.23-pre4/arch/ia64/kernel/entry.S
--- linux-2.4.23-pre3/arch/ia64/kernel/entry.S	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/entry.S	2003-09-12 12:44:34.000000000 -0700
@@ -3,6 +3,9 @@
  *
  * Kernel entry points.
  *
+ * Copyright (C) 2002-2003 
+ * 	Suresh Siddha <suresh.b.siddha@intel.com> 
+ *	Fenghua Yu <fenghua.yu@intel.com>
  * Copyright (C) 1998-2002 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1999 VA Linux Systems
@@ -48,7 +51,10 @@
 ENTRY(ia64_execve)
 	.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(3)
 	alloc loc1=ar.pfs,3,2,4,0
-	mov loc0=rp
+	/* Leave from kernel and restore all pt_regs to correspending registers. This is special 
+	 * because ia32 application needs scratch registers after return from execve.
+	 */
+	movl loc0=ia64_ret_from_execve_syscall 
 	.body
 	mov out0=in0			// filename
 	;;				// stop bit between alloc and call
@@ -72,19 +78,18 @@
 	 * this executes in less than 20 cycles even on Itanium, so it's not worth
 	 * optimizing for...).
 	 */
-	mov r4=0;		mov f2=f0;		mov b1=r0
-	mov r5=0;		mov f3=f0;		mov b2=r0
-	mov r6=0;		mov f4=f0;		mov b3=r0
-	mov r7=0;		mov f5=f0;		mov b4=r0
-	mov ar.unat=0;		mov f10=f0;		mov b5=r0
-	ldf.fill f11=[sp];	ldf.fill f12=[sp];	mov f13=f0
-	ldf.fill f14=[sp];	ldf.fill f15=[sp];	mov f16=f0
-	ldf.fill f17=[sp];	ldf.fill f18=[sp];	mov f19=f0
-	ldf.fill f20=[sp];	ldf.fill f21=[sp];	mov f22=f0
-	ldf.fill f23=[sp];	ldf.fill f24=[sp];	mov f25=f0
-	ldf.fill f26=[sp];	ldf.fill f27=[sp];	mov f28=f0
-	ldf.fill f29=[sp];	ldf.fill f30=[sp];	mov f31=f0
-	mov ar.lc=0
+	mov ar.unat=0; 		mov ar.lc=0;
+	mov r4=0;               mov f2=f0;              mov b1=r0
+	mov r5=0;               mov f3=f0;              mov b2=r0
+	mov r6=0;               mov f4=f0;              mov b3=r0
+	mov r7=0;               mov f5=f0;              mov b4=r0
+	ldf.fill f12=[sp];      mov f13=f0;             mov b5=r0
+	ldf.fill f14=[sp];      ldf.fill f15=[sp];      mov f16=f0
+	ldf.fill f17=[sp];      ldf.fill f18=[sp];      mov f19=f0
+	ldf.fill f20=[sp];      ldf.fill f21=[sp];      mov f22=f0
+	ldf.fill f23=[sp];      ldf.fill f24=[sp];      mov f25=f0
+	ldf.fill f26=[sp];      ldf.fill f27=[sp];      mov f28=f0
+	ldf.fill f29=[sp];      ldf.fill f30=[sp];      mov f31=f0
 	br.ret.sptk.many rp
 END(ia64_execve)
 
@@ -251,8 +256,6 @@
 	st8 [r14]=r21,16	// save b0
 	st8 [r15]=r22,16	// save b1
 	mov r25=b4
-	stf.spill [r2]=f10,32
-	stf.spill [r3]=f11,32
 	mov r26=b5
 	;;
 	st8 [r14]=r23,16	// save b2
@@ -351,9 +354,6 @@
 	ldf.fill f4=[r14],32
 	ldf.fill f5=[r15],32
 	;;
-	ldf.fill f10=[r14],32
-	ldf.fill f11=[r15],32
-	;;
 	ldf.fill f12=[r14],32
 	ldf.fill f13=[r15],32
 	;;
@@ -475,7 +475,7 @@
 .mem.offset 8,0;	st8.spill [r3]=r10	// clear error indication in slot for r10
 ia64_strace_leave_kernel:
 	br.call.sptk.many rp=invoke_syscall_trace // give parent a chance to catch return value
-.rety:	br.cond.sptk ia64_leave_kernel
+.rety:	br.cond.sptk ia64_leave_syscall
 
 strace_error:
 	ld8 r3=[r2]				// load pt_regs.r8
@@ -528,12 +528,186 @@
 (p7)	br.cond.spnt handle_syscall_error	// handle potential syscall failure
 END(ia64_ret_from_syscall)
 	// fall through
+/*
+ * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't
+ *	need to switch to bank 0 and doesn't restore the scratch registers.
+ *	To avoid leaking kernel bits, the scratch registers are set to
+ *	the following known-to-be-safe values:
+ *
+ *		  r1: restored (global pointer)
+ *		  r2: cleared
+ *		  r3: cleared
+ *	      r8-r11: restored (syscall return value(s))
+ *		 r12: restored (user-level stack pointer)
+ *		 r13: restored (user-level thread pointer)
+ *		 r14: cleared
+ *		 r15: restored (syscall #)
+ *	     r16-r19: cleared
+ *		 r20: user-level ar.fpsr
+ *		 r21: user-level b0
+ *		 r22: cleared
+ *		 r23: user-level ar.bspstore
+ *		 r24: user-level ar.rnat
+ *		 r25: user-level ar.unat
+ *		 r26: user-level ar.pfs
+ *		 r27: user-level ar.rsc
+ *		 r28: user-level ip
+ *		 r29: user-level psr
+ *		 r30: user-level cfm
+ *		 r31: user-level pr
+ *	      f6-f11: cleared
+ *		  pr: restored (user-level pr)
+ *		  b0: restored (user-level rp)
+ *	          b6: cleared
+ *		  b7: cleared
+ *	     ar.unat: restored (user-level ar.unat)
+ *	      ar.pfs: restored (user-level ar.pfs)
+ *	      ar.rsc: restored (user-level ar.rsc)
+ *	     ar.rnat: restored (user-level ar.rnat)
+ *	 ar.bspstore: restored (user-level ar.bspstore)
+ *	     ar.fpsr: restored (user-level ar.fpsr)
+ *	      ar.ccv: cleared
+ *	      ar.csd: cleared
+ *	      ar.ssd: cleared
+ */
+GLOBAL_ENTRY(ia64_leave_syscall)
+	PT_REGS_UNWIND_INFO(0)
+	lfetch.fault [sp]
+	movl r14=.restart1
+	;;
+	mov.ret.sptk rp=r14,.restart1
+	cmp.eq pLvSys,p0=r0,r0			// pLvSys=1: leave from syscall
+.restart1:
+	// need_resched and signals atomic test
+(pUser)	rsm psr.i
+	adds r17=IA64_TASK_NEED_RESCHED_OFFSET,r13
+	adds r18=IA64_TASK_SIGPENDING_OFFSET,r13
+#ifdef CONFIG_PERFMON
+	adds r19=IA64_TASK_PFM_OVFL_BLOCK_RESET_OFFSET,r13
+#endif
+	;;
+#ifdef CONFIG_PERFMON
+(pUser)	ld8 r19=[r19]				// load current->thread.pfm_ovfl_block_reset
+#endif
+(pUser)	ld8 r17=[r17]				// load current->need_resched
+(pUser)	ld4 r18=[r18]				// load current->sigpending
+	;;
+#ifdef CONFIG_PERFMON
+(pUser)	cmp.ne.unc p9,p0=r19,r0			// current->thread.pfm_ovfl_block_reset != 0?
+#endif
+(pUser)	cmp.ne.unc p7,p0=r17,r0			// current->need_resched != 0?
+(pUser)	cmp.ne.unc p8,p0=r18,r0			// current->sigpending != 0?
+	;;
+#ifdef CONFIG_PERFMON
+(p9)	br.call.spnt.many b7=pfm_ovfl_block_reset
+#endif
+#if __GNUC__ < 3
+(p7)	br.call.spnt.many b7=invoke_schedule
+#else
+(p7)	br.call.spnt.many b7=schedule
+#endif
+(p8)	br.call.spnt.many rp=handle_signal_delivery	// check & deliver pending signals (once)
+
+	mov  ar.csd=r0
+	mov  ar.ssd=r0
+	adds r16=PT(LOADRS)+16,r12
+	adds r17=PT(AR_BSPSTORE)+16, r12
+	mov  f6=f0		// clear f6
+	;;
+	ld8 r19=[r16],PT(R8)-PT(LOADRS)        		// load ar.rsc value for "loadrs"
+	ld8 r23=[r17],PT(R9)-PT(AR_BSPSTORE)	// load ar.bspstore (may be garbage)
+	mov r22=r0		// clear r22
+	;;
+	// start restoring the state saved on the kernel stack (struct pt_regs):
+	ld8.fill r8=[r16],16
+	ld8.fill r9=[r17],16
+	mov  f7=f0		// clear f7
+	;;
+	ld8.fill r10=[r16],16
+	ld8.fill r11=[r17],16
+	mov  f8=f0		// clear f8
+	;;
+	ld8 r29=[r16],16	// load cr.ipsr
+	ld8 r28=[r17],16	// load cr.iip
+	mov b7=r0		// clear b7
+	;;
+	ld8 r30=[r16],16	// load cr.ifs
+	ld8 r25=[r17],16	// load ar.unat
+	cmp.eq p9,p0=r0,r0	// set p9 to indicate that we should restore cr.ifs
+	;;
+	rsm psr.i | psr.ic	// initiate turning off of interrupt and interruption collection
+	invala			// invalidate ALAT
+	mov  f9=f0		// clear f9
+	;;
+	ld8 r26=[r16],16 	// load ar.pfs
+	ld8 r27=[r17],PT(PR)-PT(AR_RSC)// load ar.rsc
+	mov  f10=f0		// clear f10
+	;;
+	ld8 r24=[r16],PT(B0)-PT(AR_RNAT)// load ar.rnat (may be garbage)
+	ld8 r31=[r17],PT(R1)-PT(PR)	    // load predicates
+	mov  f11=f0		// clear f11
+	;;
+	ld8 r21=[r16],PT(R12)-PT(B0)// load b0
+	ld8.fill r1=[r17],16	// load r1
+	mov r3=r0		// clear r3
+	;;
+	ld8.fill r12=[r16],16
+	ld8.fill r13=[r17],16
+	mov r2=r0		// clear r2
+	;;
+	ld8 r20=[r16]		// ar.fpsr
+	ld8.fill r15=[r17]	// load r15
+	adds r18=16,r16
+	;;
+	mov r16=ar.bsp		// get existing backing store pointer
+	movl r17=PERCPU_ADDR+IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET
+	srlz.i			// ensure interruption collection is off
+	mov ar.ccv=r0		// clear ar.ccv
+	mov b6=r0		// clear b6
+	;;
+	ld4 r17=[r17]		// r17 = cpu_data->phys_stacked_size_p8
+	mov r14=r0		// clear r14
+(pKern)	br.cond.dpnt skip_rbs_switch
+	/*
+	 * Restore user backing store.
+	 *
+	 * NOTE: alloc, loadrs, and cover can't be predicated.
+	 */
+	cover				// add current frame into dirty partition
+	shr.u r18=r19,16	// get byte size of existing "dirty" partition
+	;;
+	mov r19=ar.bsp			// get new backing store pointer
+	sub r16=r16,r18			// krbs = old bsp - size of dirty partition
+	cmp.ne p9,p0=r0,r0		// clear p9 to skip restore of cr.ifs
+	;;
+	sub r19=r19,r16			// calculate total byte size of dirty partition
+	add r18=64,r18			// don't force in0-in7 into memory...
+	;;
+	shl r19=r19,16			// shift size of dirty partition into loadrs position
+	br.few dont_preserve_current_frame
+	;;
+END(ia64_leave_syscall)
+
+GLOBAL_ENTRY(ia64_ret_from_execve_syscall)
+	PT_REGS_UNWIND_INFO(0)
+	cmp.ge p6,p7=r8,r0			// syscall executed successfully?
+	adds r2=PT(R8)+16,sp			// r2 = &pt_regs.r8
+	adds r3=PT(R10)+16,sp			// r3 = &pt_regs.r10
+	;;
+	.mem.offset 0,0
+(p6)	st8.spill [r2]=r8	// store return value in slot for r8 and set unat bit
+	.mem.offset 8,0
+(p6)	st8.spill [r3]=r0	// clear error indication in slot for r10 and set unat bit
+(p7)	br.cond.spnt handle_syscall_error	// handle potential syscall failure
+END(ia64_ret_from_execve_syscall)
+	// fall through
 GLOBAL_ENTRY(ia64_leave_kernel)
 	PT_REGS_UNWIND_INFO(0)
 	lfetch.fault [sp]
 	movl r14=.restart
 	;;
 	mov.ret.sptk rp=r14,.restart
+	cmp.eq p0,pLvSys=r0,r0			// pLvSys=0: leave from kernel
 .restart:
 	// need_resched and signals atomic test
 (pUser)	rsm psr.i
@@ -564,18 +738,35 @@
 (p7)	br.call.spnt.many b7=schedule
 #endif
 (p8)	br.call.spnt.many rp=handle_signal_delivery	// check & deliver pending signals (once)
+
+	adds r20=PT(CR_IPSR)+16,r12
+	adds r21=PT(PR)+16,r12
 	;;
-.ret9:	adds r2=PT(R8)+16,r12
-	adds r3=PT(R9)+16,r12
+	lfetch.fault.excl [r20]
+	lfetch.fault.excl [r21]
+	adds r2=PT(B6)+16,r12
+	adds r3=PT(R16)+16,r12
+	mov r29=PT(R24)-PT(B6)
+	mov r30=PT(B7)-PT(R24)
 	;;
 	// start restoring the state saved on the kernel stack (struct pt_regs):
-	ld8.fill r8=[r2],16
-	ld8.fill r9=[r3],16
+	ld8 r28=[r2],r29	// b6
+	ld8.fill r16=[r3],128
+	mov r31=PT(AR_CSD)-PT(AR_CCV)
+	;;
+	ld8.fill r24=[r2],r30
+	ld8 r15=[r3],r31
+	;; 
+	ld8 r29=[r2],16		// b7
+	ld8 r30=[r3],16		// ar.csd
 	;;
-	ld8.fill r10=[r2],16
-	ld8.fill r11=[r3],16
+	ld8 r31=[r2],16		// ar.ssd
+	ld8.fill r8=[r3],16
 	;;
-	ld8.fill r16=[r2],16
+	ld8.fill r9=[r2],16
+	ld8.fill r10=[r3],PT(R17)-PT(R10)
+	;;
+	ld8.fill r11=[r2],PT(R18)-PT(R11)
 	ld8.fill r17=[r3],16
 	;;
 	ld8.fill r18=[r2],16
@@ -583,82 +774,78 @@
 	;;
 	ld8.fill r20=[r2],16
 	ld8.fill r21=[r3],16
-	;;
-	ld8.fill r22=[r2],16
-	ld8.fill r23=[r3],16
-	;;
-	ld8.fill r24=[r2],16
-	ld8.fill r25=[r3],16
-	;;
-	ld8.fill r26=[r2],16
-	ld8.fill r27=[r3],16
-	;;
-	ld8.fill r28=[r2],16
-	ld8.fill r29=[r3],16
-	;;
-	ld8.fill r30=[r2],16
-	ld8.fill r31=[r3],16
+	mov ar.csd=r30
+	mov ar.ssd=r31
 	;;
 	rsm psr.i | psr.ic	// initiate turning off of interrupt and interruption collection
 	invala			// invalidate ALAT
 	;;
-	ld8 r1=[r2],16		// ar.ccv
-	ld8 r13=[r3],16		// ar.fpsr
+	ld8.fill r22=[r2],24
+	ld8.fill r23=[r3],24
+	mov b6=r28
+	;;
+	ld8.fill r25=[r2],16
+	ld8.fill r26=[r3],16
+	mov b7=r29
 	;;
-	ld8 r14=[r2],16		// b0
-	ld8 r15=[r3],16+8	// b7
+	ld8.fill r27=[r2],16
+	ld8.fill r28=[r3],16
 	;;
-	ldf.fill f6=[r2],32
-	ldf.fill f7=[r3],32
+	ld8.fill r29=[r2],16
+	ld8.fill r30=[r3],24
 	;;
-	ldf.fill f8=[r2],32
-	ldf.fill f9=[r3],32
+	ld8.fill r31=[r2],32
+	ldf.fill f6=[r3],32
 	;;
-	mov ar.ccv=r1
-	mov ar.fpsr=r13
-	mov b0=r14
+	ldf.fill f7=[r2],32
+	ldf.fill f8=[r3],32
 	;;
 	srlz.i			// ensure interruption collection is off
-	mov b7=r15
+	mov ar.ccv=r15
 	;;
+	ldf.fill f9=[r2],32
+	ldf.fill f10=[r3],32
 	bsw.0			// switch back to bank 0
 	;;
-	adds r16=16,r12
-	adds r17=24,r12
+	ldf.fill f11=[r2]
+	adds r16=PT(CR_IPSR)+16,r12
+	adds r17=PT(CR_IIP)+16,r12
 	;;
-	ld8 rCRIPSR=[r16],16	// load cr.ipsr
-	ld8 rCRIIP=[r17],16	// load cr.iip
+	ld8 r29=[r16],16	// load cr.ipsr
+	ld8 r28=[r17],16	// load cr.iip
 	;;
-	ld8 rCRIFS=[r16],16	// load cr.ifs
-	ld8 rARUNAT=[r17],16	// load ar.unat
+	ld8 r30=[r16],16	// load cr.ifs
+	ld8 r25=[r17],16	// load ar.unat
 	cmp.eq p9,p0=r0,r0	// set p9 to indicate that we should restore cr.ifs
 	;;
-	ld8 rARPFS=[r16],16	// load ar.pfs
-	ld8 rARRSC=[r17],16	// load ar.rsc
+	ld8 r26=[r16],16	// load ar.pfs
+	ld8 r27=[r17],16	// load ar.rsc
 	;;
-	ld8 rARRNAT=[r16],16	// load ar.rnat (may be garbage)
-	ld8 rARBSPSTORE=[r17],16 // load ar.bspstore (may be garbage)
+	ld8 r24=[r16],16	// load ar.rnat (may be garbage)
+	ld8 r23=[r17],16 // load ar.bspstore (may be garbage)
 	;;
-	ld8 rARPR=[r16],16	// load predicates
-	ld8 rB6=[r17],16	// load b6
+	ld8 r31=[r16],16	// load predicates
+	ld8 r21=[r17],16	// load b0
 	;;
 	ld8 r19=[r16],16	// load ar.rsc value for "loadrs"
 	ld8.fill r1=[r17],16	// load r1
 	;;
-	ld8.fill r2=[r16],16
-	ld8.fill r3=[r17],16
-	;;
 	ld8.fill r12=[r16],16
 	ld8.fill r13=[r17],16
 	;;
+	ld8 r20=[r16],16
+	ld8.fill r15=[r17],16
+	;;
 	ld8.fill r14=[r16]
-	ld8.fill r15=[r17]
-	shr.u r18=r19,16	// get byte size of existing "dirty" partition
+	ld8.fill r2=[r17],16
+	adds r18=16,r16
 	;;
 	mov r16=ar.bsp		// get existing backing store pointer
 	movl r17=PERCPU_ADDR+IA64_CPU_PHYS_STACKED_SIZE_P8_OFFSET
 	;;
+	ld8.fill r3=[r18]
 	ld4 r17=[r17]		// r17 = cpu_data->phys_stacked_size_p8
+	shr.u r18=r19,16	// get byte size of existing "dirty" partition
 (pKern)	br.cond.dpnt skip_rbs_switch
 	/*
 	 * Restore user backing store.
@@ -718,7 +905,7 @@
 }{ .mib
 	mov loc3=0
 	mov loc4=0
-(pRecurse) br.call.sptk.many b6=rse_clear_invalid
+(pRecurse) br.call.sptk.many b0=rse_clear_invalid
 
 }{ .mfi	// cycle 2
 	mov loc5=0
@@ -727,7 +914,7 @@
 }{ .mib
 	mov loc6=0
 	mov loc7=0
-(pReturn) br.ret.sptk.many b6
+(pReturn) br.ret.sptk.many b0
 }
 #else /* !CONFIG_ITANIUM */
 	alloc loc0=ar.pfs,2,Nregs-2,2,0
@@ -742,14 +929,14 @@
 	mov loc5=0
 	mov loc6=0
 	mov loc7=0
-(pRecurse) br.call.sptk.many b6=rse_clear_invalid
+(pRecurse) br.call.sptk.many b0=rse_clear_invalid
 	;;
 	mov loc8=0
 	mov loc9=0
 	cmp.ne pReturn,p0=r0,in1	// if recursion count != 0, we need to do a br.ret
 	mov loc10=0
 	mov loc11=0
-(pReturn) br.ret.sptk.many b6
+(pReturn) br.ret.sptk.many b0
 #endif /* !CONFIG_ITANIUM */
 #	undef pRecurse
 #	undef pReturn
@@ -759,17 +946,22 @@
 	loadrs
 	;;
 skip_rbs_switch:
-	mov b6=rB6
-	mov ar.pfs=rARPFS
-(pUser)	mov ar.bspstore=rARBSPSTORE
-(p9)	mov cr.ifs=rCRIFS
-	mov cr.ipsr=rCRIPSR
-	mov cr.iip=rCRIIP
-	;;
-(pUser)	mov ar.rnat=rARRNAT	// must happen with RSE in lazy mode
-	mov ar.rsc=rARRSC
-	mov ar.unat=rARUNAT
-	mov pr=rARPR,-1
+(pLvSys)mov r19=r0		// clear r19 for leave_syscall, no-op otherwise
+	mov b0=r21
+	mov ar.pfs=r26
+(pUser)	mov ar.bspstore=r23
+(p9)	mov cr.ifs=r30
+(pLvSys)mov r16=r0		// clear r16 for leave_syscall, no-op otherwise
+	mov cr.ipsr=r29
+	mov ar.fpsr=r20
+(pLvSys)mov r17=r0		// clear r17 for leave_syscall, no-op otherwise
+	mov cr.iip=r28
+	;;
+(pUser)	mov ar.rnat=r24		// must happen with RSE in lazy mode
+(pLvSys)mov r18=r0		// clear r18 for leave_syscall, no-op otherwise
+	mov ar.rsc=r27
+	mov ar.unat=r25
+	mov pr=r31,-1
 	rfi
 END(ia64_leave_kernel)
 
@@ -795,7 +987,7 @@
 	;;
 .mem.offset 0,0; st8.spill [r2]=r9	// store errno in pt_regs.r8 and set unat bit
 .mem.offset 8,0; st8.spill [r3]=r10	// store error indication in pt_regs.r10 and set unat bit
-	br.cond.sptk ia64_leave_kernel
+	br.cond.sptk ia64_leave_syscall
 END(handle_syscall_error)
 
 	/*
@@ -906,6 +1098,22 @@
 	.body
 	cmp.eq pNonSys,pSys=r0,r0		// sigreturn isn't a normal syscall...
 	;;
+	/* After signal handler, live registers f6-f11 are restored to the previous
+	 * executing context values for synchronized signals(from exceptions); or they 
+	 * are cleared to 0 for asynchronized signals(from syscalls). These live registers 
+	 * will be put into pt_regs to return back to user space.
+	 */
+	adds r16=PT(F6)+32,sp
+	adds r17=PT(F7)+32,sp
+	;;
+ 	stf.spill [r16]=f6,32	
+ 	stf.spill [r17]=f7,32	
+	;;
+ 	stf.spill [r16]=f8,32	
+ 	stf.spill [r17]=f9,32	
+	;;
+ 	stf.spill [r16]=f10	
+ 	stf.spill [r17]=f11	
 	adds out0=16,sp				// out0 = &sigscratch
 	br.call.sptk.many rp=ia64_rt_sigreturn
 .ret19:	.restore sp 0
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/entry.h linux-2.4.23-pre4/arch/ia64/kernel/entry.h
--- linux-2.4.23-pre3/arch/ia64/kernel/entry.h	2001-11-09 14:26:17.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/kernel/entry.h	2003-09-12 12:44:34.000000000 -0700
@@ -4,6 +4,7 @@
  * Preserved registers that are shared between code in ivt.S and entry.S.  Be
  * careful not to step on these!
  */
+#define pLvSys		p1	/* set 1 if leave from syscall; otherwise, set 0*/
 #define pKern		p2	/* will leave_kernel return to kernel-mode? */
 #define pUser		p3	/* will leave_kernel return to user-mode? */
 #define pSys		p4	/* are we processing a (synchronous) system call? */
@@ -13,7 +14,7 @@
 #define SW(f)		(IA64_SWITCH_STACK_##f##_OFFSET)
 
 #define PT_REGS_SAVES(off)			\
-	.unwabi @svr4, 'i';			\
+	.unwabi 3, 'i';				\
 	.fframe IA64_PT_REGS_SIZE+16+(off);	\
 	.spillsp rp, PT(CR_IIP)+16+(off);	\
 	.spillsp ar.pfs, PT(CR_IFS)+16+(off);	\
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/head.S linux-2.4.23-pre4/arch/ia64/kernel/head.S
--- linux-2.4.23-pre3/arch/ia64/kernel/head.S	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/head.S	2003-09-12 12:44:34.000000000 -0700
@@ -5,7 +5,7 @@
  * to set up the kernel's global pointer and jump to the kernel
  * entry point.
  *
- * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *	Stephane Eranian <eranian@hpl.hp.com>
  * Copyright (C) 1999 VA Linux Systems
@@ -15,6 +15,7 @@
  * Copyright (C) 1999 Don Dugger <Don.Dugger@intel.com>
  * Copyright (C) 2002 Fenghua Yu <fenghua.yu@intel.com>
  *   -Optimize __ia64_save_fpu() and __ia64_load_fpu() for Itanium 2.
+ * Copyright (C) 2003 Silicon Graphics, Inc.
  */
 
 #include <linux/config.h>
@@ -65,17 +66,29 @@
 	 * that maps the kernel's text and data:
 	 */
 	rsm psr.i | psr.ic
-	mov r16=((ia64_rid(IA64_REGION_ID_KERNEL, PAGE_OFFSET) << 8) | (IA64_GRANULE_SHIFT << 2))
 	;;
 	srlz.i
+	;;
+	mov r20=((ia64_rid(IA64_REGION_ID_KERNEL, (7<<61)) << 8) | (IA64_GRANULE_SHIFT << 2))
+	movl r21=(7<<61)
+	;;
+	mov rr[r21]=r20
+	;;
+	/*
+	 * Now pin mappings into the TLB for kernel text and data
+	 */
 	mov r18=KERNEL_TR_PAGE_SHIFT<<2
 	movl r17=KERNEL_START
 	;;
-	mov rr[r17]=r16
 	mov cr.itir=r18
 	mov cr.ifa=r17
 	mov r16=IA64_TR_KERNEL
-	movl r18=((1 << KERNEL_TR_PAGE_SHIFT) | PAGE_KERNEL)
+	mov r3=ip
+	movl r18=PAGE_KERNEL
+	;;
+	dep r2=0,r3,0,KERNEL_TR_PAGE_SHIFT
+	;;
+	or r18=r2,r18
 	;;
 	srlz.i
 	;;
@@ -134,28 +147,63 @@
 	movl r3=cpucount
  	;;
 	ld4 r3=[r3]		// r3 <- smp_processor_id()
-	movl r2=init_tasks
-	;;
-	shladd r2=r3,3,r2
-	;;
-	ld8 r2=[r2]
 #else
 	mov r3=0
-	movl r2=init_task_union
-	;;
 #endif
+	;;
 	cmp4.ne isAP,isBP=r3,r0
-	;;			// RAW on r2
-	extr r3=r2,0,61		// r3 == phys addr of task struct
-	mov r16=KERNEL_TR_PAGE_NUM
+
+	/*
+	 * Make task struct pointer in init_tasks an identity mapped pointer.
+	 * The value that is compiled into the array may not be identity mapped.
+	 */
+	movl r18=init_tasks
+	;;
+	shladd r18=r3,3,r18
+	;;
+	ld8 r8=[r18]
+	;;
+	tpa r3=r8		// r3 == phys addr of task struct
+	;;
+	dep r2=-1,r3,61,3	// IMVA of task
+	;;
+	st8 [r18]=r2		// and save it back in init_tasks[thiscpu]
+
+	// load mapping for stack (virtaddr in r2, physaddr in r3)
+	// load dtr[2] only if the va for current (r2) isn't covered by the dtr[0] 
+	shr.u r18=r2,KERNEL_TR_PAGE_SHIFT               /* va of current in units of kernel-pages */
+	movl r17=KERNEL_START>>KERNEL_TR_PAGE_SHIFT     /* va of kernel-start in units of kernel-pages */
+	;;
+	cmp.eq p0,p6=r17,r18
+	rsm psr.ic
+	movl r17=PAGE_KERNEL
+	;;
+	srlz.d
+	dep r18=0,r3,0,12
+	;;
+	or r18=r17,r18
+	;;
+	mov r17=rr[r2]
+	shr.u r16=r3,IA64_GRANULE_SHIFT
+	;;
+	dep r17=0,r17,8,24
+	;;
+	mov cr.itir=r17
+	mov cr.ifa=r2
+
+	mov r19=IA64_TR_CURRENT_STACK
+	;;
+(p6)	itr.d dtr[r19]=r18
+	;;
+	ssm psr.ic
+	srlz.d
 	;;
 
 	// load the "current" pointer (r13) and ar.k6 with the current task
-	mov r13=r2
 	mov IA64_KR(CURRENT)=r3		// Physical address
-
-	// initialize k4 to a safe value (64-128MB is mapped by TR_KERNEL)
 	mov IA64_KR(CURRENT_STACK)=r16
+	mov r13=r2
+
 	/*
 	 * Reserve space at the top of the stack for "struct pt_regs".  Kernel threads
 	 * don't store interesting values in that structure, but the space still needs
@@ -670,14 +718,14 @@
 END(__ia64_init_fpu)
 
 /*
- * Switch execution mode from virtual to physical or vice versa.
+ * Switch execution mode from virtual to physical
  *
  * Inputs:
  *	r16 = new psr to establish
  *
  * Note: RSE must already be in enforced lazy mode
  */
-GLOBAL_ENTRY(ia64_switch_mode)
+GLOBAL_ENTRY(ia64_switch_mode_phys)
  {
 	alloc r2=ar.pfs,0,0,0,0
 	rsm psr.i | psr.ic		// disable interrupts and interrupt collection
@@ -687,35 +735,86 @@
  {
 	flushrs				// must be first insn in group
 	srlz.i
-	shr.u r19=r15,61		// r19 <- top 3 bits of current IP
  }
 	;;
 	mov cr.ipsr=r16			// set new PSR
-	add r3=1f-ia64_switch_mode,r15
-	xor r15=0x7,r19			// flip the region bits
+	add r3=1f-ia64_switch_mode_phys,r15
 
 	mov r17=ar.bsp
 	mov r14=rp			// get return address into a general register
+	;;
 
-	// switch RSE backing store:
+	// going to physical mode, use tpa to translate virt->phys
+	tpa r17=r17
+	tpa r3=r3
+	tpa sp=sp
+	tpa r14=r14
 	;;
-	dep r17=r15,r17,61,3		// make ar.bsp physical or virtual
+
 	mov r18=ar.rnat			// save ar.rnat
-	;;
 	mov ar.bspstore=r17		// this steps on ar.rnat
-	dep r3=r15,r3,61,3		// make rfi return address physical or virtual
+	mov cr.iip=r3
+	mov cr.ifs=r0
+	;;
+	mov ar.rnat=r18			// restore ar.rnat
+	rfi				// must be last insn in group
+	;;
+1:	mov rp=r14
+	br.ret.sptk.many rp
+END(ia64_switch_mode_phys)
+
+/*
+ * Switch execution mode from physical to virtual
+ *
+ * Inputs:
+ *	r16 = new psr to establish
+ *
+ * Note: RSE must already be in enforced lazy mode
+ */
+GLOBAL_ENTRY(ia64_switch_mode_virt)
+ {
+	alloc r2=ar.pfs,0,0,0,0
+	rsm psr.i | psr.ic		// disable interrupts and interrupt collection
+	mov r15=ip
+ }
+	;;
+ {
+	flushrs				// must be first insn in group
+	srlz.i
+ }
 	;;
+	mov cr.ipsr=r16			// set new PSR
+	add r3=1f-ia64_switch_mode_virt,r15
+
+	mov r17=ar.bsp
+	mov r14=rp			// get return address into a general register
+	;;
+
+	// going to virtual
+	//   - for code addresses, set upper bits of addr to KERNEL_START
+	//   - for stack addresses, set upper 3 bits to 0xe.... Dont change any of the
+	//     lower bits since we want it to stay identity mapped
+	movl r18=KERNEL_START
+	dep r3=0,r3,KERNEL_TR_PAGE_SHIFT,64-KERNEL_TR_PAGE_SHIFT
+	dep r14=0,r14,KERNEL_TR_PAGE_SHIFT,64-KERNEL_TR_PAGE_SHIFT
+	dep r17=-1,r17,61,3
+	dep sp=-1,sp,61,3
+	;;
+	or r3=r3,r18
+	or r14=r14,r18
+	;;
+
+	mov r18=ar.rnat			// save ar.rnat
+	mov ar.bspstore=r17		// this steps on ar.rnat
 	mov cr.iip=r3
 	mov cr.ifs=r0
-	dep sp=r15,sp,61,3		// make stack pointer physical or virtual
 	;;
 	mov ar.rnat=r18			// restore ar.rnat
-	dep r14=r15,r14,61,3		// make function return address physical or virtual
 	rfi				// must be last insn in group
 	;;
 1:	mov rp=r14
 	br.ret.sptk.many rp
-END(ia64_switch_mode)
+END(ia64_switch_mode_virt)
 
 #ifdef CONFIG_IA64_BRL_EMU
 
@@ -782,6 +881,9 @@
 	;;
 	// delay a little...
 .wait:	sub tmp=tmp,timeout
+#ifdef GAS_HAS_HINT_INSN
+	hint @pause
+#endif
 	or delay=0xf,delay	// make sure delay is non-zero (otherwise we get stuck with 0)
 	;;
 	cmp.lt p15,p0=tmp,r0
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/iosapic.c linux-2.4.23-pre4/arch/ia64/kernel/iosapic.c
--- linux-2.4.23-pre3/arch/ia64/kernel/iosapic.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/iosapic.c	2003-09-12 12:44:34.000000000 -0700
@@ -530,7 +530,7 @@
 		delivery = IOSAPIC_INIT;
 		break;
 	      case ACPI_INTERRUPT_CPEI:
-		vector = IA64_PCE_VECTOR;
+		vector = IA64_CPE_VECTOR;
 		delivery = IOSAPIC_LOWEST_PRIORITY;
 		break;
 	      default:
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/ivt.S linux-2.4.23-pre4/arch/ia64/kernel/ivt.S
--- linux-2.4.23-pre3/arch/ia64/kernel/ivt.S	2002-11-28 15:53:09.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/kernel/ivt.S	2003-09-12 12:44:34.000000000 -0700
@@ -1,6 +1,10 @@
 /*
  * arch/ia64/kernel/ivt.S
  *
+ * Copyright (C) 2002-2003 Intel Co
+ *      Suresh Siddha <suresh.b.siddha@intel.com>
+ *      Kenneth Chen <kenneth.w.chen@intel.com>
+ *      Fenghua Yu <fenghua.yu@intel.com>
  * Copyright (C) 1998-2001 Hewlett-Packard Co
  *	Stephane Eranian <eranian@hpl.hp.com>
  *	David Mosberger <davidm@hpl.hp.com>
@@ -621,6 +625,23 @@
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x2c00 Entry 11 (size 64 bundles) Break instruction (33)
 ENTRY(break_fault)
+
+/* System call entry/exit only saves/restores part of pt_regs, i.e. no scratch registers 
+ * are saved/restored except r15 which contains syscall number and needs to be saved in the
+ * entry. This optimization is based on the assumption that applications only call glibc 
+ * system call interface which doesn't use scratch registers after break into kernel.
+ * Registers saved/restored during system call entry/exit are listed as follows:
+ *
+ *   Registers to be saved & restored:
+ *	CR registers: cr_ipsr, cr_iip, cr_ifs
+ *	AR registers: ar_unat, ar_pfs, ar_rsc, ar_rnat, ar_bspstore, ar_fpsr	
+ * 	others: pr, b0, loadrs, r1, r12, r13, r15
+ *   Registers to be restored only:
+ * 	r8~r11: output value from the system call.
+ *
+ * During system call exit, scratch registers (including r15) are modified/cleared to 
+ * prevent leaking bits from kernel to user level.
+ */
 	DBG_FAULT(11)
 	mov r16=cr.iim
 	mov r17=__IA64_BREAK_SYSCALL
@@ -629,22 +650,25 @@
 	cmp.eq p0,p7=r16,r17	// is this a system call? (p7 <- false, if so)
 (p7)	br.cond.spnt non_syscall
 
-	SAVE_MIN				// uses r31; defines r2:
-
-	ssm psr.ic | PSR_DEFAULT_BITS
+	mov r21=ar.fpsr; 
+	mov r29=cr.ipsr;
+	mov r20=r1;
+	mov r25=ar.unat;
+	mov r27=ar.rsc;
+	mov r26=ar.pfs;
+	mov r28=cr.iip;
+	mov r1=IA64_KR(CURRENT);		/* r1 = current (physical) */
+	;;
+	invala;
+	extr.u r16=r29,32,2;			/* extract psr.cpl */
+	;;
+	cmp.eq pKern,pUser=r0,r16;		/* are we in kernel mode already? (psr.cpl==0) */
+	/* switch from user to kernel RBS: */
+	;;
+	mov r30=r0
+	MINSTATE_START_SAVE_MIN_VIRT
+	br.call.sptk.many b7=ia64_syscall_setup
 	;;
-	srlz.i					// guarantee that interruption collection is on
-	cmp.eq pSys,pNonSys=r0,r0		// set pSys=1, pNonSys=0
-	;;
-(p15)	ssm psr.i		// restore psr.i
-	adds r8=(IA64_PT_REGS_R8_OFFSET-IA64_PT_REGS_R16_OFFSET),r2
-	;;
-	stf8 [r8]=f1		// ensure pt_regs.r8 != 0 (see handle_syscall_error)
-	adds r3=8,r2		// set up second base pointer for SAVE_REST
-	;;
-	SAVE_REST
-	br.call.sptk.many rp=demine_args	// clear NaT bits in (potential) syscall args
-
 	mov r3=255
 	adds r15=-1024,r15			// r15 contains the syscall number---subtract 1024
 	adds r2=IA64_TASK_PTRACE_OFFSET,r13	// r2 = &current->ptrace
@@ -664,8 +688,8 @@
 
 	// arrange things so we skip over break instruction when returning:
 
-	adds r16=16,sp				// get pointer to cr_ipsr
-	adds r17=24,sp				// get pointer to cr_iip
+	adds r16=PT(CR_IPSR)+16,sp			// get pointer to cr_ipsr
+	adds r17=PT(CR_IIP)+16,sp			// get pointer to cr_iip
 	;;
 	ld8 r18=[r16]				// fetch cr_ipsr
 	tbit.z p8,p0=r2,PT_TRACESYS_BIT		// (current->ptrace & PF_TRACESYS) == 0?
@@ -685,38 +709,11 @@
 	st8 [r16]=r18				// store new value for cr.isr
 
 (p8)	br.call.sptk.many b6=b6			// ignore this return addr
+
 	br.cond.sptk ia64_trace_syscall
 	// NOT REACHED
 END(break_fault)
 
-ENTRY(demine_args)
-	alloc r2=ar.pfs,8,0,0,0
-	tnat.nz p8,p0=in0
-	tnat.nz p9,p0=in1
-	;;
-(p8)	mov in0=-1
-	tnat.nz p10,p0=in2
-	tnat.nz p11,p0=in3
-
-(p9)	mov in1=-1
-	tnat.nz p12,p0=in4
-	tnat.nz p13,p0=in5
-	;;
-(p10)	mov in2=-1
-	tnat.nz p14,p0=in6
-	tnat.nz p15,p0=in7
-
-(p11)	mov in3=-1
-	tnat.nz p8,p0=r15	// demining r15 is not a must, but it is safer
-
-(p12)	mov in4=-1
-(p13)	mov in5=-1
-	;;
-(p14)	mov in6=-1
-(p15)	mov in7=-1
-(p8)	mov r15=-1
-	br.ret.sptk.many rp
-END(demine_args)
 
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
@@ -725,7 +722,6 @@
 	DBG_FAULT(12)
 	mov r31=pr		// prepare to save predicates
 	;;
-
 	SAVE_MIN_WITH_COVER	// uses r31; defines r2 and r3
 	ssm psr.ic | PSR_DEFAULT_BITS
 	;;
@@ -757,6 +753,125 @@
 	DBG_FAULT(14)
 	FAULT(14)
 
+	/*
+	 * There is no particular reason for this code to be here, other than that
+	 * there happens to be space here that would go unused otherwise.  If this
+	 * fault ever gets "unreserved", simply moved the following code to a more
+	 * suitable spot...
+	 *
+	 * ia64_syscall_setup() is a separate subroutine so that it can
+	 *	allocate stacked registers so it can safely demine any
+	 *	potential NaT values from the input registers.
+	 *
+	 * On entry:
+	 *	- executing on bank 0 or bank 1 register set (doesn't matter)
+	 *	-  r1: stack pointer
+	 *	-  r2: current task pointer
+	 *	-  r3: preserved
+	 *	- r12: original contents (sp to be saved)
+	 *	- r13: original contents (tp to be saved)
+	 *	- r15: original contents (syscall # to be saved)
+	 *	- r18: saved bsp (after switching to kernel stack)
+	 *	- r20: saved r1 (gp)
+	 *	- r21: saved ar.fpsr
+	 *	- r22: kernel's register backing store base (krbs_base)
+	 *	- r23: saved ar.bspstore
+	 *	- r24: saved ar.rnat
+	 *	- r25: saved ar.unat
+	 *	- r26: saved ar.pfs
+	 *	- r27: saved ar.rsc
+	 *	- r28: saved cr.iip
+	 *	- r29: saved cr.ipsr
+	 *	- r31: saved pr
+	 *	-  b0: original contents (to be saved)
+	 * On exit:
+	 *	- executing on bank 1 registers
+	 *	- psr.ic enabled, interrupts restored
+	 *	-  r1: kernel's gp
+	 *	-  r3: preserved (same as on entry)
+	 *	- r12: points to kernel stack
+	 *	- r13: points to current task
+	 *	- p15: TRUE if interrupts need to be re-enabled
+	 *	- ar.fpsr: set to kernel settings
+	 */
+ENTRY(ia64_syscall_setup)
+	alloc r19=ar.pfs,8,0,0,0
+	tnat.nz p8,p0=in0
+	add r16=PT(CR_IPSR),r1  /* initialize first base pointer */
+	;;
+	st8 [r16]=r29,16;   	/* save cr.ipsr */
+	adds r17=PT(CR_IIP),r1; /* initialize second base pointer */
+	;;
+(p8)	mov in0=-1
+	tnat.nz p9,p0=in1
+	st8 [r17]=r28,16;	/* save cr.iip */
+	mov r28=b0;                   
+(pKern) mov r18=r0;             /* make sure r18 isn't NaT */
+	;;
+(p9)	mov in1=-1
+	tnat.nz p10,p0=in2
+	st8 [r16]=r30,16;	/* save cr.ifs */
+	st8 [r17]=r25,16;	/* save ar.unat */
+(pUser) sub r18=r18,r22;	/* r18=RSE.ndirty*8 */
+	;;
+	st8 [r16]=r26,16;	/* save ar.pfs */
+	st8 [r17]=r27,16;	/* save ar.rsc */
+	tbit.nz p15,p0=r29,IA64_PSR_I_BIT
+	;;                      /* avoid RAW on r16 & r17 */
+(p10)	mov in2=-1
+	nop.f 0
+	tnat.nz p11,p0=in3
+(pKern) adds r16=16,r16;        /* skip over ar_rnat field */
+(pKern) adds r17=16,r17;        /* skip over ar_bspstore field */
+	shl r18=r18,16;         /* compute ar.rsc to be used for "loadrs" */
+	;;
+(p11)	mov in3=-1
+	tnat.nz p12,p0=in4
+(pUser) st8 [r16]=r24,16;	/* save ar.rnat */
+(pUser) st8 [r17]=r23,16;	/* save ar.bspstore */
+	;;
+(p12)	mov in4=-1
+	tnat.nz p13,p0=in5
+	st8 [r16]=r31,16;	/* save predicates */
+	st8 [r17]=r28,16;	/* save b0 */
+	dep r14=-1,r0,61,3;
+	;;                                                          
+	st8 [r16]=r18,16;       /* save ar.rsc value for "loadrs" */ 
+	st8.spill [r17]=r20,16;	/* save original r1 */
+	adds r2=IA64_PT_REGS_R16_OFFSET,r1;
+	;;
+(p13)	mov in5=-1
+	tnat.nz p14,p0=in6
+.mem.offset 0,0;                st8.spill [r16]=r12,16;
+.mem.offset 8,0;                st8.spill [r17]=r13,16;
+	cmp.eq pNonSys,pSys=r0,r0       /* initialize pSys=0, pNonSys=1 */
+	;;
+(p14)	mov in6=-1
+	tnat.nz p8,p0=in7
+.mem.offset 0,0;                st8 [r16]=r21,16;    /* ar.fpsr */
+.mem.offset 8,0;                st8.spill [r17]=r15,16;
+	adds r12=-16,r1;        /* switch to kernel memory stack (with 16 bytes of scratch) */
+	;;
+	mov r13=IA64_KR(CURRENT);       /* establish `current' */
+	movl r1=__gp;           /* establish kernel global pointer */
+	;;
+	MINSTATE_END_SAVE_MIN_VIRT
+
+	tnat.nz p9,p0=r15
+(p8)	mov in7=-1
+	ssm psr.ic | PSR_DEFAULT_BITS
+	movl r17=FPSR_DEFAULT
+	adds r8=(IA64_PT_REGS_R8_OFFSET-IA64_PT_REGS_R16_OFFSET),r2
+	;;
+	srlz.i					// guarantee that interruption collection is on
+	cmp.eq pSys,pNonSys=r0,r0		// set pSys=1, pNonSys=0
+(p9)	mov r15=-1
+(p15)	ssm psr.i		// restore psr.i
+	mov.m ar.fpsr=r17
+	stf8 [r8]=f1            // ensure pt_regs.r8 != 0 (see handle_syscall_error)
+	br.ret.sptk.many b7
+END(ia64_syscall_setup)
+
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x3c00 Entry 15 (size 64 bundles) Reserved
@@ -808,90 +923,6 @@
 	DBG_FAULT(16)
 	FAULT(16)
 
-#ifdef CONFIG_IA32_SUPPORT
-
-	/*
-	 * There is no particular reason for this code to be here, other than that
-	 * there happens to be space here that would go unused otherwise.  If this
-	 * fault ever gets "unreserved", simply moved the following code to a more
-	 * suitable spot...
-	 */
-
-	// IA32 interrupt entry point
-
-ENTRY(dispatch_to_ia32_handler)
-	SAVE_MIN
-	;;
-	mov r14=cr.isr
-	ssm psr.ic | PSR_DEFAULT_BITS
-	;;
-	srlz.i					// guarantee that interruption collection is on
-	;;
-(p15)	ssm psr.i
-	adds r3=8,r2            // Base pointer for SAVE_REST
-	;;
-	SAVE_REST
-	;;
-	mov r15=0x80
-	shr r14=r14,16          // Get interrupt number
-	;;
-	cmp.ne p6,p0=r14,r15
-(p6)    br.call.dpnt.many b6=non_ia32_syscall
-
-	adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp	// 16 byte hole per SW conventions
-	adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
-	;;
-	cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
-	st8 [r15]=r8		// save original EAX in r1 (IA32 procs don't use the GP)
-	;;
-	alloc r15=ar.pfs,0,0,6,0	// must first in an insn group
-	;;
-	ld4 r8=[r14],8		// r8 == eax (syscall number)
-	mov r15=230		// number of entries in ia32 system call table
-	;;
-	cmp.ltu.unc p6,p7=r8,r15
-	ld4 out1=[r14],8	// r9 == ecx
-	;;
-	ld4 out2=[r14],8	// r10 == edx
-	;;
-	ld4 out0=[r14]		// r11 == ebx
-	adds r14=(IA64_PT_REGS_R8_OFFSET-(8*3)) + 16,sp
-	;;
-	ld4 out5=[r14],8	// r13 == ebp
-	;;
-	ld4 out3=[r14],8	// r14 == esi
-	adds r2=IA64_TASK_PTRACE_OFFSET,r13	// r2 = &current->ptrace
-	;;
-	ld4 out4=[r14]		// r15 == edi
-	movl r16=ia32_syscall_table
-	;;
-(p6)    shladd r16=r8,3,r16	// force ni_syscall if not valid syscall number
-	ld8 r2=[r2]		// r2 = current->ptrace
-	;;
-	ld8 r16=[r16]
-	tbit.z p8,p0=r2,PT_TRACESYS_BIT	// (current->ptrace & PT_TRACESYS) == 0?
-	;;
-	mov b6=r16
-	movl r15=ia32_ret_from_syscall
-	;;
-	mov rp=r15
-(p8)	br.call.sptk.many b6=b6
-	br.cond.sptk ia32_trace_syscall
-
-non_ia32_syscall:
-	alloc r15=ar.pfs,0,0,2,0
-	mov out0=r14				// interrupt #
-	add out1=16,sp				// pointer to pt_regs
-	;;			// avoid WAW on CFM
-	br.call.sptk.many rp=ia32_bad_interrupt
-.ret1:	movl r15=ia64_leave_kernel
-	;;
-	mov rp=r15
-	br.ret.sptk.many rp
-END(dispatch_to_ia32_handler)
-
-#endif /* CONFIG_IA32_SUPPORT */
-
 	.align 1024
 /////////////////////////////////////////////////////////////////////////////////////////
 // 0x4400 Entry 17 (size 64 bundles) Reserved
@@ -1415,3 +1446,89 @@
 // 0x7f00 Entry 67 (size 16 bundles) Reserved
 	DBG_FAULT(67)
 	FAULT(67)
+
+#ifdef CONFIG_IA32_SUPPORT
+
+	/*
+	 * There is no particular reason for this code to be here, other than that
+	 * there happens to be space here that would go unused otherwise.  If this
+	 * fault ever gets "unreserved", simply moved the following code to a more
+	 * suitable spot...
+	 */
+
+	// IA32 interrupt entry point
+
+ENTRY(dispatch_to_ia32_handler)
+	SAVE_MIN
+	;;
+	mov r14=cr.isr
+	ssm psr.ic | PSR_DEFAULT_BITS
+	;;
+	srlz.i					// guarantee that interruption collection is on
+	;;
+(p15)	ssm psr.i
+	adds r3=8,r2            // Base pointer for SAVE_REST
+	;;
+	SAVE_REST
+	;;
+	mov r15=0x80
+	shr r14=r14,16          // Get interrupt number
+	;;
+	cmp.ne p6,p0=r14,r15
+(p6)	br.call.dpnt.many b6=non_ia32_syscall
+
+	adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp	// 16 byte hole per SW conventions
+	adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp
+	;;
+	cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0
+	ld8 r8=[r14]		// get r8
+	;;
+	st8 [r15]=r8		// save original EAX in r1 (IA32 procs don't use the GP)
+	;; 
+	alloc r15=ar.pfs,0,0,6,0	// must first in an insn group
+	;;
+	ld4 r8=[r14],8		// r8 == eax (syscall number)
+	mov r15=230		// number of entries in ia32 system call table
+	;;
+	cmp.ltu.unc p6,p7=r8,r15
+	ld4 out1=[r14],8	// r9 == ecx
+	;;
+	ld4 out2=[r14],8	// r10 == edx
+	;;
+	ld4 out0=[r14]		// r11 == ebx
+	adds r14=(IA64_PT_REGS_R13_OFFSET) + 16,sp
+	;;
+	ld4 out5=[r14],PT(R14)-PT(R13)	// r13 == ebp
+	;;
+	ld4 out3=[r14],PT(R15)-PT(R14)	// r14 == esi
+	adds r2=IA64_TASK_PTRACE_OFFSET,r13	// r2 = &current->ptrace
+	;;
+	ld4 out4=[r14]		// r15 == edi
+	movl r16=ia32_syscall_table
+	;;
+(p6)	shladd r16=r8,3,r16	// force ni_syscall if not valid syscall number
+	ld8 r2=[r2]		// r2 = current->ptrace
+	;;
+	ld8 r16=[r16]
+	tbit.z p8,p0=r2,PT_TRACESYS_BIT	// (current->ptrace & PT_TRACESYS) == 0?
+	;;
+	mov b6=r16
+	movl r15=ia32_ret_from_syscall
+	;;
+	mov rp=r15
+(p8)	br.call.sptk.many b6=b6
+	br.cond.sptk ia32_trace_syscall
+
+non_ia32_syscall:
+	alloc r15=ar.pfs,0,0,2,0
+	mov out0=r14				// interrupt #
+	add out1=16,sp				// pointer to pt_regs
+	;;			// avoid WAW on CFM
+	br.call.sptk.many rp=ia32_bad_interrupt
+.ret1:	movl r15=ia64_leave_kernel
+	;;
+	mov rp=r15
+	br.ret.sptk.many rp
+END(dispatch_to_ia32_handler)
+
+#endif /* CONFIG_IA32_SUPPORT */
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/mca.c linux-2.4.23-pre4/arch/ia64/kernel/mca.c
--- linux-2.4.23-pre3/arch/ia64/kernel/mca.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/mca.c	2003-09-12 12:44:34.000000000 -0700
@@ -59,13 +59,13 @@
 #include <asm/sal.h>
 #include <asm/mca.h>
 
-#include <asm/processor.h>
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
 
 #undef MCA_PRT_XTRA_DATA
 
-#define print_symbol(fmt, addr)	printk(fmt, "");
+#define print_symbol(fmt, addr)	printk(fmt, "(no symbol)");
+extern void show_stack(struct task_struct *);
 
 typedef struct ia64_fptr {
 	unsigned long fp;
@@ -99,6 +99,12 @@
 	.name =		"cmc_hndlr"
 };
 
+static struct irqaction cmcp_irqaction = {
+	.handler =	ia64_mca_cmc_int_caller,
+	.flags =	SA_INTERRUPT,
+	.name =		"cmc_poll"
+};
+
 static struct irqaction mca_rdzv_irqaction = {
 	.handler =	ia64_mca_rendez_int_handler,
 	.flags =	SA_INTERRUPT,
@@ -117,6 +123,12 @@
 	.name =		"cpe_hndlr"
 };
 
+static struct irqaction mca_cpep_irqaction = {
+	.handler =	ia64_mca_cpe_int_caller,
+	.flags =	SA_INTERRUPT,
+	.name =		"cpe_poll"
+};
+
 #define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */
 #define MIN_CPE_POLL_INTERVAL (2*60*HZ)  /* 2 minutes */
 #define CMC_POLL_INTERVAL     (1*60*HZ)  /* 1 minute */
@@ -125,11 +137,20 @@
 static struct timer_list cpe_poll_timer;
 static struct timer_list cmc_poll_timer;
 /*
+ * This variable tells whether we are currently in polling mode.
  * Start with this in the wrong state so we won't play w/ timers
  * before the system is ready.
  */
 static int cmc_polling_enabled = 1;
 
+/*
+ * Clearing this variable prevents CPE polling from getting activated
+ * in mca_late_init.  Use it if your system doesn't provide a CPEI,
+ * but encounters problems retrieving CPE logs.  This should only be
+ * necessary for debugging.
+ */
+static int cpe_poll_enabled = 1;
+
 extern void salinfo_log_wakeup(int);
 
 /*
@@ -179,6 +200,9 @@
 	IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. CPU:%d vector = %#x\n",
 		       smp_processor_id(), cpe_irq);
 
+	/* SAL spec states this should run w/ interrupts enabled */
+	local_irq_enable();
+
 	/* Get the CMC error record and log it */
 	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE, 0);
 }
@@ -322,7 +346,7 @@
 }
 
 void
-init_handler_platform (sal_log_processor_info_t *proc_ptr,
+init_handler_platform (pal_min_state_area_t *ms,
 		       struct pt_regs *pt, struct switch_stack *sw)
 {
 	struct unw_frame_info info;
@@ -337,12 +361,33 @@
 	 */
 	printk("Delaying for 5 seconds...\n");
 	udelay(5*1000000);
-	show_min_state(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area);
+	show_min_state(ms);
 
-	fetch_min_state(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area, pt, sw);
+	printk("Backtrace of current task (pid %d, %s)\n", current->pid, current->comm);
+	fetch_min_state(ms, pt, sw);
 	unw_init_from_interruption(&info, current, pt, sw);
 	ia64_do_show_stack(&info, NULL);
 
+#ifdef CONFIG_SMP
+	/* read_trylock() would be handy... */
+	if (!tasklist_lock.write_lock)
+		read_lock(&tasklist_lock);
+#endif
+	{
+		struct task_struct *t;
+		for_each_task(t) {
+			if (t == current)
+				continue;
+
+			printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm);
+			show_stack(t);
+		}
+	}
+#ifdef CONFIG_SMP
+	if (!tasklist_lock.write_lock)
+		read_unlock(&tasklist_lock);
+#endif
+
 	printk("\nINIT dump complete.  Please reboot now.\n");
 	while (1);			/* hang city if no debugger */
 }
@@ -653,17 +698,17 @@
 
 	IA64_MCA_DEBUG("ia64_mca_init: registered mca rendezvous spinloop and wakeup mech.\n");
 
-	ia64_mc_info.imi_mca_handler        = __pa(mca_hldlr_ptr->fp);
+	ia64_mc_info.imi_mca_handler        = ia64_tpa(mca_hldlr_ptr->fp);
 	/*
 	 * XXX - disable SAL checksum by setting size to 0; should be
-	 *	__pa(ia64_os_mca_dispatch_end) - __pa(ia64_os_mca_dispatch);
+	 *	ia64_tpa(ia64_os_mca_dispatch_end) - ia64_tpa(ia64_os_mca_dispatch);
 	 */
 	ia64_mc_info.imi_mca_handler_size	= 0;
 
 	/* Register the os mca handler with SAL */
 	if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA,
 				       ia64_mc_info.imi_mca_handler,
-				       mca_hldlr_ptr->gp,
+				       ia64_tpa(mca_hldlr_ptr->gp),
 				       ia64_mc_info.imi_mca_handler_size,
 				       0, 0, 0)))
 	{
@@ -673,15 +718,15 @@
 	}
 
 	IA64_MCA_DEBUG("ia64_mca_init: registered os mca handler with SAL at 0x%lx, gp = 0x%lx\n",
-		       ia64_mc_info.imi_mca_handler, mca_hldlr_ptr->gp);
+		       ia64_mc_info.imi_mca_handler, ia64_tpa(mca_hldlr_ptr->gp));
 
 	/*
 	 * XXX - disable SAL checksum by setting size to 0, should be
 	 * IA64_INIT_HANDLER_SIZE
 	 */
-	ia64_mc_info.imi_monarch_init_handler		= __pa(mon_init_ptr->fp);
+	ia64_mc_info.imi_monarch_init_handler		= ia64_tpa(mon_init_ptr->fp);
 	ia64_mc_info.imi_monarch_init_handler_size	= 0;
-	ia64_mc_info.imi_slave_init_handler		= __pa(slave_init_ptr->fp);
+	ia64_mc_info.imi_slave_init_handler		= ia64_tpa(slave_init_ptr->fp);
 	ia64_mc_info.imi_slave_init_handler_size	= 0;
 
 	IA64_MCA_DEBUG("ia64_mca_init: os init handler at %lx\n",
@@ -690,10 +735,10 @@
 	/* Register the os init handler with SAL */
 	if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT,
 				       ia64_mc_info.imi_monarch_init_handler,
-				       __pa(ia64_get_gp()),
+				       ia64_tpa(ia64_get_gp()),
 				       ia64_mc_info.imi_monarch_init_handler_size,
 				       ia64_mc_info.imi_slave_init_handler,
-				       __pa(ia64_get_gp()),
+				       ia64_tpa(ia64_get_gp()),
 				       ia64_mc_info.imi_slave_init_handler_size)))
 	{
 		printk(KERN_ERR "ia64_mca_init: Failed to register m/s init handlers with SAL. "
@@ -704,10 +749,11 @@
 	IA64_MCA_DEBUG("ia64_mca_init: registered os init handler with SAL\n");
 
 	/*
-	 *  Configure the CMCI vector and handler. Interrupts for CMC are
+	 *  Configure the CMCI/P vector and handler. Interrupts for CMC are
 	 *  per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
 	 */
 	register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction);
+	register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction);
 	ia64_mca_cmc_vector_setup();       /* Setup vector on BSP & enable */
 
 	/* Setup the MCA rendezvous interrupt vector */
@@ -822,9 +868,12 @@
 	int cpu;
 
 	/* Clear the Rendez checkin flag for all cpus */
-	for(cpu = 0; cpu < smp_num_cpus; cpu++)
+	for(cpu = 0; cpu < NR_CPUS; cpu++) {
+		if (!cpu_online(cpu))
+			continue;
 		if (ia64_mc_info.imi_rendez_checkin[cpu] == IA64_MCA_RENDEZ_CHECKIN_DONE)
 			ia64_mca_wakeup(cpu);
+	}
 
 }
 
@@ -841,11 +890,11 @@
 void
 ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
 {
-	int flags;
+	unsigned long flags;
 	int cpu = smp_processor_id();
 
 	/* Mask all interrupts */
-	save_and_cli(flags);
+	local_irq_save(flags);
 
 	ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_DONE;
 	/* Register with the SAL monarch that the slave has
@@ -860,7 +909,7 @@
 	ia64_mca_wakeup_ipi_wait();
 
 	/* Enable all interrupts */
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 
@@ -882,7 +931,6 @@
 void
 ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs)
 {
-
 }
 
 /*
@@ -987,6 +1035,9 @@
 	IA64_MCA_DEBUG("ia64_mca_cmc_int_handler: received interrupt vector = %#x on CPU %d\n",
 		       cmc_irq, smp_processor_id());
 
+	/* SAL spec states this should run w/ interrupts enabled */
+	local_irq_enable();
+
 	/* Get the CMC error record and log it */
 	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC, 0);
 
@@ -994,7 +1045,7 @@
 	if (!cmc_polling_enabled) {
 		int i, count = 1; /* we know 1 happened now */
 		unsigned long now = jiffies;
-		
+
 		for (i = 0; i < CMC_HISTORY_LENGTH; i++) {
 			if (now - cmc_history[i] <= HZ)
 				count++;
@@ -1002,34 +1053,24 @@
 
 		IA64_MCA_DEBUG(KERN_INFO "CMC threshold %d/%d\n", count, CMC_HISTORY_LENGTH);
 		if (count >= CMC_HISTORY_LENGTH) {
-			/*
-			 * CMC threshold exceeded, clear the history
-			 * so we have a fresh start when we return
-			 */
-			for (index = 0 ; index < CMC_HISTORY_LENGTH; index++)
-				cmc_history[index] = 0;
-			index = 0;
 
-			/* Switch to polling mode */
 			cmc_polling_enabled = 1;
+			spin_unlock(&cmc_history_lock);
 
 			/*
-			 * Unlock & enable interrupts  before
-			 * smp_call_function or risk deadlock
+			 * We rely on the local_irq_enable() above so
+			 * that this can't deadlock.
 			 */
-			spin_unlock(&cmc_history_lock);
 			ia64_mca_cmc_vector_disable(NULL);
 
-			local_irq_enable();
-			smp_call_function(ia64_mca_cmc_vector_disable, NULL, 1, 1);
+			smp_call_function(ia64_mca_cmc_vector_disable, NULL, 1, 0);
 
 			/*
 			 * Corrected errors will still be corrected, but
 			 * make sure there's a log somewhere that indicates
 			 * something is generating more than we can handle.
 			 */
-			printk(KERN_WARNING "ia64_mca_cmc_int_handler: WARNING: Switching to polling CMC handler, error records may be lost\n");
-			
+			printk(KERN_WARNING "%s: WARNING: Switching to polling CMC handler, error records may be lost\n", __FUNCTION__);
 
 			mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL);
 
@@ -1082,16 +1123,62 @@
 /*
  *  ia64_mca_cmc_int_caller
  *
- * 	Call CMC interrupt handler, only purpose is to have a
- * 	smp_call_function callable entry.
+ * 	Triggered by sw interrupt from CMC polling routine.  Calls
+ * 	real interrupt handler and either triggers a sw interrupt
+ * 	on the next cpu or does cleanup at the end.
  *
- * Inputs   :	dummy(unused)
- * Outputs  :	None
- * */
-static void
-ia64_mca_cmc_int_caller(void *dummy)
+ * Inputs
+ *	interrupt number
+ *	client data arg ptr
+ *	saved registers ptr
+ * Outputs
+ *	None
+ */
+void
+ia64_mca_cmc_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
 {
-	ia64_mca_cmc_int_handler(0, NULL, NULL);
+	static int start_count = -1;
+	unsigned int cpuid;
+
+	cpuid = smp_processor_id();
+
+	/* If first cpu, update count */
+	if (start_count == -1)
+		start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CMC);
+
+	ia64_mca_cmc_int_handler(cpe_irq, arg, ptregs);
+
+	for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++);
+		
+	if (cpuid < NR_CPUS) {
+		platform_send_ipi(cpuid, IA64_CMCP_VECTOR, IA64_IPI_DM_INT, 0);
+	} else {
+		/* If no log recored, switch out of polling mode */
+		if (start_count == IA64_LOG_COUNT(SAL_INFO_TYPE_CMC)) {
+
+			printk(KERN_WARNING "%s: Returning to interrupt driven CMC handler\n", __FUNCTION__);
+
+			/*
+			 * The cmc interrupt handler enabled irqs, so
+			 * this can't deadlock.
+			 */
+			smp_call_function(ia64_mca_cmc_vector_enable, NULL, 1, 0);
+
+			/*
+			 * Turn off interrupts before re-enabling the
+			 * cmc vector locally.  Make sure we get out.
+			 */
+			local_irq_disable();
+			ia64_mca_cmc_vector_enable(NULL);
+			cmc_polling_enabled = 0;
+
+		} else {
+
+			mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL);
+		}
+
+		start_count = -1;
+	}
 }
 
 /*
@@ -1106,49 +1193,63 @@
 static void
 ia64_mca_cmc_poll (unsigned long dummy)
 {
-	int start_count;
-
-	start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CMC);
-
-	/* Call the interrupt handler */
-	smp_call_function(ia64_mca_cmc_int_caller, NULL, 1, 1);
-	local_irq_disable();
-	ia64_mca_cmc_int_caller(NULL);
-	local_irq_enable();
-
-	/*
-	 * If no log recored, switch out of polling mode.
-	 */
-	if (start_count == IA64_LOG_COUNT(SAL_INFO_TYPE_CMC)) {
-		printk(KERN_WARNING "ia64_mca_cmc_poll: Returning to interrupt driven CMC handler\n");
-		cmc_polling_enabled = 0;
-		smp_call_function(ia64_mca_cmc_vector_enable, NULL, 1, 1);
-		ia64_mca_cmc_vector_enable(NULL);
-	} else {
-		mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL);
-	}
+	/* Trigger a CMC interrupt cascade  */
+	platform_send_ipi(__ffs(cpu_online_map), IA64_CMCP_VECTOR, IA64_IPI_DM_INT, 0);
 }
 
 /*
  *  ia64_mca_cpe_int_caller
  *
- * 	Call CPE interrupt handler, only purpose is to have a
- * 	smp_call_function callable entry.
+ * 	Triggered by sw interrupt from CPE polling routine.  Calls
+ * 	real interrupt handler and either triggers a sw interrupt
+ * 	on the next cpu or does cleanup at the end.
  *
- * Inputs   :	dummy(unused)
- * Outputs  :	None
- * */
-static void
-ia64_mca_cpe_int_caller(void *dummy)
+ * Inputs
+ *	interrupt number
+ *	client data arg ptr
+ *	saved registers ptr
+ * Outputs
+ *	None
+ */
+void
+ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
 {
-	ia64_mca_cpe_int_handler(0, NULL, NULL);
+	static int start_count = -1;
+	static int poll_time = MAX_CPE_POLL_INTERVAL;
+	unsigned int cpuid;
+
+	cpuid = smp_processor_id();
+
+	/* If first cpu, update count */
+	if (start_count == -1)
+		start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CPE);
+
+	ia64_mca_cpe_int_handler(cpe_irq, arg, ptregs);
+
+	for (++cpuid ; cpuid < NR_CPUS && !cpu_online(cpuid) ; cpuid++);
+
+	if (cpuid < NR_CPUS) {
+		platform_send_ipi(cpuid, IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0);
+	} else {
+		/*
+		 * If a log was recorded, increase our polling frequency,
+		 * otherwise, backoff.
+		 */
+		if (start_count != IA64_LOG_COUNT(SAL_INFO_TYPE_CPE)) {
+			poll_time = max(MIN_CPE_POLL_INTERVAL, poll_time / 2);
+		} else {
+			poll_time = min(MAX_CPE_POLL_INTERVAL, poll_time * 2);
+		}
+		start_count = -1;
+		mod_timer(&cpe_poll_timer, jiffies + poll_time);
+	}
 }
 
 /*
  *  ia64_mca_cpe_poll
  *
- *	Poll for Corrected Platform Errors (CPEs), dynamically adjust
- *	polling interval based on occurance of an event.
+ *	Poll for Corrected Platform Errors (CPEs), trigger interrupt
+ *	on first cpu, from there it will trickle through all the cpus.
  *
  * Inputs   :   dummy(unused)
  * Outputs  :   None
@@ -1157,27 +1258,8 @@
 static void
 ia64_mca_cpe_poll (unsigned long dummy)
 {
-	int start_count;
-	static int poll_time = MAX_CPE_POLL_INTERVAL;
-
-	start_count = IA64_LOG_COUNT(SAL_INFO_TYPE_CPE);
-
-	/* Call the interrupt handler */
-	smp_call_function(ia64_mca_cpe_int_caller, NULL, 1, 1);
-	local_irq_disable();
-	ia64_mca_cpe_int_caller(NULL);
-	local_irq_enable();
-
-	/*
-	 * If a log was recorded, increase our polling frequency,
-	 * otherwise, backoff.
-	 */
-	if (start_count != IA64_LOG_COUNT(SAL_INFO_TYPE_CPE)) {
-		poll_time = max(MIN_CPE_POLL_INTERVAL, poll_time/2);
-	} else {
-		poll_time = min(MAX_CPE_POLL_INTERVAL, poll_time * 2);
-	}
-	mod_timer(&cpe_poll_timer, jiffies + poll_time);
+	/* Trigger a CPE interrupt cascade  */
+	platform_send_ipi(__ffs(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0);
 }
 
 /*
@@ -1203,8 +1285,10 @@
 	cpe_poll_timer.function = ia64_mca_cpe_poll;
 
 	/* If platform doesn't support CPEI, get the timer going. */
-	if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0)
+	if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) {
+		register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
 		ia64_mca_cpe_poll(0UL);
+	}
 
 	return 0;
 }
@@ -1226,29 +1310,19 @@
 void
 ia64_init_handler (struct pt_regs *pt, struct switch_stack *sw)
 {
-	sal_log_processor_info_t *proc_ptr;
-	ia64_err_rec_t *plog_ptr;
+	pal_min_state_area_t *ms;
 
-	printk(KERN_INFO "Entered OS INIT handler\n");
-
-	/* Get the INIT processor log */
-	if (!ia64_log_get(SAL_INFO_TYPE_INIT, (prfunc_t)printk))
-		return;                 // no record retrieved
-
-#ifdef IA64_DUMP_ALL_PROC_INFO
-	ia64_log_print(SAL_INFO_TYPE_INIT, (prfunc_t)printk);
-#endif
+	printk(KERN_INFO "Entered OS INIT handler. PSP=%lx\n",
+		ia64_sal_to_os_handoff_state.proc_state_param);
 
 	/*
-	 * get pointer to min state save area
-	 *
+	 * Address of minstate area provided by PAL is physical,
+	 * uncacheable (bit 63 set). Convert to Linux virtual
+	 * address in region 6.
 	 */
-	plog_ptr=(ia64_err_rec_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT);
-	proc_ptr = &plog_ptr->proc_err;
+	ms = (pal_min_state_area_t *)(ia64_sal_to_os_handoff_state.pal_min_state | (6ul<<61));
 
-	ia64_process_min_state_save(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area);
-
-	init_handler_platform(proc_ptr, pt, sw);	/* call platform specific routines */
+	init_handler_platform(ms, pt, sw);	/* call platform specific routines */
 }
 
 /*
@@ -1271,7 +1345,8 @@
 static void
 ia64_log_hexdump(unsigned char *p, unsigned long n_ch, prfunc_t prfunc)
 {
-	int i, j;
+	unsigned long i;
+	int j;
 
 	if (!p)
 		return;
@@ -1912,9 +1987,9 @@
 		ia64_log_prt_guid(&psei->guid, prfunc);
 	}
 	if (psei->valid.oem_data) {
-		platform_plat_specific_err_print((int)psei->header.len,
-				      (int)sizeof(sal_log_plat_specific_err_info_t) - 1,
-				      &(psei->oem_data[0]), prfunc);
+		platform_plat_specific_err_print((int) psei->header.len,
+				      (char *) psei->oem_data - (char *) psei,
+				      &psei->oem_data[0], prfunc);
 	}
 	prfunc("\n");
 }
@@ -2119,7 +2194,7 @@
 {
 	sal_log_section_hdr_t       *slsh;
 	int                         n_sects;
-	int                         ercd_pos;
+	u32                         ercd_pos;
 
 	if (!lh)
 		return;
@@ -2181,7 +2256,7 @@
 {
 	sal_log_section_hdr_t	*slsh;
 	int			n_sects;
-	int			ercd_pos;
+	u32			ercd_pos;
 	int			platform_err = 0;
 
 	if (!lh)
@@ -2319,3 +2394,12 @@
 	}
 	return platform_err;
 }
+
+static int __init
+ia64_mca_disable_cpe_polling(char *str)
+{
+	cpe_poll_enabled = 0;
+	return 1;
+}
+
+__setup("disable_cpe_poll", ia64_mca_disable_cpe_polling);
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/mca_asm.S linux-2.4.23-pre4/arch/ia64/kernel/mca_asm.S
--- linux-2.4.23-pre3/arch/ia64/kernel/mca_asm.S	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/mca_asm.S	2003-09-12 12:44:34.000000000 -0700
@@ -57,7 +57,9 @@
 	st8	[_tmp]=r9,0x08;;			\
 	st8	[_tmp]=r10,0x08;;			\
 	st8	[_tmp]=r11,0x08;;			\
-	st8	[_tmp]=r12,0x08
+	st8	[_tmp]=r12,0x08;;			\
+	st8	[_tmp]=r17,0x08;;			\
+	st8	[_tmp]=r18,0x08
 
 /*
  * OS_MCA_TO_SAL_HANDOFF_STATE (SAL 3.0 spec)
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/minstate.h linux-2.4.23-pre4/arch/ia64/kernel/minstate.h
--- linux-2.4.23-pre3/arch/ia64/kernel/minstate.h	2002-11-28 15:53:09.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/kernel/minstate.h	2003-09-12 12:44:34.000000000 -0700
@@ -3,43 +3,25 @@
 #include "entry.h"
 
 /*
- * A couple of convenience macros that make writing and reading
- * SAVE_MIN and SAVE_REST easier.
- */
-#define rARPR		r31
-#define rCRIFS		r30
-#define rCRIPSR		r29
-#define rCRIIP		r28
-#define rARRSC		r27
-#define rARPFS		r26
-#define rARUNAT		r25
-#define rARRNAT		r24
-#define rARBSPSTORE	r23
-#define rKRBS		r22
-#define rB6		r21
-#define rR1		r20
-
-/*
- * Here start the source dependent macros.
- */
-
-/*
- * For ivt.s we want to access the stack virtually so we dont have to disable translation
+ * For ivt.s we want to access the stack virtually so we don't have to disable translation
  * on interrupts.
+ *
+ *  On entry:
+ *	r1:	pointer to current task (ar.k6)
  */
 #define MINSTATE_START_SAVE_MIN_VIRT								\
 	dep r1=-1,r1,61,3;				/* r1 = current (virtual) */		\
 (pUser)	mov ar.rsc=0;		/* set enforced lazy mode, pl 0, little-endian, loadrs=0 */	\
 	;;											\
-(pUser)	addl rKRBS=IA64_RBS_OFFSET,r1;			/* compute base of RBS */		\
-(pUser)	mov rARRNAT=ar.rnat;									\
+(pUser)	addl r22=IA64_RBS_OFFSET,r1;			/* compute base of RBS */		\
+(pUser)	mov r24=ar.rnat;									\
 (pKern) mov r1=sp;					/* get sp  */				\
 	;;											\
 (pUser)	addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;	/* compute base of memory stack */	\
-(pUser)	mov rARBSPSTORE=ar.bspstore;			/* save ar.bspstore */			\
+(pUser)	mov r23=ar.bspstore;				/* save ar.bspstore */			\
 	;;											\
 (pKern) addl r1=-IA64_PT_REGS_SIZE,r1;			/* if in kernel mode, use sp (r12) */	\
-(pUser)	mov ar.bspstore=rKRBS;				/* switch to kernel RBS */		\
+(pUser)	mov ar.bspstore=r22;				/* switch to kernel RBS */		\
 	;;											\
 (pUser)	mov r18=ar.bsp;										\
 (pUser)	mov ar.rsc=0x3;		/* set eager mode, pl 0, little-endian, loadrs=0 */		\
@@ -51,21 +33,21 @@
 
 /*
  * For mca_asm.S we want to access the stack physically since the state is saved before we
- * go virtual and dont want to destroy the iip or ipsr.
+ * go virtual and don't want to destroy the iip or ipsr.
  */
 #define MINSTATE_START_SAVE_MIN_PHYS								\
 (pKern) movl sp=ia64_init_stack+IA64_STK_OFFSET-IA64_PT_REGS_SIZE;				\
 (pUser)	mov ar.rsc=0;		/* set enforced lazy mode, pl 0, little-endian, loadrs=0 */	\
-(pUser)	addl rKRBS=IA64_RBS_OFFSET,r1;		/* compute base of register backing store */	\
+(pUser)	addl r22=IA64_RBS_OFFSET,r1;		/* compute base of register backing store */	\
 	;;											\
-(pUser)	mov rARRNAT=ar.rnat;									\
+(pUser)	mov r24=ar.rnat;									\
 (pKern) dep r1=0,sp,61,3;				/* compute physical addr of sp	*/	\
 (pUser)	addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1;	/* compute base of memory stack */	\
-(pUser)	mov rARBSPSTORE=ar.bspstore;			/* save ar.bspstore */			\
-(pUser)	dep rKRBS=-1,rKRBS,61,3;			/* compute kernel virtual addr of RBS */\
+(pUser)	mov r23=ar.bspstore;				/* save ar.bspstore */			\
+(pUser)	dep r22=-1,r22,61,3;				/* compute kernel virtual addr of RBS */\
 	;;											\
 (pKern) addl r1=-IA64_PT_REGS_SIZE,r1;		/* if in kernel mode, use sp (r12) */		\
-(pUser)	mov ar.bspstore=rKRBS;			/* switch to kernel RBS */			\
+(pUser)	mov ar.bspstore=r22;			/* switch to kernel RBS */			\
 	;;											\
 (pUser)	mov r18=ar.bsp;										\
 (pUser)	mov ar.rsc=0x3;		/* set eager mode, pl 0, little-endian, loadrs=0 */		\
@@ -96,143 +78,168 @@
  *
  * Upon exit, the state is as follows:
  *	psr.ic: off
- *	r2 = points to &pt_regs.r16
+ *	 r2 = points to &pt_regs.r16
+ *	 r8 = contents of ar.ccv
+ *	 r9 = contents of ar.csd
+ *	r10 = contents of ar.ssd
+ *	r11 = FPSR_DEFAULT
  *	r12 = kernel sp (kernel virtual address)
  *	r13 = points to current task_struct (kernel virtual address)
  *	p15 = TRUE if psr.i is set in cr.ipsr
- *	predicate registers (other than p2, p3, and p15), b6, r3, r8, r9, r10, r11, r14, r15:
+ *	predicate registers (other than p2, p3, and p15), b6, r3, r14, r15:
  *		preserved
  *
  * Note that psr.ic is NOT turned on by this macro.  This is so that
  * we can pass interruption state as arguments to a handler.
  */
-#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA)							  \
-	mov rARRSC=ar.rsc;									  \
-	mov rARPFS=ar.pfs;									  \
-	mov rR1=r1;										  \
-	mov rARUNAT=ar.unat;									  \
-	mov rCRIPSR=cr.ipsr;									  \
-	mov rB6=b6;				/* rB6 = branch reg 6 */			  \
-	mov rCRIIP=cr.iip;									  \
-	mov r1=IA64_KR(CURRENT);		/* r1 = current (physical) */			  \
-	COVER;											  \
-	;;											  \
-	invala;											  \
-	extr.u r16=rCRIPSR,32,2;		/* extract psr.cpl */				  \
-	;;											  \
-	cmp.eq pKern,pUser=r0,r16;		/* are we in kernel mode already? (psr.cpl==0) */ \
-	/* switch from user to kernel RBS: */							  \
-	;;											  \
-	SAVE_IFS;										  \
-	MINSTATE_START_SAVE_MIN									  \
-	;;											  \
-	mov r16=r1;					/* initialize first base pointer */	  \
-	adds r17=8,r1;					/* initialize second base pointer */	  \
-	;;											  \
-	st8 [r16]=rCRIPSR,16;	/* save cr.ipsr */						  \
-	st8 [r17]=rCRIIP,16;	/* save cr.iip */						  \
-(pKern)	mov r18=r0;		/* make sure r18 isn't NaT */					  \
-	;;											  \
-	st8 [r16]=rCRIFS,16;	/* save cr.ifs */						  \
-	st8 [r17]=rARUNAT,16;	/* save ar.unat */						  \
-(pUser)	sub r18=r18,rKRBS;	/* r18=RSE.ndirty*8 */						  \
-	;;											  \
-	st8 [r16]=rARPFS,16;	/* save ar.pfs */						  \
-	st8 [r17]=rARRSC,16;	/* save ar.rsc */						  \
-	tbit.nz p15,p0=rCRIPSR,IA64_PSR_I_BIT							  \
-	;;			/* avoid RAW on r16 & r17 */					  \
-(pKern)	adds r16=16,r16;	/* skip over ar_rnat field */					  \
-(pKern)	adds r17=16,r17;	/* skip over ar_bspstore field */				  \
-(pUser)	st8 [r16]=rARRNAT,16;	/* save ar.rnat */						  \
-(pUser)	st8 [r17]=rARBSPSTORE,16;	/* save ar.bspstore */					  \
-	;;											  \
-	st8 [r16]=rARPR,16;	/* save predicates */						  \
-	st8 [r17]=rB6,16;	/* save b6 */							  \
-	shl r18=r18,16;		/* compute ar.rsc to be used for "loadrs" */			  \
-	;;											  \
-	st8 [r16]=r18,16;	/* save ar.rsc value for "loadrs" */				  \
-	st8.spill [r17]=rR1,16;	/* save original r1 */						  \
-	;;											  \
-.mem.offset 0,0;	st8.spill [r16]=r2,16;							  \
-.mem.offset 8,0;	st8.spill [r17]=r3,16;							  \
-	adds r2=IA64_PT_REGS_R16_OFFSET,r1;							  \
-	;;											  \
-.mem.offset 0,0;		st8.spill [r16]=r12,16;						  \
-.mem.offset 8,0;		st8.spill [r17]=r13,16;						  \
-	cmp.eq pNonSys,pSys=r0,r0	/* initialize pSys=0, pNonSys=1 */			  \
-	;;											  \
-.mem.offset 0,0;		st8.spill [r16]=r14,16;						  \
-.mem.offset 8,0;		st8.spill [r17]=r15,16;						  \
-	dep r14=-1,r0,61,3;									  \
-	;;											  \
-.mem.offset 0,0;		st8.spill [r16]=r8,16;						  \
-.mem.offset 8,0;		st8.spill [r17]=r9,16;						  \
-	adds r12=-16,r1;	/* switch to kernel memory stack (with 16 bytes of scratch) */	  \
-	;;											  \
-.mem.offset 0,0;		st8.spill [r16]=r10,16;						  \
-.mem.offset 8,0;		st8.spill [r17]=r11,16;						  \
-	mov r13=IA64_KR(CURRENT);	/* establish `current' */				  \
-	;;											  \
-	EXTRA;											  \
-	movl r1=__gp;		/* establish kernel global pointer */				  \
-	;;											  \
+#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA)							\
+	mov r29=cr.ipsr;									\
+	mov r17=IA64_KR(CURRENT);		/* r1 = current (physical) */			\
+	mov r20=r1;										\
+	mov r27=ar.rsc;										\
+	mov r25=ar.unat;									\
+	mov r26=ar.pfs;										\
+	mov r21=ar.fpsr;									\
+	mov r28=cr.iip;										\
+	COVER;											\
+	;;											\
+	invala;											\
+	extr.u r16=r29,32,2;		/* extract psr.cpl */					\
+	;;											\
+	cmp.eq pKern,pUser=r0,r16;	/* are we in kernel mode already? (psr.cpl==0) */	\
+	mov r1=r17; 										\
+	/* switch from user to kernel RBS: */							\
+	;;											\
+	SAVE_IFS;										\
+	MINSTATE_START_SAVE_MIN									\
+	adds r17=2*L1_CACHE_BYTES,r1;		/* really: biggest cache-line size */		\
+	adds r16=PT(CR_IPSR),r1;								\
+	;;											\
+	lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES;						\
+	st8 [r16]=r29;		/* save cr.ipsr */						\
+	;;											\
+	lfetch.fault.excl.nt1 [r17];								\
+	;;											\
+	adds r16=PT(R8),r1;	/* initialize first base pointer */				\
+	adds r17=PT(R9),r1;	/* initialize second base pointer */				\
+	;;											\
+.mem.offset 0,0; st8.spill [r16]=r8,16;								\
+.mem.offset 8,0; st8.spill [r17]=r9,16;								\
+	;;											\
+.mem.offset 0,0; st8.spill [r16]=r10,24;							\
+.mem.offset 8,0; st8.spill [r17]=r11,32;							\
+	;;											\
+	st8 [r16]=r28,8;	/* save cr.iip */						\
+	mov r28=b0;          	/* rCRIIP=branch reg b0 */					\
+(pKern)	mov r18=r0;		/* make sure r18 isn't NaT */					\
+	mov r8=ar.ccv;                                                                          \
+	mov r9=ar.csd;                                                                          \
+	mov r10=ar.ssd;                                                                         \
+	movl r11=FPSR_DEFAULT;   /* L-unit */                                                   \
+	;;											\
+	st8 [r16]=r30,16;	/* save cr.ifs */						\
+	st8 [r17]=r25,16;	/* save ar.unat */						\
+(pUser)	sub r18=r18,r22;	/* r18=RSE.ndirty*8 */						\
+	;;											\
+	st8 [r16]=r26,16;	/* save ar.pfs */						\
+	st8 [r17]=r27,16;	/* save ar.rsc */						\
+	tbit.nz p15,p0=r29,IA64_PSR_I_BIT							\
+	;;			/* avoid RAW on r16 & r17 */					\
+(pKern)	adds r16=16,r16;	/* skip over ar_rnat field */					\
+(pKern)	adds r17=16,r17;	/* skip over ar_bspstore field */				\
+(pUser)	st8 [r16]=r24,16;	/* save ar.rnat */						\
+(pUser)	st8 [r17]=r23,16;	/* save ar.bspstore */					  	\
+	;;											\
+	st8 [r16]=r31,16;	/* save predicates */						\
+	st8 [r17]=r28,16;	/* save b0 */							\
+	shl r18=r18,16;		/* compute ar.rsc to be used for "loadrs" */			\
+	;;											\
+	st8 [r16]=r18,16;	/* save ar.rsc value for "loadrs" */				\
+	st8.spill [r17]=r20,16;	/* save original r1 */						\
+	;;											\
+.mem.offset 0,0; st8.spill [r16]=r12,16;							\
+.mem.offset 8,0; st8.spill [r17]=r13,16;							\
+	cmp.eq pNonSys,pSys=r0,r0	/* initialize pSys=0, pNonSys=1 */			\
+	;;											\
+.mem.offset 0,0; st8 [r16]=r21,PT(R14)-PT(AR_FPSR); 	/* ar.fpsr */				\
+.mem.offset 8,0; st8.spill [r17]=r15,PT(R3)-PT(R15);						\
+	adds r12=-16,r1;	/* switch to kernel memory stack (with 16 bytes of scratch) */	\
+	;;											\
+	mov r13=IA64_KR(CURRENT);	/* establish `current' */				\
+.mem.offset 0,0; st8.spill [r16]=r14,8;								\
+	dep r14=-1,r0,61,3;									\
+	;;											\
+.mem.offset 0,0; st8.spill [r16]=r2,16;								\
+.mem.offset 8,0; st8.spill [r17]=r3,16;								\
+	adds r2=IA64_PT_REGS_R16_OFFSET,r1;							\
+	;;											\
+	EXTRA;											\
+	movl r1=__gp;		/* establish kernel global pointer */				\
+	;;											\
 	MINSTATE_END_SAVE_MIN
 
 /*
- * SAVE_REST saves the remainder of pt_regs (with psr.ic on).  This
- * macro guarantees to preserve all predicate registers, r8, r9, r10,
- * r11, r14, and r15.
+ * SAVE_REST saves the remainder of pt_regs (with psr.ic on).
  *
  * Assumed state upon entry:
  *	psr.ic: on
  *	r2:	points to &pt_regs.r16
  *	r3:	points to &pt_regs.r17
+ *	r8:	contents of ar.ccv
+ *	r9:	contents of ar.csd
+ *	r10:	contents of ar.ssd
+ *	r11:	FPSR_DEFAULT
+ *
+ * Registers r14 and r15 are guaranteed not to be touched by SAVE_REST.
  */
 #define SAVE_REST				\
-.mem.offset 0,0;	st8.spill [r2]=r16,16;	\
-.mem.offset 8,0;	st8.spill [r3]=r17,16;	\
-	;;					\
-.mem.offset 0,0;	st8.spill [r2]=r18,16;	\
-.mem.offset 8,0;	st8.spill [r3]=r19,16;	\
+.mem.offset 0,0; st8.spill [r2]=r16,16;		\
+.mem.offset 8,0; st8.spill [r3]=r17,16;		\
 	;;					\
-	mov r16=ar.ccv;		/* M-unit */	\
-	movl r18=FPSR_DEFAULT	/* L-unit */	\
+.mem.offset 0,0; st8.spill [r2]=r18,16;		\
+.mem.offset 8,0; st8.spill [r3]=r19,16;		\
 	;;					\
-	mov r17=ar.fpsr;	/* M-unit */	\
-	mov ar.fpsr=r18;	/* M-unit */	\
+.mem.offset 0,0; st8.spill [r2]=r20,16;		\
+.mem.offset 8,0; st8.spill [r3]=r21,16;		\
+	mov r18=b6;				\
 	;;					\
-.mem.offset 0,0;	st8.spill [r2]=r20,16;	\
-.mem.offset 8,0;	st8.spill [r3]=r21,16;	\
-	mov r18=b0;				\
-	;;					\
-.mem.offset 0,0;	st8.spill [r2]=r22,16;	\
-.mem.offset 8,0;	st8.spill [r3]=r23,16;	\
+.mem.offset 0,0; st8.spill [r2]=r22,16;		\
+.mem.offset 8,0; st8.spill [r3]=r23,16;		\
 	mov r19=b7;				\
 	;;					\
-.mem.offset 0,0;	st8.spill [r2]=r24,16;	\
-.mem.offset 8,0;	st8.spill [r3]=r25,16;	\
-	;;					\
-.mem.offset 0,0;	st8.spill [r2]=r26,16;	\
-.mem.offset 8,0;	st8.spill [r3]=r27,16;	\
+.mem.offset 0,0; st8.spill [r2]=r24,16;		\
+.mem.offset 8,0; st8.spill [r3]=r25,16;		\
 	;;					\
-.mem.offset 0,0;	st8.spill [r2]=r28,16;	\
-.mem.offset 8,0;	st8.spill [r3]=r29,16;	\
+.mem.offset 0,0; st8.spill [r2]=r26,16;		\
+.mem.offset 8,0; st8.spill [r3]=r27,16;		\
 	;;					\
-.mem.offset 0,0;	st8.spill [r2]=r30,16;	\
-.mem.offset 8,0;	st8.spill [r3]=r31,16;	\
+.mem.offset 0,0; st8.spill [r2]=r28,16;		\
+.mem.offset 8,0; st8.spill [r3]=r29,16;		\
 	;;					\
-	st8 [r2]=r16,16;	/* ar.ccv */	\
-	st8 [r3]=r17,16;	/* ar.fpsr */	\
+.mem.offset 0,0; st8.spill [r2]=r30,16;		\
+.mem.offset 8,0; st8.spill [r3]=r31,32;		\
 	;;					\
-	st8 [r2]=r18,16;	/* b0 */	\
-	st8 [r3]=r19,16+8;	/* b7 */	\
+	mov ar.fpsr=r11;	/* M-unit */	\
+	st8 [r2]=r8,8;		/* ar.ccv */	\
+	adds r24=PT(B6)-PT(F7),r3;		\
 	;;					\
 	stf.spill [r2]=f6,32;			\
 	stf.spill [r3]=f7,32;			\
 	;;					\
 	stf.spill [r2]=f8,32;			\
-	stf.spill [r3]=f9,32
+	stf.spill [r3]=f9,32;			\
+	;;					\
+	stf.spill [r2]=f10;			\
+	stf.spill [r3]=f11;			\
+	adds r25=PT(B7)-PT(F11),r3;		\
+	;;					\
+	st8 [r24]=r18,16;	/* b6 */	\
+	st8 [r25]=r19,16;	/* b7 */	\
+	;;					\
+	st8 [r24]=r9;		/* ar.csd */	\
+	st8 [r25]=r10;		/* ar.ssd */	\
+	;;
 
-#define SAVE_MIN_WITH_COVER	DO_SAVE_MIN(cover, mov rCRIFS=cr.ifs,)
-#define SAVE_MIN_WITH_COVER_R19	DO_SAVE_MIN(cover, mov rCRIFS=cr.ifs, mov r15=r19)
-#define SAVE_MIN		DO_SAVE_MIN(     , mov rCRIFS=r0, )
+#define SAVE_MIN_WITH_COVER	DO_SAVE_MIN(cover, mov r30=cr.ifs,)
+#define SAVE_MIN_WITH_COVER_R19	DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19)
+#define SAVE_MIN		DO_SAVE_MIN(     , mov r30=r0, )
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/pal.S linux-2.4.23-pre4/arch/ia64/kernel/pal.S
--- linux-2.4.23-pre3/arch/ia64/kernel/pal.S	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/pal.S	2003-09-12 12:44:34.000000000 -0700
@@ -164,7 +164,7 @@
 	;;
 	mov loc4=ar.rsc			// save RSE configuration
 	dep.z loc2=loc2,0,61		// convert pal entry point to physical
-	dep.z r8=r8,0,61		// convert rp to physical
+	tpa r8=r8			// convert rp to physical
 	;;
 	mov b7 = loc2			// install target to branch reg
 	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
@@ -174,13 +174,13 @@
 	or loc3=loc3,r17		// add in psr the bits to set
 	;;
 	andcm r16=loc3,r16		// removes bits to clear from psr
-	br.call.sptk.many rp=ia64_switch_mode
+	br.call.sptk.many rp=ia64_switch_mode_phys
 .ret1:	mov rp = r8			// install return address (physical)
 	br.cond.sptk.many b7
 1:
 	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
 	mov r16=loc3			// r16= original psr
-	br.call.sptk.many rp=ia64_switch_mode // return to virtual mode
+	br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
 .ret2:
 	mov psr.l = loc3		// restore init PSR
 
@@ -228,13 +228,13 @@
 	mov b7 = loc2			// install target to branch reg
 	;;
 	andcm r16=loc3,r16		// removes bits to clear from psr
-	br.call.sptk.many rp=ia64_switch_mode
+	br.call.sptk.many rp=ia64_switch_mode_phys
 .ret6:
 	br.call.sptk.many rp=b7		// now make the call
 .ret7:
 	mov ar.rsc=0			// put RSE in enforced lazy, LE mode
 	mov r16=loc3			// r16= original psr
-	br.call.sptk.many rp=ia64_switch_mode	// return to virtual mode
+	br.call.sptk.many rp=ia64_switch_mode_virt	// return to virtual mode
 
 .ret8:	mov psr.l  = loc3		// restore init PSR
 	mov ar.pfs = loc1
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/palinfo.c linux-2.4.23-pre4/arch/ia64/kernel/palinfo.c
--- linux-2.4.23-pre3/arch/ia64/kernel/palinfo.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/palinfo.c	2003-09-12 12:44:34.000000000 -0700
@@ -91,7 +91,7 @@
 	"eager loads and stores"
 };
 
-#define RSE_HINTS_COUNT (sizeof(rse_hints)/sizeof(const char *))
+#define RSE_HINTS_COUNT ARRAY_SIZE(rse_hints)
 
 static const char *mem_attrib[]={
 	"WB",		/* 000 */
@@ -192,15 +192,15 @@
 
 	for (i=0; i < 8 ; i++ ) {
 		if (halt_info[i].pal_power_mgmt_info_s.im == 1) {
-			p += sprintf(p,	"Power level %d:\n" \
-					"\tentry_latency       : %d cycles\n" \
-					"\texit_latency        : %d cycles\n" \
-					"\tpower consumption   : %d mW\n" \
-					"\tCache+TLB coherency : %s\n", i,
-				halt_info[i].pal_power_mgmt_info_s.entry_latency,
-				halt_info[i].pal_power_mgmt_info_s.exit_latency,
-				halt_info[i].pal_power_mgmt_info_s.power_consumption,
-				halt_info[i].pal_power_mgmt_info_s.co ? "Yes" : "No");
+			p += sprintf(p,	"Power level %d:\n"
+				     "\tentry_latency       : %d cycles\n"
+				     "\texit_latency        : %d cycles\n"
+				     "\tpower consumption   : %d mW\n"
+				     "\tCache+TLB coherency : %s\n", i,
+				     halt_info[i].pal_power_mgmt_info_s.entry_latency,
+				     halt_info[i].pal_power_mgmt_info_s.exit_latency,
+				     halt_info[i].pal_power_mgmt_info_s.power_consumption,
+				     halt_info[i].pal_power_mgmt_info_s.co ? "Yes" : "No");
 		} else {
 			p += sprintf(p,"Power level %d: not implemented\n",i);
 		}
@@ -212,9 +212,9 @@
 cache_info(char *page)
 {
 	char *p = page;
-	u64 levels, unique_caches;
+	u64 i, levels, unique_caches;
 	pal_cache_config_info_t cci;
-	int i,j, k;
+	int j, k;
 	s64 status;
 
 	if ((status = ia64_pal_cache_summary(&levels, &unique_caches)) != 0) {
@@ -232,48 +232,50 @@
 			if ((status=ia64_pal_cache_config_info(i,j, &cci)) != 0) {
 				continue;
 			}
-			p += sprintf(p, "%s Cache level %d:\n" \
-					"\tSize           : %ld bytes\n" \
-					"\tAttributes     : ",
-					cache_types[j+cci.pcci_unified], i+1,
-					cci.pcci_cache_size);
+			p += sprintf(p,
+				     "%s Cache level %lu:\n"
+				     "\tSize           : %lu bytes\n"
+				     "\tAttributes     : ",
+				     cache_types[j+cci.pcci_unified], i+1,
+				     cci.pcci_cache_size);
 
 			if (cci.pcci_unified) p += sprintf(p, "Unified ");
 
 			p += sprintf(p, "%s\n", cache_mattrib[cci.pcci_cache_attr]);
 
-			p += sprintf(p, "\tAssociativity  : %d\n" \
-					"\tLine size      : %d bytes\n" \
-					"\tStride         : %d bytes\n",
-					cci.pcci_assoc,
-					1<<cci.pcci_line_size,
-					1<<cci.pcci_stride);
+			p += sprintf(p,
+				     "\tAssociativity  : %d\n"
+				     "\tLine size      : %d bytes\n"
+				     "\tStride         : %d bytes\n",
+				     cci.pcci_assoc, 1<<cci.pcci_line_size, 1<<cci.pcci_stride);
 			if (j == 1)
 				p += sprintf(p, "\tStore latency  : N/A\n");
 			else
 				p += sprintf(p, "\tStore latency  : %d cycle(s)\n",
 						cci.pcci_st_latency);
 
-			p += sprintf(p, "\tLoad latency   : %d cycle(s)\n" \
-					"\tStore hints    : ",
-					cci.pcci_ld_latency);
+			p += sprintf(p,
+				     "\tLoad latency   : %d cycle(s)\n"
+				     "\tStore hints    : ", cci.pcci_ld_latency);
 
 			for(k=0; k < 8; k++ ) {
-				if ( cci.pcci_st_hints & 0x1) p += sprintf(p, "[%s]", cache_st_hints[k]);
+				if ( cci.pcci_st_hints & 0x1)
+					p += sprintf(p, "[%s]", cache_st_hints[k]);
 				cci.pcci_st_hints >>=1;
 			}
 			p += sprintf(p, "\n\tLoad hints     : ");
 
 			for(k=0; k < 8; k++ ) {
-				if ( cci.pcci_ld_hints & 0x1) p += sprintf(p, "[%s]", cache_ld_hints[k]);
+				if (cci.pcci_ld_hints & 0x1)
+					p += sprintf(p, "[%s]", cache_ld_hints[k]);
 				cci.pcci_ld_hints >>=1;
 			}
-			p += sprintf(p, "\n\tAlias boundary : %d byte(s)\n" \
-					"\tTag LSB        : %d\n" \
-					"\tTag MSB        : %d\n",
-					1<<cci.pcci_alias_boundary,
-					cci.pcci_tag_lsb,
-					cci.pcci_tag_msb);
+			p += sprintf(p,
+				     "\n\tAlias boundary : %d byte(s)\n"
+				     "\tTag LSB        : %d\n"
+				     "\tTag MSB        : %d\n",
+				     1<<cci.pcci_alias_boundary, cci.pcci_tag_lsb,
+				     cci.pcci_tag_msb);
 
 			/* when unified, data(j=2) is enough */
 			if (cci.pcci_unified) break;
@@ -303,20 +305,20 @@
 	}
 
 
-	p += sprintf(p, "Physical Address Space         : %d bits\n" \
-			"Virtual Address Space          : %d bits\n" \
-			"Protection Key Registers(PKR)  : %d\n" \
-			"Implemented bits in PKR.key    : %d\n" \
-			"Hash Tag ID                    : 0x%x\n" \
-			"Size of RR.rid                 : %d\n",
-			vm_info_1.pal_vm_info_1_s.phys_add_size,
-			vm_info_2.pal_vm_info_2_s.impl_va_msb+1,
-			vm_info_1.pal_vm_info_1_s.max_pkr+1,
-			vm_info_1.pal_vm_info_1_s.key_size,
-			vm_info_1.pal_vm_info_1_s.hash_tag_id,
-			vm_info_2.pal_vm_info_2_s.rid_size);
+	p += sprintf(p,
+		     "Physical Address Space         : %d bits\n"
+		     "Virtual Address Space          : %d bits\n"
+		     "Protection Key Registers(PKR)  : %d\n"
+		     "Implemented bits in PKR.key    : %d\n"
+		     "Hash Tag ID                    : 0x%x\n"
+		     "Size of RR.rid                 : %d\n",
+		     vm_info_1.pal_vm_info_1_s.phys_add_size,
+		     vm_info_2.pal_vm_info_2_s.impl_va_msb+1, vm_info_1.pal_vm_info_1_s.max_pkr+1,
+		     vm_info_1.pal_vm_info_1_s.key_size, vm_info_1.pal_vm_info_1_s.hash_tag_id,
+		     vm_info_2.pal_vm_info_2_s.rid_size);
 
-	if (ia64_pal_mem_attrib(&attrib) != 0) return 0;
+	if (ia64_pal_mem_attrib(&attrib) != 0)
+		return 0;
 
 	p += sprintf(p, "Supported memory attributes    : ");
 	sep = "";
@@ -333,13 +335,14 @@
 		return 0;
 	}
 
-	p += sprintf(p, "\nTLB walker                     : %simplemented\n" \
-			"Number of DTR                  : %d\n" \
-			"Number of ITR                  : %d\n" \
-			"TLB insertable page sizes      : ",
-			vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
-			vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
-			vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
+	p += sprintf(p,
+		     "\nTLB walker                     : %simplemented\n"
+		     "Number of DTR                  : %d\n"
+		     "Number of ITR                  : %d\n"
+		     "TLB insertable page sizes      : ",
+		     vm_info_1.pal_vm_info_1_s.vw ? "" : "not ",
+		     vm_info_1.pal_vm_info_1_s.max_dtr_entry+1,
+		     vm_info_1.pal_vm_info_1_s.max_itr_entry+1);
 
 
 	p = bitvector_process(p, tr_pages);
@@ -353,21 +356,19 @@
 		return 0;
 	}
 
-	p += sprintf(p, "\nPurge base address             : 0x%016lx\n" \
-			"Purge outer loop count         : %d\n" \
-			"Purge inner loop count         : %d\n" \
-			"Purge outer loop stride        : %d\n" \
-			"Purge inner loop stride        : %d\n",
-			ptce.base,
-			ptce.count[0],
-			ptce.count[1],
-			ptce.stride[0],
-			ptce.stride[1]);
-
-	p += sprintf(p, "TC Levels                      : %d\n" \
-			"Unique TC(s)                   : %d\n",
-			vm_info_1.pal_vm_info_1_s.num_tc_levels,
-			vm_info_1.pal_vm_info_1_s.max_unique_tcs);
+	p += sprintf(p,
+		     "\nPurge base address             : 0x%016lx\n"
+		     "Purge outer loop count         : %d\n"
+		     "Purge inner loop count         : %d\n"
+		     "Purge outer loop stride        : %d\n"
+		     "Purge inner loop stride        : %d\n",
+		     ptce.base, ptce.count[0], ptce.count[1], ptce.stride[0], ptce.stride[1]);
+
+	p += sprintf(p,
+		     "TC Levels                      : %d\n"
+		     "Unique TC(s)                   : %d\n",
+		     vm_info_1.pal_vm_info_1_s.num_tc_levels,
+		     vm_info_1.pal_vm_info_1_s.max_unique_tcs);
 
 	for(i=0; i < vm_info_1.pal_vm_info_1_s.num_tc_levels; i++) {
 		for (j=2; j>0 ; j--) {
@@ -379,15 +380,14 @@
 				continue;
 			}
 
-			p += sprintf(p, "\n%s Translation Cache Level %d:\n" \
-					"\tHash sets           : %d\n" \
-					"\tAssociativity       : %d\n" \
-					"\tNumber of entries   : %d\n" \
-					"\tFlags               : ",
-					cache_types[j+tc_info.tc_unified], i+1,
-					tc_info.tc_num_sets,
-					tc_info.tc_associativity,
-					tc_info.tc_num_entries);
+			p += sprintf(p,
+				     "\n%s Translation Cache Level %d:\n"
+				     "\tHash sets           : %d\n"
+				     "\tAssociativity       : %d\n"
+				     "\tNumber of entries   : %d\n"
+				     "\tFlags               : ",
+				     cache_types[j+tc_info.tc_unified], i+1, tc_info.tc_num_sets,
+				     tc_info.tc_associativity, tc_info.tc_num_entries);
 
 			if (tc_info.tc_pf) p += sprintf(p, "PreferredPageSizeOptimized ");
 			if (tc_info.tc_unified) p += sprintf(p, "Unified ");
@@ -436,17 +436,18 @@
 
 	if (ia64_pal_rse_info(&phys_stacked, &hints) != 0) return 0;
 
-	p += sprintf(p, "RSE stacked physical registers   : %ld\n" \
-			"RSE load/store hints             : %ld (%s)\n",
-			phys_stacked,
-			hints.ph_data,
-			hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)");
-
-	if (ia64_pal_debug_info(&iregs, &dregs)) return 0;
-
-	p += sprintf(p, "Instruction debug register pairs : %ld\n" \
-			"Data debug register pairs        : %ld\n",
-			iregs, dregs);
+	p += sprintf(p,
+		     "RSE stacked physical registers   : %ld\n"
+		     "RSE load/store hints             : %ld (%s)\n",
+		     phys_stacked, hints.ph_data,
+		     hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)");
+
+	if (ia64_pal_debug_info(&iregs, &dregs))
+		return 0;
+
+	p += sprintf(p,
+		     "Instruction debug register pairs : %ld\n"
+		     "Data debug register pairs        : %ld\n", iregs, dregs);
 
 	return p - page;
 }
@@ -563,26 +564,21 @@
 	 */
 	if (ia64_pal_version(&min_ver, &cur_ver) != 0) return 0;
 
-	p += sprintf(p, "PAL_vendor : 0x%02x (min=0x%02x)\n" \
-			"PAL_A      : %x.%x.%x (min=%x.%x.%x)\n" \
-			"PAL_B      : %x.%x.%x (min=%x.%x.%x)\n",
-			cur_ver.pal_version_s.pv_pal_vendor,
-			min_ver.pal_version_s.pv_pal_vendor,
-
-			cur_ver.pal_version_s.pv_pal_a_model>>4,
-			cur_ver.pal_version_s.pv_pal_a_model&0xf,
-			cur_ver.pal_version_s.pv_pal_a_rev,
-			min_ver.pal_version_s.pv_pal_a_model>>4,
-			min_ver.pal_version_s.pv_pal_a_model&0xf,
-			min_ver.pal_version_s.pv_pal_a_rev,
-
-			cur_ver.pal_version_s.pv_pal_b_model>>4,
-			cur_ver.pal_version_s.pv_pal_b_model&0xf,
-			cur_ver.pal_version_s.pv_pal_b_rev,
-			min_ver.pal_version_s.pv_pal_b_model>>4,
-			min_ver.pal_version_s.pv_pal_b_model&0xf,
-			min_ver.pal_version_s.pv_pal_b_rev);
-
+	p += sprintf(p,
+		     "PAL_vendor : 0x%02x (min=0x%02x)\n"
+		     "PAL_A      : %x.%x.%x (min=%x.%x.%x)\n"
+		     "PAL_B      : %x.%x.%x (min=%x.%x.%x)\n",
+		     cur_ver.pal_version_s.pv_pal_vendor, min_ver.pal_version_s.pv_pal_vendor,
+
+		     cur_ver.pal_version_s.pv_pal_a_model>>4,
+		     cur_ver.pal_version_s.pv_pal_a_model&0xf, cur_ver.pal_version_s.pv_pal_a_rev,
+		     min_ver.pal_version_s.pv_pal_a_model>>4,
+		     min_ver.pal_version_s.pv_pal_a_model&0xf, min_ver.pal_version_s.pv_pal_a_rev,
+
+		     cur_ver.pal_version_s.pv_pal_b_model>>4,
+		     cur_ver.pal_version_s.pv_pal_b_model&0xf, cur_ver.pal_version_s.pv_pal_b_rev,
+		     min_ver.pal_version_s.pv_pal_b_model>>4,
+		     min_ver.pal_version_s.pv_pal_b_model&0xf, min_ver.pal_version_s.pv_pal_b_rev);
 	return p - page;
 }
 
@@ -595,26 +591,20 @@
 
 	if (ia64_pal_perf_mon_info(pm_buffer, &pm_info) != 0) return 0;
 
-	p += sprintf(p, "PMC/PMD pairs                 : %d\n" \
-			"Counter width                 : %d bits\n" \
-			"Cycle event number            : %d\n" \
-			"Retired event number          : %d\n" \
-			"Implemented PMC               : ",
-			pm_info.pal_perf_mon_info_s.generic,
-			pm_info.pal_perf_mon_info_s.width,
-			pm_info.pal_perf_mon_info_s.cycles,
-			pm_info.pal_perf_mon_info_s.retired);
+	p += sprintf(p,
+		     "PMC/PMD pairs                 : %d\n"
+		     "Counter width                 : %d bits\n"
+		     "Cycle event number            : %d\n"
+		     "Retired event number          : %d\n"
+		     "Implemented PMC               : ",
+		     pm_info.pal_perf_mon_info_s.generic, pm_info.pal_perf_mon_info_s.width,
+		     pm_info.pal_perf_mon_info_s.cycles, pm_info.pal_perf_mon_info_s.retired);
 
 	p = bitregister_process(p, pm_buffer, 256);
-
 	p += sprintf(p, "\nImplemented PMD               : ");
-
 	p = bitregister_process(p, pm_buffer+4, 256);
-
 	p += sprintf(p, "\nCycles count capable          : ");
-
 	p = bitregister_process(p, pm_buffer+8, 256);
-
 	p += sprintf(p, "\nRetired bundles count capable : ");
 
 #ifdef CONFIG_ITANIUM
@@ -646,12 +636,11 @@
 
 	if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0;
 
-	p += sprintf(p, "Processor/Clock ratio   : %ld/%ld\n" \
-			"Bus/Clock ratio         : %ld/%ld\n" \
-			"ITC/Clock ratio         : %ld/%ld\n",
-			proc.num, proc.den,
-			bus.num, bus.den,
-			itc.num, itc.den);
+	p += sprintf(p,
+		     "Processor/Clock ratio   : %ld/%ld\n"
+		     "Bus/Clock ratio         : %ld/%ld\n"
+		     "ITC/Clock ratio         : %ld/%ld\n",
+		     proc.num, proc.den, bus.num, bus.den, itc.num, itc.den);
 
 	return p - page;
 }
@@ -665,7 +654,7 @@
 	u64 tr_buffer[4];
 	pal_vm_info_1_u_t vm_info_1;
 	pal_vm_info_2_u_t vm_info_2;
-	int i, j;
+	u64 i, j;
 	u64 max[3], pgm;
 	struct ifa_reg {
 		u64 valid:1;
@@ -711,7 +700,7 @@
 
 		status = ia64_pal_tr_read(j, i, tr_buffer, &tr_valid);
 		if (status != 0) {
-			printk(KERN_ERR "palinfo: pal call failed on tr[%d:%d]=%ld\n",
+			printk(KERN_ERR "palinfo: pal call failed on tr[%lu:%lu]=%ld\n",
 			       i, j, status);
 			continue;
 		}
@@ -725,34 +714,29 @@
 		rid_reg  = (struct rid_reg *)&tr_buffer[3];
 
 		pgm	 = -1 << (itir_reg->ps - 12);
-		p += sprintf(p, "%cTR%d: av=%d pv=%d dv=%d mv=%d\n" \
-				"\tppn  : 0x%lx\n" \
-				"\tvpn  : 0x%lx\n" \
-				"\tps   : ",
-
-				"ID"[i],
-				j,
-				tr_valid.pal_tr_valid_s.access_rights_valid,
-				tr_valid.pal_tr_valid_s.priv_level_valid,
-				tr_valid.pal_tr_valid_s.dirty_bit_valid,
-				tr_valid.pal_tr_valid_s.mem_attr_valid,
-				(gr_reg->ppn & pgm)<< 12,
-				(ifa_reg->vpn & pgm)<< 12);
+		p += sprintf(p,
+			     "%cTR%lu: av=%d pv=%d dv=%d mv=%d\n"
+			     "\tppn  : 0x%lx\n"
+			     "\tvpn  : 0x%lx\n"
+			     "\tps   : ",
+			     "ID"[i], j,
+			     tr_valid.pal_tr_valid_s.access_rights_valid,
+			     tr_valid.pal_tr_valid_s.priv_level_valid,
+			     tr_valid.pal_tr_valid_s.dirty_bit_valid,
+			     tr_valid.pal_tr_valid_s.mem_attr_valid,
+			     (gr_reg->ppn & pgm)<< 12, (ifa_reg->vpn & pgm)<< 12);
 
 		p = bitvector_process(p, 1<< itir_reg->ps);
 
-		p += sprintf(p, "\n\tpl   : %d\n" \
-				"\tar   : %d\n" \
-				"\trid  : %x\n" \
-				"\tp    : %d\n" \
-				"\tma   : %d\n" \
-				"\td    : %d\n",
-				gr_reg->pl,
-				gr_reg->ar,
-				rid_reg->rid,
-				gr_reg->p,
-				gr_reg->ma,
-				gr_reg->d);
+		p += sprintf(p,
+			     "\n\tpl   : %d\n"
+			     "\tar   : %d\n"
+			     "\trid  : %x\n"
+			     "\tp    : %d\n"
+			     "\tma   : %d\n"
+			     "\td    : %d\n",
+			     gr_reg->pl, gr_reg->ar, rid_reg->rid, gr_reg->p, gr_reg->ma,
+			     gr_reg->d);
 		}
 	}
 	return p - page;
@@ -776,7 +760,7 @@
 	{ "tr_info",		tr_info, }
 };
 
-#define NR_PALINFO_ENTRIES	(sizeof(palinfo_entries)/sizeof(palinfo_entry_t))
+#define NR_PALINFO_ENTRIES	(int) ARRAY_SIZE(palinfo_entries)
 
 /*
  * this array is used to keep track of the proc entries we create. This is
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/pci.c linux-2.4.23-pre4/arch/ia64/kernel/pci.c
--- linux-2.4.23-pre3/arch/ia64/kernel/pci.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/pci.c	2003-09-12 12:44:34.000000000 -0700
@@ -235,7 +235,7 @@
 }
 
 static u64
-add_io_space (acpi_resource_address64 *addr)
+add_io_space (struct acpi_resource_address64 *addr)
 {
 	u64 offset;
 	int sparse = 0;
@@ -266,10 +266,10 @@
 }
 
 static acpi_status
-count_window (acpi_resource *resource, void *data)
+count_window (struct acpi_resource *resource, void *data)
 {
 	unsigned int *windows = (unsigned int *) data;
-	acpi_resource_address64 addr;
+	struct acpi_resource_address64 addr;
 	acpi_status status;
 
 	status = acpi_resource_to_address64(resource, &addr);
@@ -287,11 +287,11 @@
 };
 
 static acpi_status
-add_window (acpi_resource *res, void *data)
+add_window (struct acpi_resource *res, void *data)
 {
 	struct pci_root_info *info = (struct pci_root_info *) data;
 	struct pci_window *window;
-	acpi_resource_address64 addr;
+	struct acpi_resource_address64 addr;
 	acpi_status status;
 	unsigned long flags, offset = 0;
 	struct resource *root;
@@ -390,9 +390,6 @@
 void __init
 pcibios_init (void)
 {
-	int i = 0;
-	struct pci_controller *controller;
-
 #ifdef CONFIG_IA64_MCA
 	ia64_mca_check_errors();    /* For post-failure MCA error logging */
 #endif
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/perfmon.c linux-2.4.23-pre4/arch/ia64/kernel/perfmon.c
--- linux-2.4.23-pre3/arch/ia64/kernel/perfmon.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/perfmon.c	2003-09-12 12:44:34.000000000 -0700
@@ -447,7 +447,9 @@
  * forward declarations
  */
 static void pfm_reset_pmu(struct task_struct *);
+#ifndef CONFIG_SMP
 static unsigned long pfm_lazy_save_regs (struct task_struct *ta);
+#endif
 
 #if   defined(CONFIG_ITANIUM)
 #include "perfmon_itanium.h"
@@ -472,13 +474,13 @@
 static inline void
 pfm_clear_psr_up(void)
 {
-	__asm__ __volatile__ ("rum psr.up;; srlz.i;;"::: "memory");
+	__asm__ __volatile__ ("rsm psr.up;; srlz.i;;"::: "memory");
 }
 
 static inline void
 pfm_set_psr_up(void)
 {
-	__asm__ __volatile__ ("sum psr.up;; srlz.i;;"::: "memory");
+	__asm__ __volatile__ ("ssm psr.up;; srlz.i;;"::: "memory");
 }
 
 static inline unsigned long
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/process.c linux-2.4.23-pre4/arch/ia64/kernel/process.c
--- linux-2.4.23-pre3/arch/ia64/kernel/process.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/process.c	2003-09-12 12:44:34.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * Architecture-specific setup.
  *
- * Copyright (C) 1998-2002 Hewlett-Packard Co
+ * Copyright (C) 1998-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 #define __KERNEL_SYSCALLS__	/* see <asm/unistd.h> */
@@ -33,15 +33,15 @@
 #include <asm/sn/idle.h>
 #endif
 
-#define print_symbol(fmt, addr)	printk(fmt, "");
+#define print_symbol(fmt, addr)	printk(fmt, "(no symbol)");
 
 void
 ia64_do_show_stack (struct unw_frame_info *info, void *arg)
 {
 	unsigned long ip, sp, bsp;
-	char buf[80];			/* don't make it so big that it overflows the stack! */
+	char buf[128];			/* don't make it so big that it overflows the stack! */
 
-	printk("\nCall Trace: ");
+	printk("\nCall Trace:\n");
 	do {
 		unw_get_ip(info, &ip);
 		if (ip == 0)
@@ -49,19 +49,15 @@
 
 		unw_get_sp(info, &sp);
 		unw_get_bsp(info, &bsp);
-		snprintf(buf, sizeof(buf), " [<%016lx>] %%s\n\t\t\t\tsp=%016lx bsp=%016lx\n",
+		snprintf(buf, sizeof(buf),
+			 " [<%016lx>] %%s\n"
+			 "                                sp=%016lx bsp=%016lx\n",
 			 ip, sp, bsp);
 		print_symbol(buf, ip);
 	} while (unw_unwind(info) >= 0);
 }
 
 void
-show_trace_task (struct task_struct *task)
-{
-	show_stack(task);
-}
-
-void
 show_stack (struct task_struct *task)
 {
 	if (!task)
@@ -75,19 +71,27 @@
 }
 
 void
+show_trace_task (struct task_struct *task)
+{
+	show_stack(task);
+}
+
+void
 show_regs (struct pt_regs *regs)
 {
 	unsigned long ip = regs->cr_iip + ia64_psr(regs)->ri;
 
-	printk("\nPid: %d, comm: %20s\n", current->pid, current->comm);
+	printk("\nPid: %d, CPU %d, comm: %20s\n", current->pid, smp_processor_id(), current->comm);
 	printk("psr : %016lx ifs : %016lx ip  : [<%016lx>]    %s\n",
 	       regs->cr_ipsr, regs->cr_ifs, ip, print_tainted());
+	print_symbol("ip is at %s\n", ip);
 	printk("unat: %016lx pfs : %016lx rsc : %016lx\n",
 	       regs->ar_unat, regs->ar_pfs, regs->ar_rsc);
 	printk("rnat: %016lx bsps: %016lx pr  : %016lx\n",
 	       regs->ar_rnat, regs->ar_bspstore, regs->pr);
 	printk("ldrs: %016lx ccv : %016lx fpsr: %016lx\n",
 	       regs->loadrs, regs->ar_ccv, regs->ar_fpsr);
+	printk("csd : %016lx ssd : %016lx\n", regs->ar_csd, regs->ar_ssd);
 	printk("b0  : %016lx b6  : %016lx b7  : %016lx\n", regs->b0, regs->b6, regs->b7);
 	printk("f6  : %05lx%016lx f7  : %05lx%016lx\n",
 	       regs->f6.u.bits[1], regs->f6.u.bits[0],
@@ -95,6 +99,9 @@
 	printk("f8  : %05lx%016lx f9  : %05lx%016lx\n",
 	       regs->f8.u.bits[1], regs->f8.u.bits[0],
 	       regs->f9.u.bits[1], regs->f9.u.bits[0]);
+	printk("f10 : %05lx%016lx f11 : %05lx%016lx\n",
+	       regs->f10.u.bits[1], regs->f10.u.bits[0],
+	       regs->f11.u.bits[1], regs->f11.u.bits[0]);
 
 	printk("r1  : %016lx r2  : %016lx r3  : %016lx\n", regs->r1, regs->r2, regs->r3);
 	printk("r8  : %016lx r9  : %016lx r10 : %016lx\n", regs->r8, regs->r9, regs->r10);
@@ -124,16 +131,32 @@
 		show_stack(NULL);
 }
 
+/*
+ * We use this if we don't have any better idle routine..
+ */
+void
+default_idle (void)
+{
+#ifdef CONFIG_IA64_PAL_IDLE
+	if (!current->need_resched)
+		safe_halt();
+#endif
+}
+
 void __attribute__((noreturn))
 cpu_idle (void *unused)
 {
-	/* endless idle loop with no priority at all */
 	init_idle();
 	current->nice = 20;
 	current->counter = -100;
 
 
+	/* endless idle loop with no priority at all */
 	while (1) {
+		void (*idle)(void) = pm_idle;
+		if (!idle)
+			idle = default_idle;
+
 #ifdef CONFIG_SMP
 		if (!current->need_resched)
 			min_xtp();
@@ -143,7 +166,7 @@
 #ifdef CONFIG_IA64_SGI_SN
 			snidle();
 #endif
-			continue;
+			(*idle)();
 		}
 
 #ifdef CONFIG_IA64_SGI_SN
@@ -155,8 +178,6 @@
 #endif
 		schedule();
 		check_pgt_cache();
-		if (pm_idle)
-			(*pm_idle)();
 	}
 }
 
@@ -426,6 +447,8 @@
 	dst[52] = pt->ar_pfs;	/* UNW_AR_PFS is == to pt->cr_ifs for interrupt frames */
 	unw_get_ar(info, UNW_AR_LC, &dst[53]);
 	unw_get_ar(info, UNW_AR_EC, &dst[54]);
+	unw_get_ar(info, UNW_AR_CSD, &dst[55]);
+	unw_get_ar(info, UNW_AR_SSD, &dst[56]);
 }
 
 void
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/ptrace.c linux-2.4.23-pre4/arch/ia64/kernel/ptrace.c
--- linux-2.4.23-pre3/arch/ia64/kernel/ptrace.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/ptrace.c	2003-09-12 12:44:34.000000000 -0700
@@ -28,6 +28,8 @@
 #include <asm/perfmon.h>
 #endif
 
+#define offsetof(type,field)    ((unsigned long) &((type *) 0)->field)
+
 /*
  * Bits in the PSR that we allow ptrace() to change:
  *	be, up, ac, mfl, mfh (the user mask; five bits total)
@@ -690,9 +692,12 @@
 		else
 			ia64_flush_fph(child);
 		ptr = (unsigned long *) ((unsigned long) &child->thread.fph + addr);
-	} else if (addr >= PT_F10 && addr < PT_F15 + 16) {
+	} else if ((addr >= PT_F10) && (addr < PT_F11 + 16)) {
+		/* scratch registers untouched by kernel (saved in pt_regs) */
+		ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, f10) + addr - PT_F10);
+	} else if (addr >= PT_F12 && addr < PT_F15 + 16) {
 		/* scratch registers untouched by kernel (saved in switch_stack) */
-		ptr = (unsigned long *) ((long) sw + addr - PT_NAT_BITS);
+		ptr = (unsigned long *) ((long) sw + (addr - PT_NAT_BITS - 32));
 	} else if (addr < PT_AR_LC + 8) {
 		/* preserved state: */
 		unsigned long nat_bits, scratch_unat, dummy = 0;
@@ -828,22 +833,69 @@
 			else
 				return ia64_peek(child, sw, urbs_end, rnat_addr, data);
 
-				   case PT_R1:  case PT_R2:  case PT_R3:
+		      case PT_R1:
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, r1));
+			break;
+		       
+		       case PT_R2:  case PT_R3:
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, r2) + addr - PT_R2);
+			break;
 		      case PT_R8:  case PT_R9:  case PT_R10: case PT_R11:
-		      case PT_R12: case PT_R13: case PT_R14: case PT_R15:
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, r8)+  addr - PT_R8);
+			break;
+		      case PT_R12: case PT_R13: 
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, r12)+  addr - PT_R12);
+			break;
+		      case PT_R14: 
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, r14));
+			break;
+		      case PT_R15:
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, r15));
+			break;
 		      case PT_R16: case PT_R17: case PT_R18: case PT_R19:
 		      case PT_R20: case PT_R21: case PT_R22: case PT_R23:
 		      case PT_R24: case PT_R25: case PT_R26: case PT_R27:
 		      case PT_R28: case PT_R29: case PT_R30: case PT_R31:
-		      case PT_B0:  case PT_B6:  case PT_B7:
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, r16) + addr - PT_R16);
+			break;
+		      case PT_B0:
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, b0));
+			break;
+		      case PT_B6:
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, b6));
+			break;
+		      case PT_B7:
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, b7));
+			break;
 		      case PT_F6:  case PT_F6+8: case PT_F7: case PT_F7+8:
 		      case PT_F8:  case PT_F8+8: case PT_F9: case PT_F9+8:
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, f6) + addr - PT_F6);
+			break;
 		      case PT_AR_BSPSTORE:
-		      case PT_AR_RSC: case PT_AR_UNAT: case PT_AR_PFS:
-		      case PT_AR_CCV: case PT_AR_FPSR: case PT_CR_IIP: case PT_PR:
-			/* scratch register */
-			ptr = (unsigned long *) ((long) pt + addr - PT_CR_IPSR);
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, ar_bspstore));
+			break;
+		      case PT_AR_RSC: 
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, ar_rsc));
+			break;
+		      case PT_AR_UNAT: 
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, ar_unat));
+			break;
+		      case PT_AR_PFS:
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, ar_pfs));
 			break;
+		      case PT_AR_CCV: 
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, ar_ccv));
+			break;
+		      case PT_AR_FPSR: 
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, ar_fpsr));
+			break;
+		      case PT_CR_IIP: 
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, cr_iip));
+			break;
+		      case PT_PR:
+			ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, pr));
+			break;
+			/* scratch register */
 
 		      default:
 			/* disallow accessing anything else... */
@@ -851,6 +903,8 @@
 				addr);
 			return -1;
 		}
+	} else if (addr <= PT_AR_SSD) {
+		ptr = (unsigned long *) ((long) pt + offsetof(struct pt_regs, ar_csd) + addr - PT_AR_CSD);
 	} else {
 		/* access debug registers */
 
@@ -957,7 +1011,8 @@
 
 	/* gr1-gr3 */
 
-	retval |= __copy_to_user(&ppr->gr[1], &pt->r1, sizeof(long) * 3);
+	retval |= __copy_to_user(&ppr->gr[1], &pt->r1, sizeof(long));
+	retval |= __copy_to_user(&ppr->gr[2], &pt->r2, sizeof(long) *2);
 
 	/* gr4-gr7 */
 
@@ -971,7 +1026,9 @@
 
 	/* gr12-gr15 */
 
-	retval |= __copy_to_user(&ppr->gr[12], &pt->r12, sizeof(long) * 4);
+	retval |= __copy_to_user(&ppr->gr[12], &pt->r12, sizeof(long) * 2);
+	retval |= __copy_to_user(&ppr->gr[14], &pt->r14, sizeof(long));
+	retval |= __copy_to_user(&ppr->gr[15], &pt->r15, sizeof(long));
 
 	/* gr16-gr31 */
 
@@ -999,13 +1056,13 @@
 		retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 0);
 	}
 
-	/* fr6-fr9 */
+	/* fr6-fr11 */
 
-	retval |= __copy_to_user(&ppr->fr[6], &pt->f6, sizeof(struct ia64_fpreg) * 4);
+	retval |= __copy_to_user(&ppr->fr[6], &pt->f6, sizeof(struct ia64_fpreg) * 6);
 
-	/* fp scratch regs(10-15) */
+	/* fp scratch regs(12-15) */
 
-	retval |= __copy_to_user(&ppr->fr[10], &sw->f10, sizeof(struct ia64_fpreg) * 6);
+	retval |= __copy_to_user(&ppr->fr[12], &sw->f12, sizeof(struct ia64_fpreg) * 4);
 
 	/* fr16-fr31 */
 
@@ -1082,7 +1139,8 @@
 
 	/* gr1-gr3 */
 
-	retval |= __copy_from_user(&pt->r1, &ppr->gr[1], sizeof(long) * 3);
+	retval |= __copy_from_user(&pt->r1, &ppr->gr[1], sizeof(long));
+	retval |= __copy_from_user(&pt->r2, &ppr->gr[2], sizeof(long) * 2);
 
 	/* gr4-gr7 */
 
@@ -1100,7 +1158,9 @@
 
 	/* gr12-gr15 */
 
-	retval |= __copy_from_user(&pt->r12, &ppr->gr[12], sizeof(long) * 4);
+	retval |= __copy_from_user(&pt->r12, &ppr->gr[12], sizeof(long) * 2);
+	retval |= __copy_from_user(&pt->r14, &ppr->gr[14], sizeof(long));
+	retval |= __copy_from_user(&pt->r15, &ppr->gr[15], sizeof(long));
 
 	/* gr16-gr31 */
 
@@ -1128,13 +1188,13 @@
 		retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 1);
 	}
 
-	/* fr6-fr9 */
+	/* fr6-fr11 */
 
-	retval |= __copy_from_user(&pt->f6, &ppr->fr[6], sizeof(ppr->fr[6]) * 4);
+	retval |= __copy_from_user(&pt->f6, &ppr->fr[6], sizeof(ppr->fr[6]) * 6);
 
-	/* fp scratch regs(10-15) */
+	/* fp scratch regs(12-15) */
 
-	retval |= __copy_from_user(&sw->f10, &ppr->fr[10], sizeof(ppr->fr[10]) * 6);
+	retval |= __copy_from_user(&sw->f12, &ppr->fr[12], sizeof(ppr->fr[12]) * 4);
 
 	/* fr16-fr31 */
 
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/salinfo.c linux-2.4.23-pre4/arch/ia64/kernel/salinfo.c
--- linux-2.4.23-pre3/arch/ia64/kernel/salinfo.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/salinfo.c	2003-09-12 12:44:34.000000000 -0700
@@ -42,7 +42,7 @@
 	{ "itc_drift",		IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT, },
 };
 
-#define NR_SALINFO_ENTRIES (sizeof(salinfo_entries)/sizeof(salinfo_entry_t))
+#define NR_SALINFO_ENTRIES ARRAY_SIZE(salinfo_entries)
 
 static char *salinfo_log_name[] = {
 	"mca",
@@ -98,9 +98,6 @@
 static int
 salinfo_event_open(struct inode *inode, struct file *file)
 {
-	struct proc_dir_entry *entry = (struct proc_dir_entry *) inode->u.generic_ip;
-	struct salinfo_event *event = entry->data;
-
 	if (!suser())
 		return -EPERM;
 	return 0;
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/setup.c linux-2.4.23-pre4/arch/ia64/kernel/setup.c
--- linux-2.4.23-pre3/arch/ia64/kernel/setup.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/setup.c	2003-09-12 12:44:34.000000000 -0700
@@ -32,6 +32,10 @@
 #include <linux/ioport.h>
 #include <linux/efi.h>
 
+#ifdef CONFIG_BLK_DEV_RAM
+# include <linux/blk.h>
+#endif
+
 #include <asm/ia32.h>
 #include <asm/page.h>
 #include <asm/machvec.h>
@@ -39,6 +43,8 @@
 #include <asm/sal.h>
 #include <asm/system.h>
 #include <asm/mca.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
 #include <asm/smp.h>
 
 #ifdef CONFIG_BLK_DEV_RAM
@@ -55,7 +61,7 @@
 extern char _end;
 
 #ifdef CONFIG_NUMA
- struct cpuinfo_ia64 *boot_cpu_data;
+ struct cpuinfo_ia64 *_cpu_data[NR_CPUS];
 #else
  struct cpuinfo_ia64 _cpu_data[NR_CPUS] __attribute__ ((section ("__special_page_section")));
 #endif
@@ -97,6 +103,7 @@
 static struct rsvd_region rsvd_region[IA64_MAX_RSVD_REGIONS + 1];
 static int num_rsvd_regions;
 
+#ifndef CONFIG_DISCONTIGMEM
 static unsigned long bootmap_start; /* physical address where the bootmem map is located */
 
 static int
@@ -109,18 +116,74 @@
 		*max_pfn = pfn;
 	return 0;
 }
+#endif /* !CONFIG_DISCONTIGMEM */
 
 #define IGNORE_PFN0	1	/* XXX fix me: ignore pfn 0 until TLB miss handler is updated... */
 
+#ifdef CONFIG_DISCONTIGMEM
 /*
- * Free available memory based on the primitive map created from
- * the boot parameters. This routine does not assume the incoming
- * segments are sorted.
+ * efi_memmap_walk() knows nothing about layout of memory across nodes. Find
+ * out to which node a block of memory belongs.  Ignore memory that we cannot
+ * identify, and split blocks that run across multiple nodes.
+ *
+ * Take this opportunity to round the start address up and the end address
+ * down to page boundaries.
  */
+void
+call_pernode_memory (unsigned long start, unsigned long end, void *arg)
+{
+	unsigned long rs, re;
+	void (*func)(unsigned long, unsigned long, int);
+	int i;
+
+	start = PAGE_ALIGN(start);
+	end &= PAGE_MASK;
+	if (start >= end)
+		return;
+
+	func = arg;
+
+	if (!num_memblks) {
+		/* this machine doesn't have SRAT, */
+		/* so call func with nid=0, bank=0 */
+		if (start < end)
+			(*func)(start, end, 0);
+		return;
+	}
+
+	for (i = 0; i < num_memblks; i++) {
+		rs = MAX(__pa(start), node_memblk[i].start_paddr);
+		re = MIN(__pa(end), node_memblk[i].start_paddr+node_memblk[i].size);
+
+		if (rs < re)
+			(*func)((unsigned long)__va(rs), (unsigned long)__va(re), node_memblk[i].nid);
+		if ((unsigned long)__va(re) == end)
+			break;
+	}
+}
+
+#else /* CONFIG_DISCONTIGMEM */
+
 static int
 free_available_memory (unsigned long start, unsigned long end, void *arg)
 {
+	free_bootmem(__pa(start), end - start);
+	return 0;
+}
+#endif /* CONFIG_DISCONTIGMEM */
+
+/*
+ * Filter incoming memory segments based on the primitive map created from
+ * the boot parameters. Segments contained in the map are removed from the
+ * memory ranges. A caller-specified function is called with the memory
+ * ranges that remain after filtering.
+ * This routine does not assume the incoming segments are sorted.
+ */
+int
+filter_rsvd_memory (unsigned long start, unsigned long end, void *arg)
+{
 	unsigned long range_start, range_end, prev_start;
+	void (*func)(unsigned long, unsigned long, int);
 	int i;
 
 #if IGNORE_PFN0
@@ -134,13 +197,18 @@
 	 * lowest possible address(walker uses virtual)
 	 */
 	prev_start = PAGE_OFFSET;
+	func = arg;
 
 	for (i = 0; i < num_rsvd_regions; ++i) {
 		range_start = MAX(start, prev_start);
 		range_end   = MIN(end, rsvd_region[i].start);
 
 		if (range_start < range_end)
-			free_bootmem(__pa(range_start), range_end - range_start);
+#ifdef CONFIG_DISCONTIGMEM
+			call_pernode_memory(range_start, range_end, func);
+#else
+			(*func)(range_start, range_end, 0);
+#endif
 
 		/* nothing more available in this segment */
 		if (range_end == end) return 0;
@@ -152,6 +220,7 @@
 }
 
 
+#ifndef CONFIG_DISCONTIGMEM
 /*
  * Find a place to put the bootmap and return its starting address in bootmap_start.
  * This address must be page-aligned.
@@ -190,6 +259,7 @@
 	}
 	return 0;
 }
+#endif /* CONFIG_DISCONTIGMEM */
 
 static void
 sort_regions (struct rsvd_region *rsvd_region, int max)
@@ -233,8 +303,8 @@
 				+ strlen(__va(ia64_boot_param->command_line)) + 1);
 	n++;
 
-	rsvd_region[n].start = KERNEL_START;
-	rsvd_region[n].end   = KERNEL_END;
+	rsvd_region[n].start = ia64_imva(KERNEL_START);
+	rsvd_region[n].end   = ia64_imva(KERNEL_END);
 	n++;
 
 #ifdef CONFIG_BLK_DEV_INITRD
@@ -254,6 +324,14 @@
 
 	sort_regions(rsvd_region, num_rsvd_regions);
 
+#ifdef CONFIG_DISCONTIGMEM
+	{
+		extern void discontig_mem_init(void);
+		bootmap_size = max_pfn = 0;     /* stop gcc warnings */
+		discontig_mem_init();
+	}
+#else /* !CONFIG_DISCONTIGMEM */
+
 	/* first find highest page frame number */
 	max_pfn = 0;
 	efi_memmap_walk(find_max_pfn, &max_pfn);
@@ -270,8 +348,9 @@
 	bootmap_size = init_bootmem(bootmap_start >> PAGE_SHIFT, max_pfn);
 
 	/* Free all available memory, then mark bootmem-map as being in use.  */
-	efi_memmap_walk(free_available_memory, 0);
+	efi_memmap_walk(filter_rsvd_memory, free_available_memory);
 	reserve_bootmem(bootmap_start, bootmap_size);
+#endif /* !CONFIG_DISCONTIGMEM */
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (ia64_boot_param->initrd_start) {
@@ -297,9 +376,22 @@
 	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';		/* for safety */
 
 	efi_init();
+	find_memory();
+
+#ifdef CONFIG_ACPI_BOOT
+	/* Initialize the ACPI boot-time table parser */
+	acpi_table_init();
+
+# ifdef CONFIG_ACPI_NUMA
+	acpi_numa_init();
+# endif
+#else
+# ifdef CONFIG_SMP
+	smp_build_cpu_map();	/* happens, e.g., with the Ski simulator */
+# endif
+#endif /* CONFIG_APCI_BOOT */
 
 	iomem_resource.end = ~0UL;	/* FIXME probably belongs elsewhere */
-	find_memory();
 
 #if 0
 	/* XXX fix me */
@@ -353,7 +445,7 @@
 	cpu_init();	/* initialize the bootstrap CPU */
 
 #ifdef CONFIG_ACPI_BOOT
-	acpi_boot_init(*cmdline_p);
+	acpi_boot_init();
 #endif
 #ifdef CONFIG_SERIAL_HCDP
 	if (efi.hcdp) {
@@ -446,6 +538,8 @@
 		   c->itc_freq / 1000000, c->itc_freq % 1000000,
 		   lpj*HZ/500000, (lpj*HZ/5000) % 100);
 	return 0;
+#undef lpj
+#undef cpu
 }
 
 static void *
@@ -546,7 +640,7 @@
 	unsigned int max_ctx;
 	struct cpuinfo_ia64 *my_cpu_data;
 #ifdef CONFIG_NUMA
-	int cpu, order;
+	int cpu;
 
 	/*
 	 * If NUMA is configured, the cpu_data array is not preallocated. The boot cpu
@@ -555,28 +649,14 @@
 	 * is required because some boot code references all cpu_data structures
 	 * before the cpus are actually started.
 	 */
-	if (!boot_cpu_data) {
-		my_cpu_data = alloc_bootmem_pages_node(NODE_DATA(numa_node_id()),
-						       sizeof(struct cpuinfo_ia64));
-		boot_cpu_data = my_cpu_data;
-		my_cpu_data->cpu_data[0] = my_cpu_data;
-		for (cpu = 1; cpu < NR_CPUS; ++cpu)
-			my_cpu_data->cpu_data[cpu]
-				= alloc_bootmem_pages_node(NODE_DATA(numa_node_id()),
-							   sizeof(struct cpuinfo_ia64));
-		for (cpu = 1; cpu < NR_CPUS; ++cpu)
-			memcpy(my_cpu_data->cpu_data[cpu]->cpu_data,
-			       my_cpu_data->cpu_data, sizeof(my_cpu_data->cpu_data));
-	} else {
-		order = get_order(sizeof(struct cpuinfo_ia64));
-		my_cpu_data = page_address(alloc_pages_node(numa_node_id(), GFP_KERNEL, order));
-		memcpy(my_cpu_data, boot_cpu_data->cpu_data[smp_processor_id()],
-		       sizeof(struct cpuinfo_ia64));
-		__free_pages(virt_to_page(boot_cpu_data->cpu_data[smp_processor_id()]),
-			     order);
-		for (cpu = 0; cpu < NR_CPUS; ++cpu)
-			boot_cpu_data->cpu_data[cpu]->cpu_data[smp_processor_id()] = my_cpu_data;
-	}
+	for (cpu=0; cpu < NR_CPUS; cpu++)
+		if (node_cpuid[cpu].phys_id == hard_smp_processor_id())
+			break;
+	my_cpu_data = _cpu_data[cpu];
+	my_cpu_data->node_data->active_cpu_count++;
+
+	for (cpu=0; cpu<NR_CPUS; cpu++)
+		_cpu_data[cpu]->cpu_data[smp_processor_id()] = my_cpu_data;
 #else
 	my_cpu_data = cpu_data(smp_processor_id());
 #endif
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/signal.c linux-2.4.23-pre4/arch/ia64/kernel/signal.c
--- linux-2.4.23-pre3/arch/ia64/kernel/signal.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/signal.c	2003-09-12 12:44:34.000000000 -0700
@@ -115,18 +115,28 @@
 	err |= __get_user(cfm, &sc->sc_cfm);
 	err |= __get_user(um, &sc->sc_um);			/* user mask */
 	err |= __get_user(scr->pt.ar_rsc, &sc->sc_ar_rsc);
-	err |= __get_user(scr->pt.ar_ccv, &sc->sc_ar_ccv);
 	err |= __get_user(scr->pt.ar_unat, &sc->sc_ar_unat);
 	err |= __get_user(scr->pt.ar_fpsr, &sc->sc_ar_fpsr);
 	err |= __get_user(scr->pt.ar_pfs, &sc->sc_ar_pfs);
 	err |= __get_user(scr->pt.pr, &sc->sc_pr);		/* predicates */
 	err |= __get_user(scr->pt.b0, &sc->sc_br[0]);		/* b0 (rp) */
-	err |= __get_user(scr->pt.b6, &sc->sc_br[6]);		/* b6 */
-	err |= __get_user(scr->pt.b7, &sc->sc_br[7]);		/* b7 */
-	err |= __copy_from_user(&scr->pt.r1, &sc->sc_gr[1], 3*8);	/* r1-r3 */
+	err |= __copy_from_user(&scr->pt.r1, &sc->sc_gr[1], 8);	/* r1 */
 	err |= __copy_from_user(&scr->pt.r8, &sc->sc_gr[8], 4*8);	/* r8-r11 */
-	err |= __copy_from_user(&scr->pt.r12, &sc->sc_gr[12], 4*8);	/* r12-r15 */
-	err |= __copy_from_user(&scr->pt.r16, &sc->sc_gr[16], 16*8);	/* r16-r31 */
+	err |= __copy_from_user(&scr->pt.r12, &sc->sc_gr[12], 2*8);	/* r12-r13 */
+	err |= __copy_from_user(&scr->pt.r15, &sc->sc_gr[15], 8);	/* r15 */
+	
+	if ((flags & IA64_SC_FLAG_IN_SYSCALL)==0)
+	{
+		// Only get user sig context when not in syscall. 
+		err |= __get_user(scr->pt.ar_ccv, &sc->sc_ar_ccv);
+		err |= __get_user(scr->pt.ar_csd, &sc->sc_ar25);	/* ar.csd */
+		err |= __get_user(scr->pt.ar_ssd, &sc->sc_ar26);	/* ar.ssd */
+		err |= __get_user(scr->pt.b6, &sc->sc_br[6]);		/* b6 */
+		err |= __get_user(scr->pt.b7, &sc->sc_br[7]);		/* b7 */
+		err |= __copy_from_user(&scr->pt.r2, &sc->sc_gr[2], 2*8);	/* r2-r3 */
+		err |= __copy_from_user(&scr->pt.r14, &sc->sc_gr[14], 8);	/* r14 */
+		err |= __copy_from_user(&scr->pt.r16, &sc->sc_gr[16], 16*8);	/* r16-r31 */
+	}
 
 	scr->pt.cr_ifs = cfm | (1UL << 63);
 
@@ -354,21 +364,42 @@
 	err |= __put_user(cfm, &sc->sc_cfm);
 	err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um);
 	err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc);
-	err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv);
 	err |= __put_user(scr->pt.ar_unat, &sc->sc_ar_unat);		/* ar.unat */
 	err |= __put_user(scr->pt.ar_fpsr, &sc->sc_ar_fpsr);		/* ar.fpsr */
 	err |= __put_user(scr->pt.ar_pfs, &sc->sc_ar_pfs);
 	err |= __put_user(scr->pt.pr, &sc->sc_pr);			/* predicates */
 	err |= __put_user(scr->pt.b0, &sc->sc_br[0]);			/* b0 (rp) */
-	err |= __put_user(scr->pt.b6, &sc->sc_br[6]);			/* b6 */
-	err |= __put_user(scr->pt.b7, &sc->sc_br[7]);			/* b7 */
-
-	err |= __copy_to_user(&sc->sc_gr[1], &scr->pt.r1, 3*8);		/* r1-r3 */
+	err |= __copy_to_user(&sc->sc_gr[1], &scr->pt.r1, 8);		/* r1 */
 	err |= __copy_to_user(&sc->sc_gr[8], &scr->pt.r8, 4*8);		/* r8-r11 */
-	err |= __copy_to_user(&sc->sc_gr[12], &scr->pt.r12, 4*8);	/* r12-r15 */
-	err |= __copy_to_user(&sc->sc_gr[16], &scr->pt.r16, 16*8);	/* r16-r31 */
-
+	err |= __copy_to_user(&sc->sc_gr[12], &scr->pt.r12, 2*8);	/* r12-r13 */
+	err |= __copy_to_user(&sc->sc_gr[15], &scr->pt.r15, 8);		/* r15 */
 	err |= __put_user(scr->pt.cr_iip + ia64_psr(&scr->pt)->ri, &sc->sc_ip);
+
+	if (flags & IA64_SC_FLAG_IN_SYSCALL)
+	{
+		// Clear scratch registers in sig context for asynchronized signal.
+		err |= __clear_user(&sc->sc_ar_ccv, 8);
+		err |= __clear_user(&sc->sc_ar25,8);				/* ar.csd */
+		err |= __clear_user(&sc->sc_ar26,8);				/* ar.ssd */
+		err |= __clear_user(&sc->sc_br[6],8);				/* b6 */
+		err |= __clear_user(&sc->sc_br[7],8);				/* b7 */
+
+		err |= __clear_user(&sc->sc_gr[2], 2*8);			/* r2-r3 */
+		err |= __clear_user(&sc->sc_gr[14],8);				/* r14 */
+		err |= __clear_user(&sc->sc_gr[16],16*8);			/* r16-r31 */
+	} else
+	{
+		// Copy scratch registers in sig context from pt_regs for synchronized signal.
+		err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv);
+		err |= __put_user(scr->pt.ar_csd, &sc->sc_ar25);		/* ar.csd */
+		err |= __put_user(scr->pt.ar_ssd, &sc->sc_ar26);		/* ar.ssd */
+		err |= __put_user(scr->pt.b6, &sc->sc_br[6]);			/* b6 */
+		err |= __put_user(scr->pt.b7, &sc->sc_br[7]);			/* b7 */
+
+		err |= __copy_to_user(&sc->sc_gr[2], &scr->pt.r2, 2*8);		/* r2-r3 */
+		err |= __copy_to_user(&sc->sc_gr[14], &scr->pt.r14, 8);		/* r14 */
+		err |= __copy_to_user(&sc->sc_gr[16], &scr->pt.r16, 16*8);	/* r16-r31 */
+	}
 	return err;
 }
 
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/smpboot.c linux-2.4.23-pre4/arch/ia64/kernel/smpboot.c
--- linux-2.4.23-pre3/arch/ia64/kernel/smpboot.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/smpboot.c	2003-09-12 12:44:34.000000000 -0700
@@ -320,6 +320,7 @@
 {
 	int cpuid, phys_id;
 	extern void ia64_init_itm(void);
+	extern void ia64_cpu_local_tick(void);
 
 #ifdef CONFIG_PERFMON
 	extern void pfm_init_percpu(void);
@@ -576,7 +577,7 @@
 	/* Tell SAL where to drop the AP's.  */
 	ap_startup = (struct fptr *) start_ap;
 	sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ,
-				       __pa(ap_startup->fp), __pa(ap_startup->gp), 0, 0, 0, 0);
+				      ia64_tpa(ap_startup->fp), ia64_tpa(ap_startup->gp), 0, 0, 0, 0);
 	if (sal_ret < 0) {
 		printk(KERN_ERR "SMP: Can't set SAL AP Boot Rendezvous: %s\n     Forcing UP mode\n",
 		       ia64_sal_strerror(sal_ret));
@@ -584,3 +585,27 @@
 		smp_num_cpus = 1;
 	}
 }
+
+/*
+ * Initialize the logical CPU number to SAPICID mapping
+ */
+void __init
+smp_build_cpu_map (void)
+{
+	int sapicid, cpu, i;
+	int boot_cpu_id = hard_smp_processor_id();
+
+	for (cpu = 0; cpu < NR_CPUS; cpu++)
+		ia64_cpu_to_sapicid[cpu] = -1;
+
+	ia64_cpu_to_sapicid[0] = boot_cpu_id;
+
+	for (cpu = 1, i = 0; i < smp_boot_data.cpu_count; i++) {
+		sapicid = smp_boot_data.cpu_phys_id[i];
+		if (sapicid == boot_cpu_id)
+			continue;
+		ia64_cpu_to_sapicid[cpu] = sapicid;
+		cpu++;
+	}
+}
+
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/traps.c linux-2.4.23-pre4/arch/ia64/kernel/traps.c
--- linux-2.4.23-pre3/arch/ia64/kernel/traps.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/traps.c	2003-09-12 12:44:34.000000000 -0700
@@ -273,7 +273,6 @@
 fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long *pr, long *ifs,
 	    struct pt_regs *regs)
 {
-	struct ia64_fpreg f6_11[6];
 	fp_state_t fp_state;
 	fpswa_ret_t ret;
 
@@ -288,11 +287,8 @@
 	 * pointer to point to these registers.
 	 */
 	fp_state.bitmask_low64 = 0xfc0;  /* bit6..bit11 */
-	f6_11[0] = regs->f6; f6_11[1] = regs->f7;
-	f6_11[2] = regs->f8; f6_11[3] = regs->f9;
-	__asm__ ("stf.spill %0=f10%P0" : "=m"(f6_11[4]));
-	__asm__ ("stf.spill %0=f11%P0" : "=m"(f6_11[5]));
-	fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) f6_11;
+
+	fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) &regs->f6;
 	/*
 	 * unsigned long (*EFI_FPSWA) (
 	 *      unsigned long    trap_type,
@@ -308,10 +304,7 @@
 					(unsigned long *) ipsr, (unsigned long *) fpsr,
 					(unsigned long *) isr, (unsigned long *) pr,
 					(unsigned long *) ifs, &fp_state);
-	regs->f6 = f6_11[0]; regs->f7 = f6_11[1];
-	regs->f8 = f6_11[2]; regs->f9 = f6_11[3];
-	__asm__ ("ldf.fill f10=%0%P0" :: "m"(f6_11[4]));
-	__asm__ ("ldf.fill f11=%0%P0" :: "m"(f6_11[5]));
+
 	return ret.status;
 }
 
@@ -335,8 +328,9 @@
 
 	if (jiffies - last_time > 5*HZ)
 		fpu_swa_count = 0;
-	if ((++fpu_swa_count < 5) && !(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
+	if ((fpu_swa_count < 4) && !(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
 		last_time = jiffies;
+		++fpu_swa_count;
 		printk(KERN_WARNING "%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
 		       current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr);
 	}
@@ -361,6 +355,10 @@
 			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
 			if (isr & 0x11) {
 				siginfo.si_code = FPE_FLTINV;
+			} else if (isr & 0x22) {
+				/* denormal operand gets the same si_code as underflow 
+				* see arch/i386/kernel/traps.c:math_error()  */
+				siginfo.si_code = FPE_FLTUND;
 			} else if (isr & 0x44) {
 				siginfo.si_code = FPE_FLTDIV;
 			}
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/unaligned.c linux-2.4.23-pre4/arch/ia64/kernel/unaligned.c
--- linux-2.4.23-pre3/arch/ia64/kernel/unaligned.c	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/unaligned.c	2003-09-12 12:44:34.000000000 -0700
@@ -217,8 +217,9 @@
 	RSW(f2), RSW(f3), RSW(f4), RSW(f5),
 
 	RPT(f6), RPT(f7), RPT(f8), RPT(f9),
+	RPT(f10), RPT(f11),
 
-	RSW(f10), RSW(f11), RSW(f12), RSW(f13), RSW(f14),
+	RSW(f12), RSW(f13), RSW(f14),
 	RSW(f15), RSW(f16), RSW(f17), RSW(f18), RSW(f19),
 	RSW(f20), RSW(f21), RSW(f22), RSW(f23), RSW(f24),
 	RSW(f25), RSW(f26), RSW(f27), RSW(f28), RSW(f29),
diff -urN linux-2.4.23-pre3/arch/ia64/kernel/unwind.c linux-2.4.23-pre4/arch/ia64/kernel/unwind.c
--- linux-2.4.23-pre3/arch/ia64/kernel/unwind.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/kernel/unwind.c	2003-09-12 12:44:34.000000000 -0700
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2003 Fenghua Yu <fenghua.yu@intel.com>
+ * 	- Change pt_regs_off() to make it less dependant on pt_regs structure.
+ *
  * Copyright (C) 1999-2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
@@ -209,7 +212,11 @@
 #endif
 };
 
-
+#define OFF_CASE(reg, reg_num) 					\
+	case reg:						\
+		off=struct_offset(struct pt_regs, reg_num);	\
+		break;
+
 /* Unwind accessors.  */
 
 /*
@@ -220,16 +227,40 @@
 {
 	unsigned long off =0;
 
-	if (reg >= 1 && reg <= 3)
-		off = struct_offset(struct pt_regs, r1) + 8*(reg - 1);
-	else if (reg <= 11)
-		off = struct_offset(struct pt_regs, r8) + 8*(reg - 8);
-	else if (reg <= 15)
-		off = struct_offset(struct pt_regs, r12) + 8*(reg - 12);
-	else if (reg <= 31)
-		off = struct_offset(struct pt_regs, r16) + 8*(reg - 16);
-	else
-		UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg);
+	switch (reg)
+	{
+		OFF_CASE(1,r1)
+		OFF_CASE(2,r2)
+		OFF_CASE(3,r3)
+		OFF_CASE(8,r8)
+		OFF_CASE(9,r9)
+		OFF_CASE(10,r10)
+		OFF_CASE(11,r11)
+		OFF_CASE(12,r12)
+		OFF_CASE(13,r13)
+		OFF_CASE(14,r14)
+		OFF_CASE(15,r15)
+		OFF_CASE(16,r16)
+		OFF_CASE(17,r17)
+		OFF_CASE(18,r18)
+		OFF_CASE(19,r19)
+		OFF_CASE(20,r20)
+		OFF_CASE(21,r21)
+		OFF_CASE(22,r22)
+		OFF_CASE(23,r23)
+		OFF_CASE(24,r24)
+		OFF_CASE(25,r25)
+		OFF_CASE(26,r26)
+		OFF_CASE(27,r27)
+		OFF_CASE(28,r28)
+		OFF_CASE(29,r29)
+		OFF_CASE(30,r30)
+		OFF_CASE(31,r31)
+		default:
+			UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg);
+			break;
+	}
+
 	return off;
 }
 
@@ -416,12 +447,12 @@
 		if (!addr)
 			addr = &info->sw->f2 + (regnum - 2);
 	} else if (regnum <= 15) {
-		if (regnum <= 9) {
+		if (regnum <= 11) {
 			pt = get_scratch_regs(info);
 			addr = &pt->f6  + (regnum - 6);
 		}
 		else
-			addr = &info->sw->f10 + (regnum - 10);
+			addr = &info->sw->f12 + (regnum - 12);
 	} else if (regnum <= 31) {
 		addr = info->fr_loc[regnum - 16];
 		if (!addr)
@@ -512,6 +543,16 @@
 		addr = &pt->ar_ccv;
 		break;
 
+	      case UNW_AR_CSD:
+		pt = get_scratch_regs(info);
+		addr = &pt->ar_csd;
+		break;
+
+	      case UNW_AR_SSD:
+		pt = get_scratch_regs(info);
+		addr = &pt->ar_ssd;
+		break;
+
 	      default:
 		UNW_DPRINT(0, "unwind.%s: trying to access non-existent ar%u\n",
 			   __FUNCTION__, regnum);
@@ -685,7 +726,7 @@
 	 * First, resolve implicit register save locations (see Section "11.4.2.3 Rules
 	 * for Using Unwind Descriptors", rule 3):
 	 */
-	for (i = 0; i < (int) sizeof(unw.save_order)/sizeof(unw.save_order[0]); ++i) {
+	for (i = 0; i < (int) ARRAY_SIZE(unw.save_order); ++i) {
 		reg = sr->curr.reg + unw.save_order[i];
 		if (reg->where == UNW_WHERE_GR_SAVE) {
 			reg->where = UNW_WHERE_GR;
@@ -701,7 +742,7 @@
 	 */
 	if (sr->imask) {
 		unsigned char kind, mask = 0, *cp = sr->imask;
-		unsigned long t;
+		int t;
 		static const unsigned char limit[3] = {
 			UNW_REG_F31, UNW_REG_R7, UNW_REG_B5
 		};
@@ -1379,7 +1420,7 @@
 			val = unw.preg_index[UNW_REG_F16 + (rval - 16)];
 		else {
 			opc = UNW_INSN_MOVE_SCRATCH;
-			if (rval <= 9)
+			if (rval <= 11)
 				val = struct_offset(struct pt_regs, f6) + 16*(rval - 6);
 			else
 				UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n",
@@ -1731,8 +1772,7 @@
   lazy_init:
 	off = unw.sw_off[val];
 	s[val] = (unsigned long) state->sw + off;
-	if (off >= struct_offset(struct switch_stack, r4)
-	    && off <= struct_offset(struct switch_stack, r7))
+	if (off >= struct_offset(struct switch_stack, r4) && off <= struct_offset(struct switch_stack, r7))
 		/*
 		 * We're initializing a general register: init NaT info, too.  Note that
 		 * the offset is a multiple of 8 which gives us the 3 bits needed for
@@ -1934,7 +1974,7 @@
 		   "  pr     0x%lx\n"
 		   "  sw     0x%lx\n"
 		   "  sp     0x%lx\n",
-		   __FUNCTION__, (unsigned long) task, rbslimit, rbstop, stktop, stklimit,
+		   __FUNCTION__, (unsigned long) t, rbslimit, rbstop, stktop, stklimit,
 		   info->pr, (unsigned long) info->sw, info->sp);
 	STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags));
 }
@@ -1955,7 +1995,7 @@
 		   "  bsp    0x%lx\n"
 		   "  sof    0x%lx\n"
 		   "  ip     0x%lx\n",
-		   info->bsp, sof, info->ip);
+		   __FUNCTION__, info->bsp, sof, info->ip);
 	find_save_locs(info);
 }
 
@@ -1973,7 +2013,7 @@
 		   "  bsp    0x%lx\n"
 		   "  sol    0x%lx\n"
 		   "  ip     0x%lx\n",
-		   info->bsp, sol, info->ip);
+		   __FUNCTION__, info->bsp, sol, info->ip);
 	find_save_locs(info);
 }
 
diff -urN linux-2.4.23-pre3/arch/ia64/lib/idiv64.S linux-2.4.23-pre4/arch/ia64/lib/idiv64.S
--- linux-2.4.23-pre3/arch/ia64/lib/idiv64.S	2001-11-09 14:26:17.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/lib/idiv64.S	2003-09-12 12:44:34.000000000 -0700
@@ -37,57 +37,44 @@
 #define NAME		PASTE(PASTE(__,SGN),PASTE(OP,di3))
 
 GLOBAL_ENTRY(NAME)
-	.prologue
 	.regstk 2,0,0,0
 	// Transfer inputs to FP registers.
 	setf.sig f8 = in0
 	setf.sig f9 = in1
 	;;
-	.fframe 16
-	.save.f 0x20
-	stf.spill [sp] = f17,-16
-
 	// Convert the inputs to FP, to avoid FP software-assist faults.
 	INT_TO_FP(f8, f8)
-	;;
-
-	.save.f 0x10
-	stf.spill [sp] = f16
-	.body
 	INT_TO_FP(f9, f9)
 	;;
-	frcpa.s1 f17, p6 = f8, f9	// y0 = frcpa(b)
+	frcpa.s1 f11, p6 = f8, f9	// y0 = frcpa(b)
 	;;
-(p6)	fmpy.s1 f7 = f8, f17		// q0 = a*y0
-(p6)	fnma.s1 f6 = f9, f17, f1	// e0 = -b*y0 + 1
+(p6)	fmpy.s1 f7 = f8, f11		// q0 = a*y0
+(p6)	fnma.s1 f6 = f9, f11, f1	// e0 = -b*y0 + 1
 	;;
-(p6)	fma.s1 f16 = f7, f6, f7		// q1 = q0*e0 + q0
+(p6)	fma.s1 f10 = f7, f6, f7		// q1 = q0*e0 + q0
 (p6)	fmpy.s1 f7 = f6, f6		// e1 = e0*e0
 	;;
 #ifdef MODULO
 	sub in1 = r0, in1		// in1 = -b
 #endif
-(p6)	fma.s1 f16 = f16, f7, f16	// q2 = q1*e1 + q1
-(p6)	fma.s1 f6 = f17, f6, f17	// y1 = y0*e0 + y0
+(p6)	fma.s1 f10 = f10, f7, f10	// q2 = q1*e1 + q1
+(p6)	fma.s1 f6 = f11, f6, f11	// y1 = y0*e0 + y0
 	;;
 (p6)	fma.s1 f6 = f6, f7, f6		// y2 = y1*e1 + y1
-(p6)	fnma.s1 f7 = f9, f16, f8	// r = -b*q2 + a
+(p6)	fnma.s1 f7 = f9, f10, f8	// r = -b*q2 + a
 	;;
 #ifdef MODULO
 	setf.sig f8 = in0		// f8 = a
 	setf.sig f9 = in1		// f9 = -b
 #endif
-(p6)	fma.s1 f17 = f7, f6, f16	// q3 = r*y2 + q2
+(p6)	fma.s1 f11 = f7, f6, f10	// q3 = r*y2 + q2
 	;;
-	.restore sp
-	ldf.fill f16 = [sp], 16
-	FP_TO_INT(f17, f17)		// q = trunc(q3)
+	FP_TO_INT(f11, f11)		// q = trunc(q3)
 	;;
 #ifdef MODULO
-	xma.l f17 = f17, f9, f8		// r = q*(-b) + a
+	xma.l f11 = f11, f9, f8		// r = q*(-b) + a
 	;;
 #endif
-	getf.sig r8 = f17		// transfer result to result register
-	ldf.fill f17 = [sp]
+	getf.sig r8 = f11		// transfer result to result register
 	br.ret.sptk.many rp
 END(NAME)
diff -urN linux-2.4.23-pre3/arch/ia64/mm/Makefile linux-2.4.23-pre4/arch/ia64/mm/Makefile
--- linux-2.4.23-pre3/arch/ia64/mm/Makefile	2003-06-13 07:51:29.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/mm/Makefile	2003-09-12 12:44:34.000000000 -0700
@@ -12,5 +12,7 @@
 export-objs := init.o
 
 obj-y	 := init.o fault.o tlb.o extable.o
+obj-$(CONFIG_NUMA) += numa.o
+obj-$(CONFIG_DISCONTIGMEM) += discontig.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.23-pre3/arch/ia64/mm/discontig.c linux-2.4.23-pre4/arch/ia64/mm/discontig.c
--- linux-2.4.23-pre3/arch/ia64/mm/discontig.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/mm/discontig.c	2003-09-12 12:44:34.000000000 -0700
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2000, 2003 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2001 Intel Corp.
+ * Copyright (c) 2001 Tony Luck <tony.luck@intel.com>
+ * Copyright (c) 2002 NEC Corp.
+ * Copyright (c) 2002 Kimio Suganuma <k-suganuma@da.jp.nec.com>
+ */
+
+/*
+ * Platform initialization for Discontig Memory
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/mmzone.h>
+#include <linux/acpi.h>
+#include <linux/efi.h>
+#include <asm/pgalloc.h>
+#include <asm/tlb.h>
+
+
+/*
+ * Round an address upward to the next multiple of GRANULE size.
+ */
+#define GRANULEROUNDDOWN(n) ((n) & ~(IA64_GRANULE_SIZE-1))
+#define GRANULEROUNDUP(n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1))
+
+/*
+ * Used to locate BOOT_DATA prior to initializing the node data area.
+ */
+#define BOOT_NODE_DATA(node)	pg_data_ptr[node]
+
+/*
+ * To prevent cache aliasing effects, align per-node structures so that they 
+ * start at addresses that are strided by node number.
+ */
+#define NODEDATA_ALIGN(addr, node)	((((addr) + 1024*1024-1) & ~(1024*1024-1)) + (node)*PAGE_SIZE)
+
+
+static struct ia64_node_data	*boot_node_data[NR_NODES] __initdata;
+static pg_data_t		*pg_data_ptr[NR_NODES] __initdata;
+static bootmem_data_t		bdata[NR_NODES] __initdata;
+static unsigned long		boot_pernode[NR_NODES] __initdata;
+static unsigned long		boot_pernodesize[NR_NODES] __initdata;
+
+extern int  filter_rsvd_memory (unsigned long start, unsigned long end, void *arg);
+extern struct cpuinfo_ia64 *_cpu_data[NR_CPUS];
+
+
+
+/*
+ * We allocate one of the bootmem_data_t structs for each piece of memory
+ * that we wish to treat as a contiguous block.  Each such block must start
+ * on a GRANULE boundary.  Multiple banks per node is not supported.
+ *   (Note: on SN2, all memory on a node is trated as a single bank.
+ *   Holes within the bank are supported. This works because memory
+ *   from different banks is not interleaved. The bootmap bitmap
+ *   for the node is somewhat large but not too large).
+ */
+static int __init
+build_maps(unsigned long start, unsigned long end, int node)
+{
+	bootmem_data_t	*bdp;
+	unsigned long cstart, epfn;
+
+	bdp = &bdata[node];
+	epfn = GRANULEROUNDUP(__pa(end)) >> PAGE_SHIFT;
+	cstart = GRANULEROUNDDOWN(__pa(start));
+
+	if (!bdp->node_low_pfn) {
+		bdp->node_boot_start = cstart;
+		bdp->node_low_pfn = epfn;
+	} else {
+		bdp->node_boot_start = min(cstart, bdp->node_boot_start);
+		bdp->node_low_pfn = max(epfn, bdp->node_low_pfn);
+	}
+
+	min_low_pfn = min(min_low_pfn, bdp->node_boot_start>>PAGE_SHIFT);
+	max_low_pfn = max(max_low_pfn, bdp->node_low_pfn);
+
+	return 0;
+}
+
+
+/*
+ * Count the number of cpus on the node
+ */
+static __inline__ int
+count_cpus(int node)
+{
+	int cpu, n=0;
+
+	for (cpu=0; cpu < NR_CPUS; cpu++)
+		if (node == node_cpuid[cpu].nid)
+			n++;
+	return n;
+}
+
+
+/*
+ * Find space on each node for the bootmem map & other per-node data structures.
+ *
+ * Called by efi_memmap_walk to find boot memory on each node. Note that
+ * only blocks that are free are passed to this routine (currently filtered by
+ * free_available_memory).
+ */
+static int __init
+find_pernode_space(unsigned long start, unsigned long end, int node)
+{
+	unsigned long	mapsize, pages, epfn, map=0, cpu, cpus;
+	unsigned long	pernodesize=0, pernode;
+	unsigned long	cpu_data, mmu_gathers;
+	unsigned long	pstart, length;
+	bootmem_data_t	*bdp;
+
+	pstart = __pa(start);
+	length = end - start;
+	epfn = (pstart + length) >> PAGE_SHIFT;
+	bdp = &bdata[node];
+
+	if (pstart < bdp->node_boot_start || epfn > bdp->node_low_pfn)
+		return 0;
+
+	if (!boot_pernode[node]) {
+		cpus = count_cpus(node);
+		pernodesize += PAGE_ALIGN(sizeof(struct cpuinfo_ia64)) * cpus;
+		pernodesize += L1_CACHE_ALIGN(sizeof(mmu_gather_t)) * cpus;
+		pernodesize += L1_CACHE_ALIGN(sizeof(pg_data_t));
+		pernodesize += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
+		pernodesize = PAGE_ALIGN(pernodesize);
+		pernode = NODEDATA_ALIGN(pstart, node);
+	
+		if (pstart + length > (pernode + pernodesize)) {
+			boot_pernode[node] = pernode;
+			boot_pernodesize[node] = pernodesize;
+			memset(__va(pernode), 0, pernodesize);
+
+			cpu_data = pernode;
+			pernode += PAGE_ALIGN(sizeof(struct cpuinfo_ia64)) * cpus;
+
+			mmu_gathers = pernode;
+			pernode += L1_CACHE_ALIGN(sizeof(mmu_gather_t)) * cpus;
+
+			pg_data_ptr[node] = __va(pernode);
+			pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
+
+			boot_node_data[node] = __va(pernode);
+			pernode += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
+
+			pg_data_ptr[node]->bdata = &bdata[node];
+			pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
+
+			for (cpu=0; cpu < NR_CPUS; cpu++) {
+				if (node == node_cpuid[cpu].nid) {
+					_cpu_data[cpu] = __va(cpu_data);
+					_cpu_data[cpu]->node_data = boot_node_data[node];
+					_cpu_data[cpu]->nodeid = node;
+					_cpu_data[cpu]->mmu_gathers = __va(mmu_gathers);
+					cpu_data +=  PAGE_ALIGN(sizeof(struct cpuinfo_ia64));
+					mmu_gathers += L1_CACHE_ALIGN(sizeof(mmu_gather_t));
+				}
+			}
+
+		}
+	}
+
+	pernode = boot_pernode[node];
+	pernodesize = boot_pernodesize[node];
+	if (pernode && !bdp->node_bootmem_map) {
+		pages = bdp->node_low_pfn - (bdp->node_boot_start>>PAGE_SHIFT);
+		mapsize = bootmem_bootmap_pages(pages) << PAGE_SHIFT;
+
+		if (pernode - pstart > mapsize)
+			map = pstart;
+		else if (pstart + length - pernode - pernodesize > mapsize)
+			map = pernode + pernodesize;
+
+		if (map) {
+			init_bootmem_node(
+				BOOT_NODE_DATA(node),
+				map>>PAGE_SHIFT, 
+				bdp->node_boot_start>>PAGE_SHIFT,
+				bdp->node_low_pfn);
+		}
+
+	}
+
+	return 0;
+}
+
+
+/*
+ * Free available memory to the bootmem allocator.
+ *
+ * Note that only blocks that are free are passed to this routine (currently 
+ * filtered by free_available_memory).
+ *
+ */
+static int __init
+discontig_free_bootmem_node(unsigned long start, unsigned long end, int node)
+{
+	free_bootmem_node(BOOT_NODE_DATA(node), __pa(start), end - start);
+
+	return 0;
+}
+
+
+/*
+ * Reserve the space used by the bootmem maps.
+ */
+static void __init
+discontig_reserve_bootmem(void)
+{
+	int		node;
+	unsigned long	base, size, pages;
+	bootmem_data_t	*bdp;
+
+	for (node = 0; node < numnodes; node++) {
+		bdp = BOOT_NODE_DATA(node)->bdata;
+
+		pages = bdp->node_low_pfn - (bdp->node_boot_start>>PAGE_SHIFT);
+		size = bootmem_bootmap_pages(pages) << PAGE_SHIFT;
+		base = __pa(bdp->node_bootmem_map);
+		reserve_bootmem_node(BOOT_NODE_DATA(node), base, size);
+
+		size = boot_pernodesize[node];
+		base = __pa(boot_pernode[node]);
+		reserve_bootmem_node(BOOT_NODE_DATA(node), base, size);
+	}
+}
+
+/*
+ * Initialize per-node data
+ *
+ * Finish setting up the node data for this node, then copy it to the other nodes.
+ *
+ */
+static void __init
+initialize_pernode_data(void)
+{
+	int	cpu, node;
+
+	memcpy(boot_node_data[0]->pg_data_ptrs, pg_data_ptr, sizeof(pg_data_ptr));
+	memcpy(boot_node_data[0]->node_data_ptrs, boot_node_data, sizeof(boot_node_data));
+
+	for (node=1; node < numnodes; node++) {
+		memcpy(boot_node_data[node], boot_node_data[0], sizeof(struct ia64_node_data));
+		boot_node_data[node]->node = node;
+	}
+
+	for (cpu=0; cpu < NR_CPUS; cpu++) {
+		node = node_cpuid[cpu].nid;
+		_cpu_data[cpu]->node_data = boot_node_data[node];
+		_cpu_data[cpu]->nodeid = node;
+	}
+}
+
+
+/*
+ * Called early in boot to setup the boot memory allocator, and to
+ * allocate the node-local pg_data & node-directory data structures..
+ */
+void __init
+discontig_mem_init(void)
+{
+	if (numnodes == 0) {
+		printk("node info missing!\n");
+		numnodes = 1;
+	}
+
+	min_low_pfn = -1;
+	max_low_pfn = 0;
+
+        efi_memmap_walk(filter_rsvd_memory, build_maps);
+        efi_memmap_walk(filter_rsvd_memory, find_pernode_space);
+        efi_memmap_walk(filter_rsvd_memory, discontig_free_bootmem_node);
+
+	discontig_reserve_bootmem();
+	initialize_pernode_data();
+}
+
diff -urN linux-2.4.23-pre3/arch/ia64/mm/init.c linux-2.4.23-pre4/arch/ia64/mm/init.c
--- linux-2.4.23-pre3/arch/ia64/mm/init.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/mm/init.c	2003-09-12 12:44:34.000000000 -0700
@@ -16,12 +16,14 @@
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/efi.h>
+#include <linux/mmzone.h>
 
 #include <asm/bitops.h>
 #include <asm/dma.h>
 #include <asm/ia32.h>
 #include <asm/io.h>
 #include <asm/machvec.h>
+#include <asm/numa.h>
 #include <asm/pgalloc.h>
 #include <asm/sal.h>
 #include <asm/system.h>
@@ -34,11 +36,14 @@
 extern char _stext, _etext, _edata, __init_begin, __init_end;
 
 extern void ia64_tlb_init (void);
+extern int  filter_rsvd_memory (unsigned long, unsigned long, void *);
 
+/* Note - may be changed by platform_setup */
 unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL;
 #define LARGE_GAP 0x40000000 /* Use virtual mem map if a hole is > than this */
 
-static unsigned long totalram_pages;
+static unsigned long totalram_pages, reserved_pages;
+struct page *zero_page_memmap_ptr;		/* map entry for zero page */
 
 unsigned long vmalloc_end = VMALLOC_END_INIT;
 
@@ -63,6 +68,16 @@
 	return freed;
 }
 
+inline void
+ia64_set_rbs_bot (void)
+{
+	unsigned long stack_size = current->rlim[RLIMIT_STACK].rlim_max & -16;
+
+	if (stack_size > MAX_USER_STACK_SIZE)
+		stack_size = MAX_USER_STACK_SIZE;
+	current->thread.rbs_bot = STACK_TOP - stack_size;
+}
+
 /*
  * This performs some platform-dependent address space initialization.
  * On IA-64, we want to setup the VM area for the register backing
@@ -74,6 +89,8 @@
 {
 	struct vm_area_struct *vma;
 
+	ia64_set_rbs_bot();
+
 	/*
 	 * If we're out of memory and kmem_cache_alloc() returns NULL, we simply ignore
 	 * the problem.  When the process attempts to write to the register backing store
@@ -82,7 +99,7 @@
 	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 	if (vma) {
 		vma->vm_mm = current->mm;
-		vma->vm_start = IA64_RBS_BOT;
+		vma->vm_start = current->thread.rbs_bot & PAGE_MASK;
 		vma->vm_end = vma->vm_start + PAGE_SIZE;
 		vma->vm_page_prot = PAGE_COPY;
 		vma->vm_flags = VM_READ|VM_WRITE|VM_MAYREAD|VM_MAYWRITE|VM_GROWSUP;
@@ -110,10 +127,11 @@
 void
 free_initmem (void)
 {
-	unsigned long addr;
+	unsigned long addr, eaddr;
 
-	addr = (unsigned long) &__init_begin;
-	for (; addr < (unsigned long) &__init_end; addr += PAGE_SIZE) {
+	addr = (unsigned long) ia64_imva(&__init_begin);
+	eaddr = (unsigned long) ia64_imva(&__init_end);
+	for (; addr < eaddr; addr += PAGE_SIZE) {
 		clear_bit(PG_reserved, &virt_to_page((void *)addr)->flags);
 		set_page_count(virt_to_page((void *)addr), 1);
 		free_page(addr);
@@ -189,58 +207,39 @@
 void
 show_mem(void)
 {
-	int i, total = 0, reserved = 0;
-	int shared = 0, cached = 0;
+	int i, reserved;
+	int shared, cached;
+	pg_data_t *pgdat;
+	char *tchar = (numnodes > 1) ? "\t" : "";
 
 	printk("Mem-info:\n");
 	show_free_areas();
 
-#ifdef CONFIG_DISCONTIGMEM
-	{
-		pg_data_t *pgdat = pgdat_list;
-
-		printk("Free swap:       %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-		do {
-			printk("Node ID: %d\n", pgdat->node_id);
-			for(i = 0; i < pgdat->node_size; i++) {
-				if (PageReserved(pgdat->node_mem_map+i))
-					reserved++;
-				else if (PageSwapCache(pgdat->node_mem_map+i))
-					cached++;
-				else if (page_count(pgdat->node_mem_map + i))
-					shared += page_count(pgdat->node_mem_map + i) - 1;
-			}
-			printk("\t%d pages of RAM\n", pgdat->node_size);
-			printk("\t%d reserved pages\n", reserved);
-			printk("\t%d pages shared\n", shared);
-			printk("\t%d pages swap cached\n", cached);
-			pgdat = pgdat->node_next;
-		} while (pgdat);
-		printk("Total of %ld pages in page table cache\n", pgtable_cache_size);
-		show_buffers();
-		printk("%d free buffer pages\n", nr_free_buffer_pages());
-	}
-#else /* !CONFIG_DISCONTIGMEM */
 	printk("Free swap:       %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-	i = max_mapnr;
-	while (i-- > 0) {
-		if (!VALID_PAGE(mem_map + i))
-			continue;
-		total++;
-		if (PageReserved(mem_map+i))
-			reserved++;
-		else if (PageSwapCache(mem_map+i))
-			cached++;
-		else if (page_count(mem_map + i))
-			shared += page_count(mem_map + i) - 1;
+	for_each_pgdat(pgdat) {
+		reserved=0;
+		cached=0;
+		shared=0;
+		if (numnodes > 1)
+			printk("Node ID: %d\n", pgdat->node_id);
+		for(i = 0; i < pgdat->node_size; i++) {
+			if (!VALID_PAGE(pgdat->node_mem_map+i))
+				continue;
+			if (PageReserved(pgdat->node_mem_map+i))
+				reserved++;
+			else if (PageSwapCache(pgdat->node_mem_map+i))
+				cached++;
+			else if (page_count(pgdat->node_mem_map + i))
+				shared += page_count(pgdat->node_mem_map + i) - 1;
+		}
+		printk("%s%ld pages of RAM\n", tchar, pgdat->node_size);
+		printk("%s%d reserved pages\n", tchar, reserved);
+		printk("%s%d pages shared\n", tchar, shared);
+		printk("%s%d pages swap cached\n", tchar, cached);
 	}
-	printk("%d pages of RAM\n", total);
-	printk("%d reserved pages\n", reserved);
-	printk("%d pages shared\n", shared);
-	printk("%d pages swap cached\n", cached);
-	printk("%ld pages in page table cache\n", pgtable_cache_size);
+	printk("Total of %ld pages in page table cache\n", pgtable_cache_size);
 	show_buffers();
-#endif /* !CONFIG_DISCONTIGMEM */
+	printk("%d free buffer pages\n", nr_free_buffer_pages());
 }
 
 /*
@@ -360,8 +359,10 @@
 static int
 create_mem_map_page_table (u64 start, u64 end, void *arg)
 {
-	unsigned long address, start_page, end_page;
+	unsigned long address, start_page, end_page, next_blk_page;
+	unsigned long blk_start;
 	struct page *map_start, *map_end;
+	int node=0;
 	pgd_t *pgd;
 	pmd_t *pmd;
 	pte_t *pte;
@@ -374,18 +375,35 @@
 	start_page = (unsigned long) map_start & PAGE_MASK;
 	end_page = PAGE_ALIGN((unsigned long) map_end);
 
+	/* force the first iteration to get node id */
+	blk_start = start;
+	next_blk_page = 0;
+
 	for (address = start_page; address < end_page; address += PAGE_SIZE) {
+
+		/* if we went across a node boundary, get new nid */
+		if (address >= next_blk_page) {
+			struct page *map_next_blk;
+
+			node = paddr_to_nid(__pa(blk_start));
+
+			/* get end addr of this memblk as next blk_start */
+			blk_start = (unsigned long) __va(min(end, memblk_endpaddr(__pa(blk_start))));
+			map_next_blk = vmem_map + MAP_NR_DENSE(blk_start);
+			next_blk_page = PAGE_ALIGN((unsigned long) map_next_blk);
+		}
+
 		pgd = pgd_offset_k(address);
 		if (pgd_none(*pgd))
-			pgd_populate(&init_mm, pgd, alloc_bootmem_pages(PAGE_SIZE));
+			pgd_populate(&init_mm, pgd, alloc_bootmem_pages_node(NODE_DATA(node), PAGE_SIZE));
 		pmd = pmd_offset(pgd, address);
 
 		if (pmd_none(*pmd))
-			pmd_populate(&init_mm, pmd, alloc_bootmem_pages(PAGE_SIZE));
+			pmd_populate(&init_mm, pmd, alloc_bootmem_pages_node(NODE_DATA(node), PAGE_SIZE));
 		pte = pte_offset(pmd, address);
 
 		if (pte_none(*pte))
-			set_pte(pte, mk_pte_phys(__pa(alloc_bootmem_pages(PAGE_SIZE)),
+			set_pte(pte, mk_pte_phys(__pa(alloc_bootmem_pages_node(NODE_DATA(node), PAGE_SIZE)),
 						 PAGE_KERNEL));
  	}
  	return 0;
@@ -399,6 +417,14 @@
 	int highmem;
 };
 
+struct memmap_count_callback_data {
+	int node;
+	unsigned long num_physpages;
+	unsigned long num_dma_physpages;
+	unsigned long min_pfn;
+	unsigned long max_pfn;
+} cdata;
+
 static int
 virtual_memmap_init (u64 start, u64 end, void *arg)
 {
@@ -454,17 +480,7 @@
 		efi_memmap_walk(virtual_memmap_init, &args);
 	}
 
-	return page_to_phys(end);
-}
-
-static int
-count_dma_pages (u64 start, u64 end, void *arg)
-{
-	unsigned long *count = arg;
-
-	if (end <= MAX_DMA_ADDRESS)
-		*count += (end - start) >> PAGE_SHIFT;
-	return 0;
+	return page_to_phys(end-1) + PAGE_SIZE;;
 }
 
 int
@@ -475,16 +491,27 @@
 	return __get_user(byte, (char *) page) == 0;
 }
 
+#define GRANULEROUNDDOWN(n) ((n) & ~(IA64_GRANULE_SIZE-1))
+#define GRANULEROUNDUP(n) (((n)+IA64_GRANULE_SIZE-1) & ~(IA64_GRANULE_SIZE-1))
+#define ORDERROUNDDOWN(n) ((n) & ~((PAGE_SIZE<<MAX_ORDER)-1))
 static int
-count_pages (u64 start, u64 end, void *arg)
+count_pages (u64 start, u64 end, int node)
 {
-	unsigned long *count = arg;
-
-	*count += (end - start) >> PAGE_SHIFT;
+	start = __pa(start);
+	end = __pa(end);
+	if (node == cdata.node) {
+		cdata.num_physpages += (end - start) >> PAGE_SHIFT;
+		if (start <= __pa(MAX_DMA_ADDRESS))
+			cdata.num_dma_physpages += (min(end, __pa(MAX_DMA_ADDRESS)) - start) >> PAGE_SHIFT;
+		start = GRANULEROUNDDOWN(__pa(start));
+		start = ORDERROUNDDOWN(start);
+		end = GRANULEROUNDUP(__pa(end));
+		cdata.max_pfn = max(cdata.max_pfn, end >> PAGE_SHIFT);
+		cdata.min_pfn = min(cdata.min_pfn, start >> PAGE_SHIFT);
+	}
 	return 0;
 }
 
-#ifndef CONFIG_DISCONTIGMEM
 static int
 find_largest_hole(u64 start, u64 end, void *arg)
 {
@@ -498,7 +525,6 @@
 	last_end = end;
 	return 0;
 }
-#endif
 
 /*
  * Set up the page tables.
@@ -509,73 +535,76 @@
 	unsigned long max_dma;
 	unsigned long zones_size[MAX_NR_ZONES];
 	unsigned long zholes_size[MAX_NR_ZONES];
-#ifndef CONFIG_DISCONTIGMEM
 	unsigned long max_gap;
-#endif
+	int node;
 
 	/* initialize mem_map[] */
 
-	memset(zones_size, 0, sizeof(zones_size));
-	memset(zholes_size, 0, sizeof(zholes_size));
-
-	num_physpages = 0;
-	efi_memmap_walk(count_pages, &num_physpages);
-
-	num_dma_physpages = 0;
-	efi_memmap_walk(count_dma_pages, &num_dma_physpages);
-
 	max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-
-	if (max_low_pfn < max_dma) {
-		zones_size[ZONE_DMA] = max_low_pfn;
-		zholes_size[ZONE_DMA] = max_low_pfn - num_dma_physpages;
-	} else {
-		zones_size[ZONE_DMA] = max_dma;
-		zholes_size[ZONE_DMA] = max_dma - num_dma_physpages;
-		if (num_physpages > num_dma_physpages) {
-			zones_size[ZONE_NORMAL] = max_low_pfn - max_dma;
-			zholes_size[ZONE_NORMAL] = (max_low_pfn - max_dma)
-					- (num_physpages - num_dma_physpages);
-		}
-	}
-
-#ifdef CONFIG_DISCONTIGMEM
-	free_area_init_node(0, NULL, NULL, zones_size, 0, zholes_size);
-#else
 	max_gap = 0;
 	efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
 
-	if (max_gap < LARGE_GAP) {
-		vmem_map = (struct page *)0;
-		free_area_init_node(0, NULL, NULL, zones_size, 0, zholes_size);
+	for (node=0; node < numnodes; node++) {
+		memset(zones_size, 0, sizeof(zones_size));
+		memset(zholes_size, 0, sizeof(zholes_size));
+		memset(&cdata, 0, sizeof(cdata));
+
+		cdata.node = node;
+		cdata.min_pfn = ~0;
+
+		efi_memmap_walk(filter_rsvd_memory, count_pages);
+		num_dma_physpages += cdata.num_dma_physpages;
+		num_physpages += cdata.num_physpages;
+
+		if (cdata.min_pfn >= max_dma) {
+			zones_size[ZONE_NORMAL] = cdata.max_pfn - cdata.min_pfn;
+			zholes_size[ZONE_NORMAL] = cdata.max_pfn - cdata.min_pfn - cdata.num_physpages;
+		} else if (cdata.max_pfn < max_dma) {
+			zones_size[ZONE_DMA] = cdata.max_pfn - cdata.min_pfn;
+			zholes_size[ZONE_DMA] = cdata.max_pfn - cdata.min_pfn - cdata.num_dma_physpages;
+		} else {
+			zones_size[ZONE_DMA] = max_dma - cdata.min_pfn;
+			zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] - cdata.num_dma_physpages;
+			zones_size[ZONE_NORMAL] = cdata.max_pfn - max_dma;
+			zholes_size[ZONE_NORMAL] = zones_size[ZONE_NORMAL] - (cdata.num_physpages - cdata.num_dma_physpages);
+		}
+	
+		if (numnodes == 1 && max_gap < LARGE_GAP) {
+			vmem_map = (struct page *)0;
+			zones_size[ZONE_DMA] += cdata.min_pfn;
+			zholes_size[ZONE_DMA] += cdata.min_pfn;
+			free_area_init_core(0, NODE_DATA(node), &mem_map, zones_size, 0, zholes_size, NULL);
+		} else {
+	
+			/* allocate virtual mem_map */
+	
+			if (node == 0) {
+				unsigned long map_size;
+				map_size = PAGE_ALIGN(max_low_pfn*sizeof(struct page));
+				vmalloc_end -= map_size;
+				mem_map = vmem_map = (struct page *) vmalloc_end;
+				efi_memmap_walk(create_mem_map_page_table, 0);
+				printk(KERN_INFO "Virtual mem_map starts at 0x%p\n", mem_map);
+			}
+	
+			free_area_init_node(node, NODE_DATA(node), vmem_map+cdata.min_pfn, zones_size, 
+				cdata.min_pfn<<PAGE_SHIFT, zholes_size);
+		}
 	}
-	else {
-		unsigned long map_size;
 
-		/* allocate virtual mem_map */
-
-		map_size = PAGE_ALIGN(max_low_pfn*sizeof(struct page));
-		vmalloc_end -= map_size;
-		vmem_map = (struct page *) vmalloc_end;
-		efi_memmap_walk(create_mem_map_page_table, 0);
-
-		free_area_init_node(0, NULL, vmem_map, zones_size, 0, zholes_size);
-		printk(KERN_INFO "Virtual mem_map starts at 0x%p\n", mem_map);
-	}
-#endif
+	zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
 }
 
 static int
 count_reserved_pages (u64 start, u64 end, void *arg)
 {
 	unsigned long num_reserved = 0;
-	unsigned long *count = arg;
 	struct page *pg;
 
 	for (pg = virt_to_page((void *)start); pg < virt_to_page((void *)end); ++pg)
 		if (PageReserved(pg))
 			++num_reserved;
-	*count += num_reserved;
+	reserved_pages += num_reserved;
 	return 0;
 }
 
@@ -583,8 +612,10 @@
 mem_init (void)
 {
 	extern char __start_gate_section[];
-	long reserved_pages, codesize, datasize, initsize;
+	long codesize, datasize, initsize;
 	unsigned long num_pgt_pages;
+	pg_data_t *pgdat;
+
 
 #ifdef CONFIG_PCI
 	/*
@@ -601,10 +632,11 @@
 	max_mapnr = max_low_pfn;
 	high_memory = __va(max_low_pfn * PAGE_SIZE);
 
-	totalram_pages += free_all_bootmem();
+	for_each_pgdat(pgdat)
+		totalram_pages += free_all_bootmem_node(pgdat);
 
 	reserved_pages = 0;
-	efi_memmap_walk(count_reserved_pages, &reserved_pages);
+	efi_memmap_walk(filter_rsvd_memory, count_reserved_pages);
 
 	codesize =  (unsigned long) &_etext - (unsigned long) &_stext;
 	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
@@ -629,7 +661,7 @@
 		pgt_cache_water[1] = num_pgt_pages;
 
 	/* install the gate page in the global page table: */
-	put_gate_page(virt_to_page(__start_gate_section), GATE_ADDR);
+	put_gate_page(virt_to_page(ia64_imva(__start_gate_section)), GATE_ADDR);
 
 #ifdef CONFIG_IA32_SUPPORT
 	ia32_gdt_init();
diff -urN linux-2.4.23-pre3/arch/ia64/mm/numa.c linux-2.4.23-pre4/arch/ia64/mm/numa.c
--- linux-2.4.23-pre3/arch/ia64/mm/numa.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/mm/numa.c	2003-09-12 12:44:34.000000000 -0700
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ *
+ * This file contains NUMA specific variables and functions which can
+ * be split away from DISCONTIGMEM and are used on NUMA machines with
+ * contiguous memory.
+ * 
+ *                         2002/08/07 Erich Focht <efocht@ess.nec.de>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mmzone.h>
+#include <linux/smp.h>
+#include <asm/numa.h>
+
+/*
+ * The following structures are usually initialized by ACPI or
+ * similar mechanisms and describe the NUMA characteristics of the machine.
+ */
+int num_memblks = 0;
+struct node_memblk_s node_memblk[NR_MEMBLKS];
+struct node_cpuid_s node_cpuid[NR_CPUS];
+/*
+ * This is a matrix with "distances" between nodes, they should be
+ * proportional to the memory access latency ratios.
+ */
+u8 numa_slit[NR_NODES * NR_NODES];
+
+/* Identify which cnode a physical address resides on */
+int
+paddr_to_nid(unsigned long paddr)
+{
+	int	i;
+
+	for (i = 0; i < num_memblks; i++)
+		if (paddr >= node_memblk[i].start_paddr &&
+		    paddr < node_memblk[i].start_paddr + node_memblk[i].size)
+			break;
+
+	return (i < num_memblks) ? node_memblk[i].nid : (num_memblks ? -1 : 0);
+}
+
+/* return end addr of a memblk */
+unsigned long
+memblk_endpaddr(unsigned long paddr)
+{
+	int	i;
+
+	for (i = 0; i < num_memblks; i++)
+		if (paddr >= node_memblk[i].start_paddr &&
+		    paddr < node_memblk[i].start_paddr + node_memblk[i].size)
+			return node_memblk[i].start_paddr + node_memblk[i].size;
+
+	return 0;
+}
+
+
+/* on which node is each logical CPU (one cacheline even for 64 CPUs) */
+volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned;
+
+/* which logical CPUs are on which nodes */
+volatile unsigned long node_to_cpu_mask[NR_NODES]  __cacheline_aligned;
+
+/*
+ * Build cpu to node mapping and initialize the per node cpu masks.
+ */
+void __init
+build_cpu_to_node_map (void)
+{
+	int cpu, i, node;
+
+	for(cpu = 0; cpu < NR_CPUS; ++cpu) {
+		/*
+		 * All Itanium NUMA platforms I know use ACPI, so maybe we
+		 * can drop this ifdef completely.                    [EF]
+		 */
+#ifdef CONFIG_SMP
+# ifdef CONFIG_ACPI_NUMA
+		node = -1;
+		for (i = 0; i < NR_CPUS; ++i) {
+			extern volatile int ia64_cpu_to_sapicid[];
+			if (ia64_cpu_to_sapicid[cpu] == node_cpuid[i].phys_id) {
+				node = node_cpuid[i].nid;
+				break;
+			}
+		}
+# else
+#		error Fixme: Dunno how to build CPU-to-node map.
+# endif
+		cpu_to_node_map[cpu] = node;
+		if (node >= 0)
+			__set_bit(cpu, &node_to_cpu_mask[node]);
+#else
+			__set_bit(0, &node_to_cpu_mask[0]);
+#endif
+	}
+}
+
diff -urN linux-2.4.23-pre3/arch/ia64/mm/tlb.c linux-2.4.23-pre4/arch/ia64/mm/tlb.c
--- linux-2.4.23-pre3/arch/ia64/mm/tlb.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/mm/tlb.c	2003-09-12 12:44:34.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * TLB support routines.
  *
- * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * 08/02/00 A. Mallick <asit.k.mallick@intel.com>
@@ -16,28 +16,21 @@
 #include <linux/smp.h>
 #include <linux/mm.h>
 
+#include <asm/delay.h>
 #include <asm/mmu_context.h>
 #include <asm/pgalloc.h>
 #include <asm/pal.h>
-#include <asm/delay.h>
 
-#define SUPPORTED_PGBITS (			\
-		1 << _PAGE_SIZE_256M |		\
-		1 << _PAGE_SIZE_64M  |		\
-		1 << _PAGE_SIZE_16M  |		\
-		1 << _PAGE_SIZE_4M   |		\
-		1 << _PAGE_SIZE_1M   |		\
-		1 << _PAGE_SIZE_256K |		\
-		1 << _PAGE_SIZE_64K  |		\
-		1 << _PAGE_SIZE_16K  |		\
-		1 << _PAGE_SIZE_8K   |		\
-		1 << _PAGE_SIZE_4K )
+static struct {
+	unsigned long mask;	/* mask of supported purge page-sizes */
+	unsigned long max_bits;	/* log2() of largest supported purge page-size */
+} purge;
 
 struct ia64_ctx ia64_ctx = {
-	.lock =	SPIN_LOCK_UNLOCKED,
-	.next =	1,
-	.limit =(1 << 15) - 1,		/* start out with the safe (architected) limit */
-	.max_ctx = ~0U
+	.lock =		SPIN_LOCK_UNLOCKED,
+	.next =		1,
+	.limit =	(1 << 15) - 1,		/* start out with the safe (architected) limit */
+	.max_ctx =	~0U
 };
 
 /*
@@ -149,22 +142,10 @@
 	}
 
 	nbits = ia64_fls(size + 0xfff);
-	if (((1UL << nbits) & SUPPORTED_PGBITS) == 0) {
-		if (nbits > _PAGE_SIZE_256M)
-			nbits = _PAGE_SIZE_256M;
-		else
-			/*
-			 * Some page sizes are not implemented in the
-			 * IA-64 arch, so if we get asked to clear an
-			 * unsupported page size, round up to the
-			 * nearest page size.  Note that we depend on
-			 * the fact that if page size N is not
-			 * implemented, 2*N _is_ implemented.
-			 */
-			++nbits;
-		if (((1UL << nbits) & SUPPORTED_PGBITS) == 0)
-			panic("flush_tlb_range: BUG: nbits=%lu\n", nbits);
-	}
+	while (unlikely (((1UL << nbits) & purge.mask) == 0) && (nbits < purge.max_bits))
+		++nbits;
+	if (nbits > purge.max_bits)
+		nbits = purge.max_bits;
 	start &= ~((1UL << nbits) - 1);
 
 # ifdef CONFIG_SMP
@@ -185,6 +166,15 @@
 ia64_tlb_init (void)
 {
 	ia64_ptce_info_t ptce_info;
+	unsigned long tr_pgbits;
+	long status;
+
+	if ((status = ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) != 0) {
+		printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld;"
+		       "defaulting to architected purge page-sizes.\n", status);
+		purge.mask = 0x115557000;
+	}
+	purge.max_bits = ia64_fls(purge.mask);
 
 	ia64_get_ptce(&ptce_info);
 	local_cpu_data->ptce_base = ptce_info.base;
diff -urN linux-2.4.23-pre3/arch/ia64/scripts/make_gas_hint_test.c linux-2.4.23-pre4/arch/ia64/scripts/make_gas_hint_test.c
--- linux-2.4.23-pre3/arch/ia64/scripts/make_gas_hint_test.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/scripts/make_gas_hint_test.c	2003-09-12 12:44:34.000000000 -0700
@@ -0,0 +1,15 @@
+// The code generates a test case which is used
+// to detect whether Binutil supports hint
+// instruction correctly or not.
+#include <string.h>
+#include <stdio.h>
+
+int main()
+{
+	char str[32766];
+	memset(str,'\n',32765);
+	str[32765]=0;
+	printf("%s(p7) hint @pause\n",str);
+
+	return 0;
+}
diff -urN linux-2.4.23-pre3/arch/ia64/sn/fakeprom/fpmem.c linux-2.4.23-pre4/arch/ia64/sn/fakeprom/fpmem.c
--- linux-2.4.23-pre3/arch/ia64/sn/fakeprom/fpmem.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/fakeprom/fpmem.c	2003-09-12 12:44:34.000000000 -0700
@@ -17,8 +17,58 @@
  * 	  klconfig to efi_memmap
  */
 
+
+/*
+ * Sometimes it is useful to build a fake prom with a memmap that matches another
+ * platform. There are restrictions on how successful you will be, but here
+ * are the instructions for what I have used in the past & had good luck:
+ *
+ * 	- compile a kernel for the target platform (like zx1) with the following
+ * 	  set: 
+ * 	  	#define EFI_DEBUG 1		# in arch/ia64/kernel/efi.c
+ * 	  	#define SRAT_DEBUG		# in drivers/acpi/numa.c
+ *
+ *	- this causes the kernel to dump the memmap & SRAT during boot.
+ *
+ *	- copy the console output to a file.
+ *
+ *	- run the following script with the file as input:
+ *		
+ *			#!/bin/sh
+ *			
+ *			awk '
+ *			/^mem/ {
+ *			        printf "\t{%s, %sUL, %sUL, %sUL},\n", $4, $7, $11, $12
+ *			} 
+ *			/SRAT Memory/ {
+ *			        if (srat != 1) print "SRAT"
+ *			        srat = 1
+ *			        for (i=1; i<=0;i++)
+ *			                printf "%4d |%s|\n", i, $i
+ *			        printf "\t{%s, %sUL, %sUL, %sUL},\n", $4, $6, $8, $13
+ *			}
+ *			BEGIN {
+ *			        FS="[ \[\)\(\t:=,-]"
+ *			} '
+ *			
+ * 	- this converts the memmap & SRAT info into C code array initilization statements.
+ *
+ * 	- copy & paste the initialization statements into the arrays below. Look for
+ * 	  comments "PASTE xxx HERE". In general, on the MEMMAP is present on most other
+ * 	  systems. If you have an SRAT, you may need to hack the number of nodes in fw-emu.
+ * 	  Good luck...
+ *
+ * 	- set "#define FAKE_MEMMAP 1
+ *
+ * 	- When running medusa, make sure you set the node1_memory_config to cover the
+ * 	  amount of memory that you are going to use. Also note that you can run the
+ * 	  kernel in "alias" space (starts at phy adr 0). This is kinda tricky, though
+ */
+
+
 #include <linux/config.h>
 #include <linux/efi.h>
+#include <linux/acpi.h>
 #include "fpmem.h"
 
 /*
@@ -77,9 +127,9 @@
 /* For SN, get the index th nasid */
 
 int
-GetNasid(int index)
+GetNasid(int cnode)
 {
-	return sn_memmap[index].nasid ;
+	return sn_memmap[cnode].nasid ;
 }
 
 node_memmap_t
@@ -94,6 +144,21 @@
 	return  sn_memmap[cnode].cpuconfig & (1UL<<cpu);
 }
 
+void
+GetLogicalCpu(int bsp, int *nasidp, int *cpup)
+{
+	int cnode, cpu;
+
+	for (cnode=0; cnode<GetNumNodes(); cnode++) {
+		for (cpu=0; cpu<MAX_CPUS_NODE; cpu++)
+			if (IsCpuPresent(cnode,cpu)) {
+				*nasidp = GetNasid(cnode);
+				*cpup = cpu;
+				if (bsp-- == 0)
+					return;
+			}
+	}
+}
 
 /*
  * Made this into an explicit case statement so that
@@ -102,31 +167,41 @@
  */
 
 #ifdef SGI_SN2
-int
-IsBankPresent(int index, node_memmap_t nmemmap)
-{
-	switch (index) {
-		case 0:return BankPresent(nmemmap.b0size);
-		case 1:return BankPresent(nmemmap.b1size);
-		case 2:return BankPresent(nmemmap.b2size);
-		case 3:return BankPresent(nmemmap.b3size);
-		default:return -1 ;
-	}
-}
-
-int
+long
 GetBankSize(int index, node_memmap_t nmemmap)
 {
+	int bsize, bdou, hack;
 	/*
 	 * Add 2 because there are 4 dimms per bank.
 	 */
         switch (index) {
-                case 0:return 2 + ((long)nmemmap.b0size + nmemmap.b0dou);
-                case 1:return 2 + ((long)nmemmap.b1size + nmemmap.b1dou);
-                case 2:return 2 + ((long)nmemmap.b2size + nmemmap.b2dou);
-                case 3:return 2 + ((long)nmemmap.b3size + nmemmap.b3dou);
+                case 0:
+			bsize = nmemmap.b0size;
+			bdou = nmemmap.b0dou;
+			hack = nmemmap.hack0;
+			break;
+                case 1:
+			bsize = nmemmap.b1size;
+			bdou = nmemmap.b1dou;
+			hack = nmemmap.hack1;
+			break;
+                case 2:
+			bsize = nmemmap.b2size;
+			bdou = nmemmap.b2dou;
+			hack = nmemmap.hack2;
+			break;
+                case 3:
+			bsize = nmemmap.b3size;
+			bdou = nmemmap.b3dou;
+			hack = nmemmap.hack3;
+			break;
                 default:return -1 ;
         }
+
+	if (bsize < 6 && hack == 0)
+		return (1UL<<((2+bsize+bdou)+SN2_BANK_SIZE_SHIFT))*31/32;
+	else 
+		return (16*MB)*hack;
 }
 
 #endif
@@ -141,6 +216,99 @@
         md->attribute = attr;
 }
 
+
+//#define FAKE_MEMMAP 1
+#ifdef FAKE_MEMMAP
+
+#define OFF 0x3000000000UL
+struct {
+	unsigned long	type;
+	unsigned long	attr;
+	unsigned long	start;
+	unsigned long	end;
+} mdx[] = {
+	/* PASTE SRAT HERE */
+};
+
+struct srat {
+	unsigned long	start;
+	unsigned long	len;
+	unsigned long	type;
+	unsigned long	pxm;
+} srat[] = {
+
+	/* PASTE SRAT HERE */
+
+};
+
+
+
+void *
+build_memory_srat(struct acpi_table_memory_affinity *ptr)
+{
+	int i;
+	int n = sizeof(srat)/sizeof(struct srat);
+
+        for (i=0; i<n; i++)
+		srat[i].start += OFF;
+        for (i=0; i<n; i++) {
+                ptr->header.type = ACPI_SRAT_MEMORY_AFFINITY;
+                ptr->header.length = sizeof(struct acpi_table_memory_affinity);
+                ptr->proximity_domain = srat[i].pxm;
+                ptr->base_addr_lo = srat[i].start & 0xffffffff;
+                ptr->length_lo = srat[i].len & 0xffffffff;
+                ptr->base_addr_hi = srat[i].start >> 32;
+                ptr->length_hi = srat[i].len >> 32;
+                ptr->memory_type = ACPI_ADDRESS_RANGE_MEMORY;
+                ptr->flags.enabled = 1;
+		ptr++;
+        }
+	return ptr;
+}
+
+int
+build_efi_memmap(void *md, int mdsize)
+{
+	int		i;
+
+	for (i=0; i<sizeof(mdx)/32; i++) {
+		mdx[i].start += OFF;
+		mdx[i].end += OFF;
+	}
+	for (i=0; i<sizeof(mdx)/32; i++) {
+			build_mem_desc(md, mdx[i].type, mdx[i].start, mdx[i].end-mdx[i].start, mdx[i].attr);
+			md += mdsize;
+	}
+	return i;
+
+}
+
+#else /* ! FAKE_MEMMAP */
+
+void *
+build_memory_srat(struct acpi_table_memory_affinity *ptr)
+{
+	int	cnode, nasid;
+
+	for (cnode=0; cnode<GetNumNodes(); cnode++) {
+		nasid = GetNasid(cnode);
+		ptr->header.type = ACPI_SRAT_MEMORY_AFFINITY;
+		ptr->header.length = sizeof(struct acpi_table_memory_affinity);
+		ptr->proximity_domain = PROXIMITY_DOMAIN(nasid);
+		ptr->base_addr_lo = 0;
+		ptr->length_lo = 0;
+#if defined(SGI_SN2)
+		ptr->base_addr_hi = (nasid<<6) | (3<<4);
+		ptr->length_hi = (MD_BANKSIZE*MD_BANKS_PER_NODE)>>32;
+#endif
+		ptr->memory_type = ACPI_ADDRESS_RANGE_MEMORY;
+		ptr->flags.enabled = 1;
+		ptr++;
+	}
+	return ptr;
+}
+
+
 int
 build_efi_memmap(void *md, int mdsize)
 {
@@ -148,7 +316,6 @@
 	int		cnode,bank ;
 	int		nasid ;
 	node_memmap_t	membank_info ;
-	int		bsize;
 	int		count = 0 ;
 	long		paddr, hole, numbytes;
 
@@ -157,18 +324,9 @@
 		nasid = GetNasid(cnode) ;
 		membank_info = GetMemBankInfo(cnode) ;
 		for (bank=0;bank<MD_BANKS_PER_NODE;bank++) {
-			if (IsBankPresent(bank, membank_info)) {
-				bsize = GetBankSize(bank, membank_info) ;
+			numbytes = GetBankSize(bank, membank_info);
+			if (numbytes) {
                                 paddr = PHYS_ADDRESS(nasid, (long)bank<<MD_BANK_SHFT);
-                                numbytes = BankSizeBytes(bsize);
-#ifdef SGI_SN2
-				/* 
-				 * Ignore directory.
-				 * Shorten memory chunk by 1 page - makes a better
-				 * testcase & is more like the real PROM.
-				 */
-				numbytes = numbytes * 31 / 32;
-#endif
 				/*
 				 * Only emulate the memory prom grabs
 				 * if we have lots of memory, to allow
@@ -242,6 +400,7 @@
 	}
 	return count ;
 }
+#endif /* FAKE_MEMMAP */
 
 void
 build_init(unsigned long args)
diff -urN linux-2.4.23-pre3/arch/ia64/sn/fakeprom/fpmem.h linux-2.4.23-pre4/arch/ia64/sn/fakeprom/fpmem.h
--- linux-2.4.23-pre3/arch/ia64/sn/fakeprom/fpmem.h	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/fakeprom/fpmem.h	2003-09-12 12:44:34.000000000 -0700
@@ -29,29 +29,35 @@
 {
         unsigned int    b0size  :3,     /* 0-2   bank 0 size */
                         b0dou   :1,     /* 3     bank 0 is 2-sided */
-                        ena0    :1,     /* 4     bank 0 enabled */
-                        r0      :3,     /* 5-7   reserved */
+                        hack0   :4,     /* 4-7   bank 0 hack */
         		b1size  :3,     /* 8-10  bank 1 size */
                         b1dou   :1,     /* 11    bank 1 is 2-sided */
-                        ena1    :1,     /* 12    bank 1 enabled */
-                        r1      :3,     /* 13-15 reserved */
+                        hack1   :4,     /* 12-15 bank 1 hack */
         		b2size  :3,     /* 16-18 bank 2 size */
                         b2dou   :1,     /* 19    bank 1 is 2-sided */
-                        ena2    :1,     /* 20    bank 2 enabled */
-                        r2      :3,     /* 21-23 reserved */
+                        hack2   :4,     /* 20-23 bank 2 hack */
         		b3size  :3,     /* 24-26 bank 3 size */
                         b3dou   :1,     /* 27    bank 3 is 2-sided */
-                        ena3    :1,     /* 28    bank 3 enabled */
-                        r3      :3;     /* 29-31 reserved */
+                        hack3   :4;     /* 28-31 bank 3 hack */
 } node_memmap_t ;
 
+#define PROXIMITY_DOMAIN(nasid) (((nasid)>>1) & 255)
 #define SN2_BANK_SIZE_SHIFT		(MBSHIFT+6)     /* 64 MB */
-#define BankPresent(bsize)		(bsize<6)
-#define BankSizeBytes(bsize)            (BankPresent(bsize) ? 1UL<<((bsize)+SN2_BANK_SIZE_SHIFT) : 0)
 #define MD_BANKS_PER_NODE 4
 #define MD_BANKSIZE			(1UL << 34)
+
+#define MAX_SN_NODES            256
+#define MAX_LSAPICS             512
+#define MAX_CPUS_NODE           4
+#define MAX_CPUS                (MAX_CPUS_NODE*MAX_SN_NODES)
+#define CPUS_PER_FSB            2
+#define CPUS_PER_FSB_MASK       (CPUS_PER_FSB-1)
+#define MAX_NASID               2048
+
 #endif
 
+#define FPROM_BUG()             do {while (1);} while (0)
+
 typedef struct sn_memmap_s
 {
 	short		nasid ;
@@ -66,7 +72,9 @@
 	sn_memmap_t	memmap[1];		/* start of array */
 } sn_config_t;
 
+struct acpi_table_memory_affinity;
 
+extern long base_nasid;
 
 extern void build_init(unsigned long);
 extern int build_efi_memmap(void *, int);
@@ -74,3 +82,5 @@
 extern int GetNumCpus(void);
 extern int IsCpuPresent(int, int);
 extern int GetNasid(int);
+extern void* build_memory_srat(struct acpi_table_memory_affinity *);
+extern void GetLogicalCpu(int, int *, int *);
diff -urN linux-2.4.23-pre3/arch/ia64/sn/fakeprom/fpromasm.S linux-2.4.23-pre4/arch/ia64/sn/fakeprom/fpromasm.S
--- linux-2.4.23-pre3/arch/ia64/sn/fakeprom/fpromasm.S	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/fakeprom/fpromasm.S	2003-09-12 12:44:34.000000000 -0700
@@ -253,9 +253,10 @@
 //	Note: should verify that the interrupt we got was really the ap_wakeup
 //	      interrupt but this should not be an issue on medusa
 slave:
-	nop.i		0x8beef				// Medusa - put cpu to sleep til interrupt occurs
 	mov		r8=cr.irr0;;			// Check for interrupt pending.
 	cmp.eq		p6,p0=r8,r0
+	;;
+(p6)	nop.i		0x8beef				// Medusa - put cpu to sleep til interrupt occurs
 (p6)	br.cond.sptk	slave;;
 
 	mov		r8=cr.ivr;;			// Got one. Must read ivr to accept it
@@ -361,6 +362,13 @@
 	st8	[r3]=r2
 	;;
 
+1:	cmp.eq	p6,p7=34,r28		/* PAL_VM_PAGE_SIZE */
+(p7)	br.cond.sptk.few 1f
+	movl	r8=0				/* status = 0 */
+	movl	r9=0x015557000			/* insertable page sizes */
+	movl	r10=0x115557000			/* purgeable page sizes */
+	movl	r11=0
+
 1:	cmp.eq	p6,p7=19,r28		/* PAL_RSE_INFO */
 (p7)	br.cond.sptk.few 1f
 	movl	r8=0				/* status = 0 */
diff -urN linux-2.4.23-pre3/arch/ia64/sn/fakeprom/fw-emu.c linux-2.4.23-pre4/arch/ia64/sn/fakeprom/fw-emu.c
--- linux-2.4.23-pre3/arch/ia64/sn/fakeprom/fw-emu.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/fakeprom/fw-emu.c	2003-09-12 12:44:34.000000000 -0700
@@ -47,6 +47,8 @@
 #include <asm/sn/sn2/shub_mmr.h>
 #endif
 #include <linux/acpi.h>
+#include <acpi/acpi.h>
+#include <acpi/actbl.h>
 #include "fpmem.h"
 
 #define RSDP_NAME               "RSDP"
@@ -66,11 +68,12 @@
 #define BOOT_SIG                "BOOT"      /* Boot table */
 #define ACPI_SRAT_REVISION 1
 #define ACPI_SLIT_REVISION 1
+#define ACPI_FADT_REVISION 3
+#define ACPI_DSDT_REVISION 1
 
 #define OEMID			"SGI"
 #ifdef SGI_SN2
 #define PRODUCT			"SN2"
-#define PROXIMITY_DOMAIN(nasid)	(((nasid)>>1) & 255)
 #endif
 
 #define MB	(1024*1024UL)
@@ -81,15 +84,6 @@
 #define ABS(i)			((i) > 0   ? (i) : -(i))
 #define ALIGN8(p)		(((long)(p) +7) & ~7)
 
-#define FPROM_BUG()		do {while (1);} while (0)
-#define MAX_SN_NODES		128
-#define MAX_LSAPICS		512
-#define MAX_CPUS		512
-#define MAX_CPUS_NODE		4
-#define CPUS_PER_NODE		4
-#define CPUS_PER_FSB		2
-#define CPUS_PER_FSB_MASK	(CPUS_PER_FSB-1)
-
 #define NUM_EFI_DESCS		2
 
 #define RSDP_CHECKSUM_LENGTH	20
@@ -126,11 +120,10 @@
  */
 long		base_nasid;
 long		num_cpus;
-long		bsp_entry_pc=0;
+long		bsp_entry_pc;
 long		num_nodes;
-long		app_entry_pc;
-int		bsp_lid;
 func_ptr_t	ap_entry;
+char		nasid_present[MAX_NASID];
 
 
 extern void pal_emulator(void);
@@ -141,8 +134,11 @@
 		    + sizeof(struct ia64_sal_systab)
 		    + sizeof(struct ia64_sal_desc_entry_point)
 		    + sizeof(struct ia64_sal_desc_ap_wakeup)
+		    + sizeof(struct ia64_sal_desc_platform_feature)
 		    + sizeof(struct acpi20_table_rsdp)
 		    + sizeof(struct acpi_table_xsdt)
+		    + sizeof(struct acpi_table_header) /* dummy DSDT */
+		    + sizeof(struct fadt_descriptor_rev2)
 		    + sizeof(struct acpi_table_slit)
 		    +   MAX_SN_NODES*MAX_SN_NODES+8
 		    + sizeof(struct acpi_table_madt)
@@ -242,7 +238,11 @@
 	if (index == SAL_FREQ_BASE) {
 		switch (in1) {
 		      case SAL_FREQ_BASE_PLATFORM:
-			r9 = 500000000;
+			     /* slow down the clock on large systems to reduce the interrupt rate */
+			if (num_cpus < 32)
+				r9 = 500000000UL;
+			else
+				r9 = 5000000000UL;
 			break;
 
 		      case SAL_FREQ_BASE_INTERVAL_TIMER:
@@ -446,7 +446,7 @@
 }
 
 int
-nasid_present(int nasid)
+is_nasid_present(int nasid)
 {
 	int	cnode;
 	for (cnode=0; cnode<num_nodes; cnode++)
@@ -456,7 +456,7 @@
 }
 
 void
-sys_fw_init (const char *args, int arglen, int bsp)
+sys_fw_init (const char *args, int arglen)
 {
 	/*
 	 * Use static variables to keep from overflowing the RSE stack
@@ -472,33 +472,30 @@
 	static struct acpi_table_slit *acpi_slit;
 	static struct acpi_table_madt *acpi_madt;
 	static struct acpi_table_lsapic *lsapic20;
+	static struct acpi_table_header *acpi_dsdt;
+	static struct fadt_descriptor_rev2 *acpi_fadt;
 	static struct ia64_sal_systab *sal_systab;
 	static struct acpi_table_srat *acpi_srat;
 	static struct acpi_table_processor_affinity *srat_cpu_affinity;
-	static struct acpi_table_memory_affinity *srat_memory_affinity;
 	static efi_memory_desc_t *efi_memmap, *md;
 	static unsigned long *pal_desc, *sal_desc;
 	static struct ia64_sal_desc_entry_point *sal_ed;
 	static struct ia64_boot_param *bp;
 	static struct ia64_sal_desc_ap_wakeup *sal_apwake;
+	static struct ia64_sal_desc_platform_feature *sal_feature;
 	static unsigned char checksum;
 	static char *cp, *cmd_line, *vendor;
 	static void *ptr;
 	static int mdsize, domain, last_domain ;
 	static int i, j, cnode, max_nasid, nasid, cpu, num_memmd, cpus_found;
 
-	/*
-	 * Pass the parameter base address to the build_efi_xxx routines.
-	 */
-#if defined(SGI_SN2)
-	build_init(0x3000000000UL | ((long)base_nasid<<38));
-#endif
-
 	num_nodes = GetNumNodes();
 	num_cpus = GetNumCpus();
 	for (max_nasid=0, cnode=0; cnode<num_nodes; cnode++)
 		max_nasid = MAX(max_nasid, GetNasid(cnode));
 
+	//max_nasid = 0;
+	//num_nodes = 1;
 
 	memset(fw_mem, 0, sizeof(fw_mem));
 
@@ -518,10 +515,13 @@
 	sal_ed      = (void *) cp; cp += ALIGN8(sizeof(*sal_ed));
 	sal_ptc     = (void *) cp; cp += ALIGN8(sizeof(*sal_ptc));
 	sal_apwake  = (void *) cp; cp += ALIGN8(sizeof(*sal_apwake));
+	sal_feature = (void *) cp; cp += ALIGN8(sizeof(*sal_feature));
 	acpi20_rsdp = (void *) cp; cp += ALIGN8(sizeof(*acpi20_rsdp));
-	acpi_xsdt   = (void *) cp; cp += ALIGN8(sizeof(*acpi_xsdt) + 64); 
+	acpi_xsdt   = (void *) cp; cp += ALIGN8(sizeof(*acpi_xsdt) + 64);
 			/* save space for more OS defined table pointers. */
 
+	acpi_dsdt   = (void *) cp; cp += ALIGN8(sizeof(*acpi_dsdt));
+	acpi_fadt   = (void *) cp; cp += ALIGN8(sizeof(*acpi_fadt));
 	acpi_slit   = (void *) cp; cp += ALIGN8(sizeof(*acpi_slit) + 8 + (max_nasid+1)*(max_nasid+1));
 	acpi_madt   = (void *) cp; cp += ALIGN8(sizeof(*acpi_madt) + sizeof(struct acpi_table_lsapic) * (num_cpus+1));
 	acpi_srat   = (void *) cp; cp += ALIGN8(sizeof(struct acpi_table_srat));
@@ -546,7 +546,7 @@
 	 * You can also edit this line to pass other arguments to the kernel.
 	 *    Note: disable kernel text replication.
 	 */
-	strcpy(cmd_line, "init=/bin/bash ktreplicate=0");
+	strcpy(cmd_line, "init=/bin/bash console=ttyS0");
 
 	memset(efi_systab, 0, sizeof(efi_systab));
 	efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
@@ -598,7 +598,9 @@
 	acpi_xsdt->entry[0] = __fwtab_pa(base_nasid, acpi_madt);
 	acpi_xsdt->entry[1] = __fwtab_pa(base_nasid, acpi_slit);
 	acpi_xsdt->entry[2] = __fwtab_pa(base_nasid, acpi_srat);
-	acpi_checksum(&acpi_xsdt->header, sizeof(struct acpi_table_xsdt) + 16);
+	acpi_xsdt->entry[3] = __fwtab_pa(base_nasid, acpi_fadt);
+	acpi_xsdt->entry[4] = __fwtab_pa(base_nasid, acpi_dsdt);
+	acpi_checksum(&acpi_xsdt->header, sizeof(struct acpi_table_xsdt) + 32);
 
 	/* Set up the APIC table */
 	acpi_table_initx(&acpi_madt->header, APIC_SIG, 4, 1, 1);
@@ -614,7 +616,7 @@
 			lsapic20->flags.enabled = 1;
 #if defined(SGI_SN2)
 			lsapic20->eid = nasid&0xffff;
-			lsapic20->id = (cpu<<4) | (nasid>>16);
+			lsapic20->id = (cpu<<4) | (nasid>>8);
 #endif
 			lsapic20 = (struct acpi_table_lsapic*) ((long)lsapic20+sizeof(struct acpi_table_lsapic));
 		}
@@ -624,23 +626,10 @@
 	/* Set up the SRAT table */
 	acpi_table_initx(&acpi_srat->header, SRAT_SIG, 4, ACPI_SRAT_REVISION, 1);
 	ptr = acpi_srat+1;
-	for (cnode=0; cnode<num_nodes; cnode++) {
-		nasid = GetNasid(cnode);
-		srat_memory_affinity = ptr;
-		ptr = srat_memory_affinity+1;
-		srat_memory_affinity->header.type = ACPI_SRAT_MEMORY_AFFINITY;
-		srat_memory_affinity->header.length = sizeof(struct acpi_table_memory_affinity);
-		srat_memory_affinity->proximity_domain = PROXIMITY_DOMAIN(nasid);
-		srat_memory_affinity->base_addr_lo = 0;
-		srat_memory_affinity->length_lo = 0;
-#if defined(SGI_SN2)
-		srat_memory_affinity->base_addr_hi = (nasid<<6) | (3<<4);
-		srat_memory_affinity->length_hi = (MD_BANKSIZE*MD_BANKS_PER_NODE)>>32;
-#endif
-		srat_memory_affinity->memory_type = ACPI_ADDRESS_RANGE_MEMORY;
-		srat_memory_affinity->flags.enabled = 1;
-	}
 
+	ptr = build_memory_srat(ptr);
+
+	/* Build processor SRAT */
 	for (cnode=0; cnode<num_nodes; cnode++) {
 		nasid = GetNasid(cnode);
 		for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
@@ -654,12 +643,24 @@
 			srat_cpu_affinity->flags.enabled = 1;
 #if defined(SGI_SN2)
 			srat_cpu_affinity->lsapic_eid = nasid&0xffff;
-			srat_cpu_affinity->apic_id = (cpu<<4) | (nasid>>16);
+			srat_cpu_affinity->apic_id = (cpu<<4) | (nasid>>8);
 #endif
 		}
 	}
 	acpi_checksum(&acpi_srat->header, (char*)ptr - (char*)acpi_srat);
 
+	acpi_table_initx(acpi_dsdt, DSDT_SIG, 4, ACPI_DSDT_REVISION, 1);
+	acpi_checksum(acpi_dsdt, sizeof(*acpi_dsdt));
+
+	/* Set up the FADT table */
+	acpi_table_initx((struct acpi_table_header *)&acpi_fadt->header, FADT_SIG, 4, ACPI_FADT_REVISION, 1);
+	/*
+	 * We don't have legacy PC keyboard support etc.
+	 */
+	acpi_fadt->iapc_boot_arch = 0;
+	acpi_fadt->Xdsdt = (u64)__fwtab_pa(base_nasid, acpi_dsdt);
+	acpi_checksum((struct acpi_table_header *)&acpi_fadt->header,
+		      sizeof(*acpi_fadt));
 
 	/* Set up the SLIT table */
 	acpi_table_initx(&acpi_slit->header, SLIT_SIG, 4, ACPI_SLIT_REVISION, 1);
@@ -668,8 +669,10 @@
 	memset(cp, 255, acpi_slit->localities*acpi_slit->localities);
 
 	for (i=0; i<=max_nasid; i++)
+		nasid_present[i] = is_nasid_present(i);
+	for (i=0; i<=max_nasid; i++)
 		for (j=0; j<=max_nasid; j++)
-			if (nasid_present(i) && nasid_present(j))
+			if (nasid_present[i] && nasid_present[j])
 				*(cp+PROXIMITY_DOMAIN(i)*acpi_slit->localities+PROXIMITY_DOMAIN(j)) = 10 + MIN(254, 5*ABS(i-j));
 
 	cp = acpi_slit->entry + acpi_slit->localities*acpi_slit->localities;
@@ -681,7 +684,7 @@
 	sal_systab->size = sizeof(*sal_systab);
 	sal_systab->sal_rev_minor = 1;
 	sal_systab->sal_rev_major = 0;
-	sal_systab->entry_count = 3;
+	sal_systab->entry_count = 4;
 	sal_systab->sal_b_rev_major = 0x1; /* set the SN SAL rev to */
 	sal_systab->sal_b_rev_minor = 0x0; /* 1.00 */
 
@@ -730,6 +733,10 @@
 	sal_apwake->mechanism = IA64_SAL_AP_EXTERNAL_INT;
 	sal_apwake->vector = 18;
 
+	/* Setup the SAL feature descriptor */
+	sal_feature->type = SAL_DESC_PLATFORM_FEATURE;
+	sal_feature->feature_mask = IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT;
+
 	for (checksum=0, cp=(char*)sal_systab; cp < (char *)efi_memmap; ++cp)
 		checksum += *cp;
 	sal_systab->checksum = -checksum;
@@ -754,22 +761,4 @@
 	bp->console_info.orig_x = 0;
 	bp->console_info.orig_y = 24;
 	bp->fpswa = 0;
-
-	/*
-	 * Now pick the BSP & store it LID value in
-	 * a global variable. Note if BSP is greater than last cpu,
-	 * pick the last cpu.
-	 */
-	for (cnode=0; cnode<num_nodes; cnode++) {
-		for(cpu=0; cpu<CPUS_PER_NODE; cpu++) {
-			if (!IsCpuPresent(cnode, cpu))
-				continue;
-#ifdef SGI_SN2
-			bsp_lid = (GetNasid(cnode)<<16) | (cpu<<28);
-#endif
-			if (bsp-- > 0)
-				continue;
-			return;
-		}
-	}
 }
diff -urN linux-2.4.23-pre3/arch/ia64/sn/fakeprom/main.c linux-2.4.23-pre4/arch/ia64/sn/fakeprom/main.c
--- linux-2.4.23-pre3/arch/ia64/sn/fakeprom/main.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/fakeprom/main.c	2003-09-12 12:44:34.000000000 -0700
@@ -12,90 +12,60 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <asm/bitops.h>
+#include <asm/sn/simulator.h>
+#include "fpmem.h"
 
 extern void klgraph_init(void);
-void bedrock_init(int);
-void synergy_init(int, int);
-void sys_fw_init (const char *args, int arglen, int bsp);
-
-volatile int	bootmaster=0;		/* Used to pick bootmaster */
-volatile int	nasidmaster[128]={0};	/* Used to pick node/synergy masters */
-int		init_done=0;
-extern int	bsp_lid;
-
-#define get_bit(b,p)	(((*p)>>(b))&1)
+void sys_fw_init (const char *args, int arglen);
 
 int
 fmain(int lid, int bsp) {
-	int	syn, nasid, cpu;
+	int	nasid, cpu, mynasid, mycpu, bootmaster;
+
+	/*
+	 * * Pass the parameter base address to the build_efi_xxx routines.
+	 */
+#if defined(SGI_SN2)
+	build_init(0x3000000000UL | ((long)base_nasid<<38));
+#endif
 
 	/*
 	 * First lets figure out who we are. This is done from the
 	 * LID passed to us.
 	 */
-	nasid = (lid>>16)&0xfff;
-	cpu = (lid>>28)&3;
-	syn = 0;
-	
+	mynasid = (lid>>16)&0xfff;
+	mycpu = (lid>>28)&3;
+
 	/*
-	 * Now pick a nasid master to initialize Bedrock registers.
+	 * Determine if THIS cpu is the bootmaster. The <bsp> parameter
+	 * is the logical cpu of the bootmaster. Cpus are numbered
+	 * low-to-high nasid/lid.
 	 */
-	if (test_and_set_bit(8, &nasidmaster[nasid]) == 0) {
-		bedrock_init(nasid);
-		test_and_set_bit(9, &nasidmaster[nasid]);
-	} else
-		while (get_bit(9, &nasidmaster[nasid]) == 0);
+	GetLogicalCpu(bsp, &nasid, &cpu);
+	bootmaster = (mynasid == nasid) && (mycpu == cpu);
 	
-
 	/*
-	 * Now pick a BSP & finish init.
+	 * Initialize SAL & EFI tables.
+	 *   Note: non-bootmaster cpus will return to the slave loop 
+	 *   in fpromasm.S. They spin there until they receive an
+	 *   external interrupt from the master cpu.
 	 */
-	if (test_and_set_bit(0, &bootmaster) == 0) {
-		sys_fw_init(0, 0, bsp);
-		test_and_set_bit(1, &bootmaster);
-	} else
-		while (get_bit(1, &bootmaster) == 0);
-
-	return (lid == bsp_lid);
-}
-
-
-void
-bedrock_init(int nasid)
-{
-	nasid = nasid;		/* to quiet gcc */
+	if (bootmaster) {
 #if 0
-	/*
-	 * Undef if you need fprom to generate a 1 node klgraph
-	 * information .. only works for 1 node for nasid 0.
-	 */
-	klgraph_init();
+		/*
+		 * Undef if you need fprom to generate a 1 node klgraph
+		 * information .. only works for 1 node for nasid 0.
+		 */
+		klgraph_init();
 #endif
-}
-
-
-void
-synergy_init(int nasid, int syn)
-{
-	long	*base;
-	long	off;
+		sys_fw_init(0, 0);
+	}
 
-	/*
-	 * Enable all FSB flashed interrupts.
-	 * I'd really like defines for this......
-	 */
-	base = (long*)0x80000e0000000000LL;		/* base of synergy regs */
-	for (off = 0x2a0; off < 0x2e0; off+=8)		/* offset for VEC_MASK_{0-3}_A/B */
-		*(base+off/8) = -1LL;
-
-	/*
-	 * Set the NASID in the FSB_CONFIG register.
-	 */
-	base = (long*)0x80000e0000000450LL;
-	*base = (long)((nasid<<16)|(syn<<9));
+	return (bootmaster);
 }
 
 
+
 /* Why isnt there a bcopy/memcpy in lib64.a */
 
 void* 
diff -urN linux-2.4.23-pre3/arch/ia64/sn/fakeprom/make_textsym linux-2.4.23-pre4/arch/ia64/sn/fakeprom/make_textsym
--- linux-2.4.23-pre3/arch/ia64/sn/fakeprom/make_textsym	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/sn/fakeprom/make_textsym	2003-09-12 12:44:34.000000000 -0700
@@ -0,0 +1,168 @@
+#!/bin/sh
+#
+# Build a textsym file for use in the Arium ITP probe.
+#
+#
+# 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.
+#
+# Copyright (c) 2001-2003 Silicon Graphics, Inc.  All rights reserved.
+#
+
+help() {
+cat <<END
+Build a WinDD "symtxt" file for use with the Arium ECM-30 probe.
+
+	Usage: $0 [<vmlinux file> [<output file>]]
+		If no input file is specified, it defaults to vmlinux.
+		If no output file name is specified, it defaults to "textsym".
+END
+exit 1
+}
+
+err () {
+	echo "ERROR - $*" >&2
+	exit 1
+}
+
+
+OPTS="H"
+while getopts "$OPTS" c ; do
+	case $c in
+		H)  help;;
+		\?) help;;
+	esac
+
+done
+shift `expr $OPTIND - 1`
+
+if [ -f /usr/bin/ia64-linux-objdump ] ; then
+	OBJDUMP=${OBJDUMP:-/usr/bin/ia64-linux-objdump}
+else
+	OBJDUMP=${OBJDUMP:-objdump}
+fi
+
+LINUX=${1:-vmlinux}
+TEXTSYM=${2:-${LINUX}.sym}
+TMPSYM=${2:-${LINUX}.sym.tmp}
+trap "/bin/rm -f $TMPSYM" 0
+
+[ -f $VMLINUX ] || help
+
+$OBJDUMP -t $LINUX | egrep -v '__ks' | sort > $TMPSYM
+
+# pipe everything thru sort
+echo "TEXTSYM V1.0" >$TEXTSYM
+(cat <<END 
+GLOBAL | e000000004400000 | CODE | VEC_VHPT_Translation_0000
+GLOBAL | e000000004400400 | CODE | VEC_ITLB_0400
+GLOBAL | e000000004400800 | CODE | VEC_DTLB_0800
+GLOBAL | e000000004400c00 | CODE | VEC_Alt_ITLB_0c00
+GLOBAL | e000000004401000 | CODE | VEC_Alt_DTLB_1000
+GLOBAL | e000000004401400 | CODE | VEC_Data_nested_TLB_1400
+GLOBAL | e000000004401800 | CODE | VEC_Instruction_Key_Miss_1800
+GLOBAL | e000000004401c00 | CODE | VEC_Data_Key_Miss_1c00
+GLOBAL | e000000004402000 | CODE | VEC_Dirty-bit_2000
+GLOBAL | e000000004402400 | CODE | VEC_Instruction_Access-bit_2400
+GLOBAL | e000000004402800 | CODE | VEC_Data_Access-bit_2800
+GLOBAL | e000000004402c00 | CODE | VEC_Break_instruction_2c00
+GLOBAL | e000000004403000 | CODE | VEC_External_Interrupt_3000
+GLOBAL | e000000004403400 | CODE | VEC_Reserved_3400
+GLOBAL | e000000004403800 | CODE | VEC_Reserved_3800
+GLOBAL | e000000004403c00 | CODE | VEC_Reserved_3c00
+GLOBAL | e000000004404000 | CODE | VEC_Reserved_4000
+GLOBAL | e000000004404400 | CODE | VEC_Reserved_4400
+GLOBAL | e000000004404800 | CODE | VEC_Reserved_4800
+GLOBAL | e000000004404c00 | CODE | VEC_Reserved_4c00
+GLOBAL | e000000004405000 | CODE | VEC_Page_Not_Present_5000
+GLOBAL | e000000004405100 | CODE | VEC_Key_Permission_5100
+GLOBAL | e000000004405200 | CODE | VEC_Instruction_Access_Rights_5200
+GLOBAL | e000000004405300 | CODE | VEC_Data_Access_Rights_5300
+GLOBAL | e000000004405400 | CODE | VEC_General_Exception_5400
+GLOBAL | e000000004405500 | CODE | VEC_Disabled_FP-Register_5500
+GLOBAL | e000000004405600 | CODE | VEC_Nat_Consumption_5600
+GLOBAL | e000000004405700 | CODE | VEC_Speculation_5700
+GLOBAL | e000000004405800 | CODE | VEC_Reserved_5800
+GLOBAL | e000000004405900 | CODE | VEC_Debug_5900
+GLOBAL | e000000004405a00 | CODE | VEC_Unaligned_Reference_5a00
+GLOBAL | e000000004405b00 | CODE | VEC_Unsupported_Data_Reference_5b00
+GLOBAL | e000000004405c00 | CODE | VEC_Floating-Point_Fault_5c00
+GLOBAL | e000000004405d00 | CODE | VEC_Floating_Point_Trap_5d00
+GLOBAL | e000000004405e00 | CODE | VEC_Lower_Privilege_Tranfer_Trap_5e00
+GLOBAL | e000000004405f00 | CODE | VEC_Taken_Branch_Trap_5f00
+GLOBAL | e000000004406000 | CODE | VEC_Single_Step_Trap_6000
+GLOBAL | e000000004406100 | CODE | VEC_Reserved_6100
+GLOBAL | e000000004406200 | CODE | VEC_Reserved_6200
+GLOBAL | e000000004406300 | CODE | VEC_Reserved_6300
+GLOBAL | e000000004406400 | CODE | VEC_Reserved_6400
+GLOBAL | e000000004406500 | CODE | VEC_Reserved_6500
+GLOBAL | e000000004406600 | CODE | VEC_Reserved_6600
+GLOBAL | e000000004406700 | CODE | VEC_Reserved_6700
+GLOBAL | e000000004406800 | CODE | VEC_Reserved_6800
+GLOBAL | e000000004406900 | CODE | VEC_IA-32_Exeception_6900
+GLOBAL | e000000004406a00 | CODE | VEC_IA-32_Intercept_6a00
+GLOBAL | e000000004406b00 | CODE | VEC_IA-32_Interrupt_6b00
+GLOBAL | e000000004406c00 | CODE | VEC_Reserved_6c00
+GLOBAL | e000000004406d00 | CODE | VEC_Reserved_6d00
+GLOBAL | e000000004406e00 | CODE | VEC_Reserved_6e00
+GLOBAL | e000000004406f00 | CODE | VEC_Reserved_6f00
+GLOBAL | e000000004407000 | CODE | VEC_Reserved_7000
+GLOBAL | e000000004407100 | CODE | VEC_Reserved_7100
+GLOBAL | e000000004407200 | CODE | VEC_Reserved_7200
+GLOBAL | e000000004407300 | CODE | VEC_Reserved_7300
+GLOBAL | e000000004407400 | CODE | VEC_Reserved_7400
+GLOBAL | e000000004407500 | CODE | VEC_Reserved_7500
+GLOBAL | e000000004407600 | CODE | VEC_Reserved_7600
+GLOBAL | e000000004407700 | CODE | VEC_Reserved_7700
+GLOBAL | e000000004407800 | CODE | VEC_Reserved_7800
+GLOBAL | e000000004407900 | CODE | VEC_Reserved_7900
+GLOBAL | e000000004407a00 | CODE | VEC_Reserved_7a00
+GLOBAL | e000000004407b00 | CODE | VEC_Reserved_7b00
+GLOBAL | e000000004407c00 | CODE | VEC_Reserved_7c00
+GLOBAL | e000000004407d00 | CODE | VEC_Reserved_7d00
+GLOBAL | e000000004407e00 | CODE | VEC_Reserved_7e00
+GLOBAL | e000000004407f00 | CODE | VEC_Reserved_7f00
+END
+
+
+awk '
+/ _start$/ {start=1}
+/ start_ap$/ {start=1}
+/__start_gate_section/ {start=1}
+/^e0000000/ {
+	if ($4 == ".kdb")
+		next
+	if (start && substr($NF,1,1) != "0") {
+		type = substr($0,26,5)
+		if (type == ".text")
+			printf "GLOBAL | %s | CODE | %s\n", $1, $NF
+		else {
+			n = 0
+			s = $(NF-1)
+			while (length(s) > 0) {
+				n = n*16 + (index("0123456789abcdef", substr(s,1,1)) - 1)
+				s = substr(s,2)
+			}
+			printf "GLOBAL | %s | DATA | %s | %d\n", $1, $NF, n
+		}
+	}
+	if($NF == "_end") 
+		exit
+
+}
+' $TMPSYM ) | egrep -v " __device| __vendor" | awk '
+/GLOBAL/ {
+	print $0
+	/* 38 bits of sn2 physical addrs, need addr space bits */
+	if (substr($0,19,1) == "4")
+		print substr($0,1,9) "3004" substr($0,20,16) "Phy_" substr($0,36)
+	else
+		print substr($0,1,9) "3005" substr($0,20,16) "Phy_" substr($0,36)
+
+} ' | sort -k3 >>$TEXTSYM
+
+N=`wc -l $TEXTSYM|awk '{print $1}'`
+echo "Generated TEXTSYM file" >&2
+echo "  $LINUX --> $TEXTSYM" >&2
+echo "  Found $N symbols" >&2
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/Makefile linux-2.4.23-pre4/arch/ia64/sn/io/Makefile
--- linux-2.4.23-pre3/arch/ia64/sn/io/Makefile	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/Makefile	2003-09-12 12:44:34.000000000 -0700
@@ -13,8 +13,9 @@
 
 O_TARGET := sgiio.o
  
-obj-y :=	sgi_if.o xswitch.o sgi_io_sim.o \
-		cdl.o io.o
+export-objs := snia_if.o
+
+obj-y :=	sgi_if.o xswitch.o cdl.o io.o snia_if.o
 
 obj-y		+= sn2/snio.o machvec/snio.o \
 	           drivers/snio.o platform_init/snio.o
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/drivers/Makefile linux-2.4.23-pre4/arch/ia64/sn/io/drivers/Makefile
--- linux-2.4.23-pre3/arch/ia64/sn/io/drivers/Makefile	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/drivers/Makefile	2003-09-12 12:44:34.000000000 -0700
@@ -11,7 +11,7 @@
 
 O_TARGET := snio.o
 
-obj-y				+= hubdev.o ioconfig_bus.o ifconfig_net.o
+obj-y				+= ioconfig_bus.o ifconfig_net.o
 
 obj-$(CONFIG_PCIBA)		+= pciba.o
 
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/drivers/ifconfig_net.c linux-2.4.23-pre4/arch/ia64/sn/io/drivers/ifconfig_net.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/drivers/ifconfig_net.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/drivers/ifconfig_net.c	2003-09-12 12:44:34.000000000 -0700
@@ -22,6 +22,7 @@
 #include <linux/skbuff.h>
 
 #include <asm/sn/sgi.h>
+#include <asm/uaccess.h>
 #include <linux/devfs_fs.h>
 #include <linux/devfs_fs_kernel.h>
 #include <asm/io.h>
@@ -37,8 +38,11 @@
 /*
  * Some Global definitions.
  */
-static devfs_handle_t ifconfig_net_handle;
+static vertex_hdl_t ifconfig_net_handle;
 static unsigned long ifconfig_net_debug;
+static struct ifname_MAC *new_devices;
+static struct ifname_num *ifname_num;
+
 
 /*
  * ifconfig_net_open - Opens the special device node "/devhw/.ifconfig_net".
@@ -189,8 +193,7 @@
 	char temp[64];
 #endif
 	struct ifname_MAC *ifname_MAC;
-	struct ifname_MAC *new_devices, *temp_new_devices;
-	struct ifname_num *ifname_num;
+	struct ifname_MAC *temp_new_devices;
 	unsigned long size;
 
 
@@ -204,14 +207,24 @@
 	 */
 	ifname_num = (struct ifname_num *) kmalloc(sizeof(struct ifname_num), 
 			GFP_KERNEL);
-	copy_from_user( ifname_num, (char *) arg, sizeof(struct ifname_num));
+	if (copy_from_user( ifname_num, (char *) arg, sizeof(struct ifname_num)))
+		return -EFAULT;
 	size = ifname_num->size;
 	kfree(ifname_num);
 	ifname_num = (struct ifname_num *) kmalloc(size, GFP_KERNEL);
+	if (ifname_num <= 0)
+		return -ENOMEM;
 	ifname_MAC = (struct ifname_MAC *) ((char *)ifname_num + (sizeof(struct ifname_num)) );
 
-	copy_from_user( ifname_num, (char *) arg, size);
+	if (copy_from_user( ifname_num, (char *) arg, size)){
+		kfree(ifname_num);
+		return -EFAULT;
+	}
 	new_devices =  kmalloc(size - sizeof(struct ifname_num), GFP_KERNEL);
+	if (new_devices <= 0){
+		kfree(ifname_num);
+		return -ENOMEM;
+	}
 	temp_new_devices = new_devices;
 
 	memset(new_devices, 0, size - sizeof(struct ifname_num));
@@ -257,10 +270,10 @@
 	/*
 	 * Copy back to the User Buffer area any new devices encountered.
 	 */
-	copy_to_user((char *)arg + (sizeof(struct ifname_num)), new_devices, 
-			size - sizeof(struct ifname_num));
+	kfree(new_devices);
+	return copy_to_user((char *)arg + (sizeof(struct ifname_num)), new_devices, 
+			size - sizeof(struct ifname_num))?-EFAULT:0;
 
-	return(0);
 
 }
 
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/drivers/ioconfig_bus.c linux-2.4.23-pre4/arch/ia64/sn/io/drivers/ioconfig_bus.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/drivers/ioconfig_bus.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/drivers/ioconfig_bus.c	2003-09-12 12:44:34.000000000 -0700
@@ -17,6 +17,8 @@
 #include <linux/pci.h>
 
 #include <asm/sn/sgi.h>
+#include <asm/uaccess.h>
+
 #include <linux/devfs_fs.h>
 #include <linux/devfs_fs_kernel.h>
 #include <asm/io.h>
@@ -36,6 +38,7 @@
  */
 static vertex_hdl_t ioconfig_bus_handle;
 static unsigned long ioconfig_bus_debug;
+static struct ioconfig_parm parm;
 
 #ifdef IOCONFIG_BUS_DEBUG
 #define DBG(x...)	printk(x)
@@ -162,8 +165,13 @@
 	struct ascii_moduleid *moduleid;
 
 	line = kmalloc(256, GFP_KERNEL);
+	if (line <= 0)
+		BUG(); /* Do not want to continue system boot .. */
 	memset(line, 0,256);
 	name = kmalloc(125, GFP_KERNEL);
+	if (name <= 0){
+		BUG(); /* Do not want to continue system boot .. */
+	}
 	memset(name, 0, 125);
 	moduleid = table;
 	current = file_contents;
@@ -252,6 +260,9 @@
 		ret_stuff.v0, (void *)ioconfig_file, (int)ioconfig_file_size);
 
 	ioconfig_bus_table = kmalloc( 512, GFP_KERNEL );
+	if (ioconfig_bus_table <= 0)
+		BUG(); /* Seriously, we should not be out of memory at init */
+
 	memset(ioconfig_bus_table, 0, 512);
 
 	/*
@@ -264,7 +275,6 @@
 		DBG("ioconfig_bus_init: Kernel Options given.\n");
 		(void) build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table);
 		(void) dump_ioconfig_table();
-		return;
 	}
 
 	if (ioconfig_activated) {
@@ -305,16 +315,20 @@
         unsigned int cmd, unsigned long arg)
 {
 
-	struct ioconfig_parm parm;
-
+	int length;
 	/*
 	 * Copy in the parameters.
 	 */
-	copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm));
+	length = copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm));
+	if (length <= 0)
+		return -EFAULT;
 	parm.number = free_entry - new_entry;
 	parm.ioconfig_activated = ioconfig_activated;
-	copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm));
-	copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct  ascii_moduleid) * (free_entry - new_entry));
+	if (copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm)))
+		return -EFAULT;
+
+	if (copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct  ascii_moduleid) * (free_entry - new_entry)))
+		return -EFAULT;
 
 	return 0;
 }
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/drivers/pciba.c linux-2.4.23-pre4/arch/ia64/sn/io/drivers/pciba.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/drivers/pciba.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/drivers/pciba.c	2003-09-12 12:44:34.000000000 -0700
@@ -341,8 +341,8 @@
 	TRACE();
 	
 	node = kmalloc(sizeof(struct node_data), GFP_KERNEL);
-	if (node == NULL)
-		return NULL;
+	if (node <= 0)
+		return node;
 	list_add(&node->global_node_list, &global_node_list);
 	return node;
 }
@@ -455,7 +455,7 @@
            if present */
 	if (pci_resource_len(dev, PCI_ROM_RESOURCE) != 0) {
 		nd = new_node();
-		if (nd == NULL)
+		if (nd <= 0)
 			return failure;
 		node_devfs_handle = hwgraph_register(device_dir_handle, "rom",
 						   0, DEVFS_FL_NONE, 0, 0,
@@ -478,7 +478,7 @@
            and free DMA buffers, as well as memory map those
            buffers. */
 	nd = new_node();
-	if (nd == NULL)
+	if (nd <= 0)
 		return failure;
 	node_devfs_handle =
 		hwgraph_register(device_dir_handle, "dma", 0, DEVFS_FL_NONE,
@@ -763,7 +763,7 @@
 
 		dma_alloc = (struct dma_allocation *)
 			kmalloc(sizeof(struct dma_allocation), GFP_KERNEL);
-		if (dma_alloc == NULL)
+		if (dma_alloc <= 0)
 			return -ENOMEM;
 
 		dma_alloc->size = (size_t)argv;
@@ -899,7 +899,7 @@
 	/* the __pa macro is intended for region 7 on IA64, so it
 	   doesn't work for region 6 */
   	/* pci_pa = __pa(pci_va); */
-	/* should be replaced by __tpa or equivalent (preferably a
+	/* should be replaced by ia64_tpa or equivalent (preferably a
 	   generic equivalent) */
 	pci_pa = pci_va & ~0xe000000000000000ul;
 	DPRINTF("PCI base at physical address %lx\n", pci_pa);
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/hwgdfs/hcl.c linux-2.4.23-pre4/arch/ia64/sn/io/hwgdfs/hcl.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/hwgdfs/hcl.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/hwgdfs/hcl.c	2003-09-12 12:44:34.000000000 -0700
@@ -233,6 +233,15 @@
 __setup("hcl=", hcl_setup);
 
 
+int
+hwgraph_generate_path(
+        vertex_hdl_t		de,
+        char                    *path,
+        int                     buflen)
+{
+	return (devfs_generate_path(de, path, buflen));
+}
+
 /*
  * Set device specific "fast information".
  *
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/hwgdfs/hcl_util.c linux-2.4.23-pre4/arch/ia64/sn/io/hwgdfs/hcl_util.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/hwgdfs/hcl_util.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/hwgdfs/hcl_util.c	2003-09-12 12:44:34.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: hcl_util.c,v 1.3 2003/04/24 13:59:39 pfg Exp $
+/* $Id: hcl_util.c,v 1.4 2003/07/31 12:24:27 edwardsg Exp $
  *
  * 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
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/hwgfs/hcl.c linux-2.4.23-pre4/arch/ia64/sn/io/hwgfs/hcl.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/hwgfs/hcl.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/hwgfs/hcl.c	2003-09-12 12:44:34.000000000 -0700
@@ -28,16 +28,12 @@
 #include <asm/sn/labelcl.h>
 #include <asm/sn/simulator.h>
 
-#define HCL_NAME "SGI-HWGRAPH COMPATIBILITY DRIVER"
-#define HCL_TEMP_NAME "HCL_TEMP_NAME_USED_FOR_HWGRAPH_VERTEX_CREATE"
-#define HCL_TEMP_NAME_LEN 44 
-#define HCL_VERSION "1.0"
-
 #define vertex_hdl_t hwgfs_handle_t
+
 vertex_hdl_t hwgraph_root;
 vertex_hdl_t linux_busnum;
-
 extern void pci_bus_cvlink_init(void);
+unsigned long hwgraph_debug_mask = 0;
 
 /*
  * Debug flag definition.
@@ -157,7 +153,7 @@
 	 */
 	rv = hwgraph_path_add(NULL, EDGE_LBL_HW, &hwgraph_root);
 	if (rv)
-		printk ("WARNING: init_hcl: Failed to create hwgraph_root. Error = %d.\n", rv);
+		panic("init_hcl: Failed to create hwgraph_root.\n");
 
 	/*
 	 * Create the hcl driver to support inventory entry manipulations.
@@ -235,6 +231,15 @@
 __setup("hcl=", hcl_setup);
 
 
+int
+hwgraph_generate_path(
+        vertex_hdl_t            de,
+        char                    *path,
+        int                     buflen)
+{
+        return (hwgfs_generate_path(de, path, buflen));
+}
+
 /*
  * Set device specific "fast information".
  *
@@ -492,39 +497,6 @@
 	return(0);
 }
 
-#if 0
-/*
- * hwgraph_edge_add - This routines has changed from the original conext.
- * All it does now is to create a symbolic link from "from" to "to".
- */
-/* ARGSUSED */
-int
-hwgraph_edge_add(vertex_hdl_t from, vertex_hdl_t to, char *name)
-{
-
-	char *path, *link;
-	vertex_hdl_t handle = NULL;
-	int rv, i;
-
-	handle = hwgfs_find_handle(from, name, 0, 0, 0, 1);
-	if (handle) {
-		return(0);
-	}
-
-	path = kmalloc(1024, GFP_KERNEL);
-	memset(path, 0x0, 1024);
-	link = kmalloc(1024, GFP_KERNEL);
-	memset(path, 0x0, 1024);
-	i = hwgfs_generate_path (to, link, 1024);
-	rv = hwgfs_mk_symlink (from, (const char *)name, 
-			       DEVFS_FL_DEFAULT, link,
-			       &handle, NULL);
-	return(0);
-
-
-}
-#endif
-
 int
 hwgraph_edge_add(vertex_hdl_t from, vertex_hdl_t to, char *name)
 {
@@ -916,6 +888,43 @@
 	return(GRAPH_ILLEGAL_REQUEST);
 }
 
+void
+hwgraph_debug(char *file, char * function, int line, vertex_hdl_t vhdl1, vertex_hdl_t vhdl2, char *format, ...)
+{
+
+	int pos;
+	char *hwpath;
+	va_list ap;
+
+	if ( !hwgraph_debug_mask )
+		return;
+
+	hwpath = kmalloc(MAXDEVNAME, GFP_KERNEL);
+	if (!hwpath)
+		BUG();
+
+	printk("HWGRAPH_DEBUG %s %s %d : ", file, function, line);
+
+	if (vhdl1){
+		memset(hwpath, 0, MAXDEVNAME);
+		pos = hwgfs_generate_path(vhdl1, hwpath, MAXDEVNAME);
+		printk("vhdl1 = %s : ", &hwpath[pos]);
+	}
+
+	if (vhdl2){
+		memset(hwpath, 0, MAXDEVNAME);
+		pos = hwgfs_generate_path(vhdl2, hwpath, MAXDEVNAME);
+		printk("vhdl2 = %s :", &hwpath[pos]);
+	}
+
+	memset(hwpath, 0, MAXDEVNAME);
+        va_start(ap, format);
+        vsnprintf(hwpath, 500, format, ap);
+        va_end(ap);
+	hwpath[MAXDEVNAME -1] = (char)0; /* Just in case. */
+        printk(" %s", hwpath);
+	kfree(hwpath);
+}
 
 EXPORT_SYMBOL(hwgraph_mk_dir);
 EXPORT_SYMBOL(hwgraph_path_add);
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/hwgfs/hcl_util.c linux-2.4.23-pre4/arch/ia64/sn/io/hwgfs/hcl_util.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/hwgfs/hcl_util.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/hwgfs/hcl_util.c	2003-09-12 12:44:34.000000000 -0700
@@ -22,7 +22,10 @@
 #include <asm/sn/nodepda.h>
 
 static vertex_hdl_t hwgraph_all_cnodes = GRAPH_VERTEX_NONE;
+static vertex_hdl_t hwgraph_all_cpuids = GRAPH_VERTEX_NONE;
 extern vertex_hdl_t hwgraph_root;
+extern int maxcpus;
+
 
 
 /*
@@ -96,9 +99,6 @@
 	}
 }
 
-static vertex_hdl_t hwgraph_all_cpuids = GRAPH_VERTEX_NONE;
-extern int maxcpus;
-
 void
 mark_cpuvertex_as_cpu(vertex_hdl_t vhdl, cpuid_t cpuid)
 {
@@ -161,6 +161,7 @@
 		(void)hwgraph_edge_add( hwgraph_all_cnodes,
 					vhdl,
 					cnodeid_buffer);
+		HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, hwgraph_all_cnodes, NULL, "Creating path vhdl1\n"));
 	}
 }
 
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/hwgfs/interface.c linux-2.4.23-pre4/arch/ia64/sn/io/hwgfs/interface.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/hwgfs/interface.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/hwgfs/interface.c	2003-09-12 12:44:34.000000000 -0700
@@ -38,7 +38,7 @@
 		memcpy(buf, *path, len);
 		buf[len] = '\0';
 
-		error = link_path_walk(buf, nd); 
+		error = path_walk(buf, nd); 
 		if (unlikely(error))
 			return error;
 
@@ -84,7 +84,7 @@
 	if (unlikely(error))
 		return error;
 
-	error = link_path_walk(name, &nd);
+	error = path_walk(name, &nd);
 	if (unlikely(error))
 		return error;
 
@@ -275,7 +275,7 @@
 	nd.dentry = dget(base ? base : hwgfs_vfsmount->mnt_sb->s_root);
 	nd.flags = LOOKUP_POSITIVE | (traverse_symlinks ? LOOKUP_FOLLOW : 0);
 
-	error = link_path_walk(name, &nd);
+	error = path_walk(name, &nd);
 	if (likely(!error)) {
 		dentry = nd.dentry;
 		path_release(&nd);		/* stale data from here! */
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/io.c linux-2.4.23-pre4/arch/ia64/sn/io/io.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/io.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/io.c	2003-09-12 12:44:34.000000000 -0700
@@ -86,7 +86,7 @@
 	}
 	hub_set_piomode(nasid, HUB_PIO_CONVEYOR);
 
-	mutex_spinlock_init(&hubinfo->h_bwlock);
+	spin_lock_init(&hubinfo->h_bwlock);
 /*
  * If this lock can be acquired from interrupts or bh's, add SV_INTS or SV_BHS,
  * respectively, to the flags here.
@@ -123,7 +123,6 @@
 	int bigwin, free_bw_index;
 	nasid_t nasid;
 	volatile hubreg_t junk;
-	unsigned long s;
 	caddr_t kvaddr;
 #ifdef PIOMAP_UNC_ACC_SPACE
 	uint64_t addr;
@@ -171,7 +170,7 @@
 	 */
 tryagain:
 	free_bw_index = -1;
-	s = mutex_spinlock(&hubinfo->h_bwlock);
+	spin_lock(&hubinfo->h_bwlock);
 	for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) {
 		bw_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin);
 
@@ -191,7 +190,7 @@
 		if ( xtalk_addr == bw_piomap->hpio_xtalk_info.xp_xtalk_addr &&
 		     widget == bw_piomap->hpio_xtalk_info.xp_target) {
 			bw_piomap->hpio_holdcnt++;
-			mutex_spinunlock(&hubinfo->h_bwlock, s);
+			spin_unlock(&hubinfo->h_bwlock);
 			return(bw_piomap);
 		}
 	}
@@ -265,7 +264,7 @@
 		bw_piomap->hpio_flags |= HUB_PIOMAP_IS_VALID;
 
 done:
-	mutex_spinunlock(&hubinfo->h_bwlock, s);
+	spin_unlock(&hubinfo->h_bwlock);
 	return(bw_piomap);
 }
 
@@ -285,7 +284,6 @@
 	vertex_hdl_t hubv;
 	hubinfo_t hubinfo;
 	nasid_t nasid;
-	unsigned long s;
 
 	/* 
 	 * Small windows are permanently mapped to corresponding widgets,
@@ -301,7 +299,7 @@
 	hubinfo_get(hubv, &hubinfo);
 	nasid = hubinfo->h_nasid;
 
-	s = mutex_spinlock(&hubinfo->h_bwlock);
+	spin_lock(&hubinfo->h_bwlock);
 
 	/*
 	 * If this is the last hold on this mapping, free it.
@@ -319,7 +317,7 @@
 		(void)sv_signal(&hubinfo->h_bwwait);
 	}
 
-	mutex_spinunlock(&hubinfo->h_bwlock, s);
+	spin_unlock(&hubinfo->h_bwlock);
 }
 
 /*
@@ -440,7 +438,7 @@
 hub_dmamap_free(hub_dmamap_t hub_dmamap)
 {
 	hub_dmamap->hdma_flags &= ~HUB_DMAMAP_IS_VALID;
-	kern_free(hub_dmamap);
+	kfree(hub_dmamap);
 }
 
 /*
@@ -461,12 +459,9 @@
 	if (dmamap->hdma_flags & HUB_DMAMAP_USED) {
 	    /* If the map is FIXED, re-use is OK. */
 	    if (!(dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
+		char name[MAXDEVNAME];
 		vhdl = dmamap->hdma_xtalk_info.xd_dev;
-#if defined(SUPPORT_PRINTING_V_FORMAT)
-		printk(KERN_WARNING  "%v: hub_dmamap_addr re-uses dmamap.\n",vhdl);
-#else
-		printk(KERN_WARNING  "%p: hub_dmamap_addr re-uses dmamap.\n", (void *)vhdl);
-#endif
+		printk(KERN_WARNING  "%s: hub_dmamap_addr re-uses dmamap.\n", vertex_to_name(vhdl, name, MAXDEVNAME));
 	    }
 	} else {
 		dmamap->hdma_flags |= HUB_DMAMAP_USED;
@@ -494,12 +489,9 @@
 	if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) {
 	    /* If the map is FIXED, re-use is OK. */
 	    if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
+		char name[MAXDEVNAME];
 		vhdl = hub_dmamap->hdma_xtalk_info.xd_dev;
-#if defined(SUPPORT_PRINTING_V_FORMAT)
-		printk(KERN_WARNING  "%v: hub_dmamap_list re-uses dmamap\n",vhdl);
-#else
-		printk(KERN_WARNING  "%p: hub_dmamap_list re-uses dmamap\n", (void *)vhdl);
-#endif
+		printk(KERN_WARNING  "%s: hub_dmamap_list re-uses dmamap\n", vertex_to_name(vhdl, name, MAXDEVNAME));
 	    }
 	} else {
 		hub_dmamap->hdma_flags |= HUB_DMAMAP_USED;
@@ -523,12 +515,9 @@
 	} else {
 	    /* If the map is FIXED, re-done is OK. */
 	    if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) {
+		char name[MAXDEVNAME];
 		vhdl = hub_dmamap->hdma_xtalk_info.xd_dev;
-#if defined(SUPPORT_PRINTING_V_FORMAT)
-		printk(KERN_WARNING  "%v: hub_dmamap_done already done with dmamap\n",vhdl);
-#else
-		printk(KERN_WARNING  "%p: hub_dmamap_done already done with dmamap\n", (void *)vhdl);
-#endif
+		printk(KERN_WARNING  "%s: hub_dmamap_done already done with dmamap\n", vertex_to_name(vhdl, name, MAXDEVNAME));
 	    }
 	}
 }
@@ -589,6 +578,18 @@
 }
 
 
+int
+hub_dma_enabled(vertex_hdl_t xconn_vhdl)
+{
+	return(0);
+}
+
+int
+hub_error_devenable(vertex_hdl_t xconn_vhdl, int devnum, int error_code)
+{
+	return(0);
+}
+
 
 /* CONFIGURATION MANAGEMENT */
 
@@ -807,3 +808,80 @@
 	(xtalk_provider_shutdown_f *)	hub_provider_shutdown,
 };
 
+/*
+ * per_ice_init
+ *
+ *      This code is executed once for each Ice chip.
+ */
+void
+per_ice_init(cnodeid_t cnode)
+{
+
+        /* Initialize error interrupts for this ice. */
+	printk("per_ice_init: We need to init ice here ....!\n");
+        /* ice_error_init(cnode); */
+
+}
+/*
+ * per_hub_init
+ *
+ *	This code is executed once for each Hub chip.
+ */
+void
+per_hub_init(cnodeid_t cnode)
+{
+	nasid_t		nasid;
+	nodepda_t	*npdap;
+	ii_icmr_u_t	ii_icmr;
+	ii_ibcr_u_t	ii_ibcr;
+	ii_ilcsr_u_t	ii_ilcsr;
+
+	nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+	ASSERT(nasid != INVALID_NASID);
+	ASSERT(NASID_TO_COMPACT_NODEID(nasid) == cnode);
+
+	npdap = NODEPDA(cnode);
+
+	/* Disable the request and reply errors. */
+	REMOTE_HUB_S(nasid, IIO_IWEIM, 0xC000);
+
+	/*
+	 * Set the total number of CRBs that can be used.
+	 */
+	ii_icmr.ii_icmr_regval= 0x0;
+	ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf;
+	if (enable_shub_wars_1_1() ) {
+		// Set bit one of ICMR to prevent II from sending interrupt for II bug.
+		ii_icmr.ii_icmr_regval |= 0x1;
+	}
+	REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval);
+
+	/*
+	 * Set the number of CRBs that both of the BTEs combined
+	 * can use minus 1.
+	 */
+	ii_ibcr.ii_ibcr_regval= 0x0;
+	ii_ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
+	if (ii_ilcsr.ii_ilcsr_fld_s.i_llp_stat & LNK_STAT_WORKING) {
+	    ii_ibcr.ii_ibcr_fld_s.i_count = 0x8;
+	} else {
+	    /*
+	     * if the LLP is down, there is no attached I/O, so
+	    * give BTE all the CRBs.
+	    */
+	    ii_ibcr.ii_ibcr_fld_s.i_count = 0x14;
+	}
+	REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval);
+
+	/*
+	 * Set CRB timeout to be 10ms.
+	 */
+	REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff );
+	REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
+
+	/* Initialize error interrupts for this hub. */
+	hub_error_init(cnode);
+}
+
+
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/machvec/iomv.c linux-2.4.23-pre4/arch/ia64/sn/io/machvec/iomv.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/machvec/iomv.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/machvec/iomv.c	2003-09-12 12:44:34.000000000 -0700
@@ -32,7 +32,6 @@
 		return( (void *)  (port | __IA64_UNCACHED_OFFSET));
 	} else {
 		/* but the simulator uses them... */
-		unsigned long io_base;
 		unsigned long addr;
  
 		/*
@@ -40,13 +39,9 @@
  		 * for accessing registers in bedrock local block
  		 * (so we don't do port&0xfff)
  		 */
-		if ((port >= 0x1f0 && port <= 0x1f7) ||
-			port == 0x3f6 || port == 0x3f7) {
-			io_base = (0xc000000fcc000000 | ((unsigned long)get_nasid() << 38));
-			addr = io_base | ((port >> 2) << 12) | (port & 0xfff);
-		} else {
-			addr = __ia64_get_io_port_base() | ((port >> 2) << 2);
-		}
+		addr = 0xc0000087cc000000 | ((port >> 2) << 12);
+		if ((port >= 0x1f0 && port <= 0x1f7) || port == 0x3f6 || port == 0x3f7)
+			addr |= port;
 		return(void *) addr;
 	}
 }
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/machvec/pci.c linux-2.4.23-pre4/arch/ia64/sn/io/machvec/pci.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/machvec/pci.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/machvec/pci.c	2003-09-12 12:44:34.000000000 -0700
@@ -130,13 +130,6 @@
 	if ( dev == (struct pci_dev *)0 ) {
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	}
-	/* 
-	 * if it's an IOC3 then we bail out, we special
-	 * case them with pci_fixup_ioc3
-	 */
-	if (dev->vendor == PCI_VENDOR_ID_SGI && 
-	    dev->device == PCI_DEVICE_ID_SGI_IOC3 )
-		return PCIBIOS_SUCCESSFUL;
 
 	device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn);
 	if (!device_vertex) {
@@ -163,13 +156,6 @@
 	if ( dev == (struct pci_dev *)0 ) {
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	}
-	/* 
-	 * if it's an IOC3 then we bail out, we special
-	 * case them with pci_fixup_ioc3
-	 */
-	if (dev->vendor == PCI_VENDOR_ID_SGI && 
-	    dev->device == PCI_DEVICE_ID_SGI_IOC3)
-		return PCIBIOS_SUCCESSFUL;
 
 	device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn);
 	if (!device_vertex) {
@@ -196,13 +182,6 @@
 	if ( dev == (struct pci_dev *)0 ) {
 		return PCIBIOS_DEVICE_NOT_FOUND;
 	}
-	/* 
-	 * if it's an IOC3 then we bail out, we special
-	 * case them with pci_fixup_ioc3
-	 */
-	if (dev->vendor == PCI_VENDOR_ID_SGI && 
-	    dev->device == PCI_DEVICE_ID_SGI_IOC3)
-		return PCIBIOS_SUCCESSFUL;
 
 	device_vertex = devfn_to_vertex(dev->bus->number, dev->devfn);
 	if (!device_vertex) {
@@ -241,49 +220,8 @@
 	/* sn_io_infrastructure_init(); */
 	pci_root_ops = &snia64_pci_ops;
 }
-
-void
-pci_fixup_ioc3(struct pci_dev *d)
-{
-        int 		i;
-	unsigned int 	size;
-
-        /* IOC3 only decodes 0x20 bytes of the config space, reading
-	 * beyond that is relatively benign but writing beyond that
-	 * (especially the base address registers) will shut down the
-	 * pci bus...so avoid doing so.
-	 * NOTE: this means we can't program the intr_pin into the device,
-	 *       currently we hack this with special code in 
-	 *	 sgi_pci_intr_support()
-	 */
-        DBG("pci_fixup_ioc3: Fixing base addresses for ioc3 device %s\n", d->slot_name);
-
-	/* I happen to know from the spec that the ioc3 needs only 0xfffff 
-	 * The standard pci trick of writing ~0 to the baddr and seeing
-	 * what comes back doesn't work with the ioc3
-	 */
-	size = 0xfffff;
-	d->resource[0].end = (unsigned long) d->resource[0].start + (unsigned long) size;
-
-	/*
-	 * Zero out the resource structure .. because we did not go through 
-	 * the normal PCI Infrastructure Init, garbbage are left in these 
-	 * fileds.
-	 */
-        for (i = 1; i <= PCI_ROM_RESOURCE; i++) {
-                d->resource[i].start = 0UL;
-                d->resource[i].end = 0UL;
-                d->resource[i].flags = 0UL;
-        }
-
-        d->subsystem_vendor = 0;
-        d->subsystem_device = 0;
-
-}
-
 #else
 void sn_pci_find_bios(void) {}
-void pci_fixup_ioc3(struct pci_dev *d) {}
 struct list_head pci_root_buses;
 struct list_head pci_root_buses;
 struct list_head pci_devices;
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/machvec/pci_bus_cvlink.c linux-2.4.23-pre4/arch/ia64/sn/io/machvec/pci_bus_cvlink.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	2003-09-12 12:44:34.000000000 -0700
@@ -47,14 +47,13 @@
 static int done_probing;
 extern irqpda_t *irqpdaindr;
 
-static int pci_bus_map_create(vertex_hdl_t xtalk, char * io_moduleid);
+static int pci_bus_map_create(vertex_hdl_t xtalk, int brick_type, char * io_moduleid);
 vertex_hdl_t devfn_to_vertex(unsigned char busnum, unsigned int devfn);
 
 extern void register_pcibr_intr(int irq, pcibr_intr_t intr);
 
 void sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int slot);
 
-
 /*
  * For the given device, initialize whether it is a PIC device.
  */
@@ -148,8 +147,7 @@
 	 */
 	if (func == 0) {
         	sprintf(name, "%d", slot);
-		if (hwgraph_traverse(pci_bus, name, &device_vertex) == 
-			GRAPH_SUCCESS) {
+		if (hwgraph_traverse(pci_bus, name, &device_vertex) == GRAPH_SUCCESS) {
 			if (device_vertex) {
 				return(device_vertex);
 			}
@@ -170,54 +168,6 @@
 	return(device_vertex);
 }
 
-/*
- * For the given device, initialize the addresses for both the Device(x) Flush 
- * Write Buffer register and the Xbow Flush Register for the port the PCI bus 
- * is connected.
- */
-static void
-set_flush_addresses(struct pci_dev *device_dev, 
-	struct sn_device_sysdata *device_sysdata)
-{
-	pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl);
-	pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);
-	pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
-    	bridge_t               *bridge = pcibr_soft->bs_base;
-	nasid_t			nasid;
-
-	/*
-	 * Get the nasid from the bridge.
-	 */
-	nasid = NASID_GET(device_sysdata->dma_buf_sync);
-	if (IS_PIC_DEVICE(device_dev)) {
-		device_sysdata->dma_buf_sync = (volatile unsigned int *)
-			&bridge->b_wr_req_buf[pciio_slot].reg;
-		device_sysdata->xbow_buf_sync = (volatile unsigned int *)
-			XBOW_PRIO_LINKREGS_PTR(NODE_SWIN_BASE(nasid, 0),
-			pcibr_soft->bs_xid);
-	} else {
-		/*
-		 * Accessing Xbridge and Xbow register when SHUB swapoper is on!.
-		 */
-		device_sysdata->dma_buf_sync = (volatile unsigned int *)
-			((uint64_t)&(bridge->b_wr_req_buf[pciio_slot].reg)^4);
-		device_sysdata->xbow_buf_sync = (volatile unsigned int *)
-			((uint64_t)(XBOW_PRIO_LINKREGS_PTR(
-			NODE_SWIN_BASE(nasid, 0), pcibr_soft->bs_xid)) ^ 4);
-	}
-
-#ifdef DEBUG
-	printk("set_flush_addresses: dma_buf_sync %p xbow_buf_sync %p\n", 
-		device_sysdata->dma_buf_sync, device_sysdata->xbow_buf_sync);
-
-printk("set_flush_addresses: dma_buf_sync\n");
-	while((volatile unsigned int )*device_sysdata->dma_buf_sync);
-printk("set_flush_addresses: xbow_buf_sync\n");
-	while((volatile unsigned int )*device_sysdata->xbow_buf_sync);
-#endif
-
-}
-
 struct sn_flush_nasid_entry flush_nasid_list[MAX_NASIDS];
 
 // Initialize the data structures for flushing write buffers after a PIO read.
@@ -247,6 +197,9 @@
 	if (flush_nasid_list[nasid].widget_p == NULL) {
 		flush_nasid_list[nasid].widget_p = (struct sn_flush_device_list **)kmalloc((HUB_WIDGET_ID_MAX+1) *
 			sizeof(struct sn_flush_device_list *), GFP_KERNEL);
+		if (flush_nasid_list[nasid].widget_p <= 0)
+			BUG(); /* Cannot afford to run out of memory. */
+
 		memset(flush_nasid_list[nasid].widget_p, 0, (HUB_WIDGET_ID_MAX+1) * sizeof(struct sn_flush_device_list *));
 	}
 	if (bwin > 0) {
@@ -326,6 +279,9 @@
 	if (flush_nasid_list[nasid].widget_p[wid_num] == NULL) {
 		flush_nasid_list[nasid].widget_p[wid_num] = (struct sn_flush_device_list *)kmalloc(
 			DEV_PER_WIDGET * sizeof (struct sn_flush_device_list), GFP_KERNEL);
+		if (flush_nasid_list[nasid].widget_p[wid_num] <= 0)
+			BUG(); /* Cannot afford to run out of memory. */
+
 		memset(flush_nasid_list[nasid].widget_p[wid_num], 0, 
 			DEV_PER_WIDGET * sizeof (struct sn_flush_device_list));
 		p = &flush_nasid_list[nasid].widget_p[wid_num][0];
@@ -430,13 +386,6 @@
 		}
 	}
 
-	if (vendor == PCI_VENDOR_ID_SGI) {
-		if (device == PCI_DEVICE_ID_SGI_IOC3) {
-			SET_PCIA64(dev);
-			return;
-		}
-	}
-
 }
 
 /*
@@ -455,7 +404,7 @@
 	struct sn_widget_sysdata *widget_sysdata;
 	struct sn_device_sysdata *device_sysdata;
 	pciio_intr_t intr_handle;
-	int cpuid, bit;
+	int cpuid;
 	vertex_hdl_t device_vertex;
 	pciio_intr_line_t lines;
 	extern void sn_pci_find_bios(void);
@@ -488,6 +437,9 @@
 		pci_bus = pci_bus_b(ln);
 		widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata), 
 					GFP_KERNEL);
+		if (widget_sysdata <= 0)
+			BUG(); /* Cannot afford to run out of memory */
+
 		widget_sysdata->vhdl = pci_bus_to_vertex(pci_bus->number);
 		pci_bus->sysdata = (void *)widget_sysdata;
 	}
@@ -516,24 +468,15 @@
 		unsigned long size;
 		extern int bit_pos_to_irq(int);
 
-		if (device_dev->vendor == PCI_VENDOR_ID_SGI &&
-				device_dev->device == PCI_DEVICE_ID_SGI_IOC3) {
-			extern void pci_fixup_ioc3(struct pci_dev *d);
-			pci_fixup_ioc3(device_dev);
-		}
-
 		/* Set the device vertex */
 
 		device_sysdata = kmalloc(sizeof(struct sn_device_sysdata),
 					GFP_KERNEL);
+		if (device_sysdata <= 0)
+			BUG(); /* Cannot afford to run out of memory */
+
 		device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn);
 		device_sysdata->isa64 = 0;
-		/*
-		 * Set the xbridge Device(X) Write Buffer Flush and Xbow Flush 
-		 * register addresses.
-		 */
-		(void) set_flush_addresses(device_dev, device_sysdata);
-
 		device_dev->sysdata = (void *) device_sysdata;
 		set_sn_pci64(device_dev);
 		set_isPIC(device_sysdata);
@@ -552,7 +495,7 @@
 			size = device_dev->resource[idx].end -
 				device_dev->resource[idx].start;
 			if (size) {
-				device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(vhdl, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM);
+				device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(vhdl, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, 0);
 				device_dev->resource[idx].start |= __IA64_UNCACHED_OFFSET;
 			}
 			else
@@ -583,7 +526,7 @@
 		if (size) {
 			device_dev->resource[PCI_ROM_RESOURCE].start =
 			(unsigned long) pciio_pio_addr(vhdl, 0, PCIIO_SPACE_ROM, 0, 
-				size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM);
+				size, 0, 0);
 			device_dev->resource[PCI_ROM_RESOURCE].start |= __IA64_UNCACHED_OFFSET;
 			device_dev->resource[PCI_ROM_RESOURCE].end =
 			device_dev->resource[PCI_ROM_RESOURCE].start + size;
@@ -598,11 +541,6 @@
 		pci_write_config_word(device_dev, PCI_COMMAND, cmd);
 
 		pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, (unsigned char *)&lines);
-		if (device_dev->vendor == PCI_VENDOR_ID_SGI &&
-			device_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) {
-				lines = 1;
-		}
- 
 		device_sysdata = (struct sn_device_sysdata *)device_dev->sysdata;
 		device_vertex = device_sysdata->vhdl;
  
@@ -703,13 +641,11 @@
  *	
  */
 static int 
-pci_bus_map_create(vertex_hdl_t xtalk, char * io_moduleid)
+pci_bus_map_create(vertex_hdl_t xtalk, int brick_type, char * io_moduleid)
 {
 
-	vertex_hdl_t master_node_vertex = NULL;
 	vertex_hdl_t xwidget = NULL;
 	vertex_hdl_t pci_bus = NULL;
-	hubinfo_t hubinfo = NULL;
 	xwidgetnum_t widgetnum;
 	char pathname[128];
 	graph_error_t rv;
@@ -720,73 +656,6 @@
 	int bus_number;
 
 	/*
-	 * Loop throught this vertex and get the Xwidgets ..
-	 */
-
-
-	/* PCI devices */
-
-	for (widgetnum = HUB_WIDGET_ID_MAX; widgetnum >= HUB_WIDGET_ID_MIN; widgetnum--) {
-		sprintf(pathname, "%d", widgetnum);
-		xwidget = NULL;
-		
-		/*
-		 * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget
-		 *	     /hw/module/001c16/Pbrick/xtalk/8/pci/1 is device
-		 */
-		rv = hwgraph_traverse(xtalk, pathname, &xwidget);
-		if ( (rv != GRAPH_SUCCESS) ) {
-			if (!xwidget) {
-				continue;
-			}
-		}
-
-		sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum);
-		pci_bus = NULL;
-		if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS)
-			if (!pci_bus) {
-				continue;
-}
-
-		/*
-		 * Assign the correct bus number and also the nasid of this 
-		 * pci Xwidget.
-		 * 
-		 * Should not be any race here ...
-		 */
-		num_bridges++;
-		busnum_to_pcibr_vhdl[num_bridges - 1] = pci_bus;
-
-		/*
-		 * Get the master node and from there get the NASID.
-		 */
-		master_node_vertex = device_master_get(xwidget);
-		if (!master_node_vertex) {
-			printk("WARNING: pci_bus_map_create: Unable to get .master for vertex 0x%p\n", (void *)xwidget);
-		}
-	
-		hubinfo_get(master_node_vertex, &hubinfo);
-		if (!hubinfo) {
-			printk("WARNING: pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p\n", (void *)master_node_vertex);
-			return(1);
-		} else {
-			busnum_to_nid[num_bridges - 1] = hubinfo->h_nasid;
-		}
-
-		/*
-		 * Pre assign DMA maps needed for 32 Bits Page Map DMA.
-		 */
-		busnum_to_atedmamaps[num_bridges - 1] = (void *) kmalloc(
-			sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL);
-		if (!busnum_to_atedmamaps[num_bridges - 1])
-			printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, (void *)xwidget);
-
-		memset(busnum_to_atedmamaps[num_bridges - 1], 0x0, 
-			sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS);
-
-	}
-
-	/*
 	 * PCIX devices
 	 * We number busses differently for PCI-X devices.
 	 * We start from Lowest Widget on up ..
@@ -829,11 +698,11 @@
 			 * 
 			 * Should not be any race here ...
 			 */
-			bus_number = basebus_num + bus + io_brick_map_widget(MODULE_PXBRICK, widgetnum);
+			bus_number = basebus_num + bus + io_brick_map_widget(brick_type, widgetnum);
 #ifdef DEBUG
-			printk("bus_number %d basebus_num %d bus %d io %d\n", 
+			printk("bus_number %d basebus_num %d bus %d io %d pci_bus 0x%x brick_type %d \n", 
 				bus_number, basebus_num, bus, 
-				io_brick_map_widget(MODULE_PXBRICK, widgetnum));
+				io_brick_map_widget(brick_type, widgetnum), pci_bus, brick_type);
 #endif
 			busnum_to_pcibr_vhdl[bus_number] = pci_bus;
 	
@@ -842,14 +711,71 @@
 			 */
 			busnum_to_atedmamaps[bus_number] = (void *) kmalloc(
 				sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL);
-			if (!busnum_to_atedmamaps[bus_number])
-				printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, (void *)xwidget);
+			if (busnum_to_atedmamaps[bus_number] <= 0)
+				BUG(); /* Cannot afford to run out of memory. */
 	
 			memset(busnum_to_atedmamaps[bus_number], 0x0, 
 				sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS);
 		}
 	}
 
+	/* AGP/CGbrick */
+
+	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
+
+		/* Do both buses */
+		for ( bus = 0; bus < 2; bus++ ) {
+			sprintf(pathname, "%d", widgetnum);
+			xwidget = NULL;
+			
+			/*
+			 * Example - /hw/module/001c16/slab/0/CGbrick/xtalk/15 is the xwidget
+			 *	     /hw/module/001c16/slab/0/CGbrick/xtalk/15/agp/0 is the bus
+			 *	     /hw/module/001c16/slab/0/CGbrick/xtalk/15/agp/0/1a is device
+			 */
+			rv = hwgraph_traverse(xtalk, pathname, &xwidget);
+			if ( (rv != GRAPH_SUCCESS) ) {
+				if (!xwidget) {
+					continue;
+				}
+			}
+	
+			if ( bus == 0 )
+				sprintf(pathname, "%d/"EDGE_LBL_AGP_0, widgetnum);
+			else
+				sprintf(pathname, "%d/"EDGE_LBL_AGP_1, widgetnum);
+			pci_bus = NULL;
+			if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS)
+				if (!pci_bus) {
+					continue;
+				}
+	
+			/*
+			 * Assign the correct bus number and also the nasid of this 
+			 * pci Xwidget.
+			 * 
+			 * Should not be any race here ...
+			 */
+			bus_number = basebus_num + bus + io_brick_map_widget(brick_type, widgetnum);
+#ifdef DEBUG
+			printk("bus_number %d basebus_num %d bus %d io %d pci_bus 0x%x\n", 
+				bus_number, basebus_num, bus, 
+				io_brick_map_widget(brick_type, widgetnum), pci_bus);
+#endif
+			busnum_to_pcibr_vhdl[bus_number] = pci_bus;
+
+			/*
+			 * Pre assign DMA maps needed for 32 Bits Page Map DMA.
+			 */
+			busnum_to_atedmamaps[bus_number] = (void *) kmalloc(
+				sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL);
+			if (busnum_to_atedmamaps[bus_number] <= 0)
+				BUG(); /* Cannot afford to run out of memory */
+	
+			memset(busnum_to_atedmamaps[bus_number], 0x0, 
+				sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS);
+		}
+	}
         return(0);
 }
 
@@ -868,11 +794,20 @@
 	vertex_hdl_t devfs_hdl = NULL;
 	vertex_hdl_t xtalk = NULL;
 	int rv = 0;
-	char name[256];
-	char tmp_name[256];
+	char *name;
+	char *tmp_name;
 	int i, ii, j;
 	char *brick_name;
 	extern void ioconfig_bus_new_entries(void);
+	extern int iobrick_type_get_nasid(nasid_t);
+
+	name = kmalloc(256, GFP_KERNEL);
+	if (!name)
+		BUG();
+
+	tmp_name = kmalloc(256, GFP_KERNEL);
+	if (!name)
+		 BUG();
 
 	/*
 	 * Figure out which IO Brick is connected to the Compute Bricks.
@@ -881,32 +816,39 @@
 		extern int iomoduleid_get(nasid_t);
 		moduleid_t iobrick_id;
 		nasid_t nasid = -1;
-		int nodecnt;
 		int n = 0;
 
-		nodecnt = modules[i]->nodecnt;
-		for ( n = 0; n < nodecnt; n++ ) {
+		for ( n = 0; n <= MAX_SLABS; n++ ) {
+			if (modules[i]->nodes[n] == -1)
+				continue; /* node is not alive in module */
+
 			nasid = cnodeid_to_nasid(modules[i]->nodes[n]);
 			iobrick_id = iomoduleid_get(nasid);
 			if ((int)iobrick_id > 0) { /* Valid module id */
 				char name[12];
 				memset(name, 0, 12);
 				format_module_id((char *)&(modules[i]->io[n].moduleid), iobrick_id, MODULE_FORMAT_BRIEF);
+				modules[i]->io[n].iobrick_type = (uint64_t)iobrick_type_get_nasid(nasid);
 			}
 		}
 	}
 				
 	devfs_hdl = hwgraph_path_to_vertex("hw/module");
 	for (i = 0; i < nummodules ; i++) {
-	    for ( j = 0; j < 3; j++ ) {
+	    for ( j = 0; j < 4; j++ ) {
 		if ( j == 0 )
-			brick_name = EDGE_LBL_PBRICK;
+			brick_name = EDGE_LBL_IXBRICK;
 		else if ( j == 1 )
 			brick_name = EDGE_LBL_PXBRICK;
-		else
-			brick_name = EDGE_LBL_IXBRICK;
+		else if ( j == 2 )
+			brick_name = EDGE_LBL_OPUSBRICK;
+		else	/* 3 */
+			brick_name = EDGE_LBL_CGBRICK;
+
+		for ( ii = 0; ii <= MAX_SLABS ; ii++ ) {
+			if (modules[i]->nodes[ii] == -1)
+				continue; /* Missing slab */
 
-		for ( ii = 0; ii < 2 ; ii++ ) {
 			memset(name, 0, 256);
 			memset(tmp_name, 0, 256);
 			format_module_id(name, modules[i]->id, MODULE_FORMAT_BRIEF);
@@ -915,11 +857,14 @@
 			xtalk = NULL;
 			rv = hwgraph_edge_get(devfs_hdl, name, &xtalk);
 			if ( rv == 0 ) 
-				pci_bus_map_create(xtalk, (char *)&(modules[i]->io[ii].moduleid));
+				pci_bus_map_create(xtalk, (int)modules[i]->io[ii].iobrick_type, (char *)&(modules[i]->io[ii].moduleid));
 		}
 	    }
 	}
 
+	kfree(name);
+	kfree(tmp_name);
+
 	/*
 	 * Create the Linux PCI bus number vertex link.
 	 */
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/machvec/pci_dma.c linux-2.4.23-pre4/arch/ia64/sn/io/machvec/pci_dma.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/machvec/pci_dma.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/machvec/pci_dma.c	2003-09-12 12:44:34.000000000 -0700
@@ -182,7 +182,6 @@
 	 * attributes or to a different memory region.
 	 */
 	*dma_handle = pciio_dmatrans_addr(vhdl, NULL, phys_addr, size,
-			((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) |
 					  PCIIO_DMA_CMD);
 
         /*
@@ -201,7 +200,6 @@
 	 */
 	if (!(*dma_handle)) {
 		dma_map = pciio_dmamap_alloc(vhdl, NULL, size,
-				((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) |
 					     PCIIO_DMA_CMD);
 		if (!dma_map) {
 			printk(KERN_ERR "sn_pci_alloc_consistent: Unable to "
@@ -295,10 +293,7 @@
 		 */
 		if (IS_PCIA64(hwdev)) {
 			sg->dma_address = pciio_dmatrans_addr(vhdl, NULL, phys_addr,
-						       sg->length,
-			       ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) |
-						       PCIIO_DMA_DATA |
-						       PCIIO_DMA_A64);
+						       sg->length, PCIIO_DMA_DATA | PCIIO_DMA_A64);
 			sg->dma_length = sg->length;
 			continue;
 		}
@@ -308,9 +303,7 @@
 		 */
 		if (IS_PCI32G(hwdev)) {
 			sg->dma_address = pciio_dmatrans_addr(vhdl, NULL, phys_addr,
-						       sg->length,
-					((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) |
-						       PCIIO_DMA_DATA);
+						       sg->length, PCIIO_DMA_DATA);
 			sg->dma_length = sg->length;
 			/*
 			 * See if we got a direct map entry
@@ -325,9 +318,7 @@
 		 * It is a 32 bit card and we cannot do direct mapping,
 		 * so we use an ATE.
 		 */
-		dma_map = pciio_dmamap_alloc(vhdl, NULL, sg->length,
-				((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) |
-					     PCIIO_DMA_DATA);
+		dma_map = pciio_dmamap_alloc(vhdl, NULL, sg->length, PCIIO_DMA_DATA);
 		if (!dma_map) {
 			printk(KERN_ERR "sn_pci_map_sg: Unable to allocate "
 			       "anymore 32 bit page map entries.\n");
@@ -440,9 +431,7 @@
 	if (IS_PCIA64(hwdev)) {
 		/* This device supports 64 bit DMA addresses. */
 		dma_addr = pciio_dmatrans_addr(vhdl, NULL, phys_addr, size,
-		       ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) |
-					       PCIIO_DMA_DATA |
-					       PCIIO_DMA_A64);
+					       PCIIO_DMA_DATA | PCIIO_DMA_A64);
 		return dma_addr;
 	}
 
@@ -454,7 +443,6 @@
 	 */
 	if (IS_PCI32G(hwdev)) {
 		dma_addr = pciio_dmatrans_addr(vhdl, NULL, phys_addr, size,
-			((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) |
 					       PCIIO_DMA_DATA);
 		if (dma_addr)
 			return dma_addr;
@@ -465,9 +453,7 @@
 	 * let's use the PMU instead.
 	 */
 	dma_map = NULL;
-	dma_map = pciio_dmamap_alloc(vhdl, NULL, size, 
-			((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) |
-			PCIIO_DMA_DATA);
+	dma_map = pciio_dmamap_alloc(vhdl, NULL, size, PCIIO_DMA_DATA);
 
 	if (!dma_map) {
 		printk(KERN_ERR "pci_map_single: Unable to allocate anymore "
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/platform_init/Makefile linux-2.4.23-pre4/arch/ia64/sn/io/platform_init/Makefile
--- linux-2.4.23-pre3/arch/ia64/sn/io/platform_init/Makefile	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/platform_init/Makefile	2003-09-12 12:44:34.000000000 -0700
@@ -11,6 +11,6 @@
 
 O_TARGET := snio.o
 
-obj-y				+=  sgi_io_init.o irix_io_init.o
+obj-y				+=  irix_io_init.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/platform_init/irix_io_init.c linux-2.4.23-pre4/arch/ia64/sn/io/platform_init/irix_io_init.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/platform_init/irix_io_init.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/platform_init/irix_io_init.c	2003-09-12 12:44:34.000000000 -0700
@@ -23,17 +23,55 @@
 extern void klhwg_add_all_modules(vertex_hdl_t);
 extern void klhwg_add_all_nodes(vertex_hdl_t);
 
+extern int init_hcl(void);
 extern vertex_hdl_t hwgraph_root;
 extern void io_module_init(void);
 extern int pci_bus_to_hcl_cvlink(void);
-extern void mlreset(void);
 
-/* #define DEBUG_IO_INIT 1 */
-#ifdef DEBUG_IO_INIT
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif /* DEBUG_IO_INIT */
+char arg_maxnodes[4];
+char master_baseio_wid;
+nasid_t master_baseio_nasid;
+nasid_t master_nasid = INVALID_NASID;           /* This is the partition master nasid */
+nasid_t console_nasid = (nasid_t)-1;
+
+/*
+ * Return non-zero if the given variable was specified
+ */
+int
+is_specified(char *s)
+{
+	return (strlen(s) != 0);
+}
+
+int
+check_nasid_equiv(nasid_t nasida, nasid_t nasidb)
+{
+	if ((nasida == nasidb) || (nasida == NODEPDA(NASID_TO_COMPACT_NODEID(nasidb))->xbow_peer))
+		return 1;
+	else
+		return 0;
+}
+
+int
+is_master_baseio_nasid_widget(nasid_t test_nasid, xwidgetnum_t test_wid)
+{
+
+	/*
+	 * If the widget numbers are different, we're not the master.
+	 */
+	if (test_wid != (xwidgetnum_t)master_baseio_wid) {
+		return 0;
+	}
+
+	/*
+	 * If the NASIDs are the same or equivalent, we're the master.
+	 */
+	if (check_nasid_equiv(test_nasid, master_baseio_nasid)) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
 
 /*
  * This routine is responsible for the setup of all the IRIX hwgraph style
@@ -46,14 +84,11 @@
  */
 
 void
-irix_io_init(void)
+sgi_master_io_infr_init(void)
 {
 	cnodeid_t cnode;
 
-	/*
-	 * This is the Master CPU.  Emulate mlsetup and main.c in Irix.
-	 */
-	mlreset();
+	init_hcl(); /* Sets up the hwgraph compatibility layer */
 
         /*
          * Initialize platform-dependent vertices in the hwgraph:
@@ -78,6 +113,12 @@
 
 	/* We can do headless hub cnodes here .. */
 
+	/* Initialize ICE for TIO Nodes. */
+	for (cnode = numnodes; cnode < numionodes; cnode++) {
+		extern void per_ice_init(cnodeid_t);
+		per_ice_init(cnode);
+	}
+
 	/*
 	 *
 	 * Our IO Infrastructure drivers are in place .. 
@@ -86,4 +127,12 @@
 	 */
 	init_all_devices();
 	pci_bus_to_hcl_cvlink();
+
+#ifdef  CONFIG_KDB
+        {
+                extern void kdba_io_init(void);
+                kdba_io_init();
+        }
+#endif
+
 }
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sgi_if.c linux-2.4.23-pre4/arch/ia64/sn/io/sgi_if.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sgi_if.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sgi_if.c	2003-09-12 12:44:34.000000000 -0700
@@ -21,11 +21,11 @@
 #include <asm/sn/slotnum.h>
 
 void *
-snia_kmem_zalloc(size_t size, int flag)
+snia_kmem_zalloc(size_t size)
 {
         void *ptr = kmalloc(size, GFP_KERNEL);
 	if ( ptr )
-        	BZERO(ptr, size);
+        	memset(ptr, 0, size);
         return(ptr);
 }
 
@@ -39,21 +39,12 @@
  * the alloc/free_node routines do a simple kmalloc for now ..
  */
 void *
-snia_kmem_alloc_node(register size_t size, register int flags, cnodeid_t node)
+snia_kmem_alloc_node(register size_t size, cnodeid_t node)
 {
 	/* someday will Allocate on node 'node' */
 	return(kmalloc(size, GFP_KERNEL));
 }
 
-void *
-snia_kmem_zalloc_node(register size_t size, register int flags, cnodeid_t node)
-{
-	void *ptr = kmalloc(size, GFP_KERNEL);
-	if ( ptr )
-		BZERO(ptr, size);
-        return(ptr);
-}
-
 
 /*
  * print_register() allows formatted printing of bit fields.  individual
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/Makefile linux-2.4.23-pre4/arch/ia64/sn/io/sn2/Makefile
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/Makefile	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/Makefile	2003-09-12 12:44:34.000000000 -0700
@@ -11,15 +11,14 @@
 
 O_TARGET := snio.o
 
-export-objs := pciio.o 
-
 obj-y				+= ml_SN_intr.o shub_intr.o shuberror.o shub.o \
 				   bte_error.o pcibr/pcibr.o pic.o geo_op.o \
 				   l1_command.o klconflib.o klgraph.o \
 				   ml_SN_init.o ml_iograph.o module.o pciio.o \
-				   xbow.o xtalk.o shubio.o
+				   xbow.o xtalk.o shubio.o ioc4/ioc4_if.o
+
 obj-$(CONFIG_KDB)		+= kdba_io.o
 
-subdir-y			+= pcibr
+subdir-y			+= pcibr ioc4
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/ioc4/Makefile linux-2.4.23-pre4/arch/ia64/sn/io/sn2/ioc4/Makefile
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/ioc4/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/ioc4/Makefile	2003-09-12 12:44:34.000000000 -0700
@@ -0,0 +1,22 @@
+#
+# 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.
+#
+# Copyright (C) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+#
+# Makefile for the sn2 io ioc4 routines.
+
+EXTRA_CFLAGS    := -DLITTLE_ENDIAN
+
+ifdef CONFIG_IA64_SGI_SN2
+EXTRA_CFLAGS    += -DSHUB_SWAP_WAR
+endif
+
+O_TARGET := ioc4_if.o
+export-objs := ioc4.o  sio_ioc4.o
+
+
+obj-$(CONFIG_IA64_SGI_SN2)	+= sio_ioc4.o ioc4.o
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/ioc4/ioc4.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/ioc4/ioc4.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/ioc4/ioc4.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/ioc4/ioc4.c	2003-09-12 12:44:34.000000000 -0700
@@ -0,0 +1,641 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/* This is the top level IOC4 device driver.  It does very little, farming
+ * out actual tasks to the various slave IOC4 drivers (serial, keyboard/mouse,
+ * and real-time interrupt).
+ */
+
+#include <linux/config.h>
+#include <asm/sn/types.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/iograph.h>
+#include <asm/atomic.h>
+#include <asm/sn/pci/pci_defs.h>
+#include <asm/sn/pci/pciio.h>
+#include <linux/pci.h>
+#include <asm/sn/ioc4.h>
+#include <asm/sn/pci/pci_bus_cvlink.h>
+
+/* #define DEBUG_INTERRUPTS */
+#define SUPPORT_ATOMICS
+
+#ifdef SUPPORT_ATOMICS
+
+/*
+ * support routines for local atomic operations.
+ */
+
+static spinlock_t local_lock;
+
+static inline unsigned int
+atomicSetInt(atomic_t *a, unsigned int b)
+{
+	unsigned long s;
+	unsigned int ret, new;
+
+	spin_lock_irqsave(&local_lock, s);
+	new = ret = atomic_read(a);
+	new |= b;
+	atomic_set(a, new);
+	spin_unlock_irqrestore(&local_lock, s);
+
+	return ret;
+}
+
+static unsigned int
+atomicClearInt(atomic_t *a, unsigned int b)
+{
+	unsigned long s;
+	unsigned int ret, new;
+
+	spin_lock_irqsave(&local_lock, s);
+	new = ret = atomic_read(a);
+	new &= ~b;
+	atomic_set(a, new);
+	spin_unlock_irqrestore(&local_lock, s);
+
+	return ret;
+}
+
+#else
+
+#define atomicAddInt(a,b)	*(a) += ((unsigned int)(b))
+
+static inline unsigned int
+atomicSetInt(unsigned int *a, unsigned int b)
+{
+	unsigned int ret = *a;
+
+	*a |= b;
+	return ret;
+}
+
+#define atomicSetUint64(a,b)	*(a) |= ((unsigned long long )(b))
+
+static inline unsigned int
+atomicClearInt(unsigned int *a, unsigned int b)
+{
+	unsigned int ret = *a;
+
+	*a &= ~b;
+	return ret;
+}
+
+#define atomicClearUint64(a,b)	*(a) &= ~((unsigned long long)(b))
+#endif	/* SUPPORT_ATOMICS */
+
+
+/* pci device struct */
+static const struct pci_device_id __devinitdata ioc4_s_id_table[] =
+{
+        { IOC4_VENDOR_ID_NUM, IOC4_DEVICE_ID_NUM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+        {              0,           0,          0,          0, 0, 0, 0 }
+};
+
+int __devinit ioc4_attach(struct pci_dev *, const struct pci_device_id *);
+
+struct pci_driver ioc4_s_driver =
+{
+	name : "IOC4 Serial",
+	id_table: ioc4_s_id_table,
+	probe: ioc4_attach,
+};
+
+int __init
+ioc4_serial_detect(void)
+{
+	int rc;
+
+	rc = pci_register_driver(&ioc4_s_driver);
+	return 0;
+}
+module_init(ioc4_serial_detect);
+
+
+/*
+ * Some external functions we still need.
+ */
+extern int		ioc4_serial_attach(vertex_hdl_t conn, void *mem);
+extern cpuid_t		cpuvertex_to_cpuid(vertex_hdl_t vhdl);
+
+
+/*
+ * per-IOC4 data structure
+ */
+typedef struct ioc4_soft_s {
+    vertex_hdl_t	    is_ioc4_vhdl;
+    vertex_hdl_t            is_conn_vhdl;
+
+    struct pci_dev	   *is_pci_dev;
+    ioc4_mem_t		   *is_ioc4_mem;
+
+    /* Each interrupt type has an entry in the array */
+    struct ioc4_intr_type {
+
+        /*
+         * Each in-use entry in this array contains at least
+         * one nonzero bit in sd_bits; no two entries in this
+         * array have overlapping sd_bits values.
+         */
+#define MAX_IOC4_INTR_ENTS	(8 * sizeof(ioc4reg_t))
+        struct ioc4_intr_info {
+	    ioc4reg_t		sd_bits;
+	    ioc4_intr_func_f   *sd_intr;
+	    intr_arg_t		sd_info;
+	    vertex_hdl_t	sd_vhdl;
+	    struct ioc4_soft_s *sd_soft;
+        } is_intr_info[MAX_IOC4_INTR_ENTS];
+
+        /* Number of entries active in the above array */
+        atomic_t	 is_num_intrs;
+        atomic_t	 is_intr_bits_busy;	/* Bits assigned */
+        atomic_t         is_intr_ents_free;	/* Free active entries mask*/
+    } is_intr_type[ioc4_num_intr_types];
+
+    /* is_ir_lock must be held while
+     * modifying sio_ie values, so
+     * we can be sure that sio_ie is
+     * not changing when we read it
+     * along with sio_ir.
+     */
+    spinlock_t		    is_ir_lock;		/* SIO_IE[SC] mod lock */
+} ioc4_soft_t;
+
+#define ioc4_soft_set(v,i)	hwgraph_fastinfo_set((v), (arbitrary_info_t)(i))
+#define ioc4_soft_get(v)	((ioc4_soft_t *)hwgraph_fastinfo_get(v))
+
+
+/* =====================================================================
+ *    Function Table of Contents
+ */
+
+
+/* The IOC4 hardware provides no atomic way to determine if interrupts
+ * are pending since two reads are required to do so.  The handler must
+ * read the SIO_IR and the SIO_IES, and take the logical and of the
+ * two.  When this value is zero, all interrupts have been serviced and
+ * the handler may return.
+ *
+ * This has the unfortunate "hole" that, if some other CPU or
+ * some other thread or some higher level interrupt manages to
+ * modify SIO_IE between our reads of SIO_IR and SIO_IE, we may
+ * think we have observed SIO_IR&SIO_IE==0 when in fact this
+ * condition never really occurred.
+ *
+ * To solve this, we use a simple spinlock that must be held
+ * whenever modifying SIO_IE; holding this lock while observing
+ * both SIO_IR and SIO_IE guarantees that we do not falsely
+ * conclude that no enabled interrupts are pending.
+ */
+
+void
+ioc4_write_ireg(void *ioc4_soft, ioc4reg_t val, int which, ioc4_intr_type_t type)
+{
+    ioc4_mem_t		   *mem = ((ioc4_soft_t *) ioc4_soft)->is_ioc4_mem;
+    spinlock_t		   *lp = &((ioc4_soft_t *) ioc4_soft)->is_ir_lock;
+    unsigned long	    s;
+
+
+    spin_lock_irqsave(lp, s);
+
+    switch (type) {
+      case ioc4_sio_intr_type:
+        switch (which) {
+          case IOC4_W_IES:
+	    mem->sio_ies_ro = val;
+	    break;
+
+          case IOC4_W_IEC:
+	    mem->sio_iec_ro = val;
+	    break;
+        }
+	break;
+
+      case ioc4_other_intr_type:
+        switch (which) {
+          case IOC4_W_IES:
+	    mem->other_ies_ro = val;
+	    break;
+
+          case IOC4_W_IEC:
+	    mem->other_iec_ro = val;
+	    break;
+        }
+	break;
+
+      case ioc4_num_intr_types:
+	break;
+    }
+    spin_unlock_irqrestore(lp, s);
+}
+
+
+static inline ioc4reg_t
+ioc4_pending_intrs(ioc4_soft_t * ioc4_soft, ioc4_intr_type_t type)
+{
+    ioc4_mem_t	*mem = ioc4_soft->is_ioc4_mem;
+    spinlock_t	*lp = &ioc4_soft->is_ir_lock;
+    unsigned long	    s;
+    ioc4reg_t	intrs = (ioc4reg_t)0;
+
+    ASSERT((type == ioc4_sio_intr_type) || (type == ioc4_other_intr_type));
+
+    spin_lock_irqsave(lp, s);
+
+    switch (type) {
+      case ioc4_sio_intr_type:
+        intrs = mem->sio_ir & mem->sio_ies_ro;
+        break;
+
+      case ioc4_other_intr_type:
+        intrs = mem->other_ir & mem->other_ies_ro;
+
+        /* Don't process any ATA interrupte, leave them for the ATA driver */
+        intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR); 
+        break;
+
+      case ioc4_num_intr_types:
+	break;
+    }
+
+    spin_unlock_irqrestore(lp, s);
+    return intrs;
+}
+
+
+int __devinit
+ioc4_attach(struct pci_dev *pci_handle, const struct pci_device_id *pci_id)
+{
+    ioc4_mem_t		   *mem;
+/*REFERENCED*/
+    graph_error_t	    rc;
+    vertex_hdl_t	    ioc4_vhdl;
+    ioc4_soft_t		   *soft;
+    vertex_hdl_t	    conn_vhdl = PCIDEV_VERTEX(pci_handle);
+    int                     tmp;
+    extern void ioc4_ss_connect_interrupt(int, void *, void *);
+    extern void ioc4_intr(int, void *, struct pt_regs *);
+
+    if ( pci_enable_device(pci_handle) ) {
+	    printk("ioc4_attach: Failed to enable device with pci_dev 0x%p... returning\n", (void *)pci_handle);
+	    return(-1);
+    }
+
+    pci_set_master(pci_handle);
+    snia_pciio_endian_set(pci_handle, PCIDMA_ENDIAN_LITTLE, PCIDMA_ENDIAN_BIG);
+
+    /*
+     * Get PIO mappings through our "primary"
+     * connection point to the IOC4's CFG and
+     * MEM spaces.
+     */
+
+    /*
+     * Map in the ioc4 memory - we'll do config accesses thru the pci_????() interfaces.
+     */
+
+    mem = (ioc4_mem_t *)pci_resource_start(pci_handle, 0);
+    if ( !mem ) {
+	printk(KERN_ALERT "%p/" EDGE_LBL_IOC4
+		": unable to get PIO mapping for my MEM space\n", (void *)pci_handle);
+	return -1;
+    }
+
+    if ( !request_region((unsigned long)mem, sizeof(*mem), "sioc4_mem")) {
+	printk(KERN_ALERT
+		"%p/" EDGE_LBL_IOC4
+		": unable to get request region for my MEM space\n",
+		(void *)pci_handle);
+	return -1;
+    }		
+
+    /*
+     * Create the "ioc4" vertex which hangs off of
+     * the connect points.
+     * This code is slightly paranoid.
+     */
+    rc = hwgraph_path_add(conn_vhdl, EDGE_LBL_IOC4, &ioc4_vhdl);
+    ASSERT(rc == GRAPH_SUCCESS);
+
+    /*
+     * Allocate the soft structure, fill it in a bit,
+     * and attach it to the ioc4 vertex.
+     */
+    NEW(soft);
+
+    spin_lock_init(&soft->is_ir_lock);
+    soft->is_ioc4_vhdl = ioc4_vhdl;
+    soft->is_conn_vhdl = conn_vhdl;
+    soft->is_ioc4_mem = mem;
+    soft->is_pci_dev = pci_handle;
+
+    ioc4_soft_set(ioc4_vhdl, soft);
+
+    /* Init the IOC4 */
+
+    /* SN boot PROMs allocate the PCI
+     * space and set up the pci_addr fields.
+     * Other systems need to set the base address.
+     * This is handled automatically if the PCI infrastructure
+     * is used.
+     *
+     * No need to set the latency timer since the PCI
+     * infrastructure sets it to 1 us.
+     */
+
+    pci_read_config_dword(pci_handle, IOC4_PCI_SCR, &tmp);
+
+    pci_write_config_dword(pci_handle, IOC4_PCI_SCR, 
+	     tmp | PCI_CMD_BUS_MASTER | PCI_CMD_MEM_SPACE |
+	     PCI_CMD_PAR_ERR_RESP | PCI_CMD_SERR_ENABLE);
+
+    PCI_OUTW(&mem->sio_cr, (0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT));
+
+    /* Enable serial port mode select generic PIO pins as outputs */
+    PCI_OUTW(&mem->gpcr_s, IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL);
+
+    /* Clear and disable all interrupts */
+    IOC4_WRITE_IEC(soft, ~0, ioc4_sio_intr_type);
+    PCI_OUTW(&mem->sio_ir, ~0);
+
+    IOC4_WRITE_IEC(soft, ~0, ioc4_other_intr_type);
+    PCI_OUTW(&mem->other_ir, ~0);
+
+    /*
+     * Alloc the IOC4 intr before attaching the subdevs, so the
+     * cpu handling the IOC4 intr is known (for setmustrun on
+     * the ioc4 ithreads).
+     */
+
+	/* attach interrupt handler */
+
+	ioc4_ss_connect_interrupt(pci_handle->irq, (void *)ioc4_intr, (void *)soft);
+
+    /* =============================================================
+     *				  Attach Sub-devices
+     *
+     * NB: As subdevs start calling pciio_driver_register(),
+     * we can stop explicitly calling subdev drivers.
+     *
+     * The drivers attached here have not been converted
+     * to stand on their own.  However, they *do* know
+     * to call ioc4_subdev_enabled() to decide whether
+     * to actually attach themselves.
+     *
+     * It would be nice if we could convert these
+     * few remaining drivers over so they would
+     * register as proper PCI device drivers ...
+     */
+
+    ioc4_serial_attach(conn_vhdl, (void *)soft->is_ioc4_mem);	/* DMA serial ports */
+
+    /* Normally we'd return 0 - but we need to get the ide driver init'd too. 
+     * Returning an error will keep the IOC4 on the pci list */
+    return -1;
+}
+
+
+/*
+ * ioc4_intr_connect:
+ * Arrange for interrupts for a sub-device
+ * to be delivered to the right bit of
+ * code with the right parameter.
+ *
+ * XXX- returning an error instead of panicing
+ * might be a good idea (think bugs in loadable
+ * ioc4 sub-devices).
+ */
+
+
+
+void
+ioc4_intr_connect(vertex_hdl_t conn_vhdl,
+		  ioc4_intr_type_t type,
+		  ioc4reg_t intrbits,
+		  ioc4_intr_func_f *intr,
+		  intr_arg_t info,
+		  vertex_hdl_t owner_vhdl,
+		  vertex_hdl_t intr_dev_vhdl)
+{
+    graph_error_t	    rc;
+    vertex_hdl_t	    ioc4_vhdl;
+    ioc4_soft_t		   *soft;
+    ioc4reg_t		    old, bits;
+    int			    i;
+
+    ASSERT((type == ioc4_sio_intr_type) || (type == ioc4_other_intr_type));
+
+    rc = hwgraph_traverse(conn_vhdl, EDGE_LBL_IOC4, &ioc4_vhdl);
+    if (rc != GRAPH_SUCCESS) {
+	printk(KERN_ALERT "ioc4_intr_connect(%p): ioc4_attach not yet called", (void *)owner_vhdl);
+	return;
+    }
+
+    soft = ioc4_soft_get(ioc4_vhdl);
+    ASSERT(soft != NULL);
+
+    /*
+     * Try to allocate a slot in the array
+     * that has been marked free; if there
+     * are none, extend the high water mark.
+     */
+    while (1) {
+	bits = atomic_read(&soft->is_intr_type[type].is_intr_ents_free);
+	if (bits == 0) {
+	    i = atomic_inc(&soft->is_intr_type[type].is_num_intrs) - 1;
+	    ASSERT(i < MAX_IOC4_INTR_ENTS || (printk("i %d\n", i), 0));
+	    break;
+	}
+	bits &= ~(bits - 1);	/* keep only the ls bit */
+	old = atomicClearInt(&soft->is_intr_type[type].is_intr_ents_free, bits);
+	if (bits & old) {
+		ioc4reg_t		shf;
+
+		i = 31;
+		if ((shf = (bits >> 16)))
+		    bits = shf;
+		else
+		    i -= 16;
+		if ((shf = (bits >> 8)))
+		    bits = shf;
+		else
+		    i -= 8;
+		if ((shf = (bits >> 4)))
+		    bits = shf;
+		else
+		    i -= 4;
+		if ((shf = (bits >> 2)))
+		    bits = shf;
+		else
+		    i -= 2;
+		if ((shf = (bits >> 1)))
+		    bits = shf;
+		else
+		    i -= 1;
+	    ASSERT(i < MAX_IOC4_INTR_ENTS || (printk("i %d\n", i), 0));
+	    break;
+	}
+    }
+
+    soft->is_intr_type[type].is_intr_info[i].sd_bits = intrbits;
+    soft->is_intr_type[type].is_intr_info[i].sd_intr = intr;
+    soft->is_intr_type[type].is_intr_info[i].sd_info = info;
+    soft->is_intr_type[type].is_intr_info[i].sd_vhdl = owner_vhdl;
+    soft->is_intr_type[type].is_intr_info[i].sd_soft = soft;
+
+    /* Make sure there are no bitmask overlaps */
+    {
+	ioc4reg_t		old;
+
+	old = atomicSetInt(&soft->is_intr_type[type].is_intr_bits_busy, intrbits);
+	if (old & intrbits) {
+	    printk("%p: trying to share ioc4 intr bits 0x%X\n",
+		    (void *)owner_vhdl, old & intrbits);
+
+#if DEBUG && IOC4_DEBUG
+	    {
+		int			x;
+
+		for (x = 0; x < i; x++)
+		    if (intrbits & soft->is_intr_type[type].is_intr_info[x].sd_bits) {
+			printk("%p: ioc4 intr bits 0x%X already call "
+				"0x%X(0x%X, ...)\n",
+				(void *)soft->is_intr_type[type].is_intr_info[x].sd_vhdl,
+				soft->is_intr_type[type].is_intr_info[i].sd_bits,
+				soft->is_intr_type[type].is_intr_info[i].sd_intr,
+				soft->is_intr_type[type].is_intr_info[i].sd_info);
+		    }
+	    }
+#endif
+	    panic("ioc4_intr_connect: no IOC4 interrupt source sharing allowed");
+	}
+    }
+}
+
+/*
+ * ioc4_intr_disconnect:
+ * Turn off interrupt request service for a
+ * specific service function and argument.
+ * Scans the array for connections to the specified
+ * function with the specified info and owner; turns off
+ * the bits specified in intrbits.  If this results in
+ * an empty entry, logs it in the free entry map.
+ */
+void
+ioc4_intr_disconnect(vertex_hdl_t conn_vhdl,
+		     ioc4_intr_type_t type,
+		     ioc4reg_t intrbits,
+		     ioc4_intr_func_f *intr,
+		     intr_arg_t info,
+		     vertex_hdl_t owner_vhdl)
+{
+    graph_error_t	    rc;
+    vertex_hdl_t	    ioc4_vhdl;
+    ioc4_soft_t		   *soft;
+    ioc4reg_t		    bits;
+    int			    i, num_intrs;
+
+    ASSERT((type == ioc4_sio_intr_type) || (type == ioc4_other_intr_type));
+
+    rc = hwgraph_traverse(conn_vhdl, EDGE_LBL_IOC4, &ioc4_vhdl);
+    if (rc != GRAPH_SUCCESS) {
+	printk(KERN_ALERT "%p: ioc4_intr_disconnect: ioc4_attach not yet called", (void *)owner_vhdl);
+	return;
+    }
+
+    soft = ioc4_soft_get(ioc4_vhdl);
+    ASSERT(soft != NULL);
+
+    num_intrs = (int)atomic_read(&soft->is_intr_type[type].is_num_intrs);
+    for (i = 0; i < num_intrs; ++i) {
+	if ((soft->is_intr_type[type].is_intr_info[i].sd_intr == intr) &&
+	    	(soft->is_intr_type[type].is_intr_info[i].sd_info == info) &&
+	    	(soft->is_intr_type[type].is_intr_info[i].sd_vhdl == owner_vhdl) &&
+	    	(bits = soft->is_intr_type[type].is_intr_info[i].sd_bits & intrbits)) {
+	    soft->is_intr_type[type].is_intr_info[i].sd_bits &= ~bits;
+	    atomicClearInt(&soft->is_intr_type[type].is_intr_bits_busy, bits);
+	    if (!(soft->is_intr_type[type].is_intr_info[i].sd_bits)) {
+		soft->is_intr_type[type].is_intr_info[i].sd_intr = NULL;
+		soft->is_intr_type[type].is_intr_info[i].sd_info = NULL;
+		soft->is_intr_type[type].is_intr_info[i].sd_vhdl = GRAPH_VERTEX_NONE;
+		atomicSetInt(&soft->is_intr_type[type].is_intr_ents_free, 1 << i);
+	    }
+	}
+    }
+}
+
+/* Top level IOC4 interrupt handler.  Farms out the interrupt to
+ * the various IOC4 device drivers.
+ */
+
+void
+ioc4_intr(int irq, void *arg, struct pt_regs *regs)
+{
+    ioc4_soft_t		   *soft;
+    ioc4reg_t		    this_ir;
+    ioc4reg_t		    this_mir;
+    int			    x, num_intrs = 0;
+    ioc4_intr_type_t        t;
+
+    soft = (ioc4_soft_t *)arg;
+
+    if (!soft)
+	return;			/* Polled but no console ioc4 registered */
+
+    for (t = ioc4_first_intr_type; t < ioc4_num_intr_types; t++) {
+        num_intrs = (int)atomic_read(&soft->is_intr_type[t].is_num_intrs);
+
+        this_mir = this_ir = ioc4_pending_intrs(soft, t);
+#ifdef DEBUG_INTERRUPTS
+	printk("%s : %d : this_mir 0x%x num_intrs %d\n", __FUNCTION__, __LINE__, this_mir, num_intrs);
+#endif
+
+        /* Farm out the interrupt to the various drivers depending on
+         * which interrupt bits are set.
+	 */
+        for (x = 0; x < num_intrs; x++) {
+		struct ioc4_intr_info  *ii = &soft->is_intr_type[t].is_intr_info[x];
+		if ((this_mir = this_ir & ii->sd_bits)) {
+			/* Disable owned interrupts, and call the interrupt handler */
+			IOC4_WRITE_IEC(soft, ii->sd_bits, t);
+			ii->sd_intr(ii->sd_info, this_mir);
+			this_ir &= ~this_mir;
+		}
+	}
+
+	if (this_ir)
+		printk(KERN_ALERT "unknown IOC4 %s interrupt 0x%x, sio_ir = 0x%x, sio_ies = 0x%x, other_ir = 0x%x, other_ies = 0x%x\n",
+				(t == ioc4_sio_intr_type) ? "sio" : "other",
+				this_ir,
+				soft->is_ioc4_mem->sio_ir,
+				soft->is_ioc4_mem->sio_ies_ro,
+				soft->is_ioc4_mem->other_ir,
+				soft->is_ioc4_mem->other_ies_ro);
+    }
+#ifdef DEBUG_INTERRUPTS
+    {
+	ioc4_mem_t  *mem = soft->is_ioc4_mem;
+	spinlock_t  *lp = &soft->is_ir_lock;
+	unsigned long           s;
+
+	spin_lock_irqsave(lp, s);
+	printk("%s : %d : sio_ir 0x%x sio_ies_ro 0x%x other_ir 0x%x other_ies_ro 0x%x mask 0x%x\n",
+			__FUNCTION__, __LINE__,
+			mem->sio_ir,
+			mem->sio_ies_ro,
+			mem->other_ir,
+			mem->other_ies_ro,
+			IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
+
+	spin_unlock_irqrestore(lp, s);
+    }
+#endif
+}
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/ioc4/sio_ioc4.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/ioc4/sio_ioc4.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/ioc4/sio_ioc4.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/ioc4/sio_ioc4.c	2003-09-12 12:44:35.000000000 -0700
@@ -0,0 +1,2266 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+/*
+ * This is a lower level module for the modular serial I/O driver. This
+ * module implements all hardware dependent functions for doing serial
+ * I/O on the IOC4 serial ports.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/sn/types.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/driver.h>
+#include <asm/sn/iograph.h>
+#include <asm/param.h>
+#include <asm/atomic.h>
+#include <asm/delay.h>
+#include <asm/semaphore.h>
+#include <asm/sn/pio.h>
+#include <asm/sn/xtalk/xwidget.h>
+#include <asm/sn/io.h>
+#include <asm/sn/pci/pci_defs.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/ioc4.h>
+#include <asm/sn/serialio.h>
+#include <asm/sn/uart16550.h>
+
+/* #define IOC4_SIO_DEBUG */
+/* define USE_64BIT_DMA */
+
+#define PENDING(port) (PCI_INW(&(port)->ip_ioc4->sio_ir) & port->ip_ienb)
+
+/* Default to 4k buffers */
+#ifdef IOC4_1K_BUFFERS
+#define RING_BUF_SIZE 1024
+#define IOC4_BUF_SIZE_BIT 0
+#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_1K
+#else
+#define RING_BUF_SIZE 4096
+#define IOC4_BUF_SIZE_BIT IOC4_SBBR_L_SIZE
+#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_4K
+#endif
+
+#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4)
+
+#if PAGE_SIZE < TOTAL_RING_BUF_SIZE
+#include <sys/pfdat.h>
+#endif
+
+
+#ifdef DPRINTF
+#define dprintf(x) printk x
+#else
+#define dprintf(x)
+#endif
+
+#define	NEWA(ptr,n)	(ptr = snia_kmem_zalloc((n)*sizeof (*(ptr))))
+
+#define	contig_memalloc(a,b,c)	kmem_zalloc(PAGE_SIZE * (a))
+#define sio_port_islocked(a)	0	// FIXME: ?????
+
+#define KM_PHYSCONTIG   0x0008
+#define VM_DIRECT       KM_PHYSCONTIG
+#define VM_PHYSCONTIG   KM_PHYSCONTIG
+
+#ifdef DEBUG
+#define PROGRESS()	printk("%s : %d\n", __FUNCTION__, __LINE__)
+#define NOT_PROGRESS()	printk("%s : %d - Error\n", __FUNCTION__, __LINE__)
+#else
+#define PROGRESS()	;
+#define NOT_PROGRESS()	;
+#endif
+
+static __inline__ void *
+kvpalloc(size_t size, int flags, int colour)
+{
+        if (flags & (VM_DIRECT|VM_PHYSCONTIG)) {
+                int order = 0;
+                while ((PAGE_SIZE << order) < (size << PAGE_SHIFT))
+                        order++;
+                return (void *) __get_free_pages(GFP_KERNEL, order);
+        } else
+                return vmalloc(size << PAGE_SHIFT);
+}
+
+/* Local port info for the IOC4 serial ports.  This contains as its
+ * first member the global sio port private data.
+ */
+typedef struct ioc4port {
+    sioport_t		ip_sioport;	/* Must be first struct entry! */
+
+    vertex_hdl_t	ip_conn_vhdl;	/* vhdl to use for pciio requests */
+    vertex_hdl_t	ip_port_vhdl;	/* vhdl for the serial port */
+
+    /* Base piomap addr of the ioc4 board this port is on
+     * and associated serial map;  serial map includes uart registers.
+     */
+    ioc4_mem_t	       *ip_ioc4;
+    ioc4_sregs_t       *ip_serial;
+    ioc4_uart_t        *ip_uart;
+
+    /* Ring buffer page for this port */
+    caddr_t		ip_ring_buf_k0;	/* Ring buffer location in K0 space */
+
+    /* Rings for this port */
+    struct ring	       *ip_inring;
+    struct ring	       *ip_outring;
+
+    /* Hook to port specific values for this port */
+    struct hooks       *ip_hooks;
+
+    int			ip_flags;
+
+    /* Cache of DCD/CTS bits last received */
+    char                ip_modem_bits;
+
+    /* Various rx/tx parameters */
+    int                 ip_baud;
+    int                 ip_tx_lowat;
+    int                 ip_rx_timeout;
+
+    /* Copy of notification bits */
+    int                 ip_notify;
+
+    /* Shadow copies of various registers so we don't need to PIO
+     * read them constantly
+     */
+    ioc4reg_t           ip_ienb;          /* Enabled interrupts */
+
+    ioc4reg_t           ip_sscr;
+
+    ioc4reg_t           ip_tx_prod;
+    ioc4reg_t           ip_rx_cons;
+
+    /* Back pointer to ioc4 soft area */
+    void               *ip_ioc4_soft;
+} ioc4port_t;
+
+#if DEBUG
+#define     MAXSAVEPORT 256
+static int         next_saveport = 0;
+static ioc4port_t *saveport[MAXSAVEPORT];
+#endif
+
+/* TX low water mark.  We need to notify the driver whenever TX is getting
+ * close to empty so it can refill the TX buffer and keep things going.
+ * Let's assume that if we interrupt 1 ms before the TX goes idle, we'll
+ * have no trouble getting in more chars in time (I certainly hope so).
+ */
+#define TX_LOWAT_LATENCY      1000
+#define TX_LOWAT_HZ          (1000000 / TX_LOWAT_LATENCY)
+#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ)
+
+/* Flags per port */
+#define INPUT_HIGH	0x01
+#define DCD_ON		0x02
+#define LOWAT_WRITTEN	0x04
+#define READ_ABORTED	0x08
+#define TX_DISABLED	0x10
+
+/* Get local port type from global sio port type */
+#define LPORT(port) ((ioc4port_t *) (port))
+
+/* Get global port from local port type */
+#define GPORT(port) ((sioport_t *) (port))
+
+/* Since each port has different register offsets and bitmasks
+ * for everything, we'll store those that we need in tables so we
+ * don't have to be constantly checking the port we are dealing with.
+ */
+struct hooks {
+    ioc4reg_t intr_delta_dcd;
+    ioc4reg_t intr_delta_cts;
+    ioc4reg_t intr_tx_mt;
+    ioc4reg_t intr_rx_timer;
+    ioc4reg_t intr_rx_high;
+    ioc4reg_t intr_tx_explicit;
+    ioc4reg_t intr_dma_error;
+    ioc4reg_t intr_clear;
+    ioc4reg_t intr_all;
+    char      rs422_select_pin;
+};
+
+static struct hooks hooks_array[4] =
+{
+    /* Values for port 0 */
+    {
+	IOC4_SIO_IR_S0_DELTA_DCD,
+	IOC4_SIO_IR_S0_DELTA_CTS,
+	IOC4_SIO_IR_S0_TX_MT,
+	IOC4_SIO_IR_S0_RX_TIMER,
+	IOC4_SIO_IR_S0_RX_HIGH,
+	IOC4_SIO_IR_S0_TX_EXPLICIT,
+	IOC4_OTHER_IR_S0_MEMERR,
+	(IOC4_SIO_IR_S0_TX_MT | IOC4_SIO_IR_S0_RX_FULL |
+         IOC4_SIO_IR_S0_RX_HIGH | IOC4_SIO_IR_S0_RX_TIMER |
+         IOC4_SIO_IR_S0_DELTA_DCD | IOC4_SIO_IR_S0_DELTA_CTS |
+	 IOC4_SIO_IR_S0_INT | IOC4_SIO_IR_S0_TX_EXPLICIT),
+	IOC4_SIO_IR_S0,
+	IOC4_GPPR_UART0_MODESEL_PIN,
+    },
+
+    /* Values for port 1 */
+    {
+	IOC4_SIO_IR_S1_DELTA_DCD,
+	IOC4_SIO_IR_S1_DELTA_CTS,
+	IOC4_SIO_IR_S1_TX_MT,
+	IOC4_SIO_IR_S1_RX_TIMER,
+	IOC4_SIO_IR_S1_RX_HIGH,
+	IOC4_SIO_IR_S1_TX_EXPLICIT,
+	IOC4_OTHER_IR_S1_MEMERR,
+	(IOC4_SIO_IR_S1_TX_MT | IOC4_SIO_IR_S1_RX_FULL |
+         IOC4_SIO_IR_S1_RX_HIGH | IOC4_SIO_IR_S1_RX_TIMER |
+         IOC4_SIO_IR_S1_DELTA_DCD | IOC4_SIO_IR_S1_DELTA_CTS |
+	 IOC4_SIO_IR_S1_INT | IOC4_SIO_IR_S1_TX_EXPLICIT),
+	IOC4_SIO_IR_S1,
+	IOC4_GPPR_UART1_MODESEL_PIN,
+    },
+
+    /* Values for port 2 */
+    {
+	IOC4_SIO_IR_S2_DELTA_DCD,
+	IOC4_SIO_IR_S2_DELTA_CTS,
+	IOC4_SIO_IR_S2_TX_MT,
+	IOC4_SIO_IR_S2_RX_TIMER,
+	IOC4_SIO_IR_S2_RX_HIGH,
+	IOC4_SIO_IR_S2_TX_EXPLICIT,
+	IOC4_OTHER_IR_S2_MEMERR,
+	(IOC4_SIO_IR_S2_TX_MT | IOC4_SIO_IR_S2_RX_FULL |
+         IOC4_SIO_IR_S2_RX_HIGH | IOC4_SIO_IR_S2_RX_TIMER |
+         IOC4_SIO_IR_S2_DELTA_DCD | IOC4_SIO_IR_S2_DELTA_CTS |
+	 IOC4_SIO_IR_S2_INT | IOC4_SIO_IR_S2_TX_EXPLICIT),
+	IOC4_SIO_IR_S2,
+	IOC4_GPPR_UART2_MODESEL_PIN,
+    },
+
+    /* Values for port 3 */
+    {
+	IOC4_SIO_IR_S3_DELTA_DCD,
+	IOC4_SIO_IR_S3_DELTA_CTS,
+	IOC4_SIO_IR_S3_TX_MT,
+	IOC4_SIO_IR_S3_RX_TIMER,
+	IOC4_SIO_IR_S3_RX_HIGH,
+	IOC4_SIO_IR_S3_TX_EXPLICIT,
+	IOC4_OTHER_IR_S3_MEMERR,
+	(IOC4_SIO_IR_S3_TX_MT | IOC4_SIO_IR_S3_RX_FULL |
+         IOC4_SIO_IR_S3_RX_HIGH | IOC4_SIO_IR_S3_RX_TIMER |
+         IOC4_SIO_IR_S3_DELTA_DCD | IOC4_SIO_IR_S3_DELTA_CTS |
+	 IOC4_SIO_IR_S3_INT | IOC4_SIO_IR_S3_TX_EXPLICIT),
+	IOC4_SIO_IR_S3,
+	IOC4_GPPR_UART3_MODESEL_PIN,
+    }
+};
+
+/* Macros to get into the port hooks.  Require a variable called
+ * hooks set to port->hooks
+ */
+#define H_INTR_TX_MT	   hooks->intr_tx_mt
+#define H_INTR_RX_TIMER    hooks->intr_rx_timer
+#define H_INTR_RX_HIGH	   hooks->intr_rx_high
+#define H_INTR_TX_EXPLICIT hooks->intr_tx_explicit
+#define H_INTR_DMA_ERROR   hooks->intr_dma_error
+#define H_INTR_CLEAR	   hooks->intr_clear
+#define H_INTR_DELTA_DCD   hooks->intr_delta_dcd
+#define H_INTR_DELTA_CTS   hooks->intr_delta_cts
+#define H_INTR_ALL	   hooks->intr_all
+#define H_RS422		   hooks->rs422_select_pin
+
+/* A ring buffer entry */
+struct ring_entry {
+    union {
+	struct {
+	    uint32_t alldata;
+	    uint32_t allsc;
+	} all;
+	struct {
+	    char data[4];	/* data bytes */
+	    char sc[4];		/* status/control */
+	} s;
+    } u;
+};
+
+/* Test the valid bits in any of the 4 sc chars using "allsc" member */
+#define RING_ANY_VALID \
+	((uint32_t) (IOC4_RXSB_MODEM_VALID | IOC4_RXSB_DATA_VALID) * 0x01010101)
+
+#define ring_sc     u.s.sc
+#define ring_data   u.s.data
+#define ring_allsc  u.all.allsc
+
+/* Number of entries per ring buffer. */
+#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry))
+
+/* An individual ring */
+struct ring {
+    struct ring_entry entries[ENTRIES_PER_RING];
+};
+
+/* The whole enchilada */
+struct ring_buffer {
+        struct ring TX_0_OR_2;
+        struct ring RX_0_OR_2;
+        struct ring TX_1_OR_3;
+        struct ring RX_1_OR_3;
+};
+
+/* Get a ring from a port struct */
+#define RING(port, which) \
+    &(((struct ring_buffer *) ((port)->ip_ring_buf_k0))->which)
+
+/* Local functions: */
+static int ioc4_open		(sioport_t *port);
+static int ioc4_config		(sioport_t *port, int baud, int byte_size,
+				 int stop_bits, int parenb, int parodd);
+static int ioc4_enable_hfc	(sioport_t *port, int enable);
+static int ioc4_set_extclk	(sioport_t *port, int clock_factor);
+
+/* Data transmission */
+static int do_ioc4_write	(sioport_t *port, char *buf, int len);
+static int ioc4_write		(sioport_t *port, char *buf, int len);
+static int ioc4_sync_write	(sioport_t *port, char *buf, int len);
+static void ioc4_wrflush	(sioport_t *port);
+static int ioc4_break		(sioport_t *port, int brk);
+static int ioc4_enable_tx	(sioport_t *port, int enb);
+
+/* Data reception */
+static int ioc4_read		(sioport_t *port, char *buf, int len);
+
+/* Event notification */
+static int ioc4_notification	(sioport_t *port, int mask, int on);
+static int ioc4_rx_timeout	(sioport_t *port, int timeout);
+
+/* Modem control */
+static int ioc4_set_DTR		(sioport_t *port, int dtr);
+static int ioc4_set_RTS		(sioport_t *port, int rts);
+static int ioc4_query_DCD	(sioport_t *port);
+static int ioc4_query_CTS	(sioport_t *port);
+
+/* Output mode */
+static int ioc4_set_proto	(sioport_t *port, enum sio_proto proto);
+
+/* User mapped driver support */
+static int ioc4_get_mapid	(sioport_t *port, void *arg);
+static int ioc4_set_sscr	(sioport_t *port, int arg, int flag);
+
+static struct serial_calldown ioc4_calldown = {
+    ioc4_open,
+    ioc4_config,
+    ioc4_enable_hfc,
+    ioc4_set_extclk,
+    ioc4_write,
+    ioc4_sync_write,
+    ioc4_wrflush,	/* du flush */
+    ioc4_break,
+    ioc4_enable_tx,
+    ioc4_read,
+    ioc4_notification,
+    ioc4_rx_timeout,
+    ioc4_set_DTR,
+    ioc4_set_RTS,
+    ioc4_query_DCD,
+    ioc4_query_CTS,
+    ioc4_set_proto,
+    ioc4_get_mapid,
+    0,
+    0,
+    ioc4_set_sscr
+};
+
+/* Baud rate stuff */
+#define SET_BAUD(p, b) set_baud_ti(p, b)
+static int set_baud_ti(ioc4port_t *, int);
+
+#ifdef DEBUG
+/* Performance characterization logging */
+#define DEBUGINC(x,i) stats.x += i
+
+static struct {
+
+    /* Ports present */
+    uint ports;
+
+    /* Ports killed */
+    uint killed;
+
+    /* Interrupt counts */
+    uint total_intr;
+    uint port_0_intr;
+    uint port_1_intr;
+    uint ddcd_intr;
+    uint dcts_intr;
+    uint rx_timer_intr;
+    uint rx_high_intr;
+    uint explicit_intr;
+    uint mt_intr;
+    uint mt_lowat_intr;
+
+    /* Write characteristics */
+    uint write_bytes;
+    uint write_cnt;
+    uint wrote_bytes;
+    uint tx_buf_used;
+    uint tx_buf_cnt;
+    uint tx_pio_cnt;691
+
+    /* Read characteristics */
+    uint read_bytes;
+    uint read_cnt;
+    uint drain;
+    uint drainwait;
+    uint resetdma;
+    uint read_ddcd;
+    uint rx_overrun;
+    uint parity;
+    uint framing;
+    uint brk;
+    uint red_bytes;
+    uint rx_buf_used;
+    uint rx_buf_cnt;
+
+    /* Errors */
+    uint dma_lost;
+    uint read_aborted;
+    uint read_aborted_detected;
+} stats;
+
+#else
+#define DEBUGINC(x,i)
+#endif
+
+/* Infinite loop detection.
+ */
+#define MAXITER 1000000
+#define SPIN(cond, success) \
+{ \
+	 int spiniter = 0; \
+	 success = 1; \
+	 while(cond) { \
+		 spiniter++; \
+		 if (spiniter > MAXITER) { \
+			 success = 0; \
+			 break; \
+		 } \
+	 } \
+}
+
+
+static iopaddr_t
+ring_dmatrans(vertex_hdl_t conn_vhdl, caddr_t vaddr)
+{
+    extern iopaddr_t pciio_dma_addr (vertex_hdl_t, device_desc_t, paddr_t,
+                                     size_t, pciio_dmamap_t *, unsigned);
+    iopaddr_t	paddr = (iopaddr_t)vaddr;
+
+    if (conn_vhdl != GRAPH_VERTEX_NONE)
+#ifdef	USE_64BIT_DMA
+        /* Use 64-bit DMA address when the IOC4 supports it */
+        return pciio_dmatrans_addr (conn_vhdl, 0, paddr, TOTAL_RING_BUF_SIZE, PCIIO_DMA_A64 | PCIIO_BYTE_STREAM);
+
+#else
+        /* Use 32-bit DMA address for current IOC4 */ 
+	return pciio_dma_addr (conn_vhdl, 0, paddr, TOTAL_RING_BUF_SIZE, NULL, PCIIO_BYTE_STREAM);
+#endif
+
+    return paddr;
+}
+
+
+/* If interrupt routine called enable_intrs, then would need to write
+ * mask_enable_intrs() routine.
+ */
+static inline void
+mask_disable_intrs(ioc4port_t *port, ioc4reg_t mask)
+{
+    port->ip_ienb &= ~mask;
+}
+
+
+static void
+enable_intrs(ioc4port_t *port, ioc4reg_t mask)
+{
+    struct hooks *hooks = port->ip_hooks;
+ 
+    if ((port->ip_ienb & mask) != mask) {
+	IOC4_WRITE_IES(port->ip_ioc4_soft, mask, ioc4_sio_intr_type);
+	port->ip_ienb |= mask;
+    }
+
+    if (port->ip_ienb)
+        IOC4_WRITE_IES(port->ip_ioc4_soft, H_INTR_DMA_ERROR, ioc4_other_intr_type);
+}
+
+
+static void
+disable_intrs(ioc4port_t *port, ioc4reg_t mask)
+{
+    struct hooks *hooks = port->ip_hooks;
+
+    if (port->ip_ienb & mask) {
+	IOC4_WRITE_IEC(port->ip_ioc4_soft, mask, ioc4_sio_intr_type);
+	port->ip_ienb &= ~mask;
+    }
+
+    if (!port->ip_ienb)
+        IOC4_WRITE_IEC(port->ip_ioc4_soft, H_INTR_DMA_ERROR, ioc4_other_intr_type);
+}
+
+
+/* Service any pending interrupts on the given port */
+static void
+ioc4_serial_intr(intr_arg_t arg, ioc4reg_t sio_ir)
+{
+    ioc4port_t   *port = (ioc4port_t *) arg;
+    sioport_t    *gp = GPORT(port);
+    struct hooks *hooks = port->ip_hooks;
+    unsigned      rx_high_rd_aborted = 0;
+    unsigned int  flags;
+
+    PROGRESS();
+#ifdef NOT_YET
+    ASSERT(sio_port_islocked(gp) == 0);
+#endif
+
+    /* Possible race condition here: The TX_MT interrupt bit may be
+     * cleared without the intervention of the interrupt handler,
+     * e.g. by a write.  If the top level interrupt handler reads a
+     * TX_MT, then some other processor does a write, starting up
+     * output, then we come in here, see the TX_MT and stop DMA, the
+     * output started by the other processor will hang.  Thus we can
+     * only rely on TX_MT being legitimate if it is read while the
+     * port lock is held.  Therefore this bit must be ignored in the
+     * passed in interrupt mask which was read by the top level
+     * interrupt handler since the port lock was not held at the time
+     * it was read.  We can only rely on this bit being accurate if it
+     * is read while the port lock is held.  So we'll clear it for now,
+     * and reload it later once we have the port lock.
+     */
+    sio_ir &= ~(H_INTR_TX_MT);
+
+    SIO_LOCK_PORT(gp, flags);
+
+    dprintf(("interrupt: sio_ir 0x%x\n", sio_ir));
+
+    do {
+	ioc4reg_t shadow;
+
+	/* Handle a DCD change */
+	if (sio_ir & H_INTR_DELTA_DCD) {
+	    DEBUGINC(ddcd_intr, 1);
+
+	    PROGRESS();
+	    /* ACK the interrupt */
+	    PCI_OUTW(&port->ip_ioc4->sio_ir, H_INTR_DELTA_DCD);
+
+	    /* If DCD has raised, notify upper layer.  Otherwise
+	     * wait for a record to be posted to notify of a dropped DCD.
+	     */
+	    shadow = PCI_INW(&port->ip_serial->shadow);
+	    
+            if (port->ip_notify & N_DDCD) {
+		PROGRESS();
+                if (shadow & IOC4_SHADOW_DCD)   /* Notify upper layer of DCD */
+                        UP_DDCD(gp, 1);
+                else
+                        port->ip_flags |= DCD_ON;  /* Flag delta DCD/no DCD */
+	    }
+	}
+
+	/* Handle a CTS change */
+	if (sio_ir & H_INTR_DELTA_CTS) {
+	    DEBUGINC(dcts_intr, 1);
+	    PROGRESS();
+
+	    /* ACK the interrupt */
+	    PCI_OUTW(&port->ip_ioc4->sio_ir, H_INTR_DELTA_CTS);
+
+	    shadow = PCI_INW(&port->ip_serial->shadow);
+
+	    /* Notify upper layer */
+	    if (port->ip_notify & N_DCTS) {
+		if (shadow & IOC4_SHADOW_CTS)
+		    UP_DCTS(gp, 1);
+		else
+		    UP_DCTS(gp, 0);
+	    }
+	}
+
+	/* RX timeout interrupt.  Must be some data available.  Put this
+	 * before the check for RX_HIGH since servicing this condition
+	 * may cause that condition to clear.
+	 */
+	if (sio_ir & H_INTR_RX_TIMER) {
+	    PROGRESS();
+	    DEBUGINC(rx_timer_intr, 1);
+
+	    /* ACK the interrupt */
+	    PCI_OUTW(&port->ip_ioc4->sio_ir, H_INTR_RX_TIMER);
+
+	    if (port->ip_notify & N_DATA_READY)
+		UP_DATA_READY(gp);
+	}
+
+	/* RX high interrupt. Must be after RX_TIMER.
+	 */
+	else if (sio_ir & H_INTR_RX_HIGH) {
+	    DEBUGINC(rx_high_intr, 1);
+
+	    PROGRESS();
+	    /* Data available, notify upper layer */
+	    if (port->ip_notify & N_DATA_READY)
+		UP_DATA_READY(gp);
+
+	    /* We can't ACK this interrupt.  If up_data_ready didn't
+	     * cause the condition to clear, we'll have to disable
+	     * the interrupt until the data is drained by the upper layer.
+	     * If the read was aborted, don't disable the interrupt as
+	     * this may cause us to hang indefinitely.  An aborted read
+	     * generally means that this interrupt hasn't been delivered
+	     * to the cpu yet anyway, even though we see it as asserted 
+	     * when we read the sio_ir.
+	     */
+	    if ((sio_ir = PENDING(port)) & H_INTR_RX_HIGH) {
+		PROGRESS();
+		if ((port->ip_flags & READ_ABORTED) == 0) {
+		    mask_disable_intrs(port, H_INTR_RX_HIGH);
+		    port->ip_flags |= INPUT_HIGH;
+		}
+		else {
+		    DEBUGINC(read_aborted_detected, 1);
+		    /* We will be stuck in this loop forever,
+		     * higher level will never get time to finish
+		     */
+		    rx_high_rd_aborted++;
+		}
+	    }
+	}
+
+	/* We got a low water interrupt: notify upper layer to
+	 * send more data.  Must come before TX_MT since servicing
+	 * this condition may cause that condition to clear.
+	 */
+	if (sio_ir & H_INTR_TX_EXPLICIT) {
+	    DEBUGINC(explicit_intr, 1);
+	    PROGRESS();
+
+	    port->ip_flags &= ~LOWAT_WRITTEN;
+
+	    /* ACK the interrupt */
+	    PCI_OUTW(&port->ip_ioc4->sio_ir, H_INTR_TX_EXPLICIT);
+
+	    if (port->ip_notify & N_OUTPUT_LOWAT)
+		UP_OUTPUT_LOWAT(gp);
+	}
+
+	/* Handle TX_MT.  Must come after TX_EXPLICIT.
+	 */
+	else if (sio_ir & H_INTR_TX_MT) {
+	    DEBUGINC(mt_intr, 1);
+	    PROGRESS();
+
+	    /* If the upper layer is expecting a lowat notification
+	     * and we get to this point it probably means that for
+	     * some reason the TX_EXPLICIT didn't work as expected
+	     * (that can legitimately happen if the output buffer is
+	     * filled up in just the right way).  So sent the notification
+	     * now.
+	     */
+	    if (port->ip_notify & N_OUTPUT_LOWAT) {
+		DEBUGINC(mt_lowat_intr, 1);
+		PROGRESS();
+
+		if (port->ip_notify & N_OUTPUT_LOWAT)
+		    UP_OUTPUT_LOWAT(gp);
+
+		/* We need to reload the sio_ir since the upcall may
+		 * have caused another write to occur, clearing
+		 * the TX_MT condition.
+		 */
+		sio_ir = PENDING(port);
+	    }
+
+	    /* If the TX_MT condition still persists even after the upcall,
+	     * we've got some work to do.
+	     */
+	    if (sio_ir & H_INTR_TX_MT) {
+
+		PROGRESS();
+
+		/* If we are not currently expecting DMA input, and the
+		 * transmitter has just gone idle, there is no longer any
+		 * reason for DMA, so disable it.
+		 */
+		if (!(port->ip_notify & (N_DATA_READY | N_DDCD))) {
+		    ASSERT(port->ip_sscr & IOC4_SSCR_DMA_EN);
+		    port->ip_sscr &= ~IOC4_SSCR_DMA_EN;
+		    PCI_OUTW(&port->ip_serial->sscr, port->ip_sscr);
+		}
+
+		/* Prevent infinite TX_MT interrupt */
+		mask_disable_intrs(port, H_INTR_TX_MT);
+	    }
+	}
+
+	sio_ir = PENDING(port);
+
+	/* if the read was aborted and only H_INTR_RX_HIGH,
+	 * clear H_INTR_RX_HIGH, so we do not loop forever.
+	 */
+
+	if ( rx_high_rd_aborted && (sio_ir == H_INTR_RX_HIGH) ) {
+	    sio_ir &= ~H_INTR_RX_HIGH;
+	}
+    } while (sio_ir & H_INTR_ALL);
+
+    SIO_UNLOCK_PORT(gp, flags);
+
+    /* Re-enable interrupts before returning from interrupt handler.
+     * Getting interrupted here is okay.  It'll just v() our semaphore, and
+     * we'll come through the loop again.
+     */
+
+    IOC4_WRITE_IES(port->ip_ioc4_soft, port->ip_ienb, ioc4_sio_intr_type);
+}
+
+
+/*ARGSUSED*/
+
+/* Service any pending DMA error interrupts on the given port */
+static void
+ioc4_dma_error_intr(intr_arg_t arg, ioc4reg_t other_ir)
+{
+    ioc4port_t   *port = (ioc4port_t *) arg;
+    sioport_t    *gp = GPORT(port);
+    struct hooks *hooks = port->ip_hooks;
+    unsigned int flags;
+
+    SIO_LOCK_PORT(gp, flags);
+
+    dprintf(("interrupt: other_ir 0x%x\n", other_ir));
+
+    /* ACK the interrupt */
+    PCI_OUTW(&port->ip_ioc4->other_ir, H_INTR_DMA_ERROR);
+
+    printk( "DMA error on serial port %p\n", (void *)port->ip_port_vhdl);
+
+    if (port->ip_ioc4->pci_err_addr_l & IOC4_PCI_ERR_ADDR_VLD) {
+        printk( "PCI error address is 0x%lx, master is serial port %c %s\n", 
+                ((uint64_t) port->ip_ioc4->pci_err_addr_h << 32) |
+                (port->ip_ioc4->pci_err_addr_l & IOC4_PCI_ERR_ADDR_ADDR_MSK),
+                '1' + (char) ((port->ip_ioc4->pci_err_addr_l &
+                                         IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1),
+                (port->ip_ioc4->pci_err_addr_l & IOC4_PCI_ERR_ADDR_MST_TYP_MSK) 
+                                                               ? "RX" : "TX");
+
+        if (port->ip_ioc4->pci_err_addr_l & IOC4_PCI_ERR_ADDR_MUL_ERR)
+            printk( "Multiple errors occurred\n"); 
+    }
+
+    SIO_UNLOCK_PORT(gp, flags);
+
+    /* Re-enable DMA error interrupts */
+    IOC4_WRITE_IES(port->ip_ioc4_soft, H_INTR_DMA_ERROR, ioc4_other_intr_type);
+}
+
+
+/* Baud rate setting code */
+static int
+set_baud_ti(ioc4port_t *port, int baud)
+{
+    int            actual_baud;
+    int            diff;
+    int            lcr;
+    unsigned short divisor;
+
+    divisor = SER_DIVISOR(baud, IOC4_SER_XIN_CLK);
+    if (!divisor)
+        return(1);
+    actual_baud = DIVISOR_TO_BAUD(divisor, IOC4_SER_XIN_CLK);
+
+    diff = actual_baud - baud;
+    if (diff < 0)
+        diff = -diff;
+
+    /* If we're within 1%, we've found a match */
+    if (diff * 100 > actual_baud)
+        return(1);
+
+    lcr = PCI_INB(&port->ip_uart->i4u_lcr);
+
+    PCI_OUTB(&port->ip_uart->i4u_lcr, lcr | LCR_DLAB);
+
+    PCI_OUTB(&port->ip_uart->i4u_dll, (char) divisor); 
+
+    PCI_OUTB(&port->ip_uart->i4u_dlm, (char) (divisor >> 8));
+
+    PCI_OUTB(&port->ip_uart->i4u_lcr, lcr);
+
+    return(0);
+}
+
+
+/* Initialize the sio and ioc4 hardware for a given port */
+static int
+hardware_init(ioc4port_t *port)
+{
+    ioc4reg_t     sio_cr;
+    struct hooks *hooks = port->ip_hooks;
+
+    DEBUGINC(ports, 1);
+
+    /* Idle the IOC4 serial interface */
+    PCI_OUTW(&port->ip_serial->sscr, IOC4_SSCR_RESET);
+
+    /* Wait until any pending bus activity for this port has ceased */
+    do sio_cr = PCI_INW(&port->ip_ioc4->sio_cr);
+    while(!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE));
+
+    /* Finish reset sequence */
+    PCI_OUTW(&port->ip_serial->sscr, 0);
+
+    /* Once RESET is done, reload cached tx_prod and rx_cons values
+     * and set rings to empty by making prod == cons
+     */
+    port->ip_tx_prod = PCI_INW(&port->ip_serial->stcir) & PROD_CONS_MASK;
+    PCI_OUTW(&port->ip_serial->stpir, port->ip_tx_prod);
+
+    port->ip_rx_cons = PCI_INW(&port->ip_serial->srpir) & PROD_CONS_MASK;
+    PCI_OUTW(&port->ip_serial->srcir, port->ip_rx_cons);
+
+    /* Disable interrupts for this 16550 */
+    PCI_OUTB(&port->ip_uart->i4u_lcr, 0); /* clear DLAB */
+    PCI_OUTB(&port->ip_uart->i4u_ier, 0);
+
+    /* Set the default baud */
+    SET_BAUD(port, port->ip_baud);
+
+    /* Set line control to 8 bits no parity */
+    PCI_OUTB(&port->ip_uart->i4u_lcr, LCR_BITS8 | LCR_1_STOP_BITS);
+   
+    /* Enable the FIFOs */ 
+    PCI_OUTB(&port->ip_uart->i4u_fcr, FCR_FIFOEN);
+    /* then reset 16550 FIFOs */
+    PCI_OUTB(&port->ip_uart->i4u_fcr,
+             FCR_FIFOEN | FCR_RxFIFO | FCR_TxFIFO);
+
+    /* Clear modem control register */
+    PCI_OUTB(&port->ip_uart->i4u_mcr, 0);
+
+    /* Clear deltas in modem status register */
+    PCI_INB(&port->ip_uart->i4u_msr);
+
+    /* Only do this once per port pair */
+    if (port->ip_hooks == &hooks_array[0] || port->ip_hooks == &hooks_array[2]) {
+	iopaddr_t             ring_pci_addr;
+        volatile ioc4reg_t   *sbbr_l;
+        volatile ioc4reg_t   *sbbr_h;
+
+        if(port->ip_hooks == &hooks_array[0]) {
+		sbbr_l = &port->ip_ioc4->sbbr01_l;
+		sbbr_h = &port->ip_ioc4->sbbr01_h;
+        }
+	else {
+		sbbr_l = &port->ip_ioc4->sbbr23_l;
+		sbbr_h = &port->ip_ioc4->sbbr23_h;
+	}
+
+	/* Set the DMA address */
+	ring_pci_addr = ring_dmatrans(port->ip_conn_vhdl,
+				      port->ip_ring_buf_k0);
+
+	PCI_OUTW(sbbr_h,
+		 (ioc4reg_t) ((__psunsigned_t) ring_pci_addr >> 32));
+
+	PCI_OUTW(sbbr_l,
+		 ((ioc4reg_t) (int64_t) ring_pci_addr | IOC4_BUF_SIZE_BIT));
+
+#ifdef IOC4_SIO_DEBUG
+	{
+		unsigned int tmp1, tmp2;
+
+		tmp1 = PCI_INW(sbbr_l);
+		tmp2 = PCI_INW(sbbr_h);
+		printk("========== %s : sbbr_l [%p]/0x%x sbbr_h [%p]/0x%x\n",
+				__FUNCTION__, (void *)sbbr_l, tmp1, (void *)sbbr_h, tmp2);
+	}
+#endif
+    }
+
+    /* Set the receive timeout value to 10 msec */
+    PCI_OUTW(&port->ip_serial->srtr, IOC4_SRTR_HZ / 100);
+
+    /* Set RX threshold, enable DMA */
+    /* Set high water mark at 3/4 of full ring */
+    port->ip_sscr = (ENTRIES_PER_RING * 3 / 4);
+
+    PCI_OUTW(&port->ip_serial->sscr, port->ip_sscr);
+
+    /* Disable and clear all serial related interrupt bits */
+    IOC4_WRITE_IEC(port->ip_ioc4_soft, H_INTR_CLEAR, ioc4_sio_intr_type);
+    port->ip_ienb &= ~H_INTR_CLEAR;
+    PCI_OUTW(&port->ip_ioc4->sio_ir, H_INTR_CLEAR);
+
+    return(0);
+}
+
+
+/*
+ * Device initialization.
+ * Called at *_attach() time for each
+ * IOC4 with serial ports in the system.
+ * If vhdl is GRAPH_VERTEX_NONE, do not do
+ * any graph related work; otherwise, it
+ * is the IOC4 vertex that should be used
+ * for requesting pciio services.
+ */
+int
+ioc4_serial_attach(vertex_hdl_t conn_vhdl, void *ioc4)
+{
+    /*REFERENCED*/
+    graph_error_t	rc;
+    ioc4_mem_t	       *ioc4_mem;
+    vertex_hdl_t	port_vhdl, ioc4_vhdl;
+    vertex_hdl_t	intr_dev_vhdl;
+    ioc4port_t	       *port;
+    ioc4port_t	       *ports[4];
+    static char	       *names[] = { "tty/1", "tty/2", "tty/3", "tty/4" };
+    int			x, first_port = -1, last_port = -1;
+    void	       *ioc4_soft;
+    unsigned int        ioc4_revid_min = 62;
+    unsigned int        ioc4_revid;
+
+
+    /* IOC4 firmware must be at least rev 62 */
+    ioc4_revid = pciio_config_get(conn_vhdl, PCI_CFG_REV_ID, 1); 
+
+    if (ioc4_revid < ioc4_revid_min) {
+        printk( "IOC4 serial ports not supported on firmware rev %d, please upgrade to rev %d or higher\n", ioc4_revid, ioc4_revid_min);
+        return -1;
+    }
+
+    first_port = 0;
+    last_port = 3;
+
+    /* Get back pointer to the ioc4 soft area */
+    rc = hwgraph_traverse(conn_vhdl, EDGE_LBL_IOC4, &ioc4_vhdl);
+    ASSERT(rc == GRAPH_SUCCESS);
+    ioc4_soft = (void *)hwgraph_fastinfo_get(ioc4_vhdl);
+
+    /* grab the PIO address */
+    ioc4_mem = (ioc4_mem_t *)ioc4;
+    ASSERT(ioc4_mem != NULL);
+
+    /*
+     * Create port structures for each port
+     */
+    NEWA(port, 4);
+#ifdef IOC4_SIO_DEBUG
+    printk("%s : [addr 0x%p]\n", __FUNCTION__, (void *)port);
+#endif
+    ports[0] = port++;
+    ports[1] = port++;
+    ports[2] = port++;
+    ports[3] = port++;
+
+#if DEBUG
+    {
+	int slot = atomicAddInt(&next_saveport, 4) - 4;
+	saveport[slot] = ports[0];
+	saveport[slot + 1] = ports[1];
+	saveport[slot + 2] = ports[2];
+	saveport[slot + 3] = ports[3];
+	ASSERT(slot < MAXSAVEPORT);
+    }
+#endif
+
+#ifdef DEBUG
+    if ((caddr_t) port != (caddr_t) &(port->ip_sioport))
+	panic("sioport is not first member of ioc4port struct\n");
+#endif
+
+    /* Allocate buffers and jumpstart the hardware.
+     */
+    for (x = first_port; x < (last_port + 1); x++) {
+
+	port = ports[x];
+#ifdef IOC4_SIO_DEBUG
+	printk("%s : initialize port %d [addr 0x%p/0x%p]\n", __FUNCTION__, x, (void *)port,
+								(void *)GPORT(port));
+#endif
+	port->ip_ioc4_soft = ioc4_soft;
+	rc = hwgraph_path_add(conn_vhdl, names[x], &port_vhdl);
+	ASSERT(rc == GRAPH_SUCCESS);
+	port->ip_conn_vhdl = conn_vhdl;
+	port->ip_port_vhdl = port_vhdl;
+	port->ip_ienb	= 0;
+	hwgraph_fastinfo_set(port_vhdl, (arbitrary_info_t) port);
+
+	/* Perform upper layer initialization. Create all device node
+	 * types including rs422 ports.
+	 */
+	ioc4_serial_initport(GPORT(port), x);
+	port->ip_baud = 9600;
+
+	/* Attach the calldown hooks so upper layer can call our
+	 * routines.
+	 */
+	port->ip_sioport.sio_calldown = &ioc4_calldown;
+
+	/* Map in the IOC4 register area */
+	port->ip_ioc4 = ioc4_mem;
+    }
+
+    {
+	/* Port 0 */
+	port = ports[0];
+	port->ip_hooks = &hooks_array[0];
+
+	/* Get direct hooks to the serial regs and uart regs
+	 * for this port
+	 */
+	port->ip_serial = &(port->ip_ioc4->port_0);
+	port->ip_uart = &(port->ip_ioc4->uart_0);
+#ifdef IOC4_SIO_DEBUG
+	printk("==== %s : serial port 0 address 0x%p uart address 0x%p\n",
+				__FUNCTION__, (void *)port->ip_serial, (void *)port->ip_uart);
+#endif
+
+	/* If we don't already have a ring buffer,
+	 * set one up.
+	 */
+	if (port->ip_ring_buf_k0 == 0) {
+
+#if PAGE_SIZE >= TOTAL_RING_BUF_SIZE
+	    if ((port->ip_ring_buf_k0 = kvpalloc(1, VM_DIRECT, 0)) == 0)
+		panic("ioc4_uart driver cannot allocate page\n");
+#else
+	    /* We need to allocate a chunk of memory on a
+	     * TOTAL_RING_BUF_SIZE boundary.
+	     */
+	    {
+		pgno_t pfn;
+		caddr_t vaddr;
+		if ((pfn = contig_memalloc(TOTAL_RING_BUF_SIZE / PAGE_SIZE,
+					   TOTAL_RING_BUF_SIZE / PAGE_SIZE,
+					   VM_DIRECT)) == 0)
+		    panic("ioc4_uart driver cannot allocate page\n");
+		ASSERT(small_pfn(pfn));
+		vaddr = small_pfntova_K0(pfn);
+		(void) COLOR_VALIDATION(pfdat + pfn,
+					colorof(vaddr),
+					0, VM_DIRECT);
+		port->ip_ring_buf_k0 = vaddr;
+	    }
+#endif
+	}
+	ASSERT((((int64_t)port->ip_ring_buf_k0) &
+		(TOTAL_RING_BUF_SIZE - 1)) == 0);
+	memset(port->ip_ring_buf_k0, 0, TOTAL_RING_BUF_SIZE);
+	port->ip_inring = RING(port, RX_0_OR_2);
+	port->ip_outring = RING(port, TX_0_OR_2);
+
+	/* Initialize the hardware for IOC4 */
+	hardware_init(port);
+
+	if (hwgraph_edge_get(ports[0]->ip_port_vhdl, "d", &intr_dev_vhdl) !=
+							GRAPH_SUCCESS) {
+	    intr_dev_vhdl = ports[0]->ip_port_vhdl;
+	}
+
+	/* Attach interrupt handlers */
+	ioc4_intr_connect(conn_vhdl,
+			  ioc4_sio_intr_type,
+			  IOC4_SIO_IR_S0,
+			  ioc4_serial_intr,
+			  ports[0],
+			  ports[0]->ip_port_vhdl,
+			  intr_dev_vhdl);
+
+	ioc4_intr_connect(conn_vhdl,
+			  ioc4_other_intr_type,
+			  IOC4_OTHER_IR_S0_MEMERR,
+			  ioc4_dma_error_intr,
+			  ports[0],
+			  ports[0]->ip_port_vhdl,
+			  intr_dev_vhdl);
+    }
+
+    {
+
+	/* Port 1 */
+	port = ports[1];
+	port->ip_hooks = &hooks_array[1];
+
+	port->ip_serial = &(port->ip_ioc4->port_1);
+	port->ip_uart = &(port->ip_ioc4->uart_1);
+#ifdef IOC4_SIO_DEBUG
+	printk("==== %s : serial port 1 address 0x%p uart address 0x%p\n",
+				__FUNCTION__, (void *)port->ip_serial, (void *)port->ip_uart);
+#endif
+
+	port->ip_ring_buf_k0 = ports[0]->ip_ring_buf_k0;
+	port->ip_inring = RING(port, RX_1_OR_3);
+	port->ip_outring = RING(port, TX_1_OR_3);
+
+	/* Initialize the hardware for IOC4 */
+	hardware_init(port);
+
+	if (hwgraph_edge_get(ports[1]->ip_port_vhdl, "d", &intr_dev_vhdl) !=
+							GRAPH_SUCCESS) {
+	    intr_dev_vhdl = ports[1]->ip_port_vhdl;
+	}
+
+	/* Attach interrupt handler */
+	ioc4_intr_connect(conn_vhdl,
+		          ioc4_sio_intr_type,
+		          IOC4_SIO_IR_S1,
+		          ioc4_serial_intr,
+		          ports[1],
+		          ports[1]->ip_port_vhdl,
+		          intr_dev_vhdl);
+
+	ioc4_intr_connect(conn_vhdl,
+			  ioc4_other_intr_type,
+			  IOC4_OTHER_IR_S1_MEMERR,
+			  ioc4_dma_error_intr,
+			  ports[1],
+			  ports[1]->ip_port_vhdl,
+			  intr_dev_vhdl);
+    }
+
+    {
+
+	/* Port 2 */
+	port = ports[2];
+	port->ip_hooks = &hooks_array[2];
+
+	/* Get direct hooks to the serial regs and uart regs
+	 * for this port
+	 */
+	port->ip_serial = &(port->ip_ioc4->port_2);
+	port->ip_uart = &(port->ip_ioc4->uart_2);
+#ifdef IOC4_SIO_DEBUG
+	printk("==== %s : serial port 2 address 0x%p uart address 0x%p\n",
+				__FUNCTION__, (void *)port->ip_serial, (void *)port->ip_uart);
+#endif
+
+	/* If we don't already have a ring buffer,
+	 * set one up.
+	 */
+	if (port->ip_ring_buf_k0 == 0) {
+
+#if PAGE_SIZE >= TOTAL_RING_BUF_SIZE
+	    if ((port->ip_ring_buf_k0 = kvpalloc(1, VM_DIRECT, 0)) == 0)
+		panic("ioc4_uart driver cannot allocate page\n");
+#else
+
+	    /* We need to allocate a chunk of memory on a
+	     * TOTAL_RING_BUF_SIZE boundary.
+	     */
+	    {
+		pgno_t pfn;
+		caddr_t vaddr;
+		if ((pfn = contig_memalloc(TOTAL_RING_BUF_SIZE / PAGE_SIZE,
+					   TOTAL_RING_BUF_SIZE / PAGE_SIZE,
+					   VM_DIRECT)) == 0)
+		    panic("ioc4_uart driver cannot allocate page\n");
+		ASSERT(small_pfn(pfn));
+		vaddr = small_pfntova_K0(pfn);
+		(void) COLOR_VALIDATION(pfdat + pfn,
+					colorof(vaddr),
+					0, VM_DIRECT);
+		port->ip_ring_buf_k0 = vaddr;
+	    }
+#endif
+
+	}
+	ASSERT((((int64_t)port->ip_ring_buf_k0) &
+		(TOTAL_RING_BUF_SIZE - 1)) == 0);
+	memset(port->ip_ring_buf_k0, 0, TOTAL_RING_BUF_SIZE);
+	port->ip_inring = RING(port, RX_0_OR_2);
+	port->ip_outring = RING(port, TX_0_OR_2);
+
+	/* Initialize the hardware for IOC4 */
+	hardware_init(port);
+
+	if (hwgraph_edge_get(ports[0]->ip_port_vhdl, "d", &intr_dev_vhdl) !=
+							GRAPH_SUCCESS) {
+	    intr_dev_vhdl = ports[2]->ip_port_vhdl;
+	}
+
+	/* Attach interrupt handler */
+	ioc4_intr_connect(conn_vhdl,
+			  ioc4_sio_intr_type,
+			  IOC4_SIO_IR_S2,
+			  ioc4_serial_intr,
+			  ports[2],
+			  ports[2]->ip_port_vhdl,
+			  intr_dev_vhdl);
+
+	ioc4_intr_connect(conn_vhdl,
+			  ioc4_other_intr_type,
+			  IOC4_OTHER_IR_S2_MEMERR,
+			  ioc4_dma_error_intr,
+			  ports[2],
+			  ports[2]->ip_port_vhdl,
+			  intr_dev_vhdl);
+    }
+
+    {
+
+	/* Port 3 */
+	port = ports[3];
+	port->ip_hooks = &hooks_array[3];
+
+	port->ip_serial = &(port->ip_ioc4->port_3);
+	port->ip_uart = &(port->ip_ioc4->uart_3);
+#ifdef IOC4_SIO_DEBUG
+	printk("==== %s : serial port 3 address 0x%p uart address 0x%p\n",
+				__FUNCTION__, (void *)port->ip_serial, (void *)port->ip_uart);
+#endif
+
+	port->ip_ring_buf_k0 = ports[2]->ip_ring_buf_k0;
+	port->ip_inring = RING(port, RX_1_OR_3);
+	port->ip_outring = RING(port, TX_1_OR_3);
+
+	/* Initialize the hardware for IOC4 */
+	hardware_init(port);
+
+	if (hwgraph_edge_get(ports[3]->ip_port_vhdl, "d", &intr_dev_vhdl) !=
+							GRAPH_SUCCESS) {
+	    intr_dev_vhdl = ports[3]->ip_port_vhdl;
+	}
+
+	/* Attach interrupt handler */
+	ioc4_intr_connect(conn_vhdl,
+		          ioc4_sio_intr_type,
+		          IOC4_SIO_IR_S3,
+		          ioc4_serial_intr,
+		          ports[3],
+		          ports[3]->ip_port_vhdl,
+		          intr_dev_vhdl);
+
+	ioc4_intr_connect(conn_vhdl,
+			  ioc4_other_intr_type,
+			  IOC4_OTHER_IR_S3_MEMERR,
+			  ioc4_dma_error_intr,
+			  ports[3],
+			  ports[3]->ip_port_vhdl,
+			  intr_dev_vhdl);
+    }
+
+#ifdef	DEBUG
+    idbg_addfunc( "ioc4dump", idbg_ioc4dump );
+#endif
+
+    return 0;
+}
+
+
+/* Shut down an IOC4 */
+/* ARGSUSED1 */
+void
+ioc4_serial_kill(ioc4port_t *port)
+{
+    DEBUGINC(killed, 1);
+
+    /* Notify upper layer that this port is no longer usable */
+    UP_DETACH(GPORT(port));
+
+    /* Clear everything in the sscr */
+    PCI_OUTW(&port->ip_serial->sscr, 0);
+    port->ip_sscr = 0;
+
+#ifdef DEBUG
+    /* Make sure nobody gets past the lock and accesses the hardware */
+    port->ip_ioc4 = 0;
+    port->ip_serial = 0;
+#endif
+
+}
+
+
+/*
+ * Open a port
+ */
+static int
+ioc4_open(sioport_t *port)
+{
+    ioc4port_t *p = LPORT(port);
+    int         spin_success;
+
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_OPEN));
+#endif
+
+    p->ip_flags = 0;
+    p->ip_modem_bits = 0;
+
+    /* Pause the DMA interface if necessary */
+    if (p->ip_sscr & IOC4_SSCR_DMA_EN) {
+	PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr | IOC4_SSCR_DMA_PAUSE);
+	SPIN((PCI_INW(&p->ip_serial->sscr) & IOC4_SSCR_PAUSE_STATE) == 0,
+             spin_success);
+	if (!spin_success) {
+		NOT_PROGRESS();
+		return(-1);
+	}
+    }
+
+    /* Reset the input fifo.  If the uart received chars while the port
+     * was closed and DMA is not enabled, the uart may have a bunch of
+     * chars hanging around in its RX fifo which will not be discarded
+     * by rclr in the upper layer. We must get rid of them here.
+     */
+    PCI_OUTB(&p->ip_uart->i4u_fcr, FCR_FIFOEN | FCR_RxFIFO);
+
+    /* Set defaults */
+    SET_BAUD(p, 9600);
+
+    PCI_OUTB(&p->ip_uart->i4u_lcr, LCR_BITS8 | LCR_1_STOP_BITS);
+
+    /* Re-enable DMA, set default threshold to intr whenever there is
+     * data available.
+     */
+    p->ip_sscr &= ~IOC4_SSCR_RX_THRESHOLD;
+    p->ip_sscr |= 1; /* default threshold */
+
+    /* Plug in the new sscr.  This implicitly clears the DMA_PAUSE
+     * flag if it was set above
+     */
+    PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr);
+
+    PCI_OUTW(&p->ip_serial->srtr, 0);
+
+    p->ip_tx_lowat = 1;
+
+    dprintf(("ioc4 open successful\n"));
+
+    return(0);
+}
+
+
+/*
+ * Config hardware
+ */
+static int
+ioc4_config(sioport_t *port,
+	    int baud,
+	    int byte_size,
+	    int stop_bits,
+	    int parenb,
+	    int parodd)
+{
+    ioc4port_t *p = LPORT(port);
+    char        lcr, sizebits;
+    int         spin_success;
+
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_CONFIG));
+#endif
+
+    if (SET_BAUD(p, baud))
+	return(1);
+
+    switch(byte_size) {
+      case 5:
+	sizebits = LCR_BITS5;
+	break;
+      case 6:
+	sizebits = LCR_BITS6;
+	break;
+      case 7:
+	sizebits = LCR_BITS7;
+	break;
+      case 8:
+	sizebits = LCR_BITS8;
+	break;
+      default:
+	dprintf(("invalid byte size port 0x%x size %d\n", port, byte_size));
+	return(1);
+    }
+
+    /* Pause the DMA interface if necessary */
+    if (p->ip_sscr & IOC4_SSCR_DMA_EN) {
+	PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr | IOC4_SSCR_DMA_PAUSE);
+	SPIN((PCI_INW(&p->ip_serial->sscr) & IOC4_SSCR_PAUSE_STATE) == 0,
+             spin_success);
+	if (!spin_success) 
+		return(-1);
+    }
+
+    /* Clear relevant fields in lcr */
+    lcr = PCI_INB(&p->ip_uart->i4u_lcr);
+    lcr &= ~(LCR_MASK_BITS_CHAR | LCR_EPS |
+             LCR_PEN | LCR_MASK_STOP_BITS);
+
+    /* Set byte size in lcr */
+    lcr |= sizebits;
+
+    /* Set parity */
+    if (parenb) {
+	lcr |= LCR_PEN;
+	if (!parodd)
+	    lcr |= LCR_EPS;
+    }
+
+    /* Set stop bits */
+    if (stop_bits)
+	lcr |= LCR_2_STOP_BITS;
+
+    PCI_OUTB(&p->ip_uart->i4u_lcr, lcr);
+
+    dprintf(("ioc4_config: lcr bits 0x%x\n", lcr));
+
+    /* Re-enable the DMA interface if necessary */
+    if (p->ip_sscr & IOC4_SSCR_DMA_EN) {
+	PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr);
+    }
+
+    p->ip_baud = baud;
+
+    /* When we get within this number of ring entries of filling the
+     * entire ring on TX, place an EXPLICIT intr to generate a lowat
+     * notification when output has drained.
+     */
+    p->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4;
+    if (p->ip_tx_lowat == 0)
+	p->ip_tx_lowat = 1;
+
+    ioc4_rx_timeout(port, p->ip_rx_timeout);
+
+    return(0);
+}
+
+
+/*
+ * Enable hardware flow control
+ */
+static int
+ioc4_enable_hfc(sioport_t *port, int enable)
+{
+    ioc4port_t *p = LPORT(port);
+
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_ENABLE_HFC));
+#endif
+
+    dprintf(("enable hfc port 0x%p, enb %d\n", (void *)port, enable));
+
+    if (enable)
+	p->ip_sscr |= IOC4_SSCR_HFC_EN;
+    else
+	p->ip_sscr &= ~IOC4_SSCR_HFC_EN;
+
+    PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr);
+
+    return(0);
+}
+
+
+/*
+ * Set external clock
+ */
+/*ARGSUSED*/
+static int
+ioc4_set_extclk(sioport_t *port, int clock_factor)
+{
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_SET_EXTCLK));
+    /* XXX still todo */
+#endif
+
+    /* only support 0 (no external clock) */
+    return(clock_factor);
+}
+
+
+/*
+ * Write bytes to the hardware.  Returns the number of bytes
+ * actually written.
+ */
+static int
+do_ioc4_write(sioport_t *port, char *buf, int len)
+{
+    int                prod_ptr, cons_ptr, total;
+    struct ring       *outring;
+    struct ring_entry *entry;
+    ioc4port_t        *p = LPORT(port);
+    struct hooks      *hooks = p->ip_hooks;
+
+    DEBUGINC(write_bytes, len);
+    DEBUGINC(write_cnt, 1);
+
+    dprintf(("write port 0x%p, len %d\n", (void *)port, len));
+
+    ASSERT(len >= 0);
+
+    prod_ptr = p->ip_tx_prod;
+    cons_ptr = PCI_INW(&p->ip_serial->stcir) & PROD_CONS_MASK;
+    outring = p->ip_outring;
+
+    /* Maintain a 1-entry red-zone.  The ring buffer is full when
+     * (cons - prod) % ring_size is 1.  Rather than do this subtraction
+     * in the body of the loop, I'll do it now.
+     */
+    cons_ptr = (cons_ptr - (int) sizeof(struct ring_entry)) & PROD_CONS_MASK;
+
+    total = 0;
+    /* Stuff the bytes into the output */
+    while ((prod_ptr != cons_ptr) && (len > 0)) {
+	int x;
+
+	/* Go 4 bytes (one ring entry) at a time */
+	entry = (struct ring_entry*) ((caddr_t)outring + prod_ptr);
+
+	/* Invalidate all entries */
+	entry->ring_allsc = 0;
+
+	/* Copy in some bytes */
+	for(x = 0; (x < 4) && (len > 0); x++) {
+	    entry->ring_data[x] = *buf++;
+	    entry->ring_sc[x] = IOC4_TXCB_VALID;
+	    len--;
+	    total++;
+	}
+
+	DEBUGINC(tx_buf_used, x);
+	DEBUGINC(tx_buf_cnt, 1);
+
+	/* If we are within some small threshold of filling up the entire
+	 * ring buffer, we must place an EXPLICIT intr here to generate
+	 * a lowat interrupt in case we subsequently really do fill up
+	 * the ring and the caller goes to sleep.  No need to place
+	 * more than one though.
+	 */
+	if (!(p->ip_flags & LOWAT_WRITTEN) &&
+	    ((cons_ptr - prod_ptr) & PROD_CONS_MASK) <=
+	    p->ip_tx_lowat * (int)sizeof(struct ring_entry)) {
+	    p->ip_flags |= LOWAT_WRITTEN;
+	    entry->ring_sc[0] |= IOC4_TXCB_INT_WHEN_DONE;
+	    dprintf(("write placing TX_EXPLICIT\n"));
+	}
+
+	/* Go on to next entry */
+	prod_ptr = (prod_ptr + (int) sizeof(struct ring_entry)) & PROD_CONS_MASK;
+    }
+
+    /* If we sent something, start DMA if necessary */
+    if (total > 0 && !(p->ip_sscr & IOC4_SSCR_DMA_EN)) {
+	p->ip_sscr |= IOC4_SSCR_DMA_EN;
+	PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr);
+    }
+
+    /* Store the new producer pointer.  If TX is disabled, we stuff the
+     * data into the ring buffer, but we don't actually start TX.
+     */
+    if (!(p->ip_flags & TX_DISABLED)) {
+	PCI_OUTW(&p->ip_serial->stpir, prod_ptr);
+
+	/* If we are now transmitting, enable TX_MT interrupt so we
+	 * can disable DMA if necessary when the TX finishes.
+	 */
+	if (total > 0)
+	    enable_intrs(p, H_INTR_TX_MT);
+    }
+    p->ip_tx_prod = prod_ptr;
+
+    dprintf(("write port 0x%p, wrote %d\n", (void *)port, total));
+    DEBUGINC(wrote_bytes, total);
+    return(total);
+}
+
+
+/* Asynchronous write */
+static int
+ioc4_write(sioport_t *port, char *buf, int len)
+{
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_WRITE));
+#endif
+    return(do_ioc4_write(port, buf, len));
+}
+
+
+/* Synchronous write */
+static int
+ioc4_sync_write(sioport_t *port, char *buf, int len)
+{
+    int bytes;
+
+    ASSERT(sio_port_islocked(port));
+    bytes = do_ioc4_write(port, buf, len);
+
+    /* Don't allow the system to hang if XOFF is in force */
+    if (len > 0 && bytes == 0 && (LPORT(port)->ip_flags & TX_DISABLED))
+	ioc4_enable_tx(port, 1);
+
+    return(bytes);
+}
+
+
+/* Write flush */
+static void
+ioc4_wrflush(sioport_t *port)
+{
+    ioc4port_t *p = LPORT(port);
+
+    ASSERT(sio_port_islocked(port));
+
+    /* We can't flush if TX is disabled due to XOFF. */
+    if (!(PCI_INW(&p->ip_ioc4->sio_ir) & IOC4_SIO_IR_S0_TX_MT) &&
+	(p->ip_flags & TX_DISABLED))
+	ioc4_enable_tx(port, 1);
+
+    /* Spin waiting for TX_MT to assert only if DMA is enabled.  If we
+     * are panicking and one of the other processors is already in
+     * symmon, DMA will be disabled and TX_MT will never be asserted.
+     * There may also be legitimate cases in the kernel where DMA is
+     * disabled and we won't flush correctly here.
+     */
+
+    while ((PCI_INW(&p->ip_serial->sscr) & (IOC4_SSCR_DMA_EN |
+           IOC4_SSCR_PAUSE_STATE)) == IOC4_SSCR_DMA_EN &&
+	   !(PCI_INW(&p->ip_ioc4->sio_ir) & IOC4_SIO_IR_S0_TX_MT)) {
+	udelay(5);
+    }
+}
+
+
+/*
+ * Set or clear break condition on output
+ */
+static int
+ioc4_break(sioport_t *port, int brk)
+{
+    ioc4port_t *p = LPORT(port);
+    char        lcr;
+    int         spin_success;
+
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_BREAK));
+#endif
+
+    /* Pause the DMA interface if necessary */
+    if (p->ip_sscr & IOC4_SSCR_DMA_EN) {
+	PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr | IOC4_SSCR_DMA_PAUSE);
+	SPIN((PCI_INW(&p->ip_serial->sscr) & IOC4_SSCR_PAUSE_STATE) == 0,
+             spin_success);
+	if (!spin_success)
+		return(-1);
+    }
+
+    lcr = PCI_INB(&p->ip_uart->i4u_lcr);
+    if (brk) {
+	/* Set break */
+        PCI_OUTB(&p->ip_uart->i4u_lcr, lcr | LCR_SNDBRK);
+    }
+    else {
+	/* Clear break */
+        PCI_OUTB(&p->ip_uart->i4u_lcr, lcr & ~LCR_SNDBRK);
+    }
+
+    /* Re-enable the DMA interface if necessary */
+    if (p->ip_sscr & IOC4_SSCR_DMA_EN) {
+	PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr);
+    }
+
+    dprintf(("break port 0x%p, brk %d\n", (void *)port, brk));
+
+    return(0);
+}
+
+
+static int
+ioc4_enable_tx(sioport_t *port, int enb)
+{
+    ioc4port_t   *p = LPORT(port);
+    struct hooks *hooks = p->ip_hooks;
+    int           spin_success;
+
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_ENABLE_TX));
+#endif
+
+    /* If we're already in the desired state, we're done */
+    if ((enb && !(p->ip_flags & TX_DISABLED)) ||
+	(!enb && (p->ip_flags & TX_DISABLED)))
+	return(0);
+
+    /* Pause DMA */
+    if (p->ip_sscr & IOC4_SSCR_DMA_EN) {
+	PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr | IOC4_SSCR_DMA_PAUSE);
+	SPIN((PCI_INW(&p->ip_serial->sscr) & IOC4_SSCR_PAUSE_STATE) == 0,
+             spin_success);
+	if (!spin_success)
+		return(-1);
+    }
+
+    if (enb) {
+	p->ip_flags &= ~TX_DISABLED;
+	PCI_OUTW(&p->ip_serial->stpir, p->ip_tx_prod);
+	enable_intrs(p, H_INTR_TX_MT);
+    }
+    else {
+	ioc4reg_t txcons = PCI_INW(&p->ip_serial->stcir) & PROD_CONS_MASK;
+	p->ip_flags |= TX_DISABLED;
+	disable_intrs(p, H_INTR_TX_MT);
+
+	/* Only move the transmit producer pointer back if the
+	 * transmitter is not already empty, otherwise we'll be
+	 * generating a bogus entry.
+	 */
+	if (txcons != p->ip_tx_prod)
+	    PCI_OUTW(&p->ip_serial->stpir,
+		     (txcons + (int) sizeof(struct ring_entry)) & PROD_CONS_MASK);
+    }
+
+    /* Re-enable the DMA interface if necessary */
+    if (p->ip_sscr & IOC4_SSCR_DMA_EN) 
+	PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr);
+
+    return(0);
+}
+
+
+/*
+ * Read in bytes from the hardware.  Return the number of bytes
+ * actually read.
+ */
+static int
+ioc4_read(sioport_t *port, char *buf, int len)
+{
+    int           prod_ptr, cons_ptr, total, x, spin_success;
+    struct ring  *inring;
+    ioc4port_t   *p = LPORT(port);
+    struct hooks *hooks = p->ip_hooks;
+
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_READ));
+#endif
+
+    dprintf(("read port 0x%p, len %d\n", (void *)port, len));
+
+    DEBUGINC(read_bytes, len);
+    DEBUGINC(read_cnt, 1);
+
+    ASSERT(len >= 0);
+
+    /* There is a nasty timing issue in the IOC4. When the RX_TIMER
+     * expires or the RX_HIGH condition arises, we take an interrupt.
+     * At some point while servicing the interrupt, we read bytes from
+     * the ring buffer and re-arm the RX_TIMER.  However the RX_TIMER is
+     * not started until the first byte is received *after* it is armed,
+     * and any bytes pending in the RX construction buffers are not drained
+     * to memory until either there are 4 bytes available or the RX_TIMER
+     * expires.  This leads to a potential situation where data is left
+     * in the construction buffers forever because 1 to 3 bytes were received
+     * after the interrupt was generated but before the RX_TIMER was re-armed.
+     * At that point as long as no subsequent bytes are received the
+     * timer will never be started and the bytes will remain in the
+     * construction buffer forever.  The solution is to execute a DRAIN
+     * command after rearming the timer.  This way any bytes received before
+     * the DRAIN will be drained to memory, and any bytes received after
+     * the DRAIN will start the TIMER and be drained when it expires.
+     * Luckily, this only needs to be done when the DMA buffer is empty
+     * since there is no requirement that this function return all
+     * available data as long as it returns some.
+     */
+    /* Re-arm the timer */
+    PCI_OUTW(&p->ip_serial->srcir, p->ip_rx_cons | IOC4_SRCIR_ARM);
+
+    prod_ptr = PCI_INW(&p->ip_serial->srpir) & PROD_CONS_MASK;
+    cons_ptr = p->ip_rx_cons;
+
+    if (prod_ptr == cons_ptr) {
+	int reset_dma = 0;
+
+	/* Input buffer appears empty, do a flush. */
+
+	/* DMA must be enabled for this to work. */
+	if (!(p->ip_sscr & IOC4_SSCR_DMA_EN)) {
+	    p->ip_sscr |= IOC4_SSCR_DMA_EN;
+	    reset_dma = 1;
+	}
+
+	/* Potential race condition: we must reload the srpir after
+	 * issuing the drain command, otherwise we could think the RX
+	 * buffer is empty, then take a very long interrupt, and when
+	 * we come back it's full and we wait forever for the drain to
+	 * complete.
+	 */
+	PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr | IOC4_SSCR_RX_DRAIN);
+	prod_ptr = PCI_INW(&p->ip_serial->srpir) & PROD_CONS_MASK;
+
+	DEBUGINC(drain, 1);
+
+	/* We must not wait for the DRAIN to complete unless there are
+	 * at least 8 bytes (2 ring entries) available to receive the data
+	 * otherwise the DRAIN will never complete and we'll deadlock here.
+	 * In fact, to make things easier, I'll just ignore the flush if
+	 * there is any data at all now available.
+	 */
+	if (prod_ptr == cons_ptr) {
+	    DEBUGINC(drainwait, 1);
+	    SPIN(PCI_INW(&p->ip_serial->sscr) & IOC4_SSCR_RX_DRAIN, spin_success);
+	    if (!spin_success)
+		    return(-1);
+
+	    /* SIGH. We have to reload the prod_ptr *again* since
+	     * the drain may have caused it to change
+	     */
+	    prod_ptr = PCI_INW(&p->ip_serial->srpir) & PROD_CONS_MASK;
+	}
+
+	if (reset_dma) {
+	    DEBUGINC(resetdma, 1);
+	    p->ip_sscr &= ~IOC4_SSCR_DMA_EN;
+	    PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr);
+	}
+    }
+    inring = p->ip_inring;
+
+    p->ip_flags &= ~READ_ABORTED;
+
+    total = 0;
+    /* Grab bytes from the hardware */
+    while(prod_ptr != cons_ptr && len > 0) {
+	struct ring_entry *entry;
+
+	entry = (struct ring_entry *) ((caddr_t)inring + cons_ptr);
+
+	/* According to the producer pointer, this ring entry
+	 * must contain some data.  But if the PIO happened faster
+	 * than the DMA, the data may not be available yet, so let's
+	 * wait until it arrives.
+	 */
+	if ((((volatile struct ring_entry *) entry)->ring_allsc &
+	     RING_ANY_VALID) == 0) {
+
+	    /* Indicate the read is aborted so we don't disable
+	     * the interrupt thinking that the consumer is
+	     * congested.
+	     */
+	    p->ip_flags |= READ_ABORTED;
+		
+	    DEBUGINC(read_aborted, 1);
+	    len = 0;
+	    break;
+
+	}
+
+	/* Load the bytes/status out of the ring entry */
+	for(x = 0; x < 4 && len > 0; x++) {
+	    char *sc = &(entry->ring_sc[x]);
+
+	    /* Check for change in modem state or overrun */
+	    if (*sc & IOC4_RXSB_MODEM_VALID) {
+		if (p->ip_notify & N_DDCD) {
+
+		    /* Notify upper layer if DCD dropped */
+		    if ((p->ip_flags & DCD_ON) && !(*sc & IOC4_RXSB_DCD)) {
+
+			/* If we have already copied some data, return
+			 * it.  We'll pick up the carrier drop on the next
+			 * pass.  That way we don't throw away the data
+			 * that has already been copied back to the caller's
+			 * buffer.
+			 */
+			if (total > 0) {
+			    len = 0;
+			    break;
+			}
+
+			p->ip_flags &= ~DCD_ON;
+
+			/* Turn off this notification so the carrier
+			 * drop protocol won't see it again when it
+			 * does a read.
+			 */
+			*sc &= ~IOC4_RXSB_MODEM_VALID;
+
+			/* To keep things consistent, we need to update
+			 * the consumer pointer so the next reader won't
+			 * come in and try to read the same ring entries
+			 * again.  This must be done here before the call
+			 * to UP_DDCD since UP_DDCD may do a recursive
+			 * read!
+			 */
+			if ((entry->ring_allsc & RING_ANY_VALID) == 0)
+			    cons_ptr =
+				(cons_ptr + (int) sizeof(struct ring_entry)) &
+				    PROD_CONS_MASK;
+
+			PCI_OUTW(&p->ip_serial->srcir, cons_ptr);
+			p->ip_rx_cons = cons_ptr;
+
+			/* Notify upper layer of carrier drop */
+			if (p->ip_notify & N_DDCD)
+			    UP_DDCD(port, 0);
+
+			DEBUGINC(read_ddcd, 1);
+
+			/* If we had any data to return, we would have
+			 * returned it above.
+			 */
+			return(0);
+		    }
+		}
+
+		/* Notify upper layer that an input overrun occurred */
+		if ((*sc & IOC4_RXSB_OVERRUN) && (p->ip_notify & N_OVERRUN_ERROR)) {
+		    DEBUGINC(rx_overrun, 1);
+		    UP_NCS(port, NCS_OVERRUN);
+		}
+
+		/* Don't look at this byte again */
+		*sc &= ~IOC4_RXSB_MODEM_VALID;
+	    }
+
+	    /* Check for valid data or RX errors */
+	    if (*sc & IOC4_RXSB_DATA_VALID) {
+		if ((*sc & (IOC4_RXSB_PAR_ERR | IOC4_RXSB_FRAME_ERR |
+                            IOC4_RXSB_BREAK)) &&
+		    (p->ip_notify & (N_PARITY_ERROR | N_FRAMING_ERROR | N_BREAK))) {
+
+		    /* There is an error condition on the next byte.  If
+		     * we have already transferred some bytes, we'll stop
+		     * here.  Otherwise if this is the first byte to be read,
+		     * we'll just transfer it alone after notifying the
+		     * upper layer of its status.
+		     */
+		    if (total > 0) {
+			len = 0;
+			break;
+		    }
+		    else {
+			if ((*sc & IOC4_RXSB_PAR_ERR) &&
+			    (p->ip_notify & N_PARITY_ERROR)) {
+			    DEBUGINC(parity, 1);
+			    UP_NCS(port, NCS_PARITY);
+			}
+
+			if ((*sc & IOC4_RXSB_FRAME_ERR) &&
+			    (p->ip_notify & N_FRAMING_ERROR)) {
+			    DEBUGINC(framing, 1);
+			    UP_NCS(port, NCS_FRAMING);
+			}
+
+			if ((*sc & IOC4_RXSB_BREAK) &&
+			    (p->ip_notify & N_BREAK)) {
+			    DEBUGINC(brk, 1);
+			    UP_NCS(port, NCS_BREAK);
+			}
+			len = 1;
+		    }
+		}
+
+		*sc &= ~IOC4_RXSB_DATA_VALID;
+		*buf++ = entry->ring_data[x];
+		len--;
+		total++;
+	    }
+	}
+
+	DEBUGINC(rx_buf_used, x);
+	DEBUGINC(rx_buf_cnt, 1);
+
+	/* If we used up this entry entirely, go on to the next one,
+	 * otherwise we must have run out of buffer space, so
+	 * leave the consumer pointer here for the next read in case
+	 * there are still unread bytes in this entry.
+	 */
+	if ((entry->ring_allsc & RING_ANY_VALID) == 0)
+	    cons_ptr = (cons_ptr + (int) sizeof(struct ring_entry)) &
+		PROD_CONS_MASK;
+    }
+
+    /* Update consumer pointer and re-arm RX timer interrupt */
+    PCI_OUTW(&p->ip_serial->srcir, cons_ptr);
+    p->ip_rx_cons = cons_ptr;
+
+    /* If we have now dipped below the RX high water mark and we have
+     * RX_HIGH interrupt turned off, we can now turn it back on again.
+     */
+    if ((p->ip_flags & INPUT_HIGH) &&
+	(((prod_ptr - cons_ptr) & PROD_CONS_MASK) <
+	 ((p->ip_sscr & IOC4_SSCR_RX_THRESHOLD) << IOC4_PROD_CONS_PTR_OFF))) {
+	p->ip_flags &= ~INPUT_HIGH;
+	enable_intrs(p, H_INTR_RX_HIGH);
+    }
+
+    DEBUGINC(red_bytes, total);
+
+    return(total);
+}
+
+
+/*
+ * Modify event notification
+ */
+static int
+ioc4_notification(sioport_t *port, int mask, int on)
+{
+    ioc4port_t   *p = LPORT(port);
+    struct hooks *hooks = p->ip_hooks;
+    ioc4reg_t     intrbits, sscrbits;
+
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_NOTIFICATION));
+#endif
+    ASSERT(mask);
+
+    intrbits = sscrbits = 0;
+
+    if (mask & N_DATA_READY)
+	intrbits |= (H_INTR_RX_TIMER | H_INTR_RX_HIGH);
+    if (mask & N_OUTPUT_LOWAT)
+	intrbits |= H_INTR_TX_EXPLICIT;
+    if (mask & N_DDCD) {
+	intrbits |= H_INTR_DELTA_DCD;
+	sscrbits |= IOC4_SSCR_RX_RING_DCD;
+    }
+    if (mask & N_DCTS)
+	intrbits |= H_INTR_DELTA_CTS;
+
+    if (on) {
+	enable_intrs(p, intrbits);
+	p->ip_notify |= mask;
+	p->ip_sscr |= sscrbits;
+    }
+    else {
+	disable_intrs(p, intrbits);
+	p->ip_notify &= ~mask;
+	p->ip_sscr &= ~sscrbits;
+    }
+
+    /* We require DMA if either DATA_READY or DDCD notification is
+     * currently requested.  If neither of these is requested and
+     * there is currently no TX in progress, DMA may be disabled.
+     */
+    if (p->ip_notify & (N_DATA_READY | N_DDCD)) 
+	p->ip_sscr |= IOC4_SSCR_DMA_EN;
+    else if (!(p->ip_ienb & H_INTR_TX_MT)) 
+	p->ip_sscr &= ~IOC4_SSCR_DMA_EN;
+
+    PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr);
+    return(0);
+}
+
+
+/*
+ * Set RX timeout and threshold values.  The upper layer passes in a
+ * timeout value.  In all cases it would like to be notified at least this
+ * often when there are RX chars coming in.  We set the RX timeout and
+ * RX threshold (based on baud) to ensure that the upper layer is called
+ * at roughly this interval during normal RX.
+ * The input timeout value is in ticks.
+ */
+static int
+ioc4_rx_timeout(sioport_t *port, int timeout)
+{
+    int         threshold;
+    ioc4port_t *p = LPORT(port);
+
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_RX_TIMEOUT));
+#endif
+
+    p->ip_rx_timeout = timeout;
+
+    /* Timeout is in ticks.  Let's figure out how many chars we
+     * can receive at the current baud rate in that interval
+     * and set the RX threshold to that amount.  There are 4 chars
+     * per ring entry, so we'll divide the number of chars that will
+     * arrive in timeout by 4.
+     */
+    threshold = timeout * p->ip_baud / 10 / HZ / 4;
+    if (threshold == 0)
+	threshold = 1; /* otherwise we'll intr all the time! */
+
+    if ((unsigned) threshold > (unsigned) IOC4_SSCR_RX_THRESHOLD)
+	    return(1);
+
+    p->ip_sscr &= ~IOC4_SSCR_RX_THRESHOLD;
+    p->ip_sscr |= threshold;
+
+    PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr);
+
+    /* Now set the RX timeout to the given value */
+    timeout = timeout * IOC4_SRTR_HZ / HZ;
+    if (timeout > IOC4_SRTR_CNT)
+	timeout = IOC4_SRTR_CNT;
+
+    PCI_OUTW(&p->ip_serial->srtr, timeout);
+
+    return(0);
+}
+
+
+static int
+set_DTRRTS(sioport_t *port, int val, int mask1, int mask2)
+{
+    ioc4port_t *p = LPORT(port);
+    ioc4reg_t   shadow;
+    int         spin_success;
+    char        mcr;
+
+    /* XXX need lock for pretty much this entire routine.  Makes
+     * me nervous to hold it for so long.  If we crash or hit
+     * a breakpoint in here, we're hosed.
+     */
+
+    /* Pause the DMA interface if necessary */
+    if (p->ip_sscr & IOC4_SSCR_DMA_EN) {
+	PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr | IOC4_SSCR_DMA_PAUSE);
+	SPIN((PCI_INW(&p->ip_serial->sscr) & IOC4_SSCR_PAUSE_STATE) == 0,
+             spin_success);
+	if (!spin_success)
+		return(-1);
+    }
+
+    shadow = PCI_INW(&p->ip_serial->shadow);
+    mcr = (shadow & 0xff000000) >> 24;
+
+    /* Set new value */
+    if (val) {
+	mcr |= mask1;
+        shadow |= mask2;
+    }
+    else {
+	mcr &= ~mask1;
+        shadow &= ~mask2;
+    }
+
+    PCI_OUTB(&p->ip_uart->i4u_mcr, mcr);
+
+    PCI_OUTW(&p->ip_serial->shadow, shadow);
+
+    /* Re-enable the DMA interface if necessary */
+    if (p->ip_sscr & IOC4_SSCR_DMA_EN) 
+	PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr);
+
+    return(0);
+}
+
+
+static int
+ioc4_set_DTR(sioport_t *port, int dtr)
+{
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_SET_DTR));
+#endif
+
+    dprintf(("set dtr port 0x%p, dtr %d\n", (void *)port, dtr));
+    return(set_DTRRTS(port, dtr, MCR_DTR, IOC4_SHADOW_DTR));
+}
+
+
+static int
+ioc4_set_RTS(sioport_t *port, int rts)
+{
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_SET_RTS));
+#endif
+
+    dprintf(("set rts port 0x%p, rts %d\n", (void *)port, rts));
+    return(set_DTRRTS(port, rts, MCR_RTS, IOC4_SHADOW_RTS));
+}
+
+
+static int
+ioc4_query_DCD(sioport_t *port)
+{
+    ioc4port_t *p = LPORT(port);
+    ioc4reg_t   shadow;
+
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_QUERY_DCD));
+#endif
+
+    dprintf(("get dcd port 0x%p\n", (void *)port));
+
+    shadow = PCI_INW(&p->ip_serial->shadow);
+
+    return(shadow & IOC4_SHADOW_DCD);
+}
+
+
+static int
+ioc4_query_CTS(sioport_t *port)
+{
+    ioc4port_t *p = LPORT(port);
+    ioc4reg_t   shadow;
+
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_QUERY_CTS));
+#endif
+
+    dprintf(("get cts port 0x%p\n", (void *)port));
+
+    shadow = PCI_INW(&p->ip_serial->shadow);
+
+    return(shadow & IOC4_SHADOW_CTS);
+}
+
+
+static int
+ioc4_set_proto(sioport_t *port, enum sio_proto proto)
+{
+    ioc4port_t   *p = LPORT(port);
+    struct hooks *hooks = p->ip_hooks;
+
+#ifdef NOT_YET
+    ASSERT(L_LOCKED(port, L_SET_PROTOCOL));
+#endif
+
+    switch(proto) {
+      case PROTO_RS232:
+	/* Clear the appropriate GIO pin */
+	PCI_OUTW((&p->ip_ioc4->gppr_0 + H_RS422), 0);
+	break;
+
+      case PROTO_RS422:
+	/* Set the appropriate GIO pin */
+	PCI_OUTW((&p->ip_ioc4->gppr_0 + H_RS422), 1);
+	break;
+
+      default:
+	return(1);
+    }
+
+    return(0);
+}
+
+
+// #define IS_PORT_0(p) ((p)->ip_hooks == &hooks_array[0])
+
+static int
+ioc4_get_mapid(sioport_t *port, void *arg)
+{
+    return(0);
+}
+
+
+static int
+ioc4_set_sscr(sioport_t *port, int arg, int flag)
+{
+    ioc4port_t *p = LPORT(port);
+
+    if ( flag ) {             /* reset arg bits in p->ip_sscr */
+	p->ip_sscr &= ~arg;
+    } else {                  /* set bits in p->ip_sscr */
+	p->ip_sscr |= arg;
+    }
+    PCI_OUTW(&p->ip_serial->sscr, p->ip_sscr);
+    return(p->ip_sscr);
+}
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/klconflib.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/klconflib.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/klconflib.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/klconflib.c	2003-09-12 12:44:35.000000000 -0700
@@ -39,7 +39,7 @@
 static int hasmetarouter;
 
 
-char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#=012345";
+char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#=vo2345";
 
 lboard_t *
 find_lboard(lboard_t *start, unsigned char brd_type)
@@ -278,6 +278,8 @@
 				board_name = EDGE_LBL_XBRICK;
 			else if (brd->brd_type == KLTYPE_PEBRICK)
 				board_name = EDGE_LBL_PEBRICK;
+			else if (brd->brd_type == KLTYPE_OPUSBRICK)
+				board_name = EDGE_LBL_OPUSBRICK;
 			else if (brd->brd_type == KLTYPE_CGBRICK)
 				board_name = EDGE_LBL_CGBRICK;
 			else
@@ -293,23 +295,6 @@
 	sprintf(path, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d/%s", buffer, geo_slab(brd->brd_geoid), board_name);
 }
 
-/*
- * Get the module number for a NASID.
- */
-moduleid_t
-get_module_id(nasid_t nasid)
-{
-	lboard_t *brd;
-
-	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
-
-	if (!brd)
-		return INVALID_MODULE;
-	else
-		return geo_module(brd->brd_geoid);
-}
-
-
 #define MHZ	1000000
 
 
@@ -419,7 +404,13 @@
 	strcpy(serial_number,"");
 	switch(KLCLASS(board->brd_type)) {
 	case KLCLASS_CPU: {	/* Node board */
-		klhub_t	*hub;
+		klhub_t *hub;
+
+		if (board->brd_type == KLTYPE_TIO) {
+			printk("*****board_serial_number_get: Need to support TIO.*****\n");
+			strcpy(serial_number,"");
+			return(0);
+		}
 		
 		/* Get the hub component information */
 		hub = (klhub_t *)find_first_component(board,
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/klgraph.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/klgraph.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/klgraph.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/klgraph.c	2003-09-12 12:44:35.000000000 -0700
@@ -42,6 +42,7 @@
 extern char arg_maxnodes[];
 extern u64 klgraph_addr[];
 void mark_cpuvertex_as_cpu(vertex_hdl_t vhdl, cpuid_t cpuid);
+extern int is_specified(char *);
 
 
 /*
@@ -54,7 +55,7 @@
 {
 	invent_generic_t *invent;
 
-	invent = kern_malloc(size);
+	invent = kmalloc(size, GFP_KERNEL);
 	if (!invent) return NULL;
 	
 	invent->ig_module = NODE_MODULEID(cnode);
@@ -205,6 +206,30 @@
 
 /* ARGSUSED */
 void
+klhwg_add_ice(vertex_hdl_t node_vertex, klhub_t *hub, cnodeid_t cnode)
+{
+	vertex_hdl_t myicev;
+	vertex_hdl_t ice_mon;
+	int rc;
+	extern struct file_operations shub_mon_fops;
+
+	(void) hwgraph_path_add(node_vertex, EDGE_LBL_ICE, &myicev);
+
+	HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, myicev, NULL, "Created path for ice vertex for TIO node.\n"));
+
+	rc = device_master_set(myicev, node_vertex);
+	if (rc)
+		panic("klhwg_add_ice: Unable to create ice vertex.\n");
+
+	ice_mon = hwgraph_register(myicev, EDGE_LBL_PERFMON,
+		0, DEVFS_FL_AUTO_DEVNUM,
+		0, 0,
+		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
+		&shub_mon_fops, (void *)(long)cnode);
+}
+
+/* ARGSUSED */
+void
 klhwg_add_hub(vertex_hdl_t node_vertex, klhub_t *hub, cnodeid_t cnode)
 {
 	vertex_hdl_t myhubv;
@@ -214,7 +239,13 @@
 
 	GRPRINTF(("klhwg_add_hub: adding %s\n", EDGE_LBL_HUB));
 	(void) hwgraph_path_add(node_vertex, EDGE_LBL_HUB, &myhubv);
+
+	HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, myhubv, NULL, "Created path for hub vertex for Shub node.\n"));
+
 	rc = device_master_set(myhubv, node_vertex);
+	if (rc)
+		panic("klhwg_add_hub: Unable to create hub vertex.\n");
+
 	hub_mon = hwgraph_register(myhubv, EDGE_LBL_PERFMON,
 		0, DEVFS_FL_AUTO_DEVNUM,
 		0, 0,
@@ -237,6 +268,8 @@
 		sprintf(name, "%s/%s/%c", EDGE_LBL_DISABLED, EDGE_LBL_CPU, 'a' + cpu->cpu_info.physid);
 		(void) hwgraph_path_add(node_vertex, name, &my_cpu);
 
+		HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, my_cpu, NULL, "Created path for disabled cpu slice.\n"));
+
 		mark_cpuvertex_as_cpu(my_cpu, cpu_id);
 		device_master_set(my_cpu, node_vertex);
 
@@ -264,6 +297,9 @@
 
         GRPRINTF(("klhwg_add_cpu: adding %s to vertex 0x%p\n", name, node_vertex));
         (void) hwgraph_path_add(node_vertex, name, &my_cpu);
+
+	HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, my_cpu, NULL, "Created path for active cpu slice.\n"));
+
         mark_cpuvertex_as_cpu(my_cpu, cpu_id);
         device_master_set(my_cpu, node_vertex);
 
@@ -271,6 +307,7 @@
         if (hwgraph_edge_get(node_vertex, EDGE_LBL_CPU, &cpu_dir) == GRAPH_SUCCESS) {
                 sprintf(name, "%c", 'a' + cpu->cpu_info.physid);
                 (void) hwgraph_edge_add(cpu_dir, my_cpu, name);
+		HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, cpu_dir, my_cpu, "Created % from vhdl1 to vhdl2.\n", name));
         }
 
         klhwg_cpu_invent_info(my_cpu, cnode, cpu);
@@ -278,6 +315,41 @@
 
 
 void
+klhwg_add_coretalk(cnodeid_t cnode, nasid_t tio_nasid)
+{
+	lboard_t *brd;
+	vertex_hdl_t coretalk_v, icev;
+	/*REFERENCED*/
+	graph_error_t err;
+
+	if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(tio_nasid), KLTYPE_IOBRICK_XBOW)) == NULL)
+			return;
+
+	if (KL_CONFIG_DUPLICATE_BOARD(brd))
+	    return;
+
+	icev = cnodeid_to_vertex(cnode);
+
+	err = hwgraph_path_add(icev, EDGE_LBL_CORETALK, &coretalk_v);
+	if (err != GRAPH_SUCCESS) {
+		if (err == GRAPH_DUP)
+			printk(KERN_WARNING  "klhwg_add_coretalk: Check for "
+                                        "working routers and router links!");
+
+                 panic("klhwg_add_coretalkk: Failed to add "
+                             "edge: vertex 0x%p to vertex 0x%p,"
+                             "error %d\n",
+                              (void *)icev, (void *)coretalk_v, err);
+        }
+
+	HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, coretalk_v, NULL, "Created coretalk path for TIO node.\n"));
+
+        NODEPDA(cnode)->xbow_vhdl = coretalk_v;
+
+}
+
+
+void
 klhwg_add_xbow(cnodeid_t cnode, nasid_t nasid)
 {
 	lboard_t *brd;
@@ -295,9 +367,6 @@
 	if (KL_CONFIG_DUPLICATE_BOARD(brd))
 	    return;
 
-	GRPRINTF(("klhwg_add_xbow: adding cnode %d nasid %d xbow edges\n",
-			cnode, nasid));
-
 	if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW))
 	    == NULL)
 	    return;
@@ -326,11 +395,14 @@
                                 printk(KERN_WARNING  "klhwg_add_xbow: Check for "
                                         "working routers and router links!");
 
-                        PRINT_PANIC("klhwg_add_xbow: Failed to add "
+                        panic("klhwg_add_xbow: Failed to add "
                                 "edge: vertex 0x%p to vertex 0x%p,"
                                 "error %d\n",
                                 (void *)hubv, (void *)xbow_v, err);
                 }
+
+		HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, xbow_v, NULL, "Created path for xtalk.\n"));
+
 		xswitch_vertex_init(xbow_v); 
 
 		NODEPDA(hub_cnode)->xbow_vhdl = xbow_v;
@@ -345,14 +417,71 @@
 				hub_nasid;
 		}
 
-		GRPRINTF(("klhwg_add_xbow: adding port nasid %d %s to vertex 0x%p\n",
-			hub_nasid, EDGE_LBL_XTALK, hubv));
 	}
 }
 
 
 /* ARGSUSED */
 void
+klhwg_add_tionode(vertex_hdl_t hwgraph_root, cnodeid_t cnode)
+{
+	nasid_t tio_nasid;
+	lboard_t *brd;
+	klhub_t *hub;
+	vertex_hdl_t node_vertex = NULL;
+	char path_buffer[100];
+	int rv;
+	char *s;
+	int board_disabled = 0;
+
+	tio_nasid = COMPACT_TO_NASID_NODEID(cnode);
+	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(tio_nasid), KLTYPE_TIO);
+	ASSERT(brd);
+
+	/* Generate a hardware graph path for this board. */
+	board_to_path(brd, path_buffer);
+	rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
+	if (rv != GRAPH_SUCCESS)
+		panic("TIO Node vertex creation failed.  "
+					  "Path == %s", path_buffer);
+
+	HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created path for TIO node.\n"));
+	hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
+	ASSERT(hub);
+	if(hub->hub_info.flags & KLINFO_ENABLE)
+		board_disabled = 0;
+	else
+		board_disabled = 1;
+
+	if(!board_disabled) {
+		mark_nodevertex_as_node(node_vertex,
+				    cnode + board_disabled * numionodes);
+
+		s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer));
+		NODEPDA(cnode)->hwg_node_name =
+					kmalloc(strlen(s) + 1,
+					GFP_KERNEL);
+		ASSERT_ALWAYS(NODEPDA(cnode)->hwg_node_name != NULL);
+		strcpy(NODEPDA(cnode)->hwg_node_name, s);
+
+		hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo);
+
+		/* Set up node board's slot */
+		NODEPDA(cnode)->slotdesc = brd->brd_slot;
+
+		/* Set up the module we're in */
+		NODEPDA(cnode)->geoid = brd->brd_geoid;
+		NODEPDA(cnode)->module = module_lookup(geo_module(brd->brd_geoid));
+	}
+
+        if(!board_disabled)
+                klhwg_add_ice(node_vertex, hub, cnode);
+
+}
+
+
+/* ARGSUSED */
+void
 klhwg_add_node(vertex_hdl_t hwgraph_root, cnodeid_t cnode)
 {
 	nasid_t nasid;
@@ -367,8 +496,6 @@
 
 	nasid = COMPACT_TO_NASID_NODEID(cnode);
 	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
-	GRPRINTF(("klhwg_add_node: Adding cnode %d, nasid %d, brd 0x%p\n",
-                cnode, nasid, brd));
 	ASSERT(brd);
 
 	do {
@@ -376,16 +503,11 @@
 
 		/* Generate a hardware graph path for this board. */
 		board_to_path(brd, path_buffer);
-
-		GRPRINTF(("klhwg_add_node: adding %s to vertex 0x%p\n",
-			path_buffer, hwgraph_root));
 		rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
-
 		if (rv != GRAPH_SUCCESS)
-			PRINT_PANIC("Node vertex creation failed.  "
-					  "Path == %s",
-				path_buffer);
+			panic("Node vertex creation failed.  Path == %s", path_buffer);
 
+		HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created path for SHUB node.\n"));
 		hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
 		ASSERT(hub);
 		if(hub->hub_info.flags & KLINFO_ENABLE)
@@ -427,6 +549,8 @@
 			rv = hwgraph_path_add(node_vertex, EDGE_LBL_CPU, &cpu_dir);
 			if (rv != GRAPH_SUCCESS)
 				panic("klhwg_add_node: Cannot create CPU directory\n");
+			HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, cpu_dir, NULL, "Created cpu directiry on SHUB node.\n"));
+
 		}
 
 		/* Add each CPU */
@@ -467,48 +591,34 @@
 
 	for (cnode = 0; cnode < numnodes; cnode++) {
 		nasid = COMPACT_TO_NASID_NODEID(cnode);
-
-		GRPRINTF(("klhwg_add_all_routers: adding router on cnode %d\n",
-			cnode));
-
 		brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
 				KLTYPE_ROUTER);
-
 		if (!brd)
 			/* No routers stored in this node's memory */
 			continue;
 
 		do {
 			ASSERT(brd);
-			GRPRINTF(("Router board struct is %p\n", brd));
 
 			/* Don't add duplicate boards. */
 			if (brd->brd_flags & DUPLICATE_BOARD)
 				continue;
 
-			GRPRINTF(("Router 0x%p module number is %d\n", brd, brd->brd_geoid));
 			/* Generate a hardware graph path for this board. */
 			board_to_path(brd, path_buffer);
 
-			GRPRINTF(("Router path is %s\n", path_buffer));
-
 			/* Add the router */
-			GRPRINTF(("klhwg_add_all_routers: adding %s to vertex 0x%p\n",
-				path_buffer, hwgraph_root));
 			rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex);
-
 			if (rv != GRAPH_SUCCESS)
-				PRINT_PANIC("Router vertex creation "
+				panic("Router vertex creation "
 						  "failed.  Path == %s",
 					path_buffer);
 
-			GRPRINTF(("klhwg_add_all_routers: get next board from 0x%p\n",
-					brd));
+			HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created router path.\n"));
+
 		/* Find the rest of the routers stored on this node. */
 		} while ( (brd = find_lboard_class(KLCF_NEXT(brd),
 			 KLTYPE_ROUTER)) );
-
-		GRPRINTF(("klhwg_add_all_routers: Done.\n"));
 	}
 
 }
@@ -527,13 +637,8 @@
 	int port;
 	lboard_t *dest_brd;
 
-	GRPRINTF(("klhwg_connect_one_router: Connecting router on cnode %d\n",
-			cnode));
-
 	/* Don't add duplicate boards. */
 	if (brd->brd_flags & DUPLICATE_BOARD) {
-		GRPRINTF(("klhwg_connect_one_router: Duplicate router 0x%p on cnode %d\n",
-			brd, cnode));
 		return;
 	}
 
@@ -550,7 +655,7 @@
 
 	/* We don't know what to do with multiple router components */
 	if (brd->brd_numcompts != 1) {
-		PRINT_PANIC("klhwg_connect_one_router: %d cmpts on router\n",
+		panic("klhwg_connect_one_router: %d cmpts on router\n",
 			brd->brd_numcompts);
 		return;
 	}
@@ -584,15 +689,12 @@
 		if (rc != GRAPH_SUCCESS) {
 			if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
 				continue;
-			PRINT_PANIC("Can't find router: %s", dest_path);
+			panic("Can't find router: %s", dest_path);
 		}
-		GRPRINTF(("klhwg_connect_one_router: Link from %s/%d to %s\n",
-			  path_buffer, port, dest_path));
 
 		sprintf(dest_path, "%d", port);
 
 		rc = hwgraph_edge_add(router_hndl, dest_hndl, dest_path);
-
 		if (rc == GRAPH_DUP) {
 			GRPRINTF(("Skipping port %d. nasid %d %s/%s\n",
 				  port, router->rou_port[port].port_nasid,
@@ -601,8 +703,10 @@
 		}
 
 		if (rc != GRAPH_SUCCESS && !is_specified(arg_maxnodes))
-			PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p error 0x%x\n",
+			panic("Can't create edge: %s/%s to vertex 0x%p error 0x%x\n",
 				path_buffer, dest_path, (void *)dest_hndl, rc);
+
+		HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, router_hndl, dest_hndl, "Created edge %s from vhdl1 to vhdl2.\n", dest_path));
 		
 	}
 }
@@ -656,14 +760,16 @@
 	graph_error_t rc;
 	int port;
 
-	for (cnode = 0; cnode < numnodes; cnode++) {
+	for (cnode = 0; cnode < numionodes; cnode++) {
 		nasid = COMPACT_TO_NASID_NODEID(cnode);
 
-		GRPRINTF(("klhwg_connect_hubs: Connecting hubs on cnode %d\n",
-			cnode));
-
-		brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
-		ASSERT(brd);
+		if (!(nasid & 1)) {
+			brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+			ASSERT(brd);
+		} else {
+			brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_TIO);
+			ASSERT(brd);
+		}
 
 		hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
 		ASSERT(hub);
@@ -680,10 +786,7 @@
 
 			/* Generate a hardware graph path for this board. */
 			board_to_path(brd, path_buffer);
-
-			GRPRINTF(("klhwg_connect_hubs: Hub path is %s.\n", path_buffer));
 			rc = hwgraph_traverse(hwgraph_root, path_buffer, &hub_hndl);
-
 			if (rc != GRAPH_SUCCESS)
 				printk(KERN_WARNING  "Can't find hub: %s", path_buffer);
 
@@ -699,7 +802,7 @@
 			if (rc != GRAPH_SUCCESS) {
 				if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd))
 					continue;
-				PRINT_PANIC("Can't find board: %s", dest_path);
+				panic("Can't find board: %s", dest_path);
 			} else {
 				char buf[1024];
 		
@@ -708,13 +811,18 @@
 			  	path_buffer, dest_path));
 
 				rc = hwgraph_path_add(hub_hndl, EDGE_LBL_INTERCONNECT, &hub_hndl);
+
+				HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, hub_hndl, NULL, "Created link path.\n"));
+
 				sprintf(buf,"%s/%s",path_buffer,EDGE_LBL_INTERCONNECT);
 				rc = hwgraph_traverse(hwgraph_root, buf, &hub_hndl);
 				sprintf(buf,"%d",port);
 				rc = hwgraph_edge_add(hub_hndl, dest_hndl, buf);
 
+				HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, hub_hndl, dest_hndl, "Created edge %s from vhdl1 to vhdl2.\n", buf));
+
 				if (rc != GRAPH_SUCCESS)
-					PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n",
+					panic("Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n",
 					path_buffer, dest_path, (void *)dest_hndl, rc);
 
 			}
@@ -806,7 +914,8 @@
 
 		rc = hwgraph_path_add(hwgraph_root, name, &module_vhdl);
 		ASSERT(rc == GRAPH_SUCCESS);
-		rc = rc;
+		rc = rc; /* Shut the compiler up */
+		HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, module_vhdl, NULL, "Created module path.\n"));
 
 		hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) modules[cm]);
 
@@ -816,12 +925,13 @@
 			buffer);
 
 		rc = hwgraph_path_add(hwgraph_root, name, &vhdl);
-		ASSERT_ALWAYS(rc == GRAPH_SUCCESS); 
-		rc = rc;
+		ASSERT_ALWAYS(rc == GRAPH_SUCCESS);
+		rc = rc; /* Shut the compiler up */
+		HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, vhdl, NULL, "Created L1 path.\n"));
 
 		hwgraph_info_add_LBL(vhdl,
 				     INFO_LBL_ELSC,
-				     (arbitrary_info_t) (__psint_t) 1);
+				     (arbitrary_info_t) (int64_t) 1);
 
 	}
 }
@@ -835,10 +945,18 @@
 		klhwg_add_node(hwgraph_root, cnode);
 	}
 
+	for (cnode = numnodes; cnode < numionodes; cnode++) {
+		klhwg_add_tionode(hwgraph_root, cnode);
+	}
+
 	for (cnode = 0; cnode < numnodes; cnode++) {
 		klhwg_add_xbow(cnode, cnodeid_to_nasid(cnode));
 	}
 
+	for (cnode = numnodes; cnode < numionodes; cnode++) {
+		klhwg_add_coretalk(cnode, cnodeid_to_nasid(cnode));
+	}
+
 	/*
 	 * As for router hardware inventory information, we set this
 	 * up in router.c. 
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/l1_command.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/l1_command.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/l1_command.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/l1_command.c	2003-09-12 12:44:35.000000000 -0700
@@ -60,8 +60,6 @@
 	*rack = (result & MODULE_RACK_MASK) >> MODULE_RACK_SHFT;
 	*bay = (result & MODULE_BPOS_MASK) >> MODULE_BPOS_SHFT;
 	*brick_type = (result & MODULE_BTYPE_MASK) >> MODULE_BTYPE_SHFT;
-	*brick_type = toupper(*brick_type);
-
 	return 0;
 }
 
@@ -113,12 +111,16 @@
 	brick_type = MODULE_IXBRICK; break;
       case L1_BRICKTYPE_PX: 
 	brick_type = MODULE_PXBRICK; break;
+      case L1_BRICKTYPE_OPUS: 
+	brick_type = MODULE_OPUSBRICK; break;
       case L1_BRICKTYPE_I: 
 	brick_type = MODULE_IBRICK; break;
       case L1_BRICKTYPE_P:
 	brick_type = MODULE_PBRICK; break;
       case L1_BRICKTYPE_X:
 	brick_type = MODULE_XBRICK; break;
+      case L1_BRICKTYPE_CHI_CG:
+	brick_type = MODULE_CGBRICK; break;
     }
 
     ret = RBT_TO_MODULE(rack, bay, brick_type);
@@ -179,25 +181,31 @@
         return("Unknown");
 
     case L1_BRICKTYPE_X:
-        return("Xbrick");
+        return(EDGE_LBL_XBRICK);
 
     case L1_BRICKTYPE_I:
-        return("Ibrick");
+        return(EDGE_LBL_IBRICK);
 
     case L1_BRICKTYPE_P:
-        return("Pbrick");
+        return(EDGE_LBL_PBRICK);
 
     case L1_BRICKTYPE_PX:
-        return("PXbrick");
+        return(EDGE_LBL_PXBRICK);
+
+    case L1_BRICKTYPE_OPUS:
+        return(EDGE_LBL_OPUSBRICK);
 
     case L1_BRICKTYPE_IX:
-        return("IXbrick");
+        return(EDGE_LBL_IXBRICK);
 
     case L1_BRICKTYPE_C:
         return("Cbrick");
 
     case L1_BRICKTYPE_R:
         return("Rbrick");
+
+    case L1_BRICKTYPE_CHI_CG:
+        return(EDGE_LBL_CGBRICK);
     }
 }
 
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/ml_SN_init.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/ml_SN_init.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/ml_SN_init.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/ml_SN_init.c	2003-09-12 12:44:35.000000000 -0700
@@ -25,49 +25,6 @@
 
 extern xwidgetnum_t hub_widget_id(nasid_t);
 
-extern void iograph_early_init(void);
-
-nasid_t master_nasid = INVALID_NASID;		/* This is the partition master nasid */
-nasid_t master_baseio_nasid = INVALID_NASID;	/* This is the master base I/O nasid */
-
-
-/*
- * mlreset(void)
- * 	very early machine reset - at this point NO interrupts have been
- * 	enabled; nor is memory, tlb, p0, etc setup.
- *
- * 	slave is zero when mlreset is called for the master processor and
- *	is nonzero thereafter.
- */
-
-
-void
-mlreset(int slave)
-{
-	/*
-	 * We are the master cpu and node.
-	 */ 
-	master_nasid = get_nasid();
-	set_master_bridge_base();
-
-	/* We're the master processor */
-	master_procid = smp_processor_id();
-	master_nasid = cpuid_to_nasid(master_procid);
-
-	/*
-	 * master_nasid we get back better be same as one from
-	 * get_nasid()
-	 */
-	ASSERT_ALWAYS(master_nasid == get_nasid());
-
-	/* early initialization of iograph */
-	iograph_early_init();
-
-	/* Initialize Hub Pseudodriver Management */
-	hubdev_init();
-}
-
-
 /* XXX - Move the meat of this to intr.c ? */
 /*
  * Set up the platform-dependent fields in the nodepda.
@@ -86,11 +43,9 @@
 	npda->pdinfo = (void *)hubinfo;
 	hubinfo->h_nodepda = npda;
 	hubinfo->h_cnodeid = node;
-	hubinfo->h_nasid = COMPACT_TO_NASID_NODEID(node);
 
 	spin_lock_init(&hubinfo->h_crblock);
 
-	hubinfo->h_widgetid = hub_widget_id(hubinfo->h_nasid);
 	npda->xbow_peer = INVALID_NASID;
 
 	/* 
@@ -107,7 +62,22 @@
 	npda->npda_rip_last = &npda->npda_rip_first;
 	npda->geoid.any.type = GEO_TYPE_INVALID;
 
-	mutex_init_locked(&npda->xbow_sema); /* init it locked? */
+	init_MUTEX_LOCKED(&npda->xbow_sema); /* init it locked? */
+}
+
+void
+init_platform_hubinfo(nodepda_t **nodepdaindr) {
+	cnodeid_t       cnode;
+	hubinfo_t hubinfo;
+	nodepda_t *npda;
+
+	for (cnode = 0; cnode < numionodes; cnode++) {
+		npda = nodepdaindr[cnode];
+		hubinfo = (hubinfo_t)npda->pdinfo;
+		hubinfo->h_nasid = COMPACT_TO_NASID_NODEID(cnode);
+		/* For TIO the following returns -1 */
+		hubinfo->h_widgetid = hub_widget_id(hubinfo->h_nasid);
+	}
 }
 
 void
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/ml_SN_intr.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/ml_SN_intr.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/ml_SN_intr.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/ml_SN_intr.c	2003-09-12 12:44:35.000000000 -0700
@@ -102,7 +102,7 @@
 
 	local5_config.sh_local_int5_config_regval = 0;
 	local5_config.sh_local_int5_config_s.idx = SGI_UART_VECTOR;
-	local5_config.sh_local_int5_config_s.pid = cpu0;
+	local5_config.sh_local_int5_config_s.pid = cpu;
 	HUB_S( (unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_LOCAL_INT5_CONFIG),
 		local5_config.sh_local_int5_config_regval);
 
@@ -366,6 +366,7 @@
 	vertex_hdl_t	pconn_vhdl;
 	pcibr_soft_t	pcibr_soft;
 	int 		bit;
+	static cnodeid_t last_node = 0;
 
 /* SN2 + pcibr addressing limitation */
 /* Due to this limitation, all interrupts from a given bridge must go to the name node.*/
@@ -413,18 +414,20 @@
 
 	if (candidate  != CPU_NONE) {
 		printk("Cannot target interrupt to target node (%ld).\n",candidate);
-		return CPU_NONE; } else {
-		/* printk("Cannot target interrupt to closest node (%d) 0x%p\n",
-			master_node_get(dev), (void *)owner_dev); */
+		return CPU_NONE; 
+	} else {
+		printk("Cannot target interrupt to closest node (0x%x) 0x%p\n",
+			master_node_get(dev), (void *)owner_dev);
 	}
 
 	// We couldn't put it on the closest node.  Try to find another one.
 	// Do a stupid round-robin assignment of the node.
 
 	{
-		static cnodeid_t last_node = -1;
+		int i;
+
 		if (last_node >= numnodes) last_node = 0;
-		for (candidate_node = last_node + 1; candidate_node != last_node; candidate_node++) {
+		for (i = 0, candidate_node = last_node; i < numnodes; candidate_node++,i++) {
 			if (candidate_node == numnodes) candidate_node = 0;
 			cpuid = intr_bit_reserve_test(CPU_NONE,
 							0,
@@ -435,6 +438,7 @@
 							name,
 							resp_bit);
 			if (cpuid != CPU_NONE) {
+				last_node = candidate_node + 1;
 				return cpuid;
 			}
 		}
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/ml_iograph.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/ml_iograph.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/ml_iograph.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/ml_iograph.c	2003-09-12 12:44:35.000000000 -0700
@@ -49,20 +49,20 @@
  * xswitch vertex is created.
  */
 typedef struct xswitch_vol_s {
-	mutex_t xswitch_volunteer_mutex;
+	struct semaphore xswitch_volunteer_mutex;
 	int		xswitch_volunteer_count;
 	vertex_hdl_t	xswitch_volunteer[NUM_XSWITCH_VOLUNTEER];
 } *xswitch_vol_t;
 
+
 void
 xswitch_vertex_init(vertex_hdl_t xswitch)
 {
 	xswitch_vol_t xvolinfo;
 	int rc;
-	extern void * snia_kmem_zalloc(size_t size, int flag);
 
-	xvolinfo = snia_kmem_zalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL);
-	mutex_init(&xvolinfo->xswitch_volunteer_mutex);
+	xvolinfo = snia_kmem_zalloc(sizeof(struct xswitch_vol_s));
+	init_MUTEX(&xvolinfo->xswitch_volunteer_mutex);
 	rc = hwgraph_info_add_LBL(xswitch, 
 			INFO_LBL_XSWITCH_VOL,
 			(arbitrary_info_t)xvolinfo);
@@ -108,7 +108,7 @@
 	    return;
 	}
 
-	mutex_lock(&xvolinfo->xswitch_volunteer_mutex);
+	down(&xvolinfo->xswitch_volunteer_mutex);
 	ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER);
 	xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master;
 	xvolinfo->xswitch_volunteer_count++;
@@ -126,7 +126,7 @@
 			xvolinfo->xswitch_volunteer[1] = hubv;
 		}
 	}
-	mutex_unlock(&xvolinfo->xswitch_volunteer_mutex);
+	up(&xvolinfo->xswitch_volunteer_mutex);
 }
 
 extern int xbow_port_io_enabled(nasid_t nasid, int widgetnum);
@@ -193,16 +193,16 @@
 		 * hub that owned it in the prom.
 		 */
 		if (is_master_baseio_nasid_widget(nasid, widgetnum)) {
-			extern nasid_t get_master_baseio_nasid(void);
+			extern nasid_t snia_get_master_baseio_nasid(void);
 			for (i=0; i<num_volunteer; i++) {
 				hubv = xvolinfo->xswitch_volunteer[i];
 				hubinfo_get(hubv, &hubinfo);
 				nasid = hubinfo->h_nasid;
-				if (nasid == get_master_baseio_nasid())
+				if (nasid == snia_get_master_baseio_nasid())
 					goto do_assignment;
 			}
-			PRINT_PANIC("Nasid == %d, console nasid == %d",
-				nasid, get_master_baseio_nasid());
+			panic("Nasid == %d, console nasid == %d",
+				nasid, snia_get_master_baseio_nasid());
 		}
 
 		/*
@@ -237,44 +237,12 @@
 }
 
 /*
- * Early iograph initialization.  Called by master CPU in mlreset().
- * Useful for including iograph.o in kernel.o.
- */
-void
-iograph_early_init(void)
-{
-/*
- * Need new way to get this information ..
- */
-	cnodeid_t cnode;
-	nasid_t nasid;
-	lboard_t *board;
-	
-	/*
-	 * Init. the board-to-hwgraph link early, so FRU analyzer
-	 * doesn't trip on leftover values if we panic early on.
-	 */
-	for(cnode = 0; cnode < numnodes; cnode++) {
-		nasid = COMPACT_TO_NASID_NODEID(cnode);
-		board = (lboard_t *)KL_CONFIG_INFO(nasid);
-		DBG("iograph_early_init: Found board 0x%p\n", board);
-
-		/* Check out all the board info stored on a node */
-		while(board) {
-			board->brd_graph_link = GRAPH_VERTEX_NONE;
-			board = KLCF_NEXT(board);
-			DBG("iograph_early_init: Found board 0x%p\n", board);
-		}
-	}
-}
-
-/*
  * Let boot processor know that we're done initializing our node's IO
  * and then exit.
  */
 /* ARGSUSED */
 static void
-io_init_done(cnodeid_t cnodeid,cpu_cookie_t c)
+io_init_done(cnodeid_t cnodeid,cpuid_t c)
 {
 	/* Let boot processor know that we're done. */
 }
@@ -414,8 +382,8 @@
 		 * If the current hub is not supposed to be the master 
 		 * for this widgetnum, then skip this widget.
 		 */
-		if (xswitch_info_master_assignment_get(xswitch_info,
-						       widgetnum) != hubv) {
+
+		if (xswitch_info_master_assignment_get(xswitch_info, widgetnum) != hubv) {
 			return;
 		}
 
@@ -461,6 +429,8 @@
 			(board->brd_type == KLTYPE_PBRICK) ? EDGE_LBL_PBRICK :
 			(board->brd_type == KLTYPE_PXBRICK) ? EDGE_LBL_PXBRICK :
 			(board->brd_type == KLTYPE_IXBRICK) ? EDGE_LBL_IXBRICK :
+			(board->brd_type == KLTYPE_CGBRICK) ? EDGE_LBL_CGBRICK :
+			(board->brd_type == KLTYPE_OPUSBRICK) ? EDGE_LBL_OPUSBRICK :
 			(board->brd_type == KLTYPE_XBRICK) ? EDGE_LBL_XBRICK : "?brick",
 			EDGE_LBL_XTALK, widgetnum);
 		
@@ -503,7 +473,6 @@
 				       hubv, hub_widgetid);
 
 		ia64_sn_sysctl_iobrick_module_get(nasid, &io_module);
-
 		if (io_module >= 0) {
 			char			buffer[16];
 			vertex_hdl_t		to, from;
@@ -514,8 +483,8 @@
 			memset(buffer, 0, 16);
 			format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF);
 
-			if ( islower(MODULE_GET_BTCHAR(io_module)) ) {
-				bt = toupper(MODULE_GET_BTCHAR(io_module));
+			if ( isupper(MODULE_GET_BTCHAR(io_module)) ) {
+				bt = tolower(MODULE_GET_BTCHAR(io_module));
 			}
 			else {
 				bt = MODULE_GET_BTCHAR(io_module);
@@ -534,13 +503,16 @@
 				EDGE_LBL_NODE "/" EDGE_LBL_XTALK "/"
 				"0",
 				buffer, geo_slab(board->brd_geoid));
+			DBG("io_xswitch_widget_init: FROM path '%s'\n", pathname);
+
 			from = hwgraph_path_to_vertex(pathname);
 			ASSERT_ALWAYS(from);
+
 			sprintf(pathname, EDGE_LBL_HW "/" EDGE_LBL_MODULE "/%s/"
 				EDGE_LBL_SLAB "/%d/"
 				"%s",
 				buffer, geo_slab(board->brd_geoid), brick_name);
-
+			DBG("io_xswitch_widget_init: TO path '%s'\n", pathname);
 			to = hwgraph_path_to_vertex(pathname);
 			ASSERT_ALWAYS(to);
 			rc = hwgraph_edge_add(from, to,
@@ -568,11 +540,8 @@
 	
 	DBG("io_init_xswitch_widgets: xswitchv 0x%p for cnode %d\n", xswitchv, cnode);
 
-	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; 
-	     widgetnum++) {
-		io_xswitch_widget_init(xswitchv,
-				       cnodeid_to_vertex(cnode),
-				       widgetnum);
+	for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
+		io_xswitch_widget_init(xswitchv, cnodeid_to_vertex(cnode), widgetnum);
 	}
 }
 
@@ -654,8 +623,7 @@
 	nodepda_t	*npdap;
 	struct semaphore *peer_sema = 0;
 	uint32_t	widget_partnum;
-	cpu_cookie_t	c = 0;
-	extern int hubdev_docallouts(vertex_hdl_t);
+	cpuid_t	c = 0;
 
 	npdap = NODEPDA(cnodeid);
 
@@ -671,8 +639,6 @@
 
 	ASSERT(hubv != GRAPH_VERTEX_NONE);
 
-	hubdev_docallouts(hubv);
-
 	/*
 	 * Read mfg info on this hub
 	 */
@@ -817,12 +783,15 @@
 		 *	5) Initialize all xwidgets on the xswitch
 		 */
 
+		DBG("call volunteer_for_widgets\n");
+
 		volunteer_for_widgets(switchv, hubv);
 
 		/* If there's someone else on this crossbow, recognize him */
 		if (npdap->xbow_peer != INVALID_NASID) {
 			nodepda_t *peer_npdap = NODEPDA(NASID_TO_COMPACT_NODEID(npdap->xbow_peer));
 			peer_sema = &peer_npdap->xbow_sema;
+			DBG("call volunteer_for_widgets again\n");
 			volunteer_for_widgets(switchv, peer_npdap->node_vertex);
 		}
 
@@ -830,13 +799,13 @@
 
 		/* Signal that we're done */
 		if (peer_sema) {
-			mutex_unlock(peer_sema);
+			up(peer_sema);
 		}
 		
 	}
 	else {
 	    /* Wait 'til master is done assigning widgets. */
-	    mutex_lock(&npdap->xbow_sema);
+	    down(&npdap->xbow_sema);
 	}
 
 #ifdef PROBE_TEST
@@ -961,7 +930,7 @@
 		else
 			DBG("none found!\n");
 
-		DELAY(15000000);
+		udelay(15000000);
 		//prom_reboot();
 		panic("FIXME: devnamefromarcs: should call prom_reboot here.\n");
 		/* NOTREACHED */
@@ -1013,10 +982,10 @@
         2,                                      /* 0x8            */
         1,                                      /* 0x9            */
         0, 0,                                   /* 0xa - 0xb      */
-        4,                                      /* 0xc            */
+        5,                                      /* 0xc            */
         6,                                      /* 0xd            */
-        3,                                      /* 0xe            */
-        5                                       /* 0xf            */
+        4,                                      /* 0xe            */
+        3                                       /* 0xf            */
     }
  },
 
@@ -1034,6 +1003,20 @@
     }
  },
 
+/* OPUSbrick widget number to PCI bus number map */
+ {      MODULE_OPUSBRICK,                       /* OPUSbrick type */ 
+    /*  PCI Bus #                                  Widget #       */
+    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        0,                                      /* 0x8            */
+        0,                                      /* 0x9            */
+        0, 0,                                   /* 0xa - 0xb      */
+        0,                                      /* 0xc            */
+        0,                                      /* 0xd            */
+        0,                                      /* 0xe            */
+        1                                       /* 0xf            */
+    }
+ },
+
 /* IXbrick widget number to PCI bus number map */
  {      MODULE_IXBRICK,                         /* IXbrick type   */ 
     /*  PCI Bus #                                  Widget #       */
@@ -1060,6 +1043,19 @@
         0,                                      /* 0xe            */
         0                                       /* 0xf            */
     }
+ },
+/* CG brick widget number to PCI bus number map */
+ {      MODULE_CGBRICK,                    /* CG brick       */
+    /*  PCI Bus #                                  Widget #       */
+    {   0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
+        0,                                      /* 0x8            */
+        0,                                      /* 0x9            */
+        0, 1,                                   /* 0xa - 0xb      */
+        0,                                      /* 0xc            */
+        0,                                      /* 0xd            */
+        0,                                      /* 0xe            */
+        0                                       /* 0xf            */
+     }
  }
 };
 
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/module.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/module.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/module.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/module.c	2003-09-12 12:44:35.000000000 -0700
@@ -128,21 +128,26 @@
     int			i;
     char		buffer[16];
     moduleid_t		moduleid;
+    slabid_t		slab_number;
 
     memset(buffer, 0, 16);
     moduleid = geo_module(geoid);
     format_module_id(buffer, moduleid, MODULE_FORMAT_BRIEF);
-    DPRINTF("module_add_node: moduleid=%s node=%d\n", buffer, cnodeid);
+    DPRINTF("module_add_node: moduleid=%s node=%d ", buffer, cnodeid);
 
     if ((m = module_lookup(moduleid)) == 0) {
 	m = kmalloc(sizeof (module_t), GFP_KERNEL);
-	memset(m, 0 , sizeof(module_t));
 	ASSERT_ALWAYS(m);
+	memset(m, 0 , sizeof(module_t));
+
+	for (slab_number = 0; slab_number <= MAX_SLABS; slab_number++) {
+		m->nodes[slab_number] = -1;
+	}
 
 	m->id = moduleid;
 	spin_lock_init(&m->lock);
 
-	mutex_init_locked(&m->thdcnt);
+	init_MUTEX_LOCKED(&m->thdcnt);
 
 	/* Insert in sorted order by module number */
 
@@ -153,16 +158,23 @@
 	nummodules++;
     }
 
-    m->nodes[m->nodecnt] = cnodeid;
-    m->geoid[m->nodecnt] = geoid;
-    m->nodecnt++;
+    /*
+     * Save this information in the correct slab number of the node in the 
+     * module.
+     */
+    slab_number = geo_slab(geoid);
+    DPRINTF("slab number added 0x%x\n", slab_number);
 
-    DPRINTF("module_add_node: module %s now has %d nodes\n", buffer, m->nodecnt);
+    if (m->nodes[slab_number] != -1)
+	panic("module_add_node .. slab previously found\n");
+
+    m->nodes[slab_number] = cnodeid;
+    m->geoid[slab_number] = geoid;
 
     return m;
 }
 
-int module_probe_snum(module_t *m, nasid_t nasid)
+int module_probe_snum(module_t *m, nasid_t host_nasid, nasid_t nasid)
 {
     lboard_t	       *board;
     klmod_serial_num_t *comp;
@@ -172,7 +184,7 @@
     /*
      * record brick serial number
      */
-    board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
+    board = find_lboard((lboard_t *) KL_CONFIG_INFO(host_nasid), KLTYPE_SNIA);
 
     if (! board || KL_CONFIG_DUPLICATE_BOARD(board))
     {
@@ -244,21 +256,47 @@
 
     nserial = 0;
 
+    /*
+     * First pass just scan for compute node boards KLTYPE_SNIA.
+     * We do not support memoryless compute nodes.
+     */
     for (node = 0; node < numnodes; node++) {
 	nasid = COMPACT_TO_NASID_NODEID(node);
-
 	board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
 	ASSERT(board);
 
-	m = module_add_node(board->brd_geoid, node);
+	HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, NULL, NULL, "Found Shub lboard 0x%lx nasid 0x%x cnode 0x%x \n", (unsigned long)board, (int)nasid, (int)node));
 
-	if (! m->snum_valid && module_probe_snum(m, nasid))
+	m = module_add_node(board->brd_geoid, node);
+	if (! m->snum_valid && module_probe_snum(m, nasid, nasid))
 	    nserial++;
     }
 
-    DPRINTF("********found total of %d serial numbers in the system\n",
-	    nserial);
+    /*
+     * Second scan, look for TIO's board hosted by compute nodes.
+     */
+    for (node = numnodes; node < numionodes; node++) {
+	nasid_t		tio_nasid;
+	cnodeid_t	tio_node;
+	char		serial_number[16];
 
-    if (nserial == 0)
-	DPRINTF(KERN_WARNING  "io_module_init: No serial number found.\n");
+        tio_nasid = COMPACT_TO_NASID_NODEID(node);
+        board = find_lboard((lboard_t *) KL_CONFIG_INFO(tio_nasid), KLTYPE_TIO);
+	ASSERT(board);
+	tio_node = NASID_TO_COMPACT_NODEID(tio_nasid);
+
+	HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, NULL, NULL, "Found TIO lboard 0x%lx tio nasid %d tio cnode %d\n", (unsigned long)board, (int)tio_nasid, (int)tio_node));
+
+        m = module_add_node(board->brd_geoid, tio_node);
+
+	/*
+	 * Get and initialize the serial number of TIO.
+	 */
+	board_serial_number_get( board, serial_number );
+    	if( serial_number[0] != '\0' ) {
+        	encode_str_serial( serial_number, m->snum.snum_str );
+        	m->snum_valid = 1;
+		nserial++;
+	}
+    }
 }
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c	2003-09-12 12:44:35.000000000 -0700
@@ -86,7 +86,6 @@
     int                     num_entries, entry;
     int                     i, j;
     bridgereg_t             old_enable, new_enable;
-    int                     s;
 
     /* Probe SSRAM to determine its size. */
     old_enable = bridge->b_int_enable;
@@ -113,12 +112,10 @@
      * The read following the write is required for the Bridge war
      */
 
-    s = splhi();
     bridge->b_wid_control = (bridge->b_wid_control
 			& ~BRIDGE_CTRL_SSRAM_SIZE_MASK)
 			| BRIDGE_CTRL_SSRAM_SIZE(largest_working_size);
     bridge->b_wid_control;		/* inval addr bug war */
-    splx(s);
 
     num_entries = ATE_NUM_ENTRIES(largest_working_size);
 
@@ -382,25 +379,9 @@
 	  int ate_count,
 	  bridge_ate_t ate)
 {
-	if (IS_PIC_SOFT(pcibr_soft) ) {
-    		while (ate_count-- > 0) {
-			*ate_ptr++ = ate;
-			ate += IOPGSIZE;
-		}
-	}
-	else {
-		if (io_get_sh_swapper(NASID_GET(ate_ptr))) {
-    			while (ate_count-- > 0) {
-				*ate_ptr++ = __swab64(ate);
-				ate += IOPGSIZE;
-			}
-		}
-		else {
-    			while (ate_count-- > 0) {
-				*ate_ptr++ = ate;
-				ate += IOPGSIZE;
-			}
-		}
+    	while (ate_count-- > 0) {
+		*ate_ptr++ = ate;
+		ate += IOPGSIZE;
 	}
 }
 
@@ -442,19 +423,7 @@
     for (slot = pcibr_soft->bs_min_slot; 
 		slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
 	if ((cmd_reg = cmd_regs[slot]) & PCI_CMD_BUS_MASTER) {
-		if ( IS_PIC_SOFT(pcibr_soft) ) {
-			pcibr_slot_config_set(bridge, slot, PCI_CFG_COMMAND/4, cmd_reg);
-		}
-		else {
-			if (io_get_sh_swapper(NASID_GET(bridge))) {
-				bridge->b_type0_cfg_dev[slot].l[PCI_CFG_COMMAND / 4] = __swab32(cmd_reg);
-			}
-			else {
-//				BUG(); /* Does this really work if called when io_get_sh_swapper = 0? */
-//				bridge->b_type0_cfg_dev[slot].l[PCI_CFG_COMMAND / 4] = cmd_reg;
-				pcibr_slot_config_set(bridge, slot, PCI_CFG_COMMAND/4, cmd_reg);
-			}
-		}
+		pcibr_slot_config_set(bridge, slot, PCI_CFG_COMMAND/4, cmd_reg);
 	}
     }
     pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_BUSY;
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c	2003-09-12 12:44:35.000000000 -0700
@@ -11,8 +11,10 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/string.h>
-#include <linux/interrupt.h>
+#if 0
 #include <linux/ioport.h>
+#include <linux/interrupt.h>
+#endif
 #include <asm/sn/sgi.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sn_cpuid.h>
@@ -220,8 +222,6 @@
 
 int                     pcibr_reset(vertex_hdl_t);
 pciio_endian_t          pcibr_endian_set(vertex_hdl_t, pciio_endian_t, pciio_endian_t);
-int                     pcibr_priority_bits_set(pcibr_soft_t, pciio_slot_t, pciio_priority_t);
-pciio_priority_t        pcibr_priority_set(vertex_hdl_t, pciio_priority_t);
 int                     pcibr_device_flags_set(vertex_hdl_t, pcibr_device_flags_t);
 
 extern cfg_p            pcibr_config_addr(vertex_hdl_t, unsigned);
@@ -506,17 +506,6 @@
 	slotp->bss_device = new;
 	bridge->b_wid_tflush;		/* wait until Bridge PIO complete */
     }
-    else {
-	if (io_get_sh_swapper(NASID_GET(bridge))) {
-		BRIDGE_REG_SET32((&bridge->b_device[slot].reg)) = __swab32(new);
-		slotp->bss_device = new;
-		BRIDGE_REG_GET32((&bridge->b_wid_tflush));  /* wait until Bridge PIO complete */
-	} else {
-		bridge->b_device[slot].reg = new;
-		slotp->bss_device = new;
-		bridge->b_wid_tflush;               /* wait until Bridge PIO complete */
-	}
-    }
     pcibr_unlock(pcibr_soft, s);
 
 #ifdef PIC_LATER
@@ -551,31 +540,6 @@
     pcibr_unlock(pcibr_soft, s);
 }
 
-/*
- * flush write gather buffer for slot
- */
-static void
-pcibr_device_write_gather_flush(pcibr_soft_t pcibr_soft,
-              pciio_slot_t slot)
-{
-    bridge_t               *bridge;
-    unsigned long          s;
-    volatile uint32_t     wrf;
-    s = pcibr_lock(pcibr_soft);
-    bridge = pcibr_soft->bs_base;
-
-    if ( IS_PIC_SOFT(pcibr_soft) ) {
-	wrf = bridge->b_wr_req_buf[slot].reg;
-    }
-    else {
-	if (io_get_sh_swapper(NASID_GET(bridge))) {
-		wrf = BRIDGE_REG_GET32((&bridge->b_wr_req_buf[slot].reg));
-	} else {
-		wrf = bridge->b_wr_req_buf[slot].reg;
-	}
-    }
-    pcibr_unlock(pcibr_soft, s);
-}
 
 /* =====================================================================
  *    Bridge (pcibr) "Device Driver" entry points
@@ -618,7 +582,6 @@
 	.mmap		= pcibr_mmap,
 };
 
-
 /* This is special case code used by grio. There are plans to make
  * this a bit more general in the future, but till then this should
  * be sufficient.
@@ -923,28 +886,33 @@
 
 	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, f_c, "pcibr_bus_cnvlink\n"));
 
-	if (GRAPH_SUCCESS != hwgraph_vertex_name_get(f_c, dst, MAXDEVNAME))
+	if (GRAPH_SUCCESS != hwgraph_vertex_name_get(f_c, dst, MAXDEVNAME)) {
 		return 0;
+	}
 
 	/* dst example == /hw/module/001c02/Pbrick/xtalk/8/pci/direct */
 
 	/* find the widget number */
 	xp = strstr(dst, "/"EDGE_LBL_XTALK"/");
-	if (xp == NULL)
+	if (xp == NULL) {
 		return 0;
+	}
 	widgetnum = simple_strtoul(xp+7, NULL, 0);
-	if (widgetnum < XBOW_PORT_8 || widgetnum > XBOW_PORT_F)
+	if (widgetnum < XBOW_PORT_8 || widgetnum > XBOW_PORT_F) {
 		return 0;
+	}
 
 	/* remove "/pci/direct" from path */
 	cp = strstr(dst, "/" EDGE_LBL_PCI "/" EDGE_LBL_DIRECT);
-	if (cp == NULL)
+	if (cp == NULL) {
 		return 0;
+	}
 	*cp = (char)NULL;
 
 	/* get the vertex for the widget */
-	if (GRAPH_SUCCESS != hwgraph_traverse(NULL, dp, &svtx))	
+	if (GRAPH_SUCCESS != hwgraph_traverse(NULL, dp, &svtx))	{
 		return 0;
+	}
 
 	*xp = (char)NULL;		/* remove "/xtalk/..." from path */
 
@@ -1023,13 +991,10 @@
     vertex_hdl_t            noslot_conn;
     char                    devnm[MAXDEVNAME], *s;
     pcibr_hints_t           pcibr_hints;
-    uint64_t              int_enable;
-    bridgereg_t             int_enable_32;
+    uint64_t                int_enable;
     picreg_t                int_enable_64;
     unsigned                rrb_fixed = 0;
 
-    int                     spl_level;
-
 #if PCI_FBBE
     int                     fast_back_to_back_enable;
 #endif
@@ -1069,7 +1034,7 @@
     NEW(pcibr_soft);
     if (ret_softp)
 	*ret_softp = pcibr_soft;
-    BZERO(pcibr_soft, sizeof *pcibr_soft);
+    memset(pcibr_soft, 0, sizeof *pcibr_soft);
     pcibr_soft_set(pcibr_vhdl, pcibr_soft);
     pcibr_soft->bs_conn = xconn_vhdl;
     pcibr_soft->bs_vhdl = pcibr_vhdl;
@@ -1190,6 +1155,7 @@
 	switch (pcibr_soft->bs_bricktype) {
 	case MODULE_PXBRICK:
 	case MODULE_IXBRICK:
+	case MODULE_OPUSBRICK:
 	    pcibr_soft->bs_first_slot = 0;
 	    pcibr_soft->bs_last_slot = 1;
 	    pcibr_soft->bs_last_reset = 1;
@@ -1236,6 +1202,13 @@
 		pcibr_soft->bs_last_slot = 6;
 	    }
             break;
+
+        case MODULE_CGBRICK:
+            pcibr_soft->bs_first_slot = 0;
+            pcibr_soft->bs_last_slot = 0;
+            pcibr_soft->bs_last_reset = 0;
+            break;
+
 	default:
 	    break;
         }
@@ -1316,8 +1289,6 @@
 	if (busnum == 0) {
 	    xwidget_error_register(xconn_vhdl, pcibr_error_handler_wrapper, pcibr_soft);
 	}
-    } else {
-	xwidget_error_register(xconn_vhdl, pcibr_error_handler, pcibr_soft);
     }
 
     /*
@@ -1371,8 +1342,6 @@
      */
     if (IS_PIC_SOFT(pcibr_soft))
 	bridge->b_int_device = (uint32_t) 0x006db6db;
-    else
-	bridge->b_int_device = (uint32_t) 0xffffffff;
 
     {
 	bridgereg_t             dirmap;
@@ -1411,7 +1380,7 @@
 	 * for the lowest hunk of memory.
 	 */
 	xbase = xtalk_dmatrans_addr(xconn_vhdl, 0,
-				    paddr, _PAGESZ, 0);
+				    paddr, PAGE_SIZE, 0);
 
 	if (xbase != XIO_NOWHERE) {
 	    if (XIO_PACKED(xbase)) {
@@ -1441,24 +1410,18 @@
 	 * ensure that we write and read without any interruption.
 	 * The read following the write is required for the Bridge war
 	 */
-	spl_level = splhi();
 #if IOPGSIZE == 4096
         if (IS_PIC_SOFT(pcibr_soft)) {
             bridge->p_wid_control_64 &= ~BRIDGE_CTRL_PAGE_SIZE;
-        } else {
-            bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE;
-        }
+        } 
 #elif IOPGSIZE == 16384
         if (IS_PIC_SOFT(pcibr_soft)) {
             bridge->p_wid_control_64 |= BRIDGE_CTRL_PAGE_SIZE;
-        } else {
-            bridge->b_wid_control |= BRIDGE_CTRL_PAGE_SIZE;
         }
 #else
 	<<<Unable to deal with IOPGSIZE >>>;
 #endif
 	bridge->b_wid_control;		/* inval addr bug war */
-	splx(spl_level);
 
 	/* Initialize internal mapping entries */
 	for (entry = 0; entry < pcibr_soft->bs_int_ate_size; entry++) {
@@ -1606,13 +1569,7 @@
 #ifdef PFG_TEST
 	int_enable = (uint64_t)0x7ffffeff7ffffeff;
 #endif
-    } else {
-	int_enable_32 = bridge->b_int_enable | (BRIDGE_ISR_ERRORS & 0xffffffff);
-	int_enable = ((uint64_t)int_enable_32 & 0xffffffff);
-#ifdef PFG_TEST
-	int_enable = (uint64_t)0x7ffffeff;
-#endif
-    }
+    } 
 
 
 #if BRIDGE_ERROR_INTR_WAR
@@ -1672,8 +1629,6 @@
 
     if (IS_PIC_SOFT(pcibr_soft)) {
         bridge->p_int_enable_64 = (picreg_t)int_enable;
-    } else {
-        bridge->b_int_enable = (bridgereg_t)int_enable;
     }
     bridge->b_int_mode = 0;		/* do not send "clear interrupt" packets */
 
@@ -1734,7 +1689,7 @@
     /* Setup the Bus's PCI IO Root Resource. */
     pcibr_soft->bs_io_win_root_resource.start = PCIBR_BUS_IO_BASE;
     pcibr_soft->bs_io_win_root_resource.end = 0xffffffff;
-    res = (struct resource *) kmalloc( sizeof(struct resource), KM_NOSLEEP);
+    res = (struct resource *) kmalloc( sizeof(struct resource), GFP_KERNEL);
     if (!res)
 	panic("PCIBR:Unable to allocate resource structure\n");
 
@@ -1746,13 +1701,13 @@
 	panic("PCIBR:Unable to request_resource()\n");
 
     /* Setup the Small Window Root Resource */
-    pcibr_soft->bs_swin_root_resource.start = _PAGESZ;
+    pcibr_soft->bs_swin_root_resource.start = PAGE_SIZE;
     pcibr_soft->bs_swin_root_resource.end = 0x000FFFFF;
 
     /* Setup the Bus's PCI Memory Root Resource */
     pcibr_soft->bs_mem_win_root_resource.start = 0x200000;
     pcibr_soft->bs_mem_win_root_resource.end = 0xffffffff;
-    res = (struct resource *) kmalloc( sizeof(struct resource), KM_NOSLEEP);
+    res = (struct resource *) kmalloc( sizeof(struct resource), GFP_KERNEL);
     if (!res)
         panic("PCIBR:Unable to allocate resource structure\n");
 
@@ -1862,6 +1817,7 @@
 		break;
 	case MODULE_PXBRICK:
 	case MODULE_IXBRICK:
+	case MODULE_OPUSBRICK:
 		/* 
 		 * If the IO9 is in the PXBrick (bus1, slot1) allocate
                  * RRBs to all the devices
@@ -1874,18 +1830,16 @@
 			do_pcibr_rrb_autoalloc(pcibr_soft, 2, VCHAN0, 4);
 			do_pcibr_rrb_autoalloc(pcibr_soft, 3, VCHAN0, 4);
 		} else {
-			do_pcibr_rrb_autoalloc(pcibr_soft, 0, VCHAN0, 8);
-			do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 8);
+			do_pcibr_rrb_autoalloc(pcibr_soft, 0, VCHAN0, 4);
+			do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 4);
 		}
 		break;
-	} /* switch */
-    }
 
-#ifdef LATER
-    if (strstr(nicinfo, XTALK_PCI_PART_NUM)) {
-	do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 8);
+        case MODULE_CGBRICK:
+                do_pcibr_rrb_autoalloc(pcibr_soft, 0, VCHAN0, 8);
+                break;
+	} /* switch */
     }
-#endif
 }  /* OK Special RRB allocations are done. */
 
     for (slot = pcibr_soft->bs_min_slot; 
@@ -1927,8 +1881,6 @@
     /* Disable the interrupts from the bridge */
     if (IS_PIC_SOFT(pcibr_soft)) {
 	bridge->p_int_enable_64 = 0;
-    } else {
-	bridge->b_int_enable = 0;
     }
     pcibr_unlock(pcibr_soft, s);
 
@@ -1942,7 +1894,6 @@
     pciio_device_info_unregister(pcibr_vhdl,
 				 &(pcibr_soft->bs_noslot_info->f_c));
 
-    spin_lock_destroy(&pcibr_soft->bs_lock);
     kfree(pcibr_soft->bs_name);
     
     /* Disconnect the error interrupt and free the xtalk resources 
@@ -1994,17 +1945,6 @@
     return (int) ainfo;
 }
 
-int
-pcibr_write_gather_flush(vertex_hdl_t pconn_vhdl)
-{
-    pciio_info_t  pciio_info = pciio_info_get(pconn_vhdl);
-    pcibr_soft_t  pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
-    pciio_slot_t  slot;
-    slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
-    pcibr_device_write_gather_flush(pcibr_soft, slot);
-    return 0;
-}
-
 /* =====================================================================
  *    PIO MANAGEMENT
  */
@@ -2220,17 +2160,6 @@
 			pcibr_soft->bs_slot[win].bss_device = devreg;
 			bridge->b_wid_tflush;   /* wait until Bridge PIO complete */
 		}
-		else {
-			if (io_get_sh_swapper(NASID_GET(bridge))) {
-				BRIDGE_REG_SET32((&bridge->b_device[win].reg)) = __swab32(devreg);
-				pcibr_soft->bs_slot[win].bss_device = devreg;
-				BRIDGE_REG_GET32((&bridge->b_wid_tflush)); /* wait until Bridge PIO complete */
-			} else {
-				bridge->b_device[win].reg = devreg;
-				pcibr_soft->bs_slot[win].bss_device = devreg;
-				bridge->b_wid_tflush;   /* wait until Bridge PIO complete */
-			}
-		}
 
 #ifdef PCI_LATER
 		PCIBR_DEBUG((PCIBR_DEBUG_DEVREG, pconn_vhdl, 
@@ -2418,22 +2347,6 @@
 		if (octl != nctl)		/* make the change if any */
 			bridge->b_wid_control = nctl;
 	    }
-	    else {
-	    	picreg_t             octl, nctl;
-		if (io_get_sh_swapper(NASID_GET(bridge))) {
-			octl = BRIDGE_REG_GET32((&bridge->b_wid_control));
-			nctl = bst ? octl | swb : octl & ~swb;
-
-			if (octl != nctl)           /* make the change if any */
-				BRIDGE_REG_SET32((&bridge->b_wid_control)) = __swab32(nctl);
-		} else {
-			octl = bridge->b_wid_control;
-			nctl = bst ? octl | swb : octl & ~swb;
-
-			if (octl != nctl)           /* make the change if any */
-				bridge->b_wid_control = nctl;
-		}
-	    }
 	    *bfp = bfn;			/* record the assignment */
 
 	    if (pcibr_debug_mask & PCIBR_DEBUG_PIOMAP) {
@@ -2656,7 +2569,7 @@
     /*
      * Check for proper alignment
      */
-    ASSERT(alignment >= NBPP);
+    ASSERT(alignment >= PAGE_SIZE);
     ASSERT((alignment & (alignment - 1)) == 0);
 
     align_mask = alignment - 1;
@@ -3092,7 +3005,7 @@
 				!IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) {
 		bridge_t               *bridge = pcibr_soft->bs_base;
 		volatile unsigned      *cmd_regp;
-		unsigned                cmd_reg;
+		unsigned                cmd_reg = 0;
 		unsigned long           s;
 
 		pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_SSRAM;
@@ -3103,13 +3016,6 @@
 		if ( IS_PIC_SOFT(pcibr_soft) ) {
 			cmd_reg = pcibr_slot_config_get(bridge, slot, PCI_CFG_COMMAND/4);
 		}
-		else {
-			if (io_get_sh_swapper(NASID_GET(bridge))) {
-				BRIDGE_REG_SET32((&cmd_reg)) = __swab32(*cmd_regp);
-			} else {
-				cmd_reg = pcibr_slot_config_get(bridge, slot, PCI_CFG_COMMAND/4);
-			}
-		}
 		pcibr_soft->bs_slot[slot].bss_cmd_pointer = cmd_regp;
 		pcibr_soft->bs_slot[slot].bss_cmd_shadow = cmd_reg;
 		pcibr_unlock(pcibr_soft, s);
@@ -3362,13 +3268,6 @@
 		if ( IS_PIC_SOFT(pcibr_soft) ) {
 			bridge->b_wid_tflush;	/* wait until Bridge PIO complete */
 		}
-		else {
-			if (io_get_sh_swapper(NASID_GET(bridge))) {
-				BRIDGE_REG_GET32((&bridge->b_wid_tflush));
-			} else {
-				bridge->b_wid_tflush;
-			}
-		}
 		PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev,
 			    "pcibr_dmamap_addr (PMU) : wanted paddr "
 			    "[0x%x..0x%x] returning PCI 0x%x\n", 
@@ -3827,17 +3726,6 @@
 		pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
 		bridge->b_wid_tflush;		/* wait until Bridge PIO complete */
 	}
-	else {
-		if (io_get_sh_swapper(NASID_GET(bridge))) {
-			BRIDGE_REG_SET32((&bridge->b_device[pciio_slot].reg)) = __swab32(devreg);
-			pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
-			BRIDGE_REG_GET32((&bridge->b_wid_tflush));/* wait until Bridge PIO complete */
-		} else {
-			bridge->b_device[pciio_slot].reg = devreg;
-			pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
-			bridge->b_wid_tflush;           /* wait until Bridge PIO complete */
-		}
-	}
     }
     pcibr_unlock(pcibr_soft, s);
 
@@ -3851,105 +3739,6 @@
     return desired_end;
 }
 
-/* This (re)sets the GBR and REALTIME bits and also keeps track of how
- * many sets are outstanding. Reset succeeds only if the number of outstanding
- * sets == 1.
- */
-int
-pcibr_priority_bits_set(pcibr_soft_t pcibr_soft,
-			pciio_slot_t pciio_slot,
-			pciio_priority_t device_prio)
-{
-    unsigned long           s;
-    int                    *counter;
-    bridgereg_t             rtbits = 0;
-    bridgereg_t             devreg;
-    int                     rc = PRIO_SUCCESS;
-
-    /* in dual-slot configurations, the host and the
-     * guest have separate DMA resources, so they
-     * have separate requirements for priority bits.
-     */
-
-    counter = &(pcibr_soft->bs_slot[pciio_slot].bss_pri_uctr);
-
-    /*
-     * Bridge supports PCI notions of LOW and HIGH priority
-     * arbitration rings via a "REAL_TIME" bit in the per-device
-     * Bridge register. The "GBR" bit controls access to the GBR
-     * ring on the xbow. These two bits are (re)set together.
-     *
-     * XXX- Bug in Rev B Bridge Si:
-     * Symptom: Prefetcher starts operating incorrectly. This happens
-     * due to corruption of the address storage ram in the prefetcher
-     * when a non-real time PCI request is pulled and a real-time one is
-     * put in it's place. Workaround: Use only a single arbitration ring
-     * on PCI bus. GBR and RR can still be uniquely used per
-     * device. NETLIST MERGE DONE, WILL BE FIXED IN REV C.
-     */
-
-    if (pcibr_soft->bs_rev_num != BRIDGE_PART_REV_B)
-	rtbits |= BRIDGE_DEV_RT;
-
-    /* NOTE- if we ever put DEV_RT or DEV_GBR on
-     * the disabled list, we will have to take
-     * it into account here.
-     */
-
-    s = pcibr_lock(pcibr_soft);
-    devreg = pcibr_soft->bs_slot[pciio_slot].bss_device;
-    if (device_prio == PCI_PRIO_HIGH) {
-	if ((++*counter == 1)) {
-	    if (rtbits)
-		devreg |= rtbits;
-	    else
-		rc = PRIO_FAIL;
-	}
-    } else if (device_prio == PCI_PRIO_LOW) {
-	if (*counter <= 0)
-	    rc = PRIO_FAIL;
-	else if (--*counter == 0)
-	    if (rtbits)
-		devreg &= ~rtbits;
-    }
-    if (pcibr_soft->bs_slot[pciio_slot].bss_device != devreg) {
-	bridge_t               *bridge = pcibr_soft->bs_base;
-
-	if ( IS_PIC_SOFT(pcibr_soft) ) {
-		bridge->b_device[pciio_slot].reg = devreg;
-		pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
-		bridge->b_wid_tflush;		/* wait until Bridge PIO complete */
-	}
-	else {
-		if (io_get_sh_swapper(NASID_GET(bridge))) {
-			BRIDGE_REG_SET32((&bridge->b_device[pciio_slot].reg)) = __swab32(devreg);
-			pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
-			BRIDGE_REG_GET32((&bridge->b_wid_tflush));/* wait until Bridge PIO complete */
-		} else {
-			bridge->b_device[pciio_slot].reg = devreg;
-			pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
-			bridge->b_wid_tflush;           /* wait until Bridge PIO complete */
-		}
-	}
-    }
-    pcibr_unlock(pcibr_soft, s);
-
-    return rc;
-}
-
-pciio_priority_t
-pcibr_priority_set(vertex_hdl_t pconn_vhdl,
-		   pciio_priority_t device_prio)
-{
-    pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);
-    pciio_slot_t            pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
-    pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
-
-    (void) pcibr_priority_bits_set(pcibr_soft, pciio_slot, device_prio);
-
-    return device_prio;
-}
-
 /*
  * Interfaces to allow special (e.g. SGI) drivers to set/clear
  * Bridge-specific device flags.  Many flags are modified through
@@ -4018,17 +3807,6 @@
 		pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
 		bridge->b_wid_tflush;	/* wait until Bridge PIO complete */
 	    }
-	    else {
-		if (io_get_sh_swapper(NASID_GET(bridge))) {
-			BRIDGE_REG_SET32((&bridge->b_device[pciio_slot].reg)) = __swab32(devreg);
-			pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
-			BRIDGE_REG_GET32((&bridge->b_wid_tflush));/* wait until Bridge PIO complete */
-		} else {
-			bridge->b_device[pciio_slot].reg = devreg;
-			pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
-			bridge->b_wid_tflush;       /* wait until Bridge PIO complete */
-		}
-	    }
 	}
 	pcibr_unlock(pcibr_soft, s);
 #ifdef PIC_LATER
@@ -4116,16 +3894,14 @@
     (pciio_provider_startup_f *) pcibr_provider_startup,
     (pciio_provider_shutdown_f *) pcibr_provider_shutdown,
     (pciio_reset_f *) pcibr_reset,
-    (pciio_write_gather_flush_f *) pcibr_write_gather_flush,
     (pciio_endian_set_f *) pcibr_endian_set,
-    (pciio_priority_set_f *) pcibr_priority_set,
     (pciio_config_get_f *) pcibr_config_get,
     (pciio_config_set_f *) pcibr_config_set,
     (pciio_error_devenable_f *) 0,
     (pciio_error_extract_f *) 0,
     (pciio_driver_reg_callback_f *) 0,
     (pciio_driver_unreg_callback_f *) 0,
-    (pciio_device_unregister_f 	*) pcibr_device_unregister,
+    (pciio_device_unregister_f 	*) 0,
     (pciio_dma_enabled_f		*) pcibr_dma_enabled,
 };
 
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c	2003-09-12 12:44:35.000000000 -0700
@@ -101,6 +101,7 @@
 
 #define F(s,n)          { 1l<<(s),-(s), n }
 
+#if defined(FORCE_ERRORS)
 static struct reg_values       space_v[] =
 {
     {PCIIO_SPACE_NONE, "none"},
@@ -147,6 +148,7 @@
     {BRIDGE_DEV_OFF_MASK, BRIDGE_DEV_OFF_ADDR_SHFT, "DEV_OFF", "%x"},
     {0}
 };
+#endif /* FORCE_ERRORS */
 
 static void
 print_bridge_errcmd(uint32_t cmdword, char *errtype)
@@ -663,7 +665,7 @@
 	entry = pcibr_list;
 	while (1) {
 	    if (entry == NULL) {
-		PRINT_PANIC("pcibr_error_intr_handler:\tmy parameter (0x%p) is not a pcibr_soft!", arg);
+		panic("pcibr_error_intr_handler:\tmy parameter (0x%p) is not a pcibr_soft!", arg);
 	    }
 	    if ((intr_arg_t) entry->bl_soft == arg)
 		break;
@@ -936,11 +938,11 @@
         (err_status & (BRIDGE_ISR_LLP_REC_SNERR | BRIDGE_ISR_LLP_REC_CBERR))) {
         printk("BRIDGE ERR_STATUS 0x%lx\n", err_status);
         pcibr_error_dump(pcibr_soft);
-        PRINT_PANIC("PCI Bridge Error interrupt killed the system");
+        panic("PCI Bridge Error interrupt killed the system");
     }
 
     if (err_status & BRIDGE_ISR_ERROR_FATAL) {
-	PRINT_PANIC("PCI Bridge Error interrupt killed the system");
+	panic("PCI Bridge Error interrupt killed the system");
 	    /*NOTREACHED */
     }
 
@@ -1080,7 +1082,9 @@
     int                     retval = IOERROR_HANDLED;
 
     vertex_hdl_t            pcibr_vhdl = pcibr_soft->bs_vhdl;
+#if defined(FORCE_ERRORS)
     bridge_t               *bridge = pcibr_soft->bs_base;
+#endif
 
     iopaddr_t               bad_xaddr;
 
@@ -1414,9 +1418,6 @@
 	}
 #if defined(FORCE_ERRORS)
 	if (0) {
-#elif !DEBUG
-	if (kdebug) {
-#endif
 	    /*
 	     * Dump raw data from Bridge/PCI layer.
 	     */
@@ -1444,9 +1445,8 @@
 		    BEM_ADD_REG(device);
 		}
 	    }
-#if !DEBUG || defined(FORCE_ERRORS)
 	}
-#endif
+#endif	/* FORCE_ERRORS */
 
 	/*
 	 * Since error could not be handled at lower level,
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c	2003-09-12 12:44:35.000000000 -0700
@@ -34,7 +34,7 @@
 inline int
 compare_and_swap_ptr(void **location, void *old_ptr, void *new_ptr)
 {
-	FIXME("compare_and_swap_ptr : NOT ATOMIC");
+	/* FIXME - compare_and_swap_ptr NOT ATOMIC */
 	if (*location == old_ptr) {
 		*location = new_ptr;
 		return(1);
@@ -103,7 +103,7 @@
     pcibr_intr_wrap_t	wrap;
 
 	if (cbuf->ib_in == cbuf->ib_out)
-	    PRINT_PANIC( "pcibr intr circular buffer empty, cbuf=0x%p, ib_in=ib_out=%d\n",
+	    panic( "pcibr intr circular buffer empty, cbuf=0x%p, ib_in=ib_out=%d\n",
 		(void *)cbuf, cbuf->ib_out);
 
 	wrap = cbuf->ib_cbuf[cbuf->ib_out++];
@@ -118,22 +118,21 @@
 pcibr_wrap_put(pcibr_intr_wrap_t wrap, pcibr_intr_cbuf_t cbuf)
 {
 	int	in;
-	int	s;
 
 	/*
 	 * Multiple CPUs could be executing this code simultaneously
 	 * if a handler has registered multiple interrupt lines and
 	 * the interrupts are directed to different CPUs.
 	 */
-	s = mutex_spinlock(&cbuf->ib_lock);
+	spin_lock(&cbuf->ib_lock);
 	in = (cbuf->ib_in + 1) % IBUFSIZE;
 	if (in == cbuf->ib_out) 
-	    PRINT_PANIC( "pcibr intr circular buffer full, cbuf=0x%p, ib_in=%d\n",
+	    panic( "pcibr intr circular buffer full, cbuf=0x%p, ib_in=%d\n",
 		(void *)cbuf, cbuf->ib_in);
 
 	cbuf->ib_cbuf[cbuf->ib_in] = wrap;
 	cbuf->ib_in = in;
-	mutex_spinunlock(&cbuf->ib_lock, s);
+	spin_unlock(&cbuf->ib_lock);
 	return;
 }
 
@@ -341,7 +340,7 @@
     pcibr_intr->bi_mustruncpu = CPU_NONE;
     pcibr_intr->bi_ibuf.ib_in = 0;
     pcibr_intr->bi_ibuf.ib_out = 0;
-    mutex_spinlock_init(&pcibr_intr->bi_ibuf.ib_lock);
+    spin_lock_init(&pcibr_intr->bi_ibuf.ib_lock);
     pcibr_int_bits = pcibr_soft->bs_intr_bits((pciio_info_t)pcibr_info, lines, 
 		PCIBR_NUM_SLOTS(pcibr_soft));
 
@@ -857,7 +856,7 @@
 		printk(KERN_WARNING  "NEW=0x%x/0x%x  OLD=0x%x/0x%x\n",
 			NEW_b_wid_int_upper, NEW_b_wid_int_lower,
 			OLD_b_wid_int_upper, OLD_b_wid_int_lower);
-		PRINT_PANIC("PCI Bridge interrupt targetting error\n");
+		panic("PCI Bridge interrupt targetting error\n");
 	}
     }
 
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c	2003-09-12 12:44:35.000000000 -0700
@@ -407,14 +407,6 @@
 	while (*wrb_flush)
 		;
     }
-    else {
-	if (io_get_sh_swapper(NASID_GET(bridge))) {
-		while (BRIDGE_REG_GET32((wrb_flush)));
-	} else {
-		while (*wrb_flush)
-			;
-	}
-    }
     return(0);
 }
 
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c	2003-09-12 12:44:35.000000000 -0700
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <asm/sn/sgi.h>
+#include <asm/uaccess.h>
 #include <asm/sn/sn_cpuid.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
@@ -88,6 +89,8 @@
 int max_readcount_to_bufsize[MAX_READCNT_TABLE] = {512, 1024, 2048, 4096 };
 
 
+#define COPYOUT(a, b, c)	copy_to_user(b,a,c)
+
 /*==========================================================================
  *	BRIDGE PCI SLOT RELATED IOCTLs
  */
@@ -320,9 +323,8 @@
     reg_p                        b_respp;
     pcibr_slot_info_resp_t       slotp;
     pcibr_slot_func_info_resp_t  funcp;
-    extern void snia_kmem_free(void *, int);
 
-    slotp = snia_kmem_zalloc(sizeof(*slotp), 0);
+    slotp = snia_kmem_zalloc(sizeof(*slotp));
     if (slotp == NULL) {
         return(ENOMEM);
     }
@@ -1188,8 +1190,8 @@
 
 	    align = (win) ? size : align_slot; 
 
-	    if (align < _PAGESZ)
-		align = _PAGESZ;        /* ie. 0x00004000 */
+	    if (align < PAGE_SIZE)
+		align = PAGE_SIZE;        /* ie. 0x00004000 */
  
 	    switch (space) {
 	    case PCIIO_SPACE_IO:
@@ -1740,7 +1742,6 @@
 {
 	int rv;
 	picreg_t p_old_enable = (picreg_t)0, p_new_enable;
-	extern int badaddr_val(volatile void *, int, volatile void *);
 
 	p_old_enable = bridge->p_int_enable_64;
 	p_new_enable = p_old_enable & ~(BRIDGE_IMR_PCI_MST_TIMEOUT | PIC_ISR_PCIX_MTOUT);
@@ -1753,7 +1754,7 @@
 		bridge->p_int_rst_stat_64 = (BRIDGE_IRR_PCI_GRP_CLR | PIC_PCIX_GRP_CLR);
 		(void) bridge->b_wid_tflush;	/* flushbus */
 	}
-	rv = badaddr_val((void *) cfg, 4, valp);
+	rv = snia_badaddr_val((void *) cfg, 4, valp);
 	if (bridge->p_err_int_view_64 & (BRIDGE_ISR_PCI_MST_TIMEOUT | PIC_ISR_PCIX_MTOUT)) {
 		bridge->p_int_rst_stat_64 = BRIDGE_IRR_MULTI_CLR;
 		rv = 1;         /* unoccupied slot */
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pciio.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pciio.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pciio.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pciio.c	2003-09-12 12:44:35.000000000 -0700
@@ -36,85 +36,6 @@
 
 char                    pciio_info_fingerprint[] = "pciio_info";
 
-int
-badaddr_val(volatile void *addr, int len, volatile void *ptr)
-{
-	int ret = 0;
-	volatile void *new_addr;
-
-	switch (len) {
-		case 4:
-			new_addr = (void *) addr;
-			ret = ia64_sn_probe_io_slot((long)new_addr, len, (void *)ptr);
-			break;
-		default:
-			printk(KERN_WARNING "badaddr_val given len %x but supports len of 4 only\n", len);
-	}
-
-	if (ret < 0)
-		panic("badaddr_val: unexpected status (%d) in probing", ret);
-	return(ret);
-
-}
-
-
-nasid_t
-get_console_nasid(void)
-{
-	extern nasid_t console_nasid;
-	extern nasid_t master_baseio_nasid;
-
-	if (console_nasid < 0) {
-		console_nasid = ia64_sn_get_console_nasid();
-		if (console_nasid < 0) {
-// ZZZ What do we do if we don't get a console nasid on the hardware????
-			if (IS_RUNNING_ON_SIMULATOR() )
-				console_nasid = master_baseio_nasid;
-		}
-	} 
-	return console_nasid;
-}
-
-nasid_t
-get_master_baseio_nasid(void)
-{
-	extern nasid_t master_baseio_nasid;
-	extern char master_baseio_wid;
-
-	if (master_baseio_nasid < 0) {
-		master_baseio_nasid = ia64_sn_get_master_baseio_nasid();
-
-		if ( master_baseio_nasid >= 0 ) {
-        		master_baseio_wid = WIDGETID_GET(KL_CONFIG_CH_CONS_INFO(master_baseio_nasid)->memory_base);
-		}
-	} 
-	return master_baseio_nasid;
-}
-
-int
-hub_dma_enabled(vertex_hdl_t xconn_vhdl)
-{
-	return(0);
-}
-
-int
-hub_error_devenable(vertex_hdl_t xconn_vhdl, int devnum, int error_code)
-{
-	return(0);
-}
-
-void
-ioerror_dump(char *name, int error_code, int error_mode, ioerror_t *ioerror)
-{
-}
-
-/******
- ****** end hack defines ......
- ******/
-
-
-
-
 /* =====================================================================
  *    PCI Generic Bus Provider
  * Implement PCI provider operations.  The pciio* layer provides a
@@ -136,97 +57,9 @@
  */
 
 #if !defined(DEV_FUNC)
-static pciio_provider_t *pciio_to_provider_fns(vertex_hdl_t dev);
+extern pciio_provider_t *pciio_to_provider_fns(vertex_hdl_t dev);
 #endif
 
-pciio_piomap_t          pciio_piomap_alloc(vertex_hdl_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned);
-void                    pciio_piomap_free(pciio_piomap_t);
-caddr_t                 pciio_piomap_addr(pciio_piomap_t, iopaddr_t, size_t);
-
-void                    pciio_piomap_done(pciio_piomap_t);
-caddr_t                 pciio_piotrans_addr(vertex_hdl_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned);
-caddr_t			pciio_pio_addr(vertex_hdl_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, pciio_piomap_t *, unsigned);
-
-iopaddr_t               pciio_piospace_alloc(vertex_hdl_t, device_desc_t, pciio_space_t, size_t, size_t);
-void                    pciio_piospace_free(vertex_hdl_t, pciio_space_t, iopaddr_t, size_t);
-
-pciio_dmamap_t          pciio_dmamap_alloc(vertex_hdl_t, device_desc_t, size_t, unsigned);
-void                    pciio_dmamap_free(pciio_dmamap_t);
-iopaddr_t               pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t);
-void                    pciio_dmamap_done(pciio_dmamap_t);
-iopaddr_t               pciio_dmatrans_addr(vertex_hdl_t, device_desc_t, paddr_t, size_t, unsigned);
-void			pciio_dmamap_drain(pciio_dmamap_t);
-void			pciio_dmaaddr_drain(vertex_hdl_t, paddr_t, size_t);
-void			pciio_dmalist_drain(vertex_hdl_t, alenlist_t);
-iopaddr_t               pciio_dma_addr(vertex_hdl_t, device_desc_t, paddr_t, size_t, pciio_dmamap_t *, unsigned);
-
-pciio_intr_t            pciio_intr_alloc(vertex_hdl_t, device_desc_t, pciio_intr_line_t, vertex_hdl_t);
-void                    pciio_intr_free(pciio_intr_t);
-int                     pciio_intr_connect(pciio_intr_t, intr_func_t, intr_arg_t);
-void                    pciio_intr_disconnect(pciio_intr_t);
-vertex_hdl_t            pciio_intr_cpu_get(pciio_intr_t);
-
-void			pciio_slot_func_to_name(char *, pciio_slot_t, pciio_function_t);
-
-void                    pciio_provider_startup(vertex_hdl_t);
-void                    pciio_provider_shutdown(vertex_hdl_t);
-
-pciio_endian_t          pciio_endian_set(vertex_hdl_t, pciio_endian_t, pciio_endian_t);
-pciio_priority_t        pciio_priority_set(vertex_hdl_t, pciio_priority_t);
-vertex_hdl_t            pciio_intr_dev_get(pciio_intr_t);
-
-vertex_hdl_t            pciio_pio_dev_get(pciio_piomap_t);
-pciio_slot_t            pciio_pio_slot_get(pciio_piomap_t);
-pciio_space_t           pciio_pio_space_get(pciio_piomap_t);
-iopaddr_t               pciio_pio_pciaddr_get(pciio_piomap_t);
-ulong                   pciio_pio_mapsz_get(pciio_piomap_t);
-caddr_t                 pciio_pio_kvaddr_get(pciio_piomap_t);
-
-vertex_hdl_t            pciio_dma_dev_get(pciio_dmamap_t);
-pciio_slot_t            pciio_dma_slot_get(pciio_dmamap_t);
-
-pciio_info_t            pciio_info_chk(vertex_hdl_t);
-pciio_info_t            pciio_info_get(vertex_hdl_t);
-void                    pciio_info_set(vertex_hdl_t, pciio_info_t);
-vertex_hdl_t            pciio_info_dev_get(pciio_info_t);
-pciio_slot_t            pciio_info_slot_get(pciio_info_t);
-pciio_function_t        pciio_info_function_get(pciio_info_t);
-pciio_vendor_id_t       pciio_info_vendor_id_get(pciio_info_t);
-pciio_device_id_t       pciio_info_device_id_get(pciio_info_t);
-vertex_hdl_t            pciio_info_master_get(pciio_info_t);
-arbitrary_info_t        pciio_info_mfast_get(pciio_info_t);
-pciio_provider_t       *pciio_info_pops_get(pciio_info_t);
-error_handler_f	       *pciio_info_efunc_get(pciio_info_t);
-error_handler_arg_t    *pciio_info_einfo_get(pciio_info_t);
-pciio_space_t		pciio_info_bar_space_get(pciio_info_t, int);
-iopaddr_t		pciio_info_bar_base_get(pciio_info_t, int);
-size_t			pciio_info_bar_size_get(pciio_info_t, int);
-iopaddr_t		pciio_info_rom_base_get(pciio_info_t);
-size_t			pciio_info_rom_size_get(pciio_info_t);
-
-int                     pciio_attach(vertex_hdl_t);
-
-void                    pciio_provider_register(vertex_hdl_t, pciio_provider_t *pciio_fns);
-void                    pciio_provider_unregister(vertex_hdl_t);
-pciio_provider_t       *pciio_provider_fns_get(vertex_hdl_t);
-
-int                     pciio_driver_register(pciio_vendor_id_t, pciio_device_id_t, char *driver_prefix, unsigned);
-
-vertex_hdl_t            pciio_device_register(vertex_hdl_t, vertex_hdl_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t);
-
-void			pciio_device_unregister(vertex_hdl_t);
-pciio_info_t		pciio_device_info_new(pciio_info_t, vertex_hdl_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t);
-void			pciio_device_info_free(pciio_info_t);
-vertex_hdl_t		pciio_device_info_register(vertex_hdl_t, pciio_info_t);
-void			pciio_device_info_unregister(vertex_hdl_t, pciio_info_t);
-int                     pciio_device_attach(vertex_hdl_t, int);
-int			pciio_device_detach(vertex_hdl_t, int);
-void                    pciio_error_register(vertex_hdl_t, error_handler_f *, error_handler_arg_t);
-
-int                     pciio_reset(vertex_hdl_t);
-int                     pciio_write_gather_flush(vertex_hdl_t);
-int                     pciio_slot_inuse(vertex_hdl_t);
-
 /* =====================================================================
  *    Provider Function Location
  *
@@ -239,7 +72,7 @@
 
 #if !defined(DEV_FUNC)
 
-static pciio_provider_t *
+pciio_provider_t *
 pciio_to_provider_fns(vertex_hdl_t dev)
 {
     pciio_info_t            card_info;
@@ -260,13 +93,10 @@
 	}
     }
 
-    if (provider_fns == NULL)
-#if defined(SUPPORT_PRINTING_V_FORMAT)
-	PRINT_PANIC("%v: provider_fns == NULL", dev);
-#else
-	PRINT_PANIC("0x%p: provider_fns == NULL", (void *)dev);
-#endif
-
+    if (provider_fns == NULL) {
+	char devname[MAXDEVNAME];
+	panic("%s: provider_fns == NULL", vertex_to_name(dev, devname, MAXDEVNAME));
+    }
     return provider_fns;
 
 }
@@ -395,8 +225,8 @@
 		     size_t byte_count,	/* Size of mapping */
 		     size_t align)
 {					/* Alignment needed */
-    if (align < NBPP)
-	align = NBPP;
+    if (align < PAGE_SIZE)
+	align = PAGE_SIZE;
     return DEV_FUNC(dev, piospace_alloc)
 	(dev, dev_desc, space, byte_count, align);
 }
@@ -752,50 +582,6 @@
 }
 
 /*
- * Specify endianness constraints.  The driver tells us what the device
- * does and how it would like to see things in memory.  We reply with
- * how things will actually appear in memory.
- */
-pciio_endian_t
-pciio_endian_set(vertex_hdl_t dev,
-		 pciio_endian_t device_end,
-		 pciio_endian_t desired_end)
-{
-    ASSERT((device_end == PCIDMA_ENDIAN_BIG) || (device_end == PCIDMA_ENDIAN_LITTLE));
-    ASSERT((desired_end == PCIDMA_ENDIAN_BIG) || (desired_end == PCIDMA_ENDIAN_LITTLE));
-
-#if DEBUG
-#if defined(SUPPORT_PRINTING_V_FORMAT)
-    printk(KERN_ALERT  "%v: pciio_endian_set is going away.\n"
-	    "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n"
-	    "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n",
-	    dev);
-#else
-    printk(KERN_ALERT  "0x%x: pciio_endian_set is going away.\n"
-	    "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n"
-	    "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n",
-	    dev);
-#endif
-#endif
-
-    return DEV_FUNC(dev, endian_set)
-	(dev, device_end, desired_end);
-}
-
-/*
- * Specify PCI arbitration priority.
- */
-pciio_priority_t
-pciio_priority_set(vertex_hdl_t dev,
-		   pciio_priority_t device_prio)
-{
-    ASSERT((device_prio == PCI_PRIO_HIGH) || (device_prio == PCI_PRIO_LOW));
-
-    return DEV_FUNC(dev, priority_set)
-	(dev, device_prio);
-}
-
-/*
  * Read value of configuration register
  */
 uint64_t
@@ -864,71 +650,6 @@
     return DEV_FUNC(dev, reset) (dev);
 }
 
-/*
- * flush write gather buffers
- */
-int
-pciio_write_gather_flush(vertex_hdl_t dev)
-{
-    return DEV_FUNC(dev, write_gather_flush) (dev);
-}
-
-vertex_hdl_t
-pciio_intr_dev_get(pciio_intr_t pciio_intr)
-{
-    return (pciio_intr->pi_dev);
-}
-
-/****** Generic crosstalk pio interfaces ******/
-vertex_hdl_t
-pciio_pio_dev_get(pciio_piomap_t pciio_piomap)
-{
-    return (pciio_piomap->pp_dev);
-}
-
-pciio_slot_t
-pciio_pio_slot_get(pciio_piomap_t pciio_piomap)
-{
-    return (pciio_piomap->pp_slot);
-}
-
-pciio_space_t
-pciio_pio_space_get(pciio_piomap_t pciio_piomap)
-{
-    return (pciio_piomap->pp_space);
-}
-
-iopaddr_t
-pciio_pio_pciaddr_get(pciio_piomap_t pciio_piomap)
-{
-    return (pciio_piomap->pp_pciaddr);
-}
-
-ulong
-pciio_pio_mapsz_get(pciio_piomap_t pciio_piomap)
-{
-    return (pciio_piomap->pp_mapsz);
-}
-
-caddr_t
-pciio_pio_kvaddr_get(pciio_piomap_t pciio_piomap)
-{
-    return (pciio_piomap->pp_kvaddr);
-}
-
-/****** Generic crosstalk dma interfaces ******/
-vertex_hdl_t
-pciio_dma_dev_get(pciio_dmamap_t pciio_dmamap)
-{
-    return (pciio_dmamap->pd_dev);
-}
-
-pciio_slot_t
-pciio_dma_slot_get(pciio_dmamap_t pciio_dmamap)
-{
-    return (pciio_dmamap->pd_slot);
-}
-
 /****** Generic pci slot information interfaces ******/
 
 pciio_info_t
@@ -987,30 +708,13 @@
     return (pciio_info->c_vertex);
 }
 
+
 pciio_slot_t
 pciio_info_slot_get(pciio_info_t pciio_info)
 {
     return (pciio_info->c_slot);
 }
 
-pciio_function_t
-pciio_info_function_get(pciio_info_t pciio_info)
-{
-    return (pciio_info->c_func);
-}
-
-pciio_vendor_id_t
-pciio_info_vendor_id_get(pciio_info_t pciio_info)
-{
-    return (pciio_info->c_vendor);
-}
-
-pciio_device_id_t
-pciio_info_device_id_get(pciio_info_t pciio_info)
-{
-    return (pciio_info->c_device);
-}
-
 vertex_hdl_t
 pciio_info_master_get(pciio_info_t pciio_info)
 {
@@ -1029,48 +733,6 @@
     return (pciio_info->c_pops);
 }
 
-error_handler_f	       *
-pciio_info_efunc_get(pciio_info_t pciio_info)
-{
-    return (pciio_info->c_efunc);
-}
-
-error_handler_arg_t    *
-pciio_info_einfo_get(pciio_info_t pciio_info)
-{
-    return (pciio_info->c_einfo);
-}
-
-pciio_space_t
-pciio_info_bar_space_get(pciio_info_t info, int win)
-{
-    return info->c_window[win].w_space;
-}
-
-iopaddr_t
-pciio_info_bar_base_get(pciio_info_t info, int win)
-{
-    return info->c_window[win].w_base;
-}
-
-size_t
-pciio_info_bar_size_get(pciio_info_t info, int win)
-{
-    return info->c_window[win].w_size;
-}
-
-iopaddr_t
-pciio_info_rom_base_get(pciio_info_t info)
-{
-    return info->c_rbase;
-}
-
-size_t
-pciio_info_rom_size_get(pciio_info_t info)
-{
-    return info->c_rsize;
-}
-
 
 /* =====================================================================
  *          GENERIC PCI INITIALIZATION FUNCTIONS
@@ -1085,11 +747,8 @@
 pciio_attach(vertex_hdl_t pciio)
 {
 #if DEBUG && ATTACH_DEBUG
-#if defined(SUPPORT_PRINTING_V_FORMAT)
-    printk("%v: pciio_attach\n", pciio);
-#else
-    printk("0x%x: pciio_attach\n", pciio);
-#endif
+    char devname[MAXDEVNAME];
+    printk("%s: pciio_attach\n", vertex_to_name(pciio, devname, MAXDEVNAME));
 #endif
     return 0;
 }
@@ -1127,37 +786,6 @@
     return (pciio_provider_t *) ainfo;
 }
 
-/*ARGSUSED4 */
-int
-pciio_driver_register(
-			 pciio_vendor_id_t vendor_id,
-			 pciio_device_id_t device_id,
-			 char *driver_prefix,
-			 unsigned flags)
-{
-	return(0);
-}
-
-vertex_hdl_t
-pciio_device_register(
-		vertex_hdl_t connectpt,	/* vertex for /hw/.../pciio/%d */
-		vertex_hdl_t master,	/* card's master ASIC (PCI provider) */
-		pciio_slot_t slot,	/* card's slot */
-		pciio_function_t func,	/* card's func */
-		pciio_vendor_id_t vendor_id,
-		pciio_device_id_t device_id)
-{
-    return pciio_device_info_register
-	(connectpt, pciio_device_info_new (NULL, master, slot, func,
-					   vendor_id, device_id));
-}
-
-void
-pciio_device_unregister(vertex_hdl_t pconn)
-{
-    DEV_FUNC(pconn,device_unregister)(pconn);
-}
-
 pciio_info_t
 pciio_device_info_new(
 		pciio_info_t pciio_info,
@@ -1190,7 +818,7 @@
     /* NOTE : pciio_info is a structure within the pcibr_info
      *	      and not a pointer to memory allocated on the heap !!
      */
-    BZERO((char *)pciio_info,sizeof(pciio_info));
+    memset((char *)pciio_info, 0, sizeof(pciio_info));
 }
 
 vertex_hdl_t
@@ -1330,12 +958,22 @@
 	struct resource *new_res;
 	int status = 0;
 
-	new_res = (struct resource *) kmalloc( sizeof(struct resource), KM_NOSLEEP);
+	new_res = (struct resource *) kmalloc( sizeof(struct resource), GFP_KERNEL);
 
-	status = allocate_resource( root_resource, new_res,
+	if (start > 0) {
+		status = allocate_resource( root_resource, new_res,
+			size, start /* Min start addr. */,
+			(start + size) - 1, 1,
+			NULL, NULL);
+	} else {
+		if (size > align)
+			align = size;
+		status = allocate_resource( root_resource, new_res,
 				    size, align /* Min start addr. */,
 				    root_resource->end, align,
 				    NULL, NULL);
+	}
+
 	if (status) {
 		kfree(new_res);
 		return((iopaddr_t) NULL);
@@ -1434,105 +1072,3 @@
 {
 	return(0);
 }
-
-
-/*
- * These are complementary Linux interfaces that takes in a pci_dev * as the 
- * first arguement instead of vertex_hdl_t.
- */
-iopaddr_t               snia_pciio_dmatrans_addr(struct pci_dev *, device_desc_t, paddr_t, size_t, unsigned);
-pciio_dmamap_t          snia_pciio_dmamap_alloc(struct pci_dev *, device_desc_t, size_t, unsigned);
-void                    snia_pciio_dmamap_free(pciio_dmamap_t);
-iopaddr_t               snia_pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t);
-void                    snia_pciio_dmamap_done(pciio_dmamap_t);
-pciio_endian_t          snia_pciio_endian_set(struct pci_dev *pci_dev, pciio_endian_t device_end,
-					      pciio_endian_t desired_end);
-
-#include <linux/module.h>
-EXPORT_SYMBOL(snia_pciio_dmatrans_addr);
-EXPORT_SYMBOL(snia_pciio_dmamap_alloc);
-EXPORT_SYMBOL(snia_pciio_dmamap_free);
-EXPORT_SYMBOL(snia_pciio_dmamap_addr);
-EXPORT_SYMBOL(snia_pciio_dmamap_done);
-EXPORT_SYMBOL(snia_pciio_endian_set);
-
-int
-snia_pcibr_rrb_alloc(struct pci_dev *pci_dev,
-	int *count_vchan0,
-	int *count_vchan1)
-{
-	vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev);
-
-	return pcibr_rrb_alloc(dev, count_vchan0, count_vchan1);
-}
-EXPORT_SYMBOL(snia_pcibr_rrb_alloc);
-
-pciio_endian_t
-snia_pciio_endian_set(struct pci_dev *pci_dev,
-	pciio_endian_t device_end,
-	pciio_endian_t desired_end)
-{
-	vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev);
-	
-	return DEV_FUNC(dev, endian_set)
-		(dev, device_end, desired_end);
-}
-
-iopaddr_t
-snia_pciio_dmatrans_addr(struct pci_dev *pci_dev, /* translate for this device */
-                    device_desc_t dev_desc,     /* device descriptor */
-                    paddr_t paddr,      /* system physical address */
-                    size_t byte_count,  /* length */
-                    unsigned flags)
-{                                       /* defined in dma.h */
-
-    vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev);
-
-    /*
-     * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be 
-     * set.  Otherwise, it must not be set.  This applies to SN1 and SN2.
-     */
-    return DEV_FUNC(dev, dmatrans_addr)
-        (dev, dev_desc, paddr, byte_count, (IS_PIC_DEVICE(pci_dev)) ? (flags & ~PCIIO_BYTE_STREAM) : flags | PCIIO_BYTE_STREAM);
-}
-
-pciio_dmamap_t
-snia_pciio_dmamap_alloc(struct pci_dev *pci_dev,  /* set up mappings for this device */
-                   device_desc_t dev_desc,      /* device descriptor */
-                   size_t byte_count_max,       /* max size of a mapping */
-                   unsigned flags)
-{                                       /* defined in dma.h */
-
-    vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev);
-
-    /*
-     * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be
-     * set.  Otherwise, it must not be set.  This applies to SN1 and SN2.
-     */
-    return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
-        (dev, dev_desc, byte_count_max, (IS_PIC_DEVICE(pci_dev)) ? (flags & ~PCIIO_BYTE_STREAM) : flags | PCIIO_BYTE_STREAM);
-}
-
-void
-snia_pciio_dmamap_free(pciio_dmamap_t pciio_dmamap)
-{
-    DMAMAP_FUNC(pciio_dmamap, dmamap_free)
-        (CAST_DMAMAP(pciio_dmamap));
-}
-
-iopaddr_t
-snia_pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap,  /* use these mapping resources */
-                  paddr_t paddr,        /* map for this address */
-                  size_t byte_count)
-{                                       /* map this many bytes */
-    return DMAMAP_FUNC(pciio_dmamap, dmamap_addr)
-        (CAST_DMAMAP(pciio_dmamap), paddr, byte_count);
-}
-
-void
-snia_pciio_dmamap_done(pciio_dmamap_t pciio_dmamap)
-{
-    DMAMAP_FUNC(pciio_dmamap, dmamap_done)
-        (CAST_DMAMAP(pciio_dmamap));
-}
-
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pic.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pic.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/pic.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/pic.c	2003-09-12 12:44:35.000000000 -0700
@@ -17,6 +17,7 @@
 #include <asm/sn/iograph.h>
 #include <asm/sn/invent.h>
 #include <asm/sn/hcl.h>
+#include <asm/sn/hcl_util.h>
 #include <asm/sn/labelcl.h>
 #include <asm/sn/xtalk/xwidget.h>
 #include <asm/sn/pci/bridge.h>
@@ -130,7 +131,7 @@
 	char pathname[256], peer_path[256], tmpbuf[256];
 	char *p;
 	int rc;
-	vertex_hdl_t peer_conn_v;
+	vertex_hdl_t peer_conn_v, hubv;
 	int pos;
 	slabid_t slab;
 
@@ -139,7 +140,7 @@
 		/* pcibr widget hw/module/001c11/slab/0/Pbrick/xtalk/12 */
 		/* sprintf(pathname, "%v", conn_v); */
 		xbow_peer = NASID_TO_COMPACT_NODEID(NODEPDA(cnode)->xbow_peer);
-		pos = hwgfs_generate_path(conn_v, tmpbuf, 256);
+		pos = hwgraph_generate_path(conn_v, tmpbuf, 256);
 		strcpy(pathname, &tmpbuf[pos]);
 		p = pathname + strlen("hw/module/001c01/slab/0/");
 
@@ -183,6 +184,11 @@
 			    if (!pic_bus1_widget_info_dup(conn_v, peer_conn_v, xbow_peer))
 					return 0;
 
+			    hubv = cnodeid_to_vertex(xbow_peer);
+			    ASSERT(hubv != GRAPH_VERTEX_NONE);
+			    device_master_set(peer_conn_v, hubv);
+			    xtalk_provider_register(hubv, &hub_provider);
+			    xtalk_provider_startup(hubv);
 			    return peer_conn_v;
 			}
 		}
@@ -199,6 +205,9 @@
 	vertex_hdl_t	pcibr_vhdl0, pcibr_vhdl1 = (vertex_hdl_t)0;
 	pcibr_soft_t	bus0_soft, bus1_soft = (pcibr_soft_t)0;
 	vertex_hdl_t  conn_v0, conn_v1, peer_conn_v;
+	int             brick_type;
+	int             iobrick_type_get_nasid(nasid_t nasid);
+
 
 	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach()\n"));
 
@@ -228,10 +237,19 @@
 	 * the Bridge registers themselves.
 	 */
 	/* FIXME: what should the hwgraph path look like ? */
-	rc = hwgraph_path_add(conn_v0, EDGE_LBL_PCIX_0, &pcibr_vhdl0);
-	ASSERT(rc == GRAPH_SUCCESS);
-	rc = hwgraph_path_add(conn_v1, EDGE_LBL_PCIX_1, &pcibr_vhdl1);
-	ASSERT(rc == GRAPH_SUCCESS);
+	brick_type = iobrick_type_get_nasid(NASID_GET(bridge0));
+	if ( brick_type == MODULE_CGBRICK ) {
+		rc = hwgraph_path_add(conn_v0, EDGE_LBL_AGP_0, &pcibr_vhdl0);
+		ASSERT(rc == GRAPH_SUCCESS);
+		rc = hwgraph_path_add(conn_v1, EDGE_LBL_AGP_1, &pcibr_vhdl1);
+		ASSERT(rc == GRAPH_SUCCESS);
+	}
+	else {
+		rc = hwgraph_path_add(conn_v0, EDGE_LBL_PCIX_0, &pcibr_vhdl0);
+		ASSERT(rc == GRAPH_SUCCESS);
+		rc = hwgraph_path_add(conn_v1, EDGE_LBL_PCIX_1, &pcibr_vhdl1);
+		ASSERT(rc == GRAPH_SUCCESS);
+	}
 
 	PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
 		    "pic_attach: pcibr_vhdl0=%v, pcibr_vhdl1=%v\n",
@@ -292,9 +310,7 @@
     (pciio_provider_startup_f *) pcibr_provider_startup,
     (pciio_provider_shutdown_f *) pcibr_provider_shutdown,
     (pciio_reset_f *) pcibr_reset,
-    (pciio_write_gather_flush_f *) pcibr_write_gather_flush,
     (pciio_endian_set_f *) pcibr_endian_set,
-    (pciio_priority_set_f *) pcibr_priority_set,
     (pciio_config_get_f *) pcibr_config_get,
     (pciio_config_set_f *) pcibr_config_set,
     (pciio_error_devenable_f *) 0,
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/shub.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/shub.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/shub.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/shub.c	2003-09-12 12:44:35.000000000 -0700
@@ -17,6 +17,7 @@
 #include <asm/hw_irq.h>
 #include <asm/system.h>
 #include <asm/sn/sgi.h>
+#include <asm/uaccess.h>
 #include <asm/sn/iograph.h>
 #include <asm/sn/invent.h>
 #include <asm/sn/hcl.h>
@@ -35,44 +36,18 @@
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sndrv.h>
 
-/*
- * Shub WAR for Xbridge Little Endian problem:
- *	Xbridge has to run in BIG ENDIAN even with Shub.
- */
-
-
-/*
- * io_sh_swapper: Turn on Shub byte swapping.
- *	All data destined to and from Shub to XIO are byte-swapped.
- */
-void
-io_sh_swapper(nasid_t nasid, int onoff)
-{
-    ii_iwc_u_t      ii_iwc;
-
-    ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);
-
-    ii_iwc.ii_iwc_fld_s.i_dma_byte_swap = onoff;
-    REMOTE_HUB_S(nasid, IIO_IWC, ii_iwc.ii_iwc_regval);
-    ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);
-
-}
+#define SHUB_NUM_ECF_REGISTERS 8
 
 /*
- * io_get_sh_swapper: Return current Swap mode.
- *	1 = Swap on, 0 = Swap off.
+ * A backport of the 2.5 scheduler is used by many vendors of 2.4-based
+ * distributions.
+ * We can only guess its presence by the lack of the SCHED_YIELD flag.
+ * If the heuristic doesn't work, change this define by hand.
  */
-int
-io_get_sh_swapper(nasid_t nasid)
-{
-    ii_iwc_u_t      ii_iwc;
-
-    ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC);
-    return(ii_iwc.ii_iwc_fld_s.i_dma_byte_swap);
-
-}
+#ifndef SCHED_YIELD
+#define __HAVE_NEW_SCHEDULER    1
+#endif
 
-#define SHUB_NUM_ECF_REGISTERS 8
 
 static uint32_t	shub_perf_counts[SHUB_NUM_ECF_REGISTERS];
 
@@ -206,7 +181,7 @@
 #else
         cnode = (cnodeid_t)file->private_data;
 #endif
-        if (!cnode)
+        if (cnode < 0 || cnode >= numnodes)
                 return -ENODEV;
 
         switch (cmd) {
@@ -316,7 +291,12 @@
 	struct task_struct  *tsk = current;
 
 	daemonize();
+
+#ifdef __HAVE_NEW_SCHEDULER
 	set_user_nice(tsk, 19);
+#else
+	tsk->nice = 19;
+#endif
 	sigfillset(&tsk->blocked);
 	strcpy(tsk->comm, "linkstatd");
 
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/shub_intr.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/shub_intr.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/shub_intr.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/shub_intr.c	2003-09-12 12:44:35.000000000 -0700
@@ -27,6 +27,9 @@
 #include <asm/sn/klconfig.h>
 #include <asm/sn/sn2/shub_mmr.h>
 #include <asm/sn/sn_cpuid.h>
+#include <asm/sn/pci/pcibr.h>
+#include <asm/sn/pci/pcibr_private.h>
+#include <asm/sn/pci/bridge.h>
 
 /* ARGSUSED */
 void
@@ -37,11 +40,15 @@
 xwidgetnum_t
 hub_widget_id(nasid_t nasid)
 {
-        hubii_wcr_t     ii_wcr; /* the control status register */
-        
-        ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid,IIO_WCR);
-        
-        return ii_wcr.wcr_fields_s.wcr_widget_id;
+
+	if (!(nasid & 1)) {
+        	hubii_wcr_t     ii_wcr; /* the control status register */
+        	ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid,IIO_WCR);
+        	return ii_wcr.wcr_fields_s.wcr_widget_id;
+	} else {
+		/* ICE does not have widget id. */
+		return(-1);
+	}
 }
 
 static hub_intr_t
@@ -79,7 +86,7 @@
 		xtalk_addr = SH_II_INT0 | ((unsigned long)nasid << 36) | (1UL << 47);
 	}
 
-	intr_hdl = snia_kmem_alloc_node(sizeof(struct hub_intr_s), KM_NOSLEEP, cnode);
+	intr_hdl = snia_kmem_alloc_node(sizeof(struct hub_intr_s), cnode);
 	ASSERT_ALWAYS(intr_hdl);
 
 	xtalk_info = &intr_hdl->i_xtalk_info;
@@ -188,3 +195,57 @@
 	ASSERT(rv == 0);
 	intr_hdl->i_flags &= ~HUB_INTR_IS_CONNECTED;
 }
+
+/* 
+ * Redirect an interrupt to another cpu.
+ */
+
+void
+sn_shub_redirect_intr(pcibr_intr_t intr, unsigned long cpu) {
+	unsigned long bit;
+	int cpuphys, slice;
+	nasid_t nasid;
+	unsigned long xtalk_addr;
+	bridge_t	*bridge = intr->bi_soft->bs_base;
+	picreg_t	int_enable;
+	picreg_t	host_addr;
+	int		irq;
+
+	cpuphys = cpu_physical_id(cpu);
+	slice = cpu_physical_id_to_slice(cpuphys);
+	nasid = cpu_physical_id_to_nasid(cpuphys);
+
+	if (slice) {    
+		xtalk_addr = SH_II_INT1 | ((unsigned long)nasid << 36) | (1UL << 47);
+	} else {
+		xtalk_addr = SH_II_INT0 | ((unsigned long)nasid << 36) | (1UL << 47);
+	}
+
+	for (bit = 0; bit < 8; bit++) {
+		if (intr->bi_ibits & (1 << bit) ) {
+			/* Disable interrupts. */
+			int_enable = bridge->p_int_enable_64;
+			int_enable &= ~bit;
+			bridge->p_int_enable_64 = int_enable;
+			/* Reset Host address (Interrupt destination) */
+			host_addr = bridge->p_int_addr_64[bit];
+			host_addr &= ~((1UL << 48) - 1);
+			host_addr |= xtalk_addr;
+			bridge->p_int_addr_64[bit] = host_addr;
+			/* Enable interrupt */
+			int_enable |= bit;
+			bridge->p_int_enable_64 = int_enable;
+			/* Force an interrupt, just in case. */
+			bridge->b_force_pin[bit].intr = 1;
+		}
+	}
+	irq = intr->bi_irq;
+	if (pdacpu(cpu).sn_first_irq == 0 || pdacpu(cpu).sn_first_irq > irq) {
+		pdacpu(cpu).sn_first_irq = irq;
+	}
+	if (pdacpu(cpu).sn_last_irq < irq) {
+		pdacpu(cpu).sn_last_irq = irq;
+	}
+	intr->bi_cpu = (int)cpu;
+}
+
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/shuberror.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/shuberror.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/shuberror.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/shuberror.c	2003-09-12 12:44:35.000000000 -0700
@@ -14,6 +14,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/smp.h>
+#include <asm/delay.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/io.h>
 #include <asm/sn/iograph.h>
@@ -52,7 +53,6 @@
 hub_error_clear(nasid_t nasid)
 {
 	int i;
-	hubreg_t idsr;
 
     /*
      * Make sure spurious write response errors are cleared
@@ -299,7 +299,7 @@
 	* Wait till hub indicates it's done.
 	*/
 	while (REMOTE_HUB_L(hinfo->h_nasid, IIO_ICDR) & IIO_ICDR_PND)
-		us_delay(1);
+		udelay(1);
 
 }
 
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/shubio.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/shubio.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/shubio.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/shubio.c	2003-09-12 12:44:35.000000000 -0700
@@ -310,8 +310,7 @@
 			if (!is_widget_pio_enabled(ioerror)) {
 				if (error_state_get(hub_v) == 
 				    ERROR_STATE_ACTION)
-					ioerror_dump("No outbound widget"
-						     " access - ", 
+					snia_ioerror_dump("No outbound widget access - ", 
 						     error_code, mode, ioerror);
 				return(IOERROR_HANDLED);
 			}
@@ -352,8 +351,7 @@
 			if (!is_widget_pio_enabled(ioerror)) {
 				if (error_state_get(hub_v) == 
 				    ERROR_STATE_ACTION)
-					ioerror_dump("No outbound widget"
-						     " access - ", 
+					snia_ioerror_dump("No outbound widget access - ", 
 						     error_code, mode, ioerror);
 				return(IOERROR_HANDLED);
 			}
@@ -478,7 +476,7 @@
 error_state_set(vertex_hdl_t v,error_state_t new_state)
 {
         error_state_t   old_state;
-        boolean_t       replace = B_TRUE;
+        int       replace = 1;
 
         /* Check if we have a valid hwgraph vertex */
         if ( v == (vertex_hdl_t)0 )
@@ -497,7 +495,7 @@
          * for this vertex.
          */
         if (v_error_state_get(v,old_state) != GRAPH_SUCCESS)
-                replace = B_FALSE;
+                replace = 0;
 
         if (v_error_state_set(v,new_state,replace) != GRAPH_SUCCESS) {
                 return(ERROR_RETURN_CODE_CANNOT_SET_STATE);
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/xbow.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/xbow.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/xbow.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/xbow.c	2003-09-12 12:44:35.000000000 -0700
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <asm/sn/sgi.h>
+#include <asm/delay.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn2/sn_private.h>
 #include <asm/sn/sn2/shubio.h>
@@ -28,6 +29,8 @@
 /* #define XBOW_DEBUG	1 */
 /* #define DEBUG_ERROR	1 */
 
+#define kdebug 0
+
 
 /*
  * Files needed to get the device driver entry points
@@ -311,12 +314,12 @@
 #endif /* XBRIDGE_REGS_SIM */
     rev = XWIDGET_PART_REV_NUM(id);
 
-    mutex_spinlock_init(&soft->xbow_perf_lock);
+    spin_lock_init(&soft->xbow_perf_lock);
     soft->xbow_perfcnt[0].xp_perf_reg = &xbow->xb_perf_ctr_a;
     soft->xbow_perfcnt[1].xp_perf_reg = &xbow->xb_perf_ctr_b;
 
     /* Initialization for GBR bw allocation */
-    mutex_spinlock_init(&soft->xbow_bw_alloc_lock);
+    spin_lock_init(&soft->xbow_bw_alloc_lock);
 
 #define	XBOW_8_BIT_PORT_BW_MAX		(400 * 1000 * 1000)	/* 400 MB/s */
 #define XBOW_16_BIT_PORT_BW_MAX		(800 * 1000 * 1000)	/* 800 MB/s */
@@ -419,43 +422,6 @@
     return 0;				/* attach successful */
 }
 
-/* This contains special-case code for grio. There are plans to make
- * this general sometime in the future, but till then this should
- * be good enough.
- */
-xwidgetnum_t
-xbow_widget_num_get(vertex_hdl_t dev)
-{
-	vertex_hdl_t	tdev;
-	char		devname[MAXDEVNAME];
-	xwidget_info_t	xwidget_info;
-	int		i;
-
-	vertex_to_name(dev, devname, MAXDEVNAME);
-
-	/* If this is a pci controller vertex, traverse up using
-	 * the ".." links to get to the widget.
-	 */
-	if (strstr(devname, EDGE_LBL_PCI) &&
-			strstr(devname, EDGE_LBL_CONTROLLER)) {
-		tdev = dev;
-		for (i=0; i< 2; i++) {
-			if (hwgraph_edge_get(tdev,
-				HWGRAPH_EDGELBL_DOTDOT, &tdev) !=
-					GRAPH_SUCCESS)
-				return XWIDGET_NONE;
-		}
-
-		if ((xwidget_info = xwidget_info_chk(tdev)) != NULL) {
-			return (xwidget_info_id_get(xwidget_info));
-		} else {
-			return XWIDGET_NONE;
-		}
-	}
-
-	return XWIDGET_NONE;
-}
-
 /*
  * xbow_widget_present: See if a device is present
  * on the specified port of this crossbow.
@@ -477,6 +443,10 @@
 					IS_PIC_XBOW(xbow->xb_wid_id) && port==0xf) {
 			return 1;
 		}
+		else if ( IS_PIC_XBOW(xbow->xb_wid_id) && port==0xb ) {
+			/* for opus the present bit doesn't work on port 0xb */
+			return 1;
+		}
 		return xbow->xb_link(port).link_aux_status & XB_AUX_STAT_PRESENT;
 	}
 }
@@ -805,7 +775,7 @@
 	XEM_ADD_VAR(wid_err_upper);
 	XEM_ADD_VAR(wid_err_lower);
 	XEM_ADD_VAR(wid_err_addr);
-	PRINT_PANIC("XIO Bus Error");
+	panic("XIO Bus Error");
     }
 }
 
@@ -958,8 +928,9 @@
     if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) &&
 		IS_PIC_XBOW(xbow->xb_wid_id) && (port==0xf))
 		;
-    else
-    if (!(link_aux_status & XB_AUX_STAT_PRESENT)) {
+    else if (IS_PIC_XBOW(xbow->xb_wid_id) && (port==0xb))
+		;	/* WAR for opus this is missing on 0xb */
+    else if (!(link_aux_status & XB_AUX_STAT_PRESENT)) {
 	/* nobody connected. */
 	if (mode == MODE_DEVPROBE)
 	    return IOERROR_HANDLED;
@@ -1094,14 +1065,13 @@
     xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;
     xbow_perf_link_t       *xbow_plink = xbow_soft->xbow_perflink;
     xbow_perfcount_t        perf_reg;
-    unsigned long           s;
     int                     link, i;
 
     for (i = 0; i < XBOW_PERF_COUNTERS; i++, xbow_perf++) {
 	if (xbow_perf->xp_mode == XBOW_MONITOR_NONE)
 	    continue;
 
-	s = mutex_spinlock(&xbow_soft->xbow_perf_lock);
+	spin_lock(&xbow_soft->xbow_perf_lock);
 
 	perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;
 
@@ -1111,7 +1081,7 @@
 	    ((perf_reg.xb_perf.count - xbow_perf->xp_current) & XBOW_COUNTER_MASK);
 	xbow_perf->xp_current = perf_reg.xb_perf.count;
 
-	mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
+	spin_unlock(&xbow_soft->xbow_perf_lock);
     }
 }
 
@@ -1132,7 +1102,6 @@
     xbow_linkctrl_t         xbow_link_ctrl;
     xbow_t                 *xbow = xbow_soft->base;
     xbow_perfcount_t        perf_reg;
-    unsigned long           s;
     int                     i;
 
     link -= BASE_XBOW_PORT;
@@ -1145,10 +1114,10 @@
     if ((counter < 0) || (counter >= XBOW_PERF_COUNTERS))
 	return -1;
 
-    s = mutex_spinlock(&xbow_soft->xbow_perf_lock);
+    spin_lock(&xbow_soft->xbow_perf_lock);
 
     if ((xbow_perf + counter)->xp_mode && mode) {
-	mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
+	spin_unlock(&xbow_soft->xbow_perf_lock);
 	return -1;
     }
     for (i = 0; i < XBOW_PERF_COUNTERS; i++) {
@@ -1156,7 +1125,7 @@
 	    continue;
 	if (((xbow_perf + i)->xp_link == link) &&
 	    ((xbow_perf + i)->xp_mode)) {
-	    mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
+	    spin_unlock(&xbow_soft->xbow_perf_lock);
 	    return -1;
 	}
     }
@@ -1174,7 +1143,7 @@
     *(xbowreg_t *) xbow_perf->xp_perf_reg = perf_reg.xb_counter_val;
     xbow_perf->xp_current = perf_reg.xb_perf.count;
 
-    mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
+    spin_unlock(&xbow_soft->xbow_perf_lock);
     return 0;
 }
 
@@ -1262,15 +1231,10 @@
     xbow_t                 *xbow;
     xbowreg_t               ctrl;
     xbwX_stat_t             stat;
-    unsigned                itick;
+    unsigned                long itick;
     unsigned                dtick;
-    static int              ticks_per_ms = 0;
+    static long             ticks_to_wait = HZ / 1000;
 
-    if (!ticks_per_ms) {
-	itick = get_timestamp();
-	us_delay(1000);
-	ticks_per_ms = get_timestamp() - itick;
-    }
     widget_info = xwidget_info_get(xconn_vhdl);
     port = xwidget_info_id_get(widget_info);
 
@@ -1296,16 +1260,16 @@
      */
     ctrl = xbow->xb_link(port).link_control;
     xbow->xb_link(port).link_reset = 0;
-    itick = get_timestamp();
+    itick = jiffies;
     while (1) {
 	stat.linkstatus = xbow->xb_link(port).link_status;
 	if (stat.link_alive)
 	    break;
-	dtick = get_timestamp() - itick;
-	if (dtick > ticks_per_ms) {
+	dtick = jiffies - itick;
+	if (dtick > ticks_to_wait) {
 	    return -1;			/* never came out of reset */
 	}
-	DELAY(2);			/* don't beat on link_status */
+	udelay(2);			/* don't beat on link_status */
     }
     xbow->xb_link(port).link_control = ctrl;
     return 0;
@@ -1379,7 +1343,6 @@
     xbow_soft_t             soft = xbow_soft_get(vhdl);
     volatile xbowreg_t     *xreg;
     xbowreg_t               mask;
-    unsigned long           s;
     int                     error = 0;
     bandwidth_t             old_bw_BYTES, req_bw_BYTES;
     xbowreg_t               old_xreg;
@@ -1393,7 +1356,7 @@
     ASSERT(XBOW_WIDGET_IS_VALID(src_wid));
     ASSERT(XBOW_WIDGET_IS_VALID(dest_wid));
 
-    s = mutex_spinlock(&soft->xbow_bw_alloc_lock);
+    spin_lock(&soft->xbow_bw_alloc_lock);
 
     /* Get pointer to the correct register */
     xreg = XBOW_PRIO_ARBREG_PTR(soft->base, dest_wid, src_wid);
@@ -1444,7 +1407,7 @@
 	error = 1;
     }
 
-    mutex_spinunlock(&soft->xbow_bw_alloc_lock, s);
+    spin_unlock(&soft->xbow_bw_alloc_lock);
 
     return (error);
 }
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/sn2/xtalk.c linux-2.4.23-pre4/arch/ia64/sn/io/sn2/xtalk.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/sn2/xtalk.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/io/sn2/xtalk.c	2003-09-12 12:44:35.000000000 -0700
@@ -310,7 +310,7 @@
 			       unsigned flags)
 {
 #if DEBUG
-    PRINT_PANIC("null_xtalk_early_piotrans_addr");
+    panic("null_xtalk_early_piotrans_addr");
 #endif
     return NULL;
 }
@@ -553,7 +553,7 @@
 #else
     printk(KERN_WARNING "Xbow at 0x%p encountered Fatal error", (void *)xconn);
 #endif
-    ioerror_dump("xtalk", error_code, mode, ioerror);
+    snia_ioerror_dump("xtalk", error_code, mode, ioerror);
 
     return IOERROR_UNHANDLED;
 }
@@ -921,7 +921,7 @@
 
     /* Clean out the xwidget information */
     (void)kfree(widget_info->w_name);
-    BZERO((void *)widget_info, sizeof(widget_info));
+    memset((void *)widget_info, 0, sizeof(widget_info));
     DEL(widget_info);
     
     return(0);
diff -urN linux-2.4.23-pre3/arch/ia64/sn/io/snia_if.c linux-2.4.23-pre4/arch/ia64/sn/io/snia_if.c
--- linux-2.4.23-pre3/arch/ia64/sn/io/snia_if.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/sn/io/snia_if.c	2003-09-12 12:44:35.000000000 -0700
@@ -0,0 +1,246 @@
+/* $Id$
+ *
+ * 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.
+ *
+ * Copyright (C) 2003 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <asm/sn/sgi.h>
+#include <asm/sn/xtalk/xbow.h>	/* Must be before iograph.h to get MAX_PORT_NUM */
+#include <asm/sn/iograph.h>
+#include <asm/sn/invent.h>
+#include <asm/sn/hcl.h>
+#include <asm/sn/hcl_util.h>
+#include <asm/sn/labelcl.h>
+#include <asm/sn/pci/bridge.h>
+#include <asm/sn/ioerror_handling.h>
+#include <asm/sn/pci/pciio.h>
+#include <asm/sn/pci/pciio_private.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/io.h>
+#include <asm/sn/pci/pci_bus_cvlink.h>
+#include <asm/sn/simulator.h>
+
+#if !defined(DEV_FUNC)
+extern pciio_provider_t *pciio_to_provider_fns(vertex_hdl_t dev);
+#define DEV_FUNC(dev,func)	pciio_to_provider_fns(dev)->func
+#define CAST_PIOMAP(x)		((pciio_piomap_t)(x))
+#define CAST_DMAMAP(x)		((pciio_dmamap_t)(x))
+#define CAST_INTR(x)		((pciio_intr_t)(x))
+#endif
+
+/*
+ * Many functions are not passed their vertex
+ * information directly; rather, they must
+ * dive through a resource map. These macros
+ * are available to coordinate this detail.
+ */
+#define PIOMAP_FUNC(map,func)		DEV_FUNC((map)->pp_dev,func)
+#define DMAMAP_FUNC(map,func)		DEV_FUNC((map)->pd_dev,func)
+#define INTR_FUNC(intr_hdl,func)	DEV_FUNC((intr_hdl)->pi_dev,func)
+
+int
+snia_badaddr_val(volatile void *addr, int len, volatile void *ptr)
+{
+	int ret = 0;
+	volatile void *new_addr;
+
+	switch (len) {
+		case 4:
+			new_addr = (void *) addr;
+			ret = ia64_sn_probe_io_slot((long)new_addr, len, (void *)ptr);
+			break;
+		default:
+			printk(KERN_WARNING "badaddr_val given len %x but supports len of 4 only\n", len);
+	}
+
+	if (ret < 0)
+		panic("badaddr_val: unexpected status (%d) in probing", ret);
+	return(ret);
+
+}
+
+
+nasid_t
+snia_get_console_nasid(void)
+{
+	extern nasid_t console_nasid;
+	extern nasid_t master_baseio_nasid;
+
+	if (console_nasid < 0) {
+		console_nasid = ia64_sn_get_console_nasid();
+		if (console_nasid < 0) {
+// ZZZ What do we do if we don't get a console nasid on the hardware????
+			if (IS_RUNNING_ON_SIMULATOR() )
+				console_nasid = master_baseio_nasid;
+		}
+	} 
+	return console_nasid;
+}
+
+nasid_t
+snia_get_master_baseio_nasid(void)
+{
+	extern nasid_t master_baseio_nasid;
+	extern char master_baseio_wid;
+
+	if (master_baseio_nasid < 0) {
+		master_baseio_nasid = ia64_sn_get_master_baseio_nasid();
+
+		if ( master_baseio_nasid >= 0 ) {
+        		master_baseio_wid = WIDGETID_GET(KL_CONFIG_CH_CONS_INFO(master_baseio_nasid)->memory_base);
+		}
+	} 
+	return master_baseio_nasid;
+}
+
+
+void
+snia_ioerror_dump(char *name, int error_code, int error_mode, ioerror_t *ioerror)
+{
+#ifdef	LATER
+	/* This needs to be tested */
+
+	static char *error_mode_string[] =
+		{ "probe", "kernel", "user", "reenable" };
+
+	printk("%s%s%s%s%s error in %s mode\n",
+               name,
+               (error_code & IOECODE_PIO) ? " PIO" : "",
+               (error_code & IOECODE_DMA) ? " DMA" : "",
+               (error_code & IOECODE_READ) ? " Read" : "",
+               (error_code & IOECODE_WRITE) ? " Write" : "",
+               error_mode_string[error_mode]);
+
+#define PRFIELD(f)                                  \
+        if (IOERROR_FIELDVALID(ioerror,f)) {        \
+		int tmp;                            \
+		IOERROR_GETVALUE(tmp, ioerror, f);  \
+                printk("\t%20s: 0x%x\n", #f, tmp);  \
+	}
+
+        PRFIELD(errortype);             /* error type: extra info about error */
+        PRFIELD(widgetnum);             /* Widget number that's in error */
+        PRFIELD(widgetdev);             /* Device within widget in error */
+        PRFIELD(srccpu);                /* CPU on srcnode generating error */
+        PRFIELD(srcnode);               /* Node which caused the error   */
+        PRFIELD(errnode);               /* Node where error was noticed  */
+        PRFIELD(sysioaddr);             /* Sys specific IO address       */
+        PRFIELD(xtalkaddr);             /* Xtalk (48bit) addr of Error   */
+        PRFIELD(busspace);              /* Bus specific address space    */
+        PRFIELD(busaddr);               /* Bus specific address          */
+        PRFIELD(vaddr);                 /* Virtual address of error      */
+        PRFIELD(memaddr);               /* Physical memory address       */
+        PRFIELD(epc);                   /* pc when error reported        */
+        PRFIELD(ef);                    /* eframe when error reported    */
+
+#undef  PRFIELD
+
+        {
+                /* Print a more descriptive CPU string */
+                cpuid_t srccpu;
+		IOERROR_GETVALUE(srccpu, ioerror, srccpu);
+		// smp_processor_id()
+                printk("(NOTE: CPU %d)\n", srccpu);
+                printk("\n");
+        }
+#endif	/* LATER */
+}
+
+
+int
+snia_pcibr_rrb_alloc(struct pci_dev *pci_dev,
+	int *count_vchan0,
+	int *count_vchan1)
+{
+	vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev);
+
+	return pcibr_rrb_alloc(dev, count_vchan0, count_vchan1);
+}
+
+pciio_endian_t
+snia_pciio_endian_set(struct pci_dev *pci_dev,
+	pciio_endian_t device_end,
+	pciio_endian_t desired_end)
+{
+	vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev);
+	
+	return DEV_FUNC(dev, endian_set)
+		(dev, device_end, desired_end);
+}
+
+iopaddr_t
+snia_pciio_dmatrans_addr(struct pci_dev *pci_dev, /* translate for this device */
+                    device_desc_t dev_desc,     /* device descriptor */
+                    paddr_t paddr,      /* system physical address */
+                    size_t byte_count,  /* length */
+                    unsigned flags)
+{                                       /* defined in dma.h */
+
+    vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev);
+
+    /*
+     * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be 
+     * set.  Otherwise, it must not be set.  This applies to SN1 and SN2.
+     */
+    return DEV_FUNC(dev, dmatrans_addr)
+        (dev, dev_desc, paddr, byte_count, flags & ~PCIIO_BYTE_STREAM);
+}
+
+pciio_dmamap_t
+snia_pciio_dmamap_alloc(struct pci_dev *pci_dev,  /* set up mappings for this device */
+                   device_desc_t dev_desc,      /* device descriptor */
+                   size_t byte_count_max,       /* max size of a mapping */
+                   unsigned flags)
+{                                       /* defined in dma.h */
+
+    vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev);
+
+    /*
+     * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be
+     * set.  Otherwise, it must not be set.  This applies to SN1 and SN2.
+     */
+    return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
+        (dev, dev_desc, byte_count_max, flags & ~PCIIO_BYTE_STREAM);
+}
+
+void
+snia_pciio_dmamap_free(pciio_dmamap_t pciio_dmamap)
+{
+    DMAMAP_FUNC(pciio_dmamap, dmamap_free)
+        (CAST_DMAMAP(pciio_dmamap));
+}
+
+iopaddr_t
+snia_pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap,  /* use these mapping resources */
+                  paddr_t paddr,        /* map for this address */
+                  size_t byte_count)
+{                                       /* map this many bytes */
+    return DMAMAP_FUNC(pciio_dmamap, dmamap_addr)
+        (CAST_DMAMAP(pciio_dmamap), paddr, byte_count);
+}
+
+void
+snia_pciio_dmamap_done(pciio_dmamap_t pciio_dmamap)
+{
+    DMAMAP_FUNC(pciio_dmamap, dmamap_done)
+        (CAST_DMAMAP(pciio_dmamap));
+}
+
+#include <linux/module.h>
+EXPORT_SYMBOL(snia_pciio_dmatrans_addr);
+EXPORT_SYMBOL(snia_pciio_dmamap_alloc);
+EXPORT_SYMBOL(snia_pciio_dmamap_free);
+EXPORT_SYMBOL(snia_pciio_dmamap_addr);
+EXPORT_SYMBOL(snia_pciio_dmamap_done);
+EXPORT_SYMBOL(snia_pciio_endian_set);
+EXPORT_SYMBOL(snia_pcibr_rrb_alloc);
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/Makefile linux-2.4.23-pre4/arch/ia64/sn/kernel/Makefile
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/Makefile	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/Makefile	2003-09-12 12:44:35.000000000 -0700
@@ -44,9 +44,8 @@
 
 subdir-y			= sn2
 
-obj-y				= probe.o setup.o sv.o bte.o
-obj-y			        += irq.o mca.o idle.o
-obj-y			        += sn2/sn2.o
+obj-y				= bte.o idle.o irq.o mca.o probe.o setup.o \
+				  sn_ivt.o sn2/sn2.o sv.o
 
 obj-$(CONFIG_IA64_GENERIC)      += machvec.o
 obj-$(CONFIG_MODULES)           += sn_ksyms.o
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/bte.c linux-2.4.23-pre4/arch/ia64/sn/kernel/bte.c
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/bte.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/bte.c	2003-09-12 12:44:35.000000000 -0700
@@ -156,8 +156,8 @@
 
 	/* Set the notification register */
 	BTE_PRINTKV(("IBNA - HUB_S(0x%p, 0x%lx)\n", BTEREG_NOTIF_ADDR,
-		     (TO_PHYS(__tpa(bte->most_rcnt_na)))));
-	HUB_S(BTEREG_NOTIF_ADDR, (TO_PHYS(__tpa(bte->most_rcnt_na))));
+		     (TO_PHYS(ia64_tpa(bte->most_rcnt_na)))));
+	HUB_S(BTEREG_NOTIF_ADDR, (TO_PHYS(ia64_tpa(bte->most_rcnt_na))));
 
 
 	/* Initiate the transfer */
@@ -294,7 +294,7 @@
 				headBteLen += footBteLen;
 			} else if (footBcopyLen > 0) {
 				rv = bte_copy(footBteSource,
-					      __tpa(bteBlock),
+					      ia64_tpa(bteBlock),
 					      footBteLen, mode, NULL);
 				if (rv != BTE_SUCCESS) {
 					return rv;
@@ -344,7 +344,7 @@
 
 	if (headBcopyLen > 0) {
 		rv = bte_copy(headBteSource,
-			      __tpa(bteBlock), headBteLen, mode, NULL);
+			      ia64_tpa(bteBlock), headBteLen, mode, NULL);
 		if (rv != BTE_SUCCESS) {
 			return rv;
 		}
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/irq.c linux-2.4.23-pre4/arch/ia64/sn/kernel/irq.c
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/irq.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/irq.c	2003-09-12 12:44:35.000000000 -0700
@@ -68,6 +68,13 @@
 extern void pcibr_force_interrupt(pcibr_intr_t intr);
 extern int sn_force_interrupt_flag;
 
+struct pcibr_intr_list_t {
+	struct pcibr_intr_list_t *next;
+	pcibr_intr_t intr;
+};
+
+static struct pcibr_intr_list_t **pcibr_intr_list;
+
 
 
 static unsigned int
@@ -134,14 +141,37 @@
 				platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR, IA64_IPI_DM_INT, 0);
 		}
 	}
-	__clear_bit(ivec, (volatile void *)pda.sn_in_service_ivecs);
+	clear_bit(ivec, (volatile void *)pda.sn_in_service_ivecs);
 	if (sn_force_interrupt_flag)
 		force_interrupt(irq);
 }
 
 static void
-sn_set_affinity_irq(unsigned int irq, unsigned long mask)
+sn_set_affinity_irq(unsigned int irq, unsigned long cpu)
 {
+	int redir = 0;
+	struct pcibr_intr_list_t *p = pcibr_intr_list[irq];
+	pcibr_intr_t intr;
+	extern void sn_shub_redirect_intr(pcibr_intr_t intr, unsigned long cpu);
+	extern void sn_tio_redirect_intr(pcibr_intr_t intr, unsigned long cpu);
+
+	if (p == NULL)
+		return;
+
+	intr = p->intr;
+
+	if (intr == NULL)
+		return;
+
+	if (IS_PIC_SOFT(intr->bi_soft) ) {
+		sn_shub_redirect_intr(intr, cpu);
+	// Defer TIO for now.
+	// } else if (IS_TIO_SOFT(intr->bi_soft) {
+		// sn_tio_redirect_intr(intr, cpu);
+	} else {
+		return;
+	}
+	(void) set_irq_affinity_info(irq, cpu_physical_id(cpu), redir);
 }
 
 
@@ -181,7 +211,7 @@
 	int i;
 	irq_desc_t *base_desc = _irq_desc;
 
-	for (i=IA64_FIRST_DEVICE_VECTOR; i<NR_IRQS; i++) {
+	for (i=0; i<NR_IRQS; i++) {
 		if (base_desc[i].handler == &no_irq_type) {
 			base_desc[i].handler = &irq_type_sn;
 		}
@@ -204,18 +234,11 @@
         return bit;
 }
 
-struct pcibr_intr_list_t {
-	struct pcibr_intr_list_t *next;
-	pcibr_intr_t intr;
-};
-
-static struct pcibr_intr_list_t **pcibr_intr_list;
-
 void
 register_pcibr_intr(int irq, pcibr_intr_t intr) {
 	struct pcibr_intr_list_t *p = kmalloc(sizeof(struct pcibr_intr_list_t), GFP_KERNEL);
 	struct pcibr_intr_list_t *list;
-	int cpu = SN_CPU_FROM_IRQ(irq);
+	int cpu = intr->bi_cpu;
 
 	if (pcibr_intr_list == NULL) {
 		pcibr_intr_list = kmalloc(sizeof(struct pcibr_intr_list_t *) * NR_IRQS, GFP_KERNEL);
@@ -227,7 +250,7 @@
 	if (pdacpu(cpu).sn_last_irq < irq) {
 		pdacpu(cpu).sn_last_irq = irq;
 	}
-	if (pdacpu(cpu).sn_first_irq > irq) pdacpu(cpu).sn_first_irq = irq;
+	if (pdacpu(cpu).sn_first_irq == 0 || pdacpu(cpu).sn_first_irq > irq) pdacpu(cpu).sn_first_irq = irq;
 	if (!p) panic("Could not allocate memory for pcibr_intr_list_t\n");
 	if ((list = pcibr_intr_list[irq])) {
 		while (list->next) list = list->next;
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/led.c linux-2.4.23-pre4/arch/ia64/sn/kernel/led.c
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/led.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/led.c	2003-09-12 12:44:35.000000000 -0700
@@ -0,0 +1,56 @@
+/*
+ *
+ *
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of version 2 of the GNU General Public License 
+ * as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * 
+ * Further, this software is distributed without any warranty that it is 
+ * free of the rightful claim of any third person regarding infringement 
+ * or the like.  Any license provided herein, whether implied or 
+ * otherwise, applies only to this software file.  Patent licenses, if 
+ * any, provided herein do not apply to combinations of this program with 
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write the Free Software 
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/timer.h>
+#include <asm/sn/leds.h>
+#include <asm/sn/pda.h>
+
+struct timer_list sn_led_timer;
+
+static void 
+sn_led_timeout (unsigned long arg)
+{
+	set_led_bits(pda.hb_state ^= LED_CPU_HEARTBEAT, LED_CPU_HEARTBEAT);
+	sn_led_timer.expires = jiffies + HZ/2;
+	add_timer(&sn_led_timer);
+}
+
+void __init
+sn_led_timer_init (void)
+{
+	init_timer(&sn_led_timer);
+	sn_led_timer.expires = jiffies + HZ/2;
+	sn_led_timer.function = &sn_led_timeout;
+	add_timer(&sn_led_timer);
+}
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/setup.c linux-2.4.23-pre4/arch/ia64/sn/kernel/setup.c
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/setup.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/setup.c	2003-09-12 12:44:35.000000000 -0700
@@ -56,8 +56,10 @@
 #include <asm/machvec.h>
 #include <asm/system.h>
 #include <asm/processor.h>
+#include <asm/pgalloc.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/io.h>
+#include <asm/sn/pci/pciio.h>
 #include <asm/sn/arch.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/pda.h>
@@ -71,7 +73,7 @@
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sn2/shub.h>
 
-#define pxm_to_nasid(pxm) ((pxm)<<1)
+#define pxm_to_nasid(pxm) (((pxm)<<1) | (get_nasid() & ~0x1ff))
 
 #define MAX_PHYS_MEMORY		(1UL << 49)	/* 1 TB */
 
@@ -79,8 +81,12 @@
 extern void bte_init_cpu (void);
 extern void sn_timer_init(void);
 extern unsigned long last_time_offset;
+extern void init_platform_hubinfo(nodepda_t **nodepdaindr);
 extern void (*ia64_mark_idle)(int);
+extern void (*ia64_platform_timer_extras)(void);
+extern void sn_timer_interrupt_extras(void);
 extern void snidle(int);
+extern unsigned char acpi_kbd_controller_present;
 
 unsigned long sn_rtc_cycles_per_second;   
 
@@ -90,6 +96,7 @@
 
 short	physical_node_map[MAX_PHYSNODE_ID];
 
+int	numionodes;
 /*
  * This is the address of the RRegs in the HSpace of the global
  * master.  It is used by a hack in serial.c (serial_[in|out],
@@ -223,7 +230,77 @@
 			shub_1_1_found = 1;
 }
 
+/*
+ * SN2 requires very slightly different alternate data-TLB miss handle than what
+ * the mainline linux kernel provides.  At some point this approach could be used
+ * to allow the use of the low-memory thrown away on other platforms when VGA is
+ * present.
+ *
+ * On SN2 we want to load small TCs for granule-0 (and aliases of) faulting
+ * addresses.  The details of this are more sublte than at which they first
+ * appear.
+ */
+static void __init
+sn2_replace_ivt(void)
+{
+	extern unsigned char alt_dtlb_miss[], ia64_ivt_page_fault[];
+	extern unsigned char sn2_alt_dtlb_miss[], sn2_alt_dtlb_miss_end[];
+	extern unsigned char sn2_alt_dtlb_miss_patch1[];
+
+	unsigned char *s, *d;
+	u64 *p;
+	u64 len = (u64)sn2_alt_dtlb_miss_end - (u64)sn2_alt_dtlb_miss;
+	u64 broffs = (ia64_ivt_page_fault - alt_dtlb_miss) - (sn2_alt_dtlb_miss_patch1 - sn2_alt_dtlb_miss);
+	u64 psr;
+	int i;
+
+	/* printk(KERN_DEBUG "Replacing alternate data-TLB miss handler.\n"); */
+
+	/* Check the code isn't too large */
+	if (len > 1024) {
+		printk(KERN_ERR "SGI: Specific alt_dtlb_misse too large!  Not replacing\n");
+		return;
+	}
+
+	/* check the offset is sane (should always be) */
+	if ((broffs>>4) + (1<<20) >= (1<<21)) {
+		printk(KERN_ERR "SGI: IVT patch ivt offset %ld invalid!   Not replacing!\n", broffs);
+		return;
+	}
+
+	/* 2nd half of bundle to patch (has slot 2) */
+	p = (u64*)sn2_alt_dtlb_miss_patch1 + 1;
+	/* patch the offset into slot 2 (imm20b + s) */
+	*p = (*p & ~(0x8fffff000000000)) | ((broffs & 0x1000000) << 35) | ((broffs & 0x0fffff0) << 32);
+
+	/* don't want any interrupts when doing this */
+	psr = ia64_clear_ic();
+
+	/* copy over the existing code, flush i-cache as required */
+	d = alt_dtlb_miss;
+	s = sn2_alt_dtlb_miss;
+	for (i=0; i<len; ++i, ++s) {
+		*d++ = *s;
+		if ((((u64)s) & 63) == 63) {
+			ia64_insn_group_barrier();
+			ia64_fc((void*)s);
+		}
+	}
+	ia64_insn_group_barrier();
+	ia64_fc((void*)s);
+
+	/* sync & serialize instruction stream */
+	ia64_sync_i();
+	ia64_srlz_i();
+
+	/* restore interrupt status */
+	ia64_set_psr(psr);
 
+	/* flush any TC's we have had previously loaded that could cause problems here */
+	local_flush_tlb_all();
+
+	printk(KERN_DEBUG "SGI: Replaced alt_dtlb_miss handler.\n");
+}
 
 /**
  * sn_setup - SN platform setup routine
@@ -237,12 +314,27 @@
 sn_setup(char **cmdline_p)
 {
 	long status, ticks_per_sec, drift;
-	int i, pxm;
+	int pxm;
 	int major = sn_sal_rev_major(), minor = sn_sal_rev_minor();
-	extern void io_sh_swapper(int, int);
-	extern nasid_t get_master_baseio_nasid(void);
 	extern void sn_cpu_init(void);
 
+	/*
+	 * If the generic code has enabled vga console support - lets
+	 * get rid of it again. This is a kludge for the fact that ACPI
+	 * currtently has no way of informing us if legacy VGA is available
+	 * or not.
+	 */
+#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
+	if (conswitchp == &vga_con) {
+		printk(KERN_DEBUG "SGI: Disabling VGA console\n");
+#ifdef CONFIG_DUMMY_CONSOLE
+		conswitchp = &dummy_con;
+#else
+		conswitchp = NULL;
+#endif /* CONFIG_DUMMY_CONSOLE */
+	}
+#endif /* def(CONFIG_VT) && def(CONFIG_VGA_CONSOLE) */
+
 	MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY;
 
 	memset(physical_node_map, -1, sizeof(physical_node_map));
@@ -250,6 +342,19 @@
 		if (pxm_to_nid_map[pxm] != -1)
 			physical_node_map[pxm_to_nasid(pxm)] = pxm_to_nid_map[pxm];
 
+
+	/*
+	 * Old PROMs do not provide an ACPI FADT. Disable legacy keyboard
+	 * support here so we don't have to listen to failed keyboard probe
+	 * messages.
+	 */
+	if ((major < 2 || (major == 2 && minor <= 9)) &&
+	    acpi_kbd_controller_present) {
+		printk(KERN_INFO "Disabling legacy keyboard support as prom "
+		       "is too old and doesn't provide FADT\n");
+		acpi_kbd_controller_present = 0;
+	}
+
 	printk("SGI SAL version %x.%02x\n", major, minor);
 
 	/*
@@ -262,11 +367,12 @@
 		panic("PROM version too old\n");
 	}
 
-	io_sh_swapper(get_nasid(), 0);
+	/* Patch the ivt */
+	sn2_replace_ivt();
 
 	master_nasid = get_nasid();
-	(void)get_console_nasid();
-	(void)get_master_baseio_nasid();
+	(void)snia_get_console_nasid();
+	(void)snia_get_master_baseio_nasid();
 
 	status = ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec, &drift);
 	if (status != 0 || ticks_per_sec < 100000) {
@@ -277,7 +383,7 @@
 	else
 		sn_rtc_cycles_per_second = ticks_per_sec;
 
-	platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_PCE_VECTOR;
+	platform_intr_list[ACPI_INTERRUPT_CPEI] = IA64_CPE_VECTOR;
 
 
 	if ( IS_RUNNING_ON_SIMULATOR() )
@@ -298,11 +404,6 @@
 	 */
 	sn_init_pdas(cmdline_p);
 
-	/*
-	 * Check for WARs.
-	 */
-	sn_check_for_wars();
-
 	ia64_mark_idle = &snidle;
 
 	/* 
@@ -311,11 +412,18 @@
 	 */
 	sn_cpu_init();
 
+	/*
+	 * Setup hubinfo stuff. Has to happen AFTER sn_cpu_init(),
+	 * because it uses the cnode to nasid tables.
+	 */
+	init_platform_hubinfo(nodepdaindr);
 #ifdef CONFIG_SMP
 	init_smp_config();
 #endif
 	screen_info = sn_screen_info;
 
+	ia64_platform_timer_extras = &sn_timer_interrupt_extras;
+
 	sn_timer_init();
 }
 
@@ -328,6 +436,7 @@
 sn_init_pdas(char **cmdline_p)
 {
 	cnodeid_t	cnode;
+	void scan_for_ionodes(void);
 
 	/*
 	 * Make sure that the PDA fits entirely in the same page as the 
@@ -340,6 +449,9 @@
 	for (cnode=0; cnode<numnodes; cnode++)
 		pda.cnodeid_to_nasid_table[cnode] = pxm_to_nasid(nid_to_pxm_map[cnode]);
 
+	numionodes = numnodes;
+	scan_for_ionodes();
+
         /*
          * Allocate & initalize the nodepda for each node.
          */
@@ -348,10 +460,18 @@
 		memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
         }
 
+	/* 
+	 * Allocate & initialize nodepda for TIOs.  For now, put them on node 0.
+	 */
+	for (cnode = numnodes; cnode < numionodes; cnode ++) {
+		nodepdaindr[cnode] = alloc_bootmem_node(NODE_DATA(0), sizeof(nodepda_t));
+		memset(nodepdaindr[cnode], 0, sizeof(nodepda_t));
+	}
+
 	/*
 	 * Now copy the array of nodepda pointers to each nodepda.
 	 */
-        for (cnode=0; cnode < numnodes; cnode++)
+        for (cnode=0; cnode < numionodes; cnode++)
 		memcpy(nodepdaindr[cnode]->pernode_pdaindr, nodepdaindr, sizeof(nodepdaindr));
 
 
@@ -362,8 +482,16 @@
 	 */
 	for (cnode = 0; cnode < numnodes; cnode++) {
 		init_platform_nodepda(nodepdaindr[cnode], cnode);
+		spin_lock_init(&nodepdaindr[cnode]->bist_lock);
 		bte_init_node (nodepdaindr[cnode], cnode);
 	}
+
+	/*
+	 * Handle TIO differently .. we do not do BTE init ..
+	 */
+	for (cnode = numnodes; cnode < numionodes; cnode++) {
+		init_platform_nodepda(nodepdaindr[cnode], cnode);
+	}
 }
 
 /**
@@ -383,6 +511,7 @@
 	int	nasid;
 	int	slice;
 	int	cnode, i;
+	static int	wars_have_been_checked = 0;
 
 	/*
 	 * The boot cpu makes this call again after platform initialization is
@@ -407,11 +536,22 @@
 	pda.hb_count = HZ/2;
 	pda.hb_state = 0;
 	pda.idle_flag = 0;
-	pda.shub_1_1_found = shub_1_1_found;
 	
 	memset(pda.cnodeid_to_nasid_table, -1, sizeof(pda.cnodeid_to_nasid_table));
 	for (i=0; i<numnodes; i++)
 		pda.cnodeid_to_nasid_table[i] = pxm_to_nasid(nid_to_pxm_map[i]);
+	/*
+	 * Check for WARs.
+	 * Only needs to be done once, on BSP.
+	 * Has to be done after loop above, because it uses pda.cnodeid_to_nasid_table[i].
+	 * Has to be done before assignment below.
+	 */
+	if (!wars_have_been_checked) {
+		sn_check_for_wars();
+		wars_have_been_checked = 1;
+	}
+
+	pda.shub_1_1_found = shub_1_1_found;
 
 	if (local_node_data->active_cpu_count == 1)
 		nodepda->node_first_cpu = cpuid;
@@ -444,3 +584,27 @@
 
 	bte_init_cpu();
 }
+
+/*
+ * Scan klconfig for TIO's.  Add the TIO nasids to the
+ * physical_node_map and the pda and increment numionodes.
+ */
+
+void
+scan_for_ionodes() {
+	int nasid = 0;
+	lboard_t *brd;
+
+	/* Scan all compute nodes. */
+	for (nasid = 0; nasid < MAX_PHYSNODE_ID; nasid +=2) {
+		/* if there's no nasid, don't try to read the klconfig on the node */
+		if (physical_node_map[nasid] == -1) continue;
+		brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_TIO);
+		while (brd) {
+			pda.cnodeid_to_nasid_table[numionodes] = brd->brd_nasid;
+			physical_node_map[brd->brd_nasid] = numionodes++;
+			brd = KLCF_NEXT(brd);
+			brd = find_lboard(brd, KLTYPE_TIO);
+		}
+	}
+}
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/sn2/Makefile linux-2.4.23-pre4/arch/ia64/sn/kernel/sn2/Makefile
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/sn2/Makefile	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/sn2/Makefile	2003-09-12 12:44:35.000000000 -0700
@@ -44,6 +44,6 @@
 export-objs	:= io.o
 
 obj-y		= cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \
-		  prominfo_proc.o timer.o
+		  prominfo_proc.o timer.o timer_interrupt.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/sn2/cache.c linux-2.4.23-pre4/arch/ia64/sn/kernel/sn2/cache.c
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/sn2/cache.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/sn2/cache.c	2003-09-12 12:44:35.000000000 -0700
@@ -23,6 +23,18 @@
 void
 sn_flush_all_caches(long flush_addr, long bytes)
 {
+	/*
+	 * The following double call to flush_icache_range has
+	 * the following effect which is required:
+	 *
+	 * The first flush_icache_range ensures the fc() address
+	 * is visible on the FSB.  The NUMA controller however has
+	 * not necessarily forwarded the fc() request to all other
+	 * NUMA controllers. The second call will stall
+	 * at the associated fc() instruction until the first
+	 * has been forwarded to all other NUMA controllers.
+	 */
+	flush_icache_range(flush_addr, flush_addr+bytes);
 	flush_icache_range(flush_addr, flush_addr+bytes);
 	mb();
 }
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/sn2/sn_proc_fs.c linux-2.4.23-pre4/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2003-09-12 12:44:35.000000000 -0700
@@ -36,6 +36,7 @@
 #ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
 #include <asm/sn/sn_sal.h>
+#include <asm/sn/sn_cpuid.h>
 
 
 static int partition_id_read_proc(char *page, char **start, off_t off,
@@ -184,12 +185,66 @@
 	}
 }
 
+#define SHUB_MAX_VERSION 3
+static struct proc_dir_entry **proc_entries;
+static char* shub_revision[SHUB_MAX_VERSION+1] = {
+	"unknown",
+	"1.0",
+	"1.1",
+	"1.2"
+};
+
+static int
+read_shub_info_entry(char* page, char **start, off_t off, int count, int *eof,
+		     void* data) {
+	unsigned long id;
+	int rev;
+	int nasid = (long) data; /* Data contains NASID of this node */
+	int len = 0;
+
+	id = REMOTE_HUB_L(nasid, SH_SHUB_ID);
+	rev = (id & SH_SHUB_ID_REVISION_MASK) >> SH_SHUB_ID_REVISION_SHFT;
+	len += sprintf(&page[len], "type     : SHub\n");
+	len += sprintf(&page[len], "revision : %s\n", 
+		       (rev <= SHUB_MAX_VERSION) ? shub_revision[rev] : "unknown");
+	len += sprintf(&page[len], "nasid    : %d\n", nasid);
+
+	return len;
+}
+
+static void
+register_sn_nodes(void) {
+	struct proc_dir_entry **entp;
+	cnodeid_t cnodeid;
+	nasid_t nasid;
+	char name[11];
+
+	if (!sgi_proc_dir) {
+		sgi_proc_dir = proc_mkdir("sgi_sn", 0);
+	}
+
+	proc_entries = kmalloc(numnodes * sizeof(struct proc_dir_entry *),
+			       GFP_KERNEL);
+
+	for (cnodeid = 0, entp = proc_entries;
+	     cnodeid < numnodes;
+	     cnodeid++, entp++) {
+		sprintf(name, "node%d", cnodeid);
+		*entp = proc_mkdir(name, sgi_proc_dir);
+		nasid = cnodeid_to_nasid(cnodeid);
+		create_proc_read_entry(
+			"hubinfo", 0, *entp, read_shub_info_entry,
+			(void*) (long) nasid);
+	}
+}
+
 void
 register_sn_procfs(void) {
 	register_sn_partition_id();
 	register_sn_serial_numbers();
 	register_sn_force_interrupt();
 	register_sn_linkstats();
+	register_sn_nodes();
 }
 
 #endif /* CONFIG_PROC_FS */
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/sn2/timer.c linux-2.4.23-pre4/arch/ia64/sn/kernel/sn2/timer.c
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/sn2/timer.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/sn2/timer.c	2003-09-12 12:44:35.000000000 -0700
@@ -34,7 +34,7 @@
  */
 extern unsigned long wall_jiffies; /* from kernel/timer.c */
 
-static volatile long rtc_offset;
+static volatile long rtc_offset __cacheline_aligned;
 static long rtc_cycles_per_usec;
 static long rtc_per_timer_tick;
 
@@ -86,7 +86,6 @@
 	last_wall_rtc = GET_RTC_COUNTER();
 }
 
-
 void __init
 sn_timer_init(void)
 {
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/sn2/timer_interrupt.c linux-2.4.23-pre4/arch/ia64/sn/kernel/sn2/timer_interrupt.c
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/sn2/timer_interrupt.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/sn2/timer_interrupt.c	2003-09-12 12:44:35.000000000 -0700
@@ -0,0 +1,60 @@
+/*
+ *
+ *
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of version 2 of the GNU General Public License 
+ * as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * 
+ * Further, this software is distributed without any warranty that it is 
+ * free of the rightful claim of any third person regarding infringement 
+ * or the like.  Any license provided herein, whether implied or 
+ * otherwise, applies only to this software file.  Patent licenses, if 
+ * any, provided herein do not apply to combinations of this program with 
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write the Free Software 
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <asm/sn/pda.h>
+#include <asm/sn/leds.h>
+
+extern void sn_lb_int_war_check(void);
+#define SN_LB_INT_WAR_INTERVAL 100
+
+void
+sn_timer_interrupt_extras(void)
+{
+	/* LED blinking */
+	if (!pda.hb_count--) {
+		pda.hb_count = HZ/2;
+		set_led_bits(pda.hb_state ^= LED_CPU_HEARTBEAT, LED_CPU_HEARTBEAT);
+	}
+
+	if (enable_shub_wars_1_1()) {
+		/* Bugfix code for SHUB 1.1 */
+        	if (pda.pio_shub_war_cam_addr)
+                	*pda.pio_shub_war_cam_addr = 0x8000000000000010UL;
+	}
+	if (pda.sn_lb_int_war_ticks == 0)
+		sn_lb_int_war_check();
+	pda.sn_lb_int_war_ticks++;
+	if (pda.sn_lb_int_war_ticks >= SN_LB_INT_WAR_INTERVAL)
+		pda.sn_lb_int_war_ticks = 0;
+}
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/sn2_smp.c linux-2.4.23-pre4/arch/ia64/sn/kernel/sn2_smp.c
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/sn2_smp.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/sn2_smp.c	2003-09-12 12:44:35.000000000 -0700
@@ -0,0 +1,242 @@
+/*
+ * SN2 Platform specific SMP Support
+ *
+ * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of version 2 of the GNU General Public License 
+ * as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * 
+ * Further, this software is distributed without any warranty that it is 
+ * free of the rightful claim of any third person regarding infringement 
+ * or the like.  Any license provided herein, whether implied or 
+ * otherwise, applies only to this software file.  Patent licenses, if 
+ * any, provided herein do not apply to combinations of this program with 
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write the Free Software 
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/threads.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mmzone.h>
+
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <asm/sal.h>
+#include <asm/system.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/hw_irq.h>
+#include <asm/current.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/sn2/shub_mmr.h>
+#include <asm/sn/nodepda.h>
+#include <asm/sn/rw_mmr.h>
+
+void sn2_ptc_deadlock_recovery(unsigned long data0, unsigned long data1);
+
+
+static spinlock_t sn2_global_ptc_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
+
+static unsigned long sn2_ptc_deadlock_count;
+
+
+static inline unsigned long
+wait_piowc(void)
+{
+	volatile unsigned long *piows;
+	unsigned long	ws;
+
+	piows = pda.pio_write_status_addr;
+	do {
+		__asm__ __volatile__ ("mf.a" ::: "memory");
+	} while (((ws = *piows) & SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK) != 
+			SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_MASK);
+	return ws;
+}
+
+
+
+/**
+ * sn2_global_tlb_purge - globally purge translation cache of virtual address range
+ * @start: start of virtual address range
+ * @end: end of virtual address range
+ * @nbits: specifies number of bytes to purge per instruction (num = 1<<(nbits & 0xfc))
+ *
+ * Purges the translation caches of all processors of the given virtual address
+ * range.
+ */
+
+void
+sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits)
+{
+	int			cnode, mycnode, nasid, flushed=0;
+	volatile unsigned	long	*ptc0, *ptc1;
+	unsigned long		flags=0, data0, data1;
+
+	data0 = (1UL<<SH_PTC_0_A_SHFT) |
+		(nbits<<SH_PTC_0_PS_SHFT) |
+		((ia64_get_rr(start)>>8)<<SH_PTC_0_RID_SHFT) |
+		(1UL<<SH_PTC_0_START_SHFT);
+
+	ptc0 = (long*)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_0);
+	ptc1 = (long*)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_1);
+
+	mycnode = numa_node_id();
+
+	spin_lock_irqsave(&sn2_global_ptc_lock, flags);
+
+	do {
+		data1 = start | (1UL<<SH_PTC_1_START_SHFT);
+		for (cnode = 0; cnode < numnodes; cnode++) {
+			if (is_headless_node(cnode))
+				continue;
+			if (cnode == mycnode) {
+				asm volatile ("ptc.ga %0,%1;;srlz.i;;" :: "r"(start), "r"(nbits<<2) : "memory");
+			} else {
+				nasid = cnodeid_to_nasid(cnode);
+				ptc0 = CHANGE_NASID(nasid, ptc0);
+				ptc1 = CHANGE_NASID(nasid, ptc1);
+				pio_atomic_phys_write_mmrs(ptc0, data0, ptc1, data1);
+				flushed = 1;
+			}
+		}
+
+		if (flushed && (wait_piowc() & SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_MASK)) {
+			sn2_ptc_deadlock_recovery(data0, data1);
+		}
+
+		start += (1UL << nbits);
+
+	} while (start < end);
+
+	spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
+
+}
+
+/*
+ * sn2_ptc_deadlock_recovery
+ *
+ * Recover from PTC deadlocks conditions. Recovery requires stepping thru each 
+ * TLB flush transaction.  The recovery sequence is somewhat tricky & is
+ * coded in assembly language.
+ */
+void
+sn2_ptc_deadlock_recovery(unsigned long data0, unsigned long data1)
+{
+	extern void sn2_ptc_deadlock_recovery_core(long*, long, long*, long, long*);
+	int	cnode, mycnode, nasid;
+	long	*ptc0, *ptc1, *piows;
+
+	sn2_ptc_deadlock_count++;
+
+	ptc0 = (long*)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_0);
+	ptc1 = (long*)GLOBAL_MMR_PHYS_ADDR(0, SH_PTC_1);
+	piows = (long*)pda.pio_write_status_addr;
+
+	mycnode = numa_node_id();
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+		if (is_headless_node(cnode) || cnode == mycnode)
+			continue;
+		nasid = cnodeid_to_nasid(cnode);
+		ptc0 = CHANGE_NASID(nasid, ptc0);
+		ptc1 = CHANGE_NASID(nasid, ptc1);
+		sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows);
+	}
+}
+
+/**
+ * sn_send_IPI_phys - send an IPI to a Nasid and slice
+ * @physid: physical cpuid to receive the interrupt.
+ * @vector: command to send
+ * @delivery_mode: delivery mechanism
+ *
+ * Sends an IPI (interprocessor interrupt) to the processor specified by
+ * @physid
+ *
+ * @delivery_mode can be one of the following
+ *
+ * %IA64_IPI_DM_INT - pend an interrupt
+ * %IA64_IPI_DM_PMI - pend a PMI
+ * %IA64_IPI_DM_NMI - pend an NMI
+ * %IA64_IPI_DM_INIT - pend an INIT interrupt
+ */
+void
+sn_send_IPI_phys(long physid, int vector, int delivery_mode)
+{
+	long		nasid, slice, val;
+	unsigned long	flags=0;
+	volatile long	*p;
+
+	nasid = cpu_physical_id_to_nasid(physid);
+        slice = cpu_physical_id_to_slice(physid);
+
+	p = (long*)GLOBAL_MMR_PHYS_ADDR(nasid, SH_IPI_INT);
+	val =   (1UL<<SH_IPI_INT_SEND_SHFT) | 
+		(physid<<SH_IPI_INT_PID_SHFT) | 
+	        ((long)delivery_mode<<SH_IPI_INT_TYPE_SHFT) | 
+		((long)vector<<SH_IPI_INT_IDX_SHFT) |
+		(0x000feeUL<<SH_IPI_INT_BASE_SHFT);
+
+	mb();
+	if (enable_shub_wars_1_1() ) {
+		spin_lock_irqsave(&sn2_global_ptc_lock, flags);
+	}
+	pio_phys_write_mmr(p, val);
+	if (enable_shub_wars_1_1() ) {
+		wait_piowc();
+		spin_unlock_irqrestore(&sn2_global_ptc_lock, flags);
+	}
+
+}
+
+/**
+ * sn2_send_IPI - send an IPI to a processor
+ * @cpuid: target of the IPI
+ * @vector: command to send
+ * @delivery_mode: delivery mechanism
+ * @redirect: redirect the IPI?
+ *
+ * Sends an IPI (InterProcessor Interrupt) to the processor specified by
+ * @cpuid.  @vector specifies the command to send, while @delivery_mode can 
+ * be one of the following
+ *
+ * %IA64_IPI_DM_INT - pend an interrupt
+ * %IA64_IPI_DM_PMI - pend a PMI
+ * %IA64_IPI_DM_NMI - pend an NMI
+ * %IA64_IPI_DM_INIT - pend an INIT interrupt
+ */
+void
+sn2_send_IPI(int cpuid, int vector, int delivery_mode, int redirect)
+{
+	long		physid;
+
+	physid = cpu_physical_id(cpuid);
+
+	sn_send_IPI_phys(physid, vector, delivery_mode);
+}
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/sn_ivt.S linux-2.4.23-pre4/arch/ia64/sn/kernel/sn_ivt.S
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/sn_ivt.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/sn_ivt.S	2003-09-12 12:44:35.000000000 -0700
@@ -0,0 +1,96 @@
+/* -*- mode: fundamental -*- */
+
+/*
+ * SN2 specific ivt(s)
+ *
+ * archi/ia64/sn/kernel/setup.c will dynamically replace code in the
+ * ivt with code from here
+ *
+ * Please note: We need to be sure that any changes in ivt.S are also
+ * reflected here (for example, if the ia64_ivt_page_fault register
+ * usage changes) and vice-versa.
+ *
+ * Copyright (c) 1998-2003 Hewlett-Packard Company
+ *	Stephane Eranian <eranian@hpl.hp.com>
+ *	David Mosberger <davidm@hpl.hp.com>
+ *
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ */
+
+#include <linux/config.h>
+
+#include <asm/asmmacro.h>
+#include <asm/break.h>
+#include <asm/kregs.h>
+#include <asm/offsets.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/unistd.h>
+
+
+/* If someone has a *really* good reason to disable the VHPT for SN2 I'll fix this. --cw */
+#ifdef CONFIG_DISABLE_VHPT
+#error SN2 requires VHPT be enabled
+#endif
+
+	.section ".text.init", "ax"
+
+/*
+ * SN2 specific region 6/7 dtlb miss handler.
+ *
+ * On SN2 some granule-0 addresses (and therefore any aliases) are
+ * actually used uncachable.  We load small TC entries to ensure there
+ * is no-overlap between such regions (which could cause a Cache-Check
+ * MCA).
+ */
+#define SN2_GMASK	(((1 << (36-IA64_GRANULE_SHIFT)) - 1) << IA64_GRANULE_SHIFT)
+	.global sn2_alt_dtlb_miss
+ENTRY(sn2_alt_dtlb_miss)
+	mov r16=cr.ifa					// get address that caused the TLB miss
+	movl r17=PAGE_KERNEL				// kernel protection bits (RWX)
+	mov r20=cr.isr					// need to check for SP and NA status
+	movl r19=(((1<<IA64_MAX_PHYS_BITS)-1) & ~0xfff)	// suitable mask
+	mov r21=cr.ipsr					// get ipsr incase we need to poke the ED bit
+	mov r31=pr					// save pr's
+	mov r25=_PAGE_SIZE_4K<<2				// granule-0 requires we use smaller pages
+	;;
+	movl r27=SN2_GMASK				// Mask suitable to fine granule-0 (aliased) addresses
+	tbit.nz p9,p0=r20,IA64_ISR_NA_BIT			// is non-access bit on?
+	and r22=IA64_ISR_CODE_MASK,r20			// get the isr.code field
+	extr.u r23=r21,IA64_PSR_CPL0_BIT,2			// extract psr.cpl
+	shr.u r26=r16,61					// region number
+	;;
+	tbit.nz p6,p7=r20,IA64_ISR_SP_BIT			// is speculation bit on?
+	and r19=r19,r16					// clear ED, reserved bits, and PTE control bits
+	cmp.eq p10,p11=7,r26				// p11 <- region 7 (else p10 <- !0 => region 6)
+	and r24=r27,r16					// mask away all but region bits
+	;;
+	cmp.ne.andcm p10,p0=r0,r24			// p10 <- region-6 AND granule-0
+
+/* arch/ia64/sn/kernel/setup.c patches this code, you should check there if you need to mess about with this */
+	.global sn2_alt_dtlb_miss_patch1
+sn2_alt_dtlb_miss_patch1:
+	{ .mib
+(p9)	cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22	// check isr.code field
+	cmp.ne p8,p0=r0,r23				// p8 <- cpl == 0?
+(p8)	br.cond.spnt.many ia64_ivt_page_fault		// NB: gets patched
+	}
+
+	;;
+(p10)	mov cr.itir=r25					// use smaller pagesize for tc
+	dep r21=-1,r21,IA64_PSR_ED_BIT,1			// r21 is psr with ED enabled
+	or r19=r19,r17					// insert PTE control bits into r19
+	;;
+(p6)	mov cr.ipsr=r21					// p6 (speculation): set ed (else we can get stuck)
+(p11)	dep r19=-1,r19,4,1				// set bit 4 (uncached) if the access was to region 6
+	;;
+(p7)	itc.d r19					// insert the TLB entry
+	mov pr=r31,-1					// restore pr's
+	rfi
+END(alt_dtlb_miss)
+	.align 8
+	.global sn2_alt_dtlb_miss_end
+sn2_alt_dtlb_miss_end:
diff -urN linux-2.4.23-pre3/arch/ia64/sn/kernel/sn_ksyms.c linux-2.4.23-pre4/arch/ia64/sn/kernel/sn_ksyms.c
--- linux-2.4.23-pre3/arch/ia64/sn/kernel/sn_ksyms.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/sn/kernel/sn_ksyms.c	2003-09-12 12:44:35.000000000 -0700
@@ -64,7 +64,6 @@
 #include <asm/sn/sn_sal.h>
 EXPORT_SYMBOL(sal_lock);
 EXPORT_SYMBOL(sn_partid);
-EXPORT_SYMBOL(sn_local_partid);
 EXPORT_SYMBOL(sn_system_serial_number_string);
 EXPORT_SYMBOL(sn_partition_serial_number);
 
diff -urN linux-2.4.23-pre3/arch/ia64/tools/print_offsets.c linux-2.4.23-pre4/arch/ia64/tools/print_offsets.c
--- linux-2.4.23-pre3/arch/ia64/tools/print_offsets.c	2003-08-25 04:44:39.000000000 -0700
+++ linux-2.4.23-pre4/arch/ia64/tools/print_offsets.c	2003-09-12 12:44:35.000000000 -0700
@@ -1,6 +1,7 @@
 /*
  * Utility to generate asm-ia64/offsets.h.
  *
+ * Copyright (C) 2002-2003 Fenghua Yu <fenghua.yu@intel.com>
  * Copyright (C) 1999-2001 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
@@ -63,6 +64,14 @@
 #endif
     { "IA64_TASK_PID_OFFSET",		offsetof (struct task_struct, pid) },
     { "IA64_TASK_MM_OFFSET",		offsetof (struct task_struct, mm) },
+    { "IA64_PT_REGS_B6_OFFSET",		offsetof (struct pt_regs, b6) },
+    { "IA64_PT_REGS_B7_OFFSET",		offsetof (struct pt_regs, b7) },
+    { "IA64_PT_REGS_AR_CSD_OFFSET",	offsetof (struct pt_regs, ar_csd) },
+    { "IA64_PT_REGS_AR_SSD_OFFSET",	offsetof (struct pt_regs, ar_ssd) },
+    { "IA64_PT_REGS_R8_OFFSET",		offsetof (struct pt_regs, r8) },
+    { "IA64_PT_REGS_R9_OFFSET",		offsetof (struct pt_regs, r9) },
+    { "IA64_PT_REGS_R10_OFFSET",	offsetof (struct pt_regs, r10) },
+    { "IA64_PT_REGS_R11_OFFSET",	offsetof (struct pt_regs, r11) },
     { "IA64_PT_REGS_CR_IPSR_OFFSET",	offsetof (struct pt_regs, cr_ipsr) },
     { "IA64_PT_REGS_CR_IIP_OFFSET",	offsetof (struct pt_regs, cr_iip) },
     { "IA64_PT_REGS_CR_IFS_OFFSET",	offsetof (struct pt_regs, cr_ifs) },
@@ -72,19 +81,16 @@
     { "IA64_PT_REGS_AR_RNAT_OFFSET",	offsetof (struct pt_regs, ar_rnat) },
     { "IA64_PT_REGS_AR_BSPSTORE_OFFSET",offsetof (struct pt_regs, ar_bspstore) },
     { "IA64_PT_REGS_PR_OFFSET",		offsetof (struct pt_regs, pr) },
-    { "IA64_PT_REGS_B6_OFFSET",		offsetof (struct pt_regs, b6) },
+    { "IA64_PT_REGS_B0_OFFSET",		offsetof (struct pt_regs, b0) },
     { "IA64_PT_REGS_LOADRS_OFFSET",	offsetof (struct pt_regs, loadrs) },
     { "IA64_PT_REGS_R1_OFFSET",		offsetof (struct pt_regs, r1) },
-    { "IA64_PT_REGS_R2_OFFSET",		offsetof (struct pt_regs, r2) },
-    { "IA64_PT_REGS_R3_OFFSET",		offsetof (struct pt_regs, r3) },
     { "IA64_PT_REGS_R12_OFFSET",	offsetof (struct pt_regs, r12) },
     { "IA64_PT_REGS_R13_OFFSET",	offsetof (struct pt_regs, r13) },
-    { "IA64_PT_REGS_R14_OFFSET",	offsetof (struct pt_regs, r14) },
+    { "IA64_PT_REGS_AR_FPSR_OFFSET",	offsetof (struct pt_regs, ar_fpsr) },
     { "IA64_PT_REGS_R15_OFFSET",	offsetof (struct pt_regs, r15) },
-    { "IA64_PT_REGS_R8_OFFSET",		offsetof (struct pt_regs, r8) },
-    { "IA64_PT_REGS_R9_OFFSET",		offsetof (struct pt_regs, r9) },
-    { "IA64_PT_REGS_R10_OFFSET",	offsetof (struct pt_regs, r10) },
-    { "IA64_PT_REGS_R11_OFFSET",	offsetof (struct pt_regs, r11) },
+    { "IA64_PT_REGS_R14_OFFSET",	offsetof (struct pt_regs, r14) },
+    { "IA64_PT_REGS_R2_OFFSET",		offsetof (struct pt_regs, r2) },
+    { "IA64_PT_REGS_R3_OFFSET",		offsetof (struct pt_regs, r3) },
     { "IA64_PT_REGS_R16_OFFSET",	offsetof (struct pt_regs, r16) },
     { "IA64_PT_REGS_R17_OFFSET",	offsetof (struct pt_regs, r17) },
     { "IA64_PT_REGS_R18_OFFSET",	offsetof (struct pt_regs, r18) },
@@ -102,21 +108,18 @@
     { "IA64_PT_REGS_R30_OFFSET",	offsetof (struct pt_regs, r30) },
     { "IA64_PT_REGS_R31_OFFSET",	offsetof (struct pt_regs, r31) },
     { "IA64_PT_REGS_AR_CCV_OFFSET",	offsetof (struct pt_regs, ar_ccv) },
-    { "IA64_PT_REGS_AR_FPSR_OFFSET",	offsetof (struct pt_regs, ar_fpsr) },
-    { "IA64_PT_REGS_B0_OFFSET",		offsetof (struct pt_regs, b0) },
-    { "IA64_PT_REGS_B7_OFFSET",		offsetof (struct pt_regs, b7) },
     { "IA64_PT_REGS_F6_OFFSET",		offsetof (struct pt_regs, f6) },
     { "IA64_PT_REGS_F7_OFFSET",		offsetof (struct pt_regs, f7) },
     { "IA64_PT_REGS_F8_OFFSET",		offsetof (struct pt_regs, f8) },
     { "IA64_PT_REGS_F9_OFFSET",		offsetof (struct pt_regs, f9) },
+    { "IA64_PT_REGS_F10_OFFSET",	offsetof (struct pt_regs, f10) },
+    { "IA64_PT_REGS_F11_OFFSET",	offsetof (struct pt_regs, f11) },
     { "IA64_SWITCH_STACK_CALLER_UNAT_OFFSET",	offsetof (struct switch_stack, caller_unat) },
     { "IA64_SWITCH_STACK_AR_FPSR_OFFSET",	offsetof (struct switch_stack, ar_fpsr) },
     { "IA64_SWITCH_STACK_F2_OFFSET",		offsetof (struct switch_stack, f2) },
     { "IA64_SWITCH_STACK_F3_OFFSET",		offsetof (struct switch_stack, f3) },
     { "IA64_SWITCH_STACK_F4_OFFSET",		offsetof (struct switch_stack, f4) },
     { "IA64_SWITCH_STACK_F5_OFFSET",		offsetof (struct switch_stack, f5) },
-    { "IA64_SWITCH_STACK_F10_OFFSET",		offsetof (struct switch_stack, f10) },
-    { "IA64_SWITCH_STACK_F11_OFFSET",		offsetof (struct switch_stack, f11) },
     { "IA64_SWITCH_STACK_F12_OFFSET",		offsetof (struct switch_stack, f12) },
     { "IA64_SWITCH_STACK_F13_OFFSET",		offsetof (struct switch_stack, f13) },
     { "IA64_SWITCH_STACK_F14_OFFSET",		offsetof (struct switch_stack, f14) },
diff -urN linux-2.4.23-pre3/arch/ppc/8260_io/uart.c linux-2.4.23-pre4/arch/ppc/8260_io/uart.c
--- linux-2.4.23-pre3/arch/ppc/8260_io/uart.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.23-pre4/arch/ppc/8260_io/uart.c	2003-09-12 12:44:35.000000000 -0700
@@ -47,6 +47,10 @@
 #include <asm/cpm_8260.h>
 #include <asm/irq.h>
 
+#ifdef CONFIG_MAGIC_SYSRQ
+#include <linux/sysrq.h>
+#endif
+
 #ifdef CONFIG_SERIAL_CONSOLE
 #include <linux/console.h>
 
@@ -68,6 +72,14 @@
 static int serial_refcount;
 static int serial_console_setup(struct console *co, char *options);
 
+static void serial_console_write(struct console *c, const char *s,
+		                                unsigned count);
+static kdev_t serial_console_device(struct console *c);
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+static unsigned long break_pressed; /* break, really ... */
+#endif
+
 /*
  * Serial driver configuration section.  Here are the various options:
  */
@@ -181,6 +193,16 @@
 	cbd_t			*tx_cur;
 } ser_info_t;
 
+static struct console sercons = {
+        name:           "ttyS",
+        write:          serial_console_write,
+        device:         serial_console_device,
+        setup:          serial_console_setup,
+        flags:          CON_PRINTBUFFER,
+        index:          CONFIG_SERIAL_CONSOLE_PORT,
+};
+
+
 static void change_speed(ser_info_t *info);
 static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout);
 
@@ -302,7 +324,7 @@
 	mark_bh(SERIAL_BH);
 }
 
-static _INLINE_ void receive_chars(ser_info_t *info)
+static _INLINE_ void receive_chars(ser_info_t *info, struct pt_regs *regs)
 {
 	struct tty_struct *tty = info->tty;
 	unsigned char ch, *cp;
@@ -417,6 +439,19 @@
 					}
 				}
 			}
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+			if (break_pressed && info->line == sercons.index) {
+				if (ch != 0 && time_before(jiffies,
+							break_pressed + HZ*5)) {
+					handle_sysrq(ch, regs, NULL, NULL);
+					break_pressed = 0;
+					goto ignore_char;
+				} else
+					break_pressed = 0;
+			}
+#endif
+			
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 				break;
 
@@ -425,6 +460,10 @@
 			tty->flip.count++;
 		}
 
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+	ignore_char:
+#endif
+
 		/* This BD is ready to be used again.  Clear status.
 		 * Get next BD.
 		 */
@@ -442,7 +481,36 @@
 	queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-static _INLINE_ void transmit_chars(ser_info_t *info)
+static _INLINE_ void receive_break(ser_info_t *info, struct pt_regs *regs)
+{
+	struct tty_struct *tty = info->tty;
+
+	info->state->icount.brk++;
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+	if (info->line == sercons.index) {
+		if (!break_pressed) {
+			break_pressed = jiffies;
+			return;
+		} else
+			break_pressed = 0;
+	}
+#endif
+
+	/* Check to see if there is room in the tty buffer for
+	 * the break.  If not, we exit now, losing the break.  FIXME
+	 */
+	if ((tty->flip.count + 1) >= TTY_FLIPBUF_SIZE)
+		return;
+	*(tty->flip.flag_buf_ptr++) = TTY_BREAK;
+	*(tty->flip.char_buf_ptr++) = 0;
+	tty->flip.count++;
+
+	queue_task(&tty->flip.tqueue, &tq_timer);
+}
+
+
+static _INLINE_ void transmit_chars(ser_info_t *info, struct pt_regs *regs)
 {
 
 	if (info->flags & TX_WAKEUP) {
@@ -543,19 +611,23 @@
 	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
 		smcp = &immr->im_smc[idx];
 		events = smcp->smc_smce;
+		if (events & SMCM_BRKE)
+			receive_break(info, regs);
 		if (events & SMCM_RX)
-			receive_chars(info);
+			receive_chars(info, regs);
 		if (events & SMCM_TX)
-			transmit_chars(info);
+			transmit_chars(info, regs);
 		smcp->smc_smce = events;
 	}
 	else {
 		sccp = &immr->im_scc[idx - SCC_IDX_BASE];
 		events = sccp->scc_scce;
+		if (events & SMCM_BRKE)
+			receive_break(info, regs);
 		if (events & SCCM_RX)
-			receive_chars(info);
+			receive_chars(info, regs);
 		if (events & SCCM_TX)
-			transmit_chars(info);
+			transmit_chars(info, regs);
 		sccp->scc_scce = events;
 	}
 
@@ -2218,16 +2290,6 @@
 	return MKDEV(TTYAUX_MAJOR, 64 + c->index);
 }
 
-
-static struct console sercons = {
-	name:		"ttyS",
-	write:		serial_console_write,
-	device:		serial_console_device,
-	setup:		serial_console_setup,
-	flags:		CON_PRINTBUFFER,
-	index:		CONFIG_SERIAL_CONSOLE_PORT,
-};
-
 /*
  *	Register console.
  */
diff -urN linux-2.4.23-pre3/arch/ppc/boot/simple/Makefile linux-2.4.23-pre4/arch/ppc/boot/simple/Makefile
--- linux-2.4.23-pre3/arch/ppc/boot/simple/Makefile	2003-09-12 12:44:32.000000000 -0700
+++ linux-2.4.23-pre4/arch/ppc/boot/simple/Makefile	2003-09-12 12:44:35.000000000 -0700
@@ -28,11 +28,21 @@
 TFTPIMAGE			:= /tftpboot/zImage.embedded
 MISC				:= misc-embedded.o
 endif
+ifeq ($(CONFIG_IBM_OPENBIOS),y)
+ZIMAGE				:= zImage-TREE
+ZIMAGEINITRD			:= zImage.initrd-TREE
+ZNETBOOT			:= zImage.treeboot
+ZNETBOOTRD			:= zImage.initrd.treeboot
+TFTPIMAGE			:= /tftpboot/zImage.embedded
+MISC				:= misc-embedded.o
+endif
 ifeq ($(CONFIG_EBONY),y)
 ZIMAGE				:= zImage-TREE
 ZIMAGEINITRD			:= zImage.initrd-TREE
 END				:= ebony
 ENTRYPOINT			:= 0x00800000
+ZNETBOOT			:= zImage.treeboot
+ZNETBOOTRD			:= zImage.initrd.treeboot
 TFTPIMAGE			:= /tftpboot/zImage.$(END)
 EXTRA				:= misc-44x.o
 endif
@@ -41,6 +51,8 @@
 ZIMAGEINITRD			:= zImage.initrd-TREE
 END				:= ocotea
 ENTRYPOINT			:= 0x00800000
+ZNETBOOT			:= zImage.treeboot
+ZNETBOOTRD			:= zImage.initrd.treeboot
 TFTPIMAGE			:= /tftpboot/zImage.$(END)
 EXTRA				:= misc-44x.o
 endif
@@ -163,10 +175,10 @@
 	mv zvmlinux.initrd ../images/zImage.initrd.embedded
 
 zImage-PAL4: zvmlinux
-	cp zvmlinux ../images/zImage.pal4
+	mv zvmlinux ../images/zImage.pal4
 
 zImage.initrd-PAL4: zvmlinux.initrd
-	cp zvmlinux.initrd ../images/zImage.initrd.pal4
+	mv zvmlinux.initrd ../images/zImage.initrd.pal4
 
 zImage-PPLUS: zvmlinux $(MKPREP) $(MKBUGBOOT)
 	$(MKPREP) -pbp zvmlinux ../images/zImage.pplus
diff -urN linux-2.4.23-pre3/arch/ppc/kernel/head_4xx.S linux-2.4.23-pre4/arch/ppc/kernel/head_4xx.S
--- linux-2.4.23-pre3/arch/ppc/kernel/head_4xx.S	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.23-pre4/arch/ppc/kernel/head_4xx.S	2003-09-12 12:44:35.000000000 -0700
@@ -304,6 +304,7 @@
 	 */
 	li	r22, 0x0ce2
 	andc	r21, r21, r22		/* Make sure 20, 21 are zero */
+	ori	r21, r21, _PAGE_HWEXEC	/* make it executable */
 
 	/* find the TLB index that caused the fault.  It has to be here.
 	*/
@@ -782,6 +783,7 @@
 	stw	r23, tlb_4xx_index@l(0)
 
 6:
+	ori	r21, r21, _PAGE_HWEXEC		/* make it executable */
 	tlbwe	r21, r23, TLB_DATA		/* Load TLB LO */
 
 	/* Create EPN.  This is the faulting address plus a static
diff -urN linux-2.4.23-pre3/arch/ppc/kernel/traps.c linux-2.4.23-pre4/arch/ppc/kernel/traps.c
--- linux-2.4.23-pre3/arch/ppc/kernel/traps.c	2003-09-12 12:44:32.000000000 -0700
+++ linux-2.4.23-pre4/arch/ppc/kernel/traps.c	2003-09-12 12:44:35.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/ppc/kernel/traps.c
+ *  arch/ppc/kernel/traps.c
  *
  *  Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
  *
@@ -173,6 +173,10 @@
 #define REASON_PRIVILEGED	ESR_PPR
 #define REASON_TRAP		ESR_PTR
 
+/* single-step stuff */
+#define single_stepping(regs)	(current->thread.dbcr0 & DBCR0_IC)
+#define clear_single_step(regs)	(current->thread.dbcr0 &= ~DBCR0_IC)
+
 #else
 /* On non-4xx, the reason for the machine check or program
    exception is in the MSR. */
@@ -181,6 +185,9 @@
 #define REASON_ILLEGAL		0x80000
 #define REASON_PRIVILEGED	0x40000
 #define REASON_TRAP		0x20000
+
+#define single_stepping(regs)	((regs)->msr & MSR_SE)
+#define clear_single_step(regs)	((regs)->msr &= ~MSR_SE)
 #endif
 
 void
@@ -320,6 +327,22 @@
 	return retval;
 }
 
+/*
+ * After we have successfully emulated an instruction, we have to
+ * check if the instruction was being single-stepped, and if so,
+ * pretend we got a single-step exception.  This was pointed out
+ * by Kumar Gala.  -- paulus
+ */
+static void emulate_single_step(struct pt_regs *regs)
+{
+	if (single_stepping(regs)) {
+		clear_single_step(regs);
+		if (debugger_sstep(regs))
+			return;
+		_exception(SIGTRAP, regs, TRAP_TRACE, 0);
+	}
+}
+
 void
 ProgramCheckException(struct pt_regs *regs)
 {
@@ -334,8 +357,10 @@
 	 * hardware people - not sure if it can happen on any illegal
 	 * instruction or only on FP instructions, whether there is a
 	 * pattern to occurences etc. -dgibson 31/Mar/2003 */
-	if (!(reason & REASON_TRAP) && do_mathemu(regs) == 0)
+	if (!(reason & REASON_TRAP) && do_mathemu(regs) == 0) {
+		emulate_single_step(regs);
 		return;
+	}
 #endif /* CONFIG_MATH_EMULATION */
 
 	if (reason & REASON_FP) {
@@ -371,8 +396,10 @@
 
 	if (reason & REASON_PRIVILEGED) {
 		/* Try to emulate it if we should. */
-		if (emulate_instruction(regs) == 0)
+		if (emulate_instruction(regs) == 0) {
+			emulate_single_step(regs);
 			return;
+		}
 		_exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
 		return;
 	}
@@ -397,6 +424,7 @@
 	fixed = fix_alignment(regs);
 	if (fixed == 1) {
 		regs->nip += 4;	/* skip over emulated instruction */
+		emulate_single_step(regs);
 		return;
 	}
 	if (fixed == -EFAULT) {
@@ -453,7 +481,8 @@
 			_exception(SIGSEGV, regs, 0, 0);
 		else
 			_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
-	}
+	} else
+		emulate_single_step(regs);
 }
 #endif /* CONFIG_8xx */
 
diff -urN linux-2.4.23-pre3/arch/ppc/mm/44x_mmu.c linux-2.4.23-pre4/arch/ppc/mm/44x_mmu.c
--- linux-2.4.23-pre3/arch/ppc/mm/44x_mmu.c	2003-09-12 12:44:32.000000000 -0700
+++ linux-2.4.23-pre4/arch/ppc/mm/44x_mmu.c	2003-09-12 12:44:35.000000000 -0700
@@ -53,6 +53,7 @@
 #include <asm/bootx.h>
 #include <asm/machdep.h>
 #include <asm/setup.h>
+#include <asm/ibm44x.h>
 
 #include "mmu_decl.h"
 #include "mem_pieces.h"
@@ -108,7 +109,7 @@
 	 * fetch past the end of system memory that would
 	 * result in a machine check exception.
 	 */
-	if (total_lowmem | (PPC44x_PIN_SIZE - 1))
+	if (total_lowmem & (PPC44x_PIN_SIZE - 1))
 		mem_pieces_remove(&phys_avail, total_lowmem - PAGE_SIZE, PAGE_SIZE, 1);
 
 	/* Determine number of entries necessary to cover lowmem */
@@ -124,6 +125,10 @@
 			unsigned int phys_addr = (PPC44x_LOW_SLOT-i) * PPC44x_PIN_SIZE;
 			ppc44x_pin_tlb(i, phys_addr+PAGE_OFFSET, phys_addr);
 		}
+
+	/* Make sure vmalloc doesn't use virtual space covered by
+	   the last pinned TLB entry. */
+	vmalloc_start = KERNELBASE + _ALIGN(total_lowmem, PPC44x_PIN_SIZE);
 }
 
 /*
diff -urN linux-2.4.23-pre3/arch/ppc/mm/init.c linux-2.4.23-pre4/arch/ppc/mm/init.c
--- linux-2.4.23-pre3/arch/ppc/mm/init.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.23-pre4/arch/ppc/mm/init.c	2003-09-12 12:44:35.000000000 -0700
@@ -46,6 +46,31 @@
 #include "mem_pieces.h"
 #include "mmu_decl.h"
 
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 64MB value just means that there will be a 64MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ *
+ * We no longer map larger than phys RAM with the BATs so we don't have
+ * to worry about the VMALLOC_OFFSET causing problems.  We do have to worry
+ * about clashes between our early calls to ioremap() that start growing down
+ * from ioremap_base being run into the VM area allocations (growing upwards
+ * from VMALLOC_START).  For this reason we have ioremap_bot to check when
+ * we actually run into our mappings setup in the early boot with the VM
+ * system.  This really does become a problem for machines with good amounts
+ * of RAM.  -- Cort
+ */
+#ifdef CONFIG_PIN_TLB
+#define VMALLOC_OFFSET (0x2000000) /* 32M */
+#else
+#define VMALLOC_OFFSET (0x1000000) /* 16M */
+#endif
+
+unsigned long vmalloc_start;
+
 mmu_gather_t mmu_gathers[NR_CPUS];
 
 unsigned long total_memory;
@@ -313,6 +338,7 @@
 	total_lowmem = total_memory;
 	adjust_total_lowmem();
 	set_phys_avail(total_lowmem);
+	vmalloc_start = KERNELBASE + total_lowmem;
 
 	/* Initialize the MMU hardware */
 	if (ppc_md.progress)
@@ -459,6 +485,9 @@
 
 	totalram_pages += free_all_bootmem();
 
+	/* adjust vmalloc_start */
+	vmalloc_start = (vmalloc_start + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1);
+
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* if we are booted from BootX with an initial ramdisk,
 	   make sure the ramdisk pages aren't reserved. */
diff -urN linux-2.4.23-pre3/arch/ppc/platforms/ibm440gp.h linux-2.4.23-pre4/arch/ppc/platforms/ibm440gp.h
--- linux-2.4.23-pre3/arch/ppc/platforms/ibm440gp.h	2003-09-12 12:44:32.000000000 -0700
+++ linux-2.4.23-pre4/arch/ppc/platforms/ibm440gp.h	2003-09-12 12:44:35.000000000 -0700
@@ -22,7 +22,7 @@
 
 #include <linux/config.h>
 
-#include <asm/ibm4xx.h>
+#include <asm/ibm44x.h>
 
 #define EMAC_NUMS		2
 #define UART_NUMS		2
diff -urN linux-2.4.23-pre3/arch/sparc/boot/btfixupprep.c linux-2.4.23-pre4/arch/sparc/boot/btfixupprep.c
--- linux-2.4.23-pre3/arch/sparc/boot/btfixupprep.c	2001-08-28 07:09:44.000000000 -0700
+++ linux-2.4.23-pre4/arch/sparc/boot/btfixupprep.c	2003-09-12 12:44:35.000000000 -0700
@@ -167,6 +167,8 @@
 			}
 		} else if (buffer[nbase+4] != '_')
 			continue;
+		if (!strcmp (sect, ".text.exit"))
+			continue;
 		if (strcmp (sect, ".text") && strcmp (sect, ".text.init") && strcmp (sect, ".fixup") && (strcmp (sect, "__ksymtab") || buffer[nbase+3] != 'f')) {
 			if (buffer[nbase+3] == 'f')
 				fprintf(stderr, "Wrong use of '%s' in '%s' section. It can be only used in .text, .text.init, .fixup and __ksymtab\n", buffer + shift, sect);
diff -urN linux-2.4.23-pre3/arch/sparc/kernel/sys_sunos.c linux-2.4.23-pre4/arch/sparc/kernel/sys_sunos.c
--- linux-2.4.23-pre3/arch/sparc/kernel/sys_sunos.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.23-pre4/arch/sparc/kernel/sys_sunos.c	2003-09-12 12:44:35.000000000 -0700
@@ -193,7 +193,7 @@
 	 * fool it, but this should catch most mistakes.
 	 */
 	freepages = atomic_read(&buffermem_pages) >> PAGE_SHIFT;
-	freepages += atomic_read(&page_cache_size);
+	freepages += page_cache_size;
 	freepages >>= 1;
 	freepages += nr_free_pages();
 	freepages += nr_swap_pages;
diff -urN linux-2.4.23-pre3/arch/sparc64/kernel/sys_sunos32.c linux-2.4.23-pre4/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.4.23-pre3/arch/sparc64/kernel/sys_sunos32.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.23-pre4/arch/sparc64/kernel/sys_sunos32.c	2003-09-12 12:44:35.000000000 -0700
@@ -157,7 +157,7 @@
 	 * fool it, but this should catch most mistakes.
 	 */
 	freepages = atomic_read(&buffermem_pages) >> PAGE_SHIFT;
-	freepages += atomic_read(&page_cache_size);
+	freepages += page_cache_size;
 	freepages >>= 1;
 	freepages += nr_free_pages();
 	freepages += nr_swap_pages;
diff -urN linux-2.4.23-pre3/crypto/proc.c linux-2.4.23-pre4/crypto/proc.c
--- linux-2.4.23-pre3/crypto/proc.c	2003-08-25 04:44:40.000000000 -0700
+++ linux-2.4.23-pre4/crypto/proc.c	2003-09-12 12:44:35.000000000 -0700
@@ -60,6 +60,7 @@
 	
 	switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
 	case CRYPTO_ALG_TYPE_CIPHER:
+		seq_printf(m, "type         : cipher\n");
 		seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
 		seq_printf(m, "min keysize  : %u\n",
 					alg->cra_cipher.cia_min_keysize);
@@ -70,10 +71,17 @@
 		break;
 		
 	case CRYPTO_ALG_TYPE_DIGEST:
+		seq_printf(m, "type         : digest\n");
 		seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
 		seq_printf(m, "digestsize   : %u\n",
 		           alg->cra_digest.dia_digestsize);
 		break;
+	case CRYPTO_ALG_TYPE_COMPRESS:
+		seq_printf(m, "type         : compression\n");
+		break;
+	default:
+		seq_printf(m, "type         : unknown\n");
+		break;
 	}
 
 	seq_putc(m, '\n');
diff -urN linux-2.4.23-pre3/drivers/atm/he.c linux-2.4.23-pre4/drivers/atm/he.c
--- linux-2.4.23-pre3/drivers/atm/he.c	2003-09-12 12:44:32.000000000 -0700
+++ linux-2.4.23-pre4/drivers/atm/he.c	2003-09-12 12:44:35.000000000 -0700
@@ -109,10 +109,6 @@
 #define pci_get_drvdata(pci_dev)	(pci_dev)->driver_data
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44)
-#define pci_pool_create(a, b, c, d, e)	pci_pool_create(a, b, c, d, e, SLAB_KERNEL)
-#endif
-
 #include "he.h"
 
 #include "suni.h"
@@ -785,7 +781,7 @@
 	/* small buffer pool */
 #ifdef USE_RBPS_POOL
 	he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev,
-			CONFIG_RBPS_BUFSIZE, 8, 0);
+			CONFIG_RBPS_BUFSIZE, 8, 0, SLAB_KERNEL);
 	if (he_dev->rbps_pool == NULL) {
 		hprintk("unable to create rbps pages\n");
 		return -ENOMEM;
@@ -849,7 +845,7 @@
 	/* large buffer pool */
 #ifdef USE_RBPL_POOL
 	he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev,
-			CONFIG_RBPL_BUFSIZE, 8, 0);
+			CONFIG_RBPL_BUFSIZE, 8, 0, SLAB_KERNEL);
 	if (he_dev->rbpl_pool == NULL) {
 		hprintk("unable to create rbpl pool\n");
 		return -ENOMEM;
@@ -1475,7 +1471,7 @@
 
 #ifdef USE_TPD_POOL
 	he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev,
-		sizeof(struct he_tpd), TPD_ALIGNMENT, 0);
+		sizeof(struct he_tpd), TPD_ALIGNMENT, 0, SLAB_KERNEL);
 	if (he_dev->tpd_pool == NULL) {
 		hprintk("unable to create tpd pci_pool\n");
 		return -ENOMEM;         
diff -urN linux-2.4.23-pre3/drivers/block/umem.c linux-2.4.23-pre4/drivers/block/umem.c
--- linux-2.4.23-pre3/drivers/block/umem.c	2003-06-13 07:51:32.000000000 -0700
+++ linux-2.4.23-pre4/drivers/block/umem.c	2003-09-12 12:44:35.000000000 -0700
@@ -1307,7 +1307,7 @@
 	release_mem_region(card->mem_base, card->mem_len);
  failed_req_mem:
 #endif
-	iounmap((void *) card->csr_base);
+	iounmap((void *) card->csr_remap);
  failed_remap_csr:
 	release_mem_region(card->csr_base, card->csr_len);
  failed_req_csr:
diff -urN linux-2.4.23-pre3/drivers/char/Config.in linux-2.4.23-pre4/drivers/char/Config.in
--- linux-2.4.23-pre3/drivers/char/Config.in	2003-09-12 12:44:32.000000000 -0700
+++ linux-2.4.23-pre4/drivers/char/Config.in	2003-09-12 12:44:36.000000000 -0700
@@ -267,7 +267,7 @@
 fi
 dep_tristate 'NatSemi SCx200 GPIO Support' CONFIG_SCx200_GPIO $CONFIG_SCx200
 
-if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_SGI_SN2" = 'y' ] ; then
+if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_SGI_SN2" = "y" ] ; then
    bool 'SGI SN2 fetchop support' CONFIG_FETCHOP
 fi
 
diff -urN linux-2.4.23-pre3/drivers/char/hcdp_serial.c linux-2.4.23-pre4/drivers/char/hcdp_serial.c
--- linux-2.4.23-pre3/drivers/char/hcdp_serial.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.23-pre4/drivers/char/hcdp_serial.c	2003-09-12 12:44:36.000000000 -0700
@@ -219,3 +219,41 @@
 	printk("Leaving setup_serial_hcdp()\n");
 #endif
 }
+
+#ifdef CONFIG_IA64_EARLY_PRINTK_UART
+unsigned long hcdp_early_uart(void)
+{
+	efi_system_table_t *systab;
+	efi_config_table_t *config_tables;
+	hcdp_t *hcdp = 0;
+	hcdp_dev_t *dev;
+	int i;
+
+	systab = (efi_system_table_t *) ia64_boot_param->efi_systab;
+	if (!systab)
+		return 0;
+	systab = __va(systab);
+
+	config_tables = (efi_config_table_t *) systab->tables;
+	if (!config_tables)
+		return 0;
+	config_tables = __va(config_tables);
+
+	for (i = 0; i < systab->nr_tables; i++) {
+		if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
+			hcdp = (hcdp_t *) config_tables[i].table;
+			break;
+		}
+	}
+	if (!hcdp)
+		return 0;
+	hcdp = __va(hcdp);
+
+	for (i = 0, dev = hcdp->hcdp_dev; i < hcdp->num_entries; i++, dev++) {
+		if (dev->type == HCDP_DEV_CONSOLE)
+			return (u64) dev->base_addr.addrhi << 32
+				| dev->base_addr.addrlo;
+	}
+	return 0;
+}
+#endif
diff -urN linux-2.4.23-pre3/drivers/char/n_hdlc.c linux-2.4.23-pre4/drivers/char/n_hdlc.c
--- linux-2.4.23-pre3/drivers/char/n_hdlc.c	2002-02-25 11:37:57.000000000 -0800
+++ linux-2.4.23-pre4/drivers/char/n_hdlc.c	2003-09-12 12:44:36.000000000 -0700
@@ -9,7 +9,7 @@
  *	Al Longyear <longyear@netcom.com>, Paul Mackerras <Paul.Mackerras@cs.anu.edu.au>
  *
  * Original release 01/11/99
- * $Id: n_hdlc.c,v 3.3 2001/11/08 16:16:03 paulkf Exp $
+ * $Id: n_hdlc.c,v 3.7 2003/05/01 15:45:29 paulkf Exp $
  *
  * This code is released under the GNU General Public License (GPL)
  *
@@ -78,7 +78,7 @@
  */
 
 #define HDLC_MAGIC 0x239e
-#define HDLC_VERSION "$Revision: 3.3 $"
+#define HDLC_VERSION "$Revision: 3.7 $"
 
 #include <linux/version.h>
 #include <linux/config.h>
@@ -172,9 +172,9 @@
 /*
  * HDLC buffer list manipulation functions
  */
-void n_hdlc_buf_list_init(N_HDLC_BUF_LIST *list);
-void n_hdlc_buf_put(N_HDLC_BUF_LIST *list,N_HDLC_BUF *buf);
-N_HDLC_BUF* n_hdlc_buf_get(N_HDLC_BUF_LIST *list);
+static void n_hdlc_buf_list_init(N_HDLC_BUF_LIST *list);
+static void n_hdlc_buf_put(N_HDLC_BUF_LIST *list,N_HDLC_BUF *buf);
+static N_HDLC_BUF* n_hdlc_buf_get(N_HDLC_BUF_LIST *list);
 
 /* Local functions */
 
@@ -183,13 +183,16 @@
 MODULE_PARM(debuglevel, "i");
 MODULE_PARM(maxframe, "i");
 
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
 
 /* debug level can be set by insmod for debugging purposes */
 #define DEBUG_LEVEL_INFO	1
-int debuglevel=0;
+static int debuglevel=0;
 
 /* max frame size for memory allocations */
-ssize_t	maxframe=4096;
+static ssize_t	maxframe=4096;
 
 /* TTY callbacks */
 
@@ -265,7 +268,8 @@
 		} else
 			break;
 	}
-	
+	if (n_hdlc->tbuf)
+		kfree(n_hdlc->tbuf);
 	kfree(n_hdlc);
 	
 }	/* end of n_hdlc_release() */
@@ -905,7 +909,7 @@
  * Arguments:	 	list	pointer to buffer list
  * Return Value:	None	
  */
-void n_hdlc_buf_list_init(N_HDLC_BUF_LIST *list)
+static void n_hdlc_buf_list_init(N_HDLC_BUF_LIST *list)
 {
 	memset(list,0,sizeof(N_HDLC_BUF_LIST));
 	spin_lock_init(&list->spinlock);
@@ -922,7 +926,7 @@
  * 
  * Return Value:	None	
  */
-void n_hdlc_buf_put(N_HDLC_BUF_LIST *list,N_HDLC_BUF *buf)
+static void n_hdlc_buf_put(N_HDLC_BUF_LIST *list,N_HDLC_BUF *buf)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&list->spinlock,flags);
@@ -952,7 +956,7 @@
  * 
  * 	pointer to HDLC buffer if available, otherwise NULL
  */
-N_HDLC_BUF* n_hdlc_buf_get(N_HDLC_BUF_LIST *list)
+static N_HDLC_BUF* n_hdlc_buf_get(N_HDLC_BUF_LIST *list)
 {
 	unsigned long flags;
 	N_HDLC_BUF *buf;
@@ -1025,5 +1029,4 @@
 module_init(n_hdlc_init);
 module_exit(n_hdlc_exit);
 
-MODULE_LICENSE("GPL");
 EXPORT_NO_SYMBOLS;
diff -urN linux-2.4.23-pre3/drivers/char/pcmcia/synclink_cs.c linux-2.4.23-pre4/drivers/char/pcmcia/synclink_cs.c
--- linux-2.4.23-pre3/drivers/char/pcmcia/synclink_cs.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.23-pre4/drivers/char/pcmcia/synclink_cs.c	2003-09-12 12:44:36.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink_cs.c
  *
- * $Id: synclink_cs.c,v 3.4 2002/04/22 14:36:41 paulkf Exp $
+ * $Id: synclink_cs.c,v 3.10 2003/09/05 14:04:26 paulkf Exp $
  *
  * Device driver for Microgate SyncLink PC Card
  * multiprotocol serial adapter.
@@ -483,6 +483,7 @@
 
 static int debug_level = 0;
 static int maxframe[MAX_DEVICE_COUNT] = {0,};
+static int dosyncppp[MAX_DEVICE_COUNT] = {1,1,1,1};
 
 /* The old way: bit map of interrupts to choose from */
 /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
@@ -499,9 +500,14 @@
 MODULE_PARM(cuamajor,"i");
 MODULE_PARM(debug_level,"i");
 MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i");
+MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i");
+
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
 
 static char *driver_name = "SyncLink PC Card driver";
-static char *driver_version = "$Revision: 3.4 $";
+static char *driver_version = "$Revision: 3.10 $";
 
 static struct tty_driver serial_driver, callout_driver;
 static int serial_refcount;
@@ -871,6 +877,9 @@
 		printk(badmagic, kdevname(device), routine);
 		return 1;
 	}
+#else
+	if (!info)
+		return 1;
 #endif
 	return 0;
 }
@@ -2616,14 +2625,17 @@
 {
 	MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
 
-	if (!info || mgslpc_paranoia_check(info, tty->device, "mgslpc_close"))
+	if (mgslpc_paranoia_check(info, tty->device, "mgslpc_close"))
 		return;
 	
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
 			 __FILE__,__LINE__, info->device_name, info->count);
 			 
-	if (!info->count || tty_hung_up_p(filp))
+	if (!info->count)
+		return;
+
+	if (tty_hung_up_p(filp))
 		goto cleanup;
 			
 	if ((tty->count == 1) && (info->count != 1)) {
@@ -2747,7 +2759,7 @@
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
-			if (timeout && ((orig_jiffies + timeout) < jiffies))
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
 				break;
 		}
 	} else {
@@ -2757,7 +2769,7 @@
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
-			if (timeout && ((orig_jiffies + timeout) < jiffies))
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
 				break;
 		}
 	}
@@ -2937,16 +2949,11 @@
 	info = mgslpc_device_list;
 	while(info && info->line != line)
 		info = info->next_device;
-	if ( !info ){
-		printk("%s(%d):Can't find specified device on open (line=%d)\n",
-			__FILE__,__LINE__,line);
+	if (mgslpc_paranoia_check(info, tty->device, "mgslpc_open"))
 		return -ENODEV;
-	}
 	
 	tty->driver_data = info;
 	info->tty = tty;
-	if (mgslpc_paranoia_check(info, tty->device, "mgslpc_open"))
-		return -ENODEV;
 		
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
@@ -3008,6 +3015,8 @@
 	
 cleanup:			
 	if (retval) {
+		if (tty->count == 1)
+			info->tty = 0; /* tty layer will release tty struct */
 		if(MOD_IN_USE)
 			MOD_DEC_USE_COUNT;
 		if(info->count)
@@ -3181,8 +3190,7 @@
 	if (info->line < MAX_DEVICE_COUNT) {
 		if (maxframe[info->line])
 			info->max_frame_size = maxframe[info->line];
-//		info->dosyncppp = dosyncppp[info->line];
-		info->dosyncppp = 1;
+		info->dosyncppp = dosyncppp[info->line];
 	}
 
 	mgslpc_device_count++;
diff -urN linux-2.4.23-pre3/drivers/char/rocket.c linux-2.4.23-pre4/drivers/char/rocket.c
--- linux-2.4.23-pre3/drivers/char/rocket.c	2003-09-12 12:44:32.000000000 -0700
+++ linux-2.4.23-pre4/drivers/char/rocket.c	2003-09-12 12:44:36.000000000 -0700
@@ -1052,7 +1052,7 @@
 		restore_flags(flags);
 		return;
 	}
-	if ((atomic_read(&tty->count) == 1) && (info->count != 1)) {
+	if ((tty->count == 1) && (info->count != 1)) {
 		/*
 		 * Uh, oh.  tty->count is 1, which means that the tty
 		 * structure will be freed.  Info->count should always
diff -urN linux-2.4.23-pre3/drivers/char/synclink.c linux-2.4.23-pre4/drivers/char/synclink.c
--- linux-2.4.23-pre3/drivers/char/synclink.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.23-pre4/drivers/char/synclink.c	2003-09-12 12:44:36.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * linux/drivers/char/synclink.c
  *
- * $Id: synclink.c,v 3.12 2001/07/18 19:14:21 paulkf Exp $
+ * $Id: synclink.c,v 3.21 2003/09/05 14:04:24 paulkf Exp $
  *
  * Device driver for Microgate SyncLink ISA and PCI
  * high speed multiprotocol serial adapters.
@@ -198,6 +198,7 @@
 	int			flags;
 	int			count;		/* count of opens */
 	int			line;
+	int                     hw_version;
 	unsigned short		close_delay;
 	unsigned short		closing_wait;	/* time to wait before closing */
 	
@@ -270,6 +271,7 @@
 
 	int rx_enabled;
 	int rx_overflow;
+	int rx_rcc_underrun;
 
 	int tx_enabled;
 	int tx_active;
@@ -922,7 +924,7 @@
 MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
 
 static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 3.12 $";
+static char *driver_version = "$Revision: 3.21 $";
 
 static int __init synclink_init_one (struct pci_dev *dev,
 				     const struct pci_device_id *ent);
@@ -930,17 +932,20 @@
 
 static struct pci_device_id synclink_pci_tbl[] __devinitdata = {
 	{ PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_MICROGATE, 0x0210, PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0, }, /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, synclink_pci_tbl);
 
+#ifdef MODULE_LICENSE
 MODULE_LICENSE("GPL");
+#endif
 
 static struct pci_driver synclink_pci_driver = {
 	name:		"synclink",
 	id_table:	synclink_pci_tbl,
 	probe:		synclink_init_one,
-	remove:		__devexit_p(synclink_remove_one),
+	remove:		synclink_remove_one,
 };
 
 static struct tty_driver serial_driver, callout_driver;
@@ -999,6 +1004,9 @@
 		printk(badmagic, kdevname(device), routine);
 		return 1;
 	}
+#else
+	if (!info)
+		return 1;
 #endif
 	return 0;
 }
@@ -1140,8 +1148,16 @@
 	if ( debug_level >= DEBUG_LEVEL_BH )
 		printk( "%s(%d):mgsl_bh_receive(%s)\n",
 			__FILE__,__LINE__,info->device_name);
-	
-	while( (get_rx_frame)(info) );
+	do
+	{
+		if (info->rx_rcc_underrun) {
+			unsigned long flags;
+			spin_lock_irqsave(&info->irq_spinlock,flags);
+			usc_start_receiver(info);
+			spin_unlock_irqrestore(&info->irq_spinlock,flags);
+			return;
+		}
+	} while(get_rx_frame(info));
 }
 
 void mgsl_bh_transmit(struct mgsl_struct *info)
@@ -1583,6 +1599,21 @@
 	if ( debug_level >= DEBUG_LEVEL_ISR )	
 		printk("%s(%d):mgsl_isr_misc status=%04X\n",
 			__FILE__,__LINE__,status);
+
+	if ((status & MISCSTATUS_RCC_UNDERRUN) &&
+	    (info->params.mode == MGSL_MODE_HDLC)) {
+
+		/* turn off receiver and rx DMA */
+		usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
+		usc_DmaCmd(info, DmaCmd_ResetRxChannel);
+		usc_UnlatchRxstatusBits(info, RXSTATUS_ALL);
+		usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS);
+		usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS);
+
+		/* schedule BH handler to restart receiver */
+		info->pending_bh |= BH_RECEIVE;
+		info->rx_rcc_underrun = 1;
+	}
 			
 	usc_ClearIrqPendingBits( info, MISC );
 	usc_UnlatchMiscstatusBits( info, status );
@@ -3251,14 +3282,17 @@
 {
 	struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
 
-	if (!info || mgsl_paranoia_check(info, tty->device, "mgsl_close"))
+	if (mgsl_paranoia_check(info, tty->device, "mgsl_close"))
 		return;
 	
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgsl_close(%s) entry, count=%d\n",
 			 __FILE__,__LINE__, info->device_name, info->count);
 			 
-	if (!info->count || tty_hung_up_p(filp))
+	if (!info->count)
+		return;
+
+	if (tty_hung_up_p(filp))
 		goto cleanup;
 			
 	if ((tty->count == 1) && (info->count != 1)) {
@@ -3393,7 +3427,7 @@
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
-			if (timeout && ((orig_jiffies + timeout) < jiffies))
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
 				break;
 		}
 	} else {
@@ -3403,7 +3437,7 @@
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
-			if (timeout && ((orig_jiffies + timeout) < jiffies))
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
 				break;
 		}
 	}
@@ -3612,16 +3646,11 @@
 	info = mgsl_device_list;
 	while(info && info->line != line)
 		info = info->next_device;
-	if ( !info ){
-		printk("%s(%d):Can't find specified device on open (line=%d)\n",
-			__FILE__,__LINE__,line);
+	if (mgsl_paranoia_check(info, tty->device, "mgsl_open"))
 		return -ENODEV;
-	}
 	
 	tty->driver_data = info;
 	info->tty = tty;
-	if (mgsl_paranoia_check(info, tty->device, "mgsl_open"))
-		return -ENODEV;
 		
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):mgsl_open(%s), old ref count = %d\n",
@@ -3695,6 +3724,8 @@
 	
 cleanup:			
 	if (retval) {
+		if (tty->count == 1)
+			info->tty = 0; /* tty layer will release tty struct */
 		if(MOD_IN_USE)
 			MOD_DEC_USE_COUNT;
 		if(info->count)
@@ -3760,7 +3791,7 @@
 		if (info->icount.rxover)
 			ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover);
 		if (info->icount.rxcrc)
-			ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc);
+			ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc);
 	} else {
 		ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d",
 			      info->icount.tx, info->icount.rx);
@@ -4291,9 +4322,7 @@
 				info->get_tx_holding_index=0;
 
 			/* restart transmit timer */
-			del_timer(&info->tx_timer);
-			info->tx_timer.expires = jiffies + jiffies_from_ms(5000);
-			add_timer(&info->tx_timer);
+			mod_timer(&info->tx_timer, jiffies + jiffies_from_ms(5000));
 
 			ret = 1;
 		}
@@ -4511,12 +4540,12 @@
 		info->max_frame_size = 65535;
 	
 	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		printk( "SyncLink device %s added:PCI bus IO=%04X IRQ=%d Mem=%08X LCR=%08X MaxFrameSize=%u\n",
-			info->device_name, info->io_base, info->irq_level,
+		printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n",
+			info->hw_version + 1, info->device_name, info->io_base, info->irq_level,
 			info->phys_memory_base, info->phys_lcr_base,
 		     	info->max_frame_size );
 	} else {
-		printk( "SyncLink device %s added:ISA bus IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n",
+		printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n",
 			info->device_name, info->io_base, info->irq_level, info->dma_level,
 		     	info->max_frame_size );
 	}
@@ -5367,7 +5396,11 @@
 	usc_EnableMasterIrqBit( info );
 
 	usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA +
-				TRANSMIT_STATUS + TRANSMIT_DATA );
+				TRANSMIT_STATUS + TRANSMIT_DATA + MISC);
+
+	/* arm RCC underflow interrupt */
+	usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3));
+	usc_EnableInterrupts(info, MISC);
 
 	info->mbre_bit = 0;
 	outw( 0, info->io_base ); 			/* clear Master Bus Enable (DCAR) */
@@ -5375,10 +5408,11 @@
 	info->mbre_bit = BIT8;
 	outw( BIT8, info->io_base );			/* set Master Bus Enable (DCAR) */
 
-	/* Enable DMAEN (Port 7, Bit 14) */
-	/* This connects the DMA request signal to the ISA bus */
-	/* on the ISA adapter. This has no effect for the PCI adapter */
-	usc_OutReg( info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14) );
+	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
+		/* Enable DMAEN (Port 7, Bit 14) */
+		/* This connects the DMA request signal to the ISA bus */
+		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14));
+	}
 
 	/* DMA Control Register (DCR)
 	 *
@@ -5804,6 +5838,7 @@
 
 	info->rx_enabled = 0;
 	info->rx_overflow = 0;
+	info->rx_rcc_underrun = 0;
 	
 }	/* end of stop_receiver() */
 
@@ -6355,10 +6390,11 @@
 
 	usc_EnableMasterIrqBit( info );
 
-	/* Enable INTEN (Port 6, Bit12) */
-	/* This connects the IRQ request signal to the ISA bus */
-	/* on the ISA adapter. This has no effect for the PCI adapter */
-	usc_OutReg( info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12) );
+	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
+		/* Enable INTEN (Port 6, Bit12) */
+		/* This connects the IRQ request signal to the ISA bus */
+		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
+	}
 
 }	/* end of usc_set_async_mode() */
 
@@ -6449,10 +6485,11 @@
 	usc_loopback_frame( info );
 	usc_set_sdlc_mode( info );
 
-	/* Enable INTEN (Port 6, Bit12) */
-	/* This connects the IRQ request signal to the ISA bus */
-	/* on the ISA adapter. This has no effect for the PCI adapter */
-	usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
+	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
+		/* Enable INTEN (Port 6, Bit12) */
+		/* This connects the IRQ request signal to the ISA bus */
+		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
+	}
 
 	usc_enable_aux_clock(info, info->params.clock_speed);
 
@@ -7496,7 +7533,7 @@
 	EndTime = jiffies + jiffies_from_ms(100);
 
 	for(;;) {
-		if ( jiffies > EndTime ) {
+		if (time_after(jiffies, EndTime)) {
 			rc = FALSE;
 			break;
 		}
@@ -7552,7 +7589,7 @@
 	EndTime = jiffies + jiffies_from_ms(100);
 
 	for(;;) {
-		if ( jiffies > EndTime ) {
+		if (time_after(jiffies, EndTime)) {
 			rc = FALSE;
 			break;
 		}
@@ -7600,7 +7637,7 @@
 		spin_unlock_irqrestore(&info->irq_spinlock,flags);
 
 		while ( !(status & (BIT6+BIT5+BIT4+BIT2+BIT1)) ) {
-			if ( jiffies > EndTime ) {
+			if (time_after(jiffies, EndTime)) {
 				rc = FALSE;
 				break;
 			}
@@ -7627,8 +7664,7 @@
 		/* Wait for 16C32 to write receive status to buffer entry. */
 		status=info->rx_buffer_list[0].status;
 		while ( status == 0 ) {
-			if ( jiffies > EndTime ) {
-			printk(KERN_ERR"mark 4\n");
+			if (time_after(jiffies, EndTime)) {
 				rc = FALSE;
 				break;
 			}
@@ -8202,17 +8238,20 @@
 	info->bus_type = MGSL_BUS_TYPE_PCI;
 	info->io_addr_size = 8;
 	info->irq_flags = SA_SHIRQ;
-		
-	/* Store the PCI9050 misc control register value because a flaw
-	 * in the PCI9050 prevents LCR registers from being read if 
-	 * BIOS assigns an LCR base address with bit 7 set.
-	 *  
-	 * Only the misc control register is accessed for which only 
-	 * write access is needed, so set an initial value and change 
-	 * bits to the device instance data as we write the value
-	 * to the actual misc control register.
-	 */
-	info->misc_ctrl_value = 0x087e4546;
+
+	if (dev->device == 0x0210) {
+		/* Version 1 PCI9030 based universal PCI adapter */
+		info->misc_ctrl_value = 0x007c4080;
+		info->hw_version = 1;
+	} else {
+		/* Version 0 PCI9050 based 5V PCI adapter
+		 * A PCI9050 bug prevents reading LCR registers if 
+		 * LCR base address bit 7 is set. Maintain shadow
+		 * value so we can write to LCR misc control reg.
+		 */
+		info->misc_ctrl_value = 0x087e4546;
+		info->hw_version = 0;
+	}
 				
 	mgsl_add_device(info);
 
diff -urN linux-2.4.23-pre3/drivers/char/synclinkmp.c linux-2.4.23-pre4/drivers/char/synclinkmp.c
--- linux-2.4.23-pre3/drivers/char/synclinkmp.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.23-pre4/drivers/char/synclinkmp.c	2003-09-12 12:44:36.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- * $Id: synclinkmp.c,v 3.17 2002/04/22 16:05:39 paulkf Exp $
+ * $Id: synclinkmp.c,v 3.22 2003/09/05 14:04:26 paulkf Exp $
  *
  * Device driver for Microgate SyncLink Multiport
  * high speed multiprotocol serial adapter.
@@ -504,7 +504,7 @@
 MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i");
 
 static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 3.17 $";
+static char *driver_version = "$Revision: 3.22 $";
 
 static int __devinit synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
 static void __devexit synclinkmp_remove_one(struct pci_dev *dev);
@@ -515,6 +515,10 @@
 };
 MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl);
 
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
 static struct pci_driver synclinkmp_pci_driver = {
 	name:		"synclinkmp",
 	id_table:	synclinkmp_pci_tbl,
@@ -724,6 +728,9 @@
 		printk(badmagic, kdevname(device), routine);
 		return 1;
 	}
+#else
+	if (!info)
+		return 1;
 #endif
 	return 0;
 }
@@ -748,12 +755,8 @@
 	info = synclinkmp_device_list;
 	while(info && info->line != line)
 		info = info->next_device;
-	if ( !info ){
-		printk("%s(%d):%s Can't find specified device on open (line=%d)\n",
-			__FILE__,__LINE__,info->device_name,line);
+	if (sanity_check(info, tty->device, "open"))
 		return -ENODEV;
-	}
-
 	if ( info->init_error ) {
 		printk("%s(%d):%s device is not allocated, init error=%d\n",
 			__FILE__,__LINE__,info->device_name,info->init_error);
@@ -762,8 +765,6 @@
 
 	tty->driver_data = info;
 	info->tty = tty;
-	if (sanity_check(info, tty->device, "open"))
-		return -ENODEV;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):%s open(), old ref count = %d\n",
@@ -825,6 +826,8 @@
 
 cleanup:
 	if (retval) {
+		if (tty->count == 1)
+			info->tty = 0; /* tty layer will release tty struct */
 		if(MOD_IN_USE)
 			MOD_DEC_USE_COUNT;
 		if(info->count)
@@ -841,14 +844,17 @@
 {
 	SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
 
-	if (!info || sanity_check(info, tty->device, "close"))
+	if (sanity_check(info, tty->device, "close"))
 		return;
 
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("%s(%d):%s close() entry, count=%d\n",
 			 __FILE__,__LINE__, info->device_name, info->count);
 
-	if (!info->count || tty_hung_up_p(filp))
+	if (!info->count)
+		return;
+
+	if (tty_hung_up_p(filp))
 		goto cleanup;
 
 	if ((tty->count == 1) && (info->count != 1)) {
@@ -1203,7 +1209,7 @@
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
-			if (timeout && ((orig_jiffies + timeout) < jiffies))
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
 				break;
 		}
 	} else {
@@ -1214,7 +1220,7 @@
 			schedule_timeout(char_time);
 			if (signal_pending(current))
 				break;
-			if (timeout && ((orig_jiffies + timeout) < jiffies))
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
 				break;
 		}
 	}
diff -urN linux-2.4.23-pre3/drivers/scsi/scsi_scan.c linux-2.4.23-pre4/drivers/scsi/scsi_scan.c
--- linux-2.4.23-pre3/drivers/scsi/scsi_scan.c	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/drivers/scsi/scsi_scan.c	2003-09-12 12:44:39.000000000 -0700
@@ -205,6 +205,7 @@
 	{"HP", "C7200", "*", BLIST_SPARSELUN},			/* Medium Changer */
 	{"SMSC", "USB 2 HS", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, 
 	{"XYRATEX", "RS", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"NEC", "iStorage", "*", BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN},
 
 	/*
 	 * Must be at end of list...
diff -urN linux-2.4.23-pre3/drivers/sound/i810_audio.c linux-2.4.23-pre4/drivers/sound/i810_audio.c
--- linux-2.4.23-pre3/drivers/sound/i810_audio.c	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/drivers/sound/i810_audio.c	2003-09-12 12:44:39.000000000 -0700
@@ -2727,7 +2727,7 @@
 		      i810_ac97_get(codec, AC97_POWER_CONTROL) & ~0x7f00);
 
 	/* wait for analog ready */
-	for (i=10; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--)
+	for (i=100; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--)
 	{
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout(HZ/20);
diff -urN linux-2.4.23-pre3/drivers/sound/ymfpci.c linux-2.4.23-pre4/drivers/sound/ymfpci.c
--- linux-2.4.23-pre3/drivers/sound/ymfpci.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.23-pre4/drivers/sound/ymfpci.c	2003-09-12 12:44:39.000000000 -0700
@@ -2474,7 +2474,6 @@
 	eid = ymfpci_codec_read(codec, AC97_EXTENDED_ID);
 	if (eid==0xFFFF) {
 		printk(KERN_WARNING "ymfpci: no codec attached ?\n");
-		goto out_kfree;
 	}
 
 	unit->ac97_features = eid;
@@ -2626,7 +2625,6 @@
  out_release_region:
 	release_mem_region(pci_resource_start(pcidev, 0), 0x8000);
  out_free:
-	ac97_release_codec(codec->ac97_codec[0]);
 	return -ENODEV;
 }
 
diff -urN linux-2.4.23-pre3/drivers/usb/acm.c linux-2.4.23-pre4/drivers/usb/acm.c
--- linux-2.4.23-pre3/drivers/usb/acm.c	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/drivers/usb/acm.c	2003-09-12 12:44:39.000000000 -0700
@@ -363,9 +363,10 @@
 
 	count = (count > acm->writesize) ? acm->writesize : count;
 
-	if (from_user)
-		copy_from_user(acm->writeurb.transfer_buffer, buf, count);
-	else
+	if (from_user) {
+		if (copy_from_user(acm->writeurb.transfer_buffer, buf, count))
+			return -EFAULT;
+	} else
 		memcpy(acm->writeurb.transfer_buffer, buf, count);
 
 	acm->writeurb.transfer_buffer_length = count;
diff -urN linux-2.4.23-pre3/drivers/usb/aiptek.c linux-2.4.23-pre4/drivers/usb/aiptek.c
--- linux-2.4.23-pre3/drivers/usb/aiptek.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.23-pre4/drivers/usb/aiptek.c	2003-09-12 12:44:39.000000000 -0700
@@ -1102,7 +1102,8 @@
 	int num;
 
 	num = (count < 64) ? count : 64;
-	copy_from_user(buf, buffer, num);
+	if (copy_from_user(buf, buffer, num))
+		return -EFAULT;
 	buf[num] = '\0';
 
 	scan = buf;
diff -urN linux-2.4.23-pre3/drivers/usb/host/uhci-debug.h linux-2.4.23-pre4/drivers/usb/host/uhci-debug.h
--- linux-2.4.23-pre3/drivers/usb/host/uhci-debug.h	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.23-pre4/drivers/usb/host/uhci-debug.h	2003-09-12 12:44:39.000000000 -0700
@@ -545,7 +545,8 @@
 	if (!access_ok(VERIFY_WRITE, buf, nbytes))
 		return -EINVAL;
 
-	copy_to_user(buf, up->data + pos, nbytes);
+	if (copy_to_user(buf, up->data + pos, nbytes))
+		return -EFAULT;
 
 	*ppos += nbytes;
 
diff -urN linux-2.4.23-pre3/drivers/usb/mdc800.c linux-2.4.23-pre4/drivers/usb/mdc800.c
--- linux-2.4.23-pre3/drivers/usb/mdc800.c	2003-06-13 07:51:36.000000000 -0700
+++ linux-2.4.23-pre4/drivers/usb/mdc800.c	2003-09-12 12:44:39.000000000 -0700
@@ -726,7 +726,8 @@
 		else
 		{
 			/* memcpy Bytes */
-			copy_to_user(ptr, &mdc800->out [mdc800->out_ptr], sts);
+			if (copy_to_user(ptr, &mdc800->out [mdc800->out_ptr], sts))
+				return -EFAULT;
 			ptr+=sts;
 			left-=sts;
 			mdc800->out_ptr+=sts;
diff -urN linux-2.4.23-pre3/drivers/usb/serial/pl2303.c linux-2.4.23-pre4/drivers/usb/serial/pl2303.c
--- linux-2.4.23-pre3/drivers/usb/serial/pl2303.c	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/drivers/usb/serial/pl2303.c	2003-09-12 12:44:40.000000000 -0700
@@ -153,7 +153,8 @@
 	.shutdown =		pl2303_shutdown,
 };
 
-struct pl2303_private { 
+struct pl2303_private {
+	spinlock_t lock;
 	u8 line_control;
 	u8 line_status;
 	u8 termios_initialized;
@@ -170,7 +171,8 @@
 		if (!priv)
 			return -ENOMEM;
 		memset (priv, 0x00, sizeof (struct pl2303_private));
-		serial->port[i].private = priv;
+		spin_lock_init(&priv->lock);
+		usb_set_serial_port_data(&serial->port[i], priv);
 	}
 	return 0;
 }
@@ -223,25 +225,30 @@
 static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios)
 {
 	struct usb_serial *serial = port->serial;
-	struct pl2303_private *priv;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
 	unsigned int cflag;
 	unsigned char *buf;
 	int baud;
 	int i;
+	u8 control;
 
 	dbg("%s -  port %d, initialized = %d", __FUNCTION__, port->number, 
-	     ((struct pl2303_private *) port->private)->termios_initialized);
+	     priv->termios_initialized);
 
 	if ((!port->tty) || (!port->tty->termios)) {
 		dbg("%s - no tty structures", __FUNCTION__);
 		return;
 	}
 
-	if (!(((struct pl2303_private *) port->private)->termios_initialized)) {
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!priv->termios_initialized) {
 		*(port->tty->termios) = tty_std_termios;
 		port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-		((struct pl2303_private *) port->private)->termios_initialized = 1;
+		priv->termios_initialized = 1;
 	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
 	cflag = port->tty->termios->c_cflag;
 	/* check that they really want us to change something */
 	if (old_termios) {
@@ -341,13 +348,19 @@
 			     0, 0, buf, 7, 100);
 	dbg ("0x21:0x20:0:0  %d", i);
 
-	if (cflag && CBAUD) {
-		priv = port->private;
-		if ((cflag && CBAUD) == B0)
-			priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
-		else
-			priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
-		set_control_lines (serial->dev, priv->line_control);
+	/* change control lines if we are switching to or from B0 */
+	spin_lock_irqsave(&priv->lock, flags);
+	control = priv->line_control;
+	if ((cflag & CBAUD) == B0)
+		priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+	else
+		priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+	if (control != priv->line_control) {
+		control = priv->line_control;
+		spin_unlock_irqrestore(&priv->lock, flags);
+		set_control_lines(serial->dev, control);
+	} else {
+		spin_unlock_irqrestore(&priv->lock, flags);
 	}
 	
 	buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
@@ -381,6 +394,9 @@
 		
 	dbg("%s -  port %d", __FUNCTION__, port->number);
 
+	usb_clear_halt(serial->dev, port->write_urb->pipe);
+	usb_clear_halt(serial->dev, port->read_urb->pipe);
+
 #define FISH(a,b,c,d)								\
 	result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0),	\
 			       b, a, c, d, buf, 1, 100);			\
@@ -432,6 +448,7 @@
 {
 	struct usb_serial *serial;
 	struct pl2303_private *priv;
+	unsigned long flags;
 	unsigned int c_cflag;
 	int result;
 
@@ -448,10 +465,11 @@
 			c_cflag = port->tty->termios->c_cflag;
 			if (c_cflag & HUPCL) {
 				/* drop DTR and RTS */
-				priv = port->private;
+				priv = usb_get_serial_port_data(port);
+				spin_lock_irqsave(&priv->lock, flags);
 				priv->line_control = 0;
-				set_control_lines (port->serial->dev,
-						   priv->line_control);
+				spin_unlock_irqrestore (&priv->lock, flags);
+				set_control_lines (port->serial->dev, 0);
 			}
 		}
 
@@ -479,12 +497,15 @@
 
 static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsigned int *value)
 {
-	struct pl2303_private *priv = port->private;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
 	unsigned int arg;
+	u8 control;
 
 	if (copy_from_user(&arg, value, sizeof(int)))
 		return -EFAULT;
 
+	spin_lock_irqsave (&priv->lock, flags);
 	switch (cmd) {
 		case TIOCMBIS:
 			if (arg & TIOCM_RTS)
@@ -508,17 +529,25 @@
 			priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0);
 			break;
 	}
+	control = priv->line_control;
+	spin_unlock_irqrestore (&priv->lock, flags);
 
-	return set_control_lines (port->serial->dev, priv->line_control);
+	return set_control_lines (port->serial->dev, control);
 }
 
 static int get_modem_info (struct usb_serial_port *port, unsigned int *value)
 {
-	struct pl2303_private *priv = port->private;
-	unsigned int mcr = priv->line_control;
-	unsigned int status = priv->line_status;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
+	unsigned long flags;
+	unsigned int mcr;
+	unsigned int status;
 	unsigned int result;
 
+	spin_lock_irqsave (&priv->lock, flags);
+	mcr = priv->line_control;
+	status = priv->line_status;
+	spin_unlock_irqrestore (&priv->lock, flags);
+
 	result = ((mcr & CONTROL_DTR)		? TIOCM_DTR : 0)
 		  | ((mcr & CONTROL_RTS)	? TIOCM_RTS : 0)
 		  | ((status & UART_CTS)	? TIOCM_CTS : 0)
@@ -557,7 +586,6 @@
 	return -ENOIOCTLCMD;
 }
 
-
 static void pl2303_break_ctl (struct usb_serial_port *port, int break_state)
 {
 	struct usb_serial *serial = port->serial;
@@ -586,8 +614,10 @@
 
 	dbg("%s", __FUNCTION__);
 
-	for (i = 0; i < serial->num_ports; ++i)
-		kfree (serial->port[i].private);
+	for (i = 0; i < serial->num_ports; ++i) {
+		kfree (usb_get_serial_port_data(&serial->port[i]));
+		usb_set_serial_port_data(&serial->port[i], NULL);
+	}		
 }
 
 
@@ -595,17 +625,30 @@
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
-	struct pl2303_private *priv = port->private;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	unsigned char *data = urb->transfer_buffer;
+	unsigned long flags;
+
+	dbg("%s (%d)", __FUNCTION__, port->number);
 
 	/* ints auto restart... */
 
-	if (!serial) {
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
 		return;
 	}
 
-	if (urb->status) {
-		urb->status = 0;
+	if (!serial) {
 		return;
 	}
 
@@ -615,7 +658,9 @@
 		return;
 
 	/* Save off the uart status for others to look at */
+	spin_lock_irqsave(&priv->lock, flags);
 	priv->line_status = data[UART_STATE];
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return;
 }
@@ -625,9 +670,10 @@
 {
 	struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
 	struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
-	struct pl2303_private *priv = port->private;
+	struct pl2303_private *priv = usb_get_serial_port_data(port);
 	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
+	unsigned long flags;
 	int i;
 	int result;
 	u8 status;
@@ -667,7 +713,10 @@
 
 	/* get tty_flag from status */
 	tty_flag = TTY_NORMAL;
+
+	spin_lock_irqsave(&priv->lock, flags);
 	status = priv->line_status;
+	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* break takes precedence over parity, */
 	/* which takes precedence over framing errors */
@@ -742,9 +791,14 @@
 
 static int __init pl2303_init (void)
 {
-	usb_serial_register (&pl2303_device);
+	int retval;
+	retval = usb_serial_register(&pl2303_device);
+	if (retval)
+		goto failed_usb_serial_register;
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
+failed_usb_serial_register:
+	return retval;
 }
 
 
diff -urN linux-2.4.23-pre3/drivers/usb/serial/usb-serial.h linux-2.4.23-pre4/drivers/usb/serial/usb-serial.h
--- linux-2.4.23-pre3/drivers/usb/serial/usb-serial.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-pre4/drivers/usb/serial/usb-serial.h	2003-09-12 12:44:40.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * USB Serial Converter driver
  *
- *	Copyright (C) 1999 - 2002
+ *	Copyright (C) 1999 - 2003
  *	    Greg Kroah-Hartman (greg@kroah.com)
  *
  *	This program is free software; you can redistribute it and/or modify
@@ -67,7 +67,7 @@
  * usb_serial_port: structure for the specific ports of a device.
  * @magic: magic number for internal validity of this pointer.
  * @serial: pointer back to the struct usb_serial owner of this port.
- * @tty: pointer to the coresponding tty for this port.
+ * @tty: pointer to the corresponding tty for this port.
  * @number: the number of the port (the minor number).
  * @interrupt_in_buffer: pointer to the interrupt in buffer for this port.
  * @interrupt_in_urb: pointer to the interrupt in struct urb for this port.
@@ -118,6 +118,16 @@
 	struct semaphore	sem;
 	void *			private;
 };
+/* get and set the port private data pointer helper functions */
+static inline void *usb_get_serial_port_data (struct usb_serial_port *port)
+{
+	return port->private;
+}
+
+static inline void usb_set_serial_port_data (struct usb_serial_port *port, void *data)
+{
+	port->private = data;
+}
 
 /**
  * usb_serial - structure used by the usb-serial core for a device
@@ -156,6 +166,16 @@
 
 #define NUM_DONT_CARE	(-1)
 
+/* get and set the serial private data pointer helper functions */
+static inline void *usb_get_serial_data (struct usb_serial *serial)
+{
+	return serial->private;
+}
+
+static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
+{
+	serial->private = data;
+}
 
 /**
  * usb_serial_device_type - a structure that defines a usb serial device
@@ -292,7 +312,7 @@
 	if (!port || 
 		port_paranoia_check (port, function) ||
 		serial_paranoia_check (port->serial, function)) {
-		/* then say that we dont have a valid usb_serial thing, which will
+		/* then say that we don't have a valid usb_serial thing, which will
 		 * end up genrating -ENODEV return values */ 
 		return NULL;
 	}
@@ -318,7 +338,7 @@
 
 /* Use our own dbg macro */
 #undef dbg
-#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
+#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg); } while (0)
 
 
 
diff -urN linux-2.4.23-pre3/drivers/usb/serial/usbserial.c linux-2.4.23-pre4/drivers/usb/serial/usbserial.c
--- linux-2.4.23-pre3/drivers/usb/serial/usbserial.c	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/drivers/usb/serial/usbserial.c	2003-09-12 12:44:40.000000000 -0700
@@ -556,7 +556,10 @@
 		else
 			generic_close(port, filp);
 		port->open_count = 0;
-		port->tty = NULL;
+		if (port->tty) {
+			port->tty->driver_data = NULL;
+			port->tty = NULL;
+		}
 	}
 
 	if (port->serial->type->owner)
@@ -1401,12 +1404,9 @@
 		for (i = 0; i < serial->num_ports; ++i) {
 			port = &serial->port[i];
 			down (&port->sem);
-			if (port->tty != NULL) {
-				while (port->open_count > 0) {
+			if (port->tty != NULL)
+				while (port->open_count > 0)
 					__serial_close(port, NULL);
-				}
-				port->tty->driver_data = NULL;
-			}
 			up (&port->sem);
 		}
 
diff -urN linux-2.4.23-pre3/drivers/usb/storage/unusual_devs.h linux-2.4.23-pre4/drivers/usb/storage/unusual_devs.h
--- linux-2.4.23-pre3/drivers/usb/storage/unusual_devs.h	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/drivers/usb/storage/unusual_devs.h	2003-09-12 12:44:40.000000000 -0700
@@ -618,6 +618,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
+/* Submitted by Joris Struyve <joris@struyve.be> */
+UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff,
+		"Medion",
+		"MD 7425",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_INQUIRY),
+
 /* Reported by Kevin Cernekee <kpc-usbdev@gelato.uiuc.edu>
  * Tested on hardware version 1.10.
  * Entry is needed only for the initializer function override.
diff -urN linux-2.4.23-pre3/drivers/usb/stv680.c linux-2.4.23-pre4/drivers/usb/stv680.c
--- linux-2.4.23-pre3/drivers/usb/stv680.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-pre4/drivers/usb/stv680.c	2003-09-12 12:44:40.000000000 -0700
@@ -1243,7 +1243,6 @@
 				PDEBUG (2, "STV(e): VIDIOCSPICT failed");
 				return -EFAULT;
 			}
-			copy_from_user (&p, arg, sizeof (p));
 			PDEBUG (2, "STV(i): palette set to %i in VIDIOSPICT", p.palette);
 
 			if (stv680_set_pict (stv680, &p))
diff -urN linux-2.4.23-pre3/drivers/usb/vicam.c linux-2.4.23-pre4/drivers/usb/vicam.c
--- linux-2.4.23-pre3/drivers/usb/vicam.c	2003-08-25 04:44:42.000000000 -0700
+++ linux-2.4.23-pre4/drivers/usb/vicam.c	2003-09-12 12:44:40.000000000 -0700
@@ -969,18 +969,20 @@
 			if (cam->framebuf_read_start + count <=
 			    cam->framebuf_size) {
 				// count does not exceed available bytes
-				copy_to_user(buf,
-					     (cam->framebuf) +
-					     cam->framebuf_read_start, count);
+				if (copy_to_user(buf,
+						 (cam->framebuf) +
+						 cam->framebuf_read_start, count))
+					return -EFAULT;
 				cam->framebuf_read_start += count;
 				return count;
 			} else {
 				count =
 				    cam->framebuf_size -
 				    cam->framebuf_read_start;
-				copy_to_user(buf,
-					     (cam->framebuf) +
-					     cam->framebuf_read_start, count);
+				if (copy_to_user(buf,
+						 (cam->framebuf) +
+						 cam->framebuf_read_start, count))
+					return -EFAULT;
 				cam->framebuf_read_start = cam->framebuf_size;
 				return count;
 			}
@@ -1002,7 +1004,8 @@
 	if (count > cam->framebuf_size)
 		count = cam->framebuf_size;
 
-	copy_to_user(buf, cam->framebuf, count);
+	if (copy_to_user(buf, cam->framebuf, count))
+		return -EFAULT;
 
 	if (count != cam->framebuf_size)
 		cam->framebuf_read_start = count;
diff -urN linux-2.4.23-pre3/drivers/video/Config.in linux-2.4.23-pre4/drivers/video/Config.in
--- linux-2.4.23-pre3/drivers/video/Config.in	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/drivers/video/Config.in	2003-09-12 12:44:40.000000000 -0700
@@ -147,6 +147,9 @@
 	 if [ "$CONFIG_FB_ATY" != "n" ]; then
 	    bool '    Mach64 GX support (EXPERIMENTAL)' CONFIG_FB_ATY_GX
 	    bool '    Mach64 CT/VT/GT/LT (incl. 3D RAGE) support' CONFIG_FB_ATY_CT
+            if [ "$ARCH" = "i386" -a "$CONFIG_FB_ATY_CT" != "n" ]; then
+              bool '    Mach64 generic LCD monitor support (EXPERIMENTAL)' CONFIG_FB_ATY_GENERIC_LCD
+            fi
 	 fi
  	 tristate '  ATI Radeon display support (EXPERIMENTAL)' CONFIG_FB_RADEON
 	 tristate '  ATI Rage128 display support (EXPERIMENTAL)' CONFIG_FB_ATY128
diff -urN linux-2.4.23-pre3/drivers/video/aty/atyfb.h linux-2.4.23-pre4/drivers/video/aty/atyfb.h
--- linux-2.4.23-pre3/drivers/video/aty/atyfb.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-pre4/drivers/video/aty/atyfb.h	2003-09-12 12:44:40.000000000 -0700
@@ -4,7 +4,8 @@
  */
 
 #include <linux/config.h>
-
+#include <linux/sched.h>
+#include <linux/compiler.h>
 
     /*
      *  Elements of the hardware specific atyfb_par structure
@@ -15,7 +16,6 @@
     u32 vyres;
     u32 xoffset;
     u32 yoffset;
-    u32 bpp;
     u32 h_tot_disp;
     u32 h_sync_strt_wid;
     u32 v_tot_disp;
@@ -24,6 +24,17 @@
     u32 gen_cntl;
     u32 dp_pix_width;	/* acceleration */
     u32 dp_chain_mask;	/* acceleration */
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+    u32 monitors_enabled; /* LCD monitor support */
+    u16 h_stretching;     /* LCD monitor support */
+    u16 v_stretching;     /* LCD monitor support */
+#endif
+    u8 bpp;
+    u8 h_blank_start;
+    u8 h_blank_end;
+    u16 v_blank_start;
+    u8 v_blank_end;
+    u8 genmo;
 };
 
 struct pll_514 {
@@ -40,16 +51,17 @@
 };
 
 struct pll_ct {
-    u8 pll_ref_div;
-    u8 pll_gen_cntl;
-    u8 mclk_fb_div;
+//    u8 pll_ref_div;
+//    u8 pll_gen_cntl;
+//    u8 mclk_fb_div;
     u8 pll_vclk_cntl;
     u8 vclk_post_div;
     u8 vclk_fb_div;
-    u8 pll_ext_cntl;
+//    u8 alt_post_div;
+//    u8 pll_ext_cntl;
     u32 dsp_config;	/* Mach64 GTB DSP */
     u32 dsp_on_off;	/* Mach64 GTB DSP */
-    u8 mclk_post_div_real;
+//    u8 mclk_post_div_real;
     u8 vclk_post_div_real;
 };
 
@@ -89,11 +101,42 @@
 struct fb_info_aty {
     struct fb_info fb_info;
     struct fb_info_aty *next;
+    u32* ati_regaddr[256];
     unsigned long ati_regbase_phys;
     unsigned long ati_regbase;
     unsigned long frame_buffer_phys;
     unsigned long frame_buffer;
     unsigned long clk_wr_offset;
+#ifdef CONFIG_FB_ATY_CT
+    u8 pll_ref_div;
+    u8 xclk_post_div_real;
+    u16 mclk_fb_div;
+    u8 fifo_size;
+    u8 dsp_loop_latency;
+//    u8 page_size;
+    u8 xclkpagefaultdelay,xclkmaxrasdelay;
+#endif
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+    unsigned long bios_base_phys;
+    unsigned long bios_base;
+    unsigned long lcd_table;
+    u16 lcd_width;
+    u16 lcd_height;
+    u32 lcd_pixclock;
+    u16 lcd_htotal;
+    u16 lcd_hdisp;
+    u16 lcd_hsync_start;
+    u16 lcd_hsync_delay;
+    u16 lcd_hsync_width;
+    u16 lcd_vtotal;
+    u16 lcd_vdisp;
+    u16 lcd_vsync_start;
+    u16 lcd_vsync_width;
+    u16 lcd_right;
+    u16 lcd_lower;
+    u16 lcd_hblank_width;
+    u16 lcd_vblank_width;
+#endif
     struct pci_mmap_map *mmap_map;
     struct aty_cursor *cursor;
     struct aty_cmap_regs *aty_cmap_regs;
@@ -105,6 +148,7 @@
     u32 ref_clk_per;
     u32 pll_per;
     u32 mclk_per;
+    u32 xclk_per;
     u8 bus_type;
     u8 ram_type;
     u8 mem_refresh_rate;
@@ -124,6 +168,7 @@
 #endif
     } fbcon_cmap;
     u8 blitter_may_be_busy;
+    u8 font_loaded;
 #ifdef __sparc__
     u8 mmaped;
     int open;
@@ -164,6 +209,12 @@
 #define M64F_LT_SLEEP		0x00040000
 #define M64F_XL_DLL		0x00080000
 
+#ifdef __i386__
+#   define stdcall	__attribute__ ((stdcall))
+#else
+#   define stdcall
+#endif
+#define packed		__attribute__ ((packed))
 
     /*
      *  Register access
@@ -172,70 +223,72 @@
 static inline u32 aty_ld_le32(int regindex,
 			      const struct fb_info_aty *info)
 {
-    /* Hack for bloc 1, should be cleanly optimized by compiler */
-    if (regindex >= 0x400)
-	regindex -= 0x800;
+    if (regindex >= 0x400) {
+        regindex -= 0x800;
+#if defined(__mc68000__)
+        return le32_to_cpu(*((volatile u32 *)(info->ati_regbase+regindex)));
+#else
+        return readl (info->ati_regbase + regindex);
+#endif
+    } else {
+#if defined(__mc68000__)
+        return le32_to_cpu(*((volatile u32 *)(info->ati_regaddr[regindex/4])));
+#else
+        return readl (info->ati_regaddr[regindex/4]);
+#endif
+    };
+}
 
-#ifdef CONFIG_ATARI
-    return in_le32((volatile u32 *)(info->ati_regbase+regindex));
+static inline void aty_st_le32_sr(int regindex, u32 val,
+			         const struct fb_info_aty *info)
+{
+#if defined(__mc68000__)
+    *((volatile u32 *)(info->ati_regaddr[regindex/4])) = cpu_to_le32(val);
 #else
-    return readl (info->ati_regbase + regindex);
+    writel (val,info->ati_regaddr[regindex/4]);
 #endif
 }
 
 static inline void aty_st_le32(int regindex, u32 val,
 			       const struct fb_info_aty *info)
 {
-    /* Hack for bloc 1, should be cleanly optimized by compiler */
-    if (regindex >= 0x400)
-	regindex -= 0x800;
-
-#ifdef CONFIG_ATARI
-    out_le32 (info->ati_regbase+regindex, val);
+    if (regindex >= 0x400) {
+        regindex -= 0x800;
+#if defined(__mc68000__)
+        *((volatile u32 *)(info->ati_regbase+regindex)) = cpu_to_le32(val);
+#else
+        writel (val,info->ati_regbase + regindex);
+#endif
+    } else {
+#if defined(__mc68000__)
+        *((volatile u32 *)(info->ati_regaddr[regindex/4])) = cpu_to_le32(val);
 #else
-    writel (val, info->ati_regbase + regindex);
+        writel (val,info->ati_regaddr[regindex/4]);
 #endif
+    };
 }
 
 static inline u8 aty_ld_8(int regindex,
 			  const struct fb_info_aty *info)
 {
-    /* Hack for bloc 1, should be cleanly optimized by compiler */
     if (regindex >= 0x400)
-	regindex -= 0x800;
-
-#ifdef CONFIG_ATARI
-    return in_8 (info->ati_regbase + regindex);
-#else
+        regindex -= 0x800;
     return readb (info->ati_regbase + regindex);
-#endif
 }
 
 static inline void aty_st_8(int regindex, u8 val,
 			    const struct fb_info_aty *info)
 {
-    /* Hack for bloc 1, should be cleanly optimized by compiler */
     if (regindex >= 0x400)
-	regindex -= 0x800;
-
-#ifdef CONFIG_ATARI
-    out_8 (info->ati_regbase + regindex, val);
-#else
-    writeb (val, info->ati_regbase + regindex);
-#endif
+        regindex -= 0x800;
+    writeb (val,info->ati_regbase + regindex);
 }
 
-static inline u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
-{
-    u8 res;
-
-    /* write addr byte */
-    aty_st_8(CLOCK_CNTL + 1, (offset << 2), info);
-    /* read the register value */
-    res = aty_ld_8(CLOCK_CNTL + 2, info);
-    return res;
-}
+    /* 
+     * Mach64 CT PLL operations
+     */
 
+extern u8 aty_ld_pll(int offset, const struct fb_info_aty *info) stdcall;
 
     /*
      *  DAC operations
@@ -259,10 +312,11 @@
 
 struct aty_pll_ops {
     int (*var_to_pll)(const struct fb_info_aty *info, u32 vclk_per, u8 bpp,
-		      union aty_pll *pll);
+		      u32 xres, union aty_pll *pll);
     u32 (*pll_to_var)(const struct fb_info_aty *info,
 	    	      const union aty_pll *pll);
     void (*set_pll)(const struct fb_info_aty *info, const union aty_pll *pll);
+    void (*init_pll)(struct fb_info_aty *info);
 };
 
 extern const struct aty_pll_ops aty_pll_ati18818_1;	/* ATI 18818 */
@@ -276,8 +330,8 @@
 
 extern void aty_set_pll_ct(const struct fb_info_aty *info,
 			   const union aty_pll *pll);
-extern void aty_calc_pll_ct(const struct fb_info_aty *info,
-			    struct pll_ct *pll);
+//extern void aty_calc_pll_ct(const struct fb_info_aty *info,
+//			    struct pll_ct *pll);
 
 
     /*
@@ -297,7 +351,7 @@
 
 static inline void wait_for_fifo(u16 entries, const struct fb_info_aty *info)
 {
-    while ((aty_ld_le32(FIFO_STAT, info) & 0xffff) >
+    while (__builtin_expect((aty_ld_le32(FIFO_STAT, info) & 0xffff), 0) >
 	   ((u32)(0x8000 >> entries)));
 }
 
@@ -305,20 +359,21 @@
 {
     wait_for_fifo(16, info);
     while ((aty_ld_le32(GUI_STAT, info) & 1)!= 0);
-    info->blitter_may_be_busy = 0;
+      info->blitter_may_be_busy = 0;
 }
 
 extern void aty_reset_engine(const struct fb_info_aty *info);
 extern void aty_init_engine(const struct atyfb_par *par,
 			    struct fb_info_aty *info);
 extern void aty_rectfill(int dstx, int dsty, u_int width, u_int height,
-			 u_int color, struct fb_info_aty *info);
+                         u_int color, struct fb_info_aty *info);
 
 
     /*
      *  Text console acceleration
      */
 
+extern const struct display_switch fbcon_aty0;
 extern const struct display_switch fbcon_aty8;
 extern const struct display_switch fbcon_aty16;
 extern const struct display_switch fbcon_aty24;
diff -urN linux-2.4.23-pre3/drivers/video/aty/atyfb_base.c linux-2.4.23-pre4/drivers/video/aty/atyfb_base.c
--- linux-2.4.23-pre3/drivers/video/aty/atyfb_base.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-pre4/drivers/video/aty/atyfb_base.c	2003-09-12 12:44:40.000000000 -0700
@@ -1,10 +1,9 @@
-
 /*
  *  ATI Frame Buffer Device Driver Core
  *
- *	Copyright (C) 1997-2001  Geert Uytterhoeven
- *	Copyright (C) 1998  Bernd Harries
- *	Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
+ *      Copyright (C) 1997-2001  Geert Uytterhoeven
+ *      Copyright (C) 1998  Bernd Harries
+ *      Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
  *
  *  This driver supports the following ATI graphics chips:
  *    - ATI Mach64
@@ -15,15 +14,17 @@
  *
  *  This driver is partly based on the PowerMac console driver:
  *
- *	Copyright (C) 1996 Paul Mackerras
+ *      Copyright (C) 1996 Paul Mackerras
  *
  *  and on the PowerMac ATI/mach64 display driver:
  *
- *	Copyright (C) 1997 Michael AK Tesch
+ *      Copyright (C) 1997 Michael AK Tesch
+ *
+ *            with work by Jon Howell
+ *                         Harry AC Eaton
+ *                         Anthony Tong <atong@uiuc.edu>
  *
- *	      with work by Jon Howell
- *			   Harry AC Eaton
- *			   Anthony Tong <atong@uiuc.edu>
+ *  Generic LCD support written by Daniel Mantione
  *
  *  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
@@ -41,7 +42,7 @@
     - guess PLL and MCLK based on the original PLL register values initialized
       by the BIOS or Open Firmware (if they are initialized).
 
-						(Anyone to help with this?)
+                                                (Anyone to help with this?)
 
 ******************************************************************************/
 
@@ -110,13 +111,12 @@
 /* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs */
 /*  - must be large enough to catch all GUI-Regs   */
 /*  - must be aligned to a PAGE boundary           */
-#define GUI_RESERVE	(1 * PAGE_SIZE)
+#define GUI_RESERVE     (1 * PAGE_SIZE)
 
 
 /* FIXME: remove the FAIL definition */
 #define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
 
-
     /*
      *  The Hardware parameters for each card
      */
@@ -145,22 +145,22 @@
 static int atyfb_open(struct fb_info *info, int user);
 static int atyfb_release(struct fb_info *info, int user);
 static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *fb);
+                         struct fb_info *fb);
 static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *fb);
+                         struct fb_info *fb);
 static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *fb);
+                         struct fb_info *fb);
 static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info *fb);
+                             struct fb_info *fb);
 static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info);
+                          struct fb_info *info);
 static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info);
+                          struct fb_info *info);
 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg, int con, struct fb_info *info);
+                       u_long arg, int con, struct fb_info *info);
 #ifdef __sparc__
 static int atyfb_mmap(struct fb_info *info, struct file *file,
-		      struct vm_area_struct *vma);
+                      struct vm_area_struct *vma);
 #endif
 static int atyfb_rasterimg(struct fb_info *info, int start);
 
@@ -185,32 +185,33 @@
 #endif
 
 static void aty_set_crtc(const struct fb_info_aty *info,
-			 const struct crtc *crtc);
+                         const struct crtc *crtc);
 static int aty_var_to_crtc(const struct fb_info_aty *info,
-			   const struct fb_var_screeninfo *var,
-			   struct crtc *crtc);
+                           const struct fb_var_screeninfo *var,
+                           struct crtc *crtc, u32 *monitors_enabled);
 static int aty_crtc_to_var(const struct crtc *crtc,
-			   struct fb_var_screeninfo *var);
+                           struct fb_var_screeninfo *var);
 
 static void atyfb_set_par(const struct atyfb_par *par,
-			  struct fb_info_aty *info);
+                          struct fb_info_aty *info);
 static int atyfb_decode_var(const struct fb_var_screeninfo *var,
-			    struct atyfb_par *par,
-			    const struct fb_info_aty *info);
+                            struct atyfb_par *par,
+                            const struct fb_info_aty *info,
+                            u32 monitors_enabled);
 static int atyfb_encode_var(struct fb_var_screeninfo *var,
-			    const struct atyfb_par *par,
-			    const struct fb_info_aty *info);
+                            const struct atyfb_par *par,
+                            const struct fb_info_aty *info);
 static void set_off_pitch(struct atyfb_par *par,
-			  const struct fb_info_aty *info);
+                          const struct fb_info_aty *info);
 static int encode_fix(struct fb_fix_screeninfo *fix,
-		      const struct atyfb_par *par,
-		      const struct fb_info_aty *info);
+                      const struct atyfb_par *par,
+                      const struct fb_info_aty *info);
 static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info,
-			     int bpp, int accel);
+                             int bpp, int accel);
 static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			 u_int *transp, struct fb_info *fb);
+                         u_int *transp, struct fb_info *fb);
 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			 u_int transp, struct fb_info *fb);
+                         u_int transp, struct fb_info *fb);
 static void do_install_cmap(int con, struct fb_info *info);
 #ifdef CONFIG_PPC
 static int read_aty_sense(const struct fb_info_aty *info);
@@ -229,20 +230,20 @@
 static int currcon = 0;
 
 static struct fb_ops atyfb_ops = {
-	owner:		THIS_MODULE,
-	fb_open:	atyfb_open,
-	fb_release:	atyfb_release,
-	fb_get_fix:	atyfb_get_fix,
-	fb_get_var:	atyfb_get_var,
-	fb_set_var:	atyfb_set_var,
-	fb_get_cmap:	atyfb_get_cmap,
-	fb_set_cmap:	atyfb_set_cmap,
-	fb_pan_display:	atyfb_pan_display,
-	fb_ioctl:	atyfb_ioctl,
+        owner:          THIS_MODULE,
+        fb_open:        atyfb_open,
+        fb_release:     atyfb_release,
+        fb_get_fix:     atyfb_get_fix,
+        fb_get_var:     atyfb_get_var,
+        fb_set_var:     atyfb_set_var,
+        fb_get_cmap:    atyfb_get_cmap,
+        fb_set_cmap:    atyfb_set_cmap,
+        fb_pan_display: atyfb_pan_display,
+        fb_ioctl:       atyfb_ioctl,
 #ifdef __sparc__
-	fb_mmap:	atyfb_mmap,
+        fb_mmap:        atyfb_mmap,
 #endif
-	fb_rasterimg:	atyfb_rasterimg,
+        fb_rasterimg:   atyfb_rasterimg,
 };
 
 static char atyfb_name[16] = "ATY Mach64";
@@ -252,6 +253,7 @@
 static u32 default_vram __initdata = 0;
 static int default_pll __initdata = 0;
 static int default_mclk __initdata = 0;
+static int default_xclk __initdata = 0;
 
 #ifndef MODULE
 static char *mode_option __initdata = NULL;
@@ -308,65 +310,78 @@
     u16 pci_id, chip_type;
     u8 rev_mask, rev_val;
     const char *name;
-    int pll, mclk;
+    int pll, mclk, xclk;
     u32 features;
 } aty_chips[] __initdata = {
+    /* Note to kernel maintainers: Please resfuse any patch to change a clock rate,
+       unless someone proves that a value is incorrect for him with a dump of
+       the driver information table in the BIOS. Patches accepted in the past have
+       caused chips to be overclocked by as much as 50%!
+       
+       Even in the case the table appear to be wrong, do not simply change the value
+       in the table. Ask about the chip revision the person uses and *add* an entry.
+       It's also often a good idea to contact ATi.
+       
+       Lastly, third party board vendors might use different memory clocks
+       than ATi. No examples of this have been found yet, but it is possible.
+       
+       (Daniel Mantione, 26 June 2003)
+     */
 #ifdef CONFIG_FB_ATY_GX
     /* Mach64 GX */
-    { 0x4758, 0x00d7, 0x00, 0x00, m64n_gx,      135,  50, M64F_GX },
-    { 0x4358, 0x0057, 0x00, 0x00, m64n_cx,      135,  50, M64F_GX },
+    { 0x4758, 0x00d7, 0x00, 0x00, m64n_gx,      135,  50,  50, M64F_GX },
+    { 0x4358, 0x0057, 0x00, 0x00, m64n_cx,      135,  50,  50, M64F_GX },
 #endif /* CONFIG_FB_ATY_GX */
 
 #ifdef CONFIG_FB_ATY_CT
     /* Mach64 CT */
-    { 0x4354, 0x4354, 0x00, 0x00, m64n_ct,      135,  60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO },
-    { 0x4554, 0x4554, 0x00, 0x00, m64n_et,      135,  60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO },
+    { 0x4354, 0x4354, 0x00, 0x00, m64n_ct,      135,  60,  60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO },
+    { 0x4554, 0x4554, 0x00, 0x00, m64n_et,      135,  60,  60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO },
 
     /* Mach64 VT */
-    { 0x5654, 0x5654, 0xc7, 0x00, m64n_vta3,    170,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 },
-    { 0x5654, 0x5654, 0xc7, 0x40, m64n_vta4,    200,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_MAGIC_POSTDIV },
-    { 0x5654, 0x5654, 0x00, 0x00, m64n_vtb,     200,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 },
-    { 0x5655, 0x5655, 0x00, 0x00, m64n_vtb,     200,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL },
-    { 0x5656, 0x5656, 0x00, 0x00, m64n_vt4,     230,  83, M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP },
+    { 0x5654, 0x5654, 0xc7, 0x00, m64n_vta3,    170,  67,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 },
+    { 0x5654, 0x5654, 0xc7, 0x40, m64n_vta4,    200,  67,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_MAGIC_POSTDIV },
+    { 0x5654, 0x5654, 0x00, 0x00, m64n_vtb,     200,  67,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 },
+    { 0x5655, 0x5655, 0x00, 0x00, m64n_vtb,     200,  67,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL },
+    { 0x5656, 0x5656, 0x00, 0x00, m64n_vt4,     230,  83,  83, M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP },
 
     /* Mach64 GT (3D RAGE) */
-    { 0x4754, 0x4754, 0x07, 0x00, m64n_gt,      135,  63, M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_EXTRA_BRIGHT },
-    { 0x4754, 0x4754, 0x07, 0x01, m64n_gt,      170,  67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4754, 0x4754, 0x07, 0x02, m64n_gt,      200,  67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4755, 0x4755, 0x00, 0x00, m64n_gtb,     200,  67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4756, 0x4756, 0x00, 0x00, m64n_iic_p,   230,  83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4757, 0x4757, 0x00, 0x00, m64n_iic_a,   230,  83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x475a, 0x475a, 0x00, 0x00, m64n_iic_a,   230,  83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4754, 0x4754, 0x07, 0x00, m64n_gt,      135,  63,  63, M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_EXTRA_BRIGHT },
+    { 0x4754, 0x4754, 0x07, 0x01, m64n_gt,      170,  67,  67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4754, 0x4754, 0x07, 0x02, m64n_gt,      200,  67,  67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4755, 0x4755, 0x00, 0x00, m64n_gtb,     200,  67,  67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4756, 0x4756, 0x00, 0x00, m64n_iic_p,   230,  83,  83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4757, 0x4757, 0x00, 0x00, m64n_iic_a,   230,  83,  83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x475a, 0x475a, 0x00, 0x00, m64n_iic_a,   230,  83,  83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
 
     /* Mach64 LT */
-    { 0x4c54, 0x4c54, 0x00, 0x00, m64n_lt,      135,  63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP },
-    { 0x4c47, 0x4c47, 0x00, 0x00, m64n_ltg,     230,  63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_LT_SLEEP | M64F_G3_PB_1024x768 },
+    { 0x4c54, 0x4c54, 0x00, 0x00, m64n_lt,      135,  63,  63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP },
+    { 0x4c47, 0x4c47, 0x00, 0x00, m64n_ltg,     230,  63,  63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_LT_SLEEP | M64F_G3_PB_1024x768 },
 
     /* Mach64 GTC (3D RAGE PRO) */
-    { 0x4742, 0x4742, 0x00, 0x00, m64n_gtc_ba,  230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4744, 0x4744, 0x00, 0x00, m64n_gtc_ba1, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4749, 0x4749, 0x00, 0x00, m64n_gtc_bp,  230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_MAGIC_VRAM_SIZE },
-    { 0x4750, 0x4750, 0x00, 0x00, m64n_gtc_pp,  230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4751, 0x4751, 0x00, 0x00, m64n_gtc_ppl, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4742, 0x4742, 0x00, 0x00, m64n_gtc_ba,  230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4744, 0x4744, 0x00, 0x00, m64n_gtc_ba1, 230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4749, 0x4749, 0x00, 0x00, m64n_gtc_bp,  230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_MAGIC_VRAM_SIZE },
+    { 0x4750, 0x4750, 0x00, 0x00, m64n_gtc_pp,  230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4751, 0x4751, 0x00, 0x00, m64n_gtc_ppl, 230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
 
     /* 3D RAGE XL */
-    { 0x4752, 0x4752, 0x00, 0x00, m64n_xl, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL },
+    { 0x4752, 0x4752, 0x00, 0x00, m64n_xl,      235,  83,  63, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL },
 
     /* Mach64 LT PRO */
-    { 0x4c42, 0x4c42, 0x00, 0x00, m64n_ltp_a,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
-    { 0x4c44, 0x4c44, 0x00, 0x00, m64n_ltp_p,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
-    { 0x4c49, 0x4c49, 0x00, 0x00, m64n_ltp_p,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_EXTRA_BRIGHT | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
-    { 0x4c50, 0x4c50, 0x00, 0x00, m64n_ltp_p,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
+    { 0x4c42, 0x4c42, 0x00, 0x00, m64n_ltp_a,   236,  75, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_EXTRA_BRIGHT},
+    { 0x4c44, 0x4c44, 0x00, 0x00, m64n_ltp_p,   230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_EXTRA_BRIGHT},
+    { 0x4c49, 0x4c49, 0x00, 0x00, m64n_ltp_p,   230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_EXTRA_BRIGHT | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
+    { 0x4c50, 0x4c50, 0x00, 0x00, m64n_ltp_p,   230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_EXTRA_BRIGHT},
 
     /* 3D RAGE Mobility */
-    { 0x4c4d, 0x4c4d, 0x00, 0x00, m64n_mob_p,   230,  50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS },
-    { 0x4c4e, 0x4c4e, 0x00, 0x00, m64n_mob_a,   230,  50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS },
+    { 0x4c4d, 0x4c4d, 0x00, 0x00, m64n_mob_p,   230,  83, 125, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS | M64F_EXTRA_BRIGHT},
+    { 0x4c4e, 0x4c4e, 0x00, 0x00, m64n_mob_a,   230,  83, 125, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS | M64F_EXTRA_BRIGHT},
 #endif /* CONFIG_FB_ATY_CT */
 };
 
 #if defined(CONFIG_FB_ATY_GX) || defined(CONFIG_FB_ATY_CT)
 static char ram_dram[] __initdata = "DRAM";
-static char ram_resv[] __initdata = "RESV";
 #endif /* CONFIG_FB_ATY_GX || CONFIG_FB_ATY_CT */
 
 #ifdef CONFIG_FB_ATY_GX
@@ -379,6 +394,7 @@
 static char ram_sgram[] __initdata = "SGRAM";
 static char ram_wram[] __initdata = "WRAM";
 static char ram_off[] __initdata = "OFF";
+static char ram_resv[] __initdata = "RESV";
 #endif /* CONFIG_FB_ATY_CT */
 
 #ifdef CONFIG_FB_ATY_GX
@@ -406,39 +422,39 @@
 {
     int sense, i;
 
-    aty_st_le32(GP_IO, 0x31003100, info);	/* drive outputs high */
+    aty_st_le32(GP_IO, 0x31003100, info);       /* drive outputs high */
     __delay(200);
-    aty_st_le32(GP_IO, 0, info);		/* turn off outputs */
+    aty_st_le32(GP_IO, 0, info);                /* turn off outputs */
     __delay(2000);
-    i = aty_ld_le32(GP_IO, info);		/* get primary sense value */
+    i = aty_ld_le32(GP_IO, info);               /* get primary sense value */
     sense = ((i & 0x3000) >> 3) | (i & 0x100);
 
     /* drive each sense line low in turn and collect the other 2 */
-    aty_st_le32(GP_IO, 0x20000000, info);	/* drive A low */
+    aty_st_le32(GP_IO, 0x20000000, info);       /* drive A low */
     __delay(2000);
     i = aty_ld_le32(GP_IO, info);
     sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4);
-    aty_st_le32(GP_IO, 0x20002000, info);	/* drive A high again */
+    aty_st_le32(GP_IO, 0x20002000, info);       /* drive A high again */
     __delay(200);
 
-    aty_st_le32(GP_IO, 0x10000000, info);	/* drive B low */
+    aty_st_le32(GP_IO, 0x10000000, info);       /* drive B low */
     __delay(2000);
     i = aty_ld_le32(GP_IO, info);
     sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6);
-    aty_st_le32(GP_IO, 0x10001000, info);	/* drive B high again */
+    aty_st_le32(GP_IO, 0x10001000, info);       /* drive B high again */
     __delay(200);
 
-    aty_st_le32(GP_IO, 0x01000000, info);	/* drive C low */
+    aty_st_le32(GP_IO, 0x01000000, info);       /* drive C low */
     __delay(2000);
     sense |= (aty_ld_le32(GP_IO, info) & 0x3000) >> 12;
-    aty_st_le32(GP_IO, 0, info);		/* turn off outputs */
+    aty_st_le32(GP_IO, 0, info);                /* turn off outputs */
 
     return sense;
 }
 
 #endif /* defined(CONFIG_PPC) */
 
-#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_PMAC_BACKLIGHT)
+#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD)
 static void aty_st_lcd(int index, u32 val, const struct fb_info_aty *info)
 {
     unsigned long temp;
@@ -460,7 +476,7 @@
     /* read the register value */
     return aty_ld_le32(LCD_DATA, info);
 }
-#endif /* CONFIG_PMAC_PBOOK || CONFIG_PMAC_BACKLIGHT */
+#endif /* CONFIG_PMAC_PBOOK || CONFIG_PMAC_BACKLIGHT || CONFIG_FB_ATY_GENERIC_LCD*/
 
 /* ------------------------------------------------------------------------- */
 
@@ -469,30 +485,103 @@
      */
 
 static void aty_set_crtc(const struct fb_info_aty *info,
-			 const struct crtc *crtc)
+                         const struct crtc *crtc)
 {
+    u32 v;
+    
     aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, info);
     aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, info);
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+    /* HACK:
+     * I don't want to do this, but Geert Uytterhoeven's laptop seems to
+     * have some shadowing enabled that I don't know yet how to switch
+     * off. It is a Rage Mobility M1, but doesn't happen on these chips
+     * in general. (Daniel Mantione, 26 june 2003)
+     */
+      aty_st_lcd(aty_ld_lcd(LCD_GEN_CTRL, info) | SHADOW_RW_EN, info);
+      aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, info);
+      aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, info);
+      aty_st_lcd(aty_ld_lcd(LCD_GEN_CTRL, info) & ~SHADOW_RW_EN, info);
+    /* End hack */
+#endif
+
     aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_tot_disp, info);
     aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid, info);
     aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0, info);
     aty_st_le32(CRTC_OFF_PITCH, crtc->off_pitch, info);
     aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl, info);
+/*    printk(KERN_INFO "CRTC_GEN_CNTL: %x\n",crtc->gen_cntl);
+    printk(KERN_INFO "CRTC_H_TOTAL_DISP: %x\n",crtc->h_tot_disp);
+    printk(KERN_INFO "CRTC_H_SYNC_STRT_WID: %x\n",crtc->h_sync_strt_wid);
+    printk(KERN_INFO "CRTC_V_TOTAL_DISP: %x\n",crtc->v_tot_disp);
+    printk(KERN_INFO "CRTC_V_SYNC_STRT_WID: %x\n",crtc->v_sync_strt_wid);*/
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+    /* After setting the CRTC registers we should set the LCD
+       registers.
+     */
+    if (info->lcd_table != 0) {
+        /* Enable/disable horizontal stretching */
+        v = aty_ld_lcd(HORZ_STRETCHING, info);
+        v = v & ~(HORZ_STRETCH_RATIO | HORZ_STRETCH_EN | AUTO_HORZ_RATIO |
+	          HORZ_STRETCH_LOOP);
+        v = v | HORZ_STRETCH_MODE; /* Use interpolation instead of duplication. */
+        if (crtc->h_stretching != 0)
+            v = v | HORZ_STRETCH_EN | crtc->h_stretching;
+        aty_st_lcd(HORZ_STRETCHING, v, info);
+        /*printk(KERN_INFO "HORZ_STRETCHING: %x\n", v);*/
+        
+        /* Enable/disable vertital stretching */
+        v = aty_ld_lcd(VERT_STRETCHING, info);
+        v = v & ~(VERT_STRETCH_RATIO0 | VERT_STRETCH_EN);
+        v = v | VERT_STRETCH_USE0; /* Use VERT_STRETCH_RATIO0. */
+        if (crtc->v_stretching != 0)
+            v = v | VERT_STRETCH_EN | crtc->v_stretching;
+        aty_st_lcd(VERT_STRETCHING, v, info);
+        /*printk(KERN_INFO "VERT_STRETCHING: %x\n", v);*/
+        v = aty_ld_lcd(EXT_VERT_STRETCH, info);
+        v = v & ~AUTO_VERT_RATIO;  /* Forbit the chip to guess the vertical
+                                      expansion (used for vga compatibility) */
+        v = v | VERT_STRETCH_MODE; /* Use interpolation instead of duplication. */
+        aty_st_lcd(EXT_VERT_STRETCH, v, info);
+        /*printk(KERN_INFO "EXT_VERT_STRETCH: %x\n", v);*/
+        
+        /* Don't use shadowing. Don't divide the horizontal paramters.
+           (VGA compatibility junk that might be enabled.)
+           Enable only the monitors that were enabled before we switched the
+           video mode.
+         */
+        v = aty_ld_lcd(LCD_GEN_CTRL, info);
+        v = v & ~(HORZ_DIVBY2_EN | DISABLE_PCLK_RESET | SCLK_SEL |
+		  DIS_HOR_CRT_DIVBY2 | VCLK_DAC_PM_EN | XTALIN_PM_EN |
+		  CRTC_RW_SELECT | USE_SHADOWED_ROWCUR |
+		  USE_SHADOWED_VEND | SHADOW_EN | SHADOW_RW_EN |
+		  LCD_ON | CRT_ON);
+        v = v | DONT_SHADOW_VPAR | crtc->monitors_enabled;
+        aty_st_lcd(LCD_GEN_CTRL, v, info);
+        /*printk(KERN_INFO "LCD_GEN_CTRL: %x\n", v);*/
+        aty_st_lcd(CONFIG_PANEL, aty_ld_lcd(CONFIG_PANEL, info) |
+                                 DONT_SHADOW_HEND, info);
+    };
+#endif
 }
 
 static int aty_var_to_crtc(const struct fb_info_aty *info,
-			   const struct fb_var_screeninfo *var,
-			   struct crtc *crtc)
+                           const struct fb_var_screeninfo *var,
+                           struct crtc *crtc, u32 *monitors_enabled)
 {
-    u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
+    u32 xres, yres, ryres, vxres, vyres, xoffset, yoffset, bpp;
     u32 left, right, upper, lower, hslen, vslen, sync, vmode;
     u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
     u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
     u32 pix_width, dp_pix_width, dp_chain_mask;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+    u32 lcd_hsync_start,lcd_htotal,lcd_vsync_start,lcd_vtotal;
+#endif
 
     /* input */
     xres = var->xres;
     yres = var->yres;
+    ryres = yres;
     vxres = var->xres_virtual;
     vyres = var->yres_virtual;
     xoffset = var->xoffset;
@@ -501,6 +590,7 @@
     left = var->left_margin;
     right = var->right_margin;
     upper = var->upper_margin;
+    
     lower = var->lower_margin;
     hslen = var->hsync_len;
     vslen = var->vsync_len;
@@ -512,70 +602,82 @@
     xoffset = (xoffset+7) & ~7;
     vxres = (vxres+7) & ~7;
     if (vxres < xres+xoffset)
-	vxres = xres+xoffset;
+        vxres = xres+xoffset;
     h_disp = xres/8-1;
     if (h_disp > 0xff)
-	FAIL("h_disp too large");
+        FAIL("h_disp too large");
     h_sync_strt = h_disp+(right/8);
     if (h_sync_strt > 0x1ff)
-	FAIL("h_sync_start too large");
+        FAIL("h_sync_start too large");
     h_sync_dly = right & 7;
     h_sync_wid = (hslen+7)/8;
     if (h_sync_wid > 0x1f)
-	FAIL("h_sync_wid too large");
+        FAIL("h_sync_wid too large");
     h_total = h_sync_strt+h_sync_wid+(h_sync_dly+left+7)/8;
     if (h_total > 0x1ff)
-	FAIL("h_total too large");
+        FAIL("h_total too large");
     h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
 
     if (vyres < yres+yoffset)
-	vyres = yres+yoffset;
+        vyres = yres+yoffset;
     v_disp = yres-1;
     if (v_disp > 0x7ff)
-	FAIL("v_disp too large");
+        FAIL("v_disp too large");
     v_sync_strt = v_disp+lower;
     if (v_sync_strt > 0x7ff)
-	FAIL("v_sync_strt too large");
+        FAIL("v_sync_strt too large");
     v_sync_wid = vslen;
     if (v_sync_wid > 0x1f)
-	FAIL("v_sync_wid too large");
+        FAIL("v_sync_wid too large");
     v_total = v_sync_strt+v_sync_wid+upper;
     if (v_total > 0x7ff)
-	FAIL("v_total too large");
+        FAIL("v_total too large");
     v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
-
+    /* In double scan mode, the vertical parameters need to be doubled.
+       But in interlaced mode, there is no need to half the vertical parameters.
+       Code has been tested in 1024x768, 43 Hz interlaced and 640x480, 60 Hz
+       double scan.
+     */
+   if ((vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
+       ryres <<= 1;
+       v_total <<= 1;
+       v_disp <<= 1;
+       v_sync_strt <<= 1;
+       v_sync_wid <<= 1;
+   };
+                                                           
     c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
 
     if (bpp <= 8) {
-	bpp = 8;
-	pix_width = CRTC_PIX_WIDTH_8BPP;
-	dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
-	dp_chain_mask = 0x8080;
+        bpp = 8;
+        pix_width = CRTC_PIX_WIDTH_8BPP;
+        dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
+        dp_chain_mask = 0x8080;
     } else if (bpp <= 16) {
-	bpp = 16;
-	pix_width = CRTC_PIX_WIDTH_15BPP;
-	dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
-		       BYTE_ORDER_LSB_TO_MSB;
-	dp_chain_mask = 0x4210;
+        bpp = 16;
+        pix_width = CRTC_PIX_WIDTH_15BPP;
+        dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP |
+                       BYTE_ORDER_LSB_TO_MSB;
+        dp_chain_mask = 0x4210;
     } else if (bpp <= 24 && M64_HAS(INTEGRATED)) {
-	bpp = 24;
-	pix_width = CRTC_PIX_WIDTH_24BPP;
-	dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
-	dp_chain_mask = 0x8080;
+        bpp = 24;
+        pix_width = CRTC_PIX_WIDTH_24BPP;
+        dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
+        dp_chain_mask = 0x8080;
     } else if (bpp <= 32) {
-	bpp = 32;
-	pix_width = CRTC_PIX_WIDTH_32BPP;
-	dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
-		       BYTE_ORDER_LSB_TO_MSB;
-	dp_chain_mask = 0x8080;
+        bpp = 32;
+        pix_width = CRTC_PIX_WIDTH_32BPP;
+        dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP |
+                       BYTE_ORDER_LSB_TO_MSB;
+        dp_chain_mask = 0x8080;
     } else
-	FAIL("invalid bpp");
+        FAIL("invalid bpp");
 
     if (vxres*vyres*bpp/8 > info->total_vram)
-	FAIL("not enough video RAM");
+        FAIL("not enough video RAM");
 
-    if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-	FAIL("invalid vmode");
+//    if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+//      FAIL("invalid vmode");
 
     /* output */
     crtc->vxres = vxres;
@@ -583,18 +685,97 @@
     crtc->xoffset = xoffset;
     crtc->yoffset = yoffset;
     crtc->bpp = bpp;
-    crtc->h_tot_disp = h_total | (h_disp<<16);
-    crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |
-			    ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) |
-			    (h_sync_pol<<21);
-    crtc->v_tot_disp = v_total | (v_disp<<16);
-    crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
     crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
     crtc->gen_cntl = pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE;
+    /* Enable doublescan mode if requested */
+    if ((vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
+        crtc->gen_cntl|=CRTC_DBL_SCAN_EN;
+    /* Enable interlaced mode if requested */
+    if ((vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+        crtc->gen_cntl|=CRTC_INTERLACE_EN;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+    /* We can only program the real mode parameters to the CRTC
+       if the LCD monitor is switched off. Otherwise we will have to
+       use the parameters the LCD monitor prefers, effectively setting
+       a completely different mode which simulates the requested 
+       video mode.
+     */
+    if ((info->lcd_table != 0) && ((*monitors_enabled & LCD_ON) != 0) && 
+        ((xres > info->lcd_width) || (ryres > info->lcd_height))
+       ) {
+        /* We cannot display the mode on the LCD. If the CRT is enabled
+           we can turn off the LCD.
+           If the CRT is off, it isn't a good idea to switch it on; we don't
+           know if one is connected. So it's better to fail then.
+         */
+        if (*monitors_enabled & CRT_ON) {
+            printk(KERN_INFO "Disabling lcd monitor because video mode does not fit.\n");
+            *monitors_enabled = *monitors_enabled & (~LCD_ON);
+        } else
+            FAIL("Video mode exceeds size of lcd monitor.\nConnect this computer to a conventional monitor if you really need this mode.");
+    };
+    if ((info->lcd_table == 0) || ((*monitors_enabled & LCD_ON) == 0)) {
+#endif
+        crtc->h_tot_disp = h_total | (h_disp<<16);
+        crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) |
+                                ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) |
+                                (h_sync_pol<<21);
+        crtc->v_tot_disp = v_total | (v_disp<<16);
+        crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+        /* No hardware stretching please! */
+        crtc->h_stretching = 0;
+        crtc->v_stretching = 0;
+    } else {
+        /* This is horror! When we simulate, say 640x480 on an 800x600
+           lcd monitor, the CRTC should be programmed 800x600 values for
+           the non visible part, but 640x480 for the visible part.
+           This code has been tested on a laptop with it's 800x600 lcd
+           monitor and a conventional monitor both switched on.
+           Tested modes: 640x400, 720x400, 800x600, 320x200-doublescan,
+                         800x600-interlaced
+         */
+        lcd_htotal = h_disp + info->lcd_hblank_width;
+        lcd_hsync_start = h_disp + info->lcd_right;
+        lcd_vtotal = v_disp + info->lcd_vblank_width;
+        lcd_vsync_start = v_disp + info->lcd_lower;
+        
+        crtc->h_tot_disp = (lcd_htotal) | (h_disp<<16);
+        crtc->h_sync_strt_wid = (lcd_hsync_start & 0xff) |
+                                (info->lcd_hsync_delay<<8) |
+                                ((lcd_hsync_start & 0x100)<<4) |
+                                (info->lcd_hsync_width<<16);
+        crtc->v_tot_disp = lcd_vtotal | (v_disp<<16);
+        crtc->v_sync_strt_wid = lcd_vsync_start |
+                                (info->lcd_vsync_width<<16);
+        /* To simulate the requested video mode, we use the hardware stretcher,
+           which zooms the image to the dimensions of the LCD screen. It has
+           two modes; replication and blending. Replication duplicates some
+           pixels, blending interpolates between pixels. We use blending.
+           The formula for blending is:
+              h_stretching=(source_with/dest_width)*4096
+              v_stretching=(source_lines/dest_lines)*1024
+         */
+        if (xres != info->lcd_width)
+            crtc->h_stretching = (xres*4096)/info->lcd_width;
+        else
+            crtc->h_stretching = 0;
+        if (ryres != info->lcd_height)
+            crtc->v_stretching = (ryres*1024)/info->lcd_height;
+        else
+            crtc->v_stretching = 0;
+        /* The prefered mode for the lcd is not interlaced, so disable it if
+           it was enabled. For doublescan there is no problem, because we can
+           compensate for it in the hardware stretching (we stretch half as much)
+         */
+        crtc->gen_cntl&=~CRTC_INTERLACE_EN;
+    };
+    crtc->monitors_enabled = *monitors_enabled;
+#endif
     if (M64_HAS(MAGIC_FIFO)) {
-	/* Not VTB/GTB */
-	/* FIXME: magic FIFO values */
-	crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, info) & 0x000e0000;
+        /* Not VTB/GTB */
+        /* FIXME: magic FIFO values */
+        crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, info) & 0x000e0000;
     }
     crtc->dp_pix_width = dp_pix_width;
     crtc->dp_chain_mask = dp_chain_mask;
@@ -604,18 +785,19 @@
 
 
 static int aty_crtc_to_var(const struct crtc *crtc,
-			   struct fb_var_screeninfo *var)
+                           struct fb_var_screeninfo *var)
 {
     u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
     u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
     u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
     u32 pix_width;
-
+    u32 double_scan, interlace;
+            
     /* input */
     h_total = crtc->h_tot_disp & 0x1ff;
     h_disp = (crtc->h_tot_disp>>16) & 0xff;
     h_sync_strt = (crtc->h_sync_strt_wid & 0xff) |
-		  ((crtc->h_sync_strt_wid>>4) & 0x100);
+                  ((crtc->h_sync_strt_wid>>4) & 0x100);
     h_sync_dly = (crtc->h_sync_strt_wid>>8) & 0x7;
     h_sync_wid = (crtc->h_sync_strt_wid>>16) & 0x1f;
     h_sync_pol = (crtc->h_sync_strt_wid>>21) & 0x1;
@@ -626,7 +808,9 @@
     v_sync_pol = (crtc->v_sync_strt_wid>>21) & 0x1;
     c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
     pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
-
+    double_scan = crtc->gen_cntl & CRTC_DBL_SCAN_EN;
+    interlace = crtc->gen_cntl & CRTC_INTERLACE_EN;
+                
     /* convert */
     xres = (h_disp+1)*8;
     yres = v_disp+1;
@@ -637,82 +821,82 @@
     lower = v_sync_strt-v_disp;
     vslen = v_sync_wid;
     sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
-	   (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
-	   (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
+           (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
+           (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
 
     switch (pix_width) {
 #if 0
-	case CRTC_PIX_WIDTH_4BPP:
-	    bpp = 4;
-	    var->red.offset = 0;
-	    var->red.length = 8;
-	    var->green.offset = 0;
-	    var->green.length = 8;
-	    var->blue.offset = 0;
-	    var->blue.length = 8;
-	    var->transp.offset = 0;
-	    var->transp.length = 0;
-	    break;
-#endif
-	case CRTC_PIX_WIDTH_8BPP:
-	    bpp = 8;
-	    var->red.offset = 0;
-	    var->red.length = 8;
-	    var->green.offset = 0;
-	    var->green.length = 8;
-	    var->blue.offset = 0;
-	    var->blue.length = 8;
-	    var->transp.offset = 0;
-	    var->transp.length = 0;
-	    break;
-	case CRTC_PIX_WIDTH_15BPP:	/* RGB 555 */
-	    bpp = 16;
-	    var->red.offset = 10;
-	    var->red.length = 5;
-	    var->green.offset = 5;
-	    var->green.length = 5;
-	    var->blue.offset = 0;
-	    var->blue.length = 5;
-	    var->transp.offset = 0;
-	    var->transp.length = 0;
-	    break;
+        case CRTC_PIX_WIDTH_4BPP:
+            bpp = 4;
+            var->red.offset = 0;
+            var->red.length = 8;
+            var->green.offset = 0;
+            var->green.length = 8;
+            var->blue.offset = 0;
+            var->blue.length = 8;
+            var->transp.offset = 0;
+            var->transp.length = 0;
+            break;
+#endif
+        case CRTC_PIX_WIDTH_8BPP:
+            bpp = 8;
+            var->red.offset = 0;
+            var->red.length = 8;
+            var->green.offset = 0;
+            var->green.length = 8;
+            var->blue.offset = 0;
+            var->blue.length = 8;
+            var->transp.offset = 0;
+            var->transp.length = 0;
+            break;
+        case CRTC_PIX_WIDTH_15BPP:      /* RGB 555 */
+            bpp = 16;
+            var->red.offset = 10;
+            var->red.length = 5;
+            var->green.offset = 5;
+            var->green.length = 5;
+            var->blue.offset = 0;
+            var->blue.length = 5;
+            var->transp.offset = 0;
+            var->transp.length = 0;
+            break;
 #if 0
-	case CRTC_PIX_WIDTH_16BPP:	/* RGB 565 */
-	    bpp = 16;
-	    var->red.offset = 11;
-	    var->red.length = 5;
-	    var->green.offset = 5;
-	    var->green.length = 6;
-	    var->blue.offset = 0;
-	    var->blue.length = 5;
-	    var->transp.offset = 0;
-	    var->transp.length = 0;
-	    break;
-#endif
-	case CRTC_PIX_WIDTH_24BPP:	/* RGB 888 */
-	    bpp = 24;
-	    var->red.offset = 16;
-	    var->red.length = 8;
-	    var->green.offset = 8;
-	    var->green.length = 8;
-	    var->blue.offset = 0;
-	    var->blue.length = 8;
-	    var->transp.offset = 0;
-	    var->transp.length = 0;
-	    break;
-	case CRTC_PIX_WIDTH_32BPP:	/* ARGB 8888 */
-	    bpp = 32;
-	    var->red.offset = 16;
-	    var->red.length = 8;
-	    var->green.offset = 8;
-	    var->green.length = 8;
-	    var->blue.offset = 0;
-	    var->blue.length = 8;
-	    var->transp.offset = 24;
-	    var->transp.length = 8;
-	    break;
-	default:
-	    FAIL("Invalid pixel width");
+        case CRTC_PIX_WIDTH_16BPP:      /* RGB 565 */
+            bpp = 16;
+            var->red.offset = 11;
+            var->red.length = 5;
+            var->green.offset = 5;
+            var->green.length = 6;
+            var->blue.offset = 0;
+            var->blue.length = 5;
+            var->transp.offset = 0;
+            var->transp.length = 0;
+            break;
+#endif
+        case CRTC_PIX_WIDTH_24BPP:      /* RGB 888 */
+            bpp = 24;
+            var->red.offset = 16;
+            var->red.length = 8;
+            var->green.offset = 8;
+            var->green.length = 8;
+            var->blue.offset = 0;
+            var->blue.length = 8;
+            var->transp.offset = 0;
+            var->transp.length = 0;
+            break;
+        case CRTC_PIX_WIDTH_32BPP:      /* ARGB 8888 */
+            bpp = 32;
+            var->red.offset = 16;
+            var->red.length = 8;
+            var->green.offset = 8;
+            var->green.length = 8;
+            var->blue.offset = 0;
+            var->blue.length = 8;
+            var->transp.offset = 24;
+            var->transp.length = 8;
+            break;
+        default:
+            FAIL("Invalid pixel width");
     }
 
     /* output */
@@ -731,14 +915,30 @@
     var->vsync_len = vslen;
     var->sync = sync;
     var->vmode = FB_VMODE_NONINTERLACED;
-
+    /* In double scan mode, the vertical parameters are doubled, so we need to
+       half them to get the right values.
+       In interlaced mode the values are already correct, so no correction is
+       necessary.
+       Code has been tested in 1024x768, 43 Hz interlaced and 640x480, 60 Hz
+       doublesscan.
+    */
+    if (interlace)
+        var->vmode = FB_VMODE_INTERLACED;
+    if (double_scan) {
+        var->vmode = FB_VMODE_DOUBLE;
+        var->yres>>=1;
+        var->upper_margin>>=1;
+        var->lower_margin>>=1;
+        var->vsync_len>>=1;
+    };
+                                    
     return 0;
 }
 
 /* ------------------------------------------------------------------------- */
 
 static void atyfb_set_par(const struct atyfb_par *par,
-			  struct fb_info_aty *info)
+                          struct fb_info_aty *info)
 {
     u32 i;
     int accelmode;
@@ -749,134 +949,157 @@
     info->current_par = *par;
 
     if (info->blitter_may_be_busy)
-	wait_for_idle(info);
+        wait_for_idle(info);
     tmp = aty_ld_8(CRTC_GEN_CNTL + 3, info);
     aty_set_crtc(info, &par->crtc);
+
+#if 0
     aty_st_8(CLOCK_CNTL + info->clk_wr_offset, 0, info);
-					/* better call aty_StrobeClock ?? */
+                                        /* better call aty_StrobeClock ?? */
     aty_st_8(CLOCK_CNTL + info->clk_wr_offset, CLOCK_STROBE, info);
+#endif
+    aty_st_8(CLOCK_CNTL, 0, info);
+    aty_st_8(CLOCK_CNTL, CLOCK_STROBE | CLOCK_DIV, info);
 
     info->dac_ops->set_dac(info, &par->pll, par->crtc.bpp, accelmode);
     info->pll_ops->set_pll(info, &par->pll);
 
     if (!M64_HAS(INTEGRATED)) {
-	/* Don't forget MEM_CNTL */
-	i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff;
-	switch (par->crtc.bpp) {
-	    case 8:
-		i |= 0x02000000;
-		break;
-	    case 16:
-		i |= 0x03000000;
-		break;
-	    case 32:
-		i |= 0x06000000;
-		break;
-	}
-	aty_st_le32(MEM_CNTL, i, info);
+        /* Don't forget MEM_CNTL */
+        i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff;
+        switch (par->crtc.bpp) {
+            case 8:
+                i |= 0x02000000;
+                break;
+            case 16:
+                i |= 0x03000000;
+                break;
+            case 32:
+                i |= 0x06000000;
+                break;
+        }
+        aty_st_le32(MEM_CNTL, i, info);
     } else {
-	i = aty_ld_le32(MEM_CNTL, info) & 0xf00fffff;
-	if (!M64_HAS(MAGIC_POSTDIV))
-	    i |= info->mem_refresh_rate << 20;
-	switch (par->crtc.bpp) {
-	    case 8:
-	    case 24:
-		i |= 0x00000000;
-		break;
-	    case 16:
-		i |= 0x04000000;
-		break;
-	    case 32:
-		i |= 0x08000000;
-		break;
-	}
-	if (M64_HAS(CT_BUS)) {
-	    aty_st_le32(DAC_CNTL, 0x87010184, info);
-	    aty_st_le32(BUS_CNTL, 0x680000f9, info);
-	} else if (M64_HAS(VT_BUS)) {
-	    aty_st_le32(DAC_CNTL, 0x87010184, info);
-	    aty_st_le32(BUS_CNTL, 0x680000f9, info);
-	}  else if (M64_HAS(MOBIL_BUS)) {
-	    aty_st_le32(DAC_CNTL, 0x80010102, info);
-	    aty_st_le32(BUS_CNTL, 0x7b33a040, info);
-	} else {
-	    /* GT */
-	    aty_st_le32(DAC_CNTL, 0x86010102, info);
-	    aty_st_le32(BUS_CNTL, 0x7b23a040, info);
-	    aty_st_le32(EXT_MEM_CNTL,
-			aty_ld_le32(EXT_MEM_CNTL, info) | 0x5000001, info);
-	}
-	aty_st_le32(MEM_CNTL, i, info);
+        i = aty_ld_le32(MEM_CNTL, info) & 0xf00fffff;
+        if (!M64_HAS(MAGIC_POSTDIV))
+            i |= info->mem_refresh_rate << 20;
+        switch (par->crtc.bpp) {
+            case 8:
+            case 24:
+                i |= 0x00000000;
+                break;
+            case 16:
+                i |= 0x04000000;
+                break;
+            case 32:
+                i |= 0x08000000;
+                break;
+        }
+        if (M64_HAS(CT_BUS)) {
+            aty_st_le32(DAC_CNTL, 0x87010184, info);
+            aty_st_le32(BUS_CNTL, 0x680000f9, info);
+        } else if (M64_HAS(VT_BUS)) {
+            aty_st_le32(DAC_CNTL, 0x87010184, info);
+            aty_st_le32(BUS_CNTL, 0x680000f9, info);
+        }  else if (M64_HAS(MOBIL_BUS)) {
+            aty_st_le32(DAC_CNTL, 0x80010102, info);
+            aty_st_le32(BUS_CNTL, 0x7b33a040, info);
+        } else {
+            /* GT */
+            aty_st_le32(DAC_CNTL, 0x86010102, info);
+            aty_st_le32(BUS_CNTL, 0x7b23a040, info);
+            aty_st_le32(EXT_MEM_CNTL,
+                        aty_ld_le32(EXT_MEM_CNTL, info) | 0x5000001, info);
+        }
+        aty_st_le32(MEM_CNTL, i, info);
     }
     aty_st_8(DAC_MASK, 0xff, info);
 
     /* Initialize the graphics engine */
     if (par->accel_flags & FB_ACCELF_TEXT)
-	aty_init_engine(par, info);
+        aty_init_engine(par, info);
 
 #ifdef CONFIG_FB_COMPAT_XPMAC
     if (!console_fb_info || console_fb_info == &info->fb_info) {
-	struct fb_var_screeninfo var;
-	int vmode, cmode;
-	display_info.height = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
-	display_info.width = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
-	display_info.depth = par->crtc.bpp;
-	display_info.pitch = par->crtc.vxres*par->crtc.bpp/8;
-	atyfb_encode_var(&var, par, info);
-	if (mac_var_to_vmode(&var, &vmode, &cmode))
-	    display_info.mode = 0;
-	else
-	    display_info.mode = vmode;
-	strcpy(display_info.name, atyfb_name);
-	display_info.fb_address = info->frame_buffer_phys;
-	display_info.cmap_adr_address = info->ati_regbase_phys+0xc0;
-	display_info.cmap_data_address = info->ati_regbase_phys+0xc1;
-	display_info.disp_reg_address = info->ati_regbase_phys;
+        struct fb_var_screeninfo var;
+        int vmode, cmode;
+        display_info.height = ((par->crtc.v_tot_disp>>16) & 0x7ff)+1;
+        display_info.width = (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8;
+        display_info.depth = par->crtc.bpp;
+        display_info.pitch = par->crtc.vxres*par->crtc.bpp/8;
+        atyfb_encode_var(&var, par, info);
+        if (mac_var_to_vmode(&var, &vmode, &cmode))
+            display_info.mode = 0;
+        else
+            display_info.mode = vmode;
+        strcpy(display_info.name, atyfb_name);
+        display_info.fb_address = info->frame_buffer_phys;
+        display_info.cmap_adr_address = info->ati_regbase_phys+0xc0;
+        display_info.cmap_data_address = info->ati_regbase_phys+0xc1;
+        display_info.disp_reg_address = info->ati_regbase_phys;
     }
 #endif /* CONFIG_FB_COMPAT_XPMAC */
 #ifdef CONFIG_BOOTX_TEXT
     btext_update_display(info->frame_buffer_phys,
-			 (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8,
-			 ((par->crtc.v_tot_disp>>16) & 0x7ff)+1,
-			 par->crtc.bpp,
-			 par->crtc.vxres*par->crtc.bpp/8);
+                         (((par->crtc.h_tot_disp>>16) & 0xff)+1)*8,
+                         ((par->crtc.v_tot_disp>>16) & 0x7ff)+1,
+                         par->crtc.bpp,
+                         par->crtc.vxres*par->crtc.bpp/8);
 #endif /* CONFIG_BOOTX_TEXT */
 }
 
 static int atyfb_decode_var(const struct fb_var_screeninfo *var,
-			    struct atyfb_par *par,
-			    const struct fb_info_aty *info)
+                            struct atyfb_par *par,
+                            const struct fb_info_aty *info,
+                            u32 monitors_enabled)
 {
     int err;
+    u32 pixclock,xres;
 
-    if ((err = aty_var_to_crtc(info, var, &par->crtc)) ||
-	(err = info->pll_ops->var_to_pll(info, var->pixclock, par->crtc.bpp,
-		    			 &par->pll)))
-	return err;
+    err = aty_var_to_crtc(info, var, &par->crtc, &monitors_enabled);
+    if (err == 0) {
+        /* Alert! aty_var_to_crtc can modify monitors_enabled which is
+           important for the pixclock decision */
+        pixclock = var->pixclock;
+        xres = 0;
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+        if ((info->lcd_table != 0) && ((monitors_enabled & LCD_ON) != 0)) {
+            pixclock = info->lcd_pixclock;
+            xres = var->xres;
+        };
+#endif
+        if (pixclock == 0) {
+            FAIL("Invalid pixclock");
+        } else
+            err = info->pll_ops->var_to_pll(info, pixclock, par->crtc.bpp, xres,
+	                                    &par->pll);
+    };
+    if (err != 0)
+        return err;
 
     if (var->accel_flags & FB_ACCELF_TEXT)
-	par->accel_flags = FB_ACCELF_TEXT;
+        par->accel_flags = FB_ACCELF_TEXT;
     else
-	par->accel_flags = 0;
+        par->accel_flags = 0;
 
 #if 0 /* fbmon is not done. uncomment for 2.5.x -brad */
-    if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))
-	return -EINVAL;
+    if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
+        return -EINVAL;
 #endif
 
     return 0;
 }
 
 static int atyfb_encode_var(struct fb_var_screeninfo *var,
-			    const struct atyfb_par *par,
-			    const struct fb_info_aty *info)
+                            const struct atyfb_par *par,
+                            const struct fb_info_aty *info)
 {
     int err;
 
     memset(var, 0, sizeof(struct fb_var_screeninfo));
 
     if ((err = aty_crtc_to_var(&par->crtc, var)))
-	return err;
+        return err;
     var->pixclock = info->pll_ops->pll_to_var(info, &par->pll);
 
     var->height = -1;
@@ -889,7 +1112,7 @@
 
 
 static void set_off_pitch(struct atyfb_par *par,
-			  const struct fb_info_aty *info)
+                          const struct fb_info_aty *info)
 {
     u32 xoffset = par->crtc.xoffset;
     u32 yoffset = par->crtc.yoffset;
@@ -912,11 +1135,11 @@
     struct fb_info_aty *fb = (struct fb_info_aty *)info;
 
     if (user) {
-	fb->open++;
-	fb->mmaped = 0;
-	fb->vtconsole = -1;
+        fb->open++;
+        fb->mmaped = 0;
+        fb->vtconsole = -1;
     } else {
-	fb->consolecnt++;
+        fb->consolecnt++;
     }
 #endif
     return(0);
@@ -936,42 +1159,42 @@
     struct fb_info_aty *fb = (struct fb_info_aty *)info;
 
     if (user) {
-	fb->open--;
-	mdelay(1);
-	wait_for_idle(fb);
-	if (!fb->open) {
-		int was_mmaped = fb->mmaped;
-
-		fb->mmaped = 0;
-		if (fb->vtconsole != -1)
-			vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
-		fb->vtconsole = -1;
-
-		if (was_mmaped) {
-			struct fb_var_screeninfo var;
-
-			/* Now reset the default display config, we have no
-			 * idea what the program(s) which mmap'd the chip did
-			 * to the configuration, nor whether it restored it
-			 * correctly.
-			 */
-			var = default_var;
-			if (noaccel)
-				var.accel_flags &= ~FB_ACCELF_TEXT;
-			else
-				var.accel_flags |= FB_ACCELF_TEXT;
-			if (var.yres == var.yres_virtual) {
-				u32 vram = (fb->total_vram - (PAGE_SIZE << 2));
-				var.yres_virtual = ((vram * 8) / var.bits_per_pixel) /
-					var.xres_virtual;
-				if (var.yres_virtual < var.yres)
-					var.yres_virtual = var.yres;
-			}
-			atyfb_set_var(&var, -1, &fb->fb_info);
-		}
-	}
+        fb->open--;
+        mdelay(1);
+        wait_for_idle(fb);
+        if (!fb->open) {
+                int was_mmaped = fb->mmaped;
+
+                fb->mmaped = 0;
+                if (fb->vtconsole != -1)
+                        vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
+                fb->vtconsole = -1;
+
+                if (was_mmaped) {
+                        struct fb_var_screeninfo var;
+
+                        /* Now reset the default display config, we have no
+                         * idea what the program(s) which mmap'd the chip did
+                         * to the configuration, nor whether it restored it
+                         * correctly.
+                         */
+                        var = default_var;
+                        if (noaccel)
+                                var.accel_flags &= ~FB_ACCELF_TEXT;
+                        else
+                                var.accel_flags |= FB_ACCELF_TEXT;
+                        if (var.yres == var.yres_virtual) {
+                                u32 vram = (fb->total_vram - (PAGE_SIZE << 2));
+                                var.yres_virtual = ((vram * 8) / var.bits_per_pixel) /
+                                        var.xres_virtual;
+                                if (var.yres_virtual < var.yres)
+                                        var.yres_virtual = var.yres;
+                        }
+                        atyfb_set_var(&var, -1, &fb->fb_info);
+                }
+        }
     } else {
-	fb->consolecnt--;
+        fb->consolecnt--;
     }
 #endif
     return(0);
@@ -979,8 +1202,8 @@
 
 
 static int encode_fix(struct fb_fix_screeninfo *fix,
-		      const struct atyfb_par *par,
-		      const struct fb_info_aty *info)
+                      const struct atyfb_par *par,
+                      const struct fb_info_aty *info)
 {
     memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
@@ -993,27 +1216,27 @@
      *  Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400
      */
     if (M64_HAS(GX)) {
-	fix->mmio_start = info->ati_regbase_phys;
-	fix->mmio_len = 0x400;
-	fix->accel = FB_ACCEL_ATI_MACH64GX;
+        fix->mmio_start = info->ati_regbase_phys;
+        fix->mmio_len = 0x400;
+        fix->accel = FB_ACCEL_ATI_MACH64GX;
     } else if (M64_HAS(CT)) {
-	fix->mmio_start = info->ati_regbase_phys;
-	fix->mmio_len = 0x400;
-	fix->accel = FB_ACCEL_ATI_MACH64CT;
+        fix->mmio_start = info->ati_regbase_phys;
+        fix->mmio_len = 0x400;
+        fix->accel = FB_ACCEL_ATI_MACH64CT;
     } else if (M64_HAS(VT)) {
-	fix->mmio_start = info->ati_regbase_phys-0x400;
-	fix->mmio_len = 0x800;
-	fix->accel = FB_ACCEL_ATI_MACH64VT;
+        fix->mmio_start = info->ati_regbase_phys-0x400;
+        fix->mmio_len = 0x800;
+        fix->accel = FB_ACCEL_ATI_MACH64VT;
     } else /* if (M64_HAS(GT)) */ {
-	fix->mmio_start = info->ati_regbase_phys-0x400;
-	fix->mmio_len = 0x800;
-	fix->accel = FB_ACCEL_ATI_MACH64GT;
+        fix->mmio_start = info->ati_regbase_phys-0x400;
+        fix->mmio_len = 0x800;
+        fix->accel = FB_ACCEL_ATI_MACH64GT;
     }
     fix->type = FB_TYPE_PACKED_PIXELS;
     fix->type_aux = 0;
     fix->line_length = par->crtc.vxres*par->crtc.bpp/8;
     fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
-				     : FB_VISUAL_DIRECTCOLOR;
+                                     : FB_VISUAL_DIRECTCOLOR;
     fix->ywrapstep = 0;
     fix->xpanstep = 8;
     fix->ypanstep = 1;
@@ -1027,15 +1250,18 @@
      */
 
 static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *fb)
+                         struct fb_info *fb)
 {
     const struct fb_info_aty *info = (struct fb_info_aty *)fb;
     struct atyfb_par par;
 
     if (con == -1)
-	par = info->default_par;
+        par = info->default_par;
     else
-	atyfb_decode_var(&fb_display[con].var, &par, info);
+        /* The monitors_enabled information is not important for
+           the calculation of the information in par that encode_fix
+           needs, so we pass a 0. */
+        atyfb_decode_var(&fb_display[con].var, &par, info, 0);
     encode_fix(fix, &par, info);
     return 0;
 }
@@ -1046,125 +1272,185 @@
      */
 
 static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *fb)
+                         struct fb_info *fb)
 {
     const struct fb_info_aty *info = (struct fb_info_aty *)fb;
 
     if (con == -1)
-	atyfb_encode_var(var, &info->default_par, info);
+        atyfb_encode_var(var, &info->default_par, info);
     else
-	*var = fb_display[con].var;
+        *var = fb_display[con].var;
     return 0;
 }
 
 
 static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info,
-			     int bpp, int accel)
+                             int bpp, int accel)
 {
-	    switch (bpp) {
+            switch (bpp) {
 #ifdef FBCON_HAS_CFB8
-		case 8:
-		    info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8;
-		    disp->dispsw = &info->dispsw;
-		    break;
+                case 8:
+                    info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8;
+                    disp->dispsw = &info->dispsw;
+                    break;
 #endif
 #ifdef FBCON_HAS_CFB16
-		case 16:
-		    info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16;
-		    disp->dispsw = &info->dispsw;
-		    disp->dispsw_data = info->fbcon_cmap.cfb16;
-		    break;
+                case 16:
+                    info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16;
+                    disp->dispsw = &info->dispsw;
+                    disp->dispsw_data = info->fbcon_cmap.cfb16;
+                    break;
 #endif
 #ifdef FBCON_HAS_CFB24
-		case 24:
-		    info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
-		    disp->dispsw = &info->dispsw;
-		    disp->dispsw_data = info->fbcon_cmap.cfb24;
-		    break;
+                case 24:
+                    info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
+                    disp->dispsw = &info->dispsw;
+                    disp->dispsw_data = info->fbcon_cmap.cfb24;
+                    break;
 #endif
 #ifdef FBCON_HAS_CFB32
-		case 32:
-		    info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
-		    disp->dispsw = &info->dispsw;
-		    disp->dispsw_data = info->fbcon_cmap.cfb32;
-		    break;
-#endif
-		default:
-		    disp->dispsw = &fbcon_dummy;
-	    }
+                case 32:
+                    info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
+                    disp->dispsw = &info->dispsw;
+                    disp->dispsw_data = info->fbcon_cmap.cfb32;
+                    break;
+#endif
+                default:
+                    disp->dispsw = &fbcon_dummy;
+            }
 #ifdef CONFIG_FB_ATY_CT
-	    if (info->cursor) {
-		info->dispsw.cursor = atyfb_cursor;
-		info->dispsw.set_font = atyfb_set_font;
-	    }
+            if (info->cursor) {
+                info->dispsw.cursor = atyfb_cursor;
+                info->dispsw.set_font = atyfb_set_font;
+            }
 #endif /* CONFIG_FB_ATY_CT */
 }
 
+    /*
+     * In the display mode set code we need to make desisions depending on
+     * wether the LCD or CRT monitor is enabled.
+     * This is going to give problems in the unlikely case that someone
+     * for example turns on the LCD monitor just after we tested what
+     * monitors are enabled. Since the consequences are very serious
+     * (the graphic card crashes and sends the wrong signals to the lcd
+     *  monitor which gets brighter and brighter; to prevent it from
+     * damage the computer must be switched off as soon as possible)
+     * we need to prevent this.
+     *
+     * As far as I know there is no way to prevent people switching on the
+     * LCD monitor while we are programming the video card. So the best way
+     * to do it, is detect what monitors are enabled before programming the
+     * video chip. After programming the video chip, we write this information
+     * back to the video chip, switching the LCD off again if someone enabled
+     * it. But isn't the card already crashed before we have the chance to
+     * turn the display back off? I don't think so because the CRTC is disabled
+     * while we program it.
+     */
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+static u32 atyfb_monitors_enabled(struct fb_info_aty *info) {
+     if (info->lcd_table != 0) {
+         return aty_ld_lcd(LCD_GEN_CTRL, info) & 3;
+     };
+     return 0;
+};
+#else
+#define atyfb_monitors_enabled(info) 0
+#endif
 
     /*
      *  Set the User Defined Part of the Display
      */
 
 static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *fb)
+                         struct fb_info *fb)
 {
     struct fb_info_aty *info = (struct fb_info_aty *)fb;
     struct atyfb_par par;
     struct display *display;
     int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel, accel, err;
     int activate = var->activate;
+    u32 monitors_enabled;
 
     if (con >= 0)
-	display = &fb_display[con];
+        display = &fb_display[con];
     else
-	display = fb->disp;	/* used during initialization */
+        display = fb->disp;     /* used during initialization */
 
-    if ((err = atyfb_decode_var(var, &par, info)))
-	return err;
+    monitors_enabled = atyfb_monitors_enabled(info);
+
+    /*
+     * We have to be very carefull with encode_var for LCD_panels. Fbdev
+     * applications do not know about LCD monitors. We have to make them
+     * think they are using a CRT. That means that alltough the video
+     * chip is programmed for the resolution of the LCD monitor (say 800x600),
+     * the applications expect the mode they asked for, say 640x480
+     *
+     * So when a program asks for 640x480, atyfb_decode_var sets the crtc
+     * registers for 800x600. Then atyfb_encode_var calculates the crtc
+     * registers back into the var variable, but now the var variable
+     * will contain wrong values for 800x600! Result: wrong information is
+     * returned to the program!
+     *
+     * To counter this, we call atyfb_decode_var first like if there is no
+     * lcd monitor switched on. Then we call atyfb_decode_var. Now
+     * the correct information is returned to the program, but the values
+     * for the crtc registers are not suited for the LCD monitor. We call
+     * atyfb_decode_var again to calculate the registers again, this time
+     * with the right monitors_enabled.
+     */
+
+    if ((err = atyfb_decode_var(var, &par, info, CRT_ON)))
+        return err;
 
     atyfb_encode_var(var, &par, (struct fb_info_aty *)info);
 
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+    if ((err = atyfb_decode_var(var, &par, info, monitors_enabled)))
+        return err;
+#endif
+
     if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-	oldxres = display->var.xres;
-	oldyres = display->var.yres;
-	oldvxres = display->var.xres_virtual;
-	oldvyres = display->var.yres_virtual;
-	oldbpp = display->var.bits_per_pixel;
-	oldaccel = display->var.accel_flags;
-	display->var = *var;
-	accel = var->accel_flags & FB_ACCELF_TEXT;
-	if (oldxres != var->xres || oldyres != var->yres ||
-	    oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
-	    oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
-	    struct fb_fix_screeninfo fix;
-
-	    encode_fix(&fix, &par, info);
-	    display->screen_base = (char *)info->frame_buffer;
-	    display->visual = fix.visual;
-	    display->type = fix.type;
-	    display->type_aux = fix.type_aux;
-	    display->ypanstep = fix.ypanstep;
-	    display->ywrapstep = fix.ywrapstep;
-	    display->line_length = fix.line_length;
-	    display->can_soft_blank = 1;
-	    display->inverse = 0;
-	    if (accel)
-	    	display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
-	    else
-	    	display->scrollmode = SCROLL_YREDRAW;
-	    if (info->fb_info.changevar)
-		(*info->fb_info.changevar)(con);
-	}
-	if (!info->fb_info.display_fg ||
-	    info->fb_info.display_fg->vc_num == con) {
-	    atyfb_set_par(&par, info);
-	    atyfb_set_dispsw(display, info, par.crtc.bpp, accel);
-	}
-	if (oldbpp != var->bits_per_pixel) {
-	    if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
-		return err;
-	    do_install_cmap(con, &info->fb_info);
-	}
+        oldxres = display->var.xres;
+        oldyres = display->var.yres;
+        oldvxres = display->var.xres_virtual;
+        oldvyres = display->var.yres_virtual;
+        oldbpp = display->var.bits_per_pixel;
+        oldaccel = display->var.accel_flags;
+        display->var = *var;
+        accel = var->accel_flags & FB_ACCELF_TEXT;
+        if (oldxres != var->xres || oldyres != var->yres ||
+            oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
+            oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
+            struct fb_fix_screeninfo fix;
+
+            encode_fix(&fix, &par, info);
+            display->screen_base = (char *)info->frame_buffer;
+            display->visual = fix.visual;
+            display->type = fix.type;
+            display->type_aux = fix.type_aux;
+            display->ypanstep = fix.ypanstep;
+            display->ywrapstep = fix.ywrapstep;
+            display->line_length = fix.line_length;
+            display->can_soft_blank = 1;
+            display->inverse = 0;
+            if (accel)
+                display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
+            else
+                display->scrollmode = SCROLL_YREDRAW;
+            if (info->fb_info.changevar)
+                (*info->fb_info.changevar)(con);
+        }
+        if (!info->fb_info.display_fg ||
+            info->fb_info.display_fg->vc_num == con) {
+            atyfb_set_par(&par, info);
+            atyfb_set_dispsw(display, info, par.crtc.bpp, accel);
+        }
+        if (oldbpp != var->bits_per_pixel) {
+            if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
+                return err;
+            do_install_cmap(con, &info->fb_info);
+        }
     }
 
     return 0;
@@ -1178,7 +1464,7 @@
      */
 
 static int atyfb_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info *fb)
+                             struct fb_info *fb)
 {
     struct fb_info_aty *info = (struct fb_info_aty *)fb;
     u32 xres, yres, xoffset, yoffset;
@@ -1189,7 +1475,7 @@
     xoffset = (var->xoffset+7) & ~7;
     yoffset = var->yoffset;
     if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres)
-	return -EINVAL;
+        return -EINVAL;
     par->crtc.xoffset = xoffset;
     par->crtc.yoffset = yoffset;
     set_off_pitch(par, info);
@@ -1201,15 +1487,15 @@
      */
 
 static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
+                          struct fb_info *info)
 {
     if (!info->display_fg || con == info->display_fg->vc_num) /* current console? */
-	return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info);
+        return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info);
     else if (fb_display[con].cmap.len) /* non default colormap? */
-	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+        fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
     else {
-	int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
-	fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
+        int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+        fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
     }
     return 0;
 }
@@ -1219,54 +1505,32 @@
      */
 
 static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
+                          struct fb_info *info)
 {
     int err;
     struct display *disp;
 
     if (con >= 0)
-    	disp = &fb_display[con];
+        disp = &fb_display[con];
     else
         disp = info->disp;
-    if (!disp->cmap.len) {	/* no colormap allocated? */
-	int size = disp->var.bits_per_pixel == 16 ? 32 : 256;
-	if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
-	    return err;
+    if (!disp->cmap.len) {      /* no colormap allocated? */
+        int size = disp->var.bits_per_pixel == 16 ? 32 : 256;
+        if ((err = fb_alloc_cmap(&disp->cmap, size, 0)))
+            return err;
     }
-    if (!info->display_fg || con == info->display_fg->vc_num)			/* current console? */
-	return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info);
+    if (!info->display_fg || con == info->display_fg->vc_num)                   /* current console? */
+        return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info);
     else
-	fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
+        fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
     return 0;
 }
 
 
-#ifdef DEBUG
-#define ATYIO_CLKR		0x41545900	/* ATY\00 */
-#define ATYIO_CLKW		0x41545901	/* ATY\01 */
-
-struct atyclk {
-    u32 ref_clk_per;
-    u8 pll_ref_div;
-    u8 mclk_fb_div;
-    u8 mclk_post_div;		/* 1,2,3,4,8 */
-    u8 vclk_fb_div;
-    u8 vclk_post_div;		/* 1,2,3,4,6,8,12 */
-    u32 dsp_xclks_per_row;	/* 0-16383 */
-    u32 dsp_loop_latency;	/* 0-15 */
-    u32 dsp_precision;		/* 0-7 */
-    u32 dsp_on;			/* 0-2047 */
-    u32 dsp_off;		/* 0-2047 */
-};
-
-#define ATYIO_FEATR		0x41545902	/* ATY\02 */
-#define ATYIO_FEATW		0x41545903	/* ATY\03 */
-#endif
-
 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg, int con, struct fb_info *info2)
+                       u_long arg, int con, struct fb_info *info2)
 {
-#if defined(__sparc__) || (defined(DEBUG) && defined(CONFIG_FB_ATY_CT))
+#if defined(__sparc__)
     struct fb_info_aty *info = (struct fb_info_aty *)info2;
 #endif /* __sparc__ || DEBUG */
 #ifdef __sparc__
@@ -1274,7 +1538,7 @@
     struct display *disp;
 
     if (con >= 0)
-    	disp = &fb_display[con];
+        disp = &fb_display[con];
     else
         disp = info2->disp;
 #endif
@@ -1282,72 +1546,18 @@
     switch (cmd) {
 #ifdef __sparc__
     case FBIOGTYPE:
-	fbtyp.fb_type = FBTYPE_PCI_GENERIC;
-	fbtyp.fb_width = info->current_par.crtc.vxres;
-	fbtyp.fb_height = info->current_par.crtc.vyres;
-	fbtyp.fb_depth = info->current_par.crtc.bpp;
-	fbtyp.fb_cmsize = disp->cmap.len;
-	fbtyp.fb_size = info->total_vram;
-	if (copy_to_user((struct fbtype *)arg, &fbtyp, sizeof(fbtyp)))
-		return -EFAULT;
-	break;
+        fbtyp.fb_type = FBTYPE_PCI_GENERIC;
+        fbtyp.fb_width = info->current_par.crtc.vxres;
+        fbtyp.fb_height = info->current_par.crtc.vyres;
+        fbtyp.fb_depth = info->current_par.crtc.bpp;
+        fbtyp.fb_cmsize = disp->cmap.len;
+        fbtyp.fb_size = info->total_vram;
+        if (copy_to_user((struct fbtype *)arg, &fbtyp, sizeof(fbtyp)))
+                return -EFAULT;
+        break;
 #endif /* __sparc__ */
-#if defined(DEBUG) && defined(CONFIG_FB_ATY_CT)
-    case ATYIO_CLKR:
-	if (M64_HAS(INTEGRATED)) {
-	    struct atyclk clk;
-	    union aty_pll *pll = &info->current_par.pll;
-	    u32 dsp_config = pll->ct.dsp_config;
-	    u32 dsp_on_off = pll->ct.dsp_on_off;
-	    clk.ref_clk_per = info->ref_clk_per;
-	    clk.pll_ref_div = pll->ct.pll_ref_div;
-	    clk.mclk_fb_div = pll->ct.mclk_fb_div;
-	    clk.mclk_post_div = pll->ct.mclk_post_div_real;
-	    clk.vclk_fb_div = pll->ct.vclk_fb_div;
-	    clk.vclk_post_div = pll->ct.vclk_post_div_real;
-	    clk.dsp_xclks_per_row = dsp_config & 0x3fff;
-	    clk.dsp_loop_latency = (dsp_config>>16) & 0xf;
-	    clk.dsp_precision = (dsp_config>>20) & 7;
-	    clk.dsp_on = dsp_on_off & 0x7ff;
-	    clk.dsp_off = (dsp_on_off>>16) & 0x7ff;
-	    if (copy_to_user((struct atyclk *)arg, &clk, sizeof(clk)))
-		    return -EFAULT;
-	} else
-	    return -EINVAL;
-	break;
-    case ATYIO_CLKW:
-	if (M64_HAS(INTEGRATED)) {
-	    struct atyclk clk;
-	    union aty_pll *pll = &info->current_par.pll;
-	    if (copy_from_user(&clk, (struct atyclk *)arg, sizeof(clk)))
-		    return -EFAULT;
-	    info->ref_clk_per = clk.ref_clk_per;
-	    pll->ct.pll_ref_div = clk.pll_ref_div;
-	    pll->ct.mclk_fb_div = clk.mclk_fb_div;
-	    pll->ct.mclk_post_div_real = clk.mclk_post_div;
-	    pll->ct.vclk_fb_div = clk.vclk_fb_div;
-	    pll->ct.vclk_post_div_real = clk.vclk_post_div;
-	    pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
-				 ((clk.dsp_loop_latency & 0xf)<<16) |
-				 ((clk.dsp_precision & 7)<<20);
-	    pll->ct.dsp_on_off = (clk.dsp_on & 0x7ff) |
-				 ((clk.dsp_off & 0x7ff)<<16);
-	    aty_calc_pll_ct(info, &pll->ct);
-	    aty_set_pll_ct(info, pll);
-	} else
-	    return -EINVAL;
-	break;
-    case ATYIO_FEATR:
-	if (get_user(info->features, (u32 *)arg))
-	    return -EFAULT;
-	break;
-    case ATYIO_FEATW:
-	if (put_user(info->features, (u32 *)arg))
-	    return -EFAULT;
-	break;
-#endif /* DEBUG && CONFIG_FB_ATY_CT */
     default:
-	return -EINVAL;
+        return -EINVAL;
     }
     return 0;
 }
@@ -1357,148 +1567,148 @@
     struct fb_info_aty *fb = (struct fb_info_aty *)info;
 
     if (fb->blitter_may_be_busy)
-	wait_for_idle(fb);
+        wait_for_idle(fb);
     return 0;
 }
 
 #ifdef __sparc__
 static int atyfb_mmap(struct fb_info *info, struct file *file,
-		      struct vm_area_struct *vma)
+                      struct vm_area_struct *vma)
 {
-	struct fb_info_aty *fb = (struct fb_info_aty *)info;
-	unsigned int size, page, map_size = 0;
-	unsigned long map_offset = 0;
-	unsigned long off;
-	int i;
-
-	if (!fb->mmap_map)
-		return -ENXIO;
-
-	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
-		return -EINVAL;
-
-	off = vma->vm_pgoff << PAGE_SHIFT;
-	size = vma->vm_end - vma->vm_start;
-
-	/* To stop the swapper from even considering these pages. */
-	vma->vm_flags |= (VM_SHM | VM_LOCKED);
-
-	if (((vma->vm_pgoff == 0) && (size == fb->total_vram)) ||
-	    ((off == fb->total_vram) && (size == PAGE_SIZE)))
-		off += 0x8000000000000000UL;
-
-	vma->vm_pgoff = off >> PAGE_SHIFT;	/* propagate off changes */
-
-	/* Each page, see which map applies */
-	for (page = 0; page < size; ) {
-		map_size = 0;
-		for (i = 0; fb->mmap_map[i].size; i++) {
-			unsigned long start = fb->mmap_map[i].voff;
-			unsigned long end = start + fb->mmap_map[i].size;
-			unsigned long offset = off + page;
-
-			if (start > offset)
-				continue;
-			if (offset >= end)
-				continue;
-
-			map_size = fb->mmap_map[i].size - (offset - start);
-			map_offset = fb->mmap_map[i].poff + (offset - start);
-			break;
-		}
-		if (!map_size) {
-			page += PAGE_SIZE;
-			continue;
-		}
-		if (page + map_size > size)
-			map_size = size - page;
-
-		pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
-		pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
-
-		if (remap_page_range(vma->vm_start + page, map_offset,
-				     map_size, vma->vm_page_prot))
-			return -EAGAIN;
-
-		page += map_size;
-	}
-
-	if (!map_size)
-		return -EINVAL;
-
-	vma->vm_flags |= VM_IO;
-
-	if (!fb->mmaped) {
-		int lastconsole = 0;
-
-		if (info->display_fg)
-			lastconsole = info->display_fg->vc_num;
-		fb->mmaped = 1;
-		if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {
-			fb->vtconsole = lastconsole;
-			vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
-		}
-	}
-	return 0;
+        struct fb_info_aty *fb = (struct fb_info_aty *)info;
+        unsigned int size, page, map_size = 0;
+        unsigned long map_offset = 0;
+        unsigned long off;
+        int i;
+
+        if (!fb->mmap_map)
+                return -ENXIO;
+
+        if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+                return -EINVAL;
+
+        off = vma->vm_pgoff << PAGE_SHIFT;
+        size = vma->vm_end - vma->vm_start;
+
+        /* To stop the swapper from even considering these pages. */
+        vma->vm_flags |= (VM_SHM | VM_LOCKED);
+
+        if (((vma->vm_pgoff == 0) && (size == fb->total_vram)) ||
+            ((off == fb->total_vram) && (size == PAGE_SIZE)))
+                off += 0x8000000000000000UL;
+
+        vma->vm_pgoff = off >> PAGE_SHIFT;      /* propagate off changes */
+
+        /* Each page, see which map applies */
+        for (page = 0; page < size; ) {
+                map_size = 0;
+                for (i = 0; fb->mmap_map[i].size; i++) {
+                        unsigned long start = fb->mmap_map[i].voff;
+                        unsigned long end = start + fb->mmap_map[i].size;
+                        unsigned long offset = off + page;
+
+                        if (start > offset)
+                                continue;
+                        if (offset >= end)
+                                continue;
+
+                        map_size = fb->mmap_map[i].size - (offset - start);
+                        map_offset = fb->mmap_map[i].poff + (offset - start);
+                        break;
+                }
+                if (!map_size) {
+                        page += PAGE_SIZE;
+                        continue;
+                }
+                if (page + map_size > size)
+                        map_size = size - page;
+
+                pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
+                pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
+
+                if (remap_page_range(vma->vm_start + page, map_offset,
+                                     map_size, vma->vm_page_prot))
+                        return -EAGAIN;
+
+                page += map_size;
+        }
+
+        if (!map_size)
+                return -EINVAL;
+
+        vma->vm_flags |= VM_IO;
+
+        if (!fb->mmaped) {
+                int lastconsole = 0;
+
+                if (info->display_fg)
+                        lastconsole = info->display_fg->vc_num;
+                fb->mmaped = 1;
+                if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {
+                        fb->vtconsole = lastconsole;
+                        vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
+                }
+        }
+        return 0;
 }
 
 static struct {
-	u32	yoffset;
-	u8	r[2][256];
-	u8	g[2][256];
-	u8	b[2][256];
+        u32     yoffset;
+        u8      r[2][256];
+        u8      g[2][256];
+        u8      b[2][256];
 } atyfb_save;
 
 static void atyfb_save_palette(struct fb_info *fb, int enter)
 {
-	struct fb_info_aty *info = (struct fb_info_aty *)fb;
-	int i, tmp;
+        struct fb_info_aty *info = (struct fb_info_aty *)fb;
+        int i, tmp;
 
-	for (i = 0; i < 256; i++) {
-		tmp = aty_ld_8(DAC_CNTL, info) & 0xfc;
-		if (M64_HAS(EXTRA_BRIGHT))
-			tmp |= 0x2;
-		aty_st_8(DAC_CNTL, tmp, info);
-		aty_st_8(DAC_MASK, 0xff, info);
-
-		writeb(i, &info->aty_cmap_regs->rindex);
-		atyfb_save.r[enter][i] = readb(&info->aty_cmap_regs->lut);
-		atyfb_save.g[enter][i] = readb(&info->aty_cmap_regs->lut);
-		atyfb_save.b[enter][i] = readb(&info->aty_cmap_regs->lut);
-		writeb(i, &info->aty_cmap_regs->windex);
-		writeb(atyfb_save.r[1-enter][i], &info->aty_cmap_regs->lut);
-		writeb(atyfb_save.g[1-enter][i], &info->aty_cmap_regs->lut);
-		writeb(atyfb_save.b[1-enter][i], &info->aty_cmap_regs->lut);
-	}
+        for (i = 0; i < 256; i++) {
+                tmp = aty_ld_8(DAC_CNTL, info) & 0xfc;
+                if (M64_HAS(EXTRA_BRIGHT))
+                        tmp |= 0x2;
+                aty_st_8(DAC_CNTL, tmp, info);
+                aty_st_8(DAC_MASK, 0xff, info);
+
+                writeb(i, &info->aty_cmap_regs->rindex);
+                atyfb_save.r[enter][i] = readb(&info->aty_cmap_regs->lut);
+                atyfb_save.g[enter][i] = readb(&info->aty_cmap_regs->lut);
+                atyfb_save.b[enter][i] = readb(&info->aty_cmap_regs->lut);
+                writeb(i, &info->aty_cmap_regs->windex);
+                writeb(atyfb_save.r[1-enter][i], &info->aty_cmap_regs->lut);
+                writeb(atyfb_save.g[1-enter][i], &info->aty_cmap_regs->lut);
+                writeb(atyfb_save.b[1-enter][i], &info->aty_cmap_regs->lut);
+        }
 }
 
 static void atyfb_palette(int enter)
 {
-	struct fb_info_aty *info;
-	struct atyfb_par *par;
-	struct display *d;
-	int i;
-
-	for (i = 0; i < MAX_NR_CONSOLES; i++) {
-		d = &fb_display[i];
-		if (d->fb_info &&
-		    d->fb_info->fbops == &atyfb_ops &&
-		    d->fb_info->display_fg &&
-		    d->fb_info->display_fg->vc_num == i) {
-			atyfb_save_palette(d->fb_info, enter);
-			info = (struct fb_info_aty *)d->fb_info;
-			par = &info->current_par;
-			if (enter) {
-				atyfb_save.yoffset = par->crtc.yoffset;
-				par->crtc.yoffset = 0;
-				set_off_pitch(par, info);
-			} else {
-				par->crtc.yoffset = atyfb_save.yoffset;
-				set_off_pitch(par, info);
-			}
-			break;
-		}
-	}
+        struct fb_info_aty *info;
+        struct atyfb_par *par;
+        struct display *d;
+        int i;
+
+        for (i = 0; i < MAX_NR_CONSOLES; i++) {
+                d = &fb_display[i];
+                if (d->fb_info &&
+                    d->fb_info->fbops == &atyfb_ops &&
+                    d->fb_info->display_fg &&
+                    d->fb_info->display_fg->vc_num == i) {
+                        atyfb_save_palette(d->fb_info, enter);
+                        info = (struct fb_info_aty *)d->fb_info;
+                        par = &info->current_par;
+                        if (enter) {
+                                atyfb_save.yoffset = par->crtc.yoffset;
+                                par->crtc.yoffset = 0;
+                                set_off_pitch(par, info);
+                        } else {
+                                par->crtc.yoffset = atyfb_save.yoffset;
+                                set_off_pitch(par, info);
+                        }
+                        break;
+                }
+        }
 }
 #endif /* __sparc__ */
 
@@ -1516,117 +1726,117 @@
  */
 static int aty_power_mgmt_LT(int sleep, struct fb_info_aty *info)
 {
- 	unsigned int pm;
-	int timeout;
-	
-	pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
-	pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
-	aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
-	pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
-	
-	timeout = 200000;
-	if (sleep) {
-		/* Sleep */
-		pm &= ~PWR_MGT_ON;
-		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
-		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
-		udelay(10);
-		pm &= ~(PWR_BLON | AUTO_PWR_UP);
-		pm |= SUSPEND_NOW;
-		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
-		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
-		udelay(10);
-		pm |= PWR_MGT_ON;
-		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
-		do {
-			pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
-			udelay(10);
-			if ((--timeout) == 0)
-				break;
-		} while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
-	} else {
-		/* Wakeup */
-		pm &= ~PWR_MGT_ON;
-		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
-		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
-		udelay(10);
-		pm |=  (PWR_BLON | AUTO_PWR_UP);
-		pm &= ~SUSPEND_NOW;
-		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
-		pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
-		udelay(10);
-		pm |= PWR_MGT_ON;
-		aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
-		do {
-			pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
-			udelay(10);
-			if ((--timeout) == 0)
-				break;
-		} while ((pm & PWR_MGT_STATUS_MASK) != 0);
-	}
-	mdelay(500);
+        unsigned int pm;
+        int timeout;
+        
+        pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+        pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
+        aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+        pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+        
+        timeout = 200000;
+        if (sleep) {
+                /* Sleep */
+                pm &= ~PWR_MGT_ON;
+                aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+                pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+                udelay(10);
+                pm &= ~(PWR_BLON | AUTO_PWR_UP);
+                pm |= SUSPEND_NOW;
+                aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+                pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+                udelay(10);
+                pm |= PWR_MGT_ON;
+                aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+                do {
+                        pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+                        udelay(10);
+                        if ((--timeout) == 0)
+                                break;
+                } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
+        } else {
+                /* Wakeup */
+                pm &= ~PWR_MGT_ON;
+                aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+                pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+                udelay(10);
+                pm |=  (PWR_BLON | AUTO_PWR_UP);
+                pm &= ~SUSPEND_NOW;
+                aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+                pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+                udelay(10);
+                pm |= PWR_MGT_ON;
+                aty_st_le32(POWER_MANAGEMENT_LG, pm, info);
+                do {
+                        pm = aty_ld_le32(POWER_MANAGEMENT_LG, info);
+                        udelay(10);
+                        if ((--timeout) == 0)
+                                break;
+                } while ((pm & PWR_MGT_STATUS_MASK) != 0);
+        }
+        mdelay(500);
 
-	return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
+        return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
 }
 
 static int aty_power_mgmt_LTPro(int sleep, struct fb_info_aty *info)
 {
- 	unsigned int pm;
-	int timeout;
-	
-	pm = aty_ld_lcd(POWER_MANAGEMENT, info);
-	pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
-	aty_st_lcd(POWER_MANAGEMENT, pm, info);
-	pm = aty_ld_lcd(POWER_MANAGEMENT, info);
-
-	timeout = 200;
-	if (sleep) {
-		/* Sleep */
-		pm &= ~PWR_MGT_ON;
-		aty_st_lcd(POWER_MANAGEMENT, pm, info);
-		pm = aty_ld_lcd(POWER_MANAGEMENT, info);
-		udelay(10);
-		pm &= ~(PWR_BLON | AUTO_PWR_UP);
-		pm |= SUSPEND_NOW;
-		aty_st_lcd(POWER_MANAGEMENT, pm, info);
-		pm = aty_ld_lcd(POWER_MANAGEMENT, info);
-		udelay(10);
-		pm |= PWR_MGT_ON;
-		aty_st_lcd(POWER_MANAGEMENT, pm, info);
-		do {
-			pm = aty_ld_lcd(POWER_MANAGEMENT, info);
-			mdelay(1);
-			if ((--timeout) == 0)
-				break;
-		} while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
-	} else {
-		/* Wakeup */
-		pm &= ~PWR_MGT_ON;
-		aty_st_lcd(POWER_MANAGEMENT, pm, info);
-		pm = aty_ld_lcd(POWER_MANAGEMENT, info);
-		udelay(10);
-		pm &= ~SUSPEND_NOW;
-		pm |= (PWR_BLON | AUTO_PWR_UP);
-		aty_st_lcd(POWER_MANAGEMENT, pm, info);
-		pm = aty_ld_lcd(POWER_MANAGEMENT, info);
-		udelay(10);
-		pm |= PWR_MGT_ON;
-		aty_st_lcd(POWER_MANAGEMENT, pm, info);
-		do {
-			pm = aty_ld_lcd(POWER_MANAGEMENT, info);			
-			mdelay(1);
-			if ((--timeout) == 0)
-				break;
-		} while ((pm & PWR_MGT_STATUS_MASK) != 0);
-	}
+        unsigned int pm;
+        int timeout;
+        
+        pm = aty_ld_lcd(POWER_MANAGEMENT, info);
+        pm = (pm & ~PWR_MGT_MODE_MASK) | PWR_MGT_MODE_REG;
+        aty_st_lcd(POWER_MANAGEMENT, pm, info);
+        pm = aty_ld_lcd(POWER_MANAGEMENT, info);
+
+        timeout = 200;
+        if (sleep) {
+                /* Sleep */
+                pm &= ~PWR_MGT_ON;
+                aty_st_lcd(POWER_MANAGEMENT, pm, info);
+                pm = aty_ld_lcd(POWER_MANAGEMENT, info);
+                udelay(10);
+                pm &= ~(PWR_BLON | AUTO_PWR_UP);
+                pm |= SUSPEND_NOW;
+                aty_st_lcd(POWER_MANAGEMENT, pm, info);
+                pm = aty_ld_lcd(POWER_MANAGEMENT, info);
+                udelay(10);
+                pm |= PWR_MGT_ON;
+                aty_st_lcd(POWER_MANAGEMENT, pm, info);
+                do {
+                        pm = aty_ld_lcd(POWER_MANAGEMENT, info);
+                        mdelay(1);
+                        if ((--timeout) == 0)
+                                break;
+                } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
+        } else {
+                /* Wakeup */
+                pm &= ~PWR_MGT_ON;
+                aty_st_lcd(POWER_MANAGEMENT, pm, info);
+                pm = aty_ld_lcd(POWER_MANAGEMENT, info);
+                udelay(10);
+                pm &= ~SUSPEND_NOW;
+                pm |= (PWR_BLON | AUTO_PWR_UP);
+                aty_st_lcd(POWER_MANAGEMENT, pm, info);
+                pm = aty_ld_lcd(POWER_MANAGEMENT, info);
+                udelay(10);
+                pm |= PWR_MGT_ON;
+                aty_st_lcd(POWER_MANAGEMENT, pm, info);
+                do {
+                        pm = aty_ld_lcd(POWER_MANAGEMENT, info);                        
+                        mdelay(1);
+                        if ((--timeout) == 0)
+                                break;
+                } while ((pm & PWR_MGT_STATUS_MASK) != 0);
+        }
 
-	return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
+        return timeout ? PBOOK_SLEEP_OK : PBOOK_SLEEP_REFUSE;
 }
 
 static int aty_power_mgmt(int sleep, struct fb_info_aty *info)
 {
     return M64_HAS(LT_SLEEP) ? aty_power_mgmt_LT(sleep, info)
-			     : aty_power_mgmt_LTPro(sleep, info);
+                             : aty_power_mgmt_LTPro(sleep, info);
 }
 
 /*
@@ -1635,72 +1845,72 @@
  */
 static int aty_sleep_notify(struct pmu_sleep_notifier *self, int when)
 {
-	struct fb_info_aty *info;
- 	int result;
+        struct fb_info_aty *info;
+        int result;
 
-	result = PBOOK_SLEEP_OK;
+        result = PBOOK_SLEEP_OK;
 
-	for (info = first_display; info != NULL; info = info->next) {
-		struct fb_fix_screeninfo fix;
-		int nb;
-
-		atyfb_get_fix(&fix, fg_console, (struct fb_info *)info);
-		nb = fb_display[fg_console].var.yres * fix.line_length;
-
-		switch (when) {
-		case PBOOK_SLEEP_REQUEST:
-			info->save_framebuffer = vmalloc(nb);
-			if (info->save_framebuffer == NULL)
-				return PBOOK_SLEEP_REFUSE;
-			break;
-		case PBOOK_SLEEP_REJECT:
-			if (info->save_framebuffer) {
-				vfree(info->save_framebuffer);
-				info->save_framebuffer = 0;
-			}
-			break;
-		case PBOOK_SLEEP_NOW:
-			if (currcon >= 0)
-				fb_display[currcon].dispsw = &fbcon_dummy;
-			if (info->blitter_may_be_busy)
-				wait_for_idle(info);
-			/* Stop accel engine (stop bus mastering) */
-			if (info->current_par.accel_flags & FB_ACCELF_TEXT)
-				aty_reset_engine(info);
-
-			/* Backup fb content */	
-			if (info->save_framebuffer)
-				memcpy_fromio(info->save_framebuffer,
-				       (void *)info->frame_buffer, nb);
-
-			/* Blank display and LCD */
-			atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);
-
-			/* Set chip to "suspend" mode */
-			result = aty_power_mgmt(1, info);
-			break;
-		case PBOOK_WAKE:
-			/* Wakeup chip */
-			result = aty_power_mgmt(0, info);
-
-			/* Restore fb content */			
-			if (info->save_framebuffer) {
-				memcpy_toio((void *)info->frame_buffer,
-				       info->save_framebuffer, nb);
-				vfree(info->save_framebuffer);
-				info->save_framebuffer = 0;
-			}
-			/* Restore display */
-			if (currcon >= 0) {
-				atyfb_set_dispsw(&fb_display[currcon],
-					info, info->current_par.crtc.bpp,
-					info->current_par.accel_flags & FB_ACCELF_TEXT);
-			}
-			atyfbcon_blank(0, (struct fb_info *)info);
-			break;
-		}
-	}
-	return result;
+        for (info = first_display; info != NULL; info = info->next) {
+                struct fb_fix_screeninfo fix;
+                int nb;
+
+                atyfb_get_fix(&fix, fg_console, (struct fb_info *)info);
+                nb = fb_display[fg_console].var.yres * fix.line_length;
+
+                switch (when) {
+                case PBOOK_SLEEP_REQUEST:
+                        info->save_framebuffer = vmalloc(nb);
+                        if (info->save_framebuffer == NULL)
+                                return PBOOK_SLEEP_REFUSE;
+                        break;
+                case PBOOK_SLEEP_REJECT:
+                        if (info->save_framebuffer) {
+                                vfree(info->save_framebuffer);
+                                info->save_framebuffer = 0;
+                        }
+                        break;
+                case PBOOK_SLEEP_NOW:
+                        if (currcon >= 0)
+                                fb_display[currcon].dispsw = &fbcon_dummy;
+                        if (info->blitter_may_be_busy)
+                                wait_for_idle(info);
+                        /* Stop accel engine (stop bus mastering) */
+                        if (info->current_par.accel_flags & FB_ACCELF_TEXT)
+                                aty_reset_engine(info);
+
+                        /* Backup fb content */ 
+                        if (info->save_framebuffer)
+                                memcpy_fromio(info->save_framebuffer,
+                                       (void *)info->frame_buffer, nb);
+
+                        /* Blank display and LCD */
+                        atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);
+
+                        /* Set chip to "suspend" mode */
+                        result = aty_power_mgmt(1, info);
+                        break;
+                case PBOOK_WAKE:
+                        /* Wakeup chip */
+                        result = aty_power_mgmt(0, info);
+
+                        /* Restore fb content */                        
+                        if (info->save_framebuffer) {
+                                memcpy_toio((void *)info->frame_buffer,
+                                       info->save_framebuffer, nb);
+                                vfree(info->save_framebuffer);
+                                info->save_framebuffer = 0;
+                        }
+                        /* Restore display */
+                        if (currcon >= 0) {
+                                atyfb_set_dispsw(&fb_display[currcon],
+                                        info, info->current_par.crtc.bpp,
+                                        info->current_par.accel_flags & FB_ACCELF_TEXT);
+                        }
+                        atyfbcon_blank(0, (struct fb_info *)info);
+                        break;
+                }
+        }
+        return result;
 }
 
 static struct pmu_sleep_notifier aty_sleep_notifier = {
@@ -1715,38 +1925,38 @@
      */
 
 static int backlight_conv[] = {
-	0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d,
-	0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff
+        0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d,
+        0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff
 };
 
 static int
 aty_set_backlight_enable(int on, int level, void* data)
 {
-	struct fb_info_aty *info = (struct fb_info_aty *)data;
-	unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, info);
-	
-	reg |= (BLMOD_EN | BIASMOD_EN);
-	if (on && level > BACKLIGHT_OFF) {
-		reg &= ~BIAS_MOD_LEVEL_MASK;
-		reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT);
-	} else {
-		reg &= ~BIAS_MOD_LEVEL_MASK;
-		reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT);
-	}
-	aty_st_lcd(LCD_MISC_CNTL, reg, info);
+        struct fb_info_aty *info = (struct fb_info_aty *)data;
+        unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, info);
+        
+        reg |= (BLMOD_EN | BIASMOD_EN);
+        if (on && level > BACKLIGHT_OFF) {
+                reg &= ~BIAS_MOD_LEVEL_MASK;
+                reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT);
+        } else {
+                reg &= ~BIAS_MOD_LEVEL_MASK;
+                reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT);
+        }
+        aty_st_lcd(LCD_MISC_CNTL, reg, info);
 
-	return 0;
+        return 0;
 }
 
 static int
 aty_set_backlight_level(int level, void* data)
 {
-	return aty_set_backlight_enable(1, level, data);
+        return aty_set_backlight_enable(1, level, data);
 }
 
 static struct backlight_controller aty_backlight_controller = {
-	aty_set_backlight_enable,
-	aty_set_backlight_level
+        aty_set_backlight_enable,
+        aty_set_backlight_level
 };
 #endif /* CONFIG_PMAC_BACKLIGHT */
 
@@ -1768,25 +1978,27 @@
     u16 type;
     u8 rev;
     const char *chipname = NULL, *ramname = NULL, *xtal;
-    int pll, mclk, gtb_memsize;
+    int pll, mclk, xclk, gtb_memsize;
 #if defined(CONFIG_PPC)
     int sense;
 #endif
     u8 pll_ref_div;
+    u32 monitors_enabled;
 
     info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0);
     chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
     type = chip_id & CFG_CHIP_TYPE;
     rev = (chip_id & CFG_CHIP_REV)>>24;
     for (j = 0; j < (sizeof(aty_chips)/sizeof(*aty_chips)); j++)
-	if (type == aty_chips[j].chip_type &&
-	    (rev & aty_chips[j].rev_mask) == aty_chips[j].rev_val) {
-	    chipname = aty_chips[j].name;
-	    pll = aty_chips[j].pll;
-	    mclk = aty_chips[j].mclk;
-	    info->features = aty_chips[j].features;
-	    goto found;
-	}
+        if (type == aty_chips[j].chip_type &&
+            (rev & aty_chips[j].rev_mask) == aty_chips[j].rev_val) {
+            chipname = aty_chips[j].name;
+            pll = aty_chips[j].pll;
+            mclk = aty_chips[j].mclk;
+            xclk = aty_chips[j].xclk;
+            info->features = aty_chips[j].features;
+            goto found;
+        }
     printk("atyfb: Unknown mach64 0x%04x rev 0x%04x\n", type, rev);
     return 0;
 
@@ -1794,208 +2006,245 @@
     printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname, type, rev);
 #ifdef CONFIG_FB_ATY_GX
     if (!M64_HAS(INTEGRATED)) {
-	u32 stat0;
-	u8 dac_type, dac_subtype, clk_type;
-	stat0 = aty_ld_le32(CONFIG_STAT0, info);
-	info->bus_type = (stat0 >> 0) & 0x07;
-	info->ram_type = (stat0 >> 3) & 0x07;
-	ramname = aty_gx_ram[info->ram_type];
-	/* FIXME: clockchip/RAMDAC probing? */
-	dac_type = (aty_ld_le32(DAC_CNTL, info) >> 16) & 0x07;
+        u32 stat0;
+        u8 dac_type, dac_subtype, clk_type;
+        stat0 = aty_ld_le32(CONFIG_STAT0, info);
+        info->bus_type = (stat0 >> 0) & 0x07;
+        info->ram_type = (stat0 >> 3) & 0x07;
+        ramname = aty_gx_ram[info->ram_type];
+        /* FIXME: clockchip/RAMDAC probing? */
+        dac_type = (aty_ld_le32(DAC_CNTL, info) >> 16) & 0x07;
 #ifdef CONFIG_ATARI
-	clk_type = CLK_ATI18818_1;
-	dac_type = (stat0 >> 9) & 0x07;
-	if (dac_type == 0x07)
-	    dac_subtype = DAC_ATT20C408;
-	else
-	    dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, info) & 0xF0) | dac_type;
+        clk_type = CLK_ATI18818_1;
+        dac_type = (stat0 >> 9) & 0x07;
+        if (dac_type == 0x07)
+            dac_subtype = DAC_ATT20C408;
+        else
+            dac_subtype = (aty_ld_8(SCRATCH_REG1 + 1, info) & 0xF0) | dac_type;
 #else
-	dac_type = DAC_IBMRGB514;
-	dac_subtype = DAC_IBMRGB514;
-	clk_type = CLK_IBMRGB514;
-#endif
-	switch (dac_subtype) {
-	    case DAC_IBMRGB514:
-		info->dac_ops = &aty_dac_ibm514;
-		break;
-	    case DAC_ATI68860_B:
-	    case DAC_ATI68860_C:
-		info->dac_ops = &aty_dac_ati68860b;
-		break;
-	    case DAC_ATT20C408:
-	    case DAC_ATT21C498:
-		info->dac_ops = &aty_dac_att21c498;
-		break;
-	    default:
-		printk(" atyfb_set_par: DAC type not implemented yet!\n");
-		info->dac_ops = &aty_dac_unsupported;
-		break;
-	}
-	switch (clk_type) {
-	    case CLK_ATI18818_1:
-		info->pll_ops = &aty_pll_ati18818_1;
-		break;
-	    case CLK_STG1703:
-		info->pll_ops = &aty_pll_stg1703;
-		break;
-	    case CLK_CH8398:
-		info->pll_ops = &aty_pll_ch8398;
-		break;
-	    case CLK_ATT20C408:
-		info->pll_ops = &aty_pll_att20c408;
-		break;
-	    case CLK_IBMRGB514:
-		info->pll_ops = &aty_pll_ibm514;
-		break;
-	    default:
-		printk(" atyfb_set_par: CLK type not implemented yet!");
-		info->pll_ops = &aty_pll_unsupported;
-		break;
-	}
+        dac_type = DAC_IBMRGB514;
+        dac_subtype = DAC_IBMRGB514;
+        clk_type = CLK_IBMRGB514;
+#endif
+        switch (dac_subtype) {
+            case DAC_IBMRGB514:
+                info->dac_ops = &aty_dac_ibm514;
+                break;
+            case DAC_ATI68860_B:
+            case DAC_ATI68860_C:
+                info->dac_ops = &aty_dac_ati68860b;
+                break;
+            case DAC_ATT20C408:
+            case DAC_ATT21C498:
+                info->dac_ops = &aty_dac_att21c498;
+                break;
+            default:
+                printk(" atyfb_set_par: DAC type not implemented yet!\n");
+                info->dac_ops = &aty_dac_unsupported;
+                break;
+        }
+        switch (clk_type) {
+            case CLK_ATI18818_1:
+                info->pll_ops = &aty_pll_ati18818_1;
+                break;
+            case CLK_STG1703:
+                info->pll_ops = &aty_pll_stg1703;
+                break;
+            case CLK_CH8398:
+                info->pll_ops = &aty_pll_ch8398;
+                break;
+            case CLK_ATT20C408:
+                info->pll_ops = &aty_pll_att20c408;
+                break;
+            case CLK_IBMRGB514:
+                info->pll_ops = &aty_pll_ibm514;
+                break;
+            default:
+                printk(" atyfb_set_par: CLK type not implemented yet!");
+                info->pll_ops = &aty_pll_unsupported;
+                break;
+        }
     }
 #endif /* CONFIG_FB_ATY_GX */
 #ifdef CONFIG_FB_ATY_CT
     if (M64_HAS(INTEGRATED)) {
-	info->bus_type = PCI;
-	info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07);
-	ramname = aty_ct_ram[info->ram_type];
-	info->dac_ops = &aty_dac_ct;
-	info->pll_ops = &aty_pll_ct;
-	/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
-	if (mclk == 67 && info->ram_type < SDRAM)
-	    mclk = 63;
+        info->bus_type = PCI;
+        info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07);
+        ramname = aty_ct_ram[info->ram_type];
+        info->dac_ops = &aty_dac_ct;
+        info->pll_ops = &aty_pll_ct;
+	/*
+	 * I disable the hack below because it is completely unreliable. 
+	 * DRAM at 67 is very well imaginable. If a chip is indeed clocked
+	 * below it's official clock rate because it is equiped with
+	 * too slow memory the driver information table
+	 * in the BIOS will contain the right value. So if you need it
+	 * write code to scan the driver information table, it will work
+	 * in any case the chip is clocked lower than the official rate
+	 * instead of just cases where the mclk is 67 MHz.
+	 * (Daniel Mantione, 25 may 2003)
+	 */
+        /* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
+/*        if (xclk == 67 && info->ram_type < SDRAM)
+             xclk = 63;*/
     }
 #endif /* CONFIG_FB_ATY_CT */
 
     info->ref_clk_per = 1000000000000ULL/14318180;
     xtal = "14.31818";
     if (M64_HAS(GTB_DSP) && (pll_ref_div = aty_ld_pll(PLL_REF_DIV, info))) {
-	int diff1, diff2;
-	diff1 = 510*14/pll_ref_div-pll;
-	diff2 = 510*29/pll_ref_div-pll;
-	if (diff1 < 0)
-	    diff1 = -diff1;
-	if (diff2 < 0)
-	    diff2 = -diff2;
-	if (diff2 < diff1) {
-	    info->ref_clk_per = 1000000000000ULL/29498928;
-	    xtal = "29.498928";
-	}
+        int diff1, diff2;
+        diff1 = 510*14/pll_ref_div-pll;
+        diff2 = 510*29/pll_ref_div-pll;
+        if (diff1 < 0)
+            diff1 = -diff1;
+        if (diff2 < 0)
+            diff2 = -diff2;
+        if (diff2 < diff1) {
+            info->ref_clk_per = 1000000000000ULL/29498928;
+            xtal = "29.498928";
+        }
     }
 
     i = aty_ld_le32(MEM_CNTL, info);
     gtb_memsize = M64_HAS(GTB_DSP);
     if (gtb_memsize)
-	switch (i & 0xF) {	/* 0xF used instead of MEM_SIZE_ALIAS */
-	    case MEM_SIZE_512K:
-		info->total_vram = 0x80000;
-		break;
-	    case MEM_SIZE_1M:
-		info->total_vram = 0x100000;
-		break;
-	    case MEM_SIZE_2M_GTB:
-		info->total_vram = 0x200000;
-		break;
-	    case MEM_SIZE_4M_GTB:
-		info->total_vram = 0x400000;
-		break;
-	    case MEM_SIZE_6M_GTB:
-		info->total_vram = 0x600000;
-		break;
-	    case MEM_SIZE_8M_GTB:
-		info->total_vram = 0x800000;
-		break;
-	    default:
-		info->total_vram = 0x80000;
-	}
+        switch (i & 0xF) {      /* 0xF used instead of MEM_SIZE_ALIAS */
+            case MEM_SIZE_512K:
+                info->total_vram = 0x80000;
+                break;
+            case MEM_SIZE_1M:
+                info->total_vram = 0x100000;
+                break;
+            case MEM_SIZE_2M_GTB:
+                info->total_vram = 0x200000;
+                break;
+            case MEM_SIZE_4M_GTB:
+                info->total_vram = 0x400000;
+                break;
+            case MEM_SIZE_6M_GTB:
+                info->total_vram = 0x600000;
+                break;
+            case MEM_SIZE_8M_GTB:
+                info->total_vram = 0x800000;
+                break;
+            default:
+                info->total_vram = 0x80000;
+        }
     else
-	switch (i & MEM_SIZE_ALIAS) {
-	    case MEM_SIZE_512K:
-		info->total_vram = 0x80000;
-		break;
-	    case MEM_SIZE_1M:
-		info->total_vram = 0x100000;
-		break;
-	    case MEM_SIZE_2M:
-		info->total_vram = 0x200000;
-		break;
-	    case MEM_SIZE_4M:
-		info->total_vram = 0x400000;
-		break;
-	    case MEM_SIZE_6M:
-		info->total_vram = 0x600000;
-		break;
-	    case MEM_SIZE_8M:
-		info->total_vram = 0x800000;
-		break;
-	    default:
-		info->total_vram = 0x80000;
-	}
+        switch (i & MEM_SIZE_ALIAS) {
+            case MEM_SIZE_512K:
+                info->total_vram = 0x80000;
+                break;
+            case MEM_SIZE_1M:
+                info->total_vram = 0x100000;
+                break;
+            case MEM_SIZE_2M:
+                info->total_vram = 0x200000;
+                break;
+            case MEM_SIZE_4M:
+                info->total_vram = 0x400000;
+                break;
+            case MEM_SIZE_6M:
+                info->total_vram = 0x600000;
+                break;
+            case MEM_SIZE_8M:
+                info->total_vram = 0x800000;
+                break;
+            default:
+                info->total_vram = 0x80000;
+        }
 
     if (M64_HAS(MAGIC_VRAM_SIZE)) {
-	if (aty_ld_le32(CONFIG_STAT1, info) & 0x40000000)
-	  info->total_vram += 0x400000;
+        if (aty_ld_le32(CONFIG_STAT1, info) & 0x40000000)
+          info->total_vram += 0x400000;
     }
 
     if (default_vram) {
-	info->total_vram = default_vram*1024;
-	i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
-	if (info->total_vram <= 0x80000)
-	    i |= MEM_SIZE_512K;
-	else if (info->total_vram <= 0x100000)
-	    i |= MEM_SIZE_1M;
-	else if (info->total_vram <= 0x200000)
-	    i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
-	else if (info->total_vram <= 0x400000)
-	    i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
-	else if (info->total_vram <= 0x600000)
-	    i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
-	else
-	    i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
-	aty_st_le32(MEM_CNTL, i, info);
+        info->total_vram = default_vram*1024;
+        i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
+        if (info->total_vram <= 0x80000)
+            i |= MEM_SIZE_512K;
+        else if (info->total_vram <= 0x100000)
+            i |= MEM_SIZE_1M;
+        else if (info->total_vram <= 0x200000)
+            i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
+        else if (info->total_vram <= 0x400000)
+            i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
+        else if (info->total_vram <= 0x600000)
+            i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
+        else
+            i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
+        aty_st_le32(MEM_CNTL, i, info);
     }
     if (default_pll)
-	pll = default_pll;
+        pll = default_pll;
     if (default_mclk)
-	mclk = default_mclk;
-
-    printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
-    	   info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20),
-    	   info->total_vram == 0x80000 ? 'K' : 'M', ramname, xtal, pll, mclk);
-
-    if (mclk < 44)
-	info->mem_refresh_rate = 0;	/* 000 = 10 Mhz - 43 Mhz */
-    else if (mclk < 50)
-	info->mem_refresh_rate = 1;	/* 001 = 44 Mhz - 49 Mhz */
-    else if (mclk < 55)
-	info->mem_refresh_rate = 2;	/* 010 = 50 Mhz - 54 Mhz */
-    else if (mclk < 66)
-	info->mem_refresh_rate = 3;	/* 011 = 55 Mhz - 65 Mhz */
-    else if (mclk < 75)
-	info->mem_refresh_rate = 4;	/* 100 = 66 Mhz - 74 Mhz */
-    else if (mclk < 80)
-	info->mem_refresh_rate = 5;	/* 101 = 75 Mhz - 79 Mhz */
-    else if (mclk < 100)
-	info->mem_refresh_rate = 6;	/* 110 = 80 Mhz - 100 Mhz */
+        mclk = default_mclk;
+    if (default_xclk)
+        xclk = default_xclk;
+
+    printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d Mhz XCLK\n",
+           info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20),
+           info->total_vram == 0x80000 ? 'K' : 'M', ramname, xtal, pll, mclk,
+           xclk);
+
+    if (xclk < 44)
+        info->mem_refresh_rate = 0;     /* 000 = 10 Mhz - 43 Mhz */
+    else if (xclk < 50)
+        info->mem_refresh_rate = 1;     /* 001 = 44 Mhz - 49 Mhz */
+    else if (xclk < 55)
+        info->mem_refresh_rate = 2;     /* 010 = 50 Mhz - 54 Mhz */
+    else if (xclk < 66)
+        info->mem_refresh_rate = 3;     /* 011 = 55 Mhz - 65 Mhz */
+    else if (xclk < 75)
+        info->mem_refresh_rate = 4;     /* 100 = 66 Mhz - 74 Mhz */
+    else if (xclk < 80)
+        info->mem_refresh_rate = 5;     /* 101 = 75 Mhz - 79 Mhz */
+    else if (xclk < 100)
+        info->mem_refresh_rate = 6;     /* 110 = 80 Mhz - 100 Mhz */
     else
-	info->mem_refresh_rate = 7;	/* 111 = 100 Mhz and above */
+        info->mem_refresh_rate = 7;     /* 111 = 100 Mhz and above */
     info->pll_per = 1000000/pll;
-    info->mclk_per = 1000000/mclk;
+    if ((mclk < 0) || (xclk < 0)) {
+        info->mclk_per = 0;
+        info->xclk_per = 0;
+    } else {
+        info->mclk_per = 1000000/mclk;
+        info->xclk_per = 1000000/xclk;
+    };
 
 #ifdef DEBUG
     if (M64_HAS(INTEGRATED)) {
-	int i;
-	printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
-	       "DSP_CONFIG DSP_ON_OFF\n"
-	       "%08x %08x %08x %08x     %08x      %08x   %08x\n"
-	       "PLL",
-	       aty_ld_le32(BUS_CNTL, info), aty_ld_le32(DAC_CNTL, info),
-	       aty_ld_le32(MEM_CNTL, info), aty_ld_le32(EXT_MEM_CNTL, info),
-	       aty_ld_le32(CRTC_GEN_CNTL, info), aty_ld_le32(DSP_CONFIG, info),
-	       aty_ld_le32(DSP_ON_OFF, info));
-	for (i = 0; i < 16; i++)
-	    printk(" %02x", aty_ld_pll(i, info));
-	printk("\n");
+        int i;
+        printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
+               "DSP_CONFIG DSP_ON_OFF CLOCK_CNTL\n"
+               "%08x %08x %08x %08x     %08x      %08x   %08x   %08x\n"
+               "PLL",
+               aty_ld_le32(BUS_CNTL, info), aty_ld_le32(DAC_CNTL, info),
+               aty_ld_le32(MEM_CNTL, info), aty_ld_le32(EXT_MEM_CNTL, info),
+               aty_ld_le32(CRTC_GEN_CNTL, info), aty_ld_le32(DSP_CONFIG, info),
+               aty_ld_le32(DSP_ON_OFF, info), aty_ld_le32(CLOCK_CNTL ,info));
+        for (i = 0; i < 40; i++)
+            printk(" %02x", aty_ld_pll(i, info));
+        printk("\n");
+    }
+#endif
+    info->pll_ops->init_pll(info);
+#ifdef DEBUG
+    if (M64_HAS(INTEGRATED)) {
+        int i;
+        printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
+               "DSP_CONFIG DSP_ON_OFF\n"
+               "%08x %08x %08x %08x     %08x      %08x   %08x\n"
+               "PLL",
+               aty_ld_le32(BUS_CNTL, info), aty_ld_le32(DAC_CNTL, info),
+               aty_ld_le32(MEM_CNTL, info), aty_ld_le32(EXT_MEM_CNTL, info),
+               aty_ld_le32(CRTC_GEN_CNTL, info), aty_ld_le32(DSP_CONFIG, info),
+               aty_ld_le32(DSP_ON_OFF, info));
+        for (i = 0; i < 40; i++)
+            printk(" %02x", aty_ld_pll(i, info));
+        printk("\n");
     }
 #endif
 
@@ -2005,8 +2254,8 @@
      *  the full 8 MB of video RAM on 8 MB boards
      */
     if (info->total_vram == 0x800000 ||
-	(info->bus_type == ISA && info->total_vram == 0x400000))
-	    info->total_vram -= GUI_RESERVE;
+        (info->bus_type == ISA && info->total_vram == 0x400000))
+            info->total_vram -= GUI_RESERVE;
 
     /* Clear the video memory */
     fb_memset((void *)info->frame_buffer, 0, info->total_vram);
@@ -2026,12 +2275,12 @@
 
 #ifdef CONFIG_PMAC_BACKLIGHT
     if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) {
-	/* these bits let the 101 powerbook wake up from sleep -- paulus */
-	aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, info)
-		| (USE_F32KHZ | TRISTATE_MEM_EN), info);
+        /* these bits let the 101 powerbook wake up from sleep -- paulus */
+        aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, info)
+                | (USE_F32KHZ | TRISTATE_MEM_EN), info);
     }
     if (M64_HAS(MOBIL_BUS))
-	register_backlight_controller(&aty_backlight_controller, info, "ati");
+        register_backlight_controller(&aty_backlight_controller, info, "ati");
 #endif /* CONFIG_PMAC_BACKLIGHT */
 
 #ifdef MODULE
@@ -2040,53 +2289,53 @@
     memset(&var, 0, sizeof(var));
 #ifdef CONFIG_PPC
     if (_machine == _MACH_Pmac) {
-	    /*
-	     *  FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
-	     *         applies to all Mac video cards
-	     */
-	    if (mode_option) {
-		if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
-		    var = default_var;
-	    } else {
-		if (default_vmode == VMODE_CHOOSE) {
-		    if (M64_HAS(G3_PB_1024x768))
-			/* G3 PowerBook with 1024x768 LCD */
-			default_vmode = VMODE_1024_768_60;
-		    else if (machine_is_compatible("iMac"))
-			default_vmode = VMODE_1024_768_75;
-		    else if (machine_is_compatible("PowerBook2,1"))
-			/* iBook with 800x600 LCD */
-			default_vmode = VMODE_800_600_60;
-		    else
-			default_vmode = VMODE_640_480_67;
-		    sense = read_aty_sense(info);
-		    printk(KERN_INFO "atyfb: monitor sense=%x, mode %d\n",
-			   sense, mac_map_monitor_sense(sense));
-		}
-		if (default_vmode <= 0 || default_vmode > VMODE_MAX)
-		    default_vmode = VMODE_640_480_60;
+            /*
+             *  FIXME: The NVRAM stuff should be put in a Mac-specific file, as it
+             *         applies to all Mac video cards
+             */
+            if (mode_option) {
+                if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
+                    var = default_var;
+            } else {
+                if (default_vmode == VMODE_CHOOSE) {
+                    if (M64_HAS(G3_PB_1024x768))
+                        /* G3 PowerBook with 1024x768 LCD */
+                        default_vmode = VMODE_1024_768_60;
+                    else if (machine_is_compatible("iMac"))
+                        default_vmode = VMODE_1024_768_75;
+                    else if (machine_is_compatible("PowerBook2,1"))
+                        /* iBook with 800x600 LCD */
+                        default_vmode = VMODE_800_600_60;
+                    else
+                        default_vmode = VMODE_640_480_67;
+                    sense = read_aty_sense(info);
+                    printk(KERN_INFO "atyfb: monitor sense=%x, mode %d\n",
+                           sense, mac_map_monitor_sense(sense));
+                }
+                if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+                    default_vmode = VMODE_640_480_60;
 #ifdef CONFIG_NVRAM
-		if (default_cmode == CMODE_NVRAM)
-		    default_cmode = nvram_read_byte(NV_CMODE);
+                if (default_cmode == CMODE_NVRAM)
+                    default_cmode = nvram_read_byte(NV_CMODE);
 #endif
-		if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
-		    default_cmode = CMODE_8;
-		if (mac_vmode_to_var(default_vmode, default_cmode, &var))
-		    var = default_var;
-	    }
+                if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
+                    default_cmode = CMODE_8;
+                if (mac_vmode_to_var(default_vmode, default_cmode, &var))
+                    var = default_var;
+            }
     }
     else if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
-	var = default_var;
+        var = default_var;
 #else /* !CONFIG_PPC */
 #ifdef __sparc__
     if (mode_option) {
-    	if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
-	    var = default_var;
+        if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
+            var = default_var;
     } else
-	var = default_var;
+        var = default_var;
 #else
     if (!fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0, NULL, 8))
-	var = default_var;
+        var = default_var;
 #endif /* !__sparc__ */
 #endif /* !CONFIG_PPC */
 #endif /* !MODULE */
@@ -2096,49 +2345,66 @@
         var.accel_flags |= FB_ACCELF_TEXT;
 
     if (var.yres == var.yres_virtual) {
-	u32 vram = (info->total_vram - (PAGE_SIZE << 2));
-	var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
-	if (var.yres_virtual < var.yres)
-		var.yres_virtual = var.yres;
+        u32 vram = (info->total_vram - (PAGE_SIZE << 2));
+        var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
+        if (var.yres_virtual < var.yres)
+                var.yres_virtual = var.yres;
     }
 
-    if (atyfb_decode_var(&var, &info->default_par, info)) {
-	printk("atyfb: can't set default video mode\n");
-	return 0;
+    monitors_enabled = atyfb_monitors_enabled(info);
+
+    if (atyfb_decode_var(&var, &info->default_par, info, monitors_enabled)) {
+        printk("atyfb: can't set default video mode\n");
+        return 0;
     }
 
 #ifdef __sparc__
     atyfb_save_palette(&info->fb_info, 0);
 #endif
     for (j = 0; j < 16; j++) {
-	k = color_table[j];
-	info->palette[j].red = default_red[k];
-	info->palette[j].green = default_grn[k];
-	info->palette[j].blue = default_blu[k];
+        k = color_table[j];
+        info->palette[j].red = default_red[k];
+        info->palette[j].green = default_grn[k];
+        info->palette[j].blue = default_blu[k];
     }
 
 #ifdef CONFIG_FB_ATY_CT
     if (curblink && M64_HAS(INTEGRATED)) {
-	info->cursor = aty_init_cursor(info);
-	if (info->cursor) {
-	    info->dispsw.cursor = atyfb_cursor;
-	    info->dispsw.set_font = atyfb_set_font;
-	}
+        info->cursor = aty_init_cursor(info);
+        if (info->cursor) {
+            info->dispsw.cursor = atyfb_cursor;
+            info->dispsw.set_font = atyfb_set_font;
+        }
     }
 #endif /* CONFIG_FB_ATY_CT */
 
     atyfb_set_var(&var, -1, &info->fb_info);
 
     if (register_framebuffer(&info->fb_info) < 0)
-	return 0;
+        return 0;
 
     info->next = fb_list;
     fb_list = info;
 
     printk("fb%d: %s frame buffer device on %s\n",
-	   GET_FB_IDX(info->fb_info.node), atyfb_name, name);
+           GET_FB_IDX(info->fb_info.node), atyfb_name, name);
     return 1;
 }
+						    
+void __init aty_init_register_array(struct fb_info_aty *info)
+{
+    u32 **p, **q;
+    u32 *i;
+
+    i = (u32 *) info->ati_regbase;
+    p = (u32 **) info->ati_regaddr;
+    q = p + 256;
+    do {
+        *p = i;
+        i++;
+        p++;
+    } while (p != q);
+};
 
 int __init atyfb_init(void)
 {
@@ -2157,339 +2423,544 @@
 
     /* Do not attach when we have a serial console. */
     if (!con_is_present())
-	return -ENXIO;
+        return -ENXIO;
 #else
     u16 tmp;
     int aux_app;
     unsigned long raddr;
 #endif
+#if defined(CONFIG_FB_ATY_GENERIC_LCD)
+    u16 lcd_ofs;
+    u32 driv_inf_tab,sig,rom_addr;
+#endif
 
     while ((pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) {
-	if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
-	    struct resource *rp;
+        if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+            struct resource *rp;
 #ifndef __sparc__
-	    struct resource *rrp;
+            struct resource *rrp;
 #endif
 
-	    for (i = sizeof(aty_chips)/sizeof(*aty_chips)-1; i >= 0; i--)
-		if (pdev->device == aty_chips[i].pci_id)
-		    break;
-	    if (i < 0)
-		continue;
-
-	    info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
-	    if (!info) {
-		printk("atyfb_init: can't alloc fb_info_aty\n");
-		return -ENXIO;
-	    }
-	    memset(info, 0, sizeof(struct fb_info_aty));
-
-	    rp = &pdev->resource[0];
-	    if (rp->flags & IORESOURCE_IO)
-		    rp = &pdev->resource[1];
-	    addr = rp->start;
-	    if (!addr)
-		continue;
-
-	    res_start = rp->start;
-	    res_size = rp->end-rp->start+1;
-	    if (!request_mem_region(res_start, res_size, "atyfb"))
-		continue;
+            for (i = sizeof(aty_chips)/sizeof(*aty_chips)-1; i >= 0; i--)
+                if (pdev->device == aty_chips[i].pci_id)
+                    break;
+            if (i < 0)
+                continue;
+
+            info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
+            if (!info) {
+                printk("atyfb_init: can't alloc fb_info_aty\n");
+                return -ENXIO;
+            }
+            memset(info, 0, sizeof(struct fb_info_aty));
+
+            rp = &pdev->resource[0];
+            if (rp->flags & IORESOURCE_IO)
+                    rp = &pdev->resource[1];
+            addr = rp->start;
+            if (!addr)
+                continue;
+
+            res_start = rp->start;
+            res_size = rp->end-rp->start+1;
+            if (!request_mem_region(res_start, res_size, "atyfb"))
+                continue;
 
 #ifdef __sparc__
-	    /*
-	     * Map memory-mapped registers.
-	     */
-	    info->ati_regbase = addr + 0x7ffc00UL;
-	    info->ati_regbase_phys = addr + 0x7ffc00UL;
-
-	    /*
-	     * Map in big-endian aperture.
-	     */
-	    info->frame_buffer = (unsigned long) addr + 0x800000UL;
-	    info->frame_buffer_phys = addr + 0x800000UL;
-
-	    /*
-	     * Figure mmap addresses from PCI config space.
-	     * Split Framebuffer in big- and little-endian halfs.
-	     */
-	    for (i = 0; i < 6 && pdev->resource[i].start; i++)
-		/* nothing */;
-	    j = i + 4;
-
-	    info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC);
-	    if (!info->mmap_map) {
-		printk("atyfb_init: can't alloc mmap_map\n");
-		kfree(info);
-		release_mem_region(res_start, res_size);
-		return -ENXIO;
-	    }
-	    memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
-
-	    for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
-		struct resource *rp = &pdev->resource[i];
-		int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
-		unsigned long base;
-		u32 size, pbase;
-
-		base = rp->start;
-
-		io = (rp->flags & IORESOURCE_IO);
-
-		size = rp->end - base + 1;
-
-		pci_read_config_dword(pdev, breg, &pbase);
-
-		if (io)
-			size &= ~1;
-
-		/*
-		 * Map the framebuffer a second time, this time without
-		 * the braindead _PAGE_IE setting. This is used by the
-		 * fixed Xserver, but we need to maintain the old mapping
-		 * to stay compatible with older ones...
-		 */
-		if (base == addr) {
-		    info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
-		    info->mmap_map[j].poff = base & PAGE_MASK;
-		    info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
-		    info->mmap_map[j].prot_mask = _PAGE_CACHE;
-		    info->mmap_map[j].prot_flag = _PAGE_E;
-		    j++;
-		}
-
-		/*
-		 * Here comes the old framebuffer mapping with _PAGE_IE
-		 * set for the big endian half of the framebuffer...
-		 */
-		if (base == addr) {
-		    info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
-		    info->mmap_map[j].poff = (base+0x800000) & PAGE_MASK;
-		    info->mmap_map[j].size = 0x800000;
-		    info->mmap_map[j].prot_mask = _PAGE_CACHE;
-		    info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE;
-		    size -= 0x800000;
-		    j++;
-		}
-
-		info->mmap_map[j].voff = pbase & PAGE_MASK;
-		info->mmap_map[j].poff = base & PAGE_MASK;
-		info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
-		info->mmap_map[j].prot_mask = _PAGE_CACHE;
-		info->mmap_map[j].prot_flag = _PAGE_E;
-		j++;
-	    }
-
-	    if (pdev->device != XL_CHIP_ID) {
-		    /*
-		     * Fix PROMs idea of MEM_CNTL settings...
-		     */
-		    mem = aty_ld_le32(MEM_CNTL, info);
-		    chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
-		    if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
-			!((chip_id >> 24) & 1)) {
-			switch (mem & 0x0f) {
-			    case 3:
-				mem = (mem & ~(0x0f)) | 2;
-				break;
-			    case 7:
-				mem = (mem & ~(0x0f)) | 3;
-				break;
-			    case 9:
-				mem = (mem & ~(0x0f)) | 4;
-				break;
-			    case 11:
-				mem = (mem & ~(0x0f)) | 5;
-				break;
-			    default:
-				break;
-			}
-			if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
-				mem &= ~(0x00700000);
-		    }
-		    mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
-		    aty_st_le32(MEM_CNTL, mem, info);
-	    }
-
-	    /*
-	     * If this is the console device, we will set default video
-	     * settings to what the PROM left us with.
-	     */
-	    node = prom_getchild(prom_root_node);
-	    node = prom_searchsiblings(node, "aliases");
-	    if (node) {
-		len = prom_getproperty(node, "screen", prop, sizeof(prop));
-		if (len > 0) {
-		    prop[len] = '\0';
-		    node = prom_finddevice(prop);
-		} else {
-		    node = 0;
-		}
-	    }
-
-	    pcp = pdev->sysdata;
-	    if (node == pcp->prom_node) {
-
-		struct fb_var_screeninfo *var = &default_var;
-		unsigned int N, P, Q, M, T, R;
-		u32 v_total, h_total;
-		struct crtc crtc;
-		u8 pll_regs[16];
-		u8 clock_cntl;
-
-		crtc.vxres = prom_getintdefault(node, "width", 1024);
-		crtc.vyres = prom_getintdefault(node, "height", 768);
-		crtc.bpp = prom_getintdefault(node, "depth", 8);
-		crtc.xoffset = crtc.yoffset = 0;
-		crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, info);
-		crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, info);
-		crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, info);
-		crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, info);
-		crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, info);
-		aty_crtc_to_var(&crtc, var);
-
-		h_total = var->xres + var->right_margin +
-			  var->hsync_len + var->left_margin;
-		v_total = var->yres + var->lower_margin +
-			  var->vsync_len + var->upper_margin;
-
-		/*
-		 * Read the PLL to figure actual Refresh Rate.
-		 */
-    		clock_cntl = aty_ld_8(CLOCK_CNTL, info);
-		/* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
-		for (i = 0; i < 16; i++)
-			pll_regs[i] = aty_ld_pll(i, info);
-
-		/*
-		 * PLL Reference Divider M:
-		 */
-		M = pll_regs[2];
-
-		/*
-		 * PLL Feedback Divider N (Dependant on CLOCK_CNTL):
-		 */
-		N = pll_regs[7 + (clock_cntl & 3)];
-
-		/*
-		 * PLL Post Divider P (Dependant on CLOCK_CNTL):
-		 */
-		P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
-
-		/*
-		 * PLL Divider Q:
-		 */
-		Q = N / P;
-
-		/*
-		 * Target Frequency:
-		 *
-		 *      T * M
-		 * Q = -------
-		 *      2 * R
-		 *
-		 * where R is XTALIN (= 14318 or 29498 kHz).
-		 */
-		if (pdev->device == XL_CHIP_ID)
-			R = 29498;
-		else
-			R = 14318;
+            /*
+             * Map memory-mapped registers.
+             */
+            info->ati_regbase = addr + 0x7ffc00UL;
+            info->ati_regbase_phys = addr + 0x7ffc00UL;
+
+            /*
+             * Map in big-endian aperture.
+             */
+            info->frame_buffer = (unsigned long) addr + 0x800000UL;
+            info->frame_buffer_phys = addr + 0x800000UL;
+
+            /*
+             * Figure mmap addresses from PCI config space.
+             * Split Framebuffer in big- and little-endian halfs.
+             */
+            for (i = 0; i < 6 && pdev->resource[i].start; i++)
+                /* nothing */;
+            j = i + 4;
+
+            info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC);
+            if (!info->mmap_map) {
+                printk("atyfb_init: can't alloc mmap_map\n");
+                kfree(info);
+                release_mem_region(res_start, res_size);
+                return -ENXIO;
+            }
+            memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
+
+            for (i = 0, j = 2; i < 6 && pdev->resource[i].start; i++) {
+                struct resource *rp = &pdev->resource[i];
+                int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
+                unsigned long base;
+                u32 size, pbase;
+
+                base = rp->start;
+
+                io = (rp->flags & IORESOURCE_IO);
+
+                size = rp->end - base + 1;
+
+                pci_read_config_dword(pdev, breg, &pbase);
+
+                if (io)
+                        size &= ~1;
+
+                /*
+                 * Map the framebuffer a second time, this time without
+                 * the braindead _PAGE_IE setting. This is used by the
+                 * fixed Xserver, but we need to maintain the old mapping
+                 * to stay compatible with older ones...
+                 */
+                if (base == addr) {
+                    info->mmap_map[j].voff = (pbase + 0x10000000) & PAGE_MASK;
+                    info->mmap_map[j].poff = base & PAGE_MASK;
+                    info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
+                    info->mmap_map[j].prot_mask = _PAGE_CACHE;
+                    info->mmap_map[j].prot_flag = _PAGE_E;
+                    j++;
+                }
+
+                /*
+                 * Here comes the old framebuffer mapping with _PAGE_IE
+                 * set for the big endian half of the framebuffer...
+                 */
+                if (base == addr) {
+                    info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
+                    info->mmap_map[j].poff = (base+0x800000) & PAGE_MASK;
+                    info->mmap_map[j].size = 0x800000;
+                    info->mmap_map[j].prot_mask = _PAGE_CACHE;
+                    info->mmap_map[j].prot_flag = _PAGE_E|_PAGE_IE;
+                    size -= 0x800000;
+                    j++;
+                }
+
+                info->mmap_map[j].voff = pbase & PAGE_MASK;
+                info->mmap_map[j].poff = base & PAGE_MASK;
+                info->mmap_map[j].size = (size + ~PAGE_MASK) & PAGE_MASK;
+                info->mmap_map[j].prot_mask = _PAGE_CACHE;
+                info->mmap_map[j].prot_flag = _PAGE_E;
+                j++;
+            }
+
+            if (pdev->device != XL_CHIP_ID) {
+                    /*
+                     * Fix PROMs idea of MEM_CNTL settings...
+                     */
+                    mem = aty_ld_le32(MEM_CNTL, info);
+                    chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
+                    if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
+                        !((chip_id >> 24) & 1)) {
+                        switch (mem & 0x0f) {
+                            case 3:
+                                mem = (mem & ~(0x0f)) | 2;
+                                break;
+                            case 7:
+                                mem = (mem & ~(0x0f)) | 3;
+                                break;
+                            case 9:
+                                mem = (mem & ~(0x0f)) | 4;
+                                break;
+                            case 11:
+                                mem = (mem & ~(0x0f)) | 5;
+                                break;
+                            default:
+                                break;
+                        }
+                        if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
+                                mem &= ~(0x00700000);
+                    }
+                    mem &= ~(0xcf80e000);       /* Turn off all undocumented bits. */
+                    aty_st_le32(MEM_CNTL, mem, info);
+            }
+
+            /*
+             * If this is the console device, we will set default video
+             * settings to what the PROM left us with.
+             */
+            node = prom_getchild(prom_root_node);
+            node = prom_searchsiblings(node, "aliases");
+            if (node) {
+                len = prom_getproperty(node, "screen", prop, sizeof(prop));
+                if (len > 0) {
+                    prop[len] = '\0';
+                    node = prom_finddevice(prop);
+                } else {
+                    node = 0;
+                }
+            }
+
+            pcp = pdev->sysdata;
+            if (node == pcp->prom_node) {
+
+                struct fb_var_screeninfo *var = &default_var;
+                unsigned int N, P, Q, M, T, R;
+                u32 v_total, h_total;
+                struct crtc crtc;
+                u8 pll_regs[16];
+                u8 clock_cntl;
+
+                crtc.vxres = prom_getintdefault(node, "width", 1024);
+                crtc.vyres = prom_getintdefault(node, "height", 768);
+                crtc.bpp = prom_getintdefault(node, "depth", 8);
+                crtc.xoffset = crtc.yoffset = 0;
+                crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, info);
+                crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, info);
+                crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, info);
+                crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, info);
+                crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, info);
+                aty_crtc_to_var(&crtc, var);
+
+                h_total = var->xres + var->right_margin +
+                          var->hsync_len + var->left_margin;
+                v_total = var->yres + var->lower_margin +
+                          var->vsync_len + var->upper_margin;
+
+                /*
+                 * Read the PLL to figure actual Refresh Rate.
+                 */
+                clock_cntl = aty_ld_8(CLOCK_CNTL, info);
+                /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
+                for (i = 0; i < 16; i++)
+                        pll_regs[i] = aty_ld_pll(i, info);
+
+                /*
+                 * PLL Reference Divider M:
+                 */
+                M = pll_regs[2];
+
+                /*
+                 * PLL Feedback Divider N (Dependant on CLOCK_CNTL):
+                 */
+                N = pll_regs[7 + (clock_cntl & 3)];
+
+                /*
+                 * PLL Post Divider P (Dependant on CLOCK_CNTL):
+                 */
+                P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
+
+                /*
+                 * PLL Divider Q:
+                 */
+                Q = N / P;
+
+                /*
+                 * Target Frequency:
+                 *
+                 *      T * M
+                 * Q = -------
+                 *      2 * R
+                 *
+                 * where R is XTALIN (= 14318 or 29498 kHz).
+                 */
+                if (pdev->device == XL_CHIP_ID)
+                        R = 29498;
+                else
+                        R = 14318;
 
-		T = 2 * Q * R / M;
+                T = 2 * Q * R / M;
 
-		default_var.pixclock = 1000000000 / T;
-	    }
+                default_var.pixclock = 1000000000 / T;
+            }
 #else /* __sparc__ */
 
-	    aux_app = 0;
-	    raddr = addr + 0x7ff000UL;
-	    rrp = &pdev->resource[2];
-	    if ((rrp->flags & IORESOURCE_MEM)
-		&& request_mem_region(rrp->start, rrp->end - rrp->start + 1,
-				      "atyfb")) {
-		    aux_app = 1;
-		    raddr = rrp->start;
-		    printk(KERN_INFO "atyfb: using auxiliary register aperture\n");
-	    }
-
-	    info->ati_regbase_phys = raddr;
-	    info->ati_regbase = (unsigned long) ioremap(raddr, 0x1000);
-
-	    if(!info->ati_regbase) {
-		    kfree(info);
-		    release_mem_region(res_start, res_size);
-		    return -ENOMEM;
-	    }
-
-	    info->ati_regbase_phys += aux_app? 0x400: 0xc00;
-	    info->ati_regbase += aux_app? 0x400: 0xc00;
-
-	    /*
-	     * Enable memory-space accesses using config-space
-	     * command register.
-	     */
-	    pci_read_config_word(pdev, PCI_COMMAND, &tmp);
-	    if (!(tmp & PCI_COMMAND_MEMORY)) {
-		tmp |= PCI_COMMAND_MEMORY;
-		pci_write_config_word(pdev, PCI_COMMAND, tmp);
-	    }
+            aux_app = 0;
+            raddr = addr + 0x7ff000UL;
+            rrp = &pdev->resource[2];
+            if ((rrp->flags & IORESOURCE_MEM)
+                && request_mem_region(rrp->start, rrp->end - rrp->start + 1,
+                                      "atyfb")) {
+                    aux_app = 1;
+                    raddr = rrp->start;
+                    printk(KERN_INFO "atyfb: using auxiliary register aperture\n");
+            }
+
+            info->ati_regbase_phys = raddr;
+            info->ati_regbase = (unsigned long) ioremap(raddr, 0x1000);
+
+            if(!info->ati_regbase) {
+                    kfree(info);
+                    release_mem_region(res_start, res_size);
+                    return -ENOMEM;
+            }
+
+            info->ati_regbase_phys += aux_app? 0x400: 0xc00;
+            info->ati_regbase += aux_app? 0x400: 0xc00;
+
+            /*
+             * Enable memory-space accesses using config-space
+             * command register.
+             */
+            pci_read_config_word(pdev, PCI_COMMAND, &tmp);
+            if (!(tmp & PCI_COMMAND_MEMORY)) {
+                tmp |= PCI_COMMAND_MEMORY;
+                pci_write_config_word(pdev, PCI_COMMAND, tmp);
+            }
 
 #ifdef __BIG_ENDIAN
-	    /* Use the big-endian aperture */
-	    addr += 0x800000;
+            /* Use the big-endian aperture */
+            addr += 0x800000;
 #endif
 
-	    /* Map in frame buffer */
-	    info->frame_buffer_phys = addr;
-	    info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
-
-	    if(!info->frame_buffer) {
-		    kfree(info);
-		    release_mem_region(res_start, res_size);
-		    return -ENXIO;
-	    }
+            /* Map in frame buffer */
+            info->frame_buffer_phys = addr;
+            info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
+
+            aty_init_register_array(info);
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+            /* To support an LCD panel, we should know it's dimensions and
+               it's desired pixel clock.
+               There are two ways to do it:
+                 - Check the startup video mode and calculate the panel
+                   size from it. This is unreliable.
+                 - Read it from the driver information table in the video BIOS.
+                 
+               So, we try to find a BIOS and get access to it.
+            */
+            rom_addr = 0xc0000 + ((aty_ld_le32(SCRATCH_REG1,info) & 0x7f) << 11);
+            info->bios_base_phys = rom_addr;
+            info->bios_base = (unsigned long)ioremap(rom_addr,0x10000);
+            
+            /* The BIOS starts with 0xaa55. */
+            if (*((u16 *)info->bios_base) == 0xaa55) {
+                printk(KERN_INFO "atyfb: Mach64 BIOS is located at %x, mapped at %x.\n",
+                 (u32)info->bios_base_phys,(u32)info->bios_base);
+            
+                /* Address of driver information table is at offset 0x78. */
+                driv_inf_tab=info->bios_base + *((u16 *)(info->bios_base+0x78));
+                
+                /* Check for the driver information table signature. */
+                sig = (*(u32 *)driv_inf_tab);
+                if ((sig == 0x54504c24) || /* Rage LT pro */
+                    (sig == 0x544d5224) || /* Rage mobility */
+                    (sig == 0x54435824) || /* Rage XC */
+                    (sig == 0x544c5824)) { /* Rage XL */
+                    printk(KERN_INFO "atyfb: BIOS contains driver information table.\n");
+                    lcd_ofs = (*(u16 *)(driv_inf_tab + 10));
+                    info->lcd_table = 0;
+                    if (lcd_ofs != 0) {
+                        info->lcd_table = info->bios_base + lcd_ofs;
+                    };
+                };
+            };
+            if (info->lcd_table != 0) {
+                char model[24];
+                char strbuf[16];
+                char refresh_rates_buf[100];
+                int id,tech,f,i,m,default_refresh_rate;
+                char *txtcolour;
+                char *txtmonitor;
+                char *txtdual;
+                char *txtformat;
+                u16 width,height,panel_type,refresh_rates;
+                u16 *lcdmodeptr;
+                u32 format;
+                u8 lcd_refresh_rates[16] = {50,56,60,67,70,72,75,76,85,90,100,120,140,150,160,200};
+                /* The most important information is the panel size at
+                   offset 25 and 27, but there's some other nice information
+                   which we print to the screen.
+                 */
+                id = *(u8 *)info->lcd_table;
+                strncpy(model,(char *)info->lcd_table+1,24);
+                model[23]=0;
+                
+                width = info->lcd_width = *(u16 *)(info->lcd_table+25);
+                height = info->lcd_height = *(u16 *)(info->lcd_table+27);
+                panel_type = *(u16 *)(info->lcd_table+29);
+                if (panel_type & 1)
+                    txtcolour = "colour";
+                else
+                    txtcolour = "monochrome";
+                if (panel_type & 2)
+                    txtdual = "dual (split) ";
+                else
+                    txtdual = "";
+                tech = (panel_type>>2) & 63;
+                switch (tech) {
+                    case 0:
+                        txtmonitor = "passive matrix";
+                        break;
+                    case 1:
+                        txtmonitor = "active matrix";
+                        break;
+                    case 2:
+                        txtmonitor = "active addressed STN";
+                        break;
+                    case 3:
+                        txtmonitor = "EL";
+                        break;
+                    case 4:
+                        txtmonitor = "plasma";
+                        break;
+                    default:
+                        txtmonitor = "unknown";
+                };
+                format = *(u32 *)(info->lcd_table+57);
+                if (tech == 0 || tech == 2) {
+                    switch (format & 7) {
+                        case 0:
+                            txtformat = "12 bit interface";
+                            break;
+                        case 1:
+                            txtformat = "16 bit interface";
+                            break;
+                        case 2:
+                            txtformat = "24 bit interface";
+                            break;
+                        default:
+                            txtformat = "unkown format";
+                    };
+                } else {
+                    switch (format & 7) {
+                        case 0:
+                            txtformat = "8 colours";
+                            break;
+                        case 1:
+                            txtformat = "512 colours";
+                            break;
+                        case 2:
+                            txtformat = "4096 colours";
+                            break;
+                        case 4:
+                            txtformat = "262144 colours (LT mode)";
+                            break;
+                        case 5:
+                            txtformat = "16777216 colours";
+                            break;
+                        case 6:
+                            txtformat = "262144 colours (FDPI-2 mode)";
+                            break;
+                        default:
+                            txtformat = "unkown format";
+                    };
+                };
+                printk(KERN_INFO "atyfb: %s%s %s monitor detected: %s\n        id=%d, %dx%d pixels, %s\n",
+                 txtdual,txtcolour,txtmonitor,model,id,width,height,txtformat);
+                refresh_rates_buf[0] = 0;
+                refresh_rates = *(u16 *)(info->lcd_table+62);
+                m = 1;
+                f = 0;
+                for (i=0;i<16;i++) {
+                    if (refresh_rates & m) {
+                        if (f == 0) {
+                            sprintf(strbuf,"%d",lcd_refresh_rates[i]);
+                            f++;
+                        } else
+                            sprintf(strbuf,",%d",lcd_refresh_rates[i]);
+                        strcat(refresh_rates_buf,strbuf);
+                    };
+                    m = m << 1;
+                };
+                default_refresh_rate = (*(u8 *)(info->lcd_table+61) & 0xf0) >> 4;
+                printk(KERN_INFO "        supports %s Hz refresh rates, default %d Hz\n",
+                 refresh_rates_buf,lcd_refresh_rates[default_refresh_rate]);
+                /* We now need to determine the crtc parameters for the
+                   lcd monitor. This is tricky, because they are not stored
+                   individually in the BIOS. Instead, the BIOS contains a
+                   table of display modes that work for this monitor.
+                   
+                   The idea is that we search for a mode of the same dimensions
+                   as the dimensions of the lcd monitor. Say our lcd monitor
+                   is 800x600 pixels, we search for a 800x600 monitor.
+                   The CRTC parameters we find here are the ones that we need
+                   to use to simulate other resolutions on the lcd screen.
+                 */
+                lcdmodeptr = (u16 *)(info->lcd_table + 64);
+                while (*lcdmodeptr != 0) {
+                    u32 modeptr;
+                    u16 mwidth,mheight;
+                    modeptr = info->bios_base + *lcdmodeptr;
+                    
+                    mwidth = *((u16 *)(modeptr+0));
+                    mheight = *((u16 *)(modeptr+2));
+                    
+                    if (mwidth == width && mheight == height) {
+                        info->lcd_pixclock = 100000000 / *((u16 *)(modeptr+9));
+                        info->lcd_htotal = *((u16 *)(modeptr+17)) & 511;
+                        info->lcd_hdisp = *((u16 *)(modeptr+19)) & 511;
+                        info->lcd_hsync_start = *((u16 *)(modeptr+21)) & 511;
+                        info->lcd_hsync_delay = (*((u16 *)(modeptr+21)) >> 9) & 7;
+                        info->lcd_hsync_width = *((u8 *)(modeptr+23)) & 63;
+                        info->lcd_vtotal = *((u16 *)(modeptr+24)) & 2047;
+                        info->lcd_vdisp = *((u16 *)(modeptr+26)) & 2047;
+                        info->lcd_vsync_start = *((u16 *)(modeptr+28)) & 2047;
+                        info->lcd_vsync_width = (*((u16 *)(modeptr+28)) >> 11) & 31;
+                        info->lcd_right = info->lcd_hsync_start - info->lcd_hdisp;
+                        info->lcd_lower = info->lcd_vsync_start - info->lcd_vdisp;
+                        info->lcd_hblank_width = info->lcd_htotal - info->lcd_hdisp;
+                        info->lcd_vblank_width = info->lcd_vtotal - info->lcd_vdisp;
+                        break;
+                    };
+                    
+                    lcdmodeptr++;
+                };
+                if (*lcdmodeptr == 0) {
+                    printk(KERN_WARNING "atyfb: LCD monitor CRTC parameters not found!!!\n");
+                    /* To do: Switch to CRT if possible. */
+                } else {
+                    printk(KERN_INFO "        LCD CRTC parameters: %d %d %d %d %d %d %d %d %d %d\n",
+                     info->lcd_pixclock,info->lcd_htotal,info->lcd_hdisp,info->lcd_hsync_start,
+                     info->lcd_hsync_delay,info->lcd_hsync_width,info->lcd_vtotal,info->lcd_vdisp,
+                     info->lcd_vsync_start,info->lcd_vsync_width);
+                };
+            };
+#endif
+
+            if(!info->frame_buffer) {
+                    kfree(info);
+                    release_mem_region(res_start, res_size);
+                    return -ENXIO;
+            }
 
 #endif /* __sparc__ */
 
-	    if (!aty_init(info, "PCI")) {
-		if (info->mmap_map)
-		    kfree(info->mmap_map);
-		kfree(info);
-		release_mem_region(res_start, res_size);
-		return -ENXIO;
-	    }
+            if (!aty_init(info, "PCI")) {
+                if (info->mmap_map)
+                    kfree(info->mmap_map);
+                kfree(info);
+                release_mem_region(res_start, res_size);
+                return -ENXIO;
+            }
 
 #ifdef __sparc__
-	    if (!prom_palette)
-		prom_palette = atyfb_palette;
+            if (!prom_palette)
+                prom_palette = atyfb_palette;
 
-	    /*
-	     * Add /dev/fb mmap values.
-	     */
-	    info->mmap_map[0].voff = 0x8000000000000000UL;
-	    info->mmap_map[0].poff = info->frame_buffer & PAGE_MASK;
-	    info->mmap_map[0].size = info->total_vram;
-	    info->mmap_map[0].prot_mask = _PAGE_CACHE;
-	    info->mmap_map[0].prot_flag = _PAGE_E;
-	    info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram;
-	    info->mmap_map[1].poff = info->ati_regbase & PAGE_MASK;
-	    info->mmap_map[1].size = PAGE_SIZE;
-	    info->mmap_map[1].prot_mask = _PAGE_CACHE;
-	    info->mmap_map[1].prot_flag = _PAGE_E;
+            /*
+             * Add /dev/fb mmap values.
+             */
+            info->mmap_map[0].voff = 0x8000000000000000UL;
+            info->mmap_map[0].poff = info->frame_buffer & PAGE_MASK;
+            info->mmap_map[0].size = info->total_vram;
+            info->mmap_map[0].prot_mask = _PAGE_CACHE;
+            info->mmap_map[0].prot_flag = _PAGE_E;
+            info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram;
+            info->mmap_map[1].poff = info->ati_regbase & PAGE_MASK;
+            info->mmap_map[1].size = PAGE_SIZE;
+            info->mmap_map[1].prot_mask = _PAGE_CACHE;
+            info->mmap_map[1].prot_flag = _PAGE_E;
 #endif /* __sparc__ */
 
 #ifdef CONFIG_PMAC_PBOOK
-	    if (first_display == NULL)
-		    pmu_register_sleep_notifier(&aty_sleep_notifier);
-	    info->next = first_display;
-	    first_display = info;
+            if (first_display == NULL)
+                    pmu_register_sleep_notifier(&aty_sleep_notifier);
+            info->next = first_display;
+            first_display = info;
 #endif
 
 #ifdef CONFIG_FB_COMPAT_XPMAC
-	    if (!console_fb_info)
-		console_fb_info = &info->fb_info;
+            if (!console_fb_info)
+                console_fb_info = &info->fb_info;
 #endif /* CONFIG_FB_COMPAT_XPMAC */
-	}
+        }
     }
 
 #elif defined(CONFIG_ATARI)
@@ -2498,54 +2969,52 @@
     struct fb_info_aty *info;
 
     for (m64_num = 0; m64_num < mach64_count; m64_num++) {
-	if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
-	    !phys_guiregbase[m64_num]) {
-	    printk(" phys_*[%d] parameters not set => returning early. \n",
-		   m64_num);
-	    continue;
-	}
-
-	info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
-	if (!info) {
-	    printk("atyfb_init: can't alloc fb_info_aty\n");
-	    return -ENOMEM;
-	}
-	memset(info, 0, sizeof(struct fb_info_aty));
-
-	/*
-	 *  Map the video memory (physical address given) to somewhere in the
-	 *  kernel address space.
-	 */
-	info->frame_buffer = (unsigned long)ioremap(phys_vmembase[m64_num],
-						    phys_size[m64_num]);
-	info->frame_buffer_phys = info->frame_buffer;  /* Fake! */
-	info->ati_regbase = (unsigned long)ioremap(phys_guiregbase[m64_num],
-						   0x10000)+0xFC00ul;
-	info->ati_regbase_phys = info->ati_regbase;  /* Fake! */
-
-	aty_st_le32(CLOCK_CNTL, 0x12345678, info);
-	clock_r = aty_ld_le32(CLOCK_CNTL, info);
-
-	switch (clock_r & 0x003F) {
-	    case 0x12:
-		info->clk_wr_offset = 3;  /*  */
-		break;
-	    case 0x34:
-		info->clk_wr_offset = 2;  /* Medusa ST-IO ISA Adapter etc. */
-		break;
-	    case 0x16:
-		info->clk_wr_offset = 1;  /*  */
-		break;
-	    case 0x38:
-		info->clk_wr_offset = 0;  /* Panther 1 ISA Adapter (Gerald) */
-		break;
-	}
-
-	if (!aty_init(info, "ISA bus")) {
-	    kfree(info);
-	    /* This is insufficient! kernel_map has added two large chunks!! */
-	    return -ENXIO;
-	}
+        if (!phys_vmembase[m64_num] || !phys_size[m64_num] ||
+            !phys_guiregbase[m64_num]) {
+            printk(" phys_*[%d] parameters not set => returning early. \n",
+                   m64_num);
+            continue;
+        }
+
+        info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
+        if (!info) {
+            printk("atyfb_init: can't alloc fb_info_aty\n");
+            return -ENOMEM;
+        }
+        memset(info, 0, sizeof(struct fb_info_aty));
+
+        /*
+         *  Map the video memory (physical address given) to somewhere in the
+         *  kernel address space.
+         */
+        info->frame_buffer = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
+        info->frame_buffer_phys = info->frame_buffer;  /* Fake! */
+        info->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000)+0xFC00ul;
+        info->ati_regbase_phys = info->ati_regbase;  /* Fake! */
+
+        aty_st_le32(CLOCK_CNTL, 0x12345678, info);
+        clock_r = aty_ld_le32(CLOCK_CNTL, info);
+
+        switch (clock_r & 0x003F) {
+            case 0x12:
+                info->clk_wr_offset = 3;  /*  */
+                break;
+            case 0x34:
+                info->clk_wr_offset = 2;  /* Medusa ST-IO ISA Adapter etc. */
+                break;
+            case 0x16:
+                info->clk_wr_offset = 1;  /*  */
+                break;
+            case 0x38:
+                info->clk_wr_offset = 0;  /* Panther 1 ISA Adapter (Gerald) */
+                break;
+        }
+
+        if (!aty_init(info, "ISA bus")) {
+            kfree(info);
+            /* This is insufficient! kernel_map has added two large chunks!! */
+            return -ENXIO;
+        }
     }
 #endif /* CONFIG_ATARI */
     return 0;
@@ -2557,69 +3026,71 @@
     char *this_opt;
 
     if (!options || !*options)
-	return 0;
+        return 0;
 
     while ((this_opt = strsep(&options, ",")) != NULL) {
-	if (!strncmp(this_opt, "font:", 5)) {
-		char *p;
-		int i;
-
-		p = this_opt + 5;
-		for (i = 0; i < sizeof(fontname) - 1; i++)
-			if (!*p || *p == ' ' || *p == ',')
-				break;
-		memcpy(fontname, this_opt + 5, i);
-		fontname[i] = 0;
-	} else if (!strncmp(this_opt, "noblink", 7)) {
-		curblink = 0;
-	} else if (!strncmp(this_opt, "noaccel", 7)) {
-		noaccel = 1;
-	} else if (!strncmp(this_opt, "vram:", 5))
-		default_vram = simple_strtoul(this_opt+5, NULL, 0);
-	else if (!strncmp(this_opt, "pll:", 4))
-		default_pll = simple_strtoul(this_opt+4, NULL, 0);
-	else if (!strncmp(this_opt, "mclk:", 5))
-		default_mclk = simple_strtoul(this_opt+5, NULL, 0);
+        if (!strncmp(this_opt, "font:", 5)) {
+                char *p;
+                int i;
+
+                p = this_opt + 5;
+                for (i = 0; i < sizeof(fontname) - 1; i++)
+                        if (!*p || *p == ' ' || *p == ',')
+                                break;
+                memcpy(fontname, this_opt + 5, i);
+                fontname[i] = 0;
+        } else if (!strncmp(this_opt, "noblink", 7)) {
+                curblink = 0;
+        } else if (!strncmp(this_opt, "noaccel", 7)) {
+                noaccel = 1;
+        } else if (!strncmp(this_opt, "vram:", 5))
+                default_vram = simple_strtoul(this_opt+5, NULL, 0);
+        else if (!strncmp(this_opt, "pll:", 4))
+                default_pll = simple_strtoul(this_opt+4, NULL, 0);
+        else if (!strncmp(this_opt, "mclk:", 5))
+                default_mclk = simple_strtoul(this_opt+5, NULL, 0);
+        else if (!strncmp(this_opt, "xclk:", 5))
+                default_xclk = simple_strtoul(this_opt+5, NULL, 0);
 #ifdef CONFIG_PPC
-	else if (!strncmp(this_opt, "vmode:", 6)) {
-	    unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
-	    if (vmode > 0 && vmode <= VMODE_MAX)
-		default_vmode = vmode;
-	} else if (!strncmp(this_opt, "cmode:", 6)) {
-	    unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
-	    switch (cmode) {
-		case 0:
-		case 8:
-		    default_cmode = CMODE_8;
-		    break;
-		case 15:
-		case 16:
-		    default_cmode = CMODE_16;
-		    break;
-		case 24:
-		case 32:
-		    default_cmode = CMODE_32;
-		    break;
-	    }
-	}
+        else if (!strncmp(this_opt, "vmode:", 6)) {
+            unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
+            if (vmode > 0 && vmode <= VMODE_MAX)
+                default_vmode = vmode;
+        } else if (!strncmp(this_opt, "cmode:", 6)) {
+            unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
+            switch (cmode) {
+                case 0:
+                case 8:
+                    default_cmode = CMODE_8;
+                    break;
+                case 15:
+                case 16:
+                    default_cmode = CMODE_16;
+                    break;
+                case 24:
+                case 32:
+                    default_cmode = CMODE_32;
+                    break;
+            }
+        }
 #endif
 #ifdef CONFIG_ATARI
-	/*
-	 * Why do we need this silly Mach64 argument?
-	 * We are already here because of mach64= so its redundant.
-	 */
-	else if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) {
-	    static unsigned char m64_num;
-	    static char mach64_str[80];
-	    strncpy(mach64_str, this_opt+7, 80);
-	    if (!store_video_par(mach64_str, m64_num)) {
-		m64_num++;
-		mach64_count = m64_num;
-	    }
-	}
+        /*
+         * Why do we need this silly Mach64 argument?
+         * We are already here because of mach64= so its redundant.
+         */
+        else if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) {
+            static unsigned char m64_num;
+            static char mach64_str[80];
+            strncpy(mach64_str, this_opt+7, 80);
+            if (!store_video_par(mach64_str, m64_num)) {
+                m64_num++;
+                mach64_count = m64_num;
+            }
+        }
 #endif
-	else
-	    mode_option = this_opt;
+        else
+            mode_option = this_opt;
     }
     return 0;
 }
@@ -2634,20 +3105,20 @@
     printk("store_video_par() '%s' \n", video_str);
 
     if (!(p = strtoke(video_str, ";")) || !*p)
-	goto mach64_invalid;
+        goto mach64_invalid;
     vmembase = simple_strtoul(p, NULL, 0);
     if (!(p = strtoke(NULL, ";")) || !*p)
-	goto mach64_invalid;
+        goto mach64_invalid;
     size = simple_strtoul(p, NULL, 0);
     if (!(p = strtoke(NULL, ";")) || !*p)
-	goto mach64_invalid;
+        goto mach64_invalid;
     guiregbase = simple_strtoul(p, NULL, 0);
 
     phys_vmembase[m64_num] = vmembase;
     phys_size[m64_num] = size;
     phys_guiregbase[m64_num] = guiregbase;
     printk(" stored them all: $%08lX $%08lX $%08lX \n", vmembase, size,
-	   guiregbase);
+           guiregbase);
     return 0;
 
 mach64_invalid:
@@ -2662,14 +3133,14 @@
 
     sbegin  = s ? s : ssave;
     if (!sbegin)
-	return NULL;
+        return NULL;
     if (*sbegin == '\0') {
-	ssave = NULL;
-	return NULL;
+        ssave = NULL;
+        return NULL;
     }
     send = strpbrk(sbegin, ct);
     if (send && *send != '\0')
-	*send++ = '\0';
+        *send++ = '\0';
     ssave = send;
     return sbegin;
 }
@@ -2679,24 +3150,27 @@
 {
     struct fb_info_aty *info = (struct fb_info_aty *)fb;
     struct atyfb_par par;
+    u32 monitors_enabled;
 
     /* Do we have to save the colormap? */
     if (fb_display[currcon].cmap.len)
-	fb_get_cmap(&fb_display[currcon].cmap, 1, atyfb_getcolreg, fb);
+        fb_get_cmap(&fb_display[currcon].cmap, 1, atyfb_getcolreg, fb);
 
 #ifdef CONFIG_FB_ATY_CT
     /* Erase HW Cursor */
     if (info->cursor)
-	atyfb_cursor(&fb_display[currcon], CM_ERASE,
-		     info->cursor->pos.x, info->cursor->pos.y);
+        atyfb_cursor(&fb_display[currcon], CM_ERASE,
+                     info->cursor->pos.x, info->cursor->pos.y);
 #endif /* CONFIG_FB_ATY_CT */
 
     currcon = con;
 
-    atyfb_decode_var(&fb_display[con].var, &par, info);
+    monitors_enabled = atyfb_monitors_enabled(info);
+
+    atyfb_decode_var(&fb_display[con].var, &par, info, monitors_enabled);
     atyfb_set_par(&par, info);
     atyfb_set_dispsw(&fb_display[con], info, par.crtc.bpp,
-		     par.accel_flags & FB_ACCELF_TEXT);
+                     par.accel_flags & FB_ACCELF_TEXT);
 
     /* Install new colormap */
     do_install_cmap(con, fb);
@@ -2704,8 +3178,8 @@
 #ifdef CONFIG_FB_ATY_CT
     /* Install hw cursor */
     if (info->cursor) {
-	aty_set_cursor_color(info);
-	aty_set_cursor_shape(info);
+        aty_set_cursor_color(info);
+        aty_set_cursor_shape(info);
     }
 #endif /* CONFIG_FB_ATY_CT */
     return 1;
@@ -2722,32 +3196,32 @@
 
 #ifdef CONFIG_PMAC_BACKLIGHT
     if ((_machine == _MACH_Pmac) && blank)
-    	set_backlight_enable(0);
+        set_backlight_enable(0);
 #endif /* CONFIG_PMAC_BACKLIGHT */
 
     gen_cntl = aty_ld_8(CRTC_GEN_CNTL, info);
     if (blank > 0)
-	switch (blank-1) {
-	    case VESA_NO_BLANKING:
-		gen_cntl |= 0x40;
-		break;
-	    case VESA_VSYNC_SUSPEND:
-		gen_cntl |= 0x8;
-		break;
-	    case VESA_HSYNC_SUSPEND:
-		gen_cntl |= 0x4;
-		break;
-	    case VESA_POWERDOWN:
-		gen_cntl |= 0x4c;
-		break;
-	}
+        switch (blank-1) {
+            case VESA_NO_BLANKING:
+                gen_cntl |= 0x40;
+                break;
+            case VESA_VSYNC_SUSPEND:
+                gen_cntl |= 0x8;
+                break;
+            case VESA_HSYNC_SUSPEND:
+                gen_cntl |= 0x4;
+                break;
+            case VESA_POWERDOWN:
+                gen_cntl |= 0x4c;
+                break;
+        }
     else
-	gen_cntl &= ~(0x4c);
+        gen_cntl &= ~(0x4c);
     aty_st_8(CRTC_GEN_CNTL, gen_cntl, info);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
     if ((_machine == _MACH_Pmac) && !blank)
-    	set_backlight_enable(1);
+        set_backlight_enable(1);
 #endif /* CONFIG_PMAC_BACKLIGHT */
 }
 
@@ -2758,12 +3232,12 @@
      */
 
 static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			   u_int *transp, struct fb_info *fb)
+                           u_int *transp, struct fb_info *fb)
 {
     struct fb_info_aty *info = (struct fb_info_aty *)fb;
 
     if (regno > 255)
-	return 1;
+        return 1;
     *red = (info->palette[regno].red<<8) | info->palette[regno].red;
     *green = (info->palette[regno].green<<8) | info->palette[regno].green;
     *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
@@ -2779,13 +3253,13 @@
      */
 
 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *fb)
+                           u_int transp, struct fb_info *fb)
 {
     struct fb_info_aty *info = (struct fb_info_aty *)fb;
     int i, scale;
 
     if (regno > 255)
-	return 1;
+        return 1;
     red >>= 8;
     green >>= 8;
     blue >>= 8;
@@ -2794,42 +3268,35 @@
     info->palette[regno].blue = blue;
     i = aty_ld_8(DAC_CNTL, info) & 0xfc;
     if (M64_HAS(EXTRA_BRIGHT))
-	i |= 0x2;	/*DAC_CNTL|0x2 turns off the extra brightness for gt*/
+        i |= 0x2;       /*DAC_CNTL|0x2 turns off the extra brightness for gt*/
     aty_st_8(DAC_CNTL, i, info);
     aty_st_8(DAC_MASK, 0xff, info);
     scale = (M64_HAS(INTEGRATED) && info->current_par.crtc.bpp == 16) ? 3 : 0;
-#ifdef CONFIG_ATARI
-    out_8(&info->aty_cmap_regs->windex, regno << scale);
-    out_8(&info->aty_cmap_regs->lut, red);
-    out_8(&info->aty_cmap_regs->lut, green);
-    out_8(&info->aty_cmap_regs->lut, blue);
-#else
     writeb(regno << scale, &info->aty_cmap_regs->windex);
     writeb(red, &info->aty_cmap_regs->lut);
     writeb(green, &info->aty_cmap_regs->lut);
     writeb(blue, &info->aty_cmap_regs->lut);
-#endif
     if (regno < 16)
-	switch (info->current_par.crtc.bpp) {
+        switch (info->current_par.crtc.bpp) {
 #ifdef FBCON_HAS_CFB16
-	    case 16:
-		info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
-						regno;
-		break;
+            case 16:
+                info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
+                                                regno;
+                break;
 #endif
 #ifdef FBCON_HAS_CFB24
-	    case 24:
-		info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
-						regno;
-		break;
+            case 24:
+                info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
+                                                regno;
+                break;
 #endif
 #ifdef FBCON_HAS_CFB32
-	    case 32:
-		i = (regno << 8) | regno;
-		info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
-		break;
+            case 32:
+                i = (regno << 8) | regno;
+                info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
+                break;
 #endif
-	    }
+            }
     return 0;
 }
 
@@ -2837,12 +3304,12 @@
 static void do_install_cmap(int con, struct fb_info *info)
 {
     if (con != currcon)
-	return;
+        return;
     if (fb_display[con].cmap.len)
-	fb_set_cmap(&fb_display[con].cmap, 1, atyfb_setcolreg, info);
+        fb_set_cmap(&fb_display[con].cmap, 1, atyfb_setcolreg, info);
     else {
-	int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
-	fb_set_cmap(fb_default_cmap(size), 1, atyfb_setcolreg, info);
+        int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+        fb_set_cmap(fb_default_cmap(size), 1, atyfb_setcolreg, info);
     }
 }
 
@@ -2866,27 +3333,27 @@
     height = yres - conp->vc_rows * fontheight(p);
 
     if (height && (yoffset + yres > sy)) {
-	u32 xres, xoffset;
-	u32 bgx;
+        u32 xres, xoffset;
+        u32 bgx;
 
-	xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
-	xoffset = fb_display[con].var.xoffset;
+        xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
+        xoffset = fb_display[con].var.xoffset;
 
 
-	bgx = attr_bgcol_ec(p, conp);
-	bgx |= (bgx << 8);
-	bgx |= (bgx << 16);
-
-	if (sy + height > par->crtc.vyres) {
-	    wait_for_fifo(1, info);
-	    aty_st_le32(SC_BOTTOM, sy + height - 1, info);
-	}
-	aty_rectfill(xoffset, sy, xres, height, bgx, info);
+        bgx = attr_bgcol_ec(p, conp);
+        bgx |= (bgx << 8);
+        bgx |= (bgx << 16);
+
+        if (sy + height > par->crtc.vyres) {
+            wait_for_fifo(1, info);
+            aty_st_le32(SC_BOTTOM, sy + height - 1, info);
+        }
+        aty_rectfill(xoffset, sy, xres, height, bgx, info);
     }
 
 #ifdef CONFIG_FB_ATY_CT
     if (info->cursor && (yoffset + yres <= sy))
-	atyfb_cursor(p, CM_ERASE, info->cursor->pos.x, info->cursor->pos.y);
+        atyfb_cursor(p, CM_ERASE, info->cursor->pos.x, info->cursor->pos.y);
 #endif /* CONFIG_FB_ATY_CT */
 
     info->current_par.crtc.yoffset = yoffset;
@@ -2906,34 +3373,50 @@
 void cleanup_module(void)
 {
     while (fb_list) {
-	struct fb_info_aty *info = fb_list;
-	fb_list = info->next;
+        struct fb_info_aty *info = fb_list;
+        fb_list = info->next;
 
-	unregister_framebuffer(&info->fb_info);
+        unregister_framebuffer(&info->fb_info);
 
 #ifndef __sparc__
-	if (info->ati_regbase)
-	    iounmap((void *)info->ati_regbase);
-	if (info->frame_buffer)
-	    iounmap((void *)info->frame_buffer);
+        if (info->ati_regbase)
+            iounmap((void *)info->ati_regbase);
+        if (info->frame_buffer)
+            iounmap((void *)info->frame_buffer);
 #ifdef __BIG_ENDIAN
-	if (info->cursor && info->cursor->ram)
-	    iounmap(info->cursor->ram);
+        if (info->cursor && info->cursor->ram)
+            iounmap(info->cursor->ram);
 #endif
 #endif
 
-	if (info->cursor) {
-	    if (info->cursor->timer)
-		kfree(info->cursor->timer);
-	    kfree(info->cursor);
-	}
+        if (info->cursor) {
+            if (info->cursor->timer)
+                kfree(info->cursor->timer);
+            kfree(info->cursor);
+        }
 #ifdef __sparc__
-	if (info->mmap_map)
-	    kfree(info->mmap_map);
+        if (info->mmap_map)
+            kfree(info->mmap_map);
 #endif
-	kfree(info);
+        kfree(info);
     }
 }
 
 #endif
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Geert Uytterhoeven, Bernd Harries, Eddie C. Dost, Daniel Mantione");
+MODULE_DESCRIPTION("Accelerated FBDev driver for ATI Mach64 and derivates");
+
+MODULE_PARM(curblink, "i");
+MODULE_PARM_DESC(noblink, "Enable(1) or disable(0) cursor blinking");
+MODULE_PARM(noaccel, "i");
+MODULE_PARM_DESC(noaccel, "Disable(1) or enable(0) 2d acceleration");
+MODULE_PARM(default_vram, "i");
+MODULE_PARM_DESC(default_vram, "Specify the amount of available video memory");
+MODULE_PARM(default_pll, "i");
+MODULE_PARM_DESC(default_pll, "Specify the maximum PLL rate");
+MODULE_PARM(default_mclk, "i");
+MODULE_PARM_DESC(default_mclk, "Program the chip clock frequency (in MHz)");
+MODULE_PARM(default_xclk, "i");
+MODULE_PARM_DESC(default_xclk, "Program the memory clock frequency (in MHz)");
+
diff -urN linux-2.4.23-pre3/drivers/video/aty/mach64.h linux-2.4.23-pre4/drivers/video/aty/mach64.h
--- linux-2.4.23-pre3/drivers/video/aty/mach64.h	2001-07-31 14:43:29.000000000 -0700
+++ linux-2.4.23-pre4/drivers/video/aty/mach64.h	2003-09-12 12:44:40.000000000 -0700
@@ -726,6 +726,10 @@
 #define VCLK2_POST		0x30
 #define VCLK3_POST		0xC0
 
+#define EXT_VPLL_EN		0x04
+#define EXT_VPLL_VGA_EN		0x08
+#define EXT_VPLL_INSYNC		0x10
+
 /* CONFIG_CNTL register constants */
 #define APERTURE_4M_ENABLE	1
 #define APERTURE_8M_ENABLE	2
@@ -946,6 +950,7 @@
 #define SRC_15BPP		0x300
 #define SRC_16BPP		0x400
 #define SRC_32BPP		0x600
+#define HOST_TRIPLE_EN          0x2000
 #define HOST_1BPP		0
 #define HOST_4BPP		0x10000
 #define HOST_8BPP		0x20000
@@ -1148,6 +1153,69 @@
 #define APC_LUT_MN		0x39
 #define APC_LUT_OP		0x3A
 
+/* Values in CONFIG_PANEL */
+
+#define DONT_SHADOW_HEND                0x00004000ul
+
+/* Values in LCD_GEN_CTRL */
+#define CRT_ON                          0x00000001ul
+#define LCD_ON                          0x00000002ul
+#define HORZ_DIVBY2_EN                  0x00000004ul
+#define DONT_DS_ICON                    0x00000008ul
+#define LOCK_8DOT                       0x00000010ul
+#define ICON_ENABLE                     0x00000020ul
+#define DONT_SHADOW_VPAR                0x00000040ul
+#define V2CLK_PM_EN                     0x00000080ul
+#define RST_FM                          0x00000100ul
+#define DISABLE_PCLK_RESET              0x00000200ul    /* XC/XL */
+#define DIS_HOR_CRT_DIVBY2              0x00000400ul
+#define SCLK_SEL                        0x00000800ul
+#define SCLK_DELAY                      0x0000f000ul
+#define TVCLK_PM_EN                     0x00010000ul
+#define VCLK_DAC_PM_EN                  0x00020000ul
+#define VCLK_LCD_OFF                    0x00040000ul
+#define SELECT_WAIT_4MS                 0x00080000ul
+#define XTALIN_PM_EN                    0x00080000ul    /* XC/XL */
+#define V2CLK_DAC_PM_EN                 0x00100000ul
+#define LVDS_EN                         0x00200000ul
+#define LVDS_PLL_EN                     0x00400000ul
+#define LVDS_PLL_RESET                  0x00800000ul
+#define LVDS_RESERVED_BITS              0x07000000ul
+#define CRTC_RW_SELECT                  0x08000000ul    /* LTPro */
+#define USE_SHADOWED_VEND               0x10000000ul
+#define USE_SHADOWED_ROWCUR             0x20000000ul
+#define SHADOW_EN                       0x40000000ul
+#define SHADOW_RW_EN                    0x80000000ul
+
+/* Values in HORZ_STRETCHING */
+#define HORZ_STRETCH_BLEND              0x00000ffful
+#define HORZ_STRETCH_RATIO              0x0000fffful
+#define HORZ_STRETCH_LOOP               0x00070000ul
+#define HORZ_STRETCH_LOOP09                     0x00000000ul
+#define HORZ_STRETCH_LOOP11                     0x00010000ul
+#define HORZ_STRETCH_LOOP12                     0x00020000ul
+#define HORZ_STRETCH_LOOP14                     0x00030000ul
+#define HORZ_STRETCH_LOOP15                     0x00040000ul
+/*      ?                                       0x00050000ul */
+/*      ?                                       0x00060000ul */
+/*      ?                                       0x00070000ul */
+/*      ?                               0x00080000ul */
+#define HORZ_PANEL_SIZE                 0x0ff00000ul    /* XC/XL */
+/*      ?                               0x10000000ul */
+#define AUTO_HORZ_RATIO                 0x20000000ul    /* XC/XL */
+#define HORZ_STRETCH_MODE               0x40000000ul
+#define HORZ_STRETCH_EN                 0x80000000ul
+
+/* Values in VERT_STRETCHING */
+#define VERT_STRETCH_RATIO0             0x000003fful
+#define VERT_STRETCH_RATIO1             0x000ffc00ul
+#define VERT_STRETCH_RATIO2             0x3ff00000ul
+#define VERT_STRETCH_USE0               0x40000000ul
+#define VERT_STRETCH_EN                 0x80000000ul
+
+/* Values in EXT_VERT_STRETCH */
+#define AUTO_VERT_RATIO                 0x00400000ul
+#define VERT_STRETCH_MODE		0x00000400ul
 
 /* Values in LCD_MISC_CNTL */
 #define BIAS_MOD_LEVEL_MASK	0x0000ff00
diff -urN linux-2.4.23-pre3/drivers/video/aty/mach64_ct.c linux-2.4.23-pre4/drivers/video/aty/mach64_ct.c
--- linux-2.4.23-pre3/drivers/video/aty/mach64_ct.c	2001-07-31 14:43:29.000000000 -0700
+++ linux-2.4.23-pre4/drivers/video/aty/mach64_ct.c	2003-09-12 12:44:40.000000000 -0700
@@ -16,28 +16,99 @@
 /* FIXME: remove the FAIL definition */
 #define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
 
-static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info);
+static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info) stdcall;
 
 static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
 			    struct pll_ct *pll);
-static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
+static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp, u32 stretch,
 		      struct pll_ct *pll);
 static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
-			     u8 bpp, union aty_pll *pll);
+			     u8 bpp, u32 stretch, union aty_pll *pll);
 static u32 aty_pll_ct_to_var(const struct fb_info_aty *info,
 			     const union aty_pll *pll);
 
+/*
+ * ATI Mach64 CT clock synthesis description.
+ *
+ * All clocks on the Mach64 can be calculated using the same principle:
+ *
+ *       XTALIN * x * FB_DIV
+ * CLK = ----------------------
+ *       PLL_REF_DIV * POST_DIV
+ * 
+ * XTALIN is a fixed speed clock. Common speeds are 14.31 MHz and 29.50 MHz.
+ * PLL_REF_DIV can be set by the user, but is the same for all clocks.
+ * FB_DIV can be set by the user for each clock individually, it should be set
+ * between 128 and 255, the chip will generate a bad clock signal for too low
+ * values.
+ * x depends on the type of clock; usually it is 2, but for the MCLK it can also
+ * be set to 4.
+ * POST_DIV can be set by the user for each clock individually, Possible values
+ * are 1,2,4,8 and for some clocks other values are available too.
+ * CLK is of course the clock speed that is generated.
+ *
+ * The Mach64 has these clocks:
+ *
+ * MCLK			The clock rate of the chip
+ * XCLK			The clock rate of the on-chip memory
+ * VCLK0		First pixel clock of first CRT controller
+ * VCLK1    Second pixel clock of first CRT controller
+ * VCLK2		Third pixel clock of first CRT controller
+ * VCLK3    Fourth pixel clock of first CRT controller
+ * VCLK			Selected pixel clock, one of VCLK0, VCLK1, VCLK2, VCLK3
+ * V2CLK		Pixel clock of the second CRT controller.
+ * SCLK			Multi-purpose clock
+ *
+ * - MCLK and XCLK use the same FB_DIV
+ * - VCLK0 .. VCLK3 use the same FB_DIV
+ * - V2CLK is needed when the second CRTC is used (can be used for dualhead);
+ *   i.e. CRT monitor connected to laptop has different resolution than built
+ *   in LCD monitor.
+ * - SCLK is not available on all cards; it is known to exist on the Rage LT-PRO,
+ *   Rage XL and Rage Mobility. It is known not to exist on the Mach64 VT.
+ * - V2CLK is not available on all cards, most likely only the Rage LT-PRO,
+ *   the Rage XL and the Rage Mobility
+ *
+ * SCLK can be used to:
+ * - Clock the chip instead of MCLK
+ * - Replace XTALIN with a user defined frequency
+ * - Generate the pixel clock for the LCD monitor (instead of VCLK)
+ */
+
+ /*
+  * It can be quite hard to calculate XCLK and MCLK if they don't run at the
+  * same frequency. Luckily, until now all cards that need asynchrone clock
+  * speeds seem to have SCLK.
+  * So this driver uses SCLK to clock the chip and XCLK to clock the memory.
+  */
 
+static u8 postdividers[] = {1,2,4,8,3};
 
-static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info)
+u8 stdcall aty_ld_pll(int offset, const struct fb_info_aty *info)
 {
+    u32 addr;
+
+    addr = info->ati_regbase + CLOCK_CNTL + 1;
     /* write addr byte */
-    aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, info);
-    /* write the register value */
-    aty_st_8(CLOCK_CNTL + 2, val, info);
-    aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
+    writeb((offset << 2) | PLL_WR_EN,addr);
+    addr++;
+    /* read the register value */
+    return readb(addr);
 }
 
+static void stdcall aty_st_pll(int offset, u8 val, const struct fb_info_aty *info)
+{
+    u32 addr;
+    addr = info->ati_regbase + CLOCK_CNTL + 1;
+    /* write addr byte */
+    writeb((offset << 2) | PLL_WR_EN,addr);
+    addr++;
+    /* write the register value */
+    writeb(val,addr);
+    addr--;
+    /* Disable write access */
+    writeb(offset << 2,addr);
+}
 
 /* ------------------------------------------------------------------------- */
 
@@ -45,179 +116,135 @@
      *  PLL programming (Mach64 CT family)
      */
 
+/*
+ * This procedure sets the display fifo. The display fifo is a buffer that
+ * contains data read from the video memory that waits to be processed by
+ * the CRT controller.
+ *
+ * On the more modern Mach64 variants, the chip doesn't calculate the
+ * interval after which the display fifo has to be reloaded from memory
+ * automatically, the driver has to do it instead.
+ */
+
+
+#define Maximum_DSP_PRECISION 7
+
 static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
-		      struct pll_ct *pll)
-{
-    u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off, dsp_on;
-    u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size;
+		      u32 width, struct pll_ct *pll) {
 
-    /* xclocks_per_row<<11 */
-    xclks_per_row = (pll->mclk_fb_div*pll->vclk_post_div_real*64<<11)/
-		    (pll->vclk_fb_div*pll->mclk_post_div_real*bpp);
-    if (xclks_per_row < (1<<11))
-	FAIL("Dotclock to high");
-    if (M64_HAS(FIFO_24)) {
-	fifo_size = 24;
-	dsp_loop_latency = 0;
-    } else {
-	fifo_size = 32;
-	dsp_loop_latency = 2;
-    }
-    dsp_precision = 0;
-    y = (xclks_per_row*fifo_size)>>11;
-    while (y) {
-	y >>= 1;
-	dsp_precision++;
-    }
-    dsp_precision -= 5;
-    /* fifo_off<<6 */
-    fifo_off = ((xclks_per_row*(fifo_size-1))>>5)+(3<<6);
-
-    if (info->total_vram > 1*1024*1024) {
-	if (info->ram_type >= SDRAM) {
-	    /* >1 MB SDRAM */
-	    dsp_loop_latency += 8;
-	    page_size = 8;
-	} else {
-	    /* >1 MB DRAM */
-	    dsp_loop_latency += 6;
-	    page_size = 9;
-	}
-    } else {
-	if (info->ram_type >= SDRAM) {
-	    /* <2 MB SDRAM */
-	    dsp_loop_latency += 9;
-	    page_size = 10;
-	} else {
-	    /* <2 MB DRAM */
-	    dsp_loop_latency += 8;
-	    page_size = 10;
-	}
+    u32 multiplier,divider,ras_multiplier,ras_divider,tmp;
+    u32 dsp_on,dsp_off,dsp_xclks;
+    u8 vshift,xshift;
+    s8 dsp_precision;
+
+    multiplier = ((u32)info->mclk_fb_div)*pll->vclk_post_div_real;
+    divider = ((u32)pll->vclk_fb_div)*info->xclk_post_div_real;
+
+    ras_multiplier = info->xclkmaxrasdelay;
+    ras_divider = 1;
+
+    if (bpp>=8)
+        divider = divider * (bpp >> 2);
+	
+    vshift = (6 - 2);	/* FIFO is 64 bits wide in accelerator mode ... */
+
+    if (bpp == 0)
+        vshift--;	/* ... but only 32 bits in VGA mode. */
+
+#ifdef CONFIG_FB_ATY_GENERIC_LCD
+    if (width != 0) {
+        multiplier = multiplier * info->lcd_width;
+        divider = divider * width;
+
+        ras_multiplier = ras_multiplier * info->lcd_width;
+        ras_divider = ras_divider * width;
+    };
+#endif
+
+    /* If we don't do this, 32 bits for multiplier & divider won't be
+       enough in certain situations! */
+    while (((multiplier | divider) & 1) == 0) {
+	multiplier = multiplier >> 1;
+	divider = divider >> 1;
+    };
+
+    /* Determine DSP precision first */
+    tmp = ((multiplier * info->fifo_size) << vshift) / divider;
+    for (dsp_precision = -5;  tmp;  dsp_precision++)
+        tmp >>= 1;
+    if (dsp_precision < 0)
+        dsp_precision = 0;
+    else if (dsp_precision > Maximum_DSP_PRECISION)
+        dsp_precision = Maximum_DSP_PRECISION;
+
+    xshift = 6 - dsp_precision;
+    vshift += xshift;
+
+    /* Move on to dsp_off */
+    dsp_off = ((multiplier * (info->fifo_size - 1)) << vshift) / divider -
+	      (1 << (vshift - xshift));
+
+    /* Next is dsp_on */
+//    if (bpp == 0)
+//        dsp_on = ((multiplier * 20 << vshift) + divider) / divider;
+//    else {
+        dsp_on = ((multiplier << vshift) + divider) / divider;
+        tmp = ((ras_multiplier << xshift) + ras_divider) / ras_divider;
+        if (dsp_on < tmp)
+            dsp_on = tmp;
+        dsp_on = dsp_on + (tmp * 2) + (info->xclkpagefaultdelay << xshift);
+//    };
+
+    /* Calculate rounding factor and apply it to dsp_on */
+    tmp = ((1 << (Maximum_DSP_PRECISION - dsp_precision)) - 1) >> 1;
+    dsp_on = ((dsp_on + tmp) / (tmp + 1)) * (tmp + 1);
+
+    if (dsp_on >= ((dsp_off / (tmp + 1)) * (tmp + 1)))
+    {
+        dsp_on = dsp_off - (multiplier << vshift) / divider;
+        dsp_on = (dsp_on / (tmp + 1)) * (tmp + 1);
     }
-    /* fifo_on<<6 */
-    if (xclks_per_row >= (page_size<<11))
-	fifo_on = ((2*page_size+1)<<6)+(xclks_per_row>>5);
-    else
-	fifo_on = (3*page_size+2)<<6;
 
-    dsp_xclks_per_row = xclks_per_row>>dsp_precision;
-    dsp_on = fifo_on>>dsp_precision;
-    dsp_off = fifo_off>>dsp_precision;
-
-    pll->dsp_config = (dsp_xclks_per_row & 0x3fff) |
-		      ((dsp_loop_latency & 0xf)<<16) |
-		      ((dsp_precision & 7)<<20);
-    pll->dsp_on_off = (dsp_on & 0x7ff) | ((dsp_off & 0x7ff)<<16);
+    /* Last but not least:  dsp_xclks */
+    dsp_xclks = ((multiplier << (vshift + 5)) + divider) / divider;
+
+    /* Get register values. */
+    pll->dsp_on_off = (dsp_on << 16) + dsp_off;
+    pll->dsp_config = (dsp_precision << 20) | (info->dsp_loop_latency << 16) |
+                      dsp_xclks;
     return 0;
-}
+};
 
 static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
 			    struct pll_ct *pll)
 {
-    u32 q, x;			/* x is a workaround for sparc64-linux-gcc */
-    x = x;			/* x is a workaround for sparc64-linux-gcc */
-
-    pll->pll_ref_div = info->pll_per*2*255/info->ref_clk_per;
-
-    /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
-    q = info->ref_clk_per*pll->pll_ref_div*4/info->mclk_per;	/* actually 8*q */
-    if (q < 16*8 || q > 255*8)
-	FAIL("mclk out of range");
-    else if (q < 32*8)
-	pll->mclk_post_div_real = 8;
-    else if (q < 64*8)
-	pll->mclk_post_div_real = 4;
-    else if (q < 128*8)
-	pll->mclk_post_div_real = 2;
-    else
-	pll->mclk_post_div_real = 1;
-    pll->mclk_fb_div = q*pll->mclk_post_div_real/8;
+    u32 q;
 
     /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
-    q = info->ref_clk_per*pll->pll_ref_div*4/vclk_per;	/* actually 8*q */
+    q = info->ref_clk_per*info->pll_ref_div*4/vclk_per;	/* actually 8*q */
     if (q < 16*8 || q > 255*8)
-	FAIL("vclk out of range");
-    else if (q < 32*8)
-	pll->vclk_post_div_real = 8;
-    else if (q < 64*8)
-	pll->vclk_post_div_real = 4;
-    else if (q < 128*8)
-	pll->vclk_post_div_real = 2;
-    else
-	pll->vclk_post_div_real = 1;
+        FAIL("vclk out of range");
+    else {
+        pll->vclk_post_div  = (q < 128*8);
+        pll->vclk_post_div += (q <  64*8);
+        pll->vclk_post_div += (q <  32*8);
+    };
+    pll->vclk_post_div_real = postdividers[pll->vclk_post_div];
+//    pll->vclk_post_div <<= 6;
     pll->vclk_fb_div = q*pll->vclk_post_div_real/8;
-    return 0;
-}
-
-void aty_calc_pll_ct(const struct fb_info_aty *info, struct pll_ct *pll)
-{
-    u8 mpostdiv = 0;
-    u8 vpostdiv = 0;
-
-    if (M64_HAS(SDRAM_MAGIC_PLL) && (info->ram_type >= SDRAM))
-	pll->pll_gen_cntl = 0x04;
-    else
-	pll->pll_gen_cntl = 0x84;
-
-    switch (pll->mclk_post_div_real) {
-	case 1:
-	    mpostdiv = 0;
-	    break;
-	case 2:
-	    mpostdiv = 1;
-	    break;
-	case 3:
-	    mpostdiv = 4;
-	    break;
-	case 4:
-	    mpostdiv = 2;
-	    break;
-	case 8:
-	    mpostdiv = 3;
-	    break;
-    }
-    pll->pll_gen_cntl |= mpostdiv<<4;	/* mclk */
-
-    if (M64_HAS(MAGIC_POSTDIV))
-	pll->pll_ext_cntl = 0;
-    else
-    	pll->pll_ext_cntl = mpostdiv;	/* xclk == mclk */
-
-    switch (pll->vclk_post_div_real) {
-	case 2:
-	    vpostdiv = 1;
-	    break;
-	case 3:
-	    pll->pll_ext_cntl |= 0x10;
-	case 1:
-	    vpostdiv = 0;
-	    break;
-	case 6:
-	    pll->pll_ext_cntl |= 0x10;
-	case 4:
-	    vpostdiv = 2;
-	    break;
-	case 12:
-	    pll->pll_ext_cntl |= 0x10;
-	case 8:
-	    vpostdiv = 3;
-	    break;
-    }
-
     pll->pll_vclk_cntl = 0x03;	/* VCLK = PLL_VCLK/VCLKx_POST */
-    pll->vclk_post_div = vpostdiv;
+    return 0;
 }
 
 static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
-			     u8 bpp, union aty_pll *pll)
+			     u8 bpp, u32 width, union aty_pll *pll)
 {
     int err;
 
     if ((err = aty_valid_pll_ct(info, vclk_per, &pll->ct)))
-	return err;
-    if (M64_HAS(GTB_DSP) && (err = aty_dsp_gt(info, bpp, &pll->ct)))
-	return err;
-    aty_calc_pll_ct(info, &pll->ct);
+        return err;
+    if (M64_HAS(GTB_DSP) && (err = aty_dsp_gt(info, bpp, width, &pll->ct)))
+        return err;
     return 0;
 }
 
@@ -225,7 +252,7 @@
 			     const union aty_pll *pll)
 {
     u32 ref_clk_per = info->ref_clk_per;
-    u8 pll_ref_div = pll->ct.pll_ref_div;
+    u8 pll_ref_div = info->pll_ref_div;
     u8 vclk_fb_div = pll->ct.vclk_fb_div;
     u8 vclk_post_div = pll->ct.vclk_post_div_real;
 
@@ -234,27 +261,187 @@
 
 void aty_set_pll_ct(const struct fb_info_aty *info, const union aty_pll *pll)
 {
-    aty_st_pll(PLL_REF_DIV, pll->ct.pll_ref_div, info);
-    aty_st_pll(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, info);
-    aty_st_pll(MCLK_FB_DIV, pll->ct.mclk_fb_div, info);
+    u8 a;
     aty_st_pll(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, info);
-    aty_st_pll(VCLK_POST_DIV, pll->ct.vclk_post_div, info);
+    a = aty_ld_pll(VCLK_POST_DIV, info) & ~3;
+    aty_st_pll(VCLK_POST_DIV, a | pll->ct.vclk_post_div, info);
     aty_st_pll(VCLK0_FB_DIV, pll->ct.vclk_fb_div, info);
-    aty_st_pll(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, info);
 
     if (M64_HAS(GTB_DSP)) {
-	if (M64_HAS(XL_DLL))
-	    aty_st_pll(DLL_CNTL, 0x80, info);
-	else if (info->ram_type >= SDRAM)
-	    aty_st_pll(DLL_CNTL, 0xa6, info);
-	else
-	    aty_st_pll(DLL_CNTL, 0xa0, info);
-	aty_st_pll(VFC_CNTL, 0x1b, info);
-	aty_st_le32(DSP_CONFIG, pll->ct.dsp_config, info);
-	aty_st_le32(DSP_ON_OFF, pll->ct.dsp_on_off, info);
+        aty_st_le32(DSP_CONFIG, pll->ct.dsp_config, info);
+        aty_st_le32(DSP_ON_OFF, pll->ct.dsp_on_off, info);
     }
 }
 
+
+static void __init aty_init_pll_ct(struct fb_info_aty *info) {
+    u8 pll_ref_div,pll_gen_cntl,pll_ext_cntl;
+    u8 mpost_div,xpost_div;
+    u8 sclk_post_div_real,sclk_fb_div,spll_cntl2;
+    u32 q,i;
+    u32 mc,trp,trcd,tcrd,tras;
+
+    mc = aty_ld_le32(MEM_CNTL, info);
+    trp = (mc & 0x300) >> 8;
+    trcd = (mc & 0xc00) >> 10;
+    tcrd = (mc & 0x1000) >> 12;    tras = (mc & 0x70000) >> 16;
+    info->xclkpagefaultdelay = trcd + tcrd + trp + 2;
+    info->xclkmaxrasdelay = tras + trp + 2;
+
+    if (M64_HAS(FIFO_24)) {
+        info->fifo_size = 24;
+        info->xclkpagefaultdelay += 2;
+        info->xclkmaxrasdelay += 3;
+    } else {
+        info->fifo_size = 32;
+    };
+
+    switch (info->ram_type) {
+        case DRAM:
+            if (info->total_vram<=1*1024*1024) {
+                info->dsp_loop_latency = 10;
+            } else {
+                info->dsp_loop_latency = 8;
+                info->xclkpagefaultdelay += 2;
+            };
+            break;
+        case EDO:
+        case PSEUDO_EDO:
+            if (info->total_vram<=1*1024*1024) {
+                info->dsp_loop_latency = 9;
+            } else {
+                info->dsp_loop_latency = 8;
+                info->xclkpagefaultdelay += 1;
+            };
+            break;
+        case SDRAM:
+            if (info->total_vram<=1*1024*1024) {
+                info->dsp_loop_latency = 11;
+            } else {
+                info->dsp_loop_latency = 10;
+                info->xclkpagefaultdelay += 1;
+            };
+            break;
+        case SGRAM:
+            info->dsp_loop_latency = 8;
+            info->xclkpagefaultdelay += 3;
+            break;
+        default:
+            info->dsp_loop_latency = 11;
+            info->xclkpagefaultdelay += 3;
+            break;
+    };
+
+    if (info->xclkmaxrasdelay <= info->xclkpagefaultdelay)
+        info->xclkmaxrasdelay = info->xclkpagefaultdelay + 1;
+
+    /* Exit if the user does not want us to tamper with the clock
+       rates of her chip. */
+    if (info->mclk_per == 0) {
+        u16 mclk_fb_div;
+        u8 pll_ext_cntl;
+
+        info->pll_ref_div = aty_ld_pll(PLL_REF_DIV, info);
+        pll_ext_cntl = aty_ld_pll(PLL_EXT_CNTL, info);
+        info->xclk_post_div_real = postdividers[pll_ext_cntl & 7];
+        mclk_fb_div = aty_ld_pll(MCLK_FB_DIV, info);
+        if (pll_ext_cntl & 8)
+            mclk_fb_div <<= 1;
+        info->mclk_fb_div = mclk_fb_div;
+        return;
+    };
+
+    pll_ref_div = info->pll_per*2*255/info->ref_clk_per;
+    info->pll_ref_div = pll_ref_div;
+
+    /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
+    q = info->ref_clk_per*pll_ref_div*4/info->xclk_per;	/* actually 8*q */
+    if (q < 16*8 || q > 255*8) {
+        printk(KERN_CRIT "xclk out of range\n");
+        return;
+    } else {
+        xpost_div  = (q < 128*8);
+        xpost_div += (q <  64*8);
+        xpost_div += (q <  32*8);
+    };
+    info->xclk_post_div_real = postdividers[xpost_div];
+    info->mclk_fb_div = q*info->xclk_post_div_real/8;
+
+    if (M64_HAS(SDRAM_MAGIC_PLL) && (info->ram_type >= SDRAM))
+        pll_gen_cntl = 0x04;
+    else
+	/* The Rage Mobility M1 needs bit 3 set...*/
+	/* original: pll_gen_cntl = 0x84 */
+        pll_gen_cntl = 0x8C;
+
+    if (M64_HAS(MAGIC_POSTDIV))
+        pll_ext_cntl = 0;
+    else
+       	pll_ext_cntl = xpost_div;
+
+    if (info->mclk_per == info->xclk_per)
+        pll_gen_cntl |= xpost_div<<4; /* mclk == xclk */
+    else {
+	/* 
+	 * The chip clock is not equal to the memory clock.
+	 * Therefore we will use sclk to clock the chip.
+	 */
+        pll_gen_cntl |= 6<<4;	/* mclk == sclk*/
+
+        q = info->ref_clk_per*pll_ref_div*4/info->mclk_per;	/* actually 8*q */
+        if (q < 16*8 || q > 255*8) {
+	    printk(KERN_CRIT "mclk out of range\n");
+            return;
+        } else {
+            mpost_div  = (q < 128*8);
+            mpost_div += (q <  64*8);
+            mpost_div += (q <  32*8);
+        };
+        sclk_post_div_real = postdividers[mpost_div];
+        sclk_fb_div = q*sclk_post_div_real/8;
+        spll_cntl2 = mpost_div << 4;
+	/*
+         * This disables the sclk, crashes the computer as reported:
+         * aty_st_pll(SPLL_CNTL2, 3, info);
+	 *
+         * So it seems the sclk must be enabled before it is used;
+         * so PLL_GEN_CNTL must be programmed *after* the sclk.
+	 */
+        aty_st_pll(SCLK_FB_DIV, sclk_fb_div, info);
+        aty_st_pll(SPLL_CNTL2, spll_cntl2, info);
+	/* 
+	 * The sclk has been started. However, I believe the first clock 
+	 * ticks it generates are not very stable. Hope this primitive loop
+	 * helps for Rage Mobilities that sometimes crash when
+	 * we switch to sclk. (Daniel Mantione, 13-05-2003)
+	 */
+        for (i=0;i<=0x1ffff;i++);
+    };
+
+    aty_st_pll(PLL_REF_DIV, pll_ref_div, info);
+    aty_st_pll(PLL_GEN_CNTL, pll_gen_cntl, info);
+    aty_st_pll(MCLK_FB_DIV, info->mclk_fb_div, info);
+    aty_st_pll(PLL_EXT_CNTL, pll_ext_cntl, info);
+    /* Disable the extra precision pixel clock controls since we do not
+       use them. */
+    aty_st_pll(EXT_VPLL_CNTL, aty_ld_pll(EXT_VPLL_CNTL, info) &
+	                      ~(EXT_VPLL_EN | EXT_VPLL_VGA_EN |
+			        EXT_VPLL_INSYNC), info);
+#if 0
+    /* This code causes problems on the Rage Mobility M1
+       and seems unnecessary. Comments wanted! */
+    if (M64_HAS(GTB_DSP)) {
+        if (M64_HAS(XL_DLL))
+            aty_st_pll(DLL_CNTL, 0x80, info);
+        else if (info->ram_type >= SDRAM)
+            aty_st_pll(DLL_CNTL, 0xa6, info);
+        else
+            aty_st_pll(DLL_CNTL, 0xa0, info);
+        aty_st_pll(VFC_CNTL, 0x1b, info);
+    };
+#endif
+};
+
 static int dummy(void)
 {
     return 0;
@@ -268,5 +455,6 @@
     var_to_pll:	aty_var_to_pll_ct,
     pll_to_var:	aty_pll_ct_to_var,
     set_pll:	aty_set_pll_ct,
+    init_pll:	aty_init_pll_ct
 };
 
diff -urN linux-2.4.23-pre3/drivers/video/aty/mach64_cursor.c linux-2.4.23-pre4/drivers/video/aty/mach64_cursor.c
--- linux-2.4.23-pre3/drivers/video/aty/mach64_cursor.c	2001-10-25 13:53:52.000000000 -0700
+++ linux-2.4.23-pre4/drivers/video/aty/mach64_cursor.c	2003-09-12 12:44:40.000000000 -0700
@@ -144,6 +144,10 @@
 			yoff = 0;
 		}
 
+                /* In doublescan mode, the cursor location also needs to be
+		   doubled. */
+                if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN)
+		   y<<=1;
 		wait_for_fifo(4, fb);
 		aty_st_le32(CUR_OFFSET, (c->offset >> 3) + (yoff << 1), fb);
 		aty_st_le32(CUR_HORZ_VERT_OFF,
diff -urN linux-2.4.23-pre3/drivers/video/aty/mach64_gx.c linux-2.4.23-pre4/drivers/video/aty/mach64_gx.c
--- linux-2.4.23-pre3/drivers/video/aty/mach64_gx.c	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.23-pre4/drivers/video/aty/mach64_gx.c	2003-09-12 12:44:40.000000000 -0700
@@ -5,7 +5,6 @@
 
 #include <linux/delay.h>
 #include <linux/fb.h>
-#include <linux/sched.h>
 
 #include <asm/io.h>
 
@@ -37,6 +36,11 @@
 #define MIN_N		35
 #define MAX_N		255-8
 
+static int dummy(void)
+{
+    return 0;
+}
+
 
     /*
      *  Support Functions
@@ -183,6 +187,7 @@
     var_to_pll:	aty_var_to_pll_514,
     pll_to_var:	aty_pll_514_to_var,
     set_pll:	aty_set_pll_514,
+    init_pll:	(void *)dummy
 };
 
 
@@ -467,6 +472,7 @@
     var_to_pll:	aty_var_to_pll_18818,
     pll_to_var:	aty_pll_18818_to_var,
     set_pll:	aty_set_pll18818,
+    init_pll:	(void *)dummy
 };
 
 
@@ -580,6 +586,7 @@
     var_to_pll:	aty_var_to_pll_1703,
     pll_to_var:	aty_pll_1703_to_var,
     set_pll:	aty_set_pll_1703,
+    init_pll:	(void *)dummy
 };
 
 
@@ -707,6 +714,7 @@
     var_to_pll:	aty_var_to_pll_8398,
     pll_to_var:	aty_pll_8398_to_var,
     set_pll:	aty_set_pll_8398,
+    init_pll:	(void *)dummy
 };
 
 
@@ -851,6 +859,7 @@
     var_to_pll:	aty_var_to_pll_408,
     pll_to_var:	aty_pll_408_to_var,
     set_pll:	aty_set_pll_408,
+    init_pll:	(void *)dummy
 };
 
 
@@ -870,11 +879,6 @@
     return 0;
 }
 
-static int dummy(void)
-{
-    return 0;
-}
-
 const struct aty_dac_ops aty_dac_unsupported = {
     set_dac:	aty_set_dac_unsupported,
 };
@@ -883,5 +887,6 @@
     var_to_pll:	(void *)dummy,
     pll_to_var:	(void *)dummy,
     set_pll:	(void *)dummy,
+    init_pll:	(void *)dummy
 };
 
diff -urN linux-2.4.23-pre3/fs/buffer.c linux-2.4.23-pre4/fs/buffer.c
--- linux-2.4.23-pre3/fs/buffer.c	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/fs/buffer.c	2003-09-12 12:44:40.000000000 -0700
@@ -2752,10 +2752,10 @@
 #endif
 
 	printk("Buffer memory:   %6dkB\n",
-			atomic_read(&buffermem_pages) << (PAGE_SHIFT-10));
+		atomic_read(&buffermem_pages) << (PAGE_SHIFT-10));
 
-	printk("Cache memory:   %6dkB\n",
-			(atomic_read(&page_cache_size)- atomic_read(&buffermem_pages)) << (PAGE_SHIFT-10));
+	printk("Cache memory:   %6ldkB\n",
+		(page_cache_size - atomic_read(&buffermem_pages)) << (PAGE_SHIFT-10));
 
 #ifdef CONFIG_SMP /* trylock does nothing on UP and so we could deadlock */
 	if (!spin_trylock(&lru_list_lock))
diff -urN linux-2.4.23-pre3/fs/lockd/svclock.c linux-2.4.23-pre4/fs/lockd/svclock.c
--- linux-2.4.23-pre3/fs/lockd/svclock.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/fs/lockd/svclock.c	2003-09-12 12:44:40.000000000 -0700
@@ -188,6 +188,11 @@
 	locks_init_lock(&block->b_call.a_args.lock.fl);
 	locks_init_lock(&block->b_call.a_res.lock.fl);
 
+	block->b_host = nlmsvc_lookup_host(rqstp);
+	if (block->b_host == NULL) {
+		goto failed_free;
+	}
+
 	if (!nlmclnt_setgrantargs(&block->b_call, lock))
 		goto failed_free;
 
@@ -199,7 +204,6 @@
 
 	/* Create and initialize the block */
 	block->b_daemon = rqstp->rq_server;
-	block->b_host   = host;
 	block->b_file   = file;
 
 	/* Add to file's list of blocks */
@@ -265,8 +269,7 @@
 		}
 	}
 
-	if (block->b_host)
-		nlm_release_host(block->b_host);
+	nlm_release_host(block->b_host);
 	nlmclnt_freegrantargs(&block->b_call);
 	kfree(block);
 }
@@ -515,7 +518,7 @@
 	 * Just retry the grant callback, possibly refreshing the RPC
 	 * binding */
 	if (block->b_granted) {
-		nlm_rebind_host(block->b_host);
+		nlm_rebind_host(block->b_call.a_host);
 		goto callback;
 	}
 
diff -urN linux-2.4.23-pre3/fs/nfsd/export.c linux-2.4.23-pre4/fs/nfsd/export.c
--- linux-2.4.23-pre3/fs/nfsd/export.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/fs/nfsd/export.c	2003-09-12 12:44:40.000000000 -0700
@@ -640,7 +640,7 @@
 	{ NFSEXP_UIDMAP, {"uidmap", ""}},
 	{ NFSEXP_KERBEROS, { "kerberos", ""}},
 	{ NFSEXP_SUNSECURE, { "sunsecure", ""}},
-	{ NFSEXP_CROSSMNT, {"nohide", ""}},
+	{ NFSEXP_NOHIDE, {"nohide", ""}},
 	{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
 	{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
 #ifdef MSNFS
@@ -903,8 +903,10 @@
 {
 	struct svc_client	*clp;
 
+	exp_readlock();
 	for (clp = clients; clp; clp = clp->cl_next)
 		nfsd_lockd_unexport(clp);
+	exp_unlock();
 }
 
 /*
diff -urN linux-2.4.23-pre3/fs/nfsd/nfsfh.c linux-2.4.23-pre4/fs/nfsd/nfsfh.c
--- linux-2.4.23-pre3/fs/nfsd/nfsfh.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/fs/nfsd/nfsfh.c	2003-09-12 12:44:40.000000000 -0700
@@ -305,6 +305,7 @@
 			if (pdentry) {
 				igrab(tdentry->d_inode);
 				pdentry->d_flags |= DCACHE_NFSD_DISCONNECTED;
+				pdentry->d_op = child->d_op;
 			}
 		}
 		if (pdentry == NULL)
diff -urN linux-2.4.23-pre3/fs/nfsd/vfs.c linux-2.4.23-pre4/fs/nfsd/vfs.c
--- linux-2.4.23-pre3/fs/nfsd/vfs.c	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/fs/nfsd/vfs.c	2003-09-12 12:44:40.000000000 -0700
@@ -82,7 +82,7 @@
  * N.B. After this call _both_ fhp and resfh need an fh_put
  *
  * If the lookup would cross a mountpoint, and the mounted filesystem
- * is exported to the client with NFSEXP_CROSSMNT, then the lookup is
+ * is exported to the client with NFSEXP_NOHIDE, then the lookup is
  * accepted as it stands and the mounted directory is
  * returned. Otherwise the covered directory is returned.
  * NOTE: this mountpoint crossing is not supported properly by all
@@ -116,7 +116,7 @@
 			dentry = dget(dparent);
 		else if (dparent != exp->ex_dentry)
 			dentry = dget(dparent->d_parent);
-		else if (!EX_CROSSMNT(exp))
+		else if (!EX_NOHIDE(exp))
 			dentry = dget(dparent); /* .. == . just like at / */
 		else {
 			/* checking mountpoint crossing is very different when stepping up */
@@ -158,7 +158,7 @@
 			exp2 = exp_get(rqstp->rq_client,
 				       mounts->d_inode->i_dev,
 				       mounts->d_inode->i_ino);
-			if (exp2 && EX_CROSSMNT(exp2)) {
+			if (exp2 && EX_NOHIDE(exp2)) {
 				/* successfully crossed mount point */
 				exp = exp2;
 				dput(dentry);
diff -urN linux-2.4.23-pre3/fs/proc/proc_misc.c linux-2.4.23-pre4/fs/proc/proc_misc.c
--- linux-2.4.23-pre3/fs/proc/proc_misc.c	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/fs/proc/proc_misc.c	2003-09-12 12:44:40.000000000 -0700
@@ -166,7 +166,7 @@
 #define B(x) ((unsigned long long)(x) << PAGE_SHIFT)
 	si_meminfo(&i);
 	si_swapinfo(&i);
-	pg_size = atomic_read(&page_cache_size) - i.bufferram ;
+	pg_size = page_cache_size - i.bufferram;
 
 	len = sprintf(page, "        total:    used:    free:  shared: buffers:  cached:\n"
 		"Mem:  %8Lu %8Lu %8Lu %8Lu %8Lu %8Lu\n"
diff -urN linux-2.4.23-pre3/include/asm-ia64/a.out.h linux-2.4.23-pre4/include/asm-ia64/a.out.h
--- linux-2.4.23-pre3/include/asm-ia64/a.out.h	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/a.out.h	2003-09-12 12:44:40.000000000 -0700
@@ -30,9 +30,6 @@
 #define N_TXTOFF(x)	0
 
 #ifdef __KERNEL__
-# include <asm/page.h>
-# define STACK_TOP	(0x6000000000000000UL + (1UL << (4*PAGE_SHIFT - 12)) - PAGE_SIZE)
-# define IA64_RBS_BOT	(STACK_TOP - 0x80000000L + PAGE_SIZE)	/* bottom of reg. backing store */
+#include <asm/ustack.h>
 #endif
-
 #endif /* _ASM_IA64_A_OUT_H */
diff -urN linux-2.4.23-pre3/include/asm-ia64/acpi.h linux-2.4.23-pre4/include/asm-ia64/acpi.h
--- linux-2.4.23-pre3/include/asm-ia64/acpi.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/acpi.h	2003-09-12 12:44:40.000000000 -0700
@@ -97,17 +97,18 @@
 	} while (0)
 
 const char *acpi_get_sysname (void);
-int acpi_boot_init (char *cdline);
 int acpi_request_vector (u32 int_type);
 int acpi_get_prt (struct pci_vector_struct **vectors, int *count);
 int acpi_get_interrupt_model (int *type);
 int acpi_irq_to_vector (u32 irq);
 
-#ifdef CONFIG_DISCONTIGMEM
-#define NODE_ARRAY_INDEX(x)	((x) / 8)	/* 8 bits/char */
-#define NODE_ARRAY_OFFSET(x)	((x) % 8)	/* 8 bits/char */
-#define MAX_PXM_DOMAINS		(256)
-#endif /* CONFIG_DISCONTIGMEM */
+#ifdef CONFIG_ACPI_NUMA
+#include <asm/numa.h>
+/* Proximity bitmap length; _PXM is at most 255 (8 bit)*/
+#define MAX_PXM_DOMAINS (256)
+extern int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
+extern int __initdata nid_to_pxm_map[NR_NODES];
+#endif
 
 #endif /*__KERNEL__*/
 
diff -urN linux-2.4.23-pre3/include/asm-ia64/bitops.h linux-2.4.23-pre4/include/asm-ia64/bitops.h
--- linux-2.4.23-pre3/include/asm-ia64/bitops.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/bitops.h	2003-09-12 12:44:40.000000000 -0700
@@ -282,6 +282,21 @@
 	return result;
 }
 
+/**
+ * __ffs - find first bit in word.
+ * @x: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static __inline__ unsigned long
+__ffs (unsigned long x)
+{
+	unsigned long result;
+
+	__asm__ ("popcnt %0=%1" : "=r" (result) : "r" ((x - 1) & ~x));
+	return result;
+}
+
 #ifdef __KERNEL__
 
 /*
diff -urN linux-2.4.23-pre3/include/asm-ia64/elf.h linux-2.4.23-pre4/include/asm-ia64/elf.h
--- linux-2.4.23-pre3/include/asm-ia64/elf.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-pre4/include/asm-ia64/elf.h	2003-09-12 12:44:40.000000000 -0700
@@ -61,7 +61,7 @@
  *	b0-b7
  *	ip cfm psr
  *	ar.rsc ar.bsp ar.bspstore ar.rnat
- *	ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec
+ *	ar.ccv ar.unat ar.fpsr ar.pfs ar.lc ar.ec ar.csd ar.ssd
  */
 #define ELF_NGREG	128	/* we really need just 72 but let's leave some headroom... */
 #define ELF_NFPREG	128	/* f0 and f1 could be omitted, but so what... */
diff -urN linux-2.4.23-pre3/include/asm-ia64/hw_irq.h linux-2.4.23-pre4/include/asm-ia64/hw_irq.h
--- linux-2.4.23-pre3/include/asm-ia64/hw_irq.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-pre4/include/asm-ia64/hw_irq.h	2003-09-12 12:44:40.000000000 -0700
@@ -37,8 +37,10 @@
 /*
  * Vectors 0x10-0x1f are used for low priority interrupts, e.g. CMCI.
  */
-#define IA64_PCE_VECTOR			0x1e	/* platform corrected error interrupt vector */
-#define IA64_CMC_VECTOR			0x1f	/* correctable machine-check interrupt vector */
+#define IA64_CPEP_VECTOR		0x1c	/* corrected platform error polling vector */
+#define IA64_CMCP_VECTOR		0x1d	/* corrected machine-check polling vector */
+#define IA64_CPE_VECTOR			0x1e	/* corrected platform error interrupt vector */
+#define IA64_CMC_VECTOR			0x1f	/* corrected machine-check interrupt vector */
 /*
  * Vectors 0x20-0x2f are reserved for legacy ISA IRQs.
  */
diff -urN linux-2.4.23-pre3/include/asm-ia64/mca.h linux-2.4.23-pre4/include/asm-ia64/mca.h
--- linux-2.4.23-pre3/include/asm-ia64/mca.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/mca.h	2003-09-12 12:44:40.000000000 -0700
@@ -89,6 +89,8 @@
 	u64		imsto_sal_check_ra;	/* Return address in SAL_CHECK while going
 						 * back to SAL from OS after MCA handling.
 						 */
+	u64		pal_min_state;		/* from PAL in r17 */
+	u64		proc_state_param;	/* from PAL in r18. See SDV 2:268 11.3.2.1 */
 } ia64_mca_sal_to_os_state_t;
 
 enum {
@@ -132,7 +134,9 @@
 extern void ia64_mca_rendez_int_handler(int,void *,struct pt_regs *);
 extern void ia64_mca_wakeup_int_handler(int,void *,struct pt_regs *);
 extern void ia64_mca_cmc_int_handler(int,void *,struct pt_regs *);
+extern void ia64_mca_cmc_int_caller(int,void *,struct pt_regs *);
 extern void ia64_mca_cpe_int_handler(int,void *,struct pt_regs *);
+extern void ia64_mca_cpe_int_caller(int,void *,struct pt_regs *);
 extern int  ia64_log_print(int,prfunc_t);
 extern void ia64_mca_cmc_vector_setup(void);
 extern int  ia64_mca_check_errors(void);
diff -urN linux-2.4.23-pre3/include/asm-ia64/mmzone.h linux-2.4.23-pre4/include/asm-ia64/mmzone.h
--- linux-2.4.23-pre3/include/asm-ia64/mmzone.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/include/asm-ia64/mmzone.h	2003-09-12 12:44:40.000000000 -0700
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ *
+ * Copyright (c) 2000,2003 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2002 NEC Corp.
+ * Copyright (c) 2002 Erich Focht <efocht@ess.nec.de>
+ * Copyright (c) 2002 Kimio Suganuma <k-suganuma@da.jp.nec.com>
+ */
+#ifndef _ASM_IA64_MMZONE_H
+#define _ASM_IA64_MMZONE_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+
+#ifdef CONFIG_NUMA
+
+#ifdef CONFIG_IA64_DIG
+
+/*
+ * Platform definitions for DIG platform with contiguous memory.
+ */
+#define MAX_PHYSNODE_ID	8		/* Maximum node number +1 */
+#define NR_NODES	8		/* Maximum number of nodes in SSI */
+#define NR_MEMBLKS	(NR_NODES * 32)
+
+
+
+
+#elif CONFIG_IA64_SGI_SN2
+
+/*
+ * Platform definitions for DIG platform with contiguous memory.
+ */
+#define MAX_PHYSNODE_ID	2048		/* Maximum node number +1 */
+#define NR_NODES	256		/* Maximum number of compute nodes in SSI */
+#define NR_MEMBLKS	(NR_NODES)
+
+#elif CONFIG_IA64_GENERIC
+
+
+/*
+ * Platform definitions for GENERIC platform with contiguous or discontiguous memory.
+ */
+#define MAX_PHYSNODE_ID 2048		/* Maximum node number +1 */
+#define NR_NODES        256		/* Maximum number of nodes in SSI */
+#define NR_MEMBLKS      (NR_NODES)
+
+
+#else
+#error unknown platform
+#endif
+
+extern void build_cpu_to_node_map(void);
+
+#else /* CONFIG_NUMA */
+
+#define NR_NODES	1
+
+#endif /* CONFIG_NUMA */
+#endif /* _ASM_IA64_MMZONE_H */
diff -urN linux-2.4.23-pre3/include/asm-ia64/nodedata.h linux-2.4.23-pre4/include/asm-ia64/nodedata.h
--- linux-2.4.23-pre3/include/asm-ia64/nodedata.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/include/asm-ia64/nodedata.h	2003-09-12 12:44:40.000000000 -0700
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (c) 2002 NEC Corp.
+ * Copyright (c) 2002 Erich Focht <efocht@ess.nec.de>
+ * Copyright (c) 2002 Kimio Suganuma <k-suganuma@da.jp.nec.com>
+ */
+
+
+#ifndef _ASM_IA64_NODEDATA_H
+#define _ASM_IA64_NODEDATA_H
+
+
+#include <asm/mmzone.h>
+
+/*
+ * Node Data. One of these structures is located on each node of a NUMA system.
+ */
+
+struct pglist_data;
+struct ia64_node_data {
+	short			node;
+	short			active_cpu_count;
+	/*
+	 * The fields are read-only (after boot). They contain pointers to various structures
+	 * located on other nodes. Ths data is replicated on each node in order to reduce
+	 * off-node references.
+	 */
+        struct pglist_data	*pg_data_ptrs[NR_NODES];
+	struct ia64_node_data	*node_data_ptrs[NR_NODES];
+};
+
+
+/*
+ * Return a pointer to the node_data structure for the executing cpu.
+ */
+#define local_node_data		(local_cpu_data->node_data)
+
+
+/*
+ * Return a pointer to the node_data structure for the specified node.
+ */
+#define node_data(node)	(local_node_data->node_data_ptrs[node])
+
+
+/*
+ * Given a node id, return a pointer to the pg_data_t for the node.
+ * The following 2 macros are similar. 
+ *
+ * NODE_DATA 	- should be used in all code not related to system
+ *		  initialization. It uses pernode data structures to minimize
+ *		  offnode memory references. However, these structure are not 
+ *		  present during boot. This macro can be used once cpu_init
+ *		  completes.
+ *
+ * NOTE:   The names of these macros are misleading but are difficult to change
+ *	   since they are used in generic linux & on other architecures.
+ */
+#define NODE_DATA(nid)		(local_node_data->pg_data_ptrs[nid])
+
+extern struct pglist_data * __init boot_get_pg_data_ptr(long);
+
+#endif /* _ASM_IA64_NODEDATA_H */
diff -urN linux-2.4.23-pre3/include/asm-ia64/numa.h linux-2.4.23-pre4/include/asm-ia64/numa.h
--- linux-2.4.23-pre3/include/asm-ia64/numa.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/include/asm-ia64/numa.h	2003-09-12 12:44:40.000000000 -0700
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ *
+ * This file contains NUMA specific prototypes and definitions.
+ * 
+ * 2002/08/05 Erich Focht <efocht@ess.nec.de>
+ *
+ */
+#ifndef _ASM_IA64_NUMA_H
+#define _ASM_IA64_NUMA_H
+
+#ifdef CONFIG_NUMA
+
+#ifdef CONFIG_DISCONTIGMEM
+# include <asm/mmzone.h>
+#else
+# define NR_NODES     (8)
+# define NR_MEMBLKS   (NR_NODES * 8)
+#endif
+
+#include <linux/cache.h>
+#include <linux/threads.h>
+#include <linux/smp.h>
+
+#define NODEMASK_WORDCOUNT       ((NR_NODES+(BITS_PER_LONG-1))/BITS_PER_LONG)
+
+#define NODE_MASK_NONE   { [0 ... ((NR_NODES+BITS_PER_LONG-1)/BITS_PER_LONG)-1] = 0 }
+
+typedef unsigned long   nodemask_t[NODEMASK_WORDCOUNT];
+                                                                                                                             
+extern volatile char cpu_to_node_map[NR_CPUS] __cacheline_aligned;
+extern volatile unsigned long node_to_cpu_mask[NR_NODES] __cacheline_aligned;
+
+/* Stuff below this line could be architecture independent */
+
+extern int num_memblks;		/* total number of memory chunks */
+
+/*
+ * List of node memory chunks. Filled when parsing SRAT table to
+ * obtain information about memory nodes.
+*/
+
+struct node_memblk_s {
+	unsigned long start_paddr;
+	unsigned long size;
+	int nid;		/* which logical node contains this chunk? */
+	int bank;		/* which mem bank on this node */
+};
+
+struct node_cpuid_s {
+	u16	phys_id;	/* id << 8 | eid */
+	int	nid;		/* logical node containing this CPU */
+};
+
+extern struct node_memblk_s node_memblk[NR_MEMBLKS];
+extern struct node_cpuid_s node_cpuid[NR_CPUS];
+
+/*
+ * ACPI 2.0 SLIT (System Locality Information Table)
+ * http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf
+ *
+ * This is a matrix with "distances" between nodes, they should be
+ * proportional to the memory access latency ratios.
+ */
+
+extern u8 numa_slit[NR_NODES * NR_NODES];
+#define node_distance(from,to) (numa_slit[from * numnodes + to])
+
+extern int paddr_to_nid(unsigned long paddr);
+extern unsigned long memblk_endpaddr(unsigned long paddr);
+
+#define local_nodeid (cpu_to_node_map[smp_processor_id()])
+
+#else /* !CONFIG_NUMA */
+
+#define node_distance(from,to) 10
+#define paddr_to_nid(x) 0
+#define memblk_endpaddr(x) ~0UL
+#define local_nodeid 0
+
+#endif /* CONFIG_NUMA */
+
+#endif /* _ASM_IA64_NUMA_H */
diff -urN linux-2.4.23-pre3/include/asm-ia64/numnodes.h linux-2.4.23-pre4/include/asm-ia64/numnodes.h
--- linux-2.4.23-pre3/include/asm-ia64/numnodes.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/include/asm-ia64/numnodes.h	2003-09-12 12:44:40.000000000 -0700
@@ -0,0 +1,7 @@
+#ifndef _ASM_MAX_NUMNODES_H
+#define _ASM_MAX_NUMNODES_H
+
+#include <asm/mmzone.h>
+#define MAX_NUMNODES	NR_NODES
+
+#endif /* _ASM_MAX_NUMNODES_H */
diff -urN linux-2.4.23-pre3/include/asm-ia64/page.h linux-2.4.23-pre4/include/asm-ia64/page.h
--- linux-2.4.23-pre3/include/asm-ia64/page.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/page.h	2003-09-12 12:44:40.000000000 -0700
@@ -30,6 +30,8 @@
 #define PAGE_MASK		(~(PAGE_SIZE - 1))
 #define PAGE_ALIGN(addr)	(((addr) + PAGE_SIZE - 1) & PAGE_MASK)
 
+#define RGN_MAP_LIMIT	((1UL << (4*PAGE_SHIFT - 12)) - PAGE_SIZE)	/* per region addr limit */
+
 #ifdef __ASSEMBLY__
 # define __pa(x)		((x) - PAGE_OFFSET)
 # define __va(x)		((x) + PAGE_OFFSET)
@@ -52,19 +54,8 @@
  */
 #define MAP_NR_DENSE(addr)	(((unsigned long) (addr) - PAGE_OFFSET) >> PAGE_SHIFT)
 
-#ifdef CONFIG_IA64_GENERIC
-# include <asm/machvec.h>
-# define virt_to_page(kaddr)	(mem_map + platform_map_nr(kaddr))
-# define page_to_phys(page)	((page - mem_map) << PAGE_SHIFT)
-#elif defined (CONFIG_IA64_SGI_SN1)
-# ifndef CONFIG_DISCONTIGMEM
-#  define virt_to_page(kaddr)	(mem_map + MAP_NR_DENSE(kaddr))
-#  define page_to_phys(page)	XXX fix me
-# endif
-#else
-# define virt_to_page(kaddr)	(mem_map + MAP_NR_DENSE(kaddr))
-# define page_to_phys(page)	((page - mem_map) << PAGE_SHIFT)
-#endif
+#define virt_to_page(kaddr)	(mem_map + MAP_NR_DENSE(kaddr))
+#define page_to_phys(page)	((page - mem_map) << PAGE_SHIFT)
 
 struct page;
 extern int ia64_page_valid (struct page *);
diff -urN linux-2.4.23-pre3/include/asm-ia64/pci.h linux-2.4.23-pre4/include/asm-ia64/pci.h
--- linux-2.4.23-pre3/include/asm-ia64/pci.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/pci.h	2003-09-12 12:44:40.000000000 -0700
@@ -82,8 +82,8 @@
 #define pci_dac_dma_to_offset(dev,dma_addr)	((dma_addr) & ~PAGE_MASK)
 #define pci_dac_dma_sync_single(dev,dma_addr,len,dir)	do { /* nothing */ } while (0)
 
-/* Return the index of the PCI controller for device PDEV. */
-#define pci_controller_num(PDEV)	(0)
+/* Return the PCI domain number */
+#define pci_controller_num(pdev)	(PCI_SEGMENT(pdev))
 
 #define sg_dma_address(sg)	((sg)->dma_address)
 #define sg_dma_len(sg)		((sg)->dma_length)
diff -urN linux-2.4.23-pre3/include/asm-ia64/pgtable.h linux-2.4.23-pre4/include/asm-ia64/pgtable.h
--- linux-2.4.23-pre3/include/asm-ia64/pgtable.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/pgtable.h	2003-09-12 12:44:40.000000000 -0700
@@ -163,7 +163,6 @@
 	return (addr & (local_cpu_data->unimpl_pa_mask)) == 0;
 }
 
-#ifndef CONFIG_DISCONTIGMEM
 /*
  * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel
  * memory.  For the return value to be meaningful, ADDR must be >=
@@ -179,7 +178,6 @@
  */
 #define kern_addr_valid(addr)	(1)
 
-#endif
 
 /*
  * Now come the defines and routines to manage and access the three-level
@@ -193,7 +191,6 @@
 #define set_pte(ptep, pteval)	(*(ptep) = (pteval))
 
 #define RGN_SIZE	(1UL << 61)
-#define RGN_MAP_LIMIT	((1UL << (4*PAGE_SHIFT - 12)) - PAGE_SIZE)	/* per region addr limit */
 #define RGN_KERNEL	7
 
 #define VMALLOC_START		(0xa000000000000000 + 3*PAGE_SIZE)
@@ -227,10 +224,8 @@
 #define pte_none(pte) 			(!pte_val(pte))
 #define pte_present(pte)		(pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE))
 #define pte_clear(pte)			(pte_val(*(pte)) = 0UL)
-#ifndef CONFIG_DISCONTIGMEM
 /* pte_page() returns the "struct page *" corresponding to the PTE: */
 #define pte_page(pte)			(mem_map + (unsigned long) ((pte_val(pte) & _PFN_MASK) >> PAGE_SHIFT))
-#endif
 
 #define pmd_none(pmd)			(!pmd_val(pmd))
 #define pmd_bad(pmd)			(!ia64_phys_addr_valid(pmd_val(pmd)))
@@ -430,7 +425,8 @@
  * for zero-mapped memory areas etc..
  */
 extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+extern struct page *zero_page_memmap_ptr;
+#define ZERO_PAGE(vaddr) (zero_page_memmap_ptr)
 
 /* We provide our own get_unmapped_area to cope with VA holes for userland */
 #define HAVE_ARCH_UNMAPPED_AREA
diff -urN linux-2.4.23-pre3/include/asm-ia64/processor.h linux-2.4.23-pre4/include/asm-ia64/processor.h
--- linux-2.4.23-pre3/include/asm-ia64/processor.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/processor.h	2003-09-12 12:44:40.000000000 -0700
@@ -19,6 +19,7 @@
 #include <asm/ptrace.h>
 #include <asm/kregs.h>
 #include <asm/types.h>
+#include <asm/ustack.h>
 
 #define IA64_NUM_DBG_REGS	8
 /*
@@ -87,6 +88,9 @@
 #include <asm/rse.h>
 #include <asm/unwind.h>
 #include <asm/atomic.h>
+#ifdef CONFIG_NUMA
+#include <asm/nodedata.h>
+#endif
 
 /* like above but expressed as bitfields for more efficient access: */
 struct ia64_psr {
@@ -187,8 +191,8 @@
 	} ipi;
 #endif
 #ifdef CONFIG_NUMA
-	void *node_directory;
-	int numa_node_id;
+	struct ia64_node_data *node_data;
+	int nodeid;
 	struct cpuinfo_ia64 *cpu_data[NR_CPUS];
 #endif
 	/* Platform specific word.  MUST BE LAST IN STRUCT */
@@ -213,9 +217,9 @@
  */
 #ifdef CONFIG_NUMA
 # define cpu_data(cpu)		local_cpu_data->cpu_data[cpu]
-# define numa_node_id()		(local_cpu_data->numa_node_id)
+# define numa_node_id()		(local_cpu_data->nodeid)
 #else
-  extern struct cpuinfo_ia64 _cpu_data[NR_CPUS];
+  extern struct cpuinfo_ia64	_cpu_data[NR_CPUS];
 # define cpu_data(cpu)		(&_cpu_data[cpu])
 #endif
 
@@ -257,6 +261,7 @@
 	unsigned long flags;		/* various flags */
 	__u64 map_base;			/* base address for get_unmapped_area() */
 	__u64 task_size;		/* limit for task size */
+	__u64 rbs_bot;			/* the base address for the RBS */
 	struct siginfo *siginfo;	/* current siginfo struct for ptrace() */
 
 #ifdef CONFIG_IA32_SUPPORT
@@ -265,11 +270,9 @@
 	__u64 fcr;			/* IA32 floating pt control reg */
 	__u64 fir;			/* IA32 fp except. instr. reg */
 	__u64 fdr;			/* IA32 fp except. data reg */
-	__u64 csd;			/* IA32 code selector descriptor */
-	__u64 ssd;			/* IA32 stack selector descriptor */
 	__u64 old_k1;			/* old value of ar.k1 */
 	__u64 old_iob;			/* old IOBase value */
-# define INIT_THREAD_IA32	0, 0, 0x17800000037fULL, 0, 0, 0, 0, 0, 0,
+# define INIT_THREAD_IA32	0, 0, 0x17800000037fULL, 0, 0, 0, 0, 
 #else
 # define INIT_THREAD_IA32
 #endif /* CONFIG_IA32_SUPPORT */
@@ -296,6 +299,7 @@
 	0,				/* flags */	\
 	DEFAULT_MAP_BASE,		/* map_base */	\
 	DEFAULT_TASK_SIZE,		/* task_size */	\
+	DEFAULT_USER_STACK_SIZE,	/* rbs_bot */	\
 	0,				/* siginfo */	\
 	INIT_THREAD_IA32				\
 	INIT_THREAD_PM					\
@@ -312,7 +316,7 @@
 	regs->cr_iip = new_ip;									\
 	regs->ar_rsc = 0xf;		/* eager mode, privilege level 3 */			\
 	regs->ar_rnat = 0;									\
-	regs->ar_bspstore = IA64_RBS_BOT;							\
+	regs->ar_bspstore = current->thread.rbs_bot;						\
 	regs->ar_fpsr = FPSR_DEFAULT;								\
 	regs->loadrs = 0;									\
 	regs->r8 = current->mm->dumpable;	/* set "don't zap registers" flag */		\
@@ -337,11 +341,15 @@
 		regs->r24 = 0; regs->r25 = 0; regs->r26 = 0; regs->r27 = 0;			\
 		regs->r28 = 0; regs->r29 = 0; regs->r30 = 0; regs->r31 = 0;			\
 		regs->ar_ccv = 0;								\
+		regs->ar_csd = 0;                                                               \
+		regs->ar_ssd = 0;                                                               \
 		regs->b0 = 0; regs->b7 = 0;							\
 		regs->f6.u.bits[0] = 0; regs->f6.u.bits[1] = 0;					\
 		regs->f7.u.bits[0] = 0; regs->f7.u.bits[1] = 0;					\
 		regs->f8.u.bits[0] = 0; regs->f8.u.bits[1] = 0;					\
 		regs->f9.u.bits[0] = 0; regs->f9.u.bits[1] = 0;					\
+		regs->f10.u.bits[0] = 0; regs->f10.u.bits[1] = 0;				\
+		regs->f11.u.bits[0] = 0; regs->f11.u.bits[1] = 0;				\
 	}											\
 } while (0)
 
@@ -655,8 +663,17 @@
 	asm volatile ("mov cr.lrr0=%0;; srlz.d" :: "r"(val) : "memory");
 }
 
-#define cpu_relax()	do { } while (0)
+#ifdef GAS_HAS_HINT_INSN
+static inline void
+ia64_hint_pause (void)
+{
+	asm volatile ("hint @pause" ::: "memory");
+}
 
+#define cpu_relax()	ia64_hint_pause()
+#else
+#define cpu_relax()	barrier()
+#endif
 
 static inline void
 ia64_set_lrr1 (unsigned long val)
@@ -759,18 +776,12 @@
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
 
-/*
- * Set the correctable machine check vector register
- */
 static inline void
 ia64_set_cmcv (__u64 val)
 {
 	asm volatile ("mov cr.cmcv=%0" :: "r"(val) : "memory");
 }
 
-/*
- * Read the correctable machine check vector register
- */
 static inline __u64
 ia64_get_cmcv (void)
 {
@@ -950,6 +961,18 @@
 	return result;
 }
 
+/*
+ * Take a mapped kernel address and return the equivalent address
+ * in the region 7 identity mapped virtual area.
+ */
+static inline void *
+ia64_imva (void *addr)
+{
+	void *result;
+	asm ("tpa %0=%1" : "=r"(result) : "r"(addr));
+	return __va(result);
+}
+
 #define ARCH_HAS_PREFETCH
 #define ARCH_HAS_PREFETCHW
 #define ARCH_HAS_SPINLOCK_PREFETCH
diff -urN linux-2.4.23-pre3/include/asm-ia64/ptrace.h linux-2.4.23-pre4/include/asm-ia64/ptrace.h
--- linux-2.4.23-pre3/include/asm-ia64/ptrace.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/ptrace.h	2003-09-12 12:44:40.000000000 -0700
@@ -2,6 +2,7 @@
 #define _ASM_IA64_PTRACE_H
 
 /*
+ * Copyright (C) 1998-2001 Suresh Siddha <suresh.b.siddha@intel.com>  
  * Copyright (C) 1998-2001 Hewlett-Packard Co
  * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
@@ -90,7 +91,20 @@
  *
  */
 struct pt_regs {
-	/* The following registers are saved by SAVE_MIN: */
+	/* In break_fault, only registers from cr_ipsr to r15 are saved. 
+	 * In any other interruptions, the registers cr_ipsr~r15, r8~r11, and r14~r3 are saved by 
+	 * SAVE_MIN and all other registers are saved by SAVE_REST.
+	 */
+	unsigned long b6;		/* scratch */
+	unsigned long b7;		/* scratch */
+
+	unsigned long ar_csd;           /* used by cmp8xchg16 (scratch) */
+	unsigned long ar_ssd;           /* reserved for future use (scratch) */
+
+	unsigned long r8;		/* scratch (return value register 0) */
+	unsigned long r9;		/* scratch (return value register 1) */
+	unsigned long r10;		/* scratch (return value register 2) */
+	unsigned long r11;		/* scratch (return value register 3) */
 
 	unsigned long cr_ipsr;		/* interrupted task's psr */
 	unsigned long cr_iip;		/* interrupted task's instruction pointer */
@@ -104,23 +118,19 @@
 	unsigned long ar_bspstore;	/* RSE bspstore */
 
 	unsigned long pr;		/* 64 predicate registers (1 bit each) */
-	unsigned long b6;		/* scratch */
+	unsigned long b0;		/* return pointer (bp) */
 	unsigned long loadrs;		/* size of dirty partition << 16 */
 
 	unsigned long r1;		/* the gp pointer */
-	unsigned long r2;		/* scratch */
-	unsigned long r3;		/* scratch */
 	unsigned long r12;		/* interrupted task's memory stack pointer */
 	unsigned long r13;		/* thread pointer */
-	unsigned long r14;		/* scratch */
-	unsigned long r15;		/* scratch */
 
-	unsigned long r8;		/* scratch (return value register 0) */
-	unsigned long r9;		/* scratch (return value register 1) */
-	unsigned long r10;		/* scratch (return value register 2) */
-	unsigned long r11;		/* scratch (return value register 3) */
+	unsigned long ar_fpsr;		/* floating point status (preserved) */
+	unsigned long r15;		/* scratch */
 
-	/* The following registers are saved by SAVE_REST: */
+	unsigned long r14;		/* scratch */
+	unsigned long r2;		/* scratch */
+	unsigned long r3;		/* scratch */
 
 	unsigned long r16;		/* scratch */
 	unsigned long r17;		/* scratch */
@@ -140,10 +150,7 @@
 	unsigned long r31;		/* scratch */
 
 	unsigned long ar_ccv;		/* compare/exchange value (scratch) */
-	unsigned long ar_fpsr;		/* floating point status (preserved) */
 
-	unsigned long b0;		/* return pointer (bp) */
-	unsigned long b7;		/* scratch */
 	/*
 	 * Floating point registers that the kernel considers
 	 * scratch:
@@ -152,6 +159,8 @@
 	struct ia64_fpreg f7;		/* scratch */
 	struct ia64_fpreg f8;		/* scratch */
 	struct ia64_fpreg f9;		/* scratch */
+	struct ia64_fpreg f10;		/* scratch */
+	struct ia64_fpreg f11;		/* scratch */
 };
 
 /*
@@ -168,8 +177,6 @@
 	struct ia64_fpreg f4;		/* preserved */
 	struct ia64_fpreg f5;		/* preserved */
 
-	struct ia64_fpreg f10;		/* scratch, but untouched by kernel */
-	struct ia64_fpreg f11;		/* scratch, but untouched by kernel */
 	struct ia64_fpreg f12;		/* scratch, but untouched by kernel */
 	struct ia64_fpreg f13;		/* scratch, but untouched by kernel */
 	struct ia64_fpreg f14;		/* scratch, but untouched by kernel */
diff -urN linux-2.4.23-pre3/include/asm-ia64/ptrace_offsets.h linux-2.4.23-pre4/include/asm-ia64/ptrace_offsets.h
--- linux-2.4.23-pre3/include/asm-ia64/ptrace_offsets.h	2001-07-31 10:30:09.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/ptrace_offsets.h	2003-09-12 12:44:40.000000000 -0700
@@ -11,9 +11,64 @@
  *
  *	struct uarea {
  *		struct ia64_fpreg fph[96];		// f32-f127
- *		struct switch_stack sw;
- *		struct pt_regs pt;
- *		unsigned long rsvd1[712];
+ *		unsigned long nat_bits;
+ *		unsigned long empty1;		
+ *		struct ia64_fpreg f2;			// f2-f5
+ *			.
+ *			.
+ *		struct ia64_fpreg f5;
+ *		struct ia64_fpreg f10;			// f10-f31
+ *			.
+ *			.
+ *		struct ia64_fpreg f31;
+ *		unsigned long r4;			// r4-r7
+ *			.
+ *			.
+ *		unsigned long r7;
+ *		unsigned long b1;			// b1-b5
+ *			.
+ *			.
+ *		unsigned long b5;
+ *		unsigned long ar_ec;
+ *		unsigned long ar_lc;
+ *		unsigned long empty2[5];
+ *		unsigned long cr_ipsr;
+ *		unsigned long cr_iip;
+ *		unsigned long cfm;
+ *		unsigned long ar_unat;
+ *		unsigned long ar_pfs;
+ *		unsigned long ar_rsc;
+ *		unsigned long ar_rnat;
+ *		unsigned long ar_bspstore;
+ *		unsigned long pr;
+ *		unsigned long b6;
+ *		unsigned long ar_bsp;
+ *		unsigned long r1;
+ *		unsigned long r2;
+ *		unsigned long r3;
+ *		unsigned long r12;
+ *		unsigned long r13;
+ *		unsigned long r14;
+ *		unsigned long r15;
+ *		unsigned long r8;
+ *		unsigned long r9;
+ *		unsigned long r10;
+ *		unsigned long r11;
+ *		unsigned long r16;
+ *			.
+ *			.
+ *		unsigned long r31;
+ *		unsigned long ar_ccv;
+ *		unsigned long ar_fpsr;
+ *		unsigned long b0;
+ *		unsigned long b7;
+ *		unsigned long f6;
+ *		unsigned long f7;
+ *		unsigned long f8;
+ *		unsigned long f9;
+ *		unsigned long ar_csd;
+ *		unsigned long ar_ssd;
+ *		unsigned long rsvd1[710];
  *		unsigned long dbr[8];
  *		unsigned long rsvd2[504];
  *		unsigned long ibr[8];
@@ -119,7 +174,7 @@
 #define PT_F125			0x05d0
 #define PT_F126			0x05e0
 #define PT_F127			0x05f0
-/* switch stack: */
+
 #define PT_NAT_BITS		0x0600
 
 #define PT_F2			0x0610
@@ -162,7 +217,6 @@
 #define PT_AR_EC		0x0800
 #define PT_AR_LC		0x0808
 
-/* pt_regs */
 #define PT_CR_IPSR		0x0830
 #define PT_CR_IIP		0x0838
 #define PT_CFM			0x0840
@@ -209,6 +263,8 @@
 #define PT_F7			0x0990
 #define PT_F8			0x09a0
 #define PT_F9			0x09b0
+#define PT_AR_CSD		0x09c0
+#define PT_AR_SSD		0x09c8
 
 #define PT_DBR			0x2000	/* data breakpoint registers */
 #define PT_IBR			0x3000	/* instruction breakpoint registers */
diff -urN linux-2.4.23-pre3/include/asm-ia64/resource.h linux-2.4.23-pre4/include/asm-ia64/resource.h
--- linux-2.4.23-pre3/include/asm-ia64/resource.h	2000-09-22 14:21:19.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/resource.h	2003-09-12 12:44:40.000000000 -0700
@@ -8,6 +8,8 @@
  * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
+#include <asm/ustack.h>
+
 #define RLIMIT_CPU	0		/* CPU time in ms */
 #define RLIMIT_FSIZE	1		/* Maximum filesize */
 #define RLIMIT_DATA	2		/* max data size */
@@ -35,7 +37,7 @@
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
-	{      _STK_LIM, RLIM_INFINITY },		\
+	{      _STK_LIM, DEFAULT_USER_STACK_SIZE },	\
 	{             0, RLIM_INFINITY },		\
 	{ RLIM_INFINITY, RLIM_INFINITY },		\
 	{             0,             0 },		\
diff -urN linux-2.4.23-pre3/include/asm-ia64/sal.h linux-2.4.23-pre4/include/asm-ia64/sal.h
--- linux-2.4.23-pre3/include/asm-ia64/sal.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sal.h	2003-09-12 12:44:40.000000000 -0700
@@ -23,6 +23,18 @@
  *                      (plus examples of platform error info structures from smariset @ Intel)
  */
 
+#define IA64_SAL_PLATFORM_FEATURE_BUS_LOCK_BIT		0
+#define IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT_BIT	1
+#define IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT_BIT	2
+#define IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT_BIT	 	3
+
+#define IA64_SAL_PLATFORM_FEATURE_BUS_LOCK	  (1<<IA64_SAL_PLATFORM_FEATURE_BUS_LOCK_BIT)
+#define IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT (1<<IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT_BIT)
+#define IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT (1<<IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT_BIT)
+#define IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT	  (1<<IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT_BIT)
+
+#ifndef __ASSEMBLY__
+
 #include <linux/spinlock.h>
 #include <linux/efi.h>
 
@@ -56,6 +68,13 @@
 	ia64_load_scratch_fpregs(__ia64_scn_fr);	\
 } while (0)
 
+# define SAL_CALL_REENTRANT(result,args...) do {	\
+	struct ia64_fpreg __ia64_scs_fr[6];		\
+	ia64_save_scratch_fpregs(__ia64_scs_fr);	\
+	__SAL_CALL(result, args);			\
+	ia64_load_scratch_fpregs(__ia64_scs_fr);	\
+} while (0)
+
 #define SAL_SET_VECTORS			0x01000000
 #define SAL_GET_STATE_INFO		0x01000001
 #define SAL_GET_STATE_INFO_SIZE		0x01000002
@@ -162,11 +181,6 @@
 	u8 oem_reserved[8];
 } ia64_sal_desc_memory_t;
 
-#define IA64_SAL_PLATFORM_FEATURE_BUS_LOCK		(1 << 0)
-#define IA64_SAL_PLATFORM_FEATURE_IRQ_REDIR_HINT	(1 << 1)
-#define IA64_SAL_PLATFORM_FEATURE_IPI_REDIR_HINT	(1 << 2)
-#define IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT	 	(1 << 3)
-
 typedef struct ia64_sal_desc_platform_feature {
 	u8 type;
 	u8 feature_mask;
@@ -226,7 +240,7 @@
 
 /* Encodings for machine check parameter types */
 enum {
-	SAL_MC_PARAM_RENDEZ_INT    = 1,	/* Rendezevous interrupt */
+	SAL_MC_PARAM_RENDEZ_INT    = 1,	/* Rendezvous interrupt */
 	SAL_MC_PARAM_RENDEZ_WAKEUP = 2,	/* Wakeup */
 	SAL_MC_PARAM_CPE_INT	   = 3	/* Corrected Platform Error Int */
 };
@@ -658,8 +672,8 @@
 ia64_sal_clear_state_info (u64 sal_info_type)
 {
 	struct ia64_sal_retval isrv;
-    SAL_CALL(isrv, SAL_CLEAR_STATE_INFO, sal_info_type, 0,
-             0, 0, 0, 0, 0);
+	SAL_CALL_REENTRANT(isrv, SAL_CLEAR_STATE_INFO, sal_info_type, 0,
+	              0, 0, 0, 0, 0);
 	return isrv.status;
 }
 
@@ -671,8 +685,8 @@
 ia64_sal_get_state_info (u64 sal_info_type, u64 *sal_info)
 {
 	struct ia64_sal_retval isrv;
-	SAL_CALL(isrv, SAL_GET_STATE_INFO, sal_info_type, 0,
-	         sal_info, 0, 0, 0, 0);
+	SAL_CALL_REENTRANT(isrv, SAL_GET_STATE_INFO, sal_info_type, 0,
+	              sal_info, 0, 0, 0, 0);
 	if (isrv.status)
 		return 0;
 
@@ -687,8 +701,8 @@
 ia64_sal_get_state_info_size (u64 sal_info_type)
 {
 	struct ia64_sal_retval isrv;
-    SAL_CALL(isrv, SAL_GET_STATE_INFO_SIZE, sal_info_type, 0,
-             0, 0, 0, 0, 0);
+	SAL_CALL_REENTRANT(isrv, SAL_GET_STATE_INFO_SIZE, sal_info_type, 0,
+	              0, 0, 0, 0, 0);
 	if (isrv.status)
 		return 0;
 	return isrv.v0;
@@ -792,4 +806,6 @@
 
 extern unsigned long sal_platform_features;
 
+#endif /* __ASSEMBLY__ */
+
 #endif /* _ASM_IA64_PAL_H */
diff -urN linux-2.4.23-pre3/include/asm-ia64/sigcontext.h linux-2.4.23-pre4/include/asm-ia64/sigcontext.h
--- linux-2.4.23-pre3/include/asm-ia64/sigcontext.h	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sigcontext.h	2003-09-12 12:44:40.000000000 -0700
@@ -56,7 +56,7 @@
 	unsigned long		sc_rbs_base;	/* NULL or new base of sighandler's rbs */
 	unsigned long		sc_loadrs;	/* see description above */
 
-	unsigned long		sc_ar25;	/* rsvd for scratch use */
+	unsigned long		sc_ar25;	/* cmp8xchg16 uses this */
 	unsigned long		sc_ar26;	/* rsvd for scratch use */
 	unsigned long		sc_rsvd[12];	/* reserved for future use */
 	/*
diff -urN linux-2.4.23-pre3/include/asm-ia64/smp.h linux-2.4.23-pre4/include/asm-ia64/smp.h
--- linux-2.4.23-pre3/include/asm-ia64/smp.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/smp.h	2003-09-12 12:44:40.000000000 -0700
@@ -124,6 +124,7 @@
 extern int smp_call_function_single (int cpuid, void (*func) (void *info), void *info,
 				     int retry, int wait);
 
+extern void smp_build_cpu_map(void);
 
 #endif /* CONFIG_SMP */
 #endif /* _ASM_IA64_SMP_H */
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/bte.h linux-2.4.23-pre4/include/asm-ia64/sn/bte.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/bte.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/bte.h	2003-09-12 12:44:40.000000000 -0700
@@ -59,6 +59,15 @@
 #endif	/* BTE_DEBUG */
 
 
+#ifndef L1_CACHE_MASK
+#define L1_CACHE_MASK		(L1_CACHE_BYTES - 1)
+#endif
+
+#ifndef L1_CACHE_ALIGNED
+#define L1_CACHE_ALIGNED(_p)	(((u64)(_p) & L1_CACHE_MASK) == 0)
+#endif
+
+
 /* BTE status register only supports 16 bits for length field */
 #define BTE_LEN_BITS (16)
 #define BTE_LEN_MASK ((1 << BTE_LEN_BITS) - 1)
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/cdl.h linux-2.4.23-pre4/include/asm-ia64/sn/cdl.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/cdl.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/cdl.h	2003-09-12 12:44:40.000000000 -0700
@@ -9,7 +9,9 @@
 #ifndef _ASM_IA64_SN_CDL_H
 #define _ASM_IA64_SN_CDL_H
 
+#ifdef __KERNEL__
 #include <asm/sn/sgi.h>
+#endif
 
 struct cdl {
 	int part_num;			/* Part part number */
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/dmamap.h linux-2.4.23-pre4/include/asm-ia64/sn/dmamap.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/dmamap.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/dmamap.h	2003-09-12 12:44:40.000000000 -0700
@@ -9,7 +9,7 @@
 #ifndef _ASM_IA64_SN_DMAMAP_H
 #define _ASM_IA64_SN_DMAMAP_H
 
-#include <asm/sn/sv.h>
+#include <asm/sn/types.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -41,33 +41,9 @@
 	int		dma_index;	/* Beginning map register to use */
 	int		dma_size;	/* Number of map registers to use */
 	paddr_t		dma_addr;	/* Corresponding bus addr for A24/A32 */
-	caddr_t		dma_virtaddr;	/* Beginning virtual address that is mapped */
+	unsigned long	dma_virtaddr;	/* Beginning virtual address that is mapped */
 } dmamap_t;
 
-struct alenlist_s;
-
-/*
- * Prototypes of exported functions
- */
-extern dmamap_t	*dma_mapalloc(int, int, int, int);
-extern void	dma_mapfree(dmamap_t *);
-extern int	dma_map(dmamap_t *, caddr_t, int);
-extern int	dma_map2(dmamap_t *, caddr_t, caddr_t, int);
-extern paddr_t	dma_mapaddr(dmamap_t *, caddr_t);
-extern int	dma_map_alenlist(dmamap_t *, struct alenlist_s *, size_t);
-extern uint	ev_kvtoiopnum(caddr_t);
-
-/*
- * These variables are defined in master.d/kernel
- */
-extern struct map *a24map[];
-extern struct map *a32map[];
-
-extern int a24_mapsize;
-extern int a32_mapsize;
-
-extern sv_t dmamapout;
-
 #ifdef __cplusplus
 }
 #endif
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/hcl.h linux-2.4.23-pre4/include/asm-ia64/sn/hcl.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/hcl.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/hcl.h	2003-09-12 12:44:40.000000000 -0700
@@ -14,6 +14,13 @@
 extern vertex_hdl_t hwgraph_root;
 extern vertex_hdl_t linux_busnum;
 
+void hwgraph_debug(char *, char *, int, vertex_hdl_t, vertex_hdl_t, char *, ...);
+
+#if 1
+#define HWGRAPH_DEBUG(args) hwgraph_debug args ;
+#else   
+#define HWGRAPH_DEBUG(args)
+#endif  
 
 typedef long            labelcl_info_place_t;
 typedef long            arbitrary_info_t;
@@ -55,6 +62,7 @@
 /*
  * External declarations of EXPORTED SYMBOLS in hcl.c
  */
+extern int hwgraph_generate_path(vertex_hdl_t, char *, int);
 extern vertex_hdl_t hwgraph_register(vertex_hdl_t, const char *,
 	unsigned int, unsigned int, unsigned int, unsigned int,
 	umode_t, uid_t, gid_t, struct file_operations *, void *);
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/invent.h linux-2.4.23-pre4/include/asm-ia64/sn/invent.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/invent.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/invent.h	2003-09-12 12:44:40.000000000 -0700
@@ -701,16 +701,6 @@
 
 #ifdef __KERNEL__
 
-typedef struct irix5_inventory_s {
-	app32_ptr_t	inv_next;	/* next inventory record in list */
-	int	inv_class;		/* class of object */
-	int	inv_type;		/* class sub-type of object */
-	major_t	inv_controller;		/* object major identifier */
-	minor_t	inv_unit;		/* object minor identifier */
-	int	inv_state;		/* information specific to object or
-					   class */
-} irix5_inventory_t;
-
 typedef struct invplace_s {
 	vertex_hdl_t		invplace_vhdl;		/* current vertex */
 	vertex_hdl_t		invplace_vplace;	/* place in vertex list */
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/io.h linux-2.4.23-pre4/include/asm-ia64/sn/io.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/io.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/io.h	2003-09-12 12:44:40.000000000 -0700
@@ -13,6 +13,8 @@
 
 #include <asm/sn/addrs.h>
 
+extern int numionodes;
+
 /* Because we only have PCI I/O ports.  */
 #define IIO_ITTE_BASE	0x400160	/* base of translation table entries */
 #define IIO_ITTE(bigwin)	(IIO_ITTE_BASE + 8*(bigwin))
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/ioc4.h linux-2.4.23-pre4/include/asm-ia64/sn/ioc4.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/ioc4.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/ioc4.h	2003-09-12 12:44:40.000000000 -0700
@@ -30,7 +30,6 @@
 #ifndef _ASM_IA64_SN_IOC4_H
 #define _ASM_IA64_SN_IOC4_H
 
-#if 0
 
 /*
  * ioc4.h - IOC4 chip header file
@@ -46,7 +45,7 @@
  *
  * All IOC4 registers are 32 bits wide.
  */
-typedef __uint32_t ioc4reg_t;
+typedef uint32_t ioc4reg_t;
 
 /*
  * PCI Configuration Space Register Address Map, use offset from IOC4 PCI
@@ -70,10 +69,12 @@
  * PCI Memory Space Map 
  */
 #define IOC4_PCI_ERR_ADDR_L     0x000	/* Low Error Address */
-#define IOC4_PCI_ERR_ADDR_VLD	     (0x1 << 0)
-#define IOC4_PCI_ERR_ADDR_MST_ID_MSK (0xf << 1)
-#define IOC4_PCI_ERR_ADDR_MUL_ERR    (0x1 << 5)
-#define IOC4_PCI_ERR_ADDR_ADDR_MSK   (0x3ffffff << 6)
+#define IOC4_PCI_ERR_ADDR_VLD	        (0x1 << 0)
+#define IOC4_PCI_ERR_ADDR_MST_ID_MSK    (0xf << 1)
+#define IOC4_PCI_ERR_ADDR_MST_NUM_MSK   (0xe << 1)
+#define IOC4_PCI_ERR_ADDR_MST_TYP_MSK   (0x1 << 1)
+#define IOC4_PCI_ERR_ADDR_MUL_ERR       (0x1 << 5)
+#define IOC4_PCI_ERR_ADDR_ADDR_MSK      (0x3ffffff << 6)
 
 /* Master IDs contained in PCI_ERR_ADDR_MST_ID_MSK */
 #define IOC4_MST_ID_S0_TX		0
@@ -569,26 +570,27 @@
 
 /* IOC4 UART register map */
 typedef volatile struct ioc4_uartregs {
+    char                    i4u_lcr;
     union {
-        char                    rbr;    /* read only, DLAB == 0 */
-        char                    thr;    /* write only, DLAB == 0 */
-        char                    dll;    /* DLAB == 1 */
-    } u1;
+        char                    iir;    /* read only */
+        char                    fcr;    /* write only */
+    } u3;
     union {
         char                    ier;    /* DLAB == 0 */
         char                    dlm;    /* DLAB == 1 */
     } u2;
     union {
-        char                    iir;    /* read only */
-        char                    fcr;    /* write only */
-    } u3;
-    char                    i4u_lcr;
-    char                    i4u_mcr;
-    char                    i4u_lsr;
-    char                    i4u_msr;
+        char                    rbr;    /* read only, DLAB == 0 */
+        char                    thr;    /* write only, DLAB == 0 */
+        char                    dll;    /* DLAB == 1 */
+    } u1;
     char                    i4u_scr;
+    char                    i4u_msr;
+    char                    i4u_lsr;
+    char                    i4u_mcr;
 } ioc4_uart_t;
 
+
 #define i4u_rbr u1.rbr
 #define i4u_thr u1.thr
 #define i4u_dll u1.dll
@@ -704,7 +706,6 @@
     ioc4_uart_t		    uart_3;
 } ioc4_mem_t;
 
-#endif	/* 0 */
 
 /*
  * Bytebus device space
@@ -714,7 +715,6 @@
 #define IOC4_BYTEBUS_DEV2	0xC0000L  /* Addressed using pci_bar0 */
 #define IOC4_BYTEBUS_DEV3	0xE0000L  /* Addressed using pci_bar0 */
 
-#if 0
 /* UART clock speed */
 #define IOC4_SER_XIN_CLK        66000000
 
@@ -749,7 +749,7 @@
 #define IOC4_INTA_SUBDEVS	(IOC4_SDB_SERIAL | IOC4_SDB_KBMS | IOC4_SDB_RT | IOC4_SDB_GENERIC)
 
 extern int		ioc4_subdev_enabled(vertex_hdl_t, ioc4_subdev_t);
-extern void		ioc4_subdev_enables(vertex_hdl_t, ulong_t);
+extern void		ioc4_subdev_enables(vertex_hdl_t, uint64_t);
 extern void		ioc4_subdev_enable(vertex_hdl_t, ioc4_subdev_t);
 extern void		ioc4_subdev_disable(vertex_hdl_t, ioc4_subdev_t);
 
@@ -767,7 +767,7 @@
 ioc4_intr_func_f	(intr_arg_t, ioc4reg_t);
 
 typedef void
-ioc4_intr_connect_f	(vertex_hdl_t conn_vhdl,
+ioc4_intr_connect_f	(struct pci_dev *conn_vhdl,
 			 ioc4_intr_type_t,
 			 ioc4reg_t,
 			 ioc4_intr_func_f *,
@@ -784,18 +784,17 @@
 			 intr_arg_t info,
 			 vertex_hdl_t owner_vhdl);
 
-ioc4_intr_disconnect_f	ioc4_intr_disconnect;
-ioc4_intr_connect_f	ioc4_intr_connect;
+void ioc4_intr_connect(vertex_hdl_t, ioc4_intr_type_t, ioc4reg_t,
+		  ioc4_intr_func_f *, intr_arg_t, vertex_hdl_t,
+		  vertex_hdl_t);
 
 extern int		ioc4_is_console(vertex_hdl_t conn_vhdl);
 
 extern void		ioc4_mlreset(ioc4_cfg_t *, ioc4_mem_t *);
 
-extern intr_func_f	ioc4_intr;
 
 extern ioc4_mem_t      *ioc4_mem_ptr(void *ioc4_fastinfo);
 
 typedef ioc4_intr_func_f *ioc4_intr_func_t;
 
-#endif	/* 0 */
 #endif				/* _ASM_IA64_SN_IOC4_H */
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/ioerror.h linux-2.4.23-pre4/include/asm-ia64/sn/ioerror.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/ioerror.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/ioerror.h	2003-09-12 12:44:40.000000000 -0700
@@ -185,10 +185,10 @@
 typedef int             error_handler_f(void *, int, ioerror_mode_t, ioerror_t *);
 typedef void           *error_handler_arg_t;
 
-extern void             ioerror_dump(char *, int, int, ioerror_t *);
+extern void             snia_ioerror_dump(char *, int, int, ioerror_t *);
 
 #ifdef	ERROR_DEBUG
-#define	IOERROR_DUMP(x, y, z, t)	ioerror_dump((x), (y), (z), (t))
+#define	IOERROR_DUMP(x, y, z, t)	snia_ioerror_dump((x), (y), (z), (t))
 #define	IOERR_PRINTF(x)	(x)
 #else
 #define	IOERROR_DUMP(x, y, z, t)
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/ioerror_handling.h linux-2.4.23-pre4/include/asm-ia64/sn/ioerror_handling.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/ioerror_handling.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/ioerror_handling.h	2003-09-12 12:44:40.000000000 -0700
@@ -233,10 +233,6 @@
 #define v_error_skip_env_clear(v)		\
 hwgraph_info_remove_LBL(v, INFO_LBL_ERROR_SKIP_ENV, 0)
 
-/* Skip point interfaces */
-extern error_return_code_t	error_skip_point_jump(vertex_hdl_t, boolean_t);
-extern error_return_code_t	error_skip_point_clear(vertex_hdl_t);
-
 /* REFERENCED */
 #if defined(CONFIG_SGI_IO_ERROR_HANDLING)
 
@@ -256,7 +252,7 @@
 	 * one.								 
 	 */								 
 	if (v_error_skip_env_get(v, error_env) != GRAPH_SUCCESS) {	 
-		error_env = snia_kmem_zalloc(sizeof(label_t), KM_NOSLEEP);	 
+		error_env = snia_kmem_zalloc(sizeof(label_t));
 		/* Unable to allocate memory for jum buffer. This should 
 		 * be a very rare occurrence.				 
 		 */							 
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/iograph.h linux-2.4.23-pre4/include/asm-ia64/sn/iograph.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/iograph.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/iograph.h	2003-09-12 12:44:40.000000000 -0700
@@ -68,6 +68,7 @@
 #define EDGE_LBL_HPC			"hpc"
 #define EDGE_LBL_GFX			"gfx"
 #define EDGE_LBL_HUB			"hub"		/* For SN0 */
+#define EDGE_LBL_ICE			"ice"		/* For TIO */
 #define EDGE_LBL_HW			"hw"
 #define EDGE_LBL_SYNERGY		"synergy"	/* For SNIA only */
 #define EDGE_LBL_IBUS			"ibus"		/* For EVEREST */
@@ -75,6 +76,7 @@
 #define EDGE_LBL_IO			"io"
 #define EDGE_LBL_IO4			"io4"		/* For EVEREST */
 #define EDGE_LBL_IOC3			"ioc3"
+#define EDGE_LBL_IOC4			"ioc4"
 #define EDGE_LBL_LUN                    "lun"
 #define EDGE_LBL_LINUX                  "linux"
 #define EDGE_LBL_LINUX_BUS              EDGE_LBL_LINUX "/bus/pci-x"
@@ -93,6 +95,9 @@
 #define EDGE_LBL_PCIX			"pci-x"
 #define EDGE_LBL_PCIX_0			EDGE_LBL_PCIX "/0"
 #define EDGE_LBL_PCIX_1			EDGE_LBL_PCIX "/1"
+#define EDGE_LBL_AGP			"agp"
+#define EDGE_LBL_AGP_0			EDGE_LBL_AGP "/0"
+#define EDGE_LBL_AGP_1			EDGE_LBL_AGP "/1"
 #define EDGE_LBL_PORT			"port"
 #define EDGE_LBL_PROM			"prom"
 #define EDGE_LBL_RACK			"rack"
@@ -112,6 +117,7 @@
 #define	EDGE_LBL_XIO			"xio"
 #define EDGE_LBL_XSWITCH		".xswitch"
 #define EDGE_LBL_XTALK			"xtalk"
+#define EDGE_LBL_CORETALK		"coretalk"
 #define EDGE_LBL_XWIDGET		"xwidget"
 #define EDGE_LBL_ELSC			"elsc"
 #define EDGE_LBL_L1			"L1"
@@ -129,6 +135,7 @@
 #define EDGE_LBL_PBRICK			"Pbrick"
 #define EDGE_LBL_PEBRICK		"PEbrick"
 #define EDGE_LBL_PXBRICK		"PXbrick"
+#define EDGE_LBL_OPUSBRICK		"onboardio"
 #define EDGE_LBL_IXBRICK		"IXbrick"
 #define EDGE_LBL_IBRICK			"Ibrick"
 #define EDGE_LBL_XBRICK			"Xbrick"
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/klconfig.h linux-2.4.23-pre4/include/asm-ia64/sn/klconfig.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/klconfig.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/klconfig.h	2003-09-12 12:44:40.000000000 -0700
@@ -346,6 +346,7 @@
 
 #define KLTYPE_WEIRDCPU (KLCLASS_CPU | 0x0)
 #define KLTYPE_SNIA	(KLCLASS_CPU | 0x1)
+#define KLTYPE_TIO	(KLCLASS_CPU | 0x2)
 
 #define KLTYPE_WEIRDIO	(KLCLASS_IOBRICK  | 0x0)
 #define KLTYPE_BASEIO	(KLCLASS_IO  | 0x1) /* IOC3, SuperIO, Bridge, SCSI */
@@ -393,6 +394,7 @@
 #define KLTYPE_PXBRICK		(KLCLASS_IOBRICK | 0x6)
 #define KLTYPE_IXBRICK		(KLCLASS_IOBRICK | 0x7)
 #define KLTYPE_CGBRICK		(KLCLASS_IOBRICK | 0x8)
+#define KLTYPE_OPUSBRICK	(KLCLASS_IOBRICK | 0x9)
 
 
 #define KLTYPE_PBRICK_BRIDGE	KLTYPE_PBRICK
@@ -576,6 +578,13 @@
 #define KLSTRUCT_PEBRICK	38
 #define KLSTRUCT_GIGE           39
 #define KLSTRUCT_IDE		40
+#define KLSTRUCT_IOC4		41
+#define KLSTRUCT_IOC4UART	42
+#define KLSTRUCT_IOC4_TTY	43
+#define KLSTRUCT_IOC4PCKM	44
+#define KLSTRUCT_IOC4MS		45
+#define KLSTRUCT_IOC4_ATA	46
+#define KLSTRUCT_PCIGFX		47
 
 /*
  * These are the indices of various components within a lboard structure.
@@ -846,6 +855,10 @@
 	unsigned long	pad;
 } klenetdev_t ;
 
+typedef struct klpcigfx_s {                          /* PCI GFX */
+        klinfo_t        gfx_info ;
+} klpcigfx_t ;
+
 typedef struct klkbddev_s {                          /* KBD device */
 	klinfo_t 	kbddev_info ;
 	struct keyboard_data *kbddev_cfg ; /* driver fills up this */
@@ -976,7 +989,6 @@
 extern int	config_find_xbow(nasid_t, lboard_t **, klxbow_t**);
 extern int 	update_klcfg_cpuinfo(nasid_t, int);
 extern void 	board_to_path(lboard_t *brd, char *path);
-extern moduleid_t get_module_id(nasid_t nasid);
 extern void 	nic_name_convert(char *old_name, char *new_name);
 extern int 	module_brds(nasid_t nasid, lboard_t **module_brds, int n);
 extern lboard_t *brd_from_key(uint64_t key);
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/ksys/l1.h linux-2.4.23-pre4/include/asm-ia64/sn/ksys/l1.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/ksys/l1.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/ksys/l1.h	2003-09-12 12:44:40.000000000 -0700
@@ -104,17 +104,23 @@
 					   command string */
 
 /* brick type response codes */
+#define L1_BRICKTYPE_PX         0x23            /* # */
+#define L1_BRICKTYPE_PE         0x25            /* % */
+#define L1_BRICKTYPE_N_p0       0x26            /* & */
 #define L1_BRICKTYPE_IP45       0x34            /* 4 */
-#define L1_BRICKTYPE_C          0x43            /* C */
-#define L1_BRICKTYPE_I          0x49            /* I */
-#define L1_BRICKTYPE_P          0x50            /* P */
-#define L1_BRICKTYPE_R          0x52            /* R */
-#define L1_BRICKTYPE_X          0x58            /* X */
-#define L1_BRICKTYPE_X2         0x59            /* Y */
-#define L1_BRICKTYPE_N          0x4e            /* N */
-#define L1_BRICKTYPE_PE		0x25		/* % */
-#define L1_BRICKTYPE_PX		0x23		/* # */
-#define L1_BRICKTYPE_IX		0x3d		/* = */
+#define L1_BRICKTYPE_IP41       0x35            /* 5 */
+#define L1_BRICKTYPE_TWISTER    0x36            /* 6 */ /* IP53 & ROUTER */
+#define L1_BRICKTYPE_IX         0x3d            /* = */
+#define L1_BRICKTYPE_IP34       0x61            /* a */
+#define L1_BRICKTYPE_C          0x63            /* c */
+#define L1_BRICKTYPE_I          0x69            /* i */
+#define L1_BRICKTYPE_N          0x6e            /* n */
+#define L1_BRICKTYPE_OPUS       0x6f		/* o */
+#define L1_BRICKTYPE_P          0x70            /* p */
+#define L1_BRICKTYPE_R          0x72            /* r */
+#define L1_BRICKTYPE_CHI_CG     0x76            /* v */
+#define L1_BRICKTYPE_X          0x78            /* x */
+#define L1_BRICKTYPE_X2         0x79            /* y */
 
 /* EEPROM codes (for the "read EEPROM" request) */
 /* c brick */
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/module.h linux-2.4.23-pre4/include/asm-ia64/sn/module.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/module.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/module.h	2003-09-12 12:44:40.000000000 -0700
@@ -138,6 +138,8 @@
 #define MODULE_PEBRICK          8
 #define MODULE_PXBRICK          9
 #define MODULE_IXBRICK          10
+#define MODULE_CGBRICK		11
+#define MODULE_OPUSBRICK        12
 
 /*
  * Moduleid_t comparison macros
@@ -155,12 +157,13 @@
     spinlock_t		lock;		/* Lock for this structure	   */
 
     /* List of nodes in this module */
-    cnodeid_t		nodes[MODULE_MAX_NODES];
-    geoid_t		geoid[MODULE_MAX_NODES];
+    cnodeid_t		nodes[MAX_SLABS + 1];
+    geoid_t		geoid[MAX_SLABS + 1];
     struct {
-		char	moduleid[8];
-    } io[MODULE_MAX_NODES];
-    int			nodecnt;	/* Number of nodes in array        */
+		char	 moduleid[8];
+		uint64_t iobrick_type;
+    } io[MAX_SLABS + 1];
+
     /* Fields for Module System Controller */
     int			mesgpend;	/* Message pending                 */
     int			shutdown;	/* Shutdown in progress            */
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/nodepda.h linux-2.4.23-pre4/include/asm-ia64/sn/nodepda.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/nodepda.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/nodepda.h	2003-09-12 12:44:40.000000000 -0700
@@ -65,6 +65,8 @@
 	nodepda_router_info_t	**npda_rip_last;
 
 
+	spinlock_t		bist_lock;
+
 	/*
 	 * The BTEs on this node are shared by the local cpus
 	 */
@@ -127,8 +129,7 @@
  * Check if given a compact node id the corresponding node has all the
  * cpus disabled. 
  */
-#define is_headless_node(cnode)		((cnode == CNODEID_NONE) ||			\
-					 (node_data(cnode)->active_cpu_count == 0))
+#define is_headless_node(cnode)	(!test_bit(cnode, &node_has_active_cpus))
 
 /*
  * Check if given a node vertex handle the corresponding node has all the
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/pci/bridge.h linux-2.4.23-pre4/include/asm-ia64/sn/pci/bridge.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/pci/bridge.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/pci/bridge.h	2003-09-12 12:44:40.000000000 -0700
@@ -34,20 +34,19 @@
  * For a detailed PIC register layout see pic.h.
  */
 
+#ifdef __KERNEL__
 #include <linux/config.h>
 #include <asm/sn/xtalk/xwidget.h>
 #include <asm/sn/pci/pic.h>
-
-extern int io_get_sh_swapper(nasid_t);
-#define BRIDGE_REG_GET32(reg) \
-                __swab32( *(volatile uint32_t *) (((uint64_t)reg)^4) )
-
-#define BRIDGE_REG_SET32(reg) \
-                *(volatile uint32_t *) (((uint64_t)reg)^4)
+#else
+#include <linux/config.h>
+#include <xtalk/xwidget.h>
+#include <pci/pic.h>
+#endif
 
 /* I/O page size */
 
-#if _PAGESZ == 4096
+#if PAGE_SIZE == 4096
 #define IOPFNSHIFT		12	/* 4K per mapped page */
 #else
 #define IOPFNSHIFT		14	/* 16K per mapped page */
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/pci/pci_bus_cvlink.h linux-2.4.23-pre4/include/asm-ia64/sn/pci/pci_bus_cvlink.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/pci/pci_bus_cvlink.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/pci/pci_bus_cvlink.h	2003-09-12 12:44:40.000000000 -0700
@@ -56,8 +56,6 @@
         vertex_hdl_t  vhdl;
 	int		isa64;
 	int		isPIC;
-	volatile unsigned int *dma_buf_sync;
-	volatile unsigned int *xbow_buf_sync;
 };
 
 struct sn_dma_maps_s{
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/pci/pciba.h linux-2.4.23-pre4/include/asm-ia64/sn/pci/pciba.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/pci/pciba.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/pci/pciba.h	2003-09-12 12:44:40.000000000 -0700
@@ -14,14 +14,6 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 
-/* for application compatibility with IRIX (why do I bother?) */
-
-#ifndef __KERNEL__
-typedef u_int8_t uint8_t;
-typedef u_int16_t uint16_t;
-typedef u_int32_t uint32_t;
-#endif
-
 #define PCI_CFG_VENDOR_ID	PCI_VENDOR_ID
 #define PCI_CFG_COMMAND		PCI_COMMAND
 #define PCI_CFG_REV_ID		PCI_REVISION_ID
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/pci/pcibr.h linux-2.4.23-pre4/include/asm-ia64/sn/pci/pcibr.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/pci/pcibr.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/pci/pcibr.h	2003-09-12 12:44:40.000000000 -0700
@@ -194,15 +194,10 @@
 
 extern int		pcibr_reset(vertex_hdl_t dev);
 
-extern int              pcibr_write_gather_flush(vertex_hdl_t dev);
-
 extern pciio_endian_t	pcibr_endian_set(vertex_hdl_t dev,
 					 pciio_endian_t device_end,
 					 pciio_endian_t desired_end);
 
-extern pciio_priority_t pcibr_priority_set(vertex_hdl_t dev,
-					   pciio_priority_t device_prio);
-
 extern uint64_t		pcibr_config_get(vertex_hdl_t conn,
 					 unsigned reg,
 					 unsigned size);
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/pci/pcibr_private.h linux-2.4.23-pre4/include/asm-ia64/sn/pci/pcibr_private.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/pci/pcibr_private.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/pci/pcibr_private.h	2003-09-12 12:44:40.000000000 -0700
@@ -277,9 +277,9 @@
 #define PCIBR_BUS_IO_MAX       0x0FFFFFFF
 #define PCIBR_BUS_IO_PAGE      0x100000
 
-#define PCIBR_BUS_SWIN_BASE    _PAGESZ
+#define PCIBR_BUS_SWIN_BASE    PAGE_SIZE
 #define PCIBR_BUS_SWIN_MAX     0x000FFFFF
-#define PCIBR_BUS_SWIN_PAGE    _PAGESZ
+#define PCIBR_BUS_SWIN_PAGE    PAGE_SIZE
 
 #define PCIBR_BUS_MEM_BASE     0x200000
 #define PCIBR_BUS_MEM_MAX      0x3FFFFFFF
@@ -307,7 +307,7 @@
  */
 #define PV854697 (~0)     /* PIC: write 64bit regs as 64bits. permanent */
 #define PV854827 (~0)     /* PIC: fake widget 0xf presence bit. permanent */
-#define PV855271 (~0)     /* PIC: use virt chan iff 64-bit device. permanent */
+#define PV855271 (1 << 1) /* PIC: PIC: use virt chan iff 64-bit device. */
 #define PV855272 (1 << 1) /* PIC: runaway interrupt WAR */
 #define PV856155 (1 << 1) /* PIC: arbitration WAR */
 #define PV856864 (1 << 1) /* PIC: lower timeout to free TNUMs quicker */
@@ -663,8 +663,8 @@
 /*
  * mem alloc/free macros
  */
-#define NEWAf(ptr,n,f)	(ptr = snia_kmem_zalloc((n)*sizeof (*(ptr)), (f&PCIIO_NOSLEEP)?KM_NOSLEEP:KM_SLEEP))
-#define NEWA(ptr,n)	(ptr = snia_kmem_zalloc((n)*sizeof (*(ptr)), KM_SLEEP))
+#define NEWAf(ptr,n,f)	(ptr = snia_kmem_zalloc((n)*sizeof (*(ptr))))
+#define NEWA(ptr,n)	(ptr = snia_kmem_zalloc((n)*sizeof (*(ptr))))
 #define DELA(ptr,n)	(kfree(ptr))
 
 #define NEWf(ptr,f)	NEWAf(ptr,1,f)
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/pci/pciio.h linux-2.4.23-pre4/include/asm-ia64/sn/pci/pciio.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/pci/pciio.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/pci/pciio.h	2003-09-12 12:44:40.000000000 -0700
@@ -13,17 +13,30 @@
  * pciio.h -- platform-independent PCI interface
  */
 
+#ifdef __KERNEL__
 #include <linux/config.h>
 #include <linux/ioport.h>
 #include <asm/sn/ioerror.h>
 #include <asm/sn/driver.h>
+#include <asm/sn/invent.h>
 #include <asm/sn/hcl.h>
-
+#else
+#include <linux/config.h>
+#include <linux/ioport.h>
+#include <ioerror.h>
+#include <driver.h>
+#include <hcl.h>
+#endif
 
 #ifndef __ASSEMBLY__
 
+#ifdef __KERNEL__
 #include <asm/sn/dmamap.h>
 #include <asm/sn/alenlist.h>
+#else
+#include <dmamap.h>
+#include <alenlist.h>
+#endif
 
 typedef int pciio_vendor_id_t;
 
@@ -188,20 +201,6 @@
 } pciio_endian_t;
 
 /*
- * Interface to set PCI arbitration priority for devices that require
- * realtime characteristics.  pciio_priority_set is used to switch a
- * device between the PCI high-priority arbitration ring and the low
- * priority arbitration ring.
- *
- * (Note: this is strictly for the PCI arbitrary priority.  It has
- * no direct relationship to GBR.)
- */
-typedef enum pciio_priority_e {
-    PCI_PRIO_LOW,
-    PCI_PRIO_HIGH
-} pciio_priority_t;
-
-/*
  * handles of various sorts
  */
 typedef struct pciio_piomap_s *pciio_piomap_t;
@@ -396,18 +395,11 @@
 typedef int	
 pciio_reset_f		(vertex_hdl_t conn);	/* pci connection point */
 
-typedef int
-pciio_write_gather_flush_f (vertex_hdl_t dev);    /* Device flushing buffers */
-
 typedef pciio_endian_t			/* actual endianness */
 pciio_endian_set_f      (vertex_hdl_t dev,	/* specify endianness for this device */
 			 pciio_endian_t device_end,	/* endianness of device */
 			 pciio_endian_t desired_end);	/* desired endianness */
 
-typedef pciio_priority_t
-pciio_priority_set_f    (vertex_hdl_t pcicard,
-			 pciio_priority_t device_prio);
-
 typedef uint64_t
 pciio_config_get_f	(vertex_hdl_t conn,	/* pci connection point */
 			 unsigned reg,		/* register byte offset */
@@ -479,9 +471,7 @@
     pciio_provider_startup_f *provider_startup;
     pciio_provider_shutdown_f *provider_shutdown;
     pciio_reset_f	   *reset;
-    pciio_write_gather_flush_f *write_gather_flush;
     pciio_endian_set_f     *endian_set;
-    pciio_priority_set_f   *priority_set;
     pciio_config_get_f	   *config_get;
     pciio_config_set_f	   *config_set;
 
@@ -521,13 +511,9 @@
 extern pciio_provider_startup_f pciio_provider_startup;
 extern pciio_provider_shutdown_f pciio_provider_shutdown;
 extern pciio_reset_f pciio_reset;
-extern pciio_write_gather_flush_f pciio_write_gather_flush;
 extern pciio_endian_set_f pciio_endian_set;
-extern pciio_priority_set_f pciio_priority_set;
 extern pciio_config_get_f pciio_config_get;
 extern pciio_config_set_f pciio_config_set;
-extern pciio_error_devenable_f pciio_error_devenable;
-extern pciio_error_extract_f pciio_error_extract;
 
 /* Widgetdev in the IOERROR structure is encoded as follows.
  *	+---------------------------+
@@ -695,5 +681,63 @@
 extern int              pciio_error_handler(vertex_hdl_t, int, ioerror_mode_t, ioerror_t *);
 extern int		pciio_dma_enabled(vertex_hdl_t);
 
+/**
+ * sn_pci_set_vchan - Set the requested Virtual Channel bits into the mapped DMA 
+ *                    address.
+ * @pci_dev: pci device pointer
+ * @addr: mapped dma address
+ * @vchan: Virtual Channel to use 0 or 1.
+ *
+ * Set the Virtual Channel bit in the mapped dma address.
+ */
+static inline int
+sn_pci_set_vchan(struct pci_dev *pci_dev,
+	dma_addr_t *addr,
+	int vchan)
+{
+
+	if (vchan > 1) {
+		return -1;
+	}
+
+	if (!(*addr >> 32))	/* Using a mask here would be cleaner */
+		return 0;	/* but this generates better code */
+
+	if (vchan == 1) {
+		/* Set Bit 57 */
+		*addr |= (1UL << 57);
+	} else {
+		/* Clear Bit 57 */
+		*addr &= ~(1UL << 57);
+	}
+
+	return 0;
+}
+
 #endif				/* C or C++ */
+
+
+/*
+ * Prototypes
+ */
+
+int snia_badaddr_val(volatile void *addr, int len, volatile void *ptr);
+nasid_t snia_get_console_nasid(void);
+nasid_t snia_get_master_baseio_nasid(void);
+void snia_ioerror_dump(char *name, int error_code, int error_mode, ioerror_t *ioerror);
+int snia_pcibr_rrb_alloc(struct pci_dev *pci_dev, int *count_vchan0, int *count_vchan1);
+pciio_endian_t snia_pciio_endian_set(struct pci_dev *pci_dev,
+	pciio_endian_t device_end, pciio_endian_t desired_end);
+iopaddr_t snia_pciio_dmatrans_addr(struct pci_dev *pci_dev, device_desc_t dev_desc,
+	paddr_t paddr, size_t byte_count, unsigned flags);
+pciio_dmamap_t snia_pciio_dmamap_alloc(struct pci_dev *pci_dev,
+	device_desc_t dev_desc, size_t byte_count_max, unsigned flags);
+void snia_pciio_dmamap_free(pciio_dmamap_t pciio_dmamap);
+iopaddr_t snia_pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap, paddr_t paddr,
+	size_t byte_count);
+void snia_pciio_dmamap_done(pciio_dmamap_t pciio_dmamap);
+void *snia_kmem_zalloc(size_t size);
+void snia_kmem_free(void *ptr, size_t size);
+void *snia_kmem_alloc_node(register size_t size, cnodeid_t node);
+
 #endif				/* _ASM_SN_PCI_PCIIO_H */
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/pci/pic.h linux-2.4.23-pre4/include/asm-ia64/sn/pci/pic.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/pci/pic.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/pci/pic.h	2003-09-12 12:44:40.000000000 -0700
@@ -72,9 +72,6 @@
 extern "C" {
 #endif
 
-// #include <sys/types.h>
-#include <asm/sn/pci/pciio.h>
-
 
 /*********************************************************************
  *    bus provider function table
@@ -88,7 +85,13 @@
  *	pcibr, we can go directly to this ops table.
  */
 
+#ifdef __KERNEL__
+#include <linux/config.h>
+#include <asm/sn/pci/pciio.h>
 extern pciio_provider_t pci_pic_provider;
+#else
+#include <linux/config.h>
+#endif
 
 
 /*********************************************************************
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/serialio.h linux-2.4.23-pre4/include/asm-ia64/sn/serialio.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/serialio.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/include/asm-ia64/sn/serialio.h	2003-09-12 12:44:40.000000000 -0700
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it 
+ * under the terms of version 2 of the GNU General Public License 
+ * as published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * 
+ * Further, this software is distributed without any warranty that it is 
+ * free of the rightful claim of any third person regarding infringement 
+ * or the like.  Any license provided herein, whether implied or 
+ * otherwise, applies only to this software file.  Patent licenses, if 
+ * any, provided herein do not apply to combinations of this program with 
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program; if not, write the Free Software 
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ */
+
+#ifndef _ASM_IA64_SN_SERIALIO_H
+#define _ASM_IA64_SN_SERIALIO_H
+
+/*
+ * Definitions for the modular serial i/o driver.
+ *
+ * The modular serial i/o driver is a driver which has the hardware
+ * dependent and hardware independent parts separated into separate
+ * modules. The upper half is responsible for all hardware independent
+ * operations, specifically the interface to the kernel. An upper half
+ * may implement a streams interface, character interface, or whatever
+ * interface it wishes to the kernel. The same upper half may access any
+ * physical hardware through a set of standardized entry points into the
+ * lower level, which deals directly with the hardware. Whereas a
+ * separate upper layer exists for each kernel interface type (streams,
+ * character, polling etc), a separate lower level exists for each
+ * hardware type supported. Any upper and lower layer pair may be
+ * connected to form a complete driver. This file defines the interface
+ * between the two
+ */
+
+/* Definitions needed per port by both layers. Each lower layer
+ * declares a set of per-port private data areas describing each
+ * physical port, and by definition the first member of that private
+ * data is the following structure. Thus a pointer to the lower
+ * layer's private data is interchangeable with a pointer to the
+ * common private data, and the upper layer does not allocate anything
+ * so it does need to know anything about the physical configuration
+ * of the machine. This structure may also contain any hardware
+ * independent info that must be persistent across device closes.
+ */
+typedef struct sioport {
+    /* calling vectors */
+    struct serial_calldown	*sio_calldown;
+    struct serial_callup	*sio_callup;
+
+    void	*sio_upper;	/* upper layer's private data area */
+
+    vertex_hdl_t sio_vhdl;	/* vertex handle of the hardware independent
+				 * portion of this port (e.g. tty/1 without
+				 * the d,m,f, etc)
+				 */
+    spinlock_t  sio_lock;
+} sioport_t;
+
+/* bits for sio_flags */
+#define SIO_HWGRAPH_INITED	0x1
+#define SIO_SPINLOCK_HELD	0x2
+#define SIO_MUTEX_HELD		0x4
+#define SIO_LOCKS_MASK (SIO_SPINLOCK_HELD | SIO_MUTEX_HELD)
+
+#if DEBUG
+/* bits for sio_lockcalls, one per downcall except du_write which is
+ * not called by an upper layer.
+ */
+#define L_OPEN		0x0001
+#define L_CONFIG	0x0002
+#define L_ENABLE_HFC	0x0004
+#define L_SET_EXTCLK	0x0008
+#define L_WRITE		0x0010
+#define L_BREAK		0x0020
+#define L_READ		0x0040
+#define L_NOTIFICATION	0x0080
+#define L_RX_TIMEOUT	0x0100
+#define L_SET_DTR	0x0200
+#define L_SET_RTS	0x0400
+#define L_QUERY_DCD	0x0800
+#define L_QUERY_CTS	0x1000
+#define L_SET_PROTOCOL	0x2000
+#define L_ENABLE_TX	0x4000
+
+#define L_LOCK_ALL	(~0)
+
+/* debug lock assertion: each lower layer entry point does an
+ * assertion with the following macro, passing in the port passed to
+ * the entry point and the bit corresponding to which entry point it
+ * is. If the upper layer has turned on the bit for that entry point,
+ * sio_port_islocked is called, thus an upper layer may specify that
+ * it is ok for a particular downcall to be made without the port lock
+ * held.
+ */
+#define L_LOCKED(port, flag) (((port)->sio_lockcalls & (flag)) == 0 || \
+			      sio_port_islocked(port))
+#endif
+
+/* flags for next_char_state */
+#define NCS_BREAK 1
+#define NCS_PARITY 2
+#define NCS_FRAMING 4
+#define NCS_OVERRUN 8
+
+/* protocol types for DOWN_SET_PROTOCOL */
+enum sio_proto {
+    PROTO_RS232,
+    PROTO_RS422
+};
+
+/* calldown vector. This is a set of entry points into a lower layer
+ * module, providing black-box access to the hardware by the upper
+ * layer
+ */
+struct serial_calldown {
+
+    /* hardware configuration */
+    int (*down_open)		(sioport_t *port);
+    int (*down_config)		(sioport_t *port, int baud, int byte_size,
+				 int stop_bits, int parenb, int parodd);
+    int (*down_enable_hfc)	(sioport_t *port, int enable);
+    int (*down_set_extclk)	(sioport_t *port, int clock_factor);
+
+    /* data transmission */
+    int (*down_write)		(sioport_t *port, char *buf, int len);
+    int (*down_du_write)	(sioport_t *port, char *buf, int len);
+    void (*down_du_flush)	(sioport_t *port);
+    int (*down_break)		(sioport_t *port, int brk);
+    int (*down_enable_tx)	(sioport_t *port, int enb);
+
+    /* data reception */
+    int (*down_read)		(sioport_t *port, char *buf, int len);
+    
+    /* event notification */
+    int (*down_notification)	(sioport_t *port, int mask, int on);
+    int (*down_rx_timeout)	(sioport_t *port, int timeout);
+
+    /* modem control */
+    int (*down_set_DTR)		(sioport_t *port, int dtr);
+    int (*down_set_RTS)		(sioport_t *port, int rts);
+    int (*down_query_DCD)	(sioport_t *port);
+    int (*down_query_CTS)	(sioport_t *port);
+
+    /* transmission protocol */
+    int (*down_set_protocol)	(sioport_t *port, enum sio_proto protocol);
+
+    /* memory mapped user driver support */
+    int (*down_mapid)		(sioport_t *port, void *arg);
+    int (*down_map)		(sioport_t *port, uint64_t *vt, off_t off);
+    void (*down_unmap)		(sioport_t *port);
+    int (*down_set_sscr)	(sioport_t *port, int arg, int flag);
+};
+
+/*
+ * Macros used by the upper layer to access the lower layer. Unless
+ * otherwise noted, all integer functions should return 0 on success
+ * or 1 if the hardware does not support the requested operation. In
+ * the case of non-support, the upper layer may work around the problem
+ * where appropriate or just notify the user.
+ * For hardware which supports detaching, these functions should
+ * return -1 if the hardware is no longer present.
+ */
+
+/* open a device. Do whatever initialization/resetting necessary */
+#define DOWN_OPEN(p) \
+    ((p)->sio_calldown->down_open(p))
+
+/* configure the hardware with the given baud rate, number of stop
+ * bits, byte size and parity
+ */
+#define DOWN_CONFIG(p, a, b, c, d, e) \
+    ((p)->sio_calldown->down_config(p, a, b, c, d, e))
+
+/* Enable hardware flow control. If the hardware does not support
+ * this, the upper layer will emulate HFC by manipulating RTS and CTS
+ */
+#define DOWN_ENABLE_HFC(p, enb) \
+    ((p)->sio_calldown->down_enable_hfc(p, enb))
+
+/* Set external clock to the given clock factor. If cf is zero,
+ * internal clock is used. If cf is non-zero external clock is used
+ * and the clock is cf times the baud.
+ */
+#define DOWN_SET_EXTCLK(p, cf) \
+    ((p)->sio_calldown->down_set_extclk(p, cf))
+
+/* Write bytes to the device. The number of bytes actually written is
+ * returned. The upper layer will continue to call this function until
+ * it has no more data to send or until 0 is returned, indicating that
+ * no more bytes may be sent until some have drained.
+ */
+#define DOWN_WRITE(p, buf, len) \
+    ((p)->sio_calldown->down_write(p, buf, len))
+
+/* Same as DOWN_WRITE, but called only from synchronous du output
+ * routines. Allows lower layer the option of implementing kernel
+ * printfs differently than ordinary console output.
+ */
+#define DOWN_DU_WRITE(p, buf, len) \
+    ((p)->sio_calldown->down_du_write(p, buf, len))
+
+/* Flushes previous down_du_write() calls.  Needed on serial controllers
+ * that can heavily buffer output like IOC3 for conbuf_flush().
+ */
+#define DOWN_DU_FLUSH(p) \
+     ((p)->sio_calldown->down_du_flush(p))
+
+/* Set the output break condition high or low */
+#define DOWN_BREAK(p, brk) \
+    ((p)->sio_calldown->down_break(p, brk))
+
+/* Enable/disable TX for soft flow control */
+#define DOWN_ENABLE_TX(p) \
+    ((p)->sio_calldown->down_enable_tx(p, 1))
+#define DOWN_DISABLE_TX(p) \
+    ((p)->sio_calldown->down_enable_tx(p, 0))
+
+/* Read bytes from the device. The number of bytes actually read is
+ * returned. All bytes returned by a single call have the same error
+ * status. Thus if the device has 10 bytes queued for input and byte 5
+ * has a parity error, the first call to DOWN_READ will return bytes 0-4
+ * only. A subsequent call to DOWN_READ will first cause a call to
+ * UP_PARITY_ERROR to notify the upper layer that the next byte has an
+ * error, and then the call to DOWN_READ returns byte 5 alone. A
+ * subsequent call to DOWN_READ returns bytes 6-9. The upper layer
+ * continues to call DOWN_READ until 0 is returned, or until it runs out
+ * of buffer space to receive the chars.
+ */
+#define DOWN_READ(p, buf, len) \
+    ((p)->sio_calldown->down_read(p, buf, len))
+
+/* Turn on/off event notification for the specified events. Notification
+ * status is unchanged for those events not specified.
+ */
+#define DOWN_NOTIFICATION(p, mask, on) \
+    ((p)->sio_calldown->down_notification(p, mask, on))
+
+/* Notification types. 1 per upcall. The upper layer can specify
+ * exactly which upcalls it wishes to receive. UP_DETACH is mandatory
+ * when applicable and cannot be enabled/disabled.
+ */
+#define N_DATA_READY	0x01
+#define N_OUTPUT_LOWAT	0x02
+#define N_BREAK		0x04
+#define N_PARITY_ERROR	0x08
+#define N_FRAMING_ERROR	0x10
+#define N_OVERRUN_ERROR	0x20
+#define N_DDCD		0x40
+#define N_DCTS		0x80
+
+#define N_ALL_INPUT	(N_DATA_READY | N_BREAK |			\
+			 N_PARITY_ERROR | N_FRAMING_ERROR |		\
+			 N_OVERRUN_ERROR | N_DDCD | N_DCTS)
+
+#define N_ALL_OUTPUT	N_OUTPUT_LOWAT
+
+#define N_ALL_ERRORS	(N_PARITY_ERROR | N_FRAMING_ERROR | N_OVERRUN_ERROR)
+
+#define N_ALL		(N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK |	\
+			 N_PARITY_ERROR | N_FRAMING_ERROR |		\
+			 N_OVERRUN_ERROR | N_DDCD | N_DCTS)
+
+/* Instruct the lower layer that the upper layer would like to be
+ * notified every t ticks when data is being received. If data is
+ * streaming in, the lower layer should buffer enough data that
+ * notification is not required more often than requested, and set a
+ * timeout so that notification does not occur less often than
+ * requested. If the lower layer does not support such operations, it
+ * should return 1, indicating that the upper layer should emulate these
+ * functions in software.
+ */
+#define DOWN_RX_TIMEOUT(p, t) \
+    ((p)->sio_calldown->down_rx_timeout(p, t))
+
+/* Set the output value of DTR */
+#define DOWN_SET_DTR(p, dtr) \
+    ((p)->sio_calldown->down_set_DTR(p, dtr))
+
+/* Set the output value of RTS */
+#define DOWN_SET_RTS(p, rts) \
+    ((p)->sio_calldown->down_set_RTS(p, rts))
+
+/* Query current input value of DCD */
+#define DOWN_QUERY_DCD(p) \
+    ((p)->sio_calldown->down_query_DCD(p))
+
+/* Query current input value of CTS */
+#define DOWN_QUERY_CTS(p) \
+    ((p)->sio_calldown->down_query_CTS(p))
+
+/* Set transmission protocol */
+#define DOWN_SET_PROTOCOL(p, proto) \
+    ((p)->sio_calldown->down_set_protocol(p, proto))
+
+/* Query mapped interface type */
+#define DOWN_GET_MAPID(p, arg) \
+    ((p)->sio_calldown->down_mapid(p, arg))
+
+/* Perform mapping to user address space */
+#define DOWN_MAP(p, vt, off) \
+    ((p)->sio_calldown->down_map(p, vt, off))
+
+/* Cleanup after mapped port is closed */
+#define DOWN_UNMAP(p) \
+    ((p)->sio_calldown->down_unmap(p))
+
+/* Set/Reset ioc3 sscr register */
+#define DOWN_SET_SSCR(p, arg, flag) \
+    ((p)->sio_calldown->down_set_sscr(p, arg, flag))
+
+
+/* The callup struct. This is a set of entry points providing
+ * black-box access to the upper level kernel interface by the
+ * hardware handling code. These entry points are used for event
+ * notification 
+ */
+struct serial_callup {
+    void (*up_data_ready)	(sioport_t *port);
+    void (*up_output_lowat)	(sioport_t *port);
+    void (*up_ncs)		(sioport_t *port, int ncs);
+    void (*up_dDCD)		(sioport_t *port, int dcd);
+    void (*up_dCTS)		(sioport_t *port, int cts);
+    void (*up_detach)		(sioport_t *port);
+};
+
+/*
+ * Macros used by the lower layer to access the upper layer for event
+ * notificaiton. These functions are generally called in response to
+ * an interrupt. Since the port lock may be released across UP calls,
+ * we must check the callup vector each time. However since the port
+ * lock is held during DOWN calls (from which these UP calls are made)
+ * there is no danger of the sio_callup vector being cleared between
+ * where it is checked and where it is used in the macro
+ */
+
+/* Notify the upper layer that there are input bytes available and
+ * DOWN_READ may now be called
+ */
+#define UP_DATA_READY(p) \
+    ((p)->sio_callup ? (p)->sio_callup->up_data_ready(p):(void)0)
+
+/* Notify the upper layer that the lower layer has freed up some
+ * output buffer space and DOWN_WRITE may now be called
+ */
+#define UP_OUTPUT_LOWAT(p) \
+    ((p)->sio_callup ? (p)->sio_callup->up_output_lowat(p):(void)0)
+
+/* Notify the upper layer that the next char returned by DOWN_READ
+ * has the indicated special status. (see NCS_* above)
+ */
+#define UP_NCS(p, ncs) \
+    ((p)->sio_callup ? (p)->sio_callup->up_ncs(p, ncs):(void)0)
+
+/* Notify the upper layer of the new DCD input value */
+#define UP_DDCD(p, dcd) \
+    ((p)->sio_callup ? (p)->sio_callup->up_dDCD(p, dcd):(void)0)
+
+/* Notify the upper layer of the new CTS input value */
+#define UP_DCTS(p, cts) \
+    ((p)->sio_callup ? (p)->sio_callup->up_dCTS(p, cts):(void)0)
+
+/* notify the upper layer that the lower layer hardware has been detached 
+ * Since the port lock is NOT held when this macro is executed, we must
+ * guard against the sio_callup vector being cleared between when we check
+ * it and when we make the upcall, so we use a local copy.
+ */
+#define UP_DETACH(p) \
+{ \
+    struct serial_callup *up; \
+    if ((up = (p)->sio_callup)) \
+	up->up_detach(p); \
+}
+
+/* Port locking protocol:
+ * Any time a DOWN call is made into one of the lower layer entry points,
+ * the corresponding port is already locked and remains locked throughout
+ * that downcall. When a lower layer routine makes an UP call, the port
+ * is assumed to be locked on entry to the upper layer routine, but the
+ * upper layer routine may release and reacquire the lock if it wishes.
+ * Thus the lower layer routine should not rely on the port lock being
+ * held across upcalls. Further, since the port may be disconnected
+ * any time the port lock is not held, an UP call may cause subsequent
+ * UP calls to become noops since the upcall vector will be zeroed when
+ * the port is closed. Thus, any lower layer routine making UP calls must
+ * be prepared to deal with the possibility that any UP calls it makes
+ * are noops.
+ *
+ * The only time a lower layer routine should manipulate the port lock
+ * is the lower layer interrupt handler, which should acquire the lock
+ * during its critical execution.
+ * 
+ * Any function which assumes that the port is or isn't locked should
+ * use the function sio_port_islocked in an ASSERT statement to verify
+ * this assumption
+ */
+
+#if DEBUG
+extern int sio_port_islocked(sioport_t *);
+#endif
+
+#define SIO_LOCK_PORT(port, flags)	spin_lock_irqsave(&port->sio_lock, flags)
+#define SIO_UNLOCK_PORT(port, flags)	spin_unlock_irqrestore(&port->sio_lock, flags)
+
+/* kernel debugger support */
+#ifdef _LANGUAGE_C
+extern int console_is_tport;
+#define CNTRL_A		'\001'
+#if DEBUG
+#ifndef DEBUG_CHAR
+#define DEBUG_CHAR	CNTRL_A
+#endif
+#else
+#define DEBUG_CHAR	CNTRL_A
+#endif
+#endif
+
+
+extern void ioc4_serial_initport(sioport_t *, int);
+
+
+/* flags to notify sio_initport() which type of nodes are
+ * desired for a particular hardware type
+ */
+#define NODE_TYPE_D		0x01 /* standard plain streams interface */
+#define NODE_TYPE_MODEM		0x02 /* modem streams interface */
+#define NODE_TYPE_FLOW_MODEM	0x04 /* modem/flow control streams */
+#define NODE_TYPE_CHAR		0x08 /* character interface */
+#define NODE_TYPE_MIDI		0x10 /* midi interface */
+#define NODE_TYPE_D_RS422	0x20 /* RS422 without flow control */
+#define NODE_TYPE_FLOW_RS422	0x40 /* RS422 with flow control */
+
+#define NODE_TYPE_USER		0x80 /* user mapped interface */
+#define NODE_TYPE_TIMESTAMPED	0x100 /* user mapped interface */
+
+#define NODE_TYPE_ALL_RS232	(NODE_TYPE_D | NODE_TYPE_MODEM | \
+				 NODE_TYPE_FLOW_MODEM | NODE_TYPE_CHAR | \
+				 NODE_TYPE_MIDI | NODE_TYPE_TIMESTAMPED)
+#define NODE_TYPE_ALL_RS422	(NODE_TYPE_D_RS422 | NODE_TYPE_FLOW_RS422 | \
+				 NODE_TYPE_TIMESTAMPED)
+
+/* Flags for devflags field of miditype structure */
+#define MIDIDEV_EXTERNAL 0             /* lower half initializes devflags to this for an external device */
+#define MIDIDEV_INTERNAL 0x2
+
+#define MIDIDEV_UNREGISTERED -1    /* Initialization for portidx field of miditype structure */
+
+typedef struct miditype_s{
+  int devflags;                    /* DEV_EXTERNAL, DEV_INTERNAL */
+  int portidx;  
+  void *midi_upper;                      
+  sioport_t *port;
+} miditype_t;
+
+typedef struct tsiotype_s{
+  void *tsio_upper;                      
+  sioport_t *port;
+  int portidx;
+  int urbidx;
+} tsiotype_t;
+
+#endif /* _ASM_IA64_SN_SERIALIO_H */
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/sgi.h linux-2.4.23-pre4/include/asm-ia64/sn/sgi.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/sgi.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/sgi.h	2003-09-12 12:44:40.000000000 -0700
@@ -7,14 +7,16 @@
  * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
  */
 
+/*
+ * This file is a bit of a dumping ground. A lot of things that don't really
+ * have a home, but which make life easier, end up here.
+ */
 
 #ifndef _ASM_IA64_SN_SGI_H
 #define _ASM_IA64_SN_SGI_H
 
 #include <linux/config.h>
-
 #include <asm/sn/types.h>
-#include <asm/uaccess.h>		/* for copy_??_user */
 #include <linux/mm.h>
 #include <linux/devfs_fs_kernel.h>
 #ifdef CONFIG_HWGFS_FS
@@ -25,14 +27,15 @@
 typedef devfs_handle_t vertex_hdl_t;
 #endif
 
-typedef int64_t  __psint_t;	/* needed by klgraph.c */
-
-typedef enum { B_FALSE, B_TRUE } boolean_t;
+/* Nice general name length that lots of people like to use */
+#ifndef MAXDEVNAME
+#define MAXDEVNAME 256
+#endif
 
 
 /*
-** Possible return values from graph routines.
-*/
+ * Possible return values from graph routines.
+ */
 typedef enum graph_error_e {
 	GRAPH_SUCCESS,		/* 0 */
 	GRAPH_DUP,		/* 1 */
@@ -44,87 +47,9 @@
 	GRAPH_IN_USE		/* 7 */
 } graph_error_t;
 
-#define KM_SLEEP   0x0000
-#define KM_NOSLEEP 0x0001		/* needed by kmem_alloc_node(), kmem_zalloc()
-					 * calls */
-#define VM_NOSLEEP 0x0001		/* needed kmem_alloc_node(), kmem_zalloc_node
-					 * calls */
-#define XG_WIDGET_PART_NUM      0xC102          /* KONA/xt_regs.h     XG_XT_PART_NUM_VALUE */
-
-typedef uint64_t vhandl_t;
-
-
-#define NBPP PAGE_SIZE
-#define _PAGESZ PAGE_SIZE
-
-#ifndef MAXDEVNAME
-#define MAXDEVNAME 256
-#endif
-
-#define HUB_PIO_CONVEYOR 0x1
 #define CNODEID_NONE ((cnodeid_t)-1)
-#define XTALK_PCI_PART_NUM "030-1275-"
-#define kdebug 0
-
-
-#define COPYIN(a, b, c)		copy_from_user(b,a,c)
-#define COPYOUT(a, b, c)	copy_to_user(b,a,c)
-
-#define BZERO(a,b)		memset(a, 0, b)
-
-#define kern_malloc(x)		kmalloc(x, GFP_KERNEL)
-#define kern_free(x)		kfree(x)
-
-typedef cpuid_t cpu_cookie_t;
 #define CPU_NONE		(-1)
 
-/*
- * mutext support mapping
- */
-
-#define mutex_spinlock_init(s)	spin_lock_init(s)
-inline static unsigned long
-mutex_spinlock(spinlock_t *sem) {
-	unsigned long flags = 0;
-//	spin_lock_irqsave(sem, flags);
-	spin_lock(sem);
-	return(flags);
-}
-// #define mutex_spinunlock(s,t)	spin_unlock_irqrestore(s,t)
-#define mutex_spinunlock(s,t)	spin_unlock(s)
-
-
-#define mutex_t			struct semaphore
-#define mutex_init(s)		init_MUTEX(s)
-#define mutex_init_locked(s)	init_MUTEX_LOCKED(s)
-#define mutex_lock(s)		down(s)
-#define mutex_unlock(s)		up(s)
-
-#define io_splock(s)		mutex_spinlock(s)
-#define io_spunlock(s,t)	spin_unlock(s)
-
-#define spin_lock_destroy(s)
-
-#if defined(DISABLE_ASSERT)
-#define ASSERT(expr)
-#define ASSERT_ALWAYS(expr)
-#else
-#define ASSERT(expr)  do {	\
-        if(!(expr)) { \
-		printk( "Assertion [%s] failed! %s:%s(line=%d)\n",\
-			#expr,__FILE__,__FUNCTION__,__LINE__); \
-		panic("Assertion panic\n"); 	\
-        } } while(0)
-
-#define ASSERT_ALWAYS(expr)	do {\
-        if(!(expr)) { \
-		printk( "Assertion [%s] failed! %s:%s(line=%d)\n",\
-			#expr,__FILE__,__FUNCTION__,__LINE__); \
-		panic("Assertion always panic\n"); 	\
-        } } while(0)
-#endif	/* DISABLE_ASSERT */
-
-#define PRINT_PANIC		panic
 
 /* print_register() defs */
 
@@ -151,31 +76,28 @@
 
 extern void print_register(unsigned long long, struct reg_desc *);
 
-/******************************************
- * Definitions that do not exist in linux *
- ******************************************/
-
-#define DELAY(a)
-
-/************************************************
- * Routines redefined to use linux equivalents. *
- ************************************************/
-
-/* #define FIXME(s) printk("FIXME: [ %s ] in %s at %s:%d\n", s, __FUNCTION__, __FILE__, __LINE__) */
-
-#define FIXME(s)
-
-/* move to stubs.c yet */
-#define dev_to_vhdl(dev) 0
-#define get_timestamp() 0
-#define us_delay(a)
-#define v_mapphys(a,b,c) 0    // printk("Fixme: v_mapphys - soft->base 0x%p\n", b);
-#define splhi()  0
-#define splx(s)
-
-extern void * snia_kmem_alloc_node(register size_t, register int, cnodeid_t);
-extern void * snia_kmem_zalloc(size_t, int);
-extern void * snia_kmem_zalloc_node(register size_t, register int, cnodeid_t );
-extern int is_specified(char *);
+
+/*
+ * No code is complete without an Assertion macro
+ */
+
+#if defined(DISABLE_ASSERT)
+#define ASSERT(expr)
+#define ASSERT_ALWAYS(expr)
+#else
+#define ASSERT(expr)  do {	\
+        if(!(expr)) { \
+		printk( "Assertion [%s] failed! %s:%s(line=%d)\n",\
+			#expr,__FILE__,__FUNCTION__,__LINE__); \
+		panic("Assertion panic\n"); 	\
+        } } while(0)
+
+#define ASSERT_ALWAYS(expr)	do {\
+        if(!(expr)) { \
+		printk( "Assertion [%s] failed! %s:%s(line=%d)\n",\
+			#expr,__FILE__,__FUNCTION__,__LINE__); \
+		panic("Assertion always panic\n"); 	\
+        } } while(0)
+#endif	/* DISABLE_ASSERT */
 
 #endif /* _ASM_IA64_SN_SGI_H */
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/simulator.h linux-2.4.23-pre4/include/asm-ia64/sn/simulator.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/simulator.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/simulator.h	2003-09-12 12:44:40.000000000 -0700
@@ -16,11 +16,13 @@
 #define IS_RUNNING_ON_SIMULATOR() ({long sn; asm("mov %0=cpuid[%1]" : "=r"(sn) : "r"(2)); sn == SNMAGIC;})
 
 #define SIMULATOR_SLEEP()	asm("nop.i 0x8beef")
+#define SIMULATOR_PAUSE()	asm("nop.i 0x9beef")
 
 #else
 
 #define IS_RUNNING_ON_SIMULATOR()	(0)
 #define SIMULATOR_SLEEP()
+#define SIMULATOR_PAUSE()
 
 #endif
 
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/sn2/arch.h linux-2.4.23-pre4/include/asm-ia64/sn/sn2/arch.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/sn2/arch.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/sn2/arch.h	2003-09-12 12:44:40.000000000 -0700
@@ -28,7 +28,7 @@
  * Effectively, it's the maximum number of compact node ids (cnodeid_t).
  * This is not necessarily the same as MAX_NASIDS.
  */
-#define MAX_COMPACT_NODES       128
+#define MAX_COMPACT_NODES       2048
 
 /*
  * MAX_REGIONS refers to the maximum number of hardware partitioned regions.
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/sn2/io.h linux-2.4.23-pre4/include/asm-ia64/sn/sn2/io.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/sn2/io.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/sn2/io.h	2003-09-12 12:44:40.000000000 -0700
@@ -9,7 +9,7 @@
 #ifndef _ASM_SN_SN2_IO_H
 #define _ASM_SN_SN2_IO_H
 
-extern void * sn_io_addr(unsigned long port); /* Forward definition */
+extern void * sn_io_addr(unsigned long port) __attribute__ ((__const__)); /* Forward definition */
 extern void sn_mmiob(void); /* Forward definition */
 
 #define __sn_mf_a()   __asm__ __volatile__ ("mf.a" ::: "memory")
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/sn2/shubio.h linux-2.4.23-pre4/include/asm-ia64/sn/sn2/shubio.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/sn2/shubio.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/sn2/shubio.h	2003-09-12 12:44:40.000000000 -0700
@@ -3629,13 +3629,8 @@
 extern int hub_error_devenable(vertex_hdl_t, int, int);
 extern int  hub_dma_enabled(vertex_hdl_t);
 
-/* hubdev */
-extern void hubdev_init(void);
-extern void hubdev_register(int (*attach_method)(vertex_hdl_t));
-extern int hubdev_unregister(int (*attach_method)(vertex_hdl_t));
-extern int hubdev_docallouts(vertex_hdl_t hub);
-
 extern caddr_t hubdev_prombase_get(vertex_hdl_t hub);
+
 extern cnodeid_t hubdev_cnodeid_get(vertex_hdl_t hub);
 
 #endif /* __ASSEMBLY__ */
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/sn2/sn_private.h linux-2.4.23-pre4/include/asm-ia64/sn/sn2/sn_private.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/sn2/sn_private.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/sn2/sn_private.h	2003-09-12 12:44:40.000000000 -0700
@@ -24,7 +24,6 @@
 extern __psunsigned_t get_master_bridge_base(void);
 extern void set_master_bridge_base(void);
 extern int check_nasid_equiv(nasid_t, nasid_t);
-extern nasid_t get_console_nasid(void);
 extern char get_console_pcislot(void);
 
 extern int is_master_baseio_nasid_widget(nasid_t test_nasid, xwidgetnum_t test_wid);
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/sn_sal.h linux-2.4.23-pre4/include/asm-ia64/sn/sn_sal.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/sn_sal.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/sn_sal.h	2003-09-12 12:44:40.000000000 -0700
@@ -16,6 +16,7 @@
 #include <asm/sal.h>
 #include <asm/sn/sn_cpuid.h>
 #include <asm/sn/arch.h>
+#include <asm/sn/nodepda.h>
 
 
 // SGI Specific Calls
@@ -597,8 +598,16 @@
 sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array)
 {
 	struct ia64_sal_retval ret_stuff;
-	SAL_CALL(ret_stuff, SN_SAL_MEMPROTECT, paddr, len, nasid_array,
+	int cnodeid;
+	unsigned long irq_flags;
+
+	cnodeid = nasid_to_cnodeid(get_node_number(paddr));
+	spin_lock(&NODEPDA(cnodeid)->bist_lock);
+	local_irq_save(irq_flags);
+	SAL_CALL_NOLOCK(ret_stuff, SN_SAL_MEMPROTECT, paddr, len, nasid_array,
 		 perms, 0, 0, 0);
+	local_irq_restore(irq_flags);
+	spin_unlock(&NODEPDA(cnodeid)->bist_lock);
 	return ret_stuff.status;
 }
 #define SN_MEMPROT_ACCESS_CLASS_0		0x14a080
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/uart16550.h linux-2.4.23-pre4/include/asm-ia64/sn/uart16550.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/uart16550.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/uart16550.h	2003-09-12 12:44:40.000000000 -0700
@@ -56,6 +56,9 @@
 #define		LCR_BITS7	0x02	/* 7 bits per char */
 #define		LCR_BITS8	0x03	/* 8 bits per char */
 
+#define		LCR_1_STOP_BITS	0x00	/* 1 stop bit */
+#define		LCR_2_STOP_BITS	0x04	/* 2 stop bits */
+
 #define		LCR_MASK_BITS_CHAR 		0x03
 #define 	LCR_MASK_STOP_BITS		0x04
 #define		LCR_MASK_PARITY_BITS	0x18
@@ -143,6 +146,9 @@
 #define DU_RTS_ASSERT(x)    ((x) |= MCR_RTS)
 #define DU_RTS_DEASSERT(x)  ((x) &= ~MCR_RTS)
 
+#define SER_DIVISOR(x, clk)		(((clk) + (x) * 8) / ((x) * 16))
+#define DIVISOR_TO_BAUD(div, clk)	((clk) / 16 / (div))
+
 
 /*
  * ioctl(fd, I_STR, arg)
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/xtalk/xtalk.h linux-2.4.23-pre4/include/asm-ia64/sn/xtalk/xtalk.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/xtalk/xtalk.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/xtalk/xtalk.h	2003-09-12 12:44:40.000000000 -0700
@@ -10,7 +10,9 @@
 #define _ASM_SN_XTALK_XTALK_H
 #include <linux/config.h>
 
+#ifdef __KERNEL__
 #include "asm/sn/sgi.h"
+#endif
 
 
 /*
diff -urN linux-2.4.23-pre3/include/asm-ia64/sn/xtalk/xwidget.h linux-2.4.23-pre4/include/asm-ia64/sn/xtalk/xwidget.h
--- linux-2.4.23-pre3/include/asm-ia64/sn/xtalk/xwidget.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/sn/xtalk/xwidget.h	2003-09-12 12:44:40.000000000 -0700
@@ -13,10 +13,14 @@
  * xwidget.h - generic crosstalk widget header file
  */
 
+#ifdef __KERNEL__
 #include <asm/sn/xtalk/xtalk.h>
 #ifndef __ASSEMBLY__
 #include <asm/sn/cdl.h>
 #endif /* __ASSEMBLY__ */
+#else
+#include <xtalk/xtalk.h>
+#endif
 
 #ifdef LITTLE_ENDIAN
 #define WIDGET_ID			0x00
diff -urN linux-2.4.23-pre3/include/asm-ia64/spinlock.h linux-2.4.23-pre4/include/asm-ia64/spinlock.h
--- linux-2.4.23-pre3/include/asm-ia64/spinlock.h	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/spinlock.h	2003-09-12 12:44:40.000000000 -0700
@@ -74,6 +74,12 @@
 #define SPIN_LOCK_UNLOCKED			(spinlock_t) { 0 }
 #define spin_lock_init(x)			((x)->lock = 0)
 
+#ifdef GAS_HAS_HINT_INSN
+#define HINT_PAUSE	";; (p7) hint @pause\n"
+#else
+#define HINT_PAUSE
+#endif										
+
 /*
  * Streamlined test_and_set_bit(0, (x)).  We use test-and-test-and-set
  * rather than a simple xchg to avoid writing the cache-line when
@@ -87,6 +93,7 @@
 	"ld4 r2 = [%0]\n"					\
 	";;\n"							\
 	"cmp4.eq p0,p7 = r0,r2\n"				\
+	HINT_PAUSE 						\
 	"(p7) br.cond.spnt.few 1b \n"				\
 	"cmpxchg4.acq r2 = [%0], r29, ar.ccv\n"			\
 	";;\n"							\
@@ -115,20 +122,21 @@
 	int tmp = 0;								\
 	__asm__ __volatile__ ("1:\tfetchadd4.acq %0 = [%1], 1\n"		\
 			      ";;\n"						\
-			      "tbit.nz p6,p0 = %0, 31\n"			\
-			      "(p6) br.cond.sptk.few 2f\n"			\
+			      "tbit.nz p7,p0 = %0, 31\n"			\
+			      "(p7) br.cond.sptk.few 2f\n"			\
 			      ".section .text.lock,\"ax\"\n"			\
 			      "2:\tfetchadd4.rel %0 = [%1], -1\n"		\
 			      ";;\n"						\
 			      "3:\tld4.acq %0 = [%1]\n"				\
 			      ";;\n"						\
-			      "tbit.nz p6,p0 = %0, 31\n"			\
-			      "(p6) br.cond.sptk.few 3b\n"			\
+			      "tbit.nz p7,p0 = %0, 31\n"			\
+			      HINT_PAUSE					\
+			      "(p7) br.cond.sptk.few 3b\n"			\
 			      "br.cond.sptk.few 1b\n"				\
 			      ";;\n"						\
 			      ".previous\n"					\
 			      : "=&r" (tmp)					\
-			      : "r" (rw) : "p6", "memory");			\
+			      : "r" (rw) : "p7", "memory");			\
 } while(0)
 
 #define read_unlock(rw)								\
@@ -150,6 +158,7 @@
 		"ld4 r2 = [%0]\n"						\
 		";;\n"								\
 		"cmp4.eq p0,p7 = r0,r2\n"					\
+		HINT_PAUSE							\
 		"(p7) br.cond.spnt.few 1b \n"					\
 		"cmpxchg4.acq r2 = [%0], r29, ar.ccv\n"				\
 		";;\n"								\
diff -urN linux-2.4.23-pre3/include/asm-ia64/system.h linux-2.4.23-pre4/include/asm-ia64/system.h
--- linux-2.4.23-pre3/include/asm-ia64/system.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/system.h	2003-09-12 12:44:40.000000000 -0700
@@ -104,7 +104,7 @@
 #define set_mb(var, value)	do { (var) = (value); mb(); } while (0)
 #define set_wmb(var, value)	do { (var) = (value); mb(); } while (0)
 
-#define safe_halt()         ia64_pal_halt(1)                /* PAL_HALT */
+#define safe_halt()         ia64_pal_halt_light()    /* PAL_HALT_LIGHT */
 
 /*
  * The group barrier in front of the rsm & ssm are necessary to ensure
diff -urN linux-2.4.23-pre3/include/asm-ia64/topology.h linux-2.4.23-pre4/include/asm-ia64/topology.h
--- linux-2.4.23-pre3/include/asm-ia64/topology.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/include/asm-ia64/topology.h	2003-09-12 12:44:40.000000000 -0700
@@ -0,0 +1,63 @@
+/*
+ * linux/include/asm-ia64/topology.h
+ *
+ * Copyright (C) 2002, Erich Focht, NEC
+ *
+ * All rights reserved.
+ *
+ * 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.
+ */
+#ifndef _ASM_IA64_TOPOLOGY_H
+#define _ASM_IA64_TOPOLOGY_H
+
+#include <asm/acpi.h>
+#include <asm/numa.h>
+#include <asm/smp.h>
+
+#ifdef CONFIG_NUMA
+/*
+ * Returns the number of the node containing CPU 'cpu'
+ */
+#define __cpu_to_node(cpu) (int)(cpu_to_node_map[cpu])
+
+/*
+ * Returns a bitmask of CPUs on Node 'node'.
+ */
+#define __node_to_cpu_mask(node) (node_to_cpu_mask[node])
+
+#else
+#define __cpu_to_node(cpu) (0)
+#define __node_to_cpumask(node) (&phys_cpu_present_map)
+#endif
+
+/*
+ * Returns the number of the node containing MemBlk 'memblk'
+ */
+#ifdef CONFIG_ACPI_NUMA
+#define __memblk_to_node(memblk) (node_memblk[memblk].nid)
+#else
+#define __memblk_to_node(memblk) (memblk)
+#endif
+
+/*
+ * Returns the number of the node containing Node 'nid'.
+ * Not implemented here. Multi-level hierarchies detected with
+ * the help of node_distance().
+ */
+#define __parent_node(nid) (nid)
+
+/*
+ * Returns the number of the first CPU on Node 'node'.
+ */
+#define __node_to_first_cpu(node) (__ffs(__node_to_cpu_mask(node)))
+
+/*
+ * Returns the number of the first MemBlk on Node 'node'
+ * Should be fixed when IA64 discontigmem goes in.
+ */
+#define __node_to_memblk(node) (node)
+
+#endif /* _ASM_IA64_TOPOLOGY_H */
diff -urN linux-2.4.23-pre3/include/asm-ia64/unwind.h linux-2.4.23-pre4/include/asm-ia64/unwind.h
--- linux-2.4.23-pre3/include/asm-ia64/unwind.h	2003-08-25 04:44:43.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ia64/unwind.h	2003-09-12 12:44:40.000000000 -0700
@@ -26,7 +26,9 @@
 	UNW_AR_EC,
 	UNW_AR_FPSR,
 	UNW_AR_RSC,
-	UNW_AR_CCV
+	UNW_AR_CCV,
+	UNW_AR_CSD,
+	UNW_AR_SSD
 };
 
 /*
diff -urN linux-2.4.23-pre3/include/asm-ia64/ustack.h linux-2.4.23-pre4/include/asm-ia64/ustack.h
--- linux-2.4.23-pre3/include/asm-ia64/ustack.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.23-pre4/include/asm-ia64/ustack.h	2003-09-12 12:44:40.000000000 -0700
@@ -0,0 +1,16 @@
+#ifndef _ASM_IA64_USTACK_H
+#define _ASM_IA64_USTACK_H
+
+/*
+ * Constants for the user stack size
+ */
+
+#include <asm/page.h>
+
+/* The absolute hard limit for stack size is 1/2 of the mappable space in the region */
+#define MAX_USER_STACK_SIZE	(RGN_MAP_LIMIT/2)
+/* Make a default stack size of 2GB */
+#define DEFAULT_USER_STACK_SIZE	(1UL << 31)
+#define STACK_TOP		(0x6000000000000000UL + RGN_MAP_LIMIT)
+
+#endif /* _ASM_IA64_USTACK_H */
diff -urN linux-2.4.23-pre3/include/asm-ppc/cpm_8260.h linux-2.4.23-pre4/include/asm-ppc/cpm_8260.h
--- linux-2.4.23-pre3/include/asm-ppc/cpm_8260.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ppc/cpm_8260.h	2003-09-12 12:44:40.000000000 -0700
@@ -195,7 +195,7 @@
 
 /* SMC uart mode register (Internal memory map).
 */
-#define	SMCMR_REN	((ushort)0x0001)
+#define SMCMR_REN	((ushort)0x0001)
 #define SMCMR_TEN	((ushort)0x0002)
 #define SMCMR_DM	((ushort)0x000c)
 #define SMCMR_SM_GCI	((ushort)0x0000)
@@ -212,10 +212,12 @@
 
 /* SMC Event and Mask register.
 */
-#define	SMCM_TXE	((unsigned char)0x10)
-#define	SMCM_BSY	((unsigned char)0x04)
-#define	SMCM_TX		((unsigned char)0x02)
-#define	SMCM_RX		((unsigned char)0x01)
+#define SMCM_BRKE       ((unsigned char)0x40)   /* When in UART Mode */
+#define SMCM_BRK        ((unsigned char)0x10)   /* When in UART Mode */
+#define SMCM_TXE	((unsigned char)0x10)
+#define SMCM_BSY	((unsigned char)0x04)
+#define SMCM_TX		((unsigned char)0x02)
+#define SMCM_RX		((unsigned char)0x01)
 
 /* Baud rate generators.
 */
@@ -314,10 +316,10 @@
 
 /* SCC Event and Mask register.
 */
-#define	SCCM_TXE	((unsigned char)0x10)
-#define	SCCM_BSY	((unsigned char)0x04)
-#define	SCCM_TX		((unsigned char)0x02)
-#define	SCCM_RX		((unsigned char)0x01)
+#define SCCM_TXE	((unsigned char)0x10)
+#define SCCM_BSY	((unsigned char)0x04)
+#define SCCM_TX		((unsigned char)0x02)
+#define SCCM_RX		((unsigned char)0x01)
 
 typedef struct scc_param {
 	ushort	scc_rbase;	/* Rx Buffer descriptor base address */
diff -urN linux-2.4.23-pre3/include/asm-ppc/highmem.h linux-2.4.23-pre4/include/asm-ppc/highmem.h
--- linux-2.4.23-pre3/include/asm-ppc/highmem.h	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ppc/highmem.h	2003-09-12 12:44:40.000000000 -0700
@@ -41,13 +41,13 @@
  * easily, subsequent pte tables have to be allocated in one physical
  * chunk of RAM.
  */
-#define PKMAP_BASE (0xfe000000UL)
-#define LAST_PKMAP 1024
+#define PKMAP_BASE	(0xfe000000UL)
+#define LAST_PKMAP	PTRS_PER_PTE
 #define LAST_PKMAP_MASK (LAST_PKMAP-1)
 #define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
 #define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
 
-#define KMAP_FIX_BEGIN	(0xfe400000UL)
+#define KMAP_FIX_BEGIN	(PKMAP_BASE + 0x00400000UL)
 
 extern void *kmap_high(struct page *page, int nonblock);
 extern void kunmap_high(struct page *page);
diff -urN linux-2.4.23-pre3/include/asm-ppc/pgtable.h linux-2.4.23-pre4/include/asm-ppc/pgtable.h
--- linux-2.4.23-pre3/include/asm-ppc/pgtable.h	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/include/asm-ppc/pgtable.h	2003-09-12 12:44:40.000000000 -0700
@@ -109,6 +109,13 @@
 extern unsigned long va_to_phys(unsigned long address);
 extern pte_t *va_to_pte(unsigned long address);
 extern unsigned long ioremap_bot, ioremap_base;
+extern unsigned long vmalloc_start;
+
+/* Start and end of the vmalloc area. */
+#define VMALLOC_START	vmalloc_start
+#define VMALLOC_END	ioremap_bot
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+
 #endif /* __ASSEMBLY__ */
 
 /*
@@ -196,32 +203,6 @@
 	printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
 /*
- * Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 64MB value just means that there will be a 64MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- *
- * We no longer map larger than phys RAM with the BATs so we don't have
- * to worry about the VMALLOC_OFFSET causing problems.  We do have to worry
- * about clashes between our early calls to ioremap() that start growing down
- * from ioremap_base being run into the VM area allocations (growing upwards
- * from VMALLOC_START).  For this reason we have ioremap_bot to check when
- * we actually run into our mappings setup in the early boot with the VM
- * system.  This really does become a problem for machines with good amounts
- * of RAM.  -- Cort
- */
-#define VMALLOC_OFFSET (0x1000000) /* 16M */
-#ifdef CONFIG_44x
-#define VMALLOC_START (((_ALIGN((long)high_memory, PPC44x_PIN_SIZE) + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)))
-#else
-#define VMALLOC_START ((((long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)))
-#endif
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END	ioremap_bot
-
-/*
  * Bits in a linux-style PTE.  These match the bits in the
  * (hardware-defined) PowerPC PTE as closely as possible.
  */
diff -urN linux-2.4.23-pre3/include/linux/byteorder/generic.h linux-2.4.23-pre4/include/linux/byteorder/generic.h
--- linux-2.4.23-pre3/include/linux/byteorder/generic.h	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.23-pre4/include/linux/byteorder/generic.h	2003-09-12 12:44:40.000000000 -0700
@@ -122,7 +122,7 @@
 #define be16_to_cpus __be16_to_cpus
 #endif
 
-
+#if defined(__KERNEL__)
 /*
  * Handle ntohl and suches. These have various compatibility
  * issues - like we want to give the prototype even though we
@@ -146,35 +146,26 @@
  * Do the prototypes. Somebody might want to take the
  * address or some such sick thing..
  */
-#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2)
 extern __u32			ntohl(__u32);
 extern __u32			htonl(__u32);
-#else
-extern unsigned long int	ntohl(unsigned long int);
-extern unsigned long int	htonl(unsigned long int);
-#endif
 extern unsigned short int	ntohs(unsigned short int);
 extern unsigned short int	htons(unsigned short int);
 
-
-#if defined(__GNUC__) && (__GNUC__ >= 2) && defined(__OPTIMIZE__) && !defined(__STRICT_ANSI__)
+#if defined(__GNUC__) && defined(__OPTIMIZE__)
 
 #define ___htonl(x) __cpu_to_be32(x)
 #define ___htons(x) __cpu_to_be16(x)
 #define ___ntohl(x) __be32_to_cpu(x)
 #define ___ntohs(x) __be16_to_cpu(x)
 
-#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2)
 #define htonl(x) ___htonl(x)
 #define ntohl(x) ___ntohl(x)
-#else
-#define htonl(x) ((unsigned long)___htonl(x))
-#define ntohl(x) ((unsigned long)___ntohl(x))
-#endif
 #define htons(x) ___htons(x)
 #define ntohs(x) ___ntohs(x)
 
 #endif /* OPTIMIZE */
 
+#endif /* KERNEL */
+
 
 #endif /* _LINUX_BYTEORDER_GENERIC_H */
diff -urN linux-2.4.23-pre3/include/linux/mm.h linux-2.4.23-pre4/include/linux/mm.h
--- linux-2.4.23-pre3/include/linux/mm.h	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/include/linux/mm.h	2003-09-12 12:44:40.000000000 -0700
@@ -535,8 +535,8 @@
 	return page_count(page) - !!page->buffers == 1;
 }
 
-extern int can_share_swap_page(struct page *);
-extern int remove_exclusive_swap_page(struct page *);
+extern int FASTCALL(can_share_swap_page(struct page *));
+extern int FASTCALL(remove_exclusive_swap_page(struct page *));
 
 extern void __free_pte(pte_t);
 
diff -urN linux-2.4.23-pre3/include/linux/mmzone.h linux-2.4.23-pre4/include/linux/mmzone.h
--- linux-2.4.23-pre3/include/linux/mmzone.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-pre4/include/linux/mmzone.h	2003-09-12 12:44:40.000000000 -0700
@@ -19,6 +19,11 @@
 #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
 #endif
 
+#define ZONE_DMA               0
+#define ZONE_NORMAL            1
+#define ZONE_HIGHMEM           2
+#define MAX_NR_ZONES           3
+
 typedef struct free_area_struct {
 	struct list_head	free_list;
 	unsigned long		*map;
@@ -26,6 +31,11 @@
 
 struct pglist_data;
 
+typedef struct zone_watermarks_s {
+	unsigned long min, low, high;
+} zone_watermarks_t;
+
+
 /*
  * On machines where it is needed (eg PCs) we divide physical memory
  * into multiple physical zones. On a PC we have 3 zones:
@@ -40,8 +50,27 @@
 	 */
 	spinlock_t		lock;
 	unsigned long		free_pages;
-	unsigned long		pages_min, pages_low, pages_high;
-	int			need_balance;
+	/*
+	 * We don't know if the memory that we're going to allocate will be freeable
+	 * or/and it will be released eventually, so to avoid totally wasting several
+	 * GB of ram we must reserve some of the lower zone memory (otherwise we risk
+	 * to run OOM on the lower zones despite there's tons of freeable ram
+	 * on the higher zones).
+	 */
+	zone_watermarks_t       watermarks[MAX_NR_ZONES];
+
+	/*
+	 * The below fields are protected by different locks (or by
+	 * no lock at all like need_balance), so they're longs to
+	 * provide an atomic granularity against each other on
+	 * all architectures.
+	 */
+	unsigned long           need_balance;
+	/* protected by the pagemap_lru_lock */
+	unsigned long           nr_active_pages, nr_inactive_pages;
+	/* protected by the pagecache_lock */
+	unsigned long           nr_cache_pages;
+
 
 	/*
 	 * free areas of different sizes
@@ -90,13 +119,9 @@
 	 */
 	char			*name;
 	unsigned long		size;
+	unsigned long		realsize;
 } zone_t;
 
-#define ZONE_DMA		0
-#define ZONE_NORMAL		1
-#define ZONE_HIGHMEM		2
-#define MAX_NR_ZONES		3
-
 /*
  * One allocation request operates on a zonelist. A zonelist
  * is a list of zones, the first one is the 'goal' of the
@@ -143,8 +168,8 @@
 extern int numnodes;
 extern pg_data_t *pgdat_list;
 
-#define memclass(pgzone, classzone)	(((pgzone)->zone_pgdat == (classzone)->zone_pgdat) \
-			&& ((pgzone) <= (classzone)))
+#define zone_idx(zone)                 ((zone) - (zone)->zone_pgdat->node_zones)
+#define memclass(pgzone, classzone)    (zone_idx(pgzone) <= zone_idx(classzone))
 
 /*
  * The following two are not meant for general usage. They are here as
diff -urN linux-2.4.23-pre3/include/linux/nfsd/export.h linux-2.4.23-pre4/include/linux/nfsd/export.h
--- linux-2.4.23-pre3/include/linux/nfsd/export.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-pre4/include/linux/nfsd/export.h	2003-09-12 12:44:40.000000000 -0700
@@ -35,7 +35,7 @@
 #define NFSEXP_UIDMAP		0x0040
 #define NFSEXP_KERBEROS		0x0080		/* not available */
 #define NFSEXP_SUNSECURE	0x0100
-#define NFSEXP_CROSSMNT		0x0200
+#define NFSEXP_NOHIDE		0x0200
 #define NFSEXP_NOSUBTREECHECK	0x0400
 #define	NFSEXP_NOAUTHNLM	0x0800		/* Don't authenticate NLM requests - just trust */
 #define NFSEXP_MSNFS		0x1000	/* do silly things that MS clients expect */
@@ -80,7 +80,7 @@
 #define EX_SECURE(exp)		(!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
 #define EX_ISSYNC(exp)		(!((exp)->ex_flags & NFSEXP_ASYNC))
 #define EX_RDONLY(exp)		((exp)->ex_flags & NFSEXP_READONLY)
-#define EX_CROSSMNT(exp)	((exp)->ex_flags & NFSEXP_CROSSMNT)
+#define EX_NOHIDE(exp)		((exp)->ex_flags & NFSEXP_NOHIDE)
 #define EX_SUNSECURE(exp)	((exp)->ex_flags & NFSEXP_SUNSECURE)
 #define EX_WGATHER(exp)		((exp)->ex_flags & NFSEXP_GATHERED_WRITES)
 
diff -urN linux-2.4.23-pre3/include/linux/pagemap.h linux-2.4.23-pre4/include/linux/pagemap.h
--- linux-2.4.23-pre3/include/linux/pagemap.h	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/include/linux/pagemap.h	2003-09-12 12:44:40.000000000 -0700
@@ -45,7 +45,7 @@
 #define PAGE_HASH_BITS (page_hash_bits)
 #define PAGE_HASH_SIZE (1 << PAGE_HASH_BITS)
 
-extern atomic_t page_cache_size; /* # of pages currently in the hash table */
+extern unsigned long page_cache_size; /* # of pages currently in the hash table */
 extern struct page **page_hash_table;
 
 extern void page_cache_init(unsigned long);
diff -urN linux-2.4.23-pre3/include/linux/sched.h linux-2.4.23-pre4/include/linux/sched.h
--- linux-2.4.23-pre3/include/linux/sched.h	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.23-pre4/include/linux/sched.h	2003-09-12 12:44:40.000000000 -0700
@@ -429,7 +429,6 @@
 #define PF_DUMPCORE	0x00000200	/* dumped core */
 #define PF_SIGNALED	0x00000400	/* killed by a signal */
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
-#define PF_MEMDIE	0x00001000	/* Killed for out-of-memory */
 #define PF_FREE_PAGES	0x00002000	/* per process page freeing */
 #define PF_NOIO		0x00004000	/* avoid generating further I/O */
 
@@ -575,6 +574,7 @@
 /* per-UID process charging. */
 extern struct user_struct * alloc_uid(uid_t);
 extern void free_uid(struct user_struct *);
+extern void switch_uid(struct user_struct *);
 
 #include <asm/current.h>
 
diff -urN linux-2.4.23-pre3/include/linux/sunrpc/svc.h linux-2.4.23-pre4/include/linux/sunrpc/svc.h
--- linux-2.4.23-pre3/include/linux/sunrpc/svc.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-pre4/include/linux/sunrpc/svc.h	2003-09-12 12:44:40.000000000 -0700
@@ -112,6 +112,8 @@
 				rq_secure  : 1,	/* secure port */
 				rq_auth    : 1;	/* check client */
 
+	__u32			rq_daddr;	/* dest addr of request - reply from here */
+
 	void *			rq_argp;	/* decoded arguments */
 	void *			rq_resp;	/* xdr'd results */
 
diff -urN linux-2.4.23-pre3/include/linux/swap.h linux-2.4.23-pre4/include/linux/swap.h
--- linux-2.4.23-pre3/include/linux/swap.h	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/include/linux/swap.h	2003-09-12 12:44:40.000000000 -0700
@@ -87,7 +87,7 @@
 extern unsigned int nr_free_buffer_pages(void);
 extern int nr_active_pages;
 extern int nr_inactive_pages;
-extern atomic_t page_cache_size;
+extern unsigned long page_cache_size;
 extern atomic_t buffermem_pages;
 
 extern spinlock_cacheline_t pagecache_lock_cacheline;
@@ -115,6 +115,7 @@
 extern wait_queue_head_t kswapd_wait;
 extern int FASTCALL(try_to_free_pages_zone(zone_t *, unsigned int));
 extern int FASTCALL(try_to_free_pages(unsigned int));
+extern int vm_vfs_scan_ratio, vm_cache_scan_ratio, vm_lru_balance_ratio, vm_passes, vm_gfp_debug, vm_mapped_ratio;
 
 /* linux/mm/page_io.c */
 extern void rw_swap_page(int, struct page *);
@@ -175,34 +176,46 @@
 		BUG();				\
 } while (0)
 
+extern void delta_nr_active_pages(struct page *page, long delta);
+#define inc_nr_active_pages(page) delta_nr_active_pages(page, 1)
+#define dec_nr_active_pages(page) delta_nr_active_pages(page, -1)
+
+extern void delta_nr_inactive_pages(struct page *page, long delta);
+#define inc_nr_inactive_pages(page) delta_nr_inactive_pages(page, 1)
+#define dec_nr_inactive_pages(page) delta_nr_inactive_pages(page, -1)
+
 #define add_page_to_active_list(page)		\
 do {						\
 	DEBUG_LRU_PAGE(page);			\
 	SetPageActive(page);			\
 	list_add(&(page)->lru, &active_list);	\
-	nr_active_pages++;			\
+	inc_nr_active_pages(page);		\
 } while (0)
 
 #define add_page_to_inactive_list(page)		\
 do {						\
 	DEBUG_LRU_PAGE(page);			\
 	list_add(&(page)->lru, &inactive_list);	\
-	nr_inactive_pages++;			\
+	inc_nr_inactive_pages(page);		\
 } while (0)
 
 #define del_page_from_active_list(page)		\
 do {						\
 	list_del(&(page)->lru);			\
 	ClearPageActive(page);			\
-	nr_active_pages--;			\
+	dec_nr_active_pages(page);		\
 } while (0)
 
 #define del_page_from_inactive_list(page)	\
 do {						\
 	list_del(&(page)->lru);			\
-	nr_inactive_pages--;			\
+	dec_nr_inactive_pages(page);		\
 } while (0)
 
+extern void delta_nr_cache_pages(struct page *page, long delta);
+#define inc_nr_cache_pages(page) delta_nr_cache_pages(page, 1)
+#define dec_nr_cache_pages(page) delta_nr_cache_pages(page, -1)
+
 extern spinlock_t swaplock;
 
 #define swap_list_lock()	spin_lock(&swaplock)
diff -urN linux-2.4.23-pre3/include/linux/sysctl.h linux-2.4.23-pre4/include/linux/sysctl.h
--- linux-2.4.23-pre3/include/linux/sysctl.h	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/include/linux/sysctl.h	2003-09-12 12:44:40.000000000 -0700
@@ -147,7 +147,13 @@
 	VM_MAX_MAP_COUNT=11,	/* int: Maximum number of active map areas */
 	VM_MIN_READAHEAD=12,    /* Min file readahead */
 	VM_MAX_READAHEAD=13,    /* Max file readahead */
+	VM_VFS_SCAN_RATIO=14,   /* part of the inactive vfs lists to scan */
+	VM_LRU_BALANCE_RATIO=15,/* balance active and inactive caches */
+	VM_PASSES=16,           /* number of vm passes before failing */
 	VM_PAGEBUF=17,		/* struct: Control pagebuf parameters */
+	VM_GFP_DEBUG=18,        /* debug GFP failures */
+	VM_CACHE_SCAN_RATIO=19, /* part of the inactive cache list to scan */
+	VM_MAPPED_RATIO=20,     /* amount of unfreeable pages that triggers swapout */
 };
 
 
diff -urN linux-2.4.23-pre3/include/linux/wireless.h linux-2.4.23-pre4/include/linux/wireless.h
--- linux-2.4.23-pre3/include/linux/wireless.h	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.23-pre4/include/linux/wireless.h	2003-09-12 12:44:40.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * This file define a set of standard wireless extensions
  *
- * Version :	15	12.7.02
+ * Version :	16	2.4.03
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
  * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
@@ -69,6 +69,8 @@
 
 /***************************** INCLUDES *****************************/
 
+/* To minimise problems in user space, I might remove those headers
+ * at some point. Jean II */
 #include <linux/types.h>		/* for "caddr_t" et al		*/
 #include <linux/socket.h>		/* for "struct sockaddr" et al	*/
 #include <linux/if.h>			/* for IFNAMSIZ and co... */
@@ -80,7 +82,7 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT	15
+#define WIRELESS_EXT	16
 
 /*
  * Changes :
@@ -163,6 +165,16 @@
  *	- Add IW_TXPOW_RANGE for range of Tx Powers
  *	- Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
  *	- Add IW_MODE_MONITOR for passive monitor
+ *
+ * V15 to V16
+ * ----------
+ *	- Increase the number of bitrates in iw_range to 32 (for 802.11g)
+ *	- Increase the number of frequencies in iw_range to 32 (for 802.11b+a)
+ *	- Reshuffle struct iw_range for increases, add filler
+ *	- Increase IW_MAX_AP to 64 for driver returning a lot of addresses
+ *	- Remove IW_MAX_GET_SPY because conflict with enhanced spy support
+ *	- Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy"
+ *	- Add IW_ENCODE_TEMP and iw_range->encoding_login_index
  */
 
 /**************************** CONSTANTS ****************************/
@@ -196,9 +208,11 @@
 /* SIOCGIWSTATS is strictly used between user space and the kernel, and
  * is never passed to the driver (i.e. the driver will never see it). */
 
-/* Mobile IP support (statistics per MAC address) */
+/* Spy support (statistics per MAC address - used for Mobile IP support) */
 #define SIOCSIWSPY	0x8B10		/* set spy addresses */
 #define SIOCGIWSPY	0x8B11		/* get spy info (quality of link) */
+#define SIOCSIWTHRSPY	0x8B12		/* set spy threshold (spy event) */
+#define SIOCGIWTHRSPY	0x8B13		/* get spy threshold */
 
 /* Access Point manipulation */
 #define SIOCSIWAP	0x8B14		/* set access point MAC addresses */
@@ -294,7 +308,7 @@
 #define IW_PRIV_TYPE_FLOAT	0x5000	/* struct iw_freq */
 #define IW_PRIV_TYPE_ADDR	0x6000	/* struct sockaddr */
 
-#define IW_PRIV_SIZE_FIXED	0x0800	/* Variable or fixed nuber of args */
+#define IW_PRIV_SIZE_FIXED	0x0800	/* Variable or fixed number of args */
 
 #define IW_PRIV_SIZE_MASK	0x07FF	/* Max number of those args */
 
@@ -306,13 +320,13 @@
 /* ----------------------- OTHER CONSTANTS ----------------------- */
 
 /* Maximum frequencies in the range struct */
-#define IW_MAX_FREQUENCIES	16
+#define IW_MAX_FREQUENCIES	32
 /* Note : if you have something like 80 frequencies,
  * don't increase this constant and don't fill the frequency list.
  * The user will be able to set by channel anyway... */
 
 /* Maximum bit rates in the range struct */
-#define IW_MAX_BITRATES		8
+#define IW_MAX_BITRATES		32
 
 /* Maximum tx powers in the range struct */
 #define IW_MAX_TXPOWER		8
@@ -320,8 +334,7 @@
  * a few of them in the struct iw_range. */
 
 /* Maximum of address that you may set with SPY */
-#define IW_MAX_SPY		8	/* set */
-#define IW_MAX_GET_SPY		64	/* get */
+#define IW_MAX_SPY		8
 
 /* Maximum of address that you may get in the
    list of access points in range */
@@ -354,7 +367,8 @@
 #define IW_ENCODE_ENABLED	0x0000	/* Encoding enabled */
 #define IW_ENCODE_RESTRICTED	0x4000	/* Refuse non-encoded packets */
 #define IW_ENCODE_OPEN		0x2000	/* Accept non-encoded packets */
-#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
+#define IW_ENCODE_NOKEY		0x0800  /* Key is write only, so not present */
+#define IW_ENCODE_TEMP		0x0400  /* Temporary key */
 
 /* Power management flags available (along with the value, if any) */
 #define IW_POWER_ON		0x0000	/* No details... */
@@ -482,6 +496,17 @@
 	__u32		beacon;		/* Missed beacons/superframe */
 };
 
+/*
+ *	Quality range (for spy threshold)
+ */
+struct	iw_thrspy
+{
+	struct sockaddr		addr;		/* Source address (hw/mac) */
+	struct iw_quality	qual;		/* Quality of the link */
+	struct iw_quality	low;		/* Low threshold */
+	struct iw_quality	high;		/* High threshold */
+};
+
 /* ------------------------ WIRELESS STATS ------------------------ */
 /*
  * Wireless statistics (used for /proc/net/wireless)
@@ -534,7 +559,7 @@
 	struct iw_quality qual;		/* Quality part of statistics */
 
 	struct sockaddr	ap_addr;	/* Access point address */
-	struct sockaddr	addr;		/* Destination address (hw) */
+	struct sockaddr	addr;		/* Destination address (hw/mac) */
 
 	struct iw_param	param;		/* Other small parameters */
 	struct iw_point	data;		/* Other large parameters */
@@ -582,17 +607,31 @@
 	__u32		min_nwid;	/* Minimal NWID we are able to set */
 	__u32		max_nwid;	/* Maximal NWID we are able to set */
 
-	/* Frequency */
-	__u16		num_channels;	/* Number of channels [0; num - 1] */
-	__u8		num_frequency;	/* Number of entry in the list */
-	struct iw_freq	freq[IW_MAX_FREQUENCIES];	/* list */
-	/* Note : this frequency list doesn't need to fit channel numbers */
+	/* Old Frequency (backward compat - moved lower ) */
+	__u16		old_num_channels;
+	__u8		old_num_frequency;
+	/* Filler to keep "version" at the same offset */
+	__s32		old_freq[6];
 
 	/* signal level threshold range */
 	__s32	sensitivity;
 
 	/* Quality of link & SNR stuff */
+	/* Quality range (link, level, noise)
+	 * If the quality is absolute, it will be in the range [0 ; max_qual],
+	 * if the quality is dBm, it will be in the range [max_qual ; 0].
+	 * Don't forget that we use 8 bit arithmetics... */
 	struct iw_quality	max_qual;	/* Quality of the link */
+	/* This should contain the average/typical values of the quality
+	 * indicator. This should be the threshold between a "good" and
+	 * a "bad" link (example : monitor going from green to orange).
+	 * Currently, user space apps like quality monitors don't have any
+	 * way to calibrate the measurement. With this, they can split
+	 * the range between 0 and max_qual in different quality level
+	 * (using a geometric subdivision centered on the average).
+	 * I expect that people doing the user space apps will feedback
+	 * us on which value we need to put in each driver... */
+	struct iw_quality	avg_qual;	/* Quality of the link */
 
 	/* Rates */
 	__u8		num_bitrates;	/* Number of entries in the list */
@@ -619,6 +658,8 @@
 	__u16	encoding_size[IW_MAX_ENCODING_SIZES];	/* Different token sizes */
 	__u8	num_encoding_sizes;	/* Number of entry in the list */
 	__u8	max_encoding_tokens;	/* Max number of tokens */
+	/* For drivers that need a "login/passwd" form */
+	__u8	encoding_login_index;	/* token index for login token */
 
 	/* Transmit power */
 	__u16		txpower_capa;	/* What options are supported */
@@ -638,18 +679,12 @@
 	__s32		min_r_time;	/* Minimal retry lifetime */
 	__s32		max_r_time;	/* Maximal retry lifetime */
 
-	/* Average quality of link & SNR */
-	struct iw_quality	avg_qual;	/* Quality of the link */
-	/* This should contain the average/typical values of the quality
-	 * indicator. This should be the threshold between a "good" and
-	 * a "bad" link (example : monitor going from green to orange).
-	 * Currently, user space apps like quality monitors don't have any
-	 * way to calibrate the measurement. With this, they can split
-	 * the range between 0 and max_qual in different quality level
-	 * (using a geometric subdivision centered on the average).
-	 * I expect that people doing the user space apps will feedback
-	 * us on which value we need to put in each driver...
-	 */
+	/* Frequency */
+	__u16		num_channels;	/* Number of channels [0; num - 1] */
+	__u8		num_frequency;	/* Number of entry in the list */
+	struct iw_freq	freq[IW_MAX_FREQUENCIES];	/* list */
+	/* Note : this frequency list doesn't need to fit channel numbers,
+	 * because each entry contain its channel index */
 };
 
 /*
diff -urN linux-2.4.23-pre3/include/net/iw_handler.h linux-2.4.23-pre4/include/net/iw_handler.h
--- linux-2.4.23-pre3/include/net/iw_handler.h	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.23-pre4/include/net/iw_handler.h	2003-09-12 12:44:40.000000000 -0700
@@ -1,7 +1,7 @@
 /*
  * This file define the new driver API for Wireless Extensions
  *
- * Version :	4	21.6.02
+ * Version :	5	4.12.02
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
  * Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
@@ -206,7 +206,7 @@
  * will be needed...
  * I just plan to increment with each new version.
  */
-#define IW_HANDLER_VERSION	4
+#define IW_HANDLER_VERSION	5
 
 /*
  * Changes :
@@ -220,10 +220,18 @@
  * V3 to V4
  * --------
  *	- Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
+ *
+ * V4 to V5
+ * --------
+ *	- Add new spy support : struct iw_spy_data & prototypes
  */
 
 /**************************** CONSTANTS ****************************/
 
+/* Enable enhanced spy support. Disable to reduce footprint */
+#define IW_WIRELESS_SPY
+#define IW_WIRELESS_THRSPY
+
 /* Special error message for the driver to indicate that we
  * should do a commit after return from the iw_handler */
 #define EIWCOMMIT	EINPROGRESS
@@ -315,6 +323,9 @@
 	 * We will automatically export that to user space... */
 	struct iw_priv_args *	private_args;
 
+	/* Driver enhanced spy support */
+	long			spy_offset;	/* Spy data offset */
+
 	/* In the long term, get_wireless_stats will move from
 	 * 'struct net_device' to here, to minimise bloat. */
 };
@@ -350,6 +361,33 @@
 
 /* Need to think of short header translation table. Later. */
 
+/* --------------------- ENHANCED SPY SUPPORT --------------------- */
+/*
+ * In the old days, the driver was handling spy support all by itself.
+ * Now, the driver can delegate this task to Wireless Extensions.
+ * It needs to include this struct in its private part and use the
+ * standard spy iw_handler.
+ */
+
+/*
+ * Instance specific spy data, i.e. addresses spied and quality for them.
+ */
+struct iw_spy_data
+{
+#ifdef IW_WIRELESS_SPY
+	/* --- Standard spy support --- */
+	int			spy_number;
+	u_char			spy_address[IW_MAX_SPY][ETH_ALEN];
+	struct iw_quality	spy_stat[IW_MAX_SPY];
+#ifdef IW_WIRELESS_THRSPY
+	/* --- Enhanced spy support (event) */
+	struct iw_quality	spy_thr_low;	/* Low threshold */
+	struct iw_quality	spy_thr_high;	/* High threshold */
+	u_char			spy_thr_under[IW_MAX_SPY];
+#endif /* IW_WIRELESS_THRSPY */
+#endif /* IW_WIRELESS_SPY */
+};
+
 /**************************** PROTOTYPES ****************************/
 /*
  * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
@@ -376,6 +414,31 @@
 /* We may need a function to send a stream of events to user space.
  * More on that later... */
 
+/* Standard handler for SIOCSIWSPY */
+extern int iw_handler_set_spy(struct net_device *	dev,
+			      struct iw_request_info *	info,
+			      union iwreq_data *	wrqu,
+			      char *			extra);
+/* Standard handler for SIOCGIWSPY */
+extern int iw_handler_get_spy(struct net_device *	dev,
+			      struct iw_request_info *	info,
+			      union iwreq_data *	wrqu,
+			      char *			extra);
+/* Standard handler for SIOCSIWTHRSPY */
+extern int iw_handler_set_thrspy(struct net_device *	dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *	wrqu,
+				 char *			extra);
+/* Standard handler for SIOCGIWTHRSPY */
+extern int iw_handler_get_thrspy(struct net_device *	dev,
+				 struct iw_request_info *info,
+				 union iwreq_data *	wrqu,
+				 char *			extra);
+/* Driver call to update spy records */
+extern void wireless_spy_update(struct net_device *	dev,
+				unsigned char *		address,
+				struct iw_quality *	wstats);
+
 /************************* INLINE FUNTIONS *************************/
 /*
  * Function that are so simple that it's more efficient inlining them
diff -urN linux-2.4.23-pre3/kernel/kmod.c linux-2.4.23-pre4/kernel/kmod.c
--- linux-2.4.23-pre3/kernel/kmod.c	2002-08-02 17:39:46.000000000 -0700
+++ linux-2.4.23-pre4/kernel/kmod.c	2003-09-12 12:44:40.000000000 -0700
@@ -119,15 +119,7 @@
 		if (curtask->files->fd[i]) close(i);
 	}
 
-	/* Drop the "current user" thing */
-	{
-		struct user_struct *user = curtask->user;
-		curtask->user = INIT_USER;
-		atomic_inc(&INIT_USER->__count);
-		atomic_inc(&INIT_USER->processes);
-		atomic_dec(&user->processes);
-		free_uid(user);
-	}
+	switch_uid(INIT_USER);
 
 	/* Give kmod all effective privileges.. */
 	curtask->euid = curtask->fsuid = 0;
diff -urN linux-2.4.23-pre3/kernel/sched.c linux-2.4.23-pre4/kernel/sched.c
--- linux-2.4.23-pre3/kernel/sched.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/kernel/sched.c	2003-09-12 12:44:40.000000000 -0700
@@ -1312,7 +1312,7 @@
 	this_task->cap_permitted = CAP_FULL_SET;
 	this_task->keep_capabilities = 0;
 	memcpy(this_task->rlim, init_task.rlim, sizeof(*(this_task->rlim)));
-	this_task->user = INIT_USER;
+	switch_uid(INIT_USER);
 
 	spin_unlock(&runqueue_lock);
 	write_unlock_irq(&tasklist_lock);
diff -urN linux-2.4.23-pre3/kernel/sys.c linux-2.4.23-pre4/kernel/sys.c
--- linux-2.4.23-pre3/kernel/sys.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/kernel/sys.c	2003-09-12 12:44:40.000000000 -0700
@@ -511,19 +511,12 @@
 
 static int set_user(uid_t new_ruid, int dumpclear)
 {
-	struct user_struct *new_user, *old_user;
+	struct user_struct *new_user;
 
-	/* What if a process setreuid()'s and this brings the
-	 * new uid over his NPROC rlimit?  We can check this now
-	 * cheaply with the new uid cache, so if it matters
-	 * we should be checking for it.  -DaveM
-	 */
 	new_user = alloc_uid(new_ruid);
 	if (!new_user)
 		return -EAGAIN;
-	old_user = current->user;
-	atomic_dec(&old_user->processes);
-	atomic_inc(&new_user->processes);
+	switch_uid(new_user);
 
 	if(dumpclear)
 	{
@@ -531,8 +524,6 @@
 		wmb();
 	}
 	current->uid = new_ruid;
-	current->user = new_user;
-	free_uid(old_user);
 	return 0;
 }
 
diff -urN linux-2.4.23-pre3/kernel/sysctl.c linux-2.4.23-pre4/kernel/sysctl.c
--- linux-2.4.23-pre3/kernel/sysctl.c	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/kernel/sysctl.c	2003-09-12 12:44:40.000000000 -0700
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/sysrq.h>
 #include <linux/highuid.h>
+#include <linux/swap.h>
 
 #include <asm/uaccess.h>
 
@@ -276,6 +277,18 @@
 };
 
 static ctl_table vm_table[] = {
+	{VM_GFP_DEBUG, "vm_gfp_debug", 
+	 &vm_gfp_debug, sizeof(int), 0644, NULL, &proc_dointvec},
+	{VM_VFS_SCAN_RATIO, "vm_vfs_scan_ratio", 
+	 &vm_vfs_scan_ratio, sizeof(int), 0644, NULL, &proc_dointvec},
+	{VM_CACHE_SCAN_RATIO, "vm_cache_scan_ratio", 
+	 &vm_cache_scan_ratio, sizeof(int), 0644, NULL, &proc_dointvec},
+	{VM_MAPPED_RATIO, "vm_mapped_ratio", 
+	 &vm_mapped_ratio, sizeof(int), 0644, NULL, &proc_dointvec},
+	{VM_LRU_BALANCE_RATIO, "vm_lru_balance_ratio", 
+	 &vm_lru_balance_ratio, sizeof(int), 0644, NULL, &proc_dointvec},
+	{VM_PASSES, "vm_passes", 
+	 &vm_passes, sizeof(int), 0644, NULL, &proc_dointvec},
 	{VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0644, NULL,
 	 &proc_dointvec_minmax, &sysctl_intvec, NULL,
 	 &bdflush_min, &bdflush_max},
diff -urN linux-2.4.23-pre3/kernel/user.c linux-2.4.23-pre4/kernel/user.c
--- linux-2.4.23-pre3/kernel/user.c	2000-11-28 22:43:39.000000000 -0800
+++ linux-2.4.23-pre4/kernel/user.c	2003-09-12 12:44:40.000000000 -0700
@@ -120,6 +120,23 @@
 	return up;
 }
 
+void switch_uid(struct user_struct *new_user)
+{
+ struct user_struct *old_user;
+
+ /* What if a process setreuid()'s and this brings the
+ * new uid over his NPROC rlimit? We can check this now
+ * cheaply with the new uid cache, so if it matters
+ * we should be checking for it. -DaveM
+ */
+ old_user = current->user;
+ atomic_inc(&new_user->__count);
+ atomic_inc(&new_user->processes);
+ atomic_dec(&old_user->processes);
+ current->user = new_user;
+ free_uid(old_user);
+}
+
 
 static int __init uid_cache_init(void)
 {
diff -urN linux-2.4.23-pre3/mm/filemap.c linux-2.4.23-pre4/mm/filemap.c
--- linux-2.4.23-pre3/mm/filemap.c	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/mm/filemap.c	2003-09-12 12:44:40.000000000 -0700
@@ -42,7 +42,7 @@
  * SMP-threaded pagemap-LRU 1999, Andrea Arcangeli <andrea@suse.de>
  */
 
-atomic_t page_cache_size = ATOMIC_INIT(0);
+unsigned long page_cache_size;
 unsigned int page_hash_bits;
 struct page **page_hash_table;
 
@@ -79,7 +79,7 @@
 		next->pprev_hash = &page->next_hash;
 	if (page->buffers)
 		PAGE_BUG(page);
-	atomic_inc(&page_cache_size);
+	inc_nr_cache_pages(page);
 }
 
 static inline void add_page_to_inode_queue(struct address_space *mapping, struct page * page)
@@ -113,7 +113,7 @@
 		next->pprev_hash = pprev;
 	*pprev = next;
 	page->pprev_hash = NULL;
-	atomic_dec(&page_cache_size);
+	dec_nr_cache_pages(page);
 }
 
 /*
diff -urN linux-2.4.23-pre3/mm/mmap.c linux-2.4.23-pre4/mm/mmap.c
--- linux-2.4.23-pre3/mm/mmap.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.23-pre4/mm/mmap.c	2003-09-12 12:44:40.000000000 -0700
@@ -69,7 +69,7 @@
 	    return 1;
 
 	/* The page cache contains buffer pages these days.. */
-	free = atomic_read(&page_cache_size);
+	free = page_cache_size;
 	free += nr_free_pages();
 	free += nr_swap_pages;
 
diff -urN linux-2.4.23-pre3/mm/mprotect.c linux-2.4.23-pre4/mm/mprotect.c
--- linux-2.4.23-pre3/mm/mprotect.c	2002-08-02 17:39:46.000000000 -0700
+++ linux-2.4.23-pre4/mm/mprotect.c	2003-09-12 12:44:40.000000000 -0700
@@ -275,7 +275,7 @@
 	len = PAGE_ALIGN(len);
 	end = start + len;
 	if (end < start)
-		return -EINVAL;
+		return -ENOMEM;
 	if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
 		return -EINVAL;
 	if (end == start)
diff -urN linux-2.4.23-pre3/mm/oom_kill.c linux-2.4.23-pre4/mm/oom_kill.c
--- linux-2.4.23-pre3/mm/oom_kill.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/mm/oom_kill.c	2003-09-12 12:44:40.000000000 -0700
@@ -21,6 +21,8 @@
 #include <linux/swapctl.h>
 #include <linux/timex.h>
 
+#if 0		/* Nothing in this file is used */
+
 /* #define DEBUG */
 
 /**
@@ -151,7 +153,6 @@
 	 * exit() and clear out its resources quickly...
 	 */
 	p->counter = 5 * HZ;
-	p->flags |= PF_MEMALLOC | PF_MEMDIE;
 
 	/* This process has hardware access, be more careful. */
 	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO)) {
@@ -256,3 +257,5 @@
 	first = now;
 	count = 0;
 }
+
+#endif	/* Unused file */
diff -urN linux-2.4.23-pre3/mm/page_alloc.c linux-2.4.23-pre4/mm/page_alloc.c
--- linux-2.4.23-pre3/mm/page_alloc.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-pre4/mm/page_alloc.c	2003-09-12 12:44:40.000000000 -0700
@@ -42,6 +42,9 @@
 static int zone_balance_ratio[MAX_NR_ZONES] __initdata = { 128, 128, 128, };
 static int zone_balance_min[MAX_NR_ZONES] __initdata = { 20 , 20, 20, };
 static int zone_balance_max[MAX_NR_ZONES] __initdata = { 255 , 255, 255, };
+static int lower_zone_reserve_ratio[MAX_NR_ZONES-1] = { 256, 32 };
+
+int vm_gfp_debug = 0;
 
 /*
  * Temporary debugging check.
@@ -253,7 +256,7 @@
 static struct page * balance_classzone(zone_t * classzone, unsigned int gfp_mask, unsigned int order, int * freed)
 {
 	struct page * page = NULL;
-	int __freed = 0;
+	int __freed;
 
 	if (!(gfp_mask & __GFP_WAIT))
 		goto out;
@@ -321,28 +324,31 @@
 	return page;
 }
 
+static inline unsigned long zone_free_pages(zone_t * zone, unsigned int order)
+{
+	long free = zone->free_pages - (1UL << order);
+	return free >= 0 ? free : 0;
+}
+
 /*
  * This is the 'heart' of the zoned buddy allocator:
  */
 struct page * __alloc_pages(unsigned int gfp_mask, unsigned int order, zonelist_t *zonelist)
 {
-	unsigned long min;
 	zone_t **zone, * classzone;
 	struct page * page;
-	int freed;
+	int freed, class_idx;
 
 	zone = zonelist->zones;
 	classzone = *zone;
-	if (classzone == NULL)
-		return NULL;
-	min = 1UL << order;
+	class_idx = zone_idx(classzone);
+
 	for (;;) {
 		zone_t *z = *(zone++);
 		if (!z)
 			break;
 
-		min += z->pages_low;
-		if (z->free_pages > min) {
+		if (zone_free_pages(z, order) > z->watermarks[class_idx].low) {
 			page = rmqueue(z, order);
 			if (page)
 				return page;
@@ -355,18 +361,16 @@
 		wake_up_interruptible(&kswapd_wait);
 
 	zone = zonelist->zones;
-	min = 1UL << order;
 	for (;;) {
-		unsigned long local_min;
+		unsigned long min;
 		zone_t *z = *(zone++);
 		if (!z)
 			break;
 
-		local_min = z->pages_min;
+		min = z->watermarks[class_idx].min;
 		if (!(gfp_mask & __GFP_WAIT))
-			local_min >>= 2;
-		min += local_min;
-		if (z->free_pages > min) {
+			min >>= 2;
+		if (zone_free_pages(z, order) > min) {
 			page = rmqueue(z, order);
 			if (page)
 				return page;
@@ -375,8 +379,7 @@
 
 	/* here we're in the low on memory slow path */
 
-rebalance:
-	if (current->flags & (PF_MEMALLOC | PF_MEMDIE)) {
+	if (current->flags & PF_MEMALLOC && !in_interrupt()) {
 		zone = zonelist->zones;
 		for (;;) {
 			zone_t *z = *(zone++);
@@ -392,34 +395,51 @@
 
 	/* Atomic allocations - we can't balance anything */
 	if (!(gfp_mask & __GFP_WAIT))
-		return NULL;
+		goto out;
 
+ rebalance:
 	page = balance_classzone(classzone, gfp_mask, order, &freed);
 	if (page)
 		return page;
 
 	zone = zonelist->zones;
-	min = 1UL << order;
-	for (;;) {
-		zone_t *z = *(zone++);
-		if (!z)
-			break;
+	if (likely(freed)) {
+		for (;;) {
+			zone_t *z = *(zone++);
+			if (!z)
+				break;
 
-		min += z->pages_min;
-		if (z->free_pages > min) {
-			page = rmqueue(z, order);
-			if (page)
-				return page;
+			if (zone_free_pages(z, order) > z->watermarks[class_idx].min) {
+				page = rmqueue(z, order);
+				if (page)
+					return page;
+			}
 		}
-	}
+		goto rebalance;
+	} else {
+		/* 
+		 * Check that no other task is been killed meanwhile,
+		 * in such a case we can succeed the allocation.
+		 */
+		for (;;) {
+			zone_t *z = *(zone++);
+			if (!z)
+				break;
 
-	/* Don't let big-order allocations loop */
-	if (order > 3)
-		return NULL;
+			if (zone_free_pages(z, order) > z->watermarks[class_idx].high) {
+				page = rmqueue(z, order);
+				if (page)
+					return page;
+			}
+		}
+	}
 
-	/* Yield for kswapd, and try again */
-	yield();
-	goto rebalance;
+ out:
+	printk(KERN_NOTICE "__alloc_pages: %u-order allocation failed (gfp=0x%x/%i)\n",
+	       order, gfp_mask, !!(current->flags & PF_MEMALLOC));
+	if (unlikely(vm_gfp_debug))
+		dump_stack();
+	return NULL;
 }
 
 /*
@@ -481,18 +501,25 @@
 {
 	pg_data_t *pgdat;
 	unsigned int sum = 0;
+	zonelist_t *zonelist;
+	zone_t **zonep, *zone;
 
 	for_each_pgdat(pgdat) {
-		zonelist_t *zonelist = pgdat->node_zonelists + (GFP_USER & GFP_ZONEMASK);
-		zone_t **zonep = zonelist->zones;
-		zone_t *zone;
-
-		for (zone = *zonep++; zone; zone = *zonep++) {
-			unsigned long size = zone->size;
-			unsigned long high = zone->pages_high;
-			if (size > high)
-				sum += size - high;
-		}
+		int class_idx;
+		zonelist = pgdat->node_zonelists + (GFP_USER & GFP_ZONEMASK);
+		zonep = zonelist->zones;
+		zone = *zonep;
+		class_idx = zone_idx(zone);
+
+		sum += zone->nr_cache_pages;
+		do {
+			unsigned int free = zone->free_pages - zone->watermarks[class_idx].high;
+			zonep++;
+			zone = *zonep;
+			if (free <= 0)
+				continue;
+			sum += free;
+		} while (zone);
 	}
 
 	return sum;
@@ -532,13 +559,9 @@
 		zone_t *zone;
 		for (zone = tmpdat->node_zones;
 			       	zone < tmpdat->node_zones + MAX_NR_ZONES; zone++)
-			printk("Zone:%s freepages:%6lukB min:%6lukB low:%6lukB " 
-				       "high:%6lukB\n", 
+			printk("Zone:%s freepages:%6lukB\n", 
 					zone->name,
-					K(zone->free_pages),
-					K(zone->pages_min),
-					K(zone->pages_low),
-					K(zone->pages_high));
+					K(zone->free_pages));
 			
 		tmpdat = tmpdat->node_next;
 	}
@@ -729,6 +752,7 @@
 		zone_t *zone = pgdat->node_zones + j;
 		unsigned long mask;
 		unsigned long size, realsize;
+		int idx;
 
 		zone_table[nid * MAX_NR_ZONES + j] = zone;
 		realsize = size = zones_size[j];
@@ -737,11 +761,15 @@
 
 		printk("zone(%lu): %lu pages.\n", j, size);
 		zone->size = size;
+		zone->realsize = realsize;
 		zone->name = zone_names[j];
 		zone->lock = SPIN_LOCK_UNLOCKED;
 		zone->zone_pgdat = pgdat;
 		zone->free_pages = 0;
 		zone->need_balance = 0;
+		 zone->nr_active_pages = zone->nr_inactive_pages = 0;
+
+
 		if (!size)
 			continue;
 
@@ -766,9 +794,29 @@
 			mask = zone_balance_min[j];
 		else if (mask > zone_balance_max[j])
 			mask = zone_balance_max[j];
-		zone->pages_min = mask;
-		zone->pages_low = mask*2;
-		zone->pages_high = mask*3;
+		zone->watermarks[j].min = mask;
+		zone->watermarks[j].low = mask*2;
+		zone->watermarks[j].high = mask*3;
+		/* now set the watermarks of the lower zones in the "j" classzone */
+		for (idx = j-1; idx >= 0; idx--) {
+			zone_t * lower_zone = pgdat->node_zones + idx;
+			unsigned long lower_zone_reserve;
+			if (!lower_zone->size)
+				continue;
+
+			mask = lower_zone->watermarks[idx].min;
+			lower_zone->watermarks[j].min = mask;
+			lower_zone->watermarks[j].low = mask*2;
+			lower_zone->watermarks[j].high = mask*3;
+
+			/* now the brainer part */
+			lower_zone_reserve = realsize / lower_zone_reserve_ratio[idx];
+			lower_zone->watermarks[j].min += lower_zone_reserve;
+			lower_zone->watermarks[j].low += lower_zone_reserve;
+			lower_zone->watermarks[j].high += lower_zone_reserve;
+
+			realsize += lower_zone->realsize;
+		}
 
 		zone->zone_mem_map = mem_map + offset;
 		zone->zone_start_mapnr = offset;
@@ -852,3 +900,16 @@
 }
 
 __setup("memfrac=", setup_mem_frac);
+
+static int __init setup_lower_zone_reserve(char *str)
+{
+	int j = 0;
+
+	while (get_option(&str, &lower_zone_reserve_ratio[j++]) == 2);
+	printk("setup_lower_zone_reserve: ");
+	for (j = 0; j < MAX_NR_ZONES-1; j++) printk("%d  ", lower_zone_reserve_ratio[j]);
+	printk("\n");
+	return 1;
+}
+
+__setup("lower_zone_reserve=", setup_lower_zone_reserve);
diff -urN linux-2.4.23-pre3/mm/swap.c linux-2.4.23-pre4/mm/swap.c
--- linux-2.4.23-pre3/mm/swap.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-pre4/mm/swap.c	2003-09-12 12:44:40.000000000 -0700
@@ -94,6 +94,78 @@
 	spin_unlock(&pagemap_lru_lock);
 }
 
+/**
+ * delta_nr_active_pages: alter the number of active pages.
+ *
+ * @page: the page which is being activated/deactivated
+ * @delta: +1 for activation, -1 for deactivation
+ *
+ * Called under pagecache_lock
+ */
+void delta_nr_active_pages(struct page *page, long delta)
+{
+	pg_data_t *pgdat;
+	zone_t *classzone, *overflow;
+
+	classzone = page_zone(page);
+	pgdat = classzone->zone_pgdat;
+	overflow = pgdat->node_zones + pgdat->nr_zones;
+
+	while (classzone < overflow) {
+		classzone->nr_active_pages += delta;
+		classzone++;
+	}
+	nr_active_pages += delta;
+}
+
+/**
+ * delta_nr_inactive_pages: alter the number of inactive pages.
+ *
+ * @page: the page which is being deactivated/activated
+ * @delta: +1 for deactivation, -1 for activation
+ *
+ * Called under pagecache_lock
+ */
+void delta_nr_inactive_pages(struct page *page, long delta)
+{
+	pg_data_t *pgdat;
+	zone_t *classzone, *overflow;
+
+	classzone = page_zone(page);
+	pgdat = classzone->zone_pgdat;
+	overflow = pgdat->node_zones + pgdat->nr_zones;
+
+	while (classzone < overflow) {
+		classzone->nr_inactive_pages += delta;
+		classzone++;
+	}
+	nr_inactive_pages += delta;
+}
+
+/**
+ * delta_nr_cache_pages: alter the number of pages in the pagecache
+ *
+ * @page: the page which is being added/removed
+ * @delta: +1 for addition, -1 for removal
+ *
+ * Called under pagecache_lock
+ */
+void delta_nr_cache_pages(struct page *page, long delta)
+{
+	pg_data_t *pgdat;
+	zone_t *classzone, *overflow;
+
+	classzone = page_zone(page);
+	pgdat = classzone->zone_pgdat;
+	overflow = pgdat->node_zones + pgdat->nr_zones;
+
+	while (classzone < overflow) {
+		classzone->nr_cache_pages += delta;
+		classzone++;
+	}
+	page_cache_size += delta;
+}
+
 /*
  * Perform any setup for the swap system
  */
diff -urN linux-2.4.23-pre3/mm/vmscan.c linux-2.4.23-pre4/mm/vmscan.c
--- linux-2.4.23-pre3/mm/vmscan.c	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.23-pre4/mm/vmscan.c	2003-09-12 12:44:40.000000000 -0700
@@ -27,12 +27,42 @@
 #include <asm/pgalloc.h>
 
 /*
- * The "priority" of VM scanning is how much of the queues we
- * will scan in one go. A value of 6 for DEF_PRIORITY implies
- * that we'll scan 1/64th of the queues ("queue_length >> 6")
- * during a normal aging round.
+ * "vm_passes" is the number of vm passes before failing the
+ * memory balancing. Take into account 3 passes are needed
+ * for a flush/wait/free cycle and that we only scan 1/vm_cache_scan_ratio
+ * of the inactive list at each pass.
  */
-#define DEF_PRIORITY (6)
+int vm_passes = 60;
+
+/*
+ * "vm_cache_scan_ratio" is how much of the inactive LRU queue we will scan
+ * in one go. A value of 6 for vm_cache_scan_ratio implies that we'll
+ * scan 1/6 of the inactive lists during a normal aging round.
+ */
+int vm_cache_scan_ratio = 6;
+
+/*
+ * "vm_mapped_ratio" controls the pageout rate, the smaller, the earlier
+ * we'll start to pageout.
+ */
+int vm_mapped_ratio = 100;
+
+/*
+ * "vm_lru_balance_ratio" controls the balance between active and
+ * inactive cache. The bigger vm_balance is, the easier the
+ * active cache will grow, because we'll rotate the active list
+ * slowly. A value of 2 means we'll go towards a balance of
+ * 1/3 of the cache being inactive.
+ */
+int vm_lru_balance_ratio = 2;
+
+/*
+ * "vm_vfs_scan_ratio" is what proportion of the VFS queues we will scan
+ * in one go. A value of 6 for vm_vfs_scan_ratio implies that 1/6th of
+ * the unused-inode, dentry and dquot caches will be freed during a normal
+ * aging round.
+ */
+int vm_vfs_scan_ratio = 6;
 
 /*
  * The swap-out function returns 1 if it successfully
@@ -292,13 +322,13 @@
 	return count;
 }
 
-static int FASTCALL(swap_out(unsigned int priority, unsigned int gfp_mask, zone_t * classzone));
-static int swap_out(unsigned int priority, unsigned int gfp_mask, zone_t * classzone)
+static int FASTCALL(swap_out(zone_t * classzone));
+static int swap_out(zone_t * classzone)
 {
 	int counter, nr_pages = SWAP_CLUSTER_MAX;
 	struct mm_struct *mm;
 
-	counter = mmlist_nr;
+	counter = mmlist_nr << 1;
 	do {
 		if (unlikely(current->need_resched)) {
 			__set_current_state(TASK_RUNNING);
@@ -334,15 +364,15 @@
 	return 0;
 }
 
-static int FASTCALL(shrink_cache(int nr_pages, zone_t * classzone, unsigned int gfp_mask, int priority));
-static int shrink_cache(int nr_pages, zone_t * classzone, unsigned int gfp_mask, int priority)
+static void FASTCALL(refill_inactive(int nr_pages, zone_t * classzone));
+static int FASTCALL(shrink_cache(int nr_pages, zone_t * classzone, unsigned int gfp_mask, int * failed_swapout));
+static int shrink_cache(int nr_pages, zone_t * classzone, unsigned int gfp_mask, int * failed_swapout)
 {
 	struct list_head * entry;
-	int max_scan = nr_inactive_pages / priority;
-	int max_mapped = min((nr_pages << (10 - priority)), max_scan / 10);
+	int max_scan = (classzone->nr_inactive_pages + classzone->nr_active_pages) / vm_cache_scan_ratio;
+	int max_mapped = vm_mapped_ratio * nr_pages;
 
-	spin_lock(&pagemap_lru_lock);
-	while (--max_scan >= 0 && (entry = inactive_list.prev) != &inactive_list) {
+	while (max_scan && classzone->nr_inactive_pages && (entry = inactive_list.prev) != &inactive_list) {
 		struct page * page;
 
 		if (unlikely(current->need_resched)) {
@@ -468,34 +498,49 @@
 		spin_lock(&pagecache_lock);
 
 		/*
-		 * this is the non-racy check for busy page.
+		 * This is the non-racy check for busy page.
+		 * It is critical to check PageDirty _after_ we made sure
+		 * the page is freeable so not in use by anybody.
+		 * At this point we're guaranteed that page->buffers is NULL,
+		 * nobody can refill page->buffers under us because we still
+		 * hold the page lock.
 		 */
-		if (!page->mapping || !is_page_cache_freeable(page)) {
+		if (!page->mapping || page_count(page) > 1) {
 			spin_unlock(&pagecache_lock);
 			UnlockPage(page);
 page_mapped:
-			if (--max_mapped >= 0)
-				continue;
+			if (--max_mapped < 0) {
+				spin_unlock(&pagemap_lru_lock);
 
-			/*
-			 * Alert! We've found too many mapped pages on the
-			 * inactive list, so we start swapping out now!
-			 */
-			spin_unlock(&pagemap_lru_lock);
-			swap_out(priority, gfp_mask, classzone);
-			return nr_pages;
-		}
+				nr_pages -= kmem_cache_reap(gfp_mask);
+				if (nr_pages <= 0)
+					goto out;
 
-		/*
-		 * It is critical to check PageDirty _after_ we made sure
-		 * the page is freeable* so not in use by anybody.
-		 */
+				shrink_dcache_memory(vm_vfs_scan_ratio, gfp_mask);
+				shrink_icache_memory(vm_vfs_scan_ratio, gfp_mask);
+#ifdef CONFIG_QUOTA
+				shrink_dqcache_memory(vm_vfs_scan_ratio, gfp_mask);
+#endif
+
+				if (!*failed_swapout)
+					*failed_swapout = !swap_out(classzone);
+
+				max_mapped = nr_pages * vm_mapped_ratio;
+
+				spin_lock(&pagemap_lru_lock);
+				refill_inactive(nr_pages, classzone);
+			}
+			continue;
+			
+		}
 		if (PageDirty(page)) {
 			spin_unlock(&pagecache_lock);
 			UnlockPage(page);
 			continue;
 		}
 
+		__lru_cache_del(page);
+
 		/* point of no return */
 		if (likely(!PageSwapCache(page))) {
 			__remove_inode_page(page);
@@ -508,7 +553,6 @@
 			swap_free(swap);
 		}
 
-		__lru_cache_del(page);
 		UnlockPage(page);
 
 		/* effectively free the page here */
@@ -520,6 +564,7 @@
 	}
 	spin_unlock(&pagemap_lru_lock);
 
+ out:
 	return nr_pages;
 }
 
@@ -530,13 +575,15 @@
  * We move them the other way when we see the
  * reference bit on the page.
  */
-static void refill_inactive(int nr_pages)
+static void refill_inactive(int nr_pages, zone_t * classzone)
 {
 	struct list_head * entry;
+	unsigned long ratio;
+
+	ratio = (unsigned long) nr_pages * classzone->nr_active_pages / (((unsigned long) classzone->nr_inactive_pages * vm_lru_balance_ratio) + 1);
 
-	spin_lock(&pagemap_lru_lock);
 	entry = active_list.prev;
-	while (nr_pages && entry != &active_list) {
+	while (ratio && entry != &active_list) {
 		struct page * page;
 
 		page = list_entry(entry, struct page, lru);
@@ -553,54 +600,62 @@
 		add_page_to_inactive_list(page);
 		SetPageReferenced(page);
 	}
-	spin_unlock(&pagemap_lru_lock);
+
+	if (entry != &active_list) {
+		list_del(&active_list);
+		list_add(&active_list, entry);
+	}
 }
 
-static int FASTCALL(shrink_caches(zone_t * classzone, int priority, unsigned int gfp_mask, int nr_pages));
-static int shrink_caches(zone_t * classzone, int priority, unsigned int gfp_mask, int nr_pages)
+static int FASTCALL(shrink_caches(zone_t * classzone, unsigned int gfp_mask, int nr_pages, int * failed_swapout));
+static int shrink_caches(zone_t * classzone, unsigned int gfp_mask, int nr_pages, int * failed_swapout)
 {
-	int chunk_size = nr_pages;
-	unsigned long ratio;
-
 	nr_pages -= kmem_cache_reap(gfp_mask);
 	if (nr_pages <= 0)
-		return 0;
+		goto out;
 
-	nr_pages = chunk_size;
-	/* try to keep the active list 2/3 of the size of the cache */
-	ratio = (unsigned long) nr_pages * nr_active_pages / ((nr_inactive_pages + 1) * 2);
-	refill_inactive(ratio);
-
-	nr_pages = shrink_cache(nr_pages, classzone, gfp_mask, priority);
-	if (nr_pages <= 0)
-		return 0;
+	spin_lock(&pagemap_lru_lock);
+	refill_inactive(nr_pages, classzone);
 
-	shrink_dcache_memory(priority, gfp_mask);
-	shrink_icache_memory(priority, gfp_mask);
-#ifdef CONFIG_QUOTA
-	shrink_dqcache_memory(DEF_PRIORITY, gfp_mask);
-#endif
+	nr_pages = shrink_cache(nr_pages, classzone, gfp_mask, failed_swapout);
 
-	return nr_pages;
+out:
+        return nr_pages;
 }
 
+static int check_classzone_need_balance(zone_t * classzone);
+
 int try_to_free_pages_zone(zone_t *classzone, unsigned int gfp_mask)
 {
-	int priority = DEF_PRIORITY;
-	int nr_pages = SWAP_CLUSTER_MAX;
-
 	gfp_mask = pf_gfp_mask(gfp_mask);
-	do {
-		nr_pages = shrink_caches(classzone, priority, gfp_mask, nr_pages);
-		if (nr_pages <= 0)
-			return 1;
-	} while (--priority);
 
-	/*
-	 * Hmm.. Cache shrink failed - time to kill something?
-	 * Mhwahahhaha! This is the part I really like. Giggle.
-	 */
-	out_of_memory();
+	for (;;) {
+		int tries = vm_passes;
+		int failed_swapout = !(gfp_mask & __GFP_IO);
+		int nr_pages = SWAP_CLUSTER_MAX;
+
+		do {
+			nr_pages = shrink_caches(classzone, gfp_mask, nr_pages, &failed_swapout);
+			if (nr_pages <= 0)
+				return 1;
+			shrink_dcache_memory(vm_vfs_scan_ratio, gfp_mask);
+			shrink_icache_memory(vm_vfs_scan_ratio, gfp_mask);
+#ifdef CONFIG_QUOTA
+			shrink_dqcache_memory(vm_vfs_scan_ratio, gfp_mask);
+#endif
+			if (!failed_swapout)
+				failed_swapout = !swap_out(classzone);
+		} while (--tries);
+
+	if (likely(current->pid != 1))
+		break;
+	if (!check_classzone_need_balance(classzone))
+		break;
+
+	__set_current_state(TASK_RUNNING);
+	yield();
+	}
+
 	return 0;
 }
 
@@ -627,11 +682,12 @@
 
 static int check_classzone_need_balance(zone_t * classzone)
 {
-	zone_t * first_classzone;
+	zone_t * first_zone;
+	int class_idx = zone_idx(classzone);
 
-	first_classzone = classzone->zone_pgdat->node_zones;
-	while (classzone >= first_classzone) {
-		if (classzone->free_pages > classzone->pages_high)
+	first_zone = classzone->zone_pgdat->node_zones;
+	while (classzone >= first_zone) {
+		if (classzone->free_pages > classzone->watermarks[class_idx].high)
 			return 0;
 		classzone--;
 	}
@@ -647,12 +703,12 @@
 		zone = pgdat->node_zones + i;
 		if (unlikely(current->need_resched))
 			schedule();
-		if (!zone->need_balance)
+		if (!zone->need_balance || !zone->size)
 			continue;
 		if (!try_to_free_pages_zone(zone, GFP_KSWAPD)) {
 			zone->need_balance = 0;
 			__set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ);
+			schedule_timeout(HZ*5);
 			continue;
 		}
 		if (check_classzone_need_balance(zone))
@@ -684,7 +740,7 @@
 
 	for (i = pgdat->nr_zones-1; i >= 0; i--) {
 		zone = pgdat->node_zones + i;
-		if (!zone->need_balance)
+		if (!zone->need_balance || !zone->size)
 			continue;
 		return 0;
 	}
diff -urN linux-2.4.23-pre3/net/atm/addr.c linux-2.4.23-pre4/net/atm/addr.c
--- linux-2.4.23-pre3/net/atm/addr.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/net/atm/addr.c	2003-09-12 12:44:40.000000000 -0700
@@ -118,23 +118,24 @@
 {
 	unsigned long flags;
 	struct atm_dev_addr *walk;
-	int total;
+	int total = 0, error;
+	struct sockaddr_atmsvc *tmp_buf, *tmp_bufp;
+
 
 	spin_lock_irqsave(&dev->lock, flags);
-	total = 0;
-	for (walk = dev->local; walk; walk = walk->next) {
+	for (walk = dev->local; walk; walk = walk->next)
 		total += sizeof(struct sockaddr_atmsvc);
-		if (total > size) {
-			spin_unlock_irqrestore(&dev->lock, flags);
-			return -E2BIG;
-		}
-		if (copy_to_user(u_buf,&walk->addr,
-		    sizeof(struct sockaddr_atmsvc))) {
-			spin_unlock_irqrestore(&dev->lock, flags);
-			return -EFAULT;
-		}
-		u_buf++;
+	tmp_buf = tmp_bufp = kmalloc(total, GFP_ATOMIC);
+	if (!tmp_buf) {
+		spin_unlock_irqrestore(&dev->lock, flags);
+		return -ENOMEM;
 	}
+	for (walk = dev->local; walk; walk = walk->next)
+		memcpy(tmp_bufp++, &walk->addr, sizeof(struct sockaddr_atmsvc));
 	spin_unlock_irqrestore(&dev->lock, flags);
-	return total;
+	error = total > size ? -E2BIG : total;
+	if (copy_to_user(u_buf, tmp_buf, total < size ? total : size))
+		error = -EFAULT;
+	kfree(tmp_buf);
+	return error;
 }
diff -urN linux-2.4.23-pre3/net/atm/common.c linux-2.4.23-pre4/net/atm/common.c
--- linux-2.4.23-pre3/net/atm/common.c	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/net/atm/common.c	2003-09-12 12:44:40.000000000 -0700
@@ -33,21 +33,61 @@
 #include <linux/atmlec.h>
 #include "lec.h"
 #include "lec_arpc.h"
-struct atm_lane_ops atm_lane_ops;
-#endif
-#ifdef CONFIG_ATM_LANE_MODULE
+struct atm_lane_ops *atm_lane_ops;
+static DECLARE_MUTEX(atm_lane_ops_mutex);
+
+void atm_lane_ops_set(struct atm_lane_ops *hook)
+{
+	down(&atm_lane_ops_mutex);
+	atm_lane_ops = hook;
+	up(&atm_lane_ops_mutex);
+}
+
+int try_atm_lane_ops(void)
+{
+	down(&atm_lane_ops_mutex);
+	if (atm_lane_ops && try_inc_mod_count(atm_lane_ops->owner)) {
+		up(&atm_lane_ops_mutex);
+		return 1;
+	}
+	up(&atm_lane_ops_mutex);
+	return 0;
+}
+
+#if defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_ATM_MPOA_MODULE)
 EXPORT_SYMBOL(atm_lane_ops);
+EXPORT_SYMBOL(try_atm_lane_ops);
+EXPORT_SYMBOL(atm_lane_ops_set);
+#endif
 #endif
 
 #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
 #include <linux/atmmpc.h>
 #include "mpc.h"
-struct atm_mpoa_ops atm_mpoa_ops;
-#endif
+struct atm_mpoa_ops *atm_mpoa_ops;
+static DECLARE_MUTEX(atm_mpoa_ops_mutex);
+
+void atm_mpoa_ops_set(struct atm_mpoa_ops *hook)
+{
+	down(&atm_mpoa_ops_mutex);
+	atm_mpoa_ops = hook;
+	up(&atm_mpoa_ops_mutex);
+}
+
+int try_atm_mpoa_ops(void)
+{
+	down(&atm_mpoa_ops_mutex);
+	if (atm_mpoa_ops && try_inc_mod_count(atm_mpoa_ops->owner)) {
+		up(&atm_mpoa_ops_mutex);
+		return 1;
+	}
+	up(&atm_mpoa_ops_mutex);
+	return 0;
+}
 #ifdef CONFIG_ATM_MPOA_MODULE
 EXPORT_SYMBOL(atm_mpoa_ops);
-#ifndef CONFIG_ATM_LANE_MODULE
-EXPORT_SYMBOL(atm_lane_ops);
+EXPORT_SYMBOL(try_atm_mpoa_ops);
+EXPORT_SYMBOL(atm_mpoa_ops_set);
 #endif
 #endif
 
@@ -672,7 +712,8 @@
 			}
 			if (try_atm_clip_ops()) {
 				ret_val = atm_clip_ops->clip_create(arg);
-				__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
+				if (atm_clip_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
 			} else
 				ret_val = -ENOSYS;
 			goto done;
@@ -687,7 +728,8 @@
 #endif
 			if (try_atm_clip_ops()) {
 				error = atm_clip_ops->atm_init_atmarp(vcc);
-				__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
+				if (atm_clip_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
 				if (!error)
 					sock->state = SS_CONNECTED;
 				ret_val = error;
@@ -701,7 +743,8 @@
 			}
 			if (try_atm_clip_ops()) {
 				ret_val = atm_clip_ops->clip_mkip(vcc, arg);
-				__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
+				if (atm_clip_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
 			} else
 				ret_val = -ENOSYS;
 			goto done;
@@ -712,7 +755,8 @@
 			}
 			if (try_atm_clip_ops()) {
 				ret_val = atm_clip_ops->clip_setentry(vcc, arg);
-				__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
+				if (atm_clip_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
 			} else
 				ret_val = -ENOSYS;
 			goto done;
@@ -723,7 +767,8 @@
 			}
 			if (try_atm_clip_ops()) {
 				ret_val = atm_clip_ops->clip_encap(vcc, arg);
-				__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
+				if (atm_clip_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
 			} else
 				ret_val = -ENOSYS;
 			goto done;
@@ -734,27 +779,43 @@
 				ret_val = -EPERM;
 				goto done;
 			}
-                        if (atm_lane_ops.lecd_attach == NULL)
-				atm_lane_init();
-                        if (atm_lane_ops.lecd_attach == NULL) { /* try again */
+#if defined(CONFIG_ATM_LANE_MODULE)
+                        if (!atm_lane_ops)
+				request_module("lec");
+#endif
+			if (try_atm_lane_ops()) {
+				error = atm_lane_ops->lecd_attach(vcc, (int) arg);
+				if (atm_lane_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_lane_ops->owner);
+				if (error >= 0)
+					sock->state = SS_CONNECTED;
+				ret_val =  error;
+			} else
 				ret_val = -ENOSYS;
-				goto done;
-			}
-			error = atm_lane_ops.lecd_attach(vcc, (int)arg);
-			if (error >= 0) sock->state = SS_CONNECTED;
-			ret_val =  error;
 			goto done;
                 case ATMLEC_MCAST:
-			if (!capable(CAP_NET_ADMIN))
+			if (!capable(CAP_NET_ADMIN)) {
 				ret_val = -EPERM;
-			else
-				ret_val = atm_lane_ops.mcast_attach(vcc, (int)arg);
+				goto done;
+			}
+			if (try_atm_lane_ops()) {
+				ret_val = atm_lane_ops->mcast_attach(vcc, (int) arg);
+				if (atm_lane_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_lane_ops->owner);
+			} else
+				ret_val = -ENOSYS;
 			goto done;
                 case ATMLEC_DATA:
-			if (!capable(CAP_NET_ADMIN))
+			if (!capable(CAP_NET_ADMIN)) {
 				ret_val = -EPERM;
-			else
-				ret_val = atm_lane_ops.vcc_attach(vcc, (void*)arg);
+				goto done;
+			}
+			if (try_atm_lane_ops()) {
+				ret_val = atm_lane_ops->vcc_attach(vcc, (void *) arg);
+				if (atm_lane_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_lane_ops->owner);
+			} else
+				ret_val = -ENOSYS;
 			goto done;
 #endif
 #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
@@ -763,21 +824,31 @@
 				ret_val = -EPERM;
 				goto done;
 			}
-			if (atm_mpoa_ops.mpoad_attach == NULL)
-                                atm_mpoa_init();
-			if (atm_mpoa_ops.mpoad_attach == NULL) { /* try again */
+#if defined(CONFIG_ATM_MPOA_MODULE)
+			if (!atm_mpoa_ops)
+                                request_module("mpoa");
+#endif
+			if (try_atm_mpoa_ops()) {
+				error = atm_mpoa_ops->mpoad_attach(vcc, (int) arg);
+				if (atm_mpoa_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_mpoa_ops->owner);
+				if (error >= 0)
+					sock->state = SS_CONNECTED;
+				ret_val = error;
+			} else
 				ret_val = -ENOSYS;
-				goto done;
-			}
-			error = atm_mpoa_ops.mpoad_attach(vcc, (int)arg);
-			if (error >= 0) sock->state = SS_CONNECTED;
-			ret_val = error;
 			goto done;
 		case ATMMPC_DATA:
-			if (!capable(CAP_NET_ADMIN)) 
+			if (!capable(CAP_NET_ADMIN)) {
 				ret_val = -EPERM;
-			else
-				ret_val = atm_mpoa_ops.vcc_attach(vcc, arg);
+				goto done;
+			}
+			if (try_atm_mpoa_ops()) {
+				ret_val = atm_mpoa_ops->vcc_attach(vcc, arg);
+				if (atm_mpoa_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_mpoa_ops->owner);
+			} else
+				ret_val = -ENOSYS;
 			goto done;
 #endif
 #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
@@ -1162,40 +1233,6 @@
 }
 
 
-/*
- * lane_mpoa_init.c: A couple of helper functions
- * to make modular LANE and MPOA client easier to implement
- */
-
-/*
- * This is how it goes:
- *
- * if xxxx is not compiled as module, call atm_xxxx_init_ops()
- *    from here
- * else call atm_mpoa_init_ops() from init_module() within
- *    the kernel when xxxx module is loaded
- *
- * In either case function pointers in struct atm_xxxx_ops
- * are initialized to their correct values. Either they
- * point to functions in the module or in the kernel
- */
- 
-extern struct atm_mpoa_ops atm_mpoa_ops; /* in common.c */
-extern struct atm_lane_ops atm_lane_ops; /* in common.c */
-
-#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
-void atm_mpoa_init(void)
-{
-#ifndef CONFIG_ATM_MPOA_MODULE /* not module */
-        atm_mpoa_init_ops(&atm_mpoa_ops);
-#else
-	request_module("mpoa");
-#endif
-
-        return;
-}
-#endif
-
 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
 struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
@@ -1206,18 +1243,8 @@
 EXPORT_SYMBOL(br_fdb_put_hook);
 #endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */
 #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
+#endif /* defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) */
 
-void atm_lane_init(void)
-{
-#ifndef CONFIG_ATM_LANE_MODULE /* not module */
-        atm_lane_init_ops(&atm_lane_ops);
-#else
-	request_module("lec");
-#endif
-
-        return;
-}        
-#endif
 
 static int __init atm_init(void)
 {
diff -urN linux-2.4.23-pre3/net/atm/lec.c linux-2.4.23-pre4/net/atm/lec.c
--- linux-2.4.23-pre3/net/atm/lec.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/net/atm/lec.c	2003-09-12 12:44:40.000000000 -0700
@@ -11,6 +11,7 @@
 /* We are ethernet device */
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
 #include <linux/etherdevice.h>
 #include <net/sock.h>
 #include <linux/skbuff.h>
@@ -57,8 +58,6 @@
 	unsigned char *addr);
 extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
 
-static spinlock_t lec_arp_spinlock = SPIN_LOCK_UNLOCKED;
-
 #define DUMP_PACKETS 0 /* 0 = None,
                         * 1 = 30 first bytes
                         * 2 = Whole packet
@@ -72,9 +71,9 @@
 static int lec_close(struct net_device *dev);
 static struct net_device_stats *lec_get_stats(struct net_device *dev);
 static void lec_init(struct net_device *dev);
-static __inline__ struct lec_arp_table* lec_arp_find(struct lec_priv *priv,
+static inline struct lec_arp_table* lec_arp_find(struct lec_priv *priv,
                                                      unsigned char *mac_addr);
-static __inline__ int lec_arp_remove(struct lec_arp_table **lec_arp_tables,
+static inline int lec_arp_remove(struct lec_priv *priv,
 				     struct lec_arp_table *to_remove);
 /* LANE2 functions */
 static void lane2_associate_ind (struct net_device *dev, u8 *mac_address,
@@ -96,8 +95,18 @@
 static struct net_device *dev_lec[MAX_LEC_ITF];
 
 /* This will be called from proc.c via function pointer */
-struct net_device **get_dev_lec (void) {
-        return &dev_lec[0];
+struct net_device *get_dev_lec(int itf)
+{
+	struct net_device *dev;
+
+	if (itf >= MAX_LEC_ITF)
+		return NULL;
+	rtnl_lock();
+	dev = dev_lec[itf];
+	if (dev)
+		dev_hold(dev);
+	rtnl_unlock();
+	return dev;
 }
 
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
@@ -433,7 +442,7 @@
                 break;
         case l_narp_req: /* LANE2: see 7.1.35 in the lane2 spec */
                 entry = lec_arp_find(priv, mesg->content.normal.mac_addr);
-                lec_arp_remove(priv->lec_arp_tables, entry);
+                lec_arp_remove(priv, entry);
 
                 if (mesg->content.normal.no_source_le_narp)
                         break;
@@ -834,37 +843,28 @@
         return i;
 }
 
-void atm_lane_init_ops(struct atm_lane_ops *ops)
+static struct atm_lane_ops __atm_lane_ops = 
 {
-        ops->lecd_attach = lecd_attach;
-        ops->mcast_attach = lec_mcast_attach;
-        ops->vcc_attach = lec_vcc_attach;
-        ops->get_lecs = get_dev_lec;
-
-        printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
-
-	return;
-}
+	.lecd_attach =	lecd_attach,
+	.mcast_attach =	lec_mcast_attach,
+	.vcc_attach = 	lec_vcc_attach,
+	.get_lec = 	get_dev_lec,
+	.owner = 	THIS_MODULE
+};
 
 static int __init lane_module_init(void)
 {
-        extern struct atm_lane_ops atm_lane_ops;
-
-        atm_lane_init_ops(&atm_lane_ops);
-
+        atm_lane_ops_set(&__atm_lane_ops);
+        printk("lec.c: " __DATE__ " " __TIME__ " initialized\n");
         return 0;
 }
 
 static void __exit lane_module_cleanup(void)
 {
         int i;
-        extern struct atm_lane_ops atm_lane_ops;
         struct lec_priv *priv;
 
-        atm_lane_ops.lecd_attach = NULL;
-        atm_lane_ops.mcast_attach = NULL;
-        atm_lane_ops.vcc_attach = NULL;
-        atm_lane_ops.get_lecs = NULL;
+        atm_lane_ops_set(NULL);
 
         for (i = 0; i < MAX_LEC_ITF; i++) {
                 if (dev_lec[i] != NULL) {
@@ -874,7 +874,7 @@
                         	unregister_trdev(dev_lec[i]);
                 	else
 #endif
-                        unregister_netdev(dev_lec[i]);
+				unregister_netdev(dev_lec[i]);
                         kfree(dev_lec[i]);
                         dev_lec[i] = NULL;
                 }
@@ -1074,6 +1074,7 @@
         for (i=0;i<LEC_ARP_TABLE_SIZE;i++) {
                 priv->lec_arp_tables[i] = NULL;
         }        
+	spin_lock_init(&priv->lec_arp_lock);
         init_timer(&priv->lec_arp_timer);
         priv->lec_arp_timer.expires = jiffies+LEC_ARP_REFRESH_INTERVAL;
         priv->lec_arp_timer.data = (unsigned long)priv;
@@ -1110,21 +1111,20 @@
  * Insert entry to lec_arp_table
  * LANE2: Add to the end of the list to satisfy 8.1.13
  */
-static __inline__ void 
-lec_arp_add(struct lec_arp_table **lec_arp_tables, 
-            struct lec_arp_table *to_add)
+static inline void 
+lec_arp_add(struct lec_priv *priv, struct lec_arp_table *to_add)
 {
         unsigned long flags;
         unsigned short place;
         struct lec_arp_table *tmp;
 
-        spin_lock_irqsave(&lec_arp_spinlock, flags);
+        spin_lock_irqsave(&priv->lec_arp_lock, flags);
 
         place = HASH(to_add->mac_addr[ETH_ALEN-1]);
-        tmp = lec_arp_tables[place];
+        tmp = priv->lec_arp_tables[place];
         to_add->next = NULL;
         if (tmp == NULL)
-                lec_arp_tables[place] = to_add;
+                priv->lec_arp_tables[place] = to_add;
   
         else {  /* add to the end */
                 while (tmp->next)
@@ -1132,7 +1132,7 @@
                 tmp->next = to_add;
         }
 
-        spin_unlock_irqrestore(&lec_arp_spinlock, flags);
+        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 
         DPRINTK("LEC_ARP: Added entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
                 0xff&to_add->mac_addr[0], 0xff&to_add->mac_addr[1],
@@ -1143,8 +1143,8 @@
 /*
  * Remove entry from lec_arp_table
  */
-static __inline__ int 
-lec_arp_remove(struct lec_arp_table **lec_arp_tables,
+static inline int 
+lec_arp_remove(struct lec_priv *priv,
                struct lec_arp_table *to_remove)
 {
         unsigned long flags;
@@ -1152,22 +1152,22 @@
         struct lec_arp_table *tmp;
         int remove_vcc=1;
 
-        spin_lock_irqsave(&lec_arp_spinlock, flags);
+        spin_lock_irqsave(&priv->lec_arp_lock, flags);
 
         if (!to_remove) {
-                spin_unlock_irqrestore(&lec_arp_spinlock, flags);
+                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                 return -1;
         }
         place = HASH(to_remove->mac_addr[ETH_ALEN-1]);
-        tmp = lec_arp_tables[place];
+        tmp = priv->lec_arp_tables[place];
         if (tmp == to_remove) {
-                lec_arp_tables[place] = tmp->next;
+                priv->lec_arp_tables[place] = tmp->next;
         } else {
                 while(tmp && tmp->next != to_remove) {
                         tmp = tmp->next;
                 }
                 if (!tmp) {/* Entry was not found */
-                        spin_unlock_irqrestore(&lec_arp_spinlock, flags);
+                        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                         return -1;
                 }
         }
@@ -1181,7 +1181,7 @@
                  * ESI_FLUSH_PENDING, ESI_FORWARD_DIRECT
                  */
                 for(place=0;place<LEC_ARP_TABLE_SIZE;place++) {
-                        for(tmp=lec_arp_tables[place];tmp!=NULL;tmp=tmp->next){
+                        for(tmp = priv->lec_arp_tables[place]; tmp != NULL; tmp = tmp->next) {
                                 if (memcmp(tmp->atm_addr, to_remove->atm_addr,
                                            ATM_ESA_LEN)==0) {
                                         remove_vcc=0;
@@ -1194,7 +1194,7 @@
         }
         skb_queue_purge(&to_remove->tx_wait); /* FIXME: good place for this? */
 
-        spin_unlock_irqrestore(&lec_arp_spinlock, flags);
+        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
 
         DPRINTK("LEC_ARP: Removed entry:%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
                 0xff&to_remove->mac_addr[0], 0xff&to_remove->mac_addr[1],
@@ -1390,7 +1390,7 @@
         for (i=0;i<LEC_ARP_TABLE_SIZE;i++) {
                 for(entry =priv->lec_arp_tables[i];entry != NULL; entry=next) {
                         next = entry->next;
-                        lec_arp_remove(priv->lec_arp_tables, entry);
+                        lec_arp_remove(priv, entry);
                         kfree(entry);
                 }
         }
@@ -1430,7 +1430,7 @@
 /* 
  * Find entry by mac_address
  */
-static __inline__ struct lec_arp_table*
+static inline struct lec_arp_table*
 lec_arp_find(struct lec_priv *priv,
              unsigned char *mac_addr)
 {
@@ -1568,8 +1568,6 @@
 lec_arp_check_expire(unsigned long data)
 {
         struct lec_priv *priv = (struct lec_priv *)data;
-        struct lec_arp_table **lec_arp_tables =
-                (struct lec_arp_table **)priv->lec_arp_tables;
         struct lec_arp_table *entry, *next;
         unsigned long now;
         unsigned long time_to_check;
@@ -1585,7 +1583,7 @@
                 lec_arp_get(priv);
                 now = jiffies;
                 for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
-                        for(entry = lec_arp_tables[i];entry != NULL;) {
+                        for(entry = priv->lec_arp_tables[i]; entry != NULL; ) {
                                 if ((entry->flags) & LEC_REMOTE_FLAG && 
                                     priv->topology_change)
                                         time_to_check=priv->forward_delay_time;
@@ -1601,7 +1599,7 @@
                                         /* Remove entry */
                                         DPRINTK("LEC:Entry timed out\n");
                                         next = entry->next;      
-                                        lec_arp_remove(lec_arp_tables, entry);
+                                        lec_arp_remove(priv, entry);
                                         kfree(entry);
                                         entry = next;
                                 } else {
@@ -1690,7 +1688,7 @@
                 if (!entry) {
                         return priv->mcast_vcc;
                 }
-                lec_arp_add(priv->lec_arp_tables, entry);
+                lec_arp_add(priv, entry);
                 /* We want arp-request(s) to be sent */
                 entry->packets_flooded =1;
                 entry->status = ESI_ARP_PENDING;
@@ -1723,7 +1721,7 @@
                         if (!memcmp(atm_addr, entry->atm_addr, ATM_ESA_LEN)
                             && (permanent || 
                                 !(entry->flags & LEC_PERMANENT_FLAG))) {
-                                lec_arp_remove(priv->lec_arp_tables, entry);
+                                lec_arp_remove(priv, entry);
                                 kfree(entry);
                         }
                         lec_arp_put(priv);
@@ -1789,7 +1787,7 @@
                                 entry->status = ESI_FORWARD_DIRECT;
                                 memcpy(entry->mac_addr, mac_addr, ETH_ALEN);
                                 entry->last_used = jiffies;
-                                lec_arp_add(priv->lec_arp_tables, entry);
+                                lec_arp_add(priv, entry);
                         }
                         if (remoteflag)
                                 entry->flags|=LEC_REMOTE_FLAG;
@@ -1809,7 +1807,7 @@
                         return;
                 }
                 entry->status = ESI_UNKNOWN;
-                lec_arp_add(priv->lec_arp_tables, entry);
+                lec_arp_add(priv, entry);
                 /* Temporary, changes before end of function */
         }
         memcpy(entry->atm_addr, atm_addr, ATM_ESA_LEN);
@@ -2056,7 +2054,7 @@
         to_add->old_push = vcc->push;
         vcc->push = lec_push;
         priv->mcast_vcc = vcc;
-        lec_arp_add(priv->lec_arp_tables, to_add);
+        lec_arp_add(priv, to_add);
         lec_arp_put(priv);
         return 0;
 }
@@ -2074,7 +2072,7 @@
                 for(entry = priv->lec_arp_tables[i];entry; entry=next) {
                         next = entry->next;
                         if (vcc == entry->vcc) {
-                                lec_arp_remove(priv->lec_arp_tables,entry);
+                                lec_arp_remove(priv, entry);
                                 kfree(entry);
                                 if (priv->mcast_vcc == vcc) {
                                         priv->mcast_vcc = NULL;
@@ -2154,23 +2152,23 @@
         lec_arp_get(priv);
         entry = priv->lec_arp_empty_ones;
         if (vcc == entry->vcc) {
-		spin_lock_irqsave(&lec_arp_spinlock, flags);
+		spin_lock_irqsave(&priv->lec_arp_lock, flags);
                 del_timer(&entry->timer);
                 memcpy(entry->mac_addr, src, ETH_ALEN);
                 entry->status = ESI_FORWARD_DIRECT;
                 entry->last_used = jiffies;
                 priv->lec_arp_empty_ones = entry->next;
-                spin_unlock_irqrestore(&lec_arp_spinlock, flags);
+                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                 /* We might have got an entry */
                 if ((prev=lec_arp_find(priv,src))) {
-                        lec_arp_remove(priv->lec_arp_tables, prev);
+                        lec_arp_remove(priv, prev);
                         kfree(prev);
                 }
-                lec_arp_add(priv->lec_arp_tables, entry);
+                lec_arp_add(priv, entry);
                 lec_arp_put(priv);
                 return;
         }
-        spin_lock_irqsave(&lec_arp_spinlock, flags);
+        spin_lock_irqsave(&priv->lec_arp_lock, flags);
         prev = entry;
         entry = entry->next;
         while (entry && entry->vcc != vcc) {
@@ -2180,7 +2178,7 @@
         if (!entry) {
                 DPRINTK("LEC_ARP: Arp_check_empties: entry not found!\n");
                 lec_arp_put(priv);
-                spin_unlock_irqrestore(&lec_arp_spinlock, flags);
+                spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
                 return;
         }
         del_timer(&entry->timer);
@@ -2188,12 +2186,12 @@
         entry->status = ESI_FORWARD_DIRECT;
         entry->last_used = jiffies;
         prev->next = entry->next;
-        spin_unlock_irqrestore(&lec_arp_spinlock, flags);
+        spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
         if ((prev = lec_arp_find(priv, src))) {
-                lec_arp_remove(priv->lec_arp_tables,prev);
+                lec_arp_remove(priv, prev);
                 kfree(prev);
         }
-        lec_arp_add(priv->lec_arp_tables,entry);
+        lec_arp_add(priv, entry);
         lec_arp_put(priv);  
 }
 MODULE_LICENSE("GPL");
diff -urN linux-2.4.23-pre3/net/atm/lec.h linux-2.4.23-pre4/net/atm/lec.h
--- linux-2.4.23-pre3/net/atm/lec.h	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/net/atm/lec.h	2003-09-12 12:44:40.000000000 -0700
@@ -64,7 +64,8 @@
         int (*lecd_attach)(struct atm_vcc *vcc, int arg);
         int (*mcast_attach)(struct atm_vcc *vcc, int arg);
         int (*vcc_attach)(struct atm_vcc *vcc, void *arg);
-        struct net_device **(*get_lecs)(void);
+        struct net_device * (*get_lec)(int itf);
+        struct module *owner;
 };
 
 /*
@@ -102,6 +103,7 @@
            collects all those VCCs. LANEv1 client has only one item in this
            list. These entries are not aged out. */
         atomic_t lec_arp_users;
+        spinlock_t lec_arp_lock;
         struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */
         struct atm_vcc *lecd;
         struct timer_list lec_arp_timer;
@@ -148,14 +150,16 @@
 int lecd_attach(struct atm_vcc *vcc, int arg);
 int lec_vcc_attach(struct atm_vcc *vcc, void *arg);
 int lec_mcast_attach(struct atm_vcc *vcc, int arg);
-struct net_device **get_dev_lec(void);
+struct net_device *get_dev_lec(int itf);
 int make_lec(struct atm_vcc *vcc);
 int send_to_lecd(struct lec_priv *priv,
                  atmlec_msg_type type, unsigned char *mac_addr,
                  unsigned char *atm_addr, struct sk_buff *data);
 void lec_push(struct atm_vcc *vcc, struct sk_buff *skb);
 
-void atm_lane_init(void);
-void atm_lane_init_ops(struct atm_lane_ops *ops);
+extern struct atm_lane_ops *atm_lane_ops;
+void atm_lane_ops_set(struct atm_lane_ops *hook);
+int try_atm_lane_ops(void);
+
 #endif /* _LEC_H_ */
 
diff -urN linux-2.4.23-pre3/net/atm/mpc.c linux-2.4.23-pre4/net/atm/mpc.c
--- linux-2.4.23-pre3/net/atm/mpc.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/net/atm/mpc.c	2003-09-12 12:44:40.000000000 -0700
@@ -251,12 +251,14 @@
 
 static struct net_device *find_lec_by_itfnum(int itf)
 {
-	extern struct atm_lane_ops atm_lane_ops; /* in common.c */
-	
-	if (atm_lane_ops.get_lecs == NULL)
+	struct net_device *dev;
+	if (!try_atm_lane_ops())
 		return NULL;
 
-	return atm_lane_ops.get_lecs()[itf]; /* FIXME: something better */
+	dev = atm_lane_ops->get_lec(itf);
+	if (atm_lane_ops->owner)
+		__MOD_DEC_USE_COUNT(atm_lane_ops->owner);
+	return dev;
 }
 
 static struct mpoa_client *alloc_mpc(void)
@@ -777,9 +779,10 @@
 
 	if (mpc->dev) { /* check if the lec is LANE2 capable */
 		priv = (struct lec_priv *)mpc->dev->priv;
-		if (priv->lane_version < 2)
+		if (priv->lane_version < 2) {
+			dev_put(mpc->dev);
 			mpc->dev = NULL;
-		else
+		} else
 			priv->lane2_ops->associate_indicator = lane2_assoc_ind;  
 	}
 
@@ -837,6 +840,7 @@
 		struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv;
 		priv->lane2_ops->associate_indicator = NULL;
 		stop_mpc(mpc);
+		dev_put(mpc->dev);
 	}
 
 	mpc->in_ops->destroy_cache(mpc);
@@ -973,6 +977,7 @@
 		}
 		mpc->dev_num = priv->itfnum;
 		mpc->dev = dev;
+		dev_hold(dev);
 		dprintk("mpoa: (%s) was initialized\n", dev->name);
 		break;
 	case NETDEV_UNREGISTER:
@@ -982,6 +987,7 @@
 			break;
 		dprintk("mpoa: device (%s) was deallocated\n", dev->name);
 		stop_mpc(mpc);
+		dev_put(mpc->dev);
 		mpc->dev = NULL;
 		break;
 	case NETDEV_UP:
@@ -1391,13 +1397,18 @@
 	return;
 }
 
-void atm_mpoa_init_ops(struct atm_mpoa_ops *ops)
+static struct atm_mpoa_ops __atm_mpoa_ops = {
+	.mpoad_attach =	atm_mpoa_mpoad_attach,
+	.vcc_attach =	atm_mpoa_vcc_attach,
+	.owner = THIS_MODULE
+};
+
+static __init int atm_mpoa_init(void)
 {
-	ops->mpoad_attach = atm_mpoa_mpoad_attach;
-	ops->vcc_attach = atm_mpoa_vcc_attach;
+	atm_mpoa_ops_set(&__atm_mpoa_ops);
 
 #ifdef CONFIG_PROC_FS
-	if(mpc_proc_init() != 0)
+	if (mpc_proc_init() != 0)
 		printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");
 	else
 		printk(KERN_INFO "mpoa: /proc/mpoa initialized\n");
@@ -1405,22 +1416,11 @@
 
 	printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
 
-	return;
-}
-
-#ifdef MODULE
-int init_module(void)
-{
-	extern struct atm_mpoa_ops atm_mpoa_ops;
-
-	atm_mpoa_init_ops(&atm_mpoa_ops);
-
 	return 0;
 }
 
-void cleanup_module(void)
+void __exit atm_mpoa_cleanup(void)
 {
-	extern struct atm_mpoa_ops atm_mpoa_ops;
 	struct mpoa_client *mpc, *tmp;
 	struct atm_mpoa_qos *qos, *nextqos;
 	struct lec_priv *priv;
@@ -1435,8 +1435,7 @@
 
 	del_timer(&mpc_timer);
 	unregister_netdevice_notifier(&mpoa_notifier);
-	atm_mpoa_ops.mpoad_attach = NULL;
-	atm_mpoa_ops.vcc_attach = NULL;
+	atm_mpoa_ops_set(NULL);
 
 	mpc = mpcs;
 	mpcs = NULL;
@@ -1471,5 +1470,8 @@
 
 	return;
 }
-#endif /* MODULE */
+
+module_init(atm_mpoa_init);
+module_exit(atm_mpoa_cleanup);
+
 MODULE_LICENSE("GPL");
diff -urN linux-2.4.23-pre3/net/atm/mpc.h linux-2.4.23-pre4/net/atm/mpc.h
--- linux-2.4.23-pre3/net/atm/mpc.h	2000-12-11 13:33:43.000000000 -0800
+++ linux-2.4.23-pre4/net/atm/mpc.h	2003-09-12 12:44:40.000000000 -0700
@@ -48,11 +48,13 @@
 struct atm_mpoa_ops {
         int (*mpoad_attach)(struct atm_vcc *vcc, int arg);  /* attach mpoa daemon  */
         int (*vcc_attach)(struct atm_vcc *vcc, long arg);   /* attach shortcut vcc */
+	struct module *owner;
 };
 
 /* Boot/module initialization function */
-void atm_mpoa_init(void);
-void atm_mpoa_init_ops(struct atm_mpoa_ops *ops);
+extern struct atm_mpoa_ops *atm_mpoa_ops;
+int try_atm_mpoa_ops(void);
+void atm_mpoa_ops_set(struct atm_mpoa_ops *hook);
 
 /* MPOA QoS operations */
 struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos);
diff -urN linux-2.4.23-pre3/net/atm/proc.c linux-2.4.23-pre4/net/atm/proc.c
--- linux-2.4.23-pre3/net/atm/proc.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/net/atm/proc.c	2003-09-12 12:44:40.000000000 -0700
@@ -47,7 +47,6 @@
 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
 #include "lec.h"
 #include "lec_arpc.h"
-extern struct atm_lane_ops atm_lane_ops; /* in common.c */
 #endif
 
 static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count,
@@ -358,7 +357,7 @@
 				spin_unlock_irqrestore(&dev->lock, flags);
 				spin_unlock(&atm_dev_lock);
 #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
-				if (clip_info)
+				if (clip_info && atm_clip_ops->owner)
 					__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
 #endif
 				return strlen(buf);
@@ -367,8 +366,8 @@
 	}
 	spin_unlock(&atm_dev_lock);
 #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
-	if (clip_info)
-		__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
+	if (clip_info && atm_clip_ops->owner)
+			__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
 #endif
 	return 0;
 }
@@ -458,7 +457,8 @@
 				if (--count) continue;
 				atmarp_info(n->dev,entry,NULL,buf);
 				read_unlock_bh(&clip_tbl_hook->lock);
-				__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
+				if (atm_clip_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
 				return strlen(buf);
 			}
 			for (vcc = entry->vccs; vcc;
@@ -466,12 +466,14 @@
 				if (--count) continue;
 				atmarp_info(n->dev,entry,vcc,buf);
 				read_unlock_bh(&clip_tbl_hook->lock);
-				__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
+				if (atm_clip_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
 				return strlen(buf);
 			}
 		}
 	read_unlock_bh(&clip_tbl_hook->lock);
-	__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
+	if (atm_clip_ops->owner)
+		__MOD_DEC_USE_COUNT(atm_clip_ops->owner);
 	return 0;
 }
 #endif
@@ -479,57 +481,77 @@
 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
 static int atm_lec_info(loff_t pos,char *buf)
 {
+	unsigned long flags;
 	struct lec_priv *priv;
 	struct lec_arp_table *entry;
 	int i, count, d, e;
-	struct net_device **dev_lec;
+	struct net_device *dev;
 
 	if (!pos) {
 		return sprintf(buf,"Itf  MAC          ATM destination"
 		    "                          Status            Flags "
 		    "VPI/VCI Recv VPI/VCI\n");
 	}
-	if (atm_lane_ops.get_lecs == NULL)
+	if (!try_atm_lane_ops())
 		return 0; /* the lane module is not there yet */
-	else
-		dev_lec = atm_lane_ops.get_lecs();
 
 	count = pos;
-	for(d=0;d<MAX_LEC_ITF;d++) {
-		if (!dev_lec[d] || !(priv =
-		    (struct lec_priv *) dev_lec[d]->priv)) continue;
-		for(i=0;i<LEC_ARP_TABLE_SIZE;i++) {
-			entry = priv->lec_arp_tables[i];
-			for(;entry;entry=entry->next) {
-				if (--count) continue;
-				e=sprintf(buf,"%s ",
-				    dev_lec[d]->name);
-				lec_info(entry,buf+e);
+	for(d = 0; d < MAX_LEC_ITF; d++) {
+		dev = atm_lane_ops->get_lec(d);
+		if (!dev || !(priv = (struct lec_priv *) dev->priv))
+			continue;
+		spin_lock_irqsave(&priv->lec_arp_lock, flags);
+		for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
+			for(entry = priv->lec_arp_tables[i]; entry; entry = entry->next) {
+				if (--count)
+					continue;
+				e = sprintf(buf,"%s ", dev->name);
+				lec_info(entry, buf+e);
+				spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
+				dev_put(dev);
+				if (atm_lane_ops->owner)
+					__MOD_DEC_USE_COUNT(atm_lane_ops->owner);
 				return strlen(buf);
 			}
 		}
-		for(entry=priv->lec_arp_empty_ones; entry;
-		    entry=entry->next) {
-			if (--count) continue;
-			e=sprintf(buf,"%s ",dev_lec[d]->name);
+		for(entry = priv->lec_arp_empty_ones; entry; entry = entry->next) {
+			if (--count)
+				continue;
+			e = sprintf(buf,"%s ", dev->name);
 			lec_info(entry, buf+e);
+			spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
+			dev_put(dev);
+			if (atm_lane_ops->owner)
+				__MOD_DEC_USE_COUNT(atm_lane_ops->owner);
 			return strlen(buf);
 		}
-		for(entry=priv->lec_no_forward; entry;
-		    entry=entry->next) {
-			if (--count) continue;
-			e=sprintf(buf,"%s ",dev_lec[d]->name);
+		for(entry = priv->lec_no_forward; entry; entry=entry->next) {
+			if (--count)
+				continue;
+			e = sprintf(buf,"%s ", dev->name);
 			lec_info(entry, buf+e);
+			spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
+			dev_put(dev);
+			if (atm_lane_ops->owner)
+				__MOD_DEC_USE_COUNT(atm_lane_ops->owner);
 			return strlen(buf);
 		}
-		for(entry=priv->mcast_fwds; entry;
-		    entry=entry->next) {
-			if (--count) continue;
-			e=sprintf(buf,"%s ",dev_lec[d]->name);
+		for(entry = priv->mcast_fwds; entry; entry = entry->next) {
+			if (--count)
+				continue;
+			e = sprintf(buf,"%s ", dev->name);
 			lec_info(entry, buf+e);
+			spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
+			dev_put(dev);
+			if (atm_lane_ops->owner)
+				__MOD_DEC_USE_COUNT(atm_lane_ops->owner);
 			return strlen(buf);
 		}
+		spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
+		dev_put(dev);
 	}
+	if (atm_lane_ops->owner)
+		__MOD_DEC_USE_COUNT(atm_lane_ops->owner);
 	return 0;
 }
 #endif
diff -urN linux-2.4.23-pre3/net/bridge/br_forward.c linux-2.4.23-pre4/net/bridge/br_forward.c
--- linux-2.4.23-pre3/net/bridge/br_forward.c	2002-08-02 17:39:46.000000000 -0700
+++ linux-2.4.23-pre4/net/bridge/br_forward.c	2003-09-12 12:44:40.000000000 -0700
@@ -59,6 +59,7 @@
 
 	indev = skb->dev;
 	skb->dev = to->dev;
+	skb->ip_summed = CHECKSUM_NONE;
 
 	NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
 			__br_forward_finish);
diff -urN linux-2.4.23-pre3/net/bridge/br_stp_bpdu.c linux-2.4.23-pre4/net/bridge/br_stp_bpdu.c
--- linux-2.4.23-pre3/net/bridge/br_stp_bpdu.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/net/bridge/br_stp_bpdu.c	2003-09-12 12:44:40.000000000 -0700
@@ -194,6 +194,6 @@
 	}
 
  err:
-	kfree(skb);
+	kfree_skb(skb);
 	return 0;
 }
diff -urN linux-2.4.23-pre3/net/core/wireless.c linux-2.4.23-pre4/net/core/wireless.c
--- linux-2.4.23-pre3/net/core/wireless.c	2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.23-pre4/net/core/wireless.c	2003-09-12 12:44:40.000000000 -0700
@@ -2,7 +2,7 @@
  * This file implement the Wireless Extensions APIs.
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 1997-2003 Jean Tourrilhes, All Rights Reserved.
  *
  * (As all part of the Linux kernel, this file is GPL)
  */
@@ -43,6 +43,11 @@
  *	o Turn on WE_STRICT_WRITE by default + kernel warning
  *	o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num)
  *	o Fix off-by-one in test (extra_size <= IFNAMSIZ)
+ *
+ * v6 - 9.01.03 - Jean II
+ *	o Add common spy support : iw_handler_set_spy(), wireless_spy_update()
+ *	o Add enhanced spy support : iw_handler_set_thrspy() and event.
+ *	o Add WIRELESS_EXT version display in /proc/net/wireless
  */
 
 /***************************** INCLUDES *****************************/
@@ -52,6 +57,7 @@
 #include <linux/types.h>		/* off_t */
 #include <linux/netdevice.h>		/* struct ifreq, dev_get_by_name() */
 #include <linux/rtnetlink.h>		/* rtnetlink stuff */
+#include <linux/if_arp.h>		/* ARPHRD_ETHER */
 
 #include <linux/wireless.h>		/* Pretty obvious */
 #include <net/iw_handler.h>		/* New driver API */
@@ -65,6 +71,7 @@
 /* Debuging stuff */
 #undef WE_IOCTL_DEBUG		/* Debug IOCTL API */
 #undef WE_EVENT_DEBUG		/* Debug Event dispatcher */
+#undef WE_SPY_DEBUG		/* Debug enhanced spy support */
 
 /* Options */
 #define WE_EVENT_NETLINK	/* Propagate events using rtnetlink */
@@ -72,7 +79,7 @@
 
 /************************* GLOBAL VARIABLES *************************/
 /*
- * You should not use global variables, because or re-entrancy.
+ * You should not use global variables, because of re-entrancy.
  * On our case, it's only const, so it's OK...
  */
 /*
@@ -115,11 +122,11 @@
 	/* SIOCSIWSPY */
 	{ IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0},
 	/* SIOCGIWSPY */
-	{ IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_GET_SPY, 0},
-	/* -- hole -- */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-	/* -- hole -- */
-	{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
+	{ IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0},
+	/* SIOCSIWTHRSPY */
+	{ IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0},
+	/* SIOCGIWTHRSPY */
+	{ IW_HEADER_TYPE_POINT, 0, sizeof(struct iw_thrspy), 1, 1, 0},
 	/* SIOCSIWAP */
 	{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
 	/* SIOCGIWAP */
@@ -377,9 +384,9 @@
 	struct net_device *	dev;
 
 	size = sprintf(buffer,
-		       "Inter-| sta-|   Quality        |   Discarded packets               | Missed\n"
-		       " face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon\n"
-			);
+		       "Inter-| sta-|   Quality        |   Discarded packets               | Missed | WE\n"
+		       " face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon | %d\n",
+		       WIRELESS_EXT);
 	
 	pos += size;
 	len += size;
@@ -1024,3 +1031,252 @@
 
 	return;		/* Always success, I guess ;-) */
 }
+
+/********************** ENHANCED IWSPY SUPPORT **********************/
+/*
+ * In the old days, the driver was handling spy support all by itself.
+ * Now, the driver can delegate this task to Wireless Extensions.
+ * It needs to use those standard spy iw_handler in struct iw_handler_def,
+ * push data to us via XXX and include struct iw_spy_data in its
+ * private part.
+ * One of the main advantage of centralising spy support here is that
+ * it becomes much easier to improve and extend it without having to touch
+ * the drivers. One example is the addition of the Spy-Threshold events.
+ * Note : IW_WIRELESS_SPY is defined in iw_handler.h
+ */
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : set Spy List
+ */
+int iw_handler_set_spy(struct net_device *	dev,
+		       struct iw_request_info *	info,
+		       union iwreq_data *	wrqu,
+		       char *			extra)
+{
+#ifdef IW_WIRELESS_SPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	struct sockaddr *	address = (struct sockaddr *) extra;
+
+	/* Disable spy collection while we copy the addresses.
+	 * As we don't disable interrupts, we need to do this to avoid races.
+	 * As we are the only writer, this is good enough. */
+	spydata->spy_number = 0;
+
+	/* Are there are addresses to copy? */
+	if(wrqu->data.length > 0) {
+		int i;
+
+		/* Copy addresses */
+		for(i = 0; i < wrqu->data.length; i++)
+			memcpy(spydata->spy_address[i], address[i].sa_data,
+			       ETH_ALEN);
+		/* Reset stats */
+		memset(spydata->spy_stat, 0,
+		       sizeof(struct iw_quality) * IW_MAX_SPY);
+
+#ifdef WE_SPY_DEBUG
+		printk(KERN_DEBUG "iw_handler_set_spy() :  offset %ld, spydata %p, num %d\n", dev->wireless_handlers->spy_offset, spydata, wrqu->data.length);
+		for (i = 0; i < wrqu->data.length; i++)
+			printk(KERN_DEBUG
+			       "%02X:%02X:%02X:%02X:%02X:%02X \n",
+			       spydata->spy_address[i][0],
+			       spydata->spy_address[i][1],
+			       spydata->spy_address[i][2],
+			       spydata->spy_address[i][3],
+			       spydata->spy_address[i][4],
+			       spydata->spy_address[i][5]);
+#endif	/* WE_SPY_DEBUG */
+	}
+	/* Enable addresses */
+	spydata->spy_number = wrqu->data.length;
+
+	return 0;
+#else /* IW_WIRELESS_SPY */
+	return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_SPY */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : get Spy List
+ */
+int iw_handler_get_spy(struct net_device *	dev,
+		       struct iw_request_info *	info,
+		       union iwreq_data *	wrqu,
+		       char *			extra)
+{
+#ifdef IW_WIRELESS_SPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	struct sockaddr *	address = (struct sockaddr *) extra;
+	int			i;
+
+	wrqu->data.length = spydata->spy_number;
+
+	/* Copy addresses. */
+	for(i = 0; i < spydata->spy_number; i++) 	{
+		memcpy(address[i].sa_data, spydata->spy_address[i], ETH_ALEN);
+		address[i].sa_family = AF_UNIX;
+	}
+	/* Copy stats to the user buffer (just after). */
+	if(spydata->spy_number > 0)
+		memcpy(extra  + (sizeof(struct sockaddr) *spydata->spy_number),
+		       spydata->spy_stat,
+		       sizeof(struct iw_quality) * spydata->spy_number);
+	/* Reset updated flags. */
+	for(i = 0; i < spydata->spy_number; i++)
+		spydata->spy_stat[i].updated = 0;
+	return 0;
+#else /* IW_WIRELESS_SPY */
+	return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_SPY */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : set spy threshold
+ */
+int iw_handler_set_thrspy(struct net_device *	dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *	wrqu,
+			  char *		extra)
+{
+#ifdef IW_WIRELESS_THRSPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	struct iw_thrspy *	threshold = (struct iw_thrspy *) extra;
+
+	/* Just do it */
+	memcpy(&(spydata->spy_thr_low), &(threshold->low),
+	       2 * sizeof(struct iw_quality));
+
+	/* Clear flag */
+	memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under));
+
+#ifdef WE_SPY_DEBUG
+	printk(KERN_DEBUG "iw_handler_set_thrspy() :  low %d ; high %d\n", spydata->spy_thr_low.level, spydata->spy_thr_high.level);
+#endif	/* WE_SPY_DEBUG */
+
+	return 0;
+#else /* IW_WIRELESS_THRSPY */
+	return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_THRSPY */
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Standard Wireless Handler : get spy threshold
+ */
+int iw_handler_get_thrspy(struct net_device *	dev,
+			  struct iw_request_info *info,
+			  union iwreq_data *	wrqu,
+			  char *		extra)
+{
+#ifdef IW_WIRELESS_THRSPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	struct iw_thrspy *	threshold = (struct iw_thrspy *) extra;
+
+	/* Just do it */
+	memcpy(&(threshold->low), &(spydata->spy_thr_low),
+	       2 * sizeof(struct iw_quality));
+
+	return 0;
+#else /* IW_WIRELESS_THRSPY */
+	return -EOPNOTSUPP;
+#endif /* IW_WIRELESS_THRSPY */
+}
+
+#ifdef IW_WIRELESS_THRSPY
+/*------------------------------------------------------------------*/
+/*
+ * Prepare and send a Spy Threshold event
+ */
+static void iw_send_thrspy_event(struct net_device *	dev,
+				 struct iw_spy_data *	spydata,
+				 unsigned char *	address,
+				 struct iw_quality *	wstats)
+{
+	union iwreq_data	wrqu;
+	struct iw_thrspy	threshold;
+
+	/* Init */
+	wrqu.data.length = 1;
+	wrqu.data.flags = 0;
+	/* Copy address */
+	memcpy(threshold.addr.sa_data, address, ETH_ALEN);
+	threshold.addr.sa_family = ARPHRD_ETHER;
+	/* Copy stats */
+	memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality));
+	/* Copy also thresholds */
+	memcpy(&(threshold.low), &(spydata->spy_thr_low),
+	       2 * sizeof(struct iw_quality));
+
+#ifdef WE_SPY_DEBUG
+	printk(KERN_DEBUG "iw_send_thrspy_event() : address %02X:%02X:%02X:%02X:%02X:%02X, level %d, up = %d\n",
+	       threshold.addr.sa_data[0],
+	       threshold.addr.sa_data[1],
+	       threshold.addr.sa_data[2],
+	       threshold.addr.sa_data[3],
+	       threshold.addr.sa_data[4],
+	       threshold.addr.sa_data[5], threshold.qual.level);
+#endif	/* WE_SPY_DEBUG */
+
+	/* Send event to user space */
+	wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold);
+}
+#endif /* IW_WIRELESS_THRSPY */
+
+/* ---------------------------------------------------------------- */
+/*
+ * Call for the driver to update the spy data.
+ * For now, the spy data is a simple array. As the size of the array is
+ * small, this is good enough. If we wanted to support larger number of
+ * spy addresses, we should use something more efficient...
+ */
+void wireless_spy_update(struct net_device *	dev,
+			 unsigned char *	address,
+			 struct iw_quality *	wstats)
+{
+#ifdef IW_WIRELESS_SPY
+	struct iw_spy_data *	spydata = (dev->priv +
+					   dev->wireless_handlers->spy_offset);
+	int			i;
+	int			match = -1;
+
+#ifdef WE_SPY_DEBUG
+	printk(KERN_DEBUG "wireless_spy_update() :  offset %ld, spydata %p, address %02X:%02X:%02X:%02X:%02X:%02X\n", dev->wireless_handlers->spy_offset, spydata, address[0], address[1], address[2], address[3], address[4], address[5]);
+#endif	/* WE_SPY_DEBUG */
+
+	/* Update all records that match */
+	for(i = 0; i < spydata->spy_number; i++)
+		if(!memcmp(address, spydata->spy_address[i], ETH_ALEN)) {
+			memcpy(&(spydata->spy_stat[i]), wstats,
+			       sizeof(struct iw_quality));
+			match = i;
+		}
+#ifdef IW_WIRELESS_THRSPY
+	/* Generate an event if we cross the spy threshold.
+	 * To avoid event storms, we have a simple hysteresis : we generate
+	 * event only when we go under the low threshold or above the
+	 * high threshold. */
+	if(match >= 0) {
+		if(spydata->spy_thr_under[match]) {
+			if(wstats->level > spydata->spy_thr_high.level) {
+				spydata->spy_thr_under[match] = 0;
+				iw_send_thrspy_event(dev, spydata,
+						     address, wstats);
+			}
+		} else {
+			if(wstats->level < spydata->spy_thr_low.level) {
+				spydata->spy_thr_under[match] = 1;
+				iw_send_thrspy_event(dev, spydata,
+						     address, wstats);
+			}
+		}
+	}
+#endif /* IW_WIRELESS_THRSPY */
+#endif /* IW_WIRELESS_SPY */
+}
diff -urN linux-2.4.23-pre3/net/ipv4/netfilter/ip_nat_core.c linux-2.4.23-pre4/net/ipv4/netfilter/ip_nat_core.c
--- linux-2.4.23-pre3/net/ipv4/netfilter/ip_nat_core.c	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/net/ipv4/netfilter/ip_nat_core.c	2003-09-12 12:44:40.000000000 -0700
@@ -157,8 +157,8 @@
 				continue;
 		}
 
-		if ((mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED)
-		    && proto->in_range(&newtuple, IP_NAT_MANIP_SRC,
+		if (!(mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED)
+		    || proto->in_range(&newtuple, IP_NAT_MANIP_SRC,
 				       &mr->range[i].min, &mr->range[i].max))
 			return 1;
 	}
diff -urN linux-2.4.23-pre3/net/netsyms.c linux-2.4.23-pre4/net/netsyms.c
--- linux-2.4.23-pre3/net/netsyms.c	2003-09-12 12:44:33.000000000 -0700
+++ linux-2.4.23-pre4/net/netsyms.c	2003-09-12 12:44:41.000000000 -0700
@@ -612,6 +612,11 @@
 #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
 #include <net/iw_handler.h>
 EXPORT_SYMBOL(wireless_send_event);
+EXPORT_SYMBOL(iw_handler_set_spy);
+EXPORT_SYMBOL(iw_handler_get_spy);
+EXPORT_SYMBOL(iw_handler_set_thrspy);
+EXPORT_SYMBOL(iw_handler_get_thrspy);
+EXPORT_SYMBOL(wireless_spy_update);
 #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
 
 /* ethtool.c */
diff -urN linux-2.4.23-pre3/net/sunrpc/svcsock.c linux-2.4.23-pre4/net/sunrpc/svcsock.c
--- linux-2.4.23-pre3/net/sunrpc/svcsock.c	2003-08-25 04:44:44.000000000 -0700
+++ linux-2.4.23-pre4/net/sunrpc/svcsock.c	2003-09-12 12:44:41.000000000 -0700
@@ -120,6 +120,8 @@
 	if (!(svsk->sk_flags &
 	      ( (1<<SK_CONN)|(1<<SK_DATA)|(1<<SK_CLOSE)) ))
 		return;
+	if (test_bit(SK_DEAD, &svsk->sk_flags))
+		return;
 
 	spin_lock_bh(&serv->sv_lock);
 
@@ -315,6 +317,9 @@
 	struct svc_sock	*svsk = rqstp->rq_sock;
 	struct socket	*sock = svsk->sk_sock;
 	struct msghdr	msg;
+	struct { struct cmsghdr cmh;
+		struct in_pktinfo pki;
+	} cm;
 	int		i, buflen, len;
 
 	for (i = buflen = 0; i < nr; i++)
@@ -324,8 +329,18 @@
 	msg.msg_namelen = sizeof(rqstp->rq_addr);
 	msg.msg_iov     = iov;
 	msg.msg_iovlen  = nr;
-	msg.msg_control = NULL;
-	msg.msg_controllen = 0;
+	if (rqstp->rq_prot == IPPROTO_UDP) {
+		msg.msg_control = &cm;
+		msg.msg_controllen = sizeof(cm);
+		cm.cmh.cmsg_len = sizeof(cm);
+		cm.cmh.cmsg_level = SOL_IP;
+		cm.cmh.cmsg_type = IP_PKTINFO;
+		cm.pki.ipi_ifindex = 0;
+		cm.pki.ipi_spec_dst.s_addr = rqstp->rq_daddr;
+	} else {
+		msg.msg_control = NULL;
+		msg.msg_controllen = 0;
+	}
 
 	/* This was MSG_DONTWAIT, but I now want it to wait.
 	 * The only thing that it would wait for is memory and
@@ -529,6 +544,7 @@
 	rqstp->rq_addr.sin_family = AF_INET;
 	rqstp->rq_addr.sin_port = skb->h.uh->source;
 	rqstp->rq_addr.sin_addr.s_addr = skb->nh.iph->saddr;
+	rqstp->rq_daddr = skb->nh.iph->daddr;
 
 	if (serv->sv_stats)
 		serv->sv_stats->netudpcnt++;
@@ -930,6 +946,9 @@
 	bufp->iov[0].iov_len  = bufp->len << 2;
 	bufp->base[0] = htonl(0x80000000|((bufp->len << 2) - 4));
 
+	if (test_bit(SK_DEAD, &rqstp->rq_sock->sk_flags))
+		return -ENOTCONN;
+
 	sent = svc_sendto(rqstp, bufp->iov, bufp->nriov);
 	if (sent != bufp->len<<2) {
 		printk(KERN_NOTICE "rpc-srv/tcp: %s: sent only %d bytes of %d - shutting down socket\n",
@@ -1277,6 +1296,9 @@
 
 	dprintk("svc: svc_delete_socket(%p)\n", svsk);
 
+	if (test_and_set_bit(SK_DEAD, &svsk->sk_flags))
+		return ;
+
 	serv = svsk->sk_server;
 	sk = svsk->sk_sk;
 
@@ -1293,8 +1315,6 @@
 		list_del(&svsk->sk_ready);
 
 
-	set_bit(SK_DEAD, &svsk->sk_flags);
-
 	if (!svsk->sk_inuse) {
 		spin_unlock_bh(&serv->sv_lock);
 		sock_release(svsk->sk_sock);
