diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index b46ac2aaf..d655e78c8 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -65,6 +65,7 @@ #include <86box/net_dp8390.h> #include <86box/net_ne2000.h> #include <86box/bswap.h> +#include <86box/isapnp.h> enum { @@ -88,12 +89,6 @@ enum { #define PCI_REGSIZE 256 /* size of PCI space */ -uint8_t pnp_init_key[32] = { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE, - 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61, - 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1, - 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39 }; - - typedef struct { dp8390_t *dp8390; const char *name; @@ -106,27 +101,15 @@ typedef struct { bios_mask; int card; /* PCI card slot */ int has_bios, pad; - uint8_t pnp_regs[256]; - uint8_t pnp_res_data[256]; bar_t pci_bar[2]; uint8_t pci_regs[PCI_REGSIZE]; uint8_t eeprom[128]; /* for RTL8029AS */ rom_t bios_rom; - uint8_t pnp_phase; - uint8_t pnp_magic_count; - uint8_t pnp_address; - uint8_t pnp_res_pos; - uint8_t pnp_csn; + void *pnp_card; uint8_t pnp_activate; - uint8_t pnp_io_check; uint8_t pnp_csnsav; - uint8_t pnp_id_checksum; - uint8_t pnp_serial_read_pos; - uint8_t pnp_serial_read_pair; - uint8_t pnp_serial_read; - uint8_t maclocal[6]; /* configured MAC (local) address */ - uint16_t pnp_read; uint64_t pnp_id; + uint8_t maclocal[6]; /* configured MAC (local) address */ /* RTL8019AS/RTL8029AS registers */ uint8_t config0, config2, config3; @@ -508,324 +491,75 @@ nic_writel(uint16_t addr, uint32_t val, void *priv) } -static void nic_iocheckset(nic_t *dev, uint16_t addr); -static void nic_iocheckremove(nic_t *dev, uint16_t addr); static void nic_ioset(nic_t *dev, uint16_t addr); static void nic_ioremove(nic_t *dev, uint16_t addr); -static uint8_t -nic_pnp_io_check_readb(uint16_t addr, void *priv) +static void +nic_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +{ + if (ld != 0) + return; + + nic_t *dev = (nic_t *) priv; + + if (dev->pnp_activate) + nic_ioremove(dev, dev->base_address); + + dev->base_address = config->io[0].base; + dev->base_irq = config->irq[0].irq; + dev->pnp_activate = config->activate; + + if (dev->pnp_activate && (dev->base_address != ISAPNP_IO_DISABLED) && (dev->base_irq != ISAPNP_IRQ_DISABLED)) + nic_ioset(dev, dev->base_address); +} + + +static void +nic_pnp_csn_changed(uint8_t csn, void *priv) { nic_t *dev = (nic_t *) priv; - return((dev->pnp_io_check & 0x01) ? 0x55 : 0xAA); + dev->pnp_csnsav = csn; } static uint8_t -nic_pnp_readb(uint16_t addr, void *priv) +nic_pnp_read_vendor_reg(uint8_t ld, uint8_t reg, void *priv) { + if (ld != 0) + return 0x00; + nic_t *dev = (nic_t *) priv; - uint8_t bit, next_shift; - uint8_t ret = 0xFF; - /* Plug and Play Registers */ - switch(dev->pnp_address) { - /* Card Control Registers */ - case 0x01: /* Serial Isolation */ - if (dev->pnp_phase != PNP_PHASE_ISOLATION) { - ret = 0x00; - break; - } - if (dev->pnp_serial_read_pair) { - dev->pnp_serial_read <<= 1; - /* TODO: Support for multiple PnP devices. - if (pnp_get_bus_data() != dev->pnp_serial_read) - dev->pnp_phase = PNP_PHASE_SLEEP; - } else { - */ - if (!dev->pnp_serial_read_pos) { - dev->pnp_res_pos = 0x1B; - dev->pnp_phase = PNP_PHASE_CONFIG; - nelog(1, "\nASSIGN CSN phase\n"); - } - } else { - if (dev->pnp_serial_read_pos < 64) { - bit = (dev->pnp_id >> dev->pnp_serial_read_pos) & 0x01; - next_shift = (!!(dev->pnp_id_checksum & 0x02) ^ !!(dev->pnp_id_checksum & 0x01) ^ bit) & 0x01; - dev->pnp_id_checksum >>= 1; - dev->pnp_id_checksum |= (next_shift << 7); - } else { - if (dev->pnp_serial_read_pos == 64) - dev->eeprom[0x1A] = dev->pnp_id_checksum; - bit = (dev->pnp_id_checksum >> (dev->pnp_serial_read_pos & 0x07)) & 0x01; - } - dev->pnp_serial_read = bit ? 0x55 : 0x00; - dev->pnp_serial_read_pos = (dev->pnp_serial_read_pos + 1) % 72; - } - dev->pnp_serial_read_pair ^= 1; - ret = dev->pnp_serial_read; - break; - case 0x04: /* Resource Data */ - ret = dev->eeprom[dev->pnp_res_pos]; - dev->pnp_res_pos++; - break; - case 0x05: /* Status */ - ret = 0x01; - break; - case 0x06: /* Card Select Number (CSN) */ - nelog(1, "Card Select Number (CSN)\n"); - ret = dev->pnp_csn; - break; - case 0x07: /* Logical Device Number */ - nelog(1, "Logical Device Number\n"); - ret = 0x00; - break; - case 0x30: /* Activate */ - nelog(1, "Activate\n"); - ret = dev->pnp_activate; - break; - case 0x31: /* I/O Range Check */ - nelog(1, "I/O Range Check\n"); - ret = dev->pnp_io_check; - break; + switch (reg) { + case 0xF0: + return dev->config0; - /* Logical Device Configuration Registers */ - /* Memory Configuration Registers - We currently force them to stay 0x00 because we currently do not - support a RTL8019AS BIOS. */ - case 0x40: /* BROM base address bits[23:16] */ - case 0x41: /* BROM base address bits[15:0] */ - case 0x42: /* Memory Control */ - ret = 0x00; - break; + case 0xF2: + return dev->config2; - /* I/O Configuration Registers */ - case 0x60: /* I/O base address bits[15:8] */ - ret = (dev->base_address >> 8); - break; - case 0x61: /* I/O base address bits[7:0] */ - ret = (dev->base_address & 0xFF); - break; + case 0xF3: + return dev->config3; - /* Interrupt Configuration Registers */ - case 0x70: /* IRQ level */ - ret = dev->base_irq; - break; - case 0x71: /* IRQ type */ - ret = 0x02; /* high, edge */ - break; - - /* DMA Configuration Registers */ - case 0x74: /* DMA channel select 0 */ - case 0x75: /* DMA channel select 1 */ - ret = 0x04; /* indicating no DMA channel is needed */ - break; - - /* Vendor Defined Registers */ - case 0xF0: /* CONFIG0 */ - case 0xF1: /* CONFIG1 */ - ret = 0x00; - break; - case 0xF2: /* CONFIG2 */ - ret = (dev->config2 & 0xe0); - break; - case 0xF3: /* CONFIG3 */ - ret = (dev->config3 & 0x46); - break; - case 0xF5: /* CSNSAV */ - ret = (dev->pnp_csnsav); - break; + case 0xF5: + return dev->pnp_csnsav; } - nelog(1, "nic_pnp_readb(%04X) = %02X\n", addr, ret); - return(ret); -} - - -static void nic_pnp_io_set(nic_t *dev, uint16_t read_addr); -static void nic_pnp_io_remove(nic_t *dev); - - -static void -nic_pnp_writeb(uint16_t addr, uint8_t val, void *priv) -{ - nic_t *dev = (nic_t *) priv; - uint16_t new_addr = 0; - - nelog(1, "nic_pnp_writeb(%04X, %02X)\n", addr, val); - - /* Plug and Play Registers */ - switch(dev->pnp_address) { - /* Card Control Registers */ - case 0x00: /* Set RD_DATA port */ - new_addr = val; - new_addr <<= 2; - new_addr |= 3; - nic_pnp_io_remove(dev); - nic_pnp_io_set(dev, new_addr); - nelog(1, "PnP read data address now: %04X\n", new_addr); - break; - case 0x02: /* Config Control */ - if (val & 0x01) { - /* Reset command */ - nic_pnp_io_remove(dev); - memset(dev->pnp_regs, 0, 256); - nelog(1, "All logical devices reset\n"); - } - if (val & 0x02) { - /* Wait for Key command */ - dev->pnp_phase = PNP_PHASE_WAIT_FOR_KEY; - nelog(1, "WAIT FOR KEY phase\n"); - } - if (val & 0x04) { - /* PnP Reset CSN command */ - dev->pnp_csn = dev->pnp_csnsav = 0; - nelog(1, "CSN reset\n"); - } - break; - case 0x03: /* Wake[CSN] */ - nelog(1, "Wake[%02X]\n", val); - if (val == dev->pnp_csn) { - dev->pnp_res_pos = 0x12; - dev->pnp_id_checksum = 0x6A; - if (dev->pnp_phase == PNP_PHASE_SLEEP) { - dev->pnp_phase = val ? PNP_PHASE_CONFIG : PNP_PHASE_ISOLATION; - } - } else { - if ((dev->pnp_phase == PNP_PHASE_CONFIG) || (dev->pnp_phase == PNP_PHASE_ISOLATION)) - dev->pnp_phase = PNP_PHASE_SLEEP; - } - break; - case 0x06: /* Card Select Number (CSN) */ - dev->pnp_csn = dev->pnp_csnsav = val; - dev->pnp_phase = PNP_PHASE_CONFIG; - nelog(1, "CSN set to %02X\n", dev->pnp_csn); - break; - case 0x30: /* Activate */ - if ((dev->pnp_activate ^ val) & 0x01) { - nic_ioremove(dev, dev->base_address); - if (val & 0x01) - nic_ioset(dev, dev->base_address); - - nelog(1, "I/O range %sabled\n", val & 0x02 ? "en" : "dis"); - } - dev->pnp_activate = val; - break; - case 0x31: /* I/O Range Check */ - if ((dev->pnp_io_check ^ val) & 0x02) { - nic_iocheckremove(dev, dev->base_address); - if (val & 0x02) - nic_iocheckset(dev, dev->base_address); - - nelog(1, "I/O range check %sabled\n", val & 0x02 ? "en" : "dis"); - } - dev->pnp_io_check = val; - break; - - /* Logical Device Configuration Registers */ - /* Memory Configuration Registers - We currently force them to stay 0x00 because we currently do not - support a RTL8019AS BIOS. */ - - /* I/O Configuration Registers */ - case 0x60: /* I/O base address bits[15:8] */ - if ((dev->pnp_activate & 0x01) || (dev->pnp_io_check & 0x02)) - nic_ioremove(dev, dev->base_address); - dev->base_address &= 0x00ff; - dev->base_address |= (((uint16_t) val) << 8); - if ((dev->pnp_activate & 0x01) || (dev->pnp_io_check & 0x02)) - nic_ioset(dev, dev->base_address); - nelog(1, "Base address now: %04X\n", dev->base_address); - break; - case 0x61: /* I/O base address bits[7:0] */ - if ((dev->pnp_activate & 0x01) || (dev->pnp_io_check & 0x02)) - nic_ioremove(dev, dev->base_address); - dev->base_address &= 0xff00; - dev->base_address |= val; - if ((dev->pnp_activate & 0x01) || (dev->pnp_io_check & 0x02)) - nic_ioset(dev, dev->base_address); - nelog(1, "Base address now: %04X\n", dev->base_address); - break; - - /* Interrupt Configuration Registers */ - case 0x70: /* IRQ level */ - dev->base_irq = val; - nelog(1, "IRQ now: %02i\n", dev->base_irq); - break; - - /* Vendor Defined Registers */ - case 0xF6: /* Vendor Control */ - dev->pnp_csn = 0; - break; - } - return; + return 0x00; } static void -nic_pnp_io_set(nic_t *dev, uint16_t read_addr) -{ - if ((read_addr >= 0x0200) && (read_addr <= 0x03FF)) { - io_sethandler(read_addr, 1, - nic_pnp_readb, NULL, NULL, - NULL, NULL, NULL, dev); - } - dev->pnp_read = read_addr; -} - - -static void -nic_pnp_io_remove(nic_t *dev) -{ - if ((dev->pnp_read >= 0x0200) && (dev->pnp_read <= 0x03FF)) { - io_removehandler(dev->pnp_read, 1, - nic_pnp_readb, NULL, NULL, - NULL, NULL, NULL, dev); - } -} - - -static void -nic_pnp_address_writeb(uint16_t addr, uint8_t val, void *priv) +nic_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv) { nic_t *dev = (nic_t *) priv; - /* nelog(1, "nic_pnp_address_writeb(%04X, %02X)\n", addr, val); */ - - switch(dev->pnp_phase) { - case PNP_PHASE_WAIT_FOR_KEY: - if (val == pnp_init_key[dev->pnp_magic_count]) { - dev->pnp_magic_count = (dev->pnp_magic_count + 1) & 0x1f; - if (!dev->pnp_magic_count) - dev->pnp_phase = PNP_PHASE_SLEEP; - } else - dev->pnp_magic_count = 0; - break; - default: - dev->pnp_address = val; - break; + if ((ld == 0) && (reg == 0xf6) && (val & 0x04)) { + uint8_t csn = dev->pnp_csnsav; + isapnp_set_csn(dev->pnp_card, 0); + dev->pnp_csnsav = csn; } - return; -} - - -static void -nic_iocheckset(nic_t *dev, uint16_t addr) -{ - io_sethandler(addr, 32, - nic_pnp_io_check_readb, NULL, NULL, - NULL, NULL, NULL, dev); -} - - -static void -nic_iocheckremove(nic_t *dev, uint16_t addr) -{ - io_removehandler(addr, 32, - nic_pnp_io_check_readb, NULL, NULL, - NULL, NULL, NULL, dev); } @@ -1199,7 +933,6 @@ nic_init(const device_t *info) #ifdef ENABLE_NIC_LOG int i; #endif - int c; char *ansi_id = "REALTEK PLUG & PLAY ETHERNET CARD"; uint64_t *eeprom_pnp_id; @@ -1379,14 +1112,9 @@ nic_init(const device_t *info) dev->card = pci_add_card(PCI_ADD_NORMAL, nic_pci_read, nic_pci_write, dev); } else { - io_sethandler(0x0279, 1, - NULL, NULL, NULL, - nic_pnp_address_writeb, NULL, NULL, dev); - dev->pnp_id = PNP_DEVID; dev->pnp_id <<= 32LL; dev->pnp_id |= PNP_VENDID; - dev->pnp_phase = PNP_PHASE_WAIT_FOR_KEY; } /* Initialize the RTL8029 EEPROM. */ @@ -1454,13 +1182,9 @@ nic_init(const device_t *info) /* TAG: END Tag */ dev->eeprom[0x5B] = 0x79; /* Item byte */ - for (c = 0x1b; c < 0x5c; c++) /* Checksum (2's compl) */ - dev->eeprom[0x5C] += dev->eeprom[c]; - dev->eeprom[0x5C] = -dev->eeprom[0x5C]; + /* Checksum is filled in by isapnp_add_card */ - io_sethandler(0x0A79, 1, - NULL, NULL, NULL, - nic_pnp_writeb, NULL, NULL, dev); + 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); } }