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

📄 skyeye_mach_s3c44b0x.c

📁 skyeye的开源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	skyeye_mach_s3c44b0x.c - SAMSUNG's S3C44B0X simulation for skyeye	Copyright (C) 2003 - 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 *//* * 07/19/2003	original implementation by Walimis <wlm@student.dlut.edu.cn> * 03/04/2007	rewritten by Anthony Lee <don.anthony.lee+program@gmail.com> *//* * COMPLETED: Interrupt, UART, PWM Timers, Watchdog Timer, LCD, NET, RTC, DMA, IIS * UNIMPLEMENTED: I/O Ports, etc. * * NOTE: * 	LCD: see "device/lcd/dev_lcd_s3c44b0x.c[h]" * 	SOUND: see "device/sound/dev_sound_s3c44b0x.c" * 	NET(RTL8019AS 8/16 bits): see "device/net/dev_net_rtl8019.c[h]" */#include "armdefs.h"#include "armemu.h"#include "s3c44b0.h"#include "skyeye_uart.h"#include "portable/gettimeofday.h"#define S3C44B0X_DEBUG			0#define PRINT(x...)			printf("[S3C44B0X]: " x)#if S3C44B0X_DEBUG#define DEBUG(x...)			printf("[S3C44B0X]: " 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				(64) /* MHz */#define TIMER_COUNT_DOWN_PER_SECOND	((1000000 * MCLK) >> 1) /* prescale=1, divider=1/2 */#define TIMER_COUNT_DOWN_PER_CYCLE	(TIMER_COUNT_DOWN_PER_SECOND / CYCLE_TIMES_PER_SECOND)#define BCD_TO_BIN(a)			(((a) >> 4) * 10 + ((a) & 0xf))#define BIN_TO_BCD(a)			((((a) / 10) << 4) | ((a) % 10))#define HALFWORD_SWAP(x)		(((x) >> 8) | ((x) << 8))#define WORD_SWAP(x)			((HALFWORD_SWAP((x) & 0xffff) << 16) | HALFWORD_SWAP(((x) >> 16) & 0xffff))struct s3c44b0x_uart_fifo{	unsigned char rx[16];	unsigned char tx[16];	ARMword txcnt;};typedef ARMword (s3c44b0x_dma_t)[8];#define DMA_CON(dma)			dma[0]#define DMA_ISRC(dma)			dma[1]#define DMA_IDES(dma)			dma[2]#define DMA_ICNT(dma)			dma[3]#define DMA_CSRC(dma)			dma[4]#define DMA_CDES(dma)			dma[5]#define DMA_CCNT(dma)			dma[6]#define DMA_FLY(dma)			dma[7]extern 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);extern ARMword io_read_byte(ARMul_State*, ARMword);extern ARMword io_read_halfword(ARMul_State*, ARMword);extern ARMword io_read_word(ARMul_State*, ARMword);extern void io_write_byte(ARMul_State*, ARMword, ARMword);extern void io_write_halfword(ARMul_State*, ARMword, ARMword);extern void io_write_word(ARMul_State*, ARMword, ARMword);typedef ARMword (*s3c44b0x_dma_read_func)(ARMul_State*, ARMword);typedef void (*s3c44b0x_dma_write_func)(ARMul_State*, ARMword, ARMword);static s3c44b0x_dma_read_func dma_read_funcs[12] = {	/* ZDMA */	mem_read_byte,	mem_read_halfword,	mem_read_word,	/* BDMA */	mem_read_byte,		io_read_byte,		io_read_byte,	mem_read_halfword,	io_read_halfword,	io_read_halfword,	mem_read_word,		io_read_word,		io_read_word,};static s3c44b0x_dma_write_func dma_write_funcs[12] = {	/* ZDMA */	mem_write_byte,	mem_write_halfword,	mem_write_word,	/* BDMA */	io_write_byte,		mem_write_byte,		io_write_byte,	io_write_halfword,	mem_write_halfword,	io_write_halfword,	io_write_word,		mem_write_word,		io_write_word,};/* S3C44B0X Internal IO Registers */struct s3c44b0x_io_t{	/* CPU Wrapper Registers : FIXME */	ARMword syscfg;	ARMword ncachbe0;	ARMword ncachbe1;	ARMword sbuscon;	/* Memory Controller Registers : FIXME */	ARMword bwscon;	/* Interrupt Controller Registers */	ARMword intcon;	ARMword intpnd;	ARMword intmod;	ARMword intmsk;	ARMword i_pslv;	ARMword i_pmst;	ARMword i_cslv;	ARMword i_cmst;	/* UART Registers */	ARMword ulcon0;	ARMword ulcon1;	ARMword ucon0;	ARMword ucon1;	ARMword ufcon0;	ARMword ufcon1;	ARMword umcon0;	ARMword umcon1;	ARMword utrstat0;	ARMword utrstat1;	ARMword uerstat0;	ARMword uerstat1;	ARMword ufstat0;	ARMword ufstat1;	ARMword umstat0;	ARMword umstat1;	ARMword urxh0;	ARMword urxh1;	ARMword ubrdiv0;	ARMword ubrdiv1;	struct s3c44b0x_uart_fifo ufifo0;	struct s3c44b0x_uart_fifo ufifo1;	/* PWM Timers Registers */	ARMword tcfg0;	ARMword tcfg1;	ARMword tcnt_scaler[7];	ARMword tprescaler[7];	ARMword tdivider[7];	ARMword tcon;	ARMword tcntb[6];	ARMword tcmpb[5];	ARMword tcnt[6];	ARMword tcmp[5];	/* Watchdog Timer Registers */	ARMword wtcon;	ARMword wtdat;	ARMword wtcnt;	/* RTC Registers */	ARMword rtccon;	ARMword rtcalm;	ARMword rtcrst;	ARMword ticint;	ARMword tick_count;	struct tm rtc_alarm;	long int rtc_offset;	/* DMA Registers */	s3c44b0x_dma_t dma[4];	/* IIS Registers */	ARMword iiscon;	ARMword iismod;	ARMword iispsr;	ARMword iisfifcon;	ARMhword iisfifo_rx[8];	ARMhword iisfifo_tx[8];	ARMword iisfifo_txcnt;};static struct s3c44b0x_io_t s3c44b0x_io;ARMhword *s3c44b0x_iisfifo_tx = NULL;#define io s3c44b0x_iostatic int s3c44b0x_dma_is_valid(int index);static void s3c44b0x_dma_proccess(ARMul_State *state, int index);static void s3c44b0x_io_reset(ARMul_State *state){	memset(&io, 0, sizeof(io));	/* CPU Wrapper */	io.syscfg = 0x1;	io.sbuscon = 0x80001b1b;	/* Memory Controller */	io.bwscon = (state->bigendSig ? 0x1 : 0x0);	/* Interrupt */	io.intcon = 0x7;	io.intmsk = 0x7ffffff;	io.i_pslv = 0x1b1b1b1b;	io.i_pmst = 0x1f1b;	io.i_cslv = 0x1b1b1b1b;	io.i_cmst = 0x1b;	/* UART */	io.utrstat0 = io.utrstat1 = 0x6;	/* Watchdog Timer */	io.wtcon = 0x8020; /* here we disabled watchdog */	io.wtdat = 0x8000;	io.wtcnt = 0x8000;	io.tdivider[6] = 4;	/* RTC */	io.rtc_alarm.tm_mday = 1;	/* IIS */	io.iiscon = 0x100;	s3c44b0x_iisfifo_tx = &io.iisfifo_tx[0];}/* Interrupt Routine */static void s3c44b0x_update_int(ARMul_State *state){	ARMword requests = (io.intmsk & (0x1 << INT_GLOBAL)) ? 0x0 : (io.intpnd & ~io.intmsk);	ARMword vector, irq;	state->NfiqSig = ((io.intcon & 0x1) == 0 ? ((requests & io.intmod) ? LOW : HIGH) : HIGH);	state->NirqSig = ((io.intcon & 0x2) == 0 ? ((requests & ~io.intmod) ? LOW : HIGH) : HIGH);}static void s3c44b0x_update_intr(struct machine_config *mach){	/* leave me alone, do nothing ... */}static int s3c44b0x_pending_intr(unsigned int irq){	/* Here we "return 1" so that the device won't do something for it */	if (!((io.intcon & 0x2) == 0x0 || (io.intcon & 0x5) == 0x4)) return 1;	if (io.intmsk & (0x1 << INT_GLOBAL)) return 1;	return ((io.intpnd & (0x1 << irq)) == 0 ? 0 : 1);}static void s3c44b0x_set_interrupt(unsigned int irq){	if ((io.intcon & 0x2) == 0x0 || (io.intcon & 0x5) == 0x4) { /* IRQ or FIQ enabled */		io.intpnd |= (0x1 << irq);	}}static void s3c44b0x_interrupt_read(ARMword addr, ARMword *data){	int i;	switch (addr) {		case INTCON:			*data = io.intcon;			break;		case INTPND:			*data = ((io.intmsk & (0x1 << INT_GLOBAL)) ? 0x1 : io.intpnd);			break;		case INTMOD:			*data = io.intmod;			break;		case INTMSK:			*data = io.intmsk;			break;		case I_PSLV:			*data = io.i_pslv;			break;		case I_PMST:			*data = io.i_pmst;			break;		case I_CSLV:			*data = io.i_cslv;			break;		case I_CMST:			*data = io.i_cmst;			break;		case I_ISPR:			*data = 0;			if (io.intmsk & (0x1 << INT_GLOBAL)) break;			if ((io.intcon & 0x2) != 0x0) break;			for (i = 0; i < 26; i++) { /* find which interrupt is pending */				if (((io.intpnd & ~io.intmsk) & (0x1 << i)) & ~io.intmod) {					*data = (0x1 << i);					break;				}			}			break;		case F_ISPR:			*data = 0;			if (io.intmsk & (0x1 << INT_GLOBAL)) break;			if ((io.intcon & 0x5) != 0x4) break;			for (i = 0; i < 26; i++) { /* find which interrupt is pending */				if (((io.intpnd & ~io.intmsk) & (0x1 << i)) & io.intmod) {					*data = (0x1 << i);					break;				}			}			break;		default:			break;	}	DEBUG("%s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, *data);}static void s3c44b0x_interrupt_write(ARMul_State *state, ARMword addr, ARMword data){	DEBUG("%s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, data);	switch (addr) {		case INTCON:			io.intcon = data;			break;		case INTMOD:			io.intmod = data;			break;		case INTMSK:			io.intmsk = data;			break;		case I_PSLV:			io.i_pslv = data;			break;		case I_PMST:			io.i_pmst = data;			break;		case I_ISPC:			if ((io.intcon & 0x2) != 0x0 || ((data & 0x3ffffff) & ~io.intmod) == 0) break;			io.intpnd &= (~data & 0x3ffffff);			break;		case F_ISPC:			if ((io.intcon & 0x5) != 0x4 || ((data & 0x3ffffff) & io.intmod) == 0) break;			io.intpnd &= (~data & 0x3ffffff);			break;		default:			break;	}}/* UART Routine */static void s3c44b0x_uart_do_cycle(ARMul_State *state){	int read_uart0 = 1;	struct timeval tv;	tv.tv_sec = 0;	tv.tv_usec = 0;	do {		ARMword *pUfstat = (read_uart0 ? &io.ufstat0 : &io.ufstat1);		ARMword *pUtrstat = (read_uart0 ? &io.utrstat0 : &io.utrstat1);		ARMword *pUcon = (read_uart0 ? &io.ucon0 : &io.ucon1);		ARMword *pUfcon = (read_uart0 ? &io.ufcon0 : &io.ufcon1);		ARMword *pUrxh = (read_uart0 ? &io.urxh0 : &io.urxh1);		ARMword bdma_mask = (read_uart0 ? 0x2 : 0x3);		if ((*pUcon & 0x3) == bdma_mask || (*pUcon & 0xc) == (bdma_mask << 2)) { /* BDMA request */			ARMword utxhb = (read_uart0 ? UTXH0 : UTXH1) + state->bigendSig * 3;			ARMword urxhb = (read_uart0 ? URXH0 : URXH1) + state->bigendSig * 3;			int index = (read_uart0 ? 2 : 3);			int rx_empty = ((*pUfcon & 0x1) ? ((*pUfstat & 0xf) == 0) : ((*pUtrstat & 0x1) == 0));			int tx_ready = ((*pUfcon & 0x1) ? ((*pUfstat & 0x200) == 0) : 1);			ARMword mask = 0;			if ((*pUcon & 0x3) == 0x0) rx_empty = 1;			if ((*pUcon & 0xc) == 0x0) tx_ready = 0;			do {				if (s3c44b0x_dma_is_valid(index) != 1) break;				if (((DMA_CCNT(io.dma[index]) >> 30) & 0x3) != 0x2) break;				if ((DMA_CDES(io.dma[index]) & 0xfffffff) == utxhb && tx_ready) mask |= (bdma_mask << 2);				if ((DMA_CSRC(io.dma[index]) & 0xfffffff) == urxhb && !rx_empty) mask |= bdma_mask;				if ((*pUcon & mask) != 0) s3c44b0x_dma_proccess(state, index);			} while (0);		}		if (*pUfcon & 0x1) { /* FIFO mode */			struct s3c44b0x_uart_fifo *pUfifo = (read_uart0 ? &io.ufifo0 : &io.ufifo1);			int count, tmp_count;			if ((*pUfstat & 0x100) == 0 && (*pUcon & 0x3) != 0x0) { /* FIFO not full */				tmp_count = count = (*pUfstat & 0xf);				count += skyeye_uart_read(read_uart0 ? 0 : 1, &pUfifo->rx[count], 16 - count, &tv, NULL);				if (count > tmp_count) {					*pUfstat &= ~0xf;					*pUfstat |= (count == 16 ? 0x10f : count);				}			}			while ((count = ((*pUfstat & 0xf0) >> 4)) > 0 && (*pUcon & 0xc) != 0x0) { /* handling TX FIFO */				if (pUfifo->txcnt > 0) {					pUfifo->txcnt -= 1;					break;				}				if (*pUfstat & 0x200) count++;				tmp_count = skyeye_uart_write(read_uart0 ? 0 : 1, &pUfifo->tx[0], count, NULL);				if (tmp_count <= 0) break;				count -= tmp_count;				*pUfstat &= ~0x2f0;				if (count > 0) {					*pUfstat |= (count << 4);					memmove(&pUfifo->tx[0], &pUfifo->tx[tmp_count], (size_t)count);				} else {					pUfifo->txcnt = 64;				}				if ((*pUcon & 0xc) == 0x4) { /* Transmit Mode: Interrupt request or polling mode */					s3c44b0x_set_interrupt(read_uart0 ? INT_UTXD0 : INT_UTXD1);				}				break;			}			if ((*pUfstat & 0xf) == 0) continue;			*pUrxh = (ARMword)pUfifo->rx[0];		} else { /* non FIFO mode */			unsigned char buf;			if ((*pUcon & 0x3) == 0x0) continue;			if (*pUtrstat & 0x1) continue;			if (skyeye_uart_read(read_uart0 ? 0 : 1, &buf, 1, &tv, NULL) <= 0) continue;			*pUrxh = (ARMword)buf;			*pUtrstat |= 0x1;		}		if ((*pUcon & 0x3) == 0x1) s3c44b0x_set_interrupt(read_uart0 ? INT_URXD0 : INT_URXD1);	} while((read_uart0--) && skyeye_config.uart.count > 1);}static void s3c44b0x_uart_read(ARMword addr, ARMword *data){	switch (addr) {		case ULCON0:			*data = io.ulcon0;			break;		case ULCON1:			*data = io.ulcon1;			break;		case UCON0:			*data = io.ucon0;			break;		case UCON1:			*data = io.ucon1;			break;		case UFCON0:			*data = io.ufcon0;			break;		case UFCON1:			*data = io.ufcon1;			break;		case UMCON0:			*data = io.umcon0;			break;		case UMCON1:			*data = io.umcon1;			break;		case UTRSTAT0:			*data = io.utrstat0;			break;		case UTRSTAT1:			*data = io.utrstat1;			break;		case UERSTAT0:			*data = io.uerstat0;			break;		case UERSTAT1:			*data = io.uerstat1;			break;		case UFSTAT0:			*data = io.ufstat0;			break;		case UFSTAT1:			*data = io.ufstat1;			break;		case UMSTAT0:			*data = io.umstat0;			break;		case UMSTAT1:			*data = io.umstat1;			break;		case URXH0:		case URXH1:			{				ARMword *pUfstat = (addr == URXH0 ? &io.ufstat0 : &io.ufstat1);				ARMword *pUtrstat = (addr == URXH0 ? &io.utrstat0 : &io.utrstat1);				ARMword *pUfcon = (addr == URXH0 ? &io.ufcon0 : &io.ufcon1);				ARMword *pUrxh = (addr == URXH0 ? &io.urxh0 : &io.urxh1);				*data = (*pUrxh);				if (*pUfcon & 0x1) { /* FIFO mode */					ARMword *pUcon = (addr == URXH0 ? &io.ucon0 : &io.ucon1);					struct s3c44b0x_uart_fifo *pUfifo = (addr == URXH0 ? &io.ufifo0 : &io.ufifo1);					int count = (*pUfstat & 0xf);					if (count == 0) break;					if (*pUfstat & 0x100) count++;					*pUfstat &= ~0x10f;					if (count == 1) break;					*pUfstat |= (--count);					memmove(&pUfifo->rx[0], &pUfifo->rx[1], (size_t)count);

⌨️ 快捷键说明

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