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

diff -urN linux-2.2.14-pre4/arch/ppc/boot/head.S linux-2.2.14-pre5/arch/ppc/boot/head.S
--- linux-2.2.14-pre4/arch/ppc/boot/head.S	1999-04-29 12:39:01.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/boot/head.S	2003-08-15 15:08:54.000000000 -0700
@@ -6,7 +6,7 @@
 	.text
 
 /*
- * $Id: head.S,v 1.31 1999/04/22 06:32:00 davem Exp $
+ * $Id: head.S,v 1.33 1999/09/08 01:06:58 cort Exp $
  *	
  * Boot loader philosophy:
  *      ROM loads us to some arbitrary location
@@ -125,12 +125,11 @@
 	 * get start address of kernel code which is stored as a coff
 	 * entry.  see boot/head.S -- Cort 
 	 */
-	li	r9,0x0
-	lwz	r9,0(r9)
+	li	r9,0x4
 	mtlr	r9
-	li	r9,0
 	lis	r10,0xdeadc0de@h
 	ori	r10,r10,0xdeadc0de@l
+	li	r9,0
 	stw	r10,0(r9)
 /*
  * The Radstone firmware maps PCI memory at 0xc0000000 using BAT2
diff -urN linux-2.2.14-pre4/arch/ppc/boot/Makefile linux-2.2.14-pre5/arch/ppc/boot/Makefile
--- linux-2.2.14-pre4/arch/ppc/boot/Makefile	1999-08-25 17:29:46.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/boot/Makefile	2003-08-15 15:08:54.000000000 -0700
@@ -25,12 +25,22 @@
 IOFF = 0
 ISZ = 0
 
+ifeq ($(CONFIG_ALL_PPC),y)
+CONFIG_PREP=y
+endif
+
 ifeq ($(CONFIG_SMP),y)
 TFTPIMAGE=/tftpboot/zImage.prep.smp$(MSIZE)
 else
 TFTPIMAGE=/tftpboot/zImage.prep$(MSIZE)
 endif
 
+ifeq ($(CONFIG_SMP),y)
+TFTPSIMAGE=/tftpboot/sImage.smp
+else
+TFTPSIMAGE=/tftpboot/sImage
+endif
+
 ifeq ($(CONFIG_PPC64),y)
 MSIZE=.64
 else
@@ -46,14 +56,10 @@
 OBJCOPY = $(CROSS_COMPILE)objcopy
 OBJCOPY_ARGS = -O elf32-powerpc
 
-ifeq ($(CONFIG_SMP),y)
-CFLAGS += -D__SMP__
-endif
-
 OBJECTS += vreset.o kbd.o of1275.o
- ifeq ($(CONFIG_SERIAL_CONSOLE),y)
-  OBJECTS += ns16550.o
- endif
+ifeq ($(CONFIG_SERIAL_CONSOLE),y)
+OBJECTS += ns16550.o
+endif
 
 all:	zImage
 
@@ -75,11 +81,20 @@
 		zvmlinux.initrd.tmp $@
 	rm zvmlinux.initrd.tmp
 
-zImage: zvmlinux mkprep
+zImage: zvmlinux mkprep sImage
+ifdef CONFIG_PREP
 	./mkprep -pbp zvmlinux zImage
+endif
+
+sImage: ../../../vmlinux
+ifdef CONFIG_GEMINI
+	$(OBJCOPY) -I elf32-powerpc -O binary ../../../vmlinux sImage
+endif
 
 zImage.initrd: zvmlinux.initrd mkprep
+ifdef CONFIG_PREP
 	./mkprep -pbp zvmlinux.initrd zImage.initrd
+endif
 
 zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
 #
@@ -108,7 +123,12 @@
 	$(HOSTCC) -o mkprep mkprep.c
 
 znetboot : zImage
+ifdef CONFIG_PREP
 	cp zImage $(TFTPIMAGE)
+endif
+ifdef CONFIG_GEMINI
+	cp sImage $(TFTPSIMAGE)
+endif
 
 znetboot.initrd : zImage.initrd
 	cp zImage.initrd $(TFTPIMAGE)
diff -urN linux-2.2.14-pre4/arch/ppc/chrpboot/main.c linux-2.2.14-pre5/arch/ppc/chrpboot/main.c
--- linux-2.2.14-pre4/arch/ppc/chrpboot/main.c	1999-08-09 12:04:57.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/chrpboot/main.c	2003-08-15 15:08:54.000000000 -0700
@@ -68,7 +68,7 @@
 
     flush_cache(dst, len);
     
-    sa = *(unsigned long *)PROG_START+PROG_START;
+    sa = (unsigned long)PROG_START;
     printf("start address = 0x%x\n\r", sa);
 
     (*(void (*)())sa)(0, 0, prom, a1, a2);
diff -urN linux-2.2.14-pre4/arch/ppc/coffboot/main.c linux-2.2.14-pre5/arch/ppc/coffboot/main.c
--- linux-2.2.14-pre4/arch/ppc/coffboot/main.c	1998-08-04 16:06:36.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/coffboot/main.c	2003-08-15 15:08:54.000000000 -0700
@@ -100,7 +100,7 @@
 
     flush_cache(dst, len);
 
-    sa = *(unsigned *)dst + PROG_START;
+    sa = (unsigned long)dst;
     printf("start address = 0x%x\n", sa);
 
 #if 0
@@ -165,7 +165,6 @@
 	printf("gunzip: ran out of data in header\n");
 	exit();
     }
-
     s.zalloc = zalloc;
     s.zfree = zfree;
     r = inflateInit2(&s, -MAX_WBITS);
diff -urN linux-2.2.14-pre4/arch/ppc/common_defconfig linux-2.2.14-pre5/arch/ppc/common_defconfig
--- linux-2.2.14-pre4/arch/ppc/common_defconfig	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/common_defconfig	2003-08-15 15:08:54.000000000 -0700
@@ -7,13 +7,13 @@
 #
 CONFIG_PPC=y
 CONFIG_6xx=y
-# CONFIG_PPC64 is not set
 # CONFIG_8xx is not set
 # CONFIG_PMAC is not set
 # CONFIG_PREP is not set
 # CONFIG_CHRP is not set
 CONFIG_ALL_PPC=y
 # CONFIG_APUS is not set
+# CONFIG_GEMINI is not set
 # CONFIG_MBX is not set
 # CONFIG_SMP is not set
 CONFIG_6xx=y
@@ -179,6 +179,7 @@
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
 CONFIG_AIC7XXX_PROC_STATS=y
 CONFIG_AIC7XXX_RESET_DELAY=15
+# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -197,6 +198,7 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_NCR53C8XX is not set
 CONFIG_SCSI_SYM53C8XX=y
@@ -244,6 +246,7 @@
 CONFIG_NET_ETHERNET=y
 CONFIG_MACE=y
 CONFIG_BMAC=y
+# CONFIG_NCR885E is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
@@ -258,6 +261,7 @@
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
+# CONFIG_DM9102 is not set
 CONFIG_DE4X5=y
 # CONFIG_DEC_ELCP is not set
 # CONFIG_DGRS is not set
@@ -302,7 +306,9 @@
 # CONFIG_HOSTESS_SV11 is not set
 # CONFIG_COSA is not set
 # CONFIG_SEALEVEL_4021 is not set
+# CONFIG_COMX is not set
 # CONFIG_DLCI is not set
+# CONFIG_SBNI is not set
 
 #
 # Amateur Radio support
@@ -337,6 +343,7 @@
 CONFIG_FB_MATROX_MYSTIQUE=y
 CONFIG_FB_MATROX_G100=y
 # CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_ATY is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_CFB8=y
@@ -493,8 +500,10 @@
 #
 CONFIG_SOUND=y
 CONFIG_DMASOUND=y
+# CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_MAESTRO is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_SONICVIBES is not set
 # CONFIG_SOUND_MSNDCLAS is not set
@@ -503,13 +512,13 @@
 # CONFIG_SOUND_DMAP is not set
 # CONFIG_SOUND_PAS is not set
 # CONFIG_SOUND_SB is not set
-# CONFIG_SOUND_ADLIB is not set
 # CONFIG_SOUND_GUS is not set
 # CONFIG_SOUND_MPU401 is not set
 # CONFIG_SOUND_PSS is not set
 # CONFIG_SOUND_MSS is not set
 # CONFIG_SOUND_SSCAPE is not set
 # CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_MAD16 is not set
 # CONFIG_SOUND_WAVEFRONT is not set
 CONFIG_SOUND_CS4232=m
@@ -522,6 +531,7 @@
 # CONFIG_SOUND_YM3812 is not set
 # CONFIG_SOUND_VMIDI is not set
 # CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_NM256 is not set
 
 #
 # Additional low level sound drivers
diff -urN linux-2.2.14-pre4/arch/ppc/config.in linux-2.2.14-pre5/arch/ppc/config.in
--- linux-2.2.14-pre4/arch/ppc/config.in	1999-10-19 17:14:00.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/config.in	2003-08-15 15:08:54.000000000 -0700
@@ -9,7 +9,6 @@
 define_bool CONFIG_PPC y
 choice 'Processor type' \
 	"6xx/7xx		CONFIG_6xx \
-	 630/Power3(64-Bit) 	CONFIG_PPC64 \
 	 860/821		CONFIG_8xx" 6xx/7xx
 
 choice 'Machine Type' \
@@ -18,6 +17,7 @@
 	 CHRP		CONFIG_CHRP \
 	 PowerMac/PReP/CHRP	CONFIG_ALL_PPC \
   	 APUS           CONFIG_APUS \
+	 Gemini		CONFIG_GEMINI \
 	 MBX		CONFIG_MBX" PowerMac
 
 bool 'Symmetric multi-processing support' CONFIG_SMP
diff -urN linux-2.2.14-pre4/arch/ppc/defconfig linux-2.2.14-pre5/arch/ppc/defconfig
--- linux-2.2.14-pre4/arch/ppc/defconfig	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/defconfig	2003-08-15 15:08:54.000000000 -0700
@@ -7,13 +7,13 @@
 #
 CONFIG_PPC=y
 CONFIG_6xx=y
-# CONFIG_PPC64 is not set
 # CONFIG_8xx is not set
 # CONFIG_PMAC is not set
 # CONFIG_PREP is not set
 # CONFIG_CHRP is not set
 CONFIG_ALL_PPC=y
 # CONFIG_APUS is not set
+# CONFIG_GEMINI is not set
 # CONFIG_MBX is not set
 # CONFIG_SMP is not set
 CONFIG_6xx=y
@@ -179,6 +179,7 @@
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
 CONFIG_AIC7XXX_PROC_STATS=y
 CONFIG_AIC7XXX_RESET_DELAY=15
+# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -197,6 +198,7 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_NCR53C8XX is not set
 CONFIG_SCSI_SYM53C8XX=y
@@ -244,6 +246,7 @@
 CONFIG_NET_ETHERNET=y
 CONFIG_MACE=y
 CONFIG_BMAC=y
+# CONFIG_NCR885E is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
@@ -258,6 +261,7 @@
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
+# CONFIG_DM9102 is not set
 CONFIG_DE4X5=y
 # CONFIG_DEC_ELCP is not set
 # CONFIG_DGRS is not set
@@ -302,7 +306,9 @@
 # CONFIG_HOSTESS_SV11 is not set
 # CONFIG_COSA is not set
 # CONFIG_SEALEVEL_4021 is not set
+# CONFIG_COMX is not set
 # CONFIG_DLCI is not set
+# CONFIG_SBNI is not set
 
 #
 # Amateur Radio support
@@ -337,6 +343,7 @@
 CONFIG_FB_MATROX_MYSTIQUE=y
 CONFIG_FB_MATROX_G100=y
 # CONFIG_FB_MATROX_MULTIHEAD is not set
+# CONFIG_FB_ATY is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_CFB8=y
@@ -493,8 +500,10 @@
 #
 CONFIG_SOUND=y
 CONFIG_DMASOUND=y
+# CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_MAESTRO is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_SONICVIBES is not set
 # CONFIG_SOUND_MSNDCLAS is not set
@@ -503,13 +512,13 @@
 # CONFIG_SOUND_DMAP is not set
 # CONFIG_SOUND_PAS is not set
 # CONFIG_SOUND_SB is not set
-# CONFIG_SOUND_ADLIB is not set
 # CONFIG_SOUND_GUS is not set
 # CONFIG_SOUND_MPU401 is not set
 # CONFIG_SOUND_PSS is not set
 # CONFIG_SOUND_MSS is not set
 # CONFIG_SOUND_SSCAPE is not set
 # CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_MAD16 is not set
 # CONFIG_SOUND_WAVEFRONT is not set
 CONFIG_SOUND_CS4232=m
@@ -522,6 +531,7 @@
 # CONFIG_SOUND_YM3812 is not set
 # CONFIG_SOUND_VMIDI is not set
 # CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_NM256 is not set
 
 #
 # Additional low level sound drivers
diff -urN linux-2.2.14-pre4/arch/ppc/gemini_defconfig linux-2.2.14-pre5/arch/ppc/gemini_defconfig
--- linux-2.2.14-pre4/arch/ppc/gemini_defconfig	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.14-pre5/arch/ppc/gemini_defconfig	2003-08-15 15:08:54.000000000 -0700
@@ -0,0 +1,380 @@
+#
+# Automatically generated make config: don't edit
+#
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_6xx=y
+# CONFIG_8xx is not set
+# CONFIG_PMAC is not set
+# CONFIG_PREP is not set
+# CONFIG_CHRP is not set
+# CONFIG_ALL_PPC is not set
+# CONFIG_APUS is not set
+CONFIG_GEMINI=y
+# CONFIG_MBX is not set
+# CONFIG_SMP is not set
+CONFIG_MACH_SPECIFIC=y
+CONFIG_6xx=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+CONFIG_PCI=y
+# CONFIG_PCI_QUIRKS is not set
+# CONFIG_PCI_OLD_PROC is not set
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_BINFMT_JAVA is not set
+# CONFIG_PARPORT is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_FB is not set
+# CONFIG_PMAC_PBOOK is not set
+# CONFIG_MAC_KEYBOARD is not set
+# CONFIG_MAC_FLOPPY is not set
+# CONFIG_MAC_SERIAL is not set
+# CONFIG_ADBMOUSE is not set
+# CONFIG_PROC_DEVICETREE is not set
+# CONFIG_TOTALMP is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_MOTOROLA_HOTSWAP is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_IDE is not set
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_ONLY is not set
+
+#
+# Additional Block Devices
+#
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_PARIDE_PARPORT=y
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_NETLINK=y
+# CONFIG_RTNETLINK is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_FIREWALL is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_IP_ROUTER is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_IP_ALIAS=y
+CONFIG_SYN_COOKIES=y
+
+#
+# (it is safe to leave these untouched)
+#
+# CONFIG_INET_RARP is not set
+CONFIG_SKB_LARGE=y
+# CONFIG_IPV6 is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+# CONFIG_CPU_IS_SLOW is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_G_NCR5380_PORT is not set
+# CONFIG_SCSI_G_NCR5380_MEM is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+CONFIG_SCSI_SYM53C8XX=y
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
+# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_SEAGATE is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_ETHERTAP is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+CONFIG_NCR885E=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_EISA is not set
+# CONFIG_NET_POCKET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_RADIO is not set
+
+#
+# Token ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_HOSTESS_SV11 is not set
+# CONFIG_COSA is not set
+# CONFIG_SEALEVEL_4021 is not set
+# CONFIG_COMX is not set
+# CONFIG_DLCI is not set
+# CONFIG_SBNI is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Console drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+# CONFIG_MOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+
+#
+# Video For Linux
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Joystick support
+#
+# CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_FT_NORMAL_DEBUG is not set
+# CONFIG_FT_FULL_DEBUG is not set
+# CONFIG_FT_NO_TRACE is not set
+# CONFIG_FT_NO_TRACE_AT_ALL is not set
+# CONFIG_FT_STD_FDC is not set
+# CONFIG_FT_MACH2 is not set
+# CONFIG_FT_PROBE_FC10 is not set
+# CONFIG_FT_ALT_FDC is not set
+
+#
+# USB drivers - not for the faint of heart
+#
+# CONFIG_USB is not set
+
+#
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_FAT_FS is not set
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_EFS_FS is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_SUNRPC is not set
+# CONFIG_LOCKD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_BSD_DISKLABEL is not set
+CONFIG_MAC_PARTITION=y
+# CONFIG_SMD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_KGDB is not set
+# CONFIG_XMON is not set
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/chrp_setup.c linux-2.2.14-pre5/arch/ppc/kernel/chrp_setup.c
--- linux-2.2.14-pre4/arch/ppc/kernel/chrp_setup.c	1999-08-25 17:29:46.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/kernel/chrp_setup.c	2003-08-15 15:08:54.000000000 -0700
@@ -446,6 +446,7 @@
 			(*(unsigned long *)get_property(np,
 							"8259-interrupt-acknowledge", NULL));
 	}
+	open_pic.irq_offset = 16;
 	for ( i = 16 ; i < NR_IRQS ; i++ )
 		irq_desc[i].ctl = &open_pic;
 	/* openpic knows that it's at irq 16 offset
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/gemini_pci.c linux-2.2.14-pre5/arch/ppc/kernel/gemini_pci.c
--- linux-2.2.14-pre4/arch/ppc/kernel/gemini_pci.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.14-pre5/arch/ppc/kernel/gemini_pci.c	2003-08-15 15:08:54.000000000 -0700
@@ -0,0 +1,273 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/malloc.h>
+
+#include <asm/machdep.h>
+#include <asm/gemini.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include "pci.h"
+
+#define pci_config_addr(bus,dev,offset) \
+        (0x80000000 | (bus<<16) | (dev<<8) | offset)
+
+
+int
+gemini_pcibios_read_config_byte(unsigned char bus, unsigned char dev,
+                                unsigned char offset, unsigned char *val)
+{
+	unsigned long reg;
+	reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
+	*val = ((reg >> ((offset & 0x3) << 3)) & 0xff);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_read_config_word(unsigned char bus, unsigned char dev,
+                                unsigned char offset, unsigned short *val)
+{
+	unsigned long reg;
+	reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
+	*val = ((reg >> ((offset & 0x3) << 3)) & 0xffff);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_read_config_dword(unsigned char bus, unsigned char dev,
+                                 unsigned char offset, unsigned int *val)
+{
+	*val = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_byte(unsigned char bus, unsigned char dev,
+                                 unsigned char offset, unsigned char val)
+{
+	unsigned long reg;
+	int shifts = offset & 0x3;
+
+	reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
+	reg = (reg & ~(0xff << (shifts << 3))) | (val << (shifts << 3));
+	grackle_write( pci_config_addr( bus, dev, (offset & ~(0x3))), reg );
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_word(unsigned char bus, unsigned char dev,
+                                 unsigned char offset, unsigned short val)
+{
+	unsigned long reg;
+	int shifts = offset & 0x3;
+
+	reg = grackle_read( pci_config_addr( bus, dev, (offset & ~(0x3))));
+	reg = (reg & ~(0xffff << (shifts << 3))) | (val << (shifts << 3));
+	grackle_write( pci_config_addr( bus, dev, (offset & ~(0x3))), reg );
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_dword(unsigned char bus, unsigned char dev,
+                                  unsigned char offset, unsigned int val)
+{
+	grackle_write( pci_config_addr( bus, dev, (offset & ~(0x3))), val );
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct gemini_device {
+	unsigned short vendor, device;
+	unsigned char irq;
+	unsigned short cmd;
+	unsigned char cache_line, latency;
+	void (*init)(struct pci_dev *dev);
+};
+
+static struct gemini_device gemini_map[] = {
+	{ PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C885, 11, 0x15, 32, 248, NULL },
+	{ PCI_VENDOR_ID_NCR, 0x701, 10, 0, 0, 0, NULL },
+	{ PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C042, 3, 0, 0, 0, NULL },
+	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_MPIC, 0xff, 0, 0, 0, NULL },
+	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_CMD_670, 0xff, 0, 0, 0, NULL },
+	{ PCI_VENDOR_ID_MOTOROLA, PCI_DEVICE_ID_MOTOROLA_MPC106, 0xff, 0, 0, 0, NULL },
+};
+
+static int gemini_map_count = (sizeof( gemini_map ) /
+                               sizeof( gemini_map[0] ));
+
+ 
+
+/*  This just sets up the known devices on the board. */
+__initfunc(static void mapin_device( struct pci_dev *dev ))
+{
+	struct gemini_device *p;
+	unsigned short cmd;
+	int i;
+  
+
+	for( i=0; i < gemini_map_count; i++ ) {
+		p = &(gemini_map[i]);
+    
+		if ( p->vendor == dev->vendor && 
+		     p->device == dev->device ) {
+     
+			if (p->irq != 0xff) {
+				pci_write_config_byte( dev, PCI_INTERRUPT_LINE, p->irq );
+				dev->irq = p->irq;
+			}
+
+			if (p->cmd) {
+				pci_read_config_word( dev, PCI_COMMAND, &cmd );
+				pci_write_config_word( dev, PCI_COMMAND, (p->cmd|cmd));
+			}
+
+			if (p->cache_line)
+				pci_write_config_byte( dev, PCI_CACHE_LINE_SIZE, p->cache_line );
+ 
+			if (p->latency)
+				pci_write_config_byte( dev, PCI_LATENCY_TIMER, p->latency );
+		}
+	}
+}
+
+#define KB 1024
+#define MB (KB*KB)
+
+#define ALIGN(val,align) (((val) + ((align) -1))&(~((align) -1)))
+#define MAX(a,b)   (((a) > (b)) ? (a) : (b))
+
+#define FIRST_IO_ADDR 0x10000
+#define FIRST_MEM_ADDR 0x02000000
+
+#define GEMINI_PCI_MEM_BASE (0xf0000000)
+#define GEMINI_PCI_IO_BASE  (0xfe800000)
+
+static unsigned long pci_mem_base = GEMINI_PCI_MEM_BASE;
+static unsigned long pci_io_base = GEMINI_PCI_IO_BASE;
+
+static unsigned int io_base = FIRST_IO_ADDR;
+static unsigned int mem_base = FIRST_MEM_ADDR;
+
+
+
+__initfunc(static void layout_dev( struct pci_dev *dev ))
+{
+	int i;
+	struct pci_bus *bus;
+	unsigned short cmd;
+	unsigned int reg, base, mask, size, alignto, type;
+
+	bus = dev->bus;
+
+	/* make any known settings happen */
+	mapin_device( dev );
+
+	gemini_pcibios_read_config_word( bus->number, dev->devfn, PCI_COMMAND, &cmd );
+
+	for( reg = PCI_BASE_ADDRESS_0, i=0; reg <= PCI_BASE_ADDRESS_5; reg += 4, i++ ) {
+    
+		/* MPIC already done */
+		if (dev->vendor == PCI_VENDOR_ID_IBM &&
+		    dev->device == PCI_DEVICE_ID_IBM_MPIC)
+			return;
+
+		gemini_pcibios_write_config_dword( bus->number, dev->devfn, reg, 0xffffffff );
+		gemini_pcibios_read_config_dword( bus->number, dev->devfn, reg, &base );
+		if (!base) {
+			dev->base_address[i] = 0;
+			continue;
+		}
+
+		if (base & PCI_BASE_ADDRESS_SPACE_IO) {
+			cmd |= PCI_COMMAND_IO;
+			base &= PCI_BASE_ADDRESS_IO_MASK;
+			mask = (~base << 1) | 0x1;
+			size = (mask & base) & 0xffffffff;
+			alignto = MAX(0x400, size);
+			base = ALIGN(io_base, alignto);
+			io_base = base + size;
+			gemini_pcibios_write_config_dword( bus->number, dev->devfn, reg, 
+							   ((pci_io_base + base) & 0x00ffffff) | 0x1);
+			dev->base_address[i] = (pci_io_base + base) | 0x1;
+		}
+
+		else {
+			cmd |= PCI_COMMAND_MEMORY;
+			type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+			mask = (~base << 1) | 0x1;
+			size = (mask & base) & 0xffffffff;
+			switch( type ) {
+
+			case PCI_BASE_ADDRESS_MEM_TYPE_32:
+				break;
+			case PCI_BASE_ADDRESS_MEM_TYPE_64:
+				printk("Warning: Ignoring 64-bit device; slot %d, function %d.\n",
+				       PCI_SLOT( dev->devfn ), PCI_FUNC( dev->devfn ));
+				reg += 4;
+				continue;
+			}
+
+			alignto = MAX(0x1000, size);
+			base = ALIGN(mem_base, alignto);
+			mem_base = base + size;
+			gemini_pcibios_write_config_dword( bus->number, dev->devfn,
+							   reg, (pci_mem_base + base));
+			dev->base_address[i] = pci_mem_base + base;
+		}
+	}
+
+	if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
+		cmd |= PCI_COMMAND_IO;
+
+	gemini_pcibios_write_config_word( bus->number, dev->devfn, PCI_COMMAND,
+					  (cmd|PCI_COMMAND_MASTER));
+
+}
+
+__initfunc(static void layout_bus( struct pci_bus *bus ))
+{
+	struct pci_dev *dev;
+
+	if (!bus->devices && !bus->children)
+		return;
+
+	io_base = ALIGN(io_base, 4*KB);
+	mem_base = ALIGN(mem_base, 4*KB);
+
+	for( dev = bus->devices; dev; dev = dev->sibling ) {
+		if (((dev->class >> 16) != PCI_BASE_CLASS_BRIDGE) ||
+		    ((dev->class >> 8) == PCI_CLASS_BRIDGE_OTHER))
+			layout_dev( dev );
+	}
+}
+
+
+__initfunc(void gemini_pcibios_fixup(void))
+{
+	struct pci_bus *bus;
+	unsigned long orig_mem_base, orig_io_base;
+
+	orig_mem_base = pci_mem_base;
+	orig_io_base = pci_io_base;
+
+	for( bus = &pci_root; bus; bus = bus->children )
+		layout_bus( bus );
+
+	pci_mem_base = orig_mem_base;
+	pci_io_base = orig_io_base;
+
+
+}
+
+decl_config_access_method(gemini);
+
+/* The "bootloader" for Synergy boards does none of this for us, so we need to
+   lay it all out ourselves... --Dan */
+__initfunc(void gemini_setup_pci_ptrs(void))
+{
+
+	set_config_access_method(gemini);
+	ppc_md.pcibios_fixup = gemini_pcibios_fixup;
+}
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/gemini_prom.S linux-2.2.14-pre5/arch/ppc/kernel/gemini_prom.S
--- linux-2.2.14-pre4/arch/ppc/kernel/gemini_prom.S	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.14-pre5/arch/ppc/kernel/gemini_prom.S	2003-08-15 15:08:54.000000000 -0700
@@ -0,0 +1,94 @@
+/*
+ *  arch/ppc/kernel/gemini_prom.S
+ *
+ *  Not really prom support code (yet), but sort of anti-prom code.  The current
+ *  bootloader does a number of things it shouldn't and doesn't do things that it
+ *  should.  The stuff in here is mainly a hodge-podge collection of setup code
+ *  to get the board up and running.
+ *    ---Dan
+ */
+
+#include "ppc_asm.tmpl"
+#include "ppc_defs.h"
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/gemini.h>
+
+#define HID0_ABE (1<<3)
+
+/*
+ *  On 750's the MMU is on when Linux is booted, so we need to clear out the
+ *  bootloader's BAT settings, make sure we're in supervisor state (gotcha!),
+ *  and turn off the MMU.
+ *
+ */
+
+_GLOBAL(gemini_prom_init)
+#ifdef __SMP__
+	/* Since the MMU's on, get stuff in rom space that we'll need */
+	lis	r4,GEMINI_CPUSTAT@h
+	ori	r4,r4,GEMINI_CPUSTAT@l
+	lbz	r5,0(r4)
+	andi.	r5,r5,3
+	mr	r24,r5		/* cpu # used later on */
+#endif
+	mfmsr	r4
+	li	r3,MSR_PR	/* ensure supervisor! */
+	ori	r3,r3,MSR_IR|MSR_DR
+	andc	r4,r4,r3
+	mtmsr	r4
+#if 0
+	/* zero out the bats now that the MMU is off */
+prom_no_mmu:	
+	li	r3,0
+        mtspr   IBAT0U,r3
+        mtspr   IBAT0L,r3
+        mtspr   IBAT1U,r3
+        mtspr   IBAT1L,r3
+        mtspr   IBAT2U,r3
+        mtspr   IBAT2L,r3
+        mtspr   IBAT3U,r3
+        mtspr   IBAT3L,r3
+
+        mtspr   DBAT0U,r3
+        mtspr   DBAT0L,r3
+        mtspr   DBAT1U,r3
+        mtspr   DBAT1L,r3
+        mtspr   DBAT2U,r3
+	mtspr   DBAT2L,r3
+        mtspr   DBAT3U,r3
+        mtspr   DBAT3L,r3
+#endif
+
+	/* the bootloader (as far as I'm currently aware) doesn't mess with page
+	   tables, but since we're already here, might as well zap these, too */
+	li	r4,0
+	mtspr	SDR1,r4
+
+	li	r4,16
+	mtctr	r4
+	li	r3,0
+	li	r4,0
+3:	mtsrin	r3,r4
+	addi	r3,r3,1
+	bdnz	3b
+
+#ifdef __SMP__
+	/* The 750 book (and Mot/IBM support) says that this will "assist" snooping
+	   when in SMP.  Not sure yet whether this should stay or leave... */
+	mfspr	r4,HID0
+	ori	r4,r4,HID0_ABE
+	mtspr	HID0,r4
+	sync
+#endif /* __SMP__ */
+	blr
+
+/*  apparently, SMon doesn't pay attention to HID0[SRST].  Disable the MMU and
+    branch to 0xfff00100 */
+_GLOBAL(_gemini_reboot)
+	lis	r5,GEMINI_BOOT_INIT@h
+	ori	r5,r5,GEMINI_BOOT_INIT@l
+	li	r6,MSR_IP
+	mtspr	SRR0,r5
+	mtspr	SRR1,r6
+	rfi
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/gemini_setup.c linux-2.2.14-pre5/arch/ppc/kernel/gemini_setup.c
--- linux-2.2.14-pre4/arch/ppc/kernel/gemini_setup.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.14-pre5/arch/ppc/kernel/gemini_setup.c	2003-08-15 15:08:54.000000000 -0700
@@ -0,0 +1,582 @@
+/*
+ *  linux/arch/ppc/kernel/setup.c
+ *
+ *  Copyright (C) 1995 Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ *  Synergy Microsystems board support by Dan Cox (dan@synergymicro.com)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h> 
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blk.h>
+#include <linux/console.h>
+#include <linux/openpic.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/m48t35.h>
+#include <asm/gemini.h>
+
+#include "time.h"
+#include "local_irq.h"
+#include "open_pic.h"
+
+void gemini_setup_pci_ptrs(void);
+
+static int l2_printed = 0;
+static unsigned char gemini_switch_map = 0;
+static char *gemini_board_families[] = {
+	"VGM", "VSS", "KGM", "VGR", "KSS"
+};
+
+static char *gemini_memtypes[] = {
+	"EDO DRAM, 60nS", "SDRAM, 15nS, CL=2", "SDRAM, 15nS, CL=2 with ECC"
+};
+
+static unsigned int cpu_7xx[16] = {
+	0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+static unsigned int cpu_6xx[16] = {
+	0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
+};
+
+void
+gemini_do_IRQ(struct pt_regs *regs, int cpu, int isfake)
+{
+	int irq, openpic_eoi_done = 0;
+	unsigned long bits = 0;
+	
+#ifdef __SMP__
+	if (cpu != 0) {
+		if (!isfake) {
+			smp_message_recv();
+			goto out;
+		}
+		goto out;
+	}
+	
+	{
+		unsigned int loops = 1000000;
+		while(test_bit(0, &global_irq_lock)) {
+			if (smp_processor_id() == global_irq_holder) {
+				printk("uh oh, it chokes!!! interrupt while we hold irq lock\n");
+				break;
+			}
+			if (loops-- == 0) {
+				printk("do_IRQ waiting for irq lock (holder=%d)\n", 
+				       global_irq_holder);
+			}
+		}
+	}
+#endif
+
+	irq = openpic_irq(cpu);
+	
+	if (irq == OPENPIC_VEC_SPURIOUS) {
+		ppc_spurious_interrupts++;
+		openpic_eoi_done = 1;
+		goto out;
+	}
+	
+	bits = 1UL<<irq;
+	irq -= OPENPIC_VEC_SOURCE;
+	
+	if (irq < 0) {
+		printk(KERN_DEBUG "Bogus interrupt %d from pc=%lx\n", irq,
+		       regs->nip);
+		ppc_spurious_interrupts++;
+	}
+	
+	else
+		ppc_irq_dispatch_handler(regs, irq);
+ out:
+	if (!openpic_eoi_done)
+		openpic_eoi(0);
+}
+
+static inline unsigned long _get_HID1(void)
+{
+	unsigned long val;
+
+	__asm__ __volatile__("mfspr %0,1009" : "=r" (val));
+	return val;
+}
+
+int
+gemini_get_cpuinfo(char *buffer)
+{
+	int i, len;
+	unsigned char reg, rev;
+	char *family;
+	unsigned int type;
+
+	reg = readb(GEMINI_FEAT);
+	family = gemini_board_families[((reg>>4) & 0xf)];
+	if (((reg>>4) & 0xf) > 2)
+		printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
+
+	reg = readb(GEMINI_BREV);
+	type = (reg>>4) & 0xf;
+	rev = reg & 0xf;
+
+	reg = readb(GEMINI_BECO);
+
+	len = sprintf( buffer, "machine\t\t: Gemini %s%d, rev %c, eco %d\n", 
+		       family, type, (rev + 'A'), (reg & 0xf));
+
+	len += sprintf( buffer+len, "vendor\t\t: %s\n", 
+			(_get_PVR() & (1<<15)) ? "IBM" : "Motorola");
+
+	reg = readb(GEMINI_MEMCFG);
+	len += sprintf( buffer+len, "memory type\t: %s\n", 
+			gemini_memtypes[(reg & 0xc0)>>6]);
+	len += sprintf( buffer+len, "switches on\t: ");
+	for( i=0; i < 8; i++ ) {
+		if ( gemini_switch_map & (1<<i))
+			len += sprintf(buffer+len, "%d ", i);
+	}
+	len += sprintf(buffer+len, "\n");
+
+	return len;
+}
+
+static u_char gemini_openpic_initsenses[] = {
+	1,
+	1,
+	1,
+	1,
+	0,
+	0,
+	1, /* remainder are level-triggered */
+};
+
+#define GEMINI_MPIC_ADDR (0xfcfc0000)
+#define GEMINI_MPIC_PCI_CFG (0x80005800)
+
+void __init gemini_openpic_init(void)
+{
+	grackle_write(GEMINI_MPIC_PCI_CFG + PCI_BASE_ADDRESS_0, 
+		      GEMINI_MPIC_ADDR);
+	grackle_write(GEMINI_MPIC_PCI_CFG + PCI_COMMAND, PCI_COMMAND_MEMORY);
+
+	OpenPIC = (volatile struct OpenPIC *) GEMINI_MPIC_ADDR;
+	OpenPIC_InitSenses = gemini_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
+
+	ioremap( GEMINI_MPIC_ADDR, sizeof( struct OpenPIC ));
+}
+
+
+extern unsigned long loops_per_sec;
+extern int root_mountflags;
+extern char cmd_line[];
+
+
+void __init
+gemini_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p)
+{
+	unsigned int cpu;
+	extern char cmd_line[];
+
+
+	loops_per_sec = 50000000;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* bootable off CDROM */
+	if (initrd_start)
+		ROOT_DEV = MKDEV(SCSI_CDROM_MAJOR, 0);
+	else
+#endif
+		ROOT_DEV = to_kdev_t(0x0801);
+
+	/* nothing but serial consoles... */  
+	sprintf(cmd_line, "%s console=ttyS0", cmd_line);
+
+
+	/* The user switches on the front panel can be used as follows:
+
+	   Switch 0 - adds "debug" to the command line for verbose boot info,
+	   Switch 7 - boots in single-user mode 
+
+	*/
+
+	gemini_switch_map = readb( GEMINI_USWITCH );
+  
+	if ( gemini_switch_map & (1<<GEMINI_SWITCH_VERBOSE))
+		sprintf(cmd_line, "%s debug", cmd_line);
+
+	if ( gemini_switch_map & (1<<GEMINI_SWITCH_SINGLE_USER))
+		sprintf(cmd_line, "%s single", cmd_line);
+
+	printk("Boot arguments: %s\n", cmd_line);
+
+	/* mutter some kind words about who made the CPU */
+	cpu = _get_PVR();
+	printk("CPU manufacturer: %s [rev=%04x]\n", (cpu & (1<<15)) ? "IBM" :
+	       "Motorola", (cpu & 0xffff));
+
+	/* take special pains to map the MPIC, since it isn't mapped yet */
+	gemini_openpic_init();
+
+	/* start the L2 */
+	gemini_init_l2();
+
+}
+
+
+int
+gemini_get_clock_speed(void)
+{
+	unsigned long hid1;
+	int clock;
+	unsigned char reg;
+  
+	hid1 = _get_HID1();
+	if ((_get_PVR()>>16) == 8)
+		hid1 = cpu_7xx[hid1];
+	else
+		hid1 = cpu_6xx[hid1];
+
+	reg = readb(GEMINI_BSTAT) & 0xc0;
+
+	switch( reg >> 2 ) {
+
+	case 0:
+	default:
+		clock = (hid1*100)/3;
+		break;
+  
+	case 1:
+		clock = (hid1*125)/3;
+		break;
+  
+	case 2:
+		clock = (hid1*50)/3;
+		break;
+	}
+
+	return clock;
+}
+
+
+#define L2CR_PIPE_LATEWR   (0x01800000)   /* late-write SRAM */
+#define L2CR_L2CTL         (0x00100000)   /* RAM control */
+#define L2CR_INST_DISABLE  (0x00400000)   /* disable for insn's */
+#define L2CR_L2I           (0x00200000)   /* global invalidate */
+#define L2CR_L2E           (0x80000000)   /* enable */
+#define L2CR_L2WT          (0x00080000)   /* write-through */
+
+void __init gemini_init_l2(void)
+{
+	unsigned char reg;
+	unsigned long cache;
+	int speed;
+
+	reg = readb(GEMINI_L2CFG);
+
+	/* 750's L2 initializes differently from a 604's.  Also note that a Grackle
+	   bug will hang a dual-604 board, so make sure that doesn't happen by not
+	   turning on the L2 */
+	if ( _get_PVR() >> 16 != 8 ) {
+     
+		/* check for dual cpus and cry sadly about the loss of an L2... */
+		if ((( readb(GEMINI_CPUSTAT) & 0x0c ) >> 2) != 1) 
+			printk("Sorry. Your dual-604 does not allow the L2 to be enabled due "
+			       "to a Grackle bug.\n");
+		else if ( reg & GEMINI_L2_SIZE_MASK ) {
+			printk("Enabling 604 L2 cache: %dKb\n", 
+			       (128<<((reg & GEMINI_L2_SIZE_MASK)>>6)));
+			writeb( 1, GEMINI_L2CFG );
+		}
+	}
+
+	/* do a 750 */
+	else {
+		/* Synergy's first round of 750 boards had the L2 size stuff into the
+		   board register above.  If it's there, it's used; if not, the
+		   standard default is 1Mb.  The L2 type, I'm told, is "most likely
+		   probably always going to be late-write".  --Dan */
+
+		if (reg & 0xc0) {
+			if (!l2_printed) {
+				printk("Enabling 750 L2 cache: %dKb\n", 
+				       (128 << ((reg & 0xc0)>>6)));
+				l2_printed=1;
+			}
+    
+			/* take the size given */
+			cache = (((reg>>6) & 0x3)<<28);
+		}
+		else
+			/* default of 1Mb */
+			cache = 0x3<<28;
+ 
+		reg &= 0x3;
+
+		/* a cache ratio of 1:1 and CPU clock speeds in excess of 300Mhz are bad
+		   things.  If found, tune it down to 1:1.5.  -- Dan */
+		if (!reg) {
+
+			speed = gemini_get_clock_speed();
+   
+			if (speed >= 300) {
+				printk("Warning:  L2 ratio is 1:1 on a %dMhz processor.  Dropping to 1:1.5.\n",
+				       speed );
+				printk("Contact Synergy Microsystems for an ECO to fix this problem\n");
+				reg = 0x1;
+			}
+		}
+
+		/* standard stuff */
+		cache |= ((1<<reg)<<25);
+#ifdef __SMP__
+		/* A couple errata for the 750's (both IBM and Motorola silicon)
+		   note that you can get missed cache lines on MP implementations.
+		   The workaround - if you call it that - is to make the L2
+		   write-through.  This is fixed in IBM's 3.1 rev (I'm told), but
+		   for now, always make 2.x versions use L2 write-through. --Dan */
+		if (((_get_PVR()>>8) & 0xf) <= 2)
+			cache |= L2CR_L2WT;
+#endif
+		cache |= L2CR_PIPE_LATEWR|L2CR_L2CTL|L2CR_INST_DISABLE;
+		_set_L2CR(0);
+		_set_L2CR(cache|L2CR_L2I|L2CR_L2E);
+	}
+}
+
+void
+gemini_restart(char *cmd)
+{
+	__cli();
+	/* make a clean restart, not via the MPIC */
+	_gemini_reboot();
+	for(;;);
+}
+
+void
+gemini_power_off(void)
+{
+	for(;;);
+}
+
+void
+gemini_halt(void)
+{
+	gemini_restart(NULL);
+}
+
+void __init gemini_init_IRQ(void)
+{
+	int i;
+
+	/* gemini has no 8259 */
+	open_pic.irq_offset = 0;
+	for( i=0; i < OPENPIC_VEC_SPURIOUS; i++ ) 
+		irq_desc[i].ctl = &open_pic;
+	openpic_init(1);
+#ifdef __SMP__
+	request_irq(OPENPIC_VEC_IPI, openpic_ipi_action, 0, "IPI0", 0);
+#endif	/* __SMP__ */
+}
+
+#define gemini_rtc_read(x)       (readb(GEMINI_RTC+(x)))
+#define gemini_rtc_write(val,x)  (writeb((val),(GEMINI_RTC+(x))))
+
+/* ensure that the RTC is up and running */
+void __init gemini_time_init(void)
+{
+	unsigned char reg;
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+
+	if ( reg & M48T35_RTC_STOPPED ) {
+		printk(KERN_INFO "M48T35 real-time-clock was stopped. Now starting...\n");
+		gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL);
+		gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL);
+	}
+}
+
+#undef DEBUG_RTC
+
+unsigned long
+gemini_get_rtc_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	unsigned char reg;
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+	gemini_rtc_write((reg|M48T35_RTC_READ), M48T35_RTC_CONTROL);
+#ifdef DEBUG_RTC
+	printk("get rtc: reg = %x\n", reg);
+#endif
+  
+	do {
+		sec = gemini_rtc_read(M48T35_RTC_SECONDS);
+		min = gemini_rtc_read(M48T35_RTC_MINUTES);
+		hour = gemini_rtc_read(M48T35_RTC_HOURS);
+		day = gemini_rtc_read(M48T35_RTC_DOM);
+		mon = gemini_rtc_read(M48T35_RTC_MONTH);
+		year = gemini_rtc_read(M48T35_RTC_YEAR);
+	} while( sec != gemini_rtc_read(M48T35_RTC_SECONDS));
+#ifdef DEBUG_RTC
+	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
+	       sec, min, hour, day, mon, year);
+#endif
+
+	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+	BCD_TO_BIN(sec);
+	BCD_TO_BIN(min);
+	BCD_TO_BIN(hour);
+	BCD_TO_BIN(day);
+	BCD_TO_BIN(mon);
+	BCD_TO_BIN(year);
+
+	if ((year += 1900) < 1970)
+		year += 100;
+#ifdef DEBUG_RTC
+	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
+	       sec, min, hour, day, mon, year);
+#endif
+
+	return mktime( year, mon, day, hour, min, sec );
+}
+
+
+int
+gemini_set_rtc_time( unsigned long now )
+{
+	unsigned char reg;
+	struct rtc_time tm;
+
+	to_tm( now, &tm );
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+#if DEBUG_RTC
+	printk("set rtc: reg = %x\n", reg);
+#endif
+  
+	gemini_rtc_write((reg|M48T35_RTC_SET), M48T35_RTC_CONTROL);
+#if DEBUG_RTC
+	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+  
+	tm.tm_year -= 1900;
+	BIN_TO_BCD(tm.tm_sec);
+	BIN_TO_BCD(tm.tm_min);
+	BIN_TO_BCD(tm.tm_hour);
+	BIN_TO_BCD(tm.tm_mon);
+	BIN_TO_BCD(tm.tm_mday);
+	BIN_TO_BCD(tm.tm_year);
+#ifdef DEBUG_RTC
+	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+
+	gemini_rtc_write(tm.tm_sec, M48T35_RTC_SECONDS);
+	gemini_rtc_write(tm.tm_min, M48T35_RTC_MINUTES);
+	gemini_rtc_write(tm.tm_hour, M48T35_RTC_HOURS);
+	gemini_rtc_write(tm.tm_mday, M48T35_RTC_DOM);
+	gemini_rtc_write(tm.tm_mon, M48T35_RTC_MONTH);
+	gemini_rtc_write(tm.tm_year, M48T35_RTC_YEAR);
+
+	/* done writing */
+	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+	if ((time_state == TIME_ERROR) || (time_state == TIME_BAD))
+		time_state = TIME_OK;
+  
+	return 0;
+}
+
+/*  use the RTC to determine the decrementer count */
+void __init gemini_calibrate_decr(void)
+{
+	int freq, divisor;
+	unsigned char reg;
+
+	/* determine processor bus speed */
+	reg = readb(GEMINI_BSTAT);
+
+	switch(((reg & 0x0c)>>2)&0x3) {
+	case 0:
+	default:
+		freq = 66;
+		break;
+	case 1:
+		freq = 83;
+		break;
+	case 2:
+		freq = 100;
+		break;
+	}
+
+	freq *= 1000000;
+	divisor = 4;
+	decrementer_count = freq / HZ / divisor;
+	count_period_num = divisor;
+	count_period_den = freq / 1000000;
+}
+
+
+void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5,
+			unsigned long r6, unsigned long r7)
+{
+	void layout_bus( struct pci_bus * );
+
+	gemini_setup_pci_ptrs();
+
+	ISA_DMA_THRESHOLD = 0;
+	DMA_MODE_READ = 0;
+	DMA_MODE_WRITE = 0;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if ( r4 )
+	{
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif
+
+	ppc_md.setup_arch = gemini_setup_arch;
+	ppc_md.setup_residual = NULL;
+	ppc_md.get_cpuinfo = gemini_get_cpuinfo;
+	ppc_md.irq_cannonicalize = NULL;
+	ppc_md.init_IRQ = gemini_init_IRQ;
+	ppc_md.do_IRQ = gemini_do_IRQ;
+	ppc_md.init = NULL;
+
+	ppc_md.restart = gemini_restart;
+	ppc_md.power_off = gemini_power_off;
+	ppc_md.halt = gemini_halt;
+
+	ppc_md.time_init = gemini_time_init;
+	ppc_md.set_rtc_time = gemini_set_rtc_time;
+	ppc_md.get_rtc_time = gemini_get_rtc_time;
+	ppc_md.calibrate_decr = gemini_calibrate_decr;
+
+	/* no keyboard/mouse/video stuff yet.. */
+	ppc_md.kbd_setkeycode = NULL;
+	ppc_md.kbd_getkeycode = NULL;
+	ppc_md.kbd_translate = NULL;
+	ppc_md.kbd_unexpected_up = NULL;
+	ppc_md.kbd_leds = NULL;
+	ppc_md.kbd_init_hw = NULL;
+#ifdef CONFIG_MAGIC_SYSRQ
+	ppc_md.ppc_kbd_sysrq_xlate = NULL;
+#endif
+}
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/head.S linux-2.2.14-pre5/arch/ppc/kernel/head.S
--- linux-2.2.14-pre4/arch/ppc/kernel/head.S	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/kernel/head.S	2003-08-15 15:08:54.000000000 -0700
@@ -97,19 +97,6 @@
 	bdnz	0b
 #endif
 
-#ifdef CONFIG_PPC64
-#define LOAD_BAT(n, offset, reg, RA, RB) \
-	ld	RA,offset+0(reg);	\
-	ld	RB,offset+8(reg);	\
-	mtspr	IBAT##n##U,RA;		\
-	mtspr	IBAT##n##L,RB;		\
-	ld	RA,offset+16(reg);	\
-	ld	RB,offset+24(reg);	\
-	mtspr	DBAT##n##U,RA;		\
-	mtspr	DBAT##n##L,RB;		\
-	
-#else /* CONFIG_PPC64 */
-	
 /* 601 only have IBAT cr0.eq is set on 601 when using this macro */ 
 #define LOAD_BAT(n, offset, reg, RA, RB) \
 	/* see the comment for clear_bats() -- Cort */ \
@@ -126,7 +113,6 @@
 	mtspr	DBAT##n##U,RA;		\
 	mtspr	DBAT##n##L,RB;		\
 1:	
-#endif /* CONFIG_PPC64 */	 
 
 #ifndef CONFIG_APUS
 #define tophys(rd,rs,rt)	addis	rd,rs,-KERNELBASE@h
@@ -153,7 +139,15 @@
 	.text
 	.globl	_start
 _start:
-	.long	TOPHYS(__start),0,0
+	/* 
+	 * These are here for legacy reasons, the kernel used to
+	 * need to look like a coff function entry for the pmac
+	 * but we're always started by some kind of bootloader now.
+	 *  -- Cort
+	 */
+	nop
+	nop
+	nop
 
 /* PMAC
  * Enter here with the kernel text, data and bss loaded starting at
@@ -224,16 +218,6 @@
 	
 	.globl	__start
 __start:
-#ifdef CONFIG_PPC64
-/* 
- * Go into 32-bit mode to boot.  OF should do this for
- * us already but just in case...
- * -- Cort 
- */
-	mfmsr	r10
-	clrldi	r10,r10,3
-	mtmsr	r10
-#endif	
 /*
  * We have to do any OF calls before we map ourselves to KERNELBASE,
  * because OF may have I/O devices mapped in in that area
@@ -255,7 +239,6 @@
  * call OF any more.
  */
 	lis	r11,KERNELBASE@h
-#ifndef CONFIG_PPC64
 	mfspr	r9,PVR
 	rlwinm	r9,r9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
 	cmpi	0,r9,1
@@ -269,7 +252,6 @@
 	mtspr	IBAT1U,r9
 	mtspr	IBAT1L,r10
 	b	5f
-#endif /* CONFIG_PPC64 */
 4:
 #ifdef CONFIG_APUS
 	ori	r11,r11,BL_8M<<2|0x2	/* set up an 8MB mapping */
@@ -281,17 +263,10 @@
 #else	
 	ori	r11,r11,BL_256M<<2|0x2	/* set up BAT registers for 604 */
 	li	r8,2			/* R/W access */
-#ifdef CONFIG_PPC64
-	/* clear out the high 32 bits in the BAT */
-	clrldi	r11,r11,32
-	clrldi	r8,r8,32
-	/* turn off the pagetable mappings just in case */
-	clrldi	r16,r16,63
-	mtsdr1	r16
-#else /* CONFIG_PPC64 */
 	/*
 	 * If the MMU is off clear the bats.  See clear_bat() -- Cort
 	 */
+#ifndef CONFIG_GEMINI	
 	mfmsr	r20
 	andi.	r20,r20,MSR_DR
 	bne	100f
@@ -314,14 +289,13 @@
 	mtspr	DBAT2U,r21		/* bit in upper BAT register */
 	mtspr	IBAT2L,r18
 	mtspr	IBAT2U,r21
-#endif /* CONFIG_PPC64 */
+#endif /* ndef CONFIG_GEMINI */	
 #endif
 	mtspr	DBAT0L,r8		/* N.B. 6xx (not 601) have valid */
 	mtspr	DBAT0U,r11		/* bit in upper BAT register */
 	mtspr	IBAT0L,r8
 	mtspr	IBAT0U,r11
 5:	isync
-
 #ifdef CONFIG_APUS
 	/* Unfortunately the APUS specific instructions bloat the
 	 * code so it cannot fit in the 0x100 bytes available. We have
@@ -511,7 +485,12 @@
 
 /* System reset */
 #ifdef CONFIG_SMP /* MVME/MTX start the secondary here */
+#ifdef CONFIG_GEMINI
+	. = 0x100
+	b	__secondary_start_gemini
+#else /* CONFIG_GEMINI */
 	STD_EXCEPTION(0x100, Reset, __secondary_start_psurge)
+#endif /* CONFIG_GEMINI */
 #else
 	STD_EXCEPTION(0x100, Reset, UnknownException)
 #endif	
@@ -1281,6 +1260,7 @@
 	.globl	hash_page
 hash_page:
 #ifdef __SMP__
+	SAVE_2GPRS(7,r21)
 	eieio
 	lis	r2,hash_table_lock@h
 	ori	r2,r2,hash_table_lock@l
@@ -1294,10 +1274,18 @@
 	bne-	12f
 	stwcx.	r0,0,r2
 	beq+	11f
-12:	cmpw	r6,r0
+	/* spin here a bit */
+12:	mfctr	r7
+	li	r8,1000
+	mtctr	r8
+13:
+	bdnz	13b
+	mtctr	r7
+	cmpw	r6,r0
 	bdnzf	2,10b
 	tw	31,31,31
 11:	eieio
+	REST_2GPRS(7, r21)
 #endif
 	/* Get PTE (linux-style) and check access */
 	lwz	r5,PG_TABLES(r5)		
@@ -1331,11 +1319,6 @@
 	stw	r6,0(r2)		/* update PTE (accessed/dirty bits) */
 
 	/* Convert linux-style PTE to low word of PPC-style PTE */
-#ifdef CONFIG_PPC64
-	/* clear the high 32 bits just in case */
-	clrldi	r6,r6,32
-	clrldi	r4,r4,32
-#endif /* CONFIG_PPC64 */
 	rlwinm	r4,r6,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
 	rlwimi	r6,r6,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
 	ori	r4,r4,0xe04		/* clear out reserved bits */
@@ -1343,34 +1326,17 @@
 
 	/* Construct the high word of the PPC-style PTE */
 	mfsrin	r5,r3			/* get segment reg for segment */
-#ifdef CONFIG_PPC64
-	sldi	r5,r5,12
-#else /* CONFIG_PPC64 */
 	rlwinm	r5,r5,7,1,24		/* put VSID in 0x7fffff80 bits */
-#endif /* CONFIG_PPC64 */
 	
 #ifndef __SMP__				/* do this later for SMP */
-#ifdef CONFIG_PPC64
-	ori	r5,r5,1			/* set V (valid) bit */
-#else /* CONFIG_PPC64 */
 	oris	r5,r5,0x8000		/* set V (valid) bit */
-#endif /* CONFIG_PPC64 */
 #endif
 	
-#ifdef CONFIG_PPC64
-/* XXX:	 does this insert the api correctly? -- Cort */
-	rlwimi	r5,r3,17,21,25		/* put in API (abbrev page index) */
-#else /* CONFIG_PPC64 */
 	rlwimi	r5,r3,10,26,31		/* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64 */
 	/* Get the address of the primary PTE group in the hash table */
 	.globl	hash_page_patch_A
 hash_page_patch_A:
 	lis	r4,Hash_base@h		/* base address of hash table */
-#ifdef CONFIG_PPC64
-	/* just in case */
-	clrldi	r4,r4,32
-#endif	
 	rlwimi	r4,r5,32-1,26-Hash_bits,25	/* (VSID & hash_mask) << 6 */
 	rlwinm	r0,r3,32-6,26-Hash_bits,25	/* (PI & hash_mask) << 6 */
 	xor	r4,r4,r0		/* make primary hash */
@@ -1735,33 +1701,26 @@
 	mfmsr	r0
 	ori	r1,r0,MSR_DR|MSR_IR
 	mtspr	SRR1,r1
-#ifdef CONFIG_SMP
-	/* see the function start_here_ibm_hack for explanation -- Cort */
-	andi.	0,r1,MSR_DR	/* check if the MMU is already on */
-	bne	10f
-	lis	r5,smp_ibm_chrp_hack@h
-	ori	r5,r5,smp_ibm_chrp_hack@l
-	tophys(r5,r5,r6)
-	lwz	r5,0(r5)
-	cmpi	0,r5,0
-	beq	10f
-	lis	r5,first_cpu_booted@h
-	ori	r5,r5,first_cpu_booted@l
-	tophys(r5,r5,r6)
-	lwz	r5,0(r5)
-	cmpi	0,r5,0
-	beq	10f
-	lis	r0,start_here_ibm_hack@h
-	ori	r0,r0,start_here_ibm_hack@l
-	b	1010f
-10:	
-#endif /* CONFIG_SMP */
 	lis	r0,start_here@h
 	ori	r0,r0,start_here@l
-1010:	mtspr	SRR0,r0
+	mtspr	SRR0,r0
 	SYNC
 	rfi				/* enables MMU */
 
+#ifdef CONFIG_GEMINI
+	.globl	__secondary_start_gemini
+__secondary_start_gemini:
+        mfspr   r4,HID0
+        ori     r4,r4,HID0_ICFI
+        li      r3,0
+        ori     r3,r3,HID0_ICE
+        andc    r4,r4,r3
+        mtspr   HID0,r4
+        sync
+        bl      prom_init
+        b       __secondary_start
+#endif /* CONFIG_GEMINI */
+
 #ifdef CONFIG_SMP
 	.globl	__secondary_start_psurge
 __secondary_start_psurge:
@@ -1791,25 +1750,6 @@
 	blr
 #endif /* CONFIG_SMP */
 	
-/* 
- * We get _strange_ behavior on the new IBM chrp firmware.
- * We end up here with the MMU disabled, even though we enable
- * it with the rfi that takes us here.  Somehow, a physical address
- * access fixes this by enabling the MMU.
- *
- * The IBM engineers can't explain this behavior and AIX doesn't 
- * seem to find it.  This hack gets around it for now.
- *          -- Cort
- */
-start_here_ibm_hack:
-	mfmsr	r1
-	lis	r5,smp_ibm_chrp_hack@h
-	ori	r5,r5,smp_ibm_chrp_hack@l
-	tophys(r5,r5,r6)
-	mfmsr	r1
-	stw	r1,_MSR-16(r5)
-	addi	r5,r5,_MSR-16
-	dcbf	0,r5
 #ifndef CONFIG_8xx
 start_here:
 	/*
@@ -1896,6 +1836,8 @@
 	mr	r6,r28
 	mr	r7,r27
 	bl	identify_machine
+lis r20,0xc0000000@h
+stw	r20,0(r20)	
 	bl	MMU_init
 /*
  * Go back to running unmapped so we can load up new values
@@ -1906,11 +1848,7 @@
  */
 #ifndef CONFIG_8xx
 	lis	r6,_SDR1@ha
-#ifdef CONFIG_PPC64	
-	ld	r6,_SDR1@l(r6)
-#else
 	lwz	r6,_SDR1@l(r6)
-#endif		
 #else
 	/* The right way to do this would be to track it down through
 	 * init's TSS like the context switch code does, but this is
@@ -1939,14 +1877,6 @@
 #endif
 #ifndef CONFIG_8xx
 	mtspr	SDR1,r6
-#ifdef CONFIG_PPC64
-	/* clear the v bit in the ASR so we can
-	 * behave as if we have segment registers 
-	 * -- Cort
-	 */
-	clrldi	r6,r6,63
-	mtasr	r6
-#endif /* CONFIG_PPC64 */
 	li	r0,16		/* load up segment register values */
 	mtctr	r0		/* for context 0 */
 	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
@@ -1963,17 +1893,10 @@
 	lis	r3,BATS@ha
 	addi	r3,r3,BATS@l
 	tophys(r3,r3,r4)
-#ifdef CONFIG_PPC64
-	LOAD_BAT(0,0,r3,r4,r5)
-	LOAD_BAT(1,32,r3,r4,r5)
-	LOAD_BAT(2,64,r3,r4,r5)
-	LOAD_BAT(3,96,r3,r4,r5)
-#else /* CONFIG_PPC64 */
 	LOAD_BAT(0,0,r3,r4,r5)
 	LOAD_BAT(1,16,r3,r4,r5)
 	LOAD_BAT(2,32,r3,r4,r5)
 	LOAD_BAT(3,48,r3,r4,r5)
-#endif /* CONFIG_PPC64 */
 #endif /* CONFIG_8xx */
 /* Set up for using our exception vectors */
 	/* ptr to phys current tss */
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/Makefile linux-2.2.14-pre5/arch/ppc/kernel/Makefile
--- linux-2.2.14-pre4/arch/ppc/kernel/Makefile	1999-08-25 17:29:46.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/kernel/Makefile	2003-08-15 15:08:54.000000000 -0700
@@ -40,7 +40,8 @@
 	  pmac_setup.o pmac_support.o \
 	  prep_pci.o pmac_pci.o chrp_pci.o \
 	  residual.o prom.o openpic.o feature.o \
-	  prep_nvram.o open_pic.o i8259.o pmac_pic.o indirect_pci.o
+	  prep_nvram.o open_pic.o i8259.o pmac_pic.o indirect_pci.o \
+	  gemini_pci.o gemini_prom.o gemini_setup.o
 OX_OBJS += chrp_setup.o prep_setup.o
 endif
 endif
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/open_pic.c linux-2.2.14-pre5/arch/ppc/kernel/open_pic.c
--- linux-2.2.14-pre4/arch/ppc/kernel/open_pic.c	1999-05-11 08:24:32.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/kernel/open_pic.c	2003-08-15 15:08:54.000000000 -0700
@@ -16,24 +16,24 @@
 
 void chrp_mask_and_ack_irq(unsigned int irq_nr)
 {
-	if (is_8259_irq(irq_nr))
-	    i8259_pic.mask_and_ack(irq_nr);
+	if ((_machine != _MACH_gemini) && is_8259_irq(irq_nr))
+		i8259_pic.mask_and_ack(irq_nr);
 }
 
 static void chrp_mask_irq(unsigned int irq_nr)
 {
-	if (is_8259_irq(irq_nr))
+	if ((_machine != _MACH_gemini) && is_8259_irq(irq_nr))
 		i8259_pic.disable(irq_nr);
 	else
-		openpic_disable_irq(irq_to_openpic(irq_nr));
+		openpic_disable_irq(irq_nr-open_pic.irq_offset);
 }
 
 static void chrp_unmask_irq(unsigned int irq_nr)
 {
-	if (is_8259_irq(irq_nr))
+	if ((_machine != _MACH_gemini) && is_8259_irq(irq_nr))
 		i8259_pic.enable(irq_nr);
 	else
-		openpic_enable_irq(irq_to_openpic(irq_nr));
+		openpic_enable_irq(irq_nr-open_pic.irq_offset);
 }
 
 struct hw_interrupt_type open_pic = {
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/openpic.c linux-2.2.14-pre5/arch/ppc/kernel/openpic.c
--- linux-2.2.14-pre4/arch/ppc/kernel/openpic.c	1999-04-29 12:39:01.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/kernel/openpic.c	2003-08-15 15:08:54.000000000 -0700
@@ -241,10 +241,13 @@
 	    
 	    /* Initialize the spurious interrupt */
 	    openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
-	    
-	    if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
-			    "82c59 cascade", NULL))
-		    printk("Unable to get OpenPIC IRQ 0 for cascade\n");
+
+	    if ( _machine != _MACH_gemini )
+	    {
+		    if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
+				    "82c59 cascade", NULL))
+			    printk("Unable to get OpenPIC IRQ 0 for cascade\n");
+	    }
 	    openpic_set_priority(0, 0);
 	    openpic_disable_8259_pass_through();
     }
