/*
    TMClock.h, Copyright  (c) by Lukas Ruf, lr@lpr.ch,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public Licence.
 
    A full copy of the GNU GPL is provided in the file COPYING found in the 
    development root of Topsy.
*/
/*
	
	File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Threads/ia32/TMClock.h,v $
 	Author(s):             Lukas Ruf, lr@lpr.ch
 	Affiliation:           ETH Zuerich, TIK
 	Version:               $Revision: 3040 $
 	Creation Date:         
 	Last Date of Change:   $Date: 2007-06-17 21:55:44 +0200 (Son, 17 Jun 2007) $      by: $Author: sryffel $
	
	
	$Log: TMClock.h,v $
	Revision 1.4  2000/11/15 10:13:34  ruf
	ia32Debug and Repository Reorganisation
	
	Revision 1.3  1999/12/13 21:48:34  ruf
	GNU General Public Licence Update
	
	Revision 1.2  1999/06/06 20:55:16  jeker
	putting everything together for Topsy 2.0
	
	Revision 1.1  1999/05/13 17:05:48  jeker
	Initial revision
 
*/
#ifndef __TMCLOCK_H_
#define __TMCLOCK_H_

#include "tm-include.h"
#include "Configuration.h"
 
#ifdef APIC
extern volatile unsigned long fsb_speed;
#define tFIXRATE    (unsigned long)(fsb_speed)
#else
/*
/////////////////////////////////////////
// Setting divisor
// Normal Frequency:  1.193182MHz
// Frequency  Cycle     Divisor
//    100 ->  10ms  ->  11931 = 0x2E9B
//     50 ->  20ms  ->  23864 = 0x5D38
//     20 ->  50ms  ->  59659 = 0xE90B  <- current TIMESLICE
/////////////////////////////////////////
*/
#define tFIXRATE    (unsigned long)(1193182)
#endif

#if TIMESLICE > 1000  
// timeslice longer than one second
#define tPERIOD                   TIMESLICE / 1000
#define TO_SECONDS(timerCalled)   (timerCalled * tPERIOD)
#define UPDATE_COND(timerCalled)  (TRUE)                  /* at least once a second */
#define SPIN_COND(timerCalled)    (TRUE)                  /* at least once a second */

#else
// timeslice shorter than one second
#define tFREQUENCY                (unsigned long)(1000 / TIMESLICE)
#define tDIVISOR                  (unsigned long)(tFIXRATE / tFREQUENCY)
#define TO_SECONDS(timerCalled)   (timerCalled / tFREQUENCY)
#define UPDATE_COND(timerCalled)  ((timerCalled % tFREQUENCY) == 0)
#define SPIN_COND(timerCalled)    ((tFREQUENCY < 4 ) || (_TimerCalled % (tFREQUENCY >> 2)) == 0)
#endif

#define tCYCLEms    TIMESLICE

/* 82C54 Programmable Timer */
#define MODE2_COUNTER0  0x34     /* specific control word */
#define MODE2_COUNTER1  0x74     /* specific control word */
#define MODE2_COUNTER2  0xb4     /* specific control word */

#define MODE5_COUNTER0  0x3a     /* specific control word */
#define MODE5_COUNTER1  0x7a     /* specific control word */
#define MODE5_COUNTER2  0xba     /* specific control word */

/* The 2 timers of the 82C54 programmable interval timer */
typedef enum { CLOCK0, CLOCK1 } ClockId;

/* Used modes for the 82C54, currently a single mode */
typedef enum { RATEGENERATOR } ClockMode;

/* Configuration of the 82C54 (each counter separately) */
Error setClockValue( ClockId cId, int period, ClockMode cMode);

void tmResetClockInterrupt( ClockId cId);

void TimerInit();
void _TimerISR();
unsigned long TimerSeconds();
unsigned long TimerCalled();

/* defined in TMClockAsm.S: */
void __timerSet(unsigned short pDIVISOR,
                unsigned char  pCtrlWord,
                unsigned char  pTimerChannel);
unsigned char __readRTC(unsigned char pBYTEtoREAD);
void __writeRTC(unsigned char pBYTEtoWRITE, unsigned char pVALUEtoWRITE);

/* RTC routines  * Seconds difference from January 1st 1998, 00:00, UTC */
unsigned long tmRTClockGetSeconds();

void tmRTClockSetSeconds(unsigned long seconds, unsigned long microSeconds);
unsigned int roundToMHz(unsigned int cpuFreq);

#endif

