From b3623582859c55112a16b1bba2005604b087b259 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 10 Aug 2022 17:48:32 -0400 Subject: [PATCH] Intel AC97 (Currently not functional) --- src/include/86box/snd_ac97_intel.h | 54 ++++++++ src/sound/CMakeLists.txt | 2 +- src/sound/snd_ac97_intel.c | 205 +++++++++++++++++++++++++++++ src/win/Makefile.mingw | 2 +- 4 files changed, 261 insertions(+), 2 deletions(-) create mode 100644 src/include/86box/snd_ac97_intel.h create mode 100644 src/sound/snd_ac97_intel.c diff --git a/src/include/86box/snd_ac97_intel.h b/src/include/86box/snd_ac97_intel.h new file mode 100644 index 000000000..7356c213e --- /dev/null +++ b/src/include/86box/snd_ac97_intel.h @@ -0,0 +1,54 @@ +/* + * Intel AC'97 Header + * + * Authors: Tiseno100, + * + * Copyright 2022 Tiseno100. + */ + + +/* + * Note: The Intel AC'97 code is divided into three parts + * + * 1. intel_ac97.c The main AC'97 code handling configuration. + * 3. intel_ac97_buffer.c The AC'97 buffer + * + * + * The general AC'97 configures the buffer base address and capabilities like channels, reset, interrupts etc. + * The AC'97 buffer is where all playback happens. +*/ + +#ifndef EMU_INTEL_AC97_H +# define EMU_INTEL_AC97_H +#ifdef __cplusplus +extern "C" { +#endif +#include <86box/mem.h> +#include <86box/snd_ac97.h> + +typedef struct intel_ac97_t +{ + uint16_t ac97_base; + uint16_t mixer_base; + uint32_t buffer_base; + + uint8_t regs[256]; + int irq; + + ac97_codec_t *mixer; + mem_mapping_t *buffer_location; +} intel_ac97_t; + +/* AC'97 Configuration */ +extern void intel_ac97_base(int enable, uint16_t addr, intel_ac97_t *dev); +extern void intel_ac97_mixer_base(int enable, uint16_t addr, intel_ac97_t *dev); +extern void intel_ac97_set_irq(int irq, intel_ac97_t *dev); + +extern const device_t intel_ac97_device; +extern const device_t intel_ac97_mixer_device; + +#ifdef __cplusplus +} +#endif + +#endif /*EMU_INTEL_AC97_H*/ diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 581f8d517..dfc2f1a3d 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -14,7 +14,7 @@ # add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_opl_ymfm.cpp snd_resid.cc - midi.c snd_speaker.c snd_pssj.c snd_lpt_dac.c snd_ac97_codec.c snd_ac97_via.c + midi.c snd_speaker.c snd_pssj.c snd_lpt_dac.c snd_ac97_codec.c snd_ac97_intel.c snd_ac97_via.c snd_lpt_dss.c snd_ps1.c snd_adlib.c snd_adlibgold.c snd_ad1848.c snd_audiopci.c snd_azt2316a.c snd_cms.c snd_cmi8x38.c snd_cs423x.c snd_gus.c snd_sb.c snd_sb_dsp.c snd_emu8k.c snd_mpu401.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c) diff --git a/src/sound/snd_ac97_intel.c b/src/sound/snd_ac97_intel.c new file mode 100644 index 000000000..b5e4ac52c --- /dev/null +++ b/src/sound/snd_ac97_intel.c @@ -0,0 +1,205 @@ +/* + * Intel AC'97 + * + * Authors: Tiseno100, + * + * Copyright 2022 Tiseno100. + */ + +/* + * Buffers, AC-Link and other things require understanding. + * But I also need a functional board with AC'97 to continue. +*/ + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/timer.h> +#include <86box/io.h> +#include <86box/device.h> + +#include <86box/snd_ac97.h> +#include <86box/snd_ac97_intel.h> + +#ifdef ENABLE_INTEL_AC97_LOG +int intel_ac97_do_log = ENABLE_INTEL_AC97_LOG; +static void +intel_ac97_log(const char *fmt, ...) +{ + va_list ap; + + if (intel_ac97_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define intel_ac97_log(fmt, ...) +#endif + + +/* Mixer Configuration */ +static void +intel_ac97_mixer_write(uint16_t addr, uint16_t val, void *priv) +{ + intel_ac97_t *dev = (intel_ac97_t *) priv; + + addr -= dev->mixer_base; + ac97_codec_writew(dev->mixer, addr, val); +} + +static uint16_t +intel_ac97_mixer_read(uint16_t addr, void *priv) +{ + intel_ac97_t *dev = (intel_ac97_t *) priv; + + addr -= dev->mixer_base; + return ac97_codec_readw(dev->mixer, addr); +} + +void +intel_ac97_mixer_base(int enable, uint16_t addr, intel_ac97_t *dev) +{ + if(dev->mixer_base != 0) + io_removehandler(dev->mixer_base, 256, NULL, intel_ac97_mixer_read, NULL, NULL, intel_ac97_mixer_write, NULL, dev); + + intel_ac97_log("Intel AC'97 Mixer: Base has been set on 0x%x\n", addr); + dev->mixer_base = addr; + + if((addr != 0) && enable) + io_sethandler(addr, 256, NULL, intel_ac97_mixer_read, NULL, NULL, intel_ac97_mixer_write, NULL, dev); +} + + +/* AC'97 Configuration */ +void +intel_ac97_set_irq(int irq, intel_ac97_t *dev) +{ + intel_ac97_log("Intel AC'97: IRQ Base was set to %d\n"); + + dev->irq = irq; +} + +static void +intel_ac97_write(uint16_t addr, uint8_t val, void *priv) +{ + intel_ac97_t *dev = (intel_ac97_t *) priv; + addr -= dev->ac97_base; + + intel_ac97_log("Intel AC'97: dev->regs[%02x] = %02x\n", addr, val); + + switch(addr) + { + case 0x10 ... 0x13: /* Buffer BAR */ + dev->regs[addr] = val; + break; + + case 0x15: /* Last Valid Index */ + dev->regs[addr] &= val; + break; + + case 0x16: /* Status */ + dev->regs[addr] &= val; + break; + + case 0x1b: /* Control */ + dev->regs[addr] = val & 0x1f; + break; + + case 0x2c: /* Global Control */ + dev->regs[addr] = val & 0x3f; + break; + + case 0x2e: /* Global Control */ + dev->regs[addr] = val & 0x30; + break; + + case 0x34: /* Codec Access Semaphore */ + dev->regs[addr] = val & 1; + break; + } +} + + +static uint8_t +intel_ac97_read(uint16_t addr, void *priv) +{ + intel_ac97_t *dev = (intel_ac97_t *) priv; + addr -= dev->ac97_base; + + if(addr < 0x40) { + intel_ac97_log("Intel AC'97: dev->regs[%02x] (%02x)\n", addr, dev->regs[addr]); + return dev->regs[addr]; + } + else + return 0xff; +} + +void +intel_ac97_base(int enable, uint16_t addr, intel_ac97_t *dev) +{ + if(dev->ac97_base != 0) + io_removehandler(dev->ac97_base, 64, intel_ac97_read, NULL, NULL, intel_ac97_write, NULL, NULL, dev); + + intel_ac97_log("Intel AC'97: Base has been set on 0x%x\n", addr); + dev->ac97_base = addr; + + if((addr != 0) && enable) + io_sethandler(addr, 64, intel_ac97_read, NULL, NULL, intel_ac97_write, NULL, NULL, dev); + +} + + +static void +intel_ac97_reset(void *priv) +{ + intel_ac97_t *dev = (intel_ac97_t *) priv; + memset(dev->regs, 0, sizeof(dev->regs)); /* Wash out the registers */ + + // We got nothing here yet +} + + +static void +intel_ac97_close(void *priv) +{ + intel_ac97_t *dev = (intel_ac97_t *) priv; + + free(dev); +} + + +static void * +intel_ac97_init(const device_t *info) +{ + intel_ac97_t *dev = (intel_ac97_t *) malloc(sizeof(intel_ac97_t)); + memset(dev, 0, sizeof(intel_ac97_t)); + + intel_ac97_log("Intel AC'97: Started!\n"); + // We got nothing here yet + + dev->mixer = device_add(&ad1881_device); /* Add a mixer with no real functionality for now */ + + return dev; +} + +const device_t intel_ac97_device = { + .name = "Intel AC'97 Version 2.1", + .internal_name = "intel_ac97", + .flags = 0, + .local = 0, + .init = intel_ac97_init, + .close = intel_ac97_close, + .reset = intel_ac97_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index a19510828..7f4243c2d 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -690,7 +690,7 @@ SNDOBJ := sound.o \ snd_ps1.o \ snd_lpt_dac.o snd_lpt_dss.o \ snd_adlib.o snd_adlibgold.o snd_ad1848.o snd_audiopci.o \ - snd_ac97_codec.o snd_ac97_via.o \ + snd_ac97_codec.o snd_ac97_intel.o snd_ac97_via.o \ snd_azt2316a.o snd_cs423x.o snd_cmi8x38.o \ snd_cms.o \ snd_gus.o \