Home | History | Annotate | Download | only in pcbios
      1 /*
      2  * Copyright (C) 2008 Michael Brown <mbrown (at) 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., 675 Mass Ave, Cambridge, MA 02139, USA.
     17  */
     18 
     19 FILE_LICENCE ( GPL2_OR_LATER );
     20 
     21 /** @file
     22  *
     23  * BIOS timer
     24  *
     25  */
     26 
     27 #include <gpxe/timer.h>
     28 #include <realmode.h>
     29 #include <bios.h>
     30 
     31 /**
     32  * Get current system time in ticks
     33  *
     34  * @ret ticks		Current time, in ticks
     35  *
     36  * Use direct memory access to BIOS variables, longword 0040:006C
     37  * (ticks today) and byte 0040:0070 (midnight crossover flag) instead
     38  * of calling timeofday BIOS interrupt.
     39  */
     40 static unsigned long bios_currticks ( void ) {
     41 	static int days = 0;
     42 	uint32_t ticks;
     43 	uint8_t midnight;
     44 
     45 	/* Re-enable interrupts so that the timer interrupt can occur */
     46 	__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
     47 					   "nop\n\t"
     48 					   "nop\n\t"
     49 					   "cli\n\t" ) : : );
     50 
     51 	get_real ( ticks, BDA_SEG, 0x006c );
     52 	get_real ( midnight, BDA_SEG, 0x0070 );
     53 
     54 	if ( midnight ) {
     55 		midnight = 0;
     56 		put_real ( midnight, BDA_SEG, 0x0070 );
     57 		days += 0x1800b0;
     58 	}
     59 
     60 	return ( days + ticks );
     61 }
     62 
     63 PROVIDE_TIMER_INLINE ( pcbios, udelay );
     64 PROVIDE_TIMER ( pcbios, currticks, bios_currticks );
     65 PROVIDE_TIMER_INLINE ( pcbios, ticks_per_sec );
     66