Commit 20dcee9483361ee0621cf6d68d271ecde686fd9c
1 parent
62ea5b0b
MCF5208 emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2924 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
13 changed files
with
833 additions
and
296 deletions
Makefile.target
@@ -467,7 +467,7 @@ ifeq ($(TARGET_BASE_ARCH), sh4) | @@ -467,7 +467,7 @@ ifeq ($(TARGET_BASE_ARCH), sh4) | ||
467 | VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o | 467 | VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o |
468 | endif | 468 | endif |
469 | ifeq ($(TARGET_BASE_ARCH), m68k) | 469 | ifeq ($(TARGET_BASE_ARCH), m68k) |
470 | -VL_OBJS+= an5206.o mcf5206.o ptimer.o | 470 | +VL_OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o |
471 | VL_OBJS+= m68k-semi.o | 471 | VL_OBJS+= m68k-semi.o |
472 | endif | 472 | endif |
473 | ifdef CONFIG_GDBSTUB | 473 | ifdef CONFIG_GDBSTUB |
hw/an5206.c
@@ -40,7 +40,9 @@ static void an5206_init(int ram_size, int vga_ram_size, int boot_device, | @@ -40,7 +40,9 @@ static void an5206_init(int ram_size, int vga_ram_size, int boot_device, | ||
40 | env = cpu_init(); | 40 | env = cpu_init(); |
41 | if (!cpu_model) | 41 | if (!cpu_model) |
42 | cpu_model = "m5206"; | 42 | cpu_model = "m5206"; |
43 | - cpu_m68k_set_model(env, cpu_model); | 43 | + if (cpu_m68k_set_model(env, cpu_model)) { |
44 | + cpu_abort(env, "Unable to find m68k CPU definition\n"); | ||
45 | + } | ||
44 | 46 | ||
45 | /* Initialize CPU registers. */ | 47 | /* Initialize CPU registers. */ |
46 | env->vbr = 0; | 48 | env->vbr = 0; |
hw/mcf5206.c
@@ -139,285 +139,12 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq) | @@ -139,285 +139,12 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq) | ||
139 | return s; | 139 | return s; |
140 | } | 140 | } |
141 | 141 | ||
142 | -/* UART */ | ||
143 | - | ||
144 | -typedef struct { | ||
145 | - uint8_t mr[2]; | ||
146 | - uint8_t sr; | ||
147 | - uint8_t isr; | ||
148 | - uint8_t imr; | ||
149 | - uint8_t bg1; | ||
150 | - uint8_t bg2; | ||
151 | - uint8_t fifo[4]; | ||
152 | - uint8_t tb; | ||
153 | - int current_mr; | ||
154 | - int fifo_len; | ||
155 | - int tx_enabled; | ||
156 | - int rx_enabled; | ||
157 | - qemu_irq irq; | ||
158 | - CharDriverState *chr; | ||
159 | -} m5206_uart_state; | ||
160 | - | ||
161 | -/* UART Status Register bits. */ | ||
162 | -#define M5206_UART_RxRDY 0x01 | ||
163 | -#define M5206_UART_FFULL 0x02 | ||
164 | -#define M5206_UART_TxRDY 0x04 | ||
165 | -#define M5206_UART_TxEMP 0x08 | ||
166 | -#define M5206_UART_OE 0x10 | ||
167 | -#define M5206_UART_PE 0x20 | ||
168 | -#define M5206_UART_FE 0x40 | ||
169 | -#define M5206_UART_RB 0x80 | ||
170 | - | ||
171 | -/* Interrupt flags. */ | ||
172 | -#define M5206_UART_TxINT 0x01 | ||
173 | -#define M5206_UART_RxINT 0x02 | ||
174 | -#define M5206_UART_DBINT 0x04 | ||
175 | -#define M5206_UART_COSINT 0x80 | ||
176 | - | ||
177 | -/* UMR1 flags. */ | ||
178 | -#define M5206_UART_BC0 0x01 | ||
179 | -#define M5206_UART_BC1 0x02 | ||
180 | -#define M5206_UART_PT 0x04 | ||
181 | -#define M5206_UART_PM0 0x08 | ||
182 | -#define M5206_UART_PM1 0x10 | ||
183 | -#define M5206_UART_ERR 0x20 | ||
184 | -#define M5206_UART_RxIRQ 0x40 | ||
185 | -#define M5206_UART_RxRTS 0x80 | ||
186 | - | ||
187 | -static void m5206_uart_update(m5206_uart_state *s) | ||
188 | -{ | ||
189 | - s->isr &= ~(M5206_UART_TxINT | M5206_UART_RxINT); | ||
190 | - if (s->sr & M5206_UART_TxRDY) | ||
191 | - s->isr |= M5206_UART_TxINT; | ||
192 | - if ((s->sr & ((s->mr[0] & M5206_UART_RxIRQ) | ||
193 | - ? M5206_UART_FFULL : M5206_UART_RxRDY)) != 0) | ||
194 | - s->isr |= M5206_UART_RxINT; | ||
195 | - | ||
196 | - qemu_set_irq(s->irq, (s->isr & s->imr) != 0); | ||
197 | -} | ||
198 | - | ||
199 | -static uint32_t m5206_uart_read(m5206_uart_state *s, uint32_t addr) | ||
200 | -{ | ||
201 | - switch (addr) { | ||
202 | - case 0x00: | ||
203 | - return s->mr[s->current_mr]; | ||
204 | - case 0x04: | ||
205 | - return s->sr; | ||
206 | - case 0x0c: | ||
207 | - { | ||
208 | - uint8_t val; | ||
209 | - int i; | ||
210 | - | ||
211 | - if (s->fifo_len == 0) | ||
212 | - return 0; | ||
213 | - | ||
214 | - val = s->fifo[0]; | ||
215 | - s->fifo_len--; | ||
216 | - for (i = 0; i < s->fifo_len; i++) | ||
217 | - s->fifo[i] = s->fifo[i + 1]; | ||
218 | - s->sr &= ~M5206_UART_FFULL; | ||
219 | - if (s->fifo_len == 0) | ||
220 | - s->sr &= ~M5206_UART_RxRDY; | ||
221 | - m5206_uart_update(s); | ||
222 | - return val; | ||
223 | - } | ||
224 | - case 0x10: | ||
225 | - /* TODO: Implement IPCR. */ | ||
226 | - return 0; | ||
227 | - case 0x14: | ||
228 | - return s->isr; | ||
229 | - case 0x18: | ||
230 | - return s->bg1; | ||
231 | - case 0x1c: | ||
232 | - return s->bg2; | ||
233 | - default: | ||
234 | - return 0; | ||
235 | - } | ||
236 | -} | ||
237 | - | ||
238 | -/* Update TxRDY flag and set data if present and enabled. */ | ||
239 | -static void m5206_uart_do_tx(m5206_uart_state *s) | ||
240 | -{ | ||
241 | - if (s->tx_enabled && (s->sr & M5206_UART_TxEMP) == 0) { | ||
242 | - if (s->chr) | ||
243 | - qemu_chr_write(s->chr, (unsigned char *)&s->tb, 1); | ||
244 | - s->sr |= M5206_UART_TxEMP; | ||
245 | - } | ||
246 | - if (s->tx_enabled) { | ||
247 | - s->sr |= M5206_UART_TxRDY; | ||
248 | - } else { | ||
249 | - s->sr &= ~M5206_UART_TxRDY; | ||
250 | - } | ||
251 | -} | ||
252 | - | ||
253 | -static void m5206_do_command(m5206_uart_state *s, uint8_t cmd) | ||
254 | -{ | ||
255 | - /* Misc command. */ | ||
256 | - switch ((cmd >> 4) & 3) { | ||
257 | - case 0: /* No-op. */ | ||
258 | - break; | ||
259 | - case 1: /* Reset mode register pointer. */ | ||
260 | - s->current_mr = 0; | ||
261 | - break; | ||
262 | - case 2: /* Reset receiver. */ | ||
263 | - s->rx_enabled = 0; | ||
264 | - s->fifo_len = 0; | ||
265 | - s->sr &= ~(M5206_UART_RxRDY | M5206_UART_FFULL); | ||
266 | - break; | ||
267 | - case 3: /* Reset transmitter. */ | ||
268 | - s->tx_enabled = 0; | ||
269 | - s->sr |= M5206_UART_TxEMP; | ||
270 | - s->sr &= ~M5206_UART_TxRDY; | ||
271 | - break; | ||
272 | - case 4: /* Reset error status. */ | ||
273 | - break; | ||
274 | - case 5: /* Reset break-change interrupt. */ | ||
275 | - s->isr &= ~M5206_UART_DBINT; | ||
276 | - break; | ||
277 | - case 6: /* Start break. */ | ||
278 | - case 7: /* Stop break. */ | ||
279 | - break; | ||
280 | - } | ||
281 | - | ||
282 | - /* Transmitter command. */ | ||
283 | - switch ((cmd >> 2) & 3) { | ||
284 | - case 0: /* No-op. */ | ||
285 | - break; | ||
286 | - case 1: /* Enable. */ | ||
287 | - s->tx_enabled = 1; | ||
288 | - m5206_uart_do_tx(s); | ||
289 | - break; | ||
290 | - case 2: /* Disable. */ | ||
291 | - s->tx_enabled = 0; | ||
292 | - m5206_uart_do_tx(s); | ||
293 | - break; | ||
294 | - case 3: /* Reserved. */ | ||
295 | - fprintf(stderr, "m5206_uart: Bad TX command\n"); | ||
296 | - break; | ||
297 | - } | ||
298 | - | ||
299 | - /* Receiver command. */ | ||
300 | - switch (cmd & 3) { | ||
301 | - case 0: /* No-op. */ | ||
302 | - break; | ||
303 | - case 1: /* Enable. */ | ||
304 | - s->rx_enabled = 1; | ||
305 | - break; | ||
306 | - case 2: | ||
307 | - s->rx_enabled = 0; | ||
308 | - break; | ||
309 | - case 3: /* Reserved. */ | ||
310 | - fprintf(stderr, "m5206_uart: Bad RX command\n"); | ||
311 | - break; | ||
312 | - } | ||
313 | -} | ||
314 | - | ||
315 | -static void m5206_uart_write(m5206_uart_state *s, uint32_t addr, uint32_t val) | ||
316 | -{ | ||
317 | - switch (addr) { | ||
318 | - case 0x00: | ||
319 | - s->mr[s->current_mr] = val; | ||
320 | - s->current_mr = 1; | ||
321 | - break; | ||
322 | - case 0x04: | ||
323 | - /* CSR is ignored. */ | ||
324 | - break; | ||
325 | - case 0x08: /* Command Register. */ | ||
326 | - m5206_do_command(s, val); | ||
327 | - break; | ||
328 | - case 0x0c: /* Transmit Buffer. */ | ||
329 | - s->sr &= ~M5206_UART_TxEMP; | ||
330 | - s->tb = val; | ||
331 | - m5206_uart_do_tx(s); | ||
332 | - break; | ||
333 | - case 0x10: | ||
334 | - /* ACR is ignored. */ | ||
335 | - break; | ||
336 | - case 0x14: | ||
337 | - s->imr = val; | ||
338 | - break; | ||
339 | - default: | ||
340 | - break; | ||
341 | - } | ||
342 | - m5206_uart_update(s); | ||
343 | -} | ||
344 | - | ||
345 | -static void m5206_uart_reset(m5206_uart_state *s) | ||
346 | -{ | ||
347 | - s->fifo_len = 0; | ||
348 | - s->mr[0] = 0; | ||
349 | - s->mr[1] = 0; | ||
350 | - s->sr = M5206_UART_TxEMP; | ||
351 | - s->tx_enabled = 0; | ||
352 | - s->rx_enabled = 0; | ||
353 | - s->isr = 0; | ||
354 | - s->imr = 0; | ||
355 | -} | ||
356 | - | ||
357 | -static void m5206_uart_push_byte(m5206_uart_state *s, uint8_t data) | ||
358 | -{ | ||
359 | - /* Break events overwrite the last byte if the fifo is full. */ | ||
360 | - if (s->fifo_len == 4) | ||
361 | - s->fifo_len--; | ||
362 | - | ||
363 | - s->fifo[s->fifo_len] = data; | ||
364 | - s->fifo_len++; | ||
365 | - s->sr |= M5206_UART_RxRDY; | ||
366 | - if (s->fifo_len == 4) | ||
367 | - s->sr |= M5206_UART_FFULL; | ||
368 | - | ||
369 | - m5206_uart_update(s); | ||
370 | -} | ||
371 | - | ||
372 | -static void m5206_uart_event(void *opaque, int event) | ||
373 | -{ | ||
374 | - m5206_uart_state *s = (m5206_uart_state *)opaque; | ||
375 | - | ||
376 | - switch (event) { | ||
377 | - case CHR_EVENT_BREAK: | ||
378 | - s->isr |= M5206_UART_DBINT; | ||
379 | - m5206_uart_push_byte(s, 0); | ||
380 | - break; | ||
381 | - default: | ||
382 | - break; | ||
383 | - } | ||
384 | -} | ||
385 | - | ||
386 | -static int m5206_uart_can_receive(void *opaque) | ||
387 | -{ | ||
388 | - m5206_uart_state *s = (m5206_uart_state *)opaque; | ||
389 | - | ||
390 | - return s->rx_enabled && (s->sr & M5206_UART_FFULL) == 0; | ||
391 | -} | ||
392 | - | ||
393 | -static void m5206_uart_receive(void *opaque, const uint8_t *buf, int size) | ||
394 | -{ | ||
395 | - m5206_uart_state *s = (m5206_uart_state *)opaque; | ||
396 | - | ||
397 | - m5206_uart_push_byte(s, buf[0]); | ||
398 | -} | ||
399 | - | ||
400 | -static m5206_uart_state *m5206_uart_init(qemu_irq irq, CharDriverState *chr) | ||
401 | -{ | ||
402 | - m5206_uart_state *s; | ||
403 | - | ||
404 | - s = qemu_mallocz(sizeof(m5206_uart_state)); | ||
405 | - s->chr = chr; | ||
406 | - s->irq = irq; | ||
407 | - if (chr) { | ||
408 | - qemu_chr_add_handlers(chr, m5206_uart_can_receive, m5206_uart_receive, | ||
409 | - m5206_uart_event, s); | ||
410 | - } | ||
411 | - m5206_uart_reset(s); | ||
412 | - return s; | ||
413 | -} | ||
414 | - | ||
415 | /* System Integration Module. */ | 142 | /* System Integration Module. */ |
416 | 143 | ||
417 | typedef struct { | 144 | typedef struct { |
418 | CPUState *env; | 145 | CPUState *env; |
419 | m5206_timer_state *timer[2]; | 146 | m5206_timer_state *timer[2]; |
420 | - m5206_uart_state *uart[2]; | 147 | + void *uart[2]; |
421 | uint8_t scr; | 148 | uint8_t scr; |
422 | uint8_t icr[14]; | 149 | uint8_t icr[14]; |
423 | uint16_t imr; /* 1 == interrupt is masked. */ | 150 | uint16_t imr; /* 1 == interrupt is masked. */ |
@@ -540,9 +267,9 @@ static uint32_t m5206_mbar_read(m5206_mbar_state *s, uint32_t offset) | @@ -540,9 +267,9 @@ static uint32_t m5206_mbar_read(m5206_mbar_state *s, uint32_t offset) | ||
540 | } else if (offset >= 0x120 && offset < 0x140) { | 267 | } else if (offset >= 0x120 && offset < 0x140) { |
541 | return m5206_timer_read(s->timer[1], offset - 0x120); | 268 | return m5206_timer_read(s->timer[1], offset - 0x120); |
542 | } else if (offset >= 0x140 && offset < 0x160) { | 269 | } else if (offset >= 0x140 && offset < 0x160) { |
543 | - return m5206_uart_read(s->uart[0], offset - 0x140); | 270 | + return mcf_uart_read(s->uart[0], offset - 0x140); |
544 | } else if (offset >= 0x180 && offset < 0x1a0) { | 271 | } else if (offset >= 0x180 && offset < 0x1a0) { |
545 | - return m5206_uart_read(s->uart[1], offset - 0x180); | 272 | + return mcf_uart_read(s->uart[1], offset - 0x180); |
546 | } | 273 | } |
547 | switch (offset) { | 274 | switch (offset) { |
548 | case 0x03: return s->scr; | 275 | case 0x03: return s->scr; |
@@ -580,10 +307,10 @@ static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset, | @@ -580,10 +307,10 @@ static void m5206_mbar_write(m5206_mbar_state *s, uint32_t offset, | ||
580 | m5206_timer_write(s->timer[1], offset - 0x120, value); | 307 | m5206_timer_write(s->timer[1], offset - 0x120, value); |
581 | return; | 308 | return; |
582 | } else if (offset >= 0x140 && offset < 0x160) { | 309 | } else if (offset >= 0x140 && offset < 0x160) { |
583 | - m5206_uart_write(s->uart[0], offset - 0x140, value); | 310 | + mcf_uart_write(s->uart[0], offset - 0x140, value); |
584 | return; | 311 | return; |
585 | } else if (offset >= 0x180 && offset < 0x1a0) { | 312 | } else if (offset >= 0x180 && offset < 0x1a0) { |
586 | - m5206_uart_write(s->uart[1], offset - 0x180, value); | 313 | + mcf_uart_write(s->uart[1], offset - 0x180, value); |
587 | return; | 314 | return; |
588 | } | 315 | } |
589 | switch (offset) { | 316 | switch (offset) { |
@@ -798,13 +525,13 @@ qemu_irq *mcf5206_init(uint32_t base, CPUState *env) | @@ -798,13 +525,13 @@ qemu_irq *mcf5206_init(uint32_t base, CPUState *env) | ||
798 | s = (m5206_mbar_state *)qemu_mallocz(sizeof(m5206_mbar_state)); | 525 | s = (m5206_mbar_state *)qemu_mallocz(sizeof(m5206_mbar_state)); |
799 | iomemtype = cpu_register_io_memory(0, m5206_mbar_readfn, | 526 | iomemtype = cpu_register_io_memory(0, m5206_mbar_readfn, |
800 | m5206_mbar_writefn, s); | 527 | m5206_mbar_writefn, s); |
801 | - cpu_register_physical_memory(base, 0x00000fff, iomemtype); | 528 | + cpu_register_physical_memory(base, 0x00001000, iomemtype); |
802 | 529 | ||
803 | pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14); | 530 | pic = qemu_allocate_irqs(m5206_mbar_set_irq, s, 14); |
804 | s->timer[0] = m5206_timer_init(pic[9]); | 531 | s->timer[0] = m5206_timer_init(pic[9]); |
805 | s->timer[1] = m5206_timer_init(pic[10]); | 532 | s->timer[1] = m5206_timer_init(pic[10]); |
806 | - s->uart[0] = m5206_uart_init(pic[12], serial_hds[0]); | ||
807 | - s->uart[1] = m5206_uart_init(pic[13], serial_hds[1]); | 533 | + s->uart[0] = mcf_uart_init(pic[12], serial_hds[0]); |
534 | + s->uart[1] = mcf_uart_init(pic[13], serial_hds[1]); | ||
808 | s->env = env; | 535 | s->env = env; |
809 | 536 | ||
810 | m5206_mbar_reset(s); | 537 | m5206_mbar_reset(s); |
hw/mcf5208.c
0 โ 100644
1 | +/* | ||
2 | + * Motorola ColdFire MCF5208 SoC emulation. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 CodeSourcery. | ||
5 | + * | ||
6 | + * This code is licenced under the GPL | ||
7 | + */ | ||
8 | +#include "vl.h" | ||
9 | + | ||
10 | +#define SYS_FREQ 66000000 | ||
11 | + | ||
12 | +#define PCSR_EN 0x0001 | ||
13 | +#define PCSR_RLD 0x0002 | ||
14 | +#define PCSR_PIF 0x0004 | ||
15 | +#define PCSR_PIE 0x0008 | ||
16 | +#define PCSR_OVW 0x0010 | ||
17 | +#define PCSR_DBG 0x0020 | ||
18 | +#define PCSR_DOZE 0x0040 | ||
19 | +#define PCSR_PRE_SHIFT 8 | ||
20 | +#define PCSR_PRE_MASK 0x0f00 | ||
21 | + | ||
22 | +typedef struct { | ||
23 | + qemu_irq irq; | ||
24 | + ptimer_state *timer; | ||
25 | + uint16_t pcsr; | ||
26 | + uint16_t pmr; | ||
27 | + uint16_t pcntr; | ||
28 | +} m5208_timer_state; | ||
29 | + | ||
30 | +static void m5208_timer_update(m5208_timer_state *s) | ||
31 | +{ | ||
32 | + if ((s->pcsr & (PCSR_PIE | PCSR_PIF)) == (PCSR_PIE | PCSR_PIF)) | ||
33 | + qemu_irq_raise(s->irq); | ||
34 | + else | ||
35 | + qemu_irq_lower(s->irq); | ||
36 | +} | ||
37 | + | ||
38 | +static void m5208_timer_write(m5208_timer_state *s, int offset, | ||
39 | + uint32_t value) | ||
40 | +{ | ||
41 | + int prescale; | ||
42 | + int limit; | ||
43 | + switch (offset) { | ||
44 | + case 0: | ||
45 | + /* The PIF bit is set-to-clear. */ | ||
46 | + if (value & PCSR_PIF) { | ||
47 | + s->pcsr &= ~PCSR_PIF; | ||
48 | + value &= ~PCSR_PIF; | ||
49 | + } | ||
50 | + /* Avoid frobbing the timer if we're just twiddling IRQ bits. */ | ||
51 | + if (((s->pcsr ^ value) & ~PCSR_PIE) == 0) { | ||
52 | + s->pcsr = value; | ||
53 | + m5208_timer_update(s); | ||
54 | + return; | ||
55 | + } | ||
56 | + | ||
57 | + if (s->pcsr & PCSR_EN) | ||
58 | + ptimer_stop(s->timer); | ||
59 | + | ||
60 | + s->pcsr = value; | ||
61 | + | ||
62 | + prescale = 1 << ((s->pcsr & PCSR_PRE_MASK) >> PCSR_PRE_SHIFT); | ||
63 | + ptimer_set_freq(s->timer, (SYS_FREQ / 2) / prescale); | ||
64 | + if (s->pcsr & PCSR_RLD) | ||
65 | + limit = 0xffff; | ||
66 | + else | ||
67 | + limit = s->pmr; | ||
68 | + ptimer_set_limit(s->timer, limit, 0); | ||
69 | + | ||
70 | + if (s->pcsr & PCSR_EN) | ||
71 | + ptimer_run(s->timer, 0); | ||
72 | + break; | ||
73 | + case 2: | ||
74 | + s->pmr = value; | ||
75 | + s->pcsr &= ~PCSR_PIF; | ||
76 | + if (s->pcsr & PCSR_RLD) | ||
77 | + value = 0xffff; | ||
78 | + ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW); | ||
79 | + break; | ||
80 | + case 4: | ||
81 | + break; | ||
82 | + default: | ||
83 | + /* Should never happen. */ | ||
84 | + abort(); | ||
85 | + } | ||
86 | + m5208_timer_update(s); | ||
87 | +} | ||
88 | + | ||
89 | +static void m5208_timer_trigger(void *opaque) | ||
90 | +{ | ||
91 | + m5208_timer_state *s = (m5208_timer_state *)opaque; | ||
92 | + s->pcsr |= PCSR_PIF; | ||
93 | + m5208_timer_update(s); | ||
94 | +} | ||
95 | + | ||
96 | +typedef struct { | ||
97 | + m5208_timer_state timer[2]; | ||
98 | +} m5208_sys_state; | ||
99 | + | ||
100 | +static uint32_t m5208_sys_read(void *opaque, target_phys_addr_t addr) | ||
101 | +{ | ||
102 | + m5208_sys_state *s = (m5208_sys_state *)opaque; | ||
103 | + switch (addr) { | ||
104 | + /* PIT0 */ | ||
105 | + case 0xfc080000: | ||
106 | + return s->timer[0].pcsr; | ||
107 | + case 0xfc080002: | ||
108 | + return s->timer[0].pmr; | ||
109 | + case 0xfc080004: | ||
110 | + return ptimer_get_count(s->timer[0].timer); | ||
111 | + /* PIT1 */ | ||
112 | + case 0xfc084000: | ||
113 | + return s->timer[1].pcsr; | ||
114 | + case 0xfc084002: | ||
115 | + return s->timer[1].pmr; | ||
116 | + case 0xfc084004: | ||
117 | + return ptimer_get_count(s->timer[1].timer); | ||
118 | + | ||
119 | + /* SDRAM Controller. */ | ||
120 | + case 0xfc0a8110: /* SDCS0 */ | ||
121 | + { | ||
122 | + int n; | ||
123 | + for (n = 0; n < 32; n++) { | ||
124 | + if (ram_size < (2u << n)) | ||
125 | + break; | ||
126 | + } | ||
127 | + return (n - 1) | 0x40000000; | ||
128 | + } | ||
129 | + case 0xfc0a8114: /* SDCS1 */ | ||
130 | + return 0; | ||
131 | + | ||
132 | + default: | ||
133 | + cpu_abort(cpu_single_env, "m5208_sys_read: Bad offset 0x%x\n", | ||
134 | + (int)addr); | ||
135 | + return 0; | ||
136 | + } | ||
137 | +} | ||
138 | + | ||
139 | +static void m5208_sys_write(void *opaque, target_phys_addr_t addr, | ||
140 | + uint32_t value) | ||
141 | +{ | ||
142 | + m5208_sys_state *s = (m5208_sys_state *)opaque; | ||
143 | + switch (addr) { | ||
144 | + /* PIT0 */ | ||
145 | + case 0xfc080000: | ||
146 | + case 0xfc080002: | ||
147 | + case 0xfc080004: | ||
148 | + m5208_timer_write(&s->timer[0], addr & 0xf, value); | ||
149 | + return; | ||
150 | + /* PIT1 */ | ||
151 | + case 0xfc084000: | ||
152 | + case 0xfc084002: | ||
153 | + case 0xfc084004: | ||
154 | + m5208_timer_write(&s->timer[1], addr & 0xf, value); | ||
155 | + return; | ||
156 | + default: | ||
157 | + cpu_abort(cpu_single_env, "m5208_sys_write: Bad offset 0x%x\n", | ||
158 | + (int)addr); | ||
159 | + break; | ||
160 | + } | ||
161 | +} | ||
162 | + | ||
163 | +static CPUReadMemoryFunc *m5208_sys_readfn[] = { | ||
164 | + m5208_sys_read, | ||
165 | + m5208_sys_read, | ||
166 | + m5208_sys_read | ||
167 | +}; | ||
168 | + | ||
169 | +static CPUWriteMemoryFunc *m5208_sys_writefn[] = { | ||
170 | + m5208_sys_write, | ||
171 | + m5208_sys_write, | ||
172 | + m5208_sys_write | ||
173 | +}; | ||
174 | + | ||
175 | +static void mcf5208_sys_init(qemu_irq *pic) | ||
176 | +{ | ||
177 | + int iomemtype; | ||
178 | + m5208_sys_state *s; | ||
179 | + QEMUBH *bh; | ||
180 | + int i; | ||
181 | + | ||
182 | + s = (m5208_sys_state *)qemu_mallocz(sizeof(m5208_sys_state)); | ||
183 | + iomemtype = cpu_register_io_memory(0, m5208_sys_readfn, | ||
184 | + m5208_sys_writefn, s); | ||
185 | + /* SDRAMC. */ | ||
186 | + cpu_register_physical_memory(0xfc0a8000, 0x00004000, iomemtype); | ||
187 | + /* Timers. */ | ||
188 | + for (i = 0; i < 2; i++) { | ||
189 | + bh = qemu_bh_new(m5208_timer_trigger, &s->timer[i]); | ||
190 | + s->timer[i].timer = ptimer_init(bh); | ||
191 | + cpu_register_physical_memory(0xfc080000 + 0x4000 * i, 0x00004000, | ||
192 | + iomemtype); | ||
193 | + s->timer[i].irq = pic[4 + i]; | ||
194 | + } | ||
195 | +} | ||
196 | + | ||
197 | +static void mcf5208evb_init(int ram_size, int vga_ram_size, int boot_device, | ||
198 | + DisplayState *ds, const char **fd_filename, int snapshot, | ||
199 | + const char *kernel_filename, const char *kernel_cmdline, | ||
200 | + const char *initrd_filename, const char *cpu_model) | ||
201 | +{ | ||
202 | + CPUState *env; | ||
203 | + int kernel_size; | ||
204 | + uint64_t elf_entry; | ||
205 | + target_ulong entry; | ||
206 | + qemu_irq *pic; | ||
207 | + | ||
208 | + env = cpu_init(); | ||
209 | + if (!cpu_model) | ||
210 | + cpu_model = "m5208"; | ||
211 | + if (cpu_m68k_set_model(env, cpu_model)) { | ||
212 | + cpu_abort(env, "Unable to find m68k CPU definition\n"); | ||
213 | + } | ||
214 | + | ||
215 | + /* Initialize CPU registers. */ | ||
216 | + env->vbr = 0; | ||
217 | + /* TODO: Configure BARs. */ | ||
218 | + | ||
219 | + /* DRAM at 0x20000000 */ | ||
220 | + cpu_register_physical_memory(0x40000000, ram_size, | ||
221 | + qemu_ram_alloc(ram_size) | IO_MEM_RAM); | ||
222 | + | ||
223 | + /* Internal SRAM. */ | ||
224 | + cpu_register_physical_memory(0x80000000, 16384, | ||
225 | + qemu_ram_alloc(16384) | IO_MEM_RAM); | ||
226 | + | ||
227 | + /* Internal peripherals. */ | ||
228 | + pic = mcf_intc_init(0xfc048000, env); | ||
229 | + | ||
230 | + mcf_uart_mm_init(0xfc060000, pic[26], serial_hds[0]); | ||
231 | + mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]); | ||
232 | + mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]); | ||
233 | + | ||
234 | + mcf5208_sys_init(pic); | ||
235 | + | ||
236 | + /* 0xfc000000 SCM. */ | ||
237 | + /* 0xfc004000 XBS. */ | ||
238 | + /* 0xfc008000 FlexBus CS. */ | ||
239 | + /* 0xfc030000 FEC. */ | ||
240 | + /* 0xfc040000 SCM + Power management. */ | ||
241 | + /* 0xfc044000 eDMA. */ | ||
242 | + /* 0xfc048000 INTC. */ | ||
243 | + /* 0xfc058000 I2C. */ | ||
244 | + /* 0xfc05c000 QSPI. */ | ||
245 | + /* 0xfc060000 UART0. */ | ||
246 | + /* 0xfc064000 UART0. */ | ||
247 | + /* 0xfc068000 UART0. */ | ||
248 | + /* 0xfc070000 DMA timers. */ | ||
249 | + /* 0xfc080000 PIT0. */ | ||
250 | + /* 0xfc084000 PIT1. */ | ||
251 | + /* 0xfc088000 EPORT. */ | ||
252 | + /* 0xfc08c000 Watchdog. */ | ||
253 | + /* 0xfc090000 clock module. */ | ||
254 | + /* 0xfc0a0000 CCM + reset. */ | ||
255 | + /* 0xfc0a4000 GPIO. */ | ||
256 | + /* 0xfc0a8000 SDRAM controller. */ | ||
257 | + | ||
258 | + /* Load kernel. */ | ||
259 | + if (!kernel_filename) { | ||
260 | + fprintf(stderr, "Kernel image must be specified\n"); | ||
261 | + exit(1); | ||
262 | + } | ||
263 | + | ||
264 | + kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL); | ||
265 | + entry = elf_entry; | ||
266 | + if (kernel_size < 0) { | ||
267 | + kernel_size = load_uboot(kernel_filename, &entry, NULL); | ||
268 | + } | ||
269 | + if (kernel_size < 0) { | ||
270 | + kernel_size = load_image(kernel_filename, phys_ram_base); | ||
271 | + entry = 0x20000000; | ||
272 | + } | ||
273 | + if (kernel_size < 0) { | ||
274 | + fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); | ||
275 | + exit(1); | ||
276 | + } | ||
277 | + | ||
278 | + env->pc = entry; | ||
279 | +} | ||
280 | + | ||
281 | +QEMUMachine mcf5208evb_machine = { | ||
282 | + "mcf5208evb", | ||
283 | + "MCF5206EVB", | ||
284 | + mcf5208evb_init, | ||
285 | +}; |
hw/mcf_intc.c
0 โ 100644
1 | +/* | ||
2 | + * ColdFire Interrupt Controller emulation. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 CodeSourcery. | ||
5 | + * | ||
6 | + * This code is licenced under the GPL | ||
7 | + */ | ||
8 | +#include "vl.h" | ||
9 | + | ||
10 | +typedef struct { | ||
11 | + uint64_t ipr; | ||
12 | + uint64_t imr; | ||
13 | + uint64_t ifr; | ||
14 | + uint64_t enabled; | ||
15 | + uint8_t icr[64]; | ||
16 | + CPUState *env; | ||
17 | + int active_vector; | ||
18 | +} mcf_intc_state; | ||
19 | + | ||
20 | +static void mcf_intc_update(mcf_intc_state *s) | ||
21 | +{ | ||
22 | + uint64_t active; | ||
23 | + int i; | ||
24 | + int best; | ||
25 | + int best_level; | ||
26 | + | ||
27 | + active = (s->ipr | s->ifr) & s->enabled & ~s->imr; | ||
28 | + best_level = 0; | ||
29 | + best = 64; | ||
30 | + if (active) { | ||
31 | + for (i = 0; i < 64; i++) { | ||
32 | + if ((active & 1) != 0 && s->icr[i] >= best_level) { | ||
33 | + best_level = s->icr[i]; | ||
34 | + best = i; | ||
35 | + } | ||
36 | + active >>= 1; | ||
37 | + } | ||
38 | + } | ||
39 | + s->active_vector = ((best == 64) ? 24 : (best + 64)); | ||
40 | + m68k_set_irq_level(s->env, best_level, s->active_vector); | ||
41 | +} | ||
42 | + | ||
43 | +static uint32_t mcf_intc_read(void *opaque, target_phys_addr_t addr) | ||
44 | +{ | ||
45 | + int offset; | ||
46 | + mcf_intc_state *s = (mcf_intc_state *)opaque; | ||
47 | + offset = addr & 0xff; | ||
48 | + if (offset >= 0x40 && offset < 0x80) { | ||
49 | + return s->icr[offset - 0x40]; | ||
50 | + } | ||
51 | + switch (offset) { | ||
52 | + case 0x00: | ||
53 | + return (uint32_t)(s->ipr >> 32); | ||
54 | + case 0x04: | ||
55 | + return (uint32_t)s->ipr; | ||
56 | + case 0x08: | ||
57 | + return (uint32_t)(s->imr >> 32); | ||
58 | + case 0x0c: | ||
59 | + return (uint32_t)s->imr; | ||
60 | + case 0x10: | ||
61 | + return (uint32_t)(s->ifr >> 32); | ||
62 | + case 0x14: | ||
63 | + return (uint32_t)s->ifr; | ||
64 | + case 0xe0: /* SWIACK. */ | ||
65 | + return s->active_vector; | ||
66 | + case 0xe1: case 0xe2: case 0xe3: case 0xe4: | ||
67 | + case 0xe5: case 0xe6: case 0xe7: | ||
68 | + /* LnIACK */ | ||
69 | + cpu_abort(cpu_single_env, "mcf_intc_read: LnIACK not implemented\n"); | ||
70 | + default: | ||
71 | + return 0; | ||
72 | + } | ||
73 | +} | ||
74 | + | ||
75 | +static void mcf_intc_write(void *opaque, target_phys_addr_t addr, uint32_t val) | ||
76 | +{ | ||
77 | + int offset; | ||
78 | + mcf_intc_state *s = (mcf_intc_state *)opaque; | ||
79 | + offset = addr & 0xff; | ||
80 | + if (offset >= 0x40 && offset < 0x80) { | ||
81 | + int n = offset - 0x40; | ||
82 | + s->icr[n] = val; | ||
83 | + if (val == 0) | ||
84 | + s->enabled &= ~(1ull << n); | ||
85 | + else | ||
86 | + s->enabled |= (1ull << n); | ||
87 | + mcf_intc_update(s); | ||
88 | + return; | ||
89 | + } | ||
90 | + switch (offset) { | ||
91 | + case 0x00: case 0x04: | ||
92 | + /* Ignore IPR writes. */ | ||
93 | + return; | ||
94 | + case 0x08: | ||
95 | + s->imr = (s->imr & 0xffffffff) | ((uint64_t)val << 32); | ||
96 | + break; | ||
97 | + case 0x0c: | ||
98 | + s->imr = (s->imr & 0xffffffff00000000ull) | (uint32_t)val; | ||
99 | + break; | ||
100 | + default: | ||
101 | + cpu_abort(cpu_single_env, "mcf_intc_write: Bad write offset %d\n", | ||
102 | + offset); | ||
103 | + break; | ||
104 | + } | ||
105 | + mcf_intc_update(s); | ||
106 | +} | ||
107 | + | ||
108 | +static void mcf_intc_set_irq(void *opaque, int irq, int level) | ||
109 | +{ | ||
110 | + mcf_intc_state *s = (mcf_intc_state *)opaque; | ||
111 | + if (irq >= 64) | ||
112 | + return; | ||
113 | + if (level) | ||
114 | + s->ipr |= 1ull << irq; | ||
115 | + else | ||
116 | + s->ipr &= ~(1ull << irq); | ||
117 | + mcf_intc_update(s); | ||
118 | +} | ||
119 | + | ||
120 | +static void mcf_intc_reset(mcf_intc_state *s) | ||
121 | +{ | ||
122 | + s->imr = ~0ull; | ||
123 | + s->ipr = 0; | ||
124 | + s->ifr = 0; | ||
125 | + s->enabled = 0; | ||
126 | + memset(s->icr, 0, 64); | ||
127 | + s->active_vector = 24; | ||
128 | +} | ||
129 | + | ||
130 | +static CPUReadMemoryFunc *mcf_intc_readfn[] = { | ||
131 | + mcf_intc_read, | ||
132 | + mcf_intc_read, | ||
133 | + mcf_intc_read | ||
134 | +}; | ||
135 | + | ||
136 | +static CPUWriteMemoryFunc *mcf_intc_writefn[] = { | ||
137 | + mcf_intc_write, | ||
138 | + mcf_intc_write, | ||
139 | + mcf_intc_write | ||
140 | +}; | ||
141 | + | ||
142 | +qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env) | ||
143 | +{ | ||
144 | + mcf_intc_state *s; | ||
145 | + int iomemtype; | ||
146 | + | ||
147 | + s = qemu_mallocz(sizeof(mcf_intc_state)); | ||
148 | + s->env = env; | ||
149 | + mcf_intc_reset(s); | ||
150 | + | ||
151 | + iomemtype = cpu_register_io_memory(0, mcf_intc_readfn, | ||
152 | + mcf_intc_writefn, s); | ||
153 | + cpu_register_physical_memory(base, 0x100, iomemtype); | ||
154 | + | ||
155 | + return qemu_allocate_irqs(mcf_intc_set_irq, s, 64); | ||
156 | +} |
hw/mcf_uart.c
0 โ 100644
1 | +/* | ||
2 | + * ColdFire UART emulation. | ||
3 | + * | ||
4 | + * Copyright (c) 2007 CodeSourcery. | ||
5 | + * | ||
6 | + * This code is licenced under the GPL | ||
7 | + */ | ||
8 | +#include "vl.h" | ||
9 | + | ||
10 | +typedef struct { | ||
11 | + uint8_t mr[2]; | ||
12 | + uint8_t sr; | ||
13 | + uint8_t isr; | ||
14 | + uint8_t imr; | ||
15 | + uint8_t bg1; | ||
16 | + uint8_t bg2; | ||
17 | + uint8_t fifo[4]; | ||
18 | + uint8_t tb; | ||
19 | + int current_mr; | ||
20 | + int fifo_len; | ||
21 | + int tx_enabled; | ||
22 | + int rx_enabled; | ||
23 | + qemu_irq irq; | ||
24 | + CharDriverState *chr; | ||
25 | +} mcf_uart_state; | ||
26 | + | ||
27 | +/* UART Status Register bits. */ | ||
28 | +#define MCF_UART_RxRDY 0x01 | ||
29 | +#define MCF_UART_FFULL 0x02 | ||
30 | +#define MCF_UART_TxRDY 0x04 | ||
31 | +#define MCF_UART_TxEMP 0x08 | ||
32 | +#define MCF_UART_OE 0x10 | ||
33 | +#define MCF_UART_PE 0x20 | ||
34 | +#define MCF_UART_FE 0x40 | ||
35 | +#define MCF_UART_RB 0x80 | ||
36 | + | ||
37 | +/* Interrupt flags. */ | ||
38 | +#define MCF_UART_TxINT 0x01 | ||
39 | +#define MCF_UART_RxINT 0x02 | ||
40 | +#define MCF_UART_DBINT 0x04 | ||
41 | +#define MCF_UART_COSINT 0x80 | ||
42 | + | ||
43 | +/* UMR1 flags. */ | ||
44 | +#define MCF_UART_BC0 0x01 | ||
45 | +#define MCF_UART_BC1 0x02 | ||
46 | +#define MCF_UART_PT 0x04 | ||
47 | +#define MCF_UART_PM0 0x08 | ||
48 | +#define MCF_UART_PM1 0x10 | ||
49 | +#define MCF_UART_ERR 0x20 | ||
50 | +#define MCF_UART_RxIRQ 0x40 | ||
51 | +#define MCF_UART_RxRTS 0x80 | ||
52 | + | ||
53 | +static void mcf_uart_update(mcf_uart_state *s) | ||
54 | +{ | ||
55 | + s->isr &= ~(MCF_UART_TxINT | MCF_UART_RxINT); | ||
56 | + if (s->sr & MCF_UART_TxRDY) | ||
57 | + s->isr |= MCF_UART_TxINT; | ||
58 | + if ((s->sr & ((s->mr[0] & MCF_UART_RxIRQ) | ||
59 | + ? MCF_UART_FFULL : MCF_UART_RxRDY)) != 0) | ||
60 | + s->isr |= MCF_UART_RxINT; | ||
61 | + | ||
62 | + qemu_set_irq(s->irq, (s->isr & s->imr) != 0); | ||
63 | +} | ||
64 | + | ||
65 | +uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr) | ||
66 | +{ | ||
67 | + mcf_uart_state *s = (mcf_uart_state *)opaque; | ||
68 | + switch (addr & 0x3f) { | ||
69 | + case 0x00: | ||
70 | + return s->mr[s->current_mr]; | ||
71 | + case 0x04: | ||
72 | + return s->sr; | ||
73 | + case 0x0c: | ||
74 | + { | ||
75 | + uint8_t val; | ||
76 | + int i; | ||
77 | + | ||
78 | + if (s->fifo_len == 0) | ||
79 | + return 0; | ||
80 | + | ||
81 | + val = s->fifo[0]; | ||
82 | + s->fifo_len--; | ||
83 | + for (i = 0; i < s->fifo_len; i++) | ||
84 | + s->fifo[i] = s->fifo[i + 1]; | ||
85 | + s->sr &= ~MCF_UART_FFULL; | ||
86 | + if (s->fifo_len == 0) | ||
87 | + s->sr &= ~MCF_UART_RxRDY; | ||
88 | + mcf_uart_update(s); | ||
89 | + return val; | ||
90 | + } | ||
91 | + case 0x10: | ||
92 | + /* TODO: Implement IPCR. */ | ||
93 | + return 0; | ||
94 | + case 0x14: | ||
95 | + return s->isr; | ||
96 | + case 0x18: | ||
97 | + return s->bg1; | ||
98 | + case 0x1c: | ||
99 | + return s->bg2; | ||
100 | + default: | ||
101 | + return 0; | ||
102 | + } | ||
103 | +} | ||
104 | + | ||
105 | +/* Update TxRDY flag and set data if present and enabled. */ | ||
106 | +static void mcf_uart_do_tx(mcf_uart_state *s) | ||
107 | +{ | ||
108 | + if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) { | ||
109 | + if (s->chr) | ||
110 | + qemu_chr_write(s->chr, (unsigned char *)&s->tb, 1); | ||
111 | + s->sr |= MCF_UART_TxEMP; | ||
112 | + } | ||
113 | + if (s->tx_enabled) { | ||
114 | + s->sr |= MCF_UART_TxRDY; | ||
115 | + } else { | ||
116 | + s->sr &= ~MCF_UART_TxRDY; | ||
117 | + } | ||
118 | +} | ||
119 | + | ||
120 | +static void mcf_do_command(mcf_uart_state *s, uint8_t cmd) | ||
121 | +{ | ||
122 | + /* Misc command. */ | ||
123 | + switch ((cmd >> 4) & 3) { | ||
124 | + case 0: /* No-op. */ | ||
125 | + break; | ||
126 | + case 1: /* Reset mode register pointer. */ | ||
127 | + s->current_mr = 0; | ||
128 | + break; | ||
129 | + case 2: /* Reset receiver. */ | ||
130 | + s->rx_enabled = 0; | ||
131 | + s->fifo_len = 0; | ||
132 | + s->sr &= ~(MCF_UART_RxRDY | MCF_UART_FFULL); | ||
133 | + break; | ||
134 | + case 3: /* Reset transmitter. */ | ||
135 | + s->tx_enabled = 0; | ||
136 | + s->sr |= MCF_UART_TxEMP; | ||
137 | + s->sr &= ~MCF_UART_TxRDY; | ||
138 | + break; | ||
139 | + case 4: /* Reset error status. */ | ||
140 | + break; | ||
141 | + case 5: /* Reset break-change interrupt. */ | ||
142 | + s->isr &= ~MCF_UART_DBINT; | ||
143 | + break; | ||
144 | + case 6: /* Start break. */ | ||
145 | + case 7: /* Stop break. */ | ||
146 | + break; | ||
147 | + } | ||
148 | + | ||
149 | + /* Transmitter command. */ | ||
150 | + switch ((cmd >> 2) & 3) { | ||
151 | + case 0: /* No-op. */ | ||
152 | + break; | ||
153 | + case 1: /* Enable. */ | ||
154 | + s->tx_enabled = 1; | ||
155 | + mcf_uart_do_tx(s); | ||
156 | + break; | ||
157 | + case 2: /* Disable. */ | ||
158 | + s->tx_enabled = 0; | ||
159 | + mcf_uart_do_tx(s); | ||
160 | + break; | ||
161 | + case 3: /* Reserved. */ | ||
162 | + fprintf(stderr, "mcf_uart: Bad TX command\n"); | ||
163 | + break; | ||
164 | + } | ||
165 | + | ||
166 | + /* Receiver command. */ | ||
167 | + switch (cmd & 3) { | ||
168 | + case 0: /* No-op. */ | ||
169 | + break; | ||
170 | + case 1: /* Enable. */ | ||
171 | + s->rx_enabled = 1; | ||
172 | + break; | ||
173 | + case 2: | ||
174 | + s->rx_enabled = 0; | ||
175 | + break; | ||
176 | + case 3: /* Reserved. */ | ||
177 | + fprintf(stderr, "mcf_uart: Bad RX command\n"); | ||
178 | + break; | ||
179 | + } | ||
180 | +} | ||
181 | + | ||
182 | +void mcf_uart_write(void *opaque, target_phys_addr_t addr, uint32_t val) | ||
183 | +{ | ||
184 | + mcf_uart_state *s = (mcf_uart_state *)opaque; | ||
185 | + switch (addr & 0x3f) { | ||
186 | + case 0x00: | ||
187 | + s->mr[s->current_mr] = val; | ||
188 | + s->current_mr = 1; | ||
189 | + break; | ||
190 | + case 0x04: | ||
191 | + /* CSR is ignored. */ | ||
192 | + break; | ||
193 | + case 0x08: /* Command Register. */ | ||
194 | + mcf_do_command(s, val); | ||
195 | + break; | ||
196 | + case 0x0c: /* Transmit Buffer. */ | ||
197 | + s->sr &= ~MCF_UART_TxEMP; | ||
198 | + s->tb = val; | ||
199 | + mcf_uart_do_tx(s); | ||
200 | + break; | ||
201 | + case 0x10: | ||
202 | + /* ACR is ignored. */ | ||
203 | + break; | ||
204 | + case 0x14: | ||
205 | + s->imr = val; | ||
206 | + break; | ||
207 | + default: | ||
208 | + break; | ||
209 | + } | ||
210 | + mcf_uart_update(s); | ||
211 | +} | ||
212 | + | ||
213 | +static void mcf_uart_reset(mcf_uart_state *s) | ||
214 | +{ | ||
215 | + s->fifo_len = 0; | ||
216 | + s->mr[0] = 0; | ||
217 | + s->mr[1] = 0; | ||
218 | + s->sr = MCF_UART_TxEMP; | ||
219 | + s->tx_enabled = 0; | ||
220 | + s->rx_enabled = 0; | ||
221 | + s->isr = 0; | ||
222 | + s->imr = 0; | ||
223 | +} | ||
224 | + | ||
225 | +static void mcf_uart_push_byte(mcf_uart_state *s, uint8_t data) | ||
226 | +{ | ||
227 | + /* Break events overwrite the last byte if the fifo is full. */ | ||
228 | + if (s->fifo_len == 4) | ||
229 | + s->fifo_len--; | ||
230 | + | ||
231 | + s->fifo[s->fifo_len] = data; | ||
232 | + s->fifo_len++; | ||
233 | + s->sr |= MCF_UART_RxRDY; | ||
234 | + if (s->fifo_len == 4) | ||
235 | + s->sr |= MCF_UART_FFULL; | ||
236 | + | ||
237 | + mcf_uart_update(s); | ||
238 | +} | ||
239 | + | ||
240 | +static void mcf_uart_event(void *opaque, int event) | ||
241 | +{ | ||
242 | + mcf_uart_state *s = (mcf_uart_state *)opaque; | ||
243 | + | ||
244 | + switch (event) { | ||
245 | + case CHR_EVENT_BREAK: | ||
246 | + s->isr |= MCF_UART_DBINT; | ||
247 | + mcf_uart_push_byte(s, 0); | ||
248 | + break; | ||
249 | + default: | ||
250 | + break; | ||
251 | + } | ||
252 | +} | ||
253 | + | ||
254 | +static int mcf_uart_can_receive(void *opaque) | ||
255 | +{ | ||
256 | + mcf_uart_state *s = (mcf_uart_state *)opaque; | ||
257 | + | ||
258 | + return s->rx_enabled && (s->sr & MCF_UART_FFULL) == 0; | ||
259 | +} | ||
260 | + | ||
261 | +static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size) | ||
262 | +{ | ||
263 | + mcf_uart_state *s = (mcf_uart_state *)opaque; | ||
264 | + | ||
265 | + mcf_uart_push_byte(s, buf[0]); | ||
266 | +} | ||
267 | + | ||
268 | +void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) | ||
269 | +{ | ||
270 | + mcf_uart_state *s; | ||
271 | + | ||
272 | + s = qemu_mallocz(sizeof(mcf_uart_state)); | ||
273 | + s->chr = chr; | ||
274 | + s->irq = irq; | ||
275 | + if (chr) { | ||
276 | + qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive, | ||
277 | + mcf_uart_event, s); | ||
278 | + } | ||
279 | + mcf_uart_reset(s); | ||
280 | + return s; | ||
281 | +} | ||
282 | + | ||
283 | + | ||
284 | +static CPUReadMemoryFunc *mcf_uart_readfn[] = { | ||
285 | + mcf_uart_read, | ||
286 | + mcf_uart_read, | ||
287 | + mcf_uart_read | ||
288 | +}; | ||
289 | + | ||
290 | +static CPUWriteMemoryFunc *mcf_uart_writefn[] = { | ||
291 | + mcf_uart_write, | ||
292 | + mcf_uart_write, | ||
293 | + mcf_uart_write | ||
294 | +}; | ||
295 | + | ||
296 | +void mcf_uart_mm_init(target_phys_addr_t base, qemu_irq irq, | ||
297 | + CharDriverState *chr) | ||
298 | +{ | ||
299 | + mcf_uart_state *s; | ||
300 | + int iomemtype; | ||
301 | + | ||
302 | + s = mcf_uart_init(irq, chr); | ||
303 | + iomemtype = cpu_register_io_memory(0, mcf_uart_readfn, | ||
304 | + mcf_uart_writefn, s); | ||
305 | + cpu_register_physical_memory(base, 0x40, iomemtype); | ||
306 | +} |
target-m68k/cpu.h
@@ -59,6 +59,10 @@ typedef struct CPUM68KState { | @@ -59,6 +59,10 @@ typedef struct CPUM68KState { | ||
59 | uint32_t pc; | 59 | uint32_t pc; |
60 | uint32_t sr; | 60 | uint32_t sr; |
61 | 61 | ||
62 | + /* SSP and USP. The current_sp is stored in aregs[7], the other here. */ | ||
63 | + int current_sp; | ||
64 | + uint32_t sp[2]; | ||
65 | + | ||
62 | /* Condition flags. */ | 66 | /* Condition flags. */ |
63 | uint32_t cc_op; | 67 | uint32_t cc_op; |
64 | uint32_t cc_dest; | 68 | uint32_t cc_dest; |
@@ -92,6 +96,7 @@ typedef struct CPUM68KState { | @@ -92,6 +96,7 @@ typedef struct CPUM68KState { | ||
92 | uint32_t vbr; | 96 | uint32_t vbr; |
93 | uint32_t mbar; | 97 | uint32_t mbar; |
94 | uint32_t rambar0; | 98 | uint32_t rambar0; |
99 | + uint32_t cacr; | ||
95 | 100 | ||
96 | uint32_t features; | 101 | uint32_t features; |
97 | 102 | ||
@@ -151,6 +156,12 @@ enum { | @@ -151,6 +156,12 @@ enum { | ||
151 | #define SR_S 0x2000 | 156 | #define SR_S 0x2000 |
152 | #define SR_T 0x8000 | 157 | #define SR_T 0x8000 |
153 | 158 | ||
159 | +#define M68K_SSP 0 | ||
160 | +#define M68K_USP 1 | ||
161 | + | ||
162 | +/* CACR fields are implementation defined, but some bits are common. */ | ||
163 | +#define M68K_CACR_EUSP 0x10 | ||
164 | + | ||
154 | #define MACSR_PAV0 0x100 | 165 | #define MACSR_PAV0 0x100 |
155 | #define MACSR_OMC 0x080 | 166 | #define MACSR_OMC 0x080 |
156 | #define MACSR_SU 0x040 | 167 | #define MACSR_SU 0x040 |
@@ -167,6 +178,7 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name); | @@ -167,6 +178,7 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name); | ||
167 | 178 | ||
168 | void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector); | 179 | void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector); |
169 | void m68k_set_macsr(CPUM68KState *env, uint32_t val); | 180 | void m68k_set_macsr(CPUM68KState *env, uint32_t val); |
181 | +void m68k_switch_sp(CPUM68KState *env); | ||
170 | 182 | ||
171 | #define M68K_FPCR_PREC (1 << 6) | 183 | #define M68K_FPCR_PREC (1 << 6) |
172 | 184 | ||
@@ -179,6 +191,7 @@ enum m68k_features { | @@ -179,6 +191,7 @@ enum m68k_features { | ||
179 | M68K_FEATURE_CF_FPU, | 191 | M68K_FEATURE_CF_FPU, |
180 | M68K_FEATURE_CF_MAC, | 192 | M68K_FEATURE_CF_MAC, |
181 | M68K_FEATURE_CF_EMAC, | 193 | M68K_FEATURE_CF_EMAC, |
194 | + M68K_FEATURE_USP, | ||
182 | M68K_FEATURE_EXT_FULL, /* 68020+ full extension word. */ | 195 | M68K_FEATURE_EXT_FULL, /* 68020+ full extension word. */ |
183 | M68K_FEATURE_WORD_INDEX /* word sized address index registers. */ | 196 | M68K_FEATURE_WORD_INDEX /* word sized address index registers. */ |
184 | }; | 197 | }; |
target-m68k/helper.c
@@ -28,6 +28,7 @@ | @@ -28,6 +28,7 @@ | ||
28 | 28 | ||
29 | enum m68k_cpuid { | 29 | enum m68k_cpuid { |
30 | M68K_CPUID_M5206, | 30 | M68K_CPUID_M5206, |
31 | + M68K_CPUID_M5208, | ||
31 | M68K_CPUID_CFV4E, | 32 | M68K_CPUID_CFV4E, |
32 | M68K_CPUID_ANY, | 33 | M68K_CPUID_ANY, |
33 | }; | 34 | }; |
@@ -39,6 +40,7 @@ struct m68k_def_t { | @@ -39,6 +40,7 @@ struct m68k_def_t { | ||
39 | 40 | ||
40 | static m68k_def_t m68k_cpu_defs[] = { | 41 | static m68k_def_t m68k_cpu_defs[] = { |
41 | {"m5206", M68K_CPUID_M5206}, | 42 | {"m5206", M68K_CPUID_M5206}, |
43 | + {"m5208", M68K_CPUID_M5208}, | ||
42 | {"cfv4e", M68K_CPUID_CFV4E}, | 44 | {"cfv4e", M68K_CPUID_CFV4E}, |
43 | {"any", M68K_CPUID_ANY}, | 45 | {"any", M68K_CPUID_ANY}, |
44 | {NULL, 0}, | 46 | {NULL, 0}, |
@@ -64,12 +66,18 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name) | @@ -64,12 +66,18 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name) | ||
64 | case M68K_CPUID_M5206: | 66 | case M68K_CPUID_M5206: |
65 | m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); | 67 | m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); |
66 | break; | 68 | break; |
69 | + case M68K_CPUID_M5208: | ||
70 | + m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); | ||
71 | + m68k_set_feature(env, M68K_FEATURE_CF_EMAC); | ||
72 | + m68k_set_feature(env, M68K_FEATURE_USP); | ||
73 | + break; | ||
67 | case M68K_CPUID_CFV4E: | 74 | case M68K_CPUID_CFV4E: |
68 | m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); | 75 | m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); |
69 | m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); | 76 | m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); |
70 | m68k_set_feature(env, M68K_FEATURE_CF_ISA_C); | 77 | m68k_set_feature(env, M68K_FEATURE_CF_ISA_C); |
71 | m68k_set_feature(env, M68K_FEATURE_CF_FPU); | 78 | m68k_set_feature(env, M68K_FEATURE_CF_FPU); |
72 | m68k_set_feature(env, M68K_FEATURE_CF_EMAC); | 79 | m68k_set_feature(env, M68K_FEATURE_CF_EMAC); |
80 | + m68k_set_feature(env, M68K_FEATURE_USP); | ||
73 | break; | 81 | break; |
74 | case M68K_CPUID_ANY: | 82 | case M68K_CPUID_ANY: |
75 | m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); | 83 | m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); |
@@ -79,6 +87,7 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name) | @@ -79,6 +87,7 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name) | ||
79 | /* MAC and EMAC are mututally exclusive, so pick EMAC. | 87 | /* MAC and EMAC are mututally exclusive, so pick EMAC. |
80 | It's mostly backwards compatible. */ | 88 | It's mostly backwards compatible. */ |
81 | m68k_set_feature(env, M68K_FEATURE_CF_EMAC); | 89 | m68k_set_feature(env, M68K_FEATURE_CF_EMAC); |
90 | + m68k_set_feature(env, M68K_FEATURE_USP); | ||
82 | m68k_set_feature(env, M68K_FEATURE_EXT_FULL); | 91 | m68k_set_feature(env, M68K_FEATURE_EXT_FULL); |
83 | break; | 92 | break; |
84 | } | 93 | } |
@@ -215,7 +224,11 @@ void helper_movec(CPUM68KState *env, int reg, uint32_t val) | @@ -215,7 +224,11 @@ void helper_movec(CPUM68KState *env, int reg, uint32_t val) | ||
215 | { | 224 | { |
216 | switch (reg) { | 225 | switch (reg) { |
217 | case 0x02: /* CACR */ | 226 | case 0x02: /* CACR */ |
218 | - /* Ignored. */ | 227 | + env->cacr = val; |
228 | + m68k_switch_sp(env); | ||
229 | + break; | ||
230 | + case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */ | ||
231 | + /* TODO: Implement Access Control Registers. */ | ||
219 | break; | 232 | break; |
220 | case 0x801: /* VBR */ | 233 | case 0x801: /* VBR */ |
221 | env->vbr = val; | 234 | env->vbr = val; |
@@ -261,6 +274,17 @@ void m68k_set_macsr(CPUM68KState *env, uint32_t val) | @@ -261,6 +274,17 @@ void m68k_set_macsr(CPUM68KState *env, uint32_t val) | ||
261 | env->macsr = val; | 274 | env->macsr = val; |
262 | } | 275 | } |
263 | 276 | ||
277 | +void m68k_switch_sp(CPUM68KState *env) | ||
278 | +{ | ||
279 | + int new_sp; | ||
280 | + | ||
281 | + env->sp[env->current_sp] = env->aregs[7]; | ||
282 | + new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP) | ||
283 | + ? M68K_SSP : M68K_USP; | ||
284 | + env->aregs[7] = env->sp[new_sp]; | ||
285 | + env->current_sp = new_sp; | ||
286 | +} | ||
287 | + | ||
264 | /* MMU */ | 288 | /* MMU */ |
265 | 289 | ||
266 | /* TODO: This will need fixing once the MMU is implemented. */ | 290 | /* TODO: This will need fixing once the MMU is implemented. */ |
target-m68k/op.c
@@ -478,6 +478,13 @@ OP(fp_result) | @@ -478,6 +478,13 @@ OP(fp_result) | ||
478 | FORCE_RET(); | 478 | FORCE_RET(); |
479 | } | 479 | } |
480 | 480 | ||
481 | +OP(set_sr) | ||
482 | +{ | ||
483 | + env->sr = get_op(PARAM1); | ||
484 | + m68k_switch_sp(env); | ||
485 | + FORCE_RET(); | ||
486 | +} | ||
487 | + | ||
481 | OP(jmp) | 488 | OP(jmp) |
482 | { | 489 | { |
483 | GOTO_LABEL_PARAM(1); | 490 | GOTO_LABEL_PARAM(1); |
target-m68k/op_helper.c
@@ -87,6 +87,7 @@ static void do_rte(void) | @@ -87,6 +87,7 @@ static void do_rte(void) | ||
87 | env->pc = ldl_kernel(sp + 4); | 87 | env->pc = ldl_kernel(sp + 4); |
88 | sp |= (fmt >> 28) & 3; | 88 | sp |= (fmt >> 28) & 3; |
89 | env->sr = fmt & 0xffff; | 89 | env->sr = fmt & 0xffff; |
90 | + m68k_switch_sp(env); | ||
90 | env->aregs[7] = sp + 8; | 91 | env->aregs[7] = sp + 8; |
91 | } | 92 | } |
92 | 93 | ||
@@ -128,9 +129,6 @@ void do_interrupt(int is_hw) | @@ -128,9 +129,6 @@ void do_interrupt(int is_hw) | ||
128 | } | 129 | } |
129 | } | 130 | } |
130 | 131 | ||
131 | - /* TODO: Implement USP. */ | ||
132 | - sp = env->aregs[7]; | ||
133 | - | ||
134 | vector = env->exception_index << 2; | 132 | vector = env->exception_index << 2; |
135 | 133 | ||
136 | fmt |= 0x40000000; | 134 | fmt |= 0x40000000; |
@@ -138,6 +136,15 @@ void do_interrupt(int is_hw) | @@ -138,6 +136,15 @@ void do_interrupt(int is_hw) | ||
138 | fmt |= vector << 16; | 136 | fmt |= vector << 16; |
139 | fmt |= env->sr; | 137 | fmt |= env->sr; |
140 | 138 | ||
139 | + env->sr |= SR_S; | ||
140 | + if (is_hw) { | ||
141 | + env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT); | ||
142 | + env->sr &= ~SR_M; | ||
143 | + } | ||
144 | + m68k_switch_sp(env); | ||
145 | + | ||
146 | + sp = env->aregs[7]; | ||
147 | + | ||
141 | /* ??? This could cause MMU faults. */ | 148 | /* ??? This could cause MMU faults. */ |
142 | sp &= ~3; | 149 | sp &= ~3; |
143 | sp -= 4; | 150 | sp -= 4; |
@@ -145,11 +152,6 @@ void do_interrupt(int is_hw) | @@ -145,11 +152,6 @@ void do_interrupt(int is_hw) | ||
145 | sp -= 4; | 152 | sp -= 4; |
146 | stl_kernel(sp, fmt); | 153 | stl_kernel(sp, fmt); |
147 | env->aregs[7] = sp; | 154 | env->aregs[7] = sp; |
148 | - env->sr |= SR_S; | ||
149 | - if (is_hw) { | ||
150 | - env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT); | ||
151 | - env->sr &= ~SR_M; | ||
152 | - } | ||
153 | /* Jump to vector. */ | 155 | /* Jump to vector. */ |
154 | env->pc = ldl_kernel(env->vbr + vector); | 156 | env->pc = ldl_kernel(env->vbr + vector); |
155 | } | 157 | } |
target-m68k/translate.c
@@ -1345,7 +1345,7 @@ static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only) | @@ -1345,7 +1345,7 @@ static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only) | ||
1345 | gen_op_logic_cc(gen_im32(val & 0xf)); | 1345 | gen_op_logic_cc(gen_im32(val & 0xf)); |
1346 | gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4)); | 1346 | gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4)); |
1347 | if (!ccr_only) { | 1347 | if (!ccr_only) { |
1348 | - gen_op_mov32(QREG_SR, gen_im32(val & 0xff00)); | 1348 | + gen_op_set_sr(gen_im32(val & 0xff00)); |
1349 | } | 1349 | } |
1350 | } | 1350 | } |
1351 | 1351 | ||
@@ -1365,7 +1365,7 @@ static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only) | @@ -1365,7 +1365,7 @@ static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only) | ||
1365 | gen_op_and32(src1, src1, gen_im32(1)); | 1365 | gen_op_and32(src1, src1, gen_im32(1)); |
1366 | gen_op_update_xflag_tst(src1); | 1366 | gen_op_update_xflag_tst(src1); |
1367 | if (!ccr_only) { | 1367 | if (!ccr_only) { |
1368 | - gen_op_and32(QREG_SR, reg, gen_im32(0xff00)); | 1368 | + gen_op_set_sr(reg); |
1369 | } | 1369 | } |
1370 | } | 1370 | } |
1371 | else if ((insn & 0x3f) == 0x3c) | 1371 | else if ((insn & 0x3f) == 0x3c) |
@@ -2797,8 +2797,8 @@ void register_m68k_insns (CPUM68KState *env) | @@ -2797,8 +2797,8 @@ void register_m68k_insns (CPUM68KState *env) | ||
2797 | INSN(trap, 4e40, fff0, CF_ISA_A); | 2797 | INSN(trap, 4e40, fff0, CF_ISA_A); |
2798 | INSN(link, 4e50, fff8, CF_ISA_A); | 2798 | INSN(link, 4e50, fff8, CF_ISA_A); |
2799 | INSN(unlk, 4e58, fff8, CF_ISA_A); | 2799 | INSN(unlk, 4e58, fff8, CF_ISA_A); |
2800 | - INSN(move_to_usp, 4e60, fff8, CF_ISA_B); | ||
2801 | - INSN(move_from_usp, 4e68, fff8, CF_ISA_B); | 2800 | + INSN(move_to_usp, 4e60, fff8, USP); |
2801 | + INSN(move_from_usp, 4e68, fff8, USP); | ||
2802 | INSN(nop, 4e71, ffff, CF_ISA_A); | 2802 | INSN(nop, 4e71, ffff, CF_ISA_A); |
2803 | INSN(stop, 4e72, ffff, CF_ISA_A); | 2803 | INSN(stop, 4e72, ffff, CF_ISA_A); |
2804 | INSN(rte, 4e73, ffff, CF_ISA_A); | 2804 | INSN(rte, 4e73, ffff, CF_ISA_A); |
@@ -3261,6 +3261,7 @@ void cpu_reset(CPUM68KState *env) | @@ -3261,6 +3261,7 @@ void cpu_reset(CPUM68KState *env) | ||
3261 | #if !defined (CONFIG_USER_ONLY) | 3261 | #if !defined (CONFIG_USER_ONLY) |
3262 | env->sr = 0x2700; | 3262 | env->sr = 0x2700; |
3263 | #endif | 3263 | #endif |
3264 | + m68k_switch_sp(env); | ||
3264 | /* ??? FP regs should be initialized to NaN. */ | 3265 | /* ??? FP regs should be initialized to NaN. */ |
3265 | env->cc_op = CC_OP_FLAGS; | 3266 | env->cc_op = CC_OP_FLAGS; |
3266 | /* TODO: We should set PC from the interrupt vector. */ | 3267 | /* TODO: We should set PC from the interrupt vector. */ |
vl.c
@@ -6972,6 +6972,7 @@ void register_machines(void) | @@ -6972,6 +6972,7 @@ void register_machines(void) | ||
6972 | #elif defined(TARGET_ALPHA) | 6972 | #elif defined(TARGET_ALPHA) |
6973 | /* XXX: TODO */ | 6973 | /* XXX: TODO */ |
6974 | #elif defined(TARGET_M68K) | 6974 | #elif defined(TARGET_M68K) |
6975 | + qemu_register_machine(&mcf5208evb_machine); | ||
6975 | qemu_register_machine(&an5206_machine); | 6976 | qemu_register_machine(&an5206_machine); |
6976 | #else | 6977 | #else |
6977 | #error unsupported CPU | 6978 | #error unsupported CPU |
vl.h
@@ -1593,12 +1593,25 @@ void qemu_get_ptimer(QEMUFile *f, ptimer_state *s); | @@ -1593,12 +1593,25 @@ void qemu_get_ptimer(QEMUFile *f, ptimer_state *s); | ||
1593 | 1593 | ||
1594 | #include "hw/pxa.h" | 1594 | #include "hw/pxa.h" |
1595 | 1595 | ||
1596 | +/* mcf_uart.c */ | ||
1597 | +uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr); | ||
1598 | +void mcf_uart_write(void *opaque, target_phys_addr_t addr, uint32_t val); | ||
1599 | +void *mcf_uart_init(qemu_irq irq, CharDriverState *chr); | ||
1600 | +void mcf_uart_mm_init(target_phys_addr_t base, qemu_irq irq, | ||
1601 | + CharDriverState *chr); | ||
1602 | + | ||
1603 | +/* mcf_intc.c */ | ||
1604 | +qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env); | ||
1605 | + | ||
1596 | /* mcf5206.c */ | 1606 | /* mcf5206.c */ |
1597 | qemu_irq *mcf5206_init(uint32_t base, CPUState *env); | 1607 | qemu_irq *mcf5206_init(uint32_t base, CPUState *env); |
1598 | 1608 | ||
1599 | /* an5206.c */ | 1609 | /* an5206.c */ |
1600 | extern QEMUMachine an5206_machine; | 1610 | extern QEMUMachine an5206_machine; |
1601 | 1611 | ||
1612 | +/* mcf5208.c */ | ||
1613 | +extern QEMUMachine mcf5208evb_machine; | ||
1614 | + | ||
1602 | #include "gdbstub.h" | 1615 | #include "gdbstub.h" |
1603 | 1616 | ||
1604 | #endif /* defined(QEMU_TOOL) */ | 1617 | #endif /* defined(QEMU_TOOL) */ |