Overhauled SB DSP IRQ's and masking and also how it attaches to the MPU-401, fixes IBM OS/2 2.11 among other things.

This commit is contained in:
OBattler
2020-04-12 00:18:55 +02:00
parent ac5a993b3f
commit 28115c4650
6 changed files with 219 additions and 116 deletions

View File

@@ -72,8 +72,7 @@ typedef struct mpu_t
{
uint16_t addr;
int uart_mode, intelligent,
irq, irq_mask,
midi_thru,
irq, midi_thru,
queue_pos, queue_used;
uint8_t rx_data, is_mca,
status,
@@ -135,12 +134,15 @@ typedef struct mpu_t
uint16_t prchg_mask;
} filter;
struct {
int on;
uint8_t chan, trmask;
uint32_t key[4];
int on;
uint8_t chan, trmask;
uint32_t key[4];
} chanref[5], inputref[16];
pc_timer_t mpu401_event_callback, mpu401_eoi_callback,
mpu401_reset_callback;
void (*ext_irq_update)(void *priv, int set);
int (*ext_irq_pending)(void *priv);
void *priv;
} mpu_t;
extern int mpu401_standalone_enable, mpu401_already_loaded;
@@ -154,6 +156,7 @@ extern void mpu401_setirq(mpu_t *mpu, int irq);
extern void mpu401_change_addr(mpu_t *mpu, uint16_t addr);
extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input);
extern void mpu401_device_add(void);
extern void mpu401_irq_attach(mpu_t *mpu, void (*ext_irq_update)(void *priv, int set), int (*ext_irq_pending)(void *priv), void *priv);
extern int MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort);
extern void MPU401_InputMsg(void *p, uint8_t *msg);

View File

@@ -62,8 +62,8 @@ typedef struct sb_dsp_t
uint8_t sb_test;
int sb_timei, sb_timeo;
int sb_irq8, sb_irq16;
int sb_irqm8, sb_irqm16;
int sb_irq8, sb_irq16, sb_irq401;
int sb_irqm8, sb_irqm16, sb_irqm401;
uint8_t sb_asp_regs[256];
@@ -91,6 +91,8 @@ typedef struct sb_dsp_t
int pos;
uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; /* the eeprom in the Aztech cards is attached to the DSP */
mpu_t *mpu;
} sb_dsp_t;
@@ -98,7 +100,7 @@ void sb_dsp_input_msg(void *p, uint8_t *msg);
int sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort);
void sb_dsp_set_mpu(mpu_t *src_mpu);
void sb_dsp_set_mpu(sb_dsp_t *dsp, mpu_t *src_mpu);
void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent);
void sb_dsp_close(sb_dsp_t *dsp);
@@ -115,5 +117,6 @@ void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r);
void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo);
void sb_dsp_update(sb_dsp_t *dsp);
void sb_update_irq(sb_dsp_t *dsp);
#endif /* SOUND_SND_SB_DSP_H */

View File

@@ -1179,7 +1179,7 @@ azt_init(const device_t *info)
mpu401_init(azt2316a->mpu, azt2316a->cur_mpu401_addr, azt2316a->cur_mpu401_irq, M_UART, device_get_config_int("receive_input401"));
} else
azt2316a->mpu = NULL;
sb_dsp_set_mpu(azt2316a->mpu);
sb_dsp_set_mpu(&azt2316a->sb->dsp, azt2316a->mpu);
if (device_get_config_int("receive_input"))
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &azt2316a->sb->dsp);

View File

