PIC fixes: poll mode is no longer broken.

This commit is contained in:
OBattler
2023-08-10 05:03:11 +02:00
parent b38f87f13f
commit f771e9e612

View File

@@ -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)
{