RTL8019AS and ISA PnP fixes: fixes PNPODI.COM. RTL8019AS now detects the card but thinks there's an IRQ conflict.

This commit is contained in:
OBattler
2025-09-24 15:16:59 +02:00
parent 087a005664
commit 01c410479b
5 changed files with 274 additions and 75 deletions

View File

@@ -25,6 +25,7 @@
#include <86box/io.h>
#include <86box/isapnp.h>
#include <86box/plat_unused.h>
#include "cpu.h"
#define CHECK_CURRENT_LD() \
if (!ld) { \
@@ -42,6 +43,11 @@ const uint8_t isapnp_init_key[32] = { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB
0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,
0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,
0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39 };
/* Required for the RTL8019AS. */
const uint8_t isapnp_init_key2[32] = { 0xDA, 0x6D, 0x36, 0x1B, 0x8D, 0x46, 0x23, 0x91,
0x48, 0xA4, 0xD2, 0x69, 0x34, 0x9A, 0x4D, 0x26,
0x13, 0x89, 0x44, 0xA2, 0x51, 0x28, 0x94, 0xCA,
0x65, 0x32, 0x19, 0x0C, 0x86, 0x43, 0xA1, 0x50 };
static const device_t isapnp_device;
#ifdef ENABLE_ISAPNP_LOG
@@ -85,11 +91,13 @@ typedef struct _isapnp_card_ {
uint8_t enable;
uint8_t state;
uint8_t csn;
uint8_t csnsav;
uint8_t ld;
uint8_t id_checksum;
uint8_t serial_read;
uint8_t serial_read_pair;
uint8_t serial_read_pos;
uint8_t is_rt;
uint8_t *rom;
uint16_t rom_pos;
uint16_t rom_size;
@@ -109,6 +117,7 @@ typedef struct _isapnp_card_ {
typedef struct {
uint8_t in_isolation;
uint8_t using_key2;
uint8_t reg;
uint8_t key_pos : 5;
uint16_t read_data_addr;
@@ -166,7 +175,7 @@ isapnp_device_config_changed(isapnp_card_t *card, isapnp_device_t *ld)
}
for (uint8_t i = 0; i < 8; i++) {
reg_base = 0x60 + (2 * i);
if (ld->regs[0x31] & 0x02)
if (!(ld->regs[0x30] & 0x01) && (ld->regs[0x31] & 0x02))
card->config.io[i].base = 0; /* let us handle I/O range check reads */
else
card->config.io[i].base = (ld->regs[reg_base] << 8) | ld->regs[reg_base + 1];
@@ -288,7 +297,7 @@ isapnp_read_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uint
case 0x01: /* Serial Isolation */
card = dev->first_card;
while (card) {
if (card->enable && card->rom && (card->state == PNP_STATE_ISOLATION))
if (card->enable && (card->rom != NULL) && (card->state == PNP_STATE_ISOLATION))
break;
card = card->next;
}
@@ -374,6 +383,7 @@ vendor_defined:
default:
if (reg >= 0x30) {
CHECK_CURRENT_CARD();
CHECK_CURRENT_LD();
isapnp_log("ISAPnP: Read register %02X from CSN %02X device %02X\n", reg, card->csn, ld->number);
ret = ld->regs[reg];
@@ -397,7 +407,8 @@ isapnp_read_data(UNUSED(uint16_t addr), void *priv)
card = card->next;
}
isapnp_log("ISAPnP: read_data() => ");
// isapnp_log("ISAPnP: read_data() => ");
isapnp_log("[%04X:%08X] ISAPnP: read_data() => ", CS, cpu_state.pc);
return isapnp_read_common(dev, card, dev->current_ld, dev->reg);
}
@@ -432,12 +443,14 @@ isapnp_write_addr(UNUSED(uint16_t addr), uint8_t val, void *priv)
if (card->state == PNP_STATE_WAIT_FOR_KEY) { /* checking only the first card should be fine */
/* Check written value against LFSR key. */
if (val == isapnp_init_key[dev->key_pos]) {
if ((val == isapnp_init_key[dev->key_pos]) || (val == isapnp_init_key2[dev->key_pos])) {
dev->using_key2 = (val == isapnp_init_key2[dev->key_pos]);
dev->key_pos++;
if (!dev->key_pos) {
isapnp_log("ISAPnP: Key unlocked, putting cards to SLEEP\n");
while (card) {
if (card->enable && (card->enable != ISAPNP_CARD_NO_KEY) && (card->state == PNP_STATE_WAIT_FOR_KEY))
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))
card->state = PNP_STATE_SLEEP;
card = card->next;
}
@@ -493,6 +506,7 @@ isapnp_write_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uin
card->state = PNP_STATE_WAIT_FOR_KEY;
card = card->next;
}
dev->key_pos = 0;
}
if (val & 0x04) {
isapnp_log("ISAPnP: Reset CSN\n");
@@ -566,6 +580,20 @@ isapnp_write_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uin
ld->regs[reg] = val & 0x01;
isapnp_device_config_changed(card, ld);
for (uint8_t i = 0; i < 8; i++) {
if (!ld->io_len[i])
continue;
io_addr = (ld->regs[0x60 + (2 * i)] << 8) | ld->regs[0x61 + (2 * i)];
if (val & 0x01) {
if (ld->regs[0x31] & 0x02)
io_removehandler(io_addr, ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, ld);
} else {
if (ld->regs[0x31] & 0x02)
io_sethandler(io_addr, ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, ld);
}
}
break;
case 0x31: /* I/O Range Check */
@@ -578,7 +606,7 @@ isapnp_write_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uin
io_addr = (ld->regs[0x60 + (2 * i)] << 8) | ld->regs[0x61 + (2 * i)];
if (ld->regs[reg] & 0x02)
io_removehandler(io_addr, ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, ld);
if (val & 0x02)
if ((val & 0x02) && !(ld->regs[0x30] & 0x01))
io_sethandler(io_addr, ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, ld);
}
@@ -601,6 +629,7 @@ vendor_defined:
default:
if (reg >= 0x40) {
CHECK_CURRENT_CARD();
CHECK_CURRENT_LD();
isapnp_log("ISAPnP: Write %02X to register %02X on CSN %02X device %02X\n", val, reg, card->csn, ld->number);
@@ -670,7 +699,8 @@ isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv)
}
}
isapnp_log("ISAPnP: write_data(%02X) => ", val);
// isapnp_log("ISAPnP: write_data(%02X) => ", val);
isapnp_log("[%04X:%08X] ISAPnP: write_data(%02X) => ", CS, cpu_state.pc, val);
isapnp_write_common(dev, card, dev->current_ld, dev->reg, val);
}
@@ -1163,6 +1193,22 @@ isapnp_read_reg(void *priv, uint8_t ldn, uint8_t reg)
return isapnp_read_common(device_get_priv(&isapnp_device), card, ld, reg);
}
void
isapnp_set_rt(void *priv, uint8_t is_rt)
{
isapnp_card_t *card = (isapnp_card_t *) priv;
card->is_rt = is_rt;
}
uint8_t *
isapnp_get_csnsav(void *priv)
{
isapnp_card_t *card = (isapnp_card_t *) priv;
return &card->csnsav;
}
void
isapnp_write_reg(void *priv, uint8_t ldn, uint8_t reg, uint8_t val)
{

View File

@@ -57,19 +57,21 @@ typedef struct isapnp_device_config_t {
extern const uint8_t isapnp_init_key[32];
void *isapnp_add_card(uint8_t *rom, uint16_t rom_size,
void (*config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv),
void (*csn_changed)(uint8_t csn, void *priv),
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);
uint8_t isapnp_read_reg(void *priv, uint8_t ldn, uint8_t reg);
void isapnp_write_reg(void *priv, uint8_t ldn, uint8_t reg, uint8_t val);
void isapnp_set_device_defaults(void *priv, uint8_t ldn, const isapnp_device_config_t *config);
void isapnp_reset_card(void *priv);
void isapnp_reset_device(void *priv, uint8_t ld);
extern void *isapnp_add_card(uint8_t *rom, uint16_t rom_size,
void (*config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv),
void (*csn_changed)(uint8_t csn, void *priv),
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);
extern void isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size);
extern void isapnp_enable_card(void *priv, uint8_t enable);
extern void isapnp_set_csn(void *priv, uint8_t csn);
extern uint8_t isapnp_read_reg(void *priv, uint8_t ldn, uint8_t reg);
extern void isapnp_write_reg(void *priv, uint8_t ldn, uint8_t reg, uint8_t val);
extern void isapnp_set_device_defaults(void *priv, uint8_t ldn, const isapnp_device_config_t *config);
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 uint8_t *isapnp_get_csnsav(void *priv);
#endif /*EMU_ISAPNP_H*/

View File

@@ -29,6 +29,7 @@
#include <86box/nmc93cxx.h>
#include <86box/plat_unused.h>
#define ENABLE_NMC93CXX_EEPROM_LOG 3
#ifdef ENABLE_NMC93CXX_EEPROM_LOG
int nmc93cxx_eeprom_do_log = ENABLE_NMC93CXX_EEPROM_LOG;

View File

@@ -514,7 +514,7 @@ dp8390_page0_write(dp8390_t *dev, uint32_t off, uint32_t val, UNUSED(unsigned le
{
uint8_t val2;
dp8390_log("DP839: Page0 write to register 0x%02x, value=0x%02x\n",
dp8390_log("DP8390: Page0 write to register 0x%02x, value=0x%02x\n",
off, val);
switch (off) {

View File

@@ -65,6 +65,7 @@
#include <86box/network.h>
#include <86box/net_dp8390.h>
#include <86box/net_ne2000.h>
#include <86box/nmc93cxx.h>
#include <86box/isapnp.h>
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>
@@ -85,25 +86,26 @@ typedef struct nic_t {
const char *name;
uint8_t pnp_csnsav;
uint8_t pci_slot;
uint8_t irq_state;
uint8_t pad;
uint8_t csnsav;
/* RTL8019AS/RTL8029AS registers */
uint8_t config0;
uint8_t config1;
uint8_t config2;
uint8_t config3;
uint8_t _9346cr;
uint8_t pci_regs[PCI_REGSIZE];
uint8_t eeprom[128]; /* for RTL8029AS */
uint8_t maclocal[6]; /* configured MAC (local) address */
/* POS registers, MCA boards only */
uint8_t pos_regs[8];
uint8_t eeprom_data[128];
int board;
int is_pci;
int is_mca;
@@ -121,6 +123,9 @@ typedef struct nic_t {
rom_t bios_rom;
void *pnp_card;
uint8_t *pnp_csnsav;
nmc93cxx_eeprom_t *eeprom;
} nic_t;
#ifdef ENABLE_NE2K_LOG
@@ -144,7 +149,11 @@ nelog(int lvl, const char *fmt, ...)
static void
nic_interrupt(void *priv, int set)
{
nic_t *dev = (nic_t *) priv;
nic_t *dev = (nic_t *) priv;
int enabled = 1;
if (dev->board == NE2K_RTL8019AS_PNP)
enabled = dev->config1 & 0x80;
if (dev->is_pci) {
if (set)
@@ -152,9 +161,12 @@ nic_interrupt(void *priv, int set)
else
pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
} else {
if (set)
picint(1 << dev->base_irq);
else
if (enabled && (dev->base_irq != 0x02)) {
if (set)
picint(1 << dev->base_irq);
else
picintc(1 << dev->base_irq);
} else if (dev->base_irq != 0x02)
picintc(1 << dev->base_irq);
}
}
@@ -236,6 +248,7 @@ asic_read(nic_t *dev, uint32_t off, unsigned int len)
/* If all bytes have been written, signal remote-DMA complete */
if (dev->dp8390->remote_bytes == 0) {
nelog(3, "%s: DMA read: done (%i)\n", dev->name, dev->dp8390->IMR.rdma_inte);
dev->dp8390->ISR.rdma_done = 1;
if (dev->dp8390->IMR.rdma_inte)
nic_interrupt(dev, 1);
@@ -262,6 +275,11 @@ asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len)
dev->name, (unsigned) off, (unsigned) val);
switch (off) {
default: /* this is invalid, but happens under win95 device detection */
nelog(3, "%s: ASIC write invalid address %04x, ignoring\n",
dev->name, (unsigned) off);
break;
case 0x00: /* Data register - see asic_read for a description */
if ((len > 1) && (dev->dp8390->DCR.wdsize == 0)) {
nelog(3, "%s: DMA write length %d on byte mode operation\n",
@@ -299,11 +317,6 @@ asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len)
case 0x0f: /* Reset register */
/* end of reset pulse */
break;
default: /* this is invalid, but happens under win95 device detection */
nelog(3, "%s: ASIC write invalid address %04x, ignoring\n",
dev->name, (unsigned) off);
break;
}
}
@@ -311,59 +324,137 @@ asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len)
static uint32_t
page3_read(nic_t *dev, uint32_t off, UNUSED(unsigned int len))
{
uint8_t ret = 0x00;
if (dev->board >= NE2K_RTL8019AS_PNP)
switch (off) {
case 0x1: /* 9346CR */
return (dev->_9346cr);
default:
break;
case 0x3: /* CONFIG0 */
return 0x00; /* Cable not BNC */
case 0x1: /* 9346CR */
ret = (dev->_9346cr & 0xfe);
if (((ret & 0xc0) == 0x80) && nmc93cxx_eeprom_read(dev->eeprom))
ret |= 0x01;
break;
case 0x3: /* CONFIG0 */
if (dev->board == NE2K_RTL8019AS_PNP)
ret = (dev->config0 & 0xc0) | 0x10; /* Cable not BNC */
else
ret = 0x00; /* Cable not BNC */
break;
case 0x4: /* CONFIG1 */
if (dev->board == NE2K_RTL8019AS_PNP)
ret = dev->config1;
break;
case 0x5: /* CONFIG2 */
return (dev->config2 & 0xe0);
if (dev->board == NE2K_RTL8019AS_PNP)
ret = dev->config2;
else
ret = (dev->config2 & 0xe0);
break;
case 0x6: /* CONFIG3 */
return (dev->config3 & 0x46);
if (dev->board == NE2K_RTL8019AS_PNP)
ret = dev->config3;
else
ret = (dev->config3 & 0x46);
break;
case 0x8: /* CSNSAV */
return ((dev->board == NE2K_RTL8019AS_PNP) ? dev->pnp_csnsav : 0x00);
ret = ((dev->board == NE2K_RTL8019AS_PNP) ? *dev->pnp_csnsav : 0x00);
break;
case 0xb: /* INTR */
if (dev->board == NE2K_RTL8019AS_PNP) {
ret = (pic2.irr & 0x02) ? 0x01 : 0x00;
ret |= (pic.irr & 0x08) ? 0x02 : 0x00;
ret |= (pic.irr & 0x10) ? 0x04 : 0x00;
ret |= (pic.irr & 0x20) ? 0x08 : 0x00;
ret |= (pic2.irr & 0x04) ? 0x10 : 0x00;
ret |= (pic2.irr & 0x08) ? 0x20 : 0x00;
ret |= (pic2.irr & 0x10) ? 0x40 : 0x00;
ret |= (pic2.irr & 0x80) ? 0x80 : 0x00;
}
break;
case 0xd: /* CONFIG4 */
if (dev->board == NE2K_RTL8019AS_PNP) {
uint8_t *data = (uint8_t *) nmc93cxx_eeprom_data(dev->eeprom);
ret = data[0x03];
}
break;
case 0xe: /* 8029ASID0 */
if (dev->board == NE2K_RTL8029AS)
return 0x29;
ret = 0x29;
break;
case 0xf: /* 8029ASID1 */
if (dev->board == NE2K_RTL8029AS)
return 0x80;
break;
default:
ret = 0x80;
break;
}
nelog(3, "%s: Page3 read register 0x%02x attempted\n", dev->name, off);
return 0x00;
nelog(3, "%s: Page3 read register 0x%02x, value=0x%04x\n", dev->name, off, ret);
return ret;
}
static void
page3_write(nic_t *dev, uint32_t off, uint32_t val, UNUSED(unsigned len))
{
int cfg_write_enable = ((dev->_9346cr & 0xc0) == 0xc0);
if (dev->board >= NE2K_RTL8019AS_PNP) {
nelog(3, "%s: Page2 write to register 0x%02x, len=%u, value=0x%04x\n",
nelog(3, "%s: Page3 write to register 0x%02x, len=%u, value=0x%04x\n",
dev->name, off, len, val);
switch (off) {
case 0x01: /* 9346CR */
dev->_9346cr = (val & 0xfe);
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);
data[0x00] = 0x80;
data[0x01] = 0x00;
data[0x02] = 0x80;
data[0x03] = 0x00;
dev->_9346cr = 0x21;
}
break;
case 0x03: /* CONFIG0 */
if (cfg_write_enable && (dev->board == NE2K_RTL8019AS_PNP))
dev->config0 = (val & 0xc0);
break;
case 0x04: /* CONFIG1 */
if (cfg_write_enable && (dev->board == NE2K_RTL8019AS_PNP))
dev->config1 = (dev->config1 & 0x7f) | (val & 0x80);
break;
case 0x05: /* CONFIG2 */
dev->config2 = (val & 0xe0);
if (cfg_write_enable) {
if (dev->board == NE2K_RTL8019AS_PNP)
dev->config2 = val;
else
dev->config2 = (val & 0xe0);
}
break;
case 0x06: /* CONFIG3 */
dev->config3 = (val & 0x46);
if (cfg_write_enable) {
if (dev->board == NE2K_RTL8019AS_PNP)
dev->config3 = val;
else
dev->config3 = (val & 0x46);
}
break;
case 0x09: /* HLTCLK */
@@ -491,6 +582,10 @@ 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)
{
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;
if (ld)
return;
@@ -502,10 +597,22 @@ nic_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
}
dev->base_address = config->io[0].base;
dev->base_irq = config->irq[0].irq;
if (config->activate && (dev->base_address != ISAPNP_IO_DISABLED))
nic_interrupt(dev, 0);
dev->base_irq = config->irq[0].irq;
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);
if (config->activate && (dev->base_address != ISAPNP_IO_DISABLED)) {
nic_ioset(dev, dev->base_address);
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;
}
}
static void
@@ -513,7 +620,7 @@ nic_pnp_csn_changed(uint8_t csn, void *priv)
{
nic_t *dev = (nic_t *) priv;
dev->pnp_csnsav = csn;
*dev->pnp_csnsav = csn;
}
static uint8_t
@@ -525,17 +632,21 @@ nic_pnp_read_vendor_reg(uint8_t ld, uint8_t reg, void *priv)
const nic_t *dev = (nic_t *) priv;
switch (reg) {
case 0xF0:
return dev->config0;
case 0xf0: /* CONFIG0 */
return 0x00; /* Cable not BNC */
case 0xF2:
case 0xf1: /* CONFIG1 */
return dev->config1;
break;
case 0xf2: /* CONFIG2 */
return dev->config2;
case 0xF3:
case 0xf3: /* CONFIG3 */
return dev->config3;
case 0xF5:
return dev->pnp_csnsav;
case 0xf5:
return *dev->pnp_csnsav;
default:
break;
@@ -550,9 +661,9 @@ nic_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv)
nic_t *dev = (nic_t *) priv;
if ((ld == 0) && (reg == 0xf6) && (val & 0x04)) {
uint8_t csn = dev->pnp_csnsav;
uint8_t csn = *dev->pnp_csnsav;
isapnp_set_csn(dev->pnp_card, 0);
dev->pnp_csnsav = csn;
*dev->pnp_csnsav = csn;
}
}
@@ -913,6 +1024,7 @@ nic_init(const device_t *info)
char *rom = NULL;
nic_t *dev;
int set_oui = 0;
int use_nvr = 0;
dev = calloc(1, sizeof(nic_t));
dev->name = info->name;
@@ -1144,26 +1256,33 @@ nic_init(const device_t *info)
}
/* Initialize the RTL80x9 EEPROM. */
memset(dev->eeprom, 0x00, sizeof(dev->eeprom));
memset(dev->eeprom_data, 0x00, sizeof(dev->eeprom_data));
if (dev->board == NE2K_RTL8029AS) {
memcpy(&dev->eeprom[0x02], dev->maclocal, 6);
dev->eeprom_data[0x00] = 0x00;
dev->eeprom_data[0x01] = 0x00;
dev->eeprom[0x76] = dev->eeprom[0x7A] = dev->eeprom[0x7E] = (PCI_DEVID & 0xff);
dev->eeprom[0x77] = dev->eeprom[0x7B] = dev->eeprom[0x7F] = (PCI_DEVID >> 8);
dev->eeprom[0x78] = dev->eeprom[0x7C] = (PCI_VENDID & 0xff);
dev->eeprom[0x79] = dev->eeprom[0x7D] = (PCI_VENDID >> 8);
memcpy(&dev->eeprom_data[0x02], dev->maclocal, 6);
dev->eeprom_data[0x76] = dev->eeprom_data[0x7a] = dev->eeprom_data[0x7e] = (PCI_DEVID & 0xff);
dev->eeprom_data[0x77] = dev->eeprom_data[0x7b] = dev->eeprom_data[0x7f] = (PCI_DEVID >> 8);
dev->eeprom_data[0x78] = dev->eeprom_data[0x7c] = (PCI_VENDID & 0xff);
dev->eeprom_data[0x79] = dev->eeprom_data[0x7d] = (PCI_VENDID >> 8);
use_nvr = 1;
} else {
const char *pnp_rom_file = NULL;
int pnp_rom_len = 0x4a;
switch (dev->board) {
case NE2K_RTL8019AS_PNP:
pnp_rom_file = "roms/network/rtl8019as/RTL8019A.BIN";
use_nvr = 1;
break;
case NE2K_DE220P:
pnp_rom_file = "roms/network/de220p/dlk2201a.bin";
pnp_rom_len = 0x43;
pnp_rom_len = 0x43;
use_nvr = 1;
break;
default:
@@ -1174,8 +1293,8 @@ nic_init(const device_t *info)
if (pnp_rom_file) {
FILE *fp = rom_fopen(pnp_rom_file, "rb");
if (fp) {
if (fread(&dev->eeprom[0x12], 1, pnp_rom_len, fp) == pnp_rom_len)
pnp_rom = &dev->eeprom[0x12];
if (fread(&dev->eeprom_data[0x12], 1, pnp_rom_len, fp) == pnp_rom_len)
pnp_rom = &dev->eeprom_data[0x12];
fclose(fp);
}
}
@@ -1183,10 +1302,22 @@ nic_init(const device_t *info)
switch (info->local) {
case NE2K_RTL8019AS_PNP:
case NE2K_DE220P:
dev->pnp_card = isapnp_add_card(pnp_rom, pnp_rom_len,
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(pnp_rom, pnp_rom_len,
nic_pnp_config_changed, nic_pnp_csn_changed,
nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg,
dev);
dev->pnp_csnsav = isapnp_get_csnsav(dev->pnp_card);
dev->config0 = 0x00;
dev->config1 = 0x80;
dev->config2 = 0x00;
dev->config3 = 0x80;
isapnp_set_rt(dev->pnp_card, 1);
dev->eeprom_data[0x00] = 0x80;
dev->eeprom_data[0x01] = 0x00;
dev->eeprom_data[0x02] = 0x80;
dev->eeprom_data[0x03] = 0x01;
memcpy(&dev->eeprom_data[0x04], dev->maclocal, 6);
break;
default:
@@ -1195,6 +1326,25 @@ nic_init(const device_t *info)
}
}
if (use_nvr) {
nmc93cxx_eeprom_params_t params;
char filename[1024] = { 0 };
params.nwords = 64;
params.default_content = (uint16_t *) dev->eeprom_data;
params.filename = filename;
int inst = device_get_instance();
snprintf(filename, sizeof(filename), "nmc93cxx_eeprom_%s_%d.nvr", info->internal_name, inst);
dev->eeprom = device_add_inst_params(&nmc93cxx_device, inst, &params);
if (dev->eeprom == NULL) {
free(dev);
return NULL;
}
}
if (dev->pnp_csnsav == NULL)
dev->pnp_csnsav = &dev->csnsav;
if (dev->board != NE2K_ETHERNEXT_MC)
/* Reset the board. */
nic_reset(dev);