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