@@ -509,3 +512,10 @@
     			    OPENPIC_SENSE_LEVEL,
 			    (sense ? OPENPIC_SENSE_LEVEL : 0));
 }
+
+void openpic_enable_IPI(u_int ipi)
+{
+	check_arg_ipi(ipi);
+	openpic_clearfield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
+			   OPENPIC_MASK);
+}
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/prep_pci.c linux-2.2.14-pre5/arch/ppc/kernel/prep_pci.c
--- linux-2.2.14-pre4/arch/ppc/kernel/prep_pci.c	1999-08-25 17:29:46.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/kernel/prep_pci.c	2003-08-15 15:08:54.000000000 -0700
@@ -170,7 +170,7 @@
 	0,	/* Slot 8  - unused */
 	0,	/* Slot 9  - unused */
 	0,	/* Slot 10 - unxued */
-	0,	/* Slot 11 - unused */
+	0x1e,	/* Slot 11 - PCI-ISA/IDE/USB */
 	0,	/* Slot 12 - unused */
 	0,	/* Slot 13 - unused */
 	2,	/* Slot 14 - Ethernet */
@@ -198,7 +198,7 @@
 	0,      /* Slot 8  - unused */
 	0,      /* Slot 9  - unused */
 	0,      /* Slot 10 - unxued */
