Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hwt.c
Go to the documentation of this file.
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  ************************/
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