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