aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/dec/prom
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/dec/prom
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/mips/dec/prom')
-rw-r--r--arch/mips/dec/prom/Makefile11
-rw-r--r--arch/mips/dec/prom/call_o32.S91
-rw-r--r--arch/mips/dec/prom/cmdline.c39
-rw-r--r--arch/mips/dec/prom/console.c55
-rw-r--r--arch/mips/dec/prom/dectypes.h14
-rw-r--r--arch/mips/dec/prom/identify.c177
-rw-r--r--arch/mips/dec/prom/init.c134
-rw-r--r--arch/mips/dec/prom/locore.S30
-rw-r--r--arch/mips/dec/prom/memory.c130
9 files changed, 681 insertions, 0 deletions
diff --git a/arch/mips/dec/prom/Makefile b/arch/mips/dec/prom/Makefile
new file mode 100644
index 000000000000..373822ec2d8c
--- /dev/null
+++ b/arch/mips/dec/prom/Makefile
@@ -0,0 +1,11 @@
1#
2# Makefile for the DECstation prom monitor library routines
3# under Linux.
4#
5
6lib-y += init.o memory.o cmdline.o identify.o console.o
7
8lib-$(CONFIG_MIPS32) += locore.o
9lib-$(CONFIG_MIPS64) += call_o32.o
10
11EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/dec/prom/call_o32.S b/arch/mips/dec/prom/call_o32.S
new file mode 100644
index 000000000000..0dd56db9b3d0
--- /dev/null
+++ b/arch/mips/dec/prom/call_o32.S
@@ -0,0 +1,91 @@
1/*
2 * arch/mips/dec/call_o32.S
3 *
4 * O32 interface for the 64 (or N32) ABI.
5 *
6 * Copyright (C) 2002 Maciej W. Rozycki
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
14#include <asm/asm.h>
15#include <asm/regdef.h>
16
17/* Maximum number of arguments supported. Must be even! */
18#define O32_ARGC 32
19/* Number of static registers we save. */
20#define O32_STATC 11
21/* Frame size for both of the above. */
22#define O32_FRAMESZ (4 * O32_ARGC + SZREG * O32_STATC)
23
24 .text
25
26/*
27 * O32 function call dispatcher, for interfacing 32-bit ROM routines.
28 *
29 * The standard 64 (N32) calling sequence is supported, with a0
30 * holding a function pointer, a1-a7 -- its first seven arguments
31 * and the stack -- remaining ones (up to O32_ARGC, including a1-a7).
32 * Static registers, gp and fp are preserved, v0 holds a result.
33 * This code relies on the called o32 function for sp and ra
34 * restoration and thus both this dispatcher and the current stack
35 * have to be placed in a KSEGx (or KUSEG) address space. Any
36 * pointers passed have to point to addresses within one of these
37 * spaces as well.
38 */
39NESTED(call_o32, O32_FRAMESZ, ra)
40 REG_SUBU sp,O32_FRAMESZ
41
42 REG_S ra,O32_FRAMESZ-1*SZREG(sp)
43 REG_S fp,O32_FRAMESZ-2*SZREG(sp)
44 REG_S gp,O32_FRAMESZ-3*SZREG(sp)
45 REG_S s7,O32_FRAMESZ-4*SZREG(sp)
46 REG_S s6,O32_FRAMESZ-5*SZREG(sp)
47 REG_S s5,O32_FRAMESZ-6*SZREG(sp)
48 REG_S s4,O32_FRAMESZ-7*SZREG(sp)
49 REG_S s3,O32_FRAMESZ-8*SZREG(sp)
50 REG_S s2,O32_FRAMESZ-9*SZREG(sp)
51 REG_S s1,O32_FRAMESZ-10*SZREG(sp)
52 REG_S s0,O32_FRAMESZ-11*SZREG(sp)
53
54 move jp,a0
55
56 sll a0,a1,zero
57 sll a1,a2,zero
58 sll a2,a3,zero
59 sll a3,a4,zero
60 sw a5,0x10(sp)
61 sw a6,0x14(sp)
62 sw a7,0x18(sp)
63
64 PTR_LA t0,O32_FRAMESZ(sp)
65 PTR_LA t1,0x1c(sp)
66 li t2,O32_ARGC-7
671:
68 lw t3,(t0)
69 REG_ADDU t0,SZREG
70 sw t3,(t1)
71 REG_SUBU t2,1
72 REG_ADDU t1,4
73 bnez t2,1b
74
75 jalr jp
76
77 REG_L s0,O32_FRAMESZ-11*SZREG(sp)
78 REG_L s1,O32_FRAMESZ-10*SZREG(sp)
79 REG_L s2,O32_FRAMESZ-9*SZREG(sp)
80 REG_L s3,O32_FRAMESZ-8*SZREG(sp)
81 REG_L s4,O32_FRAMESZ-7*SZREG(sp)
82 REG_L s5,O32_FRAMESZ-6*SZREG(sp)
83 REG_L s6,O32_FRAMESZ-5*SZREG(sp)
84 REG_L s7,O32_FRAMESZ-4*SZREG(sp)
85 REG_L gp,O32_FRAMESZ-3*SZREG(sp)
86 REG_L fp,O32_FRAMESZ-2*SZREG(sp)
87 REG_L ra,O32_FRAMESZ-1*SZREG(sp)
88
89 REG_ADDU sp,O32_FRAMESZ
90 jr ra
91END(call_o32)
diff --git a/arch/mips/dec/prom/cmdline.c b/arch/mips/dec/prom/cmdline.c
new file mode 100644
index 000000000000..c3490bebbc5d
--- /dev/null
+++ b/arch/mips/dec/prom/cmdline.c
@@ -0,0 +1,39 @@
1/*
2 * cmdline.c: read the command line passed to us by the PROM.
3 *
4 * Copyright (C) 1998 Harald Koerfgen
5 * Copyright (C) 2002, 2004 Maciej W. Rozycki
6 */
7#include <linux/init.h>
8#include <linux/kernel.h>
9#include <linux/string.h>
10#include <linux/types.h>
11
12#include <asm/bootinfo.h>
13#include <asm/dec/prom.h>
14
15#undef PROM_DEBUG
16
17void __init prom_init_cmdline(s32 argc, s32 *argv, u32 magic)
18{
19 char *arg;
20 int start_arg, i;
21
22 /*
23 * collect args and prepare cmd_line
24 */
25 if (!prom_is_rex(magic))
26 start_arg = 1;
27 else
28 start_arg = 2;
29 for (i = start_arg; i < argc; i++) {
30 arg = (void *)(long)(argv[i]);
31 strcat(arcs_cmdline, arg);
32 if (i < (argc - 1))
33 strcat(arcs_cmdline, " ");
34 }
35
36#ifdef PROM_DEBUG
37 printk("arcs_cmdline: %s\n", &(arcs_cmdline[0]));
38#endif
39}
diff --git a/arch/mips/dec/prom/console.c b/arch/mips/dec/prom/console.c
new file mode 100644
index 000000000000..cade16ec7e5a
--- /dev/null
+++ b/arch/mips/dec/prom/console.c
@@ -0,0 +1,55 @@
1/*
2 * arch/mips/dec/prom/console.c
3 *
4 * DECstation PROM-based early console support.
5 *
6 * Copyright (C) 2004 Maciej W. Rozycki
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13#include <linux/console.h>
14#include <linux/init.h>
15#include <linux/kernel.h>
16
17#include <asm/dec/prom.h>
18
19static void __init prom_console_write(struct console *con, const char *s,
20 unsigned int c)
21{
22 static char sfmt[] __initdata = "%%%us";
23 char fmt[13];
24
25 snprintf(fmt, sizeof(fmt), sfmt, c);
26 prom_printf(fmt, s);
27}
28
29static struct console promcons __initdata = {
30 .name = "prom",
31 .write = prom_console_write,
32 .flags = CON_PRINTBUFFER,
33 .index = -1,
34};
35
36static int promcons_output __initdata = 0;
37
38void __init register_prom_console(void)
39{
40 if (!promcons_output) {
41 promcons_output = 1;
42 register_console(&promcons);
43 }
44}
45
46void __init unregister_prom_console(void)
47{
48 if (promcons_output) {
49 unregister_console(&promcons);
50 promcons_output = 0;
51 }
52}
53
54void disable_early_printk(void)
55 __attribute__((alias("unregister_prom_console")));
diff --git a/arch/mips/dec/prom/dectypes.h b/arch/mips/dec/prom/dectypes.h
new file mode 100644
index 000000000000..707b6f1f5a9d
--- /dev/null
+++ b/arch/mips/dec/prom/dectypes.h
@@ -0,0 +1,14 @@
1#ifndef DECTYPES
2#define DECTYPES
3
4#define DS2100_3100 1 /* DS2100/3100 Pmax */
5#define DS5000_200 2 /* DS5000/200 3max */
6#define DS5000_1XX 3 /* DS5000/1xx kmin */
7#define DS5000_2X0 4 /* DS5000/2x0 3max+ */
8#define DS5800 5 /* DS5800 Isis */
9#define DS5400 6 /* DS5400 MIPSfair */
10#define DS5000_XX 7 /* DS5000/xx maxine */
11#define DS5500 11 /* DS5500 MIPSfair-2 */
12#define DS5100 12 /* DS5100 MIPSmate */
13
14#endif
diff --git a/arch/mips/dec/prom/identify.c b/arch/mips/dec/prom/identify.c
new file mode 100644
index 000000000000..9380588cb15c
--- /dev/null
+++ b/arch/mips/dec/prom/identify.c
@@ -0,0 +1,177 @@
1/*
2 * identify.c: machine identification code.
3 *
4 * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine
5 * Copyright (C) 2002, 2003, 2004 Maciej W. Rozycki
6 */
7#include <linux/init.h>
8#include <linux/kernel.h>
9#include <linux/mc146818rtc.h>
10#include <linux/module.h>
11#include <linux/string.h>
12#include <linux/types.h>
13
14#include <asm/bootinfo.h>
15#include <asm/dec/ioasic.h>
16#include <asm/dec/ioasic_addrs.h>
17#include <asm/dec/kn01.h>
18#include <asm/dec/kn02.h>
19#include <asm/dec/kn02ba.h>
20#include <asm/dec/kn02ca.h>
21#include <asm/dec/kn03.h>
22#include <asm/dec/kn230.h>
23#include <asm/dec/prom.h>
24
25#include "dectypes.h"
26
27extern unsigned long mips_machgroup;
28extern unsigned long mips_machtype;
29
30static const char *dec_system_strings[] = {
31 [MACH_DSUNKNOWN] "unknown DECstation",
32 [MACH_DS23100] "DECstation 2100/3100",
33 [MACH_DS5100] "DECsystem 5100",
34 [MACH_DS5000_200] "DECstation 5000/200",
35 [MACH_DS5000_1XX] "DECstation 5000/1xx",
36 [MACH_DS5000_XX] "Personal DECstation 5000/xx",
37 [MACH_DS5000_2X0] "DECstation 5000/2x0",
38 [MACH_DS5400] "DECsystem 5400",
39 [MACH_DS5500] "DECsystem 5500",
40 [MACH_DS5800] "DECsystem 5800",
41 [MACH_DS5900] "DECsystem 5900",
42};
43
44const char *get_system_type(void)
45{
46#define STR_BUF_LEN 64
47 static char system[STR_BUF_LEN];
48 static int called = 0;
49
50 if (called == 0) {
51 called = 1;
52 snprintf(system, STR_BUF_LEN, "Digital %s",
53 dec_system_strings[mips_machtype]);
54 }
55
56 return system;
57}
58
59
60/*
61 * Setup essential system-specific memory addresses. We need them
62 * early. Semantically the functions belong to prom/init.c, but they
63 * are compact enough we want them inlined. --macro
64 */
65volatile u8 *dec_rtc_base;
66
67EXPORT_SYMBOL(dec_rtc_base);
68
69static inline void prom_init_kn01(void)
70{
71 dec_rtc_base = (void *)KN01_RTC_BASE;
72 dec_kn_slot_size = KN01_SLOT_SIZE;
73}
74
75static inline void prom_init_kn230(void)
76{
77 dec_rtc_base = (void *)KN01_RTC_BASE;
78 dec_kn_slot_size = KN01_SLOT_SIZE;
79}
80
81static inline void prom_init_kn02(void)
82{
83 dec_rtc_base = (void *)KN02_RTC_BASE;
84 dec_kn_slot_size = KN02_SLOT_SIZE;
85}
86
87static inline void prom_init_kn02xa(void)
88{
89 ioasic_base = (void *)KN02XA_IOASIC_BASE;
90 dec_rtc_base = (void *)KN02XA_RTC_BASE;
91 dec_kn_slot_size = IOASIC_SLOT_SIZE;
92}
93
94static inline void prom_init_kn03(void)
95{
96 ioasic_base = (void *)KN03_IOASIC_BASE;
97 dec_rtc_base = (void *)KN03_RTC_BASE;
98 dec_kn_slot_size = IOASIC_SLOT_SIZE;
99}
100
101
102void __init prom_identify_arch(u32 magic)
103{
104 unsigned char dec_cpunum, dec_firmrev, dec_etc, dec_systype;
105 u32 dec_sysid;
106
107 if (!prom_is_rex(magic)) {
108 dec_sysid = simple_strtoul(prom_getenv("systype"),
109 (char **)0, 0);
110 } else {
111 dec_sysid = rex_getsysid();
112 if (dec_sysid == 0) {
113 printk("Zero sysid returned from PROM! "
114 "Assuming a PMAX-like machine.\n");
115 dec_sysid = 1;
116 }
117 }
118
119 dec_cpunum = (dec_sysid & 0xff000000) >> 24;
120 dec_systype = (dec_sysid & 0xff0000) >> 16;
121 dec_firmrev = (dec_sysid & 0xff00) >> 8;
122 dec_etc = dec_sysid & 0xff;
123
124 /* We're obviously one of the DEC machines */
125 mips_machgroup = MACH_GROUP_DEC;
126
127 /*
128 * FIXME: This may not be an exhaustive list of DECStations/Servers!
129 * Put all model-specific initialisation calls here.
130 */
131 switch (dec_systype) {
132 case DS2100_3100:
133 mips_machtype = MACH_DS23100;
134 prom_init_kn01();
135 break;
136 case DS5100: /* DS5100 MIPSMATE */
137 mips_machtype = MACH_DS5100;
138 prom_init_kn230();
139 break;
140 case DS5000_200: /* DS5000 3max */
141 mips_machtype = MACH_DS5000_200;
142 prom_init_kn02();
143 break;
144 case DS5000_1XX: /* DS5000/100 3min */
145 mips_machtype = MACH_DS5000_1XX;
146 prom_init_kn02xa();
147 break;
148 case DS5000_2X0: /* DS5000/240 3max+ or DS5900 bigmax */
149 mips_machtype = MACH_DS5000_2X0;
150 prom_init_kn03();
151 if (!(ioasic_read(IO_REG_SIR) & KN03_IO_INR_3MAXP))
152 mips_machtype = MACH_DS5900;
153 break;
154 case DS5000_XX: /* Personal DS5000/xx maxine */
155 mips_machtype = MACH_DS5000_XX;
156 prom_init_kn02xa();
157 break;
158 case DS5800: /* DS5800 Isis */
159 mips_machtype = MACH_DS5800;
160 break;
161 case DS5400: /* DS5400 MIPSfair */
162 mips_machtype = MACH_DS5400;
163 break;
164 case DS5500: /* DS5500 MIPSfair-2 */
165 mips_machtype = MACH_DS5500;
166 break;
167 default:
168 mips_machtype = MACH_DSUNKNOWN;
169 break;
170 }
171
172 if (mips_machtype == MACH_DSUNKNOWN)
173 printk("This is an %s, id is %x\n",
174 dec_system_strings[mips_machtype], dec_systype);
175 else
176 printk("This is a %s\n", dec_system_strings[mips_machtype]);
177}
diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c
new file mode 100644
index 000000000000..60f74256e689
--- /dev/null
+++ b/arch/mips/dec/prom/init.c
@@ -0,0 +1,134 @@
1/*
2 * init.c: PROM library initialisation code.
3 *
4 * Copyright (C) 1998 Harald Koerfgen
5 * Copyright (C) 2002, 2004 Maciej W. Rozycki
6 */
7#include <linux/config.h>
8#include <linux/init.h>
9#include <linux/smp.h>
10#include <linux/string.h>
11#include <linux/types.h>
12
13#include <asm/bootinfo.h>
14#include <asm/cpu.h>
15#include <asm/processor.h>
16
17#include <asm/dec/prom.h>
18
19
20int (*__rex_bootinit)(void);
21int (*__rex_bootread)(void);
22int (*__rex_getbitmap)(memmap *);
23unsigned long *(*__rex_slot_address)(int);
24void *(*__rex_gettcinfo)(void);
25int (*__rex_getsysid)(void);
26void (*__rex_clear_cache)(void);
27
28int (*__prom_getchar)(void);
29char *(*__prom_getenv)(char *);
30int (*__prom_printf)(char *, ...);
31
32int (*__pmax_open)(char*, int);
33int (*__pmax_lseek)(int, long, int);
34int (*__pmax_read)(int, void *, int);
35int (*__pmax_close)(int);
36
37
38/*
39 * Detect which PROM the DECSTATION has, and set the callback vectors
40 * appropriately.
41 */
42void __init which_prom(s32 magic, s32 *prom_vec)
43{
44 /*
45 * No sign of the REX PROM's magic number means we assume a non-REX
46 * machine (i.e. we're on a DS2100/3100, DS5100 or DS5000/2xx)
47 */
48 if (prom_is_rex(magic)) {
49 /*
50 * Set up prom abstraction structure with REX entry points.
51 */
52 __rex_bootinit =
53 (void *)(long)*(prom_vec + REX_PROM_BOOTINIT);
54 __rex_bootread =
55 (void *)(long)*(prom_vec + REX_PROM_BOOTREAD);
56 __rex_getbitmap =
57 (void *)(long)*(prom_vec + REX_PROM_GETBITMAP);
58 __prom_getchar =
59 (void *)(long)*(prom_vec + REX_PROM_GETCHAR);
60 __prom_getenv =
61 (void *)(long)*(prom_vec + REX_PROM_GETENV);
62 __rex_getsysid =
63 (void *)(long)*(prom_vec + REX_PROM_GETSYSID);
64 __rex_gettcinfo =
65 (void *)(long)*(prom_vec + REX_PROM_GETTCINFO);
66 __prom_printf =
67 (void *)(long)*(prom_vec + REX_PROM_PRINTF);
68 __rex_slot_address =
69 (void *)(long)*(prom_vec + REX_PROM_SLOTADDR);
70 __rex_clear_cache =
71 (void *)(long)*(prom_vec + REX_PROM_CLEARCACHE);
72 } else {
73 /*
74 * Set up prom abstraction structure with non-REX entry points.
75 */
76 __prom_getchar = (void *)PMAX_PROM_GETCHAR;
77 __prom_getenv = (void *)PMAX_PROM_GETENV;
78 __prom_printf = (void *)PMAX_PROM_PRINTF;
79 __pmax_open = (void *)PMAX_PROM_OPEN;
80 __pmax_lseek = (void *)PMAX_PROM_LSEEK;
81 __pmax_read = (void *)PMAX_PROM_READ;
82 __pmax_close = (void *)PMAX_PROM_CLOSE;
83 }
84}
85
86void __init prom_init(void)
87{
88 extern void dec_machine_halt(void);
89 static char cpu_msg[] __initdata =
90 "Sorry, this kernel is compiled for a wrong CPU type!\n";
91 static char r3k_msg[] __initdata =
92 "Please recompile with \"CONFIG_CPU_R3000 = y\".\n";
93 static char r4k_msg[] __initdata =
94 "Please recompile with \"CONFIG_CPU_R4x00 = y\".\n";
95 s32 argc = fw_arg0;
96 s32 argv = fw_arg1;
97 u32 magic = fw_arg2;
98 s32 prom_vec = fw_arg3;
99
100 /*
101 * Determine which PROM we have
102 * (and therefore which machine we're on!)
103 */
104 which_prom(magic, prom_vec);
105
106 if (prom_is_rex(magic))
107 rex_clear_cache();
108
109 /* Register the early console. */
110 register_prom_console();
111
112 /* Were we compiled with the right CPU option? */
113#if defined(CONFIG_CPU_R3000)
114 if ((current_cpu_data.cputype == CPU_R4000SC) ||
115 (current_cpu_data.cputype == CPU_R4400SC)) {
116 printk(cpu_msg);
117 printk(r4k_msg);
118 dec_machine_halt();
119 }
120#endif
121
122#if defined(CONFIG_CPU_R4X00)
123 if ((current_cpu_data.cputype == CPU_R3000) ||
124 (current_cpu_data.cputype == CPU_R3000A)) {
125 printk(cpu_msg);
126 printk(r3k_msg);
127 dec_machine_halt();
128 }
129#endif
130
131 prom_meminit(magic);
132 prom_identify_arch(magic);
133 prom_init_cmdline(argc, argv, magic);
134}
diff --git a/arch/mips/dec/prom/locore.S b/arch/mips/dec/prom/locore.S
new file mode 100644
index 000000000000..d9acdcefee81
--- /dev/null
+++ b/arch/mips/dec/prom/locore.S
@@ -0,0 +1,30 @@
1/*
2 * locore.S
3 */
4#include <asm/asm.h>
5#include <asm/regdef.h>
6#include <asm/mipsregs.h>
7
8 .text
9
10/*
11 * Simple general exception handling routine. This one is used for the
12 * Memory sizing routine for pmax machines. HK
13 */
14
15NESTED(genexcept_early, 0, sp)
16 .set noat
17 .set noreorder
18
19 mfc0 k0, CP0_STATUS
20 la k1, mem_err
21
22 sw k0, 0(k1)
23
24 mfc0 k0, CP0_EPC
25 nop
26 addiu k0, 4 # skip the causing instruction
27 jr k0
28 rfe
29END(genexcept_early)
30
diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c
new file mode 100644
index 000000000000..e4f6f26425ea
--- /dev/null
+++ b/arch/mips/dec/prom/memory.c
@@ -0,0 +1,130 @@
1/*
2 * memory.c: memory initialisation code.
3 *
4 * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine
5 * Copyright (C) 2000, 2002 Maciej W. Rozycki
6 */
7#include <linux/config.h>
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/mm.h>
11#include <linux/bootmem.h>
12#include <linux/types.h>
13
14#include <asm/addrspace.h>
15#include <asm/bootinfo.h>
16#include <asm/dec/machtype.h>
17#include <asm/dec/prom.h>
18#include <asm/page.h>
19#include <asm/sections.h>
20
21
22volatile unsigned long mem_err = 0; /* So we know an error occurred */
23
24/*
25 * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen
26 * off the end of real memory. Only suitable for the 2100/3100's (PMAX).
27 */
28
29#define CHUNK_SIZE 0x400000
30
31static inline void pmax_setup_memory_region(void)
32{
33 volatile unsigned char *memory_page, dummy;
34 char old_handler[0x80];
35 extern char genexcept_early;
36
37 /* Install exception handler */
38 memcpy(&old_handler, (void *)(KSEG0 + 0x80), 0x80);
39 memcpy((void *)(KSEG0 + 0x80), &genexcept_early, 0x80);
40
41 /* read unmapped and uncached (KSEG1)
42 * DECstations have at least 4MB RAM
43 * Assume less than 480MB of RAM, as this is max for 5000/2xx
44 * FIXME this should be replaced by the first free page!
45 */
46 for (memory_page = (unsigned char *) KSEG1 + CHUNK_SIZE;
47 (mem_err== 0) && (memory_page < ((unsigned char *) KSEG1+0x1E000000));
48 memory_page += CHUNK_SIZE) {
49 dummy = *memory_page;
50 }
51 memcpy((void *)(KSEG0 + 0x80), &old_handler, 0x80);
52
53 add_memory_region(0, (unsigned long)memory_page - KSEG1 - CHUNK_SIZE,
54 BOOT_MEM_RAM);
55}
56
57/*
58 * Use the REX prom calls to get hold of the memory bitmap, and thence
59 * determine memory size.
60 */
61static inline void rex_setup_memory_region(void)
62{
63 int i, bitmap_size;
64 unsigned long mem_start = 0, mem_size = 0;
65 memmap *bm;
66
67 /* some free 64k */
68 bm = (memmap *)KSEG0ADDR(0x28000);
69
70 bitmap_size = rex_getbitmap(bm);
71
72 for (i = 0; i < bitmap_size; i++) {
73 /* FIXME: very simplistically only add full sets of pages */
74 if (bm->bitmap[i] == 0xff)
75 mem_size += (8 * bm->pagesize);
76 else if (!mem_size)
77 mem_start += (8 * bm->pagesize);
78 else {
79 add_memory_region(mem_start, mem_size, BOOT_MEM_RAM);
80 mem_start += mem_size + (8 * bm->pagesize);
81 mem_size = 0;
82 }
83 }
84 if (mem_size)
85 add_memory_region(mem_start, mem_size, BOOT_MEM_RAM);
86}
87
88void __init prom_meminit(u32 magic)
89{
90 if (!prom_is_rex(magic))
91 pmax_setup_memory_region();
92 else
93 rex_setup_memory_region();
94}
95
96unsigned long __init prom_free_prom_memory(void)
97{
98 unsigned long addr, end;
99
100 /*
101 * Free everything below the kernel itself but leave
102 * the first page reserved for the exception handlers.
103 */
104
105#if defined(CONFIG_DECLANCE) || defined(CONFIG_DECLANCE_MODULE)
106 /*
107 * Leave 128 KB reserved for Lance memory for
108 * IOASIC DECstations.
109 *
110 * XXX: save this address for use in dec_lance.c?
111 */
112 if (IOASIC)
113 end = __pa(&_text) - 0x00020000;
114 else
115#endif
116 end = __pa(&_text);
117
118 addr = PAGE_SIZE;
119 while (addr < end) {
120 ClearPageReserved(virt_to_page(__va(addr)));
121 set_page_count(virt_to_page(__va(addr)), 1);
122 free_page((unsigned long)__va(addr));
123 addr += PAGE_SIZE;
124 }
125
126 printk("Freeing unused PROM memory: %ldk freed\n",
127 (end - PAGE_SIZE) >> 10);
128
129 return end - PAGE_SIZE;
130}