linux/drivers/net/fddi/skfp/hwt.c
<<
>>
Prefs
   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
  35static 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
  63void 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 ************************/
 101void 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 ************************/
 123void 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 ************************/
 146void 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 ************************/
 164u_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 ************************/
 199u_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 ************************/
 227void 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