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, 1990, 1991, 1992, 1993, 1994. * |
---|
28 | | * On-Line Applications Research Corporation (OAR). * |
---|
29 | | * All rights assigned to U.S. Government, 1994. * |
---|
30 | | * * |
---|
31 | | * This material may be reproduced by or for the U.S. Government pursuant * |
---|
32 | | * to the copyright license under the clause at DFARS 252.227-7013. This * |
---|
33 | | * notice must appear in all copies of this file and its derivatives. * |
---|
34 | | ************************************************************************** |
---|
35 | | |
---|
36 | | Also based on (from the Linux source tree): |
---|
37 | | setup.S - Copyright (C) 1991, 1992 Linus Torvalds |
---|
38 | +--------------------------------------------------------------------------*/ |
---|
39 | |
---|
40 | |
---|
41 | #include "asm.h" |
---|
42 | |
---|
43 | /*----------------------------------------------------------------------------+ |
---|
44 | | Constants |
---|
45 | +----------------------------------------------------------------------------*/ |
---|
46 | .set PROT_DATA_SEG, 0x10 # offset in gdt |
---|
47 | .set RESET_SS, PROT_DATA_SEG # initial value of stack segment register |
---|
48 | .set RESET_DS, PROT_DATA_SEG # initial value of data segment register |
---|
49 | .set RESET_ES, PROT_DATA_SEG # initial value of extra segment register |
---|
50 | .set RESET_FS, PROT_DATA_SEG # initial value of "f" segment register |
---|
51 | .set RESET_GS, PROT_DATA_SEG # initial value of "g" segment register |
---|
52 | |
---|
53 | |
---|
54 | /*----------------------------------------------------------------------------+ |
---|
55 | | Macros |
---|
56 | +----------------------------------------------------------------------------*/ |
---|
57 | #define LOAD_SEGMENTS(_value, _segment) \ |
---|
58 | movw $ ## _value, ax; \ |
---|
59 | movw ax, _segment |
---|
60 | |
---|
61 | /*----------------------------------------------------------------------------+ |
---|
62 | | CODE section |
---|
63 | +----------------------------------------------------------------------------*/ |
---|
64 | |
---|
65 | BEGIN_CODE |
---|
66 | |
---|
67 | EXTERN (establish_stack) |
---|
68 | |
---|
69 | /*----------------------------------------------------------------------------+ |
---|
70 | | empty_8042 |
---|
71 | +------------------------------------------------------------------------------ |
---|
72 | | This routine checks that the keyboard command queue is empty (after emptying |
---|
73 | | the output buffers). |
---|
74 | | No timeout is used - if this hangs there is something wrong with the machine, |
---|
75 | | and we probably couldn't proceed anyway. |
---|
76 | +----------------------------------------------------------------------------*/ |
---|
77 | SYM(empty_8042): |
---|
78 | call delay |
---|
79 | inb $0x64, al # 8042 status port |
---|
80 | testb $0x01, al # output buffer? |
---|
81 | jz SYM(no_output) |
---|
82 | call SYM(delay) |
---|
83 | in $0x60, al # read it |
---|
84 | jmp SYM(empty_8042) |
---|
85 | SYM(no_output): |
---|
86 | test $0x02, al # is input buffer full? |
---|
87 | jnz SYM(empty_8042) # yes - loop |
---|
88 | ret |
---|
89 | |
---|
90 | /*----------------------------------------------------------------------------+ |
---|
91 | | delay |
---|
92 | +------------------------------------------------------------------------------ |
---|
93 | | Delay is needed after doing I/O. We do it by writing to a non-existent port. |
---|
94 | +----------------------------------------------------------------------------*/ |
---|
95 | SYM(delay): |
---|
96 | outb al, $0xED # about 1uS delay |
---|
97 | ret |
---|
98 | |
---|
99 | /*-------------------------------------------------------------------------+ |
---|
100 | | Function: _load_segments |
---|
101 | | Description: Load board segment registers with apropriate values + enable |
---|
102 | A20 line + reprogram PIC. |
---|
103 | | Global Variables: None. |
---|
104 | | Arguments: None. |
---|
105 | | Returns: Nothing. |
---|
106 | +--------------------------------------------------------------------------*/ |
---|
107 | PUBLIC (_load_segments) |
---|
108 | SYM (_load_segments): |
---|
109 | |
---|
110 | LOAD_SEGMENTS(RESET_SS, ss) |
---|
111 | LOAD_SEGMENTS(RESET_DS, ds) |
---|
112 | LOAD_SEGMENTS(RESET_ES, es) |
---|
113 | LOAD_SEGMENTS(RESET_FS, fs) |
---|
114 | LOAD_SEGMENTS(RESET_GS, gs) |
---|
115 | |
---|
116 | /*---------------------------------------------------------------------+ |
---|
117 | | we have to enable A20 in order to access memory above 1MByte |
---|
118 | +---------------------------------------------------------------------*/ |
---|
119 | |
---|
120 | call SYM(empty_8042) |
---|
121 | movb $0xD1, al # command write |
---|
122 | outb al, $0x64 |
---|
123 | call SYM(empty_8042) |
---|
124 | movb $0xDF, al # A20 on |
---|
125 | outb al, $0x60 |
---|
126 | call SYM(empty_8042) |
---|
127 | |
---|
128 | /*---------------------------------------------------------------------+ |
---|
129 | | Now we have to reprogram the interrupts :-(. We put them right after |
---|
130 | | the intel-reserved hardware interrupts, at int 0x20-0x2F. There they |
---|
131 | | won't mess up anything. Sadly IBM really messed this up with the |
---|
132 | | original PC, and they haven't been able to rectify it afterwards. Thus |
---|
133 | | the bios puts interrupts at 0x08-0x0f, which is used for the internal |
---|
134 | | hardware interrupts as well. We just have to reprogram the 8259's, and |
---|
135 | | it isn't fun. |
---|
136 | +---------------------------------------------------------------------*/ |
---|
137 | |
---|
138 | movb $0x11, al /* initialization sequence */ |
---|
139 | outb al, $0x20 /* send it to 8259A-1 */ |
---|
140 | call SYM(delay) |
---|
141 | outb al, $0xA0 /* and to 8259A-2 */ |
---|
142 | call SYM(delay) |
---|
143 | |
---|
144 | movb $0x20, al /* start of hardware int's (0x20) */ |
---|
145 | outb al, $0x21 |
---|
146 | call SYM(delay) |
---|
147 | movb $0x28, al /* start of hardware int's 2 (0x28) */ |
---|
148 | outb al, $0xA1 |
---|
149 | call SYM(delay) |
---|
150 | |
---|
151 | movb $0x04, al /* 8259-1 is master */ |
---|
152 | outb al, $0x21 |
---|
153 | call SYM(delay) |
---|
154 | movb $0x02, al /* 8259-2 is slave */ |
---|
155 | outb al, $0xA1 |
---|
156 | call SYM(delay) |
---|
157 | |
---|
158 | movb $0x01, al /* 8086 mode for both */ |
---|
159 | outb al, $0x21 |
---|
160 | call SYM(delay) |
---|
161 | outb al, $0xA1 |
---|
162 | call SYM(delay) |
---|
163 | |
---|
164 | movb $0xFF, al /* mask off all interrupts for now */ |
---|
165 | outb al, $0xA1 |
---|
166 | call SYM(delay) |
---|
167 | movb $0xFB, al /* mask all irq's but irq2 which */ |
---|
168 | outb al, $0x21 /* is cascaded */ |
---|
169 | call SYM(delay) |
---|
170 | |
---|
171 | jmp SYM (_establish_stack) # return to the bsp entry code |
---|
172 | |
---|
173 | /*-------------------------------------------------------------------------+ |
---|
174 | | Function: _return_to_monitor |
---|
175 | | Description: Return to board's monitor (we have none so simply restart). |
---|
176 | | Global Variables: None. |
---|
177 | | Arguments: None. |
---|
178 | | Returns: Nothing. |
---|
179 | +--------------------------------------------------------------------------*/ |
---|
180 | PUBLIC (_return_to_monitor) |
---|
181 | SYM (_return_to_monitor): |
---|
182 | |
---|
183 | call SYM (Timer_exit) |
---|
184 | call SYM (Clock_exit) |
---|
185 | jmp SYM (start) |
---|
186 | |
---|
187 | END_CODE |
---|
188 | |
---|
189 | /*----------------------------------------------------------------------------+ |
---|
190 | | DATA section |
---|
191 | +----------------------------------------------------------------------------*/ |
---|
192 | |
---|
193 | BEGIN_DATA |
---|
194 | |
---|
195 | PUBLIC (_Do_Load_IDT) |
---|
196 | SYM (_Do_Load_IDT): |
---|
197 | .byte 1 # load RTEMS own Interrupt Descriptor Table |
---|
198 | |
---|
199 | PUBLIC (_Do_Load_GDT) |
---|
200 | SYM (_Do_Load_GDT): |
---|
201 | .byte 0 # use the Global Descriptor Table that is already defined |
---|
202 | |
---|
203 | END_DATA |
---|
204 | |
---|
205 | END |
---|