PCI and IRQ rework, pci.c rewritten from ground up, fixes numerous issues such as the bridge being added when the number of normal PCI devices equals the number of normal PCI slots, Windows 95 PCI operation on Intel 430NX, sharing of PCI IRQ's with non-PCI level-triggered devices, having both configuration mechanisms operating at the same time (ALi M1435), etc., and makes the code much more readable.

This commit is contained in:
OBattler
2023-08-07 03:04:52 +02:00
parent cb24ee27cb
commit c30d5d90b7
66 changed files with 1824 additions and 1643 deletions

View File

@@ -73,7 +73,8 @@ typedef struct _ac97_via_ {
uint8_t regs_linear[256];
};
} codec_shadow[2];
int slot;
uint8_t pci_slot;
uint8_t irq_state;
int irq_pin;
ac97_codec_t *codec[2][2];
@@ -115,8 +116,8 @@ ac97_via_set_slot(void *priv, int slot, int irq_pin)
ac97_via_log("AC97 VIA: set_slot(%d, %d)\n", slot, irq_pin);
dev->slot = slot;
dev->irq_pin = irq_pin;
dev->pci_slot = slot;
dev->irq_pin = irq_pin;
}
uint8_t
@@ -182,12 +183,12 @@ ac97_via_update_irqs(ac97_via_t *dev)
/* Stop immediately if any flag is set. Doing it this way optimizes
rising edges for the playback SGD (0 - first to be checked). */
if (dev->sgd_regs[i] & (dev->sgd_regs[i | 0x2] & 0x03)) {
pci_set_irq(dev->slot, dev->irq_pin);
pci_set_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state);
return;
}
}
pci_clear_irq(dev->slot, dev->irq_pin);
pci_clear_irq(dev->pci_slot, dev->irq_pin, &dev->irq_state);
}
static void

View File

@@ -53,6 +53,7 @@ typedef struct es1371_t {
uint32_t base_addr;
uint8_t int_line;
uint8_t irq_state;
uint16_t pmcsr;
@@ -120,7 +121,7 @@ typedef struct es1371_t {
int cd_vol_l;
int cd_vol_r;
int card;
uint8_t pci_slot;
int pos;
int16_t buffer[SOUNDBUFLEN * 2];
@@ -235,9 +236,9 @@ es1371_update_irqs(es1371_t *dev)
irq = 1;
if (irq)
pci_set_irq(dev->card, PCI_INTA);
pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
else
pci_clear_irq(dev->card, PCI_INTA);
pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
}
static void
@@ -2100,7 +2101,7 @@ es1371_init(const device_t *info)
dev->gameport = gameport_add(&gameport_pnp_device);
gameport_remap(dev->gameport, 0x200);
dev->card = pci_add_card(info->local ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, dev);
pci_add_card(info->local ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, dev, &dev->pci_slot);
timer_add(&dev->dac[1].timer, es1371_poll, dev, 1);

View File

@@ -97,7 +97,8 @@ typedef struct _cmi8x38_ {
uint16_t mpu_base;
uint8_t pci_regs[256];
uint8_t io_regs[256];
int slot;
uint8_t pci_slot;
uint8_t irq_state;
sb_t *sb;
void *gameport;
@@ -148,11 +149,11 @@ cmi8x38_update_irqs(cmi8x38_t *dev)
/* Calculate and use the INTR flag. */
if (*((uint32_t *) &dev->io_regs[0x10]) & 0x0401c003) {
dev->io_regs[0x13] |= 0x80;
pci_set_irq(dev->slot, PCI_INTA);
pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
cmi8x38_log("CMI8x38: Raising IRQ\n");
} else {
dev->io_regs[0x13] &= ~0x80;
pci_clear_irq(dev->slot, PCI_INTA);
pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
}
}
@@ -823,9 +824,9 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv)
/* Force IRQ if requested. Clearing this bit is undefined. */
if (val & 0x10)
pci_set_irq(dev->slot, PCI_INTA);
pci_set_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
else if ((dev->io_regs[0x17] & 0x10) && !(val & 0x10))
pci_clear_irq(dev->slot, PCI_INTA);
pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
/* Enable or disable I/O traps. */
dev->io_regs[addr] = val;
@@ -1473,7 +1474,7 @@ cmi8x38_init(const device_t *info)
}
/* Add PCI card. */
dev->slot = pci_add_card((info->local & (1 << 13)) ? PCI_ADD_SOUND : PCI_ADD_NORMAL, cmi8x38_pci_read, cmi8x38_pci_write, dev);
pci_add_card((info->local & (1 << 13)) ? PCI_ADD_SOUND : PCI_ADD_NORMAL, cmi8x38_pci_read, cmi8x38_pci_write, dev, &dev->pci_slot);
/* Perform initial reset. */
cmi8x38_reset(dev);

View File

