summaryrefslogtreecommitdiffstats
path: root/arch/mips/dec/prom
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/dec/prom')
-rw-r--r--arch/mips/dec/prom/Makefile29
-rw-r--r--arch/mips/dec/prom/cmdline.c47
-rw-r--r--arch/mips/dec/prom/dectypes.h14
-rw-r--r--arch/mips/dec/prom/identify.c99
-rw-r--r--arch/mips/dec/prom/init.c93
-rw-r--r--arch/mips/dec/prom/locore.S30
-rw-r--r--arch/mips/dec/prom/memory.c95
-rw-r--r--arch/mips/dec/prom/prom.h51
8 files changed, 458 insertions, 0 deletions
diff --git a/arch/mips/dec/prom/Makefile b/arch/mips/dec/prom/Makefile
new file mode 100644
index 000000000..33f906ece
--- /dev/null
+++ b/arch/mips/dec/prom/Makefile
@@ -0,0 +1,29 @@
+# $Id: $
+# Makefile for the DECstation prom monitor library 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
+
+OBJS = init.o memory.o cmdline.o identify.o locore.o
+
+all: rexlib.a
+
+rexlib.a: $(OBJS)
+ $(AR) rcs rexlib.a $(OBJS)
+ sync
+
+locore.o: locore.S
+
+dep:
+ $(CPP) -M *.c > .depend
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/dec/prom/cmdline.c b/arch/mips/dec/prom/cmdline.c
new file mode 100644
index 000000000..31d6ec318
--- /dev/null
+++ b/arch/mips/dec/prom/cmdline.c
@@ -0,0 +1,47 @@
+/*
+ * cmdline.c: read the command line passed to us by the PROM.
+ *
+ * Copyright (C) 1998 Harald Koerfgen
+ *
+ * $Id: $
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+#include "prom.h"
+
+#undef PROM_DEBUG
+
+#ifdef PROM_DEBUG
+extern int (*prom_printf)(char *, ...);
+#endif
+
+char arcs_cmdline[CL_SIZE];
+
+__initfunc(void prom_init_cmdline(int argc, char **argv, unsigned long magic))
+{
+ int start_arg, i;
+
+ /*
+ * collect args and prepare cmd_line
+ */
+ if (magic != REX_PROM_MAGIC)
+ start_arg = 1;
+ else
+ start_arg = 2;
+ for (i = start_arg; i < argc; i++) {
+ strcat(arcs_cmdline, argv[i]);
+ if (i < (argc - 1))
+ strcat(arcs_cmdline, " ");
+ }
+
+#ifdef PROM_DEBUG
+ prom_printf("arcs_cmdline: %s\n", &(arcs_cmdline[0]));
+#endif
+
+}
+
diff --git a/arch/mips/dec/prom/dectypes.h b/arch/mips/dec/prom/dectypes.h
new file mode 100644
index 000000000..707b6f1f5
--- /dev/null
+++ b/arch/mips/dec/prom/dectypes.h
@@ -0,0 +1,14 @@
+#ifndef DECTYPES
+#define DECTYPES
+
+#define DS2100_3100 1 /* DS2100/3100 Pmax */
+#define DS5000_200 2 /* DS5000/200 3max */
+#define DS5000_1XX 3 /* DS5000/1xx kmin */
+#define DS5000_2X0 4 /* DS5000/2x0 3max+ */
+#define DS5800 5 /* DS5800 Isis */
+#define DS5400 6 /* DS5400 MIPSfair */
+#define DS5000_XX 7 /* DS5000/xx maxine */
+#define DS5500 11 /* DS5500 MIPSfair-2 */
+#define DS5100 12 /* DS5100 MIPSmate */
+
+#endif
diff --git a/arch/mips/dec/prom/identify.c b/arch/mips/dec/prom/identify.c
new file mode 100644
index 000000000..65d7b5abf
--- /dev/null
+++ b/arch/mips/dec/prom/identify.c
@@ -0,0 +1,99 @@
+/*
+ * identify.c: machine identification code.
+ *
+ * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine
+ *
+ * $Id: $
+ */
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+#include "dectypes.h"
+#include "prom.h"
+
+extern char *(*prom_getenv)(char *);
+extern int (*prom_printf)(char *, ...);
+extern int (*rex_getsysid)(void);
+
+extern unsigned long mips_machgroup;
+extern unsigned long mips_machtype;
+
+__initfunc(void prom_identify_arch (unsigned int magic))
+{
+ unsigned char dec_cpunum, dec_firmrev, dec_etc;
+ int dec_systype;
+ unsigned long dec_sysid;
+
+ if (magic != REX_PROM_MAGIC) {
+ dec_sysid = simple_strtoul(prom_getenv("systype"), (char **)0, 0);
+ } else {
+ dec_sysid = rex_getsysid();
+ if (dec_sysid == 0) {
+ prom_printf("Zero sysid returned from PROMs! Assuming PMAX-like machine.\n");
+ dec_sysid = 1;
+ }
+ }
+
+ dec_cpunum = (dec_sysid & 0xff000000) >> 24;
+ dec_systype = (dec_sysid & 0xff0000) >> 16;
+ dec_firmrev = (dec_sysid & 0xff00) >> 8;
+ dec_etc = dec_sysid & 0xff;
+
+ /* We're obviously one of the DEC machines */
+ mips_machgroup = MACH_GROUP_DEC;
+
+ /*
+ * FIXME: This may not be an exhaustive list of DECStations/Servers!
+ * Put all model-specific initialisation calls here.
+ */
+ prom_printf("This DECstation is a ");
+
+ switch (dec_systype) {
+ case DS2100_3100:
+ prom_printf("DS2100/3100\n");
+ mips_machtype = MACH_DS23100;
+ break;
+ case DS5100: /* DS5100 MIPSMATE */
+ prom_printf("DS5100\n");
+ mips_machtype = MACH_DS5100;
+ break;
+ case DS5000_200: /* DS5000 3max */
+ prom_printf("DS5000/200\n");
+ mips_machtype = MACH_DS5000_200;
+ break;
+ case DS5000_1XX: /* DS5000/100 3min */
+ prom_printf("DS5000/1xx\n");
+ mips_machtype = MACH_DS5000_1XX;
+ break;
+ case DS5000_2X0: /* DS5000/240 3max+ */
+ prom_printf("DS5000/2x0\n");
+ mips_machtype = MACH_DS5000_2X0;
+ break;
+ case DS5000_XX: /* Personal DS5000/2x */
+ prom_printf("Personal DS5000/xx\n");
+ mips_machtype = MACH_DS5000_XX;
+ break;
+ case DS5800: /* DS5800 Isis */
+ prom_printf("DS5800\n");
+ mips_machtype = MACH_DS5800;
+ break;
+ case DS5400: /* DS5400 MIPSfair */
+ prom_printf("DS5400\n");
+ mips_machtype = MACH_DS5400;
+ break;
+ case DS5500: /* DS5500 MIPSfair-2 */
+ prom_printf("DS5500\n");
+ mips_machtype = MACH_DS5500;
+ break;
+ default:
+ prom_printf("unknown, id is %x", dec_systype);
+ mips_machtype = MACH_DSUNKNOWN;
+ break;
+ }
+}
+
+
diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c
new file mode 100644
index 000000000..717dda622
--- /dev/null
+++ b/arch/mips/dec/prom/init.c
@@ -0,0 +1,93 @@
+/*
+ * init.c: PROM library initialisation code.
+ *
+ * Copyright (C) 1998 Harald Koerfgen
+ *
+ * $Id: $
+ */
+#include <linux/init.h>
+#include <linux/config.h>
+#include "prom.h"
+
+/*
+ * PROM Interface (whichprom.c)
+ */
+typedef struct {
+ int pagesize;
+ unsigned char bitmap[0];
+} memmap;
+
+int (*rex_bootinit)(void);
+int (*rex_bootread)(void);
+int (*rex_getbitmap)(memmap *);
+unsigned long *(*rex_slot_address)(int);
+void *(*rex_gettcinfo)(void);
+int (*rex_getsysid)(void);
+void (*rex_clear_cache)(void);
+
+int (*prom_getchar)(void);
+char *(*prom_getenv)(char *);
+int (*prom_printf)(char *, ...);
+
+int (*pmax_open)(char*, int);
+int (*pmax_lseek)(int, long, int);
+int (*pmax_read)(int, void *, int);
+int (*pmax_close)(int);
+
+extern void prom_meminit(unsigned int);
+extern void prom_identify_arch(unsigned int);
+extern void prom_init_cmdline(int, char **, unsigned long);
+
+/*
+ * Detect which PROM's the DECSTATION has, and set the callback vectors
+ * appropriately.
+ */
+__initfunc(void which_prom(unsigned long magic, int *prom_vec))
+{
+ /*
+ * No sign of the REX PROM's magic number means we assume a non-REX
+ * machine (i.e. we're on a DS2100/3100, DS5100 or DS5000/2xx)
+ */
+ if (magic == REX_PROM_MAGIC)
+ {
+ /*
+ * Set up prom abstraction structure with REX entry points.
+ */
+ rex_bootinit = (int (*)(void)) *(prom_vec + REX_PROM_BOOTINIT);
+ rex_bootread = (int (*)(void)) *(prom_vec + REX_PROM_BOOTREAD);
+ rex_getbitmap = (int (*)(memmap *)) *(prom_vec + REX_PROM_GETBITMAP);
+ prom_getchar = (int (*)(void)) *(prom_vec + REX_PROM_GETCHAR);
+ prom_getenv = (char *(*)(char *)) *(prom_vec + REX_PROM_GETENV);
+ rex_getsysid = (int (*)(void)) *(prom_vec + REX_PROM_GETSYSID);
+ rex_gettcinfo = (void *(*)(void)) *(prom_vec + REX_PROM_GETTCINFO);
+ prom_printf = (int (*)(char *, ...)) *(prom_vec + REX_PROM_PRINTF);
+ rex_slot_address = (unsigned long *(*)(int)) *(prom_vec + REX_PROM_SLOTADDR);
+ rex_clear_cache = (void (*)(void)) * (prom_vec + REX_PROM_CLEARCACHE);
+ }
+ else
+ {
+ /*
+ * Set up prom abstraction structure with non-REX entry points.
+ */
+ prom_getchar = (int (*)(void)) PMAX_PROM_GETCHAR;
+ prom_getenv = (char *(*)(char *)) PMAX_PROM_GETENV;
+ prom_printf = (int (*)(char *, ...)) PMAX_PROM_PRINTF;
+ pmax_open = (int (*)(char *, int)) PMAX_PROM_OPEN;
+ pmax_lseek = (int (*)(int, long, int)) PMAX_PROM_LSEEK;
+ pmax_read = (int (*)(int, void *, int)) PMAX_PROM_READ;
+ pmax_close = (int (*)(int)) PMAX_PROM_CLOSE;
+ }
+}
+
+__initfunc(int prom_init(int argc, char **argv,
+ unsigned long magic, int *prom_vec))
+{
+ /* Determine which PROM's we have (and therefore which machine we're on!) */
+ which_prom(magic, prom_vec);
+
+ prom_meminit(magic);
+ prom_identify_arch(magic);
+ prom_init_cmdline(argc, argv, magic);
+
+ return 0;
+}
diff --git a/arch/mips/dec/prom/locore.S b/arch/mips/dec/prom/locore.S
new file mode 100644
index 000000000..2255fd3e1
--- /dev/null
+++ b/arch/mips/dec/prom/locore.S
@@ -0,0 +1,30 @@
+/*
+ * locore.S
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+
+ .text
+
+/*
+ * Simple general exception handling routine. This one is used for the
+ * Memory sizing routine for pmax machines. HK
+ */
+
+NESTED(genexcept_early, 0, sp)
+ .set noat
+ .set noreorder
+
+ mfc0 k0, CP0_STATUS
+ la k1, mem_err
+
+ sw k0,0(k1)
+
+ mfc0 k0, CP0_EPC
+ nop
+ addiu k0,4 # skip the causing instruction
+ jr k0
+ rfe
+END(genexcept_early)
+
diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c
new file mode 100644
index 000000000..5fa828384
--- /dev/null
+++ b/arch/mips/dec/prom/memory.c
@@ -0,0 +1,95 @@
+/*
+ * memory.c: memory initialisation code.
+ *
+ * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine
+ *
+ * $Id: $
+ */
+#include <asm/addrspace.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include "prom.h"
+
+typedef struct {
+ int pagesize;
+ unsigned char bitmap[0];
+} memmap;
+
+extern int (*rex_getbitmap)(memmap *);
+
+#undef PROM_DEBUG
+
+#ifdef PROM_DEBUG
+extern int (*prom_printf)(char *, ...);
+#endif
+
+extern unsigned long mips_memory_upper;
+
+volatile unsigned long mem_err = 0; /* So we know an error occured */
+
+/*
+ * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen
+ * off the end of real memory. Only suitable for the 2100/3100's (PMAX).
+ */
+
+#define CHUNK_SIZE 0x400000
+
+__initfunc(unsigned long pmax_get_memory_size(void))
+{
+ volatile unsigned char *memory_page, dummy;
+ char old_handler[0x80];
+ extern char genexcept_early;
+
+ /* Install exception handler */
+ memcpy(&old_handler, (void *)(KSEG0 + 0x80), 0x80);
+ memcpy((void *)(KSEG0 + 0x80), &genexcept_early, 0x80);
+
+ /* read unmapped and uncached (KSEG1)
+ * DECstations have at least 4MB RAM
+ * Assume less than 480MB of RAM, as this is max for 5000/2xx
+ * FIXME this should be replaced by the first free page!
+ */
+ for (memory_page = (unsigned char *) KSEG1 + CHUNK_SIZE;
+ (mem_err== 0) && (memory_page < ((unsigned char *) KSEG1+0x1E000000));
+ memory_page += CHUNK_SIZE) {
+ dummy = *memory_page;
+ }
+ memcpy((void *)(KSEG0 + 0x80), &old_handler, 0x80);
+ return (unsigned long)memory_page - KSEG1 - CHUNK_SIZE;
+}
+
+/*
+ * Use the REX prom calls to get hold of the memory bitmap, and thence
+ * determine memory size.
+ */
+__initfunc(unsigned long rex_get_memory_size(void))
+{
+ int i, bitmap_size;
+ unsigned long mem_size = 0;
+ memmap *bm;
+
+ /* some free 64k */
+ bm = (memmap *) 0x80028000;
+
+ bitmap_size = rex_getbitmap(bm);
+
+ for (i = 0; i < bitmap_size; i++) {
+ /* FIXME: very simplistically only add full sets of pages */
+ if (bm->bitmap[i] == 0xff)
+ mem_size += (8 * bm->pagesize);
+ }
+ return (mem_size);
+}
+
+__initfunc(void prom_meminit(unsigned int magic))
+{
+ if (magic != REX_PROM_MAGIC)
+ mips_memory_upper = KSEG0 + pmax_get_memory_size();
+ else
+ mips_memory_upper = KSEG0 + rex_get_memory_size();
+
+#ifdef PROM_DEBUG
+ prom_printf("mips_memory_upper: 0x%08x\n", mips_memory_upper);
+#endif
+}
diff --git a/arch/mips/dec/prom/prom.h b/arch/mips/dec/prom/prom.h
new file mode 100644
index 000000000..c63372545
--- /dev/null
+++ b/arch/mips/dec/prom/prom.h
@@ -0,0 +1,51 @@
+/*
+ * Miscellaneous definitions used to call the routines contained in the boot
+ * PROMs on various models of DECSTATION's.
+ * the rights to redistribute these changes.
+ */
+
+#ifndef __ASM_DEC_PROM_H
+#define __ASM_DEC_PROM_H
+
+/*
+ * PMAX/3MAX PROM entry points for DS2100/3100's and DS5000/2xx's. Many of
+ * these will work for MIPSen as well!
+ */
+#define VEC_RESET 0xBFC00000 /* Prom base address */
+#define PMAX_PROM_ENTRY(x) (VEC_RESET+((x)*8)) /* Prom jump table */
+
+#define PMAX_PROM_HALT PMAX_PROM_ENTRY(2) /* valid on MIPSen */
+#define PMAX_PROM_AUTOBOOT PMAX_PROM_ENTRY(5) /* valid on MIPSen */
+#define PMAX_PROM_OPEN PMAX_PROM_ENTRY(6)
+#define PMAX_PROM_READ PMAX_PROM_ENTRY(7)
+#define PMAX_PROM_CLOSE PMAX_PROM_ENTRY(10)
+#define PMAX_PROM_LSEEK PMAX_PROM_ENTRY(11)
+#define PMAX_PROM_GETCHAR PMAX_PROM_ENTRY(12)
+#define PMAX_PROM_PUTCHAR PMAX_PROM_ENTRY(13) /* 12 on MIPSen */
+#define PMAX_PROM_GETS PMAX_PROM_ENTRY(15)
+#define PMAX_PROM_PRINTF PMAX_PROM_ENTRY(17)
+#define PMAX_PROM_GETENV PMAX_PROM_ENTRY(33) /* valid on MIPSen */
+
+/*
+ * Magic number indicating REX PROM available on DECSTATION. Found in
+ * register a2 on transfer of control to program from PROM.
+ */
+#define REX_PROM_MAGIC 0x30464354
+
+/*
+ * 3MIN/MAXINE PROM entry points for DS5000/1xx's, DS5000/xx's, and
+ * DS5000/2x0.
+ */
+#define REX_PROM_GETBITMAP 0x84/4 /* get mem bitmap */
+#define REX_PROM_GETCHAR 0x24/4 /* getch() */
+#define REX_PROM_GETENV 0x64/4 /* get env. variable */
+#define REX_PROM_GETSYSID 0x80/4 /* get system id */
+#define REX_PROM_GETTCINFO 0xa4/4
+#define REX_PROM_PRINTF 0x30/4 /* printf() */
+#define REX_PROM_SLOTADDR 0x6c/4 /* slotaddr */
+#define REX_PROM_BOOTINIT 0x54/4 /* open() */
+#define REX_PROM_BOOTREAD 0x58/4 /* read() */
+#define REX_PROM_CLEARCACHE 0x7c/4
+
+#endif /* __ASM_DEC_PROM_H */
+