@@ -155,9 +155,13 @@ MPU401_QueueByteEx(mpu_t *mpu, uint8_t data, int irq)
return;
}
if ((mpu->queue_used == 0) && !mpu->irq_mask) {
mpu->state.irq_pending = 1;
picint(1 << mpu->irq);
if (mpu->queue_used == 0) {
if (mpu->ext_irq_update)
mpu->ext_irq_update(mpu->priv, 1);
else {
mpu->state.irq_pending = 1;
picint(1 << mpu->irq);
}
}
if (mpu->queue_used < MPU401_QUEUE) {
@@ -181,6 +185,20 @@ MPU401_QueueByte(mpu_t *mpu, uint8_t data)
}
static int
MPU401_IRQPending(mpu_t *mpu)
{
int irq_pending;
if (mpu->ext_irq_pending)
irq_pending = mpu->ext_irq_pending(mpu->priv);
else
irq_pending = mpu->state.irq_pending;
return irq_pending;
}
static void
MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, int block)
{
@@ -204,10 +222,14 @@ MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, int block)
}
if (mpu->queue_used == 0) {
if (mpu->state.rec_copy || mpu->state.irq_pending) {
if (mpu->state.irq_pending) {
picintc(1 << mpu->irq);
mpu->state.irq_pending = 0;
if (mpu->state.rec_copy || MPU401_IRQPending(mpu)) {
if (MPU401_IRQPending(mpu)) {
if (mpu->ext_irq_update)
mpu->ext_irq_update(mpu->priv, 0);
else {
mpu->state.irq_pending = 0;
picintc(1 << mpu->irq);
}
}
return;
}
@@ -229,7 +251,12 @@ MPU401_ClrQueue(mpu_t *mpu)
mpu->rec_queue_used = 0;
mpu->rec_queue_pos = 0;
mpu->state.sysex_in_finished = 1;
mpu->state.irq_pending = 0;
if (mpu->ext_irq_update)
mpu->ext_irq_update(mpu->priv, 0);
else {
mpu->state.irq_pending = 0;
picintc(1 << mpu->irq);
}
}
@@ -240,12 +267,20 @@ MPU401_Reset(mpu_t *mpu)
#ifdef DOSBOX_CODE
if (mpu->mode == M_INTELLIGENT) {
picintc(1 << mpu->irq);
mpu->state.irq_pending = 0;
if (mpu->ext_irq_update)
mpu->ext_irq_update(mpu->priv, 0);
else {
mpu->state.irq_pending = 0;
picintc(1 << mpu->irq);
}
}
#else
picintc(1 << mpu->irq);
mpu->state.irq_pending = 0;
if (mpu->ext_irq_update)
mpu->ext_irq_update(mpu->priv, 0);
else {
mpu->state.irq_pending = 0;
picintc(1 << mpu->irq);
}
#endif
mpu->mode = M_INTELLIGENT;
@@ -1037,10 +1072,15 @@ MPU401_EOIHandler(void *priv)
} else UpdateTrack(mpu, mpu->state.track);
}
if (mpu->state.rec_copy || !mpu->state.sysex_in_finished)
if (mpu->state.rec_copy || !mpu->state.sysex_in_finished)
return;
mpu->state.irq_pending = 0;
if (mpu->ext_irq_update)
mpu->ext_irq_update(mpu->priv, 0);
else {
mpu->state.irq_pending = 0;
picintc(1 << mpu->irq);
}
if (!(mpu->state.req_mask && mpu->clock.active))
return;
@@ -1081,13 +1121,21 @@ void
MPU401_ReadRaiseIRQ(mpu_t *mpu)
{
/* Clear IRQ. */
picintc(1 << mpu->irq);
mpu->state.irq_pending = 0;
if (mpu->ext_irq_update)
mpu->ext_irq_update(mpu->priv, 0);
else {
mpu->state.irq_pending = 0;
picintc(1 << mpu->irq);
}
if (mpu->queue_used && !mpu->irq_mask) {
if (mpu->queue_used) {
/* Bytes remaining in queue, raise IRQ again. */
mpu->state.irq_pending = 1;
picint(1 << mpu->irq);
if (mpu->ext_irq_update)
mpu->ext_irq_update(mpu->priv, 1);
else {
mpu->state.irq_pending = 1;
picint(1 << mpu->irq);
}
}
}
@@ -1234,7 +1282,8 @@ MPU401_Event(void *priv)
}
#endif
if (mpu->state.irq_pending) goto next_event;
if (MPU401_IRQPending(mpu))
goto next_event;
if (mpu->state.playing) {
for (i = 0; i < 8; i++) {
@@ -1287,7 +1336,8 @@ MPU401_Event(void *priv)
}
}
}
if (!mpu->state.irq_pending && mpu->state.req_mask)
if (MPU401_IRQPending(mpu) && mpu->state.req_mask)
MPU401_EOIHandler(mpu);
next_event:
@@ -1703,6 +1753,15 @@ mpu401_mca_feedb(void *p)
}
void
mpu401_irq_attach(mpu_t *mpu, void (*ext_irq_update)(void *priv, int set), int (*ext_irq_pending)(void *priv), void *priv)
{
mpu->ext_irq_update = ext_irq_update;
mpu->ext_irq_pending = ext_irq_pending;
mpu->priv = priv;
}
static void *
mpu401_standalone_init(const device_t *info)
{

View File

@@ -624,8 +624,7 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p)
mixer->regs[0x83] = 0xff;
sb->dsp.sb_irqm8 = 0;
sb->dsp.sb_irqm16 = 0;
if (sb->mpu != NULL)
sb->mpu->irq_mask = 0;
sb->dsp.sb_irqm401 = 0;
}
else
{
@@ -697,18 +696,9 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p)
case 0x83:
/* Interrupt mask. */
sb->dsp.sb_irqm8 = !(val & 0x01);
if (sb->dsp.sb_irqm8)
sb_irqc(&sb->dsp, 1);
sb->dsp.sb_irqm16 = !(val & 0x02);
if (sb->dsp.sb_irqm16)
sb_irqc(&sb->dsp, 0);
if (sb->mpu != NULL) {
sb->mpu->irq_mask = !(val & 0x04);
if (sb->mpu->irq_mask) {
picintc(1 << sb->mpu->irq);
sb->mpu->state.irq_pending = 0;
}
}
sb->dsp.sb_irqm401 = !(val & 0x04);
sb_update_irq(&sb->dsp);
break;
case 0x84:
@@ -721,6 +711,7 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p)
else if ((val & 0x06) == 0x02)
mpu401_change_addr(sb->mpu, 0);
}
break;
}
mixer->output_selector = mixer->regs[0x3C];
@@ -854,9 +845,8 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p)
case 0x82:
/* 0 = none, 1 = digital 8bit or SBMIDI, 2 = digital 16bit, 4 = MPU-401 */
/* 0x02000 DSP v4.04, 0x4000 DSP v4.05 0x8000 DSP v4.12. I haven't seen this making any difference, but I'm keeping it for now. */
temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | 0x4000;
if (sb->mpu)
temp |= ((sb->mpu->state.irq_pending) ? 4 : 0);
temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) |
((sb->dsp.sb_irq401) ? 4 : 0) | 0x4000;
ret = temp;
break;
@@ -1278,7 +1268,7 @@ void *sb_16_init(const device_t *info)
mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401"));
} else
sb->mpu = NULL;
sb_dsp_set_mpu(sb->mpu);
sb_dsp_set_mpu(&sb->dsp, sb->mpu);
if (device_get_config_int("receive_input"))
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
@@ -1322,7 +1312,7 @@ void *sb_awe32_init(const device_t *info)
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401"));
sb_dsp_set_mpu(sb->mpu);
sb_dsp_set_mpu(&sb->dsp, sb->mpu);
} else
sb->mpu = NULL;
emu8k_init(&sb->emu8k, emu_addr, onboard_ram);

