]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * arch/v850/kernel/sim.c -- Machine-specific stuff for GDB v850e simulator | |
3 | * | |
4 | * Copyright (C) 2001,02 NEC Corporation | |
5 | * Copyright (C) 2001,02 Miles Bader <miles@gnu.org> | |
6 | * | |
7 | * This file is subject to the terms and conditions of the GNU General | |
8 | * Public License. See the file COPYING in the main directory of this | |
9 | * archive for more details. | |
10 | * | |
11 | * Written by Miles Bader <miles@gnu.org> | |
12 | */ | |
13 | ||
14 | #include <linux/config.h> | |
15 | #include <linux/kernel.h> | |
16 | #include <linux/module.h> | |
17 | #include <linux/init.h> | |
18 | #include <linux/mm.h> | |
19 | #include <linux/swap.h> | |
20 | #include <linux/bootmem.h> | |
21 | #include <linux/irq.h> | |
22 | ||
23 | #include <asm/atomic.h> | |
24 | #include <asm/page.h> | |
25 | #include <asm/machdep.h> | |
26 | #include <asm/simsyscall.h> | |
27 | ||
28 | #include "mach.h" | |
29 | ||
30 | /* The name of a file containing the root filesystem. */ | |
31 | #define ROOT_FS "rootfs.image" | |
32 | ||
33 | extern void simcons_setup (void); | |
34 | extern void simcons_poll_ttys (void); | |
35 | extern void set_mem_root (void *addr, size_t len, char *cmd_line); | |
36 | ||
37 | static int read_file (const char *name, | |
38 | unsigned long *addr, unsigned long *len, | |
39 | const char **err); | |
40 | ||
41 | void __init mach_setup (char **cmdline) | |
42 | { | |
43 | const char *err; | |
44 | unsigned long root_dev_addr, root_dev_len; | |
45 | ||
46 | simcons_setup (); | |
47 | ||
48 | printk (KERN_INFO "Reading root filesystem: %s", ROOT_FS); | |
49 | ||
50 | if (read_file (ROOT_FS, &root_dev_addr, &root_dev_len, &err)) { | |
51 | printk (" (size %luK)\n", root_dev_len / 1024); | |
52 | set_mem_root ((void *)root_dev_addr, (size_t)root_dev_len, | |
53 | *cmdline); | |
54 | } else | |
55 | printk ("...%s failed!\n", err); | |
56 | } | |
57 | ||
58 | void mach_get_physical_ram (unsigned long *ram_start, unsigned long *ram_len) | |
59 | { | |
60 | *ram_start = RAM_ADDR; | |
61 | *ram_len = RAM_SIZE; | |
62 | } | |
63 | ||
64 | void __init mach_sched_init (struct irqaction *timer_action) | |
65 | { | |
66 | /* ...do magic timer initialization?... */ | |
67 | mach_tick = simcons_poll_ttys; | |
68 | setup_irq (0, timer_action); | |
69 | } | |
70 | ||
71 | \f | |
72 | static void irq_nop (unsigned irq) { } | |
73 | static unsigned irq_zero (unsigned irq) { return 0; } | |
74 | ||
75 | static struct hw_interrupt_type sim_irq_type = { | |
76 | "IRQ", | |
77 | irq_zero, /* startup */ | |
78 | irq_nop, /* shutdown */ | |
79 | irq_nop, /* enable */ | |
80 | irq_nop, /* disable */ | |
81 | irq_nop, /* ack */ | |
82 | irq_nop, /* end */ | |
83 | }; | |
84 | ||
85 | void __init mach_init_irqs (void) | |
86 | { | |
87 | init_irq_handlers (0, NUM_MACH_IRQS, 1, &sim_irq_type); | |
88 | } | |
89 | ||
90 | \f | |
91 | void mach_gettimeofday (struct timespec *tv) | |
92 | { | |
93 | long timeval[2], timezone[2]; | |
94 | int rval = V850_SIM_SYSCALL (gettimeofday, timeval, timezone); | |
95 | if (rval == 0) { | |
96 | tv->tv_sec = timeval[0]; | |
97 | tv->tv_nsec = timeval[1] * 1000; | |
98 | } | |
99 | } | |
100 | ||
101 | void machine_restart (char *__unused) | |
102 | { | |
103 | V850_SIM_SYSCALL (write, 1, "RESTART\n", 8); | |
104 | V850_SIM_SYSCALL (exit, 0); | |
105 | } | |
106 | ||
107 | EXPORT_SYMBOL(machine_restart); | |
108 | ||
109 | void machine_halt (void) | |
110 | { | |
111 | V850_SIM_SYSCALL (write, 1, "HALT\n", 5); | |
112 | V850_SIM_SYSCALL (exit, 0); | |
113 | } | |
114 | ||
115 | EXPORT_SYMBOL(machine_halt); | |
116 | ||
117 | void machine_power_off (void) | |
118 | { | |
119 | V850_SIM_SYSCALL (write, 1, "POWER OFF\n", 10); | |
120 | V850_SIM_SYSCALL (exit, 0); | |
121 | } | |
122 | ||
123 | EXPORT_SYMBOL(machine_power_off); | |
124 | ||
125 | \f | |
126 | /* Load data from a file called NAME into ram. The address and length | |
127 | of the data image are returned in ADDR and LEN. */ | |
128 | static int __init | |
129 | read_file (const char *name, | |
130 | unsigned long *addr, unsigned long *len, | |
131 | const char **err) | |
132 | { | |
133 | int rval, fd; | |
134 | unsigned long cur, left; | |
135 | /* Note this is not a normal stat buffer, it's an ad-hoc | |
136 | structure defined by the simulator. */ | |
137 | unsigned long stat_buf[10]; | |
138 | ||
139 | /* Stat the file to find out the length. */ | |
140 | rval = V850_SIM_SYSCALL (stat, name, stat_buf); | |
141 | if (rval < 0) { | |
142 | if (err) *err = "stat"; | |
143 | return 0; | |
144 | } | |
145 | *len = stat_buf[4]; | |
146 | ||
147 | /* Open the file; `0' is O_RDONLY. */ | |
148 | fd = V850_SIM_SYSCALL (open, name, 0); | |
149 | if (fd < 0) { | |
150 | if (err) *err = "open"; | |
151 | return 0; | |
152 | } | |
153 | ||
154 | *addr = (unsigned long)alloc_bootmem(*len); | |
155 | if (! *addr) { | |
156 | V850_SIM_SYSCALL (close, fd); | |
157 | if (err) *err = "alloc_bootmem"; | |
158 | return 0; | |
159 | } | |
160 | ||
161 | cur = *addr; | |
162 | left = *len; | |
163 | while (left > 0) { | |
164 | int chunk = V850_SIM_SYSCALL (read, fd, cur, left); | |
165 | if (chunk <= 0) | |
166 | break; | |
167 | cur += chunk; | |
168 | left -= chunk; | |
169 | } | |
170 | V850_SIM_SYSCALL (close, fd); | |
171 | if (left > 0) { | |
172 | /* Some read failed. */ | |
173 | free_bootmem (*addr, *len); | |
174 | if (err) *err = "read"; | |
175 | return 0; | |
176 | } | |
177 | ||
178 | return 1; | |
179 | } |