iPXE
timer.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <string.h>
28#include <ipxe/process.h>
29#include <ipxe/console.h>
30#include <ipxe/keys.h>
31#include <ipxe/nap.h>
32#include <ipxe/init.h>
33#include <ipxe/timer.h>
34
35/** Current timer */
36static struct timer *timer;
37
38/**
39 * Get current system time in ticks
40 *
41 * @ret ticks Current time, in ticks
42 */
43unsigned long currticks ( void ) {
44
45 /* Guard against use during early initialisation */
46 if ( ! timer ) {
47 DBGC ( &timer, "TIMER currticks() called before initialisation "
48 "from %p\n", __builtin_return_address ( 0 ) );
49 return 0;
50 }
51
52 /* Use selected timer */
53 return timer->currticks();
54}
55
56/**
57 * Delay for a fixed number of microseconds
58 *
59 * @v usecs Number of microseconds for which to delay
60 */
61void udelay ( unsigned long usecs ) {
62
63 /* Guard against use during early initialisation */
64 if ( ! timer ) {
65 DBGC ( &timer, "TIMER udelay() called before initialisation "
66 "from %p\n", __builtin_return_address ( 0 ) );
67 return;
68 }
69
70 /* Use selected timer */
71 timer->udelay ( usecs );
72}
73
74/**
75 * Delay for a fixed number of milliseconds
76 *
77 * @v msecs Number of milliseconds for which to delay
78 */
79void mdelay ( unsigned long msecs ) {
80
81 /* Guard against use during early initialisation */
82 if ( ! timer ) {
83 DBGC ( &timer, "TIMER mdelay() called before initialisation "
84 "from %p\n", __builtin_return_address ( 0 ) );
85 return;
86 }
87
88 /* Delay for specified number of milliseconds */
89 while ( msecs-- )
90 udelay ( 1000 );
91}
92
93/**
94 * Sleep (possibly interruptibly) for a fixed number of seconds
95 *
96 * @v secs Number of seconds for which to delay
97 * @v interrupted Interrupt checking method, or NULL
98 * @ret secs Number of seconds remaining, if interrupted
99 */
100static unsigned int sleep_interruptible ( unsigned int secs,
101 int ( * interrupted ) ( void ) ) {
102 unsigned long start = currticks();
103 unsigned long now;
104
105 for ( ; secs ; secs-- ) {
106 while ( ( ( now = currticks() ) - start ) < TICKS_PER_SEC ) {
107 step();
108 if ( interrupted && interrupted() )
109 return secs;
110 cpu_nap();
111 }
112 start = now;
113 }
114
115 return 0;
116}
117
118/**
119 * Check if sleep has been interrupted by keypress
120 *
121 * @ret interrupted Sleep has been interrupted
122 */
123static int keypress_interrupted ( void ) {
124
125 return ( iskey() && ( getchar() == CTRL_C ) );
126}
127
128/**
129 * Sleep (interruptibly) for a fixed number of seconds
130 *
131 * @v secs Number of seconds for which to delay
132 * @ret secs Number of seconds remaining, if interrupted
133 */
134unsigned int sleep ( unsigned int secs ) {
135
137}
138
139/**
140 * Sleep (uninterruptibly) for a fixed number of seconds
141 *
142 * @v secs Number of seconds for which to delay
143 */
144void sleep_fixed ( unsigned int secs ) {
145
146 sleep_interruptible ( secs, NULL );
147}
148
149/**
150 * Find a working timer
151 *
152 */
153static void timer_probe ( void ) {
154 int rc;
155
156 /* Use first working timer */
158 if ( ( timer->probe == NULL ) ||
159 ( ( rc = timer->probe() ) == 0 ) ) {
160 DBGC ( &timer, "TIMER using %s\n", timer->name );
161 return;
162 }
163 DBGC ( &timer, "TIMER could not initialise %s: %s\n",
164 timer->name, strerror ( rc ) );
165 }
166
167 /* This is a fatal error */
168 DBGC ( &timer, "TIMER found no working timers!\n" );
169 while ( 1 ) {}
170}
171
172/** Timer initialisation function */
173struct init_fn timer_init_fn __init_fn ( INIT_EARLY ) = {
174 .name = "timer",
175 .initialise = timer_probe,
176};
177
178/* Drag in timer configuration */
179REQUIRING_SYMBOL ( timer_init_fn );
180REQUIRE_OBJECT ( config_timer );
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
int getchar(void)
Read a single character from any console.
Definition console.c:86
int iskey(void)
Check for available input on any console.
Definition console.c:131
#define DBGC(...)
Definition compiler.h:505
#define INIT_EARLY
Early initialisation.
Definition init.h:30
uint32_t start
Starting offset.
Definition netvsc.h:1
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define REQUIRE_OBJECT(object)
Require an object.
Definition compiler.h:202
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define REQUIRING_SYMBOL(symbol)
Specify the file's requiring symbol.
Definition compiler.h:140
User interaction.
CPU sleeping.
void cpu_nap(void)
Sleep with interrupts enabled until next CPU interrupt.
iPXE timers
#define TIMERS
Timer table.
Definition timer.h:53
#define TICKS_PER_SEC
Number of ticks per second.
Definition timer.h:16
String functions.
#define __init_fn(init_order)
Declare an initialisation functon.
Definition init.h:24
Key definitions.
#define CTRL_C
Definition keys.h:21
void step(void)
Single-step a single process.
Definition process.c:99
Processes.
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
An initialisation function.
Definition init.h:15
A timer.
Definition timer.h:29
void(* udelay)(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition timer.h:49
int(* probe)(void)
Probe timer.
Definition timer.h:37
unsigned long(* currticks)(void)
Get current system time in ticks.
Definition timer.h:43
const char * name
Name.
Definition timer.h:31
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
static unsigned int sleep_interruptible(unsigned int secs, int(*interrupted)(void))
Sleep (possibly interruptibly) for a fixed number of seconds.
Definition timer.c:100
static int keypress_interrupted(void)
Check if sleep has been interrupted by keypress.
Definition timer.c:123
unsigned long currticks(void)
Get current system time in ticks.
Definition timer.c:43
void sleep_fixed(unsigned int secs)
Sleep (uninterruptibly) for a fixed number of seconds.
Definition timer.c:144
static void timer_probe(void)
Find a working timer.
Definition timer.c:153
unsigned int sleep(unsigned int secs)
Sleep (interruptibly) for a fixed number of seconds.
Definition timer.c:134
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79
void udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition timer.c:61