1 /****************************************************************************** 2 * 3 * (C)Copyright 1998,1999 SysKonnect, 4 * a business unit of Schneider & Koch & Co. Datensysteme GmbH. 5 * 6 * See the file "skfddi.c" for further information. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * The information in this file is provided "AS IS" without warranty. 14 * 15 ******************************************************************************/ 16 17 /* 18 * Timer Driver for FBI board (timer chip 82C54) 19 */ 20 21 /* 22 * Modifications: 23 * 24 * 28-Jun-1994 sw Edit v1.6. 25 * MCA: Added support for the SK-NET FDDI-FM2 adapter. The 26 * following functions have been added(+) or modified(*): 27 * hwt_start(*), hwt_stop(*), hwt_restart(*), hwt_read(*) 28 */ 29 30 #include "h/types.h" 31 #include "h/fddi.h" 32 #include "h/smc.h" 33 34 #ifndef lint 35 static const char ID_sccs[] = "@(#)hwt.c 1.13 97/04/23 (C) SK " ; 36 #endif 37 38 /* 39 * Prototypes of local functions. 40 */ 41 /* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */ 42 /*static void hwt_restart() ; */ 43 44 /************************ 45 * 46 * hwt_start 47 * 48 * Start hardware timer (clock ticks are 16us). 49 * 50 * void hwt_start( 51 * struct s_smc *smc, 52 * u_long time) ; 53 * In 54 * smc - A pointer to the SMT Context structure. 55 * 56 * time - The time in units of 16us to load the timer with. 57 * Out 58 * Nothing. 59 * 60 ************************/ 61 #define HWT_MAX (65000) 62 63 void hwt_start(struct s_smc *smc, u_long time) 64 { 65 u_short cnt ; 66 67 if (time > HWT_MAX) 68 time = HWT_MAX ; 69 70 smc->hw.t_start = time ; 71 smc->hw.t_stop = 0L ; 72 73 cnt = (u_short)time ; 74 /* 75 * if time < 16 us 76 * time = 16 us 77 */ 78 if (!cnt) 79 cnt++ ; 80 81 outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ; /* Load timer value. */ 82 outpw(ADDR(B2_TI_CRTL), TIM_START) ; /* Start timer. */ 83 84 smc->hw.timer_activ = TRUE ; 85 } 86 87 /************************ 88 * 89 * hwt_stop 90 * 91 * Stop hardware timer. 92 * 93 * void hwt_stop( 94 * struct s_smc *smc) ; 95 * In 96 * smc - A pointer to the SMT Context structure. 97 * Out 98 * Nothing. 99 * 100 ************************/ 101 void hwt_stop(struct s_smc *smc) 102 { 103 outpw(ADDR(B2_TI_CRTL), TIM_STOP) ; 104 outpw(ADDR(B2_TI_CRTL), TIM_CL_IRQ) ; 105 106 smc->hw.timer_activ = FALSE ; 107 } 108 109 /************************ 110 * 111 * hwt_init 112 * 113 * Initialize hardware timer. 114 * 115 * void hwt_init( 116 * struct s_smc *smc) ; 117 * In 118 * smc - A pointer to the SMT Context structure. 119 * Out 120 * Nothing. 121 * 122 ************************/ 123 void hwt_init(struct s_smc *smc) 124 { 125 smc->hw.t_start = 0 ; 126 smc->hw.t_stop = 0 ; 127 smc->hw.timer_activ = FALSE ; 128 129 hwt_restart(smc) ; 130 } 131 132 /************************ 133 * 134 * hwt_restart 135 * 136 * Clear timer interrupt. 137 * 138 * void hwt_restart( 139 * struct s_smc *smc) ; 140 * In 141 * smc - A pointer to the SMT Context structure. 142 * Out 143 * Nothing. 144 * 145 ************************/ 146 void hwt_restart(struct s_smc *smc) 147 { 148 hwt_stop(smc) ; 149 } 150 151 /************************ 152 * 153 * hwt_read 154 * 155 * Stop hardware timer and read time elapsed since last start. 156 * 157 * u_long hwt_read(smc) ; 158 * In 159 * smc - A pointer to the SMT Context structure. 160 * Out 161 * The elapsed time since last start in units of 16us. 162 * 163 ************************/ 164 u_long hwt_read(struct s_smc *smc) 165 { 166 u_short tr ; 167 u_long is ; 168 169 if (smc->hw.timer_activ) { 170 hwt_stop(smc) ; 171 tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ; 172 173 is = GET_ISR() ; 174 /* Check if timer expired (or wraparound). */ 175 if ((tr > smc->hw.t_start) || (is & IS_TIMINT)) { 176 hwt_restart(smc) ; 177 smc->hw.t_stop = smc->hw.t_start ; 178 } 179 else 180 smc->hw.t_stop = smc->hw.t_start - tr ; 181 } 182 return smc->hw.t_stop; 183 } 184 185 #ifdef PCI 186 /************************ 187 * 188 * hwt_quick_read 189 * 190 * Stop hardware timer and read timer value and start the timer again. 191 * 192 * u_long hwt_read(smc) ; 193 * In 194 * smc - A pointer to the SMT Context structure. 195 * Out 196 * current timer value in units of 80ns. 197 * 198 ************************/ 199 u_long hwt_quick_read(struct s_smc *smc) 200 { 201 u_long interval ; 202 u_long time ; 203 204 interval = inpd(ADDR(B2_TI_INI)) ; 205 outpw(ADDR(B2_TI_CRTL), TIM_STOP) ; 206 time = inpd(ADDR(B2_TI_VAL)) ; 207 outpd(ADDR(B2_TI_INI),time) ; 208 outpw(ADDR(B2_TI_CRTL), TIM_START) ; 209 outpd(ADDR(B2_TI_INI),interval) ; 210 211 return time; 212 } 213 214 /************************ 215 * 216 * hwt_wait_time(smc,start,duration) 217 * 218 * This function returnes after the amount of time is elapsed 219 * since the start time. 220 * 221 * para start start time 222 * duration time to wait 223 * 224 * NOTE: The function will return immediately, if the timer is not 225 * started 226 ************************/ 227 void hwt_wait_time(struct s_smc *smc, u_long start, long int duration) 228 { 229 long diff ; 230 long interval ; 231 int wrapped ; 232 233 /* 234 * check if timer is running 235 */ 236 if (smc->hw.timer_activ == FALSE || 237 hwt_quick_read(smc) == hwt_quick_read(smc)) { 238 return ; 239 } 240 241 interval = inpd(ADDR(B2_TI_INI)) ; 242 if (interval > duration) { 243 do { 244 diff = (long)(start - hwt_quick_read(smc)) ; 245 if (diff < 0) { 246 diff += interval ; 247 } 248 } while (diff <= duration) ; 249 } 250 else { 251 diff = interval ; 252 wrapped = 0 ; 253 do { 254 if (!wrapped) { 255 if (hwt_quick_read(smc) >= start) { 256 diff += interval ; 257 wrapped = 1 ; 258 } 259 } 260 else { 261 if (hwt_quick_read(smc) < start) { 262 wrapped = 0 ; 263 } 264 } 265 } while (diff <= duration) ; 266 } 267 } 268 #endif 269 270