Statistics
| Branch: | Revision:

root / hw / etraxfs_pic.c @ cd5158ea

History | View | Annotate | Download (5.3 kB)

1 e62b5b13 edgar_igl
/*
2 e62b5b13 edgar_igl
 * QEMU ETRAX Interrupt Controller.
3 e62b5b13 edgar_igl
 *
4 e62b5b13 edgar_igl
 * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
5 e62b5b13 edgar_igl
 *
6 e62b5b13 edgar_igl
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 e62b5b13 edgar_igl
 * of this software and associated documentation files (the "Software"), to deal
8 e62b5b13 edgar_igl
 * in the Software without restriction, including without limitation the rights
9 e62b5b13 edgar_igl
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 e62b5b13 edgar_igl
 * copies of the Software, and to permit persons to whom the Software is
11 e62b5b13 edgar_igl
 * furnished to do so, subject to the following conditions:
12 e62b5b13 edgar_igl
 *
13 e62b5b13 edgar_igl
 * The above copyright notice and this permission notice shall be included in
14 e62b5b13 edgar_igl
 * all copies or substantial portions of the Software.
15 e62b5b13 edgar_igl
 *
16 e62b5b13 edgar_igl
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 e62b5b13 edgar_igl
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 e62b5b13 edgar_igl
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 e62b5b13 edgar_igl
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 e62b5b13 edgar_igl
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 e62b5b13 edgar_igl
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 e62b5b13 edgar_igl
 * THE SOFTWARE.
23 e62b5b13 edgar_igl
 */
