2005-04-17 02:20:36 +04:00
/******************************************************************************
*
* ( C ) Copyright 1998 , 1999 SysKonnect ,
* a business unit of Schneider & Koch & Co . Datensysteme GmbH .
*
* See the file " skfddi.c " for further information .
*
* 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 .
*
* The information in this file is provided " AS IS " without warranty .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Timer Driver for FBI board ( timer chip 82 C54 )
*/
/*
* Modifications :
*
* 28 - Jun - 1994 sw Edit v1 .6 .
* MCA : Added support for the SK - NET FDDI - FM2 adapter . The
* following functions have been added ( + ) or modified ( * ) :
* hwt_start ( * ) , hwt_stop ( * ) , hwt_restart ( * ) , hwt_read ( * )
*/
# include "h/types.h"
# include "h/fddi.h"
# include "h/smc.h"
# ifndef lint
static const char ID_sccs [ ] = " @(#)hwt.c 1.13 97/04/23 (C) SK " ;
# endif
/*
* Prototypes of local functions .
*/
/* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */
/*static void hwt_restart() ; */
/************************
*
* hwt_start
*
* Start hardware timer ( clock ticks are 16u s ) .
*
* void hwt_start (
* struct s_smc * smc ,
* u_long time ) ;
* In
* smc - A pointer to the SMT Context structure .
*
* time - The time in units of 16u s to load the timer with .
* Out
* Nothing .
*
* * * * * * * * * * * * * * * * * * * * * * * */
# define HWT_MAX (65000)
void hwt_start ( struct s_smc * smc , u_long time )
{
u_short cnt ;
if ( time > HWT_MAX )
time = HWT_MAX ;
smc - > hw . t_start = time ;
smc - > hw . t_stop = 0L ;
cnt = ( u_short ) time ;
/*
* if time < 16 us
* time = 16 us
*/
if ( ! cnt )
cnt + + ;
2007-07-24 09:30:36 +04:00
2005-04-17 02:20:36 +04:00
outpd ( ADDR ( B2_TI_INI ) , ( u_long ) cnt * 200 ) ; /* Load timer value. */
outpw ( ADDR ( B2_TI_CRTL ) , TIM_START ) ; /* Start timer. */
2007-07-24 09:30:36 +04:00
2005-04-17 02:20:36 +04:00
smc - > hw . timer_activ = TRUE ;
}
/************************
*
* hwt_stop
*
* Stop hardware timer .
*
* void hwt_stop (
* struct s_smc * smc ) ;
* In
* smc - A pointer to the SMT Context structure .
* Out
* Nothing .
*
* * * * * * * * * * * * * * * * * * * * * * * */
void hwt_stop ( struct s_smc * smc )
{
outpw ( ADDR ( B2_TI_CRTL ) , TIM_STOP ) ;
outpw ( ADDR ( B2_TI_CRTL ) , TIM_CL_IRQ ) ;
smc - > hw . timer_activ = FALSE ;
}
/************************
*
* hwt_init
*
* Initialize hardware timer .
*
* void hwt_init (
* struct s_smc * smc ) ;
* In
* smc - A pointer to the SMT Context structure .
* Out
* Nothing .
*
* * * * * * * * * * * * * * * * * * * * * * * */
void hwt_init ( struct s_smc * smc )
{
smc - > hw . t_start = 0 ;
smc - > hw . t_stop = 0 ;
smc - > hw . timer_activ = FALSE ;
hwt_restart ( smc ) ;
}
/************************
*
* hwt_restart
*
* Clear timer interrupt .
*
* void hwt_restart (
* struct s_smc * smc ) ;
* In
* smc - A pointer to the SMT Context structure .
* Out
* Nothing .
*
* * * * * * * * * * * * * * * * * * * * * * * */
void hwt_restart ( struct s_smc * smc )
{
hwt_stop ( smc ) ;
}
/************************
*
* hwt_read
*
* Stop hardware timer and read time elapsed since last start .
*
* u_long hwt_read ( smc ) ;
* In
* smc - A pointer to the SMT Context structure .
* Out
* The elapsed time since last start in units of 16u s .
*
* * * * * * * * * * * * * * * * * * * * * * * */
u_long hwt_read ( struct s_smc * smc )
{
u_short tr ;
u_long is ;
if ( smc - > hw . timer_activ ) {
hwt_stop ( smc ) ;
tr = ( u_short ) ( ( inpd ( ADDR ( B2_TI_VAL ) ) / 200 ) & 0xffff ) ;
2007-07-24 09:30:36 +04:00
2005-04-17 02:20:36 +04:00
is = GET_ISR ( ) ;
/* Check if timer expired (or wraparound). */
if ( ( tr > smc - > hw . t_start ) | | ( is & IS_TIMINT ) ) {
hwt_restart ( smc ) ;
smc - > hw . t_stop = smc - > hw . t_start ;
}
else
smc - > hw . t_stop = smc - > hw . t_start - tr ;
}
2010-09-23 09:40:09 +04:00
return smc - > hw . t_stop ;
2005-04-17 02:20:36 +04:00
}
# ifdef PCI
/************************
*
* hwt_quick_read
*
* Stop hardware timer and read timer value and start the timer again .
*
* u_long hwt_read ( smc ) ;
* In
* smc - A pointer to the SMT Context structure .
* Out
* current timer value in units of 80 ns .
*
* * * * * * * * * * * * * * * * * * * * * * * */
u_long hwt_quick_read ( struct s_smc * smc )
{
u_long interval ;
u_long time ;
interval = inpd ( ADDR ( B2_TI_INI ) ) ;
outpw ( ADDR ( B2_TI_CRTL ) , TIM_STOP ) ;
time = inpd ( ADDR ( B2_TI_VAL ) ) ;
outpd ( ADDR ( B2_TI_INI ) , time ) ;
outpw ( ADDR ( B2_TI_CRTL ) , TIM_START ) ;
outpd ( ADDR ( B2_TI_INI ) , interval ) ;
2010-09-23 09:40:09 +04:00
return time ;
2005-04-17 02:20:36 +04:00
}
/************************
*
* hwt_wait_time ( smc , start , duration )
*
* This function returnes after the amount of time is elapsed
* since the start time .
*
* para start start time
* duration time to wait
*
2010-08-06 23:11:15 +04:00
* NOTE : The function will return immediately , if the timer is not
2005-04-17 02:20:36 +04:00
* started
* * * * * * * * * * * * * * * * * * * * * * * */
void hwt_wait_time ( struct s_smc * smc , u_long start , long int duration )
{
long diff ;
long interval ;
int wrapped ;
/*
* check if timer is running
*/
if ( smc - > hw . timer_activ = = FALSE | |
hwt_quick_read ( smc ) = = hwt_quick_read ( smc ) ) {
return ;
}
interval = inpd ( ADDR ( B2_TI_INI ) ) ;
if ( interval > duration ) {
do {
diff = ( long ) ( start - hwt_quick_read ( smc ) ) ;
if ( diff < 0 ) {
diff + = interval ;
}
} while ( diff < = duration ) ;
}
else {
diff = interval ;
wrapped = 0 ;
do {
if ( ! wrapped ) {
if ( hwt_quick_read ( smc ) > = start ) {
diff + = interval ;
wrapped = 1 ;
}
}
else {
if ( hwt_quick_read ( smc ) < start ) {
wrapped = 0 ;
}
}
} while ( diff < = duration ) ;
}
}
# endif