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 found in the file LICENSE in this distribution or at |
---|
32 | | * http://www.OARcorp.com/rtems/license.html. |
---|
33 | | ************************************************************************** |
---|
34 | | |
---|
35 | | $Id$ |
---|
36 | | |
---|
37 | | Also based on (from the Linux source tree): |
---|
38 | | setup.S - Copyright (C) 1991, 1992 Linus Torvalds |
---|
39 | +--------------------------------------------------------------------------*/ |
---|
40 | |
---|
41 | |
---|
42 | #include "asm.h" |
---|
43 | |
---|
44 | /*----------------------------------------------------------------------------+ |
---|
45 | | CODE section |
---|
46 | +----------------------------------------------------------------------------*/ |
---|
47 | EXTERN (rtems_i8259_masks) |
---|
48 | |
---|
49 | BEGIN_CODE |
---|
50 | |
---|
51 | EXTERN (_establish_stack) |
---|
52 | EXTERN (Timer_exit) |
---|
53 | EXTERN (clockOff) |
---|
54 | |
---|
55 | .p2align 4 |
---|
56 | /*----------------------------------------------------------------------------+ |
---|
57 | | delay |
---|
58 | +------------------------------------------------------------------------------ |
---|
59 | | Delay is needed after doing I/O. We do it by writing to a non-existent port. |
---|
60 | +----------------------------------------------------------------------------*/ |
---|
61 | SYM(delay): |
---|
62 | outb al, $0x80 # about 1uS delay |
---|
63 | ret |
---|
64 | |
---|
65 | /*-------------------------------------------------------------------------+ |
---|
66 | | Function: _load_segments |
---|
67 | | Description: Current environment is standard PC booted by grub. |
---|
68 | | So, there is no value in saving current GDT and IDT |
---|
69 | | settings we have to set it up ourseves. (Naturally |
---|
70 | | it will be not so in case we are booted by some |
---|
71 | | boot monitor, however, then it will be different |
---|
72 | | BSP). After that we have to load board segment registers |
---|
73 | | with apropriate values + reprogram PIC. |
---|
74 | | Global Variables: None. |
---|
75 | | Arguments: None. |
---|
76 | | Returns: Nothing. |
---|
77 | +--------------------------------------------------------------------------*/ |
---|
78 | .p2align 4 |
---|
79 | |
---|
80 | PUBLIC (_load_segments) |
---|
81 | SYM (_load_segments): |
---|
82 | |
---|
83 | lgdt SYM(gdtdesc) |
---|
84 | lidt SYM(idtdesc) |
---|
85 | |
---|
86 | /* Load CS, flush prefetched queue */ |
---|
87 | ljmp $0x8, $next_step |
---|
88 | |
---|
89 | next_step: |
---|
90 | /* Load segment registers */ |
---|
91 | movw $0x10, ax |
---|
92 | movw ax, ss |
---|
93 | movw ax, ds |
---|
94 | movw ax, es |
---|
95 | movw ax, fs |
---|
96 | movw ax, gs |
---|
97 | |
---|
98 | /*---------------------------------------------------------------------+ |
---|
99 | | Now we have to reprogram the interrupts :-(. We put them right after |
---|
100 | | the intel-reserved hardware interrupts, at int 0x20-0x2F. There they |
---|
101 | | won't mess up anything. Sadly IBM really messed this up with the |
---|
102 | | original PC, and they haven't been able to rectify it afterwards. Thus |
---|
103 | | the bios puts interrupts at 0x08-0x0f, which is used for the internal |
---|
104 | | hardware interrupts as well. We just have to reprogram the 8259's, and |
---|
105 | | it isn't fun. |
---|
106 | +---------------------------------------------------------------------*/ |
---|
107 | |
---|
108 | movb $0x11, al /* initialization sequence */ |
---|
109 | outb al, $0x20 /* send it to 8259A-1 */ |
---|
110 | call SYM(delay) |
---|
111 | outb al, $0xA0 /* and to 8259A-2 */ |
---|
112 | call SYM(delay) |
---|
113 | |
---|
114 | movb $0x20, al /* start of hardware int's (0x20) */ |
---|
115 | outb al, $0x21 |
---|
116 | call SYM(delay) |
---|
117 | movb $0x28, al /* start of hardware int's 2 (0x28) */ |
---|
118 | outb al, $0xA1 |
---|
119 | call SYM(delay) |
---|
120 | |
---|
121 | movb $0x04, al /* 8259-1 is master */ |
---|
122 | outb al, $0x21 |
---|
123 | call SYM(delay) |
---|
124 | movb $0x02, al /* 8259-2 is slave */ |
---|
125 | outb al, $0xA1 |
---|
126 | call SYM(delay) |
---|
127 | |
---|
128 | movb $0x01, al /* 8086 mode for both */ |
---|
129 | outb al, $0x21 |
---|
130 | call SYM(delay) |
---|
131 | outb al, $0xA1 |
---|
132 | call SYM(delay) |
---|
133 | |
---|
134 | movb $0xFF, al /* mask off all interrupts for now */ |
---|
135 | outb al, $0xA1 |
---|
136 | call SYM(delay) |
---|
137 | movb $0xFB, al /* mask all irq's but irq2 which */ |
---|
138 | outb al, $0x21 /* is cascaded */ |
---|
139 | call SYM(delay) |
---|
140 | |
---|
141 | movw $0xFFFB, SYM(i8259s_cache) /* set up same values in cache */ |
---|
142 | |
---|
143 | jmp SYM (_establish_stack) # return to the bsp entry code |
---|
144 | |
---|
145 | /*-------------------------------------------------------------------------+ |
---|
146 | | Function: _return_to_monitor |
---|
147 | | Description: Return to board's monitor (we have none so simply restart). |
---|
148 | | Global Variables: None. |
---|
149 | | Arguments: None. |
---|
150 | | Returns: Nothing. |
---|
151 | +--------------------------------------------------------------------------*/ |
---|
152 | |
---|
153 | .p2align 4 |
---|
154 | |
---|
155 | PUBLIC (_return_to_monitor) |
---|
156 | SYM (_return_to_monitor): |
---|
157 | |
---|
158 | call SYM (Timer_exit) |
---|
159 | call SYM (Clock_exit) |
---|
160 | jmp SYM (start) |
---|
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 | |
---|
175 | .p2align 4 |
---|
176 | |
---|
177 | PUBLIC (_Global_descriptor_table) |
---|
178 | SYM (_Global_descriptor_table): |
---|
179 | |
---|
180 | /* NULL segment */ |
---|
181 | .word 0, 0 |
---|
182 | .byte 0, 0, 0, 0 |
---|
183 | |
---|
184 | /* code segment */ |
---|
185 | .word 0xffff, 0 |
---|
186 | .byte 0, 0x9e, 0xcf, 0 |
---|
187 | |
---|
188 | /* data segment */ |
---|
189 | .word 0xffff, 0 |
---|
190 | .byte 0, 0x92, 0xcf, 0 |
---|
191 | |
---|
192 | |
---|
193 | /*---------------------------------------------------------------------------+ |
---|
194 | | Descriptor of GDT |
---|
195 | +--------------------------------------------------------------------------*/ |
---|
196 | SYM (gdtdesc): |
---|
197 | .word (3*8 - 1) |
---|
198 | .long SYM (_Global_descriptor_table) |
---|
199 | |
---|
200 | |
---|
201 | /*---------------------------------------------------------------------------+ |
---|
202 | | IDT itself |
---|
203 | +---------------------------------------------------------------------------*/ |
---|
204 | .p2align 4 |
---|
205 | |
---|
206 | PUBLIC(Interrupt_descriptor_table) |
---|
207 | SYM(Interrupt_descriptor_table): |
---|
208 | .rept 256 |
---|
209 | .word 0,0,0,0 |
---|
210 | .endr |
---|
211 | |
---|
212 | /*---------------------------------------------------------------------------+ |
---|
213 | | Descriptor of IDT |
---|
214 | +--------------------------------------------------------------------------*/ |
---|
215 | SYM(idtdesc): |
---|
216 | .word (256*8 - 1) |
---|
217 | .long SYM (Interrupt_descriptor_table) |
---|
218 | |
---|
219 | END_CODE |
---|
220 | |
---|
221 | .section .m_hdr |
---|
222 | .long 0x1BADB002 |
---|
223 | .long 0 |
---|
224 | .long 0xE4524FFE |
---|
225 | END |
---|