patch-2.4.19 linux-2.4.19/arch/mips/kernel/setup.c

Next file: linux-2.4.19/arch/mips/kernel/signal.c
Previous file: linux-2.4.19/arch/mips/kernel/scall_o32.S
Back to the patch index
Back to the overall index

diff -urN linux-2.4.18/arch/mips/kernel/setup.c linux-2.4.19/arch/mips/kernel/setup.c
@@ -4,9 +4,10 @@
  * for more details.
  *
  * Copyright (C) 1995  Linus Torvalds
- * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000  Ralf Baechle
+ * Copyright (C) 1995  Waldorf Electronics
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001  Ralf Baechle
  * Copyright (C) 1996  Stoned Elipot
- * Copyright (C) 2000  Maciej W. Rozycki
+ * Copyright (C) 2000, 2001  Maciej W. Rozycki
  */
 #include <linux/config.h>
 #include <linux/errno.h>
@@ -16,10 +17,10 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/module.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>
@@ -35,14 +36,12 @@
 #include <asm/cachectl.h>
 #include <asm/cpu.h>
 #include <asm/io.h>
-#include <asm/stackframe.h>
+#include <asm/ptrace.h>
 #include <asm/system.h>
-#ifdef CONFIG_SGI_IP22
-#include <asm/sgialib.h>
-#endif
 
-
-struct mips_cpuinfo boot_cpu_data = { 0, NULL, NULL, 0 };
+#ifndef CONFIG_SMP
+struct cpuinfo_mips cpu_data[1];
+#endif
 
 /*
  * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
@@ -95,21 +94,24 @@
 unsigned char aux_device_present;
 extern char _ftext, _etext, _fdata, _edata, _end;
 
-static char command_line[COMMAND_LINE_SIZE];
-       char saved_command_line[COMMAND_LINE_SIZE];
-extern char arcs_cmdline[COMMAND_LINE_SIZE];
+static char command_line[CL_SIZE];
+       char saved_command_line[CL_SIZE];
+extern char arcs_cmdline[CL_SIZE];
 
 /*
  * mips_io_port_base is the begin of the address space to which x86 style
  * I/O ports are mapped.
  */
-unsigned long mips_io_port_base;
+const unsigned long mips_io_port_base = -1;
+EXPORT_SYMBOL(mips_io_port_base);
+
 
 /*
  * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped
  * for the processor.
  */
 unsigned long isa_slot_offset;
+EXPORT_SYMBOL(isa_slot_offset);
 
 extern void sgi_sysinit(void);
 extern void SetUpBootInfo(void);
@@ -120,6 +122,49 @@
 static struct resource code_resource = { "Kernel code" };
 static struct resource data_resource = { "Kernel data" };
 
+static inline void check_wait(void)
+{
+	printk("Checking for 'wait' instruction... ");
+	switch(mips_cpu.cputype) {
+	case CPU_R3081:
+	case CPU_R3081E:
+		cpu_wait = r3081_wait;
+		printk(" available.\n");
+		break;
+	case CPU_TX3927:
+	case CPU_TX39XX:
+		cpu_wait = r39xx_wait;
+		printk(" available.\n");
+		break;
+	case CPU_R4200: 
+/*	case CPU_R4300: */
+	case CPU_R4600: 
+	case CPU_R4640: 
+	case CPU_R4650: 
+	case CPU_R4700: 
+	case CPU_R5000: 
+	case CPU_NEVADA:
+	case CPU_RM7000:
+	case CPU_TX49XX:
+	case CPU_4KC:
+	case CPU_4KEC:
+	case CPU_4KSC:
+	case CPU_5KC:
+/*	case CPU_20KC:*/
+		cpu_wait = r4k_wait;
+		printk(" available.\n");
+		break;
+	default:
+		printk(" unavailable.\n");
+		break;
+	}
+}
+
+void __init check_bugs(void)
+{
+	check_wait();
+}
+
 /*
  * Probe whether cpu has config register by trying to play with
  * alternate cache bit and see whether it matters.
@@ -142,9 +187,34 @@
 #endif
 }
 
+/*
+ * Get the FPU Implementation/Revision.
+ */
+static inline unsigned long cpu_get_fpu_id(void)
+{
+	unsigned long tmp, fpu_id;
+
+	tmp = read_32bit_cp0_register(CP0_STATUS);
+	__enable_fpu();
+	fpu_id = read_32bit_cp1_register(CP1_REVISION);
+	write_32bit_cp0_register(CP0_STATUS, tmp);
+	return fpu_id;
+}
+
+/*
+ * Check the CPU has an FPU the official way.
+ */
+static inline int cpu_has_fpu(void)
+{
+	return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE);
+}
+
 /* 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}};
+struct mips_cpu mips_cpu = {
+    processor_id:	PRID_IMP_UNKNOWN,
+    fpu_id:		FPIR_IMP_NONE,
+    cputype:		CPU_UNKNOWN
+};
 
 /* Shortcut for assembler access to mips_cpu.options */
 int *cpuoptions = &mips_cpu.options;
