Merge branch 'master' of https://github.com/86Box/86Box.git into EngiNerd

This commit is contained in:
EngiNerd89
2021-06-13 21:45:53 +02:00
73 changed files with 3442 additions and 1587 deletions

View File

@@ -208,34 +208,32 @@ void
pclog_ex(const char *fmt, va_list ap)
{
#ifndef RELEASE_BUILD
char temp[1024];
char temp[1024];
if (strcmp(fmt, "") == 0)
if (strcmp(fmt, "") == 0)
return;
if (stdlog == NULL) {
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else {
} else
stdlog = stdout;
}
}
}
vsprintf(temp, fmt, ap);
if (suppr_seen && ! strcmp(buff, temp)) {
vsprintf(temp, fmt, ap);
if (suppr_seen && ! strcmp(buff, temp))
seen++;
} else {
if (suppr_seen && seen) {
else {
if (suppr_seen && seen)
fprintf(stdlog, "*** %d repeats ***\n", seen);
}
seen = 0;
strcpy(buff, temp);
fprintf(stdlog, temp, ap);
}
fprintf(stdlog, "%s", temp);
}
fflush(stdlog);
fflush(stdlog);
#endif
}
@@ -267,47 +265,86 @@ pclog(const char *fmt, ...)
void
fatal(const char *fmt, ...)
{
char temp[1024];
va_list ap;
char *sp;
char temp[1024];
va_list ap;
char *sp;
va_start(ap, fmt);
va_start(ap, fmt);
if (stdlog == NULL) {
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else {
} else
stdlog = stdout;
}
}
}
vsprintf(temp, fmt, ap);
fprintf(stdlog, "%s", temp);
fflush(stdlog);
va_end(ap);
vsprintf(temp, fmt, ap);
fprintf(stdlog, "%s", temp);
fflush(stdlog);
va_end(ap);
nvr_save();
nvr_save();
config_save();
config_save();
#ifdef ENABLE_808X_LOG
dumpregs(1);
dumpregs(1);
#endif
/* Make sure the message does not have a trailing newline. */
if ((sp = strchr(temp, '\n')) != NULL) *sp = '\0';
/* Make sure the message does not have a trailing newline. */
if ((sp = strchr(temp, '\n')) != NULL) *sp = '\0';
/* Cleanly terminate all of the emulator's components so as
to avoid things like threads getting stuck. */
do_stop();
/* Cleanly terminate all of the emulator's components so as
to avoid things like threads getting stuck. */
do_stop();
ui_msgbox(MBX_ERROR | MBX_FATAL | MBX_ANSI, temp);
ui_msgbox(MBX_ERROR | MBX_FATAL | MBX_ANSI, temp);
fflush(stdlog);
fflush(stdlog);
exit(-1);
exit(-1);
}
void
fatal_ex(const char *fmt, va_list ap)
{
char temp[1024];
char *sp;
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else
stdlog = stdout;
}
vsprintf(temp, fmt, ap);
fprintf(stdlog, "%s", temp);
fflush(stdlog);
nvr_save();
config_save();
#ifdef ENABLE_808X_LOG
dumpregs(1);
#endif
/* Make sure the message does not have a trailing newline. */
if ((sp = strchr(temp, '\n')) != NULL) *sp = '\0';
/* Cleanly terminate all of the emulator's components so as
to avoid things like threads getting stuck. */
do_stop();
ui_msgbox(MBX_ERROR | MBX_FATAL | MBX_ANSI, temp);
fflush(stdlog);
}

View File

