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

📄 dv-mn103tim.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
    hw_abort(me, "bad read size for timer 6 register");  }      }static unsignedmn103tim_io_read_buffer (struct hw *me,			 void *dest,			 int space,			 unsigned_word base,			 unsigned nr_bytes){  struct mn103tim *timers = hw_data (me);  enum timer_register_types timer_reg;  HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));  timer_reg = decode_addr (me, timers, base);  /* It can be either a mode register, a base register, a binary counter, */  /* or a special timer 6 register.  Check in that order. */  if ( timer_reg >= FIRST_MODE_REG && timer_reg <= LAST_MODE_REG )    {      read_mode_reg(me, timers, timer_reg-FIRST_MODE_REG, dest, nr_bytes);    }  else if ( timer_reg <= LAST_BASE_REG )    {      read_base_reg(me, timers, timer_reg-FIRST_BASE_REG, dest, nr_bytes);    }  else if ( timer_reg <= LAST_COUNTER )    {      read_counter(me, timers, timer_reg-FIRST_COUNTER, dest, nr_bytes);    }  else if ( timer_reg <= LAST_TIMER_REG )    {      read_special_timer6_reg(me, timers, timer_reg, dest, nr_bytes);    }  else    {      hw_abort(me, "invalid timer register address.");    }  return nr_bytes;}     static voiddo_counter_event (struct hw *me,		  void *data){  struct mn103tim *timers = hw_data(me);  long timer_nr = (long) data;  int next_timer;  /* Check if counting is still enabled. */  if ( (timers->reg[timer_nr].mode & count_mask) != 0 )    {      /* Generate an interrupt for the timer underflow (TIMERn_UFLOW). */      /* Port event occurs on port of last cascaded timer. */      /* This works across timer range from 0 to NR_REG_TIMERS because */      /* the first 16 bit timer (timer 4) is not allowed to be set as  */      /* a cascading timer. */      for ( next_timer = timer_nr+1; next_timer < NR_REG_TIMERS; ++next_timer )	{	  if ( (timers->reg[next_timer].mode & clock_mask) != clk_cascaded )	    {	      break;	    }	}      hw_port_event (me, next_timer-1, 1);      /* Schedule next timeout.  */      timers->timer[timer_nr].start = hw_event_queue_time(me);      /* FIX: Check if div_ratio has changed and if it's now 0. */      timers->timer[timer_nr].event	= hw_event_queue_schedule (me, timers->timer[timer_nr].div_ratio,				   do_counter_event, (void *)timer_nr);    }  else    {      timers->timer[timer_nr].event = NULL;    }}static voiddo_counter6_event (struct hw *me,		  void *data){  struct mn103tim *timers = hw_data(me);  long timer_nr = (long) data;  int next_timer;  /* Check if counting is still enabled. */  if ( (timers->reg[timer_nr].mode & count_mask) != 0 )    {      /* Generate an interrupt for the timer underflow (TIMERn_UFLOW). */      hw_port_event (me, timer_nr, 1);      /* Schedule next timeout.  */      timers->timer[timer_nr].start = hw_event_queue_time(me);      /* FIX: Check if div_ratio has changed and if it's now 0. */      timers->timer[timer_nr].event	= hw_event_queue_schedule (me, timers->timer[timer_nr].div_ratio,				   do_counter6_event, (void *)timer_nr);    }  else    {      timers->timer[timer_nr].event = NULL;    }}static voidwrite_base_reg (struct hw *me,		struct mn103tim *timers,		int timer_nr,		const void *source,		unsigned  nr_bytes){  unsigned i;  const unsigned8 *buf8 = source;  const unsigned16 *buf16 = source;  /* If TMnCNE == 0 (counting is off),  writing to the base register     (TMnBR) causes a simultaneous write to the counter reg (TMnBC).     Else, the TMnBC is reloaded with the value from TMnBR when     underflow occurs.  Since the counter register is not explicitly     maintained, this functionality is handled in read_counter. */  /* Check nr_bytes: write of 1, 2 or 4 bytes allowed depending on timer. */  switch ( nr_bytes )    {    case 1:      /* Storing 1 byte is ok for all registers. */      timers->reg[timer_nr].base = buf8[0];      break;    case 2:      if ( timer_nr == 1 || timer_nr == 3 )	{	  hw_abort (me, "bad write size of 2 bytes to TM%dBR.", timer_nr);	}      else	{	  if ( timer_nr < NR_8BIT_TIMERS )	    {	      timers->reg[timer_nr].base = buf8[0];	      timers->reg[timer_nr+1].base = buf8[1];	    }	  else 	    {	      timers->reg[timer_nr].base = buf16[0];	    }	}      break;    case 4:      if ( timer_nr == 0 )	{	  timers->reg[0].base = buf8[0];	  timers->reg[1].base = buf8[1];	  timers->reg[2].base = buf8[2];	  timers->reg[3].base = buf8[3];	}      else if ( timer_nr == 4 )	{	  timers->reg[4].base = buf16[0];	  timers->reg[5].base = buf16[1];	}      else	{	  hw_abort (me, "bad write size of 4 bytes to TM%dBR.", timer_nr);	}      break;    default:      hw_abort (me, "bad write size must of %d bytes to TM%dBR.",		nr_bytes, timer_nr);    }     }static voidwrite_mode_reg (struct hw *me,		struct mn103tim *timers,		long timer_nr,		const void *source,		unsigned nr_bytes)     /* for timers 0 to 5 */{  unsigned i;  unsigned8 mode_val, next_mode_val;  unsigned32 div_ratio;  if ( nr_bytes != 1 )    {      hw_abort (me, "bad write size of %d bytes to TM%ldMD.", nr_bytes,		timer_nr);    }  mode_val = *(unsigned8 *)source;  timers->reg[timer_nr].mode = mode_val;        if ( ( mode_val & count_and_load_mask ) == count_and_load_mask )    {      hw_abort(me, "Cannot load base reg and start counting simultaneously.");    }  if ( ( mode_val & bits2to5_mask ) != 0 )    {      hw_abort(me, "Cannot write to bits 2 to 5 of mode register");    }  if ( mode_val & count_mask )    {      /* - de-schedule any previous event. */      /* - add new event to queue to start counting. */      /* - assert that counter == base reg? */      /* For cascaded timers, */      if ( (mode_val & clock_mask) == clk_cascaded )	{	  if ( timer_nr == 0 || timer_nr == 4 )	    {	      hw_abort(me, "Timer %ld cannot be cascaded.", timer_nr);	    }	}      else	{	  div_ratio = timers->reg[timer_nr].base;	  /* Check for cascading. */	  if ( timer_nr < NR_8BIT_TIMERS )	    {	      for ( i = timer_nr + 1; i <= 3; ++i ) 		{		  next_mode_val = timers->reg[i].mode;		  if ( ( next_mode_val & clock_mask ) == clk_cascaded )		    {		      /* Check that CNE is on. */		      if ( ( next_mode_val & count_mask ) == 0 ) 			{			  hw_abort (me, "cascaded timer not ready for counting");			}		      ASSERT(timers->timer[i].event == NULL);		      ASSERT(timers->timer[i].div_ratio == 0);		      div_ratio = div_ratio			| (timers->reg[i].base << (8*(i-timer_nr)));		    }		  else		    {		      break;		    }		}	    }	  else	    {	      /* Mode register for a 16 bit timer */	      next_mode_val = timers->reg[timer_nr+1].mode;	      if ( ( next_mode_val & clock_mask ) == clk_cascaded )		{		  /* Check that CNE is on. */		  if ( ( next_mode_val & count_mask ) == 0 ) 		    {		      hw_abort (me, "cascaded timer not ready for counting");		    }		  ASSERT(timers->timer[timer_nr+1].event == NULL);		  ASSERT(timers->timer[timer_nr+1].div_ratio == 0);		  div_ratio = div_ratio | (timers->reg[timer_nr+1].base << 16);		}	    }	  timers->timer[timer_nr].div_ratio = div_ratio;	  if ( NULL != timers->timer[timer_nr].event )	    {	      hw_event_queue_deschedule (me, timers->timer[timer_nr].event);	      timers->timer[timer_nr].event = NULL;	    }	  if ( div_ratio > 0 )	    {	      /* Set start time. */	      timers->timer[timer_nr].start = hw_event_queue_time(me);	      timers->timer[timer_nr].event		= hw_event_queue_schedule(me, div_ratio,					  do_counter_event,					  (void *)(timer_nr)); 	    }	}    }  else    {      /* Turn off counting */      if ( NULL != timers->timer[timer_nr].event )	{	  ASSERT((timers->reg[timer_nr].mode & clock_mask) != clk_cascaded);	  hw_event_queue_deschedule (me, timers->timer[timer_nr].event);	  timers->timer[timer_nr].event = NULL;	}      else	{	  if ( (timers->reg[timer_nr].mode & clock_mask) == clk_cascaded )	    {	      ASSERT(timers->timer[timer_nr].event == NULL);	    }	}          }}static voidwrite_tm6md (struct hw *me,	     struct mn103tim *timers,	     unsigned_word address,	     const void *source,	     unsigned nr_bytes){  unsigned8 mode_val0 = 0x00, mode_val1 = 0x00;  unsigned32 div_ratio;  long timer_nr = 6;  unsigned_word offset = address - timers->block[0].base;    if ((offset != 0x84 && nr_bytes > 1) || nr_bytes > 2 )    {      hw_abort (me, "Bad write size of %d bytes to TM6MD", nr_bytes);    }  if ( offset == 0x84 )  /* address of TM6MD */    {      /*  Fill in first byte of mode */      mode_val0 = *(unsigned8 *)source;      timers->tm6md0 = mode_val0;          if ( ( mode_val0 & 0x26 ) != 0 )	{	  hw_abort(me, "Cannot write to bits 5, 3, and 2 of TM6MD");	}    }    if ( offset == 0x85 || nr_bytes == 2 )    {      /*  Fill in second byte of mode */      if ( nr_bytes == 2 )	{	  mode_val1 = *(unsigned8 *)source+1;	}      else	{	  mode_val1 = *(unsigned8 *)source;	}      timers->tm6md1 = mode_val1;      if ( ( mode_val1 & count_and_load_mask ) == count_and_load_mask )	{	  hw_abort(me, "Cannot load base reg and start counting simultaneously.");	}      if ( ( mode_val1 & bits0to2_mask ) != 0 )	{	  hw_abort(me, "Cannot write to bits 8 to 10 of TM6MD");	}    }  if ( mode_val1 & count_mask )    {      /* - de-schedule any previous event. */      /* - add new event to queue to start counting. */      /* - assert that counter == base reg? */      div_ratio = timers->tm6ca;  /* binary counter for timer 6 */      timers->timer[timer_nr].div_ratio = div_ratio;      if ( NULL != timers->timer[timer_nr].event )	{	  hw_event_queue_deschedule (me, timers->timer[timer_nr].event);	  timers->timer[timer_nr].event = NULL;	}      if ( div_ratio > 0 )	{	  /* Set start time. */	  timers->timer[timer_nr].start = hw_event_queue_time(me);	  timers->timer[timer_nr].event	    = hw_event_queue_schedule(me, div_ratio,				      do_counter6_event,				      (void *)(timer_nr)); 	}    }  else    {      /* Turn off counting */      if ( NULL != timers->timer[timer_nr].event )	{	  hw_event_queue_deschedule (me, timers->timer[timer_nr].event);	  timers->timer[timer_nr].event = NULL;	}    }}static voidwrite_special_timer6_reg (struct hw *me,			  struct mn103tim *timers,			  int timer_nr,			  const void *source,			  unsigned  nr_bytes){  unsigned32 val;  switch (nr_bytes) {  case 1:    {      switch ( timer_nr ) {      case TM6MDA:	timers->tm6mda = *(unsigned8 *)source;	break;          case TM6MDB:	timers->tm6mdb = *(unsigned8 *)source;	break;          case TM6CA:	timers->tm6ca = *(unsigned8 *)source;	break;          case TM6CB:	timers->tm6cb = *(unsigned8 *)source;	break;            default:	break;      }      break;    }      case 2:    if ( timer_nr == TM6CA )      {	timers->tm6ca = *(unsigned16 *)source;      }    else if ( timer_nr == TM6CB )      {	timers->tm6cb = *(unsigned16 *)source;      }    else      {	hw_abort(me, "bad read size for timer 6 mode A/B register");      }    break;  default:    hw_abort(me, "bad read size for timer 6 register");  }      }static unsignedmn103tim_io_write_buffer (struct hw *me,			  const void *source,			  int space,			  unsigned_word base,			  unsigned nr_bytes){  struct mn103tim *timers = hw_data (me);  enum timer_register_types timer_reg;  HW_TRACE ((me, "write to 0x%08lx length %d with 0x%x", (long) base,	     (int) nr_bytes, *(unsigned32 *)source));  timer_reg = decode_addr (me, timers, base);  /* It can be either a mode register, a base register, a binary counter, */  /* or a special timer 6 register.  Check in that order. */  if ( timer_reg <= LAST_MODE_REG )    {      if ( timer_reg == 6 ) 	{	  write_tm6md(me, timers, base, source, nr_bytes);	}      else	{	  write_mode_reg(me, timers, timer_reg-FIRST_MODE_REG,			 source, nr_bytes);	}    }  else if ( timer_reg <= LAST_BASE_REG )    {      write_base_reg(me, timers, timer_reg-FIRST_BASE_REG, source, nr_bytes);    }  else if ( timer_reg <= LAST_COUNTER )    {      hw_abort(me, "cannot write to counter");    }  else if ( timer_reg <= LAST_TIMER_REG )    {      write_special_timer6_reg(me, timers, timer_reg, source, nr_bytes);    }  else    {      hw_abort(me, "invalid reg type");    }  return nr_bytes;}     const struct hw_descriptor dv_mn103tim_descriptor[] = {  { "mn103tim", mn103tim_finish, },  { NULL },};

⌨️ 快捷键说明

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