27 #include "../comedi.h"
29 #define i8253_cascade_ns_to_timer i8253_cascade_ns_to_timer_2div
31 static inline void i8253_cascade_ns_to_timer_2div_old(
int i8253_osc_base,
34 unsigned int *nanosec,
39 int div1_glb, div2_glb, ns_glb;
40 int div1_lub, div2_lub, ns_lub;
43 divider = (*nanosec + i8253_osc_base / 2) / i8253_osc_base;
48 div1_lub = div2_lub = 0;
49 div1_glb = div2_glb = 0;
55 for (div1 = divider / 65536 + 1; div1 <
div2; div1++) {
56 div2 = divider / div1;
58 ns = i8253_osc_base * div1 *
div2;
59 if (ns <= *nanosec && ns > ns_glb) {
67 ns = i8253_osc_base * div1 *
div2;
68 if (ns > *nanosec && ns < ns_lub) {
76 *nanosec = div1_lub * div2_lub * i8253_osc_base;
77 *d1 = div1_lub & 0xffff;
78 *d2 = div2_lub & 0xffff;
82 static inline void i8253_cascade_ns_to_timer_power(
int i8253_osc_base,
85 unsigned int *nanosec,
91 for (div1 = 2; div1 <= (1 << 16); div1 <<= 1) {
92 base = i8253_osc_base * div1;
97 div2 = (*nanosec + base / 2) / base;
100 div2 = (*nanosec) / base;
103 div2 = (*nanosec + base - 1) / base;
109 *nanosec = div2 * base;
119 *nanosec = div1 * div2 * i8253_osc_base;
124 static inline void i8253_cascade_ns_to_timer_2div(
int i8253_osc_base,
127 unsigned int *nanosec,
130 unsigned int divider;
131 unsigned int div1,
div2;
132 unsigned int div1_glb, div2_glb, ns_glb;
133 unsigned int div1_lub, div2_lub, ns_lub;
136 unsigned int ns_low, ns_high;
137 static const unsigned int max_count = 0x10000;
143 divider = div1 *
div2;
144 if (div1 * div2 * i8253_osc_base == *nanosec &&
145 div1 > 1 && div1 <= max_count && div2 > 1 && div2 <= max_count &&
147 divider > div1 && divider > div2 &&
148 divider * i8253_osc_base > divider &&
149 divider * i8253_osc_base > i8253_osc_base) {
153 divider = *nanosec / i8253_osc_base;
155 div1_lub = div2_lub = 0;
156 div1_glb = div2_glb = 0;
162 start = divider /
div2;
165 for (div1 = start; div1 <= divider / div1 + 1 && div1 <=
max_count;
167 for (div2 = divider / div1;
168 div1 * div2 <= divider + div1 + 1 && div2 <=
max_count;
170 ns = i8253_osc_base * div1 *
div2;
171 if (ns <= *nanosec && ns > ns_glb) {
176 if (ns >= *nanosec && ns < ns_lub) {
185 switch (round_mode) {
188 ns_high = div1_lub * div2_lub * i8253_osc_base;
189 ns_low = div1_glb * div2_glb * i8253_osc_base;
190 if (ns_high - *nanosec < *nanosec - ns_low) {
208 *nanosec = div1 * div2 * i8253_osc_base;
236 #define i8254_control_reg 3
238 static inline int i8254_load(
unsigned long base_address,
unsigned int regshift,
239 unsigned int counter_number,
unsigned int count,
244 if (counter_number > 2)
250 if ((mode == 2 || mode == 3) && count == 1)
253 byte = counter_number << 6;
258 outb(byte, base_address + (counter_number << regshift));
259 byte = (count >> 8) & 0xff;
260 outb(byte, base_address + (counter_number << regshift));
266 unsigned int regshift,
267 unsigned int counter_number,
273 if (counter_number > 2)
279 if ((mode == 2 || mode == 3) && count == 1)
282 byte = counter_number << 6;
287 writeb(byte, base_address + (counter_number << regshift));
288 byte = (count >> 8) & 0xff;
289 writeb(byte, base_address + (counter_number << regshift));
295 static inline int i8254_read(
unsigned long base_address,
unsigned int regshift,
296 unsigned int counter_number)
301 if (counter_number > 2)
305 byte = counter_number << 6;
309 ret =
inb(base_address + (counter_number << regshift));
311 ret +=
inb(base_address + (counter_number << regshift)) << 8;
316 static inline int i8254_mm_read(
void __iomem *base_address,
317 unsigned int regshift,
318 unsigned int counter_number)
323 if (counter_number > 2)
327 byte = counter_number << 6;
331 ret =
readb(base_address + (counter_number << regshift));
333 ret +=
readb(base_address + (counter_number << regshift)) << 8;
339 static inline void i8254_write(
unsigned long base_address,
340 unsigned int regshift,
341 unsigned int counter_number,
unsigned int count)
345 if (counter_number > 2)
349 outb(byte, base_address + (counter_number << regshift));
350 byte = (count >> 8) & 0xff;
351 outb(byte, base_address + (counter_number << regshift));
354 static inline void i8254_mm_write(
void __iomem *base_address,
355 unsigned int regshift,
356 unsigned int counter_number,
361 if (counter_number > 2)
365 writeb(byte, base_address + (counter_number << regshift));
366 byte = (count >> 8) & 0xff;
367 writeb(byte, base_address + (counter_number << regshift));
377 static inline int i8254_set_mode(
unsigned long base_address,
378 unsigned int regshift,
379 unsigned int counter_number,
unsigned int mode)
383 if (counter_number > 2)
388 byte = counter_number << 6;
396 static inline int i8254_mm_set_mode(
void __iomem *base_address,
397 unsigned int regshift,
398 unsigned int counter_number,
403 if (counter_number > 2)
408 byte = counter_number << 6;
416 static inline int i8254_status(
unsigned long base_address,
417 unsigned int regshift,
418 unsigned int counter_number)
420 outb(0xE0 | (2 << counter_number),
422 return inb(base_address + (counter_number << regshift));
425 static inline int i8254_mm_status(
void __iomem *base_address,
426 unsigned int regshift,
427 unsigned int counter_number)
429 writeb(0xE0 | (2 << counter_number),
431 return readb(base_address + (counter_number << regshift));