uint8_t rotate_on_auto_eoi;
uint8_t special_fully_nested_mode;
uint8_t init4; /* true if 4 byte init */
+ uint8_t elcr; /* PIIX edge/trigger selection*/
+ uint8_t elcr_mask;
} PicState;
/* 0 is master pic, 1 is slave pic */
{
int mask;
mask = 1 << irq;
- if (level) {
- if ((s->last_irr & mask) == 0)
+ if (s->elcr & mask) {
+ /* level triggered */
+ if (level) {
s->irr |= mask;
- s->last_irr |= mask;
+ s->last_irr |= mask;
+ } else {
+ s->irr &= ~mask;
+ s->last_irr &= ~mask;
+ }
} else {
- s->last_irr &= ~mask;
+ /* edge triggered */
+ if (level) {
+ if ((s->last_irr & mask) == 0)
+ s->irr |= mask;
+ s->last_irr |= mask;
+ } else {
+ s->last_irr &= ~mask;
+ }
}
}
static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
PicState *s = opaque;
- int priority, cmd, irq;
+ int priority, cmd, irq, tmp;
#ifdef DEBUG_PIC
printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val);
if (addr == 0) {
if (val & 0x10) {
/* init */
+ tmp = s->elcr_mask;
memset(s, 0, sizeof(PicState));
+ s->elcr_mask = tmp;
+
s->init_state = 1;
s->init4 = val & 1;
if (val & 0x02)
return ret;
}
+static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ PicState *s = opaque;
+ s->elcr = val & s->elcr_mask;
+}
+
+static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1)
+{
+ PicState *s = opaque;
+ return s->elcr;
+}
+
static void pic_save(QEMUFile *f, void *opaque)
{
PicState *s = opaque;
qemu_put_8s(f, &s->rotate_on_auto_eoi);
qemu_put_8s(f, &s->special_fully_nested_mode);
qemu_put_8s(f, &s->init4);
+ qemu_put_8s(f, &s->elcr);
}
static int pic_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_8s(f, &s->rotate_on_auto_eoi);
qemu_get_8s(f, &s->special_fully_nested_mode);
qemu_get_8s(f, &s->init4);
+ qemu_get_8s(f, &s->elcr);
return 0;
}
/* XXX: add generic master/slave system */
-static void pic_init1(int io_addr, PicState *s)
+static void pic_init1(int io_addr, int elcr_addr, PicState *s)
{
register_ioport_write(io_addr, 2, 1, pic_ioport_write, s);
register_ioport_read(io_addr, 2, 1, pic_ioport_read, s);
-
+ if (elcr_addr >= 0) {
+ register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s);
+ register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s);
+ }
register_savevm("i8259", io_addr, 1, pic_save, pic_load, s);
}
for(i=0;i<2;i++) {
s = &pics[i];
- term_printf("pic%d: irr=%02x imr=%02x isr=%02x hprio=%d irq_base=%02x rr_sel=%d\n",
- i, s->irr, s->imr, s->isr, s->priority_add, s->irq_base, s->read_reg_select);
+ term_printf("pic%d: irr=%02x imr=%02x isr=%02x hprio=%d irq_base=%02x rr_sel=%d elcr=%02x\n",
+ i, s->irr, s->imr, s->isr, s->priority_add,
+ s->irq_base, s->read_reg_select, s->elcr);
}
}
void pic_init(void)
{
- pic_init1(0x20, &pics[0]);
- pic_init1(0xa0, &pics[1]);
+ pic_init1(0x20, 0x4d0, &pics[0]);
+ pic_init1(0xa0, 0x4d1, &pics[1]);
+ pics[0].elcr_mask = 0xf8;
+ pics[1].elcr_mask = 0xde;
}