source: rtems/c/src/lib/libbsp/i386/pc386/startup/ldsegs.S @ 7b0c74ff

Last change on this file since 7b0c74ff was 7b0c74ff, checked in by Sebastian Huber <sebastian.huber@…>, on Jun 9, 2017 at 1:42:36 PM

i386: Support thread-local storage (TLS)

Update #2468.

  • Property mode set to 100644
File size: 7.5 KB
Line 
1/*-------------------------------------------------------------------------+
2| ldsegs.s v1.1 - PC386 BSP - 1997/08/07
3+--------------------------------------------------------------------------+
4| This file assists the board independent startup code by loading the proper
5| segment register values. The values loaded are board dependent. In addition
6| it contains code to enable the A20 line and to reprogram the PIC to relocate
7| the IRQ interrupt vectors to 0x20 -> 0x2f.
8| NOTE: No stack has been established when this routine is invoked.
9|       It returns by jumping back to bspentry.
10+--------------------------------------------------------------------------+
11| (C) Copyright 1997 -
12| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
13|
14| http://pandora.ist.utl.pt
15|
16| Instituto Superior Tecnico * Lisboa * PORTUGAL
17+--------------------------------------------------------------------------+
18| Disclaimer:
19|
20| This file is provided "AS IS" without warranty of any kind, either
21| expressed or implied.
22+--------------------------------------------------------------------------+
23| This code is base on:
24|   ldsegs.s,v 1.4 1996/04/20 16:48:30 joel Exp - go32 BSP
25| With the following copyright notice:
26| **************************************************************************
27| *  COPYRIGHT (c) 1989-1999.
28| *  On-Line Applications Research Corporation (OAR).
29| *
30| *  The license and distribution terms for this file may be
31| *  found in the file LICENSE in this distribution or at
32| *  http://www.rtems.org/license/LICENSE.
33| **************************************************************************
34+--------------------------------------------------------------------------*/
35
36#include <rtems/asm.h>
37#include <bsp/tblsizes.h> /* contains sizes of GDT and IDT */
38#include <bspopts.h>
39
40/*----------------------------------------------------------------------------+
41| CODE section
42+----------------------------------------------------------------------------*/
43EXTERN (rtems_i8259_masks)
44
45BEGIN_CODE
46
47        EXTERN (_establish_stack)
48        EXTERN (Timer_exit)
49        EXTERN (clockOff)
50
51/*----------------------------------------------------------------------------+
52| pc386_delay
53+------------------------------------------------------------------------------
54| Delay is needed after doing I/O.
55|
56| The outb version is OK on most machines BUT the loop version ...
57|
58| will delay for 1us on 1Gz machine, it will take a little bit
59| longer on slower machines, however, it does not matter because we
60| are going to call this function only a few times
61
62+----------------------------------------------------------------------------*/
63#define DELAY_USE_OUTB
64
65        .p2align 4
66        .globl _pc386_delay
67        .globl pc386_delay
68pc386_delay:
69_pc386_delay:
70#ifdef  DELAY_USE_OUTB
71        outb    al, $0x80       # about 1uS delay on most machines
72#else
73        movl    $0x200, eax
74pc386_delay1:
75        dec     eax
76        jnz     pc386_delay1
77#endif
78        ret
79
80/*-------------------------------------------------------------------------+
81|         Function: _load_segments
82|      Description: Current environment is standard PC booted by grub.
83|                   So, there is no value in saving current GDT and IDT
84|                   settings we have to set it up ourseves. (Naturally
85|                   it will be not so in case we are booted by some
86|                   boot monitor, however, then it will be different
87|                   BSP). After that we have to load board segment registers
88|                   with apropriate values +  reprogram PIC.
89| Global Variables: None.
90|        Arguments: None.
91|          Returns: Nothing.
92+--------------------------------------------------------------------------*/
93        .p2align 4
94
95        PUBLIC (_load_segments)
96SYM (_load_segments):
97
98        lgdt SYM(gdtdesc)
99        lidt SYM(IDT_Descriptor)
100
101        /* Load CS, flush prefetched queue */
102        ljmp $0x8, $next_step
103
104next_step:
105        /* Load segment registers */
106        movw $0x10, ax
107        movw ax, ss
108        movw ax, ds
109        movw ax, es
110        movw ax, fs
111        movw ax, gs
112
113/*---------------------------------------------------------------------+
114| Now we have to reprogram the interrupts :-(. We put them right after
115| the intel-reserved hardware interrupts, at int 0x20-0x2F. There they
116| won't mess up anything. Sadly IBM really messed this up with the
117| original PC, and they haven't been able to rectify it afterwards. Thus
118| the bios puts interrupts at 0x08-0x0f, which is used for the internal
119| hardware interrupts as well. We just have to reprogram the 8259's, and
120| it isn't fun.
121+---------------------------------------------------------------------*/
122
123#if (BSP_IS_EDISON == 0)
124        movb    $0x11, al               /* initialization sequence          */
125        outb    al, $0x20               /* send it to 8259A-1               */
126        call    SYM(pc386_delay)
127        outb    al, $0xA0               /* and to 8259A-2                   */
128        call    SYM(pc386_delay)
129
130        movb    $0x20, al               /* start of hardware int's (0x20)   */
131        outb    al, $0x21
132        call    SYM(pc386_delay)
133        movb    $0x28, al               /* start of hardware int's 2 (0x28) */
134        outb    al, $0xA1
135        call    SYM(pc386_delay)
136
137        movb    $0x04, al               /* 8259-1 is master                 */
138        outb    al, $0x21
139        call    SYM(pc386_delay)
140        movb    $0x02, al               /* 8259-2 is slave                  */
141        outb    al, $0xA1
142        call    SYM(pc386_delay)
143
144        movb    $0x01, al               /* 8086 mode for both               */
145        outb    al, $0x21
146        call    SYM(pc386_delay)
147        outb    al, $0xA1
148        call    SYM(pc386_delay)
149
150        /*
151         * The IMR values must correspond to the initial value of i8259s_cache.
152         */
153        movb    $0xFF, al               /* mask off all interrupts for now  */
154        outb    al, $0xA1
155        call    SYM(pc386_delay)
156        movb    $0xFB, al               /* mask all irq's but irq2 which    */
157        outb    al, $0x21               /* is cascaded                      */
158        call    SYM(pc386_delay)
159#endif
160        jmp     SYM (_establish_stack)  # return to the bsp entry code
161
162/*-------------------------------------------------------------------------+
163|         Function: _default_int_handler
164|      Description: default interrupt handler
165| Global Variables: None.
166|        Arguments: None.
167|          Returns: Nothing.
168+--------------------------------------------------------------------------*/
169        .p2align 4
170
171/*---------------------------------------------------------------------------+
172| GDT itself
173+--------------------------------------------------------------------------*/
174#if GDT_SIZE < NUM_SYSTEM_GDT_DESCRIPTORS
175#error "GDT_SIZE must be at least NUM_SYSTEM_GDT_DESCRIPTORS"
176#endif
177
178BEGIN_DATA
179        .p2align 4
180
181        PUBLIC (_Global_descriptor_table)
182SYM (_Global_descriptor_table):
183
184        /* NULL segment */
185        .word 0, 0
186        .byte 0, 0, 0, 0
187
188        /* code segment */
189        .word 0xffff, 0
190        .byte 0, 0x9e, 0xcf, 0
191
192        /* data segment */
193        .word 0xffff, 0
194        .byte 0, 0x92, 0xcf, 0
195
196        /* gs segment */
197        .word 0xffff, 0
198        .byte 0, 0x92, 0xcf, 0
199
200        /* allocated space for user segments */
201        .rept (GDT_SIZE - NUM_SYSTEM_GDT_DESCRIPTORS)
202        .word 0,0,0,0
203        .endr
204
205/*---------------------------------------------------------------------------+
206| Descriptor of GDT
207+--------------------------------------------------------------------------*/
208        PUBLIC(gdtdesc)
209SYM(gdtdesc):
210        .word (GDT_SIZE*8 - 1)
211        .long SYM (_Global_descriptor_table)
212
213/*---------------------------------------------------------------------------+
214| IDT itself
215+---------------------------------------------------------------------------*/
216        .p2align 4
217
218        PUBLIC(Interrupt_descriptor_table)
219SYM(Interrupt_descriptor_table):
220        .rept IDT_SIZE
221        .word 0,0,0,0
222        .endr
223
224/*---------------------------------------------------------------------------+
225| Descriptor of IDT
226+--------------------------------------------------------------------------*/
227
228        .p2align 4
229        PUBLIC(IDT_Descriptor)
230SYM(IDT_Descriptor):
231        .word  (IDT_SIZE*8 - 1)
232        .long  SYM (Interrupt_descriptor_table)
233
234END_DATA
235
236    .section .m_hdr
237        .long 0x1BADB002
238        .long 0
239        .long 0xE4524FFE
240END
Note: See TracBrowser for help on using the repository browser.