-	0,      /* Slot 11 - unused */
+	0x1e,   /* Slot 11 - PCI-ISA/IDE/USB */
 	0,      /* Slot 12 - unused */
 	0,      /* Slot 13 - unused */
 	2,      /* Slot 14 - Ethernet */
@@ -224,7 +224,7 @@
 	0,	/* Slot 8  - unused */
 	0,	/* Slot 9  - unused */
 	0,	/* Slot 10 - unused */
-	0,	/* Slot 11 - unused */
+	0x1e,	/* Slot 11 - PCI-ISA/IDE/USB */
 	3,	/* Slot 12 - SCSI */
 	0,	/* Slot 13 - unused */
 	2,	/* Slot 14 - Ethernet */
@@ -253,7 +253,7 @@
         0,      /* Slot 8  - unused */
         0,      /* Slot 9  - unused */
         0,      /* Slot 10 - unused */
-        0,      /* Slot 11 - unused */
+        0x1e,   /* Slot 11 - PCI-ISA/IDE/USB */
         3,      /* Slot 12 - SCSI */
         0,      /* Slot 13 - unused */
         2,      /* Slot 14 - Ethernet 1 */
@@ -1076,40 +1076,91 @@
 	return;
 }
 
+int motopenpic_to_irq(int n)
+{
+       if (n & 0xF0) {
+               return (n & 0x0F);
+       } else {
+               return(openpic_to_irq(n));
+       }
+}
+
+void prep_pib_init(void)
+{
+unsigned char   reg;
+unsigned short  short_reg;
+
+struct pci_dev *dev = NULL;
+
+	if (( _prep_type == _PREP_Motorola) && (OpenPIC)) {
+		/*
+		 * Perform specific configuration for the Via Tech or
+		 * or Winbond PCI-ISA-Bridge part.
+		 */
+		if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, 
+					PCI_DEVICE_ID_VIA_82C586_1, dev))) {
+			/*
+			 * PPCBUG does not set the enable bits
+			 * for the IDE device. Force them on here.
+			 */
+			pcibios_read_config_byte(dev->bus->number, 
+					dev->devfn, 0x40, &reg);
+
+			reg |= 0x03; /* IDE: Chip Enable Bits */
+			pcibios_write_config_byte(dev->bus->number, 
+					dev->devfn, 0x40, reg);
+
+		} else if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, 
+					PCI_DEVICE_ID_WINBOND_83C553, dev))) {
+			/*
+			 * Clear the PCI Interrupt Routing Control Register.
+			 */
+			short_reg = 0x0000;
+			pcibios_write_config_word(dev->bus->number, 
+					dev->devfn, 0x44, short_reg);
+		}
+	}
+}
 __initfunc(
 void
 prep_pcibios_fixup(void))
 {
-        struct pci_dev *dev;
-        extern unsigned char *Motherboard_map;
-        extern unsigned char *Motherboard_routes;
-        unsigned char i;
+extern unsigned char *Motherboard_map;
+extern unsigned char *Motherboard_routes;
+unsigned char	i;
+struct pci_dev  *dev;
 
-        if ( _prep_type == _PREP_Radstone )
-        {
-                printk("Radstone boards require no PCI fixups\n");
+	if (_prep_type == _PREP_Radstone) {
+		printk("Radstone boards require no PCI fixups\n");
 		return;
-        }
+	}
 
 	prep_route_pci_interrupts();
 
+	prep_pib_init();
+
 	printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
+
 	if (OpenPIC) {
-		/* PCI interrupts are controlled by the OpenPIC */
-		for(dev=pci_devices; dev; dev=dev->next) {
-			if (dev->bus->number == 0) {
-                       		dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
-				pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_PIN, dev->irq);
-			} else {
-				if (Motherboard_non0 != NULL)
-					Motherboard_non0(dev);
-			}
+
+	    /* PCI interrupts are controlled by the OpenPIC */
+	    for(dev=pci_devices; dev; dev=dev->next) {
+		if (dev->bus->number == 0) {
+		    dev->irq = 
+		       motopenpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
+
+		    pcibios_write_config_byte(dev->bus->number, dev->devfn, 
+					      PCI_INTERRUPT_PIN, dev->irq);
+		} else {
+			if (Motherboard_non0 != NULL)
+				Motherboard_non0(dev);
 		}
-		return;
+
+	    }
+	return;
 	}
 
-	for(dev=pci_devices; dev; dev=dev->next)
-	{
+	for(dev=pci_devices; dev; dev=dev->next) {
 		/*
 		 * Use our old hard-coded kludge to figure out what
 		 * irq this device uses.  This is necessary on things
@@ -1118,29 +1169,26 @@
 		unsigned char d = PCI_SLOT(dev->devfn);
 		dev->irq = Motherboard_routes[Motherboard_map[d]];
 
-		for ( i = 0 ; i <= 5 ; i++ )
-		{
-		        if ( dev->base_address[i] > 0x10000000 )
-		        {
-		                printk("Relocating PCI address %lx -> %lx\n",
-		                       dev->base_address[i],
-		                       (dev->base_address[i] & 0x00FFFFFF)
-		                       | 0x01000000);
-		                dev->base_address[i] =
-		                  (dev->base_address[i] & 0x00FFFFFF) | 0x01000000;
-		                pci_write_config_dword(dev,
-		                        PCI_BASE_ADDRESS_0+(i*0x4),
-		                       dev->base_address[i] );
-		        }
+		for ( i = 0 ; i <= 5 ; i++ ) {
+			if ( dev->base_address[i] > 0x10000000 ) {
+				printk("Relocating PCI address %lx -> %lx\n",
+				dev->base_address[i],
+				(dev->base_address[i] & 0x00FFFFFF)|0x01000000);
+
+				dev->base_address[i] = (dev->base_address[i] & 
+							0x00FFFFFF)|0x01000000;
+				pci_write_config_dword(dev, 
+						PCI_BASE_ADDRESS_0+(i*0x4),
+						dev->base_address[i] );
+			}
 		}
 #if 0
-		/*
-		 * If we have residual data and if it knows about this
-		 * device ask it what the irq is.
-		 *  -- Cort
-		 */
-		ppcd = residual_find_device_id( ~0L, dev->device,
-		                                -1,-1,-1, 0);
+	/*
+	 * If we have residual data and if it knows about this
+	 * device ask it what the irq is.
+	 *  -- Cort
+	 */
+	ppcd = residual_find_device_id( ~0L, dev->device, -1,-1,-1, 0);
 #endif
 	}
 }
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/prep_setup.c linux-2.2.14-pre5/arch/ppc/kernel/prep_setup.c
--- linux-2.2.14-pre4/arch/ppc/kernel/prep_setup.c	1999-08-25 17:29:46.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/kernel/prep_setup.c	2003-08-15 15:08:54.000000000 -0700
@@ -628,25 +628,36 @@
 void
 prep_ide_insw(ide_ioreg_t port, void *buf, int ns)
 {
-	_insw((unsigned short *)((port)+_IO_BASE), buf, ns);
+	ide_insw(((port)+(_IO_BASE)), buf, ns);
 }
 
 void
 prep_ide_outsw(ide_ioreg_t port, void *buf, int ns)
 {
-	_outsw((unsigned short *)((port)+_IO_BASE), buf, ns);
+	ide_outsw(((port)+_IO_BASE), buf, ns);
 }
 
 int
 prep_ide_default_irq(ide_ioreg_t base)
 {
-	switch (base) {
-		case 0x1f0: return 13;
-		case 0x170: return 13;
-		case 0x1e8: return 11;
-		case 0x168: return 10;
-		default:
-                        return 0;
+	if ( _prep_type == _PREP_IBM ) {
+		switch (base) {
+			case 0x1f0: return 13;
+			case 0x170: return 13;
+			case 0x1e8: return 11;
+			case 0x168: return 10;
+			default:
+				return 0;
+		}
+	} else {
+		switch (base) {
+			case 0x1f0: return 14;
+			case 0x170: return 14;
+			case 0x1e8: return 15;
+			case 0x168: return 15;
+			default:
+				return 0;
+		}
 	}
 }
 
@@ -687,6 +698,7 @@
 void
 prep_ide_fix_driveid(struct hd_driveid *id)
 {
+	ppc_generic_ide_fix_driveid(id);
 }
 
 __initfunc(void
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/prom.c linux-2.2.14-pre5/arch/ppc/kernel/prom.c
--- linux-2.2.14-pre4/arch/ppc/kernel/prom.c	1999-10-19 17:14:00.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/kernel/prom.c	2003-08-15 15:08:54.000000000 -0700
@@ -25,6 +25,7 @@
 #include <asm/smp.h>
 #include <asm/bootx.h>
 #include <asm/system.h>
+#include <asm/gemini.h>
 
 /*
  * Properties whose value is longer than this get excluded from our
@@ -277,6 +278,11 @@
 	int l;
 	char *p, *d;
 	
+#ifdef CONFIG_GEMINI
+	gemini_prom_init();
+	return;
+#endif /* CONFIG_GEMINI */
+	
 	/* check if we're apus, return if we are */
 	if ( r3 == 0x61707573 )
 		return;
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/setup.c linux-2.2.14-pre5/arch/ppc/kernel/setup.c
--- linux-2.2.14-pre4/arch/ppc/kernel/setup.c	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/kernel/setup.c	2003-08-15 15:08:54.000000000 -0700
@@ -62,6 +62,12 @@
                       unsigned long r6,
                       unsigned long r7);
 
+extern void gemini_init(unsigned long r3,
+                      unsigned long r4,
+                      unsigned long r5,
+                      unsigned long r6,
+                      unsigned long r7);
+
 extern boot_infos_t *boot_infos;
 extern char cmd_line[512];
 char saved_command_line[256];
@@ -342,7 +348,6 @@
 identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
 		 unsigned long r6, unsigned long r7)
 {
-	
 #ifdef __SMP__
 	if ( first_cpu_booted ) return 0;
 #endif /* __SMP__ */
@@ -403,6 +408,8 @@
 	_machine = _MACH_fads;
 #elif defined(CONFIG_APUS)
 	_machine = _MACH_apus;
+#elif defined(CONFIG_GEMINI)
+	_machine = _MACH_gemini;
 #else
 #error "Machine not defined correctly"
 #endif /* CONFIG_APUS */
@@ -488,6 +495,11 @@
                 mbx_init(r3, r4, r5, r6, r7);
                 break;
 #endif
+#ifdef CONFIG_GEMINI
+	case _MACH_gemini:
+                gemini_init(r3, r4, r5, r6, r7);
+		break;
+#endif
 	default:
 		printk("Unknown machine type in identify_machine!\n");
 	}
diff -urN linux-2.2.14-pre4/arch/ppc/kernel/smp.c linux-2.2.14-pre5/arch/ppc/kernel/smp.c
--- linux-2.2.14-pre4/arch/ppc/kernel/smp.c	1999-08-25 17:29:46.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/kernel/smp.c	2003-08-15 15:08:54.000000000 -0700
@@ -34,6 +34,7 @@
 #include <asm/init.h>
 #include <asm/io.h>
 #include <asm/prom.h>
+#include <asm/gemini.h>
 
 #include "time.h"
 int first_cpu_booted = 0;
@@ -175,7 +176,7 @@
 void smp_message_pass(int target, int msg, unsigned long data, int wait)
 {
 	int i;
-	if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_prep)) )
+	if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_prep|_MACH_gemini)) )
 		return;
 
 	spin_lock(&mesg_pass_lock);
@@ -296,6 +297,12 @@
 			cpu_nr = 2;
 			break;
 		}
+	case _MACH_gemini:
+		for ( i = 0; i < 4 ; i++ )
+			openpic_enable_IPI(i);
+                cpu_nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK)>>2;
+                cpu_nr = (cpu_nr == 0) ? 4 : cpu_nr;
+		break;
 	default:
 		printk("SMP not supported on this machine.\n");
 		return;
@@ -357,6 +364,10 @@
 			*MotSave_CpusState[1] = CPU_GOOD;
 			printk("CPU1 reset, waiting\n");
 			break;
