EEPROM use changes and misc (September 3rd, 2025)

1.Move the 93cxx EEPROM implementation to the mem directory since it's used by cards which are not nics (e.g.: DC390 SCSI and S3 ELSA cards).
2. DC390 specific: remove the implementation used there and use the generic one from mem (used to be on the network directory) as well as fixing bus reset when interrupts are related.
3. S3: when the 64k size is selected in the LFB, use the SVGA 64k mapping as LFB (0xA0000).
This commit is contained in:
TC1995
2025-09-03 00:49:27 +02:00
parent 649f813614
commit 5f06561469
7 changed files with 90 additions and 213 deletions

View File

@@ -21,6 +21,7 @@ add_library(mem OBJECT
intel_flash.c
mem.c
mmu_2386.c
nmc93cxx.c
rom.c
row.c
smram.c

View File

@@ -28,7 +28,7 @@
#include <86box/device.h>
#include <86box/timer.h>
#include <86box/nvr.h>
#include <86box/net_eeprom_nmc93cxx.h>
#include <86box/nmc93cxx.h>
#include <86box/plat_unused.h>
#ifdef ENABLE_NMC93CXX_EEPROM_LOG
@@ -256,7 +256,12 @@ static void
nmc93cxx_eeprom_close(void *priv)
{
nmc93cxx_eeprom_t *eeprom = (nmc93cxx_eeprom_t *) priv;
free(eeprom);
FILE *fp = nvr_fopen(eeprom->filename, "wb");
if (fp) {
fwrite(eeprom->dev.data, 2, eeprom->size, fp);
fclose(fp);
}
free(priv);
}
uint16_t *

View File

@@ -28,7 +28,6 @@ list(APPEND net_sources
net_plip.c
net_event.c
net_null.c
net_eeprom_nmc93cxx.c
net_tulip.c
net_rtl8139.c
net_l80225.c
@@ -71,9 +70,6 @@ if(NETSWITCH)
endif()
if (UNIX)
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
set_source_files_properties(net_slirp.c PROPERTIES COMPILE_FLAGS "-I/usr/local/include")
endif()
find_path(HAS_VDE "libvdeplug.h" PATHS ${VDE_INCLUDE_DIR} "/usr/include /usr/local/include" "/opt/homebrew/include" )
if(HAS_VDE)
find_library(VDE_LIB vdeplug)

View File

@@ -43,7 +43,7 @@
#include <86box/device.h>
#include <86box/thread.h>
#include <86box/network.h>
#include <86box/net_eeprom_nmc93cxx.h>
#include <86box/nmc93cxx.h>
#include <86box/nvr.h>
#include "cpu.h"
#include <86box/plat_unused.h>

View File

@@ -31,7 +31,7 @@
#include <86box/device.h>
#include <86box/thread.h>
#include <86box/network.h>
#include <86box/net_eeprom_nmc93cxx.h>
#include <86box/nmc93cxx.h>
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>
#include <86box/bswap.h>

View File

@@ -40,11 +40,11 @@
#include <86box/pci.h>
#include <86box/device.h>
#include <86box/nvr.h>
#include <86box/nmc93cxx.h>
#include <86box/plat.h>
#include <86box/scsi.h>
#include <86box/scsi_device.h>
#include <86box/scsi_pcscsi.h>
#include <86box/vid_ati_eeprom.h>
#include <86box/fifo8.h>
#include "cpu.h"
@@ -179,7 +179,6 @@ typedef struct esp_t {
int BIOSBase;
int MMIOBase;
rom_t bios;
ati_eeprom_t eeprom;
int PCIBase;
uint8_t rregs[ESP_REGS];
@@ -223,9 +222,14 @@ typedef struct esp_t {
uint8_t irq_state;
uint8_t pos_regs[8];
uint8_t eeprom_inst;
uint8_t eeprom_data[128];
nmc93cxx_eeprom_t *eeprom;
} esp_t;
static esp_t reset_state = { 0 };
static esp_t *reset_state = NULL;
#define READ_FROM_DEVICE 1
#define WRITE_TO_DEVICE 0
@@ -1534,19 +1538,19 @@ esp_reg_write(esp_t *dev, uint32_t saddr, uint32_t val)
break;
case CMD_BUSRESET:
esp_log("ESP Bus Reset val=%02x.\n", (dev->rregs[ESP_CFG1] & CFG1_RESREPT));
if (dev->mca) {
esp_lower_irq(dev);
esp_hard_reset(dev);
} else
esp_pci_soft_reset(dev);
for (uint8_t i = 0; i < 16; i++) {
for (uint8_t i = 0; i < 16; i++)
scsi_device_reset(&scsi_devices[dev->bus][i]);
}
if (!(dev->rregs[ESP_CFG1] & CFG1_RESREPT)) {
dev->rregs[ESP_RINTR] |= INTR_RST;
esp_log("ESP Bus Reset with IRQ\n");
esp_raise_irq(dev);
} else {
if (dev->mca) {
esp_lower_irq(dev);
esp_hard_reset(dev);
} else
esp_pci_soft_reset(dev);
}
break;
case CMD_TI:
@@ -1994,180 +1998,6 @@ esp_bios_disable(esp_t *dev)
#define EE_ADAPT_OPTION_INT13 0x04
#define EE_ADAPT_OPTION_SCAM_SUPPORT 0x08
/*To do: make this separate from the SCSI card*/
static void
dc390_save_eeprom(esp_t *dev)
{
FILE *fp = nvr_fopen(dev->nvr_path, "wb");
if (!fp)
return;
fwrite(dev->eeprom.data, 1, 128, fp);
fclose(fp);
}
static void
dc390_write_eeprom(esp_t *dev, int ena, int clk, int dat)
{
/*Actual EEPROM is the same as the one used by the ATI cards, the 93cxx series.*/
ati_eeprom_t *eeprom = &dev->eeprom;
uint8_t tick = eeprom->count;
uint8_t eedo = eeprom->out;
uint16_t address = eeprom->address;
uint8_t command = eeprom->opcode;
esp_log("EEPROM CS=%02x,SK=%02x,DI=%02x,DO=%02x,tick=%d\n",
ena, clk, dat, eedo, tick);
if (!eeprom->oldena && ena) {
esp_log("EEPROM Start chip select cycle\n");
tick = 0;
command = 0;
address = 0;
} else if (eeprom->oldena && !ena) {
if (!eeprom->wp) {
uint8_t subcommand = address >> 4;
if (command == 0 && subcommand == 2) {
esp_log("EEPROM Erase All\n");
for (address = 0; address < 64; address++)
eeprom->data[address] = 0xffff;
dc390_save_eeprom(dev);
} else if (command == 3) {
esp_log("EEPROM Erase Word\n");
eeprom->data[address] = 0xffff;
dc390_save_eeprom(dev);
} else if (tick >= 26) {
if (command == 1) {
esp_log("EEPROM Write Word\n");
eeprom->data[address] &= eeprom->dat;
dc390_save_eeprom(dev);
} else if (command == 0 && subcommand == 1) {
esp_log("EEPROM Write All\n");
for (address = 0; address < 64; address++)
eeprom->data[address] &= eeprom->dat;
dc390_save_eeprom(dev);
}
}
}
eedo = 1;
esp_log("EEPROM DO read\n");
} else if (ena && !eeprom->oldclk && clk) {
if (tick == 0) {
if (dat == 0) {
esp_log("EEPROM Got correct 1st start bit, waiting for 2nd start bit (1)\n");
tick++;
} else {
esp_log("EEPROM Wrong 1st start bit (is 1, should be 0)\n");
tick = 2;
}
} else if (tick == 1) {
if (dat != 0) {
esp_log("EEPROM Got correct 2nd start bit, getting command + address\n");
tick++;
} else {
esp_log("EEPROM 1st start bit is longer than needed\n");
}
} else if (tick < 4) {
tick++;
command <<= 1;
if (dat)
command += 1;
} else if (tick < 10) {
tick++;
address = (address << 1) | dat;
if (tick == 10) {
esp_log("EEPROM command = %02x, address = %02x (val = %04x)\n", command,
address, eeprom->data[address]);
if (command == 2)
eedo = 0;
address = address % 64;
if (command == 0) {
switch (address >> 4) {
case 0:
esp_log("EEPROM Write disable command\n");
eeprom->wp = 1;
break;
case 1:
esp_log("EEPROM Write all command\n");
break;
case 2:
esp_log("EEPROM Erase all command\n");
break;
case 3:
esp_log("EEPROM Write enable command\n");
eeprom->wp = 0;
break;
default:
break;
}
} else {
esp_log("EEPROM Read, write or erase word\n");
eeprom->dat = eeprom->data[address];
}
}
} else if (tick < 26) {
tick++;
if (command == 2) {
esp_log("EEPROM Read Word\n");
eedo = ((eeprom->dat & 0x8000) != 0);
}
eeprom->dat <<= 1;
eeprom->dat += dat;
} else {
esp_log("EEPROM Additional unneeded tick, not processed\n");
}
}
eeprom->count = tick;
eeprom->oldena = ena;
eeprom->oldclk = clk;
eeprom->out = eedo;
eeprom->address = address;
eeprom->opcode = command;
esp_log("EEPROM EEDO = %d\n", eeprom->out);
}
static void
dc390_load_eeprom(esp_t *dev)
{
ati_eeprom_t *eeprom = &dev->eeprom;
uint8_t *nvr = (uint8_t *) eeprom->data;
int i;
uint16_t checksum = 0;
FILE *fp;
eeprom->out = 1;
fp = nvr_fopen(dev->nvr_path, "rb");
if (fp) {
esp_log("EEPROM Load\n");
if (fread(nvr, 1, 128, fp) != 128)
fatal("dc390_eeprom_load(): Error reading data\n");
fclose(fp);
} else {
for (i = 0; i < 16; i++) {
nvr[i * 2] = 0x57;
nvr[i * 2 + 1] = 0x00;
}
esp_log("EEPROM Defaults\n");
nvr[EE_ADAPT_SCSI_ID] = 7;
nvr[EE_MODE2] = 0x0f;
nvr[EE_TAG_CMD_NUM] = 0x04;
nvr[EE_ADAPT_OPTIONS] = EE_ADAPT_OPTION_F6_F8_AT_BOOT | EE_ADAPT_OPTION_BOOT_FROM_CDROM | EE_ADAPT_OPTION_INT13;
for (i = 0; i < EE_CHKSUM1; i += 2) {
checksum += ((nvr[i] & 0xff) | (nvr[i + 1] << 8));
esp_log("Checksum calc = %04x, nvr = %02x\n", checksum, nvr[i]);
}
checksum = 0x1234 - checksum;
nvr[EE_CHKSUM1] = checksum & 0xff;
nvr[EE_CHKSUM2] = checksum >> 8;
esp_log("EEPROM Checksum = %04x\n", checksum);
}
}
static uint8_t
esp_pci_read(UNUSED(int func), int addr, void *priv)
{
@@ -2181,10 +2011,10 @@ esp_pci_read(UNUSED(int func), int addr, void *priv)
if (!dev->has_bios || dev->local)
return 0x22;
else {
if (dev->eeprom.out)
if (nmc93cxx_eeprom_read(dev->eeprom))
return 0x22;
else {
dev->eeprom.out = 1;
dev->eeprom->dev.out = 1;
return 2;
}
}
@@ -2270,9 +2100,9 @@ esp_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
if (addr == 0x80) {
eesk = val & 0x80 ? 1 : 0;
eedi = val & 0x40 ? 1 : 0;
dc390_write_eeprom(dev, 1, eesk, eedi);
nmc93cxx_eeprom_write(dev->eeprom, 1, eesk, eedi);
} else if (addr == 0xc0)
dc390_write_eeprom(dev, 0, 0, 0);
nmc93cxx_eeprom_write(dev->eeprom, 0, 0, 0);
// esp_log("ESP PCI: Write value %02X to register %02X\n", val, addr);
return;
}
@@ -2371,26 +2201,35 @@ esp_pci_reset(void *priv)
{
esp_t *dev = (esp_t *) priv;
timer_disable(&dev->timer);
if (reset_state != NULL) {
esp_io_remove(dev, dev->PCIBase, 0x80);
esp_bios_disable(dev);
timer_stop(&dev->timer);
reset_state.bios.mapping = dev->bios.mapping;
reset_state->bios.mapping = dev->bios.mapping;
reset_state->timer = dev->timer;
reset_state->pci_slot = dev->pci_slot;
reset_state.timer = dev->timer;
*dev = *reset_state;
reset_state.pci_slot = dev->pci_slot;
memcpy(dev, &reset_state, sizeof(esp_t));
esp_pci_soft_reset(dev);
esp_pci_soft_reset(dev);
esp_log("PCI Reset.\n");
}
}
static void *
dc390_init(const device_t *info)
{
esp_t *dev = calloc(1, sizeof(esp_t));
reset_state = calloc(1, sizeof(esp_t));
const char *bios_rev = NULL;
uint32_t mask = 0;
uint32_t size = 0x8000;
nmc93cxx_eeprom_params_t params;
char eeprom_filename[1024] = { 0 };
char filename[1024] = { 0 };
uint16_t checksum = 0x0000;
uint8_t i;
dev->bus = scsi_get_bus();
@@ -2434,10 +2273,40 @@ dc390_init(const device_t *info)
esp_bios_disable(dev);
if (!dev->local) {
sprintf(dev->nvr_path, "dc390_%i.nvr", device_get_instance());
dev->eeprom_inst = device_get_instance();
snprintf(eeprom_filename, sizeof(eeprom_filename), "dc390_%d.nvr", dev->eeprom_inst);
/* Load the serial EEPROM. */
dc390_load_eeprom(dev);
for (i = 0; i < 16; i++) {
dev->eeprom_data[i * 2] = 0x57;
dev->eeprom_data[i * 2 + 1] = 0x00;
}
esp_log("EEPROM Defaults\n");
dev->eeprom_data[EE_ADAPT_SCSI_ID] = 7;
dev->eeprom_data[EE_MODE2] = 0x0f;
dev->eeprom_data[EE_TAG_CMD_NUM] = 0x04;
dev->eeprom_data[EE_ADAPT_OPTIONS] = EE_ADAPT_OPTION_F6_F8_AT_BOOT | EE_ADAPT_OPTION_BOOT_FROM_CDROM | EE_ADAPT_OPTION_INT13;
for (i = 0; i < EE_CHKSUM1; i += 2) {
checksum += ((dev->eeprom_data[i] & 0xff) | (dev->eeprom_data[i + 1] << 8));
esp_log("Checksum calc = %04x, nvr = %02x\n", checksum, dev->eeprom_data[i]);
}
checksum = 0x1234 - checksum;
dev->eeprom_data[EE_CHKSUM1] = checksum & 0xff;
dev->eeprom_data[EE_CHKSUM2] = checksum >> 8;
params.nwords = 64;
params.default_content = (uint16_t *) dev->eeprom_data;
params.filename = filename;
snprintf(filename, sizeof(filename), "nmc93cxx_eeprom_%s_%d.nvr", info->internal_name, dev->eeprom_inst);
dev->eeprom = device_add_inst_params(&nmc93cxx_device, dev->eeprom_inst, &params);
if (dev->eeprom == NULL) {
free(dev);
return NULL;
}
}
esp_pci_hard_reset(dev);
@@ -2449,7 +2318,7 @@ dc390_init(const device_t *info)
scsi_bus_set_speed(dev->bus, 10000000.0);
memcpy(&reset_state, dev, sizeof(esp_t));
*reset_state = *dev;
return dev;
}
@@ -2622,7 +2491,7 @@ ncr53c9x_mca_init(const device_t *info)
fifo8_create(&dev->fifo, ESP_FIFO_SZ);
fifo8_create(&dev->cmdfifo, ESP_CMDFIFO_SZ);
dev->pos_regs[0] = 0x4f; /* MCA board ID */
dev->pos_regs[0] = 0x4d; /* MCA board ID */
dev->pos_regs[1] = 0x7f;
mca_add(ncr53c9x_mca_read, ncr53c9x_mca_write, ncr53c9x_mca_feedb, NULL, dev);
@@ -2646,6 +2515,11 @@ esp_close(void *priv)
fifo8_destroy(&dev->fifo);
fifo8_destroy(&dev->cmdfifo);
if (reset_state != NULL) {
free(reset_state);
reset_state = NULL;
}
free(dev);
dev = NULL;
}

View File

@@ -33,7 +33,7 @@
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/rom.h>
#include <86box/net_eeprom_nmc93cxx.h>
#include <86box/nmc93cxx.h>
#include <86box/nvr.h>
#include <86box/plat.h>
#include <86box/thread.h>
@@ -4807,10 +4807,10 @@ s3_updatemapping(s3_t *s3)
break;
}
s3->linear_base &= ~(s3->linear_size - 1);
if (s3->linear_base == 0xa0000) {
if ((s3->linear_base == 0xa0000) || (s3->linear_size == 0x10000)) {
mem_mapping_disable(&s3->linear_mapping);
if (!(svga->crtc[0x53] & 0x10)) {
mem_mapping_set_addr(&svga->mapping, s3->linear_base, 0x10000);
mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
svga->banked_mask = 0xffff;
}
} else {
@@ -5071,6 +5071,7 @@ s3_accel_in(uint16_t port, void *priv)
if (FIFO_FULL)
temp = 0xff;
}
s3_log("Read port=%04x, val=%02x.\n", port, temp);
return temp;
case 0x8119:
case 0x9949:
@@ -5127,7 +5128,7 @@ s3_accel_in(uint16_t port, void *priv)
s3->data_available = 0;
}
}
s3_log("FIFO Status Temp=%02x.\n", temp);
s3_log("Read port=%04x, val=%02x.\n", port, temp);
return temp;
case 0x9d48: