|
|
1.1 root 1: /*
2: * QEMU ETRAX Interrupt Controller.
3: *
4: * Copyright (c) 2008 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 "hw.h"
27: #include "etraxfs.h"
28:
29: #define D(x)
30:
31: struct fs_pic_state_t
32: {
33: CPUState *env;
34:
35: uint32_t rw_mask;
36: /* Active interrupt lines. */
37: uint32_t r_vect;
38: /* Active lines, gated through the mask. */
39: uint32_t r_masked_vect;
40: uint32_t r_nmi;
41: uint32_t r_guru;
42: };
43:
44: static void pic_update(struct fs_pic_state_t *fs)
45: {
46: CPUState *env = fs->env;
47: int i;
48: uint32_t vector = 0;
49:
50: fs->r_masked_vect = fs->r_vect & fs->rw_mask;
51:
52: /* The ETRAX interrupt controller signals interrupts to teh core
53: through an interrupt request wire and an irq vector bus. If
54: multiple interrupts are simultaneously active it chooses vector
55: 0x30 and lets the sw choose the priorities. */
56: if (fs->r_masked_vect) {
57: uint32_t mv = fs->r_masked_vect;
58: for (i = 0; i < 31; i++) {
59: if (mv & 1) {
60: vector = 0x31 + i;
61: /* Check for multiple interrupts. */
62: if (mv > 1)
63: vector = 0x30;
64: break;
65: }
66: mv >>= 1;
67: }
68: if (vector) {
69: env->interrupt_vector = vector;
70: D(printf("%s vector=%x\n", __func__, vector));
71: cpu_interrupt(env, CPU_INTERRUPT_HARD);
72: }
73: } else {
74: env->interrupt_vector = 0;
75: cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
76: D(printf("%s reset irqs\n", __func__));
77: }
78: }
79:
80: static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
81: {
82: struct fs_pic_state_t *fs = opaque;
83: uint32_t rval;
84:
85: switch (addr)
86: {
87: case 0x0:
88: rval = fs->rw_mask;
89: break;
90: case 0x4:
91: rval = fs->r_vect;
92: break;
93: case 0x8:
94: rval = fs->r_masked_vect;
95: break;
96: case 0xc:
97: rval = fs->r_nmi;
98: break;
99: case 0x10:
100: rval = fs->r_guru;
101: break;
102: default:
103: cpu_abort(fs->env, "invalid PIC register.\n");
104: break;
105:
106: }
107: D(printf("%s %x=%x\n", __func__, addr, rval));
108: return rval;
109: }
110:
111: static void
112: pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
113: {
114: struct fs_pic_state_t *fs = opaque;
115: D(printf("%s addr=%x val=%x\n", __func__, addr, value));
116: switch (addr)
117: {
118: case 0x0:
119: fs->rw_mask = value;
120: pic_update(fs);
121: break;
122: default:
123: cpu_abort(fs->env, "invalid PIC register.\n");
124: break;
125: }
126: }
127:
128: static CPUReadMemoryFunc *pic_read[] = {
129: NULL, NULL,
130: &pic_readl,
131: };
132:
133: static CPUWriteMemoryFunc *pic_write[] = {
134: NULL, NULL,
135: &pic_writel,
136: };
137:
138: void pic_info(void)
139: {
140: }
141:
142: void irq_info(void)
143: {
144: }
145:
146: static void irq_handler(void *opaque, int irq, int level)
147: {
148: struct fs_pic_state_t *fs = (void *)opaque;
149:
150: D(printf("%s irq=%d level=%d mask=%x v=%x mv=%x\n",
151: __func__, irq, level,
152: fs->rw_mask, fs->r_vect, fs->r_masked_vect));
153:
154: irq -= 1;
155: fs->r_vect &= ~(1 << irq);
156: fs->r_vect |= (!!level << irq);
157:
158: pic_update(fs);
159: }
160:
161: static void nmi_handler(void *opaque, int irq, int level)
162: {
163: struct fs_pic_state_t *fs = (void *)opaque;
164: CPUState *env = fs->env;
165: uint32_t mask;
166:
167: mask = 1 << irq;
168: if (level)
169: fs->r_nmi |= mask;
170: else
171: fs->r_nmi &= ~mask;
172:
173: if (fs->r_nmi)
174: cpu_interrupt(env, CPU_INTERRUPT_NMI);
175: else
176: cpu_reset_interrupt(env, CPU_INTERRUPT_NMI);
177: }
178:
179: static void guru_handler(void *opaque, int irq, int level)
180: {
181: struct fs_pic_state_t *fs = (void *)opaque;
182: CPUState *env = fs->env;
183: cpu_abort(env, "%s unsupported exception\n", __func__);
184:
185: }
186:
187: struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base)
188: {
189: struct fs_pic_state_t *fs = NULL;
190: struct etraxfs_pic *pic = NULL;
191: int intr_vect_regs;
192:
193: pic = qemu_mallocz(sizeof *pic);
194: pic->internal = fs = qemu_mallocz(sizeof *fs);
195:
196: fs->env = env;
197: pic->irq = qemu_allocate_irqs(irq_handler, fs, 30);
198: pic->nmi = qemu_allocate_irqs(nmi_handler, fs, 2);
199: pic->guru = qemu_allocate_irqs(guru_handler, fs, 1);
200:
201: intr_vect_regs = cpu_register_io_memory(0, pic_read, pic_write, fs);
202: cpu_register_physical_memory(base, 0x14, intr_vect_regs);
203:
204: return pic;
205: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.