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

📄 skyeye_mach_lh79520.c

📁 skyeye-1.0.0.rar surce code
💻 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 + -