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 /* 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_start 39 * 40 * Start hardware timer (clock ticks are 16us). 41 * 42 * void hwt_start( 43 * struct s_smc *smc, 44 * u_long time) ; 45 * In 46 * smc - A pointer to the SMT Context structure. 47 * 48 * time - The time in units of 16us to load the timer with. 49 * Out 50 * Nothing. 51 * 52 ************************/ 53 #define HWT_MAX (65000) 54 55 void 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 us 68 * time = 16 us 69 */ 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_stop 82 * 83 * Stop hardware timer. 84 * 85 * void hwt_stop( 86 * struct s_smc *smc) ; 87 * In 88 * smc - A pointer to the SMT Context structure. 89 * Out 90 * Nothing. 91 * 92 ************************/ 93 void 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_init 104 * 105 * Initialize hardware timer. 106 * 107 * void hwt_init( 108 * struct s_smc *smc) ; 109 * In 110 * smc - A pointer to the SMT Context structure. 111 * Out 112 * Nothing. 113 * 114 ************************/ 115 void 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_restart 127 * 128 * Clear timer interrupt. 129 * 130 * void hwt_restart( 131 * struct s_smc *smc) ; 132 * In 133 * smc - A pointer to the SMT Context structure. 134 * Out 135 * Nothing. 136 * 137 ************************/ 138 void hwt_restart(struct s_smc *smc) 139 { 140 hwt_stop(smc) ; 141 } 142 143 /************************ 144 * 145 * hwt_read 146 * 147 * Stop hardware timer and read time elapsed since last start. 148 * 149 * u_long hwt_read(smc) ; 150 * In 151 * smc - A pointer to the SMT Context structure. 152 * Out 153 * The elapsed time since last start in units of 16us. 154 * 155 ************************/ 156 u_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 else 172 smc->hw.t_stop = smc->hw.t_start - tr ; 173 } 174 return smc->hw.t_stop; 175 } 176 177 #ifdef PCI 178 /************************ 179 * 180 * hwt_quick_read 181 * 182 * Stop hardware timer and read timer value and start the timer again. 183 * 184 * u_long hwt_read(smc) ; 185 * In 186 * smc - A pointer to the SMT Context structure. 187 * Out 188 * current timer value in units of 80ns. 189 * 190 ************************/ 191 u_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 elapsed 211 * since the start time. 212 * 213 * para start start time 214 * duration time to wait 215 * 216 * NOTE: The function will return immediately, if the timer is not 217 * started 218 ************************/ 219 void 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 running 227 */ 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 #endif 261 262