⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skyeye_mach_s3c3410x.c

📁 skyeye的开源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	skyeye_mach_s3c3410x.c - SAMSUNG's S3C3410X simulation for skyeye	Copyright (C) 2007 Skyeye Develop Group	for help please send mail to <skyeye-developer@lists.gro.clinux.org>	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 *//* * 03/04/2007	Written by Anthony Lee *//* * COMPLETED: Interrupt, WatchDog, Timer, UART, DMA * UNIMPLEMENTED: I/O Port, etc. */#include "armdefs.h"#include "armemu.h"#include "s3c3410x.h"#include "skyeye_uart.h"#define S3C3410X_DEBUG			0#define PRINT(x...)			printf("[S3C3410X]: " x)#if S3C3410X_DEBUG#define DEBUG(x...)			printf("[S3C3410X]: " x)#else#define DEBUG(x...)			(void)0#endif/* * CYCLE_TIMES_PER_SECOND: * 	It's near 40000 times on my machine, * 	you can change the value to fit your machine. */#define CYCLE_TIMES_PER_SECOND		(40000)#define MCLK				(40) /* MHz */#define TIMER_COUNT_UP_PER_SECOND	(1000000 * MCLK) /* prescale=1, divider=1 */#define TIMER_COUNT_UP_PER_CYCLE	(TIMER_COUNT_UP_PER_SECOND / CYCLE_TIMES_PER_SECOND)struct s3c3410x_timer_t {	ARMword tdat;	ARMword tpre;	ARMword tcon;	ARMword tcnt;	ARMword tcnt_scaler;};struct s3c3410x_dma_t {	ARMword con;	ARMword src;	ARMword dst;	ARMword cnt;};/* S3C3410X Internal IO Registers */struct s3c3410x_io_t{	/* System Registers */	ARMword syscfg;	ARMword syscon;	/* Interrupt Controller Registers */	ARMword intmod;	ARMword intpnd;	ARMword intmsk;	ARMword intpri[8];	/* Timer Registers */	ARMword btcon;	ARMword btcnt;	ARMword btcnt_scaler;	struct s3c3410x_timer_t timer[5];	ARMword tfcon;	ARMword tfstat;	uint64_t tf4;	ARMword tf4_repeat[2];	/* UART Registers */	ARMword ulcon;	ARMword ucon;	ARMword ustat;	ARMword ufcon;	ARMword ufstat;	ARMword urxh;	ARMword ubrdiv;	/* DMA Registers */	struct s3c3410x_dma_t dma[2];};static struct s3c3410x_io_t s3c3410x_io;#define io s3c3410x_ioextern ARMword mem_read_byte(ARMul_State*, ARMword);extern ARMword mem_read_halfword(ARMul_State*, ARMword);extern ARMword mem_read_word(ARMul_State*, ARMword);extern void mem_write_byte(ARMul_State*, ARMword, ARMword);extern void mem_write_halfword(ARMul_State*, ARMword, ARMword);extern void mem_write_word(ARMul_State*, ARMword, ARMword);static int s3c3410x_dma_is_valid(int index);static void s3c3410x_dma_proccess(ARMul_State *state, int index);static void s3c3410x_io_reset(ARMul_State *state){	int i;	memset(&io, 0, sizeof(io));	/* System */	io.syscfg = 0xfff1;	/* Interrupt */	io.intpri[0] = 0x03020100;	io.intpri[1] = 0x07060504;	io.intpri[2] = 0x0b0a0908;	io.intpri[3] = 0x0f0e0d0c;	io.intpri[4] = 0x13121110;	io.intpri[5] = 0x17161514;	io.intpri[6] = 0x1b1a1918;	io.intpri[7] = 0x1f1e1d1c;	/* Timer */	for (i = 0; i < 5; i++) io.timer[i].tpre = 0xff;	for (i = 0; i < 3; i++) io.timer[i].tdat = 0xffff;	for (i = 3; i < 5; i++) io.timer[i].tdat = 0xff;	/* UART */	io.ustat = 0xc0;}/* Interrupt Routine */static void s3c3410x_update_int(ARMul_State *state){	ARMword requests = (io.syscon & 0x40) ? (io.intpnd & io.intmsk) : 0x0;	state->NfiqSig = (requests & io.intmod) ? LOW : HIGH;	state->NirqSig = (requests & ~io.intmod) ? LOW : HIGH;}static void s3c3410x_set_interrupt(unsigned int irq){	io.intpnd |= (0x1 << irq);}static void s3c3410x_interrupt_read(ARMword addr, ARMword *data){	switch (addr) {		case INTMOD:			*data = io.intmod;			break;		case INTPND:			*data = io.intpnd;			break;		case INTMSK:			*data = io.intmsk;			break;		case INTPRI0:		case INTPRI1:		case INTPRI2:		case INTPRI3:		case INTPRI4:		case INTPRI5:		case INTPRI6:		case INTPRI7:			*data = io.intpri[(addr - INTPRI0) / 0x4];			break;		default:			break;	}	DEBUG("%s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, *data);}static void s3c3410x_interrupt_write(ARMul_State *state, ARMword addr, ARMword data){	DEBUG("%s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, data);	switch (addr) {		case INTMOD:			io.intmod = data;			break;		case INTPND:			io.intpnd &= data;			break;		case INTMSK:			io.intmsk = data;			break;		case INTPRI0:		case INTPRI1:		case INTPRI2:		case INTPRI3:		case INTPRI4:		case INTPRI5:		case INTPRI6:		case INTPRI7:			io.intpri[(addr - INTPRI0) / 0x4] = data;			break;		default:			break;	}}/* Timer Routine */static void s3c3410x_timer_do_cycle(ARMul_State *state){	int i, k;	ARMword tdat, count, empty_count;	ARMword cnt_up, cnt_divider, cnt_clock_divider = 1;#if 0	switch ((io.syscon >> 3) & 0x7) {		case 0: cnt_clock_divider = 16; break;		case 1: cnt_clock_divider = 8; break;		case 2: cnt_clock_divider = 2; break;		case 4: cnt_clock_divider = 1024; break;		default: break;	}#endif	for (i = 0; i < 5; i++) {		if ((io.timer[i].tcon & 0x80) == 0) continue;		if (i < 4 || (io.tfcon & 0x1) == 0) {			tdat = io.timer[i].tdat;		} else {			if ((count = (io.tfstat & 0x7)) == 0) break;			if (io.timer[4].tcnt == (tdat = (io.tf4 & 0xff))) {				if (io.tf4_repeat[0] == 0) {					io.tf4_repeat[0] = io.tf4_repeat[1];					if ((empty_count = ((io.tfcon >> 2) & 0x3)) > 0) {						if (empty_count == 3) empty_count = 4;						if (io.tfstat & 0x8) count++;						io.tfstat = count - min(empty_count, count);						io.tf4 >>= (empty_count << 3);					}					s3c3410x_set_interrupt(INT_TF);				} else {					io.tf4_repeat[0] -= 1;				}			}		}		cnt_divider = cnt_clock_divider * (io.timer[i].tpre + 1) << (i < 3 ? 0 : (1 << (4 - (io.timer[i].tcon & 0x3))));		cnt_up = TIMER_COUNT_UP_PER_CYCLE / cnt_divider;		if (cnt_up == 0) {			if (io.timer[i].tcnt_scaler == 0) {				io.timer[i].tcnt_scaler = cnt_divider / TIMER_COUNT_UP_PER_CYCLE;				continue;			} else if ((io.timer[i].tcnt_scaler -= 1) != 0) {				continue;			}			cnt_up = 1;		}		switch ((io.timer[i].tcon >> 3) & 0x7) {			case 0: /* Interval Mode */				if (io.timer[i].tcnt == tdat) {					s3c3410x_set_interrupt(INT_TMC0 + i * 2);					io.timer[i].tcnt = 0;					break;				}				if (io.timer[i].tcnt > tdat) break;				io.timer[i].tcnt += min(tdat - io.timer[i].tcnt, cnt_up);				break;			case 1: /* Match & overflow mode (Timer0/1/2), PWM mode (Timer3/4) */				if (io.timer[i].tcnt == tdat) {					s3c3410x_set_interrupt(INT_TMC0 + i * 2);				}				if (io.timer[i].tcnt == (i < 3 ? 0xffff : 0xff)) {					s3c3410x_set_interrupt(INT_TOF0 + i * 2);					io.timer[i].tcnt = 0;					break;				}				io.timer[i].tcnt += min((io.timer[i].tcnt < tdat ? tdat :										   (i < 3 ? 0xffff : 0xff)) -							io.timer[i].tcnt, cnt_up);				break;			case 2: /* Match & DMA mode */				if (!(i == 1 || i == 3)) break;				for (k = 0; k < 2; k++) {					if (s3c3410x_dma_is_valid(k) != 1) continue;					if (((io.dma[k].con >> 2) & 0x3) != 0x3) continue;					if (i == 1 && io.dma[k].dst == TDAT1) break;					if (i == 3 && io.dma[k].dst == TDAT3) break;				}				if (k == 2) break;				if (io.timer[i].tcnt == tdat) {					s3c3410x_set_interrupt(INT_TMC0 + i * 2);					io.timer[i].tcnt = 0;					s3c3410x_dma_proccess(state, k);					break;				}				if (io.timer[i].tcnt > tdat) break;				io.timer[i].tcnt += min(tdat - io.timer[i].tcnt, cnt_up);				break;			default: /* Other mode unimplemented yet */				break;		}	}	/* Basic Timer and WatchDog */	cnt_divider = 1 << (13 - ((io.btcon >> 2) & 0x3));	cnt_up = TIMER_COUNT_UP_PER_CYCLE / cnt_divider;	if (cnt_up == 0) {		if (io.btcnt_scaler == 0) {			io.btcnt_scaler = cnt_divider / TIMER_COUNT_UP_PER_CYCLE;			goto next;		} else if ((io.btcnt_scaler -= 1) != 0) {			goto next;		}		cnt_up = 1;	}	if (io.btcnt == 0xff) {		io.btcnt = 0;		s3c3410x_set_interrupt(INT_BT);	} else {		io.btcnt += min(0xff - io.btcnt, cnt_up);	}	if (io.btcon & 0x10000) {		ARMword wdt = (io.btcon >> 8) & 0xff;		if (wdt == 0xff) { /* asserts reset signal */			state->NresetSig = LOW;			PRINT("****************** WATCHDOG RESET ******************\n");		} else {			io.btcon = (io.btcon & ~0xff00) | ((wdt + min(0xff - wdt, cnt_up)) << 8);		}	}next:	return;}static void s3c3410x_timer_read(ARMword offset, ARMword *data, int index){	switch (offset) {		case 0: /* TDAT */			*data = io.timer[index].tdat;			break;		case 2: /* TPRE */			*data = io.timer[index].tpre;			break;		case 3: /* TCON */			*data = io.timer[index].tcon;			break;		case 6: /* TCNT */			*data = io.timer[index].tcnt;			break;		case 0x8: /* TFW4 */			if (index != 4) break;			if ((io.tfcon & 0x1) == 0 || io.tfstat == 0) break;			*data = io.tf4 & 0xffffffff;			io.tf4 >>= 32;			io.tfstat = (io.tfstat < 7 ? (io.tfstat - min(io.tfstat, 4)) : (io.tfstat & ~0x8));			break;		case 0xa: /* TFHW4 */			if (index != 4) break;			if ((io.tfcon & 0x1) == 0 || io.tfstat == 0) break;			*data = io.tf4 & 0xffff;			io.tf4 >>= 16;			io.tfstat = (io.tfstat < 7 ? (io.tfstat - min(io.tfstat, 2)) : (io.tfstat & ~0x8));			break;		case 0xb: /* TFB4 */			if (index != 4) break;			if ((io.tfcon & 0x1) == 0 || io.tfstat == 0) break;			*data = io.tf4 & 0xff;			io.tf4 >>= 8;			io.tfstat = (io.tfstat < 7 ? (io.tfstat - 1) : (io.tfstat & ~0x8));			break;		case 0xe: /* TFSTAT */			if (index == 4) *data = io.tfstat;			break;		case 0xf: /* TFCON */			if (index == 4) *data = io.tfcon;			break;		default:			break;	}	DEBUG("%s(Timer%d, offset:0x%x, data:0x%x)\n", __FUNCTION__, index, offset, *data);}static void s3c3410x_timer_write(ARMul_State *state, ARMword offset, ARMword data, int index){	DEBUG("%s(Timer%d, offset:0x%x, data:0x%x)\n", __FUNCTION__, index, offset, data);	switch (offset) {		case 0: /* TDAT */			io.timer[index].tdat = min(data, (index < 3 ? 0xffff : 0xff));			break;		case 2: /* TPRE */			io.timer[index].tpre = min(data, 0xff);			break;		case 3: /* TCON */			io.timer[index].tcon = min((data & ~0x40), 0xff);			if (data & 0x40) io.timer[index].tcnt = 0;			break;		case 0x8: /* TFW4 */			if (index != 4) break;			if ((io.tfcon & 0x1) == 0 || io.tfstat > 7) break;			io.tf4 &= ~(((uint64_t)0xffffffff) << (io.tfstat << 3));			io.tf4 |= (((uint64_t)data) << (io.tfstat << 3));			io.tfstat += (io.tfstat < 4 ? 4 : 8);			break;		case 0xa: /* TFHW4 */			if (index != 4) break;			if ((io.tfcon & 0x1) == 0 || io.tfstat > 7) break;			io.tf4 &= ~(((uint64_t)0xffff) << (io.tfstat << 3));			io.tf4 |= (((uint64_t)min(data, 0xffff)) << (io.tfstat << 3));			io.tfstat += (io.tfstat < 6 ? 2 : 8);			break;		case 0xb: /* TFB4 */			if (index != 4) break;			if ((io.tfcon & 0x1) == 0 || io.tfstat > 7) break;			io.tf4 &= ~(((uint64_t)0xff) << (io.tfstat << 3));

⌨️ 快捷键说明

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