2 * ColdFire Interrupt Controller emulation.
4 * Copyright (c) 2007 CodeSourcery.
6 * This code is licenced under the GPL
20 static void mcf_intc_update(mcf_intc_state
*s
)
27 active
= (s
->ipr
| s
->ifr
) & s
->enabled
& ~s
->imr
;
31 for (i
= 0; i
< 64; i
++) {
32 if ((active
& 1) != 0 && s
->icr
[i
] >= best_level
) {
33 best_level
= s
->icr
[i
];
39 s
->active_vector
= ((best
== 64) ? 24 : (best
+ 64));
40 m68k_set_irq_level(s
->env
, best_level
, s
->active_vector
);
43 static uint32_t mcf_intc_read(void *opaque
, target_phys_addr_t addr
)
46 mcf_intc_state
*s
= (mcf_intc_state
*)opaque
;
48 if (offset
>= 0x40 && offset
< 0x80) {
49 return s
->icr
[offset
- 0x40];
53 return (uint32_t)(s
->ipr
>> 32);
55 return (uint32_t)s
->ipr
;
57 return (uint32_t)(s
->imr
>> 32);
59 return (uint32_t)s
->imr
;
61 return (uint32_t)(s
->ifr
>> 32);
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:
69 cpu_abort(cpu_single_env
, "mcf_intc_read: LnIACK not implemented\n");
75 static void mcf_intc_write(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
78 mcf_intc_state
*s
= (mcf_intc_state
*)opaque
;
80 if (offset
>= 0x40 && offset
< 0x80) {
81 int n
= offset
- 0x40;
84 s
->enabled
&= ~(1ull << n
);
86 s
->enabled
|= (1ull << n
);
92 /* Ignore IPR writes. */
95 s
->imr
= (s
->imr
& 0xffffffff) | ((uint64_t)val
<< 32);
98 s
->imr
= (s
->imr
& 0xffffffff00000000ull
) | (uint32_t)val
;
101 cpu_abort(cpu_single_env
, "mcf_intc_write: Bad write offset %d\n",
108 static void mcf_intc_set_irq(void *opaque
, int irq
, int level
)
110 mcf_intc_state
*s
= (mcf_intc_state
*)opaque
;
114 s
->ipr
|= 1ull << irq
;
116 s
->ipr
&= ~(1ull << irq
);
120 static void mcf_intc_reset(mcf_intc_state
*s
)
126 memset(s
->icr
, 0, 64);
127 s
->active_vector
= 24;
130 static CPUReadMemoryFunc
*mcf_intc_readfn
[] = {
136 static CPUWriteMemoryFunc
*mcf_intc_writefn
[] = {
142 qemu_irq
*mcf_intc_init(target_phys_addr_t base
, CPUState
*env
)
147 s
= qemu_mallocz(sizeof(mcf_intc_state
));
151 iomemtype
= cpu_register_io_memory(0, mcf_intc_readfn
,
152 mcf_intc_writefn
, s
);
153 cpu_register_physical_memory(base
, 0x100, iomemtype
);
155 return qemu_allocate_irqs(mcf_intc_set_irq
, s
, 64);