aboutsummaryrefslogtreecommitdiffstats
path: root/src/util.h
blob: 36e9a30594e44c00cc70c7156267ead172a71e88 (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
// 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 nop(void)
{
    asm volatile("nop");
}

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

#define BX_PANIC(fmt, args...) bprintf(0, fmt , ##args)
#define BX_INFO(fmt, args...) bprintf(0, fmt , ##args)

static inline void
memset(void *s, int c, size_t n)
{
    while (n)
        ((char *)s)[--n] = c;
}

static inline void *
memcpy(void *d1, const void *s1, size_t len)
{
    u8 *d = d1;
    const u8 *s = s1;

    while (len--) {
        *d++ = *s++;
    }
    return d1;
}

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();
}

static inline
void call16(struct bregs *callregs)
{
    asm volatile(
        "pushl %%ebp\n" // Save state
        "pushfl\n"
#ifdef MODE16
        "calll __call16\n"
#else
        "calll __call16_from32\n"
#endif
        "popfl\n"       // Restore state
        "popl %%ebp\n"
        : "+a" (callregs), "+m" (*callregs)
        :
        : "ebx", "ecx", "edx", "esi", "edi");
}

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), (u16)&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 bprintf(u16 action, const char *fmt, ...)
    __attribute__ ((format (printf, 2, 3)));
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, struct bregs *regs);
#define debug_enter(regs) \
    __debug_enter(__func__, regs)
#define debug_stub(regs) \
    __debug_stub(__func__, regs)
#define debug_isr(regs) \
    __debug_isr(__func__, regs)
#define printf(fmt, args...)                     \
    bprintf(1, fmt , ##args )

// 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);
}

#define set_fail(regs) do {                     \
        __debug_fail(__func__, (regs));         \
        set_cf((regs), 1);                      \
    } while (0)

#define set_code_fail(regs, code) do {          \
        set_fail(regs);                         \
        (regs)->ah = (code);                    \
    } while (0)

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

// clock.c
void handle_1583(struct bregs *regs);

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

// util.c
void usleep(u32 count);

// rombios32.c
void rombios32_init(void);

#endif // util.h