@@ -154,11 +224,27 @@
 
 static inline void cpu_probe(void)
 {
-
 #ifdef CONFIG_CPU_MIPS32
+	unsigned long config0 = read_32bit_cp0_register(CP0_CONFIG);
 	unsigned long config1;
-#endif
 
+        if (config0 & (1 << 31)) {
+		/* MIPS32 compliant CPU. Read Config 1 register. */
+		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;
+		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 << 1))
+			mips_cpu.options |= MIPS_CPU_EJTAG;
+		if (config1 & 1)
+			mips_cpu.options |= MIPS_CPU_FPU;
+		mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
+	}
+#endif
 	mips_cpu.processor_id = read_32bit_cp0_register(CP0_PRID);
 	switch (mips_cpu.processor_id & 0xff0000) {
 	case PRID_COMP_LEGACY:
@@ -166,7 +252,9 @@
 		case PRID_IMP_R2000:
 			mips_cpu.cputype = CPU_R2000;
 			mips_cpu.isa_level = MIPS_CPU_ISA_I;
-			mips_cpu.options = MIPS_CPU_TLB;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX;
+			if (cpu_has_fpu())
+				mips_cpu.options |= MIPS_CPU_FPU;
 			mips_cpu.tlbsize = 64;
 			break;
 		case PRID_IMP_R3000:
@@ -178,7 +266,9 @@
 			else
 				mips_cpu.cputype = CPU_R3000;
 			mips_cpu.isa_level = MIPS_CPU_ISA_I;
-			mips_cpu.options = MIPS_CPU_TLB;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX;
+			if (cpu_has_fpu())
+				mips_cpu.options |= MIPS_CPU_FPU;
 			mips_cpu.tlbsize = 64;
 			break;
 		case PRID_IMP_R4000:
@@ -187,8 +277,9 @@
 			else
 				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.options = R4K_OPTS | MIPS_CPU_FPU |
+			                   MIPS_CPU_32FPR | MIPS_CPU_WATCH |
+			                   MIPS_CPU_VCE;
 			mips_cpu.tlbsize = 48;
 			break;
                 case PRID_IMP_VR41XX:
@@ -197,67 +288,101 @@
                         mips_cpu.options = R4K_OPTS;
                         mips_cpu.tlbsize = 32;
                         break;
+		case PRID_IMP_R4300:
+			mips_cpu.cputype = CPU_R4300;
+			mips_cpu.isa_level = MIPS_CPU_ISA_III;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU |
+					   MIPS_CPU_32FPR;
+			mips_cpu.tlbsize = 32;
+			break;
 		case PRID_IMP_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:
+		#if 0
+ 		case PRID_IMP_R4650:
+			/*
+			 * This processor doesn't have an MMU, so it's not
+			 * "real easy" to run Linux on it. It is left purely
+			 * for documentation.  Commented out because it shares
+			 * it's c0_prid id number with the TX3900.
+			 */
 	 		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;
-*/
+		#endif
 		case PRID_IMP_TX39:
 			mips_cpu.isa_level = MIPS_CPU_ISA_I;
 			mips_cpu.options = MIPS_CPU_TLB;
 
-			switch (mips_cpu.processor_id & 0xff) {
-			case PRID_REV_TX3912:
-				mips_cpu.cputype = CPU_TX3912;
-				mips_cpu.tlbsize = 32;
-				break;
-			case PRID_REV_TX3922:
-				mips_cpu.cputype = CPU_TX3922;
-				mips_cpu.tlbsize = 64;
-				break;
-			case PRID_REV_TX3927:
+			if ((mips_cpu.processor_id & 0xf0) ==
+			    (PRID_REV_TX3927 & 0xf0)) {
 				mips_cpu.cputype = CPU_TX3927;
 				mips_cpu.tlbsize = 64;
-				break;
-			default:
-				mips_cpu.cputype = CPU_UNKNOWN;
-				break;
+				mips_cpu.icache.ways = 2;
+				mips_cpu.dcache.ways = 2;
+			} else {
+				switch (mips_cpu.processor_id & 0xff) {
+				case PRID_REV_TX3912:
+					mips_cpu.cputype = CPU_TX3912;
+					mips_cpu.tlbsize = 32;
+					break;
+				case PRID_REV_TX3922:
+					mips_cpu.cputype = CPU_TX3922;
+					mips_cpu.tlbsize = 64;
+					break;
+				default:
+					mips_cpu.cputype = CPU_UNKNOWN;
+					break;
+				}
 			}
 			break;
 		case PRID_IMP_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.options = R4K_OPTS | MIPS_CPU_FPU |
+			                   MIPS_CPU_32FPR;
 			mips_cpu.tlbsize = 48;
 			break;
+		case PRID_IMP_TX49:
+			mips_cpu.cputype = CPU_TX49XX;
+			mips_cpu.isa_level = MIPS_CPU_ISA_III;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU |
+			                   MIPS_CPU_32FPR;
+			mips_cpu.tlbsize = 48;
+			mips_cpu.icache.ways = 4;
+			mips_cpu.dcache.ways = 4;
+			break;
 		case PRID_IMP_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.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.options = R4K_OPTS | MIPS_CPU_FPU |
+			                   MIPS_CPU_32FPR | MIPS_CPU_WATCH;
+			mips_cpu.tlbsize = 48;
+			break;
+		case PRID_IMP_R5500:
+			mips_cpu.cputype = CPU_R5500;
+			mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU |
+			                   MIPS_CPU_32FPR | MIPS_CPU_WATCH;
 			mips_cpu.tlbsize = 48;
 			break;
 		case PRID_IMP_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.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;
@@ -277,7 +402,17 @@
 		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;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU |
+			                   MIPS_CPU_32FPR;
+			/*
+			 * Undocumented RM7000:  Bit 29 in the info register of
+			 * the RM7000 v2.0 indicates if the TLB has 48 or 64
+			 * entries.
+			 *
+			 * 29      1 =>    64 entry JTLB
+			 *         0 =>    48 entry JTLB
+			 */
+			mips_cpu.tlbsize = (get_info() & (1 << 29)) ? 64 : 48;
 			break;
 		case PRID_IMP_R8000:
 			mips_cpu.cputype = CPU_R8000;
@@ -294,6 +429,14 @@
 				           MIPS_CPU_COUNTER | MIPS_CPU_WATCH;
 			mips_cpu.tlbsize = 64;
 			break;
+		case PRID_IMP_R12000:
+			mips_cpu.cputype = CPU_R12000;
+			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;
 		default:
 			mips_cpu.cputype = CPU_UNKNOWN;
 			break;
@@ -304,80 +447,53 @@
 		switch (mips_cpu.processor_id & 0xff00) {
 		case PRID_IMP_4KC:
 			mips_cpu.cputype = CPU_4KC;
-			goto cpu_4kc;
+			break;
 		case PRID_IMP_4KEC:
 			mips_cpu.cputype = CPU_4KEC;
-			goto cpu_4kc;
+			break;
 		case PRID_IMP_4KSC:
 			mips_cpu.cputype = CPU_4KSC;
-cpu_4kc:
-			/* Why do we set all these options by default, THEN query them?? */
-			mips_cpu.cputype = 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.cputype = MIPS_CPU_ISA_M64;
-			/* See comment above about querying options */
-			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.isa_level = MIPS_CPU_ISA_M64;
+			break;
+		case PRID_IMP_20KC:
+			mips_cpu.cputype = CPU_20KC;
+			mips_cpu.isa_level = MIPS_CPU_ISA_M64;
 			break;
-			mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
 		default:
 			mips_cpu.cputype = CPU_UNKNOWN;
 			break;
 		}		
 		break;
-#endif
 	case PRID_COMP_ALCHEMY:
 		switch (mips_cpu.processor_id & 0xff00) {
-#ifdef CONFIG_CPU_MIPS32
-		case PRID_IMP_AU1000:
-			mips_cpu.cputype = CPU_AU1000;
-			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;
+		case PRID_IMP_AU1_REV1:
+		case PRID_IMP_AU1_REV2:
+			if (mips_cpu.processor_id & 0xff000000)
+				mips_cpu.cputype = CPU_AU1500;
+			else
+				mips_cpu.cputype = CPU_AU1000;
 			break;
-#endif
 		default:
 			mips_cpu.cputype = CPU_UNKNOWN;
 			break;
 		}
 		break;
+#endif /* CONFIG_CPU_MIPS32 */
 	case PRID_COMP_SIBYTE:
 		switch (mips_cpu.processor_id & 0xff00) {
 		case PRID_IMP_SB1:
 			mips_cpu.cputype = CPU_SB1;
-			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
-				           MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | MIPS_CPU_FPU |
-		      	           MIPS_CPU_VCE;
+			mips_cpu.isa_level = MIPS_CPU_ISA_M64;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+			                   MIPS_CPU_COUNTER | MIPS_CPU_DIVEC |
+			                   MIPS_CPU_MCHECK;
+#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
+			/* FPU in pass1 is known to have issues. */
+			mips_cpu.options |= MIPS_CPU_FPU;
+#endif
 			break;
 		default:
 			mips_cpu.cputype = CPU_UNKNOWN;
@@ -387,6 +503,15 @@
 	default:
 		mips_cpu.cputype = CPU_UNKNOWN;
 	}
+	if (mips_cpu.options & MIPS_CPU_FPU)
+		mips_cpu.fpu_id = cpu_get_fpu_id();
+}
+
+static inline void cpu_report(void)
+{
+	printk("CPU revision is: %08x\n", mips_cpu.processor_id);
+	if (mips_cpu.options & MIPS_CPU_FPU)
+		printk("FPU revision is: %08x\n", mips_cpu.fpu_id);
 }
 
 asmlinkage void __init
@@ -403,6 +528,8 @@
 	sgi_sysinit();
 #endif
 
+	cpu_report();
+
 	/*
 	 * Determine the mmu/cache attached to this machine,
 	 * then flush the tlb and caches.  On the r4xx0
@@ -410,16 +537,14 @@
 	 */
 	loadmmu();
 
-	/* 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|ST0_FR);
-	s |= ST0_CU0;
-	write_32bit_cp0_register(CP0_STATUS, s);
+	/* Disable coprocessors and set FPU for 16/32 FPR register model */
+	clear_cp0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR);
+	set_cp0_status(ST0_CU0);
 
 	start_kernel();
 }
 
