summaryrefslogtreecommitdiffstats
path: root/sys/i386/bios/apm_setup.s
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i386/bios/apm_setup.s')
-rw-r--r--sys/i386/bios/apm_setup.s134
1 files changed, 129 insertions, 5 deletions
diff --git a/sys/i386/bios/apm_setup.s b/sys/i386/bios/apm_setup.s
index d354679..b3ae77d 100644
--- a/sys/i386/bios/apm_setup.s
+++ b/sys/i386/bios/apm_setup.s
@@ -12,14 +12,29 @@
*
* Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
*
- * $Id: apm_setup.s,v 1.3 1994/10/02 01:45:42 phk Exp $
+ * $Id: apm_setup.s,v 1.4 1994/10/10 01:14:03 phk Exp $
*/
-#define ASM
+#include "apm.h"
+
+#if NAPM > 0
-#include <machine/asmacros.h>
-#include "assym.s"
+#ifdef __FreeBSD__
+#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
+#endif /* __FreeBSD__ */
+
+#ifdef MACH_KERNEL
+#define ASSEMBLER
+#include "assym.s"
+#include "i386at/apm_bios.h"
+#include "i386at/apm_segments.h"
+#define PADDR(addr) addr-KERNELBASE
+#endif /* MACH_KERNEL */
.file "apm_setup.s"
@@ -28,7 +43,12 @@ _apm_init_image:
.globl _apm_init_image
1:
-#include "apm_init/apm_init.inc"
+#ifdef __FreeBSD__
+#include "i386/apm/apm_init/apm_init.inc"
+#endif /* __FreeBSD__ */
+#ifdef MACH_KERNEL
+#include "i386at/apm_init/apm_init.inc"
+#endif /* MACH_KERNEL */
2:
_apm_init_image_size:
@@ -66,4 +86,108 @@ _apm_ds_limit:
_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@mt.cs.keio.ac.jp>)
+ */
+
+ /*
+ * 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)
+
+ /*
+ * 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_cs32_base)
+ shrl $16, %ecx
+ movw %cx, PADDR(_apm_cs16_base)
+ movw %dx, PADDR(_apm_ds_base)
+ movw %si, PADDR(_apm_cs_limit)
+ shrl $16, %esi
+ movw %si, PADDR(_apm_ds_limit)
+ movw %di, PADDR(_apm_flags)
+ ret
+#endif NAPM > 0
OpenPOWER on IntegriCloud