From 6412d01deb4b375ff5965e6f13dacb5928059919 Mon Sep 17 00:00:00 2001 From: SarahW Date: Sat, 24 Mar 2018 15:29:10 +0000 Subject: [PATCH] Added level-sensitive IRQs on PIIX and SiS497. Fixes hanging audio with AudioPCI on Windows 2000. --- src/ibm.h | 1 + src/pic.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- src/pic.h | 1 + src/piix.c | 3 +++ src/sis496.c | 3 +++ 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/ibm.h b/src/ibm.h index 491116f..5fdb9f6 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -363,6 +363,7 @@ typedef struct PIC int icw; uint8_t vector; int read; + uint8_t level_sensitive; } PIC; PIC pic,pic2; diff --git a/src/pic.c b/src/pic.c index 26918f3..b1110a4 100644 --- a/src/pic.c +++ b/src/pic.c @@ -36,6 +36,8 @@ void pic_reset() pic.mask2=0; pic2.pend=pic2.ins=0; pic_intpending = 0; + pic.level_sensitive = 0; + pic2.level_sensitive = 0; } void pic_update_mask(uint8_t *mask, uint8_t ins) @@ -275,6 +277,41 @@ void pic2_init() io_sethandler(0x00a0, 0x0002, pic2_read, NULL, NULL, pic2_write, NULL, NULL, NULL); } +static uint8_t pic_elcrx_read(uint16_t addr, void *p) +{ + uint8_t temp = 0xff; + + switch (addr) + { + case 0x4d0: + temp = pic.level_sensitive; + break; + case 0x4d1: + temp = pic2.level_sensitive; + break; + } + + return temp; +} + +static void pic_elcrx_write(uint16_t addr, uint8_t val, void *p) +{ +// pclog("pic_elcrx_write: addr=%04x val=%02x\n", addr, val); + switch (addr) + { + case 0x4d0: + pic.level_sensitive = val & 0xf8; + break; + case 0x4d1: + pic2.level_sensitive = val & 0xde; + break; + } +} + +void pic_init_elcrx() +{ + io_sethandler(0x04d0, 0x0002, pic_elcrx_read, NULL, NULL, pic_elcrx_write, NULL, NULL, NULL); +} void clearpic() { @@ -364,7 +401,8 @@ uint8_t picinterrupt() { if (temp & (1 << c)) { - pic.pend &= ~(1 << c); + if (!(pic.level_sensitive & (1 << c))) + pic.pend &= ~(1 << c); pic.ins |= (1 << c); pic_update_mask(&pic.mask2, pic.ins); @@ -385,11 +423,13 @@ uint8_t picinterrupt() { if (temp2 & (1 << c)) { - pic2.pend &= ~(1 << c); + if (!(pic2.level_sensitive & (1 << c))) + pic2.pend &= ~(1 << c); pic2.ins |= (1 << c); pic_update_mask(&pic2.mask2, pic2.ins); - pic.pend &= ~(1 << c); + if (!(pic2.level_sensitive & (1 << c))) + pic.pend &= ~(1 << c); pic.ins |= (1 << 2); /*Cascade IRQ*/ pic_update_mask(&pic.mask2, pic.ins); @@ -406,7 +446,8 @@ uint8_t picinterrupt() { if (temp & (1 << c)) { - pic.pend &= ~(1 << c); + if (!(pic.level_sensitive & (1 << c))) + pic.pend &= ~(1 << c); pic.ins |= (1 << c); pic_update_mask(&pic.mask2, pic.ins); pic_updatepending(); diff --git a/src/pic.h b/src/pic.h index e386313..1e129f3 100644 --- a/src/pic.h +++ b/src/pic.h @@ -1,5 +1,6 @@ void pic_init(); void pic2_init(); +void pic_init_elcrx(); void pic_reset(); void picint(uint16_t num); diff --git a/src/piix.c b/src/piix.c index b902419..342cce5 100644 --- a/src/piix.c +++ b/src/piix.c @@ -10,6 +10,7 @@ #include "io.h" #include "mem.h" #include "pci.h" +#include "pic.h" #include "piix.h" @@ -386,4 +387,6 @@ void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d) ide_pri_disable(); ide_sec_disable(); + + pic_init_elcrx(); } diff --git a/src/sis496.c b/src/sis496.c index a5ec77f..b958feb 100644 --- a/src/sis496.c +++ b/src/sis496.c @@ -4,6 +4,7 @@ #include "io.h" #include "mem.h" #include "pci.h" +#include "pic.h" #include "sis496.h" @@ -137,6 +138,8 @@ void *sis496_init() pci_set_card_routing(13, PCI_INTD); pci_set_card_routing(11, PCI_INTC); + pic_init_elcrx(); + return sis496; }