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

📄 skyeye_mach_lpc.c

📁 这是Skyeye 0.9 版本的源代码
💻 C
字号:
/*
	skyeye_mach_lpc.c - define machine lpc for skyeye
	Copyright (C) 2003 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 
 
*/
/*
 * 3/24/2003 	init this file.
 * 		add machine lpc's function.Most taken from original armio.c 
 * 		include: lpc_mach_init, lpc_io_do_cycle
 * 		lpc_io_read_word, lpc_io_write_word
 *		walimis <walimi@peoplemail.com.cn> 
 *		
 *3/24/2003	chenyu <chenyu-tmlinux@hpclab.cs.tsinghua.edu.cn> has done the
 *		necessary work to armio.c
 * */
#include "armdefs.h"
#include "lpc.h"
//zzc:2005-1-1
#ifdef __CYGWIN__
//chy 2005-07-28
#include <time.h>

struct timeval
{
  long tv_sec;
  long tv_usec;
};
#endif

//teawater add for arm2x86 2005.03.18-------------------------------------------
//make gcc-3.4 can compile this file
ARMword lpc_io_read_word (ARMul_State * state, ARMword addr);
void lpc_io_write_word (ARMul_State * state, ARMword addr, ARMword data);
//AJ2D--------------------------------------------------------------------------


#define DEBUG 0
#if DEBUG
#define DBG_PRINT(a...) fprintf(stderr, ##a)
#else
#define DBG_PRINT(a...)
#endif

typedef struct timer
{
  ARMword ir;
  ARMword tcr;
  ARMword tc;
  ARMword pr;
  ARMword pc;
  ARMword mcr;
  ARMword mr0;
  ARMword mr1;
  ARMword mr2;
  ARMword mr3;
  ARMword ccr;
  ARMword cr0;
  ARMword cr1;
  ARMword cr2;
  ARMword cr3;
  ARMword emr;
} lpc_timer_t;

typedef struct uart
{
  ARMword rbr;
  ARMword thr;
  ARMword ier;
  ARMword iir;
  ARMword fcr;
  ARMword lcr;
  ARMword lsr;
  ARMword msr;
  ARMword scr;
  ARMword dll;
  ARMword dlm;
  char t_fifo[16];
  char r_fifo[16];
} lpc_uart_t;

typedef struct pll
{
  ARMword con;
  ARMword cfg;
  ARMword stat;
  ARMword feed;
} lpc_pll_t;

typedef struct vic
{
  ARMword isr;
  ARMword fsr;
  ARMword risr;
  ARMword islr;
  ARMword ier;
  ARMword iecr;
  ARMword sir;
  ARMword sicr;
  ARMword per;
  ARMword var;
  ARMword dvar;
  ARMword va[15];
  ARMword vc[15];
} lpc_vic_t;

typedef struct lpc_io
{
  ARMword syscon;		/* System control */
  ARMword sysflg;		/* System status flags */
  lpc_pll_t pll;
  lpc_timer_t timer[2];
  lpc_vic_t vic;
  ARMword pinsel0;
  lpc_uart_t uart[2];		/* Receive data register */
  ARMword mmcr;			/*Memory mapping control register */


} lpc_io_t;

static lpc_io_t lpc_io;

#define io lpc_io

static void
lpc_update_int (ARMul_State * state)
{
  u32 irq = 0;
//        state->NfiqSig = (~(io.vic.risr&io.vic.ier& io.vic.)) ? LOW : HIGH;
  irq = io.vic.risr & io.vic.ier;
  io.vic.isr = irq & ~io.vic.islr;
  io.vic.fsr = irq & io.vic.islr;
  if (io.vic.isr & IRQ_UART0)
    {
      io.vic.var = io.vic.va[6];
    }
  if (io.vic.isr & IRQ_TC0)
    {
      io.vic.var = io.vic.va[4];
    }
  state->NirqSig = io.vic.isr ? LOW : HIGH;
  state->NfiqSig = io.vic.fsr ? LOW : HIGH;


}
static void
lpc_io_reset (ARMul_State * state)
{
  io.timer[0].pr = 500000;	/*prescale value */
  io.vic.isr = 0;
  io.vic.fsr = 0;
  io.vic.risr = 0;

  io.uart[0].lsr = 0x60;
  io.uart[0].iir = 0x01;
  io.pinsel0 = 0;
}

       /*

          //state->Exception = TRUE;
          } */

