Annotation of qemu/roms/ipxe/src/interface/efi/efi_timer.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (C) 2008 Michael Brown <[email protected]>.
                      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., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17:  */
                     18: 
                     19: FILE_LICENCE ( GPL2_OR_LATER );
                     20: 
                     21: #include <limits.h>
                     22: #include <assert.h>
                     23: #include <unistd.h>
                     24: #include <ipxe/timer.h>
                     25: #include <ipxe/efi/efi.h>
                     26: #include <ipxe/efi/Protocol/Cpu.h>
                     27: 
                     28: /** @file
                     29:  *
                     30:  * iPXE timer API for EFI
                     31:  *
                     32:  */
                     33: 
                     34: /** Scale factor to apply to CPU timer 0
                     35:  *
                     36:  * The timer is scaled down in order to ensure that reasonable values
                     37:  * for "number of ticks" don't exceed the size of an unsigned long.
                     38:  */
                     39: #define EFI_TIMER0_SHIFT 12
                     40: 
                     41: /** Calibration time */
                     42: #define EFI_CALIBRATE_DELAY_MS 1
                     43: 
                     44: /** CPU protocol */
                     45: static EFI_CPU_ARCH_PROTOCOL *cpu_arch;
                     46: EFI_REQUIRE_PROTOCOL ( EFI_CPU_ARCH_PROTOCOL, &cpu_arch );
                     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: 
                     57:        if ( ( efirc = bs->Stall ( usecs ) ) != 0 ) {
                     58:                DBG ( "EFI could not delay for %ldus: %s\n",
                     59:                      usecs, efi_strerror ( efirc ) );
                     60:                /* Probably screwed */
                     61:        }
                     62: }
                     63: 
                     64: /**
                     65:  * Get current system time in ticks
                     66:  *
                     67:  * @ret ticks          Current time, in ticks
                     68:  */
                     69: static unsigned long efi_currticks ( void ) {
                     70:        UINT64 time;
                     71:        EFI_STATUS efirc;
                     72: 
                     73:        /* Read CPU timer 0 (TSC) */
                     74:        if ( ( efirc = cpu_arch->GetTimerValue ( cpu_arch, 0, &time,
                     75:                                                 NULL ) ) != 0 ) {
                     76:                DBG ( "EFI could not read CPU timer: %s\n",
                     77:                      efi_strerror ( efirc ) );
                     78:                /* Probably screwed */
                     79:                return -1UL;
                     80:        }
                     81: 
                     82:        return ( time >> EFI_TIMER0_SHIFT );
                     83: }
                     84: 
                     85: /**
                     86:  * Get number of ticks per second
                     87:  *
                     88:  * @ret ticks_per_sec  Number of ticks per second
                     89:  */
                     90: static unsigned long efi_ticks_per_sec ( void ) {
                     91:        static unsigned long ticks_per_sec = 0;
                     92: 
                     93:        /* Calibrate timer, if necessary.  EFI does nominally provide
                     94:         * the timer speed via the (optional) TimerPeriod parameter to
                     95:         * the GetTimerValue() call, but it gets the speed slightly
                     96:         * wrong.  By up to three orders of magnitude.  Not helpful.
                     97:         */
                     98:        if ( ! ticks_per_sec ) {
                     99:                unsigned long start;
                    100:                unsigned long elapsed;
                    101: 
                    102:                DBG ( "Calibrating EFI timer with a %d ms delay\n",
                    103:                      EFI_CALIBRATE_DELAY_MS );
                    104:                start = currticks();
                    105:                mdelay ( EFI_CALIBRATE_DELAY_MS );
                    106:                elapsed = ( currticks() - start );
                    107:                ticks_per_sec = ( elapsed * ( 1000 / EFI_CALIBRATE_DELAY_MS ));
                    108:                DBG ( "EFI CPU timer calibrated at %ld ticks in %d ms (%ld "
                    109:                      "ticks/sec)\n", elapsed, EFI_CALIBRATE_DELAY_MS,
                    110:                      ticks_per_sec );
                    111:        }
                    112: 
                    113:        return ticks_per_sec;
                    114: }
                    115: 
                    116: PROVIDE_TIMER ( efi, udelay, efi_udelay );
                    117: PROVIDE_TIMER ( efi, currticks, efi_currticks );
                    118: PROVIDE_TIMER ( efi, ticks_per_sec, efi_ticks_per_sec );

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.