1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /****************************************************************************** 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. The 22 * 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 #ifndef lint 31 static const char ID_sccs[] = "@(#)hwt.c 1.13 97/04/23 (C) SK " ; 32 #endif 33 34 /* 35 * Prototypes of local functions. 36 */ 37 /* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */ 38 /*static void hwt_restart() ; */ 39 40 /************************ 41 * 42 * hwt_start 43 * 44 * Start hardware timer (clock ticks are 16us). 45 * 46 * void hwt_start( 47 * struct s_smc *smc, 48 * u_long time) ; 49 * In 50 * smc - A pointer to the SMT Context structure. 51 * 52 * time - The time in units of 16us to load the timer with. 53 * Out 54 * Nothing. 55 * 56 ************************/ 57 #define HWT_MAX (65000) 58 59 void hwt_start(struct s_smc *smc, u_long time) 60 { 61 u_short cnt ; 62 63 if (time > HWT_MAX) 64 time = HWT_MAX ; 65 66 smc->hw.t_start = time ; 67 smc->hw.t_stop = 0L ; 68 69 cnt = (u_short)time ; 70 /* 71 * if time < 16 us 72 * time = 16 us 73 */ 74 if (!cnt) 75 cnt++ ; 76 77 outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ; /* Load timer value. */ 78 outpw(ADDR(B2_TI_CRTL), TIM_START) ; /* Start timer. */ 79 80 smc->hw.timer_activ = TRUE ; 81 } 82 83 /************************ 84 * 85 * hwt_stop 86 * 87 * Stop hardware timer. 88 * 89 * void hwt_stop( 90 * struct s_smc *smc) ; 91 * In 92 * smc - A pointer to the SMT Context structure. 93 * Out 94 * Nothing. 95 * 96 ************************/ 97 void hwt_stop(struct s_smc *smc) 98 { 99 outpw(ADDR(B2_TI_CRTL), TIM_STOP) ; 100 outpw(ADDR(B2_TI_CRTL), TIM_CL_IRQ) ; 101 102 smc->hw.timer_activ = FALSE ; 103 } 104 105 /************************ 106 * 107 * hwt_init 108 * 109 * Initialize hardware timer. 110 * 111 * void hwt_init( 112 * struct s_smc *smc) ; 113 * In 114 * smc - A pointer to the SMT Context structure. 115 * Out 116 * Nothing. 117 * 118 ************************/ 119 void hwt_init(struct s_smc *smc) 120 { 121 smc->hw.t_start = 0 ; 122 smc->hw.t_stop = 0 ; 123 smc->hw.timer_activ = FALSE ; 124 125 hwt_restart(smc) ; 126 } 127 128 /************************ 129 * 130 * hwt_restart 131 * 132 * Clear timer interrupt. 133 * 134 * void hwt_restart( 135 * struct s_smc *smc) ; 136 * In 137 * smc - A pointer to the SMT Context structure. 138 * Out 139 * Nothing. 140 * 141 ************************/ 142 void hwt_restart(struct s_smc *smc) 143 { 144 hwt_stop(smc) ; 145 } 146 147 /************************ 148 * 149 * hwt_read 150 * 151 * Stop hardware timer and read time elapsed since last start. 152 * 153 * u_long hwt_read(smc) ; 154 * In 155 * smc - A pointer to the SMT Context structure. 156 * Out 157 * The elapsed time since last start in units of 16us. 158 * 159 ************************/ 160 u_long hwt_read(struct s_smc *smc) 161 { 162 u_short tr ; 163 u_long is ; 164 165 if (smc->hw.timer_activ) { 166 hwt_stop(smc) ; 167 tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ; 168 169 is = GET_ISR() ; 170 /* Check if timer expired (or wraparound). */ 171 if ((tr > smc->hw.t_start) || (is & IS_TIMINT)) { 172 hwt_restart(smc) ; 173 smc->hw.t_stop = smc->hw.t_start ; 174 } 175 else 176 smc->hw.t_stop = smc->hw.t_start - tr ; 177 } 178 return smc->hw.t_stop; 179 } 180 181 #ifdef PCI 182 /************************ 183 * 184 * hwt_quick_read 185 * 186 * Stop hardware timer and read timer value and start the timer again. 187 * 188 * u_long hwt_read(smc) ; 189 * In 190 * smc - A pointer to the SMT Context structure. 191 * Out 192 * current timer value in units of 80ns. 193 * 194 ************************/ 195 u_long hwt_quick_read(struct s_smc *smc) 196 { 197 u_long interval ; 198 u_long time ; 199 200 interval = inpd(ADDR(B2_TI_INI)) ; 201 outpw(ADDR(B2_TI_CRTL), TIM_STOP) ; 202 time = inpd(ADDR(B2_TI_VAL)) ; 203 outpd(ADDR(B2_TI_INI),time) ; 204 outpw(ADDR(B2_TI_CRTL), TIM_START) ; 205 outpd(ADDR(B2_TI_INI),interval) ; 206 207 return time; 208 } 209 210 /************************ 211 * 212 * hwt_wait_time(smc,start,duration) 213 * 214 * This function returnes after the amount of time is elapsed 215 * since the start time. 216 * 217 * para start start time 218 * duration time to wait 219 * 220 * NOTE: The function will return immediately, if the timer is not 221 * started 222 ************************/ 223 void hwt_wait_time(struct s_smc *smc, u_long start, long int duration) 224 { 225 long diff ; 226 long interval ; 227 int wrapped ; 228 229 /* 230 * check if timer is running 231 */ 232 if (smc->hw.timer_activ == FALSE || 233 hwt_quick_read(smc) == hwt_quick_read(smc)) { 234 return ; 235 } 236 237 interval = inpd(ADDR(B2_TI_INI)) ; 238 if (interval > duration) { 239 do { 240 diff = (long)(start - hwt_quick_read(smc)) ; 241 if (diff < 0) { 242 diff += interval ; 243 } 244 } while (diff <= duration) ; 245 } 246 else { 247 diff = interval ; 248 wrapped = 0 ; 249 do { 250 if (!wrapped) { 251 if (hwt_quick_read(smc) >= start) { 252 diff += interval ; 253 wrapped = 1 ; 254 } 255 } 256 else { 257 if (hwt_quick_read(smc) < start) { 258 wrapped = 0 ; 259 } 260 } 261 } while (diff <= duration) ; 262 } 263 } 264 #endif 265 266