/*Arculator 2.2 by Sarah Walker
  82c711 SuperIO emulation*/
#include "arc.h"
#include "82c711.h"
#include "82c711_fdc.h"
#include "config.h"
#include "ide.h"
#include "ioc.h"
#include "printer.h"

static int configmode, configindex;
static uint8_t configregs[16];

void c82c711_write(uint32_t addr, uint8_t val)
{
//        rpclog("c82c711 write %08X %02X  ", addr, val);
	addr = (addr >> 2) & 0x3ff;
//        rpclog("%03X %03X\n", addr, addr & ~7);

	if (configmode!=2)
	{
		if ((addr == 0x3F0) && (val == 0x55))
		{
			configmode++;
			return;
		}
		else
		   configmode = 0;
	}
	if (configmode == 2 && addr == 0x3F0 && val == 0xAA)
	{
		configmode = 0;
//                printf("Cleared config mode\n");
		return;
	}
	if (configmode == 2 && addr == 0x3F0)
	{
		configindex = val;
		return;
	}
	if (configmode == 2 && addr == 0x3F1)
	{
		configregs[configindex & 15] = val;
		return;
	}


	if ((addr & ~7) == 0x1f0 || addr == 0x3F6)
	   writeide(&ide_internal, addr, val);

	if ((addr & ~7) == 0x3f0 && addr != 0x3f6)
		c82c711_fdc_write(addr & 7, val, NULL);

	if ((addr & 0x3ff) == 0x278)
		printer_data_write(val);
}

uint8_t c82c711_read(uint32_t addr)
{
//        rpclog("c82c711 read %08X  ", addr);
	addr = (addr >> 2) & 0x3ff;
//        rpclog("%03X\n", addr);

	if (configmode == 2 && addr == 0x3F1)
	{
		return configregs[configindex & 15];
	}

	if (addr == 0x391) return 0xE4; /*RISC OS 3.00*/
	if (addr == 0x3FF) return 0x55;

	if ((addr & ~7) == 0x1f0 || addr == 0x3F6)
	   return readide(&ide_internal, addr);

	if ((addr & ~7) == 0x3f0)
		return c82c711_fdc_read(addr & 7, NULL);

	if ((addr & 0x3ff) == 0x279)
		return printer_status_read();

	return 0xff;
}

static void c82c711_ide_irq_raise(ide_t *ide)
{
	ioc_irqb(IOC_IRQB_IDE);
}
static void c82c711_ide_irq_clear(ide_t *ide)
{
	ioc_irqbc(IOC_IRQB_IDE);
}

void c82c711_init(void)
{
	resetide(&ide_internal,
		 hd_fn[0], hd_spt[0], hd_hpc[0], hd_cyl[0],
		 hd_fn[1], hd_spt[1], hd_hpc[1], hd_cyl[1],
		 c82c711_ide_irq_raise, c82c711_ide_irq_clear);
}
