////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002 Xilinx, Inc.  All rights reserved.
//
// Xilinx, Inc.
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A 
// COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
// ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR 
// STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
// IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE 
// FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.  
// XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO 
// THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO 
// ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE 
// FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY 
// AND FITNESS FOR A PARTICULAR PURPOSE.
// 
// $Id: timer.c,v 1.1.2.2 2003/03/14 22:21:29 mohan Exp $
//
//////////////////////////////////////////////////////////////////////////////
//#include <xtmrctr_l.h>
//#include <xparameters.h>
//#include <mb_interface.h>
//#include <xintc_l.h>
//#include <xuartlite_l.h>

#include <sys/timer.h>
#include <sys/process.h>

//int settimer( int msec, void (*handler)(int), int arg );
int resettimer( int timerid );
int add_list( int node );
int del_list( int timerid );


struct _timer timers[MAX_TIMERS] ;
signed char timers_list[MAX_TIMERS] ;
signed char head = -1 ;
int tlist_count = 0 ;
int system_time = 0 ;

extern struct _queue ready_q[] ;		

extern process_struct ptable[] ;	/* Process Table */
extern signed char flags ;
 
void timer_init()
{
  int i = 0 ;

  for( ; i < MAX_TIMERS; i++ ){
    timers[i].timer_count = -1 ;
    timers_list[i] = -1 ;
  }
}


unsigned int gettime()
{
	return system_time ;
}

void settime( unsigned int clk )
{
	system_time = clk ;
}

int sleep( int msec )
{
	int i = 0 ; 

	if( msec <= 0 ) return -1 ;
	while( (i < MAX_TIMERS) && (timers[i].timer_count != -1) ){
		i++ ;
	}
	if( i == MAX_TIMERS) return -1 ;
	timers[i].timer_count = msec ;
	timers[i].pid = sys_get_currentPID() ;
	ptable[timers[i].pid].state = PROC_WAITING ;
	flags |= PROCESS_BLOCK ;
	//timers[i].timer_func = handler ;
	//timers[i].arg = arg ;
	add_list(i) ;
}

/*
int settimer( int msec, void (*handler)(int), int arg )
{
  int i = 0, start_timer = 0 ;

  if( msec <= 0 ) return -1 ;
  while( (i < MAX_TIMERS) && (timers[i].timer_count != -1) ){
    i++ ;
  }
  if( i == MAX_TIMERS) return -1 ;
  timers[i].timer_count = msec ;
  timers[i].timer_func = handler ;
  timers[i].arg = arg ;
  start_timer = add_list(i) ;

  if( start_timer ) {
    print("Starting timer \r\n") ;

  }
  return i ;
}
*/

int resettimer( int timerid )
{
	int pid ;

	if( timers[timerid].timer_count == -1 ){
		return -1 ;
	}
	del_list( timerid ) ;
	timers[timerid].timer_count = -1 ;
	pid = timers[timerid].pid ;
	#if SCHED_TYPE == SCHED_RR
		enq( &ready_q[0], &pid, 0 ) ;
	#else /* SCHED_TYPE == SCHED_PRIO */
		enq( &ready_q[ptable[pid].priority], &pid, 0 ) ;
	#endif
	ptable[pid].state = PROC_READY ;
	return 0 ;
}


int add_list( int node )
{
	signed char prev, next ;

	if( head == -1 ){
		head = node ;
		tlist_count++ ;
		return 0 ;
	}
	if( timers[head].timer_count > timers[node].timer_count ){
		timers_list[node] = head ;
		head = node ;
		tlist_count++ ;
		return 0 ;
	}
	prev = head ;
	next = timers_list[head] ;
	while( (next != -1) &&
	       (timers[next].timer_count <= timers[node].timer_count) ){
		prev = next ;
		next = timers_list[prev] ;
	}
	timers_list[prev] = node ;
	timers_list[node] = next ;
	tlist_count++ ;
	return 0 ;
}

int del_list( int timerid )
{
	int temp ;
	if( head == timerid ) {
		if( timers_list[head] == -1 ) {
			head = -1 ;
			tlist_count-- ;
			return 0 ;
		} else {
			temp = head ;
			head = timers_list[temp] ;
			timers_list[temp] = -1 ;
			tlist_count-- ;
			return 0 ;
		}
	}
	temp = head ;
	while( (temp != -1) && (timers_list[temp] != timerid) ){
		temp = timers_list[temp] ;
	}
	timers_list[temp] = timers_list[timerid] ;
	timers_list[timerid] = -1 ;
	tlist_count-- ;
	return 0 ;
}

void timer_handler( void )
{
	int i ;
	int temp = head ;

	system_time++ ;
	if( tlist_count == 0 )	/* If Timer List is empty, Return */
		return ;
	//XUartLite_SendByte(XPAR_MYJTAGUART_BASEADDR, 'I') ;
	while( temp != -1 ) {
		timers[temp].timer_count-- ;
		if( timers[temp].timer_count == 0 ){
			//timers[temp].timer_func( timers[temp].arg ) ;
			resettimer( temp ) ;
			//XUartLite_SendByte(XPAR_MYJTAGUART_BASEADDR, 'R') ;
			temp = head ;
		} else {
			temp = timers_list[temp] ;
			break ;
		}
	}
	while( temp != -1 ){
		timers[temp].timer_count-- ;
		temp = timers_list[temp] ;
	}
}