/*lpc io_do_cycle*/
void
lpc_io_do_cycle (ARMul_State * state)
{
  int t;
  io.timer[0].pc++;
  io.timer[1].pc++;
  if (!(io.vic.risr & IRQ_TC0))
    {
      if (io.timer[0].pc >= io.timer[0].pr + 1)
	{
	  //      if (io.timer[0].pc >=  5000+1) {                        
	  io.timer[0].tc++;
	  io.timer[0].pc = 0;
	  if (io.timer[0].tc == io.timer[0].mr0)
	    {
	      //      if(io.timer[0].tc == 20){
	      io.vic.risr |= IRQ_TC0;
	      io.timer[0].tc = 0;
	    }
	  lpc_update_int (state);
	}
    }
  if (io.timer[0].pc == 0)
    {
      if (!(io.vic.risr & IRQ_UART0))
	{
	  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, i;
	      n = read (skyeye_config.uart.fd_in, &buf, sizeof (buf));
	      //printf("SKYEYE:get input is %c\n",buf);
	      if (n)
		{
		  io.uart[0].rbr = buf;
		  io.uart[0].lsr |= 0x1;
		  io.vic.risr |= IRQ_UART0;
		  lpc_update_int (state);
		}
	    }
	}			/* if (rcr > 0 && ... */
    }
}


ARMword
lpc_fix_int (ARMword val)
{
/*	ARMword ret = 0;
	if (val & (1 << 2))
		ret |= URXINT;
	if (val & (1 << 5))
		ret |= TC1OI;
	if (val & (1 << 6))
		ret |= TC2OI;
	if (val & (1 << 16))
		ret |= AT91_EXT0;*/
  return (val);
}

ARMword
lpc_unfix_int (ARMword val)
{
/*	ARMword ret = 0;
	if (val & URXINT)
		ret |= (1 << 2);
	if (val & TC1OI)
		ret |= (1 << 5);
	if (val & TC2OI)
		ret |= (1 << 6);
	if (val & AT91_EXT0)
		ret |= (1 << 16);
		*/
  return (val);
}

ARMword
lpc_uart_read (ARMul_State * state, ARMword addr, int i)
{
  ARMword data;
  //printf("lpc_uart_read,addr=%x\n",addr);
  switch ((addr & 0xfff) >> 2)
    {
    case 0x0:			// RbR
      io.uart[i].lsr &= ~0x1;
      if (i == 0)
	io.vic.risr &= ~IRQ_UART0;
      else
	io.vic.risr &= ~IRQ_UART1;
      lpc_update_int (state);
      data = io.uart[i].rbr;
      break;

    case 0x1:			// ier
      data = io.uart[i].ier;
      break;
    case 0x2:			// iir
      data = io.uart[i].iir;
      break;
    case 0x3:			// IDR
    case 0x4:			// IMR
    case 0x5:			// LSR
      data = io.uart[i].lsr;
      break;
    case 0x6:			// MSR
      data = io.uart[i].msr;
      break;
    case 0x7:			// SCR
      data = io.uart[i].scr;
      break;

    default:
      DBG_PRINT ("uart_read(%s=0x%08x)\n", "uart_reg", addr);

      break;
    }

  return (data);
}


void
lpc_uart_write (ARMul_State * state, ARMword addr, ARMword data, int i)
{
  static ARMword tx_buf = 0;

  //DBG_PRINT("uart_write(0x%x, 0x%x)\n", (addr & 0xfff) >> 2, data);
  switch ((addr & 0xfff) >> 2)
    {
    case 0x0:			// THR
      {
	char c = data;
	write (skyeye_config.uart.fd_out, &c, 1);
	//io.uart[0].lsr |= 0x40;
	io.uart[0].lsr |= 0x20;
      }
    case 0x2:			//FCR
      {
	io.uart[i].fcr = data;
	break;
      }
    case 0x7:			// SCR
      io.uart[i].scr = data;
      break;
    default:
      //printf("%c", data); fflush(stdout);
      DBG_PRINT ("uart_write(%s=0x%08x)\n", "uart_reg", addr);
      break;
    }
}

