summaryrefslogtreecommitdiff
path: root/vgasrc/vgaentry.S
blob: f9624fce2ed9c570d6283b2905f46db52d842599 (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
// Rom layout and bios assembler to C interface.
//
// Copyright (C) 2009-2013  Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.


#include "asm-offsets.h" // BREGS_*
#include "config.h" // CONFIG_*
#include "entryfuncs.S" // ENTRY_*


/****************************************************************
 * Rom Header
 ****************************************************************/

        .section .rom.header
        .code16
        .global _rom_header, _rom_header_size, _rom_header_checksum
_rom_header:
        .word 0xaa55
_rom_header_size:
        .byte 0
_rom_header_entry:
        jmp _optionrom_entry
_rom_header_checksum:
        .byte 0
_rom_header_other:
        .space 17
_rom_header_pcidata:
#if CONFIG_VGA_PCI == 1
        .word rom_pci_data
#else
        .word 0
#endif
_rom_header_pnpdata:
        .word 0
_rom_header_other2:
        .word 0
_rom_header_signature:
        .asciz "IBM"

#if CONFIG_VGA_ATI
#include "ati-tables.S"
#endif

/****************************************************************
 * Entry points
 ****************************************************************/

        // This macro implements a call while avoiding instructions
        // that old versions of x86emu have problems with.
        .macro VGA_CALLL cfunc
#if CONFIG_VGA_FIXUP_ASM
        pushw %ax
        callw \cfunc
#else
        calll \cfunc
#endif
        .endm

        // This macro is the same as ENTRY_ARG except VGA_CALLL is used.
        .macro ENTRY_ARG_VGA cfunc
        cli
        cld
        PUSHBREGS
        movw %ss, %ax           // Move %ss to %ds
        movw %ax, %ds
        movl %esp, %ebx         // Backup %esp, then zero high bits
        movzwl %sp, %esp
        movl %esp, %eax         // First arg is pointer to struct bregs
        VGA_CALLL \cfunc
        movl %ebx, %esp         // Restore %esp (including high bits)
        POPBREGS
        .endm

        DECLFUNC entry_104f05
entry_104f05:
        ENTRY_ARG_VGA vbe_104f05
        lretw

        DECLFUNC _optionrom_entry
_optionrom_entry:
        ENTRY_ARG_VGA vga_post
        lretw

        DECLFUNC entry_10
entry_10:
        ENTRY_ARG_VGA handle_10
        iretw

#define VGA_CUSTOM_BDA_FLAGS 0xb9
#define BF_EXTRA_STACK 0x40

        // Entry point using extra stack
        DECLFUNC entry_10_extrastack
entry_10_extrastack:
        cli
        cld
        pushw %ds
        pushl %eax

        movw $SEG_BDA, %ax      // Check if extra stack is enabled
        movw %ax, %ds
        testb $BF_EXTRA_STACK, VGA_CUSTOM_BDA_FLAGS
        jz 1f

        movw %cs:ExtraStackSeg, %ds // Set %ds:%eax to space on ExtraStack
        movl $(CONFIG_VGA_EXTRA_STACK_SIZE-PUSHBREGS_size-16), %eax
        SAVEBREGS_POP_DSEAX     // Save registers on extra stack
        movl %esp, PUSHBREGS_size+8(%eax)
        movw %ss, PUSHBREGS_size+12(%eax)
        popl BREGS_code(%eax)
        popw BREGS_flags(%eax)

        movw %ds, %dx           // Setup %ss/%esp and call function
        movw %dx, %ss
        movl %eax, %esp
        VGA_CALLL handle_10

        movl %esp, %eax         // Restore registers and return
        movw PUSHBREGS_size+12(%eax), %ss
        movl PUSHBREGS_size+8(%eax), %esp
        popl %edx
        popw %dx
        pushw BREGS_flags(%eax)
        pushl BREGS_code(%eax)
        RESTOREBREGS_DSEAX
        iretw

1:      // Use regular entry point if the extra stack is disabled
        popl %eax
        popw %ds
        jmp entry_10

        // Timer irq handling
        DECLFUNC entry_timer_hook
entry_timer_hook:
        ENTRY handle_timer_hook
        ljmpw *%cs:Timer_Hook_Resume

        // Timer irq handling on extra stack
        DECLFUNC entry_timer_hook_extrastack
entry_timer_hook_extrastack:
        cli
        cld
        pushw %ds               // Set %ds:%eax to space on ExtraStack
        pushl %eax
        movw %cs:ExtraStackSeg, %ds
        movl $(CONFIG_VGA_EXTRA_STACK_SIZE-PUSHBREGS_size-8), %eax
        SAVEBREGS_POP_DSEAX
        movl %esp, PUSHBREGS_size(%eax)
        movw %ss, PUSHBREGS_size+4(%eax)

        movw %ds, %dx           // Setup %ss/%esp and call function
        movw %dx, %ss
        movl %eax, %esp
        calll handle_timer_hook

        movl %esp, %eax         // Restore registers and return
        movw PUSHBREGS_size+4(%eax), %ss
        movl PUSHBREGS_size(%eax), %esp
        RESTOREBREGS_DSEAX
        ljmpw *%cs:Timer_Hook_Resume