ef80c0441b79e2ec33013a8f31154791be31dff9
[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/init.h>
24 #include <gpxe/timer.h>
25
26 static struct timer ts_table[0]
27         __table_start ( struct timer, timers );
28 static struct timer ts_table_end[0]
29         __table_end ( struct timer, timers );
30
31
32 static struct timer *used_ts = NULL;
33
34 /*
35  * This function may be used in custom timer driver.
36  *
37  * This udelay implementation works well if you've got a
38  * fast currticks().
39  */
40 void generic_currticks_udelay(unsigned int usecs)
41 {
42         tick_t t;
43
44         t = currticks();
45         while (t + usecs > currticks())
46                 ; /* xxx: Relax the cpu some way. */
47 }
48
49
50 static void timer_init(void)
51 {
52         struct timer *ts;
53
54         for (ts = ts_table; ts < ts_table_end; ts++) {
55                 if ( ts->init() == 0 ) {
56                         used_ts = ts;
57                         return;
58                 }
59         }
60
61         /* No timer found; we cannot continue */
62         assert ( 0 );
63         while ( 1 ) {};
64 }
65
66 struct init_fn ts_init_fn __init_fn ( INIT_NORMAL ) = {
67         .initialise = timer_init,
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         assert(used_ts);
78
79         ct = used_ts->currticks();
80         DBG ( "currticks: %ld.%06ld seconds\n",
81               ct / USECS_IN_SEC, ct % USECS_IN_SEC );
82
83         return ct;
84 }
85
86 /**
87  * Delay
88  *
89  * @v usecs     Time to delay, in microseconds
90  */
91 void udelay ( unsigned int usecs ) {
92         assert(used_ts);
93         used_ts->udelay ( usecs );
94 }
95
96 /**
97  * Delay
98  *
99  * @v msecs     Time to delay, in milliseconds
100  */
101 void mdelay ( unsigned int msecs ) {
102         while ( msecs-- )
103                 udelay ( USECS_IN_MSEC );
104 }
105
106 /**
107  * Delay
108  *
109  * @v secs      Time to delay, in seconds
110  */
111 unsigned int sleep ( unsigned int secs ) {
112         while ( secs-- )
113                 mdelay ( MSECS_IN_SEC );
114         return 0;
115 }