@@ -7,15 +7,14 @@
* This file is part of the 86Box distribution.
*
* Implementation of the G2 GC100/GC100A chipset.
* NOTE: As documentation is currently available only for the
* CG100 chipset, the GC100A chipset has been reverese-engineered.
* Thus, its behavior may not be fully accurate.
* NOTE: As documentation is currently available only for the
* CG100 chipset, the GC100A chipset has been reverese-engineered.
* Thus, its behavior may not be fully accurate.
*
* Authors: EngiNerd <webmaster.crrc@yahoo.it>
* Authors: EngiNerd, <webmaster.crrc@yahoo.it>
*
* Copyright 2020-2021 EngiNerd
* Copyright 2020-2021 EngiNerd.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -42,15 +41,16 @@
#include <86box/io.h>
#include <86box/video.h>
typedef struct
{
uint8_t reg[0x10];
} gc100_t;
#define ENABLE_GC100_LOG 1
#ifdef ENABLE_GC100_LOG
int gc100_do_log = ENABLE_GC100_LOG;
static void
gc100_log(const char *fmt, ...)
{
@@ -66,136 +66,130 @@ gc100_log(const char *fmt, ...)
#define gc100_log(fmt, ...)
#endif
static uint8_t
get_fdd_switch_settings(){
get_fdd_switch_settings(void)
{
int i, fdd_count = 0;
for (i = 0; i < FDD_NUM; i++) {
if (fdd_get_flags(i))
fdd_count++;
if (fdd_get_flags(i))
fdd_count++;
}
if (!fdd_count)
return 0x00;
else
return ((fdd_count - 1) << 6) | 0x01;
}
static uint8_t
get_videomode_switch_settings(){
get_videomode_switch_settings(void)
{
if (video_is_mda())
return 0x30;
return 0x30;
else if (video_is_cga())
return 0x20; /* 0x10 would be 40x25 */
return 0x20; /* 0x10 would be 40x25 */
else
return 0x00;
return 0x00;
}
static void
gc100_write(uint16_t port, uint8_t val, void *priv)
{
gc100_t *dev = (gc100_t *) priv;
uint16_t addr = port & 0xf;
dev->reg[addr] = val;
switch (addr)
{
/* addr 0x2
* bits 5-7: not used
* bit 4: intenal memory wait states
* bits 2-3: external memory wait states
* bits 0-1: i/o access wait states
*/
case 0x2:
break;
/* addr 0x3
* bits 1-7: not used
* bit 0: turbo 0 xt 1
*/
case 0x3:
if (val & 0x1)
cpu_dynamic_switch(0);
else
cpu_dynamic_switch(cpu);
break;
/* addr 0x5
* programmable dip-switches
* bits 6-7: floppy drive number
* bits 4-5: video mode
* bits 2-3: memory size
* bit 1: fpu
* bit 0: not used
*/
/* addr 0x6 */
/* addr 0x7 */
switch (addr) {
/* addr 0x2
* bits 5-7: not used
* bit 4: intenal memory wait states
* bits 2-3: external memory wait states
* bits 0-1: i/o access wait states
*/
case 2:
break;
/* addr 0x3
* bits 1-7: not used
* bit 0: turbo 0 xt 1
*/
case 3:
if (val & 1)
cpu_dynamic_switch(0);
else
cpu_dynamic_switch(cpu);
break;
/* addr 0x5
* programmable dip-switches
* bits 6-7: floppy drive number
* bits 4-5: video mode
* bits 2-3: memory size
* bit 1: fpu
* bit 0: not used
*/
/* addr 0x6 */
/* addr 0x7 */
}
gc100_log("GC100: Write %02x at %02x\n", val, port);
}
static uint8_t
gc100_read(uint16_t port, void *priv)
{
gc100_t *dev = (gc100_t *) priv;
uint8_t ret = 0xff;
uint16_t addr = port & 0xf;
ret = dev->reg[addr];
gc100_log("GC100: Read %02x at %02x\n", ret, port);
switch (addr)
{
/* addr 0x2
* bits 5-7: not used
* bit 4: intenal memory wait states
* bits 2-3: external memory wait states
* bits 0-1: i/o access wait states
*/
case 0x2:
break;
/* addr 0x3
* bits 1-7: not used
* bit 0: turbo 0 xt 1
*/
case 0x3:
break;
/* addr 0x5
* programmable dip-switches
* bits 6-7: floppy drive number
* bits 4-5: video mode
* bits 2-3: memory size
* bit 1: fpu
* bit 0: not used
*/
case 0x5:
ret = ret & 0x0c;
ret |= get_fdd_switch_settings();
ret |= get_videomode_switch_settings();
if (hasfpu)
ret |= 0x02;
switch (addr) {
/* addr 0x2
* bits 5-7: not used
* bit 4: intenal memory wait states
* bits 2-3: external memory wait states
* bits 0-1: i/o access wait states
*/
case 0x2:
break;
break;
/* addr 0x6 */
/* addr 0x7 */
/* addr 0x3
* bits 1-7: not used
* bit 0: turbo 0 xt 1
*/
case 0x3:
break;
/* addr 0x5
* programmable dip-switches
* bits 6-7: floppy drive number
* bits 4-5: video mode
* bits 2-3: memory size
* bit 1: fpu
* bit 0: not used
*/
case 0x5:
ret = ret & 0x0c;
ret |= get_fdd_switch_settings();
ret |= get_videomode_switch_settings();
if (hasfpu)
ret |= 0x02;
break;
/* addr 0x6 */
/* addr 0x7 */
}
return ret;
@@ -210,6 +204,7 @@ gc100_close(void *priv)
free(dev);
}
static void *
gc100_init(const device_t *info)
{
@@ -222,13 +217,12 @@ gc100_init(const device_t *info)
dev->reg[0x6] = 0x0;
dev->reg[0x7] = 0x0;
/* GC100A */
if(info->local) {
if (info->local) {
/* GC100A */
io_sethandler(0x0c2, 0x02, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev);
io_sethandler(0x0c5, 0x03, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev);
}
/* GC100 */
else {
} else {
/* GC100 */
io_sethandler(0x022, 0x02, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev);
io_sethandler(0x025, 0x01, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev);
}
@@ -236,6 +230,7 @@ gc100_init(const device_t *info)
return dev;
}
const device_t gc100_device = {
"G2 GC100",
0,
@@ -253,4 +248,3 @@ const device_t gc100a_device = {
{ NULL }, NULL, NULL,
NULL
};

View File

@@ -43,7 +43,7 @@
typedef struct
{
uint8_t id, smram_locked,
uint8_t has_ide, smram_locked,
regs[256];
uint16_t timer_base,
@@ -165,10 +165,6 @@ i420ex_write(int func, int addr, uint8_t val, void *priv)
if (((addr >= 0x0f) && (addr < 0x4c)) && (addr != 0x40))
return;
/* The IB (original) variant of the I420EX has no PCI IRQ steering. */
if ((addr >= 0x60) && (addr <= 0x63) && (dev->id < 0x03))
return;
switch (addr) {
case 0x05:
dev->regs[addr] = (val & 0x01);
@@ -186,21 +182,21 @@ i420ex_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x48:
dev->regs[addr] = (val & 0x3f);
#ifdef USE_420EX_IDE
ide_pri_disable();
switch (val & 0x03) {
case 0x01:
ide_set_base(0, 0x01f0);
ide_set_side(0, 0x03f6);
ide_pri_enable();
break;
case 0x02:
ide_set_base(0, 0x0170);
ide_set_side(0, 0x0376);
ide_pri_enable();
break;
if (dev->has_ide) {
ide_pri_disable();
switch (val & 0x03) {
case 0x01:
ide_set_base(0, 0x01f0);
ide_set_side(0, 0x03f6);
ide_pri_enable();
break;
case 0x02:
ide_set_base(0, 0x0170);
ide_set_side(0, 0x0376);
ide_pri_enable();
break;
}
}
#endif
break;
case 0x49: case 0x53:
dev->regs[addr] = (val & 0x1f);
@@ -385,7 +381,6 @@ i420ex_reset_hard(void *priv)
dev->regs[0x02] = 0x86; dev->regs[0x03] = 0x04; /*82378IB (I420EX)*/
dev->regs[0x04] = 0x07;
dev->regs[0x07] = 0x02;
dev->regs[0x08] = dev->id;
dev->regs[0x4c] = 0x4d;
dev->regs[0x4e] = 0x03;
@@ -404,8 +399,9 @@ i420ex_reset_hard(void *priv)
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
if (dev->has_ide)
ide_pri_disable();
}
@@ -442,6 +438,8 @@ i420ex_reset(void *p)
i420ex_t *dev = (i420ex_t *) p;
int i;
i420ex_write(0, 0x48, 0x00, p);
for (i = 0; i < 7; i++)
i420ex_write(0, 0x59 + i, 0x00, p);
@@ -488,13 +486,11 @@ i420ex_speed_changed(void *priv)
if (te)
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
if (dev->id == 0x03) {
te = timer_is_enabled(&dev->fast_off_timer);
te = timer_is_enabled(&dev->fast_off_timer);
timer_stop(&dev->fast_off_timer);
if (te)
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
}
timer_stop(&dev->fast_off_timer);
if (te)
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
}
@@ -508,12 +504,10 @@ i420ex_init(const device_t *info)
pci_add_card(PCI_ADD_NORTHBRIDGE, i420ex_read, i420ex_write, dev);
dev->id = info->local;
dev->has_ide = info->local;
timer_add(&dev->fast_off_timer, i420ex_fast_off_count, dev, 0);
i420ex_reset_hard(dev);
cpu_fast_off_flags = 0x00000000;
cpu_fast_off_val = dev->regs[0xa8];
@@ -527,12 +521,9 @@ i420ex_init(const device_t *info)
dma_alias_set();
#ifdef USE_420EX_IDE
device_add(&ide_pci_device);
ide_pri_disable();
#else
device_add(&ide_pci_2ch_device);
#endif
i420ex_reset_hard(dev);
return dev;
}
@@ -551,3 +542,18 @@ const device_t i420ex_device =
NULL,
NULL
};
const device_t i420ex_ide_device =
{
"Intel 82420EX (With IDE)",
DEVICE_PCI,
0x01,
i420ex_init,
i420ex_close,
i420ex_reset,
{ NULL },
i420ex_speed_changed,
NULL,
NULL
};

View File

@@ -396,9 +396,9 @@ piix_write(int func, int addr, uint8_t val, void *priv)
else
fregs[addr] = val & 0xcf;
if (val & 0x80)
pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED);
pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED);
else
pci_set_mirq_routing(PCI_MIRQ0, val & 0xf);
pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf);
piix_log("MIRQ%i is %s\n", addr & 0x01, (val & 0x20) ? "disabled" : "enabled");
}
break;
@@ -921,8 +921,7 @@ board_read(uint16_t port, void *priv)
uint8_t ret = 0x64;
if (port == 0x0078)
ret = 0x00;
// ret = dev->board_config[0];
ret = dev->board_config[0];
else if (port == 0x0079)
ret = dev->board_config[1];
else if (port == 0x00e0)

View File

@@ -8,12 +8,11 @@
*
* Implementation of the OPTi 82C283 chipset.
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
*
* Authors: Tiseno100
*
* Copyright 2021 Tiseno100
*
* Copyright 2021 Tiseno100.
* Copyright 2021 Miran Grca.
*/
#include <stdarg.h>
@@ -31,8 +30,10 @@
#include <86box/mem.h>
#include <86box/chipset.h>
#ifdef ENABLE_OPTI283_LOG
int opti283_do_log = ENABLE_OPTI283_LOG;
static void
opti283_log(const char *fmt, ...)
{
@@ -49,72 +50,200 @@ opti283_log(const char *fmt, ...)
#define opti283_log(fmt, ...)
#endif
typedef struct
{
uint8_t index,
regs[256];
uint32_t phys, virt;
} mem_remapping_t;
typedef struct
{
uint8_t index, shadow_high,
regs[256];
mem_remapping_t mem_remappings[2];
mem_mapping_t mem_mappings[2];
} opti283_t;
static void opti283_shadow_recalc(opti283_t *dev)
static uint8_t
opti283_read_remapped_ram(uint32_t addr, void *priv)
{
mem_set_mem_state_both(0xf0000, 0x10000, (dev->regs[0x11] & 0x80) ? (MEM_READ_EXTANY | MEM_WRITE_INTERNAL) : (MEM_READ_INTERNAL | ((dev->regs[0x14] & 0x80) ? MEM_WRITE_INTERNAL : MEM_WRITE_DISABLED)));
mem_remapping_t *dev = (mem_remapping_t *) priv;
for (uint32_t i = 0; i < 4; i++)
{
if (dev->regs[0x11] & 0x40)
mem_set_mem_state_both(0xe0000 + (i << 14), 0x4000, (dev->regs[0x12] & (1 << (4 + i))) ? (MEM_READ_INTERNAL | ((dev->regs[0x11] & 4) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
mem_set_mem_state_both(0xe0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
return mem_read_ram((addr - dev->virt) + dev->phys, priv);
}
if (dev->regs[0x11] & 0x20)
mem_set_mem_state_both(0xd0000 + (i << 14), 0x4000, (dev->regs[0x12] & (1 << i)) ? (MEM_READ_INTERNAL | ((dev->regs[0x11] & 2) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
else
mem_set_mem_state_both(0xd0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if (dev->regs[0x11] & 0x10)
mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, (dev->regs[0x13] & (1 << (4 + i))) ? (MEM_READ_INTERNAL | ((dev->regs[0x11] & 1) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
else
mem_set_mem_state_both(0xc0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
static uint16_t
opti283_read_remapped_ramw(uint32_t addr, void *priv)
{
mem_remapping_t *dev = (mem_remapping_t *) priv;
return mem_read_ramw((addr - dev->virt) + dev->phys, priv);
}
static uint32_t
opti283_read_remapped_raml(uint32_t addr, void *priv)
{
mem_remapping_t *dev = (mem_remapping_t *) priv;
return mem_read_raml((addr - dev->virt) + dev->phys, priv);
}
static void
opti283_write_remapped_ram(uint32_t addr, uint8_t val, void *priv)
{
mem_remapping_t *dev = (mem_remapping_t *) priv;
mem_write_ram((addr - dev->virt) + dev->phys, val, priv);
}
static void
opti283_write_remapped_ramw(uint32_t addr, uint16_t val, void *priv)
{
mem_remapping_t *dev = (mem_remapping_t *) priv;
mem_write_ramw((addr - dev->virt) + dev->phys, val, priv);
}
static void
opti283_write_remapped_raml(uint32_t addr, uint32_t val, void *priv)
{
mem_remapping_t *dev = (mem_remapping_t *) priv;
mem_write_raml((addr - dev->virt) + dev->phys, val, priv);
}
static void
opti283_shadow_recalc(opti283_t *dev)
{
uint32_t i, base;
uint32_t rbase;
uint8_t sh_enable, sh_mode;
uint8_t rom, sh_copy;
shadowbios = shadowbios_write = 0;
dev->shadow_high = 0;
if (dev->regs[0x11] & 0x80) {
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
shadowbios_write = 1;
} else {
shadowbios = 1;
if (dev->regs[0x14] & 0x80) {
mem_set_mem_state_both(0xf0000, 0x01000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
shadowbios_write = 1;
} else
mem_set_mem_state_both(0xf0000, 0x01000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
mem_set_mem_state_both(0xf1000, 0x0f000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
}
sh_copy = dev->regs[0x11] & 0x08;
for (i = 0; i < 12; i++) {
base = 0xc0000 + (i << 14);
if (i >= 4)
sh_enable = dev->regs[0x12] & (1 << (i - 4));
else
sh_enable = dev->regs[0x13] & (1 << (i + 4));
sh_mode = dev->regs[0x11] & (1 << (i >> 2));
rom = dev->regs[0x11] & (1 << ((i >> 2) + 4));
pclog("OPTI 283: %i/%08X: %i, %i, %i\n", i, base, (i >= 4) ? (1 << (i - 4)) : (1 << (i + 4)), (1 << (i >> 2)), (1 << ((i >> 2) + 4)));
if (sh_enable && rom) {
if (base >= 0x000e0000)
shadowbios |= 1;
if (base >= 0x000d0000)
dev->shadow_high |= 1;
if (sh_mode) {
if (base >= 0x000e0000)
shadowbios_write |= 1;
if (sh_copy)
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
} else
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
} else {
if (base >= 0xe0000)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_DISABLED);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED);
}
}
rbase = ((uint32_t) (dev->regs[0x13] & 0x0f)) << 20;
if (rbase > 0) {
dev->mem_remappings[0].virt = rbase;
mem_mapping_set_addr(&dev->mem_mappings[0], rbase, 0x00020000);
if (!dev->shadow_high) {
rbase += 0x00020000;
dev->mem_remappings[1].virt = rbase;
mem_mapping_set_addr(&dev->mem_mappings[1], rbase , 0x00020000);
} else
mem_mapping_disable(&dev->mem_mappings[1]);
} else {
mem_mapping_disable(&dev->mem_mappings[0]);
mem_mapping_disable(&dev->mem_mappings[1]);
}
}
static void
opti283_write(uint16_t addr, uint8_t val, void *priv)
{
opti283_t *dev = (opti283_t *)priv;
switch (addr)
{
case 0x22:
dev->index = val;
break;
case 0x24:
opti283_log("OPTi 283: dev->regs[%02x] = %02x\n", dev->index, val);
switch (addr) {
case 0x22:
dev->index = val;
break;
switch (dev->index)
{
case 0x10:
dev->regs[dev->index] = val;
break;
case 0x24:
opti283_log("OPTi 283: dev->regs[%02x] = %02x\n", dev->index, val);
case 0x11:
case 0x12:
case 0x13:
case 0x14:
dev->regs[dev->index] = val;
opti283_shadow_recalc(dev);
break;
}
break;
switch (dev->index) {
case 0x10:
dev->regs[dev->index] = val;
break;
case 0x14:
reset_on_hlt = !!(val & 0x40);
/* FALLTHROUGH */
case 0x11: case 0x12:
case 0x13:
dev->regs[dev->index] = val;
opti283_shadow_recalc(dev);
break;
}
break;
}
}
static uint8_t
opti283_read(uint16_t addr, void *priv)
{
opti283_t *dev = (opti283_t *)priv;
return (addr == 0x24) ? dev->regs[dev->index] : 0xff;
uint8_t ret = 0xff;
if (addr == 0x24)
ret = dev->regs[dev->index];
return ret;
}
static void
opti283_close(void *priv)
{
@@ -123,22 +252,40 @@ opti283_close(void *priv)
free(dev);
}
static void *
opti283_init(const device_t *info)
{
opti283_t *dev = (opti283_t *)malloc(sizeof(opti283_t));
memset(dev, 0, sizeof(opti283_t));
memset(dev, 0x00, sizeof(opti283_t));
io_sethandler(0x0022, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev);
io_sethandler(0x0024, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev);
dev->regs[0x10] = 0x3f;
dev->regs[0x11] = 0xf0;
dev->mem_remappings[0].phys = 0x000a0000;
dev->mem_remappings[1].phys = 0x000d0000;
mem_mapping_add(&dev->mem_mappings[0], 0, 0x00020000,
opti283_read_remapped_ram, opti283_read_remapped_ramw, opti283_read_remapped_raml,
opti283_write_remapped_ram, opti283_write_remapped_ramw, opti283_write_remapped_raml,
&ram[dev->mem_remappings[0].phys], MEM_MAPPING_INTERNAL, &dev->mem_remappings[0]);
mem_mapping_disable(&dev->mem_mappings[0]);
mem_mapping_add(&dev->mem_mappings[1], 0, 0x00020000,
opti283_read_remapped_ram, opti283_read_remapped_ramw, opti283_read_remapped_raml,
opti283_write_remapped_ram, opti283_write_remapped_ramw, opti283_write_remapped_raml,
&ram[dev->mem_remappings[1].phys], MEM_MAPPING_INTERNAL, &dev->mem_remappings[1]);
mem_mapping_disable(&dev->mem_mappings[1]);
opti283_shadow_recalc(dev);
return dev;
}
const device_t opti283_device = {
"OPTi 82C283",
0,
@@ -146,7 +293,8 @@ const device_t opti283_device = {
opti283_init,
opti283_close,
NULL,
{NULL},
{ NULL },
NULL,
NULL,
NULL};
NULL
};

View File

@@ -589,6 +589,14 @@ load_machine(void)
machine = machine_get_machine_from_internal_name("m30015");
else if (! strcmp(p, "cbm_sl386sx25"))
machine = machine_get_machine_from_internal_name("cmdsl386sx25");
else if (! strcmp(p, "award386dx")) /* ...merged machines... */
machine = machine_get_machine_from_internal_name("award486");
else if (! strcmp(p, "ami386dx"))
machine = machine_get_machine_from_internal_name("ami486");
else if (! strcmp(p, "mr386dx"))
machine = machine_get_machine_from_internal_name("mr486");
else if (! strcmp(p, "fw6400gx_s1"))
machine = machine_get_machine_from_internal_name("fw6400gx");
else if (! strcmp(p, "president")) { /* ...and removed machines */
machine = machine_get_machine_from_internal_name("mb500n");
migrate_from = NULL;

View File

@@ -142,8 +142,7 @@ void (*cpu_exec)(int cycs);
static uint8_t ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, ccr6;
static int cyrix_addr, cpu_rom_read_cycles = 4;
static uint64_t rom_read_timing_ns = 150;
static int cyrix_addr;
static void cpu_write(uint16_t addr, uint8_t val, void *priv);
@@ -359,6 +358,8 @@ cpu_set(void)
acycs = 0;
#endif
soft_reset_pci = 0;
cpu_alt_reset = 0;
unmask_a20_in_smm = 0;
@@ -407,7 +408,10 @@ cpu_set(void)
isa_cycles = cpu_s->atclk_div;
cpu_rom_prefetch_cycles = (cpu_rom_read_cycles * cpu_s->rspeed * rom_read_timing_ns + 999999999ULL) / 1000000000ULL;
if (cpu_s->rspeed <= 8000000)
cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles;
else
cpu_rom_prefetch_cycles = cpu_s->rspeed / 1000000;
cpu_set_isa_pci_div(0);
cpu_set_pci_speed(0);
@@ -1276,7 +1280,6 @@ cpu_set(void)
break;
case CPU_CYRIX3S:
case CPU_EDEN: /* This until proper timings get discovered */
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f);
#else
@@ -1377,8 +1380,10 @@ cpu_set_isa_speed(int speed)
if (speed) {
cpu_isa_speed = speed;
pc_speed_changed();
} else
} else if (cpu_busspeed >= 8000000)
cpu_isa_speed = 8000000;
else
cpu_isa_speed = cpu_busspeed;
cpu_log("cpu_set_isa_speed(%d) = %d\n", speed, cpu_isa_speed);
}
@@ -2011,58 +2016,6 @@ cpu_CPUID(void)
break;
}
break;
case CPU_EDEN:
switch (EAX) {
case 0:
EAX = 1;
if (msr.fcr2 & (1 << 14)) {
EBX = msr.fcr3 >> 32;
ECX = msr.fcr3 & 0xffffffff;
EDX = msr.fcr2 >> 32;
} else {
EBX = 0x746e6543; /* CentaurHauls */
ECX = 0x736c7561;
EDX = 0x48727561;
}
break;
case 1:
EAX = CPUID;
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MMX | CPUID_MTRR;
if (cpu_has_feature(CPU_FEATURE_CX8))
EDX |= CPUID_CMPXCHG8B;
break;
case 0x80000000:
EAX = 0x80000006;
break;
case 0x80000001:
EAX = CPUID;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_MMX | CPUID_MTRR | CPUID_3DNOW;
if (cpu_has_feature(CPU_FEATURE_CX8))
EDX |= CPUID_CMPXCHG8B;
break;
case 0x80000002: /* Processor name string */
case 0x80000003:
case 0x80000004:
EAX = 0x20414956; /* VIA Samuel 2 */
EBX = 0x756d6153;
ECX = 0x32206c65;
EDX = 0x00000000;
break;
case 0x80000005: /* Cache information */
EBX = 0x08800880; /* TLBs */
ECX = 0x40040120; /* L1 data cache */
EDX = 0x40020120; /* L1 instruction cache */
break;
case 0x80000006:
ECX = 0x40040120; /* L2 data cache */
break;
default:
EAX = EBX = ECX = EDX = 0;
break;
}
break;
}
}
@@ -2153,7 +2106,6 @@ cpu_RDMSR(void)
break;
case CPU_CYRIX3S:
case CPU_EDEN:
EAX = EDX = 0;
switch (ECX) {
case 0x10:
@@ -2605,7 +2557,6 @@ cpu_WRMSR(void)
break;
case CPU_CYRIX3S:
case CPU_EDEN:
switch (ECX) {
case 0x10:
tsc = EAX | ((uint64_t)EDX << 32);
@@ -3069,5 +3020,6 @@ cpu_update_waitstates(void)
cpu_mem_prefetch_cycles = cpu_prefetch_cycles;
cpu_rom_prefetch_cycles = (cpu_rom_read_cycles * cpu_s->rspeed * rom_read_timing_ns + 999999999ULL) / 1000000000ULL;
if (cpu_s->rspeed <= 8000000)
cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles;
}

View File

@@ -76,7 +76,6 @@ enum {
CPU_K6_2P,
CPU_K6_3P,
CPU_CYRIX3S,
CPU_EDEN,
CPU_PENTIUMPRO, /* 686 class CPUs */
CPU_PENTIUM2,
CPU_PENTIUM2D
@@ -247,7 +246,7 @@ typedef struct {
uint64_t ia32_pmc[8]; /* 0x000000c1 - 0x000000c8 */
uint64_t mtrr_cap; /* 0x000000fe */
/* IDT WinChip and WinChip 2 MSR's that are also on the VIA Cyrix III and Eden */
/* IDT WinChip and WinChip 2 MSR's that are also on the VIA Cyrix III */
uint32_t fcr; /* 0x00000107 (IDT), 0x00001107 (VIA) */
uint64_t fcr2, fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */
@@ -266,7 +265,7 @@ typedef struct {
uint64_t ecx1e0; /* 0x000001e0 */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also
on the VIA Cyrix III and Eden */
on the VIA Cyrix III */
uint64_t mtrr_physbase[8]; /* 0x00000200 - 0x0000020f */
uint64_t mtrr_physmask[8]; /* 0x00000200 - 0x0000020f (ECX & 1) */
uint64_t mtrr_fix64k_8000; /* 0x00000250 */
@@ -278,7 +277,7 @@ typedef struct {
uint64_t pat; /* 0x00000277 */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also
on the VIA Cyrix III and Eden */
on the VIA Cyrix III */
uint64_t mtrr_deftype; /* 0x000002ff */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
@@ -699,6 +698,10 @@ typedef struct
extern uint32_t addr64, addr64_2;
extern uint32_t addr64a[8], addr64a_2[8];
extern int soft_reset_pci;
extern int reset_on_hlt, hlt_reset_pending;
extern cyrix_t cyrix;
extern void (*cpu_exec)(int cycs);

View File

@@ -1036,17 +1036,6 @@ const cpu_family_t cpu_families[] = {
{"733", CPU_CYRIX3S, fpus_internal, 733333333, 5.5, 2050, 0x663, 0x663, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 66, 66, 18, 18, 88},
{"", 0}
}
}, {
.package = CPU_PKG_EBGA368,
.manufacturer = "VIA",
.name = "Eden Model 7",
.internal_name = "c3_eden",
.cpus = (const CPU[]) {
{"66", CPU_EDEN, fpus_internal, 66666666, 1.0, 2050, 0x673, 0x673, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 6, 6, 3, 3, 8}, /* out of spec */
{"100", CPU_EDEN, fpus_internal, 100000000, 1.0, 2050, 0x673, 0x673, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 9, 9, 4, 4, 12}, /* out of spec */
{"400", CPU_EDEN, fpus_internal, 400000000, 6.0, 2050, 0x673, 0x673, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 36, 36, 17, 17, 48},
{"600", CPU_EDEN, fpus_internal, 600000000, 6.0, 2050, 0x673, 0x673, 0, CPU_SUPPORTS_DYNAREC | CPU_FIXED_MULTIPLIER, 54, 54, 18, 18, 72},
}
}, {
.package = 0,
}

View File

@@ -31,6 +31,7 @@
#include <86box/rom.h>
#include <86box/nmi.h>
#include <86box/pic.h>
#include <86box/pci.h>
#include <86box/ppi.h>
#include <86box/timer.h>
@@ -56,7 +57,7 @@ uint64_t xt_cpu_multi;
int nmi = 0, nmi_auto_clear = 0;
/* Was the CPU ever reset? */
int x86_was_reset = 0;
int x86_was_reset = 0, soft_reset_pci = 0;
/* Is the TRAP flag on? */
int trap = 0;
@@ -64,6 +65,9 @@ int trap = 0;
/* The current effective address's segment. */
uint32_t easeg;
/* This is for the OPTI 283 special reset handling mode. */
int reset_on_hlt, hlt_reset_pending;
#ifdef ENABLE_X86_LOG
void dumpregs(int);
@@ -216,15 +220,28 @@ makeznptable(void)
static void
reset_common(int hard)
{
/* Make sure to gracefully leave SMM. */
if (in_smm)
leave_smm();
#ifdef ENABLE_808X_LOG
if (hard)
x808x_log("x86 reset\n");
#endif
if (!hard && reset_on_hlt) {
hlt_reset_pending++;
pclog("hlt_reset_pending = %i\n", hlt_reset_pending);
if (hlt_reset_pending == 2)
hlt_reset_pending = 0;
else
return;
}
/* Make sure to gracefully leave SMM. */
if (in_smm)
leave_smm();
/* Needed for the ALi M1533. */
if (soft_reset_pci && !hard)
pci_reset();
use32 = 0;
cpu_cur_status = 0;
stack32 = 0;
@@ -290,6 +307,9 @@ reset_common(int hard)
shadowbios = shadowbios_write = 0;
alt_access = cpu_end_block_after_ins = 0;
if (hard)
reset_on_hlt = hlt_reset_pending = 0;
if (!is286)
reset_808x(hard);
}

View File

@@ -627,6 +627,9 @@ static int opHLT(uint32_t fetchdat)
CPU_BLOCK_END();
PREFETCH_RUN(100, 1, -1, 0,0,0,0, 0);
if (hlt_reset_pending)
softresetx86();
return 0;
}

View File

@@ -679,7 +679,8 @@ static int opFSCALE(uint32_t fetchdat)
FP_ENTER();
cpu_state.pc++;
temp64 = (int64_t)ST(1);
ST(0) = ST(0) * pow(2.0, (double)temp64);
if(ST(0) != 0.0)
ST(0) = ST(0) * pow(2.0, (double)temp64);
FP_TAG_VALID;
CLOCK_CYCLES((fpu_type >= FPU_487SX) ? (x87_timings.fscale) : (x87_timings.fscale * cpu_multi));
return 0;
@@ -787,6 +788,8 @@ static int opFLDCW_a32(uint32_t fetchdat)
static int FSTENV()
{
FP_ENTER();
cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | ((cpu_state.TOP & 7) << 11);
switch ((cr0 & 1) | (cpu_state.op32 & 0x100))
{
case 0x000: /*16-bit real mode*/

View File

@@ -776,7 +776,7 @@ lm78_init(const device_t *info)
/* National Semiconductor LM78 on ISA and SMBus. */
const device_t lm78_device = {
"National Semiconductor LM78 Hardware Monitor",
DEVICE_ISA | DEVICE_PCI,
DEVICE_ISA,
0x290 | LM78_I2C,
lm78_init, lm78_close, lm78_reset,
{ NULL }, NULL, NULL,
@@ -787,7 +787,7 @@ const device_t lm78_device = {
/* Winbond W83781D on ISA and SMBus. */
const device_t w83781d_device = {
"Winbond W83781D Hardware Monitor",
DEVICE_ISA | DEVICE_PCI,
DEVICE_ISA,
0x290 | LM78_I2C | LM78_W83781D,
lm78_init, lm78_close, lm78_reset,
{ NULL }, NULL, NULL,
@@ -799,7 +799,7 @@ const device_t w83781d_device = {
I2C-only W83781D clone with additional voltages, GPIOs and fan control. */
const device_t as99127f_device = {
"ASUS AS99127F Rev. 1 Hardware Monitor",
DEVICE_ISA | DEVICE_PCI,
DEVICE_ISA,
LM78_I2C | LM78_AS99127F_REV1,
lm78_init, lm78_close, lm78_reset,
{ NULL }, NULL, NULL,
@@ -810,7 +810,7 @@ const device_t as99127f_device = {
/* Rev. 2 is manufactured by Winbond and differs only in GPI registers. */
const device_t as99127f_rev2_device = {
"ASUS AS99127F Rev. 2 Hardware Monitor",
DEVICE_ISA | DEVICE_PCI,
DEVICE_ISA,
LM78_I2C | LM78_AS99127F_REV2,
lm78_init, lm78_close, lm78_reset,
{ NULL }, NULL, NULL,
@@ -821,7 +821,7 @@ const device_t as99127f_rev2_device = {
/* Winbond W83782D on ISA and SMBus. */
const device_t w83782d_device = {
"Winbond W83782D Hardware Monitor",
DEVICE_ISA | DEVICE_PCI,
DEVICE_ISA,
0x290 | LM78_I2C | LM78_W83782D,
lm78_init, lm78_close, lm78_reset,
{ NULL }, NULL, NULL,

View File

@@ -478,9 +478,7 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv)
isapnp_log("ISAPnP: Reset CSN\n");
card = dev->first_card;
while (card) {
card->csn = 0;
if (card->csn_changed)
card->csn_changed(card->csn, card->priv);
isapnp_set_csn(card, 0);
card = card->next;
}
}
@@ -506,9 +504,7 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv)
case 0x06: /* Card Select Number */
if (dev->isolated_card) {
isapnp_log("ISAPnP: Set CSN %02X\n", val);
dev->isolated_card->csn = val;
if (dev->isolated_card->csn_changed)
dev->isolated_card->csn_changed(dev->isolated_card->csn, dev->isolated_card->priv);
isapnp_set_csn(dev->isolated_card, val);
dev->isolated_card->state = PNP_STATE_CONFIG;
dev->isolated_card = NULL;
} else {
@@ -531,7 +527,7 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv)
}
if (!ld)
fatal("ISAPnP: CSN %02X has no device %02X\n", card->csn, val);
isapnp_log("ISAPnP: CSN %02X has no device %02X\n", card->csn, val);
break;
@@ -685,8 +681,6 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
memset(card, 0, sizeof(isapnp_card_t));
card->enable = 1;
card->rom = rom;
card->rom_size = rom_size;
card->priv = priv;
card->config_changed = config_changed;
card->csn_changed = csn_changed;
@@ -702,6 +696,20 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
prev_card->next = card;
}
if (rom && rom_size)
isapnp_update_card_rom(card, rom, rom_size);
return card;
}
void
isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size)
{
isapnp_card_t *card = (isapnp_card_t *) priv;
card->rom = rom;
card->rom_size = rom_size;
/* Parse resources in ROM to allocate logical devices,
and determine the state of read-only register bits. */
#ifdef ENABLE_ISAPNP_LOG
@@ -709,11 +717,17 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
isapnp_log("ISAPnP: Parsing ROM resources for card %c%c%c%02X%02X (serial %08X)\n", '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[2], card->rom[3], (card->rom[7] << 24) | (card->rom[6] << 16) | (card->rom[5] << 8) | card->rom[4]);
#endif
uint16_t i = 9, j;
uint8_t ldn = 0, res, in_df = 0;
uint8_t existing = 0, ldn = 0, res, in_df = 0;
uint8_t irq = 0, io = 0, mem_range = 0, mem_range_32 = 0, irq_df = 0, io_df = 0, mem_range_df = 0, mem_range_32_df = 0;
uint32_t len;
isapnp_device_t *ld = NULL, *prev_ld = NULL;
/* Check if this is an existing card which already has logical devices.
Any new logical devices will be added to the list after existing ones.
Removed LDs are not flushed as we may end up with an invalid ROM. */
existing = !!card->first_ld;
/* Iterate through ROM resources. */
while (i < card->rom_size) {
if (card->rom[i] & 0x80) { /* large resource */
res = card->rom[i] & 0x7f;
@@ -723,15 +737,29 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
case 0x01: /* memory range */
case 0x05: /* 32-bit memory range */
if (res == 0x01) {
if (mem_range > 3)
fatal("ISAPnP: Memory descriptor overflow (%d)\n", mem_range);
if (!ld) {
isapnp_log("ISAPnP: >>%s Memory descriptor with no logical device\n", in_df ? ">" : "");
break;
}
if (mem_range > 3) {
isapnp_log("ISAPnP: >>%s Memory descriptor overflow (%d)\n", in_df ? ">" : "", mem_range++);
break;
}
isapnp_log("ISAPnP: >>%s Memory range %d uses upper limit = ", in_df ? ">" : "", mem_range);
res = 1 << mem_range;
mem_range++;
} else {
if (mem_range_32 > 3)
fatal("ISAPnP: 32-bit memory descriptor overflow (%d)\n", mem_range_32);
if (!ld) {
isapnp_log("ISAPnP: >>%s 32-bit memory descriptor with no logical device\n", in_df ? ">" : "");
break;
}
if (mem_range_32 > 3) {
isapnp_log("ISAPnP: >>%s 32-bit memory descriptor overflow (%d)\n", in_df ? ">" : "", mem_range_32++);
break;
}
isapnp_log("ISAPnP: >>%s 32-bit memory range %d uses upper limit = ", in_df ? ">" : "", mem_range_32);
res = 1 << (4 + mem_range_32);
@@ -775,22 +803,39 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
#endif
/* We're done with the previous logical device. */
if (ld) {
prev_ld = ld;
if (ld && !existing)
isapnp_reset_ld_regs(ld);
/* Look for an existing logical device with this number,
and create one if none exist. */
if (existing) {
ld = card->first_ld;
while (ld && (ld->number != ldn))
ld = ld->next;
}
if (ld && (ld->number == ldn)) {
/* Reset some logical device state. */
ld->mem_upperlimit = ld->io_16bit = ld->irq_types = 0;
memset(ld->io_len, 0, sizeof(ld->io_len));
} else {
/* Create logical device. */
ld = (isapnp_device_t *) malloc(sizeof(isapnp_device_t));
memset(ld, 0, sizeof(isapnp_device_t));
/* Add to end of list. */
prev_ld = card->first_ld;
if (prev_ld) {
while (prev_ld->next)
prev_ld = prev_ld->next;
prev_ld->next = ld;
} else {
card->first_ld = ld;
}
}
/* Create logical device. */
ld = (isapnp_device_t *) malloc(sizeof(isapnp_device_t));
memset(ld, 0, sizeof(isapnp_device_t));
/* Set and increment logical device number. */
ld->number = ldn++;
if (prev_ld)
prev_ld->next = ld;
else
card->first_ld = ld;
/* Start the position counts over. */
irq = io = mem_range = mem_range_32 = irq_df = io_df = mem_range_df = mem_range_32_df = 0;
@@ -798,14 +843,26 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
#ifdef ENABLE_ISAPNP_LOG
case 0x03: /* compatible device ID */
if (!ld) {
isapnp_log("ISAPnP: >> Compatible device ID with no logical device\n");
break;
}
vendor = (card->rom[i + 1] << 8) | card->rom[i + 2];
isapnp_log("ISAPnP: >> Compatible device ID: %c%c%c%02X%02X\n", '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[i + 3], card->rom[i + 4]);
break;
#endif
case 0x04: /* IRQ */
if (irq > 1)
fatal("ISAPnP: IRQ descriptor overflow (%d)\n", irq);
if (!ld) {
isapnp_log("ISAPnP: >>%s IRQ descriptor with no logical device\n", in_df ? ">" : "");
break;
}
if (irq > 1) {
isapnp_log("ISAPnP: >>%s IRQ descriptor overflow (%d)\n", in_df ? ">" : "", irq++);
break;
}
if (len == 2) /* default */
res = 0x01; /* high true edge sensitive */
@@ -822,6 +879,11 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
break;
case 0x06: /* start dependent function */
if (!ld) {
isapnp_log("ISAPnP: >> Start dependent function with no logical device\n");
break;
}
isapnp_log("ISAPnP: >> Start dependent function: %s\n", (((len == 0) || (card->rom[i + 1] == 1)) ? "acceptable" : ((card->rom[i + 1] == 0) ? "good" : ((card->rom[i + 1] == 2) ? "sub-optimal" : "unknown priority"))));
if (in_df) {
@@ -848,8 +910,15 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
break;
case 0x08: /* I/O port */
if (io > 7)
fatal("ISAPnP: I/O descriptor overflow (%d)\n", io);
if (!ld) {
isapnp_log("ISAPnP: >>%s I/O descriptor with no logical device\n", in_df ? ">" : "");
break;
}
if (io > 7) {
isapnp_log("ISAPnP: >>%s I/O descriptor overflow (%d)\n", in_df ? ">" : "", io++);
break;
}
isapnp_log("ISAPnP: >>%s I/O range %d %d-bit decode, %d ports\n", in_df ? ">" : "", io, (card->rom[i + 1] & 0x01) ? 16 : 10, card->rom[i + 7]);
@@ -873,6 +942,9 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
card->rom[i + 1] = -res;
isapnp_log("ISAPnP: End card resources (checksum %02X)\n", card->rom[i + 1]);
/* Stop parsing here. */
card->rom_size = i + 2;
break;
#ifdef ENABLE_ISAPNP_LOG
@@ -888,10 +960,8 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
}
/* We're done with the last logical device. */
if (ld)
if (ld && !existing)
isapnp_reset_ld_regs(ld);
return card;
}
@@ -904,13 +974,14 @@ isapnp_enable_card(void *priv, uint8_t enable)
/* Look for a matching card. */
isapnp_card_t *card = dev->first_card;
uint8_t will_enable;
while (card) {
if (card == priv) {
/* Enable or disable the card. */
card->enable = !!enable;
/* enable=2 is a cheat code to jump straight into CONFIG state. */
card->state = (enable == 2) ? PNP_STATE_CONFIG : PNP_STATE_WAIT_FOR_KEY;
will_enable = (enable >= ISAPNP_CARD_ENABLE);
if (will_enable ^ card->enable)
card->state = (enable == ISAPNP_CARD_FORCE_CONFIG) ? PNP_STATE_CONFIG : PNP_STATE_WAIT_FOR_KEY;
card->enable = will_enable;
/* Invalidate other references if we're disabling this card. */
if (!card->enable) {

View File

@@ -168,8 +168,8 @@ static uint8_t ide_qua_pnp_rom[] = {
0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01, /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */
0x30, /* start dependent functions, acceptable */
0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */
0x47, 0x01, 0x68, 0x01, 0x68, 0x01, 0x01, 0x08, /* I/O 0x168, decodes 16-bit, 1-byte alignment, 8 addresses */
0x47, 0x01, 0x6e, 0x03, 0x6e, 0x03, 0x01, 0x01, /* I/O 0x36E, decodes 16-bit, 1-byte alignment, 1 address */
0x47, 0x01, 0xe8, 0x01, 0xe8, 0x01, 0x01, 0x08, /* I/O 0x1E8, decodes 16-bit, 1-byte alignment, 8 addresses */
0x47, 0x01, 0xee, 0x03, 0xee, 0x03, 0x01, 0x01, /* I/O 0x3EE, decodes 16-bit, 1-byte alignment, 1 address */
0x30, /* start dependent functions, acceptable */
0x22, 0xb8, 0x1e, /* IRQ 3/4/5/7/9/10/11/12 */
0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */

View File

@@ -1,10 +1,10 @@
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the VARCem Project.
* This file is part of the 86Box distribution.
*
* Implementation of a generic Game Port.
*
@@ -12,27 +12,11 @@
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
* RichardG, <richardg867@gmail.com>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
* Copyright 2021 RichardG.
*/
#include <stdio.h>
#include <stdint.h>
@@ -45,6 +29,7 @@
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/isapnp.h>
#include <86box/gameport.h>
#include <86box/joystick_ch_flightstick_pro.h>
#include <86box/joystick_standard.h>
@@ -55,21 +40,26 @@
typedef struct {
pc_timer_t timer;
int axis_nr;
struct _gameport_ *gameport;
struct _joystick_instance_ *joystick;
} g_axis_t;
typedef struct _gameport_ {
uint8_t state;
uint16_t addr;
g_axis_t axis[4];
const joystick_if_t *joystick;
void *joystick_dat;
uint8_t len;
struct _joystick_instance_ *joystick;
struct _gameport_ *next;
} gameport_t;
typedef struct _joystick_instance_ {
uint8_t state;
g_axis_t axis[4];
int joystick_type = 0;
const joystick_if_t *intf;
void *dat;
} joystick_instance_t;
int joystick_type = 1;
static const joystick_if_t joystick_none = {
@@ -101,22 +91,54 @@ static const struct {
{ "thrustmaster_fcs", &joystick_tm_fcs },
{ "", NULL }
};
static gameport_t *gameport_global = NULL;
static joystick_instance_t *joystick_instance = NULL;
static uint8_t gameport_pnp_rom[] = {
0x09, 0xf8, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, /* BOX0002, dummy checksum (filled in by isapnp_add_card) */
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
0x82, 0x09, 0x00, 'G', 'a', 'm', 'e', ' ', 'P', 'o', 'r', 't', /* ANSI identifier */
0x15, 0x09, 0xf8, 0x00, 0x02, 0x01, /* logical device BOX0002, can participate in boot */
0x1c, 0x41, 0xd0, 0xb0, 0x2f, /* compatible device PNPB02F */
0x31, 0x00, /* start dependent functions, preferred */
0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x08, 0x08, /* I/O 0x200, decodes 16-bit, 8-byte alignment, 8 addresses */
0x30, /* start dependent functions, acceptable */
0x47, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x08, /* I/O 0x208, decodes 16-bit, 8-byte alignment, 8 addresses */
0x31, 0x02, /* start dependent functions, sub-optimal */
0x47, 0x01, 0x00, 0x01, 0xf8, 0xff, 0x08, 0x08, /* I/O 0x100-0xFFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
0x38, /* end dependent functions */
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
};
static const isapnp_device_config_t gameport_pnp_defaults[] = {
{
.activate = 1,
.io = { { .base = 0x200 }, }
}
};
const device_t *standalone_gameport_type;
int gameport_instance_id = 0;
/* Linked list of active game ports. Only the top port responds to reads
or writes, and ports at the standard 200h location are prioritized. */
static gameport_t *active_gameports = NULL;
char *
joystick_get_name(int js)
{
if (! joysticks[js].joystick)
return(NULL);
return((char *)joysticks[js].joystick->name);
if (!joysticks[js].joystick)
return NULL;
return (char *) joysticks[js].joystick->name;
}
char *
joystick_get_internal_name(int js)
{
return((char *) joysticks[js].internal_name);
return (char *) joysticks[js].internal_name;
}
@@ -125,8 +147,7 @@ joystick_get_from_internal_name(char *s)
{
int c = 0;
while (strlen((char *) joysticks[c].internal_name))
{
while (strlen((char *) joysticks[c].internal_name)) {
if (!strcmp((char *) joysticks[c].internal_name, s))
return c;
c++;
@@ -139,62 +160,63 @@ joystick_get_from_internal_name(char *s)
int
joystick_get_max_joysticks(int js)
{
return(joysticks[js].joystick->max_joysticks);
return joysticks[js].joystick->max_joysticks;
}
int
joystick_get_axis_count(int js)
{
return(joysticks[js].joystick->axis_count);
return joysticks[js].joystick->axis_count;
}
int
joystick_get_button_count(int js)
{
return(joysticks[js].joystick->button_count);
return joysticks[js].joystick->button_count;
}
int
joystick_get_pov_count(int js)
{
return(joysticks[js].joystick->pov_count);
return joysticks[js].joystick->pov_count;
}
char *
joystick_get_axis_name(int js, int id)
{
return((char *)joysticks[js].joystick->axis_names[id]);
return (char *) joysticks[js].joystick->axis_names[id];
}
char *
joystick_get_button_name(int js, int id)
{
return((char *)joysticks[js].joystick->button_names[id]);
return (char *) joysticks[js].joystick->button_names[id];
}
char *
joystick_get_pov_name(int js, int id)
{
return (char *)joysticks[js].joystick->pov_names[id];
return (char *) joysticks[js].joystick->pov_names[id];
}
static void
gameport_time(gameport_t *gameport, int nr, int axis)
gameport_time(joystick_instance_t *joystick, int nr, int axis)
{
if (axis == AXIS_NOT_PRESENT)
timer_disable(&gameport->axis[nr].timer);
timer_disable(&joystick->axis[nr].timer);
else {
/* Convert axis value to 555 timing. */
axis += 32768;
axis = (axis * 100) / 65; /*Axis now in ohms*/
axis = (axis * 100) / 65; /* axis now in ohms */
axis = (axis * 11) / 1000;
timer_set_delay_u64(&gameport->axis[nr].timer, TIMER_USEC * (axis + 24)); /*max = 11.115 ms*/
timer_set_delay_u64(&joystick->axis[nr].timer, TIMER_USEC * (axis + 24)); /* max = 11.115 ms */
}
}
@@ -202,16 +224,23 @@ gameport_time(gameport_t *gameport, int nr, int axis)
static void
gameport_write(uint16_t addr, uint8_t val, void *priv)
{
gameport_t *p = (gameport_t *)priv;
gameport_t *dev = (gameport_t *) priv;
joystick_instance_t *joystick = dev->joystick;
p->state |= 0x0f;
/* Respond only if a joystick is present and this port is at the top of the active ports list. */
if (!joystick || (active_gameports != dev))
return;
gameport_time(p, 0, p->joystick->read_axis(p->joystick_dat, 0));
gameport_time(p, 1, p->joystick->read_axis(p->joystick_dat, 1));
gameport_time(p, 2, p->joystick->read_axis(p->joystick_dat, 2));
gameport_time(p, 3, p->joystick->read_axis(p->joystick_dat, 3));
p->joystick->write(p->joystick_dat);
/* Read all axes. */
joystick->state |= 0x0f;
gameport_time(joystick, 0, joystick->intf->read_axis(joystick->dat, 0));
gameport_time(joystick, 1, joystick->intf->read_axis(joystick->dat, 1));
gameport_time(joystick, 2, joystick->intf->read_axis(joystick->dat, 2));
gameport_time(joystick, 3, joystick->intf->read_axis(joystick->dat, 3));
/* Notify the interface. */
joystick->intf->write(joystick->dat);
cycles -= ISA_CYCLES(8);
}
@@ -220,120 +249,195 @@ gameport_write(uint16_t addr, uint8_t val, void *priv)
static uint8_t
gameport_read(uint16_t addr, void *priv)
{
gameport_t *p = (gameport_t *)priv;
uint8_t ret;
gameport_t *dev = (gameport_t *) priv;
joystick_instance_t *joystick = dev->joystick;
ret = p->state | p->joystick->read(p->joystick_dat);
/* Respond only if a joystick is present and this port is at the top of the active ports list. */
if (!joystick || (active_gameports != dev))
return 0xff;
/* Merge axis state with button state. */
uint8_t ret = joystick->state | joystick->intf->read(joystick->dat);
cycles -= ISA_CYCLES(8);
return(ret);
return ret;
}
static void
timer_over(void *priv)
{
g_axis_t *axis = (g_axis_t *)priv;
gameport_t *p = axis->gameport;
g_axis_t *axis = (g_axis_t *) priv;
p->state &= ~(1 << axis->axis_nr);
axis->joystick->state &= ~(1 << axis->axis_nr);
if (axis == &p->axis[0])
p->joystick->a0_over(p->joystick_dat);
/* Notify the joystick when the first axis' period is finished. */
if (axis == &axis->joystick->axis[0])
axis->joystick->intf->a0_over(axis->joystick->dat);
}
void
gameport_update_joystick_type(void)
{
gameport_t *p = gameport_global;
/* Add a standalone game port if a joystick is enabled but no other game ports exist. */
if (standalone_gameport_type)
gameport_add(standalone_gameport_type);
if (p != NULL) {
p->joystick->close(p->joystick_dat);
p->joystick = joysticks[joystick_type].joystick;
p->joystick_dat = p->joystick->init();
/* Reset the joystick interface. */
if (joystick_instance) {
joystick_instance->intf->close(joystick_instance->dat);
joystick_instance->intf = joysticks[joystick_type].joystick;
joystick_instance->dat = joystick_instance->intf->init();
}
}
void
gameport_remap(uint16_t address)
gameport_remap(void *priv, uint16_t address)
{
gameport_t *p = gameport_global;
if (!p)
gameport_t *dev = (gameport_t *) priv, *other_dev;
if (dev->addr) {
/* Remove this port from the active ports list. */
if (active_gameports == dev) {
active_gameports = dev->next;
dev->next = NULL;
} else {
other_dev = active_gameports;
while (other_dev) {
if (other_dev->next == dev) {
other_dev->next = dev->next;
dev->next = NULL;
break;
}
other_dev = other_dev->next;
}
}
io_removehandler(dev->addr, dev->len,
gameport_read, NULL, NULL, gameport_write, NULL, NULL, dev);
}
dev->addr = address;
if (dev->addr) {
/* Add this port to the active ports list. */
if ((dev->addr & 0xfff8) == 0x200) {
/* Port within 200-207h: add to top. */
dev->next = active_gameports;
active_gameports = dev;
} else {
/* Port at other addresses: add to bottom. */
other_dev = active_gameports;
while (other_dev && other_dev->next)
other_dev = other_dev->next;
if (other_dev)
other_dev->next = dev;
}
io_sethandler(dev->addr, dev->len,
gameport_read, NULL, NULL, gameport_write, NULL, NULL, dev);
}
}
static void
gameport_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
{
if (ld > 0)
return;
if (p->addr)
io_removehandler(p->addr, (p->addr & 1) ? 1 : 8,
gameport_read, NULL, NULL, gameport_write, NULL, NULL, p);
gameport_t *dev = (gameport_t *) priv;
p->addr = address;
/* Remap the game port to the specified address, or disable it. */
gameport_remap(dev, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0);
}
if (p->addr)
io_sethandler(p->addr, (p->addr & 1) ? 1 : 8,
gameport_read, NULL, NULL, gameport_write, NULL, NULL, p);
void *
gameport_add(const device_t *gameport_type)
{
/* Prevent a standalone game port from being added later on, unless this
is an unused Super I/O game port (no MACHINE_GAMEPORT machine flag). */
if (!(gameport_type->local & 0x1000000) || (machines[machine].flags & MACHINE_GAMEPORT))
standalone_gameport_type = NULL;
/* Add game port device. */
return device_add_inst(gameport_type, gameport_instance_id++);
}
static void *
gameport_init(const device_t *info)
{
gameport_t *p = NULL;
gameport_t *dev = NULL;
if (!joystick_type) {
gameport_global = p = NULL;
return(p);
dev = malloc(sizeof(gameport_t));
memset(dev, 0x00, sizeof(gameport_t));
/* Allocate global instance. */
if (!joystick_instance && joystick_type) {
joystick_instance = malloc(sizeof(joystick_instance_t));
memset(joystick_instance, 0x00, sizeof(joystick_instance_t));
joystick_instance->axis[0].joystick = joystick_instance;
joystick_instance->axis[1].joystick = joystick_instance;
joystick_instance->axis[2].joystick = joystick_instance;
joystick_instance->axis[3].joystick = joystick_instance;
joystick_instance->axis[0].axis_nr = 0;
joystick_instance->axis[1].axis_nr = 1;
joystick_instance->axis[2].axis_nr = 2;
joystick_instance->axis[3].axis_nr = 3;
timer_add(&joystick_instance->axis[0].timer, timer_over, &joystick_instance->axis[0], 0);
timer_add(&joystick_instance->axis[1].timer, timer_over, &joystick_instance->axis[1], 0);
timer_add(&joystick_instance->axis[2].timer, timer_over, &joystick_instance->axis[2], 0);
timer_add(&joystick_instance->axis[3].timer, timer_over, &joystick_instance->axis[3], 0);
joystick_instance->intf = joysticks[joystick_type].joystick;
joystick_instance->dat = joystick_instance->intf->init();
}
p = malloc(sizeof(gameport_t));
dev->joystick = joystick_instance;
memset(p, 0x00, sizeof(gameport_t));
/* Map game port to the default address. Not applicable on PnP-only ports. */
dev->len = (info->local >> 16) & 0xff;
gameport_remap(dev, info->local & 0xffff);
p->axis[0].gameport = p;
p->axis[1].gameport = p;
p->axis[2].gameport = p;
p->axis[3].gameport = p;
/* Register ISAPnP if this is a standard game port card. */
if (info->local == 0x200)
isapnp_set_device_defaults(isapnp_add_card(gameport_pnp_rom, sizeof(gameport_pnp_rom), gameport_pnp_config_changed, NULL, NULL, NULL, dev), 0, gameport_pnp_defaults);
p->axis[0].axis_nr = 0;
p->axis[1].axis_nr = 1;
p->axis[2].axis_nr = 2;
p->axis[3].axis_nr = 3;
timer_add(&p->axis[0].timer, timer_over, &p->axis[0], 0);
timer_add(&p->axis[1].timer, timer_over, &p->axis[1], 0);
timer_add(&p->axis[2].timer, timer_over, &p->axis[2], 0);
timer_add(&p->axis[3].timer, timer_over, &p->axis[3], 0);
p->joystick = joysticks[joystick_type].joystick;
p->joystick_dat = p->joystick->init();
gameport_global = p;
gameport_remap(info->local);
return(p);
return dev;
}
static void
gameport_close(void *priv)
{
gameport_t *p = (gameport_t *)priv;
gameport_t *dev = (gameport_t *) priv;
if (p == NULL) return;
/* If this port was active, remove it from the active ports list. */
gameport_remap(dev, 0);
p->joystick->close(p->joystick_dat);
/* Free the global instance here, if it wasn't already freed. */
if (joystick_instance) {
joystick_instance->intf->close(joystick_instance->dat);
gameport_global = NULL;
free(joystick_instance);
joystick_instance = NULL;
}
free(p);
free(dev);
}
const device_t gameport_device = {
"Game port",
0, 0x200,
0, 0x080200,
gameport_init,
gameport_close,
NULL, { NULL }, NULL,
@@ -342,7 +446,34 @@ const device_t gameport_device = {
const device_t gameport_201_device = {
"Game port (port 201h only)",
0, 0x201,
0, 0x010201,
gameport_init,
gameport_close,
NULL, { NULL }, NULL,
NULL
};
const device_t gameport_pnp_device = {
"Game port (Plug and Play only)",
0, 0x080000,
gameport_init,
gameport_close,
NULL, { NULL }, NULL,
NULL
};
const device_t gameport_pnp_6io_device = {
"Game port (Plug and Play only, 6 I/O ports)",
0, 0x060000,
gameport_init,
gameport_close,
NULL, { NULL }, NULL,
NULL
};
const device_t gameport_sio_device = {
"Game port (Super I/O)",
0, 0x1080000,
gameport_init,
gameport_close,
NULL, { NULL }, NULL,

View File

@@ -152,6 +152,7 @@ extern int config_changed; /* config has changed */
/* Function prototypes. */
#ifdef HAVE_STDARG_H
extern void pclog_ex(const char *fmt, va_list);
extern void fatal_ex(const char *fmt, va_list);
#endif
extern void pclog_toggle_suppr(void);
extern void pclog(const char *fmt, ...);

View File

@@ -1,40 +1,22 @@
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the VARCem Project.
* This file is part of the 86Box distribution.
*
* Definitions for the generic game port handlers.
*
* NOTE: This module needs a good cleanup someday.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
* RichardG, <richardg867@gmail.com>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2017 Sarah Walker.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
* Copyright 2008-2018 Sarah Walker.
* Copyright 2021 RichardG.
*/
#ifndef EMU_GAMEPORT_H
# define EMU_GAMEPORT_H
@@ -125,8 +107,13 @@ extern "C" {
#ifdef EMU_DEVICE_H
extern const device_t gameport_device;
extern const device_t gameport_201_device;
#endif
extern const device_t gameport_pnp_device;
extern const device_t gameport_pnp_6io_device;
extern const device_t gameport_sio_device;
extern const device_t *standalone_gameport_type;
#endif
extern int gameport_instance_id;
extern plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS];
extern joystick_t joystick_state[MAX_JOYSTICKS];
extern int joysticks_present;
@@ -150,7 +137,8 @@ extern char *joystick_get_button_name(int js, int id);
extern char *joystick_get_pov_name(int js, int id);
extern void gameport_update_joystick_type(void);
extern void gameport_remap(uint16_t address);
extern void gameport_remap(void *priv, uint16_t address);
extern void *gameport_add(const device_t *gameport_type);
#ifdef __cplusplus
}

View File

@@ -23,6 +23,33 @@
extern void io_init(void);
extern void io_sethandler_common(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv, int step);
extern void io_removehandler_common(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv, int step);
extern void io_handler_common(int set, uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv, int step);
extern void io_sethandler(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
@@ -50,7 +77,6 @@ extern void io_handler(int set, uint16_t base, int size,
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv);
#ifdef PC98
extern void io_sethandler_interleaved(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
@@ -68,7 +94,15 @@ extern void io_removehandler_interleaved(uint16_t base, int size,
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv);
#endif
extern void io_handler_interleaved(int set, uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv);
extern uint8_t inb(uint16_t port);
extern void outb(uint16_t port, uint8_t val);

View File

@@ -25,6 +25,13 @@
#define ISAPNP_DMA_DISABLED 4
enum {
ISAPNP_CARD_DISABLE = 0,
ISAPNP_CARD_ENABLE = 1,
ISAPNP_CARD_FORCE_CONFIG /* cheat code for UMC UM8669F */
};
typedef struct {
uint8_t activate;
struct {
@@ -51,6 +58,7 @@ void *isapnp_add_card(uint8_t *rom, uint16_t rom_size,
uint8_t (*read_vendor_reg)(uint8_t ld, uint8_t reg, void *priv),
void (*write_vendor_reg)(uint8_t ld, uint8_t reg, uint8_t val, void *priv),
void *priv);
void isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size);
void isapnp_enable_card(void *priv, uint8_t enable);
void isapnp_set_csn(void *priv, uint8_t csn);
void isapnp_set_device_defaults(void *priv, uint8_t ldn, const isapnp_device_config_t *config);

46
src/include/86box/log.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Main include file for the application.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2021 Miran Grca.
* Copyright 2021 Fred N. van Kempen.
*/
#ifndef EMU_LOG_H
# define EMU_LOG_H
#ifndef RELEASE_BUILD
#ifdef __cplusplus
extern "C" {
#endif
/* Function prototypes. */
extern void log_set_suppr_seen(void *priv, int suppr_seen);
extern void log_set_dev_name(void *priv, char *dev_name);
#ifdef HAVE_STDARG_H
extern void log_out(void *priv, const char *fmt, va_list);
extern void log_fatal(void *priv, const char *fmt, ...);
#endif
extern void * log_open(char *dev_name);
extern void log_close(void *priv);
#ifdef __cplusplus
}
#endif
#else
#define log_fatal(priv, fmt, ...) fatal(fmt, ...)
#endif /*RELEASE_BUILD*/
#endif /*EMU_LOG_H*/

View File

@@ -61,6 +61,7 @@
#define MACHINE_SOUND 0x00008000 /* sys has int sound */
#define MACHINE_FDC 0x00010000 /* sys has int FDC */
#define MACHINE_NIC 0x00020000 /* sys has int NIC */
#define MACHINE_GAMEPORT 0x00040000 /* sys has int game port */
/* Combined flags. */
#define MACHINE_VIDEO_FIXED 0x00003000 /* sys has fixed int video */
/* Feature flags for internal storage controllers. */
@@ -110,7 +111,6 @@ enum {
MACHINE_TYPE_SLOT1_2,
MACHINE_TYPE_SLOT2,
MACHINE_TYPE_SOCKET370,
MACHINE_TYPE_EBGA368,
MACHINE_TYPE_MISC,
MACHINE_TYPE_MAX
};
@@ -564,9 +564,6 @@ extern int machine_at_603tcf_init(const machine_t *);
extern int machine_at_trinity371_init(const machine_t *);
extern int machine_at_p6bap_init(const machine_t *);
/* m_at_ebga368.c */
extern int machine_at_arb9673_init(const machine_t *);
/* m_at_misc.c */
extern int machine_at_vpc2007_init(const machine_t *);

View File

@@ -81,7 +81,6 @@ typedef struct _nvr_ {
void (*ven_save)(void);
uint8_t regs[NVR_MAXSIZE]; /* these are the registers */
uint8_t apc_regs[4]; /* AND THIS! IS THE APC MADAFAKA :b */
} nvr_t;

View File

@@ -44,6 +44,7 @@
#define PCI_MIRQ0 0
#define PCI_MIRQ1 1
#define PCI_MIRQ2 2
#define PCI_MIRQ3 3
#define PCI_IRQ_DISABLED -1

View File

@@ -67,6 +67,7 @@ extern const device_t um8669f_device;
extern const device_t via_vt82c686_sio_device;
extern const device_t w83787f_device;
extern const device_t w83787f_ide_device;
extern const device_t w83787f_ide_en_device;
extern const device_t w83787f_ide_sec_device;
extern const device_t w83877f_device;
extern const device_t w83877f_president_device;

View File

@@ -1,44 +1,63 @@
#define AD1848_TYPE_DEFAULT 0
#define AD1848_TYPE_CS4248 1
#define AD1848_TYPE_CS4231 2
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Definitions for AD1848 / CS4248 / CS4231 (Windows Sound System) codec emulation.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* TheCollector1995, <mariogplayer@gmail.com>
* RichardG, <richardg867@gmail.com>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2018-2020 TheCollector1995.
* Copyright 2021 RichardG.
*/
typedef struct ad1848_t
{
int index;
uint8_t regs[32]; /* 16 original + 16 CS4231A extensions */
uint8_t status;
int trd;
int mce;
int count;
int16_t out_l, out_r;
enum {
AD1848_TYPE_DEFAULT = 0,
AD1848_TYPE_CS4248,
AD1848_TYPE_CS4231,
AD1848_TYPE_CS4236
};
double cd_vol_l, cd_vol_r;
int enable;
typedef struct {
uint8_t type, index, xindex, regs[32], xregs[32], status; /* 16 original registers + 16 CS4231A extensions + 32 CS4236 extensions */
int irq, dma;
int freq;
pc_timer_t timer_count;
uint64_t timer_latch;
int count;
uint8_t trd, mce, wten: 1;
int16_t out_l, out_r;
double cd_vol_l, cd_vol_r;
int fm_vol_l, fm_vol_r;
uint8_t fmt_mask, wave_vol_mask;
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
int type;
uint8_t enable: 1, irq: 4, dma: 3;
int freq;
pc_timer_t timer_count;
uint64_t timer_latch;
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
} ad1848_t;
void ad1848_setirq(ad1848_t *ad1848, int irq);
void ad1848_setdma(ad1848_t *ad1848, int dma);
uint8_t ad1848_read(uint16_t addr, void *p);
void ad1848_write(uint16_t addr, uint8_t val, void *p);
extern void ad1848_setirq(ad1848_t *ad1848, int irq);
extern void ad1848_setdma(ad1848_t *ad1848, int dma);
extern void ad1848_updatevolmask(ad1848_t *ad1848);
void ad1848_update(ad1848_t *ad1848);
void ad1848_speed_changed(ad1848_t *ad1848);
extern uint8_t ad1848_read(uint16_t addr, void *priv);
extern void ad1848_write(uint16_t addr, uint8_t val, void *priv);
void ad1848_init(ad1848_t *ad1848, int type);
extern void ad1848_update(ad1848_t *ad1848);
extern void ad1848_speed_changed(ad1848_t *ad1848);
extern void ad1848_filter_cd_audio(int channel, double *buffer, void *priv);
extern void ad1848_init(ad1848_t *ad1848, uint8_t type);

View File

@@ -122,6 +122,7 @@ typedef struct sb_t
};
mpu_t *mpu;
emu8k_t emu8k;
void *gameport;
int pos;

View File

@@ -99,7 +99,7 @@ extern const device_t gus_device;
extern const device_t pas16_device;
#endif
/* PSSJ - What is this device? */
/* Tandy PSSJ */
extern const device_t pssj_device;
/* Creative Labs Sound Blaster */
@@ -110,6 +110,7 @@ extern const device_t sb_2_device;
extern const device_t sb_pro_v1_device;
extern const device_t sb_pro_v2_device;
extern const device_t sb_pro_mcv_device;
extern const device_t sb_pro_cs423x_device;
extern const device_t sb_16_device;
extern const device_t sb_16_pnp_device;
extern const device_t sb_32_pnp_device;
@@ -122,6 +123,11 @@ extern const device_t ssi2001_device;
/* Windows Sound System */
extern const device_t wss_device;
extern const device_t ncr_business_audio_device;
/* Crystal CS423x */
extern const device_t cs4236b_device;
extern const device_t cs4237b_device;
extern const device_t cs4238b_device;
#endif
#endif /*EMU_SOUND_H*/

View File

@@ -23,6 +23,7 @@
#define FLAG_EXT_WRITE 4
#define FLAG_LATCH8 8
#define FLAG_NOSKEW 16
#define FLAG_ADDR_BY16 32
typedef struct {
@@ -153,6 +154,9 @@ typedef struct svga_t
/*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/
int force_dword_mode;
/*Force CRTC to legacy mode. Required for Voodoo Banshee/3 until there's a proper fix*/
int force_legacy_mode;
int remap_required;
uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr);

View File

@@ -101,7 +101,7 @@ void svga_recalc_remap_func(svga_t *svga)
{
int func_nr;
if (svga->fb_only)
if (svga->fb_only || svga->force_legacy_mode)
func_nr = 0;
else {
if (svga->force_dword_mode)

172
src/io.c
View File

@@ -104,19 +104,19 @@ io_init(void)
void
io_sethandler(uint16_t base, int size,
io_sethandler_common(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
void *priv, int step)
{
int c;
io_t *p, *q = NULL;
for (c = 0; c < size; c++) {
for (c = 0; c < size; c += step) {
p = io_last[base + c];
q = (io_t *) malloc(sizeof(io_t));
memset(q, 0, sizeof(io_t));
@@ -145,19 +145,19 @@ io_sethandler(uint16_t base, int size,
void
io_removehandler(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
io_removehandler_common(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv, int step)
{
int c;
io_t *p, *q;
for (c = 0; c < size; c++) {
for (c = 0; c < size; c += step) {
p = io[base + c];
if (!p)
continue;
@@ -185,6 +185,51 @@ io_removehandler(uint16_t base, int size,
}
void
io_handler_common(int set, uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv, int step)
{
if (set)
io_sethandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, step);
else
io_removehandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, step);
}
void
io_sethandler(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
{
io_sethandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, 1);
}
void
io_removehandler(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
{
io_removehandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, 1);
}
void
io_handler(int set, uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
@@ -195,89 +240,50 @@ io_handler(int set, uint16_t base, int size,
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
{
if (set)
io_sethandler(base, size, inb, inw, inl, outb, outw, outl, priv);
else
io_removehandler(base, size, inb, inw, inl, outb, outw, outl, priv);
io_handler_common(set, base, size, inb, inw, inl, outb, outw, outl, priv, 1);
}
#ifdef PC98
void
io_sethandler_interleaved(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
io_sethandler_interleaved(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
{
int c;
io_t *p, *q;
size <<= 2;
for (c=0; c<size; c+=2) {
p = last_handler(base + c);
q = (io_t *) malloc(sizeof(io_t));
memset(q, 0, sizeof(io_t));
if (p) {
p->next = q;
q->prev = p;
} else {
io[base + c] = q;
q->prev = NULL;
}
q->inb = inb;
q->inw = inw;
q->inl = inl;
q->outb = outb;
q->outw = outw;
q->outl = outl;
q->priv = priv;
}
io_sethandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, 2);
}
void
io_removehandler_interleaved(uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
{
int c;
io_t *p, *q;
size <<= 2;
for (c = 0; c < size; c += 2) {
p = io[base + c];
if (!p)
return;
while(p) {
q = p->next;
if ((p->inb == inb) && (p->inw == inw) &&
(p->inl == inl) && (p->outb == outb) &&
(p->outw == outw) && (p->outl == outl) &&
(p->priv == priv)) {
if (p->prev)
p->prev->next = p->next;
if (p->next)
p->next->prev = p->prev;
free(p);
break;
}
p = q;
}
}
io_removehandler_common(base, size, inb, inw, inl, outb, outw, outl, priv, 2);
}
void
io_handler_interleaved(int set, uint16_t base, int size,
uint8_t (*inb)(uint16_t addr, void *priv),
uint16_t (*inw)(uint16_t addr, void *priv),
uint32_t (*inl)(uint16_t addr, void *priv),
void (*outb)(uint16_t addr, uint8_t val, void *priv),
void (*outw)(uint16_t addr, uint16_t val, void *priv),
void (*outl)(uint16_t addr, uint32_t val, void *priv),
void *priv)
{
io_handler_common(set, base, size, inb, inw, inl, outb, outw, outl, priv, 2);
}
#endif
uint8_t

162
src/log.c Normal file
View File

@@ -0,0 +1,162 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* The handler of the new logging system.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2021 Miran Grca.
* Copyright 2021 Fred N. van Kempen.
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/config.h>
#include <86box/mem.h>
#include "cpu.h"
#include <86box/plat.h>
#include <86box/version.h>
#include <86box/log.h>
#ifndef RELEASE_BUILD
typedef struct
{
char buff[1024], *dev_name;
int seen, suppr_seen;
} log_t;
void
log_set_suppr_seen(void *priv, int suppr_seen)
{
log_t *log = (log_t *) priv;
log->suppr_seen = suppr_seen;
}
void
log_set_dev_name(void *priv, char *dev_name)
{
log_t *log = (log_t *) priv;
log->dev_name = dev_name;
}
static void
log_copy(log_t *log, char *dest, const char *src, size_t dest_size)
{
memset(dest, 0x00, dest_size * sizeof(char));
if (log && log->dev_name && strcmp(log->dev_name, "")) {
strcat(dest, log->dev_name);
strcat(dest, ": ");
}
strcat(dest, src);
}
/*
* Log something to the logfile or stdout.
*
* To avoid excessively-large logfiles because some
* module repeatedly logs, we keep track of what is
* being logged, and catch repeating entries.
*/
void
log_out(void *priv, const char *fmt, va_list ap)
{
log_t *log = (log_t *) priv;
char temp[1024], fmt2[1024];
if (log == NULL)
return;
if (strcmp(fmt, "") == 0)
return;
if (stdlog == NULL) {
if (log_path[0] != '\0') {
stdlog = plat_fopen(log_path, "w");
if (stdlog == NULL)
stdlog = stdout;
} else
stdlog = stdout;
}
vsprintf(temp, fmt, ap);
if (log->suppr_seen && ! strcmp(log->buff, temp))
log->seen++;
else {
if (log->suppr_seen && log->seen) {
log_copy(log, fmt2, "*** %d repeats ***\n", 1024);
fprintf(stdlog, fmt2, log->seen);
}
log->seen = 0;
strcpy(log->buff, temp);
log_copy(log, fmt2, temp, 1024);
fprintf(stdlog, fmt2, ap);
}
fflush(stdlog);
}
void
log_fatal(void *priv, const char *fmt, ...)
{
log_t *log = (log_t *) priv;
char temp[1024], fmt2[1024];
va_list ap;
if (log == NULL)
return;
va_start(ap, fmt);
log_copy(log, fmt2, fmt, 1024);
vsprintf(temp, fmt2, ap);
fatal_ex(fmt2, ap);
va_end(ap);
exit(-1);
}
void *
log_open(char *dev_name)
{
log_t *log = malloc(sizeof(log_t));
memset(log, 0, sizeof(log_t));
log->dev_name = dev_name;
log->suppr_seen = 1;
return (void *) log;
}
void
log_close(void *priv)
{
log_t *log = (log_t *) priv;
free(log);
}
#endif

View File

@@ -20,8 +20,7 @@ add_library(mch OBJECT machine.c machine_table.c m_xt.c m_xt_compaq.c
m_at_t3100e.c m_at_t3100e_vid.c m_ps1.c m_ps1_hdc.c m_ps2_isa.c
m_ps2_mca.c m_at_compaq.c m_at_286_386sx.c m_at_386dx_486.c
m_at_socket4_5.c m_at_socket7.c m_at_sockets7.c m_at_socket8.c
m_at_slot1.c m_at_slot2.c m_at_socket370.c m_at_ebga368.c
m_at_misc.c)
m_at_slot1.c m_at_slot2.c m_at_socket370.c m_at_misc.c)
if(HEDAKA)
target_compile_definitions(mch PRIVATE USE_HEDAKA)

View File

@@ -2516,8 +2516,7 @@ machine_amstrad_init(const machine_t *model, int type)
mouse_set_poll(ms_poll, ams);
}
if (joystick_type)
device_add(&gameport_device);
standalone_gameport_type = &gameport_device;
}

View File

@@ -74,8 +74,7 @@ machine_at_common_init_ex(const machine_t *model, int type)
else if (type == 0)
device_add(&at_nvr_device);
if (joystick_type)
device_add(&gameport_device);
standalone_gameport_type = &gameport_device;
}

View File

@@ -644,7 +644,7 @@ machine_at_flytech386_init(const machine_t *model)
machine_at_common_init(model);
device_add(&ali1217_device);
device_add(&w83787f_ide_device);
device_add(&w83787f_ide_en_device);
device_add(&keyboard_ps2_device);
if (gfxcard == VID_INTERNAL)

View File

@@ -1,71 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of VIA EBGA368 Based Single Board Computers.
*
* Note: 86Box doesn't emulate all the components a SBC may have.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Tiseno100
*
* Copyright 2016-2019 Miran Grca.
* Copyright 2021 Tiseno100.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/mem.h>
#include <86box/io.h>
#include <86box/rom.h>
#include <86box/pci.h>
#include <86box/device.h>
#include <86box/chipset.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/keyboard.h>
#include <86box/flash.h>
#include <86box/sio.h>
#include <86box/hwm.h>
#include <86box/spd.h>
#include <86box/video.h>
#include "cpu.h"
#include <86box/machine.h>
int
machine_at_arb9673_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/arb9673/W9673.v12",
0x00080000, 524288, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x01, PCI_CARD_AGPBRIDGE, 1, 2, 3, 4);
device_add(&via_vt8601_device);
device_add(&via_vt82c686b_device);
device_add(&via_vt82c686_sio_device);
device_add(&via_vt82c686_hwm_device);
device_add(&keyboard_ps2_ami_pci_device);
device_add(&sst_flash_39sf040_device);
spd_register(SPD_TYPE_SDRAM, 0xf, 32);
return ret;
}

View File

@@ -204,8 +204,8 @@ machine_at_p2bls_init(const machine_t *model)
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x04, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3);
pci_register_slot(0x07, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* SCSI */
pci_register_slot(0x07, PCI_CARD_NORMAL, 3, 4, 1, 2); /* LAN */
pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3);

View File

@@ -516,8 +516,7 @@ ps1_common_init(const machine_t *model)
device_add(&keyboard_ps2_ps1_device);
/* Audio uses ports 200h and 202-207h, so only initialize gameport on 201h. */
if (joystick_type)
device_add(&gameport_201_device);
standalone_gameport_type = &gameport_201_device;
}

View File

@@ -1541,8 +1541,7 @@ machine_tandy1k_init(const machine_t *model, int type)
break;
}
if (joystick_type)
device_add(&gameport_device);
standalone_gameport_type = &gameport_device;
eep_data_out = 0x0000;
}

View File

@@ -30,8 +30,7 @@ machine_xt_common_init(const machine_t *model)
device_add(&fdc_xt_device);
nmi_init();
if (joystick_type)
device_add(&gameport_device);
standalone_gameport_type = &gameport_device;
}

View File

@@ -56,8 +56,7 @@ machine_xt_compaq_deskpro_init(const machine_t *model)
if (fdc_type == FDC_INTERNAL)
device_add(&fdc_xt_device);
nmi_init();
if (joystick_type)
device_add(&gameport_device);
standalone_gameport_type = &gameport_device;
lpt1_remove();
lpt1_init(0x03bc);

View File

@@ -174,8 +174,7 @@ machine_xt_lxt3_init(const machine_t *model)
if (fdc_type == FDC_INTERNAL)
device_add(&fdc_xt_device);
nmi_init();
if (joystick_type)
device_add(&gameport_device);
standalone_gameport_type = &gameport_device;
laserxt_init(1);

View File

@@ -738,8 +738,7 @@ machine_xt_m24_init(const machine_t *model)
/* FIXME: make sure this is correct?? */
device_add(&at_nvr_device);
if (joystick_type)
device_add(&gameport_device);
standalone_gameport_type = &gameport_device;
nmi_init();

View File

@@ -152,8 +152,7 @@ machine_xt_philips_common_init(const machine_t *model)
nmi_init();
if (joystick_type)
device_add(&gameport_device);
standalone_gameport_type = &gameport_device;
device_add(&keyboard_pc_device);

View File

@@ -181,8 +181,7 @@ machine_xt_xi8088_init(const machine_t *model)
nmi_init();
device_add(&ibmat_nvr_device);
pic2_init();
if (joystick_type)
device_add(&gameport_device);
standalone_gameport_type = &gameport_device;
return ret;
}

View File

@@ -34,6 +34,7 @@
#include <86box/rom.h>
#include <86box/lpt.h>
#include <86box/serial.h>
#include <86box/gameport.h>
#include "cpu.h"
#include <86box/video.h>
#include <86box/machine.h>
@@ -74,6 +75,8 @@ machine_init_ex(int m)
machine_log("Initializing as \"%s\"\n", machine_getname());
is_vpc = 0;
standalone_gameport_type = NULL;
gameport_instance_id = 0;
/* Set up the architecture flags. */
AT = IS_AT(machine);

View File

@@ -54,7 +54,6 @@ const machine_type_t machine_types[] = {
{ "Slot 1/2", MACHINE_TYPE_SLOT1_2 },
{ "Slot 2", MACHINE_TYPE_SLOT2 },
{ "Socket 370", MACHINE_TYPE_SOCKET370 },
{ "EBGA 368", MACHINE_TYPE_EBGA368 },
{ "Miscellaneous", MACHINE_TYPE_MISC }
};
@@ -340,7 +339,7 @@ const machine_t machines[] = {
{ "[i430VX] HP Brio 80xx", "brio80xx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 66666667, 66666667, 2200, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_brio80xx_init, NULL },
{ "[i430VX] Packard Bell PB680", "pb680", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2800, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_pb680_init, NULL },
{ "[i430VX] PC Partner MB520N", "mb520n", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2600, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mb520n_init, NULL },
{ "[i430VX] Shuttle HOT-557", "430vx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_i430vx_init, NULL },
{ "[i430VX] Shuttle HOT-557", "430vx", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 2500, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_GAMEPORT, 8192, 131072, 8192, 127, machine_at_i430vx_init, NULL },
/* 430TX */
{ "[i430TX] ADLink NuPRO-592", "nupro592", MACHINE_TYPE_SOCKET7, CPU_PKG_SOCKET5_7, 0, 66666667, 66666667, 1900, 2800, 1.5, 5.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 262144, 8192, 255, machine_at_nupro592_init, NULL },
@@ -464,10 +463,6 @@ const machine_t machines[] = {
{ "[VIA Apollo Pro133A] Acorp 6VIA90AP", "6via90ap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1572864, 8192, 255, machine_at_6via90ap_init, NULL },
{ "[VIA Apollo ProMedia] Jetway 603TCF", "603tcf", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_603tcf_init, NULL },
/* EBGA368 machines */
/* VIA Apollo Pro */
{ "[VIA Apollo ProMedia] Acrosser AR-B9673","arb9673", MACHINE_TYPE_EBGA368, CPU_PKG_EBGA368, 0, 100000000, 133333333, 2050, 2050, MACHINE_MULTIPLIER_FIXED, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 131072, 131072, 0, 31, machine_at_arb9673_init, NULL },
/* Miscellaneous/Fake/Hypervisor machines */
{ "[i440BX] Microsoft Virtual PC 2007", "vpc2007", MACHINE_TYPE_MISC, CPU_PKG_SLOT1, CPU_BLOCK(CPU_PENTIUM2, CPU_CYRIX3S), 0, 0, 0, 0, 0, 0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192,1048576, 8192, 255, machine_at_vpc2007_init, NULL },

View File

@@ -74,7 +74,7 @@ typedef struct flash_t
block_start[BLOCKS_NUM], block_end[BLOCKS_NUM],
block_len[BLOCKS_NUM];
mem_mapping_t mapping[4], mapping_h[8];
mem_mapping_t mapping[4], mapping_h[16];
} flash_t;
@@ -298,14 +298,13 @@ intel_flash_add_mappings(flash_t *dev)
uint32_t base, fbase;
uint32_t sub = 0x20000;
if (biosmask == 0x7ffff) {
if (biosmask == 0x7ffff) {
sub = 0x80000;
max = 8;
}
else if (biosmask == 0x3ffff) {
} else if (biosmask == 0x3ffff) {
sub = 0x40000;
max = 4;
}
}
for (i = 0; i < max; i++) {
if (biosmask == 0x7ffff)
@@ -331,7 +330,7 @@ intel_flash_add_mappings(flash_t *dev)
flash_read, flash_readw, flash_readl,
flash_write, flash_writew, flash_writel,
dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, (void *) dev);
mem_mapping_add(&(dev->mapping_h[i + 4]), (base | 0xfff00000), 0x10000,
mem_mapping_add(&(dev->mapping_h[i + max]), (base | 0xfff00000), 0x10000,
flash_read, flash_readw, flash_readl,
flash_write, flash_writew, flash_writel,
dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, (void *) dev);
@@ -415,101 +414,101 @@ intel_flash_init(const device_t *info)
dev->block_end[BLOCK_DATA2] = 0x7bfff;
dev->block_start[BLOCK_BOOT] = 0x7c000; /* BOOT BLOCK */
dev->block_end[BLOCK_BOOT] = 0x7ffff;
}
break;
}
break;
case 0x3ffff:
if (dev->flags & FLAG_WORD)
dev->flash_id = (dev->flags & FLAG_BXB) ? 0x2275 : 0x2274;
else
dev->flash_id = (dev->flags & FLAG_BXB) ? 0x7D : 0x7C;
case 0x3ffff:
if (dev->flags & FLAG_WORD)
dev->flash_id = (dev->flags & FLAG_BXB) ? 0x2275 : 0x2274;
else
dev->flash_id = (dev->flags & FLAG_BXB) ? 0x7D : 0x7C;
/* The block lengths are the same both flash types. */
dev->block_len[BLOCK_MAIN1] = 0x20000;
dev->block_len[BLOCK_MAIN2] = 0x18000;
dev->block_len[BLOCK_MAIN3] = 0x00000;
dev->block_len[BLOCK_MAIN4] = 0x00000;
dev->block_len[BLOCK_DATA1] = 0x02000;
dev->block_len[BLOCK_DATA2] = 0x02000;
dev->block_len[BLOCK_BOOT] = 0x04000;
/* The block lengths are the same both flash types. */
dev->block_len[BLOCK_MAIN1] = 0x20000;
dev->block_len[BLOCK_MAIN2] = 0x18000;
dev->block_len[BLOCK_MAIN3] = 0x00000;
dev->block_len[BLOCK_MAIN4] = 0x00000;
dev->block_len[BLOCK_DATA1] = 0x02000;
dev->block_len[BLOCK_DATA2] = 0x02000;
dev->block_len[BLOCK_BOOT] = 0x04000;
if (dev->flags & FLAG_BXB) { /* 28F002BX-B/28F200BX-B */
dev->block_start[BLOCK_MAIN1] = 0x20000; /* MAIN BLOCK 1 */
dev->block_end[BLOCK_MAIN1] = 0x3ffff;
dev->block_start[BLOCK_MAIN2] = 0x08000; /* MAIN BLOCK 2 */
dev->block_end[BLOCK_MAIN2] = 0x1ffff;
dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */
dev->block_end[BLOCK_MAIN3] = 0xfffff;
dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */
dev->block_end[BLOCK_MAIN4] = 0xfffff;
dev->block_start[BLOCK_DATA1] = 0x06000; /* DATA AREA 1 BLOCK */
dev->block_end[BLOCK_DATA1] = 0x07fff;
dev->block_start[BLOCK_DATA2] = 0x04000; /* DATA AREA 2 BLOCK */
dev->block_end[BLOCK_DATA2] = 0x05fff;
dev->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */
dev->block_end[BLOCK_BOOT] = 0x03fff;
} else { /* 28F002BX-T/28F200BX-T */
dev->block_start[BLOCK_MAIN1] = 0x00000; /* MAIN BLOCK 1 */
dev->block_end[BLOCK_MAIN1] = 0x1ffff;
dev->block_start[BLOCK_MAIN2] = 0x20000; /* MAIN BLOCK 2 */
dev->block_end[BLOCK_MAIN2] = 0x37fff;
dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */
dev->block_end[BLOCK_MAIN3] = 0xfffff;
dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */
dev->block_end[BLOCK_MAIN4] = 0xfffff;
dev->block_start[BLOCK_DATA1] = 0x38000; /* DATA AREA 1 BLOCK */
dev->block_end[BLOCK_DATA1] = 0x39fff;
dev->block_start[BLOCK_DATA2] = 0x3a000; /* DATA AREA 2 BLOCK */
dev->block_end[BLOCK_DATA2] = 0x3bfff;
dev->block_start[BLOCK_BOOT] = 0x3c000; /* BOOT BLOCK */
dev->block_end[BLOCK_BOOT] = 0x3ffff;
}
break;
if (dev->flags & FLAG_BXB) { /* 28F002BX-B/28F200BX-B */
dev->block_start[BLOCK_MAIN1] = 0x20000; /* MAIN BLOCK 1 */
dev->block_end[BLOCK_MAIN1] = 0x3ffff;
dev->block_start[BLOCK_MAIN2] = 0x08000; /* MAIN BLOCK 2 */
dev->block_end[BLOCK_MAIN2] = 0x1ffff;
dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */
dev->block_end[BLOCK_MAIN3] = 0xfffff;
dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */
dev->block_end[BLOCK_MAIN4] = 0xfffff;
dev->block_start[BLOCK_DATA1] = 0x06000; /* DATA AREA 1 BLOCK */
dev->block_end[BLOCK_DATA1] = 0x07fff;
dev->block_start[BLOCK_DATA2] = 0x04000; /* DATA AREA 2 BLOCK */
dev->block_end[BLOCK_DATA2] = 0x05fff;
dev->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */
dev->block_end[BLOCK_BOOT] = 0x03fff;
} else { /* 28F002BX-T/28F200BX-T */
dev->block_start[BLOCK_MAIN1] = 0x00000; /* MAIN BLOCK 1 */
dev->block_end[BLOCK_MAIN1] = 0x1ffff;
dev->block_start[BLOCK_MAIN2] = 0x20000; /* MAIN BLOCK 2 */
dev->block_end[BLOCK_MAIN2] = 0x37fff;
dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */
dev->block_end[BLOCK_MAIN3] = 0xfffff;
dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */
dev->block_end[BLOCK_MAIN4] = 0xfffff;
dev->block_start[BLOCK_DATA1] = 0x38000; /* DATA AREA 1 BLOCK */
dev->block_end[BLOCK_DATA1] = 0x39fff;
dev->block_start[BLOCK_DATA2] = 0x3a000; /* DATA AREA 2 BLOCK */
dev->block_end[BLOCK_DATA2] = 0x3bfff;
dev->block_start[BLOCK_BOOT] = 0x3c000; /* BOOT BLOCK */
dev->block_end[BLOCK_BOOT] = 0x3ffff;
}
break;
default:
dev->flash_id = (type & FLAG_BXB) ? 0x95 : 0x94;
default:
dev->flash_id = (type & FLAG_BXB) ? 0x95 : 0x94;
/* The block lengths are the same both flash types. */
dev->block_len[BLOCK_MAIN1] = 0x1c000;
dev->block_len[BLOCK_MAIN2] = 0x00000;
dev->block_len[BLOCK_MAIN3] = 0x00000;
dev->block_len[BLOCK_MAIN4] = 0x00000;
dev->block_len[BLOCK_DATA1] = 0x01000;
dev->block_len[BLOCK_DATA2] = 0x01000;
dev->block_len[BLOCK_BOOT] = 0x02000;
/* The block lengths are the same both flash types. */
dev->block_len[BLOCK_MAIN1] = 0x1c000;
dev->block_len[BLOCK_MAIN2] = 0x00000;
dev->block_len[BLOCK_MAIN3] = 0x00000;
dev->block_len[BLOCK_MAIN4] = 0x00000;
dev->block_len[BLOCK_DATA1] = 0x01000;
dev->block_len[BLOCK_DATA2] = 0x01000;
dev->block_len[BLOCK_BOOT] = 0x02000;
if (dev->flags & FLAG_BXB) { /* 28F001BX-B/28F100BX-B */
dev->block_start[BLOCK_MAIN1] = 0x04000; /* MAIN BLOCK 1 */
dev->block_end[BLOCK_MAIN1] = 0x1ffff;
dev->block_start[BLOCK_MAIN2] = 0xfffff; /* MAIN BLOCK 2 */
dev->block_end[BLOCK_MAIN2] = 0xfffff;
dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */
dev->block_end[BLOCK_MAIN3] = 0xfffff;
dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */
dev->block_end[BLOCK_MAIN4] = 0xfffff;
dev->block_start[BLOCK_DATA1] = 0x02000; /* DATA AREA 1 BLOCK */
dev->block_end[BLOCK_DATA1] = 0x02fff;
dev->block_start[BLOCK_DATA2] = 0x03000; /* DATA AREA 2 BLOCK */
dev->block_end[BLOCK_DATA2] = 0x03fff;
dev->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */
dev->block_end[BLOCK_BOOT] = 0x01fff;
} else { /* 28F001BX-T/28F100BX-T */
dev->block_start[BLOCK_MAIN1] = 0x00000; /* MAIN BLOCK 1 */
dev->block_end[BLOCK_MAIN1] = 0x1bfff;
dev->block_start[BLOCK_MAIN2] = 0xfffff; /* MAIN BLOCK 2 */
dev->block_end[BLOCK_MAIN2] = 0xfffff;
dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */
dev->block_end[BLOCK_MAIN3] = 0xfffff;
dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */
dev->block_end[BLOCK_MAIN4] = 0xfffff;
dev->block_start[BLOCK_DATA1] = 0x1c000; /* DATA AREA 1 BLOCK */
dev->block_end[BLOCK_DATA1] = 0x1cfff;
dev->block_start[BLOCK_DATA2] = 0x1d000; /* DATA AREA 2 BLOCK */
dev->block_end[BLOCK_DATA2] = 0x1dfff;
dev->block_start[BLOCK_BOOT] = 0x1e000; /* BOOT BLOCK */
dev->block_end[BLOCK_BOOT] = 0x1ffff;
}
break;
if (dev->flags & FLAG_BXB) { /* 28F001BX-B/28F100BX-B */
dev->block_start[BLOCK_MAIN1] = 0x04000; /* MAIN BLOCK 1 */
dev->block_end[BLOCK_MAIN1] = 0x1ffff;
dev->block_start[BLOCK_MAIN2] = 0xfffff; /* MAIN BLOCK 2 */
dev->block_end[BLOCK_MAIN2] = 0xfffff;
dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */
dev->block_end[BLOCK_MAIN3] = 0xfffff;
dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */
dev->block_end[BLOCK_MAIN4] = 0xfffff;
dev->block_start[BLOCK_DATA1] = 0x02000; /* DATA AREA 1 BLOCK */
dev->block_end[BLOCK_DATA1] = 0x02fff;
dev->block_start[BLOCK_DATA2] = 0x03000; /* DATA AREA 2 BLOCK */
dev->block_end[BLOCK_DATA2] = 0x03fff;
dev->block_start[BLOCK_BOOT] = 0x00000; /* BOOT BLOCK */
dev->block_end[BLOCK_BOOT] = 0x01fff;
} else { /* 28F001BX-T/28F100BX-T */
dev->block_start[BLOCK_MAIN1] = 0x00000; /* MAIN BLOCK 1 */
dev->block_end[BLOCK_MAIN1] = 0x1bfff;
dev->block_start[BLOCK_MAIN2] = 0xfffff; /* MAIN BLOCK 2 */
dev->block_end[BLOCK_MAIN2] = 0xfffff;
dev->block_start[BLOCK_MAIN3] = 0xfffff; /* MAIN BLOCK 3 */
dev->block_end[BLOCK_MAIN3] = 0xfffff;
dev->block_start[BLOCK_MAIN4] = 0xfffff; /* MAIN BLOCK 4 */
dev->block_end[BLOCK_MAIN4] = 0xfffff;
dev->block_start[BLOCK_DATA1] = 0x1c000; /* DATA AREA 1 BLOCK */
dev->block_end[BLOCK_DATA1] = 0x1cfff;
dev->block_start[BLOCK_DATA2] = 0x1d000; /* DATA AREA 2 BLOCK */
dev->block_end[BLOCK_DATA2] = 0x1dfff;
dev->block_start[BLOCK_BOOT] = 0x1e000; /* BOOT BLOCK */
dev->block_end[BLOCK_BOOT] = 0x1ffff;
}
break;
}
intel_flash_add_mappings(dev);

View File

@@ -2585,7 +2585,24 @@ mem_reset(void)
memset(page_ff, 0xff, sizeof(page_ff));
m = 1024UL * mem_size;
#ifdef USE_NEW_DYNAREC
if (byte_dirty_mask) {
free(byte_dirty_mask);
byte_dirty_mask = NULL;
}
if (byte_code_present_mask) {
free(byte_code_present_mask);
byte_code_present_mask = NULL;
}
#endif
/* Free the old pages array, if necessary. */
if (pages) {
free(pages);
pages = NULL;
}
if (ram != NULL) {
free(ram);
ram = NULL;
@@ -2596,9 +2613,12 @@ mem_reset(void)
ram2 = NULL;
}
#endif
if (mem_size > 2097152)
fatal("Attempting to use more than 2 GB of emulated RAM\n");
m = 1024UL * mem_size;
#if (!(defined __amd64__ || defined _M_X64))
if (mem_size > 1048576) {
ram = (uint8_t *)malloc(1 << 30); /* allocate and clear the RAM block of the first 1 GB */
@@ -2655,16 +2675,9 @@ mem_reset(void)
/*
* Allocate and initialize the (new) page table.
* We only do this if the size of the page table has changed.
*/
if (pages_sz != m) {
pages_sz = m;
if (pages) {
free(pages);
pages = NULL;
}
pages = (page_t *)malloc(m*sizeof(page_t));
}
pages_sz = m;
pages = (page_t *)malloc(m*sizeof(page_t));
memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *));
memset(page_lookupp, 0x04, (1 << 20) * sizeof(uint8_t));
@@ -2672,17 +2685,9 @@ mem_reset(void)
memset(pages, 0x00, pages_sz*sizeof(page_t));
#ifdef USE_NEW_DYNAREC
if (byte_dirty_mask) {
free(byte_dirty_mask);
byte_dirty_mask = NULL;
}
byte_dirty_mask = malloc((mem_size * 1024) / 8);
memset(byte_dirty_mask, 0, (mem_size * 1024) / 8);
if (byte_code_present_mask) {
free(byte_code_present_mask);
byte_code_present_mask = NULL;
}
byte_code_present_mask = malloc((mem_size * 1024) / 8);
memset(byte_code_present_mask, 0, (mem_size * 1024) / 8);
#endif

View File

@@ -427,7 +427,7 @@ check_alarm_via(nvr_t *nvr, int8_t addr, int8_t addr_2)
return((nvr->regs[addr_2] == nvr->regs[addr]) ||
((nvr->regs[addr_2] & AL_DONTCARE) == AL_DONTCARE));
} else
return 0;
return 1;
}
@@ -456,9 +456,9 @@ timer_update(void *priv)
check_alarm(nvr, RTC_MINUTES) &&
check_alarm(nvr, RTC_HOURS) &&
check_alarm_via(nvr, RTC_DOM, RTC_ALDAY) &&
check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH) &&
check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH)/* &&
check_alarm_via(nvr, RTC_DOM, RTC_ALDAY_SIS) &&
check_alarm_via(nvr, RTC_MONTH, RTC_ALMONT_SIS)) {
check_alarm_via(nvr, RTC_MONTH, RTC_ALMONT_SIS)*/) {
nvr->regs[RTC_REGC] |= REGC_AF;
if (nvr->regs[RTC_REGB] & REGB_AIE) {
nvr->regs[RTC_REGC] |= REGC_IRQF;
@@ -996,8 +996,10 @@ nvr_at_init(const device_t *info)
/* Set up the I/O handler for this device. */
io_sethandler(0x0070, 2,
nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr);
if (info->local & 8) {
io_sethandler(0x0072, 2,
nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr);
}
nvr_at_inited = 1;
}

View File

@@ -59,7 +59,7 @@ static uint8_t pci_pmc = 0, last_pci_card = 0, last_normal_pci_card = 0, last_p
static uint8_t pci_card_to_slot_mapping[256][32], pci_bus_number_to_index_mapping[256];
static uint8_t pci_irqs[16], pci_irq_level[16];
static uint64_t pci_irq_hold[16];
static pci_mirq_t pci_mirqs[3];
static pci_mirq_t pci_mirqs[4];
static int pci_type,
pci_switch,
pci_index,
@@ -446,7 +446,7 @@ pci_set_irq(uint8_t card, uint8_t pci_int)
} else
pci_log("pci_set_irq(%02X, %02X): Using IRQ %i\n", card, pci_int, irq_line);
if (picint_is_level(irq_line) && (pci_irq_hold[irq_line] & (1ULL << slot))) {
if (level && (pci_irq_hold[irq_line] & (1ULL << slot))) {
/* IRQ already held, do nothing. */
pci_log("pci_set_irq(%02X, %02X): Card is already holding the IRQ\n", card, pci_int);
return;
@@ -709,7 +709,7 @@ trc_reset(uint8_t val)
{
if (val & 2) {
dma_reset();
device_reset_all_pci();
device_reset_all();
cpu_alt_reset = 0;

View File

@@ -478,17 +478,17 @@ fdc37c93x_write(uint16_t port, uint8_t val, void *priv)
break;
case 0xF1:
if (valxor & 0xC)
fdc_update_densel_force(dev->fdc, (val & 0xC) >> 2);
fdc_update_densel_force(dev->fdc, (val & 0xc) >> 2);
break;
case 0xF2:
if (valxor & 0xC0)
fdc_update_rwc(dev->fdc, 3, (valxor & 0xC0) >> 6);
fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6);
if (valxor & 0x30)
fdc_update_rwc(dev->fdc, 2, (valxor & 0x30) >> 4);
fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4);
if (valxor & 0x0C)
fdc_update_rwc(dev->fdc, 1, (valxor & 0x0C) >> 2);
fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2);
if (valxor & 0x03)
fdc_update_rwc(dev->fdc, 0, (valxor & 0x03));
fdc_update_rwc(dev->fdc, 0, (val & 0x03));
break;
case 0xF4:
if (valxor & 0x18)

View File

@@ -31,24 +31,27 @@
#include <86box/fdc.h>
#include <86box/sio.h>
#define SIO_INDEX_PORT dev->sio_index_port
#define INDEX dev->index
#define SIO_INDEX_PORT dev->sio_index_port
#define INDEX dev->index
/* Current Logical Device Number */
#define CURRENT_LOGICAL_DEVICE dev->regs[0x07]
#define CURRENT_LOGICAL_DEVICE dev->regs[0x07]
/* Global Device Configuration */
#define ENABLED dev->device_regs[CURRENT_LOGICAL_DEVICE][0x30]
#define BASE_ADDRESS ((dev->device_regs[CURRENT_LOGICAL_DEVICE][0x60] << 8) | (dev->device_regs[CURRENT_LOGICAL_DEVICE][0x61]))
#define IRQ dev->device_regs[CURRENT_LOGICAL_DEVICE][0x70]
#define DMA dev->device_regs[CURRENT_LOGICAL_DEVICE][0x74]
#define ENABLED(ld) dev->device_regs[ld][0x30]
#define BASE_ADDRESS(ld) ((dev->device_regs[ld][0x60] << 8) | \
(dev->device_regs[ld][0x61]))
#define IRQ(ld) dev->device_regs[ld][0x70]
#define DMA(ld) dev->device_regs[ld][0x74]
/* Miscellaneous Chip Functionality */
#define SOFT_RESET (val & 0x01)
#define POWER_CONTROL dev->regs[0x22]
#define SOFT_RESET (val & 0x01)
#define POWER_CONTROL dev->regs[0x22]
#ifdef ENABLE_FDC37M60X_LOG
int fdc37m60x_do_log = ENABLE_FDC37M60X_LOG;
static void
fdc37m60x_log(const char *fmt, ...)
{
@@ -65,196 +68,217 @@ fdc37m60x_log(const char *fmt, ...)
#define fdc37m60x_log(fmt, ...)
#endif
typedef struct
{
uint8_t index, regs[256], device_regs[10][256], cfg_lock, ide_function;
uint16_t sio_index_port;
uint8_t index, regs[256], device_regs[10][256], cfg_lock, ide_function;
uint16_t sio_index_port;
fdc_t *fdc_controller;
serial_t *uart[2];
fdc_t * fdc;
serial_t * uart[2];
} fdc37m60x_t;
void fdc37m60x_fdc_handler(fdc37m60x_t *dev);
void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev);
void fdc37m60x_lpt_handler(fdc37m60x_t *dev);
void fdc37m60x_logical_device_handler(fdc37m60x_t *dev);
static void fdc37m60x_reset(void *priv);
static void fdc37m60x_fdc_handler(fdc37m60x_t *dev);
static void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev);
static void fdc37m60x_lpt_handler(fdc37m60x_t *dev);
static void fdc37m60x_logical_device_handler(fdc37m60x_t *dev);
static void fdc37m60x_reset(void *priv);
static void
fdc37m60x_write(uint16_t addr, uint8_t val, void *priv)
{
fdc37m60x_t *dev = (fdc37m60x_t *)priv;
switch (addr)
{
case 0x3f0:
case 0x370:
INDEX = val;
if (addr & 1) {
if (!dev->cfg_lock) {
switch (INDEX) {
/* Global Configuration */
case 0x02:
dev->regs[INDEX] = val;
if (SOFT_RESET)
fdc37m60x_reset(dev);
break;
/* Enter/Escape Configuration Mode */
if (val == 0x55)
dev->cfg_lock = 0;
else if (val == 0xaa)
dev->cfg_lock = 1;
break;
case 0x07:
CURRENT_LOGICAL_DEVICE = val;
break;
case 0x3f1:
case 0x371:
if (!dev->cfg_lock)
{
switch (INDEX)
{
/* Global Configuration */
case 0x02:
dev->regs[INDEX] = val;
if (SOFT_RESET)
fdc37m60x_reset(dev);
break;
case 0x22:
POWER_CONTROL = val & 0x3f;
break;
case 0x07:
CURRENT_LOGICAL_DEVICE = (val & 0x0f);
break;
case 0x23:
dev->regs[INDEX] = val & 0x3f;
break;
case 0x22:
POWER_CONTROL = val & 0x3f;
break;
case 0x24:
dev->regs[INDEX] = val & 0x4e;
break;
case 0x23:
dev->regs[INDEX] = val & 0x3f;
break;
case 0x2b: case 0x2c: case 0x2d: case 0x2e:
case 0x2f:
dev->regs[INDEX] = val;
break;
case 0x24:
dev->regs[INDEX] = val & 0xce;
break;
/* Device Configuration */
case 0x30:
case 0x60:
case 0x61:
case 0x70:
case 0x74:
if(CURRENT_LOGICAL_DEVICE <= 0x81) /* Avoid Overflow */
dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] = (INDEX == 0x30) ? (val & 1) : val;
fdc37m60x_logical_device_handler(dev);
break;
}
/* Device Configuration */
case 0x30:
case 0x60: case 0x61:
case 0x70:
case 0x74:
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
if (CURRENT_LOGICAL_DEVICE <= 0x81) /* Avoid Overflow */
dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] = (INDEX == 0x30) ? (val & 1) : val;
fdc37m60x_logical_device_handler(dev);
break;
}
}
break;
} else {
/* Enter/Escape Configuration Mode */
if (val == 0x55)
dev->cfg_lock = 0;
else if (!dev->cfg_lock && (val == 0xaa))
dev->cfg_lock = 1;
else if (!dev->cfg_lock)
INDEX = val;
}
}
static uint8_t
fdc37m60x_read(uint16_t addr, void *priv)
{
fdc37m60x_t *dev = (fdc37m60x_t *)priv;
uint8_t ret = 0xff;
return (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX];
if (addr & 1)
ret = (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX];
return ret;
}
void fdc37m60x_fdc_handler(fdc37m60x_t *dev)
static void
fdc37m60x_fdc_handler(fdc37m60x_t *dev)
{
fdc_remove(dev->fdc_controller);
if(ENABLED || (POWER_CONTROL & 0x01))
fdc_remove(dev->fdc);
if (ENABLED(0) || (POWER_CONTROL & 0x01))
{
fdc_set_base(dev->fdc_controller, BASE_ADDRESS);
fdc_set_irq(dev->fdc_controller, IRQ & 0xf);
fdc_set_dma_ch(dev->fdc_controller, DMA & 0x07);
fdc37m60x_log("SMC60x-FDC: BASE %04x IRQ %d DMA %d\n", BASE_ADDRESS, IRQ & 0xf, DMA & 0x07);
fdc_set_base(dev->fdc, BASE_ADDRESS(0));
fdc_set_irq(dev->fdc, IRQ(0) & 0xf);
fdc_set_dma_ch(dev->fdc, DMA(0) & 0x07);
fdc37m60x_log("SMC60x-FDC: BASE %04x IRQ %d DMA %d\n", BASE_ADDRESS(0), IRQ(0) & 0xf, DMA(0) & 0x07);
}
fdc_update_enh_mode(dev->fdc, dev->device_regs[0][0xf0] & 0x01);
fdc_update_densel_force(dev->fdc, (dev->device_regs[0][0xf1] & 0xc) >> 2);
fdc_update_rwc(dev->fdc, 3, (dev->device_regs[0][0xf2] & 0xc0) >> 6);
fdc_update_rwc(dev->fdc, 2, (dev->device_regs[0][0xf2] & 0x30) >> 4);
fdc_update_rwc(dev->fdc, 1, (dev->device_regs[0][0xf2] & 0x0c) >> 2);
fdc_update_rwc(dev->fdc, 0, (dev->device_regs[0][0xf2] & 0x03));
fdc_update_drvrate(dev->fdc, 0, (dev->device_regs[0][0xf4] & 0x18) >> 3);
fdc_update_drvrate(dev->fdc, 1, (dev->device_regs[0][0xf5] & 0x18) >> 3);
fdc_update_drvrate(dev->fdc, 2, (dev->device_regs[0][0xf6] & 0x18) >> 3);
fdc_update_drvrate(dev->fdc, 3, (dev->device_regs[0][0xf7] & 0x18) >> 3);
}
void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev)
static void
fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev)
{
serial_remove(dev->uart[num & 1]);
if(!(num & 1) ? (ENABLED || (POWER_CONTROL & 0x10)) : (ENABLED || (POWER_CONTROL & 0x20)))
if (ENABLED(4 + (num & 1)) || (POWER_CONTROL & (1 << (4 + (num & 1)))))
{
serial_setup(dev->uart[num & 1], BASE_ADDRESS, IRQ & 0xf);
fdc37m60x_log("SMC60x-UART%d: BASE %04x IRQ %d\n", num & 1, BASE_ADDRESS, IRQ & 0xf);
serial_setup(dev->uart[num & 1], BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf);
fdc37m60x_log("SMC60x-UART%d: BASE %04x IRQ %d\n", num & 1, BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf);
}
}
void fdc37m60x_lpt_handler(fdc37m60x_t *dev)
{
lpt1_remove();
if(ENABLED || (POWER_CONTROL & 0x80))
{
lpt1_init(BASE_ADDRESS);
lpt1_irq(IRQ & 0xf);
fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS, IRQ & 0xf);
if (ENABLED(3) || (POWER_CONTROL & 0x08)) {
lpt1_init(BASE_ADDRESS(3));
lpt1_irq(IRQ(3) & 0xf);
fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS(3), IRQ(3) & 0xf);
}
}
void fdc37m60x_logical_device_handler(fdc37m60x_t *dev)
{
/*
Register 07h:
Device 0: FDC
Device 3: LPT
Device 4: UART1
Device 5: UART2
*/
switch (CURRENT_LOGICAL_DEVICE)
{
case 0x00:
fdc37m60x_fdc_handler(dev);
break;
/* Register 07h:
Device 0: FDC
Device 3: LPT
Device 4: UART1
Device 5: UART2
*/
case 0x03:
fdc37m60x_lpt_handler(dev);
break;
switch (CURRENT_LOGICAL_DEVICE) {
case 0x00:
fdc37m60x_fdc_handler(dev);
break;
case 0x04:
fdc37m60x_uart_handler(0, dev);
break;
case 0x03:
fdc37m60x_lpt_handler(dev);
break;
case 0x05:
fdc37m60x_uart_handler(1, dev);
break;
case 0x04:
fdc37m60x_uart_handler(0, dev);
break;
case 0x05:
fdc37m60x_uart_handler(1, dev);
break;
}
}
static void
fdc37m60x_reset(void *priv)
{
fdc37m60x_t *dev = (fdc37m60x_t *)priv;
fdc37m60x_t *dev = (fdc37m60x_t *) priv;
uint8_t i;
CURRENT_LOGICAL_DEVICE = 0x00;
dev->regs[0x22] = 0x00;
memset(dev->regs, 0, sizeof(dev->regs));
for (i = 0; i < 10; i++)
memset(dev->device_regs[i], 0, sizeof(dev->device_regs[i]));
dev->regs[0x20] = 0x47;
dev->regs[0x24] = 0x04;
dev->regs[0x26] = SIO_INDEX_PORT & 0xf;
dev->regs[0x27] = (SIO_INDEX_PORT >> 4) & 0xf;
/* FDC Registers */
dev->device_regs[0][0x30] = 0x00;
dev->device_regs[0][0x60] = 0x03; /* Base Address */
dev->device_regs[0][0x61] = 0xf0;
dev->device_regs[0][0x70] = 0x06;
dev->device_regs[0][0x74] = 0x02;
dev->device_regs[0][0xf0] = 0x0e;
dev->device_regs[0][0xf2] = 0xff;
/* LPT Port */
dev->device_regs[3][0x30] = 0x00;
dev->device_regs[3][0x60] = 0x00; /* Base Address */
dev->device_regs[3][0x61] = 0x00;
dev->device_regs[3][0x64] = 0x04;
dev->device_regs[3][0x74] = 0x04;
dev->device_regs[3][0xf0] = 0x3c;
/* UART1 */
dev->device_regs[4][0x30] = 0x00;
dev->device_regs[4][0x60] = 0x00; /* Base Address */
dev->device_regs[4][0x61] = 0x00;
dev->device_regs[4][0x70] = 0x00;
/* UART2 */
dev->device_regs[5][0x30] = 0x00;
dev->device_regs[5][0x60] = 0x00; /* Base Address */
dev->device_regs[5][0x61] = 0x00;
dev->device_regs[5][0x70] = 0x00;
dev->device_regs[4][0x74] = 0x04;
dev->device_regs[4][0xf1] = 0x02;
dev->device_regs[4][0xf2] = 0x03;
/* AUX */
dev->device_regs[8][0x30] = 0x00;
dev->device_regs[8][0xc0] = 0x06;
dev->device_regs[8][0xc1] = 0x03;
fdc37m60x_fdc_handler(dev);
fdc37m60x_uart_handler(0, dev);
@@ -262,6 +286,7 @@ fdc37m60x_reset(void *priv)
fdc37m60x_lpt_handler(dev);
}
static void
fdc37m60x_close(void *priv)
{
@@ -270,6 +295,7 @@ fdc37m60x_close(void *priv)
free(dev);
}
static void *
fdc37m60x_init(const device_t *info)
{
@@ -277,25 +303,18 @@ fdc37m60x_init(const device_t *info)
memset(dev, 0, sizeof(fdc37m60x_t));
SIO_INDEX_PORT = info->local;
dev->regs[0x20] = 0x47;
dev->regs[0x24] = 0x04;
dev->device_regs[0][0xf0] = 0x0e;
dev->device_regs[0][0xf2] = 0xff;
dev->device_regs[3][0xf0] = 0x3c;
dev->device_regs[4][0xf1] = 0x02;
dev->device_regs[4][0xf2] = 0x03;
dev->device_regs[8][0xc0] = 0x06;
dev->device_regs[8][0xc1] = 0x03;
dev->fdc_controller = device_add(&fdc_at_smc_device);
dev->fdc = device_add(&fdc_at_smc_device);
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
io_sethandler(SIO_INDEX_PORT, 0x0002, fdc37m60x_read, NULL, NULL, fdc37m60x_write, NULL, NULL, dev);
fdc37m60x_reset(dev);
return dev;
}
const device_t fdc37m60x_device = {
"SMSC FDC37M60X",
0,
@@ -303,10 +322,11 @@ const device_t fdc37m60x_device = {
fdc37m60x_init,
fdc37m60x_close,
NULL,
{NULL},
{ NULL },
NULL,
NULL,
NULL};
NULL
};
const device_t fdc37m60x_370_device = {
"SMSC FDC37M60X with 10K Pull Up Resistor",
@@ -315,7 +335,8 @@ const device_t fdc37m60x_370_device = {
fdc37m60x_init,
fdc37m60x_close,
NULL,
{NULL},
{ NULL },
NULL,
NULL,
NULL};
NULL
};

View File

@@ -127,7 +127,8 @@ prime3c_write(uint16_t addr, uint8_t val, void *priv)
case 0xc5:
IDE_SIDE_ADDRESS = (val & 0xfc) | 0x02;
prime3c_ide_handler(dev);
if (HAS_IDE_FUNCTIONALITY)
prime3c_ide_handler(dev);
break;
case 0xc6:

View File

@@ -39,7 +39,7 @@
#include <86box/isapnp.h>
/* This ROM is reconstructed out of the several assumptions, some of which are based on the IT8671F. */
/* This ROM is reconstructed out of several assumptions, some of which are based on the IT8671F. */
static uint8_t um8669f_pnp_rom[] = {
0x55, 0xa3, 0x86, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, /* UMC8669, dummy checksum (filled in by isapnp_add_card) */
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
@@ -89,7 +89,7 @@ static const isapnp_device_config_t um8669f_pnp_defaults[] = {
}, {
.activate = 0
}, {
.activate = 1,
.activate = 0,
.io = { { .base = 0x200 }, }
}
};
@@ -117,14 +117,15 @@ um8669f_log(const char *fmt, ...)
typedef struct um8669f_t
{
int locked, cur_reg_108;
void *pnp_card;
int locked, cur_reg_108;
void *pnp_card;
isapnp_device_config_t *pnp_config[5];
uint8_t regs_108[256];
uint8_t regs_108[256];
fdc_t *fdc;
serial_t *uart[2];
fdc_t *fdc;
serial_t *uart[2];
void *gameport;
} um8669f_t;
@@ -179,13 +180,13 @@ um8669f_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *pri
break;
case 5:
gameport_remap(0);
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
um8669f_log("UM8669F: Game port enabled at port %04X\n", config->io[0].base);
gameport_remap(config->io[0].base);
} else
gameport_remap(dev->gameport, config->io[0].base);
} else {
um8669f_log("UM8669F: Game port disabled\n");
gameport_remap(dev->gameport, 0);
}
}
}
@@ -211,7 +212,7 @@ um8669f_write(uint16_t port, uint8_t val, void *priv)
if (dev->cur_reg_108 == 0xc1) {
um8669f_log("UM8669F: ISAPnP %sabled\n", (val & 0x80) ? "en" : "dis");
isapnp_enable_card(dev->pnp_card, (val & 0x80) ? 2 : 0);
isapnp_enable_card(dev->pnp_card, (val & 0x80) ? ISAPNP_CARD_FORCE_CONFIG : ISAPNP_CARD_DISABLE);
}
}
}
@@ -250,7 +251,7 @@ um8669f_reset(um8669f_t *dev)
lpt1_remove();
isapnp_enable_card(dev->pnp_card, 0);
isapnp_enable_card(dev->pnp_card, ISAPNP_CARD_DISABLE);
dev->locked = 1;
@@ -286,6 +287,8 @@ um8669f_init(const device_t *info)
dev->uart[0] = device_add_inst(&ns16550_device, 1);
dev->uart[1] = device_add_inst(&ns16550_device, 2);
dev->gameport = gameport_add(&gameport_sio_device);
io_sethandler(0x0108, 0x0002,
um8669f_read, NULL, NULL, um8669f_write, NULL, NULL, dev);

View File

@@ -78,7 +78,8 @@ typedef struct {
uint16_t reg_init;
int locked, rw_locked,
cur_reg,
key, ide_function;
key, ide_function,
ide_start;
fdc_t *fdc;
serial_t *uart[2];
} w83787f_t;
@@ -260,6 +261,7 @@ w83787f_write(uint16_t port, uint8_t val, void *priv)
switch (dev->cur_reg) {
case 0:
pclog("REG 00: %02X\n", val);
if ((valxor & 0xc0) && (HAS_IDE_FUNCTIONALITY))
w83787f_ide_handler(dev);
if (valxor & 0x30)
@@ -376,6 +378,14 @@ w83787f_reset(w83787f_t *dev)
ide_set_base(0, 0x1f0);
ide_set_side(0, 0x3f6);
}
if (dev->ide_start) {
dev->regs[0x00] &= 0x7f;
if (dev->ide_function & 0x20)
ide_sec_enable();
else
ide_pri_enable();
}
} else
dev->regs[0x00] = 0xd0;
@@ -426,6 +436,8 @@ w83787f_init(const device_t *info)
if ((dev->ide_function & 0x30) == 0x10)
device_add(&ide_isa_device);
dev->ide_start = !!(info->local & 0x40);
dev->reg_init = info->local & 0x0f;
w83787f_reset(dev);
@@ -451,6 +463,15 @@ const device_t w83787f_ide_device = {
NULL
};
const device_t w83787f_ide_en_device = {
"Winbond W83787F/IF Super I/O (With IDE Enabled)",
0,
0x59,
w83787f_init, w83787f_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t w83787f_ide_sec_device = {
"Winbond W83787F/IF Super I/O (With Secondary IDE)",
0,

View File

@@ -16,8 +16,8 @@
add_library(snd OBJECT sound.c openal.c snd_opl.c snd_opl_nuked.c snd_resid.cc
midi.c midi_system.c snd_speaker.c snd_pssj.c snd_lpt_dac.c
snd_lpt_dss.c snd_adlib.c snd_adlibgold.c snd_ad1848.c snd_audiopci.c
snd_azt2316a.c snd_cms.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)
snd_azt2316a.c snd_cms.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)
if(FLUIDSYNTH)
target_compile_definitions(snd PRIVATE USE_FLUIDSYNTH)

View File

@@ -1,6 +1,23 @@
/*
AD1848 / CS4248 / CS4231 CODEC emulation (Windows Sound System compatible)*/
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* AD1848 / CS4248 / CS4231 (Windows Sound System) codec emulation.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* TheCollector1995, <mariogplayer@gmail.com>
* RichardG, <richardg867@gmail.com>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2018-2020 TheCollector1995.
* Copyright 2021 RichardG.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -13,292 +30,530 @@
#include <86box/sound.h>
#include <86box/snd_ad1848.h>
#define CS4231 0x80
static int ad1848_vols_6bits[64];
static double ad1848_vols_5bits_aux_gain[32];
#define CS4231 0x80
#define CS4236 0x03
void ad1848_setirq(ad1848_t *ad1848, int irq)
static int ad1848_vols_7bits[128];
static double ad1848_vols_5bits_aux_gain[32];
void
ad1848_setirq(ad1848_t *ad1848, int irq)
{
ad1848->irq = irq;
ad1848->irq = irq;
}
void ad1848_setdma(ad1848_t *ad1848, int dma)
void
ad1848_setdma(ad1848_t *ad1848, int dma)
{
ad1848->dma = dma;
ad1848->dma = dma;
}
uint8_t ad1848_read(uint16_t addr, void *p)
void
ad1848_updatevolmask(ad1848_t *ad1848)
{
ad1848_t *ad1848 = (ad1848_t *)p;
uint8_t temp = 0xff;
switch (addr & 3)
{
case 0: /*Index*/
temp = ad1848->index | ad1848->trd | ad1848->mce;
break;
case 1:
temp = ad1848->regs[ad1848->index];
if (ad1848->index == 0x0b) {
temp ^= 0x20;
ad1848->regs[ad1848->index] = temp;
if ((ad1848->type == AD1848_TYPE_CS4236) && ((ad1848->xregs[4] & 0x10) || ad1848->wten))
ad1848->wave_vol_mask = 0x3f;
else
ad1848->wave_vol_mask = 0x7f;
}
static void
ad1848_updatefreq(ad1848_t *ad1848)
{
double freq;
uint8_t set = 0;
if (ad1848->type == AD1848_TYPE_CS4236) {
if (ad1848->xregs[11] & 0x20) {
freq = 16934400LL;
switch (ad1848->xregs[13]) {
case 1: freq /= 353; break;
case 2: freq /= 529; break;
case 3: freq /= 617; break;
case 4: freq /= 1058; break;
case 5: freq /= 1764; break;
case 6: freq /= 2117; break;
case 7: freq /= 2558; break;
default: freq /= 16 * MAX(ad1848->xregs[13], 21); break;
}
break;
case 2:
temp = ad1848->status;
break;
}
return temp;
set = 1;
} else if (ad1848->regs[22] & 0x80) {
freq = (ad1848->regs[22] & 1) ? 33868800LL : 49152000LL;
set = (ad1848->regs[22] >> 1) & 0x3f;
switch (ad1848->regs[10] & 0x30) {
case 0x00: freq /= 128 * set; break;
case 0x10: freq /= 64 * set; break;
case 0x20: freq /= 256 * set; break;
}
set = 1;
}
}
if (!set) {
freq = (ad1848->regs[8] & 1) ? 16934400LL : 24576000LL;
switch ((ad1848->regs[8] >> 1) & 7) {
case 0: freq /= 3072; break;
case 1: freq /= 1536; break;
case 2: freq /= 896; break;
case 3: freq /= 768; break;
case 4: freq /= 448; break;
case 5: freq /= 384; break;
case 6: freq /= 512; break;
case 7: freq /= 2560; break;
}
}
ad1848->freq = freq;
ad1848->timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) ad1848->freq));
}
void ad1848_write(uint16_t addr, uint8_t val, void *p)
{
ad1848_t *ad1848 = (ad1848_t *)p;
double freq;
switch (addr & 3)
{
case 0: /*Index*/
if ((ad1848->regs[12] & 0x40) && (ad1848->type == AD1848_TYPE_CS4231))
ad1848->index = val & 0x1f; /* cs4231a extended mode enabled */
else
ad1848->index = val & 0x0f; /* ad1848/cs4248 mode TODO: some variants/clones DO NOT mirror, just ignore the writes? */
ad1848->trd = val & 0x20;
ad1848->mce = val & 0x40;
break;
case 1:
switch (ad1848->index)
{
case 8:
freq = (val & 1) ? 16934400LL : 24576000LL;
switch ((val >> 1) & 7)
{
case 0: freq /= 3072; break;
case 1: freq /= 1536; break;
case 2: freq /= 896; break;
case 3: freq /= 768; break;
case 4: freq /= 448; break;
case 5: freq /= 384; break;
case 6: freq /= 512; break;
case 7: freq /= 2560; break;
}
ad1848->freq = freq;
ad1848->timer_latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq));
break;
case 9:
if (!ad1848->enable && (val & 0x41) == 0x01) {
if (ad1848->timer_latch)
timer_set_delay_u64(&ad1848->timer_count, ad1848->timer_latch);
else
timer_set_delay_u64(&ad1848->timer_count, TIMER_USEC);
}
ad1848->enable = ((val & 0x41) == 0x01);
if (!ad1848->enable) {
timer_disable(&ad1848->timer_count);
ad1848->out_l = ad1848->out_r = 0;
}
break;
case 11:
break;
case 12:
if (ad1848->type != AD1848_TYPE_DEFAULT)
ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
return;
case 14:
ad1848->count = ad1848->regs[15] | (val << 8);
break;
case 24:
if (! (val & 0x70))
ad1848->status &= 0xfe;
uint8_t
ad1848_read(uint16_t addr, void *priv)
{
ad1848_t *ad1848 = (ad1848_t *) priv;
uint8_t ret = 0xff;
switch (addr & 3) {
case 0: /* Index */
ret = ad1848->index | ad1848->trd | ad1848->mce;
break;
case 1:
ret = ad1848->regs[ad1848->index];
switch (ad1848->index) {
case 11:
ret ^= 0x20;
ad1848->regs[ad1848->index] = ret;
break;
case 18: case 19:
if (ad1848->type == AD1848_TYPE_CS4236) {
if ((ad1848->xregs[4] & 0x14) == 0x14) /* FM remapping */
ret = ad1848->xregs[ad1848->index - 12]; /* real FM volume on registers 6 and 7 */
else if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) /* wavetable remapping */
ret = ad1848->xregs[ad1848->index - 2]; /* real wavetable volume on registers 16 and 17 */
}
break;
case 23:
if ((ad1848->type == AD1848_TYPE_CS4236) && (ad1848->regs[23] & 0x08)) {
if ((ad1848->xindex & 0xfe) == 0x00) /* remapped line volume */
ret = ad1848->regs[18 + ad1848->xindex];
else
ret = ad1848->xregs[ad1848->xindex];
}
break;
}
break;
case 2:
ret = ad1848->status;
break;
}
return ret;
}
void
ad1848_write(uint16_t addr, uint8_t val, void *priv)
{
ad1848_t *ad1848 = (ad1848_t *) priv;
uint8_t temp = 0, updatefreq = 0;
switch (addr & 3) {
case 0: /* Index */
if ((ad1848->regs[12] & 0x40) && (ad1848->type >= AD1848_TYPE_CS4231))
ad1848->index = val & 0x1f; /* cs4231a extended mode enabled */
else
ad1848->index = val & 0x0f; /* ad1848/cs4248 mode TODO: some variants/clones DO NOT mirror, just ignore the writes? */
if (ad1848->type == AD1848_TYPE_CS4236)
ad1848->regs[23] &= ~0x08; /* clear XRAE */
ad1848->trd = val & 0x20;
ad1848->mce = val & 0x40;
break;
case 1:
switch (ad1848->index) {
case 10:
if (ad1848->type != AD1848_TYPE_CS4236)
break;
/* fall-through */
case 8:
updatefreq = 1;
break;
case 9:
if (!ad1848->enable && (val & 0x41) == 0x01) {
if (ad1848->timer_latch)
timer_set_delay_u64(&ad1848->timer_count, ad1848->timer_latch);
else
timer_set_delay_u64(&ad1848->timer_count, TIMER_USEC);
}
ad1848->enable = ((val & 0x41) == 0x01);
if (!ad1848->enable) {
timer_disable(&ad1848->timer_count);
ad1848->out_l = ad1848->out_r = 0;
}
break;
case 11:
return;
case 12:
if (ad1848->type != AD1848_TYPE_DEFAULT)
ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
return;
case 14:
ad1848->count = ad1848->regs[15] | (val << 8);
break;
case 17:
if (ad1848->type >= AD1848_TYPE_CS4231) /* enable additional data formats on modes 2 and 3 */
ad1848->fmt_mask = (val & 0x40) ? 0xf0 : 0x70;
break;
case 18: case 19:
if (ad1848->type == AD1848_TYPE_CS4236) {
if ((ad1848->xregs[4] & 0x14) == 0x14) { /* FM remapping */
ad1848->xregs[ad1848->index - 12] = val; /* real FM volume on extended registers 6 and 7 */
temp = 1;
if (ad1848->index == 18) {
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f];
} else {
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f];
}
}
if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) { /* wavetable remapping */
ad1848->xregs[ad1848->index - 2] = val; /* real wavetable volume on extended registers 16 and 17 */
temp = 1;
}
/* Stop here if any remapping is enabled. */
if (temp)
return;
/* HACK: the Windows 9x driver's "Synth" control writes to this
register with no remapping, even if internal FM is enabled. */
if (ad1848->index == 18) {
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = (int) ad1848_vols_5bits_aux_gain[val & 0x1f];
} else {
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = (int) ad1848_vols_5bits_aux_gain[val & 0x1f];
}
}
break;
case 22:
updatefreq = 1;
break;
case 23:
if ((ad1848->type == AD1848_TYPE_CS4236) && ((ad1848->regs[12] & 0x60) == 0x60)) {
if (!(ad1848->regs[23] & 0x08)) { /* existing (not new) XRAE is clear */
ad1848->xindex = ((val & 0x04) << 2) | (val >> 4);
break;
}
switch (ad1848->xindex) {
case 0: case 1: /* remapped line volume */
ad1848->regs[18 + ad1848->xindex] = val;
return;
case 6:
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f];
break;
case 7:
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f];
break;
case 11: case 13:
updatefreq = 1;
break;
case 25:
return;
}
ad1848->xregs[ad1848->xindex] = val;
if (updatefreq)
ad1848_updatefreq(ad1848);
return;
}
break;
case 24:
val = ad1848->regs[24] & ((val & 0x70) | 0x0f);
if (!(val & 0x70)) {
ad1848->status &= 0xfe;
picintc(1 << ad1848->irq);
}
break;
case 25:
return;
}
ad1848->regs[ad1848->index] = val;
if (updatefreq)
ad1848_updatefreq(ad1848);
if ((ad1848->type == AD1848_TYPE_CS4231) || (ad1848->type == AD1848_TYPE_CS4236)) { /* TODO: configure CD volume for CS4248/AD1848 too */
temp = (ad1848->type == AD1848_TYPE_CS4231) ? 18 : 4;
if (ad1848->regs[temp] & 0x80)
ad1848->cd_vol_l = 0;
else
ad1848->cd_vol_l = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f];
temp++;
if (ad1848->regs[temp] & 0x80)
ad1848->cd_vol_r = 0;
else
ad1848->cd_vol_r = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f];
}
break;
case 2:
ad1848->status &= 0xfe;
ad1848->regs[24] &= 0x0f;
break;
}
}
void
ad1848_speed_changed(ad1848_t *ad1848)
{
ad1848->timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) ad1848->freq));
}
void
ad1848_update(ad1848_t *ad1848)
{
for (; ad1848->pos < sound_pos_global; ad1848->pos++) {
ad1848->buffer[ad1848->pos*2] = ad1848->out_l;
ad1848->buffer[ad1848->pos*2 + 1] = ad1848->out_r;
}
}
static void
ad1848_poll(void *priv)
{
ad1848_t *ad1848 = (ad1848_t *) priv;
if (ad1848->timer_latch)
timer_advance_u64(&ad1848->timer_count, ad1848->timer_latch);
else
timer_advance_u64(&ad1848->timer_count, TIMER_USEC * 1000);
ad1848_update(ad1848);
if (ad1848->enable) {
int32_t temp;
switch (ad1848->regs[8] & ad1848->fmt_mask) {
case 0x00: /* Mono, 8-bit PCM */
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
break;
case 25:
break;
}
ad1848->regs[ad1848->index] = val;
if (ad1848->type == AD1848_TYPE_CS4231) { /* TODO: configure CD volume for CS4248/AD1848 too */
if (ad1848->regs[0x12] & 0x80)
ad1848->cd_vol_l = 0;
else
ad1848->cd_vol_l = ad1848_vols_5bits_aux_gain[ad1848->regs[0x12] & 0x1f];
if (ad1848->regs[0x13] & 0x80)
ad1848->cd_vol_r = 0;
else
ad1848->cd_vol_r = ad1848_vols_5bits_aux_gain[ad1848->regs[0x13] & 0x1f];
}
break;
case 2:
ad1848->status &= 0xfe;
break;
}
}
void ad1848_speed_changed(ad1848_t *ad1848)
{
ad1848->timer_latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq));
}
void ad1848_update(ad1848_t *ad1848)
{
for (; ad1848->pos < sound_pos_global; ad1848->pos++)
{
ad1848->buffer[ad1848->pos*2] = ad1848->out_l;
ad1848->buffer[ad1848->pos*2 + 1] = ad1848->out_r;
}
}
static void ad1848_poll(void *p)
{
ad1848_t *ad1848 = (ad1848_t *)p;
if (ad1848->timer_latch)
timer_advance_u64(&ad1848->timer_count, ad1848->timer_latch);
else
timer_advance_u64(&ad1848->timer_count, TIMER_USEC * 1000);
ad1848_update(ad1848);
if (ad1848->enable)
{
int32_t temp;
switch (ad1848->regs[8] & 0x70)
{
case 0x00: /*Mono, 8-bit PCM*/
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
break;
case 0x10: /*Stereo, 8-bit PCM*/
ad1848->out_l = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
break;
case 0x40: /*Mono, 16-bit PCM*/
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
break;
case 0x50: /*Stereo, 16-bit PCM*/
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = (dma_channel_read(ad1848->dma) << 8) | temp;
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
break;
}
if (ad1848->regs[6] & 0x80)
ad1848->out_l = 0;
else
ad1848->out_l = (ad1848->out_l * ad1848_vols_6bits[ad1848->regs[6] & 0x3f]) >> 16;
if (ad1848->regs[7] & 0x80)
ad1848->out_r = 0;
else
ad1848->out_r = (ad1848->out_r * ad1848_vols_6bits[ad1848->regs[7] & 0x3f]) >> 16;
if (ad1848->count < 0)
{
ad1848->count = ad1848->regs[15] | (ad1848->regs[14] << 8);
if (!(ad1848->status & 0x01))
{
ad1848->status |= 0x01;
if (ad1848->regs[10] & 2)
picint(1 << ad1848->irq);
}
}
ad1848->count--;
}
else
{
ad1848->out_l = ad1848->out_r = 0;
ad1848->cd_vol_l = ad1848->cd_vol_r = 0;
}
}
static void ad1848_filter_cd_audio(int channel, double *buffer, void *p)
{
ad1848_t *ad1848 = (ad1848_t *)p;
double c;
double volume = channel ? ad1848->cd_vol_r : ad1848->cd_vol_l;
c = ((*buffer) * volume) / 65536.0;
*buffer = c;
}
void ad1848_init(ad1848_t *ad1848, int type)
{
int c;
double attenuation;
ad1848->status = 0xcc;
ad1848->index = ad1848->trd = 0;
ad1848->mce = 0x40;
ad1848->regs[0] = ad1848->regs[1] = 0;
ad1848->regs[2] = ad1848->regs[3] = 0x80; /* Line-in */
ad1848->regs[4] = ad1848->regs[5] = 0x80;
ad1848->regs[6] = ad1848->regs[7] = 0x80; /* Left/right Output */
ad1848->regs[8] = 0;
ad1848->regs[9] = 0x08;
ad1848->regs[10] = ad1848->regs[11] = 0;
if ((type == AD1848_TYPE_CS4248) || (type == AD1848_TYPE_CS4231))
ad1848->regs[12] = 0x8a;
else
ad1848->regs[12] = 0xa;
ad1848->regs[13] = 0;
ad1848->regs[14] = ad1848->regs[15] = 0;
if (type == AD1848_TYPE_CS4231)
{
ad1848->regs[16] = ad1848->regs[17] = 0;
ad1848->regs[18] = ad1848->regs[19] = 0x88;
ad1848->regs[22] = 0x80;
ad1848->regs[24] = 0;
ad1848->regs[25] = CS4231;
ad1848->regs[26] = 0x80;
ad1848->regs[29] = 0x80;
}
case 0x10: /* Stereo, 8-bit PCM */
ad1848->out_l = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
break;
ad1848->out_l = 0;
ad1848->out_r = 0;
for (c = 0; c < 64; c++) {
attenuation = 0.0;
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
if (c & 0x04) attenuation -= 6.0;
if (c & 0x08) attenuation -= 12.0;
if (c & 0x10) attenuation -= 24.0;
if (c & 0x20) attenuation -= 48.0;
attenuation = pow(10, attenuation / 10);
ad1848_vols_6bits[c] = (int)(attenuation * 65536);
}
for (c = 0; c < 32; c++) {
attenuation = 12.0;
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
if (c & 0x04) attenuation -= 6.0;
if (c & 0x08) attenuation -= 12.0;
if (c & 0x10) attenuation -= 24.0;
case 0x40: /* Mono, 16-bit PCM little endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
break;
attenuation = pow(10, attenuation / 10);
case 0x50: /* Stereo, 16-bit PCM little endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = (dma_channel_read(ad1848->dma) << 8) | temp;
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
break;
ad1848_vols_5bits_aux_gain[c] = (attenuation * 65536);
}
ad1848->type = type;
timer_add(&ad1848->timer_count, ad1848_poll, ad1848, 0);
case 0xc0: /* Mono, 16-bit PCM big endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8);
break;
if (ad1848->type != AD1848_TYPE_DEFAULT && ad1848->type != AD1848_TYPE_CS4248)
sound_set_cd_audio_filter(ad1848_filter_cd_audio, ad1848);
case 0xd0: /* Stereo, 16-bit PCM big endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = dma_channel_read(ad1848->dma) | (temp << 8);
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8);
break;
}
if (ad1848->regs[6] & 0x80)
ad1848->out_l = 0;
else
ad1848->out_l = (ad1848->out_l * ad1848_vols_7bits[ad1848->regs[6] & ad1848->wave_vol_mask]) >> 16;
if (ad1848->regs[7] & 0x80)
ad1848->out_r = 0;
else
ad1848->out_r = (ad1848->out_r * ad1848_vols_7bits[ad1848->regs[7] & ad1848->wave_vol_mask]) >> 16;
if (ad1848->count < 0) {
ad1848->count = ad1848->regs[15] | (ad1848->regs[14] << 8);
if (!(ad1848->status & 0x01)) {
ad1848->status |= 0x01;
ad1848->regs[24] |= 0x10;
if (ad1848->regs[10] & 2)
picint(1 << ad1848->irq);
}
}
ad1848->count--;
} else {
ad1848->out_l = ad1848->out_r = 0;
ad1848->cd_vol_l = ad1848->cd_vol_r = 0;
}
}
void
ad1848_filter_cd_audio(int channel, double *buffer, void *priv)
{
ad1848_t *ad1848 = (ad1848_t *) priv;
double c;
double volume = channel ? ad1848->cd_vol_r : ad1848->cd_vol_l;
c = ((*buffer) * volume) / 65536.0;
*buffer = c;
}
void
ad1848_init(ad1848_t *ad1848, uint8_t type)
{
uint8_t c;
double attenuation;
ad1848->status = 0xcc;
ad1848->index = ad1848->trd = 0;
ad1848->mce = 0x40;
ad1848->wten = 0;
ad1848->regs[0] = ad1848->regs[1] = 0;
ad1848->regs[2] = ad1848->regs[3] = 0x80; /* Line-in */
ad1848->regs[4] = ad1848->regs[5] = 0x80;
ad1848->regs[6] = ad1848->regs[7] = 0x80; /* Left/right Output */
ad1848->regs[8] = 0;
ad1848->regs[9] = 0x08;
ad1848->regs[10] = ad1848->regs[11] = 0;
if ((type == AD1848_TYPE_CS4248) || (type == AD1848_TYPE_CS4231) || (type == AD1848_TYPE_CS4236))
ad1848->regs[12] = 0x8a;
else
ad1848->regs[12] = 0xa;
ad1848->regs[13] = 0;
ad1848->regs[14] = ad1848->regs[15] = 0;
if (type == AD1848_TYPE_CS4231) {
ad1848->regs[16] = ad1848->regs[17] = 0;
ad1848->regs[18] = ad1848->regs[19] = 0x88;
ad1848->regs[22] = 0x80;
ad1848->regs[24] = 0;
ad1848->regs[25] = CS4231;
ad1848->regs[26] = 0x80;
ad1848->regs[29] = 0x80;
} else if (type == AD1848_TYPE_CS4236) {
ad1848->regs[16] = ad1848->regs[17] = 0;
ad1848->regs[18] = ad1848->regs[19] = 0;
ad1848->regs[20] = ad1848->regs[21] = 0;
ad1848->regs[22] = ad1848->regs[23] = 0;
ad1848->regs[24] = 0;
ad1848->regs[25] = CS4236;
ad1848->regs[26] = 0xa0;
ad1848->regs[27] = ad1848->regs[29] = 0;
ad1848->regs[30] = ad1848->regs[31] = 0;
ad1848->xregs[0] = ad1848->xregs[1] = 0xe8;
ad1848->xregs[2] = ad1848->xregs[3] = 0xcf;
ad1848->xregs[4] = 0x84;
ad1848->xregs[5] = 0;
ad1848->xregs[6] = ad1848->xregs[7] = 0x80;
ad1848->xregs[8] = ad1848->xregs[9] = 0;
ad1848->xregs[10] = 0x3f;
ad1848->xregs[11] = 0xc0;
ad1848->xregs[14] = ad1848->xregs[15] = 0;
ad1848->xregs[16] = ad1848->xregs[17] = 0;
}
ad1848_updatefreq(ad1848);
ad1848->out_l = ad1848->out_r = 0;
ad1848->fm_vol_l = ad1848->fm_vol_r = 65536;
ad1848_updatevolmask(ad1848);
ad1848->fmt_mask = 0x70;
for (c = 0; c < 128; c++) {
attenuation = 0.0;
if (c & 0x40) {
if (c < 72) attenuation = (c - 72) * -1.5;
} else {
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
if (c & 0x04) attenuation -= 6.0;
if (c & 0x08) attenuation -= 12.0;
if (c & 0x10) attenuation -= 24.0;
if (c & 0x20) attenuation -= 48.0;
}
attenuation = pow(10, attenuation / 10);
ad1848_vols_7bits[c] = (int) (attenuation * 65536);
}
for (c = 0; c < 32; c++) {
attenuation = 12.0;
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
if (c & 0x04) attenuation -= 6.0;
if (c & 0x08) attenuation -= 12.0;
if (c & 0x10) attenuation -= 24.0;
attenuation = pow(10, attenuation / 10);
ad1848_vols_5bits_aux_gain[c] = (attenuation * 65536);
}
ad1848->type = type;
timer_add(&ad1848->timer_count, ad1848_poll, ad1848, 0);
if ((ad1848->type != AD1848_TYPE_DEFAULT) && (ad1848->type != AD1848_TYPE_CS4248))
sound_set_cd_audio_filter(ad1848_filter_cd_audio, ad1848);
}

View File

@@ -8,6 +8,7 @@
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/gameport.h>
#include <86box/io.h>
#include <86box/nmi.h>
#include <86box/mem.h>
@@ -1352,13 +1353,16 @@ static void *es1371_init(const device_t *info)
sound_add_handler(es1371_get_buffer, es1371);
sound_set_cd_audio_filter(es1371_filter_cd_audio, es1371);
/* Add our own always-present game port to override the standalone ISAPnP one. */
gameport_remap(gameport_add(&gameport_pnp_device), 0x200);
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();
/* Return a CS4297A like VMWare does. */
/* Return a CS4297A like VMware does. */
es1371->codec_regs[0x7c] = 0x4352;
es1371->codec_regs[0x7e] = 0x5910;

829
src/sound/snd_cs423x.c Normal file
View File

@@ -0,0 +1,829 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Crystal CS423x (SBPro/WSS compatible sound chips) emulation.
*
*
*
* Authors: RichardG, <richardg867@gmail.com>
*
* Copyright 2021 RichardG.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/pic.h>
#include <86box/dma.h>
#include <86box/device.h>
#include <86box/gameport.h>
#include <86box/i2c.h>
#include <86box/isapnp.h>
#include <86box/sound.h>
#include <86box/midi.h>
#include <86box/snd_ad1848.h>
#include <86box/snd_opl.h>
#include <86box/snd_sb.h>
enum {
CRYSTAL_CS4236B = 0xcb,
CRYSTAL_CS4237B = 0xc8,
CRYSTAL_CS4238B = 0xc9
};
enum {
CRYSTAL_SLAM_NONE = 0,
CRYSTAL_SLAM_INDEX = 1,
CRYSTAL_SLAM_BYTE1 = 2,
CRYSTAL_SLAM_BYTE2 = 3
};
static const uint8_t slam_init_key[32] = { 0x96, 0x35, 0x9A, 0xCD, 0xE6, 0xF3, 0x79, 0xBC,
0x5E, 0xAF, 0x57, 0x2B, 0x15, 0x8A, 0xC5, 0xE2,
0xF1, 0xF8, 0x7C, 0x3E, 0x9F, 0x4F, 0x27, 0x13,
0x09, 0x84, 0x42, 0xA1, 0xD0, 0x68, 0x34, 0x1A };
static const uint8_t cs4236b_eeprom[] = {
/* Chip configuration */
0x55, 0xbb, /* magic */
0x00, 0x00, /* length */
0x00, 0x03, /* CD-ROM and modem decode */
0x80, /* misc. config */
0x80, /* global config */
0x0b, /* chip ID */
0x20, 0x04, 0x08, 0x10, 0x80, 0x00, 0x00, /* reserved */
0x00, /* external decode length */
0x48, /* reserved */
0x75, 0xb9, 0xfc, /* IRQ routing */
0x10, 0x03, /* DMA routing */
/* PnP resources */
0x0e, 0x63, 0x42, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, /* CSC4236, dummy checksum (filled in by isapnp_add_card) */
0x0a, 0x10, 0x01, /* PnP version 1.0, vendor version 0.1 */
0x82, 0x0e, 0x00, 'C', 'r', 'y', 's', 't', 'a', 'l', ' ', 'C', 'o', 'd', 'e' ,'c', 0x00, /* ANSI identifier */
0x15, 0x0e, 0x63, 0x00, 0x00, 0x00, /* logical device CSC0000 */
0x82, 0x07, 0x00, 'W', 'S', 'S', '/', 'S', 'B', 0x00, /* ANSI identifier */
0x31, 0x00, /* start dependent functions, preferred */
0x2a, 0x02, 0x28, /* DMA 1, type A, no count by word, count by byte, not bus master, 8-bit only */
0x2a, 0x09, 0x28, /* DMA 0/3, type A, no count by word, count by byte, not bus master, 8-bit only */
0x22, 0x20, 0x00, /* IRQ 5 */
0x47, 0x01, 0x34, 0x05, 0x34, 0x05, 0x04, 0x04, /* I/O 0x534, decodes 16-bit, 4-byte alignment, 4 addresses */
0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x08, 0x04, /* I/O 0x388, decodes 16-bit, 8-byte alignment, 4 addresses */
0x47, 0x01, 0x20, 0x02, 0x20, 0x02, 0x20, 0x10, /* I/O 0x220, decodes 16-bit, 32-byte alignment, 16 addresses */
0x31, 0x01, /* start dependent functions, acceptable */
0x2a, 0x0a, 0x28, /* DMA 1/3, type A, no count by word, count by byte, not bus master, 8-bit only */
0x2a, 0x0b, 0x28, /* DMA 0/1/3, type A, no count by word, count by byte, not bus master, 8-bit only */
0x22, 0xa0, 0x9a, /* IRQ 5/7/9/11/12/15 */
0x47, 0x01, 0x34, 0x05, 0xfc, 0x0f, 0x04, 0x04, /* I/O 0x534-0xFFC, decodes 16-bit, 4-byte alignment, 4 addresses */
0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x08, 0x04, /* I/O 0x388, decodes 16-bit, 8-byte alignment, 4 addresses */
0x47, 0x01, 0x20, 0x02, 0x60, 0x02, 0x20, 0x10, /* I/O 0x220-0x260, decodes 16-bit, 32-byte alignment, 16 addresses */
0x31, 0x02, /* start dependent functions, sub-optimal */
0x2a, 0x0b, 0x28, /* DMA 0/1/3, type A, no count by word, count by byte, not bus master, 8-bit only */
0x22, 0xa0, 0x9a, /* IRQ 5/7/9/11/12/15 */
0x47, 0x01, 0x34, 0x05, 0xfc, 0x0f, 0x04, 0x04, /* I/O 0x534-0xFFC, decodes 16-bit, 4-byte alignment, 4 addresses */
0x47, 0x01, 0x88, 0x03, 0xf8, 0x03, 0x08, 0x04, /* I/O 0x388-0x3F8, decodes 16-bit, 8-byte alignment, 4 addresses */
0x47, 0x01, 0x20, 0x02, 0x00, 0x03, 0x20, 0x10, /* I/O 0x220-0x300, decodes 16-bit, 32-byte alignment, 16 addresses */
0x38, /* end dependent functions */
0x15, 0x0e, 0x63, 0x00, 0x01, 0x00, /* logical device CSC0001 */
0x82, 0x05, 0x00, 'G', 'A', 'M', 'E', 0x00, /* ANSI identifier */
0x31, 0x00, /* start dependent functions, preferred */
0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x08, 0x08, /* I/O 0x200, decodes 16-bit, 8-byte alignment, 8 addresses */
0x31, 0x01, /* start dependent functions, acceptable */
0x47, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x08, /* I/O 0x208, decodes 16-bit, 8-byte alignment, 8 addresses */
0x38, /* end dependent functions */
0x15, 0x0e, 0x63, 0x00, 0x10, 0x00, /* logical device CSC0010 */
0x82, 0x05, 0x00, 'C', 'T', 'R', 'L', 0x00, /* ANSI identifier */
0x47, 0x01, 0x20, 0x01, 0xf8, 0x0f, 0x08, 0x08, /* I/O 0x120-0xFF8, decodes 16-bit, 8-byte alignment, 8 addresses */
0x15, 0x0e, 0x63, 0x00, 0x03, 0x00, /* logical device CSC0003 */
0x82, 0x04, 0x00, 'M', 'P', 'U', 0x00, /* ANSI identifier */
0x31, 0x00, /* start dependent functions, preferred */
0x22, 0x00, 0x02, /* IRQ 9 */
0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x08, 0x02, /* I/O 0x330, decodes 16-bit, 8-byte alignment, 2 addresses */
0x31, 0x01, /* start dependent functions, acceptable */
0x22, 0x00, 0x9a, /* IRQ 9/11/12/15 */
0x47, 0x01, 0x30, 0x03, 0x60, 0x03, 0x08, 0x02, /* I/O 0x330-0x360, decodes 16-bit, 8-byte alignment, 2 addresses */
0x31, 0x02, /* start dependent functions, sub-optimal */
0x47, 0x01, 0x30, 0x03, 0xe0, 0x03, 0x08, 0x02, /* I/O 0x330-0x3E0, decodes 16-bit, 8-byte alignment, 2 addresses */
0x38, /* end dependent functions */
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
};
typedef struct cs423x_t
{
void *pnp_card;
ad1848_t ad1848;
sb_t *sb;
void *gameport;
void *i2c, *eeprom;
uint16_t wss_base, opl_base, sb_base, ctrl_base, ram_addr, eeprom_size: 11;
uint8_t type, ad1848_type, pnp_offset, regs[8], indirect_regs[16],
eeprom_data[2048], ram_data[384], ram_dl: 2, opl_wss: 1;
uint8_t pnp_enable: 1, key_pos: 5, slam_enable: 1, slam_state: 2, slam_ld, slam_reg;
isapnp_device_config_t *slam_config;
} cs423x_t;
static void cs423x_slam_enable(cs423x_t *dev, uint8_t enable);
static void cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig);
static void cs423x_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv);
static uint8_t
cs423x_read(uint16_t addr, void *priv)
{
cs423x_t *dev = (cs423x_t *) priv;
uint8_t reg = addr & 7;
uint8_t ret = dev->regs[reg];
switch (reg) {
case 1: /* EEPROM Interface */
ret &= ~0x04;
if ((dev->regs[1] & 0x04) && i2c_gpio_get_sda(dev->i2c))
ret |= 0x04;
break;
case 4: /* Control Indirect Data Register */
ret = dev->indirect_regs[dev->regs[3]];
break;
case 5: /* Control/RAM Access */
/* Reading RAM is undocumented; the WDM driver does so. */
if (dev->ram_dl == 3) {
if ((dev->ram_addr >= 0x4000) && (dev->ram_addr < 0x4180)) /* chip configuration and PnP resources */
ret = dev->ram_data[dev->ram_addr & 0x01ff];
else
ret = 0xff;
dev->ram_addr++;
}
break;
case 7: /* Global Status */
/* Context switching: take active context and interrupt flag, then clear interrupt flag. */
ret &= 0xc0;
dev->regs[7] &= 0x80;
if (dev->sb->mpu->state.irq_pending) /* MPU interrupt */
ret |= 0x08;
if (dev->ad1848.status & 0x01) /* WSS interrupt */
ret |= 0x10;
if (dev->sb->dsp.sb_irq8 || dev->sb->dsp.sb_irq16 || dev->sb->dsp.sb_irq401) /* SBPro interrupt */
ret |= 0x20;
break;
}
return ret;
}
static void
cs423x_write(uint16_t addr, uint8_t val, void *priv)
{
cs423x_t *dev = (cs423x_t *) priv;
uint8_t reg = addr & 0x07;
switch (reg) {
case 1: /* EEPROM Interface */
if (val & 0x04)
i2c_gpio_set(dev->i2c, val & 0x01, val & 0x02);
break;
case 3: /* Control Indirect Access Register */
val &= 0x0f;
break;
case 4: /* Control Indirect Data Register */
switch (dev->regs[3] & 0x0f) {
case 0: /* WSS Master Control */
if (val & 0x80)
ad1848_init(&dev->ad1848, dev->ad1848_type);
val = 0x00;
break;
case 1: /* Version / Chip ID */
case 7: /* Reserved */
case 9 ... 15: /* unspecified */
return;
case 2: /* 3D Space and {Center|Volume} */
case 6: /* Upper Channel Status */
if (dev->type < CRYSTAL_CS4237B)
return;
break;
case 3: /* 3D Enable */
if (dev->type < CRYSTAL_CS4237B)
return;
val &= 0xe0;
break;
case 4: /* Consumer Serial Port Enable */
if (dev->type < CRYSTAL_CS4237B)
return;
val &= 0xf0;
break;
case 5: /* Lower Channel Status */
if (dev->type < CRYSTAL_CS4237B)
return;
val &= 0xfe;
break;
case 8: /* CS9236 Wavetable Control */
val &= 0x0f;
cs423x_pnp_enable(dev, 0, 0);
/* Update WTEN state on the WSS codec. */
dev->ad1848.wten = !!(val & 0x08);
ad1848_updatevolmask(&dev->ad1848);
break;
}
dev->indirect_regs[dev->regs[3]] = val;
break;
case 5: /* Control/RAM Access */
switch (dev->ram_dl) {
case 0: /* commands */
switch (val) {
case 0x55: /* Disable PnP Key */
dev->pnp_enable = 0;
/* fall-through */
case 0x5a: /* Update Hardware Configuration Data */
cs423x_pnp_enable(dev, 0, 1);
break;
case 0x56: /* Disable Crystal Key */
cs423x_slam_enable(dev, 0);
break;
case 0x57: /* Jump to ROM */
break;
case 0xaa: /* Download RAM */
dev->ram_dl = 1;
break;
}
break;
case 1: /* low address byte */
dev->ram_addr = val;
dev->ram_dl++;
break;
case 2: /* high address byte */
dev->ram_addr |= (val << 8);
dev->ram_dl++;
break;
case 3: /* data */
if ((dev->ram_addr >= 0x4000) && (dev->ram_addr < 0x4180)) /* chip configuration and PnP resources */
dev->ram_data[dev->ram_addr & 0x01ff] = val;
dev->ram_addr++;
break;
}
break;
case 6: /* RAM Access End */
if (!val) {
dev->ram_dl = 0;
/* Update PnP state and resource data. */
cs423x_pnp_enable(dev, 1, 0);
}
break;
case 7: /* Global Status */
return;
}
dev->regs[reg] = val;
}
static void
cs423x_slam_write(uint16_t addr, uint8_t val, void *priv)
{
cs423x_t *dev = (cs423x_t *) priv;
uint8_t idx;
switch (dev->slam_state) {
case CRYSTAL_SLAM_NONE:
/* Not in SLAM: read and compare Crystal key. */
if (val == slam_init_key[dev->key_pos]) {
dev->key_pos++;
/* Was the key successfully written? */
if (!dev->key_pos) {
/* Discard any pending logical device configuration, just to be safe. */
if (dev->slam_config) {
free(dev->slam_config);
dev->slam_config = NULL;
}
/* Enter SLAM. */
dev->slam_state = CRYSTAL_SLAM_INDEX;
}
} else {
dev->key_pos = 0;
}
break;
case CRYSTAL_SLAM_INDEX:
/* Write register index. */
dev->slam_reg = val;
dev->slam_state = CRYSTAL_SLAM_BYTE1;
break;
case CRYSTAL_SLAM_BYTE1:
case CRYSTAL_SLAM_BYTE2:
/* Write register value: two bytes for I/O ports, single byte otherwise. */
switch (dev->slam_reg) {
case 0x06: /* Card Select Number */
isapnp_set_csn(dev->pnp_card, val);
break;
case 0x15: /* Logical Device ID */
/* Apply the previous logical device's configuration, and reuse its config structure. */
if (dev->slam_config)
cs423x_pnp_config_changed(dev->slam_ld, dev->slam_config, dev);
else
dev->slam_config = (isapnp_device_config_t *) malloc(sizeof(isapnp_device_config_t));
/* Start new logical device. */
memset(dev->slam_config, 0, sizeof(isapnp_device_config_t));
dev->slam_ld = val;
break;
case 0x47: /* I/O Port Base Address 0 */
case 0x48: /* I/O Port Base Address 1 */
case 0x42: /* I/O Port Base Address 2 */
idx = (dev->slam_reg == 0x42) ? 2 : (dev->slam_reg - 0x47);
if (dev->slam_state == CRYSTAL_SLAM_BYTE1) {
/* Set high byte, or ignore it if no logical device is selected. */
if (dev->slam_config)
dev->slam_config->io[idx].base = val << 8;
/* Prepare for the second (low byte) write. */
dev->slam_state = CRYSTAL_SLAM_BYTE2;
return;
} else if (dev->slam_config) {
/* Set low byte, or ignore it if no logical device is selected. */
dev->slam_config->io[idx].base |= val;
}
break;
case 0x22: /* Interrupt Select 0 */
case 0x27: /* Interrupt Select 1 */
/* Stop if no logical device is selected. */
if (!dev->slam_config)
break;
/* Set IRQ value. */
idx = (dev->slam_reg == 0x22) ? 0 : 1;
dev->slam_config->irq[idx].irq = val & 15;
break;
case 0x2a: /* DMA Select 0 */
case 0x25: /* DMA Select 1 */
/* Stop if no logical device is selected. */
if (!dev->slam_config)
break;
/* Set DMA value. */
idx = (dev->slam_reg == 0x2a) ? 0 : 1;
dev->slam_config->dma[idx].dma = val & 7;
break;
case 0x33: /* Activate Device */
/* Stop if no logical device is selected. */
if (!dev->slam_config)
break;
/* Activate or deactivate the device. */
dev->slam_config->activate = val & 0x01;
break;
case 0x79: /* activate chip */
/* Apply the last logical device's configuration. */
if (dev->slam_config) {
cs423x_pnp_config_changed(dev->slam_ld, dev->slam_config, dev);
free(dev->slam_config);
dev->slam_config = NULL;
}
/* Exit out of SLAM. */
dev->slam_state = CRYSTAL_SLAM_NONE;
break;
}
/* Prepare for the next register, unless a two-byte read returns above. */
dev->slam_state = CRYSTAL_SLAM_INDEX;
break;
}
}
static void
cs423x_slam_enable(cs423x_t *dev, uint8_t enable)
{
/* Disable SLAM. */
if (dev->slam_enable) {
dev->slam_state = CRYSTAL_SLAM_NONE;
dev->slam_enable = 0;
io_removehandler(0x279, 1, NULL, NULL, NULL, cs423x_slam_write, NULL, NULL, dev);
}
/* Enable SLAM if the CKD bit is not set. */
if (enable && !(dev->ram_data[2] & 0x10)) {
dev->slam_enable = 1;
io_sethandler(0x279, 1, NULL, NULL, NULL, cs423x_slam_write, NULL, NULL, dev);
}
}
static void
cs423x_ctxswitch_write(uint16_t addr, uint8_t val, void *priv)
{
cs423x_t *dev = (cs423x_t *) priv;
uint8_t ctx = (dev->regs[7] & 0x80),
enable_opl = (dev->ad1848.xregs[4] & 0x10) && !(dev->indirect_regs[2] & 0x85);
/* Check if a context switch (WSS=1 <-> SBPro=0) occurred through the address being written. */
if ((dev->regs[7] & 0x80) ? ((addr & 0xfff0) == dev->sb_base) : ((addr & 0xfffc) == dev->wss_base)) {
/* Flip context bit. */
dev->regs[7] ^= 0x80;
ctx ^= 0x80;
/* Update CD audio filter.
FIXME: not thread-safe: filter function TOCTTOU in sound_cd_thread! */
sound_set_cd_audio_filter(NULL, NULL);
if (ctx) /* WSS */
sound_set_cd_audio_filter(ad1848_filter_cd_audio, &dev->ad1848);
else /* SBPro */
sound_set_cd_audio_filter(sbpro_filter_cd_audio, dev->sb);
/* Fire a context switch interrupt if enabled. */
if ((dev->regs[0] & 0x20) && (dev->ad1848.irq > 0)) {
dev->regs[7] |= 0x40; /* set interrupt flag */
picint(1 << dev->ad1848.irq); /* control device shares IRQ with WSS and SBPro */
}
}
/* Update OPL ownership and state regardless of context switch,
to trap writes to other registers which may disable the OPL. */
dev->sb->opl_enabled = !ctx && enable_opl;
dev->opl_wss = ctx && enable_opl;
}
static void
cs423x_get_buffer(int32_t *buffer, int len, void *priv)
{
cs423x_t *dev = (cs423x_t *) priv;
int c, opl_wss = dev->opl_wss;
/* Output audio from the WSS codec, and also the OPL if we're in charge of it. */
ad1848_update(&dev->ad1848);
if (opl_wss)
opl3_update(&dev->sb->opl);
/* Don't output anything if the analog section is powered down. */
if (!(dev->indirect_regs[2] & 0xa4)) {
for (c = 0; c < len * 2; c += 2) {
if (opl_wss) {
buffer[c] += (dev->sb->opl.buffer[c] * dev->ad1848.fm_vol_l) >> 16;
buffer[c + 1] += (dev->sb->opl.buffer[c + 1] * dev->ad1848.fm_vol_r) >> 16;
}
buffer[c] += dev->ad1848.buffer[c] / 2;
buffer[c + 1] += dev->ad1848.buffer[c + 1] / 2;
}
}
dev->ad1848.pos = 0;
if (opl_wss)
dev->sb->opl.pos = 0;
}
static void
cs423x_pnp_enable(cs423x_t *dev, uint8_t update_rom, uint8_t update_hwconfig)
{
uint8_t enable = ISAPNP_CARD_ENABLE;
if (dev->pnp_card) {
/* Hide PnP card if the PKD bit is set, or if PnP was disabled by command 0x55. */
if ((dev->ram_data[2] & 0x20) || !dev->pnp_enable)
enable = ISAPNP_CARD_DISABLE;
/* Update PnP resource data if requested. */
if (update_rom)
isapnp_update_card_rom(dev->pnp_card, &dev->ram_data[dev->pnp_offset], sizeof(dev->ram_data) - dev->pnp_offset);
/* Update PnP state. */
isapnp_enable_card(dev->pnp_card, enable);
}
/* Update some register bits based on the config data in RAM if requested. */
if (update_hwconfig) {
/* Update WTEN. */
if (dev->ram_data[3] & 0x08) {
dev->indirect_regs[8] |= 0x08;
dev->ad1848.wten = 1;
} else {
dev->indirect_regs[8] &= ~0x08;
dev->ad1848.wten = 0;
}
/* Update SPS. */
if (dev->ram_data[3] & 0x04)
dev->indirect_regs[8] |= 0x04;
else
dev->indirect_regs[8] &= ~0x04;
/* Update IFM. */
if (dev->ram_data[3] & 0x80)
dev->ad1848.xregs[4] |= 0x10;
else
dev->ad1848.xregs[4] &= ~0x10;
/* Inform WSS codec of the changes. */
ad1848_updatevolmask(&dev->ad1848);
}
}
static void
cs423x_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
{
cs423x_t *dev = (cs423x_t *) priv;
switch (ld) {
case 0: /* WSS, OPL3 and SBPro */
if (dev->wss_base) {
io_removehandler(dev->wss_base, 4, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &dev->ad1848);
io_removehandler(dev->wss_base, 4, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev);
dev->wss_base = 0;
}
if (dev->opl_base) {
io_removehandler(dev->opl_base, 4, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl);
dev->opl_base = 0;
}
if (dev->sb_base) {
sb_dsp_setaddr(&dev->sb->dsp, 0);
io_removehandler(dev->sb_base, 4, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl);
io_removehandler(dev->sb_base + 8, 2, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl);
io_removehandler(dev->sb_base + 4, 2, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, dev->sb);
io_removehandler(dev->sb_base, 16, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev);
dev->sb_base = 0;
}
ad1848_setirq(&dev->ad1848, 0);
sb_dsp_setirq(&dev->sb->dsp, 0);
ad1848_setdma(&dev->ad1848, 0);
sb_dsp_setdma8(&dev->sb->dsp, 0);
if (config->activate) {
if (config->io[0].base != ISAPNP_IO_DISABLED) {
dev->wss_base = config->io[0].base;
io_sethandler(dev->wss_base, 4, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &dev->ad1848);
io_sethandler(dev->wss_base, 4, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev);
}
if (config->io[1].base != ISAPNP_IO_DISABLED) {
dev->opl_base = config->io[1].base;
io_sethandler(dev->opl_base, 4, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl);
}
if (config->io[2].base != ISAPNP_IO_DISABLED) {
dev->sb_base = config->io[2].base;
sb_dsp_setaddr(&dev->sb->dsp, dev->sb_base);
io_sethandler(dev->sb_base, 4, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl);
io_sethandler(dev->sb_base + 8, 2, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &dev->sb->opl);
io_sethandler(dev->sb_base + 4, 2, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, dev->sb);
io_sethandler(dev->sb_base, 16, NULL, NULL, NULL, cs423x_ctxswitch_write, NULL, NULL, dev);
}
if (config->irq[0].irq != ISAPNP_IRQ_DISABLED) {
ad1848_setirq(&dev->ad1848, config->irq[0].irq);
sb_dsp_setirq(&dev->sb->dsp, config->irq[0].irq);
}
if (config->dma[0].dma != ISAPNP_DMA_DISABLED) {
ad1848_setdma(&dev->ad1848, config->dma[0].dma);
sb_dsp_setdma8(&dev->sb->dsp, config->dma[0].dma);
}
}
break;
case 1: /* Game Port */
if (dev->gameport)
gameport_remap(dev->gameport, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0);
break;
case 2: /* Control Registers */
if (dev->ctrl_base) {
io_removehandler(dev->ctrl_base, 8, cs423x_read, NULL, NULL, cs423x_write, NULL, NULL, dev);
dev->ctrl_base = 0;
}
if (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) {
dev->ctrl_base = config->io[0].base;
io_sethandler(dev->ctrl_base, 8, cs423x_read, NULL, NULL, cs423x_write, NULL, NULL, dev);
}
break;
case 3: /* MPU-401 */
mpu401_change_addr(dev->sb->mpu, 0);
mpu401_setirq(dev->sb->mpu, 0);
if (config->activate) {
if (config->io[0].base != ISAPNP_IO_DISABLED)
mpu401_change_addr(dev->sb->mpu, config->io[0].base);
if (config->irq[0].irq != ISAPNP_IRQ_DISABLED)
mpu401_setirq(dev->sb->mpu, config->irq[0].irq);
}
break;
}
}
static void
cs423x_reset(void *priv)
{
cs423x_t *dev = (cs423x_t *) priv;
/* Load EEPROM data to RAM, or just clear RAM if there's no EEPROM. */
if (dev->eeprom)
memcpy(dev->ram_data, &dev->eeprom_data[4], MIN(sizeof(dev->ram_data), sizeof(dev->eeprom_data) - 4));
else
memset(dev->ram_data, 0, sizeof(dev->ram_data));
/* Reset registers. */
memset(dev->indirect_regs, 0, sizeof(dev->indirect_regs));
dev->indirect_regs[1] = dev->type;
if (dev->type == CRYSTAL_CS4238B)
dev->indirect_regs[2] = 0x20;
/* Reset WSS codec. */
ad1848_init(&dev->ad1848, dev->ad1848_type);
/* Reset PnP resource data, state and logical devices. */
dev->pnp_enable = 1;
cs423x_pnp_enable(dev, 1, 1);
if (dev->pnp_card)
isapnp_reset_card(dev->pnp_card);
/* Reset SLAM. */
cs423x_slam_enable(dev, 1);
}
static void *
cs423x_init(const device_t *info)
{
cs423x_t *dev = malloc(sizeof(cs423x_t));
memset(dev, 0, sizeof(cs423x_t));
/* Initialize model-specific data. */
dev->type = info->local;
switch (dev->type) {
case CRYSTAL_CS4236B:
case CRYSTAL_CS4237B:
case CRYSTAL_CS4238B:
/* Same WSS codec and EEPROM structure. */
dev->ad1848_type = AD1848_TYPE_CS4236;
dev->pnp_offset = 19;
/* Different Chip Version and ID registers, which shouldn't be reset by ad1848_init */
dev->ad1848.xregs[25] = dev->type;
/* Load EEPROM contents from template. */
memcpy(dev->eeprom_data, cs4236b_eeprom, sizeof(cs4236b_eeprom));
/* Set content size. */
dev->eeprom_data[2] = sizeof(cs4236b_eeprom) >> 8;
dev->eeprom_data[3] = sizeof(cs4236b_eeprom) & 0xff;
/* Set PnP card ID. */
switch (dev->type) {
case CRYSTAL_CS4237B:
dev->eeprom_data[26] = 0x37;
break;
case CRYSTAL_CS4238B:
dev->eeprom_data[26] = 0x38;
break;
}
/* Initialize game port. The '7B and '8B game port only responds to 6 I/O ports; the remaining
2 ports are reserved on those chips, and probably connected to the Digital Assist feature. */
dev->gameport = gameport_add((dev->type == CRYSTAL_CS4236B) ? &gameport_pnp_device : &gameport_pnp_6io_device);
break;
}
/* Initialize I2C bus for the EEPROM. */
dev->i2c = i2c_gpio_init("nvr_cs423x");
/* Initialize I2C EEPROM if the contents are valid. */
if ((dev->eeprom_data[0] == 0x55) && (dev->eeprom_data[1] == 0xbb))
dev->eeprom = i2c_eeprom_init(i2c_gpio_get_bus(dev->i2c), 0x50, dev->eeprom_data, sizeof(dev->eeprom_data), 1);
/* Initialize ISAPnP. */
dev->pnp_card = isapnp_add_card(NULL, 0, cs423x_pnp_config_changed, NULL, NULL, NULL, dev);
/* Initialize SBPro codec first to get the correct CD audio filter for the default
context, which is SBPro. The WSS codec is initialized later by cs423x_reset */
dev->sb = (sb_t *) device_add(&sb_pro_cs423x_device);
/* Initialize RAM, registers and WSS codec. */
cs423x_reset(dev);
sound_add_handler(cs423x_get_buffer, dev);
return dev;
}
static void
cs423x_close(void *priv)
{
cs423x_t *dev = (cs423x_t *) priv;
if (dev->eeprom)
i2c_eeprom_close(dev->eeprom);
i2c_gpio_close(dev->i2c);
free(dev);
}
static void
cs423x_speed_changed(void *priv)
{
cs423x_t *dev = (cs423x_t *) priv;
ad1848_speed_changed(&dev->ad1848);
}
const device_t cs4236b_device =
{
"Crystal CS4236B",
DEVICE_ISA | DEVICE_AT,
CRYSTAL_CS4236B,
cs423x_init, cs423x_close, cs423x_reset,
{ NULL },
cs423x_speed_changed,
NULL,
NULL
};
const device_t cs4237b_device =
{
"Crystal CS4237B",
DEVICE_ISA | DEVICE_AT,
CRYSTAL_CS4237B,
cs423x_init, cs423x_close, cs423x_reset,
{ NULL },
cs423x_speed_changed,
NULL,
NULL
};
const device_t cs4238b_device =
{
"Crystal CS4238B",
DEVICE_ISA | DEVICE_AT,
CRYSTAL_CS4238B,
cs423x_init, cs423x_close, cs423x_reset,
{ NULL },
cs423x_speed_changed,
NULL,
NULL
};

View File

@@ -130,33 +130,66 @@ int gusfreqs[]=
double vol16bit[4096];
void pollgusirqs(gus_t *gus)
void gus_update_int_status(gus_t *gus)
{
int c;
int irq_pending = 0;
int midi_irq_pending = 0;
gus->irqstatus&=~0x60;
gus->irqstatus2=0xE0;
for (c=0;c<32;c++)
{
if (gus->waveirqs[c])
{
gus->irqstatus2=0x60|c;
if (gus->rampirqs[c]) gus->irqstatus2 |= 0x80;
if (gus->rampirqs[c])
gus->irqstatus2 |= 0x80;
gus->irqstatus|=0x20;
if (gus->irq != -1)
picint(1 << gus->irq);
return;
irq_pending = 1;
break;
}
if (gus->rampirqs[c])
{
gus->irqstatus2=0xA0|c;
gus->irqstatus|=0x40;
if (gus->irq != -1)
picint(1 << gus->irq);
return;
irq_pending = 1;
break;
}
}
if ((gus->tctrl & 4) && (gus->irqstatus & 0x04))
irq_pending = 1; /*Timer 1 interrupt pending*/
if ((gus->tctrl & 8) && (gus->irqstatus & 0x08))
irq_pending = 1; /*Timer 2 interrupt pending*/
if ((gus->irqstatus & 0x80) && (gus->dmactrl & 0x20))
irq_pending = 1; /*DMA TC interrupt pending*/
midi_irq_pending = gus->midi_status & MIDI_INT_MASTER;
if (gus->irq == gus->irq_midi && gus->irq != -1)
{
if (irq_pending || midi_irq_pending)
picintlevel(1 << gus->irq);
else
picintc(1 << gus->irq);
}
else
{
if (gus->irq != -1)
{
if (irq_pending)
picintlevel(1 << gus->irq);
else
picintc(1 << gus->irq);
}
if (gus->irq_midi != -1)
{
if (midi_irq_pending)
picintlevel(1 << gus->irq_midi);
else
picintc(1 << gus->irq_midi);
}
}
gus->irqstatus2=0xE0;
if (!gus->irqstatus && gus->irq != -1) picintc(1 << gus->irq);
}
void gus_midi_update_int_status(gus_t *gus)
@@ -178,10 +211,7 @@ void gus_midi_update_int_status(gus_t *gus)
else
gus->irqstatus &= ~GUS_INT_MIDI_RECEIVE;
if ((gus->midi_status & MIDI_INT_MASTER) && (gus->irq_midi != -1))
{
picint(1 << gus->irq_midi);
}
gus_update_int_status(gus);
}
void writegus(uint16_t addr, uint8_t val, void *p)
@@ -283,6 +313,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8);
break;
case 0x45: /*Timer control*/
gus->tctrl=val;
gus_update_int_status(gus);
break;
}
break;
@@ -295,7 +326,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8);
old = gus->waveirqs[gus->voice];
gus->waveirqs[gus->voice] = ((val & 0xa0) == 0xa0) ? 1 : 0;
if (gus->waveirqs[gus->voice] != old)
pollgusirqs(gus);
gus_update_int_status(gus);
break;
case 1: /*Frequency control*/
gus->freq[gus->voice]=(gus->freq[gus->voice]&0xFF)|(val<<8);
@@ -347,7 +378,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
gus->rctrl[gus->voice] = val & 0x7F;
gus->rampirqs[gus->voice] = ((val & 0xa0) == 0xa0) ? 1 : 0;
if (gus->rampirqs[gus->voice] != old)
pollgusirqs(gus);
gus_update_int_status(gus);
break;
case 0xE:
@@ -396,7 +427,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
break;
}
gus->dmactrl=val&~0x40;
if (val&0x20) gus->irqnext=1;
gus->irqnext=1;
}
else
{
@@ -427,7 +458,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
break;
}
gus->dmactrl=val&~0x40;
if (val&0x20) gus->irqnext=1;
gus->irqnext=1;
}
}
break;
@@ -457,6 +488,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
}
gus->tctrl=val;
gus->sb_ctrl = val;
gus_update_int_status(gus);
break;
case 0x46: /*Timer 1*/
gus->t1 = gus->t1l = val;
@@ -699,7 +731,7 @@ uint8_t readgus(uint16_t addr, void *p)
val=gus->irqstatus2;
gus->rampirqs[gus->irqstatus2&0x1F]=0;
gus->waveirqs[gus->irqstatus2&0x1F]=0;
pollgusirqs(gus);
gus_update_int_status(gus);
return val;
case 0x00: case 0x01: case 0x02: case 0x03:
@@ -739,7 +771,7 @@ uint8_t readgus(uint16_t addr, void *p)
val=gus->irqstatus2;
gus->rampirqs[gus->irqstatus2&0x1F]=0;
gus->waveirqs[gus->irqstatus2&0x1F]=0;
pollgusirqs(gus);
gus_update_int_status(gus);
return val;
case 0x41: /*DMA control*/
@@ -844,8 +876,6 @@ void gus_poll_timer_1(void *p)
gus->ad_status |= 0x40;
if (gus->tctrl&4)
{
if (gus->irq != -1)
picint(1 << gus->irq);
gus->ad_status |= 0x04;
gus->irqstatus |= 0x04;
}
@@ -855,11 +885,10 @@ void gus_poll_timer_1(void *p)
{
gus->irqnext=0;
gus->irqstatus|=0x80;
if (gus->irq != -1)
picint(1 << gus->irq);
}
gus_midi_update_int_status(gus);
gus_update_int_status(gus);
}
void gus_poll_timer_2(void *p)
@@ -876,8 +905,6 @@ void gus_poll_timer_2(void *p)
gus->ad_status |= 0x20;
if (gus->tctrl&8)
{
if (gus->irq != -1)
picint(1 << gus->irq);
gus->ad_status |= 0x02;
gus->irqstatus |= 0x08;
}
@@ -887,9 +914,8 @@ void gus_poll_timer_2(void *p)
{
gus->irqnext=0;
gus->irqstatus|=0x80;
if (gus->irq != -1)
picint(1 << gus->irq);
}
gus_update_int_status(gus);
}
static void gus_update(gus_t *gus)
@@ -1069,7 +1095,7 @@ void gus_poll_wave(void *p)
}
if (update_irqs)
pollgusirqs(gus);
gus_update_int_status(gus);
}
static void gus_get_buffer(int32_t *buffer, int len, void *p)

