PIC fixes: poll mode is no longer broken.
This commit is contained in:
66
src/pic.c
66
src/pic.c
@@ -65,6 +65,8 @@ static int pic_pci = 0;
|
||||
static void (*update_pending)(void);
|
||||
|
||||
static void pic_update_request(pic_t *dev, int irq);
|
||||
static void pic_update_irr(pic_t *dev, uint16_t num);
|
||||
|
||||
static void pic_cascade(int set);
|
||||
|
||||
#ifdef ENABLE_PIC_LOG
|
||||
@@ -224,17 +226,23 @@ find_best_interrupt(pic_t *dev)
|
||||
static __inline void
|
||||
pic_update_pending_xt(void)
|
||||
{
|
||||
pic.int_pending = (find_best_interrupt(&pic) != -1);
|
||||
if (!(pic.flags & PIC_FREEZE))
|
||||
pic.int_pending = (find_best_interrupt(&pic) != -1);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
pic_update_pending_at(void)
|
||||
{
|
||||
pic2.int_pending = (find_best_interrupt(&pic2) != -1);
|
||||
if (!(pic2.flags & PIC_FREEZE)) {
|
||||
pic2.int_pending = (find_best_interrupt(&pic2) != -1);
|
||||
|
||||
pic_cascade(pic2.int_pending);
|
||||
pic_cascade(pic2.int_pending);
|
||||
}
|
||||
|
||||
pic.int_pending = (find_best_interrupt(&pic) != -1);
|
||||
if (!(pic.flags & PIC_FREEZE))
|
||||
pic.int_pending = (find_best_interrupt(&pic) != -1);
|
||||
|
||||
pic_log("pic_update_pending_at(): dev->int_pending = %i (%i)\n", pic.int_pending, !!(pic.flags & PIC_FREEZE));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -312,7 +320,7 @@ picint_is_level(int irq)
|
||||
}
|
||||
|
||||
static void
|
||||
pic_acknowledge(pic_t *dev)
|
||||
pic_acknowledge(pic_t *dev, int poll)
|
||||
{
|
||||
int pic_int = dev->interrupt & 7;
|
||||
int pic_int_num = 1 << pic_int;
|
||||
@@ -324,10 +332,13 @@ pic_acknowledge(pic_t *dev)
|
||||
/* Clear the edge sense latch. */
|
||||
dev->irq_latch &= ~pic_int_num;
|
||||
|
||||
dev->flags |= PIC_FREEZE; /* Freeze it so it still takes interrupts but they do not
|
||||
override the one currently being processed. */
|
||||
/* Clear the reset latch. */
|
||||
pic_update_request(dev, pic_int);
|
||||
if (!poll) {
|
||||
dev->flags |= PIC_FREEZE; /* Freeze it so it still takes interrupts but they do not
|
||||
override the one currently being processed. */
|
||||
|
||||
/* Clear the reset latch. */
|
||||
pic_update_request(dev, pic_int);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find IRQ for non-specific EOI (either by command or automatic) by finding the highest IRQ
|
||||
@@ -434,15 +445,16 @@ pic_read(uint16_t addr, void *priv)
|
||||
} else {
|
||||
/* Standard 8259 PIC read */
|
||||
if (dev->ocw3 & 0x04) {
|
||||
dev->flags &= ~PIC_FREEZE; /* Freeze the interrupt until the poll is over. */
|
||||
if (dev->int_pending) {
|
||||
dev->data_bus = 0x80 | (dev->interrupt & 7);
|
||||
pic_acknowledge(dev);
|
||||
pic_acknowledge(dev, 1);
|
||||
dev->int_pending = 0;
|
||||
update_pending();
|
||||
} else
|
||||
dev->data_bus = 0x00;
|
||||
dev->ocw3 &= ~0x04;
|
||||
dev->flags &= ~PIC_FREEZE; /* Freeze the interrupt until the poll is over. */
|
||||
pic_update_irr(dev, 0x00ff); /* Update IRR, just in case anything came while frozen. */
|
||||
update_pending();
|
||||
} else if (addr & 0x0001)
|
||||
dev->data_bus = dev->imr;
|
||||
else if (dev->ocw3 & 0x02) {
|
||||
@@ -509,10 +521,10 @@ pic_write(uint16_t addr, uint8_t val, void *priv)
|
||||
if (!(dev->icw1 & 1))
|
||||
dev->icw4 = 0x00;
|
||||
dev->ocw2 = dev->ocw3 = 0x00;
|
||||
dev->flags = PIC_MASTER_CLEAR;
|
||||
dev->irr = 0x00;
|
||||
dev->edge_lines = 0x00;
|
||||
dev->irq_latch = 0x00;
|
||||
dev->flags |= PIC_MASTER_CLEAR;
|
||||
for (i = 0; i <= 7; i++)
|
||||
pic_update_request(dev, i);
|
||||
dev->flags &= ~PIC_MASTER_CLEAR;
|
||||
@@ -668,7 +680,6 @@ pic_irq_get_request(pic_t *dev, int irq)
|
||||
|
||||
ret = ((dev->edge_lines & (1 << irq)) || (dev->lines[irq] > 0));
|
||||
|
||||
pic_log("pic_irq_get_request(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -679,7 +690,6 @@ pic_es_latch_clear(pic_t *dev, int irq)
|
||||
|
||||
ret = (dev->isr & (1 << irq)) || (dev->flags & PIC_MASTER_CLEAR);
|
||||
|
||||
pic_log("pic_es_latch_clear(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -690,7 +700,6 @@ pic_es_latch_out(pic_t *dev, int irq)
|
||||
|
||||
ret = !((pic_es_latch_clear(dev, irq) && (dev->irq_latch & (1 << irq))) || !pic_irq_get_request(dev, irq));
|
||||
|
||||
pic_log("pic_es_latch_out(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -701,7 +710,6 @@ pic_es_latch_nor(pic_t *dev, int irq)
|
||||
|
||||
ret = !(pic_es_latch_out(dev, irq) || picint_is_level(irq));
|
||||
|
||||
pic_log("pic_es_latch_nor(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -712,7 +720,6 @@ pic_irq_request_nor(pic_t *dev, int irq)
|
||||
|
||||
ret = !(pic_es_latch_nor(dev, irq) || !pic_irq_get_request(dev, irq));
|
||||
|
||||
pic_log("pic_irq_request_nor(%08X, %i) = %02X\n", (uint32_t) (uintptr_t) dev, irq, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -721,12 +728,8 @@ pic_update_request(pic_t *dev, int irq)
|
||||
{
|
||||
dev->irr &= ~(1 << irq);
|
||||
|
||||
if (dev->flags & PIC_FREEZE) {
|
||||
pic_log("pic_update_request(%08X, %i): FREEZE#\n", (uint32_t) (uintptr_t) dev, irq);
|
||||
} else {
|
||||
if (!(dev->flags & PIC_FREEZE))
|
||||
dev->irr |= (pic_irq_request_nor(dev, irq) << irq);
|
||||
pic_log("pic_update_request(%08X, %i): IRR = %02X\n", (uint32_t) (uintptr_t) dev, irq, dev->irr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -736,8 +739,6 @@ pic_update_irr(pic_t *dev, uint16_t num)
|
||||
if (num & (1 << i))
|
||||
pic_update_request(dev, i);
|
||||
}
|
||||
|
||||
pic_log("IRQ %04x: IRR now: %02X\n", num, dev->irr);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -792,8 +793,7 @@ picint_common(uint16_t num, int level, int set, uint8_t *irq_state)
|
||||
pic_update_irr(&pic, num & 0x00ff);
|
||||
}
|
||||
|
||||
if (!(pic.flags & PIC_FREEZE) && !(pic2.flags & PIC_FREEZE))
|
||||
update_pending();
|
||||
update_pending();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -818,7 +818,7 @@ pic_irq_ack_read(pic_t *dev, int phase)
|
||||
|
||||
if (dev != NULL) {
|
||||
if (phase == 0) {
|
||||
pic_acknowledge(dev);
|
||||
pic_acknowledge(dev, 0);
|
||||
if (slave)
|
||||
dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase);
|
||||
else
|
||||
@@ -850,6 +850,9 @@ pic_irq_ack_read(pic_t *dev, int phase)
|
||||
return dev->data_bus;
|
||||
}
|
||||
|
||||
/* 808x: Update the requests for all interrupts since any of them
|
||||
could have arrived during the freeze. */
|
||||
|
||||
uint8_t
|
||||
pic_irq_ack(void)
|
||||
{
|
||||
@@ -873,11 +876,11 @@ pic_irq_ack(void)
|
||||
/* Needed for Xi8088. */
|
||||
if (pic.flags & PIC_SLAVE_PENDING) {
|
||||
pic2.flags &= ~PIC_FREEZE;
|
||||
pic_update_request(&pic2, pic2.interrupt & 0x07);
|
||||
pic_update_irr(&pic2, num & 0x00ff);
|
||||
pic2.interrupt = 0x17;
|
||||
}
|
||||
pic.flags &= ~(PIC_SLAVE_PENDING | PIC_FREEZE);
|
||||
pic_update_request(&pic, pic.interrupt & 0x07);
|
||||
pic_update_irr(&pic, num & 0x00ff);
|
||||
pic.interrupt = 0x17;
|
||||
update_pending();
|
||||
}
|
||||
@@ -885,6 +888,9 @@ pic_irq_ack(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 286+: Only update the request for the pending interrupt as it is
|
||||
impossible that any other interrupt has arrived during the
|
||||
freeze. */
|
||||
int
|
||||
picinterrupt(void)
|
||||
{
|
||||
|
Reference in New Issue
Block a user