## Automatically generated incremental diff
## From:   linux-2.4.4-pre3
## To:     linux-2.4.4-pre4
## Robot:  $Id: make-incremental-diff,v 1.8 2001/12/04 06:05:04 hpa Exp $

diff -urN linux-2.4.4-pre3/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.4-pre3/Documentation/Configure.help	Mon Dec  3 22:35:10 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 22:35:21 2001
@@ -11002,16 +11002,16 @@
 USB device file system
 CONFIG_USB_DEVICEFS
   If you say Y here (and to "/proc file system support" below), you
-  will get a file /proc/usb/devices which lists the devices currently
-  connected to your USB busses, a file /proc/usb/drivers which lists
-  the USB kernel client drivers currently loaded, and for every
-  connected device a file named "/proc/usb/xxx/yyy", where xxx is the
-  bus number and yyy the device number; the latter files can be used
-  by user space programs to talk directly to the device. These files
-  are "virtual", meaning they are generated on the fly and not stored
-  on the hard drive.
+  will get a file /proc/bus/usb/devices which lists the devices
+  currently connected to your USB busses, a file /proc/bus/usb/drivers
+  which lists the USB kernel client drivers currently loaded, and for
+  every connected device a file named "/proc/bus/usb/xxx/yyy", where
+  xxx is the bus number and yyy the device number; the latter files
+  can be used by user space programs to talk directly to the device.
+  These files are "virtual", meaning they are generated on the fly
+  and not stored on the hard drive.
   
-  For the format of the /proc/usb/ files, please read
+  For the format of the /proc/bus/usb/ files, please read
   Documentation/usb/proc_usb_info.txt. 
 
   Please note that this code is completely unrelated to devfs, the
diff -urN linux-2.4.4-pre3/Makefile linux/Makefile
--- linux-2.4.4-pre3/Makefile	Mon Dec  3 22:35:10 2001
+++ linux/Makefile	Mon Dec  3 22:35:21 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 4
-EXTRAVERSION =-pre3
+EXTRAVERSION =-pre4
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.4-pre3/arch/alpha/config.in linux/arch/alpha/config.in
--- linux-2.4.4-pre3/arch/alpha/config.in	Fri Dec 29 14:07:19 2000
+++ linux/arch/alpha/config.in	Mon Dec  3 22:35:21 2001
@@ -5,6 +5,8 @@
 
 define_bool CONFIG_ALPHA y
 define_bool CONFIG_UID16 n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_name "Kernel configuration of Linux for Alpha machines"
 
diff -urN linux-2.4.4-pre3/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- linux-2.4.4-pre3/arch/alpha/kernel/alpha_ksyms.c	Fri Mar  2 11:15:47 2001
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Mon Dec  3 22:35:21 2001
@@ -190,7 +190,6 @@
 EXPORT_SYMBOL(synchronize_irq);
 EXPORT_SYMBOL(flush_tlb_all);
 EXPORT_SYMBOL(flush_tlb_mm);
-EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(flush_tlb_range);
 EXPORT_SYMBOL(smp_imb);
 EXPORT_SYMBOL(cpu_data);
diff -urN linux-2.4.4-pre3/arch/alpha/kernel/semaphore.c linux/arch/alpha/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/alpha/kernel/semaphore.c	Sun Nov 12 19:31:11 2000
+++ linux/arch/alpha/kernel/semaphore.c	Mon Dec  3 22:35:21 2001
@@ -263,185 +263,3 @@
 #endif
 	__up(sem);
 }
-
-
-/*
- * RW Semaphores
- */
-
-void
-__down_read_failed(struct rw_semaphore *sem, int count)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
- retry_down:
-	if (count < 0) {
-		/* Waiting on multiple readers and/or writers.  */
-		
-		/* Undo the acquisition we started in down_read.  */
-		atomic_inc(&sem->count);
-
-		current->state = TASK_UNINTERRUPTIBLE;
-		wmb();
-		add_wait_queue(&sem->wait, &wait);
-		mb();
-		while (atomic_read(&sem->count) < 0) {
-			schedule();
-			set_task_state(current, TASK_UNINTERRUPTIBLE);
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		current->state = TASK_RUNNING;
-
-		mb();
-		count = atomic_dec_return(&sem->count);
-		if (count <= 0)
-			goto retry_down;
-	} else {
-		/* Waiting on exactly one writer.  */
-
-		current->state = TASK_UNINTERRUPTIBLE;
-		wmb();
-		add_wait_queue(&sem->wait, &wait);
-		mb();
-
-		while (!test_and_clear_bit(0, &sem->granted)) {
-			schedule();
-			set_task_state(current, TASK_UNINTERRUPTIBLE);
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		current->state = TASK_RUNNING;
-	}
-}
-
-void
-__down_write_failed(struct rw_semaphore *sem, int count)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
- retry_down:
-	if (count + RW_LOCK_BIAS < 0) {
-		/* Waiting on multiple readers and/or writers.  */
-
-		/* Undo the acquisition we started in down_write.  */
-		atomic_add(RW_LOCK_BIAS, &sem->count);
-
-		current->state = TASK_UNINTERRUPTIBLE;
-		wmb();
-		add_wait_queue_exclusive(&sem->wait, &wait);
-		mb();
-	
-		while (atomic_read(&sem->count) + RW_LOCK_BIAS < 0) {
-			schedule();
-			set_task_state(current, TASK_UNINTERRUPTIBLE);
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		current->state = TASK_RUNNING;
-
-		count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-		if (count != 0)
-			goto retry_down;
-	} else {
-		/* Waiting on exactly one writer.  */
-
-		current->state = TASK_UNINTERRUPTIBLE;
-		wmb();
-		add_wait_queue_exclusive(&sem->wait, &wait);
-		mb();
-
-		while (!test_and_clear_bit(1, &sem->granted)) {
-			schedule();
-			set_task_state(current, TASK_UNINTERRUPTIBLE);
-		}
-
-		remove_wait_queue(&sem->write_bias_wait, &wait);
-		current->state = TASK_RUNNING;
-
-		/* If the lock is currently unbiased, awaken the sleepers.
-		   FIXME: This wakes up the readers early in a bit of a
-		   stampede -> bad!  */
-		count = atomic_read(&sem->count);
-		if (__builtin_expect(count >= 0, 0))
-			wake_up(&sem->wait);
-	}
-}
-
-void
-__rwsem_wake(struct rw_semaphore *sem, int readers)
-{
-	if (readers) {
-		if (test_and_set_bit(0, &sem->granted))
-			BUG();
-		wake_up(&sem->wait);
-	} else {
-		if (test_and_set_bit(1, &sem->granted))
-			BUG();
-		wake_up(&sem->write_bias_wait);
-	}
-}
-
-void
-down_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-	__down_read(sem);
-#if WAITQUEUE_DEBUG
-	if (sem->granted & 2)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_inc(&sem->readers);
-#endif
-}
-
-void
-down_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-	__down_write(sem);
-#if WAITQUEUE_DEBUG
-	if (sem->granted & 3)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	atomic_inc(&sem->writers);
-#endif
-}
-
-void
-up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-	if (sem->granted & 2)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_dec(&sem->readers);
-#endif
-	__up_read(sem);
-}
-
-void
-up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-	if (sem->granted & 3)
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (atomic_read(&sem->writers) != 1)
-		BUG();
-	atomic_dec(&sem->writers);
-#endif
-	__up_write(sem);
-}
diff -urN linux-2.4.4-pre3/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c
--- linux-2.4.4-pre3/arch/alpha/mm/init.c	Tue Nov 28 22:43:39 2000
+++ linux/arch/alpha/mm/init.c	Mon Dec  3 22:35:21 2001
@@ -43,20 +43,6 @@
 struct pgtable_cache_struct quicklists;
 #endif
 
-void
-__bad_pmd(pgd_t *pgd)
-{
-	printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
-	pgd_set(pgd, BAD_PAGETABLE);
-}
-
-void
-__bad_pte(pmd_t *pmd)
-{
-	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
-	pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
-}
-
 pgd_t *
 get_pgd_slow(void)
 {
@@ -80,66 +66,26 @@
 	return ret;
 }
 
-pmd_t *
-get_pmd_slow(pgd_t *pgd, unsigned long offset)
-{
-	pmd_t *pmd;
-
-	pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
-	if (pgd_none(*pgd)) {
-		if (pmd) {
-			clear_page((void *)pmd);
-			pgd_set(pgd, pmd);
-			return pmd + offset;
-		}
-		pgd_set(pgd, BAD_PAGETABLE);
-		return NULL;
-	}
-	free_page((unsigned long)pmd);
-	if (pgd_bad(*pgd)) {
-		__bad_pmd(pgd);
-		return NULL;
-	}
-	return (pmd_t *) pgd_page(*pgd) + offset;
-}
-
-pte_t *
-get_pte_slow(pmd_t *pmd, unsigned long offset)
-{
-	pte_t *pte;
-
-	pte = (pte_t *) __get_free_page(GFP_KERNEL);
-	if (pmd_none(*pmd)) {
-		if (pte) {
-			clear_page((void *)pte);
-			pmd_set(pmd, pte);
-			return pte + offset;
-		}
-		pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
-		return NULL;
-	}
-	free_page((unsigned long)pte);
-	if (pmd_bad(*pmd)) {
-		__bad_pte(pmd);
-		return NULL;
-	}
-	return (pte_t *) pmd_page(*pmd) + offset;
-}
-
 int do_check_pgt_cache(int low, int high)
 {
 	int freed = 0;
-        if(pgtable_cache_size > high) {
-                do {
-                        if(pgd_quicklist)
-                                free_pgd_slow(get_pgd_fast()), freed++;
-                        if(pmd_quicklist)
-                                free_pmd_slow(get_pmd_fast()), freed++;
-                        if(pte_quicklist)
-                                free_pte_slow(get_pte_fast()), freed++;
-                } while(pgtable_cache_size > low);
-        }
-        return freed;
+	if(pgtable_cache_size > high) {
+		do {
+			if(pgd_quicklist) {
+				free_pgd_slow(get_pgd_fast());
+				freed++;
+			}
+			if(pmd_quicklist) {
+				pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
+				freed++;
+			}
+			if(pte_quicklist) {
+				pte_free_slow(pte_alloc_one_fast(NULL, 0));
+				freed++;
+			}
+		} while(pgtable_cache_size > low);
+	}
+	return freed;
 }
 
 /*
diff -urN linux-2.4.4-pre3/arch/arm/config.in linux/arch/arm/config.in
--- linux-2.4.4-pre3/arch/arm/config.in	Mon Dec  3 22:35:10 2001
+++ linux/arch/arm/config.in	Mon Dec  3 22:35:21 2001
@@ -9,6 +9,8 @@
 define_bool CONFIG_SBUS n
 define_bool CONFIG_MCA n
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 
 mainmenu_option next_comment
@@ -44,7 +46,7 @@
 mainmenu_option next_comment
 comment 'Archimedes/A5000 Implementations'
 # These architectures will be combined.  However, until this
-# is complete...  Note that the ARC will take precidence over
+# is complete...  Note that the ARC will take precedence over
 # A5K
 comment 'Archimedes/A5000 Implementations (select only ONE)'
 dep_bool '  Archimedes' CONFIG_ARCH_ARC $CONFIG_ARCH_ARCA5K
diff -urN linux-2.4.4-pre3/arch/arm/kernel/semaphore.c linux/arch/arm/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/arm/kernel/semaphore.c	Sat Nov 11 19:02:40 2000
+++ linux/arch/arm/kernel/semaphore.c	Mon Dec  3 22:35:21 2001
@@ -165,321 +165,3 @@
 	spin_unlock_irqrestore(&semaphore_lock, flags);
 	return 1;
 }
-
-struct rw_semaphore *down_read_failed_biased(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->read_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	return sem;
-}
-
-struct rw_semaphore *down_write_failed_biased(struct rw_semaphore *sem)
-{
-        struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
-
-	for (;;) {
-		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->write_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	/* if the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (atomic_read(&sem->count) >= 0)
-		wake_up(&sem->wait);
-
-	return sem;
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-struct rw_semaphore *down_read_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	/* this takes care of granting the lock */
-	__up_op_read(sem, __rwsem_wake);
-
-	add_wait_queue(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	return sem;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-struct rw_semaphore *down_write_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	/* this takes care of granting the lock */
-	__up_op_write(sem, __rwsem_wake);
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;	/* we must attempt to acquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	return sem;
-}
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-struct rw_semaphore *rwsem_wake_readers(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->read_bias_granted, 1))
-		BUG();
-	wake_up(&sem->wait);
-	return sem;
-}
-
-struct rw_semaphore *rwsem_wake_writer(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->write_bias_granted, 1))
-		BUG();
-	wake_up(&sem->write_bias_wait);
-	return sem;
-}
-
-/*
- * The semaphore operations have a special calling sequence that
- * allow us to do a simpler in-line version of them. These routines
- * need to convert that sequence back into the C sequence when
- * there is contention on the semaphore.
- *
- * ip contains the semaphore pointer on entry. Save the C-clobbered
- * registers (r0 to r3 and lr), but not ip, as we use it as a return
- * value in some cases..
- */
-#ifdef CONFIG_CPU_26
-asm("	.section	.text.lock, \"ax\"
-	.align	5
-	.globl	__down_failed
-__down_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__down
-	ldmfd	sp!, {r0 - r3, pc}^
-
-	.align	5
-	.globl	__down_interruptible_failed
-__down_interruptible_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__down_interruptible
-	mov	ip, r0
-	ldmfd	sp!, {r0 - r3, pc}^
-
-	.align	5
-	.globl	__down_trylock_failed
-__down_trylock_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__down_trylock
-	mov	ip, r0
-	ldmfd	sp!, {r0 - r3, pc}^
-
-	.align	5
-	.globl	__up_wakeup
-__up_wakeup:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__up
-	ldmfd	sp!, {r0 - r3, pc}^
-
-	.align	5
-	.globl	__down_read_failed
-__down_read_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bcc	1f
-1:	bl	down_read_failed_biased
-	ldmfd	sp!, {r0 - r3, pc}^
-2:	bl	down_read_failed
-	mov	r1, pc
-	orr	r2, r1, #
-	teqp r2, #0
-
-	ldr	r3, [r0]
-	subs	r3, r3, #1
-	str	r3, [r0]
-	ldmplfd	sp!, {r0 - r3, pc}^
-  orrcs r1, r1, #0x20000000   @ Set carry
-  teqp r1, #0
-	bcc	2b
-	b	1b
-
-	.align	5
-	.globl	__down_write_failed
-__down_write_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bcc	1f
-1:	bl	down_write_failed_biased
-	ldmfd	sp!, {r0 - r3, pc}^
-2:	bl	down_write_failed
-	mov r1, pc
-	orr	r2, r1, #128
-	teqp r2, #0
-
-	ldr	r3, [r0]
-	subs	r3, r3, #"RW_LOCK_BIAS_STR"
-	str	r3, [r0]
-	ldmeqfd	sp!, {r0 - r3, pc}^
-  orrcs r1, r1, #0x20000000   @ Set carry
-	teqp r1, #0
-	bcc	2b
-	b	1b
-
-	.align	5
-	.globl	__rwsem_wake
-__rwsem_wake:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	beq	1f
-	bl	rwsem_wake_readers
-	ldmfd	sp!, {r0 - r3, pc}^
-1:	bl	rwsem_wake_writer
-	ldmfd	sp!, {r0 - r3, pc}^
-
-	.previous
-	");
-
-#else
-/* 32 bit version */
-asm("	.section	.text.lock, \"ax\"
-	.align	5
-	.globl	__down_failed
-__down_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__down
-	ldmfd	sp!, {r0 - r3, pc}
-
-	.align	5
-	.globl	__down_interruptible_failed
-__down_interruptible_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__down_interruptible
-	mov	ip, r0
-	ldmfd	sp!, {r0 - r3, pc}
-
-	.align	5
-	.globl	__down_trylock_failed
-__down_trylock_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__down_trylock
-	mov	ip, r0
-	ldmfd	sp!, {r0 - r3, pc}
-
-	.align	5
-	.globl	__up_wakeup
-__up_wakeup:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bl	__up
-	ldmfd	sp!, {r0 - r3, pc}
-
-	.align	5
-	.globl	__down_read_failed
-__down_read_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bcc	1f
-1:	bl	down_read_failed_biased
-	ldmfd	sp!, {r0 - r3, pc}
-2:	bl	down_read_failed
-	mrs	r1, cpsr
-	orr	r2, r1, #128
-	msr	cpsr_c, r2
-	ldr	r3, [r0]
-	subs	r3, r3, #1
-	str	r3, [r0]
-	msr	cpsr_c, r1
-	ldmplfd	sp!, {r0 - r3, pc}
-	bcc	2b
-	b	1b
-
-	.align	5
-	.globl	__down_write_failed
-__down_write_failed:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	bcc	1f
-1:	bl	down_write_failed_biased
-	ldmfd	sp!, {r0 - r3, pc}
-2:	bl	down_write_failed
-	mrs	r1, cpsr
-	orr	r2, r1, #128
-	msr	cpsr_c, r2
-	ldr	r3, [r0]
-	subs	r3, r3, #"RW_LOCK_BIAS_STR"
-	str	r3, [r0]
-	msr	cpsr_c, r1
-	ldmeqfd	sp!, {r0 - r3, pc}
-	bcc	2b
-	b	1b
-
-	.align	5
-	.globl	__rwsem_wake
-__rwsem_wake:
-	stmfd	sp!, {r0 - r3, lr}
-	mov	r0, ip
-	beq	1f
-	bl	rwsem_wake_readers
-	ldmfd	sp!, {r0 - r3, pc}
-1:	bl	rwsem_wake_writer
-	ldmfd	sp!, {r0 - r3, pc}
-
-	.previous
-	");
-
-#endif
diff -urN linux-2.4.4-pre3/arch/cris/config.in linux/arch/cris/config.in
--- linux-2.4.4-pre3/arch/cris/config.in	Mon Dec  3 22:35:10 2001
+++ linux/arch/cris/config.in	Mon Dec  3 22:35:21 2001
@@ -5,6 +5,8 @@
 mainmenu_name "Linux/CRIS Kernel Configuration"
 
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_option next_comment
 comment 'Code maturity level options'
diff -urN linux-2.4.4-pre3/arch/cris/kernel/semaphore.c linux/arch/cris/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/cris/kernel/semaphore.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/cris/kernel/semaphore.c	Mon Dec  3 22:35:21 2001
@@ -127,112 +127,3 @@
 {
 	return waking_non_zero_trylock(sem);
 }
-
-/*
- * RW Semaphores
- */
-void
-__down_read(struct rw_semaphore *sem, int count)
-{
-	DOWN_VAR;
-
- retry_down:
-	if (count < 0) {
-		/* Wait for the lock to become unbiased.  Readers
-		   are non-exclusive.  */
-		
-		/* This takes care of granting the lock.  */
-		up_read(sem);
-
-		add_wait_queue(&sem->wait, &wait);
-		while (atomic_read(&sem->count) < 0) {
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if (atomic_read(&sem->count) >= 0)
-				break;
-			schedule();
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		tsk->state = TASK_RUNNING;
-
-		mb();
-		count = atomic_dec_return(&sem->count);
-		if (count <= 0)
-			goto retry_down;
-	} else {
-		add_wait_queue(&sem->wait, &wait);
-
-		while (1) {
-			if (test_and_clear_bit(0, &sem->granted))
-				break;
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if ((sem->granted & 1) == 0)
-				schedule();
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		tsk->state = TASK_RUNNING;
-	}
-}
-
-void
-__down_write(struct rw_semaphore *sem, int count)
-{
-	DOWN_VAR;
-
- retry_down:
-	if (count + RW_LOCK_BIAS < 0) {
-		up_write(sem);
-
-		add_wait_queue_exclusive(&sem->wait, &wait);
-	
-		while (atomic_read(&sem->count) < 0) {
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if (atomic_read(&sem->count) >= RW_LOCK_BIAS)
-				break;
-			schedule();
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		tsk->state = TASK_RUNNING;
-
-		mb();
-		count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-		if (count != 0)
-			goto retry_down;
-	} else {
-		/* Put ourselves at the end of the list.  */
-		add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
-
-		while (1) {
-			if (test_and_clear_bit(1, &sem->granted))
-				break;
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if ((sem->granted & 2) == 0)
-				schedule();
-		}
-
-		remove_wait_queue(&sem->write_bias_wait, &wait);
-		tsk->state = TASK_RUNNING;
-
-		/* If the lock is currently unbiased, awaken the sleepers.
-		   FIXME: This wakes up the readers early in a bit of a
-		   stampede -> bad!  */
-		if (atomic_read(&sem->count) >= 0)
-			wake_up(&sem->wait);
-	}
-}
-
-void
-__rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
-{
-	if (readers) {
-		if (test_and_set_bit(0, &sem->granted))
-			BUG();
-		wake_up(&sem->wait);
-	} else {
-		if (test_and_set_bit(1, &sem->granted))
-			BUG();
-		wake_up(&sem->write_bias_wait);
-	}
-}
diff -urN linux-2.4.4-pre3/arch/i386/config.in linux/arch/i386/config.in
--- linux-2.4.4-pre3/arch/i386/config.in	Mon Dec  3 22:35:10 2001
+++ linux/arch/i386/config.in	Mon Dec  3 22:35:21 2001
@@ -9,6 +9,8 @@
 define_bool CONFIG_SBUS n
 
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
 
 mainmenu_option next_comment
 comment 'Code maturity level options'
diff -urN linux-2.4.4-pre3/arch/i386/lib/usercopy.c linux/arch/i386/lib/usercopy.c
--- linux-2.4.4-pre3/arch/i386/lib/usercopy.c	Fri Nov 12 04:29:47 1999
+++ linux/arch/i386/lib/usercopy.c	Mon Dec  3 22:35:21 2001
@@ -34,6 +34,8 @@
 		else
 			mmx_copy_user_zeroing(to, from, n);
 	}
+	else
+		memset(to, 0, n);
 	return n;
 }
 
@@ -52,6 +54,8 @@
 {
 	if (access_ok(VERIFY_READ, from, n))
 		__copy_user_zeroing(to,from,n);
+	else
+		memset(to, 0, n);
 	return n;
 }
 
diff -urN linux-2.4.4-pre3/arch/ia64/config.in linux/arch/ia64/config.in
--- linux-2.4.4-pre3/arch/ia64/config.in	Mon Dec  3 22:35:11 2001
+++ linux/arch/ia64/config.in	Mon Dec  3 22:35:21 2001
@@ -23,6 +23,8 @@
 define_bool CONFIG_EISA n
 define_bool CONFIG_MCA n
 define_bool CONFIG_SBUS n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 choice 'IA-64 processor type' \
 	"Itanium			CONFIG_ITANIUM \
diff -urN linux-2.4.4-pre3/arch/ia64/kernel/semaphore.c linux/arch/ia64/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/ia64/kernel/semaphore.c	Sat Nov 11 19:02:40 2000
+++ linux/arch/ia64/kernel/semaphore.c	Mon Dec  3 22:35:21 2001
@@ -155,180 +155,3 @@
 	spin_unlock_irqrestore(&semaphore_lock, flags);
 	return 1;
 }
-
-/*
- * Helper routines for rw semaphores.  These could be optimized some
- * more, but since they're off the critical path, I prefer clarity for
- * now...
- */
-
-/*
- * This gets called if we failed to acquire the lock, but we're biased
- * to acquire the lock by virtue of causing the count to change from 0
- * to -1.  Being biased, we sleep and attempt to grab the lock until
- * we succeed.  When this function returns, we own the lock.
- */
-static inline void
-down_read_failed_biased (struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->read_bias_granted)
-			schedule();
-	}
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-/*
- * This gets called if we failed to acquire the lock and we are not
- * biased to acquire the lock.  We undo the decrement that was
- * done earlier, go to sleep, and then attempt to re-acquire the
- * lock afterwards.
- */
-static inline void
-down_read_failed (struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	/*
-	 * Undo the decrement we did in down_read() and check if we
-	 * need to wake up someone.
-	 */
-	__up_read(sem);
-
-	add_wait_queue(&sem->wait, &wait);
-	while (sem->count < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (sem->count >= 0)
-			break;
-		schedule();
-	}
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-/*
- * Wait for the lock to become unbiased.  Readers are non-exclusive.
- */
-void
-__down_read_failed (struct rw_semaphore *sem, long count)
-{
-	while (1) {
-		if (count == -1) {
-			down_read_failed_biased(sem);
-			return;
-		}
-		/* unbiased */
-		down_read_failed(sem);
-
-		count = ia64_fetch_and_add(-1, &sem->count);
-		if (count >= 0)
-			return;
-	}
-}
-
-static inline void
-down_write_failed_biased (struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	/* put ourselves at the end of the list */
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
-
-	for (;;) {
-		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->write_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	/*
-	 * If the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (sem->count >= 0)
-		wake_up(&sem->wait);
-}
-
-
-static inline void
-down_write_failed (struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	__up_write(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (sem->count < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (sem->count >= 0)
-			break;	/* we must attempt to acquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-
-/*
- * Wait for the lock to become unbiased.  Since we're a writer, we'll
- * make ourselves exclusive.
- */
-void
-__down_write_failed (struct rw_semaphore *sem, long count)
-{
-	long old_count;
-
-	while (1) {
-		if (count == -RW_LOCK_BIAS) {
-			down_write_failed_biased(sem);
-			return;
-		}
-		down_write_failed(sem);
-
-		do {
-			old_count = sem->count;
-			count = old_count - RW_LOCK_BIAS;
-		} while (cmpxchg_acq(&sem->count, old_count, count) != old_count);
-
-		if (count == 0)
-			return;
-	}
-}
-
-void
-__rwsem_wake (struct rw_semaphore *sem, long count)
-{
-	wait_queue_head_t *wq;
-
-	if (count == 0) {
-		/* wake a writer */
-		if (xchg(&sem->write_bias_granted, 1))
-			BUG();
-		wq = &sem->write_bias_wait;
-	} else {
-		/* wake reader(s) */
-		if (xchg(&sem->read_bias_granted, 1))
-			BUG();
-		wq = &sem->wait;
-	}
-	wake_up(wq);	/* wake up everyone on the wait queue */
-}
diff -urN linux-2.4.4-pre3/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c
--- linux-2.4.4-pre3/arch/m68k/amiga/config.c	Thu Jan  4 13:00:55 2001
+++ linux/arch/m68k/amiga/config.c	Mon Dec  3 22:35:21 2001
@@ -769,20 +769,6 @@
     return 0;
 }
 
-void dbprintf(const char *fmt , ...)
-{
-	static char buf[1024];
-	va_list args;
-	extern void console_print (const char *str);
-	extern int vsprintf(char * buf, const char * fmt, va_list args);
-
-	va_start(args, fmt);
-	vsprintf(buf, fmt, args);
-	va_end(args);
-
-	console_print (buf);
-}
-
 static NORET_TYPE void amiga_reset( void )
     ATTRIB_NORET;
 
diff -urN linux-2.4.4-pre3/arch/m68k/config.in linux/arch/m68k/config.in
--- linux-2.4.4-pre3/arch/m68k/config.in	Mon Dec  3 22:35:11 2001
+++ linux/arch/m68k/config.in	Mon Dec  3 22:35:21 2001
@@ -4,6 +4,8 @@
 #
 
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_name "Linux/68k Kernel Configuration"
 
diff -urN linux-2.4.4-pre3/arch/m68k/kernel/semaphore.c linux/arch/m68k/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/m68k/kernel/semaphore.c	Fri Dec 29 14:07:20 2000
+++ linux/arch/m68k/kernel/semaphore.c	Mon Dec  3 22:35:22 2001
@@ -130,111 +130,3 @@
 {
 	return waking_non_zero_trylock(sem);
 }
-
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	__up_read(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(current, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	current->state = TASK_RUNNING;
-}
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-			break;
-		set_task_state(current, TASK_UNINTERRUPTIBLE);
-                if (!sem->read_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	current->state = TASK_RUNNING;
-}
-
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	__up_write(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(current, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;	/* we must attempt to acquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	current->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait);	/* put ourselves at the end of the list */
-
-	for (;;) {
-		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-			break;
-		set_task_state(current, TASK_UNINTERRUPTIBLE);
-		if (!sem->write_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	current->state = TASK_RUNNING;
-
-	/* if the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (atomic_read(&sem->count) >= 0)
-		wake_up(&sem->wait);
-}
-
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-void rwsem_wake_readers(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->read_bias_granted, 1))
-		BUG();
-	wake_up(&sem->wait);
-}
-
-void rwsem_wake_writer(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->write_bias_granted, 1))
-		BUG();
-	wake_up(&sem->write_bias_wait);
-}
diff -urN linux-2.4.4-pre3/arch/m68k/kernel/setup.c linux/arch/m68k/kernel/setup.c
--- linux-2.4.4-pre3/arch/m68k/kernel/setup.c	Thu Jan  4 13:00:55 2001
+++ linux/arch/m68k/kernel/setup.c	Mon Dec  3 22:35:22 2001
@@ -39,10 +39,6 @@
 #include <linux/blk.h>
 #endif
 
-#ifndef CONFIG_AMIGA
-#define dbprintf	printk
-#endif
-
 unsigned long m68k_machtype;
 unsigned long m68k_cputype;
 unsigned long m68k_fputype;
diff -urN linux-2.4.4-pre3/arch/mips/Makefile linux/arch/mips/Makefile
--- linux-2.4.4-pre3/arch/mips/Makefile	Thu Jul 27 18:36:54 2000
+++ linux/arch/mips/Makefile	Mon Dec  3 22:35:22 2001
@@ -17,8 +17,10 @@
 #
 ifdef CONFIG_CPU_LITTLE_ENDIAN
 tool-prefix	= mipsel-linux-
+output-format	= elf32-littlemips
 else
 tool-prefix	= mips-linux-
+output-format	= elf32-bigmips
 endif
 
 ifdef CONFIG_CROSSCOMPILE
@@ -26,16 +28,16 @@
 endif
 
 #
-# The ELF GCC uses -G0 -mabicalls -fpic as default.  We don't need PIC
-# code in the kernel since it only slows down the whole thing.  For the
-# old GCC these options are just the defaults.  At some point we might
-# make use of global pointer optimizations.
+# GCC uses -G0 -mabicalls -fpic as default.  We don't want PIC in the kernel
+# code since it only slows down the whole thing.  At some point we might make
+# use of global pointer optimizations but their use of $28 conflicts with
+# the current pointer optimization.
 #
 # The DECStation requires an ECOFF kernel for remote booting, other MIPS
 # machines may also.  Since BFD is incredibly buggy with respect to
 # crossformat linking we rely on the elf2ecoff tool for format conversion.
 #
-CFLAGS		+= -G 0 -mno-abicalls -fno-pic
+GCCFLAGS	:= -G 0 -mno-abicalls -fno-pic
 LINKFLAGS	+= -static -G 0
 MODFLAGS	+= -mlong-calls
 
@@ -47,37 +49,63 @@
 # CPU-dependent compiler/assembler options for optimization.
 #
 ifdef CONFIG_CPU_R3000
-CFLAGS		:= $(CFLAGS) -mcpu=r3000 -mips1
+GCCFLAGS	+= -mcpu=r3000 -mips1
+endif
+ifdef CONFIG_CPU_R3912
+GCCFLAGS	+= -mcpu=r3000 -mips1
 endif
 ifdef CONFIG_CPU_R6000
-CFLAGS		:= $(CFLAGS) -mcpu=r6000 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r6000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R4300
-CFLAGS		:= $(CFLAGS) -mcpu=r4300 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r4300 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R4X00
-CFLAGS		:= $(CFLAGS) -mcpu=r4600 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
+endif
+ifdef CONFIG_CPU_MIPS32
+GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R5000
-CFLAGS		:= $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
+endif
+ifdef CONFIG_CPU_R5432
+GCCFLAGS        += -mcpu=r8000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_NEVADA
-CFLAGS		:= $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap -mmad
+GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap -mmad
+endif
+ifdef CONFIG_CPU_RM7000
+GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R8000
-CFLAGS		:= $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R10000
-CFLAGS		:= $(CFLAGS) -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
 endif
 
+ifdef CONFIG_MIPS_FPU_EMULATOR
+CORE_FILES	+=arch/mips/math-emu/fpu_emulator.o
+SUBDIRS		+=arch/mips/math-emu
+endif
+
+#
+# The pipe options is bad for my low-mem machine
+# Uncomment this if you want this.
+#
+GCCFLAGS	+= -pipe
+
+CFLAGS		:= -I $(TOPDIR)/include/asm/gcc $(CFLAGS) $(GCCFLAGS)
+AFLAGS		+= $(GCCFLAGS)
+
 #
 # Board-dependent options and extra files
 #
 ifdef CONFIG_ALGOR_P4032
 CORE_FILES    += arch/mips/algor/algor.o
 SUBDIRS       += arch/mips/algor
-#LOADADDR      += 0x80000000
+LOADADDR      += 0x80000000
 endif
 
 #
@@ -90,6 +118,18 @@
 LOADADDR      += 0x80040000
 endif
 
+ifdef CONFIG_MIPS_ATLAS
+LIBS          += arch/mips/mips-boards/atlas/atlas.o arch/mips/mips-boards/generic/mipsboards.o
+SUBDIRS       += arch/mips/mips-boards/generic arch/mips/mips-boards/atlas
+LOADADDR      += 0x80100000
+endif
+
+ifdef CONFIG_MIPS_MALTA
+LIBS          += arch/mips/mips-boards/malta/malta.o arch/mips/mips-boards/generic/mipsboards.o
+SUBDIRS       += arch/mips/mips-boards/malta arch/mips/mips-boards/generic
+LOADADDR      += 0x80100000
+endif
+
 #
 # Acer PICA 61, Mips Magnum 4000 and Olivetti M700.
 #
@@ -100,12 +140,6 @@
 LOADADDR      += 0x80080000
 endif
 
-ifdef CONFIG_COBALT_MICRO_SERVER
-ARCHIVES      += arch/mips/cobalt/cobalt.o
-SUBDIRS       += arch/mips/cobalt
-LOADADDR      += 0x80000000
-endif
-
 ifdef CONFIG_SNI_RM200_PCI
 CORE_FILES    += arch/mips/sni/sni.o
 SUBDIRS       += arch/mips/sni arch/mips/arc
@@ -114,7 +148,8 @@
 endif
 
 ifdef CONFIG_SGI_IP22
-LIBS          += arch/mips/sgi/kernel/sgikern.a arch/mips/arc/arclib.a
+CORE_FILES    += arch/mips/sgi/kernel/ip22-kern.o
+LIBS          += arch/mips/arc/arclib.a
 SUBDIRS       += arch/mips/sgi/kernel arch/mips/arc
 #
 # Set LOADADDR to >= 0x88069000 if you want to leave space for symmon,
@@ -152,28 +187,74 @@
 endif
 
 #
-# Choosing incompatible machines durings configuration will result in
-# error messages during linking.  Select a default linkscript if
-# none has been choosen above.
 #
-ifndef LINKSCRIPT
-ifndef CONFIG_CPU_LITTLE_ENDIAN
-LINKSCRIPT    = arch/mips/ld.script.big
-else
-LINKSCRIPT    = arch/mips/ld.script.little
+# NEC DDB Vrc-5476
+#
+ifdef CONFIG_DDB5476
+SUBDIRS       += arch/mips/ddb5476
+LIBS          += arch/mips/ddb5476/ddb5476.a
+LOADADDR      += 0x80080000
 endif
+
+#
+# Galileo EV64120 Board
+#
+ifdef CONFIG_MIPS_EV64120
+LIBS          += arch/mips/galileo-boards/ev64120/ev64120.o
+SUBDIRS       += arch/mips/galileo-boards/ev64120
+LOADADDR      += 0x80100000
 endif
-LINKFLAGS     += -T $(word 1,$(LINKSCRIPT))
 
-ifdef LOADADDR
-LINKFLAGS     += -Ttext $(word 1,$(LOADADDR))
+#
+# Galileo EV96100 Board
+#
+ifdef CONFIG_MIPS_EV96100
+LIBS          += arch/mips/galileo-boards/ev96100/ev96100.o arch/mips/galileo-boards/generic/galboards.o
+SUBDIRS       += arch/mips/galileo-boards/generic arch/mips/galileo-boards/ev96100
+LOADADDR      += 0x80100000
 endif
 
 #
-# The pipe options is bad for my low-mem machine
-# Uncomment this if you want this.
+# Momentum Ocelot board
+#
+ifdef CONFIG_MOMENCO_OCELOT
+LIBS          += arch/mips/gt64120/common/gt64120.o arch/mips/gt64120/momenco_ocelot/momenco_ocelot.o
+SUBDIRS       += arch/mips/gt64120/common arch/mips/gt64120/momenco_ocelot
+LOADADDR      += 0x80100000
+endif
+
 #
-CFLAGS		+= -pipe
+# Philips Nino
+#
+ifdef CONFIG_NINO
+CORE_FILES    += arch/mips/philips/nino/nino.o \
+		 arch/mips/philips/drivers/drivers.o
+SUBDIRS       += arch/mips/philips/nino arch/mips/philips/drivers
+LOADADDR      += 0x80000000
+endif
+
+#
+# ITE 8172 eval board with QED 5231 CPU
+#
+ifdef CONFIG_MIPS_ITE8172
+LIBS		+= arch/mips/ite-boards/qed-4n-s01b/ite.o		     \
+		   arch/mips/ite-boards/generic/it8172.o
+SUBDIRS		+= arch/mips/ite-boards/generic				     \
+		   arch/mips/ite-boards/qed-4n-s01b
+LOADADDR	+= 0x80100000
+endif
+
+#
+# Choosing incompatible machines durings configuration will result in
+# error messages during linking.  Select a default linkscript if
+# none has been choosen above.
+#
+vmlinux: arch/$(ARCH)/ld.script
+
+arch/$(ARCH)/ld.script: arch/$(ARCH)/ld.script.in arch/$(ARCH)/Makefile
+	sed -e 's/@@OUTPUT_FORMAT@@/$(output-format)/' \
+	    -e 's/@@LOADADDR@@/$(LOADADDR)/' <$< >$@
+LINKFLAGS	+= -T arch/$(ARCH)/ld.script
 
 HEAD := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
 
@@ -197,8 +278,18 @@
 	$(ORIONBOOT) orionboot
 endif
 
+ifdef CONFIG_MIPS_EV64120
+GALILEOBOOT = $(MAKE) -C arch/$(ARCH)/galileo-boards/ev64120
+
+gboot: vmlinux
+	$(MAKE) -C arch/$(ARCH)/galileo-boards/ev64120/compressed 
+endif
+
 MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 
+vmlinux.ecoff: vmlinux
+	@$(MAKEBOOT) $@
+
 zImage: vmlinux
 	@$(MAKEBOOT) zImage
 
@@ -209,7 +300,7 @@
 
 archclean:
 	@$(MAKEBOOT) clean
-	$(MAKE) -C arch/$(ARCH)/kernel clean
+	rm -f arch/$(ARCH)/ld.script
 	$(MAKE) -C arch/$(ARCH)/tools clean
 	$(MAKE) -C arch/mips/baget clean
 
diff -urN linux-2.4.4-pre3/arch/mips/arc/Makefile linux/arch/mips/arc/Makefile
--- linux-2.4.4-pre3/arch/mips/arc/Makefile	Sat May 13 08:29:14 2000
+++ linux/arch/mips/arc/Makefile	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
 #
 # Makefile for the SGI arcs prom monitor library routines
 # under Linux.
@@ -10,7 +9,10 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 L_TARGET = arclib.a
-L_OBJS  = console.o init.o printf.o memory.o tree.o env.o cmdline.o misc.o \
-	  time.o file.o identify.o
+
+obj-y		+= console.o init.o memory.o tree.o env.o cmdline.o misc.o \
+		   time.o file.o identify.o
+
+obj-$(CONFIG_ARC_CONSOLE)   += arc_con.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/arc/arc_con.c linux/arch/mips/arc/arc_con.c
--- linux-2.4.4-pre3/arch/mips/arc/arc_con.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/arc/arc_con.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,69 @@
+/*
+ * Wrap-around code for a console using the
+ * ARC io-routines.
+ *
+ * Copyright (c) 1998 Harald Koerfgen 
+ */
+
+#include <linux/tty.h>
+#include <linux/major.h>
+#include <linux/ptrace.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/fs.h>
+
+extern char prom_getchar (void);
+extern void prom_printf (char *, ...);
+
+static void prom_console_write(struct console *co, const char *s,
+			       unsigned count)
+{
+	unsigned i;
+
+	/*
+	 *    Now, do each character
+	 */
+	for (i = 0; i < count; i++) {
+		if (*s == 10)
+			prom_printf("%c", 13);
+		prom_printf("%c", *s++);
+	}
+}
+
+static int prom_console_wait_key(struct console *co)
+{
+	return prom_getchar();
+}
+
+static int __init prom_console_setup(struct console *co, char *options)
+{
+	return 0;
+}
+
+static kdev_t prom_console_device(struct console *c)
+{
+	return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static struct console arc_cons = {
+	"ttyS",
+	prom_console_write,
+	NULL,
+	prom_console_device,
+	prom_console_wait_key,
+	NULL,
+	prom_console_setup,
+	CON_PRINTBUFFER,
+	-1,
+	0,
+	NULL
+};
+
+/*
+ *    Register console.
+ */
+
+void __init arc_console_init(void)
+{
+	register_console(&arc_cons);
+}
diff -urN linux-2.4.4-pre3/arch/mips/arc/cmdline.c linux/arch/mips/arc/cmdline.c
--- linux-2.4.4-pre3/arch/mips/arc/cmdline.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/arc/cmdline.c	Mon Dec  3 22:35:22 2001
@@ -2,8 +2,6 @@
  * cmdline.c: Kernel command line creation using ARCS argc/argv.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: cmdline.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -12,9 +10,9 @@
 #include <asm/sgialib.h>
 #include <asm/bootinfo.h>
 
-/* #define DEBUG_CMDLINE */
+#undef DEBUG_CMDLINE
 
-char arcs_cmdline[CL_SIZE];
+char arcs_cmdline[COMMAND_LINE_SIZE];
 
 char * __init prom_getcmdline(void)
 {
diff -urN linux-2.4.4-pre3/arch/mips/arc/console.c linux/arch/mips/arc/console.c
--- linux-2.4.4-pre3/arch/mips/arc/console.c	Mon Feb 28 07:18:20 2000
+++ linux/arch/mips/arc/console.c	Mon Dec  3 22:35:22 2001
@@ -1,50 +1,99 @@
 /*
- * console.c: SGI arcs console code.
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  *
  * Copyright (C) 1996 David S. Miller (dm@sgi.com)
  * Compability with board caches, Ulf Carlsson
- *
- * $Id: console.c,v 1.3 1999/10/09 00:00:57 ralf Exp $
  */
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <asm/sgialib.h>
 #include <asm/bcache.h>
+#include <linux/console.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+
+#ifdef CONFIG_ARC_CONSOLE
+#define __init
+#endif
 
-/* The romvec is not compatible with board caches.  Thus we disable it during
- * romvec action.  Since r4xx0.c is always compiled and linked with your kernel,
- * this shouldn't cause any harm regardless what MIPS processor you have.
+/*
+ * IP22 boardcache is not compatible with board caches.  Thus we disable it
+ * during romvec action.  Since r4xx0.c is always compiled and linked with your
+ * kernel, this shouldn't cause any harm regardless what MIPS processor you
+ * have.
  *
- * The romvec write and read functions seem to interfere with the serial lines
+ * The ARC write and read functions seem to interfere with the serial lines
  * in some way. You should be careful with them.
  */
-extern struct bcache_ops *bcops;
 
-#ifdef CONFIG_SGI_PROM_CONSOLE
-void prom_putchar(char c)
-#else
 void __init prom_putchar(char c)
-#endif
 {
 	long cnt;
 	char it = c;
 
-	bcops->bc_disable();
+	bc_disable();
 	romvec->write(1, &it, 1, &cnt);
-	bcops->bc_enable();
+	bc_enable();
 }
 
-#ifdef CONFIG_SGI_PROM_CONSOLE
-char prom_getchar(void)
-#else
 char __init prom_getchar(void)
-#endif
 {
 	long cnt;
 	char c;
 
-	bcops->bc_disable();
+	bc_disable();
 	romvec->read(0, &c, 1, &cnt);
-	bcops->bc_enable();
+	bc_enable();
+
 	return c;
+}
+
+static char ppbuf[1024];
+
+void __init prom_printf(char *fmt, ...)
+{
+	va_list args;
+	char ch, *bptr;
+	int i;
+
+	va_start(args, fmt);
+	i = vsprintf(ppbuf, fmt, args);
+
+	bptr = ppbuf;
+
+	while ((ch = *(bptr++)) != 0) {
+		if (ch == '\n')
+			prom_putchar('\r');
+
+		prom_putchar(ch);
+	}
+	va_end(args);
+}
+
+static void
+arc_console_write(struct console *con, const char *s, unsigned n)
+{
+	prom_printf("%s", s);
+}
+
+static kdev_t 
+arc_console_dev(struct console *c)
+{
+	return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static struct console arc_prom_console = {
+    name:	"prom",
+    write:	arc_console_write,
+    device:	arc_console_dev,
+    flags:	CON_PRINTBUFFER,
+    index:	-1,
+};
+
+__init void arc_setup_console(void)
+{
+	register_console(&arc_prom_console);
 }
diff -urN linux-2.4.4-pre3/arch/mips/arc/identify.c linux/arch/mips/arc/identify.c
--- linux-2.4.4-pre3/arch/mips/arc/identify.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/arc/identify.c	Mon Dec  3 22:35:22 2001
@@ -6,8 +6,6 @@
  * This code is based on arch/mips/sgi/kernel/system.c, which is
  * 
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: identify.c,v 1.2 1999/02/25 21:04:13 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -19,50 +17,51 @@
 #include <asm/bootinfo.h>
 
 struct smatch {
-    char *name;
-    int group;
-    int type;
-    int flags;
+	char *name;
+	int group;
+	int type;
+	int flags;
 };
 
 static struct smatch mach_table[] = {
-    { "SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS },
-    { "Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0 },
-    { "PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0 },
-    { "RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0 }
+	{"SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS},
+	{"Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0},
+	{"PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0},
+	{"RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0}
 };
 
 int prom_flags;
 
-static struct smatch * __init string_to_mach(char *s)
+static struct smatch *__init string_to_mach(char *s)
 {
-    int i;
-    
-    for (i = 0; i < sizeof (mach_table); i++) {
-	if(!strcmp(s, mach_table[i].name))
-	    return &mach_table[i];
-    }
-    prom_printf("\nYeee, could not determine architecture type <%s>\n", s);
-    prom_printf("press a key to reboot\n");
-    prom_getchar();
-    romvec->imode();
-    return NULL;
+	int i;
+
+	for (i = 0; i < sizeof(mach_table); i++) {
+		if (!strcmp(s, mach_table[i].name))
+			return &mach_table[i];
+	}
+	prom_printf("\nYeee, could not determine architecture type <%s>\n",
+		    s);
+	prom_printf("press a key to reboot\n");
+	prom_getchar();
+	romvec->imode();
+	return NULL;
 }
 
 void __init prom_identify_arch(void)
 {
-    pcomponent *p;
-    struct smatch *mach;
-    
-    /* The root component tells us what machine architecture we
-     * have here.
-     */
-    p = prom_getchild(PROM_NULL_COMPONENT);
-    printk("ARCH: %s\n", p->iname);
-    mach = string_to_mach(p->iname);
-
-    mips_machgroup = mach->group;
-    mips_machtype = mach->type;
-    prom_flags = mach->flags;
-}
+	pcomponent *p;
+	struct smatch *mach;
 
+	/*
+	 * The root component tells us what machine architecture we
+	 * have here.
+	 */
+	p = prom_getchild(PROM_NULL_COMPONENT);
+	printk("ARCH: %s\n", p->iname);
+	mach = string_to_mach(p->iname);
+
+	mips_machgroup = mach->group;
+	mips_machtype = mach->type;
+	prom_flags = mach->flags;
+}
diff -urN linux-2.4.4-pre3/arch/mips/arc/init.c linux/arch/mips/arc/init.c
--- linux-2.4.4-pre3/arch/mips/arc/init.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/arc/init.c	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.5 2000/03/07 15:45:27 ralf Exp $
+/*
  * This file is subject to the terms and conditions of the GNU General Public+ 
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
@@ -23,7 +23,9 @@
 
 extern void prom_testtree(void);
 
-int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+extern void arc_setup_console(void);
+
+void __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
 {
 	struct linux_promblock *pb;
 
@@ -33,7 +35,20 @@
 	prom_argv = argv;
 	prom_envp = envp;
 
-	if(pb->magic != 0x53435241) {
+#if 0
+	/* arc_printf should not use prom_printf as soon as we free
+	 * the prom buffers - This horribly breaks on Indys with framebuffer
+	 * as it simply stops after initialising swap - On the Indigo2 serial
+	 * console you will get A LOT illegal instructions - Only enable
+	 * this for early init crashes - This also brings up artefacts of
+	 * printing everything twice on serial console and on GFX Console
+	 * this has the effect of having the prom printing everything
+	 * in the small rectangle and the kernel printing around.
+	 */
+
+	arc_setup_console();
+#endif
+	if (pb->magic != 0x53435241) {
 		prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic);
 		while(1)
 			;
@@ -55,5 +70,4 @@
 		romvec->imode();
 	}
 #endif
-	return 0;
 }
diff -urN linux-2.4.4-pre3/arch/mips/arc/memory.c linux/arch/mips/arc/memory.c
--- linux-2.4.4-pre3/arch/mips/arc/memory.c	Mon Aug  7 21:02:27 2000
+++ linux/arch/mips/arc/memory.c	Mon Dec  3 22:35:22 2001
@@ -3,8 +3,6 @@
  *           given to us from the ARCS firmware.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: memory.c,v 1.10 2000/01/27 23:21:57 ralf Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -47,31 +45,25 @@
 	"LoadedProgram",
 	"FirmwareTemporary",
 	"FirmwarePermanent",
-	"FreeContigiuous"
+	"FreeContiguous"
 };
 #define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc]
 #endif
 
-static struct prom_pmemblock pblocks[PROM_MAX_PMEMBLOCKS];
-
-#define MEMTYPE_DONTUSE   0
-#define MEMTYPE_PROM      1
-#define MEMTYPE_FREE      2
-
 static inline int memtype_classify_arcs (union linux_memtypes type)
 {
 	switch (type.arcs) {
 	case arcs_fcontig:
 	case arcs_free:
-		return MEMTYPE_FREE;
+		return BOOT_MEM_RAM;
 	case arcs_atmp:
-		return MEMTYPE_PROM;
+		return BOOT_MEM_ROM_DATA;
 	case arcs_eblock:
 	case arcs_rvpage:
 	case arcs_bmem:
 	case arcs_prog:
 	case arcs_aperm:
-		return MEMTYPE_DONTUSE;
+		return BOOT_MEM_RESERVED;
 	default:
 		BUG();
 	}
@@ -83,15 +75,15 @@
 	switch (type.arc) {
 	case arc_free:
 	case arc_fcontig:
-		return MEMTYPE_FREE;
+		return BOOT_MEM_RAM;
 	case arc_atmp:
-		return MEMTYPE_PROM;
+		return BOOT_MEM_ROM_DATA;
 	case arc_eblock:
 	case arc_rvpage:
 	case arc_bmem:
 	case arc_prog:
 	case arc_aperm:
-		return MEMTYPE_DONTUSE;
+		return BOOT_MEM_RESERVED;
 	default:
 		BUG();
 	}
@@ -106,50 +98,13 @@
 	return memtype_classify_arc(type);
 }
 
-static inline unsigned long find_max_low_pfn(void)
-{
-	struct prom_pmemblock *p, *highest;
-	unsigned long pfn;
-
-	p = pblocks;
-	highest = 0;
-	while (p->size != 0) {
-		if (!highest || p->base > highest->base)
-			highest = p;
-		p++;
-	}
-
-	pfn = (highest->base + highest->size) >> PAGE_SHIFT;
-#ifdef DEBUG
-	prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn);
-#endif
-	return pfn;
-}
-
-static inline struct prom_pmemblock *find_largest_memblock(void)
-{
-	struct prom_pmemblock *p, *largest;
-
-	p = pblocks;
-	largest = 0;
-	while (p->size != 0) {
-		if (!largest || p->size > largest->size)
-			largest = p;
-		p++;
-	}
-
-	return largest;
-}
-
 void __init prom_meminit(void)
 {
-	struct prom_pmemblock *largest;
-	unsigned long bootmap_size;
 	struct linux_mdesc *p;
-	int totram;
-	int i = 0;
 
 #ifdef DEBUG
+	int i = 0;
+
 	prom_printf("ARCS MEMORY DESCRIPTOR dump:\n");
 	p = ArcGetMemoryDescriptor(PROM_NULL_MDESC);
 	while(p) {
@@ -160,77 +115,36 @@
 	}
 #endif
 
-	totram = 0;
-	i = 0;
 	p = PROM_NULL_MDESC;
 	while ((p = ArcGetMemoryDescriptor(p))) {
-		pblocks[i].type = prom_memtype_classify(p->type);
-		pblocks[i].base = p->base << PAGE_SHIFT;
-		pblocks[i].size = p->pages << PAGE_SHIFT;
-
-		switch (pblocks[i].type) {
-		case MEMTYPE_FREE:
-			totram += pblocks[i].size;
-#ifdef DEBUG
-			prom_printf("free_chunk[%d]: base=%08lx size=%x\n",
-				    i, pblocks[i].base,
-				    pblocks[i].size);
-#endif
-			i++;
-			break;
-		case MEMTYPE_PROM:
-#ifdef DEBUG
-			prom_printf("prom_chunk[%d]: base=%08lx size=%x\n",
-				    i, pblocks[i].base,
-				    pblocks[i].size);
-#endif
-			i++;
-			break;
-		default:
-			break;
-		}
-	}
-	pblocks[i].size = 0;
-
-	max_low_pfn = find_max_low_pfn();
-
-	largest = find_largest_memblock();
-	bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn);
+		unsigned long base, size;
+		long type;
 
-	for (i = 0; pblocks[i].size; i++)
-		if (pblocks[i].type == MEMTYPE_FREE)
-			free_bootmem(pblocks[i].base, pblocks[i].size);
+		base = p->base << PAGE_SHIFT;
+		size = p->pages << PAGE_SHIFT;
+		type = prom_memtype_classify(p->type);
 
-	/* This test is simpleminded.  It will fail if the bootmem bitmap
-	   falls into multiple adjacent ARC memory areas.  */
-	if (bootmap_size > largest->size) {
-		prom_printf("CRITIAL: overwriting PROM data.\n");
-		BUG();
+		add_memory_region(base, size, type);
 	}
-
-	/* Reserve the memory bootmap itself */
-	reserve_bootmem(largest->base, bootmap_size);
-
-	printk("PROMLIB: Total free ram %dK / %dMB.\n",
-	       totram >> 10, totram >> 20);
 }
 
 void __init
 prom_free_prom_memory (void)
 {
-	struct prom_pmemblock *p;
 	unsigned long freed = 0;
 	unsigned long addr;
+	int i;
 
-	for (p = pblocks; p->size != 0; p++) {
-		if (p->type != MEMTYPE_PROM)
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
 			continue;
 
-		addr = PAGE_OFFSET + p->base;
-		while (addr < p->base + p->size) {
-			ClearPageReserved(virt_to_page(addr));
-			set_page_count(virt_to_page(addr), 1);
-			free_page(addr);
+		addr = boot_mem_map.map[i].addr;
+		while (addr < boot_mem_map.map[i].addr
+			      + boot_mem_map.map[i].size) {
+			ClearPageReserved(virt_to_page(__va(addr)));
+			set_page_count(virt_to_page(__va(addr)), 1);
+			free_page((unsigned long)__va(addr));
 			addr += PAGE_SIZE;
 			freed += PAGE_SIZE;
 		}
diff -urN linux-2.4.4-pre3/arch/mips/arc/misc.c linux/arch/mips/arc/misc.c
--- linux-2.4.4-pre3/arch/mips/arc/misc.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/arc/misc.c	Mon Dec  3 22:35:22 2001
@@ -1,5 +1,4 @@
-/* $Id: misc.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $
- *
+/*
  * misc.c: Miscellaneous ARCS PROM routines.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
@@ -13,13 +12,12 @@
 #include <asm/bootinfo.h>
 #include <asm/system.h>
 
-extern unsigned long mips_cputype;
 extern void *sgiwd93_host;
 extern void reset_wd33c93(void *instance);
 
 void prom_halt(void)
 {
-	bcops->bc_disable();
+	bc_disable();
 	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
@@ -29,7 +27,7 @@
 
 void prom_powerdown(void)
 {
-	bcops->bc_disable();
+	bc_disable();
 	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
@@ -40,7 +38,7 @@
 /* XXX is this a soft reset basically? XXX */
 void prom_restart(void)
 {
-	bcops->bc_disable();
+	bc_disable();
 	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
@@ -50,7 +48,7 @@
 
 void prom_reboot(void)
 {
-	bcops->bc_disable();
+	bc_disable();
 	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
@@ -60,7 +58,7 @@
 
 void prom_imode(void)
 {
-	bcops->bc_disable();
+	bc_disable();
 	cli();
 #if CONFIG_SCSI_SGIWD93
 	reset_wd33c93(sgiwd93_host);
diff -urN linux-2.4.4-pre3/arch/mips/arc/printf.c linux/arch/mips/arc/printf.c
--- linux-2.4.4-pre3/arch/mips/arc/printf.c	Mon Feb 28 07:18:20 2000
+++ linux/arch/mips/arc/printf.c	Wed Dec 31 16:00:00 1969
@@ -1,40 +0,0 @@
-/*
- * printf.c: Putting things on the screen using SGI arcs
- *           PROM facilities.
- *
- * Copyright (C) 1996 David S. Miller (dm@sgi.com)
- *
- * $Id: printf.c,v 1.3 1999/10/09 00:00:57 ralf Exp $
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/sgialib.h>
-
-static char ppbuf[1024];
-
-#ifdef CONFIG_SGI_PROM_CONSOLE
-void prom_printf(char *fmt, ...)
-#else
-void __init prom_printf(char *fmt, ...)
-#endif
-{
-	va_list args;
-	char ch, *bptr;
-	int i;
-
-	va_start(args, fmt);
-	i = vsprintf(ppbuf, fmt, args);
-
-	bptr = ppbuf;
-
-	while((ch = *(bptr++)) != 0) {
-		if(ch == '\n')
-			prom_putchar('\r');
-
-		prom_putchar(ch);
-	}
-	va_end(args);
-	return;
-}
diff -urN linux-2.4.4-pre3/arch/mips/baget/Makefile linux/arch/mips/baget/Makefile
--- linux-2.4.4-pre3/arch/mips/baget/Makefile	Sat May 13 08:29:14 2000
+++ linux/arch/mips/baget/Makefile	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.3 1999/08/13 17:07:26 harald Exp $
 #
 # Makefile for the Baget specific kernel interface routines
 # under Linux.
@@ -12,22 +11,12 @@
 all: baget.a 
 
 O_TARGET := baget.a
-O_OBJS   := baget.o print.o setup.o time.o irq.o bagetIRQ.o reset.o wbflush.o
 
-ifeq ($(CONFIG_SERIAL),y)
-	OX_OBJS += vacserial.o
-else
-	ifeq ($(CONFIG_SERIAL),m)
-		MX_OBJS += vacserial.o
-	endif
-endif
-ifeq ($(CONFIG_VAC_RTC),y)
-	OX_OBJS += vacrtc.o
-else
-	ifeq ($(CONFIG_VAC_RTC),m)
-		MX_OBJS += vacrtc.o
-	endif
-endif
+export-objs		:= vacserial.o vacrtc.o
+obj-y			:= baget.o print.o setup.o time.o irq.o bagetIRQ.o \
+			   reset.o wbflush.o
+obj-$(CONFIG_SERIAL)	+= vacserial.o
+obj-$(CONFIG_VAC_RTC)	+= vacrtc.o
 
 bagetIRQ.o : bagetIRQ.S
 	$(CC) $(CFLAGS) -c -o $@ $<
diff -urN linux-2.4.4-pre3/arch/mips/baget/prom/Makefile linux/arch/mips/baget/prom/Makefile
--- linux-2.4.4-pre3/arch/mips/baget/prom/Makefile	Sat May 13 08:29:14 2000
+++ linux/arch/mips/baget/prom/Makefile	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,4 @@
-# $Id$
+#
 # Makefile for the Baget/MIPS prom emulator library routines.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -7,9 +7,8 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-O_TARGET := bagetlib.a
-O_OBJS   := init.o
+L_TARGET := bagetlib.a
 
-all: 	$(O_TARGET)
+obj-y	:= init.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/config.in linux/arch/mips/config.in
--- linux-2.4.4-pre3/arch/mips/config.in	Thu Nov 16 12:51:28 2000
+++ linux/arch/mips/config.in	Mon Dec  3 22:35:22 2001
@@ -28,6 +28,9 @@
 bool 'Support for SGI IP22' CONFIG_SGI_IP22
 bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI
 
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+
 #
 # Select some configuration options automatically for certain systems.
 #
@@ -329,7 +332,10 @@
 #   if [ "$CONFIG_ACCESSBUS" = "y" ]; then
 #      bool 'MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE
 #   fi
-   bool 'Enhanced Real Time Clock Support' CONFIG_RTC
+   bool 'Enhanced Real Time Clock Support' CONFIG_MIPS_RTC
+
+   define_tristate CONFIG_RTC $CONFIG_MIPS_RTC
+
    endmenu
 fi
 
diff -urN linux-2.4.4-pre3/arch/mips/ddb5074/Makefile linux/arch/mips/ddb5074/Makefile
--- linux-2.4.4-pre3/arch/mips/ddb5074/Makefile	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/Makefile	Mon Dec  3 22:35:22 2001
@@ -8,8 +8,6 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 #
-# $Id$
-#
 
 .S.s:
 	$(CPP) $(CFLAGS) $< -o $*.s
@@ -17,6 +15,7 @@
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
 O_TARGET = ddb5074.a
-O_OBJS  = setup.o irq.o time.o prom.o pci.o pci-dma.o int-handler.o nile4.o
+
+obj-y	:= setup.o irq.o time.o prom.o pci.o int-handler.o nile4.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/ddb5074/int-handler.S linux/arch/mips/ddb5074/int-handler.S
--- linux-2.4.4-pre3/arch/mips/ddb5074/int-handler.S	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/int-handler.S	Mon Dec  3 22:35:22 2001
@@ -7,54 +7,50 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: int-handler.S,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
-
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 
-	/* A lot of complication here is taken away because:
-	 *
-	 * 1) We handle one interrupt and return, sitting in a loop
-	 *    and moving across all the pending IRQ bits in the cause
-	 *    register is _NOT_ the answer, the common case is one
-	 *    pending IRQ so optimize in that direction.
-	 *
-	 * 2) We need not check against bits in the status register
-	 *    IRQ mask, that would make this routine slow as hell.
-	 *
-	 * 3) Linux only thinks in terms of all IRQs on or all IRQs
-	 *    off, nothing in between like BSD spl() brain-damage.
-	 *
-	 * Furthermore, the IRQs on the INDY look basically (barring
-	 * software IRQs which we don't use at all) like:
-	 *
-	 *	MIPS IRQ	Source
-	 *      --------        ------
-	 *             0	Software (ignored)
-	 *             1        Software (ignored)
-	 *             2        Local IRQ level zero
-	 *             3        Local IRQ level one
-	 *             4        8254 Timer zero
-	 *             5        8254 Timer one
-	 *             6        Bus Error
-	 *             7        R4k timer (what we use)
-	 *
-	 * We handle the IRQ according to _our_ priority which is:
-	 *
-	 * Highest ----     R4k Timer
-	 *                  Local IRQ zero
-	 *                  Local IRQ one
-	 *                  Bus Error
-	 *                  8254 Timer zero
-	 * Lowest  ----     8254 Timer one
-	 *
-	 * then we just return, if multiple IRQs are pending then
-	 * we will just take another exception, big deal.
-	 */
+/* A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ *    common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ *    would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ *    between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the INDY look basically (barring software IRQs
+ * which we don't use at all) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Local IRQ level zero
+ *             3        Local IRQ level one
+ *             4        8254 Timer zero
+ *             5        8254 Timer one
+ *             6        Bus Error
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ *                  Local IRQ zero
+ *                  Local IRQ one
+ *                  Bus Error
+ *                  8254 Timer zero
+ * Lowest  ----     8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
 
 	.text
 	.set	noreorder
diff -urN linux-2.4.4-pre3/arch/mips/ddb5074/irq.c linux/arch/mips/ddb5074/irq.c
--- linux-2.4.4-pre3/arch/mips/ddb5074/irq.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/irq.c	Mon Dec  3 22:35:22 2001
@@ -3,10 +3,7 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: irq.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
-
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/signal.h>
@@ -14,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/ptrace.h>
@@ -27,7 +25,7 @@
 
 extern asmlinkage void ddbIRQ(void);
 extern asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs);
-extern asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
+extern asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
 
 
 void no_action(int cpl, void *dev_id, struct pt_regs *regs)
@@ -55,177 +53,174 @@
 
 static void m1543_irq_setup(void)
 {
-    /*
-     *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
-     *  the possible IO sources in the M1543 are in use by us.  We will
-     *  use the following mapping:
-     *
-     *	    IRQ1  - keyboard (default set by M1543)
-     *	    IRQ3  - reserved for UART B (default set by M1543) (note that
-     *		    the schematics for the DDB Vrc-5074 board seem to 
-     *		    indicate that IRQ3 is connected to the DS1386 
-     *		    watchdog timer interrupt output so we might have 
-     *		    a conflict)
-     *	    IRQ4  - reserved for UART A (default set by M1543)
-     *	    IRQ5  - parallel (default set by M1543)
-     *	    IRQ8  - DS1386 time of day (RTC) interrupt
-     *	    IRQ12 - mouse
-     */
- 
-    /*
-     *  Assing mouse interrupt to IRQ12 
-     */
-
-    /* Enter configuration mode */
-    outb(0x51, M1543_PNP_CONFIG);
-    outb(0x23, M1543_PNP_CONFIG);
-
-    /* Select logical device 7 (Keyboard) */
-    outb(0x07, M1543_PNP_INDEX);
-    outb(0x07, M1543_PNP_DATA);
-
-    /* Select IRQ12 */
-    outb(0x72, M1543_PNP_INDEX);
-    outb(0x0c, M1543_PNP_DATA);
-
-    /* Leave configration mode */
-    outb(0xbb, M1543_PNP_CONFIG);
+	/*
+	 *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
+	 *  the possible IO sources in the M1543 are in use by us.  We will
+	 *  use the following mapping:
+	 *
+	 *      IRQ1  - keyboard (default set by M1543)
+	 *      IRQ3  - reserved for UART B (default set by M1543) (note that
+	 *              the schematics for the DDB Vrc-5074 board seem to 
+	 *              indicate that IRQ3 is connected to the DS1386 
+	 *              watchdog timer interrupt output so we might have 
+	 *              a conflict)
+	 *      IRQ4  - reserved for UART A (default set by M1543)
+	 *      IRQ5  - parallel (default set by M1543)
+	 *      IRQ8  - DS1386 time of day (RTC) interrupt
+	 *      IRQ12 - mouse
+	 */
+
+	/*
+	 *  Assing mouse interrupt to IRQ12 
+	 */
+
+	/* Enter configuration mode */
+	outb(0x51, M1543_PNP_CONFIG);
+	outb(0x23, M1543_PNP_CONFIG);
+
+	/* Select logical device 7 (Keyboard) */
+	outb(0x07, M1543_PNP_INDEX);
+	outb(0x07, M1543_PNP_DATA);
+
+	/* Select IRQ12 */
+	outb(0x72, M1543_PNP_INDEX);
+	outb(0x0c, M1543_PNP_DATA);
+
+	/* Leave configration mode */
+	outb(0xbb, M1543_PNP_CONFIG);
 
 
-    /* Initialize the 8259 PIC in the M1543 */
-    i8259_init();
+	/* Initialize the 8259 PIC in the M1543 */
+	i8259_init();
 
-    /* Enable the interrupt cascade */
-    nile4_enable_irq(NILE4_INT_INTE);
+	/* Enable the interrupt cascade */
+	nile4_enable_irq(NILE4_INT_INTE);
 
-    request_region(M1543_PNP_CONFIG, 2, "M1543 config");
-    request_region(M1543_INT1_MASTER_ELCR, 2, "pic ELCR");
+	request_region(M1543_PNP_CONFIG, 2, "M1543 config");
+	request_region(M1543_INT1_MASTER_ELCR, 2, "pic ELCR");
 }
 
 static void nile4_irq_setup(void)
 {
-    int i;
+	int i;
 
-    /* Map all interrupts to CPU int #0 */
-    nile4_map_irq_all(0);
+	/* Map all interrupts to CPU int #0 */
+	nile4_map_irq_all(0);
 
-    /* PCI INTA#-E# must be level triggered */
-    nile4_set_pci_irq_level_or_edge(0, 1);
-    nile4_set_pci_irq_level_or_edge(1, 1);
-    nile4_set_pci_irq_level_or_edge(2, 1);
-    nile4_set_pci_irq_level_or_edge(3, 1);
-    nile4_set_pci_irq_level_or_edge(4, 1);
-
-    /* PCI INTA#-D# must be active low, INTE# must be active high */
-    nile4_set_pci_irq_polarity(0, 0);
-    nile4_set_pci_irq_polarity(1, 0);
-    nile4_set_pci_irq_polarity(2, 0);
-    nile4_set_pci_irq_polarity(3, 0);
-    nile4_set_pci_irq_polarity(4, 1);
+	/* PCI INTA#-E# must be level triggered */
+	nile4_set_pci_irq_level_or_edge(0, 1);
+	nile4_set_pci_irq_level_or_edge(1, 1);
+	nile4_set_pci_irq_level_or_edge(2, 1);
+	nile4_set_pci_irq_level_or_edge(3, 1);
+	nile4_set_pci_irq_level_or_edge(4, 1);
+
+	/* PCI INTA#-D# must be active low, INTE# must be active high */
+	nile4_set_pci_irq_polarity(0, 0);
+	nile4_set_pci_irq_polarity(1, 0);
+	nile4_set_pci_irq_polarity(2, 0);
+	nile4_set_pci_irq_polarity(3, 0);
+	nile4_set_pci_irq_polarity(4, 1);
 
-    for (i = 0; i < 16; i++)
-	nile4_clear_irq(i);
+	for (i = 0; i < 16; i++)
+		nile4_clear_irq(i);
 
-    /* Enable CPU int #0 */
-    nile4_enable_irq_output(0);
+	/* Enable CPU int #0 */
+	nile4_enable_irq_output(0);
 
-    request_mem_region(NILE4_BASE, NILE4_SIZE, "Nile 4");
+	request_mem_region(NILE4_BASE, NILE4_SIZE, "Nile 4");
 }
 
 
 /*
  * IRQ2 is cascade interrupt to second interrupt controller
  */
-
-static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL };
+static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL };
 
 
 void disable_irq(unsigned int irq_nr)
 {
-    if (is_i8259_irq(irq_nr))
-	i8259_disable_irq(irq_nr);
-    else
-	nile4_disable_irq(irq_to_nile4(irq_nr));
+	if (is_i8259_irq(irq_nr))
+		i8259_disable_irq(irq_nr);
+	else
+		nile4_disable_irq(irq_to_nile4(irq_nr));
 }
 
 void enable_irq(unsigned int irq_nr)
 {
-    if (is_i8259_irq(irq_nr))
-	i8259_enable_irq(irq_nr);
-    else
-	nile4_enable_irq(irq_to_nile4(irq_nr));
+	if (is_i8259_irq(irq_nr))
+		i8259_enable_irq(irq_nr);
+	else
+		nile4_enable_irq(irq_to_nile4(irq_nr));
 }
 
 int table[16] = { 0, };
 
 void ddb_local0_irqdispatch(struct pt_regs *regs)
 {
-    u32 mask;
-    int nile4_irq;
+	u32 mask;
+	int nile4_irq;
 #if 1
-    volatile static int nesting = 0;
-    if (nesting++ == 0)
-	ddb5074_led_d3(1);
-    ddb5074_led_hex(nesting < 16 ? nesting : 15);
+	volatile static int nesting = 0;
+	if (nesting++ == 0)
+		ddb5074_led_d3(1);
+	ddb5074_led_hex(nesting < 16 ? nesting : 15);
 #endif
 
-    mask = nile4_get_irq_stat(0);
-    nile4_clear_irq_mask(mask);
+	mask = nile4_get_irq_stat(0);
+	nile4_clear_irq_mask(mask);
 
-    /* Handle the timer interrupt first */
-    if (mask & (1<<NILE4_INT_GPT)) {
-	nile4_disable_irq(NILE4_INT_GPT);
-	do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
-	nile4_enable_irq(NILE4_INT_GPT);
-	mask &= ~(1<<NILE4_INT_GPT);
-    }
-    for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
-	if (mask & 1) {
-	    nile4_disable_irq(nile4_irq);
-	    if (nile4_irq == NILE4_INT_INTE) {
-		int i8259_irq = nile4_i8259_iack();
-		i8259_do_irq(i8259_irq, regs);
-	    } else
-		do_IRQ(nile4_to_irq(nile4_irq), regs);
-	    nile4_enable_irq(nile4_irq);
+	/* Handle the timer interrupt first */
+	if (mask & (1 << NILE4_INT_GPT)) {
+		nile4_disable_irq(NILE4_INT_GPT);
+		do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
+		nile4_enable_irq(NILE4_INT_GPT);
+		mask &= ~(1 << NILE4_INT_GPT);
 	}
-
+	for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
+		if (mask & 1) {
+			nile4_disable_irq(nile4_irq);
+			if (nile4_irq == NILE4_INT_INTE) {
+				int i8259_irq = nile4_i8259_iack();
+				i8259_do_irq(i8259_irq, regs);
+			} else
+				do_IRQ(nile4_to_irq(nile4_irq), regs);
+			nile4_enable_irq(nile4_irq);
+		}
 #if 1
-    if (--nesting == 0)
-	ddb5074_led_d3(0);
-    ddb5074_led_hex(nesting < 16 ? nesting : 15);
+	if (--nesting == 0)
+		ddb5074_led_d3(0);
+	ddb5074_led_hex(nesting < 16 ? nesting : 15);
 #endif
 }
 
 void ddb_local1_irqdispatch(void)
 {
-    printk("ddb_local1_irqdispatch called\n");
+	printk("ddb_local1_irqdispatch called\n");
 }
 
 void ddb_buserror_irq(void)
 {
-    printk("ddb_buserror_irq called\n");
+	printk("ddb_buserror_irq called\n");
 }
 
 void ddb_8254timer_irq(void)
 {
-    printk("ddb_8254timer_irq called\n");
+	printk("ddb_8254timer_irq called\n");
 }
 
 void __init ddb_irq_setup(void)
 {
 #ifdef CONFIG_REMOTE_DEBUG
-    if (remote_debug)
-	set_debug_traps();
-    breakpoint(); /* you may move this line to whereever you want :-) */
+	if (remote_debug)
+		set_debug_traps();
+	breakpoint();		/* you may move this line to whereever you want :-) */
 #endif
-    request_region(0x20, 0x20, "pic1");
-    request_region(0xa0, 0x20, "pic2");
-    i8259_setup_irq(2, &irq2);
+	request_region(0x20, 0x20, "pic1");
+	request_region(0xa0, 0x20, "pic2");
+	i8259_setup_irq(2, &irq2);
 
-    nile4_irq_setup();
-    m1543_irq_setup();
+	nile4_irq_setup();
+	m1543_irq_setup();
 
-    set_except_vector(0, ddbIRQ);
+	set_except_vector(0, ddbIRQ);
 }
-
diff -urN linux-2.4.4-pre3/arch/mips/ddb5074/nile4.c linux/arch/mips/ddb5074/nile4.c
--- linux-2.4.4-pre3/arch/mips/ddb5074/nile4.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/nile4.c	Mon Dec  3 22:35:22 2001
@@ -3,292 +3,290 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id$
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
+
 #include <asm/nile4.h>
 
 
-    /*
-     *  Physical Device Address Registers
-     *
-     *  Note: 32 bit addressing only!
-     */
-
-void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width, int on_memory_bus,
-		    int visible)
-{
-    u32 maskbits;
-    u32 widthbits;
-
-    if (pdar > NILE4_BOOTCS || (pdar & 7)) {
-	printk("nile4_set_pdar: invalid pdar %d\n", pdar);
-	return;
-    }
-    if (pdar == NILE4_INTCS && size != 0x00200000) {
-	printk("nile4_set_pdar: INTCS size must be 2 MB\n");
-	return;
-    }
-    switch (size) {
-#if 0	/* We don't support 4 GB yet */
+/*
+ *  Physical Device Address Registers
+ *
+ *  Note: 32 bit addressing only!
+ */
+void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width,
+		    int on_memory_bus, int visible)
+{
+	u32 maskbits;
+	u32 widthbits;
+
+	if (pdar > NILE4_BOOTCS || (pdar & 7)) {
+		printk("nile4_set_pdar: invalid pdar %d\n", pdar);
+		return;
+	}
+	if (pdar == NILE4_INTCS && size != 0x00200000) {
+		printk("nile4_set_pdar: INTCS size must be 2 MB\n");
+		return;
+	}
+	switch (size) {
+#if 0				/* We don't support 4 GB yet */
 	case 0x100000000:	/* 4 GB */
-	    maskbits = 4;
-	    break;
+		maskbits = 4;
+		break;
 #endif
 	case 0x80000000:	/* 2 GB */
-	    maskbits = 5;
-	    break;
+		maskbits = 5;
+		break;
 	case 0x40000000:	/* 1 GB */
-	    maskbits = 6;
-	    break;
+		maskbits = 6;
+		break;
 	case 0x20000000:	/* 512 MB */
-	    maskbits = 7;
-	    break;
+		maskbits = 7;
+		break;
 	case 0x10000000:	/* 256 MB */
-	    maskbits = 8;
-	    break;
+		maskbits = 8;
+		break;
 	case 0x08000000:	/* 128 MB */
-	    maskbits = 9;
-	    break;
+		maskbits = 9;
+		break;
 	case 0x04000000:	/* 64 MB */
-	    maskbits = 10;
-	    break;
+		maskbits = 10;
+		break;
 	case 0x02000000:	/* 32 MB */
-	    maskbits = 11;
-	    break;
+		maskbits = 11;
+		break;
 	case 0x01000000:	/* 16 MB */
-	    maskbits = 12;
-	    break;
+		maskbits = 12;
+		break;
 	case 0x00800000:	/* 8 MB */
-	    maskbits = 13;
-	    break;
+		maskbits = 13;
+		break;
 	case 0x00400000:	/* 4 MB */
-	    maskbits = 14;
-	    break;
+		maskbits = 14;
+		break;
 	case 0x00200000:	/* 2 MB */
-	    maskbits = 15;
-	    break;
-	case 0:			/* OFF */
-	    maskbits = 0;
-	    break;
+		maskbits = 15;
+		break;
+	case 0:		/* OFF */
+		maskbits = 0;
+		break;
 	default:
-	    printk("nile4_set_pdar: unsupported size %p\n", (void *)size);
-	    return;
-    }
-    switch (width) {
+		printk("nile4_set_pdar: unsupported size %p\n", (void *) size);
+		return;
+	}
+	switch (width) {
 	case 8:
-	    widthbits = 0;
-	    break;
+		widthbits = 0;
+		break;
 	case 16:
-	    widthbits = 1;
-	    break;
+		widthbits = 1;
+		break;
 	case 32:
-	    widthbits = 2;
-	    break;
+		widthbits = 2;
+		break;
 	case 64:
-	    widthbits = 3;
-	    break;
+		widthbits = 3;
+		break;
 	default:
-	    printk("nile4_set_pdar: unsupported width %d\n", width);
-	    return;
-    }
-    nile4_out32(pdar, maskbits | (on_memory_bus ? 0x10 : 0) |
-    		      (visible ? 0x20 : 0) | (widthbits << 6) |
-		      (phys & 0xffe00000));
-    nile4_out32(pdar+4, 0);
-    /*
-     *  When programming a PDAR, the register should be read immediately after
-     *  writing it. This ensures that address decoders are properly configured.
-     */
-    (void)nile4_in32(pdar);
-    (void)nile4_in32(pdar+4);
+		printk("nile4_set_pdar: unsupported width %d\n", width);
+		return;
+	}
+	nile4_out32(pdar, maskbits | (on_memory_bus ? 0x10 : 0) |
+		    (visible ? 0x20 : 0) | (widthbits << 6) |
+		    (phys & 0xffe00000));
+	nile4_out32(pdar + 4, 0);
+	/*
+	 * When programming a PDAR, the register should be read immediately
+	 * after writing it. This ensures that address decoders are properly
+	 * configured.
+	 */
+	nile4_in32(pdar);
+	nile4_in32(pdar + 4);
 }
 
 
-    /*
-     *  PCI Master Registers
-     *
-     *  Note: 32 bit addressing only!
-     */
-
+/*
+ *  PCI Master Registers
+ *
+ *  Note: 32 bit addressing only!
+ */
 void nile4_set_pmr(u32 pmr, u32 type, u32 addr)
 {
-    if (pmr != NILE4_PCIINIT0 && pmr != NILE4_PCIINIT1) {
-	printk("nile4_set_pmr: invalid pmr %d\n", pmr);
-	return;
-    }
-    switch (type) {
+	if (pmr != NILE4_PCIINIT0 && pmr != NILE4_PCIINIT1) {
+		printk("nile4_set_pmr: invalid pmr %d\n", pmr);
+		return;
+	}
+	switch (type) {
 	case NILE4_PCICMD_IACK:	/* PCI Interrupt Acknowledge */
 	case NILE4_PCICMD_IO:	/* PCI I/O Space */
 	case NILE4_PCICMD_MEM:	/* PCI Memory Space */
 	case NILE4_PCICMD_CFG:	/* PCI Configuration Space */
-	    break;
+		break;
 	default:
-	    printk("nile4_set_pmr: invalid type %d\n", type);
-	    return;
-    }
-    nile4_out32(pmr, (type << 1) | 0x10 | (addr & 0xffe00000));
-    nile4_out32(pmr+4, 0);
+		printk("nile4_set_pmr: invalid type %d\n", type);
+		return;
+	}
+	nile4_out32(pmr, (type << 1) | 0x10 | (addr & 0xffe00000));
+	nile4_out32(pmr + 4, 0);
 }
 
 
-    /*
-     *  Interrupt Programming
-     */
-
+/*
+ *  Interrupt Programming
+ */
 void nile4_map_irq(int nile4_irq, int cpu_irq)
 {
-    u32 offset, t;
+	u32 offset, t;
 
-    offset = NILE4_INTCTRL;
-    if (nile4_irq >= 8) {
-	offset += 4;
-	nile4_irq -= 8;
-    }
-    t = nile4_in32(offset);
-    t &= ~(7 << (nile4_irq*4));
-    t |= cpu_irq << (nile4_irq*4);
-    nile4_out32(offset, t);
+	offset = NILE4_INTCTRL;
+	if (nile4_irq >= 8) {
+		offset += 4;
+		nile4_irq -= 8;
+	}
+	t = nile4_in32(offset);
+	t &= ~(7 << (nile4_irq * 4));
+	t |= cpu_irq << (nile4_irq * 4);
+	nile4_out32(offset, t);
 }
 
 void nile4_map_irq_all(int cpu_irq)
 {
-    u32 all, t;
-    
-    all = cpu_irq;
-    all |= all << 4;
-    all |= all << 8;
-    all |= all << 16;
-    t = nile4_in32(NILE4_INTCTRL);
-    t &= 0x88888888;
-    t |= all;
-    nile4_out32(NILE4_INTCTRL, t);
-    t = nile4_in32(NILE4_INTCTRL+4);
-    t &= 0x88888888;
-    t |= all;
-    nile4_out32(NILE4_INTCTRL+4, t);
+	u32 all, t;
+
+	all = cpu_irq;
+	all |= all << 4;
+	all |= all << 8;
+	all |= all << 16;
+	t = nile4_in32(NILE4_INTCTRL);
+	t &= 0x88888888;
+	t |= all;
+	nile4_out32(NILE4_INTCTRL, t);
+	t = nile4_in32(NILE4_INTCTRL + 4);
+	t &= 0x88888888;
+	t |= all;
+	nile4_out32(NILE4_INTCTRL + 4, t);
 }
 
 void nile4_enable_irq(int nile4_irq)
 {
-    u32 offset, t;
+	u32 offset, t;
 
-    offset = NILE4_INTCTRL;
-    if (nile4_irq >= 8) {
-	offset += 4;
-	nile4_irq -= 8;
-    }
-    t = nile4_in32(offset);
-    t |= 8 << (nile4_irq*4);
-    nile4_out32(offset, t);
+	offset = NILE4_INTCTRL;
+	if (nile4_irq >= 8) {
+		offset += 4;
+		nile4_irq -= 8;
+	}
+	t = nile4_in32(offset);
+	t |= 8 << (nile4_irq * 4);
+	nile4_out32(offset, t);
 }
 
 void nile4_disable_irq(int nile4_irq)
 {
-    u32 offset, t;
+	u32 offset, t;
 
-    offset = NILE4_INTCTRL;
-    if (nile4_irq >= 8) {
-	offset += 4;
-	nile4_irq -= 8;
-    }
-    t = nile4_in32(offset);
-    t &= ~(8 << (nile4_irq*4));
-    nile4_out32(offset, t);
+	offset = NILE4_INTCTRL;
+	if (nile4_irq >= 8) {
+		offset += 4;
+		nile4_irq -= 8;
+	}
+	t = nile4_in32(offset);
+	t &= ~(8 << (nile4_irq * 4));
+	nile4_out32(offset, t);
 }
 
 void nile4_disable_irq_all(void)
 {
-    nile4_out32(NILE4_INTCTRL, 0);
-    nile4_out32(NILE4_INTCTRL+4, 0);
+	nile4_out32(NILE4_INTCTRL, 0);
+	nile4_out32(NILE4_INTCTRL + 4, 0);
 }
 
 u16 nile4_get_irq_stat(int cpu_irq)
 {
-    return nile4_in16(NILE4_INTSTAT0+cpu_irq*2);
+	return nile4_in16(NILE4_INTSTAT0 + cpu_irq * 2);
 }
 
 void nile4_enable_irq_output(int cpu_irq)
 {
-    u32 t;
+	u32 t;
 
-    t = nile4_in32(NILE4_INTSTAT1+4);
-    t |= 1 << (16+cpu_irq);
-    nile4_out32(NILE4_INTSTAT1, t);
+	t = nile4_in32(NILE4_INTSTAT1 + 4);
+	t |= 1 << (16 + cpu_irq);
+	nile4_out32(NILE4_INTSTAT1, t);
 }
 
 void nile4_disable_irq_output(int cpu_irq)
 {
-    u32 t;
+	u32 t;
 
-    t = nile4_in32(NILE4_INTSTAT1+4);
-    t &= ~(1 << (16+cpu_irq));
-    nile4_out32(NILE4_INTSTAT1, t);
+	t = nile4_in32(NILE4_INTSTAT1 + 4);
+	t &= ~(1 << (16 + cpu_irq));
+	nile4_out32(NILE4_INTSTAT1, t);
 }
 
 void nile4_set_pci_irq_polarity(int pci_irq, int high)
 {
-    u32 t;
+	u32 t;
 
-    t = nile4_in32(NILE4_INTPPES);
-    if (high)
-	t &= ~(1 << (pci_irq*2));
-    else
-	t |= 1 << (pci_irq*2);
-    nile4_out32(NILE4_INTPPES, t);
+	t = nile4_in32(NILE4_INTPPES);
+	if (high)
+		t &= ~(1 << (pci_irq * 2));
+	else
+		t |= 1 << (pci_irq * 2);
+	nile4_out32(NILE4_INTPPES, t);
 }
 
 void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
 {
-    u32 t;
+	u32 t;
 
-    t = nile4_in32(NILE4_INTPPES);
-    if (level)
-	t |= 2 << (pci_irq*2);
-    else
-	t &= ~(2 << (pci_irq*2));
-    nile4_out32(NILE4_INTPPES, t);
+	t = nile4_in32(NILE4_INTPPES);
+	if (level)
+		t |= 2 << (pci_irq * 2);
+	else
+		t &= ~(2 << (pci_irq * 2));
+	nile4_out32(NILE4_INTPPES, t);
 }
 
 void nile4_clear_irq(int nile4_irq)
 {
-    nile4_out32(NILE4_INTCLR, 1 << nile4_irq);
+	nile4_out32(NILE4_INTCLR, 1 << nile4_irq);
 }
 
 void nile4_clear_irq_mask(u32 mask)
 {
-    nile4_out32(NILE4_INTCLR, mask);
+	nile4_out32(NILE4_INTCLR, mask);
 }
 
 u8 nile4_i8259_iack(void)
 {
-    u8 irq;
+	u8 irq;
 
-    /* Set window 0 for interrupt acknowledge */
-    nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IACK, 0);
-    irq = *(volatile u8 *)NILE4_PCI_IACK_BASE;
-    /* Set window 0 for PCI I/O space */
-    nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
-    return irq;
+	/* Set window 0 for interrupt acknowledge */
+	nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IACK, 0);
+	irq = *(volatile u8 *) NILE4_PCI_IACK_BASE;
+	/* Set window 0 for PCI I/O space */
+	nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
+	return irq;
 }
 
 #if 0
 void nile4_dump_irq_status(void)
 {
-    printk("CPUSTAT = %p:%p\n", (void *)nile4_in32(NILE4_CPUSTAT+4),
-    				(void *)nile4_in32(NILE4_CPUSTAT));
-    printk("INTCTRL = %p:%p\n", (void *)nile4_in32(NILE4_INTCTRL+4),
-    				(void *)nile4_in32(NILE4_INTCTRL));
-    printk("INTSTAT0 = %p:%p\n", (void *)nile4_in32(NILE4_INTSTAT0+4),
-    				(void *)nile4_in32(NILE4_INTSTAT0));
-    printk("INTSTAT1 = %p:%p\n", (void *)nile4_in32(NILE4_INTSTAT1+4),
-    				(void *)nile4_in32(NILE4_INTSTAT1));
-    printk("INTCLR = %p:%p\n", (void *)nile4_in32(NILE4_INTCLR+4),
-    				(void *)nile4_in32(NILE4_INTCLR));
-    printk("INTPPES = %p:%p\n", (void *)nile4_in32(NILE4_INTPPES+4),
-    				(void *)nile4_in32(NILE4_INTPPES));
+	printk("CPUSTAT = %p:%p\n", (void *) nile4_in32(NILE4_CPUSTAT + 4),
+	       (void *) nile4_in32(NILE4_CPUSTAT));
+	printk("INTCTRL = %p:%p\n", (void *) nile4_in32(NILE4_INTCTRL + 4),
+	       (void *) nile4_in32(NILE4_INTCTRL));
+	printk("INTSTAT0 = %p:%p\n",
+	       (void *) nile4_in32(NILE4_INTSTAT0 + 4),
+	       (void *) nile4_in32(NILE4_INTSTAT0));
+	printk("INTSTAT1 = %p:%p\n",
+	       (void *) nile4_in32(NILE4_INTSTAT1 + 4),
+	       (void *) nile4_in32(NILE4_INTSTAT1));
+	printk("INTCLR = %p:%p\n", (void *) nile4_in32(NILE4_INTCLR + 4),
+	       (void *) nile4_in32(NILE4_INTCLR));
+	printk("INTPPES = %p:%p\n", (void *) nile4_in32(NILE4_INTPPES + 4),
+	       (void *) nile4_in32(NILE4_INTPPES));
 }
 #endif
diff -urN linux-2.4.4-pre3/arch/mips/ddb5074/pci-dma.c linux/arch/mips/ddb5074/pci-dma.c
--- linux-2.4.4-pre3/arch/mips/ddb5074/pci-dma.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/pci-dma.c	Wed Dec 31 16:00:00 1969
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2000   Ani Joshi <ajoshi@unixbox.com>
- *
- *
- * Dynamic DMA mapping support.
- *
- * swiped from i386, and cloned for MIPS by Geert.
- *
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-			   dma_addr_t *dma_handle)
-{
-	void *ret;
-	int gfp = GFP_ATOMIC;
-
-	if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
-		gfp |= GFP_DMA;
-	ret = (void *)__get_free_pages(gfp, get_order(size));
-
-	if (ret != NULL) {
-		memset(ret, 0, size);
-		*dma_handle = virt_to_bus(ret);
-	}
-	return ret;
-}
-
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-			 void *vaddr, dma_addr_t dma_handle)
-{
-	free_pages((unsigned long)vaddr, get_order(size));
-}
diff -urN linux-2.4.4-pre3/arch/mips/ddb5074/pci.c linux/arch/mips/ddb5074/pci.c
--- linux-2.4.4-pre3/arch/mips/ddb5074/pci.c	Mon Nov 27 17:51:34 2000
+++ linux/arch/mips/ddb5074/pci.c	Mon Dec  3 22:35:22 2001
@@ -4,313 +4,325 @@
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Albert Dorofeev <albert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: pci.c,v 1.4 2000/02/18 00:02:17 ralf Exp $
  */
-
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
-#include <asm-mips/nile4.h>
+
+#include <asm/nile4.h>
 
 
 static u32 nile4_pre_pci_access0(int slot_num)
 {
-    u32 pci_addr = 0;
-    u32 virt_addr = NILE4_PCI_CFG_BASE;
+	u32 pci_addr = 0;
+	u32 virt_addr = NILE4_PCI_CFG_BASE;
 
-    /* Set window 1 address 8000000 - 64 bit - 2 MB (PCI config space) */
-    nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x00200000, 64, 0, 0);
-    if (slot_num > 2)
-	pci_addr = 0x00040000 << slot_num;
-    else
-	virt_addr += 0x00040000 << slot_num;
-    nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, pci_addr);
-    return virt_addr;
+	/* Set window 1 address 8000000 - 64 bit - 2 MB (PCI config space) */
+	nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x00200000, 64, 0,
+		       0);
+	if (slot_num > 2)
+		pci_addr = 0x00040000 << slot_num;
+	else
+		virt_addr += 0x00040000 << slot_num;
+	nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, pci_addr);
+	return virt_addr;
 }
 
 static void nile4_post_pci_access0(void)
 {
-    /* Set window 1 back to address 8000000 - 64 bit - 128 MB (PCI IO space) */
-    nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE), 0x08000000, 64,
-    		   1, 1);
-    nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0);
+	/*
+	 * Set window 1 back to address 8000000 - 64 bit - 128 MB
+	 * (PCI IO space)
+	 */
+	nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE),
+		       0x08000000, 64, 1, 1);
+	nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0);
 }
 
 
-static int nile4_pci_read_config_dword( struct pci_dev *dev,
-				int where, u32 *val)
+static int nile4_pci_read_config_dword(struct pci_dev *dev,
+				       int where, u32 * val)
 {
-    int slot_num, func_num;
-    u32 base;
-
-    /*
-     *  For starters let's do configuration cycle 0 only (one bus only)
-     */
-    if (dev->bus->number)
-	return PCIBIOS_FUNC_NOT_SUPPORTED;
+	int slot_num, func_num;
+	u32 base;
 
-    slot_num = PCI_SLOT(dev->devfn);
-    func_num = PCI_FUNC(dev->devfn);
-    if (slot_num == 5) {
 	/*
-	 *  This is Nile 4 and it will crash if we access it like other
-	 *   devices
+	 *  For starters let's do configuration cycle 0 only (one bus only)
 	 */
-	*val = nile4_in32(NILE4_PCI_BASE + where);
+	if (dev->bus->number)
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+	slot_num = PCI_SLOT(dev->devfn);
+	func_num = PCI_FUNC(dev->devfn);
+	if (slot_num == 5) {
+		/*
+		 * This is Nile 4 and it will crash if we access it like other
+		 * devices
+		 */
+		*val = nile4_in32(NILE4_PCI_BASE + where);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	base = nile4_pre_pci_access0(slot_num);
+	*val =
+	    *((volatile u32 *) (base + (func_num << 8) + (where & 0xfc)));
+	nile4_post_pci_access0();
 	return PCIBIOS_SUCCESSFUL;
-    }
-    base = nile4_pre_pci_access0(slot_num);
-    *val = *((volatile u32 *)(base + (func_num << 8) + (where & 0xfc)));
-    nile4_post_pci_access0();
-    return PCIBIOS_SUCCESSFUL;
 }
 
 static int nile4_pci_write_config_dword(struct pci_dev *dev, int where,
 					u32 val)
 {
-    int slot_num, func_num;
-    u32 base;
+	int slot_num, func_num;
+	u32 base;
 
-    /*
-     *  For starters let's do configuration cycle 0 only (one bus only)
-     */
-    if (dev->bus->number)
-	return PCIBIOS_FUNC_NOT_SUPPORTED;
-
-    slot_num = PCI_SLOT(dev->devfn);
-    func_num = PCI_FUNC(dev->devfn);
-    if (slot_num == 5) {
 	/*
-	 *  This is Nile 4 and it will crash if we access it like other
-	 *   devices
+	 * For starters let's do configuration cycle 0 only (one bus only)
 	 */
-	nile4_out32(NILE4_PCI_BASE + where, val);
+	if (dev->bus->number)
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+	slot_num = PCI_SLOT(dev->devfn);
+	func_num = PCI_FUNC(dev->devfn);
+	if (slot_num == 5) {
+		/*
+		 * This is Nile 4 and it will crash if we access it like other
+		 * devices
+		 */
+		nile4_out32(NILE4_PCI_BASE + where, val);
+		return PCIBIOS_SUCCESSFUL;
+	}
+	base = nile4_pre_pci_access0(slot_num);
+	*((volatile u32 *) (base + (func_num << 8) + (where & 0xfc))) =
+	    val;
+	nile4_post_pci_access0();
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_read_config_word(struct pci_dev *dev, int where,
+				      u16 * val)
+{
+	int status;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 2)
+		result >>= 16;
+	*val = result & 0xffff;
 	return PCIBIOS_SUCCESSFUL;
-    }
-    base = nile4_pre_pci_access0(slot_num);
-    *((volatile u32 *)(base + (func_num << 8) + (where & 0xfc))) = val;
-    nile4_post_pci_access0();
-    return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pci_read_config_word(struct pci_dev *dev, int where, u16 *val)
-{
-    int status;
-    u32 result;
-
-    status = nile4_pci_read_config_dword(dev, where, &result);
-    if (status != PCIBIOS_SUCCESSFUL)
-	return status;
-    if (where & 2)
-	result >>= 16;
-    *val = result & 0xffff;
-    return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pci_read_config_byte(struct pci_dev *dev, int where, u8 *val)
-{
-    int status;
-    u32 result;
-
-    status = nile4_pci_read_config_dword(dev, where, &result);
-    if (status != PCIBIOS_SUCCESSFUL)
-	return status;
-    if (where & 1)
-	result >>= 8;
-    if (where & 2)
-	result >>= 16;
-    *val = result & 0xff;
-    return PCIBIOS_SUCCESSFUL;
-}
-
-static int nile4_pci_write_config_word(struct pci_dev *dev, int where, u16 val)
-{
-    int status, shift = 0;
-    u32 result;
-
-    status = nile4_pci_read_config_dword(dev, where, &result);
-    if (status != PCIBIOS_SUCCESSFUL)
-	return status;
-    if (where & 2)
-	shift += 16;
-    result &= ~(0xffff << shift);
-    result |= val << shift;
-    return nile4_pci_write_config_dword(dev, where, result);
-}
-
-static int nile4_pci_write_config_byte( struct pci_dev *dev, int where, u8 val)
-{
-    int status, shift = 0;
-    u32 result;
-
-    status = nile4_pci_read_config_dword(dev, where, &result);
-    if (status != PCIBIOS_SUCCESSFUL)
-	return status;
-    if (where & 2)
-	shift += 16;
-    if (where & 1)
-	shift += 8;
-    result &= ~(0xff << shift);
-    result |= val << shift;
-    return nile4_pci_write_config_dword(dev, where, result);
+}
+
+static int nile4_pci_read_config_byte(struct pci_dev *dev, int where,
+				      u8 * val)
+{
+	int status;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 1)
+		result >>= 8;
+	if (where & 2)
+		result >>= 16;
+	*val = result & 0xff;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_write_config_word(struct pci_dev *dev, int where,
+				       u16 val)
+{
+	int status, shift = 0;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 2)
+		shift += 16;
+	result &= ~(0xffff << shift);
+	result |= val << shift;
+	return nile4_pci_write_config_dword(dev, where, result);
+}
+
+static int nile4_pci_write_config_byte(struct pci_dev *dev, int where,
+				       u8 val)
+{
+	int status, shift = 0;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 2)
+		shift += 16;
+	if (where & 1)
+		shift += 8;
+	result &= ~(0xff << shift);
+	result |= val << shift;
+	return nile4_pci_write_config_dword(dev, where, result);
 }
 
 struct pci_ops nile4_pci_ops = {
-    nile4_pci_read_config_byte,
-    nile4_pci_read_config_word,
-    nile4_pci_read_config_dword,
-    nile4_pci_write_config_byte,
-    nile4_pci_write_config_word,
-    nile4_pci_write_config_dword
+	nile4_pci_read_config_byte,
+	nile4_pci_read_config_word,
+	nile4_pci_read_config_dword,
+	nile4_pci_write_config_byte,
+	nile4_pci_write_config_word,
+	nile4_pci_write_config_dword
 };
 
 struct {
-    struct resource ram;
-    struct resource flash;
-    struct resource isa_io;
-    struct resource pci_io;
-    struct resource isa_mem;
-    struct resource pci_mem;
-    struct resource nile4;
-    struct resource boot;
+	struct resource ram;
+	struct resource flash;
+	struct resource isa_io;
+	struct resource pci_io;
+	struct resource isa_mem;
+	struct resource pci_mem;
+	struct resource nile4;
+	struct resource boot;
 } ddb5074_resources = {
-    { "RAM", 0x00000000, 0x03ffffff,
-      IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
-    { "Flash ROM", 0x04000000, 0x043fffff },
-    { "Nile4 ISA I/O", 0x06000000, 0x060fffff },
-    { "Nile4 PCI I/O", 0x06100000, 0x07ffffff },
-    { "Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM },
-    { "Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM },
-    { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff,
-      IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
-    { "Boot ROM", 0x1fc00000, 0x1fffffff }
+	{ "RAM", 0x00000000, 0x03ffffff,
+	  IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64},
+	{ "Flash ROM", 0x04000000, 0x043fffff},
+	{ "Nile4 ISA I/O", 0x06000000, 0x060fffff},
+	{ "Nile4 PCI I/O", 0x06100000, 0x07ffffff},
+	{ "Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM},
+	{ "Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM},
+	{ "Nile4 ctrl", 0x1fa00000, 0x1fbfffff,
+	  IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64},
+	{ "Boot ROM", 0x1fc00000, 0x1fffffff}
 };
 
 static void __init ddb5074_pci_fixup(void)
 {
-    struct pci_dev *dev;
+	struct pci_dev *dev;
 
-    pci_for_each_dev(dev) {
-	if (dev->vendor == PCI_VENDOR_ID_NEC &&
-	    dev->device == PCI_DEVICE_ID_NEC_NILE4) {
-	    /*
-	     *  The first 64-bit PCI base register should point to the Nile4
-	     *  control registers. Unfortunately this isn't the case, so we fix
-	     *  it ourselves. This allows the serial driver to find the UART.
-	     */
-	    dev->resource[0] = ddb5074_resources.nile4;
-	    request_resource(&iomem_resource, &dev->resource[0]);
-	    /*
-	     *  The second 64-bit PCI base register points to the first memory
-	     *  bank. Unfortunately the address is wrong, so we fix it (again).
-	     */
-	    dev->resource[2] = ddb5074_resources.ram;
-	    request_resource(&iomem_resource, &dev->resource[2]);
-	} else if (dev->vendor == PCI_VENDOR_ID_AL &&
-		   dev->device == PCI_DEVICE_ID_AL_M7101) {
-	    /*
-	     *  It's nice to have the LEDs on the GPIO pins available for
-	     *  debugging
-	     */
-	    extern struct pci_dev *pci_pmu;
-	    u8 t8;
-
-	    pci_pmu = dev;		/* for LEDs D2 and D3 */
-	    /* Program the lines for LEDs D2 and D3 to output */
-	    nile4_pci_read_config_byte(dev, 0x7d, &t8);
-	    t8 |= 0xc0;
-	    nile4_pci_write_config_byte(dev, 0x7d, t8);
-	    /* Turn LEDs D2 and D3 off */
-	    nile4_pci_read_config_byte(dev, 0x7e, &t8);
-	    t8 |= 0xc0;
-	    nile4_pci_write_config_byte(dev, 0x7e, t8);
+	pci_for_each_dev(dev) {
+		if (dev->vendor == PCI_VENDOR_ID_NEC &&
+		    dev->device == PCI_DEVICE_ID_NEC_NILE4) {
+			/*
+			 * The first 64-bit PCI base register should point to
+			 * the Nile4 control registers. Unfortunately this
+			 * isn't the case, so we fix it ourselves. This allows
+			 * the serial driver to find the UART.
+			 */
+			dev->resource[0] = ddb5074_resources.nile4;
+			request_resource(&iomem_resource,
+					 &dev->resource[0]);
+			/*
+			 * The second 64-bit PCI base register points to the
+			 * first memory bank. Unfortunately the address is
+			 * wrong, so we fix it (again).
+			 */
+			dev->resource[2] = ddb5074_resources.ram;
+			request_resource(&iomem_resource,
+					 &dev->resource[2]);
+		} else if (dev->vendor == PCI_VENDOR_ID_AL
+			   && dev->device == PCI_DEVICE_ID_AL_M7101) {
+			/*
+			 * It's nice to have the LEDs on the GPIO pins
+			 * available for debugging
+			 */
+			extern struct pci_dev *pci_pmu;
+			u8 t8;
+
+			pci_pmu = dev;	/* for LEDs D2 and D3 */
+			/* Program the lines for LEDs D2 and D3 to output */
+			nile4_pci_read_config_byte(dev, 0x7d, &t8);
+			t8 |= 0xc0;
+			nile4_pci_write_config_byte(dev, 0x7d, t8);
+			/* Turn LEDs D2 and D3 off */
+			nile4_pci_read_config_byte(dev, 0x7e, &t8);
+			t8 |= 0xc0;
+			nile4_pci_write_config_byte(dev, 0x7e, t8);
+		}
 	}
-    }
 }
 
 static void __init pcibios_fixup_irqs(void)
 {
-    struct pci_dev *dev;
-    int slot_num;
+	struct pci_dev *dev;
+	int slot_num;
 
-    pci_for_each_dev(dev) {
-	slot_num = PCI_SLOT(dev->devfn);
-	switch (slot_num) {
-	    case 0:
-		dev->irq = nile4_to_irq(NILE4_INT_INTE);
-		break;
-	    case 1:
-		dev->irq = nile4_to_irq(NILE4_INT_INTA);
-		break;
-	    case 2:	/* slot 1 */
-		dev->irq = nile4_to_irq(NILE4_INT_INTA);
-		break;
-	    case 3:	/* slot 2 */
-		dev->irq = nile4_to_irq(NILE4_INT_INTB);
-		break;
-	    case 4:	/* slot 3 */
-		dev->irq = nile4_to_irq(NILE4_INT_INTC);
-		break;
-	    case 5:
-		/*
-		 * Fixup so the serial driver can use the UART
-		 */
-		dev->irq = nile4_to_irq(NILE4_INT_UART);
-		break;
-	    case 13:
-		dev->irq = nile4_to_irq(NILE4_INT_INTE);
-		break;
-	    default:
-		break;
+	pci_for_each_dev(dev) {
+		slot_num = PCI_SLOT(dev->devfn);
+		switch (slot_num) {
+		case 0:
+			dev->irq = nile4_to_irq(NILE4_INT_INTE);
+			break;
+		case 1:
+			dev->irq = nile4_to_irq(NILE4_INT_INTA);
+			break;
+		case 2:	/* slot 1 */
+			dev->irq = nile4_to_irq(NILE4_INT_INTA);
+			break;
+		case 3:	/* slot 2 */
+			dev->irq = nile4_to_irq(NILE4_INT_INTB);
+			break;
+		case 4:	/* slot 3 */
+			dev->irq = nile4_to_irq(NILE4_INT_INTC);
+			break;
+		case 5:
+			/*
+			 * Fixup so the serial driver can use the UART
+			 */
+			dev->irq = nile4_to_irq(NILE4_INT_UART);
+			break;
+		case 13:
+			dev->irq = nile4_to_irq(NILE4_INT_INTE);
+			break;
+		default:
+			break;
+		}
 	}
-    }
 }
 
 void __init pcibios_init(void)
 {
-    printk("PCI: Probing PCI hardware\n");
-    ioport_resource.end = 0x1ffffff;		/*  32 MB */
-    iomem_resource.end = 0x1fffffff;		/* 512 MB */
-    /* `ram' and `nile4' are requested through the Nile4 pci_dev */
-    request_resource(&iomem_resource, &ddb5074_resources.flash);
-    request_resource(&iomem_resource, &ddb5074_resources.isa_io);
-    request_resource(&iomem_resource, &ddb5074_resources.pci_io);
-    request_resource(&iomem_resource, &ddb5074_resources.isa_mem);
-    request_resource(&iomem_resource, &ddb5074_resources.pci_mem);
-    request_resource(&iomem_resource, &ddb5074_resources.boot);
-
-    pci_scan_bus(0, &nile4_pci_ops, NULL);
-    ddb5074_pci_fixup();
-    pci_assign_unassigned_resources();
-    pcibios_fixup_irqs();
+	printk("PCI: Probing PCI hardware\n");
+	ioport_resource.end = 0x1ffffff;	/*  32 MB */
+	iomem_resource.end = 0x1fffffff;	/* 512 MB */
+	/* `ram' and `nile4' are requested through the Nile4 pci_dev */
+	request_resource(&iomem_resource, &ddb5074_resources.flash);
+	request_resource(&iomem_resource, &ddb5074_resources.isa_io);
+	request_resource(&iomem_resource, &ddb5074_resources.pci_io);
+	request_resource(&iomem_resource, &ddb5074_resources.isa_mem);
+	request_resource(&iomem_resource, &ddb5074_resources.pci_mem);
+	request_resource(&iomem_resource, &ddb5074_resources.boot);
+
+	pci_scan_bus(0, &nile4_pci_ops, NULL);
+	ddb5074_pci_fixup();
+	pci_assign_unassigned_resources();
+	pcibios_fixup_irqs();
 }
 
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
-    bus->resource[1] = &ddb5074_resources.pci_mem;
+	bus->resource[1] = &ddb5074_resources.pci_mem;
 }
 
-char *pcibios_setup (char *str)
+char *pcibios_setup(char *str)
 {
-    return str;
+	return str;
 }
 
 void __init pcibios_update_irq(struct pci_dev *dev, int irq)
 {
-    pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
 void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus,
 				      struct pbus_set_ranges_data *ranges)
 {
-    ranges->io_start -= bus->resource[0]->start;
-    ranges->io_end -= bus->resource[0]->start;
-    ranges->mem_start -= bus->resource[1]->start;
-    ranges->mem_end -= bus->resource[1]->start;
+	ranges->io_start -= bus->resource[0]->start;
+	ranges->io_end -= bus->resource[0]->start;
+	ranges->mem_start -= bus->resource[1]->start;
+	ranges->mem_end -= bus->resource[1]->start;
 }
 
 int pcibios_enable_resources(struct pci_dev *dev)
@@ -323,15 +335,15 @@
 	 *  Don't touch the Nile 4
 	 */
 	if (dev->vendor == PCI_VENDOR_ID_NEC &&
-	    dev->device == PCI_DEVICE_ID_NEC_NILE4)
-	    return 0;
+	    dev->device == PCI_DEVICE_ID_NEC_NILE4) return 0;
 
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 	old_cmd = cmd;
-	for(idx=0; idx<6; idx++) {
+	for (idx = 0; idx < 6; idx++) {
 		r = &dev->resource[idx];
 		if (!r->start && r->end) {
-			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+			printk(KERN_ERR "PCI: Device %s not available because "
+			       "of resource collisions\n", dev->slot_name);
 			return -EINVAL;
 		}
 		if (r->flags & IORESOURCE_IO)
@@ -340,7 +352,8 @@
 			cmd |= PCI_COMMAND_MEMORY;
 	}
 	if (cmd != old_cmd) {
-		printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
+		printk("PCI: Enabling device %s (%04x -> %04x)\n",
+		       dev->slot_name, old_cmd, cmd);
 		pci_write_config_word(dev, PCI_COMMAND, cmd);
 	}
 	return 0;
@@ -348,7 +361,7 @@
 
 int pcibios_enable_device(struct pci_dev *dev)
 {
-    return pcibios_enable_resources(dev);
+	return pcibios_enable_resources(dev);
 }
 
 void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
@@ -359,18 +372,23 @@
 
 	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
 	if (resource < 6) {
-		reg = PCI_BASE_ADDRESS_0 + 4*resource;
+		reg = PCI_BASE_ADDRESS_0 + 4 * resource;
 	} else if (resource == PCI_ROM_RESOURCE) {
 		res->flags |= PCI_ROM_ADDRESS_ENABLE;
 		reg = dev->rom_base_reg;
 	} else {
-		/* Somebody might have asked allocation of a non-standard resource */
+		/*
+		 * Somebody might have asked allocation of a non-standard
+		 * resource
+		 */
 		return;
 	}
-	
+
 	pci_write_config_dword(dev, reg, new);
 	pci_read_config_dword(dev, reg, &check);
-	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+	if ((new ^ check) &
+	    ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
+	     PCI_BASE_ADDRESS_MEM_MASK)) {
 		printk(KERN_ERR "PCI: Error while updating region "
 		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
 		       new, check);
@@ -400,5 +418,4 @@
 }
 
 
-struct pci_fixup pcibios_fixups[] = {};
-
+struct pci_fixup pcibios_fixups[] = { };
diff -urN linux-2.4.4-pre3/arch/mips/ddb5074/prom.c linux/arch/mips/ddb5074/prom.c
--- linux-2.4.4-pre3/arch/mips/ddb5074/prom.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/prom.c	Mon Dec  3 22:35:22 2001
@@ -3,58 +3,32 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: prom.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
-
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/bootmem.h>
+
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
 
 
-char arcs_cmdline[CL_SIZE];
-
-extern char _end;
-
-#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_ALIGN(x)	(((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
+char arcs_cmdline[COMMAND_LINE_SIZE];
 
 void __init prom_init(const char *s)
 {
-    int i = 0;
-    unsigned long mem_size, free_start, free_end, start_pfn, bootmap_size;
+	int i = 0;
 
-//  _serinit();
+	if (s != (void *) -1)
+		while (*s && i < sizeof(arcs_cmdline) - 1)
+			arcs_cmdline[i++] = *s++;
+	arcs_cmdline[i] = '\0';
 
-    if (s != (void *)-1)
-	while (*s && i < sizeof(arcs_cmdline)-1)
-	    arcs_cmdline[i++] = *s++;
-    arcs_cmdline[i] = '\0';
-
-    mips_machgroup = MACH_GROUP_NEC_DDB;
-    mips_machtype = MACH_NEC_DDB5074;
-    /* 64 MB non-upgradable */
-    mem_size = 64 << 20;
-
-    free_start = PHYSADDR(PFN_ALIGN(&_end));
-    free_end = mem_size;
-    start_pfn = PFN_UP((unsigned long)&_end);
-
-    /* Register all the contiguous memory with the bootmem allocator
-       and free it.  Be careful about the bootmem freemap.  */
-    bootmap_size = init_bootmem(start_pfn, mem_size >> PAGE_SHIFT);
-
-    /* Free the entire available memory after the _end symbol.  */
-    free_start += bootmap_size;
-    free_bootmem(free_start, free_end-free_start);
-}
+	mips_machgroup = MACH_GROUP_NEC_DDB;
+	mips_machtype = MACH_NEC_DDB5074;
 
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
-{
+	/* 64 MB non-upgradable */
+	add_memory_region(0, 64 << 20, BOOT_MEM_RAM);
 }
 
 void __init prom_free_prom_memory(void)
diff -urN linux-2.4.4-pre3/arch/mips/ddb5074/setup.c linux/arch/mips/ddb5074/setup.c
--- linux-2.4.4-pre3/arch/mips/ddb5074/setup.c	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/ddb5074/setup.c	Mon Dec  3 22:35:22 2001
@@ -3,10 +3,7 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id: setup.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
-
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kbd_ll.h>
@@ -42,85 +39,83 @@
 extern struct ide_ops std_ide_ops;
 extern struct rtc_ops ddb_rtc_ops;
 
-static void (*back_to_prom)(void) = (void (*)(void))0xbfc00000;
+static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
 
 static void ddb_machine_restart(char *command)
 {
-    u32 t;
+	u32 t;
 
-    /* PCI cold reset */
-    t = nile4_in32(NILE4_PCICTRL+4);
-    t |= 0x40000000;
-    nile4_out32(NILE4_PCICTRL+4, t);
-    /* CPU cold reset */
-    t = nile4_in32(NILE4_CPUSTAT);
-    t |= 1;
-    nile4_out32(NILE4_CPUSTAT, t);
-    /* Call the PROM */
-    back_to_prom();
+	/* PCI cold reset */
+	t = nile4_in32(NILE4_PCICTRL + 4);
+	t |= 0x40000000;
+	nile4_out32(NILE4_PCICTRL + 4, t);
+	/* CPU cold reset */
+	t = nile4_in32(NILE4_CPUSTAT);
+	t |= 1;
+	nile4_out32(NILE4_CPUSTAT, t);
+	/* Call the PROM */
+	back_to_prom();
 }
 
 static void ddb_machine_halt(void)
 {
-    printk("DDB Vrc-5074 halted.\n");
-    do {} while (1);
+	printk("DDB Vrc-5074 halted.\n");
+	do {
+	} while (1);
 }
 
 static void ddb_machine_power_off(void)
 {
-    printk("DDB Vrc-5074 halted. Please turn off the power.\n");
-    do {} while (1);
+	printk("DDB Vrc-5074 halted. Please turn off the power.\n");
+	do {
+	} while (1);
 }
 
 extern void ddb_irq_setup(void);
 
-void (*board_time_init)(struct irqaction *irq);
+void (*board_time_init) (struct irqaction * irq);
 
 
 static void __init ddb_time_init(struct irqaction *irq)
 {
-    /* set the clock to 1 Hz */
-    nile4_out32(NILE4_T2CTRL, 1000000);
-    /* enable the General-Purpose Timer */
-    nile4_out32(NILE4_T2CTRL+4, 0x00000001);
-    /* reset timer */
-    nile4_out32(NILE4_T2CNTR, 0);
-    /* enable interrupt */
-    nile4_enable_irq(NILE4_INT_GPT);
-    i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
-    set_cp0_status(ST0_IM, IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
+	/* set the clock to 1 Hz */
+	nile4_out32(NILE4_T2CTRL, 1000000);
+	/* enable the General-Purpose Timer */
+	nile4_out32(NILE4_T2CTRL + 4, 0x00000001);
+	/* reset timer */
+	nile4_out32(NILE4_T2CNTR, 0);
+	/* enable interrupt */
+	nile4_enable_irq(NILE4_INT_GPT);
+	i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
+	change_cp0_status(ST0_IM,
+		          IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
 }
 
 void __init ddb_setup(void)
 {
-    extern int panic_timeout;
+	extern int panic_timeout;
 
-    irq_setup = ddb_irq_setup;
-    mips_io_port_base = NILE4_PCI_IO_BASE;
-    isa_slot_offset = NILE4_PCI_MEM_BASE;
-    request_region(0x00, 0x20, "dma1");
-    request_region(0x40, 0x20, "timer");
-    request_region(0x70, 0x10, "rtc");
-    request_region(0x80, 0x10, "dma page reg");
-    request_region(0xc0, 0x20, "dma2");
-    board_time_init = ddb_time_init;
-
-    _machine_restart = ddb_machine_restart;
-    _machine_halt = ddb_machine_halt;
-    _machine_power_off = ddb_machine_power_off;
+	irq_setup = ddb_irq_setup;
+	mips_io_port_base = NILE4_PCI_IO_BASE;
+	isa_slot_offset = NILE4_PCI_MEM_BASE;
+	request_region(0x00, 0x20, "dma1");
+	request_region(0x40, 0x20, "timer");
+	request_region(0x70, 0x10, "rtc");
+	request_region(0x80, 0x10, "dma page reg");
+	request_region(0xc0, 0x20, "dma2");
+	board_time_init = ddb_time_init;
+
+	_machine_restart = ddb_machine_restart;
+	_machine_halt = ddb_machine_halt;
+	_machine_power_off = ddb_machine_power_off;
 
 #ifdef CONFIG_BLK_DEV_IDE
-    ide_ops = &std_ide_ops;
+	ide_ops = &std_ide_ops;
 #endif
-    rtc_ops = &ddb_rtc_ops;
+	rtc_ops = &ddb_rtc_ops;
 
-    /* Reboot on panic */
-    panic_timeout = 180;
-}
-
-int __init page_is_ram(unsigned long pagenr)
-{
-    return 1;
+	/* Reboot on panic */
+	panic_timeout = 180;
 }
 
 
@@ -133,12 +128,12 @@
 #define NS16550_BASE		(NILE4_PCI_IO_BASE+0x03f8)
 static inline u8 ns16550_in(u32 reg)
 {
-    return *(volatile u8 *)(NS16550_BASE+reg);
+	return *(volatile u8 *) (NS16550_BASE + reg);
 }
 
 static inline void ns16550_out(u32 reg, u8 val)
 {
-    *(volatile u8 *)(NS16550_BASE+reg) = val;
+	*(volatile u8 *) (NS16550_BASE + reg) = val;
 }
 #endif
 
@@ -168,87 +163,84 @@
 void _serinit(void)
 {
 #if USE_NILE4_SERIAL
-    ns16550_out(NS16550_LCR, 0x80);
-    ns16550_out(NS16550_DLM, 0x00);
-    ns16550_out(NS16550_DLL, 0x36);	/* 9600 baud */
-    ns16550_out(NS16550_LCR, 0x00);
-    ns16550_out(NS16550_LCR, 0x03);
-    ns16550_out(NS16550_FCR, 0x47);
+	ns16550_out(NS16550_LCR, 0x80);
+	ns16550_out(NS16550_DLM, 0x00);
+	ns16550_out(NS16550_DLL, 0x36);	/* 9600 baud */
+	ns16550_out(NS16550_LCR, 0x00);
+	ns16550_out(NS16550_LCR, 0x03);
+	ns16550_out(NS16550_FCR, 0x47);
 #else
-    /* done by PMON */
+	/* done by PMON */
 #endif
 }
 
 void _putc(char c)
 {
-    while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
-    ns16550_out(NS16550_THR, c);
-    if (c == '\n') {
 	while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
-	ns16550_out(NS16550_THR, '\r');
-    }
+	ns16550_out(NS16550_THR, c);
+	if (c == '\n') {
+		while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
+		ns16550_out(NS16550_THR, '\r');
+	}
 }
 
 void _puts(const char *s)
 {
-    char c;
-    while ((c = *s++))
-	_putc(c);
+	char c;
+	while ((c = *s++))
+		_putc(c);
 }
 
 char _getc(void)
 {
-    while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
-    return ns16550_in(NS16550_RBR);
+	while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
+	return ns16550_in(NS16550_RBR);
 }
 
 int _testc(void)
 {
-    return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
+	return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
 }
 
 
-    /*
-     *  Hexadecimal 7-segment LED
-     */
-
+/*
+ *  Hexadecimal 7-segment LED
+ */
 void ddb5074_led_hex(int hex)
 {
-    outb(hex, 0x80);
+	outb(hex, 0x80);
 }
 
 
-    /*
-     *  LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
-     */
-
+/*
+ *  LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
+ */
 struct pci_dev *pci_pmu = NULL;
 
 void ddb5074_led_d2(int on)
 {
-    u8 t;
+	u8 t;
 
-    if (pci_pmu) {
-	pci_read_config_byte(pci_pmu, 0x7e, &t);
-	if (on)
-	    t &= 0x7f;
-	else
-	    t |= 0x80;
-	pci_write_config_byte(pci_pmu, 0x7e, t);
-    }
+	if (pci_pmu) {
+		pci_read_config_byte(pci_pmu, 0x7e, &t);
+		if (on)
+			t &= 0x7f;
+		else
+			t |= 0x80;
+		pci_write_config_byte(pci_pmu, 0x7e, t);
+	}
 }
 
 void ddb5074_led_d3(int on)
 {
-    u8 t;
+	u8 t;
 
-    if (pci_pmu) {
-	pci_read_config_byte(pci_pmu, 0x7e, &t);
-	if (on)
-	    t &= 0xbf;
-	else
-	    t |= 0x40;
-	pci_write_config_byte(pci_pmu, 0x7e, t);
-    }
+	if (pci_pmu) {
+		pci_read_config_byte(pci_pmu, 0x7e, &t);
+		if (on)
+			t &= 0xbf;
+		else
+			t |= 0x40;
+		pci_write_config_byte(pci_pmu, 0x7e, t);
+	}
 }
-
diff -urN linux-2.4.4-pre3/arch/mips/ddb5074/time.c linux/arch/mips/ddb5074/time.c
--- linux-2.4.4-pre3/arch/mips/ddb5074/time.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/ddb5074/time.c	Mon Dec  3 22:35:22 2001
@@ -3,33 +3,30 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  $Id*
  */
-
 #include <linux/init.h>
 #include <asm/mc146818rtc.h>
 
 static unsigned char ddb_rtc_read_data(unsigned long addr)
 {
-    outb_p(addr, RTC_PORT(0));
-    return inb_p(RTC_PORT(1));
+	outb_p(addr, RTC_PORT(0));
+
+	return inb_p(RTC_PORT(1));
 }
 
 static void ddb_rtc_write_data(unsigned char data, unsigned long addr)
 {
-    outb_p(addr, RTC_PORT(0));
-    outb_p(data, RTC_PORT(1));
+	outb_p(addr, RTC_PORT(0));
+	outb_p(data, RTC_PORT(1));
 }
 
 static int ddb_rtc_bcd_mode(void)
 {
-    return 1;
+	return 1;
 }
 
 struct rtc_ops ddb_rtc_ops = {
-    ddb_rtc_read_data,
-    ddb_rtc_write_data,
-    ddb_rtc_bcd_mode
+	ddb_rtc_read_data,
+	ddb_rtc_write_data,
+	ddb_rtc_bcd_mode
 };
-
diff -urN linux-2.4.4-pre3/arch/mips/ddb5476/Makefile linux/arch/mips/ddb5476/Makefile
--- linux-2.4.4-pre3/arch/mips/ddb5476/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/Makefile	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,23 @@
+#
+# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+O_TARGET = ddb5476.a
+
+obj-y				+= setup.o irq.o time.o prom.o pci.o \
+				   int-handler.o nile4.o
+obj-$(CONFIG_REMOTE_DEBUG)	+= dbg_io.o
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/ddb5476/dbg_io.c linux/arch/mips/ddb5476/dbg_io.c
--- linux-2.4.4-pre3/arch/mips/ddb5476/dbg_io.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/dbg_io.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,125 @@
+
+#include <linux/config.h>
+
+#if (defined(CONFIG_DDB5476) && defined(CONFIG_REMOTE_DEBUG))
+
+/* --- CONFIG --- */
+
+/* we need uint32 uint8 */
+/* #include "types.h" */
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+
+/* --- END OF CONFIG --- */
+
+#define         UART16550_BAUD_2400             2400
+#define         UART16550_BAUD_4800             4800
+#define         UART16550_BAUD_9600             9600
+#define         UART16550_BAUD_19200            19200
+#define         UART16550_BAUD_38400            38400
+#define         UART16550_BAUD_57600            57600
+#define         UART16550_BAUD_115200           115200
+
+#define         UART16550_PARITY_NONE           0
+#define         UART16550_PARITY_ODD            0x08
+#define         UART16550_PARITY_EVEN           0x18
+#define         UART16550_PARITY_MARK           0x28
+#define         UART16550_PARITY_SPACE          0x38
+
+#define         UART16550_DATA_5BIT             0x0
+#define         UART16550_DATA_6BIT             0x1
+#define         UART16550_DATA_7BIT             0x2
+#define         UART16550_DATA_8BIT             0x3
+
+#define         UART16550_STOP_1BIT             0x0
+#define         UART16550_STOP_2BIT             0x4
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+
+/* [jsun] we use the second serial port for kdb */
+#define         BASE                    0xa60002f8
+#define         MAX_BAUD                115200
+
+/* === END OF CONFIG === */
+
+/* register offset */
+#define         OFS_RCV_BUFFER          0
+#define         OFS_TRANS_HOLD          0
+#define         OFS_SEND_BUFFER         0
+#define         OFS_INTR_ENABLE         1
+#define         OFS_INTR_ID             2
+#define         OFS_DATA_FORMAT         3
+#define         OFS_LINE_CONTROL        3
+#define         OFS_MODEM_CONTROL       4
+#define         OFS_RS232_OUTPUT        4
+#define         OFS_LINE_STATUS         5
+#define         OFS_MODEM_STATUS        6
+#define         OFS_RS232_INPUT         6
+#define         OFS_SCRATCH_PAD         7
+
+#define         OFS_DIVISOR_LSB         0
+#define         OFS_DIVISOR_MSB         1
+
+
+/* memory-mapped read/write of the port */
+#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
+#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+	/* disable interrupts */
+	UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+	/* set up buad rate */
+	{
+		uint32 divisor;
+
+		/* set DIAB bit */
+		UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+
+		/* set divisor */
+		divisor = MAX_BAUD / baud;
+		UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+		UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
+
+		/* clear DIAB bit */
+		UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+	}
+
+	/* set data format */
+	UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		debugInit(UART16550_BAUD_38400,
+			  UART16550_DATA_8BIT,
+			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+	}
+
+	while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+	return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+	if (!remoteDebugInitialized) {
+		remoteDebugInitialized = 1;
+		debugInit(UART16550_BAUD_9600,
+			  UART16550_DATA_8BIT,
+			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
+	}
+
+	while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
+	UART16550_WRITE(OFS_SEND_BUFFER, byte);
+	return 1;
+}
+
+#endif
diff -urN linux-2.4.4-pre3/arch/mips/ddb5476/int-handler.S linux/arch/mips/ddb5476/int-handler.S
--- linux-2.4.4-pre3/arch/mips/ddb5476/int-handler.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/int-handler.S	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,125 @@
+/*
+ *  arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
+ *
+ *  Based on arch/mips/sgi/kernel/indyIRQ.S
+ *
+ *  Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ *    common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ *    would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ *    between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the INDY look basically (barring software IRQs
+ * which we don't use at all) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Local IRQ level zero
+ *             3        Local IRQ level one
+ *             4        8254 Timer zero
+ *             5        8254 Timer one
+ *             6        Bus Error
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ *                  Local IRQ zero
+ *                  Local IRQ one
+ *                  Bus Error
+ *                  8254 Timer zero
+ * Lowest  ----     8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+	.text
+	.set	noreorder
+	.set	noat
+	.align	5
+	NESTED(ddbIRQ, PT_SIZE, sp)
+	SAVE_ALL
+	CLI
+	.set	at
+	mfc0	s1, CP0_CAUSE		# get irq mask
+
+#if 1
+	mfc0	t2,CP0_STATUS		# get enabled interrupts
+	and	s0, s1, t2		# isolate allowed ones
+#endif
+	/* First we check for r4k counter/timer IRQ. */
+	andi	a0, s0, CAUSEF_IP2	# delay slot, check local level zero
+	beq	a0, zero, 1f
+	 andi	a0, s0, CAUSEF_IP3	# delay slot, check local level one
+
+	/* Wheee, local level zero interrupt. */
+	jal	ddb_local0_irqdispatch
+	 move	a0, sp			# delay slot
+
+	j	ret_from_irq
+	 nop				# delay slot
+
+1:
+	beq	a0, zero, 1f
+	 andi	a0, s0, CAUSEF_IP6	# delay slot, check bus error
+
+	/* Wheee, local level one interrupt. */
+	move	a0, sp
+	jal	ddb_local1_irqdispatch
+	 nop
+
+	j	ret_from_irq
+	 nop
+
+1:
+	beq	a0, zero, 1f
+	 nop
+
+	/* Wheee, an asynchronous bus error... */
+	move	a0, sp
+	jal	ddb_buserror_irq
+	 nop
+
+	j	ret_from_irq
+	 nop
+
+1:
+	/* Here by mistake?  This is possible, what can happen
+	 * is that by the time we take the exception the IRQ
+	 * pin goes low, so just leave if this is the case.
+	 */
+	andi	a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
+	beq	a0, zero, 1f
+
+	/* Must be one of the 8254 timers... */
+	move	a0, sp
+	jal	ddb_8254timer_irq
+	 nop
+1:
+	/* phamtom interrupt */
+	move 	a0, s1
+	jal	ddb_phantom_irq
+	nop
+	j	ret_from_irq
+	nop
+	END(ddbIRQ)
diff -urN linux-2.4.4-pre3/arch/mips/ddb5476/irq.c linux/arch/mips/ddb5476/irq.c
--- linux-2.4.4-pre3/arch/mips/ddb5476/irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/irq.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,251 @@
+/*
+ *  arch/mips/ddb5476/irq.c -- NEC DDB Vrc-5476 interrupt routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+#include <asm/nile4.h>
+
+extern void __init i8259_init(void);
+extern void i8259_disable_irq(unsigned int irq_nr);
+extern void i8259_enable_irq(unsigned int irq_nr);
+
+extern asmlinkage void ddbIRQ(void);
+extern asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs);
+extern asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
+
+
+void no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+}
+
+
+#define M1543_PNP_CONFIG	0x03f0	/* PnP Config Port */
+#define M1543_PNP_INDEX		0x03f0	/* PnP Index Port */
+#define M1543_PNP_DATA		0x03f1	/* PnP Data Port */
+
+#define M1543_PNP_ALT_CONFIG	0x0370	/* Alternative PnP Config Port */
+#define M1543_PNP_ALT_INDEX	0x0370	/* Alternative PnP Index Port */
+#define M1543_PNP_ALT_DATA	0x0371	/* Alternative PnP Data Port */
+
+#define M1543_INT1_MASTER_CTRL	0x0020	/* INT_1 (master) Control Register */
+#define M1543_INT1_MASTER_MASK	0x0021	/* INT_1 (master) Mask Register */
+
+#define M1543_INT1_SLAVE_CTRL	0x00a0	/* INT_1 (slave) Control Register */
+#define M1543_INT1_SLAVE_MASK	0x00a1	/* INT_1 (slave) Mask Register */
+
+#define M1543_INT1_MASTER_ELCR	0x04d0	/* INT_1 (master) Edge/Level Control */
+#define M1543_INT1_SLAVE_ELCR	0x04d1	/* INT_1 (slave) Edge/Level Control */
+
+static struct {
+	struct resource m1543_config;
+	struct resource pic_elcr;
+} m1543_ioport = {
+	{ "M1543 config", M1543_PNP_CONFIG, M1543_PNP_CONFIG + 1,
+	  IORESOURCE_BUSY},
+	{ "pic ELCR", M1543_INT1_MASTER_ELCR, M1543_INT1_MASTER_ELCR + 1,
+	  IORESOURCE_BUSY}
+};
+
+static void m1543_irq_setup(void)
+{
+	/*
+	 *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
+	 *  the possible IO sources in the M1543 are in use by us.  We will
+	 *  use the following mapping:
+	 *
+	 *      IRQ1  - keyboard (default set by M1543)
+	 *      IRQ3  - reserved for UART B (default set by M1543) (note that
+	 *              the schematics for the DDB Vrc-5476 board seem to 
+	 *              indicate that IRQ3 is connected to the DS1386 
+	 *              watchdog timer interrupt output so we might have 
+	 *              a conflict)
+	 *      IRQ4  - reserved for UART A (default set by M1543)
+	 *      IRQ5  - parallel (default set by M1543)
+	 *      IRQ8  - DS1386 time of day (RTC) interrupt
+	 *      IRQ9  - USB (hardwired in ddb_setup)
+	 *      IRQ10 - PMU (hardwired in ddb_setup)
+	 *      IRQ12 - mouse
+	 *      IRQ14,15 - IDE controller (need to be confirmed, jsun)
+	 */
+
+	/*
+	 *  Assing mouse interrupt to IRQ12 
+	 */
+
+	/* Enter configuration mode */
+	outb(0x51, M1543_PNP_CONFIG);
+	outb(0x23, M1543_PNP_CONFIG);
+
+	/* Select logical device 7 (Keyboard) */
+	outb(0x07, M1543_PNP_INDEX);
+	outb(0x07, M1543_PNP_DATA);
+
+	/* Select IRQ12 */
+	outb(0x72, M1543_PNP_INDEX);
+	outb(0x0c, M1543_PNP_DATA);
+
+	/* Leave configration mode */
+	outb(0xbb, M1543_PNP_CONFIG);
+
+
+	/* Initialize the 8259 PIC in the M1543 */
+	i8259_init();
+
+	/* Enable the interrupt cascade from M1543 */
+	nile4_enable_irq(NILE4_INT_INTC);
+
+	/* request io ports */
+	if (request_resource(&ioport_resource, &m1543_ioport.m1543_config)
+	    || request_resource(&ioport_resource, &m1543_ioport.pic_elcr)) {
+		printk("m1543_irq_setup : requesting io ports failed.\n");
+		for (;;);
+	}
+}
+
+static void nile4_irq_setup(void)
+{
+	int i;
+
+	/* Map all interrupts to CPU int #0 */
+	nile4_map_irq_all(0);
+
+	/* PCI INTA#-E# must be level triggered */
+	nile4_set_pci_irq_level_or_edge(0, 1);
+	nile4_set_pci_irq_level_or_edge(1, 1);
+	nile4_set_pci_irq_level_or_edge(2, 1);
+	nile4_set_pci_irq_level_or_edge(3, 1);
+
+	/* PCI INTA#, B#, D# must be active low, INTC# must be active high */
+	nile4_set_pci_irq_polarity(0, 0);
+	nile4_set_pci_irq_polarity(1, 0);
+	nile4_set_pci_irq_polarity(2, 1);
+	nile4_set_pci_irq_polarity(3, 0);
+
+	for (i = 0; i < 16; i++)
+		nile4_clear_irq(i);
+
+	/* Enable CPU int #0 */
+	nile4_enable_irq_output(0);
+
+	/* memory resource acquire in ddb_setup */
+}
+
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL };
+
+
+void disable_irq(unsigned int irq_nr)
+{
+	if (is_i8259_irq(irq_nr))
+		i8259_disable_irq(irq_nr);
+	else
+		nile4_disable_irq(irq_to_nile4(irq_nr));
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+	if (is_i8259_irq(irq_nr))
+		i8259_enable_irq(irq_nr);
+	else
+		nile4_enable_irq(irq_to_nile4(irq_nr));
+}
+
+int table[16] = { 0, };
+
+void ddb_local0_irqdispatch(struct pt_regs *regs)
+{
+	u32 mask;
+	int nile4_irq;
+#if 0
+	volatile static int nesting = 0;
+	if (nesting++ == 0)
+		ddb5476_led_d3(1);
+	ddb5476_led_hex(nesting < 16 ? nesting : 15);
+#endif
+
+	mask = nile4_get_irq_stat(0);
+	nile4_clear_irq_mask(mask);
+
+	/* Handle the timer interrupt first */
+	if (mask & (1 << NILE4_INT_GPT)) {
+		nile4_disable_irq(NILE4_INT_GPT);
+		do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
+		nile4_enable_irq(NILE4_INT_GPT);
+		mask &= ~(1 << NILE4_INT_GPT);
+	}
+	for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
+		if (mask & 1) {
+			nile4_disable_irq(nile4_irq);
+			if (nile4_irq == NILE4_INT_INTC) {
+				int i8259_irq = nile4_i8259_iack();
+				i8259_do_irq(i8259_irq, regs);
+			} else {
+				do_IRQ(nile4_to_irq(nile4_irq), regs);
+			}
+			nile4_enable_irq(nile4_irq);
+		}
+#if 0
+	if (--nesting == 0)
+		ddb5476_led_d3(0);
+	ddb5476_led_hex(nesting < 16 ? nesting : 15);
+#endif
+}
+
+void ddb_local1_irqdispatch(void)
+{
+	printk("ddb_local1_irqdispatch called\n");
+}
+
+void ddb_buserror_irq(void)
+{
+	printk("ddb_buserror_irq called\n");
+}
+
+void ddb_8254timer_irq(void)
+{
+	printk("ddb_8254timer_irq called\n");
+}
+
+void ddb_phantom_irq(unsigned long cause)
+{
+	printk("phantom interrupts detected : \n");
+	printk("\tcause \t\t0x%08x\n", cause);
+	printk("\tcause reg\t0x%08x\n",
+	       read_32bit_cp0_register(CP0_CAUSE));
+	printk("\tstatus reg\t0x%08x\n",
+	       read_32bit_cp0_register(CP0_STATUS));
+}
+
+void __init ddb_irq_setup(void)
+{
+#ifdef CONFIG_REMOTE_DEBUG
+	printk("Wait for gdb client connection ...\n");
+	set_debug_traps();
+	breakpoint();		/* you may move this line to whereever you want :-) */
+#endif
+	i8259_setup_irq(2, &irq2);
+
+	nile4_irq_setup();
+	m1543_irq_setup();
+
+	/* we pin #0 - #4 (no internal timer) */
+	change_cp0_status(ST0_IM,
+	                  IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
+
+	set_except_vector(0, ddbIRQ);
+}
diff -urN linux-2.4.4-pre3/arch/mips/ddb5476/nile4.c linux/arch/mips/ddb5476/nile4.c
--- linux-2.4.4-pre3/arch/mips/ddb5476/nile4.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/nile4.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,293 @@
+/*
+ *  arch/mips/ddb5074/nile4.c -- NEC Vrc-5074 Nile 4 support routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/nile4.h>
+
+
+/*
+ *  Physical Device Address Registers
+ *
+ *  Note: 32 bit addressing only!
+ */
+void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width,
+		    int on_memory_bus, int visible)
+{
+	u32 maskbits;
+	u32 widthbits;
+
+	if (pdar > NILE4_BOOTCS || (pdar & 7)) {
+		printk("nile4_set_pdar: invalid pdar %d\n", pdar);
+		return;
+	}
+	if (pdar == NILE4_INTCS && size != 0x00200000) {
+		printk("nile4_set_pdar: INTCS size must be 2 MB\n");
+		return;
+	}
+	switch (size) {
+#if 0				/* We don't support 4 GB yet */
+	case 0x100000000:	/* 4 GB */
+		maskbits = 4;
+		break;
+#endif
+	case 0x80000000:	/* 2 GB */
+		maskbits = 5;
+		break;
+	case 0x40000000:	/* 1 GB */
+		maskbits = 6;
+		break;
+	case 0x20000000:	/* 512 MB */
+		maskbits = 7;
+		break;
+	case 0x10000000:	/* 256 MB */
+		maskbits = 8;
+		break;
+	case 0x08000000:	/* 128 MB */
+		maskbits = 9;
+		break;
+	case 0x04000000:	/* 64 MB */
+		maskbits = 10;
+		break;
+	case 0x02000000:	/* 32 MB */
+		maskbits = 11;
+		break;
+	case 0x01000000:	/* 16 MB */
+		maskbits = 12;
+		break;
+	case 0x00800000:	/* 8 MB */
+		maskbits = 13;
+		break;
+	case 0x00400000:	/* 4 MB */
+		maskbits = 14;
+		break;
+	case 0x00200000:	/* 2 MB */
+		maskbits = 15;
+		break;
+	case 0:		/* OFF */
+		maskbits = 0;
+		break;
+	default:
+		printk("nile4_set_pdar: unsupported size %p\n",
+		       (void *) size);
+		return;
+	}
+	switch (width) {
+	case 8:
+		widthbits = 0;
+		break;
+	case 16:
+		widthbits = 1;
+		break;
+	case 32:
+		widthbits = 2;
+		break;
+	case 64:
+		widthbits = 3;
+		break;
+	default:
+		printk("nile4_set_pdar: unsupported width %d\n", width);
+		return;
+	}
+	nile4_out32(pdar, maskbits | (on_memory_bus ? 0x10 : 0) |
+		    (visible ? 0x20 : 0) | (widthbits << 6) |
+		    (phys & 0xffe00000));
+	nile4_out32(pdar + 4, 0);
+	/*
+	 * When programming a PDAR, the register should be read immediately
+	 * after writing it. This ensures that address decoders are properly
+	 * configured.
+	 */
+	nile4_in32(pdar);
+	nile4_in32(pdar + 4);
+}
+
+
+/*
+ *  PCI Master Registers
+ *
+ *  Note: 32 bit addressing only!
+ */
+void nile4_set_pmr(u32 pmr, u32 type, u32 addr)
+{
+	if (pmr != NILE4_PCIINIT0 && pmr != NILE4_PCIINIT1) {
+		printk("nile4_set_pmr: invalid pmr %d\n", pmr);
+		return;
+	}
+	switch (type) {
+	case NILE4_PCICMD_IACK:	/* PCI Interrupt Acknowledge */
+	case NILE4_PCICMD_IO:	/* PCI I/O Space */
+	case NILE4_PCICMD_MEM:	/* PCI Memory Space */
+	case NILE4_PCICMD_CFG:	/* PCI Configuration Space */
+		break;
+	default:
+		printk("nile4_set_pmr: invalid type %d\n", type);
+		return;
+	}
+	nile4_out32(pmr, (type << 1) | 0x10 | (addr & 0xffe00000));
+	nile4_out32(pmr + 4, 0);
+}
+
+
+/*
+ *  Interrupt Programming
+ */
+void nile4_map_irq(int nile4_irq, int cpu_irq)
+{
+	u32 offset, t;
+
+	offset = NILE4_INTCTRL;
+	if (nile4_irq >= 8) {
+		offset += 4;
+		nile4_irq -= 8;
+	}
+	t = nile4_in32(offset);
+	t &= ~(7 << (nile4_irq * 4));
+	t |= cpu_irq << (nile4_irq * 4);
+	nile4_out32(offset, t);
+}
+
+void nile4_map_irq_all(int cpu_irq)
+{
+	u32 all, t;
+
+	all = cpu_irq;
+	all |= all << 4;
+	all |= all << 8;
+	all |= all << 16;
+	t = nile4_in32(NILE4_INTCTRL);
+	t &= 0x88888888;
+	t |= all;
+	nile4_out32(NILE4_INTCTRL, t);
+	t = nile4_in32(NILE4_INTCTRL + 4);
+	t &= 0x88888888;
+	t |= all;
+	nile4_out32(NILE4_INTCTRL + 4, t);
+}
+
+void nile4_enable_irq(int nile4_irq)
+{
+	u32 offset, t;
+
+	offset = NILE4_INTCTRL;
+	if (nile4_irq >= 8) {
+		offset += 4;
+		nile4_irq -= 8;
+	}
+	t = nile4_in32(offset);
+	t |= 8 << (nile4_irq * 4);
+	nile4_out32(offset, t);
+}
+
+void nile4_disable_irq(int nile4_irq)
+{
+	u32 offset, t;
+
+	offset = NILE4_INTCTRL;
+	if (nile4_irq >= 8) {
+		offset += 4;
+		nile4_irq -= 8;
+	}
+	t = nile4_in32(offset);
+	t &= ~(8 << (nile4_irq * 4));
+	nile4_out32(offset, t);
+}
+
+void nile4_disable_irq_all(void)
+{
+	nile4_out32(NILE4_INTCTRL, 0);
+	nile4_out32(NILE4_INTCTRL + 4, 0);
+}
+
+u16 nile4_get_irq_stat(int cpu_irq)
+{
+	return nile4_in16(NILE4_INTSTAT0 + cpu_irq * 2);
+}
+
+void nile4_enable_irq_output(int cpu_irq)
+{
+	u32 t;
+
+	t = nile4_in32(NILE4_INTSTAT1 + 4);
+	t |= 1 << (16 + cpu_irq);
+	nile4_out32(NILE4_INTSTAT1, t);
+}
+
+void nile4_disable_irq_output(int cpu_irq)
+{
+	u32 t;
+
+	t = nile4_in32(NILE4_INTSTAT1 + 4);
+	t &= ~(1 << (16 + cpu_irq));
+	nile4_out32(NILE4_INTSTAT1, t);
+}
+
+void nile4_set_pci_irq_polarity(int pci_irq, int high)
+{
+	u32 t;
+
+	t = nile4_in32(NILE4_INTPPES);
+	if (high)
+		t &= ~(1 << (pci_irq * 2));
+	else
+		t |= 1 << (pci_irq * 2);
+	nile4_out32(NILE4_INTPPES, t);
+}
+
+void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
+{
+	u32 t;
+
+	t = nile4_in32(NILE4_INTPPES);
+	if (level)
+		t |= 2 << (pci_irq * 2);
+	else
+		t &= ~(2 << (pci_irq * 2));
+	nile4_out32(NILE4_INTPPES, t);
+}
+
+void nile4_clear_irq(int nile4_irq)
+{
+	nile4_out32(NILE4_INTCLR, 1 << nile4_irq);
+}
+
+void nile4_clear_irq_mask(u32 mask)
+{
+	nile4_out32(NILE4_INTCLR, mask);
+}
+
+u8 nile4_i8259_iack(void)
+{
+	u8 irq;
+
+	/* Set window 0 for interrupt acknowledge */
+	nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IACK, 0);
+	irq = *(volatile u8 *) NILE4_PCI_IACK_BASE;
+	/* Set window 0 for PCI I/O space */
+	nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
+	return irq;
+}
+
+#if 0
+void nile4_dump_irq_status(void)
+{
+	printk("CPUSTAT = %p:%p\n", (void *) nile4_in32(NILE4_CPUSTAT + 4),
+	       (void *) nile4_in32(NILE4_CPUSTAT));
+	printk("INTCTRL = %p:%p\n", (void *) nile4_in32(NILE4_INTCTRL + 4),
+	       (void *) nile4_in32(NILE4_INTCTRL));
+	printk("INTSTAT0 = %p:%p\n",
+	       (void *) nile4_in32(NILE4_INTSTAT0 + 4),
+	       (void *) nile4_in32(NILE4_INTSTAT0));
+	printk("INTSTAT1 = %p:%p\n",
+	       (void *) nile4_in32(NILE4_INTSTAT1 + 4),
+	       (void *) nile4_in32(NILE4_INTSTAT1));
+	printk("INTCLR = %p:%p\n", (void *) nile4_in32(NILE4_INTCLR + 4),
+	       (void *) nile4_in32(NILE4_INTCLR));
+	printk("INTPPES = %p:%p\n", (void *) nile4_in32(NILE4_INTPPES + 4),
+	       (void *) nile4_in32(NILE4_INTPPES));
+}
+#endif
diff -urN linux-2.4.4-pre3/arch/mips/ddb5476/pci.c linux/arch/mips/ddb5476/pci.c
--- linux-2.4.4-pre3/arch/mips/ddb5476/pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/pci.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,495 @@
+/*
+ *  arch/mips/ddb5476/pci.c -- NEC DDB Vrc-5074 PCI access routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Albert Dorofeev <albert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+
+#include <asm-mips/nile4.h>
+
+
+static u32 nile4_pre_pci_access0(int slot_num)
+{
+	u32 pci_addr = 0;
+	u32 virt_addr = NILE4_PCI_CFG_BASE;
+
+	/* work around the bug for Vrc5476 */
+	if (slot_num == 13)
+		return NILE4_BASE + NILE4_PCI_BASE;
+
+	/* Set window 1 address 08000000 - 32 bit - 128 MB (PCI config space) */
+	nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x08000000, 32, 0,
+		       0);
+
+	// [jsun] we start scanning from addr:10, 
+	// with 128M we can go up to addr:26 (slot 16)
+	if (slot_num <= 16) {
+		virt_addr += 0x00000400 << slot_num;
+	} else {
+		/* for high slot, we have to set higher PCI base addr */
+		pci_addr = 0x00000400 << slot_num;
+	}
+	nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, pci_addr);
+	return virt_addr;
+}
+
+static void nile4_post_pci_access0(void)
+{
+	/*
+	 * Set window 1 back to address 08000000 - 32 bit - 128 MB
+	 * (PCI IO space)
+	 */
+	nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE),
+		       0x08000000, 32, 1, 1);
+	// nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0);
+	nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0x08000000);
+}
+
+
+static int nile4_pci_read_config_dword(struct pci_dev *dev,
+				       int where, u32 * val)
+{
+	int slot_num, func_num;
+	u32 base;
+	u32 addr;
+
+	/*
+	 *  Do we need to generate type 1 configure transaction?
+	 */
+	if (dev->bus->number) {
+		/* FIXME - not working yet */
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+		/*
+		 * the largest type 1 configuration addr is 16M, < 256M
+		 * config space
+		 */
+		slot_num = 0;
+		addr =
+		    (dev->bus->number << 16) | (dev->devfn <
+						8) | where | 1;
+	} else {
+		slot_num = PCI_SLOT(dev->devfn);
+		func_num = PCI_FUNC(dev->devfn);
+		addr = (func_num << 8) + where;
+	}
+
+	base = nile4_pre_pci_access0(slot_num);
+	*val = *(volatile u32 *) (base + addr);
+	nile4_post_pci_access0();
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_write_config_dword(struct pci_dev *dev, int where,
+					u32 val)
+{
+	int slot_num, func_num;
+	u32 base;
+	u32 addr;
+
+	/*
+	 *  Do we need to generate type 1 configure transaction?
+	 */
+	if (dev->bus->number) {
+		/* FIXME - not working yet */
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+
+		/* the largest type 1 configuration addr is 16M, < 256M config space */
+		slot_num = 0;
+		addr =
+		    (dev->bus->number << 16) | (dev->devfn <
+						8) | where | 1;
+	} else {
+		slot_num = PCI_SLOT(dev->devfn);
+		func_num = PCI_FUNC(dev->devfn);
+		addr = (func_num << 8) + where;
+	}
+
+	base = nile4_pre_pci_access0(slot_num);
+	*(volatile u32 *) (base + addr) = val;
+	nile4_post_pci_access0();
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_read_config_word(struct pci_dev *dev, int where,
+				      u16 * val)
+{
+	int status;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where & ~3, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 2)
+		result >>= 16;
+	*val = result & 0xffff;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_read_config_byte(struct pci_dev *dev, int where,
+				      u8 * val)
+{
+	int status;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where & ~3, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 1)
+		result >>= 8;
+	if (where & 2)
+		result >>= 16;
+	*val = result & 0xff;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int nile4_pci_write_config_word(struct pci_dev *dev, int where,
+				       u16 val)
+{
+	int status, shift = 0;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where & ~3, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 2)
+		shift += 16;
+	result &= ~(0xffff << shift);
+	result |= val << shift;
+	return nile4_pci_write_config_dword(dev, where & ~3, result);
+}
+
+static int nile4_pci_write_config_byte(struct pci_dev *dev, int where,
+				       u8 val)
+{
+	int status, shift = 0;
+	u32 result;
+
+	status = nile4_pci_read_config_dword(dev, where & ~3, &result);
+	if (status != PCIBIOS_SUCCESSFUL)
+		return status;
+	if (where & 2)
+		shift += 16;
+	if (where & 1)
+		shift += 8;
+	result &= ~(0xff << shift);
+	result |= val << shift;
+	return nile4_pci_write_config_dword(dev, where & ~3, result);
+}
+
+struct pci_ops nile4_pci_ops = {
+	nile4_pci_read_config_byte,
+	nile4_pci_read_config_word,
+	nile4_pci_read_config_dword,
+	nile4_pci_write_config_byte,
+	nile4_pci_write_config_word,
+	nile4_pci_write_config_dword
+};
+
+struct {
+	struct resource ram;
+	struct resource flash;
+	struct resource isa_io;
+	struct resource pci_io;
+	struct resource isa_mem;
+	struct resource pci_mem;
+	struct resource nile4;
+	struct resource boot;
+} ddb5476_resources = {
+	// { "RAM", 0x00000000, 0x03ffffff, IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
+	{
+	"RAM", 0x00000000, 0x03ffffff, IORESOURCE_MEM}, {
+	"Flash ROM", 0x04000000, 0x043fffff}, {
+	"Nile4 ISA I/O", 0x06000000, 0x060fffff}, {
+	"Nile4 PCI I/O", 0x06100000, 0x07ffffff}, {
+	"Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM}, {
+	"Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM},
+	    // { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff, IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
+	{
+	"Nile4 ctrl", 0x1fa00000, 0x1fbfffff, IORESOURCE_MEM}, {
+	"Boot ROM", 0x1fc00000, 0x1fffffff}
+};
+
+struct resource M5229_resources[5] = {
+	{"M5229 BAR0", 0x1f0, 0x1f3, IORESOURCE_IO},
+	{"M5229 BAR1", 0x3f4, 0x3f7, IORESOURCE_IO},
+	{"M5229 BAR2", 0x170, 0x173, IORESOURCE_IO},
+	{"M5229 BAR3", 0x374, 0x377, IORESOURCE_IO},
+	{"M5229 BAR4", 0xf000, 0xf00f, IORESOURCE_IO}
+};
+
+static void __init ddb5476_pci_fixup(void)
+{
+	struct pci_dev *dev;
+
+	pci_for_each_dev(dev) {
+		if (dev->vendor == PCI_VENDOR_ID_NEC &&
+		    dev->device == PCI_DEVICE_ID_NEC_VRC5476) {
+			/*
+			 * The first 64-bit PCI base register should point to
+			 * the Nile4 control registers. Unfortunately this
+			 * isn't the case, so we fix it ourselves. This allows
+			 * the serial driver to find the UART.
+			 */
+			dev->resource[0] = ddb5476_resources.nile4;
+			request_resource(&iomem_resource,
+					 &dev->resource[0]);
+			/*
+			 * The second 64-bit PCI base register points to the
+			 * first memory bank. Unfortunately the address is
+			 * wrong, so we fix it (again).
+			 */
+
+			/* [jsun] We cannot request the resource anymore,
+			 * because kernel/setup.c has already reserved "System 
+			 * RAM" resource at the same spot.  
+			 * The fundamental problem here is that PCI host 
+			 * controller should not put system RAM mapping in BAR
+			 * and make subject to PCI resource assignement.
+			 * Current fix is a total hack.  We set parent to 1 so
+                         * so that PCI resource assignement code is fooled to 
+                         * think the resource is assigned, and will not attempt
+                         * to mess with it.
+			 */
+			dev->resource[2] = ddb5476_resources.ram;
+			if (request_resource(&iomem_resource,
+			                     &dev->resource[2]) ) {
+				dev->resource[2].parent = 0x1;
+                        }
+
+		} else if (dev->vendor == PCI_VENDOR_ID_AL
+			   && dev->device == PCI_DEVICE_ID_AL_M7101) {
+			/*
+			 * It's nice to have the LEDs on the GPIO pins
+			 * available for debugging
+			 */
+			extern struct pci_dev *pci_pmu;
+			u8 t8;
+
+			pci_pmu = dev;	/* for LEDs D2 and D3 */
+			/* Program the lines for LEDs D2 and D3 to output */
+			nile4_pci_read_config_byte(dev, 0x7d, &t8);
+			t8 |= 0xc0;
+			nile4_pci_write_config_byte(dev, 0x7d, t8);
+			/* Turn LEDs D2 and D3 off */
+			nile4_pci_read_config_byte(dev, 0x7e, &t8);
+			t8 |= 0xc0;
+			nile4_pci_write_config_byte(dev, 0x7e, t8);
+		} else if (dev->vendor == PCI_VENDOR_ID_AL &&
+			   dev->device == 0x5229) {
+			int i;
+			for (i = 0; i < 5; i++) {
+				dev->resource[i] = M5229_resources[i];
+				request_resource(&ioport_resource,
+						 &dev->resource[i]);
+			}
+		}
+	}
+}
+
+static void __init pcibios_fixup_irqs(void)
+{
+	struct pci_dev *dev;
+	int slot_num;
+
+	pci_for_each_dev(dev) {
+		slot_num = PCI_SLOT(dev->devfn);
+		switch (slot_num) {
+		case 3:	/* re-programmed to USB */
+			dev->irq = 9;	/* hard-coded; see irq.c */
+			break;
+		case 4:	/* re-programmed to PMU */
+			dev->irq = 10;	/* hard-coded; see irq.c */
+			break;
+		case 6:	/* on-board pci-pci bridge */
+			dev->irq = 0xff;
+			break;
+		case 7:	/* on-board ether */
+			dev->irq = nile4_to_irq(NILE4_INT_INTB);
+			break;
+		case 8:	/* ISA-PCI bridge  */
+			dev->irq = nile4_to_irq(NILE4_INT_INTC);
+			break;
+		case 9:	/* ext slot #3 */
+			dev->irq = nile4_to_irq(NILE4_INT_INTD);
+			break;
+		case 10:	/* ext slot #4 */
+			dev->irq = nile4_to_irq(NILE4_INT_INTA);
+			break;
+		case 13:	/* Vrc5476 */
+			dev->irq = 0xff;
+			break;
+		case 14:	/* HD controller, M5229 */
+			dev->irq = 14;
+			break;
+		default:
+			printk
+			    ("JSUN : in pcibios_fixup_irqs - unkown slot %d\n",
+			     slot_num);
+			panic
+			    ("JSUN : in pcibios_fixup_irqs - unkown slot.\n");
+		}
+	}
+}
+
+void __init pcibios_init(void)
+{
+	printk("PCI: Emulate bios initialization \n");
+	/* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */
+	*(long *) (NILE4_BASE + NILE4_BAR0) = 0x8;
+
+	printk("PCI: Probing PCI hardware\n");
+	ioport_resource.end = 0x1ffffff;	/*  32 MB */
+	iomem_resource.end = 0x1fffffff;	/* 512 MB */
+
+	/* `ram' and `nile4' are requested through the Nile4 pci_dev */
+	request_resource(&iomem_resource, &ddb5476_resources.flash);
+	request_resource(&iomem_resource, &ddb5476_resources.isa_io);
+	request_resource(&iomem_resource, &ddb5476_resources.pci_io);
+	request_resource(&iomem_resource, &ddb5476_resources.isa_mem);
+	request_resource(&iomem_resource, &ddb5476_resources.pci_mem);
+	request_resource(&iomem_resource, &ddb5476_resources.boot);
+
+	pci_scan_bus(0, &nile4_pci_ops, NULL);
+	ddb5476_pci_fixup();
+	pci_assign_unassigned_resources();
+	pcibios_fixup_irqs();
+}
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+	/* [jsun] we don't know how to fix sub-buses yet */
+	if (bus->number == 0) {
+		bus->resource[1] = &ddb5476_resources.pci_mem;
+	}
+}
+
+char *pcibios_setup(char *str)
+{
+	return str;
+}
+
+void __init pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus,
+				      struct pbus_set_ranges_data *ranges)
+{
+	/*
+	 * our caller figure out range by going through the dev structures.  
+	 * I guess this is the place to fix things up if the bus is using a 
+	 * different view of the addressing space.
+	 */
+
+#if 0	/*  original DDB5074 code */
+	   if (bus->number == 0) {
+	   ranges->io_start -= bus->resource[0]->start;
+	   ranges->io_end -= bus->resource[0]->start;
+	   ranges->mem_start -= bus->resource[1]->start;
+	   ranges->mem_end -= bus->resource[1]->start;
+	   }
+#endif
+}
+
+int pcibios_enable_resources(struct pci_dev *dev)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	/*
+	 *  Don't touch the Nile 4
+	 */
+	if (dev->vendor == PCI_VENDOR_ID_NEC &&
+	    dev->device == PCI_DEVICE_ID_NEC_VRC5476) return 0;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx = 0; idx < 6; idx++) {
+		r = &dev->resource[idx];
+		if (!r->start && r->end) {
+			printk(KERN_ERR "PCI: Device %s not available because "
+			       "of resource collisions\n", dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (cmd != old_cmd) {
+		printk("PCI: Enabling device %s (%04x -> %04x)\n",
+		       dev->slot_name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+	return pcibios_enable_resources(dev);
+}
+
+void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+			     struct resource *res, int resource)
+{
+	u32 new, check;
+	int reg;
+
+	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+	if (resource < 6) {
+		reg = PCI_BASE_ADDRESS_0 + 4 * resource;
+	} else if (resource == PCI_ROM_RESOURCE) {
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+		reg = dev->rom_base_reg;
+	} else {
+		/*
+		 * Somebody might have asked allocation of a non-standard
+		 * resource
+		 */
+		return;
+	}
+
+	pci_write_config_dword(dev, reg, new);
+	pci_read_config_dword(dev, reg, &check);
+	if ((new ^ check) &
+	    ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
+	     PCI_BASE_ADDRESS_MEM_MASK)) {
+		printk(KERN_ERR "PCI: Error while updating region "
+		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+		       new, check);
+	}
+}
+
+void pcibios_align_resource(void *data, struct resource *res,
+			    unsigned long size)
+{
+	struct pci_dev *dev = data;
+
+	if (res->flags & IORESOURCE_IO) {
+		unsigned long start = res->start;
+
+		/* We need to avoid collisions with `mirrored' VGA ports
+		   and other strange ISA hardware, so we always want the
+		   addresses kilobyte aligned.  */
+		if (size > 0x100) {
+			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+			       " (%ld bytes)\n", dev->slot_name,
+			       dev->resource - res, size);
+		}
+
+		start = (start + 1024 - 1) & ~(1024 - 1);
+		res->start = start;
+	}
+}
+
+struct pci_fixup pcibios_fixups[] = { {0} };
diff -urN linux-2.4.4-pre3/arch/mips/ddb5476/prom.c linux/arch/mips/ddb5476/prom.c
--- linux-2.4.4-pre3/arch/mips/ddb5476/prom.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/prom.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,43 @@
+/*
+ *  arch/mips/ddb5476/prom.c -- NEC DDB Vrc-5476 PROM routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ *
+ *   	Jun Sun - modified for DDB5476.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+
+char arcs_cmdline[COMMAND_LINE_SIZE];
+
+/* [jsun@junsun.net] PMON passes arguments in C main() style */
+void __init prom_init(int argc, const char **arg)
+{
+	int i;
+
+	/* arg[0] is "g", the rest is boot parameters */
+	arcs_cmdline[0] = '\0';
+	for (i = 1; i < argc; i++) {
+		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+		    >= sizeof(arcs_cmdline))
+			break;
+		strcat(arcs_cmdline, arg[i]);
+		strcat(arcs_cmdline, " ");
+	}
+
+	mips_machgroup = MACH_GROUP_NEC_DDB;
+	mips_machtype = MACH_NEC_DDB5476;
+	/* 64 MB non-upgradable */
+	add_memory_region(0, 64 << 20, BOOT_MEM_RAM);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff -urN linux-2.4.4-pre3/arch/mips/ddb5476/setup.c linux/arch/mips/ddb5476/setup.c
--- linux-2.4.4-pre3/arch/mips/ddb5476/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/setup.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,375 @@
+/*
+ *  arch/mips/ddb5476/setup.c -- NEC DDB Vrc-5476 setup routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kbd_ll.h>
+#include <linux/kernel.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/console.h>
+#include <linux/sched.h>
+#include <linux/mc146818rtc.h>
+#include <linux/pc_keyb.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/addrspace.h>
+#include <asm/bcache.h>
+#include <asm/keyboard.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/nile4.h>
+
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void rs_kgdb_hook(int);
+extern void breakpoint(void);
+#endif
+
+#if defined(CONFIG_SERIAL_CONSOLE)
+extern void console_setup(char *);
+#endif
+
+extern struct ide_ops std_ide_ops;
+extern struct rtc_ops ddb_rtc_ops;
+extern struct kbd_ops std_kbd_ops;
+
+static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
+
+static void ddb_machine_restart(char *command)
+{
+	u32 t;
+
+	/* PCI cold reset */
+	t = nile4_in32(NILE4_PCICTRL + 4);
+	t |= 0x40000000;
+	nile4_out32(NILE4_PCICTRL + 4, t);
+	/* CPU cold reset */
+	t = nile4_in32(NILE4_CPUSTAT);
+	t |= 1;
+	nile4_out32(NILE4_CPUSTAT, t);
+	/* Call the PROM */
+	back_to_prom();
+}
+
+static void ddb_machine_halt(void)
+{
+	printk("DDB Vrc-5476 halted.\n");
+	while (1);
+}
+
+static void ddb_machine_power_off(void)
+{
+	printk("DDB Vrc-5476 halted. Please turn off the power.\n");
+	while (1);
+}
+
+extern void ddb_irq_setup(void);
+
+void (*board_time_init) (struct irqaction * irq);
+
+
+static void __init ddb_time_init(struct irqaction *irq)
+{
+	/* set the clock to 1 Hz */
+	nile4_out32(NILE4_T2CTRL, 1000000);
+	/* enable the General-Purpose Timer */
+	nile4_out32(NILE4_T2CTRL + 4, 0x00000001);
+	/* reset timer */
+	nile4_out32(NILE4_T2CNTR, 0);
+	/* enable interrupt */
+	nile4_enable_irq(NILE4_INT_GPT);
+	i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
+}
+
+static struct {
+	struct resource dma1;
+	struct resource pic1;
+	struct resource timer;
+	struct resource rtc;
+	struct resource dma_page_reg;
+	struct resource pic2;
+	struct resource dma2;
+} ddb5476_ioport = {
+	{
+	"dma1", 0x00, 0x1f, IORESOURCE_BUSY}, {
+	"pic1", 0x20, 0x3f, IORESOURCE_BUSY}, {
+	"timer", 0x40, 0x5f, IORESOURCE_BUSY}, {
+	"rtc", 0x70, 0x7f, IORESOURCE_BUSY}, {
+	"dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, {
+	"pic2", 0xa0, 0xbf, IORESOURCE_BUSY}, {
+	"dma2", 0xc0, 0xdf, IORESOURCE_BUSY}
+};
+
+static struct {
+	struct resource nile4;
+} ddb5476_iomem = {
+	{ "Nile 4", NILE4_BASE, NILE4_BASE + NILE4_SIZE - 1, IORESOURCE_BUSY}
+};
+
+void __init ddb_setup(void)
+{
+	extern int panic_timeout;
+
+	irq_setup = ddb_irq_setup;
+	mips_io_port_base = NILE4_PCI_IO_BASE;
+	isa_slot_offset = NILE4_PCI_MEM_BASE;
+	board_time_init = ddb_time_init;
+
+	_machine_restart = ddb_machine_restart;
+	_machine_halt = ddb_machine_halt;
+	_machine_power_off = ddb_machine_power_off;
+
+	/* request io port/mem resources  */
+	if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) ||
+	    request_resource(&ioport_resource, &ddb5476_ioport.pic1) ||
+	    request_resource(&ioport_resource, &ddb5476_ioport.timer) ||
+	    request_resource(&ioport_resource, &ddb5476_ioport.rtc) ||
+	    request_resource(&ioport_resource,
+			     &ddb5476_ioport.dma_page_reg)
+	    || request_resource(&ioport_resource, &ddb5476_ioport.pic2)
+	    || request_resource(&ioport_resource, &ddb5476_ioport.dma2)
+	    || request_resource(&iomem_resource, &ddb5476_iomem.nile4)) {
+		printk
+		    ("ddb_setup - requesting oo port resources failed.\n");
+		for (;;);
+	}
+#ifdef CONFIG_BLK_DEV_IDE
+	ide_ops = &std_ide_ops;
+#endif
+	rtc_ops = &ddb_rtc_ops;
+
+#ifdef CONFIG_PC_KEYB
+	kbd_ops = &std_kbd_ops;
+#endif
+
+	/* Reboot on panic */
+	panic_timeout = 180;
+
+	/* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */
+	/* *(long*)0xbfa00218 = 0x8; */
+
+#ifdef CONFIG_FB
+	conswitchp = &dummy_con;
+#endif
+
+
+	/* board initialization stuff - non-fundamental, but need to be set
+	 * before kernel runs */
+
+	/* setup I/O space */
+	nile4_set_pdar(NILE4_PCIW0,
+		       PHYSADDR(NILE4_PCI_IO_BASE), 0x02000000, 32, 0, 0);
+	nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0);
+
+	/* map config space to 0xa8000000, 128MB */
+	nile4_set_pdar(NILE4_PCIW1,
+		       PHYSADDR(NILE4_PCI_CFG_BASE), 0x08000000, 32, 0, 0);
+	nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, 0x0);
+
+	/* ----- M1543 PCI setup ------ */
+
+	/* we know M1543 PCI-ISA controller is at addr:18 */
+	/* xxxx1010 makes USB at addr:13 and PMU at addr:14 */
+	*(volatile unsigned char *) 0xa8040072 &= 0xf0;
+	*(volatile unsigned char *) 0xa8040072 |= 0xa;
+
+	/* setup USB interrupt to IRQ 9, (bit 0:3 - 0001)
+	 * no IOCHRDY signal, (bit 7 - 1)
+	 * M1543C & M7101 VID and Subsys Device ID are read-only (bit 6 - 1)
+	 * Bypass USB Master INTAJ level to edge conversion (bit 4 - 0)
+	 */
+	*(unsigned char *) 0xa8040074 = 0xc1;
+
+	/* setup PMU(SCI to IRQ 10 (bit 0:3 - 0011)
+	 * SCI routing to IRQ 13 disabled (bit 7 - 1)
+	 * SCI interrupt level to edge conversion bypassed (bit 4 - 0)
+	 */
+	*(unsigned char *) 0xa8040076 = 0x83;
+
+	/* setup IDE controller
+	 * enable IDE controller (bit 6 - 1)
+	 * IDE IDSEL to be addr:24 (bit 4:5 - 11)
+	 * no IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0)
+	 * no IDE ATA Primary Bus Signal Pad Control (bit 2 - 0)
+	 * primary IRQ is 14, secondary is 15 (bit 1:0 - 01
+	 */
+	// *(unsigned char*)0xa8040058 = 0x71;
+	// *(unsigned char*)0xa8040058 = 0x79;
+	// *(unsigned char*)0xa8040058 = 0x74;              // use SIRQ, primary tri-state
+	*(unsigned char *) 0xa8040058 = 0x75;	// primary tri-state
+
+#if 0
+	/* this is not necessary if M5229 does not use SIRQ */
+	*(unsigned char *) 0xa8040044 = 0x0d;	// primary to IRQ 14
+	*(unsigned char *) 0xa8040075 = 0x0d;	// secondary to IRQ 14
+#endif
+
+	/* enable IDE in the M5229 config register 0x50 (bit 0 - 1) */
+	/* M5229 IDSEL is addr:24; see above setting */
+	*(unsigned char *) 0xa9000050 |= 0x1;
+
+	/* enable bus master (bit 2)  and IO decoding  (bit 0) */
+	*(unsigned char *) 0xa9000004 |= 0x5;
+
+	/* enable native, copied from arch/ppc/k2boot/head.S */
+	/* TODO - need volatile, need to be portable */
+	*(unsigned char *) 0xa9000009 = 0xff;
+
+	/* ----- end of M1543 PCI setup ------ */
+
+	/* ----- reset on-board ether chip  ------ */
+	*((volatile u32 *) 0xa8020004) |= 1;	/* decode I/O */
+	*((volatile u32 *) 0xa8020010) = 0;	/* set BAR address */
+
+	/* send reset command */
+	*((volatile u32 *) 0xa6000000) = 1;	/* do a soft reset */
+
+	/* disable ether chip */
+	*((volatile u32 *) 0xa8020004) = 0;	/* disable any decoding */
+
+	/* put it into sleep */
+	*((volatile u32 *) 0xa8020040) = 0x80000000;
+
+	/* ----- end of reset on-board ether chip  ------ */
+
+	/* ----- set pci window 1 to pci memory space -------- */
+	nile4_set_pdar(NILE4_PCIW1,
+		       PHYSADDR(NILE4_PCI_MEM_BASE), 0x08000000, 32, 0, 0);
+	// nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0);
+	nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0x08000000);
+
+}
+
+#define USE_NILE4_SERIAL	0
+
+#if USE_NILE4_SERIAL
+#define ns16550_in(reg)		nile4_in8((reg)*8)
+#define ns16550_out(reg, val)	nile4_out8((reg)*8, (val))
+#else
+#define NS16550_BASE		(NILE4_PCI_IO_BASE+0x03f8)
+static inline u8 ns16550_in(u32 reg)
+{
+	return *(volatile u8 *) (NS16550_BASE + reg);
+}
+
+static inline void ns16550_out(u32 reg, u8 val)
+{
+	*(volatile u8 *) (NS16550_BASE + reg) = val;
+}
+#endif
+
+#define NS16550_RBR		0
+#define NS16550_THR		0
+#define NS16550_DLL		0
+#define NS16550_IER		1
+#define NS16550_DLM		1
+#define NS16550_FCR		2
+#define NS16550_IIR		2
+#define NS16550_LCR		3
+#define NS16550_MCR		4
+#define NS16550_LSR		5
+#define NS16550_MSR		6
+#define NS16550_SCR		7
+
+#define NS16550_LSR_DR		0x01	/* Data ready */
+#define NS16550_LSR_OE		0x02	/* Overrun */
+#define NS16550_LSR_PE		0x04	/* Parity error */
+#define NS16550_LSR_FE		0x08	/* Framing error */
+#define NS16550_LSR_BI		0x10	/* Break */
+#define NS16550_LSR_THRE	0x20	/* Xmit holding register empty */
+#define NS16550_LSR_TEMT	0x40	/* Xmitter empty */
+#define NS16550_LSR_ERR		0x80	/* Error */
+
+
+void _serinit(void)
+{
+#if USE_NILE4_SERIAL
+	ns16550_out(NS16550_LCR, 0x80);
+	ns16550_out(NS16550_DLM, 0x00);
+	ns16550_out(NS16550_DLL, 0x36);	/* 9600 baud */
+	ns16550_out(NS16550_LCR, 0x00);
+	ns16550_out(NS16550_LCR, 0x03);
+	ns16550_out(NS16550_FCR, 0x47);
+#else
+	/* done by PMON */
+#endif
+}
+
+void _putc(char c)
+{
+	while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
+	ns16550_out(NS16550_THR, c);
+	if (c == '\n') {
+		while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
+		ns16550_out(NS16550_THR, '\r');
+	}
+}
+
+void _puts(const char *s)
+{
+	char c;
+
+	while ((c = *s++))
+		_putc(c);
+}
+
+char _getc(void)
+{
+	while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
+
+	return ns16550_in(NS16550_RBR);
+}
+
+int _testc(void)
+{
+	return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
+}
+
+
+/*
+ *  Hexadecimal 7-segment LED
+ */
+void ddb5476_led_hex(int hex)
+{
+	outb(hex, 0x80);
+}
+
+
+/*
+ *  LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
+ */
+struct pci_dev *pci_pmu = NULL;
+
+void ddb5476_led_d2(int on)
+{
+	u8 t;
+
+	if (pci_pmu) {
+		pci_read_config_byte(pci_pmu, 0x7e, &t);
+		if (on)
+			t &= 0x7f;
+		else
+			t |= 0x80;
+		pci_write_config_byte(pci_pmu, 0x7e, t);
+	}
+}
+
+void ddb5476_led_d3(int on)
+{
+	u8 t;
+
+	if (pci_pmu) {
+		pci_read_config_byte(pci_pmu, 0x7e, &t);
+		if (on)
+			t &= 0xbf;
+		else
+			t |= 0x40;
+		pci_write_config_byte(pci_pmu, 0x7e, t);
+	}
+}
diff -urN linux-2.4.4-pre3/arch/mips/ddb5476/time.c linux/arch/mips/ddb5476/time.c
--- linux-2.4.4-pre3/arch/mips/ddb5476/time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5476/time.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,32 @@
+/*
+ *  arch/mips/ddb5074/time.c -- Timer routines
+ *
+ *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
+ *                     Sony Software Development Center Europe (SDCE), Brussels
+ */
+#include <linux/init.h>
+
+#include <asm/mc146818rtc.h>
+
+static unsigned char ddb_rtc_read_data(unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	return inb_p(RTC_PORT(1));
+}
+
+static void ddb_rtc_write_data(unsigned char data, unsigned long addr)
+{
+	outb_p(addr, RTC_PORT(0));
+	outb_p(data, RTC_PORT(1));
+}
+
+static int ddb_rtc_bcd_mode(void)
+{
+	return 1;
+}
+
+struct rtc_ops ddb_rtc_ops = {
+	ddb_rtc_read_data,
+	ddb_rtc_write_data,
+	ddb_rtc_bcd_mode
+};
diff -urN linux-2.4.4-pre3/arch/mips/dec/Makefile linux/arch/mips/dec/Makefile
--- linux-2.4.4-pre3/arch/mips/dec/Makefile	Thu Feb 24 22:52:30 2000
+++ linux/arch/mips/dec/Makefile	Mon Dec  3 22:35:22 2001
@@ -7,30 +7,20 @@
 #
 
 .S.s:
-	$(CPP) $(CFLAGS) $< -o $*.s
+	$(CPP) $(AFLAGS) $< -o $@
 .S.o:
-	$(CC) $(CFLAGS) -c $< -o $*.o
+	$(CC) $(AFLAGS) -c $< -o $@
 
-all: dec.o
 O_TARGET := dec.o
-O_OBJS	 := int-handler.o setup.o irq.o time.o reset.o rtc-dec.o
 
-ifdef CONFIG_PROM_CONSOLE
-O_OBJS   += promcon.o
-endif
+all: dec.o
 
-ifdef CONFIG_SERIAL
-O_OBJS   += serial.o
-endif
+export-objs := wbflush.o
+obj-y	 := int-handler.o setup.o irq.o time.o reset.o rtc-dec.o wbflush.o
 
-ifeq ($(CONFIG_MODULES),y)
- OX_OBJS  = wbflush.o
-else
- O_OBJS   += wbflush.o
-endif
+obj-$(CONFIG_PROM_CONSOLE)	+= promcon.o
+obj-$(CONFIG_SERIAL)		+= serial.o
 
 int-handler.o:	int-handler.S
-
-clean:
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/dec/boot/Makefile linux/arch/mips/dec/boot/Makefile
--- linux-2.4.4-pre3/arch/mips/dec/boot/Makefile	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/dec/boot/Makefile	Mon Dec  3 22:35:22 2001
@@ -18,7 +18,8 @@
 all: dec_boot.o
 
 O_TARGET := dec_boot.o
-O_OBJS	 := decstation.o
+
+obj-y	 := decstation.o
 
 clean:
 	rm -f nbImage
diff -urN linux-2.4.4-pre3/arch/mips/defconfig linux/arch/mips/defconfig
--- linux-2.4.4-pre3/arch/mips/defconfig	Sun Mar  4 14:30:18 2001
+++ linux/arch/mips/defconfig	Mon Dec  3 22:35:22 2001
@@ -16,16 +16,17 @@
 # CONFIG_COBALT_MICRO_SERVER is not set
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
-# CONFIG_ORION is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 CONFIG_SGI_IP22=y
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
 CONFIG_ARC32=y
 CONFIG_PC_KEYB=y
 CONFIG_SGI=y
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_PCI is not set
 
 #
@@ -84,17 +85,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -111,10 +118,8 @@
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -131,6 +136,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -152,6 +158,7 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_SR_EXTRA_DEVS=2
@@ -192,14 +199,14 @@
 # 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_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_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -229,6 +236,8 @@
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -283,8 +292,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -299,11 +306,13 @@
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -334,6 +343,11 @@
 # USB support
 #
 # CONFIG_USB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
 
 #
 # Kernel hacking
diff -urN linux-2.4.4-pre3/arch/mips/defconfig-cobalt linux/arch/mips/defconfig-cobalt
--- linux-2.4.4-pre3/arch/mips/defconfig-cobalt	Thu Jul 27 18:36:54 2000
+++ linux/arch/mips/defconfig-cobalt	Mon Dec  3 22:35:22 2001
@@ -17,18 +17,18 @@
 CONFIG_COBALT_28=y
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
-# CONFIG_ORION is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
-# CONFIG_ISA is not set
 CONFIG_COBALT_27=y
 CONFIG_COBALT_LCD=y
 CONFIG_COBALT_SERIAL=y
 CONFIG_PCI=y
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 
 #
 # Loadable module support
@@ -85,22 +85,26 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_BLK_DEV_LOOP=m
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_BOOT is not set
-# CONFIG_AUTODETECT_RAID is not set
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
 
 #
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
 # Networking options
 #
 # CONFIG_PACKET is not set
@@ -112,13 +116,11 @@
 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=y
 # CONFIG_IP_PIMSM_V1 is not set
 # CONFIG_IP_PIMSM_V2 is not set
-CONFIG_IP_ALIAS=y
 # CONFIG_INET_ECN is not set
 CONFIG_SYN_COOKIES=y
 # CONFIG_IPV6 is not set
@@ -130,13 +132,13 @@
 #
 CONFIG_IPX=m
 # CONFIG_IPX_INTERN is not set
-# CONFIG_SPX is not set
 CONFIG_ATALK=m
 # CONFIG_DECNET is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -171,6 +173,7 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_SR_EXTRA_DEVS=2
@@ -194,15 +197,14 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 CONFIG_SCSI_AIC7XXX=y
-# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
-# CONFIG_AIC7XXX_PROC_STATS is not set
 CONFIG_AIC7XXX_RESET_DELAY=5
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
@@ -214,8 +216,6 @@
 # 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=y
 # CONFIG_SCSI_SYM53C8XX is not set
@@ -233,6 +233,8 @@
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
@@ -265,6 +267,7 @@
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_NET_SB1000 is not set
 
 #
@@ -277,6 +280,7 @@
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_AT1700 is not set
 # CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_PCI is not set
 # CONFIG_NET_POCKET is not set
@@ -284,8 +288,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -326,6 +331,7 @@
 CONFIG_ISDN_PPP=y
 CONFIG_ISDN_PPP_VJ=y
 CONFIG_ISDN_MPP=y
+# CONFIG_ISDN_PPP_BSDCOMP is not set
 CONFIG_ISDN_AUDIO=y
 # CONFIG_ISDN_TTY_FAX is not set
 
@@ -353,6 +359,7 @@
 # CONFIG_HISAX_NO_LLC is not set
 # CONFIG_HISAX_NO_KEYPAD is not set
 CONFIG_HISAX_1TR6=y
+# CONFIG_HISAX_NI1 is not set
 
 #
 #   HiSax supported cards
@@ -374,6 +381,7 @@
 # CONFIG_HISAX_SPORTSTER is not set
 # CONFIG_HISAX_MIC is not set
 # CONFIG_HISAX_NETJET is not set
+# CONFIG_HISAX_NETJET_U is not set
 # CONFIG_HISAX_NICCY is not set
 # CONFIG_HISAX_ISURF is not set
 # CONFIG_HISAX_HSTSAPHIR is not set
@@ -383,6 +391,7 @@
 # CONFIG_HISAX_HFC_PCI is not set
 # CONFIG_HISAX_W6692 is not set
 # CONFIG_HISAX_HFC_SX is not set
+# CONFIG_HISAX_SEDLBAUER_CS is not set
 
 #
 # Active ISDN cards
@@ -393,8 +402,8 @@
 # CONFIG_ISDN_DRV_ACT2000 is not set
 # CONFIG_ISDN_DRV_EICON is not set
 # CONFIG_ISDN_CAPI is not set
-# CONFIG_ISDN_CAPI_MIDDLEWARE is not set
 # CONFIG_HYSDN is not set
+# CONFIG_HYSDN_CAPI is not set
 
 #
 # Old CD-ROM drivers (not SCSI, not IDE)
@@ -425,6 +434,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -434,11 +447,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 CONFIG_RTC=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -447,8 +455,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -456,6 +469,8 @@
 CONFIG_QUOTA=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -503,6 +518,7 @@
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
 # CONFIG_NCPFS_IOCTL_LOCKING is not set
@@ -510,8 +526,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -520,6 +534,7 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
+CONFIG_SMB_NLS=y
 CONFIG_NLS=y
 
 #
@@ -569,6 +584,11 @@
 # USB support
 #
 # CONFIG_USB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
 
 #
 # Kernel hacking
diff -urN linux-2.4.4-pre3/arch/mips/defconfig-ddb5476 linux/arch/mips/defconfig-ddb5476
--- linux-2.4.4-pre3/arch/mips/defconfig-ddb5476	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/defconfig-ddb5476	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,541 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_SMP is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Machine selection
+#
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_ALGOR_P4032 is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_DECSTATION is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_NINO is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_MOMENCO_OCELOT is not set
+CONFIG_DDB5476=y
+# CONFIG_OLIVETTI_M700 is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MCA is not set
+# CONFIG_SBUS is not set
+CONFIG_I8259=y
+CONFIG_ISA=y
+CONFIG_PCI=y
+CONFIG_PC_KEYB=y
+CONFIG_ROTTEN_IRQ=y
+CONFIG_EISA=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R3912 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_R5000 is not set
+CONFIG_CPU_R5432=y
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_WB is not set
+
+#
+# General setup
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_FPU_EMULATOR=y
+CONFIG_KCORE_ELF=y
+CONFIG_ELF_KERNEL=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_NET=y
+# CONFIG_PCI_NAMES is not set
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+# CONFIG_PHONE_IXJ is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_IDEDMA_PCI is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_PCI_WIP is not set
+# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD7409 is not set
+# CONFIG_AMD7409_OVERRIDE is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_HPT34X_AUTODMA is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_PDC202XX_BURST is not set
+# CONFIG_BLK_DEV_OSB4 is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=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_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+CONFIG_TULIP=y
+# CONFIG_DE4X5 is not set
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+CONFIG_EEPRO100=y
+# CONFIG_EEPRO100_PM is not set
+# CONFIG_LNE390 is not set
+# CONFIG_NATSEMI is not set
+CONFIG_NE2K_PCI=y
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+# CONFIG_8139TOO is not set
+# CONFIG_RTL8129 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE 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 is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_CLGEN is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+CONFIG_FB_3DFX=y
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+# CONFIG_REMOTE_DEBUG is not set
+# CONFIG_LL_DEBUG is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_MIPS_UNCACHED is not set
diff -urN linux-2.4.4-pre3/arch/mips/defconfig-decstation linux/arch/mips/defconfig-decstation
--- linux-2.4.4-pre3/arch/mips/defconfig-decstation	Thu Jul 27 18:36:54 2000
+++ linux/arch/mips/defconfig-decstation	Mon Dec  3 22:35:22 2001
@@ -16,13 +16,14 @@
 # CONFIG_COBALT_MICRO_SERVER is not set
 CONFIG_DECSTATION=y
 # CONFIG_DDB5074 is not set
-# CONFIG_ORION is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_PCI is not set
 
 #
@@ -80,17 +81,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -107,10 +114,8 @@
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -127,6 +132,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -148,6 +154,7 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 # CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 
@@ -170,6 +177,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -186,14 +194,14 @@
 # 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_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_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -224,6 +232,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -278,8 +288,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -294,17 +302,24 @@
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
 CONFIG_ULTRIX_PARTITION=y
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
 # USB support
 #
 # CONFIG_USB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
 
 #
 # Kernel hacking
diff -urN linux-2.4.4-pre3/arch/mips/defconfig-ip22 linux/arch/mips/defconfig-ip22
--- linux-2.4.4-pre3/arch/mips/defconfig-ip22	Thu Jul 27 18:36:54 2000
+++ linux/arch/mips/defconfig-ip22	Mon Dec  3 22:35:22 2001
@@ -16,16 +16,17 @@
 # CONFIG_COBALT_MICRO_SERVER is not set
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
-# CONFIG_ORION is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 CONFIG_SGI_IP22=y
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
 CONFIG_ARC32=y
 CONFIG_PC_KEYB=y
 CONFIG_SGI=y
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_PCI is not set
 
 #
@@ -84,17 +85,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -111,10 +118,8 @@
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -131,6 +136,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -152,6 +158,7 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_SR_EXTRA_DEVS=2
@@ -175,6 +182,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -191,14 +199,14 @@
 # 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_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_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -228,6 +236,8 @@
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -282,8 +292,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -298,11 +306,13 @@
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -333,6 +343,11 @@
 # USB support
 #
 # CONFIG_USB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
 
 #
 # Kernel hacking
diff -urN linux-2.4.4-pre3/arch/mips/defconfig-it8172 linux/arch/mips/defconfig-it8172
--- linux-2.4.4-pre3/arch/mips/defconfig-it8172	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/defconfig-it8172	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,569 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_MIPS=y
+# CONFIG_SMP is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Machine selection
+#
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_ALGOR_P4032 is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_DECSTATION is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_NINO is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_OLIVETTI_M700 is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SNI_RM200_PCI is not set
+CONFIG_MIPS_ITE8172=y
+# CONFIG_IT8172_REVC is not set
+CONFIG_QTRONIX_KEYBOARD=y
+CONFIG_IT8172_CIR=y
+# CONFIG_IT8172_SCR0 is not set
+# CONFIG_IT8172_SCR1 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MCA is not set
+# CONFIG_SBUS is not set
+CONFIG_PCI=y
+CONFIG_IT8712=y
+CONFIG_PC_KEYB=y
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_I8259 is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_KMOD is not set
+
+#
+# CPU selection
+#
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R3912 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_CPU_NEVADA=y
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_MIPS32 is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_WB is not set
+
+#
+# General setup
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_MIPS_FPU_EMULATOR=y
+CONFIG_KCORE_ELF=y
+CONFIG_ELF_KERNEL=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_NET=y
+CONFIG_PCI_NAMES=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_SYSCTL=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC1000 is not set
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOCPROBE is not set
+
+#
+# RAM/ROM Device Drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_MTDRAM is not set
+
+#
+# Linearly Mapped Flash Device Drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_JEDEC is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=8000000
+CONFIG_MTD_PHYSMAP_LEN=2000000
+CONFIG_MTD_PHYSMAP_BUSWIDTH=4
+
+#
+# Drivers for chip mappings
+#
+# CONFIG_MTD_MIXMEM is not set
+# CONFIG_MTD_NORA is not set
+# CONFIG_MTD_OCTAGON is not set
+# CONFIG_MTD_PNC2000 is not set
+# CONFIG_MTD_RPXLITE is not set
+# CONFIG_MTD_VMAX is not set
+
+#
+# User modules and translation layers for MTD devices
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+# CONFIG_UNIX is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+# CONFIG_PHONE_IXJ is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_PCI_WIP is not set
+# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD7409 is not set
+# CONFIG_AMD7409_OVERRIDE is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_HPT34X_AUTODMA is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+CONFIG_BLK_DEV_IT8172=y
+CONFIG_IT8172_TUNING=y
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_PDC202XX_BURST is not set
+# CONFIG_BLK_DEV_OSB4 is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_IDE_CHIPSETS=y
+
+#
+# Note: most of these also require special kernel boot parameters
+#
+# CONFIG_BLK_DEV_4DRIVES is not set
+# CONFIG_BLK_DEV_ALI14XX is not set
+# CONFIG_BLK_DEV_DTC2278 is not set
+# CONFIG_BLK_DEV_HT6560B is not set
+# CONFIG_BLK_DEV_PDC4030 is not set
+# CONFIG_BLK_DEV_QD6580 is not set
+# CONFIG_BLK_DEV_UMC8672 is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_DMA_NONPCI is not set
+CONFIG_BLK_DEV_IDE_MODES=y
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=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_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+CONFIG_TULIP=y
+# CONFIG_DE4X5 is not set
+# CONFIG_DGRS is not set
+# CONFIG_DM9102 is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_EEPRO100_PM is not set
+# CONFIG_LNE390 is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+CONFIG_8139TOO=y
+# CONFIG_RTL8129 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_LAN_SAA9730 is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# 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 is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Kernel hacking
+#
+CONFIG_CROSSCOMPILE=y
+# CONFIG_MIPS_FPE_MODULE is not set
+# CONFIG_REMOTE_DEBUG is not set
+# CONFIG_LL_DEBUG is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_MIPS_UNCACHED is not set
diff -urN linux-2.4.4-pre3/arch/mips/defconfig-orion linux/arch/mips/defconfig-orion
--- linux-2.4.4-pre3/arch/mips/defconfig-orion	Thu Jul 27 18:36:54 2000
+++ linux/arch/mips/defconfig-orion	Mon Dec  3 22:35:22 2001
@@ -16,13 +16,14 @@
 # CONFIG_COBALT_MICRO_SERVER is not set
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
-CONFIG_ORION=y
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_PCI is not set
 
 #
@@ -79,18 +80,24 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -113,6 +120,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET_AUNUDP is not set
 # CONFIG_ECONET_NATIVE is not set
 # CONFIG_WAN_ROUTER is not set
@@ -180,6 +188,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -189,11 +201,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -202,8 +209,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -211,6 +223,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -265,6 +279,7 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -276,6 +291,11 @@
 # USB support
 #
 # CONFIG_USB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
 
 #
 # Kernel hacking
diff -urN linux-2.4.4-pre3/arch/mips/defconfig-rm200 linux/arch/mips/defconfig-rm200
--- linux-2.4.4-pre3/arch/mips/defconfig-rm200	Thu Jul 27 18:36:54 2000
+++ linux/arch/mips/defconfig-rm200	Mon Dec  3 22:35:22 2001
@@ -16,16 +16,17 @@
 # CONFIG_COBALT_MICRO_SERVER is not set
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
-# CONFIG_ORION is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
 # CONFIG_OLIVETTI_M700 is not set
 # CONFIG_SGI_IP22 is not set
 CONFIG_SNI_RM200_PCI=y
+# CONFIG_MCA is not set
 # CONFIG_SBUS is not set
 CONFIG_ARC32=y
 CONFIG_PCI=y
 CONFIG_ISA=y
 CONFIG_PC_KEYB=y
+CONFIG_EISA=y
 
 #
 # Loadable module support
@@ -88,17 +89,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -113,10 +120,8 @@
 # CONFIG_IP_MULTICAST is not set
 # 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_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -133,6 +138,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -211,6 +217,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -220,11 +230,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 CONFIG_RTC=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -233,8 +238,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -242,6 +252,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -296,8 +308,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -312,11 +322,13 @@
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -339,6 +351,11 @@
 # USB support
 #
 # CONFIG_USB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
 
 #
 # Kernel hacking
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/Makefile linux/arch/mips/ite-boards/generic/Makefile
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/Makefile	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,36 @@
+#
+#  Copyright 2000 MontaVista Software Inc.
+#  Author: MontaVista Software, Inc.
+#     	ppopov@mvista.com or support@mvista.com
+#
+# Makefile for the ITE 8172 (qed-4n-s01b) board, generic files.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+all: it8172.o
+
+O_TARGET := it8172.o
+
+obj-y := it8172_rtc.o it8172_setup.o irq.o int-handler.o pmon_prom.o time.o lpc.o puts.o reset.o
+
+ifdef CONFIG_PCI
+obj-y += it8172_pci.o
+endif
+
+ifdef CONFIG_IT8172_CIR
+obj-y += it8172_cir.o 
+endif
+
+ifdef CONFIG_REMOTE_DEBUG
+ obj-y += dbg_io.o             
+endif
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/dbg_io.c linux/arch/mips/ite-boards/generic/dbg_io.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/dbg_io.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/dbg_io.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,127 @@
+
+#include <linux/config.h>
+
+#ifdef CONFIG_REMOTE_DEBUG
+
+/* --- CONFIG --- */
+
+/* we need uint32 uint8 */
+/* #include "types.h" */
+typedef         unsigned char uint8;
+typedef         unsigned int  uint32;
+
+/* --- END OF CONFIG --- */
+
+#define         UART16550_BAUD_2400             2400
+#define         UART16550_BAUD_4800             4800
+#define         UART16550_BAUD_9600             9600
+#define         UART16550_BAUD_19200            19200
+#define         UART16550_BAUD_38400            38400
+#define         UART16550_BAUD_57600            57600
+#define         UART16550_BAUD_115200           115200
+
+#define         UART16550_PARITY_NONE           0
+#define         UART16550_PARITY_ODD            0x08
+#define         UART16550_PARITY_EVEN           0x18
+#define         UART16550_PARITY_MARK           0x28
+#define         UART16550_PARITY_SPACE          0x38
+
+#define         UART16550_DATA_5BIT             0x0
+#define         UART16550_DATA_6BIT             0x1
+#define         UART16550_DATA_7BIT             0x2
+#define         UART16550_DATA_8BIT             0x3
+
+#define         UART16550_STOP_1BIT             0x0
+#define         UART16550_STOP_2BIT             0x4
+
+/* ----------------------------------------------------- */
+
+/* === CONFIG === */
+
+/* [stevel] we use the IT8712 serial port for kgdb */
+#define	DEBUG_BASE  0xB40003F8 /* 8712 serial port 1 base address */
+#define MAX_BAUD    115200
+
+/* === END OF CONFIG === */
+
+/* register offset */
+#define         OFS_RCV_BUFFER          0
+#define         OFS_TRANS_HOLD          0
+#define         OFS_SEND_BUFFER         0
+#define         OFS_INTR_ENABLE         1
+#define         OFS_INTR_ID             2
+#define         OFS_DATA_FORMAT         3
+#define         OFS_LINE_CONTROL        3
+#define         OFS_MODEM_CONTROL       4
+#define         OFS_RS232_OUTPUT        4
+#define         OFS_LINE_STATUS         5
+#define         OFS_MODEM_STATUS        6
+#define         OFS_RS232_INPUT         6
+#define         OFS_SCRATCH_PAD         7
+
+#define         OFS_DIVISOR_LSB         0
+#define         OFS_DIVISOR_MSB         1
+
+
+/* memory-mapped read/write of the port */
+#define UART16550_READ(y)    (*((volatile uint8*)(DEBUG_BASE + y)))
+#define UART16550_WRITE(y,z) ((*((volatile uint8*)(DEBUG_BASE + y))) = z)
+
+void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+    /* disable interrupts */
+    UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+    /* set up buad rate */
+    { 
+        uint32 divisor;
+       
+        /* set DIAB bit */
+        UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+        
+        /* set divisor */
+        divisor = MAX_BAUD / baud;
+        UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+        UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00)>>8);
+
+        /* clear DIAB bit */
+        UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+    }
+
+    /* set data format */
+    UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+static int remoteDebugInitialized = 0;
+
+uint8 getDebugChar(void)
+{
+    if (!remoteDebugInitialized) {
+	remoteDebugInitialized = 1;
+	debugInit(UART16550_BAUD_115200,
+		  UART16550_DATA_8BIT,
+		  UART16550_PARITY_NONE,
+		  UART16550_STOP_1BIT);
+    }
+
+    while((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+    return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+int putDebugChar(uint8 byte)
+{
+    if (!remoteDebugInitialized) {
+	remoteDebugInitialized = 1;
+	debugInit(UART16550_BAUD_115200,
+		  UART16550_DATA_8BIT,
+		  UART16550_PARITY_NONE,
+		  UART16550_STOP_1BIT);
+    }
+
+    while ((UART16550_READ(OFS_LINE_STATUS) &0x20) == 0);
+    UART16550_WRITE(OFS_SEND_BUFFER, byte);
+    return 1;
+}
+
+#endif
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/int-handler.S linux/arch/mips/ite-boards/generic/int-handler.S
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/int-handler.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/int-handler.S	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,61 @@
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+	.text
+	.set    macro
+	.set    noat
+	.align	5
+
+NESTED(it8172_IRQ, PT_SIZE, sp)
+	SAVE_ALL
+	CLI				# Important: mark KERNEL mode !
+
+        /* We're working with 'reorder' set at this point. */
+	/*
+	 * Get pending interrupts
+	 */
+
+	mfc0	t0,CP0_CAUSE		# get pending interrupts
+	mfc0	t1,CP0_STATUS		# get enabled interrupts
+	and	t0,t1			# isolate allowed ones
+
+	andi	t0,0xff00		# isolate pending bits
+        beqz    t0, 3f                  # spurious interrupt
+
+        andi    a0, t0, CAUSEF_IP7
+        beq     a0, zero, 1f
+        move    a0, sp
+        jal     mips_timer_interrupt
+	j	ret_from_irq
+        nop
+        
+1:
+        andi    a0, t0, CAUSEF_IP2      # the only int we expect at this time
+        beq     a0, zero, 3f           
+	move	a0,sp  
+	jal	it8172_hw0_irqdispatch
+
+	mfc0	t0,CP0_STATUS		# disable interrupts
+	ori	t0,1
+	xori	t0,1
+	mtc0	t0,CP0_STATUS
+        nop
+        nop
+        nop
+	
+	la      a1, ret_from_irq
+	jr	a1
+        nop
+	
+3:	
+	move a0, sp
+	jal	mips_spurious_interrupt
+        nop
+	la      a1, ret_from_irq
+	jr	a1
+        nop
+
+END(it8172_IRQ)
+
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/irq.c linux/arch/mips/ite-boards/generic/irq.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/irq.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,540 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	ITE 8172G interrupt/setup routines.
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ * Part of this file was derived from Carsten Langgaard's 
+ * arch/mips/mips-boards/atlas/atlas_int.c.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/serial_reg.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_int.h>
+#include <asm/it8172/it8172_dbg.h>
+
+#undef DEBUG_IRQ
+#ifdef DEBUG_IRQ
+/* note: prints function name for you */
+#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void breakpoint(void);
+#endif
+
+/* revisit */
+#define EXT_IRQ0_TO_IP 2 /* IP 2 */
+#define EXT_IRQ5_TO_IP 7 /* IP 7 */
+
+extern void set_debug_traps(void);
+extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
+extern asmlinkage void it8172_IRQ(void);
+irq_cpustat_t irq_stat [NR_CPUS];
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+unsigned long spurious_count = 0;
+irq_desc_t irq_desc[NR_IRQS];
+irq_desc_t *irq_desc_base=&irq_desc[0];
+
+struct it8172_intc_regs volatile *it8172_hw0_icregs
+	= (struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE));
+
+/* Function for careful CP0 interrupt mask access */
+static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
+{
+        unsigned long status = read_32bit_cp0_register(CP0_STATUS);
+        status &= ~((clr_mask & 0xFF) << 8);
+        status |=   (set_mask & 0xFF) << 8;
+        write_32bit_cp0_register(CP0_STATUS, status);
+}
+
+static inline void mask_irq(unsigned int irq_nr)
+{
+        modify_cp0_intmask(irq_nr, 0);
+}
+
+static inline void unmask_irq(unsigned int irq_nr)
+{
+        modify_cp0_intmask(0, irq_nr);
+}
+
+void disable_irq(unsigned int irq_nr)
+{
+        unsigned long flags;
+
+        save_and_cli(flags);
+        mask_irq(irq_nr);
+        restore_flags(flags);
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+        save_and_cli(flags);
+        unmask_irq(irq_nr);
+        restore_flags(flags);
+}
+
+
+void disable_it8172_irq(unsigned int irq_nr)
+{
+	unsigned short mask;
+
+	DPRINTK("disable_it8172_irq %d\n", irq_nr);
+
+	if ( (irq_nr >= IT8172_LPC_IRQ_BASE) && (irq_nr <= IT8172_SERIRQ_15)) {
+		/* LPC interrupt */
+		DPRINTK("disable, before lpc_mask  %x\n", it8172_hw0_icregs->lpc_mask);
+		it8172_hw0_icregs->lpc_mask |= (1 << (irq_nr - IT8172_LPC_IRQ_BASE));
+		DPRINTK("disable, after lpc_mask  %x\n", it8172_hw0_icregs->lpc_mask);
+	}
+	else if ( (irq_nr >= IT8172_LB_IRQ_BASE) && (irq_nr <= IT8172_IOCHK_IRQ)) {
+		/* Local Bus interrupt */
+		DPRINTK("before lb_mask  %x\n", it8172_hw0_icregs->lb_mask);
+		it8172_hw0_icregs->lb_mask |= (1 << (irq_nr - IT8172_LB_IRQ_BASE));
+		DPRINTK("after lb_mask  %x\n", it8172_hw0_icregs->lb_mask);
+	}
+	else if ( (irq_nr >= IT8172_PCI_DEV_IRQ_BASE) && (irq_nr <= IT8172_DMA_IRQ)) {
+		/* PCI and other interrupts */
+		DPRINTK("before pci_mask  %x\n", it8172_hw0_icregs->pci_mask);
+		it8172_hw0_icregs->pci_mask |= (1 << (irq_nr - IT8172_PCI_DEV_IRQ_BASE));
+		DPRINTK("after pci_mask  %x\n", it8172_hw0_icregs->pci_mask);
+	}
+	else if ( (irq_nr >= IT8172_NMI_IRQ_BASE) && (irq_nr <= IT8172_POWER_NMI_IRQ)) {
+		/* NMI interrupts */
+		DPRINTK("before nmi_mask  %x\n", it8172_hw0_icregs->nmi_mask);
+		it8172_hw0_icregs->nmi_mask |= (1 << (irq_nr - IT8172_NMI_IRQ_BASE));
+		DPRINTK("after nmi_mask  %x\n", it8172_hw0_icregs->nmi_mask);
+	}
+	else {
+		panic("disable_it8172_irq: bad irq %d\n", irq_nr);
+	}
+}
+
+
+void enable_it8172_irq(unsigned int irq_nr)
+{
+	DPRINTK("enable_it8172_irq %d\n", irq_nr);
+	if ( (irq_nr >= IT8172_LPC_IRQ_BASE) && (irq_nr <= IT8172_SERIRQ_15)) {
+		/* LPC interrupt */
+		DPRINTK("enable, before lpc_mask  %x\n", it8172_hw0_icregs->lpc_mask);
+		it8172_hw0_icregs->lpc_mask &= ~(1 << (irq_nr - IT8172_LPC_IRQ_BASE));
+		DPRINTK("enable, after lpc_mask  %x\n", it8172_hw0_icregs->lpc_mask);
+	}
+	else if ( (irq_nr >= IT8172_LB_IRQ_BASE) && (irq_nr <= IT8172_IOCHK_IRQ)) {
+		/* Local Bus interrupt */
+		DPRINTK("before lb_mask  %x\n", it8172_hw0_icregs->lb_mask);
+		it8172_hw0_icregs->lb_mask &= ~(1 << (irq_nr - IT8172_LB_IRQ_BASE));
+		DPRINTK("after lb_mask  %x\n", it8172_hw0_icregs->lb_mask);
+	}
+	else if ( (irq_nr >= IT8172_PCI_DEV_IRQ_BASE) && (irq_nr <= IT8172_DMA_IRQ)) {
+		/* PCI and other interrupts */
+		DPRINTK("before pci_mask  %x\n", it8172_hw0_icregs->pci_mask);
+		it8172_hw0_icregs->pci_mask &= ~(1 << (irq_nr - IT8172_PCI_DEV_IRQ_BASE));
+		DPRINTK("after pci_mask  %x\n", it8172_hw0_icregs->pci_mask);
+	}
+	else if ( (irq_nr >= IT8172_NMI_IRQ_BASE) && (irq_nr <= IT8172_POWER_NMI_IRQ)) {
+		/* NMI interrupts */
+		DPRINTK("before nmi_mask  %x\n", it8172_hw0_icregs->nmi_mask);
+		it8172_hw0_icregs->nmi_mask &= ~(1 << (irq_nr - IT8172_NMI_IRQ_BASE));
+		DPRINTK("after nmi_mask  %x\n", it8172_hw0_icregs->nmi_mask);
+	}
+	else {
+		panic("enable_it8172_irq: bad irq %d\n", irq_nr);
+	}
+}
+
+static unsigned int startup_ite_irq(unsigned int irq)
+{
+	enable_it8172_irq(irq);
+	return 0; 
+}
+
+#define shutdown_ite_irq	disable_it8172_irq
+#define mask_and_ack_ite_irq    disable_it8172_irq
+
+static void end_ite_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_it8172_irq(irq);
+}
+
+static struct hw_interrupt_type it8172_irq_type = {
+	"ITE8172",
+	startup_ite_irq,
+	shutdown_ite_irq,
+	enable_it8172_irq,
+	disable_it8172_irq,
+	mask_and_ack_ite_irq,
+	end_ite_irq,
+	NULL
+};
+
+
+int get_irq_list(char *buf)
+{
+        int i, len = 0, j;
+        struct irqaction * action;
+
+        len += sprintf(buf+len, "           ");
+        for (j=0; j<smp_num_cpus; j++)
+                len += sprintf(buf+len, "CPU%d       ",j);
+        *(char *)(buf+len++) = '\n';
+
+        for (i = 0 ; i < NR_IRQS ; i++) {
+                action = irq_desc[i].action;
+                if ( !action || !action->handler )
+                        continue;
+                len += sprintf(buf+len, "%3d: ", i);		
+                len += sprintf(buf+len, "%10u ", kstat_irqs(i));
+                if ( irq_desc[i].handler )		
+                        len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename );
+                else
+                        len += sprintf(buf+len, "  None      ");
+                len += sprintf(buf+len, "    %s",action->name);
+                for (action=action->next; action; action = action->next) {
+                        len += sprintf(buf+len, ", %s", action->name);
+                }
+                len += sprintf(buf+len, "\n");
+        }
+        len += sprintf(buf+len, "BAD: %10lu\n", spurious_count);
+        return len;
+}
+
+asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
+{
+	struct irqaction *action;
+	int cpu;
+
+	cpu = smp_processor_id();
+	irq_enter(cpu, irq);
+
+	kstat.irqs[cpu][irq]++;
+#if 0
+	if (irq_desc[irq].handler && irq_desc[irq].handler->ack) {
+	//	printk("invoking ack handler\n");
+		irq_desc[irq].handler->ack(irq);
+	}
+#endif
+
+	action = irq_desc[irq].action;
+
+	if (action && action->handler)
+	{
+		//mask_irq(1<<irq);
+		//printk("action->handler %x\n", action->handler);
+		disable_it8172_irq(irq);
+		//if (!(action->flags & SA_INTERRUPT)) __sti(); /* reenable ints */
+		do { 
+			action->handler(irq, action->dev_id, regs);
+			action = action->next;
+		} while ( action );
+		//__cli(); /* disable ints */
+		if (irq_desc[irq].handler)
+		{
+		}
+		//unmask_irq(1<<irq);
+		enable_it8172_irq(irq);
+	}
+	else
+	{
+		spurious_count++;
+		printk("Unhandled interrupt %d, cause %x, disabled\n", 
+				(unsigned)irq, (unsigned)regs->cp0_cause);
+		disable_it8172_irq(irq);
+		//disable_irq(1<<irq);
+	}
+	irq_exit(cpu, irq);
+}
+
+int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+	unsigned long irqflags, const char * devname, void *dev_id)
+{
+        struct irqaction *old, **p, *action;
+        unsigned long flags;
+
+        /*
+         * IP0 and IP1 are software interrupts. IP7 is typically the timer interrupt.
+	 *
+	 * The ITE QED-4N-S01B board has one single interrupt line going from
+	 * the system controller to the CPU. It's connected to the CPU external
+	 * irq pin 1, which is IP2.  The interrupt numbers are listed in it8172_int.h;
+	 * the ISA interrupts are numbered from 0 to 15, and the rest go from
+	 * there.  
+         */
+
+	//printk("request_irq: %d handler %x\n", irq, handler);
+        if (irq >= NR_IRQS) 
+                return -EINVAL;
+
+        if (!handler)
+        {
+                /* Free */
+                for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next)
+                {
+                        /* Found it - now free it */
+                        save_flags(flags);
+                        cli();
+                        *p = action->next;
+			disable_it8172_irq(irq);
+                        //disable_irq(1<<irq);
+                        restore_flags(flags);
+                        kfree(action);
+                        return 0;
+                }
+                return -ENOENT;
+        }
+        
+        action = (struct irqaction *)
+                kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+        if (!action)
+                return -ENOMEM;
+        memset(action, 0, sizeof(struct irqaction));
+        
+        save_flags(flags);
+        cli();
+        
+        action->handler = handler;
+        action->flags = irqflags;					
+        action->mask = 0;
+        action->name = devname;
+        action->dev_id = dev_id;
+        action->next = NULL;
+
+        p = &irq_desc[irq].action;
+        
+        if ((old = *p) != NULL) {
+                /* Can't share interrupts unless both agree to */
+                if (!(old->flags & action->flags & SA_SHIRQ))
+                        return -EBUSY;
+                /* add new interrupt at end of irq queue */
+                do {
+                        p = &old->next;
+                        old = *p;
+                } while (old);
+        }
+        *p = action;
+	enable_it8172_irq(irq);
+        restore_flags(flags);	
+#if 0
+	printk("request_irq: status %x cause %x\n", 
+			read_32bit_cp0_register(CP0_STATUS), read_32bit_cp0_register(CP0_CAUSE));
+#endif
+        return 0;
+}
+		
+void free_irq(unsigned int irq, void *dev_id)
+{
+        request_irq(irq, NULL, 0, NULL, dev_id);
+}
+
+void enable_cpu_timer(void)
+{
+	enable_irq(1<<EXT_IRQ5_TO_IP); /* timer interrupt */
+}
+
+unsigned long probe_irq_on (void)
+{
+        return 0;
+}
+
+int probe_irq_off (unsigned long irqs)
+{
+        return 0;
+}
+
+
+void __init init_IRQ(void)
+{
+	int i;
+
+        memset(irq_desc, 0, sizeof(irq_desc));
+        set_except_vector(0, it8172_IRQ);
+
+	/* mask all interrupts */
+	it8172_hw0_icregs->lb_mask  = 0xffff;
+	it8172_hw0_icregs->lpc_mask = 0xffff;
+	it8172_hw0_icregs->pci_mask = 0xffff;
+	it8172_hw0_icregs->nmi_mask = 0xffff;
+
+	/* make all interrupts level triggered */
+	it8172_hw0_icregs->lb_trigger  = 0;
+	it8172_hw0_icregs->lpc_trigger = 0;
+	it8172_hw0_icregs->pci_trigger = 0;
+	it8172_hw0_icregs->nmi_trigger = 0;
+
+	/* active level setting */
+	/* uart, keyboard, and mouse are active high */
+	it8172_hw0_icregs->lpc_level = (0x10 | 0x2 | 0x1000);
+	it8172_hw0_icregs->lb_level |= 0x20;
+
+	/* keyboard and mouse are edge triggered */
+	it8172_hw0_icregs->lpc_trigger |= (0x2 | 0x1000); 
+
+
+#if 0
+	// Enable this piece of code to make internal USB interrupt
+	// edge triggered.
+	it8172_hw0_icregs->pci_trigger |= 
+		(1 << (IT8172_USB_IRQ - IT8172_PCI_DEV_IRQ_BASE));
+	it8172_hw0_icregs->pci_level &= 
+		~(1 << (IT8172_USB_IRQ - IT8172_PCI_DEV_IRQ_BASE));
+#endif
+
+	for (i = 0; i <= IT8172_INT_END; i++) {
+		irq_desc[i].status	= IRQ_DISABLED;
+		irq_desc[i].action	= 0;
+		irq_desc[i].depth	= 1;
+		irq_desc[i].handler	= &it8172_irq_type;
+	}
+
+	/*
+	 * Enable external int line 2
+	 * All ITE interrupts are masked for now.
+	 */
+	enable_irq(1<<EXT_IRQ0_TO_IP);
+	//change_cp0_status(ST0_IM, IE_IRQ2);
+
+#ifdef CONFIG_REMOTE_DEBUG
+	/* If local serial I/O used for debug port, enter kgdb at once */
+	puts("Waiting for kgdb to connect...");
+	set_debug_traps();
+	breakpoint(); 
+#endif
+}
+
+void mips_spurious_interrupt(struct pt_regs *regs)
+{
+#if 1
+	return;
+#else
+	unsigned long status, cause;
+
+	printk("got spurious interrupt\n");
+	status = read_32bit_cp0_register(CP0_STATUS);
+	cause = read_32bit_cp0_register(CP0_CAUSE);
+	printk("status %x cause %x\n", status, cause);
+	printk("epc %x badvaddr %x \n", regs->cp0_epc, regs->cp0_badvaddr);
+//	while(1);
+#endif
+}
+
+void it8172_hw0_irqdispatch(struct pt_regs *regs)
+{
+	int irq;
+	unsigned short intstatus, status;
+
+	intstatus = it8172_hw0_icregs->intstatus;
+	if (intstatus & 0x8) {
+		panic("Got NMI interrupt\n");
+	}
+	else if (intstatus & 0x4) {
+		/* PCI interrupt */
+		irq = 0;
+		status = it8172_hw0_icregs->pci_req;
+		while (!(status & 0x1)) {
+			irq++;
+			status >>= 1;
+		}
+		irq += IT8172_PCI_DEV_IRQ_BASE;
+		//printk("pci int %d\n", irq);
+	}
+	else if (intstatus & 0x1) {
+		/* Local Bus interrupt */
+		irq = 0;
+		status = it8172_hw0_icregs->lb_req;
+		while (!(status & 0x1)) {
+			irq++;
+			status >>= 1;
+		}
+		irq += IT8172_LB_IRQ_BASE;
+		//printk("lb int %d\n", irq);
+	}
+	else if (intstatus & 0x2) {
+		/* LPC interrupt */
+		/* Since some lpc interrupts are edge triggered,
+		 * we could lose an interrupt this way because
+		 * we acknowledge all ints at onces. Revisit.
+		 */
+		status = it8172_hw0_icregs->lpc_req;
+		it8172_hw0_icregs->lpc_req = 0; /* acknowledge ints */
+		irq = 0;
+		while (!(status & 0x1)) {
+			irq++;
+			status >>= 1;
+		}
+		irq += IT8172_LPC_IRQ_BASE;
+		//printk("LPC int %d\n", irq);
+	}
+	else {
+		return;
+	}
+	do_IRQ(irq, regs);
+}
+
+void show_pending_irqs(void)
+{
+	fputs("intstatus:  ");
+	put32(it8172_hw0_icregs->intstatus);
+	puts("");
+
+	fputs("pci_req:  ");
+	put32(it8172_hw0_icregs->pci_req);
+	puts("");
+
+	fputs("lb_req:  ");
+	put32(it8172_hw0_icregs->lb_req);
+	puts("");
+
+	fputs("lpc_req:  ");
+	put32(it8172_hw0_icregs->lpc_req);
+	puts("");
+}
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/it8172_cir.c linux/arch/mips/ite-boards/generic/it8172_cir.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/it8172_cir.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/it8172_cir.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,171 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	IT8172 Consumer IR port generic routines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_IT8172_CIR
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_cir.h>
+
+
+volatile struct it8172_cir_regs *cir_regs[NUM_CIR_PORTS] = {
+	(volatile struct it8172_cir_regs *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_CIR0_BASE)),
+	(volatile struct it8172_cir_regs *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_CIR1_BASE))};
+
+
+/*
+ * Initialize Consumer IR Port.
+ */
+int cir_port_init(struct cir_port *cir)
+{
+	int port = cir->port;
+	unsigned char data;
+
+	/* set baud rate */
+	cir_regs[port]->bdlr = cir->baud_rate & 0xff;
+	cir_regs[port]->bdhr = (cir->baud_rate >> 8) & 0xff;
+
+	/* set receiver control register */
+	cir_regs[port]->rcr = (CIR_SET_RDWOS(cir->rdwos) | CIR_SET_RXDCR(cir->rxdcr));
+
+	/* set carrier frequency register */
+	cir_regs[port]->cfr = (CIR_SET_CF(cir->cfq) | CIR_SET_HS(cir->hcfs));
+
+	/* set fifo threshold */
+	data = cir_regs[port]->mstcr & 0xf3;
+	data |= CIR_SET_FIFO_TL(cir->fifo_tl);
+	cir_regs[port]->mstcr = data;
+
+	clear_fifo(cir);
+	enable_receiver(cir);
+	disable_rx_demodulation(cir);
+
+	set_rx_active(cir);
+	int_enable(cir);
+	rx_int_enable(cir);
+
+	return 0;
+}
+
+
+void clear_fifo(struct cir_port *cir)
+{
+	cir_regs[cir->port]->mstcr |= CIR_FIFO_CLEAR;
+}
+
+void enable_receiver(struct cir_port *cir)
+{
+	cir_regs[cir->port]->rcr |= CIR_RXEN;
+}
+
+void disable_receiver(struct cir_port *cir)
+{
+	cir_regs[cir->port]->rcr &= ~CIR_RXEN;
+}
+
+void enable_rx_demodulation(struct cir_port *cir)
+{
+	cir_regs[cir->port]->rcr |= CIR_RXEND;
+}
+
+void disable_rx_demodulation(struct cir_port *cir)
+{
+	cir_regs[cir->port]->rcr &= ~CIR_RXEND;
+}
+
+void set_rx_active(struct cir_port *cir)
+{
+	cir_regs[cir->port]->rcr |= CIR_RXACT;
+}
+
+void int_enable(struct cir_port *cir)
+{
+	cir_regs[cir->port]->ier |= CIR_IEC;
+}
+
+void rx_int_enable(struct cir_port *cir)
+{
+	cir_regs[cir->port]->ier |= CIR_RDAIE;
+}
+
+void dump_regs(struct cir_port *cir)
+{
+	printk("mstcr %x ier %x iir %x cfr %x rcr %x tcr %x tfsr %x rfsr %x\n",
+	cir_regs[cir->port]->mstcr,
+	cir_regs[cir->port]->ier,
+	cir_regs[cir->port]->iir,
+	cir_regs[cir->port]->cfr,
+	cir_regs[cir->port]->rcr,
+	cir_regs[cir->port]->tcr,
+	cir_regs[cir->port]->tfsr,
+	cir_regs[cir->port]->rfsr);
+
+	while (cir_regs[cir->port]->iir & CIR_RDAI) {
+		printk("data %x\n", cir_regs[cir->port]->dr);
+	}
+}
+
+void dump_reg_addr(struct cir_port *cir)
+{
+	printk("dr %x mstcr %x ier %x iir %x cfr %x rcr %x tcr %x bdlr %x bdhr %x tfsr %x rfsr %x\n",
+	(unsigned)&cir_regs[cir->port]->dr,
+	(unsigned)&cir_regs[cir->port]->mstcr,
+	(unsigned)&cir_regs[cir->port]->ier,
+	(unsigned)&cir_regs[cir->port]->iir,
+	(unsigned)&cir_regs[cir->port]->cfr,
+	(unsigned)&cir_regs[cir->port]->rcr,
+	(unsigned)&cir_regs[cir->port]->tcr,
+	(unsigned)&cir_regs[cir->port]->bdlr,
+	(unsigned)&cir_regs[cir->port]->bdhr,
+	(unsigned)&cir_regs[cir->port]->tfsr,
+	(unsigned)&cir_regs[cir->port]->rfsr);
+}
+
+int cir_get_rx_count(struct cir_port *cir)
+{
+	return cir_regs[cir->port]->rfsr & CIR_RXFBC_MASK;
+}
+
+char cir_read_data(struct cir_port *cir)
+{
+	return cir_regs[cir->port]->dr;
+}
+
+char get_int_status(struct cir_port *cir)
+{
+	return cir_regs[cir->port]->iir;
+}
+#endif
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/it8172_pci.c linux/arch/mips/ite-boards/generic/it8172_pci.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/it8172_pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/it8172_pci.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,276 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	IT8172 system controller specific pci support.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_PCI
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_pci.h>
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+#undef DEBUG
+#undef DEBUG_CONFIG_CYCLES
+
+static int
+it8172_pcibios_config_access(unsigned char access_type, struct pci_dev *dev,
+                           unsigned char where, u32 *data)
+{
+	/* 
+	 * config cycles are on 4 byte boundary only
+	 */
+	unsigned char bus = dev->bus->number;
+	unsigned char dev_fn = dev->devfn;
+
+#ifdef DEBUG_CONFIG_CYCLES
+	printk("it config: type %d dev %x bus %d dev_fn %x data %x\n",
+			access_type, dev, bus, dev_fn, *data);
+
+#endif
+
+	/* Setup address */
+	IT_WRITE(IT_CONFADDR, (bus << IT_BUSNUM_SHF) | 
+			(dev_fn << IT_FUNCNUM_SHF) | (where & ~0x3));
+
+
+	if (access_type == PCI_ACCESS_WRITE) {
+		IT_WRITE(IT_CONFDATA, *data);
+	} 
+	else {
+		IT_READ(IT_CONFDATA, *data);
+	}
+
+	/*
+	 * Revisit: check for master or target abort.
+	 */
+	return 0;
+
+
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int
+it8172_pcibios_read_config_byte (struct pci_dev *dev, int where, u8 *val)
+{
+	u32 data = 0;
+
+	if (it8172_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+		return -1;
+
+	*val = (data >> ((where & 3) << 3)) & 0xff;
+#ifdef DEBUG
+        printk("cfg read byte: bus %d dev_fn %x where %x: val %x\n", 
+                dev->bus->number, dev->devfn, where, *val);
+#endif
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int
+it8172_pcibios_read_config_word (struct pci_dev *dev, int where, u16 *val)
+{
+	u32 data = 0;
+
+	if (where & 1)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (it8172_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+	       return -1;
+
+	*val = (data >> ((where & 3) << 3)) & 0xffff;
+#ifdef DEBUG
+        printk("cfg read word: bus %d dev_fn %x where %x: val %x\n", 
+                dev->bus->number, dev->devfn, where, *val);
+#endif
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+it8172_pcibios_read_config_dword (struct pci_dev *dev, int where, u32 *val)
+{
+	u32 data = 0;
+
+	if (where & 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	
+	if (it8172_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+		return -1;
+
+	*val = data;
+#ifdef DEBUG
+        printk("cfg read dword: bus %d dev_fn %x where %x: val %x\n", 
+                dev->bus->number, dev->devfn, where, *val);
+#endif
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int
+it8172_pcibios_write_config_byte (struct pci_dev *dev, int where, u8 val)
+{
+	u32 data = 0;
+       
+	if (it8172_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+		return -1;
+
+	data = (data & ~(0xff << ((where & 3) << 3))) |
+	       (val << ((where & 3) << 3));
+
+	if (it8172_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+it8172_pcibios_write_config_word (struct pci_dev *dev, int where, u16 val)
+{
+        u32 data = 0;
+
+	if (where & 1)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+       
+        if (it8172_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+	       return -1;
+
+	data = (data & ~(0xffff << ((where & 3) << 3))) | 
+	       (val << ((where & 3) << 3));
+
+	if (it8172_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &data))
+	       return -1;
+
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+it8172_pcibios_write_config_dword(struct pci_dev *dev, int where, u32 val)
+{
+	if (where & 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (it8172_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &val))
+	       return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops it8172_pci_ops = {
+	it8172_pcibios_read_config_byte,
+        it8172_pcibios_read_config_word,
+	it8172_pcibios_read_config_dword,
+	it8172_pcibios_write_config_byte,
+	it8172_pcibios_write_config_word,
+	it8172_pcibios_write_config_dword
+};
+
+void __init pcibios_init(void)
+{
+
+	printk("PCI: Probing PCI hardware on host bus 0.\n");
+	pci_scan_bus(0, &it8172_pci_ops, NULL);
+}
+
+int __init
+pcibios_enable_device(struct pci_dev *dev)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for(idx=0; idx<6; idx++) {
+		r = &dev->resource[idx];
+		if (!r->start && r->end) {
+			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (dev->resource[PCI_ROM_RESOURCE].start)
+		cmd |= PCI_COMMAND_MEMORY;
+	if (cmd != old_cmd) {
+		printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+
+void __init
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+    printk("pcibios_align_resource\n");
+}
+
+char * __init
+pcibios_setup(char *str)
+{
+	/* Nothing to do for now.  */
+
+	return str;
+}
+
+void __init
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+                        struct resource *res, int resource)
+{
+	unsigned long where, size;
+	u32 reg;
+
+	where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	size = res->end - res->start;
+	pci_read_config_dword(dev, where, &reg);
+	reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
+	pci_write_config_dword(dev, where, reg);
+}
+
+void __init pcibios_fixup_bus(struct pci_bus *b)
+{
+	printk("pcibios_fixup_bus\n");
+}
+#endif /* CONFIG_PCI */
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/it8172_rtc.c linux/arch/mips/ite-boards/generic/it8172_rtc.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/it8172_rtc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/it8172_rtc.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * RTC routines for ITE8172 MC146818-compatible rtc chip.
+ *
+ */
+#include <asm/spinlock.h>
+#include <linux/mc146818rtc.h>
+#include <asm/it8172/it8172.h>
+
+#define IT8172_RTC_ADR_REG  (IT8172_PCI_IO_BASE + IT_RTC_BASE)
+#define IT8172_RTC_DAT_REG  (IT8172_RTC_ADR_REG + 1)
+
+static volatile char *rtc_adr_reg = KSEG1ADDR((volatile char *)IT8172_RTC_ADR_REG);
+static volatile char *rtc_dat_reg = KSEG1ADDR((volatile char *)IT8172_RTC_DAT_REG);
+
+unsigned char it8172_rtc_read_data(unsigned long addr)
+{
+	unsigned char retval;
+
+	*rtc_adr_reg = addr;
+	retval =  *rtc_dat_reg;
+	return retval;
+}
+
+void it8172_rtc_write_data(unsigned char data, unsigned long addr)
+{
+	*rtc_adr_reg = addr;
+	*rtc_dat_reg = data;
+}
+
+static int it8172_rtc_bcd_mode(void)
+{
+	return 0;
+}
+
+struct rtc_ops it8172_rtc_ops = {
+	&it8172_rtc_read_data,
+	&it8172_rtc_write_data,
+	&it8172_rtc_bcd_mode
+};
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/it8172_setup.c linux/arch/mips/ite-boards/generic/it8172_setup.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/it8172_setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/it8172_setup.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,310 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	IT8172/QED5231 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/serial_reg.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/it8172/it8172.h>
+#include <asm/it8712.h>
+#ifdef CONFIG_PC_KEYB
+#include <asm/keyboard.h>
+#endif
+
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
+extern void console_setup(char *, int *);
+char serial_console[20];
+#endif
+
+extern struct rtc_ops it8172_rtc_ops;
+extern struct resource ioport_resource;
+extern unsigned long mips_io_port_base;
+#ifdef CONFIG_BLK_DEV_IDE
+extern struct ide_ops std_ide_ops;
+extern struct ide_ops *ide_ops;
+#endif
+#ifdef CONFIG_PC_KEYB
+extern struct kbd_ops std_kbd_ops;
+int init_8712_keyboard(void);
+#endif
+
+extern int SearchIT8712(void);
+extern void InitLPCInterface(void);
+extern char * __init prom_getcmdline(void);
+extern void it8172_restart(void);
+extern void it8172_halt(void);
+extern void it8172_power_off(void);
+
+#ifdef CONFIG_IT8172_REVC
+struct {
+    struct resource ram;
+    struct resource pci_mem;
+    struct resource pci_io;
+    struct resource flash;
+    struct resource boot;
+} it8172_resources = {
+    { "RAM",           0,          0,          IORESOURCE_MEM }, /* to be initted */
+    { "PCI Mem",       0x10000000, 0x13FFFFFF, IORESOURCE_MEM },
+    { "PCI I/O",       0x14000000, 0x17FFFFFF                 },
+    { "Flash",         0x08000000, 0x0CFFFFFF                 },
+    { "Boot ROM",      0x1FC00000, 0x1FFFFFFF                 }
+};
+#else
+struct {
+    struct resource ram;
+    struct resource pci_mem0;
+    struct resource pci_mem1;
+    struct resource pci_io;
+    struct resource pci_mem2;
+    struct resource pci_mem3;
+    struct resource flash;
+    struct resource boot;
+} it8172_resources = {
+    { "RAM",           0,          0,          IORESOURCE_MEM }, /* to be initted */
+    { "PCI Mem0",      0x0C000000, 0x0FFFFFFF, IORESOURCE_MEM },
+    { "PCI Mem1",      0x10000000, 0x13FFFFFF, IORESOURCE_MEM },
+    { "PCI I/O",       0x14000000, 0x17FFFFFF                 },
+    { "PCI Mem2",      0x1A000000, 0x1BFFFFFF, IORESOURCE_MEM },
+    { "PCI Mem3",      0x1C000000, 0x1FBFFFFF, IORESOURCE_MEM },
+    { "Flash",         0x08000000, 0x0CFFFFFF                 },
+    { "Boot ROM",      0x1FC00000, 0x1FFFFFFF                 }
+};
+#endif
+
+
+void __init it8172_init_ram_resource(unsigned long memsize)
+{
+	it8172_resources.ram.end = memsize;
+}
+
+void __init it8172_setup(void)
+{
+#ifdef CONFIG_BLK_DEV_IT8172
+	unsigned short dsr;
+#endif
+	char *argptr;
+
+	argptr = prom_getcmdline();
+#ifdef CONFIG_SERIAL_CONSOLE
+	if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) {
+		strcpy(serial_console, "ttyS0,115200");
+		console_setup(serial_console, NULL);
+	}
+#endif	  
+
+	rtc_ops = &it8172_rtc_ops;
+
+	_machine_restart = it8172_restart;
+	_machine_halt = it8172_halt;
+	_machine_power_off = it8172_power_off;
+
+	/*
+	* IO/MEM resources. 
+	*
+	* revisit this area.
+	*/
+	mips_io_port_base = KSEG1;
+	ioport_resource.start = it8172_resources.pci_io.start;
+	ioport_resource.end = it8172_resources.pci_io.end;
+#ifdef CONFIG_IT8172_REVC
+	iomem_resource.start = it8172_resources.pci_mem.start;
+	iomem_resource.end = it8172_resources.pci_mem.end;
+#else
+	iomem_resource.start = it8172_resources.pci_mem0.start;
+	iomem_resource.end = it8172_resources.pci_mem3.end;
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+#endif
+
+#ifdef CONFIG_BLK_DEV_IT8172
+	/*
+	 * Pull IDE device out of standby mode.
+	 */
+	IT_IO_READ16(IT_PM_DSR, dsr);
+	dsr &= ~IT_PM_DSR_IDESB;
+	IT_IO_WRITE16(IT_PM_DSR, dsr);
+
+	ide_ops = &std_ide_ops;
+#endif
+
+#ifdef CONFIG_FB
+    conswitchp = &dummy_con;
+#endif
+
+	InitLPCInterface();
+
+#ifdef CONFIG_MIPS_ITE8172
+	if (SearchIT8712()) {
+		printk("Found IT8712 Super IO\n");
+		// enable IT8712 serial port
+		LPCSetConfig(LDN_SERIAL1, 0x30, 0x01); /* enable */
+		LPCSetConfig(LDN_SERIAL1, 0x23, 0x01); /* clock selection */
+#ifdef CONFIG_PC_KEYB
+		if (init_8712_keyboard()) {
+			printk("Unable to initialize keyboard\n");
+			LPCSetConfig(LDN_KEYBOARD, 0x30, 0x0); /* disable keyboard */
+		}
+		else {
+			LPCSetConfig(LDN_KEYBOARD, 0x30, 0x1); /* enable keyboard */
+			LPCSetConfig(LDN_KEYBOARD, 0xf0, 0x2);
+			LPCSetConfig(LDN_KEYBOARD, 0x71, 0x3);
+
+			LPCSetConfig(LDN_MOUSE, 0x30, 0x1); /* enable mouse */
+
+			LPCSetConfig(0x4, 0x30, 0x1);
+			LPCSetConfig(0x4, 0xf4, LPCGetConfig(0x4, 0xf4) | 0x80);
+
+			if ((LPCGetConfig(LDN_KEYBOARD, 0x30) == 0) || 
+					(LPCGetConfig(LDN_MOUSE, 0x30) == 0)) 
+				printk("Error: keyboard or mouse not enabled\n");
+
+			kbd_ops = &std_kbd_ops;
+		}
+#endif
+	}
+	else {
+		printk("IT8712 Super IO not found\n");
+	}
+#endif
+
+#ifdef CONFIG_IT8172_CIR
+	{
+		unsigned long data;
+		//printk("Enabling CIR0\n");
+		IT_IO_READ16(IT_PM_DSR, data);
+		data &= ~IT_PM_DSR_CIR0SB;
+		IT_IO_WRITE16(IT_PM_DSR, data);
+		//printk("DSR register: %x\n", (unsigned)IT_IO_READ16(IT_PM_DSR, data));
+	}
+#endif
+#ifdef CONFIG_IT8172_SCR0
+	{
+		unsigned i; 
+		/* Enable Smart Card Reader 0 */
+		/* First power it up */
+		IT_IO_READ16(IT_PM_DSR, i);
+		i &= ~IT_PM_DSR_SCR0SB;
+		IT_IO_WRITE16(IT_PM_DSR, i);
+		/* Then initialize its registers */
+		outb(( IT_SCR_SFR_GATE_UART_OFF     << IT_SCR_SFR_GATE_UART_BIT
+		      |IT_SCR_SFR_FET_CHARGE_213_US << IT_SCR_SFR_FET_CHARGE_BIT
+		      |IT_SCR_SFR_CARD_FREQ_3_5_MHZ << IT_SCR_SFR_CARD_FREQ_BIT
+		      |IT_SCR_SFR_FET_ACTIVE_INVERT << IT_SCR_SFR_FET_ACTIVE_BIT
+		      |IT_SCR_SFR_ENABLE_ON         << IT_SCR_SFR_ENABLE_BIT),
+		     IT8172_PCI_IO_BASE + IT_SCR0_BASE + IT_SCR_SFR);
+		outb(IT_SCR_SCDR_RESET_MODE_ASYNC << IT_SCR_SCDR_RESET_MODE_BIT,
+		     IT8172_PCI_IO_BASE + IT_SCR0_BASE + IT_SCR_SCDR);
+	}
+#endif /* CONFIG_IT8172_SCR0 */
+#ifdef CONFIG_IT8172_SCR1
+	{
+		unsigned i; 
+		/* Enable Smart Card Reader 1 */
+		/* First power it up */
+		IT_IO_READ16(IT_PM_DSR, i);
+		i &= ~IT_PM_DSR_SCR1SB;
+		IT_IO_WRITE16(IT_PM_DSR, i);
+		/* Then initialize its registers */
+		outb(( IT_SCR_SFR_GATE_UART_OFF     << IT_SCR_SFR_GATE_UART_BIT
+		      |IT_SCR_SFR_FET_CHARGE_213_US << IT_SCR_SFR_FET_CHARGE_BIT
+		      |IT_SCR_SFR_CARD_FREQ_3_5_MHZ << IT_SCR_SFR_CARD_FREQ_BIT
+		      |IT_SCR_SFR_FET_ACTIVE_INVERT << IT_SCR_SFR_FET_ACTIVE_BIT
+		      |IT_SCR_SFR_ENABLE_ON         << IT_SCR_SFR_ENABLE_BIT),
+		     IT8172_PCI_IO_BASE + IT_SCR1_BASE + IT_SCR_SFR);
+		outb(IT_SCR_SCDR_RESET_MODE_ASYNC << IT_SCR_SCDR_RESET_MODE_BIT,
+		     IT8172_PCI_IO_BASE + IT_SCR1_BASE + IT_SCR_SCDR);
+	}
+#endif /* CONFIG_IT8172_SCR1 */
+}
+
+
+#ifdef CONFIG_PC_KEYB
+/*
+ * According to the ITE Special BIOS Note for waking up the 
+ * keyboard controller...
+ */
+int init_8712_keyboard()
+{
+	unsigned int cmd_port = 0x14000064;
+	unsigned int data_port = 0x14000060;
+	unsigned char data;
+	int i;
+
+	printk("8712 keyboard init");
+
+	outb(0xaa, cmd_port); /* send self-test cmd */
+	i = 0;
+	while (!(inb(cmd_port) & 0x1)) { /* wait output buffer full */
+		i++;
+		if (i > 0xffffff)
+			return 1;
+	}
+
+	data = inb(data_port);
+	outb(0xcb, cmd_port); /* set ps2 mode */
+	while (inb(cmd_port) & 0x2) { /* wait while input buffer full */
+		i++;
+		if (i > 0xffffff)
+			return 1;
+	}
+	outb(0x01, data_port);
+	while (inb(cmd_port) & 0x2) { /* wait while input buffer full */
+		i++;
+		if (i > 0xffffff)
+			return 1;
+	}
+
+	outb(0x60, cmd_port); /* write 8042 command byte */
+	while (inb(cmd_port) & 0x2) { /* wait while input buffer full */
+		i++;
+		if (i > 0xffffff)
+			return 1;
+	}
+	outb(0x45, data_port); /* at interface, keyboard enabled, system flag */
+	while (inb(cmd_port) & 0x2) { /* wait while input buffer full */
+		i++;
+		if (i > 0xffffff)
+			return 1;
+	}
+
+	outb(0xae, cmd_port); /* enable interface */
+	return 0;
+}
+#endif
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/lpc.c linux/arch/mips/ite-boards/generic/lpc.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/lpc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/lpc.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,144 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	ITE Semi IT8712 Super I/O functions.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <asm/io.h>
+#include <asm/types.h>
+#include <asm/it8712.h>
+#include <asm/it8172/it8172.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+void LPCEnterMBPnP()
+{
+	int i;
+	unsigned char key[4] = {0x87, 0x01, 0x55, 0x55};
+
+	for (i = 0; i<4; i++)
+		outb(key[i], LPC_KEY_ADDR);
+
+}
+
+void LPCExitMBPnP()
+{
+	outb(0x02, LPC_KEY_ADDR);
+	outb(0x02, LPC_DATA_ADDR);
+}
+
+void LPCSetConfig(char LdnNumber, char Index, char data)
+{
+	LPCEnterMBPnP();				// Enter IT8712 MB PnP mode
+	outb(0x07, LPC_KEY_ADDR);
+	outb(LdnNumber, LPC_DATA_ADDR);
+	outb(Index, LPC_KEY_ADDR);	
+	outb(data, LPC_DATA_ADDR);
+	LPCExitMBPnP();
+}
+
+char LPCGetConfig(char LdnNumber, char Index)
+{
+	char rtn;
+
+	LPCEnterMBPnP();				// Enter IT8712 MB PnP mode
+	outb(0x07, LPC_KEY_ADDR);
+	outb(LdnNumber, LPC_DATA_ADDR);
+	outb(Index, LPC_KEY_ADDR);	
+	rtn = inb(LPC_DATA_ADDR);
+	LPCExitMBPnP();
+	return rtn;
+}
+
+int SearchIT8712()
+{
+	unsigned char Id1, Id2;
+	unsigned short Id;
+
+	LPCEnterMBPnP();
+	outb(0x20, LPC_KEY_ADDR); /* chip id byte 1 */
+	Id1 = inb(LPC_DATA_ADDR);
+	outb(0x21, LPC_KEY_ADDR); /* chip id byte 2 */
+	Id2 = inb(LPC_DATA_ADDR);
+	Id = (Id1 << 8) | Id2;
+	LPCExitMBPnP();
+	if (Id == 0x8712) 
+		return TRUE;
+	else
+		return FALSE;
+}
+
+void InitLPCInterface()
+{
+	unsigned char bus, dev_fn;
+	unsigned long data;
+
+	bus = 0;
+	dev_fn = 1<<3 | 4; 
+
+
+	/* pci cmd, SERR# Enable */
+	IT_WRITE(IT_CONFADDR,  
+		 (bus         << IT_BUSNUM_SHF)   |
+		 (dev_fn      << IT_FUNCNUM_SHF) |
+		 ((0x4 / 4) << IT_REGNUM_SHF));
+	IT_READ(IT_CONFDATA, data);
+	data |= 0x0100;
+	IT_WRITE(IT_CONFADDR,  
+		 (bus         << IT_BUSNUM_SHF)   |
+		 (dev_fn      << IT_FUNCNUM_SHF) |
+		 ((0x4 / 4) << IT_REGNUM_SHF));
+	IT_WRITE(IT_CONFDATA, data);
+
+	/* setup serial irq control register */
+	IT_WRITE(IT_CONFADDR,  
+		 (bus         << IT_BUSNUM_SHF)   |
+		 (dev_fn      << IT_FUNCNUM_SHF) |
+		 ((0x48 / 4) << IT_REGNUM_SHF));
+	IT_READ(IT_CONFDATA, data);
+	data  = (data & 0xffff00ff) | 0xc400;
+	IT_WRITE(IT_CONFADDR,  
+		 (bus         << IT_BUSNUM_SHF)   |
+		 (dev_fn      << IT_FUNCNUM_SHF) |
+		 ((0x48 / 4) << IT_REGNUM_SHF));
+	IT_WRITE(IT_CONFDATA, data);
+
+
+	/* Enable I/O Space Subtractive Decode */
+	/* default 0x4C is 0x3f220000 */
+	IT_WRITE(IT_CONFADDR,  
+		 (bus         << IT_BUSNUM_SHF)   |
+		 (dev_fn      << IT_FUNCNUM_SHF) |
+		 ((0x4C / 4) << IT_REGNUM_SHF));
+	IT_WRITE(IT_CONFDATA, 0x3f2200f3);
+}
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/pmon_prom.c linux/arch/mips/ite-boards/generic/pmon_prom.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/pmon_prom.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/pmon_prom.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,138 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *    PROM library initialisation code, assuming a version of
+ *    pmon is the boot code.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ * This file was derived from Carsten Langgaard's 
+ * arch/mips/mips-boards/xx files.
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+/* #define DEBUG_CMDLINE */
+
+char arcs_cmdline[COMMAND_LINE_SIZE];
+int prom_argc;
+char **prom_argv, **prom_envp;
+
+typedef struct
+{
+    char *name;
+/*    char *val; */
+}t_env_var;
+
+
+char * __init prom_getcmdline(void)
+{
+	return &(arcs_cmdline[0]);
+}
+
+void  __init prom_init_cmdline(void)
+{
+	char *cp;
+	int actr;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	cp = &(arcs_cmdline[0]);
+	while(actr < prom_argc) {
+	        strcpy(cp, prom_argv[actr]);
+		cp += strlen(prom_argv[actr]);
+		*cp++ = ' ';
+		actr++;
+	}
+	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+		--cp;
+	*cp = '\0';
+
+}
+
+
+char *prom_getenv(char *envname)
+{
+	/*
+	 * Return a pointer to the given environment variable.
+	 * Environment variables are stored in the form of "memsize=64".
+	 */
+
+	t_env_var *env = (t_env_var *)prom_envp;
+	int i;
+
+	i = strlen(envname);
+
+	while(env->name) {
+		if(strncmp(envname, env->name, i) == 0) {
+			return(env->name + strlen(envname) + 1);
+		}
+		env++;
+	}
+	return(NULL);
+}
+
+static inline unsigned char str2hexnum(unsigned char c)
+{
+	if(c >= '0' && c <= '9')
+	return c - '0';
+	if(c >= 'a' && c <= 'f')
+	return c - 'a' + 10;
+	return 0; /* foo */
+}
+
+int __init page_is_ram(unsigned long pagenr)
+{
+    return 1;
+}
+
+void prom_free_prom_memory (void)
+{
+}
+
+unsigned long __init prom_get_memsize(void)
+{
+	char *memsize_str;
+	unsigned int memsize;
+
+	memsize_str = prom_getenv("memsize");
+	if (!memsize_str) {
+		printk("memsize unknown: setting to 32MB\n");
+		memsize = 32; 
+	} else {
+#ifdef DEBUG
+		printk("prom_memsize: %s\n", memsize_str);
+#endif
+		memsize = simple_strtol(memsize_str, NULL, 0);
+	}
+	return memsize;
+}
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/puts.c linux/arch/mips/ite-boards/generic/puts.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/puts.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/puts.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,144 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Low level uart routines to directly access a 16550 uart.
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+
+#define SERIAL_BASE   0xB4011800 /* it8172 */
+#define SER_CMD       5
+#define SER_DATA      0x00
+#define TX_BUSY       0x20
+
+#define TIMEOUT       0xffff
+#undef SLOW_DOWN
+
+static const char digits[16] = "0123456789abcdef";
+static volatile unsigned char * const com1 = (unsigned char *)SERIAL_BASE;
+
+
+#ifdef SLOW_DOWN
+static inline void slow_down()
+{
+    int k;
+    for (k=0; k<10000; k++);
+}
+#else
+#define slow_down()
+#endif
+
+void
+putch(const unsigned char c)
+{
+    unsigned char ch;
+    int i = 0;
+
+    do {
+        ch = com1[SER_CMD];
+        slow_down();
+        i++;
+        if (i>TIMEOUT) {
+            break;
+        }
+    } while (0 == (ch & TX_BUSY));
+    com1[SER_DATA] = c;
+}
+
+void
+puts(unsigned char *cp)
+{
+    unsigned char ch;
+    int i = 0;
+
+    while (*cp) {
+        do {
+             ch = com1[SER_CMD];
+            slow_down();
+            i++;
+            if (i>TIMEOUT) {
+                break;
+            }
+        } while (0 == (ch & TX_BUSY));
+        com1[SER_DATA] = *cp++;
+    }
+    putch('\r');
+    putch('\n');
+}
+
+void
+fputs(unsigned char *cp)
+{
+    unsigned char ch;
+    int i = 0;
+
+    while (*cp) {
+
+        do {
+             ch = com1[SER_CMD];
+             slow_down();
+            i++;
+            if (i>TIMEOUT) {
+                break;
+            }
+        } while (0 == (ch & TX_BUSY));
+        com1[SER_DATA] = *cp++;
+    }
+}
+
+
+void
+put64(uint64_t ul)
+{
+    int cnt;
+    unsigned ch;
+
+    cnt = 16;            /* 16 nibbles in a 64 bit long */
+    putch('0');
+    putch('x');
+    do {
+        cnt--;
+        ch = (unsigned char)(ul >> cnt * 4) & 0x0F;
+                putch(digits[ch]);
+    } while (cnt > 0);
+}
+
+void
+put32(unsigned u)
+{
+    int cnt;
+    unsigned ch;
+
+    cnt = 8;            /* 8 nibbles in a 32 bit long */
+    putch('0');
+    putch('x');
+    do {
+        cnt--;
+        ch = (unsigned char)(u >> cnt * 4) & 0x0F;
+                putch(digits[ch]);
+    } while (cnt > 0);
+}
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/reset.c linux/arch/mips/ite-boards/generic/reset.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/reset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/reset.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,61 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	ITE 8172 reset routines.
+ *
+ * Copyright (C) 1997, 2001 Ralf Baechle
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+void it8172_restart(char *command)
+{
+	set_cp0_status(ST0_BEV | ST0_ERL);
+	change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+	flush_cache_all();
+	write_32bit_cp0_register(CP0_WIRED, 0);
+	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+void it8172_halt(void)
+{
+	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
+	while (1)
+		__asm__(".set\tmips3\n\t"
+	                "wait\n\t"
+			".set\tmips0");
+}
+
+void it8172_power_off(void)
+{
+	it8172_halt();
+}
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/generic/time.c linux/arch/mips/ite-boards/generic/time.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/generic/time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/generic/time.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,378 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Setting up the clock on the MIPS boards.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/it8172/it8172_int.h>
+
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+
+extern void enable_cpu_timer(void);
+extern volatile unsigned long wall_jiffies;
+extern rwlock_t xtime_lock;
+
+unsigned long missed_heart_beats = 0;
+static long last_rtc_update = 0;
+static unsigned long r4k_offset; /* Amount to increment compare reg each time */
+static unsigned long r4k_cur;    /* What counter should be at next timer irq */
+static unsigned int timer_tick_count=0;
+
+static inline void ack_r4ktimer(unsigned long newval)
+{
+	write_32bit_cp0_register(CP0_COMPARE, newval);
+}
+
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you won't notice until after reboot!
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+ 		retval = -1;
+	}
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+	return retval;
+}
+
+
+/*
+ * There are a lot of conceptually broken versions of the MIPS timer interrupt
+ * handler floating around.  This one is rather different, but the algorithm
+ * is provably more robust.
+ */
+void mips_timer_interrupt(struct pt_regs *regs)
+{
+	if (r4k_offset == 0)
+		goto null;
+
+	do {
+		kstat.irqs[0][MIPS_CPU_TIMER_IRQ]++;
+		do_timer(regs);
+
+		/* Historical comment/code:
+ 		 * RTC time of day s updated approx. every 11 
+ 		 * minutes.  Because of how the numbers work out 
+ 		 * we need to make absolutely sure we do this update
+ 		 * within 500ms before the * next second starts, 
+ 		 * thus the following code.
+ 		 */
+		read_lock(&xtime_lock);
+		if ((time_status & STA_UNSYNC) == 0 
+		    && xtime.tv_sec > last_rtc_update + 660 
+		    && xtime.tv_usec >= 500000 - (tick >> 1) 
+		    && xtime.tv_usec <= 500000 + (tick >> 1))
+			if (set_rtc_mmss(xtime.tv_sec) == 0)
+				last_rtc_update = xtime.tv_sec;
+			else {
+				/* do it again in 60 s */
+	    			last_rtc_update = xtime.tv_sec - 600; 
+			}
+		read_unlock(&xtime_lock);
+
+		r4k_cur += r4k_offset;
+		ack_r4ktimer(r4k_cur);
+
+	} while (((unsigned long)read_32bit_cp0_register(CP0_COUNT)
+	         - r4k_cur) < 0x7fffffff);
+
+	return;
+
+null:
+	ack_r4ktimer(0);
+}
+
+/* 
+ * Figure out the r4k offset, the amount to increment the compare
+ * register for each time tick. 
+ * Use the RTC to calculate offset.
+ */
+static unsigned long __init cal_r4koff(void)
+{
+	unsigned long count;
+	unsigned int flags;
+
+	__save_and_cli(flags);
+
+	/* Start counter exactly on falling edge of update flag */
+	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+	/* Start r4k counter. */
+	write_32bit_cp0_register(CP0_COUNT, 0);
+
+	/* Read counter exactly on falling edge of update flag */
+	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+	count = read_32bit_cp0_register(CP0_COUNT);
+
+	/* restore interrupts */
+	__restore_flags(flags);
+		
+	return (count / HZ);
+}
+
+static unsigned long __init get_mips_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	unsigned char save_control;
+
+	save_control = CMOS_READ(RTC_CONTROL);
+
+	/* Freeze it. */
+	CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL);
+
+	/* Read regs. */
+	sec = CMOS_READ(RTC_SECONDS);
+	min = CMOS_READ(RTC_MINUTES);
+	hour = CMOS_READ(RTC_HOURS);
+
+	if (!(save_control & RTC_24H))
+	{
+		if ((hour & 0xf) == 0xc)
+		        hour &= 0x80;
+	        if (hour & 0x80)
+		        hour = (hour & 0xf) + 12;     
+	}
+	day = CMOS_READ(RTC_DAY_OF_MONTH);
+	mon = CMOS_READ(RTC_MONTH);
+	year = CMOS_READ(RTC_YEAR);
+
+	/* Unfreeze clock. */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+
+	if ((year += 1900) < 1970)
+	        year += 100;
+
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+void __init time_init(void)
+{
+        unsigned int est_freq, flags;
+
+        /* Set Data mode - binary. */ 
+        CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
+
+	printk("calculating r4koff... ");
+	r4k_offset = cal_r4koff();
+	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
+
+	est_freq = 2*r4k_offset*HZ;	
+	est_freq += 5000;    /* round */
+	est_freq -= est_freq%10000;
+	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, 
+	       (est_freq%1000000)*100/1000000);
+	r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset);
+
+	write_32bit_cp0_register(CP0_COMPARE, r4k_cur);
+
+	enable_cpu_timer();
+
+	/* Read time from the RTC chipset. */
+	write_lock_irqsave (&xtime_lock, flags);
+	xtime.tv_sec = get_mips_time();
+	xtime.tv_usec = 0;
+	write_unlock_irqrestore(&xtime_lock, flags);
+}
+
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
+
+/* Cycle counter value at the previous timer interrupt.. */
+
+static unsigned int timerhi = 0, timerlo = 0;
+
+/*
+ * FIXME: Does playing with the RP bit in c0_status interfere with this code?
+ */
+static unsigned long do_fast_gettimeoffset(void)
+{
+	u32 count;
+	unsigned long res, tmp;
+
+	/* Last jiffy when do_fast_gettimeoffset() was called. */
+	static unsigned long last_jiffies=0;
+	unsigned long quotient;
+
+	/*
+	 * Cached "1/(clocks per usec)*2^32" value.
+	 * It has to be recalculated once each jiffy.
+	 */
+	static unsigned long cached_quotient=0;
+
+	tmp = jiffies;
+
+	quotient = cached_quotient;
+
+	if (tmp && last_jiffies != tmp) {
+		last_jiffies = tmp;
+		__asm__(".set\tnoreorder\n\t"
+			".set\tnoat\n\t"
+			".set\tmips3\n\t"
+			"lwu\t%0,%2\n\t"
+			"dsll32\t$1,%1,0\n\t"
+			"or\t$1,$1,%0\n\t"
+			"ddivu\t$0,$1,%3\n\t"
+			"mflo\t$1\n\t"
+			"dsll32\t%0,%4,0\n\t"
+			"nop\n\t"
+			"ddivu\t$0,%0,$1\n\t"
+			"mflo\t%0\n\t"
+			".set\tmips0\n\t"
+			".set\tat\n\t"
+			".set\treorder"
+			:"=&r" (quotient)
+			:"r" (timerhi),
+			 "m" (timerlo),
+			 "r" (tmp),
+			 "r" (USECS_PER_JIFFY)
+			:"$1");
+		cached_quotient = quotient;
+	}
+
+	/* Get last timer tick in absolute kernel time */
+	count = read_32bit_cp0_register(CP0_COUNT);
+
+	/* .. relative to previous jiffy (32 bits is enough) */
+	count -= timerlo;
+
+	__asm__("multu\t%1,%2\n\t"
+		"mfhi\t%0"
+		:"=r" (res)
+		:"r" (count),
+		 "r" (quotient));
+
+	/*
+ 	 * Due to possible jiffies inconsistencies, we need to check 
+	 * the result so that we'll get a timer that is monotonic.
+	 */
+	if (res >= USECS_PER_JIFFY)
+		res = USECS_PER_JIFFY-1;
+
+	return res;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned int flags;
+
+	read_lock_irqsave (&xtime_lock, flags);
+	*tv = xtime;
+	tv->tv_usec += do_fast_gettimeoffset();
+
+	/*
+	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
+	 * is nonzero if the timer bottom half hasnt executed yet.
+	 */
+	if (jiffies - wall_jiffies)
+		tv->tv_usec += USECS_PER_JIFFY;
+
+	read_unlock_irqrestore (&xtime_lock, flags);
+
+	if (tv->tv_usec >= 1000000) {
+		tv->tv_usec -= 1000000;
+		tv->tv_sec++;
+	}
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+	write_lock_irq (&xtime_lock);
+
+	/* This is revolting. We need to set the xtime.tv_usec correctly.
+	 * However, the value in this location is is value at the last tick.
+	 * Discover what correction gettimeofday would have done, and then
+	 * undo it!
+	 */
+	tv->tv_usec -= do_fast_gettimeoffset();
+
+	if (tv->tv_usec < 0) {
+		tv->tv_usec += 1000000;
+		tv->tv_sec--;
+	}
+
+	xtime = *tv;
+	time_adjust = 0;		/* stop active adjtime() */
+	time_status |= STA_UNSYNC;
+	time_maxerror = NTP_PHASE_LIMIT;
+	time_esterror = NTP_PHASE_LIMIT;
+
+	write_unlock_irq (&xtime_lock);
+}
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/qed-4n-s01b/Makefile linux/arch/mips/ite-boards/qed-4n-s01b/Makefile
--- linux-2.4.4-pre3/arch/mips/ite-boards/qed-4n-s01b/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/qed-4n-s01b/Makefile	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,37 @@
+#
+#  Copyright 2000 MontaVista Software Inc.
+#  Author: MontaVista Software, Inc.
+#     	ppopov@mvista.com or support@mvista.com
+#
+# Makefile for the ITE 8172 (qed-4n-s01b) board, board
+# specific files.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+all: ite.o
+
+O_TARGET := ite.o
+
+obj-y := init.o 
+
+ifdef CONFIG_PCI
+obj-y += pci_fixup.o
+endif
+
+ifdef CONFIG_BLK_DEV_INITRD
+obj-y += le_ramdisk.o
+endif
+
+
+dep:
+	$(CPP) -M *.c > .depend
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/qed-4n-s01b/README linux/arch/mips/ite-boards/qed-4n-s01b/README
--- linux-2.4.4-pre3/arch/mips/ite-boards/qed-4n-s01b/README	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/qed-4n-s01b/README	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,2 @@
+This is an ITE (www.iteusa.com) eval board for the ITE 8172G
+system controller, with a QED 5231 CPU.
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/qed-4n-s01b/init.c linux/arch/mips/ite-boards/qed-4n-s01b/init.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/qed-4n-s01b/init.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/qed-4n-s01b/init.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,87 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	IT8172/QED5231 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_dbg.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+
+extern char _end;
+extern void  __init prom_init_cmdline(void);
+extern unsigned long __init prom_get_memsize(void);
+extern void __init it8172_init_ram_resource(unsigned long memsize);
+
+#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_ALIGN(x)	(((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
+
+
+int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
+{
+	unsigned long mem_size, free_start, free_end, bootmap_size;
+	unsigned long pcicr;
+
+	prom_argc = argc;
+	prom_argv = argv;
+	prom_envp = envp;
+
+	puts("ITE board running...");
+
+	mips_machgroup = MACH_GROUP_ITE;
+	mips_machtype = MACH_QED_4N_S01B;  /* ITE board name/number */
+
+	prom_init_cmdline();
+	mem_size = prom_get_memsize();
+
+	printk("Memory size: %dMB\n", (unsigned)mem_size);
+
+	mem_size <<= 20; /* MB */
+
+	/*
+	 * make the entire physical memory visible to pci bus masters
+	 */
+	IT_READ(IT_MC_PCICR, pcicr);
+	pcicr &= ~0x1f; 
+	pcicr |= (mem_size - 1) >> 22;
+	IT_WRITE(IT_MC_PCICR, pcicr);
+
+	it8172_init_ram_resource(mem_size);
+	add_memory_region(0, 20 << 20, BOOT_MEM_RAM);
+
+	return 0;
+}
diff -urN linux-2.4.4-pre3/arch/mips/ite-boards/qed-4n-s01b/pci_fixup.c linux/arch/mips/ite-boards/qed-4n-s01b/pci_fixup.c
--- linux-2.4.4-pre3/arch/mips/ite-boards/qed-4n-s01b/pci_fixup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ite-boards/qed-4n-s01b/pci_fixup.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,197 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Board specific pci fixups.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_PCI
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_pci.h>
+#include <asm/it8172/it8172_int.h>
+
+void __init board_int_line_fixup(struct pci_dev *dev)     
+{
+	unsigned int slot, func;
+	unsigned char pin;
+        const int internal_func_irqs[7] = {
+            IT8172_AC97_IRQ,
+            IT8172_DMA_IRQ,
+            IT8172_CDMA_IRQ,
+            IT8172_USB_IRQ,
+            IT8172_BRIDGE_MASTER_IRQ,
+            IT8172_IDE_IRQ,
+            IT8172_MC68K_IRQ
+        };
+
+#ifdef DEBUG
+	printk("board_int_line_fixup bus %d\n", dev->bus->number);
+#endif
+	if (dev->bus->number != 0)
+		return;
+
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+
+#ifdef DEBUG
+	pci_read_config_dword(dev, PCI_SUBSYSTEM_VENDOR_ID, &vendor);
+#endif
+
+	slot = PCI_SLOT(dev->devfn);
+        func = PCI_FUNC(dev->devfn);
+
+	switch (slot) {
+                case 0x01:
+                    /*
+                     * Internal device 1 is actually 7 different internal
+                     * devices on the IT8172G (a multi-function device).
+                     */
+                    if (func < 7)
+                        dev->irq = internal_func_irqs[func];
+                    break;
+		case 0x10:
+			switch (pin) {
+				case 1: /* pin A */
+					dev->irq = IT8172_PCI_INTA_IRQ;
+					break;
+				case 2: /* pin B */
+					dev->irq = IT8172_PCI_INTB_IRQ;
+					break;
+				case 3: /* pin C */
+					dev->irq = IT8172_PCI_INTC_IRQ;
+					break;
+				case 4: /* pin D */
+					dev->irq = IT8172_PCI_INTD_IRQ;
+					break;
+				default:
+					dev->irq = 0xff; 
+					break;
+
+			}
+			break;
+		case 0x11:
+			switch (pin) {
+				case 1: /* pin A */
+					dev->irq = IT8172_PCI_INTA_IRQ;
+					break;
+				case 2: /* pin B */
+					dev->irq = IT8172_PCI_INTB_IRQ;
+					break;
+				case 3: /* pin C */
+					dev->irq = IT8172_PCI_INTC_IRQ;
+					break;
+				case 4: /* pin D */
+					dev->irq = IT8172_PCI_INTD_IRQ;
+					break;
+				default:
+					dev->irq = 0xff; 
+					break;
+
+			}
+			break;
+		case 0x12:
+			switch (pin) {
+				case 1: /* pin A */
+					dev->irq = IT8172_PCI_INTB_IRQ;
+					break;
+				case 2: /* pin B */
+					dev->irq = IT8172_PCI_INTC_IRQ;
+					break;
+				case 3: /* pin C */
+					dev->irq = IT8172_PCI_INTD_IRQ;
+					break;
+				case 4: /* pin D */
+					dev->irq = IT8172_PCI_INTA_IRQ;
+					break;
+				default:
+					dev->irq = 0xff; 
+					break;
+
+			}
+			break;
+		case 0x13:
+			switch (pin) {
+				case 1: /* pin A */
+					dev->irq = IT8172_PCI_INTC_IRQ;
+					break;
+				case 2: /* pin B */
+					dev->irq = IT8172_PCI_INTD_IRQ;
+					break;
+				case 3: /* pin C */
+					dev->irq = IT8172_PCI_INTA_IRQ;
+					break;
+				case 4: /* pin D */
+					dev->irq = IT8172_PCI_INTB_IRQ;
+					break;
+				default:
+					dev->irq = 0xff; 
+					break;
+
+			}
+			break;
+		case 0x14:
+			switch (pin) {
+				case 1: /* pin A */
+					dev->irq = IT8172_PCI_INTD_IRQ;
+					break;
+				case 2: /* pin B */
+					dev->irq = IT8172_PCI_INTA_IRQ;
+					break;
+				case 3: /* pin C */
+					dev->irq = IT8172_PCI_INTB_IRQ;
+					break;
+				case 4: /* pin D */
+					dev->irq = IT8172_PCI_INTC_IRQ;
+					break;
+				default:
+					dev->irq = 0xff; 
+					break;
+
+			}
+			break;
+		default:
+			return;
+	}
+
+#ifdef DEBUG
+	printk("irq fixup: slot %d, vendor %x, int line %d, int number %d\n",
+			slot, vendor, pin, dev->irq);
+#endif
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+
+}
+
+struct pci_fixup pcibios_fixups[] = {
+	{ PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, board_int_line_fixup },
+	{ 0 }
+};
+#endif
diff -urN linux-2.4.4-pre3/arch/mips/jazz/Makefile linux/arch/mips/jazz/Makefile
--- linux-2.4.4-pre3/arch/mips/jazz/Makefile	Sat May 13 08:29:14 2000
+++ linux/arch/mips/jazz/Makefile	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.5 1999/01/03 17:50:47 ralf Exp $
 #
 # Makefile for the Jazz family specific parts of the kernel
 #
@@ -8,17 +7,17 @@
 #
 
 .S.s:
-	$(CPP) $(CFLAGS) $< -o $*.s
+	$(CPP) $(CFLAGS) $< -o $@
 .S.o:
-	$(CC) $(CFLAGS) -c $< -o $*.o
+	$(CC) $(CFLAGS) -c $< -o $@
 
 all: jazz.o
+
 O_TARGET := jazz.o
-O_OBJS	 := int-handler.o jazzdma.o reset.o rtc-jazz.o setup.o floppy-jazz.o \
-	    kbd-jazz.o
 
-int-handler.o: int-handler.S
+obj-y	 := int-handler.o irq.o jazzdma.o reset.o rtc-jazz.o setup.o \
+	    floppy-jazz.o kbd-jazz.o
 
-clean:
+int-handler.o: int-handler.S
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/kernel/branch.c linux/arch/mips/kernel/branch.c
--- linux-2.4.4-pre3/arch/mips/kernel/branch.c	Wed Dec 10 10:31:09 1997
+++ linux/arch/mips/kernel/branch.c	Mon Dec  3 22:35:22 2001
@@ -5,15 +5,19 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 1997 by Ralf Baechle
+ * Copyright (C) 1996, 97, 2000 by Ralf Baechle
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <asm/branch.h>
+#include <asm/cpu.h>
 #include <asm/inst.h>
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
+#include <asm/bootinfo.h>
+#include <asm/processor.h>
 
 /*
  * Compute the return address and do emulate branch simulation, if required.
@@ -65,7 +69,7 @@
 		switch (insn.i_format.rt) {
 	 	case bltz_op:
 		case bltzl_op:
-			if (regs->regs[insn.i_format.rs] < 0)
+			if ((long)regs->regs[insn.i_format.rs] < 0)
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
 			else
 				epc += 8;
@@ -74,7 +78,7 @@
 
 		case bgez_op:
 		case bgezl_op:
-			if (regs->regs[insn.i_format.rs] >= 0)
+			if ((long)regs->regs[insn.i_format.rs] >= 0)
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
 			else
 				epc += 8;
@@ -84,7 +88,7 @@
 		case bltzal_op:
 		case bltzall_op:
 			regs->regs[31] = epc + 8;
-			if (regs->regs[insn.i_format.rs] < 0)
+			if ((long)regs->regs[insn.i_format.rs] < 0)
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
 			else
 				epc += 8;
@@ -94,7 +98,7 @@
 		case bgezal_op:
 		case bgezall_op:
 			regs->regs[31] = epc + 8;
-			if (regs->regs[insn.i_format.rs] >= 0)
+			if ((long)regs->regs[insn.i_format.rs] >= 0)
 				epc = epc + 4 + (insn.i_format.simmediate << 2);
 			else
 				epc += 8;
@@ -142,7 +146,7 @@
 	case blez_op: /* not really i_format */
 	case blezl_op:
 		/* rt field assumed to be zero */
-		if (regs->regs[insn.i_format.rs] <= 0)
+		if ((long)regs->regs[insn.i_format.rs] <= 0)
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
 		else
 			epc += 8;
@@ -152,7 +156,7 @@
 	case bgtz_op:
 	case bgtzl_op:
 		/* rt field assumed to be zero */
-		if (regs->regs[insn.i_format.rs] > 0)
+		if ((long)regs->regs[insn.i_format.rs] > 0)
 			epc = epc + 4 + (insn.i_format.simmediate << 2);
 		else
 			epc += 8;
@@ -163,6 +167,11 @@
 	 * And now the FPA/cp1 branch instructions.
 	 */
 	case cop1_op:
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+		if(!(mips_cpu.options & MIPS_CPU_FPU))
+			fcr31 = current->thread.fpu.soft.sr;
+		else
+#endif
 		asm ("cfc1\t%0,$31":"=r" (fcr31));
 		bit = (insn.i_format.rt >> 2);
 		bit += (bit != 0);
diff -urN linux-2.4.4-pre3/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c
--- linux-2.4.4-pre3/arch/mips/kernel/process.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/mips/kernel/process.c	Mon Dec  3 22:35:22 2001
@@ -1,12 +1,12 @@
-/* $Id: process.c,v 1.18 2000/01/29 01:41:59 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1994 - 1999 by Ralf Baechle and others.
+ * Copyright (C) 1994 - 2000 by Ralf Baechle and others.
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -21,6 +21,7 @@
 #include <linux/a.out.h>
 
 #include <asm/bootinfo.h>
+#include <asm/cpu.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/mipsregs.h>
@@ -55,7 +56,7 @@
 {
 	/* Forget lazy fpu state */
 	if (last_task_used_math == current) {
-		set_cp0_status(ST0_CU1, ST0_CU1);
+		set_cp0_status(ST0_CU1);
 		__asm__ __volatile__("cfc1\t$0,$31");
 		last_task_used_math = NULL;
 	}
@@ -65,7 +66,7 @@
 {
 	/* Forget lazy fpu state */
 	if (last_task_used_math == current) {
-		set_cp0_status(ST0_CU1, ST0_CU1);
+		set_cp0_status(ST0_CU1);
 		__asm__ __volatile__("cfc1\t$0,$31");
 		last_task_used_math = NULL;
 	}
@@ -81,9 +82,13 @@
 
 	childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32;
 
-	if (last_task_used_math == current) {
-		set_cp0_status(ST0_CU1, ST0_CU1);
-		save_fp(p);
+	if (last_task_used_math == current)
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+		if (mips_cpu.options & MIPS_CPU_FPU)
+#endif
+	{
+			set_cp0_status(ST0_CU1);
+			save_fp(p);
 	}
 	/* set up new TSS. */
 	childregs = (struct pt_regs *) childksp - 1;
diff -urN linux-2.4.4-pre3/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- linux-2.4.4-pre3/arch/mips/kernel/ptrace.c	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/kernel/ptrace.c	Mon Dec  3 22:35:22 2001
@@ -1,14 +1,16 @@
-/* $Id: ptrace.c,v 1.17 1999/09/28 22:25:47 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
  * Copyright (C) 1992 Ross Biro
  * Copyright (C) Linus Torvalds
- * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
  * Copyright (C) 1996 David S. Miller
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999 MIPS Technologies, Inc.
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -24,6 +26,8 @@
 #include <asm/page.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
 
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
@@ -131,13 +135,22 @@
 			break;
 		case FPR_BASE ... FPR_BASE + 31:
 			if (child->used_math) {
+			        unsigned long long *fregs
+					= (unsigned long long *)
+					    &child->thread.fpu.hard.fp_regs[0];
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+			    if(!(mips_cpu.options & MIPS_CPU_FPU)) {
+				    fregs = (unsigned long long *)
+					&child->thread.fpu.soft.regs[0];
+			    } else 
+#endif
 				if (last_task_used_math == child) {
 					enable_cp1();
 					save_fp(child);
 					disable_cp1();
 					last_task_used_math = NULL;
 				}
-				tmp = child->thread.fpu.hard.fp_regs[addr - 32];
+				tmp = (unsigned long) fregs[(addr - 32)];
 			} else {
 				tmp = -1;	/* FP not yet used  */
 			}
@@ -158,6 +171,11 @@
 			tmp = regs->lo;
 			break;
 		case FPC_CSR:
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+			if(!(mips_cpu.options & MIPS_CPU_FPU))
+				tmp = child->thread.fpu.soft.sr;
+			else
+#endif
 			tmp = child->thread.fpu.hard.control;
 			break;
 		case FPC_EIR: {	/* implementation / version register */
@@ -198,9 +216,17 @@
 			regs->regs[addr] = data;
 			break;
 		case FPR_BASE ... FPR_BASE + 31: {
-			unsigned int *fregs;
+			unsigned long long *fregs;
+			fregs = (unsigned long long *)&child->thread.fpu.hard.fp_regs[0];
 			if (child->used_math) {
-				if (last_task_used_math == child) {
+				if (last_task_used_math == child)
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+				    if(!(mips_cpu.options & MIPS_CPU_FPU)) {
+					fregs = (unsigned long long *)
+					    &child->thread.fpu.soft.regs[0];
+				    } else
+#endif
+				{
 					enable_cp1();
 					save_fp(child);
 					disable_cp1();
@@ -213,7 +239,6 @@
 				       sizeof(child->thread.fpu.hard));
 				child->thread.fpu.hard.control = 0;
 			}
-			fregs = child->thread.fpu.hard.fp_regs;
 			fregs[addr - FPR_BASE] = data;
 			break;
 		}
@@ -227,6 +252,11 @@
 			regs->lo = data;
 			break;
 		case FPC_CSR:
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+			if(!(mips_cpu.options & MIPS_CPU_FPU)) 
+				child->thread.fpu.soft.sr = data;
+			else
+#endif
 			child->thread.fpu.hard.control = data;
 			break;
 		default:
diff -urN linux-2.4.4-pre3/arch/mips/kernel/r2300_fpu.S linux/arch/mips/kernel/r2300_fpu.S
--- linux-2.4.4-pre3/arch/mips/kernel/r2300_fpu.S	Sat May 13 08:29:14 2000
+++ linux/arch/mips/kernel/r2300_fpu.S	Mon Dec  3 22:35:22 2001
@@ -1,7 +1,4 @@
-/* $Id: r2300_fpu.S,v 1.6 1999/08/09 19:43:14 harald Exp $
- *
- * r2300_fpu.S: Save/restore floating point context for signal handlers.
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
@@ -30,7 +27,7 @@
 	.set	noreorder
 	.set	mips1
 	/* Save floating point context */
-LEAF(save_fp_context)
+LEAF(_save_fp_context)
 	li	v0, 0					# assume success
 	cfc1	t1,fcr31
 	EX(swc1	$f0,(SC_FPREGS+0)(a0))
@@ -65,13 +62,13 @@
 	EX(swc1	$f29,(SC_FPREGS+232)(a0))
 	EX(swc1	$f30,(SC_FPREGS+240)(a0))
 	EX(swc1	$f31,(SC_FPREGS+248)(a0))
-	EX(sw	t1,SC_FPC_CSR(a0))
+	EX(sw	t1,(SC_FPC_CSR)(a0))
 	cfc1	t0,$0				# implementation/version
 	jr	ra
 	.set	nomacro
-	 EX(sw	t0,SC_FPC_EIR(a0))
+	 EX(sw	t0,(SC_FPC_EIR)(a0))
 	.set	macro
-	END(save_fp_context)
+	END(_save_fp_context)
 
 /*
  * Restore FPU state:
@@ -82,9 +79,9 @@
  * frame on the current content of c0_status, not on the content of the
  * stack frame which might have been changed by the user.
  */
-LEAF(restore_fp_context)
+LEAF(_restore_fp_context)
 	li	v0, 0					# assume success
-	EX(lw t0,SC_FPC_CSR(a0))
+	EX(lw t0,(SC_FPC_CSR)(a0))
 	EX(lwc1	$f0,(SC_FPREGS+0)(a0))
 	EX(lwc1	$f1,(SC_FPREGS+8)(a0))
 	EX(lwc1	$f2,(SC_FPREGS+16)(a0))
@@ -119,7 +116,7 @@
 	EX(lwc1	$f31,(SC_FPREGS+248)(a0))
 	jr	ra
 	 ctc1	t0,fcr31
-	END(restore_fp_context)
+	END(_restore_fp_context)
 
 	.type	fault@function
 	.ent	fault
diff -urN linux-2.4.4-pre3/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S
--- linux-2.4.4-pre3/arch/mips/kernel/r2300_switch.S	Sat May 13 08:29:14 2000
+++ linux/arch/mips/kernel/r2300_switch.S	Mon Dec  3 22:35:22 2001
@@ -9,7 +9,7 @@
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
  * Further modifications to make this work:
- * Copyright (c) 1998 Harald Koerfgen
+ * Copyright (c) 1998-2000 Harald Koerfgen
  */
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
@@ -30,13 +30,11 @@
 	.align	5
 
 /*
- * task_struct *r4xx0_resume(task_struct *prev,
- *                           task_struct *next)
+ * task_struct *resume(task_struct *prev,
+ *                     task_struct *next)
  */
 LEAF(resume)
-	.set	reorder
 	mfc0	t1, CP0_STATUS
-	.set	noreorder
 	sw	t1, THREAD_STATUS(a0)
 	CPU_SAVE_NONSCRATCH(a0)
 	sw	ra, THREAD_REG31(a0)
@@ -57,8 +55,10 @@
 	and	a2, a3
 	or	a2, t1
 	mtc0	a2, CP0_STATUS
+	.set	noreorder
 	jr	ra
 	 move	v0, a0
+	.set	reorder
 	END(resume)
 
 /*
@@ -74,19 +74,16 @@
 	or	t0, t3
 	mtc0	t0, CP0_STATUS
 
+	.set	noreorder
 	beqz	a0, 2f				# Save floating point state
 	 nor	t3, zero, t3
 	.set	reorder
 	lw	t1, ST_OFF(a0)			# last thread looses fpu
-	.set	noreorder
 	and	t1, t3
 	sw	t1, ST_OFF(a0)
-	swc1	$f0, (THREAD_FPU + 0x00)(a0)
 	FPU_SAVE_SINGLE(a0, t1)			# clobbers t1
 
 2:
-	lwc1	$f0, (THREAD_FPU + 0x00)($28)
-	.set	reorder
 	FPU_RESTORE_SINGLE($28, t0)		# clobbers t0
 	jr	ra
 	END(lazy_fpu_switch)
@@ -94,14 +91,20 @@
 /*
  * Save a thread's fp context.
  */
-	.set	noreorder
 LEAF(save_fp)
 	FPU_SAVE_SINGLE(a0, t1)			# clobbers t1
 	jr	ra
-	 swc1	$f0, (THREAD_FPU + 0x00)(a0)
 	END(save_fp)
 
 /*
+ * Restore a thread's fp context.
+ */
+LEAF(restore_fp)
+	FPU_RESTORE_SINGLE(a0, t1)		# clobbers t1
+	jr	ra
+	END(restore_fp)
+
+/*
  * Load the FPU with signalling NANS.  This bit pattern we're using has
  * the property that no matter wether considered as single or as double
  * precission represents signaling NANS.
@@ -153,6 +156,8 @@
 	mtc1	t0, $f28
 	mtc1	t0, $f29
 	mtc1	t0, $f30
+	.set	noreorder
 	jr	ra
 	 mtc1	t0, $f31
+	.set	reorder
 	END(init_fpu)
diff -urN linux-2.4.4-pre3/arch/mips/kernel/r4k_fpu.S linux/arch/mips/kernel/r4k_fpu.S
--- linux-2.4.4-pre3/arch/mips/kernel/r4k_fpu.S	Sat May 13 08:29:14 2000
+++ linux/arch/mips/kernel/r4k_fpu.S	Mon Dec  3 22:35:22 2001
@@ -1,15 +1,15 @@
-/* $Id: r4k_fpu.S,v 1.8 1999/09/28 22:25:47 ralf Exp $
- *
- * r4k_fpu.S: Save/restore floating point context for signal handlers.
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 1998 by Ralf Baechle
+ * Copyright (C) 1996, 1998, 2000 by Ralf Baechle
  *
  * Multi-arch abstraction and asm macros for easier reading:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ *  Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.
  */
 #include <asm/asm.h>
 #include <asm/errno.h>
@@ -19,7 +19,7 @@
 #include <asm/regdef.h>
 
 #define EX(a,b)							\
-9:	a,##b;							\
+9:	a,b;							\
 	.section __ex_table,"a";				\
 	PTR	9b, fault;					\
 	.previous
@@ -27,7 +27,7 @@
 	.set	noreorder
 	.set	mips3
 	/* Save floating point context */
-LEAF(save_fp_context)
+LEAF(_save_fp_context)
 	li	v0, 0					# assume success
 	cfc1	t1,fcr31
 
@@ -55,7 +55,7 @@
 	.set	nomacro
 	 EX(sw	t0,SC_FPC_EIR(a0))
 	.set	macro
-	END(save_fp_context)
+	END(_save_fp_context)
 
 /*
  * Restore FPU state:
@@ -66,7 +66,7 @@
  * frame on the current content of c0_status, not on the content of the
  * stack frame which might have been changed by the user.
  */
-LEAF(restore_fp_context)
+LEAF(_restore_fp_context)
 	li	v0, 0					# assume success
 	EX(lw	t0,SC_FPC_CSR(a0))
 
@@ -92,7 +92,7 @@
 	EX(ldc1	$f30,(SC_FPREGS+240)(a0))
 	jr	ra
 	 ctc1	t0,fcr31
-	END(restore_fp_context)
+	END(_restore_fp_context)
 
 	.type	fault@function
 	.ent	fault
diff -urN linux-2.4.4-pre3/arch/mips/kernel/r4k_misc.S linux/arch/mips/kernel/r4k_misc.S
--- linux-2.4.4-pre3/arch/mips/kernel/r4k_misc.S	Sat May 13 08:29:14 2000
+++ linux/arch/mips/kernel/r4k_misc.S	Mon Dec  3 22:35:22 2001
@@ -7,6 +7,13 @@
  * Multi-cpu abstraction and reworking:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  */
+/**************************************************************************
+ *  14 Nov, 2000.
+ *  Made support for MIPS32 CPUs.
+ *
+ *  Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *************************************************************************/
 #include <asm/asm.h>
 #include <asm/current.h>
 #include <asm/offset.h>
@@ -102,7 +109,6 @@
 	sw	pte, (ptr);
 
 	.set	noreorder
-	.set	mips3
 
 /*
  * From the IDT errata for the QED RM5230 (Nevada), processor revision 1.0:
@@ -147,7 +153,9 @@
 	 tlbwi
 1:
 	nop
+	.set	mips3	
 	eret
+	.set	mips0
 #endif
 
 nopage_tlbl:
@@ -169,7 +177,9 @@
 	 tlbwi
 1:
 	nop
+	.set	mips3	
 	eret
+	.set	mips0
 #endif
 
 nopage_tlbs:
@@ -201,7 +211,9 @@
 	 tlbwi
 1:
 	nop
+	.set	mips3
 	eret
+	.set	mips0
 #endif
 
 nowrite_mod:
diff -urN linux-2.4.4-pre3/arch/mips/kernel/r4k_switch.S linux/arch/mips/kernel/r4k_switch.S
--- linux-2.4.4-pre3/arch/mips/kernel/r4k_switch.S	Sat May 13 08:29:14 2000
+++ linux/arch/mips/kernel/r4k_switch.S	Mon Dec  3 22:35:22 2001
@@ -9,6 +9,14 @@
  * Copyright (C) 1994, 1995, 1996, by Andreas Busse
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
+/**************************************************************************
+ *  13 Nov, 2000.
+ *  Made support for MIPS32 CPUs and restoring of fp registers.
+ *
+ *  Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *************************************************************************/
+	
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
 #include <asm/cachectl.h>
@@ -24,8 +32,6 @@
 
 #include <asm/asmmacro.h>
 
-	.set	mips3
-
 /*
  * task_struct *r4xx0_resume(task_struct *prev, task_struct *next)
  */
@@ -95,6 +101,14 @@
 	END(save_fp)
 
 /*
+ * Restore a thread's fp context.
+ */
+LEAF(restore_fp)
+	FPU_RESTORE_DOUBLE(a0, t1)		# clobbers t1
+	jr	ra
+	END(restore_fp)
+
+/*
  * Load the FPU with signalling NANS.  This bit pattern we're using has
  * the property that no matter whether considered as single or as double
  * precision represents signaling NANS.
@@ -105,6 +119,7 @@
 #define FPU_DEFAULT  0x00000000
 
 LEAF(init_fpu)
+	.set	mips3
 	mfc0	t0, CP0_STATUS
 	li	t1, 0x20000000
 	or	t0, t1
@@ -135,3 +150,4 @@
 	 dmtc1	t0, $f30
 	.set	reorder
 	END(init_fpu)
+
diff -urN linux-2.4.4-pre3/arch/mips/kernel/r6000_fpu.S linux/arch/mips/kernel/r6000_fpu.S
--- linux-2.4.4-pre3/arch/mips/kernel/r6000_fpu.S	Sat May 13 08:29:14 2000
+++ linux/arch/mips/kernel/r6000_fpu.S	Mon Dec  3 22:35:22 2001
@@ -9,8 +9,6 @@
  *
  * Multi-arch abstraction and asm macros for easier reading:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: r6000_fpu.S,v 1.5 1999/05/01 22:40:37 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/fpregdef.h>
@@ -21,7 +19,7 @@
 	.set	noreorder
 	.set	mips2
 	/* Save floating point context */
-	LEAF(save_fp_context)
+	LEAF(_save_fp_context)
 	mfc0	t0,CP0_STATUS
 	sll	t0,t0,2
 	bgez	t0,1f
@@ -49,7 +47,7 @@
 	 sw	t0,SC_FPC_CSR(a0)
 1:	jr	ra
 	 nop
-	END(save_fp_context)
+	END(_save_fp_context)
 
 /* Restore FPU state:
  *  - fp gp registers
@@ -59,7 +57,7 @@
  * frame on the current content of c0_status, not on the content of the
  * stack frame which might have been changed by the user.
  */
-	LEAF(restore_fp_context)
+	LEAF(_restore_fp_context)
 	mfc0	t0,CP0_STATUS
 	sll	t0,t0,2
 
@@ -86,4 +84,4 @@
 	 ctc1	t0,fcr31
 1:	jr	ra
 	 nop
-	END(restore_fp_context)
+	END(_restore_fp_context)
diff -urN linux-2.4.4-pre3/arch/mips/kernel/semaphore.c linux/arch/mips/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/mips/kernel/semaphore.c	Sat Nov 11 19:02:40 2000
+++ linux/arch/mips/kernel/semaphore.c	Mon Dec  3 22:35:22 2001
@@ -127,112 +127,3 @@
 {
 	return waking_non_zero_trylock(sem);
 }
-
-/*
- * RW Semaphores
- */
-void
-__down_read(struct rw_semaphore *sem, int count)
-{
-	DOWN_VAR;
-
- retry_down:
-	if (count < 0) {
-		/* Wait for the lock to become unbiased.  Readers
-		   are non-exclusive.  */
-		
-		/* This takes care of granting the lock.  */
-		up_read(sem);
-
-		add_wait_queue(&sem->wait, &wait);
-		while (atomic_read(&sem->count) < 0) {
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if (atomic_read(&sem->count) >= 0)
-				break;
-			schedule();
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		tsk->state = TASK_RUNNING;
-
-		mb();
-		count = atomic_dec_return(&sem->count);
-		if (count <= 0)
-			goto retry_down;
-	} else {
-		add_wait_queue(&sem->wait, &wait);
-
-		while (1) {
-			if (test_and_clear_bit(0, &sem->granted))
-				break;
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if ((sem->granted & 1) == 0)
-				schedule();
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		tsk->state = TASK_RUNNING;
-	}
-}
-
-void
-__down_write(struct rw_semaphore *sem, int count)
-{
-	DOWN_VAR;
-
- retry_down:
-	if (count + RW_LOCK_BIAS < 0) {
-		up_write(sem);
-
-		add_wait_queue_exclusive(&sem->wait, &wait);
-	
-		while (atomic_read(&sem->count) < 0) {
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if (atomic_read(&sem->count) >= RW_LOCK_BIAS)
-				break;
-			schedule();
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		tsk->state = TASK_RUNNING;
-
-		mb();
-		count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-		if (count != 0)
-			goto retry_down;
-	} else {
-		/* Put ourselves at the end of the list.  */
-		add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
-
-		while (1) {
-			if (test_and_clear_bit(1, &sem->granted))
-				break;
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if ((sem->granted & 2) == 0)
-				schedule();
-		}
-
-		remove_wait_queue(&sem->write_bias_wait, &wait);
-		tsk->state = TASK_RUNNING;
-
-		/* If the lock is currently unbiased, awaken the sleepers.
-		   FIXME: This wakes up the readers early in a bit of a
-		   stampede -> bad!  */
-		if (atomic_read(&sem->count) >= 0)
-			wake_up(&sem->wait);
-	}
-}
-
-void
-__rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
-{
-	if (readers) {
-		if (test_and_set_bit(0, &sem->granted))
-			BUG();
-		wake_up(&sem->wait);
-	} else {
-		if (test_and_set_bit(1, &sem->granted))
-			BUG();
-		wake_up(&sem->write_bias_wait);
-	}
-}
diff -urN linux-2.4.4-pre3/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c
--- linux-2.4.4-pre3/arch/mips/kernel/setup.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/mips/kernel/setup.c	Mon Dec  3 22:35:22 2001
@@ -4,8 +4,9 @@
  * for more details.
  *
  * Copyright (C) 1995  Linus Torvalds
- * Copyright (C) 1995, 1996, 1997, 1998  Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000  Ralf Baechle
  * Copyright (C) 1996  Stoned Elipot
+ * Copyright (C) 2000  Maciej W. Rozycki
  */
 #include <linux/config.h>
 #include <linux/errno.h>
@@ -36,10 +37,10 @@
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
 #include <asm/cachectl.h>
+#include <asm/cpu.h>
 #include <asm/io.h>
 #include <asm/stackframe.h>
 #include <asm/system.h>
-#include <asm/cpu.h>
 #ifdef CONFIG_SGI_IP22
 #include <asm/sgialib.h>
 #endif
@@ -152,64 +153,171 @@
 #endif
 }
 
+/* declaration of the global struct */
+struct mips_cpu mips_cpu = {PRID_IMP_UNKNOWN, CPU_UNKNOWN, 0, 0, 0,
+			    {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}};
+
+/* Shortcut for assembler access to mips_cpu.options */
+int *cpuoptions = &mips_cpu.options;
+
+#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \
+		| MIPS_CPU_COUNTER | MIPS_CPU_CACHE_CDEX)
+
 static inline void cpu_probe(void)
 {
-	unsigned int prid = read_32bit_cp0_register(CP0_PRID);
-	switch(prid & 0xff00) {
+	unsigned long config1;
+
+	mips_cpu.processor_id = read_32bit_cp0_register(CP0_PRID);
+	switch (mips_cpu.processor_id & 0xff00) {
 	case PRID_IMP_R2000:
-		mips_cputype = CPU_R2000;
+		mips_cpu.cputype = CPU_R2000;
+		mips_cpu.isa_level = MIPS_CPU_ISA_I;
+		mips_cpu.options = MIPS_CPU_TLB;
+		mips_cpu.tlbsize = 64;
 		break;
 	case PRID_IMP_R3000:
-		if((prid & 0xff) == PRID_REV_R3000A)
-			if(cpu_has_confreg())
-				mips_cputype = CPU_R3081E;
+		if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A)
+			if (cpu_has_confreg())
+				mips_cpu.cputype = CPU_R3081E;
 			else
-				mips_cputype = CPU_R3000A;
+				mips_cpu.cputype = CPU_R3000A;
 		else
-			 mips_cputype = CPU_R3000;
+			 mips_cpu.cputype = CPU_R3000;
+		mips_cpu.isa_level = MIPS_CPU_ISA_I;
+		mips_cpu.options = MIPS_CPU_TLB;
+		mips_cpu.tlbsize = 64;
 		break;
 	case PRID_IMP_R4000:
-		if((prid & 0xff) == PRID_REV_R4400)
-			mips_cputype = CPU_R4400SC;
+		if ((mips_cpu.processor_id & 0xff) == PRID_REV_R4400)
+			mips_cpu.cputype = CPU_R4400SC;
 		else
-			mips_cputype = CPU_R4000SC;
+			mips_cpu.cputype = CPU_R4000SC;
+		mips_cpu.isa_level = MIPS_CPU_ISA_III;
+		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+		                   MIPS_CPU_WATCH | MIPS_CPU_VCE;
+		mips_cpu.tlbsize = 48;
 		break;
 	case PRID_IMP_R4600:
-		mips_cputype = CPU_R4600;
+		mips_cpu.cputype = CPU_R4600;
+		mips_cpu.isa_level = MIPS_CPU_ISA_III;
+		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
+		mips_cpu.tlbsize = 48;
 		break;
+/*
+ * This processor doesn't have an MMU, so it's not "real easy" to
+ * run Linux on it. It is left purely for documentation.
+ *
 	case PRID_IMP_R4650:
-		mips_cputype = CPU_R4650;
+		mips_cpu.cputype = CPU_R4650;
+		mips_cpu.isa_level = MIPS_CPU_ISA_III;
+		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
+		mips_cpu.tlbsize = 48;
+		break;
+ */
+	case PRID_IMP_R3912:
+		mips_cpu.cputype = CPU_R3912;
+		mips_cpu.isa_level = MIPS_CPU_ISA_I;
+		mips_cpu.options = MIPS_CPU_TLB;
+		mips_cpu.tlbsize = 32;
 		break;
 	case PRID_IMP_R4700:
-		mips_cputype = CPU_R4700;
+		mips_cpu.cputype = CPU_R4700;
+		mips_cpu.isa_level = MIPS_CPU_ISA_III;
+		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+		mips_cpu.tlbsize = 48;
 		break;
 	case PRID_IMP_R5000:
-		mips_cputype = CPU_R5000;
+		mips_cpu.cputype = CPU_R5000;
+		mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+		mips_cpu.tlbsize = 48;
+		break;
+	case PRID_IMP_R5432:
+	        mips_cpu.cputype = CPU_R5432;
+		mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+		mips_cpu.tlbsize = 48;
 		break;
 	case PRID_IMP_NEVADA:
-		mips_cputype = CPU_NEVADA;
+		mips_cpu.cputype = CPU_NEVADA;
+		mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | 
+		                   MIPS_CPU_DIVEC;
+		mips_cpu.tlbsize = 48;
+		mips_cpu.icache.ways = 2;
+		mips_cpu.dcache.ways = 2;
 		break;
 	case PRID_IMP_R6000:
-		mips_cputype = CPU_R6000;
+		mips_cpu.cputype = CPU_R6000;
+		mips_cpu.isa_level = MIPS_CPU_ISA_II;
+		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
+		mips_cpu.tlbsize = 32;
 		break;
 	case PRID_IMP_R6000A:
-		mips_cputype = CPU_R6000A;
+		mips_cpu.cputype = CPU_R6000A;
+		mips_cpu.isa_level = MIPS_CPU_ISA_II;
+		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
+		mips_cpu.tlbsize = 32;
+		break;
+	case PRID_IMP_RM7000:
+		mips_cpu.cputype = CPU_RM7000;
+	        mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
 		break;
 	case PRID_IMP_R8000:
-		mips_cputype = CPU_R8000;
+		mips_cpu.cputype = CPU_R8000;
+	        mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+		                   MIPS_CPU_FPU | MIPS_CPU_32FPR;
+		mips_cpu.tlbsize = 384;      /* has wierd TLB: 3-way x 128 */
 		break;
 	case PRID_IMP_R10000:
-		mips_cputype = CPU_R10000;
-		break;
-	case PRID_IMP_RM7000:
-		mips_cputype = CPU_R5000;
+		mips_cpu.cputype = CPU_R10000;
+		mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+		                   MIPS_CPU_FPU | MIPS_CPU_32FPR | 
+		                   MIPS_CPU_COUNTER | MIPS_CPU_WATCH;
+		mips_cpu.tlbsize = 64;
+		break;
+#ifdef CONFIG_CPU_MIPS32
+	case PRID_IMP_4KC:
+		mips_cpu.cputype = CPU_4KC;
+		mips_cpu.isa_level = MIPS_CPU_ISA_M32;
+		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+		                   MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
+		                   MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
+		config1 = read_mips32_cp0_config1();
+		if (config1 & (1 << 3))
+		        mips_cpu.options |= MIPS_CPU_WATCH;
+		if (config1 & (1 << 2))
+		        mips_cpu.options |= MIPS_CPU_MIPS16;
+		if (config1 & 1)
+		        mips_cpu.options |= MIPS_CPU_FPU;
+		mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
+		break;
+	case PRID_IMP_5KC:
+		mips_cpu.cputype = CPU_5KC;
+		mips_cpu.isa_level = MIPS_CPU_ISA_M64;
+		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+		                   MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
+		                   MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
+		config1 = read_mips32_cp0_config1();
+		if (config1 & (1 << 3))
+		        mips_cpu.options |= MIPS_CPU_WATCH;
+		if (config1 & (1 << 2))
+		        mips_cpu.options |= MIPS_CPU_MIPS16;
+		if (config1 & 1)
+		        mips_cpu.options |= MIPS_CPU_FPU;
+		mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
 		break;
+#endif
 	default:
-		mips_cputype = CPU_UNKNOWN;
+		mips_cpu.cputype = CPU_UNKNOWN;
 	}
 }
 
-asmlinkage void __init init_arch(int argc, char **argv, char **envp, int *prom_vec)
+asmlinkage void __init
+init_arch(int argc, char **argv, char **envp, int *prom_vec)
 {
 	unsigned int s;
 
@@ -232,18 +340,13 @@
 	 */
 	loadmmu();
 
-	/* Disable coprocessors */
+	/* Disable coprocessors and set FPU for 16 FPRs */
 	s = read_32bit_cp0_register(CP0_STATUS);
-	s &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX);
+	s &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR);
 	s |= ST0_CU0;
 	write_32bit_cp0_register(CP0_STATUS, s);
 
-	/*
-	 * Main should never return here, but
-	 * just in case, we know what happens.
-	 */
-	for(;;)
-		start_kernel();
+	start_kernel();
 }
 
 static void __init default_irq_setup(void)
diff -urN linux-2.4.4-pre3/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c
--- linux-2.4.4-pre3/arch/mips/kernel/signal.c	Wed Jan 24 15:20:59 2001
+++ linux/arch/mips/kernel/signal.c	Mon Dec  3 22:35:22 2001
@@ -31,8 +31,9 @@
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
-extern asmlinkage int save_fp_context(struct sigcontext *sc);
-extern asmlinkage int restore_fp_context(struct sigcontext *sc);
+
+extern asmlinkage int (*save_fp_context)(struct sigcontext *sc);
+extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc);
 
 extern asmlinkage void syscall_trace(void);
 
@@ -74,12 +75,12 @@
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
-asmlinkage inline int
-sys_sigsuspend(struct pt_regs regs)
+save_static_function(sys_sigsuspend);
+static_unused int
+_sys_sigsuspend(struct pt_regs regs)
 {
 	sigset_t *uset, saveset, newset;
 
-	save_static(&regs);
 	uset = (sigset_t *) regs.regs[4];
 	if (copy_from_user(&newset, uset, sizeof(sigset_t)))
 		return -EFAULT;
@@ -101,14 +102,14 @@
 	}
 }
 
-asmlinkage int
-sys_rt_sigsuspend(struct pt_regs regs)
+
+save_static_function(sys_rt_sigsuspend);
+static_unused int
+_sys_rt_sigsuspend(struct pt_regs regs)
 {
 	sigset_t *unewset, saveset, newset;
         size_t sigsetsize;
 
-	save_static(&regs);
-
 	/* XXX Don't preclude handling different sized sigset_t's.  */
 	sigsetsize = regs.regs[5];
 	if (sigsetsize != sizeof(sigset_t))
@@ -353,7 +354,7 @@
 	err |= __put_user(owned_fp, &sc->sc_ownedfp);
 
 	if (current->used_math) {	/* fp is active.  */
-		set_cp0_status(ST0_CU1, ST0_CU1);
+		set_cp0_status(ST0_CU1);
 		err |= save_fp_context(sc);
 		last_task_used_math = NULL;
 		regs->cp0_status &= ~ST0_CU1;
diff -urN linux-2.4.4-pre3/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c
--- linux-2.4.4-pre3/arch/mips/kernel/traps.c	Sun Dec  3 17:48:19 2000
+++ linux/arch/mips/kernel/traps.c	Mon Dec  3 22:35:22 2001
@@ -7,6 +7,9 @@
  * Modified for R3000 by Paul M. Antoine, 1995, 1996
  * Complete output from die() by Ulf Carlsson, 1998
  * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
  */
 #include <linux/config.h>
 #include <linux/init.h>
@@ -16,12 +19,15 @@
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 
+#include <asm/bootinfo.h>
 #include <asm/branch.h>
+#include <asm/cpu.h>
 #include <asm/cachectl.h>
+#include <asm/inst.h>
 #include <asm/jazz.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
-#include <asm/bootinfo.h>
+#include <asm/siginfo.h>
 #include <asm/watch.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -51,13 +57,15 @@
 extern asmlinkage void handle_tr(void);
 extern asmlinkage void handle_fpe(void);
 extern asmlinkage void handle_watch(void);
+extern asmlinkage void handle_mcheck(void);
 extern asmlinkage void handle_reserved(void);
 
+extern int fpu_emulator_cop1Handler(int, struct pt_regs *);
+
 static char *cpu_names[] = CPU_NAMES;
 
 char watch_available = 0;
 char dedicated_iv_available = 0;
-char vce_available = 0;
 
 void (*ibe_board_handler)(struct pt_regs *regs);
 void (*dbe_board_handler)(struct pt_regs *regs);
@@ -308,9 +316,11 @@
  */
 void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 {
-	unsigned long pc;
-	unsigned int insn;
-	extern void simfp(unsigned int);
+
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+	if(!(mips_cpu.options & MIPS_CPU_FPU))
+		panic("Floating Point Exception with No FPU");
+#endif
 
 #ifdef CONFIG_MIPS_FPE_MODULE
 	if (fpe_handler != NULL) {
@@ -318,12 +328,52 @@
 		return;
 	}
 #endif
-	if (fcr31 & 0x20000) {
+
+	if (fcr31 & FPU_CSR_UNI_X) {
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+		extern void save_fp(struct task_struct *);
+		extern void restore_fp(struct task_struct *);
+		int sig;
+		/*
+	 	 * Unimplemented operation exception.  If we've got the
+	 	 * Full software emulator on-board, let's use it...
+		 *
+		 * Force FPU to dump state into task/thread context.
+		 * We're moving a lot of data here for what is probably
+		 * a single instruction, but the alternative is to 
+		 * pre-decode the FP register operands before invoking
+		 * the emulator, which seems a bit extreme for what
+		 * should be an infrequent event.
+		 */
+		save_fp(current);
+	
+		/* Run the emulator */
+		sig = fpu_emulator_cop1Handler(0, regs);
+
+		/* 
+		 * We can't allow the emulated instruction to leave the
+		 * Unimplemented Operation bit set in the FCR31 fp-register.
+		 */
+		current->thread.fpu.soft.sr &= ~FPU_CSR_UNI_X;
+
+		/* Restore the hardware register state */
+		restore_fp(current);
+
+		/* If something went wrong, signal */
+		if (sig)
+			force_sig(sig, current);
+#else
+		/* Else use mini-emulator */
+
+		extern void simfp(int);
+		unsigned long pc;
+		unsigned int insn;
+
 		/* Retry instruction with flush to zero ...  */
 		if (!(fcr31 & (1<<24))) {
 			printk("Setting flush to zero for %s.\n",
 			       current->comm);
-			fcr31 &= ~0x20000;
+			fcr31 &= ~FPU_CSR_UNI_X;
 			fcr31 |= (1<<24);
 			__asm__ __volatile__(
 				"ctc1\t%0,$31"
@@ -332,20 +382,26 @@
 			return;
 		}
 		pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
-		if (get_user(insn, (unsigned int *)pc)) {
+		if(pc & 0x80000000) insn = *(unsigned int *)pc;
+		else if (get_user(insn, (unsigned int *)pc)) {
 			/* XXX Can this happen?  */
 			force_sig(SIGSEGV, current);
 		}
 
 		printk(KERN_DEBUG "Unimplemented exception for insn %08x at 0x%08lx in %s.\n",
 		       insn, regs->cp0_epc, current->comm);
-		simfp(insn);
+		simfp(MIPSInst(insn));
+		compute_return_epc(regs);
+#endif /* CONFIG_MIPS_FPU_EMULATOR */
+
+		return;
 	}
 
 	if (compute_return_epc(regs))
 		return;
-	//force_sig(SIGFPE, current);
-	printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm);
+
+	force_sig(SIGFPE, current);
+	printk(KERN_DEBUG "Sent send SIGFPE to %s\n", current->comm);
 }
 
 static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
@@ -382,12 +438,28 @@
 	 * (A short test says that IRIX 5.3 sends SIGTRAP for all break
 	 * insns, even for break codes that indicate arithmetic failures.
 	 * Weird ...)
+	 * But should we continue the brokenness???  --macro
 	 */
-	force_sig(SIGTRAP, current);
+	switch (bcode) {
+	case 6:
+	case 7:
+		if (bcode == 7)
+			info.si_code = FPE_INTDIV;
+		else
+			info.si_code = FPE_INTOVF;
+		info.si_signo = SIGFPE;
+		info.si_errno = 0;
+		info.si_addr = (void *)compute_return_epc(regs);
+		force_sig_info(SIGFPE, &info, current);
+		break;
+	default:
+		force_sig(SIGTRAP, current);
+	}
 }
 
 void do_tr(struct pt_regs *regs)
 {
+	siginfo_t info;
 	unsigned int opcode, bcode;
 
 	if (get_insn_opcode(regs, &opcode))
@@ -398,8 +470,23 @@
 	 * (A short test says that IRIX 5.3 sends SIGTRAP for all break
 	 * insns, even for break codes that indicate arithmetic failures.
 	 * Weird ...)
+	 * But should we continue the brokenness???  --macro
 	 */
-	force_sig(SIGTRAP, current);
+	switch (bcode) {
+	case 6:
+	case 7:
+		if (bcode == 7)
+			info.si_code = FPE_INTDIV;
+		else
+			info.si_code = FPE_INTOVF;
+		info.si_signo = SIGFPE;
+		info.si_errno = 0;
+		info.si_addr = (void *)compute_return_epc(regs);
+		force_sig_info(SIGFPE, &info, current);
+		break;
+	default:
+		force_sig(SIGTRAP, current);
+	}
 }
 
 #if !defined(CONFIG_CPU_HAS_LLSC)
@@ -520,10 +607,32 @@
 	unsigned int cpid;
 	extern void lazy_fpu_switch(void*);
 	extern void init_fpu(void);
-
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+	void fpu_emulator_init_fpu(void);
+	int sig;
+#endif
 	cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
 	if (cpid != 1)
 		goto bad_cid;
+
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+	if(!(mips_cpu.options & MIPS_CPU_FPU)) {
+	    if (last_task_used_math != current) {
+		if(!current->used_math) {
+		    fpu_emulator_init_fpu();
+		    current->used_math = 1;
+		}
+	    }
+	    sig = fpu_emulator_cop1Handler(0, regs);
+	    last_task_used_math = current;
+	    if(sig) {
+		force_sig(sig, current);
+	    }
+	    return;
+	}
+#else
+	if(!(mips_cpu.options & MIPS_CPU_FPU)) goto bad_cid;
+#endif
 
 	regs->cp0_status |= ST0_CU1;
 	if (last_task_used_math == current)
diff -urN linux-2.4.4-pre3/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile
--- linux-2.4.4-pre3/arch/mips/lib/Makefile	Tue Dec  5 23:15:12 2000
+++ linux/arch/mips/lib/Makefile	Mon Dec  3 22:35:22 2001
@@ -9,26 +9,23 @@
 
 L_TARGET = lib.a
 
-L_OBJS	= csum_partial.o csum_partial_copy.o \
-          rtc-std.o rtc-no.o memcpy.o memset.o  watch.o\
-          strlen_user.o strncpy_user.o strnlen_user.o
+obj-y				+= csum_partial.o csum_partial_copy.o \
+				   rtc-std.o rtc-no.o memcpy.o memset.o \
+				   watch.o strlen_user.o strncpy_user.o \
+				   strnlen_user.o
 
 ifdef CONFIG_CPU_R3000
-  L_OBJS += r3k_dump_tlb.o 
+  obj-y	+= r3k_dump_tlb.o 
 else
-  L_OBJS += dump_tlb.o 
+  ifdef CONFIG_CPU_R3912
+    obj-y	+= r3k_dump_tlb.o 
+  else
+    obj-y	+= dump_tlb.o 
+  endif
 endif
 
-ifdef CONFIG_BLK_DEV_FD
-  L_OBJS += floppy-no.o floppy-std.o
-endif
-
-ifdef CONFIG_IDE
-  L_OBJS += ide-std.o ide-no.o
-endif
-
-ifdef CONFIG_PC_KEYB
-  L_OBJS += kbd-std.o kbd-no.o
-endif
+obj-$(CONFIG_BLK_DEV_FD)	+= floppy-no.o floppy-std.o
+obj-$(CONFIG_IDE)		+= ide-std.o ide-no.o
+obj-$(CONFIG_PC_KEYB)		+= kbd-std.o kbd-no.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/lib/kbd-std.c linux/arch/mips/lib/kbd-std.c
--- linux-2.4.4-pre3/arch/mips/lib/kbd-std.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/lib/kbd-std.c	Mon Dec  3 22:35:22 2001
@@ -8,6 +8,7 @@
  *
  * Copyright (C) 1998, 1999 by Ralf Baechle
  */
+#include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/pc_keyb.h>
@@ -19,11 +20,17 @@
 
 static void std_kbd_request_region(void)
 {
+#ifdef CONFIG_MIPS_ITE8172
+	printk("std_kbd_request_region\n");
+	request_region(0x14000060, 16, "keyboard");
+#else
 	request_region(0x60, 16, "keyboard");
+#endif
 }
 
 static int std_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *))
 {
+	printk("std_kbd_request_irq\n");
 	return request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL);
 }
 
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/Makefile linux/arch/mips/math-emu/Makefile
--- linux-2.4.4-pre3/arch/mips/math-emu/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/Makefile	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,24 @@
+#
+# Makefile for the Linux/MIPS kernel FPU emulation.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+EXTRA_ASFLAGS = -mips2 -mcpu=r4000
+
+O_TARGET:= fpu_emulator.o
+
+obj-y	:= cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
+	   ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \
+	   dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
+	   dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \
+	   sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
+	   sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
+	   dp_sqrt.o sp_sqrt.o kernel_linkage.o
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/cp1emu.c linux/arch/mips/math-emu/cp1emu.c
--- linux-2.4.4-pre3/arch/mips/math-emu/cp1emu.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/cp1emu.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,1811 @@
+/*
+ * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator
+ * 
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * A complete emulator for MIPS coprocessor 1 instructions.  This is
+ * required for #float(switch) or #float(trap), where it catches all
+ * COP1 instructions via the "CoProcessor Unusable" exception.  
+ *
+ * More surprisingly it is also required for #float(ieee), to help out
+ * the hardware fpu at the boundaries of the IEEE-754 representation
+ * (denormalised values, infinities, underflow, etc).  It is made
+ * quite nasty because emulation of some non-COP1 instructions is
+ * required, e.g. in branch delay slots.
+ * 
+ * Notes: 
+ *  1) the IEEE754 library (-le) performs the actual arithmetic;
+ *  2) if you know that you won't have an fpu, then you'll get much 
+ *     better performance by compiling with -msoft-float!  */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Massive changes to integrate with Linux kernel.
+ *
+ *  Replace use of kernel data area with use of user stack 
+ *  for execution of instructions in branch delay slots.
+ *
+ *  Replace use of static kernel variables with thread_struct elements.
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000  MIPS Technologies, Inc.  All rights reserved.
+ *************************************************************************/
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/asm.h>
+#include <asm/branch.h>
+#include <asm/byteorder.h>
+#include <asm/inst.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+
+#include <asm/fpu_emulator.h>
+
+#include "ieee754.h"
+
+/* Strap kernel emulator for full MIPS IV emulation */
+
+#ifdef __mips
+#undef __mips
+#endif
+#define __mips 4
+
+typedef void *vaddr_t;
+
+/* Function which emulates the instruction in a branch delay slot. */
+
+static int mips_dsemul(struct pt_regs *, mips_instruction, vaddr_t);
+
+/* Function which emulates a floating point instruction. */
+
+static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *,
+	 mips_instruction);
+
+#if __mips >= 4 && __mips != 32
+static int fpux_emu(struct pt_regs *,
+		    struct mips_fpu_soft_struct *, mips_instruction);
+#endif
+
+/* Further private data for which no space exists in mips_fpu_soft_struct */
+
+struct mips_fpu_emulator_private fpuemuprivate;
+
+/* Control registers */
+
+#define FPCREG_RID	0	/* $0  = revision id */
+#define FPCREG_CSR	31	/* $31 = csr */
+
+/* Convert Mips rounding mode (0..3) to IEEE library modes. */
+static const unsigned char ieee_rm[4] = {
+	IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD
+};
+
+#if __mips >= 4
+/* convert condition code register number to csr bit */
+static const unsigned int fpucondbit[8] = {
+	FPU_CSR_COND0,
+	FPU_CSR_COND1,
+	FPU_CSR_COND2,
+	FPU_CSR_COND3,
+	FPU_CSR_COND4,
+	FPU_CSR_COND5,
+	FPU_CSR_COND6,
+	FPU_CSR_COND7
+};
+#endif
+
+
+
+/* 
+ * Redundant with logic already in kernel/branch.c,
+ * embedded in compute_return_epc.  At some point,
+ * a single subroutine should be used across both
+ * modules.
+ */
+static int isBranchInstr(mips_instruction * i)
+{
+	switch (MIPSInst_OPCODE(*i)) {
+	case spec_op:
+		switch (MIPSInst_FUNC(*i)) {
+		case jalr_op:
+		case jr_op:
+			return 1;
+		}
+		break;
+
+	case bcond_op:
+		switch (MIPSInst_RT(*i)) {
+		case bltz_op:
+		case bgez_op:
+		case bltzl_op:
+		case bgezl_op:
+		case bltzal_op:
+		case bgezal_op:
+		case bltzall_op:
+		case bgezall_op:
+			return 1;
+		}
+		break;
+
+	case j_op:
+	case jal_op:
+	case jalx_op:
+	case beq_op:
+	case bne_op:
+	case blez_op:
+	case bgtz_op:
+	case beql_op:
+	case bnel_op:
+	case blezl_op:
+	case bgtzl_op:
+		return 1;
+
+	case cop0_op:
+	case cop1_op:
+	case cop2_op:
+	case cop1x_op:
+		if (MIPSInst_RS(*i) == bc_op)
+			return 1;
+		break;
+	}
+
+	return 0;
+}
+
+#define REG_TO_VA (vaddr_t)
+#define VA_TO_REG (unsigned long)
+
+static unsigned long
+mips_get_word(struct pt_regs *xcp, void *va, int *perr)
+{
+	unsigned long temp;
+
+	if (!user_mode(xcp)) {
+		*perr = 0;
+		return (*(unsigned long *) va);
+	} else {
+		/* Use kernel get_user() macro */
+		*perr = (int) get_user(temp, (unsigned long *) va);
+		return temp;
+	}
+}
+
+static unsigned long long
+mips_get_dword(struct pt_regs *xcp, void *va, int *perr)
+{
+	unsigned long long temp;
+
+	if (!user_mode(xcp)) {
+		*perr = 0;
+		return (*(unsigned long long *) va);
+	} else {
+		/* Use kernel get_user() macro */
+		*perr = (int) get_user(temp, (unsigned long long *) va);
+		return temp;
+	}
+}
+
+static int mips_put_word(struct pt_regs *xcp, void *va, unsigned long val)
+{
+	if (!user_mode(xcp)) {
+		*(unsigned long *) va = val;
+		return 0;
+	} else {
+		/* Use kernel get_user() macro */
+		return (int) put_user(val, (unsigned long *) va);
+	}
+}
+
+static int mips_put_dword(struct pt_regs *xcp, void *va, long long val)
+{
+	if (!user_mode(xcp)) {
+		*(unsigned long long *) va = val;
+		return 0;
+	} else {
+		/* Use kernel get_user() macro */
+		return (int) put_user(val, (unsigned long long *) va);
+	}
+}
+
+
+/*
+ * In the Linux kernel, we support selection of FPR format on the
+ * basis of the Status.FR bit.  This does imply that, if a full 32
+ * FPRs are desired, there needs to be a flip-flop that can be written
+ * to one at that bit position.  In any case, normal MIPS ABI uses
+ * only the even FPRs (Status.FR = 0).
+ */
+
+#define CP0_STATUS_FR_SUPPORT
+
+/*
+ * Emulate the single floating point instruction pointed at by EPC.
+ * Two instructions if the instruction is in a branch delay slot.
+ */
+
+static int
+cop1Emulate(int xcptno, struct pt_regs *xcp,
+	    struct mips_fpu_soft_struct *ctx)
+{
+	mips_instruction ir;
+	vaddr_t emulpc;
+	vaddr_t contpc;
+	unsigned int cond;
+	int err = 0;
+
+
+	ir = mips_get_word(xcp, REG_TO_VA xcp->cp0_epc, &err);
+	if (err) {
+		fpuemuprivate.stats.errors++;
+		return SIGBUS;
+	}
+
+	/* XXX NEC Vr54xx bug workaround */
+	if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
+		xcp->cp0_cause &= ~CAUSEF_BD;
+
+	if (xcp->cp0_cause & CAUSEF_BD) {
+		/*
+		 * The instruction to be emulated is in a branch delay slot
+		 * which means that we have to  emulate the branch instruction
+		 * BEFORE we do the cop1 instruction. 
+		 *
+		 * This branch could be a COP1 branch, but in that case we
+		 * would have had a trap for that instruction, and would not
+		 * come through this route.
+		 *
+		 * Linux MIPS branch emulator operates on context, updating the
+		 * cp0_epc.
+		 */
+		emulpc = REG_TO_VA(xcp->cp0_epc + 4);	/* Snapshot emulation target */
+
+		if (__compute_return_epc(xcp)) {
+#ifdef CP1DBG
+			printk("failed to emulate branch at %p\n",
+				    REG_TO_VA(xcp->cp0_epc));
+#endif
+			return SIGILL;;
+		}
+		ir = mips_get_word(xcp, emulpc, &err);
+		if (err) {
+			fpuemuprivate.stats.errors++;
+			return SIGBUS;
+		}
+		contpc = REG_TO_VA xcp->cp0_epc;
+	} else {
+		emulpc = REG_TO_VA xcp->cp0_epc;
+		contpc = REG_TO_VA xcp->cp0_epc + 4;
+	}
+
+      emul:
+	fpuemuprivate.stats.emulated++;
+	switch (MIPSInst_OPCODE(ir)) {
+#ifdef CP0_STATUS_FR_SUPPORT
+		/* R4000+ 64-bit fpu registers */
+#ifndef SINGLE_ONLY_FPU
+	case ldc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			int ft = MIPSInst_RT(ir);
+			if (!(xcp->cp0_status & ST0_FR))
+				ft &= ~1;
+			ctx->regs[ft] = mips_get_dword(xcp, va, &err);
+			fpuemuprivate.stats.loads++;
+			if (err) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+
+	case sdc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			int ft = MIPSInst_RT(ir);
+			if (!(xcp->cp0_status & ST0_FR))
+				ft &= ~1;
+			fpuemuprivate.stats.stores++;
+			if (mips_put_dword(xcp, va, ctx->regs[ft])) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+#endif
+
+	case lwc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			fpureg_t val;
+			int ft = MIPSInst_RT(ir);
+			fpuemuprivate.stats.loads++;
+			val = mips_get_word(xcp, va, &err);
+			if (err) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+			if (xcp->cp0_status & ST0_FR) {
+				/* load whole register */
+				ctx->regs[ft] = val;
+			} else if (ft & 1) {
+				/* load to m.s. 32 bits */
+#ifdef SINGLE_ONLY_FPU
+				/* illegal register in single-float mode */
+				return SIGILL;
+#else
+				ctx->regs[(ft & ~1)] &= 0xffffffff;
+				ctx->regs[(ft & ~1)] |= val << 32;
+#endif
+			} else {
+				/* load to l.s. 32 bits */
+				ctx->regs[ft] &= ~0xffffffffLL;
+				ctx->regs[ft] |= val;
+			}
+		}
+		break;
+
+	case swc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			unsigned int val;
+			int ft = MIPSInst_RT(ir);
+			fpuemuprivate.stats.stores++;
+			if (xcp->cp0_status & ST0_FR) {
+				/* store whole register */
+				val = ctx->regs[ft];
+			} else if (ft & 1) {
+#ifdef SINGLE_ONLY_FPU
+				/* illegal register in single-float mode */
+				return SIGILL;
+#else
+				/* store from m.s. 32 bits */
+				val = ctx->regs[(ft & ~1)] >> 32;
+#endif
+			} else {
+				/* store from l.s. 32 bits */
+				val = ctx->regs[ft];
+			}
+			if (mips_put_word(xcp, va, val)) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+#else				/* old 32-bit fpu registers */
+	case lwc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			ctx->regs[MIPSInst_RT(ir)] =
+			    mips_get_word(xcp, va, &err);
+			fpuemuprivate.stats.loads++;
+			if (err) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+
+	case swc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			fpuemuprivate.stats.stores++;
+			if (mips_put_word
+			    (xcp, va, ctx->regs[MIPSInst_RT(ir)])) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+	case ldc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			unsigned int rt = MIPSInst_RT(ir) & ~1;
+			int errs = 0;
+			fpuemuprivate.stats.loads++;
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+			ctx->regs[rt + 1] =
+			    mips_get_word(xcp, va + 0, &err);
+			errs += err;
+			ctx->regs[rt + 0] =
+			    mips_get_word(xcp, va + 4, &err);
+			errs += err;
+#else
+			ctx->regs[rt + 0] =
+			    mips_get_word(xcp, va + 0, &err);
+			errs += err;
+			ctx->regs[rt + 1] =
+			    mips_get_word(xcp, va + 4, &err);
+			errs += err;
+#endif
+			if (err)
+				return SIGBUS;
+		}
+		break;
+
+	case sdc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			unsigned int rt = MIPSInst_RT(ir) & ~1;
+			fpuemuprivate.stats.stores++;
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+			if (mips_put_word(xcp, va + 0, ctx->regs[rt + 1]))
+				return SIGBUS;
+			if (mips_put_word(xcp, va + 4, ctx->regs[rt + 0]))
+				return SIGBUS;
+#else
+			if (mips_put_word(xcp, va + 0, ctx->regs[rt + 0]))
+				return SIGBUS;
+			if (mips_put_word(xcp, va + 4, ctx->regs[rt + 1]))
+				return SIGBUS;
+#endif
+		}
+		break;
+#endif
+
+	case cop1_op:
+		switch (MIPSInst_RS(ir)) {
+
+#ifdef CP0_STATUS_FR_SUPPORT
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+		case dmfc_op:
+			/* copregister fs -> gpr[rt] */
+			if (MIPSInst_RT(ir) != 0) {
+				int fs = MIPSInst_RD(ir);
+				if (!(xcp->cp0_status & ST0_FR))
+					fs &= ~1;
+				xcp->regs[MIPSInst_RT(ir)] = ctx->regs[fs];
+			}
+			break;
+
+		case dmtc_op:
+			/* copregister fs <- rt */
+			{
+				fpureg_t value;
+				int fs = MIPSInst_RD(ir);
+				if (!(xcp->cp0_status & ST0_FR))
+					fs &= ~1;
+				value =
+				    (MIPSInst_RT(ir) ==
+				     0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
+				ctx->regs[fs] = value;
+			}
+			break;
+#endif
+
+		case mfc_op:
+			/* copregister rd -> gpr[rt] */
+			if (MIPSInst_RT(ir) != 0) {
+				/* default value from l.s. 32 bits */
+				int value = ctx->regs[MIPSInst_RD(ir)];
+				if (MIPSInst_RD(ir) & 1) {
+#ifdef SINGLE_ONLY_FPU
+					/* illegal register in single-float mode */
+					return SIGILL;
+#else
+					if (!(xcp->cp0_status & ST0_FR)) {
+						/* move from m.s. 32 bits */
+						value =
+						    ctx->
+						    regs[MIPSInst_RD(ir) &
+							 ~1] >> 32;
+					}
+#endif
+				}
+				xcp->regs[MIPSInst_RT(ir)] = value;
+			}
+			break;
+
+		case mtc_op:
+			/* copregister rd <- rt */
+			{
+				fpureg_t value;
+				if (MIPSInst_RT(ir) == 0)
+					value = 0;
+				else
+					value =
+					    (unsigned int) xcp->
+					    regs[MIPSInst_RT(ir)];
+				if (MIPSInst_RD(ir) & 1) {
+#ifdef SINGLE_ONLY_FPU
+					/* illegal register in single-float mode */
+					return SIGILL;
+#else
+					if (!(xcp->cp0_status & ST0_FR)) {
+						/* move to m.s. 32 bits */
+						ctx->
+						    regs[
+							 (MIPSInst_RD(ir) &
+							  ~1)] &=
+						    0xffffffff;
+						ctx->
+						    regs[
+							 (MIPSInst_RD(ir) &
+							  ~1)] |=
+						    value << 32;
+						break;
+					}
+#endif
+				}
+				/* move to l.s. 32 bits */
+				ctx->regs[MIPSInst_RD(ir)] &=
+				    ~0xffffffffLL;
+				ctx->regs[MIPSInst_RD(ir)] |= value;
+			}
+			break;
+#else
+
+		case mfc_op:
+			/* copregister rd -> gpr[rt] */
+			if (MIPSInst_RT(ir) != 0) {
+				unsigned value =
+				    ctx->regs[MIPSInst_RD(ir)];
+				xcp->regs[MIPSInst_RT(ir)] = value;
+			}
+			break;
+
+		case mtc_op:
+			/* copregister rd <- rt */
+			{
+				unsigned value;
+				value =
+				    (MIPSInst_RT(ir) ==
+				     0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
+				ctx->regs[MIPSInst_RD(ir)] = value;
+			}
+			break;
+#endif
+
+		case cfc_op:
+			/* cop control register rd -> gpr[rt] */
+			{
+				unsigned value;
+
+				if (MIPSInst_RD(ir) == FPCREG_CSR) {
+					value = ctx->sr;
+#ifdef CSRTRACE
+					printk
+					    ("%p gpr[%d]<-csr=%08x\n",
+					     REG_TO_VA(xcp->cp0_epc),
+					     MIPSInst_RT(ir), value);
+#endif
+				} else if (MIPSInst_RD(ir) == FPCREG_RID)
+					value = 0;
+				else
+					value = 0;
+				if (MIPSInst_RT(ir))
+					xcp->regs[MIPSInst_RT(ir)] = value;
+			}
+			break;
+
+		case ctc_op:
+			/* copregister rd <- rt */
+			{
+				unsigned value;
+
+				if (MIPSInst_RT(ir) == 0)
+					value = 0;
+				else
+					value = xcp->regs[MIPSInst_RT(ir)];
+
+				/* we only have one writable control reg
+				 */
+				if (MIPSInst_RD(ir) == FPCREG_CSR) {
+#ifdef CSRTRACE
+					printk
+					    ("%p gpr[%d]->csr=%08x\n",
+					     REG_TO_VA(xcp->cp0_epc),
+					     MIPSInst_RT(ir), value);
+#endif
+					ctx->sr = value;
+					/* copy new rounding mode to ieee library state! */
+					ieee754_csr.rm =
+					    ieee_rm[value & 0x3];
+				}
+			}
+			break;
+
+		case bc_op:
+			if (xcp->cp0_cause & CAUSEF_BD) {
+				return SIGILL;
+			}
+			{
+				int likely = 0;
+
+#if __mips >= 4
+				cond =
+				    ctx->
+				    sr & fpucondbit[MIPSInst_RT(ir) >> 2];
+#else
+				cond = ctx->sr & FPU_CSR_COND;
+#endif
+				switch (MIPSInst_RT(ir) & 3) {
+				case bcfl_op:
+					likely = 1;
+				case bcf_op:
+					cond = !cond;
+					break;
+				case bctl_op:
+					likely = 1;
+				case bct_op:
+					break;
+				default:
+					/* thats an illegal instruction */
+					return SIGILL;
+				}
+
+				xcp->cp0_cause |= CAUSEF_BD;
+				if (cond) {
+					/* branch taken: emulate dslot instruction */
+					xcp->cp0_epc += 4;
+					contpc =
+					    REG_TO_VA xcp->cp0_epc +
+					    (MIPSInst_SIMM(ir) << 2);
+
+					ir =
+					    mips_get_word(xcp,
+							  REG_TO_VA(xcp->
+								    cp0_epc),
+							  &err);
+					if (err) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+
+					switch (MIPSInst_OPCODE(ir)) {
+					case lwc1_op:
+					case swc1_op:
+#if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU)
+					case ldc1_op:
+					case sdc1_op:
+#endif
+					case cop1_op:
+#if __mips >= 4 && __mips != 32
+					case cop1x_op:
+#endif
+						/* its one of ours */
+						goto emul;
+#if __mips >= 4
+					case spec_op:
+						if (MIPSInst_FUNC(ir) ==
+						    movc_op) goto emul;
+						break;
+#endif
+					}
+
+					/* single step the non-cp1 instruction in the dslot */
+					return mips_dsemul(xcp, ir,
+							   contpc);
+				} else {
+					/* branch not taken */
+					if (likely)
+						/* branch likely nullifies dslot if not taken */
+						xcp->cp0_epc += 4;
+					/* else continue & execute dslot as normal insn */
+				}
+			}
+			break;
+
+		default:
+			if (!(MIPSInst_RS(ir) & 0x10)) {
+				return SIGILL;
+			}
+			/* a real fpu computation instruction */
+			{
+				int sig;
+				if ((sig = fpu_emu(xcp, ctx, ir)))
+					return sig;
+			}
+		}
+		break;
+
+#if __mips >= 4 && __mips != 32
+	case cop1x_op:
+		{
+			int sig;
+			if ((sig = fpux_emu(xcp, ctx, ir)))
+				return sig;
+		}
+		break;
+#endif
+
+#if __mips >= 4
+	case spec_op:
+		if (MIPSInst_FUNC(ir) != movc_op)
+			return SIGILL;
+		cond = fpucondbit[MIPSInst_RT(ir) >> 2];
+		if (((ctx->sr & cond) != 0) !=
+		    ((MIPSInst_RT(ir) & 1) != 0)) return 0;
+		xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)];
+		break;
+#endif
+
+	default:
+		return SIGILL;
+	}
+
+	/* we did it !! */
+	xcp->cp0_epc = VA_TO_REG(contpc);
+	xcp->cp0_cause &= ~CAUSEF_BD;
+	return 0;
+}
+
+/*
+ * Emulate the arbritrary instruction ir at xcp->cp0_epc.  Required when
+ * we have to emulate the instruction in a COP1 branch delay slot.  Do
+ * not change cp0_epc due to the instruction
+ *
+ * According to the spec:
+ * 1) it shouldnt be a branch :-)
+ * 2) it can be a COP instruction :-(
+ * 3) if we are tring to run a protected memory space we must take
+ *    special care on memory access instructions :-(
+ */
+
+/*
+ * "Trampoline" return routine to catch exception following
+ *  execution of delay-slot instruction execution.
+ */
+
+int do_dsemulret(struct pt_regs *xcp)
+{
+#ifdef DSEMUL_TRACE
+	printk("desemulret\n");
+#endif
+	/* Set EPC to return to post-branch instruction */
+	xcp->cp0_epc = current->thread.dsemul_epc;
+	/*
+	 * Clear the state that got us here.
+	 */
+	current->thread.dsemul_aerpc = (unsigned long) 0;
+
+	return 0;
+}
+
+
+#define AdELOAD 0x8c000001	/* lw $0,1($0) */
+
+static int
+mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc)
+{
+	mips_instruction *dsemul_insns;
+	mips_instruction forcetrap;
+	extern asmlinkage void handle_dsemulret(void);
+
+	if (ir == 0) {		/* a nop is easy */
+		xcp->cp0_epc = VA_TO_REG(cpc);
+		return 0;
+	}
+#ifdef DSEMUL_TRACE
+	printk("desemul %p %p\n", REG_TO_VA(xcp->cp0_epc), cpc);
+#endif
+
+	/* 
+	 * The strategy is to push the instruction onto the user stack 
+	 * and put a trap after it which we can catch and jump to 
+	 * the required address any alternative apart from full 
+	 * instruction emulation!!.
+	 */
+	dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~3);
+	dsemul_insns -= 3;	/* Two instructions, plus one for luck ;-) */
+	/* Verify that the stack pointer is not competely insane */
+	if (verify_area
+	    (VERIFY_WRITE, dsemul_insns, sizeof(mips_instruction) * 2))
+		return SIGBUS;
+
+	if (mips_put_word(xcp, &dsemul_insns[0], ir)) {
+		fpuemuprivate.stats.errors++;
+		return (SIGBUS);
+	}
+
+	/* 
+	 * Algorithmics used a system call instruction, and
+	 * borrowed that vector.  MIPS/Linux version is a bit
+	 * more heavyweight in the interests of portability and
+	 * multiprocessor support.  We flag the thread for special
+	 * handling in the unaligned access handler and force an
+	 * address error excpetion.
+	 */
+
+	/* If one is *really* paranoid, one tests for a bad stack pointer */
+	if ((xcp->regs[29] & 0x3) == 0x3)
+		forcetrap = AdELOAD - 1;
+	else
+		forcetrap = AdELOAD;
+
+	if (mips_put_word(xcp, &dsemul_insns[1], forcetrap)) {
+		fpuemuprivate.stats.errors++;
+		return (SIGBUS);
+	}
+
+	/* Set thread state to catch and handle the exception */
+	current->thread.dsemul_epc = (unsigned long) cpc;
+	current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1];
+	xcp->cp0_epc = VA_TO_REG & dsemul_insns[0];
+
+	/* What we'd really like to do is just flush the line(s) of the */
+	/* icache containing the dsemulret instructions, but there's no */
+	/* mechanism to do this yet...  */
+	flush_cache_all();
+	return SIGILL;		/* force out of emulation loop */
+}
+
+/* 
+ * Conversion table from MIPS compare ops 48-63
+ * cond = ieee754dp_cmp(x,y,IEEE754_UN);
+ */
+static const unsigned char cmptab[8] = {
+	0,					/* cmp_0 (sig) cmp_sf */
+	IEEE754_CUN,				/* cmp_un (sig) cmp_ngle */
+	IEEE754_CEQ,				/* cmp_eq (sig) cmp_seq */
+	IEEE754_CEQ | IEEE754_CUN,		/* cmp_ueq (sig) cmp_ngl  */
+	IEEE754_CLT,				/* cmp_olt (sig) cmp_lt */
+	IEEE754_CLT | IEEE754_CUN,		/* cmp_ult (sig) cmp_nge */
+	IEEE754_CLT | IEEE754_CEQ,		/* cmp_ole (sig) cmp_le */
+	IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
+};
+
+#define SIFROMREG(si,x)	((si) = ctx->regs[x])
+#define SITOREG(si,x)	(ctx->regs[x] = (int)(si))
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+#define DIFROMREG(di,x)	((di) = ctx->regs[x])
+#define DITOREG(di,x)	(ctx->regs[x] = (di))
+#endif
+
+#define SPFROMREG(sp,x)	((sp).bits = ctx->regs[x])
+#define SPTOREG(sp,x)	(ctx->regs[x] = (sp).bits)
+
+#ifdef CP0_STATUS_FR_SUPPORT
+#define DPFROMREG(dp,x)	((dp).bits = \
+			ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)])
+#define DPTOREG(dp,x)	(ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]\
+			= (dp).bits)
+#else
+/* Beware: MIPS COP1 doubles are always little_word endian in registers */
+#define DPFROMREG(dp,x)	\
+  ((dp).bits = ((unsigned long long)ctx->regs[(x)+1] << 32) | ctx->regs[x])
+#define DPTOREG(dp,x) \
+  (ctx->regs[x] = (dp).bits, ctx->regs[(x)+1] = (dp).bits >> 32)
+#endif
+
+#if __mips >= 4 && __mips != 32
+
+/*
+ * Additional MIPS4 instructions
+ */
+
+static ieee754dp fpemu_dp_recip(ieee754dp d)
+{
+	return ieee754dp_div(ieee754dp_one(0), d);
+}
+
+static ieee754dp fpemu_dp_rsqrt(ieee754dp d)
+{
+	return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
+}
+
+static ieee754sp fpemu_sp_recip(ieee754sp s)
+{
+	return ieee754sp_div(ieee754sp_one(0), s);
+}
+
+static ieee754sp fpemu_sp_rsqrt(ieee754sp s)
+{
+	return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
+}
+
+
+static ieee754dp fpemu_dp_madd(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+	return ieee754dp_add(ieee754dp_mul(s, t), r);
+}
+
+static ieee754dp fpemu_dp_msub(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+	return ieee754dp_sub(ieee754dp_mul(s, t), r);
+}
+
+static ieee754dp fpemu_dp_nmadd(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+	return ieee754dp_neg(ieee754dp_add(ieee754dp_mul(s, t), r));
+}
+
+static ieee754dp fpemu_dp_nmsub(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+	return ieee754dp_neg(ieee754dp_sub(ieee754dp_mul(s, t), r));
+}
+
+
+static ieee754sp fpemu_sp_madd(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+	return ieee754sp_add(ieee754sp_mul(s, t), r);
+}
+
+static ieee754sp fpemu_sp_msub(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+	return ieee754sp_sub(ieee754sp_mul(s, t), r);
+}
+
+static ieee754sp fpemu_sp_nmadd(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+	return ieee754sp_neg(ieee754sp_add(ieee754sp_mul(s, t), r));
+}
+
+static ieee754sp fpemu_sp_nmsub(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+	return ieee754sp_neg(ieee754sp_sub(ieee754sp_mul(s, t), r));
+}
+
+static int
+fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+	 mips_instruction ir)
+{
+	unsigned rcsr = 0;	/* resulting csr */
+
+	fpuemuprivate.stats.cp1xops++;
+
+	switch (MIPSInst_FMA_FFMT(ir)) {
+	case s_fmt:		/* 0 */
+		{
+			ieee754sp(*handler) (ieee754sp, ieee754sp,
+					     ieee754sp);
+			ieee754sp fd, fr, fs, ft;
+
+			switch (MIPSInst_FUNC(ir)) {
+			case lwxc1_op:
+				{
+					void *va =
+					    REG_TO_VA(xcp->
+						      regs[MIPSInst_FR(ir)]
+						      +
+						      xcp->
+						      regs[MIPSInst_FT
+							   (ir)]);
+					fpureg_t val;
+					int err = 0;
+					val = mips_get_word(xcp, va, &err);
+					if (err) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+					if (xcp->cp0_status & ST0_FR) {
+						/* load whole register */
+						ctx->
+						    regs[MIPSInst_FD(ir)] =
+						    val;
+					} else if (MIPSInst_FD(ir) & 1) {
+						/* load to m.s. 32 bits */
+#if defined(SINGLE_ONLY_FPU)
+						/* illegal register in single-float mode */
+						return SIGILL;
+#else
+						ctx->
+						    regs[
+							 (MIPSInst_FD(ir) &
+							  ~1)] &=
+						    0xffffffff;
+						ctx->
+						    regs[
+							 (MIPSInst_FD(ir) &
+							  ~1)] |=
+						    val << 32;
+#endif
+					} else {
+						/* load to l.s. 32 bits */
+						ctx->
+						    regs[MIPSInst_FD(ir)]
+						    &= ~0xffffffffLL;
+						ctx->
+						    regs[MIPSInst_FD(ir)]
+						    |= val;
+					}
+				}
+				break;
+
+			case swxc1_op:
+				{
+					void *va =
+					    REG_TO_VA(xcp->
+						      regs[MIPSInst_FR(ir)]
+						      +
+						      xcp->
+						      regs[MIPSInst_FT
+							   (ir)]);
+					unsigned int val;
+					if (xcp->cp0_status & ST0_FR) {
+						/* store whole register */
+						val =
+						    ctx->
+						    regs[MIPSInst_FS(ir)];
+					} else if (MIPSInst_FS(ir) & 1) {
+#if defined(SINGLE_ONLY_FPU)
+						/* illegal register in single-float mode */
+						return SIGILL;
+#else
+						/* store from m.s. 32 bits */
+						val =
+						    ctx->
+						    regs[
+							 (MIPSInst_FS(ir) &
+							  ~1)] >> 32;
+#endif
+					} else {
+						/* store from l.s. 32 bits */
+						val =
+						    ctx->
+						    regs[MIPSInst_FS(ir)];
+					}
+					if (mips_put_word(xcp, va, val)) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+				}
+				break;
+
+			case madd_s_op:
+				handler = fpemu_sp_madd;
+				goto scoptop;
+			case msub_s_op:
+				handler = fpemu_sp_msub;
+				goto scoptop;
+			case nmadd_s_op:
+				handler = fpemu_sp_nmadd;
+				goto scoptop;
+			case nmsub_s_op:
+				handler = fpemu_sp_nmsub;
+				goto scoptop;
+
+			      scoptop:
+				SPFROMREG(fr, MIPSInst_FR(ir));
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				SPFROMREG(ft, MIPSInst_FT(ir));
+				fd = (*handler) (fr, fs, ft);
+				SPTOREG(fd, MIPSInst_FD(ir));
+
+			      copcsr:
+				if (ieee754_cxtest(IEEE754_INEXACT))
+					rcsr |=
+					    FPU_CSR_INE_X | FPU_CSR_INE_S;
+				if (ieee754_cxtest(IEEE754_UNDERFLOW))
+					rcsr |=
+					    FPU_CSR_UDF_X | FPU_CSR_UDF_S;
+				if (ieee754_cxtest(IEEE754_OVERFLOW))
+					rcsr |=
+					    FPU_CSR_OVF_X | FPU_CSR_OVF_S;
+				if (ieee754_cxtest
+				    (IEEE754_INVALID_OPERATION)) rcsr |=
+					    FPU_CSR_INV_X | FPU_CSR_INV_S;
+
+				ctx->sr =
+				    (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
+				if ((ctx->sr >> 5) & ctx->
+				    sr & FPU_CSR_ALL_E) {
+		/*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */
+					return SIGFPE;
+				}
+
+				break;
+
+			default:
+				return SIGILL;
+			}
+		}
+		break;
+
+#if !defined(SINGLE_ONLY_FPU)
+	case d_fmt:		/* 1 */
+		{
+			ieee754dp(*handler) (ieee754dp, ieee754dp,
+					     ieee754dp);
+			ieee754dp fd, fr, fs, ft;
+
+			switch (MIPSInst_FUNC(ir)) {
+			case ldxc1_op:
+				{
+					void *va =
+					    REG_TO_VA(xcp->
+						      regs[MIPSInst_FR(ir)]
+						      +
+						      xcp->
+						      regs[MIPSInst_FT
+							   (ir)]);
+					int err = 0;
+					ctx->regs[MIPSInst_FD(ir)] =
+					    mips_get_dword(xcp, va, &err);
+					if (err) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+				}
+				break;
+
+			case sdxc1_op:
+				{
+					void *va =
+					    REG_TO_VA(xcp->
+						      regs[MIPSInst_FR(ir)]
+						      +
+						      xcp->
+						      regs[MIPSInst_FT
+							   (ir)]);
+					if (mips_put_dword
+					    (xcp, va,
+					     ctx->regs[MIPSInst_FS(ir)])) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+				}
+				break;
+
+			case madd_d_op:
+				handler = fpemu_dp_madd;
+				goto dcoptop;
+			case msub_d_op:
+				handler = fpemu_dp_msub;
+				goto dcoptop;
+			case nmadd_d_op:
+				handler = fpemu_dp_nmadd;
+				goto dcoptop;
+			case nmsub_d_op:
+				handler = fpemu_dp_nmsub;
+				goto dcoptop;
+
+			      dcoptop:
+				DPFROMREG(fr, MIPSInst_FR(ir));
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				DPFROMREG(ft, MIPSInst_FT(ir));
+				fd = (*handler) (fr, fs, ft);
+				DPTOREG(fd, MIPSInst_FD(ir));
+				goto copcsr;
+
+			default:
+				return SIGILL;
+			}
+		}
+		break;
+#endif
+
+	case 0x7:		/* 7 */
+		{
+			if (MIPSInst_FUNC(ir) != pfetch_op) {
+				return SIGILL;
+			}
+			/* ignore prefx operation */
+		}
+		break;
+
+	default:
+		return SIGILL;
+	}
+
+	return 0;
+}
+#endif
+
+
+
+/*
+ * Emulate a single COP1 arithmetic instruction.
+ */
+static int
+fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+	mips_instruction ir)
+{
+	int rfmt;		/* resulting format */
+	unsigned rcsr = 0;	/* resulting csr */
+	unsigned cond;
+	union {
+		ieee754dp d;
+		ieee754sp s;
+		int w;
+#if __mips64
+		long long l;
+#endif
+	} rv;			/* resulting value */
+
+	fpuemuprivate.stats.cp1ops++;
+	switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
+
+	case s_fmt:{		/* 0 */
+		ieee754sp(*handler) ();
+
+		switch (MIPSInst_FUNC(ir)) {
+			/* binary ops */
+		case fadd_op:
+			handler = ieee754sp_add;
+			goto scopbop;
+		case fsub_op:
+			handler = ieee754sp_sub;
+			goto scopbop;
+		case fmul_op:
+			handler = ieee754sp_mul;
+			goto scopbop;
+		case fdiv_op:
+			handler = ieee754sp_div;
+			goto scopbop;
+
+			/* unary  ops */
+#if __mips >= 2 || __mips64
+		case fsqrt_op:
+			handler = ieee754sp_sqrt;
+			goto scopuop;
+#endif
+#if __mips >= 4 && __mips != 32
+		case frsqrt_op:
+			handler = fpemu_sp_rsqrt;
+			goto scopuop;
+		case frecip_op:
+			handler = fpemu_sp_recip;
+			goto scopuop;
+#endif
+#if __mips >= 4
+		case fmovc_op:
+			cond = fpucondbit[MIPSInst_FT(ir) >> 2];
+			if (((ctx->sr & cond) != 0) !=
+			    ((MIPSInst_FT(ir) & 1) != 0))
+				return 0;
+			SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+		case fmovz_op:
+			if (xcp->regs[MIPSInst_FT(ir)] != 0)
+				return 0;
+			SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+		case fmovn_op:
+			if (xcp->regs[MIPSInst_FT(ir)] == 0)
+				return 0;
+			SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+#endif
+		case fabs_op:
+			handler = ieee754sp_abs;
+			goto scopuop;
+		case fneg_op:
+			handler = ieee754sp_neg;
+			goto scopuop;
+		case fmov_op:
+			/* an easy one */
+			SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+			/* binary op on handler */
+scopbop:
+			{
+				ieee754sp fs, ft;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				SPFROMREG(ft, MIPSInst_FT(ir));
+
+				rv.s = (*handler) (fs, ft);
+				goto copcsr;
+			}
+scopuop:
+			{
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				rv.s = (*handler) (fs);
+				goto copcsr;
+			}
+copcsr:
+			if (ieee754_cxtest(IEEE754_INEXACT))
+				rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
+			if (ieee754_cxtest(IEEE754_UNDERFLOW))
+				rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
+			if (ieee754_cxtest(IEEE754_OVERFLOW))
+				rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
+			if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
+				rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
+			if (ieee754_cxtest
+				(IEEE754_INVALID_OPERATION)) rcsr |=
+					    FPU_CSR_INV_X | FPU_CSR_INV_S;
+				break;
+
+				/* unary conv ops */
+		case fcvts_op:
+			return SIGILL;	/* not defined */
+		case fcvtd_op:
+#if defined(SINGLE_ONLY_FPU)
+			return SIGILL;	/* not defined */
+#else
+			{
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				rv.d = ieee754dp_fsp(fs);
+				rfmt = d_fmt;
+				goto copcsr;
+			}
+#endif
+		case fcvtw_op:
+			{
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				rv.w = ieee754sp_tint(fs);
+				rfmt = w_fmt;
+				goto copcsr;
+			}
+
+#if __mips >= 2 || __mips64
+		case fround_op:
+		case ftrunc_op:
+		case fceil_op:
+		case ffloor_op:
+			{
+				unsigned int oldrm = ieee754_csr.rm;
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+				rv.w = ieee754sp_tint(fs);
+				ieee754_csr.rm = oldrm;
+				rfmt = w_fmt;
+				goto copcsr;
+			}
+#endif			/* __mips >= 2 */
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+		case fcvtl_op:
+			{
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				rv.l = ieee754sp_tlong(fs);
+				rfmt = l_fmt;
+				goto copcsr;
+			}
+
+		case froundl_op:
+		case ftruncl_op:
+		case fceill_op:
+		case ffloorl_op:
+			{
+				unsigned int oldrm = ieee754_csr.rm;
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+				rv.l = ieee754sp_tlong(fs);
+				ieee754_csr.rm = oldrm;
+				rfmt = l_fmt;
+				goto copcsr;
+			}
+#endif /* __mips64 && !fpu(single) */
+
+		default:
+			if (MIPSInst_FUNC(ir) >= fcmp_op) {
+				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
+				ieee754sp fs, ft;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				SPFROMREG(ft, MIPSInst_FT(ir));
+				rv.w = ieee754sp_cmp(fs, ft, cmptab[cmpop & 0x7]);
+				rfmt = -1;
+				if ((cmpop & 0x8) && ieee754_cxtest(IEEE754_INVALID_OPERATION))
+					rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+				} else {
+					return SIGILL;
+				}
+				break;
+			}
+			break;
+		}
+
+#if !defined(SINGLE_ONLY_FPU)
+	case d_fmt: {
+		ieee754dp(*handler) ();
+
+		switch (MIPSInst_FUNC(ir)) {
+			/* binary ops */
+		case fadd_op:
+			handler = ieee754dp_add;
+			goto dcopbop;
+		case fsub_op:
+			handler = ieee754dp_sub;
+			goto dcopbop;
+		case fmul_op:
+			handler = ieee754dp_mul;
+			goto dcopbop;
+		case fdiv_op:
+			handler = ieee754dp_div;
+			goto dcopbop;
+
+			/* unary  ops */
+#if __mips >= 2 || __mips64
+		case fsqrt_op:
+			handler = ieee754dp_sqrt;
+			goto dcopuop;
+#endif
+#if __mips >= 4 && __mips != 32
+		case frsqrt_op:
+			handler = fpemu_dp_rsqrt;
+			goto dcopuop;
+		case frecip_op:
+			handler = fpemu_dp_recip;
+			goto dcopuop;
+#endif
+#if __mips >= 4
+		case fmovc_op:
+			cond = fpucondbit[MIPSInst_FT(ir) >> 2];
+			if (((ctx->sr & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0))
+				return 0;
+			DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+		case fmovz_op:
+			if (xcp->regs[MIPSInst_FT(ir)] != 0)
+				return 0;
+			DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+		case fmovn_op:
+			if (xcp->regs[MIPSInst_FT(ir)] == 0)
+				return 0;
+			DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+#endif
+		case fabs_op:
+			handler = ieee754dp_abs;
+			goto dcopuop;
+		case fneg_op:
+			handler = ieee754dp_neg;
+			goto dcopuop;
+		case fmov_op:
+			/* an easy one */
+			DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+
+			/* binary op on handler */
+dcopbop:
+			{
+				ieee754dp fs, ft;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				DPFROMREG(ft, MIPSInst_FT(ir));
+
+				rv.d = (*handler) (fs, ft);
+				goto copcsr;
+			}
+dcopuop:
+			{
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				rv.d = (*handler) (fs);
+				goto copcsr;
+			}
+
+		/* unary conv ops */
+		case fcvts_op:
+			{
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				rv.s = ieee754sp_fdp(fs);
+				rfmt = s_fmt;
+				goto copcsr;
+			}
+		case fcvtd_op:
+			return SIGILL;	/* not defined */
+		case fcvtw_op:
+			{
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				rv.w = ieee754dp_tint(fs);	/* wrong */
+				rfmt = w_fmt;
+				goto copcsr;
+			}
+
+#if __mips >= 2 || __mips64
+		case fround_op:
+		case ftrunc_op:
+		case fceil_op:
+		case ffloor_op:
+			{
+				unsigned int oldrm = ieee754_csr.rm;
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+				rv.w = ieee754dp_tint(fs);
+				ieee754_csr.rm = oldrm;
+				rfmt = w_fmt;
+				goto copcsr;
+			}
+#endif
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+		case fcvtl_op:
+			{
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				rv.l = ieee754dp_tlong(fs);
+				rfmt = l_fmt;
+				goto copcsr;
+			}
+
+		case froundl_op:
+		case ftruncl_op:
+		case fceill_op:
+		case ffloorl_op:
+			{
+				unsigned int oldrm = ieee754_csr.rm;
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+				rv.l = ieee754dp_tlong(fs);
+				ieee754_csr.rm = oldrm;
+				rfmt = l_fmt;
+				goto copcsr;
+			}
+#endif /* __mips >= 3 && !fpu(single) */
+
+		default:
+			if (MIPSInst_FUNC(ir) >= fcmp_op) {
+				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
+				ieee754dp fs, ft;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				DPFROMREG(ft, MIPSInst_FT(ir));
+				rv.w = ieee754dp_cmp(fs, ft, cmptab[cmpop & 0x7]);
+				rfmt = -1;
+				if ((cmpop & 0x8) && ieee754_cxtest (IEEE754_INVALID_OPERATION))
+					rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+			} else {
+				return SIGILL;
+			}
+			break;
+		}
+		break;
+	}
+#endif				/* !defined(SINGLE_ONLY_FPU) */
+
+	case w_fmt: {
+		switch (MIPSInst_FUNC(ir)) {
+		case fcvts_op:
+			/* convert word to single precision real */
+			rv.s = ieee754sp_fint(ctx-> regs[MIPSInst_FS(ir)]);
+			rfmt = s_fmt;
+			goto copcsr;
+#if !defined(SINGLE_ONLY_FPU)
+		case fcvtd_op:
+			/* convert word to double precision real */
+			rv.d = ieee754dp_fint(ctx-> regs[MIPSInst_FS(ir)]);
+			rfmt = d_fmt;
+			goto copcsr;
+#endif
+		default:
+			return SIGILL;
+		}
+		break;
+	}
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+	case l_fmt: {
+		switch (MIPSInst_FUNC(ir)) {
+		case fcvts_op:
+			/* convert long to single precision real */
+			rv.s = ieee754sp_flong(ctx-> regs[MIPSInst_FS(ir)]);
+			rfmt = s_fmt;
+			goto copcsr;
+		case fcvtd_op:
+			/* convert long to double precision real */
+			rv.d = ieee754dp_flong(ctx-> regs[MIPSInst_FS(ir)]);
+			rfmt = d_fmt;
+			goto copcsr;
+		default:
+			return SIGILL;
+		}
+		break;
+	}
+#endif
+
+	default:
+		return SIGILL;
+	}
+
+	/*
+	 * Update the fpu CSR register for this operation.
+	 * If an exception is required, generate a tidy SIGFPE exception,
+	 * without updating the result register.
+	 * Note: cause exception bits do not accumulate, they are rewritten
+	 * for each op; only the flag/sticky bits accumulate.
+	 */
+	ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
+	if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) {
+		/*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */
+		return SIGFPE;
+	}
+
+	/* 
+	 * Now we can safely write the result back to the register file.
+	 */
+	switch (rfmt) {
+	case -1: {
+#if __mips >= 4
+		cond = fpucondbit[MIPSInst_FD(ir) >> 2];
+#else
+		cond = FPU_CSR_COND;
+#endif
+		if (rv.w)
+			ctx->sr |= cond;
+		else
+			ctx->sr &= ~cond;
+		break;
+	}
+#if !defined(SINGLE_ONLY_FPU)
+	case d_fmt:
+		DPTOREG(rv.d, MIPSInst_FD(ir));
+		break;
+#endif
+	case s_fmt:
+		SPTOREG(rv.s, MIPSInst_FD(ir));
+		break;
+	case w_fmt:
+		SITOREG(rv.w, MIPSInst_FD(ir));
+		break;
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+	case l_fmt:
+		DITOREG(rv.l, MIPSInst_FD(ir));
+		break;
+#endif
+	default:
+		return SIGILL;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Emulate the floating point instruction at EPC, and continue
+ * to run until we hit a non-fp instruction, or a backward
+ * branch.  This cuts down dramatically on the per instruction 
+ * exception overhead.
+ */
+int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp)
+{
+	struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
+	unsigned long oldepc, prevepc;
+	unsigned int insn;
+	int sig = 0;
+	int err = 0;
+
+	oldepc = xcp->cp0_epc;
+	do {
+		prevepc = xcp->cp0_epc;
+		insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err);
+		if (err) {
+			fpuemuprivate.stats.errors++;
+			return SIGBUS;
+		}
+		if (insn != 0)
+			sig = cop1Emulate(xcptno, xcp, ctx);
+		else
+			xcp->cp0_epc += 4;	/* skip nops */
+	} while (xcp->cp0_epc > prevepc && sig == 0);
+
+	/* SIGILL indicates a non-fpu instruction */
+	if (sig == SIGILL && xcp->cp0_epc != oldepc)
+		/* but if epc has advanced, then ignore it */
+		sig = 0;
+
+	return sig;
+}
+
+
+#ifdef NOTDEF
+/*
+ * Patch up the hardware fpu state when an f.p. exception occurs.  
+ */
+static int cop1Patcher(int xcptno, struct pt_regs *xcp)
+{
+	struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
+	unsigned sr;
+	int sig;
+
+	/* reenable Cp1, else fpe_save() will get nested exception */
+	sr = mips_bissr(ST0_CU1);
+
+	/* get fpu registers and status, then clear pending exceptions */
+	fpe_save(ctx);
+	fpe_setsr(ctx->sr &= ~FPU_CSR_ALL_X);
+
+	/* get current rounding mode for IEEE library, and emulate insn */
+	ieee754_csr.rm = ieee_rm[ctx->sr & 0x3];
+	sig = cop1Emulate(xcptno, xcp, ctx);
+
+	/* don't return with f.p. exceptions pending */
+	ctx->sr &= ~FPU_CSR_ALL_X;
+	fpe_restore(ctx);
+
+	mips_setsr(sr);
+	return sig;
+}
+
+void _cop1_init(int emulate)
+{
+	extern int _nofpu;
+
+	if (emulate) {
+		/* 
+		 * Install cop1 emulator to handle "coprocessor unusable" exception
+		 */
+		xcption(XCPTCPU, cop1Handler);
+		fpuemuactive = 1;	/* tell dbg.c that we are in charge */
+		_nofpu = 0;	/* tell setjmp() it "has" an fpu */
+	} else {
+		/* 
+		 * Install cop1 emulator for floating point exceptions only,
+		 * i.e. denormalised results, underflow, overflow etc, which
+		 * must be emulated in s/w.
+		 */
+#ifdef 1
+		/* r4000 or above use dedicate exception */
+		xcption(XCPTFPE, cop1Patcher);
+#else
+		/* r3000 et al use interrupt */
+		extern int _sbd_getfpuintr(void);
+		int intno = _sbd_getfpuintr();
+		intrupt(intno, cop1Patcher, 0);
+		mips_bissr(SR_IM0 << intno);
+#endif
+
+#if (#cpu(r4640) || #cpu(r4650)) && !defined(SINGLE_ONLY_FPU)
+		/* For R4640/R4650 compiled *without* the -msingle-float flag,
+		   then we share responsibility: the h/w handles the single
+		   precision operations, and the trap emulator handles the
+		   double precision. We set fpuemuactive so that dbg.c first
+		   fetches the s/w state before saving the h/w state. */
+		fpuemuactive = 1;
+		{
+			int i;
+			/* initialise the unused d.p high order words to be NaN */
+			for (i = 0; i < 32; i++)
+				current->thread.fpu.soft.regs[i] =
+				    0x7ff80bad00000000LL;
+		}
+#endif				/* (r4640 || r4650) && !fpu(single) */
+	}
+}
+#endif
+
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_add.c linux/arch/mips/math-emu/dp_add.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_add.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_add.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,186 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
+{
+	COMPXDP;
+	COMPYDP;
+
+	EXPLODEXDP;
+	EXPLODEYDP;
+
+	CLEARCX;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "add", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y, "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754dp_nanxcpt(x, "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754dp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Inifity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		if (xs == ys)
+			return x;
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return x;
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		if (xs == ys)
+			return x;
+		else
+			return ieee754dp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return x;
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		DPDNORMX;
+
+		/* FALL THROUGH */
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		DPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		DPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	assert(xm & DP_HIDDEN_BIT);
+	assert(ym & DP_HIDDEN_BIT);
+
+	/* provide guard,round and stick bit space */
+	xm <<= 3;
+	ym <<= 3;
+
+	if (xe > ye) {
+		/* have to shift y fraction right to align
+		 */
+		int s = xe - ye;
+		ym = XDPSRS(ym, s);
+		ye += s;
+	} else if (ye > xe) {
+		/* have to shift x fraction right to align
+		 */
+		int s = ye - xe;
+		xm = XDPSRS(xm, s);
+		xe += s;
+	}
+	assert(xe == ye);
+	assert(xe <= DP_EMAX);
+
+	if (xs == ys) {
+		/* generate 28 bit result of adding two 27 bit numbers
+		 * leaving result in xm,xs,xe
+		 */
+		xm = xm + ym;
+		xe = xe;
+		xs = xs;
+
+		if (xm >> (DP_MBITS + 1 + 3)) {	/* carry out */
+			xm = XDPSRS1(xm);
+			xe++;
+		}
+	} else {
+		if (xm >= ym) {
+			xm = xm - ym;
+			xe = xe;
+			xs = xs;
+		} else {
+			xm = ym - xm;
+			xe = xe;
+			xs = ys;
+		}
+		if (xm == 0)
+			return ieee754dp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+		/* normalize to rounding precision */
+		while ((xm >> (DP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+
+	}
+	DPNORMRET2(xs, xe, xm, "add", x, y);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_cmp.c linux/arch/mips/math-emu/dp_cmp.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_cmp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_cmp.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp)
+{
+	CLEARCX;
+
+	if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) {
+		if (cmp & IEEE754_CUN)
+			return 1;
+		if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
+			if (SETCX(IEEE754_INVALID_OPERATION))
+				return ieee754si_xcpt(0, "fcmpf", x);
+		}
+		return 0;
+	} else {
+		long long int vx = x.bits;
+		long long int vy = y.bits;
+
+		if (vx < 0)
+			vx = -vx ^ DP_SIGN_BIT;
+		if (vy < 0)
+			vy = -vy ^ DP_SIGN_BIT;
+
+		if (vx < vy)
+			return (cmp & IEEE754_CLT) != 0;
+		else if (vx == vy)
+			return (cmp & IEEE754_CEQ) != 0;
+		else
+			return (cmp & IEEE754_CGT) != 0;
+	}
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_div.c linux/arch/mips/math-emu/dp_div.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_div.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_div.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,160 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
+{
+	COMPXDP;
+	COMPYDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+	EXPLODEYDP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "div", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y, "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754dp_nanxcpt(x, "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754dp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Infinity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+		return ieee754dp_zero(xs ^ ys);
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return ieee754dp_inf(xs ^ ys);
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		SETCX(IEEE754_ZERO_DIVIDE);
+		return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		return ieee754dp_zero(xs == ys ? 0 : 1);
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		DPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		DPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		DPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	assert(xm & DP_HIDDEN_BIT);
+	assert(ym & DP_HIDDEN_BIT);
+
+	/* provide rounding space */
+	xm <<= 3;
+	ym <<= 3;
+
+	{
+		/* now the dirty work */
+
+		unsigned long long rm = 0;
+		int re = xe - ye;
+		unsigned long long bm;
+
+		for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) {
+			if (xm >= ym) {
+				xm -= ym;
+				rm |= bm;
+				if (xm == 0)
+					break;
+			}
+			xm <<= 1;
+		}
+		rm <<= 1;
+		if (xm)
+			rm |= 1;	/* have remainder, set sticky */
+
+		assert(rm);
+
+		/* normalise rm to rounding precision ?
+		 */
+		while ((rm >> (DP_MBITS + 3)) == 0) {
+			rm <<= 1;
+			re--;
+		}
+
+		DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+	}
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_fint.c linux/arch/mips/math-emu/dp_fint.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_fint.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_fint.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,78 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_fint(int x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	if (x == 0)
+		return ieee754dp_zero(0);
+	if (x == 1 || x == -1)
+		return ieee754dp_one(x < 0);
+	if (x == 10 || x == -10)
+		return ieee754dp_ten(x < 0);
+
+	xs = (x < 0);
+	if (xs) {
+		if (x == (1 << 31))
+			xm = ((unsigned) 1 << 31);	/* max neg can't be safely negated */
+		else
+			xm = -x;
+	} else {
+		xm = x;
+	}
+
+#if 1
+	/* normalize - result can never be inexact or overflow */
+	xe = DP_MBITS;
+	while ((xm >> DP_MBITS) == 0) {
+		xm <<= 1;
+		xe--;
+	}
+	return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+#else
+	/* normalize */
+	xe = DP_MBITS + 3;
+	while ((xm >> (DP_MBITS + 3)) == 0) {
+		xm <<= 1;
+		xe--;
+	}
+	DPNORMRET1(xs, xe, xm, "fint", x);
+#endif
+}
+
+ieee754dp ieee754dp_funs(unsigned int u)
+{
+	if ((int) u < 0)
+		return ieee754dp_add(ieee754dp_1e31(),
+				     ieee754dp_fint(u & ~(1 << 31)));
+	return ieee754dp_fint(u);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_flong.c linux/arch/mips/math-emu/dp_flong.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_flong.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_flong.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,76 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_flong(long long x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	if (x == 0)
+		return ieee754dp_zero(0);
+	if (x == 1 || x == -1)
+		return ieee754dp_one(x < 0);
+	if (x == 10 || x == -10)
+		return ieee754dp_ten(x < 0);
+
+	xs = (x < 0);
+	if (xs) {
+		if (x == (1ULL << 63))
+			xm = (1ULL << 63);	/* max neg can't be safely negated */
+		else
+			xm = -x;
+	} else {
+		xm = x;
+	}
+
+	/* normalize */
+	xe = DP_MBITS + 3;
+	if (xm >> (DP_MBITS + 1 + 3)) {
+		/* shunt out overflow bits */
+		while (xm >> (DP_MBITS + 1 + 3)) {
+			XDPSRSX1();
+		}
+	} else {
+		/* normalize in grs extended double precision */
+		while ((xm >> (DP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	DPNORMRET1(xs, xe, xm, "dp_flong", x);
+}
+
+ieee754dp ieee754dp_fulong(unsigned long long u)
+{
+	if ((long long) u < 0)
+		return ieee754dp_add(ieee754dp_1e63(),
+				     ieee754dp_flong(u & ~(1ULL << 63)));
+	return ieee754dp_flong(u);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_frexp.c linux/arch/mips/math-emu/dp_frexp.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_frexp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_frexp.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,53 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+/* close to ieeep754dp_logb 
+*/
+ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr)
+{
+	COMPXDP;
+	CLEARCX;
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		*eptr = 0;
+		return x;
+	case IEEE754_CLASS_DNORM:
+		DPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	*eptr = xe + 1;
+	return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_fsp.c linux/arch/mips/math-emu/dp_fsp.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_fsp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_fsp.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,70 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_fsp(ieee754sp x)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		return ieee754dp_nanxcpt(builddp(xs,
+						 DP_EMAX + 1 + DP_EBIAS,
+						 ((unsigned long long) xm
+						  << (DP_MBITS -
+						      SP_MBITS))), "fsp",
+					 x);
+	case IEEE754_CLASS_INF:
+		return ieee754dp_inf(xs);
+	case IEEE754_CLASS_ZERO:
+		return ieee754dp_zero(xs);
+	case IEEE754_CLASS_DNORM:
+		/* normalize */
+		while ((xm >> SP_MBITS) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+
+	/* CANT possibly overflow,underflow, or need rounding
+	 */
+
+	/* drop the hidden bit */
+	xm &= ~SP_HIDDEN_BIT;
+
+	return builddp(xs, xe + DP_EBIAS,
+		       (unsigned long long) xm << (DP_MBITS - SP_MBITS));
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_logb.c linux/arch/mips/math-emu/dp_logb.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_logb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_logb.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,54 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_logb(ieee754dp x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754dp_nanxcpt(x, "logb", x);
+	case IEEE754_CLASS_QNAN:
+		return x;
+	case IEEE754_CLASS_INF:
+		return ieee754dp_inf(0);
+	case IEEE754_CLASS_ZERO:
+		return ieee754dp_inf(1);
+	case IEEE754_CLASS_DNORM:
+		DPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	return ieee754dp_fint(xe);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_modf.c linux/arch/mips/math-emu/dp_modf.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_modf.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_modf.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,80 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+/* modf function is always exact for a finite number
+*/
+ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		*ip = x;
+		return x;
+	case IEEE754_CLASS_DNORM:
+		/* far to small */
+		*ip = ieee754dp_zero(xs);
+		return x;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe < 0) {
+		*ip = ieee754dp_zero(xs);
+		return x;
+	}
+	if (xe >= DP_MBITS) {
+		*ip = x;
+		return ieee754dp_zero(xs);
+	}
+	/* generate ipart mantissa by clearing bottom bits 
+	 */
+	*ip = builddp(xs, xe + DP_EBIAS,
+		      ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) &
+		      ~DP_HIDDEN_BIT);
+
+	/* generate fpart mantissa by clearing top bits
+	 * and normalizing (must be able to normalize)
+	 */
+	xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe));
+	if (xm == 0)
+		return ieee754dp_zero(xs);
+
+	while ((xm >> DP_MBITS) == 0) {
+		xm <<= 1;
+		xe--;
+	}
+	return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_mul.c linux/arch/mips/math-emu/dp_mul.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_mul.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_mul.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,180 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
+{
+	COMPXDP;
+	COMPYDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+	EXPLODEYDP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "mul", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y, "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754dp_nanxcpt(x, "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754dp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Infinity handeling */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		return ieee754dp_inf(xs ^ ys);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return ieee754dp_zero(xs ^ ys);
+
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		DPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		DPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		DPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	/* rm = xm * ym, re = xe+ye basicly */
+	assert(xm & DP_HIDDEN_BIT);
+	assert(ym & DP_HIDDEN_BIT);
+	{
+		int re = xe + ye;
+		int rs = xs ^ ys;
+		unsigned long long rm;
+
+		/* shunt to top of word */
+		xm <<= 64 - (DP_MBITS + 1);
+		ym <<= 64 - (DP_MBITS + 1);
+
+		/* multiply 32bits xm,ym to give high 32bits rm with stickness
+		 */
+
+		/* 32 * 32 => 64 */
+#define DPXMULT(x,y)	((unsigned long long)(x) * (unsigned long long)y)
+
+		{
+			unsigned lxm = xm;
+			unsigned hxm = xm >> 32;
+			unsigned lym = ym;
+			unsigned hym = ym >> 32;
+			unsigned long long lrm;
+			unsigned long long hrm;
+
+			lrm = DPXMULT(lxm, lym);
+			hrm = DPXMULT(hxm, hym);
+
+			{
+				unsigned long long t = DPXMULT(lxm, hym);
+				{
+					unsigned long long at =
+					    lrm + (t << 32);
+					hrm += at < lrm;
+					lrm = at;
+				}
+				hrm = hrm + (t >> 32);
+			}
+
+			{
+				unsigned long long t = DPXMULT(hxm, lym);
+				{
+					unsigned long long at =
+					    lrm + (t << 32);
+					hrm += at < lrm;
+					lrm = at;
+				}
+				hrm = hrm + (t >> 32);
+			}
+			rm = hrm | (lrm != 0);
+		}
+
+		/*
+		 * sticky shift down to normal rounding precision
+		 */
+		if ((signed long long) rm < 0) {
+			rm =
+			    (rm >> (64 - (DP_MBITS + 1 + 3))) |
+			    ((rm << (DP_MBITS + 1 + 3)) != 0);
+			re++;
+		} else {
+			rm =
+			    (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) |
+			    ((rm << (DP_MBITS + 1 + 3 + 1)) != 0);
+		}
+		assert(rm & (DP_HIDDEN_BIT << 3));
+		DPNORMRET2(rs, re, rm, "mul", x, y);
+	}
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_scalb.c linux/arch/mips/math-emu/dp_scalb.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_scalb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_scalb.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_scalb(ieee754dp x, int n)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754dp_nanxcpt(x, "scalb", x, n);
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		return x;
+	case IEEE754_CLASS_DNORM:
+		DPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
+}
+
+
+ieee754dp ieee754dp_ldexp(ieee754dp x, int n)
+{
+	return ieee754dp_scalb(x, n);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_simple.c linux/arch/mips/math-emu/dp_simple.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_simple.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_simple.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,66 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+int ieee754dp_finite(ieee754dp x)
+{
+	return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS;
+}
+
+ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y)
+{
+	CLEARCX;
+	DPSIGN(x) = DPSIGN(y);
+	return x;
+}
+
+
+ieee754dp ieee754dp_neg(ieee754dp x)
+{
+	CLEARCX;
+
+	if (ieee754dp_isnan(x))	/* but not infinity */
+		return ieee754dp_nanxcpt(x, "neg", x);
+
+	/* quick fix up */
+	DPSIGN(x) ^= 1;
+	return x;
+}
+
+
+ieee754dp ieee754dp_abs(ieee754dp x)
+{
+	CLEARCX;
+
+	if (ieee754dp_isnan(x))	/* but not infinity */
+		return ieee754dp_nanxcpt(x, "abs", x);
+
+	/* quick fix up */
+	DPSIGN(x) = 0;
+	return x;
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_sqrt.c linux/arch/mips/math-emu/dp_sqrt.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_sqrt.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_sqrt.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,167 @@
+/* IEEE754 floating point arithmetic
+ * double precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+static const struct ieee754dp_konst knan = {
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+	0, 0, DP_EBIAS + DP_EMAX + 1, 0
+#else
+	0, DP_EBIAS + DP_EMAX + 1, 0, 0
+#endif
+};
+
+#define nan	((ieee754dp)knan)
+
+static const unsigned table[] = {
+	0, 1204, 3062, 5746, 9193, 13348, 18162, 23592,
+	29598, 36145, 43202, 50740, 58733, 67158, 75992,
+	85215, 83599, 71378, 60428, 50647, 41945, 34246,
+	27478, 21581, 16499, 12183, 8588, 5674, 3403,
+	1742, 661, 130
+};
+
+ieee754dp ieee754dp_sqrt(ieee754dp x)
+{
+	struct ieee754_csr oldcsr;
+	ieee754dp y, z, t;
+	unsigned scalx, yh;
+	COMPXDP;
+
+	EXPLODEXDP;
+
+	/* x == INF or NAN? */
+	switch (xc) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		/* sqrt(Nan) = Nan */
+		return ieee754dp_nanxcpt(x, "sqrt");
+	case IEEE754_CLASS_ZERO:
+		/* sqrt(0) = 0 */
+		return x;
+	case IEEE754_CLASS_INF:
+		if (xs)
+			/* sqrt(-Inf) = Nan */
+			return ieee754dp_nanxcpt(nan, "sqrt");
+		/* sqrt(+Inf) = Inf */
+		return x;
+	case IEEE754_CLASS_DNORM:
+		DPDNORMX;
+		/* fall through */
+	case IEEE754_CLASS_NORM:
+		if (xs)
+			/* sqrt(-x) = Nan */
+			return ieee754dp_nanxcpt(nan, "sqrt");
+		break;
+	}
+
+	/* save old csr; switch off INX enable & flag; set RN rounding */
+	oldcsr = ieee754_csr;
+	ieee754_csr.mx &= ~IEEE754_INEXACT;
+	ieee754_csr.sx &= ~IEEE754_INEXACT;
+	ieee754_csr.rm = IEEE754_RN;
+
+	/* adjust exponent to prevent overflow */
+	scalx = 0;
+	if (xe > 512) {		/* x > 2**-512? */
+		xe -= 512;	/* x = x / 2**512 */
+		scalx += 256;
+	} else if (xe < -512) {	/* x < 2**-512? */
+		xe += 512;	/* x = x * 2**512 */
+		scalx -= 256;
+	}
+
+	y = x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+
+	/* magic initial approximation to almost 8 sig. bits */
+	yh = y.bits >> 32;
+	yh = (yh >> 1) + 0x1ff80000;
+	yh = yh - table[(yh >> 15) & 31];
+	y.bits = ((unsigned long long) yh << 32) | (y.bits & 0xffffffff);
+
+	/* Heron's rule once with correction to improve to ~18 sig. bits */
+	/* t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; */
+	t = ieee754dp_div(x, y);
+	y = ieee754dp_add(y, t);
+	y.bits -= 0x0010000600000000LL;
+	y.bits &= 0xffffffff00000000LL;
+
+	/* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */
+	/* t=y*y; z=t;  pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */
+	z = t = ieee754dp_mul(y, y);
+	t.parts.bexp += 0x001;
+	t = ieee754dp_add(t, z);
+	z = ieee754dp_mul(ieee754dp_sub(x, z), y);
+
+	/* t=z/(t+x) ;  pt[n0]+=0x00100000; y+=t; */
+	t = ieee754dp_div(z, ieee754dp_add(t, x));
+	t.parts.bexp += 0x001;
+	y = ieee754dp_add(y, t);
+
+	/* twiddle last bit to force y correctly rounded */
+
+	/* set RZ, clear INEX flag */
+	ieee754_csr.rm = IEEE754_RZ;
+	ieee754_csr.sx &= ~IEEE754_INEXACT;
+
+	/* t=x/y; ...chopped quotient, possibly inexact */
+	t = ieee754dp_div(x, y);
+
+	if (ieee754_csr.sx & IEEE754_INEXACT || t.bits != y.bits) {
+
+		if (!(ieee754_csr.sx & IEEE754_INEXACT))
+			/* t = t-ulp */
+			t.bits -= 1;
+
+		/* add inexact to result status */
+		oldcsr.cx |= IEEE754_INEXACT;
+		oldcsr.sx |= IEEE754_INEXACT;
+
+		switch (oldcsr.rm) {
+		case IEEE754_RP:
+			y.bits += 1;
+			/* drop through */
+		case IEEE754_RN:
+			t.bits += 1;
+			break;
+		}
+
+		/* y=y+t; ...chopped sum */
+		y = ieee754dp_add(y, t);
+
+		/* adjust scalx for correctly rounded sqrt(x) */
+		scalx -= 1;
+	}
+
+	/* py[n0]=py[n0]+scalx; ...scale back y */
+	y.parts.bexp += scalx;
+
+	/* restore rounding mode, possibly set inexact */
+	ieee754_csr = oldcsr;
+
+	return y;
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_sub.c linux/arch/mips/math-emu/dp_sub.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_sub.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_sub.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,193 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
+{
+	COMPXDP;
+	COMPYDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+	EXPLODEYDP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "sub", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y, "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754dp_nanxcpt(x, "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754dp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Inifity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		if (xs != ys)
+			return x;
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+		return ieee754dp_inf(ys ^ 1);
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return x;
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		if (xs != ys)
+			return x;
+		else
+			return ieee754dp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return x;
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		/* quick fix up */
+		DPSIGN(y) ^= 1;
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		DPDNORMX;
+		/* FAAL THOROUGH */
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		/* normalize ym,ye */
+		DPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		/* normalize xm,xe */
+		DPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	/* flip sign of y and handle as add */
+	ys ^= 1;
+
+	assert(xm & DP_HIDDEN_BIT);
+	assert(ym & DP_HIDDEN_BIT);
+
+
+	/* provide guard,round and stick bit dpace */
+	xm <<= 3;
+	ym <<= 3;
+
+	if (xe > ye) {
+		/* have to shift y fraction right to align
+		 */
+		int s = xe - ye;
+		ym = XDPSRS(ym, s);
+		ye += s;
+	} else if (ye > xe) {
+		/* have to shift x fraction right to align
+		 */
+		int s = ye - xe;
+		xm = XDPSRS(xm, s);
+		xe += s;
+	}
+	assert(xe == ye);
+	assert(xe <= DP_EMAX);
+
+	if (xs == ys) {
+		/* generate 28 bit result of adding two 27 bit numbers
+		 */
+		xm = xm + ym;
+		xe = xe;
+		xs = xs;
+
+		if (xm >> (DP_MBITS + 1 + 3)) {	/* carry out */
+			xm = XDPSRS1(xm);	/* shift preserving sticky */
+			xe++;
+		}
+	} else {
+		if (xm >= ym) {
+			xm = xm - ym;
+			xe = xe;
+			xs = xs;
+		} else {
+			xm = ym - xm;
+			xe = xe;
+			xs = ys;
+		}
+		if (xm == 0)
+			if (ieee754_csr.rm == IEEE754_RD)
+				return ieee754dp_zero(1);	/* round negative inf. => sign = -1 */
+			else
+				return ieee754dp_zero(0);	/* other round modes   => sign = 1 */
+
+		/* normalize to rounding precision 
+		 */
+		while ((xm >> (DP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	DPNORMRET2(xs, xe, xm, "sub", x, y);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_tint.c linux/arch/mips/math-emu/dp_tint.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_tint.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_tint.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,88 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <linux/kernel.h>
+#include "ieee754dp.h"
+
+int ieee754dp_tint(ieee754dp x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754si_xcpt(ieee754si_indef(), "fixdp", x);
+	case IEEE754_CLASS_INF:
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754si_xcpt(ieee754si_indef(), "fixdp", x);
+	case IEEE754_CLASS_ZERO:
+		return 0;
+	case IEEE754_CLASS_DNORM:	/* much to small */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754si_xcpt(0, "fixdp", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe >= 31) {
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754si_xcpt(ieee754si_indef(), "fix", x);
+	}
+	if (xe < 0) {
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754si_xcpt(0, "fix", x);
+	}
+	/* oh gawd */
+	if (xe > DP_MBITS) {
+		xm <<= xe - DP_MBITS;
+	} else if (xe < DP_MBITS) {
+		/* XXX no rounding 
+		 */
+		xm >>= DP_MBITS - xe;
+	}
+	if (xs)
+		return -xm;
+	else
+		return xm;
+}
+
+
+unsigned int ieee754dp_tuns(ieee754dp x)
+{
+	ieee754dp hb = ieee754dp_1e31();
+
+	/* what if x < 0 ?? */
+	if (ieee754dp_lt(x, hb))
+		return (unsigned) ieee754dp_tint(x);
+
+	return (unsigned) ieee754dp_tint(ieee754dp_sub(x, hb)) |
+	    ((unsigned) 1 << 31);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/dp_tlong.c linux/arch/mips/math-emu/dp_tlong.c
--- linux-2.4.4-pre3/arch/mips/math-emu/dp_tlong.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/dp_tlong.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,141 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+long long ieee754dp_tlong(ieee754dp x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+	case IEEE754_CLASS_INF:
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+	case IEEE754_CLASS_ZERO:
+		return 0;
+	case IEEE754_CLASS_DNORM:	/* much too small */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754di_xcpt(0, "dp_tlong", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe >= 63) {
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+	}
+	if (xe < 0) {
+		if (ieee754_csr.rm == IEEE754_RU) {
+			if (xs) {	/* Negative  */
+				return 0x0000000000000000LL;
+			} else {	/* Positive */
+				return 0x0000000000000001LL;
+			}
+		} else if (ieee754_csr.rm == IEEE754_RD) {
+			if (xs) {	/* Negative , return -1 */
+				return 0xffffffffffffffffLL;
+			} else {	/* Positive */
+				return 0x0000000000000000LL;
+			}
+		} else {
+			SETCX(IEEE754_UNDERFLOW);
+			return ieee754di_xcpt(0, "dp_tlong", x);
+		}
+	}
+	/* oh gawd */
+	if (xe > DP_MBITS) {
+		xm <<= xe - DP_MBITS;
+	} else if (xe < DP_MBITS) {
+		unsigned long long residue;
+		unsigned long long mask = 0;
+		int i;
+		int round;
+		int sticky;
+		int odd;
+
+		/* compute mask */
+		for (i = 0; i < DP_MBITS - xe; i++) {
+			mask = mask << 1;
+			mask = mask | 0x1;
+		}
+		residue = (xm & mask) << (64 - (DP_MBITS - xe));
+		round =
+		    ((0x8000000000000000LL & residue) !=
+		     0x0000000000000000LL);
+		sticky =
+		    ((0x7fffffffffffffffLL & residue) !=
+		     0x0000000000000000LL);
+
+		xm >>= DP_MBITS - xe;
+
+		odd = ((xm & 0x1) != 0x0000000000000000LL);
+
+		/* Do the rounding */
+		if (!round && sticky) {
+			if ((ieee754_csr.rm == IEEE754_RU && !xs)
+			    || (ieee754_csr.rm == IEEE754_RD && xs)) {
+				xm++;
+			}
+		} else if (round && !sticky) {
+			if ((ieee754_csr.rm == IEEE754_RU && !xs)
+			    || (ieee754_csr.rm == IEEE754_RD && xs)
+			    || (ieee754_csr.rm == IEEE754_RN && odd)) {
+				xm++;
+			}
+		} else if (round && sticky) {
+			if ((ieee754_csr.rm == IEEE754_RU && !xs)
+			    || (ieee754_csr.rm == IEEE754_RD && xs)
+			    || (ieee754_csr.rm == IEEE754_RN)) {
+				xm++;
+			}
+		}
+	}
+	if (xs)
+		return -xm;
+	else
+		return xm;
+}
+
+
+unsigned long long ieee754dp_tulong(ieee754dp x)
+{
+	ieee754dp hb = ieee754dp_1e63();
+
+	/* what if x < 0 ?? */
+	if (ieee754dp_lt(x, hb))
+		return (unsigned long long) ieee754dp_tlong(x);
+
+	return (unsigned long long) ieee754dp_tlong(ieee754dp_sub(x, hb)) |
+	    (1ULL << 63);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/ieee754.c linux/arch/mips/math-emu/ieee754.c
--- linux-2.4.4-pre3/arch/mips/math-emu/ieee754.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/ieee754.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,138 @@
+/* ieee754 floating point arithmetic
+ * single and double precision
+ *
+ * BUGS
+ * not much dp done
+ * doesnt generate IEEE754_INEXACT
+ *
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+#define DP_EBIAS	1023
+#define DP_EMIN		(-1022)
+#define DP_EMAX		1023
+
+#define SP_EBIAS	127
+#define SP_EMIN		(-126)
+#define SP_EMAX		127
+
+/* indexed by class */
+const char *const ieee754_cname[] = {
+	"Normal",
+	"Zero",
+	"Denormal",
+	"Infinity",
+	"QNaN",
+	"SNaN",
+};
+
+/* the control status register 
+*/
+struct ieee754_csr ieee754_csr;
+
+/* special constants
+*/
+
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+#define SPSTR(s,b,m) {m,b,s}
+#define DPSTR(s,b,mh,ml) {ml,mh,b,s}
+#endif
+
+#ifdef __MIPSEB__
+#define SPSTR(s,b,m) {s,b,m}
+#define DPSTR(s,b,mh,ml) {s,b,mh,ml}
+#endif
+
+const struct ieee754dp_konst __ieee754dp_spcvals[] = {
+	DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0),	/* + zero   */
+	DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0),	/* - zero   */
+	DPSTR(0, DP_EBIAS, 0, 0),	/* + 1.0   */
+	DPSTR(1, DP_EBIAS, 0, 0),	/* - 1.0   */
+	DPSTR(0, 3 + DP_EBIAS, 0x40000, 0),	/* + 10.0   */
+	DPSTR(1, 3 + DP_EBIAS, 0x40000, 0),	/* - 10.0   */
+	DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0),	/* + infinity */
+	DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0),	/* - infinity */
+	DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0x40000, 0),	/* + indef quiet Nan */
+	DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF),	/* + max */
+	DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF),	/* - max */
+	DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0),	/* + min normal */
+	DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0),	/* - min normal */
+	DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1),	/* + min denormal */
+	DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1),	/* - min denormal */
+	DPSTR(0, 31 + DP_EBIAS, 0, 0),	/* + 1.0e31 */
+	DPSTR(0, 63 + DP_EBIAS, 0, 0),	/* + 1.0e63 */
+};
+
+const struct ieee754sp_konst __ieee754sp_spcvals[] = {
+	SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0),	/* + zero   */
+	SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0),	/* - zero   */
+	SPSTR(0, SP_EBIAS, 0),	/* + 1.0   */
+	SPSTR(1, SP_EBIAS, 0),	/* - 1.0   */
+	SPSTR(0, 3 + SP_EBIAS, 0x200000),	/* + 10.0   */
+	SPSTR(1, 3 + SP_EBIAS, 0x200000),	/* - 10.0   */
+	SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0),	/* + infinity */
+	SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0),	/* - infinity */
+	SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0x200000),	/* + indef quiet Nan  */
+	SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF),	/* + max normal */
+	SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF),	/* - max normal */
+	SPSTR(0, SP_EMIN + SP_EBIAS, 0),	/* + min normal */
+	SPSTR(1, SP_EMIN + SP_EBIAS, 0),	/* - min normal */
+	SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1),	/* + min denormal */
+	SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1),	/* - min denormal */
+	SPSTR(0, 31 + SP_EBIAS, 0),	/* + 1.0e31 */
+	SPSTR(0, 63 + SP_EBIAS, 0),	/* + 1.0e63 */
+};
+
+
+int ieee754si_xcpt(int r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	if (!TSTX())
+		return r;
+	ax.op = op;
+	ax.rt = IEEE754_RT_SI;
+	ax.rv.si = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.si;
+}
+
+long long ieee754di_xcpt(long long r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	if (!TSTX())
+		return r;
+	ax.op = op;
+	ax.rt = IEEE754_RT_DI;
+	ax.rv.di = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.di;
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/ieee754.h linux/arch/mips/math-emu/ieee754.h
--- linux-2.4.4-pre3/arch/mips/math-emu/ieee754.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/ieee754.h	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,490 @@
+/* single and double precision fp ops
+ * missing extended precision.
+*/
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Modification to allow integration with Linux kernel 
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#ifdef __KERNEL__
+/* Going from Algorithmics to Linux native environment, add this */
+#include <linux/types.h>
+
+/* 
+ * Not very pretty, but the Linux kernel's normal va_list definition 
+ * does not allow it to be used as a structure element, as it is here.
+ */
+#ifndef _STDARG_H
+#include <stdarg.h>
+#endif
+
+#else
+
+/* Note that __KERNEL__ is taken to mean Linux kernel */
+
+#if #system(OpenBSD)
+#include <machine/types.h>
+#endif
+#include <machine/endian.h>
+
+#endif				/* __KERNEL__ */
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+struct ieee754dp_konst {
+	unsigned mantlo:32;
+	unsigned manthi:20;
+	unsigned bexp:11;
+	unsigned sign:1;
+};
+struct ieee754sp_konst {
+	unsigned mant:23;
+	unsigned bexp:8;
+	unsigned sign:1;
+};
+
+typedef union _ieee754dp {
+	struct ieee754dp_konst oparts;
+	struct {
+		unsigned long long mant:52;
+		unsigned int bexp:11;
+		unsigned int sign:1;
+	} parts;
+	unsigned long long bits;
+	double d;
+} ieee754dp;
+
+typedef union _ieee754sp {
+	struct ieee754sp_konst parts;
+	float f;
+	unsigned long bits;
+} ieee754sp;
+#endif
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+struct ieee754dp_konst {
+	unsigned sign:1;
+	unsigned bexp:11;
+	unsigned manthi:20;
+	unsigned mantlo:32;
+};
+typedef union _ieee754dp {
+	struct ieee754dp_konst oparts;
+	struct {
+		unsigned int sign:1;
+		unsigned int bexp:11;
+		unsigned long long mant:52;
+	} parts;
+	double d;
+	unsigned long long bits;
+} ieee754dp;
+
+struct ieee754sp_konst {
+	unsigned sign:1;
+	unsigned bexp:8;
+	unsigned mant:23;
+};
+
+typedef union _ieee754sp {
+	struct ieee754sp_konst parts;
+	float f;
+	unsigned long bits;
+} ieee754sp;
+#endif
+
+/*
+ * single precision (often aka float)
+*/
+int ieee754sp_finite(ieee754sp x);
+int ieee754sp_class(ieee754sp x);
+
+ieee754sp ieee754sp_abs(ieee754sp x);
+ieee754sp ieee754sp_neg(ieee754sp x);
+ieee754sp ieee754sp_scalb(ieee754sp x, int);
+ieee754sp ieee754sp_logb(ieee754sp x);
+
+/* x with sign of y */
+ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y);
+
+ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y);
+
+ieee754sp ieee754sp_fint(int x);
+ieee754sp ieee754sp_funs(unsigned x);
+ieee754sp ieee754sp_flong(long long x);
+ieee754sp ieee754sp_fulong(unsigned long long x);
+ieee754sp ieee754sp_fdp(ieee754dp x);
+
+int ieee754sp_tint(ieee754sp x);
+unsigned int ieee754sp_tuns(ieee754sp x);
+long long ieee754sp_tlong(ieee754sp x);
+unsigned long long ieee754sp_tulong(ieee754sp x);
+
+int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop);
+/*
+ * basic sp math
+ */
+ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip);
+ieee754sp ieee754sp_frexp(ieee754sp x, int *exp);
+ieee754sp ieee754sp_ldexp(ieee754sp x, int exp);
+
+ieee754sp ieee754sp_ceil(ieee754sp x);
+ieee754sp ieee754sp_floor(ieee754sp x);
+ieee754sp ieee754sp_trunc(ieee754sp x);
+
+ieee754sp ieee754sp_sqrt(ieee754sp x);
+
+/*
+ * double precision (often aka double)
+*/
+int ieee754dp_finite(ieee754dp x);
+int ieee754dp_class(ieee754dp x);
+
+/* x with sign of y */
+ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y);
+
+ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y);
+
+ieee754dp ieee754dp_abs(ieee754dp x);
+ieee754dp ieee754dp_neg(ieee754dp x);
+ieee754dp ieee754dp_scalb(ieee754dp x, int);
+
+/* return exponent as integer in floating point format 
+ */
+ieee754dp ieee754dp_logb(ieee754dp x);
+
+ieee754dp ieee754dp_fint(int x);
+ieee754dp ieee754dp_funs(unsigned x);
+ieee754dp ieee754dp_flong(long long x);
+ieee754dp ieee754dp_fulong(unsigned long long x);
+ieee754dp ieee754dp_fsp(ieee754sp x);
+
+ieee754dp ieee754dp_ceil(ieee754dp x);
+ieee754dp ieee754dp_floor(ieee754dp x);
+ieee754dp ieee754dp_trunc(ieee754dp x);
+
+int ieee754dp_tint(ieee754dp x);
+unsigned int ieee754dp_tuns(ieee754dp x);
+long long ieee754dp_tlong(ieee754dp x);
+unsigned long long ieee754dp_tulong(ieee754dp x);
+
+int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop);
+/*
+ * basic sp math
+ */
+ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip);
+ieee754dp ieee754dp_frexp(ieee754dp x, int *exp);
+ieee754dp ieee754dp_ldexp(ieee754dp x, int exp);
+
+ieee754dp ieee754dp_ceil(ieee754dp x);
+ieee754dp ieee754dp_floor(ieee754dp x);
+ieee754dp ieee754dp_trunc(ieee754dp x);
+
+ieee754dp ieee754dp_sqrt(ieee754dp x);
+
+
+
+/* 5 types of floating point number 
+*/
+#define IEEE754_CLASS_NORM	0x00
+#define IEEE754_CLASS_ZERO	0x01
+#define IEEE754_CLASS_DNORM	0x02
+#define IEEE754_CLASS_INF	0x03
+#define IEEE754_CLASS_SNAN	0x04
+#define IEEE754_CLASS_QNAN	0x05
+extern const char *const ieee754_cname[];
+
+/* exception numbers */
+#define IEEE754_INEXACT			0x01
+#define IEEE754_UNDERFLOW		0x02
+#define IEEE754_OVERFLOW		0x04
+#define IEEE754_ZERO_DIVIDE		0x08
+#define IEEE754_INVALID_OPERATION	0x10
+
+/* cmp operators
+*/
+#define IEEE754_CLT	0x01
+#define IEEE754_CEQ	0x02
+#define IEEE754_CGT	0x04
+#define IEEE754_CUN	0x08
+
+/* rounding mode 
+*/
+#define IEEE754_RN	0	/* round to nearest */
+#define IEEE754_RZ	1	/* round toward zero  */
+#define IEEE754_RD	2	/* round toward -Infinity */
+#define IEEE754_RU	3	/* round toward +Infinity */
+
+/* other naming */
+#define IEEE754_RM	IEEE754_RD
+#define IEEE754_RP	IEEE754_RU
+
+/* "normal" comparisons
+*/
+static __inline int ieee754sp_eq(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CEQ);
+}
+
+static __inline int ieee754sp_ne(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y,
+			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN);
+}
+
+static __inline int ieee754sp_lt(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CLT);
+}
+
+static __inline int ieee754sp_le(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ);
+}
+
+static __inline int ieee754sp_gt(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CGT);
+}
+
+
+static __inline int ieee754sp_ge(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_eq(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_ne(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y,
+			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN);
+}
+
+static __inline int ieee754dp_lt(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CLT);
+}
+
+static __inline int ieee754dp_le(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_gt(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CGT);
+}
+
+static __inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ);
+}
+
+
+/* like strtod
+*/
+ieee754dp ieee754dp_fstr(const char *s, char **endp);
+char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af);
+
+
+/* the control status register 
+*/
+struct ieee754_csr {
+	unsigned pad:13;
+	unsigned noq:1;		/* set 1 for no quiet NaN's */
+	unsigned nod:1;		/* set 1 for no denormalised numbers */
+	unsigned cx:5;		/* exceptions this operation */
+	unsigned mx:5;		/* exception enable  mask */
+	unsigned sx:5;		/* exceptions total */
+	unsigned rm:2;		/* current rounding mode */
+};
+extern struct ieee754_csr ieee754_csr;
+
+static __inline unsigned ieee754_getrm(void)
+{
+	return (ieee754_csr.rm);
+}
+static __inline unsigned ieee754_setrm(unsigned rm)
+{
+	return (ieee754_csr.rm = rm);
+}
+
+/*
+ * get current exceptions
+ */
+static __inline unsigned ieee754_getcx(void)
+{
+	return (ieee754_csr.cx);
+}
+
+/* test for current exception condition 
+ */
+static __inline int ieee754_cxtest(unsigned n)
+{
+	return (ieee754_csr.cx & n);
+}
+
+/*
+ * get sticky exceptions
+ */
+static __inline unsigned ieee754_getsx(void)
+{
+	return (ieee754_csr.sx);
+}
+
+/* clear sticky conditions
+*/
+static __inline unsigned ieee754_clrsx(void)
+{
+	return (ieee754_csr.sx = 0);
+}
+
+/* test for sticky exception condition 
+ */
+static __inline int ieee754_sxtest(unsigned n)
+{
+	return (ieee754_csr.sx & n);
+}
+
+/* debugging */
+ieee754sp ieee754sp_dump(char *s, ieee754sp x);
+ieee754dp ieee754dp_dump(char *s, ieee754dp x);
+
+#define IEEE754_SPCVAL_PZERO	0
+#define IEEE754_SPCVAL_NZERO	1
+#define IEEE754_SPCVAL_PONE	2
+#define IEEE754_SPCVAL_NONE	3
+#define IEEE754_SPCVAL_PTEN	4
+#define IEEE754_SPCVAL_NTEN	5
+#define IEEE754_SPCVAL_PINFINITY	6
+#define IEEE754_SPCVAL_NINFINITY	7
+#define IEEE754_SPCVAL_INDEF	8
+#define IEEE754_SPCVAL_PMAX	9	/* +max norm */
+#define IEEE754_SPCVAL_NMAX	10	/* -max norm */
+#define IEEE754_SPCVAL_PMIN	11	/* +min norm */
+#define IEEE754_SPCVAL_NMIN	12	/* +min norm */
+#define IEEE754_SPCVAL_PMIND	13	/* +min denorm */
+#define IEEE754_SPCVAL_NMIND	14	/* +min denorm */
+#define IEEE754_SPCVAL_P1E31	15	/* + 1.0e31 */
+#define IEEE754_SPCVAL_P1E63	16	/* + 1.0e63 */
+
+extern const struct ieee754dp_konst __ieee754dp_spcvals[];
+extern const struct ieee754sp_konst __ieee754sp_spcvals[];
+#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals)
+#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals)
+
+/* return infinity with given sign
+*/
+#define ieee754dp_inf(sn)	\
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754dp_zero(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754dp_one(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754dp_ten(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754dp_indef() \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754dp_max(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754dp_min(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754dp_mind(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754dp_1e31() \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754dp_1e63() \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63])
+
+#define ieee754sp_inf(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754sp_zero(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754sp_one(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754sp_ten(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754sp_indef() \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754sp_max(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754sp_min(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754sp_mind(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754sp_1e31() \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754sp_1e63() \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63])
+
+/* indefinite integer value 
+*/
+#define ieee754si_indef()	INT_MIN
+#ifdef LONG_LONG_MIN
+#define ieee754di_indef()	LONG_LONG_MIN
+#else
+#define ieee754di_indef()	(-9223372036854775807LL-1)
+#endif
+
+/* IEEE exception context, passed to handler */
+struct ieee754xctx {
+	const char *op;		/* operation name */
+	int rt;			/* result type */
+	union {
+		ieee754sp sp;	/* single precision */
+		ieee754dp dp;	/* double precision */
+#ifdef IEEE854_XP
+		ieee754xp xp;	/* extended precision */
+#endif
+		int si;		/* standard signed integer (32bits) */
+		long long di;	/* extended signed integer (64bits) */
+	} rv;			/* default result format implied by op */
+	va_list ap;
+};
+
+/* result types for xctx.rt */
+#define IEEE754_RT_SP	0
+#define IEEE754_RT_DP	1
+#define IEEE754_RT_XP	2
+#define IEEE754_RT_SI	3
+#define IEEE754_RT_DI	4
+
+extern void ieee754_xcpt(struct ieee754xctx *xcp);
+
+/* compat */
+#define ieee754dp_fix(x)	ieee754dp_tint(x)
+#define ieee754sp_fix(x)	ieee754sp_tint(x)
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/ieee754d.c linux/arch/mips/math-emu/ieee754d.c
--- linux-2.4.4-pre3/arch/mips/math-emu/ieee754d.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/ieee754d.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,142 @@
+/* some debug functions
+*/
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Modified to build and operate in Linux kernel environment. 
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#include "ieee754.h"
+
+#define DP_EBIAS	1023
+#define DP_EMIN		(-1022)
+#define DP_EMAX		1023
+#define DP_FBITS	52
+
+#define SP_EBIAS	127
+#define SP_EMIN		(-126)
+#define SP_EMAX		127
+#define SP_FBITS	23
+
+#define DP_MBIT(x)	((unsigned long long)1 << (x))
+#define DP_HIDDEN_BIT	DP_MBIT(DP_FBITS)
+#define DP_SIGN_BIT	DP_MBIT(63)
+
+
+#define SP_MBIT(x)	((unsigned long)1 << (x))
+#define SP_HIDDEN_BIT	SP_MBIT(SP_FBITS)
+#define SP_SIGN_BIT	SP_MBIT(31)
+
+
+#define SPSIGN(sp)	(sp.parts.sign)
+#define SPBEXP(sp)	(sp.parts.bexp)
+#define SPMANT(sp)	(sp.parts.mant)
+
+#define DPSIGN(dp)	(dp.parts.sign)
+#define DPBEXP(dp)	(dp.parts.bexp)
+#define DPMANT(dp)	(dp.parts.mant)
+
+ieee754dp ieee754dp_dump(char *m, ieee754dp x)
+{
+	int i;
+
+	printk("%s", m);
+	printk("<%08x,%08x>\n", (unsigned) (x.bits >> 32),
+	       (unsigned) x.bits);
+	printk("\t=");
+	switch (ieee754dp_class(x)) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		printk("Nan %c", DPSIGN(x) ? '-' : '+');
+		for (i = DP_FBITS - 1; i >= 0; i--)
+			printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+		break;
+	case IEEE754_CLASS_INF:
+		printk("%cInfinity", DPSIGN(x) ? '-' : '+');
+		break;
+	case IEEE754_CLASS_ZERO:
+		printk("%cZero", DPSIGN(x) ? '-' : '+');
+		break;
+	case IEEE754_CLASS_DNORM:
+		printk("%c0.", DPSIGN(x) ? '-' : '+');
+		for (i = DP_FBITS - 1; i >= 0; i--)
+			printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+		printk("e%d", DPBEXP(x) - DP_EBIAS);
+		break;
+	case IEEE754_CLASS_NORM:
+		printk("%c1.", DPSIGN(x) ? '-' : '+');
+		for (i = DP_FBITS - 1; i >= 0; i--)
+			printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+		printk("e%d", DPBEXP(x) - DP_EBIAS);
+		break;
+	default:
+		printk("Illegal/Unknown IEEE754 value class");
+	}
+	printk("\n");
+	return x;
+}
+
+ieee754sp ieee754sp_dump(char *m, ieee754sp x)
+{
+	int i;
+
+	printk("%s=", m);
+	printk("<%08x>\n", (unsigned) x.bits);
+	printk("\t=");
+	switch (ieee754sp_class(x)) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		printk("Nan %c", SPSIGN(x) ? '-' : '+');
+		for (i = SP_FBITS - 1; i >= 0; i--)
+			printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+		break;
+	case IEEE754_CLASS_INF:
+		printk("%cInfinity", SPSIGN(x) ? '-' : '+');
+		break;
+	case IEEE754_CLASS_ZERO:
+		printk("%cZero", SPSIGN(x) ? '-' : '+');
+		break;
+	case IEEE754_CLASS_DNORM:
+		printk("%c0.", SPSIGN(x) ? '-' : '+');
+		for (i = SP_FBITS - 1; i >= 0; i--)
+			printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+		printk("e%d", SPBEXP(x) - SP_EBIAS);
+		break;
+	case IEEE754_CLASS_NORM:
+		printk("%c1.", SPSIGN(x) ? '-' : '+');
+		for (i = SP_FBITS - 1; i >= 0; i--)
+			printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+		printk("e%d", SPBEXP(x) - SP_EBIAS);
+		break;
+	default:
+		printk("Illegal/Unknown IEEE754 value class");
+	}
+	printk("\n");
+	return x;
+}
+
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/ieee754dp.c linux/arch/mips/math-emu/ieee754dp.c
--- linux-2.4.4-pre3/arch/mips/math-emu/ieee754dp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/ieee754dp.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,197 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+int ieee754dp_class(ieee754dp x)
+{
+	COMPXDP;
+	EXPLODEXDP;
+	return xc;
+}
+
+int ieee754dp_isnan(ieee754dp x)
+{
+	return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;
+}
+
+int ieee754dp_issnan(ieee754dp x)
+{
+	assert(ieee754dp_isnan(x));
+	if (ieee754_csr.noq)
+		return 1;
+	return !(DPMANT(x) & DP_MBIT(DP_MBITS - 1));
+}
+
+
+ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+	if (!TSTX())
+		return r;
+
+	ax.op = op;
+	ax.rt = IEEE754_RT_DP;
+	ax.rv.dp = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.dp;
+}
+
+ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	assert(ieee754dp_isnan(r));
+
+	if (!ieee754dp_issnan(r))	/* QNAN does not cause invalid op !! */
+		return r;
+
+	if (!SETCX(IEEE754_INVALID_OPERATION)) {
+		/* not enabled convert to a quiet NaN */
+		if (ieee754_csr.noq)
+			return r;
+		DPMANT(r) |= DP_MBIT(DP_MBITS - 1);
+		return r;
+	}
+
+	ax.op = op;
+	ax.rt = 0;
+	ax.rv.dp = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.dp;
+}
+
+ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y)
+{
+	assert(ieee754dp_isnan(x));
+	assert(ieee754dp_isnan(y));
+
+	if (DPMANT(x) > DPMANT(y))
+		return x;
+	else
+		return y;
+}
+
+
+/* generate a normal/denormal number with over,under handeling
+ * sn is sign
+ * xe is an unbiased exponent
+ * xm is 3bit extended precision value.
+ */
+ieee754dp ieee754dp_format(int sn, int xe, unsigned long long xm)
+{
+	assert(xm);		/* we dont gen exact zeros (probably should) */
+
+	assert((xm >> (DP_MBITS + 1 + 3)) == 0);	/* no execess */
+	assert(xm & (DP_HIDDEN_BIT << 3));
+
+	if (xe < DP_EMIN) {
+		/* strip lower bits */
+		int es = DP_EMIN - xe;
+
+		if (ieee754_csr.nod) {
+			SETCX(IEEE754_UNDERFLOW);
+			return ieee754dp_zero(sn);
+		}
+
+		/* sticky right shift es bits 
+		 */
+		xm = XDPSRS(xm, es);
+		xe += es;
+
+		assert((xm & (DP_HIDDEN_BIT << 3)) == 0);
+		assert(xe == DP_EMIN);
+	}
+	if (xm & (DP_MBIT(3) - 1)) {
+		SETCX(IEEE754_INEXACT);
+		/* inexact must round of 3 bits 
+		 */
+		switch (ieee754_csr.rm) {
+		case IEEE754_RZ:
+			break;
+		case IEEE754_RN:
+			xm += 0x3 + ((xm >> 3) & 1);
+			/* xm += (xm&0x8)?0x4:0x3 */
+			break;
+		case IEEE754_RU:	/* toward +Infinity */
+			if (!sn)	/* ?? */
+				xm += 0x8;
+			break;
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn)	/* ?? */
+				xm += 0x8;
+			break;
+		}
+		/* adjust exponent for rounding add overflowing 
+		 */
+		if (xm >> (DP_MBITS + 3 + 1)) {	/* add causes mantissa overflow */
+			xm >>= 1;
+			xe++;
+		}
+	}
+	/* strip grs bits */
+	xm >>= 3;
+
+	assert((xm >> (DP_MBITS + 1)) == 0);	/* no execess */
+	assert(xe >= DP_EMIN);
+
+	if (xe > DP_EMAX) {
+		SETCX(IEEE754_OVERFLOW);
+		/* -O can be table indexed by (rm,sn) */
+		switch (ieee754_csr.rm) {
+		case IEEE754_RN:
+			return ieee754dp_inf(sn);
+		case IEEE754_RZ:
+			return ieee754dp_max(sn);
+		case IEEE754_RU:	/* toward +Infinity */
+			if (sn == 0)
+				return ieee754dp_inf(0);
+			else
+				return ieee754dp_max(1);
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn == 0)
+				return ieee754dp_max(0);
+			else
+				return ieee754dp_inf(1);
+		}
+	}
+	/* gen norm/denorm/zero */
+
+	if ((xm & DP_HIDDEN_BIT) == 0) {
+		/* we underflow (tiny/zero) */
+		assert(xe == DP_EMIN);
+		SETCX(IEEE754_UNDERFLOW);
+		return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);
+	} else {
+		assert((xm >> (DP_MBITS + 1)) == 0);	/* no execess */
+		assert(xm & DP_HIDDEN_BIT);
+
+		return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+	}
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/ieee754dp.h linux/arch/mips/math-emu/ieee754dp.h
--- linux-2.4.4-pre3/arch/mips/math-emu/ieee754dp.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/ieee754dp.h	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,83 @@
+/* 
+ * IEEE754 floating point
+ * double precision internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+#define assert(expr) ((void)0)
+
+/* 3bit extended double precision sticky right shift */
+#define XDPSRS(v,rs)	\
+  ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))
+
+#define XDPSRSX1() \
+  (xe++, (xm = (xm >> 1) | (xm & 1)))
+
+#define XDPSRS1(v)	\
+  (((v) >> 1) | ((v) & 1))
+
+/* convert denormal to normalized with extended exponent */
+#define DPDNORMx(m,e) \
+  while( (m >> DP_MBITS) == 0) { m <<= 1; e--; }
+#define DPDNORMX	DPDNORMx(xm,xe)
+#define DPDNORMY	DPDNORMx(ym,ye)
+
+static __inline ieee754dp builddp(int s, int bx, unsigned long long m)
+{
+	ieee754dp r;
+
+	assert((s) == 0 || (s) == 1);
+	assert((bx) >= DP_EMIN - 1 + DP_EBIAS
+	       && (bx) <= DP_EMAX + 1 + DP_EBIAS);
+	assert(((m) >> DP_MBITS) == 0);
+
+	r.parts.sign = s;
+	r.parts.bexp = bx;
+	r.parts.mant = m;
+	return r;
+}
+
+extern int ieee754dp_isnan(ieee754dp);
+extern int ieee754dp_issnan(ieee754dp);
+extern int ieee754si_xcpt(int, const char *, ...);
+extern long long ieee754di_xcpt(long long, const char *, ...);
+extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...);
+extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...);
+extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp);
+extern ieee754dp ieee754dp_format(int, int, unsigned long long);
+
+
+#define DPNORMRET2(s,e,m,name,a0,a1) \
+{ \
+    ieee754dp V = ieee754dp_format(s,e,m); \
+    if(TSTX()) \
+      return ieee754dp_xcpt(V,name,a0,a1); \
+    else \
+      return V; \
+}
+
+#define DPNORMRET1(s,e,m,name,a0)  DPNORMRET2(s,e,m,name,a0,a0)
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/ieee754int.h linux/arch/mips/math-emu/ieee754int.h
--- linux-2.4.4-pre3/arch/mips/math-emu/ieee754int.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/ieee754int.h	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,135 @@
+/* 
+ * IEEE754 floating point
+ * common internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754.h"
+
+#define DP_EBIAS	1023
+#define DP_EMIN		(-1022)
+#define DP_EMAX		1023
+#define DP_MBITS	52
+
+#define SP_EBIAS	127
+#define SP_EMIN		(-126)
+#define SP_EMAX		127
+#define SP_MBITS	23
+
+#define DP_MBIT(x)	((unsigned long long)1 << (x))
+#define DP_HIDDEN_BIT	DP_MBIT(DP_MBITS)
+#define DP_SIGN_BIT	DP_MBIT(63)
+
+#define SP_MBIT(x)	((unsigned long)1 << (x))
+#define SP_HIDDEN_BIT	SP_MBIT(SP_MBITS)
+#define SP_SIGN_BIT	SP_MBIT(31)
+
+
+#define SPSIGN(sp)	(sp.parts.sign)
+#define SPBEXP(sp)	(sp.parts.bexp)
+#define SPMANT(sp)	(sp.parts.mant)
+
+#define DPSIGN(dp)	(dp.parts.sign)
+#define DPBEXP(dp)	(dp.parts.bexp)
+#define DPMANT(dp)	(dp.parts.mant)
+
+#define CLPAIR(x,y)	((x)*6+(y))
+
+#define CLEARCX	\
+  (ieee754_csr.cx = 0)
+
+#define SETCX(x) \
+  (ieee754_csr.cx |= (x),ieee754_csr.sx |= (x),ieee754_csr.mx & (x))
+
+#define TSTX()	\
+	(ieee754_csr.cx & ieee754_csr.mx)
+
+
+#define COMPXSP \
+  unsigned xm; int xe; int xs; int xc
+
+#define COMPYSP \
+  unsigned ym; int ye; int ys; int yc
+
+#define EXPLODESP(v,vc,vs,ve,vm) \
+{\
+    vs = SPSIGN(v);\
+    ve = SPBEXP(v);\
+    vm = SPMANT(v);\
+    if(ve == SP_EMAX+1+SP_EBIAS){\
+	if(vm == 0)\
+	  vc = IEEE754_CLASS_INF;\
+	else if(vm & SP_MBIT(SP_MBITS-1)) \
+	  vc = IEEE754_CLASS_QNAN;\
+	else \
+	  vc = IEEE754_CLASS_SNAN;\
+    } else if(ve == SP_EMIN-1+SP_EBIAS) {\
+	if(vm) {\
+	    ve = SP_EMIN;\
+	    vc = IEEE754_CLASS_DNORM;\
+	} else\
+	  vc = IEEE754_CLASS_ZERO;\
+    } else {\
+	ve -= SP_EBIAS;\
+	vm |= SP_HIDDEN_BIT;\
+	vc = IEEE754_CLASS_NORM;\
+    }\
+}
+#define EXPLODEXSP EXPLODESP(x,xc,xs,xe,xm)
+#define EXPLODEYSP EXPLODESP(y,yc,ys,ye,ym)
+
+
+#define COMPXDP \
+unsigned long long xm; int xe; int xs; int xc
+
+#define COMPYDP \
+unsigned long long ym; int ye; int ys; int yc
+
+#define EXPLODEDP(v,vc,vs,ve,vm) \
+{\
+    vm = DPMANT(v);\
+    vs = DPSIGN(v);\
+    ve = DPBEXP(v);\
+    if(ve == DP_EMAX+1+DP_EBIAS){\
+	if(vm == 0)\
+	  vc = IEEE754_CLASS_INF;\
+	else if(vm & DP_MBIT(DP_MBITS-1)) \
+	  vc = IEEE754_CLASS_QNAN;\
+	else \
+	  vc = IEEE754_CLASS_SNAN;\
+    } else if(ve == DP_EMIN-1+DP_EBIAS) {\
+	if(vm) {\
+	    ve = DP_EMIN;\
+	    vc = IEEE754_CLASS_DNORM;\
+	} else\
+	  vc = IEEE754_CLASS_ZERO;\
+    } else {\
+	ve -= DP_EBIAS;\
+	vm |= DP_HIDDEN_BIT;\
+	vc = IEEE754_CLASS_NORM;\
+    }\
+}
+#define EXPLODEXDP EXPLODEDP(x,xc,xs,xe,xm)
+#define EXPLODEYDP EXPLODEDP(y,yc,ys,ye,ym)
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/ieee754m.c linux/arch/mips/math-emu/ieee754m.c
--- linux-2.4.4-pre3/arch/mips/math-emu/ieee754m.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/ieee754m.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,56 @@
+/*
+ * floor, trunc, ceil
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754.h"
+
+ieee754dp ieee754dp_floor(ieee754dp x)
+{
+	ieee754dp i;
+
+	if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
+		return ieee754dp_sub(i, ieee754dp_one(0));
+	else
+		return i;
+}
+
+ieee754dp ieee754dp_ceil(ieee754dp x)
+{
+	ieee754dp i;
+
+	if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
+		return ieee754dp_add(i, ieee754dp_one(0));
+	else
+		return i;
+}
+
+ieee754dp ieee754dp_trunc(ieee754dp x)
+{
+	ieee754dp i;
+
+	(void) ieee754dp_modf(x, &i);
+	return i;
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/ieee754sp.c linux/arch/mips/math-emu/ieee754sp.c
--- linux-2.4.4-pre3/arch/mips/math-emu/ieee754sp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/ieee754sp.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,197 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+int ieee754sp_class(ieee754sp x)
+{
+	COMPXSP;
+	EXPLODEXSP;
+	return xc;
+}
+
+int ieee754sp_isnan(ieee754sp x)
+{
+	return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;
+}
+
+int ieee754sp_issnan(ieee754sp x)
+{
+	assert(ieee754sp_isnan(x));
+	if (ieee754_csr.noq)
+		return 1;
+	return !(SPMANT(x) & SP_MBIT(SP_MBITS - 1));
+}
+
+
+ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	if (!TSTX())
+		return r;
+
+	ax.op = op;
+	ax.rt = IEEE754_RT_SP;
+	ax.rv.sp = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.sp;
+}
+
+ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	assert(ieee754sp_isnan(r));
+
+	if (!ieee754sp_issnan(r))	/* QNAN does not cause invalid op !! */
+		return r;
+
+	if (!SETCX(IEEE754_INVALID_OPERATION)) {
+		/* not enabled convert to a quiet NaN */
+		if (ieee754_csr.noq)
+			return r;
+		SPMANT(r) |= SP_MBIT(SP_MBITS - 1);
+		return r;
+	}
+
+	ax.op = op;
+	ax.rt = 0;
+	ax.rv.sp = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.sp;
+}
+
+ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y)
+{
+	assert(ieee754sp_isnan(x));
+	assert(ieee754sp_isnan(y));
+
+	if (SPMANT(x) > SPMANT(y))
+		return x;
+	else
+		return y;
+}
+
+
+/* generate a normal/denormal number with over,under handeling
+ * sn is sign
+ * xe is an unbiased exponent
+ * xm is 3bit extended precision value.
+ */
+ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
+{
+	assert(xm);		/* we dont gen exact zeros (probably should) */
+
+	assert((xm >> (SP_MBITS + 1 + 3)) == 0);	/* no execess */
+	assert(xm & (SP_HIDDEN_BIT << 3));
+
+	if (xe < SP_EMIN) {
+		/* strip lower bits */
+		int es = SP_EMIN - xe;
+
+		if (ieee754_csr.nod) {
+			SETCX(IEEE754_UNDERFLOW);
+			return ieee754sp_zero(sn);
+		}
+
+		/* sticky right shift es bits 
+		 */
+		SPXSRSXn(es);
+
+		assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
+		assert(xe == SP_EMIN);
+	}
+	if (xm & (SP_MBIT(3) - 1)) {
+		SETCX(IEEE754_INEXACT);
+		/* inexact must round of 3 bits 
+		 */
+		switch (ieee754_csr.rm) {
+		case IEEE754_RZ:
+			break;
+		case IEEE754_RN:
+			xm += 0x3 + ((xm >> 3) & 1);
+			/* xm += (xm&0x8)?0x4:0x3 */
+			break;
+		case IEEE754_RU:	/* toward +Infinity */
+			if (!sn)	/* ?? */
+				xm += 0x8;
+			break;
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn)	/* ?? */
+				xm += 0x8;
+			break;
+		}
+		/* adjust exponent for rounding add overflowing 
+		 */
+		if (xm >> (SP_MBITS + 1 + 3)) {	/* add causes mantissa overflow */
+			xm >>= 1;
+			xe++;
+		}
+	}
+	/* strip grs bits */
+	xm >>= 3;
+
+	assert((xm >> (SP_MBITS + 1)) == 0);	/* no execess */
+	assert(xe >= SP_EMIN);
+
+	if (xe > SP_EMAX) {
+		SETCX(IEEE754_OVERFLOW);
+		/* -O can be table indexed by (rm,sn) */
+		switch (ieee754_csr.rm) {
+		case IEEE754_RN:
+			return ieee754sp_inf(sn);
+		case IEEE754_RZ:
+			return ieee754sp_max(sn);
+		case IEEE754_RU:	/* toward +Infinity */
+			if (sn == 0)
+				return ieee754sp_inf(0);
+			else
+				return ieee754sp_max(1);
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn == 0)
+				return ieee754sp_max(0);
+			else
+				return ieee754sp_inf(1);
+		}
+	}
+	/* gen norm/denorm/zero */
+
+	if ((xm & SP_HIDDEN_BIT) == 0) {
+		/* we underflow (tiny/zero) */
+		assert(xe == SP_EMIN);
+		SETCX(IEEE754_UNDERFLOW);
+		return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
+	} else {
+		assert((xm >> (SP_MBITS + 1)) == 0);	/* no execess */
+		assert(xm & SP_HIDDEN_BIT);
+
+		return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+	}
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/ieee754sp.h linux/arch/mips/math-emu/ieee754sp.h
--- linux-2.4.4-pre3/arch/mips/math-emu/ieee754sp.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/ieee754sp.h	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,89 @@
+/* 
+ * IEEE754 floating point
+ * double precision internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+#define assert(expr) ((void)0)
+
+/* 3bit extended single precision sticky right shift */
+#define SPXSRSXn(rs) \
+  (xe += rs, \
+   xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
+
+#define SPXSRSX1() \
+  (xe++, (xm = (xm >> 1) | (xm & 1)))
+
+#define SPXSRSYn(rs) \
+   (ye+=rs, \
+    ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
+
+#define SPXSRSY1() \
+   (ye++, (ym = (ym >> 1) | (ym & 1)))
+
+/* convert denormal to normalized with extended exponent */
+#define SPDNORMx(m,e) \
+  while( (m >> SP_MBITS) == 0) { m <<= 1; e--; }
+#define SPDNORMX	SPDNORMx(xm,xe)
+#define SPDNORMY	SPDNORMx(ym,ye)
+
+static __inline ieee754sp buildsp(int s, int bx, unsigned m)
+{
+	ieee754sp r;
+
+	assert((s) == 0 || (s) == 1);
+	assert((bx) >= SP_EMIN - 1 + SP_EBIAS
+	       && (bx) <= SP_EMAX + 1 + SP_EBIAS);
+	assert(((m) >> SP_MBITS) == 0);
+
+	r.parts.sign = s;
+	r.parts.bexp = bx;
+	r.parts.mant = m;
+
+	return r;
+}
+
+extern int ieee754sp_isnan(ieee754sp);
+extern int ieee754sp_issnan(ieee754sp);
+extern int ieee754si_xcpt(int, const char *, ...);
+extern long long ieee754di_xcpt(long long, const char *, ...);
+extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...);
+extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...);
+extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp);
+extern ieee754sp ieee754sp_format(int, int, unsigned);
+
+
+#define SPNORMRET2(s,e,m,name,a0,a1) \
+{ \
+    ieee754sp V = ieee754sp_format(s,e,m); \
+    if(TSTX()) \
+      return ieee754sp_xcpt(V,name,a0,a1); \
+    else \
+      return V; \
+}
+
+#define SPNORMRET1(s,e,m,name,a0)  SPNORMRET2(s,e,m,name,a0,a0)
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/ieee754xcpt.c linux/arch/mips/math-emu/ieee754xcpt.c
--- linux-2.4.4-pre3/arch/mips/math-emu/ieee754xcpt.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/ieee754xcpt.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,48 @@
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Added preprocessor hacks to map to Linux kernel diagnostics. 
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *************************************************************************/
+
+#include "ieee754.h"
+
+/*
+ * Very naff exception handler (you can plug in your own and
+ * override this).
+ */
+
+static const char *const rtnames[] = {
+	"sp", "dp", "xp", "si", "di"
+};
+
+void ieee754_xcpt(struct ieee754xctx *xcp)
+{
+	printk("floating point exception in \"%s\", type=%s\n",
+		xcp->op, rtnames[xcp->rt]);
+}
+
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/kernel_linkage.c linux/arch/mips/math-emu/kernel_linkage.c
--- linux-2.4.4-pre3/arch/mips/math-emu/kernel_linkage.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/kernel_linkage.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,95 @@
+/**************************************************************************
+ *
+ *  arch/mips/math_emu/kernel_linkage.c
+ *
+ *  Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ *************************************************************************/
+/*
+ * Routines corresponding to Linux kernel FP context
+ * manipulation primitives for the Algorithmics MIPS
+ * FPU Emulator
+ */
+
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/signal.h>
+#include <asm/uaccess.h>
+
+#include <asm/fpu_emulator.h>
+
+extern struct mips_fpu_emulator_private fpuemuprivate;
+
+#define SIGNALLING_NAN 0x7ff800007ff80000LL
+
+void fpu_emulator_init_fpu(void)
+{
+	static int first = 1;
+	int i;
+ 
+	if (first) {
+		first = 0;
+		printk("Algorithmics/MIPS FPU Emulator v1.4\n");
+	}
+
+	current->thread.fpu.soft.sr = 0;
+	for (i = 0; i < 32; i++) {
+		current->thread.fpu.soft.regs[i] = SIGNALLING_NAN;
+	}
+}
+
+
+/*
+ * Emulator context save/restore to/from a signal context
+ * presumed to be on the user stack, and therefore accessed
+ * with appropriate macros from uaccess.h
+ */
+
+int fpu_emulator_save_context(struct sigcontext *sc)
+{
+	int i;
+	int err = 0;
+
+	for (i = 0; i < 32; i++) {
+		err |=
+		    __put_user(current->thread.fpu.soft.regs[i],
+			       &sc->sc_fpregs[i]);
+	}
+	err |= __put_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr);
+	err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+	return err;
+}
+
+int fpu_emulator_restore_context(struct sigcontext *sc)
+{
+	int i;
+	int err = 0;
+
+	for (i = 0; i < 32; i++) {
+		err |=
+		    __get_user(current->thread.fpu.soft.regs[i],
+			       &sc->sc_fpregs[i]);
+	}
+	err |= __get_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr);
+	err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+	return err;
+}
+
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_add.c linux/arch/mips/math-emu/sp_add.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_add.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_add.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,180 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
+{
+	COMPXSP;
+	COMPYSP;
+
+	EXPLODEXSP;
+	EXPLODEYSP;
+
+	CLEARCX;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "add", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y, "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754sp_nanxcpt(x, "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754sp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Inifity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		if (xs == ys)
+			return x;
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return x;
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		if (xs == ys)
+			return x;
+		else
+			return ieee754sp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return x;
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		SPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		SPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		SPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	assert(xm & SP_HIDDEN_BIT);
+	assert(ym & SP_HIDDEN_BIT);
+
+	/* provide guard,round and stick bit space */
+	xm <<= 3;
+	ym <<= 3;
+
+	if (xe > ye) {
+		/* have to shift y fraction right to align
+		 */
+		int s = xe - ye;
+		SPXSRSYn(s);
+	} else if (ye > xe) {
+		/* have to shift x fraction right to align
+		 */
+		int s = ye - xe;
+		SPXSRSXn(s);
+	}
+	assert(xe == ye);
+	assert(xe <= SP_EMAX);
+
+	if (xs == ys) {
+		/* generate 28 bit result of adding two 27 bit numbers
+		 * leaving result in xm,xs,xe
+		 */
+		xm = xm + ym;
+		xe = xe;
+		xs = xs;
+
+		if (xm >> (SP_MBITS + 1 + 3)) {	/* carry out */
+			SPXSRSX1();
+		}
+	} else {
+		if (xm >= ym) {
+			xm = xm - ym;
+			xe = xe;
+			xs = xs;
+		} else {
+			xm = ym - xm;
+			xe = xe;
+			xs = ys;
+		}
+		if (xm == 0)
+			return ieee754sp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+		/* normalize in extended single precision */
+		while ((xm >> (SP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+
+	}
+	SPNORMRET2(xs, xe, xm, "add", x, y);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_cmp.c linux/arch/mips/math-emu/sp_cmp.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_cmp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_cmp.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp)
+{
+	CLEARCX;
+
+	if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) {
+		if (cmp & IEEE754_CUN)
+			return 1;
+		if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
+			if (SETCX(IEEE754_INVALID_OPERATION))
+				return ieee754si_xcpt(0, "fcmpf", x);
+		}
+		return 0;
+	} else {
+		int vx = x.bits;
+		int vy = y.bits;
+
+		if (vx < 0)
+			vx = -vx ^ SP_SIGN_BIT;
+		if (vy < 0)
+			vy = -vy ^ SP_SIGN_BIT;
+
+		if (vx < vy)
+			return (cmp & IEEE754_CLT) != 0;
+		else if (vx == vy)
+			return (cmp & IEEE754_CEQ) != 0;
+		else
+			return (cmp & IEEE754_CGT) != 0;
+	}
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_div.c linux/arch/mips/math-emu/sp_div.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_div.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_div.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,160 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
+{
+	COMPXSP;
+	COMPYSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+	EXPLODEYSP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "div", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y, "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754sp_nanxcpt(x, "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754sp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Infinity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+		return ieee754sp_zero(xs ^ ys);
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return ieee754sp_inf(xs ^ ys);
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		SETCX(IEEE754_ZERO_DIVIDE);
+		return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		return ieee754sp_zero(xs == ys ? 0 : 1);
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		SPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		SPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		SPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	assert(xm & SP_HIDDEN_BIT);
+	assert(ym & SP_HIDDEN_BIT);
+
+	/* provide rounding space */
+	xm <<= 3;
+	ym <<= 3;
+
+	{
+		/* now the dirty work */
+
+		unsigned rm = 0;
+		int re = xe - ye;
+		unsigned bm;
+
+		for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) {
+			if (xm >= ym) {
+				xm -= ym;
+				rm |= bm;
+				if (xm == 0)
+					break;
+			}
+			xm <<= 1;
+		}
+		rm <<= 1;
+		if (xm)
+			rm |= 1;	/* have remainder, set sticky */
+
+		assert(rm);
+
+		/* normalise rm to rounding precision ?
+		 */
+		while ((rm >> (SP_MBITS + 3)) == 0) {
+			rm <<= 1;
+			re--;
+		}
+
+		SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+	}
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_fdp.c linux/arch/mips/math-emu/sp_fdp.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_fdp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_fdp.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,69 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_fdp(ieee754dp x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		return ieee754sp_nanxcpt(buildsp(xs,
+						 SP_EMAX + 1 + SP_EBIAS,
+						 (unsigned long)
+						 (xm >>
+						  (DP_MBITS - SP_MBITS))),
+					 "fdp", x);
+	case IEEE754_CLASS_INF:
+		return ieee754sp_inf(xs);
+	case IEEE754_CLASS_ZERO:
+		return ieee754sp_zero(xs);
+	case IEEE754_CLASS_DNORM:
+		/* cant possibly be sp representable */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+
+	{
+		unsigned long rm;
+
+		/* convert from DP_MBITS to SP_MBITS+3 with sticky right shift 
+		 */
+		rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) |
+		    ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0);
+
+		SPNORMRET1(xs, xe, rm, "fdp", x);
+	}
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_fint.c linux/arch/mips/math-emu/sp_fint.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_fint.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_fint.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,78 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_fint(int x)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	if (x == 0)
+		return ieee754sp_zero(0);
+	if (x == 1 || x == -1)
+		return ieee754sp_one(x < 0);
+	if (x == 10 || x == -10)
+		return ieee754sp_ten(x < 0);
+
+	xs = (x < 0);
+	if (xs) {
+		if (x == (1 << 31))
+			xm = ((unsigned) 1 << 31);	/* max neg can't be safely negated */
+		else
+			xm = -x;
+	} else {
+		xm = x;
+	}
+	xe = SP_MBITS + 3;
+
+	if (xm >> (SP_MBITS + 1 + 3)) {
+		/* shunt out overflow bits 
+		 */
+		while (xm >> (SP_MBITS + 1 + 3)) {
+			SPXSRSX1();
+		}
+	} else {
+		/* normalize in grs extended single precision 
+		 */
+		while ((xm >> (SP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	SPNORMRET1(xs, xe, xm, "fint", x);
+}
+
+
+ieee754sp ieee754sp_funs(unsigned int u)
+{
+	if ((int) u < 0)
+		return ieee754sp_add(ieee754sp_1e31(),
+				     ieee754sp_fint(u & ~(1 << 31)));
+	return ieee754sp_fint(u);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_flong.c linux/arch/mips/math-emu/sp_flong.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_flong.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_flong.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,77 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_flong(long long x)
+{
+	COMPXDP;		/* <--- need 64-bit mantissa temp */
+
+	CLEARCX;
+
+	if (x == 0)
+		return ieee754sp_zero(0);
+	if (x == 1 || x == -1)
+		return ieee754sp_one(x < 0);
+	if (x == 10 || x == -10)
+		return ieee754sp_ten(x < 0);
+
+	xs = (x < 0);
+	if (xs) {
+		if (x == (1ULL << 63))
+			xm = (1ULL << 63);	/* max neg can't be safely negated */
+		else
+			xm = -x;
+	} else {
+		xm = x;
+	}
+	xe = SP_MBITS + 3;
+
+	if (xm >> (SP_MBITS + 1 + 3)) {
+		/* shunt out overflow bits 
+		 */
+		while (xm >> (SP_MBITS + 1 + 3)) {
+			SPXSRSX1();
+		}
+	} else {
+		/* normalize in grs extended single precision */
+		while ((xm >> (SP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	SPNORMRET1(xs, xe, xm, "sp_flong", x);
+}
+
+
+ieee754sp ieee754sp_fulong(unsigned long long u)
+{
+	if ((long long) u < 0)
+		return ieee754sp_add(ieee754sp_1e63(),
+				     ieee754sp_flong(u & ~(1ULL << 63)));
+	return ieee754sp_flong(u);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_frexp.c linux/arch/mips/math-emu/sp_frexp.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_frexp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_frexp.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,53 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+/* close to ieeep754sp_logb 
+*/
+ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr)
+{
+	COMPXSP;
+	CLEARCX;
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		*eptr = 0;
+		return x;
+	case IEEE754_CLASS_DNORM:
+		SPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	*eptr = xe + 1;
+	return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_logb.c linux/arch/mips/math-emu/sp_logb.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_logb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_logb.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,54 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_logb(ieee754sp x)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754sp_nanxcpt(x, "logb", x);
+	case IEEE754_CLASS_QNAN:
+		return x;
+	case IEEE754_CLASS_INF:
+		return ieee754sp_inf(0);
+	case IEEE754_CLASS_ZERO:
+		return ieee754sp_inf(1);
+	case IEEE754_CLASS_DNORM:
+		SPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	return ieee754sp_fint(xe);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_modf.c linux/arch/mips/math-emu/sp_modf.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_modf.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_modf.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,80 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+/* modf function is always exact for a finite number
+*/
+ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		*ip = x;
+		return x;
+	case IEEE754_CLASS_DNORM:
+		/* far to small */
+		*ip = ieee754sp_zero(xs);
+		return x;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe < 0) {
+		*ip = ieee754sp_zero(xs);
+		return x;
+	}
+	if (xe >= SP_MBITS) {
+		*ip = x;
+		return ieee754sp_zero(xs);
+	}
+	/* generate ipart mantissa by clearing bottom bits 
+	 */
+	*ip = buildsp(xs, xe + SP_EBIAS,
+		      ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) &
+		      ~SP_HIDDEN_BIT);
+
+	/* generate fpart mantissa by clearing top bits
+	 * and normalizing (must be able to normalize)
+	 */
+	xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe));
+	if (xm == 0)
+		return ieee754sp_zero(xs);
+
+	while ((xm >> SP_MBITS) == 0) {
+		xm <<= 1;
+		xe--;
+	}
+	return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_mul.c linux/arch/mips/math-emu/sp_mul.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_mul.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_mul.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,174 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
+{
+	COMPXSP;
+	COMPYSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+	EXPLODEYSP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "mul", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y, "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754sp_nanxcpt(x, "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754sp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Infinity handeling */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		return ieee754sp_inf(xs ^ ys);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return ieee754sp_zero(xs ^ ys);
+
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		SPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		SPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		SPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	/* rm = xm * ym, re = xe+ye basicly */
+	assert(xm & SP_HIDDEN_BIT);
+	assert(ym & SP_HIDDEN_BIT);
+
+	{
+		int re = xe + ye;
+		int rs = xs ^ ys;
+		unsigned rm;
+
+		/* shunt to top of word */
+		xm <<= 32 - (SP_MBITS + 1);
+		ym <<= 32 - (SP_MBITS + 1);
+
+		/* multiply 32bits xm,ym to give high 32bits rm with stickness
+		 */
+		{
+			unsigned short lxm = xm & 0xffff;
+			unsigned short hxm = xm >> 16;
+			unsigned short lym = ym & 0xffff;
+			unsigned short hym = ym >> 16;
+			unsigned lrm;
+			unsigned hrm;
+
+			lrm = lxm * lym;	/* 16 * 16 => 32 */
+			hrm = hxm * hym;	/* 16 * 16 => 32 */
+
+			{
+				unsigned t = lxm * hym;	/* 16 * 16 => 32 */
+				{
+					unsigned at = lrm + (t << 16);
+					hrm += at < lrm;
+					lrm = at;
+				}
+				hrm = hrm + (t >> 16);
+			}
+
+			{
+				unsigned t = hxm * lym;	/* 16 * 16 => 32 */
+				{
+					unsigned at = lrm + (t << 16);
+					hrm += at < lrm;
+					lrm = at;
+				}
+				hrm = hrm + (t >> 16);
+			}
+			rm = hrm | (lrm != 0);
+		}
+
+		/*
+		 * sticky shift down to normal rounding precision
+		 */
+		if ((int) rm < 0) {
+			rm = (rm >> (32 - (SP_MBITS + 1 + 3))) |
+			    ((rm << (SP_MBITS + 1 + 3)) != 0);
+			re++;
+		} else {
+			rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) |
+			    ((rm << (SP_MBITS + 1 + 3 + 1)) != 0);
+		}
+		assert(rm & (SP_HIDDEN_BIT << 3));
+
+		SPNORMRET2(rs, re, rm, "mul", x, y);
+	}
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_scalb.c linux/arch/mips/math-emu/sp_scalb.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_scalb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_scalb.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_scalb(ieee754sp x, int n)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754sp_nanxcpt(x, "scalb", x, n);
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		return x;
+	case IEEE754_CLASS_DNORM:
+		SPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
+}
+
+
+ieee754sp ieee754sp_ldexp(ieee754sp x, int n)
+{
+	return ieee754sp_scalb(x, n);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_simple.c linux/arch/mips/math-emu/sp_simple.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_simple.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_simple.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,66 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+int ieee754sp_finite(ieee754sp x)
+{
+	return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
+}
+
+ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y)
+{
+	CLEARCX;
+	SPSIGN(x) = SPSIGN(y);
+	return x;
+}
+
+
+ieee754sp ieee754sp_neg(ieee754sp x)
+{
+	CLEARCX;
+
+	if (ieee754sp_isnan(x))	/* but not infinity */
+		return ieee754sp_nanxcpt(x, "neg", x);
+
+	/* quick fix up */
+	SPSIGN(x) ^= 1;
+	return x;
+}
+
+
+ieee754sp ieee754sp_abs(ieee754sp x)
+{
+	CLEARCX;
+
+	if (ieee754sp_isnan(x))	/* but not infinity */
+		return ieee754sp_nanxcpt(x, "abs", x);
+
+	/* quick fix up */
+	SPSIGN(x) = 0;
+	return x;
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_sqrt.c linux/arch/mips/math-emu/sp_sqrt.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_sqrt.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_sqrt.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,115 @@
+/* IEEE754 floating point arithmetic
+ * single precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+static const struct ieee754sp_konst knan = {
+	0, SP_EBIAS + SP_EMAX + 1, 0
+};
+
+#define nan	((ieee754sp)knan)
+
+ieee754sp ieee754sp_sqrt(ieee754sp x)
+{
+	int sign = (int) 0x80000000;
+	int ix, s, q, m, t, i;
+	unsigned int r;
+	COMPXDP;
+
+	/* take care of Inf and NaN */
+
+	EXPLODEXDP;
+
+	/* x == INF or NAN? */
+	switch (xc) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		/* sqrt(Nan) = Nan */
+		return ieee754sp_nanxcpt(x, "sqrt");
+	case IEEE754_CLASS_ZERO:
+		/* sqrt(0) = 0 */
+		return x;
+	case IEEE754_CLASS_INF:
+		if (xs)
+			/* sqrt(-Inf) = Nan */
+			return ieee754sp_nanxcpt(nan, "sqrt");
+		/* sqrt(+Inf) = Inf */
+		return x;
+	case IEEE754_CLASS_DNORM:
+	case IEEE754_CLASS_NORM:
+		if (xs)
+			/* sqrt(-x) = Nan */
+			return ieee754sp_nanxcpt(nan, "sqrt");
+		break;
+	}
+
+	ix = x.bits;
+
+	/* normalize x */
+	m = (ix >> 23);
+	if (m == 0) {		/* subnormal x */
+		for (i = 0; (ix & 0x00800000) == 0; i++)
+			ix <<= 1;
+		m -= i - 1;
+	}
+	m -= 127;		/* unbias exponent */
+	ix = (ix & 0x007fffff) | 0x00800000;
+	if (m & 1)		/* odd m, double x to make it even */
+		ix += ix;
+	m >>= 1;		/* m = [m/2] */
+
+	/* generate sqrt(x) bit by bit */
+	ix += ix;
+	q = s = 0;		/* q = sqrt(x) */
+	r = 0x01000000;		/* r = moving bit from right to left */
+
+	while (r != 0) {
+		t = s + r;
+		if (t <= ix) {
+			s = t + r;
+			ix -= t;
+			q += r;
+		}
+		ix += ix;
+		r >>= 1;
+	}
+
+	if (ix != 0) {
+		switch (ieee754_csr.rm) {
+		case IEEE754_RP:
+			q += 2;
+			break;
+		case IEEE754_RN:
+			q += (q & 1);
+			break;
+		}
+	}
+	ix = (q >> 1) + 0x3f000000;
+	ix += (m << 23);
+	x.bits = ix;
+	return x;
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_sub.c linux/arch/mips/math-emu/sp_sub.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_sub.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_sub.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,187 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
+{
+	COMPXSP;
+	COMPYSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+	EXPLODEYSP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "sub", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y, "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754sp_nanxcpt(x, "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754sp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Inifity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		if (xs != ys)
+			return x;
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+		return ieee754sp_inf(ys ^ 1);
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return x;
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		if (xs != ys)
+			return x;
+		else
+			return ieee754sp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return x;
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		/* quick fix up */
+		DPSIGN(y) ^= 1;
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		SPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		SPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		SPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	/* flip sign of y and handle as add */
+	ys ^= 1;
+
+	assert(xm & SP_HIDDEN_BIT);
+	assert(ym & SP_HIDDEN_BIT);
+
+
+	/* provide guard,round and stick bit space */
+	xm <<= 3;
+	ym <<= 3;
+
+	if (xe > ye) {
+		/* have to shift y fraction right to align
+		 */
+		int s = xe - ye;
+		SPXSRSYn(s);
+	} else if (ye > xe) {
+		/* have to shift x fraction right to align
+		 */
+		int s = ye - xe;
+		SPXSRSXn(s);
+	}
+	assert(xe == ye);
+	assert(xe <= SP_EMAX);
+
+	if (xs == ys) {
+		/* generate 28 bit result of adding two 27 bit numbers
+		 */
+		xm = xm + ym;
+		xe = xe;
+		xs = xs;
+
+		if (xm >> (SP_MBITS + 1 + 3)) {	/* carry out */
+			SPXSRSX1();	/* shift preserving sticky */
+		}
+	} else {
+		if (xm >= ym) {
+			xm = xm - ym;
+			xe = xe;
+			xs = xs;
+		} else {
+			xm = ym - xm;
+			xe = xe;
+			xs = ys;
+		}
+		if (xm == 0)
+			if (ieee754_csr.rm == IEEE754_RD)
+				return ieee754sp_zero(1);	/* round negative inf. => sign = -1 */
+			else
+				return ieee754sp_zero(0);	/* other round modes   => sign = 1 */
+
+		/* normalize to rounding precision 
+		 */
+		while ((xm >> (SP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	SPNORMRET2(xs, xe, xm, "sub", x, y);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_tint.c linux/arch/mips/math-emu/sp_tint.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_tint.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_tint.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,88 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <linux/kernel.h>
+#include "ieee754sp.h"
+
+int ieee754sp_tint(ieee754sp x)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754si_xcpt(ieee754si_indef(), "fixsp", x);
+	case IEEE754_CLASS_INF:
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754si_xcpt(ieee754si_indef(), "fixsp", x);
+	case IEEE754_CLASS_ZERO:
+		return 0;
+	case IEEE754_CLASS_DNORM:	/* much to small */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754si_xcpt(0, "fixsp", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe >= 31) {
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754si_xcpt(ieee754si_indef(), "fix", x);
+	}
+	if (xe < 0) {
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754si_xcpt(0, "fix", x);
+	}
+	/* oh gawd */
+	if (xe > SP_MBITS) {
+		xm <<= xe - SP_MBITS;
+	} else if (xe < SP_MBITS) {
+		/* XXX no rounding 
+		 */
+		xm >>= SP_MBITS - xe;
+	}
+	if (xs)
+		return -xm;
+	else
+		return xm;
+}
+
+
+unsigned int ieee754sp_tuns(ieee754sp x)
+{
+	ieee754sp hb = ieee754sp_1e31();
+
+	/* what if x < 0 ?? */
+	if (ieee754sp_lt(x, hb))
+		return (unsigned) ieee754sp_tint(x);
+
+	return (unsigned) ieee754sp_tint(ieee754sp_sub(x, hb)) |
+	    ((unsigned) 1 << 31);
+}
diff -urN linux-2.4.4-pre3/arch/mips/math-emu/sp_tlong.c linux/arch/mips/math-emu/sp_tlong.c
--- linux-2.4.4-pre3/arch/mips/math-emu/sp_tlong.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/math-emu/sp_tlong.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,87 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+long long ieee754sp_tlong(ieee754sp x)
+{
+	COMPXDP;		/* <-- need 64-bit mantissa tmp */
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+	case IEEE754_CLASS_INF:
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+	case IEEE754_CLASS_ZERO:
+		return 0;
+	case IEEE754_CLASS_DNORM:	/* much to small */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754di_xcpt(0, "sp_tlong", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe >= 63) {
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+	}
+	if (xe < 0) {
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754di_xcpt(0, "sp_tlong", x);
+	}
+	/* oh gawd */
+	if (xe > SP_MBITS) {
+		xm <<= xe - SP_MBITS;
+	} else if (xe < SP_MBITS) {
+		/* XXX no rounding 
+		 */
+		xm >>= SP_MBITS - xe;
+	}
+	if (xs)
+		return -xm;
+	else
+		return xm;
+}
+
+
+unsigned long long ieee754sp_tulong(ieee754sp x)
+{
+	ieee754sp hb = ieee754sp_1e63();
+
+	/* what if x < 0 ?? */
+	if (ieee754sp_lt(x, hb))
+		return (unsigned long long) ieee754sp_tlong(x);
+
+	return (unsigned long long) ieee754sp_tlong(ieee754sp_sub(x, hb)) |
+	    (1ULL << 63);
+}
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/atlas/Makefile linux/arch/mips/mips-boards/atlas/Makefile
--- linux-2.4.4-pre3/arch/mips/mips-boards/atlas/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/atlas/Makefile	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,42 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+#
+# ########################################################################
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# #######################################################################
+#
+# Makefile for the MIPS Atlas specific kernel interface routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+all: atlas.o
+
+O_TARGET := atlas.o
+
+obj-y	:= atlas_int.o atlas_rtc.o atlas_setup.o
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/atlas/atlas_int.c linux/arch/mips/mips-boards/atlas/atlas_int.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/atlas/atlas_int.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/atlas/atlas_int.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,248 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Routines for generic manipulation of the interrupts found on the MIPS 
+ * Atlas board.
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/irq.h>
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/atlasint.h>
+#include <asm/gdb-stub.h>
+
+
+struct atlas_ictrl_regs *atlas_hw0_icregs
+	= (struct atlas_ictrl_regs *)ATLAS_ICTRL_REGS_BASE;
+
+extern asmlinkage void mipsIRQ(void);
+extern void do_IRQ(int irq, struct pt_regs *regs);
+
+unsigned long spurious_count = 0;
+irq_desc_t irq_desc[NR_IRQS];
+
+#if 0
+#define DEBUG_INT(x...) printk(x)
+#else
+#define DEBUG_INT(x...)
+#endif
+
+void disable_atlas_irq(unsigned int irq_nr)
+{
+	atlas_hw0_icregs->intrsten = (1 << irq_nr);
+}
+
+void enable_atlas_irq(unsigned int irq_nr)
+{
+	atlas_hw0_icregs->intseten = (1 << irq_nr);
+}
+
+static unsigned int startup_atlas_irq(unsigned int irq)
+{
+	enable_atlas_irq(irq);
+	return 0; /* never anything pending */
+}
+
+#define shutdown_atlas_irq	disable_atlas_irq
+
+#define mask_and_ack_atlas_irq disable_atlas_irq
+
+static void end_atlas_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_atlas_irq(irq);
+}
+
+static struct hw_interrupt_type atlas_irq_type = {
+	"Atlas",
+	startup_atlas_irq,
+	shutdown_atlas_irq,
+	enable_atlas_irq,
+	disable_atlas_irq,
+	mask_and_ack_atlas_irq,
+	end_atlas_irq,
+	NULL
+};
+
+int get_irq_list(char *buf)
+{
+	int i, len = 0;
+	int num = 0;
+	struct irqaction *action;
+
+	for (i = 0; i < ATLASINT_END; i++, num++) {
+		action = irq_desc[i].action;
+		if (!action) 
+			continue;
+		len += sprintf(buf+len, "%2d: %8d %c %s",
+			num, kstat.irqs[0][num],
+			(action->flags & SA_INTERRUPT) ? '+' : ' ',
+			action->name);
+		for (action=action->next; action; action = action->next) {
+			len += sprintf(buf+len, ",%s %s",
+				(action->flags & SA_INTERRUPT) ? " +" : "",
+				action->name);
+		}
+		len += sprintf(buf+len, " [hw0]\n");
+	}
+	return len;
+}
+
+int request_irq(unsigned int irq, 
+		void (*handler)(int, void *, struct pt_regs *),
+		unsigned long irqflags, 
+		const char * devname,
+		void *dev_id)
+{  
+        struct irqaction *action;
+
+	DEBUG_INT("request_irq: irq=%d, devname = %s\n", irq, devname);
+
+	if (irq >= ATLASINT_END)
+		return -EINVAL;
+	if (!handler)
+		return -EINVAL;
+
+	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if(!action)
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	action->mask = 0;
+	action->name = devname;
+	action->dev_id = dev_id;
+	action->next = 0;
+	irq_desc[irq].action = action;
+	enable_atlas_irq(irq);
+
+	return 0;
+}
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+	struct irqaction *action;
+
+	if (irq >= ATLASINT_END) {
+		printk("Trying to free IRQ%d\n",irq);
+		return;
+	}
+
+	action = irq_desc[irq].action;
+	irq_desc[irq].action = NULL;
+	disable_atlas_irq(irq);
+	kfree(action);
+}
+
+static inline int ls1bit32(unsigned int x)
+{
+	int b = 31, s;
+
+	s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
+	s =  8; if (x <<  8 == 0) s = 0; b -= s; x <<= s;
+	s =  4; if (x <<  4 == 0) s = 0; b -= s; x <<= s;
+	s =  2; if (x <<  2 == 0) s = 0; b -= s; x <<= s;
+	s =  1; if (x <<  1 == 0) s = 0; b -= s;
+
+	return b;
+}
+
+void atlas_hw0_irqdispatch(struct pt_regs *regs)
+{
+	struct irqaction *action;
+	unsigned long int_status;
+	int irq, cpu = smp_processor_id();
+
+	int_status = atlas_hw0_icregs->intstatus; 
+
+	/* if int_status == 0, then the interrupt has already been cleared */
+	if (int_status == 0)
+		return;
+
+	irq = ls1bit32(int_status);
+	action = irq_desc[irq].action;
+
+	DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq);
+
+	/* if action == NULL, then we don't have a handler for the irq */
+	if ( action == NULL ) {
+		printk("No handler for hw0 irq: %i\n", irq);
+		spurious_count++;
+		return;
+	}
+
+	irq_enter(cpu, irq);
+	kstat.irqs[0][irq]++;
+	action->handler(irq, action->dev_id, regs);
+	irq_exit(cpu, irq);
+
+	return;		
+}
+
+unsigned long probe_irq_on (void)
+{
+	return 0;
+}
+
+
+int probe_irq_off (unsigned long irqs)
+{
+	return 0;
+}
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void breakpoint(void);
+extern int remote_debug;
+#endif
+
+void __init init_IRQ(void)
+{
+	int i;
+
+	/* 
+	 * Mask out all interrupt by writing "1" to all bit position in 
+	 * the interrupt reset reg. 
+	 */
+	atlas_hw0_icregs->intrsten = 0xffffffff;    
+
+	/* Now safe to set the exception vector. */
+	set_except_vector(0, mipsIRQ);
+
+	for (i = 0; i <= ATLASINT_END; i++) {
+		irq_desc[i].status	= IRQ_DISABLED;
+		irq_desc[i].action	= 0;
+		irq_desc[i].depth	= 1;
+		irq_desc[i].handler	= &atlas_irq_type;
+	}
+
+#ifdef CONFIG_REMOTE_DEBUG
+	if (remote_debug) {
+		set_debug_traps();
+		breakpoint();
+	}
+#endif
+}
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/atlas/atlas_rtc.c linux/arch/mips/mips-boards/atlas/atlas_rtc.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/atlas/atlas_rtc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/atlas/atlas_rtc.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,58 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * RTC routines for Atlas style attached Dallas chip.
+ *
+ */
+#include <linux/spinlock.h>
+#include <linux/mc146818rtc.h>
+#include <asm/mips-boards/atlas.h>
+
+
+static unsigned char atlas_rtc_read_data(unsigned long addr)
+{
+	volatile unsigned int *rtc_adr_reg = (void *)ATLAS_RTC_ADR_REG;
+	volatile unsigned int *rtc_dat_reg = (void *)ATLAS_RTC_DAT_REG;
+
+	*rtc_adr_reg = addr;
+
+	return *rtc_dat_reg;
+}
+
+static void atlas_rtc_write_data(unsigned char data, unsigned long addr)
+{
+	volatile unsigned int *rtc_adr_reg = (void *)ATLAS_RTC_ADR_REG;
+	volatile unsigned int *rtc_dat_reg = (void *)ATLAS_RTC_DAT_REG;
+
+	*rtc_adr_reg = addr;
+	*rtc_dat_reg = data;
+}
+
+static int atlas_rtc_bcd_mode(void)
+{
+	return 0;
+}
+
+struct rtc_ops atlas_rtc_ops = {
+	&atlas_rtc_read_data,
+	&atlas_rtc_write_data,
+	&atlas_rtc_bcd_mode
+};
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/atlas/atlas_setup.c linux/arch/mips/mips-boards/atlas/atlas_setup.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/atlas/atlas_setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/atlas/atlas_setup.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,115 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Atlas specific setup.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mc146818rtc.h>
+#include <linux/ioport.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/gt64120.h>
+#include <asm/mips-boards/atlasint.h>
+
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
+extern void console_setup(char *, int *);
+char serial_console[20];
+#endif
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void rs_kgdb_hook(int);
+extern void saa9730_kgdb_hook(void);
+extern void breakpoint(void);
+int remote_debug = 0;
+#endif
+
+extern struct rtc_ops atlas_rtc_ops;
+
+extern void mips_reboot_setup(void);
+
+void __init atlas_setup(void)
+{
+#ifdef CONFIG_REMOTE_DEBUG
+	int rs_putDebugChar(char);
+	char rs_getDebugChar(void);
+	int saa9730_putDebugChar(char);
+	char saa9730_getDebugChar(void);
+	extern int (*putDebugChar)(char);
+	extern char (*getDebugChar)(void);
+#endif
+	char *argptr;
+
+	ioport_resource.end = 0x7fffffff;
+
+#ifdef CONFIG_SERIAL_CONSOLE
+	argptr = prom_getcmdline();
+	if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) {
+		int i = 0;
+		char *s = prom_getenv("modetty0");
+		while(s[i] >= '0' && s[i] <= '9')
+			i++;
+		strcpy(serial_console, "ttyS0,");
+		strncpy(serial_console + 6, s, i);
+		prom_printf("Config serial console: %s\n", serial_console);
+		console_setup(serial_console, NULL);
+	}
+#endif	  
+
+#ifdef CONFIG_REMOTE_DEBUG
+	argptr = prom_getcmdline();
+	if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
+		int line;
+		argptr += strlen("kgdb=ttyS");
+		if (*argptr != '0' && *argptr != '1')
+			printk("KGDB: Uknown serial line /dev/ttyS%c, "
+			       "falling back to /dev/ttyS1\n", *argptr);
+		line = *argptr == '0' ? 0 : 1;
+		printk("KGDB: Using serial line /dev/ttyS%d for session\n",
+		       line ? 1 : 0);
+
+		if(line == 0) {
+			rs_kgdb_hook(line);
+			putDebugChar = rs_putDebugChar;
+			getDebugChar = rs_getDebugChar;
+		} else {
+			saa9730_kgdb_hook();
+			putDebugChar = saa9730_putDebugChar;
+			getDebugChar = saa9730_getDebugChar;
+		}
+
+		prom_printf("KGDB: Using serial line /dev/ttyS%d for session, "
+			    "please connect your debugger\n", line ? 1 : 0);
+
+		remote_debug = 1;
+		/* Breakpoints and stuff are in atlas_irq_setup() */
+	}
+#endif
+	argptr = prom_getcmdline();
+
+	if ((argptr = strstr(argptr, "nofpu")) != NULL)
+		mips_cpu.options &= ~MIPS_CPU_FPU;
+
+	rtc_ops = &atlas_rtc_ops;
+
+	mips_reboot_setup();
+}
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/generic/Makefile linux/arch/mips/mips-boards/generic/Makefile
--- linux-2.4.4-pre3/arch/mips/mips-boards/generic/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/generic/Makefile	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,41 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+#
+# ########################################################################
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# #######################################################################
+#
+# Makefile for the MIPS boards generic routines under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+O_TARGET := mipsboards.o
+
+obj-y				:= mipsIRQ.o pci.o reset.o display.o init.o \
+				   memory.o printf.o cmdline.o time.o
+obj-$(CONFIG_REMOTE_DEBUG)	+= gdb_hook.o
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/generic/cmdline.c linux/arch/mips/mips-boards/generic/cmdline.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/generic/cmdline.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/generic/cmdline.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,53 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Kernel command line creation using the prom monitor (YAMON) argc/argv.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+extern int prom_argc;
+extern char **prom_argv;
+
+char arcs_cmdline[COMMAND_LINE_SIZE];
+
+char * __init prom_getcmdline(void)
+{
+	return &(arcs_cmdline[0]);
+}
+
+
+void  __init prom_init_cmdline(void)
+{
+	char *cp;
+	int actr;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	cp = &(arcs_cmdline[0]);
+	while(actr < prom_argc) {
+	        strcpy(cp, prom_argv[actr]);
+		cp += strlen(prom_argv[actr]);
+		*cp++ = ' ';
+		actr++;
+	}
+	if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
+		--cp;
+	*cp = '\0';
+}
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/generic/display.c linux/arch/mips/mips-boards/generic/display.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/generic/display.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/generic/display.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,47 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ * 
+ * Display routines for display messages in MIPS boards ascii display.
+ *
+ */
+
+#include <asm/mips-boards/generic.h>
+
+
+void mips_display_message(const char *str)
+{
+        volatile unsigned int *display = (void *)ASCII_DISPLAY_POS_BASE;
+	int i;
+
+	for (i = 0; i <= 14; i=i+2) {
+	         if (*str)
+		         display[i] = *str++;
+		 else
+		         display[i] = ' ';
+	}
+}
+
+void mips_display_word(unsigned int num)
+{
+        volatile unsigned int *display = (void *)ASCII_DISPLAY_WORD_BASE;
+	
+	*display = num;
+}
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/generic/gdb_hook.c linux/arch/mips/mips-boards/generic/gdb_hook.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/generic/gdb_hook.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/generic/gdb_hook.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,205 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * This is the interface to the remote debugger stub.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+
+#include <asm/serial.h>
+#include <asm/io.h>
+
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
+	SERIAL_PORT_DFNS	/* Defined in serial.h */
+};
+
+static struct async_struct kdb_port_info = {0};
+
+int (*putDebugChar)(char);
+char (*getDebugChar)(void);
+
+static __inline__ unsigned int serial_in(struct async_struct *info, int offset)
+{
+	return inb(info->port + offset);
+}
+
+static __inline__ void serial_out(struct async_struct *info, int offset,
+				int value)
+{
+	outb(value, info->port+offset);
+}
+
+void rs_kgdb_hook(int tty_no) {
+	int t;
+	struct serial_state *ser = &rs_table[tty_no];
+
+	kdb_port_info.state = ser;
+	kdb_port_info.magic = SERIAL_MAGIC;
+	kdb_port_info.port = ser->port;
+	kdb_port_info.flags = ser->flags;
+
+	/*
+	 * Clear all interrupts
+	 */
+	serial_in(&kdb_port_info, UART_LSR);
+	serial_in(&kdb_port_info, UART_RX);
+	serial_in(&kdb_port_info, UART_IIR);
+	serial_in(&kdb_port_info, UART_MSR);
+
+	/*
+	 * Now, initialize the UART 
+	 */
+	serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);	/* reset DLAB */
+	if (kdb_port_info.flags & ASYNC_FOURPORT) {
+		kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS;
+		t = UART_MCR_DTR | UART_MCR_OUT1;
+	} else {
+		kdb_port_info.MCR 
+			= UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
+		t = UART_MCR_DTR | UART_MCR_RTS;
+	}
+
+	kdb_port_info.MCR = t;		/* no interrupts, please */
+	serial_out(&kdb_port_info, UART_MCR, kdb_port_info.MCR);
+	
+	/*
+	 * and set the speed of the serial port
+	 * (currently hardwired to 9600 8N1
+	 */
+
+	/* baud rate is fixed to 9600 (is this sufficient?)*/
+	t = kdb_port_info.state->baud_base / 9600;	
+	/* set DLAB */
+	serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB);
+	serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */
+	serial_out(&kdb_port_info, UART_DLM, t >> 8);  /* MS of divisor */
+	/* reset DLAB */
+	serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);
+}
+
+int rs_putDebugChar(char c)
+{
+
+	if (!kdb_port_info.state) { 	/* need to init device first */
+		return 0;
+	}
+
+	while ((serial_in(&kdb_port_info, UART_LSR) & UART_LSR_THRE) == 0)
+		;
+
+	serial_out(&kdb_port_info, UART_TX, c);
+
+	return 1;
+}
+
+char rs_getDebugChar(void)
+{
+	if (!kdb_port_info.state) { 	/* need to init device first */
+		return 0;
+	}
+
+	while (!(serial_in(&kdb_port_info, UART_LSR) & 1))
+		;
+
+	return(serial_in(&kdb_port_info, UART_RX));
+}
+
+
+#ifdef CONFIG_MIPS_ATLAS
+
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/saa9730_uart.h>
+
+#define INB(a)     inb((unsigned long)a)
+#define OUTB(x,a)  outb(x,(unsigned long)a)
+
+/*
+ * This is the interface to the remote debugger stub
+ * if the Philips part is used for the debug port,
+ * called from the platform setup code.
+ *
+ * PCI init will not have been done yet, we make a
+ * universal assumption about the way the bootloader (YAMON)
+ * have located and set up the chip.
+ */
+static t_uart_saa9730_regmap *kgdb_uart = (void *)(ATLAS_SAA9730_REG + SAA9730_UART_REGS_ADDR);
+
+static int saa9730_kgdb_active = 0;
+
+void saa9730_kgdb_hook(void) 
+{
+        volatile unsigned char t;
+
+        /*
+         * Clear all interrupts
+         */
+	t = INB(&kgdb_uart->Lsr);
+	t += INB(&kgdb_uart->Msr);
+	t += INB(&kgdb_uart->Thr_Rbr);
+	t += INB(&kgdb_uart->Iir_Fcr);
+
+        /*
+         * Now, initialize the UART
+         */
+	/* 8 data bits, one stop bit, no parity */
+	OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr);
+
+        /* baud rate is fixed to 9600 (is this sufficient?)*/
+	OUTB(0, &kgdb_uart->BaudDivMsb); /* HACK - Assumes standard crystal */
+	OUTB(23, &kgdb_uart->BaudDivLsb); /* HACK - known for MIPS Atlas */
+
+	/* Set RTS/DTR active */
+	OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr);
+	saa9730_kgdb_active = 1;
+}
+
+int saa9730_putDebugChar(char c)
+{
+
+        if (!saa9730_kgdb_active) {     /* need to init device first */
+                return 0;
+        }
+
+        while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE))
+                ;
+	OUTB(c, &kgdb_uart->Thr_Rbr);
+
+        return 1;
+}
+
+char saa9730_getDebugChar(void)
+{
+	char c;
+
+        if (!saa9730_kgdb_active) {     /* need to init device first */
+                return 0;
+        }
+        while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR))
+                ;
+
+	c = INB(&kgdb_uart->Thr_Rbr);
+        return(c);
+}
+
+#endif
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/generic/init.c linux/arch/mips/mips-boards/generic/init.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/generic/init.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/generic/init.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,139 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * PROM library initialisation code.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#include <asm/io.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/gt64120.h>
+#include <asm/mips-boards/malta.h>
+
+/* Environment variable */
+typedef struct
+{
+	char *name;
+	char *val;
+} t_env_var;
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+
+int init_debug = 0;
+
+char *prom_getenv(char *envname)
+{
+        /*
+	 * Return a pointer to the given environment variable.
+	 */
+
+	t_env_var *env = (t_env_var *)prom_envp;
+	int i;
+
+	i = strlen(envname);
+
+	while(env->name) {
+		if(strncmp(envname, env->name, i) == 0) {
+			return(env->val);
+		}
+		env++;
+	}
+	return(NULL);
+}
+
+static inline unsigned char str2hexnum(unsigned char c)
+{
+	if(c >= '0' && c <= '9')
+		return c - '0';
+	if(c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	return 0; /* foo */
+}
+
+static inline void str2eaddr(unsigned char *ea, unsigned char *str)
+{
+	int i;
+
+	for(i = 0; i < 6; i++) {
+		unsigned char num;
+
+		if((*str == '.') || (*str == ':'))
+			str++;
+		num = str2hexnum(*str++) << 4;
+		num |= (str2hexnum(*str++));
+		ea[i] = num;
+	}
+}
+ 
+int get_ethernet_addr(char *ethernet_addr)
+{
+        char *ethaddr_str;
+
+        ethaddr_str = prom_getenv("ethaddr");
+	if (!ethaddr_str) {
+	        printk("ethaddr not set in boot prom\n");
+		return -1;
+	}
+	str2eaddr(ethernet_addr, ethaddr_str);
+
+	if (init_debug > 1) {
+	        int i;
+		printk("get_ethernet_addr: ");
+	        for (i=0; i<5; i++)
+		        printk("%02x:", (unsigned char)*(ethernet_addr+i));
+		printk("%02x\n", *(ethernet_addr+i));
+	}
+
+	return 0;
+}
+
+int __init prom_init(int argc, char **argv, char **envp)
+{
+	prom_argc = argc;
+	prom_argv = argv;
+	prom_envp = envp;
+
+	mips_display_message("LINUX");
+
+	/*
+	 * Setup the North bridge to do Master byte-lane swapping when 
+	 * running in bigendian.
+	 */
+#if defined(__MIPSEL__)
+	GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT |
+		 GT_PCI0_CMD_SBYTESWAP_BIT);
+#else
+	GT_WRITE(GT_PCI0_CMD_OFS, 0);
+#endif
+
+#if defined(CONFIG_MIPS_MALTA)
+	mips_io_port_base = MALTA_PORT_BASE;
+#else
+	mips_io_port_base = KSEG1;
+#endif
+	setup_prom_printf(0);
+	prom_printf("\nLINUX started...\n");
+	prom_init_cmdline();
+	prom_meminit();
+
+	return 0;
+}
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/generic/memory.c linux/arch/mips/mips-boards/generic/memory.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/generic/memory.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/generic/memory.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,169 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * PROM library functions for acquiring/using memory descriptors given to 
+ * us from the YAMON.
+ * 
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+
+#include <asm/mips-boards/prom.h>
+
+/*#define DEBUG*/
+
+enum yamon_memtypes {
+	yamon_dontuse,
+	yamon_prom,
+	yamon_free,
+};
+struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
+
+#ifdef DEBUG
+static char *mtypes[3] = {
+	"Dont use memory",
+	"YAMON PROM memory",
+	"Free memmory",
+};
+#endif
+
+
+struct prom_pmemblock * __init prom_getmdesc(void)
+{
+	char *memsize_str;
+	unsigned int memsize;
+
+	memsize_str = prom_getenv("memsize");
+	if (!memsize_str) {
+		prom_printf("memsize not set in boot prom, set to default (32Mb)\n");
+		memsize = 0x02000000;
+	} else {
+#ifdef DEBUG
+		prom_printf("prom_memsize = %s\n", memsize_str);
+#endif
+		memsize = simple_strtol(memsize_str, NULL, 0);
+	}
+
+	memset(mdesc, 0, sizeof(mdesc));
+
+	mdesc[0].type = yamon_dontuse;
+	mdesc[0].base = 0x00000000;
+	mdesc[0].size = 0x00001000;
+
+	mdesc[1].type = yamon_prom;
+	mdesc[1].base = 0x00001000;
+	mdesc[1].size = 0x000ef000;
+
+#if (CONFIG_MIPS_MALTA)
+	/* 
+	 * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
+	 * south bridge and PCI access always forwarded to the ISA Bus and 
+	 * BIOSCS# is always generated.
+	 * This mean that this area can't be used as DMA memory for PCI 
+	 * devices.
+	 */
+	mdesc[2].type = yamon_dontuse;
+	mdesc[2].base = 0x000f0000;
+	mdesc[2].size = 0x00010000;
+#else
+	mdesc[2].type = yamon_prom;
+	mdesc[2].base = 0x000f0000;
+	mdesc[2].size = 0x00010000;
+#endif
+
+	mdesc[3].type = yamon_free;
+	mdesc[3].base = 0x00100000;
+	mdesc[3].size = memsize - mdesc[3].base;
+
+	return &mdesc[0];
+}
+
+static int __init prom_memtype_classify (unsigned int type)
+{
+	switch (type) {
+	case yamon_free:
+		return BOOT_MEM_RAM;
+	case yamon_prom:
+		return BOOT_MEM_ROM_DATA;
+	default:
+		return BOOT_MEM_RESERVED;
+	}
+}
+
+void __init prom_meminit(void)
+{
+	struct prom_pmemblock *p;
+
+#ifdef DEBUG
+	int i = 0;
+
+	prom_printf("YAMON MEMORY DESCRIPTOR dump:\n");
+	p = prom_getmdesc();
+	while (p->size) {
+		prom_printf("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n",
+			    i, p, p->base, p->size, mtypes[p->type]);
+		p++;
+		i++;
+	}
+#endif
+	p = prom_getmdesc();
+	while (p->size) {
+		unsigned long base, size;
+		long type;
+
+		type = prom_memtype_classify (p->type);
+		base = p->base;
+		size = p->size;
+
+		add_memory_region(base, size, type);
+
+		p++;
+	}
+}
+
+void prom_free_prom_memory (void)
+{
+	int i;
+	struct prom_pmemblock *p;
+	unsigned long freed = 0;
+	unsigned long addr;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+			continue;
+
+		addr = boot_mem_map.map[i].addr;
+		while (addr < boot_mem_map.map[i].addr
+			      + boot_mem_map.map[i].size) {
+		        ClearPageReserved(virt_to_page(phys_to_virt(addr)));
+			set_page_count(virt_to_page(phys_to_virt(addr)), 1);
+			free_page(phys_to_virt(addr));
+			addr += PAGE_SIZE;
+			freed += PAGE_SIZE;
+		}
+	}
+	printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
+}
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/generic/mipsIRQ.S linux/arch/mips/mips-boards/generic/mipsIRQ.S
--- linux-2.4.4-pre3/arch/mips/mips-boards/generic/mipsIRQ.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/generic/mipsIRQ.S	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,122 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Interrupt exception dispatch code.
+ *
+ */
+#include <linux/config.h>
+
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/* A lot of complication here is taken away because:
+ *
+ * 1) We handle one interrupt and return, sitting in a loop and moving across
+ *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
+ *    common case is one pending IRQ so optimize in that direction.
+ *
+ * 2) We need not check against bits in the status register IRQ mask, that
+ *    would make this routine slow as hell.
+ *
+ * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
+ *    between like BSD spl() brain-damage.
+ *
+ * Furthermore, the IRQs on the MIPS board look basically (barring software
+ * IRQs which we don't use at all and all external interrupt sources are
+ * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *	MIPS IRQ	Source
+ *      --------        ------
+ *             0	Software (ignored)
+ *             1        Software (ignored)
+ *             2        Combined hardware interrupt (hw0)
+ *             3        Hardware (ignored)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+	.text
+	.set	noreorder
+	.set	noat
+	.align	5
+	NESTED(mipsIRQ, PT_SIZE, sp)
+	SAVE_ALL
+	CLI
+	.set	at
+
+	mfc0	s0, CP0_CAUSE		# get irq mask
+
+	/* First we check for r4k counter/timer IRQ. */
+	andi	a0, s0, CAUSEF_IP7
+	beq	a0, zero, 1f
+	 andi	a0, s0, CAUSEF_IP2	# delay slot, check hw0 interrupt
+
+	/* Wheee, a timer interrupt. */
+	move	a0, sp
+	jal	mips_timer_interrupt
+	 nop
+
+	j	ret_from_irq
+	 nop
+
+1:
+	beq	a0, zero, 1f
+	 nop
+
+	/* Wheee, combined hardware level zero interrupt. */
+#if defined(CONFIG_MIPS_ATLAS)
+	jal	atlas_hw0_irqdispatch
+#elif defined(CONFIG_MIPS_MALTA)
+	jal	malta_hw0_irqdispatch
+#else
+#error "MIPS board not supported\n"	
+#endif
+	 move	a0, sp			# delay slot
+
+	j	ret_from_irq
+	 nop				# delay slot
+
+1:
+	/*
+	 * Here by mistake?  This is possible, what can happen is that by the
+	 * time we take the exception the IRQ pin goes low, so just leave if
+	 * this is the case.
+	 */
+	move	a1,s0
+	PRINT("Got interrupt: c0_cause = %08x\n")
+	mfc0	a1, CP0_EPC
+	PRINT("c0_epc = %08x\n")
+
+	j	ret_from_irq
+	 nop
+	END(mipsIRQ)
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/generic/pci.c linux/arch/mips/mips-boards/generic/pci.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/generic/pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/generic/pci.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,328 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * MIPS boards specific PCI support.
+ *
+ */
+#include <linux/config.h>
+
+#ifdef CONFIG_PCI
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/gt64120.h>
+#ifdef CONFIG_MIPS_MALTA
+#include <asm/mips-boards/malta.h>
+#endif
+
+#define PCI_ACCESS_READ  0
+#define PCI_ACCESS_WRITE 1
+
+static int
+mips_pcibios_config_access(unsigned char access_type, struct pci_dev *dev,
+                           unsigned char where, u32 *data)
+{
+	unsigned char bus = dev->bus->number;
+	unsigned char dev_fn = dev->devfn;
+        u32 intr;
+
+	if ((bus == 0) && (dev_fn >= PCI_DEVFN(31,0)))
+	        return -1; /* Because of a bug in the galileo (for slot 31). */
+
+	/* Clear cause register bits */
+	GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | 
+	                             GT_INTRCAUSE_TARABORT0_BIT));
+
+	/* Setup address */
+	GT_WRITE(GT_PCI0_CFGADDR_OFS, 
+		 (bus         << GT_PCI0_CFGADDR_BUSNUM_SHF)   |
+		 (dev_fn      << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
+		 ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF)   |
+		 GT_PCI0_CFGADDR_CONFIGEN_BIT);
+
+	if (access_type == PCI_ACCESS_WRITE) {
+	        if (bus == 0 && dev_fn == 0) {
+		        /* 
+			 * Galileo is acting differently than other devices. 
+			 */
+		        GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+		} else {
+		        GT_PCI_WRITE(GT_PCI0_CFGDATA_OFS, *data);
+		}
+	} else {
+	        if (bus == 0 && dev_fn == 0) {
+		        /* 
+			 * Galileo is acting differently than other devices. 
+			 */
+		        GT_READ(GT_PCI0_CFGDATA_OFS, *data);
+		} else {
+		        GT_PCI_READ(GT_PCI0_CFGDATA_OFS, *data);
+		}
+	}
+
+	/* Check for master or target abort */
+	GT_READ(GT_INTRCAUSE_OFS, intr);
+
+	if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT))
+	{
+	        /* Error occured */
+
+	        /* Clear bits */
+	        GT_WRITE( GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | 
+					      GT_INTRCAUSE_TARABORT0_BIT) );
+
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/*
+ * We can't address 8 and 16 bit words directly.  Instead we have to
+ * read/write a 32bit word and mask/modify the data we actually want.
+ */
+static int
+mips_pcibios_read_config_byte (struct pci_dev *dev, int where, u8 *val)
+{
+	u32 data = 0;
+
+	if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+		return -1;
+
+	*val = (data >> ((where & 3) << 3)) & 0xff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int
+mips_pcibios_read_config_word (struct pci_dev *dev, int where, u16 *val)
+{
+	u32 data = 0;
+
+	if (where & 1)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+	       return -1;
+
+	*val = (data >> ((where & 3) << 3)) & 0xffff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mips_pcibios_read_config_dword (struct pci_dev *dev, int where, u32 *val)
+{
+	u32 data = 0;
+
+	if (where & 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	
+	if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+		return -1;
+
+	*val = data;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int
+mips_pcibios_write_config_byte (struct pci_dev *dev, int where, u8 val)
+{
+	u32 data = 0;
+       
+	if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+		return -1;
+
+	data = (data & ~(0xff << ((where & 3) << 3))) |
+	       (val << ((where & 3) << 3));
+
+	if (mips_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &data))
+		return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mips_pcibios_write_config_word (struct pci_dev *dev, int where, u16 val)
+{
+        u32 data = 0;
+
+	if (where & 1)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+       
+        if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data))
+	       return -1;
+
+	data = (data & ~(0xffff << ((where & 3) << 3))) | 
+	       (val << ((where & 3) << 3));
+
+	if (mips_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &data))
+	       return -1;
+
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mips_pcibios_write_config_dword(struct pci_dev *dev, int where, u32 val)
+{
+	if (where & 3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (mips_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &val))
+	       return -1;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops mips_pci_ops = {
+	mips_pcibios_read_config_byte,
+        mips_pcibios_read_config_word,
+	mips_pcibios_read_config_dword,
+	mips_pcibios_write_config_byte,
+	mips_pcibios_write_config_word,
+	mips_pcibios_write_config_dword
+};
+
+void __init pcibios_init(void)
+{
+#ifdef CONFIG_MIPS_MALTA
+	struct pci_dev *pdev;
+	unsigned char reg_val;
+#endif
+
+	printk("PCI: Probing PCI hardware on host bus 0.\n");
+	pci_scan_bus(0, &mips_pci_ops, NULL);
+
+	/* 
+	 * Due to a bug in the Galileo system controller, we need to setup 
+	 * the PCI BAR for the Galileo internal registers.
+	 * This should be done in the bios/bootprom and will be fixed in
+	 * a later revision of YAMON (the MIPS boards boot prom).
+	 */
+	GT_WRITE(GT_PCI0_CFGADDR_OFS,
+		 (0 << GT_PCI0_CFGADDR_BUSNUM_SHF)   |  /* Local bus */
+		 (0 << GT_PCI0_CFGADDR_DEVNUM_SHF)   |  /* GT64120 device */
+		 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |  /* Function 0 */
+		 ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) |  /* BAR 4 */
+		 GT_PCI0_CFGADDR_CONFIGEN_BIT );
+
+	/* Perform the write */
+	GT_WRITE( GT_PCI0_CFGDATA_OFS, PHYSADDR(MIPS_GT_BASE)); 
+
+#ifdef CONFIG_MIPS_MALTA
+	pci_for_each_dev(pdev) {
+		if ((pdev->vendor == PCI_VENDOR_ID_INTEL)
+		    && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB)
+		    && (PCI_SLOT(pdev->devfn) == 0x0a)) {
+			/*
+			 * IDE Decode enable.
+			 */
+			pci_read_config_byte(pdev, 0x41, &reg_val);
+        		pci_write_config_byte(pdev, 0x41, reg_val | 0x80);
+			pci_read_config_byte(pdev, 0x43, &reg_val);
+        		pci_write_config_byte(pdev, 0x43, reg_val | 0x80);
+		}
+
+		if ((pdev->vendor == PCI_VENDOR_ID_INTEL)
+		    && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB_0)
+		    && (PCI_SLOT(pdev->devfn) == 0x0a)) {
+			/*
+			 * Set top of main memory accessible by ISA or DMA
+			 * devices to 16 Mb.
+			 */
+			pci_read_config_byte(pdev, 0x69, &reg_val);
+			pci_write_config_byte(pdev, 0x69, reg_val | 0xf0);
+		}
+	}
+
+	/* 
+	 * Activate Floppy Controller in the SMSC FDC37M817 Super I/O 
+	 * Controller.
+	 * This should be done in the bios/bootprom and will be fixed in
+         * a later revision of YAMON (the MIPS boards boot prom).
+	 */
+	/* Entering config state. */
+	SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG); 
+       
+	/* Activate floppy controller. */
+	SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG);
+	SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG);
+	SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG);
+	SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG);
+
+	/* Exit config state. */
+	SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG);
+#endif
+}
+
+int __init
+pcibios_enable_device(struct pci_dev *dev)
+{
+	/* Not needed, since we enable all devices at startup.  */
+	return 0;
+}
+
+void __init
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+}
+
+char * __init
+pcibios_setup(char *str)
+{
+	/* Nothing to do for now.  */
+
+	return str;
+}
+
+struct pci_fixup pcibios_fixups[] = {
+	{ 0 }
+};
+
+void __init
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+                        struct resource *res, int resource)
+{
+	unsigned long where, size;
+	u32 reg;
+
+	where = PCI_BASE_ADDRESS_0 + (resource * 4);
+	size = res->end - res->start;
+	pci_read_config_dword(dev, where, &reg);
+	reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
+	pci_write_config_dword(dev, where, reg);
+}
+
+/*
+ *  Called after each bus is probed, but before its children
+ *  are examined.
+ */
+void __init pcibios_fixup_bus(struct pci_bus *b)
+{
+	pci_read_bridge_bases(b);
+}
+
+#endif /* CONFIG_PCI */
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/generic/printf.c linux/arch/mips/mips-boards/generic/printf.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/generic/printf.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/generic/printf.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,140 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/serial.h>
+
+
+#ifdef CONFIG_MIPS_ATLAS 
+/* 
+ * Atlas registers are memory mapped on 64-bit aligned boundaries and 
+ * only word access are allowed.
+ * When reading the UART 8 bit registers only the LSB are valid.
+ */
+unsigned int atlas_serial_in(struct async_struct *info, int offset)
+{
+	return (*(volatile unsigned int *)(info->port + mips_io_port_base + offset*8) & 0xff);
+}
+
+void atlas_serial_out(struct async_struct *info, int offset, int value)
+{
+	*(volatile unsigned int *)(info->port + mips_io_port_base + offset*8) = value;
+}
+
+#define serial_in  atlas_serial_in
+#define serial_out atlas_serial_out
+
+#else
+
+static unsigned int serial_in(struct async_struct *info, int offset)
+{
+	return inb(info->port + offset);
+}
+
+static void serial_out(struct async_struct *info, int offset,
+				int value)
+{
+	outb(value, info->port + offset);
+}
+#endif
+
+static struct serial_state rs_table[] = {
+	SERIAL_PORT_DFNS	/* Defined in serial.h */
+};
+
+/*
+ * Hooks to fake "prom" console I/O before devices 
+ * are fully initialized. 
+ */
+static struct async_struct prom_port_info = {0};
+
+void __init setup_prom_printf(int tty_no) {
+	struct serial_state *ser = &rs_table[tty_no];
+
+	prom_port_info.state = ser;
+	prom_port_info.magic = SERIAL_MAGIC;
+	prom_port_info.port = ser->port;
+	prom_port_info.flags = ser->flags;
+
+	/* No setup of UART - assume YAMON left in sane state */
+}
+
+int putPromChar(char c)
+{
+        if (!prom_port_info.state) { 	/* need to init device first */
+		return 0;
+	}
+
+	while ((serial_in(&prom_port_info, UART_LSR) & UART_LSR_THRE) == 0)
+		;
+
+	serial_out(&prom_port_info, UART_TX, c);
+
+	return 1;
+}
+
+char getPromChar(void)
+{
+	if (!prom_port_info.state) { 	/* need to init device first */
+		return 0;
+	}
+
+	while (!(serial_in(&prom_port_info, UART_LSR) & 1))
+		;
+
+	return(serial_in(&prom_port_info, UART_RX));
+}
+
+static char buf[1024];
+
+void __init prom_printf(char *fmt, ...)
+{
+	va_list args;
+	int l;
+	char *p, *buf_end;
+	long flags;
+
+	int putPromChar(char);
+
+	/* Low level, brute force, not SMP safe... */
+	save_and_cli(flags);
+	va_start(args, fmt);
+	l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */
+	va_end(args);
+
+	buf_end = buf + l;
+
+	for (p = buf; p < buf_end; p++) {
+		/* Crude cr/nl handling is better than none */
+		if(*p == '\n')putPromChar('\r');
+		putPromChar(*p);
+	}
+	restore_flags(flags);
+}
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/generic/reset.c linux/arch/mips/mips-boards/generic/reset.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/generic/reset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/generic/reset.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,72 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Reset the MIPS boards.
+ *
+ */
+#include <linux/config.h>
+
+#include <asm/reboot.h>
+#include <asm/mips-boards/generic.h>
+#if defined(CONFIG_MIPS_ATLAS)
+#include <asm/mips-boards/atlas.h>
+#endif
+
+static void mips_machine_restart(char *command);
+static void mips_machine_halt(void);
+#if defined(CONFIG_MIPS_ATLAS)
+static void atlas_machine_power_off(void);
+#endif
+
+static void mips_machine_restart(char *command)
+{
+        volatile unsigned int *softres_reg = (void *)SOFTRES_REG;
+
+	*softres_reg = GORESET;
+}
+
+static void mips_machine_halt(void)
+{
+        volatile unsigned int *softres_reg = (void *)SOFTRES_REG;
+
+	*softres_reg = GORESET;
+}
+
+#if defined(CONFIG_MIPS_ATLAS)
+static void atlas_machine_power_off(void)
+{
+        volatile unsigned int *psustby_reg = (void *)ATLAS_PSUSTBY_REG;
+
+	*psustby_reg = ATLAS_GOSTBY;
+}
+#endif
+
+void mips_reboot_setup(void)
+{
+	_machine_restart = mips_machine_restart;
+	_machine_halt = mips_machine_halt;
+#if defined(CONFIG_MIPS_ATLAS)
+	_machine_power_off = atlas_machine_power_off;
+#endif
+#if defined(CONFIG_MIPS_MALTA)
+	_machine_power_off = mips_machine_halt;
+#endif
+}
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/generic/time.c linux/arch/mips/mips-boards/generic/time.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/generic/time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/generic/time.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,410 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Setting up the clock on the MIPS boards.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/div64.h>
+
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+
+extern volatile unsigned long wall_jiffies;
+static long last_rtc_update = 0;
+unsigned long missed_heart_beats = 0;
+
+static unsigned long r4k_offset; /* Amount to increment compare reg each time */
+static unsigned long r4k_cur;    /* What counter should be at next timer irq */
+extern rwlock_t xtime_lock;
+
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+
+#if defined(CONFIG_MIPS_ATLAS)
+static char display_string[] = "        LINUX ON ATLAS       ";
+#endif
+#if defined(CONFIG_MIPS_MALTA)
+static char display_string[] = "        LINUX ON MALTA       ";
+#endif
+static unsigned int display_count = 0;
+#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) 
+
+static unsigned int timer_tick_count=0;
+
+
+static inline void ack_r4ktimer(unsigned long newval)
+{
+	write_32bit_cp0_register(CP0_COMPARE, newval);
+}
+
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you won't notice until after reboot!
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+ 		retval = -1;
+	}
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+	return retval;
+}
+
+/*
+ * There are a lot of conceptually broken versions of the MIPS timer interrupt
+ * handler floating around.  This one is rather different, but the algorithm
+ * is provably more robust.
+ */
+void mips_timer_interrupt(struct pt_regs *regs)
+{
+	int irq = 7;
+
+	if (r4k_offset == 0)
+		goto null;
+
+	do {
+		kstat.irqs[0][irq]++;
+		do_timer(regs);
+
+		/* Historical comment/code:
+ 		 * RTC time of day s updated approx. every 11 
+ 		 * minutes.  Because of how the numbers work out 
+ 		 * we need to make absolutely sure we do this update
+ 		 * within 500ms before the * next second starts, 
+ 		 * thus the following code.
+ 		 */
+		read_lock(&xtime_lock);
+		if ((time_status & STA_UNSYNC) == 0 
+		    && xtime.tv_sec > last_rtc_update + 660 
+		    && xtime.tv_usec >= 500000 - (tick >> 1) 
+		    && xtime.tv_usec <= 500000 + (tick >> 1))
+			if (set_rtc_mmss(xtime.tv_sec) == 0)
+				last_rtc_update = xtime.tv_sec;
+			else
+				/* do it again in 60 s */
+	    			last_rtc_update = xtime.tv_sec - 600; 
+		read_unlock(&xtime_lock);
+
+		if ((timer_tick_count++ % HZ) == 0) {
+		    mips_display_message(&display_string[display_count++]);
+		    if (display_count == MAX_DISPLAY_COUNT)
+		        display_count = 0;
+		}
+
+		r4k_cur += r4k_offset;
+		ack_r4ktimer(r4k_cur);
+
+	} while (((unsigned long)read_32bit_cp0_register(CP0_COUNT)
+	         - r4k_cur) < 0x7fffffff);
+
+	return;
+
+null:
+	ack_r4ktimer(0);
+}
+
+/* 
+ * Figure out the r4k offset, the amount to increment the compare
+ * register for each time tick. 
+ * Use the RTC to calculate offset.
+ */
+static unsigned long __init cal_r4koff(void)
+{
+	unsigned long count;
+	unsigned int flags;
+
+	__save_and_cli(flags);
+
+	/* Start counter exactly on falling edge of update flag */
+	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+	/* Start r4k counter. */
+	write_32bit_cp0_register(CP0_COUNT, 0);
+
+	/* Read counter exactly on falling edge of update flag */
+	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+	count = read_32bit_cp0_register(CP0_COUNT);
+
+	/* restore interrupts */
+	__restore_flags(flags);
+
+	return (count / HZ);
+}
+
+static unsigned long __init get_mips_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	unsigned char save_control;
+
+	save_control = CMOS_READ(RTC_CONTROL);
+
+	/* Freeze it. */
+	CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL);
+
+	/* Read regs. */
+	sec = CMOS_READ(RTC_SECONDS);
+	min = CMOS_READ(RTC_MINUTES);
+	hour = CMOS_READ(RTC_HOURS);
+
+	if (!(save_control & RTC_24H))
+	{
+		if ((hour & 0xf) == 0xc)
+		        hour &= 0x80;
+	        if (hour & 0x80)
+		        hour = (hour & 0xf) + 12;     
+	}
+	day = CMOS_READ(RTC_DAY_OF_MONTH);
+	mon = CMOS_READ(RTC_MONTH);
+	year = CMOS_READ(RTC_YEAR);
+
+	/* Unfreeze clock. */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+
+	if ((year += 1900) < 1970)
+	        year += 100;
+
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+void __init time_init(void)
+{
+        unsigned int est_freq, flags;
+
+        /* Set Data mode - binary. */ 
+        CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
+
+	printk("calculating r4koff... ");
+	r4k_offset = cal_r4koff();
+	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);
+
+	est_freq = 2*r4k_offset*HZ;	
+	est_freq += 5000;    /* round */
+	est_freq -= est_freq%10000;
+	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, 
+	       (est_freq%1000000)*100/1000000);
+	r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset);
+
+	write_32bit_cp0_register(CP0_COMPARE, r4k_cur);
+	change_cp0_status(ST0_IM, ALLINTS);
+
+	/* Read time from the RTC chipset. */
+	write_lock_irqsave (&xtime_lock, flags);
+	xtime.tv_sec = get_mips_time();
+	xtime.tv_usec = 0;
+	write_unlock_irqrestore(&xtime_lock, flags);
+}
+
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
+#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff)
+
+/* Cycle counter value at the previous timer interrupt.. */
+
+static unsigned int timerhi = 0, timerlo = 0;
+
+/*
+ * FIXME: Does playing with the RP bit in c0_status interfere with this code?
+ */
+static unsigned long do_fast_gettimeoffset(void)
+{
+	u32 count;
+	unsigned long res, tmp;
+
+	/* Last jiffy when do_fast_gettimeoffset() was called. */
+	static unsigned long last_jiffies=0;
+	unsigned long quotient;
+
+	/*
+	 * Cached "1/(clocks per usec)*2^32" value.
+	 * It has to be recalculated once each jiffy.
+	 */
+	static unsigned long cached_quotient=0;
+
+	tmp = jiffies;
+
+	quotient = cached_quotient;
+
+	if (tmp && last_jiffies != tmp) {
+		last_jiffies = tmp;
+#ifdef CONFIG_CPU_MIPS32
+		if (last_jiffies != 0) {
+			unsigned long r0;
+			do_div64_32(r0, timerhi, timerlo, tmp);
+			do_div64_32(quotient, USECS_PER_JIFFY,
+				    USECS_PER_JIFFY_FRAC, r0);
+			cached_quotient = quotient;
+		}
+#else
+		__asm__(".set\tnoreorder\n\t"
+			".set\tnoat\n\t"
+			".set\tmips3\n\t"
+			"lwu\t%0,%2\n\t"
+			"dsll32\t$1,%1,0\n\t"
+			"or\t$1,$1,%0\n\t"
+			"ddivu\t$0,$1,%3\n\t"
+			"mflo\t$1\n\t"
+			"dsll32\t%0,%4,0\n\t"
+			"nop\n\t"
+			"ddivu\t$0,%0,$1\n\t"
+			"mflo\t%0\n\t"
+			".set\tmips0\n\t"
+			".set\tat\n\t"
+			".set\treorder"
+			:"=&r" (quotient)
+			:"r" (timerhi),
+			 "m" (timerlo),
+			 "r" (tmp),
+			 "r" (USECS_PER_JIFFY)
+			:"$1");
+		cached_quotient = quotient;
+#endif
+	}
+
+	/* Get last timer tick in absolute kernel time */
+	count = read_32bit_cp0_register(CP0_COUNT);
+
+	/* .. relative to previous jiffy (32 bits is enough) */
+	count -= timerlo;
+
+	__asm__("multu\t%1,%2\n\t"
+		"mfhi\t%0"
+		:"=r" (res)
+		:"r" (count),
+		 "r" (quotient));
+
+	/*
+ 	 * Due to possible jiffies inconsistencies, we need to check 
+	 * the result so that we'll get a timer that is monotonic.
+	 */
+	if (res >= USECS_PER_JIFFY)
+		res = USECS_PER_JIFFY-1;
+
+	return res;
+}
+
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned int flags;
+
+	read_lock_irqsave (&xtime_lock, flags);
+	*tv = xtime;
+	tv->tv_usec += do_fast_gettimeoffset();
+
+	/*
+	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
+	 * is nonzero if the timer bottom half hasnt executed yet.
+	 */
+	if (jiffies - wall_jiffies)
+		tv->tv_usec += USECS_PER_JIFFY;
+
+	read_unlock_irqrestore (&xtime_lock, flags);
+
+	if (tv->tv_usec >= 1000000) {
+		tv->tv_usec -= 1000000;
+		tv->tv_sec++;
+	}
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+	write_lock_irq (&xtime_lock);
+
+	/* This is revolting. We need to set the xtime.tv_usec correctly.
+	 * However, the value in this location is is value at the last tick.
+	 * Discover what correction gettimeofday would have done, and then
+	 * undo it!
+	 */
+	tv->tv_usec -= do_fast_gettimeoffset();
+
+	if (tv->tv_usec < 0) {
+		tv->tv_usec += 1000000;
+		tv->tv_sec--;
+	}
+
+	xtime = *tv;
+	time_adjust = 0;		/* stop active adjtime() */
+	time_status |= STA_UNSYNC;
+	time_maxerror = NTP_PHASE_LIMIT;
+	time_esterror = NTP_PHASE_LIMIT;
+
+	write_unlock_irq (&xtime_lock);
+}
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/malta/Makefile linux/arch/mips/mips-boards/malta/Makefile
--- linux-2.4.4-pre3/arch/mips/mips-boards/malta/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/malta/Makefile	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,40 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+#
+# ########################################################################
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+# 
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+# 
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# #######################################################################
+#
+# Makefile for the MIPS Malta specific kernel interface routines
+# under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+O_TARGET := malta.o
+
+obj-y := malta_int.o malta_rtc.o malta_setup.o
+
+include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/malta/malta_int.c linux/arch/mips/mips-boards/malta/malta_int.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/malta/malta_int.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/malta/malta_int.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,378 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Routines for generic manipulation of the interrupts found on the MIPS 
+ * Malta board.
+ * The interrupt controller is located in the South Bridge a PIIX4 device 
+ * with two internal 82C95 interrupt controllers.
+ */
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/random.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mips-boards/malta.h>
+#include <asm/mips-boards/maltaint.h>
+#include <asm/mips-boards/piix4.h>
+#include <asm/gt64120.h>
+#include <asm/mips-boards/generic.h>
+
+extern asmlinkage void mipsIRQ(void);
+
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+unsigned long spurious_count = 0;
+
+static struct irqaction *hw0_irq_action[MALTAINT_END] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL
+};
+
+static struct irqaction r4ktimer_action = {
+	NULL, 0, 0, "R4000 timer/counter", NULL, NULL,
+};
+
+static struct irqaction *irq_action[8] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, &r4ktimer_action
+};
+
+#if 0
+#define DEBUG_INT(x...) printk(x)
+#else
+#define DEBUG_INT(x...)
+#endif
+
+/*
+ * This contains the interrupt mask for both 82C59 interrupt controllers.
+ */
+static unsigned int cached_int_mask = 0xffff;
+
+
+void disable_irq(unsigned int irq_nr)
+{
+        unsigned long flags;
+
+	if(irq_nr >= MALTAINT_END) {
+		printk("whee, invalid irq_nr %d\n", irq_nr);
+		panic("IRQ, you lose...");
+	}
+
+	save_and_cli(flags);
+	cached_int_mask |= (1 << irq_nr);
+	if (irq_nr & 8) {
+	        outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1);
+	} else {
+		outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1);
+	}
+	restore_flags(flags);
+}
+
+
+void enable_irq(unsigned int irq_nr)
+{
+        unsigned long flags;
+
+	if(irq_nr >= MALTAINT_END) {
+		printk("whee, invalid irq_nr %d\n", irq_nr);
+		panic("IRQ, you lose...");
+	}
+
+	save_and_cli(flags);
+	cached_int_mask &= ~(1 << irq_nr);
+	if (irq_nr & 8) {
+		outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1);
+
+		/* Enable irq 2 (cascade interrupt). */
+	        cached_int_mask &= ~(1 << 2); 
+		outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1);
+	} else {
+		outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1);
+	}	
+	restore_flags(flags);
+}
+
+
+int get_irq_list(char *buf)
+{
+	int i, len = 0;
+	int num = 0;
+	struct irqaction *action;
+
+	for (i = 0; i < 8; i++, num++) {
+		action = irq_action[i];
+		if (!action) 
+			continue;
+		len += sprintf(buf+len, "%2d: %8d %c %s",
+			num, kstat.irqs[0][num],
+			(action->flags & SA_INTERRUPT) ? '+' : ' ',
+			action->name);
+		for (action=action->next; action; action = action->next) {
+			len += sprintf(buf+len, ",%s %s",
+				(action->flags & SA_INTERRUPT) ? " +" : "",
+				action->name);
+		}
+		len += sprintf(buf+len, " [on-chip]\n");
+	}
+	for (i = 0; i < MALTAINT_END; i++, num++) {
+		action = hw0_irq_action[i];
+		if (!action) 
+			continue;
+		len += sprintf(buf+len, "%2d: %8d %c %s",
+			num, kstat.irqs[0][num],
+			(action->flags & SA_INTERRUPT) ? '+' : ' ',
+			action->name);
+		for (action=action->next; action; action = action->next) {
+			len += sprintf(buf+len, ",%s %s",
+				(action->flags & SA_INTERRUPT) ? " +" : "",
+				action->name);
+		}
+		len += sprintf(buf+len, " [hw0]\n");
+	}
+	return len;
+}
+
+
+static int setup_irq(unsigned int irq, struct irqaction * new)
+{
+	int shared = 0;
+	struct irqaction *old, **p;
+
+	p = &hw0_irq_action[irq];
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ))
+			return -EBUSY;
+
+		/* Can't share interrupts unless both are same type */
+		if ((old->flags ^ new->flags) & SA_INTERRUPT)
+			return -EBUSY;
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	if (new->flags & SA_SAMPLE_RANDOM)
+		rand_initialize_irq(irq);
+
+	*p = new;
+	if (!shared)
+		enable_irq(irq);
+
+	return 0;
+}
+
+int request_irq(unsigned int irq, 
+		void (*handler)(int, void *, struct pt_regs *),
+		unsigned long irqflags, 
+		const char * devname,
+		void *dev_id)
+{  
+        struct irqaction *action;
+	int retval;
+
+	DEBUG_INT("request_irq: irq=%d, devname = %s\n", irq, devname);
+
+        if (irq >= MALTAINT_END)
+	        return -EINVAL;
+	if (!handler)
+	        return -EINVAL;
+
+	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if(!action)
+	        return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	action->mask = 0;
+	action->name = devname;
+	action->dev_id = dev_id;
+	action->next = 0;
+
+	retval = setup_irq(irq, action);
+	if (retval)
+		kfree(action);
+
+	return retval;	
+}
+
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+	struct irqaction *action, **p;
+
+	if (irq >= MALTAINT_END) {
+		printk("Trying to free IRQ%d\n",irq);
+		return;
+	}
+	
+	for (p = &hw0_irq_action[irq]; (action = *p) != NULL; 
+	     p = &action->next) 
+	{
+		if (action->dev_id != dev_id)
+			continue;
+
+		/* Found it - now free it */
+		*p = action->next;
+		kfree(action);
+		if (!hw0_irq_action[irq])
+			disable_irq(irq);
+		return;
+	}
+	printk("Trying to free IRQ%d\n",irq);
+}
+
+void __init init_IRQ(void)
+{
+	irq_setup();
+}
+
+static inline int get_int(int *irq)
+{
+	/*  
+	 * Determine highest priority pending interrupt by performing
+         * a PCI Interrupt Acknowledge cycle.
+	 */
+	GT_READ(GT_PCI0_IACK_OFS, *irq);
+	*irq &= 0xFF;
+
+	/*  
+	 * IRQ7 is used to detect spurious interrupts.
+	 * The interrupt acknowledge cycle returns IRQ7, if no 
+	 * interrupts is requested.
+	 * We can differentiate between this situation and a
+	 * "Normal" IRQ7 by reading the ISR.
+	 */
+	if (*irq == 7) 
+	{
+		outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR, PIIX4_ICTLR1_OCW3);
+		if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7)))
+		        return -1;    /* Spurious interrupt. */
+	}
+
+	return 0;
+}
+
+static inline void ack_int(int irq)
+{
+	if (irq & 8) {
+	        /* Specific EOI to cascade */
+		outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI | PIIX4_OCW2_ILS_2, 
+		     PIIX4_ICTLR1_OCW2);
+
+	        /* Non specific EOI to cascade */
+		outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI, PIIX4_ICTLR2_OCW2);
+	} else {
+	        /* Non specific EOI to cascade */
+		outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI, PIIX4_ICTLR1_OCW2);
+	}
+}
+
+void malta_hw0_irqdispatch(struct pt_regs *regs)
+{
+        struct irqaction *action;
+	int irq=0, cpu = smp_processor_id();
+
+	DEBUG_INT("malta_hw0_irqdispatch\n");
+	
+	if (get_int(&irq))
+	        return;  /* interrupt has already been cleared */
+
+	disable_irq(irq);
+	ack_int(irq);
+
+	DEBUG_INT("malta_hw0_irqdispatch: irq=%d\n", irq);
+	action = hw0_irq_action[irq];
+
+	/* 
+	 * if action == NULL, then we don't have a handler 
+	 * for the irq 
+	 */
+	if ( action == NULL )
+		return;
+
+	irq_enter(cpu, irq);
+	kstat.irqs[0][irq + 8]++;
+	do {
+	        action->handler(irq, action->dev_id, regs);
+		action = action->next;
+	} while (action);
+
+	enable_irq(irq);
+	irq_exit(cpu, irq);
+}
+
+
+unsigned long probe_irq_on (void)
+{
+	unsigned int i, irqs = 0;
+	unsigned long delay;
+
+	/* first, enable any unassigned irqs */
+	for (i = MALTAINT_END-1; i > 0; i--) {
+		if (!hw0_irq_action[i]) {
+			enable_irq(i);
+			irqs |= (1 << i);
+		}
+	}
+
+	/* wait for spurious interrupts to mask themselves out again */
+	for (delay = jiffies + HZ/10; time_before(jiffies, delay); )
+		/* about 100ms delay */;
+
+	/* now filter out any obviously spurious interrupts */
+	return irqs & ~cached_int_mask;
+}
+
+
+int probe_irq_off (unsigned long irqs)
+{
+	unsigned int i;
+
+	irqs &= cached_int_mask;
+	if (!irqs)
+		return 0;
+	i = ffz(~irqs);
+	if (irqs != (irqs & (1 << i)))
+		i = -i;
+
+	return i;
+}
+
+
+void __init maltaint_init(void)
+{
+        /* 
+	 * Mask out all interrupt by writing "1" to all bit position in 
+	 * the IMR register. 
+	 */
+	outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1);
+	outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1);
+
+	/* Now safe to set the exception vector. */
+	set_except_vector(0, mipsIRQ);
+}
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/malta/malta_rtc.c linux/arch/mips/mips-boards/malta/malta_rtc.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/malta/malta_rtc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/malta/malta_rtc.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,51 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * RTC routines for Malta style attached PIIX4 device, which contains a
+ * Motorola MC146818A-compatible Real Time Clock.
+ *
+ */
+#include <linux/spinlock.h>
+#include <linux/mc146818rtc.h>
+#include <asm/mips-boards/malta.h>
+
+static unsigned char malta_rtc_read_data(unsigned long addr)
+{
+	outb(addr, MALTA_RTC_ADR_REG);
+	return inb(MALTA_RTC_DAT_REG);
+}
+
+static void malta_rtc_write_data(unsigned char data, unsigned long addr)
+{
+	outb(addr, MALTA_RTC_ADR_REG);
+	outb(data, MALTA_RTC_DAT_REG);
+}
+
+static int malta_rtc_bcd_mode(void)
+{
+	return 0;
+}
+
+struct rtc_ops malta_rtc_ops = {
+	&malta_rtc_read_data,
+	&malta_rtc_write_data,
+	&malta_rtc_bcd_mode
+};
diff -urN linux-2.4.4-pre3/arch/mips/mips-boards/malta/malta_setup.c linux/arch/mips/mips-boards/malta/malta_setup.c
--- linux-2.4.4-pre3/arch/mips/mips-boards/malta/malta_setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/mips-boards/malta/malta_setup.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,159 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Malta specific setup, including init of the feature struct.
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mc146818rtc.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#ifdef CONFIG_BLK_DEV_IDE
+#include <linux/ide.h>
+#endif
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/malta.h>
+#include <asm/mips-boards/maltaint.h>
+#ifdef CONFIG_BLK_DEV_FD
+#include <asm/floppy.h>
+#endif
+#include <asm/dma.h>
+
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
+extern void console_setup(char *, int *);
+char serial_console[20];
+#endif
+
+#ifdef CONFIG_REMOTE_DEBUG
+extern void set_debug_traps(void);
+extern void rs_kgdb_hook(int);
+extern void breakpoint(void);
+static int remote_debug = 0;
+#endif
+
+#ifdef CONFIG_BLK_DEV_IDE
+extern struct ide_ops std_ide_ops;
+#endif
+#ifdef CONFIG_BLK_DEV_FD
+extern struct fd_ops std_fd_ops;
+#endif
+extern struct rtc_ops malta_rtc_ops;
+
+extern void mips_reboot_setup(void);
+
+struct resource standard_io_resources[] = {
+	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
+	{ "pic1", 0x20, 0x3f, IORESOURCE_BUSY },
+	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
+	{ "pic2", 0xa0, 0xbf, IORESOURCE_BUSY },
+	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+};
+
+#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
+
+static void __init malta_irq_setup(void)
+{
+  	maltaint_init();
+
+#ifdef CONFIG_REMOTE_DEBUG
+	if (remote_debug) {
+		set_debug_traps();
+		breakpoint(); 
+	}
+#endif
+}
+
+
+void __init malta_setup(void)
+{
+#ifdef CONFIG_REMOTE_DEBUG
+	int rs_putDebugChar(char);
+	char rs_getDebugChar(void);
+	extern int (*putDebugChar)(char);
+	extern char (*getDebugChar)(void);
+#endif
+	char *argptr;
+	int i;
+
+	irq_setup = malta_irq_setup;
+
+	/* Request I/O space for devices used on the Malta board. */
+	for (i = 0; i < STANDARD_IO_RESOURCES; i++)
+		request_resource(&ioport_resource, standard_io_resources+i);
+
+	/* 
+	 * Enable DMA channel 4 (cascade channel) in the PIIX4 south bridge.
+	 */
+	enable_dma(4);
+
+#ifdef CONFIG_SERIAL_CONSOLE
+	argptr = prom_getcmdline();
+	if ((argptr = strstr(argptr, "console=")) == NULL) {
+		argptr = prom_getcmdline();
+		strcat(argptr, " console=ttyS0,38400");
+	}
+#endif
+
+#ifdef CONFIG_REMOTE_DEBUG
+	argptr = prom_getcmdline();
+	if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
+		int line;
+		argptr += strlen("kgdb=ttyS");
+		if (*argptr != '0' && *argptr != '1')
+			printk("KGDB: Uknown serial line /dev/ttyS%c, "
+			       "falling back to /dev/ttyS1\n", *argptr);
+		line = *argptr == '0' ? 0 : 1;
+		printk("KGDB: Using serial line /dev/ttyS%d for session\n",
+		       line ? 1 : 0);
+
+		rs_kgdb_hook(line);
+		putDebugChar = rs_putDebugChar;
+		getDebugChar = rs_getDebugChar;
+
+		prom_printf("KGDB: Using serial line /dev/ttyS%d for session, "
+			    "please connect your debugger\n", line ? 1 : 0);
+
+		remote_debug = 1;
+		/* Breakpoints and stuff are in malta_irq_setup() */
+	}
+#endif
+
+	argptr = prom_getcmdline();
+	if ((argptr = strstr(argptr, "nofpu")) != NULL)
+		mips_cpu.options &= ~MIPS_CPU_FPU;
+		
+	rtc_ops = &malta_rtc_ops;
+#ifdef CONFIG_BLK_DEV_IDE
+        ide_ops = &std_ide_ops;
+#endif
+#ifdef CONFIG_BLK_DEV_FD
+        fd_ops = &std_fd_ops;
+#endif
+	mips_reboot_setup();
+}
diff -urN linux-2.4.4-pre3/arch/mips/mm/Makefile linux/arch/mips/mm/Makefile
--- linux-2.4.4-pre3/arch/mips/mm/Makefile	Thu Feb 24 22:52:30 2000
+++ linux/arch/mips/mm/Makefile	Mon Dec  3 22:35:22 2001
@@ -8,34 +8,20 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := mm.o
-O_OBJS	 := extable.o init.o fault.o loadmmu.o
 
-ifdef CONFIG_CPU_R3000
-O_OBJS   += r2300.o
-endif
+export-objs			+= umap.o
+obj-y				+= extable.o init.o fault.o loadmmu.o
 
-ifdef CONFIG_CPU_R4300
-O_OBJS   += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_R4X00
-O_OBJS   += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_R5000
-O_OBJS   += r4xx0.o
-endif
-
-ifdef CONFIG_CPU_NEVADA
-O_OBJS   += r4xx0.o
-endif
-
-ifdef CONFIG_SGI_IP22
-O_OBJS   += umap.o
-endif
-
-ifdef CONFIG_BAGET_MIPS
-O_OBJS   += umap.o
-endif
+obj-$(CONFIG_CPU_R3000)		+= r2300.o
+obj-$(CONFIG_CPU_R3912)		+= r2300.o
+obj-$(CONFIG_CPU_R4300)		+= r4xx0.o
+obj-$(CONFIG_CPU_R4X00)		+= r4xx0.o
+obj-$(CONFIG_CPU_R5000)		+= r4xx0.o
+obj-$(CONFIG_CPU_NEVADA)	+= r4xx0.o
+obj-$(CONFIG_CPU_R5432)		+= r5432.o
+obj-$(CONFIG_CPU_RM7000)	+= rm7k.o
+obj-$(CONFIG_CPU_MIPS32)	+= mips32.o
+obj-$(CONFIG_SGI_IP22)		+= umap.o
+obj-$(CONFIG_BAGET_MIPS)	+= umap.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/orion/Makefile linux/arch/mips/orion/Makefile
--- linux-2.4.4-pre3/arch/mips/orion/Makefile	Tue Jul 11 11:14:48 2000
+++ linux/arch/mips/orion/Makefile	Wed Dec 31 16:00:00 1969
@@ -1,48 +0,0 @@
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License.  See the file "COPYING" in the main directory of this archive
-# for more details.
-#
-#
-# Produce a bootimage for the IPSX
-#  Copyright (C) 2000 Cort Dougan <cort@fsmlabs.com>
-#
-
-.S.s:
-	$(CPP) $(CFLAGS) $< -o $*.s
-.S.o:
-	$(CC) $(CFLAGS) -c $< -o $*.o
-
-OBJS = promcon.o char.o serial.8530.o orion.hw.init.o setup.o irq.o int-handler.o
-
-all: orionkern.a
-
-orionkern.a: $(OBJS) initrd.o #no_initrd.o
-	$(AR) rcs orionkern.a $(OBJS) initrd.o #no_initrd.o
-	sync
-
-initrd.c: piggyback ramdisk.image.gz
-	./piggyback initrd < ramdisk.image.gz > initrd.c
-
-piggyback: piggyback.c
-	$(HOSTCC) $(HOSTCFLAGS) -o piggyback piggyback.c
-
-orionboot: orion.ctl
-
-patchapp: patchapp.c
-	$(HOSTCC) -o $@ $^
-
-orion.ctl: patchapp ../../../vmlinux
-	$(OBJCOPY) -Obinary ../../../vmlinux orion.nosym
-	./patchapp orion.nosym orion
-	cp -f orion.bin orion.ctl
-
-# Don't build dependencies, this may die if $(CC) isn't gcc
-dep:
-
-clean:
-	rm -f patchapp orion.bin orion.nosym orion.ctl initrd.c
-
-dummy:
-
-include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/orion/int-handler.S linux/arch/mips/orion/int-handler.S
--- linux-2.4.4-pre3/arch/mips/orion/int-handler.S	Tue Jul 11 11:14:48 2000
+++ linux/arch/mips/orion/int-handler.S	Wed Dec 31 16:00:00 1969
@@ -1,53 +0,0 @@
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-	.text
-	.set    mips1
-	.set    reorder
-	.set    macro
-	.set    noat
-	.align	5
-
-NESTED(orionIRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI				# Important: mark KERNEL mode !
-	/*
-	 * Get pending interrupts
-	 */
-	mfc0	t0,CP0_CAUSE		# get pending interrupts
-	mfc0	t1,CP0_STATUS		# get enabled interrupts
-	and	t0,t1			# isolate allowed ones
-	andi	t0,0xff00		# isolate pending bits
-	sll	t0,16			# shift the pending bits down
-	beqz	t0,3f			# no pending intrs, then spurious
-	nop				# delay slot
-	
-	/*
-	 * Find irq with highest priority
-	 * FIXME: This is slow - use binary search
-	 */
-	la	a0,7
-1:	bltz	t0,2f			# found pending irq
-	subu	a0,1
-	sll	t0,1
-	b	1b
-	nop				# delay slot
-
-call_do_IRQ:
-2:	move	a1,sp
-	jal	do_IRQ
-	nop				# delay slot
-
-	mfc0	t0,CP0_STATUS		# disable interrupts
-	ori	t0,1
-	xori	t0,1
-	mtc0	t0,CP0_STATUS
-	
-	la      a1, ret_from_irq
-	jr	a1
-	
-3:	j	spurious_interrupt
-END(orionIRQ)
-
diff -urN linux-2.4.4-pre3/arch/mips/orion/irq.c linux/arch/mips/orion/irq.c
--- linux-2.4.4-pre3/arch/mips/orion/irq.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/mips/orion/irq.c	Wed Dec 31 16:00:00 1969
@@ -1,281 +0,0 @@
-/*
- * Code to handle irqs on Orion boards
- *  -- Cort <cort@fsmlabs.com>
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-
-#include <asm/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-#include <asm/orion.h>
-
-void (*board_time_init)(struct irqaction *irq);
-extern asmlinkage void orionIRQ(void);
-unsigned long spurious_count = 0;
-irq_desc_t irq_desc[NR_IRQS];
-
-static void galileo_ack(unsigned int irq_nr)
-{
-	*((unsigned long *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0xC18) ) = (((( 0 )&0xff)<<24)+	((( 0 )&0xff00)<<8)+	((( 0 )&0xff0000)>>8)+	((( 0 )&0xff000000)>>24))  ;
-}
-
-struct hw_interrupt_type galileo_pic = {
-        " Galileo  ",
-        NULL,
-        NULL,
-        NULL, /* unmask_irq */
-        NULL, /* mask_irq */
-        galileo_ack, /* mask_and_ack */
-        0
-};
-
-/* Function for careful CP0 interrupt mask access */
-static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
-{
-	unsigned long status = read_32bit_cp0_register(CP0_STATUS);
-	status &= ~((clr_mask & 0xFF) << 8);
-	status |=   (set_mask & 0xFF) << 8;
-	write_32bit_cp0_register(CP0_STATUS, status);
-}
-
-static inline void mask_irq(unsigned int irq_nr)
-{
-        modify_cp0_intmask(irq_nr, 0);
-}
-
-static inline void unmask_irq(unsigned int irq_nr)
-{
-	modify_cp0_intmask(0, irq_nr);
-}
-
-void disable_irq(unsigned int irq_nr)
-{
-	unsigned long flags;
-
-	save_and_cli(flags);
-	mask_irq(irq_nr);
-	restore_flags(flags);
-}
-
-void enable_irq(unsigned int irq_nr)
-{
-	unsigned long flags;
-
-	save_and_cli(flags);
-	unmask_irq(irq_nr);
-	restore_flags(flags);
-}
-
-/*static struct irqaction *irq_action[NR_IRQS] = {
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
-*/
-void __init orion_time_init(struct irqaction *irq)
-{
-	__u32 timer_count;
-	
-	irq_desc[2].handler = &galileo_pic;
-	irq_desc[2].action = irq;
-	
-	/* This code was provided by the CoSine guys and despite its
-	 * appearance init's the timer.
-	 * -- Cort
-	 */
-	*((__u32 *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0x864) ) = (((( 0 )&0xff)<<24)+	((( 0 )&0xff00)<<8)+	((( 0 )&0xff0000)>>8)+	((( 0 )&0xff000000)>>24)) ;
-	
-	*((__u32 *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0x850) ) = (((( 0 )&0xff)<<24)+	((( 0 )&0xff00)<<8)+	((( 0 )&0xff0000)>>8)+	((( 0 )&0xff000000)>>24)) ;
-
-        timer_count = 300000000/100;
-	
-	*((__u32 *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0x850) ) = ((((  timer_count  )&0xff)<<24)+	(((  timer_count  )&0xff00)<<8)+	(((  timer_count  )&0xff0000)>>8)+	(((  timer_count  )&0xff000000)>>24))  ;
-
-	*((__u32 *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0xC1C) ) = ((((  0x100   )&0xff)<<24)+	(((  0x100   )&0xff00)<<8)+	(((  0x100   )&0xff0000)>>8)+	(((  0x100   )&0xff000000)>>24))  ;
-     
-	*((__u32 *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0x864) ) = ((((  0x03  )&0xff)<<24)+	(((  0x03  )&0xff00)<<8)+	(((  0x03  )&0xff0000)>>8)+	(((  0x03  )&0xff000000)>>24))  ;
-     
-	*((__u32 *) (((unsigned)( 0x14000000  )|0xA0000000)   + 0xC18) ) = (((( 0 )&0xff)<<24)+	((( 0 )&0xff00)<<8)+	((( 0 )&0xff0000)>>8)+	((( 0 )&0xff000000)>>24))  ;
-}
-
-int get_irq_list(char *buf)
-{
-	int i, len = 0, j;
-	struct irqaction * action;
-
-	len += sprintf(buf+len, "           ");
-	for (j=0; j<smp_num_cpus; j++)
-		len += sprintf(buf+len, "CPU%d       ",j);
-	*(char *)(buf+len++) = '\n';
-
-	for (i = 0 ; i < NR_IRQS ; i++) {
-		action = irq_desc[i].action;
-		if ( !action || !action->handler )
-			continue;
-		len += sprintf(buf+len, "%3d: ", i);		
-		len += sprintf(buf+len, "%10u ", kstat_irqs(i));
-		if ( irq_desc[i].handler )		
-			len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename );
-		else
-			len += sprintf(buf+len, "  None      ");
-		len += sprintf(buf+len, "    %s",action->name);
-		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ", %s", action->name);
-		}
-		len += sprintf(buf+len, "\n");
-	}
-	len += sprintf(buf+len, "BAD: %10lu\n", spurious_count);
-	return len;
-}
-
-asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
-{
-	struct irqaction *action;
-	int do_random, cpu;
-	int status;
-
-	cpu = smp_processor_id();
-	irq_enter(cpu);
-	kstat.irqs[cpu][irq]++;
-	status = 0;
-
-	if (irq_desc[irq].handler->ack)
-		irq_desc[irq].handler->ack(irq);
-	
-	action = irq_desc[irq].action;
-	if (action && action->handler)
-	{
-		if (!(action->flags & SA_INTERRUPT))
-			__sti();
-		do { 
-			status |= action->flags;
-			action->handler(irq, action->dev_id, regs);
-			action = action->next;
-		} while ( action );
-		__cli();
-		if (irq_desc[irq].handler)
-		{
-			if (irq_desc[irq].handler->end)
-				irq_desc[irq].handler->end(irq);
-			else if (irq_desc[irq].handler->enable)
-				irq_desc[irq].handler->enable(irq);
-		}
-	}
-
-	irq_exit(cpu);
-
-	if (softirq_active(cpu)&softirq_mask(cpu))
-		do_softirq();
-
-	/* unmasking and bottom half handling is done magically for us. */
-}
-
-int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-	unsigned long irqflags, const char * devname, void *dev_id)
-{
-	struct irqaction *old, **p, *action;
-	unsigned long flags;
-
-	if (irq >= NR_IRQS)
-		return -EINVAL;
-	if (!handler)
-	{
-		/* Free */
-		for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next)
-		{
-			/* Found it - now free it */
-			save_flags(flags);
-			cli();
-			*p = action->next;
-			restore_flags(flags);
-			kfree(action);
-			return 0;
-		}
-		return -ENOENT;
-	}
-	
-	action = (struct irqaction *)
-		kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-	if (!action)
-		return -ENOMEM;
-	
-	save_flags(flags);
-	cli();
-	
-	action->handler = handler;
-	action->flags = irqflags;					
-	action->mask = 0;
-	action->name = devname;
-	action->dev_id = dev_id;
-	action->next = NULL;
-	enable_irq(irq);
-	
-	p = &irq_desc[irq].action;
-	
-	if ((old = *p) != NULL) {
-		/* Can't share interrupts unless both agree to */
-		if (!(old->flags & action->flags & SA_SHIRQ))
-			return -EBUSY;
-		/* add new interrupt at end of irq queue */
-		do {
-			p = &old->next;
-			old = *p;
-		} while (old);
-	}
-	*p = action;
-
-	restore_flags(flags);	
-	return 0;
-}
-		
-void free_irq(unsigned int irq, void *dev_id)
-{
-	request_irq(irq, NULL, 0, NULL, dev_id);
-}
-
-
-unsigned long probe_irq_on (void)
-{
-	return 0;
-}
-
-int probe_irq_off (unsigned long irqs)
-{
-	return 0;
-}
-
-int (*irq_cannonicalize)(int irq);
-
-int orion_irq_cannonicalize(int i)
-{
-	return i;
-}
-
-void __init init_IRQ(void)
-{
-	
-	irq_cannonicalize = orion_irq_cannonicalize;
-	set_except_vector(0, orionIRQ);
-}
-
-EXPORT_SYMBOL(irq_cannonicalize);
-
diff -urN linux-2.4.4-pre3/arch/mips/orion/ld.script.orion linux/arch/mips/orion/ld.script.orion
--- linux-2.4.4-pre3/arch/mips/orion/ld.script.orion	Tue Jul 11 11:14:48 2000
+++ linux/arch/mips/orion/ld.script.orion	Wed Dec 31 16:00:00 1969
@@ -1,113 +0,0 @@
-OUTPUT_FORMAT("elf32-bigmips")
-OUTPUT_ARCH(mips)
-ENTRY(kernel_entry)
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  . = 0x80100000;
-  /* app_header is needed for the Orion bootloader -- Cort */
-  .app_header	:	{ *(.app_header) }
-  .init          : { *(.init)		} =0
-  .text      :
-  {
-    _ftext = . ;
-    *(.text)
-    *(.rodata)
-    *(.rodata1)
-    /* .gnu.warning sections are handled specially by elf32.em.  */
-    *(.gnu.warning)
-  } =0
-  _etext = .;
-  PROVIDE (etext = .);
-
-  . = ALIGN(8192);
-  .data.init_task : { *(.data.init_task) }
-
-  /* Startup code */
-  . = ALIGN(4096);
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { *(.setup.init) }
-  __setup_end = .;
-  __initcall_start = .;
-  .initcall.init : { *(.initcall.init) }
-  __initcall_end = .;
-  . = ALIGN(4096);	/* Align double page for init_task_union */
-  __init_end = .;
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  .fini      : { *(.fini)    } =0
-  .reginfo : { *(.reginfo) }
-  /* Adjust the address for the data segment.  We want to adjust up to
-     the same address within the page on the next page up.  It would
-     be more correct to do this:
-       . = .;
-     The current expression does not correctly handle the case of a
-     text segment ending precisely at the end of a page; it causes the
-     data segment to skip a page.  The above expression does not have
-     this problem, but it will currently (2/95) cause BFD to allocate
-     a single segment, combining both text and data, for this case.
-     This will prevent the text segment from being shared among
-     multiple executions of the program; I think that is more
-     important than losing a page of the virtual address space (note
-     that no actual memory is lost; the page which is skipped can not
-     be referenced).  */
-  . = .;
-  .data    :
-  {
-    _fdata = . ;
-    *(.data)
-    CONSTRUCTORS
-  }
-  .data1   : { *(.data1) }
-  _gp = . + 0x8000;
-  .lit8 : { *(.lit8) }
-  .lit4 : { *(.lit4) }
-  .ctors         : { *(.ctors)   }
-  .dtors         : { *(.dtors)   }
-  .got           : { *(.got.plt) *(.got) }
-  .dynamic       : { *(.dynamic) }
-  /* We want the small data sections together, so single-instruction offsets
-     can access them all, and initialized data all before uninitialized, so
-     we can shorten the on-disk segment size.  */
-  .sdata     : { *(.sdata) }
-  _edata  =  .;
-  PROVIDE (edata = .);
-
-  __bss_start = .;
-  _fbss = .;
-  .sbss      : { *(.sbss) *(.scommon) }
-  .bss       :
-  {
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  _end = . ;
-  PROVIDE (end = .);
-  }
-  /* These are needed for ELF backends which have not yet been
-     converted to the new style linker.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  /* DWARF debug sections.
-     Symbols in the .debug DWARF section are relative to the beginning of the
-     section so we begin .debug at 0.  It's not clear yet what needs to happen
-     for the others.   */
-  .debug          0 : { *(.debug) }
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  .line           0 : { *(.line) }
-  /* These must appear regardless of  .  */
-  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
-  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
-}
diff -urN linux-2.4.4-pre3/arch/mips/orion/misc.c linux/arch/mips/orion/misc.c
--- linux-2.4.4-pre3/arch/mips/orion/misc.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/mips/orion/misc.c	Wed Dec 31 16:00:00 1969
@@ -1,100 +0,0 @@
-/*
- * Catch-all for Orion-specify code that doesn't fit easily elsewhere.
- *   -- Cort
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/hdreg.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/utsname.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#ifdef CONFIG_BLK_DEV_RAM
-#include <linux/blk.h>
-#endif
-#include <linux/ide.h>
-#ifdef CONFIG_RTC
-#include <linux/timex.h>
-#endif
-
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/io.h>
-#include <asm/stackframe.h>
-#include <asm/system.h>
-#include <asm/cpu.h>
-#include <linux/bootmem.h>
-#include <asm/addrspace.h>
-#include <asm/mc146818rtc.h>
-
-char arcs_cmdline[CL_SIZE] = {0, };
-extern int _end;
-
-static unsigned char orion_rtc_read_data(unsigned long addr)
-{
-	return 0;
-}
-
-static void orion_rtc_write_data(unsigned char data, unsigned long addr)
-{
-}
-
-static int orion_rtc_bcd_mode(void)
-{
-	return 0;
-}
-
-struct rtc_ops orion_rtc_ops = {
-	&orion_rtc_read_data,
-	&orion_rtc_write_data,
-	&orion_rtc_bcd_mode
-};
-
-extern void InitCIB(void);
-extern void InitQpic(void);
-extern void InitCupid(void);
-
-void __init orion_setup(void)
-{
-	InitCIB();
-	InitQpic();
-	InitCupid();
-}
-
-#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_ALIGN(x)	(((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
-
-
-int orion_sysinit(void)
-{
-	unsigned long mem_size, free_start, free_end, start_pfn, bootmap_size;
-	
-	mips_machgroup = MACH_GROUP_ORION;
-	/* 64 MB non-upgradable */
-	mem_size = 32 << 20;
-	
-	free_start = PHYSADDR(PFN_ALIGN(&_end));
-	free_end = mem_size;
-	start_pfn = PFN_UP((unsigned long)&_end);
-	
-	/* Register all the contiguous memory with the bootmem allocator
-	   and free it.  Be careful about the bootmem freemap.  */
-	bootmap_size = init_bootmem(start_pfn, mem_size >> PAGE_SHIFT);
-	
-	/* Free the entire available memory after the _end symbol.  */
-	free_start += bootmap_size;
-	free_bootmem(free_start, free_end-free_start);
-}
diff -urN linux-2.4.4-pre3/arch/mips/orion/no_initrd.c linux/arch/mips/orion/no_initrd.c
--- linux-2.4.4-pre3/arch/mips/orion/no_initrd.c	Tue Jul 11 11:14:48 2000
+++ linux/arch/mips/orion/no_initrd.c	Wed Dec 31 16:00:00 1969
@@ -1,2 +0,0 @@
-unsigned long *orion_initrd_start = 0;
-unsigned long orion_initrd_size = 0;
diff -urN linux-2.4.4-pre3/arch/mips/orion/piggyback.c linux/arch/mips/orion/piggyback.c
--- linux-2.4.4-pre3/arch/mips/orion/piggyback.c	Tue Jul 11 11:14:48 2000
+++ linux/arch/mips/orion/piggyback.c	Wed Dec 31 16:00:00 1969
@@ -1,59 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-
-extern long ce_exec_config[];
-
-int main(int argc, char *argv[])
-{
-	int i, cnt, pos, len;
-	unsigned int cksum, val;
-	unsigned char *lp;
-	unsigned char buf[8192];
-	if (argc != 2)
-	{
-		fprintf(stderr, "usage: %s name <in-file >out-file\n",
-			argv[0]);
-		exit(1);
-	}
-	fprintf(stdout, "/*\n");
-	fprintf(stdout, "* Miscellaneous data structures:\n");
-	fprintf(stdout, "* WARNING - this file is automatically generated!\n");
-	fprintf(stdout, "*/\n");
-	fprintf(stdout, "\n");
-	fprintf(stdout, "unsigned long orion_%s_start[] = {\n", argv[1]);
-	pos = 0;
-	cksum = 0;
-	while ((len = read(0, buf, sizeof(buf))) > 0)
-	{
-		cnt = 0;
-		lp = (unsigned char *)buf;
-		len = (len + 3) & ~3;  /* Round up to longwords */
-		for (i = 0;  i < len;  i += 4)
-		{
-			if (cnt == 0)
-			{
-				fprintf(stdout, "\t");
-			}
-			fprintf(stdout, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
-			val = *(unsigned long *)lp;
-			cksum ^= val;
-			lp += 4;
-			if (++cnt == 4)
-			{
-				cnt = 0;
-				fprintf(stdout, ", /* %x */\n", pos+i-12);
-				fflush(stdout);
-			} else
-			{
-				fprintf(stdout, ",");
-			}
-		}
-		pos += len;
-	}
-	fprintf(stdout, "0 };\n");
-	fprintf(stdout, "unsigned long orion_%s_size = 0x%x;\n", argv[1], pos);
-	fflush(stdout);
-	fclose(stdout);
-	fprintf(stderr, "cksum = %x\n", cksum);
-	exit(0);
-}
diff -urN linux-2.4.4-pre3/arch/mips/orion/promcon.c linux/arch/mips/orion/promcon.c
--- linux-2.4.4-pre3/arch/mips/orion/promcon.c	Thu Oct 12 14:20:48 2000
+++ linux/arch/mips/orion/promcon.c	Wed Dec 31 16:00:00 1969
@@ -1,168 +0,0 @@
-/*
- * Wrap-around code for a console using the
- * SGI PROM io-routines.
- *
- * Copyright (c) 1999 Ulf Carlsson
- *
- * Derived from DECstation promcon.c
- * Copyright (c) 1998 Harald Koerfgen 
- */
-
-#include <linux/tty.h>
-#include <linux/major.h>
-#include <linux/ptrace.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/fs.h>
-/*
-#include <asm/sgialib.h>
-*/
-extern void prom_printf(char *fmt, ...);
-unsigned long splx(unsigned long mask){return 0;}
-#if 0
-unsigned long ramsize=0x100000;
-unsigned long RamSize(){return ramsize;}
-extern void prom_printf(char *fmt, ...);
-unsigned long splx(unsigned long mask){return 0;}
-long PssSetIntHandler(unsigned long intnum, void *handler){}
-long PssEnableInt(unsigned long intnum){}
-long PssDisableInt(unsigned long intnum){}
-unsigned long t_ident(char name[4], unsigned long node, unsigned long *tid){}
-#endif
-
-extern void  SerialPollConout(unsigned char c);
-static void prom_console_write(struct console *co, const char *s,
-			       unsigned count)
-{
-    unsigned i;
-
-    /*
-     *    Now, do each character
-     */
-    for (i = 0; i < count; i++) {
-	if (*s == 10)
-	  SerialPollConout(13);
-	SerialPollConout(*s++);
-    }
-}
-extern int prom_getchar(void);
-static int prom_console_wait_key(struct console *co)
-{
-    return prom_getchar();
-}
-
-extern void SerialPollInit(void);
-extern void  SerialSetup(unsigned long  baud, unsigned long  console, unsigned long  host, unsigned long  intr_desc);
-static int __init prom_console_setup(struct console *co, char *options)
-{
-  SerialSetup(19200,1,1,3);
-  SerialPollInit();
-  SerialPollOn();
-  return 0;
-}
-
-static kdev_t prom_console_device(struct console *c)
-{
-    return MKDEV(TTY_MAJOR, 64 + c->index);
-}
-
-static struct console sercons =
-{
-    name:	"ttyS",
-    write:	prom_console_write,
-    device:	prom_console_device,
-    wait_key:	prom_console_wait_key,
-    setup:	prom_console_setup,
-    flags:	CON_PRINTBUFFER,
-    index:	-1,
-};
-
-/*
- *    Register console.
- */
-
-void serial_console_init(void)
-{
-	register_console(&sercons);
-}
-
-extern void prom_putchar(int mychar);
-
-static char ppbuf[1000];
-
-
-void prom_printf(char *fmt, ...)
-{
-	va_list args;
-	char ch, *bptr;
-	int i;
-
-	va_start(args, fmt);
-	i = vsprintf(ppbuf, fmt, args);
-
-	bptr = ppbuf;
-
-	while((ch = *(bptr++)) != 0) {
-		if(ch == '\n')
-			prom_putchar('\r');
-
-		prom_putchar(ch);
-	}
-	va_end(args);
-	return;
-}
-
-
-
-void prom_putchar(int mychar){}
-int prom_getchar(void){return 0;}
-struct app_header_s {
-  unsigned long    MAGIC_JMP;
-  unsigned long    MAGIC_NOP;
-  unsigned long    header_tag;    
-  unsigned long    header_flags;
-  unsigned long    header_length;
-  unsigned long    header_cksum;
-     
-  void             *load_addr;
-  void             *end_addr;
-  void             *start_addr;
-  char             *app_name_p;
-  char             *version_p;
-  char             *date_p;
-  char             *time_p;
-  unsigned long    type;
-  unsigned long    crc;
-  unsigned long    reserved;
-};
-typedef struct app_header_s app_header_t;
-char linked_app_name[]="linux";
-char *linked_app_name_p=&linked_app_name[0];
-
-char linked_app_ver[]="2.4 -test1";
-char *linked_app_ver_p=&linked_app_ver[0];
-
-char linked_app_date[]="today";
-char *linked_app_date_p=&linked_app_date[0];
-
-char linked_app_time[]="now";
-char *linked_app_time_p=&linked_app_time[0];
-extern void *__bss_start;
-extern void *kernel_entry;
-
-app_header_t app_header __attribute__ ((section (".app_header"))) = {
-  (0x10000000 | (((sizeof(app_header_t)>>2)-1) & 0xffff)) ,
-  0 ,
-  (((( 0x4321  ) & 0xFFFF) << 16) | ((  0x0100  ) & 0xFFFF))  ,
-  0x80000000 ,
-  sizeof(app_header_t),
-  0,
-  &app_header,
-  &__bss_start,
-  &kernel_entry,
-  linked_app_name,
-  linked_app_ver,
-  linked_app_date,
-  linked_app_time,
-  0
-};
diff -urN linux-2.4.4-pre3/arch/mips/orion/setup.c linux/arch/mips/orion/setup.c
--- linux-2.4.4-pre3/arch/mips/orion/setup.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/mips/orion/setup.c	Wed Dec 31 16:00:00 1969
@@ -1,125 +0,0 @@
-/*
- * Catch-all for Orion-specific code that doesn't fit easily elsewhere.
- *   -- Cort
- */
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/hdreg.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/utsname.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/interrupt.h>
-#ifdef CONFIG_BLK_DEV_RAM
-#include <linux/blk.h>
-#endif
-#include <linux/ide.h>
-#ifdef CONFIG_RTC
-#include <linux/timex.h>
-#endif
-
-#include <asm/asm.h>
-#include <asm/bootinfo.h>
-#include <asm/cachectl.h>
-#include <asm/io.h>
-#include <asm/stackframe.h>
-#include <asm/system.h>
-#include <asm/cpu.h>
-#include <linux/bootmem.h>
-#include <asm/addrspace.h>
-#include <asm/mc146818rtc.h>
-#include <asm/orion.h>
-
-char arcs_cmdline[CL_SIZE] = { "console=ttyS0,19200" };
-extern int _end;
-
-static unsigned char orion_rtc_read_data(unsigned long addr)
-{
-	return 0;
-}
-
-static void orion_rtc_write_data(unsigned char data, unsigned long addr)
-{
-}
-
-static int orion_rtc_bcd_mode(void)
-{
-	return 0;
-}
-
-struct rtc_ops orion_rtc_ops = {
-	&orion_rtc_read_data,
-	&orion_rtc_write_data,
-	&orion_rtc_bcd_mode
-};
-
-extern void InitCIB(void);
-extern void InitQpic(void);
-extern void InitCupid(void);
-
-void __init orion_setup(void)
-{
-	extern void (*board_time_init)(struct irqaction *irq);
-	void orion_time_init(struct irqaction *);
-	
-	rtc_ops = &orion_rtc_ops;
-	board_time_init = orion_time_init;
-	mips_io_port_base = GT64120_BASE;
-
-	InitCIB();
-	InitQpic();
-	InitCupid();
-}
-
-#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_ALIGN(x)	(((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
-
-unsigned long mem_size;
-int __init prom_init(int a, char **b, char **c, int *d)
-{
-	unsigned long free_start, free_end, start_pfn, bootmap_size;
-	extern unsigned long orion_initrd_start[], orion_initrd_size;
-
-	mips_machgroup = MACH_GROUP_ORION;
-	/* 64 MB non-upgradable */
-	mem_size = 64 << 20;
-	
-	free_start = PHYSADDR(PFN_ALIGN(&_end));
-	free_end = mem_size;
-	start_pfn = PFN_UP((unsigned long)&_end);
-	
-	/* Register all the contiguous memory with the bootmem allocator
-	   and free it.  Be careful about the bootmem freemap.  */
-	bootmap_size = init_bootmem(start_pfn, mem_size >> PAGE_SHIFT);
-	
-	/* Free the entire available memory after the _end symbol.  */
-	free_start += bootmap_size;
-	free_bootmem(free_start, free_end-free_start);
-
-	initrd_start = (ulong)orion_initrd_start;
-	initrd_end = (ulong)orion_initrd_start + (ulong)orion_initrd_size;
-	initrd_below_start_ok = 1;
-
-	return 0;
-}
-
-void prom_free_prom_memory (void)
-{
-}
-
-int page_is_ram(unsigned long pagenr)
-{
-	if ( pagenr < (mem_size >> PAGE_SHIFT) )
-		return 1;
-	return 0;
-}
diff -urN linux-2.4.4-pre3/arch/mips/sgi/kernel/Makefile linux/arch/mips/sgi/kernel/Makefile
--- linux-2.4.4-pre3/arch/mips/sgi/kernel/Makefile	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/sgi/kernel/Makefile	Mon Dec  3 22:35:22 2001
@@ -13,21 +13,13 @@
 .S.o:
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
-OBJS  = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o \
-        system.o indyIRQ.o reset.o setup.o time.o
-ifdef CONFIG_SGI_PROM_CONSOLE
-OBJS += promcon.o
-endif
+O_TARGET := ip22-kern.o
 
-all: sgikern.a
+all: ip22-kern.o indyIRQ.o
 
-sgikern.a: $(OBJS)
-	$(AR) rcs sgikern.a $(OBJS)
-	sync
+obj-y	+= indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o system.o \
+	   indyIRQ.o reset.o setup.o time.o
 
 indyIRQ.o: indyIRQ.S
-
-dep:
-	$(CPP) $(CPPFLAGS) -M *.c > .depend
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips/sni/Makefile linux/arch/mips/sni/Makefile
--- linux-2.4.4-pre3/arch/mips/sni/Makefile	Sat May 13 08:29:14 2000
+++ linux/arch/mips/sni/Makefile	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.3 1999/01/04 16:03:57 ralf Exp $
 #
 # Makefile for the SNI specific part of the kernel
 #
@@ -12,12 +11,12 @@
 .S.o:
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
-all: sni.o
+all:	sni.o int-handler.o
+
 O_TARGET := sni.o
-O_OBJS	 := dma.o int-handler.o io.o pci.o pcimt_scache.o reset.o setup.o
 
-int-handler.o: int-handler.S
+obj-y	 := int-handler.o io.o irq.o pci.o pcimt_scache.o reset.o setup.o
 
-clean:
+int-handler.o: int-handler.S
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/arch/mips64/config.in linux/arch/mips64/config.in
--- linux-2.4.4-pre3/arch/mips64/config.in	Sun Feb  4 21:48:46 2001
+++ linux/arch/mips64/config.in	Mon Dec  3 22:35:22 2001
@@ -25,6 +25,9 @@
 fi
 endmenu
 
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+
 #
 # Select some configuration options automatically based on user selections
 #
diff -urN linux-2.4.4-pre3/arch/mips64/defconfig linux/arch/mips64/defconfig
--- linux-2.4.4-pre3/arch/mips64/defconfig	Sun Mar  4 14:30:18 2001
+++ linux/arch/mips64/defconfig	Mon Dec  3 22:35:22 2001
@@ -120,6 +120,11 @@
 # CONFIG_BRIDGE is not set
 
 #
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
 # Telephony Support
 #
 # CONFIG_PHONE is not set
@@ -422,6 +427,7 @@
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
diff -urN linux-2.4.4-pre3/arch/mips64/defconfig-ip22 linux/arch/mips64/defconfig-ip22
--- linux-2.4.4-pre3/arch/mips64/defconfig-ip22	Sun Feb  4 21:48:46 2001
+++ linux/arch/mips64/defconfig-ip22	Mon Dec  3 22:35:22 2001
@@ -110,6 +110,11 @@
 # CONFIG_BRIDGE is not set
 
 #
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
 # Telephony Support
 #
 # CONFIG_PHONE is not set
diff -urN linux-2.4.4-pre3/arch/mips64/defconfig-ip27 linux/arch/mips64/defconfig-ip27
--- linux-2.4.4-pre3/arch/mips64/defconfig-ip27	Sun Feb  4 21:48:46 2001
+++ linux/arch/mips64/defconfig-ip27	Mon Dec  3 22:35:22 2001
@@ -120,6 +120,11 @@
 # CONFIG_BRIDGE is not set
 
 #
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
 # Telephony Support
 #
 # CONFIG_PHONE is not set
@@ -165,6 +170,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -421,6 +427,7 @@
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
diff -urN linux-2.4.4-pre3/arch/mips64/kernel/semaphore.c linux/arch/mips64/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/mips64/kernel/semaphore.c	Sat Nov 11 19:02:40 2000
+++ linux/arch/mips64/kernel/semaphore.c	Mon Dec  3 22:35:22 2001
@@ -127,112 +127,3 @@
 {
 	return waking_non_zero_trylock(sem);
 }
-
-/*
- * RW Semaphores
- */
-void
-__down_read(struct rw_semaphore *sem, int count)
-{
-	DOWN_VAR;
-
- retry_down:
-	if (count < 0) {
-		/* Wait for the lock to become unbiased.  Readers
-		   are non-exclusive.  */
-		
-		/* This takes care of granting the lock.  */
-		up_read(sem);
-
-		add_wait_queue(&sem->wait, &wait);
-		while (atomic_read(&sem->count) < 0) {
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if (atomic_read(&sem->count) >= 0)
-				break;
-			schedule();
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		tsk->state = TASK_RUNNING;
-
-		mb();
-		count = atomic_dec_return(&sem->count);
-		if (count <= 0)
-			goto retry_down;
-	} else {
-		add_wait_queue(&sem->wait, &wait);
-
-		while (1) {
-			if (test_and_clear_bit(0, &sem->granted))
-				break;
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if ((sem->granted & 1) == 0)
-				schedule();
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		tsk->state = TASK_RUNNING;
-	}
-}
-
-void
-__down_write(struct rw_semaphore *sem, int count)
-{
-	DOWN_VAR;
-
- retry_down:
-	if (count + RW_LOCK_BIAS < 0) {
-		up_write(sem);
-
-		add_wait_queue_exclusive(&sem->wait, &wait);
-	
-		while (atomic_read(&sem->count) < 0) {
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if (atomic_read(&sem->count) >= RW_LOCK_BIAS)
-				break;
-			schedule();
-		}
-
-		remove_wait_queue(&sem->wait, &wait);
-		tsk->state = TASK_RUNNING;
-
-		mb();
-		count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-		if (count != 0)
-			goto retry_down;
-	} else {
-		/* Put ourselves at the end of the list.  */
-		add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
-
-		while (1) {
-			if (test_and_clear_bit(1, &sem->granted))
-				break;
-			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-			if ((sem->granted & 2) == 0)
-				schedule();
-		}
-
-		remove_wait_queue(&sem->write_bias_wait, &wait);
-		tsk->state = TASK_RUNNING;
-
-		/* If the lock is currently unbiased, awaken the sleepers.
-		   FIXME: This wakes up the readers early in a bit of a
-		   stampede -> bad!  */
-		if (atomic_read(&sem->count) >= 0)
-			wake_up(&sem->wait);
-	}
-}
-
-void
-__rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
-{
-	if (readers) {
-		if (test_and_set_bit(0, &sem->granted))
-			BUG();
-		wake_up(&sem->wait);
-	} else {
-		if (test_and_set_bit(1, &sem->granted))
-			BUG();
-		wake_up(&sem->write_bias_wait);
-	}
-}
diff -urN linux-2.4.4-pre3/arch/mips64/mm/Makefile linux/arch/mips64/mm/Makefile
--- linux-2.4.4-pre3/arch/mips64/mm/Makefile	Sun Feb  4 21:48:46 2001
+++ linux/arch/mips64/mm/Makefile	Mon Dec  3 22:35:22 2001
@@ -4,7 +4,8 @@
 
 O_TARGET := mm.o
 
-obj-y	 := extable.o init.o fault.o loadmmu.o
+export-objs			+= umap.o
+obj-y				:= extable.o init.o fault.o loadmmu.o
 
 obj-$(CONFIG_CPU_R4300)		+= r4xx0.o
 obj-$(CONFIG_CPU_R4X00)		+= r4xx0.o
diff -urN linux-2.4.4-pre3/arch/mips64/tools/Makefile linux/arch/mips64/tools/Makefile
--- linux-2.4.4-pre3/arch/mips64/tools/Makefile	Sun Jul  9 22:18:16 2000
+++ linux/arch/mips64/tools/Makefile	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1999/08/18 21:46:53 ralf Exp $
 #
 # Makefile for MIPS kernel build tools.
 #
diff -urN linux-2.4.4-pre3/arch/parisc/config.in linux/arch/parisc/config.in
--- linux-2.4.4-pre3/arch/parisc/config.in	Tue Dec  5 12:29:39 2000
+++ linux/arch/parisc/config.in	Mon Dec  3 22:35:22 2001
@@ -7,6 +7,8 @@
 
 define_bool CONFIG_PARISC y
 define_bool CONFIG_UID16 n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_option next_comment
 comment 'Code maturity level options'
diff -urN linux-2.4.4-pre3/arch/parisc/kernel/semaphore.c linux/arch/parisc/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/parisc/kernel/semaphore.c	Tue Dec  5 12:29:39 2000
+++ linux/arch/parisc/kernel/semaphore.c	Mon Dec  3 22:35:22 2001
@@ -129,111 +129,3 @@
 {
 	return waking_non_zero_trylock(sem);
 }
-
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	__up_read(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(current, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	current->state = TASK_RUNNING;
-}
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-			break;
-		set_task_state(current, TASK_UNINTERRUPTIBLE);
-                if (!sem->read_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	current->state = TASK_RUNNING;
-}
-
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	__up_write(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(current, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
-		if (atomic_read(&sem->count) >= 0)
-			break;	/* we must attempt to aquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	current->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait);	/* put ourselves at the end of the list */
-
-	for (;;) {
-		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-			break;
-		set_task_state(current, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE);
-		if (!sem->write_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	current->state = TASK_RUNNING;
-
-	/* if the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (atomic_read(&sem->count) >= 0)
-		wake_up(&sem->wait);
-}
-
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-void rwsem_wake_readers(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->read_bias_granted, 1))
-		BUG();
-	wake_up(&sem->wait);
-}
-
-void rwsem_wake_writer(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->write_bias_granted, 1))
-		BUG();
-	wake_up(&sem->write_bias_wait);
-}
diff -urN linux-2.4.4-pre3/arch/ppc/config.in linux/arch/ppc/config.in
--- linux-2.4.4-pre3/arch/ppc/config.in	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/config.in	Mon Dec  3 22:35:22 2001
@@ -3,6 +3,8 @@
 # see Documentation/kbuild/config-language.txt.
 #
 define_bool CONFIG_UID16 n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_name "Linux/PowerPC Kernel Configuration"
 
diff -urN linux-2.4.4-pre3/arch/ppc/kernel/semaphore.c linux/arch/ppc/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/ppc/kernel/semaphore.c	Sat Nov 11 19:02:40 2000
+++ linux/arch/ppc/kernel/semaphore.c	Mon Dec  3 22:35:22 2001
@@ -137,44 +137,3 @@
 {
 	return waking_non_zero_trylock(sem);
 }
-
-
-/*
- * rw semaphores    Ani Joshi <ajoshi@unixbox.com>
- * based on alpha port by Andrea Arcangeli <andrea@suse.de>
- */
-
-void down_read_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	do {
-		__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		spin_unlock_irq(&sem->lock);
-		schedule();
-		spin_lock_irq(&sem->lock);
-	} while(sem->wr);
-
-	remove_wait_queue(&sem->wait, &wait);
-}
-
-void down_write_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	do {
-		__set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		spin_unlock_irq(&sem->lock);
-		schedule();
-		spin_lock_irq(&sem->lock);
-	} while(sem->rd || sem->wr);
-
-	remove_wait_queue(&sem->wait, &wait);
-}
-
diff -urN linux-2.4.4-pre3/arch/s390/config.in linux/arch/s390/config.in
--- linux-2.4.4-pre3/arch/s390/config.in	Mon Dec  3 22:35:11 2001
+++ linux/arch/s390/config.in	Mon Dec  3 22:35:22 2001
@@ -7,6 +7,8 @@
 define_bool CONFIG_EISA n
 define_bool CONFIG_MCA n
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_name "Linux Kernel Configuration"
 define_bool CONFIG_ARCH_S390 y
diff -urN linux-2.4.4-pre3/arch/s390/kernel/semaphore.c linux/arch/s390/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/s390/kernel/semaphore.c	Tue Feb 13 14:13:44 2001
+++ linux/arch/s390/kernel/semaphore.c	Mon Dec  3 22:35:22 2001
@@ -158,145 +158,3 @@
 	spin_unlock_irqrestore(&semaphore_lock, flags);
 	return 1;
 }
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->read_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait);	/* put ourselves at the end of the list */
-
-	for (;;) {
-		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->write_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	/* if the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (atomic_read(&sem->count) >= 0)
-		wake_up(&sem->wait);
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	up_read(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	up_write(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;	/* we must attempt to acquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-void rwsem_wake_readers(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->read_bias_granted, 1))
-		BUG();
-	wake_up(&sem->wait);
-}
-
-void rwsem_wake_writers(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->write_bias_granted, 1))
-		BUG();
-	wake_up(&sem->write_bias_wait);
-}
-
-void __down_read_failed(int count, struct rw_semaphore *sem) 
-{
-	do {
-		if (count == -1) {
-			down_read_failed_biased(sem);
-			break;
-		}
-		down_read_failed(sem);
-		count = atomic_dec_return(&sem->count);
-	} while (count != 0);
-}
-
-void __down_write_failed(int count, struct rw_semaphore *sem)
-{
-	do {
-		if (count < 0 && count > -RW_LOCK_BIAS) {
-			down_write_failed_biased(sem);
-			break;
-		}
-		down_write_failed(sem);
-		count = atomic_add_return(-RW_LOCK_BIAS, &sem->count);
-	} while (count != 0);
-}
-
-void __rwsem_wake(int count, struct rw_semaphore *sem)
-{
-	if (count == 0)
-		rwsem_wake_readers(sem);
-	else
-		rwsem_wake_writers(sem);
-}
-
diff -urN linux-2.4.4-pre3/arch/s390x/config.in linux/arch/s390x/config.in
--- linux-2.4.4-pre3/arch/s390x/config.in	Mon Dec  3 22:35:11 2001
+++ linux/arch/s390x/config.in	Mon Dec  3 22:35:22 2001
@@ -6,6 +6,8 @@
 define_bool CONFIG_ISA n
 define_bool CONFIG_EISA n
 define_bool CONFIG_MCA n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_name "Linux Kernel Configuration"
 define_bool CONFIG_ARCH_S390 y
diff -urN linux-2.4.4-pre3/arch/s390x/kernel/semaphore.c linux/arch/s390x/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/s390x/kernel/semaphore.c	Tue Feb 13 14:13:44 2001
+++ linux/arch/s390x/kernel/semaphore.c	Mon Dec  3 22:35:22 2001
@@ -158,145 +158,3 @@
 	spin_unlock_irqrestore(&semaphore_lock, flags);
 	return 1;
 }
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->read_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait);	/* put ourselves at the end of the list */
-
-	for (;;) {
-		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->write_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	/* if the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (atomic_read(&sem->count) >= 0)
-		wake_up(&sem->wait);
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	up_read(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	up_write(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;	/* we must attempt to acquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-void rwsem_wake_readers(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->read_bias_granted, 1))
-		BUG();
-	wake_up(&sem->wait);
-}
-
-void rwsem_wake_writers(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->write_bias_granted, 1))
-		BUG();
-	wake_up(&sem->write_bias_wait);
-}
-
-void __down_read_failed(int count, struct rw_semaphore *sem) 
-{
-	do {
-		if (count == -1) {
-			down_read_failed_biased(sem);
-			break;
-		}
-		down_read_failed(sem);
-		count = atomic_dec_return(&sem->count);
-	} while (count != 0);
-}
-
-void __down_write_failed(int count, struct rw_semaphore *sem)
-{
-	do {
-		if (count < 0 && count > -RW_LOCK_BIAS) {
-			down_write_failed_biased(sem);
-			break;
-		}
-		down_write_failed(sem);
-		count = atomic_add_return(-RW_LOCK_BIAS, &sem->count);
-	} while (count != 0);
-}
-
-void __rwsem_wake(int count, struct rw_semaphore *sem)
-{
-	if (count == 0)
-		rwsem_wake_readers(sem);
-	else
-		rwsem_wake_writers(sem);
-}
-
diff -urN linux-2.4.4-pre3/arch/sh/config.in linux/arch/sh/config.in
--- linux-2.4.4-pre3/arch/sh/config.in	Thu Jan  4 13:19:13 2001
+++ linux/arch/sh/config.in	Mon Dec  3 22:35:22 2001
@@ -7,6 +7,8 @@
 define_bool CONFIG_SUPERH y
 
 define_bool CONFIG_UID16 y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 mainmenu_option next_comment
 comment 'Code maturity level options'
diff -urN linux-2.4.4-pre3/arch/sh/kernel/semaphore.c linux/arch/sh/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/sh/kernel/semaphore.c	Sat Nov 11 19:02:40 2000
+++ linux/arch/sh/kernel/semaphore.c	Mon Dec  3 22:35:22 2001
@@ -135,162 +135,3 @@
 {
 	return waking_non_zero_trylock(sem);
 }
-
-/* Called when someone has done an up that transitioned from
- * negative to non-negative, meaning that the lock has been
- * granted to whomever owned the bias.
- */
-struct rw_semaphore *rwsem_wake_readers(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->read_bias_granted, 1))
-		BUG();
-	wake_up(&sem->wait);
-	return sem;
-}
-
-struct rw_semaphore *rwsem_wake_writer(struct rw_semaphore *sem)
-{
-	if (xchg(&sem->write_bias_granted, 1))
-		BUG();
-	wake_up(&sem->write_bias_wait);
-	return sem;
-}
-
-struct rw_semaphore * __rwsem_wake(struct rw_semaphore *sem)
-{
-	if (atomic_read(&sem->count) == 0)
-		return rwsem_wake_writer(sem);
-	else
-		return rwsem_wake_readers(sem);
-}
-
-struct rw_semaphore *down_read_failed_biased(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->read_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	return sem;
-}
-
-struct rw_semaphore *down_write_failed_biased(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait);	/* put ourselves at the end of the list */
-
-	for (;;) {
-		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!sem->write_bias_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	/* if the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (atomic_read(&sem->count) >= 0)
-		wake_up(&sem->wait);
-
-	return sem;
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-struct rw_semaphore *down_read_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	__up_read(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	return sem;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-struct rw_semaphore *down_write_failed(struct rw_semaphore *sem)
-{
-	struct task_struct *tsk = current;
-	DECLARE_WAITQUEUE(wait, tsk);
-
-	__up_write(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (atomic_read(&sem->count) < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (atomic_read(&sem->count) >= 0)
-			break;	/* we must attempt to acquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	return sem;
-}
-
-struct rw_semaphore *__down_read(struct rw_semaphore *sem, int carry)
-{
-	if (carry) {
-		int saved, new;
-
-		do {
-			down_read_failed(sem);
-			saved = atomic_read(&sem->count);
-			if ((new = atomic_dec_return(&sem->count)) >= 0)
-				return sem;
-		} while (!(new < 0 && saved >=0));
-	}
-
-	return down_read_failed_biased(sem);
-}
-
-struct rw_semaphore *__down_write(struct rw_semaphore *sem, int carry)
-{
-	if (carry) {
-		int saved, new;
-
-		do {
-			down_write_failed(sem);
-			saved = atomic_read(&sem->count);
-			if ((new = atomic_sub_return(RW_LOCK_BIAS, &sem->count) ) == 0)
-				return sem;
-		} while (!(new < 0 && saved >=0));
-	}
-
-	return down_write_failed_biased(sem);
-}
diff -urN linux-2.4.4-pre3/arch/sparc/config.in linux/arch/sparc/config.in
--- linux-2.4.4-pre3/arch/sparc/config.in	Sun Feb 18 19:49:44 2001
+++ linux/arch/sparc/config.in	Mon Dec  3 22:35:22 2001
@@ -48,6 +48,8 @@
 define_bool CONFIG_SUN_CONSOLE y
 define_bool CONFIG_SUN_AUXIO y
 define_bool CONFIG_SUN_IO y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 
 bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4
 if [ "$CONFIG_SUN4" != "y" ]; then
diff -urN linux-2.4.4-pre3/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- linux-2.4.4-pre3/arch/sparc/kernel/irq.c	Sun Feb 18 19:49:44 2001
+++ linux/arch/sparc/kernel/irq.c	Mon Dec  3 22:35:22 2001
@@ -8,7 +8,7 @@
  *  Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
  *  Copyright (C) 1995 Pete A. Zaitcev (zaitcev@metabyte.com)
  *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
- *  Copyright (C) 1998-2000 Anton Blanchard (anton@linuxcare.com)
+ *  Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
  */
 
 #include <linux/config.h>
diff -urN linux-2.4.4-pre3/arch/sparc/kernel/semaphore.c linux/arch/sparc/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/sparc/kernel/semaphore.c	Mon Jan 22 13:30:20 2001
+++ linux/arch/sparc/kernel/semaphore.c	Mon Dec  3 22:35:22 2001
@@ -151,119 +151,3 @@
 	spin_unlock_irqrestore(&semaphore_lock, flags);
 	return 1;
 }
-
-/* rw mutexes
- * Implemented by Jakub Jelinek (jakub@redhat.com) based on
- * i386 implementation by Ben LaHaise (bcrl@redhat.com).
- */
-
-extern inline int ldstub(unsigned char *p)
-{
-	int ret;
-	asm volatile("ldstub %1, %0" : "=r" (ret) : "m" (*p) : "memory");
-	return ret;
-}
-
-#define DOWN_VAR				\
-	struct task_struct *tsk = current;	\
-	DECLARE_WAITQUEUE(wait, tsk);
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-	DOWN_VAR
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (!ldstub(&sem->read_not_granted))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (sem->read_not_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-	DOWN_VAR
-
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
-
-	for (;;) {
-		if (!ldstub(&sem->write_not_granted))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (sem->write_not_granted)
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	/* if the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (sem->count >= 0)
-		wake_up(&sem->wait);
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-	DOWN_VAR
-
-	__up_read(sem); /* this takes care of granting the lock */
-
-	add_wait_queue(&sem->wait, &wait);
-
-	while (sem->count < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (sem->count >= 0)
-			break;
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-	DOWN_VAR
-
-	__up_write(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (sem->count < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (sem->count >= 0)
-			break;  /* we must attempt to acquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
-{
-	if (readers) {
-		/* Due to lame ldstub we don't do here
-		   a BUG() consistency check */
-		sem->read_not_granted = 0;
-		wake_up(&sem->wait);
-	} else {
-		sem->write_not_granted = 0;
-		wake_up(&sem->write_bias_wait);
-	}
-}
diff -urN linux-2.4.4-pre3/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c
--- linux-2.4.4-pre3/arch/sparc/kernel/setup.c	Sun Feb 18 19:49:54 2001
+++ linux/arch/sparc/kernel/setup.c	Mon Dec  3 22:35:22 2001
@@ -2,7 +2,7 @@
  *  linux/arch/sparc/kernel/setup.c
  *
  *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
- *  Copyright (C) 2000  Anton Blanchard (anton@linuxcare.com)
+ *  Copyright (C) 2000  Anton Blanchard (anton@samba.org)
  */
 
 #include <linux/errno.h>
diff -urN linux-2.4.4-pre3/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c
--- linux-2.4.4-pre3/arch/sparc/kernel/sys_sparc.c	Mon Dec  3 22:35:11 2001
+++ linux/arch/sparc/kernel/sys_sparc.c	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.69 2001/03/27 02:36:37 davem Exp $
+/* $Id: sys_sparc.c,v 1.70 2001/04/14 01:12:02 davem Exp $
  * linux/arch/sparc/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -299,7 +299,6 @@
 	} else if ((ARCH_SUN4C_SUN4 && addr < 0xe0000000 &&
 		    addr + new_len > 0x20000000) ||
 		   addr + new_len > TASK_SIZE - PAGE_SIZE) {
-		unsigned long (*get_addr)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 		unsigned long map_flags = 0;
 		struct file *file = NULL;
 
diff -urN linux-2.4.4-pre3/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- linux-2.4.4-pre3/arch/sparc/mm/init.c	Sun Mar 25 18:14:21 2001
+++ linux/arch/sparc/mm/init.c	Mon Dec  3 22:35:22 2001
@@ -1,10 +1,10 @@
-/*  $Id: init.c,v 1.97 2001/02/26 02:57:34 anton Exp $
+/*  $Id: init.c,v 1.96 2000/11/30 08:51:50 anton Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  *  Copyright (C) 1995 Eddie C. Dost (ecd@skynet.be)
  *  Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- *  Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
+ *  Copyright (C) 2000 Anton Blanchard (anton@samba.org)
  */
 
 #include <linux/config.h>
diff -urN linux-2.4.4-pre3/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- linux-2.4.4-pre3/arch/sparc/mm/srmmu.c	Sun Mar 25 18:14:21 2001
+++ linux/arch/sparc/mm/srmmu.c	Mon Dec  3 22:35:22 2001
@@ -5,7 +5,7 @@
  * Copyright (C) 1995 Pete Zaitcev
  * Copyright (C) 1996 Eddie C. Dost    (ecd@skynet.be)
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1999,2000 Anton Blanchard (anton@linuxcare.com)
+ * Copyright (C) 1999,2000 Anton Blanchard (anton@samba.org)
  */
 
 #include <linux/config.h>
diff -urN linux-2.4.4-pre3/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- linux-2.4.4-pre3/arch/sparc/mm/sun4c.c	Sun Mar 25 18:14:21 2001
+++ linux/arch/sparc/mm/sun4c.c	Mon Dec  3 22:35:22 2001
@@ -4,7 +4,7 @@
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
  * Copyright (C) 1996 Andrew Tridgell (Andrew.Tridgell@anu.edu.au)
- * Copyright (C) 1997-2000 Anton Blanchard (anton@linuxcare.com)
+ * Copyright (C) 1997-2000 Anton Blanchard (anton@samba.org)
  * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
diff -urN linux-2.4.4-pre3/arch/sparc64/config.in linux/arch/sparc64/config.in
--- linux-2.4.4-pre3/arch/sparc64/config.in	Mon Dec  3 22:35:11 2001
+++ linux/arch/sparc64/config.in	Mon Dec  3 22:35:22 2001
@@ -33,6 +33,8 @@
 
 # Global things across all Sun machines.
 define_bool CONFIG_HAVE_DEC_LOCK y
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
 define_bool CONFIG_ISA n
 define_bool CONFIG_EISA n
 define_bool CONFIG_MCA n
diff -urN linux-2.4.4-pre3/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- linux-2.4.4-pre3/arch/sparc64/defconfig	Mon Dec  3 22:35:11 2001
+++ linux/arch/sparc64/defconfig	Mon Dec  3 22:35:22 2001
@@ -446,6 +446,7 @@
 CONFIG_EFS_FS=m
 # CONFIG_JFFS_FS is not set
 CONFIG_CRAMFS=m
+# CONFIG_TMPFS is not set
 CONFIG_RAMFS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
diff -urN linux-2.4.4-pre3/arch/sparc64/kernel/semaphore.c linux/arch/sparc64/kernel/semaphore.c
--- linux-2.4.4-pre3/arch/sparc64/kernel/semaphore.c	Sat Nov 11 19:02:40 2000
+++ linux/arch/sparc64/kernel/semaphore.c	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,4 @@
-/* $Id: semaphore.c,v 1.5 2000/11/10 04:02:03 davem Exp $
+/* $Id: semaphore.c,v 1.6 2001/04/14 01:12:02 davem Exp $
  *  Generic semaphore code. Buyer beware. Do your own
  * specific changes in <asm/semaphore-helper.h>
  */
@@ -125,173 +125,4 @@
 int __down_trylock(struct semaphore * sem)
 {
 	return waking_non_zero_trylock(sem);
-}
-
-/* rw mutexes
- * Implemented by Jakub Jelinek (jakub@redhat.com) based on
- * i386 implementation by Ben LaHaise (bcrl@redhat.com).
- */
-
-asm("
-	.text
-	.align	32
-	.globl	__down_read_failed
-__down_read_failed:
-	save		%sp, -160, %sp
-	membar		#StoreStore
-	brz,pt		%g5, 3f
-	 mov		%g7, %l0
-1:	call		down_read_failed
-	 mov		%l0, %o0
-2:	lduw		[%l0], %l1
-	sub		%l1, 1, %l2
-	cas		[%l0], %l1, %l2
-
-	cmp		%l1, %l2
-	bne,pn		%icc, 2b
-	 membar		#StoreStore
-	subcc		%l1, 1, %g0
-	bpos,pt		%icc, 4f
-	 nop
-	bcc,pn		%icc, 1b
-	 nop
-
-3:	call		down_read_failed_biased
-	 mov		%l0, %o0
-4:	ret
-	 restore
-	.previous
-");
-
-asm("
-	.text
-	.align	32
-	.globl	__down_write_failed
-__down_write_failed:
-	save		%sp, -160, %sp
-	membar		#StoreStore
-	tst		%g5
-	bge,pt		%icc, 3f
-	 mov		%g7, %l0
-1:	call		down_write_failed
-	 mov		%l0, %o0
-2:	lduw		[%l0], %l1
-	sethi		%hi (" RW_LOCK_BIAS_STR "), %l3
-	sub		%l1, %l3, %l2
-	cas		[%l0], %l1, %l2
-
-	cmp		%l1, %l2
-	bne,pn		%icc, 2b
-	 membar		#StoreStore
-	subcc		%l1, %l3, %g0
-	be,pt		%icc, 4f
-	 nop
-	bcc,pn		%icc, 1b
-	 nop
-
-3:	call		down_write_failed_biased
-	 mov		%l0, %o0
-4:	ret
-	 restore
-	.previous
-");
-
-void down_read_failed_biased(struct rw_semaphore *sem)
-{
-	DOWN_VAR
-
-	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
-
-	for (;;) {
-		if (test_and_clear_le_bit(0, &sem->granted))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!test_le_bit(0, &sem->granted))
-			schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-void down_write_failed_biased(struct rw_semaphore *sem)
-{
-	DOWN_VAR
-
-	add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */
-
-	for (;;) {
-		if (test_and_clear_le_bit(1, &sem->granted))
-			break;
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (!test_le_bit(1, &sem->granted))
-			schedule();
-	}
-
-	remove_wait_queue(&sem->write_bias_wait, &wait);
-	tsk->state = TASK_RUNNING;
-
-	/* if the lock is currently unbiased, awaken the sleepers
-	 * FIXME: this wakes up the readers early in a bit of a
-	 * stampede -> bad!
-	 */
-	if (sem->count >= 0)
-		wake_up(&sem->wait);
-}
-
-/* Wait for the lock to become unbiased.  Readers
- * are non-exclusive. =)
- */
-void down_read_failed(struct rw_semaphore *sem)
-{
-	DOWN_VAR
-
-	__up_read(sem); /* this takes care of granting the lock */
-
-	add_wait_queue(&sem->wait, &wait);
-
-	while (sem->count < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (sem->count >= 0)
-			break;
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-/* Wait for the lock to become unbiased. Since we're
- * a writer, we'll make ourselves exclusive.
- */
-void down_write_failed(struct rw_semaphore *sem)
-{
-	DOWN_VAR
-
-	__up_write(sem);	/* this takes care of granting the lock */
-
-	add_wait_queue_exclusive(&sem->wait, &wait);
-
-	while (sem->count < 0) {
-		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
-		if (sem->count >= 0)
-			break;  /* we must attempt to acquire or bias the lock */
-		schedule();
-	}
-
-	remove_wait_queue(&sem->wait, &wait);
-	tsk->state = TASK_RUNNING;
-}
-
-void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
-{
-	if (readers) {
-		if (test_and_set_le_bit(0, &sem->granted))
-			BUG();
-		wake_up(&sem->wait);
-	} else {
-		if (test_and_set_le_bit(1, &sem->granted))
-			BUG();
-		wake_up(&sem->write_bias_wait);
-	}
 }
diff -urN linux-2.4.4-pre3/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- linux-2.4.4-pre3/arch/sparc64/kernel/sparc64_ksyms.c	Mon Dec  3 22:35:11 2001
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.104 2001/04/05 11:08:11 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.105 2001/04/14 01:12:02 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -159,21 +159,16 @@
 EXPORT_SYMBOL(__down_trylock);
 EXPORT_SYMBOL(__up);
 
-/* rw semaphores */
-EXPORT_SYMBOL_NOVERS(__down_read_failed);
-EXPORT_SYMBOL_NOVERS(__down_write_failed);
-EXPORT_SYMBOL_NOVERS(__rwsem_wake);
-
 /* Atomic counter implementation. */
 EXPORT_SYMBOL(__atomic_add);
 EXPORT_SYMBOL(__atomic_sub);
 
 /* Atomic bit operations. */
-EXPORT_SYMBOL(__test_and_set_bit);
-EXPORT_SYMBOL(__test_and_clear_bit);
-EXPORT_SYMBOL(__test_and_change_bit);
-EXPORT_SYMBOL(__test_and_set_le_bit);
-EXPORT_SYMBOL(__test_and_clear_le_bit);
+EXPORT_SYMBOL(___test_and_set_bit);
+EXPORT_SYMBOL(___test_and_clear_bit);
+EXPORT_SYMBOL(___test_and_change_bit);
+EXPORT_SYMBOL(___test_and_set_le_bit);
+EXPORT_SYMBOL(___test_and_clear_le_bit);
 
 EXPORT_SYMBOL(ivector_table);
 EXPORT_SYMBOL(enable_irq);
diff -urN linux-2.4.4-pre3/arch/sparc64/kernel/starfire.c linux/arch/sparc64/kernel/starfire.c
--- linux-2.4.4-pre3/arch/sparc64/kernel/starfire.c	Sun Feb 18 19:49:54 2001
+++ linux/arch/sparc64/kernel/starfire.c	Mon Dec  3 22:35:22 2001
@@ -2,7 +2,7 @@
  * starfire.c: Starfire/E10000 support.
  *
  * Copyright (C) 1998 David S. Miller (davem@redhat.com)
- * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com)
+ * Copyright (C) 2000 Anton Blanchard (anton@samba.org)
  */
 
 #include <linux/kernel.h>
diff -urN linux-2.4.4-pre3/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c
--- linux-2.4.4-pre3/arch/sparc64/kernel/sys_sparc.c	Mon Dec  3 22:35:11 2001
+++ linux/arch/sparc64/kernel/sys_sparc.c	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.51 2001/03/27 02:36:37 davem Exp $
+/* $Id: sys_sparc.c,v 1.52 2001/04/14 01:12:02 davem Exp $
  * linux/arch/sparc64/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -338,7 +338,6 @@
 		    new_addr + new_len > -PAGE_OFFSET)
 			goto out_sem;
 	} else if (addr < PAGE_OFFSET && addr + new_len > -PAGE_OFFSET) {
-		unsigned long (*get_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 		unsigned long map_flags = 0;
 		struct file *file = NULL;
 
diff -urN linux-2.4.4-pre3/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.4.4-pre3/arch/sparc64/kernel/sys_sparc32.c	Mon Dec  3 22:35:11 2001
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.175 2001/03/27 02:36:37 davem Exp $
+/* $Id: sys_sparc32.c,v 1.176 2001/04/14 01:12:02 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -4138,7 +4138,6 @@
 		if (new_addr > 0xf0000000UL - new_len)
 			goto out_sem;
 	} else if (addr > 0xf0000000UL - new_len) {
-		unsigned long (*get_addr)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 		unsigned long map_flags = 0;
 		struct file *file = NULL;
 
@@ -4154,7 +4153,7 @@
 		}
 
 		/* MREMAP_FIXED checked above. */
-		new_addr = get_unmapped_addr(file, addr, new_len,
+		new_addr = get_unmapped_area(file, addr, new_len,
 				    vma ? vma->vm_pgoff : 0,
 				    map_flags);
 		ret = new_addr;
diff -urN linux-2.4.4-pre3/arch/sparc64/lib/bitops.S linux/arch/sparc64/lib/bitops.S
--- linux-2.4.4-pre3/arch/sparc64/lib/bitops.S	Thu Mar 30 16:54:53 2000
+++ linux/arch/sparc64/lib/bitops.S	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,4 @@
-/* $Id: bitops.S,v 1.1 2000/03/27 10:38:41 davem Exp $
+/* $Id: bitops.S,v 1.2 2001/04/14 01:12:02 davem Exp $
  * bitops.S: Sparc64 atomic bit operations.
  *
  * Copyright (C) 2000 David S. Miller (davem@redhat.com)
@@ -11,8 +11,8 @@
 	.globl	__bitops_begin
 __bitops_begin:
 
-	.globl	__test_and_set_bit
-__test_and_set_bit:	/* %o0=nr, %o1=addr */
+	.globl	___test_and_set_bit
+___test_and_set_bit:	/* %o0=nr, %o1=addr */
 	srlx	%o0, 6, %g1
 	mov	1, %g5
 	sllx	%g1, 3, %g3
@@ -30,8 +30,8 @@
 2:	retl
 	 nop
 
-	.globl	__test_and_clear_bit
-__test_and_clear_bit:	/* %o0=nr, %o1=addr */
+	.globl	___test_and_clear_bit
+___test_and_clear_bit:	/* %o0=nr, %o1=addr */
 	srlx	%o0, 6, %g1
 	mov	1, %g5
 	sllx	%g1, 3, %g3
@@ -49,8 +49,8 @@
 2:	retl
 	 nop
 
-	.globl	__test_and_change_bit
-__test_and_change_bit:	/* %o0=nr, %o1=addr */
+	.globl	___test_and_change_bit
+___test_and_change_bit:	/* %o0=nr, %o1=addr */
 	srlx	%o0, 6, %g1
 	mov	1, %g5
 	sllx	%g1, 3, %g3
@@ -68,8 +68,8 @@
 	 nop
 	nop
 
-	.globl	__test_and_set_le_bit
-__test_and_set_le_bit:	/* %o0=nr, %o1=addr */
+	.globl	___test_and_set_le_bit
+___test_and_set_le_bit:	/* %o0=nr, %o1=addr */
 	srlx	%o0, 5, %g1
 	mov	1, %g5
 	sllx	%g1, 2, %g3
@@ -87,8 +87,8 @@
 2:	retl
 	 nop
 
-	.globl	__test_and_clear_le_bit
-__test_and_clear_le_bit:	/* %o0=nr, %o1=addr */
+	.globl	___test_and_clear_le_bit
+___test_and_clear_le_bit:	/* %o0=nr, %o1=addr */
 	srlx	%o0, 5, %g1
 	mov	1, %g5
 	sllx	%g1, 2, %g3
diff -urN linux-2.4.4-pre3/arch/sparc64/solaris/timod.c linux/arch/sparc64/solaris/timod.c
--- linux-2.4.4-pre3/arch/sparc64/solaris/timod.c	Fri Aug  4 18:16:11 2000
+++ linux/arch/sparc64/solaris/timod.c	Mon Dec  3 22:35:22 2001
@@ -611,7 +611,7 @@
 		return 0;
 	}
 	default:
-		printk("timod_putmsg: unsuported command %u.\n", ret);
+		printk("timod_putmsg: unsupported command %u.\n", ret);
 		break;
 	}
 	return -EINVAL;
diff -urN linux-2.4.4-pre3/drivers/block/cciss.c linux/drivers/block/cciss.c
--- linux-2.4.4-pre3/drivers/block/cciss.c	Fri Feb  9 11:30:22 2001
+++ linux/drivers/block/cciss.c	Mon Dec  3 22:35:22 2001
@@ -583,13 +583,15 @@
 		if (iocommand.Request.Type.Direction == XFER_WRITE)
 		{
 			/* Copy the data into the buffer we created */ 
-			if (copy_from_user(buff, iocommand.buf, iocommand.buf_size))
+			if (copy_from_user(buff, iocommand.buf,
+						iocommand.buf_size)) {
+				kfree(buff);
 				return -EFAULT;
+			}
 		}
 		if ((c = cmd_alloc(NULL)) == NULL)
 		{
-			if(buff!=NULL)
-				kfree(buff);
+			kfree(buff);
 			return -ENOMEM;
 		}
 			// Fill in the command type 
@@ -636,8 +638,7 @@
 		if ( copy_to_user((void *) arg, &iocommand, sizeof( IOCTL_Command_struct) ) )
 		{
 			cmd_free(NULL, c);
-			if (buff != NULL) 
-				kfree(buff);
+			kfree(buff);
 			return( -EFAULT);	
 		} 	
 
@@ -648,11 +649,11 @@
 			{
 			             cmd_free(NULL, c);
 			             kfree(buff);
+				     return -EFAULT;	
 			}
                 }
 		cmd_free(NULL, c);
-                if (buff != NULL)
-                	kfree(buff);
+                kfree(buff);
                 return(0);
 	} 
 
@@ -761,7 +762,7 @@
         hba[ctlr]->gendisk.nr_real = 0;
 
         /*
-         * Tell the array controller not to give us any interupts while
+         * Tell the array controller not to give us any interrupts while
          * we check the new geometry.  Then turn interrupts back on when
          * we're done.
          */
@@ -1087,7 +1088,7 @@
 	if (timeout)
 		status = 0; 
 	if(cmd->err_info->CommandStatus != 0) 
-	{ /* an error has occured */ 
+	{ /* an error has occurred */ 
 		switch(cmd->err_info->CommandStatus)
 		{
 			case CMD_TARGET_STATUS:
@@ -1846,12 +1847,9 @@
 			|| (hba[i]->errinfo_pool == NULL))
                 {
                         nr_ctlr = i;
-			if(hba[i]->cmd_pool_bits)
-                                kfree(hba[i]->cmd_pool_bits);
-                        if(hba[i]->cmd_pool)
-                                kfree(hba[i]->cmd_pool);
-			if(hba[i]->errinfo_pool)
-				kfree(hba[i]->errinfo_pool);
+			kfree(hba[i]->cmd_pool_bits);
+			kfree(hba[i]->cmd_pool);
+			kfree(hba[i]->errinfo_pool);
                         free_irq(hba[i]->intr, hba[i]);
                         unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
                         num_cntlrs_reg--;
diff -urN linux-2.4.4-pre3/drivers/block/cciss.h linux/drivers/block/cciss.h
--- linux-2.4.4-pre3/drivers/block/cciss.h	Sat Feb  3 12:13:19 2001
+++ linux/drivers/block/cciss.h	Mon Dec  3 22:35:22 2001
@@ -122,7 +122,7 @@
 }
 
 /*  
- *  This card is the oposite of the other cards.  
+ *  This card is the opposite of the other cards.  
  *   0 turns interrupts on... 
  *   0x08 turns them off... 
  */
@@ -138,7 +138,7 @@
 	}
 }
 /*
- *  This card is the oposite of the other cards.
+ *  This card is the opposite of the other cards.
  *   0 turns interrupts on...
  *   0x04 turns them off...
  */
diff -urN linux-2.4.4-pre3/drivers/block/cciss_cmd.h linux/drivers/block/cciss_cmd.h
--- linux-2.4.4-pre3/drivers/block/cciss_cmd.h	Fri Sep 22 17:11:37 2000
+++ linux/drivers/block/cciss_cmd.h	Mon Dec  3 22:35:22 2001
@@ -222,7 +222,7 @@
   ErrDescriptor_struct     ErrDesc;
   SGDescriptor_struct      SG[MAXSGENTRIES];
 	/* information associated with the command */ 
-  __u32			   busaddr; /* physical addres of this record */
+  __u32			   busaddr; /* physical address of this record */
   ErrorInfo_struct * 	   err_info; /* pointer to the allocated mem */ 
   int			   cmd_type; 
   struct _CommandList_struct *prev;
diff -urN linux-2.4.4-pre3/drivers/char/Makefile linux/drivers/char/Makefile
--- linux-2.4.4-pre3/drivers/char/Makefile	Tue Mar  6 19:44:34 2001
+++ linux/drivers/char/Makefile	Mon Dec  3 22:35:22 2001
@@ -68,6 +68,23 @@
   KEYBD    = scan_keyb.o hp600_keyb.o
   CONSOLE  = console.o
   endif
+  ifeq ($(CONFIG_SH_DMIDA),y)
+  # DMIDA does not connect the HD64465 PS/2 keyboard port
+  # but we allow for USB keyboards to be plugged in.
+  KEYMAP   = defkeymap.o
+  KEYBD    = # hd64465_keyb.o pc_keyb.o
+  CONSOLE  = console.o
+  endif
+  ifeq ($(CONFIG_SH_EC3104),y)
+  KEYMAP   = defkeymap.o
+  KEYBD    = ec3104_keyb.o
+  CONSOLE  = console.o
+  endif
+  ifeq ($(CONFIG_SH_DREAMCAST),y)
+  KEYMAP   = defkeymap.o
+  KEYBD    =
+  CONSOLE  = console.o
+  endif
 endif
 
 ifeq ($(CONFIG_DECSTATION),y)
diff -urN linux-2.4.4-pre3/drivers/char/drm/ffb_drv.c linux/drivers/char/drm/ffb_drv.c
--- linux-2.4.4-pre3/drivers/char/drm/ffb_drv.c	Mon Dec  3 22:35:11 2001
+++ linux/drivers/char/drm/ffb_drv.c	Mon Dec  3 22:35:22 2001
@@ -1,4 +1,4 @@
-/* $Id: ffb_drv.c,v 1.11 2001/03/27 02:36:37 davem Exp $
+/* $Id: ffb_drv.c,v 1.12 2001/04/14 01:12:03 davem Exp $
  * ffb_drv.c: Creator/Creator3D direct rendering driver.
  *
  * Copyright (C) 2000 David S. Miller (davem@redhat.com)
diff -urN linux-2.4.4-pre3/drivers/char/ec3104_keyb.c linux/drivers/char/ec3104_keyb.c
--- linux-2.4.4-pre3/drivers/char/ec3104_keyb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/ec3104_keyb.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,461 @@
+/*
+ * linux/drivers/char/ec3104_keyb.c
+ * 
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * based on linux/drivers/char/pc_keyb.c, which had the following comments:
+ *
+ * Separation of the PC low-level part by Geert Uytterhoeven, May 1997
+ * See keyboard.c for the whole history.
+ *
+ * Major cleanup by Martin Mares, May 1997
+ *
+ * Combined the keyboard and PS/2 mouse handling into one file,
+ * because they share the same hardware.
+ * Johan Myreen <jem@iki.fi> 1998-10-08.
+ *
+ * Code fixes to handle mouse ACKs properly.
+ * C. Scott Ananian <cananian@alumni.princeton.edu> 1999-01-29.
+ */
+/* EC3104 note:
+ * This code was written without any documentation about the EC3104 chip.  While
+ * I hope I got most of the basic functionality right, the register names I use
+ * are most likely completely different from those in the chip documentation.
+ *
+ * If you have any further information about the EC3104, please tell me
+ * (prumpf@tux.org).
+ */
+
+#include <linux/config.h>
+
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/init.h>
+#include <linux/kbd_ll.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+#include <linux/kbd_kern.h>
+#include <linux/smp_lock.h>
+
+#include <asm/keyboard.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/ec3104.h>
+
+#include <asm/io.h>
+
+/* Some configuration switches are present in the include file... */
+
+#include <linux/pc_keyb.h>
+
+#define MSR_CTS 0x10
+#define MCR_RTS 0x02
+#define LSR_DR 0x01
+#define LSR_BOTH_EMPTY 0x60
+
+static struct e5_struct {
+	u8 packet[8];
+	int pos;
+	int length;
+
+	u8 cached_mcr;
+	u8 last_msr;
+} ec3104_keyb;
+	
+/* Simple translation table for the SysRq keys */
+
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char ec3104_kbd_sysrq_xlate[128] =
+	"\000\0331234567890-=\177\t"			/* 0x00 - 0x0f */
+	"qwertyuiop[]\r\000as"				/* 0x10 - 0x1f */
+	"dfghjkl;'`\000\\zxcv"				/* 0x20 - 0x2f */
+	"bnm,./\000*\000 \000\201\202\203\204\205"	/* 0x30 - 0x3f */
+	"\206\207\210\211\212\000\000789-456+1"		/* 0x40 - 0x4f */
+	"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
+	"\r\000/";					/* 0x60 - 0x6f */
+#endif
+
+static void kbd_write_command_w(int data);
+static void kbd_write_output_w(int data);
+#ifdef CONFIG_PSMOUSE
+static void aux_write_ack(int val);
+static void __aux_write_ack(int val);
+#endif
+
+static spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+static unsigned char handle_kbd_event(void);
+
+/* used only by send_data - set by keyboard_interrupt */
+static volatile unsigned char reply_expected;
+static volatile unsigned char acknowledge;
+static volatile unsigned char resend;
+
+
+int ec3104_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+	return 0;
+}
+
+int ec3104_kbd_getkeycode(unsigned int scancode)
+{
+	return 0;
+}
+
+
+/* yes, it probably would be faster to use an array.  I don't care. */
+
+static inline unsigned char ec3104_scan2key(unsigned char scancode)
+{
+	switch (scancode) {
+	case  1: /* '`' */
+		return 41;
+		
+	case  2 ... 27:
+		return scancode;
+		
+	case 28: /* '\\' */
+		return 43;
+
+	case 29 ... 39:
+		return scancode + 1;
+
+	case 40: /* '\r' */
+		return 28;
+
+	case 41 ... 50:
+		return scancode + 3;
+
+	case 51: /* ' ' */
+		return 57;
+		
+	case 52: /* escape */
+		return 1;
+
+	case 54: /* insert/delete (labelled delete) */
+		/* this should arguably be 110, but I'd like to have ctrl-alt-del
+		 * working with a standard keymap */
+		return 111;
+
+	case 55: /* left */
+		return 105;
+	case 56: /* home */
+		return 102;
+	case 57: /* end */
+		return 107;
+	case 58: /* up */
+		return 103;
+	case 59: /* down */
+		return 108;
+	case 60: /* pgup */
+		return 104;
+	case 61: /* pgdown */
+		return 109;
+	case 62: /* right */
+		return 106;
+
+	case 79 ... 88: /* f1 - f10 */
+		return scancode - 20;
+
+	case 89 ... 90: /* f11 - f12 */
+		return scancode - 2;
+
+	case 91: /* left shift */
+		return 42;
+
+	case 92: /* right shift */
+		return 54;
+
+	case 93: /* left alt */
+		return 56;
+	case 94: /* right alt */
+		return 100;
+	case 95: /* left ctrl */
+		return 29;
+	case 96: /* right ctrl */
+		return 97;
+
+	case 97: /* caps lock */
+		return 58;
+	case 102: /* left windows */
+		return 125;
+	case 103: /* right windows */
+		return 126;
+
+	case 106: /* Fn */
+		/* this is wrong. */
+		return 84;
+
+	default:
+		return 0;
+	}
+}
+		
+int ec3104_kbd_translate(unsigned char scancode, unsigned char *keycode,
+		    char raw_mode)
+{
+	scancode &= 0x7f;
+
+	*keycode = ec3104_scan2key(scancode);
+
+ 	return 1;
+}
+
+char ec3104_kbd_unexpected_up(unsigned char keycode)
+{
+	return 0200;
+}
+
+static inline void handle_keyboard_event(unsigned char scancode)
+{
+#ifdef CONFIG_VT
+	handle_scancode(scancode, !(scancode & 0x80));
+#endif				
+	tasklet_schedule(&keyboard_tasklet);
+}	
+
+void ec3104_kbd_leds(unsigned char leds)
+{
+}
+
+static u8 e5_checksum(u8 *packet, int count)
+{
+	int i;
+	u8 sum = 0;
+
+	for (i=0; i<count; i++)
+		sum ^= packet[i];
+		
+	if (sum & 0x80)
+		sum ^= 0xc0;
+
+	return sum;
+}
+
+static void e5_wait_for_cts(struct e5_struct *k)
+{
+	u8 msr;
+		
+	do {
+		msr = ctrl_inb(EC3104_SER4_MSR);
+	} while (!(msr & MSR_CTS));
+}
+
+
+static void e5_send_byte(u8 byte, struct e5_struct *k)
+{
+	u8 status;
+		
+	do {
+		status = ctrl_inb(EC3104_SER4_LSR);
+	} while ((status & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY);
+	
+	printk("<%02x>", byte);
+
+	ctrl_outb(byte, EC3104_SER4_DATA);
+
+	do {
+		status = ctrl_inb(EC3104_SER4_LSR);
+	} while ((status & LSR_BOTH_EMPTY) != LSR_BOTH_EMPTY);
+	
+}
+
+static int e5_send_packet(u8 *packet, int count, struct e5_struct *k)
+{
+	int i;
+
+	disable_irq(EC3104_IRQ_SER4);
+	
+	if (k->cached_mcr & MCR_RTS) {
+		printk("e5_send_packet: too slow\n");
+		enable_irq(EC3104_IRQ_SER4);
+		return -EAGAIN;
+	}
+
+	k->cached_mcr |= MCR_RTS;
+	ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
+
+	e5_wait_for_cts(k);
+
+	printk("p: ");
+
+	for(i=0; i<count; i++)
+		e5_send_byte(packet[i], k);
+
+	e5_send_byte(e5_checksum(packet, count), k);
+
+	printk("\n");
+
+	udelay(1500);
+
+	k->cached_mcr &= ~MCR_RTS;
+	ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
+
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	
+	
+
+	enable_irq(EC3104_IRQ_SER4);
+
+	
+
+	return 0;
+}
+
+/*
+ * E5 packets we know about:
+ * E5->host 0x80 0x05 <checksum> - resend packet
+ * host->E5 0x83 0x43 <contrast> - set LCD contrast
+ * host->E5 0x85 0x41 0x02 <brightness> 0x02 - set LCD backlight
+ * E5->host 0x87 <ps2 packet> 0x00 <checksum> - external PS2 
+ * E5->host 0x88 <scancode> <checksum> - key press
+ */
+
+static void e5_receive(struct e5_struct *k)
+{
+	k->packet[k->pos++] = ctrl_inb(EC3104_SER4_DATA);
+
+	if (k->pos == 1) {
+		switch(k->packet[0]) {
+		case 0x80:
+			k->length = 3;
+			break;
+			
+		case 0x87: /* PS2 ext */
+			k->length = 6;
+			break;
+
+		case 0x88: /* keyboard */
+			k->length = 3;
+			break;
+
+		default:
+			k->length = 1;
+			printk(KERN_WARNING "unknown E5 packet %02x\n",
+			       k->packet[0]);
+		}
+	}
+
+	if (k->pos == k->length) {
+		int i;
+
+		if (e5_checksum(k->packet, k->length) != 0)
+			printk(KERN_WARNING "E5: wrong checksum\n");
+
+#if 0
+		printk("E5 packet [");
+		for(i=0; i<k->length; i++) {
+			printk("%02x ", k->packet[i]);
+		}
+
+		printk("(%02x)]\n", e5_checksum(k->packet, k->length-1));
+#endif
+
+		switch(k->packet[0]) {
+		case 0x80:
+		case 0x88:
+			handle_keyboard_event(k->packet[1]);
+			break;
+		}
+
+		k->pos = k->length = 0;
+	}
+}
+
+static void ec3104_keyb_interrupt(int irq, void *data, struct pt_regs *regs)
+{
+	struct e5_struct *k = &ec3104_keyb;
+	u8 msr, lsr;
+
+	kbd_pt_regs = regs;
+
+	msr = ctrl_inb(EC3104_SER4_MSR);
+	
+	if ((msr & MSR_CTS) && !(k->last_msr & MSR_CTS)) {
+		if (k->cached_mcr & MCR_RTS)
+			printk("confused: RTS already high\n");
+		/* CTS went high.  Send RTS. */
+		k->cached_mcr |= MCR_RTS;
+		
+		ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
+	} else if ((!(msr & MSR_CTS)) && (k->last_msr & MSR_CTS)) {
+		/* CTS went low. */
+		if (!(k->cached_mcr & MCR_RTS))
+			printk("confused: RTS already low\n");
+
+		k->cached_mcr &= ~MCR_RTS;
+
+		ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
+	}
+
+	k->last_msr = msr;
+
+	lsr = ctrl_inb(EC3104_SER4_LSR);
+
+	if (lsr & LSR_DR)
+		e5_receive(k);
+}
+
+static void ec3104_keyb_clear_state(void)
+{
+	struct e5_struct *k = &ec3104_keyb;
+	u8 msr, lsr;
+	
+	/* we want CTS to be low */
+	k->last_msr = 0;
+
+	for (;;) {
+		schedule_timeout(HZ/10);
+
+		msr = ctrl_inb(EC3104_SER4_MSR);
+	
+		lsr = ctrl_inb(EC3104_SER4_LSR);
+		
+		if (lsr & LSR_DR) {
+			e5_receive(k);
+			continue;
+		}
+
+		if ((msr & MSR_CTS) && !(k->last_msr & MSR_CTS)) {
+			if (k->cached_mcr & MCR_RTS)
+				printk("confused: RTS already high\n");
+			/* CTS went high.  Send RTS. */
+			k->cached_mcr |= MCR_RTS;
+		
+			ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
+		} else if ((!(msr & MSR_CTS)) && (k->last_msr & MSR_CTS)) {
+			/* CTS went low. */
+			if (!(k->cached_mcr & MCR_RTS))
+				printk("confused: RTS already low\n");
+			
+			k->cached_mcr &= ~MCR_RTS;
+			
+			ctrl_outb(k->cached_mcr, EC3104_SER4_MCR);
+		} else
+			break;
+
+		k->last_msr = msr;
+
+		continue;
+	}
+}
+
+void __init ec3104_kbd_init_hw(void)
+{
+	ec3104_keyb.last_msr = ctrl_inb(EC3104_SER4_MSR);
+	ec3104_keyb.cached_mcr = ctrl_inb(EC3104_SER4_MCR);
+
+	ec3104_keyb_clear_state();
+
+	/* Ok, finally allocate the IRQ, and off we go.. */
+	request_irq(EC3104_IRQ_SER4, ec3104_keyb_interrupt, 0, "keyboard", NULL);
+}
diff -urN linux-2.4.4-pre3/drivers/char/epca.c linux/drivers/char/epca.c
--- linux-2.4.4-pre3/drivers/char/epca.c	Fri Feb 16 16:02:35 2001
+++ linux/drivers/char/epca.c	Mon Dec  3 22:35:22 2001
@@ -769,7 +769,7 @@
 		globalwinon(ch);
 
 		/* -----------------------------------------------------------------	
-			Anding against size will wrap the pointer back to its begining 
+			Anding against size will wrap the pointer back to its beginning 
 			position if it is necessary.  This will only work if size is
 			a power of 2 which should always be the case.  Size is determined 
 			by the cards on board FEP/OS.
@@ -789,7 +789,7 @@
 			tail = bc->tout;
 
 		/* ------------------------------------------------------------------	
-			Anding against size will wrap the pointer back to its begining 
+			Anding against size will wrap the pointer back to its beginning 
 			position if it is necessary.  This will only work if size is
 			a power of 2 which should always be the case.  Size is determined 
 			by the cards on board FEP/OS.
@@ -818,7 +818,7 @@
 		                tail                               head
 
 			The above diagram shows that buffer locations 2,3,4,5 and 6 have
-			data to be transmited, while head points at the next empty
+			data to be transmitted, while head points at the next empty
 			location.  To calculate how much space is available first we have
 			to determine if the head pointer (tin) has wrapped.  To do this
 			compare the head pointer to the tail pointer,  If head is equal
@@ -827,9 +827,9 @@
 			that value from the buffers size.  A one is subtracted from the
 			new value to indicate how much space is available between the 
 			head pointer and end of buffer; as well as the space between the
-			begining of the buffer and the tail.  If the head is not greater
+			beginning of the buffer and the tail.  If the head is not greater
 			or equal to the tail this indicates that the head has wrapped
-			around to the begining of the buffer.  To calculate the space 
+			around to the beginning of the buffer.  To calculate the space 
 			available in this case simply subtract head from tail.  This new 
 			value minus one represents the space available betwwen the head 
 			and tail pointers.  In this example head (7) is greater than tail (2)
@@ -849,7 +849,7 @@
 		                head                               tail
 
 			The above diagram shows that buffer locations 7,8,9,0 and 1 have
-			data to be transmited, while head points at the next empty
+			data to be transmitted, while head points at the next empty
 			location.  To find the space available we compare head to tail.  If
 			head is not equal to, or greater than tail this indicates that head
 			has wrapped around. In this case head (2) is not equal to, or
@@ -1339,7 +1339,7 @@
 		}
 
 		/* ---------------------------------------------------------------
-			Allow someone else to be scheduled.  We will occasionaly go
+			Allow someone else to be scheduled.  We will occasionally go
 			through this loop until one of the above conditions change.
 			The below schedule call will allow other processes to enter and
 			prevent this loop from hogging the cpu.
@@ -1685,7 +1685,7 @@
 		       the boards array is correct.  This could be wrong if
 		       the card in question is PCI (And therefore has no ports 
 		       entry in the boards structure.)  The rest of the 
-		       information will be valid for PCI because the begining
+		       information will be valid for PCI because the beginning
 		       of pc_init scans for PCI and determines i/o and base
 		       memory addresses.  I am not sure if it is possible to 
 		       read the number of ports supported by the card prior to
@@ -1937,7 +1937,7 @@
  
 	/*  -------------------------------------------------------------
 		This call is made by the user via. the ioctl call DIGI_INIT.
-		It is resposible for setting up all the card specific stuff.
+		It is responsible for setting up all the card specific stuff.
 	---------------------------------------------------------------- */
 	bd = &boards[crd];
 
diff -urN linux-2.4.4-pre3/drivers/char/mem.c linux/drivers/char/mem.c
--- linux-2.4.4-pre3/drivers/char/mem.c	Mon Mar 19 12:35:08 2001
+++ linux/drivers/char/mem.c	Mon Dec  3 22:35:22 2001
@@ -41,6 +41,9 @@
 #ifdef CONFIG_MDA_CONSOLE
 extern void mda_console_init(void);
 #endif
+#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
+extern void tapechar_init(void);
+#endif
 #if defined(CONFIG_ADB)
 extern void adbdev_init(void);
 #endif
@@ -639,6 +642,9 @@
 #endif
 #ifdef CONFIG_FTAPE
 	ftape_init();
+#endif
+#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
+	tapechar_init();
 #endif
 #if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_CHAR)
 	tapechar_init();
diff -urN linux-2.4.4-pre3/drivers/char/misc.c linux/drivers/char/misc.c
--- linux-2.4.4-pre3/drivers/char/misc.c	Sun Mar 25 18:24:31 2001
+++ linux/drivers/char/misc.c	Mon Dec  3 22:35:22 2001
@@ -73,10 +73,8 @@
 extern int rtc_DP8570A_init(void);
 extern int rtc_MK48T08_init(void);
 extern int ds1286_init(void);
-extern int dsp56k_init(void);
 extern int radio_init(void);
 extern int pmu_device_init(void);
-extern int qpmouse_init(void);
 extern int tosh_init(void);
 
 static int misc_read_proc(char *buf, char **start, off_t offset,
@@ -173,10 +171,20 @@
 int misc_register(struct miscdevice * misc)
 {
 	static devfs_handle_t devfs_handle;
-
+	struct miscdevice *c;
+	
 	if (misc->next || misc->prev)
 		return -EBUSY;
 	down(&misc_sem);
+	c = misc_list.next;
+
+	while ((c != &misc_list) && (c->minor != misc->minor))
+		c = c->next;
+	if (c != &misc_list) {
+		up(&misc_sem);
+		return -EBUSY;
+	}
+
 	if (misc->minor == MISC_DYNAMIC_MINOR) {
 		int i = DYNAMIC_MINORS;
 		while (--i >= 0)
@@ -245,9 +253,6 @@
 int __init misc_init(void)
 {
 	create_proc_read_entry("misc", 0, 0, misc_read_proc, NULL);
-#if defined CONFIG_82C710_MOUSE
-	qpmouse_init();
-#endif
 #ifdef CONFIG_MVME16x
 	rtc_MK48T08_init();
 #endif
@@ -256,9 +261,6 @@
 #endif
 #ifdef CONFIG_SGI_DS1286
 	ds1286_init();
-#endif
-#ifdef CONFIG_ATARI_DSP56K
-	dsp56k_init();
 #endif
 #ifdef CONFIG_MISC_RADIO
 	radio_init();
diff -urN linux-2.4.4-pre3/drivers/char/n_r3964.c linux/drivers/char/n_r3964.c
--- linux-2.4.4-pre3/drivers/char/n_r3964.c	Mon Dec  3 22:35:11 2001
+++ linux/drivers/char/n_r3964.c	Mon Dec  3 22:35:22 2001
@@ -983,13 +983,14 @@
    {
 queue_the_message:
 
-      save_flags(flags);
-      cli();
-
       pMsg = kmalloc(sizeof(struct r3964_message), GFP_KERNEL);
       TRACE_M("add_msg - kmalloc %x",(int)pMsg);
-      if(pMsg==NULL)
+      if(pMsg==NULL) {
          return;
+      }
+
+      save_flags(flags);
+      cli();
 
       pMsg->msg_id = msg_id;
       pMsg->arg    = arg;
diff -urN linux-2.4.4-pre3/drivers/char/qpmouse.c linux/drivers/char/qpmouse.c
--- linux-2.4.4-pre3/drivers/char/qpmouse.c	Fri Feb  9 11:30:22 2001
+++ linux/drivers/char/qpmouse.c	Mon Dec  3 22:35:22 2001
@@ -24,9 +24,8 @@
  */
 
 #include <linux/module.h>
- 
-#include <linux/sched.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/fcntl.h>
 #include <linux/errno.h>
@@ -146,11 +145,11 @@
 	fasync_qp(-1, file, 0);
 	if (!--qp_count) {
 		if (!poll_qp_status())
-			printk("Warning: Mouse device busy in release_qp()\n");
+			printk(KERN_WARNING "Warning: Mouse device busy in release_qp()\n");
 		status = inb_p(qp_status);
 		outb_p(status & ~(QP_ENABLE|QP_INTS_ON), qp_status);
 		if (!poll_qp_status())
-			printk("Warning: Mouse device busy in release_qp()\n");
+			printk(KERN_WARNING "Warning: Mouse device busy in release_qp()\n");
 		free_irq(QP_IRQ, NULL);
 	}
 	unlock_kernel();
@@ -188,7 +187,7 @@
 	outb_p(status, qp_status);              /* Enable interrupts */
 
 	while (!poll_qp_status()) {
-		printk("Error: Mouse device busy in open_qp()\n");
+		printk(KERN_ERR "Error: Mouse device busy in open_qp()\n");
 		qp_count--;
 		status &= ~(QP_ENABLE|QP_INTS_ON);
 		outb_p(status, qp_status);
@@ -303,7 +302,9 @@
  * Initialize driver.
  */
 static struct miscdevice qp_mouse = {
-	PSMOUSE_MINOR, "QPmouse", &qp_fops
+	minor:		PSMOUSE_MINOR,
+	name:		"QPmouse",
+	fops:		&qp_fops,
 };
 
 /*
@@ -337,37 +338,36 @@
 	return 1;
 }
 
-int __init qpmouse_init(void)
+static const char msg_banner[] __initdata = KERN_INFO "82C710 type pointing device detected -- driver installed.\n";
+static const char msg_nomem[]  __initdata = KERN_ERR "qpmouse: no queue memory.\n";
+
+static int __init qpmouse_init_driver(void)
 {
 	if (!probe_qp())
 		return -EIO;
 
-	printk(KERN_INFO "82C710 type pointing device detected -- driver installed.\n");
+	printk(msg_banner);
+
 /*	printk("82C710 address = %x (should be 0x310)\n", qp_data); */
 	queue = (struct qp_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
-	if(queue==NULL)
-	{
-		printk(KERN_ERR "qpmouse: no queue memory.\n");
+	if (queue == NULL) {
+		printk(msg_nomem);
 		return -ENOMEM;
-	}	
+	}
 	qp_present = 1;
 	misc_register(&qp_mouse);
 	memset(queue, 0, sizeof(*queue));
 	queue->head = queue->tail = 0;
 	init_waitqueue_head(&queue->proc_list);
-
 	return 0;
 }
 
-#ifdef MODULE
-int init_module(void)
-{
-	return qpmouse_init();
-}
-
-void cleanup_module(void)
+static void __exit qpmouse_exit_driver(void)
 {
 	misc_deregister(&qp_mouse);
 	kfree(queue);
 }
-#endif
+
+module_init(qpmouse_init_driver);
+module_exit(qpmouse_exit_driver);
+
diff -urN linux-2.4.4-pre3/drivers/char/qtronix.c linux/drivers/char/qtronix.c
--- linux-2.4.4-pre3/drivers/char/qtronix.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/qtronix.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,597 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Qtronix 990P infrared keyboard driver.
+ *
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *
+ *  The bottom portion of this driver was take from 
+ *  pc_keyb.c  Please see that file for copyrights.
+ *
+ *  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.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+
+/* 
+ * NOTE:  
+ *
+ *	This driver has only been tested with the Consumer IR
+ *	port of the ITE 8172 system controller.
+ *
+ *	You do not need this driver if you are using the ps/2 or
+ *	USB adapter that the keyboard ships with.  You only need 
+ *	this driver if your board has a IR port and the keyboard
+ *	data is being sent directly to the IR.  In that case,
+ *	you also need some low-level IR support. See it8172_cir.c.
+ *	
+ */
+
+#ifdef CONFIG_QTRONIX_KEYBOARD
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+
+#include <asm/it8172/it8172.h>
+#include <asm/it8172/it8172_int.h>
+#include <asm/it8172/it8172_cir.h>
+
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/init.h>
+#include <linux/kbd_ll.h>
+#include <linux/delay.h>
+#include <linux/random.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include <linux/malloc.h>
+#include <linux/kbd_kern.h>
+#include <linux/smp_lock.h>
+#include <asm/io.h>
+#include <linux/pc_keyb.h>
+
+#include <asm/keyboard.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#define leading1 0
+#define leading2 0xF
+
+#define KBD_CIR_PORT 0
+#define AUX_RECONNECT 170 /* scancode when ps2 device is plugged (back) in */
+
+static int data_index;
+struct cir_port *cir;
+static unsigned char kbdbytes[5];
+static unsigned char cir_data[32]; /* we only need 16 chars */
+
+static void kbd_int_handler(int irq, void *dev_id, struct pt_regs *regs);
+static int handle_data(unsigned char *p_data);
+static inline void handle_mouse_event(unsigned char scancode);
+static inline void handle_keyboard_event(unsigned char scancode, int down);
+static int __init psaux_init(void);
+
+static struct aux_queue *queue;	/* Mouse data buffer. */
+static int aux_count = 0;
+
+/*
+ * Keys accessed through the 'Fn' key
+ * The Fn key does not produce a key-up sequence. So, the first
+ * time the user presses it, it will be key-down event. The key
+ * stays down until the user presses it again.
+ */
+#define NUM_FN_KEYS 56
+static unsigned char fn_keys[NUM_FN_KEYS] = {
+	0,0,0,0,0,0,0,0,        /* 0 7   */
+	8,9,10,93,0,0,0,0,      /* 8 15  */
+	0,0,0,0,0,0,0,5,        /* 16 23 */
+	6,7,91,0,0,0,0,0,       /* 24 31 */
+	0,0,0,0,0,2,3,4,        /* 32 39 */
+	92,0,0,0,0,0,0,0,       /* 40 47 */
+	0,0,0,0,11,0,94,95        /* 48 55 */
+
+};
+
+void init_qtronix_990P_kbd(void)
+{
+	int retval;
+
+	cir = (struct cir_port *)kmalloc(sizeof(struct cir_port), GFP_KERNEL);
+	if (!cir) {
+		printk("Unable to initialize Qtronix keyboard\n");
+		return;
+	}
+
+	/* 
+	 * revisit
+	 * this should be programmable, somehow by the, by the user.
+	 */
+	cir->port = KBD_CIR_PORT;
+	cir->baud_rate = 0x1d;
+	cir->rdwos = 0;
+	cir->rxdcr = 0x3;
+	cir->hcfs = 0;
+	cir->fifo_tl = 0;
+	cir->cfq = 0x1d;
+	cir_port_init(cir);
+
+	retval = request_irq(IT8172_CIR0_IRQ, kbd_int_handler, 
+			(unsigned long )(SA_INTERRUPT|SA_SHIRQ), 
+			(const char *)"Qtronix IR Keyboard", (void *)cir);
+
+	if (retval) {
+		printk("unable to allocate cir %d irq %d\n", 
+				cir->port, IT8172_CIR0_IRQ);
+	}
+#ifdef CONFIG_PSMOUSE
+	psaux_init();
+#endif
+}
+
+static inline unsigned char BitReverse(unsigned short key)
+{
+	unsigned char rkey = 0;
+	rkey |= (key & 0x1) << 7;
+	rkey |= (key & 0x2) << 5;
+	rkey |= (key & 0x4) << 3;
+	rkey |= (key & 0x8) << 1;
+	rkey |= (key & 0x10) >> 1;
+	rkey |= (key & 0x20) >> 3;
+	rkey |= (key & 0x40) >> 5;
+	rkey |= (key & 0x80) >> 7;
+	return rkey;
+
+}
+
+
+static inline u_int8_t UpperByte(u_int8_t data)
+{
+	return (data >> 4);
+}
+
+
+static inline u_int8_t LowerByte(u_int8_t data)
+{
+	return (data & 0xF);
+}
+
+
+int CheckSumOk(u_int8_t byte1, u_int8_t byte2, 
+		u_int8_t byte3, u_int8_t byte4, u_int8_t byte5)
+{
+	u_int8_t CheckSum;
+
+	CheckSum = (byte1 & 0x0F) + byte2 + byte3 + byte4 + byte5;
+	if ( LowerByte(UpperByte(CheckSum) + LowerByte(CheckSum)) != UpperByte(byte1) )
+		return 0;
+	else
+		return 1;
+}
+
+
+static void kbd_int_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct cir_port *cir;
+	int j;
+	unsigned char int_status;
+
+	cir = (struct cir_port *)dev_id;
+	int_status = get_int_status(cir);;
+	if (int_status & 0x4) {
+		clear_fifo(cir);
+		return;
+	}
+
+	while (cir_get_rx_count(cir)) {
+
+		cir_data[data_index] = cir_read_data(cir);
+
+		if (data_index == 0) {/* expecting first byte */
+			if (cir_data[data_index] != leading1) {
+				//printk("!leading byte %x\n", cir_data[data_index]);
+				set_rx_active(cir);
+				clear_fifo(cir);
+				continue;
+			}
+		}
+		if (data_index == 1) {
+			if ((cir_data[data_index] & 0xf) != leading2) {
+				set_rx_active(cir);
+				data_index = 0; /* start over */
+				clear_fifo(cir);
+				continue;
+			}
+		}
+
+		if ( (cir_data[data_index] == 0xff)) { /* last byte */
+			//printk("data_index %d\n", data_index);
+			set_rx_active(cir);
+#if 0
+			for (j=0; j<=data_index; j++) {
+				printk("rx_data %d:  %x\n", j, cir_data[j]);
+			}
+#endif
+			data_index = 0;
+			handle_data(cir_data);
+			return;
+		}
+		else if (data_index>16) {
+			set_rx_active(cir);
+#if 0
+			printk("warning: data_index %d\n", data_index);
+			for (j=0; j<=data_index; j++) {
+				printk("rx_data %d:  %x\n", j, cir_data[j]);
+			}
+#endif
+			data_index = 0;
+			clear_fifo(cir);
+			return;
+		}
+		data_index++;
+	}
+}
+
+
+#define NUM_KBD_BYTES 5
+static int handle_data(unsigned char *p_data)
+{
+	u_int32_t bit_bucket;
+	u_int32_t i, j;
+	u_int32_t got_bits, next_byte;
+	int down = 0;
+
+	/* Reorganize the bit stream */
+	for (i=0; i<16; i++)
+		p_data[i] = BitReverse(~p_data[i]);
+
+	/* 
+	 * We've already previously checked that p_data[0]
+	 * is equal to leading1 and that (p_data[1] & 0xf)
+	 * is equal to leading2. These twelve bits are the
+	 * leader code.  We can now throw them away (the 12
+	 * bits) and continue parsing the stream.
+	 */
+	bit_bucket = p_data[1] << 12;
+	got_bits = 4;
+	next_byte = 2;
+
+	/* 
+	 * Process four bits at a time
+	 */
+	for (i=0; i<NUM_KBD_BYTES; i++) {
+
+		kbdbytes[i]=0;
+
+		for (j=0; j<8; j++) /* 8 bits per byte */
+		{
+			if (got_bits < 4) {
+				bit_bucket |= (p_data[next_byte++] << (8 - got_bits));
+				got_bits += 8;
+			}
+
+			if ((bit_bucket & 0xF000) == 0x8000) { 
+				/* Convert 1000b to 1 */
+				kbdbytes[i] = 0x80 | (kbdbytes[i] >> 1);
+				got_bits -= 4;
+				bit_bucket = bit_bucket << 4;
+			}
+			else if ((bit_bucket & 0xC000) == 0x8000) {
+				/* Convert 10b to 0 */
+				kbdbytes[i] =  kbdbytes[i] >> 1;
+				got_bits -= 2;
+				bit_bucket = bit_bucket << 2;
+			}
+			else {
+				/* bad serial stream */
+				return 1;
+			}
+
+			if (next_byte > 16) {
+				//printk("error: too many bytes\n");
+				return 1;
+			}
+		}
+	}
+
+
+	if (!CheckSumOk(kbdbytes[0], kbdbytes[1], 
+				kbdbytes[2], kbdbytes[3], kbdbytes[4])) {
+		//printk("checksum failed\n");
+		return 1;
+	}
+
+	if (kbdbytes[1] & 0x08) {
+		//printk("m: %x %x %x\n", kbdbytes[1], kbdbytes[2], kbdbytes[3]);
+		handle_mouse_event(kbdbytes[1]);
+		handle_mouse_event(kbdbytes[2]);
+		handle_mouse_event(kbdbytes[3]);
+	}
+	else {
+		if (kbdbytes[2] == 0) down = 1;
+#if 0
+		if (down)
+			printk("down %d\n", kbdbytes[3]);
+		else
+			printk("up %d\n", kbdbytes[3]);
+#endif
+		handle_keyboard_event(kbdbytes[3], down);
+	}
+	return 0;
+}
+
+
+spinlock_t kbd_controller_lock = SPIN_LOCK_UNLOCKED;
+static unsigned char handle_kbd_event(void);
+
+
+int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+	printk("pckbd_setkeycode scancode %x keycode %x\n", scancode, keycode);
+	return 0;
+}
+
+int pckbd_getkeycode(unsigned int scancode)
+{
+	return scancode;
+}
+
+
+int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+		    char raw_mode)
+{
+	static int prev_scancode = 0;
+
+	if (scancode == 0x00 || scancode == 0xff) {
+		prev_scancode = 0;
+		return 0;
+	}
+
+	/* todo */
+	if (!prev_scancode && scancode == 160) { /* Fn key down */
+		//printk("Fn key down\n");
+		prev_scancode = 160;
+		return 0;
+	}
+	else if (prev_scancode && scancode == 160) { /* Fn key up */
+		//printk("Fn key up\n");
+		prev_scancode = 0;
+		return 0;
+	}
+
+	/* todo */
+	if (prev_scancode == 160) {
+		if (scancode <= NUM_FN_KEYS) {
+			*keycode = fn_keys[scancode];
+			//printk("fn keycode %d\n", *keycode);
+		}
+		else
+			return 0;
+	} 
+	else if (scancode <= 127) {
+		*keycode = scancode;
+	}
+	else
+		return 0;
+
+
+ 	return 1;
+}
+
+char pckbd_unexpected_up(unsigned char keycode)
+{
+	//printk("pckbd_unexpected_up\n");
+	return 0;
+}
+
+static unsigned char kbd_exists = 1;
+
+static inline void handle_keyboard_event(unsigned char scancode, int down)
+{
+	kbd_exists = 1;
+	handle_scancode(scancode, down);
+	tasklet_schedule(&keyboard_tasklet);
+}	
+
+
+void pckbd_leds(unsigned char leds)
+{
+}
+
+/* dummy */
+void pckbd_init_hw(void)
+{
+}
+
+
+
+static inline void handle_mouse_event(unsigned char scancode)
+{
+	if(scancode == AUX_RECONNECT){
+		queue->head = queue->tail = 0;  /* Flush input queue */
+	//	__aux_write_ack(AUX_ENABLE_DEV);  /* ping the mouse :) */
+		return;
+	}
+
+	add_mouse_randomness(scancode);
+	if (aux_count) {
+		int head = queue->head;
+
+		queue->buf[head] = scancode;
+		head = (head + 1) & (AUX_BUF_SIZE-1);
+		if (head != queue->tail) {
+			queue->head = head;
+			kill_fasync(&queue->fasync, SIGIO, POLL_IN);
+			wake_up_interruptible(&queue->proc_list);
+		}
+	}
+}
+
+static unsigned char get_from_queue(void)
+{
+	unsigned char result;
+	unsigned long flags;
+
+	spin_lock_irqsave(&kbd_controller_lock, flags);
+	result = queue->buf[queue->tail];
+	queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
+	spin_unlock_irqrestore(&kbd_controller_lock, flags);
+	return result;
+}
+
+
+static inline int queue_empty(void)
+{
+	return queue->head == queue->tail;
+}
+
+static int fasync_aux(int fd, struct file *filp, int on)
+{
+	int retval;
+
+	//printk("fasync_aux\n");
+	retval = fasync_helper(fd, filp, on, &queue->fasync);
+	if (retval < 0)
+		return retval;
+	return 0;
+}
+
+
+/*
+ * Random magic cookie for the aux device
+ */
+#define AUX_DEV ((void *)queue)
+
+static int release_aux(struct inode * inode, struct file * file)
+{
+	lock_kernel();
+	fasync_aux(-1, file, 0);
+	aux_count--;
+	unlock_kernel();
+	return 0;
+}
+
+static int open_aux(struct inode * inode, struct file * file)
+{
+	if (aux_count++) {
+		return 0;
+	}
+	queue->head = queue->tail = 0;		/* Flush input queue */
+	return 0;
+}
+
+/*
+ * Put bytes from input queue to buffer.
+ */
+
+static ssize_t read_aux(struct file * file, char * buffer,
+			size_t count, loff_t *ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	ssize_t i = count;
+	unsigned char c;
+
+	if (queue_empty()) {
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+		add_wait_queue(&queue->proc_list, &wait);
+repeat:
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (queue_empty() && !signal_pending(current)) {
+			schedule();
+			goto repeat;
+		}
+		current->state = TASK_RUNNING;
+		remove_wait_queue(&queue->proc_list, &wait);
+	}
+	while (i > 0 && !queue_empty()) {
+		c = get_from_queue();
+		put_user(c, buffer++);
+		i--;
+	}
+	if (count-i) {
+		file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+		return count-i;
+	}
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+	return 0;
+}
+
+/*
+ * Write to the aux device.
+ */
+
+static ssize_t write_aux(struct file * file, const char * buffer,
+			 size_t count, loff_t *ppos)
+{
+	/*
+	 * The ITE boards this was tested on did not have the
+	 * transmit wires connected.
+	 */
+	return count;
+}
+
+static unsigned int aux_poll(struct file *file, poll_table * wait)
+{
+	poll_wait(file, &queue->proc_list, wait);
+	if (!queue_empty())
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+struct file_operations psaux_fops = {
+	read:		read_aux,
+	write:		write_aux,
+	poll:		aux_poll,
+	open:		open_aux,
+	release:	release_aux,
+	fasync:		fasync_aux,
+};
+
+/*
+ * Initialize driver.
+ */
+static struct miscdevice psaux_mouse = {
+	PSMOUSE_MINOR, "psaux", &psaux_fops
+};
+
+static int __init psaux_init(void)
+{
+	misc_register(&psaux_mouse);
+	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
+	memset(queue, 0, sizeof(*queue));
+	queue->head = queue->tail = 0;
+	init_waitqueue_head(&queue->proc_list);
+
+	return 0;
+}
+#endif
diff -urN linux-2.4.4-pre3/drivers/char/qtronixmap.map linux/drivers/char/qtronixmap.map
--- linux-2.4.4-pre3/drivers/char/qtronixmap.map	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/qtronixmap.map	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,287 @@
+# Default kernel keymap. This uses 7 modifier combinations.
+keymaps 0-2,4-5,8,12
+# Change the above line into
+#	keymaps 0-2,4-6,8,12
+# in case you want the entries
+#	altgr   control keycode  83 = Boot            
+#	altgr   control keycode 111 = Boot            
+# below.
+#
+# In fact AltGr is used very little, and one more keymap can
+# be saved by mapping AltGr to Alt (and adapting a few entries):
+# keycode 100 = Alt
+#
+keycode   1 = grave        asciitilde
+	alt     keycode   1 = Meta_Escape     
+keycode   2 = one              exclam          
+	alt     keycode   2 = Meta_one        
+keycode   3 = two              at               at              
+	control	keycode   3 = nul             
+	shift	control	keycode   3 = nul             
+	alt	keycode   3 = Meta_two        
+keycode   4 = three            numbersign      
+	control keycode   4 = Escape          
+	alt     keycode   4 = Meta_three      
+keycode   5 = four             dollar           dollar          
+	control keycode   5 = Control_backslash
+	alt     keycode   5 = Meta_four       
+keycode   6 = five             percent         
+	control keycode   6 = Control_bracketright
+	alt     keycode   6 = Meta_five       
+keycode   7 = six              asciicircum     
+	control keycode   7 = Control_asciicircum
+	alt     keycode   7 = Meta_six        
+keycode   8 = seven            ampersand        braceleft       
+	control keycode   8 = Control_underscore
+	alt     keycode   8 = Meta_seven      
+keycode   9 = eight            asterisk         bracketleft     
+	control keycode   9 = Delete          
+	alt     keycode   9 = Meta_eight      
+keycode  10 = nine             parenleft        bracketright    
+	alt     keycode  10 = Meta_nine       
+keycode  11 = zero             parenright       braceright      
+	alt     keycode  11 = Meta_zero       
+keycode  12 = minus            underscore       backslash       
+	control	keycode  12 = Control_underscore
+	shift	control	keycode  12 = Control_underscore
+	alt	keycode  12 = Meta_minus      
+keycode  13 = equal            plus            
+	alt     keycode  13 = Meta_equal      
+keycode  15 = Delete           Delete          
+	control keycode  15 = BackSpace
+	alt     keycode  15 = Meta_Delete     
+keycode  16 = Tab              Tab             
+	alt     keycode  16 = Meta_Tab        
+keycode  17 = q               
+keycode  18 = w               
+keycode  19 = e
+keycode  20 = r               
+keycode  21 = t               
+keycode  22 = y               
+keycode  23 = u	 
+keycode  24 = i               
+keycode  25 = o               
+keycode  26 = p               
+keycode  27 = bracketleft      braceleft       
+	control keycode  27 = Escape          
+	alt     keycode  27 = Meta_bracketleft
+keycode  28 = bracketright     braceright
+	control keycode  28 = Control_bracketright
+	alt     keycode  28 = Meta_bracketright
+keycode  29 = backslash        bar             
+	control keycode  29 = Control_backslash
+	alt     keycode  29 = Meta_backslash  
+keycode  30 = Caps_Lock
+keycode  31 = a               
+keycode  32 = s
+keycode  33 = d
+keycode  34 = f               
+keycode  35 = g               
+keycode  36 = h               
+keycode  37 = j               
+keycode  38 = k               
+keycode  39 = l               
+keycode  40 = semicolon        colon           
+	alt     keycode  39 = Meta_semicolon  
+keycode  41 = apostrophe       quotedbl        
+	control keycode  40 = Control_g       
+	alt     keycode  40 = Meta_apostrophe 
+keycode  42 = grave            asciitilde      
+	control keycode  41 = nul             
+	alt     keycode  41 = Meta_grave      
+keycode  43 = Return          
+	alt     keycode  43 = Meta_Control_m  
+keycode  44 = Shift               
+keycode  46 = z
+keycode  47 = x               
+keycode  48 = c
+keycode  49 = v               
+keycode  50 = b               
+keycode  51 = n
+keycode  52 = m
+keycode  53 = comma            less            
+	alt     keycode  51 = Meta_comma      
+keycode  54 = period           greater         
+	control keycode  52 = Compose         
+	alt     keycode  52 = Meta_period     
+keycode  55 = slash            question        
+	control keycode  53 = Delete          
+	alt     keycode  53 = Meta_slash      
+keycode  57 = Shift
+keycode  58 = Control
+keycode  60 = Alt
+keycode  61 = space            space           
+	control keycode  61 = nul             
+	alt     keycode  61 = Meta_space      
+keycode  62 = Alt
+
+keycode 75 = Insert          
+keycode 76 = Delete          
+
+keycode 83 = Up              
+keycode 84 = Down              
+
+keycode 85 = Prior           
+	shift   keycode 85 = Scroll_Backward 
+keycode 86 = Next            
+	shift   keycode 86 = Scroll_Forward  
+keycode 89 = Right           
+	alt     keycode 89 = Incr_Console
+keycode 79 = Left            
+	alt     keycode 79 = Decr_Console
+
+keycode  90 = Num_Lock
+	shift   keycode  90 = Bare_Num_Lock
+
+keycode 91 = minus
+keycode 92 = plus
+keycode 93 = KP_Multiply
+keycode 94 = period
+keycode 95 = KP_Divide
+
+keycode 107 = Select          
+keycode 108 = Down            
+
+keycode 110 = Escape           Escape          
+	alt     keycode   1 = Meta_Escape     
+
+keycode  112 = F1              F11              Console_13      
+	control keycode  112 = F1              
+	alt     keycode  112 = Console_1       
+	control alt     keycode  112 = Console_1       
+keycode  113 = F2              F12              Console_14      
+	control keycode  113 = F2              
+	alt     keycode  113 = Console_2       
+	control alt     keycode  113 = Console_2       
+keycode  114 = F3              F13              Console_15      
+	control keycode  114 = F3              
+	alt     keycode  114 = Console_3       
+	control alt     keycode  114 = Console_3       
+keycode  115 = F4              F14              Console_16      
+	control keycode  115 = F4              
+	alt     keycode  115 = Console_4       
+	control alt     keycode  115 = Console_4       
+keycode  116 = F5              F15              Console_17      
+	control keycode  116 = F5              
+	alt     keycode  116 = Console_5       
+	control alt     keycode  116 = Console_5       
+keycode  117 = F6              F16              Console_18      
+	control keycode  117 = F6              
+	alt     keycode  117 = Console_6       
+	control alt     keycode  117 = Console_6       
+keycode  118 = F7              F17              Console_19      
+	control keycode  118 = F7              
+	alt     keycode  118 = Console_7       
+	control alt     keycode  118 = Console_7       
+keycode  119 = F8              F18              Console_20      
+	control keycode  119 = F8              
+	alt     keycode  119 = Console_8       
+	control alt     keycode  119 = Console_8       
+keycode  120 = F9              F19              Console_21      
+	control keycode  120 = F9              
+	alt     keycode  120 = Console_9       
+	control alt     keycode  120 = Console_9       
+keycode  121 = F10             F20              Console_22      
+	control keycode  121 = F10             
+	alt     keycode  121 = Console_10      
+	control alt     keycode  121 = Console_10      
+	
+keycode 126 = Pause           
+
+
+string F1 = "\033[[A"
+string F2 = "\033[[B"
+string F3 = "\033[[C"
+string F4 = "\033[[D"
+string F5 = "\033[[E"
+string F6 = "\033[17~"
+string F7 = "\033[18~"
+string F8 = "\033[19~"
+string F9 = "\033[20~"
+string F10 = "\033[21~"
+string F11 = "\033[23~"
+string F12 = "\033[24~"
+string F13 = "\033[25~"
+string F14 = "\033[26~"
+string F15 = "\033[28~"
+string F16 = "\033[29~"
+string F17 = "\033[31~"
+string F18 = "\033[32~"
+string F19 = "\033[33~"
+string F20 = "\033[34~"
+string Find = "\033[1~"
+string Insert = "\033[2~"
+string Remove = "\033[3~"
+string Select = "\033[4~"
+string Prior = "\033[5~"
+string Next = "\033[6~"
+string Macro = "\033[M"
+string Pause = "\033[P"
+compose '`' 'A' to 'À'
+compose '`' 'a' to 'à'
+compose '\'' 'A' to 'Á'
+compose '\'' 'a' to 'á'
+compose '^' 'A' to 'Â'
+compose '^' 'a' to 'â'
+compose '~' 'A' to 'Ã'
+compose '~' 'a' to 'ã'
+compose '"' 'A' to 'Ä'
+compose '"' 'a' to 'ä'
+compose 'O' 'A' to 'Å'
+compose 'o' 'a' to 'å'
+compose '0' 'A' to 'Å'
+compose '0' 'a' to 'å'
+compose 'A' 'A' to 'Å'
+compose 'a' 'a' to 'å'
+compose 'A' 'E' to 'Æ'
+compose 'a' 'e' to 'æ'
+compose ',' 'C' to 'Ç'
+compose ',' 'c' to 'ç'
+compose '`' 'E' to 'È'
+compose '`' 'e' to 'è'
+compose '\'' 'E' to 'É'
+compose '\'' 'e' to 'é'
+compose '^' 'E' to 'Ê'
+compose '^' 'e' to 'ê'
+compose '"' 'E' to 'Ë'
+compose '"' 'e' to 'ë'
+compose '`' 'I' to 'Ì'
+compose '`' 'i' to 'ì'
+compose '\'' 'I' to 'Í'
+compose '\'' 'i' to 'í'
+compose '^' 'I' to 'Î'
+compose '^' 'i' to 'î'
+compose '"' 'I' to 'Ï'
+compose '"' 'i' to 'ï'
+compose '-' 'D' to 'Ð'
+compose '-' 'd' to 'ð'
+compose '~' 'N' to 'Ñ'
+compose '~' 'n' to 'ñ'
+compose '`' 'O' to 'Ò'
+compose '`' 'o' to 'ò'
+compose '\'' 'O' to 'Ó'
+compose '\'' 'o' to 'ó'
+compose '^' 'O' to 'Ô'
+compose '^' 'o' to 'ô'
+compose '~' 'O' to 'Õ'
+compose '~' 'o' to 'õ'
+compose '"' 'O' to 'Ö'
+compose '"' 'o' to 'ö'
+compose '/' 'O' to 'Ø'
+compose '/' 'o' to 'ø'
+compose '`' 'U' to 'Ù'
+compose '`' 'u' to 'ù'
+compose '\'' 'U' to 'Ú'
+compose '\'' 'u' to 'ú'
+compose '^' 'U' to 'Û'
+compose '^' 'u' to 'û'
+compose '"' 'U' to 'Ü'
+compose '"' 'u' to 'ü'
+compose '\'' 'Y' to 'Ý'
+compose '\'' 'y' to 'ý'
+compose 'T' 'H' to 'Þ'
+compose 't' 'h' to 'þ'
+compose 's' 's' to 'ß'
+compose '"' 'y' to 'ÿ'
+compose 's' 'z' to 'ß'
+compose 'i' 'j' to 'ÿ'
diff -urN linux-2.4.4-pre3/drivers/char/rio/rio_linux.c linux/drivers/char/rio/rio_linux.c
--- linux-2.4.4-pre3/drivers/char/rio/rio_linux.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/char/rio/rio_linux.c	Mon Dec  3 22:35:22 2001
@@ -1031,8 +1031,10 @@
  free2:kfree (p->RIOHosts);
  free1:kfree (p);
  free0:
-  rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p %p %p\n", 
-               p, p->RIOHosts, p->RIOPortp, rio_termios, rio_termios);
+  if (p) {
+	rio_dprintk (RIO_DEBUG_INIT, "Not enough memory! %p %p %p %p %p\n", 
+        	       p, p->RIOHosts, p->RIOPortp, rio_termios, rio_termios);
+  }
   return -ENOMEM;
 }
 
diff -urN linux-2.4.4-pre3/drivers/char/rio/rioctrl.c linux/drivers/char/rio/rioctrl.c
--- linux-2.4.4-pre3/drivers/char/rio/rioctrl.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/char/rio/rioctrl.c	Mon Dec  3 22:35:22 2001
@@ -764,7 +764,7 @@
 							PortP->Config &= ~RIO_WAITDRAIN;
 					 	}
 					 /*
-					 ** Store setings if locking or unlocking port or if the
+					 ** Store settings if locking or unlocking port or if the
 					 ** port is not locked, when setting the store option.
 					 */
 					 if (PortP->Mapped &&
diff -urN linux-2.4.4-pre3/drivers/char/serial.c linux/drivers/char/serial.c
--- linux-2.4.4-pre3/drivers/char/serial.c	Mon Dec  3 22:35:11 2001
+++ linux/drivers/char/serial.c	Mon Dec  3 22:35:22 2001
@@ -5726,6 +5726,10 @@
 		case 9600:
 		default:
 			cflag |= B9600;
+			/*
+			 * Set this to a sane value to prevent a divide error
+			 */
+			baud  = 9600;
 			break;
 	}
 	switch(bits) {
diff -urN linux-2.4.4-pre3/drivers/input/keybdev.c linux/drivers/input/keybdev.c
--- linux-2.4.4-pre3/drivers/input/keybdev.c	Sun Mar 25 18:14:21 2001
+++ linux/drivers/input/keybdev.c	Mon Dec  3 22:35:22 2001
@@ -37,7 +37,8 @@
 #include <linux/module.h>
 #include <linux/kbd_kern.h>
 
-#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(__alpha__) || defined(__mips__) || defined(CONFIG_SPARC64)
+#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(__alpha__) || \
+    defined(__mips__) || defined(CONFIG_SPARC64) || defined(CONFIG_SUPERH)
 
 static int x86_sysrq_alt = 0;
 #ifdef CONFIG_SPARC64
diff -urN linux-2.4.4-pre3/drivers/media/radio/Config.in linux/drivers/media/radio/Config.in
--- linux-2.4.4-pre3/drivers/media/radio/Config.in	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/Config.in	Mon Dec  3 22:35:22 2001
@@ -23,7 +23,7 @@
 fi
 dep_tristate '  Guillemot MAXI Radio FM 2000 radio' CONFIG_RADIO_MAXIRADIO $CONFIG_VIDEO_DEV
 dep_tristate '  Maestro on board radio' CONFIG_RADIO_MAESTRO $CONFIG_VIDEO_DEV
-dep_tristate '  Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
+dep_tristate '  miroSOUND PCM20 radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV $CONFIG_SOUND_ACI_MIXER
 dep_tristate '  SF16FMI Radio' CONFIG_RADIO_SF16FMI $CONFIG_VIDEO_DEV
 if [ "$CONFIG_RADIO_SF16FMI" = "y" ]; then
    hex '    SF16FMI I/O port (0x284 or 0x384)' CONFIG_RADIO_SF16FMI_PORT 284
diff -urN linux-2.4.4-pre3/drivers/media/radio/Makefile linux/drivers/media/radio/Makefile
--- linux-2.4.4-pre3/drivers/media/radio/Makefile	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/Makefile	Mon Dec  3 22:35:22 2001
@@ -23,7 +23,9 @@
 
 export-objs     :=	
 
-list-multi	:=	
+list-multi	:= miropcm20.o
+
+miropcm20-objs	:= radio-miropcm20.o rds-miropcm20.o
 
 obj-$(CONFIG_RADIO_AZTECH) += radio-aztech.o
 obj-$(CONFIG_RADIO_RTRACK2) += radio-rtrack2.o
@@ -34,9 +36,12 @@
 obj-$(CONFIG_RADIO_MAXIRADIO) += radio-maxiradio.o
 obj-$(CONFIG_RADIO_RTRACK) += radio-aimslab.o
 obj-$(CONFIG_RADIO_ZOLTRIX) += radio-zoltrix.o
-obj-$(CONFIG_RADIO_MIROPCM20) += radio-miropcm20.o
+obj-$(CONFIG_RADIO_MIROPCM20) += miropcm20.o
 obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o
 obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
 obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
 
 include $(TOPDIR)/Rules.make
+
+miropcm20.o: $(miropcm20-objs)
+	$(LD) -r -o $@ $(miropcm20-objs)
diff -urN linux-2.4.4-pre3/drivers/media/radio/radio-miropcm20.c linux/drivers/media/radio/radio-miropcm20.c
--- linux-2.4.4-pre3/drivers/media/radio/radio-miropcm20.c	Fri Mar  2 11:12:10 2001
+++ linux/drivers/media/radio/radio-miropcm20.c	Mon Dec  3 22:35:22 2001
@@ -2,62 +2,53 @@
  * (c) 1998 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
  * Thanks to Norberto Pellici for the ACI device interface specification
  * The API part is based on the radiotrack driver by M. Kirkwood
- * This driver relies on the aci mixer (drivers/sound/lowlevel/aci.c)
+ * This driver relies on the aci mixer (drivers/sound/aci.c)
  * Look there for further info...
  */
 
-#include <linux/module.h>		/* Modules 			*/
-#include <linux/init.h>			/* Initdata			*/
-#include <asm/uaccess.h>		/* copy to/from user		*/
-#include <linux/videodev.h>		/* kernel radio structs		*/
-#include "../../sound/miroaci.h"	/* ACI Control by acimixer      */
+/* Revision history:
+ *
+ *   1998        Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
+ *   2000-09-05  Robert Siemer <Robert.Siemer@gmx.de>
+ *        removed unfinished volume control (maybe adding it later again)
+ *        use OSS-mixer; added stereo control
+ */
+
+/* What ever you think about the ACI, version 0x07 is not very well!
+ * I cant get frequency, 'tuner status', 'tuner flags' or mute/mono
+ * conditions...                Robert 
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/videodev.h>
+#include <linux/devfs_fs_kernel.h>
+#include <asm/uaccess.h>
+
+char * aci_radio_name;
+
+#include "../../sound/aci.h"
 
 static int users = 0;
 
 struct pcm20_device
 {
-	int port;
-	int curvol;
-	unsigned long curfreq;
+	unsigned long freq;
 	int muted;
+	int stereo;
 };
 
 
-/* local things */
-
-
-static void pcm20_mute(struct pcm20_device *dev)
+static int pcm20_mute(struct pcm20_device *dev, unsigned char mute)
 {
-
-	dev->muted = 1;
-	aci_write_cmd(0xa3,0x01);			
-
+	dev->muted = mute;
+	return aci_write_cmd(0xa3, mute);
 }
 
-static int pcm20_setvol(struct pcm20_device *dev, int vol)
+static int pcm20_stereo(struct pcm20_device *dev, unsigned char stereo)
 {
-
-	if(vol == dev->curvol) {	/* requested volume = current */
-		if (dev->muted) {	/* user is unmuting the card  */
-			dev->muted = 0;
-			aci_write_cmd(0xa3,0x00); 	/* enable card */
-		}	
-	
-		return 0;
-	}
-
-	if(vol == 0) {			/* volume = 0 means mute the card */
-		aci_write_cmd(0x3d, 0x20);
-		aci_write_cmd(0x35, 0x20);
-		return 0;
-	}
-
-	dev->muted = 0;
-	aci_write_cmd(0x3d, 32-vol); 	/* Right Channel */
-	aci_write_cmd(0x35, 32-vol);	/* Left Channel */
-	dev->curvol = vol;
-
-	return 0;
+	dev->stereo = stereo;
+	return aci_write_cmd(0xa4, !stereo);
 }
 
 static int pcm20_setfreq(struct pcm20_device *dev, unsigned long freq)
@@ -65,28 +56,79 @@
 	unsigned char freql;
 	unsigned char freqh;
 
-	freq = (freq * 10) / 16;
-	freql = freq & 0xff;
-	freqh = freq >> 8;	
+	dev->freq=freq;
 
+	freq /= 160;
+	if (!(aci_version==0x07 || aci_version>=0xb0))
+		freq /= 10;  /* I don't know exactly which version
+			      * needs this hack */
+	freql = freq & 0xff;
+	freqh = freq >> 8;
 
-	aci_write_cmd_d(0xa7, freql, freqh);	/*  Tune to frequency	*/
+	aci_rds_cmd(RDS_RESET, 0, 0);
+	pcm20_stereo(dev, 1);
 
-	return 0;
+	return aci_rw_cmd(0xa7, freql, freqh);	/*  Tune to frequency	*/
 }
 
-int pcm20_getsigstr(struct pcm20_device *dev)
+static int pcm20_getflags(struct pcm20_device *dev, __u32 *flags, __u16 *signal)
 {
+	/* okay, check for signal, stereo and rds here... */
+	int i;
 	unsigned char buf;
-	aci_indexed_cmd(0xf0, 0x32, &buf);
-	if ((buf & 0x80) == 0x80)	
+
+	if ((i=aci_rw_cmd(0xa9, -1, -1))<0)
+		return i;
+#if DEBUG
+	printk("check_sig: 0x%x\n", i);
+#endif
+	if (i & 0x80) {
+		/* no signal from tuner */
+		*flags=0;
+		*signal=0;
+		return 0;
+	} else
+		*signal=0xffff;
+
+	if ((i=aci_rw_cmd(0xa8, -1, -1))<0)
+		return i;
+	if (i & 0x40) {
+		*flags=0;
+	} else {
+		/* stereo */
+		*flags=VIDEO_TUNER_STEREO_ON;
+		/* I cant see stereo, when forced to mono */
+		dev->stereo=1;
+	}
+
+	if ((i=aci_rds_cmd(RDS_STATUS, &buf, 1))<0)
+		return i;
+	if (buf & 1)
+		/* RDS available */
+		*flags|=VIDEO_TUNER_RDS_ON;
+	else
 		return 0;
-	return 1;		/* signal present		*/
+
+	if ((i=aci_rds_cmd(RDS_RXVALUE, &buf, 1))<0)
+		return i;
+#if DEBUG
+	printk("rds-signal: %d\n", buf);
+#endif
+	if (buf > 15) {
+		printk("rds-miropcm20: RX strengths unexpected high...\n");
+		buf=15;
+	}
+	/* refine signal */
+	if ((*signal=SCALE(15, 0xffff, buf))==0)
+		*signal = 1;
+
+	return 0;
 }
 
 static int pcm20_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
 {
 	struct pcm20_device *pcm20=dev->priv;
+	int i;
 	
 	switch(cmd)
 	{
@@ -113,11 +155,11 @@
 				return -EFAULT;
 			if(v.tuner)	/* Only 1 tuner */ 
 				return -EINVAL;
-			v.rangelow=(int)(87.5*16);
-			v.rangehigh=(int)(108.0*16);
-			v.flags=0;
+			v.rangelow=87*16000;
+			v.rangehigh=108*16000;
+			pcm20_getflags(pcm20, &v.flags, &v.signal);
+			v.flags|=VIDEO_TUNER_LOW;
 			v.mode=VIDEO_MODE_AUTO;
-			v.signal=0xFFFF*pcm20_getsigstr(pcm20);
 			strcpy(v.name, "FM");
 			if(copy_to_user(arg,&v, sizeof(v)))
 				return -EFAULT;
@@ -134,20 +176,28 @@
 			return 0;
 		}
 		case VIDIOCGFREQ:
-			if(copy_to_user(arg, &pcm20->curfreq, sizeof(pcm20->curfreq)))
+			if(copy_to_user(arg, &pcm20->freq, sizeof(pcm20->freq)))
 				return -EFAULT;
 			return 0;
 		case VIDIOCSFREQ:
-			if(copy_from_user(&pcm20->curfreq, arg,sizeof(pcm20->curfreq)))
+			if(copy_from_user(&pcm20->freq, arg, sizeof(pcm20->freq)))
 				return -EFAULT;
-			pcm20_setfreq(pcm20, pcm20->curfreq);
-			return 0;
+			i=pcm20_setfreq(pcm20, pcm20->freq);
+#if DEBUG
+			printk("First view (setfreq): 0x%x\n", i);
+#endif
+			return i;
 		case VIDIOCGAUDIO:
 		{	
 			struct video_audio v;
 			memset(&v,0, sizeof(v));
-			v.flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
-			v.volume=pcm20->curvol * 2048;
+			v.flags=VIDEO_AUDIO_MUTABLE;
+			if (pcm20->muted)
+				v.flags|=VIDEO_AUDIO_MUTE;
+			v.mode=VIDEO_SOUND_STEREO;
+			if (pcm20->stereo)
+				v.mode|=VIDEO_SOUND_MONO;
+			/* v.step=2048; */
 			strcpy(v.name, "Radio");
 			if(copy_to_user(arg,&v, sizeof(v)))
 				return -EFAULT;
@@ -157,14 +207,15 @@
 		{
 			struct video_audio v;
 			if(copy_from_user(&v, arg, sizeof(v))) 
-				return -EFAULT;	
+				return -EFAULT;
 			if(v.audio) 
 				return -EINVAL;
 
-			if(v.flags&VIDEO_AUDIO_MUTE) 
-				pcm20_mute(pcm20);
-			else
-				pcm20_setvol(pcm20,v.volume/2048);	
+			pcm20_mute(pcm20, !!(v.flags&VIDEO_AUDIO_MUTE));
+			if(v.flags&VIDEO_SOUND_MONO)
+				pcm20_stereo(pcm20, 0);
+			if(v.flags&VIDEO_SOUND_STEREO)
+				pcm20_stereo(pcm20, 1);
 
 			return 0;
 		}
@@ -186,7 +237,12 @@
 	users--;
 }
 
-static struct pcm20_device pcm20_unit;
+static struct pcm20_device pcm20_unit=
+{
+	freq:   87*16000,
+	muted:  1,
+	stereo: 0
+};
 
 static struct video_device pcm20_radio=
 {
@@ -197,24 +253,23 @@
 	open:		pcm20_open,
 	close:		pcm20_close,
 	ioctl:		pcm20_ioctl,
+	priv:		&pcm20_unit
 };
 
 static int __init pcm20_init(void)
 {
-
-	pcm20_radio.priv=&pcm20_unit;
-	
 	if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO)==-1)
 		return -EINVAL;
 		
+	if(attach_aci_rds()<0) {
+		video_unregister_device(&pcm20_radio);
+		return -EINVAL;
+	}
+#if DEBUG
+	printk("v4l-name: %s\n", devfs_get_name(pcm20_radio.devfs_handle, 0));
+#endif
 	printk(KERN_INFO "Miro PCM20 radio card driver.\n");
 
- 	/* mute card - prevents noisy bootups */
-
-	/* this ensures that the volume is all the way down  */
-
-	pcm20_unit.curvol = 0;
-
 	return 0;
 }
 
@@ -225,9 +280,9 @@
 
 static void __exit pcm20_cleanup(void)
 {
+	unload_aci_rds();
 	video_unregister_device(&pcm20_radio);
 }
 
 module_init(pcm20_init);
 module_exit(pcm20_cleanup);
-
diff -urN linux-2.4.4-pre3/drivers/media/radio/rds-miropcm20.c linux/drivers/media/radio/rds-miropcm20.c
--- linux-2.4.4-pre3/drivers/media/radio/rds-miropcm20.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/media/radio/rds-miropcm20.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,249 @@
+/*
+ *  Many thanks to Fred Seidel <seidel@metabox.de>, the
+ *  designer of the RDS decoder hardware. With his help
+ *  I was able to code this driver.
+ *  Thanks also to Norberto Pellicci, Dominic Mounteney
+ *  <DMounteney@pinnaclesys.com> and www.teleauskunft.de
+ *  for good hints on finding Fred. It was somewhat hard
+ *  to locate him here in Germany... [:
+ *
+ * Revision history:
+ *
+ *   2000-08-09  Robert Siemer <Robert.Siemer@gmx.de>
+ *        RDS support for MiroSound PCM20 radio
+ */
+
+#define _NO_VERSION_
+
+/* #include <linux/kernel.h> */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include "../../sound/aci.h"
+
+#define WATCHMASK       0352 /* 11101010 */
+
+#define DEBUG 0
+
+static struct semaphore aci_rds_sem;
+
+
+#define RDS_BUSYMASK        0x10   /* Bit 4 */
+#define RDS_CLOCKMASK       0x08   /* Bit 3 */
+#define RDS_DATAMASK        0x04   /* Bit 2 */
+
+
+static void print_matrix(char array[], unsigned int length)
+{
+        int i, j;
+
+        for (i=0; i<length; i++) {
+                printk("aci-rds: ");
+                for (j=7; j>=0; j--) {
+                        printk("%d", (array[i] >> j) & 0x1);
+                }
+                if (i%8 == 0)
+                        printk(" byte-border\n");
+                else
+                        printk("\n");
+        }
+}
+
+static int byte2trans(unsigned char byte, unsigned char sendbuffer[], int size)
+{
+	int i;
+
+	if (size != 8)
+		return -1;
+	for (i = 7; i >= 0; i--)
+		sendbuffer[7-i] = (byte & (1 << i)) ? RDS_DATAMASK : 0;
+	sendbuffer[0] |= RDS_CLOCKMASK;
+
+	return 0;
+}
+
+static int trans2byte(unsigned char buffer[], int size)
+{
+	int i;
+	unsigned char byte=0;
+
+	if (size != 8)
+		return -1;
+	for (i = 7; i >= 0; i--)
+		byte |= ((buffer[7-i] & RDS_DATAMASK) ? 1 : 0) << i;
+
+	return byte;
+}
+
+static int trans2data(unsigned char readbuffer[], int readsize, unsigned char data[], int datasize)
+{
+	int i,j;
+
+	if (readsize != datasize*8)
+		return -1;
+	for (i = 0; i < datasize; i++)
+		if ((j=trans2byte(&readbuffer[i*8], 8)) < 0)
+			return -1;
+		else
+			data[i]=j;
+	return 0;
+}
+
+static int rds_waitread(void)
+{
+	unsigned char byte;
+	int i=2000;
+
+	do {
+		byte=inb(RDS_REGISTER);
+		if ((byte & WATCHMASK) != WATCHMASK)
+			printk("aci-rds: Hidden information discoverd!\n");
+		i--;
+	}
+	while ((byte & RDS_BUSYMASK) && i);
+
+	if (i) {
+#if DEBUG
+		printk("rds_waitread()");
+		print_matrix(&byte, 1);
+#endif
+		return (byte);
+	} else {
+		printk("aci-rds: rds_waitread() timeout...\n");
+		return -1;
+	}
+}
+
+/* dont use any ..._nowait() function if you are not sure what you do... */
+
+static inline void rds_rawwrite_nowait(unsigned char byte)
+{
+#if DEBUG
+	printk("rds_rawwrite()");
+	print_matrix(&byte, 1);
+#endif
+	outb(byte, RDS_REGISTER);
+}
+
+static int rds_rawwrite(unsigned char byte)
+{
+	if (rds_waitread() >= 0) {
+		rds_rawwrite_nowait(byte);
+		return 0;
+	} else
+		return -1;
+}
+
+static int rds_write(unsigned char cmd)
+{
+	unsigned char sendbuffer[8];
+	int i;
+	
+	if (byte2trans(cmd, sendbuffer, 8) != 0){
+		return -1;
+	} else {
+		for (i=0; i<8; i++) {
+			rds_rawwrite(sendbuffer[i]);
+		}
+	}
+	return 0;
+}
+
+static int rds_readcycle_nowait(void)
+{
+	rds_rawwrite_nowait(0);
+	return rds_waitread();
+}
+
+static int rds_readcycle(void)
+{
+	if (rds_rawwrite(0) < 0)
+		return -1;
+	return rds_waitread();
+}
+
+static int rds_read(unsigned char databuffer[], int datasize)
+{
+
+#define READSIZE (8*datasize)
+
+	int i,j;
+	unsigned char* readbuffer;
+
+	if (!datasize)  /* nothing to read */
+		return 0;
+
+	/* to be able to use rds_readcycle_nowait()
+	   I have to readwait() here */
+	if (rds_waitread() < 0)
+		return -1;
+	
+	if ((readbuffer=kmalloc(READSIZE, GFP_KERNEL)) == 0) {
+		printk("aci-rds: Out of memory...\n");
+		return -ENOMEM;
+	} else {
+		if (signal_pending(current)) {
+			kfree(readbuffer);
+			return -EINTR;
+		}
+	}
+	
+	for (i=0; i< READSIZE; i++)
+		if((j=rds_readcycle_nowait()) < 0) {
+			kfree(readbuffer);
+			return -1;
+		} else
+			readbuffer[i]=j;
+	if (trans2data(readbuffer, READSIZE, databuffer, datasize) < 0) {
+		kfree(readbuffer);
+		return -1;
+	}
+	kfree(readbuffer);
+	return 0;
+}
+
+static int rds_ack(void)
+{
+	int i=rds_readcycle();
+
+	if (i < 0)
+		return -1;
+	if (i & RDS_DATAMASK) {
+		return 0;  /* ACK  */
+	} else {
+		return 1;  /* NACK */
+	}
+}
+
+int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize)
+{
+	int ret;
+
+	if (down_interruptible(&aci_rds_sem))
+		return -EINTR;
+
+	if (rds_write(cmd))
+		ret = -2;
+
+	/* RDS_RESET doesn't need further processing */
+	if (cmd!=RDS_RESET && (rds_ack() || rds_read(databuffer, datasize)))
+		ret = -1;
+	else
+		ret = 0;
+
+	up(&aci_rds_sem);
+	
+	return ret;
+}
+
+int __init attach_aci_rds(void)
+{
+	init_MUTEX(&aci_rds_sem);
+	return 0;
+}
+
+void __exit unload_aci_rds(void)
+{
+}
diff -urN linux-2.4.4-pre3/drivers/net/acenic.c linux/drivers/net/acenic.c
--- linux-2.4.4-pre3/drivers/net/acenic.c	Mon Dec  3 22:35:12 2001
+++ linux/drivers/net/acenic.c	Mon Dec  3 22:35:22 2001
@@ -3318,6 +3318,6 @@
 
 /*
  * Local variables:
- * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h   -c -o acenic.o acenic.c"
+ * compile-command: "gcc -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h   -c -o acenic.o acenic.c"
  * End:
  */
diff -urN linux-2.4.4-pre3/drivers/net/appletalk/ipddp.c linux/drivers/net/appletalk/ipddp.c
--- linux-2.4.4-pre3/drivers/net/appletalk/ipddp.c	Sun Dec  3 17:45:22 2000
+++ linux/drivers/net/appletalk/ipddp.c	Mon Dec  3 22:35:22 2001
@@ -20,12 +20,9 @@
  *      Director, National Security Agency.
  *
  *      This software may be used and distributed according to the terms
- *      of the GNU Public License, incorporated herein by reference.
+ *      of the GNU General Public License, incorporated herein by reference.
  */
 
-static const char *version = 
-	"ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n";
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -39,7 +36,9 @@
 
 #include "ipddp.h"		/* Our stuff */
 
-static struct ipddp_route *ipddp_route_list = NULL;
+static const char version[] = KERN_INFO "ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n";
+
+static struct ipddp_route *ipddp_route_list;
 
 #ifdef CONFIG_IPDDP_ENCAP
 static int ipddp_mode = IPDDP_ENCAP;
@@ -47,12 +46,6 @@
 static int ipddp_mode = IPDDP_DECAP;
 #endif
 
-/* Use 0 for production, 1 for verification, 2 for debug, 3 for verbose debug */
-#ifndef IPDDP_DEBUG
-#define IPDDP_DEBUG 1
-#endif
-static unsigned int ipddp_debug = IPDDP_DEBUG;
-
 /* Index to functions, as function prototypes. */
 static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev);
 static struct net_device_stats *ipddp_get_stats(struct net_device *dev);
@@ -64,12 +57,12 @@
 
 static int __init ipddp_init(struct net_device *dev)
 {
-	static unsigned version_printed = 0;
+	static unsigned version_printed;
 
 	SET_MODULE_OWNER(dev);
 
-	if (ipddp_debug && version_printed++ == 0)
-                printk("%s", version);
+	if (version_printed++ == 0)
+                printk(version);
 
 	/* Let the user now what mode we are in */
 	if(ipddp_mode == IPDDP_ENCAP)
@@ -193,25 +186,23 @@
 static int ipddp_create(struct ipddp_route *new_rt)
 {
         struct ipddp_route *rt =(struct ipddp_route*) kmalloc(sizeof(*rt), GFP_KERNEL);
-	struct ipddp_route *test;
 
-        if(rt == NULL)
+        if (rt == NULL)
                 return -ENOMEM;
 
         rt->ip = new_rt->ip;
         rt->at = new_rt->at;
         rt->next = NULL;
-        rt->dev = atrtr_get_dev(&rt->at);
-        if(rt->dev == NULL)
-        {
-        	kfree(rt);
-                return (-ENETUNREACH);
+        if ((rt->dev = atrtr_get_dev(&rt->at)) == NULL) {
+		kfree(rt);
+                return -ENETUNREACH;
         }
 
-	test = ipddp_find_route(rt);
-	if(test != NULL)
-		return (-EEXIST);
-	
+	if (ipddp_find_route(rt)) {
+		kfree(rt);
+		return -EEXIST;
+	}
+
         rt->next = ipddp_route_list;
         ipddp_route_list = rt;
 
@@ -307,11 +298,16 @@
 
 static void __exit ipddp_cleanup_module(void)
 {
+        struct ipddp_route *p;
+
 	unregister_netdev(&dev_ipddp);
         kfree(dev_ipddp.priv);
 
-	memset(&dev_ipddp, 0, sizeof(dev_ipddp));
-	dev_ipddp.init = ipddp_init;
+        while (ipddp_route_list) {
+                p = ipddp_route_list->next;
+                kfree(ipddp_route_list);
+                ipddp_route_list = p;
+        }
 }
 
 module_init(ipddp_init_module);
diff -urN linux-2.4.4-pre3/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- linux-2.4.4-pre3/drivers/net/de4x5.c	Mon Dec  3 22:35:12 2001
+++ linux/drivers/net/de4x5.c	Mon Dec  3 22:35:22 2001
@@ -429,11 +429,17 @@
                            <mporter@eng.mcd.mot.com>
                           Remove double checking for DEBUG_RX in de4x5_dbg_rx()
 			   from report by <geert@linux-m68k.org>
- 
+      0.546  22-Feb-01    Fixes Alpha XP1000 oops.  The srom_search function
+                           was causing a page fault when initializing the
+                           variable 'pb', on a non de4x5 PCI device, in this
+                           case a PCI bridge (DEC chip 21152). The value of
+                           'pb' is now only initialized if a de4x5 chip is
+                           present. 
+                           <france@handhelds.org>  
     =========================================================================
 */
 
-static const char *version = "de4x5.c:V0.545 1999/11/28 davies@maniac.ultranet.com\n";
+static const char *version = "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.com\n";
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -2304,12 +2310,12 @@
 	/* Skip the pci_bus list entry */
 	if (list_entry(walk, struct pci_bus, devices) == dev->bus) continue;
 
-	pb = this_dev->bus->number;
 	vendor = this_dev->vendor;
 	device = this_dev->device << 8;
 	if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
 
 	/* Get the chip configuration revision register */
+	pb = this_dev->bus->number;
 	pcibios_read_config_dword(pb, this_dev->devfn, PCI_REVISION_ID, &cfrv);
 
 	/* Set the device number information */
diff -urN linux-2.4.4-pre3/drivers/net/de600.c linux/drivers/net/de600.c
--- linux-2.4.4-pre3/drivers/net/de600.c	Mon Dec  3 22:35:12 2001
+++ linux/drivers/net/de600.c	Mon Dec  3 22:35:22 2001
@@ -597,7 +597,6 @@
 	}
 
 	skb = dev_alloc_skb(size+2);
-	restore_flags(flags);
 	if (skb == NULL) {
 		printk("%s: Couldn't allocate a sk_buff of size %d.\n",
 			dev->name, size);
diff -urN linux-2.4.4-pre3/drivers/net/de620.c linux/drivers/net/de620.c
--- linux-2.4.4-pre3/drivers/net/de620.c	Mon Dec  3 22:35:12 2001
+++ linux/drivers/net/de620.c	Mon Dec  3 22:35:22 2001
@@ -690,7 +690,6 @@
 		else { /* Yep! Go get it! */
 			skb_reserve(skb,2);	/* Align */
 			skb->dev = dev;
-			skb->used = 0;
 			/* skb->data points to the start of sk_buff data area */
 			buffer = skb_put(skb,size);
 			/* copy the packet into the buffer */
diff -urN linux-2.4.4-pre3/drivers/net/depca.c linux/drivers/net/depca.c
--- linux-2.4.4-pre3/drivers/net/depca.c	Tue Mar  6 19:28:35 2001
+++ linux/drivers/net/depca.c	Mon Dec  3 22:35:22 2001
@@ -1818,9 +1818,7 @@
   ManCode[5]='\0';
 
   for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) {
-    const char * volatile lhs = ManCode;
-    const char * volatile rhs = signatures[i];		/* egcs-1.1.2 bug */
-    if (strstr(lhs, rhs) != NULL) {
+    if (strstr(ManCode, signatures[i]) != NULL) {
       strcpy(name,ManCode);
       status = 1;
     }
diff -urN linux-2.4.4-pre3/drivers/net/gt96100eth.c linux/drivers/net/gt96100eth.c
--- linux-2.4.4-pre3/drivers/net/gt96100eth.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/gt96100eth.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,1253 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	stevel@mvista.com or support@mvista.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Ethernet driver for the MIPS GT96100 Advanced Communication Controller.
+ * 
+ */
+
+#ifndef __mips__
+#error This driver only works with MIPS architectures!
+#endif
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#include "gt96100eth.h"
+
+#ifdef GT96100_DEBUG
+static int gt96100_debug = GT96100_DEBUG;
+#else
+static int gt96100_debug = 3;
+#endif
+
+// prototypes
+static void *dmaalloc(size_t size, dma_addr_t * dma_handle);
+static void dmafree(size_t size, void *vaddr);
+static int gt96100_add_hash_entry(struct net_device *dev,
+				  unsigned char *addr);
+static void read_mib_counters(struct gt96100_private *gp);
+static int read_MII(struct net_device *dev, u32 reg);
+static int write_MII(struct net_device *dev, u32 reg, u16 data);
+static void dump_MII(struct net_device *dev);
+static void update_stats(struct gt96100_private *gp);
+static void abort(struct net_device *dev, u32 abort_bits);
+static void hard_stop(struct net_device *dev);
+static void enable_ether_irq(struct net_device *dev);
+static void disable_ether_irq(struct net_device *dev);
+static int __init gt96100_probe1(struct net_device *dev, long ioaddr,
+				 int irq, int port_num);
+static int gt96100_init(struct net_device *dev);
+static int gt96100_open(struct net_device *dev);
+static int gt96100_close(struct net_device *dev);
+static int gt96100_tx(struct sk_buff *skb, struct net_device *dev);
+static int gt96100_rx(struct net_device *dev, u32 status);
+static void gt96100_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void gt96100_tx_timeout(struct net_device *dev);
+static void gt96100_set_rx_mode(struct net_device *dev);
+static struct net_device_stats *gt96100_get_stats(struct net_device *dev);
+
+static char version[] __devinitdata =
+    "gt96100eth.c:0.1 stevel@mvista.com\n";
+
+// FIX! Need real Ethernet addresses
+static unsigned char gt96100_station_addr[2][6] __devinitdata =
+    { {0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
+{0x01, 0x02, 0x03, 0x04, 0x05, 0x07}
+};
+
+#define nibswap(x) ((((x) >> 4) & 0x0f) | (((x) << 4) & 0xf0))
+
+#define RUN_AT(x) (jiffies + (x))
+
+// For reading/writing 32-bit words from/to DMA memory
+#define cpu_to_dma32 cpu_to_be32
+#define dma32_to_cpu be32_to_cpu
+
+/*
+ * Base address and interupt of the GT96100 ethernet controllers
+ */
+static struct {
+	unsigned int port;
+	int irq;
+} gt96100_iflist[NUM_INTERFACES] = {
+	{
+	GT96100_ETH0_BASE, GT96100_ETHER0_IRQ}, {
+	GT96100_ETH1_BASE, GT96100_ETHER1_IRQ}
+};
+
+/*
+  DMA memory allocation, derived from pci_alloc_consistent.
+*/
+static void *dmaalloc(size_t size, dma_addr_t * dma_handle)
+{
+	void *ret;
+
+	ret =
+	    (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA,
+				      get_order(size));
+
+	if (ret != NULL) {
+		dma_cache_inv((unsigned long) ret, size);
+		if (dma_handle != NULL)
+			*dma_handle = virt_to_phys(ret);
+
+		/* bump virtual address up to non-cached area */
+		ret = KSEG1ADDR(ret);
+	}
+
+	return ret;
+}
+
+static void dmafree(size_t size, void *vaddr)
+{
+	vaddr = KSEG0ADDR(vaddr);
+	free_pages((unsigned long) vaddr, get_order(size));
+}
+
+
+static int read_MII(struct net_device *dev, u32 reg)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	int timedout = 20;
+	u32 smir = smirOpCode | (gp->phy_addr << smirPhyAdBit) |
+	    (reg << smirRegAdBit);
+
+	// wait for last operation to complete
+	while (GT96100_READ(GT96100_ETH_SMI_REG) & smirBusy) {
+		// snooze for 1 msec and check again
+#if 0
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(10 * HZ / 10000);
+#else
+		mdelay(1);
+#endif
+
+		if (--timedout == 0) {
+			printk(KERN_ERR "%s: read_MII busy timeout!!\n",
+			       dev->name);
+			return -1;
+		}
+	}
+
+	GT96100_WRITE(GT96100_ETH_SMI_REG, smir);
+
+	timedout = 20;
+	// wait for read to complete
+	while (!(smir = GT96100_READ(GT96100_ETH_SMI_REG) & smirReadValid)) {
+		// snooze for 1 msec and check again
+#if 0
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(10 * HZ / 10000);
+#else
+		mdelay(1);
+#endif
+
+		if (--timedout == 0) {
+			printk(KERN_ERR "%s: read_MII timeout!!\n",
+			       dev->name);
+			return -1;
+		}
+	}
+
+	return (int) (smir & smirDataMask);
+}
+
+static int write_MII(struct net_device *dev, u32 reg, u16 data)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	int timedout = 20;
+	u32 smir =
+	    (gp->phy_addr << smirPhyAdBit) | (reg << smirRegAdBit) | data;
+
+	// wait for last operation to complete
+	while (GT96100_READ(GT96100_ETH_SMI_REG) & smirBusy) {
+		// snooze for 1 msec and check again
+#if 0
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(10 * HZ / 10000);
+#else
+		mdelay(1);
+#endif
+
+		if (--timedout == 0) {
+			printk(KERN_ERR "%s: write_MII busy timeout!!\n",
+			       dev->name);
+			return -1;
+		}
+	}
+
+	GT96100_WRITE(GT96100_ETH_SMI_REG, smir);
+	return 0;
+}
+
+
+static void dump_MII(struct net_device *dev)
+{
+	int i, val;
+
+	for (i = 0; i < 7; i++) {
+		if ((val = read_MII(dev, i)) >= 0)
+			printk("%s: MII Reg %d=%x\n", dev->name, i, val);
+	}
+	for (i = 16; i < 21; i++) {
+		if ((val = read_MII(dev, i)) >= 0)
+			printk("%s: MII Reg %d=%x\n", dev->name, i, val);
+	}
+}
+
+
+static int
+gt96100_add_hash_entry(struct net_device *dev, unsigned char *addr)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	u16 hashResult, stmp;
+	unsigned char ctmp, hash_ea[6];
+	u32 tblEntry, *tblEntryAddr;
+	int i;
+
+	for (i = 0; i < 6; i++) {
+		// nibble swap
+		ctmp = nibswap(addr[i]);
+		// invert every nibble
+		hash_ea[i] = ((ctmp & 1) << 3) | ((ctmp & 8) >> 3) |
+		    ((ctmp & 2) << 1) | ((ctmp & 4) >> 1);
+		hash_ea[i] |= ((ctmp & 0x10) << 3) | ((ctmp & 0x80) >> 3) |
+		    ((ctmp & 0x20) << 1) | ((ctmp & 0x40) >> 1);
+	}
+
+	if (gp->hash_mode == 0) {
+		hashResult = ((u16) hash_ea[0] & 0xfc) << 7;
+		stmp =
+		    ((u16) hash_ea[0] & 0x03) | (((u16) hash_ea[1] & 0x7f)
+						 << 2);
+		stmp ^=
+		    (((u16) hash_ea[1] >> 7) & 0x01) | ((u16) hash_ea[2] <<
+							1);
+		stmp ^= (u16) hash_ea[3] | (((u16) hash_ea[4] & 1) << 8);
+		hashResult |= stmp;
+	} else {
+		return -1;	// don't support hash mode 1
+	}
+
+	tblEntryAddr =
+	    (u32 *) (&gp->hash_table[((u32) hashResult & 0x7ff) << 3]);
+
+	for (i = 0; i < HASH_HOP_NUMBER; i++) {
+		if ((*tblEntryAddr & hteValid)
+		    && !(*tblEntryAddr & hteSkip)) {
+			// This entry is already occupied, go to next entry
+			tblEntryAddr += 2;
+		} else {
+			memset(tblEntryAddr, 0, 8);
+			tblEntry = hteValid | hteRD;
+			tblEntry |= (u32) addr[5] << 3;
+			tblEntry |= (u32) addr[4] << 11;
+			tblEntry |= (u32) addr[3] << 19;
+			tblEntry |= ((u32) addr[2] & 0x1f) << 27;
+			*(tblEntryAddr + 1) = cpu_to_dma32(tblEntry);
+			tblEntry = ((u32) addr[2] >> 5) & 0x07;
+			tblEntry |= (u32) addr[1] << 3;
+			tblEntry |= (u32) addr[0] << 11;
+			*tblEntryAddr = cpu_to_dma32(tblEntry);
+			break;
+		}
+	}
+
+	if (i >= HASH_HOP_NUMBER) {
+		printk(KERN_ERR "%s: gt96100_add_hash_entry expired!\n",
+		       dev->name);
+		return -1;	// Couldn't find an unused entry
+	}
+
+	return 0;
+}
+
+
+static void read_mib_counters(struct gt96100_private *gp)
+{
+	u32 *mib_regs = (u32 *) & gp->mib;
+	int i;
+
+	for (i = 0; i < sizeof(mib_counters_t) / sizeof(u32); i++)
+		mib_regs[i] =
+		    GT96100ETH_READ(gp,
+				    GT96100_ETH_MIB_COUNT_BASE +
+				    i * sizeof(u32));
+}
+
+
+static void update_stats(struct gt96100_private *gp)
+{
+	mib_counters_t *mib = &gp->mib;
+	struct net_device_stats *stats = &gp->stats;
+
+	read_mib_counters(gp);
+
+	stats->rx_packets = mib->totalFramesReceived;
+	stats->tx_packets = mib->framesSent;
+	stats->rx_bytes = mib->totalByteReceived;
+	stats->tx_bytes = mib->byteSent;
+	stats->rx_errors = mib->totalFramesReceived - mib->framesReceived;
+	//the tx error counters are incremented by the ISR
+	//rx_dropped incremented by gt96100_rx
+	//tx_dropped incremented by gt96100_tx
+	stats->multicast = mib->multicastFramesReceived;
+	// Tx collisions incremented by ISR, so add in MIB Rx collisions
+	stats->collisions += mib->collision + mib->lateCollision;
+	stats->rx_length_errors = mib->oversizeFrames + mib->fragments;
+	// The RxError condition means the Rx DMA encountered a
+	// CPU owned descriptor, which, if things are working as
+	// they should, means the Rx ring has overflowed.
+	stats->rx_over_errors = mib->macRxError;
+	stats->rx_crc_errors = mib->cRCError;
+}
+
+static void abort(struct net_device *dev, u32 abort_bits)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	int timedout = 100;	// wait up to 100 msec for hard stop to complete
+
+	if (gt96100_debug > 2)
+		printk(KERN_INFO "%s: abort\n", dev->name);
+
+	// Return if neither Rx or Tx abort bits are set
+	if (!(abort_bits & (sdcmrAR | sdcmrAT)))
+		return;
+
+	// make sure only the Rx/Tx abort bits are set
+	abort_bits &= (sdcmrAR | sdcmrAT);
+
+	spin_lock(&gp->lock);
+
+	// abort any Rx/Tx DMA immediately
+	GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM, abort_bits);
+
+	if (gt96100_debug > 2)
+		printk(KERN_INFO "%s: abort: SDMA comm = %x\n",
+		       dev->name, GT96100ETH_READ(gp,
+						  GT96100_ETH_SDMA_COMM));
+
+	// wait for abort to complete
+	while (GT96100ETH_READ(gp, GT96100_ETH_SDMA_COMM) & abort_bits) {
+		// snooze for 20 msec and check again
+#if 0
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(10 * HZ / 10000);
+#else
+		mdelay(1);
+#endif
+
+		if (--timedout == 0) {
+			printk(KERN_ERR "%s: abort timeout!!\n",
+			       dev->name);
+			break;
+		}
+	}
+
+	if (gt96100_debug > 2)
+		printk(KERN_INFO "%s: abort: timedout=%d\n", dev->name,
+		       timedout);
+
+	spin_unlock(&gp->lock);
+}
+
+
+static void hard_stop(struct net_device *dev)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+
+	if (gt96100_debug > 2)
+		printk(KERN_INFO "%s: hard stop\n", dev->name);
+
+	disable_ether_irq(dev);
+
+	abort(dev, sdcmrAR | sdcmrAT);
+
+	// disable port
+	GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG, 0);
+}
+
+
+static void enable_ether_irq(struct net_device *dev)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	u32 intMask;
+
+	// unmask interrupts
+	GT96100ETH_WRITE(gp, GT96100_ETH_INT_MASK,
+			 icrRxBuffer | icrTxBufferLow | icrTxEndLow |
+			 icrRxError | icrTxErrorLow | icrRxOVR |
+			 icrTxUdr | icrRxBufferQ0 | icrRxErrorQ0 |
+			 icrMIIPhySTC);
+
+	// now route ethernet interrupts to GT Int0 (eth0 and eth1 will be
+	// sharing it).
+	// FIX! The kernel's irq code should do this
+	intMask = GT96100_READ(GT96100_INT0_HIGH_MASK);
+	intMask |= 1 << gp->port_num;
+	GT96100_WRITE(GT96100_INT0_HIGH_MASK, intMask);
+}
+
+static void disable_ether_irq(struct net_device *dev)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	u32 intMask;
+
+	// FIX! The kernel's irq code should do this
+	intMask = GT96100_READ(GT96100_INT0_HIGH_MASK);
+	intMask &= ~(1 << gp->port_num);
+	GT96100_WRITE(GT96100_INT0_HIGH_MASK, intMask);
+
+	GT96100ETH_WRITE(gp, GT96100_ETH_INT_MASK, 0);
+}
+
+
+/*
+ * Probe for a GT96100 ethernet controller.
+ */
+int __init gt96100_probe(struct net_device *dev)
+{
+	unsigned int base_addr = dev ? dev->base_addr : 0;
+	int i;
+
+#ifndef CONFIG_MIPS_GT96100ETH
+	return -ENODEV;
+#endif
+
+	if (gt96100_debug > 2)
+		printk(KERN_INFO "%s: gt96100_probe\n", dev->name);
+
+	if (base_addr >= KSEG0)	/* Check a single specified location. */
+		return gt96100_probe1(dev, base_addr, dev->irq, 0);
+	else if (base_addr != 0)	/* Don't probe at all. */
+		return -ENXIO;
+
+//	for (i = 0; i<NUM_INTERFACES; i++) {
+	for (i = NUM_INTERFACES - 1; i >= 0; i--) {
+		int base_addr = gt96100_iflist[i].port;
+#if 0
+		if (check_region(base_addr, GT96100_ETH_IO_SIZE)) {
+			printk(KERN_ERR
+			       "%s: gt96100_probe: ioaddr 0x%lx taken?\n",
+			       dev->name, base_addr);
+			continue;
+		}
+#endif
+		if (gt96100_probe1
+		    (dev, base_addr, gt96100_iflist[i].irq, i) == 0)
+			return 0;
+	}
+	return -ENODEV;
+}
+
+
+
+static int __init
+gt96100_probe1(struct net_device *dev, long ioaddr, int irq, int port_num)
+{
+	static unsigned version_printed = 0;
+	struct gt96100_private *gp = NULL;
+	int i, retval;
+	u32 cpuConfig;
+
+	// FIX! probe for GT96100 by reading a suitable register
+
+	if (gt96100_debug > 2)
+		printk(KERN_INFO "gt96100_probe1: ioaddr 0x%lx, irq %d\n",
+		       ioaddr, irq);
+
+	request_region(ioaddr, GT96100_ETH_IO_SIZE, "GT96100ETH");
+
+	cpuConfig = GT96100_READ(GT96100_CPU_INTERF_CONFIG);
+	if (cpuConfig & (1 << 12)) {
+		printk(KERN_ERR
+		       "gt96100_probe1: must be in Big Endian mode!\n");
+		retval = -ENODEV;
+		goto free_region;
+	}
+
+	if (gt96100_debug > 2)
+		printk(KERN_INFO
+		       "gt96100_probe1: chip in Big Endian mode - cool\n");
+
+	/* Allocate a new 'dev' if needed. */
+	if (dev == NULL)
+		dev = init_etherdev(0, sizeof(struct gt96100_private));
+
+	if (gt96100_debug && version_printed++ == 0)
+		printk(version);
+
+	if (irq < 0) {
+		printk(KERN_ERR
+		       "gt96100_probe1: irq unknown - probing not supported\n");
+		retval = -ENODEV;
+		goto free_region;
+	}
+
+	printk(KERN_INFO "%s: GT-96100 ethernet found at 0x%lx, irq %d\n",
+	       dev->name, ioaddr, irq);
+
+	/* private struct aligned and zeroed by init_etherdev */
+	/* Fill in the 'dev' fields. */
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+	memcpy(dev->dev_addr, gt96100_station_addr[port_num],
+	       sizeof(dev->dev_addr));
+
+	printk(KERN_INFO "%s: HW Address ", dev->name);
+	for (i = 0; i < sizeof(dev->dev_addr); i++) {
+		printk("%2.2x", dev->dev_addr[i]);
+		printk(i < 5 ? ":" : "\n");
+	}
+
+	/* Initialize our private structure. */
+	if (dev->priv == NULL) {
+
+		gp =
+		    (struct gt96100_private *) kmalloc(sizeof(*gp),
+						       GFP_KERNEL);
+		if (gp == NULL) {
+			retval = -ENOMEM;
+			goto free_region;
+		}
+
+		dev->priv = gp;
+	}
+
+	gp = dev->priv;
+
+	memset(gp, 0, sizeof(*gp));	// clear it
+
+	gp->port_num = port_num;
+	gp->io_size = GT96100_ETH_IO_SIZE;
+	gp->port_offset = port_num * GT96100_ETH_IO_SIZE;
+	gp->phy_addr = port_num + 1;
+
+	if (gt96100_debug > 2)
+		printk(KERN_INFO "%s: gt96100_probe1, port %d\n",
+		       dev->name, gp->port_num);
+
+	// Allocate Rx and Tx descriptor rings
+	if (gp->rx_ring == NULL) {
+		// All descriptors in ring must be 16-byte aligned
+		gp->rx_ring = dmaalloc(sizeof(gt96100_rd_t) * RX_RING_SIZE
+				       +
+				       sizeof(gt96100_td_t) * TX_RING_SIZE,
+				       &gp->rx_ring_dma);
+		if (gp->rx_ring == NULL) {
+			retval = -ENOMEM;
+			goto free_region;
+		}
+
+		gp->tx_ring =
+		    (gt96100_td_t *) (gp->rx_ring + RX_RING_SIZE);
+		gp->tx_ring_dma =
+		    gp->rx_ring_dma + sizeof(gt96100_rd_t) * RX_RING_SIZE;
+	}
+
+	if (gt96100_debug > 2)
+		printk(KERN_INFO
+		       "%s: gt96100_probe1, rx_ring=%p, tx_ring=%p\n",
+		       dev->name, gp->rx_ring, gp->tx_ring);
+
+	// Allocate Rx Hash Table
+	if (gp->hash_table == NULL) {
+		gp->hash_table = (char *) dmaalloc(RX_HASH_TABLE_SIZE,
+						   &gp->hash_table_dma);
+		if (gp->hash_table == NULL) {
+			dmafree(sizeof(gt96100_rd_t) * RX_RING_SIZE
+				+ sizeof(gt96100_td_t) * TX_RING_SIZE,
+				gp->rx_ring);
+			retval = -ENOMEM;
+			goto free_region;
+		}
+	}
+
+	if (gt96100_debug > 2)
+		printk(KERN_INFO "%s: gt96100_probe1, hash=%p\n",
+		       dev->name, gp->hash_table);
+
+	spin_lock_init(&gp->lock);
+
+	dev->open = gt96100_open;
+	dev->hard_start_xmit = gt96100_tx;
+	dev->stop = gt96100_close;
+	dev->get_stats = gt96100_get_stats;
+	//dev->do_ioctl = gt96100_ioctl;
+	dev->set_multicast_list = gt96100_set_rx_mode;
+	dev->tx_timeout = gt96100_tx_timeout;
+	dev->watchdog_timeo = GT96100ETH_TX_TIMEOUT;
+
+	/* Fill in the fields of the device structure with ethernet values. */
+	ether_setup(dev);
+	return 0;
+
+      free_region:
+	release_region(ioaddr, gp->io_size);
+	unregister_netdev(dev);
+	if (dev->priv != NULL)
+		kfree(dev->priv);
+	kfree(dev);
+	printk(KERN_ERR "%s: gt96100_probe1 failed.  Returns %d\n",
+	       dev->name, retval);
+	return retval;
+}
+
+
+static int gt96100_init(struct net_device *dev)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	unsigned long flags;
+	u32 phyAD, ciu;
+	int i;
+
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_init: dev=%p\n", dev->name, dev);
+
+	// Stop and disable Port
+	hard_stop(dev);
+
+	spin_lock_irqsave(&gp->lock, flags);
+
+	// First things first, set-up hash table
+	memset(gp->hash_table, 0, RX_HASH_TABLE_SIZE);	// clear it
+	gp->hash_mode = 0;
+	// Add a single entry to hash table - our ethernet address
+	gt96100_add_hash_entry(dev, dev->dev_addr);
+	// Set-up DMA ptr to hash table
+	GT96100ETH_WRITE(gp, GT96100_ETH_HASH_TBL_PTR, gp->hash_table_dma);
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_init: Hash Tbl Ptr=%x\n", dev->name,
+		       GT96100ETH_READ(gp, GT96100_ETH_HASH_TBL_PTR));
+
+	// Setup Tx descriptor ring
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		gp->tx_ring[i].cmdstat = 0;	// CPU owns
+		gp->tx_ring[i].byte_cnt = 0;
+		gp->tx_ring[i].buff_ptr = 0;
+		gp->tx_ring[i].next =
+		    cpu_to_dma32(gp->tx_ring_dma +
+				 sizeof(gt96100_td_t) * (i + 1));
+	}
+	/* Wrap the ring. */
+	gp->tx_ring[i - 1].next = cpu_to_dma32(gp->tx_ring_dma);
+
+	// setup only the lowest priority TxCDP reg
+	GT96100ETH_WRITE(gp, GT96100_ETH_CURR_TX_DESC_PTR0,
+			 gp->tx_ring_dma);
+	GT96100ETH_WRITE(gp, GT96100_ETH_CURR_TX_DESC_PTR1, 0);
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_init: Curr Tx Desc Ptr0=%x\n",
+		       dev->name, GT96100ETH_READ(gp,
+						  GT96100_ETH_CURR_TX_DESC_PTR0));
+
+	// Setup Rx descriptor ring 
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		dma_addr_t rx_buff_dma;
+		gp->rx_ring[i].next =
+		    cpu_to_dma32(gp->rx_ring_dma +
+				 sizeof(gt96100_rd_t) * (i + 1));
+		if (gp->rx_buff[i] == NULL)
+			gp->rx_buff[i] =
+			    dmaalloc(PKT_BUF_SZ, &rx_buff_dma);
+		else
+			rx_buff_dma = virt_to_phys(gp->rx_buff[i]);
+		if (gp->rx_buff[i] == NULL)
+			break;
+		gp->rx_ring[i].buff_ptr = cpu_to_dma32(rx_buff_dma);
+		gp->rx_ring[i].buff_cnt_sz =
+		    cpu_to_dma32(PKT_BUF_SZ << rdBuffSzBit);
+		// Give ownership to device, enable interrupt
+		gp->rx_ring[i].cmdstat =
+		    cpu_to_dma32((u32) (rxOwn | rxEI));
+	}
+
+	if (i != RX_RING_SIZE) {
+		int j;
+		for (j = 0; j < RX_RING_SIZE; j++) {
+			if (gp->rx_buff[j]) {
+				dmafree(PKT_BUF_SZ, gp->rx_buff[j]);
+				gp->rx_buff[j] = NULL;
+			}
+		}
+		printk(KERN_ERR "%s: Rx ring allocation failed.\n",
+		       dev->name);
+		spin_unlock_irqrestore(&gp->lock, flags);
+		return -ENOMEM;
+	}
+
+	/* Wrap the ring. */
+	gp->rx_ring[i - 1].next = cpu_to_dma32(gp->rx_ring_dma);
+
+	// Set our MII PHY device address
+	phyAD = GT96100_READ(GT96100_ETH_PHY_ADDR_REG);
+	phyAD &= ~(0x1f << (gp->port_num * 5));
+	phyAD |= gp->phy_addr << (gp->port_num * 5);
+	GT96100_WRITE(GT96100_ETH_PHY_ADDR_REG, phyAD);
+
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_init: PhyAD=%x\n", dev->name,
+		       GT96100_READ(GT96100_ETH_PHY_ADDR_REG));
+
+	// Clear all the RxFDP and RXCDP regs...
+	for (i = 0; i < 4; i++) {
+		GT96100ETH_WRITE(gp, GT96100_ETH_1ST_RX_DESC_PTR0 + i * 4,
+				 0);
+		GT96100ETH_WRITE(gp, GT96100_ETH_CURR_RX_DESC_PTR0 + i * 4,
+				 0);
+	}
+	// and setup only the lowest priority RxFDP and RxCDP regs
+	GT96100ETH_WRITE(gp, GT96100_ETH_1ST_RX_DESC_PTR0,
+			 gp->rx_ring_dma);
+	GT96100ETH_WRITE(gp, GT96100_ETH_CURR_RX_DESC_PTR0,
+			 gp->rx_ring_dma);
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_init: 1st/Curr Rx Desc Ptr0=%x/%x\n",
+		       dev->name, GT96100ETH_READ(gp,
+						  GT96100_ETH_1ST_RX_DESC_PTR0),
+		       GT96100ETH_READ(gp, GT96100_ETH_CURR_RX_DESC_PTR0));
+
+	// init Rx/Tx indeces and pkt counters
+	gp->rx_next_out = gp->tx_next_in = gp->tx_next_out = 0;
+	gp->tx_count = 0;
+
+	// setup DMA
+
+	// FIX! this should be done by Kernel setup code
+	ciu = GT96100_READ(GT96100_CIU_ARBITER_CONFIG);
+	ciu |= (0x0c << (gp->port_num * 2));	// set Ether DMA req priority to high
+	// FIX! setting the following bit causes the EV96100 board to hang!!!
+	//ciu |= (1 << (24+gp->port_num));   // pull Ethernet port out of Reset???
+	// FIX! endian mode???
+	ciu &= ~(1 << 31);	// set desc endianess to Big
+	GT96100_WRITE(GT96100_CIU_ARBITER_CONFIG, ciu);
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_init: CIU Config=%x/%x\n", dev->name,
+		       ciu, GT96100_READ(GT96100_CIU_ARBITER_CONFIG));
+
+	// We want the Rx/Tx DMA to write/read data to/from memory in
+	// Big Endian mode. Also set DMA Burst Size to 8 64Bit words.
+	// FIX! endian mode???
+	GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_CONFIG,
+			 //sdcrBLMR | sdcrBLMT |
+			 (0xf << sdcrRCBit) | sdcrRIFB | (3 << sdcrBSZBit));
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_init: SDMA Config=%x\n", dev->name,
+		       GT96100ETH_READ(gp, GT96100_ETH_SDMA_CONFIG));
+
+	// start Rx DMA
+	GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM, sdcmrERD);
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_init: SDMA Comm=%x\n", dev->name,
+		       GT96100ETH_READ(gp, GT96100_ETH_SDMA_COMM));
+
+	// enable interrupts
+	enable_ether_irq(dev);
+
+	/*
+	 * Disable all Type-of-Service queueing. All Rx packets will be
+	 * treated normally and will be sent to the lowest priority
+	 * queue.
+	 *
+	 * Disable flow-control for now. FIX! support flow control?
+	 */
+	// clear all the MIB ctr regs
+	// Enable reg clear on read. FIX! desc of this bit is inconsistent
+	// in the GT-96100A datasheet.
+	GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG_EXT,
+			 pcxrFCTL | pcxrFCTLen | pcxrFLP);
+	read_mib_counters(gp);
+	GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG_EXT,
+			 pcxrFCTL | pcxrFCTLen | pcxrFLP | pcxrMIBclrMode);
+
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_init: Port Config Ext=%x\n", dev->name,
+		       GT96100ETH_READ(gp, GT96100_ETH_PORT_CONFIG_EXT));
+
+	// enable this port (set hash size to 1/2K)
+	GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG, pcrEN | pcrHS);
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_init: Port Config=%x\n", dev->name,
+		       GT96100ETH_READ(gp, GT96100_ETH_PORT_CONFIG));
+
+	// we should now be receiving frames
+	if (gt96100_debug > 2)
+		dump_MII(dev);
+
+	spin_unlock_irqrestore(&gp->lock, flags);
+	return 0;
+}
+
+
+static int gt96100_open(struct net_device *dev)
+{
+	int retval;
+
+	MOD_INC_USE_COUNT;
+
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_open: dev=%p\n", dev->name, dev);
+
+	if ((retval = request_irq(dev->irq, &gt96100_interrupt,
+				  SA_SHIRQ, dev->name, dev))) {
+		printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name,
+		       dev->irq);
+		MOD_DEC_USE_COUNT;
+		return retval;
+	}
+	// Initialize and startup the GT-96100 ethernet port
+	if ((retval = gt96100_init(dev))) {
+		printk(KERN_ERR "%s: error in gt96100_init\n", dev->name);
+		free_irq(dev->irq, dev);
+		MOD_DEC_USE_COUNT;
+		return retval;
+	}
+
+	netif_start_queue(dev);
+
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_open: Initialization done.\n",
+		       dev->name);
+
+	return 0;
+}
+
+static int gt96100_close(struct net_device *dev)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	int i;
+
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_close: dev=%p\n", dev->name, dev);
+
+	// stop the device
+	if (netif_device_present(dev)) {
+		netif_stop_queue(dev);
+		hard_stop(dev);
+	}
+	// free the Rx DMA buffers
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		if (gp->rx_buff[i]) {
+			dmafree(PKT_BUF_SZ, gp->rx_buff[i]);
+			gp->rx_buff[i] = NULL;
+		}
+	}
+
+	free_irq(dev->irq, dev);
+
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+
+static int gt96100_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	unsigned long flags;
+	int nextIn;
+
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_tx: skb->len=%d, skb->data=%p\n",
+		       dev->name, skb->len, skb->data);
+
+	spin_lock_irqsave(&gp->lock, flags);
+
+	if (gp->tx_count >= TX_RING_SIZE) {
+		printk(KERN_WARNING
+		       "%s: Tx Ring full, refusing to send buffer.\n",
+		       dev->name);
+		gp->stats.tx_dropped++;
+		spin_unlock_irqrestore(&gp->lock, flags);
+		return 1;
+	}
+	// Prepare the Descriptor at tx_next_in
+	nextIn = gp->tx_next_in;
+
+	if (dma32_to_cpu(gp->tx_ring[nextIn].cmdstat) & txOwn) {
+		printk(KERN_ERR "%s: gt96100_tx: TxOwn bit wrong!!\n",
+		       dev->name);
+	}
+
+	gp->tx_skbuff[nextIn] = skb;
+	gp->tx_ring[nextIn].byte_cnt =
+	    cpu_to_dma32(skb->len << tdByteCntBit);
+	gp->tx_ring[nextIn].buff_ptr =
+	    cpu_to_dma32(virt_to_phys(skb->data));
+	// Give ownership to device, set first and last desc, enable interrupt
+	// Setting of ownership bit must be *last*!
+	gp->tx_ring[nextIn].cmdstat =
+	    cpu_to_dma32((u32) (txOwn | txEI | txFirst | txLast));
+
+	// increment tx_next_in with wrap
+	gp->tx_next_in = (nextIn + 1) % TX_RING_SIZE;
+	// If count is zero, DMA should be stopped, so restart
+	if (gp->tx_count == 0) {
+		if (GT96100ETH_READ(gp, GT96100_ETH_PORT_STATUS) &
+		    psrTxLow) printk(KERN_WARNING
+				     "%s: Tx count zero but Tx queue running!\n",
+				     dev->name);
+		GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM,
+				 sdcmrERD | sdcmrTXDL);
+	}
+	// increment count and stop queue if full
+	if (++gp->tx_count == TX_RING_SIZE)
+		netif_stop_queue(dev);
+
+	dev->trans_start = jiffies;
+	spin_unlock_irqrestore(&gp->lock, flags);
+
+	return 0;
+}
+
+
+static int gt96100_rx(struct net_device *dev, u32 status)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	struct sk_buff *skb;
+	int pkt_len, nextOut;
+	gt96100_rd_t *rd;
+	u32 cmdstat;
+
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_rx: dev=%p, status = %x\n",
+		       dev->name, dev, status);
+
+	// Continue until we reach the current descriptor pointer
+	for (nextOut = gp->rx_next_out;
+	     nextOut !=
+	     (GT96100ETH_READ(gp, GT96100_ETH_CURR_RX_DESC_PTR0) -
+	      gp->rx_ring_dma) / sizeof(gt96100_rd_t);
+	     nextOut = (nextOut + 1) % RX_RING_SIZE) {
+
+		rd = &gp->rx_ring[nextOut];
+		cmdstat = dma32_to_cpu(rd->cmdstat);
+
+		if (cmdstat & (u32) rxOwn) {
+			cmdstat &= ~((u32) rxOwn);
+			rd->cmdstat = cpu_to_dma32(cmdstat);
+			printk(KERN_ERR
+			       "%s: gt96100_rx: ownership bit wrong!\n",
+			       dev->name);
+		}
+		// must be first and last (ie only) buffer of packet
+		if (!(cmdstat & (u32) rxFirst)
+		    || !(cmdstat & (u32) rxLast)) {
+			printk(KERN_ERR
+			       "%s: gt96100_rx: desc not first and last!\n",
+			       dev->name);
+			continue;
+		}
+		// drop this received pkt if there were any errors
+		if ((cmdstat & (u32) rxErrorSummary)
+		    || (status & icrRxErrorQ0)) {
+			// update the detailed rx error counters that are not covered
+			// by the MIB counters.
+			if (cmdstat & (u32) rxOverrun)
+				gp->stats.rx_fifo_errors++;
+			continue;
+		}
+
+		pkt_len = dma32_to_cpu(rd->buff_cnt_sz) & rdByteCntMask;
+
+		/* Create new skb. */
+		skb = dev_alloc_skb(pkt_len + 2);
+		if (skb == NULL) {
+			printk(KERN_ERR
+			       "%s: Memory squeeze, dropping packet.\n",
+			       dev->name);
+			gp->stats.rx_dropped++;
+			continue;
+		}
+		skb->dev = dev;
+		skb_reserve(skb, 2);	/* 16 byte IP header align */
+		skb_put(skb, pkt_len);	/* Make room */
+		eth_copy_and_sum(skb, gp->rx_buff[nextOut], pkt_len, 0);
+		skb->protocol = eth_type_trans(skb, dev);
+		netif_rx(skb);	/* pass the packet to upper layers */
+
+		// now we can release ownership of this desc back to device
+		cmdstat |= (u32) rxOwn;
+		rd->cmdstat = cpu_to_dma32(cmdstat);
+
+		dev->last_rx = jiffies;
+	}
+
+	gp->rx_next_out = nextOut;
+	return 0;
+}
+
+
+static void gt96100_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	u32 status;
+
+	if (dev == NULL) {
+		printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
+		return;
+	}
+
+	status = GT96100ETH_READ(gp, GT96100_ETH_INT_CAUSE);
+	// ACK interrupts
+#if 0
+	GT96100ETH_CLRBIT(gp, GT96100_ETH_INT_CAUSE,
+			  icrEtherIntSum | icrRxBufferQ1 | icrRxBufferQ2 |
+			  icrRxBufferQ3 | icrRxBufferQ0 | icrTxBufferHigh |
+			  icrTxEndHigh | icrTxBufferLow | icrTxEndLow |
+			  icrTxErrorHigh | icrTxErrorLow | icrTxUdr);
+#else
+	GT96100ETH_WRITE(gp, GT96100_ETH_INT_CAUSE, 0);
+#endif
+
+	if ((status & icrEtherIntSum) == 0) {
+		// not our interrupt
+		//printk("%s: isr: no ints? icr=%x,cp0_cause=%x\n",
+		//       dev->name, status, read_32bit_cp0_register(CP0_CAUSE));
+		return;
+	}
+
+	if (gt96100_debug > 3)
+		printk("%s: isr: entry, icr=%x\n", dev->name, status);
+
+	if (status & (icrRxBufferQ1 | icrRxBufferQ2 | icrRxBufferQ3)) {
+		printk(KERN_ERR "%s: isr: Rx intr in unused queues!?\n",
+		       dev->name);
+	}
+
+	if (status & icrRxBufferQ0) {
+		gt96100_rx(dev, status);
+	}
+
+	if (status & (icrTxBufferHigh | icrTxEndHigh)) {
+		printk(KERN_ERR "%s: isr: Tx intr in unused queue!?\n",
+		       dev->name);
+	}
+
+	if (status & icrMIIPhySTC) {
+		u32 psr = GT96100ETH_READ(gp, GT96100_ETH_PORT_STATUS);
+		printk("%s: port status:\n", dev->name);
+		printk
+		    ("%s:     %s MBit/s, %s-duplex, flow-control %s, link is %s,\n",
+		     dev->name, psr & psrSpeed ? "100" : "10",
+		     psr & psrDuplex ? "full" : "half",
+		     psr & psrFctl ? "disabled" : "enabled",
+		     psr & psrLink ? "up" : "down");
+		printk
+		    ("%s:     TxLowQ is %s, TxHighQ is %s, Transmitter is %s\n",
+		     dev->name, psr & psrTxLow ? "running" : "stopped",
+		     psr & psrTxHigh ? "running" : "stopped",
+		     psr & psrTxInProg ? "on" : "off");
+		gp->last_psr = psr;
+	}
+
+	if (status & (icrTxBufferLow | icrTxEndLow)) {
+		int nextOut;
+		gt96100_td_t *td;
+		u32 cmdstat;
+
+		// Continue until we reach the current descriptor pointer
+		for (nextOut = gp->tx_next_out;
+		     nextOut !=
+		     (GT96100ETH_READ(gp, GT96100_ETH_CURR_TX_DESC_PTR0) -
+		      gp->tx_ring_dma) / sizeof(gt96100_td_t);
+		     nextOut = (nextOut + 1) % TX_RING_SIZE) {
+
+			td = &gp->tx_ring[nextOut];
+			cmdstat = dma32_to_cpu(td->cmdstat);
+
+			if (gt96100_debug > 2)
+				printk("%s: isr: Tx desc cmdstat=%x\n",
+				       dev->name, cmdstat);
+
+			if (cmdstat & (u32) txOwn) {
+				cmdstat &= ~((u32) txOwn);
+				td->cmdstat = cpu_to_dma32(cmdstat);
+				printk(KERN_ERR
+				       "%s: isr: Tx ownership bit wrong!\n",
+				       dev->name);
+			}
+			// increment Tx error stats
+			if (cmdstat & (u32) txErrorSummary) {
+				if (gt96100_debug > 2)
+					printk
+					    ("%s: gt96100_interrupt: Tx error, cmdstat = %x\n",
+					     dev->name, cmdstat);
+				gp->stats.tx_errors++;
+				if (cmdstat & (u32) txReTxLimit)
+					gp->stats.collisions++;
+				if (cmdstat & (u32) txUnderrun)
+					gp->stats.tx_fifo_errors++;
+				if (cmdstat & (u32) txLateCollision)
+					gp->stats.tx_window_errors++;
+			}
+			// Wake the queue if the ring was full
+			if (gp->tx_count == TX_RING_SIZE)
+				netif_wake_queue(dev);
+
+			// decrement tx ring buffer count
+			if (gp->tx_count)
+				gp->tx_count--;
+
+			// free the skb
+			if (gp->tx_skbuff[nextOut]) {
+				if (gt96100_debug > 2)
+					printk
+					    ("%s: isr: good Tx, skb=%p\n",
+					     dev->name,
+					     gp->tx_skbuff[nextOut]);
+				dev_kfree_skb_irq(gp->tx_skbuff[nextOut]);
+				gp->tx_skbuff[nextOut] = NULL;
+			} else {
+				printk(KERN_ERR "%s: isr: no skb!\n",
+				       dev->name);
+			}
+		}
+
+		if (gp->tx_count == 0 && nextOut != gp->tx_next_in) {
+			// FIX! this should probably be a panic
+			printk(KERN_ERR
+			       "%s: isr: warning! Tx queue inconsistent\n",
+			       dev->name);
+		}
+
+		gp->tx_next_out = nextOut;
+
+		if ((status & icrTxEndLow) && gp->tx_count != 0) {
+			// we must restart the DMA
+			if (gt96100_debug > 2)
+				printk("%s: isr: Restarting Tx DMA\n",
+				       dev->name);
+			GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM,
+					 sdcmrERD | sdcmrTXDL);
+		}
+	}
+	// Now check TX errors (RX errors were handled in gt96100_rx)
+
+	if (status & icrTxErrorHigh) {
+		printk(KERN_ERR
+		       "%s: isr: Tx resource error in unused queue!?\n",
+		       dev->name);
+	}
+
+	if (status & icrTxErrorLow) {
+		printk(KERN_ERR "%s: isr: Tx resource error\n", dev->name);
+	}
+
+	if (status & icrTxUdr) {
+		printk(KERN_ERR "%s: isr: Tx underrun error\n", dev->name);
+	}
+
+	if (gt96100_debug > 3)
+		printk("%s: isr: exit, icr=%x\n",
+		       dev->name, GT96100ETH_READ(gp,
+						  GT96100_ETH_INT_CAUSE));
+}
+
+
+/*
+ * The Tx ring has been full longer than the watchdog timeout
+ * value, meaning that the interrupt routine has not been freeing
+ * up space in the Tx ring buffer.
+ */
+static void gt96100_tx_timeout(struct net_device *dev)
+{
+//    struct gt96100_private *gp = (struct gt96100_private *)dev->priv;
+
+	printk(KERN_ERR "%s: gt96100_tx_timeout: dev=%p\n", dev->name,
+	       dev);
+
+	// FIX! do something, like reset the device
+}
+
+
+static void gt96100_set_rx_mode(struct net_device *dev)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	unsigned long flags;
+	struct dev_mc_list *mcptr;
+
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_set_rx_mode: dev=%p, flags=%x\n",
+		       dev->name, dev, dev->flags);
+
+	// stop the Receiver DMA
+	abort(dev, sdcmrAR);
+
+	spin_lock_irqsave(&gp->lock, flags);
+
+	if (dev->flags & IFF_PROMISC)
+		GT96100ETH_WRITE(gp, GT96100_ETH_PORT_CONFIG,
+				 pcrEN | pcrHS | pcrPM);
+
+	memset(gp->hash_table, 0, RX_HASH_TABLE_SIZE);	// clear hash table
+	// Add our ethernet address
+	gt96100_add_hash_entry(dev, dev->dev_addr);
+
+	if (dev->mc_count) {
+		for (mcptr = dev->mc_list; mcptr; mcptr = mcptr->next) {
+			gt96100_add_hash_entry(dev, mcptr->dmi_addr);
+		}
+	}
+	// restart Rx DMA
+	GT96100ETH_WRITE(gp, GT96100_ETH_SDMA_COMM, sdcmrERD);
+
+	spin_unlock_irqrestore(&gp->lock, flags);
+}
+
+static struct net_device_stats *gt96100_get_stats(struct net_device *dev)
+{
+	struct gt96100_private *gp = (struct gt96100_private *) dev->priv;
+	unsigned long flags;
+
+	if (gt96100_debug > 2)
+		printk("%s: gt96100_get_stats: dev=%p\n", dev->name, dev);
+
+	if (netif_device_present(dev)) {
+		spin_lock_irqsave(&gp->lock, flags);
+		update_stats(gp);
+		spin_unlock_irqrestore(&gp->lock, flags);
+	}
+
+	return &gp->stats;
+}
+
+module_init(gt96100_probe);
diff -urN linux-2.4.4-pre3/drivers/net/gt96100eth.h linux/drivers/net/gt96100eth.h
--- linux-2.4.4-pre3/drivers/net/gt96100eth.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/gt96100eth.h	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	stevel@mvista.com or support@mvista.com
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Ethernet driver definitions for the MIPS GT96100 Advanced
+ * Communication Controller.
+ * 
+ */
+#ifndef _GT96100ETH_H
+#define _GT96100ETH_H
+
+#include <linux/config.h>
+#include <asm/galileo-boards/gt96100.h>
+
+/* Keep the ring sizes a power of two for efficiency. */
+#define TX_RING_SIZE	16
+#define RX_RING_SIZE	32
+#define PKT_BUF_SZ	1536	/* Size of each temporary Rx buffer. */
+
+#define RX_HASH_TABLE_SIZE 16384
+#define HASH_HOP_NUMBER 12
+
+#define NUM_INTERFACES 2
+
+#define GT96100ETH_TX_TIMEOUT HZ
+
+#define GT96100_ETH0_BASE (MIPS_GT96100_BASE + GT96100_ETH_PORT_CONFIG)
+#define GT96100_ETH1_BASE (GT96100_ETH0_BASE + GT96100_ETH_IO_SIZE)
+
+#ifdef CONFIG_MIPS_EV96100
+#define GT96100_ETHER0_IRQ 4
+#define GT96100_ETHER1_IRQ 4
+#else
+#define GT96100_ETHER0_IRQ -1
+#define GT96100_ETHER1_IRQ -1
+#endif
+
+#define GT96100ETH_READ(gp, offset) \
+    GT96100_READ((gp->port_offset + offset))
+
+#define GT96100ETH_WRITE(gp, offset, data) \
+    GT96100_WRITE((gp->port_offset + offset), data)
+
+#define GT96100ETH_SETBIT(gp, offset, bits) {\
+    u32 val = GT96100ETH_READ(gp, offset); val |= (u32)(bits); \
+    GT96100ETH_WRITE(gp, offset, val); }
+
+#define GT96100ETH_CLRBIT(gp, offset, bits) {\
+    u32 val = GT96100ETH_READ(gp, offset); val &= (u32)(~(bits)); \
+    GT96100ETH_WRITE(gp, offset, val); }
+
+
+/* Bit definitions of the SMI Reg */
+enum {
+	smirDataMask = 0xffff,
+	smirPhyAdMask = 0x1f << 16,
+	smirPhyAdBit = 16,
+	smirRegAdMask = 0x1f << 21,
+	smirRegAdBit = 21,
+	smirOpCode = 1 << 26,
+	smirReadValid = 1 << 27,
+	smirBusy = 1 << 28
+};
+
+/* Bit definitions of the Port Config Reg */
+enum pcr_bits {
+	pcrPM = 1,
+	pcrRBM = 2,
+	pcrPBF = 4,
+	pcrEN = 1 << 7,
+	pcrLPBKMask = 0x3 << 8,
+	pcrLPBKBit = 8,
+	pcrFC = 1 << 10,
+	pcrHS = 1 << 12,
+	pcrHM = 1 << 13,
+	pcrHDM = 1 << 14,
+	pcrHD = 1 << 15,
+	pcrISLMask = 0x7 << 28,
+	pcrISLBit = 28,
+	pcrACCS = 1 << 31
+};
+
+/* Bit definitions of the Port Config Extend Reg */
+enum pcxr_bits {
+	pcxrIGMP = 1,
+	pcxrSPAN = 2,
+	pcxrPAR = 4,
+	pcxrPRIOtxMask = 0x7 << 3,
+	pcxrPRIOtxBit = 3,
+	pcxrPRIOrxMask = 0x3 << 6,
+	pcxrPRIOrxBit = 6,
+	pcxrPRIOrxOverride = 1 << 8,
+	pcxrDPLXen = 1 << 9,
+	pcxrFCTLen = 1 << 10,
+	pcxrFLP = 1 << 11,
+	pcxrFCTL = 1 << 12,
+	pcxrMFLMask = 0x3 << 14,
+	pcxrMFLBit = 14,
+	pcxrMIBclrMode = 1 << 16,
+	pcxrSpeed = 1 << 18,
+	pcxrSpeeden = 1 << 19,
+	pcxrRMIIen = 1 << 20,
+	pcxrDSCPen = 1 << 21
+};
+
+/* Bit definitions of the Port Command Reg */
+enum pcmr_bits {
+	pcmrFJ = 1 << 15
+};
+
+
+/* Bit definitions of the Port Status Reg */
+enum psr_bits {
+	psrSpeed = 1,
+	psrDuplex = 2,
+	psrFctl = 4,
+	psrLink = 8,
+	psrPause = 1 << 4,
+	psrTxLow = 1 << 5,
+	psrTxHigh = 1 << 6,
+	psrTxInProg = 1 << 7
+};
+
+/* Bit definitions of the SDMA Config Reg */
+enum sdcr_bits {
+	sdcrRCMask = 0xf << 2,
+	sdcrRCBit = 2,
+	sdcrBLMR = 1 << 6,
+	sdcrBLMT = 1 << 7,
+	sdcrPOVR = 1 << 8,
+	sdcrRIFB = 1 << 9,
+	sdcrBSZMask = 0x3 << 12,
+	sdcrBSZBit = 12
+};
+
+/* Bit definitions of the SDMA Command Reg */
+enum sdcmr_bits {
+	sdcmrERD = 1 << 7,
+	sdcmrAR = 1 << 15,
+	sdcmrSTDH = 1 << 16,
+	sdcmrSTDL = 1 << 17,
+	sdcmrTXDH = 1 << 23,
+	sdcmrTXDL = 1 << 24,
+	sdcmrAT = 1 << 31
+};
+
+/* Bit definitions of the Interrupt Cause Reg */
+enum icr_bits {
+	icrRxBuffer = 1,
+	icrTxBufferHigh = 1 << 2,
+	icrTxBufferLow = 1 << 3,
+	icrTxEndHigh = 1 << 6,
+	icrTxEndLow = 1 << 7,
+	icrRxError = 1 << 8,
+	icrTxErrorHigh = 1 << 10,
+	icrTxErrorLow = 1 << 11,
+	icrRxOVR = 1 << 12,
+	icrTxUdr = 1 << 13,
+	icrRxBufferQ0 = 1 << 16,
+	icrRxBufferQ1 = 1 << 17,
+	icrRxBufferQ2 = 1 << 18,
+	icrRxBufferQ3 = 1 << 19,
+	icrRxErrorQ0 = 1 << 20,
+	icrRxErrorQ1 = 1 << 21,
+	icrRxErrorQ2 = 1 << 22,
+	icrRxErrorQ3 = 1 << 23,
+	icrMIIPhySTC = 1 << 28,
+	icrSMIdone = 1 << 29,
+	icrEtherIntSum = 1 << 31
+};
+
+
+/* The Rx and Tx descriptor lists. */
+
+typedef struct {
+	u32 cmdstat;
+	u32 byte_cnt;
+	u32 buff_ptr;
+	u32 next;
+} gt96100_td_t;
+
+#define tdByteCntBit 16
+
+typedef struct {
+	u32 cmdstat;
+	u32 buff_cnt_sz;
+	u32 buff_ptr;
+	u32 next;
+} gt96100_rd_t;
+
+#define rdBuffSzBit 16
+#define rdByteCntMask 0xffff
+
+
+/* Values for the Tx command-status descriptor entry. */
+enum td_cmdstat {
+	txOwn = 1 << 31,
+	txAutoMode = 1 << 30,
+	txEI = 1 << 23,
+	txGenCRC = 1 << 22,
+	txPad = 1 << 18,
+	txFirst = 1 << 17,
+	txLast = 1 << 16,
+	txErrorSummary = 1 << 15,
+	txReTxCntMask = 0x0f << 10,
+	txReTxCntBit = 10,
+	txCollision = 1 << 9,
+	txReTxLimit = 1 << 8,
+	txUnderrun = 1 << 6,
+	txLateCollision = 1 << 5
+};
+
+#define TxReTxCntBit 10
+
+/* Values for the Rx command-status descriptor entry. */
+enum rd_cmdstat {
+	rxOwn = 1 << 31,
+	rxAutoMode = 1 << 30,
+	rxEI = 1 << 23,
+	rxFirst = 1 << 17,
+	rxLast = 1 << 16,
+	rxErrorSummary = 1 << 15,
+	rxIGMP = 1 << 14,
+	rxHashExpired = 1 << 13,
+	rxMissedFrame = 1 << 12,
+	rxFrameType = 1 << 11,
+	rxShortFrame = 1 << 8,
+	rxMaxFrameLen = 1 << 7,
+	rxOverrun = 1 << 6,
+	rxCollision = 1 << 4,
+	rxCRCError = 1
+};
+
+/* Bit fields of a Hash Table Entry */
+enum hash_table_entry {
+	hteValid = 1,
+	hteSkip = 2,
+	hteRD = 4
+};
+
+// The MIB counters
+typedef struct {
+	u32 byteReceived;
+	u32 byteSent;
+	u32 framesReceived;
+	u32 framesSent;
+	u32 totalByteReceived;
+	u32 totalFramesReceived;
+	u32 broadcastFramesReceived;
+	u32 multicastFramesReceived;
+	u32 cRCError;
+	u32 oversizeFrames;
+	u32 fragments;
+	u32 jabber;
+	u32 collision;
+	u32 lateCollision;
+	u32 frames64;
+	u32 frames65_127;
+	u32 frames128_255;
+	u32 frames256_511;
+	u32 frames512_1023;
+	u32 frames1024_MaxSize;
+	u32 macRxError;
+	u32 droppedFrames;
+	u32 outMulticastFrames;
+	u32 outBroadcastFrames;
+	u32 undersizeFrames;
+} mib_counters_t;
+
+
+struct gt96100_private {
+	gt96100_rd_t *rx_ring;
+	gt96100_td_t *tx_ring;
+	// The Rx and Tx rings must be 16-byte aligned
+	dma_addr_t rx_ring_dma;
+	dma_addr_t tx_ring_dma;
+	char *hash_table;
+	// The Hash Table must be 8-byte aligned
+	dma_addr_t hash_table_dma;
+	int hash_mode;
+
+	// The Rx buffers must be 8-byte aligned
+	char *rx_buff[RX_RING_SIZE];
+	// Tx buffers (tx_skbuff[i]->data) with less than 8 bytes
+	// of payload must be 8-byte aligned
+	struct sk_buff *tx_skbuff[TX_RING_SIZE];
+	int rx_next_out;	/* The next free ring entry to receive */
+	int tx_next_in;		/* The next free ring entry to send */
+	int tx_next_out;	/* The last ring entry the ISR processed */
+	int tx_count;		/* current # of pkts waiting to be sent in Tx ring */
+
+	mib_counters_t mib;
+	struct net_device_stats stats;
+
+	int io_size;
+	int port_num;		// 0 or 1
+	u32 port_offset;
+
+	int phy_addr;		// PHY address
+	u32 last_psr;		// last value of the port status register
+
+	int options;		/* User-settable misc. driver options. */
+	int drv_flags;
+	unsigned char phys[2];	/* MII device addresses. */
+	spinlock_t lock;	/* Serialise access to device */
+};
+
+#endif
diff -urN linux-2.4.4-pre3/drivers/net/hamradio/6pack.c linux/drivers/net/hamradio/6pack.c
--- linux-2.4.4-pre3/drivers/net/hamradio/6pack.c	Thu Feb  8 16:32:44 2001
+++ linux/drivers/net/hamradio/6pack.c	Mon Dec  3 22:35:22 2001
@@ -711,10 +711,6 @@
 	/* Do sanity checks on maximum device parameter. */
 	if (sixpack_maxdev < 4)
 		sixpack_maxdev = 4;
-	if (sixpack_maxdev * sizeof(void*) >= KMALLOC_MAXSIZE) {
-	        printk(msg_invparm);
-		return -ENFILE;
-	}
 
 	printk(msg_banner, sixpack_maxdev);
 
diff -urN linux-2.4.4-pre3/drivers/net/pcmcia/aironet4500_cs.c linux/drivers/net/pcmcia/aironet4500_cs.c
--- linux-2.4.4-pre3/drivers/net/pcmcia/aironet4500_cs.c	Tue Mar 20 12:05:00 2001
+++ linux/drivers/net/pcmcia/aironet4500_cs.c	Mon Dec  3 22:35:22 2001
@@ -179,12 +179,14 @@
 	link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
 	if (!link)
 		return NULL;
+	memset(link, 0, sizeof(struct dev_link_t));
+
 	link->dev = kmalloc(sizeof(struct dev_node_t), GFP_KERNEL);
 	if (!link->dev) {
 		kfree(link);
 		return NULL;
 	}
-	memset(link, 0, sizeof(struct dev_link_t));
+
 	memset(link->dev, 0, sizeof(struct dev_node_t));
 
 	link->release.function = &awc_release;
diff -urN linux-2.4.4-pre3/drivers/net/saa9730.c linux/drivers/net/saa9730.c
--- linux-2.4.4-pre3/drivers/net/saa9730.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/saa9730.c	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,1082 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * SAA9730 ethernet driver.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/pci.h>
+
+#include <asm/addrspace.h>
+#include <asm/mips-boards/prom.h>
+
+#include "saa9730.h"
+
+#ifdef LAN_SAA9730_DEBUG
+int lan_saa9730_debug = LAN_SAA9730_DEBUG;
+#else
+int lan_saa9730_debug;
+#endif
+
+
+/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */
+static unsigned int pci_irq_line = 0;
+
+#define INL(a)     inl((unsigned long)a)
+#define OUTL(x,a)  outl(x,(unsigned long)a)
+
+static void evm_saa9730_enable_lan_int(struct lan_saa9730_private *lp)
+{
+	OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
+	     &lp->evm_saa9730_regs->InterruptBlock1);
+	OUTL(INL(&lp->evm_saa9730_regs->InterruptStatus1) | EVM_LAN_INT,
+	     &lp->evm_saa9730_regs->InterruptStatus1);
+	OUTL(INL(&lp->evm_saa9730_regs->InterruptEnable1) | EVM_LAN_INT |
+	     EVM_MASTER_EN, &lp->evm_saa9730_regs->InterruptEnable1);
+}
+static void evm_saa9730_disable_lan_int(struct lan_saa9730_private *lp)
+{
+	OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
+	     &lp->evm_saa9730_regs->InterruptBlock1);
+	OUTL(INL(&lp->evm_saa9730_regs->InterruptEnable1) & ~EVM_LAN_INT,
+	     &lp->evm_saa9730_regs->InterruptEnable1);
+}
+
+static void evm_saa9730_clear_lan_int(struct lan_saa9730_private *lp)
+{
+	OUTL(EVM_LAN_INT, &lp->evm_saa9730_regs->InterruptStatus1);
+}
+
+static void evm_saa9730_block_lan_int(struct lan_saa9730_private *lp)
+{
+	OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) & ~EVM_LAN_INT,
+	     &lp->evm_saa9730_regs->InterruptBlock1);
+}
+
+static void evm_saa9730_unblock_lan_int(struct lan_saa9730_private *lp)
+{
+	OUTL(INL(&lp->evm_saa9730_regs->InterruptBlock1) | EVM_LAN_INT,
+	     &lp->evm_saa9730_regs->InterruptBlock1);
+}
+
+static void show_saa9730_regs(struct lan_saa9730_private *lp)
+{
+	int i, j;
+	printk("TxmBufferA = %x\n", lp->TxmBuffer[0][0]);
+	printk("TxmBufferB = %x\n", lp->TxmBuffer[1][0]);
+	printk("RcvBufferA = %x\n", lp->RcvBuffer[0][0]);
+	printk("RcvBufferB = %x\n", lp->RcvBuffer[1][0]);
+	for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
+		for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) {
+			printk("TxmBuffer[%d][%d] = %x\n", i, j,
+			       le32_to_cpu(*(unsigned int *)
+					   lp->TxmBuffer[i][j]));
+		}
+	}
+	for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
+		for (j = 0; j < LAN_SAA9730_RCV_Q_SIZE; j++) {
+			printk("RcvBuffer[%d][%d] = %x\n", i, j,
+			       le32_to_cpu(*(unsigned int *)
+					   lp->RcvBuffer[i][j]));
+		}
+	}
+	printk("lp->evm_saa9730_regs->InterruptBlock1 = %x\n",
+	       INL(&lp->evm_saa9730_regs->InterruptBlock1));
+	printk("lp->evm_saa9730_regs->InterruptStatus1 = %x\n",
+	       INL(&lp->evm_saa9730_regs->InterruptStatus1));
+	printk("lp->evm_saa9730_regs->InterruptEnable1 = %x\n",
+	       INL(&lp->evm_saa9730_regs->InterruptEnable1));
+	printk("lp->lan_saa9730_regs->Ok2Use = %x\n",
+	       INL(&lp->lan_saa9730_regs->Ok2Use));
+	printk("lp->NextTxmBufferIndex = %x\n", lp->NextTxmBufferIndex);
+	printk("lp->NextTxmPacketIndex = %x\n", lp->NextTxmPacketIndex);
+	printk("lp->PendingTxmBufferIndex = %x\n",
+	       lp->PendingTxmBufferIndex);
+	printk("lp->PendingTxmPacketIndex = %x\n",
+	       lp->PendingTxmPacketIndex);
+	printk("lp->lan_saa9730_regs->LanDmaCtl = %x\n",
+	       INL(&lp->lan_saa9730_regs->LanDmaCtl));
+	printk("lp->lan_saa9730_regs->DmaStatus = %x\n",
+	       INL(&lp->lan_saa9730_regs->DmaStatus));
+	printk("lp->lan_saa9730_regs->CamCtl = %x\n",
+	       INL(&lp->lan_saa9730_regs->CamCtl));
+	printk("lp->lan_saa9730_regs->TxCtl = %x\n",
+	       INL(&lp->lan_saa9730_regs->TxCtl));
+	printk("lp->lan_saa9730_regs->TxStatus = %x\n",
+	       INL(&lp->lan_saa9730_regs->TxStatus));
+	printk("lp->lan_saa9730_regs->RxCtl = %x\n",
+	       INL(&lp->lan_saa9730_regs->RxCtl));
+	printk("lp->lan_saa9730_regs->RxStatus = %x\n",
+	       INL(&lp->lan_saa9730_regs->RxStatus));
+	for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) {
+		OUTL(i, &lp->lan_saa9730_regs->CamAddress);
+		printk("lp->lan_saa9730_regs->CamData = %x\n",
+		       INL(&lp->lan_saa9730_regs->CamData));
+	}
+	printk("lp->stats.tx_packets = %lx\n", lp->stats.tx_packets);
+	printk("lp->stats.tx_errors = %lx\n", lp->stats.tx_errors);
+	printk("lp->stats.tx_aborted_errors = %lx\n",
+	       lp->stats.tx_aborted_errors);
+	printk("lp->stats.tx_window_errors = %lx\n",
+	       lp->stats.tx_window_errors);
+	printk("lp->stats.tx_carrier_errors = %lx\n",
+	       lp->stats.tx_carrier_errors);
+	printk("lp->stats.tx_fifo_errors = %lx\n",
+	       lp->stats.tx_fifo_errors);
+	printk("lp->stats.tx_heartbeat_errors = %lx\n",
+	       lp->stats.tx_heartbeat_errors);
+	printk("lp->stats.collisions = %lx\n", lp->stats.collisions);
+
+	printk("lp->stats.rx_packets = %lx\n", lp->stats.rx_packets);
+	printk("lp->stats.rx_errors = %lx\n", lp->stats.rx_errors);
+	printk("lp->stats.rx_dropped = %lx\n", lp->stats.rx_dropped);
+	printk("lp->stats.rx_crc_errors = %lx\n", lp->stats.rx_crc_errors);
+	printk("lp->stats.rx_frame_errors = %lx\n",
+	       lp->stats.rx_frame_errors);
+	printk("lp->stats.rx_fifo_errors = %lx\n",
+	       lp->stats.rx_fifo_errors);
+	printk("lp->stats.rx_length_errors = %lx\n",
+	       lp->stats.rx_length_errors);
+
+	printk("lp->lan_saa9730_regs->DebugPCIMasterAddr = %x\n",
+	       INL(&lp->lan_saa9730_regs->DebugPCIMasterAddr));
+	printk("lp->lan_saa9730_regs->DebugLanTxStateMachine = %x\n",
+	       INL(&lp->lan_saa9730_regs->DebugLanTxStateMachine));
+	printk("lp->lan_saa9730_regs->DebugLanRxStateMachine = %x\n",
+	       INL(&lp->lan_saa9730_regs->DebugLanRxStateMachine));
+	printk("lp->lan_saa9730_regs->DebugLanTxFifoPointers = %x\n",
+	       INL(&lp->lan_saa9730_regs->DebugLanTxFifoPointers));
+	printk("lp->lan_saa9730_regs->DebugLanRxFifoPointers = %x\n",
+	       INL(&lp->lan_saa9730_regs->DebugLanRxFifoPointers));
+	printk("lp->lan_saa9730_regs->DebugLanCtlStateMachine = %x\n",
+	       INL(&lp->lan_saa9730_regs->DebugLanCtlStateMachine));
+}
+
+static void lan_saa9730_buffer_init(struct lan_saa9730_private *lp)
+{
+	int i, j;
+
+	/* Init RX buffers */
+	for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
+		for (j = 0; j < LAN_SAA9730_RCV_Q_SIZE; j++) {
+			*(unsigned int *) lp->RcvBuffer[i][j] =
+			    cpu_to_le32(RXSF_READY <<
+					RX_STAT_CTL_OWNER_SHF);
+		}
+	}
+
+	/* Init TX buffers */
+	for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
+		for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) {
+			*(unsigned int *) lp->TxmBuffer[i][j] =
+			    cpu_to_le32(TXSF_EMPTY <<
+					TX_STAT_CTL_OWNER_SHF);
+		}
+	}
+}
+
+static int lan_saa9730_allocate_buffers(struct lan_saa9730_private *lp)
+{
+	unsigned int mem_size;
+	void *Pa;
+	unsigned int i, j, RcvBufferSize, TxmBufferSize;
+	unsigned int buffer_start;
+
+	/* 
+	 * Allocate all RX and TX packets in one chunk. 
+	 * The Rx and Tx packets must be PACKET_SIZE aligned.
+	 */
+	mem_size = ((LAN_SAA9730_RCV_Q_SIZE + LAN_SAA9730_TXM_Q_SIZE) *
+		    LAN_SAA9730_PACKET_SIZE * LAN_SAA9730_BUFFERS) +
+	    LAN_SAA9730_PACKET_SIZE;
+	buffer_start =
+	    (unsigned int) kmalloc(mem_size, GFP_DMA | GFP_KERNEL);
+
+	/* 
+	 * Set DMA buffer to kseg1 (uncached).
+	 * Make sure to flush before using it uncached.
+	 */
+	Pa = (void *) KSEG1ADDR((buffer_start + LAN_SAA9730_PACKET_SIZE) &
+				~(LAN_SAA9730_PACKET_SIZE - 1));
+	dma_cache_wback_inv((unsigned long) Pa, mem_size);
+
+	/* Initialize buffer space */
+	RcvBufferSize = LAN_SAA9730_PACKET_SIZE;
+	TxmBufferSize = LAN_SAA9730_PACKET_SIZE;
+	lp->DmaRcvPackets = LAN_SAA9730_RCV_Q_SIZE;
+	lp->DmaTxmPackets = LAN_SAA9730_TXM_Q_SIZE;
+
+	/* Init RX buffers */
+	for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
+		for (j = 0; j < LAN_SAA9730_RCV_Q_SIZE; j++) {
+			*(unsigned int *) Pa =
+			    cpu_to_le32(RXSF_READY <<
+					RX_STAT_CTL_OWNER_SHF);
+			lp->RcvBuffer[i][j] = (unsigned int) Pa;
+			Pa += RcvBufferSize;
+		}
+	}
+
+	/* Init TX buffers */
+	for (i = 0; i < LAN_SAA9730_BUFFERS; i++) {
+		for (j = 0; j < LAN_SAA9730_TXM_Q_SIZE; j++) {
+			*(unsigned int *) Pa =
+			    cpu_to_le32(TXSF_EMPTY <<
+					TX_STAT_CTL_OWNER_SHF);
+			lp->TxmBuffer[i][j] = (unsigned int) Pa;
+			Pa += TxmBufferSize;
+		}
+	}
+
+	/* 
+	 * Set rx buffer A and rx buffer B to point to the first two buffer 
+	 * spaces.
+	 */
+	OUTL(PHYSADDR(lp->RcvBuffer[0][0]),
+	     &lp->lan_saa9730_regs->RxBuffA);
+	OUTL(PHYSADDR(lp->RcvBuffer[1][0]),
+	     &lp->lan_saa9730_regs->RxBuffB);
+
+	/* Initialize Buffer Index */
+	lp->NextRcvPacketIndex = 0;
+	lp->NextRcvToUseIsA = 1;
+
+	/* Set current buffer index & next availble packet index */
+	lp->NextTxmPacketIndex = 0;
+	lp->NextTxmBufferIndex = 0;
+	lp->PendingTxmPacketIndex = 0;
+	lp->PendingTxmBufferIndex = 0;
+
+	/* 
+	 * Set txm_buf_a and txm_buf_b to point to the first two buffer
+	 * space 
+	 */
+	OUTL(PHYSADDR(lp->TxmBuffer[0][0]),
+	     &lp->lan_saa9730_regs->TxBuffA);
+	OUTL(PHYSADDR(lp->TxmBuffer[1][0]),
+	     &lp->lan_saa9730_regs->TxBuffB);
+
+	/* Set packet number */
+	OUTL((lp->DmaRcvPackets << PK_COUNT_RX_A_SHF) |
+	     (lp->DmaRcvPackets << PK_COUNT_RX_B_SHF) |
+	     (lp->DmaTxmPackets << PK_COUNT_TX_A_SHF) |
+	     (lp->DmaTxmPackets << PK_COUNT_TX_B_SHF),
+	     &lp->lan_saa9730_regs->PacketCount);
+
+	return 0;
+}
+
+static int lan_saa9730_cam_load(struct lan_saa9730_private *lp)
+{
+	unsigned int i;
+	unsigned char *NetworkAddress;
+
+	NetworkAddress = (unsigned char *) &lp->PhysicalAddress[0][0];
+
+	for (i = 0; i < LAN_SAA9730_CAM_DWORDS; i++) {
+		/* First set address to where data is written */
+		OUTL(i, &lp->lan_saa9730_regs->CamAddress);
+		OUTL((NetworkAddress[0] << 24) | (NetworkAddress[1] << 16)
+		     | (NetworkAddress[2] << 8) | NetworkAddress[3],
+		     &lp->lan_saa9730_regs->CamData);
+		NetworkAddress += 4;
+	}
+	return 0;
+}
+
+static int lan_saa9730_cam_init(struct net_device *dev)
+{
+	struct lan_saa9730_private *lp =
+	    (struct lan_saa9730_private *) dev->priv;
+	unsigned int i;
+
+	/* Copy MAC-address into all entries. */
+	for (i = 0; i < LAN_SAA9730_CAM_ENTRIES; i++) {
+		memcpy((unsigned char *) lp->PhysicalAddress[i],
+		       (unsigned char *) dev->dev_addr, 6);
+	}
+
+	return 0;
+}
+
+static int lan_saa9730_mii_init(struct lan_saa9730_private *lp)
+{
+	int i, l;
+
+	/* Check link status, spin here till station is not busy. */
+	i = 0;
+	while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) {
+		i++;
+		if (i > 100) {
+			printk("Error: lan_saa9730_mii_init: timeout\n");
+			return -1;
+		}
+		udelay(1000);	/* wait 1 ms. */
+	}
+
+	/* Now set the control and address register. */
+	OUTL(MD_CA_BUSY | PHY_STATUS | PHY_ADDRESS << MD_CA_PHY_SHF,
+	     &lp->lan_saa9730_regs->StationMgmtCtl);
+
+	/* check link status, spin here till station is not busy */
+	i = 0;
+	while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) & MD_CA_BUSY) {
+		i++;
+		if (i > 100) {
+			printk("Error: lan_saa9730_mii_init: timeout\n");
+			return -1;
+		}
+		udelay(1000);	/* wait 1 ms. */
+	}
+
+	/* Wait for 1 ms. */
+	udelay(1000);
+
+	/* Check the link status. */
+	if (INL(&lp->lan_saa9730_regs->StationMgmtData) &
+	    PHY_STATUS_LINK_UP) {
+		/* Link is up. */
+		return 0;
+	} else {
+		/* Link is down, reset the PHY first. */
+
+		/* set PHY address = 'CONTROL' */
+		OUTL(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL,
+		     &lp->lan_saa9730_regs->StationMgmtCtl);
+
+		/* Wait for 1 ms. */
+		udelay(1000);
+
+		/* set 'CONTROL' = force reset and renegotiate */
+		OUTL(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG |
+		     PHY_CONTROL_RESTART_AUTO_NEG,
+		     &lp->lan_saa9730_regs->StationMgmtData);
+
+		/* Wait for 50 ms. */
+		udelay(50 * 1000);
+
+		/* set 'BUSY' to start operation */
+		OUTL(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR |
+		     PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl);
+
+		/* await completion */
+		i = 0;
+		while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) &
+		       MD_CA_BUSY) {
+			i++;
+			if (i > 100) {
+				printk
+				    ("Error: lan_saa9730_mii_init: timeout\n");
+				return -1;
+			}
+			udelay(1000);	/* wait 1 ms. */
+		}
+
+		/* Wait for 1 ms. */
+		udelay(1000);
+
+		for (l = 0; l < 2; l++) {
+			/* set PHY address = 'STATUS' */
+			OUTL(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF |
+			     PHY_STATUS,
+			     &lp->lan_saa9730_regs->StationMgmtCtl);
+
+			/* await completion */
+			i = 0;
+			while (INL(&lp->lan_saa9730_regs->StationMgmtCtl) &
+			       MD_CA_BUSY) {
+				i++;
+				if (i > 100) {
+					printk
+					    ("Error: lan_saa9730_mii_init: timeout\n");
+					return -1;
+				}
+				udelay(1000);	/* wait 1 ms. */
+			}
+
+			/* wait for 3 sec. */
+			udelay(3000 * 1000);
+
+			/* check the link status */
+			if (INL(&lp->lan_saa9730_regs->StationMgmtData) &
+			    PHY_STATUS_LINK_UP) {
+				/* link is up */
+				break;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int lan_saa9730_control_init(struct lan_saa9730_private *lp)
+{
+	/* Initialize DMA control register. */
+	OUTL((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) |
+	     (LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) |
+	     (LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF)
+	     | DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN |
+	     DMA_CTL_MAC_RX_INT_EN | DMA_CTL_MAC_TX_INT_EN,
+	     &lp->lan_saa9730_regs->LanDmaCtl);
+
+	/* Initial MAC control register. */
+	OUTL((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP,
+	     &lp->lan_saa9730_regs->MacCtl);
+
+	/* Initialize CAM control register. */
+	OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC,
+	     &lp->lan_saa9730_regs->CamCtl);
+
+	/* 
+	 * Initialize CAM enable register, only turn on first entry, should
+	 * contain own addr. 
+	 */
+	OUTL(0x0001, &lp->lan_saa9730_regs->CamEnable);
+
+	/* Initialize Tx control register */
+	OUTL(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl);
+
+	/* Initialize Rcv control register */
+	OUTL(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl);
+
+	/* Reset DMA engine */
+	OUTL(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
+
+	return 0;
+}
+
+static int lan_saa9730_stop(struct lan_saa9730_private *lp)
+{
+	int i;
+
+	/* Stop DMA first */
+	OUTL(INL(&lp->lan_saa9730_regs->LanDmaCtl) &
+	     ~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA),
+	     &lp->lan_saa9730_regs->LanDmaCtl);
+
+	/* Set the SW Reset bits in DMA and MAC control registers */
+	OUTL(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);
+	OUTL(INL(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET,
+	     &lp->lan_saa9730_regs->MacCtl);
+
+	/* 
+	 * Wait for MAC reset to have finished. The reset bit is auto cleared
+	 * when the reset is done.
+	 */
+	i = 0;
+	while (INL(&lp->lan_saa9730_regs->MacCtl) & MAC_CONTROL_RESET) {
+		i++;
+		if (i > 100) {
+			printk
+			    ("Error: lan_sa9730_stop: MAC reset timeout\n");
+			return -1;
+		}
+		udelay(1000);	/* wait 1 ms. */
+	}
+
+	return 0;
+}
+
+static int lan_saa9730_dma_init(struct lan_saa9730_private *lp)
+{
+	/* Stop lan controller. */
+	lan_saa9730_stop(lp);
+
+	OUTL(LAN_SAA9730_DEFAULT_TIME_OUT_CNT,
+	     &lp->lan_saa9730_regs->Timeout);
+
+	return 0;
+}
+
+static int lan_saa9730_start(struct lan_saa9730_private *lp)
+{
+	lan_saa9730_buffer_init(lp);
+
+	/* Initialize Rx Buffer Index */
+	lp->NextRcvPacketIndex = 0;
+	lp->NextRcvToUseIsA = 1;
+
+	/* Set current buffer index & next availble packet index */
+	lp->NextTxmPacketIndex = 0;
+	lp->NextTxmBufferIndex = 0;
+	lp->PendingTxmPacketIndex = 0;
+	lp->PendingTxmBufferIndex = 0;
+
+	OUTL(INL(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA |
+	     DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl);
+
+	/* For Tx, turn on MAC then DMA */
+	OUTL(INL(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN,
+	     &lp->lan_saa9730_regs->TxCtl);
+
+	/* For Rx, turn on DMA then MAC */
+	OUTL(INL(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN,
+	     &lp->lan_saa9730_regs->RxCtl);
+
+	/* Set Ok2Use to let hardware owns the buffers */
+	OUTL(OK2USE_RX_A | OK2USE_RX_B | OK2USE_TX_A | OK2USE_TX_B,
+	     &lp->lan_saa9730_regs->Ok2Use);
+
+	return 0;
+}
+
+static int lan_saa9730_restart(struct lan_saa9730_private *lp)
+{
+	lan_saa9730_stop(lp);
+	lan_saa9730_start(lp);
+
+	return 0;
+}
+
+static int lan_saa9730_tx(struct net_device *dev)
+{
+	struct lan_saa9730_private *lp =
+	    (struct lan_saa9730_private *) dev->priv;
+	unsigned int *pPacket;
+	unsigned int tx_status;
+
+	if (lan_saa9730_debug > 5)
+		printk("lan_saa9730_tx interrupt\n");
+
+	/* Clear interrupt. */
+	OUTL(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus);
+
+	while (1) {
+		pPacket =
+		    (unsigned int *) lp->TxmBuffer[lp->
+						   PendingTxmBufferIndex]
+		    [lp->PendingTxmPacketIndex];
+
+		/* Get status of first packet transmitted. */
+		tx_status = le32_to_cpu(*pPacket);
+
+		/* Check ownership. */
+		if ((tx_status & TX_STAT_CTL_OWNER_MSK) !=
+		    (TXSF_HWDONE << TX_STAT_CTL_OWNER_SHF)) break;
+
+		/* Check for error. */
+		if (tx_status & TX_STAT_CTL_ERROR_MSK) {
+			if (lan_saa9730_debug > 1)
+				printk("lan_saa9730_tx: tx error = %x\n",
+				       tx_status);
+
+			lp->stats.tx_errors++;
+			if (tx_status &
+			    (TX_STATUS_EX_COLL << TX_STAT_CTL_STATUS_SHF))
+				    lp->stats.tx_aborted_errors++;
+			if (tx_status &
+			    (TX_STATUS_LATE_COLL <<
+			     TX_STAT_CTL_STATUS_SHF)) lp->stats.
+	     tx_window_errors++;
+			if (tx_status &
+			    (TX_STATUS_L_CARR << TX_STAT_CTL_STATUS_SHF))
+				    lp->stats.tx_carrier_errors++;
+			if (tx_status &
+			    (TX_STATUS_UNDER << TX_STAT_CTL_STATUS_SHF))
+				    lp->stats.tx_fifo_errors++;
+			if (tx_status &
+			    (TX_STATUS_SQ_ERR << TX_STAT_CTL_STATUS_SHF))
+				    lp->stats.tx_heartbeat_errors++;
+
+			lp->stats.collisions +=
+			    tx_status & TX_STATUS_TX_COLL_MSK;
+		}
+
+		/* Free buffer. */
+		*pPacket =
+		    cpu_to_le32(TXSF_EMPTY << TX_STAT_CTL_OWNER_SHF);
+
+		/* Update pending index pointer. */
+		lp->PendingTxmPacketIndex++;
+		if (lp->PendingTxmPacketIndex >= LAN_SAA9730_TXM_Q_SIZE) {
+			lp->PendingTxmPacketIndex = 0;
+			lp->PendingTxmBufferIndex ^= 1;
+		}
+	}
+
+	/* Make sure A and B are available to hardware. */
+	OUTL(OK2USE_TX_A | OK2USE_TX_B, &lp->lan_saa9730_regs->Ok2Use);
+
+	if (netif_queue_stopped(dev)) {
+		/* The tx buffer is no longer full. */
+		netif_wake_queue(dev);
+	}
+
+	return 0;
+}
+
+static int lan_saa9730_rx(struct net_device *dev)
+{
+	struct lan_saa9730_private *lp =
+	    (struct lan_saa9730_private *) dev->priv;
+	int len = 0;
+	struct sk_buff *skb = 0;
+	unsigned int rx_status;
+	int BufferIndex;
+	int PacketIndex;
+	unsigned int *pPacket;
+	unsigned char *pData;
+
+	if (lan_saa9730_debug > 5)
+		printk("lan_saa9730_rx interrupt\n");
+
+	/* Clear receive interrupts. */
+	OUTL(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT |
+	     DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus);
+
+	/* Address next packet */
+	if (lp->NextRcvToUseIsA)
+		BufferIndex = 0;
+	else
+		BufferIndex = 1;
+	PacketIndex = lp->NextRcvPacketIndex;
+	pPacket = (unsigned int *) lp->RcvBuffer[BufferIndex][PacketIndex];
+	rx_status = le32_to_cpu(*pPacket);
+
+	/* Process each packet. */
+	while ((rx_status & RX_STAT_CTL_OWNER_MSK) ==
+	       (RXSF_HWDONE << RX_STAT_CTL_OWNER_SHF)) {
+		/* Check the rx status. */
+		if (rx_status & (RX_STATUS_GOOD << RX_STAT_CTL_STATUS_SHF)) {
+			/* Received packet is good. */
+			len = (rx_status & RX_STAT_CTL_LENGTH_MSK) >>
+			    RX_STAT_CTL_LENGTH_SHF;
+
+			pData = (unsigned char *) pPacket;
+			pData += 4;
+			skb = dev_alloc_skb(len + 2);
+			if (skb == 0) {
+				printk
+				    ("%s: Memory squeeze, deferring packet.\n",
+				     dev->name);
+				lp->stats.rx_dropped++;
+			} else {
+				lp->stats.rx_bytes += len;
+				lp->stats.rx_packets++;
+				skb->dev = dev;
+				skb_reserve(skb, 2);	/* 16 byte align */
+				skb_put(skb, len);	/* make room */
+				eth_copy_and_sum(skb,
+						 (unsigned char *) pData,
+						 len, 0);
+				skb->protocol = eth_type_trans(skb, dev);
+				netif_rx(skb);
+			}
+		} else {
+			/* We got an error packet. */
+			if (lan_saa9730_debug > 2)
+				printk
+				    ("lan_saa9730_rx: We got an error packet = %x\n",
+				     rx_status);
+
+			lp->stats.rx_errors++;
+			if (rx_status &
+			    (RX_STATUS_CRC_ERR << RX_STAT_CTL_STATUS_SHF))
+				    lp->stats.rx_crc_errors++;
+			if (rx_status &
+			    (RX_STATUS_ALIGN_ERR <<
+			     RX_STAT_CTL_STATUS_SHF)) lp->stats.
+	     rx_frame_errors++;
+			if (rx_status &
+			    (RX_STATUS_OVERFLOW << RX_STAT_CTL_STATUS_SHF))
+				    lp->stats.rx_fifo_errors++;
+			if (rx_status &
+			    (RX_STATUS_LONG_ERR << RX_STAT_CTL_STATUS_SHF))
+				    lp->stats.rx_length_errors++;
+		}
+
+		/* Indicate we have processed the buffer. */
+		*pPacket =
+		    cpu_to_le32(RXSF_READY << RX_STAT_CTL_OWNER_SHF);
+
+		/* Go to next packet in sequence. */
+		lp->NextRcvPacketIndex++;
+		if (lp->NextRcvPacketIndex >= LAN_SAA9730_RCV_Q_SIZE) {
+			lp->NextRcvPacketIndex = 0;
+			if (BufferIndex) {
+				lp->NextRcvToUseIsA = 1;
+			} else {
+				lp->NextRcvToUseIsA = 0;
+			}
+		}
+		OUTL(OK2USE_RX_A | OK2USE_RX_B,
+		     &lp->lan_saa9730_regs->Ok2Use);
+
+		/* Address next packet */
+		if (lp->NextRcvToUseIsA)
+			BufferIndex = 0;
+		else
+			BufferIndex = 1;
+		PacketIndex = lp->NextRcvPacketIndex;
+		pPacket =
+		    (unsigned int *) lp->
+		    RcvBuffer[BufferIndex][PacketIndex];
+		rx_status = le32_to_cpu(*pPacket);
+	}
+
+	/* Make sure A and B are available to hardware. */
+	OUTL(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use);
+
+	return 0;
+}
+
+static void lan_saa9730_interrupt(const int irq, void *dev_id,
+				  struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+	struct lan_saa9730_private *lp =
+	    (struct lan_saa9730_private *) dev->priv;
+
+	if (lan_saa9730_debug > 5)
+		printk("lan_saa9730_interrupt\n");
+
+	/* Disable the EVM LAN interrupt. */
+	evm_saa9730_block_lan_int(lp);
+
+	/* Clear the EVM LAN interrupt. */
+	evm_saa9730_clear_lan_int(lp);
+
+	/* Service pending transmit interrupts. */
+	if (INL(&lp->lan_saa9730_regs->DmaStatus) & DMA_STATUS_MAC_TX_INT)
+		lan_saa9730_tx(dev);
+
+	/* Service pending receive interrupts. */
+	if (INL(&lp->lan_saa9730_regs->DmaStatus) &
+	    (DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT |
+	     DMA_STATUS_RX_TO_INT)) lan_saa9730_rx(dev);
+
+	/* Enable the EVM LAN interrupt. */
+	evm_saa9730_unblock_lan_int(lp);
+
+	return;
+}
+
+static int lan_saa9730_open_fail(struct net_device *dev)
+{
+	return -ENODEV;
+}
+
+static int lan_saa9730_open(struct net_device *dev)
+{
+	struct lan_saa9730_private *lp =
+	    (struct lan_saa9730_private *) dev->priv;
+
+	/* Associate IRQ with lan_saa9730_interrupt */
+	if (request_irq(dev->irq, &lan_saa9730_interrupt, 0, "SAA9730 Eth",
+			dev)) {
+		printk("lan_saa9730_open: Can't get irq %d\n", dev->irq);
+		return -EAGAIN;
+	}
+
+	/* Enable the Lan interrupt in the event manager. */
+	evm_saa9730_enable_lan_int(lp);
+
+	/* Start the LAN controller */
+	if (lan_saa9730_start(lp))
+		return -1;
+
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static int lan_saa9730_write(struct lan_saa9730_private *lp,
+			     struct sk_buff *skb, int skblen)
+{
+	unsigned char *pbData = skb->data;
+	unsigned int len = skblen;
+	unsigned char *pbPacketData;
+	unsigned int tx_status;
+	int BufferIndex;
+	int PacketIndex;
+
+	if (lan_saa9730_debug > 5)
+		printk("lan_saa9730_write: skb=%08x\n",
+		       (unsigned int) skb);
+
+	BufferIndex = lp->NextTxmBufferIndex;
+	PacketIndex = lp->NextTxmPacketIndex;
+
+	tx_status =
+	    le32_to_cpu(*(unsigned int *) lp->
+			TxmBuffer[BufferIndex][PacketIndex]);
+	if ((tx_status & TX_STAT_CTL_OWNER_MSK) !=
+	    (TXSF_EMPTY << TX_STAT_CTL_OWNER_SHF)) {
+		if (lan_saa9730_debug > 4)
+			printk
+			    ("lan_saa9730_write: Tx buffer not available: tx_status = %x\n",
+			     tx_status);
+		return -1;
+	}
+
+	lp->NextTxmPacketIndex++;
+	if (lp->NextTxmPacketIndex >= LAN_SAA9730_TXM_Q_SIZE) {
+		lp->NextTxmPacketIndex = 0;
+		lp->NextTxmBufferIndex ^= 1;
+	}
+
+	pbPacketData =
+	    (unsigned char *) lp->TxmBuffer[BufferIndex][PacketIndex];
+	pbPacketData += 4;
+
+	/* copy the bits */
+	memcpy(pbPacketData, pbData, len);
+
+	/* Set transmit status for hardware */
+	*(unsigned int *) lp->TxmBuffer[BufferIndex][PacketIndex] =
+	    cpu_to_le32((TXSF_READY << TX_STAT_CTL_OWNER_SHF) |
+			(TX_STAT_CTL_INT_AFTER_TX << TX_STAT_CTL_FRAME_SHF)
+			| (len << TX_STAT_CTL_LENGTH_SHF));
+
+	/* Set hardware tx buffer. */
+	OUTL(OK2USE_TX_A | OK2USE_TX_B, &lp->lan_saa9730_regs->Ok2Use);
+
+	return 0;
+}
+
+static void lan_saa9730_tx_timeout(struct net_device *dev)
+{
+	struct lan_saa9730_private *lp =
+	    (struct lan_saa9730_private *) dev->priv;
+
+	/* Transmitter timeout, serious problems */
+	lp->stats.tx_errors++;
+	printk("%s: transmit timed out, reset\n", dev->name);
+	/*show_saa9730_regs(lp); */
+	lan_saa9730_restart(lp);
+
+	dev->trans_start = jiffies;
+	netif_start_queue(dev);
+}
+
+static int lan_saa9730_start_xmit(struct sk_buff *skb,
+				  struct net_device *dev)
+{
+	struct lan_saa9730_private *lp =
+	    (struct lan_saa9730_private *) dev->priv;
+	unsigned long flags;
+	int skblen;
+	int len;
+
+	if (lan_saa9730_debug > 4)
+		printk("Send packet: skb=%08x\n", (unsigned int) skb);
+
+	skblen = skb->len;
+	save_and_cli(flags);
+	len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
+
+	if (lan_saa9730_write(lp, skb, skblen)) {
+		restore_flags(flags);
+		printk
+		    ("Error when writing packet to controller: skb=%08x\n",
+		     (unsigned int) skb);
+		netif_stop_queue(dev);
+		return -1;
+	}
+
+	lp->stats.tx_bytes += len;
+	lp->stats.tx_packets++;
+
+	dev->trans_start = jiffies;
+	netif_start_queue(dev);
+	dev_kfree_skb(skb);
+
+	restore_flags(flags);
+
+	return 0;
+}
+
+static int lan_saa9730_close(struct net_device *dev)
+{
+	struct lan_saa9730_private *lp =
+	    (struct lan_saa9730_private *) dev->priv;
+
+	if (lan_saa9730_debug > 1)
+		printk("lan_saa9730_close:\n");
+
+	netif_stop_queue(dev);
+
+	/* Disable the Lan interrupt in the event manager. */
+	evm_saa9730_disable_lan_int(lp);
+
+	/* Stop the controller */
+	if (lan_saa9730_stop(lp))
+		return -1;
+
+	free_irq(dev->irq, (void *) dev);
+
+	return 0;
+}
+
+static struct net_device_stats *lan_saa9730_get_stats(struct net_device
+						      *dev)
+{
+	struct lan_saa9730_private *lp =
+	    (struct lan_saa9730_private *) dev->priv;
+
+	return &lp->stats;
+}
+
+static void lan_saa9730_set_multicast(struct net_device *dev)
+{
+	struct lan_saa9730_private *lp =
+	    (struct lan_saa9730_private *) dev->priv;
+
+	/* Stop the controller */
+	lan_saa9730_stop(lp);
+
+	if (dev->flags & IFF_PROMISC) {
+		/* accept all packets */
+		OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_STATION_ACC |
+		     CAM_CONTROL_GROUP_ACC | CAM_CONTROL_BROAD_ACC,
+		     &lp->lan_saa9730_regs->CamCtl);
+	} else {
+		if (dev->flags & IFF_ALLMULTI) {
+			/* accept all multicast packets */
+			OUTL(CAM_CONTROL_COMP_EN | CAM_CONTROL_GROUP_ACC |
+			     CAM_CONTROL_BROAD_ACC,
+			     &lp->lan_saa9730_regs->CamCtl);
+		} else {
+			/* 
+			 * Will handle the multicast stuff later. -carstenl
+			 */
+		}
+	}
+
+	lan_saa9730_restart(lp);
+}
+
+static int lan_saa9730_init(struct net_device *dev, int ioaddr, int irq)
+{
+	struct lan_saa9730_private *lp;
+	unsigned char ethernet_addr[6];
+
+	dev = init_etherdev(dev, 0);
+
+	dev->open = lan_saa9730_open_fail;
+	if (get_ethernet_addr(ethernet_addr))
+		return -1;
+
+	memcpy(dev->dev_addr, ethernet_addr, 6);
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+
+	/* 
+	 * Make certain the data structures used by the controller are aligned 
+	 * and DMAble. 
+	 */
+	lp = (struct lan_saa9730_private *) (((unsigned long)
+					      kmalloc(sizeof(*lp) + 7,
+						      GFP_DMA | GFP_KERNEL)
+					      + 7) & ~7);
+
+	dev->priv = lp;
+	memset(lp, 0, sizeof(*lp));
+
+	/* Set SAA9730 LAN base address. */
+	lp->lan_saa9730_regs = (t_lan_saa9730_regmap *) (ioaddr +
+							 SAA9730_LAN_REGS_ADDR);
+
+	/* Set SAA9730 EVM base address. */
+	lp->evm_saa9730_regs = (t_evm_saa9730_regmap *) (ioaddr +
+							 SAA9730_EVM_REGS_ADDR);
+
+	/* Allocate LAN RX/TX frame buffer space. */
+	if (lan_saa9730_allocate_buffers(lp))
+		return -1;
+
+	/* Stop LAN controller. */
+	if (lan_saa9730_stop(lp))
+		return -1;
+
+	/* Initialize CAM registers. */
+	if (lan_saa9730_cam_init(dev))
+		return -1;
+
+	/* Initialize MII registers. */
+	if (lan_saa9730_mii_init(lp))
+		return -1;
+
+	/* Initialize control registers. */
+	if (lan_saa9730_control_init(lp))
+		return -1;
+
+	/* Load CAM registers. */
+	if (lan_saa9730_cam_load(lp))
+		return -1;
+
+	/* Initialize DMA context registers. */
+	if (lan_saa9730_dma_init(lp))
+		return -1;
+
+	dev->open = lan_saa9730_open;
+	dev->hard_start_xmit = lan_saa9730_start_xmit;
+	dev->stop = lan_saa9730_close;
+	dev->get_stats = lan_saa9730_get_stats;
+	dev->set_multicast_list = lan_saa9730_set_multicast;
+	dev->tx_timeout = lan_saa9730_tx_timeout;
+	dev->watchdog_timeo = (HZ >> 1);
+	dev->dma = 0;
+
+	return 0;
+}
+
+
+static int __init saa9730_probe(void)
+{
+	struct net_device *dev = NULL;
+
+	if (pci_present()) {
+		struct pci_dev *pdev = NULL;
+		if (lan_saa9730_debug > 1)
+			printk
+			    ("saa9730.c: PCI bios is present, checking for devices...\n");
+
+		while ((pdev = pci_find_device(PCI_VENDOR_ID_PHILIPS,
+					       PCI_DEVICE_ID_PHILIPS_SAA9730,
+					       pdev))) {
+			unsigned int pci_ioaddr;
+
+			pci_irq_line = pdev->irq;
+			/* LAN base address in located at BAR 1. */
+
+			pci_ioaddr = pci_resource_start(pdev, 1);
+			pci_set_master(pdev);
+
+			printk("Found SAA9730 (PCI) at %#x, irq %d.\n",
+			       pci_ioaddr, pci_irq_line);
+			if (!lan_saa9730_init
+			    (dev, pci_ioaddr, pci_irq_line)) return 0;
+			else
+				printk("Lan init failed.\n");
+		}
+	}
+
+	return -ENODEV;
+}
+
+module_init(saa9730_probe);
diff -urN linux-2.4.4-pre3/drivers/net/saa9730.h linux/drivers/net/saa9730.h
--- linux-2.4.4-pre3/drivers/net/saa9730.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/saa9730.h	Mon Dec  3 22:35:22 2001
@@ -0,0 +1,370 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * SAA9730 ethernet driver description.
+ *
+ */
+#ifndef _SAA9730_H
+#define _SAA9730_H
+
+
+/* Number of 6-byte entries in the CAM. */
+#define LAN_SAA9730_CAM_ENTRIES              10
+#define	LAN_SAA9730_CAM_DWORDS               ((LAN_SAA9730_CAM_ENTRIES*6)/4)
+
+/* TX and RX packet size: fixed to 2048 bytes, according to HW requirements. */
+#define LAN_SAA9730_PACKET_SIZE                       2048
+
+/* 
+ * Number of TX buffers = number of RX buffers = 2, which is fixed according 
+ * to HW requirements. 
+ */
+#define LAN_SAA9730_BUFFERS                           2
+
+/* Number of RX packets per RX buffer. */
+#define LAN_SAA9730_RCV_Q_SIZE                        15
+
+/* Number of TX packets per TX buffer. */
+#define LAN_SAA9730_TXM_Q_SIZE                        15
+
+/*
+ * We get an interrupt for each LAN_SAA9730_DEFAULT_RCV_Q_INT_THRESHOLD 
+ * packets received. 
+ * If however we receive less than  LAN_SAA9730_DEFAULT_RCV_Q_INT_THRESHOLD
+ * packets, the hardware can timeout after a certain time and still tell 
+ * us packets have arrived.
+ * The timeout value in unit of 32 PCI clocks (33Mhz).
+ * The value 200 approximates 0.0002 seconds.
+ */
+#define LAN_SAA9730_RCV_Q_INT_THRESHOLD               1
+#define LAN_SAA9730_DEFAULT_TIME_OUT_CNT              10
+
+#define RXSF_NDIS                       0
+#define RXSF_READY                      2
+#define RXSF_HWDONE                     3
+
+#define TXSF_EMPTY                      0
+#define TXSF_READY                      2
+#define TXSF_HWDONE                     3
+
+#define LANEND_LITTLE                   0
+#define LANEND_BIG_2143                 1
+#define LANEND_BIG_4321                 2
+
+#define LANMB_ANY                       0
+#define LANMB_8                         1
+#define LANMB_32                        2
+#define LANMB_64                        3
+
+#define MACCM_AUTOMATIC                 0
+#define MACCM_10MB                      1
+#define MACCM_MII                       2
+
+/* 
+ * PHY definitions for Basic registers of QS6612 (used on MIPS ATLAS board) 
+ */
+#define PHY_CONTROL                     0x0
+#define PHY_STATUS                      0x1
+#define PHY_STATUS_LINK_UP              0x4
+#define PHY_CONTROL_RESET               0x8000
+#define PHY_CONTROL_AUTO_NEG            0x1000
+#define PHY_CONTROL_RESTART_AUTO_NEG    0x0200
+#define PHY_ADDRESS                     0x0
+
+/* PK_COUNT register. */
+#define PK_COUNT_TX_A_SHF               24
+#define PK_COUNT_TX_A_MSK               (0xff << PK_COUNT_TX_A_SHF)
+#define PK_COUNT_TX_B_SHF               16
+#define PK_COUNT_TX_B_MSK               (0xff << PK_COUNT_TX_B_SHF)
+#define PK_COUNT_RX_A_SHF               8
+#define PK_COUNT_RX_A_MSK               (0xff << PK_COUNT_RX_A_SHF)
+#define PK_COUNT_RX_B_SHF               0
+#define PK_COUNT_RX_B_MSK               (0xff << PK_COUNT_RX_B_SHF)
+
+/* OK2USE register. */
+#define OK2USE_TX_A                     0x8
+#define OK2USE_TX_B                     0x4
+#define OK2USE_RX_A                     0x2
+#define OK2USE_RX_B                     0x1
+
+/* LAN DMA CONTROL register. */
+#define DMA_CTL_BLK_INT                 0x80000000
+#define DMA_CTL_MAX_XFER_SHF            18
+#define DMA_CTL_MAX_XFER_MSK            (0x3 << LAN_DMA_CTL_MAX_XFER_SHF)
+#define DMA_CTL_ENDIAN_SHF              16
+#define DMA_CTL_ENDIAN_MSK              (0x3 << LAN_DMA_CTL_ENDIAN_SHF)
+#define DMA_CTL_RX_INT_COUNT_SHF        8
+#define DMA_CTL_RX_INT_COUNT_MSK        (0xff << LAN_DMA_CTL_RX_INT_COUNT_SHF)
+#define DMA_CTL_EN_TX_DMA               0x00000080
+#define DMA_CTL_EN_RX_DMA               0x00000040
+#define DMA_CTL_RX_INT_BUFFUL_EN        0x00000020
+#define DMA_CTL_RX_INT_TO_EN            0x00000010
+#define DMA_CTL_RX_INT_EN               0x00000008
+#define DMA_CTL_TX_INT_EN               0x00000004
+#define DMA_CTL_MAC_TX_INT_EN           0x00000002
+#define DMA_CTL_MAC_RX_INT_EN           0x00000001
+
+/* DMA STATUS register. */
+#define DMA_STATUS_BAD_ADDR_SHF         16
+#define DMA_STATUS_BAD_ADDR_MSK         (0xf << DMA_STATUS_BAD_ADDR_SHF)
+#define DMA_STATUS_RX_PKTS_RECEIVED_SHF 8
+#define DMA_STATUS_RX_PKTS_RECEIVED_MSK (0xff << DMA_STATUS_RX_PKTS_RECEIVED_SHF)
+#define DMA_STATUS_TX_EN_SYNC           0x00000080
+#define DMA_STATUS_RX_BUF_A_FUL         0x00000040
+#define DMA_STATUS_RX_BUF_B_FUL         0x00000020
+#define DMA_STATUS_RX_TO_INT            0x00000010
+#define DMA_STATUS_RX_INT               0x00000008
+#define DMA_STATUS_TX_INT               0x00000004
+#define DMA_STATUS_MAC_TX_INT           0x00000002
+#define DMA_STATUS_MAC_RX_INT           0x00000001
+
+/* DMA TEST/PANIC SWITHES register. */
+#define DMA_TEST_LOOPBACK               0x01000000
+#define DMA_TEST_SW_RESET               0x00000001
+
+/* MAC CONTROL register. */
+#define MAC_CONTROL_EN_MISS_ROLL        0x00002000
+#define MAC_CONTROL_MISS_ROLL           0x00000400
+#define MAC_CONTROL_LOOP10              0x00000080
+#define MAC_CONTROL_CONN_SHF            5
+#define MAC_CONTROL_CONN_MSK            (0x3 << MAC_CONTROL_CONN_SHF)
+#define MAC_CONTROL_MAC_LOOP            0x00000010
+#define MAC_CONTROL_FULL_DUP            0x00000008
+#define MAC_CONTROL_RESET               0x00000004
+#define MAC_CONTROL_HALT_IMM            0x00000002
+#define MAC_CONTROL_HALT_REQ            0x00000001
+
+/* CAM CONTROL register. */
+#define CAM_CONTROL_COMP_EN             0x00000010
+#define CAM_CONTROL_NEG_CAM             0x00000008
+#define CAM_CONTROL_BROAD_ACC           0x00000004
+#define CAM_CONTROL_GROUP_ACC           0x00000002
+#define CAM_CONTROL_STATION_ACC         0x00000001
+
+/* TRANSMIT CONTROL register. */
+#define TX_CTL_EN_COMP                  0x00004000
+#define TX_CTL_EN_TX_PAR                0x00002000
+#define TX_CTL_EN_LATE_COLL             0x00001000
+#define TX_CTL_EN_EX_COLL               0x00000800
+#define TX_CTL_EN_L_CARR                0x00000400
+#define TX_CTL_EN_EX_DEFER              0x00000200
+#define TX_CTL_EN_UNDER                 0x00000100
+#define TX_CTL_MII10                    0x00000080
+#define TX_CTL_SD_PAUSE                 0x00000040
+#define TX_CTL_NO_EX_DEF0               0x00000020
+#define TX_CTL_F_BACK                   0x00000010
+#define TX_CTL_NO_CRC                   0x00000008
+#define TX_CTL_NO_PAD                   0x00000004
+#define TX_CTL_TX_HALT                  0x00000002
+#define TX_CTL_TX_EN                    0x00000001
+
+/* TRANSMIT STATUS register. */
+#define TX_STATUS_SQ_ERR                0x00010000
+#define TX_STATUS_TX_HALTED             0x00008000
+#define TX_STATUS_COMP                  0x00004000
+#define TX_STATUS_TX_PAR                0x00002000
+#define TX_STATUS_LATE_COLL             0x00001000
+#define TX_STATUS_TX10_STAT             0x00000800
+#define TX_STATUS_L_CARR                0x00000400
+#define TX_STATUS_EX_DEFER              0x00000200
+#define TX_STATUS_UNDER                 0x00000100
+#define TX_STATUS_IN_TX                 0x00000080
+#define TX_STATUS_PAUSED                0x00000040
+#define TX_STATUS_TX_DEFERRED           0x00000020
+#define TX_STATUS_EX_COLL               0x00000010
+#define TX_STATUS_TX_COLL_SHF           0
+#define TX_STATUS_TX_COLL_MSK           (0xf << TX_STATUS_TX_COLL_SHF)
+
+/* RECEIVE CONTROL register. */
+#define RX_CTL_EN_GOOD                  0x00004000
+#define RX_CTL_EN_RX_PAR                0x00002000
+#define RX_CTL_EN_LONG_ERR              0x00000800
+#define RX_CTL_EN_OVER                  0x00000400
+#define RX_CTL_EN_CRC_ERR               0x00000200
+#define RX_CTL_EN_ALIGN                 0x00000100
+#define RX_CTL_IGNORE_CRC               0x00000040
+#define RX_CTL_PASS_CTL                 0x00000020
+#define RX_CTL_STRIP_CRC                0x00000010
+#define RX_CTL_SHORT_EN                 0x00000008
+#define RX_CTL_LONG_EN                  0x00000004
+#define RX_CTL_RX_HALT                  0x00000002
+#define RX_CTL_RX_EN                    0x00000001
+
+/* RECEIVE STATUS register. */
+#define RX_STATUS_RX_HALTED             0x00008000
+#define RX_STATUS_GOOD                  0x00004000
+#define RX_STATUS_RX_PAR                0x00002000
+#define RX_STATUS_LONG_ERR              0x00000800
+#define RX_STATUS_OVERFLOW              0x00000400
+#define RX_STATUS_CRC_ERR               0x00000200
+#define RX_STATUS_ALIGN_ERR             0x00000100
+#define RX_STATUS_RX10_STAT             0x00000080
+#define RX_STATUS_INT_RX                0x00000040
+#define RX_STATUS_CTL_RECD              0x00000020
+
+/* MD_CA register. */
+#define MD_CA_PRE_SUP                   0x00001000
+#define MD_CA_BUSY                      0x00000800
+#define MD_CA_WR                        0x00000400
+#define MD_CA_PHY_SHF                   5
+#define MD_CA_PHY_MSK                   (0x1f << MD_CA_PHY_SHF)
+#define MD_CA_ADDR_SHF                  0
+#define MD_CA_ADDR_MSK                  (0x1f << MD_CA_ADDR_SHF)
+
+/* Tx Status/Control. */
+#define TX_STAT_CTL_OWNER_SHF           30
+#define TX_STAT_CTL_OWNER_MSK           (0x3 << TX_STAT_CTL_OWNER_SHF)
+#define TX_STAT_CTL_FRAME_SHF           27
+#define TX_STAT_CTL_FRAME_MSK           (0x7 << TX_STAT_CTL_FRAME_SHF)
+#define TX_STAT_CTL_STATUS_SHF          11
+#define TX_STAT_CTL_STATUS_MSK          (0x1ffff << TX_STAT_CTL_STATUS_SHF)
+#define TX_STAT_CTL_LENGTH_SHF          0
+#define TX_STAT_CTL_LENGTH_MSK          (0x7ff << TX_STAT_CTL_LENGTH_SHF)
+
+#define TX_STAT_CTL_ERROR_MSK           ((TX_STATUS_SQ_ERR      |     \
+					  TX_STATUS_TX_HALTED   |     \
+					  TX_STATUS_TX_PAR      |     \
+					  TX_STATUS_LATE_COLL   |     \
+					  TX_STATUS_L_CARR      |     \
+					  TX_STATUS_EX_DEFER    |     \
+					  TX_STATUS_UNDER       |     \
+					  TX_STATUS_PAUSED      |     \
+					  TX_STATUS_TX_DEFERRED |     \
+					  TX_STATUS_EX_COLL     |     \
+					  TX_STATUS_TX_COLL_MSK)      \
+                                                    << TX_STAT_CTL_STATUS_SHF)
+#define TX_STAT_CTL_INT_AFTER_TX        0x4
+
+/* Rx Status/Control. */
+#define RX_STAT_CTL_OWNER_SHF           30
+#define RX_STAT_CTL_OWNER_MSK           (0x3 << RX_STAT_CTL_OWNER_SHF)
+#define RX_STAT_CTL_STATUS_SHF          11
+#define RX_STAT_CTL_STATUS_MSK          (0xffff << RX_STAT_CTL_STATUS_SHF)
+#define RX_STAT_CTL_LENGTH_SHF          0
+#define RX_STAT_CTL_LENGTH_MSK          (0x7ff << RX_STAT_CTL_LENGTH_SHF)
+
+
+
+/* The SAA9730 (LAN) controller register map, as seen via the PCI-bus. */
+#define SAA9730_LAN_REGS_ADDR   0x20400
+
+struct lan_saa9730_regmap {
+	volatile unsigned int TxBuffA;			/* 0x20400 */
+	volatile unsigned int TxBuffB;			/* 0x20404 */
+	volatile unsigned int RxBuffA;			/* 0x20408 */
+	volatile unsigned int RxBuffB;			/* 0x2040c */
+	volatile unsigned int PacketCount;		/* 0x20410 */
+	volatile unsigned int Ok2Use;			/* 0x20414 */
+	volatile unsigned int LanDmaCtl;		/* 0x20418 */
+	volatile unsigned int Timeout;			/* 0x2041c */
+	volatile unsigned int DmaStatus;		/* 0x20420 */
+	volatile unsigned int DmaTest;			/* 0x20424 */
+	volatile unsigned char filler20428[0x20430 - 0x20428];
+	volatile unsigned int PauseCount;		/* 0x20430 */
+	volatile unsigned int RemotePauseCount;		/* 0x20434 */
+	volatile unsigned char filler20438[0x20440 - 0x20438];
+	volatile unsigned int MacCtl;			/* 0x20440 */
+	volatile unsigned int CamCtl;			/* 0x20444 */
+	volatile unsigned int TxCtl;			/* 0x20448 */
+	volatile unsigned int TxStatus;			/* 0x2044c */
+	volatile unsigned int RxCtl;			/* 0x20450 */
+	volatile unsigned int RxStatus;			/* 0x20454 */
+	volatile unsigned int StationMgmtData;		/* 0x20458 */
+	volatile unsigned int StationMgmtCtl;		/* 0x2045c */
+	volatile unsigned int CamAddress;		/* 0x20460 */
+	volatile unsigned int CamData;			/* 0x20464 */
+	volatile unsigned int CamEnable;		/* 0x20468 */
+	volatile unsigned char filler2046c[0x20500 - 0x2046c];
+	volatile unsigned int DebugPCIMasterAddr;	/* 0x20500 */
+	volatile unsigned int DebugLanTxStateMachine;	/* 0x20504 */
+	volatile unsigned int DebugLanRxStateMachine;	/* 0x20508 */
+	volatile unsigned int DebugLanTxFifoPointers;	/* 0x2050c */
+	volatile unsigned int DebugLanRxFifoPointers;	/* 0x20510 */
+	volatile unsigned int DebugLanCtlStateMachine;	/* 0x20514 */
+};
+typedef volatile struct lan_saa9730_regmap t_lan_saa9730_regmap;
+
+
+/* EVM interrupt control registers. */
+#define EVM_LAN_INT                     0x00010000
+#define EVM_MASTER_EN                   0x00000001
+
+/* The SAA9730 (EVM) controller register map, as seen via the PCI-bus. */
+#define SAA9730_EVM_REGS_ADDR   0x02000
+
+struct evm_saa9730_regmap {
+	volatile unsigned int InterruptStatus1;		/* 0x2000 */
+	volatile unsigned int InterruptEnable1;		/* 0x2004 */
+	volatile unsigned int InterruptMonitor1;	/* 0x2008 */
+	volatile unsigned int Counter;			/* 0x200c */
+	volatile unsigned int CounterThreshold;		/* 0x2010 */
+	volatile unsigned int CounterControl;		/* 0x2014 */
+	volatile unsigned int GpioControl1;		/* 0x2018 */
+	volatile unsigned int InterruptStatus2;		/* 0x201c */
+	volatile unsigned int InterruptEnable2;		/* 0x2020 */
+	volatile unsigned int InterruptMonitor2;	/* 0x2024 */
+	volatile unsigned int GpioControl2;		/* 0x2028 */
+	volatile unsigned int InterruptBlock1;		/* 0x202c */
+	volatile unsigned int InterruptBlock2;		/* 0x2030 */
+};
+typedef volatile struct evm_saa9730_regmap t_evm_saa9730_regmap;
+
+
+struct lan_saa9730_private {
+	/* Pointer for the SAA9730 LAN controller register set. */
+	t_lan_saa9730_regmap *lan_saa9730_regs;
+
+	/* Pointer to the SAA9730 EVM register. */
+	t_evm_saa9730_regmap *evm_saa9730_regs;
+
+	/* TRUE if the next buffer to write is RxBuffA,  FALSE if RxBuffB. */
+	unsigned char NextRcvToUseIsA;
+	/* Rcv buffer Index. */
+	unsigned char NextRcvPacketIndex;
+
+	/* Index of next packet to use in that buffer. */
+	unsigned char NextTxmPacketIndex;
+	/* Next buffer index. */
+	unsigned char NextTxmBufferIndex;
+
+	/* Index of first pending packet ready to send. */
+	unsigned char PendingTxmPacketIndex;
+	/* Pending buffer index. */
+	unsigned char PendingTxmBufferIndex;
+
+	unsigned char DmaRcvPackets;
+	unsigned char DmaTxmPackets;
+
+	unsigned char RcvAIndex;	/* index into RcvBufferSpace[] for Blk A */
+	unsigned char RcvBIndex;	/* index into RcvBufferSpace[] for Blk B */
+
+	unsigned int
+	    TxmBuffer[LAN_SAA9730_BUFFERS][LAN_SAA9730_TXM_Q_SIZE];
+	unsigned int
+	    RcvBuffer[LAN_SAA9730_BUFFERS][LAN_SAA9730_RCV_Q_SIZE];
+	unsigned int TxBufferFree[LAN_SAA9730_BUFFERS];
+
+	unsigned char PhysicalAddress[LAN_SAA9730_CAM_ENTRIES][6];
+
+	struct net_device_stats stats;
+};
+
+#endif /* _SAA9730_H */
diff -urN linux-2.4.4-pre3/drivers/net/tokenring/smctr.c linux/drivers/net/tokenring/smctr.c
--- linux-2.4.4-pre3/drivers/net/tokenring/smctr.c	Tue Mar 20 12:05:00 2001
+++ linux/drivers/net/tokenring/smctr.c	Mon Dec  3 22:35:22 2001
@@ -5269,7 +5269,7 @@
         return (POSITIVE_ACK);
 }
 
-/* Reset the ring speed to the oposite of what it was. This auto-pilot
+/* Reset the ring speed to the opposite of what it was. This auto-pilot
  * mode requires a complete reset and re-init of the adapter.
  */
 static int smctr_set_ring_speed(struct net_device *dev)
diff -urN linux-2.4.4-pre3/drivers/pci/Makefile linux/drivers/pci/Makefile
--- linux-2.4.4-pre3/drivers/pci/Makefile	Fri Dec 29 14:07:22 2000
+++ linux/drivers/pci/Makefile	Mon Dec  3 22:35:22 2001
@@ -21,6 +21,7 @@
 #
 obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
 obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
+obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
 
 ifndef CONFIG_X86
 obj-y += syscall.o
diff -urN linux-2.4.4-pre3/drivers/scsi/53c7xx.c linux/drivers/scsi/53c7xx.c
--- linux-2.4.4-pre3/drivers/scsi/53c7xx.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/scsi/53c7xx.c	Mon Dec  3 22:35:22 2001
@@ -198,7 +198,7 @@
  * Architecture : 
  * This driver is built around a Linux queue of commands waiting to 
  * be executed, and a shared Linux/NCR array of commands to start.  Commands
- * are transfered to the array  by the run_process_issue_queue() function 
+ * are transferred to the array  by the run_process_issue_queue() function 
  * which is called whenever a command completes.
  *
  * As commands are completed, the interrupt routine is triggered,
@@ -1077,19 +1077,18 @@
     {
 	printk("scsi%d : IRQ%d not free, detaching\n",
 		host->host_no, host->irq);
-	scsi_unregister (host);
-	return -1;
+	goto err_unregister;
     } 
 
     if ((hostdata->run_tests && hostdata->run_tests(host) == -1) ||
         (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) {
     	/* XXX Should disable interrupts, etc. here */
-	scsi_unregister (host);
-    	return -1;
+	goto err_free_irq;
     } else {
 	if (host->io_port)  {
 	    host->n_io_port = 128;
-	    request_region (host->io_port, host->n_io_port, "ncr53c7xx");
+	    if (!request_region (host->io_port, host->n_io_port, "ncr53c7xx"))
+		goto err_free_irq;
 	}
     }
     
@@ -1098,6 +1097,12 @@
 	hard_reset (host);
     }
     return 0;
+
+ err_free_irq:
+    free_irq(host->irq,  NCR53c7x0_intr);
+ err_unregister:
+    scsi_unregister(host);
+    return -1;
 }
 
 /* 
@@ -1206,8 +1211,11 @@
     size += 256;
 #endif
     /* Size should be < 8K, so we can fit it in two pages. */
-    if (size > 8192)
-      panic("53c7xx: hostdata > 8K");
+    if (size > 8192) {
+      printk(KERN_ERR "53c7xx: hostdata > 8K\n");
+      return -1;
+    }
+
     instance = scsi_register (tpnt, 4);
     if (!instance)
     {
@@ -3091,8 +3099,10 @@
 #endif
 /* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */
 
-        if (size > 4096)
-            panic ("53c7xx: allocate_cmd size > 4K");
+        if (size > 4096) {
+            printk (KERN_ERR "53c7xx: allocate_cmd size > 4K\n");
+	    return NULL;
+	}
         real = get_free_page(GFP_ATOMIC);
         if (real == 0)
         	return NULL;
@@ -3272,7 +3282,7 @@
 
     /*
      * The saved data pointer is set up so that a RESTORE POINTERS message 
-     * will start the data transfer over at the begining.
+     * will start the data transfer over at the beginning.
      */
 
     tmp->saved_data_pointer = virt_to_bus (hostdata->script) + 
@@ -4965,7 +4975,7 @@
      * chances of this happening, and handle it if it occurs anyway.
      *
      * Simply continue with what we were doing, and control should
-     * be transfered to the schedule routine which will ultimately
+     * be transferred to the schedule routine which will ultimately
      * pass control onto the reselection or selection (not yet)
      * code.
      */
diff -urN linux-2.4.4-pre3/drivers/scsi/53c7xx.scr linux/drivers/scsi/53c7xx.scr
--- linux-2.4.4-pre3/drivers/scsi/53c7xx.scr	Sat Mar 21 11:09:47 1998
+++ linux/drivers/scsi/53c7xx.scr	Mon Dec  3 22:35:22 2001
@@ -1136,7 +1136,7 @@
 #if (CHIP == 710)
 #if defined(MVME16x_INTFLY)
 ; For MVME16x (ie CHIP=710) we will force an INTFLY by triggering a software
-; interupt (SW7).  We can use SCRATCH, as we are about to jump to
+; interrupt (SW7).  We can use SCRATCH, as we are about to jump to
 ; schedule, which corrupts it anyway.  Will probably remove this later,
 ; but want to check performance effects first.
 
diff -urN linux-2.4.4-pre3/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- linux-2.4.4-pre3/drivers/scsi/megaraid.c	Mon Dec  3 22:35:12 2001
+++ linux/drivers/scsi/megaraid.c	Mon Dec  3 22:35:23 2001
@@ -75,7 +75,7 @@
  *     Changed megaraid_command to use wait_queue.
  *
  * Version 1.00:
- *     Checks to see if an irq ocurred while in isr, and runs through
+ *     Checks to see if an irq occurred while in isr, and runs through
  *       routine again.
  *     Copies mailbox to temp area before processing in isr
  *     Added barrier() in busy wait to fix volatility bug
@@ -293,6 +293,9 @@
  *	Left 2.0 support but removed 2.1.x support.
  *	Collected much of the compat glue into one spot
  *
+ *	Version 1.14g-ac2 - 22/03/01
+ *	Fixed a non obvious dereference after free in the driver unload path
+ *
  * BUGS:
  *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
  *     fails to detect the controller as a pci device on the system.
@@ -392,17 +395,19 @@
 }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)	/* 0x020200 */
+#include <linux/smp.h>
+#define cpuid smp_processor_id()
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	/* 0x020100 */
 
 /*
- *	Linux 2.2 and higher
+ *	Linux 2.4 and higher
  *
  *	No driver private lock
  *	Use the io_request_lock not cli/sti
  *	queue task is a simple api without irq forms
  */
- 
-#include <linux/smp.h>
-#define cpuid smp_processor_id()
 
 MODULE_AUTHOR ("American Megatrends Inc.");
 MODULE_DESCRIPTION ("AMI MegaRAID driver");
@@ -415,18 +420,42 @@
 #define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
 #define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)	/* 0x020400 */
+#define queue_task_irq(a,b)     queue_task(a,b)
+#define queue_task_irq_off(a,b) queue_task(a,b)
+
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)	/* 0x020200 */
+
+/*
+ *	Linux 2.2 and higher
+ *
+ *	No driver private lock
+ *	Use the io_request_lock not cli/sti
+ *	No pci region api
+ *	queue_task is now a single simple API
+ */
+
+static char kernel_version[] = UTS_RELEASE;
+MODULE_AUTHOR ("American Megatrends Inc.");
+MODULE_DESCRIPTION ("AMI MegaRAID driver");
+
+#define DRIVER_LOCK_T
+#define DRIVER_LOCK_INIT(p)
+#define DRIVER_LOCK(p)
+#define DRIVER_UNLOCK(p)
+#define IO_LOCK_T unsigned long io_flags = 0;
+#define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
+#define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
+
 #define pci_free_consistent(a,b,c,d)
 #define pci_unmap_single(a,b,c,d,e)
 
 #define init_MUTEX_LOCKED(x)	((x)=MUTEX_LOCKED)
 #define init_MUTEX(x)		((x)=MUTEX)
 
-#define DECLARE_WAIT_QUEUE_HEAD(x)	struct wait_queue *x = NULL
-#endif
-
 #define queue_task_irq(a,b)     queue_task(a,b)
 #define queue_task_irq_off(a,b) queue_task(a,b)
+
+#define DECLARE_WAIT_QUEUE_HEAD(x)	struct wait_queue *x = NULL
 #else
 
 /*
@@ -2738,7 +2767,6 @@
 			     sizeof (mega_mailbox64),
 			     (void *) megaCfg->mailbox64ptr,
 			     megaCfg->dma_handle64);
-	scsi_unregister (pSHost);
 
 #ifdef CONFIG_PROC_FS
 	if (megaCfg->controller_proc_dir_entry) {
@@ -2759,12 +2787,21 @@
 #endif
 
 	/*
+	 *	Release the controller memory. A word of warning this frees
+	 *	hostdata and that includes megaCfg-> so be careful what you
+	 *	dereference beyond this point
+	 */
+	 
+	scsi_unregister (pSHost);
+
+	/*
 	 * Unregister the character device interface to the driver. Ideally this
 	 * should have been done in cleanup_module routine. Since this is hidden
 	 * in file "scsi_module.c", we do it here.
 	 * major is the major number of the character device returned by call to
 	 * register_chrdev() routine.
 	 */
+
 	unregister_chrdev (major, "megadev");
 	unregister_reboot_notifier (&mega_notifier);
 
@@ -4274,8 +4311,9 @@
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 static
-#endif
+#endif				/* LINUX VERSION 2.4.XX */
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) || defined(MODULE)
 Scsi_Host_Template driver_template = MEGARAID;
+
 #include "scsi_module.c"
-#endif
+#endif				/* LINUX VERSION 2.4.XX || MODULE */
diff -urN linux-2.4.4-pre3/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h
--- linux-2.4.4-pre3/drivers/scsi/megaraid.h	Tue Mar  6 19:44:37 2001
+++ linux/drivers/scsi/megaraid.h	Mon Dec  3 22:35:23 2001
@@ -27,7 +27,7 @@
 #define M_RD_IOCTL_CMD_NEW		0x81
 #define M_RD_DRIVER_IOCTL_INTERFACE	0x82
 
-#define MEGARAID_VERSION "v1.14g (Release Date: Feb 5, 2001; 11:42)"
+#define MEGARAID_VERSION "v1.14g-ac2 (Release Date: Mar 22, 2001; 19:34:02)"
 #define MEGARAID_IOCTL_VERSION 	114
 
 /* Methods */
diff -urN linux-2.4.4-pre3/drivers/scsi/qlogicfc.c linux/drivers/scsi/qlogicfc.c
--- linux-2.4.4-pre3/drivers/scsi/qlogicfc.c	Mon Dec  3 22:35:12 2001
+++ linux/drivers/scsi/qlogicfc.c	Mon Dec  3 22:35:23 2001
@@ -195,8 +195,8 @@
 #define FLASH_BIOS_ADDR	0x00
 #define FLASH_BIOS_DATA	0x02
 #define ISP_CTRL_STATUS	0x06	/* configuration register #1 */
-#define PCI_INTER_CTL	0x08	/* pci interupt control */
-#define PCI_INTER_STS	0x0a	/* pci interupt status */
+#define PCI_INTER_CTL	0x08	/* pci interrupt control */
+#define PCI_INTER_STS	0x0a	/* pci interrupt status */
 #define PCI_SEMAPHORE	0x0c	/* pci semaphore */
 #define PCI_NVRAM	0x0e	/* pci nvram interface */
 
@@ -227,7 +227,7 @@
 #define REQUEST_TRANSFER_ERROR		0x8003
 #define RESPONSE_TRANSFER_ERROR		0x8004
 #define REQUEST_QUEUE_WAKEUP		0x8005
-#define LIP_OCCURED                     0x8010
+#define LIP_OCCURRED                     0x8010
 #define LOOP_UP                         0x8011
 #define LOOP_DOWN                       0x8012
 #define LIP_RECEIVED                    0x8013
@@ -369,7 +369,7 @@
 #define STF_ABORTED			0x0020
 #define STF_TIMEOUT			0x0040
 
-/* interupt control commands */
+/* interrupt control commands */
 #define ISP_EN_INT			0x8000
 #define ISP_EN_RISC			0x0008
 
@@ -757,6 +757,10 @@
 				continue;
 
 		        host = scsi_register(tmpt, sizeof(struct isp2x00_hostdata));
+			if (!host) {
+			        printk("qlogicfc%d : could not register host.\n", hostdata->host_id);
+				continue;
+			}
 			host->max_id = QLOGICFC_MAX_ID + 1;
 			host->max_lun = QLOGICFC_MAX_LUN;
 			host->hostt->use_new_eh_code = 1;
@@ -768,6 +772,7 @@
 
 			if (!hostdata->res){
 			        printk("qlogicfc%d : could not allocate memory for request and response queue.\n", hostdata->host_id);
+				pci64_free_consistent(pdev, RES_SIZE + REQ_SIZE, hostdata->res, busaddr);
 			        scsi_unregister(host);
 				continue;
 			}
@@ -813,7 +818,7 @@
 				scsi_unregister(host);
 				continue;
 			}
-			if (check_region(host->io_port, 0xff)) {
+			if (!request_region(host->io_port, 0xff, "qlogicfc")) {
 			        printk("qlogicfc%d : i/o region 0x%lx-0x%lx already "
 				       "in use\n",
 				       hostdata->host_id, host->io_port, host->io_port + 0xff);
@@ -822,7 +827,6 @@
 				scsi_unregister(host);
 				continue;
 			}
-			request_region(host->io_port, 0xff, "qlogicfc");
 
 			outw(0x0, host->io_port + PCI_SEMAPHORE);
 			outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR);
@@ -1520,7 +1524,7 @@
 			if (hostdata->adapter_state == AS_LOOP_GOOD)
 				hostdata->adapter_state = AS_REDO_FABRIC_PORTDB;
 			break;		        
-		case LIP_OCCURED:
+		case LIP_OCCURRED:
 		case LIP_RECEIVED:
 		        printk("qlogicfc%d : Loop Reinitialized\n", hostdata->host_id);
 			if (hostdata->adapter_state == AS_LOOP_GOOD)
diff -urN linux-2.4.4-pre3/drivers/sgi/Makefile linux/drivers/sgi/Makefile
--- linux-2.4.4-pre3/drivers/sgi/Makefile	Sun Aug  6 11:23:40 2000
+++ linux/drivers/sgi/Makefile	Mon Dec  3 22:35:23 2001
@@ -7,17 +7,13 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-SUB_DIRS     :=
-MOD_SUB_DIRS := $(SUB_DIRS) char
-ALL_SUB_DIRS := $(SUB_DIRS) char
-
-
-L_OBJS   := 
 L_TARGET := sgi.a
 
+#
 # Character and Audio devices for SGI machines.
 #
-SUB_DIRS += char
-L_OBJS += char/sgichar.o
+subdir-y	+= char
+subdir-m	+= char
+obj-y		+= char/sgichar.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/drivers/sgi/char/Makefile linux/drivers/sgi/char/Makefile
--- linux-2.4.4-pre3/drivers/sgi/char/Makefile	Fri Jun 25 17:39:34 1999
+++ linux/drivers/sgi/char/Makefile	Mon Dec  3 22:35:23 2001
@@ -8,25 +8,12 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 O_TARGET := sgichar.o
-OX_OBJS := newport.o
-O_OBJS   := sgicons.o \
-	usema.o shmiq.o streamable.o
 
-ifeq ($(CONFIG_SGI_SERIAL),y)
-  O_OBJS += sgiserial.o
-endif
+export-objs	:= newport.o shmiq.o sgicons.o usema.o
+obj-y		:= newport.o shmiq.o sgicons.o usema.o streamable.o
 
-ifeq ($(CONFIG_SGI_DS1286),y)
-  O_OBJS += ds1286.o
-endif
-
-ifeq ($(CONFIG_SGI_NEWPORT_GFX),y)
-  O_OBJS +=  graphics.o rrm.o
-else 
-ifeq ($(CONFIG_SGI_NEWPORT_GFX),m)
-  OX_OBJS  +=  graphics_syms.o
-  MX_OBJS +=  graphics.o rrm.o
-endif
-endif
+obj-$(CONFIG_SGI_SERIAL)	+= sgiserial.o
+obj-$(CONFIG_SGI_DS1286)	+= ds1286.o
+obj-$(CONFIG_SGI_NEWPORT_GFX)	+= graphics.o rrm.o
 
 include $(TOPDIR)/Rules.make
diff -urN linux-2.4.4-pre3/drivers/sound/Config.in linux/drivers/sound/Config.in
--- linux-2.4.4-pre3/drivers/sound/Config.in	Tue Mar  6 19:28:32 2001
+++ linux/drivers/sound/Config.in	Mon Dec  3 22:35:23 2001
@@ -93,7 +93,7 @@
    fi
    dep_tristate '    Aztech Sound Galaxy (non-PnP) cards' CONFIG_SOUND_SGALAXY $CONFIG_SOUND_OSS
    dep_tristate '    Adlib Cards' CONFIG_SOUND_ADLIB $CONFIG_SOUND_OSS
-   dep_tristate '    ACI mixer (miroPCM12)' CONFIG_SOUND_ACI_MIXER $CONFIG_SOUND_OSS
+   dep_tristate '    ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20)' CONFIG_SOUND_ACI_MIXER $CONFIG_SOUND_OSS
    dep_tristate '    Crystal CS4232 based (PnP) cards' CONFIG_SOUND_CS4232 $CONFIG_SOUND_OSS
    dep_tristate '    Ensoniq SoundScape support' CONFIG_SOUND_SSCAPE $CONFIG_SOUND_OSS
    dep_tristate '    Gravis Ultrasound support' CONFIG_SOUND_GUS $CONFIG_SOUND_OSS
@@ -171,8 +171,10 @@
    fi
 	 
    if [ "$CONFIG_ARM" = "y" ]; then
-      dep_tristate '    VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
-      dep_tristate '    Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS
+      if [ "$CONFIG_ARCH_ACORN" = "y" -o "$CONFIG_ARCH_CLPS7500" = "y" ]; then
+         dep_tristate '    VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
+      fi
+      dep_tristate '    Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS $CONFIG_ARCH_NETWINDER
    fi
 
 fi
diff -urN linux-2.4.4-pre3/drivers/sound/Makefile linux/drivers/sound/Makefile
--- linux-2.4.4-pre3/drivers/sound/Makefile	Sun Feb  4 10:05:29 2001
+++ linux/drivers/sound/Makefile	Mon Dec  3 22:35:23 2001
@@ -10,7 +10,7 @@
 export-objs	:=  ad1848.o audio_syms.o midi_syms.o mpu401.o \
 		    msnd.o opl3.o sb_common.o sequencer_syms.o \
 		    sound_core.o sound_syms.o uart401.o	\
-		    nm256_audio.o ac97.o ac97_codec.o
+		    nm256_audio.o ac97.o ac97_codec.o aci.o
 
 # Each configuration option enables a list of files.
 
@@ -29,7 +29,7 @@
 obj-$(CONFIG_SOUND_CS4232)	+= cs4232.o uart401.o
 obj-$(CONFIG_SOUND_OPL3SA2)	+= opl3sa2.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_MSS)		+= ad1848.o
-obj-$(CONFIG_SOUND_PAS)		+= pas2.o sb_lib.o uart401.o
+obj-$(CONFIG_SOUND_PAS)		+= pas2.o sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_SB)		+= sb.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_WAVEFRONT)	+= wavefront.o
 obj-$(CONFIG_SOUND_MAUI)	+= maui.o mpu401.o
diff -urN linux-2.4.4-pre3/drivers/sound/aci.c linux/drivers/sound/aci.c
--- linux-2.4.4-pre3/drivers/sound/aci.c	Fri Feb 16 16:02:36 2001
+++ linux/drivers/sound/aci.c	Mon Dec  3 22:35:23 2001
@@ -10,15 +10,17 @@
  * The main function of the ACI is to control the mixer and to get a
  * product identification. On the PCM20, ACI also controls the radio
  * tuner on this card, this is supported in the Video for Linux 
- * radio-miropcm20 driver.
- * 
- * This Voxware ACI driver currently only supports the ACI functions
- * on the miroSOUND PCM12 and PCM20 card. Support for miro sound cards 
- * with additional ACI functions can easily be added later.
- *
- * / NOTE / When compiling as a module, make sure to load the module 
- * after loading the mad16 module. The initialisation code expects the
- * MAD16 default mixer to be already available.
+ * miropcm20 driver.
+ * -
+ * This is a fullfeatured implementation. Unsupported features
+ * are bugs... (:
+ *
+ * It is not longer necessary to load the mad16 module first. The
+ * user is currently responsible to set the mad16 mixer correctly.
+ *
+ * To toggle the solo mode for full duplex operation just use the OSS
+ * record switch for the pcm ('wave') controller.           Robert
+ * -
  *
  * Revision history:
  *
@@ -34,72 +36,78 @@
  *   1998-08-18  Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
  *	  Small modification to export ACI functions and 
  *	  complete modularisation.
+ *   2000-06-20  Robert Siemer <Robert.Siemer@gmx.de>
+ *        Don't initialize the CS4231A mixer anymore, so the code is
+ *        working again, and other small changes to fit in todays
+ *        kernels.
+ *   2000-08-26  Robert Siemer
+ *        Clean up and rewrite for 2.4.x. Maybe it's SMP safe now... (:
+ *        ioctl bugfix, and integration of solo-mode into OSS-API,
+ *        added (OSS-limited) equalizer support, return value bugfix,
+ *        changed param aci_reset to reset, new params: ide, wss.
  */
 
-/*
- * Some driver specific information and features:
- *
- * This mixer driver identifies itself to applications as "ACI" in
- * mixer_info.id as retrieved by ioctl(fd, SOUND_MIXER_INFO, &mixer_info).
- *
- * Proprietary mixer features that go beyond the standard OSS mixer
- * interface are:
- * 
- * Full duplex solo configuration:
- *
- *   int solo_mode;
- *   ioctl(fd, SOUND_MIXER_PRIVATE1, &solo_mode);
- *
- *   solo_mode = 0: deactivate solo mode (default)
- *   solo_mode > 0: activate solo mode
- *                  With activated solo mode, the PCM input can not any
- *                  longer hear the signals produced by the PCM output.
- *                  Activating solo mode is important in duplex mode in order
- *                  to avoid feedback distortions.
- *   solo_mode < 0: do not change solo mode (just retrieve the status)
- *
- *   When the ioctl() returns 0, solo_mode contains the previous
- *   status (0 = deactivated, 1 = activated). If solo mode is not
- *   implemented on this card, ioctl() returns -1 and sets errno to
- *   EINVAL.
- *
- */
-
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h> 
-
+#include <linux/proc_fs.h>
+#include <linux/slab.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
 #include "sound_config.h"
 
-#undef  DEBUG		/* if defined, produce a verbose report via syslog */
+int aci_port;	/* as determined by bit 4 in the OPTi 929 MC4 register */
+int aci_idcode[2];	/* manufacturer and product ID */
+int aci_version;	/* ACI firmware version	*/
+
+EXPORT_SYMBOL(aci_port);
+EXPORT_SYMBOL(aci_idcode);
+EXPORT_SYMBOL(aci_version);
 
-int aci_port = 0x354;	/* as determined by bit 4 in the OPTi 929 MC4 register */
-unsigned char aci_idcode[2] = {0, 0};	/* manufacturer and product ID */
-unsigned char aci_version = 0;		/* ACI firmware version	*/
-int aci_solo;		/* status bit of the card that can't be		*
+#include "aci.h"
+
+
+static int aci_solo=0;	/* status bit of the card that can't be		*
+			 * checked with ACI versions prior to 0xb0	*/
+static int aci_amp=0;   /* status bit for power-amp/line-out level
+			   but I have no docs about what is what... */
+static int aci_micpreamp=3; /* microphone preamp-level that can't be    *
 			 * checked with ACI versions prior to 0xb0	*/
 
-static int aci_present = 0;
+static int mixer_device;
+static struct semaphore aci_sem;
 
-#ifdef MODULE                  /* Whether the aci mixer is to be reset.    */
-int aci_reset = 0;             /* Default: don't reset if the driver is a  */
-MODULE_PARM(aci_reset,"i");
-#else                          /* module; use "insmod aci.o aci_reset=1" */
-int aci_reset = 1;             /* to override.                             */
+#ifdef MODULE
+static int reset = 0;
+MODULE_PARM(reset,"i");
+MODULE_PARM_DESC(reset,"When set to 1, reset aci mixer.");
+#else
+static int reset = 1;
 #endif
 
+static int ide=-1;
+MODULE_PARM(ide,"i");
+MODULE_PARM_DESC(ide,"1 enable, 0 disable ide-port - untested"
+		 " default: do nothing");
+static int wss=-1;
+MODULE_PARM(wss,"i");
+MODULE_PARM_DESC(wss,"change between ACI/WSS-mixer; use 0 and 1 - untested"
+		 " default: do nothing; for PCM1-pro only");
+
+static void print_bits(unsigned char c)
+{
+	int j;
+	printk(KERN_DEBUG "aci: ");
+
+	for (j=7; j>=0; j--) {
+		printk(KERN_DEBUG "%d", (c >> j) & 0x1);
+	}
 
-#define COMMAND_REGISTER    (aci_port)
-#define STATUS_REGISTER     (aci_port + 1)
-#define BUSY_REGISTER       (aci_port + 2)
+	printk(KERN_DEBUG "\n");
+}
 
 /*
- * Wait until the ACI microcontroller has set the READYFLAG in the
- * Busy/IRQ Source Register to 0. This is required to avoid
- * overrunning the sound card microcontroller. We do a busy wait here,
- * because the microcontroller is not supposed to signal a busy
- * condition for more than a few clock cycles. In case of a time-out,
- * this function returns -1.
- *
  * This busy wait code normally requires less than 15 loops and
  * practically always less than 100 loops on my i486/DX2 66 MHz.
  *
@@ -107,459 +115,476 @@
  * function can take a VERY long time, because the PCM12 does some kind
  * of fade-in effect. For this reason, access to the MUTE function has
  * not been implemented at all.
+ *
+ * - The OSS interface has no mute option. It takes about 3 seconds to
+ * fade-in on my PCM20. busy_wait() handles it great now...     Robert
  */
 
 static int busy_wait(void)
 {
+	#define MINTIME 500
 	long timeout;
+	unsigned char byte;
 
-	for (timeout = 0; timeout < 10000000L; timeout++)
-		if ((inb_p(BUSY_REGISTER) & 1) == 0)
-			return 0;
-
-#ifdef DEBUG
-	printk("ACI: READYFLAG timed out.\n");
-#endif
-
-	return -1;
-}
-
-
-/*
- * Read the GENERAL STATUS register.
- */
-
-static int read_general_status(void)
-{
-	unsigned long flags;
-	int status;
-
-	save_flags(flags);
-	cli();
-	
-	if (busy_wait()) {
-		restore_flags(flags);
-		return -1;
+	for (timeout = 1; timeout <= MINTIME+30; timeout++) {
+		if (((byte=inb(BUSY_REGISTER)) & 1) == 0) {
+			if (timeout >= MINTIME)
+				printk(KERN_DEBUG "aci: Got READYFLAG in round %ld.\n", timeout-MINTIME);
+			return byte;
+		}
+		if (timeout >= MINTIME) {
+			long out=10*HZ;
+			switch (timeout-MINTIME) {
+			case 0 ... 9:
+				out /= 10;
+			case 10 ... 19:
+				out /= 10;
+			case 20 ... 30:
+				out /= 10;
+			default:
+				current->state=TASK_UNINTERRUPTIBLE;
+				schedule_timeout(out);
+				break;
+			}
+		}
 	}
-	
-	status = (unsigned) inb_p(STATUS_REGISTER);
-	restore_flags(flags);
-	return status;
+	printk(KERN_WARNING "aci: busy_wait() time out.\n");
+	return -EBUSY;
 }
 
+/* The four ACI command types are fucked up. [-:
+ * implied is: 1w      - special case for INIT
+ * write   is: 2w1r
+ * read    is: x(1w1r) where x is 1 or 2 (1 CHECK_SIG, 1 CHECK_STER,
+ *                                        1 VERSION, 2 IDCODE)
+ *  the command is only in the first write, rest is protocol overhead
+ *
+ * indexed is technically a write and used for STATUS
+ * and the special case for TUNE is: 3w1r
+ * 
+ * Here the new general sheme: TUNE --> aci_rw_cmd(x,  y,  z)
+ *                indexed and write --> aci_rw_cmd(x,  y, -1)
+ *           implied and read (x=1) --> aci_rw_cmd(x, -1, -1)
+ *
+ * Read (x>=2) is not implemented (only used during initialization).
+ * Use aci_idcode[2] and aci_version...                    Robert
+ */
 
-/*
- * The four ACI command types (implied, write, read and indexed) can
- * be sent to the microcontroller using the following four functions.
- * If a problem occurred, they return -1.
+/* Some notes for error detection: theoretically it is possible.
+ * But it doubles the I/O-traffic from ww(r) to wwwrw(r) in the normal 
+ * case and doesn't seem to be designed for that...        Robert
  */
 
-int aci_implied_cmd(unsigned char opcode)
+static inline int aci_rawwrite(unsigned char byte)
 {
-	unsigned long flags;
-
-#ifdef DEBUG
-	printk("ACI: aci_implied_cmd(0x%02x)\n", opcode);
+	if (busy_wait() >= 0) {
+#if DEBUG
+		printk(KERN_DEBUG "aci_rawwrite(%d)\n", byte);
 #endif
-
-	save_flags(flags);
-	cli();
-  
-  	if (read_general_status() < 0 || busy_wait()) {
-		restore_flags(flags);
-		return -1;
-	}
-	
-	outb_p(opcode, COMMAND_REGISTER);
-
-	restore_flags(flags);
-	return 0;
+		outb(byte, COMMAND_REGISTER);
+		return 0;
+	} else
+		return -EBUSY;
 }
 
-
-int aci_write_cmd(unsigned char opcode, unsigned char parameter)
+static inline int aci_rawread(void)
 {
-	unsigned long flags;
-	int status;
+	unsigned char byte;
 
-#ifdef DEBUG
-	printk("ACI: aci_write_cmd(0x%02x, 0x%02x)\n", opcode, parameter);
+	if (busy_wait() >= 0) {
+		byte=inb(STATUS_REGISTER);
+#if DEBUG
+		printk(KERN_DEBUG "%d = aci_rawread()\n", byte);
 #endif
+		return byte;
+	} else
+		return -EBUSY;
+}
 
-	save_flags(flags);
-	cli();
-	
-	if (read_general_status() < 0 || busy_wait()) {
-		restore_flags(flags);
-		return -1;
-	}
 
-	outb_p(opcode, COMMAND_REGISTER);
-	if (busy_wait()) {
-		restore_flags(flags);
-		return -1;
-	}
+int aci_rw_cmd(int write1, int write2, int write3)
+{
+	int write[] = {write1, write2, write3};
+	int read, i;
 
-	outb_p(parameter, COMMAND_REGISTER);
+	if (down_interruptible(&aci_sem))
+		return -EINTR;
 
-	if ((status = read_general_status()) < 0) {
-		restore_flags(flags);
-		return -1;
+	for (i=0; i<3; i++) {
+		if (write[i]< 0 || write[i] > 255)
+			break;
+		else
+			if (aci_rawwrite(write[i])<0) {
+				up(&aci_sem);
+				return -EBUSY;
+			}
 	}
-
-	/* polarity of the INVALID flag depends on ACI version */
-	if ((aci_version <  0xb0 && (status & 0x40) != 0) ||
-	  (aci_version >= 0xb0 && (status & 0x40) == 0)) {
-	  	restore_flags(flags);
-		printk("ACI: invalid write command 0x%02x, 0x%02x.\n",
-			opcode, parameter);
-		return -1;
+	
+	if ((read=aci_rawread())<0) {
+		up(&aci_sem);
+		return -EBUSY;
 	}
 
-	restore_flags(flags);
-	return 0;
+	up(&aci_sem);
+	return read;
 }
 
-/*
- * This write command send 2 parameters instead of one.
- * Only used in PCM20 radio frequency tuning control
- */
+EXPORT_SYMBOL(aci_rw_cmd);
 
-int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2)
+static int setvolume(caddr_t arg, 
+		     unsigned char left_index, unsigned char right_index)
 {
-	unsigned long flags;
-	int status;
+	int vol, ret, uservol, buf;
 
-#ifdef DEBUG
-	printk("ACI: aci_write_cmd_d(0x%02x, 0x%02x)\n", opcode, parameter, parameter2);
-#endif
-
-	save_flags(flags);
-	cli();
-	
-	if (read_general_status() < 0 || busy_wait()) {
-		restore_flags(flags);
-		return -1;
-	}
+	__get_user(uservol, (int *)arg);
 
-	outb_p(opcode, COMMAND_REGISTER);
-	if (busy_wait()) {
-		restore_flags(flags);
-		return -1;
-	}
+	/* left channel */
+	vol = uservol & 0xff;
+	if (vol > 100)
+		vol = 100;
+	vol = SCALE(100, 0x20, vol);
+	if ((buf=aci_write_cmd(left_index, 0x20 - vol))<0)
+		return buf;
+	ret = SCALE(0x20, 100, vol);
 
-	outb_p(parameter, COMMAND_REGISTER);
-	if (busy_wait()) {
-		restore_flags(flags);
-		return -1;
-	}
-	
-	outb_p(parameter2, COMMAND_REGISTER);
-	
-	if ((status = read_general_status()) < 0) {
-		restore_flags(flags);
-		return -1;
-	}
-	
-	/* polarity of the INVALID flag depends on ACI version */
-	if ((aci_version <  0xb0 && (status & 0x40) != 0) ||
-	  (aci_version >= 0xb0 && (status & 0x40) == 0)) {
-		restore_flags(flags);
-#if 0	/* Frequency tuning works, but the INVALID flag is set ??? */
-		printk("ACI: invalid write (double) command 0x%02x, 0x%02x, 0x%02x.\n",
-			opcode, parameter, parameter2);
-#endif
-		return -1;
-  	}
-	
-	restore_flags(flags);
-	return 0;
-}
 
-int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter)
-{
-	unsigned long flags;
-	int i = 0;
-	
-	save_flags(flags);
-	cli();
+	/* right channel */
+	vol = (uservol >> 8) & 0xff;
+	if (vol > 100)
+		vol = 100;
+	vol = SCALE(100, 0x20, vol);
+	if ((buf=aci_write_cmd(right_index, 0x20 - vol))<0)
+		return buf;
+	ret |= SCALE(0x20, 100, vol) << 8;
  
- 	if (read_general_status() < 0) {
-		restore_flags(flags);
-		return -1;
-	}
-	while (i < length) {
-		if (busy_wait()) {
-			restore_flags(flags);
-			return -1;
-		}
-			
-		outb_p(opcode, COMMAND_REGISTER);
-		if (busy_wait()) {
-			restore_flags(flags);
-			return -1;
-		}
-			
-		parameter[i++] = inb_p(STATUS_REGISTER);
-#ifdef DEBUG
-		if (i == 1)
-			printk("ACI: aci_read_cmd(0x%02x, %d) = 0x%02x\n",
-				opcode, length, parameter[i-1]);
-		else
-			printk("ACI: aci_read_cmd cont.: 0x%02x\n", parameter[i-1]);
-#endif
-	}
+	__put_user(ret, (int *)arg);
 
-	restore_flags(flags);
 	return 0;
 }
 
-
-int aci_indexed_cmd(unsigned char opcode, unsigned char index,
-		       unsigned char *parameter)
+static int getvolume(caddr_t arg,
+		     unsigned char left_index, unsigned char right_index)
 {
-	unsigned long flags;
+	int vol;
+	int buf;
 
-	save_flags(flags);
-	cli();
-  
-	if (read_general_status() < 0 || busy_wait()) {
-	  	restore_flags(flags);
-		return -1;
-	}
-	
-	outb_p(opcode, COMMAND_REGISTER);
-	if (busy_wait()) {
-		restore_flags(flags);
-		return -1;
-	}
-	
-	outb_p(index, COMMAND_REGISTER);
-	if (busy_wait()) {
-		restore_flags(flags);
-		return -1;
-	}
+	/* left channel */
+	if ((buf=aci_indexed_cmd(0xf0, left_index))<0)
+		return buf;
+	vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
 	
-	*parameter = inb_p(STATUS_REGISTER);
-#ifdef DEBUG
-	printk("ACI: aci_indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode, index,
-		*parameter);
-#endif
+	/* right channel */
+	if ((buf=aci_indexed_cmd(0xf0, right_index))<0)
+		return buf;
+	vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
+
+	__put_user(vol, (int *)arg);
 
-	restore_flags(flags);
 	return 0;
 }
 
 
-/*
- * The following macro SCALE can be used to scale one integer volume
- * value into another one using only integer arithmetic. If the input
- * value x is in the range 0 <= x <= xmax, then the result will be in
- * the range 0 <= SCALE(xmax,ymax,x) <= ymax.
- *
- * This macro has for all xmax, ymax > 0 and all 0 <= x <= xmax the
- * following nice properties:
- *
- * - SCALE(xmax,ymax,xmax) = ymax
- * - SCALE(xmax,ymax,0) = 0
- * - SCALE(xmax,ymax,SCALE(ymax,xmax,SCALE(xmax,ymax,x))) = SCALE(xmax,ymax,x)
- *
- * In addition, the rounding error is minimal and nicely distributed.
- * The proofs are left as an exercise to the reader.
+/* The equalizer is somewhat strange on the ACI. From -12dB to +12dB
+ * write:  0xff..down.to..0x80==0x00..up.to..0x7f
  */
 
-#define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
+static inline unsigned int eq_oss2aci(unsigned int vol)
+{
+	int boost=0;
+	unsigned int ret;
+
+	if (vol > 100)
+		vol = 100;
+	if (vol > 50) {
+		vol -= 51;
+		boost=1;
+	}
+	if (boost)
+		ret=SCALE(49, 0x7e, vol)+1;
+	else
+		ret=0xff - SCALE(50, 0x7f, vol);
+	return ret;
+}
+
+static inline unsigned int eq_aci2oss(unsigned int vol)
+{
+	if (vol < 0x80)
+		return SCALE(0x7f, 50, vol) + 50;
+	else
+		return SCALE(0x7f, 50, 0xff-vol);
+}
 
 
-static int getvolume(caddr_t arg,
-		     unsigned char left_index, unsigned char right_index)
+static int setequalizer(caddr_t arg, 
+			unsigned char left_index, unsigned char right_index)
 {
-	int vol;
-	unsigned char buf;
+	int buf;
+	unsigned int vol;
+
+	__get_user(vol, (int *)arg);
 
 	/* left channel */
-	if (aci_indexed_cmd(0xf0, left_index, &buf))
-		return -EIO;
-	vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
-	
+	if ((buf=aci_write_cmd(left_index, eq_oss2aci(vol & 0xff)))<0)
+		return buf;
+
 	/* right channel */
-	if (aci_indexed_cmd(0xf0, right_index, &buf))
-		return -EIO;
-	vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
+	if ((buf=aci_write_cmd(right_index, eq_oss2aci((vol>>8) & 0xff)))<0)
+		return buf;
 
-	return (*(int *) arg = vol);
+	/* the ACI equalizer is more precise */
+	return 0;
 }
 
-
-static int setvolume(caddr_t arg, 
-		     unsigned char left_index, unsigned char right_index)
+static int getequalizer(caddr_t arg,
+			unsigned char left_index, unsigned char right_index)
 {
-	int vol, ret;
+	int buf;
+	unsigned int vol;
 
 	/* left channel */
-	vol = *(int *)arg & 0xff;
-	if (vol > 100)
-		vol = 100;
-	vol = SCALE(100, 0x20, vol);
-	if (aci_write_cmd(left_index, 0x20 - vol))
-		return -EIO;
-	ret = SCALE(0x20, 100, vol);
+	if ((buf=aci_indexed_cmd(0xf0, left_index))<0)
+		return buf;
+	vol = eq_aci2oss(buf);
+	
+	/* right channel */
+	if ((buf=aci_indexed_cmd(0xf0, right_index))<0)
+		return buf;
+	vol |= eq_aci2oss(buf) << 8;
 
+	__put_user(vol, (int *)arg);
 
-	/* right channel */
-	vol = (*(int *)arg >> 8) & 0xff;
-	if (vol > 100)
-		vol = 100;
-	vol = SCALE(100, 0x20, vol);
-	if (aci_write_cmd(right_index, 0x20 - vol))
-		return -EIO;
-	ret |= SCALE(0x20, 100, vol) << 8;
- 
-	return (*(int *) arg = ret);
+	return 0;
 }
 
-
-static int
-aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
+static int aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
 {
-	int status, vol;
-	unsigned char buf;
+	int vol, buf;
 
-	/* handle solo mode control */
-	if (cmd == SOUND_MIXER_PRIVATE1) {
-		if (*(int *) arg >= 0) {
-			aci_solo = !!*(int *) arg;
-			if (aci_write_cmd(0xd2, aci_solo))
-				return -EIO;
-		} else if (aci_version >= 0xb0) {
-			if ((status = read_general_status()) < 0)
-				return -EIO;
-			return (*(int *) arg = (status & 0x20) == 0);
+	switch (cmd) {
+	case SOUND_MIXER_WRITE_VOLUME:
+		return setvolume(arg, 0x01, 0x00);
+	case SOUND_MIXER_WRITE_CD:
+		return setvolume(arg, 0x3c, 0x34);
+	case SOUND_MIXER_WRITE_MIC:
+		return setvolume(arg, 0x38, 0x30);
+	case SOUND_MIXER_WRITE_LINE:
+		return setvolume(arg, 0x39, 0x31);
+	case SOUND_MIXER_WRITE_SYNTH:
+		return setvolume(arg, 0x3b, 0x33);
+	case SOUND_MIXER_WRITE_PCM:
+		return setvolume(arg, 0x3a, 0x32);
+	case MIXER_WRITE(SOUND_MIXER_RADIO): /* fall through */
+	case SOUND_MIXER_WRITE_LINE1:  /* AUX1 or radio */
+		return setvolume(arg, 0x3d, 0x35);
+	case SOUND_MIXER_WRITE_LINE2:  /* AUX2 */
+		return setvolume(arg, 0x3e, 0x36);
+	case SOUND_MIXER_WRITE_BASS:   /* set band one and two */
+		if (aci_idcode[1]=='C') {
+			if ((buf=setequalizer(arg, 0x48, 0x40)) || 
+			    (buf=setequalizer(arg, 0x49, 0x41)));
+			return buf;
 		}
-		
-		return (*(int *) arg = aci_solo);
-	}
-	
-	if (((cmd >> 8) & 0xff) == 'M') {
-		if (cmd & SIOC_IN)
-			/* read and write */
-			switch (cmd & 0xff) {
-				case SOUND_MIXER_VOLUME:
-					return setvolume(arg, 0x01, 0x00);
-				case SOUND_MIXER_CD:
-					return setvolume(arg, 0x3c, 0x34);
-				case SOUND_MIXER_MIC:
-					return setvolume(arg, 0x38, 0x30);
-				case SOUND_MIXER_LINE:
-					return setvolume(arg, 0x39, 0x31);
-				case SOUND_MIXER_SYNTH:
-					return setvolume(arg, 0x3b, 0x33);
-				case SOUND_MIXER_PCM:
-					return setvolume(arg, 0x3a, 0x32);
-				case SOUND_MIXER_LINE1:  /* AUX1 */
-					return setvolume(arg, 0x3d, 0x35);
-				case SOUND_MIXER_LINE2:  /* AUX2 */
-					return setvolume(arg, 0x3e, 0x36);
-				case SOUND_MIXER_IGAIN:  /* MIC pre-amp */
-					vol = *(int *) arg & 0xff;
-					if (vol > 100)
-						vol = 100;
-					vol = SCALE(100, 3, vol);
-					if (aci_write_cmd(0x03, vol))
-						return -EIO;
-					vol = SCALE(3, 100, vol);
-					return (*(int *) arg = vol | (vol << 8));
-				case SOUND_MIXER_RECSRC:
-					return (*(int *) arg = 0);
-					break;
-				default:
-					return -EINVAL;
+		break;
+	case SOUND_MIXER_WRITE_TREBLE: /* set band six and seven */
+		if (aci_idcode[1]=='C') {
+			if ((buf=setequalizer(arg, 0x4d, 0x45)) || 
+			    (buf=setequalizer(arg, 0x4e, 0x46)));
+			return buf;
+		}
+		break;
+	case SOUND_MIXER_WRITE_IGAIN:  /* MIC pre-amp */
+		if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
+			__get_user(vol, (int *)arg);
+			vol = vol & 0xff;
+			if (vol > 100)
+				vol = 100;
+			vol = SCALE(100, 3, vol);
+			if ((buf=aci_write_cmd(0x03, vol))<0)
+				return buf;
+			aci_micpreamp = vol;
+			vol = SCALE(3, 100, vol);
+			vol |= (vol << 8);
+			__put_user(vol, (int *)arg);
+			return 0;
+		}
+		break;
+	case SOUND_MIXER_WRITE_OGAIN:  /* Power-amp/line-out level */
+		if (aci_idcode[1]=='A' || aci_idcode[1]=='B') {
+			__get_user(buf, (int *)arg);
+			buf = buf & 0xff;
+			if (buf > 50)
+				vol = 1;
+			else
+				vol = 0;
+			if ((buf=aci_write_cmd(0x0f, vol))<0)
+				return buf;
+			aci_amp = vol;
+			if (aci_amp)
+				buf = (100 || 100<<8);
+			else
+				buf = 0;
+			__put_user(buf, (int *)arg);
+			return 0;
+		}
+		break;
+	case SOUND_MIXER_WRITE_RECSRC:
+		/* handle solo mode control */
+		__get_user(buf, (int *)arg);
+		/* unset solo when RECSRC for PCM is requested */
+		if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
+			vol = !(buf & SOUND_MASK_PCM);
+			if ((buf=aci_write_cmd(0xd2, vol))<0)
+				return buf;
+			aci_solo = vol;
+		}
+		buf = (SOUND_MASK_CD| SOUND_MASK_MIC| SOUND_MASK_LINE|
+		       SOUND_MASK_SYNTH| SOUND_MASK_LINE2);
+		if (aci_idcode[1] == 'C') /* PCM20 radio */
+			buf |= SOUND_MASK_RADIO;
+		else
+			buf |= SOUND_MASK_LINE1;
+		if (!aci_solo)
+			buf |= SOUND_MASK_PCM;
+		__put_user(buf, (int *)arg);
+		return 0;
+	case SOUND_MIXER_READ_DEVMASK:
+		buf = (SOUND_MASK_VOLUME | SOUND_MASK_CD    |
+		       SOUND_MASK_MIC    | SOUND_MASK_LINE  |
+		       SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
+		       SOUND_MASK_LINE2);
+		switch (aci_idcode[1]) {
+		case 'C': /* PCM20 radio */
+			buf |= (SOUND_MASK_RADIO | SOUND_MASK_IGAIN |
+				SOUND_MASK_BASS  | SOUND_MASK_TREBLE);
+			break;
+		case 'B': /* PCM12 */
+			buf |= (SOUND_MASK_LINE1 | SOUND_MASK_IGAIN |
+				SOUND_MASK_OGAIN);
+			break;
+		case 'A': /* PCM1-pro */
+			buf |= (SOUND_MASK_LINE1 | SOUND_MASK_OGAIN);
+			break;
+		default:
+			buf |= SOUND_MASK_LINE1;
+		}
+		__put_user(buf, (int *)arg);
+		return 0;
+	case SOUND_MIXER_READ_STEREODEVS:
+		buf = (SOUND_MASK_VOLUME | SOUND_MASK_CD    |
+		       SOUND_MASK_MIC    | SOUND_MASK_LINE  |
+		       SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
+		       SOUND_MASK_LINE2);
+		switch (aci_idcode[1]) {
+		case 'C': /* PCM20 radio */
+			buf |= (SOUND_MASK_RADIO |
+				SOUND_MASK_BASS  | SOUND_MASK_TREBLE);
+			break;
+		default:
+			buf |= SOUND_MASK_LINE1;
+		}
+		__put_user(buf, (int *)arg);
+		return 0;
+	case SOUND_MIXER_READ_RECMASK:
+		buf = (SOUND_MASK_CD| SOUND_MASK_MIC| SOUND_MASK_LINE|
+		       SOUND_MASK_SYNTH| SOUND_MASK_LINE2| SOUND_MASK_PCM);
+		if (aci_idcode[1] == 'C') /* PCM20 radio */
+			buf |= SOUND_MASK_RADIO;
+		else
+			buf |= SOUND_MASK_LINE1;
+
+		__put_user(buf, (int *)arg);
+		return 0;
+	case SOUND_MIXER_READ_RECSRC:
+		buf = (SOUND_MASK_CD    | SOUND_MASK_MIC   | SOUND_MASK_LINE  |
+		       SOUND_MASK_SYNTH | SOUND_MASK_LINE2);
+		/* do we need aci_solo or can I get it from the ACI? */
+		switch (aci_idcode[1]) {
+		case 'B': /* PCM12 */
+		case 'C': /* PCM20 radio */
+			if (aci_version >= 0xb0) {
+				if ((vol=aci_rw_cmd(0xf0, 0x00, -1))<0)
+					return vol;
+				if (vol & 0x20)
+					buf |= SOUND_MASK_PCM;
 			}
+			else
+				if (!aci_solo)
+					buf |= SOUND_MASK_PCM;
+			break;
+		default:
+			buf |= SOUND_MASK_PCM;
+		}
+		if (aci_idcode[1] == 'C') /* PCM20 radio */
+			buf |= SOUND_MASK_RADIO;
 		else
-			/* only read */
-			switch (cmd & 0xff) {
-				case SOUND_MIXER_DEVMASK:
-					return (*(int *) arg =
-				 SOUND_MASK_VOLUME | SOUND_MASK_CD    |
-				 SOUND_MASK_MIC    | SOUND_MASK_LINE  |
-				 SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
-#if 0
-				 SOUND_MASK_IGAIN  |
-#endif
-				 SOUND_MASK_LINE1  | SOUND_MASK_LINE2);
-				 	break;
-				case SOUND_MIXER_STEREODEVS:
-					return (*(int *) arg =
-				 SOUND_MASK_VOLUME | SOUND_MASK_CD   |
-				 SOUND_MASK_MIC    | SOUND_MASK_LINE |
-				 SOUND_MASK_SYNTH  | SOUND_MASK_PCM  |
-				 SOUND_MASK_LINE1  | SOUND_MASK_LINE2);
-				 	break;
-				case SOUND_MIXER_RECMASK:
-					return (*(int *) arg = 0);
-					break;
-				case SOUND_MIXER_RECSRC:
-					return (*(int *) arg = 0);
-					break;
-				case SOUND_MIXER_CAPS:
-					return (*(int *) arg = 0);
-					break;
-				case SOUND_MIXER_VOLUME:
-					return getvolume(arg, 0x04, 0x03);
-				case SOUND_MIXER_CD:
-					return getvolume(arg, 0x0a, 0x09);
-				case SOUND_MIXER_MIC:
-					return getvolume(arg, 0x06, 0x05);
-				case SOUND_MIXER_LINE:
-					return getvolume(arg, 0x08, 0x07);
-				case SOUND_MIXER_SYNTH:
-					return getvolume(arg, 0x0c, 0x0b);
-				case SOUND_MIXER_PCM:
-					return getvolume(arg, 0x0e, 0x0d);
-				case SOUND_MIXER_LINE1:  /* AUX1 */
-					return getvolume(arg, 0x11, 0x10);
-				case SOUND_MIXER_LINE2:  /* AUX2 */
-					return getvolume(arg, 0x13, 0x12);
-				case SOUND_MIXER_IGAIN:  /* MIC pre-amp */
-					if (aci_indexed_cmd(0xf0, 0x21, &buf))
-						return -EIO;
-					vol = SCALE(3, 100, buf <= 3 ? buf : 3);
-					vol |= vol << 8;
-					return (*(int *) arg = vol);
-				default:
-					return -EINVAL;
+			buf |= SOUND_MASK_LINE1;
+
+		__put_user(buf, (int *)arg);
+		return 0;
+	case SOUND_MIXER_READ_CAPS:
+		__put_user(0, (int *)arg);
+		return 0;
+	case SOUND_MIXER_READ_VOLUME:
+		return getvolume(arg, 0x04, 0x03);
+	case SOUND_MIXER_READ_CD:
+		return getvolume(arg, 0x0a, 0x09);
+	case SOUND_MIXER_READ_MIC:
+		return getvolume(arg, 0x06, 0x05);
+	case SOUND_MIXER_READ_LINE:
+		return getvolume(arg, 0x08, 0x07);
+	case SOUND_MIXER_READ_SYNTH:
+		return getvolume(arg, 0x0c, 0x0b);
+	case SOUND_MIXER_READ_PCM:
+		return getvolume(arg, 0x0e, 0x0d);
+	case MIXER_READ(SOUND_MIXER_RADIO): /* fall through */
+	case SOUND_MIXER_READ_LINE1:  /* AUX1 */
+		return getvolume(arg, 0x11, 0x10);
+	case SOUND_MIXER_READ_LINE2:  /* AUX2 */
+		return getvolume(arg, 0x13, 0x12);
+	case SOUND_MIXER_READ_BASS:   /* get band one */
+		if (aci_idcode[1]=='C') {
+			return getequalizer(arg, 0x23, 0x22);
+		}
+		break;
+	case SOUND_MIXER_READ_TREBLE: /* get band seven */
+		if (aci_idcode[1]=='C') {
+			return getequalizer(arg, 0x2f, 0x2e);
+		}
+		break;
+	case SOUND_MIXER_READ_IGAIN:  /* MIC pre-amp */
+		if (aci_idcode[1]=='B' || aci_idcode[1]=='C') {
+			/* aci_micpreamp or ACI? */
+			if (aci_version >= 0xb0) {
+				if ((buf=aci_indexed_cmd(0xf0, 0x21))<0)
+					return buf;
 			}
+			else
+				buf=aci_micpreamp;
+			vol = SCALE(3, 100, buf <= 3 ? buf : 3);
+			vol |= vol << 8;
+			__put_user(vol, (int *)arg);
+			return 0;
+		}
+		break;
+	case SOUND_MIXER_READ_OGAIN:
+		if (aci_amp)
+			buf = (100 || 100<<8);
+		else
+			buf = 0;
+		__put_user(buf, (int *)arg);
+		return 0;
 	}
-	
 	return -EINVAL;
 }
 
-
 static struct mixer_operations aci_mixer_operations =
 {
-	owner:	THIS_MODULE,
-	id:	"ACI",
-	name:	"ACI mixer",
-	ioctl:	aci_mixer_ioctl
+	owner: THIS_MODULE,
+	id:    "ACI",
+	ioctl: aci_mixer_ioctl
 };
 
-static unsigned char
-mad_read (int port)
-{
-	outb (0xE3, 0xf8f); /* Write MAD16 password */
-	return inb (port);  /* Read from port */
-}
-
-
 /*
- * Check, whether there actually is any ACI port operational and if
- * one was found, then initialize the ACI interface, reserve the I/O
- * addresses and attach the new mixer to the relevant VoxWare data
- * structures.
- *
- * Returns:  1   ACI mixer detected
- *           0   nothing there
- *
  * There is also an internal mixer in the codec (CS4231A or AD1845),
  * that deserves no purpose in an ACI based system which uses an
  * external ACI controlled stereo mixer. Make sure that this codec
@@ -570,153 +595,108 @@
 
 static int __init attach_aci(void)
 {
-	char *boardname = "unknown";
-	int volume;
+	char *boardname;
+	int i;
 
-#define MC4_PORT	0xf90
+	init_MUTEX(&aci_sem);
 
-	aci_port =
-		(mad_read(MC4_PORT) & 0x10) ? 0x344 : 0x354;
+	outb(0xE3, 0xf8f); /* Write MAD16 password */
+	aci_port = (inb(0xf90) & 0x10) ?
+		0x344: 0x354; /* Get aci_port from MC4_PORT */
 
 	if (check_region(aci_port, 3)) {
-#ifdef DEBUG
-		printk("ACI: I/O area 0x%03x-0x%03x already used.\n",
-			aci_port, aci_port+2);
-#endif
-		return 0;
+		printk(KERN_NOTICE "aci: I/O area 0x%03x-0x%03x already used.\n",
+		       aci_port, aci_port+2);
+		return -EBUSY;
 	}
-	
-	if (aci_read_cmd(0xf2, 2, aci_idcode)) {
-#ifdef DEBUG
-		printk("ACI: Failed to read idcode.\n");
-#endif
-		return 0;
+
+	/* force ACI into a known state */
+	for (i=0; i<3; i++)
+		if (aci_rw_cmd(0xdf, -1, -1)<0)
+			return -EFAULT;
+
+	/* official this is one aci read call: */
+	if ((aci_idcode[0]=aci_rw_cmd(0xf2, -1, -1))<0 ||
+	    (aci_idcode[1]=aci_rw_cmd(0xf2, -1, -1))<0) {
+		printk(KERN_ERR "aci: Failed to read idcode on 0x%03x.\n", aci_port);
+		return -EFAULT;
 	}
-	
-	if (aci_read_cmd(0xf1, 1, &aci_version)) {
-#ifdef DEBUG
-		printk("ACI: Failed to read version.\n");
-#endif
-		return 0;
+
+	if ((aci_version=aci_rw_cmd(0xf1, -1, -1))<0) {
+		printk(KERN_ERR "aci: Failed to read version on 0x%03x.\n", aci_port);
+		return -EFAULT;
 	}
 
-	if (aci_idcode[0] == 0x6d) {
+	if (aci_idcode[0] == 'm') {
 		/* It looks like a miro sound card. */
 		switch (aci_idcode[1]) {
-			case 0x41:
-				boardname = "PCM1 pro / early PCM12";
-				break;
-			case 0x42:
-				boardname = "PCM12";
-				break;
-			case 0x43:
-				boardname = "PCM20";
-				break;
-			default:
-				boardname = "unknown miro";
+		case 'A':
+			boardname = "PCM1 pro / early PCM12";
+			break;
+		case 'B':
+			boardname = "PCM12";
+			break;
+		case 'C':
+			boardname = "PCM20 radio";
+			break;
+		default:
+			boardname = "unknown miro";
 		}
-	} else
-#ifndef DEBUG
-	return 0;
-#endif
-  
-  	printk("<ACI %02x, id %02x %02x (%s)> at 0x%03x\n",
-		aci_version, aci_idcode[0], aci_idcode[1], boardname, aci_port);
-
-	if (aci_reset) {
-		/* initialize ACI mixer */
-		aci_implied_cmd(0xff);
-		aci_solo = 0;
-	}
-
-	/* attach the mixer */
-	request_region(aci_port, 3, "sound mixer (ACI)");
-	if (num_mixers < MAX_MIXER_DEV) {
-		if (num_mixers > 0 &&
-		  !strncmp("MAD16 WSS", mixer_devs[num_mixers-1]->name, 9)) {
-			/*
-			 * The previously registered mixer device is the CS4231A which
-			 * has no function on an ACI card. Make the ACI mixer the first
-			 * of the two mixer devices.
-			 */
-			mixer_devs[num_mixers] = mixer_devs[num_mixers-1];
-			mixer_devs[num_mixers-1] = &aci_mixer_operations;
-			/*
-			 * Initialize the CS4231A mixer with reasonable values. It is
-			 * unlikely that the user ever will want to change these as all
-			 * channels can be mixed via ACI.
-			 */
-			volume = 0x6464;
-			mixer_devs[num_mixers]->ioctl(num_mixers,
-				SOUND_MIXER_WRITE_PCM, (caddr_t) &volume);
-			volume = 0x6464;
-			mixer_devs[num_mixers]->ioctl(num_mixers,
-				SOUND_MIXER_WRITE_IGAIN,   (caddr_t) &volume);
-			volume = 0;
-			mixer_devs[num_mixers]->ioctl(num_mixers,
-				SOUND_MIXER_WRITE_SPEAKER, (caddr_t) &volume);
-			volume = 0;
-			mixer_devs[num_mixers]->ioctl(num_mixers,
-				SOUND_MIXER_WRITE_MIC, (caddr_t) &volume);
-			volume = 0;
-			mixer_devs[num_mixers]->ioctl(num_mixers,
-				SOUND_MIXER_WRITE_IMIX, (caddr_t) &volume);
-			volume = 0;
-			mixer_devs[num_mixers]->ioctl(num_mixers,
-				SOUND_MIXER_WRITE_LINE1, (caddr_t) &volume);
-			volume = 0;
-			mixer_devs[num_mixers]->ioctl(num_mixers,
-				SOUND_MIXER_WRITE_LINE2, (caddr_t) &volume);
-			volume = 0;
-			mixer_devs[num_mixers]->ioctl(num_mixers,
-				SOUND_MIXER_WRITE_LINE3, (caddr_t) &volume);
-			volume = SOUND_MASK_LINE1;
-			mixer_devs[num_mixers]->ioctl(num_mixers,
-				SOUND_MIXER_WRITE_RECSRC, (caddr_t) &volume);
-			num_mixers++;
-		} else
-			mixer_devs[num_mixers++] = &aci_mixer_operations;
-	}
-
-	/* Just do something; otherwise the first write command fails, at
-	 * least with my PCM20.
-	 */
-	aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_READ_VOLUME, (caddr_t) &volume);
-	
-	if (aci_reset) {
-		/* Initialize ACI mixer with reasonable power-up values */
-		volume = 0x3232;
-		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_VOLUME, (caddr_t) &volume);
-		volume = 0x3232;
-		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_SYNTH,  (caddr_t) &volume);
-		volume = 0x3232;
-		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_PCM,    (caddr_t) &volume);
-		volume = 0x3232;
-		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE,   (caddr_t) &volume);
-		volume = 0x3232;
-		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_MIC,    (caddr_t) &volume);
-		volume = 0x3232;
-		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_CD,     (caddr_t) &volume);
-		volume = 0x3232;
-		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE1,  (caddr_t) &volume);
-		volume = 0x3232;
-		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE2,  (caddr_t) &volume);
+	} else {
+		printk(KERN_WARNING "aci: Warning: unsupported card! - "
+		       "no hardware, no specs...\n");
+		boardname = "unknown Cardinal Technologies";
+	}
+
+	printk(KERN_INFO "<ACI 0x%02x, id %02x/%02x \"%c/%c\", (%s)> at 0x%03x\n",
+	       aci_version,
+	       aci_idcode[0], aci_idcode[1],
+	       aci_idcode[0], aci_idcode[1],
+	       boardname, aci_port);
+
+	if (reset) {
+		/* first write()s after reset fail with my PCM20 */
+		if (aci_rw_cmd(0xff, -1, -1)<0 ||
+		    aci_rw_cmd(0xdf, 0xdf, 0xdf)<0 ||
+		    aci_rw_cmd(0xdf, 0xdf, 0xdf)<0)
+			return -EBUSY;
+	}
+
+	/* the PCM20 is muted after reset (and reboot) */
+	if (aci_rw_cmd(0x0d, 0x00, -1)<0)
+		return -EBUSY;
+
+	if (ide>=0)
+		if (aci_rw_cmd(0xd0, !ide, -1)<0)
+			return -EBUSY;
+	
+	if (wss>=0 && aci_idcode[1]=='A')
+		if (aci_rw_cmd(0xd1, !!wss, -1)<0)
+			return -EBUSY;
+
+	if (!request_region(aci_port, 3, "sound mixer (ACI)"))
+		return -ENOMEM;
+
+	if ((mixer_device = sound_install_mixer(MIXER_DRIVER_VERSION,
+						boardname,
+						&aci_mixer_operations,
+						sizeof(aci_mixer_operations),
+						NULL)) >= 0) {
+		/* Maybe initialize the CS4231A mixer here... */
+	} else {
+		printk(KERN_ERR "aci: Failed to install mixer.\n");
+		release_region(aci_port, 3);
+		return mixer_device;
 	}
 
-	aci_present = 1;
-
-	return 1;
+	return 0;
 }
 
 static void __exit unload_aci(void)
 {
-	if (aci_present)
-		release_region(aci_port, 3);
+	sound_unload_mixerdev(mixer_device);
+	release_region(aci_port, 3);
 }
-
-EXPORT_SYMBOL(aci_write_cmd);
-EXPORT_SYMBOL(aci_indexed_cmd);
-EXPORT_SYMBOL(aci_write_cmd_d);
 
 module_init(attach_aci);
 module_exit(unload_aci);
diff -urN linux-2.4.4-pre3/drivers/sound/aci.h linux/drivers/sound/aci.h
--- linux-2.4.4-pre3/drivers/sound/aci.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/aci.h	Mon Dec  3 22:35:23 2001
@@ -0,0 +1,55 @@
+#ifndef _ACI_H_
+#define _ACI_H_
+
+extern int aci_port;
+extern int aci_idcode[2];	/* manufacturer and product ID */
+extern int aci_version;		/* ACI firmware version	*/
+extern int aci_rw_cmd(int write1, int write2, int write3);
+
+extern char * aci_radio_name;
+extern int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize);
+
+#define aci_indexed_cmd(a, b) aci_rw_cmd(a, b, -1)
+#define aci_write_cmd(a, b)   aci_rw_cmd(a, b, -1)
+#define aci_read_cmd(a)       aci_rw_cmd(a,-1, -1)
+
+#define COMMAND_REGISTER    (aci_port)      /* write register */
+#define STATUS_REGISTER     (aci_port + 1)  /* read register */
+#define BUSY_REGISTER       (aci_port + 2)  /* also used for rds */
+
+#define RDS_REGISTER        BUSY_REGISTER
+
+#define RDS_STATUS      0x01
+#define RDS_STATIONNAME 0x02
+#define RDS_TEXT        0x03
+#define RDS_ALTFREQ     0x04
+#define RDS_TIMEDATE    0x05
+#define RDS_PI_CODE     0x06
+#define RDS_PTYTATP     0x07
+#define RDS_RESET       0x08
+#define RDS_RXVALUE     0x09
+
+/*
+ * The following macro SCALE can be used to scale one integer volume
+ * value into another one using only integer arithmetic. If the input
+ * value x is in the range 0 <= x <= xmax, then the result will be in
+ * the range 0 <= SCALE(xmax,ymax,x) <= ymax.
+ *
+ * This macro has for all xmax, ymax > 0 and all 0 <= x <= xmax the
+ * following nice properties:
+ *
+ * - SCALE(xmax,ymax,xmax) = ymax
+ * - SCALE(xmax,ymax,0) = 0
+ * - SCALE(xmax,ymax,SCALE(ymax,xmax,SCALE(xmax,ymax,x))) = SCALE(xmax,ymax,x)
+ *
+ * In addition, the rounding error is minimal and nicely distributed.
+ * The proofs are left as an exercise to the reader.
+ */
+
+#define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
+
+extern void __exit unload_aci_rds(void);
+extern int __init attach_aci_rds(void);
+
+
+#endif  /* _ACI_H_ */
diff -urN linux-2.4.4-pre3/drivers/sound/aedsp16.c linux/drivers/sound/aedsp16.c
--- linux-2.4.4-pre3/drivers/sound/aedsp16.c	Wed Sep 27 13:53:57 2000
+++ linux/drivers/sound/aedsp16.c	Mon Dec  3 22:35:23 2001
@@ -257,9 +257,9 @@
 
 #define VERSION "1.3"		/* Version of Audio Excel DSP 16 driver */
 
-#undef	AEDSP16_DEBUG 1		/* Define this to enable debug code     */
-#undef	AEDSP16_DEBUG_MORE 1	/* Define this to enable more debug     */
-#undef	AEDSP16_INFO  1		/* Define this to enable info code      */
+#undef	AEDSP16_DEBUG 		/* Define this to 1 to enable debug code     */
+#undef	AEDSP16_DEBUG_MORE 	/* Define this to 1 to enable more debug     */
+#undef	AEDSP16_INFO 		/* Define this to 1 to enable info code      */
 
 #if defined(AEDSP16_DEBUG)
 # define DBG(x)  printk x
diff -urN linux-2.4.4-pre3/drivers/sound/emu10k1/cardmi.h linux/drivers/sound/emu10k1/cardmi.h
--- linux-2.4.4-pre3/drivers/sound/emu10k1/cardmi.h	Mon Dec 11 13:02:20 2000
+++ linux/drivers/sound/emu10k1/cardmi.h	Mon Dec  3 22:35:23 2001
@@ -34,6 +34,7 @@
 #define _CARDMI_H
 
 #include "icardmid.h"
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 
 typedef enum
diff -urN linux-2.4.4-pre3/drivers/sound/emu10k1/timer.h linux/drivers/sound/emu10k1/timer.h
--- linux-2.4.4-pre3/drivers/sound/emu10k1/timer.h	Mon Dec 11 13:02:19 2000
+++ linux/drivers/sound/emu10k1/timer.h	Mon Dec  3 22:35:23 2001
@@ -27,6 +27,7 @@
 #ifndef _TIMER_H
 #define _TIMER_H
 
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include "hwaccess.h"
 
diff -urN linux-2.4.4-pre3/drivers/sound/miroaci.h linux/drivers/sound/miroaci.h
--- linux-2.4.4-pre3/drivers/sound/miroaci.h	Sun Mar 12 19:13:06 2000
+++ linux/drivers/sound/miroaci.h	Wed Dec 31 16:00:00 1969
@@ -1,5 +0,0 @@
-extern int aci_implied_cmd(unsigned char opcode);
-extern int aci_write_cmd(unsigned char opcode, unsigned char parameter);
-extern int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2);
-extern int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter);
-extern int aci_indexed_cmd(unsigned char opcode, unsigned char index, unsigned char *parameter);
diff -urN linux-2.4.4-pre3/drivers/sound/vidc.c linux/drivers/sound/vidc.c
--- linux-2.4.4-pre3/drivers/sound/vidc.c	Wed Sep 27 13:39:23 2000
+++ linux/drivers/sound/vidc.c	Mon Dec  3 22:35:23 2001
@@ -17,6 +17,7 @@
  * We currently support a mixer device, but it is currently non-functional.
  */
 
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -82,6 +83,7 @@
 static void	(*old_mksound)(unsigned int hz, unsigned int ticks);
 extern void	(*kd_mksound)(unsigned int hz, unsigned int ticks);
 extern void	vidc_update_filler(int bits, int channels);
+extern int	softoss_dev;
 
 static void
 vidc_mksound(unsigned int hz, unsigned int ticks)
@@ -214,8 +216,8 @@
 			rate = VIDC_SOUND_CLOCK / hwrate;
 		}
 
-		outl(0xb0000000 | (hwrate - 2), IO_VIDC_BASE);
-		outl(0xb1000000 | hwctrl, IO_VIDC_BASE);
+		vidc_writel(0xb0000000 | (hwrate - 2));
+		vidc_writel(0xb1000000 | hwctrl);
 
 		newsize = (10000 / hwrate) & ~3;
 		if (newsize < 208)
@@ -354,7 +356,7 @@
 
 			dma_interrupt = vidc_audio_dma_interrupt;
 			vidc_sound_dma_irq(0, NULL, NULL);
-			outb(DMA_CR_E | 0x10, IOMD_SD0CR);
+			iomd_writeb(DMA_CR_E | 0x10, IOMD_SD0CR);
 
 			local_irq_restore(flags);
 		}
@@ -473,6 +475,9 @@
 	vidc_adev = adev;
 	vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8));
 
+#if defined(CONFIG_SOUND_SOFTOSS) || defined(CONFIG_SOUND_SOFTOSS_MODULE)
+	softoss_dev = adev;
+#endif
 	return;
 
 irq_failed:
diff -urN linux-2.4.4-pre3/drivers/sound/waveartist.c linux/drivers/sound/waveartist.c
--- linux-2.4.4-pre3/drivers/sound/waveartist.c	Sat Nov 11 18:33:14 2000
+++ linux/drivers/sound/waveartist.c	Mon Dec  3 22:35:23 2001
@@ -1824,7 +1824,7 @@
 	io	= ints[1];
 	irq	= ints[2];
 	dma	= ints[3];
-	dma16	= ints[4];
+	dma2	= ints[4];
 
 	return 1;
 }
diff -urN linux-2.4.4-pre3/drivers/tc/Makefile linux/drivers/tc/Makefile
--- linux-2.4.4-pre3/drivers/tc/Makefile	Fri Jun 25 17:38:40 1999
+++ linux/drivers/tc/Makefile	Mon Dec  3 22:35:23 2001
@@ -7,27 +7,36 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-SUB_DIRS     :=
-MOD_SUB_DIRS := 
-ALL_SUB_DIRS := 
-
-L_TARGET := tc.a
-L_OBJS   := tc.o
-
-# Nasty trick as nobody references tcsyms.o, but we still want it linked.
-# Stolen from pci Makefile
-ifeq ($(CONFIG_MODULES),y)
-O_TARGET = tc_syms.o
-OX_OBJS  = tcsyms.o
-O_OBJS   = tc.o
-L_OBJS   := tc_syms.o
-else
-L_OBJS   := tc.o
-endif
-
-ifdef CONFIG_ZS
-L_OBJS   += zs.o
-endif
+# All of the (potential) objects that export symbols.
+# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
+
+export-objs	:= tc.o
+
+# Object file lists.
+
+obj-y		:=
+obj-m		:=
+obj-n		:=
+obj-		:=
+
+obj-$(CONFIG_TC) += tc.o
+obj-$(CONFIG_ZS) += zs.o
+obj-$(CONFIG_VT) += lk201.o lk201-map.o lk201-remap.o
+
+# Files that are both resident and modular: remove from modular.
+
+obj-m		:= $(filter-out $(obj-y), $(obj-m))
+
+# Translate to Rules.make lists.
+
+L_TARGET	:= tc.a
+
+L_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-y)))
+LX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-y)))
+M_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-m)))
 
 include $(TOPDIR)/Rules.make
 
+lk201-map.c: lk201-map.map
+	loadkeys --mktable lk201-map.map > lk201-map.c
diff -urN linux-2.4.4-pre3/drivers/usb/hub.c linux/drivers/usb/hub.c
--- linux-2.4.4-pre3/drivers/usb/hub.c	Sun Mar 25 18:14:21 2001
+++ linux/drivers/usb/hub.c	Mon Dec  3 22:35:23 2001
@@ -98,15 +98,12 @@
 	hub->nerrors = 0;
 
 	/* Something happened, let khubd figure it out */
-	if (waitqueue_active(&khubd_wait)) {
-		/* Add the hub to the event queue */
-		spin_lock_irqsave(&hub_event_lock, flags);
-		if (list_empty(&hub->event_list)) {
-			list_add(&hub->event_list, &hub_event_list);
-			wake_up(&khubd_wait);
-		}
-		spin_unlock_irqrestore(&hub_event_lock, flags);
+	spin_lock_irqsave(&hub_event_lock, flags);
+	if (list_empty(&hub->event_list)) {
+		list_add(&hub->event_list, &hub_event_list);
+		wake_up(&khubd_wait);
 	}
+	spin_unlock_irqrestore(&hub_event_lock, flags);
 }
 
 static void usb_hub_power_on(struct usb_hub *hub)
@@ -239,7 +236,6 @@
 
 static void *hub_probe(struct usb_device *dev, unsigned int i,
 		       const struct usb_device_id *id)
-
 {
 	struct usb_interface_descriptor *interface;
 	struct usb_endpoint_descriptor *endpoint;
@@ -293,7 +289,7 @@
 
 	INIT_LIST_HEAD(&hub->event_list);
 	hub->dev = dev;
-	init_MUTEX(&hub->khubd_sem);
+	atomic_set(&hub->refcnt, 1);
 
 	/* Record the new hub's existence */
 	spin_lock_irqsave(&hub_event_lock, flags);
@@ -322,6 +318,29 @@
 	return NULL;
 }
 
+static void hub_get(struct usb_hub *hub)
+{
+	atomic_inc(&hub->refcnt);
+}
+
+static void hub_put(struct usb_hub *hub)
+{
+	if (atomic_dec_and_test(&hub->refcnt)) {
+		if (hub->urb) {
+			usb_unlink_urb(hub->urb);
+			usb_free_urb(hub->urb);
+			hub->urb = NULL;
+		}
+
+		if (hub->descriptor) {
+			kfree(hub->descriptor);
+			hub->descriptor = NULL;
+		}
+
+		kfree(hub);
+	}
+}
+
 static void hub_disconnect(struct usb_device *dev, void *ptr)
 {
 	struct usb_hub *hub = (struct usb_hub *)ptr;
@@ -337,22 +356,7 @@
 
 	spin_unlock_irqrestore(&hub_event_lock, flags);
 
-	down(&hub->khubd_sem); /* Wait for khubd to leave this hub alone. */
-	up(&hub->khubd_sem);
-
-	if (hub->urb) {
-		usb_unlink_urb(hub->urb);
-		usb_free_urb(hub->urb);
-		hub->urb = NULL;
-	}
-
-	if (hub->descriptor) {
-		kfree(hub->descriptor);
-		hub->descriptor = NULL;
-	}
-
-	/* Free the memory */
-	kfree(hub);
+	hub_put(hub);
 }
 
 static int hub_ioctl(struct usb_device *hub, unsigned int code, void *user_data)
@@ -406,6 +410,7 @@
 	if (usb_reset_device(dev))
 		return -1;
 
+	hub->urb->dev = dev;                                                    
 	if (usb_submit_urb(hub->urb))
 		return -1;
 
@@ -663,7 +668,7 @@
 		list_del(tmp);
 		INIT_LIST_HEAD(tmp);
 
-		down(&hub->khubd_sem); /* never blocks, we were on list */
+		hub_get(hub);
 		spin_unlock_irqrestore(&hub_event_lock, flags);
 
 		if (hub->error) {
@@ -672,7 +677,7 @@
 			if (usb_hub_reset(hub)) {
 				err("error resetting hub %d - disconnecting", dev->devnum);
 				usb_hub_disconnect(dev);
-				up(&hub->khubd_sem);
+				hub_put(hub);
 				continue;
 			}
 
@@ -748,7 +753,7 @@
                         	usb_hub_power_on(hub);
 			}
 		}
-		up(&hub->khubd_sem);
+		hub_put(hub);
         } /* end while (1) */
 
 	spin_unlock_irqrestore(&hub_event_lock, flags);
diff -urN linux-2.4.4-pre3/drivers/usb/hub.h linux/drivers/usb/hub.h
--- linux-2.4.4-pre3/drivers/usb/hub.h	Fri Mar 23 11:50:01 2001
+++ linux/drivers/usb/hub.h	Mon Dec  3 22:35:23 2001
@@ -109,7 +109,7 @@
 
 	struct usb_hub_descriptor *descriptor;
 
-	struct semaphore khubd_sem;
+	atomic_t refcnt;
 };
 
 #endif
diff -urN linux-2.4.4-pre3/drivers/video/Config.in linux/drivers/video/Config.in
--- linux-2.4.4-pre3/drivers/video/Config.in	Thu Jan  4 13:00:55 2001
+++ linux/drivers/video/Config.in	Mon Dec  3 22:35:23 2001
@@ -98,6 +98,14 @@
          bool '    CGsix (GX,TurboGX) support' CONFIG_FB_CGSIX
       fi
    fi
+   bool '  Epson 1355 framebuffer support' CONFIG_FB_E1355
+   if [ "$CONFIG_FB_E1355" = "y" ]; then
+      hex '    Register Base Address' CONFIG_E1355_REG_BASE a8000000
+      hex '    Framebuffer Base Address' CONFIG_E1355_FB_BASE a8200000
+   fi
+   if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then
+      tristate '  Dreamcast Frame Buffer support' CONFIG_FB_DC
+   fi
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       if [ "$CONFIG_PCI" != "n" ]; then
 	 tristate '  Matrox acceleration (EXPERIMENTAL)' CONFIG_FB_MATROX
diff -urN linux-2.4.4-pre3/drivers/video/Makefile linux/drivers/video/Makefile
--- linux-2.4.4-pre3/drivers/video/Makefile	Fri Dec 29 14:07:23 2000
+++ linux/drivers/video/Makefile	Mon Dec  3 22:35:23 2001
@@ -100,6 +100,8 @@
 obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o  
 obj-$(CONFIG_FB_HIT)              += hitfb.o fbgen.o
+obj-$(CONFIG_FB_E1355)            += epson1355fb.o fbgen.o
+obj-$(CONFIG_FB_DC)               += dcfb.o fbgen.o
 
 # Generic Low Level Drivers
 
diff -urN linux-2.4.4-pre3/drivers/video/dcfb.c linux/drivers/video/dcfb.c
--- linux-2.4.4-pre3/drivers/video/dcfb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/dcfb.c	Mon Dec  3 22:35:23 2001
@@ -0,0 +1,504 @@
+/*
+ *	$Id: dcfb.c,v 1.1 2001/04/01 15:02:51 yaegashi Exp $
+ *	SEGA Dreamcast framebuffer
+ */
+ 
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/nubus.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+
+#include <linux/fb.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb32.h>
+
+#define BORDERRGB	0xa05f8040
+#define DISPLAYMODE	0xa05f8044
+#define ALPHAMODE	0xa05f8048
+#define DISPLAYALIGN	0xa05f804c
+#define BASEOFFSET1	0xa05f8050
+#define BASEOFFSET2	0xa05f8054
+#define DISPLAYSIZE	0xa05f805c
+#define SYNCMODE	0xa05f80d0
+#define VERTICALRANGE	0xa05f80dc
+#define HORIZPOSITION	0xa05f80ec
+#define VERTPOSITION	0xa05f80f0
+#define PALETTEMODE	0xa05f8108
+#define VIDEOOUTPUT	0xa0702c00
+
+static unsigned long dc_parm_vga_16bpp[] = {
+    DISPLAYMODE,	0x00800005,
+    BASEOFFSET1,	0,
+    BASEOFFSET2,	640*2,
+    DISPLAYSIZE,	(1<<20)+((480-1)<<10)+(640*2/4-1),
+    SYNCMODE,		0x100,
+    VERTPOSITION,	0x00230023,
+    VERTICALRANGE,	0x00280208,
+    HORIZPOSITION,	0x00000090,
+    VIDEOOUTPUT,	0,
+    0, 0,
+};
+    
+static unsigned long dc_parm_vga_32bpp[] = {
+    DISPLAYMODE,	0x0080000d,
+    BASEOFFSET1,	0,
+    BASEOFFSET2,	640*4,
+    DISPLAYSIZE,	(1<<20)+((480-1)<<10)+(640*4/4-1),
+    SYNCMODE,		0x100,
+    VERTPOSITION,	0x00230023,
+    VERTICALRANGE,	0x00280208,
+    HORIZPOSITION,	0x00000090,
+    VIDEOOUTPUT,	0,
+    0, 0,
+};
+
+static unsigned long *dc_parm_vga[] = {
+    dc_parm_vga_16bpp,
+    dc_parm_vga_32bpp,
+};
+
+static unsigned long dc_parm_composite_16bpp[] = {
+    DISPLAYMODE,	0x00000005,
+    BASEOFFSET1,	0,
+    BASEOFFSET2,	640*2,
+    DISPLAYSIZE,	((640*2/4+1)<<20)+((240-1)<<10)+(640*2/4-1),
+    SYNCMODE,		0x150,
+    VERTPOSITION,	0x00120012,
+    VERTICALRANGE,	0x00240204,
+    HORIZPOSITION,	0x000000a4,
+    VIDEOOUTPUT,	0x300,
+    0, 0,
+};
+    
+static unsigned long dc_parm_composite_32bpp[] = {
+    DISPLAYMODE,	0x0000000d,
+    BASEOFFSET1,	0,
+    BASEOFFSET2,	640*4,
+    DISPLAYSIZE,	((640*4/4+1)<<20)+((240-1)<<10)+(640*4/4-1),
+    SYNCMODE,		0x150,
+    VERTPOSITION,	0x00120012,
+    VERTICALRANGE,	0x00240204,
+    HORIZPOSITION,	0x000000a4,
+    VIDEOOUTPUT,	0x300,
+    0, 0,
+};
+
+static unsigned long *dc_parm_composite[] = {
+    dc_parm_composite_16bpp,
+    dc_parm_composite_32bpp,
+};
+
+static unsigned long dc_parm_interlace_16bpp[] = {
+    DISPLAYMODE,	0x00000005,
+    BASEOFFSET1,	0,
+    BASEOFFSET2,	640*2,
+    DISPLAYSIZE,	((640*2/4+1)<<20)+((240-1)<<10)+(640*2/4-1),
+    SYNCMODE,		0x150,
+    VERTPOSITION,	0x00120012,
+    VERTICALRANGE,	0x00240204,
+    HORIZPOSITION,	0x000000a4,
+    VIDEOOUTPUT,	0,
+    0, 0,
+};
+    
+static unsigned long dc_parm_interlace_32bpp[] = {
+    DISPLAYMODE,	0x0000000d,
+    BASEOFFSET1,	0,
+    BASEOFFSET2,	640*4,
+    DISPLAYSIZE,	((640*4/4+1)<<20)+((240-1)<<10)+(640*4/4-1),
+    SYNCMODE,		0x150,
+    VERTPOSITION,	0x00120012,
+    VERTICALRANGE,	0x00240204,
+    HORIZPOSITION,	0x000000a4,
+    VIDEOOUTPUT,	0,
+    0, 0,
+};
+
+static unsigned long *dc_parm_interlace[] = {
+    dc_parm_interlace_16bpp,
+    dc_parm_interlace_32bpp,
+};
+
+struct dcfb_info {
+    struct fb_info_gen gen;
+};
+
+struct dcfb_par
+{
+    int x, y;
+    int bpp;
+};
+
+static struct dcfb_info fb_info;
+static struct dcfb_par current_par;
+static int current_par_valid = 0;
+static struct display disp;
+
+static union {
+#ifdef FBCON_HAS_CFB16
+    u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+    u32 cfb32[16];
+#endif
+} fbcon_cmap;
+
+static unsigned long **dc_parms;
+static unsigned long dc_videobase, dc_videosize;
+static struct fb_var_screeninfo default_var;
+
+int dcfb_init(void);
+
+static void dcfb_set_par(struct dcfb_par *par, const struct fb_info *info);
+static void dcfb_encode_var(struct fb_var_screeninfo *var, 
+			      struct dcfb_par *par,
+			      const struct fb_info *info);
+
+
+/*
+ *	Check cable type.
+ *	0: VGA, 2: RGB, 3: Composite
+ */
+
+#define	PCTRA	0xff80002c
+#define PDTRA	0xff800030
+
+static int dcfb_cable_check(void)
+{
+    unsigned long temp = ctrl_inl(PCTRA);
+    temp &= 0xfff0ffff;
+    temp |= 0x000a0000;
+    ctrl_outl(temp, PCTRA);
+    return (ctrl_inw(PDTRA)>>8)&3;
+}
+
+static void dcfb_detect(void)
+{
+    struct dcfb_par par;
+    int cable = dcfb_cable_check();
+    unsigned long **parm_list[4] = {
+	dc_parm_vga, dc_parm_vga, dc_parm_interlace, dc_parm_composite,
+    };
+    char *cable_name[] = { "VGA", "VGA", "Interlace", "Composite", };
+
+    dc_videobase = 0xa5000000;
+    dc_videosize = 0x00200000;
+
+    par.x = 640;
+    par.y = 480;
+    par.bpp = 32;
+    dc_parms = parm_list[cable];
+    printk(KERN_INFO "Dreamcast video cable detected: %s.\n", cable_name[cable]);
+
+    dcfb_set_par(&par, NULL);
+    dcfb_encode_var(&default_var, &par, NULL);
+}
+
+static int dcfb_encode_fix(struct fb_fix_screeninfo *fix,
+			    struct dcfb_par *par,
+			    const struct fb_info *info)
+{
+    memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+    strcpy(fix->id, "SEGA Dreamcast");
+    fix->smem_start = dc_videobase;
+    fix->smem_len = dc_videosize;
+    fix->type = FB_TYPE_PACKED_PIXELS;
+    fix->type_aux = 0;
+    fix->visual = FB_VISUAL_TRUECOLOR;
+    fix->xpanstep = 0;
+    fix->ypanstep = 0;
+    fix->ywrapstep = 0;
+
+    switch(par->bpp) {
+    default:
+    case 16:
+	fix->line_length = par->x*2;
+	break;
+    case 32:
+	fix->line_length = par->x*4;
+	break;
+    }
+
+    return 0;
+}
+
+
+static int dcfb_decode_var(struct fb_var_screeninfo *var,
+			    struct dcfb_par *par,
+			    const struct fb_info *info)
+{
+    par->x = var->xres;
+    par->y = var->yres;
+    par->bpp = var->bits_per_pixel;
+    return 0;
+}
+
+
+static void dcfb_encode_var(struct fb_var_screeninfo *var, 
+			     struct dcfb_par *par,
+			     const struct fb_info *info)
+{
+    memset(var, 0, sizeof(*var));
+
+    var->xres = par->x;
+    var->yres = par->y;
+    var->xres_virtual = var->xres;
+    var->yres_virtual = var->yres;
+    var->xoffset = 0;
+    var->yoffset = 0;
+    var->bits_per_pixel = par->bpp;
+    var->grayscale = 0;
+    var->transp.offset = 0;
+    var->transp.length = 0;
+    var->transp.msb_right = 0;
+    var->nonstd = 0;
+    var->activate = 0;
+    var->height = -1;
+    var->width = -1;
+    var->vmode = FB_VMODE_NONINTERLACED;
+    var->pixclock = 0;
+    var->sync = 0;
+    var->left_margin = 0;
+    var->right_margin = 0;
+    var->upper_margin = 0;
+    var->lower_margin = 0;
+    var->hsync_len = 0;
+    var->vsync_len = 0;
+
+    switch (var->bits_per_pixel) {
+
+	case 16:	/* RGB 565 */
+	    var->red.offset = 11;
+	    var->red.length = 5;
+	    var->green.offset = 5;
+	    var->green.length = 6;
+	    var->blue.offset = 0;
+	    var->blue.length = 5;
+	    var->transp.offset = 0;
+	    var->transp.length = 0;
+	    break;
+
+	case 32:
+	    var->red.offset = 16;
+	    var->red.length = 8;
+	    var->green.offset = 8;
+	    var->green.length = 8;
+	    var->blue.offset = 0;
+	    var->blue.length = 8;
+	    var->transp.offset = 0;
+	    var->transp.length = 0;
+	    break;
+
+    }
+
+    var->red.msb_right = 0;
+    var->green.msb_right = 0;
+    var->blue.msb_right = 0;
+    var->transp.msb_right = 0;
+}
+
+
+static void dcfb_get_par(struct dcfb_par *par, const struct fb_info *info)
+{
+    *par = current_par;
+}
+
+
+static void dcfb_set_par(struct dcfb_par *par, const struct fb_info *info)
+{
+    unsigned long a, d, *p;
+
+    current_par = *par;
+    current_par_valid = 1;
+
+    switch(par->bpp) {
+    default:
+    case 16:
+	p = dc_parms[0];
+	break;
+    case 32:
+	p = dc_parms[1];
+	break;
+    }
+
+    ctrl_outl(0, 0xa05f8008);	/* reset? */
+    ctrl_outl(0, BORDERRGB);
+
+    while(1) {
+	a = *p++; d = *p++;
+	if (!a) break;
+	ctrl_outl(d, a);
+    }
+
+}
+
+static struct {
+  u_int red, green, blue;
+} palette[256];
+
+static int dcfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                         u_int *transp, struct fb_info *info)
+{
+    if (regno > 255)
+	return 1;	
+
+    *red = palette[regno].red;
+    *green = palette[regno].green;
+    *blue = palette[regno].blue;
+    *transp = 0;
+    
+    return 0;
+}
+
+
+static int dcfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp, struct fb_info *info)
+{
+    if (regno > 255)
+	return 1;
+
+    palette[regno].red = red;
+    palette[regno].green = green;
+    palette[regno].blue = blue;
+    
+    if(regno<16) {
+	switch(current_par.bpp) {
+#ifdef FBCON_HAS_CFB16
+	case 16:
+	    fbcon_cmap.cfb16[regno] =
+		((red   & 0xf800)      ) |
+		((green & 0xfc00) >>  5) |
+		((blue  & 0xf800) >> 11);
+	    break;
+#endif
+#ifdef FBCON_HAS_CFB32
+	case 32:
+	    fbcon_cmap.cfb32[regno] =
+		((red   & 0xff00) <<  8) |
+		((green & 0xff00)      ) |
+		((blue  & 0xff00) >>  8);
+	    break;
+#endif
+	}
+    }
+
+    return 0;
+}
+
+static int dcfb_blank(int blank_mode, const struct fb_info *info)
+{
+    return 0;
+}
+
+
+static void dcfb_set_disp(const void *par, struct display *disp,
+			   struct fb_info_gen *info)
+{
+    disp->screen_base = (void *)dc_videobase;
+    disp->scrollmode = SCROLL_YREDRAW;
+
+    switch(((struct dcfb_par *)par)->bpp) {
+#ifdef FBCON_HAS_CFB16
+    case 16:
+	disp->dispsw = &fbcon_cfb16;
+	disp->dispsw_data = fbcon_cmap.cfb16;
+	break;
+#endif
+#ifdef FBCON_HAS_CFB32
+    case 32:
+	disp->dispsw = &fbcon_cfb32;
+	disp->dispsw_data = fbcon_cmap.cfb32;
+	break;
+#endif
+    default:
+	disp->dispsw = &fbcon_dummy;
+    }
+}
+
+
+struct fbgen_hwswitch dcfb_switch = {
+    dcfb_detect,
+    dcfb_encode_fix,
+    dcfb_decode_var,
+    dcfb_encode_var,
+    dcfb_get_par,
+    dcfb_set_par,
+    dcfb_getcolreg,
+    dcfb_setcolreg,
+    NULL,
+    dcfb_blank,
+    dcfb_set_disp
+};
+
+static struct fb_ops dcfb_ops = {
+	owner:		THIS_MODULE,
+	fb_get_fix:	fbgen_get_fix,
+	fb_get_var:	fbgen_get_var,
+	fb_set_var:	fbgen_set_var,
+	fb_get_cmap:	fbgen_get_cmap,
+	fb_set_cmap:	fbgen_set_cmap,
+};
+
+
+int __init dcfb_init(void)
+{
+    strcpy(fb_info.gen.info.modename, "SEGA Dreamcast");
+    fb_info.gen.info.node = -1;
+    fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
+    fb_info.gen.info.fbops = &dcfb_ops;
+    fb_info.gen.info.disp = &disp;
+    fb_info.gen.info.changevar = NULL;
+    fb_info.gen.info.switch_con = &fbgen_switch;
+    fb_info.gen.info.updatevar = &fbgen_update_var;
+    fb_info.gen.info.blank = &fbgen_blank;
+    fb_info.gen.parsize = sizeof(struct dcfb_par);
+    fb_info.gen.fbhw = &dcfb_switch;
+    fb_info.gen.fbhw->detect();
+    
+    fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+    disp.var.activate = FB_ACTIVATE_NOW;
+    fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+    fbgen_set_disp(-1, &fb_info.gen);
+    fbgen_install_cmap(0, &fb_info.gen);
+    
+    if(register_framebuffer(&fb_info.gen.info)<0) return -EINVAL;
+    
+    printk(KERN_INFO "fb%d: %s frame buffer device\n",
+	   GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename);
+    
+    return 0;
+}
+
+
+void dcfb_cleanup(struct fb_info *info)
+{
+    unregister_framebuffer(info);
+}
+
+
+#ifdef MODULE
+int init_module(void)
+{
+    return dcfb_init();
+}
+
+void cleanup_module(void)
+{
+    dcfb_cleanup(void);
+}
+#endif
diff -urN linux-2.4.4-pre3/drivers/video/epson1355fb.c linux/drivers/video/epson1355fb.c
--- linux-2.4.4-pre3/drivers/video/epson1355fb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/epson1355fb.c	Mon Dec  3 22:35:23 2001
@@ -0,0 +1,539 @@
+/*
+ * linux/drivers/video/epson1355fb.c
+ *	-- Support for the Epson SED1355 LCD/CRT controller
+ *
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ *
+ * based on linux/drivers/video/skeletonfb.c, which was
+ *  Created 28 Dec 1997 by Geert Uytterhoeven
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+/* TODO (roughly in order of priority):
+ * 16 bpp support
+ * crt support
+ * hw cursor support
+ * SwivelView
+ */
+
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-mfb.h>
+#include <video/fbcon.h>
+
+/* Register defines.  The docs don't seem to provide nice mnemonic names
+ * so I made them up myself ... */
+
+#define E1355_PANEL	0x02
+#define E1355_DISPLAY	0x0D
+#define E1355_MISC	0x1B
+#define E1355_GPIO	0x20
+#define E1355_LUT_INDEX 0x24
+#define E1355_LUT_DATA	0x26
+
+#ifdef CONFIG_SUPERH
+#define E1355_REG_BASE	CONFIG_E1355_REG_BASE
+#define E1355_FB_BASE	CONFIG_E1355_FB_BASE
+
+static inline u8 e1355_read_reg(int index)
+{
+	return ctrl_inb(E1355_REG_BASE + index);
+}
+
+static inline void e1355_write_reg(u8 data, int index)
+{
+	ctrl_outb(data, E1355_REG_BASE + index);
+}
+
+static inline u16 e1355_read_reg16(int index)
+{
+	return e1355_read_reg(index) + (e1355_read_reg(index+1) << 8);
+}
+
+static inline void e1355_write_reg16(u16 data, int index)
+{
+	e1355_write_reg((data&0xff), index);
+	e1355_write_reg(((data>>8)&0xff), index + 1);
+}
+#else
+#error unknown architecture
+#endif
+
+struct e1355fb_info {
+	struct fb_info_gen gen;
+};
+
+static int current_par_valid = 0;
+static struct display disp;
+
+static struct fb_var_screeninfo default_var;
+
+int e1355fb_init(void);
+int e1355fb_setup(char*);
+static int e1355_encode_var(struct fb_var_screeninfo *var, const void *par,
+			    struct fb_info_gen *info);
+/* ------------------- chipset specific functions -------------------------- */
+
+
+static void disable_hw_cursor(void)
+{
+	u8 curs;
+
+	curs = e1355_read_reg(0x27);
+	curs &= ~0xc0;
+	e1355_write_reg(curs, 0x27);
+}
+
+static void e1355_detect(void)
+{
+	u8 rev;
+
+	e1355_write_reg(0x00, E1355_MISC);
+
+	rev = e1355_read_reg(0x00);
+
+	if ((rev & 0xfc) != 0x0c) {
+		printk(KERN_WARNING "Epson 1355 not detected\n");
+	}
+
+	/* XXX */
+	disable_hw_cursor();
+
+	e1355_encode_var(&default_var, NULL, NULL);
+}
+
+struct e1355_par {
+	u32 xres;
+	u32 yres;
+
+	int bpp;
+	int mem_bpp;
+
+	u32 panel_xres;
+	u32 panel_yres;
+	
+	int panel_width;
+	int panel_ymul;
+};
+
+static int e1355_encode_fix(struct fb_fix_screeninfo *fix,
+			    const void *raw_par,
+			    struct fb_info_gen *info)
+{
+	const struct e1355_par *par = raw_par;
+	
+	memset(fix, 0, sizeof *fix);
+	
+	fix->type= FB_TYPE_PACKED_PIXELS;
+
+	if (!par)
+		BUG();
+
+	if (par->bpp == 1) {
+		fix->visual = FB_VISUAL_MONO10;
+	} else if (par->bpp <= 8) {
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	} else {
+		fix->visual = FB_VISUAL_TRUECOLOR;
+	}
+
+	return 0;
+}
+
+static int e1355_set_bpp(struct e1355_par *par, int bpp)
+{
+	int code;
+	u8 disp;
+	u16 bytes_per_line;
+
+	switch(bpp) {
+	case 1:
+		code = 0; break;
+	case 2:
+		code = 1; break;
+	case 4:
+		code = 2; break;
+	case 8:
+		code = 3; break;
+	case 16:
+		code = 5; break;
+	default:
+		return -EINVAL; break;
+	}
+
+	disp = e1355_read_reg(E1355_DISPLAY);
+	disp &= ~0x1c;
+	disp |= code << 2;
+	e1355_write_reg(disp, E1355_DISPLAY);
+	
+	bytes_per_line = (par->xres * bpp) >> 3;
+	
+	e1355_write_reg16(bytes_per_line, 0x16);
+
+	par->bpp = bpp;
+
+	return 0;
+}
+		
+static int e1355_decode_var(const struct fb_var_screeninfo *var,
+			    void *raw_par,
+			    struct fb_info_gen *info)
+{
+	struct e1355_par *par = raw_par;
+	int ret;
+
+	if (!par)
+		BUG();
+
+	/*
+	 * Don't allow setting any of these yet: xres and yres don't
+	 * make sense for LCD panels; xres_virtual and yres_virtual
+	 * should be supported fine by our hardware though.
+	 */
+	if (var->xres != par->xres ||
+	    var->yres != par->yres ||
+	    var->xres != var->xres_virtual ||
+	    var->yres != var->yres_virtual ||
+	    var->xoffset != 0 ||
+	    var->yoffset != 0)
+		return -EINVAL;
+
+	if(var->bits_per_pixel != par->bpp) {
+		ret = e1355_set_bpp(par, var->bits_per_pixel);
+
+		if (ret)
+			goto out_err;
+	}
+		
+	return 0;
+
+ out_err:
+	return ret;
+}
+
+static void dump_panel_data(void)
+{
+	u8 panel = e1355_read_reg(E1355_PANEL);
+	int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
+
+	printk("%s %s %s panel, width %d bits\n",
+	       panel & 2 ? "dual" : "single",
+	       panel & 4 ? "color" : "mono",
+	       panel & 1 ? "TFT" : "passive",
+	       width[panel&1][(panel>>4)&3]);
+
+	printk("resolution %d x %d\n",
+	       (e1355_read_reg(0x04) + 1) * 8,
+	       ((e1355_read_reg16(0x08) + 1) * (1 + ((panel & 3) == 2))));
+}
+
+static int e1355_bpp_to_var(int bpp, struct fb_var_screeninfo *var)
+{
+	switch(bpp) {
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		var->bits_per_pixel = bpp;
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length = bpp;
+		break;
+	case 16:
+		var->bits_per_pixel = 16;
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		break;
+	}
+
+	return 0;
+}
+
+static int e1355_encode_var(struct fb_var_screeninfo *var, const void *raw_par,
+			    struct fb_info_gen *info)
+{
+	u8 panel, display;
+	u32 xres, xres_virtual, yres;
+	static int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
+	static int bpp_tab[8] = { 1, 2, 4, 8, 15, 16 };
+	int bpp, hw_bpp;
+	int is_color, is_dual, is_tft;
+	int lcd_enabled, crt_enabled;
+
+	panel = e1355_read_reg(E1355_PANEL);
+	display = e1355_read_reg(E1355_DISPLAY);
+
+	is_color = (panel & 0x04) != 0;
+	is_dual  = (panel & 0x02) != 0;
+	is_tft   = (panel & 0x01) != 0;
+
+	bpp = bpp_tab[(display>>2)&7]; 
+	e1355_bpp_to_var(bpp, var);
+
+	crt_enabled = (display & 0x02) != 0;
+	lcd_enabled = (display & 0x02) != 0;
+
+	hw_bpp = width[is_tft][(panel>>4)&3];
+
+	xres = e1355_read_reg(0x04) + 1;
+	yres = e1355_read_reg16(0x08) + 1;
+	
+	xres *= 8;
+	/* talk about weird hardware .. */
+	yres *= (is_dual && !crt_enabled) ? 2 : 1;
+
+	xres_virtual = e1355_read_reg16(0x16);
+	/* it's in 2-byte words initially */
+	xres_virtual *= 16;
+	xres_virtual /= var->bits_per_pixel;
+
+	var->xres = xres;
+	var->yres = yres;
+	var->xres_virtual = xres_virtual;
+	var->yres_virtual = yres;
+
+	var->xoffset = var->yoffset = 0;
+
+	var->grayscale = !is_color;
+	
+	return 0;
+}
+
+#define is_dual(panel) (((panel)&3)==2)
+
+static void get_panel_data(struct e1355_par *par)
+{
+	u8 panel;
+	int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } };
+
+	panel = e1355_read_reg(E1355_PANEL);
+
+	par->panel_width = width[panel&1][(panel>>4)&3];
+	par->panel_xres = (e1355_read_reg(0x04) + 1) * 8;
+	par->panel_ymul = is_dual(panel) ? 2 : 1;
+	par->panel_yres = ((e1355_read_reg16(0x08) + 1)
+			   * par->panel_ymul);
+}
+
+static void e1355_get_par(void *raw_par, struct fb_info_gen *info)
+{
+	struct e1355_par *par = raw_par;
+
+	get_panel_data(par);
+}
+
+static void e1355_set_par(const void *par, struct fb_info_gen *info)
+{
+}
+
+static int e1355_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+			   unsigned *blue, unsigned *transp,
+			   struct fb_info *info)
+{
+	u8 r, g, b;
+
+	e1355_write_reg(regno, E1355_LUT_INDEX);
+	r = e1355_read_reg(E1355_LUT_DATA);
+	g = e1355_read_reg(E1355_LUT_DATA);
+	b = e1355_read_reg(E1355_LUT_DATA);
+
+	*red = r << 8;
+	*green = g << 8;
+	*blue = b << 8;
+
+	return 0;
+}
+
+static int e1355_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	u8 r = (red >> 8) & 0xf0;
+	u8 g = (green>>8) & 0xf0;
+	u8 b = (blue>> 8) & 0xf0;
+
+	e1355_write_reg(regno, E1355_LUT_INDEX);
+	e1355_write_reg(r, E1355_LUT_DATA);
+	e1355_write_reg(g, E1355_LUT_DATA);
+	e1355_write_reg(b, E1355_LUT_DATA);
+	
+	return 0;
+}
+
+static int e1355_pan_display(const struct fb_var_screeninfo *var,
+			     struct fb_info_gen *info)
+{
+	BUG();
+	
+	return -EINVAL;
+}
+
+/*
+ * The AERO_HACKS parts disable/enable the backlight on the Compaq Aero 8000.
+ * I'm not sure they aren't dangerous to the hardware, so be warned.
+ */
+#undef AERO_HACKS
+
+static int e1355_blank(int blank_mode, struct fb_info_gen *info)
+{
+	u8 disp;
+
+	switch (blank_mode) {
+	case VESA_NO_BLANKING:
+		disp = e1355_read_reg(E1355_DISPLAY);
+		disp |= 1;
+		e1355_write_reg(disp, E1355_DISPLAY);
+ 		
+#ifdef AERO_HACKS
+		e1355_write_reg(0x6, 0x20);
+#endif
+		break;
+
+	case VESA_VSYNC_SUSPEND:
+	case VESA_HSYNC_SUSPEND:
+	case VESA_POWERDOWN:
+		disp = e1355_read_reg(E1355_DISPLAY);
+		disp &= ~1;
+		e1355_write_reg(disp, E1355_DISPLAY);
+
+#ifdef AERO_HACKS
+		e1355_write_reg(0x0, 0x20);
+#endif
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct display_switch e1355_dispsw;
+
+static void e1355_set_disp(const void *unused, struct display *disp,
+			   struct fb_info_gen *info)
+{
+	struct display_switch *d;
+
+	disp->screen_base = (void *)E1355_FB_BASE;
+	disp->dispsw = &e1355_dispsw;
+	
+	switch(disp->var.bits_per_pixel) {
+#ifdef FBCON_HAS_MFB
+	case 1:
+		d = &fbcon_mfb; break;
+#endif	       
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		d = &fbcon_cfb8; break;
+#endif
+	default:
+		BUG(); break;
+	}
+
+	memcpy(&e1355_dispsw, d, sizeof *d);
+
+	/* reading is terribly slow for us */
+#if 0 /* XXX: need to work out why this doesn't work */
+	e1355_dispsw.bmove = fbcon_redraw_bmove;
+#endif
+}
+
+/* ------------ Interfaces to hardware functions ------------ */
+
+
+struct fbgen_hwswitch e1355_switch = {
+	detect:		e1355_detect,
+	encode_fix:	e1355_encode_fix,
+	decode_var:	e1355_decode_var,
+	encode_var:	e1355_encode_var,
+	get_par:	e1355_get_par,
+	set_par:	e1355_set_par,
+	getcolreg:	e1355_getcolreg,
+	setcolreg:	e1355_setcolreg,
+	pan_display:	e1355_pan_display,
+	blank:		e1355_blank,
+	set_disp:	e1355_set_disp,
+};
+
+
+/* ------------ Hardware Independent Functions ------------ */
+
+
+static struct fb_ops e1355fb_ops = {
+	owner:		THIS_MODULE,
+	fb_get_fix:	fbgen_get_fix,
+	fb_get_var:	fbgen_get_var,
+	fb_set_var:	fbgen_set_var,
+	fb_get_cmap:	fbgen_get_cmap,
+	fb_set_cmap:	fbgen_set_cmap,
+	fb_pan_display:	fbgen_pan_display,
+};
+
+static struct e1355fb_info fb_info;
+
+int __init e1355fb_setup(char *str)
+{
+	return 0;
+}
+
+int __init e1355fb_init(void)
+{
+	fb_info.gen.fbhw = &e1355_switch;
+	fb_info.gen.fbhw->detect();
+	strcpy(fb_info.gen.info.modename, "SED1355");
+	fb_info.gen.info.changevar = NULL;
+	fb_info.gen.info.node = -1;
+	fb_info.gen.info.fbops = &e1355fb_ops;
+	fb_info.gen.info.disp = &disp;
+	fb_info.gen.parsize = sizeof(struct e1355_par);
+	fb_info.gen.info.switch_con = &fbgen_switch;
+	fb_info.gen.info.updatevar = &fbgen_update_var;
+	fb_info.gen.info.blank = &fbgen_blank;
+	fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
+	/* This should give a reasonable default video mode */
+	fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+	fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+	fbgen_set_disp(-1, &fb_info.gen);
+	if (disp.var.bits_per_pixel > 1) 
+		fbgen_install_cmap(0, &fb_info.gen);
+	if (register_framebuffer(&fb_info.gen.info) < 0)
+		return -EINVAL;
+	printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node),
+	       fb_info.gen.info.modename);
+
+	return 0;
+}
+
+
+    /*
+     *  Cleanup
+     */
+
+void e1355fb_cleanup(struct fb_info *info)
+{
+	/*
+	 *  If your driver supports multiple boards, you should unregister and
+	 *  clean up all instances.
+	 */
+	
+	unregister_framebuffer(info);
+	/* ... */
+}
+
diff -urN linux-2.4.4-pre3/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- linux-2.4.4-pre3/drivers/video/fbmem.c	Mon Dec  3 22:35:12 2001
+++ linux/drivers/video/fbmem.c	Mon Dec  3 22:35:23 2001
@@ -120,7 +120,10 @@
 extern int stifb_setup(char*);
 extern int radeonfb_init(void);
 extern int radeonfb_setup(char*);
-
+extern int e1355fb_init(void);
+extern int e1355fb_setup(char*);
+extern int dcfb_init(void);
+  
 static struct {
 	const char *name;
 	int (*init)(void);
@@ -199,6 +202,9 @@
 #ifdef CONFIG_FB_SIS
 	{ "sisfb", sisfb_init, sisfb_setup },
 #endif
+#ifdef CONFIG_FB_E1355
+	{ "e1355fb", e1355fb_init, e1355fb_setup },
+#endif
 
 	/*
 	 * Generic drivers that are used as fallbacks
@@ -263,6 +269,9 @@
 #endif
 #ifdef CONFIG_FB_HIT
 	{ "hitfb", hitfb_init, NULL },
+#endif
+#ifdef CONFIG_FB_DC
+	{ "dcfb", dcfb_init, NULL },
 #endif
 
 	/*
diff -urN linux-2.4.4-pre3/fs/devfs/base.c linux/fs/devfs/base.c
--- linux-2.4.4-pre3/fs/devfs/base.c	Fri Feb  9 11:29:44 2001
+++ linux/fs/devfs/base.c	Mon Dec  3 22:35:23 2001
@@ -3339,7 +3339,7 @@
 }   /*  End Function devfsd_close  */
 
 
-int __init init_devfs_fs (void)
+static int __init init_devfs_fs (void)
 {
     int err;
 
@@ -3369,3 +3369,5 @@
     if (err == 0) printk ("Mounted devfs on /dev\n");
     else printk ("Warning: unable to mount devfs, err: %d\n", err);
 }   /*  End Function mount_devfs_fs  */
+
+module_init(init_devfs_fs)
diff -urN linux-2.4.4-pre3/fs/devpts/inode.c linux/fs/devpts/inode.c
--- linux-2.4.4-pre3/fs/devpts/inode.c	Fri Feb  9 11:29:44 2001
+++ linux/fs/devpts/inode.c	Mon Dec  3 22:35:23 2001
@@ -220,7 +220,7 @@
 	}
 }
 
-int __init init_devpts_fs(void)
+static int __init init_devpts_fs(void)
 {
 	int err = register_filesystem(&devpts_fs_type);
 	if (!err) {
@@ -228,28 +228,25 @@
 		err = PTR_ERR(devpts_mnt);
 		if (!IS_ERR(devpts_mnt))
 			err = 0;
-	}
-	return err;
-}
-
 #ifdef MODULE
-
-int init_module(void)
-{
-	int err = init_devpts_fs();
-	if ( !err ) {
-		devpts_upcall_new  = devpts_pty_new;
-		devpts_upcall_kill = devpts_pty_kill;
+		if ( !err ) {
+			devpts_upcall_new  = devpts_pty_new;
+			devpts_upcall_kill = devpts_pty_kill;
+		}
+#endif
 	}
 	return err;
 }
 
-void cleanup_module(void)
+static void __exit exit_devpts_fs(void)
 {
+#ifdef MODULE
 	devpts_upcall_new  = NULL;
 	devpts_upcall_kill = NULL;
+#endif
 	unregister_filesystem(&devpts_fs_type);
 	kern_umount(devpts_mnt);
 }
 
-#endif
+module_init(init_devpts_fs)
+module_exit(exit_devpts_fs)
diff -urN linux-2.4.4-pre3/fs/filesystems.c linux/fs/filesystems.c
--- linux-2.4.4-pre3/fs/filesystems.c	Mon Sep 25 17:05:01 2000
+++ linux/fs/filesystems.c	Mon Dec  3 22:35:23 2001
@@ -7,36 +7,10 @@
  */
 
 #include <linux/config.h>
-#include <linux/fs.h>
-
-#include <linux/devfs_fs_kernel.h>
-#include <linux/nfs_fs.h>
-#include <linux/auto_fs.h>
-#include <linux/devpts_fs.h>
-#include <linux/major.h>
-#include <linux/smp.h>
+#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/module.h>
 #include <linux/nfsd/interface.h>
-
-#ifdef CONFIG_DEVPTS_FS
-extern int init_devpts_fs(void);
-#endif
-
-void __init filesystem_setup(void)
-{
-	init_devfs_fs();  /*  Header file may make this empty  */
-
-#ifdef CONFIG_NFS_FS
-	init_nfs_fs();
-#endif
-
-#ifdef CONFIG_DEVPTS_FS
-	init_devpts_fs();
-#endif
-}
 
 #if defined(CONFIG_NFSD_MODULE)
 struct nfsd_linkage *nfsd_linkage = NULL;
diff -urN linux-2.4.4-pre3/fs/nfs/inode.c linux/fs/nfs/inode.c
--- linux-2.4.4-pre3/fs/nfs/inode.c	Fri Mar  2 11:12:11 2001
+++ linux/fs/nfs/inode.c	Mon Dec  3 22:35:23 2001
@@ -15,6 +15,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/init.h>
 
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -1060,8 +1061,7 @@
 /*
  * Initialize NFS
  */
-int
-init_nfs_fs(void)
+static int __init init_nfs_fs(void)
 {
 	int err;
 
@@ -1079,23 +1079,7 @@
         return register_filesystem(&nfs_fs_type);
 }
 
-/*
- * Every kernel module contains stuff like this.
- */
-#ifdef MODULE
-
-EXPORT_NO_SYMBOLS;
-/* Not quite true; I just maintain it */
-MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
-
-int
-init_module(void)
-{
-	return init_nfs_fs();
-}
-
-void
-cleanup_module(void)
+static void __exit exit_nfs_fs(void)
 {
 	nfs_destroy_readpagecache();
 	nfs_destroy_nfspagecache();
@@ -1104,4 +1088,10 @@
 #endif
 	unregister_filesystem(&nfs_fs_type);
 }
-#endif
+
+EXPORT_NO_SYMBOLS;
+/* Not quite true; I just maintain it */
+MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
+
+module_init(init_nfs_fs)
+module_exit(exit_nfs_fs)
diff -urN linux-2.4.4-pre3/fs/partitions/Makefile linux/fs/partitions/Makefile
--- linux-2.4.4-pre3/fs/partitions/Makefile	Fri Dec 29 14:07:23 2000
+++ linux/fs/partitions/Makefile	Mon Dec  3 22:35:23 2001
@@ -9,7 +9,7 @@
 
 O_TARGET := partitions.o
 
-export-objs := check.o
+export-objs := check.o ibm.o
 
 obj-y := check.o
 
diff -urN linux-2.4.4-pre3/fs/partitions/ibm.c linux/fs/partitions/ibm.c
--- linux-2.4.4-pre3/fs/partitions/ibm.c	Fri Feb 16 16:02:37 2001
+++ linux/fs/partitions/ibm.c	Mon Dec  3 22:35:23 2001
@@ -1,14 +1,17 @@
 /*
  * File...........: linux/fs/partitions/ibm.c      
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ *                  Volker Sameske <sameske@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
 
  * History of changes (starts July 2000)
- * 07/10/00 Fixed detection of CMS formatted disks               
-
+ * 07/10/00 Fixed detection of CMS formatted disks     
+ * 02/13/00 VTOC partition support added
  */
 
+#include <linux/config.h>
+#include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/genhd.h>
 #include <linux/kernel.h>
@@ -25,145 +28,177 @@
 
 #include "ibm.h"
 #include "check.h"
+#include <asm/vtoc.h>
 
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
 /* We hook in when DASD is a module... */
 int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
+int (*genhd_dasd_fillgeo)(int,struct hd_geometry *) = NULL;
+EXPORT_SYMBOL(genhd_dasd_fillgeo);
+EXPORT_SYMBOL(genhd_dasd_name);
 #endif /* LINUX_IS_24 */
 
 typedef enum {
-  ibm_partition_none = 0,
-  ibm_partition_lnx1 = 1,
-  ibm_partition_vol1 = 3,
-  ibm_partition_cms1 = 4
+  ibm_partition_lnx1 = 0,
+  ibm_partition_vol1 = 1,
+  ibm_partition_cms1 = 2,
+  ibm_partition_none = 3
 } ibm_partition_t;
 
+static char* part_names[] = {   [ibm_partition_lnx1] = "LNX1",
+			     [ibm_partition_vol1] = "VOL1",
+			     [ibm_partition_cms1] = "CMS1",
+			     [ibm_partition_none] = "(nonl)"
+};
+
 static ibm_partition_t
 get_partition_type ( char * type )
 {
-        static char lnx[5]="LNX1";
-        static char vol[5]="VOL1";
-        static char cms[5]="CMS1";
-        if ( ! strncmp ( lnx, "LNX1",4 ) ) {
-                ASCEBC(lnx,4);
-                ASCEBC(vol,4);
-                ASCEBC(cms,4);
-        }
-        if ( ! strncmp (type,lnx,4) ||
-             ! strncmp (type,"LNX1",4) )
-                return ibm_partition_lnx1;
-        if ( ! strncmp (type,vol,4) )
-                return ibm_partition_vol1;
-        if ( ! strncmp (type,cms,4) )
-                return ibm_partition_cms1;
-        return ibm_partition_none;
+	int i;
+	for ( i = 0; i < 3; i ++) {
+		if ( ! strncmp (type,part_names[i],4) ) 
+			break;
+	}
+        return i;
+}
+
+/*
+ * add the two default partitions
+ * - whole dasd
+ * - whole dasd without "offset"
+ */
+static inline void
+two_partitions(struct gendisk *hd,
+	       int minor,
+	       int blocksize,
+	       int offset,
+	       int size) {
+
+        add_gd_partition( hd, minor, 0,size);
+	add_gd_partition( hd, minor + 1, 
+			   offset * (blocksize >> 9),
+			   size-offset*(blocksize>>9));
+}
+
+
+/*
+ * compute the block number from a 
+ * cyl-cyl-head-head structure
+ */
+static inline int
+cchh2blk (cchh_t *ptr, struct hd_geometry *geo) {
+        return ptr->cc * geo->heads * geo->sectors +
+	       ptr->hh * geo->sectors;
+}
+
+
+/*
+ * compute the block number from a 
+ * cyl-cyl-head-head-block structure
+ */
+static inline int
+cchhb2blk (cchhb_t *ptr, struct hd_geometry *geo) {
+        return ptr->cc * geo->heads * geo->sectors +
+		ptr->hh * geo->sectors +
+		ptr->b;
 }
 
 int 
 ibm_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int
 first_part_minor)
 {
-	struct buffer_head *bh;
+	struct buffer_head *bh, *buf;
 	ibm_partition_t partition_type;
 	char type[5] = {0,};
 	char name[7] = {0,};
 	struct hd_geometry geo;
-	mm_segment_t old_fs;
 	int blocksize;
-	struct file *filp = NULL;
-	struct inode *inode = NULL;
-	int offset, size;
+	int offset=0, size=0, psize=0, counter=0;
+	unsigned int blk;
+	format1_label_t f1;
+	volume_label_t vlabel;
 
+	if ( first_sector != 0 ) {
+		BUG();
+	}
+	if ( !genhd_dasd_fillgeo ) {
+		return 0;
+	}
+	genhd_dasd_fillgeo(dev,&geo);
 	blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
 	if ( blocksize <= 0 ) {
 		return 0;
 	}
-	set_blocksize(dev, blocksize);  /* OUCH !! */
-
-	/* find out offset of volume label (partn table) */
-	inode = get_empty_inode();
-	inode -> i_rdev = dev;
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
-	inode -> i_bdev = bdget(kdev_t_to_nr(dev));
-#endif /* KERNEL_VERSION */
-	filp = (struct file *)kmalloc (sizeof(struct file),GFP_KERNEL);
-	if (!filp)
-		return 0;
-	memset(filp,0,sizeof(struct file));
-	filp ->f_mode = 1; /* read only */
-	blkdev_open(inode,filp);
-	old_fs=get_fs();
-	set_fs(KERNEL_DS);
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
-	inode-> i_bdev -> bd_op->ioctl (inode, filp, HDIO_GETGEO, (unsigned long)(&geo));
-#else
-	filp->f_op->ioctl (inode, filp, HDIO_GETGEO, (unsigned long)(&geo));
-#endif /* KERNEL_VERSION */
-	set_fs(old_fs);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
-        blkdev_put(inode->i_bdev,BDEV_FILE);
-#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
-	blkdev_close(inode,filp);
-#else
-	blkdev_release(inode);
-#endif /* LINUX_VERSION_CODE */
 
-	size = hd -> sizes[MINOR(dev)]<<1;
+	set_blocksize(dev, blocksize);  /* OUCH !! */
 	if ( ( bh = bread( dev, geo.start, blocksize) ) != NULL ) {
-		strncpy ( type,bh -> b_data, 4);
+		strncpy ( type,bh -> b_data + 0, 4);
 		strncpy ( name,bh -> b_data + 4, 6);
+		memcpy (&vlabel, bh->b_data, sizeof(volume_label_t));
         } else {
 		return 0;
 	}
-	if ( (*(char *)bh -> b_data) & 0x80 ) {
-		EBCASC(name,6);
-	}
-	switch ( partition_type = get_partition_type(type) ) {
-	case ibm_partition_lnx1: 
-		offset = (geo.start + 1);
-		printk ( "(LNX1)/%6s:",name);
-		break;
-	case ibm_partition_vol1:
-		offset = 0;
-		size = 0;
-		printk ( "(VOL1)/%6s:",name);
-		break;
+	EBCASC(type,4);
+	EBCASC(name,6);
+
+	partition_type = get_partition_type(type);
+	printk ( "%6s/%6s:",part_names[partition_type],name);
+	switch ( partition_type ) {
 	case ibm_partition_cms1:
-		printk ( "(CMS1)/%6s:",name);
-		if (* (((long *)bh->b_data) + 13) == 0) {
-			/* disk holds a CMS filesystem */
-			offset = (geo.start + 1);
-			printk ("(CMS)");
-		} else {
+		if (* (((long *)bh->b_data) + 13) != 0) {
 			/* disk is reserved minidisk */
-			// mdisk_setup_data.size[i] =
-			// (label[7] - 1 - label[13]) *
-			// (label[3] >> 9) >> 1;
 			long *label=(long*)bh->b_data;
 			blocksize = label[3];
 			offset = label[13];
 			size = (label[7]-1)*(blocksize>>9); 
 			printk ("(MDSK)");
+		} else {
+			offset = (geo.start + 1);
+			size = hd -> sizes[MINOR(dev)]<<1;
 		}
+		two_partitions( hd, MINOR(dev), blocksize, 
+				offset, size);
 		break;
+	case ibm_partition_lnx1: 
 	case ibm_partition_none:
-		printk ( "(nonl)/      :");
-		offset = (geo.start+1);
+		offset = (geo.start + 1);
+		size = hd -> sizes[MINOR(dev)]<<1;
+		two_partitions( hd, MINOR(dev), blocksize, 
+				offset, size);
+		break;
+	case ibm_partition_vol1:
+		add_gd_partition(hd, MINOR(dev), 0, size);
+
+		/* get block number and read then first format1 label */
+		blk = cchhb2blk(&vlabel.vtoc, &geo) + 1;
+		if ((buf = bread( dev, blk, blocksize)) != NULL) {
+		        memcpy (&f1, buf->b_data, sizeof(format1_label_t));
+			bforget(buf);
+		}
+
+		while (f1.DS1FMTID == _ascebc['1']) {
+		        offset = cchh2blk(&f1.DS1EXT1.llimit, &geo);
+			psize  = cchh2blk(&f1.DS1EXT1.ulimit, &geo) - 
+				offset + 1;
+			
+			counter++;
+			add_gd_partition(hd, MINOR(dev) + counter, 
+					  offset * (blocksize >> 9),
+					  psize * (blocksize >> 9));
+			
+			blk++;
+			if ((buf = bread( dev, blk, blocksize)) != NULL) {
+			        memcpy (&f1, buf->b_data, 
+					sizeof(format1_label_t));
+				bforget(buf);
+			}
+		}
 		break;
 	default:
-		offset = 0;
-		size = 0;
-		
+		add_gd_partition( hd, MINOR(dev), 0, 0);
+		add_gd_partition( hd, MINOR(dev) + 1, 0, 0);
 	}
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
-	add_gd_partition( hd, MINOR(dev), 0,size);
-	add_gd_partition( hd, MINOR(dev) + 1, offset * (blocksize >> 9),
-			  size-offset*(blocksize>>9));
-#else
-	add_partition( hd, MINOR(dev), 0,size,0);
-	add_partition( hd, MINOR(dev) + 1, offset * (blocksize >> 9),
-			  size-offset*(blocksize>>9) ,0 );
-#endif /* LINUX_VERSION */
+
 	printk ( "\n" );
 	bforget(bh);
 	return 1;
diff -urN linux-2.4.4-pre3/fs/proc/proc_misc.c linux/fs/proc/proc_misc.c
--- linux-2.4.4-pre3/fs/proc/proc_misc.c	Fri Mar 23 11:45:28 2001
+++ linux/fs/proc/proc_misc.c	Mon Dec  3 22:35:23 2001
@@ -274,8 +274,10 @@
 		user += kstat.per_cpu_user[cpu];
 		nice += kstat.per_cpu_nice[cpu];
 		system += kstat.per_cpu_system[cpu];
+#if !defined(CONFIG_ARCH_S390)
 		for (j = 0 ; j < NR_IRQS ; j++)
 			sum += kstat.irqs[cpu][j];
+#endif
 	}
 
 	len = sprintf(page, "cpu  %u %u %u %lu\n", user, nice, system,
@@ -299,8 +301,10 @@
 			kstat.pswpout,
 			sum
 	);
+#if !defined(CONFIG_ARCH_S390)
 	for (i = 0 ; i < NR_IRQS ; i++)
 		len += sprintf(page + len, " %u", kstat_irqs(i));
+#endif
 
 	len += sprintf(page + len, "\ndisk_io: ");
 
diff -urN linux-2.4.4-pre3/fs/reiserfs/fix_node.c linux/fs/reiserfs/fix_node.c
--- linux-2.4.4-pre3/fs/reiserfs/fix_node.c	Fri Mar  2 18:38:39 2001
+++ linux/fs/reiserfs/fix_node.c	Mon Dec  3 22:35:23 2001
@@ -479,7 +479,7 @@
     // do not count last 'end_bytes' units of 'end_item'-th item
     end_bytes = (to_bytes != -1) ? to_bytes : 0;
 
-    /* go through all item begining from the start_item-th item and ending by
+    /* go through all item beginning from the start_item-th item and ending by
        the end_item-th item. Do not count first 'start_bytes' units of
        'start_item'-th item and last 'end_bytes' of 'end_item'-th item */
     
diff -urN linux-2.4.4-pre3/fs/reiserfs/prints.c linux/fs/reiserfs/prints.c
--- linux-2.4.4-pre3/fs/reiserfs/prints.c	Mon Jan 15 15:31:19 2001
+++ linux/fs/reiserfs/prints.c	Mon Dec  3 22:35:23 2001
@@ -259,14 +259,14 @@
 {
   do_reiserfs_warning;
   /* console_print (error_buf); */
-  printk ("%s", error_buf);
+  printk (KERN_WARNING "%s", error_buf);
 }
 
 void reiserfs_debug (struct super_block *s, int level, const char * fmt, ...)
 {
 #ifdef CONFIG_REISERFS_CHECK
   do_reiserfs_warning;
-  printk ("%s", error_buf);
+  printk (KERN_DEBUG "%s", error_buf);
 #else
   ; 
 #endif
diff -urN linux-2.4.4-pre3/fs/reiserfs/stree.c linux/fs/reiserfs/stree.c
--- linux-2.4.4-pre3/fs/reiserfs/stree.c	Fri Mar  2 18:38:39 2001
+++ linux/fs/reiserfs/stree.c	Mon Dec  3 22:35:23 2001
@@ -380,7 +380,7 @@
     /* Parent at the path is not in the tree now. */
     if ( ! B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)) )
       return &MIN_KEY;
-    /* Check whether position in the parrent is correct. */
+    /* Check whether position in the parent is correct. */
     if ( (n_position = PATH_OFFSET_POSITION(p_s_chk_path, n_path_offset)) > B_NR_ITEMS(p_s_parent) )
       return &MIN_KEY;
     /* Check whether parent at the path really points to the child. */
diff -urN linux-2.4.4-pre3/fs/reiserfs/super.c linux/fs/reiserfs/super.c
--- linux-2.4.4-pre3/fs/reiserfs/super.c	Fri Mar  2 11:12:12 2001
+++ linux/fs/reiserfs/super.c	Mon Dec  3 22:35:23 2001
@@ -412,6 +412,7 @@
     SB_BUFFER_WITH_SB (s) = bh;
     SB_DISK_SUPER_BLOCK (s) = rs;
     s->s_op = &reiserfs_sops;
+    s->s_maxbytes = MAX_NON_LFS;
     return 0;
 }
 #endif
diff -urN linux-2.4.4-pre3/fs/romfs/inode.c linux/fs/romfs/inode.c
--- linux-2.4.4-pre3/fs/romfs/inode.c	Fri Mar  2 11:12:12 2001
+++ linux/fs/romfs/inode.c	Mon Dec  3 22:35:23 2001
@@ -403,9 +403,11 @@
 	void *buf;
 	int result = -EIO;
 
+	page_cache_get(page);
 	lock_kernel();
-	get_page(page);
-	buf = page_address(page);
+	buf = kmap(page);
+	if (!buf)
+		goto err_out;
 
 	/* 32 bit warning -- but not for us :) */
 	offset = page->index << PAGE_CACHE_SHIFT;
@@ -428,7 +430,9 @@
 
 	UnlockPage(page);
 
-	__free_page(page);
+	kunmap(page);
+err_out:
+	page_cache_release(page);
 	unlock_kernel();
 
 	return result;
diff -urN linux-2.4.4-pre3/fs/smbfs/ioctl.c linux/fs/smbfs/ioctl.c
--- linux-2.4.4-pre3/fs/smbfs/ioctl.c	Tue Jul 18 22:30:34 2000
+++ linux/fs/smbfs/ioctl.c	Mon Dec  3 22:35:23 2001
@@ -45,7 +45,7 @@
 		if (!copy_from_user(&opt, (void *)arg, sizeof(opt)))
 			result = smb_newconn(server, &opt);
 		break;
-	default:
+	default:;
 	}
 
 	return result;
diff -urN linux-2.4.4-pre3/fs/smbfs/proc.c linux/fs/smbfs/proc.c
--- linux-2.4.4-pre3/fs/smbfs/proc.c	Tue Mar  6 19:14:59 2001
+++ linux/fs/smbfs/proc.c	Mon Dec  3 22:35:23 2001
@@ -697,7 +697,7 @@
 #else
 	/*
 	 * We don't want to be interrupted. For example, what if 'current'
-	 * already has recieved a signal? sleep_on would terminate immediately
+	 * already has received a signal? sleep_on would terminate immediately
 	 * and smbmount would not be able to re-establish connection.
 	 *
 	 * smbmount should be able to reconnect later, but it can't because
@@ -712,7 +712,7 @@
 	if (server->state == CONN_VALID) {
 		/* This should be changed to VERBOSE, except many smbfs
 		   problems is with the userspace daemon not reconnecting. */
-		PARANOIA("sucessful, new pid=%d, generation=%d\n",
+		PARANOIA("successful, new pid=%d, generation=%d\n",
 			 server->conn_pid, server->generation);
 		result = 1;
 	}
diff -urN linux-2.4.4-pre3/fs/stat.c linux/fs/stat.c
--- linux-2.4.4-pre3/fs/stat.c	Tue Dec  5 12:29:39 2000
+++ linux/fs/stat.c	Mon Dec  3 22:35:23 2001
@@ -25,7 +25,7 @@
 }
 
 
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__) && !defined(__hppa__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(CONFIG_ARCH_S390) && !defined(__hppa__)
 
 /*
  * For backward compatibility?  Maybe this should be moved
@@ -38,7 +38,7 @@
 
 	if (warncount > 0) {
 		warncount--;
-		printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n",
+		printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
 			current->comm);
 	} else if (warncount < 0) {
 		/* it's laughable, but... */
@@ -53,7 +53,7 @@
 	SET_OLDSTAT_GID(tmp, inode->i_gid);
 	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
 #if BITS_PER_LONG == 32
-	if (inode->i_size > 0x7fffffff)
+	if (inode->i_size > MAX_NON_LFS)
 		return -EOVERFLOW;
 #endif	
 	tmp.st_size = inode->i_size;
@@ -79,7 +79,7 @@
 	SET_STAT_GID(tmp, inode->i_gid);
 	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
 #if BITS_PER_LONG == 32
-	if (inode->i_size > 0x7fffffff)
+	if (inode->i_size > MAX_NON_LFS)
 		return -EOVERFLOW;
 #endif	
 	tmp.st_size = inode->i_size;
diff -urN linux-2.4.4-pre3/fs/super.c linux/fs/super.c
--- linux-2.4.4-pre3/fs/super.c	Mon Dec  3 22:35:13 2001
+++ linux/fs/super.c	Mon Dec  3 22:35:23 2001
@@ -691,7 +691,7 @@
  *	the request.
  */
  
-struct super_block *get_empty_super(void)
+static struct super_block *get_empty_super(void)
 {
 	struct super_block *s;
 
@@ -738,6 +738,7 @@
 	sema_init(&s->s_dquot.dqio_sem, 1);
 	sema_init(&s->s_dquot.dqoff_sem, 1);
 	s->s_dquot.flags = 0;
+	s->s_maxbytes = MAX_NON_LFS;
 	lock_super(s);
 	if (!type->read_super(s, data, silent))
 		goto out_fail;
diff -urN linux-2.4.4-pre3/fs/udf/partition.c linux/fs/udf/partition.c
--- linux-2.4.4-pre3/fs/udf/partition.c	Fri Feb  9 11:29:44 2001
+++ linux/fs/udf/partition.c	Mon Dec  3 22:35:23 2001
@@ -162,6 +162,10 @@
 					mapsize = (rtl * sizeof(Uint32)) +
 						((partlen/(1 << sdata->s_spar_pshift)) * sizeof(Uint8) * num);
 					sdata->s_spar_map = kmalloc(mapsize, GFP_KERNEL);
+					if (!sdata->s_spar_map) {
+						printk("couldnt allocate UDF s_spar_map!\n");
+						return;
+					}
 					sdata->s_spar_remap.s_spar_remap32 = &sdata->s_spar_map[rtl];
 					memset(sdata->s_spar_map, 0xFF, mapsize);
 				}
diff -urN linux-2.4.4-pre3/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- linux-2.4.4-pre3/include/asm-alpha/io.h	Fri Mar  2 11:12:07 2001
+++ linux/include/asm-alpha/io.h	Mon Dec  3 22:35:23 2001
@@ -1,10 +1,6 @@
 #ifndef __ALPHA_IO_H
 #define __ALPHA_IO_H
 
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <asm/system.h>
-
 /* We don't use IO slowdowns on the Alpha, but.. */
 #define __SLOW_DOWN_IO	do { } while (0)
 #define SLOW_DOWN_IO	do { } while (0)
@@ -19,6 +15,9 @@
 #endif
 
 #ifdef __KERNEL__
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/system.h>
 #include <asm/machvec.h>
 
 /*
diff -urN linux-2.4.4-pre3/include/asm-alpha/ioctls.h linux/include/asm-alpha/ioctls.h
--- linux-2.4.4-pre3/include/asm-alpha/ioctls.h	Thu Jan 27 16:40:09 2000
+++ linux/include/asm-alpha/ioctls.h	Mon Dec  3 22:35:23 2001
@@ -106,5 +106,7 @@
 
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define TIOCGHAYESESP	0x545E  /* Get Hayes ESP configuration */
+#define TIOCSHAYESESP	0x545F  /* Set Hayes ESP configuration */
 
 #endif /* _ASM_ALPHA_IOCTLS_H */
diff -urN linux-2.4.4-pre3/include/asm-alpha/pgalloc.h linux/include/asm-alpha/pgalloc.h
--- linux-2.4.4-pre3/include/asm-alpha/pgalloc.h	Fri Dec 29 14:07:23 2000
+++ linux/include/asm-alpha/pgalloc.h	Mon Dec  3 22:35:23 2001
@@ -241,6 +241,9 @@
 #define pte_quicklist (quicklists.pte_cache)
 #define pgtable_cache_size (quicklists.pgtable_cache_sz)
 
+#define pmd_populate(mm, pmd, pte)	pmd_set(pmd, pte)
+#define pgd_populate(mm, pgd, pmd)	pgd_set(pgd, pmd)
+
 extern pgd_t *get_pgd_slow(void);
 
 static inline pgd_t *get_pgd_fast(void)
@@ -268,9 +271,15 @@
 	free_page((unsigned long)pgd);
 }
 
-extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long address_premasked);
+static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+	pmd_t *ret = (pmd_t *)__get_free_page(GFP_KERNEL);
+	if (ret)
+		clear_page(ret);
+	return ret;
+}
 
-static inline pmd_t *get_pmd_fast(void)
+static inline pmd_t *pmd_alloc_one_fast(struct mm_struct *mm, unsigned long address)
 {
 	unsigned long *ret;
 
@@ -282,21 +291,27 @@
 	return (pmd_t *)ret;
 }
 
-static inline void free_pmd_fast(pmd_t *pmd)
+static inline void pmd_free_fast(pmd_t *pmd)
 {
 	*(unsigned long *)pmd = (unsigned long) pte_quicklist;
 	pte_quicklist = (unsigned long *) pmd;
 	pgtable_cache_size++;
 }
 
-static inline void free_pmd_slow(pmd_t *pmd)
+static inline void pmd_free_slow(pmd_t *pmd)
 {
 	free_page((unsigned long)pmd);
 }
 
-extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
+static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+	pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL);
+	if (pte)
+		clear_page(pte);
+	return pte;
+}
 
-static inline pte_t *get_pte_fast(void)
+static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
 {
 	unsigned long *ret;
 
@@ -308,66 +323,22 @@
 	return (pte_t *)ret;
 }
 
-static inline void free_pte_fast(pte_t *pte)
+static inline void pte_free_fast(pte_t *pte)
 {
 	*(unsigned long *)pte = (unsigned long) pte_quicklist;
 	pte_quicklist = (unsigned long *) pte;
 	pgtable_cache_size++;
 }
 
-static inline void free_pte_slow(pte_t *pte)
+static inline void pte_free_slow(pte_t *pte)
 {
 	free_page((unsigned long)pte);
 }
 
-extern void __bad_pte(pmd_t *pmd);
-extern void __bad_pmd(pgd_t *pgd);
-
-#define pte_free_kernel(pte)	free_pte_fast(pte)
-#define pte_free(pte)		free_pte_fast(pte)
-#define pmd_free_kernel(pmd)	free_pmd_fast(pmd)
-#define pmd_free(pmd)		free_pmd_fast(pmd)
+#define pte_free(pte)		pte_free_fast(pte)
+#define pmd_free(pmd)		pmd_free_fast(pmd)
 #define pgd_free(pgd)		free_pgd_fast(pgd)
 #define pgd_alloc()		get_pgd_fast()
-
-static inline pte_t * pte_alloc(pmd_t *pmd, unsigned long address)
-{
-	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-	if (pmd_none(*pmd)) {
-		pte_t *page = get_pte_fast();
-		
-		if (!page)
-			return get_pte_slow(pmd, address);
-		pmd_set(pmd, page);
-		return page + address;
-	}
-	if (pmd_bad(*pmd)) {
-		__bad_pte(pmd);
-		return NULL;
-	}
-	return (pte_t *) pmd_page(*pmd) + address;
-}
-
-static inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
-{
-	address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
-	if (pgd_none(*pgd)) {
-		pmd_t *page = get_pmd_fast();
-		
-		if (!page)
-			return get_pmd_slow(pgd, address);
-		pgd_set(pgd, page);
-		return page + address;
-	}
-	if (pgd_bad(*pgd)) {
-		__bad_pmd(pgd);
-		return NULL;
-	}
-	return (pmd_t *) pgd_page(*pgd) + address;
-}
-
-#define pte_alloc_kernel	pte_alloc
-#define pmd_alloc_kernel	pmd_alloc
 
 extern int do_check_pgt_cache(int, int);
 
diff -urN linux-2.4.4-pre3/include/asm-alpha/pgtable.h linux/include/asm-alpha/pgtable.h
--- linux-2.4.4-pre3/include/asm-alpha/pgtable.h	Sun Dec  3 17:45:20 2000
+++ linux/include/asm-alpha/pgtable.h	Mon Dec  3 22:35:23 2001
@@ -59,11 +59,6 @@
 #define _PAGE_FOW	0x0004	/* used for page protection (fault on write) */
 #define _PAGE_FOE	0x0008	/* used for page protection (fault on exec) */
 #define _PAGE_ASM	0x0010
-#if defined(CONFIG_ALPHA_EV6) && !defined(CONFIG_SMP)
-#define _PAGE_MBE	0x0080	/* MB disable bit for EV6.  */
-#else
-#define _PAGE_MBE	0x0000
-#endif
 #define _PAGE_KRE	0x0100	/* xxx - see below on the "accessed" bit */
 #define _PAGE_URE	0x0200	/* xxx */
 #define _PAGE_KWE	0x1000	/* used to do the dirty bit in software */
@@ -90,20 +85,19 @@
 #define _PFN_MASK	0xFFFFFFFF00000000
 
 #define _PAGE_TABLE	(_PAGE_VALID | __DIRTY_BITS | __ACCESS_BITS)
-#define _PAGE_CHG_MASK	(_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS | _PAGE_MBE)
+#define _PAGE_CHG_MASK	(_PFN_MASK | __DIRTY_BITS | __ACCESS_BITS)
 
 /*
- * All the normal masks have the "page accessed" bits on, as any time they
- * are used, the page is accessed.  They are cleared only by the page-out
- * routines. 
+ * All the normal masks have the "page accessed" bits on, as any time they are used,
+ * the page is accessed. They are cleared only by the page-out routines
  */
 #define PAGE_NONE	__pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE)
 #define PAGE_SHARED	__pgprot(_PAGE_VALID | __ACCESS_BITS)
 #define PAGE_COPY	__pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
 #define PAGE_READONLY	__pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
-#define PAGE_KERNEL	__pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE | _PAGE_MBE)
+#define PAGE_KERNEL	__pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE)
 
-#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_MBE | (x))
+#define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x))
 
 #define _PAGE_P(x) _PAGE_NORMAL((x) | (((x) & _PAGE_FOW)?0:_PAGE_FOW))
 #define _PAGE_S(x) _PAGE_NORMAL(x)
@@ -195,7 +189,6 @@
  * Conversion functions:  convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
-
 #define mk_pte(page, pgprot)						\
 ({									\
 	pte_t pte;							\
@@ -206,7 +199,7 @@
 })
 
 extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
-{ pte_t pte; pte_val(pte) = (PHYS_TWIDDLE(physpage) << (32-PAGE_SHIFT)) | (pgprot_val(pgprot) & ~_PAGE_MBE); return pte; }
+{ pte_t pte; pte_val(pte) = (PHYS_TWIDDLE(physpage) << (32-PAGE_SHIFT)) | pgprot_val(pgprot); return pte; }
 
 extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
diff -urN linux-2.4.4-pre3/include/asm-alpha/semaphore.h linux/include/asm-alpha/semaphore.h
--- linux-2.4.4-pre3/include/asm-alpha/semaphore.h	Fri Mar  2 11:12:07 2001
+++ linux/include/asm-alpha/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -13,6 +13,7 @@
 #include <asm/atomic.h>
 #include <asm/compiler.h>	/* __builtin_expect */
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 #define DEBUG_SEMAPHORE 0
 #define DEBUG_RW_SEMAPHORE 0
@@ -223,151 +224,6 @@
 }
 #endif
 
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and
- * lots of processes.  BIAS must be chosen such that subtracting
- * BIAS once per CPU will result in the int remaining
- * negative.
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *	      -ben
- *
- * Once we start supporting machines with more than 128 CPUs,
- * we should go for using a 64bit atomic type instead of 32bit
- * as counter. We shall probably go for bias 0x80000000 then,
- * so that single sethi can set it.
- *
- *	      -jj
- */
-
-#define RW_LOCK_BIAS		0x01000000
-
-struct rw_semaphore {
-	atomic_t		count;
-	/* bit 0 means read bias granted;
-	   bit 1 means write bias granted.  */
-	unsigned		granted;
-	wait_queue_head_t	wait;
-	wait_queue_head_t	write_bias_wait;
-#if WAITQUEUE_DEBUG
-	long			__magic;
-	atomic_t		readers;
-	atomic_t		writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT	, ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT	/* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count)					\
-	{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait)		\
-	  __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) \
-	__DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) \
-	__DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) \
-	__DECLARE_RWSEM_GENERIC(name, 0)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	atomic_set (&sem->count, RW_LOCK_BIAS);
-	sem->granted = 0;
-	init_waitqueue_head(&sem->wait);
-	init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-	atomic_set(&sem->readers, 0);
-	atomic_set(&sem->writers, 0);
-#endif
-}
-
-extern void down_read(struct rw_semaphore *);
-extern void down_write(struct rw_semaphore *);
-extern void up_read(struct rw_semaphore *);
-extern void up_write(struct rw_semaphore *);
-extern void __down_read_failed(struct rw_semaphore *, int);
-extern void __down_write_failed(struct rw_semaphore *, int);
-extern void __rwsem_wake(struct rw_semaphore *, int);
-
-static inline void __down_read(struct rw_semaphore *sem)
-{
-	long count = atomic_dec_return(&sem->count);
-	if (__builtin_expect(count < 0, 0))
-		__down_read_failed(sem, count);
-}
-
-static inline void __down_write(struct rw_semaphore *sem)
-{
-	long count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-	if (__builtin_expect(count != 0, 0))
-		__down_write_failed(sem, count);
-}
-
-/* When a reader does a release, the only significant case is when there
-   was a writer waiting, and we've bumped the count to 0, then we must
-   wake the writer up.  */
-
-static inline void __up_read(struct rw_semaphore *sem)
-{
-	long count;
-	mb();
-	count = atomic_inc_return(&sem->count);
-	if (__builtin_expect(count == 0, 0))
-		__rwsem_wake(sem, 0);
-}
-
-/* Releasing the writer is easy -- just release it and wake up
-   any sleepers.  */
-
-static inline void __up_write(struct rw_semaphore *sem)
-{
-	long count, wake;
-	mb();
-	count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-
-	/* Only do the wake if we were, but are no longer, negative.  */
-	wake = ((int)(count - RW_LOCK_BIAS) < 0) && count >= 0;
-	if (__builtin_expect(wake, 0))
-		__rwsem_wake(sem, count);
-}
-
-#if !WAITQUEUE_DEBUG && !DEBUG_RW_SEMAPHORE
-extern inline void down_read(struct rw_semaphore *sem)
-{
-	__down_read(sem);
-}
-extern inline void down_write(struct rw_semaphore *sem)
-{
-	__down_write(sem);
-}
-extern inline void up_read(struct rw_semaphore *sem)
-{
-	__up_read(sem);
-}
-extern inline void up_write(struct rw_semaphore *sem)
-{
-	__up_write(sem);
-}
 #endif
 
 #endif
diff -urN linux-2.4.4-pre3/include/asm-arm/semaphore.h linux/include/asm-arm/semaphore.h
--- linux-2.4.4-pre3/include/asm-arm/semaphore.h	Sun Feb 13 10:47:01 2000
+++ linux/include/asm-arm/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -7,6 +7,7 @@
 #include <linux/linkage.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 #include <asm/atomic.h>
 #include <asm/proc/locks.h>
@@ -122,135 +123,6 @@
 #endif
 
 	__up_op(sem, __up_wakeup);
-}
-
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *              -ben
- */
-struct rw_semaphore {
-	atomic_t                count;
-	volatile unsigned char  write_bias_granted;
-	volatile unsigned char  read_bias_granted;
-	volatile unsigned char  pad1;
-	volatile unsigned char  pad2;
-	wait_queue_head_t       wait;
-	wait_queue_head_t	write_bias_wait;
-#if WAITQUEUE_DEBUG
-	long			__magic;
-	atomic_t		readers;
-	atomic_t		writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT	, ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT	/* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-	__WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-	__SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-	atomic_set(&sem->count, RW_LOCK_BIAS);
-	sem->read_bias_granted = 0;
-	sem->write_bias_granted = 0;
-	init_waitqueue_head(&sem->wait);
-	init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-	atomic_set(&sem->readers, 0);
-	atomic_set(&sem->writers, 0);
-#endif
-}
-
-extern struct rw_semaphore *__down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *__down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *__rwsem_wake(struct rw_semaphore *sem);
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-	__down_op_read(sem, __down_read_failed);
-#if WAITQUEUE_DEBUG
-	if (sem->write_bias_granted)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-	__down_op_write(sem, __down_write_failed);
-#if WAITQUEUE_DEBUG
-	if (atomic_read(&sem->writers))
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (sem->read_bias_granted)
-		BUG();
-	if (sem->write_bias_granted)
-		BUG();
-	atomic_inc(&sem->writers);
-#endif
-}
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	if (sem->write_bias_granted)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_dec(&sem->readers);
-#endif
-	__up_op_read(sem, __rwsem_wake);
-}
-
-extern inline void up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	if (sem->read_bias_granted)
-		BUG();
-	if (sem->write_bias_granted)
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (atomic_read(&sem->writers) != 1)
-		BUG();
-	atomic_dec(&sem->writers);
-#endif
-	__up_op_write(sem, __rwsem_wake);
 }
 
 #endif
diff -urN linux-2.4.4-pre3/include/asm-cris/semaphore.h linux/include/asm-cris/semaphore.h
--- linux-2.4.4-pre3/include/asm-cris/semaphore.h	Thu Feb  8 16:32:44 2001
+++ linux/include/asm-cris/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -9,6 +9,7 @@
 
 #include <linux/wait.h>
 #include <linux/spinlock.h>
+#include <linux/rwsem.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -155,167 +156,6 @@
 	if(wakeup) {
 		__up(sem);
 	}
-}
-
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *              -ben
- */
-
-struct rw_semaphore {
-        atomic_t                count;
-	/* bit 0 means read bias granted;
-	   bit 1 means write bias granted.  */
-        unsigned granted;
-        wait_queue_head_t       wait;
-        wait_queue_head_t       write_bias_wait;
-#if WAITQUEUE_DEBUG
-        long                    __magic;
-        atomic_t                readers;
-        atomic_t                writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT      , ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT      /* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-        __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-        __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-        struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-        atomic_set(&sem->count, RW_LOCK_BIAS);
-        sem->granted = 0;
-        init_waitqueue_head(&sem->wait);
-        init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-        sem->__magic = (long)&sem->__magic;
-        atomic_set(&sem->readers, 0);
-        atomic_set(&sem->writers, 0);
-#endif
-}
-
-/* The expensive part is outlined.  */
-extern void __down_read(struct rw_semaphore *sem, int count);
-extern void __down_write(struct rw_semaphore *sem, int count);
-extern void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers);
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-        int count;
-
-#if WAITQUEUE_DEBUG
-        CHECK_MAGIC(sem->__magic);
-#endif
-
-        count = atomic_dec_return(&sem->count);
-        if (count < 0) {
-                __down_read(sem, count);
-        }
-        mb();
-
-#if WAITQUEUE_DEBUG
-        if (sem->granted & 2)
-                BUG();
-        if (atomic_read(&sem->writers))
-                BUG();
-        atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-        int count;
-
-#if WAITQUEUE_DEBUG
-        CHECK_MAGIC(sem->__magic);
-#endif
-
-        count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-        if (count) {
-                __down_write(sem, count);
-        }
-        mb();
-
-#if WAITQUEUE_DEBUG
-        if (atomic_read(&sem->writers))
-                BUG();
-        if (atomic_read(&sem->readers))
-                BUG();
-        if (sem->granted & 3)
-                BUG();
-        atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant case is when
-   there was a writer waiting, and we've bumped the count to 0: we must
-   wake the writer up.  */
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-        CHECK_MAGIC(sem->__magic);
-        if (sem->granted & 2)
-                BUG();
-        if (atomic_read(&sem->writers))
-                BUG();
-        atomic_dec(&sem->readers);
-#endif
-
-        mb();
-        if (atomic_inc_return(&sem->count) == 0)
-                __rwsem_wake(sem, 0);
-}
-
-/*
- * Releasing the writer is easy -- just release it and wake up any sleepers.
- */
-extern inline void up_write(struct rw_semaphore *sem)
-{
-        int count;
-
-#if WAITQUEUE_DEBUG
-        CHECK_MAGIC(sem->__magic);
-        if (sem->granted & 3)
-                BUG();
-        if (atomic_read(&sem->readers))
-                BUG();
-        if (atomic_read(&sem->writers) != 1)
-                BUG();
-        atomic_dec(&sem->writers);
-#endif
-
-        mb();
-        count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-        if (count - RW_LOCK_BIAS < 0 && count >= 0) {
-                /* Only do the wake if we're no longer negative.  */
-                __rwsem_wake(sem, count);
-        }
 }
 
 #endif
diff -urN linux-2.4.4-pre3/include/asm-i386/rwsem-spin.h linux/include/asm-i386/rwsem-spin.h
--- linux-2.4.4-pre3/include/asm-i386/rwsem-spin.h	Mon Dec  3 22:35:13 2001
+++ linux/include/asm-i386/rwsem-spin.h	Mon Dec  3 22:35:23 2001
@@ -18,8 +18,6 @@
 
 #ifdef __KERNEL__
 
-#define CONFIG_USING_SPINLOCK_BASED_RWSEM 1
-
 /*
  * the semaphore definition
  */
diff -urN linux-2.4.4-pre3/include/asm-i386/rwsem.h linux/include/asm-i386/rwsem.h
--- linux-2.4.4-pre3/include/asm-i386/rwsem.h	Mon Dec  3 22:35:13 2001
+++ linux/include/asm-i386/rwsem.h	Mon Dec  3 22:35:23 2001
@@ -1,4 +1,4 @@
-/* rwsem.h: R/W semaphores based on spinlocks
+/* rwsem.h: R/W semaphores optimised using i386 assembly
  *
  * Written by David Howells (dhowells@redhat.com).
  *
@@ -14,7 +14,6 @@
 
 #ifdef __KERNEL__
 
-#define __HAVE_ARCH_SPECIFIC_RWSEM_IMPLEMENTATION 1
 #ifdef CONFIG_X86_XADD
 #include <asm/rwsem-xadd.h> /* use XADD based semaphores if possible */
 #else
diff -urN linux-2.4.4-pre3/include/asm-ia64/ia32.h linux/include/asm-ia64/ia32.h
--- linux-2.4.4-pre3/include/asm-ia64/ia32.h	Mon Dec  3 22:35:13 2001
+++ linux/include/asm-ia64/ia32.h	Mon Dec  3 22:35:23 2001
@@ -355,7 +355,7 @@
 		(granularity << IA32_SEG_G)		       |       \
 		(((base >> 24) & 0xFF) << IA32_SEG_HIGH_BASE)) 
 
-#define IA32_IOBASE    0x2000000000000000 /* Virtual addres for I/O space */
+#define IA32_IOBASE    0x2000000000000000 /* Virtual address for I/O space */
 
 #define IA32_CR0       0x80000001      /* Enable PG and PE bits */
 #define IA32_CR4       0	       /* No architectural extensions */
diff -urN linux-2.4.4-pre3/include/asm-ia64/semaphore.h linux/include/asm-ia64/semaphore.h
--- linux-2.4.4-pre3/include/asm-ia64/semaphore.h	Mon Dec  3 22:35:13 2001
+++ linux/include/asm-ia64/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -7,6 +7,7 @@
  */
 
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 #include <asm/atomic.h>
 
@@ -116,208 +117,6 @@
 #endif
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
-}
-
-/*
- * rw mutexes (should that be mutices? =) -- throw rw spinlocks and
- * semaphores together, and this is what we end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer subtracts BIAS
- * ands gets 0 for the case of an uncontended lock.  Readers decrement
- * by 1 and see a positive value when uncontended, negative if there
- * are writers waiting (in which case it goes to sleep).  BIAS must be
- * chosen such that subtracting BIAS once per CPU will result either
- * in zero (uncontended case) or in a negative value (contention
- * case).  On the other hand, BIAS must be at least as big as the
- * number of processes in the system.
- *
- * On IA-64, we use a BIAS value of 0x100000000, which supports up to
- * 2 billion (2^31) processors and 4 billion processes.
- *
- * In terms of fairness, when there is heavy use of the lock, we want
- * to see the lock being passed back and forth between readers and
- * writers (like in a producer/consumer style of communication).
- *
- *	      -ben (with clarifications & IA-64 comments by davidm)
- */
-#define RW_LOCK_BIAS		0x100000000ul
-
-struct rw_semaphore {
-	volatile long		count;
-	volatile __u8		write_bias_granted;
-	volatile __u8		read_bias_granted;
-	__u16			pad1;
-	__u32			pad2;
-	wait_queue_head_t	wait;
-	wait_queue_head_t	write_bias_wait;
-#if WAITQUEUE_DEBUG
-	long			__magic;
-	atomic_t		readers;
-	atomic_t		writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-# define __RWSEM_DEBUG_INIT	, ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-# define __RWSEM_DEBUG_INIT
-#endif
-
-#define __RWSEM_INITIALIZER(name,count)						\
-{										\
-	(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),	\
-	__WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait)			\
-	__SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT				\
-}
-
-#define __DECLARE_RWSEM_GENERIC(name,count)					\
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name)			__DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name)		__DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS - 1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name)	__DECLARE_RWSEM_GENERIC(name, 0)
-
-extern void __down_read_failed (struct rw_semaphore *sem, long count);
-extern void __down_write_failed (struct rw_semaphore *sem, long count);
-extern void __rwsem_wake (struct rw_semaphore *sem, long count);
-
-static inline void
-init_rwsem (struct rw_semaphore *sem)
-{
-	sem->count = RW_LOCK_BIAS;
-	sem->read_bias_granted = 0;
-	sem->write_bias_granted = 0;
-	init_waitqueue_head(&sem->wait);
-	init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-	atomic_set(&sem->readers, 0);
-	atomic_set(&sem->writers, 0);
-#endif
-}
-
-static inline void
-down_read (struct rw_semaphore *sem)
-{
-	long count;
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
-	count = ia64_fetch_and_add(-1, &sem->count);
-	if (count < 0)
-		__down_read_failed(sem, count);
-
-#if WAITQUEUE_DEBUG
-	if (sem->write_bias_granted)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_inc(&sem->readers);
-#endif
-}
-
-static inline void
-down_write (struct rw_semaphore *sem)
-{
-	long old_count, new_count;
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
-	do {
-		old_count = sem->count;
-		new_count = old_count - RW_LOCK_BIAS;
-	} while (cmpxchg_acq(&sem->count, old_count, new_count) != old_count);
-
-	if (new_count != 0)
-		__down_write_failed(sem, new_count);
-#if WAITQUEUE_DEBUG
-	if (atomic_read(&sem->writers))
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (sem->read_bias_granted)
-		BUG();
-	if (sem->write_bias_granted)
-		BUG();
-	atomic_inc(&sem->writers);
-#endif
-}
-
-/*
- * When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-static inline void
-__up_read (struct rw_semaphore *sem)
-{
-	long count;
-
-	count = ia64_fetch_and_add(1, &sem->count);
-	if (count == 0)
-		/*
-		 * Other processes are blocked already; resolve
-		 * contention by letting either a writer or a reader
-		 * proceed...
-		 */
-		__rwsem_wake(sem, count);
-}
-
-/*
- * Releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-static inline void
-__up_write (struct rw_semaphore *sem)
-{
-	long old_count, new_count;
-
-	do {
-		old_count = sem->count;
-		new_count = old_count + RW_LOCK_BIAS;
-	} while (cmpxchg_rel(&sem->count, old_count, new_count) != old_count);
-
-	/*
-	 * Note: new_count <u RW_LOCK_BIAS <=> old_count < 0 && new_count >= 0.
-	 *	 (where <u is "unsigned less-than").
-	 */
-	if ((unsigned long) new_count < RW_LOCK_BIAS)
-		/* someone is blocked already, resolve contention... */
-		__rwsem_wake(sem, new_count);
-}
-
-static inline void
-up_read (struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	if (sem->write_bias_granted)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_dec(&sem->readers);
-#endif
-	__up_read(sem);
-}
-
-static inline void
-up_write (struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	if (sem->read_bias_granted)
-		BUG();
-	if (sem->write_bias_granted)
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (atomic_read(&sem->writers) != 1)
-		BUG();
-	atomic_dec(&sem->writers);
-#endif
-	__up_write(sem);
 }
 
 #endif /* _ASM_IA64_SEMAPHORE_H */
diff -urN linux-2.4.4-pre3/include/asm-m68k/semaphore.h linux/include/asm-m68k/semaphore.h
--- linux-2.4.4-pre3/include/asm-m68k/semaphore.h	Mon Jan 31 10:32:53 2000
+++ linux/include/asm-m68k/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -8,6 +8,7 @@
 #include <linux/linkage.h>
 #include <linux/wait.h>
 #include <linux/spinlock.h>
+#include <linux/rwsem.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -185,201 +186,6 @@
 		: "memory");
 }
 
-
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * m68k version by Roman Zippel
- */
-
-struct rw_semaphore {
-	atomic_t		count;
-	volatile unsigned char	write_bias_granted;
-	volatile unsigned char	read_bias_granted;
-	volatile unsigned char	pad1;
-	volatile unsigned char	pad2;
-	wait_queue_head_t	wait;
-	wait_queue_head_t	write_bias_wait;
-#if WAITQUEUE_DEBUG
-	long			__magic;
-	atomic_t		readers;
-	atomic_t		writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT	, ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT	/* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-	__WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-	__SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-	atomic_set(&sem->count, RW_LOCK_BIAS);
-	sem->read_bias_granted = 0;
-	sem->write_bias_granted = 0;
-	init_waitqueue_head(&sem->wait);
-	init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-	atomic_set(&sem->readers, 0);
-	atomic_set(&sem->writers, 0);
-#endif
-}
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-	register struct rw_semaphore *__sem __asm__ ("%a1") = sem;
-
-#if WAITQUEUE_DEBUG
-	if (sem->__magic != (long)&sem->__magic)
-		BUG();
-#endif
-	__asm__ __volatile__(
-		"| atomic down_read operation\n\t"
-		"subql #1,%0@\n\t"
-		"jmi 2f\n"
-		"1:\n"
-		".section .text.lock,\"ax\"\n"
-		".even\n"
-		"2:\n\t"
-		"pea 1b\n\t"
-		"jbra __down_read_failed\n"
-		".previous"
-		: /* no outputs */
-		: "a" (__sem)
-		: "memory");
-#if WAITQUEUE_DEBUG
-	if (sem->write_bias_granted)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-	register struct rw_semaphore *__sem __asm__ ("%a1") = sem;
-
-#if WAITQUEUE_DEBUG
-	if (sem->__magic != (long)&sem->__magic)
-		BUG();
-#endif
-	__asm__ __volatile__(
-		"| atomic down_write operation\n\t"
-		"subl %1,%0@\n\t"
-		"jne 2f\n"
-		"1:\n"
-		".section .text.lock,\"ax\"\n"
-		".even\n"
-		"2:\n\t"
-		"pea 1b\n\t"
-		"jbra __down_write_failed\n"
-		".previous"
-		: /* no outputs */
-		: "a" (__sem), "id" (RW_LOCK_BIAS)
-		: "memory");
-#if WAITQUEUE_DEBUG
-	if (atomic_read(&sem->writers))
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (sem->read_bias_granted)
-		BUG();
-	if (sem->write_bias_granted)
-		BUG();
-	atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-extern inline void __up_read(struct rw_semaphore *sem)
-{
-	register struct rw_semaphore *__sem __asm__ ("%a1") = sem;
-
-	__asm__ __volatile__(
-		"| atomic up_read operation\n\t"
-		"addql #1,%0@\n\t"
-		"jeq 2f\n"
-		"1:\n"
-		".section .text.lock,\"ax\"\n"
-		".even\n"
-		"2:\n\t"
-		"pea 1b\n\t"
-		"jbra __rwsem_wake\n"
-		".previous"
-		: /* no outputs */
-		: "a" (__sem)
-		: "memory");
-}
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	if (sem->write_bias_granted)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_dec(&sem->readers);
-#endif
-	__up_read(sem);
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-extern inline void __up_write(struct rw_semaphore *sem)
-{
-	register struct rw_semaphore *__sem __asm__ ("%a1") = sem;
-
-	__asm__ __volatile__(
-		"| atomic up_write operation\n\t"
-		"addl %1,%0@\n\t"
-		"jcs 2f\n"
-		"1:\n"
-		".section .text.lock,\"ax\"\n"
-		".even\n"
-		"2:\n\t"
-		"pea 1b\n\t"
-		"jbra __rwsem_wake\n"
-		".previous"
-		: /* no outputs */
-		: "a" (__sem), "id" (RW_LOCK_BIAS)
-		: "memory");
-}
-
-extern inline void up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	if (sem->read_bias_granted)
-		BUG();
-	if (sem->write_bias_granted)
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (atomic_read(&sem->writers) != 1)
-		BUG();
-	atomic_dec(&sem->writers);
-#endif
-	__up_write(sem);
-}
 #endif /* __ASSEMBLY__ */
 
 #endif
diff -urN linux-2.4.4-pre3/include/asm-mips/bootinfo.h linux/include/asm-mips/bootinfo.h
--- linux-2.4.4-pre3/include/asm-mips/bootinfo.h	Tue Jul 11 11:15:02 2000
+++ linux/include/asm-mips/bootinfo.h	Mon Dec  3 22:35:23 2001
@@ -1,16 +1,13 @@
-/* $Id: bootinfo.h,v 1.11 2000/03/06 11:14:32 raiko Exp $
- *
- * bootinfo.h -- Definition of the Linux/MIPS boot information structure
- *
- * Copyright (C) 1995, 1996 by Ralf Baechle, Andreas Busse,
- *                             Stoned Elipot and Paul M. Antoine.
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
+ *
+ * Copyright (C) 1995, 1996 by Ralf Baechle, Andreas Busse,
+ *                             Stoned Elipot and Paul M. Antoine.
  */
-#ifndef __ASM_MIPS_BOOTINFO_H
-#define __ASM_MIPS_BOOTINFO_H
+#ifndef _ASM_BOOTINFO_H
+#define _ASM_BOOTINFO_H
 
 /*
  * Values for machgroup
@@ -105,8 +102,9 @@
  * Valid machtype for group NEC DDB
  */
 #define MACH_NEC_DDB5074	 0	/* NEC DDB Vrc-5074 */
+#define MACH_NEC_DDB5476         1      /* NEC DDB Vrc-5476 */
 
-#define GROUP_NEC_DDB_NAMES { "Vrc-5074" }
+#define GROUP_NEC_DDB_NAMES { "Vrc-5074", "Vrc-5476"}
 
 /*
  * Valid machtype for group BAGET
diff -urN linux-2.4.4-pre3/include/asm-mips/it8172/it8172.h linux/include/asm-mips/it8172/it8172.h
--- linux-2.4.4-pre3/include/asm-mips/it8172/it8172.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/it8172/it8172.h	Mon Dec  3 22:35:23 2001
@@ -0,0 +1,406 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	IT8172 system controller defines.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __IT8172__H__
+#define __IT8172__H__
+
+#include <asm/addrspace.h>
+
+#define IT8172_BASE			0x18000000	
+#define IT8172_PCI_IO_BASE		0x14000000
+#define IT8172_PCI_MEM_BASE		0x10000000
+
+// System registers offsets from IT8172_BASE
+#define IT_CMFPCR			0x0
+#define IT_DSRR				0x2
+#define IT_PCDCR			0x4
+#define IT_SPLLCR			0x6
+#define IT_CIDR				0x10
+#define IT_CRNR				0x12
+#define IT_CPUTR			0x14
+#define IT_CTCR				0x16
+#define IT_SDPR				0xF0
+
+// Power management register offset from IT8172_PCI_IO_BASE
+// Power Management Device Standby Register
+#define IT_PM_DSR		0x15800
+
+#define IT_PM_DSR_TMR0SB	0x0001
+#define IT_PM_DSR_TMR1SB	0x0002
+#define IT_PM_DSR_CIR0SB	0x0004
+#define IT_PM_DSR_CIR1SB	0x0008
+#define IT_PM_DSR_SCR0SB	0x0010
+#define IT_PM_DSR_SCR1SB	0x0020
+#define IT_PM_DSR_PPSB		0x0040
+#define IT_PM_DSR_I2CSB		0x0080
+#define IT_PM_DSR_UARTSB	0x0100
+#define IT_PM_DSR_IDESB		0x0200
+#define IT_PM_DSR_ACSB		0x0400
+#define IT_PM_DSR_M68KSB	0x0800
+
+// Power Management PCI Device Software Reset Register
+#define IT_PM_PCISR             0x15802
+
+#define IT_PM_PCISR_IDESR       0x0001
+#define IT_PM_PCISR_CDMASR      0x0002
+#define IT_PM_PCISR_USBSR       0x0004
+#define IT_PM_PCISR_DMASR       0x0008
+#define IT_PM_PCISR_ACSR        0x0010
+#define IT_PM_PCISR_MEMSR       0x0020
+#define IT_PM_PCISR_68KSR       0x0040
+
+
+// PCI Configuration address and data register offsets
+// from IT8172_BASE
+#define IT_CONFADDR			0x4000
+#define IT_BUSNUM_SHF                   16
+#define IT_DEVNUM_SHF                   11
+#define IT_FUNCNUM_SHF                  8
+#define IT_REGNUM_SHF                   2
+
+#define IT_CONFDATA			0x4004
+
+// PCI configuration header common register offsets
+#define IT_VID				0x00
+#define IT_DID				0x02
+#define IT_PCICMD			0x04
+#define IT_PCISTS			0x06
+#define IT_RID				0x08
+#define IT_CLASSC			0x09
+#define IT_HEADT			0x0E
+#define IT_SERIRQC			0x49
+
+// PCI to Internal/LPC Bus Bridge configuration header register offset
+#define IT_P2I_BCR				0x4C
+#define IT_P2I_D0IOSC				0x50 
+#define IT_P2I_D1IOSC				0x54
+#define IT_P2I_D2IOSC				0x58 
+#define IT_P2I_D3IOSC				0x5C 
+#define IT_P2I_D4IOSC				0x60 
+#define IT_P2I_D5IOSC				0x64 
+#define IT_P2I_D6IOSC				0x68 
+#define IT_P2I_D7IOSC				0x6C 
+#define IT_P2I_D8IOSC				0x70 
+#define IT_P2I_D9IOSC				0x74 
+#define IT_P2I_D10IOSC				0x78 
+#define IT_P2I_D11IOSC				0x7C 
+
+// Memory controller register offsets from IT8172_BASE
+#define IT_MC_SDRMR					0x1000
+#define IT_MC_SDRTR					0x1004
+#define IT_MC_MCR					0x1008
+#define IT_MC_SDTYPE					0x100C
+#define IT_MC_WPBA					0x1010
+#define IT_MC_WPTA					0x1014
+#define IT_MC_HATR					0x1018
+#define IT_MC_PCICR					0x101C
+
+// Flash/ROM control register offsets from IT8172_BASE
+#define IT_FC_BRCR					0x2000
+#define IT_FC_FCR					0x2004
+#define IT_FC_DCR					0x2008
+
+// M68K interface bridge configuration header register offset
+#define IT_M68K_MBCSR					0x54
+#define IT_M68K_TMR					0x58
+#define IT_M68K_BCR					0x5C
+#define IT_M68K_BSR					0x5D
+#define IT_M68K_DTR					0x5F
+
+// Register offset from IT8172_PCI_IO_BASE 
+// These registers are accessible through 8172 PCI IO window.
+
+// INTC 
+#define IT_INTC_BASE				0x10000
+#define IT_INTC_LBDNIRR				0x10000
+#define IT_INTC_LBDNIMR				0x10002
+#define IT_INTC_LBDNITR				0x10004
+#define IT_INTC_LBDNIAR				0x10006
+#define IT_INTC_LPCNIRR				0x10010
+#define IT_INTC_LPCNIMR				0x10012
+#define IT_INTC_LPCNITR				0x10014
+#define IT_INTC_LPCNIAR				0x10016
+#define IT_INTC_PDNIRR				0x10020
+#define IT_INTC_PDNIMR				0x10022
+#define IT_INTC_PDNITR				0x10024
+#define IT_INTC_PDNIAR				0x10026
+#define IT_INTC_UMNIRR				0x10030
+#define IT_INTC_UMNITR				0x10034
+#define IT_INTC_UMNIAR				0x10036
+#define IT_INTC_TYPER				0x107FE
+
+// IT8172 PCI device number
+#define IT_C2P_DEVICE				0
+#define IT_AUDIO_DEVICE				1
+#define IT_DMAC_DEVICE				1
+#define IT_CDMAC_DEVICE				1
+#define IT_USB_DEVICE				1
+#define IT_P2I_DEVICE				1
+#define IT_IDE_DEVICE				1
+#define IT_M68K_DEVICE				1
+
+// IT8172 PCI function number
+#define IT_C2P_FUNCION				0
+#define IT_AUDIO_FUNCTION			0
+#define IT_DMAC_FUNCTION			1
+#define IT_CDMAC_FUNCTION			2
+#define IT_USB_FUNCTION				3
+#define IT_P2I_FUNCTION				4
+#define IT_IDE_FUNCTION				5
+#define IT_M68K_FUNCTION			6
+
+// IT8172 GPIO
+#define IT_GPADR				0x13800
+#define IT_GPBDR				0x13808
+#define IT_GPCDR				0x13810
+#define IT_GPACR				0x13802
+#define IT_GPBCR				0x1380A
+#define IT_GPCCR				0x13812
+#define IT_GPAICR				0x13804
+#define IT_GPBICR				0x1380C
+#define IT_GPCICR				0x13814
+#define IT_GPAISR				0x13806
+#define IT_GPBISR				0x1380E
+#define IT_GPCISR				0x13816
+#define IT_GCR					0x13818
+
+// IT8172 RTC
+#define IT_RTC_BASE				0x14800
+#define IT_RTC_RIR0				0x00
+#define IT_RTC_RTR0				0x01
+#define IT_RTC_RIR1				0x02
+#define IT_RTC_RTR1				0x03
+#define IT_RTC_RIR2				0x04
+#define IT_RTC_RTR2				0x05
+#define IT_RTC_RCTR				0x08
+#define IT_RTC_RA				0x0A
+#define IT_RTC_RB				0x0B
+#define IT_RTC_RC				0x0C
+#define IT_RTC_RD				0x0D
+
+#define RTC_SEC_INDEX				0x00
+#define RTC_MIN_INDEX				0x02
+#define RTC_HOUR_INDEX				0x04
+#define RTC_DAY_INDEX				0x06
+#define RTC_DATE_INDEX				0x07
+#define RTC_MONTH_INDEX				0x08
+#define RTC_YEAR_INDEX				0x09
+
+// IT8172 internal device registers
+#define IT_TIMER_BASE				0x10800
+#define IT_CIR0_BASE				0x11000
+#define IT_UART_BASE				0x11800
+#define IT_SCR0_BASE				0x12000
+#define IT_SCR1_BASE				0x12800
+#define IT_PP_BASE				0x13000
+#define IT_I2C_BASE				0x14000
+#define IT_CIR1_BASE				0x15000
+
+// IT8172 Smart Card Reader offsets from IT_SCR*_BASE
+#define IT_SCR_SFR				0x08
+#define IT_SCR_SCDR				0x09
+
+// IT8172 IT_SCR_SFR bit definition & mask
+#define	IT_SCR_SFR_GATE_UART			0x40
+#define	IT_SCR_SFR_GATE_UART_BIT		6
+#define IT_SCR_SFR_GATE_UART_OFF		0
+#define	IT_SCR_SFR_GATE_UART_ON			1
+#define	IT_SCR_SFR_FET_CHARGE			0x30
+#define	IT_SCR_SFR_FET_CHARGE_BIT		4
+#define IT_SCR_SFR_FET_CHARGE_3_3_US		3
+#define IT_SCR_SFR_FET_CHARGE_13_US		2
+#define IT_SCR_SFR_FET_CHARGE_53_US		1
+#define IT_SCR_SFR_FET_CHARGE_213_US		0
+#define	IT_SCR_SFR_CARD_FREQ			0x0C
+#define	IT_SCR_SFR_CARD_FREQ_BIT		2
+#define IT_SCR_SFR_CARD_FREQ_STOP		3
+#define IT_SCR_SFR_CARD_FREQ_3_5_MHZ		0
+#define IT_SCR_SFR_CARD_FREQ_7_1_MHZ		2
+#define IT_SCR_SFR_CARD_FREQ_96_DIV_MHZ		1
+#define	IT_SCR_SFR_FET_ACTIVE			0x02
+#define	IT_SCR_SFR_FET_ACTIVE_BIT		1
+#define IT_SCR_SFR_FET_ACTIVE_INVERT		0
+#define IT_SCR_SFR_FET_ACTIVE_NONINVERT		1
+#define	IT_SCR_SFR_ENABLE			0x01
+#define	IT_SCR_SFR_ENABLE_BIT			0
+#define IT_SCR_SFR_ENABLE_OFF			0
+#define IT_SCR_SFR_ENABLE_ON			1
+
+// IT8172 IT_SCR_SCDR bit definition & mask
+#define	IT_SCR_SCDR_RESET_MODE			0x80
+#define	IT_SCR_SCDR_RESET_MODE_BIT		7
+#define	IT_SCR_SCDR_RESET_MODE_ASYNC		0
+#define IT_SCR_SCDR_RESET_MODE_SYNC		1
+#define	IT_SCR_SCDR_DIVISOR			0x7F
+#define	IT_SCR_SCDR_DIVISOR_BIT			0
+#define	IT_SCR_SCDR_DIVISOR_STOP_VAL_1		0x00
+#define	IT_SCR_SCDR_DIVISOR_STOP_VAL_2		0x01
+#define	IT_SCR_SCDR_DIVISOR_STOP_VAL_3		0x7F
+
+// IT8172 DMA
+#define IT_DMAC_BASE				0x16000
+#define IT_DMAC_BCAR0				0x00
+#define IT_DMAC_BCAR1				0x04
+#define IT_DMAC_BCAR2				0x08
+#define IT_DMAC_BCAR3				0x0C
+#define IT_DMAC_BCCR0				0x02
+#define IT_DMAC_BCCR1				0x06
+#define IT_DMAC_BCCR2				0x0a
+#define IT_DMAC_BCCR3				0x0e
+#define IT_DMAC_CR				0x10
+#define IT_DMAC_SR				0x12
+#define IT_DMAC_ESR				0x13
+#define IT_DMAC_RQR				0x14
+#define IT_DMAC_MR				0x16
+#define IT_DMAC_EMR				0x17
+#define IT_DMAC_MKR				0x18
+#define IT_DMAC_PAR0				0x20
+#define IT_DMAC_PAR1				0x22
+#define IT_DMAC_PAR2				0x24
+#define IT_DMAC_PAR3				0x26
+
+// IT8172 IDE
+#define IT_IDE_BASE				0x17800
+#define IT_IDE_STATUS				0x1F7
+
+// IT8172 Audio Controller
+#define IT_AC_BASE				0x17000
+#define	IT_AC_PCMOV				0x00
+#define IT_AC_FMOV				0x02
+#define	IT_AC_I2SV				0x04
+#define IT_AC_DRSS				0x06
+#define IT_AC_PCC				0x08
+#define IT_AC_PCDL				0x0A
+#define IT_AC_PCB1STA				0x0C
+#define IT_AC_PCB2STA				0x10
+#define IT_AC_CAPCC				0x14
+#define IT_AC_CAPCDL				0x16
+#define IT_AC_CAPB1STA				0x18
+#define IT_AC_CAPB2STA				0x1C
+#define IT_AC_CODECC				0x22
+#define IT_AC_I2SMC				0x24
+#define IT_AC_VS				0x26
+#define IT_AC_SRCS				0x28
+#define IT_AC_CIRCP				0x2A
+#define IT_AC_CIRDP				0x2C
+#define IT_AC_TM				0x4A
+#define IT_AC_PFDP				0x4C
+#define IT_AC_GC				0x54
+#define IT_AC_IMC				0x56
+#define IT_AC_ISC				0x5B
+#define IT_AC_OPL3SR				0x68
+#define IT_AC_OPL3DWDR				0x69
+#define IT_AC_OPL3AB1W				0x6A
+#define IT_AC_OPL3DW				0x6B
+#define IT_AC_BPDC				0x70
+
+// Audio : IT_AC_PCC bit definition & mask
+#define	PCC_SM					0x8000
+#define	PCC_SM_BIT				15
+#define	PCC_SM_STEREO				1
+#define PCC_SM_MONO				0
+
+#define	PCC_DF					0x4000
+#define PCC_DF_BIT				14
+#define	PCC_DF_8				0
+#define PCC_DF_16				1
+
+#define	PCC_CF					0x3000
+#define PCC_CF_BIT				12
+#define	PCC_CF_2				0
+#define PCC_CF_4				1
+#define PCC_CF_6				2
+
+#define PCC_SR					0x0F00
+#define PCC_SR_BIT				8
+#define	PCC_SR_5500				0
+#define	PCC_SR_8000				1
+#define	PCC_SR_9600				2
+#define	PCC_SR_11025				3
+#define	PCC_SR_16000				4
+#define	PCC_SR_19200				5
+#define	PCC_SR_22050				6
+#define	PCC_SR_32000				7
+#define	PCC_SR_38400				8
+#define	PCC_SR_44100				9
+#define	PCC_SR_48000				10
+
+#define PCC_CSP					0x0080
+#define PCC_CSP_BIT				7
+#define PCC_CSP_STOP				0
+#define PCC_CSP_STOP_NOW			1
+
+#define PCC_CP					0x0040
+#define	PCC_CP_BIT				6
+#define PCC_CP_NORMAL				0
+#define PCC_CP_PAUSE				1
+
+#define PCC_CA					0x0020
+#define PCC_CA_BIT				5
+#define PCC_CA_NO_START				0
+#define PCC_CA_START				1
+
+#define PCC_CB2L				0x0004
+#define PCC_CB2L_BIT				2
+#define PCC_CB2L_NO				0
+#define PCC_CB2L_YES				1
+
+#define PCC_CB1L				0x0002
+#define PCC_CB1L_BIT				1
+#define PCC_CB1L_NO				0
+#define PCC_CB1L_YES				1
+
+#define PCC_DE					0x0001
+#define PCC_DE_BIT				0
+#define PCC_DE_NOT_EMPTY			0
+#define PCC_DE_EMPTY				1
+
+// IT8172 Timer
+#define IT_TIMER_BASE				0x10800
+#define	TIMER_TCVR0				0x00
+#define TIMER_TRVR0				0x02
+#define	TIMER_TCR0				0x04
+#define TIMER_TIRR				0x06
+#define	TIMER_TCVR1				0x08
+#define TIMER_TRVR1				0x0A
+#define	TIMER_TCR1				0x0C
+#define TIMER_TIDR				0x0E
+
+
+#define IT_WRITE(ofs, data) *(volatile u32 *)KSEG1ADDR((IT8172_BASE+ofs)) = data
+#define IT_READ(ofs, data)  data = *(volatile u32 *)KSEG1ADDR((IT8172_BASE+ofs))
+
+#define IT_IO_WRITE(ofs, data) *(volatile u32 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs)) = data
+#define IT_IO_READ(ofs, data)  data = *(volatile u32 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs))
+
+#define IT_IO_WRITE16(ofs, data) *(volatile u16 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs)) = data
+#define IT_IO_READ16(ofs, data)  data = *(volatile u16 *)KSEG1ADDR((IT8172_PCI_IO_BASE+ofs))
+
+#endif
diff -urN linux-2.4.4-pre3/include/asm-mips/it8172/it8172_cir.h linux/include/asm-mips/it8172/it8172_cir.h
--- linux-2.4.4-pre3/include/asm-mips/it8172/it8172_cir.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/it8172/it8172_cir.h	Mon Dec  3 22:35:23 2001
@@ -0,0 +1,140 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	IT8172 Consumer IR port defines.
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define NUM_CIR_PORTS 2
+
+/* Master Control Register */
+#define CIR_RESET              0x1
+#define CIR_FIFO_CLEAR         0x2
+#define CIR_SET_FIFO_TL(x)     (((x)&0x3)<<2)
+#define CIR_ILE                0x10
+#define CIR_ILSEL              0x20
+
+/* Interrupt Enable Register */
+#define CIR_TLDLIE             0x1
+#define CIR_RDAIE              0x2
+#define CIR_RFOIE              0x4
+#define CIR_IEC                0x80
+
+/* Interrupt Identification Register */
+#define CIR_TLDLI              0x1
+#define CIR_RDAI               0x2
+#define CIR_RFOI               0x4
+#define CIR_NIP                0x80
+
+/* Carrier Frequency Register */
+#define CIR_SET_CF(x)          ((x)&0x1f)
+  #define CFQ_38_480           0xB       /* 38 KHz low, 480 KHz high */
+#define CIR_HCFS               0x20
+  #define CIR_SET_HS(x)        (((x)&0x1)<<5)
+    
+
+/* Receiver Control Register */
+#define CIR_SET_RXDCR(x)       ((x)&0x7)
+#define CIR_RXACT              0x8
+#define CIR_RXEND              0x10
+#define CIR_RDWOS              0x20
+  #define CIR_SET_RDWOS(x)     (((x)&0x1)<<5)
+#define CIR_RXEN               0x80
+
+/* Transmitter Control Register */
+#define CIR_SET_TXMPW(x)       ((x)&0x7)
+#define CIR_SET_TXMPM(x)       (((x)&0x3)<<3)
+#define CIR_TXENDF             0x20
+#define CIR_TXRLE              0x40
+
+/* Receiver FIFO Status Register */
+#define CIR_RXFBC_MASK         0x3f
+#define CIR_RXFTO              0x80
+
+/* Wakeup Code Length Register */
+#define CIR_SET_WCL            ((x)&0x3f)
+#define CIR_WCL_MASK(x)        ((x)&0x3f)
+
+/* Wakeup Power Control/Status Register */
+#define CIR_BTMON              0x2
+#define CIR_CIRON              0x4
+#define CIR_RCRST              0x10
+#define CIR_WCRST              0x20
+
+struct cir_port {
+	int port;
+	unsigned short baud_rate;
+	unsigned char fifo_tl;
+	unsigned char cfq;
+	unsigned char hcfs;
+	unsigned char rdwos;
+	unsigned char rxdcr;
+};
+
+struct it8172_cir_regs {
+	unsigned char dr;       /* data                        */
+	char pad;
+	unsigned char mstcr;    /* master control              */
+	char pad1;
+	unsigned char ier;      /* interrupt enable            */
+	char pad2;
+	unsigned char iir;      /* interrupt identification    */
+	char pad3;
+	unsigned char cfr;      /* carrier frequency           */
+	char pad4;
+	unsigned char rcr;      /* receiver control            */
+	char pad5;
+	unsigned char tcr;      /* transmitter control         */
+	char pad6;
+	char pad7;
+	char pad8;
+	unsigned char bdlr;     /* baud rate divisor low byte  */
+	char pad9;
+	unsigned char bdhr;     /* baud rate divisor high byte */
+	char pad10;
+	unsigned char tfsr;     /* tx fifo byte count          */
+	char pad11;
+	unsigned char rfsr;     /* rx fifo status              */
+	char pad12;
+	unsigned char wcl;      /* wakeup code length          */
+	char pad13;
+	unsigned char wcr;      /* wakeup code read/write      */
+	char pad14;
+	unsigned char wps;      /* wakeup power control/status */
+};
+
+int cir_port_init(struct cir_port *cir);
+extern void clear_fifo(struct cir_port *cir);
+extern void enable_receiver(struct cir_port *cir);
+extern void disable_receiver(struct cir_port *cir);
+extern void enable_rx_demodulation(struct cir_port *cir);
+extern void disable_rx_demodulation(struct cir_port *cir);
+extern void set_rx_active(struct cir_port *cir);
+extern void int_enable(struct cir_port *cir);
+extern void rx_int_enable(struct cir_port *cir);
+extern char get_int_status(struct cir_port *cir);
+extern int cir_get_rx_count(struct cir_port *cir);
+extern char cir_read_data(struct cir_port *cir);
diff -urN linux-2.4.4-pre3/include/asm-mips/it8172/it8172_dbg.h linux/include/asm-mips/it8172/it8172_dbg.h
--- linux-2.4.4-pre3/include/asm-mips/it8172/it8172_dbg.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/it8172/it8172_dbg.h	Mon Dec  3 22:35:23 2001
@@ -0,0 +1,38 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	Function prototypes for low level uart routines to 
+ *	directly access a 16550 uart.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/types.h>
+
+extern void putch(const unsigned char c);
+extern void puts(unsigned char *cp);
+extern void fputs(unsigned char *cp);
+extern void put64(uint64_t ul);
+extern void put32(unsigned u);
diff -urN linux-2.4.4-pre3/include/asm-mips/it8172/it8172_int.h linux/include/asm-mips/it8172/it8172_int.h
--- linux-2.4.4-pre3/include/asm-mips/it8172/it8172_int.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/it8172/it8172_int.h	Mon Dec  3 22:35:23 2001
@@ -0,0 +1,146 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	ITE 8172 Interrupt Numbering
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _MIPS_ITEINT_H
+#define _MIPS_ITEINT_H
+
+/*
+ * Here's the "strategy":
+ * We number the LPC serial irqs from 0 to 15,
+ * the local bus irqs from 16 to 31,
+ * the pci dev register interrupts from 32 to 47,
+ * and the non-maskable ints from 48 to 53.
+ */
+
+#define IT8172_LPC_IRQ_BASE  0    /* first LPC int number */
+#define IT8172_SERIRQ_0      (IT8172_LPC_IRQ_BASE + 0)
+#define IT8172_SERIRQ_1      (IT8172_LPC_IRQ_BASE + 1)
+#define IT8172_SERIRQ_2      (IT8172_LPC_IRQ_BASE + 2)
+#define IT8172_SERIRQ_3      (IT8172_LPC_IRQ_BASE + 3)
+#define IT8172_SERIRQ_4      (IT8172_LPC_IRQ_BASE + 4)
+#define IT8172_SERIRQ_5      (IT8172_LPC_IRQ_BASE + 5)
+#define IT8172_SERIRQ_6      (IT8172_LPC_IRQ_BASE + 6)
+#define IT8172_SERIRQ_7      (IT8172_LPC_IRQ_BASE + 7)
+#define IT8172_SERIRQ_8      (IT8172_LPC_IRQ_BASE + 8)
+#define IT8172_SERIRQ_9      (IT8172_LPC_IRQ_BASE + 9)
+#define IT8172_SERIRQ_10     (IT8172_LPC_IRQ_BASE + 10)
+#define IT8172_SERIRQ_11     (IT8172_LPC_IRQ_BASE + 11)
+#define IT8172_SERIRQ_12     (IT8172_LPC_IRQ_BASE + 12)
+#define IT8172_SERIRQ_13     (IT8172_LPC_IRQ_BASE + 13)
+#define IT8172_SERIRQ_14     (IT8172_LPC_IRQ_BASE + 14)
+#define IT8172_SERIRQ_15     (IT8172_LPC_IRQ_BASE + 15)
+
+#define IT8172_LB_IRQ_BASE  16   /* first local bus int number */
+#define IT8172_PPR_IRQ          (IT8172_LB_IRQ_BASE + 0) /* parallel port */
+#define IT8172_TIMER0_IRQ       (IT8172_LB_IRQ_BASE + 1)
+#define IT8172_TIMER1_IRQ       (IT8172_LB_IRQ_BASE + 2)
+#define IT8172_I2C_IRQ          (IT8172_LB_IRQ_BASE + 3)
+#define IT8172_GPIO_IRQ         (IT8172_LB_IRQ_BASE + 4)
+#define IT8172_CIR0_IRQ         (IT8172_LB_IRQ_BASE + 5)
+#define IT8172_CIR1_IRQ         (IT8172_LB_IRQ_BASE + 6)
+#define IT8172_UART_IRQ         (IT8172_LB_IRQ_BASE + 7)
+#define IT8172_SCR0_IRQ         (IT8172_LB_IRQ_BASE + 8)
+#define IT8172_SCR1_IRQ         (IT8172_LB_IRQ_BASE + 9)
+#define IT8172_RTC_IRQ          (IT8172_LB_IRQ_BASE + 10)
+#define IT8172_IOCHK_IRQ        (IT8172_LB_IRQ_BASE + 11)
+/* 12 - 15 reserved */
+
+/*
+ * Note here that the pci dev registers includes bits for more than
+ * just the pci devices.
+ */
+#define IT8172_PCI_DEV_IRQ_BASE  32   /* first pci dev irq */
+#define IT8172_AC97_IRQ          (IT8172_PCI_DEV_IRQ_BASE + 0)
+#define IT8172_MC68K_IRQ         (IT8172_PCI_DEV_IRQ_BASE + 1)
+#define IT8172_IDE_IRQ           (IT8172_PCI_DEV_IRQ_BASE + 2)
+#define IT8172_USB_IRQ           (IT8172_PCI_DEV_IRQ_BASE + 3)
+#define IT8172_BRIDGE_MASTER_IRQ (IT8172_PCI_DEV_IRQ_BASE + 4)
+#define IT8172_BRIDGE_TARGET_IRQ (IT8172_PCI_DEV_IRQ_BASE + 5)
+#define IT8172_PCI_INTA_IRQ      (IT8172_PCI_DEV_IRQ_BASE + 6)
+#define IT8172_PCI_INTB_IRQ      (IT8172_PCI_DEV_IRQ_BASE + 7)
+#define IT8172_PCI_INTC_IRQ      (IT8172_PCI_DEV_IRQ_BASE + 8)
+#define IT8172_PCI_INTD_IRQ      (IT8172_PCI_DEV_IRQ_BASE + 9)
+#define IT8172_S_INTA_IRQ        (IT8172_PCI_DEV_IRQ_BASE + 10)
+#define IT8172_S_INTB_IRQ        (IT8172_PCI_DEV_IRQ_BASE + 11)
+#define IT8172_S_INTC_IRQ        (IT8172_PCI_DEV_IRQ_BASE + 12)
+#define IT8172_S_INTD_IRQ        (IT8172_PCI_DEV_IRQ_BASE + 13)
+#define IT8172_CDMA_IRQ          (IT8172_PCI_DEV_IRQ_BASE + 14)
+#define IT8172_DMA_IRQ           (IT8172_PCI_DEV_IRQ_BASE + 15)
+
+#define IT8172_NMI_IRQ_BASE      48
+#define IT8172_SER_NMI_IRQ       (IT8172_NMI_IRQ_BASE + 0)
+#define IT8172_PCI_NMI_IRQ       (IT8172_NMI_IRQ_BASE + 1)
+#define IT8172_RTC_NMI_IRQ       (IT8172_NMI_IRQ_BASE + 2)
+#define IT8172_CPUIF_NMI_IRQ     (IT8172_NMI_IRQ_BASE + 3)
+#define IT8172_PMER_NMI_IRQ      (IT8172_NMI_IRQ_BASE + 4)
+#define IT8172_POWER_NMI_IRQ     (IT8172_NMI_IRQ_BASE + 5)
+
+/* Finally, let's move over here the mips cpu timer interrupt.
+ * This is more or less strictly for statistics.
+ */
+#define MIPS_CPU_TIMER_IRQ       (IT8172_NMI_IRQ_BASE + 6)
+
+#define IT8172_INT_END           MIPS_CPU_TIMER_IRQ
+
+/* 
+ * IT8172 Interrupt Controller Registers
+ */
+struct it8172_intc_regs {
+        volatile unsigned short lb_req;      /* offset 0 */
+        volatile unsigned short lb_mask;
+        volatile unsigned short lb_trigger;
+        volatile unsigned short lb_level;
+	unsigned char pad0[8];
+
+        volatile unsigned short lpc_req;     /* offset 0x10 */
+        volatile unsigned short lpc_mask;
+        volatile unsigned short lpc_trigger;
+        volatile unsigned short lpc_level;
+	unsigned char pad1[8];
+
+        volatile unsigned short pci_req;     /* offset 0x20 */
+        volatile unsigned short pci_mask;
+        volatile unsigned short pci_trigger;
+        volatile unsigned short pci_level;
+	unsigned char pad2[8];
+
+        volatile unsigned short nmi_req;     /* offset 0x30 */
+        volatile unsigned short nmi_mask;
+        volatile unsigned short nmi_trigger;
+        volatile unsigned short nmi_level;
+	unsigned char pad3[6];
+
+        volatile unsigned short nmi_redir;   /* offset 0x3E */
+	unsigned char pad4[0xBE];
+
+        volatile unsigned short intstatus;    /* offset 0xFE */
+};
+
+#endif /* _MIPS_ITEINT_H */
diff -urN linux-2.4.4-pre3/include/asm-mips/it8172/it8172_lpc.h linux/include/asm-mips/it8172/it8172_lpc.h
--- linux-2.4.4-pre3/include/asm-mips/it8172/it8172_lpc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/it8172/it8172_lpc.h	Mon Dec  3 22:35:23 2001
@@ -0,0 +1,29 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	IT8172 system controller defines.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
diff -urN linux-2.4.4-pre3/include/asm-mips/it8172/it8172_pci.h linux/include/asm-mips/it8172/it8172_pci.h
--- linux-2.4.4-pre3/include/asm-mips/it8172/it8172_pci.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/it8172/it8172_pci.h	Mon Dec  3 22:35:23 2001
@@ -0,0 +1,108 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ *	IT8172 system controller specific pci defines.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ *         	ppopov@mvista.com or support@mvista.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _8172PCI_H_
+#define _8172PCI_H_
+
+// PCI configuration space Type0
+#define	PCI_IDREG	0x00
+#define	PCI_CMDSTSREG	0x04
+#define	PCI_CLASSREG	0x08
+#define	PCI_BHLCREG	0x0C
+#define	PCI_BASE1REG	0x10
+#define	PCI_BASE2REG	0x14
+#define	PCI_BASE3REG	0x18
+#define	PCI_BASE4REG	0x1C
+#define	PCI_BASE5REG	0x20
+#define	PCI_BASE6REG	0x24
+#define	PCI_ROMBASEREG	0x30
+#define	PCI_INTRREG	0x3C
+
+// PCI configuration space Type1
+#define	PCI_BUSNOREG	0x18
+
+#define	IT_PCI_VENDORID(x)	((x) & 0xFFFF)
+#define	IT_PCI_DEVICEID(x)	(((x)>>16) & 0xFFFF)
+
+// Command register
+#define	PCI_CMD_IOEN		0x00000001
+#define	PCI_CMD_MEMEN		0x00000002
+#define	PCI_CMD_BUSMASTER	0x00000004
+#define	PCI_CMD_SPCYCLE		0x00000008
+#define	PCI_CMD_WRINV		0x00000010
+#define	PCI_CMD_VGASNOOP	0x00000020
+#define	PCI_CMD_PERR		0x00000040
+#define	PCI_CMD_WAITCTRL	0x00000080
+#define	PCI_CMD_SERR		0x00000100
+#define	PCI_CMD_FAST_BACKTOBACK	0x00000200
+
+// Status register
+#define	PCI_STS_66MHZ		0x00200000
+#define	PCI_STS_SUPPORT_UDF	0x00400000
+#define	PCI_STS_FAST_BACKTOBACK	0x00800000
+#define	PCI_STS_DATA_PERR	0x01000000
+#define	PCI_STS_DEVSEL0		0x02000000
+#define	PCI_STS_DEVSEL1		0x04000000
+#define	PCI_STS_SIG_TGTABORT	0x08000000
+#define	PCI_STS_RCV_TGTABORT	0x10000000
+#define	PCI_STS_RCV_MSTABORT	0x20000000
+#define	PCI_STS_SYSERR		0x40000000
+#define	PCI_STS_DETCT_PERR	0x80000000
+
+#define	IT_PCI_CLASS(x)		(((x)>>24) & 0xFF)
+#define	IT_PCI_SUBCLASS(x)		(((x)>>16) & 0xFF)
+#define	IT_PCI_INTERFACE(x)	(((x)>>8) & 0xFF)
+#define	IT_PCI_REVISION(x)		((x) & 0xFF)
+
+// PCI class code
+#define	PCI_CLASS_BRIDGE			0x06
+
+// bridge subclass
+#define	PCI_SUBCLASS_BRIDGE_HOST		0x00
+#define	PCI_SUBCLASS_BRIDGE_PCI			0x04
+
+// BHLCREG
+#define	IT_PCI_BIST(x)		(((x)>>24) & 0xFF)
+#define	IT_PCI_HEADERTYPE(x)	(((x)>>16) & 0xFF)
+#define	IT_PCI_LATENCYTIMER(x)	(((x)>>8) & 0xFF)
+#define	IT_PCI_CACHELINESIZE(x)	((x) & 0xFF)
+
+#define	PCI_MULTIFUNC	0x80
+
+// INTRREG
+#define	IT_PCI_MAXLAT(x)		(((x)>>24) & 0xFF)
+#define	IT_PCI_MINGNT(x)		(((x)>>16) & 0xFF)
+#define	IT_PCI_INTRPIN(x)		(((x)>>8) & 0xFF)
+#define	IT_PCI_INTRLINE(x)		((x) & 0xFF)
+
+#define	PCI_VENDOR_NEC	0x1033
+#define PCI_VENDOR_DEC	0x1101
+
+#endif // _8172PCI_H_
diff -urN linux-2.4.4-pre3/include/asm-mips/it8712.h linux/include/asm-mips/it8712.h
--- linux-2.4.4-pre3/include/asm-mips/it8712.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/it8712.h	Mon Dec  3 22:35:23 2001
@@ -0,0 +1,28 @@
+
+#ifndef __IT8712_H__
+#define __IT8712_H__
+
+#define LPC_BASE_ADDR	0x14000000
+
+// MB PnP configuration register 
+#define LPC_KEY_ADDR	0x1400002E
+#define LPC_DATA_ADDR	0x1400002F
+
+// Device LDN
+#define LDN_SERIAL1	0x01
+#define LDN_SERIAL2	0x02
+#define LDN_PARALLEL	0x03
+#define LDN_KEYBOARD	0x05
+#define LDN_MOUSE	0x06
+
+#define IT8712_UART1_PORT      0x3F8
+#define IT8712_UART2_PORT      0x2F8
+
+#ifndef ASM_ONLY
+
+void LPCSetConfig(char LdnNumber, char Index, char data);
+char LPCGetConfig(char LdnNumber, char Index);
+
+#endif
+
+#endif
diff -urN linux-2.4.4-pre3/include/asm-mips/keyboard.h linux/include/asm-mips/keyboard.h
--- linux-2.4.4-pre3/include/asm-mips/keyboard.h	Sun Jul  9 22:18:15 2000
+++ linux/include/asm-mips/keyboard.h	Mon Dec  3 22:35:23 2001
@@ -45,7 +45,7 @@
 	void (*kbd_request_region)(void);
 	int (*kbd_request_irq)(void (*handler)(int, void *, struct pt_regs *));
 
-	/* PSaux driver resource managment  */
+	/* PSaux driver resource management  */
 	int (*aux_request_irq)(void (*handler)(int, void *, struct pt_regs *));
 	void (*aux_free_irq)(void);
 
diff -urN linux-2.4.4-pre3/include/asm-mips/mipsregs.h linux/include/asm-mips/mipsregs.h
--- linux-2.4.4-pre3/include/asm-mips/mipsregs.h	Sun Jul  9 22:18:15 2000
+++ linux/include/asm-mips/mipsregs.h	Mon Dec  3 22:35:23 2001
@@ -292,7 +292,7 @@
 /*
  * Bitfields and bit numbers in the coprocessor 0 cause register.
  *
- * Refer to to your MIPS R4xx0 manual, chapter 5 for explanation.
+ * Refer to your MIPS R4xx0 manual, chapter 5 for explanation.
  */
 #define  CAUSEB_EXCCODE		2
 #define  CAUSEF_EXCCODE		(31  <<  2)
diff -urN linux-2.4.4-pre3/include/asm-mips/pci.h linux/include/asm-mips/pci.h
--- linux-2.4.4-pre3/include/asm-mips/pci.h	Thu Jun 22 07:17:16 2000
+++ linux/include/asm-mips/pci.h	Mon Dec  3 22:35:23 2001
@@ -40,7 +40,7 @@
 #include <linux/string.h>
 #include <asm/io.h>
 
-#ifdef CONFIG_DDB5074
+#if (defined(CONFIG_DDB5074) || defined(CONFIG_DDB5476))
 #undef PCIBIOS_MIN_IO
 #undef PCIBIOS_MIN_MEM
 #define PCIBIOS_MIN_IO		0x0100000
diff -urN linux-2.4.4-pre3/include/asm-mips/processor.h linux/include/asm-mips/processor.h
--- linux-2.4.4-pre3/include/asm-mips/processor.h	Sat Dec 30 09:35:40 2000
+++ linux/include/asm-mips/processor.h	Mon Dec  3 22:35:23 2001
@@ -98,15 +98,20 @@
 #define NUM_FPU_REGS	32
 
 struct mips_fpu_hard_struct {
-	unsigned int fp_regs[NUM_FPU_REGS];
+	double fp_regs[NUM_FPU_REGS];
 	unsigned int control;
-} __attribute__((aligned(8)));
+};
 
 /*
- * FIXME: no fpu emulator yet (but who cares anyway?)
+ * It would be nice to add some more fields for emulator statistics, but there
+ * are a number of fixed offsets in offset.h and elsewhere that would have to
+ * be recalculated by hand.  So the additional information will be private to
+ * the FPU emulator for now.  See asm-mips/fpu_emulator.h.
  */
+typedef u64 fpureg_t;
 struct mips_fpu_soft_struct {
-	long	dummy;
+	fpureg_t	regs[NUM_FPU_REGS];
+	unsigned int	sr;
 };
 
 union mips_fpu_union {
@@ -148,6 +153,21 @@
 	mm_segment_t current_ds;
 	unsigned long irix_trampoline;  /* Wheee... */
 	unsigned long irix_oldctx;
+
+	/*
+	 * These are really only needed if the full FPU emulator is configured.
+	 * Would be made conditional on MIPS_FPU_EMULATOR if it weren't for the
+	 * fact that having offset.h rebuilt differently for different config
+	 * options would be asking for trouble.
+	 *
+	 * Saved EPC during delay-slot emulation (see math-emu/cp1emu.c)
+	 */
+	unsigned long dsemul_epc;
+
+	/*
+	 * Pointer to instruction used to induce address error
+	 */
+	unsigned long dsemul_aerpc;
 };
 
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
@@ -176,7 +196,12 @@
 	/* \
 	 * For now the default is to fix address errors \
 	 */ \
-	MF_FIXADE, { 0 }, 0, 0 \
+	MF_FIXADE, { 0 }, 0, 0, \
+	/* \
+	 * dsemul_epc and dsemul_aerpc should never be used uninitialized, \
+	 * but... \
+	 */ \
+	0 ,0 \
 }
 
 #ifdef __KERNEL__
diff -urN linux-2.4.4-pre3/include/asm-mips/semaphore.h linux/include/asm-mips/semaphore.h
--- linux-2.4.4-pre3/include/asm-mips/semaphore.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/config.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
 #ifdef __MIPSEB__
@@ -215,7 +216,7 @@
 	atomic_t		count;
 	/* bit 0 means read bias granted;
 	   bit 1 means write bias granted.  */
-	unsigned		granted;
+	unsigned long		granted; /* pedant: long req'd for set_bit */
 	wait_queue_head_t	wait;
 	wait_queue_head_t	write_bias_wait;
 #if WAITQUEUE_DEBUG
diff -urN linux-2.4.4-pre3/include/asm-mips/sgi/sgimc.h linux/include/asm-mips/sgi/sgimc.h
--- linux-2.4.4-pre3/include/asm-mips/sgi/sgimc.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/sgi/sgimc.h	Mon Dec  3 22:35:23 2001
@@ -200,7 +200,7 @@
 	u32 _unused7;
 	volatile u32 dmamode;     /* DMA mode config bit settings */
 	u32 _unused8;
-	volatile u32 dmacount;    /* Zoom and byte count for DMA */
+	volatile u32 dmaccount;    /* Zoom and byte count for DMA */
 	u32 _unused9;
 	volatile u32 dmastart;    /* Pedal to the metal. */
 	u32 _unused10;
diff -urN linux-2.4.4-pre3/include/asm-mips/shmiq.h linux/include/asm-mips/shmiq.h
--- linux-2.4.4-pre3/include/asm-mips/shmiq.h	Tue Dec 16 12:46:13 1997
+++ linux/include/asm-mips/shmiq.h	Mon Dec  3 22:35:23 2001
@@ -146,7 +146,7 @@
 /* get time since last event */
 #define QIOCGETITIME    _IOR('Q', 11, time_t)
 
-/* set curent screen */
+/* set current screen */
 #define QIOCSETSCRN     _IOW('Q',6,int)
 
 
diff -urN linux-2.4.4-pre3/include/asm-mips64/errno.h linux/include/asm-mips64/errno.h
--- linux-2.4.4-pre3/include/asm-mips64/errno.h	Sun Feb  4 21:48:46 2001
+++ linux/include/asm-mips64/errno.h	Mon Dec  3 22:35:23 2001
@@ -142,7 +142,6 @@
  */
 #define ENOMEDIUM	159	/* No medium found */
 #define EMEDIUMTYPE	160	/* Wrong medium type */
-#define EHASHCOLLISION	125	/* Number of hash collisons exceeds maximum generation counter value.  */
 
 #define EDQUOT		1133	/* Quota exceeded */
 
diff -urN linux-2.4.4-pre3/include/asm-mips64/keyboard.h linux/include/asm-mips64/keyboard.h
--- linux-2.4.4-pre3/include/asm-mips64/keyboard.h	Mon Feb 28 07:18:20 2000
+++ linux/include/asm-mips64/keyboard.h	Mon Dec  3 22:35:23 2001
@@ -44,7 +44,7 @@
 	void (*kbd_request_region)(void);
 	int (*kbd_request_irq)(void (*handler)(int, void *, struct pt_regs *));
 
-	/* PSaux driver resource managment  */
+	/* PSaux driver resource management  */
 	int (*aux_request_irq)(void (*handler)(int, void *, struct pt_regs *));
 	void (*aux_free_irq)(void);
 
diff -urN linux-2.4.4-pre3/include/asm-mips64/mipsregs.h linux/include/asm-mips64/mipsregs.h
--- linux-2.4.4-pre3/include/asm-mips64/mipsregs.h	Tue Nov 28 21:42:04 2000
+++ linux/include/asm-mips64/mipsregs.h	Mon Dec  3 22:35:23 2001
@@ -216,7 +216,7 @@
 /*
  * Bitfields and bit numbers in the coprocessor 0 cause register.
  *
- * Refer to to your MIPS R4xx0 manual, chapter 5 for explanation.
+ * Refer to your MIPS R4xx0 manual, chapter 5 for explanation.
  */
 #define  CAUSEB_EXCCODE		2
 #define  CAUSEF_EXCCODE		(31  <<  2)
diff -urN linux-2.4.4-pre3/include/asm-mips64/mmzone.h linux/include/asm-mips64/mmzone.h
--- linux-2.4.4-pre3/include/asm-mips64/mmzone.h	Wed Aug  9 13:46:02 2000
+++ linux/include/asm-mips64/mmzone.h	Mon Dec  3 22:35:23 2001
@@ -58,7 +58,7 @@
 
 /*
  * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
- * and returns the the mem_map of that node.
+ * and returns the mem_map of that node.
  */
 #define ADDR_TO_MAPBASE(kaddr) \
 			NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
diff -urN linux-2.4.4-pre3/include/asm-mips64/pci/bridge.h linux/include/asm-mips64/pci/bridge.h
--- linux-2.4.4-pre3/include/asm-mips64/pci/bridge.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips64/pci/bridge.h	Mon Dec  3 22:35:23 2001
@@ -276,7 +276,7 @@
 				ds:2,		/* Data size	  */
 				gbr:1,		/* GBR enable	  */
 				vbpm:1,		/* VBPM message	  */
-				error:1,	/* Error occured  */
+				error:1,	/* Error occurred  */
 				barr:1,		/* Barrier op	  */
 				rsvd:8;
 		} berr_st;
diff -urN linux-2.4.4-pre3/include/asm-mips64/semaphore.h linux/include/asm-mips64/semaphore.h
--- linux-2.4.4-pre3/include/asm-mips64/semaphore.h	Tue Nov 28 21:42:04 2000
+++ linux/include/asm-mips64/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -13,6 +13,7 @@
 #include <asm/atomic.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
 #ifdef __MIPSEB__
@@ -167,180 +168,6 @@
 #endif
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
-}
-
-/*
- * rw mutexes (should that be mutices? =) -- throw rw spinlocks and
- * semaphores together, and this is what we end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer subtracts BIAS ands
- * gets 0 for the case of an uncontended lock.  Readers decrement by 1 and
- * see a positive value when uncontended, negative if there are writers
- * waiting (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and lots of processes.
- * BIAS must be chosen such that subtracting BIAS once per CPU will result
- * in the int remaining negative.  In terms of fairness, this should result
- * in the lock flopping back and forth between readers and writers under
- * heavy use.
- *
- * Once we start supporting machines with more than 128 CPUs, we should go
- * for using a 64bit atomic type instead of 32bit as counter. We shall
- * probably go for bias 0x80000000 then, so that single sethi can set it.
- * */
-
-#define RW_LOCK_BIAS		0x01000000
-
-struct rw_semaphore {
-	atomic_t		count;
-	/* bit 0 means read bias granted;
-	   bit 1 means write bias granted.  */
-	unsigned long		granted;
-	wait_queue_head_t	wait;
-	wait_queue_head_t	write_bias_wait;
-#if WAITQUEUE_DEBUG
-	long			__magic;
-	atomic_t		readers;
-	atomic_t		writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT	, ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT	/* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count)					\
-	{ ATOMIC_INIT(count), 0,					\
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait),			\
-	  __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait)		\
-	  __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) \
-	__DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) \
-	__DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) \
-	__DECLARE_RWSEM_GENERIC(name, 0)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	atomic_set(&sem->count, RW_LOCK_BIAS);
-	sem->granted = 0;
-	init_waitqueue_head(&sem->wait);
-	init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-	atomic_set(&sem->readers, 0);
-	atomic_set(&sem->writers, 0);
-#endif
-}
-
-/* The expensive part is outlined.  */
-extern void __down_read(struct rw_semaphore *sem, int count);
-extern void __down_write(struct rw_semaphore *sem, int count);
-extern void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers);
-
-static inline void down_read(struct rw_semaphore *sem)
-{
-	int count;
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
-	count = atomic_dec_return(&sem->count);
-	if (count < 0) {
-		__down_read(sem, count);
-	}
-	mb();
-
-#if WAITQUEUE_DEBUG
-	if (sem->granted & 2)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_inc(&sem->readers);
-#endif
-}
-
-static inline void down_write(struct rw_semaphore *sem)
-{
-	int count;
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
-	count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
-	if (count) {
-		__down_write(sem, count);
-	}
-	mb();
-
-#if WAITQUEUE_DEBUG
-	if (atomic_read(&sem->writers))
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (sem->granted & 3)
-		BUG();
-	atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant case is when
-   there was a writer waiting, and we've bumped the count to 0: we must
-   wake the writer up.  */
-
-static inline void up_read(struct rw_semaphore *sem)
-{
-	int count;
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-	if (sem->granted & 2)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_dec(&sem->readers);
-#endif
-
-	mb();
-	count = atomic_inc_return(&sem->count);
-	if (count == 0) {
-		__rwsem_wake(sem, 0);
-	}
-}
-
-/*
- * Releasing the writer is easy -- just release it and wake up any sleepers.
- */
-static inline void up_write(struct rw_semaphore *sem)
-{
-	int count;
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-	if (sem->granted & 3)
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (atomic_read(&sem->writers) != 1)
-		BUG();
-	atomic_dec(&sem->writers);
-#endif
-
-	mb();
-	count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-	if (count - RW_LOCK_BIAS < 0 && count >= 0) {
-		/* Only do the wake if we're no longer negative.  */
-		__rwsem_wake(sem, count);
-	}
 }
 
 #endif /* _ASM_SEMAPHORE_H */
diff -urN linux-2.4.4-pre3/include/asm-mips64/shmiq.h linux/include/asm-mips64/shmiq.h
--- linux-2.4.4-pre3/include/asm-mips64/shmiq.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips64/shmiq.h	Mon Dec  3 22:35:23 2001
@@ -153,7 +153,7 @@
 /* get time since last event */
 #define QIOCGETITIME    _IOR('Q', 11, time_t)
 
-/* set curent screen */
+/* set current screen */
 #define QIOCSETSCRN     _IOW('Q',6,int)
 
 
diff -urN linux-2.4.4-pre3/include/asm-parisc/semaphore.h linux/include/asm-parisc/semaphore.h
--- linux-2.4.4-pre3/include/asm-parisc/semaphore.h	Tue Dec  5 12:29:39 2000
+++ linux/include/asm-parisc/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -17,6 +17,7 @@
  */
 
 #include <linux/spinlock.h>
+#include <linux/rwsem.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -133,169 +134,6 @@
 #endif
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
-}
-
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and
- * lots of processes.  BIAS must be chosen such that subl'ing
- * BIAS once per CPU will result in the long remaining
- * negative.
- *
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *              -ben
- */
-struct rw_semaphore {
-        atomic_t                count;
-        volatile unsigned char  write_bias_granted;
-        volatile unsigned char  read_bias_granted;
-        volatile unsigned char  pad1;
-        volatile unsigned char  pad2;
-        wait_queue_head_t       wait;
-        wait_queue_head_t       write_bias_wait;
-#if WAITQUEUE_DEBUG
-        long                    __magic;
-        atomic_t                readers;
-        atomic_t                writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT      , ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT      /* */
-#endif
-
-#define RW_LOCK_BIAS 0x01000000
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-        __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-        __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-        struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-        atomic_set(&sem->count, RW_LOCK_BIAS);
-        sem->read_bias_granted = 0;
-        sem->write_bias_granted = 0;
-        init_waitqueue_head(&sem->wait);
-        init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-        sem->__magic = (long)&sem->__magic;
-        atomic_set(&sem->readers, 0);
-        atomic_set(&sem->writers, 0);
-#endif
-}
-
-#ifdef FIXME_WILLY_FIXME_FOR_REAL_THIS_TIME
-extern struct rw_semaphore *__build_read_lock(struct rw_semaphore *sem, const char *what);
-extern struct rw_semaphore *__build_write_lock(struct rw_semaphore *sem, const char *what);
-#endif
-
-/* we use FASTCALL convention for the helpers */
-extern struct rw_semaphore *FASTCALL(__down_read_failed(struct rw_semaphore *sem));
-extern struct rw_semaphore *FASTCALL(__down_write_failed(struct rw_semaphore *sem));
-extern struct rw_semaphore *FASTCALL(__rwsem_wake(struct rw_semaphore *sem));
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-        if (sem->__magic != (long)&sem->__magic)
-                BUG();
-#endif
-#ifdef FIXME_WILLY_FIXME_FOR_REAL_THIS_TIME
-        __build_read_lock(sem, "__down_read_failed");
-#endif
-#if WAITQUEUE_DEBUG
-        if (sem->write_bias_granted)
-                BUG();
-        if (atomic_read(&sem->writers))
-                BUG();
-        atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-        if (sem->__magic != (long)&sem->__magic)
-                BUG();
-#endif
-#ifdef FIXME_WILLY_FIXME_FOR_REAL_THIS_TIME
-        __build_write_lock(sem, "__down_write_failed");
-#endif
-#if WAITQUEUE_DEBUG
-        if (atomic_read(&sem->writers))
-                BUG();
-        if (atomic_read(&sem->readers))
-                BUG();
-        if (sem->read_bias_granted)
-                BUG();
-        if (sem->write_bias_granted)
-                BUG();
-        atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-extern inline void __up_read(struct rw_semaphore *sem)
-{
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-extern inline void __up_write(struct rw_semaphore *sem)
-{
-}
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-        if (sem->write_bias_granted)
-                BUG();
-        if (atomic_read(&sem->writers))
-                BUG();
-        atomic_dec(&sem->readers);
-#endif
-        __up_read(sem);
-}
-
-extern inline void up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-        if (sem->read_bias_granted)
-                BUG();
-        if (sem->write_bias_granted)
-                BUG();
-        if (atomic_read(&sem->readers))
-                BUG();
-        if (atomic_read(&sem->writers) != 1)
-                BUG();
-        atomic_dec(&sem->writers);
-#endif
-        __up_write(sem);
 }
 
 #endif /* _ASM_PARISC_SEMAPHORE_H */
diff -urN linux-2.4.4-pre3/include/asm-ppc/semaphore.h linux/include/asm-ppc/semaphore.h
--- linux-2.4.4-pre3/include/asm-ppc/semaphore.h	Fri Mar 23 22:42:31 2001
+++ linux/include/asm-ppc/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -14,6 +14,7 @@
 #include <asm/atomic.h>
 #include <asm/system.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
 	atomic_t count;
@@ -105,99 +106,6 @@
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
 }	
-
-
-/* RW spinlock-based semaphores */
-
-struct rw_semaphore
-{
-	spinlock_t lock;
-	int rd, wr;
-	wait_queue_head_t wait;
-#if WAITQUEUE_DEBUG
-	long __magic;
-#endif
-};
-
-#define RW_LOCK_BIAS	2	/* XXX bogus */
-#define __RWSEM_INITIALIZER(name, count)		\
-{							\
-	SPIN_LOCK_UNLOCKED,				\
-	(count) == 1, (count) == 0,			\
-	__WAIT_QUEUE_HEAD_INITIALIZER((name).wait)	\
-	__SEM_DEBUG_INIT(name)				\
-}
-
-#define __DECLARE_RWSEM_GENERIC(name, count)		\
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name, count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name, RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name, 0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-	spin_lock_init(&sem->lock);
-	sem->rd = sem->wr = 0;
-	init_waitqueue_head(&sem->wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-#endif
-}
-
-#ifndef CHECK_MAGIC
-#define CHECK_MAGIC(x)
-#endif
-
-extern void down_read_failed(struct rw_semaphore *);
-extern void down_write_failed(struct rw_semaphore *);
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-	CHECK_MAGIC(sem->__magic);
-
-	spin_lock_irq(&sem->lock);
-	if (sem->wr)
-		down_read_failed(sem);
-	sem->rd++;
-	spin_unlock_irq(&sem->lock);
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-	CHECK_MAGIC(sem->__magic);
-
-	spin_lock(&sem->lock);
-	if(sem->rd || sem->wr)
-		down_write_failed(sem);
-	sem->wr = 1;
-	spin_unlock(&sem->lock);
-}
-
-#define up_read(sem)							\
-	do {								\
-		unsigned long flags;					\
-									\
-		CHECK_MAGIC((sem)->__magic);				\
-									\
-		spin_lock_irqsave(&(sem)->lock, flags);			\
-		if (!--(sem)->rd && waitqueue_active(&(sem)->wait))	\
-			wake_up(&(sem)->wait);				\
-		spin_unlock_irqrestore(&(sem)->lock, flags);		\
-	} while (0)
-
-#define up_write(sem)							\
-	do {								\
-		unsigned long flags;					\
-									\
-		CHECK_MAGIC((sem)->__magic);				\
-									\
-		spin_lock_irqsave(&(sem)->lock, flags);			\
-		(sem)->wr = 0;						\
-		if (waitqueue_active(&(sem)->wait))			\
-			wake_up(&(sem)->wait);				\
-		spin_unlock_irqrestore(&(sem)->lock, flags);		\
-	} while (0)
 
 
 #endif /* __KERNEL__ */
diff -urN linux-2.4.4-pre3/include/asm-s390/semaphore.h linux/include/asm-s390/semaphore.h
--- linux-2.4.4-pre3/include/asm-s390/semaphore.h	Tue Feb 13 14:13:44 2001
+++ linux/include/asm-s390/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -14,6 +14,7 @@
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
 	atomic_t count;
@@ -89,103 +90,6 @@
 {
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
-}
-
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and
- * lots of processes.  BIAS must be chosen such that subl'ing
- * BIAS once per CPU will result in the long remaining
- * negative.
- *
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *		-ben
- */
-struct rw_semaphore {
-	atomic_t		count;
-	volatile unsigned int	write_bias_granted;
-	volatile unsigned int	read_bias_granted;
-	wait_queue_head_t	wait;
-	wait_queue_head_t	write_bias_wait;
-};
-
-#define RW_LOCK_BIAS		 0x01000000
-
-#define __RWSEM_DEBUG_INIT	/* */
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-	__WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-	__SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	atomic_set(&sem->count, RW_LOCK_BIAS);
-	sem->read_bias_granted = 0;
-	sem->write_bias_granted = 0;
-	init_waitqueue_head(&sem->wait);
-	init_waitqueue_head(&sem->write_bias_wait);
-}
-
-extern void __down_read_failed(int, struct rw_semaphore *);
-extern void __down_write_failed(int, struct rw_semaphore *);
-extern void __rwsem_wake(int, struct rw_semaphore *);
-
-static inline void down_read(struct rw_semaphore *sem)
-{
-	int count;
-	count = atomic_dec_return(&sem->count);
-	if (count < 0)
-		__down_read_failed(count, sem);
-}
-
-static inline void down_write(struct rw_semaphore *sem)
-{
-	int count;
-	count = atomic_add_return (-RW_LOCK_BIAS, &sem->count);
-	if (count < 0)
-		__down_write_failed(count, sem);
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-static inline void up_read(struct rw_semaphore *sem)
-{
-	int count;
-	count = atomic_inc_return(&sem->count);
-	if (count == 0)
-		__rwsem_wake(count, sem);
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-static inline void up_write(struct rw_semaphore *sem)
-{
-	int count;
-	count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-	if (count >= 0 && count < RW_LOCK_BIAS)
-		__rwsem_wake(count, sem);
 }
 
 #endif
diff -urN linux-2.4.4-pre3/include/asm-s390x/semaphore.h linux/include/asm-s390x/semaphore.h
--- linux-2.4.4-pre3/include/asm-s390x/semaphore.h	Tue Feb 13 14:13:44 2001
+++ linux/include/asm-s390x/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -14,6 +14,7 @@
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
 	atomic_t count;
@@ -89,103 +90,6 @@
 {
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
-}
-
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and
- * lots of processes.  BIAS must be chosen such that subl'ing
- * BIAS once per CPU will result in the long remaining
- * negative.
- *
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *		-ben
- */
-struct rw_semaphore {
-	atomic_t		count;
-	volatile unsigned int	write_bias_granted;
-	volatile unsigned int	read_bias_granted;
-	wait_queue_head_t	wait;
-	wait_queue_head_t	write_bias_wait;
-};
-
-#define RW_LOCK_BIAS		 0x01000000
-
-#define __RWSEM_DEBUG_INIT	/* */
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-	__WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-	__SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	atomic_set(&sem->count, RW_LOCK_BIAS);
-	sem->read_bias_granted = 0;
-	sem->write_bias_granted = 0;
-	init_waitqueue_head(&sem->wait);
-	init_waitqueue_head(&sem->write_bias_wait);
-}
-
-extern void __down_read_failed(int, struct rw_semaphore *);
-extern void __down_write_failed(int, struct rw_semaphore *);
-extern void __rwsem_wake(int, struct rw_semaphore *);
-
-static inline void down_read(struct rw_semaphore *sem)
-{
-	int count;
-	count = atomic_dec_return(&sem->count);
-	if (count < 0)
-		__down_read_failed(count, sem);
-}
-
-static inline void down_write(struct rw_semaphore *sem)
-{
-	int count;
-	count = atomic_add_return (-RW_LOCK_BIAS, &sem->count);
-	if (count < 0)
-		__down_write_failed(count, sem);
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-static inline void up_read(struct rw_semaphore *sem)
-{
-	int count;
-	count = atomic_inc_return(&sem->count);
-	if (count == 0)
-		__rwsem_wake(count, sem);
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-static inline void up_write(struct rw_semaphore *sem)
-{
-	int count;
-	count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-	if (count >= 0 && count < RW_LOCK_BIAS)
-		__rwsem_wake(count, sem);
 }
 
 #endif
diff -urN linux-2.4.4-pre3/include/asm-sh/semaphore.h linux/include/asm-sh/semaphore.h
--- linux-2.4.4-pre3/include/asm-sh/semaphore.h	Sun Mar  5 09:33:55 2000
+++ linux/include/asm-sh/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -13,6 +13,7 @@
  */
 
 #include <linux/spinlock.h>
+#include <linux/rwsem.h>
 
 #include <asm/system.h>
 #include <asm/atomic.h>
@@ -134,151 +135,6 @@
 #endif
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
-}
-
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * SuperH version by Niibe Yutaka
- */
-struct rw_semaphore {
-	atomic_t		count;
-	volatile unsigned char	write_bias_granted;
-	volatile unsigned char	read_bias_granted;
-	volatile unsigned char	pad1;
-	volatile unsigned char	pad2;
-	wait_queue_head_t	wait;
-	wait_queue_head_t	write_bias_wait;
-#if WAITQUEUE_DEBUG
-	long			__magic;
-	atomic_t		readers;
-	atomic_t		writers;
-#endif
-};
-
-#define RW_LOCK_BIAS		 0x01000000
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT	, ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT	/* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-	__WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-	__SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-	atomic_set(&sem->count, RW_LOCK_BIAS);
-	sem->read_bias_granted = 0;
-	sem->write_bias_granted = 0;
-	init_waitqueue_head(&sem->wait);
-	init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-	atomic_set(&sem->readers, 0);
-	atomic_set(&sem->writers, 0);
-#endif
-}
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-	int saved = atomic_read(&sem->count), new;
-#if WAITQUEUE_DEBUG
-	if (sem->__magic != (long)&sem->__magic)
-		BUG();
-#endif
-	if ((new = atomic_dec_return(&sem->count)) < 0)
-		__down_read(sem, (new < 0 && saved >=0));
-#if WAITQUEUE_DEBUG
-	if (sem->write_bias_granted)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-	int saved = atomic_read(&sem->count), new;
-#if WAITQUEUE_DEBUG
-	if (sem->__magic != (long)&sem->__magic)
-		BUG();
-#endif
-	if ((new = atomic_sub_return(RW_LOCK_BIAS, &sem->count)) != 0)
-		__down_write(sem, (new < 0 && saved >=0));
-#if WAITQUEUE_DEBUG
-	if (atomic_read(&sem->writers))
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (sem->read_bias_granted)
-		BUG();
-	if (sem->write_bias_granted)
-		BUG();
-	atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-extern inline void __up_read(struct rw_semaphore *sem)
-{
-	if (atomic_inc_return(&sem->count) == 0)
-		__rwsem_wake(sem);
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-extern inline void __up_write(struct rw_semaphore *sem)
-{
-	int saved = atomic_read(&sem->count), new;
-
-	new = atomic_add_return(RW_LOCK_BIAS, &sem->count);
-	if (saved < 0 && new >= 0)
-		__rwsem_wake(sem);
-}
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	if (sem->write_bias_granted)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_dec(&sem->readers);
-#endif
-	__up_read(sem);
-}
-
-extern inline void up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	if (sem->read_bias_granted)
-		BUG();
-	if (sem->write_bias_granted)
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (atomic_read(&sem->writers) != 1)
-		BUG();
-	atomic_dec(&sem->writers);
-#endif
-	__up_write(sem);
 }
 
 #endif /* __ASM_SH_SEMAPHORE_H */
diff -urN linux-2.4.4-pre3/include/asm-sparc/semaphore.h linux/include/asm-sparc/semaphore.h
--- linux-2.4.4-pre3/include/asm-sparc/semaphore.h	Sun Mar 25 18:14:21 2001
+++ linux/include/asm-sparc/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -7,6 +7,7 @@
 
 #include <asm/atomic.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
 	atomic_t count;
@@ -207,201 +208,6 @@
 	: "0" (increment), "r" (ptr), "i" (__up)
 	: "g3", "g4", "g7", "memory", "cc");
 }	
-
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and
- * lots of processes.  BIAS must be chosen such that subtracting
- * BIAS once per CPU will result in the int remaining
- * negative.
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *	      -ben
- */
-#define RW_LOCK_BIAS		0x01000000
-
-struct rw_semaphore {
-	int			count;
-	unsigned char		lock;
-	unsigned char		read_not_granted;
-	unsigned char		write_not_granted;
-	wait_queue_head_t	wait;
-	wait_queue_head_t	write_bias_wait;
-#if WAITQUEUE_DEBUG
-	long			__magic;
-	atomic_t		readers;
-	atomic_t		writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT	, ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT	/* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ (count), 0, 0xff, 0xff, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-  __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-  __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RW_LOCK_BIAS;
-	sem->lock = 0;
-	sem->read_not_granted = 0xff;
-	sem->write_not_granted = 0xff;
-	init_waitqueue_head(&sem->wait);
-	init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-	atomic_set(&sem->readers, 0);
-	atomic_set(&sem->writers, 0);
-#endif
-}
-
-extern void ___down_read(/* Special calling convention */ void);
-extern void ___down_write(/* Special calling convention */ void);
-extern void ___up_read(/* Special calling convention */ void);
-extern void ___up_write(/* Special calling convention */ void);
-
-static inline void down_read(struct rw_semaphore *sem)
-{
-	register volatile int *ptr asm("g1");
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
-	ptr = &sem->count;
-
-	__asm__ __volatile__("
-	mov	%%o7, %%g4
-	call	%1
-	 add	%%o7, 8, %%o7
-	"
-	:: "r" (ptr), "i" (___down_read)
-	: "g2", "g3", "g4", "g7", "memory", "cc");
-#if WAITQUEUE_DEBUG
-	if (!sem->write_not_granted)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_inc(&sem->readers);
-#endif
-}
-
-static inline void down_write(struct rw_semaphore *sem)
-{
-	register volatile int *ptr asm("g1");
-
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-
-	ptr = &sem->count;
-
-	__asm__ __volatile__("
-	mov	%%o7, %%g4
-	call	%1
-	 add	%%o7, 8, %%o7
-	"
-	:: "r" (ptr), "i" (___down_write)
-	: "g2", "g3", "g4", "g7", "memory", "cc");
-#if WAITQUEUE_DEBUG
-	if (atomic_read(&sem->writers))
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (!sem->read_not_granted)
-		BUG();
-	if (!sem->write_not_granted)
-		BUG();
-	atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-static inline void __up_read(struct rw_semaphore *sem)
-{
-	register volatile int *ptr asm("g1");
-
-	ptr = &sem->count;
-
-	__asm__ __volatile__("
-	mov	%%o7, %%g4
-	call	%1
-	 add	%%o7, 8, %%o7
-	"
-	:: "r" (ptr), "i" (___up_read)
-	: "g2", "g3", "g4", "g7", "memory", "cc");
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-static inline void __up_write(struct rw_semaphore *sem)
-{
-	register volatile int *ptr asm("g1");
-
-	ptr = &sem->count;
-
-	__asm__ __volatile__("
-	mov	%%o7, %%g4
-	call	%1
-	 add	%%o7, 8, %%o7
-	"
-	:: "r" (ptr), "i" (___up_write)
-	: "g2", "g3", "g4", "g7", "memory", "cc");
-}
-
-static inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	if (!sem->write_not_granted)
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_dec(&sem->readers);
-#endif
-	__up_read(sem);
-}
-
-static inline void up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	if (!sem->read_not_granted)
-		BUG();
-	if (!sem->write_not_granted)
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (atomic_read(&sem->writers) != 1)
-		BUG();
-	atomic_dec(&sem->writers);
-#endif
-	__up_write(sem);
-}
 
 #endif /* __KERNEL__ */
 
diff -urN linux-2.4.4-pre3/include/asm-sparc64/bitops.h linux/include/asm-sparc64/bitops.h
--- linux-2.4.4-pre3/include/asm-sparc64/bitops.h	Tue Oct  3 09:24:41 2000
+++ linux/include/asm-sparc64/bitops.h	Mon Dec  3 22:35:23 2001
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.31 2000/09/23 02:09:21 davem Exp $
+/* $Id: bitops.h,v 1.32 2001/04/14 01:12:16 davem Exp $
  * bitops.h: Bit string operations on the V9.
  *
  * Copyright 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -9,16 +9,24 @@
 
 #include <asm/byteorder.h>
 
-extern long __test_and_set_bit(unsigned long nr, volatile void *addr);
-extern long __test_and_clear_bit(unsigned long nr, volatile void *addr);
-extern long __test_and_change_bit(unsigned long nr, volatile void *addr);
-
-#define test_and_set_bit(nr,addr)	(__test_and_set_bit(nr,addr)!=0)
-#define test_and_clear_bit(nr,addr)	(__test_and_clear_bit(nr,addr)!=0)
-#define test_and_change_bit(nr,addr)	(__test_and_change_bit(nr,addr)!=0)
-#define set_bit(nr,addr)		((void)__test_and_set_bit(nr,addr))
-#define clear_bit(nr,addr)		((void)__test_and_clear_bit(nr,addr))
-#define change_bit(nr,addr)		((void)__test_and_change_bit(nr,addr))
+extern long ___test_and_set_bit(unsigned long nr, volatile void *addr);
+extern long ___test_and_clear_bit(unsigned long nr, volatile void *addr);
+extern long ___test_and_change_bit(unsigned long nr, volatile void *addr);
+
+#define test_and_set_bit(nr,addr)	(___test_and_set_bit(nr,addr)!=0)
+#define test_and_clear_bit(nr,addr)	(___test_and_clear_bit(nr,addr)!=0)
+#define test_and_change_bit(nr,addr)	(___test_and_change_bit(nr,addr)!=0)
+#define set_bit(nr,addr)		((void)___test_and_set_bit(nr,addr))
+#define clear_bit(nr,addr)		((void)___test_and_clear_bit(nr,addr))
+#define change_bit(nr,addr)		((void)___test_and_change_bit(nr,addr))
+
+/* "non-atomic" versions, nothing special for now... */
+#define __set_bit(X,Y)		set_bit(X,Y)
+#define __clear_bit(X,Y)	clear_bit(X,Y)
+#define __change_bit(X,Y)	change_bit(X,Y)
+#define __test_and_set_bit(X,Y)		test_and_set_bit(X,Y)
+#define __test_and_clear_bit(X,Y)	test_and_clear_bit(X,Y)
+#define __test_and_change_bit(X,Y)	test_and_change_bit(X,Y)
 
 #define smp_mb__before_clear_bit()	do { } while(0)
 #define smp_mb__after_clear_bit()	do { } while(0)
@@ -170,13 +178,13 @@
 #define find_first_zero_bit(addr, size) \
         find_next_zero_bit((addr), (size), 0)
 
-extern long __test_and_set_le_bit(int nr, volatile void *addr);
-extern long __test_and_clear_le_bit(int nr, volatile void *addr);
+extern long ___test_and_set_le_bit(int nr, volatile void *addr);
+extern long ___test_and_clear_le_bit(int nr, volatile void *addr);
 
-#define test_and_set_le_bit(nr,addr)	(__test_and_set_le_bit(nr,addr)!=0)
-#define test_and_clear_le_bit(nr,addr)	(__test_and_clear_le_bit(nr,addr)!=0)
-#define set_le_bit(nr,addr)		((void)__test_and_set_le_bit(nr,addr))
-#define clear_le_bit(nr,addr)		((void)__test_and_clear_le_bit(nr,addr))
+#define test_and_set_le_bit(nr,addr)	(___test_and_set_le_bit(nr,addr)!=0)
+#define test_and_clear_le_bit(nr,addr)	(___test_and_clear_le_bit(nr,addr)!=0)
+#define set_le_bit(nr,addr)		((void)___test_and_set_le_bit(nr,addr))
+#define clear_le_bit(nr,addr)		((void)___test_and_clear_le_bit(nr,addr))
 
 extern __inline__ int test_le_bit(int nr, __const__ void * addr)
 {
diff -urN linux-2.4.4-pre3/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h
--- linux-2.4.4-pre3/include/asm-sparc64/pgtable.h	Mon Dec  3 22:35:13 2001
+++ linux/include/asm-sparc64/pgtable.h	Mon Dec  3 22:35:23 2001
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.139 2001/03/27 02:36:37 davem Exp $
+/* $Id: pgtable.h,v 1.140 2001/04/12 22:41:15 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -254,12 +254,13 @@
 }
 
 /* Encode and de-code a swap entry */
-#define SWP_TYPE(entry)		(((entry).val >> PAGE_SHIFT) & 0xff)
-#define SWP_OFFSET(entry)	((entry).val >> (PAGE_SHIFT + 8))
+#define SWP_TYPE(entry)		(((entry).val >> PAGE_SHIFT) & 0xffUL)
+#define SWP_OFFSET(entry)	((entry).val >> (PAGE_SHIFT + 8UL))
 #define SWP_ENTRY(type, offset)	\
 	( (swp_entry_t) \
 	  { \
-		((type << PAGE_SHIFT) | (offset << (PAGE_SHIFT + 8))) \
+		(((long)(type) << PAGE_SHIFT) | \
+                 ((long)(offset) << (PAGE_SHIFT + 8UL))) \
 	  } )
 #define pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
 #define swp_entry_to_pte(x)		((pte_t) { (x).val })
diff -urN linux-2.4.4-pre3/include/asm-sparc64/rwsem.h linux/include/asm-sparc64/rwsem.h
--- linux-2.4.4-pre3/include/asm-sparc64/rwsem.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/rwsem.h	Mon Dec  3 22:35:23 2001
@@ -0,0 +1,11 @@
+/* $Id: rwsem.h,v 1.1 2001/04/14 01:12:16 davem Exp $ */
+#ifndef _SPARC64_RWSEM_H
+#define _SPARC64_RWSEM_H
+
+#ifndef _LINUX_RWSEM_H
+#error please dont include asm/rwsem.h directly, use linux/rwsem.h instead
+#endif
+
+#undef __HAVE_ARCH_SPECIFIC_RWSEM_IMPLEMENTATION
+
+#endif /* _SPARC64_RWSEM_H */
diff -urN linux-2.4.4-pre3/include/asm-sparc64/semaphore.h linux/include/asm-sparc64/semaphore.h
--- linux-2.4.4-pre3/include/asm-sparc64/semaphore.h	Wed Jul 12 16:45:30 2000
+++ linux/include/asm-sparc64/semaphore.h	Mon Dec  3 22:35:23 2001
@@ -8,6 +8,7 @@
 #include <asm/bitops.h>
 #include <asm/system.h>
 #include <linux/wait.h>
+#include <linux/rwsem.h>
 
 struct semaphore {
 	atomic_t count;
@@ -199,268 +200,6 @@
 		.previous\n"
 	: : "r" (sem), "i" (__up)
 	: "g5", "g7", "memory", "cc");
-}
-
-/* rw mutexes (should that be mutices? =) -- throw rw
- * spinlocks and semaphores together, and this is what we
- * end up with...
- *
- * The lock is initialized to BIAS.  This way, a writer
- * subtracts BIAS ands gets 0 for the case of an uncontended
- * lock.  Readers decrement by 1 and see a positive value
- * when uncontended, negative if there are writers waiting
- * (in which case it goes to sleep).
- *
- * The value 0x01000000 supports up to 128 processors and
- * lots of processes.  BIAS must be chosen such that subtracting
- * BIAS once per CPU will result in the int remaining
- * negative.
- * In terms of fairness, this should result in the lock
- * flopping back and forth between readers and writers
- * under heavy use.
- *
- *	      -ben
- *
- * Once we start supporting machines with more than 128 CPUs,
- * we should go for using a 64bit atomic type instead of 32bit
- * as counter. We shall probably go for bias 0x80000000 then,
- * so that single sethi can set it.
- *
- *	      -jj
- */
-#define RW_LOCK_BIAS		0x01000000
-#define RW_LOCK_BIAS_STR	"0x01000000"
-
-struct rw_semaphore {
-	int			count;
-	/* So that this does not have to be 64bit type,
-	 * we'll use le bitops on it which use casa instead of casx.
-	 * bit 0 means read bias granted
-	 * bit 1 means write bias granted
-	 */
-	unsigned		granted;
-	wait_queue_head_t	wait;
-	wait_queue_head_t	write_bias_wait;
-#if WAITQUEUE_DEBUG
-	long			__magic;
-	atomic_t		readers;
-	atomic_t		writers;
-#endif
-};
-
-#if WAITQUEUE_DEBUG
-#define __RWSEM_DEBUG_INIT	, ATOMIC_INIT(0), ATOMIC_INIT(0)
-#else
-#define __RWSEM_DEBUG_INIT	/* */
-#endif
-
-#define __RWSEM_INITIALIZER(name,count) \
-{ (count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
-  __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
-  __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
-
-#define __DECLARE_RWSEM_GENERIC(name,count) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
-
-#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
-#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
-#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
-
-extern inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RW_LOCK_BIAS;
-	sem->granted = 0;
-	init_waitqueue_head(&sem->wait);
-	init_waitqueue_head(&sem->write_bias_wait);
-#if WAITQUEUE_DEBUG
-	sem->__magic = (long)&sem->__magic;
-	atomic_set(&sem->readers, 0);
-	atomic_set(&sem->writers, 0);
-#endif
-}
-
-extern void __down_read_failed(/* Special calling convention */ void);
-extern void __down_write_failed(/* Special calling convention */ void);
-extern void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers);
-
-extern inline void down_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-	__asm__ __volatile__("
-	1:	lduw	[%0], %%g5
-		subcc	%%g5, 1, %%g7
-		cas	[%0], %%g5, %%g7
-		bneg,pn	%%icc, 3f
-		 cmp	%%g5, %%g7
-		bne,pn	%%icc, 1b
-		 membar	#StoreStore
-	2:
-		.subsection 2
-	3:	bne,pn	%%icc, 1b
-		 mov	%0, %%g7
-		save	%%sp, -160, %%sp
-		mov	%%g1, %%l1
-		mov	%%g2, %%l2
-		call	%1
-		 mov	%%g3, %%l3
-		mov	%%l1, %%g1
-		mov	%%l2, %%g2
-		ba,pt	%%xcc, 2b
-		 restore %%l3, %%g0, %%g3
-		.previous\n"
-	: : "r" (sem), "i" (__down_read_failed)
-	: "g5", "g7", "memory", "cc");
-#if WAITQUEUE_DEBUG
-	if (test_le_bit(1, &sem->granted))
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_inc(&sem->readers);
-#endif
-}
-
-extern inline void down_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	CHECK_MAGIC(sem->__magic);
-#endif
-	__asm__ __volatile__("
-	1:	lduw	[%0], %%g5
-		sethi	%%hi(" RW_LOCK_BIAS_STR "), %%g7
-		subcc	%%g5, %%g7, %%g7
-		cas	[%0], %%g5, %%g7
-		bne,pn	%%icc, 3f
-		 cmp	%%g5, %%g7
-		bne,pn	%%icc, 1b
-		 membar	#StoreStore
-	2:
-		.subsection 2
-	3:	bne,pn	%%icc, 1b
-		 mov	%0, %%g7
-		save	%%sp, -160, %%sp
-		mov	%%g1, %%l1
-		mov	%%g2, %%l2
-		call	%1
-		 mov	%%g3, %%l3
-		mov	%%l1, %%g1
-		mov	%%l2, %%g2
-		ba,pt	%%xcc, 2b
-		 restore %%l3, %%g0, %%g3
-		.previous\n"
-	: : "r" (sem), "i" (__down_write_failed)
-	: "g5", "g7", "memory", "cc");
-#if WAITQUEUE_DEBUG
-	if (atomic_read(&sem->writers))
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (test_le_bit(0, &sem->granted))
-		BUG();
-	if (test_le_bit(1, &sem->granted))
-		BUG();
-	atomic_inc(&sem->writers);
-#endif
-}
-
-/* When a reader does a release, the only significant
- * case is when there was a writer waiting, and we've
- * bumped the count to 0: we must wake the writer up.
- */
-extern inline void __up_read(struct rw_semaphore *sem)
-{
-	__asm__ __volatile__("
-		membar	#StoreLoad | #LoadLoad
-	1:	lduw	[%0], %%g5
-		addcc	%%g5, 1, %%g7
-		cas	[%0], %%g5, %%g7
-		be,pn	%%icc, 3f
-		 cmp	%%g5, %%g7
-		bne,pn	%%icc, 1b
-		 nop
-	2:
-		.subsection 2
-	3:	bne,pn	%%icc, 1b
-		 mov	%0, %%g7
-		save	%%sp, -160, %%sp
-		mov	%%g1, %%l1
-		mov	%%g2, %%l2
-		clr	%%o1
-		mov	%%g7, %%o0
-		call	%1
-		 mov	%%g3, %%l3
-		mov	%%l1, %%g1
-		mov	%%l2, %%g2
-		ba,pt	%%xcc, 2b
-		 restore %%l3, %%g0, %%g3
-		.previous\n"
-	: : "r" (sem), "i" (__rwsem_wake)
-	: "g5", "g7", "memory", "cc");
-}
-
-/* releasing the writer is easy -- just release it and
- * wake up any sleepers.
- */
-extern inline void __up_write(struct rw_semaphore *sem)
-{
-	__asm__ __volatile__("
-		membar	#StoreLoad | #LoadLoad
-	1:	lduw	[%0], %%g5
-		sethi	%%hi(" RW_LOCK_BIAS_STR "), %%g7
-		add	%%g5, %%g7, %%g7
-		cas	[%0], %%g5, %%g7
-		cmp	%%g5, %%g7
-		bne,pn	%%icc, 1b
-		 sethi	%%hi(" RW_LOCK_BIAS_STR "), %%g7
-		addcc	%%g5, %%g7, %%g5
-		bcs,pn	%%icc, 3f
-		 nop
-	2:
-		.subsection 2
-	3:	mov	%0, %%g7
-		save	%%sp, -160, %%sp
-		mov	%%g1, %%l1
-		mov	%%g2, %%l2
-		srl	%%g5, 0, %%o1
-		mov	%%g7, %%o0
-		call	%1
-		 mov	%%g3, %%l3
-		mov	%%l1, %%g1
-		mov	%%l2, %%g2
-		ba,pt	%%xcc, 2b
-		 restore %%l3, %%g0, %%g3
-		.previous\n"
-	: : "r" (sem), "i" (__rwsem_wake)
-	: "g5", "g7", "memory", "cc");
-}
-
-extern inline void up_read(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	if (test_le_bit(1, &sem->granted))
-		BUG();
-	if (atomic_read(&sem->writers))
-		BUG();
-	atomic_dec(&sem->readers);
-#endif
-	__up_read(sem);
-}
-
-extern inline void up_write(struct rw_semaphore *sem)
-{
-#if WAITQUEUE_DEBUG
-	if (test_le_bit(0, &sem->granted))
-		BUG();
-	if (test_le_bit(1, &sem->granted))
-		BUG();
-	if (atomic_read(&sem->readers))
-		BUG();
-	if (atomic_read(&sem->writers) != 1)
-		BUG();
-	atomic_dec(&sem->writers);
-#endif
-	__up_write(sem);
 }
 
 #endif /* __KERNEL__ */
diff -urN linux-2.4.4-pre3/include/linux/devfs_fs_kernel.h linux/include/linux/devfs_fs_kernel.h
--- linux-2.4.4-pre3/include/linux/devfs_fs_kernel.h	Mon Mar 26 15:48:11 2001
+++ linux/include/linux/devfs_fs_kernel.h	Mon Dec  3 22:35:23 2001
@@ -96,7 +96,6 @@
 				   unsigned int minor_start,
 				   umode_t mode, void *ops, void *info);
 
-extern int init_devfs_fs (void);
 extern void mount_devfs_fs (void);
 extern void devfs_make_root (const char *name);
 #else  /*  CONFIG_DEVFS_FS  */
@@ -233,10 +232,6 @@
     return;
 }
 
-static inline int init_devfs_fs (void)
-{
-    return 0;
-}
 static inline void mount_devfs_fs (void)
 {
     return;
diff -urN linux-2.4.4-pre3/include/linux/fs.h linux/include/linux/fs.h
--- linux-2.4.4-pre3/include/linux/fs.h	Mon Dec  3 22:35:13 2001
+++ linux/include/linux/fs.h	Mon Dec  3 22:35:23 2001
@@ -1295,7 +1295,6 @@
 
 extern struct file_system_type *get_fs_type(const char *name);
 extern struct super_block *get_super(kdev_t);
-struct super_block *get_empty_super(void);
 extern void put_super(kdev_t);
 unsigned long generate_cluster(kdev_t, int b[], int);
 unsigned long generate_cluster_swab32(kdev_t, int b[], int);
diff -urN linux-2.4.4-pre3/include/linux/if_arp.h linux/include/linux/if_arp.h
--- linux-2.4.4-pre3/include/linux/if_arp.h	Mon Mar 26 15:48:19 2001
+++ linux/include/linux/if_arp.h	Mon Dec  3 22:35:23 2001
@@ -73,7 +73,7 @@
 #define ARPHRD_ECONET	782		/* Acorn Econet			*/
 #define ARPHRD_IRDA 	783		/* Linux-IrDA			*/
 /* ARP works differently on different FC media .. so  */
-#define ARPHRD_FCPP	784		/* Point to point fibrechanel	*/
+#define ARPHRD_FCPP	784		/* Point to point fibrechannel	*/
 #define ARPHRD_FCAL	785		/* Fibrechannel arbitrated loop */
 #define ARPHRD_FCPL	786		/* Fibrechannel public loop	*/
 #define ARPHRD_FCFABRIC	787		/* Fibrechannel fabric		*/
diff -urN linux-2.4.4-pre3/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- linux-2.4.4-pre3/include/linux/nfs_fs.h	Mon Mar 26 15:48:42 2001
+++ linux/include/linux/nfs_fs.h	Mon Dec  3 22:35:23 2001
@@ -137,7 +137,6 @@
  * linux/fs/nfs/inode.c
  */
 extern struct super_block *nfs_read_super(struct super_block *, void *, int);
-extern int init_nfs_fs(void);
 extern void nfs_zap_caches(struct inode *);
 extern int nfs_inode_is_stale(struct inode *, struct nfs_fh *,
 				struct nfs_fattr *);
diff -urN linux-2.4.4-pre3/include/linux/rwsem-spinlock.h linux/include/linux/rwsem-spinlock.h
--- linux-2.4.4-pre3/include/linux/rwsem-spinlock.h	Mon Dec  3 22:35:13 2001
+++ linux/include/linux/rwsem-spinlock.h	Mon Dec  3 22:35:23 2001
@@ -14,8 +14,6 @@
 
 #ifdef __KERNEL__
 
-#define CONFIG_USING_SPINLOCK_BASED_RWSEM 1
-
 /*
  * the semaphore definition
  */
diff -urN linux-2.4.4-pre3/include/linux/rwsem.h linux/include/linux/rwsem.h
--- linux-2.4.4-pre3/include/linux/rwsem.h	Mon Dec  3 22:35:13 2001
+++ linux/include/linux/rwsem.h	Mon Dec  3 22:35:23 2001
@@ -42,21 +42,29 @@
 #include <asm/atomic.h>
 #include <linux/wait.h>
 
-#if RWSEM_DEBUG
-#define rwsemdebug(FMT, ARGS...) do { if (sem->debug) printk(FMT,##ARGS); } while(0)
+#ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
+#include <linux/rwsem-spinlock.h> /* use a generic implementation */
 #else
-#define rwsemdebug(FMT, ARGS...)
+#include <asm/rwsem.h> /* use an arch-specific implementation */
 #endif
 
+/* defined contention handler functions for the generic case
+ * - these are also used for the exchange-and-add based algorithm
+ */
+#if defined(CONFIG_RWSEM_GENERIC) || defined(CONFIG_RWSEM_XCHGADD_ALGORITHM)
 /* we use FASTCALL convention for the helpers */
 extern struct rw_semaphore *FASTCALL(rwsem_down_read_failed(struct rw_semaphore *sem));
 extern struct rw_semaphore *FASTCALL(rwsem_down_write_failed(struct rw_semaphore *sem));
 extern struct rw_semaphore *FASTCALL(rwsem_wake(struct rw_semaphore *sem));
+#endif
 
-#include <asm/rwsem.h> /* find the arch specific bits */
-
-#ifndef __HAVE_ARCH_SPECIFIC_RWSEM_IMPLEMENTATION
-#include <linux/rwsem-spinlock.h>
+#ifndef rwsemtrace
+#if RWSEM_DEBUG
+#include <asm/current.h>
+#define rwsemtrace(SEM,FMT) do { if ((SEM)->debug) printk("[%d] "FMT"(count=%08lx)\n",current->pid,(SEM)->count); } while(0)
+#else
+#define rwsemtrace(SEM,FMT)
+#endif
 #endif
 
 /*
@@ -64,7 +72,7 @@
  */
 static inline void down_read(struct rw_semaphore *sem)
 {
-	rwsemdebug("Entering down_read(count=%08lx)\n",sem->count);
+	rwsemtrace(sem,"Entering down_read");
 
 #if RWSEM_DEBUG_MAGIC
 	if (sem->__magic != (long)&sem->__magic)
@@ -79,7 +87,7 @@
 	atomic_inc(&sem->readers);
 #endif
 
-	rwsemdebug("Leaving down_read(count=%08lx)\n",sem->count);
+	rwsemtrace(sem,"Leaving down_read");
 }
 
 /*
@@ -87,7 +95,7 @@
  */
 static inline void down_write(struct rw_semaphore *sem)
 {
-	rwsemdebug("Entering down_write(count=%08lx)\n",sem->count);
+	rwsemtrace(sem,"Entering down_write");
 
 #if RWSEM_DEBUG_MAGIC
 	if (sem->__magic != (long)&sem->__magic)
@@ -104,7 +112,7 @@
 	atomic_inc(&sem->writers);
 #endif
 
-	rwsemdebug("Leaving down_write(count=%08lx)\n",sem->count);
+	rwsemtrace(sem,"Leaving down_write");
 }
 
 /*
@@ -112,7 +120,7 @@
  */
 static inline void up_read(struct rw_semaphore *sem)
 {
-	rwsemdebug("Entering up_read(count=%08lx)\n",sem->count);
+	rwsemtrace(sem,"Entering up_read");
 
 #if RWSEM_DEBUG_MAGIC
 	if (atomic_read(&sem->writers))
@@ -121,7 +129,7 @@
 #endif
 	__up_read(sem);
 
-	rwsemdebug("Leaving up_read(count=%08lx)\n",sem->count);
+	rwsemtrace(sem,"Leaving up_read");
 }
 
 /*
@@ -129,7 +137,7 @@
  */
 static inline void up_write(struct rw_semaphore *sem)
 {
-	rwsemdebug("Entering up_write(count=%08lx)\n",sem->count);
+	rwsemtrace(sem,"Entering up_write");
 
 #if RWSEM_DEBUG_MAGIC
 	if (atomic_read(&sem->readers))
@@ -140,7 +148,7 @@
 #endif
 	__up_write(sem);
 
-	rwsemdebug("Leaving up_write(count=%08lx)\n",sem->count);
+	rwsemtrace(sem,"Leaving up_write");
 }
 
 
diff -urN linux-2.4.4-pre3/include/linux/sunrpc/sched.h linux/include/linux/sunrpc/sched.h
--- linux-2.4.4-pre3/include/linux/sunrpc/sched.h	Mon Mar 26 15:48:29 2001
+++ linux/include/linux/sunrpc/sched.h	Mon Dec  3 22:35:23 2001
@@ -80,7 +80,7 @@
 	unsigned short		tk_lock;	/* Task lock counter */
 	unsigned char		tk_active   : 1,/* Task has been activated */
 				tk_wakeup   : 1;/* Task waiting to wake up */
-	unsigned int		tk_runstate;	/* Task run status */
+	unsigned long		tk_runstate;	/* Task run status */
 #ifdef RPC_DEBUG
 	unsigned short		tk_pid;		/* debugging aid */
 #endif
diff -urN linux-2.4.4-pre3/include/linux/tty_ldisc.h linux/include/linux/tty_ldisc.h
--- linux-2.4.4-pre3/include/linux/tty_ldisc.h	Mon Mar 26 15:48:11 2001
+++ linux/include/linux/tty_ldisc.h	Mon Dec  3 22:35:23 2001
@@ -2,22 +2,22 @@
 #define _LINUX_TTY_LDISC_H
 
 /*
- * This structure defines the interface between the tty line discpline
+ * This structure defines the interface between the tty line discipline
  * implementation and the tty routines.  The following routines can be
  * defined; unless noted otherwise, they are optional, and can be
  * filled in with a null pointer.
  *
  * int	(*open)(struct tty_struct *);
  *
- * 	This function is called when the line discpline is associated
- * 	with the tty.  The line discpline can use this as an
+ * 	This function is called when the line discipline is associated
+ * 	with the tty.  The line discipline can use this as an
  * 	opportunity to initialize any state needed by the ldisc routines.
  * 
  * void	(*close)(struct tty_struct *);
  *
- *	This function is called when the line discpline is being
+ *	This function is called when the line discipline is being
  * 	shutdown, either because the tty is being closed or because
- * 	the tty is being changed to use a new line discpline
+ * 	the tty is being changed to use a new line discipline
  * 
  * void	(*flush_buffer)(struct tty_struct *tty);
  *
@@ -28,14 +28,14 @@
  * ssize_t (*chars_in_buffer)(struct tty_struct *tty);
  *
  * 	This function returns the number of input characters the line
- *	iscpline may have queued up to be delivered to the user mode
+ *	discipline may have queued up to be delivered to the user mode
  *	process.
  * 
  * ssize_t (*read)(struct tty_struct * tty, struct file * file,
  *		   unsigned char * buf, size_t nr);
  *
  * 	This function is called when the user requests to read from
- * 	the tty.  The line discpline will return whatever characters
+ * 	the tty.  The line discipline will return whatever characters
  * 	it has buffered up for the user.  If this function is not
  * 	defined, the user will receive an EIO error.
  * 
@@ -43,7 +43,7 @@
  * 		    const unsigned char * buf, size_t nr);
  *
  * 	This function is called when the user requests to write to the
- * 	tty.  The line discpline will deliver the characters to the
+ * 	tty.  The line discipline will deliver the characters to the
  * 	low-level tty device for transmission, optionally performing
  * 	some processing on the characters first.  If this function is
  * 	not defined, the user will receive an EIO error.
@@ -54,7 +54,7 @@
  *	This function is called when the user requests an ioctl which
  * 	is not handled by the tty layer or the low-level tty driver.
  * 	It is intended for ioctls which affect line discpline
- * 	operation.  Not that the search order for ioctls is (1) tty
+ * 	operation.  Note that the search order for ioctls is (1) tty
  * 	layer, (2) tty low-level driver, (3) line discpline.  So a
  * 	low-level driver can "grab" an ioctl request before the line
  * 	discpline has a chance to see it.
@@ -62,7 +62,7 @@
  * void	(*set_termios)(struct tty_struct *tty, struct termios * old);
  *
  * 	This function notifies the line discpline that a change has
- * 	been made to the termios stucture.
+ * 	been made to the termios structure.
  * 
  * int	(*poll)(struct tty_struct * tty, struct file * file,
  * 		  poll_table *wait);
diff -urN linux-2.4.4-pre3/include/linux/wanrouter.h linux/include/linux/wanrouter.h
--- linux-2.4.4-pre3/include/linux/wanrouter.h	Mon Dec  3 22:35:13 2001
+++ linux/include/linux/wanrouter.h	Mon Dec  3 22:35:23 2001
@@ -5,6 +5,7 @@
 *
 * Author: 	Nenad Corbic <ncorbic@sangoma.com>
 *		Gideon Hack 	
+* Additions:	Arnaldo Melo
 *
 * Copyright:	(c) 1995-2000 Sangoma Technologies Inc.
 *
@@ -18,6 +19,8 @@
 * Jan 28, 2000  Nenad Corbic    Added support for the ASYNC protocol.
 * Oct 04, 1999  Nenad Corbic 	Updated for 2.1.0 release
 * Jun 02, 1999  Gideon Hack	Added support for the S514 adapter.
+* May 23, 1999	Arnaldo Melo	Added local_addr to wanif_conf_t
+*				WAN_DISCONNECTING state added
 * Jul 20, 1998	David Fong	Added Inverse ARP options to 'wanif_conf_t'
 * Jun 12, 1998	David Fong	Added Cisco HDLC support.
 * Dec 16, 1997	Jaspreet Singh	Moved 'enable_IPX' and 'network_number' to
@@ -423,6 +426,9 @@
 	unsigned inarp_interval;	/* sec, between InARP requests */
 	unsigned long network_number;	/* Network Number for IPX */
 	char mc;			/* Multicast on or off */
+	char local_addr[WAN_ADDRESS_SZ+1];/* local media address, ASCIIZ */
+	unsigned char port;		/* board port */
+	unsigned char protocol;		/* prococol used in this channel (TCPOX25 or X25) */
 	char pap;			/* PAP enabled or disabled */
 	char chap;			/* CHAP enabled or disabled */
 	unsigned char userid[511];	/* List of User Id */
@@ -432,7 +438,6 @@
 	unsigned char ignore_cts;	/*  Ignore these to determine */
 	unsigned char ignore_keepalive;	/*  link status (Yes or No) */
 	unsigned char hdlc_streaming;	/*  Hdlc streaming mode (Y/N) */
-	unsigned char receive_only;	/*  no transmit buffering (Y/N) */
 	unsigned keepalive_tx_tmr;	/* transmit keepalive timer */
 	unsigned keepalive_rx_tmr;	/* receive  keepalive timer */
 	unsigned keepalive_err_margin;	/* keepalive_error_tolerance */
@@ -462,7 +467,7 @@
 	unsigned rx_complete_length;
 	unsigned xon_char;
 	unsigned xoff_char;
-
+	unsigned char receive_only;	/*  no transmit buffering (Y/N) */
 } wanif_conf_t;
 
 #ifdef	__KERNEL__
@@ -508,11 +513,11 @@
 					/****** status and statistics *******/
 	char state;			/* device state */
 	char api_status;		/* device api status */
-      #if defined(LINUX_2_1) || defined(LINUX_2_4)
+#if defined(LINUX_2_1) || defined(LINUX_2_4)
 	struct net_device_stats stats; 	/* interface statistics */
-      #else
+#else
 	struct enet_statistics stats;	/* interface statistics */
-      #endif
+#endif
 	unsigned reserved[16];		/* reserved for future use */
 	unsigned long critical;		/* critical section flag */
 	spinlock_t lock;                /* Support for SMP Locking */
@@ -530,11 +535,11 @@
 	struct wan_device* next;	/* -> next device */
 	netdevice_t* dev;		/* list of network interfaces */
 	unsigned ndev;			/* number of interfaces */
-      #ifdef LINUX_2_4
+#ifdef LINUX_2_4
 	struct proc_dir_entry *dent;	/* proc filesystem entry */
-      #else
+#else
 	struct proc_dir_entry dent;	/* proc filesystem entry */
-      #endif
+#endif
 } wan_device_t;
 
 /* Public functions available for device drivers */
diff -urN linux-2.4.4-pre3/init/main.c linux/init/main.c
--- linux-2.4.4-pre3/init/main.c	Mon Mar 19 12:26:25 2001
+++ linux/init/main.c	Mon Dec  3 22:35:23 2001
@@ -96,7 +96,6 @@
 extern void net_notifier_init(void);
 
 extern void free_initmem(void);
-extern void filesystem_setup(void);
 
 #ifdef CONFIG_TC
 extern void tc_init(void);
@@ -722,9 +721,6 @@
 
 	start_context_thread();
 	do_initcalls();
-
-	/* .. filesystems .. */
-	filesystem_setup();
 
 #ifdef CONFIG_IRDA
 	irda_device_init(); /* Must be done after protocol initialization */
diff -urN linux-2.4.4-pre3/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.4.4-pre3/kernel/ksyms.c	Fri Mar  2 15:16:59 2001
+++ linux/kernel/ksyms.c	Mon Dec  3 22:35:23 2001
@@ -129,7 +129,6 @@
 EXPORT_SYMBOL(update_atime);
 EXPORT_SYMBOL(get_fs_type);
 EXPORT_SYMBOL(get_super);
-EXPORT_SYMBOL(get_empty_super);
 EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(names_cachep);
 EXPORT_SYMBOL(fput);
diff -urN linux-2.4.4-pre3/lib/Makefile linux/lib/Makefile
--- linux-2.4.4-pre3/lib/Makefile	Mon Dec  3 22:35:13 2001
+++ linux/lib/Makefile	Mon Dec  3 22:35:23 2001
@@ -8,9 +8,14 @@
 
 L_TARGET := lib.a
 
-export-objs := cmdline.o rwsem.o
+export-objs := cmdline.o
 
-obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o rwsem.o
+obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o
+
+ifneq ($(CONFIG_RWSEM_GENERIC_SPINLOCK)$(CONFIG_RWSEM_XCHGADD_ALGORITHM),nn)
+export-objs += rwsem.o
+obj-y += rwsem.o
+endif
 
 ifneq ($(CONFIG_HAVE_DEC_LOCK),y) 
   obj-y += dec_and_lock.o
diff -urN linux-2.4.4-pre3/lib/rwsem.c linux/lib/rwsem.c
--- linux-2.4.4-pre3/lib/rwsem.c	Mon Dec  3 22:35:13 2001
+++ linux/lib/rwsem.c	Mon Dec  3 22:35:23 2001
@@ -18,7 +18,7 @@
 	DECLARE_WAITQUEUE(wait,tsk);
 	signed long count;
 
-	rwsemdebug("[%d] Entering rwsem_down_read_failed(%08lx)\n",current->pid,sem->count);
+	rwsemtrace(sem,"Entering rwsem_down_read_failed");
 
 	/* this waitqueue context flag will be cleared when we are granted the lock */
 	__set_bit(RWSEM_WAITING_FOR_READ,&wait.flags);
@@ -28,7 +28,6 @@
 
 	/* note that we're now waiting on the lock, but no longer actively read-locking */
 	count = rwsem_atomic_update(RWSEM_WAITING_BIAS-RWSEM_ACTIVE_BIAS,sem);
-	rwsemdebug("X(%08lx)\n",count);
 
 	/* if there are no longer active locks, wake the front queued process(es) up
 	 * - it might even be this process, since the waker takes a more active part
@@ -47,8 +46,7 @@
 	remove_wait_queue(&sem->wait,&wait);
 	tsk->state = TASK_RUNNING;
 
-	rwsemdebug("[%d] Leaving rwsem_down_read_failed(%08lx)\n",current->pid,sem->count);
-
+	rwsemtrace(sem,"Leaving rwsem_down_read_failed");
 	return sem;
 }
 
@@ -61,7 +59,7 @@
 	DECLARE_WAITQUEUE(wait,tsk);
 	signed long count;
 
-	rwsemdebug("[%d] Entering rwsem_down_write_failed(%08lx)\n",current->pid,sem->count);
+	rwsemtrace(sem,"Entering rwsem_down_write_failed");
 
 	/* this waitqueue context flag will be cleared when we are granted the lock */
 	__set_bit(RWSEM_WAITING_FOR_WRITE,&wait.flags);
@@ -71,7 +69,6 @@
 
 	/* note that we're waiting on the lock, but no longer actively locking */
 	count = rwsem_atomic_update(-RWSEM_ACTIVE_BIAS,sem);
-	rwsemdebug("[%d] updated(%08lx)\n",current->pid,count);
 
 	/* if there are no longer active locks, wake the front queued process(es) up
 	 * - it might even be this process, since the waker takes a more active part
@@ -90,8 +87,7 @@
 	remove_wait_queue(&sem->wait,&wait);
 	tsk->state = TASK_RUNNING;
 
-	rwsemdebug("[%d] Leaving rwsem_down_write_failed(%08lx)\n",current->pid,sem->count);
-
+	rwsemtrace(sem,"Leaving rwsem_down_write_failed");
 	return sem;
 }
 
@@ -106,7 +102,7 @@
 	signed long count;
 	int woken;
 
-	rwsemdebug("[%d] Entering rwsem_wake(%08lx)\n",current->pid,sem->count);
+	rwsemtrace(sem,"Entering rwsem_wake");
 
  try_again:
 	/* try to grab an 'activity' marker
@@ -115,7 +111,7 @@
 	 * - be horribly naughty, and only deal with the LSW of the atomic counter
 	 */
 	if (rwsem_cmpxchgw(sem,0,RWSEM_ACTIVE_BIAS)!=0) {
-		rwsemdebug("[%d] rwsem_wake: abort wakeup due to renewed activity\n",current->pid);
+		rwsemtrace(sem,"rwsem_wake: abort wakeup due to renewed activity");
 		goto out;
 	}
 
@@ -139,13 +135,13 @@
 	rwsem_atomic_update(woken,sem);
 
  out:
-	rwsemdebug("[%d] Leaving rwsem_wake(%08lx)\n",current->pid,sem->count);
+	rwsemtrace(sem,"Leaving rwsem_wake");
 	return sem;
 
 	/* come here if we need to correct the counter for odd SMP-isms */
  counter_correction:
 	count = rwsem_atomic_update(-RWSEM_ACTIVE_BIAS,sem);
-	rwsemdebug("[%d] corrected(%08lx)\n",current->pid,count);
+	rwsemtrace(sem,"corrected count");
 	if (!(count & RWSEM_ACTIVE_MASK))
 		goto try_again;
 	goto out;
diff -urN linux-2.4.4-pre3/lib/vsprintf.c linux/lib/vsprintf.c
--- linux-2.4.4-pre3/lib/vsprintf.c	Tue Mar  6 19:44:37 2001
+++ linux/lib/vsprintf.c	Mon Dec  3 22:35:23 2001
@@ -377,7 +377,7 @@
  * sprintf - Format a string and place it in a buffer
  * @buf: The buffer to place the result into
  * @fmt: The format string to use
- * @args: Arguments for the format string
+ * @...: Arguments for the format string
  */
 int sprintf(char * buf, const char *fmt, ...)
 {
diff -urN linux-2.4.4-pre3/mm/bootmem.c linux/mm/bootmem.c
--- linux-2.4.4-pre3/mm/bootmem.c	Wed Oct 18 15:18:41 2000
+++ linux/mm/bootmem.c	Mon Dec  3 22:35:23 2001
@@ -176,6 +176,7 @@
 		preferred = 0;
 		goto restart_scan;
 	}
+	return NULL;
 found:
 	if (start >= eidx)
 		BUG();
@@ -316,7 +317,8 @@
 	/*
 	 * Whoops, we cannot satisfy the allocation request.
 	 */
-	BUG();
+	printk(KERN_ALERT "bootmem alloc of %lu bytes failed!\n", size);
+	panic("Out of memory");
 	return NULL;
 }
 
diff -urN linux-2.4.4-pre3/mm/filemap.c linux/mm/filemap.c
--- linux-2.4.4-pre3/mm/filemap.c	Mon Dec  3 22:35:13 2001
+++ linux/mm/filemap.c	Mon Dec  3 22:35:23 2001
@@ -2456,12 +2456,13 @@
 	unsigned long	written;
 	long		status;
 	int		err;
+	unsigned	bytes;
 
 	cached_page = NULL;
 
 	if (!access_ok(VERIFY_READ, buf, count))
 		return -EFAULT;
-
+		
 	down(&inode->i_sem);
 
 	pos = *ppos;
@@ -2484,26 +2485,64 @@
 	 * Check whether we've reached the file size limit.
 	 */
 	err = -EFBIG;
+	
 	if (limit != RLIM_INFINITY) {
 		if (pos >= limit) {
 			send_sig(SIGXFSZ, current, 0);
 			goto out;
 		}
-		if (count > limit - pos) {
+		if (pos > 0xFFFFFFFFULL || count > limit - (u32)pos) {
+			/* send_sig(SIGXFSZ, current, 0); */
+			count = limit - (u32)pos;
+		}
+	}
+
+	/*
+	 *	LFS rule 
+	 */
+	if ( pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) {
+		if (pos >= MAX_NON_LFS) {
 			send_sig(SIGXFSZ, current, 0);
-			count = limit - pos;
+			goto out;
+		}
+		if (count > MAX_NON_LFS - (u32)pos) {
+			/* send_sig(SIGXFSZ, current, 0); */
+			count = MAX_NON_LFS - (u32)pos;
 		}
 	}
 
-	status  = 0;
-	if (count) {
-		remove_suid(inode);
-		inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-		mark_inode_dirty_sync(inode);
+	/*
+	 *	Are we about to exceed the fs block limit ?
+	 *
+	 *	If we have written data it becomes a short write
+	 *	If we have exceeded without writing data we send
+	 *	a signal and give them an EFBIG.
+	 *
+	 *	Linus frestrict idea will clean these up nicely..
+	 */
+	 
+	if (pos > inode->i_sb->s_maxbytes)
+	{
+		send_sig(SIGXFSZ, current, 0);
+		err = -EFBIG;
+		goto out;	
+	}
+
+	if (pos + count > inode->i_sb->s_maxbytes)
+		count = inode->i_sb->s_maxbytes - pos;
+
+	if (count == 0) {
+		err = 0;
+		goto out;
 	}
 
+	status  = 0;
+	remove_suid(inode);
+	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+	mark_inode_dirty_sync(inode);
+
 	while (count) {
-		unsigned long bytes, index, offset;
+		unsigned long index, offset;
 		char *kaddr;
 		int deactivate = 1;
 
diff -urN linux-2.4.4-pre3/mm/mmap.c linux/mm/mmap.c
--- linux-2.4.4-pre3/mm/mmap.c	Mon Dec  3 22:35:13 2001
+++ linux/mm/mmap.c	Mon Dec  3 22:35:23 2001
@@ -418,6 +418,8 @@
 		addr = vma->vm_end;
 	}
 }
+#else
+extern unsigned long arch_get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 #endif	
 
 unsigned long get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
diff -urN linux-2.4.4-pre3/net/sunrpc/sysctl.c linux/net/sunrpc/sysctl.c
--- linux-2.4.4-pre3/net/sunrpc/sysctl.c	Sun Oct  1 20:35:16 2000
+++ linux/net/sunrpc/sysctl.c	Mon Dec  3 22:35:23 2001
@@ -63,7 +63,7 @@
 {
 	char		tmpbuf[20], *p, c;
 	unsigned int	value;
-	int		left, len;
+	size_t		left, len;
 
 	if ((file->f_pos && !write) || !*lenp) {
 		*lenp = 0;
