Annotation of qemu/roms/ipxe/src/interface/efi/efi_timer.c, revision 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.