mirror of
https://github.com/qemu/qemu.git
synced 2024-11-28 22:33:36 +08:00
Made the etrax timers and serial-ports base address relocatable. Use target_phys_addr_t instead of target_ulong.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4058 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
05ba7d5f34
commit
ca87d03b77
18
hw/etraxfs.c
18
hw/etraxfs.c
@ -35,10 +35,10 @@ static void main_cpu_reset(void *opaque)
|
||||
}
|
||||
|
||||
/* Init functions for different blocks. */
|
||||
extern qemu_irq *etraxfs_pic_init(CPUState *env, target_ulong base);
|
||||
/* TODO: Make these blocks relocate:able. */
|
||||
extern void etraxfs_timer_init(CPUState *env, qemu_irq *irqs);
|
||||
extern void etraxfs_ser_init(CPUState *env, qemu_irq *irqs);
|
||||
extern qemu_irq *etraxfs_pic_init(CPUState *env, target_phys_addr_t base);
|
||||
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs,
|
||||
target_phys_addr_t base);
|
||||
void etraxfs_ser_init(CPUState *env, qemu_irq *irqs, target_phys_addr_t base);
|
||||
|
||||
static
|
||||
void bareetraxfs_init (int ram_size, int vga_ram_size,
|
||||
@ -84,8 +84,14 @@ void bareetraxfs_init (int ram_size, int vga_ram_size,
|
||||
4, 0x0000, 0x0000, 0x0000, 0x0000);
|
||||
|
||||
pic = etraxfs_pic_init(env, 0xb001c000);
|
||||
etraxfs_timer_init(env, pic);
|
||||
etraxfs_ser_init(env, pic);
|
||||
/* 2 timers. */
|
||||
etraxfs_timer_init(env, pic, 0xb001e000);
|
||||
etraxfs_timer_init(env, pic, 0xb005e000);
|
||||
/* 4 serial ports. */
|
||||
etraxfs_ser_init(env, pic, 0xb0026000);
|
||||
etraxfs_ser_init(env, pic, 0xb0028000);
|
||||
etraxfs_ser_init(env, pic, 0xb002a000);
|
||||
etraxfs_ser_init(env, pic, 0xb002c000);
|
||||
|
||||
kernel_size = load_image(kernel_filename, phys_ram_base + 0x4000);
|
||||
/* magic for boot. */
|
||||
|
@ -30,7 +30,7 @@
|
||||
struct fs_pic_state_t
|
||||
{
|
||||
CPUState *env;
|
||||
target_ulong base;
|
||||
target_phys_addr_t base;
|
||||
|
||||
uint32_t rw_mask;
|
||||
/* Active interrupt lines. */
|
||||
@ -186,7 +186,7 @@ static void etraxfs_pic_handler(void *opaque, int irq, int level)
|
||||
}
|
||||
}
|
||||
|
||||
qemu_irq *etraxfs_pic_init(CPUState *env, target_ulong base)
|
||||
qemu_irq *etraxfs_pic_init(CPUState *env, target_phys_addr_t base)
|
||||
{
|
||||
struct fs_pic_state_t *fs;
|
||||
qemu_irq *pic;
|
||||
|
@ -35,25 +35,20 @@
|
||||
|
||||
static uint32_t ser_readb (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
CPUState *env;
|
||||
uint32_t r = 0;
|
||||
|
||||
env = opaque;
|
||||
D(CPUState *env = opaque);
|
||||
D(printf ("%s %x pc=%x\n", __func__, addr, env->pc));
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
static uint32_t ser_readw (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
CPUState *env;
|
||||
uint32_t r = 0;
|
||||
env = opaque;
|
||||
D(CPUState *env = opaque);
|
||||
D(printf ("%s %x pc=%x\n", __func__, addr, env->pc));
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
CPUState *env = opaque;
|
||||
D(CPUState *env = opaque);
|
||||
uint32_t r = 0;
|
||||
|
||||
switch (addr & 0xfff)
|
||||
@ -75,21 +70,19 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
|
||||
static void
|
||||
ser_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
CPUState *env;
|
||||
env = opaque;
|
||||
D(CPUState *env = opaque);
|
||||
D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc));
|
||||
}
|
||||
static void
|
||||
ser_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
CPUState *env;
|
||||
env = opaque;
|
||||
D(CPUState *env = opaque);
|
||||
D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc));
|
||||
}
|
||||
static void
|
||||
ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
CPUState *env = opaque;
|
||||
D(CPUState *env = opaque);
|
||||
|
||||
switch (addr & 0xfff)
|
||||
{
|
||||
@ -121,13 +114,9 @@ static CPUWriteMemoryFunc *ser_write[] = {
|
||||
&ser_writel,
|
||||
};
|
||||
|
||||
void etraxfs_ser_init(CPUState *env, qemu_irq *irqs)
|
||||
void etraxfs_ser_init(CPUState *env, qemu_irq *irqs, target_phys_addr_t base)
|
||||
{
|
||||
int ser_regs;
|
||||
|
||||
ser_regs = cpu_register_io_memory(0, ser_read, ser_write, env);
|
||||
cpu_register_physical_memory (0xb0026000, 0x3c, ser_regs);
|
||||
cpu_register_physical_memory (0xb0028000, 0x3c, ser_regs);
|
||||
cpu_register_physical_memory (0xb002a000, 0x3c, ser_regs);
|
||||
cpu_register_physical_memory (0xb002c000, 0x3c, ser_regs);
|
||||
cpu_register_physical_memory (base, 0x3c, ser_regs);
|
||||
}
|
||||
|
@ -28,27 +28,28 @@
|
||||
|
||||
#define D(x)
|
||||
|
||||
#define R_TIME 0xb001e038
|
||||
#define RW_TMR0_DIV 0xb001e000
|
||||
#define R_TMR0_DATA 0xb001e004
|
||||
#define RW_TMR0_CTRL 0xb001e008
|
||||
#define RW_TMR1_DIV 0xb001e010
|
||||
#define R_TMR1_DATA 0xb001e014
|
||||
#define RW_TMR1_CTRL 0xb001e018
|
||||
|
||||
#define RW_WD_CTRL 0xb001e040
|
||||
#define RW_INTR_MASK 0xb001e048
|
||||
#define RW_ACK_INTR 0xb001e04c
|
||||
#define R_INTR 0xb001e050
|
||||
#define R_MASKED_INTR 0xb001e054
|
||||
#define RW_TMR0_DIV 0x00
|
||||
#define R_TMR0_DATA 0x04
|
||||
#define RW_TMR0_CTRL 0x08
|
||||
#define RW_TMR1_DIV 0x10
|
||||
#define R_TMR1_DATA 0x14
|
||||
#define RW_TMR1_CTRL 0x18
|
||||
#define R_TIME 0x38
|
||||
#define RW_WD_CTRL 0x40
|
||||
#define RW_INTR_MASK 0x48
|
||||
#define RW_ACK_INTR 0x4c
|
||||
#define R_INTR 0x50
|
||||
#define R_MASKED_INTR 0x54
|
||||
|
||||
struct fs_timer_t {
|
||||
QEMUBH *bh;
|
||||
unsigned int limit;
|
||||
int scale;
|
||||
ptimer_state *ptimer;
|
||||
CPUState *env;
|
||||
qemu_irq *irq;
|
||||
target_phys_addr_t base;
|
||||
|
||||
QEMUBH *bh;
|
||||
ptimer_state *ptimer;
|
||||
unsigned int limit;
|
||||
int scale;
|
||||
uint32_t mask;
|
||||
struct timeval last;
|
||||
|
||||
@ -57,16 +58,6 @@ struct fs_timer_t {
|
||||
uint32_t r_intr;
|
||||
};
|
||||
|
||||
static struct fs_timer_t timer[2];
|
||||
|
||||
static inline int timer_index(target_phys_addr_t addr)
|
||||
{
|
||||
int t = 0;
|
||||
if (addr >= 0xb005e000)
|
||||
t = 1;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* diff two timevals. Return a single int in us. */
|
||||
int diff_timeval_us(struct timeval *a, struct timeval *b)
|
||||
{
|
||||
@ -78,31 +69,23 @@ int diff_timeval_us(struct timeval *a, struct timeval *b)
|
||||
return diff;
|
||||
}
|
||||
|
||||
static uint32_t timer_readb (void *opaque, target_phys_addr_t addr)
|
||||
static uint32_t timer_rinvalid (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
CPUState *env;
|
||||
uint32_t r = 0;
|
||||
|
||||
env = opaque;
|
||||
D(printf ("%s %x pc=%x\n", __func__, addr, env->pc));
|
||||
return r;
|
||||
}
|
||||
static uint32_t timer_readw (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
CPUState *env;
|
||||
uint32_t r = 0;
|
||||
|
||||
env = opaque;
|
||||
D(printf ("%s %x pc=%x\n", __func__, addr, env->pc));
|
||||
return r;
|
||||
struct fs_timer_t *t = opaque;
|
||||
CPUState *env = t->env;
|
||||
cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n",
|
||||
addr, env->pc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
CPUState *env = opaque;
|
||||
struct fs_timer_t *t = opaque;
|
||||
D(CPUState *env = t->env);
|
||||
uint32_t r = 0;
|
||||
int t = timer_index(addr);
|
||||
|
||||
/* Make addr relative to this instances base. */
|
||||
addr -= t->base;
|
||||
switch (addr) {
|
||||
case R_TMR0_DATA:
|
||||
break;
|
||||
@ -113,21 +96,21 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
if (!(timer[t].last.tv_sec == 0
|
||||
&& timer[t].last.tv_usec == 0)) {
|
||||
r = diff_timeval_us(&now, &timer[t].last);
|
||||
if (!(t->last.tv_sec == 0
|
||||
&& t->last.tv_usec == 0)) {
|
||||
r = diff_timeval_us(&now, &t->last);
|
||||
r *= 1000; /* convert to ns. */
|
||||
r++; /* make sure we increase for each call. */
|
||||
}
|
||||
timer[t].last = now;
|
||||
t->last = now;
|
||||
break;
|
||||
}
|
||||
|
||||
case RW_INTR_MASK:
|
||||
r = timer[t].rw_intr_mask;
|
||||
r = t->rw_intr_mask;
|
||||
break;
|
||||
case R_MASKED_INTR:
|
||||
r = timer[t].r_intr & timer[t].rw_intr_mask;
|
||||
r = t->r_intr & t->rw_intr_mask;
|
||||
break;
|
||||
default:
|
||||
D(printf ("%s %x p=%x\n", __func__, addr, env->pc));
|
||||
@ -137,18 +120,12 @@ static uint32_t timer_readl (void *opaque, target_phys_addr_t addr)
|
||||
}
|
||||
|
||||
static void
|
||||
timer_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
|
||||
timer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
CPUState *env;
|
||||
env = opaque;
|
||||
D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc));
|
||||
}
|
||||
static void
|
||||
timer_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
CPUState *env;
|
||||
env = opaque;
|
||||
D(printf ("%s %x %x pc=%x\n", __func__, addr, value, env->pc));
|
||||
struct fs_timer_t *t = opaque;
|
||||
CPUState *env = t->env;
|
||||
cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n",
|
||||
addr, env->pc);
|
||||
}
|
||||
|
||||
static void write_ctrl(struct fs_timer_t *t, uint32_t v)
|
||||
@ -212,20 +189,22 @@ static void timer_ack_irq(struct fs_timer_t *t)
|
||||
static void
|
||||
timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
|
||||
{
|
||||
CPUState *env = opaque;
|
||||
int t = timer_index(addr);
|
||||
struct fs_timer_t *t = opaque;
|
||||
CPUState *env = t->env;
|
||||
|
||||
D(printf ("%s %x %x pc=%x\n",
|
||||
__func__, addr, value, env->pc));
|
||||
/* Make addr relative to this instances base. */
|
||||
addr -= t->base;
|
||||
switch (addr)
|
||||
{
|
||||
case RW_TMR0_DIV:
|
||||
D(printf ("RW_TMR0_DIV=%x\n", value));
|
||||
timer[t].limit = value;
|
||||
t->limit = value;
|
||||
break;
|
||||
case RW_TMR0_CTRL:
|
||||
D(printf ("RW_TMR0_CTRL=%x\n", value));
|
||||
write_ctrl(&timer[t], value);
|
||||
write_ctrl(t, value);
|
||||
break;
|
||||
case RW_TMR1_DIV:
|
||||
D(printf ("RW_TMR1_DIV=%x\n", value));
|
||||
@ -235,14 +214,14 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
|
||||
break;
|
||||
case RW_INTR_MASK:
|
||||
D(printf ("RW_INTR_MASK=%x\n", value));
|
||||
timer[t].rw_intr_mask = value;
|
||||
t->rw_intr_mask = value;
|
||||
break;
|
||||
case RW_WD_CTRL:
|
||||
D(printf ("RW_WD_CTRL=%x\n", value));
|
||||
break;
|
||||
case RW_ACK_INTR:
|
||||
timer[t].r_intr &= ~value;
|
||||
timer_ack_irq(&timer[t]);
|
||||
t->r_intr &= ~value;
|
||||
timer_ack_irq(t);
|
||||
break;
|
||||
default:
|
||||
printf ("%s %x %x pc=%x\n",
|
||||
@ -252,14 +231,14 @@ timer_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
|
||||
}
|
||||
|
||||
static CPUReadMemoryFunc *timer_read[] = {
|
||||
&timer_readb,
|
||||
&timer_readw,
|
||||
&timer_rinvalid,
|
||||
&timer_rinvalid,
|
||||
&timer_readl,
|
||||
};
|
||||
|
||||
static CPUWriteMemoryFunc *timer_write[] = {
|
||||
&timer_writeb,
|
||||
&timer_writew,
|
||||
&timer_winvalid,
|
||||
&timer_winvalid,
|
||||
&timer_writel,
|
||||
};
|
||||
|
||||
@ -273,23 +252,23 @@ static void timer_irq(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs)
|
||||
void etraxfs_timer_init(CPUState *env, qemu_irq *irqs,
|
||||
target_phys_addr_t base)
|
||||
{
|
||||
static struct fs_timer_t *t;
|
||||
int timer_regs;
|
||||
|
||||
timer[0].bh = qemu_bh_new(timer_irq, &timer[0]);
|
||||
timer[0].ptimer = ptimer_init(timer[0].bh);
|
||||
timer[0].irq = irqs + 26;
|
||||
timer[0].mask = 1;
|
||||
timer[0].env = env;
|
||||
t = qemu_mallocz(sizeof *t);
|
||||
if (!t)
|
||||
return;
|
||||
|
||||
timer[1].bh = qemu_bh_new(timer_irq, &timer[1]);
|
||||
timer[1].ptimer = ptimer_init(timer[1].bh);
|
||||
timer[1].irq = irqs + 26;
|
||||
timer[1].mask = 1;
|
||||
timer[1].env = env;
|
||||
t->bh = qemu_bh_new(timer_irq, t);
|
||||
t->ptimer = ptimer_init(t->bh);
|
||||
t->irq = irqs + 26;
|
||||
t->mask = 1;
|
||||
t->env = env;
|
||||
t->base = base;
|
||||
|
||||
timer_regs = cpu_register_io_memory(0, timer_read, timer_write, env);
|
||||
cpu_register_physical_memory (0xb001e000, 0x5c, timer_regs);
|
||||
cpu_register_physical_memory (0xb005e000, 0x5c, timer_regs);
|
||||
timer_regs = cpu_register_io_memory(0, timer_read, timer_write, t);
|
||||
cpu_register_physical_memory (base, 0x5c, timer_regs);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user