2 * ColdFire Interrupt Controller emulation.
4 * Copyright (c) 2007 CodeSourcery.
6 * This code is licensed under the GPL
21 static void mcf_intc_update(mcf_intc_state
*s
)
28 active
= (s
->ipr
| s
->ifr
) & s
->enabled
& ~s
->imr
;
32 for (i
= 0; i
< 64; i
++) {
33 if ((active
& 1) != 0 && s
->icr
[i
] >= best_level
) {
34 best_level
= s
->icr
[i
];
40 s
->active_vector
= ((best
== 64) ? 24 : (best
+ 64));
41 m68k_set_irq_level(s
->env
, best_level
, s
->active_vector
);
44 static uint32_t mcf_intc_read(void *opaque
, target_phys_addr_t addr
)
47 mcf_intc_state
*s
= (mcf_intc_state
*)opaque
;
49 if (offset
>= 0x40 && offset
< 0x80) {
50 return s
->icr
[offset
- 0x40];
54 return (uint32_t)(s
->ipr
>> 32);
56 return (uint32_t)s
->ipr
;
58 return (uint32_t)(s
->imr
>> 32);
60 return (uint32_t)s
->imr
;
62 return (uint32_t)(s
->ifr
>> 32);
64 return (uint32_t)s
->ifr
;
65 case 0xe0: /* SWIACK. */
66 return s
->active_vector
;
67 case 0xe1: case 0xe2: case 0xe3: case 0xe4:
68 case 0xe5: case 0xe6: case 0xe7:
70 hw_error("mcf_intc_read: LnIACK not implemented\n");
76 static void mcf_intc_write(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
79 mcf_intc_state
*s
= (mcf_intc_state
*)opaque
;
81 if (offset
>= 0x40 && offset
< 0x80) {
82 int n
= offset
- 0x40;
85 s
->enabled
&= ~(1ull << n
);
87 s
->enabled
|= (1ull << n
);
93 /* Ignore IPR writes. */
96 s
->imr
= (s
->imr
& 0xffffffff) | ((uint64_t)val
<< 32);
99 s
->imr
= (s
->imr
& 0xffffffff00000000ull
) | (uint32_t)val
;
102 hw_error("mcf_intc_write: Bad write offset %d\n", offset
);
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
* const mcf_intc_readfn
[] = {
136 static CPUWriteMemoryFunc
* const 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(mcf_intc_readfn
,
153 DEVICE_NATIVE_ENDIAN
);
154 cpu_register_physical_memory(base
, 0x100, iomemtype
);
156 return qemu_allocate_irqs(mcf_intc_set_irq
, s
, 64);