+		case _MACH_gemini:
+			openpic_init_processor( 1<<i );
+			openpic_init_processor( 0 );
+			break;
 		}
 		
 		/*
diff -urN linux-2.2.14-pre4/arch/ppc/Makefile linux-2.2.14-pre5/arch/ppc/Makefile
--- linux-2.2.14-pre4/arch/ppc/Makefile	1999-08-09 12:04:57.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/Makefile	2003-08-15 15:08:54.000000000 -0700
@@ -112,6 +112,10 @@
 	rm -f .config arch/ppc/defconfig
 	ln -s apus_defconfig arch/ppc/defconfig
 
+gemini_config:
+	rm -f .config arch/ppc/defconfig
+	ln -s gemini_defconfig arch/ppc/defconfig
+
 tags:
 	etags */*.c include/{asm,linux}/*.h arch/ppc/kernel/*.{c,h}
 
diff -urN linux-2.2.14-pre4/arch/ppc/mm/init.c linux-2.2.14-pre5/arch/ppc/mm/init.c
--- linux-2.2.14-pre4/arch/ppc/mm/init.c	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/arch/ppc/mm/init.c	2003-08-15 15:08:54.000000000 -0700
@@ -54,6 +54,7 @@
 #include <asm/setup.h>
 #include <asm/amigahw.h>
 /* END APUS includes */
+#include <asm/gemini.h>
 
 int prom_trashed;
 atomic_t next_mmu_context;
@@ -83,6 +84,7 @@
 unsigned long *prep_find_end_of_memory(void);
 unsigned long *pmac_find_end_of_memory(void);
 unsigned long *apus_find_end_of_memory(void);
+unsigned long *gemini_find_end_of_memory(void);
 extern unsigned long *find_end_of_memory(void);
 #ifdef CONFIG_MBX
 unsigned long *mbx_find_end_of_memory(void);
@@ -987,6 +989,10 @@
 		FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
 		FREESEC(__prep_begin,__prep_end,num_prep_pages);
 		break;
+	case _MACH_gemini:
+		FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
+		FREESEC(__prep_begin,__prep_end,num_prep_pages);
+		break;
 	}
 
 	if ( !have_of )
@@ -1024,9 +1030,13 @@
 	else if (_machine == _MACH_apus )
 		end_of_DRAM = apus_find_end_of_memory();
 #endif
+#ifdef CONFIG_GEMINI	
+	else if ( _machine == _MACH_gemini )
+		end_of_DRAM = gemini_find_end_of_memory();
+#endif /* CONFIG_GEMINI	*/
 	else /* prep */
 		end_of_DRAM = prep_find_end_of_memory();
-
+*(unsigned long *)(KERNELBASE) = 0xdeadbeef;	
         hash_init();
         _SDR1 = __pa(Hash) | (Hash_mask >> 10);
 	ioremap_base = 0xf8000000;
@@ -1069,6 +1079,10 @@
 		   (kernel_map) remaps individual IO regions to
 		   0x90000000. */
 		break;
+	case _MACH_gemini:
+		setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE);
+		setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
+		break;
 	}
 	ioremap_bot = ioremap_base;
 #else /* CONFIG_8xx */
@@ -1409,6 +1423,32 @@
 	return (__va(total));
 }
 
+#if defined(CONFIG_GEMINI)
+unsigned long __init *gemini_find_end_of_memory(void)
+{
+	unsigned long total, kstart, ksize, *ret;
+	unsigned char reg;
+*(unsigned long *)(KERNELBASE) = 0x1;
+	reg = readb(GEMINI_MEMCFG);
+*(unsigned long *)(KERNELBASE) = 0x2;
+	total = ((1<<((reg & 0x7) - 1)) *
+		 (8<<((reg >> 3) & 0x7)));
+	total *= (1024*1024);
+	phys_mem.regions[0].address = 0;
+	phys_mem.regions[0].size = total;
+	phys_mem.n_regions = 1;
+	
+	ret = __va(phys_mem.regions[0].size);
+	phys_avail = phys_mem;
+	kstart = __pa(_stext);
+	ksize = PAGE_ALIGN( _end - _stext );
+*(unsigned long *)(KERNELBASE) = 0x3;
+	remove_mem_piece( &phys_avail, kstart, ksize, 0 );
+*(unsigned long *)(KERNELBASE) = 0x4;
+	return ret;
+}
+#endif /* defined(CONFIG_GEMINI) */
+
 #ifdef CONFIG_APUS
 #define HARDWARE_MAPPED_SIZE (512*1024)
 __initfunc(unsigned long *apus_find_end_of_memory(void))
diff -urN linux-2.2.14-pre4/CREDITS linux-2.2.14-pre5/CREDITS
--- linux-2.2.14-pre4/CREDITS	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/CREDITS	2003-08-15 15:08:54.000000000 -0700
@@ -997,6 +997,7 @@
 
 N: Jan Kara
 E: jack@atrey.karlin.mff.cuni.cz
+E: jack@suse.cz
 D: Quota fixes for 2.2 kernel
 D: Few other fixes in filesystem area (isofs, loopback)
 W: http://atrey.karlin.mff.cuni.cz/~jack/
diff -urN linux-2.2.14-pre4/drivers/char/busmouse.c linux-2.2.14-pre5/drivers/char/busmouse.c
--- linux-2.2.14-pre4/drivers/char/busmouse.c	1998-12-16 13:38:18.000000000 -0800
+++ linux-2.2.14-pre5/drivers/char/busmouse.c	2003-08-15 15:08:54.000000000 -0700
@@ -210,7 +210,8 @@
 	buttons = mouse.buttons;
 	mouse.dx -= dx;
 	mouse.dy -= dy;
-	mouse.ready = 0;
+	if(mouse.dx==0 && mouse.dy==0)
+		mouse.ready = 0;
 	enable_irq(mouse_irq);
 	/* restore_flags(flags); */
 
diff -urN linux-2.2.14-pre4/drivers/char/console.c linux-2.2.14-pre5/drivers/char/console.c
--- linux-2.2.14-pre4/drivers/char/console.c	1999-10-19 17:14:00.000000000 -0700
+++ linux-2.2.14-pre5/drivers/char/console.c	2003-08-15 15:08:54.000000000 -0700
@@ -2820,6 +2820,7 @@
 EXPORT_SYMBOL(video_font_height);
 EXPORT_SYMBOL(video_scan_lines);
 EXPORT_SYMBOL(vc_resize);
+EXPORT_SYMBOL(fg_console);
 
 #ifndef VT_SINGLE_DRIVER
 EXPORT_SYMBOL(take_over_console);
diff -urN linux-2.2.14-pre4/drivers/char/msbusmouse.c linux-2.2.14-pre5/drivers/char/msbusmouse.c
--- linux-2.2.14-pre4/drivers/char/msbusmouse.c	1998-12-16 13:39:11.000000000 -0800
+++ linux-2.2.14-pre5/drivers/char/msbusmouse.c	2003-08-15 15:08:54.000000000 -0700
@@ -157,7 +157,8 @@
 		put_user(0x00, buffer + i);
 	mouse.dx -= dx;
 	mouse.dy += dy;
-	mouse.ready = 0;
+	if(mouse.dx == 0 && mouse.dy == 0)
+		mouse.ready = 0;
 	return i;	
 }
 
diff -urN linux-2.2.14-pre4/drivers/net/Config.in linux-2.2.14-pre5/drivers/net/Config.in
--- linux-2.2.14-pre4/drivers/net/Config.in	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/drivers/net/Config.in	2003-08-15 15:08:54.000000000 -0700
@@ -46,6 +46,7 @@
   if [ "$CONFIG_PPC" = "y" ]; then
     tristate 'MACE (Power Mac ethernet) support' CONFIG_MACE
     tristate 'BMAC (G3 ethernet) support' CONFIG_BMAC
+    tristate 'Symbios 53c885 (Synergy ethernet) support' CONFIG_NCR885E
   fi
   if [ "$CONFIG_ZORRO" = "y" ]; then
     tristate 'Ariadne support' CONFIG_ARIADNE
diff -urN linux-2.2.14-pre4/drivers/net/lance.c linux-2.2.14-pre5/drivers/net/lance.c
--- linux-2.2.14-pre4/drivers/net/lance.c	1999-08-09 12:04:39.000000000 -0700
+++ linux-2.2.14-pre5/drivers/net/lance.c	2003-08-15 15:08:54.000000000 -0700
@@ -40,12 +40,16 @@
     8/20/96 Fixed 7990 autoIRQ failure and reversed unneeded alignment -djb
     v1.12 10/27/97 Module support -djb
     v1.14  2/3/98 Module support modified, made PCI support optional -djb
+    v1.15 5/27/99 Fixed bug in the cleanup_module(). dev->priv was freed
+                  before unregister_netdev() which caused NULL pointer
+                  reference later in the chain (in rtnetlink_fill_ifinfo())
+                  -- Mika Kuoppala <miku@iki.fi>
     
     Forward ported v1.14 to 2.1.129, merged the PCI and misc changes from
     the 2.1 version of the old driver - Alan Cox
 */
 
-static const char *version = "lance.c:v1.14ac 1998/11/20 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n";
+static const char *version = "lance.c:v1.15ac 1999/11/13 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n";
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -349,11 +353,11 @@
 	for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) {
 		struct device *dev = &dev_lance[this_dev];
 		if (dev->priv != NULL) {
-			kfree(dev->priv);
-			dev->priv = NULL;
+			unregister_netdev(dev);	
 			free_dma(dev->dma);
 			release_region(dev->base_addr, LANCE_TOTAL_SIZE);
-			unregister_netdev(dev);
+			kfree(dev->priv);
+			dev->priv = NULL;
 		}
 	}
 }
diff -urN linux-2.2.14-pre4/drivers/net/Makefile linux-2.2.14-pre5/drivers/net/Makefile
--- linux-2.2.14-pre4/drivers/net/Makefile	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/drivers/net/Makefile	2003-08-15 15:08:54.000000000 -0700
@@ -1154,6 +1154,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_NCR885E),y)
+L_OBJS += ncr885e.o
+else
+  ifeq ($(CONFIG_NCR885E),m)
+  M_OBJS += ncr885e.o
+  endif
+endif
+
 ifeq ($(CONFIG_VENDOR_SANGOMA),y)
   LX_OBJS += sdladrv.o
   L_OBJS += sdlamain.o
diff -urN linux-2.2.14-pre4/drivers/net/ncr885_debug.h linux-2.2.14-pre5/drivers/net/ncr885_debug.h
--- linux-2.2.14-pre4/drivers/net/ncr885_debug.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.14-pre5/drivers/net/ncr885_debug.h	2003-08-15 15:08:54.000000000 -0700
@@ -0,0 +1,54 @@
+#ifndef _H_NCR885_DEBUG
+#define _H_NCR885_DEBUG
+
+struct ncr885e_regs {
+  unsigned long tx_status;
+  unsigned long rx_status;
+  unsigned long mac_config;
+  unsigned long tx_control;
+  unsigned long rx_control;
+  unsigned long tx_cmd_ptr;
+  unsigned long rx_cmd_ptr;
+  unsigned long int_status;
+};
+
+#ifndef __KERNEL__
+
+struct ncr885e_private {
+
+  struct dbdma_cmd *head;
+  struct dbdma_cmd *tx_cmds;
+  struct dbdma_cmd *rx_cmds;
+  struct dbdma_cmd *stop_cmd;
+
+  struct sk_buff *tx_skbufs[NR_TX_RING];
+  struct sk_buff *rx_skbufs[NR_RX_RING];
+
+  int rx_current;
+  int rx_dirty;
+
+  int tx_dirty;
+  int tx_current;
+
+  unsigned short tx_status[NR_TX_RING];
+
+  unsigned char tx_fullup;
+  unsigned char tx_active;
+  
+  struct net_device_stats  stats;
+
+  struct device *dev;
+
+  struct timer_list tx_timeout;
+  int timeout_active;
+
+  spinlock_t lock;
+};
+
+#endif /* __KERNEL__ */
+
+
+#define NCR885E_GET_PRIV   _IOR('N',1,sizeof( struct ncr885e_private ))
+#define NCR885E_GET_REGS   _IOR('N',2,sizeof( struct ncr885e_regs ))
+
+#endif
diff -urN linux-2.2.14-pre4/drivers/net/ncr885e.c linux-2.2.14-pre5/drivers/net/ncr885e.c
--- linux-2.2.14-pre4/drivers/net/ncr885e.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.14-pre5/drivers/net/ncr885e.c	2003-08-15 15:08:54.000000000 -0700
@@ -0,0 +1,1458 @@
+/*
+ *  An Ethernet driver for the dual-function NCR 53C885 SCSI/Ethernet
+ *  controller.
+ *
+ *
+ *  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.
+ *
+ */
+
+static const char *version =
+"ncr885e.c:v0.8 11/30/98 dan@synergymicro.com\n";
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT 
+#define MOD_DEC_USE_COUNT
+#endif
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include <asm/dbdma.h>
+#include <asm/uaccess.h>
+
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include "ncr885e.h"
+#include "ncr885_debug.h"
+
+static const char *chipname = "ncr885e";
+
+/* debugging flags */
+#if 0
+#define DEBUG_FUNC    0x0001
+#define DEBUG_PACKET  0x0002
+#define DEBUG_CMD     0x0004
+#define DEBUG_CHANNEL 0x0008
+#define DEBUG_INT     0x0010
+#define DEBUG_RX      0x0020
+#define DEBUG_TX      0x0040
+#define DEBUG_DMA     0x0080
+#define DEBUG_MAC     0x0100
+#define DEBUG_DRIVER  0x0200
+#define DEBUG_ALL     0x1fff
+#endif
+
+#ifdef DEBUG_NCR885E
+#define NCR885E_DEBUG   0
+#else
+#define NCR885E_DEBUG   0
+#endif
+
+/* The 885's Ethernet PCI device id. */
+#ifndef PCI_DEVICE_ID_NCR_53C885_ETHERNET
+#define PCI_DEVICE_ID_NCR_53C885_ETHERNET  0x0701
+#endif
+
+#define NR_RX_RING    8
+#define NR_TX_RING    8
+#define MAX_TX_ACTIVE (NR_TX_RING-1)
+#define NCMDS_TX      NR_TX_RING
+
+#define RX_BUFLEN     (ETH_FRAME_LEN + 8)
+#define TX_TIMEOUT    5*HZ
+
+#define NCR885E_TOTAL_SIZE 0xe0
+
+#define TXSR          (1<<6)   /* tx: xfer status written */
+#define TXABORT       (1<<7)   /* tx: abort */
+#define EOP           (1<<7)   /* rx: end of packet written to buffer */
+
+int ncr885e_debug = NCR885E_DEBUG;
+static int print_version = 0;
+
+struct ncr885e_private {
+
+	/* preserve a 1-1 marking with buffs */
+	struct dbdma_cmd *head;
+	struct dbdma_cmd *tx_cmds;
+	struct dbdma_cmd *rx_cmds;
+	struct dbdma_cmd *stop_cmd;
+
+	struct sk_buff *tx_skbufs[NR_TX_RING];
+	struct sk_buff *rx_skbufs[NR_RX_RING];
+
+	int rx_current;
+	int rx_dirty;
+
+	int tx_dirty;
+	int tx_current;
+
+	unsigned short tx_status[NR_TX_RING];
+
+	unsigned char tx_fullup;
+	unsigned char tx_active;
+  
+	struct net_device_stats  stats;
+
+	struct device *dev;
+
+	struct timer_list tx_timeout;
+	int timeout_active;
+
+	spinlock_t lock;
+};
+
+#ifdef MODULE
+static struct device *root_dev = NULL;
+#endif
+
+
+static int ncr885e_open( struct device *dev );
+static int ncr885e_close( struct device *dev );
+static void ncr885e_rx( struct device *dev );
+static void ncr885e_tx( struct device *dev );
+static int ncr885e_probe1( struct device *dev, unsigned long ioaddr,
+			   unsigned char irq );
+static int ncr885e_xmit_start( struct sk_buff *skb, struct device *dev );
+static struct net_device_stats *ncr885e_stats( struct device *dev );
+static void ncr885e_set_multicast( struct device *dev );
+static void ncr885e_config( struct device *dev );
+static int ncr885e_set_address( struct device *dev, void *addr );
+static void ncr885e_interrupt( int irq, void *dev_id, struct pt_regs *regs );
+static void show_dbdma_cmd( volatile struct dbdma_cmd *cmd );
+#if 0
+static int read_eeprom( unsigned int ioadddr, int location );
+#endif
+
+#ifdef NCR885E_DEBUG_MII
+static void show_mii( unsigned long ioaddr );
+static int read_mii( unsigned long ioaddr, int reg );
+static void write_mii( unsigned long ioaddr, int reg, int data );
+#endif /* NCR885E_DEBUG_MII */
+
+#define TX_RESET_FLAGS    (TX_CHANNEL_RUN|TX_CHANNEL_PAUSE|TX_CHANNEL_WAKE)
+#define RX_RESET_FLAGS    (RX_CHANNEL_RUN|RX_CHANNEL_PAUSE|RX_CHANNEL_WAKE)
+
+
+#if 0
+static int
+debug_ioctl( struct device *dev, struct ifreq *req, int cmd )
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct ncr885e_private *sp = (struct ncr885e_private *) dev->priv;
+	struct ncr885e_private *data;
+	struct ncr885e_regs *regs;
+	unsigned long flags;
+
+	union {
+		struct ncr885e_regs dump;
+		struct ncr885e_private priv;    
+	} temp;
+
+	switch( cmd ) {
+
+		/* dump the rx ring status */
+	case NCR885E_GET_PRIV:
+
+		data = (struct ncr885e_private *) &req->ifr_data;    
+
+		if ( verify_area(VERIFY_WRITE, &req->ifr_data,
+				 sizeof( struct ncr885e_private )))
+			return -EFAULT;
+
+		memcpy((char *) &temp.priv, sp, sizeof( struct ncr885e_private ));
+		copy_to_user( data, (char *) &temp.priv, sizeof( struct ncr885e_private));
+		break;
+
+	case NCR885E_GET_REGS:
+
+		regs = (struct ncr885e_regs *) &req->ifr_data;
+  
+		if ( verify_area( VERIFY_WRITE, &req->ifr_data,
+				  sizeof( struct ncr885e_regs )))
+			return -EFAULT;
+
+		spin_lock_irqsave( &sp->lock, flags ); 
+
+		temp.dump.tx_status = inl( ioaddr + TX_CHANNEL_STATUS );
+		temp.dump.rx_status = inl( ioaddr + RX_CHANNEL_STATUS );
+		temp.dump.mac_config = inl( ioaddr + MAC_CONFIG );
+		temp.dump.tx_control = inl( ioaddr + TX_CHANNEL_CONTROL );
+		temp.dump.rx_control = inl( ioaddr + RX_CHANNEL_CONTROL );
+		temp.dump.tx_cmd_ptr = inl( ioaddr + TX_CMD_PTR_LO );
+		temp.dump.rx_cmd_ptr = inl( ioaddr + RX_CMD_PTR_LO );
+		temp.dump.int_status = inl( ioaddr + INTERRUPT_STATUS_REG );
+
+		spin_unlock_irqrestore( &sp->lock, flags );
+		copy_to_user( regs, (char *) &temp.dump, sizeof( struct ncr885e_regs ));
+
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+#endif
+
+/*  Enable interrupts on the 53C885 */
+static inline void
+ncr885e_enable( struct device *dev )
+
+{
+	unsigned long ioaddr = dev->base_addr;
+	unsigned short reg;
+
+	reg = inw(ioaddr + INTERRUPT_ENABLE);
+	outw(reg | INTERRUPT_INTE, ioaddr + INTERRUPT_ENABLE);
+}
+
+/*  Disable interrupts on the 53c885 */
+static inline void
+ncr885e_disable( struct device *dev )
+
+{
+	unsigned long ioaddr = dev->base_addr;
+	unsigned short reg;
+
+	reg = inw( ioaddr + INTERRUPT_ENABLE );
+	outw( reg & ~INTERRUPT_INTE, ioaddr + INTERRUPT_ENABLE );
+}
+
+
+static inline void
+ncr885e_reset( struct device *dev )
+
+{
+	unsigned short reg;  
+	unsigned long cntl;
+	int i;
+	unsigned long ioaddr = dev->base_addr;
+
+	if (ncr885e_debug > 1)
+		printk( KERN_INFO "%s: Resetting 53C885...\n", dev->name );
+
+	/* disable interrupts on the 53C885 */
+	ncr885e_disable( dev );
+  
+	/* disable rx in the MAC */
+	reg = inw( ioaddr + MAC_CONFIG );
+	outw( reg & ~MAC_CONFIG_RXEN, ioaddr + MAC_CONFIG );
+  
+	for( i=0; i < 100; i++ ) {
+
+		if ( !(inw( ioaddr + MAC_CONFIG ) & MAC_CONFIG_RXEN ))
+			break;
+		udelay( 10 );
+	}
+  
+	reg = inw( ioaddr + MAC_CONFIG );
+	outw( reg | MAC_CONFIG_SRST, ioaddr + MAC_CONFIG );
+	outw( reg, ioaddr + MAC_CONFIG );
+
+	/* disable both rx and tx DBDMA channels */
+	outl( TX_DBDMA_ENABLE << 16, ioaddr + TX_CHANNEL_CONTROL );
+	outl( RX_DBDMA_ENABLE << 16, ioaddr + RX_CHANNEL_CONTROL );
+
+	for( i=0; i < 100; i++ ) {
+    
+		if ( !(inw( ioaddr + TX_CHANNEL_STATUS ) & TX_DBDMA_ENABLE ) &&
+		     !(inw( ioaddr + RX_CHANNEL_STATUS ) & RX_DBDMA_ENABLE ))
+			break;
+		udelay( 10 );
+	}
+
+	/* perform a "software reset" */
+	cntl = inl( ioaddr + DBDMA_CONTROL );
+	outl( cntl | DBDMA_SRST, ioaddr + DBDMA_CONTROL );
+
+	for( i=0; i < 100; i++ ) {
+  
+		if ( !(inl( ioaddr + DBDMA_CONTROL ) & DBDMA_SRST ))
+			break;
+		udelay( 10 );
+	}
+
+	/* books says that a software reset should be done to the MAC, as
+	   well.  This true??? */
+
+	if (ncr885e_debug > 3) 
+		printk( KERN_INFO "%s: reset complete\n", dev->name );
+
+}
+
+
+/*  configure the 53C885 chip.
+
+    The DBDMA command descriptors on the 53C885 can be programmed to
+    branch, interrupt or pause conditionally or always by using the
+    interrupt, branch and wait select registers.  */
+
+static void
+ncr885e_config( struct device *dev )
+
+{
+	unsigned long ioaddr = dev->base_addr;
+
+	if (ncr885e_debug > 3)
+		printk( KERN_INFO "%s: Configuring 53C885.\n", dev->name );
+
+	ncr885e_reset( dev );
+ 
+	/* The 53C885 can be programmed to perform conditional DBDMA
+	   branches, interrupts or waits.
+  
+	   Neither channel makes use of "wait", as it requires that the
+	   DBDMA engine to be restarted.  Don't go there.  The rx channel
+	   will branch upon the successful reception of a packet ('EOP' in
+	   the xfer_status field).  The branch address is to the STOP
+	   DBDMA command descriptor, which shuts down the rx channel until
+	   the interrupt is serviced.   */
+     
+	/* cause tx channel to stop after "status received" */
+	outl( 0, ioaddr + TX_INT_SELECT );
+	outl( (TX_WAIT_STAT_RECV << 16) | TX_WAIT_STAT_RECV, 
+	      ioaddr + TX_WAIT_SELECT );
+	outl( 0, ioaddr + TX_BRANCH_SELECT );
+
+	/* cause rx channel to branch to the STOP descriptor on "End-of-Packet" */
+#if 0
+	outl( (RX_INT_SELECT_EOP << 16) | RX_INT_SELECT_EOP,
+	      ioaddr + RX_INT_SELECT );
+#else
+	outl( 0, ioaddr + RX_INT_SELECT );
+#endif
+#if 0
+	outl( 0, ioaddr + RX_WAIT_SELECT );
+#else
+	outl( (RX_WAIT_SELECT_EOP << 16) | RX_WAIT_SELECT_EOP, 
+	      ioaddr + RX_WAIT_SELECT );
+#endif
+#if 1
+	outl( 0, ioaddr + RX_BRANCH_SELECT );
+#else
+	outl( (RX_BRANCH_SELECT_EOP << 16) | RX_BRANCH_SELECT_EOP,
+	      ioaddr + RX_BRANCH_SELECT );
+#endif
+
+	/* configure DBDMA */
+	outl( (DBDMA_BE | DBDMA_DPMRLE | DBDMA_TDPCE |
+	       DBDMA_DDPE | DBDMA_TDPE |
+	       (DBDMA_BURST_4 << DBDMA_TX_BST_SHIFT) |
+	       (DBDMA_BURST_4 << DBDMA_RX_BST_SHIFT) |
+	       (DBDMA_TX_ARBITRATION_DEFAULT) |
+	       (DBDMA_RX_ARBITRATION_DEFAULT)), ioaddr + DBDMA_CONTROL );
+
+	outl( 0, ioaddr + TX_THRESHOLD );
+
+	/* disable MAC loopback */
+	outl( (MAC_CONFIG_ITXA | MAC_CONFIG_RXEN | MAC_CONFIG_RETRYL |
+	       MAC_CONFIG_PADEN | (0x18 << 16)),
+	      ioaddr + MAC_CONFIG );
+
+	/* configure MAC */
+	outl( (MAC_CONFIG_ITXA | MAC_CONFIG_RXEN | MAC_CONFIG_RETRYL |
+	       MAC_CONFIG_PADEN | ( 0x18 << 16)), ioaddr + MAC_CONFIG );
+
+	outw( (0x1018), ioaddr + NBTOB_INTP_GAP );
+
+	/* clear and enable interrupts */
+	inw( ioaddr + INTERRUPT_CLEAR );
+	ncr885e_enable( dev );
+
+	/* and enable them in the chip */
+	outl( (INTERRUPT_INTE|INTERRUPT_TX_MASK|INTERRUPT_RX_MASK)<<16,
+	      ioaddr + INTERRUPT_ENABLE - 2);
+
+	if (ncr885e_debug > 3)
+		printk( KERN_INFO "%s: 53C885 config complete.\n", dev->name );
+
+	return;
+}
+
+
+
+/*
+   transmit interrupt  */
+
+static void
+ncr885e_tx( struct device *dev )
+
+{
+	struct ncr885e_private *sp = (struct ncr885e_private *) dev->priv;
+	volatile struct dbdma_cmd *cp, *dp;
+	unsigned short txbits, xfer;
+	int i;
+
+	del_timer( &sp->tx_timeout );
+
+	if (ncr885e_debug > 3)
+		printk( KERN_INFO "%s: ncr885e_tx: active=%d, dirty=%d, current=%d\n", 
+			dev->name, sp->tx_active, sp->tx_dirty, sp->tx_current );
+
+	sp->timeout_active = 0;
+
+	i = sp->tx_dirty;
+	cp = sp->tx_cmds + (i*3);
+	dp = cp+1;
+	sp->tx_active--;
+
+	xfer = inw( &dp->xfer_status );
+	txbits = inw( &sp->tx_status[i] );
+
+	if (ncr885e_debug > 4) {
+		show_dbdma_cmd( cp );
+		show_dbdma_cmd( dp );
+	}
+
+	/* get xmit result */
+	txbits = inw( &sp->tx_status[i] );
+
+	if (ncr885e_debug > 3)
+		printk( KERN_INFO "%s: tx xfer=%04x, txbits=%04x\n", dev->name,
+			xfer, txbits );
+
+	/* look for any channel status (?) */
+	if ( xfer ) {
+
+		dev_kfree_skb( sp->tx_skbufs[i] );
+		mark_bh( NET_BH );
+
+		if ( txbits & TX_STATUS_TXOK ) {
+			sp->stats.tx_packets++;
+			sp->stats.tx_bytes += inw( &cp->req_count );
+		}
+
+		/* dropped packets */
+		if ( txbits & (TX_STATUS_TDLC|TX_STATUS_TDEC) ) {
+			sp->stats.tx_dropped++;
+		}
+
+		/* add the collisions */
+		sp->stats.collisions += ( txbits & 0x04 );
+
+	}
+
+	dev->tbusy = 0;
+  
+	return;
+}
+
+/*  rx interrupt handling */
+static void
+ncr885e_rx( struct device *dev )
+
+{
+	struct ncr885e_private *sp = (struct ncr885e_private *) dev->priv;
+	volatile struct dbdma_cmd *cp;
+	struct sk_buff *skb;
+	int i, nb;
+	unsigned short status;
+	unsigned char *data, *stats;
+	unsigned long rxbits, ioaddr = dev->base_addr;
+
+	i = sp->rx_current;
+	cp = sp->rx_cmds + (i*2);
+
+	if (ncr885e_debug > 3)
+		printk( KERN_INFO "%s: ncr885e_rx dirty=%d, current=%d (cp@%p)\n",
+			dev->name, sp->rx_dirty, sp->rx_current, cp );
+
+	nb = inw( &cp->req_count ) - inw( &cp->res_count );
+	status = inw( &cp->xfer_status );
+
+	if (ncr885e_debug > 3)
+		printk( KERN_INFO "%s: (rx %d) bytes=%d, xfer_status=%04x\n", 
+			dev->name, i, nb, status );
+
+	if ( status ) {
+
+		skb = sp->rx_skbufs[i];
+		data = skb->data;
+		stats = data + nb - 3;
+		rxbits = (stats[0]|stats[1]<<8|stats[2]<<16);
+  
+		if (ncr885e_debug > 3)
+			printk( KERN_INFO "  rx_bits=%06lx\n", rxbits );
+
+		skb->dev = dev;
+		skb_put( skb, nb-3 );
+		skb->protocol = eth_type_trans( skb, dev );
+		netif_rx( skb );
+		sp->rx_skbufs[i] = 0;
+
+		if ( rxbits & RX_STATUS_RXOK ) {
+			sp->stats.rx_packets++;
+			sp->stats.rx_bytes += nb;
+		}
+
+		if ( rxbits & RX_STATUS_MCAST )
+			sp->stats.multicast++;
+
+	}
+
+	sp->rx_dirty = sp->rx_current;
+
+	if ( ++sp->rx_current >= NR_RX_RING )
+		sp->rx_current = 0;
+
+	/* fix up the one we just trashed */
+	cp = sp->rx_cmds + (sp->rx_dirty * 2);
+
+	skb = dev_alloc_skb( RX_BUFLEN + 2 );
+	if ( skb != 0 ) {
+		skb_reserve( skb, 2 );
+		sp->rx_skbufs[sp->rx_dirty] = skb;
+	}
+
+	if (ncr885e_debug > 2)
+		printk( KERN_INFO "%s: ncr885e_rx: using ring index %d, filling cp @ %p\n", 
+			dev->name, sp->rx_current, cp );
+  
+	outw( RX_BUFLEN, &cp->req_count );
+	outw( 0, &cp->res_count );
+	data = skb->data;
+	outl( virt_to_bus( data ), &cp->phy_addr );
+	outw( 0, &cp->xfer_status );
+
+	cp = sp->rx_cmds + (sp->rx_current * 2);
+
+	/* restart rx DMA */
+	outl( virt_to_bus( cp ), ioaddr + RX_CMD_PTR_LO );
+	outl( (RX_DBDMA_ENABLE << 16)|RX_CHANNEL_RUN,
+	      ioaddr + RX_CHANNEL_CONTROL );
+
+	return;
+}
+
+static void
+ncr885e_misc_ints( struct device *dev, unsigned short status )
+
+{
+	struct ncr885e_private *sp = (struct ncr885e_private *) dev->priv;
+	struct dbdma_cmd *cp;
+	unsigned long ioaddr = dev->base_addr;
+
+	if (ncr885e_debug > 1)
+		printk( KERN_INFO "miscellaneous interrupt handled; status=%02x\n", 
+			status );
+
+	/* various transmit errors */
+	if ( status & 
+	     (INTERRUPT_PPET | INTERRUPT_PBFT | INTERRUPT_IIDT) ) {
+
+		/* illegal instruction in tx dma */
+		if ( status & INTERRUPT_IIDT ) {
+
+			cp = (struct dbdma_cmd *) bus_to_virt( inl( ioaddr + TX_CMD_PTR_LO ));
+			printk( KERN_INFO "%s: tx illegal insn:\n", dev->name );
+			printk( KERN_INFO " tx DBDMA - cmd = %p, status = %04x\n", 
+				cp, inw( ioaddr + TX_CHANNEL_STATUS ));
+			printk( KERN_INFO " command = %04x, phy_addr=%08x, req_count=%04x\n",
+				inw( &cp->command ), inw( &cp->phy_addr ), inw( &cp->req_count ));
+		}
+
+		if ( status & INTERRUPT_PPET )
+			printk( KERN_INFO "%s: tx PCI parity error\n", dev->name );
+ 
+		if ( status & INTERRUPT_PBFT )
+			printk( KERN_INFO "%s: tx PCI bus fault\n", dev->name );
+	}
+
+	/* look for rx errors */
+	if ( status &
+	     (INTERRUPT_PPER | INTERRUPT_PBFR | INTERRUPT_IIDR)) {
+
+		/* illegal instruction in rx dma */
+		if ( status & INTERRUPT_IIDR ) {
+#if 0
+			cmd = inl( ioaddr + RX_CMD_PTR_LO );      
+#endif
+			printk( KERN_ERR "%s: rx illegal DMA instruction:\n", dev->name );
+			printk( KERN_ERR "    channel status=%04x,\n",
+				inl( ioaddr + RX_CHANNEL_STATUS ));
+#if 0
+			show_dbdma_cmd( bus_to_virt( inl( ioaddr + RX_CMD_PTR_LO )));
+			printk( KERN_ERR "    instr (%08x) %08x %08x %08x\n",
+				(int) cmd, cmd[0], cmd[1], cmd[2] );
+#endif
+		}
+
+		/* PCI parity error */
+		if ( status & INTERRUPT_PPER )
+			printk( KERN_INFO "%s: rx PCI parity error\n", dev->name );
+
+		if ( status & INTERRUPT_PBFR )
+			printk( KERN_INFO "%s: rx PCI bus fault\n", dev->name );
+
+		sp->stats.rx_errors++;
+	}
+
+	if ( status & INTERRUPT_WI ) {
+		printk( KERN_INFO "%s: link pulse\n", dev->name );
+	}
+
+	/* bump any counters */
+  
+
+	return;
+}
+
+static void
+ncr885e_interrupt( int irq, void *dev_id, struct pt_regs *regs )
+
+{
+	struct device  *dev = (struct device *) dev_id;
+	struct ncr885e_private *sp;
+	unsigned short status;
+	int ioaddr;
+
+	if ( dev == NULL ) {
+		printk( KERN_ERR "symba: Interrupt IRQ %d for unknown device\n", irq );
+		return;
+	}
+
+	ioaddr = dev->base_addr;
+	sp = (struct ncr885e_private *) dev->priv;
+	spin_lock( &sp->lock );
+  
+	if ( dev->interrupt ) {
+		printk( KERN_ERR "%s: Re-entering interrupt handler...\n", 
+			dev->name );
+	}
+
+	dev->interrupt = 1;
+	status = inw( ioaddr + INTERRUPT_CLEAR );
+
+	if (ncr885e_debug > 2)
+		printk( KERN_INFO "%s: 53C885 interrupt 0x%02x\n", dev->name, status );
+
+	/* handle non-tx and rx interrupts first */
+	if ( status & ~(INTERRUPT_DIT|INTERRUPT_DIR))
+		ncr885e_misc_ints( dev, status );
+
+	/* look for tx interrupt: more to transmit, DBDMA stopped, or tx done */
+	if ( ( status & INTERRUPT_DIT ) ) {
+
+		if (ncr885e_debug > 2)
+			printk( KERN_INFO "%s: tx int; int=%02x, chan stat=%02x\n", 
+				dev->name, status, inw( ioaddr + TX_CHANNEL_STATUS ));
+
+		/* turn off timer */
+		del_timer( &sp->tx_timeout );
+		sp->timeout_active = 0;
+
+		/* stop DMA */
+		outl( TX_DBDMA_ENABLE << 16, ioaddr + TX_CHANNEL_CONTROL );
+
+		ncr885e_tx( dev );
+	}
+
+	if ( status & INTERRUPT_DIR ) {
+
+		if ( ncr885e_debug > 2 )
+			printk( KERN_INFO "%s: rx interrupt; int=%02x, rx channel stat=%02x\n", 
+				dev->name, status, inw( ioaddr + RX_CHANNEL_STATUS ));
+
+		/* stop DMA */
+		outl( RX_DBDMA_ENABLE << 16, ioaddr + RX_CHANNEL_CONTROL );
+    
+		/* and handle the interrupt */
+		ncr885e_rx( dev );
+	}
+  
+	dev->interrupt = 0;
+	spin_unlock( &sp->lock );
+
+	return;
+}
+
+
+/*  doesn't set the address permanently, however... */
+static int 
+ncr885e_set_address( struct device *dev, void *addr )
+
+{
+	struct ncr885e_private *sp = (struct ncr885e_private *) dev->priv;
+	struct sockaddr *saddr = addr;
+	unsigned long  flags;
+	unsigned short reg[3];
+	unsigned char *ioaddr, *p;
+	int i;
+
+	memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len );
+
+	p = (unsigned char *) dev->dev_addr;
+	printk( KERN_INFO "%s: setting new MAC address - ", dev->name );
+#if 0
+	for( p = (unsigned char *) dev->dev_addr, i=0; i < 6; i++, p++ ) 
+		printk("%c%2.2x", i ? ':' : ' ', *p );
+#endif
+
+
+	p = (unsigned char *) &reg;
+	for( i=0; i < 6; i++ )
+		p[i] = dev->dev_addr[i];
+
+#if 0
+	printk("%s: Setting new mac address - ", dev->name );
+	for( i=0; i < 6; i++ ) {
+		printk("%02x", i ? ':' : ' ', p[i] );
+	}
+
+	printk("\n");
+#endif
+
+	/* stop rx for the change */
+	outl( RX_DBDMA_ENABLE << 16, ioaddr + RX_CHANNEL_CONTROL );
+  
+	spin_lock_irqsave( &sp->lock, flags );
+
+	ioaddr = (unsigned char *) dev->base_addr;
+
+	for( i = 0; i < 3; i++ ) {
+		reg[i] = ((reg[i] & 0xff) << 8) | ((reg[i] >> 8) & 0xff);
+		printk("%04x ", reg[i] );
+		outw( reg[i], ioaddr + STATION_ADDRESS_0 + (i*2));
+	}
+	printk("\n");
+
+	spin_unlock_irqrestore( &sp->lock, flags );
+
+	/* restart rx */
+	outl((RX_DBDMA_ENABLE << 16)|RX_CHANNEL_RUN, 
+	     ioaddr + RX_CHANNEL_CONTROL );
+
+	return 0;
+}
+
+static void 
+ncr885e_tx_timeout( unsigned long data )
+
+{
+	struct device *dev = (struct device *) data;
+	struct ncr885e_private *sp = (struct ncr885e_private *) dev->priv;
+	unsigned long flags, ioaddr;
+	int i;
+  
+	save_flags( flags );
+	cli();
+
+	ioaddr = dev->base_addr;
+	sp->timeout_active = 0;
+	i = sp->tx_dirty;
+
+	/* if we weren't active, bail... */
+	if ( sp->tx_active == 0 ) {
+		printk( KERN_INFO "%s: ncr885e_timeout...tx not active!\n", dev->name );
+		goto out;
+	}
+
+	printk( KERN_ERR "%s: 53C885 timed out.  Resetting...\n", dev->name );
+
+	/* disable rx and tx DMA */
+	outl( (TX_DBDMA_ENABLE << 16), ioaddr + TX_CHANNEL_CONTROL );
+	outl( (RX_DBDMA_ENABLE << 16), ioaddr + RX_CHANNEL_CONTROL );
+
+	/* reset the chip */
+	ncr885e_config( dev );
+	ncr885e_enable( dev );
+
+	/* clear the wedged skb in the tx ring */
+	sp->tx_active = 0;
+	++sp->stats.tx_errors;
+  
+	if ( sp->tx_skbufs[i] ) {
+		dev_kfree_skb( sp->tx_skbufs[i] );
+		sp->tx_skbufs[i] = 0;
+	}
+
+	/* start anew from the beginning of the ring buffer (why not?) */
+	sp->tx_current = 0;
+	dev->tbusy = 0;
+	mark_bh( NET_BH );
+
+	/* restart rx dma */
+	outl( (RX_DBDMA_ENABLE << 16) | RX_CHANNEL_RUN,
+	      ioaddr + RX_CHANNEL_CONTROL );  
+ out:
+
+	restore_flags( flags );
+}
+
+static inline void
+ncr885e_set_timeout( struct device *dev )
+
+{
+	struct ncr885e_private *sp = (struct ncr885e_private *) dev->priv;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+
+	if ( sp->timeout_active )
+		del_timer( &sp->tx_timeout );
+
+	sp->tx_timeout.expires = jiffies + TX_TIMEOUT;
+	sp->tx_timeout.function = ncr885e_tx_timeout;
+	sp->tx_timeout.data = (unsigned long) dev;
+	add_timer( &sp->tx_timeout );
+	sp->timeout_active = 1;
+	restore_flags( flags );
+}
+
+
+/*
+ *  The goal is to set up DBDMA such that the rx ring contains only
+ *  one DMA descriptor per ring element and the tx ring has two (using
+ *  the cool features of branch- and wait-select.  However, I'm not sure
+ *  if it's possible.  For now, we plod through it with 3 descriptors
+ *  for tx, and two for rx.
+ */
+
+static int
+ncr885e_open( struct device *dev )
+
+{
+	struct ncr885e_private *sp = (struct ncr885e_private *) dev->priv;
+	unsigned long ioaddr = dev->base_addr;
+	struct sk_buff *skb;
+	int i, size;
+	char *data;
+	struct dbdma_cmd *cp;
+	unsigned long flags;
+
+	/* allocate enough space for the tx and rx rings and a STOP descriptor */  
+	size = (sizeof( struct dbdma_cmd ) *
+		((NR_TX_RING * 3) + (NR_RX_RING * 2) + 1));
+
+	cp = kmalloc( size, GFP_KERNEL );
+
+	if ( cp == 0 ) {
+		printk( KERN_ERR "Insufficient memory (%d bytes) for DBDMA\n", size );
+		return -ENOMEM;
+	}
+
+	spin_lock_init( &sp->lock );
+	spin_lock_irqsave( &sp->lock, flags );
+
+	memset((char *) cp, 0, size );
+	sp->head = cp;
+
+	sp->stop_cmd = cp;
+	outl( DBDMA_STOP, &cp->command );
+  
+	sp->rx_cmds = ++cp;
+
+	for( i = 0; i < NR_RX_RING; i++ ) {
+
+		cp = sp->rx_cmds + (i*2);
+		skb = dev_alloc_skb( RX_BUFLEN + 2 );
+
+		/* if there is insufficient memory, make this last ring use a 
+		   static buffer and leave the loop with that skb as final one */
+		if ( skb == 0 ) {
+			printk( KERN_ERR "%s: insufficient memory for rx ring buffer\n",
+				dev->name );
+			break;
+		}
+
+		skb_reserve( skb, 2 );
+		sp->rx_skbufs[i] = skb;
+		data = skb->data;
+
+		/* The DMA commands here are done such that an EOP is the only
+		   way that we should get an interrupt.  This means that we could
+		   fill more than one skbuff before getting the interrupt at EOP. */
+
+		/* Handle rx DMA such that it always interrupts.... */
+		outw( (INPUT_MORE|INTR_ALWAYS), &cp->command );
+		outw( RX_BUFLEN, &cp->req_count );
+		outw( 0, &cp->res_count );
+		outl( virt_to_bus( data ), &cp->phy_addr );
+		outl( virt_to_bus( sp->stop_cmd ), &cp->cmd_dep );
+		outw( 0, &cp->xfer_status );
+#if 0
+		printk( KERN_INFO "rx at %p\n", cp );
+		show_dbdma_cmd( cp );
+#endif
+		++cp;
+
+		outw( DBDMA_STOP, &cp->command );
+
+	}
+
+	/* initialize to all rx buffers are available, fill limit is the end */
+	sp->rx_dirty = 0;
+	sp->rx_current = 0;
+
+	/* fill the tx ring */
+	sp->tx_cmds = cp+1;
+
+	for( i = 0; i < NR_TX_RING; i++ ) {
+
+		/* minimal setup for tx command */
+		cp = sp->tx_cmds + (i*3);
+		outw( OUTPUT_LAST, &cp->command );
+		if (ncr885e_debug > 3) {
+			printk( KERN_INFO "tx OUTPUT_LAST at %p\n", cp );
+			show_dbdma_cmd( cp );
+		}
+
+		/* full setup for the status cmd */
+		cp++;
+		outw( INPUT_LAST|INTR_ALWAYS|WAIT_IFCLR, &cp->command );
+		outl( virt_to_bus( &sp->tx_status[i] ), &cp->phy_addr );
+		outw( 2, &cp->req_count );
+		if ( ncr885e_debug > 3) {
+			printk( KERN_INFO "tx INPUT_LAST cmd at %p\n", cp );
+			show_dbdma_cmd( cp );
+		}
+
+		++cp;
+		outw( DBDMA_STOP, &cp->command );
+ 
+	}
+#if 0
+	/* chain the last tx DMA command to the STOP cmd */
+	outw((INPUT_LAST|INTR_ALWAYS|BR_ALWAYS), &cp->command );
+	outl( virt_to_bus( sp->stop_cmd ), &cp->cmd_dep );
+#endif
+	sp->tx_active = 0;
+	sp->tx_current = 0;
+	sp->tx_dirty = 0;
+
+	spin_unlock_irqrestore( &sp->lock, flags );
+
+	/* the order seems important here for some reason.  If the MPIC isn't
+	   enabled before the ethernet chip is enabled, shrapnel from the
+	   bootloader causes us to receive interrupts even though we've not 
+	   yet enabled the tx channel.  Go figure.  It'd be better to configure
+	   the chip in the probe1() routine, but then we don't see interrupts
+	   at all.  Everything looks all right on the logic analyzer, but... */
+
+	ncr885e_config( dev );
+
+	/* enable ethernet interrupts */
+	if ( request_irq( dev->irq, &ncr885e_interrupt, SA_SHIRQ, chipname, dev )) {
+		printk( KERN_ERR "%s: can't get irq %d\n", dev->name, dev->irq );
+		return -EAGAIN;
+	}
+
+	(void) inw( ioaddr + INTERRUPT_CLEAR );
+
+	ncr885e_enable( dev );
+
+	/* start rx DBDMA */
+	outl( virt_to_bus( sp->rx_cmds ), ioaddr + RX_CMD_PTR_LO );
+	outl( (RX_DBDMA_ENABLE << 16)|RX_CHANNEL_RUN,
+	      ioaddr + RX_CHANNEL_CONTROL );
+
+	dev->start = 1;
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+static int
+ncr885e_xmit_start( struct sk_buff *skb, struct device *dev )
+
+{
+	struct ncr885e_private *sp = (struct ncr885e_private *) dev->priv;
+	volatile struct dbdma_cmd *cp, *dp;
+	unsigned long flags, ioaddr = dev->base_addr;
+	int len, next, fill, entry;
+
+	if ( ncr885e_debug > 3)
+		printk( KERN_INFO "%s: xmit_start len=%d, dirty=%d, current=%d, active=%d\n",
+			dev->name, skb->len, sp->tx_dirty, sp->tx_current, sp->tx_active );
+
+	spin_lock_irqsave( &sp->lock, flags );
+
+	/* find the free slot in the ring buffer */
+	fill = sp->tx_current;
+	next = fill + 1;
+
+	if ( next >= NR_TX_RING )
+		next = 0;
+
+	/* mark ourselves as busy, even if we have too many packets waiting */
+	dev->tbusy = 1;
+
+	/* see if it's necessary to defer this packet */
+	if ( sp->tx_active >= MAX_TX_ACTIVE ) {
+		spin_unlock_irqrestore( &sp->lock, flags );
+		return -1;
+	}
+
+	sp->tx_active++;  /* bump "active tx" count */
+	sp->tx_current = next;  /* and show that we've used this buffer */
+	sp->tx_dirty = fill;     /* and mark this one to get picked up */
+
+	len = skb->len;
+
+	if ( len > ETH_FRAME_LEN ) {
+		printk( KERN_DEBUG "%s: xmit frame too long (%d)\n", dev->name, len );
+		len = ETH_FRAME_LEN;
+	}  
+
+	/* get index into the tx DBDMA chain */
+	entry = fill * 3;
+	sp->tx_skbufs[fill] = skb;
+	cp = sp->tx_cmds + entry;
+	dp = cp + 1;
+
+	/* update the rest of the OUTPUT_MORE descriptor */
+	outw( len, &cp->req_count );
+	outl( virt_to_bus( skb->data ), &cp->phy_addr );
+	outw( 0, &cp->xfer_status );
+	outw( 0, &cp->res_count );
+
+	/* and finish off the INPUT_MORE */
+	outw( 0, &dp->xfer_status );
+	outw( 0, &dp->res_count );
+	sp->tx_status[fill] = 0;
+	outl( virt_to_bus( &sp->tx_status[fill] ), &dp->phy_addr );
+
+	if ( ncr885e_debug > 2 )
+		printk(KERN_INFO "%s: xmit_start: active %d, tx_current %d, tx_dirty %d\n",
+		       dev->name, sp->tx_active, sp->tx_current, sp->tx_dirty );
+
+	if ( ncr885e_debug > 4 ) {
+		show_dbdma_cmd( cp );
+		show_dbdma_cmd( dp );
+	}
+
+
+	/* restart the tx DMA engine */
+	outl( virt_to_bus( cp ), ioaddr + TX_CMD_PTR_LO );
+	outl( (TX_DBDMA_ENABLE << 16)|TX_CHANNEL_RUN, 
+	      ioaddr + TX_CHANNEL_CONTROL );
+
+	ncr885e_set_timeout( dev );
+
+	spin_unlock_irqrestore( &sp->lock, flags );
+	dev->trans_start = jiffies;
+
+	return 0;      
+}
+
+static int
+ncr885e_close(struct device *dev)
+
+{
+	int i;
+	struct ncr885e_private *np = (struct ncr885e_private *) dev->priv;
+	unsigned long ioaddr = dev->base_addr;
+
+	dev->start = 0;
+	dev->tbusy = 1;
+
+	spin_lock( &np->lock );
+
+	printk(KERN_INFO "%s: NCR885E Ethernet closing...\n", dev->name );
+
+	if (ncr885e_debug > 1)
+		printk(KERN_DEBUG "%s: Shutting down Ethernet chip\n", dev->name);
+
+	ncr885e_disable(dev);
+
+	del_timer(&np->tx_timeout);
+
+	/* flip off rx and tx */
+	outl( (RX_DBDMA_ENABLE << 16), ioaddr + RX_CHANNEL_CONTROL );
+	outl( (TX_DBDMA_ENABLE << 16), ioaddr + TX_CHANNEL_CONTROL );  
+
+	/* free up the IRQ */
+	free_irq( dev->irq, dev );
+
+	for( i = 0; i < NR_RX_RING; i++ ) {
+		if (np->rx_skbufs[i])
+			dev_kfree_skb( np->rx_skbufs[i] );
+		np->rx_skbufs[i] = 0;
+	}
+#if 0
+	for (i = 0; i < NR_TX_RING; i++) {
+		if (np->tx_skbufs[i])
+			dev_kfree_skb(np->tx_skbufs[i]);
+		np->tx_skbufs[i] = 0;
+	}
+#endif
+	spin_unlock( &np->lock );
+
+	kfree( np->head );
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+
+/*
+ *  multicast promiscuous mode isn't used here.  Allow code in the
+ *  IP stack to determine which multicast packets are good or bad....
+ *  (this avoids having to use the hash table registers)
+ */
+static void
+ncr885e_set_multicast( struct device *dev )
+
+{
+	int ioaddr = dev->base_addr;
+
+	if ( ncr885e_debug > 3 )
+		printk("%s: set_multicast: dev->flags = %x, AF=%04x\n", 
+		       dev->name, dev->flags, inw( ioaddr + ADDRESS_FILTER ));
+
+	if ( dev->flags & IFF_PROMISC ) {
+		printk( KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name );
+		outw( ADDRESS_RPPRO, ioaddr + ADDRESS_FILTER );
+	}
+
+	/* accept all multicast packets without checking the mc_list.  */
+	else if ( dev->flags & IFF_ALLMULTI ) {
+		printk( KERN_INFO "%s: Enabling all multicast packets.\n", 
+			dev->name );
+		outw( ADDRESS_RPPRM, ioaddr + ADDRESS_FILTER );
+	}
+
+	/* enable broadcast rx */
+	else {
+		outw( ADDRESS_RPABC, ioaddr + ADDRESS_FILTER );
+	}  
+}
+
+static struct net_device_stats *
+ncr885e_stats( struct device *dev )
+
+{
+	struct ncr885e_private *np = (struct ncr885e_private *) dev->priv;
+
+	return &np->stats;
+}
+
+/*  By this function, we're certain that we have a 885 Ethernet controller
+ *  so we finish setting it up and wrap up all the required Linux ethernet
+ *  configuration.
+ */
+
+static int
+ncr885e_probe1( struct device *dev, unsigned long ioaddr, unsigned char irq )
+
+{
+	struct ncr885e_private *sp;
+	unsigned short station_addr[3], val;
+	unsigned char *p;
+	int  i;
+
+	dev = init_etherdev( dev, 0 );
+
+	/* construct private data for the 885 ethernet */
+	dev->priv = kmalloc( sizeof( struct ncr885e_private ), GFP_KERNEL );
+
+	if ( dev->priv == NULL )
+		return -ENOMEM;
+
+	sp = (struct ncr885e_private *) dev->priv;
+	memset( sp, 0, sizeof( struct ncr885e_private ));
+
+	/* snag the station address and display it */
+	for( i = 0; i < 3; i++ ) {
+		val = inw( ioaddr + STATION_ADDRESS_0 + (i*2));
+		station_addr[i] = ((val >> 8) & 0xff) | ((val << 8) & 0xff00);
+	}
+
+	printk( KERN_INFO "%s: %s at %08lx,", dev->name, chipname, ioaddr );
+
+	p = (unsigned char *) &station_addr;
+
+	for( i=0; i < 6; i++ ) {
+		dev->dev_addr[i] = *p;
+		printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i] );
+		p++;
+	}
+
+	printk(", IRQ %d.\n", irq );
+
+	request_region( ioaddr, NCR885E_TOTAL_SIZE, dev->name );
+
+	/* set up a timer */
+	init_timer( &sp->tx_timeout );
+	sp->timeout_active = 0;
+
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+
+	ether_setup( dev );
+
+	/* everything else */
+	dev->open = ncr885e_open;
+	dev->stop = ncr885e_close;
+	dev->get_stats = ncr885e_stats;
+	dev->hard_start_xmit = ncr885e_xmit_start;
+	dev->set_multicast_list = ncr885e_set_multicast;
+	dev->set_mac_address = ncr885e_set_address;
+
+	return 0;
+}
+
+/*  Since the NCR 53C885 is a multi-function chip, I'm not worrying about
+ *  trying to get the the device(s) in slot order.  For our (Synergy's)
+ *  purpose, there's just a single 53C885 on the board and we don't 
+ *  worry about the rest.
+ */
+
+int __init ncr885e_probe( struct device *dev )
+{
+	struct pci_dev *pdev = NULL;
+	unsigned int ioaddr, chips = 0;
+	unsigned short cmd;
+	unsigned char irq, latency;
+
+	while(( pdev = pci_find_device( PCI_VENDOR_ID_NCR, 
+					PCI_DEVICE_ID_NCR_53C885_ETHERNET,
+					pdev )) != NULL ) {
+
+		if ( !print_version ) {
+			print_version++;
+			printk( KERN_INFO "%s", version );
+		}
+
+		/* Use I/O space */
+		pci_read_config_dword( pdev, PCI_BASE_ADDRESS_0, &ioaddr );
+		pci_read_config_byte( pdev, PCI_INTERRUPT_LINE, &irq );
+
+		ioaddr &= ~3;
+		/* Adjust around the Grackle... */
+#ifdef CONFIG_GEMINI
+		ioaddr |= 0xfe000000;
+#endif
+
+		if ( check_region( ioaddr, NCR885E_TOTAL_SIZE ))
+			continue;
+
+		/* finish off the probe */
+		if ( !(ncr885e_probe1( dev, ioaddr, irq ))) {
+
+			chips++;
+
+			/* Access is via I/O space, bus master enabled... */
+			pci_read_config_word( pdev, PCI_COMMAND, &cmd );
+
+			if ( !(cmd & PCI_COMMAND_MASTER) ) {
+				printk( KERN_INFO "  PCI master bit not set! Now setting.\n");
+				cmd |= PCI_COMMAND_MASTER;
+				pci_write_config_word( pdev, PCI_COMMAND, cmd );
+			}
+
+			if ( !(cmd & PCI_COMMAND_IO) ) {
+				printk( KERN_INFO "  Enabling I/O space.\n" );
+				cmd |= PCI_COMMAND_IO;
+				pci_write_config_word( pdev, PCI_COMMAND, cmd );
+			}
+
+			pci_read_config_byte( pdev, PCI_LATENCY_TIMER, &latency );
+
+			if ( latency < 10 ) {
+				printk( KERN_INFO "  PCI latency timer (CFLT) is unreasonably"
+					" low at %d.  Setting to 255.\n", latency );
+				pci_write_config_byte( pdev, PCI_LATENCY_TIMER, 255 );
+			}
+		}
+	}
+
+	if ( !chips )
+		return -ENODEV;
+	else
+		return 0;
+}
+
+/* debugging to peek at dma descriptors */
+static void
+show_dbdma_cmd( volatile struct dbdma_cmd *cmd )
+
+{
+	printk( KERN_INFO " cmd %04x, physaddr %08x, req_count %04x\n",
+		inw( &cmd->command ), inl( &cmd->phy_addr ), inw( &cmd->req_count ));
+	printk( KERN_INFO " res_count %04x, xfer_status %04x, branch %08x\n", 
+		inw( &cmd->res_count ), inw( &cmd->xfer_status ),inl( &cmd->cmd_dep ));
+}
+
+#if 0
+static int
+read_eeprom( unsigned int ioaddr, int location )
+
+{
+	int loop;
+	unsigned char val;
+
+	outb( (location & 0xff), ioaddr + EE_WORD_ADDR );
+
+	/* take spillover from location in control reg */
+	outb(EE_CONTROL_RND_READB | (location & (0x7<<8)), ioaddr + EE_CONTROL);
+
+	loop = 1000;
+	while( (inb( ioaddr + EE_STATUS) & EE_SEB) &&
+	       (loop > 0) ) {
+		udelay( 10 );
+		loop--;
+	}
+
+	if ( inb( ioaddr + EE_STATUS ) & EE_SEE ) {
+		printk("%s: Serial EEPROM read error\n", chipname);
+		val = 0xff;
+	}
+
+	else 
+		val = inb( ioaddr + EE_READ_DATA );
+
+	return (int) val;
+}
+#endif
+
+#ifdef NCR885E_DEBUG_MII
+static void
+show_mii( unsigned long ioaddr )
+
+{
+	int   phyctrl, phystat, phyadvert, phypartner, phyexpan;
+
+	phyctrl = read_mii( ioaddr, MII_AUTO_NEGOTIATION_CONTROL );
+	phystat = read_mii( ioaddr, MII_AUTO_NEGOTIATION_STATUS );
+	phyadvert = read_mii( ioaddr, MII_AUTO_NEGOTIATION_ADVERTISEMENT );
+	phypartner = read_mii( ioaddr, MII_AUTO_NEGOTIATION_LINK_PARTNER );
+	phyexpan = read_mii( ioaddr, MII_AUTO_NEGOTIATION_EXPANSION );
+
+	printk( KERN_INFO "PHY: advert=%d %s, partner=%s %s, link=%d, %s%s\n",
+		(phyadvert & MANATECH_100BASETX_FULL_DUPLEX ? 100 : 10),
+		(phyctrl & MANC_AUTO_NEGOTIATION_ENABLE ? "auto" : "fixed"),
+		(phypartner & MANLP_ACKNOWLEDGE ?
+		 (phypartner & MANATECH_100BASETX_FULL_DUPLEX ? "100" : "10") :
+		 "?"),
+		(phyexpan & MANE_LINK_PARTNER_AUTO_ABLE ? "auto" : "fixed"),
+		(phyctrl & MANC_PHY_SPEED_100 ? 100 : 10),
+		(phystat & MANS_LINK_STATUS ? "up" : "down"),
+		(phyexpan & MANE_PARALLEL_DETECTION_FAULT ? " PD-fault" : "" ));
+	return;
+}
+
+
+static int
+read_mii( unsigned long ioaddr, int reg )
+
+{
+	int    timeout;
+
+
+	timeout = 100000;
+
+	while( inw( ioaddr + MII_INDICATOR ) & MII_BUSY ) {
+
+		if ( timeout-- < 0 ) {
+			printk( KERN_INFO "Timed out waiting for MII\n" );
+			return -1;
+		}
+	}
+
+	outw( (1<<8) + reg, ioaddr + MII_ADDRESS );
+	outw( MIIM_RSTAT, ioaddr + MIIM_COMMAND );
+
+	timeout = 100000;
+	while( inw( ioaddr + MII_INDICATOR ) & MII_BUSY ) {
+		if ( timeout-- < 0 ) {
+			printk( KERN_INFO "Timed out waiting for MII\n" );
+			return -1;
+		}
+	}
+
+	return( inw( ioaddr + MII_READ_DATA ));
+}
+
+static void
+write_mii( unsigned long ioaddr, int reg, int data )
+
+{
+	int timeout=100000;
+
+	printk( KERN_INFO "MII indicator: %02x\n", inw( ioaddr + MII_INDICATOR ));
+
+	while( inw( ioaddr + MII_INDICATOR ) & MII_BUSY ) {
+		if ( timeout-- <= 0 ) {
+			printk( KERN_INFO "Timeout waiting to write to MII\n" );
+			return;
+		}
+		udelay( 10 );
+	}
+
+	outw( (1<<8) + reg, ioaddr + MII_ADDRESS );
+	outw( data, ioaddr + MII_WRITE_DATA );
+
+	return;
+}
+
+#endif /* NCR885E_DEBUG_MII */
+
+#ifdef MODULE
+#if defined(LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20118
+MODULE_AUTHOR("dan@synergymicro.com");
+MODULE_DESCRIPTION("Symbios 53C885 Ethernet driver");
+MODULE_PARM(debug, "i");
+#endif 
+
+static int debug = 1;
+
+int
+init_module(void)
+{
+	if ( debug >= 0)
+		ncr885e_debug = debug;
+
+	return ncr885e_probe( NULL );
+}
+
+void
+cleanup_module(void)
+{
+	struct ncr885e_private *np;
+
+	if ( root_dev ) {
+
+		unregister_netdev( root_dev );
+		np = (struct ncr885e_private *) root_dev->priv;
+		release_region( root_dev->base_addr, NCR885E_TOTAL_SIZE );
+		kfree( root_dev->priv );
+		root_dev = NULL;
+	}  
+}
+#endif /* MODULE */
+
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O6 -c symba.c"
+ * End:
+ */
diff -urN linux-2.2.14-pre4/drivers/net/ncr885e.h linux-2.2.14-pre5/drivers/net/ncr885e.h
--- linux-2.2.14-pre4/drivers/net/ncr885e.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.14-pre5/drivers/net/ncr885e.h	2003-08-15 15:08:54.000000000 -0700
@@ -0,0 +1,367 @@
+#ifndef _NET_H_SYMBA
+#define _NET_H_SYMBA
+
+/* transmit status bit definitions */
+#define TX_STATUS_TXOK         (1<<13)     /* success */
+#define TX_STATUS_TDLC         (1<<12)     /* dropped for late colls */
+#define TX_STATUS_TCXSDFR      (1<<11)     /* excessive deferral */
+#define TX_STATUS_TDEC         (1<<10)     /* excessive collisions */
+#define TX_STATUS_TAUR         (1<<9)      /* abort on underrun/"jumbo" */
+#define TX_STATUS_PDFRD        (1<<8)      /* packet deferred */
+#define TX_STATUS_BCAST        (1<<7)      /* broadcast ok */
+#define TX_STATUS_MCAST        (1<<6)      /* multicast ok */
+#define TX_STATUS_CRCERR       (1<<5)      /* CRC error */
+#define TX_STATUS_LC           (1<<4)      /* late collision */
+#define TX_STATUS_CCNT_MASK    0xf         /* collision count */
+
+#define T_TXOK      (1<<13)
+#define T_TDLC      (1<<12)
+#define T_TCXSDFR   (1<<11)
+#define T_TDEC      (1<<10)
+#define T_TAUR      (1<<9)
+#define T_PDFRD     (1<<8)
+#define T_BCAST     (1<<7)
+#define T_MCAST     (1<<6)
+#define T_LC        (1<<4)
+#define T_CCNT_MASK 0xf
+
+/* receive status bit definitions */
+#define RX_STATUS_RXOVRN       (1<<23)     /* overrun */
+#define RX_STATUS_CEPS         (1<<22)     /* carrier event already seen */
+#define RX_STATUS_RXOK         (1<<21)     /* success */
+#define RX_STATUS_BCAST        (1<<20)     /* broadcast ok */
+#define RX_STATUS_MCAST        (1<<19)     /* multicast ok */
+#define RX_STATUS_CRCERR       (1<<18)     /* CRC error */
+#define RX_STATUS_DR           (1<<17)     /* dribble nibble */
+#define RX_STATUS_RCV          (1<<16)     /* rx code violation */
+#define RX_STATUS_PTL          (1<<15)     /* pkt > 1518 bytes */
+#define RX_STATUS_PTS          (1<<14)     /* pkt < 64 bytes */
+#define RX_STATUS_LEN_MASK     0x1fff      /* length mask */
+
+#define EEPROM_LENGTH          100
+
+
+/*  Serial EEPROM interface  */
+#define EE_STATUS              0xf0
+#define EE_CONTROL             0xf1
+#define EE_WORD_ADDR           0xf2
+#define EE_READ_DATA           0xf3
+#define EE_WRITE_DATA          0xf4
+#define EE_FEATURE_ENB         0xf5
+
+/*  Use on EE_STATUS  */
+#define EE_SEB                 (1<<8)
+#define EE_SEE                     1
+
+/*  Serial EEPROM commands */
+#define EE_CONTROL_SEQ_READB   (1<<4)
+#define EE_CONTROL_RND_WRITEB  (1<<5)
+#define EE_CONTROL_RND_READB   ((1<<4)|(1<<5))
+
+/*  Enable writing to serial EEPROM */
+#define EE_WRITE_ENB                1
+
+/*  The 885 configuration register */
+#define MAC_CONFIG             0xa0
+#define  MAC_CONFIG_SRST       1<<15
+#define  MAC_CONFIG_ITXA       1<<13
+#define  MAC_CONFIG_RXEN       1<<12
+#define  MAC_CONFIG_INTLB      1<<10
+#define  MAC_CONFIG_MODE_MASK  (1<<8|1<<9)
+#define  MAC_CONFIG_MODE_TP    1<<8
+#define  MAC_CONFIG_HUGEN      1<<5
+#define  MAC_CONFIG_RETRYL     1<<4
+#define  MAC_CONFIG_CRCEN      1<<3
+#define  MAC_CONFIG_PADEN      1<<2
+#define  MAC_CONFIG_FULLD      1<<1
+#define  MAC_CONFIG_NOCFR      1<<0
+
+
+
+
+
+#define TX_WAIT_SELECT         0x18
+#define RX_CHANNEL_CONTROL     0x40
+
+/* Tx channel status */
+#define TX_DBDMA_REG           0x00
+#define TX_CHANNEL_CONTROL     0x00
+#define TX_CHANNEL_STATUS      0x04
+#define  TX_STATUS_RUN         1<<15
+#define  TX_STATUS_PAUSE       1<<14
+#define  TX_STATUS_WAKE        1<<12
+#define  TX_STATUS_DEAD        1<<11
+#define  TX_STATUS_ACTIVE      1<<10
+#define  TX_STATUS_BT          1<<8
+#define  TX_STATUS_TXABORT     1<<7
+#define  TX_STATUS_TXSR        1<<6
+
+#define  TX_CHANNEL_RUN        TX_STATUS_RUN
+#define  TX_CHANNEL_PAUSE      TX_STATUS_PAUSE
+#define  TX_CHANNEL_WAKE       TX_STATUS_WAKE
+#define  TX_CHANNEL_DEAD       TX_STATUS_DEAD
+#define  TX_CHANNEL_ACTIVE     TX_STATUS_ACTIVE
+#define  TX_CHANNEL_BT         TX_STATUS_BT
+#define  TX_CHANNEL_TXABORT    TX_STATUS_TXABORT
+#define  TX_CHANNEL_TXSR       TX_STATUS_TXSR
+
+#define  TX_DBDMA_ENABLE       (TX_CHANNEL_WAKE | TX_CHANNEL_PAUSE | \
+                                TX_CHANNEL_RUN )
+
+/* Transmit command ptr lo register */
+#define TX_CMD_PTR_LO          0x0c
+
+/* Transmit interrupt select register */
+#define TX_INT_SELECT          0x10
+
+/* Transmit branch select register */
+#define TX_BRANCH_SELECT       0x14
+
+/* Transmit wait select register */
+#define TX_WAIT_SELECT         0x18
+#define  TX_WAIT_STAT_RECV     0x40
+
+/* Rx channel status */
+#define RX_DBDMA_REG           0x40
+#define RX_CHANNEL_CONTROL     0x40
+#define RX_CHANNEL_STATUS      0x44
+#define  RX_STATUS_RUN         1<<15
+#define  RX_STATUS_PAUSE       1<<14
+#define  RX_STATUS_WAKE        1<<12
+#define  RX_STATUS_DEAD        1<<11
+#define  RX_STATUS_ACTIVE      1<<10
+#define  RX_STATUS_BT          1<<8
+#define  RX_STATUS_EOP         1<<6
+
+#define  RX_CHANNEL_RUN        RX_STATUS_RUN
+#define  RX_CHANNEL_PAUSE      RX_STATUS_PAUSE
+#define  RX_CHANNEL_WAKE       RX_STATUS_WAKE
+#define  RX_CHANNEL_DEAD       RX_STATUS_DEAD
+#define  RX_CHANNEL_ACTIVE     RX_STATUS_ACTIVE
+#define  RX_CHANNEL_BT         RX_STATUS_BT
+#define  RX_CHANNEL_EOP        RX_STATUS_EOP
+
+#define  RX_DBDMA_ENABLE       (RX_CHANNEL_WAKE | RX_CHANNEL_PAUSE | \
+                                RX_CHANNEL_RUN)
+
+/*  Receive command ptr lo  */
+#define RX_CMD_PTR_LO          0x4c
+
+/*  Receive interrupt select register */
+#define RX_INT_SELECT          0x50
+#define  RX_INT_SELECT_EOP     0x40
+
+/*  Receive branch select  */
+#define RX_BRANCH_SELECT       0x54
+#define  RX_BRANCH_SELECT_EOP  0x40
+
+/*  Receive wait select  */
+#define RX_WAIT_SELECT         0x58
+#define  RX_WAIT_SELECT_EOP    0x40
+
+/*  Event status register  */
+#define EVENT_STATUS           0x80
+#define  EVENT_TXSR            1<<2
+#define  EVENT_EOP             1<<1
+#define  EVENT_TXABORT         1<<0
+
+/*  Interrupt enable register  */
+#define INTERRUPT_ENABLE       0x82
+
+/*  Interrupt clear register  */
+#define INTERRUPT_CLEAR        0x84
+
+/*  Interrupt status register  */
+#define INTERRUPT_STATUS_REG   0x86
+
+/*  bits for the above three interrupt registers */
+#define  INTERRUPT_INTE        1<<15   /* interrupt enable */
+#define  INTERRUPT_WI          1<<9    /* wakeup interrupt */
+#define  INTERRUPT_ERI         1<<8    /* early recieve interrupt */
+#define  INTERRUPT_PPET        1<<7    /* PCI Tx parity error */
+#define  INTERRUPT_PBFT        1<<6    /* PCI Tx bus fault */
+#define  INTERRUPT_IIDT        1<<5    /* illegal instruction Tx */
+#define  INTERRUPT_DIT         1<<4    /* DBDMA Tx interrupt */
+#define  INTERRUPT_PPER        1<<3    /* PCI Rx parity error */
+#define  INTERRUPT_PBFR        1<<2    /* PCI Rx bus fault */
+#define  INTERRUPT_IIDR        1<<1    /* illegal instruction Rx */
+#define  INTERRUPT_DIR         1<<0    /* DBDMA Rx interrupt */
+
+#define  INTERRUPT_TX_MASK     (INTERRUPT_PBFT|INTERRUPT_IIDT| \
+                                INTERRUPT_PPET|INTERRUPT_DIT)
+#define  INTERRUPT_RX_MASK     (INTERRUPT_PBFR|INTERRUPT_IIDR| \
+                                INTERRUPT_PPER|INTERRUPT_DIR)
+
+/*  chip revision register */
+#define CHIP_REVISION_REG      0x8c
+#define  CHIP_PCIREV_MASK      (0xf<<16)
+#define  CHIP_PCIDEV_MASK      0xff
+
+/*  Tx threshold register */
+#define TX_THRESHOLD           0x94
+
+/*  General purpose register */
+#define GEN_PURPOSE_REG        0x9e
+
+/*  General purpose pin control reg */
+#define GEN_PIN_CONTROL_REG    0x9f
+
+/*  DBDMA control register  */
+#define DBDMA_CONTROL          0x90
+#define  DBDMA_SRST            1<<31
+#define  DBDMA_TDPCE           1<<23
+#define  DBDMA_BE              1<<22
+#define  DBDMA_TAP_MASK        (1<<19|1<<20|1<<21)
+#define  DBDMA_RAP_MASK        (1<<16|1<<17|1<<18)
+#define  DBDMA_DPMRLE          1<<15
+#define  DBDMA_WIE             1<<14
+#define  DBDMA_MP              1<<13
+#define  DBDMA_SME             1<<12
+#define  DBDMA_CME             1<<11
+#define  DBDMA_DDPE            1<<10
+#define  DBDMA_TDPE            1<<9
+#define  DBDMA_EXTE            1<<8
+#define  DBDMA_BST_MASK        (1<<4|1<<5|1<<6)
+#define  DBDMA_BSR_MASK        (1<<0|1<<1|1<<2)
+
+#define  DBDMA_BURST_1         (0x00)
+#define  DBDMA_BURST_2         (0x01)
+#define  DBDMA_BURST_4         (0x02)
+#define  DBDMA_BURST_8         (0x03)
+#define  DBDMA_BURST_16        (0x04)
+#define  DBDMA_BURST_32        (0x05)
+#define  DBDMA_BURST_64        (0x06)
+#define  DBDMA_BURST_128       (0x07)
+
+#define  DBDMA_TX_BST_SHIFT    (4)
+#define  DBDMA_RX_BST_SHIFT    (0)
+
+#define  DBDMA_TX_ARBITRATION_DEFAULT ( 1 << 19 )
+#define  DBDMA_RX_ARBITRATION_DEFAULT ( 2 << 16 )
+
+
+/*  Back-to-back interpacket gap register */
+#define BTOB_INTP_GAP          0xa2
+#define  BTOB_INTP_DEFAULT     0x18
+
+/*  Non-back-to-back interpacket gap register */
+#define NBTOB_INTP_GAP         0xa4
+
+/*  MIIM command register */
+#define MIIM_COMMAND           0xa6
+#define  MIIM_SCAN             1<<1
+#define  MIIM_RSTAT            1<<0
+
+/*  MII address register */
+#define MII_ADDRESS            0xa8
+#define  MII_FIAD_MASK         (1<<8|1<<9|1<<10|1<<11|1<<12)
+#define  MII_RGAD_MASK         (1<<0|1<<1|1<<2|1<<3|1<<4)
+
+#define TPPMD_CONTROL_REG      0xa8
+#define  TPPMD_FO              1<<1
+#define  TPPMD_LB              1<<0
+
+/*  MII read and write registers */
+#define MII_WRITE_DATA         0xaa
+#define MII_READ_DATA          0xac
+
+/*  MII indicators */
+#define MII_INDICATOR          0xae
+#define  MII_NVALID            1<<2
+#define  MII_SCAN              1<<1
+#define  MII_BUSY              1<<0
+
+/*  Address filter  */
+#define ADDRESS_FILTER         0xd0
+#define  ADDRESS_RPPRM         1<<3       /* multicast promis. mode */
+#define  ADDRESS_RPPRO         1<<2       /* promiscuous mode */
+#define  ADDRESS_RPAMC         1<<1       /* accept multicasts */
+#define  ADDRESS_RPABC         1<<0       /* accept broadcasts */
+
+/*  Station addresses
+
+    Note that if the serial EEPROM is disabled, these values are all
+    zero.  If, like us, you get the chips when they're fresh, they're
+    also zero and you have to initialize the address */
+#define STATION_ADDRESS_0      0xd2
+#define STATION_ADDRESS_1      0xd4
+#define STATION_ADDRESS_2      0xd6
+
+/*  Hash tables  */
+#define HASH_TABLE_0           0xd8
+#define HASH_TABLE_1           0xda
+#define HASH_TABLE_2           0xdc
+#define HASH_TABLE_3           0xde
+
+/* PHY indentifiers */
+#define PHY_IDENTIFIER_0       0xe4
+#define PHY_IDENTIFIER_1       0xe6
+
+/*  MII Auto-negotiation register definitions  */
+
+#define MII_AUTO_NEGOTIATION_CONTROL        (0x0000)
+#define   MANC_PHY_RESET                      (0x8000)
+#define   MANC_PHY_LOOPBACK_ENABLE            (0x4000)
+#define   MANC_PHY_LOOPBACK_DISABLE           (0x0000)
+#define   MANC_PHY_SPEED_100                  (0x2000)
+#define   MANC_PHY_SPEED_10                   (0x0000)
+#define   MANC_AUTO_NEGOTIATION_ENABLE        (0x1000)
+#define   MANC_AUTO_NEGOTIATION_DISABLE       (0x0000)
+#define   MANC_PHY_POWER_DOWN                 (0x0800)
+#define   MANC_PHY_POWER_UP                   (0x0000)
+#define   MANC_ISOLATE_ENABLE                 (0x0400)
+#define   MANC_ISOLATE_DISABLE                (0x0000)
+#define   MANC_RESTART_AUTO_NEGOTIATION       (0x0200)
+#define   MANC_FULL_DUPLEX                    (0x0100)
+#define   MANC_HALF_DUPLEX                    (0x0000)
+
+#define MII_AUTO_NEGOTIATION_STATUS         (0x0001)
+#define   MANS_100BASE_T4_HALF_DUPLEX         (0x8000)
+#define   MANS_100BASE_X_FULL_DUPLEX          (0x4000)
+#define   MANS_100BASE_X_HALF_DUPLEX          (0x2000)
+#define   MANS_10MBS_FULL_DUPLEX              (0x1000)
+#define   MANS_10MBS_HALF_DUPLEX              (0x0800)
+#define   MANS_AUTO_NEGOTIATION_COMPLETE      (0x0020)
+#define   MANS_REMOTE_FAULT                   (0x0010)
+#define   MANS_AUTO_NEGOTIATION_ABILITY       (0x0008)
+#define   MANS_LINK_STATUS                    (0x0004)
+#define   MANS_JABBER_DETECT                  (0x0002)
+#define   MANS_EXTENDED_CAPABILITY            (0x0001)
+
+#define MII_PHY_IDENTIFIER_1                (0x0002)
+#define MII_PHY_IDENTIFIER_2                (0x0003)
+
+#define MII_AUTO_NEGOTIATION_ADVERTISEMENT  (0x0004)
+#define   MANA_NEXT_PAGE                      (0x8000)
+#define   MANA_REMOTE_FAULT                   (0x2000)
+#define   MANA_TECHNOLOGY_ABILITY_MASK        (0x1FE0)
+#define     MANATECH_10BASET_HALF_DUPLEX        (0x0020)
+#define     MANATECH_10BASET_FULL_DUPLEX        (0x0040)
+#define     MANATECH_100BASETX_HALF_DUPLEX      (0x0080)
+#define     MANATECH_100BASETX_FULL_DUPLEX      (0x0100)
+#define     MANATECH_100BASET4                  (0x0200)
+#define   MANA_SELECTOR_MASK                  (0x001F)
+#define     MANASELECTOR_802_3                  (0x0001)
+
+#define MII_AUTO_NEGOTIATION_LINK_PARTNER   (0x0005)
+#define   MANLP_NEXT_PAGE                     (0x8000)
+#define   MANLP_ACKNOWLEDGE                   (0x4000)
+#define   MANLP_REMOTE_FAULT                  (0x2000)
+#define   MANLP_TECHNOLOGY_ABILITY_MASK       (0x1FE0)
+#define   MANLP_SELECTOR_MASK                 (0x001F)
+
+#define MII_AUTO_NEGOTIATION_EXPANSION      (0x0006)
+#define   MANE_PARALLEL_DETECTION_FAULT       (0x0010)
+#define   MANE_LINK_PARTNER_NEXT_PAGE_ABLE    (0x0008)
+#define   MANE_NEXT_PAGE_ABLE                 (0x0004)
+#define   MANE_PAGE_RECEIVED                  (0x0002)
+#define   MANE_LINK_PARTNER_AUTO_ABLE         (0x0001)
+
+#define MII_AUTO_NEGOTIATION_NEXT_PAGE_TRANSMIT (0x0007)
+#define   MANNPT_NEXT_PAGE                    (0x8000)
+#define   MANNPT_MESSAGE_PAGE                 (0x2000)
+#define   MANNPT_ACKNOWLEDGE_2                (0x1000)
+#define   MANNPT_TOGGLE                       (0x0800)
+#define   MANNPT_MESSAGE_FIELD_MASK           (0x07FF)
+
+#endif
diff -urN linux-2.2.14-pre4/drivers/net/Space.c linux-2.2.14-pre5/drivers/net/Space.c
--- linux-2.2.14-pre4/drivers/net/Space.c	1999-10-19 17:14:01.000000000 -0700
+++ linux-2.2.14-pre5/drivers/net/Space.c	2003-08-15 15:08:54.000000000 -0700
@@ -103,6 +103,7 @@
 extern int tlan_probe(struct device *);
 extern int mace_probe(struct device *);
 extern int bmac_probe(struct device *);
+extern int ncr885e_probe(struct device *);
 extern int cs89x0_probe(struct device *dev);
 extern int ethertap_probe(struct device *dev);
 extern int ether1_probe (struct device *dev);
@@ -454,6 +455,9 @@
 #ifdef CONFIG_BMAC
 	{bmac_probe, 0},
 #endif
+#ifdef CONFIG_NCR885E
+	{ncr885e_probe, 0},
+#endif
 	{NULL, 0},
 };
 
diff -urN linux-2.2.14-pre4/drivers/scsi/scsi.c linux-2.2.14-pre5/drivers/scsi/scsi.c
--- linux-2.2.14-pre4/drivers/scsi/scsi.c	1999-10-19 17:14:01.000000000 -0700
+++ linux-2.2.14-pre5/drivers/scsi/scsi.c	2003-08-15 15:08:54.000000000 -0700
@@ -258,6 +258,7 @@
 {"TEAC","CD-ROM","1.06", BLIST_NOLUN},          /* causes failed REQUEST SENSE on lun 1
 						 * for seagate controller, which causes
 						 * SCSI code to reset bus.*/
+	{"TEAC", "MT-2ST/45S2-27", "RV M", BLIST_NOLUN},	/* Responds to all lun */
 {"TEXEL","CD-ROM","1.06", BLIST_NOLUN},         /* causes failed REQUEST SENSE on lun 1
 						 * for seagate controller, which causes
 						 * SCSI code to reset bus.*/
