|
|
1.1 root 1: /*
2: * ColdFire Interrupt Controller emulation.
3: *
4: * Copyright (c) 2007 CodeSourcery.
5: *
1.1.1.5 root 6: * This code is licensed under the GPL
1.1 root 7: */
8: #include "hw.h"
9: #include "mcf.h"
1.1.1.7 ! root 10: #include "exec-memory.h"
1.1 root 11:
12: typedef struct {
1.1.1.7 ! root 13: MemoryRegion iomem;
1.1 root 14: uint64_t ipr;
15: uint64_t imr;
16: uint64_t ifr;
17: uint64_t enabled;
18: uint8_t icr[64];
1.1.1.7 ! root 19: CPUM68KState *env;
1.1 root 20: int active_vector;
21: } mcf_intc_state;
22:
23: static void mcf_intc_update(mcf_intc_state *s)
24: {
25: uint64_t active;
26: int i;
27: int best;
28: int best_level;
29:
30: active = (s->ipr | s->ifr) & s->enabled & ~s->imr;
31: best_level = 0;
32: best = 64;
33: if (active) {
34: for (i = 0; i < 64; i++) {
35: if ((active & 1) != 0 && s->icr[i] >= best_level) {
36: best_level = s->icr[i];
37: best = i;
38: }
39: active >>= 1;
40: }
41: }
42: s->active_vector = ((best == 64) ? 24 : (best + 64));
43: m68k_set_irq_level(s->env, best_level, s->active_vector);
44: }
45:
1.1.1.7 ! root 46: static uint64_t mcf_intc_read(void *opaque, target_phys_addr_t addr,
! 47: unsigned size)
1.1 root 48: {
49: int offset;
50: mcf_intc_state *s = (mcf_intc_state *)opaque;
51: offset = addr & 0xff;
52: if (offset >= 0x40 && offset < 0x80) {
53: return s->icr[offset - 0x40];
54: }
55: switch (offset) {
56: case 0x00:
57: return (uint32_t)(s->ipr >> 32);
58: case 0x04:
59: return (uint32_t)s->ipr;
60: case 0x08:
61: return (uint32_t)(s->imr >> 32);
62: case 0x0c:
63: return (uint32_t)s->imr;
64: case 0x10:
65: return (uint32_t)(s->ifr >> 32);
66: case 0x14:
67: return (uint32_t)s->ifr;
68: case 0xe0: /* SWIACK. */
69: return s->active_vector;
70: case 0xe1: case 0xe2: case 0xe3: case 0xe4:
71: case 0xe5: case 0xe6: case 0xe7:
72: /* LnIACK */
1.1.1.2 root 73: hw_error("mcf_intc_read: LnIACK not implemented\n");
1.1 root 74: default:
75: return 0;
76: }
77: }
78:
1.1.1.7 ! root 79: static void mcf_intc_write(void *opaque, target_phys_addr_t addr,
! 80: uint64_t val, unsigned size)
1.1 root 81: {
82: int offset;
83: mcf_intc_state *s = (mcf_intc_state *)opaque;
84: offset = addr & 0xff;
85: if (offset >= 0x40 && offset < 0x80) {
86: int n = offset - 0x40;
87: s->icr[n] = val;
88: if (val == 0)
89: s->enabled &= ~(1ull << n);
90: else
91: s->enabled |= (1ull << n);
92: mcf_intc_update(s);
93: return;
94: }
95: switch (offset) {
96: case 0x00: case 0x04:
97: /* Ignore IPR writes. */
98: return;
99: case 0x08:
100: s->imr = (s->imr & 0xffffffff) | ((uint64_t)val << 32);
101: break;
102: case 0x0c:
103: s->imr = (s->imr & 0xffffffff00000000ull) | (uint32_t)val;
104: break;
105: default:
1.1.1.2 root 106: hw_error("mcf_intc_write: Bad write offset %d\n", offset);
1.1 root 107: break;
108: }
109: mcf_intc_update(s);
110: }
111:
112: static void mcf_intc_set_irq(void *opaque, int irq, int level)
113: {
114: mcf_intc_state *s = (mcf_intc_state *)opaque;
115: if (irq >= 64)
116: return;
117: if (level)
118: s->ipr |= 1ull << irq;
119: else
120: s->ipr &= ~(1ull << irq);
121: mcf_intc_update(s);
122: }
123:
124: static void mcf_intc_reset(mcf_intc_state *s)
125: {
126: s->imr = ~0ull;
127: s->ipr = 0;
128: s->ifr = 0;
129: s->enabled = 0;
130: memset(s->icr, 0, 64);
131: s->active_vector = 24;
132: }
133:
1.1.1.7 ! root 134: static const MemoryRegionOps mcf_intc_ops = {
! 135: .read = mcf_intc_read,
! 136: .write = mcf_intc_write,
! 137: .endianness = DEVICE_NATIVE_ENDIAN,
1.1 root 138: };
139:
1.1.1.7 ! root 140: qemu_irq *mcf_intc_init(MemoryRegion *sysmem,
! 141: target_phys_addr_t base,
! 142: CPUM68KState *env)
1.1 root 143: {
144: mcf_intc_state *s;
145:
1.1.1.6 root 146: s = g_malloc0(sizeof(mcf_intc_state));
1.1 root 147: s->env = env;
148: mcf_intc_reset(s);
149:
1.1.1.7 ! root 150: memory_region_init_io(&s->iomem, &mcf_intc_ops, s, "mcf", 0x100);
! 151: memory_region_add_subregion(sysmem, base, &s->iomem);
1.1 root 152:
153: return qemu_allocate_irqs(mcf_intc_set_irq, s, 64);
154: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.