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 (*update_pending)(void);
|
||||||
|
|
||||||
static void pic_update_request(pic_t *dev, int irq);
|
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);
|
static void pic_cascade(int set);
|
||||||
|
|
||||||
#ifdef ENABLE_PIC_LOG
|
#ifdef ENABLE_PIC_LOG
|
||||||
@@ -224,17 +226,23 @@ find_best_interrupt(pic_t *dev)
|
|||||||
static __inline void
|
static __inline void
|
||||||
pic_update_pending_xt(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
|
static __inline void
|
||||||
pic_update_pending_at(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
|
static void
|
||||||
@@ -312,7 +320,7 @@ picint_is_level(int irq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pic_acknowledge(pic_t *dev)
|
pic_acknowledge(pic_t *dev, int poll)
|
||||||
{
|
{
|
||||||
int pic_int = dev->interrupt & 7;
|
int pic_int = dev->interrupt & 7;
|
||||||
int pic_int_num = 1 << pic_int;
|
int pic_int_num = 1 << pic_int;
|
||||||
@@ -324,10 +332,13 @@ pic_acknowledge(pic_t *dev)
|
|||||||
/* Clear the edge sense latch. */
|
/* Clear the edge sense latch. */
|
||||||
dev->irq_latch &= ~pic_int_num;
|
dev->irq_latch &= ~pic_int_num;
|
||||||
|
|
||||||
dev->flags |= PIC_FREEZE; /* Freeze it so it still takes interrupts but they do not
|
if (!poll) {
|
||||||
override the one currently being processed. */
|
dev->flags |= PIC_FREEZE; /* Freeze it so it still takes interrupts but they do not
|
||||||
/* Clear the reset latch. */
|
override the one currently being processed. */
|
||||||
pic_update_request(dev, pic_int);
|
|
||||||
|
/* 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
|
/* 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 {
|
} else {
|
||||||
/* Standard 8259 PIC read */
|
/* Standard 8259 PIC read */
|
||||||
if (dev->ocw3 & 0x04) {
|
if (dev->ocw3 & 0x04) {
|
||||||
dev->flags &= ~PIC_FREEZE; /* Freeze the interrupt until the poll is over. */
|
|
||||||
if (dev->int_pending) {
|
if (dev->int_pending) {
|
||||||
dev->data_bus = 0x80 | (dev->interrupt & 7);
|
dev->data_bus = 0x80 | (dev->interrupt & 7);
|
||||||
pic_acknowledge(dev);
|
pic_acknowledge(dev, 1);
|
||||||
dev->int_pending = 0;
|
dev->int_pending = 0;
|
||||||
update_pending();
|
|
||||||
} else
|
} else
|
||||||
dev->data_bus = 0x00;
|
dev->data_bus = 0x00;
|
||||||
dev->ocw3 &= ~0x04;
|
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)
|
} else if (addr & 0x0001)
|
||||||
dev->data_bus = dev->imr;
|
dev->data_bus = dev->imr;
|
||||||
else if (dev->ocw3 & 0x02) {
|
else if (dev->ocw3 & 0x02) {
|
||||||
@@ -509,10 +521,10 @@ pic_write(uint16_t addr, uint8_t val, void *priv)
|
|||||||
if (!(dev->icw1 & 1))
|
if (!(dev->icw1 & 1))
|
||||||
dev->icw4 = 0x00;
|
dev->icw4 = 0x00;
|
||||||
dev->ocw2 = dev->ocw3 = 0x00;
|
dev->ocw2 = dev->ocw3 = 0x00;
|
||||||
|
dev->flags = PIC_MASTER_CLEAR;
|
||||||
dev->irr = 0x00;
|
dev->irr = 0x00;
|
||||||
dev->edge_lines = 0x00;
|
dev->edge_lines = 0x00;
|
||||||
dev->irq_latch = 0x00;
|
dev->irq_latch = 0x00;
|
||||||
dev->flags |= PIC_MASTER_CLEAR;
|
|
||||||
for (i = 0; i <= 7; i++)
|
for (i = 0; i <= 7; i++)
|
||||||
pic_update_request(dev, i);
|
pic_update_request(dev, i);
|
||||||
dev->flags &= ~PIC_MASTER_CLEAR;
|
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));
|
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;
|
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);
|
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;
|
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));
|
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;
|
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));
|
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;
|
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));
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -721,12 +728,8 @@ pic_update_request(pic_t *dev, int irq)
|
|||||||
{
|
{
|
||||||
dev->irr &= ~(1 << irq);
|
dev->irr &= ~(1 << irq);
|
||||||
|
|
||||||
if (dev->flags & PIC_FREEZE) {
|
if (!(dev->flags & PIC_FREEZE))
|
||||||
pic_log("pic_update_request(%08X, %i): FREEZE#\n", (uint32_t) (uintptr_t) dev, irq);
|
|
||||||
} else {
|
|
||||||
dev->irr |= (pic_irq_request_nor(dev, irq) << irq);
|
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
|
static void
|
||||||
@@ -736,8 +739,6 @@ pic_update_irr(pic_t *dev, uint16_t num)
|
|||||||
if (num & (1 << i))
|
if (num & (1 << i))
|
||||||
pic_update_request(dev, i);
|
pic_update_request(dev, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
pic_log("IRQ %04x: IRR now: %02X\n", num, dev->irr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -792,8 +793,7 @@ picint_common(uint16_t num, int level, int set, uint8_t *irq_state)
|
|||||||
pic_update_irr(&pic, num & 0x00ff);
|
pic_update_irr(&pic, num & 0x00ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pic.flags & PIC_FREEZE) && !(pic2.flags & PIC_FREEZE))
|
update_pending();
|
||||||
update_pending();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -818,7 +818,7 @@ pic_irq_ack_read(pic_t *dev, int phase)
|
|||||||
|
|
||||||
if (dev != NULL) {
|
if (dev != NULL) {
|
||||||
if (phase == 0) {
|
if (phase == 0) {
|
||||||
pic_acknowledge(dev);
|
pic_acknowledge(dev, 0);
|
||||||
if (slave)
|
if (slave)
|
||||||
dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase);
|
dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase);
|
||||||
else
|
else
|
||||||
@@ -850,6 +850,9 @@ pic_irq_ack_read(pic_t *dev, int phase)
|
|||||||
return dev->data_bus;
|
return dev->data_bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 808x: Update the requests for all interrupts since any of them
|
||||||
|
could have arrived during the freeze. */
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
pic_irq_ack(void)
|
pic_irq_ack(void)
|
||||||
{
|
{
|
||||||
@@ -873,11 +876,11 @@ pic_irq_ack(void)
|
|||||||
/* Needed for Xi8088. */
|
/* Needed for Xi8088. */
|
||||||
if (pic.flags & PIC_SLAVE_PENDING) {
|
if (pic.flags & PIC_SLAVE_PENDING) {
|
||||||
pic2.flags &= ~PIC_FREEZE;
|
pic2.flags &= ~PIC_FREEZE;
|
||||||
pic_update_request(&pic2, pic2.interrupt & 0x07);
|
pic_update_irr(&pic2, num & 0x00ff);
|
||||||
pic2.interrupt = 0x17;
|
pic2.interrupt = 0x17;
|
||||||
}
|
}
|
||||||
pic.flags &= ~(PIC_SLAVE_PENDING | PIC_FREEZE);
|
pic.flags &= ~(PIC_SLAVE_PENDING | PIC_FREEZE);
|
||||||
pic_update_request(&pic, pic.interrupt & 0x07);
|
pic_update_irr(&pic, num & 0x00ff);
|
||||||
pic.interrupt = 0x17;
|
pic.interrupt = 0x17;
|
||||||
update_pending();
|
update_pending();
|
||||||
}
|
}
|
||||||
@@ -885,6 +888,9 @@ pic_irq_ack(void)
|
|||||||
return ret;
|
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
|
int
|
||||||
picinterrupt(void)
|
picinterrupt(void)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user