View File

@@ -44,8 +44,6 @@ static int sbe2dat[4][9] = {
{ 0x01, -0x02, 0x04, -0x08, -0x10, 0x20, -0x40, 0x80, 90 }
};
static mpu_t *mpu;
static int sb_commands[256]=
{
-1, 2,-1,-1, 1, 2,-1, 0, 1,-1,-1,-1,-1,-1, 2, 1,
@@ -179,28 +177,81 @@ recalc_sb16_filter(int playback_freq)
}
void
sb_update_irq(sb_dsp_t *dsp)
{
int irq_pending;
irq_pending = (dsp->sb_irq8 && !dsp->sb_irqm8) ||
(dsp->sb_irq16 && !dsp->sb_irqm16) ||
(dsp->sb_irq401 && !dsp->sb_irq401);
if (irq_pending)
picint(1 << dsp->sb_irqnum);
else
picintc(1 << dsp->sb_irqnum);
}
void
sb_update_status(sb_dsp_t *dsp, int bit, int set)
{
switch (bit) {
case 0:
default:
dsp->sb_irq8 = set;
break;
case 1:
dsp->sb_irq16 = set;
break;
case 2:
dsp->sb_irq401 = set;
break;
}
sb_update_irq(dsp);
}
void
sb_irq(sb_dsp_t *dsp, int irq8)
{
sb_dsp_log("IRQ %i %02X\n", irq8, pic.mask);
if (irq8 && !dsp->sb_irqm8)
dsp->sb_irq8 = 1;
else if (!irq8 && !dsp->sb_irqm16)
dsp->sb_irq16 = 1;
picint(1 << dsp->sb_irqnum);
sb_update_status(dsp, !irq8, 1);
}
void
sb_irqc(sb_dsp_t *dsp, int irq8)
{
if (irq8)
dsp->sb_irq8 = 0;
else
dsp->sb_irq16 = 0;
sb_update_status(dsp, !irq8, 0);
}
picintc(1 << dsp->sb_irqnum);
static void
sb_dsp_irq_update(void *priv, int set)
{
sb_dsp_t *dsp = (sb_dsp_t *) priv;
sb_update_status(dsp, 2, set);
}
static int
sb_dsp_irq_pending(void *priv)
{
sb_dsp_t *dsp = (sb_dsp_t *) priv;
return dsp->sb_irq401;
}
void
sb_dsp_set_mpu(sb_dsp_t *dsp, mpu_t *mpu)
{
dsp->mpu = mpu;
if (mpu != NULL)
mpu401_irq_attach(mpu, sb_dsp_irq_update, sb_dsp_irq_pending, dsp);
}
@@ -217,8 +268,10 @@ sb_dsp_reset(sb_dsp_t *dsp)
dsp->sb_8_length = 0xffff;
dsp->sb_8_autolen = 0xffff;
sb_irqc(dsp, 0);
sb_irqc(dsp, 1);
dsp->sb_irq8 = 0;
dsp->sb_irq16 = 0;
dsp->sb_irq401 = 0;
sb_update_irq(dsp);
dsp->sb_16_pause = 0;
dsp->sb_read_wp = dsp->sb_read_rp = 0;
dsp->sb_data_stat = -1;
@@ -853,8 +906,8 @@ sb_read(uint16_t a, void *priv)
switch (a & 0xf) {
case 0xA: /* Read data */
if (mpu && dsp->uart_midi) {
ret = MPU401_ReadData(mpu);
if (dsp->mpu && dsp->uart_midi) {
ret = MPU401_ReadData(dsp->mpu);
} else {
dsp->sbreaddat = dsp->sb_read_data[dsp->sb_read_rp];
if (dsp->sb_read_rp != dsp->sb_read_wp) {
@@ -912,69 +965,64 @@ sb_read(uint16_t a, void *priv)
}
/* This should not even be needed. */
void
sb_dsp_set_mpu(mpu_t *src_mpu)
{
mpu = src_mpu;
}
void
sb_dsp_input_msg(void *p, uint8_t *msg)
{
sb_dsp_t *dsp = (sb_dsp_t *) p;
sb_dsp_t *dsp = (sb_dsp_t *) p;
uint8_t len = msg[3], i = 0;
sb_dsp_log("MIDI in sysex = %d, uart irq = %d, msg = %d\n", dsp->midi_in_sysex, dsp->uart_irq, msg[3]);
sb_dsp_log("MIDI in sysex = %d, uart irq = %d, msg = %d\n", dsp->midi_in_sysex, dsp->uart_irq, msg[3]);
if (!dsp->uart_irq && !dsp->midi_in_poll && (mpu != NULL)) {
MPU401_InputMsg(mpu, msg);
return;
}
if (!dsp->uart_irq && !dsp->midi_in_poll && (dsp->mpu != NULL)) {
MPU401_InputMsg(dsp->mpu, msg);
return;
}
if (dsp->midi_in_sysex) {
return;
}
if (dsp->midi_in_sysex)
return;
uint8_t len = msg[3];
uint8_t i = 0;
if (dsp->uart_irq) {
for (i=0;i<len;i++)
sb_add_data(dsp, msg[i]);
sb_dsp_log("SB IRQ8 = %d\n", dsp->sb_irq8);
if (!dsp->sb_irq8)
picint(1 << dsp->sb_irqnum);
} else if (dsp->midi_in_poll) {
for (i=0;i<len;i++)
sb_add_data(dsp, msg[i]);
}
if (dsp->uart_irq) {
for (i = 0; i < len; i++)
sb_add_data(dsp, msg[i]);
sb_irq(dsp, 1);
} else if (dsp->midi_in_poll) {
for (i = 0; i < len; i++)
sb_add_data(dsp, msg[i]);
}
}
int
sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
{
sb_dsp_t *dsp = (sb_dsp_t *) p;
sb_dsp_t *dsp = (sb_dsp_t *) p;
uint32_t i;
uint32_t i;
if (!dsp->uart_irq && !dsp->midi_in_poll && (dsp->mpu != NULL))
return MPU401_InputSysex(dsp->mpu, buffer, len, abort);
if (!dsp->uart_irq && !dsp->midi_in_poll && (mpu != NULL))
return MPU401_InputSysex(mpu, buffer, len, abort);
if (abort) {
dsp->midi_in_sysex = 0;
return 0;
}
dsp->midi_in_sysex = 1;
for (i=0;i<len;i++) {
if (dsp->sb_read_rp == dsp->sb_read_wp) {
sb_dsp_log("Length sysex SB = %d\n", len-i);
return (len-i);
}
sb_add_data(dsp, buffer[i]);
}
if (abort) {
dsp->midi_in_sysex = 0;
return 0;
}
dsp->midi_in_sysex = 1;
for (i = 0; i < len; i++) {
if (dsp->sb_read_rp == dsp->sb_read_wp) {
sb_dsp_log("Length sysex SB = %d\n", len - i);
return (len - i);
}
sb_add_data(dsp, buffer[i]);
}
dsp->midi_in_sysex = 0;
return 0;
}
void
sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent)
{
@@ -986,7 +1034,7 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent)
dsp->sb_irqnum = 7;
dsp->sb_8_dmanum = 1;
dsp->sb_16_dmanum = 5;
mpu = NULL;
dsp->mpu = NULL;
sb_doreset(dsp);