Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / net / fddi / skfp / hwt.c
diff --git a/kernel/drivers/net/fddi/skfp/hwt.c b/kernel/drivers/net/fddi/skfp/hwt.c
new file mode 100644 (file)
index 0000000..c0798fd
--- /dev/null
@@ -0,0 +1,269 @@
+/******************************************************************************
+ *
+ *     (C)Copyright 1998,1999 SysKonnect,
+ *     a business unit of Schneider & Koch & Co. Datensysteme GmbH.
+ *
+ *     See the file "skfddi.c" for further information.
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+
+/*
+ * Timer Driver for FBI board (timer chip 82C54)
+ */
+
+/*
+ * Modifications:
+ *
+ *     28-Jun-1994 sw  Edit v1.6.
+ *                     MCA: Added support for the SK-NET FDDI-FM2 adapter. The
+ *                      following functions have been added(+) or modified(*):
+ *                      hwt_start(*), hwt_stop(*), hwt_restart(*), hwt_read(*)
+ */
+
+#include "h/types.h"
+#include "h/fddi.h"
+#include "h/smc.h"
+
+#ifndef        lint
+static const char ID_sccs[] = "@(#)hwt.c       1.13 97/04/23 (C) SK " ;
+#endif
+
+/*
+ * Prototypes of local functions.
+ */
+/* 28-Jun-1994 sw - Note: hwt_restart() is also used in module 'drvfbi.c'. */
+/*static void hwt_restart() ; */
+
+/************************
+ *
+ *     hwt_start
+ *
+ *     Start hardware timer (clock ticks are 16us).
+ *
+ *     void hwt_start(
+ *             struct s_smc *smc,
+ *             u_long time) ;
+ * In
+ *     smc - A pointer to the SMT Context structure.
+ *
+ *     time - The time in units of 16us to load the timer with.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+#define        HWT_MAX (65000)
+
+void hwt_start(struct s_smc *smc, u_long time)
+{
+       u_short cnt ;
+
+       if (time > HWT_MAX)
+               time = HWT_MAX ;
+
+       smc->hw.t_start = time ;
+       smc->hw.t_stop = 0L ;
+
+       cnt = (u_short)time ;
+       /*
+        * if time < 16 us
+        *      time = 16 us
+        */
+       if (!cnt)
+               cnt++ ;
+
+       outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ;    /* Load timer value. */
+       outpw(ADDR(B2_TI_CRTL), TIM_START) ;            /* Start timer. */
+
+       smc->hw.timer_activ = TRUE ;
+}
+
+/************************
+ *
+ *     hwt_stop
+ *
+ *     Stop hardware timer.
+ *
+ *     void hwt_stop(
+ *             struct s_smc *smc) ;
+ * In
+ *     smc - A pointer to the SMT Context structure.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void hwt_stop(struct s_smc *smc)
+{
+       outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;
+       outpw(ADDR(B2_TI_CRTL), TIM_CL_IRQ) ;
+
+       smc->hw.timer_activ = FALSE ;
+}
+
+/************************
+ *
+ *     hwt_init
+ *
+ *     Initialize hardware timer.
+ *
+ *     void hwt_init(
+ *             struct s_smc *smc) ;
+ * In
+ *     smc - A pointer to the SMT Context structure.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void hwt_init(struct s_smc *smc)
+{
+       smc->hw.t_start = 0 ;
+       smc->hw.t_stop  = 0 ;
+       smc->hw.timer_activ = FALSE ;
+
+       hwt_restart(smc) ;
+}
+
+/************************
+ *
+ *     hwt_restart
+ *
+ *     Clear timer interrupt.
+ *
+ *     void hwt_restart(
+ *             struct s_smc *smc) ;
+ * In
+ *     smc - A pointer to the SMT Context structure.
+ * Out
+ *     Nothing.
+ *
+ ************************/
+void hwt_restart(struct s_smc *smc)
+{
+       hwt_stop(smc) ;
+}
+
+/************************
+ *
+ *     hwt_read
+ *
+ *     Stop hardware timer and read time elapsed since last start.
+ *
+ *     u_long hwt_read(smc) ;
+ * In
+ *     smc - A pointer to the SMT Context structure.
+ * Out
+ *     The elapsed time since last start in units of 16us.
+ *
+ ************************/
+u_long hwt_read(struct s_smc *smc)
+{
+       u_short tr ;
+       u_long  is ;
+
+       if (smc->hw.timer_activ) {
+               hwt_stop(smc) ;
+               tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ;
+
+               is = GET_ISR() ;
+               /* Check if timer expired (or wraparound). */
+               if ((tr > smc->hw.t_start) || (is & IS_TIMINT)) {
+                       hwt_restart(smc) ;
+                       smc->hw.t_stop = smc->hw.t_start ;
+               }
+               else
+                       smc->hw.t_stop = smc->hw.t_start - tr ;
+       }
+       return smc->hw.t_stop;
+}
+
+#ifdef PCI
+/************************
+ *
+ *     hwt_quick_read
+ *
+ *     Stop hardware timer and read timer value and start the timer again.
+ *
+ *     u_long hwt_read(smc) ;
+ * In
+ *     smc - A pointer to the SMT Context structure.
+ * Out
+ *     current timer value in units of 80ns.
+ *
+ ************************/
+u_long hwt_quick_read(struct s_smc *smc)
+{
+       u_long interval ;
+       u_long time ;
+
+       interval = inpd(ADDR(B2_TI_INI)) ;
+       outpw(ADDR(B2_TI_CRTL), TIM_STOP) ;
+       time = inpd(ADDR(B2_TI_VAL)) ;
+       outpd(ADDR(B2_TI_INI),time) ;
+       outpw(ADDR(B2_TI_CRTL), TIM_START) ;
+       outpd(ADDR(B2_TI_INI),interval) ;
+
+       return time;
+}
+
+/************************
+ *
+ *     hwt_wait_time(smc,start,duration)
+ *
+ *     This function returnes after the amount of time is elapsed
+ *     since the start time.
+ * 
+ * para        start           start time
+ *     duration        time to wait
+ *
+ * NOTE: The function will return immediately, if the timer is not
+ *      started
+ ************************/
+void hwt_wait_time(struct s_smc *smc, u_long start, long int duration)
+{
+       long    diff ;
+       long    interval ;
+       int     wrapped ;
+
+       /*
+        * check if timer is running
+        */
+       if (smc->hw.timer_activ == FALSE ||
+               hwt_quick_read(smc) == hwt_quick_read(smc)) {
+               return ;
+       }
+
+       interval = inpd(ADDR(B2_TI_INI)) ;
+       if (interval > duration) {
+               do {
+                       diff = (long)(start - hwt_quick_read(smc)) ;
+                       if (diff < 0) {
+                               diff += interval ;
+                       }
+               } while (diff <= duration) ;
+       }
+       else {
+               diff = interval ;
+               wrapped = 0 ;
+               do {
+                       if (!wrapped) {
+                               if (hwt_quick_read(smc) >= start) {
+                                       diff += interval ;
+                                       wrapped = 1 ;
+                               }
+                       }
+                       else {
+                               if (hwt_quick_read(smc) < start) {
+                                       wrapped = 0 ;
+                               }
+                       }
+               } while (diff <= duration) ;
+       }
+}
+#endif
+