1145 lines
43 KiB
C
1145 lines
43 KiB
C
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include "../86box.h"
|
|
#include "../ibm.h"
|
|
#include "../device.h"
|
|
#include "../io.h"
|
|
#include "../mem.h"
|
|
#include "../pci.h"
|
|
#include "../timer.h"
|
|
#include "sound.h"
|
|
#include "snd_audiopci.h"
|
|
|
|
|
|
typedef struct
|
|
{
|
|
uint8_t pci_command, pci_serr;
|
|
|
|
uint32_t base_addr;
|
|
|
|
uint8_t int_line;
|
|
|
|
uint16_t pmcsr;
|
|
|
|
uint32_t int_ctrl;
|
|
uint32_t int_status;
|
|
|
|
uint32_t legacy_ctrl;
|
|
|
|
int mem_page;
|
|
|
|
uint32_t si_cr;
|
|
|
|
uint32_t sr_cir;
|
|
uint16_t sr_ram[128];
|
|
|
|
uint8_t uart_ctrl;
|
|
uint8_t uart_status;
|
|
|
|
uint16_t codec_regs[64];
|
|
uint32_t codec_ctrl;
|
|
|
|
struct
|
|
{
|
|
uint32_t addr, addr_latch;
|
|
uint16_t count, size;
|
|
|
|
uint16_t samp_ct, curr_samp_ct;
|
|
|
|
int64_t time, latch;
|
|
|
|
uint32_t vf, ac;
|
|
|
|
int16_t buffer_l[64], buffer_r[64];
|
|
int buffer_pos, buffer_pos_end;
|
|
|
|
int16_t out_l, out_r;
|
|
|
|
int32_t vol_l, vol_r;
|
|
} dac[2], adc;
|
|
|
|
int64_t dac_latch, dac_time;
|
|
|
|
int master_vol_l, master_vol_r;
|
|
|
|
int card;
|
|
|
|
int pos;
|
|
int16_t buffer[SOUNDBUFLEN * 2];
|
|
} es1371_t;
|
|
|
|
#define LEGACY_SB_ADDR (1 << 29)
|
|
#define LEGACY_SSCAPE_ADDR_SHIFT 27
|
|
#define LEGACY_CODEC_ADDR_SHIFT 25
|
|
#define LEGACY_FORCE_IRQ (1 << 24)
|
|
#define LEGACY_CAPTURE_SLAVE_DMA (1 << 23)
|
|
#define LEGACY_CAPTURE_SLAVE_PIC (1 << 22)
|
|
#define LEGACY_CAPTURE_MASTER_DMA (1 << 21)
|
|
#define LEGACY_CAPTURE_MASTER_PIC (1 << 20)
|
|
#define LEGACY_CAPTURE_ADLIB (1 << 19)
|
|
#define LEGACY_CAPTURE_SB (1 << 18)
|
|
#define LEGACY_CAPTURE_CODEC (1 << 17)
|
|
#define LEGACY_CAPTURE_SSCAPE (1 << 16)
|
|
#define LEGACY_EVENT_SSCAPE (0 << 8)
|
|
#define LEGACY_EVENT_CODEC (1 << 8)
|
|
#define LEGACY_EVENT_SB (2 << 8)
|
|
#define LEGACY_EVENT_ADLIB (3 << 8)
|
|
#define LEGACY_EVENT_MASTER_PIC (4 << 8)
|
|
#define LEGACY_EVENT_MASTER_DMA (5 << 8)
|
|
#define LEGACY_EVENT_SLAVE_PIC (6 << 8)
|
|
#define LEGACY_EVENT_SLAVE_DMA (7 << 8)
|
|
#define LEGACY_EVENT_MASK (7 << 8)
|
|
#define LEGACY_EVENT_ADDR_SHIFT 3
|
|
#define LEGACY_EVENT_ADDR_MASK (0x1f << 3)
|
|
#define LEGACY_EVENT_TYPE_RW (1 << 2)
|
|
#define LEGACY_INT (1 << 0)
|
|
|
|
#define SRC_RAM_WE (1 << 24)
|
|
|
|
#define CODEC_READ (1 << 23)
|
|
#define CODEC_READY (1 << 31)
|
|
|
|
#define INT_DAC1_EN (1 << 6)
|
|
#define INT_DAC2_EN (1 << 5)
|
|
|
|
#define SI_P2_INTR_EN (1 << 9)
|
|
#define SI_P1_INTR_EN (1 << 8)
|
|
|
|
#define INT_STATUS_INTR (1 << 31)
|
|
#define INT_STATUS_DAC1 (1 << 2)
|
|
#define INT_STATUS_DAC2 (1 << 1)
|
|
|
|
#define FORMAT_MONO_8 0
|
|
#define FORMAT_STEREO_8 1
|
|
#define FORMAT_MONO_16 2
|
|
#define FORMAT_STEREO_16 3
|
|
|
|
const int32_t codec_attn[]=
|
|
{
|
|
25,32,41,51,65,82,103,130,164,206,260,327,412,519,653,
|
|
822,1036,1304,1641,2067,2602,3276,4125,5192,6537,8230,10362,13044,
|
|
16422,20674,26027,32767
|
|
};
|
|
|
|
static void es1371_fetch(es1371_t *es1371, int dac_nr);
|
|
static void update_legacy(es1371_t *es1371);
|
|
|
|
#ifdef ENABLE_AUDIOPCI_LOG
|
|
int audiopci_do_log = ENABLE_AUDIOPCI_LOG;
|
|
#endif
|
|
|
|
static void audiopci_log(const char *format, ...)
|
|
{
|
|
#ifdef ENABLE_AUDIOPCI_LOG
|
|
if (audiopci_do_log)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, format);
|
|
vprintf(format, ap);
|
|
va_end(ap);
|
|
fflush(stdout);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void es1371_update_irqs(es1371_t *es1371)
|
|
{
|
|
int irq = 0;
|
|
|
|
if ((es1371->int_status & INT_STATUS_DAC1) && (es1371->si_cr & SI_P1_INTR_EN))
|
|
irq = 1;
|
|
if ((es1371->int_status & INT_STATUS_DAC2) && (es1371->si_cr & SI_P2_INTR_EN))
|
|
irq = 1;
|
|
|
|
if (irq)
|
|
es1371->int_status |= INT_STATUS_INTR;
|
|
else
|
|
es1371->int_status &= ~INT_STATUS_INTR;
|
|
|
|
if (es1371->legacy_ctrl & LEGACY_FORCE_IRQ)
|
|
irq = 1;
|
|
|
|
if (irq)
|
|
{
|
|
pci_set_irq(es1371->card, PCI_INTA);
|
|
// audiopci_log("Raise IRQ\n");
|
|
}
|
|
else
|
|
{
|
|
pci_clear_irq(es1371->card, PCI_INTA);
|
|
// audiopci_log("Drop IRQ\n");
|
|
}
|
|
}
|
|
|
|
static uint8_t es1371_inb(uint16_t port, void *p)
|
|
{
|
|
es1371_t *es1371 = (es1371_t *)p;
|
|
uint8_t ret = 0;
|
|
|
|
switch (port & 0x3f)
|
|
{
|
|
case 0x00:
|
|
ret = es1371->int_ctrl & 0xff;
|
|
break;
|
|
case 0x01:
|
|
ret = (es1371->int_ctrl >> 8) & 0xff;
|
|
break;
|
|
case 0x02:
|
|
ret = (es1371->int_ctrl >> 16) & 0xff;
|
|
break;
|
|
case 0x03:
|
|
ret = (es1371->int_ctrl >> 24) & 0xff;
|
|
break;
|
|
|
|
case 0x04:
|
|
ret = es1371->int_status & 0xff;
|
|
break;
|
|
case 0x05:
|
|
ret = (es1371->int_status >> 8) & 0xff;
|
|
break;
|
|
case 0x06:
|
|
ret = (es1371->int_status >> 16) & 0xff;
|
|
break;
|
|
case 0x07:
|
|
ret = (es1371->int_status >> 24) & 0xff;
|
|
break;
|
|
|
|
|
|
case 0x09:
|
|
ret = es1371->uart_status;
|
|
break;
|
|
|
|
case 0x0c:
|
|
ret = es1371->mem_page;
|
|
break;
|
|
|
|
case 0x1a:
|
|
ret = es1371->legacy_ctrl >> 16;
|
|
break;
|
|
case 0x1b:
|
|
ret = es1371->legacy_ctrl >> 24;
|
|
break;
|
|
|
|
case 0x20:
|
|
ret = es1371->si_cr & 0xff;
|
|
break;
|
|
case 0x21:
|
|
ret = es1371->si_cr >> 8;
|
|
break;
|
|
case 0x22:
|
|
ret = (es1371->si_cr >> 16) | 0x80;
|
|
break;
|
|
case 0x23:
|
|
ret = 0xff;
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_inb: port=%04x\n", port);
|
|
}
|
|
|
|
// audiopci_log("es1371_inb: port=%04x ret=%02x\n", port, ret);
|
|
// output = 3;
|
|
return ret;
|
|
}
|
|
static uint16_t es1371_inw(uint16_t port, void *p)
|
|
{
|
|
es1371_t *es1371 = (es1371_t *)p;
|
|
uint16_t ret = 0;
|
|
|
|
switch (port & 0x3e)
|
|
{
|
|
case 0x00:
|
|
ret = es1371->int_ctrl & 0xffff;
|
|
break;
|
|
case 0x02:
|
|
ret = (es1371->int_ctrl >> 16) & 0xffff;
|
|
break;
|
|
|
|
case 0x18:
|
|
ret = es1371->legacy_ctrl & 0xffff;
|
|
// audiopci_log("Read legacy ctrl %04x\n", ret);
|
|
break;
|
|
|
|
case 0x26:
|
|
ret = es1371->dac[0].curr_samp_ct;
|
|
break;
|
|
|
|
case 0x2a:
|
|
ret = es1371->dac[1].curr_samp_ct;
|
|
break;
|
|
|
|
case 0x36:
|
|
switch (es1371->mem_page)
|
|
{
|
|
case 0xc:
|
|
ret = es1371->dac[0].count;
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_inw: mem_page=%x port=%04x\n", es1371->mem_page, port);
|
|
}
|
|
break;
|
|
|
|
case 0x3e:
|
|
switch (es1371->mem_page)
|
|
{
|
|
case 0xc:
|
|
ret = es1371->dac[1].count;
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_inw: mem_page=%x port=%04x\n", es1371->mem_page, port);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_inw: port=%04x\n", port);
|
|
}
|
|
|
|
// audiopci_log("es1371_inw: port=%04x ret=%04x %04x:%08x\n", port, ret, CS,cpu_state.pc);
|
|
return ret;
|
|
}
|
|
static uint32_t es1371_inl(uint16_t port, void *p)
|
|
{
|
|
es1371_t *es1371 = (es1371_t *)p;
|
|
uint32_t ret = 0;
|
|
|
|
switch (port & 0x3c)
|
|
{
|
|
case 0x00:
|
|
ret = es1371->int_ctrl;
|
|
break;
|
|
case 0x04:
|
|
ret = es1371->int_status;
|
|
break;
|
|
|
|
case 0x10:
|
|
ret = es1371->sr_cir & ~0xffff;
|
|
ret |= es1371->sr_ram[es1371->sr_cir >> 25];
|
|
break;
|
|
|
|
case 0x14:
|
|
ret = es1371->codec_ctrl & 0x00ff0000;
|
|
ret |= es1371->codec_regs[(es1371->codec_ctrl >> 16) & 0x3f];
|
|
ret |= CODEC_READY;
|
|
break;
|
|
|
|
case 0x34:
|
|
switch (es1371->mem_page)
|
|
{
|
|
|
|
case 0xc:
|
|
ret = es1371->dac[0].size | (es1371->dac[0].count << 16);
|
|
break;
|
|
|
|
case 0xd:
|
|
|
|
ret = es1371->adc.size | (es1371->adc.count << 16);
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port);
|
|
}
|
|
break;
|
|
|
|
case 0x3c:
|
|
switch (es1371->mem_page)
|
|
{
|
|
case 0xc:
|
|
ret = es1371->dac[1].size | (es1371->dac[1].count << 16);
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_inl: port=%04x\n", port);
|
|
}
|
|
|
|
// audiopci_log("es1371_inl: port=%04x ret=%08x %08x\n", port, ret, cpu_state.pc);
|
|
return ret;
|
|
}
|
|
|
|
static void es1371_outb(uint16_t port, uint8_t val, void *p)
|
|
{
|
|
es1371_t *es1371 = (es1371_t *)p;
|
|
|
|
// audiopci_log("es1371_outb: port=%04x val=%02x %04x:%08x\n", port, val, cs, cpu_state.pc);
|
|
switch (port & 0x3f)
|
|
{
|
|
case 0x00:
|
|
if (!(es1371->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN))
|
|
{
|
|
es1371->dac[0].addr = es1371->dac[0].addr_latch;
|
|
es1371->dac[0].buffer_pos = 0;
|
|
es1371->dac[0].buffer_pos_end = 0;
|
|
es1371_fetch(es1371, 0);
|
|
}
|
|
if (!(es1371->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN))
|
|
{
|
|
es1371->dac[1].addr = es1371->dac[1].addr_latch;
|
|
es1371->dac[1].buffer_pos = 0;
|
|
es1371->dac[1].buffer_pos_end = 0;
|
|
es1371_fetch(es1371, 1);
|
|
}
|
|
es1371->int_ctrl = (es1371->int_ctrl & 0xffffff00) | val;
|
|
break;
|
|
case 0x01:
|
|
es1371->int_ctrl = (es1371->int_ctrl & 0xffff00ff) | (val << 8);
|
|
break;
|
|
case 0x02:
|
|
es1371->int_ctrl = (es1371->int_ctrl & 0xff00ffff) | (val << 16);
|
|
break;
|
|
case 0x03:
|
|
es1371->int_ctrl = (es1371->int_ctrl & 0x00ffffff) | (val << 24);
|
|
break;
|
|
|
|
case 0x09:
|
|
es1371->uart_ctrl = val;
|
|
break;
|
|
|
|
case 0x0c:
|
|
es1371->mem_page = val & 0xf;
|
|
break;
|
|
|
|
case 0x18:
|
|
es1371->legacy_ctrl |= LEGACY_INT;
|
|
nmi = 0;
|
|
break;
|
|
case 0x1a:
|
|
es1371->legacy_ctrl = (es1371->legacy_ctrl & 0xff00ffff) | (val << 16);
|
|
update_legacy(es1371);
|
|
break;
|
|
case 0x1b:
|
|
es1371->legacy_ctrl = (es1371->legacy_ctrl & 0x00ffffff) | (val << 24);
|
|
es1371_update_irqs(es1371);
|
|
// output = 3;
|
|
update_legacy(es1371);
|
|
break;
|
|
|
|
case 0x20:
|
|
es1371->si_cr = (es1371->si_cr & 0xffff00) | val;
|
|
break;
|
|
case 0x21:
|
|
es1371->si_cr = (es1371->si_cr & 0xff00ff) | (val << 8);
|
|
if (!(es1371->si_cr & SI_P1_INTR_EN))
|
|
es1371->int_status &= ~INT_STATUS_DAC1;
|
|
if (!(es1371->si_cr & SI_P2_INTR_EN))
|
|
es1371->int_status &= ~INT_STATUS_DAC2;
|
|
es1371_update_irqs(es1371);
|
|
break;
|
|
case 0x22:
|
|
es1371->si_cr = (es1371->si_cr & 0x00ffff) | (val << 16);
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_outb: port=%04x val=%02x\n", port, val);
|
|
}
|
|
}
|
|
static void es1371_outw(uint16_t port, uint16_t val, void *p)
|
|
{
|
|
es1371_t *es1371 = (es1371_t *)p;
|
|
|
|
// audiopci_log("es1371_outw: port=%04x val=%04x\n", port, val);
|
|
switch (port & 0x3f)
|
|
{
|
|
case 0x0c:
|
|
es1371->mem_page = val & 0xf;
|
|
break;
|
|
|
|
case 0x24:
|
|
es1371->dac[0].samp_ct = val;
|
|
break;
|
|
|
|
case 0x28:
|
|
es1371->dac[1].samp_ct = val;
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_outw: port=%04x val=%04x\n", port, val);
|
|
}
|
|
}
|
|
static void es1371_outl(uint16_t port, uint32_t val, void *p)
|
|
{
|
|
es1371_t *es1371 = (es1371_t *)p;
|
|
|
|
// audiopci_log("es1371_outl: port=%04x val=%08x %04x:%08x\n", port, val, CS, cpu_state.pc);
|
|
switch (port & 0x3f)
|
|
{
|
|
case 0x04:
|
|
break;
|
|
|
|
case 0x0c:
|
|
es1371->mem_page = val & 0xf;
|
|
break;
|
|
|
|
case 0x10:
|
|
es1371->sr_cir = val;
|
|
if (es1371->sr_cir & SRC_RAM_WE)
|
|
{
|
|
// audiopci_log("Write SR RAM %02x %04x\n", es1371->sr_cir >> 25, val & 0xffff);
|
|
es1371->sr_ram[es1371->sr_cir >> 25] = val & 0xffff;
|
|
switch (es1371->sr_cir >> 25)
|
|
{
|
|
case 0x71:
|
|
es1371->dac[0].vf = (es1371->dac[0].vf & ~0x1f8000) | ((val & 0xfc00) << 5);
|
|
es1371->dac[0].ac = (es1371->dac[0].ac & ~0x7f8000) | ((val & 0x00ff) << 15);
|
|
break;
|
|
case 0x72:
|
|
es1371->dac[0].ac = (es1371->dac[0].ac & ~0x7fff) | (val & 0x7fff);
|
|
break;
|
|
case 0x73:
|
|
es1371->dac[0].vf = (es1371->dac[0].vf & ~0x7fff) | (val & 0x7fff);
|
|
break;
|
|
|
|
case 0x75:
|
|
es1371->dac[1].vf = (es1371->dac[1].vf & ~0x1f8000) | ((val & 0xfc00) << 5);
|
|
es1371->dac[1].ac = (es1371->dac[1].ac & ~0x7f8000) | ((val & 0x00ff) << 15);
|
|
break;
|
|
case 0x76:
|
|
es1371->dac[1].ac = (es1371->dac[1].ac & ~0x7fff) | (val & 0x7fff);
|
|
break;
|
|
case 0x77:
|
|
es1371->dac[1].vf = (es1371->dac[1].vf & ~0x7fff) | (val & 0x7fff);
|
|
break;
|
|
|
|
case 0x7c:
|
|
es1371->dac[0].vol_l = (int32_t)(int16_t)(val & 0xffff);
|
|
break;
|
|
case 0x7d:
|
|
es1371->dac[0].vol_r = (int32_t)(int16_t)(val & 0xffff);
|
|
break;
|
|
case 0x7e:
|
|
es1371->dac[1].vol_l = (int32_t)(int16_t)(val & 0xffff);
|
|
break;
|
|
case 0x7f:
|
|
es1371->dac[1].vol_r = (int32_t)(int16_t)(val & 0xffff);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0x14:
|
|
es1371->codec_ctrl = val;
|
|
if (!(val & CODEC_READ))
|
|
{
|
|
// audiopci_log("Write codec %02x %04x\n", (val >> 16) & 0x3f, val & 0xffff);
|
|
es1371->codec_regs[(val >> 16) & 0x3f] = val & 0xffff;
|
|
switch ((val >> 16) & 0x3f)
|
|
{
|
|
case 0x02: /*Master volume*/
|
|
if (val & 0x8000)
|
|
es1371->master_vol_l = es1371->master_vol_r = 0;
|
|
else
|
|
{
|
|
if (val & 0x2000)
|
|
es1371->master_vol_l = codec_attn[0];
|
|
else
|
|
es1371->master_vol_l = codec_attn[0x1f - ((val >> 8) & 0x1f)];
|
|
if (val & 0x20)
|
|
es1371->master_vol_r = codec_attn[0];
|
|
else
|
|
es1371->master_vol_r = codec_attn[0x1f - (val & 0x1f)];
|
|
}
|
|
break;
|
|
case 0x12: /*CD volume*/
|
|
if (val & 0x8000)
|
|
sound_set_cd_volume(0, 0);
|
|
else
|
|
sound_set_cd_volume(codec_attn[0x1f - ((val >> 8) & 0x1f)] * 2, codec_attn[0x1f - (val & 0x1f)] * 2);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0x24:
|
|
es1371->dac[0].samp_ct = val & 0xffff;
|
|
break;
|
|
|
|
case 0x28:
|
|
es1371->dac[1].samp_ct = val & 0xffff;
|
|
break;
|
|
|
|
case 0x30:
|
|
switch (es1371->mem_page)
|
|
{
|
|
case 0x0: case 0x1: case 0x2: case 0x3:
|
|
case 0x4: case 0x5: case 0x6: case 0x7:
|
|
case 0x8: case 0x9: case 0xa: case 0xb:
|
|
break;
|
|
|
|
case 0xc:
|
|
es1371->dac[0].addr_latch = val;
|
|
// audiopci_log("DAC1 addr %08x\n", val);
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val);
|
|
}
|
|
break;
|
|
case 0x34:
|
|
switch (es1371->mem_page)
|
|
{
|
|
case 0x0: case 0x1: case 0x2: case 0x3:
|
|
case 0x4: case 0x5: case 0x6: case 0x7:
|
|
case 0x8: case 0x9: case 0xa: case 0xb:
|
|
break;
|
|
|
|
case 0xc:
|
|
es1371->dac[0].size = val & 0xffff;
|
|
es1371->dac[0].count = val >> 16;
|
|
if (es1371->dac[0].count)
|
|
es1371->dac[0].count -= 4;
|
|
break;
|
|
|
|
case 0xd:
|
|
es1371->adc.size = val & 0xffff;
|
|
es1371->adc.count = val >> 16;
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val);
|
|
}
|
|
break;
|
|
case 0x38:
|
|
switch (es1371->mem_page)
|
|
{
|
|
case 0x0: case 0x1: case 0x2: case 0x3:
|
|
case 0x4: case 0x5: case 0x6: case 0x7:
|
|
case 0x8: case 0x9: case 0xa: case 0xb:
|
|
break;
|
|
|
|
case 0xc:
|
|
es1371->dac[1].addr_latch = val;
|
|
break;
|
|
|
|
case 0xd:
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val);
|
|
}
|
|
break;
|
|
case 0x3c:
|
|
switch (es1371->mem_page)
|
|
{
|
|
case 0x0: case 0x1: case 0x2: case 0x3:
|
|
case 0x4: case 0x5: case 0x6: case 0x7:
|
|
case 0x8: case 0x9: case 0xa: case 0xb:
|
|
break;
|
|
|
|
case 0xc:
|
|
es1371->dac[1].size = val & 0xffff;
|
|
es1371->dac[1].count = val >> 16;
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
audiopci_log("Bad es1371_outl: port=%04x val=%08x\n", port, val);
|
|
}
|
|
}
|
|
|
|
static void capture_event(es1371_t *es1371, int type, int rw, uint16_t port)
|
|
{
|
|
es1371->legacy_ctrl &= ~(LEGACY_EVENT_MASK | LEGACY_EVENT_ADDR_MASK);
|
|
es1371->legacy_ctrl |= type;
|
|
if (rw)
|
|
es1371->legacy_ctrl |= LEGACY_EVENT_TYPE_RW;
|
|
else
|
|
es1371->legacy_ctrl &= ~LEGACY_EVENT_TYPE_RW;
|
|
es1371->legacy_ctrl |= ((port << LEGACY_EVENT_ADDR_SHIFT) & LEGACY_EVENT_ADDR_MASK);
|
|
es1371->legacy_ctrl &= ~LEGACY_INT;
|
|
nmi = 1;
|
|
// audiopci_log("Event! %s %04x\n", rw ? "write" : "read", port);
|
|
}
|
|
|
|
static void capture_write_sscape(uint16_t port, uint8_t val, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_SSCAPE, 1, port);
|
|
}
|
|
static void capture_write_codec(uint16_t port, uint8_t val, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_CODEC, 1, port);
|
|
}
|
|
static void capture_write_sb(uint16_t port, uint8_t val, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_SB, 1, port);
|
|
}
|
|
static void capture_write_adlib(uint16_t port, uint8_t val, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_ADLIB, 1, port);
|
|
}
|
|
static void capture_write_master_pic(uint16_t port, uint8_t val, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_MASTER_PIC, 1, port);
|
|
}
|
|
static void capture_write_master_dma(uint16_t port, uint8_t val, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_MASTER_DMA, 1, port);
|
|
}
|
|
static void capture_write_slave_pic(uint16_t port, uint8_t val, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_SLAVE_PIC, 1, port);
|
|
}
|
|
static void capture_write_slave_dma(uint16_t port, uint8_t val, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_SLAVE_DMA, 1, port);
|
|
}
|
|
|
|
static uint8_t capture_read_sscape(uint16_t port, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_SSCAPE, 0, port);
|
|
return 0xff;
|
|
}
|
|
static uint8_t capture_read_codec(uint16_t port, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_CODEC, 0, port);
|
|
return 0xff;
|
|
}
|
|
static uint8_t capture_read_sb(uint16_t port, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_SB, 0, port);
|
|
return 0xff;
|
|
}
|
|
static uint8_t capture_read_adlib(uint16_t port, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_ADLIB, 0, port);
|
|
return 0xff;
|
|
}
|
|
static uint8_t capture_read_master_pic(uint16_t port, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_MASTER_PIC, 0, port);
|
|
return 0xff;
|
|
}
|
|
static uint8_t capture_read_master_dma(uint16_t port, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_MASTER_DMA, 0, port);
|
|
return 0xff;
|
|
}
|
|
static uint8_t capture_read_slave_pic(uint16_t port, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_SLAVE_PIC, 0, port);
|
|
return 0xff;
|
|
}
|
|
static uint8_t capture_read_slave_dma(uint16_t port, void *p)
|
|
{
|
|
capture_event(p, LEGACY_EVENT_SLAVE_DMA, 0, port);
|
|
return 0xff;
|
|
}
|
|
|
|
static void update_legacy(es1371_t *es1371)
|
|
{
|
|
io_removehandler(0x0320, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371);
|
|
io_removehandler(0x0330, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371);
|
|
io_removehandler(0x0340, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371);
|
|
io_removehandler(0x0350, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371);
|
|
|
|
io_removehandler(0x5300, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371);
|
|
io_removehandler(0xe800, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371);
|
|
io_removehandler(0xf400, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371);
|
|
|
|
io_removehandler(0x0220, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371);
|
|
io_removehandler(0x0240, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371);
|
|
|
|
io_removehandler(0x0388, 0x0004, capture_read_adlib,NULL,NULL, capture_write_adlib,NULL,NULL, es1371);
|
|
|
|
io_removehandler(0x0020, 0x0002, capture_read_master_pic,NULL,NULL, capture_write_master_pic,NULL,NULL, es1371);
|
|
io_removehandler(0x0000, 0x0010, capture_read_master_dma,NULL,NULL, capture_write_master_dma,NULL,NULL, es1371);
|
|
io_removehandler(0x00a0, 0x0002, capture_read_slave_pic,NULL,NULL, capture_write_slave_pic,NULL,NULL, es1371);
|
|
io_removehandler(0x00c0, 0x0020, capture_read_slave_dma,NULL,NULL, capture_write_slave_dma,NULL,NULL, es1371);
|
|
|
|
if (es1371->legacy_ctrl & LEGACY_CAPTURE_SSCAPE)
|
|
{
|
|
switch ((es1371->legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3)
|
|
{
|
|
case 0: io_sethandler(0x0320, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
|
|
case 1: io_sethandler(0x0330, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
|
|
case 2: io_sethandler(0x0340, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
|
|
case 3: io_sethandler(0x0350, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break;
|
|
}
|
|
}
|
|
if (es1371->legacy_ctrl & LEGACY_CAPTURE_CODEC)
|
|
{
|
|
switch ((es1371->legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3)
|
|
{
|
|
case 0: io_sethandler(0x5300, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break;
|
|
case 2: io_sethandler(0xe800, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break;
|
|
case 3: io_sethandler(0xf400, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break;
|
|
}
|
|
}
|
|
if (es1371->legacy_ctrl & LEGACY_CAPTURE_SB)
|
|
{
|
|
if (!(es1371->legacy_ctrl & LEGACY_SB_ADDR))
|
|
io_sethandler(0x0220, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371);
|
|
else
|
|
io_sethandler(0x0240, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371);
|
|
}
|
|
if (es1371->legacy_ctrl & LEGACY_CAPTURE_ADLIB)
|
|
io_sethandler(0x0388, 0x0004, capture_read_adlib,NULL,NULL, capture_write_adlib,NULL,NULL, es1371);
|
|
if (es1371->legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC)
|
|
io_sethandler(0x0020, 0x0002, capture_read_master_pic,NULL,NULL, capture_write_master_pic,NULL,NULL, es1371);
|
|
if (es1371->legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA)
|
|
io_sethandler(0x0000, 0x0010, capture_read_master_dma,NULL,NULL, capture_write_master_dma,NULL,NULL, es1371);
|
|
if (es1371->legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC)
|
|
io_sethandler(0x00a0, 0x0002, capture_read_slave_pic,NULL,NULL, capture_write_slave_pic,NULL,NULL, es1371);
|
|
if (es1371->legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA)
|
|
io_sethandler(0x00c0, 0x0020, capture_read_slave_dma,NULL,NULL, capture_write_slave_dma,NULL,NULL, es1371);
|
|
}
|
|
|
|
|
|
static uint8_t es1371_pci_read(int func, int addr, void *p)
|
|
{
|
|
es1371_t *es1371 = (es1371_t *)p;
|
|
|
|
if (func)
|
|
return 0;
|
|
|
|
//audiopci_log("ES1371 PCI read %08X PC=%08x\n", addr, cpu_state.pc);
|
|
|
|
switch (addr)
|
|
{
|
|
case 0x00: return 0x74; /*Ensoniq*/
|
|
case 0x01: return 0x12;
|
|
|
|
case 0x02: return 0x71; /*ES1371*/
|
|
case 0x03: return 0x13;
|
|
|
|
case 0x04: return es1371->pci_command;
|
|
case 0x05: return es1371->pci_serr;
|
|
|
|
case 0x06: return 0x10; /*Supports ACPI*/
|
|
case 0x07: return 0;
|
|
|
|
case 0x08: return 2; /*Revision ID*/
|
|
case 0x09: return 0x00; /*Multimedia audio device*/
|
|
case 0x0a: return 0x01;
|
|
case 0x0b: return 0x04;
|
|
|
|
case 0x10: return 0x01 | (es1371->base_addr & 0xc0); /*memBaseAddr*/
|
|
case 0x11: return es1371->base_addr >> 8;
|
|
case 0x12: return es1371->base_addr >> 16;
|
|
case 0x13: return es1371->base_addr >> 24;
|
|
|
|
case 0x2c: return 0x74; /*Subsystem vendor ID*/
|
|
case 0x2d: return 0x12;
|
|
case 0x2e: return 0x71;
|
|
case 0x2f: return 0x13;
|
|
|
|
case 0x34: return 0xdc; /*Capabilites pointer*/
|
|
|
|
case 0x3c: return es1371->int_line;
|
|
case 0x3d: return 0x01; /*INTA*/
|
|
|
|
case 0x3e: return 0xc; /*Minimum grant*/
|
|
case 0x3f: return 0x80; /*Maximum latency*/
|
|
|
|
case 0xdc: return 0x01; /*Capabilities identifier*/
|
|
case 0xdd: return 0x00; /*Next item pointer*/
|
|
case 0xde: return 0x31; /*Power management capabilities*/
|
|
case 0xdf: return 0x6c;
|
|
|
|
case 0xe0: return es1371->pmcsr & 0xff;
|
|
case 0xe1: return es1371->pmcsr >> 8;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void es1371_pci_write(int func, int addr, uint8_t val, void *p)
|
|
{
|
|
es1371_t *es1371 = (es1371_t *)p;
|
|
|
|
if (func)
|
|
return;
|
|
|
|
// audiopci_log("ES1371 PCI write %04X %02X PC=%08x\n", addr, val, cpu_state.pc);
|
|
|
|
switch (addr)
|
|
{
|
|
case 0x04:
|
|
if (es1371->pci_command & PCI_COMMAND_IO)
|
|
io_removehandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371);
|
|
es1371->pci_command = val & 0x05;
|
|
if (es1371->pci_command & PCI_COMMAND_IO)
|
|
io_sethandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371);
|
|
break;
|
|
case 0x05:
|
|
es1371->pci_serr = val & 1;
|
|
break;
|
|
|
|
case 0x10:
|
|
if (es1371->pci_command & PCI_COMMAND_IO)
|
|
io_removehandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371);
|
|
es1371->base_addr = (es1371->base_addr & 0xffffff00) | (val & 0xc0);
|
|
if (es1371->pci_command & PCI_COMMAND_IO)
|
|
io_sethandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371);
|
|
break;
|
|
case 0x11:
|
|
if (es1371->pci_command & PCI_COMMAND_IO)
|
|
io_removehandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371);
|
|
es1371->base_addr = (es1371->base_addr & 0xffff00c0) | (val << 8);
|
|
if (es1371->pci_command & PCI_COMMAND_IO)
|
|
io_sethandler(es1371->base_addr, 0x0040, es1371_inb, es1371_inw, es1371_inl, es1371_outb, es1371_outw, es1371_outl, es1371);
|
|
break;
|
|
case 0x12:
|
|
es1371->base_addr = (es1371->base_addr & 0xff00ffc0) | (val << 16);
|
|
break;
|
|
case 0x13:
|
|
es1371->base_addr = (es1371->base_addr & 0x00ffffc0) | (val << 24);
|
|
break;
|
|
|
|
case 0x3c:
|
|
es1371->int_line = val;
|
|
break;
|
|
|
|
case 0xe0:
|
|
es1371->pmcsr = (es1371->pmcsr & 0xff00) | (val & 0x03);
|
|
break;
|
|
case 0xe1:
|
|
es1371->pmcsr = (es1371->pmcsr & 0x00ff) | ((val & 0x01) << 8);
|
|
break;
|
|
}
|
|
// audiopci_log("es1371->base_addr %08x\n", es1371->base_addr);
|
|
}
|
|
|
|
static void es1371_fetch(es1371_t *es1371, int dac_nr)
|
|
{
|
|
int format = dac_nr ? ((es1371->si_cr >> 2) & 3) : (es1371->si_cr & 3);
|
|
int pos = es1371->dac[dac_nr].buffer_pos & 63;
|
|
int c;
|
|
|
|
//audiopci_log("Fetch format=%i %08x %08x %08x %08x %08x\n", format, es1371->dac[dac_nr].count, es1371->dac[dac_nr].size, es1371->dac[dac_nr].curr_samp_ct,es1371->dac[dac_nr].samp_ct, es1371->dac[dac_nr].addr);
|
|
switch (format)
|
|
{
|
|
case FORMAT_MONO_8:
|
|
for (c = 0; c < 32; c += 4)
|
|
{
|
|
es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr) ^ 0x80) << 8;
|
|
es1371->dac[dac_nr].buffer_l[(pos+c+1) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr+1) ^ 0x80) << 8;
|
|
es1371->dac[dac_nr].buffer_l[(pos+c+2) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+2) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr+2) ^ 0x80) << 8;
|
|
es1371->dac[dac_nr].buffer_l[(pos+c+3) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+3) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr+3) ^ 0x80) << 8;
|
|
es1371->dac[dac_nr].addr += 4;
|
|
|
|
es1371->dac[dac_nr].buffer_pos_end += 4;
|
|
es1371->dac[dac_nr].count++;
|
|
if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size)
|
|
{
|
|
es1371->dac[dac_nr].count = 0;
|
|
es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case FORMAT_STEREO_8:
|
|
for (c = 0; c < 16; c += 2)
|
|
{
|
|
es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr) ^ 0x80) << 8;
|
|
es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr + 1) ^ 0x80) << 8;
|
|
es1371->dac[dac_nr].buffer_l[(pos+c+1) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr + 2) ^ 0x80) << 8;
|
|
es1371->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(es1371->dac[dac_nr].addr + 3) ^ 0x80) << 8;
|
|
es1371->dac[dac_nr].addr += 4;
|
|
|
|
es1371->dac[dac_nr].buffer_pos_end += 2;
|
|
es1371->dac[dac_nr].count++;
|
|
if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size)
|
|
{
|
|
es1371->dac[dac_nr].count = 0;
|
|
es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case FORMAT_MONO_16:
|
|
for (c = 0; c < 16; c += 2)
|
|
{
|
|
es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr);
|
|
es1371->dac[dac_nr].buffer_l[(pos+c+1) & 63] = es1371->dac[dac_nr].buffer_r[(pos+c+1) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr + 2);
|
|
es1371->dac[dac_nr].addr += 4;
|
|
|
|
es1371->dac[dac_nr].buffer_pos_end += 2;
|
|
es1371->dac[dac_nr].count++;
|
|
if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size)
|
|
{
|
|
es1371->dac[dac_nr].count = 0;
|
|
es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case FORMAT_STEREO_16:
|
|
for (c = 0; c < 4; c++)
|
|
{
|
|
es1371->dac[dac_nr].buffer_l[(pos+c) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr);
|
|
es1371->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(es1371->dac[dac_nr].addr + 2);
|
|
// audiopci_log("Fetch %02x %08x %04x %04x\n", (pos+c) & 63, es1371->dac[dac_nr].addr, es1371->dac[dac_nr].buffer_l[(pos+c) & 63], es1371->dac[dac_nr].buffer_r[(pos+c) & 63]);
|
|
es1371->dac[dac_nr].addr += 4;
|
|
|
|
es1371->dac[dac_nr].buffer_pos_end++;
|
|
es1371->dac[dac_nr].count++;
|
|
if (es1371->dac[dac_nr].count > es1371->dac[dac_nr].size)
|
|
{
|
|
es1371->dac[dac_nr].count = 0;
|
|
es1371->dac[dac_nr].addr = es1371->dac[dac_nr].addr_latch;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void es1371_next_sample(es1371_t *es1371, int dac_nr)
|
|
{
|
|
if ((es1371->dac[dac_nr].buffer_pos - es1371->dac[dac_nr].buffer_pos_end) >= 0)
|
|
{
|
|
es1371_fetch(es1371, dac_nr);
|
|
}
|
|
|
|
es1371->dac[dac_nr].out_l = es1371->dac[dac_nr].buffer_l[es1371->dac[dac_nr].buffer_pos & 63];
|
|
es1371->dac[dac_nr].out_r = es1371->dac[dac_nr].buffer_r[es1371->dac[dac_nr].buffer_pos & 63];
|
|
// audiopci_log("Use %02x %04x %04x\n", es1371->dac[dac_nr].buffer_pos & 63, es1371->dac[dac_nr].out_l, es1371->dac[dac_nr].out_r);
|
|
|
|
es1371->dac[dac_nr].buffer_pos++;
|
|
// audiopci_log("Next sample %08x %08x %08x\n", es1371->dac[dac_nr].buffer_pos, es1371->dac[dac_nr].buffer_pos_end, es1371->dac[dac_nr].curr_samp_ct);
|
|
}
|
|
|
|
//static FILE *es1371_f;//,*es1371_f2;
|
|
static void es1371_poll(void *p)
|
|
{
|
|
es1371_t *es1371 = (es1371_t *)p;
|
|
|
|
es1371->dac[1].time += es1371->dac[1].latch;
|
|
|
|
if (es1371->int_ctrl & INT_DAC1_EN)
|
|
{
|
|
// audiopci_log("1Samp %i %i %08x\n", es1371->dac[0].curr_samp_ct, es1371->dac[0].samp_ct, es1371->dac[0].ac);
|
|
es1371->dac[0].ac += es1371->dac[0].vf;
|
|
if (es1371->dac[0].ac & (~0 << (15+4)))
|
|
{
|
|
es1371->dac[0].ac &= ~(~0 << (15+4));
|
|
es1371_next_sample(es1371, 0);
|
|
|
|
es1371->dac[0].curr_samp_ct++;
|
|
if (es1371->dac[0].curr_samp_ct == es1371->dac[0].samp_ct)
|
|
{
|
|
// audiopci_log("DAC1 IRQ\n");
|
|
es1371->int_status |= INT_STATUS_DAC1;
|
|
es1371_update_irqs(es1371);
|
|
}
|
|
if (es1371->dac[0].curr_samp_ct > es1371->dac[0].samp_ct)
|
|
{
|
|
es1371->dac[0].curr_samp_ct = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (es1371->int_ctrl & INT_DAC2_EN)
|
|
{
|
|
// audiopci_log("2Samp %i %i %08x\n", es1371->dac[1].curr_samp_ct, es1371->dac[1].samp_ct, es1371->dac[1].ac);
|
|
es1371->dac[1].ac += es1371->dac[1].vf;
|
|
if (es1371->dac[1].ac & (~0 << (15+4)))
|
|
{
|
|
es1371->dac[1].ac &= ~(~0 << (15+4));
|
|
es1371_next_sample(es1371, 1);
|
|
|
|
es1371->dac[1].curr_samp_ct++;
|
|
if (es1371->dac[1].curr_samp_ct > es1371->dac[1].samp_ct)
|
|
{
|
|
es1371->dac[1].curr_samp_ct = 0;
|
|
// audiopci_log("DAC2 IRQ\n");
|
|
es1371->int_status |= INT_STATUS_DAC2;
|
|
es1371_update_irqs(es1371);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (; es1371->pos < sound_pos_global; es1371->pos++)
|
|
{
|
|
int32_t l, r;
|
|
|
|
l = (es1371->dac[0].out_l * es1371->dac[0].vol_l) >> 12;
|
|
l += ((es1371->dac[1].out_l * es1371->dac[1].vol_l) >> 12);
|
|
r = (es1371->dac[0].out_r * es1371->dac[0].vol_r) >> 12;
|
|
r += ((es1371->dac[1].out_r * es1371->dac[1].vol_r) >> 12);
|
|
|
|
l >>= 1;
|
|
r >>= 1;
|
|
|
|
l = (l * es1371->master_vol_l) >> 15;
|
|
r = (r * es1371->master_vol_r) >> 15;
|
|
|
|
if (l < -32768)
|
|
l = -32768;
|
|
else if (l > 32767)
|
|
l = 32767;
|
|
if (r < -32768)
|
|
r = -32768;
|
|
else if (r > 32767)
|
|
r = 32767;
|
|
|
|
es1371->buffer[es1371->pos*2] = l;
|
|
es1371->buffer[es1371->pos*2 + 1] = r;
|
|
}
|
|
}
|
|
|
|
static void es1371_get_buffer(int32_t *buffer, int len, void *p)
|
|
{
|
|
es1371_t *es1371 = (es1371_t *)p;
|
|
int c;
|
|
|
|
for (c = 0; c < len * 2; c++)
|
|
buffer[c] += (es1371->buffer[c] / 2);
|
|
|
|
es1371->pos = 0;
|
|
}
|
|
|
|
static void *es1371_init()
|
|
{
|
|
es1371_t *es1371 = malloc(sizeof(es1371_t));
|
|
memset(es1371, 0, sizeof(es1371_t));
|
|
|
|
sound_add_handler(es1371_get_buffer, es1371);
|
|
|
|
es1371->card = pci_add_card(PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, es1371);
|
|
|
|
timer_add(es1371_poll, &es1371->dac[1].time, TIMER_ALWAYS_ENABLED, es1371);
|
|
|
|
return es1371;
|
|
}
|
|
|
|
static void es1371_close(void *p)
|
|
{
|
|
es1371_t *es1371 = (es1371_t *)p;
|
|
|
|
free(es1371);
|
|
}
|
|
|
|
static void es1371_speed_changed(void *p)
|
|
{
|
|
es1371_t *es1371 = (es1371_t *)p;
|
|
|
|
es1371->dac[1].latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0));
|
|
}
|
|
|
|
device_t es1371_device =
|
|
{
|
|
"Ensoniq AudioPCI (ES1371)",
|
|
DEVICE_PCI,
|
|
0,
|
|
es1371_init,
|
|
es1371_close,
|
|
NULL,
|
|
NULL,
|
|
es1371_speed_changed,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|