Files
86Box/src/vid_ati_eeprom.c

224 lines
10 KiB
C

/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#include "ibm.h"
#include "vid_ati_eeprom.h"
enum
{
EEPROM_IDLE,
EEPROM_WAIT,
EEPROM_OPCODE,
EEPROM_INPUT,
EEPROM_OUTPUT
};
enum
{
EEPROM_OP_EW = 4,
EEPROM_OP_WRITE = 5,
EEPROM_OP_READ = 6,
EEPROM_OP_ERASE = 7,
EEPROM_OP_WRALMAIN = -1
};
enum
{
EEPROM_OP_EWDS = 0,
EEPROM_OP_WRAL = 1,
EEPROM_OP_ERAL = 2,
EEPROM_OP_EWEN = 3
};
void ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type)
{
FILE *f;
eeprom->type = type;
strcpy(eeprom->fn, fn);
f = romfopen(eeprom->fn, "rb");
if (!f)
{
memset(eeprom->data, 0, eeprom->type ? 512 : 128);
return;
}
fread(eeprom->data, 1, eeprom->type ? 512 : 128, f);
fclose(f);
}
void ati_eeprom_save(ati_eeprom_t *eeprom)
{
FILE *f = romfopen(eeprom->fn, "wb");
if (!f) return;
fwrite(eeprom->data, 1, eeprom->type ? 512 : 128, f);
fclose(f);
}
void ati_eeprom_write(ati_eeprom_t *eeprom, int ena, int clk, int dat)
{
int c;
// pclog("EEPROM write %i %i %i\n", ena, clk, dat);
if (!ena)
{
eeprom->out = 1;
}
if (clk && !eeprom->oldclk)
{
if (ena && !eeprom->oldena)
{
eeprom->state = EEPROM_WAIT;
eeprom->opcode = 0;
eeprom->count = 3;
eeprom->out = 1;
}
else if (ena)
{
// pclog("EEPROM receive %i %i %i\n", ena, clk, dat);
switch (eeprom->state)
{
case EEPROM_WAIT:
if (!dat)
break;
eeprom->state = EEPROM_OPCODE;
/* fall through */
case EEPROM_OPCODE:
eeprom->opcode = (eeprom->opcode << 1) | (dat ? 1 : 0);
eeprom->count--;
if (!eeprom->count)
{
// pclog("EEPROM opcode - %i\n", eeprom->opcode);
switch (eeprom->opcode)
{
case EEPROM_OP_WRITE:
eeprom->count = eeprom->type ? 24 : 22;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_READ:
eeprom->count = eeprom->type ? 8 : 6;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_EW:
eeprom->count = 2;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
case EEPROM_OP_ERASE:
eeprom->count = eeprom->type ? 8 : 6;
eeprom->state = EEPROM_INPUT;
eeprom->dat = 0;
break;
}
}
break;
case EEPROM_INPUT:
eeprom->dat = (eeprom->dat << 1) | (dat ? 1 : 0);
eeprom->count--;
if (!eeprom->count)
{
// pclog("EEPROM dat - %02X\n", eeprom->dat);
switch (eeprom->opcode)
{
case EEPROM_OP_WRITE:
// pclog("EEPROM_OP_WRITE addr %02X eeprom_dat %04X\n", (eeprom->dat >> 16) & (eeprom->type ? 255 : 63), eeprom->dat & 0xffff);
if (!eeprom->wp)
{
eeprom->data[(eeprom->dat >> 16) & (eeprom->type ? 255 : 63)] = eeprom->dat & 0xffff;
ati_eeprom_save(eeprom);
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_OP_READ:
eeprom->count = 17;
eeprom->state = EEPROM_OUTPUT;
eeprom->dat = eeprom->data[eeprom->dat];
// pclog("Trigger EEPROM_OUTPUT %04X\n", eeprom->dat);
break;
case EEPROM_OP_EW:
// pclog("EEPROM_OP_EW %i\n", eeprom->dat);
switch (eeprom->dat)
{
case EEPROM_OP_EWDS:
eeprom->wp = 1;
break;
case EEPROM_OP_WRAL:
eeprom->opcode = EEPROM_OP_WRALMAIN;
eeprom->count = 20;
break;
case EEPROM_OP_ERAL:
if (!eeprom->wp)
{
memset(eeprom->data, 0xff, 128);
ati_eeprom_save(eeprom);
}
break;
case EEPROM_OP_EWEN:
eeprom->wp = 0;
break;
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_OP_ERASE:
// pclog("EEPROM_OP_ERASE %i\n", eeprom->dat);
if (!eeprom->wp)
{
eeprom->data[eeprom->dat] = 0xffff;
ati_eeprom_save(eeprom);
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_OP_WRALMAIN:
// pclog("EEPROM_OP_WRAL %04X\n", eeprom->dat);
if (!eeprom->wp)
{
for (c = 0; c < 256; c++)
eeprom->data[c] = eeprom->dat;
ati_eeprom_save(eeprom);
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
}
}
break;
}
}
eeprom->oldena = ena;
}
else if (!clk && eeprom->oldclk)
{
if (ena)
{
switch (eeprom->state)
{
case EEPROM_OUTPUT:
eeprom->out = (eeprom->dat & 0x10000) ? 1 : 0;
eeprom->dat <<= 1;
// pclog("EEPROM_OUTPUT - data %i\n", eeprom->out);
eeprom->count--;
if (!eeprom->count)
{
// pclog("EEPROM_OUTPUT complete\n");
eeprom->state = EEPROM_IDLE;
}
break;
}
}
}
eeprom->oldclk = clk;
}
int ati_eeprom_read(ati_eeprom_t *eeprom)
{
return eeprom->out;
}