-void __init add_memory_region(unsigned long start, unsigned long size,
+void __init add_memory_region(phys_t start, phys_t size,
 			      long type)
 {
 	int x = boot_mem_map.nr_map;
@@ -440,8 +565,10 @@
 	int i;
 
 	for (i = 0; i < boot_mem_map.nr_map; i++) {
-		printk(" memory: %08lx @ %08lx ",
-			boot_mem_map.map[i].size, boot_mem_map.map[i].addr);
+		printk(" memory: %08Lx @ %08Lx ",
+			(u64) boot_mem_map.map[i].size,
+		        (u64) boot_mem_map.map[i].addr);
+
 		switch (boot_mem_map.map[i].type) {
 		case BOOT_MEM_RAM:
 			printk("(usable)\n");
@@ -498,7 +625,7 @@
 		c = *(from++);
 		if (!c)
 			break;
-		if (COMMAND_LINE_SIZE <= ++len)
+		if (CL_SIZE <= ++len)
 			break;
 		*(to++) = c;
 	}
@@ -514,19 +641,30 @@
 {
 	void atlas_setup(void);
 	void baget_setup(void);
+	void cobalt_setup(void);
 	void ddb_setup(void);
 	void decstation_setup(void);
 	void deskstation_setup(void);
 	void jazz_setup(void);
 	void sni_rm200_pci_setup(void);
-	void sgi_setup(void);
+	void ip22_setup(void);
         void ev96100_setup(void);
 	void malta_setup(void);
+	void ikos_setup(void);
 	void momenco_ocelot_setup(void);
 	void nino_setup(void);
+	void nec_osprey_setup(void);
+	void jmr3927_setup(void);
+ 	void it8172_setup(void);
+	void swarm_setup(void);
+	void hp_setup(void);
 
 	unsigned long bootmap_size;
-	unsigned long start_pfn, max_pfn, first_usable_pfn;
+	unsigned long start_pfn, max_pfn, max_low_pfn, first_usable_pfn;
+#ifdef CONFIG_BLK_DEV_INITRD
+	unsigned long tmp;
+	unsigned long* initrd_header;
+#endif
 
 	int i;
 
@@ -551,6 +689,11 @@
 		baget_setup();
 		break;
 #endif
+#ifdef CONFIG_MIPS_COBALT
+        case MACH_GROUP_COBALT:
+                cobalt_setup();
+                break;
+#endif
 #ifdef CONFIG_DECSTATION
 	case MACH_GROUP_DEC:
 		decstation_setup();
@@ -579,7 +722,7 @@
 #ifdef CONFIG_SGI_IP22
 	/* As of now this is only IP22.  */
 	case MACH_GROUP_SGI:
-		sgi_setup();
+		ip22_setup();
 		break;
 #endif
 #ifdef CONFIG_SNI_RM200_PCI
@@ -602,6 +745,11 @@
                ddb_setup();
                break;
 #endif
+#ifdef CONFIG_NEC_OSPREY
+	case MACH_GROUP_NEC_VR41XX:
+		nec_osprey_setup();
+		break;
+#endif
 #ifdef CONFIG_MIPS_EV96100
 	case MACH_GROUP_GALILEO:
 		ev96100_setup();
@@ -628,6 +776,26 @@
 		au1000_setup();
 		break;
 #endif
+#ifdef CONFIG_MIPS_PB1500
+	case MACH_GROUP_ALCHEMY:
+		au1500_setup();
+		break;
+#endif
+#ifdef CONFIG_TOSHIBA_JMR3927
+	case MACH_GROUP_TOSHIBA:
+		jmr3927_setup();
+		break;
+#endif
+#ifdef CONFIG_SIBYTE_SWARM
+	case MACH_GROUP_SIBYTE:
+		swarm_setup();
+		break;
+#endif
+#ifdef CONFIG_HP_LASERJET
+        case MACH_GROUP_HP_LJ:
+                hp_setup();
+                break;
+#endif
 	default:
 		panic("Unsupported architecture");
 	}
@@ -643,11 +811,26 @@
 #define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
 #define PFN_PHYS(x)	((x) << PAGE_SHIFT)
 
+#define MAXMEM		HIGHMEM_START
+#define MAXMEM_PFN	PFN_DOWN(MAXMEM)
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8; 
+	if (tmp < (unsigned long)&_end) 
+		tmp += PAGE_SIZE;
+	initrd_header = (unsigned long *)tmp;
+	if (initrd_header[0] == 0x494E5244) {
+		initrd_start = (unsigned long)&initrd_header[2];
+		initrd_end = initrd_start + initrd_header[1];
+	}
+	start_pfn = PFN_UP(__pa((&_end)+(initrd_end - initrd_start) + PAGE_SIZE));
+#else
 	/*
 	 * Partially used pages are not usable - thus
 	 * we are rounding upwards.
 	 */
 	start_pfn = PFN_UP(__pa(&_end));
+#endif	/* CONFIG_BLK_DEV_INITRD */
 
 	/* Find the highest page frame number we have available.  */
 	max_pfn = 0;
@@ -674,9 +857,36 @@
 			}
 		}
 	}
-	
-	/* Initialize the boot-time allocator.  */
-	bootmap_size = init_bootmem(first_usable_pfn, max_pfn);
+
+	/*
+	 * Determine low and high memory ranges
+	 */
+	max_low_pfn = max_pfn;
+	if (max_low_pfn > MAXMEM_PFN) {
+		max_low_pfn = MAXMEM_PFN;
+#ifndef CONFIG_HIGHMEM
+		/* Maximum memory usable is what is directly addressable */
+		printk(KERN_WARNING "Warning only %ldMB will be used.\n",
+		       MAXMEM>>20);
+		printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+#endif
+	}
+
+#ifdef CONFIG_HIGHMEM
+	/*
+	 * Crude, we really should make a better attempt at detecting
+	 * highstart_pfn
+	 */
+	highstart_pfn = highend_pfn = max_pfn;
+	if (max_pfn > MAXMEM_PFN) {
+		highstart_pfn = MAXMEM_PFN;
+		printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+		       (highend_pfn - highstart_pfn) >> (20 - PAGE_SHIFT));
+	}
+#endif
+
+	/* Initialize the boot-time allocator with low memory only.  */
+	bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn);
 
 	/*
 	 * Register fully available low RAM pages with the bootmem allocator.
@@ -694,7 +904,7 @@
 		 * We are rounding up the start address of usable memory:
 		 */
 		curr_pfn = PFN_UP(boot_mem_map.map[i].addr);
-		if (curr_pfn >= max_pfn)
+		if (curr_pfn >= max_low_pfn)
 			continue;
 		if (curr_pfn < start_pfn)
 			curr_pfn = start_pfn;
@@ -705,8 +915,19 @@
 		last_pfn = PFN_DOWN(boot_mem_map.map[i].addr
 				    + boot_mem_map.map[i].size);
 
-		if (last_pfn > max_pfn)
-			last_pfn = max_pfn;
+		if (last_pfn > max_low_pfn)
+			last_pfn = max_low_pfn;
+
+		/*
+		 * Only register lowmem part of lowmem segment with bootmem.
+		 */
+		size = last_pfn - curr_pfn;
+		if (curr_pfn > PFN_DOWN(HIGHMEM_START))
+			continue;
+		if (curr_pfn + size - 1 > PFN_DOWN(HIGHMEM_START))
+			size = PFN_DOWN(HIGHMEM_START) - curr_pfn;
+		if (!size)
+			continue;
 
 		/*
 		 * ... finally, did all the rounding and playing
@@ -715,7 +936,7 @@
 		if (last_pfn <= curr_pfn)
 			continue;
 
-		size = last_pfn - curr_pfn;
+		/* Register lowmem ranges */
 		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
 	}
 
@@ -725,7 +946,7 @@
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* Board specific code should have set up initrd_start and initrd_end */
 	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
