FreeBSD/Linux Kernel Cross Reference
sys/pc/apmjump.s
1 /*
2 * Far call, absolute indirect.
3 * The argument is the offset.
4 * We use a global structure for the jump params,
5 * so this is *not* reentrant or thread safe.
6 */
7
8 #include "mem.h"
9
10 #define SSOVERRIDE BYTE $0x36
11 #define CSOVERRIDE BYTE $0x2E
12 #define RETF BYTE $0xCB
13
14 GLOBL apmjumpstruct+0(SB), $8
15
16 TEXT fortytwo(SB), $0
17 MOVL $42, AX
18 RETF
19
20 TEXT getcs(SB), $0
21 PUSHL CS
22 POPL AX
23 RET
24
25 TEXT apmfarcall(SB), $0
26 /*
27 * We call push and pop ourselves.
28 * As soon as we do the first push or pop,
29 * we can't use FP anymore.
30 */
31 MOVL off+4(FP), BX
32 MOVL seg+0(FP), CX
33 MOVL BX, apmjumpstruct+0(SB)
34 MOVL CX, apmjumpstruct+4(SB)
35
36 /* load necessary registers from Ureg */
37 MOVL ureg+8(FP), DI
38 MOVL 28(DI), AX
39 MOVL 16(DI), BX
40 MOVL 24(DI), CX
41 MOVL 20(DI), DX
42
43 /* save registers, segments */
44 PUSHL DS
45 PUSHL ES
46 PUSHL FS
47 PUSHL GS
48 PUSHL BP
49 PUSHL DI
50
51 /*
52 * paranoia: zero the segments, since it's the
53 * BIOS's responsibility to initialize them.
54 * (trick picked up from Linux driver).
55 PUSHL DX
56 XORL DX, DX
57 PUSHL DX
58 POPL DS
59 PUSHL DX
60 POPL ES
61 PUSHL DX
62 POPL FS
63 PUSHL DX
64 POPL GS
65 POPL DX
66 */
67
68 PUSHL $APMDSEG
69 POPL DS
70
71 /*
72 * The actual call.
73 */
74 CSOVERRIDE; BYTE $0xFF; BYTE $0x1D
75 LONG $apmjumpstruct+0(SB)
76
77 /* restore segments, registers */
78 POPL DI
79 POPL BP
80 POPL GS
81 POPL FS
82 POPL ES
83 POPL DS
84
85 PUSHFL
86 POPL 64(DI)
87
88 /* store interesting registers back in Ureg */
89 MOVL AX, 28(DI)
90 MOVL BX, 16(DI)
91 MOVL CX, 24(DI)
92 MOVL DX, 20(DI)
93 MOVL SI, 4(DI)
94
95 PUSHFL
96 POPL AX
97 ANDL $1, AX /* carry flag */
98 RET
Cache object: 61514cd364d89b84630ef8b741436a6c
|