40 |
40 |
//#define DEBUG_IRQ_LATENCY
|
41 |
41 |
//#define DEBUG_IRQ_COUNT
|
42 |
42 |
|
43 |
|
typedef struct PicState {
|
|
43 |
struct PicState {
|
44 |
44 |
uint8_t last_irr; /* edge detection */
|
45 |
45 |
uint8_t irr; /* interrupt request register */
|
46 |
46 |
uint8_t imr; /* interrupt mask register */
|
... | ... | |
62 |
62 |
bool master; /* reflects /SP input pin */
|
63 |
63 |
MemoryRegion base_io;
|
64 |
64 |
MemoryRegion elcr_io;
|
65 |
|
} PicState;
|
66 |
|
|
67 |
|
struct PicState2 {
|
68 |
|
/* 0 is master pic, 1 is slave pic */
|
69 |
|
/* XXX: better separation between the two pics */
|
70 |
|
PicState pics[2];
|
71 |
|
void *irq_request_opaque;
|
72 |
65 |
};
|
73 |
66 |
|
74 |
67 |
#if defined(DEBUG_PIC) || defined (DEBUG_IRQ_COUNT)
|
... | ... | |
77 |
70 |
#ifdef DEBUG_IRQ_COUNT
|
78 |
71 |
static uint64_t irq_count[16];
|
79 |
72 |
#endif
|
80 |
|
PicState2 *isa_pic;
|
|
73 |
PicState *isa_pic;
|
|
74 |
static PicState *slave_pic;
|
81 |
75 |
|
82 |
76 |
/* return the highest priority found in mask (highest = smallest
|
83 |
77 |
number). Return 8 if no irq */
|
... | ... | |
168 |
162 |
|
169 |
163 |
static void i8259_set_irq(void *opaque, int irq, int level)
|
170 |
164 |
{
|
171 |
|
PicState2 *s = opaque;
|
|
165 |
PicState *s = irq <= 7 ? isa_pic : slave_pic;
|
172 |
166 |
|
173 |
167 |
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
|
174 |
168 |
if (level != irq_level[irq]) {
|
... | ... | |
185 |
179 |
irq_time[irq] = qemu_get_clock_ns(vm_clock);
|
186 |
180 |
}
|
187 |
181 |
#endif
|
188 |
|
pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
|
|
182 |
pic_set_irq1(s, irq & 7, level);
|
189 |
183 |
}
|
190 |
184 |
|
191 |
185 |
/* acknowledge interrupt 'irq' */
|
... | ... | |
203 |
197 |
pic_update_irq(s);
|
204 |
198 |
}
|
205 |
199 |
|
206 |
|
int pic_read_irq(PicState2 *s)
|
|
200 |
int pic_read_irq(PicState *s)
|
207 |
201 |
{
|
208 |
202 |
int irq, irq2, intno;
|
209 |
203 |
|
210 |
|
irq = pic_get_irq(&s->pics[0]);
|
|
204 |
irq = pic_get_irq(s);
|
211 |
205 |
if (irq >= 0) {
|
212 |
206 |
if (irq == 2) {
|
213 |
|
irq2 = pic_get_irq(&s->pics[1]);
|
|
207 |
irq2 = pic_get_irq(slave_pic);
|
214 |
208 |
if (irq2 >= 0) {
|
215 |
|
pic_intack(&s->pics[1], irq2);
|
|
209 |
pic_intack(slave_pic, irq2);
|
216 |
210 |
} else {
|
217 |
211 |
/* spurious IRQ on slave controller */
|
218 |
212 |
irq2 = 7;
|
219 |
213 |
}
|
220 |
|
intno = s->pics[1].irq_base + irq2;
|
|
214 |
intno = slave_pic->irq_base + irq2;
|
221 |
215 |
} else {
|
222 |
|
intno = s->pics[0].irq_base + irq;
|
|
216 |
intno = s->irq_base + irq;
|
223 |
217 |
}
|
224 |
|
pic_intack(&s->pics[0], irq);
|
|
218 |
pic_intack(s, irq);
|
225 |
219 |
} else {
|
226 |
220 |
/* spurious IRQ on host controller */
|
227 |
221 |
irq = 7;
|
228 |
|
intno = s->pics[0].irq_base + irq;
|
|
222 |
intno = s->irq_base + irq;
|
229 |
223 |
}
|
230 |
224 |
|
231 |
225 |
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_LATENCY)
|
... | ... | |
390 |
384 |
return ret;
|
391 |
385 |
}
|
392 |
386 |
|
393 |
|
int pic_get_output(PicState2 *s)
|
|
387 |
int pic_get_output(PicState *s)
|
394 |
388 |
{
|
395 |
|
return (pic_get_irq(&s->pics[0]) >= 0);
|
|
389 |
return (pic_get_irq(s) >= 0);
|
396 |
390 |
}
|
397 |
391 |
|
398 |
392 |
static void elcr_ioport_write(void *opaque, target_phys_addr_t addr,
|
... | ... | |
480 |
474 |
if (!isa_pic)
|
481 |
475 |
return;
|
482 |
476 |
|
483 |
|
for(i=0;i<2;i++) {
|
484 |
|
s = &isa_pic->pics[i];
|
|
477 |
for (i = 0; i < 2; i++) {
|
|
478 |
s = i == 0 ? isa_pic : slave_pic;
|
485 |
479 |
monitor_printf(mon, "pic%d: irr=%02x imr=%02x isr=%02x hprio=%d "
|
486 |
480 |
"irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
|
487 |
481 |
i, s->irr, s->imr, s->isr, s->priority_add,
|
... | ... | |
510 |
504 |
qemu_irq *i8259_init(qemu_irq parent_irq)
|
511 |
505 |
{
|
512 |
506 |
qemu_irq *irqs;
|
513 |
|
PicState2 *s;
|
514 |
|
|
515 |
|
s = g_malloc0(sizeof(PicState2));
|
516 |
|
irqs = qemu_allocate_irqs(i8259_set_irq, s, 16);
|
517 |
|
pic_init(0x20, 0x4d0, &s->pics[0], parent_irq, true);
|
518 |
|
pic_init(0xa0, 0x4d1, &s->pics[1], irqs[2], false);
|
519 |
|
s->pics[0].elcr_mask = 0xf8;
|
520 |
|
s->pics[1].elcr_mask = 0xde;
|
|
507 |
PicState *s;
|
|
508 |
|
|
509 |
irqs = qemu_allocate_irqs(i8259_set_irq, NULL, 16);
|
|
510 |
|
|
511 |
s = g_malloc0(sizeof(PicState));
|
|
512 |
pic_init(0x20, 0x4d0, s, parent_irq, true);
|
|
513 |
s->elcr_mask = 0xf8;
|
521 |
514 |
isa_pic = s;
|
|
515 |
|
|
516 |
s = g_malloc0(sizeof(PicState));
|
|
517 |
pic_init(0xa0, 0x4d1, s, irqs[2], false);
|
|
518 |
s->elcr_mask = 0xde;
|
|
519 |
slave_pic = s;
|
|
520 |
|
522 |
521 |
return irqs;
|
523 |
522 |
}
|