~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/ipxe/src/interface/efi/efi_timer.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
24
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
25
 
 
26
#include <string.h>
 
27
#include <errno.h>
 
28
#include <unistd.h>
 
29
#include <ipxe/timer.h>
 
30
#include <ipxe/init.h>
 
31
#include <ipxe/efi/efi.h>
 
32
 
 
33
/** @file
 
34
 *
 
35
 * iPXE timer API for EFI
 
36
 *
 
37
 */
 
38
 
 
39
/** Current tick count */
 
40
static unsigned long efi_jiffies;
 
41
 
 
42
/** Timer tick event */
 
43
static EFI_EVENT efi_tick_event;
 
44
 
 
45
/** Colour for debug messages */
 
46
#define colour &efi_jiffies
 
47
 
 
48
/**
 
49
 * Delay for a fixed number of microseconds
 
50
 *
 
51
 * @v usecs             Number of microseconds for which to delay
 
52
 */
 
53
static void efi_udelay ( unsigned long usecs ) {
 
54
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 
55
        EFI_STATUS efirc;
 
56
        int rc;
 
57
 
 
58
        if ( ( efirc = bs->Stall ( usecs ) ) != 0 ) {
 
59
                rc = -EEFI ( efirc );
 
60
                DBGC ( colour, "EFI could not delay for %ldus: %s\n",
 
61
                       usecs, strerror ( rc ) );
 
62
                /* Probably screwed */
 
63
        }
 
64
}
 
65
 
 
66
/**
 
67
 * Get current system time in ticks
 
68
 *
 
69
 * @ret ticks           Current time, in ticks
 
70
 */
 
71
static unsigned long efi_currticks ( void ) {
 
72
 
 
73
        return efi_jiffies;
 
74
}
 
75
 
 
76
/**
 
77
 * Timer tick
 
78
 *
 
79
 * @v event             Timer tick event
 
80
 * @v context           Event context
 
81
 */
 
82
static EFIAPI void efi_tick ( EFI_EVENT event __unused,
 
83
                              void *context __unused ) {
 
84
 
 
85
        /* Increment tick count */
 
86
        efi_jiffies++;
 
87
}
 
88
 
 
89
/**
 
90
 * Start timer tick
 
91
 *
 
92
 */
 
93
static void efi_tick_startup ( void ) {
 
94
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 
95
        EFI_STATUS efirc;
 
96
        int rc;
 
97
 
 
98
        /* Create timer tick event */
 
99
        if ( ( efirc = bs->CreateEvent ( ( EVT_TIMER | EVT_NOTIFY_SIGNAL ),
 
100
                                         TPL_CALLBACK, efi_tick, NULL,
 
101
                                         &efi_tick_event ) ) != 0 ) {
 
102
                rc = -EEFI ( efirc );
 
103
                DBGC ( colour, "EFI could not create timer tick: %s\n",
 
104
                       strerror ( rc ) );
 
105
                /* Nothing we can do about it */
 
106
                return;
 
107
        }
 
108
 
 
109
        /* Start timer tick */
 
110
        if ( ( efirc = bs->SetTimer ( efi_tick_event, TimerPeriodic,
 
111
                                      ( 10000000 / EFI_TICKS_PER_SEC ) ) ) !=0){
 
112
                rc = -EEFI ( efirc );
 
113
                DBGC ( colour, "EFI could not start timer tick: %s\n",
 
114
                       strerror ( rc ) );
 
115
                /* Nothing we can do about it */
 
116
                return;
 
117
        }
 
118
        DBGC ( colour, "EFI timer started at %d ticks per second\n",
 
119
               EFI_TICKS_PER_SEC );
 
120
}
 
121
 
 
122
/**
 
123
 * Stop timer tick
 
124
 *
 
125
 * @v booting           System is shutting down in order to boot
 
126
 */
 
127
static void efi_tick_shutdown ( int booting __unused ) {
 
128
        EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
 
129
        EFI_STATUS efirc;
 
130
        int rc;
 
131
 
 
132
        /* Stop timer tick */
 
133
        if ( ( efirc = bs->SetTimer ( efi_tick_event, TimerCancel, 0 ) ) != 0 ){
 
134
                rc = -EEFI ( efirc );
 
135
                DBGC ( colour, "EFI could not stop timer tick: %s\n",
 
136
                       strerror ( rc ) );
 
137
                /* Self-destruct initiated */
 
138
                return;
 
139
        }
 
140
        DBGC ( colour, "EFI timer stopped\n" );
 
141
 
 
142
        /* Destroy timer tick event */
 
143
        if ( ( efirc = bs->CloseEvent ( efi_tick_event ) ) != 0 ) {
 
144
                rc = -EEFI ( efirc );
 
145
                DBGC ( colour, "EFI could not destroy timer tick: %s\n",
 
146
                       strerror ( rc ) );
 
147
                /* Probably non-fatal */
 
148
                return;
 
149
        }
 
150
}
 
151
 
 
152
/** Timer tick startup function */
 
153
struct startup_fn efi_tick_startup_fn __startup_fn ( STARTUP_EARLY ) = {
 
154
        .startup = efi_tick_startup,
 
155
        .shutdown = efi_tick_shutdown,
 
156
};
 
157
 
 
158
PROVIDE_TIMER ( efi, udelay, efi_udelay );
 
159
PROVIDE_TIMER ( efi, currticks, efi_currticks );
 
160
PROVIDE_TIMER_INLINE ( efi, ticks_per_sec );