262 lines
5.0 KiB
C
262 lines
5.0 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/******************************************************************************
|
|
*
|
|
* (C)Copyright 1998,1999 SysKonnect,
|
|
* a business unit of Schneider & Koch & Co. Datensysteme GmbH.
|
|
*
|
|
* See the file "skfddi.c" for further information.
|
|
*
|
|
* The information in this file is provided "AS IS" without warranty.
|
|
*
|
|
******************************************************************************/
|
|
|
|
/*
|
|
* Timer Driver for FBI board (timer chip 82C54)
|
|
*/
|
|
|
|
/*
|
|
* 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"
|
|
|
|
/*
|
|
* 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 16us).
|
|
*
|
|
* 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 16us 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++ ;
|
|
|
|
outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ; /* Load timer value. */
|
|
outpw(ADDR(B2_TI_CRTL), TIM_START) ; /* Start timer. */
|
|
|
|
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 16us.
|
|
*
|
|
************************/
|
|
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) ;
|
|
|
|
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 ;
|
|
}
|
|
return smc->hw.t_stop;
|
|
}
|
|
|
|
#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 80ns.
|
|
*
|
|
************************/
|
|
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) ;
|
|
|
|
return time;
|
|
}
|
|
|
|
/************************
|
|
*
|
|
* 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
|
|
*
|
|
* NOTE: The function will return immediately, if the timer is not
|
|
* 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
|
|
|