📄 skyeye_mach_s3c44b0x.c
字号:
/* 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> *//* * WARNING: uncompleted yet !!! * * COMPLETED: Interrupt, UART, Timer, LCD * TODO: I/O Ports, RTC, etc. */#include "armdefs.h"#include "s3c44b0.h"#include "skyeye_uart.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/* S3C44B0X Internal IO Registers */struct s3c44b0x_io_t{ /* CPU Wrapper Registers */ ARMword syscfg; ARMword ncachbe0; ARMword ncachbe1; ARMword sbuscon; /* 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; /* Timers Registers */ ARMword tcfg0; ARMword tcfg1; ARMword tcon; ARMword tcntb[6]; ARMword tcmpb[5]; ARMword tcnt[6]; ARMword tcmp[5]; ARMword ttmp[6]; ARMword ttmpb[6];};static struct s3c44b0x_io_t s3c44b0x_io;#define io s3c44b0x_iostatic void s3c44b0x_io_reset(ARMul_State * state){ memset(&io, 0, sizeof(io)); /* CPU Wrapper */ io.syscfg = 0x1; io.sbuscon = 0x80001b1b; /* 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;}/* Interrupt Routine */static void s3c44b0x_update_int(ARMul_State *state){ ARMword requests = (io.intmsk & (0x1 << INT_GLOBAL)) ? 0x0 : (io.intpnd & ~io.intmsk); state->NfiqSig = (requests & io.intmod) ? LOW : HIGH; state->NirqSig = (requests & ~io.intmod) ? LOW : HIGH;}static void s3c44b0x_update_intr(void *mach){ struct machine_config *mc = (struct machine_config*)mach; ARMul_State *state = (ARMul_State*)mc->state; s3c44b0x_update_int(state);}static int s3c44b0x_pending_intr(unsigned int irq){ 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.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: case F_ISPR: *data = 0; if ((addr == I_ISPR && (io.intcon & 0x2) == 0x0) || (addr == F_ISPR && (io.intcon & 0x5) == 0x4)) { for (i = 0; i < 26; i++) { /* find which interrupt is pending */ if (io.intpnd & (0x1 << i)) { *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; if (io.intmsk & (0x1 << INT_GLOBAL)) io.intpnd = 0x1; break; case I_PSLV: io.i_pslv = data; break; case I_PMST: io.i_pmst = data; break; case I_ISPC: io.intpnd &= (~data & 0x3ffffff); break; case F_ISPC: 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; unsigned char buf; 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); if ((*pUtrstat & 0x1) == 0x0) { /* Receive buffer: Completely empty */ if (skyeye_uart_read(read_uart0 ? 0 : 1, &buf, 1, &tv, NULL) > 0) { *pUrxh = (ARMword)buf; *pUtrstat |= 0x1; /* for FIFO mode */ *pUfstat &= ~0x10f; *pUfstat |= 0x1; if ((*pUcon & 0x3) == 0x1) { /* Receive Mode: Interrupt request or polling mode */ s3c44b0x_set_interrupt(read_uart0 ? INT_URXD0 : INT_URXD1); } } } } while(read_uart0--);}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: *data = io.urxh0; io.utrstat0 &= ~0x1; io.ufstat0 &= ~0x10f; /* for FIFO mode */ break; case URXH1: *data = io.urxh1; io.utrstat1 &= ~0x1; io.ufstat1 &= ~0x10f; /* for FIFO mode */ break; case UBRDIV0: *data = io.ubrdiv0; break; case UBRDIV1: *data = io.ubrdiv1; break; default: break; }// DEBUG("%s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, *data);}static void s3c44b0x_uart_write(ARMul_State *state, ARMword addr, ARMword data){ char tmp;// DEBUG("%s(addr:0x%x, data:0x%x)\n", __FUNCTION__, addr, data); switch (addr) { case ULCON0: io.ulcon0 = data; break; case ULCON1: io.ulcon1 = data; break; case UCON0: io.ucon0 = data; break; case UCON1: io.ucon1 = data; break; case UFCON0: io.ufcon0 = data; break; case UFCON1: io.ufcon1 = data; break; case UMCON0: io.umcon0 = data; break; case UMCON1: io.umcon1 = data; break; case UTXH0: case UTXH1: { tmp = data & 0xff; skyeye_uart_write(addr == UTXH0 ? 0 : 1, (void*)&tmp, 1, NULL); if (addr == UTXH0) { io.utrstat0 |= 0x6; io.ufstat0 &= ~0x2f0; /* for FIFO mode */ } else { io.utrstat1 |= 0x6; io.ufstat1 &= ~0x2f0; /* for FIFO mode */ } tmp = (addr = UTXH0 ? io.ucon0 : io.ucon1) & 0xc; if (tmp == 0x4) { /* Transmit Mode: Interrupt request or polling mode */ s3c44b0x_set_interrupt(addr = UTXH0 ? INT_UTXD0 : INT_UTXD1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -