Commit 83fa1010ae342c5ad0392182fcdcce438c71b163
1 parent
f1ccf904
EtraxFS board support, by Edgar E. Iglesias.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3364 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
568 additions
and
0 deletions
hw/etraxfs.c
0 → 100644
1 | +/* | ||
2 | + * QEMU ETRAX System Emulator | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB. | ||
5 | + * | ||
6 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | + * of this software and associated documentation files (the "Software"), to deal | ||
8 | + * in the Software without restriction, including without limitation the rights | ||
9 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | + * copies of the Software, and to permit persons to whom the Software is | ||
11 | + * furnished to do so, subject to the following conditions: | ||
12 | + * | ||
13 | + * The above copyright notice and this permission notice shall be included in | ||
14 | + * all copies or substantial portions of the Software. | ||
15 | + * | ||
16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
22 | + * THE SOFTWARE. | ||
23 | + */ | ||
24 | +#include <time.h> | ||
25 | +#include <sys/time.h> | ||
26 | +#include "vl.h" | ||
27 | + | ||
28 | +extern FILE *logfile; | ||
29 | + | ||
30 | +static void main_cpu_reset(void *opaque) | ||
31 | +{ | ||
32 | + CPUState *env = opaque; | ||
33 | + cpu_reset(env); | ||
34 | +} | ||
35 | + | ||
36 | +static uint32_t fs_mmio_readb (void *opaque, target_phys_addr_t addr) | ||
37 | +{ | ||
38 | + CPUState *env = opaque; | ||
39 | + uint32_t r = 0; | ||
40 | + printf ("%s %x pc=%x\n", __func__, addr, env->pc); | ||
41 | + return r; | ||
42 | +} | ||
43 | +static uint32_t fs_mmio_readw (void *opaque, target_phys_addr_t addr) | ||
44 | +{ | ||
45 | + CPUState *env = opaque; | ||
46 | + uint32_t r = 0; | ||
47 | + printf ("%s %x pc=%x\n", __func__, addr, env->pc); | ||
48 | + return r; | ||
49 | +} | ||
50 | + | ||
51 | +static uint32_t fs_mmio_readl (void *opaque, target_phys_addr_t addr) | ||
52 | +{ | ||
53 | + CPUState *env = opaque; | ||
54 | + uint32_t r = 0; | ||
55 | + printf ("%s %x p=%x\n", __func__, addr, env->pc); | ||
56 | + return r; | ||
57 | +} | ||
58 | + | ||
59 | +static void | ||
60 | +fs_mmio_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
61 | +{ | ||
62 | + CPUState *env = opaque; | ||
63 | + printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | ||
64 | +} | ||
65 | +static void | ||
66 | +fs_mmio_writew (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
67 | +{ | ||
68 | + CPUState *env = opaque; | ||
69 | + printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | ||
70 | +} | ||
71 | +static void | ||
72 | +fs_mmio_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
73 | +{ | ||
74 | + CPUState *env = opaque; | ||
75 | + printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | ||
76 | +} | ||
77 | + | ||
78 | +static CPUReadMemoryFunc *fs_mmio_read[] = { | ||
79 | + &fs_mmio_readb, | ||
80 | + &fs_mmio_readw, | ||
81 | + &fs_mmio_readl, | ||
82 | +}; | ||
83 | + | ||
84 | +static CPUWriteMemoryFunc *fs_mmio_write[] = { | ||
85 | + &fs_mmio_writeb, | ||
86 | + &fs_mmio_writew, | ||
87 | + &fs_mmio_writel, | ||
88 | +}; | ||
89 | + | ||
90 | + | ||
91 | +/* Init functions for different blocks. */ | ||
92 | +extern void etraxfs_timer_init(CPUState *env, qemu_irq *irqs); | ||
93 | +extern void etraxfs_ser_init(CPUState *env, qemu_irq *irqs); | ||
94 | + | ||
95 | +void etrax_ack_irq(CPUState *env, uint32_t mask) | ||
96 | +{ | ||
97 | + env->pending_interrupts &= ~mask; | ||
98 | +} | ||
99 | + | ||
100 | +static void dummy_cpu_set_irq(void *opaque, int irq, int level) | ||
101 | +{ | ||
102 | + CPUState *env = opaque; | ||
103 | + | ||
104 | + /* Hmm, should this really be done here? */ | ||
105 | + env->pending_interrupts |= 1 << irq; | ||
106 | + cpu_interrupt(env, CPU_INTERRUPT_HARD); | ||
107 | +} | ||
108 | + | ||
109 | +static | ||
110 | +void bareetraxfs_init (int ram_size, int vga_ram_size, int boot_device, | ||
111 | + DisplayState *ds, const char **fd_filename, int snapshot, | ||
112 | + const char *kernel_filename, const char *kernel_cmdline, | ||
113 | + const char *initrd_filename, const char *cpu_model) | ||
114 | +{ | ||
115 | + CPUState *env; | ||
116 | + qemu_irq *irqs; | ||
117 | + int kernel_size; | ||
118 | + int internal_regs; | ||
119 | + | ||
120 | + /* init CPUs */ | ||
121 | + if (cpu_model == NULL) { | ||
122 | + cpu_model = "crisv32"; | ||
123 | + } | ||
124 | + env = cpu_init(); | ||
125 | +/* register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); */ | ||
126 | + qemu_register_reset(main_cpu_reset, env); | ||
127 | + irqs = qemu_allocate_irqs(dummy_cpu_set_irq, env, 32); | ||
128 | + | ||
129 | + internal_regs = cpu_register_io_memory(0, | ||
130 | + fs_mmio_read, fs_mmio_write, env); | ||
131 | + /* 0xb0050000 is the last reg. */ | ||
132 | + cpu_register_physical_memory (0xac000000, 0x4010000, internal_regs); | ||
133 | + /* allocate RAM */ | ||
134 | + cpu_register_physical_memory(0x40000000, ram_size, IO_MEM_RAM); | ||
135 | + | ||
136 | + etraxfs_timer_init(env, irqs); | ||
137 | + etraxfs_ser_init(env, irqs); | ||
138 | + | ||
139 | + kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000); | ||
140 | + /* magic for boot. */ | ||
141 | + env->regs[8] = 0x56902387; | ||
142 | + env->regs[9] = 0x40004000 + kernel_size; | ||
143 | + env->pc = 0x40004000; | ||
144 | + | ||
145 | + { | ||
146 | + unsigned char *ptr = phys_ram_base + 0x4000; | ||
147 | + int i; | ||
148 | + for (i = 0; i < 8; i++) | ||
149 | + { | ||
150 | + printf ("%2.2x ", ptr[i]); | ||
151 | + } | ||
152 | + printf("\n"); | ||
153 | + } | ||
154 | + | ||
155 | + printf ("pc =%x\n", env->pc); | ||
156 | + printf ("ram size =%d\n", ram_size); | ||
157 | + printf ("kernel name =%s\n", kernel_filename); | ||
158 | + printf ("kernel size =%d\n", kernel_size); | ||
159 | + printf ("cpu haltd =%d\n", env->halted); | ||
160 | +} | ||
161 | + | ||
162 | +void DMA_run(void) | ||
163 | +{ | ||
164 | +} | ||
165 | + | ||
166 | +void pic_info() | ||
167 | +{ | ||
168 | +} | ||
169 | + | ||
170 | +void irq_info() | ||
171 | +{ | ||
172 | +} | ||
173 | + | ||
174 | +QEMUMachine bareetraxfs_machine = { | ||
175 | + "bareetraxfs", | ||
176 | + "Bare ETRAX FS board", | ||
177 | + bareetraxfs_init, | ||
178 | +}; |
hw/etraxfs_ser.c
0 → 100644
1 | +/* | ||
2 | + * QEMU ETRAX System Emulator | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB. | ||
5 | + * | ||
6 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | + * of this software and associated documentation files (the "Software"), to deal | ||
8 | + * in the Software without restriction, including without limitation the rights | ||
9 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | + * copies of the Software, and to permit persons to whom the Software is | ||
11 | + * furnished to do so, subject to the following conditions: | ||
12 | + * | ||
13 | + * The above copyright notice and this permission notice shall be included in | ||
14 | + * all copies or substantial portions of the Software. | ||
15 | + * | ||
16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
22 | + * THE SOFTWARE. | ||
23 | + */ | ||
24 | + | ||
25 | +#include <stdio.h> | ||
26 | +#include <ctype.h> | ||
27 | +#include "vl.h" | ||
28 | + | ||
29 | +#define RW_TR_DMA_EN 0xb0026004 | ||
30 | +#define RW_DOUT 0xb002601c | ||
31 | +#define RW_STAT_DIN 0xb0026020 | ||
32 | +#define R_STAT_DIN 0xb0026024 | ||
33 | + | ||
34 | +static uint32_t ser_readb (void *opaque, target_phys_addr_t addr) | ||
35 | +{ | ||
36 | + CPUState *env = opaque; | ||
37 | + uint32_t r = 0; | ||
38 | + printf ("%s %x pc=%x\n", __func__, addr, env->pc); | ||
39 | + return r; | ||
40 | +} | ||
41 | +static uint32_t ser_readw (void *opaque, target_phys_addr_t addr) | ||
42 | +{ | ||
43 | + CPUState *env = opaque; | ||
44 | + uint32_t r = 0; | ||
45 | + printf ("%s %x pc=%x\n", __func__, addr, env->pc); | ||
46 | + return r; | ||
47 | +} | ||
48 | + | ||
49 | +static uint32_t ser_readl (void *opaque, target_phys_addr_t addr) | ||
50 | +{ | ||
51 | + CPUState *env = opaque; | ||
52 | + uint32_t r = 0; | ||
53 | + | ||
54 | + switch (addr) | ||
55 | + { | ||
56 | + case RW_TR_DMA_EN: | ||
57 | + break; | ||
58 | + case R_STAT_DIN: | ||
59 | + r |= 1 << 24; /* set tr_rdy. */ | ||
60 | + r |= 1 << 22; /* set tr_idle. */ | ||
61 | + break; | ||
62 | + | ||
63 | + default: | ||
64 | + printf ("%s %x p=%x\n", __func__, addr, env->pc); | ||
65 | + break; | ||
66 | + } | ||
67 | + return r; | ||
68 | +} | ||
69 | + | ||
70 | +static void | ||
71 | +ser_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
72 | +{ | ||
73 | + CPUState *env = opaque; | ||
74 | + printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | ||
75 | +} | ||
76 | +static void | ||
77 | +ser_writew (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
78 | +{ | ||
79 | + CPUState *env = opaque; | ||
80 | + printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | ||
81 | +} | ||
82 | +static void | ||
83 | +ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
84 | +{ | ||
85 | + CPUState *env = opaque; | ||
86 | + | ||
87 | + switch (addr) | ||
88 | + { | ||
89 | + case RW_TR_DMA_EN: | ||
90 | + break; | ||
91 | + case RW_DOUT: | ||
92 | + if (isprint(value) || isspace(value)) | ||
93 | + putchar(value); | ||
94 | + else | ||
95 | + putchar('.'); | ||
96 | + break; | ||
97 | + default: | ||
98 | + printf ("%s %x %x pc=%x\n", | ||
99 | + __func__, addr, value, env->pc); | ||
100 | + break; | ||
101 | + } | ||
102 | +} | ||
103 | + | ||
104 | +static CPUReadMemoryFunc *ser_read[] = { | ||
105 | + &ser_readb, | ||
106 | + &ser_readw, | ||
107 | + &ser_readl, | ||
108 | +}; | ||
109 | + | ||
110 | +static CPUWriteMemoryFunc *ser_write[] = { | ||
111 | + &ser_writeb, | ||
112 | + &ser_writew, | ||
113 | + &ser_writel, | ||
114 | +}; | ||
115 | + | ||
116 | +void etraxfs_ser_init(CPUState *env, qemu_irq *irqs) | ||
117 | +{ | ||
118 | + int ser_regs; | ||
119 | + | ||
120 | + ser_regs = cpu_register_io_memory(0, ser_read, ser_write, env); | ||
121 | + cpu_register_physical_memory (0xb0026000, 0x3c, ser_regs); | ||
122 | +} |
hw/etraxfs_timer.c
0 → 100644
1 | +/* | ||
2 | + * QEMU ETRAX System Emulator | ||
3 | + * | ||
4 | + * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB. | ||
5 | + * | ||
6 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | + * of this software and associated documentation files (the "Software"), to deal | ||
8 | + * in the Software without restriction, including without limitation the rights | ||
9 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | + * copies of the Software, and to permit persons to whom the Software is | ||
11 | + * furnished to do so, subject to the following conditions: | ||
12 | + * | ||
13 | + * The above copyright notice and this permission notice shall be included in | ||
14 | + * all copies or substantial portions of the Software. | ||
15 | + * | ||
16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
22 | + * THE SOFTWARE. | ||
23 | + */ | ||
24 | +#include <stdio.h> | ||
25 | +#include <sys/time.h> | ||
26 | +#include "vl.h" | ||
27 | + | ||
28 | +void etrax_ack_irq(CPUState *env, uint32_t mask); | ||
29 | + | ||
30 | +#define R_TIME 0xb001e038 | ||
31 | +#define RW_TMR0_DIV 0xb001e000 | ||
32 | +#define R_TMR0_DATA 0xb001e004 | ||
33 | +#define RW_TMR0_CTRL 0xb001e008 | ||
34 | +#define RW_TMR1_DIV 0xb001e010 | ||
35 | +#define R_TMR1_DATA 0xb001e014 | ||
36 | +#define RW_TMR1_CTRL 0xb001e018 | ||
37 | + | ||
38 | +#define RW_INTR_MASK 0xb001e048 | ||
39 | +#define RW_ACK_INTR 0xb001e04c | ||
40 | +#define R_INTR 0xb001e050 | ||
41 | +#define R_MASKED_INTR 0xb001e054 | ||
42 | + | ||
43 | + | ||
44 | +uint32_t rw_intr_mask; | ||
45 | +uint32_t rw_ack_intr; | ||
46 | +uint32_t r_intr; | ||
47 | + | ||
48 | +struct fs_timer_t { | ||
49 | + QEMUBH *bh; | ||
50 | + unsigned int limit; | ||
51 | + int scale; | ||
52 | + ptimer_state *ptimer; | ||
53 | + CPUState *env; | ||
54 | + qemu_irq *irq; | ||
55 | + uint32_t mask; | ||
56 | +}; | ||
57 | + | ||
58 | +static struct fs_timer_t timer0; | ||
59 | + | ||
60 | +/* diff two timevals. Return a single int in us. */ | ||
61 | +int diff_timeval_us(struct timeval *a, struct timeval *b) | ||
62 | +{ | ||
63 | + int diff; | ||
64 | + | ||
65 | + /* assume these values are signed. */ | ||
66 | + diff = (a->tv_sec - b->tv_sec) * 1000 * 1000; | ||
67 | + diff += (a->tv_usec - b->tv_usec); | ||
68 | + return diff; | ||
69 | +} | ||
70 | + | ||
71 | +static uint32_t timer_readb (void *opaque, target_phys_addr_t addr) | ||
72 | +{ | ||
73 | + CPUState *env = opaque; | ||
74 | + uint32_t r = 0; | ||
75 | + printf ("%s %x pc=%x\n", __func__, addr, env->pc); | ||
76 | + return r; | ||
77 | +} | ||
78 | +static uint32_t timer_readw (void *opaque, target_phys_addr_t addr) | ||
79 | +{ | ||
80 | + CPUState *env = opaque; | ||
81 | + uint32_t r = 0; | ||
82 | + printf ("%s %x pc=%x\n", __func__, addr, env->pc); | ||
83 | + return r; | ||
84 | +} | ||
85 | + | ||
86 | +static uint32_t timer_readl (void *opaque, target_phys_addr_t addr) | ||
87 | +{ | ||
88 | + CPUState *env = opaque; | ||
89 | + uint32_t r = 0; | ||
90 | + | ||
91 | + switch (addr) { | ||
92 | + case R_TMR0_DATA: | ||
93 | + break; | ||
94 | + case R_TMR1_DATA: | ||
95 | + printf ("R_TMR1_DATA\n"); | ||
96 | + break; | ||
97 | + case R_TIME: | ||
98 | + { | ||
99 | + static struct timeval last; | ||
100 | + struct timeval now; | ||
101 | + gettimeofday(&now, NULL); | ||
102 | + if (!(last.tv_sec == 0 && last.tv_usec == 0)) { | ||
103 | + r = diff_timeval_us(&now, &last); | ||
104 | + r *= 1000; /* convert to ns. */ | ||
105 | + r++; /* make sure we increase for each call. */ | ||
106 | + } | ||
107 | + last = now; | ||
108 | + break; | ||
109 | + } | ||
110 | + | ||
111 | + case RW_INTR_MASK: | ||
112 | + r = rw_intr_mask; | ||
113 | + break; | ||
114 | + case R_MASKED_INTR: | ||
115 | + r = r_intr & rw_intr_mask; | ||
116 | + break; | ||
117 | + default: | ||
118 | + printf ("%s %x p=%x\n", __func__, addr, env->pc); | ||
119 | + break; | ||
120 | + } | ||
121 | + return r; | ||
122 | +} | ||
123 | + | ||
124 | +static void | ||
125 | +timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
126 | +{ | ||
127 | + CPUState *env = opaque; | ||
128 | + printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | ||
129 | +} | ||
130 | +static void | ||
131 | +timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
132 | +{ | ||
133 | + CPUState *env = opaque; | ||
134 | + printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc); | ||
135 | +} | ||
136 | + | ||
137 | +static void write_ctrl(struct fs_timer_t *t, uint32_t v) | ||
138 | +{ | ||
139 | + int op; | ||
140 | + int freq; | ||
141 | + int freq_hz; | ||
142 | + | ||
143 | + op = v & 3; | ||
144 | + freq = v >> 2; | ||
145 | + freq_hz = 32000000; | ||
146 | + | ||
147 | + switch (freq) | ||
148 | + { | ||
149 | + case 0: | ||
150 | + case 1: | ||
151 | + printf ("extern or disabled timer clock?\n"); | ||
152 | + break; | ||
153 | + case 4: freq_hz = 29493000; break; | ||
154 | + case 5: freq_hz = 32000000; break; | ||
155 | + case 6: freq_hz = 32768000; break; | ||
156 | + case 7: freq_hz = 100000000; break; | ||
157 | + default: | ||
158 | + abort(); | ||
159 | + break; | ||
160 | + } | ||
161 | + | ||
162 | + printf ("freq_hz=%d limit=%d\n", freq_hz, t->limit); | ||
163 | + t->scale = 0; | ||
164 | + if (t->limit > 2048) | ||
165 | + { | ||
166 | + t->scale = 2048; | ||
167 | + ptimer_set_period(timer0.ptimer, freq_hz / t->scale); | ||
168 | + } | ||
169 | + | ||
170 | + printf ("op=%d\n", op); | ||
171 | + switch (op) | ||
172 | + { | ||
173 | + case 0: | ||
174 | + printf ("limit=%d %d\n", t->limit, t->limit/t->scale); | ||
175 | + ptimer_set_limit(t->ptimer, t->limit / t->scale, 1); | ||
176 | + break; | ||
177 | + case 1: | ||
178 | + ptimer_stop(t->ptimer); | ||
179 | + break; | ||
180 | + case 2: | ||
181 | + ptimer_run(t->ptimer, 0); | ||
182 | + break; | ||
183 | + default: | ||
184 | + abort(); | ||
185 | + break; | ||
186 | + } | ||
187 | +} | ||
188 | + | ||
189 | +static void timer_ack_irq(void) | ||
190 | +{ | ||
191 | + if (!(r_intr & timer0.mask & rw_intr_mask)) { | ||
192 | + qemu_irq_lower(timer0.irq[0]); | ||
193 | + etrax_ack_irq(timer0.env, 1 << 0x1b); | ||
194 | + } | ||
195 | +} | ||
196 | + | ||
197 | +static void | ||
198 | +timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | ||
199 | +{ | ||
200 | + CPUState *env = opaque; | ||
201 | + printf ("%s %x %x pc=%x\n", | ||
202 | + __func__, addr, value, env->pc); | ||
203 | + switch (addr) | ||
204 | + { | ||
205 | + case RW_TMR0_DIV: | ||
206 | + printf ("RW_TMR0_DIV=%x\n", value); | ||
207 | + timer0.limit = value; | ||
208 | + break; | ||
209 | + case RW_TMR0_CTRL: | ||
210 | + printf ("RW_TMR0_CTRL=%x\n", value); | ||
211 | + write_ctrl(&timer0, value); | ||
212 | + break; | ||
213 | + case RW_TMR1_DIV: | ||
214 | + printf ("RW_TMR1_DIV=%x\n", value); | ||
215 | + break; | ||
216 | + case RW_TMR1_CTRL: | ||
217 | + printf ("RW_TMR1_CTRL=%x\n", value); | ||
218 | + break; | ||
219 | + case RW_INTR_MASK: | ||
220 | + printf ("RW_INTR_MASK=%x\n", value); | ||
221 | + rw_intr_mask = value; | ||
222 | + break; | ||
223 | + case RW_ACK_INTR: | ||
224 | + r_intr &= ~value; | ||
225 | + timer_ack_irq(); | ||
226 | + break; | ||
227 | + default: | ||
228 | + printf ("%s %x %x pc=%x\n", | ||
229 | + __func__, addr, value, env->pc); | ||
230 | + break; | ||
231 | + } | ||
232 | +} | ||
233 | + | ||
234 | +static CPUReadMemoryFunc *timer_read[] = { | ||
235 | + &timer_readb, | ||
236 | + &timer_readw, | ||
237 | + &timer_readl, | ||
238 | +}; | ||
239 | + | ||
240 | +static CPUWriteMemoryFunc *timer_write[] = { | ||
241 | + &timer_writeb, | ||
242 | + &timer_writew, | ||
243 | + &timer_writel, | ||
244 | +}; | ||
245 | + | ||
246 | +static void timer_irq(void *opaque) | ||
247 | +{ | ||
248 | + struct fs_timer_t *t = opaque; | ||
249 | + | ||
250 | + r_intr |= t->mask; | ||
251 | + if (t->mask & rw_intr_mask) { | ||
252 | + qemu_irq_raise(t->irq[0]); | ||
253 | + } | ||
254 | +} | ||
255 | + | ||
256 | +void etraxfs_timer_init(CPUState *env, qemu_irq *irqs) | ||
257 | +{ | ||
258 | + int timer_regs; | ||
259 | + | ||
260 | + timer0.bh = qemu_bh_new(timer_irq, &timer0); | ||
261 | + timer0.ptimer = ptimer_init(timer0.bh); | ||
262 | + timer0.irq = irqs + 0x1b; | ||
263 | + timer0.mask = 1; | ||
264 | + timer0.env = env; | ||
265 | + | ||
266 | + timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env); | ||
267 | + cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs); | ||
268 | +} |