View File

@@ -31,6 +31,7 @@
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/gameport.h>
#include <86box/pic.h>
#include <86box/sound.h>
#include <86box/midi.h>
@@ -71,6 +72,9 @@ static const uint16_t sb_mcv_addr[8] = {0x200, 0x210, 0x220, 0x230, 0x240, 0x250
static const int sb_pro_mcv_irqs[4] = {7, 5, 3, 3};
/* Each card in the SB16 family has a million variants, and it shows in the large variety of device IDs for the PnP models.
These ROMs were reconstructed in a best-effort basis, around what Linux pnpdump configs and kernel logs could be found
in mailing lists, forums and other places, as well as Linux's own SB PnP card tables for ALSA and OSS. */
static uint8_t sb_16_pnp_rom[] = {
0x0e, 0x8c, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL0028, dummy checksum (filled in by isapnp_add_card) */
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
@@ -87,14 +91,19 @@ static uint8_t sb_16_pnp_rom[] = {
0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */
0x38, /* end dependent functions */
0x15, 0x0e, 0x8c, 0x70, 0x01, 0x00, /* logical device CTL7001 */
0x1c, 0x41, 0xd0, 0xb0, 0x2f, /* compatible device PNPB02F */
0x82, 0x04, 0x00, 'G', 'a', 'm', 'e', /* ANSI identifier */
0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x01, 0x08, /* I/O 0x200, decodes 16-bit, 1-byte alignment, 8 addresses */
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
};
static uint8_t sb_32_pnp_rom[] = {
0x0e, 0x8c, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL009C, dummy checksum (filled in by isapnp_add_card) */
0x0e, 0x8c, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL0048, dummy checksum (filled in by isapnp_add_card) */
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
0x82, 0x11, 0x00, 'C', 'r', 'e', 'a', 't', 'i', 'v', 'e', ' ', 'S', 'B', '3', '2', ' ', 'P', 'n', 'P', /* ANSI identifier */
0x16, 0x0e, 0x8c, 0x00, 0x41, 0x00, 0xa9, /* logical device CTL0041, supports vendor-specific registers 0x38/0x3A/0x3C/0x3F */
0x16, 0x0e, 0x8c, 0x00, 0x31, 0x00, 0xa9, /* logical device CTL0031, supports vendor-specific registers 0x38/0x3A/0x3C/0x3F */
0x82, 0x05, 0x00, 'A', 'u', 'd', 'i', 'o', /* ANSI identifier */
0x31, 0x00, /* start dependent functions, preferred */
0x22, 0x20, 0x00, /* IRQ 5 */
@@ -153,14 +162,19 @@ static uint8_t sb_32_pnp_rom[] = {
0x47, 0x01, 0x20, 0x06, 0x80, 0x06, 0x20, 0x04, /* I/O 0x620-0x680, decodes 16-bit, 32-byte alignment, 4 addresses */
0x38, /* end dependent functions */
0x15, 0x0e, 0x8c, 0x70, 0x01, 0x00, /* logical device CTL7001 */
0x1c, 0x41, 0xd0, 0xb0, 0x2f, /* compatible device PNPB02F */
0x82, 0x04, 0x00, 'G', 'a', 'm', 'e', /* ANSI identifier */
0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x01, 0x08, /* I/O 0x200, decodes 16-bit, 1-byte alignment, 8 addresses */
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
};
static uint8_t sb_awe32_pnp_rom[] = {
0x0e, 0x8c, 0x00, 0x9a, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL009A, dummy checksum (filled in by isapnp_add_card) */
0x0e, 0x8c, 0x00, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL0043, dummy checksum (filled in by isapnp_add_card) */
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
0x82, 0x15, 0x00, 'C', 'r', 'e', 'a', 't', 'i', 'v', 'e', ' ', 'S', 'B', ' ', 'A', 'W', 'E', '3', '2', ' ', 'P', 'n', 'P', /* ANSI identifier */
0x16, 0x0e, 0x8c, 0x00, 0x41, 0x00, 0xa9, /* logical device CTL0041, supports vendor-specific registers 0x38/0x3A/0x3C/0x3F */
0x16, 0x0e, 0x8c, 0x00, 0x31, 0x00, 0xa9, /* logical device CTL0031, supports vendor-specific registers 0x38/0x3A/0x3C/0x3F */
0x82, 0x05, 0x00, 'A', 'u', 'd', 'i', 'o', /* ANSI identifier */
0x31, 0x00, /* start dependent functions, preferred */
0x22, 0x20, 0x00, /* IRQ 5 */
@@ -223,6 +237,11 @@ static uint8_t sb_awe32_pnp_rom[] = {
0x47, 0x01, 0x20, 0x0e, 0x80, 0x0e, 0x20, 0x04, /* I/O 0xE20-0xE80, decodes 16-bit, 32-byte alignment, 4 addresses */
0x38, /* end dependent functions */
0x15, 0x0e, 0x8c, 0x70, 0x01, 0x00, /* logical device CTL7001 */
0x1c, 0x41, 0xd0, 0xb0, 0x2f, /* compatible device PNPB02F */
0x82, 0x04, 0x00, 'G', 'a', 'm', 'e', /* ANSI identifier */
0x47, 0x01, 0x00, 0x02, 0x00, 0x02, 0x01, 0x08, /* I/O 0x200, decodes 16-bit, 1-byte alignment, 8 addresses */
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
};
@@ -1188,69 +1207,75 @@ sb_pro_mcv_write(int port, uint8_t val, void *p)
static void
sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
{
if (ld != 0)
return;
sb_t *sb = (sb_t *) priv;
uint16_t addr = sb->dsp.sb_addr;
uint8_t val;
io_removehandler(addr, 0x0004, opl3_read, NULL, NULL,
opl3_write, NULL, NULL, &sb->opl);
io_removehandler(addr + 8, 0x0002, opl3_read, NULL, NULL,
opl3_write, NULL, NULL, &sb->opl);
io_removehandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL,
sb_ct1745_mixer_write, NULL, NULL, sb);
switch (ld) {
case 0: /* Audio */
io_removehandler(addr, 0x0004, opl3_read, NULL, NULL,
opl3_write, NULL, NULL, &sb->opl);
io_removehandler(addr + 8, 0x0002, opl3_read, NULL, NULL,
opl3_write, NULL, NULL, &sb->opl);
io_removehandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL,
sb_ct1745_mixer_write, NULL, NULL, sb);
addr = sb->opl_pnp_addr;
if (addr) {
sb->opl_pnp_addr = 0;
io_removehandler(addr, 0x0004, opl3_read, NULL, NULL,
opl3_write, NULL, NULL, &sb->opl);
}
addr = sb->opl_pnp_addr;
if (addr) {
sb->opl_pnp_addr = 0;
io_removehandler(addr, 0x0004, opl3_read, NULL, NULL,
opl3_write, NULL, NULL, &sb->opl);
}
sb_dsp_setaddr(&sb->dsp, 0);
sb_dsp_setirq(&sb->dsp, 0);
sb_dsp_setdma8(&sb->dsp, ISAPNP_DMA_DISABLED);
sb_dsp_setdma16(&sb->dsp, ISAPNP_DMA_DISABLED);
sb_dsp_setaddr(&sb->dsp, 0);
sb_dsp_setirq(&sb->dsp, 0);
sb_dsp_setdma8(&sb->dsp, ISAPNP_DMA_DISABLED);
sb_dsp_setdma16(&sb->dsp, ISAPNP_DMA_DISABLED);
mpu401_change_addr(sb->mpu, 0);
mpu401_change_addr(sb->mpu, 0);
if (config->activate) {
addr = config->io[0].base;
if (addr != ISAPNP_IO_DISABLED) {
io_sethandler(addr, 0x0004, opl3_read, NULL, NULL,
opl3_write, NULL, NULL, &sb->opl);
io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL,
opl3_write, NULL, NULL, &sb->opl);
io_sethandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL,
sb_ct1745_mixer_write, NULL, NULL, sb);
if (config->activate) {
addr = config->io[0].base;
if (addr != ISAPNP_IO_DISABLED) {
io_sethandler(addr, 0x0004, opl3_read, NULL, NULL,
opl3_write, NULL, NULL, &sb->opl);
io_sethandler(addr + 8, 0x0002, opl3_read, NULL, NULL,
opl3_write, NULL, NULL, &sb->opl);
io_sethandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL,
sb_ct1745_mixer_write, NULL, NULL, sb);
sb_dsp_setaddr(&sb->dsp, addr);
}
sb_dsp_setaddr(&sb->dsp, addr);
}
addr = config->io[1].base;
if (addr != ISAPNP_IO_DISABLED)
mpu401_change_addr(sb->mpu, addr);
addr = config->io[1].base;
if (addr != ISAPNP_IO_DISABLED)
mpu401_change_addr(sb->mpu, addr);
addr = config->io[2].base;
if (addr != ISAPNP_IO_DISABLED) {
sb->opl_pnp_addr = addr;
io_sethandler(addr, 0x0004, opl3_read, NULL, NULL,
opl3_write, NULL, NULL, &sb->opl);
}
addr = config->io[2].base;
if (addr != ISAPNP_IO_DISABLED) {
sb->opl_pnp_addr = addr;
io_sethandler(addr, 0x0004, opl3_read, NULL, NULL,
opl3_write, NULL, NULL, &sb->opl);
}
val = config->irq[0].irq;
if (val != ISAPNP_IRQ_DISABLED)
sb_dsp_setirq(&sb->dsp, val);
val = config->irq[0].irq;
if (val != ISAPNP_IRQ_DISABLED)
sb_dsp_setirq(&sb->dsp, val);
val = config->dma[0].dma;
if (val != ISAPNP_DMA_DISABLED)
sb_dsp_setdma8(&sb->dsp, val);
val = config->dma[0].dma;
if (val != ISAPNP_DMA_DISABLED)
sb_dsp_setdma8(&sb->dsp, val);
val = config->dma[1].dma;
if (val != ISAPNP_DMA_DISABLED)
sb_dsp_setdma16(&sb->dsp, val);
val = config->dma[1].dma;
if (val != ISAPNP_DMA_DISABLED)
sb_dsp_setdma16(&sb->dsp, val);
}
break;
case 1: /* Game */
gameport_remap(sb->gameport, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0);
break;
}
}
@@ -1259,21 +1284,18 @@ static void
sb_awe32_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
{
sb_t *sb = (sb_t *) priv;
uint16_t addr;
switch (ld) {
case 0:
case 0: /* Audio */
sb_16_pnp_config_changed(0, config, sb);
break;
case 1:
emu8k_change_addr(&sb->emu8k, 0);
case 1: /* WaveTable */
emu8k_change_addr(&sb->emu8k, (config->activate && (config->io[0].base != ISAPNP_IO_DISABLED)) ? config->io[0].base : 0);
break;
if (config->activate) {
addr = config->io[0].base;
if (addr != ISAPNP_IO_DISABLED)
emu8k_change_addr(&sb->emu8k, addr);
}
case 2: /* Game */
sb_16_pnp_config_changed(1, config, sb);
break;
}
}
@@ -1602,6 +1624,31 @@ sb_pro_mcv_init(const device_t *info)
}
static void *
sb_pro_cs423x_init(const device_t *info)
{
sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0, sizeof(sb_t));
sb->opl_enabled = 0; /* updated by cs423x code */
opl3_init(&sb->opl);
sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb);
sb_ct1345_mixer_reset(sb);
sb->mixer_enabled = 1;
sound_add_handler(sb_get_buffer_sbpro, sb);
sound_set_cd_audio_filter(sbpro_filter_cd_audio, sb);
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
mpu401_init(sb->mpu, 0, 0, M_UART, 1);
sb_dsp_set_mpu(&sb->dsp, sb->mpu);
return sb;
}
static void *
sb_16_init(const device_t *info)
{
@@ -1676,6 +1723,8 @@ sb_16_pnp_init(const device_t *info)
if (device_get_config_int("receive_input"))
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
sb->gameport = gameport_add(&gameport_pnp_device);
isapnp_add_card(sb_16_pnp_rom, sizeof(sb_16_pnp_rom), sb_16_pnp_config_changed, NULL, NULL, NULL, sb);
return sb;
@@ -1771,6 +1820,8 @@ sb_awe32_pnp_init(const device_t *info)
if (device_get_config_int("receive_input"))
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
sb->gameport = gameport_add(&gameport_pnp_device);
if (info->local == 1)
isapnp_add_card(sb_32_pnp_rom, sizeof(sb_32_pnp_rom), sb_awe32_pnp_config_changed, NULL, NULL, NULL, sb);
else
@@ -2483,6 +2534,17 @@ const device_t sb_pro_mcv_device =
NULL
};
const device_t sb_pro_cs423x_device =
{
"Crystal CS423x Sound Blaster Pro compatibility",
DEVICE_ISA | DEVICE_AT,
0,
sb_pro_cs423x_init, sb_close, NULL, { NULL },
sb_speed_changed,
NULL,
NULL
};
const device_t sb_16_device =
{
"Sound Blaster 16",

View File

@@ -34,217 +34,231 @@
#include <86box/snd_opl.h>
/*530, 11, 3 - 530=23*/
/*530, 11, 1 - 530=22*/
/*530, 11, 0 - 530=21*/
/*530, 10, 1 - 530=1a*/
/*530, 9, 1 - 530=12*/
/*530, 7, 1 - 530=0a*/
/*604, 11, 1 - 530=22*/
/*e80, 11, 1 - 530=22*/
/*f40, 11, 1 - 530=22*/
/* 530, 11, 3 - 530=23
* 530, 11, 1 - 530=22
* 530, 11, 0 - 530=21
* 530, 10, 1 - 530=1a
* 530, 9, 1 - 530=12
* 530, 7, 1 - 530=0a
* 604, 11, 1 - 530=22
* e80, 11, 1 - 530=22
* f40, 11, 1 - 530=22
*/
static int wss_dma[4] = {0, 0, 1, 3};
static int wss_irq[8] = {5, 7, 9, 10, 11, 12, 14, 15}; /*W95 only uses 7-9, others may be wrong*/
static const int wss_dma[4] = {0, 0, 1, 3};
static const int wss_irq[8] = {5, 7, 9, 10, 11, 12, 14, 15}; /* W95 only uses 7-9, others may be wrong */
typedef struct wss_t
{
uint8_t config;
ad1848_t ad1848;
opl_t opl;
typedef struct wss_t {
uint8_t config;
int opl_enabled;
uint8_t pos_regs[8];
ad1848_t ad1848;
opl_t opl;
int opl_enabled;
uint8_t pos_regs[8];
} wss_t;
uint8_t wss_read(uint16_t addr, void *p)
{
wss_t *wss = (wss_t *)p;
uint8_t temp;
temp = 4 | (wss->config & 0x40);
return temp;
uint8_t
wss_read(uint16_t addr, void *priv) {
wss_t *wss = (wss_t *) priv;
return 4 | (wss->config & 0x40);
}
void wss_write(uint16_t addr, uint8_t val, void *p)
{
wss_t *wss = (wss_t *)p;
wss->config = val;
ad1848_setdma(&wss->ad1848, wss_dma[val & 3]);
ad1848_setirq(&wss->ad1848, wss_irq[(val >> 3) & 7]);
void
wss_write(uint16_t addr, uint8_t val, void *priv)
{
wss_t *wss = (wss_t *) priv;
wss->config = val;
ad1848_setdma(&wss->ad1848, wss_dma[val & 3]);
ad1848_setirq(&wss->ad1848, wss_irq[(val >> 3) & 7]);
}
static void wss_get_buffer(int32_t *buffer, int len, void *p)
static void
wss_get_buffer(int32_t *buffer, int len, void *priv)
{
wss_t *wss = (wss_t *)p;
int c;
wss_t *wss = (wss_t *) priv;
int c;
opl3_update(&wss->opl);
ad1848_update(&wss->ad1848);
for (c = 0; c < len * 2; c++) {
buffer[c] += wss->opl.buffer[c];
buffer[c] += (wss->ad1848.buffer[c] / 2);
}
opl3_update(&wss->opl);
ad1848_update(&wss->ad1848);
for (c = 0; c < len * 2; c++) {
buffer[c] += wss->opl.buffer[c];
buffer[c] += wss->ad1848.buffer[c] / 2;
}
wss->opl.pos = 0;
wss->ad1848.pos = 0;
wss->opl.pos = 0;
wss->ad1848.pos = 0;
}
void *wss_init(const device_t *info)
void *
wss_init(const device_t *info)
{
wss_t *wss = malloc(sizeof(wss_t));
memset(wss, 0, sizeof(wss_t));
wss_t *wss = malloc(sizeof(wss_t));
memset(wss, 0, sizeof(wss_t));
uint16_t addr = device_get_config_hex16("base");
wss->opl_enabled = device_get_config_int("opl");
uint16_t addr = device_get_config_hex16("base");
wss->opl_enabled = device_get_config_int("opl");
if (wss->opl_enabled)
opl3_init(&wss->opl);
ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT);
if (wss->opl_enabled)
opl3_init(&wss->opl);
ad1848_setirq(&wss->ad1848, 7);
ad1848_setdma(&wss->ad1848, 3);
ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT);
if (wss->opl_enabled)
ad1848_setirq(&wss->ad1848, 7);
ad1848_setdma(&wss->ad1848, 3);
if (wss->opl_enabled)
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
io_sethandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss);
io_sethandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848);
sound_add_handler(wss_get_buffer, wss);
return wss;
}
static uint8_t
ncr_audio_mca_read(int port, void *priv)
{
wss_t *wss = (wss_t *) priv;
return wss->pos_regs[port & 7];
}
static void
ncr_audio_mca_write(int port, uint8_t val, void *priv)
{
wss_t *wss = (wss_t *) priv;
uint16_t ports[4] = {0x530, 0xE80, 0xF40, 0x604};
uint16_t addr;
if (port < 0x102)
return;
wss->opl_enabled = (wss->pos_regs[2] & 0x20) ? 1 : 0;
addr = ports[(wss->pos_regs[2] & 0x18) >> 3];
io_removehandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
io_removehandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss);
io_removehandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848);
wss->pos_regs[port & 7] = val;
if (wss->pos_regs[2] & 1) {
addr = ports[(wss->pos_regs[2] & 0x18) >> 3];
if (wss->opl_enabled)
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
io_sethandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss);
io_sethandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848);
sound_add_handler(wss_get_buffer, wss);
return wss;
}
}
static uint8_t ncr_audio_mca_read(int port, void *p)
static uint8_t
ncr_audio_mca_feedb(void *priv)
{
wss_t *wss = (wss_t *)p;
return wss->pos_regs[port & 7];
wss_t *wss = (wss_t *) priv;
return (wss->pos_regs[2] & 1);
}
static void ncr_audio_mca_write(int port, uint8_t val, void *p)
void *
ncr_audio_init(const device_t *info)
{
wss_t *wss = (wss_t *)p;
uint16_t ports[4] = {0x530, 0xE80, 0xF40, 0x604};
uint16_t addr;
wss_t *wss = malloc(sizeof(wss_t));
memset(wss, 0, sizeof(wss_t));
if (port < 0x102)
return;
opl3_init(&wss->opl);
ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT);
wss->opl_enabled = (wss->pos_regs[2] & 0x20) ? 1 : 0;
addr = ports[(wss->pos_regs[2] & 0x18) >> 3];
io_removehandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
io_removehandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss);
io_removehandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848);
ad1848_setirq(&wss->ad1848, 7);
ad1848_setdma(&wss->ad1848, 3);
wss->pos_regs[port & 7] = val;
mca_add(ncr_audio_mca_read, ncr_audio_mca_write, ncr_audio_mca_feedb, NULL, wss);
wss->pos_regs[0] = 0x16;
wss->pos_regs[1] = 0x51;
if (wss->pos_regs[2] & 1) {
addr = ports[(wss->pos_regs[2] & 0x18) >> 3];
sound_add_handler(wss_get_buffer, wss);
if (wss->opl_enabled)
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
io_sethandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss);
io_sethandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848);
}
return wss;
}
static uint8_t ncr_audio_mca_feedb(void *p)
{
wss_t *wss = (wss_t *)p;
return (wss->pos_regs[2] & 1);
void
wss_close(void *priv)
{
wss_t *wss = (wss_t *) priv;
free(wss);
}
void *ncr_audio_init(const device_t *info)
void
wss_speed_changed(void *priv)
{
wss_t *wss = malloc(sizeof(wss_t));
memset(wss, 0, sizeof(wss_t));
opl3_init(&wss->opl);
ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT);
ad1848_setirq(&wss->ad1848, 7);
ad1848_setdma(&wss->ad1848, 3);
mca_add(ncr_audio_mca_read, ncr_audio_mca_write, ncr_audio_mca_feedb, NULL, wss);
wss->pos_regs[0] = 0x16;
wss->pos_regs[1] = 0x51;
sound_add_handler(wss_get_buffer, wss);
return wss;
wss_t *wss = (wss_t *) priv;
ad1848_speed_changed(&wss->ad1848);
}
void wss_close(void *p)
{
wss_t *wss = (wss_t *)p;
free(wss);
}
void wss_speed_changed(void *p)
{
wss_t *wss = (wss_t *)p;
ad1848_speed_changed(&wss->ad1848);
}
static const device_config_t wss_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x530, "", { 0 },
{
{
"0x530", 0x530
},
{
"0x604", 0x604
},
{
"0xe80", 0xe80
},
{
"0xf40", 0xf40
},
{
""
}
}
},
static const device_config_t wss_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x530, "", { 0 },
{
"opl", "Enable OPL", CONFIG_BINARY, "", 1
},
{
"", "", -1
}
{
"0x530", 0x530
},
{
"0x604", 0x604
},
{
"0xe80", 0xe80
},
{
"0xf40", 0xf40
},
{
""
}
}
},
{
"opl", "Enable OPL", CONFIG_BINARY, "", 1
},
{
"", "", -1
}
};
const device_t wss_device =
{
"Windows Sound System",
DEVICE_ISA | DEVICE_AT, 0,
wss_init, wss_close, NULL,
{ NULL },
wss_speed_changed,
NULL,
wss_config
"Windows Sound System",
DEVICE_ISA | DEVICE_AT, 0,
wss_init, wss_close, NULL,
{ NULL },
wss_speed_changed,
NULL,
wss_config
};
const device_t ncr_business_audio_device =
{
"NCR Business Audio",
DEVICE_MCA, 0,
ncr_audio_init, wss_close, NULL,
{ NULL },
wss_speed_changed,
NULL,
NULL
"NCR Business Audio",
DEVICE_MCA, 0,
ncr_audio_init, wss_close, NULL,
{ NULL },
wss_speed_changed,
NULL,
NULL
};

