mirror of https://github.com/ipxe/ipxe.git
58 lines
1.2 KiB
C
58 lines
1.2 KiB
C
/*
|
|
* Etherboot routines for PCBIOS firmware.
|
|
*
|
|
* Body of routines taken from old pcbios.S
|
|
*/
|
|
|
|
#include <gpxe/init.h>
|
|
#include <gpxe/timer.h>
|
|
#include <stdio.h>
|
|
#include <realmode.h>
|
|
#include <bios.h>
|
|
#include <bits/timer2.h>
|
|
|
|
/* A bit faster actually, but we don't care. */
|
|
#define TIMER2_TICKS_PER_SEC 18
|
|
|
|
/*
|
|
* Use direct memory access to BIOS variables, longword 0040:006C (ticks
|
|
* today) and byte 0040:0070 (midnight crossover flag) instead of calling
|
|
* timeofday BIOS interrupt.
|
|
*/
|
|
|
|
static tick_t bios_currticks ( void ) {
|
|
static int days = 0;
|
|
uint32_t ticks;
|
|
uint8_t midnight;
|
|
|
|
/* Re-enable interrupts so that the timer interrupt can occur */
|
|
__asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
|
|
"nop\n\t"
|
|
"nop\n\t"
|
|
"cli\n\t" ) : : );
|
|
|
|
get_real ( ticks, BDA_SEG, 0x006c );
|
|
get_real ( midnight, BDA_SEG, 0x0070 );
|
|
|
|
if ( midnight ) {
|
|
midnight = 0;
|
|
put_real ( midnight, BDA_SEG, 0x0070 );
|
|
days += 0x1800b0;
|
|
}
|
|
|
|
return ( (days + ticks) * (USECS_IN_SEC / TIMER2_TICKS_PER_SEC) );
|
|
}
|
|
|
|
static int bios_ts_init(void)
|
|
{
|
|
DBG("BIOS timer installed\n");
|
|
return 0;
|
|
}
|
|
|
|
struct timer bios_ts __timer ( 02 ) = {
|
|
.init = bios_ts_init,
|
|
.udelay = i386_timer2_udelay,
|
|
.currticks = bios_currticks,
|
|
};
|
|
|