summaryrefslogtreecommitdiffstats
path: root/bsps/i386/pc386/start/start16.S
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/i386/pc386/start/start16.S')
-rw-r--r--bsps/i386/pc386/start/start16.S254
1 files changed, 254 insertions, 0 deletions
diff --git a/bsps/i386/pc386/start/start16.S b/bsps/i386/pc386/start/start16.S
new file mode 100644
index 0000000000..3d46f40ed6
--- /dev/null
+++ b/bsps/i386/pc386/start/start16.S
@@ -0,0 +1,254 @@
+/*--------------------------------------------------------------------------+
+ * start16.s v1.0 - PC386 BSP - 1998/04/13
+ *--------------------------------------------------------------------------+
+ * This file contains the entry point for the application.
+ * The name of this entry point is compiler dependent.
+ * It jumps to the BSP which is responsible for performing all initialization.
+ *--------------------------------------------------------------------------+
+ * (C) Copyright 1997 -
+ * - NavIST Group - Real-Time Distributed Systems and Industrial Automation
+ *
+ * http://pandora.ist.utl.pt
+ *
+ * Instituto Superior Tecnico * Lisboa * PORTUGAL
+ *--------------------------------------------------------------------------+
+ * Disclaimer:
+ *
+ * This file is provided "AS IS" without warranty of any kind, either
+ * expressed or implied.
+ *--------------------------------------------------------------------------+
+ */
+
+/*
+ * COPYRIGHT (c) 2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+
+#include <bspopts.h>
+
+/*---------------------------------------------------------------------------+
+| Constants
++----------------------------------------------------------------------------*/
+
+#if defined(SMP_SECONDARY_CORE)
+.set PROT_CODE_SEG, 0x08 # offset of code segment descriptor into GDT
+#else
+.set PROT_CODE_SEG, 0x0 # offset of code segment descriptor into GDT
+#endif
+
+.set PROT_DATA_SEG, 0x10 # offset of code segment descriptor into GDT
+.set CR0_PE, 1 # protected mode flag on CR0 register
+.set HDRSTART, HEADERADDR # address of start of bin2boot header
+.set HDROFF, 0x24 # offset into bin2boot header of start32 addr
+.set STACKOFF, 0x200-0x10 # offset to load into %esp, from start of image
+
+/* #define NEW_GAS */
+#ifdef NEW_GAS
+ #define LJMPL ljmpl
+#else
+ #define LJMPL ljmp
+#endif
+
+/*----------------------------------------------------------------------------+
+| CODE section
++----------------------------------------------------------------------------*/
+
+.text
+#if defined(SMP_SECONDARY_CORE)
+ .globl app_processor_start # entry point
+app_processor_start:
+#else
+ .globl _start16 # entry point
+ .globl start16
+start16:
+_start16:
+#endif
+
+.code16
+ cli # DISABLE INTERRUPTS!!!
+#if defined(SMP_SECONDARY_CORE)
+ jmp 1f
+ .align 4
+app_cpu_start:
+ .long 0
+app_cpu_stack:
+ .long 0
+1:
+#endif
+ movw %cs, %ax # Initialize the rest of
+ movw %ax, %ds # segment registers
+ movw %ax, %es
+ movw %ax, %ss
+
+#if !defined(SMP_SECONDARY_CODE) && (RTEMS_VIDEO_80x50 == 1)
+ movl $0x0040,%eax # use 32 bit constant to ensure 16 MSB=0
+ mov %ax,%es
+ movw %es:0x4a, %ax # get 16 bit number of columns
+ cmpw $0, %ax # or 0 if no video adapter
+ je 1f # if no video, skip touching it
+ /*---------------------------------------------------------------------+
+ | Switch VGA video to 80 lines x 50 columns mode. Has to be done before
+ | turning protected mode on since it uses BIOS int 10h (video) services.
+ +---------------------------------------------------------------------*/
+
+ movw $0x0003, %ax # forced set
+ int $0x10
+ movw $0x1112, %ax # use 8x8 font
+ xorb %bl, %bl
+ int $0x10
+ movw $0x1201, %ax # turn off cursor emulation
+ movb $0x34, %bl
+ int $0x10
+ movb $0x01, %ah # define cursor (scan lines 0 to 7)
+ movw $0x0007, %cx
+ int $0x10
+1:
+#endif /* !SMP_SECONDARY_CODE and RTEMS_VIDEO_80x50 */
+
+ /*---------------------------------------------------------------------+
+ | Bare PC machines boot in real mode! We have to turn protected mode on.
+ +---------------------------------------------------------------------*/
+
+#if defined(SMP_SECONDARY_CORE)
+ lgdt gdtptr - app_processor_start # load Global Descriptor Table
+#else
+ lgdt gdtptr - start16 # load Global Descriptor Table
+#endif /* SMP_SECONDARY_CORE */
+
+ movl %cr0, %eax
+ orl $CR0_PE, %eax
+ movl %eax, %cr0 # turn on protected mode
+#if defined(SMP_SECONDARY_CORE)
+ LJMPL $PROT_CODE_SEG, $2f # flush prefetch queue, and reload %cs
+#else
+ LJMPL $PROT_CODE_SEG, $2f # flush prefetch queue, and reload %cs
+#endif
+.code32
+2:
+
+ /*---------------------------------------------------------------------+
+ | load the other segment registers
+ +---------------------------------------------------------------------*/
+ movl $PROT_DATA_SEG, %eax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+#if defined(SMP_SECONDARY_CORE)
+ movl app_cpu_stack, %esp # stack pointer
+ movl app_cpu_stack, %ebp # base pointer
+ #else
+ movl $start16 + STACKOFF, %esp # set up stack pointer
+ addl $start16 + STACKOFF, %ebp # set up stack pointer
+#endif /* SMP_SECONDARY_CORE */
+
+ /*---------------------------------------------------------------------+
+ | we have to enable A20 in order to access memory above 1MByte
+ +---------------------------------------------------------------------*/
+ call empty_8042
+ movb $0xD1, %al # command write
+ outb %al, $0x64
+ call empty_8042
+ movb $0xDF, %al # A20 on
+ outb %al, $0x60
+ call empty_8042
+
+ call pc386_delay
+ call pc386_delay
+ call pc386_delay
+
+#if defined(SMP_SECONDARY_CORE)
+ movl app_cpu_start, %eax # jump to app CPU start
+#else
+ movl %cs:HDRSTART + HDROFF, %eax # jump to start of 32 bit code
+#endif /* SMP_SECONDARY_CORE */
+ pushl %eax
+ ret
+
+
+/*----------------------------------------------------------------------------+
+| pc386_delay
++------------------------------------------------------------------------------
+| Delay is needed after doing I/O.
+|
+| The outb version is OK on most machines BUT the loop version ...
+|
+| will delay for 1us on 1Gz machine, it will take a little bit
+| longer on slower machines, however, it does not matter because we
+| are going to call this function only a few times
+!
+| NOTE: Saving the content of the EAX register just in case. - Rosimildo.
++----------------------------------------------------------------------------*/
+ .p2align 4
+ .globl _pc386_delay
+ .globl pc386_delay
+pc386_delay:
+_pc386_delay:
+ pushl %eax
+#if defined(USE_OUTB_FOR_DELAY)
+ outb %al, $0x80 # about 1uS delay on most machines
+
+#else
+
+ movl $0x200, %eax
+pc386_delay1:
+ dec %eax
+ jnz pc386_delay1
+#endif
+ popl %eax
+ ret
+
+/*----------------------------------------------------------------------------+
+| empty_8042
++------------------------------------------------------------------------------
+| This routine checks that the keyboard command queue is empty (after emptying
+| the output buffers).
+| No timeout is used - if this hangs there is something wrong with the machine,
+| and we probably couldn't proceed anyway.
++----------------------------------------------------------------------------*/
+ .p2align 4
+ .globl _empty_8042
+ .globl empty_8042
+empty_8042:
+_empty_8042:
+ call pc386_delay
+ inb $0x64, %al # 8042 status port
+ testb $0x01, %al # output buffer?
+ jz no_output
+ call pc386_delay
+ in $0x60, %al # read it
+ jmp empty_8042
+no_output:
+ test $0x02, %al # is input buffer full?
+ jnz empty_8042 # yes - loop
+ ret
+
+/*----------------------------------------------------------------------------+
+| DATA section
++----------------------------------------------------------------------------*/
+
+/**************************
+* GLOBAL DESCRIPTOR TABLE *
+**************************/
+
+ .p2align 4
+gdtptr:
+ /* we use the NULL descriptor to store the GDT pointer - a trick quite
+ nifty due to: Robert Collins (rcollins@x86.org) */
+ .word gdtlen - 1
+ .long gdtptr
+ .word 0x0000
+
+ /* code segment */
+ .word 0xffff, 0
+ .byte 0, 0x9f, 0xcf, 0
+
+ /* data segment */
+ .word 0xffff, 0
+ .byte 0, 0x93, 0xcf, 0
+
+ .set gdtlen, . - gdtptr # length of GDT