1 |
30 |
unneback |
/*-------------------------------------------------------------------------+
|
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 |
|
|
| Constants
|
24 |
|
|
+----------------------------------------------------------------------------*/
|
25 |
|
|
|
26 |
|
|
.set PROT_CODE_SEG, 0x08 # offset of code segment descriptor into GDT
|
27 |
|
|
.set PROT_DATA_SEG, 0x10 # offset of code segment descriptor into GDT
|
28 |
|
|
.set CR0_PE, 1 # protected mode flag on CR0 register
|
29 |
|
|
.set HDRSTART, HEADERADDR # address of start of bin2boot header
|
30 |
|
|
.set HDROFF, 0x24 # offset into bin2boot header of start32 addr
|
31 |
|
|
.set STACKOFF, 0x200-0x10 # offset to load into %esp, from start of image
|
32 |
|
|
|
33 |
|
|
/* #define NEW_GAS */
|
34 |
|
|
/*----------------------------------------------------------------------------+
|
35 |
|
|
| CODE section
|
36 |
|
|
+----------------------------------------------------------------------------*/
|
37 |
|
|
|
38 |
|
|
.text
|
39 |
|
|
|
40 |
|
|
.globl _start16 # entry point
|
41 |
|
|
.globl start16
|
42 |
|
|
start16:
|
43 |
|
|
_start16:
|
44 |
|
|
|
45 |
|
|
.code16
|
46 |
|
|
|
47 |
|
|
cli # DISABLE INTERRUPTS!!!
|
48 |
|
|
|
49 |
|
|
movw %cs, %ax #
|
50 |
|
|
movw %ax, %ds # set the rest of real mode registers
|
51 |
|
|
movw %ax, %es #
|
52 |
|
|
movw %ax, %ss #
|
53 |
|
|
|
54 |
|
|
#if defined(RTEMS_VIDEO_80x50)
|
55 |
|
|
|
56 |
|
|
/*---------------------------------------------------------------------+
|
57 |
|
|
| Switch VGA video to 80 lines x 50 columns mode. Has to be done before
|
58 |
|
|
| turning protected mode on since it uses BIOS int 10h (video) services.
|
59 |
|
|
+---------------------------------------------------------------------*/
|
60 |
|
|
|
61 |
|
|
movw $0x0003, %ax # forced set
|
62 |
|
|
int $0x10
|
63 |
|
|
movw $0x1112, %ax # use 8x8 font
|
64 |
|
|
xorb %bl, %bl
|
65 |
|
|
int $0x10
|
66 |
|
|
movw $0x1201, %ax # turn off cursor emulation
|
67 |
|
|
movb $0x34, %bl
|
68 |
|
|
int $0x10
|
69 |
|
|
movb $0x01, %ah # define cursor (scan lines 0 to 7)
|
70 |
|
|
movw $0x0007, %cx
|
71 |
|
|
int $0x10
|
72 |
|
|
|
73 |
|
|
#endif /* RTEMS_VIDEO_80x50 */
|
74 |
|
|
|
75 |
|
|
/*---------------------------------------------------------------------+
|
76 |
|
|
| Bare PC machines boot in real mode! We have to turn protected mode on.
|
77 |
|
|
+---------------------------------------------------------------------*/
|
78 |
|
|
|
79 |
|
|
lgdt gdtptr - start16 # load Global Descriptor Table
|
80 |
|
|
movl %cr0, %eax
|
81 |
|
|
orl $CR0_PE, %eax
|
82 |
|
|
movl %eax, %cr0 # turn on protected mode
|
83 |
|
|
|
84 |
|
|
#ifdef NEW_GAS
|
85 |
|
|
ljmpl $PROT_CODE_SEG, $1f # flush prefetch queue, and reload %cs
|
86 |
|
|
#else
|
87 |
|
|
ljmp $PROT_CODE_SEG, $1f # flush prefetch queue, and reload %cs
|
88 |
|
|
#endif
|
89 |
|
|
.code32
|
90 |
|
|
1:
|
91 |
|
|
/*---------------------------------------------------------------------+
|
92 |
|
|
| load the other segment registers
|
93 |
|
|
+---------------------------------------------------------------------*/
|
94 |
|
|
movl $PROT_DATA_SEG, %eax
|
95 |
|
|
movw %ax, %ds
|
96 |
|
|
movw %ax, %es
|
97 |
|
|
movw %ax, %ss
|
98 |
|
|
movl $start16 + STACKOFF, %esp # set up stack pointer
|
99 |
|
|
addl $start16 + STACKOFF, %ebp # set up stack pointer
|
100 |
|
|
|
101 |
|
|
/*---------------------------------------------------------------------+
|
102 |
|
|
| we have to enable A20 in order to access memory above 1MByte
|
103 |
|
|
+---------------------------------------------------------------------*/
|
104 |
|
|
call empty_8042
|
105 |
|
|
movb $0xD1, %al # command write
|
106 |
|
|
outb %al, $0x64
|
107 |
|
|
call empty_8042
|
108 |
|
|
movb $0xDF, %al # A20 on
|
109 |
|
|
outb %al, $0x60
|
110 |
|
|
call empty_8042
|
111 |
|
|
|
112 |
|
|
call pc386_delay
|
113 |
|
|
call pc386_delay
|
114 |
|
|
call pc386_delay
|
115 |
|
|
|
116 |
|
|
movl %cs:HDRSTART + HDROFF, %eax #
|
117 |
|
|
pushl %eax # jump to start of 32 bit code
|
118 |
|
|
ret #
|
119 |
|
|
|
120 |
|
|
/*----------------------------------------------------------------------------+
|
121 |
|
|
| pc386_delay
|
122 |
|
|
+------------------------------------------------------------------------------
|
123 |
|
|
| Delay is needed after doing I/O.
|
124 |
|
|
|
|
125 |
|
|
| The outb version is OK on most machines BUT the loop version ...
|
126 |
|
|
|
|
127 |
|
|
| will delay for 1us on 1Gz machine, it will take a little bit
|
128 |
|
|
| longer on slower machines, however, it does not matter because we
|
129 |
|
|
| are going to call this function only a few times
|
130 |
|
|
!
|
131 |
|
|
| NOTE: Saving the content of the EAX register just in case. - Rosimildo.
|
132 |
|
|
+----------------------------------------------------------------------------*/
|
133 |
|
|
.p2align 4
|
134 |
|
|
.globl _pc386_delay
|
135 |
|
|
.globl pc386_delay
|
136 |
|
|
pc386_delay:
|
137 |
|
|
_pc386_delay:
|
138 |
|
|
pushl %eax
|
139 |
|
|
#if defined(USE_OUTB_FOR_DELAY)
|
140 |
|
|
outb %al, $0x80 # about 1uS delay on most machines
|
141 |
|
|
|
142 |
|
|
#else
|
143 |
|
|
|
144 |
|
|
movl $0x200, %eax
|
145 |
|
|
pc386_delay1:
|
146 |
|
|
dec %eax
|
147 |
|
|
jnz pc386_delay1
|
148 |
|
|
#endif
|
149 |
|
|
popl %eax
|
150 |
|
|
ret
|
151 |
|
|
|
152 |
|
|
/*----------------------------------------------------------------------------+
|
153 |
|
|
| empty_8042
|
154 |
|
|
+------------------------------------------------------------------------------
|
155 |
|
|
| This routine checks that the keyboard command queue is empty (after emptying
|
156 |
|
|
| the output buffers).
|
157 |
|
|
| No timeout is used - if this hangs there is something wrong with the machine,
|
158 |
|
|
| and we probably couldn't proceed anyway.
|
159 |
|
|
+----------------------------------------------------------------------------*/
|
160 |
|
|
.p2align 4
|
161 |
|
|
.globl _empty_8042
|
162 |
|
|
.globl empty_8042
|
163 |
|
|
empty_8042:
|
164 |
|
|
_empty_8042:
|
165 |
|
|
call pc386_delay
|
166 |
|
|
inb $0x64, %al # 8042 status port
|
167 |
|
|
testb $0x01, %al # output buffer?
|
168 |
|
|
jz no_output
|
169 |
|
|
call pc386_delay
|
170 |
|
|
in $0x60, %al # read it
|
171 |
|
|
jmp empty_8042
|
172 |
|
|
no_output:
|
173 |
|
|
test $0x02, %al # is input buffer full?
|
174 |
|
|
jnz empty_8042 # yes - loop
|
175 |
|
|
ret
|
176 |
|
|
|
177 |
|
|
/*----------------------------------------------------------------------------+
|
178 |
|
|
| DATA section
|
179 |
|
|
+----------------------------------------------------------------------------*/
|
180 |
|
|
|
181 |
|
|
/**************************
|
182 |
|
|
* GLOBAL DESCRIPTOR TABLE *
|
183 |
|
|
**************************/
|
184 |
|
|
|
185 |
|
|
.p2align 4
|
186 |
|
|
gdtptr:
|
187 |
|
|
/* we use the NULL descriptor to store the GDT pointer - a trick quite
|
188 |
|
|
nifty due to: Robert Collins (rcollins@x86.org) */
|
189 |
|
|
.word gdtlen - 1
|
190 |
|
|
.long gdtptr
|
191 |
|
|
.word 0x0000
|
192 |
|
|
|
193 |
|
|
/* code segment */
|
194 |
|
|
.word 0xffff, 0
|
195 |
|
|
.byte 0, 0x9f, 0xcf, 0
|
196 |
|
|
|
197 |
|
|
/* data segment */
|
198 |
|
|
.word 0xffff, 0
|
199 |
|
|
.byte 0, 0x93, 0xcf, 0
|
200 |
|
|
|
201 |
|
|
.set gdtlen, . - gdtptr # length of GDT
|
202 |
|
|
|