ARMword
lpc_io_read_word (ARMul_State * state, ARMword addr)
{
  /*
   *       * The LPC system registers
   *               */

  ARMword data = -1;
  static ARMword current_ivr = 0;	/* mega hack,  2.0 needs this */
  int i;
  ARMword dataimr = 0;


  switch (addr)
    {
    case 0xfffff000:		/* ISR */
//              data = unfix_int(io.intsr);
//              dataimr = unfix_int(io.intmr);
      data = io.vic.isr;
      DBG_PRINT ("read ISR=%d\n", data);
      break;
    case 0xfffff004:		/* interrupt status register */
      data = io.vic.fsr;
      DBG_PRINT ("SKYEYE:read ISR=%x,%x\n", data, io.vic.fsr);
      break;
    case 0xfffff008:		/* IMR */
      data = io.vic.risr;
      break;
    case 0xfffff00c:		/* CORE interrupt status register */
      data = io.vic.islr;
      break;
    case 0xfffff010:		/* IER */
      data = io.vic.ier;
      DBG_PRINT ("read IER=%x,after update ier=%x\n", data, io.vic.ier);
      break;

    case 0xfffff014:		/* IECR */
      data = io.vic.iecr;
      lpc_update_int (state);
      break;
    case 0xfffff034:		/* DVAR */
      data = io.vic.dvar;
      break;
    case 0xfffff030:		/* VAR */
      data = io.vic.var;
      break;

      /*Timer0 */
    case 0xe0004000:
      data = io.timer[0].ir;
      break;
    case 0xe0004004:
      data = io.timer[0].tcr;
      break;
    case 0xe0004008:
      data = io.timer[0].tc;
      //io.vic.risr &= ~IRQ_TC0;
      //printf("SKYEYE:Clear TC Interrupt,tc=%x,risr=%x,\n",data,io.vic.risr);
      //lpc_update_int(state);
      break;
    case 0xe000400c:
      data = io.timer[0].pr;
      break;
    case 0xe0004010:
      data = io.timer[0].pc;
      break;
    case 0xe0004014:
      data = io.timer[0].mcr;
      break;
    case 0xe0004018:
      data = io.timer[0].mr0;
      break;

/*pll*/
    case 0xe01fc080:
      data = io.pll.con;
      break;
    case 0xe01fc084:
      data = io.pll.cfg;
      break;
    case 0xe01fc088:
      data = io.pll.stat;
      break;
    case 0xe01fc08c:
      data = io.pll.feed;
    case 0xe002c000:
      data = io.pinsel0;
      break;
    default:
      if (addr >= 0xe000c000 && addr <= 0xe000c01c)
	{
	  data = lpc_uart_read (state, addr, 0);
	  break;
	}
      if (addr >= 0xe0001000 && addr <= 0xe000101c)
	{
	  data = lpc_uart_read (state, addr, 1);
	  break;
	}
      if (addr - 0xfffff100 <= 0x3c && addr - 0xfffff100 >= 0)
	{
	  data = io.vic.va[(addr - 0xfffff100) / 4];
	  break;
	}
      if (addr - 0xfffff200 <= 0x3c && addr - 0xfffff200 >= 0)
	{
	  data = io.vic.vc[(addr - 0xfffff200) / 4];
	  break;
	}

      printf ("ERROR:io_read: addr = %x\n", addr);

      /*fprintf(stderr,"NumInstr %llu, io_read_word unknown addr(0x%08x) = 0x%08x\n", state->NumInstrs, addr, data); */
      SKYEYE_OUTREGS (stderr);
      //ARMul_Debug(state, 0, 0);
      break;
    }
  return data;
}

ARMword
lpc_io_read_byte (ARMul_State * state, ARMword addr)
{
  return lpc_io_read_word (state, addr);
//                      SKYEYE_OUTREGS(stderr);
  //exit(-1);

}

ARMword
lpc_io_read_halfword (ARMul_State * state, ARMword addr)
{
  return lpc_io_read_word (state, addr);
  //SKYEYE_OUTREGS(stderr);
  //exit(-1);
}


