aboutsummaryrefslogtreecommitdiff
path: root/src/util.h
blob: 6689b062a90f2f3b571d409c380e221dbe59728b (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
// 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");
}

#define DEBUGF(fmt, args...) bprintf(0, fmt , ##args)
#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
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 = 0xf000;
    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_exit(const char *fname, struct bregs *regs);
void __debug_stub(const char *fname, struct bregs *regs);
#define debug_enter(regs) \
    __debug_enter(__func__, regs)
#define debug_exit(regs) \
    __debug_exit(__func__, regs)
#define debug_stub(regs) \
    __debug_stub(__func__, regs)
#define printf(fmt, args...)                     \
    bprintf(1, fmt , ##args )

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

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

// Frequent bios return helper
#define RET_EUNSUPPORTED 0x86
static inline void
handle_ret(struct bregs *regs, u8 code)
{
    regs->ah = code;
    set_cf(regs, code);
}

#endif // util.h