1 |
30 |
unneback |
/*-------------------------------------------------------------------------+
|
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 found in the file LICENSE in this distribution or at
|
32 |
|
|
| * http://www.OARcorp.com/rtems/license.html.
|
33 |
|
|
| **************************************************************************
|
34 |
|
|
|
|
35 |
|
|
| $Id: ldsegs.S,v 1.2 2001-09-27 11:59:48 chris Exp $
|
36 |
|
|
+--------------------------------------------------------------------------*/
|
37 |
|
|
|
38 |
|
|
|
39 |
|
|
#include "asm.h"
|
40 |
|
|
|
41 |
|
|
/*----------------------------------------------------------------------------+
|
42 |
|
|
| CODE section
|
43 |
|
|
+----------------------------------------------------------------------------*/
|
44 |
|
|
EXTERN (rtems_i8259_masks)
|
45 |
|
|
|
46 |
|
|
BEGIN_CODE
|
47 |
|
|
|
48 |
|
|
EXTERN (_establish_stack)
|
49 |
|
|
EXTERN (Timer_exit)
|
50 |
|
|
EXTERN (clockOff)
|
51 |
|
|
|
52 |
|
|
/*----------------------------------------------------------------------------+
|
53 |
|
|
| pc386_delay
|
54 |
|
|
+------------------------------------------------------------------------------
|
55 |
|
|
| Delay is needed after doing I/O.
|
56 |
|
|
|
|
57 |
|
|
| The outb version is OK on most machines BUT the loop version ...
|
58 |
|
|
|
|
59 |
|
|
| will delay for 1us on 1Gz machine, it will take a little bit
|
60 |
|
|
| longer on slower machines, however, it does not matter because we
|
61 |
|
|
| are going to call this function only a few times
|
62 |
|
|
|
63 |
|
|
+----------------------------------------------------------------------------*/
|
64 |
|
|
#define DELAY_USE_OUTB
|
65 |
|
|
|
66 |
|
|
.p2align 4
|
67 |
|
|
.globl _pc386_delay
|
68 |
|
|
.globl pc386_delay
|
69 |
|
|
pc386_delay:
|
70 |
|
|
_pc386_delay:
|
71 |
|
|
#ifdef DELAY_USE_OUTB
|
72 |
|
|
outb al, $0x80 # about 1uS delay on most machines
|
73 |
|
|
#else
|
74 |
|
|
movl $0x200, eax
|
75 |
|
|
pc386_delay1:
|
76 |
|
|
dec eax
|
77 |
|
|
jnz pc386_delay1
|
78 |
|
|
#endif
|
79 |
|
|
ret
|
80 |
|
|
|
81 |
|
|
/*-------------------------------------------------------------------------+
|
82 |
|
|
| Function: _load_segments
|
83 |
|
|
| Description: Current environment is standard PC booted by grub.
|
84 |
|
|
| So, there is no value in saving current GDT and IDT
|
85 |
|
|
| settings we have to set it up ourseves. (Naturally
|
86 |
|
|
| it will be not so in case we are booted by some
|
87 |
|
|
| boot monitor, however, then it will be different
|
88 |
|
|
| BSP). After that we have to load board segment registers
|
89 |
|
|
| with apropriate values + reprogram PIC.
|
90 |
|
|
| Global Variables: None.
|
91 |
|
|
| Arguments: None.
|
92 |
|
|
| Returns: Nothing.
|
93 |
|
|
+--------------------------------------------------------------------------*/
|
94 |
|
|
.p2align 4
|
95 |
|
|
|
96 |
|
|
PUBLIC (_load_segments)
|
97 |
|
|
SYM (_load_segments):
|
98 |
|
|
|
99 |
|
|
lgdt SYM(gdtdesc)
|
100 |
|
|
lidt SYM(idtdesc)
|
101 |
|
|
|
102 |
|
|
/* Load CS, flush prefetched queue */
|
103 |
|
|
ljmp $0x8, $next_step
|
104 |
|
|
|
105 |
|
|
next_step:
|
106 |
|
|
/* Load segment registers */
|
107 |
|
|
movw $0x10, ax
|
108 |
|
|
movw ax, ss
|
109 |
|
|
movw ax, ds
|
110 |
|
|
movw ax, es
|
111 |
|
|
movw ax, fs
|
112 |
|
|
movw ax, gs
|
113 |
|
|
|
114 |
|
|
/*---------------------------------------------------------------------+
|
115 |
|
|
| Now we have to reprogram the interrupts :-(. We put them right after
|
116 |
|
|
| the intel-reserved hardware interrupts, at int 0x20-0x2F. There they
|
117 |
|
|
| won't mess up anything. Sadly IBM really messed this up with the
|
118 |
|
|
| original PC, and they haven't been able to rectify it afterwards. Thus
|
119 |
|
|
| the bios puts interrupts at 0x08-0x0f, which is used for the internal
|
120 |
|
|
| hardware interrupts as well. We just have to reprogram the 8259's, and
|
121 |
|
|
| it isn't fun.
|
122 |
|
|
+---------------------------------------------------------------------*/
|
123 |
|
|
|
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 |
|
|
movb $0xFF, al /* mask off all interrupts for now */
|
151 |
|
|
outb al, $0xA1
|
152 |
|
|
call SYM(pc386_delay)
|
153 |
|
|
movb $0xFB, al /* mask all irq's but irq2 which */
|
154 |
|
|
outb al, $0x21 /* is cascaded */
|
155 |
|
|
call SYM(pc386_delay)
|
156 |
|
|
|
157 |
|
|
movw $0xFFFB, SYM(i8259s_cache) /* set up same values in cache */
|
158 |
|
|
|
159 |
|
|
jmp SYM (_establish_stack) # return to the bsp entry code
|
160 |
|
|
|
161 |
|
|
/*-------------------------------------------------------------------------+
|
162 |
|
|
| Function: _return_to_monitor
|
163 |
|
|
| Description: Return to board's monitor (we have none so simply restart).
|
164 |
|
|
| Global Variables: None.
|
165 |
|
|
| Arguments: None.
|
166 |
|
|
| Returns: Nothing.
|
167 |
|
|
+--------------------------------------------------------------------------*/
|
168 |
|
|
|
169 |
|
|
.p2align 4
|
170 |
|
|
|
171 |
|
|
PUBLIC (_return_to_monitor)
|
172 |
|
|
SYM (_return_to_monitor):
|
173 |
|
|
|
174 |
|
|
call SYM (Timer_exit)
|
175 |
|
|
call SYM (Clock_exit)
|
176 |
|
|
jmp SYM (start)
|
177 |
|
|
|
178 |
|
|
/*-------------------------------------------------------------------------+
|
179 |
|
|
| Function: _default_int_handler
|
180 |
|
|
| Description: default interrupt handler
|
181 |
|
|
| Global Variables: None.
|
182 |
|
|
| Arguments: None.
|
183 |
|
|
| Returns: Nothing.
|
184 |
|
|
+--------------------------------------------------------------------------*/
|
185 |
|
|
.p2align 4
|
186 |
|
|
|
187 |
|
|
/*---------------------------------------------------------------------------+
|
188 |
|
|
| GDT itself
|
189 |
|
|
+--------------------------------------------------------------------------*/
|
190 |
|
|
|
191 |
|
|
.p2align 4
|
192 |
|
|
|
193 |
|
|
PUBLIC (_Global_descriptor_table)
|
194 |
|
|
SYM (_Global_descriptor_table):
|
195 |
|
|
|
196 |
|
|
/* NULL segment */
|
197 |
|
|
.word 0, 0
|
198 |
|
|
.byte 0, 0, 0, 0
|
199 |
|
|
|
200 |
|
|
/* code segment */
|
201 |
|
|
.word 0xffff, 0
|
202 |
|
|
.byte 0, 0x9e, 0xcf, 0
|
203 |
|
|
|
204 |
|
|
/* data segment */
|
205 |
|
|
.word 0xffff, 0
|
206 |
|
|
.byte 0, 0x92, 0xcf, 0
|
207 |
|
|
|
208 |
|
|
|
209 |
|
|
/*---------------------------------------------------------------------------+
|
210 |
|
|
| Descriptor of GDT
|
211 |
|
|
+--------------------------------------------------------------------------*/
|
212 |
|
|
SYM (gdtdesc):
|
213 |
|
|
.word (3*8 - 1)
|
214 |
|
|
.long SYM (_Global_descriptor_table)
|
215 |
|
|
|
216 |
|
|
|
217 |
|
|
/*---------------------------------------------------------------------------+
|
218 |
|
|
| IDT itself
|
219 |
|
|
+---------------------------------------------------------------------------*/
|
220 |
|
|
.p2align 4
|
221 |
|
|
|
222 |
|
|
PUBLIC(Interrupt_descriptor_table)
|
223 |
|
|
SYM(Interrupt_descriptor_table):
|
224 |
|
|
.rept 256
|
225 |
|
|
.word 0,0,0,0
|
226 |
|
|
.endr
|
227 |
|
|
|
228 |
|
|
/*---------------------------------------------------------------------------+
|
229 |
|
|
| Descriptor of IDT
|
230 |
|
|
+--------------------------------------------------------------------------*/
|
231 |
|
|
SYM(idtdesc):
|
232 |
|
|
.word (256*8 - 1)
|
233 |
|
|
.long SYM (Interrupt_descriptor_table)
|
234 |
|
|
|
235 |
|
|
END_CODE
|
236 |
|
|
|
237 |
|
|
.section .m_hdr
|
238 |
|
|
.long 0x1BADB002
|
239 |
|
|
.long 0
|
240 |
|
|
.long 0xE4524FFE
|
241 |
|
|
END
|