fcbe7f3246c1c201fb0247b043750bf58f9cc8ed
[people/balajirrao/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 "compiler.h"
9
10 #define BIOS_DATA_SEG 0x0040
11
12 #define CF ( 1 << 0 )
13
14 /**************************************************************************
15 CURRTICKS - Get Time
16 Use direct memory access to BIOS variables, longword 0040:006C (ticks
17 today) and byte 0040:0070 (midnight crossover flag) instead of calling
18 timeofday BIOS interrupt.
19 **************************************************************************/
20 #if defined(CONFIG_TSC_CURRTICKS)
21 #undef CONFIG_BIOS_CURRTICKS
22 #else
23 #define CONFIG_BIOS_CURRTICKS 1
24 #endif
25 #if defined(CONFIG_BIOS_CURRTICKS)
26 unsigned long currticks ( void ) {
27         static uint32_t days = 0;
28         uint32_t ticks;
29         uint8_t midnight;
30
31         /* Re-enable interrupts so that the timer interrupt can occur
32          */
33         REAL_EXEC ( rm_currticks,
34                     "sti\n\t"
35                     "nop\n\t"
36                     "nop\n\t"
37                     "cli\n\t",
38                     0,
39                     OUT_CONSTRAINTS (),
40                     IN_CONSTRAINTS (),
41                     CLOBBER ( "eax" ) ); /* can't have an empty clobber list */
42
43         get_real ( ticks, BIOS_DATA_SEG, 0x006c );
44         get_real ( midnight, BIOS_DATA_SEG, 0x0070 );
45
46         if ( midnight ) {
47                 midnight = 0;
48                 put_real ( midnight, BIOS_DATA_SEG, 0x0070 );
49                 days += 0x1800b0;
50         }
51         return ( days + ticks );
52 }
53 #endif  /* CONFIG_BIOS_CURRTICKS */
54
55 /**************************************************************************
56 CPU_NAP - Save power by halting the CPU until the next interrupt
57 **************************************************************************/
58 void cpu_nap ( void ) {
59         REAL_EXEC ( rm_cpu_nap,
60                     "sti\n\t"
61                     "hlt\n\t"
62                     "cli\n\t",
63                     0,
64                     OUT_CONSTRAINTS (),
65                     IN_CONSTRAINTS (),
66                     CLOBBER ( "eax" ) ); /* can't have an empty clobber list */
67 }
68
69 #if     (TRY_FLOPPY_FIRST > 0)
70 /**************************************************************************
71 DISK_INIT - Initialize the disk system
72 **************************************************************************/
73 void disk_init ( void ) {
74         REAL_EXEC ( rm_disk_init,
75                     "sti\n\t"
76                     "xorw %ax,%ax\n\t"
77                     "movb $0x80,%dl\n\t"
78                     "int $0x13\n\t"
79                     "cli\n\t",
80                     0,
81                     OUT_CONSTRAINTS (),
82                     IN_CONSTRAINTS (),
83                     CLOBBER ( "eax", "ebx", "ecx", "edx",
84                               "ebp", "esi", "edi" ) );
85 }
86
87 /**************************************************************************
88 DISK_READ - Read a sector from disk
89 **************************************************************************/
90 unsigned int pcbios_disk_read ( int drive, int cylinder, int head, int sector,
91                                 char *fixme_buf ) {
92         uint16_t ax, flags, discard_c, discard_d;
93         segoff_t buf = SEGOFF ( fixme_buf );
94
95         /* FIXME: buf should be passed in as a segoff_t rather than a
96          * char *
97          */
98
99         REAL_EXEC ( rm_pcbios_disk_read,
100                     "sti\n\t"
101                     "pushl %%ebx\n\t"      /* Convert %ebx to %es:bx */
102                     "popl %%bx\n\t"
103                     "popl %%es\n\t"
104                     "movb $0x02, %%ah\n\t" /* INT 13,2 - Read disk sector */
105                     "movb $0x01, %%al\n\t" /* Read one sector */
106                     "int $0x13\n\t"
107                     "pushfw\n\t"
108                     "popw %%bx\n\t"
109                     "cli\n\t",
110                     4,
111                     OUT_CONSTRAINTS ( "=a" ( ax ), "=b" ( flags ),
112                                       "=c" ( discard_c ), "=d" ( discard_d ) ),
113                     IN_CONSTRAINTS ( "c" ( ( ( cylinder & 0xff ) << 8 ) |
114                                            ( ( cylinder >> 8 ) & 0x3 ) |
115                                            sector ),
116                                      "d" ( ( head << 8 ) | drive ),
117                                      "b" ( buf ) ),
118                     CLOBBER ( "ebp", "esi", "edi" ) );
119         );
120
121         return ( flags & CF ) ? ax : 0;
122 }
123 #endif /* TRY_FLOPPY_FIRST */