From 041d29da8aa74b21f73d8ec42ba17a5fa187e6d3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 5 Sep 2021 17:42:33 +0200 Subject: [PATCH] AudioPCI (ES1371) clean-up and overhaul. --- src/sound/snd_audiopci.c | 2694 ++++++++++++++++++++++---------------- 1 file changed, 1585 insertions(+), 1109 deletions(-) diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index e34324657..995edb6a8 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -23,69 +23,70 @@ #define ES1371_NCoef 91 + static float low_fir_es1371_coef[ES1371_NCoef]; + typedef struct { - uint8_t pci_command, pci_serr; + uint8_t pci_command, pci_serr; - uint32_t base_addr; + uint32_t base_addr; - uint8_t int_line; + uint8_t int_line; - uint16_t pmcsr; + uint16_t pmcsr; - uint32_t int_ctrl; - uint32_t int_status; + uint32_t int_ctrl, int_status, + legacy_ctrl; - uint32_t legacy_ctrl; + int mem_page; - int mem_page; + uint32_t si_cr; - uint32_t si_cr; + uint32_t sr_cir; + uint16_t sr_ram[128]; - uint32_t sr_cir; - uint16_t sr_ram[128]; + uint8_t uart_ctrl, uart_status, + uart_res; + uint32_t uart_fifo; - uint8_t uart_ctrl; - uint8_t uart_status; - - ac97_codec_t *codec; - uint32_t codec_ctrl; + ac97_codec_t * codec; + uint32_t codec_ctrl; struct { - uint32_t addr, addr_latch; - uint16_t count, size; + uint32_t addr, addr_latch; + uint16_t count, size; - uint16_t samp_ct; - int curr_samp_ct; + uint16_t samp_ct; + int curr_samp_ct; - pc_timer_t timer; - uint64_t latch; + pc_timer_t timer; + uint64_t latch; - uint32_t vf, ac; + uint32_t vf, ac; - int16_t buffer_l[64], buffer_r[64]; - int buffer_pos, buffer_pos_end; + int16_t buffer_l[64], buffer_r[64]; + int buffer_pos, buffer_pos_end; - int filtered_l[32], filtered_r[32]; - int f_pos; + int filtered_l[32], filtered_r[32]; + int f_pos; - int16_t out_l, out_r; + int16_t out_l, out_r; - int32_t vol_l, vol_r; + int32_t vol_l, vol_r; } dac[2], adc; - int64_t dac_latch, dac_time; + int64_t dac_latch, dac_time; - int master_vol_l, master_vol_r; - int cd_vol_l, cd_vol_r; + int master_vol_l, master_vol_r, + cd_vol_l, cd_vol_r; - int card; + int card; - int pos; - int16_t buffer[SOUNDBUFLEN * 2]; + int pos; + int16_t buffer[SOUNDBUFLEN * 2]; - int type; + int type; } es1371_t; @@ -145,8 +146,10 @@ typedef struct { #define FORMAT_MONO_16 2 #define FORMAT_STEREO_16 3 -static void es1371_fetch(es1371_t *es1371, int dac_nr); -static void update_legacy(es1371_t *es1371, uint32_t old_legacy_ctrl); + +static void es1371_fetch(es1371_t *dev, int dac_nr); +static void update_legacy(es1371_t *dev, uint32_t old_legacy_ctrl); + #ifdef ENABLE_AUDIOPCI_LOG int audiopci_do_log = ENABLE_AUDIOPCI_LOG; @@ -168,1234 +171,1707 @@ audiopci_log(const char *fmt, ...) #endif -static void es1371_update_irqs(es1371_t *es1371) +static void +es1371_update_irqs(es1371_t *dev) { - 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; - } - /*MIDI input is unsupported for now*/ - if ((es1371->int_status & INT_STATUS_UART) && (es1371->uart_status & UART_STATUS_TXINT)) { - irq = 1; - } + int irq = 0; - if (irq) - es1371->int_status |= INT_STATUS_INTR; - else - es1371->int_status &= ~INT_STATUS_INTR; + if ((dev->int_status & INT_STATUS_DAC1) && (dev->si_cr & SI_P1_INTR_EN)) + irq = 1; + if ((dev->int_status & INT_STATUS_DAC2) && (dev->si_cr & SI_P2_INTR_EN)) + irq = 1; - 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"); - } + /* MIDI input is unsupported for now */ + if ((dev->int_status & INT_STATUS_UART) && (dev->uart_status & UART_STATUS_TXINT)) + irq = 1; + + if (irq) + dev->int_status |= INT_STATUS_INTR; + else + dev->int_status &= ~INT_STATUS_INTR; + + if (dev->legacy_ctrl & LEGACY_FORCE_IRQ) + irq = 1; + + if (irq) + pci_set_irq(dev->card, PCI_INTA); + else + pci_clear_irq(dev->card, PCI_INTA); } -static uint8_t es1371_inb(uint16_t port, void *p) + +static void +es1371_reset(void *p) { - es1371_t *es1371 = (es1371_t *)p; - uint8_t ret = 0; - - switch (port & 0x3f) - { - case 0x00: - ret = es1371->int_ctrl & 0xff; + es1371_t *dev = (es1371_t *) p; + + nmi = 0; + + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + dev->int_ctrl = 0xfc0f0000; + + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as longword only */ + dev->int_status = 0x7ffffec0; + + /* UART Status Register, Address 09H + Addressable as byte only */ + dev->uart_status = 0x00; + + /* UART Control Register, Address 09H + Addressable as byte only */ + dev->uart_ctrl = 0x00; + + /* UART Reserved Register, Address 0AH + Addressable as byte only */ + dev->uart_res = 0x00; + + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + dev->mem_page = 0x00; + + /* Sample Rate Concerter Interface Register, Address 10H + Addressable as longword only */ + dev->sr_cir = 0x00000000; + + /* CODEC Write Register, Address 14H + Addressable as longword only */ + dev->codec_ctrl = 0x00000000; + + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + dev->legacy_ctrl = 0x0000f800; + + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + dev->si_cr = 0xff800000; + + /* DAC1 Channel Sample Count Register, Address 24H + Addressable as word, longword */ + dev->dac[0].samp_ct = 0x00000000; + dev->dac[0].curr_samp_ct = 0x00000000; + + /* DAC2 Channel Sample Count Register, Address 28H + Addressable as word, longword */ + dev->dac[1].samp_ct = 0x00000000; + dev->dac[1].curr_samp_ct = 0x00000000; + + /* ADC Channel Sample Count Register, Address 2CH + Addressable as word, longword */ + dev->adc.samp_ct = 0x00000000; + dev->adc.curr_samp_ct = 0x00000000; + + /* DAC1 Frame Register 1, Address 30H, Memory Page 1100b + Addressable as longword only */ + dev->dac[0].addr_latch = 0x00000000; + + /* DAC1 Frame Register 2, Address 34H, Memory Page 1100b + Addressable as longword only */ + dev->dac[0].size = 0x00000000; + dev->dac[0].count = 0x00000000; + + /* DAC2 Frame Register 1, Address 38H, Memory Page 1100b + Addressable as longword only */ + dev->dac[1].addr_latch = 0x00000000; + + /* DAC2 Frame Register 2, Address 3CH, Memory Page 1100b + Addressable as longword only */ + dev->dac[1].size = 0x00000000; + dev->dac[1].count = 0x00000000; + + /* ADC Frame Register 1, Address 30H, Memory Page 1101b + Addressable as longword only */ + dev->adc.addr_latch = 0x00000000; + + /* ADC Frame Register 2, Address 34H, Memory Page 1101b + Addressable as longword only */ + dev->adc.size = 0x00000000; + dev->adc.count = 0x00000000; + + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + dev->uart_fifo = 0xfffffe00; +} + + +static uint32_t +es1371_read_frame_reg(es1371_t *dev, int frame, int page) +{ + uint32_t ret = 0xffffffff; + + switch (frame) { + case 0x30: + switch (page) { + /* DAC1 Frame Register 1, Address 30H, Memory Page 1100b + Addressable as longword only */ + case 0xc: + ret = dev->dac[0].addr_latch; + break; + /* ADC Frame Register 1, Address 30H, Memory Page 1101b + Addressable as longword only */ + case 0xd: + ret = dev->adc.addr_latch; + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: case 0xf: + ret = dev->uart_fifo; + break; + } break; - case 0x01: - ret = (es1371->int_ctrl >> 8) & 0xff; + case 0x34: + switch (page) { + /* DAC1 Frame Register 2, Address 34H, Memory Page 1100b + Addressable as longword only */ + case 0xc: + ret = dev->dac[0].size | (dev->dac[0].count << 16); + break; + /* ADC Frame Register 2, Address 34H, Memory Page 1101b + Addressable as longword only */ + case 0xd: + ret = dev->adc.size | (dev->adc.count << 16); + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: case 0xf: + ret = dev->uart_fifo; + break; + } break; - case 0x02: - ret = (es1371->int_ctrl >> 16) & 0xff; + case 0x38: + switch (page) { + /* DAC2 Frame Register 1, Address 38H, Memory Page 1100b + Addressable as longword only */ + case 0xc: + ret = dev->dac[1].addr_latch; + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: case 0xf: + ret = dev->uart_fifo; + break; + } break; - case 0x03: - ret = (es1371->int_ctrl >> 24) & 0xff; + case 0x3c: + switch (page) { + /* DAC2 Frame Register 2, Address 3CH, Memory Page 1100b + Addressable as longword only */ + case 0xc: + ret = dev->dac[1].size | (dev->dac[1].count << 16); + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: case 0xf: + ret = dev->uart_fifo; + break; + } + break; + } + + return ret; +} + + +static void +es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val) +{ + switch (frame) { + case 0x30: + switch (page) { + /* DAC1 Frame Register 1, Address 30H, Memory Page 1100b + Addressable as longword only */ + case 0xc: + dev->dac[0].addr_latch = val; + break; + /* ADC Frame Register 1, Address 30H, Memory Page 1101b + Addressable as longword only */ + case 0xd: + dev->adc.addr_latch = val; + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: case 0xf: + dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff); + break; + } + break; + case 0x34: + switch (page) { + /* DAC1 Frame Register 2, Address 34H, Memory Page 1100b + Addressable as longword only */ + case 0xc: + dev->dac[0].size = val & 0xffff; + dev->dac[0].count = val >> 16; + break; + /* ADC Frame Register 2, Address 34H, Memory Page 1101b + Addressable as longword only */ + case 0xd: + dev->adc.size = val & 0xffff; + dev->adc.count = val >> 16; + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: case 0xf: + dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff); + break; + } + break; + case 0x38: + switch (page) { + /* DAC2 Frame Register 1, Address 38H, Memory Page 1100b + Addressable as longword only */ + case 0xc: + dev->dac[1].addr_latch = val; + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: case 0xf: + dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff); + break; + } + break; + case 0x3c: + switch (page) { + /* DAC2 Frame Register 2, Address 3CH, Memory Page 1100b + Addressable as longword only */ + case 0xc: + dev->dac[1].size = val & 0xffff; + dev->dac[1].count = val >> 16; + break; + /* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b + Addressable as longword only */ + case 0xe: case 0xf: + dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff); + break; + } + break; + } +} + + +static uint8_t +es1371_inb(uint16_t port, void *p) +{ + es1371_t *dev = (es1371_t *) p; + uint8_t ret = 0xff; + + switch (port & 0x3f) { + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + case 0x00: + ret = dev->int_ctrl & 0xff; + break; + case 0x01: + ret = (dev->int_ctrl >> 8) & 0xff; + break; + case 0x02: + ret = (dev->int_ctrl >> 16) & 0x0f; + break; + case 0x03: + ret = ((dev->int_ctrl >> 24) & 0x03) | 0xfc; break; - case 0x04: - ret = es1371->int_status & 0xff; + /* Interrupt/Chip Select Status Register, Address 04H + Addressable as longword only, but PCem implemens byte access, which + must be for a reason */ + case 0x04: + ret = dev->int_status & 0xff; break; - case 0x05: - ret = (es1371->int_status >> 8) & 0xff; + case 0x05: + ret = (dev->int_status >> 8) & 0xff; break; - case 0x06: - ret = (es1371->int_status >> 16) & 0xff; + case 0x06: + ret = (dev->int_status >> 16) & 0x0f; break; - case 0x07: - ret = (es1371->int_status >> 24) & 0xff; + case 0x07: + ret = ((dev->int_status >> 24) & 0x03) | 0xfc; + break; + + /* UART Data Register, Address 08H + Addressable as byte only */ + case 0x08: + ret = 0x00; + break; + + /* UART Status Register, Address 09H + Addressable as byte only */ + case 0x09: + ret = dev->uart_status & 0x87; + audiopci_log("ES1371 UART Status = %02x\n", dev->uart_status); + break; + + /* UART Reserved Register, Address 0AH + Addressable as byte only */ + case 0x0a: + ret = dev->uart_res & 0x01; + break; + + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + case 0x0c: + ret = dev->mem_page; + break; + case 0x0d ... 0x0e: + ret = 0x00; break; - case 0x09: - ret = es1371->uart_status & 0xc7; - audiopci_log("ES1371 UART Status = %02x\n", es1371->uart_status); + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + case 0x18: + ret = dev->legacy_ctrl & 0xfd; break; - - case 0x0c: - ret = es1371->mem_page; + case 0x19: + ret = ((dev->legacy_ctrl >> 8) & 0x07) | 0xf8; break; - - case 0x1a: - ret = es1371->legacy_ctrl >> 16; + case 0x1a: + ret = dev->legacy_ctrl >> 16; break; - case 0x1b: - ret = es1371->legacy_ctrl >> 24; + case 0x1b: + ret = dev->legacy_ctrl >> 24; break; - - case 0x20: - ret = es1371->si_cr & 0xff; + + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + case 0x20: + ret = dev->si_cr & 0xff; break; - case 0x21: - ret = es1371->si_cr >> 8; + case 0x21: + ret = dev->si_cr >> 8; break; - case 0x22: - ret = (es1371->si_cr >> 16) | 0x80; + case 0x22: + ret = (dev->si_cr >> 16) | 0x80; break; - case 0x23: + case 0x23: ret = 0xff; break; - default: + 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: - ret = es1371_inb(port, p); - ret |= es1371_inb(port + 1, p) << 8; - } - -// 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 | CODEC_READY; - break; - - case 0x30: - switch (es1371->mem_page) { - case 0xe: case 0xf: - audiopci_log("ES1371 0x30 read UART FIFO: val = %02x\n", ret & 0xff); - break; - } - 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; - - case 0xe: case 0xf: - audiopci_log("ES1371 0x34 read UART FIFO: val = %02x\n", ret & 0xff); - break; - - default: - audiopci_log("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port); - } - break; - - case 0x38: - switch (es1371->mem_page) { - case 0xe: case 0xf: - audiopci_log("ES1371 0x38 read UART FIFO: val = %02x\n", ret & 0xff); - break; - } - break; - - case 0x3c: - switch (es1371->mem_page) { - case 0xc: - ret = es1371->dac[1].size | (es1371->dac[1].count << 16); - break; - - case 0xe: case 0xf: - audiopci_log("ES1371 0x3c read UART FIFO: val = %02x\n", ret & 0xff); - break; - - default: - audiopci_log("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port); - } - break; - - default: - ret = es1371_inw(port, p); - ret |= es1371_inw(port + 2, p) << 16; - } - - audiopci_log("es1371_inl: port=%04x ret=%08x\n", port, ret); - return ret; + audiopci_log("es1371_inb: port=%04x ret=%02x\n", port, ret); + return ret; } -static void es1371_outb(uint16_t port, uint8_t val, void *p) -{ - es1371_t *es1371 = (es1371_t *)p; - uint32_t old_legacy_ctrl; - audiopci_log("es1371_outb: port=%04x val=%02x\n", port, val); - 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; +static uint16_t +es1371_inw(uint16_t port, void *p) +{ + es1371_t *dev = (es1371_t *) p; + uint16_t ret = 0xffff; + + switch (port & 0x3e) { + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + case 0x00: + ret = dev->int_ctrl & 0xffff; break; - case 0x01: - es1371->int_ctrl = (es1371->int_ctrl & 0xffff00ff) | (val << 8); + case 0x02: + ret = ((dev->int_ctrl >> 16) & 0x030f) | 0xfc00; break; - case 0x02: - es1371->int_ctrl = (es1371->int_ctrl & 0xff00ffff) | (val << 16); + + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + case 0x0c: + ret = dev->mem_page; break; - case 0x03: - es1371->int_ctrl = (es1371->int_ctrl & 0x00ffffff) | (val << 24); + case 0x0e: + ret = 0x0000; + break; + + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + case 0x18: + ret = (dev->legacy_ctrl & 0x07fd) | 0xf800; + break; + case 0x1a: + ret = dev->legacy_ctrl >> 16; + break; + + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + case 0x20: + ret = dev->si_cr & 0xffff; + break; + case 0x22: + ret = (dev->si_cr >> 16) | 0xff80; + break; + + /* DAC1 Channel Sample Count Register, Address 24H + Addressable as word, longword */ + case 0x24: + ret = dev->dac[0].samp_ct; + break; + case 0x26: + ret = dev->dac[0].curr_samp_ct; + break; + + /* DAC2 Channel Sample Count Register, Address 28H + Addressable as word, longword */ + case 0x28: + ret = dev->dac[1].samp_ct; + break; + case 0x2a: + ret = dev->dac[1].curr_samp_ct; + break; + + /* ADC Channel Sample Count Register, Address 2CH + Addressable as word, longword */ + case 0x2c: + ret = dev->adc.samp_ct; + break; + case 0x2e: + ret = dev->adc.curr_samp_ct; + break; + + case 0x30: case 0x34: case 0x38: case 0x3c: + ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page) & 0xffff; + break; + case 0x32: case 0x36: case 0x3a: case 0x3e: + ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page) >> 16; + break; + } + + return ret; +} + + +static uint32_t +es1371_inl(uint16_t port, void *p) +{ + es1371_t *dev = (es1371_t *) p; + uint32_t ret = 0xffffffff; + + switch (port & 0x3c) { + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + case 0x00: + ret = (dev->int_ctrl & 0x030fffff) | 0xfc000000; + break; + + /* Interrupt/Chip Select Status Register, Address 04H + Addressable as longword only */ + case 0x04: + ret = dev->int_status; + break; + + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + case 0x0c: + ret = dev->mem_page; + break; + + /* Sample Rate Concerter Interface Register, Address 10H + Addressable as longword only */ + case 0x10: + ret = dev->sr_cir & ~0xffff; + ret |= dev->sr_ram[dev->sr_cir >> 25]; break; - case 0x08: + /* CODEC Read Register, Address 14H + Addressable as longword only */ + case 0x14: + ret = dev->codec_ctrl | CODEC_READY; + break; + + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + case 0x18: + ret = (dev->legacy_ctrl & 0xffff07fd) | 0x0000f800; + break; + + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + case 0x20: + ret = dev->si_cr | 0xff800000; + break; + + /* DAC1 Channel Sample Count Register, Address 24H + Addressable as word, longword */ + case 0x24: + ret = dev->dac[0].samp_ct | (((uint32_t) dev->dac[0].curr_samp_ct) << 16); + break; + + /* DAC2 Channel Sample Count Register, Address 28H + Addressable as word, longword */ + case 0x28: + ret = dev->dac[1].samp_ct | (((uint32_t) dev->dac[1].curr_samp_ct) << 16); + break; + + /* ADC Channel Sample Count Register, Address 2CH + Addressable as word, longword */ + case 0x2c: + ret = dev->adc.samp_ct | (((uint32_t) dev->adc.curr_samp_ct) << 16); + break; + + case 0x30: case 0x34: case 0x38: case 0x3c: + ret = es1371_read_frame_reg(dev, port & 0x3c, dev->mem_page); + break; + } + + audiopci_log("es1371_inl: port=%04x ret=%08x\n", port, ret); + return ret; +} + + +static void +es1371_outb(uint16_t port, uint8_t val, void *p) +{ + es1371_t *dev = (es1371_t *)p; + uint32_t old_legacy_ctrl; + + audiopci_log("es1371_outb: port=%04x val=%02x\n", port, val); + + switch (port & 0x3f) { + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + case 0x00: + if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) { + dev->dac[0].addr = dev->dac[0].addr_latch; + dev->dac[0].buffer_pos = 0; + dev->dac[0].buffer_pos_end = 0; + es1371_fetch(dev, 0); + } + if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { + dev->dac[1].addr = dev->dac[1].addr_latch; + dev->dac[1].buffer_pos = 0; + dev->dac[1].buffer_pos_end = 0; + es1371_fetch(dev, 1); + } + dev->int_ctrl = (dev->int_ctrl & 0xffffff00) | val; + break; + case 0x01: + dev->int_ctrl = (dev->int_ctrl & 0xffff00ff) | (val << 8); + break; + case 0x02: + dev->int_ctrl = (dev->int_ctrl & 0xff00ffff) | (val << 16); + break; + case 0x03: + dev->int_ctrl = (dev->int_ctrl & 0x00ffffff) | (val << 24); + break; + + /* UART Data Register, Address 08H + Addressable as byte only */ + case 0x08: midi_raw_out_byte(val); break; - - case 0x09: - es1371->uart_ctrl = val & 0xe3; - audiopci_log("ES1371 UART Cntrl = %02x\n", es1371->uart_ctrl); - break; - - case 0x0c: - es1371->mem_page = val & 0xf; + + /* UART Control Register, Address 09H + Addressable as byte only */ + case 0x09: + dev->uart_ctrl = val & 0xe3; + audiopci_log("ES1371 UART Cntrl = %02x\n", dev->uart_ctrl); break; - case 0x18: - es1371->legacy_ctrl |= LEGACY_INT; - nmi = 0; + /* UART Reserved Register, Address 0AH + Addressable as byte only */ + case 0x0a: + dev->uart_res = val & 0x01; break; - case 0x1a: - old_legacy_ctrl = es1371->legacy_ctrl; - es1371->legacy_ctrl = (es1371->legacy_ctrl & 0xff00ffff) | (val << 16); - update_legacy(es1371, old_legacy_ctrl); + + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + case 0x0c: + dev->mem_page = val & 0xf; break; - case 0x1b: - old_legacy_ctrl = es1371->legacy_ctrl; - es1371->legacy_ctrl = (es1371->legacy_ctrl & 0x00ffffff) | (val << 24); - es1371_update_irqs(es1371); -// output = 3; - update_legacy(es1371, old_legacy_ctrl); + case 0x0d ... 0x0f: break; - - case 0x20: - es1371->si_cr = (es1371->si_cr & 0xffff00) | val; + + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + case 0x18: + dev->legacy_ctrl |= LEGACY_INT; + // nmi = 0; 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); + case 0x1a: + old_legacy_ctrl = dev->legacy_ctrl; + dev->legacy_ctrl = (dev->legacy_ctrl & 0xff00ffff) | (val << 16); + update_legacy(dev, old_legacy_ctrl); break; - case 0x22: - es1371->si_cr = (es1371->si_cr & 0x00ffff) | (val << 16); + case 0x1b: + old_legacy_ctrl = dev->legacy_ctrl; + dev->legacy_ctrl = (dev->legacy_ctrl & 0x00ffffff) | (val << 24); + es1371_update_irqs(dev); + update_legacy(dev, old_legacy_ctrl); break; - - default: + + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + case 0x20: + dev->si_cr = (dev->si_cr & 0xffffff00) | val; + break; + case 0x21: + dev->si_cr = (dev->si_cr & 0xffff00ff) | (val << 8); + if (!(dev->si_cr & SI_P1_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC1; + if (!(dev->si_cr & SI_P2_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC2; + es1371_update_irqs(dev); + break; + case 0x22: + dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x7f) << 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) + + +static void +es1371_outw(uint16_t port, uint16_t val, void *p) { - es1371_t *es1371 = (es1371_t *)p; + es1371_t *dev = (es1371_t *)p; + uint32_t old_legacy_ctrl; -// audiopci_log("es1371_outw: port=%04x val=%04x\n", port, val); - switch (port & 0x3f) - { - case 0x0c: - es1371->mem_page = val & 0xf; + switch (port & 0x3f) { + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + case 0x00: + if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) { + dev->dac[0].addr = dev->dac[0].addr_latch; + dev->dac[0].buffer_pos = 0; + dev->dac[0].buffer_pos_end = 0; + es1371_fetch(dev, 0); + } + if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { + dev->dac[1].addr = dev->dac[1].addr_latch; + dev->dac[1].buffer_pos = 0; + dev->dac[1].buffer_pos_end = 0; + es1371_fetch(dev, 1); + } + dev->int_ctrl = (dev->int_ctrl & 0xffff0000) | val; + break; + case 0x02: + dev->int_ctrl = (dev->int_ctrl & 0x0000ffff) | (val << 16); break; - case 0x24: - es1371->dac[0].samp_ct = val; + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + case 0x0c: + dev->mem_page = val & 0xf; + break; + case 0x0e: break; - case 0x28: - es1371->dac[1].samp_ct = val; + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + case 0x18: + dev->legacy_ctrl |= LEGACY_INT; + // nmi = 0; break; - - default: - es1371_outb(port, val & 0xff, p); - es1371_outb(port + 1, (val >> 8) & 0xff, p); - } + case 0x1a: + old_legacy_ctrl = dev->legacy_ctrl; + dev->legacy_ctrl = (dev->legacy_ctrl & 0x0000ffff) | (val << 16); + es1371_update_irqs(dev); + update_legacy(dev, old_legacy_ctrl); + break; + + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + case 0x20: + dev->si_cr = (dev->si_cr & 0xffff0000) | val; + if (!(dev->si_cr & SI_P1_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC1; + if (!(dev->si_cr & SI_P2_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC2; + es1371_update_irqs(dev); + break; + case 0x22: + dev->si_cr = (dev->si_cr & 0xff80ffff) | ((val & 0x007f) << 16); + break; + + /* DAC1 Channel Sample Count Register, Address 24H + Addressable as word, longword */ + case 0x24: + dev->dac[0].samp_ct = val; + break; + + /* DAC2 Channel Sample Count Register, Address 28H + Addressable as word, longword */ + case 0x28: + dev->dac[1].samp_ct = val; + break; + + /* ADC Channel Sample Count Register, Address 2CH + Addressable as word, longword */ + case 0x2c: + dev->adc.samp_ct = val; + break; + } } -static void es1371_outl(uint16_t port, uint32_t val, void *p) + + +static void +es1371_outl(uint16_t port, uint32_t val, void *p) { - es1371_t *es1371 = (es1371_t *)p; + es1371_t *dev = (es1371_t *)p; + uint32_t old_legacy_ctrl; - audiopci_log("es1371_outl: port=%04x val=%08x\n", port, val); - switch (port & 0x3f) - { - case 0x04: - break; - - case 0x0c: - es1371->mem_page = val & 0xf; + audiopci_log("es1371_outl: port=%04x val=%08x\n", port, val); + + switch (port & 0x3f) { + /* Interrupt/Chip Select Control Register, Address 00H + Addressable as byte, word, longword */ + case 0x00: + if (!(dev->int_ctrl & INT_DAC1_EN) && (val & INT_DAC1_EN)) { + dev->dac[0].addr = dev->dac[0].addr_latch; + dev->dac[0].buffer_pos = 0; + dev->dac[0].buffer_pos_end = 0; + es1371_fetch(dev, 0); + } + if (!(dev->int_ctrl & INT_DAC2_EN) && (val & INT_DAC2_EN)) { + dev->dac[1].addr = dev->dac[1].addr_latch; + dev->dac[1].buffer_pos = 0; + dev->dac[1].buffer_pos_end = 0; + es1371_fetch(dev, 1); + } + dev->int_ctrl = val; 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) - { + /* Interrupt/Chip Select Status Register, Address 04H + Addressable as longword only */ + case 0x04: + break; + + /* Memory Page Register, Address 0CH + Addressable as byte, word, longword */ + case 0x0c: + dev->mem_page = val & 0xf; + break; + + /* Sample Rate Concerter Interface Register, Address 10H + Addressable as longword only */ + case 0x10: + dev->sr_cir = val; + if (dev->sr_cir & SRC_RAM_WE) { + dev->sr_ram[dev->sr_cir >> 25] = val & 0xffff; + switch (dev->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); - es1371->dac[0].f_pos = 0; - break; + dev->dac[0].vf = (dev->dac[0].vf & ~0x1f8000) | ((val & 0xfc00) << 5); + dev->dac[0].ac = (dev->dac[0].ac & ~0x7f8000) | ((val & 0x00ff) << 15); + dev->dac[0].f_pos = 0; + break; case 0x72: - es1371->dac[0].ac = (es1371->dac[0].ac & ~0x7fff) | (val & 0x7fff); - break; + dev->dac[0].ac = (dev->dac[0].ac & ~0x7fff) | (val & 0x7fff); + break; case 0x73: - es1371->dac[0].vf = (es1371->dac[0].vf & ~0x7fff) | (val & 0x7fff); - break; + dev->dac[0].vf = (dev->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); - es1371->dac[1].f_pos = 0; - break; + dev->dac[1].vf = (dev->dac[1].vf & ~0x1f8000) | ((val & 0xfc00) << 5); + dev->dac[1].ac = (dev->dac[1].ac & ~0x7f8000) | ((val & 0x00ff) << 15); + dev->dac[1].f_pos = 0; + break; case 0x76: - es1371->dac[1].ac = (es1371->dac[1].ac & ~0x7fff) | (val & 0x7fff); - break; + dev->dac[1].ac = (dev->dac[1].ac & ~0x7fff) | (val & 0x7fff); + break; case 0x77: - es1371->dac[1].vf = (es1371->dac[1].vf & ~0x7fff) | (val & 0x7fff); - break; - + dev->dac[1].vf = (dev->dac[1].vf & ~0x7fff) | (val & 0x7fff); + break; + case 0x7c: - es1371->dac[0].vol_l = (int32_t)(int16_t)(val & 0xffff); - break; + dev->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; + dev->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; + dev->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; + dev->dac[1].vol_r = (int32_t)(int16_t)(val & 0xffff); + break; } } break; - case 0x14: + /* CODEC Write Register, Address 14H + Addressable as longword only */ + case 0x14: if (val & CODEC_READ) { - es1371->codec_ctrl &= 0x00ff0000; + dev->codec_ctrl &= 0x00ff0000; val = (val >> 16) & 0x7e; - es1371->codec_ctrl |= ac97_codec_read(es1371->codec, val); - es1371->codec_ctrl |= ac97_codec_read(es1371->codec, val | 1) << 8; + dev->codec_ctrl |= ac97_codec_read(dev->codec, val); + dev->codec_ctrl |= ac97_codec_read(dev->codec, val | 1) << 8; } else { - es1371->codec_ctrl = val & 0x00ffffff; - ac97_codec_write(es1371->codec, (val >> 16) & 0x7e, val & 0xff); - ac97_codec_write(es1371->codec, ((val >> 16) & 0x7e) | 1, val >> 8); + dev->codec_ctrl = val & 0x00ffffff; + ac97_codec_write(dev->codec, (val >> 16) & 0x7e, val & 0xff); + ac97_codec_write(dev->codec, ((val >> 16) & 0x7e) | 1, val >> 8); - ac97_codec_getattn(es1371->codec, 0x02, &es1371->master_vol_l, &es1371->master_vol_r); - ac97_codec_getattn(es1371->codec, 0x12, &es1371->cd_vol_l, &es1371->cd_vol_r); - } - 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; - - case 0xe: case 0xf: - audiopci_log("ES1371 0x30 write UART FIFO: val = %02x\n", val & 0xff); - 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; - break; - - case 0xd: - es1371->adc.size = val & 0xffff; - es1371->adc.count = val >> 16; - break; - - case 0xe: case 0xf: - audiopci_log("ES1371 0x34 write UART FIFO: val = %02x\n", val & 0xff); - 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; - - case 0xe: case 0xf: - audiopci_log("ES1371 0x38 write UART FIFO: val = %02x\n", val & 0xff); - 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; - - case 0xe: case 0xf: - audiopci_log("ES1371 0x3c write UART FIFO: val = %02x\n", val & 0xff); - break; - - default: - audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val); + ac97_codec_getattn(dev->codec, 0x02, &dev->master_vol_l, &dev->master_vol_r); + ac97_codec_getattn(dev->codec, 0x12, &dev->cd_vol_l, &dev->cd_vol_r); } break; - default: - es1371_outw(port, val & 0xffff, p); - es1371_outw(port + 2, (val >> 16) & 0xffff, p); + /* Legacy Control/Status Register, Address 18H + Addressable as byte, word, longword */ + case 0x18: + old_legacy_ctrl = dev->legacy_ctrl; + dev->legacy_ctrl = (dev->legacy_ctrl & 0x0000ffff) | (val & 0xffff0000); + dev->legacy_ctrl |= LEGACY_INT; + // nmi = 0; + es1371_update_irqs(dev); + update_legacy(dev, old_legacy_ctrl); + break; + + /* Serial Interface Control Register, Address 20H + Addressable as byte, word, longword */ + case 0x20: + dev->si_cr = (val & 0x007fffff) | 0xff800000; + if (!(dev->si_cr & SI_P1_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC1; + if (!(dev->si_cr & SI_P2_INTR_EN)) + dev->int_status &= ~INT_STATUS_DAC2; + es1371_update_irqs(dev); + break; + + /* DAC1 Channel Sample Count Register, Address 24H + Addressable as word, longword */ + case 0x24: + dev->dac[0].samp_ct = val & 0xffff; + break; + + /* DAC2 Channel Sample Count Register, Address 28H + Addressable as word, longword */ + case 0x28: + dev->dac[1].samp_ct = val & 0xffff; + break; + + /* ADC Channel Sample Count Register, Address 2CH + Addressable as word, longword */ + case 0x2c: + dev->adc.samp_ct = val & 0xffff; + break; + + case 0x30: case 0x34: case 0x38: case 0x3c: + es1371_write_frame_reg(dev, port & 0x3c, dev->mem_page, val); + break; + } +} + + +static void +capture_event(es1371_t *dev, int type, int rw, uint16_t port) +{ + dev->legacy_ctrl &= ~(LEGACY_EVENT_MASK | LEGACY_EVENT_ADDR_MASK); + dev->legacy_ctrl |= type; + if (rw) + dev->legacy_ctrl |= LEGACY_EVENT_TYPE_RW; + else + dev->legacy_ctrl &= ~LEGACY_EVENT_TYPE_RW; + dev->legacy_ctrl |= ((port << LEGACY_EVENT_ADDR_SHIFT) & LEGACY_EVENT_ADDR_MASK); + dev->legacy_ctrl &= ~LEGACY_INT; + nmi = 1; +} + + +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 *dev, uint32_t old_legacy_ctrl) +{ + if (old_legacy_ctrl & LEGACY_CAPTURE_SSCAPE) { + switch ((old_legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) { + case 0: + io_removehandler(0x0320, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + case 1: + io_removehandler(0x0330, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + case 2: + io_removehandler(0x0340, 0x0008, + capture_read_sscape, NULL ,NULL, + capture_write_sscape, NULL, NULL, dev); + break; + case 3: + io_removehandler(0x0350, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; } -} + } -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, uint32_t old_legacy_ctrl) -{ - if (old_legacy_ctrl & LEGACY_CAPTURE_SSCAPE) - { - switch ((old_legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) - { - case 0: io_removehandler(0x0320, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break; - case 1: io_removehandler(0x0330, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break; - case 2: io_removehandler(0x0340, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break; - case 3: io_removehandler(0x0350, 0x0008, capture_read_sscape,NULL,NULL, capture_write_sscape,NULL,NULL, es1371); break; - } - } - if (old_legacy_ctrl & LEGACY_CAPTURE_CODEC) - { - switch ((old_legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3) - { - case 0: io_removehandler(0x5300, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break; - case 2: io_removehandler(0xe800, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break; - case 3: io_removehandler(0xf400, 0x0080, capture_read_codec,NULL,NULL, capture_write_codec,NULL,NULL, es1371); break; - } - } - if (old_legacy_ctrl & LEGACY_CAPTURE_SB) - { - if (!(old_legacy_ctrl & LEGACY_SB_ADDR)) - io_removehandler(0x0220, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371); - else - io_removehandler(0x0240, 0x0010, capture_read_sb,NULL,NULL, capture_write_sb,NULL,NULL, es1371); - } - if (old_legacy_ctrl & LEGACY_CAPTURE_ADLIB) - io_removehandler(0x0388, 0x0004, capture_read_adlib,NULL,NULL, capture_write_adlib,NULL,NULL, es1371); - if (old_legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC) - io_removehandler(0x0020, 0x0002, capture_read_master_pic,NULL,NULL, capture_write_master_pic,NULL,NULL, es1371); - if (old_legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA) - io_removehandler(0x0000, 0x0010, capture_read_master_dma,NULL,NULL, capture_write_master_dma,NULL,NULL, es1371); - if (old_legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC) - io_removehandler(0x00a0, 0x0002, capture_read_slave_pic,NULL,NULL, capture_write_slave_pic,NULL,NULL, es1371); - if (old_legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA) - 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); - - if (addr > 0x3f) - return 0x00; - - 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 0x00; - - case 0x08: return 0x02; /* 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; + if (old_legacy_ctrl & LEGACY_CAPTURE_CODEC) { + switch ((old_legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3) { + case 0: + io_removehandler(0x5300, 0x0080, + capture_read_codec, NULL, NULL, + capture_write_codec, NULL, NULL, dev); + break; + case 2: + io_removehandler(0xe800, 0x0080, + capture_read_codec, NULL, NULL, + capture_write_codec,NULL,NULL, dev); + break; + case 3: + io_removehandler(0xf400, 0x0080, + capture_read_codec, NULL, NULL, + capture_write_codec, NULL, NULL, dev); + break; } - 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; + if (old_legacy_ctrl & LEGACY_CAPTURE_SB) { + if (!(old_legacy_ctrl & LEGACY_SB_ADDR)) { + io_removehandler(0x0220, 0x0010, + capture_read_sb, NULL, NULL, + capture_write_sb, NULL, NULL, dev); + } else { + io_removehandler(0x0240, 0x0010, + capture_read_sb, NULL, NULL, + capture_write_sb, NULL, NULL, dev); } -// audiopci_log("es1371->base_addr %08x\n", es1371->base_addr); + } + + if (old_legacy_ctrl & LEGACY_CAPTURE_ADLIB) { + io_removehandler(0x0388, 0x0004, + capture_read_adlib, NULL, NULL, + capture_write_adlib, NULL, NULL, dev); + } + + if (old_legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC) { + io_removehandler(0x0020, 0x0002, + capture_read_master_pic, NULL, NULL, + capture_write_master_pic,NULL,NULL, dev); + } + + if (old_legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA) { + io_removehandler(0x0000, 0x0010, + capture_read_master_dma, NULL, NULL, + capture_write_master_dma, NULL, NULL, dev); + } + + if (old_legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC) { + io_removehandler(0x00a0, 0x0002, + capture_read_slave_pic, NULL, NULL, + capture_write_slave_pic, NULL, NULL, dev); + } + + if (old_legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA) { + io_removehandler(0x00c0, 0x0020, + capture_read_slave_dma, NULL, NULL, + capture_write_slave_dma, NULL, NULL, dev); + } + + if (dev->legacy_ctrl & LEGACY_CAPTURE_SSCAPE) { + switch ((dev->legacy_ctrl >> LEGACY_SSCAPE_ADDR_SHIFT) & 3) { + case 0: + io_sethandler(0x0320, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + case 1: + io_sethandler(0x0330, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + case 2: + io_sethandler(0x0340, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + case 3: + io_sethandler(0x0350, 0x0008, + capture_read_sscape, NULL, NULL, + capture_write_sscape, NULL, NULL, dev); + break; + } + } + + if (dev->legacy_ctrl & LEGACY_CAPTURE_CODEC) { + switch ((dev->legacy_ctrl >> LEGACY_CODEC_ADDR_SHIFT) & 3) { + case 0: + io_sethandler(0x5300, 0x0080, + capture_read_codec, NULL, NULL, + capture_write_codec, NULL, NULL, dev); + break; + case 2: + io_sethandler(0xe800, 0x0080, + capture_read_codec, NULL, NULL, + capture_write_codec, NULL, NULL, dev); + break; + case 3: + io_sethandler(0xf400, 0x0080, + capture_read_codec, NULL, NULL, + capture_write_codec, NULL, NULL, dev); + break; + } + } + + if (dev->legacy_ctrl & LEGACY_CAPTURE_SB) { + if (!(dev->legacy_ctrl & LEGACY_SB_ADDR)) { + io_sethandler(0x0220, 0x0010, + capture_read_sb, NULL, NULL, + capture_write_sb, NULL, NULL, dev); + } else { + io_sethandler(0x0240, 0x0010, + capture_read_sb, NULL, NULL, + capture_write_sb, NULL, NULL, dev); + } + } + + if (dev->legacy_ctrl & LEGACY_CAPTURE_ADLIB) { + io_sethandler(0x0388, 0x0004, + capture_read_adlib, NULL, NULL, + capture_write_adlib, NULL, NULL, dev); + } + + if (dev->legacy_ctrl & LEGACY_CAPTURE_MASTER_PIC) { + io_sethandler(0x0020, 0x0002, + capture_read_master_pic, NULL, NULL, + capture_write_master_pic, NULL, NULL, dev); + } + + if (dev->legacy_ctrl & LEGACY_CAPTURE_MASTER_DMA) { + io_sethandler(0x0000, 0x0010, + capture_read_master_dma, NULL, NULL, + capture_write_master_dma, NULL, NULL, dev); + } + + if (dev->legacy_ctrl & LEGACY_CAPTURE_SLAVE_PIC) { + io_sethandler(0x00a0, 0x0002, + capture_read_slave_pic, NULL, NULL, + capture_write_slave_pic, NULL, NULL, dev); + } + + if (dev->legacy_ctrl & LEGACY_CAPTURE_SLAVE_DMA) { + io_sethandler(0x00c0, 0x0020, + capture_read_slave_dma, NULL, NULL, + capture_write_slave_dma, NULL, NULL, dev); + } } -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; +static uint8_t +es1371_pci_read(int func, int addr, void *p) +{ + es1371_t *dev = (es1371_t *)p; + + if (func > 0) + return 0xff; + + if (addr > 0x3f) + return 0x00; + + switch (addr) { + case 0x00: return 0x74; /* Ensoniq */ + case 0x01: return 0x12; + + case 0x02: return 0x71; /* ES1371 */ + case 0x03: return 0x13; + + case 0x04: return dev->pci_command; + case 0x05: return dev->pci_serr; + + case 0x06: return 0x10; /* Supports ACPI */ + case 0x07: return 0x00; + + case 0x08: return 0x02; /* Revision ID */ + case 0x09: return 0x00; /* Multimedia audio device */ + case 0x0a: return 0x01; + case 0x0b: return 0x04; + + case 0x10: return 0x01 | (dev->base_addr & 0xc0); /* memBaseAddr */ + case 0x11: return dev->base_addr >> 8; + case 0x12: return dev->base_addr >> 16; + case 0x13: return dev->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 dev->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 dev->pmcsr & 0xff; + case 0xe1: return dev->pmcsr >> 8; + } + + return 0x00; +} + + +static void +es1371_io_set(es1371_t *dev, int set) +{ + if (dev->pci_command & PCI_COMMAND_IO) { + io_handler(set, dev->base_addr, 0x0040, + es1371_inb, es1371_inw, es1371_inl, + es1371_outb, es1371_outw, es1371_outl, dev); + } +} + + +static void +es1371_pci_write(int func, int addr, uint8_t val, void *p) +{ + es1371_t *dev = (es1371_t *)p; + + if (func) + return; + + switch (addr) { + case 0x04: + es1371_io_set(dev, 0); + dev->pci_command = val & 0x05; + es1371_io_set(dev, 1); + break; + case 0x05: + dev->pci_serr = val & 1; + break; + + case 0x10: + es1371_io_set(dev, 0); + dev->base_addr = (dev->base_addr & 0xffffff00) | (val & 0xc0); + es1371_io_set(dev, 1); + break; + case 0x11: + es1371_io_set(dev, 0); + dev->base_addr = (dev->base_addr & 0xffff00c0) | (val << 8); + es1371_io_set(dev, 1); + break; + case 0x12: + dev->base_addr = (dev->base_addr & 0xff00ffc0) | (val << 16); + break; + case 0x13: + dev->base_addr = (dev->base_addr & 0x00ffffc0) | (val << 24); + break; + + case 0x3c: + dev->int_line = val; + break; + + case 0xe0: + dev->pmcsr = (dev->pmcsr & 0xff00) | (val & 0x03); + break; + case 0xe1: + dev->pmcsr = (dev->pmcsr & 0x00ff) | ((val & 0x01) << 8); + break; + } +} + + +static void +es1371_fetch(es1371_t *dev, int dac_nr) +{ + int format = dac_nr ? ((dev->si_cr >> 2) & 3) : (dev->si_cr & 3); + int pos = dev->dac[dac_nr].buffer_pos & 63; + int c; + + switch (format) { + case FORMAT_MONO_8: + for (c = 0; c < 32; c += 4) { + dev->dac[dac_nr].buffer_l[(pos+c) & 63] = dev->dac[dac_nr].buffer_r[(pos+c) & 63] = + (mem_readb_phys(dev->dac[dac_nr].addr) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_l[(pos+c+1) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+1) & 63] = + (mem_readb_phys(dev->dac[dac_nr].addr+1) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_l[(pos+c+2) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+2) & 63] = + (mem_readb_phys(dev->dac[dac_nr].addr+2) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_l[(pos+c+3) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+3) & 63] = + (mem_readb_phys(dev->dac[dac_nr].addr+3) ^ 0x80) << 8; + dev->dac[dac_nr].addr += 4; + + dev->dac[dac_nr].buffer_pos_end += 4; + dev->dac[dac_nr].count++; + + if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { + dev->dac[dac_nr].count = 0; + dev->dac[dac_nr].addr = dev->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; + + case FORMAT_STEREO_8: + for (c = 0; c < 16; c += 2) { + dev->dac[dac_nr].buffer_l[(pos+c) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_r[(pos+c) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 1) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_l[(pos+c+1) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 2) ^ 0x80) << 8; + dev->dac[dac_nr].buffer_r[(pos+c+1) & 63] = (mem_readb_phys(dev->dac[dac_nr].addr + 3) ^ 0x80) << 8; + dev->dac[dac_nr].addr += 4; + + dev->dac[dac_nr].buffer_pos_end += 2; + dev->dac[dac_nr].count++; + + if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { + dev->dac[dac_nr].count = 0; + dev->dac[dac_nr].addr = dev->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; + case FORMAT_MONO_16: + for (c = 0; c < 16; c += 2) { + dev->dac[dac_nr].buffer_l[(pos+c) & 63] = dev->dac[dac_nr].buffer_r[(pos+c) & 63] = + mem_readw_phys(dev->dac[dac_nr].addr); + dev->dac[dac_nr].buffer_l[(pos+c+1) & 63] = dev->dac[dac_nr].buffer_r[(pos+c+1) & 63] = + mem_readw_phys(dev->dac[dac_nr].addr + 2); + dev->dac[dac_nr].addr += 4; + + dev->dac[dac_nr].buffer_pos_end += 2; + dev->dac[dac_nr].count++; + + if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { + dev->dac[dac_nr].count = 0; + dev->dac[dac_nr].addr = dev->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; + + case FORMAT_STEREO_16: + for (c = 0; c < 4; c++) { + dev->dac[dac_nr].buffer_l[(pos+c) & 63] = mem_readw_phys(dev->dac[dac_nr].addr); + dev->dac[dac_nr].buffer_r[(pos+c) & 63] = mem_readw_phys(dev->dac[dac_nr].addr + 2); + dev->dac[dac_nr].addr += 4; + + dev->dac[dac_nr].buffer_pos_end++; + dev->dac[dac_nr].count++; + + if (dev->dac[dac_nr].count > dev->dac[dac_nr].size) { + dev->dac[dac_nr].count = 0; + dev->dac[dac_nr].addr = dev->dac[dac_nr].addr_latch; break; } } break; - } + } } -static inline float low_fir_es1371(int dac_nr, int i, float NewSample) + +static inline float +low_fir_es1371(int dac_nr, int i, float NewSample) { - static float x[2][2][128]; //input samples - static int x_pos[2] = {0, 0}; - float out = 0.0; - int read_pos; - int n_coef; - int pos = x_pos[dac_nr]; + static float x[2][2][128]; //input samples + static int x_pos[2] = {0, 0}; + float out = 0.0; + int read_pos, n_coef; + int pos = x_pos[dac_nr]; - x[dac_nr][i][pos] = NewSample; + x[dac_nr][i][pos] = NewSample; - /*Since only 1/16th of input samples are non-zero, only filter those that - are valid.*/ - read_pos = (pos + 15) & (127 & ~15); - n_coef = (16 - pos) & 15; + /* Since only 1/16th of input samples are non-zero, only filter those that + are valid.*/ + read_pos = (pos + 15) & (127 & ~15); + n_coef = (16 - pos) & 15; - while (n_coef < ES1371_NCoef) - { - out += low_fir_es1371_coef[n_coef] * x[dac_nr][i][read_pos]; - read_pos = (read_pos + 16) & (127 & ~15); - n_coef += 16; + while (n_coef < ES1371_NCoef) { + out += low_fir_es1371_coef[n_coef] * x[dac_nr][i][read_pos]; + read_pos = (read_pos + 16) & (127 & ~15); + n_coef += 16; + } + + if (i == 1) { + x_pos[dac_nr] = (x_pos[dac_nr] + 1) & 127; + if (x_pos[dac_nr] > 127) + x_pos[dac_nr] = 0; + } + + return out; +} + + +static void +es1371_next_sample_filtered(es1371_t *dev, int dac_nr, int out_idx) +{ + int out_l, out_r; + int c; + + if ((dev->dac[dac_nr].buffer_pos - dev->dac[dac_nr].buffer_pos_end) >= 0) + es1371_fetch(dev, dac_nr); + + out_l = dev->dac[dac_nr].buffer_l[dev->dac[dac_nr].buffer_pos & 63]; + out_r = dev->dac[dac_nr].buffer_r[dev->dac[dac_nr].buffer_pos & 63]; + + dev->dac[dac_nr].filtered_l[out_idx] = (int)low_fir_es1371(dac_nr, 0, (float)out_l); + dev->dac[dac_nr].filtered_r[out_idx] = (int)low_fir_es1371(dac_nr, 1, (float)out_r); + + for (c = 1; c < 16; c++) { + dev->dac[dac_nr].filtered_l[out_idx+c] = (int)low_fir_es1371(dac_nr, 0, 0); + dev->dac[dac_nr].filtered_r[out_idx+c] = (int)low_fir_es1371(dac_nr, 1, 0); + } + + dev->dac[dac_nr].buffer_pos++; +} + + +static void +es1371_update(es1371_t *dev) +{ + int32_t l, r; + + l = (dev->dac[0].out_l * dev->dac[0].vol_l) >> 12; + l += ((dev->dac[1].out_l * dev->dac[1].vol_l) >> 12); + r = (dev->dac[0].out_r * dev->dac[0].vol_r) >> 12; + r += ((dev->dac[1].out_r * dev->dac[1].vol_r) >> 12); + + l >>= 1; + r >>= 1; + + l = (l * dev->master_vol_l) >> 15; + r = (r * dev->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; + + for (; dev->pos < sound_pos_global; dev->pos++) { + dev->buffer[dev->pos*2] = l; + dev->buffer[dev->pos*2 + 1] = r; + } +} + + +static void +es1371_poll(void *p) +{ + es1371_t *dev = (es1371_t *)p; + int frac, idx, samp1_l, samp1_r, samp2_l, samp2_r; + + timer_advance_u64(&dev->dac[1].timer, dev->dac[1].latch); + + es1371_update(dev); + + if (dev->int_ctrl & INT_UART_EN) { + audiopci_log("UART INT Enabled\n"); + if (dev->uart_ctrl & UART_CTRL_RXINTEN) { + /* We currently don't implement MIDI Input. + But if anything sets MIDI Input and Output together we'd have to take account + of the MIDI Output case, and disable IRQ's and RX bits when MIDI Input is + enabled as well but not in the MIDI Output portion */ + if (dev->uart_ctrl & UART_CTRL_TXINTEN) + dev->int_status |= INT_STATUS_UART; + else + dev->int_status &= ~INT_STATUS_UART; + } else if (!(dev->uart_ctrl & UART_CTRL_RXINTEN) && ((dev->uart_ctrl & UART_CTRL_TXINTEN))) { + /* Or enable the UART IRQ and the respective TX bits only when the MIDI Output is + enabled */ + dev->int_status |= INT_STATUS_UART; } - if (i == 1) - { - x_pos[dac_nr] = (x_pos[dac_nr] + 1) & 127; - if (x_pos[dac_nr] > 127) - x_pos[dac_nr] = 0; - } + if (dev->uart_ctrl & UART_CTRL_RXINTEN) { + if (dev->uart_ctrl & UART_CTRL_TXINTEN) + dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY); + else + dev->uart_status &= ~(UART_STATUS_TXINT | UART_STATUS_TXRDY); + } else + dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY); - return out; -} + es1371_update_irqs(dev); + } -static void es1371_next_sample_filtered(es1371_t *es1371, int dac_nr, int out_idx) -{ - int out_l, out_r; - int c; - - if ((es1371->dac[dac_nr].buffer_pos - es1371->dac[dac_nr].buffer_pos_end) >= 0) - { - es1371_fetch(es1371, dac_nr); - } + if (dev->int_ctrl & INT_DAC1_EN) { + frac = dev->dac[0].ac & 0x7fff; + idx = dev->dac[0].ac >> 15; + samp1_l = dev->dac[0].filtered_l[idx]; + samp1_r = dev->dac[0].filtered_r[idx]; + samp2_l = dev->dac[0].filtered_l[(idx + 1) & 31]; + samp2_r = dev->dac[0].filtered_r[(idx + 1) & 31]; - out_l = es1371->dac[dac_nr].buffer_l[es1371->dac[dac_nr].buffer_pos & 63]; - out_r = es1371->dac[dac_nr].buffer_r[es1371->dac[dac_nr].buffer_pos & 63]; - - es1371->dac[dac_nr].filtered_l[out_idx] = (int)low_fir_es1371(dac_nr, 0, (float)out_l); - es1371->dac[dac_nr].filtered_r[out_idx] = (int)low_fir_es1371(dac_nr, 1, (float)out_r); - for (c = 1; c < 16; c++) - { - es1371->dac[dac_nr].filtered_l[out_idx+c] = (int)low_fir_es1371(dac_nr, 0, 0); - es1371->dac[dac_nr].filtered_r[out_idx+c] = (int)low_fir_es1371(dac_nr, 1, 0); - } - -// 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); -} + dev->dac[0].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; + dev->dac[0].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; + dev->dac[0].ac += dev->dac[0].vf; + dev->dac[0].ac &= ((32 << 15) - 1); + if ((dev->dac[0].ac >> (15+4)) != dev->dac[0].f_pos) { + es1371_next_sample_filtered(dev, 0, dev->dac[0].f_pos ? 16 : 0); + dev->dac[0].f_pos = (dev->dac[0].f_pos + 1) & 1; -//static FILE *es1371_f;//,*es1371_f2; - -static void es1371_update(es1371_t *es1371) -{ - 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; - - for (; es1371->pos < sound_pos_global; es1371->pos++) - { - es1371->buffer[es1371->pos*2] = l; - es1371->buffer[es1371->pos*2 + 1] = r; - } -} - -static void es1371_poll(void *p) -{ - es1371_t *es1371 = (es1371_t *)p; - - timer_advance_u64(&es1371->dac[1].timer, es1371->dac[1].latch); - - es1371_update(es1371); - - if (es1371->int_ctrl & INT_UART_EN) { - audiopci_log("UART INT Enabled\n"); - if (es1371->uart_ctrl & UART_CTRL_RXINTEN) { /*We currently don't implement MIDI Input.*/ - /*But if anything sets MIDI Input and Output together we'd have to take account - of the MIDI Output case, and disable IRQ's and RX bits when MIDI Input is enabled as well but not in the MIDI Output portion*/ - if (es1371->uart_ctrl & UART_CTRL_TXINTEN) - es1371->int_status |= INT_STATUS_UART; - else - es1371->int_status &= ~INT_STATUS_UART; - } else if (!(es1371->uart_ctrl & UART_CTRL_RXINTEN) && ((es1371->uart_ctrl & UART_CTRL_TXINTEN))) { /*Or enable the UART IRQ and the respective TX bits only when the MIDI Output is enabled*/ - es1371->int_status |= INT_STATUS_UART; - } - - if (es1371->uart_ctrl & UART_CTRL_RXINTEN) { - if (es1371->uart_ctrl & UART_CTRL_TXINTEN) - es1371->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY); - else - es1371->uart_status &= ~(UART_STATUS_TXINT | UART_STATUS_TXRDY); - } else - es1371->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY); - - es1371_update_irqs(es1371); - } - - if (es1371->int_ctrl & INT_DAC1_EN) { - int frac = es1371->dac[0].ac & 0x7fff; - int idx = es1371->dac[0].ac >> 15; - int samp1_l = es1371->dac[0].filtered_l[idx]; - int samp1_r = es1371->dac[0].filtered_r[idx]; - int samp2_l = es1371->dac[0].filtered_l[(idx + 1) & 31]; - int samp2_r = es1371->dac[0].filtered_r[(idx + 1) & 31]; - - es1371->dac[0].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; - es1371->dac[0].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; - es1371->dac[0].ac += es1371->dac[0].vf; - es1371->dac[0].ac &= ((32 << 15) - 1); - if ((es1371->dac[0].ac >> (15+4)) != es1371->dac[0].f_pos) - { - es1371_next_sample_filtered(es1371, 0, es1371->dac[0].f_pos ? 16 : 0); - es1371->dac[0].f_pos = (es1371->dac[0].f_pos + 1) & 1; - - es1371->dac[0].curr_samp_ct--; - if (es1371->dac[0].curr_samp_ct < 0) - { - es1371->int_status |= INT_STATUS_DAC1; - es1371_update_irqs(es1371); - es1371->dac[0].curr_samp_ct = es1371->dac[0].samp_ct; - } + dev->dac[0].curr_samp_ct--; + if (dev->dac[0].curr_samp_ct < 0) { + dev->int_status |= INT_STATUS_DAC1; + es1371_update_irqs(dev); + dev->dac[0].curr_samp_ct = dev->dac[0].samp_ct; } } + } - if (es1371->int_ctrl & INT_DAC2_EN) - { - int frac = es1371->dac[1].ac & 0x7fff; - int idx = es1371->dac[1].ac >> 15; - int samp1_l = es1371->dac[1].filtered_l[idx]; - int samp1_r = es1371->dac[1].filtered_r[idx]; - int samp2_l = es1371->dac[1].filtered_l[(idx + 1) & 31]; - int samp2_r = es1371->dac[1].filtered_r[(idx + 1) & 31]; - - es1371->dac[1].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; - es1371->dac[1].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; - es1371->dac[1].ac += es1371->dac[1].vf; - es1371->dac[1].ac &= ((32 << 15) - 1); - if ((es1371->dac[1].ac >> (15+4)) != es1371->dac[1].f_pos) - { - es1371_next_sample_filtered(es1371, 1, es1371->dac[1].f_pos ? 16 : 0); - es1371->dac[1].f_pos = (es1371->dac[1].f_pos + 1) & 1; + if (dev->int_ctrl & INT_DAC2_EN) { + frac = dev->dac[1].ac & 0x7fff; + idx = dev->dac[1].ac >> 15; + samp1_l = dev->dac[1].filtered_l[idx]; + samp1_r = dev->dac[1].filtered_r[idx]; + samp2_l = dev->dac[1].filtered_l[(idx + 1) & 31]; + samp2_r = dev->dac[1].filtered_r[(idx + 1) & 31]; - es1371->dac[1].curr_samp_ct--; - if (es1371->dac[1].curr_samp_ct < 0) - { - es1371->int_status |= INT_STATUS_DAC2; - es1371_update_irqs(es1371); - es1371->dac[1].curr_samp_ct = es1371->dac[1].samp_ct; - } + dev->dac[1].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15; + dev->dac[1].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15; + dev->dac[1].ac += dev->dac[1].vf; + dev->dac[1].ac &= ((32 << 15) - 1); + if ((dev->dac[1].ac >> (15+4)) != dev->dac[1].f_pos) { + es1371_next_sample_filtered(dev, 1, dev->dac[1].f_pos ? 16 : 0); + dev->dac[1].f_pos = (dev->dac[1].f_pos + 1) & 1; + + dev->dac[1].curr_samp_ct--; + if (dev->dac[1].curr_samp_ct < 0) { + dev->int_status |= INT_STATUS_DAC2; + es1371_update_irqs(dev); + dev->dac[1].curr_samp_ct = dev->dac[1].samp_ct; } } + } } -static void es1371_get_buffer(int32_t *buffer, int len, void *p) + +static void +es1371_get_buffer(int32_t *buffer, int len, void *p) { - es1371_t *es1371 = (es1371_t *)p; - int c; + es1371_t *dev = (es1371_t *)p; + int c; - es1371_update(es1371); + es1371_update(dev); - for (c = 0; c < len * 2; c++) - buffer[c] += (es1371->buffer[c] / 2); - - es1371->pos = 0; + for (c = 0; c < len * 2; c++) + buffer[c] += (dev->buffer[c] / 2); + + dev->pos = 0; } -static void es1371_filter_cd_audio(int channel, double *buffer, void *p) + +static void +es1371_filter_cd_audio(int channel, double *buffer, void *p) { - es1371_t *es1371 = (es1371_t *)p; - int32_t c; - int cd = channel ? es1371->cd_vol_r : es1371->cd_vol_l; - int master = channel ? es1371->master_vol_r : es1371->master_vol_l; + es1371_t *dev = (es1371_t *)p; + int32_t c; + int cd = channel ? dev->cd_vol_r : dev->cd_vol_l; + int master = channel ? dev->master_vol_r : dev->master_vol_l; - c = (((int32_t) *buffer) * cd) >> 15; - c = (c * master) >> 15; + c = (((int32_t) *buffer) * cd) >> 15; + c = (c * master) >> 15; - *buffer = (double) c; + *buffer = (double) c; } -static inline double sinc(double x) + +static inline +double sinc(double x) { - return sin(M_PI * x) / (M_PI * x); + return sin(M_PI * x) / (M_PI * x); } -static void generate_es1371_filter() + +static void +generate_es1371_filter(void) { - /*Cutoff frequency = 1 / 32*/ - float fC = 1.0 / 32.0; - float gain; - int n; - - for (n = 0; n < ES1371_NCoef; n++) - { - /*Blackman window*/ - double w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(ES1371_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(ES1371_NCoef-1))); - /*Sinc filter*/ - double h = sinc(2.0 * fC * ((double)n - ((double)(ES1371_NCoef-1) / 2.0))); - - /*Create windowed-sinc filter*/ - low_fir_es1371_coef[n] = w * h; - } - - low_fir_es1371_coef[(ES1371_NCoef - 1) / 2] = 1.0; + /* Cutoff frequency = 1 / 32 */ + float fC = 1.0 / 32.0; + float gain; + int n; - gain = 0.0; - for (n = 0; n < ES1371_NCoef; n++) - gain += low_fir_es1371_coef[n] / (float)N; + for (n = 0; n < ES1371_NCoef; n++) { + /* Blackman window */ + double w = 0.42 - (0.5 * cos((2.0*n*M_PI)/(double)(ES1371_NCoef-1))) + (0.08 * cos((4.0*n*M_PI)/(double)(ES1371_NCoef-1))); + /* Sinc filter */ + double h = sinc(2.0 * fC * ((double)n - ((double)(ES1371_NCoef-1) / 2.0))); - gain /= 0.95; + /* Create windowed-sinc filter */ + low_fir_es1371_coef[n] = w * h; + } - /*Normalise filter, to produce unity gain*/ - for (n = 0; n < ES1371_NCoef; n++) - low_fir_es1371_coef[n] /= gain; -} + low_fir_es1371_coef[(ES1371_NCoef - 1) / 2] = 1.0; -static void *es1371_init(const device_t *info) -{ - es1371_t *es1371 = malloc(sizeof(es1371_t)); - memset(es1371, 0, sizeof(es1371_t)); - - sound_add_handler(es1371_get_buffer, es1371); - sound_set_cd_audio_filter(es1371_filter_cd_audio, es1371); + gain = 0.0; + for (n = 0; n < ES1371_NCoef; n++) + gain += low_fir_es1371_coef[n] / (float)N; - /* Add our own always-present game port to override the standalone ISAPnP one. */ - gameport_remap(gameport_add(&gameport_pnp_device), 0x200); + gain /= 0.95; - es1371->card = pci_add_card(info->local ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, es1371); - - timer_add(&es1371->dac[1].timer, es1371_poll, es1371, 1); - - generate_es1371_filter(); - - ac97_codec = &es1371->codec; - ac97_codec_count = 1; - ac97_codec_id = 0; - if (!info->local) /* let the machine decide the codec on onboard implementations */ - device_add(&cs4297a_device); - - return es1371; + /* Normalise filter, to produce unity gain */ + for (n = 0; n < ES1371_NCoef; n++) + low_fir_es1371_coef[n] /= gain; } -static void es1371_close(void *p) + +static void * +es1371_init(const device_t *info) { - es1371_t *es1371 = (es1371_t *)p; - - free(es1371); + es1371_t *dev = malloc(sizeof(es1371_t)); + memset(dev, 0x00, sizeof(es1371_t)); + + sound_add_handler(es1371_get_buffer, dev); + sound_set_cd_audio_filter(es1371_filter_cd_audio, dev); + + /* Add our own always-present game port to override the standalone ISAPnP one. */ + gameport_remap(gameport_add(&gameport_pnp_device), 0x200); + + dev->card = pci_add_card(info->local ? PCI_ADD_SOUND : PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, dev); + + timer_add(&dev->dac[1].timer, es1371_poll, dev, 1); + + generate_es1371_filter(); + + ac97_codec = &dev->codec; + ac97_codec_count = 1; + ac97_codec_id = 0; + /* Let the machine decide the codec on onboard implementations. */ + if (!info->local) + device_add(&cs4297a_device); + + es1371_reset(dev); + + return dev; } -static void es1371_speed_changed(void *p) + +static void +es1371_close(void *p) { - es1371_t *es1371 = (es1371_t *)p; - - es1371->dac[1].latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / 48000.0)); + es1371_t *dev = (es1371_t *) p; + + free(dev); } - -void es1371_add_status_info_dac(es1371_t *es1371, char *s, int max_len, int dac_nr) + + +static void +es1371_speed_changed(void *p) { - int ena = dac_nr ? INT_DAC2_EN : INT_DAC1_EN; - char *dac_name = dac_nr ? "DAC2 (Wave)" : "DAC1 (MIDI)"; - char temps[128]; + es1371_t *dev = (es1371_t *)p; - if (es1371->int_ctrl & ena) - { - int format = dac_nr ? ((es1371->si_cr >> 2) & 3) : (es1371->si_cr & 3); - double freq = 48000.0 * ((double)es1371->dac[dac_nr].vf / (32768.0 * 16.0)); - - switch (format) - { - case FORMAT_MONO_8: - snprintf(temps, 128, "%s format : 8-bit mono\n", dac_name); - break; - case FORMAT_STEREO_8: - snprintf(temps, 128, "%s format : 8-bit stereo\n", dac_name); - break; - case FORMAT_MONO_16: - snprintf(temps, 128, "%s format : 16-bit mono\n", dac_name); - break; - case FORMAT_STEREO_16: - snprintf(temps, 128, "%s format : 16-bit stereo\n", dac_name); - break; - } - - strncat(s, temps, max_len); - max_len -= strlen(temps); - - snprintf(temps, 128, "Playback frequency : %i Hz\n", (int)freq); - strncat(s, temps, max_len); - } - else - { - snprintf(temps, max_len, "%s stopped\n", dac_name); - strncat(s, temps, max_len); - } + dev->dac[1].latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / 48000.0)); } + const device_t es1371_device = { "Ensoniq AudioPCI (ES1371)", @@ -1417,7 +1893,7 @@ const device_t es1371_onboard_device = 1, es1371_init, es1371_close, - NULL, + es1371_reset, { NULL }, es1371_speed_changed, NULL,