@@ -268,7 +269,8 @@
 {"HP", "C1750A", "3226", BLIST_NOLUN},          /* scanjet iic */
 {"HP", "C1790A", "", BLIST_NOLUN},              /* scanjet iip */
 {"HP", "C2500A", "", BLIST_NOLUN},              /* scanjet iicx */
-{"YAMAHA", "CDR102", "1.00", BLIST_NOLUN},	/* extra reset */
+{"YAMAHA","CDR100","1.00", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */
+{"YAMAHA","CDR102","1.00", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */
 {"RELISYS", "Scorpio", "*", BLIST_NOLUN},	/* responds to all LUN */
 
 /*
@@ -292,8 +294,6 @@
 {"nCipher","Fastness Crypto","*", BLIST_FORCELUN},
 {"NEC","PD-1 ODX654P","*", BLIST_FORCELUN | BLIST_SINGLELUN},
 {"MATSHITA","PD-1","*", BLIST_FORCELUN | BLIST_SINGLELUN},
-{"YAMAHA","CDR100","1.00", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */
-{"YAMAHA","CDR102","1.00", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */
 {"iomega","jaz 1GB","J.86", BLIST_NOTQ | BLIST_NOLUN},
 {"CREATIVE","DVD-RAM RAM","*", BLIST_GHOST},
 {"MATSHITA","PD-2 LF-D100","*", BLIST_GHOST},
diff -urN linux-2.2.14-pre4/fs/dcache.c linux-2.2.14-pre5/fs/dcache.c
--- linux-2.2.14-pre4/fs/dcache.c	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/fs/dcache.c	2003-08-15 15:08:54.000000000 -0700
@@ -45,9 +45,9 @@
 #define D_HASHBITS     d_hash_shift
 #define D_HASHMASK     d_hash_mask
 
-static unsigned int d_hash_mask = 0;
-static unsigned int d_hash_shift = 0;
-static struct list_head *dentry_hashtable = NULL;
+static unsigned int d_hash_mask;
+static unsigned int d_hash_shift;
+static struct list_head *dentry_hashtable;
 static LIST_HEAD(dentry_unused);
 
 struct {
@@ -71,18 +71,23 @@
  * Release the dentry's inode, using the fileystem
  * d_iput() operation if defined.
  */
-static inline void dentry_iput(struct dentry * dentry)
+static inline int dentry_iput(struct dentry * dentry)
 {
 	struct inode *inode = dentry->d_inode;
+	int ret = 0;
+
 	if (inode) {
 		dentry->d_inode = NULL;
 		list_del(&dentry->d_alias);
 		INIT_LIST_HEAD(&dentry->d_alias);
+		ret = inode->i_count == 1;
 		if (dentry->d_op && dentry->d_op->d_iput)
 			dentry->d_op->d_iput(dentry, inode);
 		else
 			iput(inode);
 	}
+
+	return ret;
 }
 
 /*
@@ -197,86 +202,23 @@
 }
 
 /*
- * Select less valuable dentries to be pruned when we need
- * inodes or memory. The selected dentries are moved to the
- * old end of the list where prune_dcache() can find them.
- * 
- * Negative dentries are included in the selection so that
- * they don't accumulate at the end of the list. The count
- * returned is the total number of dentries selected, which
- * may be much larger than the requested number of inodes.
- */
-int select_dcache(int inode_count, int page_count)
-{
-	struct list_head *next, *tail = &dentry_unused;
-	int found = 0;
-	int depth = dentry_stat.nr_unused >> 1;
-	unsigned long max_value = 4;
-
-	if (page_count)
-		max_value = -1;
-
-	next = tail->prev;
-	while (next != &dentry_unused && depth--) {
-		struct list_head *tmp = next;
-		struct dentry *dentry = list_entry(tmp, struct dentry, d_lru);
-		struct inode *inode = dentry->d_inode;
-		unsigned long value = 0;	
-
-		next = tmp->prev;
-		if (dentry->d_count) {
-			dentry_stat.nr_unused--;
-			list_del(tmp);
-			INIT_LIST_HEAD(tmp);
-			continue;
-		}
-
-		/*
-		 * Select dentries based on the page cache count ...
-		 * should factor in number of uses as well. We take
-		 * all negative dentries so that they don't accumulate.
-		 * (We skip inodes that aren't immediately available.)
-		 */
-		if (inode) {
-			value = inode->i_nrpages;	
-			if (value >= max_value)
-				continue;
-			if (inode->i_state || inode->i_count > 1)
-				continue;
-		}
-
-		/*
-		 * Move the selected dentries behind the tail.
-		 */
-		if (tmp != tail->prev) {
-			list_del(tmp);
-			list_add(tmp, tail->prev);
-		}
-		tail = tmp;
-		found++;
-		if (inode && --inode_count <= 0)
-			break;
-		if (page_count && (page_count -= value) <= 0)
-			break;
-	}
-	return found;
-}
-
-/*
  * Throw away a dentry - free the inode, dput the parent.
  * This requires that the LRU list has already been
  * removed.
  */
-static inline void prune_one_dentry(struct dentry * dentry)
+static inline int prune_one_dentry(struct dentry * dentry)
 {
 	struct dentry * parent;
+	int ret;
 
 	list_del(&dentry->d_hash);
 	list_del(&dentry->d_child);
-	dentry_iput(dentry);
+	ret = dentry_iput(dentry);
 	parent = dentry->d_parent;
 	d_free(dentry);
 	dput(parent);
+
+	return ret;
 }
 
 /*
@@ -284,9 +226,21 @@
  * more memory, or simply when we need to unmount
  * something (at which point we need to unuse
  * all dentries).
+ *
+ * If you don't want a limit on the number of
+ * inodes that will be released then call
+ * with i_nr = -1.
+ *
+ * If you don't want a limit on the number of
+ * dentries that will be released then call
+ * with d_nr = 0.
+ *
+ * Returns the number of inodes released.
  */
-void prune_dcache(int count)
+int prune_dcache(int d_nr, int i_nr)
 {
+	int __i_nr = i_nr;
+
 	for (;;) {
 		struct dentry *dentry;
 		struct list_head *tmp = dentry_unused.prev;
@@ -298,11 +252,15 @@
 		INIT_LIST_HEAD(tmp);
 		dentry = list_entry(tmp, struct dentry, d_lru);
 		if (!dentry->d_count) {
-			prune_one_dentry(dentry);
-			if (!--count)
+			i_nr -= prune_one_dentry(dentry);
+			if (!i_nr)
+				break;
+			if (!--d_nr)
 				break;
 		}
 	}
+
+	return __i_nr - i_nr;
 }
 
 /*
@@ -457,7 +415,7 @@
 	int found;
 
 	while ((found = select_parent(parent)) != 0)
-		prune_dcache(found);
+		prune_dcache(found, -1);
 }
 
 /*
@@ -477,7 +435,7 @@
 		int count = 0;
 		if (priority)
 			count = dentry_stat.nr_unused / priority;
-		prune_dcache(count);
+		prune_dcache(count, -1);
 	}
 }
 
@@ -926,8 +884,9 @@
 		panic("Cannot create dentry cache");
 
 	memory_size = num_physpages << PAGE_SHIFT;
-	for (order = 5; (1UL << order) < memory_size; order++)
-		;
+	memory_size >>= 13;
+	memory_size *= 2 * sizeof(void *);
+	for (order = 0; ((1UL << order) << PAGE_SHIFT) < memory_size; order++);
 
 	do {
 		unsigned long tmp;
diff -urN linux-2.2.14-pre4/fs/dquot.c linux-2.2.14-pre5/fs/dquot.c
--- linux-2.2.14-pre4/fs/dquot.c	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/fs/dquot.c	2003-08-15 15:08:54.000000000 -0700
@@ -31,6 +31,9 @@
  *		add_dquot_ref() restarts after blocking
  *		Added check for bogus uid and fixed check for group in quotactl.
  *		Jan Kara, <jack@atrey.karlin.mff.cuni.cz>, 4-6/99
+ *		Definitely (hopefully) fixed deadlock in write_dquot(). We no
+ *		longer account quota files.
+ *		Jan Kara, <jack@suse.cz>, 11/99, sposored by SuSE CR
  *
  * (C) Copyright 1994 - 1997 Marco van Wieringen 
  */
@@ -245,6 +248,9 @@
 	wake_up(&dquot->dq_wait);
 }
 
+/*
+ *	We don't have to be afraid of deadlocks as we never have quotas on quota files...
+ */
 static void write_dquot(struct dquot *dquot)
 {
 	short type = dquot->dq_type;
@@ -252,20 +258,14 @@
 	mm_segment_t fs;
 	loff_t offset;
 	ssize_t ret;
-	struct dqblk data;
 	struct semaphore *sem = &dquot->dq_mnt->mnt_dquot.dqio_sem;
 
-	/*
-	 * We copy our data to preserve consistency when dquot is not locked.
-	 * We can't lock it because it can cause deadlocks - think about
-	 * growing the quota file...
-	 */
-	memcpy(&data, &dquot->dq_dqb, sizeof(struct dqblk));
-	down(sem);
+	lock_dquot(dquot);
 	if (!dquot->dq_mnt) {	/* Invalidated quota? */
-		up(sem);
+		unlock_dquot(dquot);
 		return;
 	}
+	down(sem);
 	filp = dquot->dq_mnt->mnt_dquot.files[type];
 	offset = dqoff(dquot->dq_id);
 	fs = get_fs();
@@ -278,18 +278,15 @@
 	dquot->dq_flags &= ~DQ_MOD;
 	ret = 0;
 	if (filp)
-		ret = filp->f_op->write(filp, (char *)&data, 
+		ret = filp->f_op->write(filp, (char *)&dquot->dq_dqb, 
 					sizeof(struct dqblk), &offset);
 	if (ret != sizeof(struct dqblk))
 		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
 			kdevname(dquot->dq_dev));
 
-	/*
-	 * Be sure that anybody didn't invalidated the dquot in the mean time...
-	 * Nasty but I don't see other choice when we don't want to lock dquot.
-	 */
-	up(sem);
 	set_fs(fs);
+	up(sem);
+	unlock_dquot(dquot);
 
 	dqstats.writes++;
 }
@@ -572,10 +569,9 @@
 	/*
 	 * Try pruning the dcache to free up some dquots ...
 	 */
-	count = select_dcache(128, 0);
-	if (count) {
-		printk(KERN_DEBUG "get_empty_dquot: pruning %d\n", count);
-		prune_dcache(count);
+	printk(KERN_DEBUG "get_empty_dquot: pruning %d\n", count);
+	if (prune_dcache(0, 128))
+	{
 		free_inode_memory(count);
 		goto repeat;
 	}
@@ -652,12 +648,31 @@
 	return dquot;
 }
 
+/* Check whether this inode is quota file */
+static inline int is_quotafile(struct inode *inode)
+{
+	int cnt;
+	struct vfsmount *vfsmnt;
+	struct file **files;
+
+	vfsmnt = lookup_vfsmnt(inode->i_dev);
+	if (!vfsmnt)
+		return 0;
+	files = vfsmnt->mnt_dquot.files;
+	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+		if (files[cnt] && files[cnt]->f_dentry->d_inode == inode)
+			return 1;
+	return 0;
+}
+
 static int dqinit_needed(struct inode *inode, short type)
 {
 	int cnt;
 
         if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
                 return 0;
+	if (is_quotafile(inode))
+		return 0;
 	if (type != -1)
 		return inode->i_dquot[type] == NODQUOT;
 	for (cnt = 0; cnt < MAXQUOTAS; cnt++)
@@ -1070,6 +1085,9 @@
 	if (S_ISREG(inode->i_mode) ||
             S_ISDIR(inode->i_mode) ||
             S_ISLNK(inode->i_mode)) {
+		/* We don't want to have quotas on quota files - nasty deadlocks possible */
+		if (is_quotafile(inode))
+			return;
 		for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 			if (type != -1 && cnt != type)
 				continue;
@@ -1512,6 +1530,7 @@
 	error = -EINVAL;
 	if (inode->i_size == 0 || (inode->i_size % sizeof(struct dqblk)) != 0)
 		goto out_f;
+	dquot_drop(inode);	/* We don't want quota on quota files */
 
 	set_enable_flags(vfsmnt, type);
 	mnt_dquot->files[type] = f;
diff -urN linux-2.2.14-pre4/fs/ext2/balloc.c linux-2.2.14-pre5/fs/ext2/balloc.c
--- linux-2.2.14-pre4/fs/ext2/balloc.c	1999-08-09 12:04:41.000000000 -0700
+++ linux-2.2.14-pre5/fs/ext2/balloc.c	2003-08-15 15:08:54.000000000 -0700
@@ -603,6 +603,8 @@
 		unlock_super (sb);
 		return 0;
 	}
+	if (!buffer_uptodate(bh))
+		wait_on_buffer(bh);
 	memset(bh->b_data, 0, sb->s_blocksize);
 	mark_buffer_uptodate(bh, 1);
 	mark_buffer_dirty(bh, 1);
diff -urN linux-2.2.14-pre4/fs/ext2/fsync.c linux-2.2.14-pre5/fs/ext2/fsync.c
--- linux-2.2.14-pre4/fs/ext2/fsync.c	1998-05-20 13:09:12.000000000 -0700
+++ linux-2.2.14-pre5/fs/ext2/fsync.c	2003-08-15 15:08:54.000000000 -0700
@@ -45,10 +45,21 @@
 	if (!bh)
 		return 0;
 	if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
-		brelse (bh);
-		return -1;
+		/* There can be a parallell read(2) that started read-I/O
+		   on the buffer so we can't assume that there's been
+		   an I/O error without first waiting I/O completation. */
+		wait_on_buffer(bh);
+		if (!buffer_uptodate(bh))
+		{
+			brelse (bh);
+			return -1;
+		}
 	}
 	if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
+		if (wait)
+			/* when we return from fsync all the blocks
+			   must be _just_ stored on disk */
+			wait_on_buffer(bh);
 		brelse (bh);
 		return 0;
 	}
@@ -68,10 +79,21 @@
 	if (!bh)
 		return 0;
 	if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
-		brelse (bh);
-		return -1;
+		/* There can be a parallell read(2) that started read-I/O
+		   on the buffer so we can't assume that there's been
+		   an I/O error without first waiting I/O completation. */
+		wait_on_buffer(bh);
+		if (!buffer_uptodate(bh))
+		{
+			brelse (bh);
+			return -1;
+		}
 	}
 	if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) {
+		if (wait)
+			/* when we return from fsync all the blocks
+			   must be _just_ stored on disk */
+			wait_on_buffer(bh);
 		brelse (bh);
 		return 0;
 	}
diff -urN linux-2.2.14-pre4/fs/ext2/inode.c linux-2.2.14-pre5/fs/ext2/inode.c
--- linux-2.2.14-pre4/fs/ext2/inode.c	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/fs/ext2/inode.c	2003-08-15 15:08:54.000000000 -0700
@@ -125,6 +125,8 @@
 				    "cannot get block %lu", result);
 			return 0;
 		}
+		if (!buffer_uptodate(bh))
+			wait_on_buffer(bh);
 		memset(bh->b_data, 0, inode->i_sb->s_blocksize);
 		mark_buffer_uptodate(bh, 1);
 		mark_buffer_dirty(bh, 1);
diff -urN linux-2.2.14-pre4/fs/inode.c linux-2.2.14-pre5/fs/inode.c
--- linux-2.2.14-pre4/fs/inode.c	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/fs/inode.c	2003-08-15 15:08:54.000000000 -0700
@@ -343,12 +343,11 @@
 	(((inode)->i_count | (inode)->i_state) == 0)
 #define INODE(entry)	(list_entry(entry, struct inode, i_list))
 
-static int free_inodes(void)
+static int __free_inodes(struct list_head * freeable)
 {
-	struct list_head list, *entry, *freeable = &list;
+	struct list_head *entry;
 	int found = 0;
 
-	INIT_LIST_HEAD(freeable);
 	entry = inode_in_use.next;
 	while (entry != &inode_in_use) {
 		struct list_head *tmp = entry;
@@ -361,15 +360,19 @@
 		INIT_LIST_HEAD(&INODE(tmp)->i_hash);
 		list_add(tmp, freeable);
 		list_entry(tmp, struct inode, i_list)->i_state = I_FREEING;
-		found = 1;
+		found++;
 	}
 
-	if (found)
-		dispose_list(freeable);
-
 	return found;
 }
 
+static void free_inodes(void)
+{
+	LIST_HEAD(throw_away);
+	if (__free_inodes(&throw_away))
+		dispose_list(&throw_away);
+}
+
 /*
  * Searches the inodes list for freeable inodes,
  * shrinking the dcache before (and possible after,
@@ -377,6 +380,36 @@
  */
 static void try_to_free_inodes(int goal)
 {
+	static int block;
+	static struct wait_queue * wait_inode_freeing;
+	LIST_HEAD(throw_away);
+	
+	/* We must make sure to not eat the inodes
+	   while the blocker task sleeps otherwise
+	   the blocker task may find none inode
+	   available. */
+	if (block)
+	{
+		struct wait_queue __wait;
+
+		__wait.task = current;
+		add_wait_queue(&wait_inode_freeing, &__wait);
+		for (;;)
+		{
+			/* NOTE: we rely only on the inode_lock to be sure
+			   to not miss the unblock event */
+			current->state = TASK_UNINTERRUPTIBLE;
+			spin_unlock(&inode_lock);
+			schedule();
+			spin_lock(&inode_lock);
+			if (!block)
+				break;
+		}
+		remove_wait_queue(&wait_inode_freeing, &__wait);
+		current->state = TASK_RUNNING;
+	}
+
+	block = 1;
 	/*
 	 * First stry to just get rid of unused inodes.
 	 *
@@ -384,16 +417,18 @@
 	 * to try to shrink the dcache and sync existing
 	 * inodes..
 	 */
-	free_inodes();
-	goal -= inodes_stat.nr_free_inodes;
+	goal -= __free_inodes(&throw_away);
 	if (goal > 0) {
 		spin_unlock(&inode_lock);
-		select_dcache(goal, 0);
-		prune_dcache(goal);
+		prune_dcache(0, goal);
 		spin_lock(&inode_lock);
 		sync_all_inodes();
-		free_inodes();
+		__free_inodes(&throw_away);
 	}
+	if (!list_empty(&throw_away))
+		dispose_list(&throw_away);
+	block = 0;
+	wake_up(&wait_inode_freeing);
 }
 
 /*
@@ -472,7 +507,7 @@
 	 * If the allocation failed, do an extensive pruning of 
 	 * the dcache and then try again to free some inodes.
 	 */
-	prune_dcache(inodes_stat.nr_inodes >> 2);
+	prune_dcache(0, inodes_stat.nr_inodes >> 2);
 
 	spin_lock(&inode_lock);
 	free_inodes();
diff -urN linux-2.2.14-pre4/fs/isofs/inode.c linux-2.2.14-pre5/fs/isofs/inode.c
--- linux-2.2.14-pre4/fs/isofs/inode.c	1999-10-19 17:14:02.000000000 -0700
+++ linux-2.2.14-pre5/fs/isofs/inode.c	2003-08-15 15:08:54.000000000 -0700
@@ -954,7 +954,7 @@
 	printk("isofs_bmap: mapped inode:block %x:%d to block %lu\n",
 		inode->i_ino, block, (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode));
 #endif
-	return (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode);
+	return firstext + ((b_off - offset) >> ISOFS_BUFFER_BITS(inode));
 }
 
 
@@ -1162,8 +1162,7 @@
 	  iso_date(raw_inode->date, high_sierra);
 
 	inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) +
-					   isonum_711 (raw_inode->ext_attr_length))
-	  << inode -> i_sb -> u.isofs_sb.s_log_zone_size;
+					   isonum_711 (raw_inode->ext_attr_length));
 
 /* Now test for possible Rock Ridge extensions which will override some of
    these numbers in the inode structure. */
diff -urN linux-2.2.14-pre4/fs/isofs/rock.c linux-2.2.14-pre5/fs/isofs/rock.c
--- linux-2.2.14-pre4/fs/isofs/rock.c	1998-09-25 16:27:13.000000000 -0700
+++ linux-2.2.14-pre5/fs/isofs/rock.c	2003-08-15 15:08:54.000000000 -0700
@@ -358,9 +358,10 @@
 #ifdef DEBUG
 	printk("RR CL (%x)\n",inode->i_ino);
 #endif
-	inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location) <<
-		inode -> i_sb -> u.isofs_sb.s_log_zone_size;
-	reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent);
+	inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location);
+	reloc = iget(inode->i_sb,
+		     (inode->u.isofs_i.i_first_extent <<
+		      inode -> i_sb -> u.isofs_sb.s_log_zone_size));
 	if (!reloc)
 		goto out;
 	inode->i_mode = reloc->i_mode;
diff -urN linux-2.2.14-pre4/fs/lockd/mon.c linux-2.2.14-pre5/fs/lockd/mon.c
--- linux-2.2.14-pre4/fs/lockd/mon.c	1999-10-19 17:14:02.000000000 -0700
+++ linux-2.2.14-pre5/fs/lockd/mon.c	2003-08-15 15:08:54.000000000 -0700
@@ -195,6 +195,12 @@
 #define SM_my_id_sz	(3+1+SM_my_name_sz)
 #define SM_mon_id_sz	(1+XDR_QUADLEN(20)+SM_my_id_sz)
 #define SM_mon_sz	(SM_mon_id_sz+4)
+#define SM_monres_sz	2
+#define SM_unmonres_sz	1
+
+#ifndef MAX
+# define MAX(a, b)	(((a) > (b))? (a) : (b))
+#endif
 
 static struct rpc_procinfo	nsm_procedures[] = {
         { "sm_null",
@@ -205,10 +211,10 @@
 		(kxdrproc_t) xdr_error, 0, 0 },
         { "sm_mon",
 		(kxdrproc_t) xdr_encode_mon,
-		(kxdrproc_t) xdr_decode_stat_res, SM_mon_sz, 2 },
+		(kxdrproc_t) xdr_decode_stat_res, MAX(SM_mon_sz, SM_monres_sz) << 2, 0 },
         { "sm_unmon",
 		(kxdrproc_t) xdr_encode_mon,
-		(kxdrproc_t) xdr_decode_stat, SM_mon_id_sz, 1 },
+		(kxdrproc_t) xdr_decode_stat, MAX(SM_mon_id_sz, SM_unmonres_sz) << 2, 0 },
         { "sm_unmon_all",
 		(kxdrproc_t) xdr_error,
 		(kxdrproc_t) xdr_error, 0, 0 },
diff -urN linux-2.2.14-pre4/fs/smbfs/proc.c linux-2.2.14-pre5/fs/smbfs/proc.c
--- linux-2.2.14-pre4/fs/smbfs/proc.c	1999-06-13 19:54:06.000000000 -0700
+++ linux-2.2.14-pre5/fs/smbfs/proc.c	2003-08-15 15:08:54.000000000 -0700
@@ -1599,8 +1599,7 @@
 			command = TRANSACT2_FINDFIRST;
 			WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
 			WSET(param, 2, max_matches);	/* max count */
-			WSET(param, 4, 8 + 4 + 2);	/* resume required +
-							   close on end +
+			WSET(param, 4, 4 + 2);		/* close on end +
 							   continue */
 			WSET(param, 6, info_level);
 			DSET(param, 8, 0);
diff -urN linux-2.2.14-pre4/include/asm-ppc/gemini.h linux-2.2.14-pre5/include/asm-ppc/gemini.h
--- linux-2.2.14-pre4/include/asm-ppc/gemini.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.14-pre5/include/asm-ppc/gemini.h	2003-08-15 15:08:54.000000000 -0700
@@ -0,0 +1,166 @@
+/*
+ *  include/asm-ppc/gemini.h
+ *
+ *
+ *  Onboard registers and descriptions for Synergy Microsystems' 
+ *  "Gemini" boards.
+ *
+ */
+#ifndef __PPC_GEMINI_H
+#define __PPC_GEMINI_H
+
+/*  Registers  */
+
+#define GEMINI_SERIAL_B     (0xffeffb00)
+#define GEMINI_SERIAL_A     (0xffeffb08)
+#define GEMINI_USWITCH      (0xffeffd00)
+#define GEMINI_BREV         (0xffeffe00)
+#define GEMINI_BECO         (0xffeffe08)
+#define GEMINI_FEAT         (0xffeffe10)
+#define GEMINI_BSTAT        (0xffeffe18)
+#define GEMINI_CPUSTAT      (0xffeffe20)
+#define GEMINI_L2CFG        (0xffeffe30)
+#define GEMINI_MEMCFG       (0xffeffe38)
+#define GEMINI_FLROM        (0xffeffe40)
+#define GEMINI_P0PCI        (0xffeffe48)
+#define GEMINI_FLWIN        (0xffeffe50)
+#define GEMINI_P0INTMASK    (0xffeffe60)
+#define GEMINI_P0INTAP      (0xffeffe68)
+#define GEMINI_PCIERR       (0xffeffe70)
+#define GEMINI_LEDBASE      (0xffeffe80)
+#define GEMINI_RTC          (0xffe9fff8)
+#define GEMINI_LEDS         8
+#define GEMINI_SWITCHES     8
+
+
+/* Flash ROM bit definitions */
+#define GEMINI_FLS_WEN      (1<<0)
+#define GEMINI_FLS_JMP      (1<<6)
+#define GEMINI_FLS_BOOT     (1<<7)
+
+/* Memory bit definitions */
+#define GEMINI_MEM_TYPE_MASK 0xc0
+#define GEMINI_MEM_SIZE_MASK 0x38
+#define GEMINI_MEM_BANK_MASK 0x07
+
+/* L2 cache bit definitions */
+#define GEMINI_L2_SIZE_MASK  0xc0
+#define GEMINI_L2_RATIO_MASK 0x03
+
+/* Timebase register bit definitons */
+#define GEMINI_TIMEB0_EN     (1<<0)
+#define GEMINI_TIMEB1_EN     (1<<1)
+#define GEMINI_TIMEB2_EN     (1<<2)
+#define GEMINI_TIMEB3_EN     (1<<3)
+
+/* CPU status bit definitions */
+#define GEMINI_CPU_ID_MASK   0x03
+#define GEMINI_CPU_COUNT_MASK 0x0c
+#define GEMINI_CPU0_HALTED   (1<<4)
+#define GEMINI_CPU1_HALTED   (1<<5)
+#define GEMINI_CPU2_HALTED   (1<<6)
+#define GEMINI_CPU3_HALTED   (1<<7)
+
+/* Board status bit definitions */
+#define GEMINI_BRD_FAIL      (1<<0)   /* FAIL led is lit */
+#define GEMINI_BRD_BUS_MASK  0x0c     /* PowerPC bus speed */
+
+/* Board family/feature bit descriptions */
+#define GEMINI_FEAT_HAS_FLASH (1<<0)
+#define GEMINI_FEAT_HAS_ETH   (1<<1)
+#define GEMINI_FEAT_HAS_SCSI  (1<<2)
+#define GEMINI_FEAT_HAS_P0    (1<<3)
+#define GEMINI_FEAT_FAM_MASK  0xf0
+
+/* Mod/ECO bit definitions */
+#define GEMINI_ECO_LEVEL_MASK 0x0f
+#define GEMINI_MOD_MASK       0xf0
+
+/* Type/revision bit definitions */
+#define GEMINI_REV_MASK       0x0f
+#define GEMINI_TYPE_MASK      0xf0
+
+/* User switch definitions */
+#define GEMINI_SWITCH_VERBOSE    1     /* adds "debug" to boot cmd line */
+#define GEMINI_SWITCH_SINGLE_USER 7    /* boots into "single-user" mode */
+
+#define SGS_RTC_CONTROL  0
+#define SGS_RTC_SECONDS  1
+#define SGS_RTC_MINUTES  2
+#define SGS_RTC_HOURS    3
+#define SGS_RTC_DAY      4
+#define SGS_RTC_DAY_OF_MONTH 5
+#define SGS_RTC_MONTH    6
+#define SGS_RTC_YEAR     7
+
+#define SGS_RTC_SET  0x80
+#define SGS_RTC_IS_STOPPED 0x80
+
+#define GRACKLE_CONFIG_ADDR_ADDR  (0xfec00000)
+#define GRACKLE_CONFIG_DATA_ADDR  (0xfee00000)
+
+#define GEMINI_BOOT_INIT  (0xfff00100)
+
+#ifndef __ASSEMBLY__
+
+static inline void grackle_write( unsigned long addr, unsigned long data )
+{
+  __asm__ __volatile__(
+  " stwbrx %1, 0, %0\n \
+    sync\n \
+    stwbrx %3, 0, %2\n \
+    sync "
+  : /* no output */
+  : "r" (GRACKLE_CONFIG_ADDR_ADDR), "r" (addr),
+    "r" (GRACKLE_CONFIG_DATA_ADDR), "r" (data));
+}
+
+static inline unsigned long grackle_read( unsigned long addr )
+{
+  unsigned long val;
+
+  __asm__ __volatile__(
+  " stwbrx %1, 0, %2\n \
+    sync\n \
+    lwbrx %0, 0, %3\n \
+    sync "
+  : "=r" (val)
+  : "r" (addr), "r" (GRACKLE_CONFIG_ADDR_ADDR),
+    "r" (GRACKLE_CONFIG_DATA_ADDR));
+
+  return val;
+}
+
+static inline void gemini_led_on( int led )
+{
+  if (led >= 0 && led < GEMINI_LEDS)
+    *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 1;
+}
+
+static inline void gemini_led_off(int led)
+{
+  if (led >= 0 && led < GEMINI_LEDS)
+    *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 0;
+}
+
+static inline int gemini_led_val(int led)
+{
+  int val = 0;
+  if (led >= 0 && led < GEMINI_LEDS)
+    val = *(unsigned char *)(GEMINI_LEDBASE + (led<<3));
+  return (val & 0x1);
+}
+
+/* returns processor id from the board */
+static inline int gemini_processor(void)
+{
+  unsigned char cpu = *(unsigned char *)(GEMINI_CPUSTAT);
+  return (int) ((cpu == 0) ? 4 : (cpu & GEMINI_CPU_ID_MASK));
+}
+
+
+extern void _gemini_reboot(void);
+extern void gemini_prom_init(void);
+extern void gemini_init_l2(void);
+#endif /* __ASSEMBLY__ */
+#endif
diff -urN linux-2.2.14-pre4/include/asm-ppc/gemini_serial.h linux-2.2.14-pre5/include/asm-ppc/gemini_serial.h
--- linux-2.2.14-pre4/include/asm-ppc/gemini_serial.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.14-pre5/include/asm-ppc/gemini_serial.h	2003-08-15 15:08:54.000000000 -0700
@@ -0,0 +1,32 @@
+#ifndef __ASMPPC_GEMINI_SERIAL_H
+#define __ASMPPC_GEMINI_SERIAL_H
+
+#include <asm/gemini.h>
+
+/* Rate for the 24.576 Mhz clock for the onboard serial chip */
+#define BASE_BAUD  (24576000 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define STD_SERIAL_PORT_DEFNS \
+        { 0, BASE_BAUD, GEMINI_SERIAL_A, 15, STD_COM_FLAGS }, /* ttyS0 */ \
+        { 0, BASE_BAUD, GEMINI_SERIAL_B, 14, STD_COM_FLAGS }, /* ttyS1 */ \
+
+#ifdef CONFIG_GEMINI_PU32
+#define PU32_SERIAL_PORT_DEFNS \
+        { 0, BASE_BAUD, NULL, 0, STD_COM_FLAGS },
+#else
+#define PU32_SERIAL_PORT_DEFNS
+#endif
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DEFNS \
+        PU32_SERIAL_PORT_DEFNS
+
+#endif
diff -urN linux-2.2.14-pre4/include/asm-ppc/keyboard.h linux-2.2.14-pre5/include/asm-ppc/keyboard.h
--- linux-2.2.14-pre4/include/asm-ppc/keyboard.h	1999-08-25 17:29:49.000000000 -0700
+++ linux-2.2.14-pre5/include/asm-ppc/keyboard.h	2003-08-15 15:08:54.000000000 -0700
@@ -15,73 +15,68 @@
 
 #ifdef __KERNEL__
 
-#include <linux/ioport.h>
-#include <asm/io.h>
-
 #include <linux/config.h>
-#include <asm/adb.h>
 #include <asm/machdep.h>
-#ifdef CONFIG_APUS
-#include <asm-m68k/keyboard.h>
-#else
+
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
 
 #define KEYBOARD_IRQ			1
 #define DISABLE_KBD_DURING_INTERRUPTS	0
 #define INIT_KBD
 
-#ifdef CONFIG_PREP
-extern int prep_kbd_present;
-#endif /* CONFIG_PREP */
-
 static inline int kbd_setkeycode(unsigned int scancode, unsigned int keycode)
 {
-	return ppc_md.kbd_setkeycode(scancode, keycode);
+	if ( ppc_md.kbd_setkeycode )
+		return ppc_md.kbd_setkeycode(scancode, keycode);
+	else
+		return 0;
 }
   
 static inline int kbd_getkeycode(unsigned int scancode)
 {
-	return ppc_md.kbd_getkeycode(scancode);
+	if ( ppc_md.kbd_getkeycode )
+		return ppc_md.kbd_getkeycode(scancode);
+	else
+		return 0;
 }
   
 static inline int kbd_translate(unsigned char keycode, unsigned char *keycodep,
 				char raw_mode)
 {
-	return ppc_md.kbd_translate(keycode, keycodep, raw_mode);
+	if ( ppc_md.kbd_translate )
+		return ppc_md.kbd_translate(keycode, keycodep, raw_mode);
+	else
+		return 0;
 }
   
 static inline int kbd_unexpected_up(unsigned char keycode)
 {
-	return ppc_md.kbd_unexpected_up(keycode);
+	if ( ppc_md.kbd_unexpected_up )
+		return ppc_md.kbd_unexpected_up(keycode);
+	else
+		return 0;
 }
   
 static inline void kbd_leds(unsigned char leds)
 {
-#ifdef CONFIG_PREP
-	if (prep_kbd_present)
-#endif /* CONFIG_PREP */
+	if ( ppc_md.kbd_leds )
 		ppc_md.kbd_leds(leds);
 }
   
 static inline void kbd_init_hw(void)
 {
-#ifdef CONFIG_PREP
-	if (prep_kbd_present)
-#endif /* CONFIG_PREP */
+	if ( ppc_md.kbd_init_hw )
 		ppc_md.kbd_init_hw();
 }
 
-#define kbd_sysrq_xlate	(ppc_md.kbd_sysrq_xlate)
-
-#ifdef CONFIG_MAC_KEYBOARD
-# define SYSRQ_KEY 0x69
-#else
-# define SYSRQ_KEY 0x54
-#endif
+#define kbd_sysrq_xlate	(ppc_md.ppc_kbd_sysrq_xlate)
 
-#endif /* CONFIG_APUS */
+extern unsigned long SYSRQ_KEY;
 
 /* resource allocation */
-#define kbd_request_region() request_region(0x60, 16, "keyboard")
+#define kbd_request_region()
 #define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
                                              "keyboard", NULL)
 
diff -urN linux-2.2.14-pre4/include/asm-ppc/m48t35.h linux-2.2.14-pre5/include/asm-ppc/m48t35.h
--- linux-2.2.14-pre4/include/asm-ppc/m48t35.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.2.14-pre5/include/asm-ppc/m48t35.h	2003-08-15 15:08:54.000000000 -0700
@@ -0,0 +1,30 @@
+/*
+ *  Registers for the SGS-Thomson M48T35 Timekeeper RAM chip
+ */
+
+#ifndef __PPC_M48T35_H
+#define __PPC_M48T35_H
+
+/* RTC offsets */
+#define M48T35_RTC_CONTROL  0
+#define M48T35_RTC_SECONDS  1
+#define M48T35_RTC_MINUTES  2
+#define M48T35_RTC_HOURS    3
+#define M48T35_RTC_DAY      4
+#define M48T35_RTC_DOM      5
+#define M48T35_RTC_MONTH    6
+#define M48T35_RTC_YEAR     7
+
+#define M48T35_RTC_SET      0x80
+#define M48T35_RTC_STOPPED  0x80
+#define M48T35_RTC_READ     0x40
+
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(x)   ((x)=((x)&15) + ((x)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(x)   ((x)=(((x)/10)<<4) + (x)%10)
+#endif
+
+#endif
diff -urN linux-2.2.14-pre4/include/asm-ppc/processor.h linux-2.2.14-pre5/include/asm-ppc/processor.h
--- linux-2.2.14-pre4/include/asm-ppc/processor.h	1999-08-25 17:29:50.000000000 -0700
+++ linux-2.2.14-pre5/include/asm-ppc/processor.h	2003-08-15 15:08:54.000000000 -0700
@@ -69,6 +69,7 @@
 #define _MACH_rpxlite 64  /* RPCG RPX-Lite 8xx board */
 #define _MACH_bseip   128 /* Bright Star Engineering ip-Engine */
 #define _MACH_yk      256 /* Motorola Yellowknife */
+#define _MACH_gemini  512 /* Synergy Microsystems gemini board */
 
 /* see residual.h for these */
 #define _PREP_Motorola 0x01  /* motorola prep */
diff -urN linux-2.2.14-pre4/include/asm-ppc/serial.h linux-2.2.14-pre5/include/asm-ppc/serial.h
--- linux-2.2.14-pre4/include/asm-ppc/serial.h	1998-08-04 16:06:36.000000000 -0700
+++ linux-2.2.14-pre5/include/asm-ppc/serial.h	2003-08-15 15:08:54.000000000 -0700
@@ -4,7 +4,10 @@
 
 #include <linux/config.h>
 
-#ifdef CONFIG_APUS
+#if defined(CONFIG_GEMINI)
+#include <asm/gemini_serial.h>
+#else
+#if defined(CONFIG_APUS)
 #include <asm-m68k/serial.h>
 #else
 
@@ -119,5 +122,5 @@
 	EXTRA_SERIAL_PORT_DEFNS		\
 	HUB6_SERIAL_PORT_DFNS		\
 	MCA_SERIAL_PORT_DFNS
-
-#endif /* CONFIG_APUS */
+#endif
+#endif
diff -urN linux-2.2.14-pre4/include/linux/dcache.h linux-2.2.14-pre5/include/linux/dcache.h
--- linux-2.2.14-pre4/include/linux/dcache.h	1999-05-08 17:56:37.000000000 -0700
+++ linux-2.2.14-pre5/include/linux/dcache.h	2003-08-15 15:08:54.000000000 -0700
@@ -133,15 +133,14 @@
 
 /* allocate/de-allocate */
 extern struct dentry * d_alloc(struct dentry * parent, const struct qstr *name);
-extern void prune_dcache(int);
+extern int prune_dcache(int, int);
 extern void shrink_dcache_sb(struct super_block *);
 extern void shrink_dcache_parent(struct dentry *);
 extern int d_invalidate(struct dentry *);
 
-#define shrink_dcache() prune_dcache(0)
+#define shrink_dcache() prune_dcache(0, -1)
 
 /* dcache memory management */
-extern int  select_dcache(int, int);
 extern void shrink_dcache_memory(int, unsigned int);
 extern void check_dcache_memory(void);
 extern void free_inode_memory(int);	/* defined in fs/inode.c */
diff -urN linux-2.2.14-pre4/include/linux/msg.h linux-2.2.14-pre5/include/linux/msg.h
--- linux-2.2.14-pre4/include/linux/msg.h	1998-12-27 22:19:28.000000000 -0800
+++ linux-2.2.14-pre5/include/linux/msg.h	2003-08-15 15:08:54.000000000 -0700
@@ -49,6 +49,7 @@
 #define MSGMNI   128   /* <= 1K */     /* max # of msg queue identifiers */
 #define MSGMAX  4056   /* <= 4056 */   /* max size of message (bytes) */
 #define MSGMNB 16384   /* ? */        /* default max size of a message queue */
+#define MSGQNUM 1024   /* <=65535 */	  /* Max messages in flight / queue */
 
 /* unused */
 #define MSGPOOL (MSGMNI*MSGMNB/1024)  /* size in kilobytes of message pool */
diff -urN linux-2.2.14-pre4/ipc/msg.c linux-2.2.14-pre5/ipc/msg.c
--- linux-2.2.14-pre4/ipc/msg.c	1998-11-20 11:43:19.000000000 -0800
+++ linux-2.2.14-pre5/ipc/msg.c	2003-08-15 15:08:54.000000000 -0700
@@ -50,6 +50,7 @@
 	struct ipc_perm *ipcp;
 	struct msg *msgh;
 	long mtype;
+	int err;
 	
 	if (msgsz > MSGMAX || (long) msgsz < 0 || msqid < 0)
 		return -EINVAL;
@@ -70,34 +71,38 @@
 	if (ipcperms(ipcp, S_IWUGO)) 
 		return -EACCES;
 	
-	if (msgsz + msq->msg_cbytes > msq->msg_qbytes) { 
-		if (msgsz + msq->msg_cbytes > msq->msg_qbytes) { 
-			/* still no space in queue */
-			if (msgflg & IPC_NOWAIT)
-				return -EAGAIN;
-			if (signal_pending(current))
-				return -EINTR;
-			interruptible_sleep_on (&msq->wwait);
-			goto slept;
-		}
+	if (msgsz + msq->msg_cbytes > msq->msg_qbytes || msq->msg_qnum>= MSGQNUM) { 
+		/* still no space in queue */
+		if (msgflg & IPC_NOWAIT)
+			return -EAGAIN;
+		if (signal_pending(current))
+			return -EINTR;
+		interruptible_sleep_on (&msq->wwait);
+		goto slept;
 	}
-	
-	/* allocate message header and text space*/ 
+
+	/* Charge first to avoid races */
+	msgbytes  += msgsz;
+	msghdrs++;
+	msq->msg_qnum++;
+	msq->msg_cbytes += msgsz;
+
+	/* allocate message header and text space */ 
+	err = -ENOMEM;
 	msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_KERNEL);
-	if (!msgh)
-		return -ENOMEM;
+	if (!msgh) 
+		goto uncharge;
 	msgh->msg_spot = (char *) (msgh + 1);
 
-	if (copy_from_user(msgh->msg_spot, msgp->mtext, msgsz))
-	{
-		kfree(msgh);
-		return -EFAULT;
+	err = -EFAULT; 
+	if (copy_from_user(msgh->msg_spot, msgp->mtext, msgsz))	{
+		goto uncharge;
 	}
 	
+	err = -EIDRM; 
 	if (msgque[id] == IPC_UNUSED || msgque[id] == IPC_NOID
 		|| msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) {
-		kfree(msgh);
-		return -EIDRM;
+		goto uncharge;
 	}
 
 	msgh->msg_next = NULL;
@@ -111,14 +116,19 @@
 		msq->msg_last->msg_next = msgh;
 		msq->msg_last = msgh;
 	}
-	msq->msg_cbytes += msgsz;
-	msgbytes  += msgsz;
-	msghdrs++;
-	msq->msg_qnum++;
 	msq->msg_lspid = current->pid;
 	msq->msg_stime = CURRENT_TIME;
 	wake_up (&msq->rwait);
 	return 0;
+
+uncharge:
+	msgbytes  -= msgsz;
+	msghdrs--;
+	msq->msg_qnum--;
+	msq->msg_cbytes -= msgsz;
+	if (msgh)
+		kfree(msgh); 
+	return err;
 }
 
 static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg)
diff -urN linux-2.2.14-pre4/net/ipv4/tcp_ipv4.c linux-2.2.14-pre5/net/ipv4/tcp_ipv4.c
--- linux-2.2.14-pre4/net/ipv4/tcp_ipv4.c	2003-08-15 15:08:53.000000000 -0700
+++ linux-2.2.14-pre5/net/ipv4/tcp_ipv4.c	2003-08-15 15:08:54.000000000 -0700
@@ -182,7 +182,7 @@
 
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
 	if (child->num != sk->num) {
-		unsigned short snum = ntohs(child->num);
+		unsigned short snum = child->num;
 		for(tb = tcp_bhash[tcp_bhashfn(snum)];
 		    tb && tb->port != snum;
 		    tb = tb->next)
