From ae369dc34d8b9b43b112b1435dedaa4c18eb6070 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 25 Sep 2025 00:58:53 +0200 Subject: [PATCH] RTL8019AS and ISA PnP: More fixes. --- src/device/isapnp.c | 103 +++++++++++++++++++++++++++++-------- src/include/86box/isapnp.h | 3 ++ src/network/net_ne2000.c | 86 ++++++++++++++++++++++--------- 3 files changed, 147 insertions(+), 45 deletions(-) diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 675d9adf7..46cd52c24 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -98,6 +98,8 @@ typedef struct _isapnp_card_ { uint8_t serial_read_pair; uint8_t serial_read_pos; uint8_t is_rt; + uint8_t normal; + uint8_t multiple_lds; uint8_t *rom; uint16_t rom_pos; uint16_t rom_size; @@ -449,15 +451,16 @@ isapnp_write_addr(UNUSED(uint16_t addr), uint8_t val, void *priv) if (!dev->key_pos) { isapnp_log("ISAPnP: Key unlocked, putting cards to SLEEP\n"); while (card) { - int is_rt = (!dev->using_key2 || card->is_rt); - if (card->enable && is_rt && (card->enable != ISAPNP_CARD_NO_KEY) && (card->state == PNP_STATE_WAIT_FOR_KEY)) + int match_rt = (dev->using_key2 && card->is_rt); + int match_normal = (!dev->using_key2 && card->normal); + if (card->enable && (match_rt || match_normal) && + (card->enable != ISAPNP_CARD_NO_KEY) && (card->state == PNP_STATE_WAIT_FOR_KEY)) card->state = PNP_STATE_SLEEP; card = card->next; } } - } else { + } else dev->key_pos = 0; - } } } @@ -527,8 +530,22 @@ isapnp_write_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uin if (card->csn == val) { card->rom_pos = 0; card->id_checksum = isapnp_init_key[0]; - if (card->state == PNP_STATE_SLEEP) + if (card->state == PNP_STATE_SLEEP) { card->state = (val == 0) ? PNP_STATE_ISOLATION : PNP_STATE_CONFIG; + + if (!card->multiple_lds) { + ld = card->first_ld; + while (ld) { + if (ld->number == 0x00) { + isapnp_log("ISAPnP: Select CSN %02X device 00\n", card->csn); + dev->current_ld_card = card; + dev->current_ld = ld; + break; + } + ld = ld->next; + } + } + } } else card->state = PNP_STATE_SLEEP; @@ -549,27 +566,28 @@ isapnp_write_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uin break; case 0x07: /* Logical Device Number */ - CHECK_CURRENT_CARD(); + if (card->multiple_lds) { + CHECK_CURRENT_CARD(); - card->ld = val; - ld = card->first_ld; - while (ld) { - if (ld->number == val) { - isapnp_log("ISAPnP: Select CSN %02X device %02X\n", card->csn, val); - dev->current_ld_card = card; - dev->current_ld = ld; - break; + card->ld = val; + ld = card->first_ld; + while (ld) { + if (ld->number == val) { + isapnp_log("ISAPnP: Select CSN %02X device %02X\n", card->csn, val); + dev->current_ld_card = card; + dev->current_ld = ld; + break; + } + ld = ld->next; } - ld = ld->next; - } - if (!ld) { - isapnp_log("ISAPnP: CSN %02X has no device %02X, creating one\n", card->csn, val); - dev->current_ld_card = card; - dev->current_ld = isapnp_create_ld(card); - dev->current_ld->number = val; + if (!ld) { + isapnp_log("ISAPnP: CSN %02X has no device %02X, creating one\n", card->csn, val); + dev->current_ld_card = card; + dev->current_ld = isapnp_create_ld(card); + dev->current_ld->number = val; + } } - break; case 0x30: /* Activate */ @@ -759,11 +777,13 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, isapnp_card_t *card = (isapnp_card_t *) calloc(1, sizeof(isapnp_card_t)); card->enable = 1; + card->normal = 1; card->priv = priv; card->config_changed = config_changed; card->csn_changed = csn_changed; card->read_vendor_reg = read_vendor_reg; card->write_vendor_reg = write_vendor_reg; + card->multiple_lds = 1; if (!dev->first_card) { dev->first_card = card; @@ -1201,6 +1221,45 @@ isapnp_set_rt(void *priv, uint8_t is_rt) card->is_rt = is_rt; } +void +isapnp_set_normal(void *priv, uint8_t normal) +{ + isapnp_card_t *card = (isapnp_card_t *) priv; + + card->normal = normal; +} + +void +isapnp_activate(void *priv, uint16_t base, uint8_t irq) +{ + isapnp_card_t *card = (isapnp_card_t *) priv; + isapnp_device_t *ld = card->first_ld; + + while (ld) { + if (ld->number == 0x00) + break; + ld = ld->next; + } + + if (ld != NULL) { + ld->regs[0x30] = 0x01; + ld->regs[0x60] = base >> 4; + if (!(ld->io_16bit & (1 << ((0x60 >> 1) & 0x07)))) + ld->regs[0x60] &= 0x03; + ld->regs[0x61] = base & 0x0f; + ld->regs[0x70] = irq; + } +} + +void +isapnp_set_single_ld(void *priv) +{ + isapnp_card_t *card = (isapnp_card_t *) priv; + + card->multiple_lds = 0; + card->ld = 0x00; +} + uint8_t * isapnp_get_csnsav(void *priv) { diff --git a/src/include/86box/isapnp.h b/src/include/86box/isapnp.h index 2ffbd2d66..7d730564a 100644 --- a/src/include/86box/isapnp.h +++ b/src/include/86box/isapnp.h @@ -72,6 +72,9 @@ extern void isapnp_set_device_defaults(void *priv, uint8_t ldn, const isapnp extern void isapnp_reset_card(void *priv); extern void isapnp_reset_device(void *priv, uint8_t ld); extern void isapnp_set_rt(void *priv, uint8_t is_rt); +extern void isapnp_set_normal(void *priv, uint8_t normal); +extern void isapnp_activate(void *priv, uint16_t base, uint8_t irq); +extern void isapnp_set_single_ld(void *priv); extern uint8_t *isapnp_get_csnsav(void *priv); #endif /*EMU_ISAPNP_H*/ diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index d7e4e28a0..2a9f3f551 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -69,6 +69,7 @@ #include <86box/isapnp.h> #include <86box/plat_fallthrough.h> #include <86box/plat_unused.h> +#include "cpu.h" /* ROM BIOS file paths. */ #define ROM_PATH_NE1000 "roms/network/ne1000/ne1000.rom" @@ -340,7 +341,7 @@ page3_read(nic_t *dev, uint32_t off, UNUSED(unsigned int len)) case 0x3: /* CONFIG0 */ if (dev->board == NE2K_RTL8019AS_PNP) - ret = (dev->config0 & 0xc0) | 0x10; /* Cable not BNC */ + ret = dev->config0; else ret = 0x00; /* Cable not BNC */ break; @@ -418,20 +419,20 @@ page3_write(nic_t *dev, uint32_t off, uint32_t val, UNUSED(unsigned len)) if ((val & 0xc0) == 0x80) nmc93cxx_eeprom_write(dev->eeprom, !!(val & 0x08), !!(val & 0x04), !!(val & 0x02)); else if ((val & 0xc0) == 0x40) { - uint8_t *data = (uint8_t *) nmc93cxx_eeprom_data(dev->eeprom); + uint8_t *data = (uint8_t *) nmc93cxx_eeprom_data(dev->eeprom); - data[0x00] = 0x80; - data[0x01] = 0x00; - data[0x02] = 0x80; - data[0x03] = 0x00; + dev->config1 = (data[0x00] & 0x7f) | 0x80; + dev->config2 = (data[0x01] & 0xdf); + dev->config3 = (data[0x02] & 0x77) | 0x80; + dev->_9346cr = 0x21; - dev->_9346cr = 0x21; + isapnp_set_normal(dev->pnp_card, !!(dev->config3 & 0x80)); } break; case 0x03: /* CONFIG0 */ if (cfg_write_enable && (dev->board == NE2K_RTL8019AS_PNP)) - dev->config0 = (val & 0xc0); + dev->config0 = (dev->config0 & 0x3f) | (val & 0xc0); break; case 0x04: /* CONFIG1 */ @@ -442,7 +443,7 @@ page3_write(nic_t *dev, uint32_t off, uint32_t val, UNUSED(unsigned len)) case 0x05: /* CONFIG2 */ if (cfg_write_enable) { if (dev->board == NE2K_RTL8019AS_PNP) - dev->config2 = val; + dev->config2 = (dev->config2 & 0x1f) | (val & 0xe0); else dev->config2 = (val & 0xe0); } @@ -451,7 +452,7 @@ page3_write(nic_t *dev, uint32_t off, uint32_t val, UNUSED(unsigned len)) case 0x06: /* CONFIG3 */ if (cfg_write_enable) { if (dev->board == NE2K_RTL8019AS_PNP) - dev->config3 = val; + dev->config3 = (dev->config3 & 0xf9) | (val & 0x06); else dev->config3 = (val & 0x46); } @@ -582,9 +583,11 @@ static void nic_ioremove(nic_t *dev, uint16_t addr); static void nic_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { +#if 0 uint8_t irq_map[16] = { 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0x00, 0x00, 0x00, 0x40, 0x50, 0x60, 0x00, 0x00, 0x70 }; uint8_t ios = 0x00; +#endif if (ld) return; @@ -600,18 +603,22 @@ nic_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) nic_interrupt(dev, 0); dev->base_irq = config->irq[0].irq; +#if 0 if ((dev->base_irq >= 0x00) && (dev->base_irq <= 0x0f)) dev->config1 = (dev->config1 & 0x8f) | irq_map[dev->base_irq]; else dev->config1 = (dev->config1 & 0x8f); +#endif if (config->activate && (dev->base_address != ISAPNP_IO_DISABLED)) { nic_ioset(dev, dev->base_address); +#if 0 ios |= (dev->base_address & 0x0100) ? 0x00 : 0x04; ios |= (dev->base_address & 0x0080) ? 0x08 : 0x00; ios |= (dev->base_address & 0x0040) ? 0x02 : 0x00; ios |= (dev->base_address & 0x0020) ? 0x01 : 0x00; dev->config1 = (dev->config1 & 0xf0) | ios; +#endif } } @@ -626,33 +633,38 @@ nic_pnp_csn_changed(uint8_t csn, void *priv) static uint8_t nic_pnp_read_vendor_reg(uint8_t ld, uint8_t reg, void *priv) { - if (ld != 0) - return 0x00; + uint8_t ret = 0x00; const nic_t *dev = (nic_t *) priv; - switch (reg) { + if (ld == 0) switch (reg) { + default: + break; + case 0xf0: /* CONFIG0 */ - return 0x00; /* Cable not BNC */ + ret = dev->config0; + break; case 0xf1: /* CONFIG1 */ - return dev->config1; + ret = dev->config1; break; case 0xf2: /* CONFIG2 */ - return dev->config2; + ret = dev->config2; + break; case 0xf3: /* CONFIG3 */ - return dev->config3; + ret = dev->config3; + break; case 0xf5: - return *dev->pnp_csnsav; - - default: + ret = *dev->pnp_csnsav; break; } - return 0x00; + nelog(3, "[R] Vendor register: %02X (LD = %02X) = %02X\n", reg, ld, ret); + + return ret; } static void @@ -660,6 +672,8 @@ nic_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv) { nic_t *dev = (nic_t *) priv; + nelog(3, "[W] Vendor register: %02X (LD = %02X) = %02X\n", reg, ld, val); + if ((ld == 0) && (reg == 0xf6) && (val & 0x04)) { uint8_t csn = *dev->pnp_csnsav; isapnp_set_csn(dev->pnp_card, 0); @@ -1307,7 +1321,7 @@ nic_init(const device_t *info) nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg, dev); dev->pnp_csnsav = isapnp_get_csnsav(dev->pnp_card); - dev->config0 = 0x00; + dev->config0 = 0x10 /* Cable not BNC */; dev->config1 = 0x80; dev->config2 = 0x00; dev->config3 = 0x80; @@ -1315,7 +1329,7 @@ nic_init(const device_t *info) dev->eeprom_data[0x00] = 0x80; dev->eeprom_data[0x01] = 0x00; - dev->eeprom_data[0x02] = 0x80; + dev->eeprom_data[0x02] = 0x81; dev->eeprom_data[0x03] = 0x01; memcpy(&dev->eeprom_data[0x04], dev->maclocal, 6); break; @@ -1340,6 +1354,32 @@ nic_init(const device_t *info) free(dev); return NULL; } + if (info->local == NE2K_RTL8019AS_PNP) { + uint8_t *data = (uint8_t *) nmc93cxx_eeprom_data(dev->eeprom); + + dev->config1 = (data[0x00] & 0x7f) | 0x80; + dev->config2 = (data[0x01] & 0xdf); + dev->config3 = (data[0x02] & 0xf7); + + isapnp_set_normal(dev->pnp_card, !!(dev->config3 & 0x80)); + isapnp_set_single_ld(dev->pnp_card); + + if (!(dev->config3 & 0x01)) { + uint8_t irq_map[8] = { 9, 3, 4, 5, 10, 11, 12, 15 }; + dev->base_address = 0x0000; + + dev->base_irq = irq_map[(dev->config1 >> 4) & 0x07]; + + dev->base_address = (dev->config1 & 0x01) ? 0x0020 : 0x0000; + dev->base_address |= (dev->config1 & 0x02) ? 0x0040 : 0x0000; + dev->base_address |= (dev->config1 & 0x04) ? 0x0000 : 0x0100; + dev->base_address |= (dev->config1 & 0x08) ? 0x0080 : 0x0000; + + nic_ioset(dev, dev->base_address); + + isapnp_activate(dev->pnp_card, dev->base_address, dev->base_irq); + } + } } if (dev->pnp_csnsav == NULL)