Statistics
| Branch: | Revision:

root / hw / etraxfs_pic.c @ 4af39611

History | View | Annotate | Download (4.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 376253ec aliguori
#include "pc.h"
28 5ef98b47 edgar_igl
#include "etraxfs.h"
29 e62b5b13 edgar_igl
30 e62b5b13 edgar_igl
#define D(x)
31 e62b5b13 edgar_igl
32 8d13fcc0 Edgar E. Iglesias
#define R_RW_MASK        0
33 8d13fcc0 Edgar E. Iglesias
#define R_R_VECT        1
34 8d13fcc0 Edgar E. Iglesias
#define R_R_MASKED_VECT        2
35 8d13fcc0 Edgar E. Iglesias
#define R_R_NMI                3
36 8d13fcc0 Edgar E. Iglesias
#define R_R_GURU        4
37 8d13fcc0 Edgar E. Iglesias
#define R_MAX                5
38 8d13fcc0 Edgar E. Iglesias
39 b23b0fd0 Edgar E. Iglesias
struct fs_pic_state
40 e62b5b13 edgar_igl
{
41 e62b5b13 edgar_igl
        CPUState *env;
42 8d13fcc0 Edgar E. Iglesias
        uint32_t regs[R_MAX];
43 e62b5b13 edgar_igl
};
44 e62b5b13 edgar_igl
45 b23b0fd0 Edgar E. Iglesias
static void pic_update(struct fs_pic_state *fs)
46 70ea255d edgar_igl
{        
47 70ea255d edgar_igl
        CPUState *env = fs->env;
48 70ea255d edgar_igl
        uint32_t vector = 0;
49 8d13fcc0 Edgar E. Iglesias
        int i;
50 70ea255d edgar_igl
51 8d13fcc0 Edgar E. Iglesias
        fs->regs[R_R_MASKED_VECT] = fs->regs[R_R_VECT] & fs->regs[R_RW_MASK];
52 70ea255d edgar_igl
53 70ea255d edgar_igl
        /* The ETRAX interrupt controller signals interrupts to teh core
54 70ea255d edgar_igl
           through an interrupt request wire and an irq vector bus. If 
55 70ea255d edgar_igl
           multiple interrupts are simultaneously active it chooses vector 
56 70ea255d edgar_igl
           0x30 and lets the sw choose the priorities.  */
57 8d13fcc0 Edgar E. Iglesias
        if (fs->regs[R_R_MASKED_VECT]) {
58 8d13fcc0 Edgar E. Iglesias
                uint32_t mv = fs->regs[R_R_MASKED_VECT];
59 70ea255d edgar_igl
                for (i = 0; i < 31; i++) {
60 70ea255d edgar_igl
                        if (mv & 1) {
61 70ea255d edgar_igl
                                vector = 0x31 + i;
62 70ea255d edgar_igl
                                /* Check for multiple interrupts.  */
63 70ea255d edgar_igl
                                if (mv > 1)
64 70ea255d edgar_igl
                                        vector = 0x30;
65 70ea255d edgar_igl
                                break;
66 70ea255d edgar_igl
                        }
67 70ea255d edgar_igl
                        mv >>= 1;
68 70ea255d edgar_igl
                }
69 70ea255d edgar_igl
                if (vector) {
70 70ea255d edgar_igl
                        env->interrupt_vector = vector;
71 70ea255d edgar_igl
                        D(printf("%s vector=%x\n", __func__, vector));
72 70ea255d edgar_igl
                        cpu_interrupt(env, CPU_INTERRUPT_HARD);
73 70ea255d edgar_igl
                }
74 70ea255d edgar_igl
        } else {
75 70ea255d edgar_igl
                env->interrupt_vector = 0;
76 70ea255d edgar_igl
                cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
77 70ea255d edgar_igl
                D(printf("%s reset irqs\n", __func__));
78 70ea255d edgar_igl
        }
79 e62b5b13 edgar_igl
}
80 e62b5b13 edgar_igl
81 e62b5b13 edgar_igl
static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
82 e62b5b13 edgar_igl
{
83 b23b0fd0 Edgar E. Iglesias
        struct fs_pic_state *fs = opaque;
84 e62b5b13 edgar_igl
        uint32_t rval;
85 e62b5b13 edgar_igl
86 8d13fcc0 Edgar E. Iglesias
        rval = fs->regs[addr >> 2];
87 e62b5b13 edgar_igl
        D(printf("%s %x=%x\n", __func__, addr, rval));
88 e62b5b13 edgar_igl
        return rval;
89 e62b5b13 edgar_igl
}
90 e62b5b13 edgar_igl
91 e62b5b13 edgar_igl
static void
92 e62b5b13 edgar_igl
pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
93 e62b5b13 edgar_igl
{
94 b23b0fd0 Edgar E. Iglesias
        struct fs_pic_state *fs = opaque;
95 e62b5b13 edgar_igl
        D(printf("%s addr=%x val=%x\n", __func__, addr, value));
96 8d13fcc0 Edgar E. Iglesias
97 8d13fcc0 Edgar E. Iglesias
        if (addr == R_RW_MASK) {
98 8d13fcc0 Edgar E. Iglesias
                fs->regs[R_RW_MASK] = value;
99 8d13fcc0 Edgar E. Iglesias
                pic_update(fs);
100 e62b5b13 edgar_igl
        }
101 e62b5b13 edgar_igl
}
102 e62b5b13 edgar_igl
103 e62b5b13 edgar_igl
static CPUReadMemoryFunc *pic_read[] = {
104 70ea255d edgar_igl
        NULL, NULL,
105 e62b5b13 edgar_igl
        &pic_readl,
106 e62b5b13 edgar_igl
};
107 e62b5b13 edgar_igl
108 e62b5b13 edgar_igl
static CPUWriteMemoryFunc *pic_write[] = {
109 70ea255d edgar_igl
        NULL, NULL,
110 e62b5b13 edgar_igl
        &pic_writel,
111 e62b5b13 edgar_igl
};
112 e62b5b13 edgar_igl
113 376253ec aliguori
void pic_info(Monitor *mon)
114 e62b5b13 edgar_igl
{
115 e62b5b13 edgar_igl
}
116 e62b5b13 edgar_igl
117 376253ec aliguori
void irq_info(Monitor *mon)
118 e62b5b13 edgar_igl
{
119 e62b5b13 edgar_igl
}
120 e62b5b13 edgar_igl
121 5ef98b47 edgar_igl
static void irq_handler(void *opaque, int irq, int level)
122 e62b5b13 edgar_igl
{        
123 b23b0fd0 Edgar E. Iglesias
        struct fs_pic_state *fs = (void *)opaque;
124 48318011 edgar_igl
        irq -= 1;
125 8d13fcc0 Edgar E. Iglesias
        fs->regs[R_R_VECT] &= ~(1 << irq);
126 8d13fcc0 Edgar E. Iglesias
        fs->regs[R_R_VECT] |= (!!level << irq);
127 e62b5b13 edgar_igl
128 70ea255d edgar_igl
        pic_update(fs);
129 e62b5b13 edgar_igl
}
130 e62b5b13 edgar_igl
131 5ef98b47 edgar_igl
static void nmi_handler(void *opaque, int irq, int level)
132 5ef98b47 edgar_igl
{        
133 b23b0fd0 Edgar E. Iglesias
        struct fs_pic_state *fs = (void *)opaque;
134 5ef98b47 edgar_igl
        CPUState *env = fs->env;
135 5ef98b47 edgar_igl
        uint32_t mask;
136 5ef98b47 edgar_igl
137 5ef98b47 edgar_igl
        mask = 1 << irq;
138 5ef98b47 edgar_igl
        if (level)
139 8d13fcc0 Edgar E. Iglesias
                fs->regs[R_R_NMI] |= mask;
140 5ef98b47 edgar_igl
        else
141 8d13fcc0 Edgar E. Iglesias
                fs->regs[R_R_NMI] &= ~mask;
142 5ef98b47 edgar_igl
143 8d13fcc0 Edgar E. Iglesias
        if (fs->regs[R_R_NMI])
144 5ef98b47 edgar_igl
                cpu_interrupt(env, CPU_INTERRUPT_NMI);
145 5ef98b47 edgar_igl
        else
146 5ef98b47 edgar_igl
                cpu_reset_interrupt(env, CPU_INTERRUPT_NMI);
147 5ef98b47 edgar_igl
}
148 5ef98b47 edgar_igl
149 5ef98b47 edgar_igl
static void guru_handler(void *opaque, int irq, int level)
150 5ef98b47 edgar_igl
{        
151 2ac71179 Paul Brook
        hw_error("%s unsupported exception\n", __func__);
152 5ef98b47 edgar_igl
}
153 5ef98b47 edgar_igl
154 5ef98b47 edgar_igl
struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base)
155 e62b5b13 edgar_igl
{
156 b23b0fd0 Edgar E. Iglesias
        struct fs_pic_state *fs = NULL;
157 5ef98b47 edgar_igl
        struct etraxfs_pic *pic = NULL;
158 e62b5b13 edgar_igl
        int intr_vect_regs;
159 e62b5b13 edgar_igl
160 5ef98b47 edgar_igl
        pic = qemu_mallocz(sizeof *pic);
161 5ef98b47 edgar_igl
        pic->internal = fs = qemu_mallocz(sizeof *fs);
162 e62b5b13 edgar_igl
163 5ef98b47 edgar_igl
        fs->env = env;
164 5ef98b47 edgar_igl
        pic->irq = qemu_allocate_irqs(irq_handler, fs, 30);
165 5ef98b47 edgar_igl
        pic->nmi = qemu_allocate_irqs(nmi_handler, fs, 2);
166 5ef98b47 edgar_igl
        pic->guru = qemu_allocate_irqs(guru_handler, fs, 1);
167 e62b5b13 edgar_igl
168 e62b5b13 edgar_igl
        intr_vect_regs = cpu_register_io_memory(0, pic_read, pic_write, fs);
169 8d13fcc0 Edgar E. Iglesias
        cpu_register_physical_memory(base, R_MAX * 4, intr_vect_regs);
170 e62b5b13 edgar_igl
171 e62b5b13 edgar_igl
        return pic;
172 e62b5b13 edgar_igl
}