Commit 70ea255d8be9ca5af3eb20a6ad000ea4ab1e2d17

Authored by edgar_igl
1 parent ab86bb3b

ETRAX: Correctly update the interrupt vector when interrupts get masked.

Cannot believe this bug has been around for so long.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6207 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 38 additions and 64 deletions
hw/etraxfs_pic.c
... ... @@ -41,13 +41,40 @@ struct fs_pic_state_t
41 41 uint32_t r_guru;
42 42 };
43 43  
44   -static uint32_t pic_readb (void *opaque, target_phys_addr_t addr)
45   -{
46   - return 0;
47   -}
48   -static uint32_t pic_readw (void *opaque, target_phys_addr_t addr)
49   -{
50   - return 0;
  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 + }
51 78 }
52 79  
53 80 static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
... ... @@ -82,16 +109,6 @@ static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
82 109 }
83 110  
84 111 static void
85   -pic_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
86   -{
87   -}
88   -
89   -static void
90   -pic_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
91   -{
92   -}
93   -
94   -static void
95 112 pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
96 113 {
97 114 struct fs_pic_state_t *fs = opaque;
... ... @@ -100,18 +117,7 @@ pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
100 117 {
101 118 case 0x0:
102 119 fs->rw_mask = value;
103   - break;
104   - case 0x4:
105   - fs->r_vect = value;
106   - break;
107   - case 0x8:
108   - fs->r_masked_vect = value;
109   - break;
110   - case 0xc:
111   - fs->r_nmi = value;
112   - break;
113   - case 0x10:
114   - fs->r_guru = value;
  120 + pic_update(fs);
115 121 break;
116 122 default:
117 123 cpu_abort(fs->env, "invalid PIC register.\n");
... ... @@ -120,14 +126,12 @@ pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
120 126 }
121 127  
122 128 static CPUReadMemoryFunc *pic_read[] = {
123   - &pic_readb,
124   - &pic_readw,
  129 + NULL, NULL,
125 130 &pic_readl,
126 131 };
127 132  
128 133 static CPUWriteMemoryFunc *pic_write[] = {
129   - &pic_writeb,
130   - &pic_writew,
  134 + NULL, NULL,
131 135 &pic_writel,
132 136 };
133 137  
... ... @@ -142,9 +146,6 @@ void irq_info(void)
142 146 static void irq_handler(void *opaque, int irq, int level)
143 147 {
144 148 struct fs_pic_state_t *fs = (void *)opaque;
145   - CPUState *env = fs->env;
146   - int i;
147   - uint32_t vector = 0;
148 149  
149 150 D(printf("%s irq=%d level=%d mask=%x v=%x mv=%x\n",
150 151 __func__, irq, level,
... ... @@ -153,34 +154,8 @@ static void irq_handler(void *opaque, int irq, int level)
153 154 irq -= 1;
154 155 fs->r_vect &= ~(1 << irq);
155 156 fs->r_vect |= (!!level << irq);
156   - fs->r_masked_vect = fs->r_vect & fs->rw_mask;
157 157  
158   - /* The ETRAX interrupt controller signals interrupts to teh core
159   - through an interrupt request wire and an irq vector bus. If
160   - multiple interrupts are simultaneously active it chooses vector
161   - 0x30 and lets the sw choose the priorities. */
162   - if (fs->r_masked_vect) {
163   - uint32_t mv = fs->r_masked_vect;
164   - for (i = 0; i < 31; i++) {
165   - if (mv & 1) {
166   - vector = 0x31 + i;
167   - /* Check for multiple interrupts. */
168   - if (mv > 1)
169   - vector = 0x30;
170   - break;
171   - }
172   - mv >>= 1;
173   - }
174   - if (vector) {
175   - env->interrupt_vector = vector;
176   - D(printf("%s vector=%x\n", __func__, vector));
177   - cpu_interrupt(env, CPU_INTERRUPT_HARD);
178   - }
179   - } else {
180   - env->interrupt_vector = 0;
181   - cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
182   - D(printf("%s reset irqs\n", __func__));
183   - }
  158 + pic_update(fs);
184 159 }
185 160  
186 161 static void nmi_handler(void *opaque, int irq, int level)
... ... @@ -209,7 +184,6 @@ static void guru_handler(void *opaque, int irq, int level)
209 184  
210 185 }
211 186  
212   -
213 187 struct etraxfs_pic *etraxfs_pic_init(CPUState *env, target_phys_addr_t base)
214 188 {
215 189 struct fs_pic_state_t *fs = NULL;
... ...