[7150f00f] | 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 | | ************************************************************************** |
---|
[08311cc3] | 27 | | * COPYRIGHT (c) 1989-1999. |
---|
[6f9c75c3] | 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. |
---|
[7150f00f] | 33 | | ************************************************************************** |
---|
| 34 | | |
---|
[6f9c75c3] | 35 | | $Id$ |
---|
[7150f00f] | 36 | +--------------------------------------------------------------------------*/ |
---|
| 37 | |
---|
| 38 | |
---|
| 39 | #include "asm.h" |
---|
| 40 | |
---|
| 41 | /*----------------------------------------------------------------------------+ |
---|
| 42 | | CODE section |
---|
| 43 | +----------------------------------------------------------------------------*/ |
---|
[67a2288] | 44 | EXTERN (rtems_i8259_masks) |
---|
| 45 | |
---|
[7150f00f] | 46 | BEGIN_CODE |
---|
| 47 | |
---|
[4050a7f] | 48 | EXTERN (_establish_stack) |
---|
| 49 | EXTERN (Timer_exit) |
---|
[67a2288] | 50 | EXTERN (clockOff) |
---|
[7150f00f] | 51 | |
---|
| 52 | /*----------------------------------------------------------------------------+ |
---|
[df49c60] | 53 | | pc386_delay |
---|
[7150f00f] | 54 | +------------------------------------------------------------------------------ |
---|
[76c356f] | 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 | |
---|
[7150f00f] | 63 | +----------------------------------------------------------------------------*/ |
---|
[2116e33] | 64 | #define DELAY_USE_OUTB |
---|
| 65 | |
---|
[76c356f] | 66 | .p2align 4 |
---|
[df49c60] | 67 | .globl _pc386_delay |
---|
| 68 | .globl pc386_delay |
---|
| 69 | pc386_delay: |
---|
| 70 | _pc386_delay: |
---|
[2116e33] | 71 | #ifdef DELAY_USE_OUTB |
---|
| 72 | outb al, $0x80 # about 1uS delay on most machines |
---|
| 73 | #else |
---|
| 74 | movl $0x200, eax |
---|
[df49c60] | 75 | pc386_delay1: |
---|
[2116e33] | 76 | dec eax |
---|
[df49c60] | 77 | jnz pc386_delay1 |
---|
[2116e33] | 78 | #endif |
---|
[c3538f3] | 79 | ret |
---|
[76c356f] | 80 | |
---|
[7150f00f] | 81 | /*-------------------------------------------------------------------------+ |
---|
| 82 | | Function: _load_segments |
---|
[4050a7f] | 83 | | Description: Current environment is standard PC booted by grub. |
---|
| 84 | | So, there is no value in saving current GDT and IDT |
---|
[5d18fb0] | 85 | | settings we have to set it up ourseves. (Naturally |
---|
[4050a7f] | 86 | | it will be not so in case we are booted by some |
---|
| 87 | | boot monitor, however, then it will be different |
---|
[5d18fb0] | 88 | | BSP). After that we have to load board segment registers |
---|
[4050a7f] | 89 | | with apropriate values + reprogram PIC. |
---|
[7150f00f] | 90 | | Global Variables: None. |
---|
| 91 | | Arguments: None. |
---|
| 92 | | Returns: Nothing. |
---|
| 93 | +--------------------------------------------------------------------------*/ |
---|
[4050a7f] | 94 | .p2align 4 |
---|
| 95 | |
---|
[7150f00f] | 96 | PUBLIC (_load_segments) |
---|
| 97 | SYM (_load_segments): |
---|
[4050a7f] | 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 | +---------------------------------------------------------------------*/ |
---|
[7150f00f] | 123 | |
---|
| 124 | movb $0x11, al /* initialization sequence */ |
---|
| 125 | outb al, $0x20 /* send it to 8259A-1 */ |
---|
[df49c60] | 126 | call SYM(pc386_delay) |
---|
[7150f00f] | 127 | outb al, $0xA0 /* and to 8259A-2 */ |
---|
[df49c60] | 128 | call SYM(pc386_delay) |
---|
[7150f00f] | 129 | |
---|
| 130 | movb $0x20, al /* start of hardware int's (0x20) */ |
---|
| 131 | outb al, $0x21 |
---|
[df49c60] | 132 | call SYM(pc386_delay) |
---|
[7150f00f] | 133 | movb $0x28, al /* start of hardware int's 2 (0x28) */ |
---|
| 134 | outb al, $0xA1 |
---|
[df49c60] | 135 | call SYM(pc386_delay) |
---|
[7150f00f] | 136 | |
---|
| 137 | movb $0x04, al /* 8259-1 is master */ |
---|
| 138 | outb al, $0x21 |
---|
[df49c60] | 139 | call SYM(pc386_delay) |
---|
[7150f00f] | 140 | movb $0x02, al /* 8259-2 is slave */ |
---|
| 141 | outb al, $0xA1 |
---|
[df49c60] | 142 | call SYM(pc386_delay) |
---|
[7150f00f] | 143 | |
---|
| 144 | movb $0x01, al /* 8086 mode for both */ |
---|
| 145 | outb al, $0x21 |
---|
[df49c60] | 146 | call SYM(pc386_delay) |
---|
[7150f00f] | 147 | outb al, $0xA1 |
---|
[df49c60] | 148 | call SYM(pc386_delay) |
---|
[7150f00f] | 149 | |
---|
| 150 | movb $0xFF, al /* mask off all interrupts for now */ |
---|
| 151 | outb al, $0xA1 |
---|
[df49c60] | 152 | call SYM(pc386_delay) |
---|
[7150f00f] | 153 | movb $0xFB, al /* mask all irq's but irq2 which */ |
---|
| 154 | outb al, $0x21 /* is cascaded */ |
---|
[df49c60] | 155 | call SYM(pc386_delay) |
---|
[7150f00f] | 156 | |
---|
[99826740] | 157 | movw $0xFFFB, SYM(i8259s_cache) /* set up same values in cache */ |
---|
| 158 | |
---|
[7150f00f] | 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 | +--------------------------------------------------------------------------*/ |
---|
[4050a7f] | 168 | |
---|
| 169 | .p2align 4 |
---|
| 170 | |
---|
[7150f00f] | 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 | |
---|
[4050a7f] | 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): |
---|
[7150f00f] | 195 | |
---|
[4050a7f] | 196 | /* NULL segment */ |
---|
| 197 | .word 0, 0 |
---|
| 198 | .byte 0, 0, 0, 0 |
---|
[7150f00f] | 199 | |
---|
[4050a7f] | 200 | /* code segment */ |
---|
| 201 | .word 0xffff, 0 |
---|
| 202 | .byte 0, 0x9e, 0xcf, 0 |
---|
[7150f00f] | 203 | |
---|
[4050a7f] | 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) |
---|
[7150f00f] | 215 | |
---|
[4050a7f] | 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 |
---|
[7150f00f] | 236 | |
---|
[99826740] | 237 | .section .m_hdr |
---|
| 238 | .long 0x1BADB002 |
---|
| 239 | .long 0 |
---|
| 240 | .long 0xE4524FFE |
---|
[7150f00f] | 241 | END |
---|