/*
    armio.c - I/O registers and interrupt controller.
    ARMulator extensions for the ARM7100 family.
    Copyright (C) 1999  Ben Williamson

	Changes to support running uClinux/Atmel AT91 targets
    Copyright (C) 2002  David McCullough <davidm@snapgear.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include "armdefs.h"

/*
 *  7/17/2003     clean some routine.
 *                clean io_reset only to do special mach_io_reset function.
 *                wlm <wlm@student.dlut.edu.cn>
 */

/*chy 2003-01-14 */

//extern int big_endian;

#if 0
static void update_lcd(ARMul_State *state)
{
	lcd_disable(state);
	if (state->io.syscon & LCDEN) {
		ARMword lcdcon = state->io.lcdcon;
		ARMword vbufsiz = lcdcon & VBUFSIZ;

		ARMword linelen = (lcdcon & LINELEN) >> LINELEN_SHIFT;
		int width, height, depth;

		switch (lcdcon & (GSEN|GSMD)) {
		case GSEN:
			depth = 2;
			break;
		case GSEN|GSMD:
			depth = 4;
			break;
		default:
			depth = 1;
			break;
		}
		width = (linelen + 1) * 16;
		height = (vbufsiz + 1) * 128 / depth / width;
		lcd_enable(state, width, height, depth);
	}
}

#endif

/* Reset IO. 
 * Now only reset some Internal IO Register.
 * Every machine has a reset routine to init it's special registers.
 * wlm 2003/7/17
 * */
void
io_reset(ARMul_State *state)
{
	skyeye_config.mach->mach_io_reset(state);
}

void
io_do_cycle(ARMul_State *state)
{
	skyeye_config.mach->mach_io_do_cycle(state);

#if BENW_PATCH
		/* keep the UI alive */
		//lcd_cycle(state);
#endif

}

unsigned char
mem_read_char(ARMul_State *state, ARMword addr)
{
	union {
		unsigned char buf[4];
		ARMword	w;
	} tmp;

	tmp.w = mem_read_word(state, addr & ~0x3);
	if (state->bigendSig == HIGH)
	//if (big_endian)
		return(tmp.buf[3 - (addr & 0x3)]);
	return(tmp.buf[addr & 0x3]);
}

void
mem_write_char(ARMul_State *state, ARMword addr, unsigned char c)
{
	union {
		unsigned char buf[4];
		ARMword	w;
	} tmp;

	tmp.w = mem_read_word(state, addr & ~0x3);
	if (state->bigendSig == HIGH) /*big enddian?*/
	//if (big_endian)
		tmp.buf[3 - (addr & 0x3)] = c;
	else
		tmp.buf[addr & 0x3] = c;
	mem_write_word(state, addr & ~0x3, tmp.w);
}

/* Internal registers from 0x80000000 to 0x80002000.
   We also define a "debug I/O" register thereafter. */

ARMword
io_read_byte(ARMul_State *state, ARMword addr)
{
	skyeye_config.mach->mach_io_read_byte(state, addr);
}
ARMword
io_read_halfword(ARMul_State *state, ARMword addr)
{
	skyeye_config.mach->mach_io_read_halfword(state, addr);
}
ARMword
io_read_word(ARMul_State *state, ARMword addr)
{
	skyeye_config.mach->mach_io_read_word(state, addr);
}

void
io_write_byte(ARMul_State *state, ARMword addr, ARMword data)
{
	skyeye_config.mach->mach_io_write_byte(state, addr, data);
}
void
io_write_halfword(ARMul_State *state, ARMword addr, ARMword data)
{
	skyeye_config.mach->mach_io_write_halfword(state, addr, data);
}
void
io_write_word(ARMul_State *state, ARMword addr, ARMword data)
{
	skyeye_config.mach->mach_io_write_word(state, addr, data);
}
