source: rtems/c/src/lib/libbsp/i386/pc386/start/start16.S @ 441b90e

4.115
Last change on this file since 441b90e was 8a7ed82, checked in by Jennifer Averett <Jennifer.Averett@…>, on Aug 1, 2011 at 1:41:37 PM

2011-08-01 Jennifer Averett <Jennifer.Averett@…>

PR 1802

  • Makefile.am, configure.ac, preinstall.am, clock/ckinit.c, start/start16.S, startup/bspstart.c, startup/ldsegs.S: Add SMP support for i386.
  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*--------------------------------------------------------------------------+
2 * start16.s v1.0 - PC386 BSP - 1998/04/13
3 *--------------------------------------------------------------------------+
4 * This file contains the entry point for the application.
5 * The name of this entry point is compiler dependent.
6 * It jumps to the BSP which is responsible for performing all initialization.
7 *--------------------------------------------------------------------------+
8 * (C) Copyright 1997 -
9 * - NavIST Group - Real-Time Distributed Systems and Industrial Automation
10 *
11 * http://pandora.ist.utl.pt
12 *
13 * Instituto Superior Tecnico * Lisboa * PORTUGAL
14 *--------------------------------------------------------------------------+
15 * Disclaimer:
16 *
17 * This file is provided "AS IS" without warranty of any kind, either
18 * expressed or implied.
19 *--------------------------------------------------------------------------+
20 */
21
22/*
23 *  COPYRIGHT (c) 2011.
24 *  On-Line Applications Research Corporation (OAR).
25 *
26 *  The license and distribution terms for this file may be
27 *  found in the file LICENSE in this distribution or at
28 *  http://www.rtems.com/license/LICENSE.
29 *
30 *  $Id$
31 */
32
33
34#include <bspopts.h>
35
36/*---------------------------------------------------------------------------+
37| Constants
38+----------------------------------------------------------------------------*/
39
40#if defined(SMP_SECONDARY_CORE)
41.set PROT_CODE_SEG, 0x08        # offset of code segment descriptor into GDT
42#else
43.set PROT_CODE_SEG, 0x0         # offset of code segment descriptor into GDT
44#endif
45
46.set PROT_DATA_SEG, 0x10        # offset of code segment descriptor into GDT
47.set CR0_PE,        1           # protected mode flag on CR0 register
48.set HDRSTART,      HEADERADDR  # address of start of bin2boot header
49.set HDROFF,        0x24        # offset into bin2boot header of start32 addr
50.set STACKOFF,      0x200-0x10  # offset to load into %esp, from start of image
51
52/* #define NEW_GAS */
53#ifdef NEW_GAS
54  #define LJMPL ljmpl
55#else
56  #define LJMPL ljmp
57#endif
58
59/*----------------------------------------------------------------------------+
60| CODE section
61+----------------------------------------------------------------------------*/
62
63.text
64#if defined(SMP_SECONDARY_CORE)
65        .globl app_processor_start                # entry point
66app_processor_start:
67#else
68        .globl _start16         # entry point
69        .globl start16
70start16:
71_start16:
72#endif
73
74.code16
75        cli                     # DISABLE INTERRUPTS!!!
76#if defined(SMP_SECONDARY_CORE)
77        jmp     1f
78        .align 4
79app_cpu_start:
80        .long   0
81app_cpu_stack:
82        .long   0
831:
84#endif
85        movw    %cs, %ax                   # Initialize the rest of
86        movw    %ax, %ds                   #   segment registers
87        movw    %ax, %es
88        movw    %ax, %ss
89
90#if !defined(SMP_SECONDARY_CODE) && (RTEMS_VIDEO_80x50 == 1)
91        movl    $0x0040,%eax    # use 32 bit constant to ensure 16 MSB=0
92        mov     %ax,%es
93        movw    %es:0x4a, %ax   # get 16 bit number of columns
94        cmpw    $0, %ax         # or 0 if no video adapter
95        je      1f              # if no video, skip touching it
96        /*---------------------------------------------------------------------+
97        | Switch VGA video to 80 lines x 50 columns mode. Has to be done before
98        | turning protected mode on since it uses BIOS int 10h (video) services.
99        +---------------------------------------------------------------------*/
100
101        movw    $0x0003, %ax    # forced set
102        int     $0x10
103        movw    $0x1112, %ax    # use 8x8 font
104        xorb    %bl, %bl
105        int     $0x10
106        movw    $0x1201, %ax    # turn off cursor emulation
107        movb    $0x34, %bl
108        int     $0x10
109        movb    $0x01, %ah      # define cursor (scan lines 0 to 7)
110        movw    $0x0007, %cx
111        int     $0x10
1121:
113#endif /* !SMP_SECONDARY_CODE and RTEMS_VIDEO_80x50 */
114
115        /*---------------------------------------------------------------------+
116        | Bare PC machines boot in real mode! We have to turn protected mode on.
117        +---------------------------------------------------------------------*/
118
119#if defined(SMP_SECONDARY_CORE)
120        lgdt    gdtptr - app_processor_start  # load Global Descriptor Table
121#else
122        lgdt    gdtptr - start16        # load Global Descriptor Table
123#endif /* SMP_SECONDARY_CORE */
124
125        movl    %cr0, %eax
126        orl     $CR0_PE, %eax
127        movl    %eax, %cr0              # turn on protected mode
128#if defined(SMP_SECONDARY_CORE)
129        LJMPL   $PROT_CODE_SEG, $2f     # flush prefetch queue, and reload %cs
130#else
131        LJMPL   $PROT_CODE_SEG, $2f     # flush prefetch queue, and reload %cs
132#endif
133.code32
1342:
135
136        /*---------------------------------------------------------------------+
137        | load the other segment registers
138        +---------------------------------------------------------------------*/
139        movl    $PROT_DATA_SEG, %eax
140        movw    %ax, %ds
141        movw    %ax, %es
142        movw    %ax, %ss
143#if defined(SMP_SECONDARY_CORE)
144        movl    app_cpu_stack, %esp            # stack pointer
145        movl    app_cpu_stack, %ebp            # base pointer
146 #else
147        movl    $start16 + STACKOFF, %esp       # set up stack pointer
148        addl    $start16 + STACKOFF, %ebp       # set up stack pointer
149#endif  /* SMP_SECONDARY_CORE */
150
151        /*---------------------------------------------------------------------+
152        | we have to enable A20 in order to access memory above 1MByte
153        +---------------------------------------------------------------------*/
154        call    empty_8042
155        movb    $0xD1, %al                      # command write
156        outb    %al, $0x64
157        call    empty_8042
158        movb    $0xDF, %al                      # A20 on
159        outb    %al, $0x60
160        call    empty_8042
161
162        call    pc386_delay
163        call    pc386_delay
164        call    pc386_delay
165
166#if defined(SMP_SECONDARY_CORE)
167        movl    app_cpu_start, %eax             # jump to app CPU start
168#else
169        movl    %cs:HDRSTART + HDROFF, %eax     # jump to start of 32 bit code
170#endif  /* SMP_SECONDARY_CORE */
171        pushl   %eax                           
172        ret                                   
173 
174
175/*----------------------------------------------------------------------------+
176| pc386_delay
177+------------------------------------------------------------------------------
178| Delay is needed after doing I/O.
179|
180| The outb version is OK on most machines BUT the loop version ...
181|
182| will delay for 1us on 1Gz machine, it will take a little bit
183| longer on slower machines, however, it does not matter because we
184| are going to call this function only a few times
185!
186| NOTE: Saving the content of the EAX register just in case. - Rosimildo.
187+----------------------------------------------------------------------------*/
188        .p2align 4
189        .globl _pc386_delay
190        .globl pc386_delay
191pc386_delay:
192_pc386_delay:
193        pushl   %eax
194#if defined(USE_OUTB_FOR_DELAY)
195        outb    %al, $0x80       # about 1uS delay on most machines
196
197#else
198
199        movl    $0x200, %eax
200pc386_delay1:
201        dec     %eax
202        jnz     pc386_delay1
203#endif
204        popl    %eax
205        ret
206
207/*----------------------------------------------------------------------------+
208| empty_8042
209+------------------------------------------------------------------------------
210| This routine checks that the keyboard command queue is empty (after emptying
211| the output buffers).
212| No timeout is used - if this hangs there is something wrong with the machine,
213| and we probably couldn't proceed anyway.
214+----------------------------------------------------------------------------*/
215        .p2align 4
216        .globl _empty_8042
217        .globl empty_8042
218empty_8042:
219_empty_8042:
220        call    pc386_delay
221        inb     $0x64, %al      # 8042 status port
222        testb   $0x01, %al      # output buffer?
223        jz      no_output
224        call    pc386_delay
225        in      $0x60, %al      # read it
226        jmp     empty_8042
227no_output:
228        test    $0x02, %al      # is input buffer full?
229        jnz     empty_8042      # yes - loop
230        ret
231
232/*----------------------------------------------------------------------------+
233| DATA section
234+----------------------------------------------------------------------------*/
235
236/**************************
237* GLOBAL DESCRIPTOR TABLE *
238**************************/
239
240        .p2align 4
241gdtptr:
242        /* we use the NULL descriptor to store the GDT pointer - a trick quite
243           nifty due to: Robert Collins (rcollins@x86.org) */
244        .word   gdtlen - 1
245        .long   gdtptr
246        .word   0x0000
247
248        /* code segment */
249        .word   0xffff, 0
250        .byte   0, 0x9f, 0xcf, 0
251
252        /* data segment */
253        .word   0xffff, 0
254        .byte   0, 0x93, 0xcf, 0
255
256        .set    gdtlen, . - gdtptr      # length of GDT
Note: See TracBrowser for help on using the repository browser.