etraxfs_timer.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 265 行

C
265
字号
/* * QEMU ETRAX Timers * * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include <stdio.h>#include <sys/time.h>#include "hw.h"#include "qemu-timer.h"#define D(x)#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 0x54struct fs_timer_t {	CPUState *env;	qemu_irq *irq;	target_phys_addr_t base;	QEMUBH *bh;	ptimer_state *ptimer;	struct timeval last;	/* Control registers.  */	uint32_t rw_tmr0_div;	uint32_t r_tmr0_data;	uint32_t rw_tmr0_ctrl;	uint32_t rw_tmr1_div;	uint32_t r_tmr1_data;	uint32_t rw_tmr1_ctrl;	uint32_t rw_intr_mask;	uint32_t rw_ack_intr;	uint32_t r_intr;	uint32_t r_masked_intr;};static uint32_t timer_rinvalid (void *opaque, target_phys_addr_t addr){	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){	struct fs_timer_t *t = opaque;	D(CPUState *env = t->env);	uint32_t r = 0;	/* Make addr relative to this instances base.  */	addr -= t->base;	switch (addr) {	case R_TMR0_DATA:		break;	case R_TMR1_DATA:		D(printf ("R_TMR1_DATA\n"));		break;	case R_TIME:		r = qemu_get_clock(vm_clock) * 10;		break;	case RW_INTR_MASK:		r = t->rw_intr_mask;		break;	case R_MASKED_INTR:		r = t->r_intr & t->rw_intr_mask;		break;	default:		D(printf ("%s %x p=%x\n", __func__, addr, env->pc));		break;	}	return r;}static voidtimer_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value){	struct fs_timer_t *t = opaque;	CPUState *env = t->env;	cpu_abort(env, "Unsupported short access. reg=%x pc=%x.\n", 		  addr, env->pc);}#define TIMER_SLOWDOWN 1static void update_ctrl(struct fs_timer_t *t){	unsigned int op;	unsigned int freq;	unsigned int freq_hz;	unsigned int div;	op = t->rw_tmr0_ctrl & 3;	freq = t->rw_tmr0_ctrl >> 2;	freq_hz = 32000000;	switch (freq)	{	case 0:	case 1:		D(printf ("extern or disabled timer clock?\n"));		break;	case 4: freq_hz =  29493000; break;	case 5: freq_hz =  32000000; break;	case 6: freq_hz =  32768000; break;	case 7: freq_hz = 100000000; break;	default:		abort();		break;	}	D(printf ("freq_hz=%d div=%d\n", freq_hz, t->rw_tmr0_div));	div = t->rw_tmr0_div * TIMER_SLOWDOWN;	div >>= 15;	freq_hz >>= 15;	ptimer_set_freq(t->ptimer, freq_hz);	ptimer_set_limit(t->ptimer, div, 0);	switch (op)	{		case 0:			/* Load.  */			ptimer_set_limit(t->ptimer, div, 1);			ptimer_run(t->ptimer, 1);			break;		case 1:			/* Hold.  */			ptimer_stop(t->ptimer);			break;		case 2:			/* Run.  */			ptimer_run(t->ptimer, 0);			break;		default:			abort();			break;	}}static void timer_update_irq(struct fs_timer_t *t){	t->r_intr &= ~(t->rw_ack_intr);	t->r_masked_intr = t->r_intr & t->rw_intr_mask;	D(printf("%s: masked_intr=%x\n", __func__, t->r_masked_intr));	if (t->r_masked_intr)		qemu_irq_raise(t->irq[0]);	else		qemu_irq_lower(t->irq[0]);}static void timer_hit(void *opaque){	struct fs_timer_t *t = opaque;	t->r_intr |= 1;	timer_update_irq(t);}static voidtimer_writel (void *opaque, target_phys_addr_t addr, uint32_t value){	struct fs_timer_t *t = opaque;	CPUState *env = t->env;	/* Make addr relative to this instances base.  */	addr -= t->base;	switch (addr)	{		case RW_TMR0_DIV:			t->rw_tmr0_div = value;			break;		case RW_TMR0_CTRL:			D(printf ("RW_TMR0_CTRL=%x\n", value));			t->rw_tmr0_ctrl = value;			update_ctrl(t);			break;		case RW_TMR1_DIV:			t->rw_tmr1_div = value;			break;		case RW_TMR1_CTRL:			D(printf ("RW_TMR1_CTRL=%x\n", value));			break;		case RW_INTR_MASK:			D(printf ("RW_INTR_MASK=%x\n", value));			t->rw_intr_mask = value;			timer_update_irq(t);			break;		case RW_WD_CTRL:			D(printf ("RW_WD_CTRL=%x\n", value));			break;		case RW_ACK_INTR:			t->rw_ack_intr = value;			timer_update_irq(t);			t->rw_ack_intr = 0;			break;		default:			printf ("%s %x %x pc=%x\n",				__func__, addr, value, env->pc);			break;	}}static CPUReadMemoryFunc *timer_read[] = {    &timer_rinvalid,    &timer_rinvalid,    &timer_readl,};static CPUWriteMemoryFunc *timer_write[] = {    &timer_winvalid,    &timer_winvalid,    &timer_writel,};void etraxfs_timer_init(CPUState *env, qemu_irq *irqs, 			target_phys_addr_t base){	static struct fs_timer_t *t;	int timer_regs;	t = qemu_mallocz(sizeof *t);	if (!t)		return;	t->bh = qemu_bh_new(timer_hit, t);	t->ptimer = ptimer_init(t->bh);	t->irq = irqs;	t->env = env;	t->base = base;	timer_regs = cpu_register_io_memory(0, timer_read, timer_write, t);	cpu_register_physical_memory (base, 0x5c, timer_regs);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?