Commit | Line | Data |
---|---|---|
1da177e4 LT |
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++ ; | |
af096046 | 80 | |
1da177e4 LT |
81 | outpd(ADDR(B2_TI_INI), (u_long) cnt * 200) ; /* Load timer value. */ |
82 | outpw(ADDR(B2_TI_CRTL), TIM_START) ; /* Start timer. */ | |
af096046 | 83 | |
1da177e4 LT |
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 | { | |
1da177e4 LT |
103 | outpw(ADDR(B2_TI_CRTL), TIM_STOP) ; |
104 | outpw(ADDR(B2_TI_CRTL), TIM_CL_IRQ) ; | |
1da177e4 LT |
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) ; | |
1da177e4 LT |
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 ; | |
1da177e4 | 167 | u_long is ; |
1da177e4 LT |
168 | |
169 | if (smc->hw.timer_activ) { | |
170 | hwt_stop(smc) ; | |
1da177e4 | 171 | tr = (u_short)((inpd(ADDR(B2_TI_VAL))/200) & 0xffff) ; |
af096046 | 172 | |
1da177e4 LT |
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 fuction 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 |