📄 skyeye_mach_lh79520.c
字号:
/*
skyeye_mach_lh79520.c - define machine lh79520 for skyeye
Copyright (C) 2003 Skyeye Develop Group
for help please send mail to <skyeye-developer@lists.sf.linuxforum.net>
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
*/
/*
* 11/17/2004 init this file.
* add machine lh79520's function.
* include: lh79520_mach_init, lh79520_io_do_cycle
* lh79520_io_read_word, lh79520_io_write_word
* Cai Qiang <caiqiang@ustc.edu>
*
* */
#include "armdefs.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "lh79520-hardware.h"
#include "lh79520-irqs.h"
#include "serial_amba_pl011.h"
#include "lh79520.h"
//zzc:2005-1-1
#ifdef __CYGWIN__
//chy 2005-07-28
#include <time.h>
struct timeval
{
long tv_sec;
long tv_usec;
};
#endif
#define REVISION "$Revision: 1.1.1.1 $"
#define TC_DIVISOR (50) /* Set your BogoMips here :) */
#define DEBUG 1
#if DEBUG
#define DBG_PRINT(a...) fprintf(stderr,##a)
#else
#define DBG_PRINT(a...)
#endif
/*Internal IO Register*/
typedef struct lh79520_io
{
ARMword intsr; /* Interrupt status reg */
ARMword intmr; /* Interrupt mask reg */
ARMword tcd[2]; /* Timer/counter data */
ARMword tcd_reload[2]; /* Last value written */
ARMword tcd_ctrl[2]; /* Timer Control Register */
int tc_prescale;
ARMword uartdr; /* Receive Data Register */
ARMword uartfr; /* Flag Register */
ARMword uartcr; /* Control Register */
ARMword uartimsc; /* Interrupt Mask Set/Clear register */
ARMword uartmis; /* Masked Interrupt Status Register */
} lh79520_io_t;
static lh79520_io_t lh79520_io;
#define io lh79520_io
static void
lh79520_update_int (ARMul_State * state)
{
ARMword requests = io.intsr & io.intmr;
state->NfiqSig = (requests & 0x0001) ? LOW : HIGH;
state->NirqSig = (requests & 0xfffffffe) ? LOW : HIGH;
}
static void
lh79520_io_reset (ARMul_State * state)
{
int i;
io.intmr = 0;
io.intsr = 0;
for (i = 0; i < 2; i++)
{
io.tcd[i] = 0xffff;
io.tcd_reload[i] = 0xffff;
io.tcd_ctrl[i] = 0;
}
io.tc_prescale = TC_DIVISOR;
io.uartdr = 0;
io.uartfr = AMBA_UARTFR_TXFE;
}
static void
UART2VIC (ARMul_State * state)
{
if (io.uartmis)
io.intsr |= UART1INT;
else
io.intsr &= ~UART1INT;
lh79520_update_int (state);
}
void
lh79520_io_do_cycle (ARMul_State * state)
{
int t;
io.tc_prescale--;
if (io.tc_prescale < 0)
{
io.tc_prescale = TC_DIVISOR;
for (t = 0; t < 2 - 1; t++)
{ //only timer0 be supported now
if (io.tcd[t] == 0)
{
if (io.tcd_ctrl[t] & TIMER_CONTROL_MODE)
{ //Periodic mode
io.tcd[t] = io.tcd_reload[t];
}
else
{ //Free-Running mode
io.tcd[t] = 0xffff;
}
io.intsr |= (t ? TC2OI : TC1OI);
lh79520_update_int (state);
}
else
{
io.tcd[t]--;
}
}
if (!(io.intsr & UART1INT))
{
fd_set rfds;
struct timeval tv;
FD_ZERO (&rfds);
FD_SET (skyeye_config.uart.fd_in, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
if (select (skyeye_config.uart.fd_in + 1, &rfds, NULL, NULL, &tv) ==
1)
{
unsigned char buf;
int n;
n = read (skyeye_config.uart.fd_in, &buf, 1);
if (n)
{
io.uartdr = (int) buf;
io.uartfr &= ~AMBA_UARTFR_RXFE;
io.uartmis |= AMBA_UART_IS_RX;
UART2VIC (state);
}
}
} //if (!(io.intsr & UART1INT))
}
}
ARMword
lh79520_io_read_word (ARMul_State * state, ARMword addr)
{
ARMword data = 0;
switch (addr)
{
case RCPC_PHYS:
case RCPC_HCLKPrescale:
case RCPC_periphClkCtrl:
case IOCON_UARTMux:
case UART1_PHYS + UARTLCR_H:
// printf("%s(%x)\n", __func__, addr);
break;
case UART1_PHYS + UARTCR:
data = io.uartcr;
break;
case UART0_PHYS + UARTFR:
case UART1_PHYS + UARTFR:
data = io.uartfr;
break;
case UART1_PHYS + UARTRSR:
data = 0;
break;
case UART1_PHYS + UARTIMSC: //5: TXIM 4: RXIM
data = io.uartimsc;
break;
case UART1_PHYS + UARTMIS: //5: TXIM 4: RXIM
data = io.uartmis;
break;
case UART1_PHYS + UARTDR:
data = io.uartdr;
io.uartfr |= AMBA_UARTFR_RXFE;
io.uartmis &= ~AMBA_UART_IS_RX;
UART2VIC (state);
break;
case VIC_IRQStatus:
data = io.intsr;
break;
case VIC_IntEnable:
data = io.intmr;
break;
default:
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
printf ("SKYEYE:unknown io addr, %s(0x%08x), pc %x \n", __func__, addr,
state->Reg[15]);
//SKYEYE_DBG("io_read_word(0x%08x) = 0x%08x\n", addr, data);
break;
}
return data;
}
ARMword
lh79520_io_read_byte (ARMul_State * state, ARMword addr)
{
//some parts of kernel such as printascii use byte operation
if (addr >= UART1_PHYS + UARTDR && addr <= UART1_PHYS + UARTICR)
return lh79520_io_read_word (state, addr);
else
{
printf ("SKYEYE: %s error\n", __func__);
printf ("SKYEYE: state->pc=%x,state->instr=%x,addr=%x\n", state->pc,
state->instr, addr);
system ("stty sane");
exit (-1);
}
}
ARMword
lh79520_io_read_halfword (ARMul_State * state, ARMword addr)
{
//some parts of kernel use it
if (addr >= UART1_PHYS + UARTDR && addr <= UART1_PHYS + UARTICR)
return lh79520_io_read_word (state, addr);
else
{
printf ("SKYEYE: %s error %x\n", __func__, addr);
system ("stty sane");
exit (-1);
}
}
void
lh79520_io_write_word (ARMul_State * state, ARMword addr, ARMword data)
{
ARMword tmp;
if (addr >= VIC_VectAddr && addr <= VIC_VectAddr + 0x3c)
{
// printf("%s VectAddr(%x %x)\n", __func__, addr, data);
return;
}
if (addr >= VIC_VectCntl && addr <= VIC_VectCntl + 0x3c)
{
// printf("%s VectCntl(%x %x)\n", __func__, addr, data);
return;
}
if (addr >= DMAC_PHYS && addr < RCPC_PHYS)
{
// printf("%s DMAC(%x %x)\n", __func__, addr, data);
return;
}
switch (addr)
{
case VIC_IntSelect:
case IOCON_MiscMux:
case IOCON_UARTMux:
case RCPC_PHYS:
case RCPC_intClear:
case RCPC_intConfig:
case RCPC_HCLKPrescale:
case RCPC_periphClkCtrl:
case TIMER0_LOAD:
case TIMER0_VALUE:
case TIMER1_LOAD:
case TIMER1_VALUE:
case TIMER1_CONTROL:
case TIMER1_CLEAR:
case TIMER2_CONTROL:
case TIMER3_CONTROL:
case UART1_PHYS + UARTIBRD:
case UART1_PHYS + UARTLCR_H:
// printf("%s(%x %x)\n", __func__, addr, data);
break;
case TIMER0_CONTROL:
io.tcd_ctrl[0] = data;
break;
case TIMER0_CLEAR:
io.intsr &= ~TC1OI;
lh79520_update_int (state);
break;
case VIC_IntEnable:
io.intmr = data;
lh79520_update_int (state);
break;
case VIC_IntEnClear:
io.intmr &= ~data;
lh79520_update_int (state);
break;
case UART0_PHYS:
case UART1_PHYS:
/* The UART writes chars to console */
{
char c = data;
// write(skyeye_config.uart.fd_out, &c, 1);
printf ("%c", c);
fflush (stdout);
}
break;
case UART1_PHYS + UARTCR:
io.uartcr = data;
break;
case UART1_PHYS + UARTIMSC: //5: TXIM 4: RXIM
io.uartimsc = data;
if (data & AMBA_UART_IS_TX)
io.uartmis |= AMBA_UART_IS_TX;
else
io.uartmis &= ~AMBA_UART_IS_TX;
UART2VIC (state);
break;
default:
//chy 2003-07-11: sometime has fault, but linux can continue running !!!!????
printf ("SKYEYE:unknown io addr, %s(0x%08x, 0x%08x), pc %x \n",
__func__, addr, data, state->Reg[15]);
break;
}
}
void
lh79520_io_write_byte (ARMul_State * state, ARMword addr, ARMword data)
{
//some parts of kernel such as printascii use byte operation
if (addr >= UART1_PHYS + UARTDR && addr <= UART1_PHYS + UARTICR)
return lh79520_io_write_word (state, addr, data);
else
{
printf ("SKYEYE: %s(%x %x) error\n", __func__, addr, data);
SKYEYE_OUTREGS (stderr);
system ("stty sane");
exit (-1);
}
}
void
lh79520_io_write_halfword (ARMul_State * state, ARMword addr, ARMword data)
{
printf ("SKYEYE: %s error %x %x\n", __func__, addr, data);
exit (-1);
}
void
lh79520_mach_init (ARMul_State * state, machine_config_t * this_mach)
{
ARMul_SelectProcessor (state, ARM_v4_Prop);
state->lateabtSig = HIGH;
// state->Reg[1] = 999; //MACH_TYPE_LH79520EVB
state->Reg[1] = 997; //MACH_TYPE_LH79520LPD
this_mach->mach_io_do_cycle = lh79520_io_do_cycle;
this_mach->mach_io_reset = lh79520_io_reset;
this_mach->mach_io_read_byte = lh79520_io_read_byte;
this_mach->mach_io_write_byte = lh79520_io_write_byte;
this_mach->mach_io_read_halfword = lh79520_io_read_halfword;
this_mach->mach_io_write_halfword = lh79520_io_write_halfword;
this_mach->mach_io_read_word = lh79520_io_read_word;
this_mach->mach_io_write_word = lh79520_io_write_word;
this_mach->mach_update_int = lh79520_update_int;
state->mach_io.instr = (ARMword *) & io.intsr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -