mirror of
https://github.com/86Box/86Box.git
synced 2026-02-25 04:45:31 -07:00
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:
@@ -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)
|
||||
|
||||
@@ -1,283 +0,0 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of National Semiconductors NMC93Cxx EEPROMs.
|
||||
*
|
||||
*
|
||||
* Authors: Cacodemon345
|
||||
*
|
||||
* Copyright 2023 Cacodemon345
|
||||
*/
|
||||
|
||||
/* Ported over from QEMU */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <wchar.h>
|
||||
#include <time.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/nvr.h>
|
||||
#include <86box/net_eeprom_nmc93cxx.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
#ifdef ENABLE_NMC93CXX_EEPROM_LOG
|
||||
int nmc93cxx_eeprom_do_log = ENABLE_NMC93CXX_EEPROM_LOG;
|
||||
|
||||
static void
|
||||
nmc93cxx_eeprom_log(int lvl, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (nmc93cxx_eeprom_do_log >= lvl) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define nmc93cxx_eeprom_log(lvl, fmt, ...)
|
||||
#endif
|
||||
|
||||
static void *
|
||||
nmc93cxx_eeprom_init(const device_t *info)
|
||||
{
|
||||
uint16_t nwords = 64;
|
||||
uint8_t addrbits = 6;
|
||||
uint8_t filldefault = 1;
|
||||
nmc93cxx_eeprom_params_t *params_details = (nmc93cxx_eeprom_params_t *) info->local;
|
||||
nmc93cxx_eeprom_t *eeprom = NULL;
|
||||
if (info->local == 0)
|
||||
return NULL;
|
||||
|
||||
nwords = params_details->nwords;
|
||||
|
||||
switch (nwords) {
|
||||
case 16:
|
||||
case 64:
|
||||
addrbits = 6;
|
||||
break;
|
||||
case 128:
|
||||
case 256:
|
||||
addrbits = 8;
|
||||
break;
|
||||
default:
|
||||
nwords = 64;
|
||||
addrbits = 6;
|
||||
break;
|
||||
}
|
||||
eeprom = calloc(1, sizeof(nmc93cxx_eeprom_t) + ((nwords + 1) * 2));
|
||||
if (!eeprom)
|
||||
return NULL;
|
||||
eeprom->size = nwords;
|
||||
eeprom->addrbits = addrbits;
|
||||
/* Output DO is tristate, read results in 1. */
|
||||
eeprom->dev.out = 1;
|
||||
|
||||
if (params_details->filename) {
|
||||
FILE *fp = nvr_fopen(params_details->filename, "rb");
|
||||
strncpy(eeprom->filename, params_details->filename, sizeof(eeprom->filename) - 1);
|
||||
if (fp) {
|
||||
filldefault = !fread(eeprom->dev.data, sizeof(uint16_t), nwords, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
if (filldefault) {
|
||||
memcpy(eeprom->dev.data, params_details->default_content, nwords * sizeof(uint16_t));
|
||||
}
|
||||
|
||||
return eeprom;
|
||||
}
|
||||
|
||||
static void
|
||||
nmc93cxx_eeprom_save(nmc93cxx_eeprom_t *eeprom)
|
||||
{
|
||||
FILE *fp = nvr_fopen(eeprom->filename, "wb");
|
||||
if (!fp)
|
||||
return;
|
||||
fwrite(eeprom->dev.data, 2, eeprom->size, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void
|
||||
nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi)
|
||||
{
|
||||
uint8_t tick = eeprom->dev.count;
|
||||
uint8_t eedo = eeprom->dev.out;
|
||||
uint16_t address = eeprom->dev.address;
|
||||
uint8_t command = eeprom->dev.opcode;
|
||||
|
||||
nmc93cxx_eeprom_log(1, "CS=%u SK=%u DI=%u DO=%u, tick = %u\n",
|
||||
eecs, eesk, eedi, eedo, tick);
|
||||
|
||||
if (!eeprom->dev.oldena && eecs) {
|
||||
/* Start chip select cycle. */
|
||||
nmc93cxx_eeprom_log(1, "Cycle start, waiting for 1st start bit (0)\n");
|
||||
tick = 0;
|
||||
command = 0x0;
|
||||
address = 0x0;
|
||||
} else if (eeprom->dev.oldena && !eecs) {
|
||||
/* End chip select cycle. This triggers write / erase. */
|
||||
if (!eeprom->dev.wp) {
|
||||
uint8_t subcommand = address >> (eeprom->addrbits - 2);
|
||||
if (command == 0 && subcommand == 2) {
|
||||
/* Erase all. */
|
||||
for (address = 0; address < eeprom->size; address++)
|
||||
eeprom->dev.data[address] = 0xffff;
|
||||
|
||||
nmc93cxx_eeprom_save(eeprom);
|
||||
} else if (command == 3) {
|
||||
/* Erase word. */
|
||||
eeprom->dev.data[address] = 0xffff;
|
||||
nmc93cxx_eeprom_save(eeprom);
|
||||
} else if (tick >= (2 + 2 + eeprom->addrbits + 16)) {
|
||||
if (command == 1) {
|
||||
/* Write word. */
|
||||
eeprom->dev.data[address] &= eeprom->dev.dat;
|
||||
nmc93cxx_eeprom_save(eeprom);
|
||||
} else if (command == 0 && subcommand == 1) {
|
||||
/* Write all. */
|
||||
for (address = 0; address < eeprom->size; address++)
|
||||
eeprom->dev.data[address] &= eeprom->dev.dat;
|
||||
|
||||
nmc93cxx_eeprom_save(eeprom);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Output DO is tristate, read results in 1. */
|
||||
eedo = 1;
|
||||
} else if (eecs && !eeprom->dev.oldclk && eesk) {
|
||||
/* Raising edge of clock shifts data in. */
|
||||
if (tick == 0) {
|
||||
/* Wait for 1st start bit. */
|
||||
if (eedi == 0) {
|
||||
nmc93cxx_eeprom_log(1, "Got correct 1st start bit, waiting for 2nd start bit (1)\n");
|
||||
tick++;
|
||||
} else {
|
||||
nmc93cxx_eeprom_log(1, "wrong 1st start bit (is 1, should be 0)\n");
|
||||
tick = 2;
|
||||
#if 0
|
||||
~ assert(!"wrong start bit");
|
||||
#endif
|
||||
}
|
||||
} else if (tick == 1) {
|
||||
/* Wait for 2nd start bit. */
|
||||
if (eedi != 0) {
|
||||
nmc93cxx_eeprom_log(1, "Got correct 2nd start bit, getting command + address\n");
|
||||
tick++;
|
||||
} else {
|
||||
nmc93cxx_eeprom_log(1, "1st start bit is longer than needed\n");
|
||||
}
|
||||
} else if (tick < 2 + 2) {
|
||||
/* Got 2 start bits, transfer 2 opcode bits. */
|
||||
tick++;
|
||||
command <<= 1;
|
||||
if (eedi) {
|
||||
command += 1;
|
||||
}
|
||||
} else if (tick < 2 + 2 + eeprom->addrbits) {
|
||||
/* Got 2 start bits and 2 opcode bits, transfer all address bits. */
|
||||
tick++;
|
||||
address = ((address << 1) | eedi);
|
||||
if (tick == 2 + 2 + eeprom->addrbits) {
|
||||
nmc93cxx_eeprom_log(1, "Address = 0x%02x (value 0x%04x)\n",
|
||||
address, eeprom->dev.data[address]);
|
||||
if (command == 2) {
|
||||
eedo = 0;
|
||||
}
|
||||
address = address % eeprom->size;
|
||||
if (command == 0) {
|
||||
/* Command code in upper 2 bits of address. */
|
||||
switch (address >> (eeprom->addrbits - 2)) {
|
||||
case 0:
|
||||
nmc93cxx_eeprom_log(1, "write disable command\n");
|
||||
eeprom->dev.wp = 1;
|
||||
break;
|
||||
case 1:
|
||||
nmc93cxx_eeprom_log(1, "write all command\n");
|
||||
break;
|
||||
case 2:
|
||||
nmc93cxx_eeprom_log(1, "erase all command\n");
|
||||
break;
|
||||
case 3:
|
||||
nmc93cxx_eeprom_log(1, "write enable command\n");
|
||||
eeprom->dev.wp = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Read, write or erase word. */
|
||||
eeprom->dev.dat = eeprom->dev.data[address];
|
||||
}
|
||||
}
|
||||
} else if (tick < 2 + 2 + eeprom->addrbits + 16) {
|
||||
/* Transfer 16 data bits. */
|
||||
tick++;
|
||||
if (command == 2) {
|
||||
/* Read word. */
|
||||
eedo = ((eeprom->dev.dat & 0x8000) != 0);
|
||||
}
|
||||
eeprom->dev.dat <<= 1;
|
||||
eeprom->dev.dat += eedi;
|
||||
} else {
|
||||
nmc93cxx_eeprom_log(1, "additional unneeded tick, not processed\n");
|
||||
}
|
||||
}
|
||||
/* Save status of EEPROM. */
|
||||
eeprom->dev.count = tick;
|
||||
eeprom->dev.oldena = eecs;
|
||||
eeprom->dev.oldclk = eesk;
|
||||
eeprom->dev.out = eedo;
|
||||
eeprom->dev.address = address;
|
||||
eeprom->dev.opcode = command;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
nmc93cxx_eeprom_read(nmc93cxx_eeprom_t *eeprom)
|
||||
{
|
||||
/* Return status of pin DO (0 or 1). */
|
||||
return eeprom->dev.out;
|
||||
}
|
||||
|
||||
static void
|
||||
nmc93cxx_eeprom_close(void *priv)
|
||||
{
|
||||
nmc93cxx_eeprom_t *eeprom = (nmc93cxx_eeprom_t *) priv;
|
||||
free(eeprom);
|
||||
}
|
||||
|
||||
uint16_t *
|
||||
nmc93cxx_eeprom_data(nmc93cxx_eeprom_t *eeprom)
|
||||
{
|
||||
if (UNLIKELY(eeprom == NULL))
|
||||
return NULL;
|
||||
/* Get EEPROM data array. */
|
||||
return &eeprom->dev.data[0];
|
||||
}
|
||||
|
||||
const device_t nmc93cxx_device = {
|
||||
.name = "National Semiconductor NMC93Cxx",
|
||||
.internal_name = "nmc93cxx",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = nmc93cxx_eeprom_init,
|
||||
.close = nmc93cxx_eeprom_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user