Files
86Box/src/video/vid_ati_eeprom.c
OBattler a412ceb4d9 Applied all relevant PCem commits;
Extensively cleaned up and changed the CD-ROM code;
Removed CD-ROM IOCTTL (it was causing performance and stability issues);
Turned a lot of things into device_t's;
Added the PS/1 Model 2011 XTA and standalone XTA hard disk controllers, ported from Varcem;
Numerous FDC fixes for the PS/1 Model 2121;
NVR changes ported from Varcem;
The PCap code no longer requires libpcap to be compiled;
Numerous fixes to various SCSI controllers;
Updated NukedOPL to 1.8;
Fixes to OpenAL initialization and closing, should give less Audio issues now;
Revorked parts of the common (S)VGA code (also based on code from QEMU);
Removed the Removable SCSI hard disks (they were a never finished experiment so there was no need to keep them there);
Cleaned up the SCSI hard disk and Iomega ZIP code (but more cleanups of that are coming in the future);
In some occasions (IDE hard disks in multiple sector mode and SCSI hard disks) the status bar icon is no longer updated, should improve performance a bit;
Redid the way the tertiary and quaternary IDE controllers are configured (and they are now device_t's);
Extensively reworked the IDE code and fixed quite a few bugs;
Fixes to XT MFM, AT MFM, and AT ESDI code;
Some changes to XTIDE and MCA ESDI code;
Some fixes to the CD-ROM image handler.
2018-04-25 23:51:13 +02:00

236 lines
9.7 KiB
C

/*
* 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 the EEPROM on select ATI cards.
*
* Version: @(#)vid_ati_eeprom.c 1.0.2 2018/04/11
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../device.h"
#include "../mem.h"
#include "../nvr.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, wchar_t *fn, int type)
{
FILE *f;
eeprom->type = type;
wcscpy(eeprom->fn, fn);
f = nvr_fopen(eeprom->fn, L"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 = nvr_fopen(eeprom->fn, L"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;
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)
{
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)
{
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)
{
switch (eeprom->opcode)
{
case EEPROM_OP_WRITE:
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];
break;
case EEPROM_OP_EW:
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:
if (!eeprom->wp)
{
eeprom->data[eeprom->dat] = 0xffff;
ati_eeprom_save(eeprom);
}
eeprom->state = EEPROM_IDLE;
eeprom->out = 1;
break;
case EEPROM_OP_WRALMAIN:
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;
eeprom->count--;
if (!eeprom->count)
{
eeprom->state = EEPROM_IDLE;
}
break;
}
}
}
eeprom->oldclk = clk;
}
int ati_eeprom_read(ati_eeprom_t *eeprom)
{
return eeprom->out;
}