-	if( __rd_start != __rd_end ) {
+	if (&__rd_start != &__rd_end) {
 		initrd_start = (unsigned long)&__rd_start;
 		initrd_end = (unsigned long)&__rd_end;
 	}
@@ -757,6 +978,7 @@
 	 */
 	for (i = 0; i < boot_mem_map.nr_map; i++) {
 		struct resource *res;
+		unsigned long addr_pfn, end_pfn;
 
 		res = alloc_bootmem(sizeof(struct resource));
 		switch (boot_mem_map.map[i].type) {
@@ -768,8 +990,16 @@
 		default:
 			res->name = "reserved";
 		}
+		addr_pfn = PFN_UP(boot_mem_map.map[i].addr);
+		end_pfn = PFN_UP(boot_mem_map.map[i].addr+boot_mem_map.map[i].size);
+		if (addr_pfn > max_low_pfn)
+			continue;
 		res->start = boot_mem_map.map[i].addr;
-		res->end = res->start + boot_mem_map.map[i].size - 1;
+		if (end_pfn < max_low_pfn) {
+			res->end = res->start + boot_mem_map.map[i].size - 1;
+		} else {
+			res->end = max_low_pfn - 1;
+		}
 		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 		request_resource(&iomem_resource, res);
 
@@ -789,9 +1019,22 @@
 	write_32bit_cp0_register(CP0_CONF, cfg|CONF_HALT);
 }
 
+void r39xx_wait(void)
+{
+	unsigned long cfg = read_32bit_cp0_register(CP0_CONF);
+	write_32bit_cp0_register(CP0_CONF, cfg|TX39_CONF_HALT);
+}
+
 void r4k_wait(void)
 {
 	__asm__(".set\tmips3\n\t"
 		"wait\n\t"
 		".set\tmips0");
 }
+
+static int __init fpu_disable(char *s)
+{
+	mips_cpu.options &= ~MIPS_CPU_FPU;
+	return 1;
+}
+__setup("nofpu", fpu_disable);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)