ebcbbc04e335f0ed24158d9678ff8564d90c69aa
[people/xl0/gpxe.git] / src / arch / i386 / firmware / pcbios / bios.c
1 /* Etherboot routines for PCBIOS firmware.
2  *
3  * Body of routines taken from old pcbios.S
4  */
5
6 #include <stdint.h>
7 #include <realmode.h>
8 #include <bios.h>
9
10 #define CF ( 1 << 0 )
11
12 /**************************************************************************
13 CURRTICKS - Get Time
14 Use direct memory access to BIOS variables, longword 0040:006C (ticks
15 today) and byte 0040:0070 (midnight crossover flag) instead of calling
16 timeofday BIOS interrupt.
17 **************************************************************************/
18 #if defined(CONFIG_TSC_CURRTICKS)
19 #undef CONFIG_BIOS_CURRTICKS
20 #else
21 #define CONFIG_BIOS_CURRTICKS 1
22 #endif
23 #if defined(CONFIG_BIOS_CURRTICKS)
24 unsigned long currticks ( void ) {
25         static uint32_t days = 0;
26         uint32_t ticks;
27         uint8_t midnight;
28
29         /* Re-enable interrupts so that the timer interrupt can occur
30          */
31         REAL_EXEC ( rm_currticks,
32                     "sti\n\t"
33                     "nop\n\t"
34                     "nop\n\t"
35                     "cli\n\t",
36                     0,
37                     OUT_CONSTRAINTS (),
38                     IN_CONSTRAINTS (),
39                     CLOBBER ( "eax" ) ); /* can't have an empty clobber list */
40
41         get_real ( ticks, BDA_SEG, 0x006c );
42         get_real ( midnight, BDA_SEG, 0x0070 );
43
44         if ( midnight ) {
45                 midnight = 0;
46                 put_real ( midnight, BDA_SEG, 0x0070 );
47                 days += 0x1800b0;
48         }
49         return ( days + ticks );
50 }
51 #endif  /* CONFIG_BIOS_CURRTICKS */
52
53 /**************************************************************************
54 CPU_NAP - Save power by halting the CPU until the next interrupt
55 **************************************************************************/
56 void cpu_nap ( void ) {
57         REAL_EXEC ( rm_cpu_nap,
58                     "sti\n\t"
59                     "hlt\n\t"
60                     "cli\n\t",
61                     0,
62                     OUT_CONSTRAINTS (),
63                     IN_CONSTRAINTS (),
64                     CLOBBER ( "eax" ) ); /* can't have an empty clobber list */
65 }