DMA: Implemented autoinit mode in the PS/2 MCA side (although the bit is undocumented in said side, but documented in the ISA/PCI side).
Networking: Added the WD8013EP/A MCA nic, which is more supported than the WD80x3ET/A plus an initial ram size configuration before POS configuration. Sound: Added the Reply MCA OEM of SB16 with its own MCA POS ID and properly implemented the IRQ's and DMA's of the AdLib Gold in its EEPROM plus an initial configurable setting for them and an initial DRQ implementation into said card.
This commit is contained in:
@@ -62,6 +62,7 @@ static struct {
|
||||
|
||||
|
||||
#define DMA_PS2_IOA (1 << 0)
|
||||
#define DMA_PS2_AUTOINIT (1 << 1)
|
||||
#define DMA_PS2_XFER_MEM_TO_IO (1 << 2)
|
||||
#define DMA_PS2_XFER_IO_TO_MEM (3 << 2)
|
||||
#define DMA_PS2_XFER_MASK (3 << 2)
|
||||
@@ -729,6 +730,8 @@ dma_ps2_write(uint16_t addr, uint8_t val, void *priv)
|
||||
else if ((val & DMA_PS2_XFER_MASK) == DMA_PS2_XFER_IO_TO_MEM)
|
||||
mode |= 4;
|
||||
dma_c->mode = (dma_c->mode & ~0x2c) | mode;
|
||||
if (val & DMA_PS2_AUTOINIT)
|
||||
dma_c->mode |= 0x10;
|
||||
dma_c->ps2_mode = val;
|
||||
dma_c->size = val & DMA_PS2_SIZE16;
|
||||
break;
|
||||
|
@@ -50,7 +50,8 @@ enum {
|
||||
WD8003EB, /* WD8003EB : 8-bit ISA, 5x3 interface chip */
|
||||
WD8013EBT, /* WD8013EBT : 16-bit ISA, no interface chip */
|
||||
WD8003ETA, /* WD8003ET/A: 16-bit MCA, no interface chip */
|
||||
WD8003EA /* WD8003E/A : 16-bit MCA, 5x3 interface chip */
|
||||
WD8003EA, /* WD8003E/A : 16-bit MCA, 5x3 interface chip */
|
||||
WD8013EPA
|
||||
};
|
||||
|
||||
extern const device_t wd8003e_device;
|
||||
@@ -58,5 +59,6 @@ extern const device_t wd8003eb_device;
|
||||
extern const device_t wd8013ebt_device;
|
||||
extern const device_t wd8003eta_device;
|
||||
extern const device_t wd8003ea_device;
|
||||
extern const device_t wd8013epa_device;
|
||||
|
||||
#endif /*NET_WD8003_H*/
|
||||
|
@@ -120,6 +120,7 @@ extern const device_t sb_16_device;
|
||||
extern const device_t sb_16_pnp_device;
|
||||
extern const device_t sb_16_compat_device;
|
||||
extern const device_t sb_16_compat_nompu_device;
|
||||
extern const device_t sb_16_reply_mca_device;
|
||||
extern const device_t sb_32_pnp_device;
|
||||
extern const device_t sb_awe32_device;
|
||||
extern const device_t sb_awe32_pnp_device;
|
||||
|
@@ -540,7 +540,6 @@ wd_mca_read(int port, void *priv)
|
||||
|
||||
#define MCA_6FC0_IRQS { 3, 4, 10, 15 }
|
||||
|
||||
|
||||
static void
|
||||
wd_mca_write(int port, uint8_t val, void *priv)
|
||||
{
|
||||
@@ -582,6 +581,68 @@ wd_mca_write(int port, uint8_t val, void *priv)
|
||||
dev->base_address, dev->irq, dev->ram_addr);
|
||||
}
|
||||
|
||||
static void
|
||||
wd_8013epa_mca_write(int port, uint8_t val, void *priv)
|
||||
{
|
||||
wd_t *dev = (wd_t *)priv;
|
||||
|
||||
/* MCA does not write registers below 0x0100. */
|
||||
if (port < 0x0102) return;
|
||||
|
||||
/* Save the MCA register value. */
|
||||
dev->pos_regs[port & 7] = val;
|
||||
|
||||
/*
|
||||
* The PS/2 Model 80 BIOS always enables a card if it finds one,
|
||||
* even if no resources were assigned yet (because we only added
|
||||
* the card, but have not run AutoConfig yet...)
|
||||
*
|
||||
* So, remove current address, if any.
|
||||
*/
|
||||
if (dev->base_address)
|
||||
wd_io_remove(dev, dev->base_address);
|
||||
|
||||
dev->base_address = 0x800 + ((dev->pos_regs[2] & 0xf0) << 8);
|
||||
|
||||
switch (dev->pos_regs[5] & 0x0c) {
|
||||
case 0:
|
||||
dev->irq = 3;
|
||||
break;
|
||||
case 4:
|
||||
dev->irq = 4;
|
||||
break;
|
||||
case 8:
|
||||
dev->irq = 10;
|
||||
break;
|
||||
case 0x0c:
|
||||
dev->irq = 14;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->pos_regs[3] & 0x10)
|
||||
dev->ram_size = 0x4000;
|
||||
else
|
||||
dev->ram_size = 0x2000;
|
||||
|
||||
dev->ram_addr = ((dev->pos_regs[3] & 0x0f) << 13) + 0xc0000;
|
||||
if (dev->pos_regs[3] & 0x80)
|
||||
dev->ram_addr += 0xf00000;
|
||||
|
||||
/* Initialize the device if fully configured. */
|
||||
/* Register (new) I/O handler. */
|
||||
if (dev->pos_regs[2] & 0x01)
|
||||
wd_io_set(dev, dev->base_address);
|
||||
|
||||
mem_mapping_set_addr(&dev->ram_mapping, dev->ram_addr, dev->ram_size);
|
||||
|
||||
mem_mapping_disable(&dev->ram_mapping);
|
||||
if ((dev->msr & WE_MSR_ENABLE_RAM) && (dev->pos_regs[2] & 0x01))
|
||||
mem_mapping_enable(&dev->ram_mapping);
|
||||
|
||||
wdlog("%s: attached IO=0x%X IRQ=%d, RAM addr=0x%06x\n", dev->name,
|
||||
dev->base_address, dev->irq, dev->ram_addr);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
wd_mca_feedb(void *priv)
|
||||
@@ -624,9 +685,12 @@ wd_init(const device_t *info)
|
||||
dev->maclocal[5] = (mac & 0xff);
|
||||
}
|
||||
|
||||
if ((dev->board == WD8003ETA) || (dev->board == WD8003EA))
|
||||
mca_add(wd_mca_read, wd_mca_write, wd_mca_feedb, NULL, dev);
|
||||
else {
|
||||
if ((dev->board == WD8003ETA) || (dev->board == WD8003EA) || dev->board == WD8013EPA) {
|
||||
if (dev->board == WD8013EPA)
|
||||
mca_add(wd_mca_read, wd_8013epa_mca_write, wd_mca_feedb, NULL, dev);
|
||||
else
|
||||
mca_add(wd_mca_read, wd_mca_write, wd_mca_feedb, NULL, dev);
|
||||
} else {
|
||||
dev->base_address = device_get_config_hex16("base");
|
||||
dev->irq = device_get_config_int("irq");
|
||||
dev->ram_addr = device_get_config_hex20("ram_addr");
|
||||
@@ -679,12 +743,20 @@ wd_init(const device_t *info)
|
||||
dev->board_chip = WE_ID_SOFT_CONFIG;
|
||||
/* Ethernet, MCA, no interface chip, RAM 16k */
|
||||
case WD8003ETA:
|
||||
dev->board_chip |= 0x05 | WE_ID_BUS_MCA;
|
||||
dev->board_chip |= WE_TYPE_WD8013EBT | WE_ID_BUS_MCA;
|
||||
dev->ram_size = 0x4000;
|
||||
dev->pos_regs[0] = 0xC0;
|
||||
dev->pos_regs[1] = 0x6F;
|
||||
dev->bit16 = 3;
|
||||
break;
|
||||
|
||||
case WD8013EPA:
|
||||
dev->board_chip = WE_TYPE_WD8013EP | WE_ID_BUS_MCA;
|
||||
dev->ram_size = device_get_config_int("ram_size");
|
||||
dev->pos_regs[0] = 0xC8;
|
||||
dev->pos_regs[1] = 0x61;
|
||||
dev->bit16 = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
dev->irr |= WE_IRR_ENABLE_IRQ;
|
||||
@@ -969,6 +1041,31 @@ static const device_config_t wd8013_config[] = {
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
|
||||
static const device_config_t wd8013epa_config[] = {
|
||||
{
|
||||
.name = "ram_size",
|
||||
.description = "Initial RAM size",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = "",
|
||||
.default_int = 16384,
|
||||
.file_filter = "",
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "8 kB", .value = 8192 },
|
||||
{ .description = "16 kB", .value = 16384 },
|
||||
{ .description = "" }
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "mac",
|
||||
.description = "MAC Address",
|
||||
.type = CONFIG_MAC,
|
||||
.default_string = "",
|
||||
.default_int = -1
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
|
||||
static const device_config_t mca_mac_config[] = {
|
||||
{
|
||||
.name = "mac",
|
||||
@@ -1050,3 +1147,17 @@ const device_t wd8003ea_device = {
|
||||
.force_redraw = NULL,
|
||||
.config = mca_mac_config
|
||||
};
|
||||
|
||||
const device_t wd8013epa_device = {
|
||||
.name = "Western Digital WD8013EP/A",
|
||||
.internal_name = "wd8013epa",
|
||||
.flags = DEVICE_MCA,
|
||||
.local = WD8013EPA,
|
||||
.init = wd_init,
|
||||
.close = wd_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = wd8013epa_config
|
||||
};
|
||||
|
@@ -103,6 +103,7 @@ static netcard_t net_cards[] = {
|
||||
{ ðernext_mc_device, NULL },
|
||||
{ &wd8003eta_device, NULL },
|
||||
{ &wd8003ea_device, NULL },
|
||||
{ &wd8013epa_device, NULL },
|
||||
{ &pcnet_am79c973_device, NULL },
|
||||
{ &pcnet_am79c970a_device, NULL },
|
||||
{ &rtl8029as_device, NULL },
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
typedef struct adgold_t {
|
||||
int adgold_irq_status;
|
||||
int irq, dma, hdma;
|
||||
|
||||
uint8_t adgold_eeprom[0x1a];
|
||||
|
||||
@@ -157,7 +158,7 @@ adgold_update_irq_status(adgold_t *adgold)
|
||||
adgold->adgold_status = temp;
|
||||
|
||||
if ((adgold->adgold_status ^ 0xf) && !adgold->adgold_irq_status) {
|
||||
picint(0x80);
|
||||
picint(1 << adgold->irq);
|
||||
}
|
||||
|
||||
adgold->adgold_irq_status = adgold->adgold_status ^ 0xf;
|
||||
@@ -167,23 +168,26 @@ void
|
||||
adgold_getsamp_dma(adgold_t *adgold, int channel)
|
||||
{
|
||||
int temp;
|
||||
dma_set_drq(adgold->dma, 1);
|
||||
|
||||
if ((adgold->adgold_mma_regs[channel][0xc] & 0x60) && (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) >= 127))
|
||||
return;
|
||||
|
||||
temp = dma_channel_read(1);
|
||||
if (temp == DMA_NODATA)
|
||||
temp = dma_channel_read(adgold->dma);
|
||||
if (temp == DMA_NODATA) {
|
||||
return;
|
||||
}
|
||||
adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_end[channel]] = temp;
|
||||
adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255;
|
||||
adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255;
|
||||
if (adgold->adgold_mma_regs[channel][0xc] & 0x60) {
|
||||
temp = dma_channel_read(1);
|
||||
temp = dma_channel_read(adgold->dma);
|
||||
adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_end[channel]] = temp;
|
||||
adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255;
|
||||
adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255;
|
||||
}
|
||||
if (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) >= adgold->adgold_mma_intpos[channel]) {
|
||||
adgold->adgold_mma_status &= ~(0x01 << channel);
|
||||
adgold_update_irq_status(adgold);
|
||||
dma_set_drq(adgold->dma, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,10 +339,11 @@ adgold_write(uint16_t addr, uint8_t val, void *p)
|
||||
break; /* 7350 Hz*/
|
||||
}
|
||||
if (val & 0x80) {
|
||||
adgold->adgold_mma_enable[0] = 0;
|
||||
adgold->adgold_mma_enable[0] = 0;
|
||||
adgold->adgold_mma_fifo_end[0] = adgold->adgold_mma_fifo_start[0] = 0;
|
||||
adgold->adgold_mma_status &= ~0x01;
|
||||
adgold_update_irq_status(adgold);
|
||||
dma_set_drq(adgold->dma, 0);
|
||||
}
|
||||
if ((val & 0x01)) /*Start playback*/
|
||||
{
|
||||
@@ -347,7 +352,7 @@ adgold_write(uint16_t addr, uint8_t val, void *p)
|
||||
|
||||
if (adgold->adgold_mma_regs[0][0xc] & 1) {
|
||||
if (adgold->adgold_mma_regs[0][0xc] & 0x80) {
|
||||
adgold->adgold_mma_enable[1] = 1;
|
||||
adgold->adgold_mma_enable[1] = 1;
|
||||
adgold->adgold_mma.voice_count[1] = adgold->adgold_mma.voice_latch[1];
|
||||
|
||||
while (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) {
|
||||
@@ -357,10 +362,12 @@ adgold_write(uint16_t addr, uint8_t val, void *p)
|
||||
if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) {
|
||||
adgold->adgold_mma_status &= ~0x01;
|
||||
adgold_update_irq_status(adgold);
|
||||
dma_set_drq(adgold->dma, 0);
|
||||
}
|
||||
if (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) >= adgold->adgold_mma_intpos[1]) {
|
||||
adgold->adgold_mma_status &= ~0x02;
|
||||
adgold_update_irq_status(adgold);
|
||||
dma_set_drq(adgold->dma, 0);
|
||||
}
|
||||
} else {
|
||||
while (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) {
|
||||
@@ -369,6 +376,7 @@ adgold_write(uint16_t addr, uint8_t val, void *p)
|
||||
if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) {
|
||||
adgold->adgold_mma_status &= ~0x01;
|
||||
adgold_update_irq_status(adgold);
|
||||
dma_set_drq(adgold->dma, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -379,10 +387,11 @@ adgold_write(uint16_t addr, uint8_t val, void *p)
|
||||
case 0xb:
|
||||
if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) {
|
||||
adgold->adgold_mma_fifo[0][adgold->adgold_mma_fifo_end[0]] = val;
|
||||
adgold->adgold_mma_fifo_end[0] = (adgold->adgold_mma_fifo_end[0] + 1) & 255;
|
||||
adgold->adgold_mma_fifo_end[0] = (adgold->adgold_mma_fifo_end[0] + 1) & 255;
|
||||
if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) {
|
||||
adgold->adgold_mma_status &= ~0x01;
|
||||
adgold_update_irq_status(adgold);
|
||||
dma_set_drq(adgold->dma, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -457,6 +466,7 @@ adgold_write(uint16_t addr, uint8_t val, void *p)
|
||||
adgold->adgold_mma_fifo_end[1] = adgold->adgold_mma_fifo_start[1] = 0;
|
||||
adgold->adgold_mma_status &= ~0x02;
|
||||
adgold_update_irq_status(adgold);
|
||||
dma_set_drq(adgold->dma, 0);
|
||||
}
|
||||
if ((val & 0x01)) /*Start playback*/
|
||||
{
|
||||
@@ -479,6 +489,7 @@ adgold_write(uint16_t addr, uint8_t val, void *p)
|
||||
if (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) >= adgold->adgold_mma_intpos[1]) {
|
||||
adgold->adgold_mma_status &= ~0x02;
|
||||
adgold_update_irq_status(adgold);
|
||||
dma_set_drq(adgold->dma, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -525,6 +536,7 @@ adgold_read(uint16_t addr, void *p)
|
||||
|
||||
default:
|
||||
temp = adgold->adgold_38x_regs[adgold->adgold_38x_addr];
|
||||
break;
|
||||
}
|
||||
} else
|
||||
temp = opl3_read(addr, &adgold->opl);
|
||||
@@ -877,8 +889,9 @@ adgold_init(const device_t *info)
|
||||
adgold_t *adgold = malloc(sizeof(adgold_t));
|
||||
memset(adgold, 0, sizeof(adgold_t));
|
||||
|
||||
adgold->dma = device_get_config_int("dma");
|
||||
adgold->irq = device_get_config_int("irq");
|
||||
adgold->surround_enabled = device_get_config_int("surround");
|
||||
|
||||
adgold->gameport_enabled = device_get_config_int("gameport");
|
||||
|
||||
opl3_init(&adgold->opl);
|
||||
@@ -912,9 +925,9 @@ adgold_init(const device_t *info)
|
||||
adgold->adgold_eeprom[0x10] = 0xff;
|
||||
adgold->adgold_eeprom[0x11] = 0x20;
|
||||
adgold->adgold_eeprom[0x12] = 0x00;
|
||||
adgold->adgold_eeprom[0x13] = 0x0b; /* IRQ 1, DMA1 */
|
||||
adgold->adgold_eeprom[0x14] = 0x00; /* DMA2 */
|
||||
adgold->adgold_eeprom[0x15] = 0x71; /* Port */
|
||||
adgold->adgold_eeprom[0x13] = 0xa0;
|
||||
adgold->adgold_eeprom[0x14] = 0x00;
|
||||
adgold->adgold_eeprom[0x15] = 0x388 / 8; /*Present at 388-38f*/
|
||||
adgold->adgold_eeprom[0x16] = 0x00;
|
||||
adgold->adgold_eeprom[0x17] = 0x68;
|
||||
adgold->adgold_eeprom[0x18] = 0x00; /* Surround */
|
||||
@@ -927,25 +940,36 @@ adgold_init(const device_t *info)
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
adgold->adgold_status = 0xf;
|
||||
adgold->adgold_38x_addr = 0;
|
||||
adgold->adgold_eeprom[0x13] = 3 | (1 << 3); /*IRQ 7, DMA 1*/
|
||||
// adgold->adgold_eeprom[0x14] = 3 << 4; /*DMA 3 - Double check this */
|
||||
adgold->adgold_eeprom[0x14] = 0x00; /*DMA ?*/
|
||||
adgold->adgold_eeprom[0x15] = 0x388 / 8; /*Present at 388-38f*/
|
||||
adgold->adgold_status = 0xf;
|
||||
adgold->adgold_38x_addr = 0;
|
||||
switch (adgold->irq) {
|
||||
case 3:
|
||||
adgold->adgold_eeprom[0x13] |= 0x00;
|
||||
break;
|
||||
case 4:
|
||||
adgold->adgold_eeprom[0x13] |= 0x01;
|
||||
break;
|
||||
case 5:
|
||||
adgold->adgold_eeprom[0x13] |= 0x02;
|
||||
break;
|
||||
case 7:
|
||||
adgold->adgold_eeprom[0x13] |= 0x03;
|
||||
break;
|
||||
}
|
||||
adgold->adgold_eeprom[0x13] |= (adgold->dma << 3);
|
||||
memcpy(adgold->adgold_38x_regs, adgold->adgold_eeprom, 0x19);
|
||||
adgold->vol_l = attenuation[adgold->adgold_eeprom[0x04] & 0x3f];
|
||||
adgold->vol_r = attenuation[adgold->adgold_eeprom[0x05] & 0x3f];
|
||||
adgold->bass = adgold->adgold_eeprom[0x06] & 0xf;
|
||||
adgold->treble = adgold->adgold_eeprom[0x07] & 0xf;
|
||||
adgold->fm_vol_l = (int) (int8_t) (adgold->adgold_eeprom[0x09] - 128);
|
||||
adgold->fm_vol_r = (int) (int8_t) (adgold->adgold_eeprom[0x0a] - 128);
|
||||
adgold->vol_l = attenuation[adgold->adgold_eeprom[0x04] & 0x3f];
|
||||
adgold->vol_r = attenuation[adgold->adgold_eeprom[0x05] & 0x3f];
|
||||
adgold->bass = adgold->adgold_eeprom[0x06] & 0xf;
|
||||
adgold->treble = adgold->adgold_eeprom[0x07] & 0xf;
|
||||
adgold->fm_vol_l = (int) (int8_t) (adgold->adgold_eeprom[0x09] - 128);
|
||||
adgold->fm_vol_r = (int) (int8_t) (adgold->adgold_eeprom[0x0a] - 128);
|
||||
adgold->samp_vol_l = (int) (int8_t) (adgold->adgold_eeprom[0x0b] - 128);
|
||||
adgold->samp_vol_r = (int) (int8_t) (adgold->adgold_eeprom[0x0c] - 128);
|
||||
adgold->aux_vol_l = (int) (int8_t) (adgold->adgold_eeprom[0x0d] - 128);
|
||||
adgold->aux_vol_r = (int) (int8_t) (adgold->adgold_eeprom[0x0e] - 128);
|
||||
|
||||
adgold->adgold_mma_enable[0] = 0;
|
||||
adgold->adgold_mma_enable[0] = 0;
|
||||
adgold->adgold_mma_fifo_start[0] = adgold->adgold_mma_fifo_end[0] = 0;
|
||||
|
||||
/*388/389 are handled by adlib_init*/
|
||||
@@ -982,6 +1006,54 @@ adgold_close(void *p)
|
||||
|
||||
static const device_config_t adgold_config[] = {
|
||||
// clang-format off
|
||||
{
|
||||
.name = "irq",
|
||||
.description = "IRQ",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = "",
|
||||
.default_int = 7,
|
||||
.file_filter = "",
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{
|
||||
.description = "IRQ 3",
|
||||
.value = 3
|
||||
},
|
||||
{
|
||||
.description = "IRQ 4",
|
||||
.value = 4
|
||||
},
|
||||
{
|
||||
.description = "IRQ 5",
|
||||
.value = 5
|
||||
},
|
||||
{
|
||||
.description = "IRQ 7",
|
||||
.value = 7
|
||||
},
|
||||
{ .description = "" }
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "dma",
|
||||
.description = "Low DMA channel",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = "",
|
||||
.default_int = 1,
|
||||
.file_filter = "",
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{
|
||||
.description = "DMA 1",
|
||||
.value = 1
|
||||
},
|
||||
{
|
||||
.description = "DMA 3",
|
||||
.value = 3
|
||||
},
|
||||
{ .description = "" }
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "gameport",
|
||||
.description = "Enable Game port",
|
||||
|
@@ -1198,6 +1198,148 @@ sb_pro_mcv_write(int port, uint8_t val, void *p)
|
||||
sb_dsp_setdma8(&sb->dsp, sb->pos_regs[4] & 3);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
sb_16_reply_mca_read(int port, void *p)
|
||||
{
|
||||
sb_t *sb = (sb_t *) p;
|
||||
uint8_t ret = sb->pos_regs[port & 7];
|
||||
|
||||
sb_log("sb_16_reply_mca_read: port=%04x ret=%02x\n", port, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
sb_16_reply_mca_write(int port, uint8_t val, void *p)
|
||||
{
|
||||
uint16_t addr, mpu401_addr;
|
||||
int low_dma, high_dma;
|
||||
sb_t *sb = (sb_t *) p;
|
||||
|
||||
if (port < 0x102)
|
||||
return;
|
||||
|
||||
sb_log("sb_16_reply_mca_write: port=%04x val=%02x\n", port, val);
|
||||
|
||||
switch (sb->pos_regs[2] & 0xc4) {
|
||||
case 4:
|
||||
addr = 0x220;
|
||||
break;
|
||||
case 0x44:
|
||||
addr = 0x240;
|
||||
break;
|
||||
case 0x84:
|
||||
addr = 0x260;
|
||||
break;
|
||||
case 0xc4:
|
||||
addr = 0x280;
|
||||
break;
|
||||
case 0:
|
||||
addr = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (addr) {
|
||||
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(0x0388, 0x0004,
|
||||
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);
|
||||
}
|
||||
|
||||
/* DSP I/O handler is activated in sb_dsp_setaddr */
|
||||
sb_dsp_setaddr(&sb->dsp, 0);
|
||||
mpu401_change_addr(sb->mpu, 0);
|
||||
gameport_remap(sb->gameport, 0);
|
||||
|
||||
sb->pos_regs[port & 7] = val;
|
||||
|
||||
if (sb->pos_regs[2] & 1) {
|
||||
switch (sb->pos_regs[2] & 0xc4) {
|
||||
case 4:
|
||||
addr = 0x220;
|
||||
break;
|
||||
case 0x44:
|
||||
addr = 0x240;
|
||||
break;
|
||||
case 0x84:
|
||||
addr = 0x260;
|
||||
break;
|
||||
case 0xc4:
|
||||
addr = 0x280;
|
||||
break;
|
||||
case 0:
|
||||
addr = 0;
|
||||
break;
|
||||
}
|
||||
switch (sb->pos_regs[2] & 0x18) {
|
||||
case 8:
|
||||
mpu401_addr = 0x330;
|
||||
break;
|
||||
case 0x18:
|
||||
mpu401_addr = 0x300;
|
||||
break;
|
||||
case 0:
|
||||
mpu401_addr = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (addr) {
|
||||
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(0x0388, 0x0004,
|
||||
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);
|
||||
}
|
||||
|
||||
/* DSP I/O handler is activated in sb_dsp_setaddr */
|
||||
sb_dsp_setaddr(&sb->dsp, addr);
|
||||
mpu401_change_addr(sb->mpu, mpu401_addr);
|
||||
gameport_remap(sb->gameport, (sb->pos_regs[2] & 0x20) ? 0x200 : 0);
|
||||
}
|
||||
|
||||
switch (sb->pos_regs[4] & 0x60) {
|
||||
case 0x20:
|
||||
sb_dsp_setirq(&sb->dsp, 5);
|
||||
break;
|
||||
case 0x40:
|
||||
sb_dsp_setirq(&sb->dsp, 7);
|
||||
break;
|
||||
case 0x60:
|
||||
sb_dsp_setirq(&sb->dsp, 10);
|
||||
break;
|
||||
}
|
||||
|
||||
low_dma = sb->pos_regs[3] & 3;
|
||||
high_dma = (sb->pos_regs[3] >> 4) & 7;
|
||||
if (!high_dma)
|
||||
high_dma = low_dma;
|
||||
|
||||
sb_dsp_setdma8(&sb->dsp, low_dma);
|
||||
sb_dsp_setdma16(&sb->dsp, high_dma);
|
||||
}
|
||||
|
||||
static void
|
||||
sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
|
||||
{
|
||||
@@ -1785,6 +1927,41 @@ sb_16_init(const device_t *info)
|
||||
return sb;
|
||||
}
|
||||
|
||||
static void *
|
||||
sb_16_reply_mca_init(const device_t *info)
|
||||
{
|
||||
sb_t *sb = malloc(sizeof(sb_t));
|
||||
memset(sb, 0x00, sizeof(sb_t));
|
||||
|
||||
sb->opl_enabled = 1;
|
||||
opl3_init(&sb->opl);
|
||||
|
||||
sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
|
||||
sb_ct1745_mixer_reset(sb);
|
||||
|
||||
sb->mixer_enabled = 1;
|
||||
sb->mixer_sb16.output_filter = 1;
|
||||
sound_add_handler(sb_get_buffer_sb16_awe32, sb);
|
||||
sound_set_cd_audio_filter(sb16_awe32_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, device_get_config_int("receive_input401"));
|
||||
sb_dsp_set_mpu(&sb->dsp, sb->mpu);
|
||||
|
||||
if (device_get_config_int("receive_input"))
|
||||
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
|
||||
|
||||
sb->gameport = gameport_add(&gameport_device);
|
||||
|
||||
/* I/O handlers activated in sb_pro_mcv_write */
|
||||
mca_add(sb_16_reply_mca_read, sb_16_reply_mca_write, sb_mcv_feedb, NULL, sb);
|
||||
sb->pos_regs[0] = 0x38;
|
||||
sb->pos_regs[1] = 0x51;
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
static void *
|
||||
sb_16_pnp_init(const device_t *info)
|
||||
{
|
||||
@@ -3371,6 +3548,20 @@ const device_t sb_16_device = {
|
||||
.config = sb_16_config
|
||||
};
|
||||
|
||||
const device_t sb_16_reply_mca_device = {
|
||||
.name = "Sound Blaster 16 Reply MCA",
|
||||
.internal_name = "sb16_reply_mca",
|
||||
.flags = DEVICE_MCA,
|
||||
.local = 0,
|
||||
.init = sb_16_reply_mca_init,
|
||||
.close = sb_close,
|
||||
.reset = NULL,
|
||||
{ .available = NULL },
|
||||
.speed_changed = sb_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = sb_16_pnp_config
|
||||
};
|
||||
|
||||
const device_t sb_16_pnp_device = {
|
||||
.name = "Sound Blaster 16 PnP",
|
||||
.internal_name = "sb16_pnp",
|
||||
|
@@ -140,6 +140,7 @@ static const SOUND_CARD sound_cards[] = {
|
||||
{ &ncr_business_audio_device },
|
||||
{ &sb_mcv_device },
|
||||
{ &sb_pro_mcv_device },
|
||||
{ &sb_16_reply_mca_device },
|
||||
{ &cmi8338_device },
|
||||
{ &cmi8738_device },
|
||||
{ &es1371_device },
|
||||
|
Reference in New Issue
Block a user