void
lpc_io_write_word (ARMul_State * state, ARMword addr, ARMword data)
{
  /*
   * The lpc system registers
   */


  switch (addr)
    {
    case 0xfffff000:		/* ISR */
      DBG_PRINT ("SKYEYE:can not write  ISR,it is RO,=%d\n", data);
      break;
    case 0xfffff004:		/* interrupt status register */
      //io.vic.fsr = data ;
//              DBG_PRINT("read ISR=%x,%x\n", data, io.intsr);
      DBG_PRINT ("can not write  fsr,it is RO,=%d\n", data);
      break;
    case 0xfffff008:		/* IMR */
      //io.vic.risr = data;
      DBG_PRINT ("can not write  risr,it is RO,=%d\n", data);
      break;
    case 0xfffff00c:		/* CORE interrupt status register */
      io.vic.islr = data;
      break;
    case 0xfffff010:		/* IER */
      io.vic.ier = data;
      io.vic.iecr = ~data;
      lpc_update_int (state);
//              data = unfix_int(io.intmr);
      DBG_PRINT ("write IER=%x,after update ier=%x\n", data, io.vic.ier);
      break;
    case 0xfffff014:		/* IECR */
      io.vic.iecr = data;
      io.vic.ier = ~data;
      lpc_update_int (state);
      break;

    case 0xfffff018:		/* SIR */
      io.vic.sir = data;
      break;
    case 0xfffff01c:		/* SICR */
      io.vic.sicr = data;
      break;
    case 0xfffff020:		/* PER */
      io.vic.per = data;
      break;
    case 0xfffff030:		/* VAR */
      io.vic.var = data;
      break;
    case 0xfffff034:		/* DVAR */
      io.vic.dvar = data;
      break;


      /*Timer0 */
    case 0xe0004000:
      io.timer[0].ir = data;
      if (io.timer[0].ir & 0x1)
	{
	  io.timer[0].ir &= 0x0;
	  io.vic.risr &= ~IRQ_TC0;
	}
      lpc_update_int (state);
      break;
    case 0xe0004004:
      io.timer[0].tcr = data;
      break;
    case 0xe0004008:
      io.timer[0].tc = data;
      break;
    case 0xe000400c:
      io.timer[0].pr = data;
      break;
    case 0xe0004010:
      io.timer[0].pc = data;
      break;
    case 0xe0004014:
      io.timer[0].mcr = data;
      break;
    case 0xe0004018:
      io.timer[0].mr0 = data;
      break;

      /*pll */
    case 0xe01fc080:
      io.pll.con = data;
      break;
    case 0xe01fc084:
      io.pll.cfg = data;
      break;
    case 0xe01fc088:
      io.pll.stat = data;
      break;
    case 0xe01fc08c:
      io.pll.feed = data;
      break;
      /*memory map control */
    case 0xe01fc040:
      io.mmcr = data;
      break;
    case 0xe002c000:
      io.pinsel0 = data;
      break;
    default:
      if (addr >= 0xe000c000 && addr <= 0xe000c01c)
	{
	  lpc_uart_write (state, addr, data, 0);
	  break;
	}
      if (addr >= 0xe0001000 && addr <= 0xe000101c)
	{
	  lpc_uart_write (state, addr, data, 1);
	  break;
	}

      if (addr - 0xfffff100 <= 0x3c && addr - 0xfffff100 >= 0)
	{
	  io.vic.va[(addr - 0xfffff100) / 4] = data;
	  break;
	}
      if (addr - 0xfffff200 <= 0x3c && addr - 0xfffff200 >= 0)
	{
	  io.vic.vc[(addr - 0xfffff200) / 4] = data;
	  break;
	}
      printf ("ERROR:io_write a non-exsiting addr:addr = %x, data = %x\n",
	      addr, data);
      /*
         fprintf(stderr,"NumInstr %llu,io_write_word unknown addr(1x%08x) = 0x%08x\n", state->NumInstrs, addr, data); */
      //SKYEYE_OUTREGS(stderr);
      //ARMul_Debug(state, 0, 0);
      break;
    }
}

void
lpc_io_write_byte (ARMul_State * state, ARMword addr, ARMword data)
{

  lpc_io_write_word (state, addr, data);
  //SKYEYE_OUTREGS(stderr);
  //exit(-1);

}

void
lpc_io_write_halfword (ARMul_State * state, ARMword addr, ARMword data)
{
  lpc_io_write_word (state, addr, data);
  //SKYEYE_OUTREGS(stderr);
  //exit(-1);
}


void
lpc_mach_init (ARMul_State * state, machine_config_t * this_mach)
{
  //chy 2003-08-19, setprocessor
  ARMul_SelectProcessor (state, ARM_v4_Prop);
  //chy 2004-05-09, set lateabtSig
  state->lateabtSig = HIGH;

  this_mach->mach_io_do_cycle = lpc_io_do_cycle;
  this_mach->mach_io_reset = lpc_io_reset;
  this_mach->mach_io_read_byte = lpc_io_read_byte;
  this_mach->mach_io_write_byte = lpc_io_write_byte;
  this_mach->mach_io_read_halfword = lpc_io_read_halfword;
  this_mach->mach_io_write_halfword = lpc_io_write_halfword;
  this_mach->mach_io_read_word = lpc_io_read_word;
  this_mach->mach_io_write_word = lpc_io_write_word;

  this_mach->mach_update_int = lpc_update_int;

  //ksh 2004-2-7


  state->mach_io.instr = (ARMword *) & io.vic.isr;
  //*state->io.instr = (ARMword *)&io.intsr;
  //state->io->net_flags = (ARMword *)&io.net_flags;
  //state->mach_io.net_int = (ARMword *)&io.net_int;


}

⌨️ 快捷键说明

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