Merge pull request #3847 from 86Box/tc1995
DEC/Tulip/Intel 21140/21143 fixes:
This commit is contained in:
@@ -16,34 +16,27 @@
|
|||||||
|
|
||||||
/* Ported over from QEMU */
|
/* Ported over from QEMU */
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <wchar.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#define HAVE_STDARG_H
|
||||||
#include <86box/86box.h>
|
#include <86box/86box.h>
|
||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
#include <86box/timer.h>
|
#include <86box/timer.h>
|
||||||
#include <86box/nvr.h>
|
#include <86box/nvr.h>
|
||||||
|
#include <86box/vid_ati_eeprom.h>
|
||||||
#include <86box/net_eeprom_nmc93cxx.h>
|
#include <86box/net_eeprom_nmc93cxx.h>
|
||||||
#include <86box/plat_unused.h>
|
#include <86box/plat_unused.h>
|
||||||
|
|
||||||
struct nmc93cxx_eeprom_t {
|
struct nmc93cxx_eeprom_t {
|
||||||
uint8_t tick;
|
ati_eeprom_t dev;
|
||||||
uint8_t address;
|
|
||||||
uint8_t command;
|
|
||||||
uint8_t writable;
|
|
||||||
|
|
||||||
uint8_t eecs;
|
|
||||||
uint8_t eesk;
|
|
||||||
uint8_t eedo;
|
|
||||||
|
|
||||||
uint8_t addrbits;
|
uint8_t addrbits;
|
||||||
uint16_t size;
|
uint16_t size;
|
||||||
uint16_t data;
|
|
||||||
char filename[1024];
|
char filename[1024];
|
||||||
uint16_t contents[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct nmc93cxx_eeprom_t nmc93cxx_eeprom_t;
|
typedef struct nmc93cxx_eeprom_t nmc93cxx_eeprom_t;
|
||||||
@@ -66,6 +59,16 @@ nmc93cxx_eeprom_log(int lvl, const char *fmt, ...)
|
|||||||
# define nmc93cxx_eeprom_log(lvl, fmt, ...)
|
# define nmc93cxx_eeprom_log(lvl, fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
nmc93cxx_eeprom_save(nmc93cxx_eeprom_t *eeprom)
|
||||||
|
{
|
||||||
|
FILE *fp = nvr_fopen(eeprom->filename, "wb");
|
||||||
|
if (fp) {
|
||||||
|
fwrite(eeprom->dev.data, 2, eeprom->size, fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
nmc93cxx_eeprom_init_params(UNUSED(const device_t *info), void *params)
|
nmc93cxx_eeprom_init_params(UNUSED(const device_t *info), void *params)
|
||||||
{
|
{
|
||||||
@@ -99,19 +102,19 @@ nmc93cxx_eeprom_init_params(UNUSED(const device_t *info), void *params)
|
|||||||
eeprom->size = nwords;
|
eeprom->size = nwords;
|
||||||
eeprom->addrbits = addrbits;
|
eeprom->addrbits = addrbits;
|
||||||
/* Output DO is tristate, read results in 1. */
|
/* Output DO is tristate, read results in 1. */
|
||||||
eeprom->eedo = 1;
|
eeprom->dev.out = 1;
|
||||||
|
|
||||||
if (params_details->filename) {
|
if (params_details->filename) {
|
||||||
FILE *fp = nvr_fopen(params_details->filename, "rb");
|
FILE *fp = nvr_fopen(params_details->filename, "rb");
|
||||||
strncpy(eeprom->filename, params_details->filename, sizeof(eeprom->filename) - 1);
|
strncpy(eeprom->filename, params_details->filename, sizeof(eeprom->filename) - 1);
|
||||||
if (fp) {
|
if (fp) {
|
||||||
filldefault = !fread(eeprom->contents, sizeof(uint16_t), nwords, fp);
|
filldefault = !fread(eeprom->dev.data, sizeof(uint16_t), nwords, fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filldefault) {
|
if (filldefault) {
|
||||||
memcpy(eeprom->contents, params_details->default_content, nwords * sizeof(uint16_t));
|
memcpy(eeprom->dev.data, params_details->default_content, nwords * sizeof(uint16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
return eeprom;
|
return eeprom;
|
||||||
@@ -120,47 +123,47 @@ nmc93cxx_eeprom_init_params(UNUSED(const device_t *info), void *params)
|
|||||||
void
|
void
|
||||||
nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi)
|
nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi)
|
||||||
{
|
{
|
||||||
uint8_t tick = eeprom->tick;
|
uint8_t tick = eeprom->dev.count;
|
||||||
uint8_t eedo = eeprom->eedo;
|
uint8_t eedo = eeprom->dev.out;
|
||||||
uint16_t address = eeprom->address;
|
uint16_t address = eeprom->dev.address;
|
||||||
uint8_t command = eeprom->command;
|
uint8_t command = eeprom->dev.opcode;
|
||||||
|
|
||||||
nmc93cxx_eeprom_log(1, "CS=%u SK=%u DI=%u DO=%u, tick = %u\n",
|
nmc93cxx_eeprom_log(1, "CS=%u SK=%u DI=%u DO=%u, tick = %u\n",
|
||||||
eecs, eesk, eedi, eedo, tick);
|
eecs, eesk, eedi, eedo, tick);
|
||||||
|
|
||||||
if (!eeprom->eecs && eecs) {
|
if (!eeprom->dev.oldena && eecs) {
|
||||||
/* Start chip select cycle. */
|
/* Start chip select cycle. */
|
||||||
nmc93cxx_eeprom_log(1, "Cycle start, waiting for 1st start bit (0)\n");
|
nmc93cxx_eeprom_log(1, "Cycle start, waiting for 1st start bit (0)\n");
|
||||||
tick = 0;
|
tick = 0;
|
||||||
command = 0x0;
|
command = 0x0;
|
||||||
address = 0x0;
|
address = 0x0;
|
||||||
} else if (eeprom->eecs && !eecs) {
|
} else if (eeprom->dev.oldena && !eecs) {
|
||||||
/* End chip select cycle. This triggers write / erase. */
|
/* End chip select cycle. This triggers write / erase. */
|
||||||
if (eeprom->writable) {
|
if (!eeprom->dev.wp) {
|
||||||
uint8_t subcommand = address >> (eeprom->addrbits - 2);
|
uint8_t subcommand = address >> (eeprom->addrbits - 2);
|
||||||
if (command == 0 && subcommand == 2) {
|
if (command == 0 && subcommand == 2) {
|
||||||
/* Erase all. */
|
/* Erase all. */
|
||||||
for (address = 0; address < eeprom->size; address++) {
|
for (address = 0; address < eeprom->size; address++) {
|
||||||
eeprom->contents[address] = 0xffff;
|
eeprom->dev.data[address] = 0xffff;
|
||||||
}
|
}
|
||||||
} else if (command == 3) {
|
} else if (command == 3) {
|
||||||
/* Erase word. */
|
/* Erase word. */
|
||||||
eeprom->contents[address] = 0xffff;
|
eeprom->dev.data[address] = 0xffff;
|
||||||
} else if (tick >= 2 + 2 + eeprom->addrbits + 16) {
|
} else if (tick >= 2 + 2 + eeprom->addrbits + 16) {
|
||||||
if (command == 1) {
|
if (command == 1) {
|
||||||
/* Write word. */
|
/* Write word. */
|
||||||
eeprom->contents[address] &= eeprom->data;
|
eeprom->dev.data[address] &= eeprom->dev.dat;
|
||||||
} else if (command == 0 && subcommand == 1) {
|
} else if (command == 0 && subcommand == 1) {
|
||||||
/* Write all. */
|
/* Write all. */
|
||||||
for (address = 0; address < eeprom->size; address++) {
|
for (address = 0; address < eeprom->size; address++) {
|
||||||
eeprom->contents[address] &= eeprom->data;
|
eeprom->dev.data[address] &= eeprom->dev.dat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Output DO is tristate, read results in 1. */
|
/* Output DO is tristate, read results in 1. */
|
||||||
eedo = 1;
|
eedo = 1;
|
||||||
} else if (eecs && !eeprom->eesk && eesk) {
|
} else if (eecs && !eeprom->dev.oldclk && eesk) {
|
||||||
/* Raising edge of clock shifts data in. */
|
/* Raising edge of clock shifts data in. */
|
||||||
if (tick == 0) {
|
if (tick == 0) {
|
||||||
/* Wait for 1st start bit. */
|
/* Wait for 1st start bit. */
|
||||||
@@ -194,8 +197,8 @@ nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi)
|
|||||||
tick++;
|
tick++;
|
||||||
address = ((address << 1) | eedi);
|
address = ((address << 1) | eedi);
|
||||||
if (tick == 2 + 2 + eeprom->addrbits) {
|
if (tick == 2 + 2 + eeprom->addrbits) {
|
||||||
nmc93cxx_eeprom_log(1, "%s command, address = 0x%02x (value 0x%04x)\n",
|
nmc93cxx_eeprom_log(1, "Address = 0x%02x (value 0x%04x)\n",
|
||||||
opstring[command], address, eeprom->contents[address]);
|
address, eeprom->dev.data[address]);
|
||||||
if (command == 2) {
|
if (command == 2) {
|
||||||
eedo = 0;
|
eedo = 0;
|
||||||
}
|
}
|
||||||
@@ -205,7 +208,7 @@ nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi)
|
|||||||
switch (address >> (eeprom->addrbits - 2)) {
|
switch (address >> (eeprom->addrbits - 2)) {
|
||||||
case 0:
|
case 0:
|
||||||
nmc93cxx_eeprom_log(1, "write disable command\n");
|
nmc93cxx_eeprom_log(1, "write disable command\n");
|
||||||
eeprom->writable = 0;
|
eeprom->dev.wp = 1;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
nmc93cxx_eeprom_log(1, "write all command\n");
|
nmc93cxx_eeprom_log(1, "write all command\n");
|
||||||
@@ -215,7 +218,7 @@ nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi)
|
|||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
nmc93cxx_eeprom_log(1, "write enable command\n");
|
nmc93cxx_eeprom_log(1, "write enable command\n");
|
||||||
eeprom->writable = 1;
|
eeprom->dev.wp = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -223,7 +226,7 @@ nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Read, write or erase word. */
|
/* Read, write or erase word. */
|
||||||
eeprom->data = eeprom->contents[address];
|
eeprom->dev.dat = eeprom->dev.data[address];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (tick < 2 + 2 + eeprom->addrbits + 16) {
|
} else if (tick < 2 + 2 + eeprom->addrbits + 16) {
|
||||||
@@ -231,28 +234,28 @@ nmc93cxx_eeprom_write(nmc93cxx_eeprom_t *eeprom, int eecs, int eesk, int eedi)
|
|||||||
tick++;
|
tick++;
|
||||||
if (command == 2) {
|
if (command == 2) {
|
||||||
/* Read word. */
|
/* Read word. */
|
||||||
eedo = ((eeprom->data & 0x8000) != 0);
|
eedo = ((eeprom->dev.dat & 0x8000) != 0);
|
||||||
}
|
}
|
||||||
eeprom->data <<= 1;
|
eeprom->dev.dat <<= 1;
|
||||||
eeprom->data += eedi;
|
eeprom->dev.dat += eedi;
|
||||||
} else {
|
} else {
|
||||||
nmc93cxx_eeprom_log(1, "additional unneeded tick, not processed\n");
|
nmc93cxx_eeprom_log(1, "additional unneeded tick, not processed\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Save status of EEPROM. */
|
/* Save status of EEPROM. */
|
||||||
eeprom->tick = tick;
|
eeprom->dev.count = tick;
|
||||||
eeprom->eecs = eecs;
|
eeprom->dev.oldena = eecs;
|
||||||
eeprom->eesk = eesk;
|
eeprom->dev.oldclk = eesk;
|
||||||
eeprom->eedo = eedo;
|
eeprom->dev.out = eedo;
|
||||||
eeprom->address = address;
|
eeprom->dev.address = address;
|
||||||
eeprom->command = command;
|
eeprom->dev.opcode = command;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t
|
uint16_t
|
||||||
nmc93cxx_eeprom_read(nmc93cxx_eeprom_t *eeprom)
|
nmc93cxx_eeprom_read(nmc93cxx_eeprom_t *eeprom)
|
||||||
{
|
{
|
||||||
/* Return status of pin DO (0 or 1). */
|
/* Return status of pin DO (0 or 1). */
|
||||||
return eeprom->eedo;
|
return eeprom->dev.out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -261,7 +264,7 @@ nmc93cxx_eeprom_close(void *priv)
|
|||||||
nmc93cxx_eeprom_t *eeprom = (nmc93cxx_eeprom_t *) priv;
|
nmc93cxx_eeprom_t *eeprom = (nmc93cxx_eeprom_t *) priv;
|
||||||
FILE *fp = nvr_fopen(eeprom->filename, "wb");
|
FILE *fp = nvr_fopen(eeprom->filename, "wb");
|
||||||
if (fp) {
|
if (fp) {
|
||||||
fwrite(eeprom->contents, 2, eeprom->size, fp);
|
fwrite(eeprom->dev.data, 2, eeprom->size, fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
free(priv);
|
free(priv);
|
||||||
@@ -271,7 +274,7 @@ uint16_t *
|
|||||||
nmc93cxx_eeprom_data(nmc93cxx_eeprom_t *eeprom)
|
nmc93cxx_eeprom_data(nmc93cxx_eeprom_t *eeprom)
|
||||||
{
|
{
|
||||||
/* Get EEPROM data array. */
|
/* Get EEPROM data array. */
|
||||||
return &eeprom->contents[0];
|
return &eeprom->dev.data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_t nmc93cxx_device = {
|
const device_t nmc93cxx_device = {
|
||||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user