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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
|
/*
* Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@jp.FreeBSD.org>
* Copyright (C) 1997 by Poul-Henning Kamp <phk@FreeBSD.org>
*
* This software may be used, modified, copied, distributed, and sold,
* in both source and binary form provided that the above copyright and
* these terms are retained. Under no circumstances is the author
* responsible for the proper functioning of this software, nor does
* the author assume any responsibility for damages incurred with its
* use.
*
* Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
*
* $Id: apm_setup.s,v 1.12 1997/11/04 18:12:45 nate Exp $
*/
#include "apm.h"
#if NAPM > 0
#define ASSEMBLER
#include "assym.s" /* system definitions */
#include <machine/asmacros.h> /* miscellaneous asm macros */
#include <machine/apm_bios.h>
#include <machine/apm_segments.h>
#define PADDR(addr) addr-KERNBASE
.file "apm_setup.s"
.data
_apm_init_image:
.globl _apm_init_image
1:
#include "i386/apm/apm_init/apm_init.inc"
2:
_apm_init_image_size:
.globl _apm_init_image_size
.long 2b - 1b
_apm_version:
.globl _apm_version
.long 0
_apm_cs_entry:
.globl _apm_cs_entry
.long 0
_apm_cs16_base:
.globl _apm_cs16_base
.word 0
_apm_cs32_base:
.globl _apm_cs32_base
.word 0
_apm_ds_base:
.globl _apm_ds_base
.word 0
_apm_cs32_limit:
.globl _apm_cs32_limit
.word 0
_apm_cs16_limit:
.globl _apm_cs16_limit
.word 0
_apm_ds_limit:
.globl _apm_ds_limit
.word 0
_apm_flags:
.globl _apm_flags
.word 0
.globl _apm_current_gdt_pdesc /* current GDT pseudo desc. */
_apm_current_gdt_pdesc:
.word 0, 0, 0
.globl _bootstrap_gdt
_bootstrap_gdt:
.space SIZEOF_GDT*BOOTSTRAP_GDT_NUM
.text
_apm_setup:
.globl _apm_setup
/*
* Setup APM BIOS:
*
* APM BIOS initialization should be done from real mode or V86 mode.
*
* (by HOSOKAWA, Tatsumi <hosokawa@jp.FreeBSD.org>)
*/
/*
* Don't trust the value of %fs and %gs (some AT-compatible BIOS
* implementations leave junk values in these segment registers
* on bootstrap)
*/
xorl %eax, %eax /* null selector */
movw %ax, %fs
movw %ax, %gs
/*
* Copy APM initializer under 1MB boundary:
*
* APM initializer program must switch the CPU to real mode.
* But FreeBSD kernel runs above 1MB boundary. So we must
* copy the initializer code to conventional memory.
*/
movl PADDR(_apm_init_image_size), %ecx /* size */
lea PADDR(_apm_init_image), %esi /* source */
movl $ APM_OURADDR, %edi /* destination */
cld
rep
movsb
/* get GDT base */
sgdt PADDR(_apm_current_gdt_pdesc)
/* copy GDT to _bootstrap_gdt */
xorl %ecx, %ecx
movw PADDR(_apm_current_gdt_pdesc), %cx
movl PADDR(_apm_current_gdt_pdesc + 2), %esi
lea PADDR(_bootstrap_gdt), %edi
cld
rep
movsb
/* setup GDT pseudo descriptor */
movw $(SIZEOF_GDT*BOOTSTRAP_GDT_NUM), %ax
movw %ax, PADDR(_apm_current_gdt_pdesc)
leal PADDR(_bootstrap_gdt), %eax
movl %eax, PADDR(_apm_current_gdt_pdesc + 2)
/* load new GDTR */
lgdt PADDR(_apm_current_gdt_pdesc)
/* setup GDT for APM initializer */
lea PADDR(_bootstrap_gdt), %ecx
movl $(APM_OURADDR), %eax /* use %ax for 15..0 */
movl %eax, %ebx
shrl $16, %ebx /* use %bl for 23..16 */
/* use %bh for 31..24 */
#define APM_SETUP_GDT(index, attrib) \
movl $(index), %si ; \
lea 0(%ecx,%esi,8), %edx ; \
movw $0xffff, (%edx) ; \
movw %ax, 2(%edx) ; \
movb %bl, 4(%edx) ; \
movw $(attrib), 5(%edx) ; \
movb %bh, 7(%edx)
APM_SETUP_GDT(APM_INIT_CS_INDEX , CS32_ATTRIB)
APM_SETUP_GDT(APM_INIT_DS_INDEX , DS32_ATTRIB)
APM_SETUP_GDT(APM_INIT_CS16_INDEX, CS16_ATTRIB)
APM_SETUP_GDT(APM_INIT_DS16_INDEX, DS16_ATTRIB)
/*
* Call the initializer:
*
* direct intersegment call to conventional memory code
*/
.byte 0x9a /* actually, lcall $APM_INIT_CS_SEL, $0 */
.long 0
.word APM_INIT_CS_SEL
movl %eax, PADDR(_apm_version)
movl %ebx, PADDR(_apm_cs_entry)
movw %cx, PADDR(_apm_cs16_base)
shrl $16, %ecx
movw %cx, PADDR(_apm_cs32_base)
movw %dx, PADDR(_apm_ds_base)
movw %si, PADDR(_apm_cs32_limit)
shrl $16, %esi
movw %si, PADDR(_apm_ds_limit)
movw %di, PADDR(_apm_flags)
ret
.text
.align 2
.globl _apm_bios_call
_apm_bios_call:
pushl %ebp
movl 8(%esp),%ebp
pushl %esi
pushl %edi
pushl %ebx
movl 20(%ebp),%edi
movl 16(%ebp),%esi
movl 12(%ebp),%edx
movl 8(%ebp),%ecx
movl 4(%ebp),%ebx
movl 0(%ebp),%eax
pushl %ebp
lcall _apm_addr
popl %ebp
movl %eax,0(%ebp)
jc 1f
xorl %eax,%eax
jz 2f
1: movl $1, %eax
2: movl %ebx,4(%ebp)
movl %ecx,8(%ebp)
movl %edx,12(%ebp)
movl %esi,16(%ebp)
movl %edi,20(%ebp)
popl %ebx
popl %edi
popl %esi
popl %ebp
ret
#endif NAPM > 0
|