Commit c73f96fddc0f5ec7c708290f159b04cfa09ef713

Authored by blueswir1
1 parent 938255d2

Fix irq handling (Hervé Poussineau)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4245 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 33 additions and 15 deletions
hw/esp.c
@@ -127,7 +127,7 @@ struct ESPState { @@ -127,7 +127,7 @@ struct ESPState {
127 #define STAT_TC 0x10 127 #define STAT_TC 0x10
128 #define STAT_PE 0x20 128 #define STAT_PE 0x20
129 #define STAT_GE 0x40 129 #define STAT_GE 0x40
130 -#define STAT_IN 0x80 130 +#define STAT_INT 0x80
131 131
132 #define INTR_FC 0x08 132 #define INTR_FC 0x08
133 #define INTR_BS 0x10 133 #define INTR_BS 0x10
@@ -143,6 +143,22 @@ struct ESPState { @@ -143,6 +143,22 @@ struct ESPState {
143 143
144 #define TCHI_FAS100A 0x4 144 #define TCHI_FAS100A 0x4
145 145
  146 +static void esp_raise_irq(ESPState *s)
  147 +{
  148 + if (!(s->rregs[ESP_RSTAT] & STAT_INT)) {
  149 + s->rregs[ESP_RSTAT] |= STAT_INT;
  150 + qemu_irq_raise(s->irq);
  151 + }
  152 +}
  153 +
  154 +static void esp_lower_irq(ESPState *s)
  155 +{
  156 + if (s->rregs[ESP_RSTAT] & STAT_INT) {
  157 + s->rregs[ESP_RSTAT] &= ~STAT_INT;
  158 + qemu_irq_lower(s->irq);
  159 + }
  160 +}
  161 +
146 static int get_cmd(ESPState *s, uint8_t *buf) 162 static int get_cmd(ESPState *s, uint8_t *buf)
147 { 163 {
148 uint32_t dmalen; 164 uint32_t dmalen;
@@ -171,10 +187,10 @@ static int get_cmd(ESPState *s, uint8_t *buf) @@ -171,10 +187,10 @@ static int get_cmd(ESPState *s, uint8_t *buf)
171 187
172 if (target >= ESP_MAX_DEVS || !s->scsi_dev[target]) { 188 if (target >= ESP_MAX_DEVS || !s->scsi_dev[target]) {
173 // No such drive 189 // No such drive
174 - s->rregs[ESP_RSTAT] = STAT_IN; 190 + s->rregs[ESP_RSTAT] = 0;
175 s->rregs[ESP_RINTR] = INTR_DC; 191 s->rregs[ESP_RINTR] = INTR_DC;
176 s->rregs[ESP_RSEQ] = SEQ_0; 192 s->rregs[ESP_RSEQ] = SEQ_0;
177 - qemu_irq_raise(s->irq); 193 + esp_raise_irq(s);
178 return 0; 194 return 0;
179 } 195 }
180 s->current_dev = s->scsi_dev[target]; 196 s->current_dev = s->scsi_dev[target];
@@ -191,7 +207,7 @@ static void do_cmd(ESPState *s, uint8_t *buf) @@ -191,7 +207,7 @@ static void do_cmd(ESPState *s, uint8_t *buf)
191 datalen = s->current_dev->send_command(s->current_dev, 0, &buf[1], lun); 207 datalen = s->current_dev->send_command(s->current_dev, 0, &buf[1], lun);
192 s->ti_size = datalen; 208 s->ti_size = datalen;
193 if (datalen != 0) { 209 if (datalen != 0) {
194 - s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC; 210 + s->rregs[ESP_RSTAT] = STAT_TC;
195 s->dma_left = 0; 211 s->dma_left = 0;
196 s->dma_counter = 0; 212 s->dma_counter = 0;
197 if (datalen > 0) { 213 if (datalen > 0) {
@@ -204,7 +220,7 @@ static void do_cmd(ESPState *s, uint8_t *buf) @@ -204,7 +220,7 @@ static void do_cmd(ESPState *s, uint8_t *buf)
204 } 220 }
205 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; 221 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
206 s->rregs[ESP_RSEQ] = SEQ_CD; 222 s->rregs[ESP_RSEQ] = SEQ_CD;
207 - qemu_irq_raise(s->irq); 223 + esp_raise_irq(s);
208 } 224 }
209 225
210 static void handle_satn(ESPState *s) 226 static void handle_satn(ESPState *s)
@@ -223,10 +239,10 @@ static void handle_satn_stop(ESPState *s) @@ -223,10 +239,10 @@ static void handle_satn_stop(ESPState *s)
223 if (s->cmdlen) { 239 if (s->cmdlen) {
224 DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen); 240 DPRINTF("Set ATN & Stop: cmdlen %d\n", s->cmdlen);
225 s->do_cmd = 1; 241 s->do_cmd = 1;
226 - s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC | STAT_CD; 242 + s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
227 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; 243 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
228 s->rregs[ESP_RSEQ] = SEQ_CD; 244 s->rregs[ESP_RSEQ] = SEQ_CD;
229 - qemu_irq_raise(s->irq); 245 + esp_raise_irq(s);
230 } 246 }
231 } 247 }
232 248
@@ -237,7 +253,7 @@ static void write_response(ESPState *s) @@ -237,7 +253,7 @@ static void write_response(ESPState *s)
237 s->ti_buf[1] = 0; 253 s->ti_buf[1] = 0;
238 if (s->dma) { 254 if (s->dma) {
239 s->dma_memory_write(s->dma_opaque, s->ti_buf, 2); 255 s->dma_memory_write(s->dma_opaque, s->ti_buf, 2);
240 - s->rregs[ESP_RSTAT] = STAT_IN | STAT_TC | STAT_ST; 256 + s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
241 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC; 257 s->rregs[ESP_RINTR] = INTR_BS | INTR_FC;
242 s->rregs[ESP_RSEQ] = SEQ_CD; 258 s->rregs[ESP_RSEQ] = SEQ_CD;
243 } else { 259 } else {
@@ -246,18 +262,18 @@ static void write_response(ESPState *s) @@ -246,18 +262,18 @@ static void write_response(ESPState *s)
246 s->ti_wptr = 0; 262 s->ti_wptr = 0;
247 s->rregs[ESP_RFLAGS] = 2; 263 s->rregs[ESP_RFLAGS] = 2;
248 } 264 }
249 - qemu_irq_raise(s->irq); 265 + esp_raise_irq(s);
250 } 266 }
251 267
252 static void esp_dma_done(ESPState *s) 268 static void esp_dma_done(ESPState *s)
253 { 269 {
254 - s->rregs[ESP_RSTAT] |= STAT_IN | STAT_TC; 270 + s->rregs[ESP_RSTAT] |= STAT_TC;
255 s->rregs[ESP_RINTR] = INTR_BS; 271 s->rregs[ESP_RINTR] = INTR_BS;
256 s->rregs[ESP_RSEQ] = 0; 272 s->rregs[ESP_RSEQ] = 0;
257 s->rregs[ESP_RFLAGS] = 0; 273 s->rregs[ESP_RFLAGS] = 0;
258 s->rregs[ESP_TCLO] = 0; 274 s->rregs[ESP_TCLO] = 0;
259 s->rregs[ESP_TCMID] = 0; 275 s->rregs[ESP_TCMID] = 0;
260 - qemu_irq_raise(s->irq); 276 + esp_raise_irq(s);
261 } 277 }
262 278
263 static void esp_do_dma(ESPState *s) 279 static void esp_do_dma(ESPState *s)
@@ -381,6 +397,8 @@ static void esp_reset(void *opaque) @@ -381,6 +397,8 @@ static void esp_reset(void *opaque)
381 { 397 {
382 ESPState *s = opaque; 398 ESPState *s = opaque;
383 399
  400 + esp_lower_irq(s);
  401 +
384 memset(s->rregs, 0, ESP_REGS); 402 memset(s->rregs, 0, ESP_REGS);
385 memset(s->wregs, 0, ESP_REGS); 403 memset(s->wregs, 0, ESP_REGS);
386 s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a 404 s->rregs[ESP_TCHI] = TCHI_FAS100A; // Indicate fas100a
@@ -415,7 +433,7 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr) @@ -415,7 +433,7 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
415 } else { 433 } else {
416 s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++]; 434 s->rregs[ESP_FIFO] = s->ti_buf[s->ti_rptr++];
417 } 435 }
418 - qemu_irq_raise(s->irq); 436 + esp_raise_irq(s);
419 } 437 }
420 if (s->ti_size == 0) { 438 if (s->ti_size == 0) {
421 s->ti_rptr = 0; 439 s->ti_rptr = 0;
@@ -424,8 +442,8 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr) @@ -424,8 +442,8 @@ static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
424 break; 442 break;
425 case ESP_RINTR: 443 case ESP_RINTR:
426 // Clear interrupt/error status bits 444 // Clear interrupt/error status bits
427 - s->rregs[ESP_RSTAT] &= ~(STAT_IN | STAT_GE | STAT_PE);  
428 - qemu_irq_lower(s->irq); 445 + s->rregs[ESP_RSTAT] &= ~(STAT_GE | STAT_PE);
  446 + esp_lower_irq(s);
429 break; 447 break;
430 default: 448 default:
431 break; 449 break;
@@ -487,7 +505,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -487,7 +505,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
487 DPRINTF("Bus reset (%2.2x)\n", val); 505 DPRINTF("Bus reset (%2.2x)\n", val);
488 s->rregs[ESP_RINTR] = INTR_RST; 506 s->rregs[ESP_RINTR] = INTR_RST;
489 if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) { 507 if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) {
490 - qemu_irq_raise(s->irq); 508 + esp_raise_irq(s);
491 } 509 }
492 break; 510 break;
493 case CMD_TI: 511 case CMD_TI: