1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75#include <linux/errno.h>
76#include <linux/sched.h>
77#include <linux/kernel.h>
78#include <linux/param.h>
79#include <linux/string.h>
80#include <linux/mm.h>
81#include <linux/vmalloc.h>
82#include <linux/interrupt.h>
83#include <linux/time.h>
84#include <linux/delay.h>
85
86#include <asm/segment.h>
87#include <asm/io.h>
88#include <asm/irq.h>
89#include <asm/delay.h>
90#include <asm/rtc.h>
91
92#include <linux/config.h>
93#include <linux/version.h>
94
95#include <asm/svinto.h>
96#include <asm/fasttimer.h>
97#include <linux/proc_fs.h>
98
99
100#define DEBUG_LOG_INCLUDED
101#define FAST_TIMER_LOG
102
103
104#define FAST_TIMER_SANITY_CHECKS
105
106#ifdef FAST_TIMER_SANITY_CHECKS
107#define SANITYCHECK(x) x
108static int sanity_failed = 0;
109#else
110#define SANITYCHECK(x)
111#endif
112
113#define D1(x)
114#define D2(x)
115#define DP(x)
116
117#define __INLINE__ inline
118
119static int fast_timer_running = 0;
120static int fast_timers_added = 0;
121static int fast_timers_started = 0;
122static int fast_timers_expired = 0;
123static int fast_timers_deleted = 0;
124static int fast_timer_is_init = 0;
125static int fast_timer_ints = 0;
126
127struct fast_timer *fast_timer_list = NULL;
128
129#ifdef DEBUG_LOG_INCLUDED
130#define DEBUG_LOG_MAX 128
131static const char * debug_log_string[DEBUG_LOG_MAX];
132static unsigned long debug_log_value[DEBUG_LOG_MAX];
133static int debug_log_cnt = 0;
134static int debug_log_cnt_wrapped = 0;
135
136#define DEBUG_LOG(string, value) \
137{ \
138 unsigned long log_flags; \
139 save_flags(log_flags); \
140 cli(); \
141 debug_log_string[debug_log_cnt] = (string); \
142 debug_log_value[debug_log_cnt] = (unsigned long)(value); \
143 if (++debug_log_cnt >= DEBUG_LOG_MAX) \
144 { \
145 debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \
146 debug_log_cnt_wrapped = 1; \
147 } \
148 restore_flags(log_flags); \
149}
150#else
151#define DEBUG_LOG(string, value)
152#endif
153
154
155
156#define NUM_TIMER_FREQ 15
157#define MAX_USABLE_TIMER_FREQ 7
158#define MAX_DELAY_US 853333L
159const unsigned long timer_freq_100[NUM_TIMER_FREQ] =
160{
161 3,
162 6,
163 12,
164 24,
165 48,
166 96,
167 192,
168 384,
169 576,
170 1152,
171 2304,
172 4608,
173 9216,
174 18432,
175 62500,
176
177};
178#define NUM_TIMER_STATS 16
179#ifdef FAST_TIMER_LOG
180struct fast_timer timer_added_log[NUM_TIMER_STATS];
181struct fast_timer timer_started_log[NUM_TIMER_STATS];
182struct fast_timer timer_expired_log[NUM_TIMER_STATS];
183#endif
184
185int timer_div_settings[NUM_TIMER_STATS];
186int timer_freq_settings[NUM_TIMER_STATS];
187int timer_delay_settings[NUM_TIMER_STATS];
188
189
190void __INLINE__ do_gettimeofday_fast(struct timeval *tv)
191{
192 unsigned long sec = jiffies;
193 unsigned long usec = GET_JIFFIES_USEC();
194
195 usec += (sec % HZ) * (1000000 / HZ);
196 sec = sec / HZ;
197
198 if (usec > 1000000)
199 {
200 usec -= 1000000;
201 sec++;
202 }
203 tv->tv_sec = sec;
204 tv->tv_usec = usec;
205}
206
207int __INLINE__ timeval_cmp(struct timeval *t0, struct timeval *t1)
208{
209 if (t0->tv_sec < t1->tv_sec)
210 {
211 return -1;
212 }
213 else if (t0->tv_sec > t1->tv_sec)
214 {
215 return 1;
216 }
217 if (t0->tv_usec < t1->tv_usec)
218 {
219 return -1;
220 }
221 else if (t0->tv_usec > t1->tv_usec)
222 {
223 return 1;
224 }
225 return 0;
226}
227
228void __INLINE__ start_timer1(unsigned long delay_us)
229{
230 int freq_index = 0;
231 unsigned long upper_limit = MAX_DELAY_US;
232
233 unsigned long div;
234
235
236
237
238#if 1
239 while (delay_us < upper_limit && freq_index < MAX_USABLE_TIMER_FREQ)
240 {
241 freq_index++;
242 upper_limit >>= 1;
243 }
244 if (freq_index > 0)
245 {
246 freq_index--;
247 }
248#else
249 freq_index = 6;
250#endif
251 div = delay_us * timer_freq_100[freq_index]/10000;
252 if (div < 2)
253 {
254
255 div = 2;
256 }
257 if (div > 255)
258 {
259 div = 0;
260
261
262
263 }
264
265 timer_div_settings[fast_timers_started % NUM_TIMER_STATS] = div;
266 timer_freq_settings[fast_timers_started % NUM_TIMER_STATS] = freq_index;
267 timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us;
268
269 D1(printk("start_timer1 : %d us freq: %i div: %i\n",
270 delay_us, freq_index, div));
271
272 *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);
273
274
275 *R_TIMER_CTRL = r_timer_ctrl_shadow =
276 (r_timer_ctrl_shadow &
277 ~IO_MASK(R_TIMER_CTRL, timerdiv1) &
278 ~IO_MASK(R_TIMER_CTRL, tm1) &
279 ~IO_MASK(R_TIMER_CTRL, clksel1)) |
280 IO_FIELD(R_TIMER_CTRL, timerdiv1, div) |
281 IO_STATE(R_TIMER_CTRL, tm1, stop_ld) |
282 IO_FIELD(R_TIMER_CTRL, clksel1, freq_index );
283
284
285 *R_TIMER_CTRL = r_timer_ctrl_shadow |
286 IO_STATE(R_TIMER_CTRL, i1, clr);
287
288
289 *R_TIMER_CTRL = r_timer_ctrl_shadow =
290 (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
291 IO_STATE(R_TIMER_CTRL, tm1, run);
292
293
294 *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer1, set);
295 fast_timers_started++;
296 fast_timer_running = 1;
297}
298
299
300void start_one_shot_timer(struct fast_timer *t,
301 fast_timer_function_type *function,
302 unsigned long data,
303 unsigned long delay_us,
304 const char *name)
305{
306 unsigned long flags;
307 struct fast_timer *tmp;
308
309 D1(printk("sft %s %d us\n", name, delay_us));
310
311 save_flags(flags);
312 cli();
313
314 do_gettimeofday_fast(&t->tv_set);
315 tmp = fast_timer_list;
316
317 SANITYCHECK({
318 while (tmp != NULL)
319 {
320 if (tmp == t)
321 {
322 printk(KERN_WARNING
323 "timer name: %s data: 0x%08lX already in list!\n", name, data);
324 sanity_failed++;
325 return;
326 }
327 else
328 {
329 tmp = tmp->next;
330 }
331 }
332 tmp = fast_timer_list;
333 });
334
335 t->delay_us = delay_us;
336 t->function = function;
337 t->data = data;
338 t->name = name;
339
340 t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000;
341 t->tv_expires.tv_sec = t->tv_set.tv_sec + delay_us / 1000000;
342 if (t->tv_expires.tv_usec > 1000000)
343 {
344 t->tv_expires.tv_usec -= 1000000;
345 t->tv_expires.tv_sec++;
346 }
347#ifdef FAST_TIMER_LOG
348 timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t;
349#endif
350 fast_timers_added++;
351
352
353 if (tmp == NULL || timeval_cmp(&t->tv_expires, &tmp->tv_expires) < 0)
354 {
355
356 t->prev = NULL;
357 t->next = fast_timer_list;
358 if (fast_timer_list)
359 {
360 fast_timer_list->prev = t;
361 }
362 fast_timer_list = t;
363#ifdef FAST_TIMER_LOG
364 timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
365#endif
366 start_timer1(delay_us);
367 } else {
368
369 while (tmp->next &&
370 timeval_cmp(&t->tv_expires, &tmp->next->tv_expires) > 0)
371 {
372 tmp = tmp->next;
373 }
374
375 t->prev = tmp;
376 t->next = tmp->next;
377 if (tmp->next)
378 {
379 tmp->next->prev = t;
380 }
381 tmp->next = t;
382 }
383
384 D2(printk("start_one_shot_timer: %d us done\n", delay_us));
385
386 restore_flags(flags);
387}
388
389static inline int detach_fast_timer (struct fast_timer *t)
390{
391 struct fast_timer *next, *prev;
392 if (!fast_timer_pending(t))
393 return 0;
394 next = t->next;
395 prev = t->prev;
396 if (next)
397 next->prev = prev;
398 if (prev)
399 prev->next = next;
400 else
401 fast_timer_list = next;
402 fast_timers_deleted++;
403 return 1;
404}
405
406int del_fast_timer(struct fast_timer * t)
407{
408 unsigned long flags;
409 int ret;
410
411 save_flags(flags);
412 cli();
413 ret = detach_fast_timer(t);
414 t->next = t->prev = NULL;
415 restore_flags(flags);
416 return ret;
417}
418
419
420
421
422
423
424static void
425timer1_handler(int irq, void *dev_id, struct pt_regs *regs)
426{
427 struct fast_timer *t;
428 unsigned long flags;
429
430 save_flags(flags);
431 cli();
432
433
434 *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr);
435
436
437
438 *R_TIMER_CTRL = r_timer_ctrl_shadow =
439 (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
440 IO_STATE(R_TIMER_CTRL, tm1, stop_ld);
441
442
443 *R_TIMER_CTRL = r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr);
444
445 fast_timer_running = 0;
446 fast_timer_ints++;
447
448 restore_flags(flags);
449
450 t = fast_timer_list;
451 while (t)
452 {
453 struct timeval tv;
454
455
456 do_gettimeofday_fast(&tv);
457 D1(printk("t: %is %06ius\n", tv.tv_sec, tv.tv_usec));
458
459 if (timeval_cmp(&t->tv_expires, &tv) <= 0)
460 {
461
462#ifdef FAST_TIMER_LOG
463 timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t;
464#endif
465 fast_timers_expired++;
466
467
468 save_flags(flags);
469 cli();
470 if (t->prev)
471 {
472 t->prev->next = t->next;
473 }
474 else
475 {
476 fast_timer_list = t->next;
477 }
478 if (t->next)
479 {
480 t->next->prev = t->prev;
481 }
482 t->prev = NULL;
483 t->next = NULL;
484 restore_flags(flags);
485
486 if (t->function != NULL)
487 {
488 t->function(t->data);
489 }
490 else
491 {
492 DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints);
493 }
494 }
495 else
496 {
497
498 D1(printk(".\n"));
499 }
500
501 save_flags(flags);
502 cli();
503 if ((t = fast_timer_list) != NULL)
504 {
505
506 long us;
507 struct timeval tv;
508
509 do_gettimeofday_fast(&tv);
510 us = ((t->tv_expires.tv_sec - tv.tv_sec) * 1000000 +
511 t->tv_expires.tv_usec - tv.tv_usec);
512 if (us > 0)
513 {
514 if (!fast_timer_running)
515 {
516#ifdef FAST_TIMER_LOG
517 timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t;
518#endif
519 start_timer1(us);
520 }
521 restore_flags(flags);
522 break;
523 }
524 else
525 {
526
527
528
529 D1(printk("e! %d\n", us));
530 }
531 }
532 restore_flags(flags);
533 }
534
535 if (!t)
536 {
537 D1(printk("t1 stop!\n"));
538 }
539}
540
541static void wake_up_func(unsigned long data)
542{
543#ifdef DECLARE_WAITQUEUE
544 wait_queue_head_t *sleep_wait_p = (wait_queue_head_t*)data;
545#else
546 struct wait_queue **sleep_wait_p = (struct wait_queue **)data;
547#endif
548 wake_up(sleep_wait_p);
549}
550
551
552
553
554void schedule_usleep(unsigned long us)
555{
556 struct fast_timer t;
557#ifdef DECLARE_WAITQUEUE
558 wait_queue_head_t sleep_wait;
559 init_waitqueue_head(&sleep_wait);
560 {
561 DECLARE_WAITQUEUE(wait, current);
562#else
563 struct wait_queue *sleep_wait = NULL;
564 struct wait_queue wait = { current, NULL };
565#endif
566
567 D1(printk("schedule_usleep(%d)\n", us));
568 add_wait_queue(&sleep_wait, &wait);
569 set_current_state(TASK_INTERRUPTIBLE);
570 start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us,
571 "usleep");
572 schedule();
573 set_current_state(TASK_RUNNING);
574 remove_wait_queue(&sleep_wait, &wait);
575 D1(printk("done schedule_usleep(%d)\n", us));
576#ifdef DECLARE_WAITQUEUE
577 }
578#endif
579}
580
581#ifdef CONFIG_PROC_FS
582static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
583#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
584 ,int *eof, void *data_unused
585#else
586 ,int unused
587#endif
588 );
589#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
590static struct proc_dir_entry *fasttimer_proc_entry;
591#else
592static struct proc_dir_entry fasttimer_proc_entry =
593{
594 0, 9, "fasttimer",
595 S_IFREG | S_IRUGO, 1, 0, 0,
596 0, NULL ,
597 &proc_fasttimer_read ,
598};
599#endif
600#endif
601
602#ifdef CONFIG_PROC_FS
603
604
605#define BIG_BUF_SIZE (500 + NUM_TIMER_STATS * 300)
606
607static int proc_fasttimer_read(char *buf, char **start, off_t offset, int len
608#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
609 ,int *eof, void *data_unused
610#else
611 ,int unused
612#endif
613 )
614{
615 unsigned long flags;
616 int i = 0;
617 int num_to_show;
618 struct timeval tv;
619 struct fast_timer *t, *nextt;
620 static char *bigbuf = NULL;
621 static unsigned long used;
622
623 if (!bigbuf && !(bigbuf = vmalloc(BIG_BUF_SIZE)))
624 {
625 used = 0;
626 bigbuf[0] = '\0';
627 return 0;
628 }
629
630 if (!offset || !used)
631 {
632 do_gettimeofday_fast(&tv);
633
634 used = 0;
635 used += sprintf(bigbuf + used, "Fast timers added: %i\n",
636 fast_timers_added);
637 used += sprintf(bigbuf + used, "Fast timers started: %i\n",
638 fast_timers_started);
639 used += sprintf(bigbuf + used, "Fast timer interrupts: %i\n",
640 fast_timer_ints);
641 used += sprintf(bigbuf + used, "Fast timers expired: %i\n",
642 fast_timers_expired);
643 used += sprintf(bigbuf + used, "Fast timers deleted: %i\n",
644 fast_timers_deleted);
645 used += sprintf(bigbuf + used, "Fast timer running: %s\n",
646 fast_timer_running ? "yes" : "no");
647 used += sprintf(bigbuf + used, "Current time: %lu.%06lu\n",
648 (unsigned long)tv.tv_sec,
649 (unsigned long)tv.tv_usec);
650#ifdef FAST_TIMER_SANITY_CHECKS
651 used += sprintf(bigbuf + used, "Sanity failed: %i\n",
652 sanity_failed);
653#endif
654 used += sprintf(bigbuf + used, "\n");
655
656#ifdef DEBUG_LOG_INCLUDED
657 {
658 int end_i = debug_log_cnt;
659 i = 0;
660
661 if (debug_log_cnt_wrapped)
662 {
663 i = debug_log_cnt;
664 }
665
666 while ((i != end_i || (debug_log_cnt_wrapped && !used)) &&
667 used+100 < BIG_BUF_SIZE)
668 {
669 used += sprintf(bigbuf + used, debug_log_string[i],
670 debug_log_value[i]);
671 i = (i+1) % DEBUG_LOG_MAX;
672 }
673 }
674 used += sprintf(bigbuf + used, "\n");
675#endif
676
677 num_to_show = (fast_timers_started < NUM_TIMER_STATS ? fast_timers_started:
678 NUM_TIMER_STATS);
679 used += sprintf(bigbuf + used, "Timers started: %i\n", fast_timers_started);
680 for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE) ; i++)
681 {
682 int cur = (fast_timers_started - i - 1) % NUM_TIMER_STATS;
683
684#if 1
685 used += sprintf(bigbuf + used, "div: %i freq: %i delay: %i"
686 "\n",
687 timer_div_settings[cur],
688 timer_freq_settings[cur],
689 timer_delay_settings[cur]
690 );
691#endif
692#ifdef FAST_TIMER_LOG
693 t = &timer_started_log[cur];
694 used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
695 "d: %6li us data: 0x%08lX"
696 "\n",
697 t->name,
698 (unsigned long)t->tv_set.tv_sec,
699 (unsigned long)t->tv_set.tv_usec,
700 (unsigned long)t->tv_expires.tv_sec,
701 (unsigned long)t->tv_expires.tv_usec,
702 t->delay_us,
703 t->data
704 );
705#endif
706 }
707 used += sprintf(bigbuf + used, "\n");
708
709#ifdef FAST_TIMER_LOG
710 num_to_show = (fast_timers_added < NUM_TIMER_STATS ? fast_timers_added:
711 NUM_TIMER_STATS);
712 used += sprintf(bigbuf + used, "Timers added: %i\n", fast_timers_added);
713 for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE); i++)
714 {
715 t = &timer_added_log[(fast_timers_added - i - 1) % NUM_TIMER_STATS];
716 used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
717 "d: %6li us data: 0x%08lX"
718 "\n",
719 t->name,
720 (unsigned long)t->tv_set.tv_sec,
721 (unsigned long)t->tv_set.tv_usec,
722 (unsigned long)t->tv_expires.tv_sec,
723 (unsigned long)t->tv_expires.tv_usec,
724 t->delay_us,
725 t->data
726 );
727 }
728 used += sprintf(bigbuf + used, "\n");
729
730 num_to_show = (fast_timers_expired < NUM_TIMER_STATS ? fast_timers_expired:
731 NUM_TIMER_STATS);
732 used += sprintf(bigbuf + used, "Timers expired: %i\n", fast_timers_expired);
733 for (i = 0; i < num_to_show && (used+100 < BIG_BUF_SIZE); i++)
734 {
735 t = &timer_expired_log[(fast_timers_expired - i - 1) % NUM_TIMER_STATS];
736 used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
737 "d: %6li us data: 0x%08lX"
738 "\n",
739 t->name,
740 (unsigned long)t->tv_set.tv_sec,
741 (unsigned long)t->tv_set.tv_usec,
742 (unsigned long)t->tv_expires.tv_sec,
743 (unsigned long)t->tv_expires.tv_usec,
744 t->delay_us,
745 t->data
746 );
747 }
748 used += sprintf(bigbuf + used, "\n");
749#endif
750
751 used += sprintf(bigbuf + used, "Active timers:\n");
752 save_flags(flags);
753 cli();
754 t = fast_timer_list;
755 while (t != NULL && (used+100 < BIG_BUF_SIZE))
756 {
757 nextt = t->next;
758 restore_flags(flags);
759 used += sprintf(bigbuf + used, "%-14s s: %6lu.%06lu e: %6lu.%06lu "
760 "d: %6li us data: 0x%08lX"
761
762 "\n",
763 t->name,
764 (unsigned long)t->tv_set.tv_sec,
765 (unsigned long)t->tv_set.tv_usec,
766 (unsigned long)t->tv_expires.tv_sec,
767 (unsigned long)t->tv_expires.tv_usec,
768 t->delay_us,
769 t->data
770
771 );
772 cli();
773 if (t->next != nextt)
774 {
775 printk(KERN_WARNING "timer removed!\n");
776 }
777 t = nextt;
778 }
779 restore_flags(flags);
780 }
781
782 if (used - offset < len)
783 {
784 len = used - offset;
785 }
786
787 memcpy(buf, bigbuf + offset, len);
788 *start = buf;
789#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
790 *eof = 1;
791#endif
792
793 return len;
794}
795#endif
796
797#ifdef FAST_TIMER_TEST
798static volatile unsigned long i = 0;
799static volatile int num_test_timeout = 0;
800static struct fast_timer tr[10];
801static int exp_num[10];
802
803static struct timeval tv_exp[100];
804
805static void test_timeout(unsigned long data)
806{
807 do_gettimeofday_fast(&tv_exp[data]);
808 exp_num[data] = num_test_timeout;
809
810 num_test_timeout++;
811}
812
813static void test_timeout1(unsigned long data)
814{
815 do_gettimeofday_fast(&tv_exp[data]);
816 exp_num[data] = num_test_timeout;
817 if (data < 7)
818 {
819 start_one_shot_timer(&tr[i], test_timeout1, i, 1000, "timeout1");
820 i++;
821 }
822 num_test_timeout++;
823}
824
825DP(
826static char buf0[2000];
827static char buf1[2000];
828static char buf2[2000];
829static char buf3[2000];
830static char buf4[2000];
831);
832
833static char buf5[6000];
834static int j_u[1000];
835
836static void fast_timer_test(void)
837{
838 int prev_num;
839 int j;
840
841 struct timeval tv, tv0, tv1, tv2;
842
843 printk("fast_timer_test() start\n");
844 do_gettimeofday_fast(&tv);
845
846 for (j = 0; j < 1000; j++)
847 {
848 j_u[j] = GET_JIFFIES_USEC();
849 }
850 for (j = 0; j < 100; j++)
851 {
852 do_gettimeofday_fast(&tv_exp[j]);
853 }
854 printk("fast_timer_test() %is %06i\n", tv.tv_sec, tv.tv_usec);
855
856 for (j = 0; j < 1000; j++)
857 {
858 printk("%i %i %i %i %i\n",j_u[j], j_u[j+1], j_u[j+2], j_u[j+3], j_u[j+4]);
859 j += 4;
860 }
861 for (j = 0; j < 100; j++)
862 {
863 printk("%i.%i %i.%i %i.%i %i.%i %i.%i\n",
864 tv_exp[j].tv_sec,tv_exp[j].tv_usec,
865 tv_exp[j+1].tv_sec,tv_exp[j+1].tv_usec,
866 tv_exp[j+2].tv_sec,tv_exp[j+2].tv_usec,
867 tv_exp[j+3].tv_sec,tv_exp[j+3].tv_usec,
868 tv_exp[j+4].tv_sec,tv_exp[j+4].tv_usec);
869 j += 4;
870 }
871 do_gettimeofday_fast(&tv0);
872 start_one_shot_timer(&tr[i], test_timeout, i, 50000, "test0");
873 DP(proc_fasttimer_read(buf0, NULL, 0, 0, 0));
874 i++;
875 start_one_shot_timer(&tr[i], test_timeout, i, 70000, "test1");
876 DP(proc_fasttimer_read(buf1, NULL, 0, 0, 0));
877 i++;
878 start_one_shot_timer(&tr[i], test_timeout, i, 40000, "test2");
879 DP(proc_fasttimer_read(buf2, NULL, 0, 0, 0));
880 i++;
881 start_one_shot_timer(&tr[i], test_timeout, i, 60000, "test3");
882 DP(proc_fasttimer_read(buf3, NULL, 0, 0, 0));
883 i++;
884 start_one_shot_timer(&tr[i], test_timeout1, i, 55000, "test4xx");
885 DP(proc_fasttimer_read(buf4, NULL, 0, 0, 0));
886 i++;
887 do_gettimeofday_fast(&tv1);
888
889 proc_fasttimer_read(buf5, NULL, 0, 0, 0);
890
891 prev_num = num_test_timeout;
892 while (num_test_timeout < i)
893 {
894 if (num_test_timeout != prev_num)
895 {
896 prev_num = num_test_timeout;
897 }
898 }
899 do_gettimeofday_fast(&tv2);
900 printk("Timers started %is %06i\n", tv0.tv_sec, tv0.tv_usec);
901 printk("Timers started at %is %06i\n", tv1.tv_sec, tv1.tv_usec);
902 printk("Timers done %is %06i\n", tv2.tv_sec, tv2.tv_usec);
903 DP(printk("buf0:\n");
904 printk(buf0);
905 printk("buf1:\n");
906 printk(buf1);
907 printk("buf2:\n");
908 printk(buf2);
909 printk("buf3:\n");
910 printk(buf3);
911 printk("buf4:\n");
912 printk(buf4);
913 );
914 printk("buf5:\n");
915 printk(buf5);
916
917 printk("timers set:\n");
918 for(j = 0; j<i; j++)
919 {
920 struct fast_timer *t = &tr[j];
921 printk("%-10s set: %6is %06ius exp: %6is %06ius "
922 "data: 0x%08X func: 0x%08X\n",
923 t->name,
924 t->tv_set.tv_sec,
925 t->tv_set.tv_usec,
926 t->tv_expires.tv_sec,
927 t->tv_expires.tv_usec,
928 t->data,
929 t->function
930 );
931
932 printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n",
933 t->delay_us,
934 tv_exp[j].tv_sec,
935 tv_exp[j].tv_usec,
936 exp_num[j],
937 (tv_exp[j].tv_sec - t->tv_expires.tv_sec)*1000000 + tv_exp[j].tv_usec - t->tv_expires.tv_usec);
938 }
939 proc_fasttimer_read(buf5, NULL, 0, 0, 0);
940 printk("buf5 after all done:\n");
941 printk(buf5);
942 printk("fast_timer_test() done\n");
943}
944#endif
945
946
947void fast_timer_init(void)
948{
949
950 if (!fast_timer_is_init)
951 {
952#if 0 && defined(FAST_TIMER_TEST)
953 int i;
954#endif
955
956 printk(KERN_INFO "fast_timer_init()\n");
957
958#if 0 && defined(FAST_TIMER_TEST)
959 for (i = 0; i <= TIMER0_DIV; i++)
960 {
961
962 printk("%3i %6u\n", i, timer0_value_us[i]);
963 }
964#endif
965#ifdef CONFIG_PROC_FS
966#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)
967 if ((fasttimer_proc_entry = create_proc_entry( "fasttimer", 0, 0 )))
968 fasttimer_proc_entry->read_proc = proc_fasttimer_read;
969#else
970 proc_register_dynamic(&proc_root, &fasttimer_proc_entry);
971#endif
972#endif
973 if(request_irq(TIMER1_IRQ_NBR, timer1_handler, SA_SHIRQ,
974 "fast timer int", NULL))
975 {
976 printk(KERN_CRIT "err: timer1 irq\n");
977 }
978 fast_timer_is_init = 1;
979#ifdef FAST_TIMER_TEST
980 printk("do test\n");
981 fast_timer_test();
982#endif
983 }
984}
985