262 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/******************************************************************************3 *4 * (C)Copyright 1998,1999 SysKonnect,5 * a business unit of Schneider & Koch & Co. Datensysteme GmbH.6 *7 * See the file "skfddi.c" for further information.8 *9 * The information in this file is provided "AS IS" without warranty.10 *11 ******************************************************************************/12 13/*14 * Timer Driver for FBI board (timer chip 82C54)15 */16 17/*18 * Modifications:19 *20 * 28-Jun-1994 sw Edit v1.6.21 * MCA: Added support for the SK-NET FDDI-FM2 adapter. The22 * following functions have been added(+) or modified(*):23 * hwt_start(*), hwt_stop(*), hwt_restart(*), hwt_read(*)24 */25 26#include "h/types.h"27#include "h/fddi.h"28#include "h/smc.h"29 30/*31 * Prototypes of local functions.32 */33/* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */34/*static void hwt_restart() ; */35 36/************************37 *38 * hwt_start39 *40 * Start hardware timer (clock ticks are 16us).41 *42 * void hwt_start(43 * struct s_smc *smc,44 * u_long time) ;45 * In46 * smc - A pointer to the SMT Context structure.47 *48 * time - The time in units of 16us to load the timer with.49 * Out50 * Nothing.51 *52 ************************/53#define HWT_MAX (65000)54 55void hwt_start(struct s_smc *smc, u_long time)56{57 u_short cnt ;58 59 if (time > HWT_MAX)60 time = HWT_MAX ;61 62 smc->hw.t_start = time ;63 smc->hw.t_stop = 0L ;64 65 cnt = (u_short)time ;66 /*67 * if time < 16 us68 * time = 16 us69 */70 if (!cnt)71 cnt++ ;72 73 outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ; /* Load timer value. */74 outpw(ADDR(B2_TI_CRTL), TIM_START) ; /* Start timer. */75 76 smc->hw.timer_activ = TRUE ;77}78 79/************************80 *81 * hwt_stop82 *83 * Stop hardware timer.84 *85 * void hwt_stop(86 * struct s_smc *smc) ;87 * In88 * smc - A pointer to the SMT Context structure.89 * Out90 * Nothing.91 *92 ************************/93void hwt_stop(struct s_smc *smc)94{95 outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;96 outpw(ADDR(B2_TI_CRTL), TIM_CL_IRQ) ;97 98 smc->hw.timer_activ = FALSE ;99}100 101/************************102 *103 * hwt_init104 *105 * Initialize hardware timer.106 *107 * void hwt_init(108 * struct s_smc *smc) ;109 * In110 * smc - A pointer to the SMT Context structure.111 * Out112 * Nothing.113 *114 ************************/115void hwt_init(struct s_smc *smc)116{117 smc->hw.t_start = 0 ;118 smc->hw.t_stop = 0 ;119 smc->hw.timer_activ = FALSE ;120 121 hwt_restart(smc) ;122}123 124/************************125 *126 * hwt_restart127 *128 * Clear timer interrupt.129 *130 * void hwt_restart(131 * struct s_smc *smc) ;132 * In133 * smc - A pointer to the SMT Context structure.134 * Out135 * Nothing.136 *137 ************************/138void hwt_restart(struct s_smc *smc)139{140 hwt_stop(smc) ;141}142 143/************************144 *145 * hwt_read146 *147 * Stop hardware timer and read time elapsed since last start.148 *149 * u_long hwt_read(smc) ;150 * In151 * smc - A pointer to the SMT Context structure.152 * Out153 * The elapsed time since last start in units of 16us.154 *155 ************************/156u_long hwt_read(struct s_smc *smc)157{158 u_short tr ;159 u_long is ;160 161 if (smc->hw.timer_activ) {162 hwt_stop(smc) ;163 tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ;164 165 is = GET_ISR() ;166 /* Check if timer expired (or wraparound). */167 if ((tr > smc->hw.t_start) || (is & IS_TIMINT)) {168 hwt_restart(smc) ;169 smc->hw.t_stop = smc->hw.t_start ;170 }171 else172 smc->hw.t_stop = smc->hw.t_start - tr ;173 }174 return smc->hw.t_stop;175}176 177#ifdef PCI178/************************179 *180 * hwt_quick_read181 *182 * Stop hardware timer and read timer value and start the timer again.183 *184 * u_long hwt_read(smc) ;185 * In186 * smc - A pointer to the SMT Context structure.187 * Out188 * current timer value in units of 80ns.189 *190 ************************/191u_long hwt_quick_read(struct s_smc *smc)192{193 u_long interval ;194 u_long time ;195 196 interval = inpd(ADDR(B2_TI_INI)) ;197 outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;198 time = inpd(ADDR(B2_TI_VAL)) ;199 outpd(ADDR(B2_TI_INI),time) ;200 outpw(ADDR(B2_TI_CRTL), TIM_START) ;201 outpd(ADDR(B2_TI_INI),interval) ;202 203 return time;204}205 206/************************207 *208 * hwt_wait_time(smc,start,duration)209 *210 * This function returnes after the amount of time is elapsed211 * since the start time.212 * 213 * para start start time214 * duration time to wait215 *216 * NOTE: The function will return immediately, if the timer is not217 * started218 ************************/219void hwt_wait_time(struct s_smc *smc, u_long start, long int duration)220{221 long diff ;222 long interval ;223 int wrapped ;224 225 /*226 * check if timer is running227 */228 if (smc->hw.timer_activ == FALSE ||229 hwt_quick_read(smc) == hwt_quick_read(smc)) {230 return ;231 }232 233 interval = inpd(ADDR(B2_TI_INI)) ;234 if (interval > duration) {235 do {236 diff = (long)(start - hwt_quick_read(smc)) ;237 if (diff < 0) {238 diff += interval ;239 }240 } while (diff <= duration) ;241 }242 else {243 diff = interval ;244 wrapped = 0 ;245 do {246 if (!wrapped) {247 if (hwt_quick_read(smc) >= start) {248 diff += interval ;249 wrapped = 1 ;250 }251 }252 else {253 if (hwt_quick_read(smc) < start) {254 wrapped = 0 ;255 }256 }257 } while (diff <= duration) ;258 }259}260#endif261 262