aboutsummaryrefslogtreecommitdiff
path: root/src/util.h
blob: 11ca26972f48056c70c69a972e2d380af9c1cb57 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Basic x86 asm functions and function defs.
//
// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU GPLv3 license.
#ifndef __UTIL_H
#define __UTIL_H

#include "ioport.h" // outb
#include "biosvar.h" // struct bregs

static inline void irq_disable(void)
{
    asm volatile("cli": : :"memory");
}

static inline void irq_enable(void)
{
    asm volatile("sti": : :"memory");
}

static inline unsigned long irq_save(void)
{
    unsigned long flags;
    asm volatile("pushfl ; popl %0" : "=g" (flags));
    irq_disable();
    return flags;
}

static inline void irq_restore(unsigned long flags)
{
    asm volatile("pushl %0 ; popfl" : : "g" (flags) : "memory", "cc");
}

static inline void cpu_relax(void)
{
    asm volatile("rep ; nop": : :"memory");
}

static inline void nop(void)
{
    asm volatile("nop");
}

static inline void hlt(void)
{
    asm volatile("hlt");
}

void *memset(void *s, int c, size_t n);
void *memcpy(void *d1, const void *s1, size_t len);

static inline void
eoi_master_pic()
{
    outb(PIC1_IRQ5, PORT_PIC1);
}

static inline void
eoi_both_pics()
{
    outb(PIC2_IRQ13, PORT_PIC2);
    eoi_master_pic();
}

// Call a function with a specified register state.  Note that on
// return, the interrupt enable/disable flag may be altered.
static inline
void call16(struct bregs *callregs)
{
    asm volatile(
#ifdef MODE16
        "calll __call16\n"
#else
        "calll __call16_from32\n"
#endif
        : "+a" (callregs), "+m" (*callregs)
        :
        : "ebx", "ecx", "edx", "esi", "edi", "ebp", "cc");
}

static inline
void __call16_int(struct bregs *callregs, u16 offset)
{
    callregs->cs = SEG_BIOS;
    callregs->ip = offset;
    call16(callregs);
}

#ifdef MODE16
#define call16_int(nr, callregs) do {                           \
        extern void irq_trampoline_ ##nr ();                    \
        __call16_int((callregs), (u32)&irq_trampoline_ ##nr );  \
    } while (0)
#else
#include "../out/rom16.offset.auto.h"
#define call16_int(nr, callregs)                                \
    __call16_int((callregs), OFFSET_irq_trampoline_ ##nr )
#endif

// output.c
void BX_PANIC(const char *fmt, ...)
    __attribute__ ((format (printf, 1, 2)))
    __attribute__ ((noreturn));
void printf(const char *fmt, ...)
    __attribute__ ((format (printf, 1, 2)));
void __dprintf(const char *fmt, ...)
    __attribute__ ((format (printf, 1, 2)));
#define dprintf(lvl, fmt, args...) do {                         \
        if (CONFIG_DEBUG_LEVEL && (lvl) <= CONFIG_DEBUG_LEVEL)  \
            __dprintf((fmt) , ##args );                         \
    } while (0)
void __debug_enter(const char *fname, struct bregs *regs);
void __debug_fail(const char *fname, struct bregs *regs);
void __debug_stub(const char *fname, struct bregs *regs);
void __debug_isr(const char *fname);
#define debug_enter(regs) \
    __debug_enter(__func__, regs)
#define debug_stub(regs) \
    __debug_stub(__func__, regs)
#define debug_isr(regs) \
    __debug_isr(__func__)

// Frequently used return codes
#define RET_EUNSUPPORTED 0x86
static inline void
set_success(struct bregs *regs)
{
    set_cf(regs, 0);
}

static inline void
set_code_success(struct bregs *regs)
{
    regs->ah = 0;
    set_cf(regs, 0);
}

void __set_fail(const char *fname, struct bregs *regs);
void __set_code_fail(const char *fname, struct bregs *regs, u8 code);

#define set_fail(regs) \
    __set_fail(__func__, (regs))
#define set_code_fail(regs, code)               \
    __set_code_fail(__func__, (regs), (code))

// kbd.c
void handle_15c2(struct bregs *regs);

// serial.c
void serial_setup();
void debug_serial_setup();
void debug_serial(char c);
void lpt_setup();

// clock.c
void timer_setup();
int usleep(u32 count);
void handle_1583(struct bregs *regs);
void handle_1586(struct bregs *regs);

// apm.c
void VISIBLE16 handle_1553(struct bregs *regs);

// pcibios.c
void handle_1ab1(struct bregs *regs);

// util.c
u8 checksum(u8 *far_data, u32 len);

// rombios32.c
void rombios32_init(void);

// boot.c
void printf_bootdev(u16 bootdev);

// post_menu.c
void interactive_bootmenu();

#endif // util.h