[Timers] Initialise timers on first use
[people/balajirrao/gpxe.git] / src / core / timer.c
1 /*
2  * core/timer.c
3  *
4  * Copyright (C) 2007 Alexey Zaytsev <alexey.zaytsev@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include <stddef.h>
22 #include <assert.h>
23 #include <gpxe/timer.h>
24
25 static struct timer ts_table[0]
26         __table_start ( struct timer, timers );
27 static struct timer ts_table_end[0]
28         __table_end ( struct timer, timers );
29
30 /*
31  * This function may be used in custom timer driver.
32  *
33  * This udelay implementation works well if you've got a
34  * fast currticks().
35  */
36 void generic_currticks_udelay ( unsigned int usecs ) {
37         tick_t start;
38         tick_t elapsed;
39         
40         start = currticks();
41         do {
42                 /* xxx: Relax the cpu some way. */
43                 elapsed = ( currticks() - start );
44         } while ( elapsed < usecs );
45 }
46
47 /**
48  * Identify timer source
49  *
50  * @ret timer           Timer source
51  */
52 static struct timer * timer ( void ) {
53         static struct timer *ts = NULL;
54
55         /* If we have a timer, use it */
56         if ( ts )
57                 return ts;
58
59         /* Scan for a usable timer */
60         for ( ts = ts_table ; ts < ts_table_end ; ts++ ) {
61                 if ( ts->init() == 0 )
62                         return ts;
63         }
64
65         /* No timer found; we cannot continue */
66         assert ( 0 );
67         while ( 1 ) {};
68 }
69
70 /**
71  * Read current time
72  *
73  * @ret ticks   Current time, in ticks
74  */
75 tick_t currticks ( void ) {
76         tick_t ct;
77
78         ct = timer()->currticks();
79         DBG ( "currticks: %ld.%06ld seconds\n",
80               ct / USECS_IN_SEC, ct % USECS_IN_SEC );
81
82         return ct;
83 }
84
85 /**
86  * Delay
87  *
88  * @v usecs     Time to delay, in microseconds
89  */
90 void udelay ( unsigned int usecs ) {
91         timer()->udelay ( usecs );
92 }
93
94 /**
95  * Delay
96  *
97  * @v msecs     Time to delay, in milliseconds
98  */
99 void mdelay ( unsigned int msecs ) {
100         while ( msecs-- )
101                 udelay ( USECS_IN_MSEC );
102 }
103
104 /**
105  * Delay
106  *
107  * @v secs      Time to delay, in seconds
108  */
109 unsigned int sleep ( unsigned int secs ) {
110         while ( secs-- )
111                 mdelay ( MSECS_IN_SEC );
112         return 0;
113 }