summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/setup.c')
-rw-r--r--arch/mips/kernel/setup.c328
1 files changed, 207 insertions, 121 deletions
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index f5037fbd7..30304abda 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -2,10 +2,12 @@
* linux/arch/mips/kernel/setup.c
*
* Copyright (C) 1995 Linus Torvalds
- * Copyright (C) 1995 Ralf Baechle
+ * Copyright (C) 1995, 1996 Ralf Baechle
+ * Copyright (C) 1996 Stoned Elipot
*/
-
+#include <linux/config.h>
#include <linux/errno.h>
+#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -14,15 +16,20 @@
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/malloc.h>
-#include <linux/ldt.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 <asm/asm.h>
#include <asm/bootinfo.h>
+#include <asm/cache.h>
+#include <asm/io.h>
#include <asm/vector.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
#include <asm/stackframe.h>
#include <asm/system.h>
@@ -31,177 +38,256 @@
*/
struct feature *feature;
-#ifdef CONFIG_ACER_PICA_61
-void acer_pica_61_handle_int(void);
-struct feature acer_pica_61_feature = {
- acer_pica_61_handle_int
-};
-#endif
-#ifdef CONFIG_DECSTATION
-void decstation_handle_handle_int(void);
-struct feature decstation_feature = {
- decstation_handle_handle_int
-};
-#endif
-#ifdef CONFIG_DESKSTATION_RPC44
-void deskstation_rpc44_handle_int(void);
-struct feature deskstation_rpc44_feature = {
- deskstation_rpc44_handle_int
-};
-#endif
-#ifdef CONFIG_DESKSTATION_TYNE
-void deskstation_tyne_handle_int(void);
-struct feature deskstation_tyne_feature = {
- deskstation_tyne_handle_int
-};
-#endif
-#ifdef CONFIG_MIPS_MAGNUM_4000
-void mips_magnum_4000_handle_int(void);
-struct feature mips_magnum_4000_feature = {
- mips_magnum_4000_handle_int
-};
-#endif
+/*
+ * What to do to keep the caches consistent with memory
+ * We don't use the normal cacheflush routine to keep Tyne caches happier.
+ */
+void (*fd_cacheflush)(const void *addr, size_t size);
/*
- * Tell us the machine setup..
+ * Not all of the MIPS CPUs have the "wait" instruction available. This
+ * is set to true if it is available. The wait instruction stops the
+ * pipeline and reduces the power consumption of the CPU very much.
*/
-char wait_available; /* set if the "wait" instruction available */
+char wait_available;
/*
- * Bus types ..
+ * There are several bus types available for MIPS machines. "RISC PC"
+ * type machines have ISA, EISA or PCI available, some DECstations have
+ * Turbochannel, SGI has GIO, there are lots of VME boxes ...
+ * This flag is set if a EISA slots are available.
*/
int EISA_bus = 0;
/*
- * Setup options
+ * Do a hardware reset.
*/
-struct drive_info_struct drive_info;
-struct screen_info screen_info = SCREEN_INFO;
+void (*hard_reset_now)(void);
+
+/*
+ * Milo passes some information to the kernel that looks like as if it
+ * had been returned by a Intel PC BIOS. Milo doesn't fill the passed
+ * drive_info and Linux can find out about this anyway, so I'm going to
+ * remove this sometime. screen_info contains information about the
+ * resolution of the text screen. For VGA graphics based machine this
+ * information is being use to continue the screen output just below
+ * the BIOS printed text and with the same text resolution.
+ */
+struct drive_info_struct drive_info = DEFAULT_DRIVE_INFO;
+struct screen_info screen_info = DEFAULT_SCREEN_INFO;
+
+/*
+ * setup informations
+ *
+ * These are intialized so they are in the .data section
+ */
+unsigned long mips_memory_upper = KSEG0; /* this is set by kernel_entry() */
+unsigned long mips_cputype = CPU_UNKNOWN;
+unsigned long mips_machtype = MACH_UNKNOWN; /* this is set by bi_EarlySnarf() */
+unsigned long mips_machgroup = MACH_GROUP_UNKNOWN; /* this is set by bi_EarlySnarf() */
+unsigned long mips_tlb_entries = 48; /* this is set by bi_EarlySnarf() */
+unsigned long mips_vram_base = KSEG0;
-unsigned char aux_device_present;
-extern int ramdisk_size;
extern int root_mountflags;
extern int _end;
extern char empty_zero_page[PAGE_SIZE];
/*
- * Initialise this structure so that it will be placed in the
- * .data section of the object file
- */
-struct bootinfo boot_info = BOOT_INFO;
-
-/*
* This is set up by the setup-routine at boot-time
*/
#define PARAM empty_zero_page
-#if 0
-#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
-#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
-#endif
+#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
+#define INITRD_START (*(unsigned long *) (PARAM+0x218))
+#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
static char command_line[CL_SIZE] = { 0, };
+ char saved_command_line[CL_SIZE];
-#if 0
/*
- * Code for easy access to new style bootinfo
- *
- * Parameter: tag -- taglist entry
- *
- * returns : (tag *) -- pointer to taglist entry, NULL for not found
+ * The board specific setup routine sets irq_setup to point to a board
+ * specific setup routine.
*/
-tag *
-bi_TagFind(enum bi_tag tag)
+void (*irq_setup)(void);
+
+static void default_irq_setup(void)
{
- /* TBD */
- return 0;
+ panic("Unknown machtype in init_IRQ");
}
-/*
- * Only for taglist creators (bootloaders)
- *
- * Parameter: tag -- (enum bi_tag) taglist entry
- *
- * returns : 1 -- success
- * 0 -- failure
- */
-int
-bi_TagAdd(enum bi_tag tag, unsigned long size, void *tagdata)
+static void default_fd_cacheflush(const void *addr, size_t size)
{
- /* TBD */
- return 0;
}
-#endif /* 0 */
-void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p)
+static asmlinkage void
+default_cacheflush(unsigned long addr, unsigned long nbytes, unsigned int flags)
{
- unsigned long memory_start, memory_end;
+ /*
+ * Someone didn't set his cacheflush() handler ...
+ */
+ panic("default_cacheflush() called.\n");
+}
+asmlinkage void (*cacheflush)(unsigned long addr, unsigned long nbytes, unsigned int flags) = default_cacheflush;
- switch(boot_info.machtype)
- {
-#ifdef CONFIG_ACER_PICA_61
- case MACH_ACER_PICA_61:
- feature = &acer_pica_61_feature;
+static __inline__ void
+cpu_init(void)
+{
+ asmlinkage void handle_reserved(void);
+ void mips1_cpu_init(void);
+ void mips2_cpu_init(void);
+ void mips3_cpu_init(void);
+ void mips4_cpu_init(void);
+ int i;
+
+ /*
+ * Setup default vectors
+ */
+ for (i=0;i<=31;i++)
+ set_except_vector(i, handle_reserved);
+
+ switch(mips_cputype) {
+#ifdef CONFIG_CPU_R3000
+ case CPU_R2000: case CPU_R3000: case CPU_R3000A: case CPU_R3041:
+ case CPU_R3051: case CPU_R3052: case CPU_R3081: case CPU_R3081E:
+ mips1_cpu_init();
+ break;
+#endif
+#ifdef CONFIG_CPU_R6000
+ case CPU_R6000: case CPU_R6000A:
+ mips2_cpu_init();
break;
#endif
-#ifdef CONFIG_DECSTATION
- case MACH_DECSTATION:
- feature = &decstation_feature;
+#ifdef CONFIG_CPU_R4X00
+ case CPU_R4000MC: case CPU_R4400MC: case CPU_R4000SC:
+ case CPU_R4400SC: case CPU_R4000PC: case CPU_R4400PC:
+ case CPU_R4200: case CPU_R4300: /* case CPU_R4640: */
+ case CPU_R4600: case CPU_R4700:
+ mips3_cpu_init();
break;
#endif
-#ifdef CONFIG_DESKSTATION_RPC
- case MACH_DESKSTATION_RPC:
- feature = &deskstation_rpc44_feature;
+#ifdef CONFIG_CPU_R8000
+ case CPU_R8000: case CPU_R5000:
+ printk("Detected unsupported CPU type %s.\n",
+ cpu_names[mips_cputype]);
+ panic("Can't handle CPU");
break;
#endif
-#ifdef CONFIG_DESKSTATION_TYNE
- case MACH_DESKSTATION_TYNE:
- feature = &deskstation_tyne_feature;
+#ifdef CONFIG_CPU_R10000
+ case CPU_R10000:
+ mips4_cpu_init();
+#endif
+ case CPU_UNKNOWN:
+ default:
+ panic("Unknown or unsupported CPU type");
+ }
+}
+
+void setup_arch(char **cmdline_p,
+ unsigned long * memory_start_p, unsigned long * memory_end_p)
+{
+ unsigned long memory_end;
+ tag* atag;
+ void decstation_setup(void);
+ void deskstation_setup(void);
+ void jazz_setup(void);
+ void sni_rm200_pci_setup(void);
+
+ /* Perhaps a lot of tags are not getting 'snarfed' - */
+ /* please help yourself */
+
+ atag = bi_TagFind(tag_cputype);
+ memcpy(&mips_cputype, TAGVALPTR(atag), atag->size);
+
+ cpu_init();
+
+ atag = bi_TagFind(tag_vram_base);
+ memcpy(&mips_vram_base, TAGVALPTR(atag), atag->size);
+
+ irq_setup = default_irq_setup;
+ fd_cacheflush = default_fd_cacheflush;
+
+ switch(mips_machgroup)
+ {
+#ifdef CONFIG_MIPS_DECSTATION
+ case MACH_GROUP_DEC:
+ decstation_setup();
break;
#endif
-#ifdef CONFIG_MIPS_MAGNUM_4000
- case MACH_MIPS_MAGNUM_4000:
- feature = &mips_magnum_4000_feature;
+#if defined(CONFIG_MIPS_ARC)
+/* Perhaps arch/mips/deskstation should be renommed arch/mips/arc.
+ * For now CONFIG_MIPS_ARC means DeskStation. -Stoned.
+ */
+ case MACH_GROUP_ARC:
+ deskstation_setup();
+ break;
+#endif
+#ifdef CONFIG_MIPS_JAZZ
+ case MACH_GROUP_JAZZ:
+ jazz_setup();
+ break;
+#endif
+#ifdef CONFIG_SNI_RM200_PCI
+ case MACH_GROUP_SNI_RM:
+ sni_rm200_pci_setup();
break;
#endif
default:
panic("Unsupported architecture");
}
-#if 0
- ROOT_DEV = ORIG_ROOT_DEV;
-#else
- ROOT_DEV = 0x021c; /* fd0H1440 */
-/* ROOT_DEV = 0x0101; */ /* ram */
-/* ROOT_DEV = 0x00ff; */ /* NFS */
+ atag = bi_TagFind(tag_drive_info);
+ memcpy(&drive_info, TAGVALPTR(atag), atag->size);
+
+ memory_end = mips_memory_upper;
+ /*
+ * Due to prefetching and similar mechanism the CPU sometimes
+ * generates addresses beyond the end of memory. We leave the size
+ * of one cache line at the end of memory unused to make shure we
+ * don't catch this type of bus errors.
+ */
+ memory_end -= 32;
+ memory_end &= PAGE_MASK;
+
+#ifdef CONFIG_BLK_DEV_RAM
+ rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+ rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+ rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
#endif
- memcpy(&drive_info, &boot_info.drive_info, sizeof(drive_info));
-#if 0
- aux_device_present = AUX_DEVICE_INFO;
+#ifdef CONFIG_MAX_16M
+ /*
+ * There is a quite large number of different PC chipset based boards
+ * available and so I include this option here just in case ...
+ */
+ if (memory_end > PAGE_OFFSET + 16*1024*1024)
+ memory_end = PAGE_OFFSET + 16*1024*1024;
#endif
- memory_end = boot_info.memupper;
- memory_end &= PAGE_MASK;
- ramdisk_size = boot_info.ramdisk_size;
- if (boot_info.mount_root_rdonly)
- root_mountflags |= MS_RDONLY;
- memory_start = (unsigned long) &_end;
- memory_start += (ramdisk_size << 10);
+ atag= bi_TagFind(tag_screen_info);
+ if (atag)
+ memcpy(&screen_info, TAGVALPTR(atag), atag->size);
+
+ atag = bi_TagFind(tag_command_line);
+ if (atag)
+ memcpy(&command_line, TAGVALPTR(atag), atag->size);
+ printk("Command line: '%s'\n", command_line);
+
+ memcpy(saved_command_line, command_line, CL_SIZE);
+ saved_command_line[CL_SIZE-1] = '\0';
*cmdline_p = command_line;
- *memory_start_p = memory_start;
+ *memory_start_p = (unsigned long) &_end;
*memory_end_p = memory_end;
-#if 0
- /*
- * Check that struct pt_regs is defined properly
- * (Should be optimized away, but gcc 2.6.3 is too bad..)
- */
- if (FR_SIZE != sizeof(struct pt_regs) ||
- FR_SIZE & 7)
- {
- panic("Check_definition_of_struct_pt_regs\n");
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (LOADER_TYPE) {
+ initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
+ initrd_end = initrd_start+INITRD_SIZE;
+ if (initrd_end > memory_end) {
+ printk("initrd extends beyond end of memory "
+ "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ initrd_end,memory_end);
+ initrd_start = 0;
+ }
}
#endif
}