24 e62b5b13 edgar_igl
25 e62b5b13 edgar_igl
#include <stdio.h>
26 e62b5b13 edgar_igl
#include "hw.h"
27 5ef98b47 edgar_igl
#include "etraxfs.h"
28 e62b5b13 edgar_igl
29 e62b5b13 edgar_igl
#define D(x)
30 e62b5b13 edgar_igl
31 e62b5b13 edgar_igl
struct fs_pic_state_t
32 e62b5b13 edgar_igl
{
33 e62b5b13 edgar_igl
        CPUState *env;
34 e62b5b13 edgar_igl
35 e62b5b13 edgar_igl
        uint32_t rw_mask;
36 e62b5b13 edgar_igl
        /* Active interrupt lines.  */
37 e62b5b13 edgar_igl
        uint32_t r_vect;
38 e62b5b13 edgar_igl
        /* Active lines, gated through the mask.  */
39 e62b5b13 edgar_igl
        uint32_t r_masked_vect;
40 e62b5b13 edgar_igl
        uint32_t r_nmi;
41 e62b5b13 edgar_igl
        uint32_t r_guru;
42 e62b5b13 edgar_igl
};
43 e62b5b13 edgar_igl
44 e62b5b13 edgar_igl
static uint32_t pic_readb (void *opaque, target_phys_addr_t addr)
45 e62b5b13 edgar_igl
{
46 e62b5b13 edgar_igl
        return 0;
47 e62b5b13 edgar_igl
}
48 e62b5b13 edgar_igl
static uint32_t pic_readw (void *opaque, target_phys_addr_t addr)
49 e62b5b13 edgar_igl
{
50 e62b5b13 edgar_igl
        return 0;
51 e62b5b13 edgar_igl
}
52 e62b5b13 edgar_igl
53 e62b5b13 edgar_igl
static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
54 e62b5b13 edgar_igl
{
55 e62b5b13 edgar_igl
        struct fs_pic_state_t *fs = opaque;
56 e62b5b13 edgar_igl
        uint32_t rval;
57 e62b5b13 edgar_igl
58 e62b5b13 edgar_igl
        switch (addr)
59 e62b5b13 edgar_igl
        {
60 e62b5b13 edgar_igl
                case 0x0: 
61 e62b5b13 edgar_igl
                        rval = fs->rw_mask;
62 e62b5b13 edgar_igl
                        break;
63 e62b5b13 edgar_igl
                case 0x4: 
64 e62b5b13 edgar_igl
                        rval = fs->r_vect;
65 e62b5b13 edgar_igl
                        break;
66 e62b5b13 edgar_igl
                case 0x8: 
67 e62b5b13 edgar_igl
                        rval = fs->r_masked_vect;
68 e62b5b13 edgar_igl
                        break;
69 e62b5b13 edgar_igl
                case 0xc: 
70 e62b5b13 edgar_igl
                        rval = fs->r_nmi;
71 e62b5b13 edgar_igl
                        break;
72 e62b5b13 edgar_igl
                case 0x10: 
73 e62b5b13 edgar_igl
                        rval = fs->r_guru;
74 e62b5b13 edgar_igl
                        break;
75 e62b5b13 edgar_igl
                default:
76 e62b5b13 edgar_igl
                        cpu_abort(fs->env, "invalid PIC register.\n");
77 e62b5b13 edgar_igl
                        break;
78 e62b5b13 edgar_igl
79 e62b5b13 edgar_igl
        }
80 e62b5b13 edgar_igl
        D(printf("%s %x=%x\n", __func__, addr, rval));
81 e62b5b13 edgar_igl
        return rval;
82 e62b5b13 edgar_igl
}
83 e62b5b13 edgar_igl
84 e62b5b13 edgar_igl
static void
85 e62b5b13 edgar_igl
pic_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
86 e62b5b13 edgar_igl
{
87 e62b5b13 edgar_igl
}
88 e62b5b13 edgar_igl
89 e62b5b13 edgar_igl
static void
90 e62b5b13 edgar_igl
pic_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
91 e62b5b13 edgar_igl
{
92 e62b5b13 edgar_igl
}
93 e62b5b13 edgar_igl
94 e62b5b13 edgar_igl
static void
95 e62b5b13 edgar_igl
pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
96 e62b5b13 edgar_igl
{
97 e62b5b13 edgar_igl
        struct fs_pic_state_t *fs = opaque;
98 e62b5b13 edgar_igl
        D(printf("%s addr=%x val=%x\n", __func__, addr, value));
99 e62b5b13 edgar_igl
        switch (addr) 
100 e62b5b13 edgar_igl
        {
101 e62b5b13 edgar_igl
                case 0x0: 
102 e62b5b13 edgar_igl
                        fs->rw_mask = value;
103 e62b5b13 edgar_igl
                        break;
104 e62b5b13 edgar_igl
                case 0x4: 
105 e62b5b13 edgar_igl
                        fs->r_vect = value;
106 e62b5b13 edgar_igl
                        break;
107 e62b5b13 edgar_igl
                case 0x8: 
108 e62b5b13 edgar_igl
                        fs->r_masked_vect = value;
109 e62b5b13 edgar_igl
                        break;
110 e62b5b13 edgar_igl
                case 0xc: 
111 e62b5b13 edgar_igl
                        fs->r_nmi = value;
112 e62b5b13 edgar_igl
                        break;
113 e62b5b13 edgar_igl
                case 0x10: 
114 e62b5b13 edgar_igl
                        fs->r_guru = value;
115 e62b5b13 edgar_igl
                        break;
116 e62b5b13 edgar_igl
                default:
117 e62b5b13 edgar_igl
                        cpu_abort(fs->env, "invalid PIC register.\n");
118 e62b5b13 edgar_igl
                        break;
119 e62b5b13 edgar_igl
        }
120 e62b5b13 edgar_igl
}
121 e62b5b13 edgar_igl
122 e62b5b13 edgar_igl
static CPUReadMemoryFunc *pic_read[] = {
123 e62b5b13 edgar_igl
        &pic_readb,
124 e62b5b13 edgar_igl
        &pic_readw,
125 e62b5b13 edgar_igl
        &pic_readl,
126 e62b5b13 edgar_igl
};
127 e62b5b13 edgar_igl
128 e62b5b13 edgar_igl
static CPUWriteMemoryFunc *pic_write[] = {
129 e62b5b13 edgar_igl
        &pic_writeb,
130 e62b5b13 edgar_igl
        &pic_writew,
131 e62b5b13 edgar_igl
        &pic_writel,
132 e62b5b13 edgar_igl
};
133 e62b5b13 edgar_igl
134 e62b5b13 edgar_igl
void pic_info(void)
135 e62b5b13 edgar_igl
{
136 e62b5b13 edgar_igl
}
137 e62b5b13 edgar_igl
138 e62b5b13 edgar_igl
void irq_info(void)
139 e62b5b13 edgar_igl
{
140 e62b5b13 edgar_igl
}
141 e62b5b13 edgar_igl
142 5ef98b47 edgar_igl
static void irq_handler(void *opaque, int irq, int level)
143 e62b5b13 edgar_igl
{        
144 e62b5b13 edgar_igl
        struct fs_pic_state_t *fs = (void *)opaque;
145 e62b5b13 edgar_igl
        CPUState *env = fs->env;
146 e62b5b13 edgar_igl
        int i;
147 e62b5b13 edgar_igl
        uint32_t vector = 0;
148 e62b5b13 edgar_igl
149 e62b5b13 edgar_igl
        D(printf("%s irq=%d level=%d mask=%x v=%x mv=%x\n", 
150 e62b5b13 edgar_igl
                 __func__, irq, level,
151 e62b5b13 edgar_igl
                 fs->rw_mask, fs->r_vect, fs->r_masked_vect));
152 e62b5b13 edgar_igl
153 48318011 edgar_igl
        irq -= 1;
154 e62b5b13 edgar_igl
        fs->r_vect &= ~(1 << irq);
155 e62b5b13 edgar_igl
        fs->r_vect |= (!!level << irq);
156 e62b5b13 edgar_igl
        fs->r_masked_vect = fs->r_vect & fs->rw_mask;
157 e62b5b13 edgar_igl
158 e62b5b13 edgar_igl
        /* The ETRAX interrupt controller signals interrupts to teh core
159 e62b5b13 edgar_igl
           through an interrupt request wire and an irq vector bus. If 
160 e62b5b13 edgar_igl
           multiple interrupts are simultaneously active it chooses vector 
161 e62b5b13 edgar_igl
           0x30 and lets the sw choose the priorities.  */
162 e62b5b13 edgar_igl
        if (fs->r_masked_vect) {
163 e62b5b13 edgar_igl
                uint32_t mv = fs->r_masked_vect;
164 e62b5b13 edgar_igl
                for (i = 0; i < 31; i++) {
165 e62b5b13 edgar_igl
                        if (mv & 1) {
166 e62b5b13 edgar_igl
                                vector = 0x31 + i;
167 e62b5b13 edgar_igl
                                /* Check for multiple interrupts.  */
168 e62b5b13 edgar_igl
                                if (mv > 1)
169 e62b5b13 edgar_igl
                                        vector = 0x30;
170 e62b5b13 edgar_igl
                                break;
171 e62b5b13 edgar_igl
                        }
172 e62b5b13 edgar_igl
                        mv >>= 1;
173 e62b5b13 edgar_igl
                }
174 e62b5b13 edgar_igl
                if (vector) {
175 e62b5b13 edgar_igl
                        env->interrupt_vector = vector;
176 e62b5b13 edgar_igl
                        D(printf("%s vector=%x\n", __func__, vector));
177 e62b5b13 edgar_igl
                        cpu_interrupt(env, CPU_INTERRUPT_HARD);
178 e62b5b13 edgar_igl
                }
179 e62b5b13 edgar_igl
        } else {
180 e62b5b13 edgar_igl
                env->interrupt_vector = 0;
181 e62b5b13 edgar_igl
                cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
182 e62b5b13 edgar_igl
                D(printf("%s reset irqs\n", __func__));
183 e62b5b13 edgar_igl
        }
184 e62b5b13 edgar_igl
}
185 e62b5b13 edgar_igl
186 5ef98b47 edgar_igl
static void nmi_handler(void *opaque, int irq, int level)
187 5ef98b47 edgar_igl
{        
188 5ef98b47 edgar_igl
        struct fs_pic_state_t *fs = (void *)opaque;
189 5ef98b47 edgar_igl
        CPUState *env = fs->env;
190 5ef98b47 edgar_igl
        uint32_t mask;
191 5ef98b47 edgar_igl
192 5ef98b47 edgar_igl
        mask = 1 << irq;
193 5ef98b47 edgar_igl
        if (level)
194 5ef98b47 edgar_igl
                fs->r_nmi |= mask;
195 5ef98b47 edgar_igl
        else
196 5ef98b47 edgar_igl
                fs->r_nmi &= ~mask;
197 5ef98b47 edgar_igl
198 5ef98b47 edgar_igl
        if (fs->r_nmi)
199 5ef98b47 edgar_igl
                cpu_interrupt(env, CPU_INTERRUPT_NMI);
200 5ef98b47 edgar_igl
        else
201 5ef98b47 edgar_igl
                cpu_reset_interrupt(env, CPU_INTERRUPT_NMI);
202 5ef98b47 edgar_igl
}
203 5ef98b47 edgar_igl
204 5ef98b47 edgar_igl
static void guru_handler(void *opaque, int irq, int level)
205 5ef98b47 edgar_igl
{        
206 5ef98b47 edgar_igl
        struct fs_pic_state_t *fs = (void *)opaque;
207 5ef98b47 edgar_igl
        CPUState *env = fs->env;
208 5ef98b47 edgar_igl
        cpu_abort(env, "%s unsupported exception\n", __func__);
209 5ef98b47 edgar_igl
210 5ef98b47 edgar_igl
}
211 5ef98b47 edgar_igl
212 5ef98b47 edgar_igl
213 5ef98b47 edgar_igl
struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base)
214 e62b5b13 edgar_igl
{
215 5ef98b47 edgar_igl
        struct fs_pic_state_t *fs = NULL;
216 5ef98b47 edgar_igl
        struct etraxfs_pic *pic = NULL;
217 e62b5b13 edgar_igl
        int intr_vect_regs;
218 e62b5b13 edgar_igl
219 5ef98b47 edgar_igl
        pic = qemu_mallocz(sizeof *pic);
220 5ef98b47 edgar_igl
        pic->internal = fs = qemu_mallocz(sizeof *fs);
221 5ef98b47 edgar_igl
        if (!fs || !pic)
222 5ef98b47 edgar_igl
                goto err;
223 e62b5b13 edgar_igl
224 5ef98b47 edgar_igl
        fs->env = env;
225 5ef98b47 edgar_igl
        pic->irq = qemu_allocate_irqs(irq_handler, fs, 30);
226 5ef98b47 edgar_igl
        pic->nmi = qemu_allocate_irqs(nmi_handler, fs, 2);
227 5ef98b47 edgar_igl
        pic->guru = qemu_allocate_irqs(guru_handler, fs, 1);
228 e62b5b13 edgar_igl
229 e62b5b13 edgar_igl
        intr_vect_regs = cpu_register_io_memory(0, pic_read, pic_write, fs);
230 e62b5b13 edgar_igl
        cpu_register_physical_memory(base, 0x14, intr_vect_regs);
231 e62b5b13 edgar_igl
232 e62b5b13 edgar_igl
        return pic;
233 5ef98b47 edgar_igl
  err:
234 5ef98b47 edgar_igl
        free(pic);
235 5ef98b47 edgar_igl
        free(fs);
236 5ef98b47 edgar_igl
        return NULL;
237 e62b5b13 edgar_igl
}