📄 armio.c
字号:
/*
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>
*/
/* 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
* */
/* some machine need less number. e.g. s3c2440 only need DIVISOR = 1 to boot*/
#define DIVISOR (50)
static int prescale = DIVISOR;
void
io_reset (ARMul_State * state)
{
struct device_desc *dev;
int i;
for (i = 0; i < skyeye_config.mach->dev_count; i++)
{
dev = skyeye_config.mach->devices[i];
if (dev->reset)
dev->reset (dev);
}
skyeye_config.mach->mach_io_reset (state);
}
void
io_do_cycle (ARMul_State * state)
{
struct device_desc *dev;
int i;
prescale--;
if (prescale < 0)
{
prescale = DIVISOR;
for (i = 0; i < skyeye_config.mach->dev_count; i++)
{
dev = skyeye_config.mach->devices[i];
if (dev->update)
dev->update (dev);
}
skyeye_config.mach->mach_io_do_cycle (state);
}
}
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)
{
struct device_desc *dev;
ARMword data;
int i;
for (i = 0; i < skyeye_config.mach->dev_count; i++)
{
dev = skyeye_config.mach->devices[i];
if (!dev->read_byte)
continue;
/* if we specify size=0, we don't check
* whether "addr" is in the range of address space of device.
* */
if (dev->size == 0)
{
if (dev->read_byte (dev, addr, (u8 *) & data) != ADDR_NOHIT)
return data;
}
else if ((addr >= dev->base) && (addr < (dev->base + dev->size)))
{
if (dev->read_byte (dev, addr, (u8 *) & data) != ADDR_NOHIT)
return data;
}
}
return skyeye_config.mach->mach_io_read_byte (state, addr);
}
ARMword
io_read_halfword (ARMul_State * state, ARMword addr)
{
struct device_desc *dev;
ARMword data;
int i;
for (i = 0; i < skyeye_config.mach->dev_count; i++)
{
dev = skyeye_config.mach->devices[i];
if (!dev->read_halfword)
continue;
/* if we specify size=0, we don't check
* whether "addr" is in the range of address space of device.
* */
if (dev->size == 0)
{
if (dev->read_halfword (dev, addr, (u16 *) & data) != ADDR_NOHIT)
return data;
}
else if ((addr >= dev->base) && (addr < (dev->base + dev->size)))
{
if (dev->read_halfword (dev, addr, (u16 *) & data) != ADDR_NOHIT)
return data;
}
}
return skyeye_config.mach->mach_io_read_halfword (state, addr);
}
ARMword
io_read_word (ARMul_State * state, ARMword addr)
{
struct device_desc *dev;
ARMword data;
int i;
for (i = 0; i < skyeye_config.mach->dev_count; i++)
{
dev = skyeye_config.mach->devices[i];
if (!dev->read_word)
continue;
/* if we specify size=0, we don't check
* whether "addr" is in the range of address space of device.
* */
if (dev->size == 0)
{
if (dev->read_word (dev, addr, (u32 *) & data) != ADDR_NOHIT)
return data;
}
else if ((addr >= dev->base) && (addr < (dev->base + dev->size)))
{
if (dev->read_word (dev, addr, (u32 *) & data) != ADDR_NOHIT)
return data;
}
}
return skyeye_config.mach->mach_io_read_word (state, addr);
}
void
io_write_byte (ARMul_State * state, ARMword addr, ARMword data)
{
struct device_desc *dev;
int i;
for (i = 0; i < skyeye_config.mach->dev_count; i++)
{
dev = skyeye_config.mach->devices[i];
if (!dev->write_byte)
continue;
/* if we specify size=0, we don't check
* whether "addr" is in the range of address space of device.
* */
if (dev->size == 0)
{
if (dev->write_byte (dev, addr, (u8) data) != ADDR_NOHIT)
return;
}
else if ((addr >= dev->base) && (addr < (dev->base + dev->size)))
{
if (dev->write_byte (dev, addr, (u8) data) != ADDR_NOHIT)
return;
}
}
skyeye_config.mach->mach_io_write_byte (state, addr, data);
}
void
io_write_halfword (ARMul_State * state, ARMword addr, ARMword data)
{
struct device_desc *dev;
int i;
for (i = 0; i < skyeye_config.mach->dev_count; i++)
{
dev = skyeye_config.mach->devices[i];
if (!dev->write_halfword)
continue;
/* if we specify size=0, we don't check
* whether "addr" is in the range of address space of device.
* */
if (dev->size == 0)
{
if (dev->write_halfword (dev, addr, (u16) data) != ADDR_NOHIT)
return;
}
else if ((addr >= dev->base) && (addr < (dev->base + dev->size)))
{
if (dev->write_halfword (dev, addr, (u16) data) != ADDR_NOHIT)
return;
}
}
skyeye_config.mach->mach_io_write_halfword (state, addr, data);
}
void
io_write_word (ARMul_State * state, ARMword addr, ARMword data)
{
struct device_desc *dev;
int i;
for (i = 0; i < skyeye_config.mach->dev_count; i++)
{
dev = skyeye_config.mach->devices[i];
if (!dev->write_word)
continue;
/* if we specify size=0, we don't check
* whether "addr" is in the range of address space of device.
* */
if (dev->size == 0)
{
if (dev->write_word (dev, addr, data) != ADDR_NOHIT)
return;
}
else if ((addr >= dev->base) && (addr < (dev->base + dev->size)))
{
if (dev->write_word (dev, addr, data) != ADDR_NOHIT)
return;
}
}
skyeye_config.mach->mach_io_write_word (state, addr, data);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -