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

diff -urN linux-2.4.21-bk11/Makefile linux-2.4.21-bk12/Makefile
--- linux-2.4.21-bk11/Makefile	2003-07-17 02:52:21.000000000 -0700
+++ linux-2.4.21-bk12/Makefile	2003-07-17 02:52:27.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 21
-EXTRAVERSION = -bk11
+EXTRAVERSION = -bk12
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -230,6 +230,7 @@
 # files removed with 'make mrproper'
 MRPROPER_FILES = \
 	include/linux/autoconf.h include/linux/version.h \
+	lib/crc32table.h lib/gen_crc32table \
 	drivers/net/hamradio/soundmodem/sm_tbl_{afsk1200,afsk2666,fsk9600}.h \
 	drivers/net/hamradio/soundmodem/sm_tbl_{hapn4800,psk4800}.h \
 	drivers/net/hamradio/soundmodem/sm_tbl_{afsk2400_7,afsk2400_8}.h \
diff -urN linux-2.4.21-bk11/arch/ppc/kernel/ppc4xx_pic.c linux-2.4.21-bk12/arch/ppc/kernel/ppc4xx_pic.c
--- linux-2.4.21-bk11/arch/ppc/kernel/ppc4xx_pic.c	2003-07-17 02:52:23.000000000 -0700
+++ linux-2.4.21-bk12/arch/ppc/kernel/ppc4xx_pic.c	2003-07-17 02:52:28.000000000 -0700
@@ -370,9 +370,9 @@
 		       bit, sense);
 #endif
 		ppc_cached_sense_mask[word] |=
-		    (sense & IRQ_SENSE_MASK) << (31 - bit);
+		    (~sense & IRQ_SENSE_MASK) << (31 - bit);
 		ppc_cached_pol_mask[word] |=
-		    ((~sense & IRQ_POLARITY_MASK) >> 1) << (31 - bit);
+		    ((sense & IRQ_POLARITY_MASK) >> 1) << (31 - bit);
 		switch (word) {
 		case 0:
 #ifdef PPC4xx_PIC_DEBUG
diff -urN linux-2.4.21-bk11/arch/sh/Makefile linux-2.4.21-bk12/arch/sh/Makefile
--- linux-2.4.21-bk11/arch/sh/Makefile	2001-10-15 13:36:48.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/Makefile	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.6 2000/06/10 03:03:52 gniibe Exp $
+# $Id: Makefile,v 1.1.1.1.2.2 2002/05/10 17:58:54 jzs 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
@@ -24,6 +24,14 @@
 LDFLAGS		:= -EB
 endif
 
+ifdef CONFIG_SH_KGDB
+CFLAGS :=$(CFLAGS:-fomit-frame-pointer=) -g
+AFLAGS += -g
+ifdef CONFIG_KGDB_MORE
+CFLAGS += $(shell echo $(CONFIG_KGDB_OPTIONS) | sed -e 's/"//g')
+endif
+endif
+
 LD	=$(CROSS_COMPILE)ld $(LDFLAGS)
 OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -R .stab -R .stabstr -S
 
diff -urN linux-2.4.21-bk11/arch/sh/config.in linux-2.4.21-bk12/arch/sh/config.in
--- linux-2.4.21-bk11/arch/sh/config.in	2003-07-17 02:52:24.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/config.in	2003-07-17 02:52:28.000000000 -0700
@@ -42,7 +42,10 @@
 	 CAT68701		CONFIG_SH_CAT68701		\
 	 BigSur			CONFIG_SH_BIGSUR		\
 	 SH2000			CONFIG_SH_SH2000		\
+	 HS7729PCI		CONFIG_SH_HS7729PCI		\
 	 ADX			CONFIG_SH_ADX			\
+	 SecureEdge5410		CONFIG_SH_SECUREEDGE5410	\
+	 KeyWest		CONFIG_SH_KEYWEST		\
 	 BareCPU		CONFIG_SH_UNKNOWN" Generic
 
 # The SH7750 RTC module is disabled in the Dreamcast
@@ -63,7 +66,8 @@
     SH7709 CONFIG_CPU_SUBTYPE_SH7709 \
     SH7750 CONFIG_CPU_SUBTYPE_SH7750 \
     SH7751 CONFIG_CPU_SUBTYPE_SH7751 \
-    ST40STB1 CONFIG_CPU_SUBTYPE_ST40STB1" SH7708
+    ST40RA/ST40STB1 CONFIG_CPU_SUBTYPE_ST40STB1 \
+    ST40GX1 CONFIG_CPU_SUBTYPE_ST40GX1" SH7708
 if [ "$CONFIG_CPU_SUBTYPE_SH7707" = "y" ]; then
    define_bool CONFIG_CPU_SH3 y
    define_bool CONFIG_CPU_SH4 n
@@ -87,6 +91,12 @@
 if [ "$CONFIG_CPU_SUBTYPE_ST40STB1" = "y" ]; then
    define_bool CONFIG_CPU_SH3 n
    define_bool CONFIG_CPU_SH4 y
+   define_bool CONFIG_CPU_SUBTYPE_ST40 y
+fi
+if [ "$CONFIG_CPU_SUBTYPE_ST40GX1" = "y" ]; then
+   define_bool CONFIG_CPU_SH3 n
+   define_bool CONFIG_CPU_SH4 y
+   define_bool CONFIG_CPU_SUBTYPE_ST40 y
 fi
 bool 'Little Endian' CONFIG_CPU_LITTLE_ENDIAN
 # Platform-specific memory start and size definitions
@@ -101,12 +111,13 @@
    define_bool CONFIG_MEMORY_SET y
 fi
 if [ "$CONFIG_SH_HP600" = "y" -o "$CONFIG_SH_BIGSUR" = "y" -o \
-     "$CONFIG_SH_DREAMCAST" = "y" -o "$CONFIG_SH_SH2000" = "y" ]; then
+     "$CONFIG_SH_DREAMCAST" = "y" -o "$CONFIG_SH_SH2000" = "y" -o \
+     "$CONFIG_SH_KEYWEST" = "y" ]; then
    define_hex CONFIG_MEMORY_START 0c000000
    define_hex CONFIG_MEMORY_SIZE 00400000
    define_bool CONFIG_MEMORY_SET y
 fi
-if [ "$CONFIG_CPU_SUBTYPE_ST40STB1" = "y" ]; then
+if [ "$CONFIG_CPU_SUBTYPE_ST40" = "y" ]; then
    bool 'Memory on LMI' CONFIG_ST40_LMI_MEMORY
    if [ "$CONFIG_ST40_LMI_MEMORY" = "y" ] ; then
       define_hex CONFIG_MEMORY_START 08000000
@@ -119,11 +130,29 @@
    define_hex CONFIG_MEMORY_SIZE 00400000
    define_bool CONFIG_MEMORY_SET y
 fi
+if [ "$CONFIG_SH_SECUREEDGE5410" = "y" ]; then
+   define_hex CONFIG_MEMORY_START 08000000
+   define_hex CONFIG_MEMORY_SIZE 01000000
+   define_bool CONFIG_MEMORY_SET y
+fi
+if [ "$CONFIG_SH_HS7729PCI" = "y" ]; then
+   define_hex CONFIG_MEMORY_START 0c000000
+   define_hex CONFIG_MEMORY_SIZE 04000000
+   define_bool CONFIG_MEMORY_SET y
+fi
 # If none of the above have set memory start/size, ask the user.
 if [ "$CONFIG_MEMORY_SET" != "y" ]; then
    hex 'Physical memory start address' CONFIG_MEMORY_START 08000000
    hex 'Physical memory size' CONFIG_MEMORY_SIZE 00400000
 fi
+dep_bool 'Enable OC RAM zone (experimental)' CONFIG_SCRATCH_SPACE $CONFIG_EXPERIMENTAL
+
+if [ "$CONFIG_CPU_SUBTYPE_ST40" = "y" ]; then
+   bool 'PCI emulation of on-chip peripherals' CONFIG_SH_PCI_EMULATION
+   if [ "$CONFIG_SH_PCI_EMULATION" = "y" -a "$CONFIG_CPU_SUBTYPE_ST40GX1" = "y" ]; then
+      bool '  USB OHCI Host Controller' CONFIG_SH_PCI_USB
+   fi
+fi
 endmenu
 
 if [ "$CONFIG_SH_HP690" = "y" ]; then
@@ -138,7 +167,13 @@
 # Even on SuperH devices which don't have an ISA bus,
 # this variable helps the PCMCIA modules handle
 # IRQ requesting properly -- Greg Banks.
-define_bool CONFIG_ISA y
+
+if [ "$CONFIG_SH_SECUREEDGE5410" = "y" ]; then
+   define_bool CONFIG_ISA n
+else
+   define_bool CONFIG_ISA y
+fi
+
 define_bool CONFIG_EISA n
 define_bool CONFIG_MCA n
 define_bool CONFIG_SBUS n
@@ -147,7 +182,7 @@
 
 if [ "$CONFIG_SH_GENERIC" = "y" -o "$CONFIG_SH_SOLUTION_ENGINE" = "y" -o \
      "$CONFIG_SH_UNKNOWN" = "y" -o "$CONFIG_SH_CAT68701" = "y" -o \
-     "$CONFIG_SH_ADX" = "y" ]; then
+     "$CONFIG_SH_ADX" = "y" -o "$CONFIG_SH_HS7729PCI" = "y" ]; then
   bool 'Compact Flash Enabler support' CONFIG_CF_ENABLER
 fi
 
@@ -175,21 +210,24 @@
    int 'HD64465 IRQ' CONFIG_HD64465_IRQ 5
 fi
 
+bool 'Wakeup UBC on startup' CONFIG_UBC_WAKEUP
 bool 'DMA controller (DMAC) support' CONFIG_SH_DMA
+bool 'Default bootloader kernel arguments' CONFIG_CMDLINE_BOOL
+if [ "$CONFIG_CMDLINE_BOOL" = "y" ] ; then
+  string 'Initial kernel command string' CONFIG_CMDLINE "console=ttySC1,115200"
+fi
 
 bool 'PCI support' CONFIG_PCI
 if [ "$CONFIG_PCI" = "y" ]; then
-   choice '  PCI access mode' \
-	"BIOS		CONFIG_PCI_GOBIOS	\
-	 Direct		CONFIG_PCI_GODIRECT	\
-	 Any		CONFIG_PCI_GOANY"	Any
-   if [ "$CONFIG_PCI_GOBIOS" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then
-      define_bool CONFIG_PCI_BIOS y
-   fi
-   if [ "$CONFIG_PCI_GODIRECT" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then
-      define_bool CONFIG_PCI_DIRECT y
-   fi
-   bool 'Cache and PCI noncoherent' CONFIG_SH_PCIDMA_NONCOHERENT
+  if [ "$CONFIG_SH_HS7729PCI" = "y" ]; then
+     define_bool CONFIG_PCI_SD0001 y
+     define_hex CONFIG_PCI_SD0001_IRQ 0
+     define_hex CONFIG_PCI_SD0001_BASE b0000000
+     define_bool CONFIG_SH_PCIDMA_NONCOHERENT y
+  else
+     define_bool CONFIG_PCI_SD0001 n
+     bool 'Cache and PCI noncoherent' CONFIG_SH_PCIDMA_NONCOHERENT
+  fi
 fi
 
 source drivers/pci/Config.in
@@ -259,7 +297,7 @@
    bool 'Network device support' CONFIG_NETDEVICES
    if [ "$CONFIG_NETDEVICES" = "y" ]; then
       source drivers/net/Config.in
-      if [ "$CONFIG_ATM" != "n" ]; then
+      if [ "$CONFIG_ATM" = "y" ]; then
          source drivers/atm/Config.in
       fi
    fi
@@ -280,9 +318,9 @@
 #
 source drivers/input/Config.in
 
-# if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then
-#    source drivers/maple/Config.in
-# fi
+if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then
+   source drivers/maple/Config.in
+fi
 
 mainmenu_option next_comment
 comment 'Character devices'
@@ -341,7 +379,7 @@
 bool 'Watchdog Timer Support' CONFIG_WATCHDOG
 if [ "$CONFIG_WATCHDOG" != "n" ]; then
    bool '  Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT
-   dep_tristate '  SH 3/4 Watchdog' CONFIG_SH_WDT $CONFIG_SUPERH
+   dep_tristate '  SuperH Watchdog' CONFIG_SH_WDT $CONFIG_SUPERH
 fi
 endmenu
 
@@ -385,6 +423,33 @@
 if [ "$CONFIG_SH_STANDARD_BIOS" = "y" ]; then
    bool 'Early printk support' CONFIG_SH_EARLY_PRINTK
 fi
+bool 'Include KGDB kernel debugger' CONFIG_SH_KGDB
+if [ "$CONFIG_SH_KGDB" = "y" ]; then
+   bool ' Enter KGDB on NMI' CONFIG_KGDB_NMI
+   bool ' Include KGDB thread support' CONFIG_KGDB_THREAD
+   bool ' Console messages through GDB' CONFIG_SH_KGDB_CONSOLE
+   bool ' Allow SysRq "G" to enter KGDB?' CONFIG_KGDB_SYSRQ
+   if [ "$CONFIG_KGDB_SYSRQ" != "n" ]; then
+      define_bool CONFIG_MAGIC_SYSRQ y
+   fi
+   bool ' Include KGDB kernel asserts' CONFIG_KGDB_KERNEL_ASSERTS
+   bool ' Add additional compile options' CONFIG_KGDB_MORE
+   if [ "$CONFIG_KGDB_MORE" = "y" ]; then
+      string ' Additional compile options' CONFIG_KGDB_OPTIONS "-O1"
+   fi
+   mainmenu_option next_comment
+   comment '     Default KGDB port setup'
+      int 'Port number (ttySCn)' CONFIG_KGDB_DEFPORT 1
+      int 'Baud rate' CONFIG_KGDB_DEFBAUD 115200
+      choice 'Parity' \
+         "None CONFIG_KGDB_DEFPARITY_N	\
+          Even CONFIG_KGDB_DEFPARITY_E	\
+          Odd  CONFIG_KGDB_DEFPARITY_O"	None
+      choice 'DataBits' \
+         "7 CONFIG_KGDB_DEFBITS_7	\
+          8 CONFIG_KGDB_DEFBITS_8"	8
+   endmenu
+fi
 endmenu
 
 source crypto/Config.in
diff -urN linux-2.4.21-bk11/arch/sh/kernel/Makefile linux-2.4.21-bk12/arch/sh/kernel/Makefile
--- linux-2.4.21-bk11/arch/sh/kernel/Makefile	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/Makefile	2003-07-17 02:52:28.000000000 -0700
@@ -12,40 +12,48 @@
 
 O_TARGET := kernel.o
 
-export-objs	:= io.o io_generic.o io_hd64461.o setup_hd64461.o sh_ksyms.o
+export-objs	:= io.o io_generic.o io_hd64461.o setup_hd64461.o sh_ksyms.o \
+		   dma.o
 
 obj-y	:= process.o signal.o entry.o traps.o irq.o irq_ipr.o \
 	ptrace.o setup.o time.o sys_sh.o semaphore.o \
-	irq_imask.o io.o io_generic.o sh_ksyms.o
+	irq_imask.o io.o io_generic.o sh_ksyms.o ubc.o
 
 obj-$(CONFIG_CF_ENABLER)	+= cf-enabler.o
 obj-$(CONFIG_CPU_SH4)		+= fpu.o
 obj-$(CONFIG_SH_RTC)            += rtc.o
 obj-$(CONFIG_SH_DMA)		+= dma.o
 obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o
+obj-$(CONFIG_SH_KGDB)		+= kgdb_stub.o kgdb_jmp.o
 
 ifeq ($(CONFIG_PCI),y)
 ifeq ($(CONFIG_SH_DREAMCAST),y)
 obj-y 				+= pci-dc.o pcibios.o
 else
 obj-y                           += pci-dma.o pcibios.o
-obj-$(CONFIG_CPU_SUBTYPE_ST40STB1)+= pci_st40.o
+obj-$(CONFIG_CPU_SUBTYPE_ST40)+= pci_st40.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7751)+= pci-sh7751.o 
 obj-$(CONFIG_SH_BIGSUR)+= pci-bigsur.o
 obj-$(CONFIG_SH_7751_SOLUTION_ENGINE)+= pci-7751se.o
+obj-$(CONFIG_PCI_SD0001)+= pci-sd0001.o
+obj-$(CONFIG_SH_SECUREEDGE5410)	+= pci-snapgear.o
+obj-$(CONFIG_SH_KEYWEST)	+= pci-v320usc.o
 endif
 endif
 
 obj-$(CONFIG_SH_HP600)		+= mach_hp600.o
 machine-specific-objs		+= mach_hp600.o
 
+obj-$(CONFIG_SH_HS7729PCI)	+= mach_hs7729pci.o setup_hs7729pci.o io_hs7729pci.o
+machine-specific-objs		+= mach_hs7729pci.o setup_hs7729pci.o io_hs7729pci.o
+
 obj-$(CONFIG_SH_SOLUTION_ENGINE)+= mach_se.o setup_se.o io_se.o led_se.o
 machine-specific-objs		+= mach_se.o setup_se.o io_se.o led_se.o
 
 obj-$(CONFIG_SH_7751_SOLUTION_ENGINE)+= mach_7751se.o setup_7751se.o \
-					io_7751se.o led_7751se.o
+					io_7751se.o led_se.o
 machine-specific-objs           += mach_7751se.o 7751setup_se.o \
-				   io_7751se.o led_7751se.o pci-7751se.o
+				   io_7751se.o led_se.o pci-7751se.o
 
 obj-$(CONFIG_SH_BIGSUR)		+= mach_bigsur.o setup_bigsur.o io_bigsur.o led_bigsur.o
 machine-specific-objs		+= mach_bigsur.o setup_bigsur.o io_bigsur.o led_bigsur.o
@@ -65,11 +73,21 @@
 obj-$(CONFIG_HD64461)		+= setup_hd64461.o io_hd64461.o
 machine-specific-objs		+= setup_hd64461.o io_hd64461.o
 
-obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) +=irq_intc2.o
+obj-$(CONFIG_CPU_SUBTYPE_ST40) +=irq_intc2.o
 
 obj-$(CONFIG_SH_ADX)		+= mach_adx.o setup_adx.o io_adx.o irq_maskreg.o
 machine-specific-objs		+= mach_adx.o setup_adx.o io_adx.o irq_maskreg.o
 
+obj-$(CONFIG_SH_SECUREEDGE5410)	+= mach_snapgear.o setup_snapgear.o io_snapgear.o
+machine-specific-objs		+= mach_snapgear.o setup_snapgear.o io_snapgear.o
+ifeq ($(CONFIG_RTC),y)
+obj-$(CONFIG_SH_SECUREEDGE5410)	+= rtc-snapgear.o
+machine-specific-objs		+= rtc-snapgear.o
+endif
+
+obj-$(CONFIG_SH_KEYWEST)	+= mach_keywest.o setup_keywest.o io_keywest.o
+machine-specific-objs		+= mach_keywest.o setup_keywest.o io_keywest.o
+
 # Doesn't compile well, so don't include in machine-specific-objs
 obj-$(CONFIG_HD64465)		+= setup_hd64465.o io_hd64465.o hd64465_gpio.o
 obj-$(CONFIG_SH_DMIDA)		+= mach_dmida.o
diff -urN linux-2.4.21-bk11/arch/sh/kernel/cf-enabler.c linux-2.4.21-bk12/arch/sh/kernel/cf-enabler.c
--- linux-2.4.21-bk11/arch/sh/kernel/cf-enabler.c	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/cf-enabler.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: cf-enabler.c,v 1.8 2001/07/18 12:32:21 gniibe Exp $
+/* $Id: cf-enabler.c,v 1.1.1.1.2.1 2003/06/24 08:52:51 dwmw2 Exp $
  *
  *  linux/drivers/block/cf-enabler.c
  *
@@ -11,7 +11,7 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
-
+#include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
@@ -87,7 +87,7 @@
 	return 0;
 }
 
-#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_SOLUTION_ENGINE)
+#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_SOLUTION_ENGINE) || defined(CONFIG_SH_HS7729PCI)
 #include <asm/hitachi_se.h>
 
 /*
@@ -142,15 +142,31 @@
 	ctrl_outw(0x2000, MRSHPC_ICR);
 	ctrl_outb(0x00, PA_MRSHPC_MW2 + 0x206);
 	ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200);
+
+	if (MACH_HS7729PCI) {
+		/* Empirical evidence shows that we have to delay for
+		   ten milliseconds and then redo the last outb. 
+		   I have no clue why. And all the docs are in Japanese
+		   so I feel no shame in just doing it this way. Besides,
+		   all this is just a crap hack for the fact that we don't
+		   have sensible userspace-less PCMCIA support in 2.4.
+
+		   dwmw2.
+		 */
+		mdelay(10);
+		ctrl_outb(0x42, PA_MRSHPC_MW2 + 0x200);
+	}
+
 	return 0;
 }
 #endif
 
 int __init cf_init(void)
 {
-#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_SOLUTION_ENGINE)
-	if (MACH_SE)
+#if defined(CONFIG_SH_GENERIC) || defined(CONFIG_SH_SOLUTION_ENGINE) || defined(CONFIG_SH_HS7729PCI)
+	if (MACH_SE || MACH_HS7729PCI) {
 		return cf_init_se();
+	}
 #endif
 	return cf_init_default();
 }
diff -urN linux-2.4.21-bk11/arch/sh/kernel/dma.c linux-2.4.21-bk12/arch/sh/kernel/dma.c
--- linux-2.4.21-bk11/arch/sh/kernel/dma.c	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/dma.c	2003-07-17 02:52:28.000000000 -0700
@@ -10,6 +10,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 
 #include <asm/signal.h>
 #include <asm/dma.h>
@@ -137,6 +138,25 @@
 	return 0;
 }
 
+static void __exit exit_dma(void)
+{
+#ifdef CONFIG_CPU_SH4
+	free_irq(DMAE_IRQ);
+#endif
+}
+
 module_init(init_dma);
+module_exit(exit_dma);
+
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(setup_dma);
+EXPORT_SYMBOL(claim_dma_lock);
+EXPORT_SYMBOL(release_dma_lock);
+EXPORT_SYMBOL(enable_dma);
+EXPORT_SYMBOL(disable_dma);
+EXPORT_SYMBOL(set_dma_mode);
+EXPORT_SYMBOL(set_dma_addr);
+EXPORT_SYMBOL(set_dma_count);
+EXPORT_SYMBOL(get_dma_residue);
 
-/**/
diff -urN linux-2.4.21-bk11/arch/sh/kernel/entry.S linux-2.4.21-bk12/arch/sh/kernel/entry.S
--- linux-2.4.21-bk11/arch/sh/kernel/entry.S	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/entry.S	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.71 2001/07/27 11:47:50 gniibe Exp $
+/* $Id: entry.S,v 1.1.1.1.2.15 2003/07/09 09:59:30 trent Exp $
  *
  *  linux/arch/sh/entry.S
  *
@@ -15,12 +15,6 @@
 #include <linux/config.h>
 
 
-/*
- * Define this to turn on compatibility with the previous
- * system call ABI.  This feature is not properly maintained.
- */
-#undef COMPAT_OLD_SYSCALL_ABI
-
 ! NOTE:
 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
 ! to be jumped is too far, but it causes illegal slot exception.
@@ -38,6 +32,12 @@
  *
  *    jmp	@k0	    ! control-transfer instruction
  *     ldc	k1, ssr     ! delay slot
+ */
+
+/*
+ * ABI at ret_from_syscall:
+ *	r8: from_syscall (0 or 1) indicating it's from syscall or not
+ *	r9: original r0 (to restart system call)
  *
  * Stack layout in 'ret_from_syscall':
  * 	ptrace needs to have all regs on the stack.
@@ -53,8 +53,7 @@
  *	gbr
  *	mach
  *	macl
- *	syscall #
- *
+ *	dummy
  */
 
 /*
@@ -66,7 +65,6 @@
 tsk_ptrace	= 24
 
 PT_TRACESYS  = 0x00000002
-PF_USEDFPU   = 0x00100000
 
 ENOSYS = 38
 EINVAL = 22
@@ -87,6 +85,10 @@
 MMU_TEA = 0xff00000c		! TLB Exception Address Register
 #endif
 
+#if defined(CONFIG_KGDB_NMI)
+NMI_VEC = 0x1c0			! Must catch early for debounce
+#endif
+
 /* Offsets to the stack */
 OFF_R0         =  0		/* Return value. New ABI also arg4 */
 OFF_R1         =  4     	/* New ABI: arg5 */
@@ -97,9 +99,8 @@
 OFF_R6         =  24     	/* New ABI: arg2 */
 OFF_R7         =  28     	/* New ABI: arg3 */
 OFF_SP	   =  (15*4)
+OFF_PC	   =  (16*4)
 OFF_SR	   =  (16*4+8)
-SYSCALL_NR =  (16*4+6*4)
-
 
 #define k0	r0
 #define k1	r1
@@ -220,10 +221,36 @@
 1:	.long	MMU_TEA
 2:	.long   SYMBOL_NAME(do_address_error)
 
-#if defined(CONFIG_SH_STANDARD_BIOS)
+
+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
+! If both are configured, handle the debug traps (breakpoints) in SW,
+! but still allow BIOS traps to FW.
+
 	.align	2
-	/* Unwind the stack and jmp to the debug entry */
 debug_kernel:
+#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
+	/* Force BIOS call to FW (debug_trap put TRA in r8) */
+	mov	r8,r0
+	shlr2	r0
+	cmp/eq	#0x3f,r0
+	bt	debug_kernel_fw
+#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
+
+debug_enter:		
+#if defined(CONFIG_SH_KGDB)
+	/* Jump to kgdb, pass stacked regs as arg */
+debug_kernel_sw:
+	mov.l	3f, r0
+	jmp	@r0
+	 mov	r15, r4
+	.align	2
+3:	.long	SYMBOL_NAME(kgdb_handle_exception)
+#endif /* CONFIG_SH_KGDB */
+
+#if defined(CONFIG_SH_STANDARD_BIOS)
+	/* Unwind the stack and jmp to the debug entry */
+debug_kernel_fw:
 	mov.l	@r15+, r0
 	mov.l	@r15+, r1
 	mov.l	@r15+, r2
@@ -259,11 +286,14 @@
 	.align	2
 1:	.long	0x300000f0
 2:	.long	SYMBOL_NAME(gdb_vbr_vector)
-#endif
+#endif /* CONFIG_SH_STANDARD_BIOS */
+
+#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
+
 
 	.align	2
 debug_trap:	
-#if defined(CONFIG_SH_STANDARD_BIOS)
+#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
 	mov	#OFF_SR, r0
 	mov.l	@(r0,r15), r0		! get status register
 	shll	r0
@@ -304,7 +334,8 @@
 	mov.l	@(tsk_ptrace,r0), r0	! Is current PTRACE_SYSCALL'd?
 	mov	#PT_TRACESYS, r1
 	tst	r1, r0
-	bt	ret_from_syscall
+	bt/s	syscall_ret
+	 mov	#0, r0
 	bra	syscall_ret_trace
 	 nop	 
 
@@ -346,29 +377,11 @@
 	mov.l	@r9, r8
 	!
 	! Is the trap argument >= 0x20? (TRA will be >= 0x80)
-	mov	#0x20, r9
-	extu.b	r9, r9
-	shll2	r9
-	cmp/hs	r9, r8
+	mov	#0x7f, r9
+	cmp/hi	r9, r8
 	bt	debug_trap
 	!
-	mov	#SYSCALL_NR, r14
-	add	r15, r14
-	!
-#ifdef COMPAT_OLD_SYSCALL_ABI
-	mov	#0x40, r9
-	cmp/hs	r9, r8
-	bf/s	old_abi_system_call
-	 nop
-#endif
 	! New Syscall ABI
-	add	#-0x40, r8
-	shlr2	r8
-	shll8	r8
-	shll8	r8 		    	! r8 = num_args<<16
-	mov	r3, r10
-	or	r8, r10	! Encode syscall # and # of arguments
-	mov.l	r10, @r14		! set syscall_nr
 	STI()
 	!
 	stc	k_current, r11
@@ -416,6 +429,10 @@
 	mov.l	__sct, r11
 	add	r11, r9
 	mov.l	@r9, r11
+	!		    Prepare args for do_signal on syscall return
+	mov	#1, r8			! indicate it's syscall return
+	mov.l	@(OFF_R0,r15), r9	! save original r0 (syscall arg4)
+	!
 	jmp	@r11	    	! jump to specific syscall handler
 	 nop
 
@@ -427,74 +444,6 @@
 	jmp	@r1    	! Call syscall_trace() which notifies superior
 	 lds	r0, pr    	! Then return to ret_from_syscall()
 
-
-
-#ifdef COMPAT_OLD_SYSCALL_ABI
-! Handle old ABI system call.
-! Note that ptrace(SYSCALL) is not supported for the old ABI.
-! At this point:
-!   r0, r4-7 as per ABI
-!   r8  = value of TRA register (= num_args<<2)
-!   r14 = points to SYSCALL_NR in stack frame
-old_abi_system_call:
-	mov 	r0, r9    	    	! Save system call number in r9
-	!   	    	    	    	! arrange for return which pops stack
-	mov.l	__old_abi_syscall_ret, r10
-	lds	r10, pr
-	!				  Build the stack frame if TRA > 0
-	mov	r8, r10
-	cmp/pl	r10
-	bf	0f
-	mov.l	@(OFF_SP,r15), r0	! get original user stack
-7:	add	#-4, r10
-4:	mov.l	@(r0,r10), r1	! May cause address error exception..
-	mov.l	r1, @-r15
-	cmp/pl	r10
-	bt	7b
-0:
-	mov.l	r9, @r14	    	! set syscall_nr
-	STI()
-	!   	    	    Call the system call handler through the table.
-	!   	    	    First check for bad syscall number
-	mov.l	__n_sys, r10
-	cmp/hs	r10, r9
-	bf	2f
-	!   	    	    Bad syscall number
-	rts			! return to old_abi_syscall_ret
-    	 mov	#-ENOSYS, r0
-	!   	    	    Good syscall number
-2:	shll2	r9		! x4
-	mov.l	__sct, r11
-	add	r11, r9
-	mov.l	@r9, r11
-	jmp	@r11	    	! call specific syscall handler,
-	 nop
-
-    	.align 2
-__old_abi_syscall_ret:
-	.long	old_abi_syscall_ret
-
-    	! This code gets called on address error exception when copying
-	! syscall arguments from user stack to kernel stack.  It is
-	! supposed to return -EINVAL through old_abi_syscall_ret, but it
-	! appears to have been broken for a long time in that the r0
-	! return value will be saved into the kernel stack relative to r15
-	! but the value of r15 is not correct partway through the loop.
-	! So the user prog is returned its old r0 value, not -EINVAL.
-	! Greg Banks 28 Aug 2000.
-	.section	.fixup,"ax"
-fixup_syscall_argerr:
-    	! First get r15 back to 
-	rts
-    	 mov	#-EINVAL, r0
-    	.previous
-
-	.section	__ex_table, "a"
-	.align	2
-	.long	4b,fixup_syscall_argerr
-    	.previous
-#endif
-
 	.align	2
 __TRA:	.long	TRA
 __syscall_trace:
@@ -511,12 +460,28 @@
 
 	.align	2
 reschedule:
+	! gUSA handling
+	mov.l	@(OFF_SP,r15), r0	! get user space stack pointer
+	mov	r0, r1
+	shll	r0
+	bf/s	1f
+	 shll	r0
+	bf/s	1f
+	 mov	#OFF_PC, r0
+	! 				  SP >= 0xc0000000 : gUSA mark
+	mov.l	@(r0,r15), r2		! get user space PC (program counter)
+	mov.l	@(OFF_R0,r15), r3	! end point
+	cmp/hs	r3, r2			! r2 >= r3? 
+	bt	1f
+	add	r3, r1			! rewind point #2
+	mov.l	r1, @(r0,r15)		! reset PC to rewind point #2
+	!
+1:	mov.l	2f, r1
 	mova	SYMBOL_NAME(ret_from_syscall), r0
-	mov.l	1f, r1
 	jmp	@r1
 	 lds	r0, pr
 	.align	2
-1:	.long	SYMBOL_NAME(schedule)
+2:	.long	SYMBOL_NAME(schedule)
 
 ret_from_irq:
 ret_from_exception:
@@ -527,14 +492,9 @@
 	bt	restore_all	! Yes, it's from kernel, go back soon
 	!
 	bra	ret_from_syscall
-	 nop
+	 mov	#0, r8		! indicate it's *not* syscall return
 
 	.align 2
-#ifdef COMPAT_OLD_SYSCALL_ABI
-old_abi_syscall_ret:
-	add	r8, r15	! pop off the arguments
-	/* fall through */
-#endif
 syscall_ret:
 	mov.l	r0, @(OFF_R0,r15)	! save the return value
 	/* fall through */
@@ -553,9 +513,11 @@
 	tst	r0, r0
 	bt	restore_all
 signal_return:
+	mov.l	__do_signal, r1
 	mov	r15, r4
 	mov	#0, r5
-	mov.l	__do_signal, r1
+	mov	r8, r6
+	mov	r9, r7
 	mova	restore_all, r0
 	jmp	@r1
 	 lds	r0, pr
@@ -567,12 +529,6 @@
 
 	.align 2
 restore_all:
-#if defined(__SH4__)
-	mov.l	__fpu_prepare_fd, r0
-	jsr	@r0
-	 stc	sr, r4
-#endif
-	!
 	mov.l	@r15+, r0
 	mov.l	@r15+, r1
 	mov.l	@r15+, r2
@@ -585,7 +541,7 @@
 	stc	sr, r8
 	mov.l	__blrb_flags, r9	! BL =1, RB=1
 	or	r9, r8
-	ldc	r8, sr		! here, change the register bank
+	ldc	r8, sr			! here, change the register bank
 	!
 	mov.l	@r15+, r8
 	mov.l	@r15+, r9
@@ -594,25 +550,26 @@
 	mov.l	@r15+, r12
 	mov.l	@r15+, r13
 	mov.l	@r15+, r14
-	mov.l	@r15+, k4	! original stack pointer
+	mov.l	@r15+, k4		! original stack pointer
 	ldc.l	@r15+, spc
 	lds.l	@r15+, pr
-	mov.l	@r15+, k3	! original SR
+	mov.l	@r15+, k3		! original SR
 	ldc.l	@r15+, gbr
 	lds.l	@r15+, mach
 	lds.l	@r15+, macl
-	add	#4, r15	! Skip syscall number
+	add	#4, r15			! skip placeholder
+	!
 	!
 	! Calculate new SR value
-	mov	k3, k2	! original SR value
+	mov	k3, k2			! original SR value
 	mov.l	1f, k1
 	stc	sr, k0
-	and	k1, k0	! Get current FD-bit
+	and	k1, k0			! Get current FD-bit
 	mov.l	2f, k1
-	and	k1, k2	! Mask orignal SR value
-	or	k0, k2	! Inherit current FD-bit
+	and	k1, k2			! Mask orignal SR value
+	or	k0, k2			! Inherit current FD-bit
 	!
-	mov	k3, k0	! Calculate IMASK-bits
+	mov	k3, k0			! Calculate IMASK-bits
 	shlr2	k0
 	and	#0x3c, k0
 	cmp/eq	#0x3c, k0
@@ -620,54 +577,14 @@
 	 shll2	k0
 	mov	g_imask, k0
 	!
-7:	or	k0, k2	! Set the IMASK-bits
+7:	or	k0, k2			! Set the IMASK-bits
 	ldc	k2, ssr
 	!
-#if defined(__SH4__)
-	shll	k2
-	shll	k2
-	bf	9f		! user mode
-	/* Kernel to kernel transition */
-	mov.l	1f, k1
-	tst	k1, k3
-	bf	9f		! it hadn't FPU
-	! Kernel to kernel and FPU was used
-	! There's the case we don't get FPU now
-	stc	sr, k2
-	tst	k1, k2
-	bt	8f
-	! We need to grab FPU here
-	xor	k1, k2
-	ldc	k2, sr		! Grab FPU
-	mov.l	__init_task_flags, k1
-	mov.l	@k1, k2
-	mov.l	__PF_USEDFPU, k0
-	or	k0, k2
-	mov.l	k2, @k1		! Set init_task.flags |= PF_USEDFPU
-	!
-	! Restoring FPU...
-	!
-8:	mov.l	3f, k1
-	lds	k1, fpscr
-	fmov.s	@r15+, fr0
-	fmov.s	@r15+, fr1
-	fmov.s	@r15+, fr2
-	fmov.s	@r15+, fr3
-	fmov.s	@r15+, fr4
-	fmov.s	@r15+, fr5
-	fmov.s	@r15+, fr6
-	fmov.s	@r15+, fr7
-	fmov.s	@r15+, fr8
-	fmov.s	@r15+, fr9
-	fmov.s	@r15+, fr10
-	fmov.s	@r15+, fr11
-	fmov.s	@r15+, fr12
-	fmov.s	@r15+, fr13
-	fmov.s	@r15+, fr14
-	fmov.s	@r15+, fr15
-	lds.l	@r15+, fpscr
-	lds.l	@r15+, fpul
-9:
+#if defined(CONFIG_KGDB_NMI)
+	! Clear in_nmi
+	mov.l	4f, k0
+	mov	#0, k1
+	mov.b	k1, @k0
 #endif
 	mov	k4, r15
 	rte
@@ -675,17 +592,13 @@
 
 	.align	2
 __blrb_flags:	.long	0x30000000
-#if defined(__SH4__)
-__fpu_prepare_fd:
-	.long	SYMBOL_NAME(fpu_prepare_fd)
-__init_task_flags:
-	.long	SYMBOL_NAME(init_task_union)+4
-__PF_USEDFPU:
-	.long	PF_USEDFPU
-#endif
 1:	.long	0x00008000	! FD
 2:	.long	0xffff7f0f	! ~(IMASK+FD)
 3:	.long	0x00080000	! SZ=0, PR=1
+#if defined(CONFIG_KGDB_NMI)
+4:	.long	SYMBOL_NAME(in_nmi)
+#endif
+
 
 ! Exception Vector Base
 !
@@ -717,6 +630,22 @@
 interrupt:
 	mov.l	2f, k2
 	mov.l	3f, k3
+#if defined(CONFIG_KGDB_NMI)
+	! Debounce (filter nested NMI)
+	mov.l	@k2, k0
+	mov.l	5f, k1
+	cmp/eq	k1, k0
+	bf	0f
+	mov.l	6f, k1
+	tas.b	@k1
+	bt	0f
+	rte
+	 nop
+	.align	2
+5:	.long	NMI_VEC
+6:	.long	SYMBOL_NAME(in_nmi)
+0:
+#endif /* defined(CONFIG_KGDB_NMI) */
 	bra	handle_exception
 	 mov.l	@k2, k2
 
@@ -732,61 +661,21 @@
 	! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
 	! save all registers onto stack.
 	!
-	stc	ssr, k0	! from kernel space?
-	shll	k0		! Check MD bit (bit30) by shifting it into the T bit
-	shll	k0
-#if defined(__SH4__)
-	bf/s	8f		! it's from user to kernel transition
-	 mov	r15, k0	! save original stack to k0
-	/* It's a kernel to kernel transition. */
-	/* Is the FPU disabled? */
-	mov.l	2f, k1
-	stc	ssr, k0
-	tst	k1, k0
-	mov.l	4f, k1
-	bf/s	9f		! FPU is not enabled, no need to save it
-	 mov	r15, k0	! save original stack to k0
-	! FPU is enabled, save it
-	! /* XXX: Need to save another bank of FPU if all FPU feature is used */
-	! /* Currently it's not the case for GCC (only udivsi3_i4, divsi3_i4) */
-	sts.l	fpul,  @-r15
-	sts.l	fpscr, @-r15
-	mov.l	6f, k1
-	lds	k1, fpscr
-	mov.l	3f, k1
-	fmov.s	fr15, @-r15
-	fmov.s	fr14, @-r15
-	fmov.s	fr13, @-r15
-	fmov.s	fr12, @-r15
-	fmov.s	fr11, @-r15
-	fmov.s	fr10, @-r15
-	fmov.s	fr9, @-r15
-	fmov.s	fr8, @-r15
-	fmov.s	fr7, @-r15
-	fmov.s	fr6, @-r15
-	fmov.s	fr5, @-r15
-	fmov.s	fr4, @-r15
-	fmov.s	fr3, @-r15
-	fmov.s	fr2, @-r15
-	fmov.s	fr1, @-r15
-	bra 9f
-	 fmov.s	fr0, @-r15
-#else
-	mov.l	3f, k1
-	bt/s	9f		! it's a kernel to kernel transition, and skip the FPU save.
-	 mov	r15, k0	! save original stack to k0 anyway
-#endif
-8:	/* User space to kernel */
+	stc	ssr, k0		! Is it from kernel space?
+	shll	k0		! Check MD bit (bit30) by shifting it into...
+	shll	k0		!       ...the T bit
+	bt/s	9f		! It's a kernel to kernel transition.
+	 mov	r15, k0		! save original stack to k0
+	/* User space to kernel */
 	mov	#0x20, k1
-	shll8	k1			! k1 <= 8192 == THREAD_SIZE
+	shll8	k1		! k1 <= 8192 == THREAD_SIZE
 	add	current, k1
 	mov	k1, r15		! change to kernel stack
 	!
-	mov.l	4f, k1			! let kernel release FPU
-9:	! Save the user registers on the stack.
-	! At this point, k1 should have been set to the new SR value
-  	mov	#-1, k4
-	mov.l	k4, @-r15		! syscall_nr (default: -1)
+9:	mov.l	3f, k1
+	!
+	! Save the user registers on the stack.
+	add	#-4, r15	! placeholder
 	!
 	sts.l	macl, @-r15
 	sts.l	mach, @-r15
@@ -806,11 +695,11 @@
 	mov.l	r9, @-r15
 	mov.l	r8, @-r15
 	!
-	stc	sr, r8	! Back to normal register bank, and
-	or	k1, r8	! Block all interrupts, may release FPU
+	stc	sr, r8		! Back to normal register bank, and
+	or	k1, r8		! Block all interrupts
 	mov.l	5f, k1
-	and	k1, r8	! ...
-	ldc	r8, sr	! ...changed here.
+	and	k1, r8		! ...
+	ldc	r8, sr		! ...changed here.
 	!
 	mov.l	r7, @-r15
 	mov.l	r6, @-r15
@@ -831,9 +720,7 @@
 	 nop
 	.align	2
 1:	.long	SYMBOL_NAME(exception_handling_table)
-2:	.long	0x00008000	! FD=1
 3:	.long	0x000000f0	! FD=0, IMASK=15
-4:	.long	0x000080f0	! FD=1, IMASK=15
 5:	.long	0xcfffffff	! RB=0, BL=0
 6:	.long	0x00080000	! SZ=0, PR=1
 
@@ -862,7 +749,11 @@
 	.long	error	! reserved_instruction      (filled by trap_init)
 	.long	error	! illegal_slot_instruction  (filled by trap_init)
 ENTRY(nmi_slot)
+#if defined (CONFIG_KGDB_NMI)
+	.long	debug_enter			! Allow trap to debugger
+#else
 	.long	none				! Not implemented yet
+#endif
 ENTRY(user_break_point_trap)
 	.long	break_point_trap
 ENTRY(interrupt_table)
@@ -978,7 +869,7 @@
 	.long	SYMBOL_NAME(do_IRQ)	!     pwon
 	.long	SYMBOL_NAME(do_IRQ)	!     pwdwn
 	.long	SYMBOL_NAME(do_IRQ)	!     err
-#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
+#elif defined(CONFIG_CPU_SUBTYPE_ST40)
 	.long	error			!  50 0x840
 	.long	error			!  51 0x860
 	.long	error			!  52 0x880
@@ -1010,14 +901,14 @@
 	.long	SYMBOL_NAME(do_IRQ)	!  78 0xbc0 DMA ERR
 	.long	error			!  79 0xbe0
 	.long	SYMBOL_NAME(do_IRQ)	!  80 0xc00 PIO0
-	.long	SYMBOL_NAME(do_IRQ)	!  81 0xc20 PIO1
-	.long	SYMBOL_NAME(do_IRQ)	!  82 0xc40 PIO2
+	.long	error			!  81 0xc20
+	.long	error			!  82 0xc40
 	.long	error			!  83 0xc60
-	.long	error			!  84 0xc80
+	.long	SYMBOL_NAME(do_IRQ)	!  84 0xc80 PIO1
 	.long	error			!  85 0xca0
 	.long	error			!  86 0xcc0
 	.long	error			!  87 0xce0
-	.long	error			!  88 0xd00
+	.long	SYMBOL_NAME(do_IRQ)	!  88 0xd00 PIO2
 	.long	error			!  89 0xd20
 	.long	error			!  90 0xd40
 	.long	error			!  91 0xd60
@@ -1041,6 +932,7 @@
 	.long	error			! 109 0xfa0
 	.long	error			! 110 0xfc0
 	.long	error			! 111 0xfe0
+# if defined(CONFIG_CPU_SUBTYPE_ST40STB1)
 	.long	SYMBOL_NAME(do_IRQ)	! 112 0x1000 Mailbox
 	.long	error			! 113 0x1020
 	.long	error			! 114 0x1040
@@ -1073,6 +965,74 @@
 	.long	error			! 141 0x13a0
 	.long	error			! 142 0x13c0
 	.long	error			! 143 0x13e0
+# elif defined(CONFIG_CPU_SUBTYPE_ST40GX1)
+	.long	SYMBOL_NAME(do_IRQ)	! 112 0x1000 Mailbox
+	.long	error			! 113 0x1020
+	.long	error			! 114 0x1040
+	.long	error			! 115 0x1060
+	.long	SYMBOL_NAME(do_IRQ)	! 116 0x1080 SSC0
+	.long	error			! 117 0x10a0
+	.long	error			! 118 0x10c0
+	.long	error			! 119 0x10e0
+	.long	SYMBOL_NAME(do_IRQ)	! 120 0x1100 IRBlaster IRB
+	.long	error			! 121 0x1120
+	.long	error			! 122 0x1140
+	.long	error			! 123 0x1160
+	.long	SYMBOL_NAME(do_IRQ)	! 124 0x1180 USB host
+	.long	error			! 125 0x11a0
+	.long	error			! 126 0x11c0
+	.long	error			! 127 0x11e0
+	.long	SYMBOL_NAME(do_IRQ)	! 128 0x1200 Video Processor BLITER
+	.long	error			! 129 0x1220
+	.long	error			! 130 0x1240
+	.long	error			! 131 0x1260
+	.long	SYMBOL_NAME(do_IRQ)	! 132 0x1280 UART0 UART0
+	.long	error			! 133 0x12a0
+	.long	SYMBOL_NAME(do_IRQ)	! 134 0x12c0       UART2
+	.long	error			! 135 0x12e0
+	.long	SYMBOL_NAME(do_IRQ)	! 136 0x1300 Additional PIO IO_PIO0
+	.long	error			! 137 0x1320
+	.long	error			! 138 0x1340
+	.long	error			! 139 0x1360
+	.long	SYMBOL_NAME(do_IRQ)	! 140 0x1380 EMPI INV_ADDR
+	.long	error			! 141 0x13a0
+	.long	error			! 142 0x13c0
+	.long	error			! 143 0x13e0
+	.long	SYMBOL_NAME(do_IRQ)	! 144 0x1400 MAFE
+	.long	error			! 145 0x1420
+	.long	error			! 146 0x1440
+	.long	error			! 147 0x1460
+	.long	SYMBOL_NAME(do_IRQ)	! 148 0x1480 PWM
+	.long	error			! 149 0x14a0
+	.long	error			! 150 0x14c0
+	.long	error			! 151 0x14e0
+	.long	SYMBOL_NAME(do_IRQ)	! 152 0x1500 SSC1
+	.long	error			! 153 0x1520
+	.long	error			! 154 0x1540
+	.long	error			! 155 0x1560
+	.long	SYMBOL_NAME(do_IRQ)	! 156 0x1580 Additional PIO IO_PIO1
+	.long	error			! 157 0x15a0
+	.long	error			! 158 0x15c0
+	.long	error			! 159 0x15e0
+	.long	SYMBOL_NAME(do_IRQ)	! 160 0x1600 USB target
+	.long	error			! 161 0x1620
+	.long	error			! 162 0x1640
+	.long	error			! 163 0x1660
+	.long	SYMBOL_NAME(do_IRQ)	! 164 0x1680 UART1 UART1
+	.long	error			! 165 0x16a0
+	.long	error			! 166 0x16c0
+	.long	error			! 167 0x16e0
+	.long	SYMBOL_NAME(do_IRQ)	! 168 0x1700 Teletext TTXT
+	.long	error			! 169 0x1720
+	.long	error			! 170 0x1740
+	.long	error			! 171 0x1760
+	.long	SYMBOL_NAME(do_IRQ)	! 172 0x1780 Video Sync VTG
+	.long	SYMBOL_NAME(do_IRQ)	! 173 0x17a0            DVP0
+	.long	SYMBOL_NAME(do_IRQ)	! 174 0x17c0            DVP1
+	.long	error			! 175 0x17e0
+# else
+#  error Unknown ST40 type
+# endif
 #endif
 
 ENTRY(sys_call_table)
@@ -1185,7 +1145,7 @@
 	.long SYMBOL_NAME(sys_newstat)
 	.long SYMBOL_NAME(sys_newlstat)
 	.long SYMBOL_NAME(sys_newfstat)
-	.long SYMBOL_NAME(sys_uname)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old uname */
 	.long SYMBOL_NAME(sys_ni_syscall)	/* 110 */ /* iopl */
 	.long SYMBOL_NAME(sys_vhangup)
 	.long SYMBOL_NAME(sys_ni_syscall)	/* idle */
@@ -1199,7 +1159,7 @@
 	.long SYMBOL_NAME(sys_clone)		/* 120 */
 	.long SYMBOL_NAME(sys_setdomainname)
 	.long SYMBOL_NAME(sys_newuname)
-	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_modify_ldt */
+	.long SYMBOL_NAME(sys_cacheflush)	/* sys_modify_ldt for i386 */
 	.long SYMBOL_NAME(sys_adjtimex)
 	.long SYMBOL_NAME(sys_mprotect)		/* 125 */
 	.long SYMBOL_NAME(sys_sigprocmask)
@@ -1256,8 +1216,8 @@
 	.long SYMBOL_NAME(sys_rt_sigtimedwait)
 	.long SYMBOL_NAME(sys_rt_sigqueueinfo)
 	.long SYMBOL_NAME(sys_rt_sigsuspend)
-	.long SYMBOL_NAME(sys_pread)		/* 180 */
-	.long SYMBOL_NAME(sys_pwrite)
+	.long SYMBOL_NAME(sys_pread_wrapper)	/* 180 */
+	.long SYMBOL_NAME(sys_pwrite_wrapper)
 	.long SYMBOL_NAME(sys_chown16)
 	.long SYMBOL_NAME(sys_getcwd)
 	.long SYMBOL_NAME(sys_capget)
@@ -1299,15 +1259,16 @@
 	.long SYMBOL_NAME(sys_getdents64)	/* 220 */
 	.long SYMBOL_NAME(sys_fcntl64)
 	.long SYMBOL_NAME(sys_gettid)
-	.long SYMBOL_NAME(sys_tkill)
-
+ 	.long SYMBOL_NAME(sys_tkill)
+	.long SYMBOL_NAME(sys_ni_syscall)
+	.long SYMBOL_NAME(sys_readahead)	/* 225 */
 	/*
 	 * NOTE!! This doesn't have to be exact - we just have
 	 * to make sure we have _enough_ of the "sys_ni_syscall"
 	 * entries. Don't panic if you notice that this hasn't
 	 * been shrunk every time we add a new system call.
 	 */
-	.rept NR_syscalls-221
+	.rept NR_syscalls-(.-sys_call_table)/4
 		.long SYMBOL_NAME(sys_ni_syscall)
 	.endr
 
diff -urN linux-2.4.21-bk11/arch/sh/kernel/fpu.c linux-2.4.21-bk12/arch/sh/kernel/fpu.c
--- linux-2.4.21-bk11/arch/sh/kernel/fpu.c	2001-01-28 18:56:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/fpu.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: fpu.c,v 1.29 2000/03/22 13:42:10 gniibe Exp $
+/* $Id: fpu.c,v 1.1.1.1.2.1 2002/01/25 00:51:42 gniibe Exp $
  *
  * linux/arch/sh/kernel/fpu.c
  *
@@ -18,6 +18,10 @@
 #include <asm/processor.h>
 #include <asm/io.h>
 
+/*
+ * Save FPU registers onto task structure.
+ * Assume called with FPU enabled (SR.FD=0).
+ */
 void
 save_fpu(struct task_struct *tsk)
 {
@@ -118,7 +122,8 @@
  * double precission represents signaling NANS.  
  */
 
-void fpu_init(void)
+static void
+fpu_init(void)
 {
 	asm volatile("lds	%0, fpul\n\t"
 		     "lds	%1, fpscr\n\t"
@@ -160,15 +165,125 @@
 		     : "r" (0), "r" (FPSCR_INIT));
 }
 
+/**
+ *	denormal_to_double - Given denormalized float number,
+ *	                     store double float
+ *
+ *	@fpu: Pointer to sh_fpu_hard structure
+ *	@n: Index to FP register
+ */
+static void
+denormal_to_double (struct sh_fpu_hard_struct *fpu, int n)
+{
+	unsigned long du, dl;
+	unsigned long x = fpu->fpul;
+	int exp = 1023 - 126;
+
+	if (x != 0 && (x & 0x7f800000) == 0) {
+		du = (x & 0x80000000);
+		while ((x & 0x00800000) == 0) {
+			x <<= 1;
+			exp--;
+		}
+		x &= 0x007fffff;
+		du |= (exp << 20) | (x >> 3);
+		dl = x << 29;
+
+		fpu->fp_regs[n] = du;
+		fpu->fp_regs[n+1] = dl;
+	}
+}
+
+/**
+ *	ieee_fpe_handler - Handle denormalized number exception
+ *
+ *	@regs: Pointer to register structure
+ *
+ *	Returns 1 when it's handled (should not cause exception).
+ */
+static int
+ieee_fpe_handler (struct pt_regs *regs)
+{
+	unsigned short insn = *(unsigned short *) regs->pc;
+	unsigned short finsn;
+	unsigned long nextpc;
+	int nib[4] = {
+		(insn >> 12) & 0xf,
+		(insn >> 8) & 0xf,
+		(insn >> 4) & 0xf,
+		insn & 0xf};
+
+	if (nib[0] == 0xb ||
+	    (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */
+		regs->pr = regs->pc + 4;
+  
+	if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */
+		nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3);
+		finsn = *(unsigned short *) (regs->pc + 2);
+	} else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */
+		if (regs->sr & 1)
+			nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+		else
+			nextpc = regs->pc + 4;
+		finsn = *(unsigned short *) (regs->pc + 2);
+	} else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */
+		if (regs->sr & 1)
+			nextpc = regs->pc + 4;
+		else
+			nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+		finsn = *(unsigned short *) (regs->pc + 2);
+	} else if (nib[0] == 0x4 && nib[3] == 0xb &&
+		 (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */
+		nextpc = regs->regs[nib[1]];
+		finsn = *(unsigned short *) (regs->pc + 2);
+	} else if (nib[0] == 0x0 && nib[3] == 0x3 &&
+		 (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */
+		nextpc = regs->pc + 4 + regs->regs[nib[1]];
+		finsn = *(unsigned short *) (regs->pc + 2);
+	} else if (insn == 0x000b) { /* rts */
+		nextpc = regs->pr;
+		finsn = *(unsigned short *) (regs->pc + 2);
+	} else {
+		nextpc = regs->pc + 2;
+		finsn = insn;
+	}
+
+	if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
+		struct task_struct *tsk = current;
+
+		save_fpu(tsk);
+		if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) {
+			/* FPU error */
+			denormal_to_double (&tsk->thread.fpu.hard,
+					    (finsn >> 8) & 0xf);
+			tsk->thread.fpu.hard.fpscr &=
+				~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
+			grab_fpu();
+			restore_fpu(tsk);
+			tsk->flags |= PF_USEDFPU;
+		} else {
+			tsk->thread.trap_no = 11;
+			tsk->thread.error_code = 0;
+			force_sig(SIGFPE, tsk);
+		}
+
+		regs->pc = nextpc;
+		return 1;
+	}
+
+	return 0;
+}
+
 asmlinkage void
 do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7,
 	     struct pt_regs regs)
 {
 	struct task_struct *tsk = current;
 
-	regs.pc += 2;
+	if (ieee_fpe_handler (&regs))
+		return;
 
-	grab_fpu();
+	regs.pc += 2;
 	save_fpu(tsk);
 	tsk->thread.trap_no = 11;
 	tsk->thread.error_code = 0;
@@ -181,102 +296,12 @@
 {
 	struct task_struct *tsk = current;
 
-	if (!user_mode(&regs)) {
-		if (tsk != &init_task) {
-			unlazy_fpu(tsk);
-		}
-		tsk = &init_task;
-		if (tsk->flags & PF_USEDFPU) {
-			/*
-			 * This weird situation can be occurred.
-			 *
-			 * There's race condition in __cli:
-			 *
-			 *   (1) SR --> register
-			 *   (2) Set IMASK of register
-			 *   (3) SR <-- register
-			 *
-			 * Between (1) and (2), or (2) and (3) getting
-			 * interrupt, and interrupt handler (or
-			 * softirq) may use FPU.
-			 *
-			 * Then, SR.FD is overwritten by (3).
-			 *
-			 * This results init_task.PF_USEDFPU is on,
-			 * with SR.FD == 1.
-			 *
-			 */
-			release_fpu();
-			return;
-		}
-	}
-
 	grab_fpu();
-	if (tsk->used_math) {
-		/* Using the FPU again.  */
-		restore_fpu(tsk);
-	} else	{
-		/* First time FPU user.  */
-		fpu_init();
-		tsk->used_math = 1;
-	}
-	tsk->flags |= PF_USEDFPU;
-	release_fpu();
-}
-
-/*
- * Change current FD flag to set FD flag back to exception
- */
-asmlinkage void
-fpu_prepare_fd(unsigned long sr, unsigned long r5, unsigned long r6,
-	       unsigned long r7, struct pt_regs regs)
-{
-	__cli();
 	if (!user_mode(&regs)) {
-		if (init_task.flags & PF_USEDFPU)
-			grab_fpu();
-		else {
-			if (!(sr & SR_FD)) {
-				BUG();
-				release_fpu();
-			}
-		}
+		printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
 		return;
 	}
 
-	if (sr & SR_FD) { /* Kernel doesn't grab FPU */
-		if (current->flags & PF_USEDFPU)
-			grab_fpu();
-		else {
-			if (init_task.flags & PF_USEDFPU) {
-				/*
-				 * This weird situation can be occurred.
-				 * See the comment in do_fpu_state_restore.
-				 */
-				grab_fpu();
-				save_fpu(&init_task);
-			}
-		}
-	} else {
-		if (init_task.flags & PF_USEDFPU)
-			save_fpu(&init_task);
-		else {
-			BUG();
-			release_fpu();
-		}
-	}
-}
-
-/* Short cut for the FPU exception */
-asmlinkage void
-enable_fpu_in_danger(void)
-{
-	struct task_struct *tsk = current;
-
-	if (tsk != &init_task)
-		unlazy_fpu(tsk);
-
-	tsk = &init_task;
 	if (tsk->used_math) {
 		/* Using the FPU again.  */
 		restore_fpu(tsk);
diff -urN linux-2.4.21-bk11/arch/sh/kernel/head.S linux-2.4.21-bk12/arch/sh/kernel/head.S
--- linux-2.4.21-bk11/arch/sh/kernel/head.S	2001-01-28 18:56:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/head.S	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.17 2000/03/06 12:44:24 gniibe Exp $
+/* $Id: head.S,v 1.1.1.1.2.1 2002/01/25 00:51:42 gniibe Exp $
  *
  *  arch/sh/kernel/head.S
  *
@@ -50,12 +50,6 @@
 	sub	r1, r0		!
 	ldc	r0, r7_bank	! ... and init_task
 	!
-#if defined(__SH4__)
-	!                       Initialize fpu
-	mov.l   7f, r0
-	jsr     @r0
-	 nop
-#endif
 	!			Enable cache
 	mov.l	6f, r0
 	jsr	@r0
@@ -74,12 +68,9 @@
 	 nop
 
 	.balign 4
-1:	.long	0x400000F0		! MD=1, RB=0, BL=0, FD=0, IMASK=0xF
+1:	.long	0x400080F0		! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
 2:	.long	SYMBOL_NAME(stack)
 3:	.long	SYMBOL_NAME(__bss_start)
 4:	.long	SYMBOL_NAME(_end)
 5:	.long	SYMBOL_NAME(start_kernel)
 6:	.long	SYMBOL_NAME(cache_init)
-#if defined(__SH4__)
-7:	.long   SYMBOL_NAME(fpu_init)
-#endif
diff -urN linux-2.4.21-bk11/arch/sh/kernel/io_hs7729pci.c linux-2.4.21-bk12/arch/sh/kernel/io_hs7729pci.c
--- linux-2.4.21-bk11/arch/sh/kernel/io_hs7729pci.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/io_hs7729pci.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,338 @@
+/* $Id: io_hs7729pci.c,v 1.1.2.1 2003/06/24 08:45:47 dwmw2 Exp $
+ *
+ * linux/arch/sh/kernel/io_hs7729pci.c
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * I/O routine for Hitachi Semiconductor and Devices HS7729PCI.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/hitachi_hs7729pci.h>
+
+#include "pci-sd0001.h"
+
+#ifdef CONFIG_PCI
+#define io_is_pci(port) (port >= PCIBIOS_MIN_IO)
+#else
+#define io_is_pci(port) (0)
+#endif
+
+/* SH pcmcia io window base, start and end.  */
+int sh_pcic_io_wbase = 0xb8400000;
+int sh_pcic_io_start;
+int sh_pcic_io_stop;
+int sh_pcic_io_type;
+int sh_pcic_io_dummy;
+
+static inline void delay(void)
+{
+	ctrl_inw(0xa0000000);
+}
+
+/* MS7750 requires special versions of in*, out* routines, since
+   PC-like io ports are located at upper half byte of 16-bit word which
+   can be accessed only with 16-bit wide.  */
+
+static inline volatile __u16 *
+port2adr(unsigned long port)
+{
+	if (port >= 0x2000)
+		return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
+	else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+		return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
+	
+	else
+		return (volatile __u16 *) (PA_SUPERIO + (port << 1));
+}
+
+static inline int
+shifted_port(unsigned long port)
+{
+	/* For IDE registers, value is not shifted */
+	if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6 || 
+	    (0x170 <= port && port < 0x178) || port == 0x376 || 
+	    port >= 0x1000)
+		return 0;
+	else
+		return 1;
+}
+
+#define maybebadio(name,port) \
+  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
+	 #name, (port), (__u32) __builtin_return_address(0))
+
+
+unsigned char hs7729pci_inb(unsigned long port)
+{
+	if (io_is_pci(port))
+		return sd0001_inb(port);
+	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+		return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
+	if (shifted_port(port))
+		return (*port2adr(port) >> 8); 
+#if defined(CONFIG_CF_ENABLER)
+	else if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+		return *(__u8 *)(PA_MRSHPC_IO + port + 0x40000);
+#endif
+	else
+		return (*port2adr(port))&0xff; 
+}
+
+unsigned char hs7729pci_inb_p(unsigned long port)
+{
+	unsigned long v;
+
+	if (io_is_pci(port))
+		v =  sd0001_inb(port);
+	else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+		v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
+	else if (shifted_port(port))
+		v = (*port2adr(port) >> 8); 
+#if defined(CONFIG_CF_ENABLER)
+	else if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+		v = *(__u8 *)(PA_MRSHPC_IO + port + 0x40000);
+#endif
+	else
+		v = (*port2adr(port))&0xff; 
+	delay();
+	return v;
+}
+
+unsigned short hs7729pci_inw(unsigned long port)
+{
+	if (io_is_pci(port))
+		return sd0001_inw(port);
+	if (port >= 0x2000 ||
+		 (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
+		return *port2adr(port);
+
+	maybebadio(inw, port);
+}
+
+unsigned int hs7729pci_inl(unsigned long port)
+{
+	if (io_is_pci(port))
+		return sd0001_inl(port);
+	else 
+		maybebadio(inl, port);
+}
+
+void hs7729pci_outb(unsigned char value, unsigned long port)
+{
+	if (io_is_pci(port))
+		sd0001_outb(value, port);
+	else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+		*(__u8 *)(sh_pcic_io_wbase + port) = value; 
+	else if (shifted_port(port))
+		*(port2adr(port)) = value << 8;
+#if defined(CONFIG_CF_ENABLER)
+	else if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+		*(__u8 *)(PA_MRSHPC_IO + port + 0x40000) = value;
+#endif
+	else
+		*(port2adr(port)) = value;
+}
+
+void hs7729pci_outb_p(unsigned char value, unsigned long port)
+{
+	if (io_is_pci(port))
+		sd0001_outb(value, port);
+	else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+		*(__u8 *)(sh_pcic_io_wbase + port) = value; 
+	else if (shifted_port(port))
+		*(port2adr(port)) = value << 8;
+#if defined(CONFIG_CF_ENABLER)
+	else if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+		*(__u8 *)(PA_MRSHPC_IO + port + 0x40000) = value;
+#endif
+	else
+		*(port2adr(port)) = value;
+	delay();
+}
+
+void hs7729pci_outw(unsigned short value, unsigned long port)
+{
+	if (io_is_pci(port))
+		sd0001_outw(value, port);
+	else if (port >= 0x2000 ||
+	    (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
+		*port2adr(port) = value;
+	else 
+		maybebadio(outw, port);
+}
+
+void hs7729pci_outl(unsigned int value, unsigned long port)
+{
+	if (io_is_pci(port))
+		sd0001_outl(value, port);
+	else
+		maybebadio(outl, port);
+}
+
+void hs7729pci_insb(unsigned long port, void *addr, unsigned long count)
+{
+	volatile __u16 *p = port2adr(port);
+
+	if (io_is_pci(port))
+		sd0001_insb(port, addr, count);
+	else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
+		volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
+		while (count--)
+			*((__u8 *) addr)++ = *bp;
+	} else if (shifted_port(port)) {
+		while (count--)
+			*((__u8 *) addr)++ = *p >> 8;
+#if defined(CONFIG_CF_ENABLER)
+	} else if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) {
+		volatile __u8 *q = (__u8 *)(PA_MRSHPC_IO + port + 0x40000);
+		while (count--) {
+			*((__u8 *) addr)++ = *q;
+		}
+#endif
+	} else {
+		while (count--)
+			*((__u8 *) addr)++ = *p;
+
+	}
+}
+
+void hs7729pci_insw(unsigned long port, void *addr, unsigned long count)
+{
+	volatile __u16 *p;
+
+	 if (io_is_pci(port))
+		 return sd0001_insw(port, addr, count);
+#if defined(CONFIG_CF_ENABLER)
+	 if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) {
+		p = (__u16 *)(PA_MRSHPC_IO + port);
+	 } else
+#endif
+		 p = port2adr(port);
+	 while (count--)
+		 *((__u16 *) addr)++ = *p;
+}
+
+void hs7729pci_insl(unsigned long port, void *addr, unsigned long count)
+{
+	if (io_is_pci(port))
+		sd0001_insl(port, addr, count);
+	else
+		maybebadio(insl, port);
+}
+
+void hs7729pci_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+	volatile __u16 *p = port2adr(port);
+
+	if (io_is_pci(port)) {
+		sd0001_outsb(port, addr, count);
+		return;
+	}
+	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
+		volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port); 
+		while (count--)
+			*bp = *((__u8 *) addr)++;
+	} else if (shifted_port(port)) {
+		while (count--)
+			*p = *((__u8 *) addr)++ << 8;
+#if defined(CONFIG_CF_ENABLER)
+	} else if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) {
+		volatile __u8 *q = (__u8 *)(PA_MRSHPC_IO + port + 0x40000);
+		while (count--) {
+			*q = *((__u8 *) addr)++;
+		}
+#endif
+	} else while (count--)
+		*p = *((__u8 *) addr)++;
+}
+
+void hs7729pci_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+	volatile __u16 *p;
+
+	if (io_is_pci(port)) {
+		sd0001_outsw(port, addr, count);
+		return;
+	}
+#if defined(CONFIG_CF_ENABLER)
+	if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) {
+		p = (__u16 *)(PA_MRSHPC_IO + port);
+	} else
+#endif
+		p = port2adr(port);
+	while (count--)
+		*p = *((__u16 *) addr)++;
+}
+
+void hs7729pci_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+	if (io_is_pci(port))
+		sd0001_outsl(port, addr, count);
+	else
+		maybebadio(outsl, port);
+}
+
+/* Map ISA bus address to the real address. Only for PCMCIA.  */
+
+/* ISA page descriptor.  */
+static __u32 sh_isa_memmap[256];
+
+static int
+sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
+{
+	int idx;
+
+	if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
+		return -1;
+
+	idx = start >> 12;
+	sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
+#if 0
+	printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
+	       start, length, offset, idx, sh_isa_memmap[idx]);
+#endif
+	return 0;
+}
+
+unsigned long
+hs7729pci_isa_port2addr(unsigned long offset)
+{
+	int idx;
+
+	idx = (offset >> 12) & 0xff;
+	offset &= 0xfff;
+	return sh_isa_memmap[idx] + offset;
+}
+
+void *hs7729pci_ioremap(unsigned long phys_addr, unsigned long size)
+{
+        /* Don't allow wraparound or zero size */
+        if (!size || (phys_addr + size - 1) < phys_addr)
+                return NULL;
+
+#ifdef CONFIG_PCI
+	if (phys_addr >= PCIBIOS_MIN_MEM &&
+	    phys_addr < (PCIBIOS_MIN_MEM&0xfc000000)+0x03000000)
+		return sd0001_ioremap(phys_addr, size);
+#endif
+	   return (void *) P2SEGADDR(phys_addr);
+}
+
+void hs7729pci_iounmap(void *addr) 
+{
+#ifdef CONFIG_PCI
+	/* Ideally for cleanliness we'd have a better way of knowing
+	   if it came from the PCI controller. */
+	if ((unsigned long)addr >= VMALLOC_START && 
+	    (unsigned long)addr < VMALLOC_END)
+		sd0001_iounmap(addr);
+#endif
+}
+		
diff -urN linux-2.4.21-bk11/arch/sh/kernel/io_keywest.c linux-2.4.21-bk12/arch/sh/kernel/io_keywest.c
--- linux-2.4.21-bk11/arch/sh/kernel/io_keywest.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/io_keywest.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,330 @@
+/*
+ * linux/arch/sh/io_keywest.c
+ *
+ * IO functions for a Hitachi KeyWest Evaluation Board.
+ *
+ * Copyright (C) 2001 Lineo, Japan
+ *
+ * This file is subject to the terms and conditions of the GNU General Publi
+c
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/keywest.h>
+
+//#define KEYWEST_DEBUG 3
+#undef KEYWEST_DEBUG
+
+#ifdef KEYWEST_DEBUG
+#define DPRINTK(args...)	printk(args)
+#define DIPRINTK(n, args...)	if (KEYWEST_DEBUG>(n)) printk(args)
+#else
+#define DPRINTK(args...)
+#define DIPRINTK(n, args...)
+#endif
+
+
+/* Low iomap maps port 0-1K to addresses in 8byte chunks */
+#define KEYWEST_IOMAP_LO_THRESH 0x400
+#define KEYWEST_IOMAP_LO_SHIFT	3
+#define KEYWEST_IOMAP_LO_MASK	((1<<KEYWEST_IOMAP_LO_SHIFT)-1)
+#define KEYWEST_IOMAP_LO_NMAP	(KEYWEST_IOMAP_LO_THRESH>>KEYWEST_IOMAP_LO_SHIFT)
+static u32 keywest_iomap_lo[KEYWEST_IOMAP_LO_NMAP];
+static u8 keywest_iomap_lo_shift[KEYWEST_IOMAP_LO_NMAP];
+
+/* High iomap maps port 1K-64K to addresses in 1K chunks */
+#define KEYWEST_IOMAP_HI_THRESH 0x10000
+#define KEYWEST_IOMAP_HI_SHIFT	10
+#define KEYWEST_IOMAP_HI_MASK	((1<<KEYWEST_IOMAP_HI_SHIFT)-1)
+#define KEYWEST_IOMAP_HI_NMAP	(KEYWEST_IOMAP_HI_THRESH>>KEYWEST_IOMAP_HI_SHIFT)
+static u32 keywest_iomap_hi[KEYWEST_IOMAP_HI_NMAP];
+static u8 keywest_iomap_hi_shift[KEYWEST_IOMAP_HI_NMAP];
+
+#ifndef MAX
+#define MAX(a,b)    ((a)>(b)?(a):(b))
+#endif
+
+#define PORT2ADDR(x) keywest_isa_port2addr(x)
+//#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
+//#define PORT2ADDR(x) (x)
+
+void keywest_port_map(u32 baseport, u32 nports, u32 addr, u8 shift)
+{
+    u32 port, endport = baseport + nports;
+
+    DPRINTK("keywest_port_map(base=0x%0x, n=0x%0x, addr=0x%08x)\n",
+	    baseport, nports, addr);
+	    
+	for (port = baseport ;
+	     port < endport && port < KEYWEST_IOMAP_LO_THRESH ;
+	     port += (1<<KEYWEST_IOMAP_LO_SHIFT)) {
+	    	DPRINTK("    maplo[0x%x] = 0x%08x\n", port, addr);
+    	    keywest_iomap_lo[port>>KEYWEST_IOMAP_LO_SHIFT] = addr;
+    	    keywest_iomap_lo_shift[port>>KEYWEST_IOMAP_LO_SHIFT] = shift;
+	    	addr += (1<<(KEYWEST_IOMAP_LO_SHIFT));
+	}
+
+	for (port = MAX(baseport, KEYWEST_IOMAP_LO_THRESH) ;
+	     port < endport && port < KEYWEST_IOMAP_HI_THRESH ;
+	     port += (1<<KEYWEST_IOMAP_HI_SHIFT)) {
+	    	DPRINTK("    maphi[0x%x] = 0x%08x\n", port, addr);
+    	    keywest_iomap_hi[port>>KEYWEST_IOMAP_HI_SHIFT] = addr;
+    	    keywest_iomap_hi_shift[port>>KEYWEST_IOMAP_HI_SHIFT] = shift;
+	    	addr += (1<<(KEYWEST_IOMAP_HI_SHIFT));
+	}
+}
+EXPORT_SYMBOL(keywest_port_map);
+
+void keywest_port_unmap(u32 baseport, u32 nports)
+{
+    u32 port, endport = baseport + nports;
+	
+    DPRINTK("keywest_port_unmap(base=0x%0x, n=0x%0x)\n", baseport, nports);
+
+	for (port = baseport ;
+	     port < endport && port < KEYWEST_IOMAP_LO_THRESH ;
+	     port += (1<<KEYWEST_IOMAP_LO_SHIFT)) {
+    	    keywest_iomap_lo[port>>KEYWEST_IOMAP_LO_SHIFT] = 0;
+	}
+
+	for (port = MAX(baseport, KEYWEST_IOMAP_LO_THRESH) ;
+	     port < endport && port < KEYWEST_IOMAP_HI_THRESH ;
+	     port += (1<<KEYWEST_IOMAP_HI_SHIFT)) {
+    	    keywest_iomap_hi[port>>KEYWEST_IOMAP_HI_SHIFT] = 0;
+	}
+}
+EXPORT_SYMBOL(keywest_port_unmap);
+
+unsigned long keywest_isa_port2addr(unsigned long port)
+{
+    unsigned long addr;
+	unsigned char shift;
+
+	/* Physical address not in P0, do nothing */
+	if (PXSEG(port))
+		return(port);
+
+	addr = 0;
+	/* physical address in P0, map to P2 */
+	if (port >= 0x30000)
+	    addr = P2SEGADDR(port);
+	/* Key West I/O + HD64465 registers 0x10000-0x30000 */
+	else if (port >= KEYWEST_IOMAP_HI_THRESH)
+	    addr = KEYWEST_INTERNAL_BASE + (port - KEYWEST_IOMAP_HI_THRESH);
+	/* Handle remapping of high IO/PCI IO ports */
+	else if (port >= KEYWEST_IOMAP_LO_THRESH) {
+	    addr = keywest_iomap_hi[port >> KEYWEST_IOMAP_HI_SHIFT];
+	    shift = keywest_iomap_hi_shift[port >> KEYWEST_IOMAP_HI_SHIFT];
+	    if (addr != 0)
+		    addr += (port & KEYWEST_IOMAP_HI_MASK) << shift;
+	}
+	/* Handle remapping of low IO ports */
+	else {
+	    addr = keywest_iomap_lo[port >> KEYWEST_IOMAP_LO_SHIFT];
+	    shift = keywest_iomap_lo_shift[port >> KEYWEST_IOMAP_LO_SHIFT];
+	    if (addr != 0)
+	    	addr += (port & KEYWEST_IOMAP_LO_MASK) << shift;
+	}
+
+    DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr);
+
+	return addr;
+}
+
+static inline void delay(void)
+{
+	ctrl_inw(0xa0000000);
+}
+
+unsigned char keywest_inb(unsigned long port)
+{
+	unsigned long addr = PORT2ADDR(port);
+	unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr);
+
+	DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b);
+	return b;
+}
+
+unsigned char keywest_inb_p(unsigned long port)
+{
+    unsigned long v;
+	unsigned long addr = PORT2ADDR(port);
+
+	v = (addr == 0 ? 0 : *(volatile unsigned char*)addr);
+	delay();
+	DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v);
+	return v;
+}
+
+unsigned short keywest_inw(unsigned long port)
+{
+    unsigned long addr = PORT2ADDR(port);
+	unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr);
+	DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b);
+	return b;
+}
+
+unsigned int keywest_inl(unsigned long port)
+{
+    unsigned long addr = PORT2ADDR(port);
+	unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr);
+	DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b);
+	return b;
+}
+
+void keywest_insb(unsigned long port, void *buffer, unsigned long count)
+{
+	unsigned char *buf=buffer;
+	while(count--) *buf++=inb(port);
+}
+
+void keywest_insw(unsigned long port, void *buffer, unsigned long count)
+{
+	unsigned short *buf=buffer;
+	while(count--) *buf++=inw(port);
+}
+
+void keywest_insl(unsigned long port, void *buffer, unsigned long count)
+{
+#if 0
+	unsigned long *buf=buffer;
+	while(count--) *buf++=inl(port);
+#else
+	union {
+		unsigned long l;
+		unsigned short s[2];
+		unsigned char c[4];
+	} align;
+	port = (((unsigned long)(port)) & 0xe0000000) ? port :
+			keywest_isa_port2addr(port);
+	switch (((unsigned long) buffer) & 0x3) {
+	case 0: {
+		register unsigned long *buf=buffer, *endp = buf + count;
+		while (buf < endp)
+			*buf++ = * (volatile unsigned long *) port;
+		break;
+		}
+	case 2: {
+		register unsigned short *buf=buffer, *endp = buf + (count << 1);
+		while (buf < endp) {
+			align.l = * (volatile unsigned long *) port;
+			*buf++ = align.s[0];
+			*buf++ = align.s[1];
+		}
+		break;
+		}
+	case 1:
+	case 3: {
+		register unsigned char *buf=buffer, *endp = buf + (count << 2);
+		while (buf < endp) {
+			align.l = * (volatile unsigned long *) port;
+			*buf++ = align.c[0];
+			*buf++ = align.c[1];
+			*buf++ = align.c[2];
+			*buf++ = align.c[3];
+		}
+		break;
+		}
+	}
+#endif
+}
+
+void keywest_outb(unsigned char b, unsigned long port)
+{
+	unsigned long addr = PORT2ADDR(port);
+
+	DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr);
+	if (addr != 0)
+	    *(volatile unsigned char*)addr = b;
+}
+
+void keywest_outb_p(unsigned char b, unsigned long port)
+{
+	unsigned long addr = PORT2ADDR(port);
+
+	DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr);
+    if (addr != 0)
+	    *(volatile unsigned char*)addr = b;
+	delay();
+}
+
+void keywest_outw(unsigned short b, unsigned long port)
+{
+	unsigned long addr = PORT2ADDR(port);
+	DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr);
+	if (addr != 0)
+	    *(volatile unsigned short*)addr = b;
+}
+
+void keywest_outl(unsigned int b, unsigned long port)
+{
+	unsigned long addr = PORT2ADDR(port);
+	DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr);
+	if (addr != 0)
+            *(volatile unsigned long*)addr = b;
+}
+
+void keywest_outsb(unsigned long port, const void *buffer, unsigned long count)
+{
+	const unsigned char *buf=buffer;
+	while(count--) outb(*buf++, port);
+}
+
+void keywest_outsw(unsigned long port, const void *buffer, unsigned long count)
+{
+	const unsigned short *buf=buffer;
+	while(count--) outw(*buf++, port);
+}
+
+void keywest_outsl(unsigned long port, const void *buffer, unsigned long count)
+{
+#if 0
+	const unsigned long *buf=buffer;
+	while(count--) outl(*buf++, port);
+#else
+	union {
+		unsigned long l;
+		unsigned short s[2];
+		unsigned char c[4];
+	} align;
+	port = (((unsigned long)(port)) & 0xe0000000) ? port :
+			keywest_isa_port2addr(port);
+	switch (((unsigned long) buffer) & 0x3) {
+	case 0: {
+		register unsigned long *buf=buffer, *endp = buf + count;
+		while (buf < endp)
+			* (volatile unsigned long *) port = *buf++;
+		break;
+		}
+	case 2: {
+		register unsigned short *buf=buffer, *endp = buf + (count << 1);
+		while (buf < endp) {
+			align.s[0] = *buf++;
+			align.s[1] = *buf++;
+			* (volatile unsigned long *) port = align.l;
+		}
+		break;
+		}
+	case 1:
+	case 3: {
+		register unsigned char *buf=buffer, *endp = buf + (count << 2);
+		while (buf < endp) {
+			align.c[0] = *buf++;
+			align.c[1] = *buf++;
+			align.c[2] = *buf++;
+			align.c[3] = *buf++;
+			* (volatile unsigned long *) port = align.l;
+		}
+		break;
+		}
+	}
+#endif
+}
+
diff -urN linux-2.4.21-bk11/arch/sh/kernel/io_se.c linux-2.4.21-bk12/arch/sh/kernel/io_se.c
--- linux-2.4.21-bk11/arch/sh/kernel/io_se.c	2001-10-15 13:36:48.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/io_se.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: io_se.c,v 1.12 2001/08/11 01:23:28 jzs Exp $
+/* $Id: io_se.c,v 1.1.1.1.2.1 2002/02/26 11:42:29 gniibe Exp $
  *
  * linux/arch/sh/kernel/io_se.c
  *
@@ -23,6 +23,7 @@
 static inline void delay(void)
 {
 	ctrl_inw(0xa0000000);
+	ctrl_inw(0xa0000000);
 }
 
 /* MS7750 requires special versions of in*, out* routines, since
diff -urN linux-2.4.21-bk11/arch/sh/kernel/io_snapgear.c linux-2.4.21-bk12/arch/sh/kernel/io_snapgear.c
--- linux-2.4.21-bk11/arch/sh/kernel/io_snapgear.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/io_snapgear.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,299 @@
+/* 
+ * linux/arch/sh/kernel/io_7751se.c
+ *
+ * Copyright (C) 2002  David McCullough <davidm@snapgear.com>
+ * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for Hitachi 7751 SolutionEngine.
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_se.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+
+#include <asm/pci.h>
+#include <asm/pci-sh7751.h>
+
+#ifdef CONFIG_SH_SECUREEDGE5410
+unsigned short secureedge5410_ioport;
+#endif
+
+/*
+ * The SnapGear uses the built-in PCI controller (PCIC)
+ * of the 7751 processor
+ */ 
+
+#define PCIIOBR		(volatile long *)PCI_REG(SH7751_PCIIOBR)
+#define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
+#define PCI_IO_AREA	SH7751_PCI_IO_BASE
+#define PCI_MEM_AREA	SH7751_PCI_CONFIG_BASE
+
+
+#define PCI_IOMAP(adr)	(PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
+
+
+#define maybebadio(name,port) \
+  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
+	 #name, (port), (__u32) __builtin_return_address(0))
+
+
+static inline void delay(void)
+{
+	ctrl_inw(0xa0000000);
+}
+
+
+static inline volatile __u16 *
+port2adr(unsigned int port)
+{
+#if 0
+	if (port >= 0x2000)
+		return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
+#endif
+	maybebadio(name,port);
+	return (volatile __u16*)port;
+}
+
+
+/* In case someone configures the kernel w/o PCI support: in that */
+/* scenario, don't ever bother to check for PCI-window addresses */
+
+/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
+#if defined(CONFIG_PCI)
+#define CHECK_SH7751_PCIIO(port) \
+  ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
+#else
+#define CHECK_SH7751_PCIIO(port) (0)
+#endif
+
+/*
+ * General outline: remap really low stuff [eventually] to SuperIO,
+ * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO)
+ * is mapped through the PCI IO window.  Stuff with high bits (PXSEG)
+ * should be way beyond the window, and is used  w/o translation for
+ * compatibility.
+ */
+
+unsigned char snapgear_inb(unsigned long port)
+{
+	if (PXSEG(port))
+		return *(volatile unsigned char *)port;
+	else if (CHECK_SH7751_PCIIO(port))
+		return *(volatile unsigned char *)PCI_IOMAP(port);
+	else
+		return (*port2adr(port))&0xff; 
+}
+
+
+unsigned char snapgear_inb_p(unsigned long port)
+{
+	unsigned char v;
+
+	if (PXSEG(port))
+		v = *(volatile unsigned char *)port;
+	else if (CHECK_SH7751_PCIIO(port))
+		v = *(volatile unsigned char *)PCI_IOMAP(port);
+	else
+		v = (*port2adr(port))&0xff; 
+	delay();
+	return v;
+}
+
+
+unsigned short snapgear_inw(unsigned long port)
+{
+	if (PXSEG(port))
+		return *(volatile unsigned short *)port;
+	else if (CHECK_SH7751_PCIIO(port))
+		return *(volatile unsigned short *)PCI_IOMAP(port);
+	else if (port >= 0x2000)
+		return *port2adr(port);
+	else
+		maybebadio(inw, port);
+	return 0;
+}
+
+
+unsigned int snapgear_inl(unsigned long port)
+{
+	if (PXSEG(port))
+		return *(volatile unsigned long *)port;
+	else if (CHECK_SH7751_PCIIO(port))
+		return *(volatile unsigned int *)PCI_IOMAP(port);
+	else if (port >= 0x2000)
+		return *port2adr(port);
+	else
+		maybebadio(inl, port);
+	return 0;
+}
+
+
+void snapgear_outb(unsigned char value, unsigned long port)
+{
+
+	if (PXSEG(port))
+		*(volatile unsigned char *)port = value;
+	else if (CHECK_SH7751_PCIIO(port))
+		*((unsigned char*)PCI_IOMAP(port)) = value;
+	else
+		*(port2adr(port)) = value;
+}
+
+
+void snapgear_outb_p(unsigned char value, unsigned long port)
+{
+	if (PXSEG(port))
+		*(volatile unsigned char *)port = value;
+	else if (CHECK_SH7751_PCIIO(port))
+		*((unsigned char*)PCI_IOMAP(port)) = value;
+	else
+		*(port2adr(port)) = value;
+	delay();
+}
+
+
+void snapgear_outw(unsigned short value, unsigned long port)
+{
+	if (PXSEG(port))
+		*(volatile unsigned short *)port = value;
+	else if (CHECK_SH7751_PCIIO(port))
+		*((unsigned short *)PCI_IOMAP(port)) = value;
+	else if (port >= 0x2000)
+		*port2adr(port) = value;
+	else
+		maybebadio(outw, port);
+}
+
+
+void snapgear_outl(unsigned int value, unsigned long port)
+{
+	if (PXSEG(port))
+		*(volatile unsigned long *)port = value;
+	else if (CHECK_SH7751_PCIIO(port))
+		*((unsigned long*)PCI_IOMAP(port)) = value;
+	else
+		maybebadio(outl, port);
+}
+
+
+void snapgear_insb(unsigned long port, void *addr, unsigned long count)
+{
+	unsigned char *p = addr;
+	while (count--) *p++ = snapgear_inb(port);
+}
+
+
+void snapgear_insw(unsigned long port, void *addr, unsigned long count)
+{
+	unsigned short *p = addr;
+	while (count--) *p++ = snapgear_inw(port);
+}
+
+
+void snapgear_insl(unsigned long port, void *addr, unsigned long count)
+{
+	maybebadio(insl, port);
+}
+
+
+void snapgear_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+	unsigned char *p = (unsigned char*)addr;
+	while (count--) snapgear_outb(*p++, port);
+}
+
+
+void snapgear_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+	unsigned short *p = (unsigned short*)addr;
+	while (count--) snapgear_outw(*p++, port);
+}
+
+
+void snapgear_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+	maybebadio(outsw, port);
+}
+
+
+/* For read/write calls, just copy generic (pass-thru); PCIMBR is  */
+/* already set up.  For a larger memory space, these would need to */
+/* reset PCIMBR as needed on a per-call basis...                   */
+
+unsigned char snapgear_readb(unsigned long addr)
+{
+	return (* ((volatile unsigned char *) addr));
+}
+
+
+unsigned short snapgear_readw(unsigned long addr)
+{
+	return (* ((volatile unsigned short *) addr));
+}
+
+
+unsigned int snapgear_readl(unsigned long addr)
+{
+	return (* ((volatile unsigned long *) addr));
+}
+
+
+void snapgear_writeb(unsigned char b, unsigned long addr)
+{
+	*(volatile unsigned char*)addr = b;
+}
+
+
+void snapgear_writew(unsigned short b, unsigned long addr)
+{
+	*(volatile unsigned short*)addr = b;
+}
+
+
+void snapgear_writel(unsigned int b, unsigned long addr)
+{
+	*(volatile unsigned long*)addr = b;
+}
+
+
+/* Map ISA bus address to the real address. Only for PCMCIA.  */
+
+
+/* ISA page descriptor.  */
+static __u32 sh_isa_memmap[256];
+
+
+static int
+sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
+{
+	int idx;
+
+	if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
+		return -1;
+
+	idx = start >> 12;
+	sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
+#if 0
+	printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
+	       start, length, offset, idx, sh_isa_memmap[idx]);
+#endif
+	return 0;
+}
+
+
+unsigned long
+snapgear_isa_port2addr(unsigned long offset)
+{
+	int idx;
+
+	idx = (offset >> 12) & 0xff;
+	offset &= 0xfff;
+	return sh_isa_memmap[idx] + offset;
+}
diff -urN linux-2.4.21-bk11/arch/sh/kernel/kgdb_jmp.S linux-2.4.21-bk12/arch/sh/kernel/kgdb_jmp.S
--- linux-2.4.21-bk11/arch/sh/kernel/kgdb_jmp.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/kgdb_jmp.S	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,33 @@
+#include <linux/linkage.h>
+
+ENTRY(kgdb_setjmp)
+	add	#(9*4), r4
+	sts.l	pr, @-r4
+	mov.l	r15, @-r4
+	mov.l	r14, @-r4
+	mov.l	r13, @-r4
+	mov.l	r12, @-r4
+	mov.l	r11, @-r4
+	mov.l	r10, @-r4
+	mov.l	r9, @-r4
+	mov.l	r8, @-r4
+	rts
+	 mov	#0, r0
+
+ENTRY(kgdb_longjmp)
+	mov.l	@r4+, r8
+	mov.l	@r4+, r9
+	mov.l	@r4+, r10
+	mov.l	@r4+, r11
+	mov.l	@r4+, r12
+	mov.l	@r4+, r13
+	mov.l	@r4+, r14
+	mov.l	@r4+, r15
+	lds.l	@r4+, pr
+	mov	r5, r0
+	tst	r0, r0
+	bf	1f
+	mov	#1, r0	! in case val==0
+1:	rts
+	 nop
+
diff -urN linux-2.4.21-bk11/arch/sh/kernel/kgdb_stub.c linux-2.4.21-bk12/arch/sh/kernel/kgdb_stub.c
--- linux-2.4.21-bk11/arch/sh/kernel/kgdb_stub.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/kgdb_stub.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,1488 @@
+/*
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Contains extracts from code by Glenn Engel, Jim Kingdon,
+ * David Grothe <dave@gcom.com>, Tigran Aivazian <tigran@sco.com>,
+ * Amit S. Kale <akale@veritas.com>,  William Gatliff <bgat@open-widgets.com>,
+ * Ben Lee, Steve Chamberlain and Benoit Miller <fulg@iname.com>.
+ * 
+ * This version by Henry Bell <henry.bell@st.com>
+ * Minor modifications by Jeremy Siegel <jsiegel@mvista.com>
+ * 
+ * Contains low-level support for remote debug using GDB. 
+ *
+ * To enable debugger support, two things need to happen. A call to
+ * set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * A breakpoint also needs to be generated to begin communication.  This
+ * is most easily accomplished by a call to breakpoint() which does
+ * a trapa if the initialisation phase has been successfully completed.
+ *
+ * In this case, set_debug_traps() is not used to "take over" exceptions;
+ * other kernel code is modified instead to enter the kgdb functions here
+ * when appropriate (see entry.S for breakpoint traps and NMI interrupts,
+ * see traps.c for kernel error exceptions).
+ *
+ * The following gdb commands are supported:
+ *
+ *    Command       Function                               Return value
+ *
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ *    XAA..AA,LLLL: Same, but data is binary (not hex)     OK or ENN
+ *
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ *    CNN;          Resume at current address with signal  SNN
+ *    CNN;AA..AA    Resume at address AA..AA with signal   SNN
+ *
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ *    SNN;          Step one instruction with signal       SNN
+ *    SNNAA..AA     Step one instruction from AA..AA w/NN  SNN
+ *
+ *    k             kill (Detach GDB)
+ *
+ *    d             Toggle debug flag
+ *    D             Detach GDB 
+ *
+ *    Hct           Set thread t for operations,           OK or ENN
+ *                  c = 'c' (step, cont), c = 'g' (other
+ *                  operations)
+ *
+ *    qC            Query current thread ID                QCpid
+ *    qfThreadInfo  Get list of current threads (first)    m<id>
+ *    qsThreadInfo   "    "  "     "      "   (subsequent)
+ *    qOffsets      Get section offsets                  Text=x;Data=y;Bss=z
+ * 
+ *    TXX           Find if thread XX is alive             OK or ENN
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ *    O             Output to GDB console
+ *
+ * Remote communication protocol.
+ *
+ *    A debug packet whose contents are <data> is encapsulated for
+ *    transmission in the form:
+ *
+ *       $ <data> # CSUM1 CSUM2
+ *
+ *       <data> must be ASCII alphanumeric and cannot include characters
+ *       '$' or '#'.  If <data> starts with two characters followed by
+ *       ':', then the existing stubs interpret this as a sequence number.
+ *
+ *       CSUM1 and CSUM2 are ascii hex representation of an 8-bit 
+ *       checksum of <data>, the most significant nibble is sent first.
+ *       the hex digits 0-9,a-f are used.
+ *
+ *    Receiver responds with:
+ *
+ *       +       - if CSUM is correct and ready for next packet
+ *       -       - if CSUM is incorrect
+ *
+ * Responses can be run-length encoded to save space.  A '*' means that
+ * the next character is an ASCII encoding giving a repeat count which
+ * stands for that many repititions of the character preceding the '*'.
+ * The encoding is n+29, yielding a printable character where n >=3 
+ * (which is where RLE starts to win).  Don't use an n > 126. 
+ *
+ * So "0* " means the same as "0000".
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/current.h>
+#include <asm/signal.h>
+#include <asm/pgtable.h>
+#include <asm/ptrace.h>
+#include <asm/kgdb.h>
+
+#ifdef CONFIG_SH_KGDB_CONSOLE
+#include <linux/console.h>
+#endif
+
+/* Function pointers for linkage */
+kgdb_debug_hook_t *kgdb_debug_hook;
+kgdb_bus_error_hook_t *kgdb_bus_err_hook;
+
+int (*kgdb_getchar)(void);
+void (*kgdb_putchar)(int);
+
+static void put_debug_char(int c)
+{
+	if (!kgdb_putchar)
+		return;
+	(*kgdb_putchar)(c);
+}
+static int get_debug_char(void)
+{
+	if (!kgdb_getchar)
+		return -1;
+	return (*kgdb_getchar)();
+}
+
+/* Num chars in in/out bound buffers, register packets need NUMREGBYTES * 2 */
+#define BUFMAX 1024
+#define NUMREGBYTES (MAXREG*4)
+#define OUTBUFMAX (NUMREGBYTES*2+512)
+
+enum regs {
+	R0 = 0, R1,  R2,  R3,   R4,   R5,  R6, R7,
+	R8, R9, R10, R11, R12,  R13,  R14, R15,
+	PC, PR, GBR, VBR, MACH, MACL, SR,
+	/*  */
+	MAXREG
+};
+
+static unsigned int registers[MAXREG];
+struct kgdb_regs trap_registers;
+
+char kgdb_in_gdb_mode;
+char in_nmi;			/* Set during NMI to prevent reentry */
+int kgdb_nofault;		/* Boolean to ignore bus errs (i.e. in GDB) */
+int kgdb_enabled = 1;		/* Default to enabled, cmdline can disable */
+int kgdb_halt;
+
+/* Exposed for user access */
+struct task_struct *kgdb_current;
+unsigned int kgdb_g_imask;
+int kgdb_trapa_val;
+int kgdb_excode;
+struct pt_regs *kgdb_tregs;
+
+/* Default values for SCI (can override via kernel args in setup.c) */
+#ifndef CONFIG_KGDB_DEFPORT
+#define CONFIG_KGDB_DEFPORT 1
+#endif
+
+#ifndef CONFIG_KGDB_DEFBAUD
+#define CONFIG_KGDB_DEFBAUD 115200
+#endif
+
+#if defined(CONFIG_KGDB_DEFPARITY_E)
+#define CONFIG_KGDB_DEFPARITY 'E'
+#elif defined(CONFIG_KGDB_DEFPARITY_O)
+#define CONFIG_KGDB_DEFPARITY 'O'
+#else /* CONFIG_KGDB_DEFPARITY_N */
+#define CONFIG_KGDB_DEFPARITY 'N'
+#endif
+
+#ifdef CONFIG_KGDB_DEFBITS_7
+#define CONFIG_KGDB_DEFBITS '7'
+#else /* CONFIG_KGDB_DEFBITS_8 */
+#define CONFIG_KGDB_DEFBITS '8'
+#endif
+
+/* SCI/UART settings, used in kgdb_serial_setup() */
+int (*kgdb_serial_setup)(void) = kgdb_sci_setup;
+int  kgdb_portnum = CONFIG_KGDB_DEFPORT;
+int  kgdb_baud = CONFIG_KGDB_DEFBAUD;
+char kgdb_parity = CONFIG_KGDB_DEFPARITY;
+char kgdb_bits = CONFIG_KGDB_DEFBITS;
+int  kgdb_cflag;
+
+/* Jump buffer for setjmp/longjmp */
+static jmp_buf rem_com_env;
+
+/* TRA differs sh3/4 */
+#if defined(__sh3__)
+#define TRA 0xffffffd0
+#elif defined(__SH4__)
+#define TRA 0xff000020
+#endif
+
+/* Macros for single step instruction identification */
+#define OPCODE_BT(op)         (((op) & 0xff00) == 0x8900)
+#define OPCODE_BF(op)         (((op) & 0xff00) == 0x8b00)
+#define OPCODE_BTF_DISP(op)   (((op) & 0x80) ? (((op) | 0xffffff80) << 1) : \
+			      (((op) & 0x7f ) << 1))
+#define OPCODE_BFS(op)        (((op) & 0xff00) == 0x8f00)
+#define OPCODE_BTS(op)        (((op) & 0xff00) == 0x8d00)
+#define OPCODE_BRA(op)        (((op) & 0xf000) == 0xa000)
+#define OPCODE_BRA_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
+			      (((op) & 0x7ff) << 1))
+#define OPCODE_BRAF(op)       (((op) & 0xf0ff) == 0x0023)
+#define OPCODE_BRAF_REG(op)   (((op) & 0x0f00) >> 8)
+#define OPCODE_BSR(op)        (((op) & 0xf000) == 0xb000)
+#define OPCODE_BSR_DISP(op)   (((op) & 0x800) ? (((op) | 0xfffff800) << 1) : \
+			      (((op) & 0x7ff) << 1))
+#define OPCODE_BSRF(op)       (((op) & 0xf0ff) == 0x0003)
+#define OPCODE_BSRF_REG(op)   (((op) >> 8) & 0xf)
+#define OPCODE_JMP(op)        (((op) & 0xf0ff) == 0x402b)
+#define OPCODE_JMP_REG(op)    (((op) >> 8) & 0xf)
+#define OPCODE_JSR(op)        (((op) & 0xf0ff) == 0x400b)
+#define OPCODE_JSR_REG(op)    (((op) >> 8) & 0xf)
+#define OPCODE_RTS(op)        ((op) == 0xb)
+#define OPCODE_RTE(op)        ((op) == 0x2b)
+
+#define SR_T_BIT_MASK           0x1
+#define STEP_OPCODE             0xc320
+#define BIOS_CALL_TRAP          0x3f
+
+/* Exception codes as per SH-4 core manual */
+#define ADDRESS_ERROR_LOAD_VEC   7
+#define ADDRESS_ERROR_STORE_VEC  8
+#define TRAP_VEC                 11
+#define INVALID_INSN_VEC         12
+#define INVALID_SLOT_VEC         13
+#define NMI_VEC                  14
+#define USER_BREAK_VEC           15
+#define SERIAL_BREAK_VEC         58
+
+/* Misc static */
+static int stepped_address;
+static short stepped_opcode;
+static const char hexchars[] = "0123456789abcdef";
+static char in_buffer[BUFMAX];
+static char out_buffer[OUTBUFMAX];
+
+static void kgdb_to_gdb(const char *s);
+
+#ifdef CONFIG_KGDB_THREAD
+static struct task_struct *trapped_thread;
+static struct task_struct *current_thread;
+typedef unsigned char threadref[8];
+#define BUF_THREAD_ID_SIZE 16
+#endif
+
+/* Return addr as a real volatile address */
+static inline unsigned int ctrl_inl(const unsigned long addr)
+{
+	return *(volatile unsigned long *) addr;
+}
+
+/* Correctly set *addr using volatile */
+static inline void ctrl_outl(const unsigned int b, unsigned long addr)
+{
+	*(volatile unsigned long *) addr = b;
+}
+
+/* Get high hex bits */
+static char highhex(const int x)
+{
+	return hexchars[(x >> 4) & 0xf];
+}
+
+/* Get low hex bits */
+static char lowhex(const int x)
+{
+	return hexchars[x & 0xf];
+}
+
+/* Convert ch to hex */
+static int hex(const char ch)
+{
+	if ((ch >= 'a') && (ch <= 'f'))
+		return (ch - 'a' + 10);
+	if ((ch >= '0') && (ch <= '9'))
+		return (ch - '0');
+	if ((ch >= 'A') && (ch <= 'F'))
+		return (ch - 'A' + 10);
+	return (-1);
+}
+
+/* Convert the memory pointed to by mem into hex, placing result in buf.
+   Returns a pointer to the last char put in buf (null) */
+static char *mem_to_hex(const char *mem, char *buf, const int count)
+{
+	int i;
+	int ch;
+	unsigned short s_val;
+	unsigned long l_val;
+
+	/* Check for 16 or 32 */
+	if (count == 2 && ((long) mem & 1) == 0) {
+		s_val = *(unsigned short *) mem;
+		mem = (char *) &s_val;
+	} else if (count == 4 && ((long) mem & 3) == 0) {
+		l_val = *(unsigned long *) mem;
+		mem = (char *) &l_val;
+	}
+	for (i = 0; i < count; i++) {
+		ch = *mem++;
+		*buf++ = highhex(ch);
+		*buf++ = lowhex(ch);
+	}
+	*buf = 0;
+	return (buf);
+}
+
+/* Convert the hex array pointed to by buf into binary, to be placed in mem.
+   Return a pointer to the character after the last byte written */
+static char *hex_to_mem(const char *buf, char *mem, const int count)
+{
+	int i;
+	unsigned char ch;
+
+	for (i = 0; i < count; i++) {
+		ch = hex(*buf++) << 4;
+		ch = ch + hex(*buf++);
+		*mem++ = ch;
+	}
+	return (mem);
+}
+
+/* While finding valid hex chars, convert to an integer, then return it */
+static int hex_to_int(char **ptr, int *int_value)
+{
+	int num_chars = 0;
+	int hex_value;
+
+	*int_value = 0;
+
+	while (**ptr) {
+		hex_value = hex(**ptr);
+		if (hex_value >= 0) {
+			*int_value = (*int_value << 4) | hex_value;
+			num_chars++;
+		} else
+			break;
+		(*ptr)++;
+	}
+	return num_chars;
+}
+
+/*  Copy the binary array pointed to by buf into mem.  Fix $, #,
+    and 0x7d escaped with 0x7d.  Return a pointer to the character 
+    after the last byte written. */
+static char *ebin_to_mem(const char *buf, char *mem, int count)
+{
+	for (; count > 0; count--, buf++) {
+		if (*buf == 0x7d)
+			*mem++ = *(++buf) ^ 0x20;
+		else
+			*mem++ = *buf;
+	}
+	return mem;
+}
+
+/* Pack a hex byte */
+static char *pack_hex_byte(char *pkt, int byte)
+{
+	*pkt++ = hexchars[(byte >> 4) & 0xf];
+	*pkt++ = hexchars[(byte & 0xf)];
+	return pkt;
+}
+
+#ifdef CONFIG_KGDB_THREAD
+
+/* Pack a thread ID */
+static char *pack_threadid(char *pkt, threadref * id)
+{
+	char *limit;
+	unsigned char *altid;
+
+	altid = (unsigned char *) id;
+
+	limit = pkt + BUF_THREAD_ID_SIZE;
+	while (pkt < limit)
+		pkt = pack_hex_byte(pkt, *altid++);
+	return pkt;
+}
+
+/* Convert an integer into our threadref */
+static void int_to_threadref(threadref * id, const int value)
+{
+	unsigned char *scan = (unsigned char *) id;
+	int i = 4;
+
+	while (i--)
+		*scan++ = 0;
+
+	*scan++ = (value >> 24) & 0xff;
+	*scan++ = (value >> 16) & 0xff;
+	*scan++ = (value >> 8) & 0xff;
+	*scan++ = (value & 0xff);
+}
+
+/* Return a task structure ptr for a particular pid */
+static struct task_struct *get_thread(int pid)
+{
+	struct task_struct *thread;
+
+	/* Use PID_MAX w/gdb for pid 0 */
+	if (pid == PID_MAX) pid = 0;
+
+	/* First check via PID */
+	thread = find_task_by_pid(pid);
+
+	if (thread)
+		return thread;
+
+	/* Start at the start */
+	thread = init_tasks[0];
+
+	/* Walk along the linked list of tasks */
+	do {
+		if (thread->pid == pid)
+			return thread;
+		thread = thread->next_task;
+	} while (thread != init_tasks[0]);
+
+	return NULL;
+}
+
+#endif /* CONFIG_KGDB_THREAD */
+
+/* Scan for the start char '$', read the packet and check the checksum */
+static void get_packet(char *buffer, int buflen)
+{
+	unsigned char checksum;
+	unsigned char xmitcsum;
+	int i;
+	int count;
+	char ch;
+
+	do {
+		/* Ignore everything until the start character */
+		while ((ch = get_debug_char()) != '$');
+
+		checksum = 0;
+		xmitcsum = -1;
+		count = 0;
+
+		/* Now, read until a # or end of buffer is found */
+		while (count < (buflen - 1)) {
+			ch = get_debug_char();
+
+			if (ch == '#')
+				break;
+
+			checksum = checksum + ch;
+			buffer[count] = ch;
+			count = count + 1;
+		}
+
+		buffer[count] = 0;
+
+		/* Continue to read checksum following # */
+		if (ch == '#') {
+			xmitcsum = hex(get_debug_char()) << 4;
+			xmitcsum += hex(get_debug_char());
+
+			/* Checksum */
+			if (checksum != xmitcsum)
+				put_debug_char('-');	/* Failed checksum */
+			else {
+				/* Ack successful transfer */
+				put_debug_char('+');
+
+				/* If a sequence char is present, reply 
+				   the sequence ID */
+				if (buffer[2] == ':') {
+					put_debug_char(buffer[0]);
+					put_debug_char(buffer[1]);
+
+					/* Remove sequence chars from buffer */
+					count = strlen(buffer);
+					for (i = 3; i <= count; i++)
+						buffer[i - 3] = buffer[i];
+				}
+			}
+		}
+	}
+	while (checksum != xmitcsum);	/* Keep trying while we fail */
+}
+
+/* Send the packet in the buffer with run-length encoding */
+static void put_packet(char *buffer)
+{
+	int checksum;
+	char *src;
+	int runlen;
+	int encode;
+
+	do {
+		src = buffer;
+		put_debug_char('$');
+		checksum = 0;
+
+		/* Continue while we still have chars left */
+		while (*src) {
+			/* Check for runs up to 99 chars long */
+			for (runlen = 1; runlen < 99; runlen++) {
+				if (src[0] != src[runlen])
+					break;
+			}
+
+			if (runlen > 3) {
+				/* Got a useful amount, send encoding */
+				encode = runlen + ' ' - 4;
+				put_debug_char(*src);   checksum += *src;
+				put_debug_char('*');    checksum += '*';
+				put_debug_char(encode); checksum += encode;
+				src += runlen;
+			} else {
+				/* Otherwise just send the current char */
+				put_debug_char(*src);   checksum += *src;
+				src += 1;
+			}
+		}
+
+		/* '#' Separator, put high and low components of checksum */
+		put_debug_char('#');
+		put_debug_char(highhex(checksum));
+		put_debug_char(lowhex(checksum));
+	}
+	while ((get_debug_char()) != '+');	/* While no ack */
+}
+
+/* A bus error has occurred - perform a longjmp to return execution and
+   allow handling of the error */
+static void kgdb_handle_bus_error(void)
+{
+	kgdb_longjmp(rem_com_env, 1);
+}
+
+/* Translate SH-3/4 exception numbers to unix-like signal values */
+static int compute_signal(const int excep_code)
+{
+	int sigval;
+
+	switch (excep_code) {
+
+	case INVALID_INSN_VEC:
+	case INVALID_SLOT_VEC:
+		sigval = SIGILL;
+		break;
+	case ADDRESS_ERROR_LOAD_VEC:
+	case ADDRESS_ERROR_STORE_VEC:
+		sigval = SIGSEGV;
+		break;
+
+	case SERIAL_BREAK_VEC:
+	case NMI_VEC:
+		sigval = SIGINT;
+		break;
+
+	case USER_BREAK_VEC:
+	case TRAP_VEC:
+		sigval = SIGTRAP;
+		break;
+
+	default:
+		sigval = SIGBUS;	/* "software generated" */
+		break;
+	}
+
+	return (sigval);
+}
+
+/* Make a local copy of the registers passed into the handler (bletch) */
+static void kgdb_regs_to_gdb_regs(const struct kgdb_regs *regs,
+				  int *gdb_regs)
+{
+	gdb_regs[R0] = regs->regs[R0];
+	gdb_regs[R1] = regs->regs[R1];
+	gdb_regs[R2] = regs->regs[R2];
+	gdb_regs[R3] = regs->regs[R3];
+	gdb_regs[R4] = regs->regs[R4];
+	gdb_regs[R5] = regs->regs[R5];
+	gdb_regs[R6] = regs->regs[R6];
+	gdb_regs[R7] = regs->regs[R7];
+	gdb_regs[R8] = regs->regs[R8];
+	gdb_regs[R9] = regs->regs[R9];
+	gdb_regs[R10] = regs->regs[R10];
+	gdb_regs[R11] = regs->regs[R11];
+	gdb_regs[R12] = regs->regs[R12];
+	gdb_regs[R13] = regs->regs[R13];
+	gdb_regs[R14] = regs->regs[R14];
+	gdb_regs[R15] = regs->regs[R15];
+	gdb_regs[PC] = regs->pc;
+	gdb_regs[PR] = regs->pr;
+	gdb_regs[GBR] = regs->gbr;
+	gdb_regs[MACH] = regs->mach;
+	gdb_regs[MACL] = regs->macl;
+	gdb_regs[SR] = regs->sr;
+	gdb_regs[VBR] = regs->vbr;
+}
+
+/* Copy local gdb registers back to kgdb regs, for later copy to kernel */
+static void gdb_regs_to_kgdb_regs(const int *gdb_regs,
+				  struct kgdb_regs *regs)
+{
+	regs->regs[R0] = gdb_regs[R0];
+	regs->regs[R1] = gdb_regs[R1];
+	regs->regs[R2] = gdb_regs[R2];
+	regs->regs[R3] = gdb_regs[R3];
+	regs->regs[R4] = gdb_regs[R4];
+	regs->regs[R5] = gdb_regs[R5];
+	regs->regs[R6] = gdb_regs[R6];
+	regs->regs[R7] = gdb_regs[R7];
+	regs->regs[R8] = gdb_regs[R8];
+	regs->regs[R9] = gdb_regs[R9];
+	regs->regs[R10] = gdb_regs[R10];
+	regs->regs[R11] = gdb_regs[R11];
+	regs->regs[R12] = gdb_regs[R12];
+	regs->regs[R13] = gdb_regs[R13];
+	regs->regs[R14] = gdb_regs[R14];
+	regs->regs[R15] = gdb_regs[R15];
+	regs->pc = gdb_regs[PC];
+	regs->pr = gdb_regs[PR];
+	regs->gbr = gdb_regs[GBR];
+	regs->mach = gdb_regs[MACH];
+	regs->macl = gdb_regs[MACL];
+	regs->sr = gdb_regs[SR];
+	regs->vbr = gdb_regs[VBR];
+}
+
+#ifdef CONFIG_KGDB_THREAD
+/* Make a local copy of registers from the specified thread */
+asmlinkage void ret_from_fork(void);
+static void thread_regs_to_gdb_regs(const struct task_struct *thread,
+				    int *gdb_regs)
+{
+	int regno;
+	int *tregs;
+
+	/* Initialize to zero */
+	for (regno = 0; regno < MAXREG; regno++)
+		gdb_regs[regno] = 0;
+
+	/* Just making sure... */
+	if (thread == NULL)
+		return;
+
+	/* A new fork has pt_regs on the stack from a fork() call */
+	if (thread->thread.pc == (unsigned long)ret_from_fork) {
+
+		int vbr_val;
+		struct pt_regs *kregs;
+		kregs = (struct pt_regs*)thread->thread.sp;
+
+		gdb_regs[R0] = kregs->regs[R0];
+		gdb_regs[R1] = kregs->regs[R1];
+		gdb_regs[R2] = kregs->regs[R2];
+		gdb_regs[R3] = kregs->regs[R3];
+		gdb_regs[R4] = kregs->regs[R4];
+		gdb_regs[R5] = kregs->regs[R5];
+		gdb_regs[R6] = kregs->regs[R6];
+		gdb_regs[R7] = kregs->regs[R7];
+		gdb_regs[R8] = kregs->regs[R8];
+		gdb_regs[R9] = kregs->regs[R9];
+		gdb_regs[R10] = kregs->regs[R10];
+		gdb_regs[R11] = kregs->regs[R11];
+		gdb_regs[R12] = kregs->regs[R12];
+		gdb_regs[R13] = kregs->regs[R13];
+		gdb_regs[R14] = kregs->regs[R14];
+		gdb_regs[R15] = kregs->regs[R15];
+		gdb_regs[PC] = kregs->pc;
+		gdb_regs[PR] = kregs->pr;
+		gdb_regs[GBR] = kregs->gbr;
+		gdb_regs[MACH] = kregs->mach;
+		gdb_regs[MACL] = kregs->macl;
+		gdb_regs[SR] = kregs->sr;
+
+		asm("stc vbr, %0":"=r"(vbr_val));
+		gdb_regs[VBR] = vbr_val;
+		return;
+	}
+
+	/* Otherwise, we have only some registers from switch_to() */
+	tregs = (int *)thread->thread.sp;
+	gdb_regs[R15] = (int)tregs;
+	gdb_regs[R14] = *tregs++;
+	gdb_regs[R13] = *tregs++;
+	gdb_regs[R12] = *tregs++;
+	gdb_regs[R11] = *tregs++;
+	gdb_regs[R10] = *tregs++;
+	gdb_regs[R9] = *tregs++;
+	gdb_regs[R8] = *tregs++;
+	gdb_regs[PR] = *tregs++;
+	gdb_regs[GBR] = *tregs++;
+	gdb_regs[PC] = thread->thread.pc;
+}
+#endif /* CONFIG_KGDB_THREAD */
+
+/* Calculate the new address for after a step */
+static short *get_step_address(void)
+{
+	short op = *(short *) trap_registers.pc;
+	long addr;
+
+	/* BT */
+	if (OPCODE_BT(op)) {
+		if (trap_registers.sr & SR_T_BIT_MASK)
+			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+		else
+			addr = trap_registers.pc + 2;
+	}
+
+	/* BTS */
+	else if (OPCODE_BTS(op)) {
+		if (trap_registers.sr & SR_T_BIT_MASK)
+			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+		else
+			addr = trap_registers.pc + 4;	/* Not in delay slot */
+	}
+
+	/* BF */
+	else if (OPCODE_BF(op)) {
+		if (!(trap_registers.sr & SR_T_BIT_MASK))
+			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+		else
+			addr = trap_registers.pc + 2;
+	}
+
+	/* BFS */
+	else if (OPCODE_BFS(op)) {
+		if (!(trap_registers.sr & SR_T_BIT_MASK))
+			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);
+		else
+			addr = trap_registers.pc + 4;	/* Not in delay slot */
+	}
+
+	/* BRA */
+	else if (OPCODE_BRA(op))
+		addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op);
+
+	/* BRAF */
+	else if (OPCODE_BRAF(op))
+		addr = trap_registers.pc + 4
+		    + trap_registers.regs[OPCODE_BRAF_REG(op)];
+
+	/* BSR */
+	else if (OPCODE_BSR(op))
+		addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op);
+
+	/* BSRF */
+	else if (OPCODE_BSRF(op))
+		addr = trap_registers.pc + 4
+		    + trap_registers.regs[OPCODE_BSRF_REG(op)];
+
+	/* JMP */
+	else if (OPCODE_JMP(op))
+		addr = trap_registers.regs[OPCODE_JMP_REG(op)];
+
+	/* JSR */
+	else if (OPCODE_JSR(op))
+		addr = trap_registers.regs[OPCODE_JSR_REG(op)];
+
+	/* RTS */
+	else if (OPCODE_RTS(op))
+		addr = trap_registers.pr;
+
+	/* RTE */
+	else if (OPCODE_RTE(op))
+		addr = trap_registers.regs[15];
+
+	/* Other */
+	else
+		addr = trap_registers.pc + 2;
+
+	kgdb_flush_icache_range(addr, addr + 2);
+	return (short *) addr;
+}
+
+/* Set up a single-step.  Replace the instruction immediately after the 
+   current instruction (i.e. next in the expected flow of control) with a
+   trap instruction, so that returning will cause only a single instruction
+   to be executed. Note that this model is slightly broken for instructions
+   with delay slots (e.g. B[TF]S, BSR, BRA etc), where both the branch
+   and the instruction in the delay slot will be executed. */
+static void do_single_step(void)
+{
+	unsigned short *addr = 0;
+
+	/* Determine where the target instruction will send us to */
+	addr = get_step_address();
+	stepped_address = (int)addr;
+
+	/* Replace it */
+	stepped_opcode = *(short *)addr;
+	*addr = STEP_OPCODE;
+
+	/* Flush and return */
+	kgdb_flush_icache_range((long) addr, (long) addr + 2);
+	return;
+}
+
+/* Undo a single step */
+static void undo_single_step(void)
+{
+	/* If we have stepped, put back the old instruction */
+	/* Use stepped_address in case we stopped elsewhere */
+	if (stepped_opcode != 0) {
+		*(short*)stepped_address = stepped_opcode;
+		kgdb_flush_icache_range(stepped_address, stepped_address + 2);
+	}
+	stepped_opcode = 0;
+}
+
+/* Send a signal message */
+static void send_signal_msg(const int signum)
+{
+#ifndef CONFIG_KGDB_THREAD
+	out_buffer[0] = 'S';
+	out_buffer[1] = highhex(signum);
+	out_buffer[2] = lowhex(signum);
+	out_buffer[3] = 0;
+	put_packet(out_buffer);
+#else /* CONFIG_KGDB_THREAD */
+	int threadid;
+	threadref thref;
+	char *out = out_buffer;
+	const char *tstring = "thread";
+
+	*out++ = 'T';
+	*out++ = highhex(signum);
+	*out++ = lowhex(signum);
+
+	while (*tstring) {
+		*out++ = *tstring++;
+	}
+	*out++ = ':';
+
+	threadid = trapped_thread->pid;
+	if (threadid == 0) threadid = PID_MAX;
+	int_to_threadref(&thref, threadid);
+	pack_threadid(out, &thref);
+	out += BUF_THREAD_ID_SIZE;
+	*out++ = ';';
+
+	*out = 0;
+	put_packet(out_buffer);
+#endif /* CONFIG_KGDB_THREAD */
+}
+
+/* Reply that all was well */
+static void send_ok_msg(void)
+{
+	strcpy(out_buffer, "OK");
+	put_packet(out_buffer);
+}
+
+/* Reply that an error occurred */
+static void send_err_msg(void)
+{
+	strcpy(out_buffer, "E01");
+	put_packet(out_buffer);
+}
+
+/* Empty message indicates unrecognised command */
+static void send_empty_msg(void)
+{
+	put_packet("");
+}
+
+/* Read memory due to 'm' message */
+static void read_mem_msg(void)
+{
+	char *ptr;
+	int addr;
+	int length;
+
+	/* Jmp, disable bus error handler */
+	if (kgdb_setjmp(rem_com_env) == 0) {
+
+		kgdb_nofault = 1;
+
+		/* Walk through, have m<addr>,<length> */
+		ptr = &in_buffer[1];
+		if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
+			if (hex_to_int(&ptr, &length)) {
+				ptr = 0;
+				if (length * 2 > OUTBUFMAX)
+					length = OUTBUFMAX / 2;
+				mem_to_hex((char *) addr, out_buffer, length);
+			}
+		if (ptr)
+			send_err_msg();
+		else
+			put_packet(out_buffer);
+	} else
+		send_err_msg();
+
+	/* Restore bus error handler */
+	kgdb_nofault = 0;
+}
+
+/* Write memory due to 'M' or 'X' message */
+static void write_mem_msg(int binary)
+{
+	char *ptr;
+	int addr;
+	int length;
+
+	if (kgdb_setjmp(rem_com_env) == 0) {
+
+		kgdb_nofault = 1;
+
+		/* Walk through, have M<addr>,<length>:<data> */
+		ptr = &in_buffer[1];
+		if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))
+			if (hex_to_int(&ptr, &length) && (*ptr++ == ':')) {
+				if (binary)
+					ebin_to_mem(ptr, (char*)addr, length);
+				else
+					hex_to_mem(ptr, (char*)addr, length);
+				kgdb_flush_icache_range(addr, addr + length);
+				ptr = 0;
+				send_ok_msg();
+			}
+		if (ptr)
+			send_err_msg();
+	} else
+		send_err_msg();
+
+	/* Restore bus error handler */
+	kgdb_nofault = 0;
+}
+
+/* Continue message  */
+static void continue_msg(void)
+{
+	/* Try to read optional parameter, PC unchanged if none */
+	char *ptr = &in_buffer[1];
+	int addr;
+
+	if (hex_to_int(&ptr, &addr))
+		trap_registers.pc = addr;
+}
+
+/* Continue message with signal */
+static void continue_with_sig_msg(void)
+{
+	int signal;
+	char *ptr = &in_buffer[1];
+	int addr;
+
+	/* Report limitation */
+	kgdb_to_gdb("Cannot force signal in kgdb, continuing anyway.\n");
+
+	/* Signal */
+	hex_to_int(&ptr, &signal);
+	if (*ptr == ';')
+		ptr++;
+
+	/* Optional address */
+	if (hex_to_int(&ptr, &addr))
+		trap_registers.pc = addr;
+}
+
+/* Step message */
+static void step_msg(void)
+{
+	continue_msg();
+	do_single_step();
+}
+
+/* Step message with signal */
+static void step_with_sig_msg(void)
+{
+	continue_with_sig_msg();
+	do_single_step();
+}
+
+/* Send register contents */
+static void send_regs_msg(void)
+{
+#ifdef CONFIG_KGDB_THREAD
+	if (!current_thread)
+		kgdb_regs_to_gdb_regs(&trap_registers, registers);
+	else
+		thread_regs_to_gdb_regs(current_thread, registers);
+#else
+	kgdb_regs_to_gdb_regs(&trap_registers, registers);
+#endif
+
+	mem_to_hex((char *) registers, out_buffer, NUMREGBYTES);
+	put_packet(out_buffer);
+}
+
+/* Set register contents - currently can't set other thread's registers */
+static void set_regs_msg(void)
+{
+#ifdef CONFIG_KGDB_THREAD
+	if (!current_thread) {
+#endif
+		kgdb_regs_to_gdb_regs(&trap_registers, registers);
+		hex_to_mem(&in_buffer[1], (char *) registers, NUMREGBYTES);
+		gdb_regs_to_kgdb_regs(registers, &trap_registers);
+		send_ok_msg();
+#ifdef CONFIG_KGDB_THREAD
+	} else
+		send_err_msg();
+#endif
+}
+
+
+#ifdef CONFIG_KGDB_THREAD
+
+/* Set the status for a thread */
+void set_thread_msg(void)
+{
+	int threadid;
+	struct task_struct *thread = NULL;
+	char *ptr;
+
+	switch (in_buffer[1]) {
+
+       	/* To select which thread for gG etc messages, i.e. supported */
+	case 'g':
+
+		ptr = &in_buffer[2];
+		hex_to_int(&ptr, &threadid);
+		thread = get_thread(threadid);
+
+		/* If we haven't found it */
+		if (!thread) {
+			send_err_msg();
+			break;
+		}
+
+		/* Set current_thread (or not) */
+		if (thread == trapped_thread)
+			current_thread = NULL;
+		else
+			current_thread = thread;
+		send_ok_msg();
+		break;
+
+	/* To select which thread for cCsS messages, i.e. unsupported */
+	case 'c':
+		send_ok_msg();
+		break;
+
+	default:
+		send_empty_msg();
+		break;
+	}
+}
+
+/* Is a thread alive? */
+static void thread_status_msg(void)
+{
+	char *ptr;
+	int threadid;
+	struct task_struct *thread = NULL;
+
+	ptr = &in_buffer[1];
+	hex_to_int(&ptr, &threadid);
+	thread = get_thread(threadid);
+	if (thread)
+		send_ok_msg();
+	else
+		send_err_msg();
+}
+/* Send the current thread ID */
+static void thread_id_msg(void)
+{
+	int threadid;
+	threadref thref;
+
+	out_buffer[0] = 'Q';
+	out_buffer[1] = 'C';
+
+	if (current_thread)
+		threadid = current_thread->pid;
+	else if (trapped_thread)
+		threadid = trapped_thread->pid;
+	else /* Impossible, but just in case! */
+	{
+		send_err_msg();
+		return;
+	}
+
+	/* Translate pid 0 to PID_MAX for gdb */
+	if (threadid == 0) threadid = PID_MAX;
+
+	int_to_threadref(&thref, threadid);
+	pack_threadid(out_buffer + 2, &thref);
+	out_buffer[2 + BUF_THREAD_ID_SIZE] = '\0';
+	put_packet(out_buffer);
+}
+
+/* Send thread info */
+static void thread_info_msg(void)
+{
+	struct task_struct *thread = NULL;
+	int threadid;
+	char *pos;
+	threadref thref;
+
+	/* Start with 'm' */
+	out_buffer[0] = 'm';
+	pos = &out_buffer[1];
+
+	/* For all possible thread IDs - this will overrun if > 44 threads! */
+	/* Start at 1 and include PID_MAX (since GDB won't use pid 0...) */
+	for (threadid = 1; threadid <= PID_MAX; threadid++) {
+
+		read_lock(&tasklist_lock);
+		thread = get_thread(threadid);
+		read_unlock(&tasklist_lock);
+
+		/* If it's a valid thread */
+		if (thread) {
+			int_to_threadref(&thref, threadid);
+			pack_threadid(pos, &thref);
+			pos += BUF_THREAD_ID_SIZE;
+			*pos++ = ',';
+		}
+	}
+	*--pos = 0;		/* Lose final comma */
+	put_packet(out_buffer);
+
+}
+
+/* Return printable info for gdb's 'info threads' command */
+static void thread_extra_info_msg(void)
+{
+	int threadid;
+	struct task_struct *thread = NULL;
+	char buffer[20], *ptr;
+	int i;
+
+	/* Extract thread ID */
+	ptr = &in_buffer[17];
+	hex_to_int(&ptr, &threadid);
+	thread = get_thread(threadid);
+
+	/* If we don't recognise it, say so */
+	if (thread == NULL)
+		strcpy(buffer, "(unknown)");
+	else
+		strcpy(buffer, thread->comm);
+
+	/* Construct packet */
+	for (i = 0, ptr = out_buffer; buffer[i]; i++)
+		ptr = pack_hex_byte(ptr, buffer[i]);
+
+	if (thread->thread.pc == (unsigned long)ret_from_fork) {
+		strcpy(buffer, "<new fork>");
+		for (i = 0; buffer[i]; i++)
+			ptr = pack_hex_byte(ptr, buffer[i]);
+	}
+
+	*ptr = '\0';
+	put_packet(out_buffer);
+}
+
+/* Handle all qFooBarBaz messages - have to use an if statement as
+   opposed to a switch because q messages can have > 1 char id. */
+static void query_msg(void)
+{
+	const char *q_start = &in_buffer[1];
+
+	/* qC = return current thread ID */
+	if (strncmp(q_start, "C", 1) == 0)
+		thread_id_msg();
+
+	/* qfThreadInfo = query all threads (first) */
+	else if (strncmp(q_start, "fThreadInfo", 11) == 0)
+		thread_info_msg();
+
+	/* qsThreadInfo = query all threads (subsequent). We know we have sent
+	   them all after the qfThreadInfo message, so there are no to send */
+	else if (strncmp(q_start, "sThreadInfo", 11) == 0)
+		put_packet("l");	/* el = last */
+
+	/* qThreadExtraInfo = supply printable information per thread */
+	else if (strncmp(q_start, "ThreadExtraInfo", 15) == 0)
+		thread_extra_info_msg();
+
+	/* Unsupported - empty message as per spec */
+	else
+		send_empty_msg();
+}
+#endif /* CONFIG_KGDB_THREAD */
+
+/* The command loop, read and act on requests */
+static void kgdb_command_loop(const int excep_code, const int trapa_value)
+{
+	int sigval;
+
+	if (excep_code == NMI_VEC) {
+#ifndef CONFIG_KGDB_NMI
+		KGDB_PRINTK("Ignoring unexpected NMI?\n");
+		return;
+#else /* CONFIG_KGDB_NMI */
+		if (!kgdb_enabled) {
+			kgdb_enabled = 1;
+			kgdb_init();
+		}
+#endif /* CONFIG_KGDB_NMI */
+	}
+
+	/* Ignore if we're disabled */
+	if (!kgdb_enabled)
+		return;
+
+#ifdef CONFIG_KGDB_THREAD
+	/* Until GDB specifies a thread */
+	current_thread = NULL;
+	trapped_thread = current;
+#endif
+
+	/* Enter GDB mode (e.g. after detach) */
+	if (!kgdb_in_gdb_mode) {
+		/* Do serial setup, notify user, issue preemptive ack */
+		(void)kgdb_serial_setup();
+		KGDB_PRINTK("Waiting for GDB (on %s%d at %d baud)\n",
+			    (kgdb_porttype ? kgdb_porttype->name : ""),
+			    kgdb_portnum, kgdb_baud);
+		kgdb_in_gdb_mode = 1;
+		put_debug_char('+');
+	}
+
+	/* Reply to host that an exception has occurred */
+	sigval = compute_signal(excep_code);
+	send_signal_msg(sigval);
+
+	/* TRAP_VEC exception indicates a software trap inserted in place of
+	   code by GDB so back up PC by one instruction, as this instruction
+	   will later be replaced by its original one.  Do NOT do this for
+	   trap 0xff, since that indicates a compiled-in breakpoint which
+	   will not be replaced (and we would retake the trap forever) */
+	if ((excep_code == TRAP_VEC) && (trapa_value != (0xff << 2))) {
+		trap_registers.pc -= 2;
+	}
+
+	/* Undo any stepping we may have done */
+	undo_single_step();
+
+	while (1) {
+
+		out_buffer[0] = 0;
+		get_packet(in_buffer, BUFMAX);
+
+		/* Examine first char of buffer to see what we need to do */
+		switch (in_buffer[0]) {
+
+		case '?':	/* Send which signal we've received */
+			send_signal_msg(sigval);
+			break;
+
+		case 'g':	/* Return the values of the CPU registers */
+			send_regs_msg();
+			break;
+
+		case 'G':	/* Set the value of the CPU registers */
+			set_regs_msg();
+			break;
+
+		case 'm':	/* Read LLLL bytes address AA..AA */
+			read_mem_msg();
+			break;
+
+		case 'M':	/* Write LLLL bytes address AA..AA, ret OK */
+			write_mem_msg(0);	/* 0 = data in hex */
+			break;
+
+		case 'X':	/* Write LLLL bytes esc bin address AA..AA */
+			if (kgdb_bits == '8')
+				write_mem_msg(1); /* 1 = data in binary */
+			else
+				send_empty_msg();
+			break;
+
+		case 'C':	/* Continue, signum included, we ignore it */
+			continue_with_sig_msg();
+			return;
+
+		case 'c':	/* Continue at address AA..AA (optional) */
+			continue_msg();
+			return;
+
+		case 'S':	/* Step, signum included, we ignore it */
+			step_with_sig_msg();
+			return;
+
+		case 's':	/* Step one instruction from AA..AA */
+			step_msg();
+			return;
+
+#ifdef CONFIG_KGDB_THREAD
+
+		case 'H':	/* Task related */
+			set_thread_msg();
+			break;
+
+		case 'T':	/* Query thread status */
+			thread_status_msg();
+			break;
+
+		case 'q':	/* Handle query - currently thread-related */
+			query_msg();
+			break;
+#endif
+
+		case 'k':	/* 'Kill the program' with a kernel ? */
+			break;
+
+		case 'D':	/* Detach from program, send reply OK */
+			kgdb_in_gdb_mode = 0;
+			send_ok_msg();
+			get_debug_char();
+			return;
+
+		default:
+			send_empty_msg();
+			break;
+		}
+	}
+}
+
+/* There has been an exception, most likely a breakpoint. */
+void kgdb_handle_exception(struct pt_regs *regs)
+{
+	int excep_code, vbr_val;
+	int count;
+	int trapa_value = ctrl_inl(TRA);
+
+	/* Copy kernel regs (from stack) */
+	for (count = 0; count < 16; count++)
+		trap_registers.regs[count] = regs->regs[count];
+	trap_registers.pc = regs->pc;
+	trap_registers.pr = regs->pr;
+	trap_registers.sr = regs->sr;
+	trap_registers.gbr = regs->gbr;
+	trap_registers.mach = regs->mach;
+	trap_registers.macl = regs->macl;
+
+	asm("stc vbr, %0":"=r"(vbr_val));
+	trap_registers.vbr = vbr_val;
+
+	/* Get excode for command loop call, user access */
+	asm("stc r2_bank, %0":"=r"(excep_code));
+	kgdb_excode = excep_code;
+
+	/* Other interesting environment items for reference */
+	asm("stc r6_bank, %0":"=r"(kgdb_g_imask));
+	kgdb_current = current;
+	kgdb_trapa_val = trapa_value;
+	kgdb_tregs = regs;
+
+	/* Act on the exception */
+	kgdb_command_loop(excep_code >> 5, trapa_value);
+
+	kgdb_current = NULL;
+
+	/* Copy back the (maybe modified) registers */
+	for (count = 0; count < 16; count++)
+		regs->regs[count] = trap_registers.regs[count];
+	regs->pc = trap_registers.pc;
+	regs->pr = trap_registers.pr;
+	regs->sr = trap_registers.sr;
+	regs->gbr = trap_registers.gbr;
+	regs->mach = trap_registers.mach;
+	regs->macl = trap_registers.macl;
+
+	vbr_val = trap_registers.vbr;
+	asm("ldc %0, vbr": :"r"(vbr_val));
+
+	return;
+}
+
+/* Trigger a breakpoint by function */
+void breakpoint(void)
+{
+	if (!kgdb_enabled) {
+		kgdb_enabled = 1;
+		kgdb_init();
+	}
+	BREAKPOINT();
+}
+
+/* Initialise the KGDB data structures and serial configuration */
+int kgdb_init(void)
+{
+	if (!kgdb_enabled)
+		return 1;
+
+	in_nmi = 0;
+	kgdb_nofault = 0;
+	stepped_opcode = 0;
+	kgdb_in_gdb_mode = 0;
+
+	/* Set up for serial comms */
+	if (kgdb_serial_setup == NULL) {
+		KGDB_PRINTK("no serial init function!!\n");
+		return -1;
+	}
+
+	if (kgdb_serial_setup() != 0) {
+		KGDB_PRINTK("serial setup error\n");
+		return -1;
+	}
+
+	/* Init ptr to exception handler */
+	kgdb_debug_hook = kgdb_handle_exception;
+	kgdb_bus_err_hook = kgdb_handle_bus_error;
+
+	/* Enter kgdb now if requested, or just report init done */
+	if (kgdb_halt) {
+		kgdb_in_gdb_mode = 1;
+		put_debug_char('+');
+		breakpoint();
+	}
+	else
+	{
+		KGDB_PRINTK("stub is initialized.\n");
+	}
+
+	return 0;
+}
+
+/* Make function available for "user messages"; console will use it too. */
+
+char gdbmsgbuf[BUFMAX];
+#define MAXOUT ((BUFMAX-2)/2)
+
+static void kgdb_msg_write(const char *s, unsigned count)
+{
+	int i;
+	int wcount;
+	char *bufptr;
+
+	/* 'O'utput */
+	gdbmsgbuf[0] = 'O';
+
+	/* Fill and send buffers... */
+	while (count > 0) {
+		bufptr = gdbmsgbuf + 1;
+
+		/* Calculate how many this time */
+		wcount = (count > MAXOUT) ? MAXOUT : count;
+		
+		/* Pack in hex chars */
+		for (i = 0; i < wcount; i++)
+			bufptr = pack_hex_byte(bufptr, s[i]);
+		*bufptr = '\0';
+
+		/* Move up */
+		s += wcount;
+		count -= wcount;
+
+		/* Write packet */
+		put_packet(gdbmsgbuf);
+	}
+}
+
+static void kgdb_to_gdb(const char *s)
+{
+	kgdb_msg_write(s, strlen(s));
+}
+
+#ifdef CONFIG_SH_KGDB_CONSOLE
+void kgdb_console_write(struct console *co, const char *s, unsigned count)
+{
+	/* Bail if we're not talking to GDB */
+	if (!kgdb_in_gdb_mode)
+		return;
+
+	kgdb_msg_write(s, count);
+}
+#endif
diff -urN linux-2.4.21-bk11/arch/sh/kernel/led_se.c linux-2.4.21-bk12/arch/sh/kernel/led_se.c
--- linux-2.4.21-bk11/arch/sh/kernel/led_se.c	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/led_se.c	2003-07-17 02:52:28.000000000 -0700
@@ -10,7 +10,12 @@
  */
 
 #include <linux/config.h>
+
+#ifdef CONFIG_SH_7751_SOLUTION_ENGINE
+#include <asm/hitachi_7751se.h>
+#else
 #include <asm/hitachi_se.h>
+#endif
 
 static void mach_led(int position, int value)
 {
diff -urN linux-2.4.21-bk11/arch/sh/kernel/mach_7751se.c linux-2.4.21-bk12/arch/sh/kernel/mach_7751se.c
--- linux-2.4.21-bk11/arch/sh/kernel/mach_7751se.c	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/mach_7751se.c	2003-07-17 02:52:28.000000000 -0700
@@ -18,7 +18,7 @@
 
 #include <asm/io_7751se.h>
 
-void heartbeat_7751se(void);
+void heartbeat_se(void);
 void setup_7751se(void);
 void init_7751se_IRQ(void);
 
@@ -67,7 +67,7 @@
 	mv_init_arch:		setup_7751se,
 	mv_init_irq:		init_7751se_IRQ,
 #ifdef CONFIG_HEARTBEAT
-	mv_heartbeat:		heartbeat_7751se,
+	mv_heartbeat:		heartbeat_se,
 #endif
 
 	mv_rtc_gettimeofday:	sh_rtc_gettimeofday,
diff -urN linux-2.4.21-bk11/arch/sh/kernel/mach_hs7729pci.c linux-2.4.21-bk12/arch/sh/kernel/mach_hs7729pci.c
--- linux-2.4.21-bk11/arch/sh/kernel/mach_hs7729pci.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/mach_hs7729pci.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,81 @@
+/*
+ * linux/arch/sh/kernel/mach_hs7729pci.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Machine vector for the Hitachi Semiconductor ans Devices HS7729PCI
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+#include <asm/rtc.h>
+
+#include <asm/io_hs7729pci.h>
+
+void setup_hs7729pci(void);
+void init_hs7729pci_IRQ(void);
+
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_hs7729pci __initmv = {
+	mv_name:		"HS7729PCI",
+
+#if defined(__SH4__)
+	mv_nr_irqs:		48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+	mv_nr_irqs:		32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+	mv_nr_irqs:		61,
+#endif
+
+	mv_inb:			hs7729pci_inb,
+	mv_inw:			hs7729pci_inw,
+	mv_inl:			hs7729pci_inl,
+	mv_outb:		hs7729pci_outb,
+	mv_outw:		hs7729pci_outw,
+	mv_outl:		hs7729pci_outl,
+
+	mv_inb_p:		hs7729pci_inb_p,
+	mv_inw_p:		hs7729pci_inw,
+	mv_inl_p:		hs7729pci_inl,
+	mv_outb_p:		hs7729pci_outb_p,
+	mv_outw_p:		hs7729pci_outw,
+	mv_outl_p:		hs7729pci_outl,
+
+	mv_insb:		hs7729pci_insb,
+	mv_insw:		hs7729pci_insw,
+	mv_insl:		hs7729pci_insl,
+	mv_outsb:		hs7729pci_outsb,
+	mv_outsw:		hs7729pci_outsw,
+	mv_outsl:		hs7729pci_outsl,
+
+	mv_readb:		generic_readb,
+	mv_readw:		generic_readw,
+	mv_readl:		generic_readl,
+	mv_writeb:		generic_writeb,
+	mv_writew:		generic_writew,
+	mv_writel:		generic_writel,
+
+	mv_ioremap:		hs7729pci_ioremap,
+	mv_iounmap:		hs7729pci_iounmap,
+
+	mv_isa_port2addr:	hs7729pci_isa_port2addr,
+
+	mv_init_arch:		setup_hs7729pci,
+	mv_init_irq:		init_hs7729pci_IRQ,
+
+	mv_rtc_gettimeofday:	sh_rtc_gettimeofday,
+	mv_rtc_settimeofday:	sh_rtc_settimeofday,
+
+	mv_hw_hs7729pci:	1,
+};
+ALIAS_MV(hs7729pci)
diff -urN linux-2.4.21-bk11/arch/sh/kernel/mach_keywest.c linux-2.4.21-bk12/arch/sh/kernel/mach_keywest.c
--- linux-2.4.21-bk11/arch/sh/kernel/mach_keywest.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/mach_keywest.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,70 @@
+/*
+ * linux/arch/sh/kernel/mach_keywest.c
+ *
+ * Machine vector for HSA KeyWest Evaluiation board
+ *
+ * Copyright (C) 2001 Lineo, Japan
+ *   
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+#include <asm/io.h>
+#include <asm/io_keywest.h>
+#include <asm/irq.h>
+
+/*
+ * The Machine Vector
+ */
+extern void heartbeat_keywest(void);
+extern void setup_keywest(void);
+extern void init_keywest_IRQ(void);
+
+struct sh_machine_vector mv_keywest __initmv = {
+	mv_name:		"Key West",
+	mv_nr_irqs:		NR_IRQS,     // Defined in <asm/irq.h>
+	mv_inb:			keywest_inb,
+	mv_inw:			keywest_inw,
+	mv_inl:			keywest_inl,
+	mv_outb:		keywest_outb,
+	mv_outw:		keywest_outw,
+	mv_outl:		keywest_outl,
+
+	mv_inb_p:		keywest_inb_p,
+	mv_inw_p:		keywest_inw,
+	mv_inl_p:		keywest_inl,
+	mv_outb_p:		keywest_outb_p,
+	mv_outw_p:		keywest_outw,
+	mv_outl_p:		keywest_outl,
+
+	mv_insb:		keywest_insb,
+	mv_insw:		keywest_insw,
+	mv_insl:		keywest_insl,
+	mv_outsb:		keywest_outsb,
+	mv_outsw:		keywest_outsw,
+	mv_outsl:		keywest_outsl,
+
+	mv_readb:		generic_readb,
+	mv_readw:		generic_readw,
+	mv_readl:		generic_readl,
+	mv_writeb:		generic_writeb,
+	mv_writew:		generic_writew,
+	mv_writel:		generic_writel,
+
+	mv_ioremap:		generic_ioremap,
+	mv_iounmap:		generic_iounmap,
+
+	mv_isa_port2addr:	keywest_isa_port2addr,
+	mv_irq_demux:       keywest_irq_demux,
+
+	mv_init_arch:		setup_keywest,
+	mv_init_irq:		init_keywest_IRQ,
+	mv_rtc_gettimeofday:	sh_rtc_gettimeofday,
+	mv_rtc_settimeofday:	sh_rtc_settimeofday,
+
+};
+ALIAS_MV(keywest)
diff -urN linux-2.4.21-bk11/arch/sh/kernel/mach_snapgear.c linux-2.4.21-bk12/arch/sh/kernel/mach_snapgear.c
--- linux-2.4.21-bk11/arch/sh/kernel/mach_snapgear.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/mach_snapgear.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,82 @@
+/*
+ * linux/arch/sh/kernel/mach_snapgear.c
+ *
+ * Minor tweak of mach_se.c file to reference SnapGear items.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Machine vector for the Hitachi 7751 SolutionEngine
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io_snapgear.h>
+
+extern void setup_snapgear(void);
+extern void init_snapgear_IRQ(void);
+
+extern void snapgear_rtc_gettimeofday(struct timeval *tv);
+extern int snapgear_rtc_settimeofday(const struct timeval *tv);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_snapgear __initmv = {
+	mv_name:		"SnapGear",
+
+	mv_nr_irqs:		72,
+
+	mv_inb:			snapgear_inb,
+	mv_inw:			snapgear_inw,
+	mv_inl:			snapgear_inl,
+	mv_outb:		snapgear_outb,
+	mv_outw:		snapgear_outw,
+	mv_outl:		snapgear_outl,
+
+	mv_inb_p:		snapgear_inb_p,
+	mv_inw_p:		snapgear_inw,
+	mv_inl_p:		snapgear_inl,
+	mv_outb_p:		snapgear_outb_p,
+	mv_outw_p:		snapgear_outw,
+	mv_outl_p:		snapgear_outl,
+
+	mv_insb:		snapgear_insb,
+	mv_insw:		snapgear_insw,
+	mv_insl:		snapgear_insl,
+	mv_outsb:		snapgear_outsb,
+	mv_outsw:		snapgear_outsw,
+	mv_outsl:		snapgear_outsl,
+
+	mv_readb:		snapgear_readb,
+	mv_readw:		snapgear_readw,
+	mv_readl:		snapgear_readl,
+	mv_writeb:		snapgear_writeb,
+	mv_writew:		snapgear_writew,
+	mv_writel:		snapgear_writel,
+
+	mv_ioremap:		generic_ioremap,
+	mv_iounmap:		generic_iounmap,
+
+	mv_isa_port2addr:	snapgear_isa_port2addr,
+
+	mv_init_arch:		setup_snapgear,
+	mv_init_irq:		init_snapgear_IRQ,
+
+#ifndef CONFIG_RTC
+	mv_rtc_gettimeofday:	sh_rtc_gettimeofday,
+	mv_rtc_settimeofday:	sh_rtc_settimeofday,
+#else
+	mv_rtc_gettimeofday:	snapgear_rtc_gettimeofday,
+	mv_rtc_settimeofday:	snapgear_rtc_settimeofday,
+#endif
+
+	mv_hw_snapgear:		1,
+};
+ALIAS_MV(snapgear)
diff -urN linux-2.4.21-bk11/arch/sh/kernel/pci-sd0001.c linux-2.4.21-bk12/arch/sh/kernel/pci-sd0001.c
--- linux-2.4.21-bk11/arch/sh/kernel/pci-sd0001.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/pci-sd0001.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,795 @@
+/*
+ *   $Id: pci-sd0001.c,v 1.1.2.1 2003/06/24 08:40:50 dwmw2 Exp $
+ *
+ *   linux/arch/sh/kernel/pci-sd0001.c
+ *
+ *   Support Hitachi Semcon SD0001 SH3 PCI Host Bridge .
+ *  
+ *
+ *   Copyright (C) 2000  Hitachi ULSI Systems Co., Ltd.
+ *   All Rights Reserved.
+ *
+ *   Copyright (C) 2001-2003 Red Hat, Inc.
+ *
+ *   Authors:	Masayuki Okada (macha@adc.hitachi-ul.co.jp)
+ *              David Woodhouse (dwmw2@redhat.com)
+ *
+ *
+ *   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, or (at your option)
+ *   any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/vmalloc.h>
+
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "pci-sd0001.h"
+
+spinlock_t sd0001_indirect_lock = SPIN_LOCK_UNLOCKED;
+
+int remap_area_pages(unsigned long address, unsigned long phys_addr,
+                     unsigned long size, unsigned long flags);
+
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+#define SD0001_INDIR_TIME	1000000		/* ´ÖÀÜ¥¢¥¯¥»¥¹´°Î»ÂÔ¤ÁºÇÂç²ó¿ô */
+
+static char *err_int_msg [] = {
+	"Detect Master Abort",
+	"Assert Master Abort",
+	"Detect Target Abort",
+	"Assert Target Abort",
+	"Assert PERR",
+	"Detect PERR",
+	"Detect SERR",
+	"Asster SERR",
+	"Bus Timeout",
+	"Bus Retry Over",
+};
+
+/*
+ * PCI¥Ð¥¹¤Î¥Ð¥¹¥ê¥»¥Ã¥È¼Â¹Ô
+ */
+static void sd0001_bus_reset(void)
+{
+	sd0001_writel(SD0001_RST_BUSRST, RESET);
+
+	udelay(64);
+
+	sd0001_writel(0, RESET);
+}
+
+/*
+ * SD0001¥½¥Õ¥È¥ê¥»¥Ã¥È
+ */
+static void sd0001_chip_reset(void)
+{
+	sd0001_writel(SD0001_RST_SWRST, RESET);
+}
+
+
+#define ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
+
+static void
+sd0001_int_pcierr (int irq, void *dummy, struct pt_regs *regs)
+{
+	static char  errStrings[30*12];
+	u32 int_status;
+	u32 mask;
+	u32 indrct_flg;
+	int reset_fatal;
+	int   i;
+	int   to_cnt = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sd0001_indirect_lock, flags);
+
+	if ((int_status = (sd0001_readl(INT_STS1) & SD0001_INT_BUSERR))) {
+		DBG("pciIntErrorHandle Called: status 0x%08x\n", int_status, 0, 0, 0, 0, 0);
+
+		for (mask = 1 << 20, i = 0, errStrings[0] = '\0'; i < 11; i++, mask <<= 1) {
+			if (int_status & mask) {
+/* 				err_int_cnt[i] ++; */
+				strcat(errStrings, err_int_msg[i]);
+				strcat(errStrings, ", ");
+			}
+		}
+		i = strlen(errStrings);
+		errStrings[i-2]= '\0';
+
+		printk(KERN_ERR "PCI Bus 0x%08x(%s) Error\n", int_status, errStrings);
+
+		reset_fatal = 0;
+
+		if (int_status & (SD0001_INT_SSERR|SD0001_INT_RPERR
+				  |SD0001_INT_SPERR|SD0001_INT_STABT
+				  |SD0001_INT_RTABT|SD0001_INT_RMABT)) {
+			/* Clear of Configration Status Bits */
+			sd0001_writel(4, INDIRECT_ADR);
+			sd0001_writel(0xf9000000, INDIRECT_DATA);
+			sd0001_writel(0x000c0002, INDIRECT_CTL);
+			to_cnt = 0;
+			while (((indrct_flg = sd0001_readl(INDIRECT_STS)) & SD0001_INDRCTF_INDFLG)
+			       && (to_cnt++ < SD0001_INDIR_TIME))
+				;
+
+
+			if (indrct_flg & SD0001_INDRCTF_INDFLG) {
+				panic("SD0001 Fatal Error 1\n");
+			} else {
+				if (indrct_flg & SD0001_INDRCTF_MABTRCV) {
+					sd0001_writel(SD0001_INDRCTC_FLGRESET, INDIRECT_CTL);
+					reset_fatal = -1;
+				}
+			}
+			int_status = sd0001_readl(INT_STS1) & SD0001_INT_BUSERR;
+		}
+
+		if (int_status != 0) {
+			sd0001_writel(int_status, INT_STS1); /* ³ä¤ê¹þ¤ß¥¯¥ê¥¢ */
+
+			if (reset_fatal || (sd0001_readl(INT_STS2) & SD0001_INT_BUSERR)) {
+				printk(KERN_CRIT "Fatal Error:SD0001 PCI Status Can't Clear 0x%08x\n",
+				       int_status & 0x7fffffff);
+				sd0001_writel(sd0001_readl(INT_ENABLE) & ~int_status, INT_ENABLE);
+				/* Masked Error Interrupt */
+			}
+		}
+	}
+	spin_unlock_irqrestore(&sd0001_indirect_lock, flags);
+}
+
+
+static inline u32 convert_dev_to_addr (struct pci_dev *dev, u32 reg)
+{
+	return (SD0001_CONFIG_ADDR_EN
+		| (dev->bus->number << 16)
+		| ((dev->devfn & 0xff) << 8)
+		| (reg & 0xff)
+		| ((dev->bus->number)?0x00:0x01));
+}
+
+
+static int sd0001_indirect_RW (u32  addr, u32 cmd, u32  be,
+				  u32  rw, u32  *data)
+{
+	u32 indrct_flg;
+	u32 int_sts;
+	u32 to_cnt = 0;
+	int st = PCIBIOS_SUCCESSFUL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sd0001_indirect_lock, flags);
+	if ((cmd & SD0001_INDRCTC_CMD_MASK) == SD0001_INDRCTC_CMD_MEMR
+	    || (cmd & SD0001_INDRCTC_CMD_MASK) == SD0001_INDRCTC_CMD_MEMW)
+		sd0001_writel(addr & 0xfffffffc, INDIRECT_ADR);
+	else
+		sd0001_writel(addr, INDIRECT_ADR);
+
+	if (rw == SD0001_INDRCTC_IOWT || rw == SD0001_INDRCTC_COWT)
+		sd0001_writel(*data, INDIRECT_DATA);
+
+	sd0001_writel(be | cmd | rw , INDIRECT_CTL);
+
+	while (((indrct_flg = sd0001_readl(INDIRECT_STS)) & SD0001_INDRCTF_INDFLG)
+	       && (to_cnt++ < SD0001_INDIR_TIME));
+
+	int_sts = sd0001_readl(INT_STS1) & SD0001_INT_BUSERR;
+    
+	if (indrct_flg & SD0001_INDRCTF_INDFLG) {	/* ¥¿¥¤¥à¥¢¥¦¥È */
+		printk("SD0001 Fatal Error 2\n");
+		spin_unlock_irqrestore(&sd0001_indirect_lock, flags);
+
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	if (int_sts != 0 || (indrct_flg & SD0001_INDRCTF_MABTRCV) != 0) {
+		if ((st = (indrct_flg & SD0001_INDRCTF_MABTRCV) >> 19) != 0) {
+			sd0001_writel(SD0001_INDRCTC_FLGRESET, INDIRECT_CTL);
+			st |= 0x80000000;
+		}
+
+		st |= 0x80000000 | int_sts;
+
+		if ((int_sts & (SD0001_INT_SSERR|SD0001_INT_RPERR
+				|SD0001_INT_SPERR|SD0001_INT_STABT
+				|SD0001_INT_RTABT|SD0001_INT_RMABT))
+		    || (indrct_flg & SD0001_INDRCTF_MABTRCV)) {
+			/* Clear of Configration Status Bits */
+			sd0001_writel(4, INDIRECT_ADR);
+			sd0001_writel(0xf9000000, INDIRECT_DATA);
+			sd0001_writel(0x000c0002, INDIRECT_CTL);
+
+			to_cnt = 0;
+			while (((indrct_flg = sd0001_readl(INDIRECT_STS)) & SD0001_INDRCTF_INDFLG)
+			       && (to_cnt++ < SD0001_INDIR_TIME));
+
+			if (indrct_flg & SD0001_INDRCTF_INDFLG) {	/* ¥¿¥¤¥à¥¢¥¦¥È */
+				panic("SD0001 Fatal Error 3\n");
+			}
+
+			if (indrct_flg & SD0001_INDRCTF_MABTRCV) {
+				
+				sd0001_writel(SD0001_INDRCTC_FLGRESET, INDIRECT_CTL);
+			}
+		}
+		
+		printk(KERN_ERR "PCI Bus Error: status 0x%08x\n", st);
+
+		if ((int_sts = sd0001_readl(INT_STS1) & SD0001_INT_BUSERR) != 0) {
+			sd0001_writel(int_sts, INT_STS1);	/* ³ä¤ê¹þ¤ß¥¯¥ê¥¢ */
+			
+			if (sd0001_readl(INT_STS2) & SD0001_INT_BUSERR) {
+				printk(KERN_CRIT "Fatal Error:SD0001 PCI Status Can't Clear 0x%08x\n",
+				       sd0001_readl(INT_STS2) & SD0001_INT_BUSERR);
+				sd0001_writel(sd0001_readl(INT_ENABLE) & ~int_sts, INT_ENABLE); /* Masked Error Interrupt */
+			}
+		}
+
+		*data = 0xffffffff;
+	} else {
+		if (rw != SD0001_INDRCTC_IOWT && rw != SD0001_INDRCTC_COWT)
+			*data = sd0001_readl(INDIRECT_DATA);
+	}
+
+	spin_unlock_irqrestore(&sd0001_indirect_lock, flags);
+	return st;
+}
+
+static inline
+int sd0001_config_RW (struct pci_dev *dev, u32 reg, u32 be, u32 rw, u32 *data)
+{
+	u32  reg_addr = convert_dev_to_addr(dev, reg);
+
+	if (reg_addr == 0) {
+		*data = 0xffffffff;
+		return PCIBIOS_SUCCESSFUL;
+	}
+    
+	return sd0001_indirect_RW (reg_addr, 0, be, rw, data);
+
+}
+
+
+static int sd0001_read_config_byte(struct pci_dev *dev, int reg, u8 *val)
+{
+	int  offset;
+	u32  be;
+	int  re;
+	union {
+		u32 ldata;
+		u8  bdata[4];
+	} work;
+
+	be = SD0001_INDRCTC_BE_BYTE << (reg & 0x03);
+	re = sd0001_config_RW (dev, reg, be, SD0001_INDRCTC_CORD, &work.ldata);
+
+#if __LITTLE_ENDIAN__
+	offset = reg & 0x03;
+#else  /* __LITTLE_ENDIAN__ */
+	offset = 3 - (reg & 0x03);
+#endif /* __LITTLE_ENDIAN__ */
+	*val = work.bdata[offset];
+
+	return re;
+
+}
+
+
+static int sd0001_read_config_word(struct pci_dev *dev, int reg, u16 *val)
+{
+	int  offset;
+	u32 be;
+	int  re;
+	union {
+		u32 ldata;
+		u16 wdata[2];
+	} work;
+
+	be = SD0001_INDRCTC_BE_WORD << (reg & 0x02);
+	
+	re = sd0001_config_RW (dev, reg, be, SD0001_INDRCTC_CORD, &work.ldata);
+	
+#if __LITTLE_ENDIAN__
+	offset = (reg >> 1) & 0x01;
+#else  /* __LITTLE_ENDIAN__ */
+	offset = 1 - ((reg >> 1) & 0x01);
+#endif /* __LITTLE_ENDIAN__ */
+	
+	*val = work.wdata[offset];
+	
+	return re;
+}
+
+
+static int sd0001_read_config_dword(struct pci_dev *dev, int reg, u32 *val)
+{
+	return sd0001_config_RW (dev, reg, SD0001_INDRCTC_BE_LONG,
+			      SD0001_INDRCTC_CORD, val);
+}
+
+static int sd0001_write_config_byte (struct pci_dev *dev, int reg, u8 val)
+{
+	int  offset;
+	u32 be;
+	union {
+		u32 ldata;
+		u8  bdata[4];
+	} work;
+
+	be = SD0001_INDRCTC_BE_BYTE << (reg & 0x03);
+#if __LITTLE_ENDIAN__
+	offset = reg & 0x03;
+#else  /* __LITTLE_ENDIAN__ */
+	offset = 3 - (reg & 0x03);
+#endif /* __LITTLE_ENDIAN__ */
+	work.bdata[offset] = val;
+
+	return sd0001_config_RW(dev, reg, be, SD0001_INDRCTC_COWT, &work.ldata);
+    
+}
+
+
+static int sd0001_write_config_word (struct pci_dev *dev, int reg, u16 val)
+{
+	int  offset;
+	u32 be;
+	union {
+		u32  ldata;
+		u16  wdata[2];
+	} work;
+
+
+	be = SD0001_INDRCTC_BE_WORD << (reg & 0x02);
+#if __LITTLE_ENDIAN__
+	offset = (reg >> 1) & 0x01;
+#else  /* __LITTLE_ENDIAN__ */
+	offset = 1 - ((reg >> 1) & 0x01);
+#endif /* __LITTLE_ENDIAN__ */
+
+	work.wdata[offset] = val;
+
+	return sd0001_config_RW (dev, reg, be, SD0001_INDRCTC_COWT, &work.ldata);
+
+}
+
+
+static int sd0001_write_config_dword (struct pci_dev *dev, int reg, u32 val)
+{
+	return sd0001_config_RW (dev, reg, SD0001_INDRCTC_BE_LONG, SD0001_INDRCTC_COWT, &val);
+}
+
+static struct pci_ops sd0001_pci_ops = 
+{
+	.read_byte =	sd0001_read_config_byte,
+	.read_word =	sd0001_read_config_word,
+	.read_dword =	sd0001_read_config_dword,
+	.write_byte =	sd0001_write_config_byte,
+	.write_word =	sd0001_write_config_word,
+	.write_dword =	sd0001_write_config_dword
+};
+
+int __init pci_setup_sd0001 (void)
+{
+	sd0001_writel(0, INT_ENABLE);		/* all Interrupt = Mask */
+
+	sd0001_bus_reset();
+
+	/*
+	 * PCI¥Ð¥¹À©¸æ¤ÎÆ°ºî¥â¡¼¥É(MCW0¥ì¥¸¥¹¥¿)ÀßÄê
+	 * ¡¦PCI¥Ð¥¹¤Î¥ê¥È¥é¥¤²ó¿ô : Ìµ¸Â²ó
+	 * ¡¦¥Ð¥¹¥°¥é¥ó¥É¤ÎÍÞ»ß¤Ê¤·
+	 */
+#if __LITTLE_ENDIAN__
+	sd0001_writel(0x0000, PCI_CTL);
+#else
+	sd0001_writel(SD0001_CTL_MASTER_SWAP | SD0001_CTL_PCI_EDCONV, PCI_CTL);
+#endif
+	sd0001_writel(0, PCI_IO_OFFSET);
+	sd0001_writel(PCIBIOS_MIN_MEM, PCI_MEM_OFFSET);
+
+
+	if (request_irq(CONFIG_PCI_SD0001_IRQ, &sd0001_int_pcierr, SA_SHIRQ, "PCI Bus Error", NULL))
+		printk(KERN_ERR "Can't Setup PCI Bus Error Interrupt\n");
+
+	/* FIXME: Enable INT[ABCD] only when devices actually want them.
+	   We should probably demux them so they appear to the kernel as
+	   separate IRQs */
+	sd0001_writel(SD0001_INT_INTEN|SD0001_INT_BUSERR
+		|SD0001_INT_INTD|SD0001_INT_INTC|SD0001_INT_INTB
+		|SD0001_INT_INTA, INT_ENABLE);
+
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+void __init
+pcibios_fixup_pbus_ranges(struct pci_bus * bus,
+	struct pbus_set_ranges_data * ranges)
+{
+	ranges->io_start -= bus->resource[0]->start;
+	ranges->io_end -= bus->resource[0]->start;
+	ranges->mem_start -= bus->resource[1]->start;
+	ranges->mem_end -= bus->resource[1]->start;
+}
+
+
+static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
+{
+        return PCI_SLOT(dev->devfn);
+}
+
+static int __init sd0001_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return CONFIG_PCI_SD0001_IRQ;
+}
+
+void __init pcibios_init(void)
+{
+	printk(KERN_NOTICE "Linux/SH SD0001 PCI Initialise\n");
+	
+	ioport_resource.end = 0xffff;
+	iomem_resource.end = 0xfeffffff;
+
+	pci_setup_sd0001();
+	pci_scan_bus(0, &sd0001_pci_ops, NULL);
+
+	pci_assign_unassigned_resources();
+
+	pci_fixup_irqs(no_swizzle, sd0001_map_irq);
+}
+
+char * __init pcibios_setup(char *str)
+{
+        return str;
+}
+
+extern unsigned long memory_start, memory_end;
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct list_head *list;
+
+	list_for_each(list, &bus->devices) {
+		struct pci_dev *dev = pci_dev_b(list);
+		u16 cmd;
+		if (dev->class >> 8 == PCI_CLASS_BRIDGE_HOST) {
+			memset(&dev->resource[1], 0, sizeof(struct resource));
+			dev->resource[1].start = __pa(memory_start);
+			dev->resource[1].end = __pa(memory_end)-1;
+			dev->resource[1].flags = IORESOURCE_MEM|IORESOURCE_PREFETCH;
+			dev->resource[1].name = "PCI Host RAM";
+			request_resource(&iomem_resource, &dev->resource[1]);
+
+#if 0
+			printk("res1 (@%p) %s %08lx %08lx %x %p %p %p\n", 
+			       &dev->resource[1],
+			       dev->resource[1].name,
+			       dev->resource[1].start,
+			       dev->resource[1].end,
+			       dev->resource[1].flags,
+			       dev->resource[1].parent,
+			       dev->resource[1].sibling,
+			       dev->resource[1].child);
+#endif
+			pcibios_update_resource(dev, bus->resource[1], 
+						&dev->resource[1], 1);
+
+			cmd = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+			pci_write_config_word(dev, PCI_COMMAND, cmd);
+			pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
+		}
+	}
+}
+
+
+
+/* Add future fixups here... */
+struct pci_fixup pcibios_fixups[] = {
+        { 0 }
+};
+
+
+        /*
+         * Mapping for PCI Devices.
+	 * The SD0001 has a 48MiB window onto the PCI memory space, mapped
+	 * into the CPU's address space at 0xb1000000-0xb3ffffff. 
+	 * The range of the PCI space which is accessible is controlled
+	 * by the SD0001's PCI_MEM_OFFSET register, which has a granularity
+	 * of 64MiB. 
+	 *
+	 * As far as I can tell from the little I can understand of
+	 * the SD0001 documentation and from the behaviour of the
+	 * device, you have a 48MiB window which can only be moved
+	 * with 64MiB granularity. Therefore to the best of my
+	 * knowledge, you cannot access any PCI memory address where
+	 * (<addr> & 0x03000000) == 0x03000000, except by going 
+	 * indirectly through the PCI bridge like we do for configuration
+	 * and I/O cycles.
+	 *
+	 * Hopefully, this is untrue and there's some way of doing it that
+	 * I just don't know because I can't read the docs. For now, we
+	 * allow only access to the first 48MiB of PCI memory space.
+	 *
+	 * In addition to that joy, it appears that when accessing PCI
+	 * memory space directly, the SD0001 swaps address lines #21
+	 * and #22, hence the macro below to swap addresses back
+	 * again.
+	 *
+	 * Me and my baseball bat want a quiet word with someone. 
+	 *
+	 * dwmw2.
+         */
+
+#define unmunge(x) (((x) & ~0x00300000) | ( ((x)&0x00100000) << 1) | ( ((x)&0x00200000) >> 1))
+
+void *sd0001_ioremap(unsigned long phys_addr, unsigned long size)
+{
+        unsigned long offset;
+
+	if ((phys_addr & 0xFFF00000) == ((phys_addr+size) & 0xFFF00000)) {
+		/* It fits within a single mebibyte we can still use the 
+		   directly-mapped region... */
+		return (void *)(SD0001_MEM_BASE-(PCIBIOS_MIN_MEM&0xfc000000)+unmunge(phys_addr));
+	}
+
+	/* It crosses a mebibyte boundary and hence we have to
+	   play VM tricks to make the region which is physically
+	   contiguous on the PCI bus but not physically contiguous
+	   on the SH3 bus appear virtually contiguous to the kernel.
+	   Got that? Did I mention my baseball bat yet? */
+	void * addr;
+	struct vm_struct * area;
+		
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(phys_addr + size - 1) - phys_addr;
+
+	area = get_vm_area(size, VM_IOREMAP);
+	if (!area)
+		return NULL;
+	addr = area->addr;
+
+	phys_addr += SD0001_MEM_BASE;
+	while (size) {
+		unsigned long this_size;
+
+		this_size = 0x100000 - (phys_addr & 0xfffff);
+		this_size = min(this_size, size);
+
+		if (remap_area_pages(VMALLOC_VMADDR(addr),
+				     unmunge(phys_addr), this_size, 
+				     _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_FLAGS_HARD)) {
+			vfree(area->addr);
+			return NULL;
+		}
+		size -= this_size;
+		phys_addr += this_size;
+		addr += this_size;
+	}
+	return (void *) (offset + (char *)area->addr);
+}
+
+void sd0001_iounmap(void *addr)
+{
+	if ((unsigned long)addr >= VMALLOC_START && 
+	    (unsigned long)addr < VMALLOC_END)
+		vfree((void *)((unsigned long)addr & ~PAGE_MASK));
+}
+
+
+static void sd0001_indirect_access_wait(unsigned long i)
+{
+
+	while((sd0001_readl(INDIRECT_STS) & SD0001_INDRCTF_INDFLG)
+	      && --i)
+		;
+
+	if (i == 0) {
+		printk("##### Long Indirect access wait #####\n");
+		mdelay(20);
+	}
+}
+
+static inline void delay(void)
+{
+	ctrl_inw(0xa0000000);
+}
+
+/* PCI IO read long word cycle */
+unsigned long sd0001_inl(unsigned long port)
+{
+	return *(volatile unsigned long *) (SD0001_IO_BASE+port);
+}
+void sd0001_outl(unsigned long value, unsigned long port)
+{
+	*(volatile unsigned long *)(SD0001_IO_BASE+port) = value;
+}
+
+/* The SD0001 doesn't correctly handle byte enables for sub-word
+   accesses, so we have to do it indirectly like we do configuration
+   cycles */
+
+/* PCI IO read byte cycle */
+unsigned char sd0001_inb(unsigned long port)
+{
+	unsigned long work, val, byte_e;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sd0001_indirect_lock, flags);
+	val = 0;
+	byte_e = 0x00010000;
+	work = (port & 0x00000003);
+	byte_e <<= work;
+
+	port &= 0xFFFFFFFC;
+	sd0001_writel(port, INDIRECT_ADR);
+	sd0001_writel(0x00008204 | byte_e, INDIRECT_CTL); /* I/O read cycle */
+	sd0001_indirect_access_wait(100);
+	val = sd0001_readl(INDIRECT_DATA);
+
+	val >>= (work*8);
+	val &= 0x000000FF;
+
+	spin_unlock_irqrestore(&sd0001_indirect_lock, flags);
+
+	return val;
+}
+
+/* PCI IO write byte cycle */
+void sd0001_outb(unsigned char value, unsigned long port)
+{
+	unsigned long work, data, byte_e;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sd0001_indirect_lock, flags);
+	byte_e = 0x00010000;
+	work = (port & 0x00000003);
+	byte_e <<= work;
+
+	data = value;
+	data <<= (work*8);
+
+	port &= 0xFFFFFFFC;
+	sd0001_writel(data, INDIRECT_DATA);
+	sd0001_writel(port, INDIRECT_ADR);
+	sd0001_writel((0x00008308 | byte_e), INDIRECT_CTL);	/* I/O write cycle */
+	sd0001_indirect_access_wait(100);
+
+	spin_unlock_irqrestore(&sd0001_indirect_lock, flags);
+}
+
+/* PCI IO read word cycle */
+unsigned short sd0001_inw(unsigned long port)
+{
+	unsigned long work, val, byte_e;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sd0001_indirect_lock, flags);
+	val = 0;
+	byte_e = 0x00030000;
+	work = (port & 0x00000003);
+	byte_e <<= (work & 0x00000002);
+	work >>= 1;
+
+	port &= 0xFFFFFFFC;
+	sd0001_writel(port, INDIRECT_ADR);
+	sd0001_writel((0x00008204 | byte_e), INDIRECT_CTL);	/* I/O read cycle */
+	sd0001_indirect_access_wait(100);
+	val = sd0001_readl(INDIRECT_DATA) ;
+
+	val >>= (work*16);
+	val &= 0x0000FFFF;
+
+	spin_unlock_irqrestore(&sd0001_indirect_lock, flags);
+
+	return val;
+}
+
+/* PCI IO write word cycle */
+void sd0001_outw(unsigned short value, unsigned long port)
+{
+	unsigned long work, data, byte_e;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sd0001_indirect_lock, flags);
+	byte_e = 0x00030000;
+	work = (port & 0x00000003);
+	byte_e <<= (work & 0x00000002);
+	work >>= 1;
+
+	port &= 0xFFFFFFFC;
+	data = value;
+	data <<= (work*16);
+
+	sd0001_writel(data, INDIRECT_DATA);
+	sd0001_writel(port, INDIRECT_ADR);
+	sd0001_writel((0x00008308 | byte_e), INDIRECT_CTL);	/* I/O write cycle */
+	sd0001_indirect_access_wait(100);
+	spin_unlock_irqrestore(&sd0001_indirect_lock, flags);
+}
+
+void sd0001_insb(unsigned long port, void *addr, unsigned long count)
+{
+
+	while (count--)
+		*((unsigned char *) addr)++ = (unsigned char)sd0001_inb(port);
+}
+
+void sd0001_insw(unsigned long port, void *addr, unsigned long count)
+{
+
+	while (count--)
+		*((unsigned short *) addr)++ = (unsigned short)sd0001_inw(port);
+}
+
+void sd0001_insl(unsigned long port, void *addr, unsigned long count)
+{
+
+	while (count--)
+		*((unsigned long *) addr)++ = sd0001_inl(port);
+}
+
+void sd0001_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+
+	while (count--)
+		sd0001_outb(*((unsigned char *)addr)++, port);
+}
+
+void sd0001_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+
+	while (count--)
+		sd0001_outw(*((unsigned short *)addr)++, port);
+}
+
+void sd0001_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+
+	while (count--)
+		sd0001_outl(*((unsigned long *)addr)++, port);
+}
+
+unsigned char sd0001_inb_p(unsigned long port)
+{
+	unsigned long v;
+
+	v = sd0001_inb(port);
+	delay();
+	return v;
+}
+
+void sd0001_outb_p(unsigned char value, unsigned long port)
+{
+
+	sd0001_outb(value, port);
+	delay();
+}
diff -urN linux-2.4.21-bk11/arch/sh/kernel/pci-sd0001.h linux-2.4.21-bk12/arch/sh/kernel/pci-sd0001.h
--- linux-2.4.21-bk11/arch/sh/kernel/pci-sd0001.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/pci-sd0001.h	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,248 @@
+/*
+ *   $Id: pci-sd0001.h,v 1.1.2.1 2003/06/24 08:40:50 dwmw2 Exp $
+ *
+ *   linux/arch/sh/kernel/pci_sd0001.h
+ *
+ *   Support Hitachi Semcon SD0001 SH3 PCI Host Bridge .
+ *  
+ *
+ *   Copyright (C) 2000  Masayuki Okada (macha@adc.hitachi-ul.co.jp)
+ *                       Hitachi ULSI Systems Co., Ltd.
+ *
+ *   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, or (at your option)
+ *   any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ *
+ *   Revision History
+ *    ----------------
+ *
+ */
+
+/*
+ * SD0001 PCI¥Ö¥ê¥Ã¥¸¡¡¥ì¥¸¥¹¥¿¡¢¥Ó¥Ã¥ÈÄêµÁ
+ */
+
+
+#ifndef __PCI_SD0001_H
+#define __PCI_SD0001_H
+
+#define SD0001_IO_BASE (P2SEGADDR(CONFIG_PCI_SD0001_BASE)+0x00800000)
+#define SD0001_MEM_BASE (P2SEGADDR(CONFIG_PCI_SD0001_BASE)+0x01000000)
+
+#define SD0001_REG(x) ((volatile u32 *)P2SEGADDR(CONFIG_PCI_SD0001_BASE + (x)))
+
+#define sd0001_writel(value, reg) do { *(SD0001_REG(SD0001_REG_##reg)) = value; } while(0)
+#define sd0001_readl(reg) (*(SD0001_REG(SD0001_REG_##reg)))
+
+#define SD0001_REG_REV			(0x00)	/* PCI Class & Revision Code */
+#define SD0001_REG_RESET		(0x08)	/* ¥ê¥»¥Ã¥È */
+#define SD0001_REG_SDRAM_CTL		(0x10)	/* SDRAM ¥â¡¼¥É/À©¸æ */
+#define SD0001_REG_INT_STS1		(0x20)	/* ³ä¤ê¹þÍ×°øÉ½¼¨ */
+#define SD0001_REG_INT_ENABLE		(0x24)	/* ³ä¤ê¹þ¤ß¥Þ¥¹¥¯ */
+#define SD0001_REG_INT_STS2		(0x28)	/* ³ä¹þ¤ß¥¹¥Æ¡¼¥¿¥¹ */
+#define SD0001_REG_DMA1_CTL_STS		(0x30)	/* DMA ¥³¥Þ¥ó¥É & ¥¹¥Æ¡¼¥¿¥¹ */
+#define SD0001_REG_DMA1_SADR		(0x34)	/* DMA ¥½¡¼¥¹¥¢¥É¥ì¥¹ */
+#define SD0001_REG_DMA1_DADR		(0x38)	/* DMA ¥Ç¥£¥¹¥Æ¥£¥Í¡¼¥·¥ç¥ó¥¢¥É¥ì¥¹ */
+#define SD0001_REG_DMA1_CNT		(0x3c)	/* DMA Å¾Á÷¥Ð¥¤¥È¿ô */
+#define SD0001_REG_DMA2_CTL_STS		(0x40)	/* DMA ¥³¥Þ¥ó¥É & ¥¹¥Æ¡¼¥¿¥¹ */
+#define SD0001_REG_DMA2_SADR		(0x44)	/* DMA ¥½¡¼¥¹¥¢¥É¥ì¥¹ */
+#define SD0001_REG_DMA2_DADR		(0x48)	/* DMA ¥Ç¥£¥¹¥Æ¥£¥Í¡¼¥·¥ç¥ó¥¢¥É¥ì¥¹ */
+#define SD0001_REG_DMA2_CNT		(0x4c)	/* DMA Å¾Á÷¥Ð¥¤¥È¿ô */
+#define SD0001_REG_PCI_CTL		(0x50)	/* PCI¥Ð¥¹Æ°ºî¥â¡¼¥É */
+#define SD0001_REG_PCI_IO_OFFSET	(0x58)	/* PCIÄ¾ÀÜI/O¥¢¥¯¥»¥¹¥ª¥Õ¥»¥Ã¥È */
+#define SD0001_REG_PCI_MEM_OFFSET	(0x5c)	/* PCIÄ¾ÀÜ¥á¥â¥ê¥¢¥¯¥»¥¹¥ª¥Õ¥»¥Ã¥È */
+#define SD0001_REG_INDIRECT_ADR		(0x60)	/* PCI Configuration¥ì¥¸¥¹¥¿¥¢¥É¥ì¥¹ */
+#define SD0001_REG_INDIRECT_DATA	(0x64)	/* PCI Configuration¥Ç¡¼¥¿¥ì¥¸¥¹¥¿ */
+#define SD0001_REG_INDIRECT_CTL		(0x68)	/* PCI¥Ð¥¹´ÖÀÜ¥¢¥¯¥»¥¹À©¸æ */
+#define SD0001_REG_INDIRECT_STS		(0x6c)	/* PCI¥Ð¥¹´ÖÀÜ¥¢¥¯¥»¥¹¥¹¥Æ¡¼¥¿¥¹ */
+#define SD0001_REG_AWAKE		(0x70)	/* AWAKE³ä¹þ¤ß */
+#define SD0001_REG_MAIL			(0x74)	/* MailÄÌ¿® */
+
+
+/*
+ * SD0001 ¥ì¥¸¥¹¥¿¤Î³Æ¥Ó¥Ã¥È¤Îµ¡Ç½¤ÎÄêµÁ
+ */
+/* MODE ¥ì¥¸¥¹¥¿ */
+
+/* RST ¥ì¥¸¥¹¥¿ */
+#define	 SD0001_RST_SWRST		0x80000000	/* SD0001¤Î¥ê¥»¥Ã¥È */
+#define	 SD0001_RST_BUSRST		0x40000000	/* PCI¥Ð¥¹¥½¥Õ¥È¥ê¥»¥Ã¥È */
+#define	 SD0001_RST_MASK		0xc0000000	/* RST¥ì¥¸¥¹¥¿ÀßÄê¥Þ¥¹¥¯ */
+
+
+/* SH3 SD0001  PCI Devices Space & Mamory Size */
+#define	 SD0001_PCI_IO_WINDOW		0x00800000	/* PCI I/O¶õ´Ö Window: 8MiB */
+#define	 SD0001_PCI_MEM_WINDOW		0x03000000	/* PCI MEM¶õ´Ö Window: 48MiB */
+#define  SD0001_PCI_WINDOW_SHIFT	22		
+#define	 SD0001_SDRAM_MAX		0x04000000	/* SDMAN¥µ¥¤¥º 64MiB */
+
+
+/* pci_ctl ¥ì¥¸¥¹¥¿ */
+#define  SD0001_CTL_MASTER_SWAP		0x80000000	/* PCI¥Ð¥¹¥Þ¥¹¥¿¡¼Å¾Á÷»þ¤Î
+							   Byte Swap ON */
+#define  SD0001_CTL_PCI_EDCONV		0x40000000	/* PCI¥Ç¥Ð¥¤¥¹¥¢¥¯¥»¥¹»þ¤Î
+							   EndianÊÑ´¹ ON */
+#define	 SD0001_CTL_RETRY_MASK		0x000000f0	/* PCI¥ê¥È¥é¥¤¥ª¡¼¥Ð¸¡½Ð¥«¥¦¥ó¥ÈÃÍ */
+#define  SD0001_CTL_NOGNT		0x00000002	/* PCI GNT¿®¹æ¤ÎÈ¯¹ÔÄä»ß */
+
+/* SD_MDCTL ¥ì¥¸¥¹¥¿ */
+#define	 SD0001_SDMD_KIND_MASK		0xc0000000	/* SDRAM ¼ïÊÌ ÀßÄê¥Þ¥¹¥¯*/
+#define	 SD0001_SDMD_KIND_16		0x00000000	/* SDRAM 16Mbits */
+#define	 SD0001_SDMD_KIND_64		0x40000000	/* SDRAM 64Mbits */
+#define	 SD0001_SDMD_KIND_128		0x80000000	/* SDRAM 128Mbits */
+#define	 SD0001_SDMD_KIND_256		0xc0000000	/* SDRAM 256Mbits */
+#define	 SD0001_SDMD_SIZE_MASK		0x30000000	/* SDRAM SIZE ÀßÄê¥Þ¥¹¥¯ */
+#define	 SD0001_SDMD_SIZE_4		0x00000000	/* ¥Ç¡¼¥¿¥Ð¥¹ 4bits */
+#define	 SD0001_SDMD_SIZE_8		0x10000000	/* ¥Ç¡¼¥¿¥Ð¥¹ 8bits */
+#define	 SD0001_SDMD_SIZE_16		0x20000000	/* ¥Ç¡¼¥¿¥Ð¥¹ 16bits */
+#define	 SD0001_SDMD_SIZE_32		0x30000000	/* ¥Ç¡¼¥¿¥Ð¥¹ 32bits */
+#define	 SD0001_SDMD_REF_MASK		0x0000f000	/* ¥ê¥Õ¥ì¥Ã¥·¥å¡¦¥µ¥¤¥¯¥ë ÀßÄê¥Þ¥¹¥¯ */
+#define	 SD0001_SDMD_REF_DEF		0x00000000	/* ¥ê¥Õ¥ì¥Ã¥·¥å¡¦¥µ¥¤¥¯¥ë ¥Ç¥Õ¥©¥ë¥È(128cycles) */
+#define	 SD0001_SDMD_REF_128		0x00001000	/* ¥ê¥Õ¥ì¥Ã¥·¥å¡¦¥µ¥¤¥¯¥ë 128cycles */
+#define	 SD0001_SDMD_REF_256		0x00002000	/* ¥ê¥Õ¥ì¥Ã¥·¥å¡¦¥µ¥¤¥¯¥ë 256cycles */
+#define	 SD0001_SDMD_REF_384		0x00003000	/* ¥ê¥Õ¥ì¥Ã¥·¥å¡¦¥µ¥¤¥¯¥ë 384cycles */
+#define	 SD0001_SDMD_REF_512		0x00004000	/* ¥ê¥Õ¥ì¥Ã¥·¥å¡¦¥µ¥¤¥¯¥ë 512cycles */
+#define	 SD0001_SDMD_REF_640		0x00005000	/* ¥ê¥Õ¥ì¥Ã¥·¥å¡¦¥µ¥¤¥¯¥ë 640cycles */
+#define	 SD0001_SDMD_REF_768		0x00006000	/* ¥ê¥Õ¥ì¥Ã¥·¥å¡¦¥µ¥¤¥¯¥ë 768cycles */
+#define	 SD0001_SDMD_REF_896		0x00007000	/* ¥ê¥Õ¥ì¥Ã¥·¥å¡¦¥µ¥¤¥¯¥ë 896cycles */
+#define	 SD0001_SDMD_REF_STOP		0x00008000	/* ¥ê¥Õ¥ì¥Ã¥·¥åÄä»ß */
+
+#define	 SD0001_SDMD_LMODE_MASK		0x00000070	/* CAS¥ì¥¤¥Æ¥ó¥· ÀßÄê¥Þ¥¹¥¯ */
+#define  SD0001_SDMD_LMODE_1		0x00000000	/* CAS¥ì¥¤¥Æ¥ó¥· 1 */
+#define  SD0001_SDMD_LMODE_2		0x00000010	/* CAS¥ì¥¤¥Æ¥ó¥· 2 */
+#define  SD0001_SDMD_LMODE_3		0x00000020	/* CAS¥ì¥¤¥Æ¥ó¥· 3 */
+#define  SD0001_SDMD_MASK		0xf000f070	/* SDMS ÀßÄê¥Þ¥¹¥¯ */
+
+
+/* ³ä¤ê¹þ¤ß ¥Þ¥¹¥¯ */
+#define	 SD0001_INT_INTEN		0x80000000	/* Á´³ä¤ê¹þ¤ß¥Þ¥¹¥¯ */
+#define	 SD0001_INT_RETRY		0x20000000	/* PCI¥Ð¥¹¥ê¥È¥é¥¤²ó¿ô¥ª¡¼¥Ð¡¼ */
+#define	 SD0001_INT_TO			0x10000000	/* PCI¥Ð¥¹¥¿¥¤¥à¥¢¥¦¥È */
+#define	 SD0001_INT_SSERR		0x08000000	/* SERR#¥¢¥µ¡¼¥È */
+#define	 SD0001_INT_RSERR		0x04000000	/* SERR#¸¡½Ð */
+#define	 SD0001_INT_RPERR		0x02000000	/* PERR#¸¡½Ð */
+#define	 SD0001_INT_SPERR		0x01000000	/* PERR#¥¢¥µ¡¼¥È */
+#define	 SD0001_INT_STABT		0x00800000	/* ¥¿¡¼¥²¥Ã¥È¥¢¥Ü¡¼¥ÈÈ¯¹Ô */
+#define	 SD0001_INT_RTABT		0x00400000	/* ¥¿¡¼¥²¥Ã¥È¥¢¥Ü¡¼¥È¸¡½Ð */
+#define	 SD0001_INT_LOCK		0x00200000	/* ¥Ç¥Ã¥É¥í¥Ã¥¯¸¡½Ð */
+#define	 SD0001_INT_RMABT		0x00100000	/* ¥Þ¥¹¥¿¡¼¥¢¥Ü¡¼¥È¸¡½Ð */
+#define	 SD0001_INT_BUSERR		0x3ff00000	/* PCI¥Ð¥¹¥¨¥é¡¼³ä¹þ¤ß */
+#define	 SD0001_INT_AWINT		0x00001000	/* AWAKE³ä¹þ¤ß */
+#define	 SD0001_INT_DMA1		0x00000020	/* DMA¥Á¥ã¥Í¥ë1´°Î» */
+#define	 SD0001_INT_DMA2		0x00000010	/* DMA¥Á¥ã¥Í¥ë2´°Î» */
+#define	 SD0001_INT_INTD		0x00000008	/* PCI¥Ð¥¹INTD# */
+#define	 SD0001_INT_INTC		0x00000004	/* PCI¥Ð¥¹INTC# */
+#define	 SD0001_INT_INTB		0x00000002	/* PCI¥Ð¥¹INTB# */
+#define	 SD0001_INT_INTA		0x00000001	/* PCI¥Ð¥¹INTA# */
+#define	 SD0001_INT_VAILD		0x3ff0103f	/* ³ä¤ê¹þ¤ßÍ­¸ú¥Ó¥Ã¥È */
+
+/* CONFIG_ADDRESS ¥ì¥¸¥¹¥¿ */
+#define	 SD0001_CONFIG_ADDR_EN		0x80000000	/* ¥³¥ó¥Õ¥£¥°¥ì¡¼¥·¥ç¥ó¥µ¥¤¥¯¥ë¥¤¥Í¡¼¥Ö¥ë */
+
+
+/* INDRCT_CMD ¥ì¥¸¥¹¥¿ */
+#define	 SD0001_INDRCTC_BE_MASK		0x000f0000	/* ¥Ð¥¤¥È¥¤¥Í¡¼¥Ö¥ë */
+#define	 SD0001_INDRCTC_BE_BYTE		0x00010000	/* ¥Ð¥¤¥È¥¢¥¯¥»¥¹³«»Ï°ÌÃÖ */
+#define	 SD0001_INDRCTC_BE_WORD		0x00030000	/* ¥ï¡¼¥É¥¢¥¯¥»¥¹³«»Ï°ÌÃÖ */
+#define	 SD0001_INDRCTC_BE_LONG		0x000f0000	/* ¥í¥ó¥°¥ï¡¼¥É¥¢¥¯¥»¥¹ */
+#define	 SD0001_INDRCTC_CMDEN		0x00008000	/* CMD Enable */
+#define	 SD0001_INDRCTC_CMD_IOR		0x00000200	/* I/O Read CMD */
+#define	 SD0001_INDRCTC_CMD_IOW		0x00000300	/* I/O Write CMD */
+#define	 SD0001_INDRCTC_CMD_MEMR	0x00000600	/* Memory Read CMD */
+#define	 SD0001_INDRCTC_CMD_MEMW	0x00000700	/* Memory Write CMD */
+#define	 SD0001_INDRCTC_CMD_INTA	0x00000000	/* Interrupt Ack CMD */
+#define	 SD0001_INDRCTC_CMD_MASK	0x00000f00	/* CMD ¥³¡¼¥É */
+#define	 SD0001_INDRCTC_FLGRESET	0x00000080	/* INDRCT_FLG¤Î¥¨¥é¡¼¥Õ¥é¥°¤Î¥ê¥»¥Ã¥È */
+#define	 SD0001_INDRCTC_IOWT		0x00000008	/* ´ÖÀÜI/O¥é¥¤¥È»Ø¼¨ */
+#define	 SD0001_INDRCTC_IORD		0x00000004	/* ´ÖÀÜI/O¥ê¡¼¥É»Ø¼¨ */
+#define	 SD0001_INDRCTC_COWT		0x00000002	/* ¥³¥ó¥Õ¥£¥°¥ì¡¼¥·¥ç¥ó¥é¥¤¥È»Ø¼¨ */
+#define	 SD0001_INDRCTC_CORD		0x00000001	/* ¥³¥ó¥Õ¥£¥°¥ì¡¼¥·¥ç¥ó¥ê¡¼¥É»Ø¼¨ */
+#define	 SD0001_INDRCTC_MASK		0x000f8f8f	/* INDRCT_CMD ÀßÄê»þ¥Þ¥¹¥¯ */
+
+/* INDRCT_FLG ¥ì¥¸¥¹¥¿ */
+#define	 SD0001_INDRCTF_MABTRCV		0x00080000	/* ¥Þ¥¹¥¿¡¼¥¢¥Ü¡¼¥ÈÈ¯À¸ */
+#define	 SD0001_INDRCTF_INDFLG		0x00000001	/* ´ÖÀÜ¥¢¥¯¥»¥¹¼Â¹ÔÃæ */
+
+
+/* Awake ¥ì¥¸¥¹¥¿ */
+#define	 SD0001_AWAKE_AWOK		0x80000000	/* AWAKE READÉ½¼¨ */
+#define	 SD0001_AWAKE_AWV		0x7fffffff	/* AWAKE READÉÕ¿ï¾ðÊó */
+
+/* Mail ¥ì¥¸¥¹¥¿ */
+#define	 SD0001_MAIL_FLAG		0x80000000	/* MAIL ³ä¹þ¤ßÈ¯À¸ */
+#define	 SD0001_MAIL_DATA		0x7fffffff	/* MAIL ³ä¹þ¤ßÉÕ¿ï¾ðÊó */
+
+
+/*
+ * SD0001 ÆâÂ¢ DMAC ¥ì¥¸¥¹¥¿µ¡Ç½ÄêµÁ
+ */
+
+/* DMATCR ¥ì¥¸¥¹¥¿ */
+#define	 SD0001_DMATCR_MASK		0x0fffffff	/* DMATCRÀßÄê¥Þ¥¹¥¯ */
+#define	 SD0001_DMATCR_MAX		0x04000000	/* ºÇÂçÅ¾Á÷¥Ð¥¤¥È¿ô */
+
+
+
+/* DMCMD ¥ì¥¸¥¹¥¿ */
+#define	 SD0001_DMCMD_EXEC		0x80000000	/* DMA³«»Ï»Ø¼¨ / ¼Â¹ÔÃæÉ½¼¨ */
+#define	 SD0001_DMCMD_NEND		0x40000000	/* DMAÀ®¸ù¤Ë¤è¤ë´°Î» */
+#define	 SD0001_DMCMD_AEND		0x20000000	/* DMA¼ºÇÔ¤Ë¤è¤ë´°Î» */
+#define	 SD0001_DMCMD_STATUS		0x60000000	/* DMA´°Î»¥¹¥Æ¡¼¥¿¥¹ */
+
+#define  SD0001_DMCMD_SWAP		0x00010000	/* Å¾Á÷¥Ç¡¼¥¿¤Î Byte Swap */
+#define	 SD0001_DMCMD_DSR_RAM_PCI	0x00000100	/* DMAÅ¾Á÷Êý¸þ¡§ SDRAM ¢ª PCI */
+#define	 SD0001_DMCMD_DSR_PCI_RAM	0x00000200	/* DMAÅ¾Á÷Êý¸þ¡§ PCI ¢ª SDRAM */
+#define	 SD0001_DMCMD_DSR_RAM_RAM	0x00000000	/* DMAÅ¾Á÷Êý¸þ¡§ SDRAM ¢ª SDRAM */
+#define	 SD0001_DMCMD_MASK		0xe0010f00	/* DMCMD¥ì¥¸¥¹¥¿ÀßÄê¥Þ¥¹¥¯ */
+
+
+/* INTM PCI ¥ì¥¸¥¹¥¿ */
+#define  SD0001_INTMPCI_PERR		0x80000000	/* Detected Perr ³ä¹þ¤ß¥Þ¥¹¥¯ */
+#define  SD0001_INTMPCI_SERR		0x40000000	/* Signalled SERR ³ä¹þ¤ß¥Þ¥¹¥¯ */
+#define  SD0001_INTMPCI_MBAT		0x20000000	/* Received Master Abort ³ä¹þ¤ß¥Þ¥¹¥¯ */
+#define  SD0001_INTMPCI_RTABT		0x10000000	/* Received Target Abort ³ä¹þ¤ß¥Þ¥¹¥¯ */
+#define  SD0001_INTMPCI_STABT		0x08000000	/* Signalled Target Abort ³ä¹þ¤ß¥Þ¥¹¥¯ */
+#define  SD0001_INTMPCI_DPERR		0x01000000	/* DPerr Detected ³ä¹þ¤ß¥Þ¥¹¥¯ */
+#define  SD0001_INTMPCI_MAIL		0x00800000	/* MAIL¥ì¥¸¥¹¥¿³ä¹þ¤ß */
+
+
+/* RESET PCI ¥ì¥¸¥¹¥¿*/
+#define  SD0001_RSTPCI_SWRST		0x80000000	/* ¥¿¡¼¥²¥Ã¥È¥Ç¥Ð¥¤¥¹ ¥ê¥»¥Ã¥È */
+#define  SD0001_RSTPCI_ALIVE		0x40000000	/* ¥¿¡¼¥²¥Ã¥È¥â¡¼¥É¤Î»þ¤ÎRESET¥ì¥¸¥¹¥¿¤Î */
+							/*    bit30(PCIRST)¤ÎÃÍ¡£ Read Only */
+
+
+extern int pci_setup_sd0001(void);
+
+void sd0001_outl(unsigned long, unsigned long); 
+unsigned long sd0001_inl(unsigned long);
+void sd0001_outw(unsigned short, unsigned long);
+unsigned short sd0001_inw(unsigned long);
+void sd0001_outb(unsigned char, unsigned long);
+unsigned char sd0001_inb(unsigned long);
+void sd0001_insb(unsigned long, void *, unsigned long);
+void sd0001_insw(unsigned long, void *, unsigned long);
+void sd0001_insl(unsigned long, void *, unsigned long);
+void sd0001_outsb(unsigned long, const void *, unsigned long);
+void sd0001_outsw(unsigned long, const void *, unsigned long);
+void sd0001_outsl(unsigned long, const void *, unsigned long);
+unsigned char sd0001_inb_p(unsigned long);
+void sd0001_outb_p(unsigned char, unsigned long);
+
+void *sd0001_ioremap(unsigned long, unsigned long);
+void sd0001_iounmap(void *);
+
+
+#endif /* __PCI_SD0001_H */
diff -urN linux-2.4.21-bk11/arch/sh/kernel/pci-sh7751.c linux-2.4.21-bk12/arch/sh/kernel/pci-sh7751.c
--- linux-2.4.21-bk11/arch/sh/kernel/pci-sh7751.c	2001-11-04 09:31:58.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/pci-sh7751.c	2003-07-17 02:52:28.000000000 -0700
@@ -38,8 +38,6 @@
  * Direct access to PCI hardware...
  */
 
-#ifdef CONFIG_PCI_DIRECT
-
 
 #define CONFIG_CMD(dev, where) (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3))
 
@@ -226,20 +224,6 @@
 	return NULL;
 }
 
-#endif
-
-/*
- * BIOS32 and PCI BIOS handling.
- * 
- * The BIOS version of the pci functions is not yet implemented but it is left
- * in for completeness.  Currently an error will be generated at compile time. 
- */
- 
-#ifdef CONFIG_PCI_BIOS
-
-#error PCI BIOS is not yet supported on SH7751
-
-#endif /* CONFIG_PCI_BIOS */
 
 /***************************************************************************************/
 
@@ -342,16 +326,9 @@
 	struct pci_ops *dir = NULL;
 
 	PCIDBG(1,"PCI: Starting intialization.\n");
-#ifdef CONFIG_PCI_BIOS
-	if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) {
-		pci_probe |= PCI_BIOS_SORT;
-		pci_bios_present = 1;
-	}
-#endif
-#ifdef CONFIG_PCI_DIRECT
+
 	if (pci_probe & PCI_PROBE_CONF1 )
 		dir = pci_check_direct();
-#endif
 	if (dir) {
 		pci_root_ops = dir;
 	    if(!pcibios_init_platform())
@@ -372,11 +349,6 @@
 	pci_fixup_irqs(pcibios_swizzle, pcibios_lookup_irq);
 	pcibios_fixup_peer_bridges();
 	pcibios_resource_survey();
-
-#ifdef CONFIG_PCI_BIOS
-	if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
-		pcibios_sort();
-#endif
 }
 
 char * __init pcibios_setup(char *str)
@@ -384,29 +356,10 @@
 	if (!strcmp(str, "off")) {
 		pci_probe = 0;
 		return NULL;
-	}
-#ifdef CONFIG_PCI_BIOS
-	else if (!strcmp(str, "bios")) {
-		pci_probe = PCI_PROBE_BIOS;
-		return NULL;
-	} else if (!strcmp(str, "nobios")) {
-		pci_probe &= ~PCI_PROBE_BIOS;
-		return NULL;
-	} else if (!strcmp(str, "nosort")) {
-		pci_probe |= PCI_NO_SORT;
-		return NULL;
-	} else if (!strcmp(str, "biosirq")) {
-		pci_probe |= PCI_BIOS_IRQ_SCAN;
-		return NULL;
-	}
-#endif
-#ifdef CONFIG_PCI_DIRECT
-	else if (!strcmp(str, "conf1")) {
+	} else if (!strcmp(str, "conf1")) {
 		pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS;
 		return NULL;
-	}
-#endif
-	else if (!strcmp(str, "rom")) {
+	} else if (!strcmp(str, "rom")) {
 		pci_probe |= PCI_ASSIGN_ROMS;
 		return NULL;
 	} else if (!strncmp(str, "lastbus=", 8)) {
diff -urN linux-2.4.21-bk11/arch/sh/kernel/pci-snapgear.c linux-2.4.21-bk12/arch/sh/kernel/pci-snapgear.c
--- linux-2.4.21-bk11/arch/sh/kernel/pci-snapgear.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/pci-snapgear.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,188 @@
+/*
+ * linux/arch/sh/kernel/pci-snapgear.c
+ *
+ * Author:  David McCullough <davidm@snapgear.com>
+ *
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * PCI initialization for the SnapGear boards
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/pci-sh7751.h>
+
+#define PCI_REG(reg)        (SH7751_PCIREG_BASE+reg)
+
+/* PCI: default LOCAL memory window sizes (seen from PCI bus) */
+#define SNAPGEAR_LSR0_SIZE    (64*(1<<20)) //64MB
+#define SNAPGEAR_LSR1_SIZE    (64*(1<<20)) //64MB
+
+/*
+ * Initialize the SnapGear PCI interface 
+ * Setup hardware to be Central Funtion
+ * Copy the BSR regs to the PCI interface
+ * Setup PCI windows into local RAM
+ */
+int __init pcibios_init_platform(void) {
+	u32 reg;
+	u32 word;
+	u32 id;
+
+	PCIDBG(1,"PCI: snapgear_pci_init called\n");
+	/* Set the BCR's to enable PCI access */
+	reg = inl(SH7751_BCR1);
+	reg |= 0x80000;
+	outl(reg, SH7751_BCR1);
+	
+	/* check for SH7751/SH7751R hardware */
+	id = inl(SH7751_PCIREG_BASE+SH7751_PCICONF0);
+	switch (id) {
+	case (SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID:
+		printk("PCI: SH7751 PCI host bridge found.\n");
+		break;
+	case (SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID:
+		printk("PCI: SH7751R PCI host bridge found.\n");
+		break;
+	default:
+		printk("PCI: Unknown PCI host bridge (id=0x%x).\n", id);
+		return(0);
+	}
+	
+	/* Turn the clocks back on (not done in reset)*/
+	outl(0, PCI_REG(SH7751_PCICLKR));
+	/* Clear Powerdown IRQ's (not done in reset) */
+	word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0;
+	outl(word, PCI_REG(SH7751_PCICLKR));
+
+#if 0
+/*
+ *	This code is removed as it is done in the bootloader and doing it
+ *	here means the MAC addresses loaded by the bootloader get lost
+ */
+	/* toggle PCI reset pin */
+	word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST;
+	outl(word,PCI_REG(SH7751_PCICR));    
+	/* Wait for a long time... not 1 sec. but long enough */
+	mdelay(100);
+	word = SH7751_PCICR_PREFIX;
+	outl(word,PCI_REG(SH7751_PCICR)); 
+#endif
+	
+    /* set the command/status bits to:
+     * Wait Cycle Control + Parity Enable + Bus Master +
+     * Mem space enable
+     */
+    word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER | 
+           SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
+	outl(word, PCI_REG(SH7751_PCICONF1));
+
+	/* define this host as the host bridge */
+	word = SH7751_PCI_HOST_BRIDGE << 24;
+	outl(word, PCI_REG(SH7751_PCICONF2));
+
+	/* Set IO and Mem windows to local address 
+	 * Make PCI and local address the same for easy 1 to 1 mapping 
+	 * Window0 = SNAPGEAR_LSR0_SIZE @ non-cached CS2 base = SDRAM
+	 * Window1 = SNAPGEAR_LSR1_SIZE @ cached CS2 base = SDRAM 
+	 */
+	word = SNAPGEAR_LSR0_SIZE - 1;
+	outl(word, PCI_REG(SH7751_PCILSR0));
+	word = SNAPGEAR_LSR1_SIZE - 1;
+	outl(word, PCI_REG(SH7751_PCILSR1));
+	/* Set the values on window 0 PCI config registers */
+	word = P2SEGADDR(SH7751_CS2_BASE_ADDR);
+	outl(word, PCI_REG(SH7751_PCILAR0));
+	outl(word, PCI_REG(SH7751_PCICONF5));
+	/* Set the values on window 1 PCI config registers */
+	word =  PHYSADDR(SH7751_CS2_BASE_ADDR);
+	outl(word, PCI_REG(SH7751_PCILAR1));
+	outl(word, PCI_REG(SH7751_PCICONF6));
+
+	/* Set the local 16MB PCI memory space window to 
+	 * the lowest PCI mapped address
+	 */
+	word = PCIBIOS_MIN_MEM & SH7751_PCIMBR_MASK;
+	PCIDBG(2,"PCI: Setting upper bits of Memory window to 0x%x\n", word);
+	outl(word , PCI_REG(SH7751_PCIMBR));
+
+	/* Map IO space into PCI IO window
+	 * The IO window is 64K-PCIBIOS_MIN_IO in size
+	 * IO addresses will be translated to the 
+	 * PCI IO window base address
+	 */
+	PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO,
+	    (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO);
+	    
+	/* Make sure the MSB's of IO window are set to access PCI space correctly */
+	word = PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK;
+	PCIDBG(2,"PCI: Setting upper bits of IO window to 0x%x\n", word);
+	outl(word, PCI_REG(SH7751_PCIIOBR));
+	
+	/* Set PCI WCRx, BCRx's, copy from BSC locations */
+	word = inl(SH7751_BCR1);
+	/* check BCR for SDRAM in area 3 */
+	if(((word >> 2) & 1) == 0) {
+		printk("PCI: Area 2 is not configured for SDRAM. BCR1=0x%x\n", word);
+		return 0;
+	}
+	outl(word, PCI_REG(SH7751_PCIBCR1));
+	word = (u16)inw(SH7751_BCR2);
+	/* check BCR2 for 32bit SDRAM interface*/
+	if(((word >> 4) & 0x3) != 0x3) {
+		printk("PCI: Area 2 is not 32 bit SDRAM. BCR2=0x%x\n", word);
+		return 0;
+	}
+	outl(word, PCI_REG(SH7751_PCIBCR2));
+	/* configure the wait control registers */
+	word = inl(SH7751_WCR1);
+	outl(word, PCI_REG(SH7751_PCIWCR1));
+	word = inl(SH7751_WCR2);
+	outl(word, PCI_REG(SH7751_PCIWCR2));
+	word = inl(SH7751_WCR3);
+	outl(word, PCI_REG(SH7751_PCIWCR3));
+	word = inl(SH7751_MCR);
+	outl(word, PCI_REG(SH7751_PCIMCR));
+
+	/* NOTE: I'm ignoring the PCI error IRQs for now..
+	 * TODO: add support for the internal error interrupts and
+	 * DMA interrupts...
+	 */
+	 
+	/* SH7751 init done, set central function init complete */
+	/* use round robin mode to stop a device starving/overruning */
+	word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN | SH7751_PCICR_ARBM;
+	outl(word,PCI_REG(SH7751_PCICR)); 
+	PCIDBG(2,"PCI: snapgear_pci_init finished\n");
+
+	return 1;
+}
+
+int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+{
+	int irq = -1;
+
+	switch (slot) {
+	case 8:  /* the PCI bridge */ break;
+	case 11: irq = 8;  break; /* USB    */
+	case 12: irq = 11; break; /* PCMCIA */
+	case 13: irq = 5;  break; /* eth0   */
+	case 14: irq = 8;  break; /* eth1   */
+	case 15: irq = 11; break; /* safenet (unused) */
+	}
+
+    printk("PCI: Mapping SnapGear IRQ for slot %d, pin %c to irq %d\n",
+			slot, pin - 1 + 'A', irq);
+
+    return irq;
+}
+
diff -urN linux-2.4.21-bk11/arch/sh/kernel/pci-v320usc.c linux-2.4.21-bk12/arch/sh/kernel/pci-v320usc.c
--- linux-2.4.21-bk11/arch/sh/kernel/pci-v320usc.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/pci-v320usc.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,518 @@
+/****************************************************************************/
+/*
+ * pci.c: V3 Hurricane specific PCI support.
+ *
+ * Copyright (C) 1999,2000 Dan Aizenstros (dan@vcubed.com)
+ * Copyright (C) 2001, Lineo Inc., <davidm@moreton.com.au>
+ *               SH3 port.
+ */
+/****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/autoconf.h>
+#include <asm/byteorder.h>
+#include <asm/pci.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+
+#include "pci-v320usc.h"
+
+/****************************************************************************/
+#ifdef CONFIG_PCI
+/****************************************************************************/
+
+#ifndef CONFIG_PCMCIA
+#define V320USC_MEM_SPACE	0xB8000000 /* V320 sees this as AC000000 ! */
+#define V320USC_IO_SPACE	0xB4000000
+#define V320USC_CONF_SPACE	0xB4000000
+#else
+#define V320USC_MEM_SPACE	0xab000000
+#define V320USC_IO_SPACE	0xaa000000
+#define V320USC_CONF_SPACE	0xaa000000
+#endif
+#define	V320USC_BASE		0xb1fd0000
+
+#ifdef __LITTLE_ENDIAN
+#define reg08(x)	(V320USC_BASE + (V320USC_##x))
+#define reg16(x)	(V320USC_BASE + (V320USC_##x))
+#else
+#define reg08(x)	(V320USC_BASE + ((V320USC_##x)^3))
+#define reg16(x)	(V320USC_BASE + ((V320USC_##x)^2))
+#endif
+
+#define reg32(x)	(V320USC_BASE + (V320USC_##x))
+
+#define v320usc_inb(addr)			readb(reg08(addr)
+#define v320usc_outb(value, addr)	writeb(value, reg08(addr))
+#define v320usc_inw(addr)			readw(reg16(addr))
+#define v320usc_outw(value, addr)	writew(value, reg16(addr))
+#define v320usc_inl(addr)			readl(reg32(addr))
+#define v320usc_outl(value, addr)	writel(value, reg32(addr))
+
+/****************************************************************************/
+
+/* Set the LB_PCI_BASE0 register to allow PCI Memory cycles to be used */
+
+static void set_io_cycles(void)
+{
+	u32 tempscratch;
+
+	v320usc_outl(
+		(v320usc_inl(LB_PCI_BASE0) &
+		~(LB_PCI_BASEX_PCI_CMD_MASK | LB_PCI_BASEX_ALOW_MASK))
+		| LB_PCI_BASEX_IO, LB_PCI_BASE0);
+
+	/* do a read of the register to flush the posting buffer */
+	tempscratch = v320usc_inl(LB_PCI_BASE0);
+}
+
+
+/* Set the LB_PCI_BASE0 register to allow PCI Config cycles to be used */
+static void set_config_cycles(int alow)
+{
+	u32 tempscratch;
+
+	tempscratch = v320usc_inl(LB_PCI_BASE0);
+
+	v320usc_outl((tempscratch & 
+		~(LB_PCI_BASEX_PCI_CMD_MASK | LB_PCI_BASEX_ALOW_MASK))
+		| LB_PCI_BASEX_CONFIG | alow, LB_PCI_BASE0);
+
+	/* do a read of the register to flush the posting buffer */
+	tempscratch = v320usc_inl(LB_PCI_BASE0);
+}
+
+
+static int mkaddr (unsigned char bus,
+		unsigned char devfn,
+		unsigned char where)
+{
+	int addr, alow;
+
+	if (bus) {
+		addr =  ((bus    & 0xff) << 0x10) | 
+			((devfn & 0xff) << 0x08) |
+			 (where  & 0xff);
+
+		/* set alow for type 1 configuration cycle */
+		alow = 1;
+	} else {
+		int device, function;
+
+		if (devfn >= PCI_DEVFN(12, 0))
+			return -1;
+
+		device = PCI_SLOT(devfn);
+		function = PCI_FUNC(devfn);
+
+		/* This next line assumes that the PCI backplane connects  */
+		/* the IDSEL line for each slot to a Address line with a   */
+		/* small value resistor.  Note: The PCI spec. suggests     */
+		/* several options here.  This code assumes the following  */
+		/* IDSEL to Address line mapping.                          */
+
+		/* Slot  Address Line */
+		/*  0  - AD11 */
+		/*  1  - AD12 */
+		/*  2  - AD13 */
+		/*  3  - AD14 */
+		/*  4  - AD15 */
+
+		/* 0x800 is AD11 set, shift left by the slot number (device) */
+		addr = (0x800 << device) | (function << 8) | where;
+		
+		/* set alow for type 0 configuration cycle */
+		alow = 0;
+	}
+
+	set_config_cycles(alow);
+
+	return addr;
+}
+
+
+static int v320usc_pcibios_read_config_byte (
+						struct pci_dev *dev,
+						int where,
+						u8 *val)
+{
+	int retVal = PCIBIOS_SUCCESSFUL;
+	unsigned long flags;
+	int addr;
+
+	save_and_cli(flags);
+
+	/* Clear status bits */
+	v320usc_outw(v320usc_inw(PCI_STAT_W), PCI_STAT_W);
+
+	if ((addr = mkaddr(dev->bus->number, dev->devfn, where)) == -1)
+		retVal = -1;
+	else {
+		// *val = readb(V320USC_CONF_SPACE + addr);
+		*val = * (unsigned char *) (V320USC_CONF_SPACE + addr);
+
+		/* Check for master abort */
+		if (v320usc_inw(PCI_STAT_W) & PCI_STAT_W_M_ABORT) {
+			v320usc_outw(0xffff, PCI_STAT_W);
+			// printk("Master abort byte\n");
+			*val = 0xff;
+		}
+	}
+
+	set_io_cycles();
+	restore_flags(flags);
+	return retVal;
+}
+
+
+static int v320usc_pcibios_read_config_word (
+						struct pci_dev *dev,
+						int where,
+						u16 *val)
+{
+	int retVal = PCIBIOS_SUCCESSFUL;
+	unsigned long flags;
+	int addr;
+
+	if (where & 1)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	save_and_cli(flags);
+
+	/* Clear status bits */
+	v320usc_outw(v320usc_inw(PCI_STAT_W), PCI_STAT_W);
+
+	if ((addr = mkaddr(dev->bus->number, dev->devfn, where)) == -1)
+		retVal = -1;
+	else {
+		*val = readw(V320USC_CONF_SPACE + addr);
+
+		/* Check for master abort */
+		if (v320usc_inw(PCI_STAT_W) & PCI_STAT_W_M_ABORT) {
+			v320usc_outw(0xffff, PCI_STAT_W);
+			// printk("Master abort word\n");
+			*val = 0xffff;
+		}
+	}
+
+	set_io_cycles();
+
+	restore_flags(flags);
+
+	return retVal;
+}
+
+
+static int v320usc_pcibios_read_config_dword (
+						struct pci_dev *dev,
+						int where,
+						u32 *val)
+{
+	int retVal = PCIBIOS_SUCCESSFUL;
+	unsigned long flags;
+	int addr;
+
+	if (where & 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	save_and_cli(flags);
+
+	/* Clear status bits */
+	v320usc_outw(v320usc_inw(PCI_STAT_W), PCI_STAT_W);
+
+	if ((addr = mkaddr(dev->bus->number, dev->devfn, where)) == -1)
+		retVal = -1;
+	else {
+		*val = readl(V320USC_CONF_SPACE + addr);
+
+		/* Check for master abort */
+		if (v320usc_inw(PCI_STAT_W) & PCI_STAT_W_M_ABORT) {
+			v320usc_outw(0xffff, PCI_STAT_W);
+			// printk("Master abort long\n");
+			*val = 0xffffffff;
+		}
+	}
+
+	set_io_cycles();
+
+	restore_flags(flags);
+
+	return retVal;
+}
+
+
+static int v320usc_pcibios_write_config_byte (
+						struct pci_dev *dev,
+						int where,
+						u8 val)
+{
+	int retVal = PCIBIOS_SUCCESSFUL;
+	unsigned long flags;
+	int addr;
+
+	save_and_cli(flags);
+
+	if ((addr = mkaddr(dev->bus->number, dev->devfn, where)) == -1)
+		retVal = -1;
+	else
+		writeb(val, V320USC_CONF_SPACE + addr);
+
+	/* wait for write FIFO to empty */
+	v320usc_inw(PCI_STAT_W);
+
+	set_io_cycles();
+
+	restore_flags(flags);
+
+	return retVal;
+}
+
+
+static int v320usc_pcibios_write_config_word (
+						struct pci_dev *dev,
+						int where,
+						u16 val)
+{
+	int retVal = PCIBIOS_SUCCESSFUL;
+	unsigned long flags;
+	int addr;
+
+	if (where & 1)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	save_and_cli(flags);
+
+	if ((addr = mkaddr(dev->bus->number, dev->devfn, where)) == -1)
+		retVal = -1;
+	else
+		writew(val, V320USC_CONF_SPACE + addr);
+
+	/* wait for write FIFO to empty */
+	v320usc_inw(PCI_STAT_W);
+
+	set_io_cycles();
+
+	restore_flags(flags);
+
+	return retVal;
+}
+
+
+static int v320usc_pcibios_write_config_dword (
+						struct pci_dev *dev,
+						int where,
+						u32 val)
+{
+	int retVal = PCIBIOS_SUCCESSFUL;
+	unsigned long flags;
+	int addr;
+
+	if (where & 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	save_and_cli(flags);
+
+	if ((addr = mkaddr(dev->bus->number, dev->devfn, where)) == -1)
+		retVal = -1;
+	else
+		writel(val, V320USC_CONF_SPACE + addr);
+
+	/* wait for write FIFO to empty */
+	v320usc_inw(PCI_STAT_W);
+
+	set_io_cycles();
+
+	restore_flags(flags);
+
+	return retVal;
+}
+
+
+struct pci_ops pci_config_ops = {
+	v320usc_pcibios_read_config_byte,
+	v320usc_pcibios_read_config_word,
+	v320usc_pcibios_read_config_dword,
+	v320usc_pcibios_write_config_byte,
+	v320usc_pcibios_write_config_word,
+	v320usc_pcibios_write_config_dword
+};
+
+/****************************************************************************/
+
+/* Everything hangs off this */
+static struct pci_bus *pci_root_bus;
+
+static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
+{
+	return PCI_SLOT(dev->devfn);
+}
+
+
+static int __init map_keywest_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (pin >= 1 && pin <= 4)
+		return(PINT_IRQ_BASE + 2 + pin - 1);
+	return(-1);
+}
+
+
+char *
+pcibios_setup(char *str)
+{
+	return(str);
+}
+
+
+void __init
+pcibios_fixup_pbus_ranges(struct pci_bus *bus,
+			  struct pbus_set_ranges_data *ranges)
+{
+	ranges->io_start -= bus->resource[0]->start;
+	ranges->io_end -= bus->resource[0]->start;
+	ranges->mem_start -= bus->resource[1]->start;
+	ranges->mem_end -= bus->resource[1]->start;
+}
+
+
+void __init pcibios_init(void)
+{
+	char *mode;
+
+	if (sh_mv.mv_init_pci != NULL)
+		sh_mv.mv_init_pci();
+
+	if (v320usc_inw(PCI_VENDOR) != V3USC_PCI_VENDOR) {
+		printk("V320USC: PCI bridge chip not found\n");
+		return;
+	}
+
+	switch (v320usc_inw(PCI_DEVICE)) {
+	case V3USC_PCI_DEVICE_MIPS_9: mode = "MIPS 9-bit"; break;
+	case V3USC_PCI_DEVICE_MIPS_5: mode = "MIPS 5-bit"; break;
+	case V3USC_PCI_DEVICE_SH3:    mode = "SH-3"; break;
+	case V3USC_PCI_DEVICE_SH4:    mode = "SH-4"; break;
+	default:                      mode = "unknown !"; break;
+	}
+	printk("V3 Semiconductor V320USC bridge in %s mode\n", mode);
+
+	/*
+	 * RST_OUT de asserted
+	 */
+	v320usc_outb(0x80, SYSTEM);
+
+	/*
+	 * 16x8 latency time, GRANT, Normal arbitration, RAM Disable,
+	 * CLK_OUT Disable, SYNC_RDY, BREQ_NEG
+	 */
+	v320usc_outl(0x10120001, LB_BUS_CFG);
+
+	/*
+	 * System error enable, PCI bus master, Memory & IO Access enable
+	 */
+	v320usc_outw(0x0047, PCI_CMD_W);
+	v320usc_outw(0xf100, PCI_STAT_W); /* clear any errors */
+
+	/*
+	 * 32x8 clocks as Latency Timer
+	 */
+	v320usc_outl(0x00008800, PCI_HDR_CFG);
+
+	v320usc_outl(0x00005761, DRAM_BLK0);
+	v320usc_outl(0x02005761, DRAM_BLK1);
+	v320usc_outl(0x00000000, DRAM_BLK2);
+	v320usc_outl(0x00000000, DRAM_BLK3);
+	v320usc_outl(0x00000942, DRAM_CFG);
+	v320usc_outl(0x80030066, PCI_BUS_CFG);
+
+	v320usc_outl(v320usc_inl(INT_STAT), INT_STAT); /* clear any ints */
+
+	v320usc_outl(0x00000000, INT_CFG0);
+	v320usc_outl(0x00000000, INT_CFG1);
+	v320usc_outl(0x00000000, INT_CFG2);
+	v320usc_outl(0x00000000, INT_CFG3);
+
+#if 0
+	v320usc_outl(0x0c000000, PCI_I2O_BASE);
+	v320usc_outl(0x0c010053, PCI_I2O_MAP);
+#endif
+	v320usc_outl(0x0c000001, PCI_MEM_BASE);
+	v320usc_outl(0x00010063, PCI_MEM_MAP);
+
+	v320usc_outl(0x00000000, LB_PCU_BASE); /* Disable PCU on SuperH */
+#if 0
+	v320usc_outl(0x00000081, PCI_PCU_BASE);
+#endif
+
+#ifndef CONFIG_PCMCIA
+	v320usc_outl(0xB4002030, LB_PCI_BASE0); /* 64Mb */
+	v320usc_outl(0xACB86030, LB_PCI_BASE1); /* 64Mb */
+#else
+	v320usc_outl(0x9e002010, LB_PCI_BASE0); /* 16Mb */
+	v320usc_outl(0x9fAb6010, LB_PCI_BASE1); /* 16Mb */
+#endif
+
+	/*
+	 * do the scan
+	 */
+	pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
+	pci_assign_unassigned_resources();
+	pci_fixup_irqs(no_swizzle, map_keywest_irq);
+
+#ifndef CONFIG_PCMCIA
+	v320usc_outl(0xB4002030, LB_PCI_BASE0); /* 64Mb */
+	v320usc_outl(0xACB86030, LB_PCI_BASE1); /* 64Mb */
+#else
+	v320usc_outl(0x9e002010, LB_PCI_BASE0); /* 16Mb */
+	v320usc_outl(0x9fAb6010, LB_PCI_BASE1); /* 16Mb */
+#endif
+
+	/*
+	 * Lock the system registers
+	 */
+	v320usc_outb(0x60, SYSTEM);
+
+	/*
+	 * Map all the PCI IO space
+	 */
+	mach_port_map(PCIBIOS_MIN_IO, (64*1024) - PCIBIOS_MIN_IO,
+			V320USC_IO_SPACE+PCIBIOS_MIN_IO, 0);
+}
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+	printk("%s,%d: %s()\n", __FILE__, __LINE__, __FUNCTION__);
+}
+
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+	int i;
+
+	/*
+	 * PCI IDE controllers use non-standard I/O port decoding, respect it.
+	 */
+	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+		return;
+	printk("PCI: IDE base address fixup for %s\n", d->slot_name);
+	for(i=0; i<4; i++) {
+		struct resource *r = &d->resource[i];
+		if ((r->start & ~0x80) == 0x374) {
+			r->start |= 2;
+			r->end = r->start;
+		}
+	}
+}
+
+/* Add future fixups here... */
+struct pci_fixup pcibios_fixups[] = {
+	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
+	{ 0 }
+};
+
+/****************************************************************************/
+#endif /* CONFIG_PCI */
diff -urN linux-2.4.21-bk11/arch/sh/kernel/pci-v320usc.h linux-2.4.21-bk12/arch/sh/kernel/pci-v320usc.h
--- linux-2.4.21-bk11/arch/sh/kernel/pci-v320usc.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/pci-v320usc.h	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,454 @@
+/*
+ * v320usc.h: Register defines for the V320USC family of devices.
+ *
+ * Copyright (C) 1999,2000 Dan Aizenstros (dan@vcubed.com)
+ *
+ * $Id: pci-v320usc.h,v 1.1 2003/02/20 04:26:36 gerg Exp $
+ */
+
+#ifndef _V320USC_H_
+#define _V320USC_H_
+
+#include <linux/pci.h>
+
+/*
+ * General parameters
+ */
+/* set debug level 4=verbose...1=terse */
+#define DEBUG_PCI 3
+// #undef DEBUG_PCI
+
+#ifdef DEBUG_PCI
+#define PCIDBG(n, x...) { if(DEBUG_PCI>=n) printk(x); }
+#else
+#define PCIDBG(n, x...)
+#endif
+
+#if 0
+/* startup values */
+#define PCI_PROBE_BIOS 1
+#define PCI_PROBE_CONF1 2
+#define PCI_PROBE_CONF2 4
+#define PCI_NO_SORT 0x100
+#define PCI_BIOS_SORT 0x200
+#define PCI_NO_CHECKS 0x400
+#define PCI_ASSIGN_ROMS 0x1000
+#define PCI_BIOS_IRQ_SCAN 0x2000
+#endif
+
+
+/*
+ *	platform specific parameters
+ */
+ 
+/*
+ * PCI Command Register
+ * - Offset 04h, Size 16 bits
+ */
+#define PCI_CMD_W_IO_EN			0x0001		/* I/O access */
+#define PCI_CMD_W_MEM_EN		0x0002		/* Memory access */
+#define PCI_CMD_W_MASTER_EN		0x0004		/* PCI Master */
+#define PCI_CMD_W_MWI_EN		0x0010		/* Memory Write and */
+							/* Invalidate enable            */
+#define PCI_CMD_W_PAR_EN		0x0040		/* Parity error */
+#define PCI_CMD_W_SERR_EN		0x0100		/* System error */
+							/* If PAR_EN is enabled then SERR is  */
+							/* driven in response to parity error */
+#define PCI_CMD_W_FBB_EN		0x0200		/* Fast back to back */
+							/* transfers when Bus Master     */
+
+/*
+ * PCI Status Register
+ * - Offset 06h, Size 16 bits
+ */
+#define PCI_STAT_W_NEW_CAP		0x0010		/* New Capabilites          */
+#define PCI_STAT_W_UDF			0x0040		/* User Defined Feature     */
+#define PCI_STAT_W_FAST_BACK		0x0008		/* Fast Back to Back Target */
+							/* - Used to indicate ability of this   */
+							/* device to other Bus Masters          */
+#define PCI_STAT_W_PAR_REP		0x0010		/* Data Parity Report when    */
+							/* USC is a Bus Master and PERR is driven */
+#define PCI_STAT_W_DEVSEL_MASK		0x0600		/* 10-9 Bits Device Select */
+							/* Timing                              */
+#define PCI_STAT_W_DEVSEL_SHIFT		9
+
+#define PCI_STAT_W_T_ABORT		0x1000		/* Target Abort - set in */
+							/* response to a target abort detected */
+							/* while USC was a Bus Master          */
+#define PCI_STAT_W_M_ABORT		0x2000		/* Master Abort - set in   */
+							/* response to a master abort detected */
+							/* while USC was a Bus Master          */
+#define PCI_STAT_W_SYS_ERR		0x4000		/* System Error - set in */
+							/* response to a system error on the */
+							/* SERR pin                          */
+#define PCI_STAT_W_PAR_ERR		0x8000		/* Parity Error - set in */
+							/* response to a parity error on the */
+							/* PCI bus                           */
+
+/*
+ * PCI Class and Revision Register
+ * - Offset 08h, Size 32 bits
+ */
+#define PCI_CC_REV_VREV_MASK		0x0000000f	/* 3-0 Bits Stepping ID  */
+							/* Rev A = 0,Rev B0 = 1, Rev B1 = 2, */
+							/* Rev B2 = 3 */
+#define PCI_CC_REV_VREV_SHIFT		0
+
+#define PCI_CC_REV_UREV_MASK		0x000000f0	/* 7-4 Bits User Revision ID */
+							/* user definable for system revisions   */
+#define PCI_CC_REV_UREV_SHIFT		4
+
+#define PCI_CC_REV_PROG_IF_MASK		0x0000ff00	/* 15-8 Bits PCI Programming */
+							/* Interface code                        */
+#define PCI_CC_REV_PROG_IF_SHIFT	8
+
+#define PCI_CC_REV_SUB_CLASS_MASK	0x00ff0000	/* 23-16 Bits PCI Sub Class */
+#define PCI_CC_REV_SUB_CLASS_SHIFT	16
+
+#define PCI_CC_REV_BASE_CLASS_MASK	0xff000000	/* 32-24 Bits PCI Base Class */
+#define PCI_CC_REV_BASE_CLASS_SHIFT 	24
+
+/*
+ * PCI Access to local memory map access
+ * - Offset 10h, Size 32 bits (I2O mode)
+ */
+#define PCI_I2O_BASE_IO			0x00000001	/* I/O 1 - I/O space */
+							/* 0 - Memory Space              */
+#define PCI_I2O_BASE_TYPE_MASK		0x00000006	/* 2-1 Bits Address range */
+							/* type                               */
+#define PCI_I2O_BASE_TYPE_SHIFT		1		/* 0 - device can be mapped */
+							/* any where in a 32 bit address space  */
+#define PCI_I2O_BASE_PREFETCH		0x00000008	/* Prefetchable - no effect */
+#define PCI_I2O_BASE_ADR_BASE_MASK	0xfff00000	/* 31-20 Bits Base address */
+							/* of ATU                              */
+#define PCI_I2O_BASE_ADR_BASE_SHIFT	20
+
+/*
+ * PCI Access to local memory map access
+ * - Offset 14h, Size 32 bits
+ */
+#define PCI_MEM_BASE_IO			0x00000001	/* I/O 1 - I/O space */
+							/* 0 - Memory Space              */
+#define PCI_MEM_BASE_TYPE_MASK		0x00000006	/* 2-1 Bits Address range */
+							/* type                               */
+#define PCI_MEM_BASE_TYPE_SHIFT		1		/* 0 - device can be mapped */
+							/* any where in a 32 bit address space  */
+#define PCI_MEM_BASE_PREFETCH		0x00000008	/* Prefetchable - no effect */
+#define PCI_MEM_BASE_ADR_BASE_MASK	0xfff00000	/* 31-20 Bits Base address */
+							/* of ATU                              */
+#define PCI_MEM_BASE_ADR_BASE_SHIFT	20
+
+/*
+ * PCI Bus Parameters Register
+ * - Offset 3ch, Size 32 bits
+ */
+#define PCI_BPARAM_INT_LINE_MASK	0x000000ff	/* 7-0 Bits Interrupt Line */
+#define PCI_BPARAM_INT_LINE_SHIFT	0
+#define PCI_BPARAM_INT_PIN_MASK		0x00000700	/* 10-8 Bits Interrupt Pin */
+							/* 0 - disable, 1 - INTA, 2 - INT B    */
+							/* 3 - INT C, 4 - INT C                */
+#define PCI_BPARAM_INT_PIN_SHIFT	8
+#define PCI_BPARAM_MIN_GRANT_MASK	0x00ff0000	/* 23-16 Bits Minimum Grant */
+#define PCI_BPARAM_MIN_GRANT_SHIFT	16
+#define PCI_BPARAM_MAX_LAT_MASK		0xff000000	/* 31-24 Bits Maximum Latency */
+#define PCI_BPARAM_MAX_LAT_SHIFT	24
+
+/*
+ * LB_PCI_BASEx Registers
+ * - Offset 60h, Size 32 bits
+ * - Offset 64h, Size 32 bits
+ */
+#define LB_PCI_BASEX_ALOW_MASK		0x00000003	/* select value AD1:0 */
+#define LB_PCI_BASEX_ALOW_SHIFT		0x00000000
+#define LB_PCI_BASEX_ERR_EN		0x00000004
+#define LB_PCI_BASEX_PREFETCH		0x00000008	/* prefetch */
+#define LB_PCI_BASEX_SIZE_DISABLE	0x00000000
+#define LB_PCI_BASEX_SIZE_16MB		0x00000010
+#define LB_PCI_BASEX_SIZE_32MB		0x00000020
+#define LB_PCI_BASEX_SIZE_64MB		0x00000030
+#define LB_PCI_BASEX_SIZE_128MB		0x00000040
+#define LB_PCI_BASEX_SIZE_256MB		0x00000050
+#define LB_PCI_BASEX_SIZE_512MB		0x00000060
+#define LB_PCI_BASEX_SIZE_1GB		0x00000070
+#define LB_PCI_BASEX_BYTE_SWAP_NO	0x00000000	/* No swap 32 bits */
+#define LB_PCI_BASEX_BYTE_SWAP_16	0x00000100	/* 16 bits */
+#define LB_PCI_BASEX_BYTE_SWAP_8	0x00000200	/* bits */
+#define LB_PCI_BASEX_BYTE_SWAP_AUTO	0x00000300	/* Auto swap use BE[3:0] */
+#define LB_PCI_BASEX_COMBINE		0x00000800	/* Burst Write Combine */
+
+#define LB_PCI_BASEX_PCI_CMD_MASK	0x0000e000
+#define LB_PCI_BASEX_PCI_CMD_SHIFT	13
+#define LB_PCI_BASEX_INT_ACK		0x00000000	/* Interrupt Ack */
+#define LB_PCI_BASEX_IO			0x00002000	/* I/O Read/Write */
+#define LB_PCI_BASEX_MEMORY		0x00006000	/* Memory Read/Write */
+#define LB_PCI_BASEX_CONFIG		0x0000a000	/* Configuration Read/Write */
+#define LB_PCI_BASEX_MULTI_MEMORY	0x0000c000	/* Multiple Memory Read/Write */
+#define LB_PCI_BASEX_MEMORY_INVALIDATE	0x0000e000	/* Multiple Memory Read/e */
+							/* Write Invalidate       */
+#define LB_PCI_BASEX_MAP_ADR_MASK	0x00ff0000	/* PCI Address map */
+#define LB_PCI_BASEX_MAP_ADR_SHIFT	16
+#define LB_PCI_BASEX_BASE		0xff000000	/* Local Address base */
+#define LB_PCI_BASEX_BASE_ADR_SHIFT	24
+
+
+/*
+ * SDRAM Local Base Address Register 
+ * - Offset 78h, Size 32 bits
+ */
+#define LB_SDRAM_BASE_ENABLE		0x01		/* must be enabled to access */
+#define LB_SDRAM_BASE_SIZE_64M		0x00
+#define LB_SDRAM_BASE_SIZE_128M		0x10
+#define LB_SDRAM_BASE_SIZE_256M		0x20
+#define LB_SDRAM_BASE_SIZE_512M		0x30
+#define LB_SDRAM_BASE_SIZE_1G		0x40
+
+#define LB_SDRAM_BASE_MASK		0xfc000000
+#define LB_SDRAM_BASE_SHIFT		26
+
+
+/*
+ * Interrupt Configuration Register
+ * - Offset e0h, Size 32 bits
+ * - Offset e4h, Size 32 bits
+ * - Offset e8h, Size 32 bits
+ * - Offset 158h, Size 32 bits
+ */
+#define INT_CFGX_LB_MBI			0x00000001
+#define INT_CFGX_PCI_MBI		0x00000002
+#define INT_CFGX_I2O_OP_NE		0x00000008
+#define INT_CFGX_I2O_IF_NF		0x00000010
+#define INT_CFGX_I2O_IP_NE		0x00000020
+#define INT_CFGX_I2O_OP_NF		0x00000040
+#define INT_CFGX_I2O_OF_NE		0x00000080
+#define INT_CFGX_INT0			0x00000100
+#define INT_CFGX_INT1			0x00000200
+#define INT_CFGX_INT2			0x00000400
+#define INT_CFGX_INT3			0x00000800
+#define INT_CFGX_TIMER0			0x00001000
+#define INT_CFGX_TIMER1			0x00002000
+#define INT_CFGX_ENUM			0x00004000
+#define INT_CFGX_DMA0			0x00010000
+#define INT_CFGX_DMA1			0x00020000
+#define INT_CFGX_PWR_STATE		0x00100000
+#define INT_CFGX_HBI			0x00200000
+#define INT_CFGX_WDI			0x00400000
+#define INT_CFGX_BWI			0x00800000
+#define INT_CFGX_PSLAVE_PI		0x01000000
+#define INT_CFGX_PMASTER_PI		0x02000000
+#define INT_CFGX_PCI_T_ABORT		0x04000000
+#define INT_CFGX_PCI_M_ABORT		0x08000000
+#define INT_CFGX_DRA_PI			0x10000000
+#define INT_CFGX_MODE			0x20000000
+#define INT_CFGX_DI0			0x40000000
+#define INT_CFGX_DI1			0x80000000
+
+
+/*
+ * Interrupt Status Register
+ * - Offset ECh, Size 32 bits
+ */
+#define INT_STAT_BWI			0x00800000
+#define INT_STAT_WDI			0x00400000
+#define INT_STAT_HBI			0x00200000
+#define INT_STAT_DMA1			0x00020000
+#define INT_STAT_DMA0			0x00010000
+#define INT_STAT_TIMER1			0x00002000
+#define INT_STAT_TIMER0			0x00001000
+#define INT_STAT_INT3			0x00000800
+#define INT_STAT_INT2			0x00000400
+#define INT_STAT_INT1			0x00000200
+#define INT_STAT_INT0			0x00000100
+
+
+/*
+ * General Purpose Timer Control Register
+ * - Offset 150h, Size 16 bits
+ * - Offset 152h, Size 16 bits
+ */
+#define TIMER_CTLX_W_TI_MODE_0		0x0000		/* Timer input event */
+#define TIMER_CTLX_W_TI_MODE_1		0x0001
+#define TIMER_CTLX_W_TI_MODE_2		0x0002
+#define TIMER_CTLX_W_TI_MODE_3		0x0003
+
+#define TIMER_CTLX_W_CNT_EN_0		0x0000		/* Count enable */
+#define TIMER_CTLX_W_CNT_EN_1		0x0004
+#define TIMER_CTLX_W_CNT_EN_2		0x0008
+#define TIMER_CTLX_W_CNT_EN_3		0x000C
+
+#define TIMER_CTLX_W_TRG_MODE_0		0x0000		/* Trigger mode */
+#define TIMER_CTLX_W_TRG_MODE_1		0x0010
+#define TIMER_CTLX_W_TRG_MODE_2		0x0020
+#define TIMER_CTLX_W_TRG_MODE_3		0x0030
+
+#define TIMER_CTLX_W_TO_MODE_0		0x0000		/* Timer output mode */
+#define TIMER_CTLX_W_TO_MODE_1		0x0100
+#define TIMER_CTLX_W_TO_MODE_2		0x0200
+#define TIMER_CTLX_W_TO_MODE_3		0x0300
+#define TIMER_CTLX_W_TO_MODE_4		0x0400
+#define TIMER_CTLX_W_TO_MODE_5		0x0500
+
+#define TIMER_CTLX_W_DLTCH_0		0x0000		/* Data latch mode */
+#define TIMER_CTLX_W_DLTCH_1		0x0800
+#define TIMER_CTLX_W_DLTCH_2		0x1000
+
+#define TIMER_CTLX_W_ENABLE		0x8000		/* Timer enable */
+
+
+/*
+ * DMA Delay Register
+ * - Offset 16Ch, Size 8 bits
+ */
+#define DMA_DELAY_MASK			0x000000ff
+#define DMA_DELAY_SHIFT			0
+
+/*
+ * DMA Command / Status Register
+ * - Offset 170h, Size 32 bits
+ * - Offset 174h, Size 32 bits
+ */
+#define DMA_CSR_IPR			0x00000001	/* initiate DMA transfer */
+#define DMA_CSR_HALT			0x00000002	/* pause DMA transfer */
+#define DMA_CSR_DONE			0x00000004	/* DMA transfer complete */
+#define DMA_CSR_DCI			0x00000008	/* DMA control interrupt status	*/
+#define DMA_CSR_DPE			0x00000010	/* DMA PCI BUS error status */
+#define DMA_CSR_DONE_EN			0x00000400	/* DONE interrupt enable */
+#define DMA_CSR_DCI_EN			0x00000800	/* DCI interrupt enable */
+#define DMA_CSR_DPE_EN			0x00001000	/* DPE interrupt enable */
+#define DMA_CSR_PRIORITY		0x00008000	/* DMA channel priority */
+#define DMA_CSR_PCI_CMD0_MASK		0x000E0000	/* PCI Command Type 0 */
+#define DMA_CSR_PCI_CMD0_SHIFT		17
+#define DMA_CSR_PCI_CMD1_MASK		0x00E00000	/* PCI Command Type 1 */
+#define DMA_CSR_PCI_CMD1_SHIFT		21
+ 
+/*
+ * DMA Transfer Control Register
+ * - Offset 180h, Size 32 bits
+ * - Offset 190h, Size 32 bits
+ */
+#define DMA_XFER_DMA_CNT_MASK		0x000FFFFF	/* DMA transfer count */
+#define DMA_XFER_DMA_CNT_SHIFT		0
+#define DMA_XFER_DTERM_EN		0x00400000	/* External terminate count enable */
+#define DMA_XFER_BLOCK_FILL		0x00800000	/* Block fill feature enable */
+#define DMA_XFER_DST_BUS		0x01000000	/* DMA destination BUS */
+#define DMA_XFER_SRC_BUS		0x02000000	/* DMA source BUS */
+#define DMA_XFER_PDST_TYPE		0x04000000	/* PCI destination command type */
+#define DMA_XFER_PSRC_TYPE		0x08000000	/* PCI source command type */
+#define DMA_XFER_SWAP_MASK		0x30000000	/* Byte swap control */
+#define DMA_XFER_SWAP_SHIFT		28
+#define DMA_XFER_UPDT_CNT		0x40000000	/* Update count */
+#define DMA_XFER_DREQ_EN		0x80000000	/* External DRQ enable */
+
+
+/*
+ * DMA Control Block Register
+ * - Offset 180h, Size 32 bits
+ * - Offset 190h, Size 32 bits
+ */
+#define DMA_CTLB_BUS			0x00000001	/* DMA Control block address space */
+#define DMA_CTLB_SA_INC_DIS		0x00000004	/* Source address increment disable */
+#define DMA_CTLB_DA_INC_DIS		0x00000008	/* Dest address increment disable */
+#define DMA_CTLB_ADDR_MASK		0xFFFFFFF0	/* DMA Control block address mask */
+#define DMA_CTLB_ADDR_SHIFT		4
+
+
+/*
+ * V320USC registers offsets
+ */
+#define	V320USC_PCI_VENDOR		0x00
+#define	V320USC_PCI_DEVICE		0x02
+#define	V320USC_PCI_CMD_W		0x04
+#define	V320USC_PCI_STAT_W		0x06
+#define	V320USC_PCI_CC_REV		0x08
+#define	V320USC_PCI_HDR_CFG		0x0c
+#define	V320USC_PCI_I2O_BASE	0x10
+#define	V320USC_PCI_MEM_BASE	0x14
+#define	V320USC_PCI_REG_BASE	0x18
+#define	V320USC_PCI_PCU_BASE	0x1c
+#define	V320USC_PCI_BPARM		0x3c
+#define	V320USC_PCI_I2O_MAP		0x50
+#define	V320USC_PCI_MEM_MAP		0x54
+#define	V320USC_PCI_BUS_CFG		0x5c
+#define	V320USC_LB_PCI_BASE0	0x60
+#define	V320USC_LB_PCI_BASE1	0x64
+#define	V320USC_LB_PCU_BASE		0x6c
+#define	V320USC_SYSTEM			0x73
+#define	V320USC_LB_SDRAM_BASE	0x78
+#define	V320USC_LB_BUS_CFG		0x7c
+#define	V320USC_LB_PCI_CTL_W	0x84
+#define	V320USC_DRAM_CFG	0x8C
+#define	V320USC_DRAM_BLK0	0x90
+#define	V320USC_DRAM_BLK1	0x94
+#define	V320USC_DRAM_BLK2	0x98
+#define	V320USC_DRAM_BLK3	0x9c
+#define	V320USC_INT_CFG0		0xe0
+#define	V320USC_INT_CFG1		0xe4
+#define	V320USC_INT_CFG2		0xe8
+#define	V320USC_INT_STAT		0xec
+#define	V320USC_WD_HBI_W		0xf4
+#define	V320USC_TIMER_DATA0		0x140
+#define	V320USC_TIMER_DATA1		0x144
+#define	V320USC_TIMER_CTL0_W		0x150
+#define	V320USC_TIMER_CTL1_W		0x152
+#define	V320USC_INT_CFG3		0x158
+#define	V320USC_DMA_DELAY		0x16C
+#define	V320USC_DMA_CSR0		0x170
+#define	V320USC_DMA_CSR1		0x174
+#define	V320USC_DMA_XFER_CTL0		0x180
+#define	V320USC_DMA_SRC_ADR0		0x184
+#define	V320USC_DMA_DST_ADR0		0x188
+#define	V320USC_DMA_CTLB_ADR0		0x18C
+#define	V320USC_DMA_XFER_CTL1		0x190
+#define	V320USC_DMA_SRC_ADR1		0x194
+#define	V320USC_DMA_DST_ADR1		0x198
+#define	V320USC_DMA_CTLB_ADR1		0x19C
+
+/*
+ * Vendor/Device ID settings
+ */
+
+#define	V3USC_PCI_VENDOR		0x11b0
+#define	V3USC_PCI_DEVICE_MIPS_9 0x0100
+#define	V3USC_PCI_DEVICE_MIPS_5 0x0101
+#define	V3USC_PCI_DEVICE_SH3	0x0102
+#define	V3USC_PCI_DEVICE_SH4	0x0103
+
+/*
+ * Stepping of V3USC320 as read back from V3USC_PCI_CC_REV register
+ */
+#define V3USC_REV_A0 0
+#define V3USC_REV_B0 1
+#define V3USC_REV_B1 2
+
+/*
+ * PCI Bus Parameters Register
+ * - Offset 3ch, Size 32 bits
+ */
+#define INTERRUPT_PIN_DISABLE		0x0		/* Disabled */
+#define INTERRUPT_PIN_INTA		0x1		/* Use INTA */
+#define INTERRUPT_PIN_INTB		0x2		/* Use INTB */
+#define INTERRUPT_PIN_INTC		0x3		/* Use INTC */
+#define INTERRUPT_PIN_INTD		0x4		/* Use INTD */
+
+/*
+ * PCI Base Address for Peripheral Access 
+ * - Offset 1ch, Size 32 bits
+ * PCI Intelligent I/O Address Translation Unit Local Bus Address Map Register
+ * - Offset ??h, Size 32 bits
+ */
+#define BYTE_SWAP_NO			0x0		/* No swap 32 bits */
+#define BYTE_SWAP_16			0x1		/* 16 bits */
+#define BYTE_SWAP_8			0x2		/* 8 bits */
+#define BYTE_SWAP_AUTO			0x3		/* Auto swap use BE[3:0]   */
+#define APERTURE_SIZE_1M		0x0		/* Aperture size of 1 MB   */
+#define APERTURE_SIZE_2M		0x1		/* Aperture size of 2 MB   */
+#define APERTURE_SIZE_4M		0x2		/* Aperture size of 4 MB   */
+#define APERTURE_SIZE_8M		0x3		/* Aperture size of 8 MB   */
+#define APERTURE_SIZE_16M		0x4		/* Aperture size of 16 MB  */
+#define APERTURE_SIZE_32M		0x5		/* Aperture size of 32 MB  */
+#define APERTURE_SIZE_64M		0x6		/* Aperture size of 64 MB  */
+#define APERTURE_SIZE_128M		0x7		/* Aperture size of 128 MB */
+#define APERTURE_SIZE_256M		0x8		/* Aperture size of 256 MB */
+#define APERTURE_SIZE_512M		0x9		/* Aperture size of 512 MB */
+#define APERTURE_SIZE_1G		0xa		/* Aperture size of 1 GB   */
+
+#endif /* _V320USC_H_ */
diff -urN linux-2.4.21-bk11/arch/sh/kernel/pci_st40.c linux-2.4.21-bk12/arch/sh/kernel/pci_st40.c
--- linux-2.4.21-bk11/arch/sh/kernel/pci_st40.c	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/pci_st40.c	2003-07-17 02:52:28.000000000 -0700
@@ -21,6 +21,8 @@
 
 #include "pci_st40.h"
 
+static struct resource pci_io_space, pci_mem_space;
+
 /* This is in P2 of course */
 #define ST40PCI_BASE_ADDRESS     (0xb0000000)
 #define ST40PCI_MEM_ADDRESS      (ST40PCI_BASE_ADDRESS+0x0)
@@ -28,97 +30,183 @@
 #define ST40PCI_REG_ADDRESS      (ST40PCI_BASE_ADDRESS+0x07000000)
 
 #define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x))
-
-#define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg))
-#define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg))
-#define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg))
+#define ST40PCI_REG_INDEXED(reg, index) 				\
+	(ST40PCI_REG(reg##0) +					\
+	  ((ST40PCI_REG(reg##1) - ST40PCI_REG(reg##0))*index))
+
+#define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg));udelay(2);
+#define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg));udelay(2);
+#define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg));udelay(2);
+#define ST40PCI_WRITE_INDEXED(reg, index, val)				\
+	 writel((val), ST40PCI_REG_INDEXED(reg, index)); udelay(2);
 
 #define ST40PCI_READ(reg) readl(ST40PCI_REG(reg))
 #define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg))
 #define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg))
+#define ST40PCI_READ_INDEXED(reg, index) readl(ST40PCI_REG_INDEXED(reg, index))
 
 #define ST40PCI_SERR_IRQ        64
-#define ST40PCI_SERR_INT_GROUP  0
-#define ST40PCI_SERR_INT_POS    0
-#define ST40PCI_SERR_INT_PRI    15
-
 #define ST40PCI_ERR_IRQ        65
-#define ST40PCI_ERR_INT_GROUP   1
-#define ST40PCI_ERR_INT_POS     1
-#define ST40PCI_ERR_INT_PRI     14
+#define ST40PCI_AD_INT			66
+#define ST40PCI_PWR_DWN_INT		67
 
+#define PLLPCICR (0xbb040000+0x10)	// CLKGENA.PLL2CR
 
+/* From ST's include/asm-sh/st40_clock.h */
 /* Macros to extract PLL params */
 #define PLL_MDIV(reg)  ( ((unsigned)reg) & 0xff )
 #define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff )
-#define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x3 )
+#define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x7 )
 #define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff )
 
-/* Build up the appropriate settings */
-#define PLL_SET(mdiv,ndiv,pdiv,setup) \
-( ((mdiv)&0xff) | (((ndiv)&0xff)<<8) | (((pdiv)&3)<<16)| (((setup)&0x1ff)<<19))
+/*
+ * The pcibios_map_platform_irq function is defined in the appropraite
+ * board specific code and referenced here
+ */
+extern int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
+
+static void __init pcibios_assign_resources(void);
+
+static __init void SetPCIPLL(void)
+{
+	{
+		/* Lets play with the PLL values */
+		unsigned long pll1cr1;
+		unsigned long mdiv, ndiv, pdiv;
+		unsigned long muxcr;
+		unsigned int muxcr_ratios[4] = { 8, 16, 21, 1 };
+		unsigned int freq;
+
+#define CLKGENA            0xbb040000
+#define CLKGENA_PLL2_MUXCR CLKGENA + 0x48
+		pll1cr1 = ctrl_inl(PLLPCICR);
+		printk("PLL1CR1 %08x\n", pll1cr1);
+		mdiv = PLL_MDIV(pll1cr1);
+		ndiv = PLL_NDIV(pll1cr1);
+		pdiv = PLL_PDIV(pll1cr1);
+		printk("mdiv %02x ndiv %02x pdiv %02x\n", mdiv, ndiv, pdiv);
+		freq = ((2*27*ndiv)/mdiv) / (1 << pdiv);
+		printk("PLL freq %dMHz\n", freq);
+		muxcr = ctrl_inl(CLKGENA_PLL2_MUXCR);
+		printk("PCI freq %dMhz\n", freq / muxcr_ratios[muxcr & 3]);
+	}
+}
+
+
+struct pci_err {
+  unsigned mask;
+  const char *error_string;
+};
 
-#define PLLPCICR (0xbb040000+0x10)
 
-#define PLLPCICR_POWERON (1<<28)
-#define PLLPCICR_OUT_EN (1<<29)
-#define PLLPCICR_LOCKSELECT (1<<30)
-#define PLLPCICR_LOCK (1<<31)
+static struct pci_err int_error[]={
+  { INT_MNLTDIM,"MNLTDIM: Master non-lock transfer"},
+  { INT_TTADI,  "TTADI: Illegal byte enable in I/O transfer"},  
+  { INT_TMTO,   "TMTO: Target memory read/write timeout"},  
+  { INT_MDEI,   "MDEI: Master function disable error"},
+  { INT_APEDI,  "APEDI: Address parity error"},
+  { INT_SDI,    "SDI: SERR detected"},
+  { INT_DPEITW, "DPEITW: Data parity error target write"},  
+  { INT_PEDITR, "PEDITR: PERR detected"},
+  { INT_TADIM,  "TADIM: Target abort detected"},
+  { INT_MADIM,  "MADIM: Master abort detected"},
+  { INT_MWPDI,  "MWPDI: PERR from target at data write"},
+  { INT_MRDPEI, "MRDPEI: Master read data parity error"}
+};
+#define NUM_PCI_INT_ERRS (sizeof(int_error)/sizeof(struct pci_err))
 
+static struct pci_err aint_error[]={
+  { AINT_MBI,   "MBI: Master broken"},
+  { AINT_TBTOI, "TBTOI: Target bus timeout"},
+  { AINT_MBTOI, "MBTOI: Master bus timeout"},
+  { AINT_TAI,   "TAI: Target abort"},
+  { AINT_MAI,   "MAI: Master abort"},
+  { AINT_RDPEI, "RDPEI: Read data parity"},
+  { AINT_WDPE,  "WDPE: Write data parity"}
+};
 
-#define PLL_25MHZ 0x793c8512
-#define PLL_33MHZ PLL_SET(18,88,3,295)
 
+#define NUM_PCI_AINT_ERRS (sizeof(aint_error)/sizeof(struct pci_err))
 
-static __init void SetPCIPLL(void)
+static void print_pci_errors(unsigned reg,struct pci_err *error,int num_errors)
 {
-	/* Stop the PLL */
-	writel(0, PLLPCICR);
+  int i;
 
-	/* Always run at 33Mhz. The PCI clock is totally async 
-	 * to the rest of the system
-	 */
-	writel(PLL_33MHZ | PLLPCICR_POWERON, PLLPCICR);
+  for(i=0;i<num_errors;i++) {
+    if(reg & error[i].mask) {
+      printk("%s\n",error[i].error_string);
+    }
+  }
 
-	printk("ST40PCI: Waiting for PCI PLL to lock\n");
-	while ((readl(PLLPCICR) & PLLPCICR_LOCK) == 0);
-	writel(readl(PLLPCICR) | PLLPCICR_OUT_EN, PLLPCICR);
 }
 
 
+static char * pci_commands[16]={
+	"Int Ack",
+	"Special Cycle",
+	"I/O Read",
+	"I/O Write",
+	"Reserved",
+	"Reserved",
+	"Memory Read",
+	"Memory Write",
+	"Reserved",
+	"Reserved",
+	"Configuration Read",
+	"Configuration Write",
+	"Memory Read Multiple",
+	"Dual Address Cycle",
+	"Memory Read Line",
+	"Memory Write-and-Invalidate"
+};
+
+
 static void st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs)
 {
 
 	unsigned pci_int, pci_air, pci_cir, pci_aint;
+	static int count=0;
+
+
+	pci_int = ST40PCI_READ(INT);pci_aint = ST40PCI_READ(AINT);
+	pci_cir = ST40PCI_READ(CIR);pci_air = ST40PCI_READ(AIR);
+
+	/* Reset state to stop multiple interrupts */
+        ST40PCI_WRITE(INT, ~0); ST40PCI_WRITE(AINT, ~0); 
+
 
-	pci_int = ST40PCI_READ(INT);
-	pci_cir = ST40PCI_READ(CIR);
-	pci_air = ST40PCI_READ(AIR);
-
-	if (pci_int) {
-		printk("PCI INTERRUPT!\n");
-		printk("PCI INT -> 0x%x\n", pci_int & 0xffff);
-		printk("PCI AIR -> 0x%x\n", pci_air);
-		printk("PCI CIR -> 0x%x\n", pci_cir);
-		ST40PCI_WRITE(INT, ~0);
-	}
-
-	pci_aint = ST40PCI_READ(AINT);
-	if (pci_aint) {
-		printk("PCI ARB INTERRUPT!\n");
-		printk("PCI AINT -> 0x%x\n", pci_aint);
-		printk("PCI AIR -> 0x%x\n", pci_air);
-		printk("PCI CIR -> 0x%x\n", pci_cir);
-		ST40PCI_WRITE(AINT, ~0);
+	if(++count>1) return;
+
+	printk("** PCI ERROR **\n");
+
+        if(pci_int) {
+		printk("** INT register status\n");
+		print_pci_errors(pci_int,int_error,NUM_PCI_INT_ERRS);
 	}
 
+        if(pci_aint) {
+		printk("** AINT register status\n");
+		print_pci_errors(pci_aint,aint_error,NUM_PCI_AINT_ERRS);
+	}   
+	
+	printk("** Address and command info\n");
+
+	printk("** Command  %s : Address 0x%x\n",
+	       pci_commands[pci_cir&0xf],pci_air);
+
+	if(pci_cir&CIR_PIOTEM) {
+		printk("CIR_PIOTEM:PIO transfer error for master\n");
+	}
+        if(pci_cir&CIR_RWTET) {
+		printk("CIR_RWTET:Read/Write transfer error for target\n");
+	}
 }
 
 
 /* Rounds a number UP to the nearest power of two. Used for
  * sizing the PCI window.
  */
-static u32 __init r2p2(u32 num)
+static u32 r2p2(u32 num)
 {
 	int i = 31;
 	u32 tmp = num;
@@ -161,17 +249,49 @@
 }
 
 
+static void __init pci_fixup_cache_line(struct pci_dev *d)
+{
+	pci_write_config_byte(d,PCI_CACHE_LINE_SIZE,0);
+}
+
+
 /* Add future fixups here... */
 struct pci_fixup pcibios_fixups[] = {
 	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
+	{ PCI_FIXUP_FINAL,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_cache_line },
 	{ 0 }
 };
 
+char * __init pcibios_setup(char *str)
+{
+	return str;
+}
+
+static void __init st40pci_init_resources(void)
+{
+	pci_io_space.start = PCIBIOS_MIN_IO;
+	pci_io_space.end   = 64*1024 - PCIBIOS_MIN_IO - 1;
+	pci_io_space.name = "ST40 PCI";
+	pci_io_space.flags = IORESOURCE_IO;
+
+	request_resource(&ioport_resource, &pci_io_space);
+
+	pci_mem_space.start = PCIBIOS_MIN_MEM;
+	pci_mem_space.end   = PCIBIOS_MIN_MEM + (96*1024*1024) -1;
+	pci_mem_space.name = "ST40 PCI";
+	pci_mem_space.flags = IORESOURCE_MEM;
+
+	request_resource(&iomem_resource, &pci_mem_space);
+}
+
 int __init st40pci_init(unsigned memStart, unsigned memSize)
 {
 	u32 lsr0;
 
+ 	printk("PCI version register reads 0x%x\n",ST40PCI_READ(VCR_VERSION));
+
 	SetPCIPLL();
+	st40pci_init_resources();
 
 	/* Initialises the ST40 pci subsystem, performing a reset, then programming
 	 * up the address space decoders appropriately
@@ -184,21 +304,22 @@
 	/* Loop while core resets */
 	while (ST40PCI_READ(CR) & CR_SOFT_RESET);
 
+	/* Switch off interrupts */
+	ST40PCI_WRITE(INTM, 0);
+	ST40PCI_WRITE(AINT, 0);
+
 	/* Now, lets reset all the cards on the bus with extreme prejudice */
 	ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL);
 	udelay(250);
 
 	/* Set bus active, take it out of reset */
-	ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_CFINT | CR_PFCS | CR_PFE);
+	ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_BMAM | CR_CFINT | CR_PFCS | CR_PFE);
 
 	/* The PCI spec says that no access must be made to the bus until 1 second
 	 * after reset. This seem ludicrously long, but some delay is needed here
 	 */
 	mdelay(1000);
 
-	/* Switch off interrupts */
-	ST40PCI_WRITE(INTM, 0);
-	ST40PCI_WRITE(AINT, 0);
 
 	/* Allow it to be a master */
 
@@ -224,47 +345,24 @@
 	/* Set up the 64K window */
 	ST40PCI_WRITE(IOBMR, 0x0);
 
-	/* Now we set up the mbars so the PCI bus can see the memory of the machine */
+	/* Now we set up the mbars so the PCI bus can see the local memory */
+	/* Expose a 256M window starting at PCI address 0... */
+	ST40PCI_WRITE(CSR_MBAR0, 0);
+	ST40PCI_WRITE(LSR0, 0x0fff0001);
 
-	if (memSize < (64 * 1024)) {
-		printk("Ridiculous memory size of 0x%x?\n",memSize);
-		return 0;
-	}
-
-	lsr0 =
-	    (memSize >
-	     (512 * 1024 * 1024)) ? 0x1fff0001 : ((r2p2(memSize) -
-						   0x10000) | 0x1);
-
-	ST40PCI_WRITE(LSR0, lsr0);
-
-	ST40PCI_WRITE(CSR_MBAR0, memStart);
-	ST40PCI_WRITE(LAR0, memStart);
+	/* ... and set up the initial incomming window to expose all of RAM */
+	pci_set_rbar_region(7, memStart, memStart, memSize);
 
 	/* Maximise timeout values */
 	ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff);
 	ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff);
 	ST40PCI_WRITE_BYTE(CSR_MIT, 0xff);
 
-
-	/* Install the pci interrupt handlers */
-	make_intc2_irq(ST40PCI_SERR_IRQ, INTC2_BASE0,
-		       ST40PCI_SERR_INT_GROUP, ST40PCI_SERR_INT_POS,
-		       ST40PCI_SERR_INT_PRI);
-
-	make_intc2_irq(ST40PCI_ERR_IRQ, INTC2_BASE0, ST40PCI_ERR_INT_GROUP,
-		       ST40PCI_ERR_INT_POS, ST40PCI_ERR_INT_PRI);
-
+	ST40PCI_WRITE_BYTE(PERF,PERF_MASTER_WRITE_POSTING);
 
 	return 1;
 }
 
-char * __init pcibios_setup(char *str)
-{
-	return str;
-}
-
-
 #define SET_CONFIG_BITS(bus,devfn,where)\
   (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0))
 
@@ -276,7 +374,7 @@
 	if (ST40PCI_READ(INT) & INT_MADIM) {
 		/* Should we clear config space version as well ??? */
 		ST40PCI_WRITE(INT, INT_MADIM);
-		ST40PCI_WRITE_SHORT(CSR_STATUS, 0);
+		ST40PCI_WRITE_SHORT(CSR_STATUS, PCI_RMA);
 		return 1;
 	}
 
@@ -287,6 +385,8 @@
 static int st40pci_read_config_byte(struct pci_dev *dev, int where,
 				    u8 * val)
 {
+	CheckForMasterAbort();
+
 	ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
 
 	*val = ST40PCI_READ_BYTE(PDR + (where & 3));
@@ -301,6 +401,8 @@
 static int st40pci_read_config_word(struct pci_dev *dev, int where,
 				    u16 * val)
 {
+	CheckForMasterAbort();
+
 	ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
 
 	*val = ST40PCI_READ_SHORT(PDR + (where & 2));
@@ -315,13 +417,15 @@
 static int st40pci_read_config_dword(struct pci_dev *dev, int where,
 				     u32 * val)
 {
+	CheckForMasterAbort();
 
 	ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where));
 
 	*val = ST40PCI_READ(PDR);
 
-	if (CheckForMasterAbort())
+	if (CheckForMasterAbort()) {
 		*val = 0xffffffff;
+	}
 
 	return PCIBIOS_SUCCESSFUL;
 }
@@ -379,45 +483,37 @@
 
 static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
 {
+	printk("swizzle for dev %d on bus %d slot %d pin is %d\n",
+	       dev->devfn,dev->bus->number, PCI_SLOT(dev->devfn),*pin);
 	return PCI_SLOT(dev->devfn);
 }
 
+static inline u8 bridge_swizzle(u8 pin, u8 slot) 
+{
+	return (((pin-1) + slot) % 4) + 1;
+}
 
-/* This needs to be shunted out of here into the board specific bit */
-#define HARP_PCI_IRQ    1
-#define HARP_BRIDGE_IRQ 2
-#define OVERDRIVE_SLOT0_IRQ 0
-
-static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	switch (slot) {
-#ifdef CONFIG_SH_STB1_HARP
-	case 2:		/*This is the PCI slot on the */
-		return HARP_PCI_IRQ;
-	case 1:		/* this is the bridge */
-		return HARP_BRIDGE_IRQ;
-#elif defined(CONFIG_SH_STB1_OVERDRIVE)
-	case 1:
-	case 2:
-	case 3:
-		return slot - 1;
-#else
-#error Unknown board
-#endif
-	default:
-		return -1;
+u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+	if (dev->bus->number != 0) {
+		u8 pin = *pinp;
+		do {
+			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+			/* Move up the chain of bridges. */
+			dev = dev->bus->self;
+		} while (dev->bus->self);
+		*pinp = pin;
+
+		/* The slot is the slot of the last bridge. */
 	}
-}
 
+	return PCI_SLOT(dev->devfn);
+}
 
 void __init
 pcibios_fixup_pbus_ranges(struct pci_bus *bus,
 			  struct pbus_set_ranges_data *ranges)
 {
-	ranges->io_start -= bus->resource[0]->start;
-	ranges->io_end -= bus->resource[0]->start;
-	ranges->mem_start -= bus->resource[1]->start;
-	ranges->mem_end -= bus->resource[1]->start;
 }
 
 void __init pcibios_init(void)
@@ -435,12 +531,20 @@
 	st40pci_init(PHYSADDR(memory_start),
 		     PHYSADDR(memory_end) - PHYSADDR(memory_start));
 
+	if (request_irq(ST40PCI_SERR_IRQ, st40_pci_irq, 
+                        SA_INTERRUPT, "st40pci", NULL)) {
+		printk(KERN_ERR "st40pci: Cannot hook interrupt\n");
+		return;
+	}
+
 	if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq, 
                         SA_INTERRUPT, "st40pci", NULL)) {
 		printk(KERN_ERR "st40pci: Cannot hook interrupt\n");
 		return;
 	}
 
+	/* Reset state just in case any outstanding (usually SERR) */
+        ST40PCI_WRITE(INT, ~0); ST40PCI_WRITE(AINT, ~0); 
 	/* Enable the PCI interrupts on the device */
 	ST40PCI_WRITE(INTM, ~0);
 	ST40PCI_WRITE(AINT, ~0);
@@ -454,10 +558,137 @@
 	/* ok, do the scan man */
 	pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
 	pci_assign_unassigned_resources();
-	pci_fixup_irqs(no_swizzle, map_harp_irq);
+	pci_fixup_irqs(no_swizzle, pcibios_map_platform_irq);
 
 }
 
+void __init
+pcibios_fixup_resource(struct resource *res, struct resource *root)
+{
+        res->start += root->start;
+        res->end += root->start;
+}
+
+void __init
+pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
+{
+        /* Update device resources.  */
+        int i;
+
+        for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+                if (!dev->resource[i].start)
+                        continue;
+                if (dev->resource[i].flags & IORESOURCE_IO)
+                        pcibios_fixup_resource(&dev->resource[i],
+                                               &pci_io_space);
+                else if (dev->resource[i].flags & IORESOURCE_MEM)
+                        pcibios_fixup_resource(&dev->resource[i],
+                                               &pci_mem_space);
+        }
+}
+
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
+	/* Propogate hose info into the subordinate devices.  */
+	struct list_head *ln;
+	struct pci_dev *dev = bus->self;
+
+	if (!dev) {
+		bus->resource[0] = &pci_io_space;
+		bus->resource[1] = &pci_mem_space;
+	}
+
+	for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
+		struct pci_dev *dev = pci_dev_b(ln);
+		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+			pcibios_fixup_device_resources(dev, bus);
+	}
+}
+
+static void __init pcibios_assign_resources(void)
+{
+	struct pci_dev *dev;
+	int idx;
+	struct resource *r;
+	pci_for_each_dev(dev) {
+		int class = dev->class >> 8;
+
+		/* Don't touch classless devices and host bridges */
+		if (!class || class == PCI_CLASS_BRIDGE_HOST)
+			continue;
+
+		for(idx=0; idx<6; idx++) {
+			r = &dev->resource[idx];
+
+			/*
+			 *  Don't touch IDE controllers and I/O ports of video cards!
+			 */
+			if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
+			    (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
+				continue;
+
+			/*
+			 *  We shall assign a new address to this resource, either because
+			 *  the BIOS forgot to do so or because we have decided the old
+			 *  address was unusable for some reason.
+			 */
+			if (!r->start && r->end)
+                        {
+                          	pci_assign_resource(dev, idx);
+                         }
+		}
+#if 0 /* don't assign ROMs */
+		if (pci_probe & PCI_ASSIGN_ROMS) {
+			r = &dev->resource[PCI_ROM_RESOURCE];
+			r->end -= r->start;
+			r->start = 0;
+			if (r->end)
+				pci_assign_resource(dev, PCI_ROM_RESOURCE);
+		}
+#endif
+        }
+}
+
+/*
+ * Publish a region of local address space over the PCI bus
+ * to other devices.
+ */
+void pci_set_rbar_region(unsigned int region,     unsigned long localAddr,
+			 unsigned long pciOffset, unsigned long regionSize)
+{
+	unsigned long mask;
+
+	if (region > 7)
+		return;
+
+	if (regionSize > (512 * 1024 * 1024))
+		return;
+
+	mask = r2p2(regionSize) - 0x10000;
+
+	/* Diable the region (in case currently in use, should never happen) */
+	ST40PCI_WRITE_INDEXED(RSR, region, 0);
+
+	/* Start of local address space to publish */
+	ST40PCI_WRITE_INDEXED(RLAR, region, PHYSADDR(localAddr) );
+
+	/* Start of region in PCI address space as an offset from MBAR0 */
+	ST40PCI_WRITE_INDEXED(RBAR, region, pciOffset);
+
+	/* Size of region */
+	ST40PCI_WRITE_INDEXED(RSR, region, mask | 1);
+} 
+
+/*
+ * Make a previously published region of local address space
+ * inaccessible to other PCI devices.
+ */ 
+void pci_clear_rbar_region(unsigned int region)
+{
+	if (region > 7)
+		return;
+
+	ST40PCI_WRITE_INDEXED(RSR, region, 0);
+	ST40PCI_WRITE_INDEXED(RBAR, region, 0);
+	ST40PCI_WRITE_INDEXED(RLAR, region, 0);
 }
diff -urN linux-2.4.21-bk11/arch/sh/kernel/pci_st40.h linux-2.4.21-bk12/arch/sh/kernel/pci_st40.h
--- linux-2.4.21-bk11/arch/sh/kernel/pci_st40.h	2001-04-11 21:24:52.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/pci_st40.h	2003-07-17 02:52:28.000000000 -0700
@@ -33,13 +33,37 @@
 #define ST40PCI_LAR0          0x1c
 
 #define ST40PCI_INT           0x24
+#define INT_MNLTDIM           (1<<15)
+#define INT_TTADI             (1<<14)
+#define INT_TMTO              (1<<9)
+#define INT_MDEI              (1<<8)
+#define INT_APEDI             (1<<7)
+#define INT_SDI               (1<<6)
+#define INT_DPEITW            (1<<5)
+#define INT_PEDITR            (1<<4)
+#define INT_TADIM             (1<<3)
 #define INT_MADIM             (1<<2)
+#define INT_MWPDI             (1<<1)
+#define INT_MRDPEI            (1<<0)
 
 
 #define ST40PCI_INTM          0x28
 #define ST40PCI_AIR           0x2c
+
 #define ST40PCI_CIR           0x30
+#define CIR_PIOTEM            (1<<31)
+#define CIR_RWTET             (1<<26)
+
+
 #define ST40PCI_AINT          0x40
+#define AINT_MBI              (1<<13)
+#define AINT_TBTOI            (1<<12)
+#define AINT_MBTOI            (1<<11)
+#define AINT_TAI              (1<<3)
+#define AINT_MAI              (1<<2)
+#define AINT_RDPEI            (1<<1)
+#define AINT_WDPE             (1<<0)
+
 #define ST40PCI_AINTM         0x44
 #define ST40PCI_BMIR          0x48
 #define ST40PCI_PAR           0x4c
@@ -51,11 +75,58 @@
 #define ST40PCI_IOBMR         0x74
 #define ST40PCI_PDR           0x78
 
+/* H8 specific registers start here */
+#define ST40PCI_WCBAR         0x7c
+#define ST40PCI_LOCCFG_UNLOCK 0x34
+
+#define ST40PCI_RBAR0         0x100
+#define ST40PCI_RSR0          0x104
+#define ST40PCI_RLAR0         0x108
+
+#define ST40PCI_RBAR1         0x110
+#define ST40PCI_RSR1          0x114
+#define ST40PCI_RLAR1         0x118
+
+
+#define ST40PCI_RBAR2         0x120
+#define ST40PCI_RSR2          0x124
+#define ST40PCI_RLAR2         0x128
+
+#define ST40PCI_RBAR3         0x130
+#define ST40PCI_RSR3          0x134
+#define ST40PCI_RLAR3         0x138
+
+#define ST40PCI_RBAR4         0x140
+#define ST40PCI_RSR4          0x144
+#define ST40PCI_RLAR4         0x148
+
+#define ST40PCI_RBAR5         0x150
+#define ST40PCI_RSR5          0x154
+#define ST40PCI_RLAR5         0x158
+
+#define ST40PCI_RBAR6         0x160
+#define ST40PCI_RSR6          0x164
+#define ST40PCI_RLAR6         0x168
+
+#define ST40PCI_RBAR7         0x170
+#define ST40PCI_RSR7          0x174
+#define ST40PCI_RLAR7         0x178
+
+
+#define ST40PCI_RBAR(n)      (0x100+(0x10*(n)))
+#define ST40PCI_RSR(n)       (0x104+(0x10*(n)))
+#define ST40PCI_RLAR(n)      (0x108+(0x10*(n)))
+
+#define ST40PCI_PERF               0x80
+#define PERF_MASTER_WRITE_POSTING  (1<<4)
+/* H8 specific registers end here */
+
 /* These are configs space registers */
 #define ST40PCI_CSR_VID               0x10000
 #define ST40PCI_CSR_DID               0x10002
 #define ST40PCI_CSR_CMD               0x10004
 #define ST40PCI_CSR_STATUS            0x10006
+#define   PCI_RMA			(1<<13)
 #define ST40PCI_CSR_MBAR0             0x10010
 #define ST40PCI_CSR_TRDY              0x10040
 #define ST40PCI_CSR_RETRY             0x10041
@@ -63,4 +134,10 @@
 
 #define ST40_IO_ADDR 0xb6000000       
 
+#define ST40PCI_INTPIN			0x1003d
+
+void pci_set_rbar_region(unsigned int region,     unsigned long localAddr,
+			 unsigned long pciOffset, unsigned long regionSize);
+void pci_clear_rbar_region(unsigned int region);
+
 #endif /* __PCI_ST40_H__ */
diff -urN linux-2.4.21-bk11/arch/sh/kernel/process.c linux-2.4.21-bk12/arch/sh/kernel/process.c
--- linux-2.4.21-bk11/arch/sh/kernel/process.c	2003-06-13 07:51:32.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/process.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.35 2001/10/11 09:18:17 gniibe Exp $
+/* $Id: process.c,v 1.1.1.1.2.4 2003/05/29 04:21:33 lethal Exp $
  *
  *  linux/arch/sh/kernel/process.c
  *
@@ -21,6 +21,8 @@
 
 static int hlt_counter=0;
 
+int ubc_usercnt = 0;
+
 #define HARD_IDLE_TIMEOUT (HZ / 3)
 
 void disable_hlt(void)
@@ -45,8 +47,9 @@
 
 	while (1) {
 		if (hlt_counter) {
-			if (current->need_resched)
-				break;
+			while (1)
+				if (current->need_resched)
+					break;
 		} else {
 			__cli();
 			while (!current->need_resched) {
@@ -148,7 +151,10 @@
  */
 void exit_thread(void)
 {
-	/* Nothing to do. */
+	if (current->thread.ubc_pc1) {
+		current->thread.ubc_pc1 = 0;
+		ubc_usercnt -= 1;
+	}
 }
 
 void flush_thread(void)
@@ -179,11 +185,7 @@
 
 	fpvalid = tsk->used_math;
 	if (fpvalid) {
-		unsigned long flags;
-
-		save_and_cli(flags);
 		unlazy_fpu(tsk);
-		restore_flags(flags);
 		memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
 	}
 
@@ -203,15 +205,9 @@
 #if defined(__SH4__)
 	struct task_struct *tsk = current;
 
-	if (tsk != &init_task) {
-		unsigned long flags;
-
-		save_and_cli(flags);
-		unlazy_fpu(tsk);
-		restore_flags(flags);
-		p->thread.fpu = current->thread.fpu;
-		p->used_math = tsk->used_math;
-	}
+	unlazy_fpu(tsk);
+	p->thread.fpu = current->thread.fpu;
+	p->used_math = tsk->used_math;
 #endif
 	childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p)) - 1;
 	*childregs = *regs;
@@ -227,6 +223,9 @@
 	p->thread.sp = (unsigned long) childregs;
 	p->thread.pc = (unsigned long) ret_from_fork;
 
+	p->thread.ubc_pc1 = 0;
+	p->thread.ubc_pc2 = 0;
+
 	return 0;
 }
 
@@ -250,6 +249,37 @@
 	dump->u_fpvalid = dump_fpu(regs, &dump->fpu);
 }
 
+/* Tracing by user break controller.  */
+static inline void
+ubc_set_tracing(int asid, unsigned long nextpc1, unsigned nextpc2)
+{
+	ctrl_outl(nextpc1, UBC_BARA);
+	ctrl_outb(asid, UBC_BASRA);
+	if(UBC_TYPE_SH7729){
+		ctrl_outl(0, UBC_BAMRA);
+		ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
+	}else{
+		ctrl_outb(0, UBC_BAMRA);
+		ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
+	}
+
+	if (nextpc2 != (unsigned long) -1) {
+		ctrl_outl(nextpc2, UBC_BARB);
+		ctrl_outb(asid, UBC_BASRB);
+		if(UBC_TYPE_SH7729){
+			ctrl_outl(0, UBC_BAMRB);
+			ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRB);
+		}else{
+			ctrl_outb(0, UBC_BAMRB);
+			ctrl_outw(BBR_INST | BBR_READ, UBC_BBRB);
+		}
+	}
+	if(UBC_TYPE_SH7729)
+		ctrl_outl(BRCR_PCTE, UBC_BRCR);
+	else
+		ctrl_outw(0, UBC_BRCR);
+}
+
 /*
  *	switch_to(x,y) should switch tasks from x to y.
  *
@@ -257,14 +287,9 @@
 void __switch_to(struct task_struct *prev, struct task_struct *next)
 {
 #if defined(__SH4__)
-	if (prev != &init_task) {
-		unsigned long flags;
-
-		save_and_cli(flags);
-		unlazy_fpu(prev);
-		restore_flags(flags);
-	}
+	unlazy_fpu(prev);
 #endif
+
 	/*
 	 * Restore the kernel mode register
 	 *   	k7 (r7_bank1)
@@ -272,6 +297,19 @@
 	asm volatile("ldc	%0, r7_bank"
 		     : /* no output */
 		     :"r" (next));
+
+	/* If no tasks are using the UBC, we're done */
+	if (ubc_usercnt == 0)
+		return;
+
+	/* Otherwise, set or clear UBC as appropriate */
+	if (next->thread.ubc_pc1) {
+		ubc_set_tracing(next->mm->context & MMU_CONTEXT_ASID_MASK,
+				next->thread.ubc_pc1, next->thread.ubc_pc2);
+	} else {
+		ctrl_outw(0, UBC_BBRA);
+		ctrl_outw(0, UBC_BBRB);
+	}
 }
 
 asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
@@ -375,6 +413,9 @@
 	/* Clear tracing.  */
 	ctrl_outw(0, UBC_BBRA);
 	ctrl_outw(0, UBC_BBRB);
+	current->thread.ubc_pc1 = 0;
+	current->thread.ubc_pc2 = (unsigned long) -1;
+	ubc_usercnt -= 1;
 
 	force_sig(SIGTRAP, current);
 }
diff -urN linux-2.4.21-bk11/arch/sh/kernel/ptrace.c linux-2.4.21-bk12/arch/sh/kernel/ptrace.c
--- linux-2.4.21-bk11/arch/sh/kernel/ptrace.c	2001-10-15 13:36:48.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/ptrace.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: ptrace.c,v 1.13 2001/10/01 02:21:50 gniibe Exp $
+/* $Id: ptrace.c,v 1.1.1.1.2.1 2002/11/12 02:24:19 jzs Exp $
  *
  * linux/arch/sh/kernel/ptrace.c
  *
@@ -116,37 +116,6 @@
 	return;
 }
 
-/* Tracing by user break controller.  */
-static void
-ubc_set_tracing(int asid, unsigned long nextpc1, unsigned nextpc2)
-{
-	ctrl_outl(nextpc1, UBC_BARA);
-	ctrl_outb(asid, UBC_BASRA);
-	if(UBC_TYPE_SH7729){
-		ctrl_outl(0x0fff, UBC_BAMRA);
-		ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
-	}else{
-		ctrl_outb(BAMR_12, UBC_BAMRA);
-		ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA);
-	}
-
-	if (nextpc2 != (unsigned long) -1) {
-		ctrl_outl(nextpc2, UBC_BARB);
-		ctrl_outb(asid, UBC_BASRB);
-		if(UBC_TYPE_SH7729){
-			ctrl_outl(0x0fff, UBC_BAMRB);
-			ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRB);
-		}else{
-			ctrl_outb(BAMR_12, UBC_BAMRB);
-			ctrl_outw(BBR_INST | BBR_READ, UBC_BBRB);
-		}
-	}
-	if(UBC_TYPE_SH7729)
-		ctrl_outl(BRCR_PCBA | BRCR_PCBB | BRCR_PCTE, UBC_BRCR);
-	else
-		ctrl_outw(BRCR_PCBA | BRCR_PCBB, UBC_BRCR);
-}
-
 /*
  * Called by kernel/ptrace.c when detaching..
  *
@@ -342,8 +311,11 @@
 		if (nextpc2 != (unsigned long) -1 && (nextpc2 & 0x80000000))
 			break;
 
-		ubc_set_tracing(child->mm->context & MMU_CONTEXT_ASID_MASK,
-				nextpc1, nextpc2);
+		/* Next scheduling will set up UBC */
+		if (child->thread.ubc_pc1 == 0)
+			ubc_usercnt += 1;
+		child->thread.ubc_pc1 = nextpc1;
+		child->thread.ubc_pc2 = nextpc2;
 
 		child->exit_code = data;
 		/* give it a chance to run. */
diff -urN linux-2.4.21-bk11/arch/sh/kernel/rtc-snapgear.c linux-2.4.21-bk12/arch/sh/kernel/rtc-snapgear.c
--- linux-2.4.21-bk11/arch/sh/kernel/rtc-snapgear.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/rtc-snapgear.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,323 @@
+/****************************************************************************/
+/*
+ * linux/arch/sh/kernel/rtc-snapgear.c -- Secureedge5410 RTC code
+ *
+ *  Copyright (C) 2002  David McCullough <davidm@snapgear.com>
+ *
+ * The SecureEdge5410 can have one of 2 real time clocks, the SH
+ * built in version or the preferred external DS1302.  Here we work out
+ * each to see what we have and then run with it.
+ */
+/****************************************************************************/
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/io.h>
+#include <asm/rtc.h>
+#include <asm/mc146818rtc.h>
+
+/****************************************************************************/
+
+static int use_ds1302 = 0;
+
+/****************************************************************************/
+/*
+ *	we need to implement a DS1302 driver here that can operate in
+ *	conjunction with the builtin rtc driver which is already quite friendly
+ */
+/*****************************************************************************/
+
+#define	RTC_CMD_READ	0x81		/* Read command */
+#define	RTC_CMD_WRITE	0x80		/* Write command */
+
+#define	RTC_ADDR_YEAR	0x06		/* Address of year register */
+#define	RTC_ADDR_DAY	0x05		/* Address of day of week register */
+#define	RTC_ADDR_MON	0x04		/* Address of month register */
+#define	RTC_ADDR_DATE	0x03		/* Address of day of month register */
+#define	RTC_ADDR_HOUR	0x02		/* Address of hour register */
+#define	RTC_ADDR_MIN	0x01		/* Address of minute register */
+#define	RTC_ADDR_SEC	0x00		/* Address of second register */
+
+#define	RTC_RESET	0x1000
+#define	RTC_IODATA	0x0800
+#define	RTC_SCLK	0x0400
+
+#define set_dirp(x)
+#define get_dirp(x) 0
+#define set_dp(x)	SECUREEDGE_WRITE_IOPORT(x, 0x1c00)
+#define get_dp(x)	SECUREEDGE_READ_IOPORT()
+
+static void ds1302_sendbits(unsigned int val)
+{
+	int	i;
+
+	for (i = 8; (i); i--, val >>= 1) {
+		set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? RTC_IODATA : 0));
+		set_dp(get_dp() | RTC_SCLK);	// clock high
+		set_dp(get_dp() & ~RTC_SCLK);	// clock low
+	}
+}
+
+static unsigned int ds1302_recvbits(void)
+{
+	unsigned int	val;
+	int		i;
+
+	for (i = 0, val = 0; (i < 8); i++) {
+		val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i);
+		set_dp(get_dp() | RTC_SCLK);	// clock high
+		set_dp(get_dp() & ~RTC_SCLK);	// clock low
+	}
+	return(val);
+}
+
+static unsigned int ds1302_readbyte(unsigned int addr)
+{
+	unsigned int	val;
+	unsigned long	flags;
+
+#if 0
+	printk("SnapGear RTC: ds1302_readbyte(addr=%x)\n", addr);
+#endif
+
+	save_flags(flags); cli();
+	set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
+	set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
+
+	set_dp(get_dp() | RTC_RESET);
+	ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ);
+	set_dirp(get_dirp() & ~RTC_IODATA);
+	val = ds1302_recvbits();
+	set_dp(get_dp() & ~RTC_RESET);
+	restore_flags(flags);
+
+	return(val);
+}
+
+static void ds1302_writebyte(unsigned int addr, unsigned int val)
+{
+	unsigned long	flags;
+
+#if 0
+	printk("SnapGear RTC: ds1302_writebyte(addr=%x)\n", addr);
+#endif
+
+	save_flags(flags); cli();
+	set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
+	set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
+	set_dp(get_dp() | RTC_RESET);
+	ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE);
+	ds1302_sendbits(val);
+	set_dp(get_dp() & ~RTC_RESET);
+	restore_flags(flags);
+}
+
+static void ds1302_reset(void)
+{
+	unsigned long	flags;
+	/* Hardware dependant reset/init */
+	save_flags(flags); cli();
+	set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
+	set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
+	restore_flags(flags);
+}
+
+/*****************************************************************************/
+
+static inline int bcd2int(int val)
+{
+	return((((val & 0xf0) >> 4) * 10) + (val & 0xf));
+}
+
+static inline int int2bcd(int val)
+{
+	return(((val / 10) << 4) + (val % 10));
+}
+
+/*****************************************************************************/
+/*
+ *	Write and Read some RAM in the DS1302,  if it works assume it's there
+ *	Otherwise use the SH4 internal RTC
+ */
+
+void __init secureedge5410_rtc_init(void)
+{
+	unsigned char *test = "snapgear";
+	int i;
+
+	ds1302_reset();
+
+	use_ds1302 = 1;
+
+	for (i = 0; test[i]; i++)
+		ds1302_writebyte(32 + i, test[i]);
+
+	for (i = 0; test[i]; i++)
+		if (ds1302_readbyte(32 + i) != test[i]) {
+			use_ds1302 = 0;
+			break;
+		}
+
+	printk("SnapGear RTC: using %s rtc.\n", use_ds1302 ? "ds1302" : "internal");
+}
+
+/****************************************************************************/
+/*
+ *	our generic interface that chooses the correct code to use
+ */
+
+void snapgear_rtc_gettimeofday(struct timeval *tv)
+{
+	unsigned int sec, min, hr, day, mon, yr;
+
+	if (!use_ds1302) {
+		sh_rtc_gettimeofday(tv);
+		return;
+	}
+
+ 	sec = bcd2int(ds1302_readbyte(RTC_ADDR_SEC));
+ 	min = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
+ 	hr  = bcd2int(ds1302_readbyte(RTC_ADDR_HOUR));
+ 	day = bcd2int(ds1302_readbyte(RTC_ADDR_DATE));
+ 	mon = bcd2int(ds1302_readbyte(RTC_ADDR_MON));
+ 	yr  = bcd2int(ds1302_readbyte(RTC_ADDR_YEAR));
+
+bad_time:
+	if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
+	    hr > 23 || min > 59 || sec > 59) {
+		printk(KERN_ERR
+		       "SnapGear RTC: invalid value, resetting to 1 Jan 2000\n");
+		ds1302_writebyte(RTC_ADDR_MIN,  min = 0);
+		ds1302_writebyte(RTC_ADDR_HOUR, hr  = 0);
+		ds1302_writebyte(RTC_ADDR_DAY,        7);
+		ds1302_writebyte(RTC_ADDR_DATE, day = 1);
+		ds1302_writebyte(RTC_ADDR_MON,  mon = 1);
+		ds1302_writebyte(RTC_ADDR_YEAR, yr  = 0);
+		ds1302_writebyte(RTC_ADDR_SEC,  sec = 0);
+	}
+
+	tv->tv_sec = mktime(2000 + yr, mon, day, hr, min, sec);
+	if (tv->tv_sec < 0) {
+#if 0
+		printk("BAD TIME %d %d %d %d %d %d\n", yr, mon, day, hr, min, sec);
+#endif
+		yr = 100;
+		goto bad_time;
+	}
+	tv->tv_usec = 0;
+}
+
+int snapgear_rtc_settimeofday(const struct timeval *tv)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned long nowtime;
+
+	if (!use_ds1302) {
+		sh_rtc_settimeofday(tv);
+		return(0);
+	}
+
+/*
+ *	This is called direct from the kernel timer handling code.
+ *	It is supposed to synchronize the kernel clock to the RTC.
+ */
+
+	nowtime = tv->tv_sec;
+
+#if 1
+	printk("SnapGear RTC: snapgear_rtc_settimeofday(nowtime=%ld)\n", nowtime);
+#endif
+
+	/* STOP RTC */
+	ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
+
+	cmos_minutes = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;	/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		ds1302_writebyte(RTC_ADDR_MIN, int2bcd(real_minutes));
+		ds1302_writebyte(RTC_ADDR_SEC, int2bcd(real_seconds));
+	} else {
+		printk(KERN_WARNING
+		       "SnapGear RTC: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+		retval = -1;
+	}
+
+	/* START RTC */
+	ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80);
+	return(0);
+}
+
+unsigned char secureedge5410_cmos_read(int addr)
+{
+	unsigned char val = 0;
+
+	if (!use_ds1302)
+		return(__CMOS_READ(addr, w));
+
+	switch(addr) {
+	case RTC_SECONDS:       val = ds1302_readbyte(RTC_ADDR_SEC);  break;
+	case RTC_SECONDS_ALARM:                                       break;
+	case RTC_MINUTES:       val = ds1302_readbyte(RTC_ADDR_MIN);  break;
+	case RTC_MINUTES_ALARM:                                       break;
+	case RTC_HOURS:         val = ds1302_readbyte(RTC_ADDR_HOUR); break;
+	case RTC_HOURS_ALARM:                                         break;
+	case RTC_DAY_OF_WEEK:   val = ds1302_readbyte(RTC_ADDR_DAY);  break;
+	case RTC_DAY_OF_MONTH:  val = ds1302_readbyte(RTC_ADDR_DATE); break;
+	case RTC_MONTH:         val = ds1302_readbyte(RTC_ADDR_MON);  break;
+	case RTC_YEAR:          val = ds1302_readbyte(RTC_ADDR_YEAR); break;
+	case RTC_REG_A:         /* RTC_FREQ_SELECT */                 break;
+	case RTC_REG_B:	        /* RTC_CONTROL */                     break;
+	case RTC_REG_C:	        /* RTC_INTR_FLAGS */                  break;
+	case RTC_REG_D:         val = RTC_VRT /* RTC_VALID */;        break;
+	default:                                                      break;
+	}
+
+	return(val);
+}
+
+void secureedge5410_cmos_write(unsigned char val, int addr)
+{
+	if (!use_ds1302) {
+		__CMOS_WRITE(val, addr, w);
+		return;
+	}
+
+	switch(addr) {
+	case RTC_SECONDS:       ds1302_writebyte(RTC_ADDR_SEC, val);  break;
+	case RTC_SECONDS_ALARM:                                       break;
+	case RTC_MINUTES:       ds1302_writebyte(RTC_ADDR_MIN, val);  break;
+	case RTC_MINUTES_ALARM:                                       break;
+	case RTC_HOURS:         ds1302_writebyte(RTC_ADDR_HOUR, val); break;
+	case RTC_HOURS_ALARM:                                         break;
+	case RTC_DAY_OF_WEEK:   ds1302_writebyte(RTC_ADDR_DAY, val);  break;
+	case RTC_DAY_OF_MONTH:  ds1302_writebyte(RTC_ADDR_DATE, val); break;
+	case RTC_MONTH:         ds1302_writebyte(RTC_ADDR_MON, val);  break;
+	case RTC_YEAR:          ds1302_writebyte(RTC_ADDR_YEAR, val); break;
+	case RTC_REG_A:         /* RTC_FREQ_SELECT */                 break;
+	case RTC_REG_B:        	/* RTC_CONTROL */                     break;
+	case RTC_REG_C:	        /* RTC_INTR_FLAGS */                  break;
+	case RTC_REG_D:	        /* RTC_VALID */                       break;
+	default:                                                      break;
+	}
+}
+
+/****************************************************************************/
diff -urN linux-2.4.21-bk11/arch/sh/kernel/rtc.c linux-2.4.21-bk12/arch/sh/kernel/rtc.c
--- linux-2.4.21-bk11/arch/sh/kernel/rtc.c	2002-02-25 11:37:56.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/rtc.c	2003-07-17 02:52:28.000000000 -0700
@@ -23,7 +23,7 @@
 
 void sh_rtc_gettimeofday(struct timeval *tv)
 {
-	unsigned int sec128, sec, min, hr, wk, day, mon, yr, yr100;
+	unsigned int sec128, sec, min, hr, wk, day, mon, yr, yr100, badval;
 
  again:
 	do {
@@ -53,16 +53,21 @@
 	}
 #endif
 
-	BCD_TO_BIN(yr100);
-	BCD_TO_BIN(yr);
-	BCD_TO_BIN(mon);
-	BCD_TO_BIN(day);
-	BCD_TO_BIN(hr);
-	BCD_TO_BIN(min);
-	BCD_TO_BIN(sec);
+	badval = ((yr & 15) > 9 || (mon & 15) > 9 || (day & 15) > 9 ||
+		 (hr & 15) > 9 || (min & 15) > 9 || (sec & 15) > 9);
 
-	if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
-	    hr > 23 || min > 59 || sec > 59) {
+	if (!badval) {
+		BCD_TO_BIN(yr100);
+		BCD_TO_BIN(yr);
+		BCD_TO_BIN(mon);
+		BCD_TO_BIN(day);
+		BCD_TO_BIN(hr);
+		BCD_TO_BIN(min);
+		BCD_TO_BIN(sec);
+	}
+
+	if (badval || yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
+	    hr > 23 || min > 59 || sec > 59 || (yr100 != 19 && yr100 != 20)) {
 		printk(KERN_ERR
 		       "SH RTC: invalid value, resetting to 1 Jan 2000\n");
 		ctrl_outb(RCR2_RESET, RCR2);  /* Reset & Stop */
diff -urN linux-2.4.21-bk11/arch/sh/kernel/setup.c linux-2.4.21-bk12/arch/sh/kernel/setup.c
--- linux-2.4.21-bk11/arch/sh/kernel/setup.c	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/setup.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.31 2001/08/23 16:36:40 dwmw2 Exp $
+/* $Id: setup.c,v 1.1.1.1.2.7 2003/06/20 13:13:25 trent Exp $
  *
  *  linux/arch/sh/kernel/setup.c
  *
@@ -44,6 +44,11 @@
 #include <asm/sh_bios.h>
 #endif
 
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+static int kgdb_parse_options(char *options);
+#endif
+
 /*
  * Machine setup..
  */
@@ -298,6 +303,10 @@
 
 	parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable);
 
+#ifdef CONFIG_CMDLINE_BOOL
+	sprintf(*cmdline_p, CONFIG_CMDLINE);
+#endif
+
 #ifdef CONFIG_SH_GENERIC
 	if (mv == NULL) {
 		mv = &mv_unknown;
@@ -475,10 +484,20 @@
 	}
 
 #if defined(__SH4__)
-	/* We already grab/initialized FPU in head.S.  Make it consisitent. */
-	init_task.used_math = 1;
-	init_task.flags |= PF_USEDFPU;
+	init_task.used_math = 0;
+	init_task.flags &= ~PF_USEDFPU;
+#endif
+
+#ifdef CONFIG_UBC_WAKEUP
+	/*
+	 * Some brain-damaged loaders decided it would be a good idea to put
+	 * the UBC to sleep. This causes some issues when it comes to things
+	 * like PTRACE_SINGLESTEP or doing hardware watchpoints in GDB.  So ..
+	 * we wake it up and hope that all is well.
+	 */
+	ubc_wakeup();
 #endif
+
 	paging_init();
 }
 
@@ -528,7 +547,7 @@
 	
 	PRINT_CLOCK("CPU", boot_cpu_data.cpu_clock);
 	PRINT_CLOCK("Bus", boot_cpu_data.bus_clock);
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
 	PRINT_CLOCK("Memory", boot_cpu_data.memory_clock);
 #endif
 	PRINT_CLOCK("Peripheral module", boot_cpu_data.module_clock);
@@ -553,4 +572,94 @@
 	stop:	c_stop,
 	show:	show_cpuinfo,
 };
-#endif
+#endif /* CONFIG_PROC_FS */
+
+#ifdef CONFIG_SH_KGDB
+/*
+ * Parse command-line kgdb options.  By default KGDB is enabled,
+ * entered on error (or other action) using default serial info.
+ * The command-line option can include a serial port specification
+ * and an action to override default or configured behavior.
+ */
+struct kgdb_sermap kgdb_sci_sermap =
+{ "ttySC", 5, kgdb_sci_setup, NULL };
+
+struct kgdb_sermap *kgdb_serlist = &kgdb_sci_sermap;
+struct kgdb_sermap *kgdb_porttype = &kgdb_sci_sermap;
+
+void kgdb_register_sermap(struct kgdb_sermap *map)
+{
+	struct kgdb_sermap *last;
+
+	for (last = kgdb_serlist; last->next; last = last->next)
+		;
+	last->next = map;
+	if (!map->namelen) {
+		map->namelen = strlen(map->name);
+	}
+}
+
+static int __init kgdb_parse_options(char *options)
+{
+	char c;
+	int baud;
+
+	/* Check for port spec (or use default) */
+
+	/* Determine port type and instance */
+	if (!memcmp(options, "tty", 3)) {
+		struct kgdb_sermap *map = kgdb_serlist;
+
+		while (map && memcmp(options, map->name, map->namelen))
+			map = map->next;
+
+		if (!map) {
+			KGDB_PRINTK("unknown port spec in %s\n", options);
+			return -1;
+		}
+
+		kgdb_porttype = map;
+		kgdb_serial_setup = map->setup_fn;
+		kgdb_portnum = options[map->namelen] - '0';
+		options += map->namelen + 1;
+
+		options = (*options == ',') ? options+1 : options;
+		
+		/* Read optional parameters (baud/parity/bits) */
+		baud = simple_strtoul(options, &options, 10);
+		if (baud != 0) {
+			kgdb_baud = baud;
+
+			c = toupper(*options);
+			if (c == 'E' || c == 'O' || c == 'N') {
+				kgdb_parity = c;
+				options++;
+			}
+
+			c = *options;
+			if (c == '7' || c == '8') {
+				kgdb_bits = c;
+				options++;
+			}
+			options = (*options == ',') ? options+1 : options;
+		}
+	}
+
+	/* Check for action specification */
+	if (!memcmp(options, "halt", 4)) {
+		kgdb_halt = 1;
+		options += 4;
+	} else if (!memcmp(options, "disabled", 8)) {
+		kgdb_enabled = 0;
+		options += 8;
+	}
+
+	if (*options) {
+                KGDB_PRINTK("ignored unknown options: %s\n", options);
+		return 0;
+	}
+	return 1;
+}
+__setup("kgdb=", kgdb_parse_options);
+#endif /* CONFIG_SH_KGDB */
+
diff -urN linux-2.4.21-bk11/arch/sh/kernel/setup_hs7729pci.c linux-2.4.21-bk12/arch/sh/kernel/setup_hs7729pci.c
--- linux-2.4.21-bk11/arch/sh/kernel/setup_hs7729pci.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/setup_hs7729pci.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,212 @@
+/* $Id: setup_hs7729pci.c,v 1.1.2.1 2003/06/24 08:45:47 dwmw2 Exp $
+ *
+ * linux/arch/sh/kernel/setup_hs7729pci.c
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Hitachi Semiconductor and Devices HS7729PCI Support.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <asm/io.h>
+#include <asm/hitachi_hs7729pci.h>
+#include <asm/smc37c93x.h>
+
+static int interrupt_count;
+static int sevenseg_count;
+
+extern unsigned char aux_device_present;
+
+/*
+ * Configure the Super I/O chip
+ */
+static void __init smsc_config(int index, int data)
+{
+	outb_p(index, INDEX_PORT);
+	outb_p(data, DATA_PORT);
+}
+
+static void __init init_smsc(void)
+{
+	outb_p(CONFIG_ENTER, CONFIG_PORT);
+	outb_p(CONFIG_ENTER, CONFIG_PORT);
+
+#if defined(CONFIG_BLK_DEV_FD)
+	/* FDC */
+	smsc_config(CURRENT_LDN_INDEX, LDN_FDC);
+	smsc_config(ACTIVATE_INDEX, 0x01);
+	smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE)
+	/* IDE1 */
+	smsc_config(CURRENT_LDN_INDEX, LDN_IDE1);
+	smsc_config(ACTIVATE_INDEX, 0x01);
+	smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */
+	smsc_config(IO_BASE_HI_INDEX, 0x01);
+        smsc_config(IO_BASE_LO_INDEX, 0x70);
+	smsc_config(0x62, 0x03);
+        smsc_config(0x63, 0x76);
+
+#if 0
+#define SMSC_RD(adr) ({ outb(adr, 0x3f0), inb(0x3f1); })
+
+	printk("IDE1 addrs 0x%02x%02x, 0x%02x%02x\n", SMSC_RD(0x60), SMSC_RD(0x61), SMSC_RD(0x62), SMSC_RD(0x63));
+	printk("IDE1 Reg 0xF0: %02x. IDE1 Reg 0xF1: %02x\n", SMSC_RD(0xf0), SMSC_RD(0xf1));
+	printk("Power reg: %02x\n", SMSC_RD(0x22));
+	smsc_config(0x22, 0x3f);
+	printk("Power reg changed to: %02x\n", SMSC_RD(0x22));
+#endif	       
+#endif
+
+	/* AUXIO (GPIO): to use IDE1 */
+	smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO);
+	smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */
+	smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */
+
+#if defined(CONFIG_SERIAL)
+	/* COM1 */
+	smsc_config(CURRENT_LDN_INDEX, LDN_COM1);
+	smsc_config(ACTIVATE_INDEX, 0x01);
+	smsc_config(IO_BASE_HI_INDEX, 0x03);
+	smsc_config(IO_BASE_LO_INDEX, 0xf8);
+	smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */
+
+	/* COM2 */
+	smsc_config(CURRENT_LDN_INDEX, LDN_COM2);
+	smsc_config(ACTIVATE_INDEX, 0x01);
+	smsc_config(IO_BASE_HI_INDEX, 0x02);
+	smsc_config(IO_BASE_LO_INDEX, 0xf8);
+	smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */
+#endif
+
+	/* RTC */
+	smsc_config(CURRENT_LDN_INDEX, LDN_RTC);
+	smsc_config(ACTIVATE_INDEX, 0x01);
+	smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */
+
+#if defined(CONFIG_VT)
+	disable_irq(1);
+
+	/* KBD */
+	smsc_config(CURRENT_LDN_INDEX, LDN_KBC);
+	smsc_config(ACTIVATE_INDEX, 0x01);
+	smsc_config(IRQ_SELECT_INDEX, 1); /* IRQ1 */
+	smsc_config(IRQ_SELECT_INDEX+2, 12); /* IRQ12 */
+
+	/* Let it probe for PS/2 port. It should find one. */
+	aux_device_present = 0;
+#endif
+
+#if defined(CONFIG_PARPORT)
+	/* PARALLEL */
+	smsc_config(CURRENT_LDN_INDEX, LDN_PARPORT);
+	smsc_config(ACTIVATE_INDEX, 0x01);
+	smsc_config(IO_BASE_HI_INDEX, 0x03);
+	smsc_config(IO_BASE_LO_INDEX, 0x78);
+	smsc_config(IRQ_SELECT_INDEX, 5); /* IRQ5 */
+#endif
+
+	outb_p(CONFIG_EXIT, CONFIG_PORT);
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_hs7729pci_IRQ(void)
+{
+	/*
+	 * Super I/O (Just mimic PC):
+	 *  0: SD0001
+	 *  1: keyboard
+	 *  3: serial 0
+	 *  4: serial 1
+	 *  5: printer
+	 *  6: floppy
+	 *  8: rtc
+	 * 12: mouse
+	 * 14: ide0
+	 */
+	ctrl_outw(0x0130, BCR_ILCRA);
+	ctrl_outw(0x0070, BCR_ILCRB);
+	ctrl_outw(0x9abc, BCR_ILCRC);
+	ctrl_outw(0xef84, BCR_ILCRD);
+	ctrl_outw(0x0506, BCR_ILCRE);
+	ctrl_outw(0x0002, BCR_ILCRF);
+	ctrl_outw(0x000d, BCR_ILCRG);
+
+	make_ipr_irq(15, BCR_ILCRA, 3, 0x00); /* IRQ15 */
+	make_ipr_irq(14, BCR_ILCRA, 2, 0x01); /* IRQ14 */
+	make_ipr_irq(12, BCR_ILCRA, 1, 0x03); /* IRQ12 */
+
+	make_ipr_irq( 8, BCR_ILCRB, 1, 0x07); /* IRQ8 */
+
+	make_ipr_irq( 6, BCR_ILCRC, 3, 0x09); /* IRQ6 */
+	make_ipr_irq( 5, BCR_ILCRC, 2, 0x0a); /* IRQ5 */
+	make_ipr_irq( 4, BCR_ILCRC, 1, 0x0b); /* IRQ4 */
+	make_ipr_irq( 3, BCR_ILCRC, 0, 0x0c); /* IRQ3 */
+
+	make_ipr_irq( 1, BCR_ILCRD, 3, 0x0e); /* IRQ1 */
+	make_ipr_irq( 0, BCR_ILCRD, 2, 0x0f); /* PCI_IRQ0 */
+	make_ipr_irq( 7, BCR_ILCRD, 1, 0x08); /* USB1_IRQ */
+	make_ipr_irq(11, BCR_ILCRD, 0, 0x04); /* USB2_IRQ */
+
+	make_ipr_irq(10, BCR_ILCRE, 2, 0x05); /* PC_IRQ2 */
+	make_ipr_irq( 9, BCR_ILCRE, 0, 0x06); /* PC_IRQ1 */
+
+	make_ipr_irq(13, BCR_ILCRF, 0, 0x02); /* SLOT_IRQ5 */
+
+	make_ipr_irq( 2, BCR_ILCRG, 0, 0x0d); /* SLOT_IRQ1 */
+}
+
+/*
+ * Initialize the board
+ */
+
+void __init setup_hs7729pci(void)
+{
+	init_smsc();
+	/* XXX: RTC setting comes here */
+	interrupt_count = 0;
+	sevenseg_count = 0;
+	ctrl_outw(0xffff, PA_LED);
+	ctrl_outw(0x3f3f, PA_7SEG);
+}
+
+void debug_interrupt(void)
+{
+	ctrl_outw(interrupt_count, PA_LED);
+	if (interrupt_count == 0xffff)
+		interrupt_count = 0;
+	else
+		interrupt_count++;
+}
+
+static int sevenseg_data[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
+			  0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};
+
+void set_sevenseg(unsigned char val)
+{
+	unsigned short data;
+
+	data = sevenseg_data[(val & 0xf0) >> 4] << 8;
+	data |= sevenseg_data[val & 0x0f];
+
+	ctrl_outw(data, PA_7SEG);
+}
+
+void debug_sevenseg(void)
+{
+	set_sevenseg(sevenseg_count);
+
+	if (sevenseg_count == 0xff)
+		sevenseg_count = 0;
+	else
+		sevenseg_count++;
+}
diff -urN linux-2.4.21-bk11/arch/sh/kernel/setup_keywest.c linux-2.4.21-bk12/arch/sh/kernel/setup_keywest.c
--- linux-2.4.21-bk11/arch/sh/kernel/setup_keywest.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/setup_keywest.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,215 @@
+/*
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+ * 
+ * Setup and IRQ handling code for the HD64465 companion chip.
+ * by Greg Banks <gbanks@pocketpenguins.com>
+ * Copyright (c) 2000 PocketPenguins Inc
+ *
+ * Derived from setup_hd64465.c which bore the message:
+ * Greg Banks <gbanks@pocketpenguins.com>
+ * Copyright (c) 2000 PocketPenguins Inc and
+ * Copyright (C) 2000 YAEGASHI Takeshi
+ * and setup_cqreek.c which bore message:
+ * Copyright (C) 2000  Niibe Yutaka
+ * 
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Setup and IRQ functions for a Hitachi Big Sur Evaluation Board.
+ * 
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+
+#include <asm/io_keywest.h>
+#include <asm/hd64465.h>
+#include <asm/keywest.h>
+
+//#define KEYWEST_DEBUG 3
+#undef KEYWEST_DEBUG
+
+//LED
+#define ALPHA_LED       0xb1ffe038
+
+#ifdef KEYWEST_DEBUG
+#define DPRINTK(args...)	printk(args)
+#define DIPRINTK(n, args...)	if (KEYWEST_DEBUG>(n)) printk(args)
+#else
+#define DPRINTK(args...)
+#define DIPRINTK(n, args...)
+#endif /* KEYWEST_DEBUG */
+
+#ifdef CONFIG_HD64465
+extern int hd64465_irq_demux(int irq);
+#endif /* CONFIG_HD64465 */
+
+extern void keywest_alpha(int i, char ch);
+
+int keywest_irq_demux(int irq)
+{
+	int demux_irq = irq;
+
+#ifdef CONFIG_HD64465
+	demux_irq = hd64465_irq_demux(demux_irq);
+#endif /* CONFIG_HD64465 */
+
+#ifndef CONFIG_SH_GENERIC
+	demux_irq = ipr_irq_demux(demux_irq);
+#endif
+
+	return demux_irq;
+}
+
+
+void __init init_keywest_IRQ(void)
+{
+	if (!MACH_KEYWEST) return;
+
+}
+
+void keywest_puts(const char* s)
+{
+	int n = 0;
+
+	while (*s)    { keywest_alpha(n++, *s++); }
+	while (n < 8) { keywest_alpha(n++, ' ');  }
+}
+EXPORT_SYMBOL(keywest_puts);
+
+void keywest_printf(const char* fmt, ...)
+{
+	char buffer[32];
+	va_list ap;
+
+	va_start(ap, fmt);
+        vsprintf(buffer, fmt, ap);
+	va_end(ap);
+	keywest_puts(buffer);
+}
+EXPORT_SYMBOL(keywest_printf);
+
+static void tahoe_init(void)
+{
+#ifdef CONFIG_HD64465
+	if (inw(HD64465_REG_SDID) != HD64465_SDID) {
+		printk("Tahoe board is not present.\n");
+
+		return;
+	 }
+
+	printk("Hitachi HD64465 chip support (%d.%d)\n",
+		inw(HD64465_REG_SRR) >> 8, inw(HD64465_REG_SRR) & 0xFF);
+
+	outw(~0, HD64465_REG_NIMR);
+	//outw(0x03, HD64465_REG_SPLLCR);
+#ifdef CONFIG_VT
+	outw(inw(HD64465_REG_SMSCR) & (~HD64465_SMSCR_PS2ST), HD64465_REG_SMSCR); /* PS2   */ 
+	//outw(inw(HD64465_REG_SMSCR) & (~HD64465_SMSCR_KBCST), HD64465_REG_SMSCR); /* keyboard  */ 
+#endif
+#ifdef CONFIG_SERIAL
+	outw(inw(HD64465_REG_SMSCR) & (~HD64465_SMSCR_UARTST), HD64465_REG_SMSCR); /* UART */
+#endif
+#ifdef CONFIG_PARPORT
+	outw(inw(HD64465_REG_SMSCR) & (~HD64465_SMSCR_PPST), HD64465_REG_SMSCR); /* PARPORT */
+#endif
+
+#ifdef CONFIG_PCMCIA
+	outw(inw(HD64465_REG_SMSCR) & (~HD64465_SMSCR_PC0ST), HD64465_REG_SMSCR); /* PC0    */
+	outw(inw(HD64465_REG_SMSCR) & (~HD64465_SMSCR_PC1ST), HD64465_REG_SMSCR); /* PC1    */
+
+	/* turn on PCMCIA area 5 and 6 in BCR1 */
+	* (unsigned short *) 0xffffff60 |= 0x3;
+
+	/* must put both area 5 and 6 into 8 or 16 bit mode in BCR2 */
+	* (unsigned short *) 0xffffff62 &= ~0x3c00;
+	* (unsigned short *) 0xffffff62 |= 0x2800;		/* 16 bit mode */
+
+	/* setup all the PCMCIA dual purpose pins to be PCMCIA pins */
+	* (unsigned short *) 0xa4000108 = 0x0000;   /* port E, all pins */
+	* (unsigned short *) 0xa400010a = 0x0000;   /* port F, all pins */
+	* (unsigned short *) 0xa400010c = 0x0000;   /* port G, all pins */
+
+	/* put the PCMCIA interrupts into edge triggered mode */
+	// BAD * (unsigned short *) 0xb0005004 |= 0x6000;
+
+#endif
+
+	/* 0x3c00*/
+	* (unsigned short *) 0xa400010e &= ~0x3f00; /* port H, pins 4, 5 & 6 */
+
+	printk("Hitachi HD64465 configured at 0x%x on irq %d\n",
+		CONFIG_HD64465_IOBASE, HD64465_IRQ_BASE);
+#endif
+}
+
+static void keywest_init(void)
+{
+	keywest_printf("%s", "Key West");
+#ifdef CONFIG_PCI
+	/*
+	 * make sure these pins are in PCI mode (PINT)
+	 */
+	* (unsigned short *) 0xa4000104 = 0xaaaa;	/* port C, all inputs */
+	* (unsigned short *) 0xa4000108 = 0x0000;   /* port E, all pins */
+	* (unsigned short *) 0xa4000110 = 0x0000;   /* port J, all pins */
+#ifndef CONFIG_PCMCIA
+	* (unsigned short *) 0xffffff62 |= 0x3c00;	/* Area 5/6 in 32 bit mode */
+
+	/* Make sure Area 5 & 6 are in PCI mode */
+	* (unsigned short *) 0xffffff60 &= ~0x3;   /* 5 & 6 as normal memory *
+	* (unsigned short *) 0xffffff60 &= ~0x1e0; /* ordinary memory 5 & 6 */
+#endif
+#endif
+}
+
+int __init setup_keywest(void)
+{
+	static int done = 0; /* run this only once */
+
+	if (!MACH_KEYWEST || done) return 0;
+	done = 1;
+
+	keywest_init();
+	tahoe_init();
+#if defined (CONFIG_HD64465) && defined (CONFIG_SERIAL) 
+	/* remap IO ports for first ISA serial port to HD64465 UART */
+	mach_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1);
+#endif /* CONFIG_HD64465 && CONFIG_SERIAL */
+
+    return 0;
+}
+
+void keywest_alpha(int i, char ch)
+{
+	volatile unsigned char *alpha = (unsigned char *)ALPHA_LED;
+        *(alpha + i) = ch;
+}
+
+#if 0 //keywest board(rev.4) not support status LED
+void keywest_led_on()
+{
+	volatile unsigned char *led = (unsigned char *)STATUS_LED;
+        *led = 0x82;
+}
+
+void keywest_led_off()
+{
+        volatile unsigned char *led = (unsigned char *)STATUS_LED;
+        *led = 0x02;
+}
+#endif
+
+module_init(setup_keywest);
diff -urN linux-2.4.21-bk11/arch/sh/kernel/setup_se.c linux-2.4.21-bk12/arch/sh/kernel/setup_se.c
--- linux-2.4.21-bk11/arch/sh/kernel/setup_se.c	2000-08-09 13:59:04.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/setup_se.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: setup_se.c,v 1.6 2000/05/14 08:41:25 gniibe Exp $
+/* $Id: setup_se.c,v 1.1.1.1.2.2 2002/05/10 17:58:54 jzs Exp $
  *
  * linux/arch/sh/kernel/setup_se.c
  *
@@ -18,6 +18,10 @@
 #include <asm/hitachi_se.h>
 #include <asm/smc37c93x.h>
 
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+#endif
+
 /*
  * Configure the Super I/O chip
  */
@@ -108,6 +112,11 @@
 	make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */
 }
 
+#ifdef CONFIG_SH_KGDB
+static int kgdb_uart_setup(void);
+static struct kgdb_sermap kgdb_uart_sermap = 
+{ "ttyS", 0, kgdb_uart_setup, NULL };
+#endif
 
 /*
  * Initialize the board
@@ -116,4 +125,133 @@
 {
 	init_smsc();
 	/* XXX: RTC setting comes here */
+#ifdef CONFIG_SH_KGDB
+	kgdb_register_sermap(&kgdb_uart_sermap);
+#endif
+}
+
+/*********************************************************************
+ * Currently a hack (e.g. does not interact well w/serial.c, lots of *
+ * hardcoded stuff) but may be useful if SCI/F needs debugging.      *
+ * Mostly copied from x86 code (see files asm-i386/kgdb_local.h and  *
+ * arch/i386/lib/kgdb_serial.c).                                     *
+ *********************************************************************/
+
+#ifdef CONFIG_SH_KGDB
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+
+#define COM1_PORT 0x3f8  /* Base I/O address */
+#define COM1_IRQ  4      /* IRQ not used yet */
+#define COM2_PORT 0x2f8  /* Base I/O address */
+#define COM2_IRQ  3      /* IRQ not used yet */
+
+#define SB_CLOCK 1843200 /* Serial baud clock */
+#define SB_BASE (SB_CLOCK/16)
+#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS
+
+struct uart_port {
+	int base;
+};
+#define UART_NPORTS 2
+struct uart_port uart_ports[] = {
+	{ COM1_PORT },
+	{ COM2_PORT },
+};
+struct uart_port *kgdb_uart_port;
+
+#define UART_IN(reg)	inb_p(kgdb_uart_port->base + reg)
+#define UART_OUT(reg,v)	outb_p((v), kgdb_uart_port->base + reg)
+
+/* Basic read/write functions for the UART */
+#define UART_LSR_RXCERR    (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE)
+static int kgdb_uart_getchar(void)
+{
+	int lsr;
+	int c = -1;
+
+	while (c == -1) {
+		lsr = UART_IN(UART_LSR);
+		if (lsr & UART_LSR_DR) 
+			c = UART_IN(UART_RX);
+		if ((lsr & UART_LSR_RXCERR))
+			c = -1;
+	}
+	return c;
+}
+
+static void kgdb_uart_putchar(int c)
+{
+	while ((UART_IN(UART_LSR) & UART_LSR_THRE) == 0)
+		;
+	UART_OUT(UART_TX, c);
+}
+
+/*
+ * Initialize UART to configured/requested values.
+ * (But we don't interrupts yet, or interact w/serial.c)
+ */
+static int kgdb_uart_setup(void)
+{
+	int port;
+	int lcr = 0;
+	int bdiv = 0;
+
+	if (kgdb_portnum >= UART_NPORTS) {
+		KGDB_PRINTK("uart port %d invalid.\n", kgdb_portnum);
+		return -1;
+	}
+
+	kgdb_uart_port = &uart_ports[kgdb_portnum];
+
+	/* Init sequence from gdb_hook_interrupt */
+	UART_IN(UART_RX);
+	UART_OUT(UART_IER, 0);
+
+	UART_IN(UART_RX);	/* Serial driver comments say */
+	UART_IN(UART_IIR);	/* this clears interrupt regs */
+	UART_IN(UART_MSR);
+
+	/* Figure basic LCR values */
+	switch (kgdb_bits) {
+	case '7':
+		lcr |= UART_LCR_WLEN7;
+		break;
+	default: case '8': 
+		lcr |= UART_LCR_WLEN8;
+		break;
+	}
+	switch (kgdb_parity) {
+	case 'O':
+		lcr |= UART_LCR_PARITY;
+		break;
+	case 'E':
+		lcr |= (UART_LCR_PARITY | UART_LCR_EPAR);
+		break;
+	default: break;
+	}
+
+	/* Figure the baud rate divisor */
+	bdiv = (SB_BASE/kgdb_baud);
+	
+	/* Set the baud rate and LCR values */
+	UART_OUT(UART_LCR, (lcr | UART_LCR_DLAB));
+	UART_OUT(UART_DLL, (bdiv & 0xff));
+	UART_OUT(UART_DLM, ((bdiv >> 8) & 0xff));
+	UART_OUT(UART_LCR, lcr);
+
+	/* Set the MCR */
+	UART_OUT(UART_MCR, SB_MCR);
+
+	/* Turn off FIFOs for now */
+	UART_OUT(UART_FCR, 0);
+
+	/* Setup complete: initialize function pointers */
+	kgdb_getchar = kgdb_uart_getchar;
+	kgdb_putchar = kgdb_uart_putchar;
+
+	return 0;
 }
+#endif /* CONFIG_SH_KGDB */
diff -urN linux-2.4.21-bk11/arch/sh/kernel/setup_snapgear.c linux-2.4.21-bk12/arch/sh/kernel/setup_snapgear.c
--- linux-2.4.21-bk11/arch/sh/kernel/setup_snapgear.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/setup_snapgear.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,187 @@
+/****************************************************************************/
+/* 
+ * linux/arch/sh/kernel/setup_snapgear.c
+ *
+ * Copyright (C) 2002  David McCullough <davidm@snapgear.com>
+ *
+ * Based on files with the following comments:
+ *
+ *           Copyright (C) 2000  Kazumoto Kojima
+ *
+ *           Modified for 7751 Solution Engine by
+ *           Ian da Silva and Jeremy Siegel, 2001.
+ */
+/****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/timer.h>
+#include <linux/ledman.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+
+/****************************************************************************/
+/*
+ * EraseConfig handling functions
+ */
+
+static void
+eraseconfig_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+#if defined(CONFIG_SH_SECUREEDGE5410)
+{
+	volatile char dummy = * (volatile char *) 0xb8000000;
+}
+#endif
+#ifdef CONFIG_LEDMAN
+	ledman_signalreset();
+#else
+	printk("SnapGear: erase switch interrupt!\n");
+#endif
+}
+
+static int __init
+eraseconfig_init(void)
+{
+	printk("SnapGear: EraseConfig init\n");
+	/* Setup "EraseConfig" switch on external IRQ 0 */
+	if (request_irq(IRL0_IRQ, eraseconfig_interrupt, SA_INTERRUPT,
+				"Erase Config", NULL))
+		printk("SnapGear: failed to register IRQ%d for Reset witch\n",
+				IRL0_IRQ);
+	else
+		printk("SnapGear: registered EraseConfig switch on IRQ%d\n",
+				IRL0_IRQ);
+	return(0);
+}
+
+module_init(eraseconfig_init);
+
+/****************************************************************************/
+/*
+ * Initialize IRQ setting
+ *
+ * IRL0 = erase switch
+ * IRL1 = eth0
+ * IRL2 = eth1
+ * IRL3 = crypto
+ */
+
+void __init
+init_snapgear_IRQ(void)
+{
+	/* enable individual interrupt mode for externals */
+	ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+
+	printk("Setup SnapGear IRQ/IPR ...\n");
+
+	make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY);
+	make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY);
+	make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY);
+	make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY);
+}
+
+/****************************************************************************/
+/*
+ *	Fast poll interrupt simulator.
+ */
+
+#define FAST_POLL	1000
+//#define FAST_POLL_INTR
+
+#define FASTTIMER_IRQ   17
+#define FASTTIMER_IPR_ADDR  INTC_IPRA
+#define FASTTIMER_IPR_POS    2
+#define FASTTIMER_PRIORITY   3
+
+#ifdef FAST_POLL_INTR
+#define TMU1_TCR_INIT	0x0020
+#else
+#define TMU1_TCR_INIT	0
+#endif
+#define TMU_TSTR_INIT	1
+#define TMU1_TCR_CALIB	0x0000
+#define TMU_TOCR	0xffd80000	/* Byte access */
+#define TMU_TSTR	0xffd80004	/* Byte access */
+#define TMU1_TCOR	0xffd80014	/* Long access */
+#define TMU1_TCNT	0xffd80018	/* Long access */
+#define TMU1_TCR	0xffd8001c	/* Word access */
+
+
+#ifdef FAST_POLL_INTR
+static void fast_timer_irq(int irq, void *dev_instance, struct pt_regs *regs)
+{
+	unsigned long timer_status;
+    timer_status = ctrl_inw(TMU1_TCR);
+	timer_status &= ~0x100;
+	ctrl_outw(timer_status, TMU1_TCR);
+}
+#endif
+
+/*
+ * return the current ticks on the fast timer
+ */
+
+unsigned long
+fast_timer_count(void)
+{
+	return(ctrl_inl(TMU1_TCNT));
+}
+
+/*
+ * setup a fast timer for profiling etc etc
+ */
+
+static void
+setup_fast_timer()
+{
+	unsigned long interval;
+
+#ifdef FAST_POLL_INTR
+	interval = (current_cpu_data.module_clock/4 + FAST_POLL/2) / FAST_POLL;
+
+	make_ipr_irq(FASTTIMER_IRQ, FASTTIMER_IPR_ADDR, FASTTIMER_IPR_POS,
+			FASTTIMER_PRIORITY);
+
+	printk("SnapGear: %dHz fast timer on IRQ %d\n",FAST_POLL,FASTTIMER_IRQ);
+
+	if (request_irq(FASTTIMER_IRQ, fast_timer_irq, 0, "SnapGear fast timer",
+			NULL) != 0)
+		printk("%s(%d): request_irq() failed?\n", __FILE__, __LINE__);
+#else
+	printk("SnapGear: fast timer running\n",FAST_POLL,FASTTIMER_IRQ);
+	interval = 0xffffffff;
+#endif
+
+	ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x2, TMU_TSTR); /* disable timer 1 */
+	ctrl_outw(TMU1_TCR_INIT, TMU1_TCR);
+	ctrl_outl(interval, TMU1_TCOR);
+	ctrl_outl(interval, TMU1_TCNT);
+	ctrl_outb(ctrl_inb(TMU_TSTR) | 0x2, TMU_TSTR); /* enable timer 1 */
+
+	printk("Timer count 1 = 0x%x\n", fast_timer_count());
+	udelay(1000);
+	printk("Timer count 2 = 0x%x\n", fast_timer_count());
+}
+
+/****************************************************************************/
+/*
+ * Initialize the board
+ */
+
+void __init
+setup_snapgear(void)
+{
+	/* XXX: RTC setting comes here */
+#ifdef CONFIG_RTC
+	secureedge5410_rtc_init();
+#endif
+ 	// setup_fast_timer();
+}
+
+/****************************************************************************/
diff -urN linux-2.4.21-bk11/arch/sh/kernel/sh_ksyms.c linux-2.4.21-bk12/arch/sh/kernel/sh_ksyms.c
--- linux-2.4.21-bk11/arch/sh/kernel/sh_ksyms.c	2002-02-25 11:37:56.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/sh_ksyms.c	2003-07-17 02:52:28.000000000 -0700
@@ -56,6 +56,7 @@
 #endif
 
 /* mem exports */
+EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(memchr);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memcpy_fromio);
@@ -64,6 +65,7 @@
 EXPORT_SYMBOL(memset_io);
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(__copy_user);
 
 #ifdef CONFIG_VT
 EXPORT_SYMBOL(screen_info);
@@ -77,6 +79,7 @@
 EXPORT_SYMBOL(__up);
 EXPORT_SYMBOL(__down);
 EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down_trylock);
 
 EXPORT_SYMBOL(__udelay);
 EXPORT_SYMBOL(__const_udelay);
diff -urN linux-2.4.21-bk11/arch/sh/kernel/signal.c linux-2.4.21-bk12/arch/sh/kernel/signal.c
--- linux-2.4.21-bk11/arch/sh/kernel/signal.c	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/signal.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.21 2000/03/11 14:06:21 gniibe Exp $
+/* $Id: signal.c,v 1.1.1.1.2.11 2002/10/23 00:57:46 mrbrown Exp $
  *
  *  linux/arch/sh/kernel/signal.c
  *
@@ -30,7 +30,8 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
+asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset,
+			 int from_syscall, unsigned long orig_r0);
 
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
 {
@@ -88,7 +89,7 @@
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(&regs, &saveset))
+		if (do_signal(&regs, &saveset, 0, 0))
 			return -EINTR;
 	}
 }
@@ -117,7 +118,7 @@
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(&regs, &saveset))
+		if (do_signal(&regs, &saveset, 0, 0))
 			return -EINTR;
 	}
 }
@@ -167,20 +168,21 @@
  * Do a signal return; undo the signal stack.
  */
 
+#define MOVW(n)	(0x9300|((n)-2))	/* Move mem word at PC+n to R3 */
+#define TRAP16	0xc310			/* Syscall w/no args (NR in R3) */
+
 struct sigframe
 {
 	struct sigcontext sc;
 	unsigned long extramask[_NSIG_WORDS-1];
-	char retcode[4];
+	u16 retcode[3];
 };
 
 struct rt_sigframe
 {
-	struct siginfo *pinfo;
-	void *puc;
 	struct siginfo info;
 	struct ucontext uc;
-	char retcode[4];
+	u16 retcode[3];
 };
 
 #if defined(__SH4__)
@@ -196,39 +198,32 @@
 static inline int save_sigcontext_fpu(struct sigcontext *sc)
 {
 	struct task_struct *tsk = current;
-	unsigned long flags;
-	int val;
 
 	if (!tsk->used_math) {
-	  val = 0;
-		__copy_to_user(&sc->sc_ownedfp, &val, sizeof(int));
+		__put_user(0, &sc->sc_ownedfp);
 		return 0;
 	}
 
-	val = 1;
-	__copy_to_user(&sc->sc_ownedfp, &val, sizeof(int));
+	__put_user(1, &sc->sc_ownedfp);
 
 	/* This will cause a "finit" to be triggered by the next
 	   attempted FPU operation by the 'current' process.
 	   */
 	tsk->used_math = 0;
 
-	save_and_cli(flags);
 	unlazy_fpu(tsk);
-	restore_flags(flags);
-
 	return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard,
 			      sizeof(long)*(16*2+2));
 }
 #endif
 
 static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *r0_p)
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
 {
 	unsigned int err = 0;
 
 #define COPY(x)		err |= __get_user(regs->x, &sc->sc_##x)
-			COPY(regs[1]);
+	COPY(regs[0]);	COPY(regs[1]);
 	COPY(regs[2]);	COPY(regs[3]);
 	COPY(regs[4]);	COPY(regs[5]);
 	COPY(regs[6]);	COPY(regs[7]);
@@ -254,19 +249,16 @@
 			err |= restore_sigcontext_fpu(sc);
 	}
 #endif
-
-	regs->syscall_nr = -1;		/* disable syscall checks */
-	err |= __get_user(*r0_p, &sc->sc_regs[0]);
 	return err;
 }
 
+
 asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
 			     unsigned long r6, unsigned long r7,
 			     struct pt_regs regs)
 {
 	struct sigframe *frame = (struct sigframe *)regs.regs[15];
 	sigset_t set;
-	int r0;
 
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
@@ -284,9 +276,9 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 
-	if (restore_sigcontext(&regs, &frame->sc, &r0))
+	if (restore_sigcontext(&regs, &frame->sc))
 		goto badframe;
-	return r0;
+	return regs.regs[0];
 
 badframe:
 	force_sig(SIGSEGV, current);
@@ -300,7 +292,6 @@
 	struct rt_sigframe *frame = (struct rt_sigframe *)regs.regs[15];
 	sigset_t set;
 	stack_t st;
-	int r0;
 
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
@@ -314,7 +305,7 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 
-	if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &r0))
+	if (restore_sigcontext(&regs, &frame->uc.uc_mcontext))
 		goto badframe;
 
 	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
@@ -322,13 +313,12 @@
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
 	do_sigaltstack(&st, NULL, regs.regs[15]);
-
-	return r0;
+	return regs.regs[0];
 
 badframe:
 	force_sig(SIGSEGV, current);
 	return 0;
-}	
+}
 
 /*
  * Set up a signal frame.
@@ -406,15 +396,11 @@
 	if (ka->sa.sa_flags & SA_RESTORER) {
 		regs->pr = (unsigned long) ka->sa.sa_restorer;
 	} else {
-		/* This is : mov  #__NR_sigreturn,r3 ; trapa #0x10 */
-#ifdef __LITTLE_ENDIAN__
-		unsigned long code = 0xc310e300 | (__NR_sigreturn);
-#else
-		unsigned long code = 0xe300c310 | (__NR_sigreturn << 16);
-#endif
-
+		/* Generate return code (system call to sigreturn) */
+		err |= __put_user(MOVW(2), &frame->retcode[0]);
+		err |= __put_user(TRAP16, &frame->retcode[1]);
+		err |= __put_user((__NR_sigreturn), &frame->retcode[2]);
 		regs->pr = (unsigned long) frame->retcode;
-		err |= __put_user(code, (long *)(frame->retcode+0));
 	}
 
 	if (err)
@@ -459,8 +445,6 @@
 		? current->exec_domain->signal_invmap[sig]
 		: sig;
 
-	err |= __put_user(&frame->info, &frame->pinfo);
-	err |= __put_user(&frame->uc, &frame->puc);
 	err |= copy_siginfo_to_user(&frame->info, info);
 
 	/* Create the ucontext.  */
@@ -480,24 +464,22 @@
 	if (ka->sa.sa_flags & SA_RESTORER) {
 		regs->pr = (unsigned long) ka->sa.sa_restorer;
 	} else {
-		/* This is : mov  #__NR_rt_sigreturn,r3 ; trapa #0x10 */
-#ifdef __LITTLE_ENDIAN__
-		unsigned long code = 0xc310e300 | (__NR_rt_sigreturn);
-#else
-		unsigned long code = 0xe300c310 | (__NR_rt_sigreturn << 16);
-#endif
-
+		/* Generate return code (system call to rt_sigreturn) */
+		err |= __put_user(MOVW(2), &frame->retcode[0]);
+		err |= __put_user(TRAP16, &frame->retcode[1]);
+		err |= __put_user((__NR_rt_sigreturn), &frame->retcode[2]);
 		regs->pr = (unsigned long) frame->retcode;
-		err |= __put_user(code, (long *)(frame->retcode+0));
 	}
 
 	if (err)
 		goto give_sigsegv;
 
-	/* Set up registers for signal handler */
-	regs->regs[15] = (unsigned long) frame;
-	regs->regs[4] = signal; /* Arg for signal handler */
-	regs->pc = (unsigned long) ka->sa.sa_handler;
+	/* Set up registers (SP, PC, and args) for signal handler */
+	regs->regs[15] = (unsigned long) frame;		/* Stack pointer */
+	regs->regs[4] = signal;				/* Arg1 (signal) */
+	regs->regs[5] = (unsigned long)&frame->info;	/* Arg2 (siginfo) */
+	regs->regs[6] = (unsigned long)&frame->uc;	/* Arg3 (context) */
+	regs->pc = (unsigned long) ka->sa.sa_handler;	/* Program counter */
 
 	set_fs(USER_DS);
 
@@ -521,10 +503,11 @@
 
 static void
 handle_signal(unsigned long sig, struct k_sigaction *ka,
-	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+	      siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, 
+	      int from_syscall, unsigned long orig_r0)
 {
 	/* Are we from a system call? */
-	if (regs->syscall_nr >= 0) {
+	if (from_syscall) {
 		/* If so, check system call restarting.. */
 		switch (regs->regs[0]) {
 			case -ERESTARTNOHAND:
@@ -538,9 +521,20 @@
 				}
 			/* fallthrough */
 			case -ERESTARTNOINTR:
-				regs->regs[0] = regs->syscall_nr;
+				regs->regs[0] = orig_r0;
 				regs->pc -= 2;
 		}
+	} else {
+		/* gUSA handling */
+		if (regs->regs[15] >= 0xc0000000) {
+			int offset = (int)regs->regs[15];
+
+			/* Reset stack pointer: clear critical region mark */
+			regs->regs[15] = regs->regs[1];
+			if (regs->pc < regs->regs[0])
+				/* Go to rewind point #1 */
+				regs->pc = regs->regs[0] + offset - 2;
+		}
 	}
 
 	/* Set up the stack frame */
@@ -570,7 +564,8 @@
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+int do_signal(struct pt_regs *regs, sigset_t *oldset,
+	      int from_syscall, unsigned long orig_r0)
 {
 	siginfo_t info;
 	struct k_sigaction *ka;
@@ -677,17 +672,18 @@
 		}
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, ka, &info, oldset, regs);
+		handle_signal(signr, ka, &info, oldset, regs,
+			      from_syscall, orig_r0);
 		return 1;
 	}
 
 	/* Did we come from a system call? */
-	if (regs->syscall_nr >= 0) {
+	if (from_syscall) {
 		/* Restart the system call - no handlers present */
 		if (regs->regs[0] == -ERESTARTNOHAND ||
 		    regs->regs[0] == -ERESTARTSYS ||
 		    regs->regs[0] == -ERESTARTNOINTR) {
-			regs->regs[0] = regs->syscall_nr;
+			regs->regs[0] = orig_r0;
 			regs->pc -= 2;
 		}
 	}
diff -urN linux-2.4.21-bk11/arch/sh/kernel/sys_sh.c linux-2.4.21-bk12/arch/sh/kernel/sys_sh.c
--- linux-2.4.21-bk11/arch/sh/kernel/sys_sh.c	2001-10-15 13:36:48.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/sys_sh.c	2003-07-17 02:52:28.000000000 -0700
@@ -23,6 +23,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
+#include <asm/cachectl.h>
 
 /*
  * sys_pipe() is the normal C calling standard for creating
@@ -221,15 +222,41 @@
 	return -EINVAL;
 }
 
-asmlinkage int sys_uname(struct old_utsname * name)
+/* sys_cacheflush -- flush (part of) the processor cache.  */
+asmlinkage int
+sys_cacheflush (unsigned long addr, unsigned long len, int op)
 {
-	int err;
-	if (!name)
+	struct vm_area_struct *vma;
+
+	if ((op < 0) || (op > (CACHEFLUSH_D_PURGE|CACHEFLUSH_I)))
+		return -EINVAL;
+
+	/*
+	 * Verify that the specified address region actually belongs
+	 * to this process.
+	 */
+	if (addr + len < addr)
 		return -EFAULT;
-	down_read(&uts_sem);
-	err=copy_to_user(name, &system_utsname, sizeof (*name));
-	up_read(&uts_sem);
-	return err?-EFAULT:0;
+	vma = find_vma (current->mm, addr);
+	if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
+		return -EFAULT;
+
+	switch (op & CACHEFLUSH_D_PURGE) {
+		case CACHEFLUSH_D_INVAL:
+			__flush_invalidate_region(addr, len);
+			break;
+		case CACHEFLUSH_D_WB:
+			__flush_wback_region(addr, len);
+			break;
+		case CACHEFLUSH_D_PURGE:
+			__flush_purge_region(addr, len);
+			break;
+	}
+	if (op & CACHEFLUSH_I) {
+		__flush_icache_all();
+	}
+
+	return 0;
 }
 
 asmlinkage int sys_pause(void)
@@ -238,3 +265,19 @@
 	schedule();
 	return -ERESTARTNOHAND;
 }
+
+asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char * buf,
+			     size_t count, long dummy, loff_t pos)
+{
+	extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
+					size_t count, loff_t pos);
+	return sys_pread(fd, buf, count, pos);
+}
+
+asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char * buf,
+			      size_t count, long dummy, loff_t pos)
+{
+	extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
+					size_t count, loff_t pos);
+	return sys_pwrite(fd, buf, count, pos);
+}
diff -urN linux-2.4.21-bk11/arch/sh/kernel/time.c linux-2.4.21-bk12/arch/sh/kernel/time.c
--- linux-2.4.21-bk11/arch/sh/kernel/time.c	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/kernel/time.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.30 2001/09/01 14:34:31 mrbrown Exp $
+/* $Id: time.c,v 1.1.1.1.2.5 2003/06/20 13:13:25 trent Exp $
  *
  *  linux/arch/sh/kernel/time.c
  *
@@ -29,15 +29,21 @@
 #include <asm/delay.h>
 #include <asm/machvec.h>
 #include <asm/rtc.h>
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+#endif
 
 #include <linux/timex.h>
 #include <linux/irq.h>
 
-#define TMU_TOCR_INIT	0x00
-#define TMU0_TCR_INIT	0x0020
-#define TMU_TSTR_INIT	1
+#define TMU_TOCR_INIT	0x00	/* Don't output RTC clock */
+
+#define TMU0_TCR_INIT	0x0020	/* Clock/4, rising edge; interrupt on */
+#define TMU0_TCR_CALIB	0x0000	/* Clock/4, rising edge; no interrupt */
+#define TMU0_TSTR_INIT	0x01	/* Bit to turn on TMU0 */
 
-#define TMU0_TCR_CALIB	0x0000
+#define TMU1_TCR_INIT	0x0000	/* Clock/4, rising edge; no interrupt */
+#define TMU1_TSTR_INIT  0x02	/* Bit to turn on TMU1 */
 
 #if defined(__sh3__)
 #define TMU_TOCR	0xfffffe90	/* Byte access */
@@ -47,6 +53,10 @@
 #define TMU0_TCNT	0xfffffe98	/* Long access */
 #define TMU0_TCR	0xfffffe9c	/* Word access */
 
+#define TMU1_TCOR	0xfffffea0	/* Long access */
+#define TMU1_TCNT	0xfffffea4	/* Long access */
+#define TMU1_TCR	0xfffffea8	/* Word access */
+
 #define FRQCR		0xffffff80
 #elif defined(__SH4__)
 #define TMU_TOCR	0xffd80000	/* Byte access */
@@ -56,6 +66,10 @@
 #define TMU0_TCNT	0xffd8000c	/* Long access */
 #define TMU0_TCR	0xffd80010	/* Word access */
 
+#define TMU1_TCOR	0xffd80014	/* Long access */
+#define TMU1_TCNT	0xffd80018	/* Long access */
+#define TMU1_TCR	0xffd8001c	/* Word access */
+
 #define FRQCR		0xffc00000
 
 /* Core Processor Version Register */
@@ -64,10 +78,10 @@
 #define CCN_PVR_CHIP_MASK  0xff
 #define CCN_PVR_CHIP_ST40STB1 0x4
 
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
 #define CLOCKGEN_MEMCLKCR 0xbb040038
 #define MEMCLKCR_RATIO_MASK 0x7
-#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */
+#endif /* CONFIG_CPU_SUBTYPE_ST40 */
 #endif /* __sh3__ or __SH4__ */
 
 extern rwlock_t xtime_lock;
@@ -176,6 +190,27 @@
 /* last time the RTC clock got updated */
 static long last_rtc_update;
 
+static __inline__ void sh_do_profile (unsigned long pc)
+{
+	extern int _stext;
+
+	if (!prof_buffer)
+		return;
+
+	if(pc >= 0xa0000000UL && pc < 0xc0000000UL)
+		pc -= 0x20000000;
+	pc -= (unsigned long) &_stext;
+	pc >>= prof_shift;
+	/*
+	 * Don't ignore out-of-bounds PC values silently,
+	 * put them into the last histogram slot, so if
+	 * present, they will show up as a sharp peak.
+	 */
+	if (pc > prof_len-1)
+		pc = prof_len-1;
+	prof_buffer[pc]++;
+}
+
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -257,7 +292,7 @@
 	} while (tv1.tv_usec == tv2.tv_usec && tv1.tv_sec == tv2.tv_sec);
 
 	/* actually start the timer */
-	ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+	ctrl_outb(TMU0_TSTR_INIT, TMU_TSTR);
 
 	do {
 		rtc_gettimeofday(&tv2);
@@ -288,7 +323,7 @@
 void __init time_init(void)
 {
 	unsigned int cpu_clock, master_clock, bus_clock, module_clock;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
 	unsigned int memory_clock;
 #endif
 	unsigned int timer_freq;
@@ -303,7 +338,7 @@
 #define bfc_table ifc_table	/* Same */
 	static int pfc_table[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
 
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
 	struct frqcr_data {
 		unsigned short frqcr;
 		struct {
@@ -384,7 +419,7 @@
 	}
 #elif defined(__SH4__)
 	{
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
 		unsigned long pvr;
 
 		/* This should probably be moved into the SH3 probing code, and then use the processor
@@ -438,14 +473,14 @@
 	master_clock = module_clock * pfc;
 	bus_clock = master_clock / bfc;
 	cpu_clock = master_clock / ifc;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
  skip_calc:
 #endif
 	printk("CPU clock: %d.%02dMHz\n",
 	       (cpu_clock / 1000000), (cpu_clock % 1000000)/10000);
 	printk("Bus clock: %d.%02dMHz\n",
 	       (bus_clock/1000000), (bus_clock % 1000000)/10000);
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
 	printk("Memory clock: %d.%02dMHz\n",
 	       (memory_clock/1000000), (memory_clock % 1000000)/10000);
 #endif
@@ -458,16 +493,35 @@
 	current_cpu_data.cpu_clock    = cpu_clock;
 	current_cpu_data.master_clock = master_clock;
 	current_cpu_data.bus_clock    = bus_clock;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
 	current_cpu_data.memory_clock = memory_clock;
 #endif
 	current_cpu_data.module_clock = module_clock;
 
-	/* Start TMU0 */
+	/* Stop all timers */
 	ctrl_outb(0, TMU_TSTR);
 	ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
+
+	/* Start TMU0 (jiffy interrupts) */
 	ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
 	ctrl_outl(interval, TMU0_TCOR);
 	ctrl_outl(interval, TMU0_TCNT);
-	ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+	ctrl_outb(TMU0_TSTR_INIT, TMU_TSTR);
+
+#if defined(CONFIG_START_TMU1)
+	/* Start TMU1 (free-running) */
+	ctrl_outw(TMU1_TCR_INIT, TMU1_TCR);
+	ctrl_outl(0xffffffff, TMU1_TCOR);
+	ctrl_outl(0xffffffff, TMU1_TCNT);
+	ctrl_outb((ctrl_inb(TMU_TSTR) | TMU1_TSTR_INIT), TMU_TSTR);
+#endif
+
+#if defined(CONFIG_SH_KGDB)
+	/*
+	 * Set up kgdb as requested. We do it here because the serial
+	 * init uses the timer vars we just set up for figuring baud.
+	 */
+        kgdb_init();
+#endif
+
 }
diff -urN linux-2.4.21-bk11/arch/sh/kernel/traps.c linux-2.4.21-bk12/arch/sh/kernel/traps.c
--- linux-2.4.21-bk11/arch/sh/kernel/traps.c	2002-02-25 11:37:56.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/traps.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,10 +1,11 @@
-/* $Id: traps.c,v 1.14 2001/07/24 08:07:10 gniibe Exp $
+/* $Id: traps.c,v 1.1.1.1.2.4 2002/05/10 17:58:54 jzs Exp $
  *
  *  linux/arch/sh/traps.c
  *
  *  SuperH version: Copyright (C) 1999 Niibe Yutaka
  *                  Copyright (C) 2000 Philipp Rumpf
  *                  Copyright (C) 2000 David Howells
+ *                  Copyright (C) 2002 Paul Mundt
  */
 
 /*
@@ -31,6 +32,19 @@
 #include <asm/atomic.h>
 #include <asm/processor.h>
 
+#ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
+#define CHK_REMOTE_DEBUG(regs)                                               \
+{                                                                            \
+  if ((kgdb_debug_hook != (kgdb_debug_hook_t *) NULL) && (!user_mode(regs))) \
+  {                                                                          \
+    (*kgdb_debug_hook)(regs);                                                \
+  }                                                                          \
+}
+#else
+#define CHK_REMOTE_DEBUG(regs)
+#endif
+
 #define DO_ERROR(trapnr, signr, str, name, tsk) \
 asmlinkage void do_##name(unsigned long r4, unsigned long r5, \
 			  unsigned long r6, unsigned long r7, \
@@ -42,6 +56,7 @@
 	sti(); \
 	tsk->thread.error_code = error_code; \
 	tsk->thread.trap_no = trapnr; \
+        CHK_REMOTE_DEBUG(&regs); \
 	force_sig(signr, tsk); \
 	die_if_no_fixup(str,&regs,error_code); \
 }
@@ -61,6 +76,7 @@
 	console_verbose();
 	spin_lock_irq(&die_lock);
 	printk("%s: %04lx\n", str, err & 0xffff);
+	CHK_REMOTE_DEBUG(regs);
 	show_regs(regs);
 	spin_unlock_irq(&die_lock);
 	do_exit(SIGSEGV);
@@ -300,10 +316,19 @@
 /*
  * handle an instruction that does an unaligned memory access
  * - have to be careful of branch delay-slot instructions that fault
+ *  SH3:
  *   - if the branch would be taken PC points to the branch
  *   - if the branch would not be taken, PC points to delay-slot
+ *  SH4:
+ *   - PC always points to delayed branch
  * - return 0 if handled, -EFAULT if failed (may not return if in kernel)
  */
+
+/* Macros to determine offset from current PC for branch instructions */
+/* Explicit type coercion is used to force sign extension where needed */
+#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4)
+#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4)
+
 static int handle_unaligned_access(u16 instruction, struct pt_regs *regs)
 {
 	u_int rm;
@@ -392,15 +417,27 @@
 			break;
 		case 0x0F00: /* bf/s lab */
 			ret = handle_unaligned_delayslot(regs);
-			if (ret==0)
-				regs->pc += (instruction&0x00FF)*2 + 4;
+			if (ret==0) {
+#if defined(__SH4__)
+				if ((regs->sr & 0x00000001) != 0)
+					regs->pc += 4; /* next after slot */
+				else
+#endif
+					regs->pc += SH_PC_8BIT_OFFSET(instruction);
+			}
 			break;
 		case 0x0900: /* bt   lab - no delayslot */
 			break;
 		case 0x0D00: /* bt/s lab */
 			ret = handle_unaligned_delayslot(regs);
-			if (ret==0)
-				regs->pc += (instruction&0x00FF)*2 + 4;
+			if (ret==0) {
+#if defined(__SH4__)
+				if ((regs->sr & 0x00000001) == 0)
+					regs->pc += 4; /* next after slot */
+				else
+#endif
+					regs->pc += SH_PC_8BIT_OFFSET(instruction);
+			}
 			break;
 		}
 		break;
@@ -408,14 +445,14 @@
 	case 0xA000: /* bra label */
 		ret = handle_unaligned_delayslot(regs);
 		if (ret==0)
-			regs->pc += (instruction&0x0FFF)*2 + 4;
+			regs->pc += SH_PC_12BIT_OFFSET(instruction);
 		break;
 
 	case 0xB000: /* bsr label */
 		ret = handle_unaligned_delayslot(regs);
 		if (ret==0) {
 			regs->pr = regs->pc + 4;
-			regs->pc += (instruction&0x0FFF)*2 + 4;
+			regs->pc += SH_PC_12BIT_OFFSET(instruction);
 		}
 		break;
 	}
@@ -539,29 +576,51 @@
 		     : "memory");
 }
 
-void dump_stack(void)
+void show_task(unsigned long *sp)
 {
-	unsigned long *start;
-	unsigned long *end;
-	unsigned long *p;
-
-	asm("mov	r15, %0" : "=r" (start));
-	asm("stc	r7_bank, %0" : "=r" (end));
-	end += 8192/4;
-
-	printk("%08lx:%08lx\n", (unsigned long)start, (unsigned long)end);
-	for (p=start; p < end; p++) {
-		extern long _text, _etext;
-		unsigned long v=*p;
-
-		if ((v >= (unsigned long )&_text)
-		    && (v <= (unsigned long )&_etext)) {
-			printk("%08lx\n", v);
+	unsigned long *stack, addr;
+	unsigned long module_start = VMALLOC_START;
+	unsigned long module_end = VMALLOC_END;
+	extern long _text, _etext;
+	int i = 1;
+
+	if (!sp) {
+		__asm__ __volatile__ (
+			"mov r15, %0\n\t"
+			"stc r7_bank, %1\n\t"
+			: "=r" (module_start),
+			  "=r" (module_end)
+		);
+		
+		sp = (unsigned long *)module_start;
+	}
+
+	stack = sp;
+
+	printk("\nCall trace: ");
+
+	while (((long)stack & (THREAD_SIZE - 1))) {
+		if (__get_user(addr, stack)) {
+			printk("Failing address 0x%lx\n", *stack);
+			break;
+		}
+		stack++;
+
+		if (((addr >= (unsigned long)&_text) &&
+		     (addr <= (unsigned long)&_etext)) ||
+		    ((addr >= module_start) && (addr <= module_end))) {
+			if (i && ((i % 8) == 0))
+				printk("\n       ");
+
+			printk("[<%08lx>] ", addr);
+			i++;
 		}
 	}
+
+	printk("\n");
 }
 
 void show_trace_task(struct task_struct *tsk)
 {
-	printk("Backtrace not yet implemented for SH.\n");
+	show_task((unsigned long *)tsk->thread.sp);
 }
diff -urN linux-2.4.21-bk11/arch/sh/kernel/ubc.S linux-2.4.21-bk12/arch/sh/kernel/ubc.S
--- linux-2.4.21-bk11/arch/sh/kernel/ubc.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/kernel/ubc.S	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,59 @@
+/*
+ * arch/sh/kernel/ubc.S
+ *
+ * Set of management routines for the User Break Controller (UBC)
+ *
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * 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.
+ */
+#include <linux/linkage.h>
+#include <asm/ubc.h>
+
+#define STBCR2		0xffc00010
+
+ENTRY(ubc_sleep)
+	mov	#0, r0
+
+	mov.l	1f, r1		! Zero out UBC_BBRA ..
+	mov.w	r0, @r1
+
+	mov.l	2f, r1		! .. same for BBRB ..
+	mov.w	r0, @r1
+
+	mov.l	3f, r1		! .. and again for BRCR.
+	mov.w	r0, @r1
+
+	mov.w	@r1, r0		! Dummy read BRCR
+
+	mov.l	4f, r1		! Set MSTP5 in STBCR2
+	mov.b	@r1, r0
+	or	#0x01, r0
+	mov.b	r0, @r1
+
+	mov.b	@r1, r0		! Two dummy reads ..
+	mov.b	@r1, r0
+
+	rts
+	nop
+
+ENTRY(ubc_wakeup)
+	mov.l	4f, r1		! Clear MSTP5
+	mov.b	@r1, r0
+	and	#0xfe, r0
+	mov.b	r0, @r1
+
+	mov.b	@r1, r0		! Two more dummy reads ..
+	mov.b	@r1, r0
+
+	rts
+	nop
+
+1:	.long	UBC_BBRA
+2:	.long	UBC_BBRB
+3:	.long	UBC_BRCR
+4:	.long	STBCR2
+
diff -urN linux-2.4.21-bk11/arch/sh/lib/delay.c linux-2.4.21-bk12/arch/sh/lib/delay.c
--- linux-2.4.21-bk11/arch/sh/lib/delay.c	2001-01-28 18:56:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/lib/delay.c	2003-07-17 02:52:28.000000000 -0700
@@ -33,3 +33,8 @@
 {
 	__const_udelay(usecs * 0x000010c6);  /* 2**32 / 1000000 */
 }
+
+void __ndelay(unsigned long nsecs)
+{
+	__const_udelay(nsecs * 5);  /* 2**32 / 1000000000 (rounded up) */
+}
diff -urN linux-2.4.21-bk11/arch/sh/mm/Makefile linux-2.4.21-bk12/arch/sh/mm/Makefile
--- linux-2.4.21-bk11/arch/sh/mm/Makefile	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/mm/Makefile	2003-07-17 02:52:28.000000000 -0700
@@ -10,8 +10,9 @@
 O_TARGET := mm.o
 obj-y	 := init.o fault.o extable.o clear_page.o copy_page.o
 
+obj-$(CONFIG_PCI_SD0001) += ioremap.o
 obj-$(CONFIG_CPU_SH3) += cache-sh3.o
-obj-$(CONFIG_CPU_SH4) += cache-sh4.o __clear_user_page-sh4.o __copy_user_page-sh4.o ioremap.o
+obj-$(CONFIG_CPU_SH4) += cache-sh4.o ioremap.o
 
 USE_STANDARD_AS_RULE := true
 
diff -urN linux-2.4.21-bk11/arch/sh/mm/cache-sh4.c linux-2.4.21-bk12/arch/sh/mm/cache-sh4.c
--- linux-2.4.21-bk11/arch/sh/mm/cache-sh4.c	2001-10-15 13:36:48.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/mm/cache-sh4.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,9 +1,8 @@
-/* $Id: cache-sh4.c,v 1.16 2001/09/10 11:06:35 dwmw2 Exp $
+/* $Id: cache-sh4.c,v 1.1.1.1.2.8 2003/07/09 09:59:30 trent Exp $
  *
- *  linux/arch/sh/mm/cache.c
- *
- * Copyright (C) 1999, 2000  Niibe Yutaka
+ *  linux/arch/sh/mm/cache-sh4.c
  *
+ * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
  */
 
 #include <linux/config.h>
@@ -42,6 +41,7 @@
 #define CACHE_OC_ADDRESS_ARRAY 0xf4000000
 #define CACHE_VALID	  1
 #define CACHE_UPDATED	  2
+#define CACHE_ASSOC	  8
 
 #define CACHE_OC_WAY_SHIFT       13
 #define CACHE_IC_WAY_SHIFT       13
@@ -56,8 +56,8 @@
 static void __init
 detect_cpu_and_cache_system(void)
 {
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
-	cpu_data->type = CPU_ST40STB1;
+#ifdef CONFIG_CPU_SUBTYPE_ST40
+	cpu_data->type = CPU_ST40;
 #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
 	cpu_data->type = CPU_SH7750;
 #else
@@ -109,7 +109,7 @@
 				    unsigned long size, unsigned long flags);
 
 	if (remap_area_pages(P3SEG, 0, PAGE_SIZE*4, _PAGE_CACHABLE))
-		panic("p3_cachie_init failed.");
+		panic("%s failed.", __FUNCTION__);
 	sema_init (&p3map_sem[0], 1);
 	sema_init (&p3map_sem[1], 1);
 	sema_init (&p3map_sem[2], 1);
@@ -177,6 +177,17 @@
 	}
 }
 
+void __flush_icache_all(void)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	jump_to_P2();
+	ctrl_outl(CCR_CACHE_VAL|CCR_CACHE_ICI, CCR);
+	back_to_P1();
+	restore_flags(flags);
+}
+
 /*
  * Write back the range of D-cache, and purge the I-cache.
  *
@@ -208,44 +219,26 @@
 	restore_flags(flags);
 }
 
-/*
- * Writeback&Invalidate the D-cache of the page
- */
-static void __flush_dcache_page(unsigned long phys)
+static inline void flush_cache_4096(unsigned long start,
+				    unsigned long phys)
 {
-	unsigned long addr, data;
-	unsigned long flags;
-
-	phys |= CACHE_VALID;
-
-	save_and_cli(flags);
-	jump_to_P2();
-
-	/* Loop all the D-cache */
-	for (addr = CACHE_OC_ADDRESS_ARRAY;
-	     addr < (CACHE_OC_ADDRESS_ARRAY
-		     +(CACHE_OC_NUM_ENTRIES<< CACHE_OC_ENTRY_SHIFT));
-	     addr += (1<<CACHE_OC_ENTRY_SHIFT)) {
-		data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID);
-		if (data == phys)
-			ctrl_outl(0, addr);
-	}
+	unsigned long flags; 
+	extern void __flush_cache_4096(unsigned long addr, unsigned long phys, unsigned long exec_offset);
 
-#if 0 /* DEBUG DEBUG */
-	/* Loop all the I-cache */
-	for (addr = CACHE_IC_ADDRESS_ARRAY;
-	     addr < (CACHE_IC_ADDRESS_ARRAY
-		     +(CACHE_IC_NUM_ENTRIES<< CACHE_IC_ENTRY_SHIFT));
-	     addr += (1<<CACHE_IC_ENTRY_SHIFT)) {
-		data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID);
-		if (data == phys) {
-			printk(KERN_INFO "__flush_cache_page: I-cache entry found\n");
-			ctrl_outl(0, addr);
-		}
-	}
+#if defined(CONFIG_CPU_SUBTYPE_SH7751) || defined(CONFIG_CPU_SUBTYPE_ST40)
+	if (start >= CACHE_OC_ADDRESS_ARRAY) {
+		/*
+		 * SH7751 and ST40 have no restriction to handle cache.
+		 * (While SH7750 must do that at P2 area.)
+		 */
+		__flush_cache_4096(start | CACHE_ASSOC, phys | 0x80000000, 0);
+	} else
 #endif
-	back_to_P1();
-	restore_flags(flags);
+	{
+		save_and_cli(flags);
+		__flush_cache_4096(start | CACHE_ASSOC, phys | 0x80000000, 0x20000000);
+		restore_flags(flags);
+	}
 }
 
 /*
@@ -254,38 +247,77 @@
  */
 void flush_dcache_page(struct page *page)
 {
-	if (test_bit(PG_mapped, &page->flags))
-		__flush_dcache_page(PHYSADDR(page_address(page)));
+	if (test_bit(PG_mapped, &page->flags)) {
+		unsigned long phys = PHYSADDR(page_address(page));
+
+		/* Loop all the D-cache */
+		flush_cache_4096(CACHE_OC_ADDRESS_ARRAY,          phys);
+		flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x1000, phys);
+		flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x2000, phys);
+		flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x3000, phys);
+	}
 }
 
-void flush_cache_all(void)
+static inline void flush_icache_all(void)
 {
-	extern unsigned long empty_zero_page[1024];
 	unsigned long flags;
-	unsigned long addr;
 
 	save_and_cli(flags);
-
-	/* Prefetch the data to write back D-cache */
-	for (addr = (unsigned long)empty_zero_page;
-	     addr < (unsigned long)empty_zero_page + 1024*16;
-	     addr += L1_CACHE_BYTES)
-		asm volatile("pref @%0"::"r" (addr));
-
 	jump_to_P2();
-	/* Flush D-cache/I-cache */
-	ctrl_outl(CCR_CACHE_INIT, CCR);
+	/* Flush I-cache */
+	ctrl_outl(CCR_CACHE_VAL|CCR_CACHE_ICI, CCR);
 	back_to_P1();
 	restore_flags(flags);
 }
 
+void flush_cache_all(void)
+{
+	extern void __flush_dcache_all(void);
+
+	__flush_dcache_all();
+	flush_icache_all();
+}
+
 void flush_cache_mm(struct mm_struct *mm)
 {
 	/* Is there any good way? */
 	/* XXX: possibly call flush_cache_range for each vm area */
+	/* 
+	 * FIXME: Really, the optimal solution here would be able to flush out
+	 * individual lines created by the specified context, but this isn't
+	 * feasible for a number of architectures (such as MIPS, and some
+	 * SPARC) .. is this possible for SuperH?
+	 *
+	 * In the meantime, we'll just flush all of the caches.. this
+	 * seems to be the simplest way to avoid at least a few wasted
+	 * cache flushes. -Lethal
+	 */
 	flush_cache_all();
 }
 
+static void __flush_cache_page(struct vm_area_struct *vma,
+			       unsigned long address,
+			       unsigned long phys)
+{
+	/* We only need to flush D-cache when we have alias */
+	if ((address^phys) & CACHE_ALIAS) {
+		/* Loop 4K of the D-cache */
+		flush_cache_4096(
+			CACHE_OC_ADDRESS_ARRAY | (address & CACHE_ALIAS),
+			phys);
+		/* Loop another 4K of the D-cache */
+		flush_cache_4096(
+			CACHE_OC_ADDRESS_ARRAY | (phys & CACHE_ALIAS),
+			phys);
+	}
+
+	if (vma->vm_flags & VM_EXEC)
+		/* Loop 4K (half) of the I-cache */
+		flush_cache_4096(
+			CACHE_IC_ADDRESS_ARRAY | (address & 0x1000),
+			phys);
+}
+
 /*
  * Write back and invalidate D-caches.
  *
@@ -298,14 +330,53 @@
 void flush_cache_range(struct mm_struct *mm, unsigned long start,
 		       unsigned long end)
 {
-	/*
-	 * We could call flush_cache_page for the pages of these range,
-	 * but it's not efficient (scan the caches all the time...).
-	 *
-	 * We can't use A-bit magic, as there's the case we don't have
-	 * valid entry on TLB.
-	 */
-	flush_cache_all();
+	extern void flush_cache_4096_all(unsigned long start);
+
+	unsigned long p = start & PAGE_MASK;
+	pgd_t *dir;
+	pmd_t *pmd;
+	pte_t *pte;
+	pte_t entry;
+	unsigned long phys;
+	unsigned long d = 0;
+
+	dir = pgd_offset(mm, p);
+	pmd = pmd_offset(dir, p);
+
+	do {
+		if (pmd_none(*pmd) || pmd_bad(*pmd)) {
+			p &= ~((1 << PMD_SHIFT) -1);
+			p += (1 << PMD_SHIFT);
+			pmd++;
+			continue;
+		}
+		pte = pte_offset(pmd, p);
+		do {
+			entry = *pte;
+			if ((pte_val(entry) & _PAGE_PRESENT)) {
+				phys = pte_val(entry)&PTE_PHYS_MASK;
+				if ((p^phys) & CACHE_ALIAS) {
+					d |= 1 << ((p & CACHE_ALIAS)>>12); 
+					d |= 1 << ((phys & CACHE_ALIAS)>>12);
+					if (d == 0x0f)
+						goto loop_exit;
+				}
+			}
+			pte++;
+			p += PAGE_SIZE;
+		} while (p < end && (unsigned long)pte & PAGE_MASK);
+		pmd++;
+	} while (p < end);
+ loop_exit:
+	if (d & 1)
+		flush_cache_4096_all(0);
+	if (d & 2)
+		flush_cache_4096_all(0x1000);
+	if (d & 4)
+		flush_cache_4096_all(0x2000);
+	if (d & 8)
+		flush_cache_4096_all(0x3000);
+	flush_icache_all();
 }
 
 /*
@@ -319,8 +390,7 @@
 	pmd_t *pmd;
 	pte_t *pte;
 	pte_t entry;
-	unsigned long phys, addr, data;
-	unsigned long flags;
+	unsigned long phys;
 
 	dir = pgd_offset(vma->vm_mm, address);
 	pmd = pmd_offset(dir, address);
@@ -328,49 +398,11 @@
 		return;
 	pte = pte_offset(pmd, address);
 	entry = *pte;
-	if (pte_none(entry) || !pte_present(entry))
+	if (!(pte_val(entry) & _PAGE_PRESENT))
 		return;
 
 	phys = pte_val(entry)&PTE_PHYS_MASK;
-
-	phys |= CACHE_VALID;
-	save_and_cli(flags);
-	jump_to_P2();
-
-	/* We only need to flush D-cache when we have alias */
-	if ((address^phys) & CACHE_ALIAS) {
-		/* Loop 4K of the D-cache */
-		for (addr = CACHE_OC_ADDRESS_ARRAY | (address & CACHE_ALIAS);
-		     addr < (CACHE_OC_ADDRESS_ARRAY + (address & CACHE_ALIAS) 
-			     +(CACHE_OC_NUM_ENTRIES/4<<CACHE_OC_ENTRY_SHIFT));
-		     addr += (1<<CACHE_OC_ENTRY_SHIFT)) {
-			data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID);
-			if (data == phys)
-				ctrl_outl(0, addr);
-		}
-		/* Loop another 4K of the D-cache */
-		for (addr = CACHE_OC_ADDRESS_ARRAY | (phys & CACHE_ALIAS);
-		     addr < (CACHE_OC_ADDRESS_ARRAY + (phys & CACHE_ALIAS) 
-			     +(CACHE_OC_NUM_ENTRIES/4<<CACHE_OC_ENTRY_SHIFT));
-		     addr += (1<<CACHE_OC_ENTRY_SHIFT)) {
-			data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID);
-			if (data == phys)
-				ctrl_outl(0, addr);
-		}
-	}
-
-	if (vma->vm_flags & VM_EXEC)
-		/* Loop 4K of the I-cache */
-		for (addr = CACHE_IC_ADDRESS_ARRAY|(address&0x1000);
-		     addr < ((CACHE_IC_ADDRESS_ARRAY|(address&0x1000))
-			     +(CACHE_IC_NUM_ENTRIES/2<<CACHE_IC_ENTRY_SHIFT));
-		     addr += (1<<CACHE_IC_ENTRY_SHIFT)) {
-			data = ctrl_inl(addr)&(0x1ffff000|CACHE_VALID);
-			if (data == phys)
-				ctrl_outl(0, addr);
-		}
-	back_to_P1();
-	restore_flags(flags);
+	__flush_cache_page(vma, address, phys);
 }
 
 /*
diff -urN linux-2.4.21-bk11/arch/sh/mm/clear_page.S linux-2.4.21-bk12/arch/sh/mm/clear_page.S
--- linux-2.4.21-bk11/arch/sh/mm/clear_page.S	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/mm/clear_page.S	2003-07-17 02:52:28.000000000 -0700
@@ -1,10 +1,13 @@
-/* $Id: clear_page.S,v 1.1 2001/07/23 10:08:50 gniibe Exp $
+/* $Id: clear_page.S,v 1.1.1.1.2.8 2003/04/18 10:53:25 sugioka Exp $
  *
- * clear_page implementation of SuperH
+ * __clear_user_page, __clear_user, clear_page implementation of SuperH
  *
- * Copyright (C) 2001  Niibe Yutaka & Kaz Kojima
+ * Copyright (C) 2001  Kaz Kojima
+ * Copyright (C) 2001, 2002  Niibe Yutaka
  *
  */
+#include <linux/config.h>
+#include <linux/linkage.h>
 
 /*
  * clear_page
@@ -18,7 +21,6 @@
  * r4 --- to
  * r5 --- to + 4096
  */
-#include <linux/linkage.h>
 ENTRY(clear_page)
 	mov	r4,r5
 	mov.w	.Llimit,r0
@@ -50,3 +52,244 @@
 	rts
 	 nop
 .Llimit:	.word	(4096-28)
+
+ENTRY(__clear_user)
+	!
+	mov	#0, r0
+	mov	#0xe0, r1	! 0xffffffe0
+	!
+	! r4..(r4+31)&~32 	   -------- not aligned	[ Area 0 ]
+	! (r4+31)&~32..(r4+r5)&~32 -------- aligned	[ Area 1 ]
+	! (r4+r5)&~32..r4+r5       -------- not aligned	[ Area 2 ]
+	!
+	! Clear area 0
+	mov	r4, r2
+	!
+	tst	r1, r5		! length < 32
+	bt	.Larea2		! skip to remainder
+	!
+	add	#31, r2
+	and	r1, r2
+	cmp/eq	r4, r2
+	bt	.Larea1
+	mov	r2, r3
+	sub	r4, r3
+	mov	r3, r7
+	mov	r4, r2
+	!
+.L0:	dt	r3
+0:	mov.b	r0, @r2
+	bf/s	.L0
+	 add	#1, r2
+	!
+	sub	r7, r5
+	mov	r2, r4
+.Larea1:
+	mov	r4, r3
+	add	r5, r3
+	and	r1, r3
+	cmp/hi	r2, r3
+	bf	.Larea2
+	!
+	! Clear area 1
+#if defined(__SH4__)
+1:	movca.l	r0, @r2
+#else
+1:	mov.l	r0, @r2
+#endif
+	add	#4, r2
+2:	mov.l	r0, @r2
+	add	#4, r2
+3:	mov.l	r0, @r2
+	add	#4, r2
+4:	mov.l	r0, @r2
+	add	#4, r2
+5:	mov.l	r0, @r2
+	add	#4, r2
+6:	mov.l	r0, @r2
+	add	#4, r2
+7:	mov.l	r0, @r2
+	add	#4, r2
+8:	mov.l	r0, @r2
+	add	#4, r2
+	cmp/hi	r2, r3
+	bt/s	1b
+	 nop
+	!
+	! Clear area 2
+.Larea2:
+	mov	r4, r3
+	add	r5, r3
+	cmp/hs	r3, r2
+	bt/s	.Ldone
+	 sub	r2, r3
+.L2:	dt	r3
+9:	mov.b	r0, @r2
+	bf/s	.L2
+	 add	#1, r2
+	!
+.Ldone:	rts
+	 mov	#0, r0	! return 0 as normal return
+
+	! return the number of bytes remained
+.Lbad_clear_user:
+	mov	r4, r0
+	add	r5, r0
+	rts
+	 sub	r2, r0
+
+.section __ex_table,"a"
+	.align 2
+	.long	0b, .Lbad_clear_user
+	.long	1b, .Lbad_clear_user
+	.long	2b, .Lbad_clear_user
+	.long	3b, .Lbad_clear_user
+	.long	4b, .Lbad_clear_user
+	.long	5b, .Lbad_clear_user
+	.long	6b, .Lbad_clear_user
+	.long	7b, .Lbad_clear_user
+	.long	8b, .Lbad_clear_user
+	.long	9b, .Lbad_clear_user
+.previous
+
+#if defined(__SH4__)
+/*
+ * __clear_user_page
+ * @to: P1 address (with same color)
+ * @orig_to: P1 address
+ *
+ * void __clear_user_page(void *to, void *orig_to)
+ */
+
+/*
+ * r0 --- scratch 
+ * r4 --- to
+ * r5 --- orig_to
+ * r6 --- to + 4096
+ */
+ENTRY(__clear_user_page)
+	mov.w	.L4096,r0
+	mov	r4,r6
+	add	r0,r6
+	mov	#0,r0
+	!
+1:	ocbi	@r5
+	add	#32,r5
+	movca.l	r0,@r4
+	mov	r4,r1
+	add	#32,r4
+	mov.l	r0,@-r4
+	mov.l	r0,@-r4
+	mov.l	r0,@-r4
+	mov.l	r0,@-r4
+	mov.l	r0,@-r4
+	mov.l	r0,@-r4
+	mov.l	r0,@-r4
+	add	#28,r4
+	cmp/eq	r6,r4
+	bf/s	1b
+	 ocbwb	@r1
+	!
+	rts
+	 nop
+.L4096:	.word	4096
+
+ENTRY(__flush_cache_4096)
+	mov.l	1f,r3
+	add	r6,r3
+	mov	r4,r0
+	mov	#64,r2
+	shll	r2
+	mov	#64,r6
+	jmp	@r3
+	 mov	#96,r7
+	.align	2
+1:	.long	2f
+2:
+	.rept	32
+	mov.l	r5,@r0
+	mov.l	r5,@(32,r0)
+	mov.l	r5,@(r0,r6)
+	mov.l	r5,@(r0,r7)
+	add	r2,r5
+	add	r2,r0
+	.endr
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	rts
+	 nop
+
+ENTRY(__flush_dcache_all)
+	mov.l	2f,r0
+	mov.l	3f,r4
+	and	r0,r4		! r4 = (unsigned long)&empty_zero_page[0] & ~0xffffc000
+	stc	sr,r1		! save SR
+	mov.l	4f,r2
+	or	r1,r2
+	mov	#32,r3
+	shll2	r3
+1:
+	ldc	r2,sr		! set BL bit
+	movca.l	r0,@r4
+	ocbi	@r4
+	add	#32,r4
+	movca.l	r0,@r4
+	ocbi	@r4
+	add	#32,r4
+	movca.l	r0,@r4
+	ocbi	@r4
+	add	#32,r4
+	movca.l	r0,@r4
+	ocbi	@r4
+	ldc	r1,sr		! restore SR
+	dt	r3
+	bf/s	1b
+	 add	#32,r4
+
+	rts
+	 nop
+	.align	2
+2:	.long	0xffffc000
+3:	.long	SYMBOL_NAME(empty_zero_page)
+4:	.long	0x10000000	! BL bit
+
+/* flush_cache_4096_all(unsigned long addr) */
+ENTRY(flush_cache_4096_all)
+	mov.l	2f,r0
+	mov.l	3f,r2
+	and	r0,r2
+	or	r2,r4		! r4 = addr | (unsigned long)&empty_zero_page[0] & ~0x3fff
+	stc	sr,r1		! save SR
+	mov.l	4f,r2
+	or	r1,r2
+	mov	#32,r3
+1:
+	ldc	r2,sr		! set BL bit
+	movca.l	r0,@r4
+	ocbi	@r4
+	add	#32,r4
+	movca.l	r0,@r4
+	ocbi	@r4
+	add	#32,r4
+	movca.l	r0,@r4
+	ocbi	@r4
+	add	#32,r4
+	movca.l	r0,@r4
+	ocbi	@r4
+	ldc	r1,sr		! restore SR
+	dt	r3
+	bf/s	1b
+	 add	#32,r4
+
+	rts
+	 nop
+	.align	2
+2:	.long	0xffffc000
+3:	.long	SYMBOL_NAME(empty_zero_page)
+4:	.long	0x10000000	! BL bit
+#endif
diff -urN linux-2.4.21-bk11/arch/sh/mm/copy_page.S linux-2.4.21-bk12/arch/sh/mm/copy_page.S
--- linux-2.4.21-bk11/arch/sh/mm/copy_page.S	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/mm/copy_page.S	2003-07-17 02:52:28.000000000 -0700
@@ -1,10 +1,12 @@
-/* $Id: copy_page.S,v 1.2 2001/07/23 10:27:25 gniibe Exp $
+/* $Id: copy_page.S,v 1.1.1.1.2.6 2003/03/23 15:30:58 sugioka Exp $
  *
- * copy_page implementation of SuperH
+ * copy_page, __copy_user_page, __copy_user implementation of SuperH
  *
  * Copyright (C) 2001  Niibe Yutaka & Kaz Kojima
+ * Copyright (C) 2002  Toshinobu Sugioka
  *
  */
+#include <linux/linkage.h>
 
 /*
  * copy_page
@@ -21,7 +23,6 @@
  * r10 --- to
  * r11 --- from
  */
-#include <linux/linkage.h>
 ENTRY(copy_page)
 	mov.l	r8,@-r15
 	mov.l	r10,@-r15
@@ -66,4 +67,331 @@
 	mov.l	@r15+,r8
 	rts
 	 nop
+
+#if defined(__SH4__)
+/*
+ * __copy_user_page
+ * @to: P1 address (with same color)
+ * @from: P1 address
+ * @orig_to: P1 address
+ *
+ * void __copy_user_page(void *to, void *from, void *orig_to)
+ */
+
+/*
+ * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch 
+ * r8 --- from + 4096
+ * r9 --- orig_to
+ * r10 --- to
+ * r11 --- from
+ */
+ENTRY(__copy_user_page)
+	mov.l	r8,@-r15
+	mov.l	r9,@-r15
+	mov.l	r10,@-r15
+	mov.l	r11,@-r15
+	mov	r4,r10
+	mov	r5,r11
+	mov	r6,r9
+	mov	r5,r8
+	mov.w	.L4096,r0
+	add	r0,r8
+	!
+1:	ocbi	@r9
+	add	#32,r9
+	mov.l	@r11+,r0
+	mov.l	@r11+,r1
+	mov.l	@r11+,r2
+	mov.l	@r11+,r3
+	mov.l	@r11+,r4
+	mov.l	@r11+,r5
+	mov.l	@r11+,r6
+	mov.l	@r11+,r7
+	movca.l	r0,@r10
+	mov	r10,r0
+	add	#32,r10
+	mov.l	r7,@-r10
+	mov.l	r6,@-r10
+	mov.l	r5,@-r10
+	mov.l	r4,@-r10
+	mov.l	r3,@-r10
+	mov.l	r2,@-r10
+	mov.l	r1,@-r10
+	ocbwb	@r0
+	cmp/eq	r11,r8
+	bf/s	1b
+	 add	#28,r10
+	!
+	mov.l	@r15+,r11
+	mov.l	@r15+,r10
+	mov.l	@r15+,r9
+	mov.l	@r15+,r8
+	rts
+	 nop
+#endif
 .L4096:	.word	4096
+/*
+ * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
+ * Return the number of bytes NOT copied
+ */
+#define EX(...)			\
+	9999: __VA_ARGS__ ;		\
+	.section __ex_table, "a";	\
+	.long 9999b, 6000f	;	\
+	.previous
+ENTRY(__copy_user)
+	tst	r6,r6		! Check explicitly for zero
+	bf	1f
+	rts
+	 mov	#0,r0		! normal return
+1:
+	mov.l	r10,@-r15
+	mov.l	r9,@-r15
+	mov.l	r8,@-r15
+	mov	r4,r3
+	add	r6,r3		! last destination address
+	mov	#12,r0		! Check if small number of bytes
+	cmp/gt	r0,r6
+	bt	2f
+	bra	.L_cleanup_loop
+	 nop
+2:
+	neg	r5,r0		! Calculate bytes needed to align source
+	add	#4,r0
+	and	#3,r0
+	tst	r0,r0
+	bt	.L_jump
+	mov	r0,r1
+
+.L_loop1:
+	! Copy bytes to align source
+EX(	mov.b	@r5+,r0		)
+	dt	r1
+EX(	mov.b	r0,@r4		)
+	add	#-1,r6
+	bf/s	.L_loop1
+	 add	#1,r4
+
+.L_jump:
+	mov	r6,r2		! Calculate number of longwords to copy
+	shlr2	r2
+	tst	r2,r2
+	bt	.L_cleanup
+
+	mov	r4,r0		! Jump to appropriate routine
+	and	#3,r0
+	mov	r0,r1
+	shll2	r1
+	mova	.L_jump_tbl,r0
+	mov.l	@(r0,r1),r1
+	jmp	@r1
+	 nop
+
+	.align 2
+.L_jump_tbl:
+	.long	.L_dest00
+	.long	.L_dest01
+	.long	.L_dest10
+	.long	.L_dest11
+
+! Destination = 00
+
+.L_dest00:
+	mov	r2,r7
+	shlr2	r7
+	shlr	r7
+	tst	r7,r7
+	mov	#7,r0
+	bt/s	1f
+	 and	r0,r2
+	.align 2
+2:
+EX(	mov.l	@r5+,r0		)
+EX(	mov.l	@r5+,r8		)
+EX(	mov.l	@r5+,r9		)
+EX(	mov.l	@r5+,r10	)
+EX(	mov.l	r0,@r4		)
+EX(	mov.l	r8,@(4,r4)	)
+EX(	mov.l	r9,@(8,r4)	)
+EX(	mov.l	r10,@(12,r4)	)
+EX(	mov.l	@r5+,r0		)
+EX(	mov.l	@r5+,r8		)
+EX(	mov.l	@r5+,r9		)
+EX(	mov.l	@r5+,r10	)
+	dt	r7
+EX(	mov.l	r0,@(16,r4)	)
+EX(	mov.l	r8,@(20,r4)	)
+EX(	mov.l	r9,@(24,r4)	)
+EX(	mov.l	r10,@(28,r4)	)
+	bf/s	2b
+	 add	#32,r4
+	tst	r2,r2
+	bt	.L_cleanup
+1:
+EX(	mov.l	@r5+,r0		)
+	dt	r2
+EX(	mov.l	r0,@r4		)
+	bf/s	1b
+	 add	#4,r4
+
+	bra	.L_cleanup
+	 nop
+
+! Destination = 10
+
+.L_dest10:
+	mov	r2,r7
+	shlr2	r7
+	shlr	r7
+	tst	r7,r7
+	mov	#7,r0
+	bt/s	1f
+	 and	r0,r2
+2:
+	dt	r7
+#ifdef __LITTLE_ENDIAN__
+EX(	mov.l	@r5+,r0		)
+EX(	mov.l	@r5+,r1		)
+EX(	mov.l	@r5+,r8		)
+EX(	mov.l	@r5+,r9		)
+EX(	mov.l	@r5+,r10	)
+EX(	mov.w	r0,@r4		)
+	add	#2,r4
+	xtrct	r1,r0
+	xtrct	r8,r1
+	xtrct	r9,r8
+	xtrct	r10,r9
+
+EX(	mov.l	r0,@r4		)
+EX(	mov.l	r1,@(4,r4)	)
+EX(	mov.l	r8,@(8,r4)	)
+EX(	mov.l	r9,@(12,r4)	)
+
+EX(	mov.l	@r5+,r1		)
+EX(	mov.l	@r5+,r8		)
+EX(	mov.l	@r5+,r0		)
+	xtrct	r1,r10
+	xtrct	r8,r1
+	xtrct	r0,r8
+	shlr16	r0
+EX(	mov.l	r10,@(16,r4)	)
+EX(	mov.l	r1,@(20,r4)	)
+EX(	mov.l	r8,@(24,r4)	)
+EX(	mov.w	r0,@(28,r4)	)
+	bf/s	2b
+	 add	#30,r4
+#else
+EX(	mov.l	@(28,r5),r0	)
+EX(	mov.l	@(24,r5),r8	)
+EX(	mov.l	@(20,r5),r9	)
+EX(	mov.l	@(16,r5),r10	)
+EX(	mov.w	r0,@(30,r4)	)
+	add	#-2,r4
+	xtrct	r8,r0
+	xtrct	r9,r8
+	xtrct	r10,r9
+EX(	mov.l	r0,@(28,r4)	)
+EX(	mov.l	r8,@(24,r4)	)
+EX(	mov.l	r9,@(20,r4)	)
+
+EX(	mov.l	@(12,r5),r0	)
+EX(	mov.l	@(8,r5),r8	)
+	xtrct	r0,r10
+EX(	mov.l	@(4,r5),r9	)
+	mov.l	r10,@(16,r4)
+EX(	mov.l	@r5,r10		)
+	xtrct	r8,r0
+	xtrct	r9,r8
+	xtrct	r10,r9
+EX(	mov.l	r0,@(12,r4)	)
+EX(	mov.l	r8,@(8,r4)	)
+	swap.w	r10,r0
+EX(	mov.l	r9,@(4,r4)	)
+EX(	mov.w	r0,@(2,r4)	)
+
+	add	#32,r5
+	bf/s	2b
+	 add	#34,r4
+#endif
+	tst	r2,r2
+	bt	.L_cleanup
+
+1:	! Read longword, write two words per iteration
+EX(	mov.l	@r5+,r0		)
+	dt	r2
+#ifdef __LITTLE_ENDIAN__
+EX(	mov.w	r0,@r4		)
+	shlr16	r0
+EX(	mov.w 	r0,@(2,r4)	)
+#else
+EX(	mov.w	r0,@(2,r4)	)
+	shlr16	r0
+EX(	mov.w	r0,@r4		)
+#endif
+	bf/s	1b
+	 add	#4,r4
+
+	bra	.L_cleanup
+	 nop
+
+! Destination = 01 or 11
+
+.L_dest01:
+.L_dest11:
+	! Read longword, write byte, word, byte per iteration
+EX(	mov.l	@r5+,r0		)
+	dt	r2
+#ifdef __LITTLE_ENDIAN__
+EX(	mov.b	r0,@r4		)
+	shlr8	r0
+	add	#1,r4
+EX(	mov.w	r0,@r4		)
+	shlr16	r0
+EX(	mov.b	r0,@(2,r4)	)
+	bf/s	.L_dest01
+	 add	#3,r4
+#else
+EX(	mov.b	r0,@(3,r4)	)
+	shlr8	r0
+	swap.w	r0,r7
+EX(	mov.b	r7,@r4		)
+	add	#1,r4
+EX(	mov.w	r0,@r4		)
+	bf/s	.L_dest01
+	 add	#3,r4
+#endif
+
+! Cleanup last few bytes
+.L_cleanup:
+	mov	r6,r0
+	and	#3,r0
+	tst	r0,r0
+	bt	.L_exit
+	mov	r0,r6
+
+.L_cleanup_loop:
+EX(	mov.b	@r5+,r0		)
+	dt	r6
+EX(	mov.b	r0,@r4		)
+	bf/s	.L_cleanup_loop
+	 add	#1,r4
+
+.L_exit:
+	mov	#0,r0		! normal return
+5000:
+
+# Exception handler:
+.section .fixup, "ax"
+6000:
+	mov.l	8000f,r1
+	mov	r3,r0
+	jmp	@r1
+	 sub	r4,r0
+	.align	2
+8000:	.long	5000b
+
+.previous
+	mov.l	@r15+,r8
+	mov.l	@r15+,r9
+	rts
+	 mov.l	@r15+,r10
diff -urN linux-2.4.21-bk11/arch/sh/mm/fault.c linux-2.4.21-bk12/arch/sh/mm/fault.c
--- linux-2.4.21-bk11/arch/sh/mm/fault.c	2002-11-28 15:53:11.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/mm/fault.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.49 2001/10/06 19:46:00 lethal Exp $
+/* $Id: fault.c,v 1.1.1.1.2.3 2002/10/24 05:52:58 mrbrown Exp $
  *
  *  linux/arch/sh/mm/fault.c
  *  Copyright (C) 1999  Niibe Yutaka
@@ -27,6 +27,10 @@
 #include <asm/hardirq.h>
 #include <asm/mmu_context.h>
 
+#if defined(CONFIG_SH_KGDB)
+#include <asm/kgdb.h>
+#endif
+
 extern void die(const char *,struct pt_regs *,long);
 
 /*
@@ -95,6 +99,11 @@
 	unsigned long page;
 	unsigned long fixup;
 
+#if defined(CONFIG_SH_KGDB)
+	if (kgdb_nofault && kgdb_bus_err_hook)
+	  kgdb_bus_err_hook();
+#endif
+
 	tsk = current;
 	mm = tsk->mm;
 
@@ -243,10 +252,16 @@
 	pte_t *pte;
 	pte_t entry;
 
+#if defined(CONFIG_SH_KGDB)
+	if (kgdb_nofault && kgdb_bus_err_hook)
+	  kgdb_bus_err_hook();
+#endif
 	if (address >= P3SEG && address < P4SEG)
 		dir = pgd_offset_k(address);
 	else if (address >= TASK_SIZE)
 		return 1;
+	else if (!current->mm)
+		return 1;
 	else
 		dir = pgd_offset(current->mm, address);
 
diff -urN linux-2.4.21-bk11/arch/sh/mm/init.c linux-2.4.21-bk12/arch/sh/mm/init.c
--- linux-2.4.21-bk11/arch/sh/mm/init.c	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/mm/init.c	2003-07-17 02:52:28.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.19 2001/10/01 02:21:50 gniibe Exp $
+/* $Id: init.c,v 1.1.1.1.2.2 2003/07/07 11:23:21 trent Exp $
  *
  *  linux/arch/sh/mm/init.c
  *
@@ -139,7 +139,7 @@
 void __init mem_init(void)
 {
 	extern unsigned long empty_zero_page[1024];
-	int codesize, reservedpages, datasize, initsize;
+	int codesize, reservedpages, datasize, bsssize, initsize, pagemapsize;
 	int tmp;
 
 	max_mapnr = num_physpages = MAX_LOW_PFN - START_PFN;
@@ -163,15 +163,19 @@
 			reservedpages++;
 	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
 	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+	bsssize  =  (unsigned long) &_end - (unsigned long) &__bss_start;
 	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+	pagemapsize = (max_mapnr + 1)*sizeof(struct page);
 
-	printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
-		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
-		max_mapnr << (PAGE_SHIFT-10),
-		codesize >> 10,
-		reservedpages << (PAGE_SHIFT-10),
-		datasize >> 10,
-		initsize >> 10);
+	printk("Memory: %luk/%luk available (%dk reserved including: %dk kernel code, %dk data, %dk BSS, %dk init, %dk page map)\n",
+	       (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+	       max_mapnr << (PAGE_SHIFT-10),
+	       reservedpages << (PAGE_SHIFT-10),
+	       codesize >> 10,
+	       datasize >> 10,
+	       bsssize >> 10,
+	       initsize >> 10,
+	       pagemapsize >> 10);
 
 	p3_cache_init();
 }
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/Makefile linux-2.4.21-bk12/arch/sh/overdrive/Makefile
--- linux-2.4.21-bk11/arch/sh/overdrive/Makefile	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/Makefile	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,20 @@
+#
+# Makefile for the STMicroelectronics Overdrive specific parts of the kernel
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+all: overdrive.o
+
+clean:
+
+O_TARGET := overdrive.o
+obj-y	 := mach.o setup.o io.o led.o
+
+ifneq ($(CONFIG_SH_GENERIC)$(CONFIG_SH_7750_OVERDRIVE),)
+obj-$(CONFIG_PCI) +=  irq.o fpga.o galileo.o
+endif
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/fpga.c linux-2.4.21-bk12/arch/sh/overdrive/fpga.c
--- linux-2.4.21-bk11/arch/sh/overdrive/fpga.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/fpga.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,134 @@
+/* 
+ * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * This file handles programming up the Altera Flex10K that interfaces to
+ * the Galileo, and does the PS/2 keyboard and mouse
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+
+#include "gt64111.h"
+#include "overdrive.h"
+#include "fpga.h"
+
+#define FPGA_NotConfigHigh()  (*FPGA_ControlReg) = (*FPGA_ControlReg) | ENABLE_FPGA_BIT
+#define FPGA_NotConfigLow()   (*FPGA_ControlReg) = (*FPGA_ControlReg) & RESET_FPGA_MASK
+
+/* I need to find out what (if any) the real delay factor here is */
+/* The delay is definately not critical */
+#define long_delay() {int i;for(i=0;i<10000;i++);}
+#define short_delay() {int i;for(i=0;i<100;i++);}
+
+static void __init program_overdrive_fpga(const unsigned char *fpgacode,
+					  int size)
+{
+	int timeout = 0;
+	int i, j;
+	unsigned char b;
+	static volatile unsigned char *FPGA_ControlReg =
+	    (volatile unsigned char *) (OVERDRIVE_CTRL);
+	static volatile unsigned char *FPGA_ProgramReg =
+	    (volatile unsigned char *) (FPGA_DCLK_ADDRESS);
+
+	printk("FPGA:  Commencing FPGA Programming\n");
+
+	/* The PCI reset but MUST be low when programming the FPGA !!! */
+	b = (*FPGA_ControlReg) & RESET_PCI_MASK;
+
+	(*FPGA_ControlReg) = b;
+
+	/* Prepare FPGA to program */
+
+	FPGA_NotConfigHigh();
+	long_delay();
+
+	FPGA_NotConfigLow();
+	short_delay();
+
+	while ((*FPGA_ProgramReg & FPGA_NOT_STATUS) != 0) {
+		printk("FPGA:  Waiting for NotStatus to go Low ... \n");
+	}
+
+	FPGA_NotConfigHigh();
+
+	/* Wait for FPGA "ready to be programmed" signal */
+	printk("FPGA:  Waiting for NotStatus to go high (FPGA ready)... \n");
+
+	for (timeout = 0;
+	     (((*FPGA_ProgramReg & FPGA_NOT_STATUS) == 0)
+	      && (timeout < FPGA_TIMEOUT)); timeout++);
+
+	/* Check if timeout condition occured - i.e. an error */
+
+	if (timeout == FPGA_TIMEOUT) {
+		printk
+		    ("FPGA:  Failed to program - Timeout waiting for notSTATUS to go high\n");
+		return;
+	}
+
+	printk("FPGA:  Copying data to FPGA ... %d bytes\n", size);
+
+	/* Copy array to FPGA - bit at a time */
+
+	for (i = 0; i < size; i++) {
+		volatile unsigned w = 0;
+
+		for (j = 0; j < 8; j++) {
+			*FPGA_ProgramReg = (fpgacode[i] >> j) & 0x01;
+			short_delay();
+		}
+		if ((i & 0x3ff) == 0) {
+			printk(".");
+		}
+	}
+
+	/* Waiting for CONFDONE to go high - means the program is complete  */
+
+	for (timeout = 0;
+	     (((*FPGA_ProgramReg & FPGA_CONFDONE) == 0)
+	      && (timeout < FPGA_TIMEOUT)); timeout++) {
+
+		*FPGA_ProgramReg = 0x0;
+		long_delay();
+	}
+
+	if (timeout == FPGA_TIMEOUT) {
+		printk
+		    ("FPGA:  Failed to program - Timeout waiting for CONFDONE to go high\n");
+		return;
+	} else {		/* Clock another 10 times - gets the device into a working state      */
+		for (i = 0; i < 10; i++) {
+			*FPGA_ProgramReg = 0x0;
+			short_delay();
+		}
+	}
+
+	printk("FPGA:  Programming complete\n");
+}
+
+
+static const unsigned char __init fpgacode[] = {
+#include "./overdrive.ttf"	/* Code from maxplus2 compiler */
+	, 0, 0
+};
+
+
+int __init init_overdrive_fpga(void)
+{
+	program_overdrive_fpga(fpgacode, sizeof(fpgacode));
+
+	return 0;
+}
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/fpga.h linux-2.4.21-bk12/arch/sh/overdrive/fpga.h
--- linux-2.4.21-bk11/arch/sh/overdrive/fpga.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/fpga.h	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,15 @@
+/* 
+ * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ */
+
+#ifndef __FPGA_OD_H__
+#define __FPGA_OD_H__
+
+/* This routine will program up the fpga which interfaces to the galileo */
+int init_overdrive_fpga(void);
+
+#endif
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/galileo.c linux-2.4.21-bk12/arch/sh/overdrive/galileo.c
--- linux-2.4.21-bk11/arch/sh/overdrive/galileo.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/galileo.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,594 @@
+/* 
+ * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * This file contains the PCI routines required for the Galileo GT6411 
+ * PCI bridge as used on the Orion and Overdrive boards.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+
+#include "overdrive.h"
+#include "gt64111.h"
+
+
+/* After boot, we shift the Galileo registers so that they appear 
+ * in BANK6, along with IO space. This means we can have one contingous
+ * lump of PCI address space without these registers appearing in the 
+ * middle of them 
+ */
+
+#define GT64111_BASE_ADDRESS  0xbb000000
+#define GT64111_IO_BASE_ADDRESS  0x1000
+/* The GT64111 registers appear at this address to the SH4 after reset */
+#define RESET_GT64111_BASE_ADDRESS           0xb4000000
+
+/* Macros used to access the Galileo registers */
+#define RESET_GT64111_REG(x) (RESET_GT64111_BASE_ADDRESS+x)
+#define GT64111_REG(x) (GT64111_BASE_ADDRESS+x)
+
+#define RESET_GT_WRITE(x,v) writel((v),RESET_GT64111_REG(x))
+
+#define RESET_GT_READ(x) readl(RESET_GT64111_REG(x))
+
+#define GT_WRITE(x,v) writel((v),GT64111_REG(x))
+#define GT_WRITE_BYTE(x,v) writeb((v),GT64111_REG(x))
+#define GT_WRITE_SHORT(x,v) writew((v),GT64111_REG(x))
+
+#define GT_READ(x)    readl(GT64111_REG(x))
+#define GT_READ_BYTE(x)  readb(GT64111_REG(x))
+#define GT_READ_SHORT(x) readw(GT64111_REG(x))
+
+
+/* Where the various SH banks start at */
+#define SH_BANK4_ADR 0xb0000000
+#define SH_BANK5_ADR 0xb4000000
+#define SH_BANK6_ADR 0xb8000000
+
+/* Masks out everything but lines 28,27,26 */
+#define BANK_SELECT_MASK 0x1c000000
+
+#define SH4_TO_BANK(x) ( (x) & BANK_SELECT_MASK)
+
+/* 
+ * Masks used for address conversaion. Bank 6 is used for IO and 
+ * has all the address bits zeroed by the FPGA. Special case this
+ */
+#define MEMORY_BANK_MASK 0x1fffffff
+#define IO_BANK_MASK  0x03ffffff
+
+/* Mark bank 6 as the bank used for IO. You can change this in the FPGA code
+ * if you want 
+ */
+#define IO_BANK_ADR PCI_GTIO_BASE
+
+/* Will select the correct mask to apply depending on the SH$ address */
+#define SELECT_BANK_MASK(x) \
+   ( (SH4_TO_BANK(x)==SH4_TO_BANK(IO_BANK_ADR)) ? IO_BANK_MASK : MEMORY_BANK_MASK)
+
+/* Converts between PCI space and P2 region */
+#define SH4_TO_PCI(x) ((x)&SELECT_BANK_MASK(x))
+
+/* Various macros for figuring out what to stick in the Galileo registers. 
+ * You *really* don't want to figure this stuff out by hand, you always get
+ * it wrong
+ */
+#define GT_MEM_LO_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7ff)
+#define GT_MEM_HI_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7f)
+#define GT_MEM_SUB_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>20)&0xff)
+
+#define PROGRAM_HI_LO(block,a,s) \
+    GT_WRITE(block##_LO_DEC_ADR,GT_MEM_LO_ADR(a));\
+    GT_WRITE(block##_HI_DEC_ADR,GT_MEM_HI_ADR(a+s-1))
+
+#define PROGRAM_SUB_HI_LO(block,a,s) \
+    GT_WRITE(block##_LO_DEC_ADR,GT_MEM_SUB_ADR(a));\
+    GT_WRITE(block##_HI_DEC_ADR,GT_MEM_SUB_ADR(a+s-1))
+
+/* We need to set the size, and the offset register */
+
+#define GT_BAR_MASK(x) ((x)&~0xfff)
+
+/* Macro to set up the BAR in the Galileo. Essentially used for the DRAM */
+#define PROGRAM_GT_BAR(block,a,s) \
+  GT_WRITE(PCI_##block##_BANK_SIZE,GT_BAR_MASK((s-1)));\
+  write_config_to_galileo(PCI_CONFIG_##block##_BASE_ADR,\
+			     GT_BAR_MASK(a))
+
+#define DISABLE_GT_BAR(block) \
+  GT_WRITE(PCI_##block##_BANK_SIZE,0),\
+  GT_CONFIG_WRITE(PCI_CONFIG_##block##_BASE_ADR,\
+    0x80000000)
+
+/* Macros to disable things we are not going to use */
+#define DISABLE_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0x7ff);\
+                          GT_WRITE(x##_HI_DEC_ADR,0x00)
+
+#define DISABLE_SUB_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0xff);\
+                              GT_WRITE(x##_HI_DEC_ADR,0x00)
+
+static void __init reset_pci(void)
+{
+	/* Set RESET_PCI bit high */
+	writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL);
+	udelay(250);
+
+	/* Set RESET_PCI bit low */
+	writeb(readb(OVERDRIVE_CTRL) & RESET_PCI_MASK, OVERDRIVE_CTRL);
+	udelay(250);
+
+	writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL);
+	udelay(250);
+}
+
+static int write_config_to_galileo(int where, u32 val);
+#define GT_CONFIG_WRITE(where,val) write_config_to_galileo(where,val)
+
+#define ENABLE_PCI_DRAM
+
+
+#ifdef TEST_DRAM
+/* Test function to check out if the PCI DRAM is working OK */
+static int  /* __init */ test_dram(unsigned *base, unsigned size)
+{
+	unsigned *p = base;
+	unsigned *end = (unsigned *) (((unsigned) base) + size);
+	unsigned w;
+
+	for (p = base; p < end; p++) {
+		*p = 0xffffffff;
+		if (*p != 0xffffffff) {
+			printk("AAARGH -write failed!!! at %p is %x\n", p,
+			       *p);
+			return 0;
+		}
+		*p = 0x0;
+		if (*p != 0x0) {
+			printk("AAARGH -write failed!!!\n");
+			return 0;
+		}
+	}
+
+	for (p = base; p < end; p++) {
+		*p = (unsigned) p;
+		if (*p != (unsigned) p) {
+			printk("Failed at 0x%p, actually is 0x%x\n", p,
+			       *p);
+			return 0;
+		}
+	}
+
+	for (p = base; p < end; p++) {
+		w = ((unsigned) p & 0xffff0000);
+		*p = w | (w >> 16);
+	}
+
+	for (p = base; p < end; p++) {
+		w = ((unsigned) p & 0xffff0000);
+		w |= (w >> 16);
+		if (*p != w) {
+			printk
+			    ("Failed at 0x%p, should be 0x%x actually is 0x%x\n",
+			     p, w, *p);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+#endif
+
+
+/* Function to set up and initialise the galileo. This sets up the BARS,
+ * maps the DRAM into the address space etc,etc
+ */
+int __init galileo_init(void)
+{
+	reset_pci();
+
+	/* Now shift the galileo regs into this block */
+	RESET_GT_WRITE(INTERNAL_SPACE_DEC,
+		       GT_MEM_LO_ADR(GT64111_BASE_ADDRESS));
+
+	/* Should have a sanity check here, that you can read back  at the new
+	 * address what you just wrote 
+	 */
+
+	/* Disable decode for all regions */
+	DISABLE_DECODE(RAS10);
+	DISABLE_DECODE(RAS32);
+	DISABLE_DECODE(CS20);
+	DISABLE_DECODE(CS3);
+	DISABLE_DECODE(PCI_IO);
+	DISABLE_DECODE(PCI_MEM0);
+	DISABLE_DECODE(PCI_MEM1);
+
+	/* Disable all BARS */
+	GT_WRITE(BAR_ENABLE_ADR, 0x1ff);
+	DISABLE_GT_BAR(RAS10);
+	DISABLE_GT_BAR(RAS32);
+	DISABLE_GT_BAR(CS20);
+	DISABLE_GT_BAR(CS3);
+
+	/* Tell the BAR where the IO registers now are */
+	GT_CONFIG_WRITE(PCI_CONFIG_INT_REG_IO_ADR,GT_BAR_MASK(
+					    (GT64111_IO_BASE_ADDRESS &
+					     IO_BANK_MASK)));
+	/* set up a 112 Mb decode */
+	PROGRAM_HI_LO(PCI_MEM0, SH_BANK4_ADR, 112 * 1024 * 1024);
+
+	/* Set up a 32 MB io space decode */
+	PROGRAM_HI_LO(PCI_IO, IO_BANK_ADR, 32 * 1024 * 1024);
+
+#ifdef ENABLE_PCI_DRAM
+	/* Program up the DRAM configuration - there is DRAM only in bank 0 */
+	/* Now set up the DRAM decode */
+	PROGRAM_HI_LO(RAS10, PCI_DRAM_BASE, PCI_DRAM_SIZE);
+	/* And the sub decode */
+	PROGRAM_SUB_HI_LO(RAS0, PCI_DRAM_BASE, PCI_DRAM_SIZE);
+
+	DISABLE_SUB_DECODE(RAS1);
+
+	/* Set refresh rate */
+	GT_WRITE(DRAM_BANK0_PARMS, 0x3f);
+	GT_WRITE(DRAM_CFG, 0x100);
+
+	/* we have to lob off the top bits rememeber!! */
+	PROGRAM_GT_BAR(RAS10, SH4_TO_PCI(PCI_DRAM_BASE), PCI_DRAM_SIZE);
+
+#endif
+
+	/* We are only interested in decoding RAS10 and the Galileo's internal 
+	 * registers (as IO) on the PCI bus
+	 */
+#ifdef ENABLE_PCI_DRAM
+	GT_WRITE(BAR_ENABLE_ADR, (~((1 << 8) | (1 << 3))) & 0x1ff);
+#else
+	GT_WRITE(BAR_ENABLE_ADR, (~(1 << 3)) & 0x1ff);
+#endif
+
+	/* Change the class code to host bridge, it actually powers up 
+	 * as a memory controller
+         */
+	GT_CONFIG_WRITE(8, 0x06000011);
+
+	/* Allow the galileo to master the PCI bus */
+	GT_CONFIG_WRITE(PCI_COMMAND,
+			PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
+			PCI_COMMAND_IO);
+
+
+#if 0
+        printk("Testing PCI DRAM - ");
+	if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) {
+		printk("Passed\n");
+	}else {
+		printk("FAILED\n");
+	}
+#endif
+	return 0;
+
+}
+
+
+#define SET_CONFIG_BITS(bus,devfn,where)\
+  ((1<<31) | ((bus) << 16) | ((devfn) << 8) | ((where) & ~3))
+
+#define CONFIG_CMD(dev, where) SET_CONFIG_BITS((dev)->bus->number,(dev)->devfn,where)
+
+/* This write to the galileo config registers, unlike the functions below, can
+ * be used before the PCI subsystem has started up
+ */
+static int __init write_config_to_galileo(int where, u32 val)
+{
+	GT_WRITE(PCI_CFG_ADR, SET_CONFIG_BITS(0, 0, where));
+
+	GT_WRITE(PCI_CFG_DATA, val);
+	return 0;
+}
+
+/* We exclude the galileo and slot 31, the galileo because I don't know how to stop
+ * the setup code shagging up the setup I have done on it, and 31 because the whole
+ * thing locks up if you try to access that slot (which doesn't exist of course anyway
+ */
+
+#define EXCLUDED_DEV(dev) ((dev->bus->number==0) && ((PCI_SLOT(dev->devfn)==0) || (PCI_SLOT(dev->devfn) == 31)))
+
+static int galileo_read_config_byte(struct pci_dev *dev, int where,
+				    u8 * val)
+{
+
+        
+	/* I suspect this doesn't work because this drives a special cycle ? */
+	if (EXCLUDED_DEV(dev)) {
+		*val = 0xff;
+		return PCIBIOS_SUCCESSFUL;
+	}
+	/* Start the config cycle */
+	GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
+	/* Read back the result */
+	*val = GT_READ_BYTE(PCI_CFG_DATA + (where & 3));
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int galileo_read_config_word(struct pci_dev *dev, int where,
+				    u16 * val)
+{
+
+        if (EXCLUDED_DEV(dev)) {
+		*val = 0xffff;
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
+	*val = GT_READ_SHORT(PCI_CFG_DATA + (where & 2));
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int galileo_read_config_dword(struct pci_dev *dev, int where,
+				     u32 * val)
+{
+	if (EXCLUDED_DEV(dev)) {
+		*val = 0xffffffff;
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
+	*val = GT_READ(PCI_CFG_DATA);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int galileo_write_config_byte(struct pci_dev *dev, int where,
+				     u8 val)
+{
+	GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
+
+	GT_WRITE_BYTE(PCI_CFG_DATA + (where & 3), val);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int galileo_write_config_word(struct pci_dev *dev, int where,
+				     u16 val)
+{
+	GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
+
+	GT_WRITE_SHORT(PCI_CFG_DATA + (where & 2), val);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int galileo_write_config_dword(struct pci_dev *dev, int where,
+				      u32 val)
+{
+	GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
+
+	GT_WRITE(PCI_CFG_DATA, val);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_config_ops = {
+	galileo_read_config_byte,
+	galileo_read_config_word,
+	galileo_read_config_dword,
+	galileo_write_config_byte,
+	galileo_write_config_word,
+	galileo_write_config_dword
+};
+
+
+/* Everything hangs off this */
+static struct pci_bus *pci_root_bus;
+
+
+static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
+{
+	return PCI_SLOT(dev->devfn);
+}
+
+static int __init map_od_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	/* Slot 1: Galileo 
+	 * Slot 2: PCI Slot 1
+	 * Slot 3: PCI Slot 2
+	 * Slot 4: ESS
+	 */
+	switch (slot) {
+	case 2: 
+		return OVERDRIVE_PCI_IRQ1;
+	case 3:
+		/* Note this assumes you have a hacked card in slot 2 */
+		return OVERDRIVE_PCI_IRQ2;
+	case 4:
+		return OVERDRIVE_ESS_IRQ;
+	default:
+		/* printk("PCI: Unexpected IRQ mapping request for slot %d\n", slot); */
+		return -1;
+	}
+}
+
+
+
+void __init
+pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
+{
+        ranges->io_start -= bus->resource[0]->start;
+        ranges->io_end -= bus->resource[0]->start;
+        ranges->mem_start -= bus->resource[1]->start;
+        ranges->mem_end -= bus->resource[1]->start;
+}                                                                                
+
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+	int i;
+
+	/*
+	 * PCI IDE controllers use non-standard I/O port decoding, respect it.
+	 */
+	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+		return;
+	printk("PCI: IDE base address fixup for %s\n", d->slot_name);
+	for(i=0; i<4; i++) {
+		struct resource *r = &d->resource[i];
+		if ((r->start & ~0x80) == 0x374) {
+			r->start |= 2;
+			r->end = r->start;
+		}
+	}
+}
+
+
+/* Add future fixups here... */
+struct pci_fixup pcibios_fixups[] = {
+	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
+	{ 0 }
+};
+
+void __init pcibios_init(void)
+{
+	static struct resource galio,galmem;
+
+        /* Allocate the registers used by the Galileo */
+        galio.flags = IORESOURCE_IO;
+        galio.name  = "Galileo GT64011";
+        galmem.flags = IORESOURCE_MEM|IORESOURCE_PREFETCH;
+        galmem.name  = "Galileo GT64011 DRAM";
+
+        allocate_resource(&ioport_resource, &galio, 256,
+		    GT64111_IO_BASE_ADDRESS,GT64111_IO_BASE_ADDRESS+256, 256, NULL, NULL);
+        allocate_resource(&iomem_resource, &galmem,PCI_DRAM_SIZE,
+		    PHYSADDR(PCI_DRAM_BASE), PHYSADDR(PCI_DRAM_BASE)+PCI_DRAM_SIZE, 
+			     PCI_DRAM_SIZE, NULL, NULL);
+
+  	/* ok, do the scan man */
+	pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
+
+        pci_assign_unassigned_resources();
+	pci_fixup_irqs(no_swizzle, map_od_irq);
+
+#ifdef TEST_DRAM
+        printk("Testing PCI DRAM - ");
+	if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) {
+		printk("Passed\n");
+	}else {
+		printk("FAILED\n");
+	}
+#endif
+
+}
+
+char * __init pcibios_setup(char *str)
+{
+	return str;
+}
+
+
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx = 0; idx < 6; idx++) {
+		r = dev->resource + idx;
+		if (!r->start && r->end) {
+			printk(KERN_ERR
+			       "PCI: Device %s not available because"
+			       " of resource collisions\n",
+			       dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (cmd != old_cmd) {
+		printk("PCI: enabling device %s (%04x -> %04x)\n",
+		       dev->slot_name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+
+}
+
+/* We should do some optimisation work here I think. Ok for now though */
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+
+}
+
+void pcibios_align_resource(void *data, struct resource *res,
+			    unsigned long size)
+{
+}
+
+void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+			     struct resource *res, int resource)
+{
+
+	unsigned long where, size;
+	u32 reg;
+	
+
+	printk("PCI: Assigning %3s %08lx to %s\n",
+	       res->flags & IORESOURCE_IO ? "IO" : "MEM",
+	       res->start, dev->name);
+
+	where = PCI_BASE_ADDRESS_0 + resource * 4;
+	size = res->end - res->start;
+
+	pci_read_config_dword(dev, where, &reg);
+	reg = (reg & size) | (((u32) (res->start - root->start)) & ~size);
+	pci_write_config_dword(dev, where, reg);
+}
+
+
+void __init pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+	printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name);
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+/*
+ *  If we set up a device for bus mastering, we need to check the latency
+ *  timer as certain crappy BIOSes forget to set it properly.
+ */
+unsigned int pcibios_max_latency = 255;
+
+void pcibios_set_master(struct pci_dev *dev)
+{
+	u8 lat;
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+	if (lat < 16)
+		lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+	else if (lat > pcibios_max_latency)
+		lat = pcibios_max_latency;
+	else
+		return;
+	printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+}
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/gt64111.h linux-2.4.21-bk12/arch/sh/overdrive/gt64111.h
--- linux-2.4.21-bk11/arch/sh/overdrive/gt64111.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/gt64111.h	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,109 @@
+#ifndef _GT64111_H_
+#define _GT64111_H_
+
+#define MASTER_INTERFACE         0x0
+#define RAS10_LO_DEC_ADR         0x8        
+#define RAS10_HI_DEC_ADR         0x10
+#define RAS32_LO_DEC_ADR         0x18
+#define RAS32_HI_DEC_ADR         0x20
+#define CS20_LO_DEC_ADR          0x28
+#define CS20_HI_DEC_ADR          0x30
+#define CS3_LO_DEC_ADR           0x38
+#define CS3_HI_DEC_ADR           0x40
+#define PCI_IO_LO_DEC_ADR        0x48
+#define PCI_IO_HI_DEC_ADR        0x50
+#define PCI_MEM0_LO_DEC_ADR      0x58
+#define PCI_MEM0_HI_DEC_ADR      0x60
+#define INTERNAL_SPACE_DEC       0x68
+#define BUS_ERR_ADR_LO_CPU       0x70
+#define READONLY0                0x78
+#define PCI_MEM1_LO_DEC_ADR      0x80
+#define PCI_MEM1_HI_DEC_ADR      0x88
+#define RAS0_LO_DEC_ADR          0x400   
+#define RAS0_HI_DEC_ADR          0x404
+#define RAS1_LO_DEC_ADR          0x408
+#define RAS1_HI_DEC_ADR          0x40c
+#define RAS2_LO_DEC_ADR          0x410
+#define RAS2_HI_DEC_ADR          0x414
+#define RAS3_LO_DEC_ADR          0x418
+#define RAS3_HI_DEC_ADR          0x41c
+#define DEV_CS0_LO_DEC_ADR       0x420
+#define DEV_CS0_HI_DEC_ADR       0x424
+#define DEV_CS1_LO_DEC_ADR       0x428
+#define DEV_CS1_HI_DEC_ADR       0x42c
+#define DEV_CS2_LO_DEC_ADR       0x430
+#define DEV_CS2_HI_DEC_ADR       0x434
+#define DEV_CS3_LO_DEC_ADR       0x438
+#define DEV_CS3_HI_DEC_ADR       0x43c
+#define DEV_BOOTCS_LO_DEC_ADR    0x440
+#define DEV_BOOTCS_HI_DEC_ADR    0x444
+#define DEV_ADR_DEC_ERR          0x470
+#define DRAM_CFG                 0x448   
+#define DRAM_BANK0_PARMS         0x44c   
+#define DRAM_BANK1_PARMS         0x450
+#define DRAM_BANK2_PARMS         0x454
+#define DRAM_BANK3_PARMS         0x458
+#define DEV_BANK0_PARMS          0x45c
+#define DEV_BANK1_PARMS          0x460
+#define DEV_BANK2_PARMS          0x464
+#define DEV_BANK3_PARMS          0x468
+#define DEV_BOOT_BANK_PARMS      0x46c
+#define CH0_DMA_BYTECOUNT        0x800
+#define CH1_DMA_BYTECOUNT        0x804
+#define CH2_DMA_BYTECOUNT        0x808
+#define CH3_DMA_BYTECOUNT        0x80c
+#define CH0_DMA_SRC_ADR          0x810
+#define CH1_DMA_SRC_ADR          0x814
+#define CH2_DMA_SRC_ADR          0x818
+#define CH3_DMA_SRC_ADR          0x81c
+#define CH0_DMA_DST_ADR          0x820
+#define CH1_DMA_DST_ADR          0x824
+#define CH2_DMA_DST_ADR          0x828
+#define CH3_DMA_DST_ADR          0x82c
+#define CH0_NEXT_REC_PTR         0x830
+#define CH1_NEXT_REC_PTR         0x834
+#define CH2_NEXT_REC_PTR         0x838
+#define CH3_NEXT_REC_PTR         0x83c
+#define CH0_CTRL                 0x840
+#define CH1_CTRL                 0x844
+#define CH2_CTRL                 0x848
+#define CH3_CTRL                 0x84c
+#define DMA_ARBITER              0x860
+#define TIMER0                   0x850
+#define TIMER1                   0x854
+#define TIMER2                   0x858
+#define TIMER3                   0x85c
+#define TIMER_CTRL               0x864
+#define PCI_CMD                  0xc00
+#define PCI_TIMEOUT              0xc04
+#define PCI_RAS10_BANK_SIZE      0xc08
+#define PCI_RAS32_BANK_SIZE      0xc0c
+#define PCI_CS20_BANK_SIZE       0xc10
+#define PCI_CS3_BANK_SIZE        0xc14
+#define PCI_SERRMASK             0xc28
+#define PCI_INTACK               0xc34
+#define PCI_BAR_EN               0xc3c
+#define PCI_CFG_ADR              0xcf8
+#define PCI_CFG_DATA             0xcfc
+#define PCI_INTCAUSE             0xc18
+#define PCI_MAST_MASK            0xc1c
+#define PCI_PCIMASK              0xc24
+#define BAR_ENABLE_ADR           0xc3c
+
+/* These are config registers, accessible via PCI space */
+#define PCI_CONFIG_RAS10_BASE_ADR   0x010
+#define PCI_CONFIG_RAS32_BASE_ADR   0x014
+#define PCI_CONFIG_CS20_BASE_ADR    0x018
+#define PCI_CONFIG_CS3_BASE_ADR     0x01c
+#define PCI_CONFIG_INT_REG_MM_ADR   0x020
+#define PCI_CONFIG_INT_REG_IO_ADR   0x024
+#define PCI_CONFIG_BOARD_VENDOR     0x02c
+#define PCI_CONFIG_ROM_ADR          0x030
+#define PCI_CONFIG_INT_PIN_LINE     0x03c
+
+
+
+
+
+#endif
+
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/io.c linux-2.4.21-bk12/arch/sh/overdrive/io.c
--- linux-2.4.21-bk11/arch/sh/overdrive/io.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/io.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,173 @@
+/* 
+ * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * This file contains the I/O routines for use on the overdrive board
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+
+#include "overdrive.h"
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the SuperH architecture, we just read/write the
+ * memory location directly.
+ */
+
+#define dprintk(x...)
+
+/* Translates an IO address to where it is mapped in memory */
+
+#define io_addr(x) (((unsigned)(x))|PCI_GTIO_BASE)
+
+unsigned char od_inb(unsigned long port)
+{
+dprintk("od_inb(%x)\n", port);
+	return readb(io_addr(port)) & 0xff;
+}
+
+
+unsigned short od_inw(unsigned long port)
+{
+dprintk("od_inw(%x)\n", port);
+	return readw(io_addr(port)) & 0xffff;
+}
+
+unsigned int od_inl(unsigned long port)
+{
+dprintk("od_inl(%x)\n", port);
+	return readl(io_addr(port));
+}
+
+void od_outb(unsigned char value, unsigned long port)
+{
+dprintk("od_outb(%x, %x)\n", value, port);
+	writeb(value, io_addr(port));
+}
+
+void od_outw(unsigned short value, unsigned long port)
+{
+dprintk("od_outw(%x, %x)\n", value, port);
+	writew(value, io_addr(port));
+}
+
+void od_outl(unsigned int value, unsigned long port)
+{
+dprintk("od_outl(%x, %x)\n", value, port);
+	writel(value, io_addr(port));
+}
+
+/* This is horrible at the moment - needs more work to do something sensible */
+#define IO_DELAY() udelay(10)
+
+#define OUT_DELAY(x,type) \
+void od_out##x##_p(unsigned type value,unsigned long port){out##x(value,port);IO_DELAY();}
+
+#define IN_DELAY(x,type) \
+unsigned type od_in##x##_p(unsigned long port) {unsigned type tmp=in##x(port);IO_DELAY();return tmp;}
+
+
+OUT_DELAY(b,char)
+OUT_DELAY(w,short)
+OUT_DELAY(l,int)
+
+IN_DELAY(b,char)
+IN_DELAY(w,short)
+IN_DELAY(l,int)
+
+
+/*  Now for the string version of these functions */
+void od_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+	int i;
+	unsigned char *p = (unsigned char *) addr;
+
+	for (i = 0; i < count; i++, p++) {
+		outb(*p, port);
+	}
+}
+
+
+void od_insb(unsigned long port, void *addr, unsigned long count)
+{
+	int i;
+	unsigned char *p = (unsigned char *) addr;
+
+	for (i = 0; i < count; i++, p++) {
+		*p = inb(port);
+	}
+}
+
+/* For the 16 and 32 bit string functions, we have to worry about alignment.
+ * The SH does not do unaligned accesses, so we have to read as bytes and
+ * then write as a word or dword. 
+ * This can be optimised a lot more, especially in the case where the data
+ * is aligned
+ */
+
+void od_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+	int i;
+	unsigned short tmp;
+	unsigned char *p = (unsigned char *) addr;
+
+	for (i = 0; i < count; i++, p += 2) {
+		tmp = (*p) | ((*(p + 1)) << 8);
+		outw(tmp, port);
+	}
+}
+
+
+void od_insw(unsigned long port, void *addr, unsigned long count)
+{
+	int i;
+	unsigned short tmp;
+	unsigned char *p = (unsigned char *) addr;
+
+	for (i = 0; i < count; i++, p += 2) {
+		tmp = inw(port);
+		p[0] = tmp & 0xff;
+		p[1] = (tmp >> 8) & 0xff;
+	}
+}
+
+
+void od_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+	int i;
+	unsigned tmp;
+	unsigned char *p = (unsigned char *) addr;
+
+	for (i = 0; i < count; i++, p += 4) {
+		tmp = (*p) | ((*(p + 1)) << 8) | ((*(p + 2)) << 16) |
+		      ((*(p + 3)) << 24);
+		outl(tmp, port);
+	}
+}
+
+
+void od_insl(unsigned long port, void *addr, unsigned long count)
+{
+	int i;
+	unsigned tmp;
+	unsigned char *p = (unsigned char *) addr;
+
+	for (i = 0; i < count; i++, p += 4) {
+		tmp = inl(port);
+		p[0] = tmp & 0xff;
+		p[1] = (tmp >> 8) & 0xff;
+		p[2] = (tmp >> 16) & 0xff;
+		p[3] = (tmp >> 24) & 0xff;
+
+	}
+}
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/io_od.h linux-2.4.21-bk12/arch/sh/overdrive/io_od.h
--- linux-2.4.21-bk11/arch/sh/overdrive/io_od.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/io_od.h	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,77 @@
+/*
+ * include/asm-sh/io_od.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for an STMicroelectronics Overdrive
+ */
+
+#ifndef _ASM_SH_IO_OD_H
+#define _ASM_SH_IO_OD_H
+
+#include <asm/io_generic.h>
+
+extern unsigned char od_inb(unsigned long port);
+extern unsigned short od_inw(unsigned long port);
+extern unsigned int od_inl(unsigned long port);
+
+extern void od_outb(unsigned char value, unsigned long port);
+extern void od_outw(unsigned short value, unsigned long port);
+extern void od_outl(unsigned int value, unsigned long port);
+
+extern unsigned char od_inb_p(unsigned long port);
+extern unsigned short od_inw_p(unsigned long port);
+extern unsigned int od_inl_p(unsigned long port);
+extern void od_outb_p(unsigned char value, unsigned long port);
+extern void od_outw_p(unsigned short value, unsigned long port);
+extern void od_outl_p(unsigned int value, unsigned long port);
+
+extern void od_insb(unsigned long port, void *addr, unsigned long count);
+extern void od_insw(unsigned long port, void *addr, unsigned long count);
+extern void od_insl(unsigned long port, void *addr, unsigned long count);
+extern void od_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void od_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void od_outsl(unsigned long port, const void *addr, unsigned long count);
+
+extern unsigned long od_isa_port2addr(unsigned long offset);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			od_inb
+# define __inw			od_inw
+# define __inl			od_inl
+# define __outb			od_outb
+# define __outw			od_outw
+# define __outl			od_outl
+
+# define __inb_p		od_inb_p
+# define __inw_p		od_inw_p
+# define __inl_p		od_inl_p
+# define __outb_p		od_outb_p
+# define __outw_p		od_outw_p
+# define __outl_p		od_outl_p
+
+# define __insb			od_insb
+# define __insw			od_insw
+# define __insl			od_insl
+# define __outsb		od_outsb
+# define __outsw		od_outsw
+# define __outsl		od_outsl
+
+# define __readb		generic_readb
+# define __readw		generic_readw
+# define __readl		generic_readl
+# define __writeb		generic_writeb
+# define __writew		generic_writew
+# define __writel		generic_writel
+
+# define __isa_port2addr	od_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __iounmap		generic_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_OD_H */
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/irq.c linux-2.4.21-bk12/arch/sh/overdrive/irq.c
--- linux-2.4.21-bk11/arch/sh/overdrive/irq.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/irq.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,192 @@
+/* 
+ * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * Looks after interrupts on the overdrive board.
+ *
+ * Bases on the IPR irq system
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "overdrive.h"
+
+struct od_data {
+	int overdrive_irq;
+	int irq_mask;
+};
+
+#define NUM_EXTERNAL_IRQS 16
+#define EXTERNAL_IRQ_NOT_IN_USE (-1)
+#define EXTERNAL_IRQ_NOT_ASSIGNED (-1)
+
+/*
+ * This table is used to determine what to program into the FPGA's CT register
+ * for the specified Linux IRQ.
+ *
+ * The irq_mask gives the interrupt number from the PCI board (PCI_Int(6:0))
+ * but is one greater than that because the because the FPGA treats 0
+ * as disabled, a value of 1 asserts PCI_Int0, and so on.
+ *
+ * The overdrive_irq specifies which of the eight interrupt sources generates
+ * that interrupt, and but is multiplied by four to give the bit offset into
+ * the CT register.
+ *
+ * The seven interrupts levels (SH4 IRL's) we have available here is hardwired
+ * by the EPLD. The assignments here of which PCI interrupt generates each
+ * level is arbitary.
+ */
+static struct od_data od_data_table[NUM_EXTERNAL_IRQS] = {
+	/*    overdrive_irq       , irq_mask */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},	/* 0 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, 7},	/* 1 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, 6},	/* 2 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},	/* 3 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, 5},	/* 4 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},	/* 5 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},	/* 6 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, 4},	/* 7 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},	/* 8 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},	/* 9 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, 3},	/* 10 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, 2},	/* 11 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},	/* 12 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, 1},	/* 13 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},	/* 14 */
+	{EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}	/* 15 */
+};
+
+static void set_od_data(int overdrive_irq, int irq)
+{
+	if (irq >= NUM_EXTERNAL_IRQS || irq < 0)
+		return;
+	od_data_table[irq].overdrive_irq = overdrive_irq << 2;
+}
+
+static void enable_od_irq(unsigned int irq);
+void disable_od_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_od_irq disable_od_irq
+
+static void mask_and_ack_od(unsigned int);
+static void end_od_irq(unsigned int irq);
+
+static unsigned int startup_od_irq(unsigned int irq)
+{
+	enable_od_irq(irq);
+	return 0;		/* never anything pending */
+}
+
+static struct hw_interrupt_type od_irq_type = {
+	"Overdrive-IRQ",
+	startup_od_irq,
+	shutdown_od_irq,
+	enable_od_irq,
+	disable_od_irq,
+	mask_and_ack_od,
+	end_od_irq
+};
+
+static void disable_od_irq(unsigned int irq)
+{
+	unsigned val, flags;
+	int overdrive_irq;
+	unsigned mask;
+
+	/* Not a valid interrupt */
+	if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
+		return;
+
+        /* Is is necessary to use a cli here? Would a spinlock not be 
+         * mroe efficient?
+         */
+	save_and_cli(flags);
+	overdrive_irq = od_data_table[irq].overdrive_irq;
+	if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) {
+		mask = ~(0x7 << overdrive_irq);
+		val = ctrl_inl(OVERDRIVE_INT_CT);
+		val &= mask;
+		ctrl_outl(val, OVERDRIVE_INT_CT);
+	}
+	restore_flags(flags);
+}
+
+static void enable_od_irq(unsigned int irq)
+{
+	unsigned val, flags;
+	int overdrive_irq;
+	unsigned mask;
+
+	/* Not a valid interrupt */
+	if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
+		return;
+
+	/* Set priority in OD back to original value */
+	save_and_cli(flags);
+	/* This one is not in use currently */
+	overdrive_irq = od_data_table[irq].overdrive_irq;
+	if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) {
+		val = ctrl_inl(OVERDRIVE_INT_CT);
+		mask = ~(0x7 << overdrive_irq);
+		val &= mask;
+		mask = od_data_table[irq].irq_mask << overdrive_irq;
+		val |= mask;
+		ctrl_outl(val, OVERDRIVE_INT_CT);
+	}
+	restore_flags(flags);
+}
+
+
+
+/* this functions sets the desired irq handler to be an overdrive type */
+static void __init make_od_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
+	irq_desc[irq].handler = &od_irq_type;
+	disable_od_irq(irq);
+}
+
+
+static void mask_and_ack_od(unsigned int irq)
+{
+	disable_od_irq(irq);
+}
+
+static void end_od_irq(unsigned int irq)
+{
+	enable_od_irq(irq);
+}
+
+void __init init_overdrive_irq(void)
+{
+	int i;
+
+	/* Disable all interrupts */
+	ctrl_outl(0, OVERDRIVE_INT_CT);
+
+	/* Update interrupt pin mode to use encoded interrupts */
+	i = ctrl_inw(INTC_ICR);
+	i &= ~INTC_ICR_IRLM;
+	ctrl_outw(i, INTC_ICR);
+
+	for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
+		if (od_data_table[i].irq_mask != EXTERNAL_IRQ_NOT_IN_USE) {
+			make_od_irq(i);
+		} else if (i != 15) {	// Cannot use imask on level 15
+			make_imask_irq(i);
+		}
+	}
+
+	/* Set up the interrupts */
+	set_od_data(OVERDRIVE_PCI_INTA, OVERDRIVE_PCI_IRQ1);
+	set_od_data(OVERDRIVE_PCI_INTB, OVERDRIVE_PCI_IRQ2);
+	set_od_data(OVERDRIVE_AUDIO_INT, OVERDRIVE_ESS_IRQ);
+}
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/led.c linux-2.4.21-bk12/arch/sh/overdrive/led.c
--- linux-2.4.21-bk11/arch/sh/overdrive/led.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/led.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/sh/overdrive/led.c
+ *
+ * Copyright (C) 1999 Stuart Menefy <stuart.menefy@st.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * This file contains an Overdrive specific LED feature.
+ */
+
+#include <linux/config.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include "overdrive.h"
+
+static void mach_led(int position, int value)
+{
+	unsigned long flags;
+	unsigned long reg;
+
+	save_and_cli(flags);
+	
+	reg = readl(OVERDRIVE_CTRL);
+	if (value) {
+		reg |= (1<<3);
+	} else {
+		reg &= ~(1<<3);
+	}
+	writel(reg, OVERDRIVE_CTRL);
+
+	restore_flags(flags);
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* acts like an actual heart beat -- ie thump-thump-pause... */
+void heartbeat_od(void)
+{
+	static unsigned cnt = 0, period = 0, dist = 0;
+
+	if (cnt == 0 || cnt == dist)
+		mach_led( -1, 1);
+	else if (cnt == 7 || cnt == dist+7)
+		mach_led( -1, 0);
+
+	if (++cnt > period) {
+		cnt = 0;
+		/* The hyperbolic function below modifies the heartbeat period
+		 * length in dependency of the current (5min) load. It goes
+		 * through the points f(0)=126, f(1)=86, f(5)=51,
+		 * f(inf)->30. */
+		period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
+		dist = period / 4;
+	}
+}
+#endif /* CONFIG_HEARTBEAT */
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/mach.c linux-2.4.21-bk12/arch/sh/overdrive/mach.c
--- linux-2.4.21-bk11/arch/sh/overdrive/mach.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/mach.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/sh/overdrive/mach.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Machine vector for the STMicroelectronics Overdrive
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+
+#include <asm/io_unknown.h>
+#include <asm/io_generic.h>
+#include <asm/io_od.h>
+
+void heartbeat_od(void);
+void setup_od(void);
+void init_overdrive_irq(void);
+void galileo_pcibios_init(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_od __initmv = {
+	mv_name:		"SH7750 Overdrive",
+
+	mv_nr_irqs:		48,
+
+	mv_inb:			od_inb,
+	mv_inw:			od_inw,
+	mv_inl:			od_inl,
+	mv_outb:		od_outb,
+	mv_outw:		od_outw,
+	mv_outl:		od_outl,
+
+	mv_inb_p:		od_inb_p,
+	mv_inw_p:		od_inw_p,
+	mv_inl_p:		od_inl_p,
+	mv_outb_p:		od_outb_p,
+	mv_outw_p:		od_outw_p,
+	mv_outl_p:		od_outl_p,
+
+	mv_insb:		od_insb,
+	mv_insw:		od_insw,
+	mv_insl:		od_insl,
+	mv_outsb:		od_outsb,
+	mv_outsw:		od_outsw,
+	mv_outsl:		od_outsl,
+
+	mv_readb:		generic_readb,
+	mv_readw:		generic_readw,
+	mv_readl:		generic_readl,
+	mv_writeb:		generic_writeb,
+	mv_writew:		generic_writew,
+	mv_writel:		generic_writel,
+
+	mv_ioremap:		generic_ioremap,
+	mv_iounmap:		generic_iounmap,
+
+	mv_isa_port2addr:	generic_isa_port2addr,
+
+	mv_init_arch:		setup_od,
+#ifdef CONFIG_PCI
+	mv_init_irq:		init_overdrive_irq,
+#endif
+#ifdef CONFIG_HEARTBEAT
+	mv_heartbeat:		heartbeat_od,
+#endif
+	mv_rtc_gettimeofday:	sh_rtc_gettimeofday,
+	mv_rtc_settimeofday:	sh_rtc_settimeofday,
+};
+
+ALIAS_MV(od)
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/overdrive.h linux-2.4.21-bk12/arch/sh/overdrive/overdrive.h
--- linux-2.4.21-bk11/arch/sh/overdrive/overdrive.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/overdrive.h	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,89 @@
+/* 
+ * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ */
+
+#include <linux/config.h>
+
+#ifndef __OVERDRIVE_H__
+#define __OVERDRIVE_H__
+
+#define OVERDRIVE_INT_CT 0xa3a00000
+#define OVERDRIVE_INT_DT 0xa3b00000
+
+#define OVERDRIVE_CTRL    0xa3000000
+
+/* Shoving all these bits into the same register is not a good idea. 
+ * As soon as I get a spare moment, I'll change the FPGA and put each 
+ * bit in a separate register
+ */
+
+#define VALID_CTRL_BITS		          0x1f
+
+#define ENABLE_RS232_MASK	  	  0x1e
+#define DISABLE_RS232_BIT		  0x01
+
+#define ENABLE_NMI_MASK			  0x1d
+#define DISABLE_NMI_BIT			  0x02
+
+#define RESET_PCI_MASK			  0x1b
+#define ENABLE_PCI_BIT			  0x04
+
+#define ENABLE_LED_MASK			  0x17
+#define DISABLE_LED_BIT			  0x08
+
+#define RESET_FPGA_MASK			  0x0f
+#define ENABLE_FPGA_BIT			  0x10
+
+
+#define FPGA_DCLK_ADDRESS           0xA3C00000
+
+#define FPGA_DATA        0x01	/*   W */
+#define FPGA_CONFDONE    0x02	/* R   */
+#define FPGA_NOT_STATUS  0x04	/* R   */
+#define FPGA_INITDONE    0x08	/* R   */
+
+#define FPGA_TIMEOUT     100000
+
+
+/* Interrupts for the overdrive. Note that these numbers have 
+ * nothing to do with the actual IRQ numbers they appear on, 
+ * this is all programmable. This is simply the position in the 
+ * INT_CT register.
+ */
+
+#define OVERDRIVE_PCI_INTA              0
+#define OVERDRIVE_PCI_INTB              1
+#define OVERDRIVE_PCI_INTC              2
+#define OVERDRIVE_PCI_INTD              3
+#define OVERDRIVE_GALILEO_INT           4
+#define OVERDRIVE_GALILEO_LOCAL_INT     5
+#define OVERDRIVE_AUDIO_INT             6
+#define OVERDRIVE_KEYBOARD_INT          7
+
+/* Which Linux IRQ should we assign to each interrupt source? */
+#define OVERDRIVE_PCI_IRQ1              2
+#ifdef CONFIG_HACKED_NE2K
+#define OVERDRIVE_PCI_IRQ2              7
+#else
+#define OVERDRIVE_PCI_IRQ2              2
+#undef OVERDRIVE_PCI_INTB 
+#define OVERDRIVE_PCI_INTB OVERDRIVE_PCI_INTA
+
+#endif
+
+/* Put the ESS solo audio chip on IRQ 4 */
+#define OVERDRIVE_ESS_IRQ               4
+
+/* Where the memory behind the PCI bus appears */
+#define PCI_DRAM_BASE   0xb7000000
+#define PCI_DRAM_SIZE (16*1024*1024)
+#define PCI_DRAM_FINISH (PCI_DRAM_BASE+PCI_DRAM_SIZE-1)
+
+/* Where the IO region appears in the memory */
+#define PCI_GTIO_BASE   0xb8000000
+
+#endif
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/pcidma.c linux-2.4.21-bk12/arch/sh/overdrive/pcidma.c
--- linux-2.4.21-bk11/arch/sh/overdrive/pcidma.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/pcidma.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,46 @@
+/* 
+ * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * Dynamic DMA mapping support.
+ *
+ * On the overdrive, we can only DMA from memory behind the PCI bus!
+ * this means that all DMA'able memory must come from there. 
+ * this restriction will not apply to later boards.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+			   dma_addr_t * dma_handle)
+{
+	void *ret;
+	int gfp = GFP_ATOMIC;
+
+        printk("BUG: pci_alloc_consistent() called - not yet supported\n");
+	/* We ALWAYS need DMA memory on the overdrive hardware,
+	 * due to it's extreme wierdness
+	 * Need to flush the cache here as well, since the memory
+	 * can still be seen through the cache!
+	 */
+	gfp |= GFP_DMA;
+	ret = (void *) __get_free_pages(gfp, get_order(size));
+
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		*dma_handle = virt_to_bus(ret);
+	}
+	return ret;
+}
+
+void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+			 void *vaddr, dma_addr_t dma_handle)
+{
+	free_pages((unsigned long) vaddr, get_order(size));
+}
diff -urN linux-2.4.21-bk11/arch/sh/overdrive/setup.c linux-2.4.21-bk12/arch/sh/overdrive/setup.c
--- linux-2.4.21-bk11/arch/sh/overdrive/setup.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/arch/sh/overdrive/setup.c	2003-07-17 02:52:28.000000000 -0700
@@ -0,0 +1,32 @@
+/*
+ * arch/sh/overdrive/setup.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * STMicroelectronics Overdrive Support.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+#include "overdrive.h"
+#include "fpga.h"
+
+/*
+ * Initialize the board
+ */
+int __init setup_od(void)
+{
+#ifdef CONFIG_PCI
+	init_overdrive_fpga();
+	galileo_init(); 
+#endif
+
+        /* Enable RS232 receive buffers */
+	writel(0x1e, OVERDRIVE_CTRL);
+}
diff -urN linux-2.4.21-bk11/arch/sh/stboards/setup.c linux-2.4.21-bk12/arch/sh/stboards/setup.c
--- linux-2.4.21-bk11/arch/sh/stboards/setup.c	2001-06-27 13:55:29.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh/stboards/setup.c	2003-07-17 02:52:28.000000000 -0700
@@ -48,3 +48,31 @@
 
 	return 0;
 }
+
+#ifdef CONFIG_PCI
+/*
+ * PCI based boards need a function that maps IRQ's to given PCI
+ * slots. This code is used by the st40 pci routines in arch/sh/kernel
+ */
+ 
+int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+    	switch (slot) {
+#ifdef CONFIG_SH_STB1_HARP
+	case 2:		/*This is the PCI slot on the */
+		return HARP_PCI_IRQ;
+	case 1:		/* this is the bridge */
+		return HARP_BRIDGE_IRQ;
+#elif defined(CONFIG_SH_STB1_OVERDRIVE)
+	case 1:
+	case 2:
+	case 3:
+		return slot - 1;
+#else
+#error Unknown board
+#endif
+	default:
+		return -1;
+	}
+}
+#endif
diff -urN linux-2.4.21-bk11/arch/sh64/config.in linux-2.4.21-bk12/arch/sh64/config.in
--- linux-2.4.21-bk11/arch/sh64/config.in	2003-07-17 02:52:24.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh64/config.in	2003-07-17 02:52:28.000000000 -0700
@@ -198,7 +198,7 @@
    bool 'Network device support' CONFIG_NETDEVICES
    if [ "$CONFIG_NETDEVICES" = "y" ]; then
       source drivers/net/Config.in
-      if [ "$CONFIG_ATM" = "y" ]; then
+      if [ "$CONFIG_ATM" != "n" ]; then
          source drivers/atm/Config.in
       fi
    fi
diff -urN linux-2.4.21-bk11/arch/sh64/defconfig linux-2.4.21-bk12/arch/sh64/defconfig
--- linux-2.4.21-bk11/arch/sh64/defconfig	2003-07-17 02:52:24.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh64/defconfig	2003-07-17 02:52:28.000000000 -0700
@@ -36,6 +36,9 @@
 # CONFIG_CPU_SUBTYPE_SH5_103 is not set
 CONFIG_LITTLE_ENDIAN=y
 # CONFIG_BIG_ENDIAN is not set
+# CONFIG_SH64_FPU_DENORM_FLUSH is not set
+CONFIG_SH64_PGTABLE_2_LEVEL=y
+# CONFIG_SH64_PGTABLE_3_LEVEL is not set
 
 #
 # Memory options
@@ -155,6 +158,11 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
 # CONFIG_BLK_DEV_IDE_MODES is not set
 # CONFIG_BLK_DEV_HD is not set
 
@@ -295,6 +303,7 @@
 # CONFIG_PPDEV is not set
 CONFIG_HEARTBEAT=y
 CONFIG_HDSP253_LED=y
+CONFIG_SH_DMA=y
 # CONFIG_PSMOUSE is not set
 
 #
@@ -306,6 +315,7 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
+# CONFIG_QFMT_V2 is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -315,6 +325,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
@@ -364,6 +375,7 @@
 # CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_DIRECTIO is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 # CONFIG_NFSD_V3 is not set
@@ -465,3 +477,15 @@
 # CONFIG_DEBUG_KERNEL_WITH_GDB_STUB is not set
 # CONFIG_SH64_PAGE_TABLE_AUDIT is not set
 # CONFIG_SH64_PROC_TLB is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+# CONFIG_ZLIB_INFLATE is not set
+# CONFIG_ZLIB_DEFLATE is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
diff -urN linux-2.4.21-bk11/arch/sh64/mach-cayman/irq.c linux-2.4.21-bk12/arch/sh64/mach-cayman/irq.c
--- linux-2.4.21-bk11/arch/sh64/mach-cayman/irq.c	2003-07-17 02:52:24.000000000 -0700
+++ linux-2.4.21-bk12/arch/sh64/mach-cayman/irq.c	2003-07-17 02:52:28.000000000 -0700
@@ -14,6 +14,7 @@
 
 #include <linux/config.h>
 #include <asm/irq.h>
+#include <asm/page.h>
 #include <asm/io.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
@@ -37,13 +38,15 @@
 }
 
 static struct irqaction cayman_action_smsc = {
-	cayman_interrupt_smsc, SA_INTERRUPT, 0, "Cayman SMSC Mux",
-	NULL, NULL
+	.name		= "Cayman SMSC Mux",
+	.handler	= cayman_interrupt_smsc,
+	.flags		= SA_INTERRUPT,
 };
 
 static struct irqaction cayman_action_pci2 = {
-	cayman_interrupt_pci2, SA_INTERRUPT, 0, "Cayman PCI2 Mux",
-	NULL, NULL
+	.name		= "Cayman PCI2 Mux",
+	.handler	= cayman_interrupt_pci2,
+	.flags		= SA_INTERRUPT,
 };
 
 static void enable_cayman_irq(unsigned int irq)
@@ -87,10 +90,8 @@
 
 static void end_cayman_irq(unsigned int irq)
 {
-	/* SIM: Note when we upgrade to the new kernel, this will need to be aded:
-	 * if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-	 */
-	enable_cayman_irq(irq);
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_cayman_irq(irq);
 }
 
 static unsigned int startup_cayman_irq(unsigned int irq)
@@ -105,13 +106,13 @@
 }
 
 struct hw_interrupt_type cayman_irq_type = {
-	"Cayman-IRQ",
-	startup_cayman_irq,
-	shutdown_cayman_irq,
-	enable_cayman_irq,
-	disable_cayman_irq,
-	ack_cayman_irq,
-	end_cayman_irq
+	.typename	= "Cayman-IRQ",
+	.startup	= startup_cayman_irq,
+	.shutdown	= shutdown_cayman_irq,
+	.enable		= enable_cayman_irq,
+	.disable	= disable_cayman_irq,
+	.ack		= ack_cayman_irq,
+	.end		= end_cayman_irq,
 };
 
 int cayman_irq_demux(int evt)
@@ -158,14 +159,15 @@
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
 int cayman_irq_describe(char* p, int irq)
 {
-  if (irq < NR_INTC_IRQS) 
-    return intc_irq_describe(p, irq);
-  else if (irq < NR_INTC_IRQS + 8)
-    return sprintf(p, "(SMSC %d)", irq - NR_INTC_IRQS);
-  else if ((irq >= NR_INTC_IRQS + 24) && (irq < NR_INTC_IRQS + 32))
-    return sprintf(p, "(PCI2 %d)", irq - (NR_INTC_IRQS + 24)); 
-  else
-    return 0;
+	if (irq < NR_INTC_IRQS) {
+		return intc_irq_describe(p, irq);
+	} else if (irq < NR_INTC_IRQS + 8) {
+		return sprintf(p, "(SMSC %d)", irq - NR_INTC_IRQS);
+	} else if ((irq >= NR_INTC_IRQS + 24) && (irq < NR_INTC_IRQS + 32)) {
+		return sprintf(p, "(PCI2 %d)", irq - (NR_INTC_IRQS + 24)); 
+	}
+
+	return 0;
 }
 #endif
 
@@ -174,8 +176,9 @@
 	int i;
 
 	epld_virt = onchip_remap(EPLD_BASE, 1024, "EPLD");
-	if (epld_virt == NULL) {
-		panic("Unable to remap EPLD\n");
+	if (!epld_virt) {
+		printk(KERN_ERR "Cayman IRQ: Unable to remap EPLD\n");
+		return;
 	}
 
 	for (i=0; i<NR_EXT_IRQS; i++) {
diff -urN linux-2.4.21-bk11/arch/sparc64/kernel/head.S linux-2.4.21-bk12/arch/sparc64/kernel/head.S
--- linux-2.4.21-bk11/arch/sparc64/kernel/head.S	2003-06-13 07:51:32.000000000 -0700
+++ linux-2.4.21-bk12/arch/sparc64/kernel/head.S	2003-07-17 02:52:28.000000000 -0700
@@ -66,7 +66,7 @@
 sparc_ramdisk_size:
         .word   0
         .xword  reboot_command
-	.xword	bootstr_len
+	.xword	bootstr_info
 	.word	_end
 
 	/* We must be careful, 32-bit OpenBOOT will get confused if it
@@ -742,8 +742,9 @@
 
 	.data
 	.align	8
-	.globl	prom_tba
+	.globl	prom_tba, tlb_type
 prom_tba:	.xword	0
+tlb_type:	.word	0	/* Must NOT end up in BSS */
 	.section	".fixup",#alloc,#execinstr
 	.globl	__ret_efault
 __ret_efault:
diff -urN linux-2.4.21-bk11/arch/sparc64/mm/init.c linux-2.4.21-bk12/arch/sparc64/mm/init.c
--- linux-2.4.21-bk11/arch/sparc64/mm/init.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.21-bk12/arch/sparc64/mm/init.c	2003-07-17 02:52:28.000000000 -0700
@@ -46,8 +46,6 @@
 /* Ugly, but necessary... -DaveM */
 unsigned long phys_base;
 
-enum ultra_tlb_layout tlb_type = spitfire;
-
 /* get_new_mmu_context() uses "cache + 1".  */
 spinlock_t ctx_alloc_lock = SPIN_LOCK_UNLOCKED;
 unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
diff -urN linux-2.4.21-bk11/arch/sparc64/prom/bootstr.c linux-2.4.21-bk12/arch/sparc64/prom/bootstr.c
--- linux-2.4.21-bk11/arch/sparc64/prom/bootstr.c	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.21-bk12/arch/sparc64/prom/bootstr.c	2003-07-17 02:52:28.000000000 -0700
@@ -15,16 +15,22 @@
  */
 
 #define BARG_LEN  256
-int bootstr_len = BARG_LEN;
-static int bootstr_valid = 0;
-static char bootstr_buf[BARG_LEN] = { 0 };
+struct {
+	int bootstr_len;
+	int bootstr_valid;
+	char bootstr_buf[BARG_LEN];
+} bootstr_info = {
+	.bootstr_len = BARG_LEN,
+};
 
 char * __init
 prom_getbootargs(void)
 {
 	/* This check saves us from a panic when bootfd patches args. */
-	if (bootstr_valid) return bootstr_buf;
-	prom_getstring(prom_chosen_node, "bootargs", bootstr_buf, BARG_LEN);
-	bootstr_valid = 1;
-	return bootstr_buf;
+	if (bootstr_info.bootstr_valid)
+		return bootstr_info.bootstr_buf;
+	prom_getstring(prom_chosen_node, "bootargs",
+		       bootstr_info.bootstr_buf, BARG_LEN);
+	bootstr_info.bootstr_valid = 1;
+	return bootstr_info.bootstr_buf;
 }
diff -urN linux-2.4.21-bk11/drivers/block/ll_rw_blk.c linux-2.4.21-bk12/drivers/block/ll_rw_blk.c
--- linux-2.4.21-bk11/drivers/block/ll_rw_blk.c	2003-07-17 02:52:24.000000000 -0700
+++ linux-2.4.21-bk12/drivers/block/ll_rw_blk.c	2003-07-17 02:52:29.000000000 -0700
@@ -458,6 +458,7 @@
   
  	INIT_LIST_HEAD(&q->rq.free);
 	q->rq.count = 0;
+	q->rq.pending[READ] = q->rq.pending[WRITE] = 0;
 	q->nr_requests = 0;
 
 	si_meminfo(&si);
@@ -549,18 +550,35 @@
 static struct request *get_request(request_queue_t *q, int rw)
 {
 	struct request *rq = NULL;
-	struct request_list *rl;
+	struct request_list *rl = &q->rq;
 
-	rl = &q->rq;
-	if (!list_empty(&rl->free) && !blk_oversized_queue(q)) {
+	if (blk_oversized_queue(q)) {
+		int rlim = q->nr_requests >> 5;
+
+		if (rlim < 4)
+			rlim = 4;
+
+		/*
+		 * if its a write, or we have more than a handful of reads
+		 * pending, bail out
+		 */
+		if ((rw == WRITE) || (rw == READ && rl->pending[READ] > rlim))
+			return NULL;
+		if (blk_oversized_queue_reads(q))
+			return NULL;
+	}
+	
+	if (!list_empty(&rl->free)) {
 		rq = blkdev_free_rq(&rl->free);
 		list_del(&rq->queue);
 		rl->count--;
+		rl->pending[rw]++;
 		rq->rq_status = RQ_ACTIVE;
 		rq->cmd = rw;
 		rq->special = NULL;
 		rq->q = q;
 	}
+
 	return rq;
 }
 
@@ -866,13 +884,25 @@
 	 * assume it has free buffers and check waiters
 	 */
 	if (q) {
+		struct request_list *rl = &q->rq;
 		int oversized_batch = 0;
 
 		if (q->can_throttle)
 			oversized_batch = blk_oversized_queue_batch(q);
-		q->rq.count++;
-		list_add(&req->queue, &q->rq.free);
-		if (q->rq.count >= q->batch_requests && !oversized_batch) {
+		rl->count++;
+		/*
+		 * paranoia check
+		 */
+		if (req->cmd == READ || req->cmd == WRITE)
+			rl->pending[req->cmd]--;
+		if (rl->pending[READ] > q->nr_requests)
+			printk("blk: reads: %u\n", rl->pending[READ]);
+		if (rl->pending[WRITE] > q->nr_requests)
+			printk("blk: writes: %u\n", rl->pending[WRITE]);
+		if (rl->pending[READ] + rl->pending[WRITE] > q->nr_requests)
+			printk("blk: r/w: %u + %u > %u\n", rl->pending[READ], rl->pending[WRITE], q->nr_requests);
+		list_add(&req->queue, &rl->free);
+		if (rl->count >= q->batch_requests && !oversized_batch) {
 			smp_mb();
 			if (waitqueue_active(&q->wait_for_requests))
 				wake_up(&q->wait_for_requests);
@@ -947,7 +977,7 @@
 static int __make_request(request_queue_t * q, int rw,
 				  struct buffer_head * bh)
 {
-	unsigned int sector, count;
+	unsigned int sector, count, sync;
 	int max_segments = MAX_SEGMENTS;
 	struct request * req, *freereq = NULL;
 	int rw_ahead, max_sectors, el_ret;
@@ -958,6 +988,7 @@
 
 	count = bh->b_size >> 9;
 	sector = bh->b_rsector;
+	sync = test_and_clear_bit(BH_Sync, &bh->b_state);
 
 	rw_ahead = 0;	/* normal case; gets changed below for READA */
 	switch (rw) {
@@ -1124,6 +1155,8 @@
 		blkdev_release_request(freereq);
 	if (should_wake)
 		get_request_wait_wakeup(q, rw);
+	if (sync)
+		__generic_unplug_device(q);
 	spin_unlock_irq(&io_request_lock);
 	return 0;
 end_io:
diff -urN linux-2.4.21-bk11/drivers/video/radeonfb.c linux-2.4.21-bk12/drivers/video/radeonfb.c
--- linux-2.4.21-bk11/drivers/video/radeonfb.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/drivers/video/radeonfb.c	2003-07-17 02:52:29.000000000 -0700
@@ -902,6 +902,8 @@
 static int radeonfb_pci_register (struct pci_dev *pdev,
                                  const struct pci_device_id *ent);
 static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev);
+static int radeon_do_set_var (struct fb_var_screeninfo *var, int con,
+                             int real, struct fb_info *info);
 
 #ifdef CONFIG_PMAC_PBOOK
 static int radeon_sleep_notify(struct pmu_sleep_notifier *self, int when);
@@ -2077,7 +2079,7 @@
 	rinfo->bpp = disp->var.bits_per_pixel;
 
 	/* Apply that dawn mode ! */
-	radeonfb_set_var(&disp->var, -1, info);
+	radeon_do_set_var(&disp->var, -1, 0, info);
 
 	return 0;
 }
@@ -2288,9 +2290,8 @@
 }
 
 
-
-static int radeonfb_set_var (struct fb_var_screeninfo *var, int con,
-                             struct fb_info *info)
+static int radeon_do_set_var (struct fb_var_screeninfo *var, int con,
+                             int real, struct fb_info *info)
 {
         struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
         struct display *disp;
@@ -2457,9 +2458,10 @@
 	        v.accel_flags &= ~FB_ACCELF_TEXT;
         
         memcpy (&disp->var, &v, sizeof (v));
-        
-        radeon_load_video_mode (rinfo, &v);
-	if (accel) {
+
+        if (real)
+        	radeon_load_video_mode (rinfo, &v);
+	if (accel && real) {
 		if (radeon_engine_init(rinfo) < 0) {
                         var->accel_flags &= ~FB_ACCELF_TEXT;
 			goto try_again;
@@ -2477,12 +2479,18 @@
                 if (info && info->changevar && con >= 0)
                         info->changevar(con);
         }
-                
-        do_install_cmap(con, info);
+
+        if (real)        
+        	do_install_cmap(con, info);
   
         return 0;
 }
 
+static int radeonfb_set_var (struct fb_var_screeninfo *var, int con,
+                             struct fb_info *info)
+{
+	return radeon_do_set_var(var, con, 1, info);
+}
 
 
 static int radeonfb_get_cmap (struct fb_cmap *cmap, int kspc, int con,
diff -urN linux-2.4.21-bk11/fs/Makefile linux-2.4.21-bk12/fs/Makefile
--- linux-2.4.21-bk11/fs/Makefile	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/Makefile	2003-07-17 02:52:30.000000000 -0700
@@ -38,8 +38,8 @@
 subdir-$(CONFIG_BFS_FS)		+= bfs
 subdir-$(CONFIG_ISO9660_FS)	+= isofs
 subdir-$(CONFIG_DEVFS_FS)	+= devfs
+subdir-$(CONFIG_HFSPLUS_FS)	+= hfsplus # Before hfs to find wrapped HFS+
 subdir-$(CONFIG_HFS_FS)		+= hfs
-subdir-$(CONFIG_HFSPLUS_FS)	+= hfsplus
 subdir-$(CONFIG_VXFS_FS)	+= freevxfs
 subdir-$(CONFIG_NFS_FS)		+= nfs
 subdir-$(CONFIG_NFSD)		+= nfsd
diff -urN linux-2.4.21-bk11/fs/buffer.c linux-2.4.21-bk12/fs/buffer.c
--- linux-2.4.21-bk11/fs/buffer.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/buffer.c	2003-07-17 02:52:30.000000000 -0700
@@ -1142,6 +1142,7 @@
 	bh = getblk(dev, block, size);
 	if (buffer_uptodate(bh))
 		return bh;
+	set_bit(BH_Sync, &bh->b_state);
 	ll_rw_block(READ, 1, &bh);
 	wait_on_buffer(bh);
 	if (buffer_uptodate(bh))
diff -urN linux-2.4.21-bk11/fs/hfsplus/bfind.c linux-2.4.21-bk12/fs/hfsplus/bfind.c
--- linux-2.4.21-bk11/fs/hfsplus/bfind.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/bfind.c	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001
  * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  * Search routines for btrees
  */
@@ -122,6 +123,68 @@
 	return 0;
 }
 
+int hfsplus_btree_move(struct hfsplus_find_data *fd, int cnt)
+{
+	struct hfsplus_btree *tree;
+	hfsplus_bnode *bnode;
+	int idx, res = 0;
+	u16 off, len, keylen;
+
+	bnode = fd->bnode;
+	tree = bnode->tree;
+
+	if (cnt < -0xFFFF || cnt > 0xFFFF)
+		return -EINVAL;
+
+	if (cnt < 0) {
+		cnt = -cnt;
+		while (cnt > fd->record) {
+			cnt -= fd->record + 1;
+			fd->record = bnode->num_recs - 1;
+			idx = bnode->prev;
+			if (!idx) {
+				res = -ENOENT;
+				goto out;
+			}
+			hfsplus_put_bnode(bnode);
+			bnode = hfsplus_find_bnode(tree, idx);
+			if (!bnode) {
+				res = -EIO;
+				goto out;
+			}
+		}
+		fd->record -= cnt;
+	} else {
+		while (cnt >= bnode->num_recs - fd->record) {
+			cnt -= bnode->num_recs - fd->record;
+			fd->record = 0;
+			idx = bnode->next;
+			if (!idx) {
+				res = -ENOENT;
+				goto out;
+			}
+			hfsplus_put_bnode(bnode);
+			bnode = hfsplus_find_bnode(tree, idx);
+			if (!bnode) {
+				res = -EIO;
+				goto out;
+			}
+		}
+		fd->record += cnt;
+	}
+
+	len = hfsplus_brec_lenoff(bnode, fd->record, &off);
+	keylen = hfsplus_brec_keylen(bnode, fd->record);
+	fd->keyoffset = off;
+	fd->keylength = keylen;
+	fd->entryoffset = off + keylen;
+	fd->entrylength = len - keylen;
+	hfsplus_bnode_readbytes(bnode, fd->key, off, keylen);
+out:
+	fd->bnode = bnode;
+	return res;
+}
+
 int hfsplus_find_init(hfsplus_btree *tree, struct hfsplus_find_data *fd)
 {
 	fd->tree = tree;
diff -urN linux-2.4.21-bk11/fs/hfsplus/bnode.c linux-2.4.21-bk12/fs/hfsplus/bnode.c
--- linux-2.4.21-bk11/fs/hfsplus/bnode.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/bnode.c	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001
  * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  * Handle basic btree node operations
  */
diff -urN linux-2.4.21-bk11/fs/hfsplus/brec.c linux-2.4.21-bk12/fs/hfsplus/brec.c
--- linux-2.4.21-bk11/fs/hfsplus/brec.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/brec.c	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001
  * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  * Handle individual btree records
  */
@@ -10,26 +11,6 @@
 #include "hfsplus_fs.h"
 #include "hfsplus_raw.h"
 
-/* Get the offset of the given record in the given node */
-u16 hfsplus_brec_off(hfsplus_bnode *node, u16 rec)
-{
-	u16 dataoff;
-
-	dataoff = node->tree->node_size - (rec + 1) * 2;
-	return hfsplus_bnode_read_u16(node, dataoff);
-}
-
-/* Get the length of the given record in the given node */
-u16 hfsplus_brec_len(hfsplus_bnode *node, u16 rec)
-{
-	u16 retval[2];
-	u16 dataoff;
-
-	dataoff = node->tree->node_size - (rec + 2) * 2;
-	hfsplus_bnode_readbytes(node, retval, dataoff, 4);
-	return be16_to_cpu(retval[0]) - be16_to_cpu(retval[1]);
-}
-
 /* Get the length and offset of the given record in the given node */
 u16 hfsplus_brec_lenoff(hfsplus_bnode *node, u16 rec, u16 *off)
 {
@@ -42,20 +23,6 @@
 	return be16_to_cpu(retval[0]) - *off;
 }
 
-/* Copy a record from a node into a buffer, return the actual length */
-u16 hfsplus_brec_data(hfsplus_bnode *node, u16 rec, char *buf,
-			   u16 len)
-{
-	u16 recoff, reclen, cplen;
-
-	reclen = hfsplus_brec_lenoff(node, rec, &recoff);
-	if (!reclen)
-		return 0;
-	cplen = (reclen>len) ? len : reclen;
-	hfsplus_bnode_readbytes(node, buf, recoff, cplen);
-	return reclen;
-}
-
 /* Get the length of the key from a keyed record */
 u16 hfsplus_brec_keylen(hfsplus_bnode *node, u16 rec)
 {
@@ -70,7 +37,7 @@
 	   !(node->tree->attributes & HFSPLUS_TREE_VAR_NDXKEY_SIZE)) {
 		retval = node->tree->max_key_len;
 	} else {
-		recoff = hfsplus_brec_off(node, rec);
+		recoff = hfsplus_bnode_read_u16(node, node->tree->node_size - (rec + 1) * 2);
 		if (!recoff)
 			return 0;
 		hfsplus_bnode_readbytes(node, buf, recoff, klsz);
@@ -81,22 +48,3 @@
 	}
 	return (retval + klsz + 1) & 0xFFFE;
 }
-
-/* Get a copy of the key of the given record, returns real key length */
-u16 hfsplus_brec_key(hfsplus_bnode *node, u16 rec, void *buf,
-			  u16 len)
-{
-	u16 recoff, reclen, keylen, tocopy;
-
-	reclen = hfsplus_brec_lenoff(node, rec, &recoff);
-	keylen = hfsplus_brec_keylen(node, rec);
-	if (!reclen || !keylen)
-		return 0;
-	if (keylen > reclen) {
-		printk("HFS+-fs: corrupt key length in B*Tree (%d,%d,%d,%d,%d)\n", node->this, rec, reclen, keylen, recoff);
-		return 0;
-	}
-	tocopy = (len > keylen) ? keylen : len;
-	hfsplus_bnode_readbytes(node, buf, recoff, tocopy);
-	return keylen;
-}
diff -urN linux-2.4.21-bk11/fs/hfsplus/btiter.c linux-2.4.21-bk12/fs/hfsplus/btiter.c
--- linux-2.4.21-bk11/fs/hfsplus/btiter.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/btiter.c	1969-12-31 16:00:00.000000000 -0800
@@ -1,72 +0,0 @@
-/*
- *  linux/fs/hfsplus/btiter.c
- *
- * Copyright (C) 2001
- * Brad Boyer (flar@allandria.com)
- *
- * Iterators for btrees
- */
-
-#include "hfsplus_fs.h"
-
-int hfsplus_btiter_move(struct hfsplus_find_data *fd, int cnt)
-{
-	struct hfsplus_btree *tree;
-	hfsplus_bnode *bnode;
-	int idx, res = 0;
-	u16 off, len, keylen;
-
-	bnode = fd->bnode;
-	tree = bnode->tree;
-
-	if (cnt < -0xFFFF || cnt > 0xFFFF)
-		return -EINVAL;
-
-	if (cnt < 0) {
-		cnt = -cnt;
-		while (cnt > fd->record) {
-			cnt -= fd->record + 1;
-			fd->record = bnode->num_recs - 1;
-			idx = bnode->prev;
-			if (!idx) {
-				res = -ENOENT;
-				goto out;
-			}
-			hfsplus_put_bnode(bnode);
-			bnode = hfsplus_find_bnode(tree, idx);
-			if (!bnode) {
-				res = -EIO;
-				goto out;
-			}
-		}
-		fd->record -= cnt;
-	} else {
-		while (cnt >= bnode->num_recs - fd->record) {
-			cnt -= bnode->num_recs - fd->record;
-			fd->record = 0;
-			idx = bnode->next;
-			if (!idx) {
-				res = -ENOENT;
-				goto out;
-			}
-			hfsplus_put_bnode(bnode);
-			bnode = hfsplus_find_bnode(tree, idx);
-			if (!bnode) {
-				res = -EIO;
-				goto out;
-			}
-		}
-		fd->record += cnt;
-	}
-
-	len = hfsplus_brec_lenoff(bnode, fd->record, &off);
-	keylen = hfsplus_brec_keylen(bnode, fd->record);
-	fd->keyoffset = off;
-	fd->keylength = keylen;
-	fd->entryoffset = off + keylen;
-	fd->entrylength = len - keylen;
-	hfsplus_bnode_readbytes(bnode, fd->key, off, keylen);
-out:
-	fd->bnode = bnode;
-	return res;
-}
diff -urN linux-2.4.21-bk11/fs/hfsplus/btree.c linux-2.4.21-bk12/fs/hfsplus/btree.c
--- linux-2.4.21-bk11/fs/hfsplus/btree.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/btree.c	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001
  * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  * Handle opening/closing btree
  */
diff -urN linux-2.4.21-bk11/fs/hfsplus/catalog.c linux-2.4.21-bk12/fs/hfsplus/catalog.c
--- linux-2.4.21-bk11/fs/hfsplus/catalog.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/catalog.c	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001
  * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  * Handling of catalog records
  */
@@ -71,6 +72,9 @@
 			folder->attribute_mod_date = folder->access_date = 
 			hfsp_now2mt();
 		hfsplus_set_perms(inode, &folder->permissions);
+		if (inode == HFSPLUS_SB(inode->i_sb).hidden_dir)
+			/* invisible and namelocked */
+			folder->user_info.frFlags = cpu_to_be16(0x5000);
 		return sizeof(*folder);
 	} else {
 		hfsplus_cat_file *file;
@@ -82,9 +86,11 @@
 		file->create_date = file->content_mod_date =
 			file->attribute_mod_date = file->access_date =
 			hfsp_now2mt();
-		if (cnid == inode->i_ino)
+		if (cnid == inode->i_ino) {
 			hfsplus_set_perms(inode, &file->permissions);
-		else {
+			file->user_info.fdType = cpu_to_be32(HFSPLUS_SB(inode->i_sb).type);
+			file->user_info.fdCreator = cpu_to_be32(HFSPLUS_SB(inode->i_sb).creator);
+		} else {
 			file->user_info.fdType = cpu_to_be32(HFSP_HARDLINK_TYPE);
 			file->user_info.fdCreator = cpu_to_be32(HFSP_HFSPLUS_CREATOR);
 			file->user_info.fdFlags = cpu_to_be16(0x100);
diff -urN linux-2.4.21-bk11/fs/hfsplus/dir.c linux-2.4.21-bk12/fs/hfsplus/dir.c
--- linux-2.4.21-bk11/fs/hfsplus/dir.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/dir.c	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001
  * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  * Handling of directories
  */
@@ -143,7 +144,7 @@
 	default:
 		if (filp->f_pos >= inode->i_size)
 			goto out;
-		err = hfsplus_btiter_move(&fd, filp->f_pos - 1);
+		err = hfsplus_btree_move(&fd, filp->f_pos - 1);
 		if (err)
 			goto out;
 	}
@@ -190,7 +191,7 @@
 		filp->f_pos++;
 		if (filp->f_pos >= inode->i_size)
 			goto out;
-		err = hfsplus_btiter_move(&fd, 1);
+		err = hfsplus_btree_move(&fd, 1);
 		if (err)
 			goto out;
 	}
@@ -236,11 +237,10 @@
 
 int hfsplus_create(struct inode *dir, struct dentry *dentry, int mode)
 {
-	struct super_block *sb = dir->i_sb;
 	struct inode *inode;
 	int res;
 
-	inode = hfsplus_new_inode(sb, mode);
+	inode = hfsplus_new_inode(dir->i_sb, mode);
 	if (!inode)
 		return -ENOSPC;
 
@@ -355,13 +355,10 @@
 
 int hfsplus_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
-	struct super_block *sb;
 	struct inode *inode;
 	int res;
 
-	sb = dir->i_sb;
-	inode = dentry->d_inode;
-	inode = hfsplus_new_inode(sb, S_IFDIR | mode);
+	inode = hfsplus_new_inode(dir->i_sb, S_IFDIR | mode);
 	if (!inode)
 		return -ENOSPC;
 
@@ -463,9 +460,11 @@
 			return res;
 	}
 
-	res = hfsplus_rename_cat(old_dentry->d_inode->i_ino,
+	res = hfsplus_rename_cat((u32)(unsigned long)old_dentry->d_fsdata,
 				 old_dir, &old_dentry->d_name,
 				 new_dir, &new_dentry->d_name);
+	if (!res)
+		new_dentry->d_fsdata = old_dentry->d_fsdata;
 	return res;
 }
 
diff -urN linux-2.4.21-bk11/fs/hfsplus/extents.c linux-2.4.21-bk12/fs/hfsplus/extents.c
--- linux-2.4.21-bk11/fs/hfsplus/extents.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/extents.c	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001
  * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  * Handling of Extents both in catalog and extents overflow trees
  */
@@ -49,7 +50,7 @@
 	key->ext.pad = 0;
 }
 
-static int hfsplus_find_extent(hfsplus_extent *extent, u32 off)
+static u32 hfsplus_find_extent(hfsplus_extent *extent, u32 off)
 {
 	int i;
 	u32 count;
@@ -85,30 +86,26 @@
 int hfsplus_get_block(struct inode *inode, sector_t iblock,
 		      struct buffer_head *bh_result, int create)
 {
-	struct super_block *s;
+	struct super_block *sb;
 	hfsplus_extent_rec ext_entry;
 	struct hfsplus_find_data fd;
-	unsigned long ino;
 	int err = -EIO;
 	u32 ablock, dblock = 0;
 
-	ino = inode->i_ino;
-	s = inode->i_sb;
+	sb = inode->i_sb;
 
 	/* Convert inode block to disk allocation block */
 	ablock = iblock;
 
 	if (ablock >= HFSPLUS_I(inode).total_blocks) {
-		if (ablock > HFSPLUS_I(inode).total_blocks || !create) {
-			BUG();
+		if (ablock > HFSPLUS_I(inode).total_blocks || !create)
 			return -EIO;
-		}
 		if (ablock >= HFSPLUS_I(inode).alloc_blocks) {
 			err = hfsplus_extend_file(inode);
 			if (err)
 				return err;
 		}
-		HFSPLUS_I(inode).mmu_private += s->s_blocksize;
+		HFSPLUS_I(inode).mmu_private += sb->s_blocksize;
 		HFSPLUS_I(inode).total_blocks++;
 		mark_inode_dirty(inode);
 	} else
@@ -117,27 +114,23 @@
 	if (ablock < HFSPLUS_I(inode).extent_blocks) {
 		dblock = hfsplus_find_extent(HFSPLUS_I(inode).extents, ablock);
 	} else {
-		hfsplus_find_init(HFSPLUS_SB(s).ext_tree, &fd);
-		hfsplus_fill_ext_key(fd.search_key, ino, ablock, HFSPLUS_IS_RSRC(inode) ?
+		hfsplus_find_init(HFSPLUS_SB(sb).ext_tree, &fd);
+		hfsplus_fill_ext_key(fd.search_key, inode->i_ino, ablock, HFSPLUS_IS_RSRC(inode) ?
 				     HFSPLUS_TYPE_RSRC : HFSPLUS_TYPE_DATA);
 		err = hfsplus_find_extentry(&fd, ext_entry);
 		if (!err)
 			dblock = hfsplus_find_extent(ext_entry, ablock -
 						    be32_to_cpu(fd.key->ext.start_block));
 		hfsplus_find_exit(&fd);
-		if (err) {
-			BUG();
+		if (err)
 			return err;
-		}
 	}
 
-	if (!dblock) {
-		BUG();
+	if (!dblock)
 		return -EIO;
-	}
 	dprint(DBG_EXTENT, "get_block(%lu): %lu - %u\n", inode->i_ino, iblock, dblock);
 
-	map_bh(bh_result, s, dblock + HFSPLUS_SB(s).blockoffset);
+	map_bh(bh_result, sb, dblock + HFSPLUS_SB(sb).blockoffset);
 	if (create)
 		set_buffer_new(bh_result);
 	return 0;
diff -urN linux-2.4.21-bk11/fs/hfsplus/hfsplus_fs.h linux-2.4.21-bk12/fs/hfsplus/hfsplus_fs.h
--- linux-2.4.21-bk11/fs/hfsplus/hfsplus_fs.h	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/hfsplus_fs.h	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 1999
  * Brad Boyer (flar@pants.nu)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  */
 
@@ -12,8 +13,6 @@
 #include <linux/fs.h>
 #include <linux/version.h>
 #include "hfsplus_raw.h"
-#include "hfsplus_fs_sb.h"
-#include "hfsplus_fs_i.h"
 
 #define DBG_BNODE_REFS	0x00000001
 #define DBG_BNODE_MOD	0x00000002
@@ -111,6 +110,88 @@
 #define HFSPLUS_BNODE_DIRTY	3
 #define HFSPLUS_BNODE_DELETED	4
 
+/*
+ * HFS+ superblock info (built from Volume Header on disk)
+ */
+
+struct hfsplus_vh;
+struct hfsplus_btree;
+
+struct hfsplus_sb_info {
+	struct buffer_head *s_vhbh;
+	struct hfsplus_vh *s_vhdr;
+	struct hfsplus_btree *ext_tree;
+	struct hfsplus_btree *cat_tree;
+	struct hfsplus_btree *attr_tree;
+	struct inode *alloc_file;
+	struct inode *hidden_dir;
+
+	/* Runtime variables */
+	u32 blockoffset;
+	u32 sect_count;
+	//int a2b_shift;
+
+	/* Stuff in host order from Vol Header */
+	u32 total_blocks;
+	u32 free_blocks;
+	u32 next_alloc;
+	u32 next_cnid;
+	u32 file_count;
+	u32 folder_count;
+
+	/* Config options */
+	u32 creator;
+	u32 type;
+
+	int charcase;
+	int fork;
+	int namemap;
+
+	umode_t umask;
+	uid_t uid;
+	gid_t gid;
+
+	unsigned long flags;
+
+	atomic_t inode_cnt;
+	u32 last_inode_cnt;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	struct list_head rsrc_inodes;
+#else
+	struct hlist_head rsrc_inodes;
+#endif
+};
+
+#define HFSPLUS_SB_WRITEBACKUP	0x0001
+
+
+struct hfsplus_inode_info {
+	/* Device number in hfsplus_permissions in catalog */
+	u32 dev;
+	/* Allocation extents from catlog record or volume header */
+	hfsplus_extent_rec extents;
+	u32 total_blocks, extent_blocks, alloc_blocks;
+	atomic_t opencnt;
+
+	struct inode *rsrc_inode;
+	unsigned long flags;
+
+	struct list_head open_dir_list;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	unsigned long mmu_private;
+#else
+	loff_t mmu_private;
+	struct inode vfs_inode;
+#endif
+};
+
+#define HFSPLUS_FLG_RSRC	0x0001
+#define HFSPLUS_FLG_DIRTYMODE	0x0002
+
+#define HFSPLUS_IS_DATA(inode)   (!(HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC))
+#define HFSPLUS_IS_RSRC(inode)   (HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC)
+
 struct hfsplus_find_data {
 	/* filled by caller */
 	hfsplus_btree_key *search_key;
@@ -143,6 +224,7 @@
 int hfsplus_btree_find(struct hfsplus_find_data *);
 int hfsplus_btree_find_entry(struct hfsplus_find_data *,
 			     void *, int);
+int hfsplus_btree_move(struct hfsplus_find_data *, int);
 int hfsplus_find_init(hfsplus_btree *, struct hfsplus_find_data *);
 void hfsplus_find_exit(struct hfsplus_find_data *);
 
@@ -166,15 +248,8 @@
 int hfsplus_bnode_remove_rec(struct hfsplus_find_data *);
 
 /* brec.c */
-u16 hfsplus_brec_off(hfsplus_bnode *, u16);
-u16 hfsplus_brec_len(hfsplus_bnode *, u16);
 u16 hfsplus_brec_lenoff(hfsplus_bnode *, u16, u16 *);
-u16 hfsplus_brec_data(hfsplus_bnode *, u16, char *, u16);
 u16 hfsplus_brec_keylen(hfsplus_bnode *, u16);
-u16 hfsplus_brec_key(hfsplus_bnode *, u16, void *, u16);
-
-/* btiter.c */
-int hfsplus_btiter_move(struct hfsplus_find_data *, int);
 
 /* btree.c */
 hfsplus_btree *hfsplus_open_btree(struct super_block *, u32);
@@ -264,9 +339,9 @@
 #define wait_on_page_locked(page) wait_on_page(page)
 #define get_seconds()		CURRENT_TIME
 #define page_symlink(i,n,l)		block_symlink(i,n,l)
-#define map_bh(bh, sb, bl) ({					\
+#define map_bh(bh, sb, block) ({				\
 	bh->b_dev = kdev_t_to_nr(sb->s_dev);			\
-	bh->b_blocknr = dblock + HFSPLUS_SB(sb).blockoffset;	\
+	bh->b_blocknr = block;					\
 	bh->b_state |= (1UL << BH_Mapped);			\
 })
 #define set_buffer_new(bh)	(bh->b_state |= (1UL << BH_New))
diff -urN linux-2.4.21-bk11/fs/hfsplus/hfsplus_fs_i.h linux-2.4.21-bk12/fs/hfsplus/hfsplus_fs_i.h
--- linux-2.4.21-bk11/fs/hfsplus/hfsplus_fs_i.h	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/hfsplus_fs_i.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,41 +0,0 @@
-/*
- *  linux/include/linux/hfsplus_fs_i.h
- *
- * Copyright (C) 1999
- * Brad Boyer (flar@pants.nu)
- *
- */
-
-#ifndef _LINUX_HFSPLUS_FS_I_H
-#define _LINUX_HFSPLUS_FS_I_H
-
-#include <linux/types.h>
-#include <linux/version.h>
-#include "hfsplus_raw.h"
-
-struct hfsplus_inode_info {
-	/* Device number in hfsplus_permissions in catalog */
-	u32 dev;
-	/* Allocation extents from catlog record or volume header */
-	hfsplus_extent_rec extents;
-	u32 total_blocks, extent_blocks, alloc_blocks;
-	atomic_t opencnt;
-
-	struct inode *rsrc_inode;
-	unsigned long flags;
-
-	struct list_head open_dir_list;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	unsigned long mmu_private;
-#else
-	loff_t mmu_private;
-	struct inode vfs_inode;
-#endif
-};
-
-#define HFSPLUS_FLG_RSRC	0x0001
-
-#define HFSPLUS_IS_DATA(inode)   (!(HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC))
-#define HFSPLUS_IS_RSRC(inode)   (HFSPLUS_I(inode).flags & HFSPLUS_FLG_RSRC)
-
-#endif
diff -urN linux-2.4.21-bk11/fs/hfsplus/hfsplus_fs_sb.h linux-2.4.21-bk12/fs/hfsplus/hfsplus_fs_sb.h
--- linux-2.4.21-bk11/fs/hfsplus/hfsplus_fs_sb.h	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/hfsplus_fs_sb.h	1969-12-31 16:00:00.000000000 -0800
@@ -1,69 +0,0 @@
-/*
- *  linux/include/linux/hfsplus_fs_sb.h
- *
- * Copyright (C) 1999
- * Brad Boyer (flar@pants.nu)
- *
- */
-
-#ifndef _LINUX_HFSPLUS_FS_SB_H
-#define _LINUX_HFSPLUS_FS_SB_H
-
-#include <linux/types.h>
-
-/*
- * HFS+ superblock info (built from Volume Header on disk)
- */
-
-struct hfsplus_vh;
-struct hfsplus_btree;
-
-struct hfsplus_sb_info {
-	struct buffer_head *s_vhbh;
-	struct hfsplus_vh *s_vhdr;
-	struct hfsplus_btree *ext_tree;
-	struct hfsplus_btree *cat_tree;
-	struct hfsplus_btree *attr_tree;
-	struct inode *alloc_file;
-	struct inode *hidden_dir;
-
-	/* Runtime variables */
-	u32 blockoffset;
-	u32 sect_count;
-	//int a2b_shift;
-
-	/* Stuff in host order from Vol Header */
-	u32 total_blocks;
-	u32 free_blocks;
-	u32 next_alloc;
-	u32 next_cnid;
-	u32 file_count;
-	u32 folder_count;
-
-	/* Config options */
-	u32 creator;
-	u32 type;
-
-	int charcase;
-	int fork;
-	int namemap;
-
-	umode_t umask;
-	uid_t uid;
-	gid_t gid;
-
-	unsigned long flags;
-
-	atomic_t inode_cnt;
-	u32 last_inode_cnt;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	struct list_head rsrc_inodes;
-#else
-	struct hlist_head rsrc_inodes;
-#endif
-};
-
-#define HFSPLUS_SB_WRITEBACKUP	0x0001
-
-#endif
diff -urN linux-2.4.21-bk11/fs/hfsplus/hfsplus_raw.h linux-2.4.21-bk12/fs/hfsplus/hfsplus_raw.h
--- linux-2.4.21-bk11/fs/hfsplus/hfsplus_raw.h	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/hfsplus_raw.h	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 1999
  * Brad Boyer (flar@pants.nu)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  * Format of structures on disk
  * Information taken from Apple Technote #1150 (HFS Plus Volume Format)
@@ -36,8 +37,10 @@
 
 #define HFSP_HIDDENDIR_NAME	"\xe2\x90\x80\xe2\x90\x80\xe2\x90\x80\xe2\x90\x80HFS+ Private Data"
 
-#define HFSP_HARDLINK_TYPE	0x686c6e6b
-#define HFSP_HFSPLUS_CREATOR	0x6866732b
+#define HFSP_HARDLINK_TYPE	0x686c6e6b	/* 'hlnk' */
+#define HFSP_HFSPLUS_CREATOR	0x6866732b	/* 'hfs+' */
+
+#define HFSP_MOUNT_VERSION	0x482b4c78	/* 'H+Lx' */
 
 /* Structures used on disk */
 
diff -urN linux-2.4.21-bk11/fs/hfsplus/inode.c linux-2.4.21-bk12/fs/hfsplus/inode.c
--- linux-2.4.21-bk11/fs/hfsplus/inode.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/inode.c	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001
  * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  * Inode handling routines
  */
@@ -184,21 +185,29 @@
 	return NULL;
 }
 
-static void hfsplus_get_perms(struct inode *inode, hfsplus_perm *perms)
+static void hfsplus_get_perms(struct inode *inode, hfsplus_perm *perms, int dir)
 {
-	struct super_block *s = inode->i_sb;
+	struct super_block *sb = inode->i_sb;
+	int mode;
 
-	inode->i_mode = be32_to_cpu(perms->mode);
-	if (!inode->i_mode)
-		inode->i_mode = S_IFREG | (S_IRWXUGO & ~(HFSPLUS_SB(s).umask));
+	mode = be32_to_cpu(perms->mode) & 0xffff;
 
 	inode->i_uid = be32_to_cpu(perms->owner);
-	if (!inode->i_uid)
-		inode->i_uid = HFSPLUS_SB(s).uid;
+	if (!inode->i_uid && !mode)
+		inode->i_uid = HFSPLUS_SB(sb).uid;
 
 	inode->i_gid = be32_to_cpu(perms->group);
-	if (!inode->i_gid)
-		inode->i_gid = HFSPLUS_SB(s).gid;
+	if (!inode->i_gid && !mode)
+		inode->i_gid = HFSPLUS_SB(sb).gid;
+
+	if (dir) {
+		mode = mode ? (mode & S_IALLUGO) :
+			(S_IRWXUGO & ~(HFSPLUS_SB(sb).umask));
+		mode |= S_IFDIR;
+	} else if (!mode)
+		mode = S_IFREG | ((S_IRUGO|S_IWUGO) &
+			~(HFSPLUS_SB(sb).umask));
+	inode->i_mode = mode;
 }
 
 static void hfsplus_set_perms(struct inode *inode, hfsplus_perm *perms)
@@ -257,35 +266,6 @@
 	.release	= hfsplus_file_release,
 };
 
-#if 0
-static nlink_t hfsplus_count_subdirs(struct inode *inode)
-{
-	struct hfsplus_find_data fd;
-	hfsplus_cat_entry entry;
-	nlink_t res = 0;
-	u32 cnid;
-
-	hfsplus_find_init(HFSPLUS_SB(inode->i_sb).cat_tree, &fd);
-	hfsplus_fill_cat_key(fd.search_key, inode->i_ino, NULL);
-	res = hfsplus_btree_find(&fd);
-	if (res)
-		goto out;
-	cnid = cpu_to_be32(inode->i_ino);
-	for (;;) {
-		if (fd.key->cat.parent != cnid)
-			break;
-		if (be16_to_cpu(entry.type) == HFSPLUS_FOLDER)
-			res++;
-
-		if (hfsplus_btiter_move(&fd, 1))
-			break;
-	}
-out:
-	hfsplus_find_exit(&fd);
-	return res;
-}
-#endif
-
 struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
 {
 	struct inode *inode = new_inode(sb);
@@ -392,9 +372,7 @@
 					sizeof(hfsplus_cat_folder));
 		memset(&HFSPLUS_I(inode).extents, 0,
 		       sizeof(hfsplus_extent_rec));
-		hfsplus_get_perms(inode, &(folder->permissions));
-		inode->i_mode = S_IFDIR | (inode->i_mode & ~S_IFMT);
-		//inode->i_nlink = 2 + hfsplus_count_subdirs(inode);
+		hfsplus_get_perms(inode, &folder->permissions, 1);
 		inode->i_nlink = 1;
 		inode->i_size = 2 + be32_to_cpu(folder->valence);
 		inode->i_atime = hfsp_mt2ut(folder->access_date);
@@ -414,12 +392,11 @@
 
 		hfsplus_inode_read_fork(inode, HFSPLUS_IS_DATA(inode) ?
 					&file->data_fork : &file->rsrc_fork);
-		hfsplus_get_perms(inode, &file->permissions);
+		hfsplus_get_perms(inode, &file->permissions, 0);
 		inode->i_nlink = 1;
 		if (S_ISREG(inode->i_mode)) {
 			if (file->permissions.dev)
 				inode->i_nlink = be32_to_cpu(file->permissions.dev);
-			inode->i_mode = S_IFREG | (inode->i_mode & ~S_IFMT);
 			inode->i_op = &hfsplus_file_inode_operations;
 			inode->i_fop = &hfsplus_file_operations;
 			inode->i_mapping->a_ops = &hfsplus_aops;
diff -urN linux-2.4.21-bk11/fs/hfsplus/options.c linux-2.4.21-bk12/fs/hfsplus/options.c
--- linux-2.4.21-bk11/fs/hfsplus/options.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/options.c	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001
  * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  * Option parsing
  */
@@ -100,12 +101,12 @@
 
 		if (!strcmp(curropt, "creator")) {
 			if (!fill_fourchar(&(results->creator), value)) {
-				printk("HFS+-fs: creator requires a value\n");
+				printk("HFS+-fs: creator requires a 4 character value\n");
 				return 0;
 			}
 		} else if (!strcmp(curropt, "type")) {
 			if (!fill_fourchar(&(results->type), value)) {
-				printk("HFS+-fs: type requires a value\n");
+				printk("HFS+-fs: type requires a 4 character value\n");
 				return 0;
 			}
 		} else if (!strcmp(curropt, "case")) {
diff -urN linux-2.4.21-bk11/fs/hfsplus/super.c linux-2.4.21-bk12/fs/hfsplus/super.c
--- linux-2.4.21-bk11/fs/hfsplus/super.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/super.c	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001
  * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  */
 
@@ -232,6 +233,28 @@
 	return 0;
 }
 
+int hfsplus_remount(struct super_block *sb, int *flags, char *data)
+{
+	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+		return 0;
+	if (!(*flags & MS_RDONLY)) {
+		struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr;
+
+		if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_INCNSTNT)) ||
+		    !(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
+			printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
+			       "running fsck.hfsplus is recommended.  leaving read-only.\n");
+			sb->s_flags |= MS_RDONLY;
+			*flags |= MS_RDONLY;
+		} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
+			printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n");
+			sb->s_flags |= MS_RDONLY;
+			*flags |= MS_RDONLY;
+		}
+	}
+	return 0;
+}
+
 static struct super_operations hfsplus_sops = {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
 	.alloc_inode	= hfsplus_alloc_inode,
@@ -243,6 +266,7 @@
 	.put_super	= hfsplus_put_super,
 	.write_super	= hfsplus_write_super,
 	.statfs		= hfsplus_statfs,
+	.remount_fs	= hfsplus_remount,
 };
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
@@ -266,6 +290,16 @@
 	}
 	memset(sbi, 0, sizeof(HFSPLUS_SB(sb)));
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+	if (sizeof(struct inode) - offsetof(struct inode, u) < sizeof(struct hfsplus_inode_info)) {
+		extern void hfsplus_inode_info_exceeded_space_in_inode_error(void);
+		hfsplus_inode_info_exceeded_space_in_inode_error();
+	}
+
+	if (sizeof(struct super_block) - offsetof(struct super_block, u) < sizeof(struct hfsplus_sb_info)) {
+		extern void hfsplus_sb_info_exceeded_space_in_super_block_error(void);
+		hfsplus_sb_info_exceeded_space_in_super_block_error();
+	}
+
 	INIT_LIST_HEAD(&HFSPLUS_SB(sb).rsrc_inodes);
 #else
 	sb->s_fs_info = sbi;
@@ -309,6 +343,18 @@
 	/* Set up operations so we can load metadata */
 	sb->s_op = &hfsplus_sops;
 
+	if ((vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_INCNSTNT)) ||
+	    !(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) {
+		if (!silent)
+			printk("HFS+-fs warning: Filesystem was not cleanly unmounted, "
+			       "running fsck.hfsplus is recommended.  mounting read-only.\n");
+		sb->s_flags |= MS_RDONLY;
+	} else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) {
+		if (!silent)
+			printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n");
+		sb->s_flags |= MS_RDONLY;
+	}
+
 	/* Load metadata objects (B*Trees) */
 	HFSPLUS_SB(sb).ext_tree = hfsplus_open_btree(sb, HFSPLUS_EXT_CNID);
 	if (!HFSPLUS_SB(sb).ext_tree) {
@@ -355,7 +401,10 @@
 	if (sb->s_flags & MS_RDONLY)
 		goto out;
 
-	//vhdr->last_mount_vers = cpu_to_be32('LNX0');
+	/* H+LX == hfsplusutils, H+Lx == this driver, H+lx is unused
+	 * all three are registered with Apple for our use
+	 */
+	vhdr->last_mount_vers = cpu_to_be32(HFSP_MOUNT_VERSION);
 	vhdr->modify_date = hfsp_now2mt();
 	vhdr->write_count = cpu_to_be32(be32_to_cpu(vhdr->write_count) + 1);
 	vhdr->attributes &= cpu_to_be32(~HFSPLUS_VOL_UNMNT);
diff -urN linux-2.4.21-bk11/fs/hfsplus/unicode.c linux-2.4.21-bk12/fs/hfsplus/unicode.c
--- linux-2.4.21-bk11/fs/hfsplus/unicode.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/unicode.c	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001
  * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  * Handler routines for unicode strings
  */
diff -urN linux-2.4.21-bk11/fs/hfsplus/wrapper.c linux-2.4.21-bk12/fs/hfsplus/wrapper.c
--- linux-2.4.21-bk11/fs/hfsplus/wrapper.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/hfsplus/wrapper.c	2003-07-17 02:52:30.000000000 -0700
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001
  * Brad Boyer (flar@allandria.com)
+ * (C) 2003 Ardis Technologies <roman@ardistech.com>
  *
  * Handling of HFS wrappers around HFS+ volumes
  */
diff -urN linux-2.4.21-bk11/fs/reiserfs/namei.c linux-2.4.21-bk12/fs/reiserfs/namei.c
--- linux-2.4.21-bk11/fs/reiserfs/namei.c	2003-07-17 02:52:25.000000000 -0700
+++ linux-2.4.21-bk12/fs/reiserfs/namei.c	2003-07-17 02:52:30.000000000 -0700
@@ -781,6 +781,7 @@
     int windex ;
     struct reiserfs_transaction_handle th ;
     int jbegin_count;
+    unsigned long savelink;
 
     inode = dentry->d_inode;
 
@@ -816,11 +817,20 @@
 	inode->i_nlink = 1;
     }
 
+    inode->i_nlink--;
+
+    /* 
+     * we schedule before doing the add_save_link call, save the link
+     * count so we don't race
+     */
+    savelink = inode->i_nlink;
+
+
     retval = reiserfs_cut_from_item (&th, &path, &(de.de_entry_key), dir, NULL, 0);
-    if (retval < 0)
+    if (retval < 0) {
+	inode->i_nlink++;
 	goto end_unlink;
-
-    inode->i_nlink--;
+    }
     inode->i_ctime = CURRENT_TIME;
     reiserfs_update_sd (&th, inode);
 
@@ -829,7 +839,7 @@
     dir->i_ctime = dir->i_mtime = CURRENT_TIME;
     reiserfs_update_sd (&th, dir);
 
-    if (!inode->i_nlink)
+    if (!savelink)
        /* prevent file from getting lost */
        add_save_link (&th, inode, 0/* not truncate */);
 
@@ -937,6 +947,12 @@
 	//FIXME: sd_nlink is 32 bit for new files
 	return -EMLINK;
     }
+    if (inode->i_nlink == 0) {
+        return -ENOENT;
+    }
+
+    /* inc before scheduling so reiserfs_unlink knows we are here */
+    inode->i_nlink++;
 
     journal_begin(&th, dir->i_sb, jbegin_count) ;
     windex = push_journal_writer("reiserfs_link") ;
@@ -949,12 +965,12 @@
     reiserfs_update_inode_transaction(dir) ;
 
     if (retval) {
+	inode->i_nlink--;
 	pop_journal_writer(windex) ;
 	journal_end(&th, dir->i_sb, jbegin_count) ;
 	return retval;
     }
 
-    inode->i_nlink++;
     ctime = CURRENT_TIME;
     inode->i_ctime = ctime;
     reiserfs_update_sd (&th, inode);
@@ -1029,6 +1045,7 @@
     int jbegin_count ; 
     umode_t old_inode_mode;
     time_t ctime;
+    unsigned long savelink = 1;
 
 
     /* two balancings: old name removal, new name insertion or "save" link,
@@ -1200,6 +1217,7 @@
 	}
 	ctime = CURRENT_TIME;
 	new_dentry_inode->i_ctime = ctime;
+	savelink = new_dentry_inode->i_nlink;
     }
 
     if (S_ISDIR(old_inode_mode)) {
@@ -1233,7 +1251,7 @@
     reiserfs_update_sd (&th, new_dir);
 
     if (new_dentry_inode) {
-	if (new_dentry_inode->i_nlink == 0)
+	if (savelink == 0)
 	    add_save_link (&th, new_dentry_inode, 0/* not truncate */);
 	reiserfs_update_sd (&th, new_dentry_inode);
     }
diff -urN linux-2.4.21-bk11/include/asm-ppc/highmem.h linux-2.4.21-bk12/include/asm-ppc/highmem.h
--- linux-2.4.21-bk11/include/asm-ppc/highmem.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-ppc/highmem.h	2003-07-17 02:52:30.000000000 -0700
@@ -102,7 +102,7 @@
 static inline void kunmap_atomic(void *kvaddr, enum km_type type)
 {
 #if HIGHMEM_DEBUG
-	unsigned long vaddr = (unsigned long) kvaddr;
+	unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
 	unsigned int idx = type + KM_TYPE_NR*smp_processor_id();
 
 	if (vaddr < KMAP_FIX_BEGIN) // FIXME
diff -urN linux-2.4.21-bk11/include/asm-sh/bugs.h linux-2.4.21-bk12/include/asm-sh/bugs.h
--- linux-2.4.21-bk11/include/asm-sh/bugs.h	2001-06-27 13:55:29.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/bugs.h	2003-07-17 02:52:30.000000000 -0700
@@ -34,9 +34,9 @@
 		*p++ = '4';
 		printk("CPU: SH7750/SH7751\n");
 		break;
-	case CPU_ST40STB1:
+	case CPU_ST40:
 		*p++ = '4';
-		printk("CPU: ST40STB1\n");
+		printk("CPU: ST40STB1/GX1\n");
 		break;
 	default:
 		printk("CPU: ??????\n");
diff -urN linux-2.4.21-bk11/include/asm-sh/cachectl.h linux-2.4.21-bk12/include/asm-sh/cachectl.h
--- linux-2.4.21-bk11/include/asm-sh/cachectl.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/cachectl.h	2003-07-17 02:52:30.000000000 -0700
@@ -0,0 +1,12 @@
+#ifndef _SH_CACHECTL_H
+#define _SH_CACHECTL_H
+
+/* Definitions for the cacheflush system call.  */
+
+#define CACHEFLUSH_D_INVAL	0x1	/* invalidate (without write back) */
+#define CACHEFLUSH_D_WB		0x2	/* write back (without invalidate) */
+#define CACHEFLUSH_D_PURGE	0x3	/* writeback and invalidate */
+
+#define CACHEFLUSH_I		0x4
+
+#endif /* _SH_CACHECTL_H */
diff -urN linux-2.4.21-bk11/include/asm-sh/delay.h linux-2.4.21-bk12/include/asm-sh/delay.h
--- linux-2.4.21-bk11/include/asm-sh/delay.h	2001-01-04 13:19:13.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/delay.h	2003-07-17 02:52:30.000000000 -0700
@@ -10,6 +10,7 @@
 extern void __bad_udelay(void);
 
 extern void __udelay(unsigned long usecs);
+extern void __ndelay(unsigned long nsecs);
 extern void __const_udelay(unsigned long usecs);
 extern void __delay(unsigned long loops);
 
@@ -17,4 +18,8 @@
 	((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \
 	__udelay(n))
 
+#define ndelay(n) (__builtin_constant_p(n) ? \
+        ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
+        __ndelay(n))
+
 #endif /* __ASM_SH_DELAY_H */
diff -urN linux-2.4.21-bk11/include/asm-sh/hitachi_hs7729pci.h linux-2.4.21-bk12/include/asm-sh/hitachi_hs7729pci.h
--- linux-2.4.21-bk11/include/asm-sh/hitachi_hs7729pci.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/hitachi_hs7729pci.h	2003-07-17 02:52:30.000000000 -0700
@@ -0,0 +1,54 @@
+#ifndef __ASM_SH_HITACHI_HS7729PCI_H
+#define __ASM_SH_HITACHI_HS7729PCI_H
+
+/*
+ * linux/include/asm-sh/hitachi_hs7729pci.h
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Hitachi Semiconductor and Devices HS7729PCI support
+ */
+
+/* Box specific addresses.  */
+
+#define PA_SUPERIO	0xa8000000	/* SMC37C935A super io chip */
+#define PA_DIPSW0	0xa8c00000	/* Dip switch 5,6 */
+#define PA_DIPSW1	0xa8c00002	/* Dip switch 7,8 */
+#define PA_LED		0xa8c40000	/* LED */
+#define PA_7SEG		0xa8c40002	/* 7 segment LED */
+#define PA_BCR		0xa8c80000	/* FPGA */
+
+#define PA_MRSHPC	0xb83fffe0	/* MR-SHPC-01 PCMCIA controler */
+#define PA_MRSHPC_MW1	0xb8400000	/* MR-SHPC-01 memory window base */
+#define PA_MRSHPC_MW2	0xb8500000	/* MR-SHPC-01 attribute window base */
+#define PA_MRSHPC_IO	0xb8600000	/* MR-SHPC-01 I/O window base */
+#define MRSHPC_OPTION   (PA_MRSHPC + 0x06)
+#define MRSHPC_CSR      (PA_MRSHPC + 0x08)
+#define MRSHPC_ISR      (PA_MRSHPC + 0x0a)
+#define MRSHPC_ICR      (PA_MRSHPC + 0x0c)
+#define MRSHPC_CPWCR    (PA_MRSHPC + 0x0e)
+#define MRSHPC_MW0CR1   (PA_MRSHPC + 0x10)
+#define MRSHPC_MW1CR1   (PA_MRSHPC + 0x12)
+#define MRSHPC_IOWCR1   (PA_MRSHPC + 0x14)
+#define MRSHPC_MW0CR2   (PA_MRSHPC + 0x16)
+#define MRSHPC_MW1CR2   (PA_MRSHPC + 0x18)
+#define MRSHPC_IOWCR2   (PA_MRSHPC + 0x1a)
+#define MRSHPC_CDCR     (PA_MRSHPC + 0x1c)
+#define MRSHPC_PCIC_INFO (PA_MRSHPC + 0x1e)
+
+#define BCR_ILCRA	(PA_BCR + 0)
+#define BCR_ILCRB	(PA_BCR + 2)
+#define BCR_ILCRC	(PA_BCR + 4)
+#define BCR_ILCRD	(PA_BCR + 6)
+#define BCR_ILCRE	(PA_BCR + 8)
+#define BCR_ILCRF	(PA_BCR + 10)
+#define BCR_ILCRG	(PA_BCR + 12)
+
+#define SH7729PCI_PCI_HOST_BRIDGE 0xb0000000	/* SD0001 Register */
+#define SH7729PCI_PCI_AREA	0xb0800000	/* PCI I/O Window */
+#define SH7729PCI_PCI_MEM_START CONFIG_MEMORY_START
+#define SH7729PCI_PCI_MEM_SIZE  CONFIG_MEMORY_SIZE
+
+#define SH7729PCI_PCI_IRQ  0		/* SD0001 Interrupt Number */
+
+#endif  /* __ASM_SH_HITACHI_HS7729PCI_H */
diff -urN linux-2.4.21-bk11/include/asm-sh/hw_irq.h linux-2.4.21-bk12/include/asm-sh/hw_irq.h
--- linux-2.4.21-bk11/include/asm-sh/hw_irq.h	1999-08-30 18:12:59.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/hw_irq.h	2003-07-17 02:52:30.000000000 -0700
@@ -1,6 +1,4 @@
 #ifndef __ASM_SH_HW_IRQ_H
 #define __ASM_SH_HW_IRQ_H
-static __inline__ void sh_do_profile (unsigned long pc) {/*Not implemented yet*/}
-
 static __inline__ void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { /* Nothing to do */ }
 #endif /* __ASM_SH_HW_IRQ_H */
diff -urN linux-2.4.21-bk11/include/asm-sh/ide.h linux-2.4.21-bk12/include/asm-sh/ide.h
--- linux-2.4.21-bk11/include/asm-sh/ide.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/ide.h	2003-07-17 02:52:30.000000000 -0700
@@ -15,13 +15,24 @@
 #ifdef __KERNEL__
 
 #include <linux/config.h>
+#include <asm-generic/ide_iops.h>
 #include <asm/machvec.h>
 
 #ifndef MAX_HWIFS
-/* Should never have less than 2, ide-pci.c(ide_match_hwif) requires it */
-#define MAX_HWIFS	2
+/* Should never have fewer than 2, ide-pci.c(ide_match_hwif) requires it */
+#define MAX_HWIFS	4
 #endif
 
+static __inline__ int ide_default_irq_hs7729pci(ide_ioreg_t base)
+{
+	switch (base) {
+		case 0x01f0: return 9;
+		case 0x0170: return 14;
+		default:
+			return 0;
+	}
+}
+
 static __inline__ int ide_default_irq_hp600(ide_ioreg_t base)
 {
 	switch (base) {
@@ -37,6 +48,9 @@
 	if (MACH_HP600) {
 		return ide_default_irq_hp600(base);
 	}
+	if (MACH_HS7729PCI) {
+		return ide_default_irq_hs7729pci(base);
+	}
 	switch (base) {
 		case 0x01f0: return 14;
 		case 0x0170: return 15;
@@ -98,6 +112,7 @@
 	int index;
 
 	for(index = 0; index < MAX_HWIFS; index++) {
+		memset(&hw, 0, sizeof hw);
 		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
 		hw.irq = ide_default_irq(ide_default_io_base(index));
 		ide_register_hw(&hw, NULL);
@@ -105,8 +120,6 @@
 #endif /* CONFIG_BLK_DEV_IDEPCI */
 }
 
-#include <asm-generic/ide_iops.h>
-
 #endif /* __KERNEL__ */
 
 #endif /* __ASM_SH_IDE_H */
diff -urN linux-2.4.21-bk11/include/asm-sh/io.h linux-2.4.21-bk12/include/asm-sh/io.h
--- linux-2.4.21-bk11/include/asm-sh/io.h	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/io.h	2003-07-17 02:52:30.000000000 -0700
@@ -125,6 +125,8 @@
 #  include <asm/io_cat68701.h>
 # elif defined(CONFIG_SH_BIGSUR)
 #  include <asm/io_bigsur.h>
+# elif defined(CONFIG_SH_HS7729PCI)
+#  include <asm/io_hs7729pci.h>
 # elif defined(CONFIG_SH_7751_SOLUTION_ENGINE)
 #  include <asm/io_7751se.h>
 # elif defined(CONFIG_SH_ADX)
diff -urN linux-2.4.21-bk11/include/asm-sh/io_hs7729pci.h linux-2.4.21-bk12/include/asm-sh/io_hs7729pci.h
--- linux-2.4.21-bk11/include/asm-sh/io_hs7729pci.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/io_hs7729pci.h	2003-07-17 02:52:30.000000000 -0700
@@ -0,0 +1,93 @@
+/*
+ * include/asm-sh/io_hs7729pci.h
+ *
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for an Hitachi Semiconductor and Devices HS7729PCI
+ */
+
+#ifndef _ASM_SH_IO_HS7729PCI_H
+#define _ASM_SH_IO_HS7729PCI_H
+
+#include <asm/io_generic.h>
+
+extern unsigned char hs7729pci_inb(unsigned long port);
+extern unsigned short hs7729pci_inw(unsigned long port);
+extern unsigned int hs7729pci_inl(unsigned long port);
+
+extern void hs7729pci_outb(unsigned char value, unsigned long port);
+extern void hs7729pci_outw(unsigned short value, unsigned long port);
+extern void hs7729pci_outl(unsigned int value, unsigned long port);
+
+extern unsigned char hs7729pci_inb_p(unsigned long port);
+extern void hs7729pci_outb_p(unsigned char value, unsigned long port);
+
+extern void hs7729pci_insb(unsigned long port, void *addr, unsigned long count);
+extern void hs7729pci_insw(unsigned long port, void *addr, unsigned long count);
+extern void hs7729pci_insl(unsigned long port, void *addr, unsigned long count);
+extern void hs7729pci_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void hs7729pci_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void hs7729pci_outsl(unsigned long port, const void *addr, unsigned long count);
+
+extern unsigned char hs7729pci_readb(unsigned long addr);
+extern unsigned short hs7729pci_readw(unsigned long addr);
+extern unsigned long hs7729pci_readl(unsigned long addr);
+extern void hs7729pci_writeb(unsigned char b, unsigned long addr);
+extern void hs7729pci_writew(unsigned short b, unsigned long addr);
+extern void hs7729pci_writel(unsigned int b, unsigned long addr);
+
+extern unsigned long hs7729pci_isa_port2addr(unsigned long offset);
+
+extern void *hs7729pci_ioremap(unsigned long, unsigned long);
+extern void hs7729pci_iounmap(void *addr);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			hs7729pci_inb
+# define __inw			hs7729pci_inw
+# define __inl			hs7729pci_inl
+# define __outb			hs7729pci_outb
+# define __outw			hs7729pci_outw
+# define __outl			hs7729pci_outl
+
+# define __inb_p		hs7729pci_inb_p
+# define __inw_p		hs7729pci_inw
+# define __inl_p		hs7729pci_inl
+# define __outb_p		hs7729pci_outb_p
+# define __outw_p		hs7729pci_outw
+# define __outl_p		hs7729pci_outl
+
+# define __insb			hs7729pci_insb
+# define __insw			hs7729pci_insw
+# define __insl			hs7729pci_insl
+# define __outsb		hs7729pci_outsb
+# define __outsw		hs7729pci_outsw
+# define __outsl		hs7729pci_outsl
+
+#if 0
+# define __readb		hs7729pci_readb
+# define __readw		hs7729pci_readw
+# define __readl		hs7729pci_readl
+# define __writeb		hs7729pci_writeb
+# define __writew		hs7729pci_writew
+# define __writel		hs7729pci_writel
+#else
+# define __readb		generic_readb
+# define __readw		generic_readw
+# define __readl		generic_readl
+# define __writeb		generic_writeb
+# define __writew		generic_writew
+# define __writel		generic_writel
+#endif
+
+# define __isa_port2addr	hs7729pci_isa_port2addr
+# define __ioremap		hs7729pci_ioremap
+# define __ioremap_nocache	hs7729pci_ioremap
+# define __iounmap		hs7729pci_iounmap
+
+#endif
+
+#endif /* _ASM_SH_IO_HS7729PCI_H */
diff -urN linux-2.4.21-bk11/include/asm-sh/io_keywest.h linux-2.4.21-bk12/include/asm-sh/io_keywest.h
--- linux-2.4.21-bk11/include/asm-sh/io_keywest.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/io_keywest.h	2003-07-17 02:52:30.000000000 -0700
@@ -0,0 +1,91 @@
+/*
+ * include/asm-sh/io_keywest.h
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+ * Derived from io_hd64465.h, which bore the message:
+ * By Greg Banks <gbanks@pocketpenguins.com>
+ * (c) 2000 PocketPenguins Inc. 
+ * and from io_hd64461.h, which bore the message:
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for a Hitachi Big Sur Evaluation Board.
+ */
+
+#ifndef _ASM_SH_IO_KEYWEST_H
+#define _ASM_SH_IO_KEYWEST_H
+
+#include <linux/types.h>
+#include <asm/io_generic.h>
+
+extern unsigned char keywest_inb(unsigned long port);
+extern unsigned short keywest_inw(unsigned long port);
+extern unsigned int keywest_inl(unsigned long port);
+
+extern void keywest_outb(unsigned char value, unsigned long port);
+extern void keywest_outw(unsigned short value, unsigned long port);
+extern void keywest_outl(unsigned int value, unsigned long port);
+
+extern unsigned char keywest_inb_p(unsigned long port);
+extern void keywest_outb_p(unsigned char value, unsigned long port);
+
+extern void keywest_insb(unsigned long port, void *addr, unsigned long count);
+extern void keywest_insw(unsigned long port, void *addr, unsigned long count);
+extern void keywest_insl(unsigned long port, void *addr, unsigned long count);
+extern void keywest_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void keywest_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void keywest_outsl(unsigned long port, const void *addr, unsigned long count);
+extern unsigned long keywest_isa_port2addr(unsigned long offset);
+extern int keywest_irq_demux(int irq);
+extern void keywest_init_pci(void);
+/* Provision for generic secondary demux step -- used by PCMCIA code */
+extern void keywest_register_irq_demux(int irq,
+		int (*demux)(int irq, void *dev), void *dev);
+extern void keywest_unregister_irq_demux(int irq);
+/* Set this variable to 1 to see port traffic */
+extern int keywest_io_debug;
+/* Map a range of ports to a range of kernel virtual memory. */
+extern void keywest_port_map(u32 baseport, u32 nports, u32 addr, u8 shift);
+extern void keywest_port_unmap(u32 baseport, u32 nports);
+#define mach_port_map keywest_port_map
+#define mach_port_unmap keywest_port_unmap
+
+#endif /* _ASM_SH_IO_KEYWEST_H */
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			keywest_inb
+# define __inw			keywest_inw
+# define __inl			keywest_inl
+# define __outb			keywest_outb
+# define __outw			keywest_outw
+# define __outl			keywest_outl
+
+# define __inb_p		keywest_inb_p
+# define __inw_p		keywest_inw
+# define __inl_p		keywest_inl
+# define __outb_p		keywest_outb_p
+# define __outw_p		keywest_outw
+# define __outl_p		keywest_outl
+
+# define __insb			keywest_insb
+# define __insw			keywest_insw
+# define __insl			keywest_insl
+# define __outsb		keywest_outsb
+# define __outsw		keywest_outsw
+# define __outsl		keywest_outsl
+
+# define __readb		generic_readb
+# define __readw		generic_readw
+# define __readl		generic_readl
+# define __writeb		generic_writeb
+# define __writew		generic_writew
+# define __writel		generic_writel
+
+# define __isa_port2addr	keywest_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __iounmap		generic_iounmap
+
+#endif
diff -urN linux-2.4.21-bk11/include/asm-sh/io_snapgear.h linux-2.4.21-bk12/include/asm-sh/io_snapgear.h
--- linux-2.4.21-bk11/include/asm-sh/io_snapgear.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/io_snapgear.h	2003-07-17 02:52:30.000000000 -0700
@@ -0,0 +1,143 @@
+/*
+ * include/asm-sh/io_snapgear.h
+ *
+ * Modified version of io_se.h for the snapgear-specific functions.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for a SnapGear
+ */
+
+#ifndef _ASM_SH_IO_SNAPGEAR_H
+#define _ASM_SH_IO_SNAPGEAR_H
+
+#include <asm/irq.h>
+
+#if defined(__SH4__)
+/*
+ * The external interrupt lines, these take up ints 0 - 15 inclusive
+ * depending on the priority for the interrupt.  In fact the priority
+ * is the interrupt :-)
+ */
+
+#define IRL0_IRQ		2
+#define IRL0_IPR_ADDR	INTC_IPRD
+#define IRL0_IPR_POS	3
+#define IRL0_PRIORITY	13
+
+#define IRL1_IRQ		5
+#define IRL1_IPR_ADDR	INTC_IPRD
+#define IRL1_IPR_POS	2
+#define IRL1_PRIORITY	10
+
+#define IRL2_IRQ		8
+#define IRL2_IPR_ADDR	INTC_IPRD
+#define IRL2_IPR_POS	1
+#define IRL2_PRIORITY	7
+
+#define IRL3_IRQ		11
+#define IRL3_IPR_ADDR	INTC_IPRD
+#define IRL3_IPR_POS	0
+#define IRL3_PRIORITY	4
+#endif
+
+#include <asm/io_generic.h>
+
+extern unsigned char snapgear_inb(unsigned long port);
+extern unsigned short snapgear_inw(unsigned long port);
+extern unsigned int snapgear_inl(unsigned long port);
+
+extern void snapgear_outb(unsigned char value, unsigned long port);
+extern void snapgear_outw(unsigned short value, unsigned long port);
+extern void snapgear_outl(unsigned int value, unsigned long port);
+
+extern unsigned char snapgear_inb_p(unsigned long port);
+extern void snapgear_outb_p(unsigned char value, unsigned long port);
+
+extern void snapgear_insb(unsigned long port, void *addr, unsigned long count);
+extern void snapgear_insw(unsigned long port, void *addr, unsigned long count);
+extern void snapgear_insl(unsigned long port, void *addr, unsigned long count);
+extern void snapgear_outsb(unsigned long port, const void *addr, unsigned long count);
+extern void snapgear_outsw(unsigned long port, const void *addr, unsigned long count);
+extern void snapgear_outsl(unsigned long port, const void *addr, unsigned long count);
+
+extern unsigned char snapgear_readb(unsigned long addr);
+extern unsigned short snapgear_readw(unsigned long addr);
+extern unsigned int snapgear_readl(unsigned long addr);
+extern void snapgear_writeb(unsigned char b, unsigned long addr);
+extern void snapgear_writew(unsigned short b, unsigned long addr);
+extern void snapgear_writel(unsigned int b, unsigned long addr);
+
+extern unsigned long snapgear_isa_port2addr(unsigned long offset);
+
+#ifdef __WANT_IO_DEF
+
+# define __inb			snapgear_inb
+# define __inw			snapgear_inw
+# define __inl			snapgear_inl
+# define __outb			snapgear_outb
+# define __outw			snapgear_outw
+# define __outl			snapgear_outl
+
+# define __inb_p		snapgear_inb_p
+# define __inw_p		snapgear_inw
+# define __inl_p		snapgear_inl
+# define __outb_p		snapgear_outb_p
+# define __outw_p		snapgear_outw
+# define __outl_p		snapgear_outl
+
+# define __insb			snapgear_insb
+# define __insw			snapgear_insw
+# define __insl			snapgear_insl
+# define __outsb		snapgear_outsb
+# define __outsw		snapgear_outsw
+# define __outsl		snapgear_outsl
+
+# define __readb		snapgear_readb
+# define __readw		snapgear_readw
+# define __readl		snapgear_readl
+# define __writeb		snapgear_writeb
+# define __writew		snapgear_writew
+# define __writel		snapgear_writel
+
+# define __isa_port2addr	snapgear_isa_port2addr
+# define __ioremap		generic_ioremap
+# define __iounmap		generic_iounmap
+
+#endif
+
+#ifdef CONFIG_SH_SECUREEDGE5410
+/*
+ * We need to remember what was written to the ioport as some bits
+ * are shared with other functions and you cannot read back what was
+ * written :-|
+ *
+ * Bit        Read                   Write
+ * -----------------------------------------------
+ * D0         DCD on ttySC1          power
+ * D1         Reset Switch           heatbeat
+ * D2         ttySC0 CTS (7100)      LAN
+ * D3         -                      WAN
+ * D4         ttySC0 DCD (7100)      CONSOLE
+ * D5         -                      ONLINE
+ * D6         -                      VPN
+ * D7         -                      DTR on ttySC1
+ * D8         -                      ttySC0 RTS (7100)
+ * D9         -                      ttySC0 DTR (7100)
+ * D10        -                      RTC SCLK
+ * D11        RTC DATA               RTC DATA
+ * D12        -                      RTS RESET
+ */
+
+ #define SECUREEDGE_IOPORT_ADDR ((volatile short *) 0xb0000000)
+ extern unsigned short secureedge5410_ioport;
+
+ #define SECUREEDGE_WRITE_IOPORT(val, mask) (*SECUREEDGE_IOPORT_ADDR = \
+		 (secureedge5410_ioport = \
+		 		((secureedge5410_ioport & ~(mask)) | ((val) & (mask)))))
+ #define SECUREEDGE_READ_IOPORT() \
+ 		 ((*SECUREEDGE_IOPORT_ADDR&0x0817) | (secureedge5410_ioport&~0x0817))
+#endif
+
+#endif /* _ASM_SH_IO_SNAPGEAR_H */
diff -urN linux-2.4.21-bk11/include/asm-sh/irq.h linux-2.4.21-bk12/include/asm-sh/irq.h
--- linux-2.4.21-bk11/include/asm-sh/irq.h	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/irq.h	2003-07-17 02:52:30.000000000 -0700
@@ -80,7 +80,7 @@
 #define IRDA_IPR_POS	2
 #define IRDA_PRIORITY	3
 #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || \
-      defined(CONFIG_CPU_SUBTYPE_ST40STB1)
+      defined(CONFIG_CPU_SUBTYPE_ST40)
 #define SCIF_ERI_IRQ	40
 #define SCIF_RXI_IRQ	41
 #define SCIF_BRI_IRQ	42
@@ -88,7 +88,7 @@
 #define SCIF_IPR_ADDR	INTC_IPRC
 #define SCIF_IPR_POS	1
 #define SCIF_PRIORITY	3
-#if defined(CONFIG_CPU_SUBTYPE_ST40STB1)
+#if defined(CONFIG_CPU_SUBTYPE_ST40)
 #define SCIF1_ERI_IRQ	23
 #define SCIF1_RXI_IRQ	24
 #define SCIF1_BRI_IRQ	25
@@ -123,6 +123,10 @@
 #  define ONCHIP_NR_IRQS 72
 # elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
 #  define ONCHIP_NR_IRQS 144
+# elif defined(CONFIG_CPU_SUBTYPE_ST40GX1)
+#   define ONCHIP_NR_IRQS 176
+# else
+#  error Unknown chip
 # endif
 #endif
 
@@ -265,7 +269,7 @@
 #endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) || \
-    defined(CONFIG_CPU_SUBTYPE_ST40STB1)
+    defined(CONFIG_CPU_SUBTYPE_ST40)
 #define INTC_ICR        0xffd00000
 #define INTC_ICR_NMIL	(1<<15)
 #define INTC_ICR_MAI	(1<<14)
@@ -274,9 +278,15 @@
 #define INTC_ICR_IRLM	(1<<7)
 #endif
 
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
 #define INTC2_FIRST_IRQ 64
-#define NR_INTC2_IRQS 25
+#if defined(CONFIG_CPU_SUBTYPE_ST40STB1)
+#define NR_INTC2_IRQS 80
+#elif defined(CONFIG_CPU_SUBTYPE_ST40GX1)
+#define NR_INTC2_IRQS 112
+#else
+#error Unknown CPU
+#endif
  
 #define INTC2_BASE0 0xfe080000
 #define INTC2_INTC2MODE  (INTC2_BASE0+0x80)
diff -urN linux-2.4.21-bk11/include/asm-sh/keyboard-hs7729pci.h linux-2.4.21-bk12/include/asm-sh/keyboard-hs7729pci.h
--- linux-2.4.21-bk11/include/asm-sh/keyboard-hs7729pci.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/keyboard-hs7729pci.h	2003-07-17 02:52:30.000000000 -0700
@@ -0,0 +1,68 @@
+/*
+ *  linux/include/asm-sh/keyboard.h
+ *
+ *  Created 3 Nov 1996 by Geert Uytterhoeven
+ */
+
+/*
+ *  This file contains the i386 architecture specific keyboard definitions
+ */
+
+#ifndef __ASM_SH_KEYBOARD_HS7729PCI_H
+#define __ASM_SH_KEYBOARD_HS7729PCI_H
+
+#ifdef __KERNEL__
+
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+
+#define KEYBOARD_IRQ			1
+#define DISABLE_KBD_DURING_INTERRUPTS	0
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern unsigned char pckbd_sysrq_xlate[128];
+
+#define kbd_setkeycode		pckbd_setkeycode
+#define kbd_getkeycode		pckbd_getkeycode
+#define kbd_translate		pckbd_translate
+#define kbd_unexpected_up	pckbd_unexpected_up
+#define kbd_leds		pckbd_leds
+#define kbd_init_hw		pckbd_init_hw
+#define kbd_sysrq_xlate		pckbd_sysrq_xlate
+
+#define SYSRQ_KEY 0x54
+
+/* resource allocation */
+#define kbd_request_region()
+#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
+                                             "keyboard", NULL)
+
+/* How to access the keyboard macros on this platform.  */
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+/* Some stoneage hardware needs delays after some operations.  */
+#define kbd_pause() do { } while(0)
+
+/*
+ * Machine specific bits for the PS/2 driver
+ */
+
+#define AUX_IRQ 12
+
+#define aux_request_irq(hand, dev_id)					\
+	request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
+
+#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_KEYBOARD_HS7729PCI_H */
diff -urN linux-2.4.21-bk11/include/asm-sh/keyboard.h linux-2.4.21-bk12/include/asm-sh/keyboard.h
--- linux-2.4.21-bk11/include/asm-sh/keyboard.h	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/keyboard.h	2003-07-17 02:52:30.000000000 -0700
@@ -1,7 +1,7 @@
 #ifndef	__ASM_SH_KEYBOARD_H
 #define	__ASM_SH_KEYBOARD_H
 /*
- *	$Id: keyboard.h,v 1.12 2001/09/06 04:01:41 gniibe Exp $
+ *	$Id: keyboard.h,v 1.2 2001/10/15 04:32:05 mrbrown Exp $
  */
 
 #include <linux/kd.h>
@@ -10,6 +10,8 @@
 
 #ifdef CONFIG_SH_EC3104
 #include <asm/keyboard-ec3104.h>
+#elif defined(CONFIG_SH_HS7729PCI)
+#include <asm/keyboard-hs7729pci.h>
 #else
 static __inline__ int kbd_setkeycode(unsigned int scancode,
 				     unsigned int keycode)
diff -urN linux-2.4.21-bk11/include/asm-sh/kgdb.h linux-2.4.21-bk12/include/asm-sh/kgdb.h
--- linux-2.4.21-bk11/include/asm-sh/kgdb.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/kgdb.h	2003-07-17 02:52:30.000000000 -0700
@@ -0,0 +1,131 @@
+/*
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Based on original code by Glenn Engel, Jim Kingdon,
+ * David Grothe <dave@gcom.com>, Tigran Aivazian, <tigran@sco.com> and
+ * Amit S. Kale <akale@veritas.com>
+ * 
+ * Super-H port based on sh-stub.c (Ben Lee and Steve Chamberlain) by
+ * Henry Bell <henry.bell@st.com>
+ * 
+ * Header file for low-level support for remote debug using GDB. 
+ *
+ */
+
+#ifndef __KGDB_H
+#define __KGDB_H
+
+#include <asm/ptrace.h>
+
+/* Same as pt_regs but has vbr in place of syscall_nr */
+struct kgdb_regs {
+        unsigned long regs[16];
+        unsigned long pc;
+        unsigned long pr;
+        unsigned long sr;
+        unsigned long gbr;
+        unsigned long mach;
+        unsigned long macl;
+        unsigned long vbr;
+};
+
+/* State info */
+extern char kgdb_in_gdb_mode;
+extern int kgdb_done_init;
+extern int kgdb_enabled;
+extern int kgdb_nofault;	/* Ignore bus errors (in gdb mem access) */
+extern int kgdb_halt;		/* Execute initial breakpoint at startup */
+extern char in_nmi;		/* Debounce flag to prevent NMI reentry*/
+
+/* SCI */
+extern int kgdb_portnum;
+extern int kgdb_baud;
+extern char kgdb_parity;
+extern char kgdb_bits;
+extern int kgdb_cflag;
+extern int kgdb_sci_setup(void);
+
+/* Init and interface stuff */
+extern int kgdb_init(void);
+extern int (*kgdb_serial_setup)(void);
+extern int (*kgdb_getchar)(void);
+extern void (*kgdb_putchar)(int);
+
+struct kgdb_sermap {
+	char *name;
+	int namelen;
+	int (*setup_fn)(void);
+	struct kgdb_sermap *next;
+};
+extern void kgdb_register_sermap(struct kgdb_sermap *map);
+extern struct kgdb_sermap *kgdb_porttype;
+
+/* Trap functions */
+typedef void (kgdb_debug_hook_t)(struct pt_regs *regs); 
+typedef void (kgdb_bus_error_hook_t)(void);
+extern kgdb_debug_hook_t  *kgdb_debug_hook;
+extern kgdb_bus_error_hook_t *kgdb_bus_err_hook;
+
+extern void breakpoint(void);
+
+/* Console */
+struct console;
+void kgdb_console_write(struct console *co, const char *s, unsigned count);
+void kgdb_console_init(void);
+
+/* Prototypes for jmp fns */
+#define _JBLEN 9
+typedef        int jmp_buf[_JBLEN];
+extern void    kgdb_longjmp(jmp_buf __jmpb, int __retval);
+extern int     kgdb_setjmp(jmp_buf __jmpb);
+
+/* Variadic macro to print our own message to the console */
+#define KGDB_PRINTK(...) printk("KGDB: " __VA_ARGS__)
+
+/* Forced breakpoint */
+#define BREAKPOINT() do {                                     \
+  if (kgdb_enabled) {                                         \
+    asm volatile("trapa   #0xff");                            \
+  }                                                           \
+} while (0)
+
+/* KGDB should be able to flush all kernel text space */
+#if defined(__sh3__)
+#define kgdb_flush_icache_range(start, end)	do { } while (0)
+#elif defined(__SH4__)
+#define kgdb_flush_icache_range(start, end) \
+{									       \
+	extern void __flush_purge_region(void *, int);			       \
+	__flush_purge_region((void*)(start), (int)(end) - (int)(start));       \
+	flush_icache_range((start), (end));				       \
+}
+#endif
+
+
+/* Kernel assert macros */
+#ifdef CONFIG_KGDB_KERNEL_ASSERTS
+
+/* Predefined conditions */
+#define KA_VALID_ERRNO(errno) ((errno) > 0 && (errno) <= EMEDIUMTYPE)
+#define KA_VALID_PTR_ERR(ptr) KA_VALID_ERRNO(-PTR_ERR(ptr))
+#define KA_VALID_KPTR(ptr)  (!(ptr) || \
+              ((void *)(ptr) >= (void *)PAGE_OFFSET &&  \
+               (void *)(ptr) < ERR_PTR(-EMEDIUMTYPE)))
+#define KA_VALID_PTRORERR(errptr) \
+               (KA_VALID_KPTR(errptr) || KA_VALID_PTR_ERR(errptr))
+#define KA_HELD_GKL()  (current->lock_depth >= 0)
+
+/* The actual assert */
+#define KGDB_ASSERT(condition, message) do {                   \
+       if (!(condition) && (kgdb_enabled)) {                   \
+               KGDB_PRINTK("Assertion failed at %s:%d: %s\n",  \
+                                  __FILE__, __LINE__, message);\
+               BREAKPOINT();                                   \
+       }                                                       \
+} while (0)
+#else
+#define KGDB_ASSERT(condition, message)
+#endif
+
+#endif
diff -urN linux-2.4.21-bk11/include/asm-sh/machvec.h linux-2.4.21-bk12/include/asm-sh/machvec.h
--- linux-2.4.21-bk11/include/asm-sh/machvec.h	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/machvec.h	2003-07-17 02:52:30.000000000 -0700
@@ -76,6 +76,7 @@
 	unsigned int mv_hw_hd64465 : 1;
 	unsigned int mv_hw_dreamcast : 1;
 	unsigned int mv_hw_bigsur : 1;
+	unsigned int mv_hw_hs7729pci : 1;
 	unsigned int mv_hw_7751se: 1;
 	unsigned int mv_hw_adx : 1;
 };
@@ -94,6 +95,7 @@
 #define MACH_SH2000	(sh_mv.mv_hw_sh2000)
 #define MACH_DREAMCAST	(sh_mv.mv_hw_dreamcast)
 #define MACH_BIGSUR	(sh_mv.mv_hw_bigsur)
+#define MACH_HS7729PCI	(sh_mv.mv_hw_hs7729pci)
 #define MACH_7751SE	(sh_mv.mv_hw_7751se)
 #define MACH_ADX	(sh_mv.mv_hw_adx)
 #else
@@ -157,6 +159,11 @@
 # else
 #  define MACH_BIGSUR		0
 # endif
+# ifdef CONFIG_SH_HS7729PCI
+#  define MACH_HS7729PCI	1
+# else
+#  define MACH_HS7729PCI	0
+# endif
 # ifdef CONFIG_SH_ADX
 #  define MACH_ADX		1
 # else
diff -urN linux-2.4.21-bk11/include/asm-sh/mmu_context.h linux-2.4.21-bk12/include/asm-sh/mmu_context.h
--- linux-2.4.21-bk11/include/asm-sh/mmu_context.h	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/mmu_context.h	2003-07-17 02:52:30.000000000 -0700
@@ -29,19 +29,32 @@
  */
 #define MMU_VPN_MASK	0xfffff000
 
+/*
+ * Get MMU context if needed.
+ */
 static __inline__ void
-get_new_mmu_context(struct mm_struct *mm)
+get_mmu_context(struct mm_struct *mm)
 {
 	extern void flush_tlb_all(void);
+	unsigned long mc = mmu_context_cache;
 
-	unsigned long mc = ++mmu_context_cache;
+	/* Check if we have old version of context. */
+	if (((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0)
+		/* It's up to date, do nothing */
+		return;
 
+	/* It's old, we need to get new context with new version. */
+	mc = ++mmu_context_cache;
 	if (!(mc & MMU_CONTEXT_ASID_MASK)) {
-		/* We exhaust ASID of this version.
-		   Flush all TLB and start new cycle. */
+		/*
+		 * We exhaust ASID of this version.
+		 * Flush all TLB and start new cycle.
+		 */
 		flush_tlb_all();
-		/* Fix version if needed.
-		   Note that we avoid version #0 to distingush NO_CONTEXT. */
+		/*
+		 * Fix version; Note that we avoid version #0
+		 * to distingush NO_CONTEXT.
+		 */
 		if (!mc)
 			mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION;
 	}
@@ -49,21 +62,6 @@
 }
 
 /*
- * Get MMU context if needed.
- */
-static __inline__ void
-get_mmu_context(struct mm_struct *mm)
-{
-	if (mm) {
-		unsigned long mc = mmu_context_cache;
-		/* Check if we have old version of context.
-		   If it's old, we need to get new context with new version. */
-		if ((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK)
-			get_new_mmu_context(mm);
-	}
-}
-
-/*
  * Initialize the context related info for a new mm_struct
  * instance.
  */
@@ -169,8 +167,6 @@
 	if (prev != next) {
 		unsigned long __pgdir = (unsigned long)next->pgd;
 
-		clear_bit(cpu, &prev->cpu_vm_mask);
-		set_bit(cpu, &next->cpu_vm_mask);
 		__asm__ __volatile__("mov.l	%0, %1"
 				     : /* no output */
 				     : "r" (__pgdir), "m" (__m(MMU_TTB)));
@@ -185,4 +181,5 @@
 enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
 {
 }
+
 #endif /* __ASM_SH_MMU_CONTEXT_H */
diff -urN linux-2.4.21-bk11/include/asm-sh/mmzone.h linux-2.4.21-bk12/include/asm-sh/mmzone.h
--- linux-2.4.21-bk11/include/asm-sh/mmzone.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/mmzone.h	2003-07-17 02:52:30.000000000 -0700
@@ -0,0 +1,61 @@
+/*
+ *  linux/include/asm-sh/mmzone.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_SH_MMZONE_H
+#define __ASM_SH_MMZONE_H
+
+#include <linux/config.h>
+
+/* Currently, just for HP690 */
+#define PHYSADDR_TO_NID(phys)	((((phys) - __MEMORY_START) >= 0x01000000)?1:0)
+#define NR_NODES 2
+
+extern pg_data_t discontig_page_data[NR_NODES];
+extern bootmem_data_t discontig_node_bdata[NR_NODES];
+
+#ifdef CONFIG_DISCONTIGMEM
+/*
+ * Following are macros that each numa implmentation must define.
+ */
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(kaddr)	PHYSADDR_TO_NID(__pa(kaddr))
+
+/*
+ * Return a pointer to the node data for node n.
+ */
+#define NODE_DATA(nid)		(&discontig_page_data[nid])
+
+/*
+ * NODE_MEM_MAP gives the kaddr for the mem_map of the node.
+ */
+#define NODE_MEM_MAP(nid)	(NODE_DATA(nid)->node_mem_map)
+
+#define phys_to_page(phys)						\
+({ unsigned int node = PHYSADDR_TO_NID(phys); 		      		\
+   NODE_MEM_MAP(node)				 		 	\
+     + (((phys) - NODE_DATA(node)->node_start_paddr) >> PAGE_SHIFT); })
+
+static inline int is_valid_page(struct page *page)
+{
+	unsigned int i;
+
+	for (i = 0; i < NR_NODES; i++) {
+		if (page >= NODE_MEM_MAP(i) &&
+		    page < NODE_MEM_MAP(i) + NODE_DATA(i)->node_size)
+			return 1;
+	}
+	return 0;
+}
+
+#define VALID_PAGE(page)	is_valid_page(page)
+#define page_to_phys(page)	PHYSADDR(page_address(page))
+
+#endif /* CONFIG_DISCONTIGMEM */
+#endif
diff -urN linux-2.4.21-bk11/include/asm-sh/parport.h linux-2.4.21-bk12/include/asm-sh/parport.h
--- linux-2.4.21-bk11/include/asm-sh/parport.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/parport.h	2003-07-17 02:52:30.000000000 -0700
@@ -0,0 +1,22 @@
+/*
+ * parport.h: SuperH-specific parport initialisation
+ *
+ * This file should only be included by drivers/parport/parport_pc.c.
+ *
+ */
+
+#ifndef _ASM_SH_PARPORT_H
+#define _ASM_SH_PARPORT_H
+
+#include <asm/machvec.h>
+
+static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
+{
+	if (MACH_HS7729PCI)
+		return !!parport_pc_probe_port(0x378, 0, 5, 
+					       PARPORT_DMA_NONE, NULL);
+
+	return 0;
+}
+
+#endif /* _ASM_SH_PARPORT_H */
diff -urN linux-2.4.21-bk11/include/asm-sh/pci.h linux-2.4.21-bk12/include/asm-sh/pci.h
--- linux-2.4.21-bk11/include/asm-sh/pci.h	2002-02-25 11:38:13.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/pci.h	2003-07-17 02:52:30.000000000 -0700
@@ -11,8 +11,8 @@
 
 #define pcibios_assign_all_busses()	1
 
-#if defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-/* These are currently the correct values for the STM overdrive board. 
+#if defined(CONFIG_CPU_SUBTYPE_ST40)
+/* These are currently the correct values for the ST40 based chips.
  * We need some way of setting this on a board specific way, it will 
  * not be the same on other boards I think
  */
@@ -29,6 +29,9 @@
 #elif defined(CONFIG_SH_7751_SOLUTION_ENGINE)
 #define PCIBIOS_MIN_IO          0x4000
 #define PCIBIOS_MIN_MEM         0xFD000000
+#elif defined(CONFIG_PCI_SD0001)
+#define PCIBIOS_MIN_IO		0x2000
+#define PCIBIOS_MIN_MEM		0x01000000L
 #endif
 
 struct pci_dev;
@@ -50,6 +53,14 @@
 #include <linux/string.h>
 #include <asm/io.h>
 
+struct pci_dev;
+
+/* The PCI address space does equal the physical memory
+ * address space.  The networking and block device layers use
+ * this boolean for bounce buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS	(1)
+
 /* Allocate and map kernel buffer using consistent mode DMA for a device.
  * hwdev should be valid struct pci_dev pointer for PCI devices,
  * NULL for PCI-like buses (ISA, EISA).
diff -urN linux-2.4.21-bk11/include/asm-sh/pgalloc.h linux-2.4.21-bk12/include/asm-sh/pgalloc.h
--- linux-2.4.21-bk11/include/asm-sh/pgalloc.h	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/pgalloc.h	2003-07-17 02:52:30.000000000 -0700
@@ -69,7 +69,7 @@
 #define pgd_populate(mm, pmd, pte)	BUG()
 
 /* Do nothing */
-static inline int do_check_pgt_cache(int low, int high) { }
+static inline int do_check_pgt_cache(int low, int high) { return 0; }
 
 /*
  * TLB flushing:
diff -urN linux-2.4.21-bk11/include/asm-sh/processor.h linux-2.4.21-bk12/include/asm-sh/processor.h
--- linux-2.4.21-bk11/include/asm-sh/processor.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/processor.h	2003-07-17 02:52:30.000000000 -0700
@@ -23,8 +23,8 @@
 enum cpu_type {
 	CPU_SH7708,		/* Represents 7707, 7708, 7708S, 7708R, 7709 */
 	CPU_SH7729,		/* Represents 7709A, 7729 */
-	CPU_SH7750,     /* Represents 7750, 7751 */
-	CPU_ST40STB1,
+	CPU_SH7750,     	/* Represents 7750, 7751 */
+	CPU_ST40,		/* Represents ST40STB1 and ST40GX1 */
 	CPU_SH_NONE
 };
 
@@ -34,7 +34,7 @@
 	unsigned long loops_per_jiffy;
 
 	unsigned int cpu_clock, master_clock, bus_clock, module_clock;
-#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#ifdef CONFIG_CPU_SUBTYPE_ST40
 	unsigned int memory_clock;
 #endif
 };
@@ -104,17 +104,23 @@
 
 	unsigned long trap_no, error_code;
 	unsigned long address;
-	/* Hardware debugging registers may come here */
+
+	/* Hardware debugging registers */
+	unsigned long ubc_pc1, ubc_pc2;
 
 	/* floating point info */
 	union sh_fpu_union fpu;
 };
 
+/* Count of active tasks with UBC settings */
+extern int ubc_usercnt;
+
 #define INIT_THREAD  {						\
 	sizeof(init_stack) + (long) &init_stack, /* sp */	\
 	0,					 /* pc */	\
 	0, 0, 							\
 	0, 							\
+	0, -1, 							\
 	{{{0,}},} 				/* fpu state */	\
 }
 
@@ -184,19 +190,23 @@
 
 #define unlazy_fpu(tsk) do { 			\
 	if ((tsk)->flags & PF_USEDFPU) {	\
-		grab_fpu();			\
 		save_fpu(tsk); 			\
 	}					\
 } while (0)
 
 #define clear_fpu(tsk) do { 			\
-	if ((tsk)->flags & PF_USEDFPU)	 	\
+	if ((tsk)->flags & PF_USEDFPU) { 	\
 		(tsk)->flags &= ~PF_USEDFPU; 	\
+		release_fpu();			\
+	}					\
 } while (0)
 
 /* Double presision, NANS as NANS, rounding to nearest, no exceptions */
 #define FPSCR_INIT  0x00080000
 
+#define	FPSCR_CAUSE_MASK	0x0001f000	/* Cause bits */
+#define	FPSCR_FLAG_MASK		0x0000007c	/* Flag bits */
+
 /*
  * Return saved PC of a blocked thread.
  */
diff -urN linux-2.4.21-bk11/include/asm-sh/ptrace.h linux-2.4.21-bk12/include/asm-sh/ptrace.h
--- linux-2.4.21-bk11/include/asm-sh/ptrace.h	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/ptrace.h	2003-07-17 02:52:30.000000000 -0700
@@ -2,6 +2,7 @@
 #define __ASM_SH_PTRACE_H
 
 #include <asm/processor.h>
+#include <asm/ubc.h>
 
 /*
  * Copyright (C) 1999, 2000  Niibe Yutaka
@@ -20,7 +21,7 @@
  *
  * We follows above, except:
  *	16 --- program counter (PC)
- *	22 --- syscall #
+ *	22 --- syscall # (now just a placeholder)
  *	23 --- floating point communication register
  */
 #define REG_REG0	 0
@@ -36,13 +37,13 @@
 
 #define REG_SYSCALL	22
 
-#define REG_FPUL	23
+#define REG_FPREG0	23
+#define REG_FPREG15	38
+#define REG_XFREG0	39
+#define REG_XFREG15	54
 
-#define REG_FPREG0	24
-#define REG_FPREG15	39
-#define REG_XDREG0	40
-#define REG_XDREG14	47
-#define REG_FPSCR	48
+#define REG_FPSCR	55
+#define REG_FPUL	56
 
 #define PTRACE_SETOPTIONS         21
 
@@ -61,75 +62,13 @@
 	unsigned long gbr;
 	unsigned long mach;
 	unsigned long macl;
-	long syscall_nr;
+	unsigned long dummy;
 };
 
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->sr & 0x40000000)==0)
 #define instruction_pointer(regs) ((regs)->pc)
 extern void show_regs(struct pt_regs *);
-
-/* User Break Controller */
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7709)
-#define UBC_TYPE_SH7729	(cpu_data->type == CPU_SH7729)
-#else
-#define UBC_TYPE_SH7729	0
-#endif
-
-#if defined(__sh3__)
-#define UBC_BARA                0xffffffb0
-#define UBC_BAMRA               0xffffffb4
-#define UBC_BBRA                0xffffffb8
-#define UBC_BASRA               0xffffffe4
-#define UBC_BARB                0xffffffa0
-#define UBC_BAMRB               0xffffffa4
-#define UBC_BBRB                0xffffffa8
-#define UBC_BASRB               0xffffffe8
-#define UBC_BDRB                0xffffff90
-#define UBC_BDMRB               0xffffff94
-#define UBC_BRCR                0xffffff98
-#elif defined(__SH4__)
-#define UBC_BARA		0xff200000
-#define UBC_BAMRA		0xff200004
-#define UBC_BBRA		0xff200008
-#define UBC_BASRA		0xff000014
-#define UBC_BARB		0xff20000c
-#define UBC_BAMRB		0xff200010
-#define UBC_BBRB		0xff200014
-#define UBC_BASRB		0xff000018
-#define UBC_BDRB		0xff200018
-#define UBC_BDMRB		0xff20001c
-#define UBC_BRCR		0xff200020
-#endif
-
-#define BAMR_ASID		(1 << 2)
-#define BAMR_NONE		0
-#define BAMR_10			0x1
-#define BAMR_12			0x2
-#define BAMR_ALL		0x3
-#define BAMR_16			0x8
-#define BAMR_20			0x9
-
-#define BBR_INST		(1 << 4)
-#define BBR_DATA		(2 << 4)
-#define BBR_READ		(1 << 2)
-#define BBR_WRITE		(2 << 2)
-#define BBR_BYTE		0x1
-#define BBR_HALF		0x2
-#define BBR_LONG		0x3
-#define BBR_QUAD		(1 << 6)	/* SH7750 */
-#define BBR_CPU			(1 << 6)	/* SH7709A,SH7729 */
-#define BBR_DMA			(2 << 6)	/* SH7709A,SH7729 */
-
-#define BRCR_CMFA		(1 << 15)
-#define BRCR_CMFB		(1 << 14)
-#define BRCR_PCTE		(1 << 11)
-#define BRCR_PCBA		(1 << 10)	/* 1: after execution */
-#define BRCR_DBEB		(1 << 7)
-#define BRCR_PCBB		(1 << 6)
-#define BRCR_SEQ		(1 << 3)
-#define BRCR_UBDE		(1 << 0)
 #endif
 
 #endif /* __ASM_SH_PTRACE_H */
diff -urN linux-2.4.21-bk11/include/asm-sh/scatterlist.h linux-2.4.21-bk12/include/asm-sh/scatterlist.h
--- linux-2.4.21-bk11/include/asm-sh/scatterlist.h	2001-10-12 15:35:54.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/scatterlist.h	2003-07-17 02:52:30.000000000 -0700
@@ -2,7 +2,12 @@
 #define __ASM_SH_SCATTERLIST_H
 
 struct scatterlist {
-    char *  address;    /* Location data is to be transferred to */
+    char *  address;    /* Location data is to be transferred to, NULL for
+			 * highmem page */
+    struct page * page; /* Location for highmem page, if any */
+    unsigned int offset;/* for highmem, page offset */
+
+    dma_addr_t dma_address;
     unsigned int length;
 };
 
diff -urN linux-2.4.21-bk11/include/asm-sh/segment.h linux-2.4.21-bk12/include/asm-sh/segment.h
--- linux-2.4.21-bk11/include/asm-sh/segment.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/segment.h	2003-07-17 02:52:30.000000000 -0700
@@ -0,0 +1,6 @@
+#ifndef _ASM_SH_SEGMENT_H
+#define _ASM_SH_SEGMENT_H
+
+/* Only here because we have some old header files that expect it.. */
+
+#endif /* _ASM_SH_SEGMENT_H */
diff -urN linux-2.4.21-bk11/include/asm-sh/system.h linux-2.4.21-bk12/include/asm-sh/system.h
--- linux-2.4.21-bk11/include/asm-sh/system.h	2003-06-13 07:51:38.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/system.h	2003-07-17 02:52:30.000000000 -0700
@@ -130,7 +130,9 @@
 }
 
 #define __save_flags(x) \
-	__asm__("stc sr, %0; and #0xf0, %0" : "=&z" (x) :/**/: "memory" )
+	__asm__ __volatile__("stc sr, %0\n\t" \
+			     "and #0xf0, %0"  \
+			     : "=&z" (x) :/**/: "memory" )
 
 static __inline__ unsigned long __save_and_cli(void)
 {
diff -urN linux-2.4.21-bk11/include/asm-sh/types.h linux-2.4.21-bk12/include/asm-sh/types.h
--- linux-2.4.21-bk11/include/asm-sh/types.h	2000-03-05 09:33:55.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/types.h	2003-07-17 02:52:30.000000000 -0700
@@ -44,6 +44,7 @@
 /* Dma addresses are 32-bits wide.  */
 
 typedef u32 dma_addr_t;
+typedef u64 dma64_addr_t;
 
 #endif /* __KERNEL__ */
 
diff -urN linux-2.4.21-bk11/include/asm-sh/uaccess.h linux-2.4.21-bk12/include/asm-sh/uaccess.h
--- linux-2.4.21-bk11/include/asm-sh/uaccess.h	2002-02-25 11:38:13.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/uaccess.h	2003-07-17 02:52:30.000000000 -0700
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.13 2001/10/01 02:22:01 gniibe Exp $
+/* $Id: uaccess.h,v 1.1.1.1.2.4 2002/08/28 16:52:43 gniibe Exp $
  *
  * User space memory access functions
  *
@@ -102,12 +102,11 @@
 } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
 
 #define __get_user_check(x,ptr,size) ({ \
-long __gu_err; \
+long __gu_err = -EFAULT; \
 __typeof__(*(ptr)) __gu_val; \
 long __gu_addr; \
 __asm__("":"=r" (__gu_val)); \
 __gu_addr = (long) (ptr); \
-__asm__("":"=r" (__gu_err)); \
 if (__access_ok(__gu_addr,size)) { \
 switch (size) { \
 case 1: __get_user_asm("b"); break; \
@@ -155,12 +154,11 @@
 } __pu_err; })
 
 #define __put_user_check(x,ptr,size) ({ \
-long __pu_err; \
+long __pu_err = -EFAULT; \
 __typeof__(*(ptr)) __pu_val; \
 long __pu_addr; \
 __pu_val = (x); \
 __pu_addr = (long) (ptr); \
-__asm__("":"=r" (__pu_err)); \
 if (__access_ok(__pu_addr,size)) { \
 switch (size) { \
 case 1: __put_user_asm("b"); break; \
@@ -244,42 +242,7 @@
 
 /* Generic arbitrary sized copy.  */
 /* Return the number of bytes NOT copied */
-/* XXX: should be such that: 4byte and the rest. */
-static __inline__ __kernel_size_t
-__copy_user(void *__to, const void *__from, __kernel_size_t __n)
-{
-	unsigned long __dummy, _f, _t;
-	__kernel_size_t res;
-
-	if ((res = __n))
-	__asm__ __volatile__(
-		"9:\n\t"
-		"mov.b	@%2+, %1\n\t"
-		"dt	%0\n"
-		"1:\n\t"
-		"mov.b	%1, @%3\n\t"
-		"bf/s	9b\n\t"
-		" add	#1, %3\n"
-		"2:\n"
-		".section .fixup,\"ax\"\n"
-		"3:\n\t"
-		"mov.l	5f, %1\n\t"
-		"jmp	@%1\n\t"
-		" add	#1, %0\n\t"
-		".balign 4\n"
-		"5:	.long 2b\n"
-		".previous\n"
-		".section __ex_table,\"a\"\n"
-		"	.balign 4\n"
-		"	.long 9b,2b\n"
-		"	.long 1b,3b\n"
-		".previous"
-		: "=r" (res), "=&z" (__dummy), "=r" (_f), "=r" (_t)
-		: "2" (__from), "3" (__to), "0" (res)
-		: "memory", "t");
-
-	return res;
-}
+extern __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n);
 
 #define copy_to_user(to,from,n) ({ \
 void *__copy_to = (void *) (to); \
@@ -308,39 +271,11 @@
 	__copy_user((void *)(to),		\
 		    (void *)(from), n)
 
-/* XXX: Not sure it works well..
-   should be such that: 4byte clear and the rest. */
-static __inline__ __kernel_size_t
-__clear_user(void *addr, __kernel_size_t size)
-{
-	unsigned long __a;
-
-	__asm__ __volatile__(
-		"9:\n\t"
-		"dt	%0\n"
-		"1:\n\t"
-		"mov.b	%4, @%1\n\t"
-		"bf/s	9b\n\t"
-		" add	#1, %1\n"
-		"2:\n"
-		".section .fixup,\"ax\"\n"
-		"3:\n\t"
-		"mov.l	4f, %1\n\t"
-		"jmp	@%1\n\t"
-		" nop\n"
-		".balign 4\n"
-		"4:	.long 2b\n"
-		".previous\n"
-		".section __ex_table,\"a\"\n"
-		"	.balign 4\n"
-		"	.long 1b,3b\n"
-		".previous"
-		: "=r" (size), "=r" (__a)
-		: "0" (size), "1" (addr), "r" (0)
-		: "memory", "t");
-
-	return size;
-}
+/*
+ * Clear the area and return remaining number of bytes
+ * (on failure.  Usually it's 0.)
+ */
+extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size);
 
 #define clear_user(addr,n) ({ \
 void * __cl_addr = (addr); \
@@ -396,8 +331,6 @@
 __sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \
 } __sfu_res; })
 
-#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
-
 /*
  * Return the size of a string (including the ending 0!)
  */
@@ -436,12 +369,20 @@
 
 static __inline__ long strnlen_user(const char *s, long n)
 {
-	if (!__addr_ok(s))
+	if (!access_ok(VERIFY_READ, s, n))
 		return 0;
 	else
 		return __strnlen_user(s, n);
 }
 
+static __inline__ long strlen_user(const char *s)
+{
+	if (!access_ok(VERIFY_READ, s, 0))
+		return 0;
+	else
+		return __strnlen_user(s, ~0UL >> 1);
+}
+
 struct exception_table_entry
 {
 	unsigned long insn, fixup;
diff -urN linux-2.4.21-bk11/include/asm-sh/ubc.h linux-2.4.21-bk12/include/asm-sh/ubc.h
--- linux-2.4.21-bk11/include/asm-sh/ubc.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4.21-bk12/include/asm-sh/ubc.h	2003-07-17 02:52:30.000000000 -0700
@@ -0,0 +1,73 @@
+#ifndef __ASM_SH_UBC_H
+#define __ASM_SH_UBC_H
+
+/* User Break Controller */
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7709)
+#define UBC_TYPE_SH7729	(cpu_data->type == CPU_SH7729)
+#else
+#define UBC_TYPE_SH7729	0
+#endif
+
+#if defined(__sh3__)
+#define UBC_BARA                0xffffffb0
+#define UBC_BAMRA               0xffffffb4
+#define UBC_BBRA                0xffffffb8
+#define UBC_BASRA               0xffffffe4
+#define UBC_BARB                0xffffffa0
+#define UBC_BAMRB               0xffffffa4
+#define UBC_BBRB                0xffffffa8
+#define UBC_BASRB               0xffffffe8
+#define UBC_BDRB                0xffffff90
+#define UBC_BDMRB               0xffffff94
+#define UBC_BRCR                0xffffff98
+#elif defined(__SH4__)
+#define UBC_BARA		0xff200000
+#define UBC_BAMRA		0xff200004
+#define UBC_BBRA		0xff200008
+#define UBC_BASRA		0xff000014
+#define UBC_BARB		0xff20000c
+#define UBC_BAMRB		0xff200010
+#define UBC_BBRB		0xff200014
+#define UBC_BASRB		0xff000018
+#define UBC_BDRB		0xff200018
+#define UBC_BDMRB		0xff20001c
+#define UBC_BRCR		0xff200020
+#endif
+
+#define BAMR_ASID		(1 << 2)
+#define BAMR_NONE		0
+#define BAMR_10			0x1
+#define BAMR_12			0x2
+#define BAMR_ALL		0x3
+#define BAMR_16			0x8
+#define BAMR_20			0x9
+
+#define BBR_INST		(1 << 4)
+#define BBR_DATA		(2 << 4)
+#define BBR_READ		(1 << 2)
+#define BBR_WRITE		(2 << 2)
+#define BBR_BYTE		0x1
+#define BBR_HALF		0x2
+#define BBR_LONG		0x3
+#define BBR_QUAD		(1 << 6)	/* SH7750 */
+#define BBR_CPU			(1 << 6)	/* SH7709A,SH7729 */
+#define BBR_DMA			(2 << 6)	/* SH7709A,SH7729 */
+
+#define BRCR_CMFA		(1 << 15)
+#define BRCR_CMFB		(1 << 14)
+#define BRCR_PCTE		(1 << 11)
+#define BRCR_PCBA		(1 << 10)	/* 1: after execution */
+#define BRCR_DBEB		(1 << 7)
+#define BRCR_PCBB		(1 << 6)
+#define BRCR_SEQ		(1 << 3)
+#define BRCR_UBDE		(1 << 0)
+
+#ifndef __ASSEMBLY__
+/* arch/sh/kernel/ubc.S */
+extern void ubc_wakeup(void);
+extern void ubc_sleep(void);
+#endif
+
+#endif /* __ASM_SH_UBC_H */
+
diff -urN linux-2.4.21-bk11/include/asm-sh/unistd.h linux-2.4.21-bk12/include/asm-sh/unistd.h
--- linux-2.4.21-bk11/include/asm-sh/unistd.h	2002-08-02 17:39:45.000000000 -0700
+++ linux-2.4.21-bk12/include/asm-sh/unistd.h	2003-07-17 02:52:30.000000000 -0700
@@ -233,6 +233,7 @@
 #define __NR_fcntl64		221
 #define __NR_gettid		222
 #define __NR_tkill		223
+#define __NR_readahead		225
 
 /* user-visible error numbers are in the range -1 - -125: see <asm-sh/errno.h> */
 
diff -urN linux-2.4.21-bk11/include/linux/blkdev.h linux-2.4.21-bk12/include/linux/blkdev.h
--- linux-2.4.21-bk11/include/linux/blkdev.h	2003-07-17 02:52:26.000000000 -0700
+++ linux-2.4.21-bk12/include/linux/blkdev.h	2003-07-17 02:52:30.000000000 -0700
@@ -66,6 +66,7 @@
 
 struct request_list {
 	unsigned int count;
+	unsigned int pending[2];
 	struct list_head free;
 };
 
@@ -295,6 +296,13 @@
 	return q->rq.count == 0;
 }
 
+static inline int blk_oversized_queue_reads(request_queue_t * q)
+{
+	if (q->can_throttle)
+		return atomic_read(&q->nr_sectors) > q->max_queue_sectors + q->batch_sectors;
+	return q->rq.count == 0;
+}
+
 static inline int blk_oversized_queue_batch(request_queue_t * q)
 {
 	return atomic_read(&q->nr_sectors) > q->max_queue_sectors - q->batch_sectors;
diff -urN linux-2.4.21-bk11/include/linux/fs.h linux-2.4.21-bk12/include/linux/fs.h
--- linux-2.4.21-bk11/include/linux/fs.h	2003-07-17 02:52:26.000000000 -0700
+++ linux-2.4.21-bk12/include/linux/fs.h	2003-07-17 02:52:30.000000000 -0700
@@ -221,6 +221,7 @@
 	BH_Launder,	/* 1 if we can throttle on this buffer */
 	BH_Attached,	/* 1 if b_inode_buffers is linked into a list */
 	BH_JBD,		/* 1 if it has an attached journal_head */
+	BH_Sync,	/* 1 if the buffer is a sync read */
 
 	BH_PrivateStart,/* not a state bit, but the first bit available
 			 * for private allocation by other entities
diff -urN linux-2.4.21-bk11/kernel/ksyms.c linux-2.4.21-bk12/kernel/ksyms.c
--- linux-2.4.21-bk11/kernel/ksyms.c	2003-07-17 02:52:26.000000000 -0700
+++ linux-2.4.21-bk12/kernel/ksyms.c	2003-07-17 02:52:30.000000000 -0700
@@ -269,6 +269,7 @@
 EXPORT_SYMBOL(grab_cache_page_nowait);
 EXPORT_SYMBOL(read_cache_page);
 EXPORT_SYMBOL(set_page_dirty);
+EXPORT_SYMBOL(mark_page_accessed);
 EXPORT_SYMBOL(vfs_readlink);
 EXPORT_SYMBOL(vfs_follow_link);
 EXPORT_SYMBOL(page_readlink);