View File

@@ -88,6 +88,7 @@ static const SOUND_CARD sound_cards[] =
{ "adlibgold", &adgold_device },
{ "azt2316a", &azt2316a_device },
{ "azt1605", &azt1605_device },
{ "cs4236b", &cs4236b_device },
{ "sb", &sb_1_device },
{ "sb1.5", &sb_15_device },
{ "sb2.0", &sb_2_device },

View File

@@ -901,6 +901,8 @@ gd54xx_out(uint16_t addr, uint8_t val, void *p)
svga->adv_flags |= FLAG_EXT_WRITE;
if (svga->gdcreg[0xb] & 0x08)
svga->adv_flags |= FLAG_LATCH8;
if (svga->gdcreg[0xb] & 0x10)
svga->adv_flags |= FLAG_ADDR_BY16;
gd54xx_recalc_banking(gd54xx);
break;
@@ -1994,8 +1996,7 @@ gd54xx_write_modes45(svga_t *svga, uint8_t val, uint32_t addr)
switch (svga->writemode) {
case 4:
if (svga->gdcreg[0xb] & 0x10) {
addr <<= 2;
if (svga->adv_flags & FLAG_ADDR_BY16) {
addr &= svga->decode_mask;
for (i = 0; i < 8; i++) {
@@ -2016,8 +2017,7 @@ gd54xx_write_modes45(svga_t *svga, uint8_t val, uint32_t addr)
break;
case 5:
if (svga->gdcreg[0xb] & 0x10) {
addr <<= 2;
if (svga->adv_flags & FLAG_ADDR_BY16) {
addr &= svga->decode_mask;
for (i = 0; i < 8; i++) {

View File

@@ -405,6 +405,7 @@ oti_init(const device_t *info)
oti_in, NULL, NULL, oti_out, NULL, NULL, oti);
oti->svga.miscout = 1;
oti->svga.packed_chain4 = 1;
return(oti);
}

View File

@@ -355,22 +355,31 @@ static void s3_pci_write(int func, int addr, uint8_t val, void *p);
/*Remap address for chain-4/doubleword style layout*/
static __inline uint32_t
dword_remap(uint32_t in_addr)
dword_remap(svga_t *svga, uint32_t in_addr)
{
if (svga->packed_chain4)
return in_addr;
return ((in_addr << 2) & 0x3fff0) |
((in_addr >> 14) & 0xc) |
(in_addr & ~0x3fffc);
}
static __inline uint32_t
dword_remap_w(uint32_t in_addr)
dword_remap_w(svga_t *svga, uint32_t in_addr)
{
if (svga->packed_chain4)
return in_addr;
return ((in_addr << 2) & 0x1fff8) |
((in_addr >> 14) & 0x6) |
(in_addr & ~0x1fffe);
}
static __inline uint32_t
dword_remap_l(uint32_t in_addr)
dword_remap_l(svga_t *svga, uint32_t in_addr)
{
if (svga->packed_chain4)
return in_addr;
return ((in_addr << 2) & 0xfffc) |
((in_addr >> 14) & 0x3) |
(in_addr & ~0xffff);
@@ -1657,7 +1666,7 @@ s3_hwcursor_draw(svga_t *svga, int displine)
for (x = 0; x < 64; x += 16)
{
uint32_t remapped_addr = dword_remap(svga->hwcursor_latch.addr);
uint32_t remapped_addr = dword_remap(svga, svga->hwcursor_latch.addr);
dat[0] = (svga->vram[remapped_addr] << 8) | svga->vram[remapped_addr + 1];
dat[1] = (svga->vram[remapped_addr + 2] << 8) | svga->vram[remapped_addr + 3];
@@ -1938,8 +1947,9 @@ static void s3_trio64v_overlay_draw(svga_t *svga, int displine)
int x_size, x_read = 4, x_write = 4;
int x;
uint32_t *p;
uint8_t *src = &svga->vram[svga->overlay_latch.addr];
uint32_t remapped_addr = dword_remap(svga, svga->overlay_latch.addr);
uint8_t *src = &svga->vram[remapped_addr];
p = &(buffer32->line[displine][offset + svga->x_add]);
if ((offset + s3->streams.sec_w) > s3->streams.pri_w)
@@ -2264,7 +2274,8 @@ s3_out(uint16_t addr, uint8_t val, void *p)
{
case 0x31:
s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4);
svga->force_dword_mode = val & 0x08;
if (!svga->packed_chain4)
svga->force_dword_mode = !!(val & 0x08);
break;
case 0x32:
if (svga->crtc[0x31] & 0x30)
@@ -2528,8 +2539,19 @@ s3_in(uint16_t addr, void *p)
case 0x6a: return s3->bank;
/* Phoenix S3 video BIOS'es seem to expect CRTC registers 6B and 6C
to be mirrors of 59 and 5A. */
case 0x6b: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? (svga->crtc[0x59] & 0xfe) : svga->crtc[0x59]);
case 0x6c: return (s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? 0 : (svga->crtc[0x5a] & 0x80);
case 0x6b:
if (svga->crtc[0x53] & 0x08) {
return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : (svga->crtc[0x59] & 0xfe);
} else {
return svga->crtc[0x59];
}
break;
case 0x6c:
if (svga->crtc[0x53] & 0x08)
return 0x00;
else
return (svga->crtc[0x5a] & 0x80);
break;
}
return svga->crtc[svga->crtcreg];
}
@@ -2591,7 +2613,7 @@ static void s3_recalctimings(svga_t *svga)
if (s3->width == 2048 || s3->width == 1280 || s3->width == 1600)
svga->hdisp *= 2;
} else if ((s3->chip != S3_86C801) && (s3->chip != S3_86C805) && (s3->chip != S3_TRIO32) &&
(s3->chip != S3_TRIO64) && (s3->chip != S3_TRIO64V)) {
(s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964) && (s3->chip != S3_VISION968)) {
if (s3->width == 1280 || s3->width == 1600)
svga->hdisp *= 2;
}
@@ -2608,7 +2630,7 @@ static void s3_recalctimings(svga_t *svga)
svga->hdisp /= 2;
}
if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) &&
(s3->chip != S3_TRIO64) && (s3->chip != S3_TRIO64V)) {
(s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) {
if (s3->width == 1280 || s3->width == 1600)
svga->hdisp *= 2;
}
@@ -2624,7 +2646,7 @@ static void s3_recalctimings(svga_t *svga)
svga->hdisp /= 2;
}
if ((s3->chip != S3_VISION868) && (s3->chip != S3_TRIO32) &&
(s3->chip != S3_TRIO64) && (s3->chip != S3_TRIO64V)) {
(s3->chip != S3_TRIO64) && (s3->chip != S3_VISION964)) {
if (s3->width == 1280 || s3->width == 1600)
svga->hdisp *= 2;
}
@@ -2684,7 +2706,8 @@ static void s3_trio64v_recalctimings(svga_t *svga)
if (svga->crtc[0x51] & 0x30) svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4;
else if (svga->crtc[0x43] & 0x04) svga->rowoffset |= 0x100;
if (!svga->rowoffset) svga->rowoffset = 256;
svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10));
if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10)) {
switch (svga->bpp) {
case 8:
@@ -2828,7 +2851,6 @@ s3_updatemapping(s3_t *s3)
case S3_TRIO64V:
case S3_TRIO64V2:
case S3_86C928:
case S3_VISION868:
s3->linear_size = 0x400000;
break;
default:
@@ -2852,9 +2874,10 @@ s3_updatemapping(s3_t *s3)
s3->linear_base &= 0xfe000000;
mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size);
}
} else
} else {
mem_mapping_disable(&s3->linear_mapping);
}
/* Memory mapped I/O. */
if ((svga->crtc[0x53] & 0x10) || (s3->accel.advfunc_cntl & 0x20)) {
mem_mapping_disable(&svga->mapping);
@@ -2863,18 +2886,16 @@ s3_updatemapping(s3_t *s3)
mem_mapping_set_addr(&s3->mmio_mapping, 0xb8000, 0x8000);
else
mem_mapping_set_addr(&s3->mmio_mapping, 0xa0000, 0x10000);
} else {
} else
mem_mapping_enable(&s3->mmio_mapping);
}
} else
mem_mapping_disable(&s3->mmio_mapping);
/* New MMIO. */
if (svga->crtc[0x53] & 0x08) {
if (svga->crtc[0x53] & 0x08)
mem_mapping_set_addr(&s3->new_mmio_mapping, s3->linear_base + 0x1000000, 0x20000);
} else {
else
mem_mapping_disable(&s3->new_mmio_mapping);
}
}
}
@@ -3258,45 +3279,59 @@ s3_accel_in(uint16_t port, void *p)
break;
case 0xd148: case 0xd2e8:
s3_wait_fifo_idle(s3);
return s3->accel.ropmix & 0xff;
case 0xd149: case 0xd2e9:
s3_wait_fifo_idle(s3);
return s3->accel.ropmix >> 8;
case 0xe548: case 0xe6e8:
s3_wait_fifo_idle(s3);
return s3->accel.pat_bg_color & 0xff;
case 0xe549: case 0xe6e9:
s3_wait_fifo_idle(s3);
return s3->accel.pat_bg_color >> 8;
case 0xe54a: case 0xe6ea:
s3_wait_fifo_idle(s3);
return s3->accel.pat_bg_color >> 16;
case 0xe54b: case 0xe6eb:
s3_wait_fifo_idle(s3);
return s3->accel.pat_bg_color >> 24;
case 0xe948: case 0xeae8:
s3_wait_fifo_idle(s3);
return s3->accel.pat_y & 0xff;
case 0xe949: case 0xeae9:
s3_wait_fifo_idle(s3);
return s3->accel.pat_y >> 8;
case 0xe94a: case 0xeaea:
s3_wait_fifo_idle(s3);
return s3->accel.pat_x & 0xff;
case 0xe94b: case 0xeaeb:
s3_wait_fifo_idle(s3);
return s3->accel.pat_x >> 8;
case 0xed48: case 0xeee8:
s3_wait_fifo_idle(s3);
return s3->accel.pat_fg_color & 0xff;
case 0xed49: case 0xeee9:
s3_wait_fifo_idle(s3);
return s3->accel.pat_fg_color >> 8;
case 0xed4a: case 0xeeea:
s3_wait_fifo_idle(s3);
return s3->accel.pat_fg_color >> 16;
case 0xed4b: case 0xeeeb:
s3_wait_fifo_idle(s3);
return s3->accel.pat_fg_color >> 24;
case 0xe148: case 0xe2e8:
@@ -3723,9 +3758,9 @@ polygon_setup(s3_t *s3)
}
#define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[dword_remap(addr) & s3->vram_mask]; \
else if (s3->bpp == 1) dat = vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)]; \
else dat = vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)];
#define READ(addr, dat) if (s3->bpp == 0) dat = svga->vram[dword_remap(svga, addr) & s3->vram_mask]; \
else if (s3->bpp == 1) dat = vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)]; \
else dat = vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)];
#define MIX_READ { \
switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \
@@ -4030,18 +4065,18 @@ polygon_setup(s3_t *s3)
#define WRITE(addr, dat) if (s3->bpp == 0) \
{ \
svga->vram[dword_remap(addr) & s3->vram_mask] = dat; \
svga->changedvram[(dword_remap(addr) & s3->vram_mask) >> 12] = changeframecount; \
svga->vram[dword_remap(svga, addr) & s3->vram_mask] = dat; \
svga->changedvram[(dword_remap(svga, addr) & s3->vram_mask) >> 12] = changeframecount; \
} \
else if (s3->bpp == 1) \
{ \
vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)] = dat; \
svga->changedvram[(dword_remap_w(addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \
vram_w[dword_remap_w(svga, addr) & (s3->vram_mask >> 1)] = dat; \
svga->changedvram[(dword_remap_w(svga, addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \
} \
else \
{ \
vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)] = dat; \
svga->changedvram[(dword_remap_l(addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \
vram_l[dword_remap_l(svga, addr) & (s3->vram_mask >> 2)] = dat; \
svga->changedvram[(dword_remap_l(svga, addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \
}
@@ -5525,6 +5560,7 @@ s3_pci_read(int func, int addr, void *p)
{
s3_t *s3 = (s3_t *)p;
svga_t *svga = &s3->svga;
switch (addr)
{
case 0x00: return 0x33; /*'S3'*/
@@ -5560,9 +5596,21 @@ s3_pci_read(int func, int addr, void *p)
case 0x10: return 0x00; /*Linear frame buffer address*/
case 0x11: return 0x00;
case 0x12: return (s3->chip >= S3_TRIO64V || s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? 0 : (svga->crtc[0x5a] & 0x80);
case 0x13: return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? (svga->crtc[0x59] & 0xfe) : svga->crtc[0x59]);
case 0x12:
if (svga->crtc[0x53] & 0x08)
return 0x00;
else
return (svga->crtc[0x5a] & 0x80);
break;
case 0x13:
if (svga->crtc[0x53] & 0x08) {
return (s3->chip >= S3_TRIO64V) ? (svga->crtc[0x59] & 0xfc) : (svga->crtc[0x59] & 0xfe);
} else {
return svga->crtc[0x59];
}
break;
case 0x30: return s3->has_bios ? (s3->pci_regs[0x30] & 0x01) : 0x00; /*BIOS ROM address*/
case 0x31: return 0x00;
case 0x32: return s3->has_bios ? s3->pci_regs[0x32] : 0x00;
@@ -5591,14 +5639,18 @@ s3_pci_write(int func, int addr, uint8_t val, void *p)
break;
case 0x12:
if (s3->chip != S3_TRIO64V && s3->chip != S3_TRIO64V2 && s3->chip != S3_VISION968 && s3->chip != S3_VISION868) {
if (!(svga->crtc[0x53] & 0x08)) {
svga->crtc[0x5a] = (svga->crtc[0x5a] & 0x7f) | (val & 0x80);
s3_updatemapping(s3);
}
break;
case 0x13:
svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : ((s3->chip == S3_VISION968 || s3->chip == S3_VISION868) ? (val & 0xfe) : val);
if (svga->crtc[0x53] & 0x08) {
svga->crtc[0x59] = (s3->chip >= S3_TRIO64V) ? (val & 0xfc) : (val & 0xfe);
} else {
svga->crtc[0x59] = val;
}
s3_updatemapping(s3);
break;
@@ -6059,6 +6111,7 @@ static void *s3_init(const device_t *info)
svga->crtc[0x59] = 0x00;
svga->crtc[0x5a] = 0x0a;
}
svga->packed_chain4 = 1;
svga->ramdac = device_add(&ibm_rgb528_ramdac_device);
svga->clock_gen = device_add(&icd2061_device);
@@ -6066,7 +6119,7 @@ static void *s3_init(const device_t *info)
break;
case S3_PHOENIX_VISION868:
svga->decode_mask = (4 << 20) - 1;
svga->decode_mask = (8 << 20) - 1;
s3->id = 0xe1; /*Vision868*/
s3->id_ext = 0x90;
s3->id_ext_pci = 0x80;
@@ -6082,6 +6135,7 @@ static void *s3_init(const device_t *info)
svga->crtc[0x59] = 0x00;
svga->crtc[0x5a] = 0x0a;
}
svga->packed_chain4 = 1;
svga->ramdac = device_add(&sdac_ramdac_device);
svga->clock_gen = svga->ramdac;
@@ -6114,6 +6168,12 @@ static void *s3_init(const device_t *info)
s3->id_ext = s3->id_ext_pci = 0x11;
s3->packed_mmio = 1;
if (info->local == S3_PHOENIX_TRIO64VPLUS || info->local == S3_PHOENIX_TRIO64VPLUS_ONBOARD) {
if (s3->pci)
svga->crtc[0x53] = 0x08;
svga->packed_chain4 = 1;
}
svga->clock_gen = s3;
svga->getclock = s3_trio64_getclock;
break;
@@ -6123,7 +6183,9 @@ static void *s3_init(const device_t *info)
s3->id = 0xe1; /*Trio64V2/DX*/
s3->id_ext = s3->id_ext_pci = 0x01;
s3->packed_mmio = 1;
svga->crtc[0x53] = 0x08;
svga->crtc[0x6c] = 1;
svga->packed_chain4 = 1;
svga->clock_gen = s3;
svga->getclock = s3_trio64_getclock;

View File

@@ -167,10 +167,6 @@ sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga)
switch (ramdac->magic_count) {
case 4:
sdac_control_write(ramdac, svga, val);
if (!(ramdac->type & ICS_S3))
ramdac->magic_count = 0;
break;
case 5:
ramdac->magic_count = 0;
break;
default:
@@ -215,21 +211,15 @@ sdac_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga)
switch (rs) {
case 0x02:
switch (ramdac->magic_count) {
case 1:
case 2: case 3:
case 1: case 2:
temp = 0x00;
ramdac->magic_count++;
break;
case 4:
if (ramdac->type & ICS_S3) {
temp = 0x70; /* SDAC ID */
ramdac->magic_count++;
} else {
temp = ramdac->command;
ramdac->magic_count = 0;
}
case 3:
temp = (ramdac->type & ICS_S3) ? 0x70 : 0x00;
ramdac->magic_count++;
break;
case 5:
case 4:
temp = ramdac->command;
ramdac->magic_count = 0;
break;

View File

@@ -1056,9 +1056,11 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p)
}
if (!(svga->gdcreg[6] & 1))
svga->fullchange = 2;
svga->fullchange = 2;
if ((svga->adv_flags & FLAG_ADDR_BY8) && (svga->writemode < 4))
if ((svga->adv_flags & FLAG_ADDR_BY16) && (svga->writemode == 4 || svga->writemode == 5))
addr <<= 4;
else if ((svga->adv_flags & FLAG_ADDR_BY8) && (svga->writemode < 4))
addr <<= 3;
else if (((svga->chain4 && svga->packed_chain4) || svga->fb_only) && (svga->writemode < 4)) {
writemask2 = 1 << (addr & 3);
@@ -1244,7 +1246,9 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p)
latch_addr = (addr << count) & svga->decode_mask;
count = (1 << count);
if (svga->adv_flags & FLAG_ADDR_BY8)
if (svga->adv_flags & FLAG_ADDR_BY16)
addr <<= 4;
else if (svga->adv_flags & FLAG_ADDR_BY8)
addr <<= 3;
else if ((svga->chain4 && svga->packed_chain4) || svga->fb_only) {
addr &= svga->decode_mask;

View File

@@ -906,8 +906,8 @@ svga_render_15bpp_lowres(svga_t *svga)
*p++ = video_15to32[dat >> 16];
} else
memset(&(p[x]), 0x00, 2 * sizeof(uint32_t));
svga->ma += 4;
}
svga->ma += 4;
}
svga->ma &= svga->vram_display_mask;
}
@@ -966,8 +966,8 @@ svga_render_15bpp_highres(svga_t *svga)
*p++ = video_15to32[dat >> 16];
} else
memset(&(p[x]), 0x00, 2 * sizeof(uint32_t));
svga->ma += 4;
}
svga->ma += 4;
}
svga->ma &= svga->vram_display_mask;
}

View File

@@ -485,9 +485,11 @@ static void banshee_recalctimings(svga_t *svga)
// banshee_log("svga->hdisp=%i\n", svga->hdisp);
svga->interlace = 0;
svga->force_legacy_mode = 0;
if (banshee->vgaInit0 & VGAINIT0_EXTENDED_SHIFT_OUT)
{
svga->force_legacy_mode = 1;
switch (VIDPROCCFG_DESKTOP_PIX_FORMAT)
{
case PIX_FORMAT_8:
@@ -664,6 +666,7 @@ static void banshee_ext_outl(uint16_t addr, uint32_t val, void *p)
banshee->vgaInit1 = val;
svga->write_bank = (val & 0x3ff) << 15;
svga->read_bank = ((val >> 10) & 0x3ff) << 15;
svga->packed_chain4 = !!(val & 0x00100000);
break;
case PLL_pllCtrl0:

View File

@@ -634,7 +634,6 @@ MCHOBJ := machine.o machine_table.o \
m_at_286_386sx.o m_at_386dx_486.o \
m_at_socket4_5.o m_at_socket7.o m_at_sockets7.o \
m_at_socket8.o m_at_slot1.o m_at_slot2.o m_at_socket370.o \
m_at_ebga368.o \
m_at_misc.o
DEVOBJ := bugger.o hwm.o hwm_lm75.o hwm_lm78.o hwm_gl518sm.o hwm_vt82c686.o ibm_5161.o isamem.o isartc.o \
@@ -724,7 +723,7 @@ SNDOBJ := sound.o \
snd_pssj.o \
snd_lpt_dac.o snd_lpt_dss.o \
snd_adlib.o snd_adlibgold.o snd_ad1848.o snd_audiopci.o \
snd_azt2316a.o \
snd_azt2316a.o snd_cs423x.o \
snd_cms.o \
snd_gus.o \
snd_sb.o snd_sb_dsp.o \