Merge pull request #1318 from richardg867/master
ISAPnP fixes, Adaptec AHA-1542CP and PCnet-ISA+
This commit is contained in:
@@ -423,8 +423,9 @@ device_get_name(const device_t *d, int bus, char *name)
|
||||
fbus = strstr(tname, sbus);
|
||||
if (fbus == tname)
|
||||
strcat(name, tname + strlen(sbus) + 1);
|
||||
/* Special case to not strip the "oPCI" from "Ensoniq AudioPCI". */
|
||||
else if ((fbus == NULL) || (*(fbus - 1) == 'o'))
|
||||
/* Special case to not strip the "oPCI" from "Ensoniq AudioPCI" or
|
||||
the "-ISA" from "AMD PCnet-ISA". */
|
||||
else if ((fbus == NULL) || (*(fbus - 1) == 'o') || (*(fbus - 1) == '-'))
|
||||
strcat(name, tname);
|
||||
else {
|
||||
strncat(name, tname, fbus - tname - 1);
|
||||
|
||||
@@ -85,6 +85,7 @@ enum {
|
||||
typedef struct _isapnp_device_ {
|
||||
uint8_t number;
|
||||
uint8_t regs[256];
|
||||
uint8_t mem_upperlimit, irq_types, io_16bit;
|
||||
|
||||
struct _isapnp_device_ *next;
|
||||
} isapnp_device_t;
|
||||
@@ -116,26 +117,28 @@ typedef struct {
|
||||
|
||||
|
||||
static void
|
||||
isapnp_device_config_changed(isapnp_t *dev)
|
||||
isapnp_device_config_changed(isapnp_card_t *card, isapnp_device_t *ld)
|
||||
{
|
||||
/* Ignore device if it hasn't signed up for configuration changes. */
|
||||
if (!dev->current_ld_card->config_changed)
|
||||
if (!card->config_changed)
|
||||
return;
|
||||
|
||||
/* Populate config structure, performing endianness conversion as needed. */
|
||||
isapnp_card_t *card = dev->current_ld_card;
|
||||
isapnp_device_t *ld = dev->current_ld;
|
||||
card->config.activate = ld->regs[0x30] & 0x01;
|
||||
uint8_t i, reg_base;
|
||||
for (i = 0; i < 4; i++) {
|
||||
reg_base = 0x40 + (8 * i);
|
||||
card->config.mem[i].base = (ld->regs[reg_base] << 16) | (ld->regs[reg_base + 1] << 8);
|
||||
card->config.mem[i].size = (ld->regs[reg_base + 3] << 16) | (ld->regs[reg_base + 4] << 8);
|
||||
if (ld->regs[reg_base + 2] & 0x01) /* upper limit */
|
||||
card->config.mem[i].size -= card->config.mem[i].base;
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
reg_base = (i == 0) ? 0x76 : (0x80 + (16 * i));
|
||||
card->config.mem32[i].base = (ld->regs[reg_base] << 24) | (ld->regs[reg_base + 1] << 16) | (ld->regs[reg_base + 2] << 8) | ld->regs[reg_base + 3];
|
||||
card->config.mem32[i].size = (ld->regs[reg_base + 5] << 24) | (ld->regs[reg_base + 6] << 16) | (ld->regs[reg_base + 7] << 8) | ld->regs[reg_base + 8];
|
||||
if (ld->regs[reg_base + 4] & 0x01) /* upper limit */
|
||||
card->config.mem32[i].size -= card->config.mem32[i].base;
|
||||
}
|
||||
for (i = 0; i < 8; i++) {
|
||||
reg_base = 0x60 + (2 * i);
|
||||
@@ -157,6 +160,36 @@ isapnp_device_config_changed(isapnp_t *dev)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
isapnp_reset_ld_regs(isapnp_device_t *ld)
|
||||
{
|
||||
memset(ld->regs, 0, sizeof(ld->regs));
|
||||
|
||||
/* DMA disable uses a non-zero value. */
|
||||
ld->regs[0x74] = ld->regs[0x75] = ISAPNP_DMA_DISABLED;
|
||||
|
||||
/* Set the upper limit bit on memory ranges which require it. */
|
||||
uint8_t i;
|
||||
for (i = 0; i < 4; i++)
|
||||
ld->regs[0x42 + (8 * i)] |= !!(ld->mem_upperlimit & (1 << i));
|
||||
ld->regs[0x7a] |= !!(ld->mem_upperlimit & (1 << 4));
|
||||
for (i = 1; i < 4; i++)
|
||||
ld->regs[0x84 + (16 * i)] |= !!(ld->mem_upperlimit & (1 << (4 + i)));
|
||||
|
||||
/* Set the default IRQ type bits. */
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (ld->irq_types & (0x1 << (4 * i)))
|
||||
ld->regs[0x70 + (2 * i)] = 0x02;
|
||||
else if (ld->irq_types & (0x2 << (4 * i)))
|
||||
ld->regs[0x70 + (2 * i)] = 0x00;
|
||||
else if (ld->irq_types & (0x4 << (4 * i)))
|
||||
ld->regs[0x70 + (2 * i)] = 0x03;
|
||||
else if (ld->irq_types & (0x8 << (4 * i)))
|
||||
ld->regs[0x70 + (2 * i)] = 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
isapnp_read_rangecheck(uint16_t addr, void *priv)
|
||||
{
|
||||
@@ -278,6 +311,8 @@ isapnp_read_data(uint16_t addr, void *priv)
|
||||
ret = card->read_vendor_reg(0, dev->reg, card->priv);
|
||||
break;
|
||||
|
||||
case 0x38: case 0x39: case 0x3a: case 0x3b:
|
||||
case 0x3c: case 0x3d: case 0x3e: case 0x3f:
|
||||
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
|
||||
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
|
||||
case 0xf8: case 0xf9: case 0xfa: case 0xfb:
|
||||
@@ -359,7 +394,7 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv)
|
||||
isapnp_t *dev = (isapnp_t *) priv;
|
||||
isapnp_card_t *card;
|
||||
isapnp_device_t *ld;
|
||||
uint16_t io_addr;
|
||||
uint16_t io_addr, reset_cards = 0;
|
||||
|
||||
isapnp_log("ISAPnP: write_data(%02X)\n", val);
|
||||
|
||||
@@ -378,18 +413,21 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv)
|
||||
while (card) {
|
||||
ld = card->first_ld;
|
||||
while (ld) {
|
||||
memset(ld->regs, 0, sizeof(ld->regs));
|
||||
dev->current_ld = ld;
|
||||
dev->current_ld_card = card;
|
||||
isapnp_device_config_changed(dev);
|
||||
if (card->state != PNP_STATE_WAIT_FOR_KEY) {
|
||||
isapnp_reset_ld_regs(ld);
|
||||
isapnp_device_config_changed(card, ld);
|
||||
reset_cards++;
|
||||
}
|
||||
ld = ld->next;
|
||||
}
|
||||
card = card->next;
|
||||
}
|
||||
|
||||
dev->current_ld = NULL;
|
||||
dev->current_ld_card = NULL;
|
||||
dev->isolated_card = NULL;
|
||||
if (reset_cards != 0) {
|
||||
dev->current_ld = NULL;
|
||||
dev->current_ld_card = NULL;
|
||||
dev->isolated_card = NULL;
|
||||
}
|
||||
}
|
||||
if (val & 0x02) {
|
||||
isapnp_log("ISAPnP: Return to WAIT_FOR_KEY\n");
|
||||
@@ -460,26 +498,8 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv)
|
||||
ld = ld->next;
|
||||
}
|
||||
|
||||
if (!ld) {
|
||||
isapnp_log("ISAPnP: Creating CSN %02X device %02X\n", card->csn, val);
|
||||
|
||||
ld = (isapnp_device_t *) malloc(sizeof(isapnp_device_t));
|
||||
memset(ld, 0, sizeof(isapnp_device_t));
|
||||
|
||||
ld->number = val;
|
||||
|
||||
dev->current_ld_card = card;
|
||||
dev->current_ld = ld;
|
||||
|
||||
if (!card->first_ld) {
|
||||
card->first_ld = ld;
|
||||
} else {
|
||||
ld = card->first_ld;
|
||||
while (ld->next)
|
||||
ld = ld->next;
|
||||
ld->next = dev->current_ld;
|
||||
}
|
||||
}
|
||||
if (!ld)
|
||||
fatal("ISAPnP: CSN %02X has no device %02X\n", card->csn, val);
|
||||
|
||||
break;
|
||||
|
||||
@@ -489,7 +509,7 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv)
|
||||
isapnp_log("ISAPnP: Activate CSN %02X device %02X\n", dev->current_ld_card->csn, dev->current_ld->number);
|
||||
|
||||
dev->current_ld->regs[dev->reg] = val & 0x01;
|
||||
isapnp_device_config_changed(dev);
|
||||
isapnp_device_config_changed(dev->current_ld_card, dev->current_ld);
|
||||
|
||||
break;
|
||||
|
||||
@@ -525,6 +545,8 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv)
|
||||
card->write_vendor_reg(0, dev->reg, val, card->priv);
|
||||
break;
|
||||
|
||||
case 0x38: case 0x39: case 0x3a: case 0x3b:
|
||||
case 0x3c: case 0x3d: case 0x3e: case 0x3f:
|
||||
case 0xf0: case 0xf1: case 0xf2: case 0xf3:
|
||||
case 0xf4: case 0xf5: case 0xf6: case 0xf7:
|
||||
case 0xf8: case 0xf9: case 0xfa: case 0xfb:
|
||||
@@ -536,11 +558,40 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (dev->reg >= 0x38) {
|
||||
if (dev->reg >= 0x40) {
|
||||
CHECK_CURRENT_LD();
|
||||
isapnp_log("ISAPnP: Write %02X to register %02X on CSN %02X device %02X\n", val, dev->reg, dev->current_ld_card->csn, dev->current_ld->number);
|
||||
|
||||
switch (dev->reg) {
|
||||
case 0x42: case 0x4a: case 0x52: case 0x5a:
|
||||
case 0x7a: case 0x84: case 0x94: case 0xa4:
|
||||
/* read-only memory range length / upper limit bit */
|
||||
val = (val & 0xfe) | (dev->current_ld->regs[dev->reg] & 0x01);
|
||||
break;
|
||||
|
||||
case 0x60: case 0x62: case 0x64: case 0x66: case 0x68: case 0x6a: case 0x6c: case 0x6e:
|
||||
/* discard upper address bits if this I/O range can only decode 10-bit */
|
||||
if (!(dev->current_ld->io_16bit & (1 << ((dev->reg >> 1) & 0x07))))
|
||||
val &= 0x07;
|
||||
break;
|
||||
|
||||
case 0x71: case 0x73:
|
||||
/* limit IRQ types to supported ones */
|
||||
if ((val & 0x01) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x0c : 0xc0))) /* level, not supported = force edge */
|
||||
val &= ~0x01;
|
||||
else if (!(val & 0x01) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x03 : 0x30))) /* edge, not supported = force level */
|
||||
val |= 0x01;
|
||||
|
||||
if ((val & 0x02) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x05 : 0x50))) /* high, not supported = force low */
|
||||
val &= ~0x02;
|
||||
else if (!(val & 0x02) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x0a : 0xa0))) /* low, not supported = force high */
|
||||
val |= 0x02;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
dev->current_ld->regs[dev->reg] = val;
|
||||
isapnp_device_config_changed(dev);
|
||||
isapnp_device_config_changed(dev->current_ld_card, dev->current_ld);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -604,14 +655,6 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
|
||||
|
||||
card->rom = rom;
|
||||
card->rom_size = rom_size;
|
||||
|
||||
/* Populate descriptor checksum in ROM. */
|
||||
uint16_t checksum_offset = card->rom_size - 1;
|
||||
card->rom[checksum_offset] = 0x00;
|
||||
for (uint16_t i = 9; i < checksum_offset; i++)
|
||||
card->rom[checksum_offset] += card->rom[i];
|
||||
card->rom[checksum_offset] = -card->rom[checksum_offset];
|
||||
|
||||
card->priv = priv;
|
||||
card->config_changed = config_changed;
|
||||
card->csn_changed = csn_changed;
|
||||
@@ -621,12 +664,198 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
|
||||
if (!dev->first_card) {
|
||||
dev->first_card = card;
|
||||
} else {
|
||||
isapnp_card_t *current_card = dev->first_card;
|
||||
while (current_card->next)
|
||||
current_card = current_card->next;
|
||||
current_card->next = card;
|
||||
isapnp_card_t *prev_card = dev->first_card;
|
||||
while (prev_card->next)
|
||||
prev_card = prev_card->next;
|
||||
prev_card->next = card;
|
||||
}
|
||||
|
||||
/* Parse resources in ROM to allocate logical devices,
|
||||
and determine the state of read-only register bits. */
|
||||
#ifdef ENABLE_ISAPNP_LOG
|
||||
uint16_t vendor = (card->rom[0] << 8) | card->rom[1];
|
||||
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 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;
|
||||
|
||||
while (i < card->rom_size) {
|
||||
if (card->rom[i] & 0x80) { /* large resource */
|
||||
res = card->rom[i] & 0x7f;
|
||||
len = (card->rom[i + 2] << 8) | card->rom[i + 1];
|
||||
|
||||
switch (res) {
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
isapnp_log("ISAPnP: >>%s 32-bit memory range %d uses upper limit = ", in_df ? ">" : "", mem_range_32);
|
||||
res = 1 << (4 + mem_range_32);
|
||||
mem_range_32++;
|
||||
}
|
||||
|
||||
if (card->rom[i + 3] & 0x4) {
|
||||
isapnp_log("yes\n");
|
||||
ld->mem_upperlimit |= res;
|
||||
} else {
|
||||
isapnp_log("no\n");
|
||||
ld->mem_upperlimit &= ~res;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_ISAPNP_LOG
|
||||
case 0x02: /* ANSI identifier */
|
||||
res = card->rom[i + 3 + len];
|
||||
card->rom[i + 3 + len] = '\0';
|
||||
isapnp_log("ISAPnP: >%s ANSI identifier: \"%s\"\n", ldn ? ">" : "", &card->rom[i + 3]);
|
||||
card->rom[i + 3 + len] = res;
|
||||
break;
|
||||
|
||||
default:
|
||||
isapnp_log("ISAPnP: >%s%s Large resource %02X (length %d)\n", ldn ? ">" : "", in_df ? ">" : "", res, (card->rom[i + 2] << 8) | card->rom[i + 1]);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
i += 3; /* header */
|
||||
} else { /* small resource */
|
||||
res = (card->rom[i] >> 3) & 0x0f;
|
||||
len = card->rom[i] & 0x07;
|
||||
|
||||
switch (res) {
|
||||
case 0x02:
|
||||
#ifdef ENABLE_ISAPNP_LOG
|
||||
vendor = (card->rom[i + 1] << 8) | card->rom[i + 2];
|
||||
isapnp_log("ISAPnP: > Logical device %02X: %c%c%c%02X%02X\n", ldn, '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[i + 3], card->rom[i + 4]);
|
||||
#endif
|
||||
|
||||
/* We're done with the previous logical device. */
|
||||
if (ld) {
|
||||
prev_ld = ld;
|
||||
isapnp_reset_ld_regs(ld);
|
||||
}
|
||||
|
||||
/* Create logical device. */
|
||||
ld = (isapnp_device_t *) malloc(sizeof(isapnp_device_t));
|
||||
memset(ld, 0, sizeof(isapnp_device_t));
|
||||
|
||||
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;
|
||||
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_ISAPNP_LOG
|
||||
case 0x03: /* compatible device ID */
|
||||
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 (len == 2) /* default */
|
||||
res = 0x01; /* high true edge sensitive */
|
||||
else /* specific */
|
||||
res = card->rom[i + 3] & 0x0f;
|
||||
|
||||
isapnp_log("ISAPnP: >>%s IRQ index %d interrupt types = %01X\n", in_df ? ">" : "", irq, res);
|
||||
|
||||
ld->irq_types &= ~(0x0f << (4 * irq));
|
||||
ld->irq_types |= res << (4 * irq);
|
||||
|
||||
irq++;
|
||||
|
||||
break;
|
||||
|
||||
case 0x06: /* start dependent function */
|
||||
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) {
|
||||
/* We're in a dependent function and this is the next one starting.
|
||||
Walk positions back to the saved values. */
|
||||
irq = irq_df;
|
||||
io = io_df;
|
||||
mem_range = mem_range_df;
|
||||
mem_range_32 = mem_range_32_df;
|
||||
} else {
|
||||
/* Save current positions to restore at the next DF. */
|
||||
irq_df = irq;
|
||||
io_df = io;
|
||||
mem_range_df = mem_range;
|
||||
mem_range_32_df = mem_range_32;
|
||||
in_df = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0x07: /* end dependent function */
|
||||
isapnp_log("ISAPnP: >> End dependent function\n");
|
||||
in_df = 0;
|
||||
break;
|
||||
|
||||
case 0x08: /* I/O port */
|
||||
if (io > 7)
|
||||
fatal("ISAPnP: I/O descriptor overflow (%d)\n", io);
|
||||
|
||||
isapnp_log("ISAPnP: >>%s I/O range %d %d-bit decode\n", in_df ? ">" : "", io, (card->rom[i + 1] & 0x01) ? 16 : 10);
|
||||
|
||||
if (card->rom[i + 1] & 0x01)
|
||||
ld->io_16bit |= 1 << io;
|
||||
else
|
||||
ld->io_16bit &= ~(1 << io);
|
||||
|
||||
io++;
|
||||
|
||||
break;
|
||||
|
||||
case 0x0f: /* end tag */
|
||||
/* Calculate checksum. */
|
||||
res = 0x00;
|
||||
for (j = 9; j <= i; j++)
|
||||
res += card->rom[j];
|
||||
card->rom[i + 1] = -res;
|
||||
|
||||
isapnp_log("ISAPnP: End card resources (checksum %02X)\n", card->rom[i + 1]);
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_ISAPNP_LOG
|
||||
default:
|
||||
isapnp_log("ISAPnP: >%s%s Small resource %02X (length %d)\n", ldn ? ">" : "", in_df ? ">" : "", res, card->rom[i] & 0x07);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
i++; /* header */
|
||||
}
|
||||
i += len; /* specified length */
|
||||
}
|
||||
|
||||
/* We're done with the last logical device. */
|
||||
if (ld)
|
||||
isapnp_reset_ld_regs(ld);
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,14 +24,16 @@ enum {
|
||||
DEV_AM79C960 = 1, /* PCnet-ISA (ISA, 10 Mbps, NE2100/NE1500T compatible) */
|
||||
DEV_AM79C960_EB = 2, /* PCnet-ISA (ISA, 10 Mbps, Racal InterLan EtherBlaster compatible) */
|
||||
DEV_AM79C960_VLB = 3, /* PCnet-VLB (VLB, 10 Mbps, NE2100/NE1500T compatible) */
|
||||
DEV_AM79C970A = 4, /* PCnet-PCI II (PCI, 10 Mbps) */
|
||||
DEV_AM79C973 = 5 /* PCnet-FAST III (PCI, 10/100 Mbps) */
|
||||
DEV_AM79C961 = 4, /* PCnet-ISA+ (ISA, 10 Mbps, NE2100/NE1500T compatible, Plug and Play) */
|
||||
DEV_AM79C970A = 5, /* PCnet-PCI II (PCI, 10 Mbps) */
|
||||
DEV_AM79C973 = 6 /* PCnet-FAST III (PCI, 10/100 Mbps) */
|
||||
};
|
||||
|
||||
|
||||
extern const device_t pcnet_am79c960_device;
|
||||
extern const device_t pcnet_am79c960_eb_device;
|
||||
extern const device_t pcnet_am79c960_vlb_device;
|
||||
extern const device_t pcnet_am79c961_device;
|
||||
extern const device_t pcnet_am79c970a_device;
|
||||
extern const device_t pcnet_am79c973_device;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ extern const device_t aha154xa_device;
|
||||
extern const device_t aha154xb_device;
|
||||
extern const device_t aha154xc_device;
|
||||
extern const device_t aha154xcf_device;
|
||||
extern const device_t aha154xcp_device;
|
||||
extern const device_t aha1640_device;
|
||||
|
||||
extern void aha_device_reset(void *p);
|
||||
|
||||
@@ -367,6 +367,7 @@ typedef struct {
|
||||
#define X54X_LBA_BIOS 4
|
||||
#define X54X_INT_GEOM_WRITABLE 8
|
||||
#define X54X_MBX_24BIT 16
|
||||
#define X54X_ISAPNP 32
|
||||
|
||||
typedef struct {
|
||||
/* 32 bytes */
|
||||
@@ -401,7 +402,8 @@ typedef struct {
|
||||
CmdBuf[128],
|
||||
DataBuf[65536],
|
||||
shadow_ram[128],
|
||||
dma_buffer[128];
|
||||
dma_buffer[128],
|
||||
cmd_33_buf[4096];
|
||||
|
||||
/* 16 bytes */
|
||||
char *fw_rev; /* The 4 bytes of the revision command information + 2 extra bytes for BusLogic */
|
||||
@@ -415,7 +417,11 @@ typedef struct {
|
||||
rom_ioaddr, /* offset in BIOS of I/O addr */
|
||||
rom_shram, /* index to shared RAM */
|
||||
rom_shramsz, /* size of shared RAM */
|
||||
rom_fwhigh; /* offset in BIOS of ver ID */
|
||||
rom_fwhigh, /* offset in BIOS of ver ID */
|
||||
pnp_len, /* length of the PnP ROM */
|
||||
pnp_offset, /* offset in the microcode ROM of the PnP ROM */
|
||||
cmd_33_len, /* length of the SCSISelect code decompressor program */
|
||||
cmd_33_offset; /* offset in the microcode ROM of the SCSISelect code decompressor program */
|
||||
|
||||
/* 16 + 20 + 52 = 88 bytes */
|
||||
volatile int
|
||||
@@ -445,6 +451,7 @@ typedef struct {
|
||||
|
||||
/* 8 bytes */
|
||||
wchar_t *bios_path, /* path to BIOS image file */
|
||||
*mcode_path, /* path to microcode image file, needed by the AHA-1542CP */
|
||||
*nvr_path; /* path to NVR image file */
|
||||
|
||||
/* 56 bytes */
|
||||
|
||||
@@ -126,6 +126,8 @@ typedef struct sb_t
|
||||
int pos;
|
||||
|
||||
uint8_t pos_regs[8];
|
||||
|
||||
uint16_t opl_pnp_addr;
|
||||
} sb_t;
|
||||
|
||||
extern void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p);
|
||||
|
||||
@@ -68,13 +68,6 @@
|
||||
#include <86box/isapnp.h>
|
||||
|
||||
|
||||
enum {
|
||||
PNP_PHASE_WAIT_FOR_KEY = 0,
|
||||
PNP_PHASE_CONFIG,
|
||||
PNP_PHASE_ISOLATION,
|
||||
PNP_PHASE_SLEEP
|
||||
};
|
||||
|
||||
/* ROM BIOS file paths. */
|
||||
#define ROM_PATH_NE1000 L"roms/network/ne1000/ne1000.rom"
|
||||
#define ROM_PATH_NE2000 L"roms/network/ne2000/ne2000.rom"
|
||||
@@ -82,13 +75,25 @@ enum {
|
||||
#define ROM_PATH_RTL8029 L"roms/network/rtl8029as/rtl8029as.rom"
|
||||
|
||||
/* PCI info. */
|
||||
#define PNP_VENDID 0x4a8c /* Realtek, Inc */
|
||||
#define PCI_VENDID 0x10ec /* Realtek, Inc */
|
||||
#define PNP_DEVID 0x8019 /* RTL8029AS */
|
||||
#define PCI_DEVID 0x8029 /* RTL8029AS */
|
||||
#define PCI_REGSIZE 256 /* size of PCI space */
|
||||
|
||||
|
||||
static uint8_t rtl8019as_pnp_rom[] = {
|
||||
0x4a, 0x8c, 0x80, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, /* RTL8019, dummy checksum (filled in by isapnp_add_card) */
|
||||
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
|
||||
0x82, 0x22, 0x00, 'R', 'E', 'A', 'L', 'T', 'E', 'K', ' ', 'P', 'L', 'U', 'G', ' ', '&', ' ', 'P', 'L', 'A', 'Y', ' ', 'E', 'T', 'H', 'E', 'R', 'N', 'E', 'T', ' ', 'C', 'A', 'R', 'D', 0x00, /* ANSI identifier */
|
||||
|
||||
0x16, 0x4a, 0x8c, 0x80, 0x19, 0x02, 0x00, /* logical device RTL8019 */
|
||||
0x1c, 0x41, 0xd0, 0x80, 0xd6, /* compatible device PNP80D6 */
|
||||
0x47, 0x00, 0x20, 0x02, 0x80, 0x03, 0x20, 0x20, /* I/O 0x220-0x380, decodes 10-bit, 32-byte alignment, 32 addresses */
|
||||
0x23, 0x38, 0x9e, 0x01, /* IRQ 3/4/5/9/10/11/12/15, high true edge sensitive */
|
||||
|
||||
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
dp8390_t *dp8390;
|
||||
const char *name;
|
||||
@@ -108,7 +113,6 @@ typedef struct {
|
||||
void *pnp_card;
|
||||
uint8_t pnp_activate;
|
||||
uint8_t pnp_csnsav;
|
||||
uint64_t pnp_id;
|
||||
uint8_t maclocal[6]; /* configured MAC (local) address */
|
||||
|
||||
/* RTL8019AS/RTL8029AS registers */
|
||||
@@ -933,8 +937,6 @@ nic_init(const device_t *info)
|
||||
#ifdef ENABLE_NIC_LOG
|
||||
int i;
|
||||
#endif
|
||||
char *ansi_id = "REALTEK PLUG & PLAY ETHERNET CARD";
|
||||
uint64_t *eeprom_pnp_id;
|
||||
|
||||
/* Get the desired debug level. */
|
||||
#ifdef ENABLE_NIC_LOG
|
||||
@@ -1111,10 +1113,6 @@ nic_init(const device_t *info)
|
||||
/* Add device to the PCI bus, keep its slot number. */
|
||||
dev->card = pci_add_card(PCI_ADD_NORMAL,
|
||||
nic_pci_read, nic_pci_write, dev);
|
||||
} else {
|
||||
dev->pnp_id = PNP_DEVID;
|
||||
dev->pnp_id <<= 32LL;
|
||||
dev->pnp_id |= PNP_VENDID;
|
||||
}
|
||||
|
||||
/* Initialize the RTL8029 EEPROM. */
|
||||
@@ -1128,63 +1126,15 @@ nic_init(const device_t *info)
|
||||
dev->eeprom[0x7E] = (PCI_DEVID&0xff);
|
||||
dev->eeprom[0x77] =
|
||||
dev->eeprom[0x7B] =
|
||||
dev->eeprom[0x7F] = (dev->board == NE2K_RTL8019AS) ? (PNP_DEVID>>8) : (PCI_DEVID>>8);
|
||||
dev->eeprom[0x7F] = (PCI_DEVID>>8);
|
||||
dev->eeprom[0x78] =
|
||||
dev->eeprom[0x7C] = (PCI_VENDID&0xff);
|
||||
dev->eeprom[0x79] =
|
||||
dev->eeprom[0x7D] = (PCI_VENDID>>8);
|
||||
} else {
|
||||
eeprom_pnp_id = (uint64_t *) &dev->eeprom[0x12];
|
||||
*eeprom_pnp_id = dev->pnp_id;
|
||||
memcpy(&dev->eeprom[0x12], rtl8019as_pnp_rom, sizeof(rtl8019as_pnp_rom));
|
||||
|
||||
/* TAG: Plug and Play Version Number. */
|
||||
dev->eeprom[0x1B] = 0x0A; /* Item byte */
|
||||
dev->eeprom[0x1C] = 0x10; /* PnP version */
|
||||
dev->eeprom[0x1D] = 0x10; /* Vendor version */
|
||||
|
||||
/* TAG: ANSI Identifier String. */
|
||||
dev->eeprom[0x1E] = 0x82; /* Item byte */
|
||||
dev->eeprom[0x1F] = 0x22; /* Length bits 7-0 */
|
||||
dev->eeprom[0x20] = 0x00; /* Length bits 15-8 */
|
||||
memcpy(&dev->eeprom[0x21], ansi_id, 0x22);
|
||||
|
||||
/* TAG: Logical Device ID. */
|
||||
dev->eeprom[0x43] = 0x16; /* Item byte */
|
||||
dev->eeprom[0x44] = 0x4A; /* Logical device ID0 */
|
||||
dev->eeprom[0x45] = 0x8C; /* Logical device ID1 */
|
||||
dev->eeprom[0x46] = 0x80; /* Logical device ID2 */
|
||||
dev->eeprom[0x47] = 0x19; /* Logical device ID3 */
|
||||
dev->eeprom[0x48] = 0x02; /* Flag0 (02=BROM/disabled) */
|
||||
dev->eeprom[0x49] = 0x00; /* Flag 1 */
|
||||
|
||||
/* TAG: Compatible Device ID (NE2000) */
|
||||
dev->eeprom[0x4A] = 0x1C; /* Item byte */
|
||||
dev->eeprom[0x4B] = 0x41; /* Compatible ID0 */
|
||||
dev->eeprom[0x4C] = 0xD0; /* Compatible ID1 */
|
||||
dev->eeprom[0x4D] = 0x80; /* Compatible ID2 */
|
||||
dev->eeprom[0x4E] = 0xD6; /* Compatible ID3 */
|
||||
|
||||
/* TAG: I/O Format */
|
||||
dev->eeprom[0x4F] = 0x47; /* Item byte */
|
||||
dev->eeprom[0x50] = 0x00; /* I/O information */
|
||||
dev->eeprom[0x51] = 0x20; /* Min. I/O base bits 7-0 */
|
||||
dev->eeprom[0x52] = 0x02; /* Min. I/O base bits 15-8 */
|
||||
dev->eeprom[0x53] = 0x80; /* Max. I/O base bits 7-0 */
|
||||
dev->eeprom[0x54] = 0x03; /* Max. I/O base bits 15-8 */
|
||||
dev->eeprom[0x55] = 0x20; /* Base alignment */
|
||||
dev->eeprom[0x56] = 0x20; /* Range length */
|
||||
|
||||
/* TAG: IRQ Format. */
|
||||
dev->eeprom[0x57] = 0x23; /* Item byte */
|
||||
dev->eeprom[0x58] = 0x38; /* IRQ mask bits 7-0 */
|
||||
dev->eeprom[0x59] = 0x9E; /* IRQ mask bits 15-8 */
|
||||
dev->eeprom[0x5A] = 0x01; /* IRQ information */
|
||||
|
||||
/* TAG: END Tag */
|
||||
dev->eeprom[0x5B] = 0x79; /* Item byte */
|
||||
/* Checksum is filled in by isapnp_add_card */
|
||||
|
||||
dev->pnp_card = isapnp_add_card(&dev->eeprom[0x12], 75, nic_pnp_config_changed, nic_pnp_csn_changed, nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg, dev);
|
||||
dev->pnp_card = isapnp_add_card(&dev->eeprom[0x12], sizeof(rtl8019as_pnp_rom), nic_pnp_config_changed, nic_pnp_csn_changed, nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg, dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <86box/pic.h>
|
||||
#include <86box/random.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/isapnp.h>
|
||||
#include <86box/network.h>
|
||||
#include <86box/net_pcnet.h>
|
||||
#include <86box/bswap.h>
|
||||
@@ -80,7 +81,7 @@ typedef struct RTNETETHERHDR
|
||||
#define BCR_LED1 5
|
||||
#define BCR_LED2 6
|
||||
#define BCR_LED3 7
|
||||
#define BCR_RESERVED8 8
|
||||
#define BCR_SWCONFIG 8
|
||||
#define BCR_FDC 9
|
||||
/* 10 - 15 = reserved */
|
||||
#define BCR_IOBASEL 16 /* Reserved */
|
||||
@@ -189,6 +190,21 @@ typedef struct RTNETETHERHDR
|
||||
#define PHYSADDR(S,A) ((A) | (S)->GCUpperPhys)
|
||||
|
||||
|
||||
static const uint8_t am79c961_pnp_rom[] = {
|
||||
0x04, 0x96, 0x55, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, /* ADV55AA, dummy checksum (filled in by isapnp_add_card) */
|
||||
0x0a, 0x10, 0x00, /* PnP version 1.0, vendor version 0.0 */
|
||||
0x82, 0x1c, 0x00, 'A', 'M', 'D', ' ', 'E', 't', 'h', 'e', 'r', 'n', 'e', 't', ' ', 'N', 'e', 't', 'w', 'o', 'r', 'k', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r', /* ANSI identifier */
|
||||
|
||||
0x16, 0x04, 0x96, 0x55, 0xaa, 0x00, 0xbd, /* logical device ADV55AA, supports vendor-specific registers 0x38/0x3A/0x3B/0x3C/0x3D/0x3F */
|
||||
0x1c, 0x41, 0xd0, 0x82, 0x8c, /* compatible device PNP828C */
|
||||
0x47, 0x00, 0x00, 0x02, 0xe0, 0x03, 0x20, 0x18, /* I/O 0x200-0x3E0, decodes 10-bit, 32-byte alignment, 24 addresses */
|
||||
0x2a, 0xe8, 0x02, /* DMA 3/5/6/7, compatibility, no count by word, no count by byte, not bus master, 16-bit only */
|
||||
0x23, 0x38, 0x9e, 0x09, /* IRQ 3/4/5/9/10/11/12/15, low true level sensitive, high true edge sensitive */
|
||||
|
||||
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
mem_mapping_t mmio_mapping;
|
||||
const char *name;
|
||||
@@ -211,7 +227,7 @@ typedef struct {
|
||||
uint32_t GCRDRA;
|
||||
/** Address of the TX descriptor table (ring). Loaded at init. */
|
||||
uint32_t GCTDRA;
|
||||
uint8_t aPROM[16];
|
||||
uint8_t aPROM[256];
|
||||
uint16_t aCSR[CSR_MAX_REG];
|
||||
uint16_t aBCR[BCR_MAX_RAP];
|
||||
uint16_t aMII[MII_MAX_REG];
|
||||
@@ -885,6 +901,7 @@ pcnetSoftReset(nic_t *dev)
|
||||
case DEV_AM79C960:
|
||||
case DEV_AM79C960_EB:
|
||||
case DEV_AM79C960_VLB:
|
||||
case DEV_AM79C961:
|
||||
dev->aCSR[88] = 0x3003;
|
||||
dev->aCSR[89] = 0x0262;
|
||||
break;
|
||||
@@ -1751,10 +1768,6 @@ pcnetHardReset(nic_t *dev)
|
||||
dev->aBCR[BCR_LED2] = 0x0088;
|
||||
dev->aBCR[BCR_LED3] = 0x0090;
|
||||
|
||||
/* For ISA PnP cards, BCR8 reports IRQ/DMA (e.g. 0x0035 means IRQ 3, DMA 5). */
|
||||
if (dev->is_isa)
|
||||
dev->aBCR[8] = dev->dma_channel | (dev->base_irq << 4);
|
||||
|
||||
dev->aBCR[BCR_FDC] = 0x0000;
|
||||
dev->aBCR[BCR_BSBC] = 0x9001;
|
||||
dev->aBCR[BCR_EECAS] = 0x0002;
|
||||
@@ -2227,6 +2240,14 @@ pcnet_bcr_readw(nic_t *dev, uint16_t rap)
|
||||
} else
|
||||
val = 0xffff;
|
||||
break;
|
||||
|
||||
case BCR_SWCONFIG:
|
||||
if (dev->board == DEV_AM79C961)
|
||||
val = ((dev->base_irq & 0x0f) << 4) | (dev->dma_channel & 0x07);
|
||||
else
|
||||
val = 0xffff;
|
||||
break;
|
||||
|
||||
default:
|
||||
val = rap < BCR_MAX_RAP ? dev->aBCR[rap] : 0;
|
||||
break;
|
||||
@@ -2745,6 +2766,65 @@ pcnet_pci_read(int func, int addr, void *p)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
pcnet_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
|
||||
{
|
||||
if (ld)
|
||||
return;
|
||||
|
||||
nic_t *dev = (nic_t *) priv;
|
||||
|
||||
dev->base_address = 0;
|
||||
dev->base_irq = 0;
|
||||
dev->dma_channel = -1;
|
||||
|
||||
if (dev->base_address) {
|
||||
pcnet_ioremove(dev, dev->base_address, 0x20);
|
||||
dev->base_address = 0;
|
||||
}
|
||||
|
||||
if (config->activate) {
|
||||
dev->base_address = config->io[0].base;
|
||||
if (dev->base_address != ISAPNP_IO_DISABLED)
|
||||
pcnet_ioset(dev, dev->base_address, 0x20);
|
||||
|
||||
dev->base_irq = config->irq[0].irq;
|
||||
dev->dma_channel = config->dma[0].dma;
|
||||
if (dev->dma_channel == ISAPNP_DMA_DISABLED)
|
||||
dev->dma_channel = -1;
|
||||
|
||||
/* Update PnP register mirrors in ROM. */
|
||||
dev->aPROM[32] = dev->base_address >> 8;
|
||||
dev->aPROM[33] = dev->base_address;
|
||||
dev->aPROM[34] = dev->base_irq;
|
||||
dev->aPROM[35] = (config->irq[0].level << 1) | config->irq[0].type;
|
||||
dev->aPROM[36] = (dev->dma_channel == -1) ? ISAPNP_DMA_DISABLED : dev->dma_channel;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
pcnet_pnp_read_vendor_reg(uint8_t ld, uint8_t reg, void *priv)
|
||||
{
|
||||
nic_t *dev = (nic_t *) priv;
|
||||
|
||||
if (!ld && (reg == 0xf0))
|
||||
return dev->aPROM[50];
|
||||
else
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
static void
|
||||
pcnet_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv)
|
||||
{
|
||||
if (ld)
|
||||
return;
|
||||
|
||||
nic_t *dev = (nic_t *) priv;
|
||||
|
||||
if (reg == 0xf0)
|
||||
dev->aPROM[50] = val & 0x1f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes down the link temporarily if it's current status is up.
|
||||
*
|
||||
@@ -2942,6 +3022,8 @@ pcnet_init(const device_t *info)
|
||||
dev->aPROM[9] = 0x11;
|
||||
else if (dev->is_vlb)
|
||||
dev->aPROM[9] = 0x10;
|
||||
else if (dev->board == DEV_AM79C961)
|
||||
dev->aPROM[9] = 0x01;
|
||||
else
|
||||
dev->aPROM[9] = 0x00;
|
||||
|
||||
@@ -2981,6 +3063,18 @@ pcnet_init(const device_t *info)
|
||||
/* Add device to the PCI bus, keep its slot number. */
|
||||
dev->card = pci_add_card(PCI_ADD_NORMAL,
|
||||
pcnet_pci_read, pcnet_pci_write, dev);
|
||||
} else if (dev->board == DEV_AM79C961) {
|
||||
dev->dma_channel = -1;
|
||||
|
||||
/* Weird secondary checksum. The datasheet isn't clear on what
|
||||
role it might play with the PnP register mirrors before it. */
|
||||
for (c = 0, checksum = 0; c < 54; c++)
|
||||
checksum += dev->aPROM[c];
|
||||
|
||||
dev->aPROM[51] = checksum;
|
||||
|
||||
memcpy(&dev->aPROM[0x40], am79c961_pnp_rom, sizeof(am79c961_pnp_rom));
|
||||
isapnp_add_card(&dev->aPROM[0x40], sizeof(am79c961_pnp_rom), pcnet_pnp_config_changed, NULL, pcnet_pnp_read_vendor_reg, pcnet_pnp_write_vendor_reg, dev);
|
||||
} else {
|
||||
dev->base_address = device_get_config_hex16("base");
|
||||
dev->base_irq = device_get_config_int("irq");
|
||||
@@ -3164,7 +3258,7 @@ static const device_config_t pcnet_vlb_config[] =
|
||||
};
|
||||
|
||||
const device_t pcnet_am79c960_device = {
|
||||
"AMD Am79c960 (PCnet-ISA) ",
|
||||
"AMD PCnet-ISA ",
|
||||
DEVICE_AT | DEVICE_ISA,
|
||||
DEV_AM79C960,
|
||||
pcnet_init, pcnet_close, NULL,
|
||||
@@ -3173,7 +3267,7 @@ const device_t pcnet_am79c960_device = {
|
||||
};
|
||||
|
||||
const device_t pcnet_am79c960_eb_device = {
|
||||
"AMD Am79c960EB (PCnet-ISA) ",
|
||||
"Racal Interlan EtherBlaster",
|
||||
DEVICE_AT | DEVICE_ISA,
|
||||
DEV_AM79C960_EB,
|
||||
pcnet_init, pcnet_close, NULL,
|
||||
@@ -3182,7 +3276,7 @@ const device_t pcnet_am79c960_eb_device = {
|
||||
};
|
||||
|
||||
const device_t pcnet_am79c960_vlb_device = {
|
||||
"AMD Am79c960 (PCnet-VL) ",
|
||||
"AMD PCnet-VL",
|
||||
DEVICE_VLB,
|
||||
DEV_AM79C960_VLB,
|
||||
pcnet_init, pcnet_close, NULL,
|
||||
@@ -3190,8 +3284,17 @@ const device_t pcnet_am79c960_vlb_device = {
|
||||
pcnet_vlb_config
|
||||
};
|
||||
|
||||
const device_t pcnet_am79c961_device = {
|
||||
"AMD PCnet-ISA+",
|
||||
DEVICE_AT | DEVICE_ISA,
|
||||
DEV_AM79C961,
|
||||
pcnet_init, pcnet_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
pcnet_pci_config
|
||||
};
|
||||
|
||||
const device_t pcnet_am79c970a_device = {
|
||||
"AMD Am79c970a (PCnet-PCI II)",
|
||||
"AMD PCnet-PCI II",
|
||||
DEVICE_PCI,
|
||||
DEV_AM79C970A,
|
||||
pcnet_init, pcnet_close, NULL,
|
||||
@@ -3200,7 +3303,7 @@ const device_t pcnet_am79c970a_device = {
|
||||
};
|
||||
|
||||
const device_t pcnet_am79c973_device = {
|
||||
"AMD Am79c973 (PCnet-FAST)",
|
||||
"AMD PCnet-FAST III",
|
||||
DEVICE_PCI,
|
||||
DEV_AM79C973,
|
||||
pcnet_init, pcnet_close, NULL,
|
||||
|
||||
@@ -73,6 +73,7 @@ static netcard_t net_cards[] = {
|
||||
{ "none", NULL, NULL },
|
||||
{ "3c503", &threec503_device, NULL },
|
||||
{ "pcnetisa", &pcnet_am79c960_device, NULL },
|
||||
{ "pcnetisaplus", &pcnet_am79c961_device, NULL },
|
||||
{ "ne1k", &ne1000_device, NULL },
|
||||
{ "ne2k", &ne2000_device, NULL },
|
||||
{ "pcnetracal", &pcnet_am79c960_eb_device, NULL },
|
||||
|
||||
@@ -61,6 +61,7 @@ static SCSI_CARD scsi_cards[] = {
|
||||
{ "aha154xb", &aha154xb_device, },
|
||||
{ "aha154xc", &aha154xc_device, },
|
||||
{ "aha154xcf", &aha154xcf_device, },
|
||||
{ "aha154xcp", &aha154xcp_device, },
|
||||
{ "bt542b", &buslogic_542b_1991_device, },
|
||||
{ "bt542bh", &buslogic_device, },
|
||||
{ "bt545s", &buslogic_545s_device, },
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <86box/plat.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/isapnp.h>
|
||||
#include <86box/scsi.h>
|
||||
#include <86box/scsi_aha154x.h>
|
||||
#include <86box/scsi_x54x.h>
|
||||
@@ -70,6 +71,8 @@ uint16_t aha_ports[] = {
|
||||
0x0130, 0x0134, 0x0000, 0x0000
|
||||
};
|
||||
|
||||
static uint8_t *aha1542cp_pnp_rom = NULL;
|
||||
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct {
|
||||
@@ -309,6 +312,12 @@ aha_param_len(void *p)
|
||||
case CMD_MBENABLE:
|
||||
return 2;
|
||||
|
||||
case 0x39:
|
||||
return 3;
|
||||
|
||||
case 0x40:
|
||||
return 2;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -409,17 +418,47 @@ aha_cmds(void *p)
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x2C: /* AHA-1542CP sends this */
|
||||
dev->DataBuf[0] = 0x00;
|
||||
case 0x2C: /* Detect termination status */
|
||||
/* Bits 7,6 are termination status and must be 1,0 for the BIOS to work. */
|
||||
dev->DataBuf[0] = 0x40;
|
||||
dev->DataReplyLeft = 1;
|
||||
break;
|
||||
|
||||
case 0x33: /* AHA-1542CP sends this */
|
||||
case 0x2D: /* ???? - Returns two bytes according to the microcode */
|
||||
dev->DataBuf[0] = 0x00;
|
||||
dev->DataBuf[1] = 0x00;
|
||||
dev->DataBuf[2] = 0x00;
|
||||
dev->DataBuf[3] = 0x00;
|
||||
dev->DataReplyLeft = 256;
|
||||
dev->DataBuf[0] = 0x00;
|
||||
dev->DataReplyLeft = 2;
|
||||
break;
|
||||
|
||||
case 0x33: /* Send the SCSISelect code decompressor program */
|
||||
if (dev->cmd_33_len == 0x0000) {
|
||||
/* If we are on a controller without this command, return invalid command. */
|
||||
dev->DataReplyLeft = 0;
|
||||
dev->Status |= STAT_INVCMD;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We have to send (decompressor program length + 2 bytes of little endian size). */
|
||||
dev->DataReplyLeft = dev->cmd_33_len + 2;
|
||||
memset(dev->DataBuf, 0x00, dev->DataReplyLeft);
|
||||
dev->DataBuf[0] = dev->cmd_33_len & 0xff;
|
||||
dev->DataBuf[1] = (dev->cmd_33_len >> 8) & 0xff;
|
||||
memcpy(&(dev->DataBuf[2]), dev->cmd_33_buf, dev->cmd_33_len);
|
||||
break;
|
||||
|
||||
case 0x39: /* Receive 3 bytes: address high, address low, byte to write to that address. */
|
||||
/* Since we are not running the actual microcode, just log the received values
|
||||
(if logging is enabled) and break. */
|
||||
aha_log("aha_cmds(): Command 0x39: %02X -> %02X%02X\n",
|
||||
dev->CmdBuf[2], dev->CmdBuf[0], dev->CmdBuf[1]);
|
||||
break;
|
||||
|
||||
case 0x40: /* Receive 2 bytes: address high, address low, then return one byte from that
|
||||
address. */
|
||||
aha_log("aha_cmds(): Command 0x40: %02X%02X\n",
|
||||
dev->CmdBuf[0], dev->CmdBuf[1]);
|
||||
dev->DataReplyLeft = 1;
|
||||
dev->DataBuf[0] = 0xff;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -597,6 +636,94 @@ aha_mca_feedb(void *priv)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aha_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
|
||||
{
|
||||
x54x_t *dev = (x54x_t *) priv;
|
||||
int i;
|
||||
|
||||
switch (ld) {
|
||||
case 0:
|
||||
if (dev->Base) {
|
||||
x54x_io_remove(dev, dev->Base, 4);
|
||||
dev->Base = 0;
|
||||
}
|
||||
|
||||
dev->Irq = 0;
|
||||
dev->DmaChannel = ISAPNP_DMA_DISABLED;
|
||||
dev->rom_addr = 0;
|
||||
|
||||
mem_mapping_disable(&dev->bios.mapping);
|
||||
|
||||
if (config->activate) {
|
||||
dev->Base = config->io[0].base;
|
||||
if (dev->Base != ISAPNP_IO_DISABLED)
|
||||
x54x_io_set(dev, dev->Base, 4);
|
||||
|
||||
/*
|
||||
* Patch the ROM BIOS image for stuff Adaptec deliberately
|
||||
* made hard to understand. Well, maybe not, maybe it was
|
||||
* their way of handling issues like these at the time..
|
||||
*
|
||||
* Patch 1: emulate the I/O ADDR SW setting by patching a
|
||||
* byte in the BIOS that indicates the I/O ADDR
|
||||
* switch setting on the board.
|
||||
*/
|
||||
if (dev->rom_ioaddr != 0x0000) {
|
||||
/* Look up the I/O address in the table. */
|
||||
for (i=0; i<8; i++)
|
||||
if (aha_ports[i] == dev->Base) break;
|
||||
if (i == 8) {
|
||||
aha_log("%s: invalid I/O address %04x selected!\n",
|
||||
dev->name, dev->Base);
|
||||
return;
|
||||
}
|
||||
dev->bios.rom[dev->rom_ioaddr] = (uint8_t)i;
|
||||
/* Negation of the DIP switches to satify the checksum. */
|
||||
dev->bios.rom[dev->rom_ioaddr + 1] = (uint8_t)((i ^ 0xff) + 1);
|
||||
}
|
||||
|
||||
dev->Irq = config->irq[0].irq;
|
||||
dev->DmaChannel = config->dma[0].dma;
|
||||
|
||||
dev->nvr[1] = (dev->Irq - 9) | (dev->DmaChannel << 4);
|
||||
aha_eeprom_save(dev);
|
||||
|
||||
dev->rom_addr = config->mem[0].base;
|
||||
if (dev->rom_addr) {
|
||||
mem_mapping_enable(&dev->bios.mapping);
|
||||
aha_log("SCSI BIOS set to: %08X-%08X\n", dev->rom_addr, dev->rom_addr + config->mem[0].size - 1);
|
||||
mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, config->mem[0].size);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
#ifdef AHA1542CP_FDC
|
||||
case 1:
|
||||
if (dev->fdc_address) {
|
||||
fdc_remove(dev->fdc);
|
||||
dev->fdc_address = 0;
|
||||
}
|
||||
|
||||
fdc_set_irq(dev->fdc, 0);
|
||||
fdc_set_dma_ch(dev->fdc, ISAPNP_DMA_DISABLED);
|
||||
|
||||
if (config->activate) {
|
||||
dev->fdc_address = config->io[0].base;
|
||||
if (dev->fdc_address != ISAPNP_IO_DISABLED)
|
||||
fdc_set_base(dev->fdc, dev->fdc_address);
|
||||
|
||||
fdc_set_irq(dev->fdc, config->irq[0].irq);
|
||||
fdc_set_dma_ch(dev->fdc, config->dma[0].dma);
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the board's ROM BIOS. */
|
||||
static void
|
||||
aha_setbios(x54x_t *dev)
|
||||
@@ -705,6 +832,68 @@ aha_setbios(x54x_t *dev)
|
||||
}
|
||||
|
||||
|
||||
/* Get the SCSISelect code decompressor program from the microcode rom for the
|
||||
AHA-1542CP. */
|
||||
static void
|
||||
aha_setmcode(x54x_t *dev)
|
||||
{
|
||||
uint32_t temp;
|
||||
FILE *f;
|
||||
|
||||
/* Only if this device has a BIOS ROM. */
|
||||
if (dev->mcode_path == NULL) return;
|
||||
|
||||
/* Open the microcode image file and make sure it exists. */
|
||||
aha_log("%s: loading microcode from '%ls'\n", dev->name, dev->bios_path);
|
||||
if ((f = rom_fopen(dev->mcode_path, L"rb")) == NULL) {
|
||||
aha_log("%s: microcode ROM not found!\n", dev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Manually load and process the ROM image.
|
||||
*
|
||||
* We *could* use the system "rom_init" function here, but for
|
||||
* this special case, we can't: we may need WRITE access to the
|
||||
* memory later on.
|
||||
*/
|
||||
(void)fseek(f, 0L, SEEK_END);
|
||||
temp = ftell(f);
|
||||
(void)fseek(f, 0L, SEEK_SET);
|
||||
|
||||
if (temp < (dev->cmd_33_offset + dev->cmd_33_len - 1)) {
|
||||
aha_log("%s: microcode ROM size invalid!\n", dev->name);
|
||||
(void)fclose(f);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate the buffer and then read the real PnP ROM into it. */
|
||||
if (aha1542cp_pnp_rom != NULL) {
|
||||
free(aha1542cp_pnp_rom);
|
||||
aha1542cp_pnp_rom = NULL;
|
||||
}
|
||||
aha1542cp_pnp_rom = (uint8_t *) malloc(dev->pnp_len + 7);
|
||||
fseek(f, dev->pnp_offset, SEEK_SET);
|
||||
(void)fread(aha1542cp_pnp_rom, dev->pnp_len, 1, f);
|
||||
memset(&(aha1542cp_pnp_rom[4]), 0x00, 5);
|
||||
fseek(f, dev->pnp_offset + 4, SEEK_SET);
|
||||
(void)fread(&(aha1542cp_pnp_rom[9]), dev->pnp_len - 4, 1, f);
|
||||
/* Even the real AHA-1542CP microcode seem to be flipping bit
|
||||
4 to not erroneously indicate there is a range length. */
|
||||
aha1542cp_pnp_rom[0x87] |= 0x04;
|
||||
/* Insert the terminator and the checksum byte that will later
|
||||
be filled in by the isapnp code. */
|
||||
aha1542cp_pnp_rom[dev->pnp_len + 5] = 0x79;
|
||||
aha1542cp_pnp_rom[dev->pnp_len + 6] = 0x00;
|
||||
|
||||
/* Load the SCSISelect decompression code. */
|
||||
fseek(f, dev->cmd_33_offset, SEEK_SET);
|
||||
(void)fread(dev->cmd_33_buf, dev->cmd_33_len, 1, f);
|
||||
|
||||
(void)fclose(f);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
aha_initnvr(x54x_t *dev)
|
||||
{
|
||||
@@ -755,6 +944,18 @@ aha_setnvr(x54x_t *dev)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
aha1542cp_close(void *priv)
|
||||
{
|
||||
if (aha1542cp_pnp_rom != NULL) {
|
||||
free(aha1542cp_pnp_rom);
|
||||
aha1542cp_pnp_rom = NULL;
|
||||
}
|
||||
|
||||
x54x_close(priv);
|
||||
}
|
||||
|
||||
|
||||
/* General initialization routine for all boards. */
|
||||
static void *
|
||||
aha_init(const device_t *info)
|
||||
@@ -791,6 +992,11 @@ aha_init(const device_t *info)
|
||||
dev->ven_cmds = aha_cmds;
|
||||
dev->get_ven_data = aha_setup_data;
|
||||
|
||||
dev->mcode_path = NULL;
|
||||
dev->cmd_33_len = 0x0000;
|
||||
dev->cmd_33_offset = 0x0000;
|
||||
memset(dev->cmd_33_buf, 0x00, 4096);
|
||||
|
||||
strcpy(dev->vendor, "Adaptec");
|
||||
|
||||
/* Perform per-board initialization. */
|
||||
@@ -851,7 +1057,7 @@ aha_init(const device_t *info)
|
||||
dev->rom_shramsz = 128; /* size of shadow RAM */
|
||||
dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */
|
||||
dev->rom_fwhigh = 0x0022; /* firmware version (hi/lo) */
|
||||
dev->flags |= X54X_CDROM_BOOT;
|
||||
dev->flags |= X54X_CDROM_BOOT;
|
||||
dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */
|
||||
dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */
|
||||
dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */
|
||||
@@ -863,16 +1069,31 @@ aha_init(const device_t *info)
|
||||
case AHA_154xCP:
|
||||
strcpy(dev->name, "AHA-154xCP");
|
||||
dev->bios_path = L"roms/scsi/adaptec/aha1542cp102.bin";
|
||||
dev->nvr_path = L"aha1540cp.nvr";
|
||||
dev->mcode_path = L"roms/scsi/adaptec/908301-00_f_mcode_17c9.u12";
|
||||
dev->nvr_path = L"aha1542cp.nvr";
|
||||
dev->fw_rev = "F001";
|
||||
dev->rom_shram = 0x3F80; /* shadow RAM address base */
|
||||
dev->rom_shramsz = 128; /* size of shadow RAM */
|
||||
dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */
|
||||
dev->rom_fwhigh = 0x0055; /* firmware version (hi/lo) */
|
||||
dev->flags |= X54X_CDROM_BOOT;
|
||||
dev->flags |= X54X_ISAPNP;
|
||||
dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */
|
||||
dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */
|
||||
dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */
|
||||
dev->ha_bps = 10000000.0; /* fast SCSI */
|
||||
dev->ha_bps = 10000000.0; /* fast SCSI */
|
||||
dev->pnp_len = 0x00be; /* length of the PnP ROM */
|
||||
dev->pnp_offset = 0x533d; /* offset of the PnP ROM in the microcode ROM */
|
||||
dev->cmd_33_len = 0x06dc; /* length of the SCSISelect code expansion routine returned by
|
||||
SCSI controller command 0x33 */
|
||||
dev->cmd_33_offset = 0x7000; /* offset of the SCSISelect code expansion routine in the
|
||||
microcode ROM */
|
||||
aha_setmcode(dev);
|
||||
if (aha1542cp_pnp_rom)
|
||||
isapnp_add_card(aha1542cp_pnp_rom, dev->pnp_len + 7, aha_pnp_config_changed, NULL, NULL, NULL, dev);
|
||||
#ifdef AHA1542CP_FDC
|
||||
dev->fdc = device_add(&fdc_at_device);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case AHA_1640:
|
||||
@@ -900,7 +1121,7 @@ aha_init(const device_t *info)
|
||||
/* Initialize the device. */
|
||||
x54x_device_reset(dev);
|
||||
|
||||
if (!(dev->bus & DEVICE_MCA)) {
|
||||
if (!(dev->bus & DEVICE_MCA) && !(dev->flags & X54X_ISAPNP)) {
|
||||
/* Register our address space. */
|
||||
x54x_io_set(dev, dev->Base, 4);
|
||||
|
||||
@@ -1297,6 +1518,15 @@ const device_t aha154xcf_device = {
|
||||
aha_154xcf_config
|
||||
};
|
||||
|
||||
const device_t aha154xcp_device = {
|
||||
"Adaptec AHA-154xCP",
|
||||
DEVICE_ISA | DEVICE_AT,
|
||||
AHA_154xCP,
|
||||
aha_init, aha1542cp_close, NULL,
|
||||
{ NULL }, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t aha1640_device = {
|
||||
"Adaptec AHA-1640",
|
||||
DEVICE_MCA,
|
||||
|
||||
@@ -92,6 +92,8 @@ x54x_irq(x54x_t *dev, int set)
|
||||
else
|
||||
pci_clear_irq(dev->pci_slot, PCI_INTA);
|
||||
} else {
|
||||
x54x_log("%sing IRQ %i\n", set ? "Rais" : "Lower", irq);
|
||||
|
||||
if (set) {
|
||||
if (dev->interrupt_type)
|
||||
int_type = dev->interrupt_type(dev);
|
||||
@@ -961,7 +963,7 @@ x54x_scsi_cmd(x54x_t *dev)
|
||||
else
|
||||
dev->callback_sub_phase = 2;
|
||||
|
||||
x54x_log("scsi_devices[%02i].Status = %02X\n", id, sd->status);
|
||||
x54x_log("scsi_devices[%02i].Status = %02X\n", req->TargetID, sd->status);
|
||||
}
|
||||
|
||||
|
||||
@@ -1310,7 +1312,7 @@ x54x_cmd_callback(void *priv)
|
||||
|
||||
period = (1000000.0 / dev->ha_bps) * ((double) dev->temp_period);
|
||||
timer_on(&dev->timer, dev->media_period + period + 10.0, 0);
|
||||
x54x_log("Temporary period: %lf us (%" PRIi64 " periods)\n", dev->timer.period, dev->temp_period);
|
||||
// x54x_log("Temporary period: %lf us (%" PRIi64 " periods)\n", dev->timer.period, dev->temp_period);
|
||||
}
|
||||
|
||||
|
||||
@@ -1371,6 +1373,13 @@ x54x_in(uint16_t port, void *priv)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_X54X_LOG
|
||||
if (port == 0x0332)
|
||||
x54x_log("x54x_in(): %04X, %02X, %08X\n", port, ret, dev->DataReplyLeft);
|
||||
else
|
||||
x54x_log("x54x_in(): %04X, %02X\n", port, ret);
|
||||
#endif
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,10 +74,10 @@ static const int sb_pro_mcv_irqs[4] = {7, 5, 3, 3};
|
||||
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 */
|
||||
0x82, 0x11, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x53, 0x42, 0x31, 0x36, 0x20, 0x50, 0x6e, 0x50, /* ANSI identifier "Creative SB16 PnP" */
|
||||
0x82, 0x11, 0x00, 'C', 'r', 'e', 'a', 't', 'i', 'v', 'e', ' ', 'S', 'B', '1', '6', ' ', 'P', 'n', 'P', /* ANSI identifier */
|
||||
|
||||
0x15, 0x0e, 0x8c, 0x00, 0x31, 0x00, /* logical device CTL0031 */
|
||||
0x82, 0x05, 0x00, 0x41, 0x75, 0x64, 0x69, 0x6f, /* ANSI identifier "Audio" */
|
||||
0x82, 0x05, 0x00, 'A', 'u', 'd', 'i', 'o', /* ANSI identifier */
|
||||
0x30, /* start dependent functions, acceptable */
|
||||
0x22, 0xa0, 0x04, /* IRQ 5/7/10 */
|
||||
0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */
|
||||
@@ -86,18 +86,19 @@ static uint8_t sb_16_pnp_rom[] = {
|
||||
0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */
|
||||
0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */
|
||||
0x38, /* end dependent functions */
|
||||
|
||||
0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */
|
||||
};
|
||||
static uint8_t sb_awe32_pnp_rom[] = {
|
||||
0x0e, 0x8c, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL009C, dummy checksum (filled in by isapnp_add_card) */
|
||||
0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */
|
||||
0x82, 0x11, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x53, 0x42, 0x33, 0x32, 0x20, 0x50, 0x6e, 0x50, /* ANSI identifier "Creative SB32 PnP" */
|
||||
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 */
|
||||
0x82, 0x05, 0x00, 0x41, 0x75, 0x64, 0x69, 0x6f, /* ANSI identifier "Audio" */
|
||||
0x16, 0x0e, 0x8c, 0x00, 0x41, 0x00, 0xa9, /* logical device CTL0041, 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 */
|
||||
0x2a, 0x01, 0x0c, /* DMA 1, compatibility, no count by word, count by byte, is bus master, 8-bit only */
|
||||
0x2a, 0x02, 0x0c, /* DMA 1, compatibility, no count by word, count by byte, is bus master, 8-bit only */
|
||||
0x2a, 0x20, 0x16, /* DMA 5, compatibility, count by word, no count by byte, is bus master, 16-bit only */
|
||||
0x47, 0x01, 0x20, 0x02, 0x20, 0x02, 0x01, 0x10, /* I/O 0x220, decodes 16-bit, 1-byte alignment, 16 addresses */
|
||||
0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x01, 0x02, /* I/O 0x330, decodes 16-bit, 1-byte alignment, 2 addresses */
|
||||
@@ -144,8 +145,8 @@ static uint8_t sb_awe32_pnp_rom[] = {
|
||||
0x47, 0x01, 0x88, 0x03, 0x94, 0x03, 0x04, 0x04, /* I/O 0x388-0x394, decodes 16-bit, 4-byte alignment, 4 addresses */
|
||||
0x38, /* end dependent functions */
|
||||
|
||||
0x16, 0x0e, 0x8c, 0x00, 0x21, 0x00, 0xa9, /* logical device CTL0021, supports vendor-specific registers 0x38/0x3a/0x3c/0x3f */
|
||||
0x82, 0x09, 0x00, 0x57, 0x61, 0x76, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, /* ANSI identifier "WaveTable" */
|
||||
0x16, 0x0e, 0x8c, 0x00, 0x21, 0x00, 0xa9, /* logical device CTL0021, supports vendor-specific registers 0x38/0x3A/0x3C/0x3F */
|
||||
0x82, 0x09, 0x00, 'W', 'a', 'v', 'e', 'T', 'a', 'b', 'l', 'e', /* ANSI identifier */
|
||||
0x31, 0x00, /* start dependent functions, preferred */
|
||||
0x47, 0x01, 0x20, 0x06, 0x20, 0x06, 0x01, 0x04, /* I/O 0x620, decodes 16-bit, 1-byte alignment, 4 addresses */
|
||||
0x30, /* start dependent functions, acceptable */
|
||||
@@ -1131,15 +1132,20 @@ sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
|
||||
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);
|
||||
|
||||
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, 0);
|
||||
sb_dsp_setdma16(&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);
|
||||
|
||||
@@ -1161,9 +1167,11 @@ sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
|
||||
mpu401_change_addr(sb->mpu, addr);
|
||||
|
||||
addr = config->io[2].base;
|
||||
if (addr != ISAPNP_IO_DISABLED)
|
||||
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL,
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user