@@ -98,6 +98,9 @@ typedef struct gus_t {
int irqnext;
uint8_t irq_state;
uint8_t midi_irq_state;
pc_timer_t timer_1;
pc_timer_t timer_2;
@@ -157,8 +160,10 @@ double vol16bit[4096];
void
gus_update_int_status(gus_t *gus)
{
int irq_pending = 0;
int midi_irq_pending = 0;
int irq_pending = 0;
int midi_irq_pending = 0;
int intr_pending = 0;
int midi_intr_pending = 0;
gus->irqstatus &= ~0x60;
gus->irqstatus2 = 0xE0;
@@ -187,24 +192,35 @@ gus_update_int_status(gus_t *gus)
midi_irq_pending = gus->midi_status & MIDI_INT_MASTER;
if (gus->irq == gus->irq_midi && gus->irq != -1) {
if (gus->irq == gus->irq_midi) {
if (irq_pending || midi_irq_pending)
picintlevel(1 << gus->irq);
intr_pending = 1;
else
picintc(1 << gus->irq);
intr_pending = 0;
} else {
if (gus->irq != -1) {
if (irq_pending)
picintlevel(1 << gus->irq);
else
picintc(1 << gus->irq);
}
if (gus->irq_midi != -1) {
if (midi_irq_pending)
picintlevel(1 << gus->irq_midi);
else
picintc(1 << gus->irq_midi);
}
if (irq_pending)
intr_pending = 1;
else
intr_pending = 0;
if (midi_irq_pending)
midi_intr_pending = 1;
else
midi_intr_pending = 0;
}
if (gus->irq != -1) {
if (intr_pending)
picintlevel(1 << gus->irq, &gus->irq_state);
else
picintclevel(1 << gus->irq, &gus->irq_state);
}
if (gus->irq_midi != -1) {
if (midi_intr_pending)
picintlevel(1 << gus->irq_midi, &gus->midi_irq_state);
else
picintclevel(1 << gus->irq_midi, &gus->midi_irq_state);
}
}
@@ -1174,6 +1190,103 @@ gus_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
return 0;
}
static void
gus_reset(void *p)
{
gus_t *gus = (gus_t *) p;
int c;
double out = 1.0;
if (gus == NULL)
return;
memset(gus->ram, 0x00, (gus->gus_end_ram));
for (c = 0; c < 32; c++) {
gus->ctrl[c] = 1;
gus->rctrl[c] = 1;
gus->rfreq[c] = 63 * 512;
}
for (c = 4095; c >= 0; c--) {
vol16bit[c] = out;
out /= 1.002709201; /* 0.0235 dB Steps */
}
gus->voices = 14;
gus->samp_latch = (uint64_t) (TIMER_USEC * (1000000.0 / 44100.0));
gus->t1l = gus->t2l = 0xff;
gus->global = 0;
gus->addr = 0;
gus->dmaaddr = 0;
gus->voice = 0;
memset(gus->start, 0x00, 32 * sizeof(uint32_t));
memset(gus->end, 0x00, 32 * sizeof(uint32_t));
memset(gus->cur, 0x00, 32 * sizeof(uint32_t));
memset(gus->startx, 0x00, 32 * sizeof(uint32_t));
memset(gus->endx, 0x00, 32 * sizeof(uint32_t));
memset(gus->curx, 0x00, 32 * sizeof(uint32_t));
memset(gus->rstart, 0x00, 32 * sizeof(int));
memset(gus->rend, 0x00, 32 * sizeof(int));
memset(gus->rcur, 0x00, 32 * sizeof(int));
memset(gus->freq, 0x00, 32 * sizeof(uint16_t));
memset(gus->curvol, 0x00, 32 * sizeof(int));
memset(gus->pan_l, 0x00, 32 * sizeof(int));
memset(gus->pan_r, 0x00, 32 * sizeof(int));
gus->t1on = 0;
gus->t2on = 0;
gus->tctrl = 0;
gus->t1 = 0;
gus->t2 = 0;
gus->irqstatus = 0;
gus->irqstatus2 = 0;
gus->adcommand = 0;
memset(gus->waveirqs, 0x00, 32 * sizeof(int));
memset(gus->rampirqs, 0x00, 32 * sizeof(int));
gus->dmactrl = 0;
gus->uart_out = 1;
gus->sb_2xa = 0;
gus->sb_2xc = 0;
gus->sb_2xe = 0;
gus->sb_ctrl = 0;
gus->sb_nmi = 0;
gus->reg_ctrl = 0;
gus->ad_status = 0;
gus->ad_data = 0;
gus->ad_timer_ctrl = 0;
gus->midi_ctrl = 0;
gus->midi_status = 0;
memset(gus->midi_queue, 0x00, 64 * sizeof(uint8_t));
gus->midi_data = 0;
gus->midi_r = 0;
gus->midi_w = 0;
gus->uart_in = 0;
gus->uart_out = 0;
gus->sysex = 0;
gus->gp1 = 0;
gus->gp2 = 0;
gus->gp1_addr = 0;
gus->gp2_addr = 0;
gus->usrr = 0;
gus->max_ctrl = 0;
gus->irq_state = 0;
gus->midi_irq_state = 0;
gus_update_int_status(gus);
}
void *
gus_init(UNUSED(const device_t *info))
{
@@ -1181,7 +1294,7 @@ gus_init(UNUSED(const device_t *info))
double out = 1.0;
uint8_t gus_ram = device_get_config_int("gus_ram");
gus_t *gus = malloc(sizeof(gus_t));
memset(gus, 0, sizeof(gus_t));
memset(gus, 0x00, sizeof(gus_t));
gus->gus_end_ram = 1 << (18 + gus_ram);
gus->ram = (uint8_t *) malloc(gus->gus_end_ram);
@@ -1359,7 +1472,7 @@ const device_t gus_device = {
.local = 0,
.init = gus_init,
.close = gus_close,
.reset = NULL,
.reset = gus_reset,
{ .available = NULL },
.speed_changed = gus_speed_changed,
.force_redraw = NULL,