Merge pull request #6124 from 86Box/tc1995

EEPROM and misc changes (September 3rd, 2025)
This commit is contained in:
Miran Grča
2025-09-03 00:55:18 +02:00
committed by GitHub
8 changed files with 90 additions and 210 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

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: