Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:41

0001 /*-------------------------------------------------------------------------+
0002 | ldsegs.s v1.1 - PC386 BSP - 1997/08/07
0003 +--------------------------------------------------------------------------+
0004 | This file assists the board independent startup code by loading the proper
0005 | segment register values. The values loaded are board dependent. In addition
0006 | it contains code to enable the A20 line and to reprogram the PIC to relocate
0007 | the IRQ interrupt vectors to 0x20 -> 0x2f.
0008 | NOTE: No stack has been established when this routine is invoked.
0009 |   It returns by jumping back to bspentry.
0010 +--------------------------------------------------------------------------+
0011 | (C) Copyright 1997 -
0012 | - NavIST Group - Real-Time Distributed Systems and Industrial Automation
0013 |
0014 | http://pandora.ist.utl.pt
0015 |
0016 | Instituto Superior Tecnico * Lisboa * PORTUGAL
0017 +--------------------------------------------------------------------------+
0018 | Disclaimer:
0019 |
0020 | This file is provided "AS IS" without warranty of any kind, either
0021 | expressed or implied.
0022 +--------------------------------------------------------------------------+
0023 | This code is base on:
0024 |   ldsegs.s,v 1.4 1996/04/20 16:48:30 joel Exp - go32 BSP
0025 | With the following copyright notice:
0026 | **************************************************************************
0027 | *  COPYRIGHT (c) 1989-1999.
0028 | *  On-Line Applications Research Corporation (OAR).
0029 | *
0030 | *  The license and distribution terms for this file may be
0031 | *  found in the file LICENSE in this distribution or at
0032 | *  http://www.rtems.org/license/LICENSE.
0033 | **************************************************************************
0034 +--------------------------------------------------------------------------*/
0035 
0036 #include <rtems/asm.h>
0037 #include <bsp/tblsizes.h> /* contains sizes of GDT and IDT */
0038 #include <bspopts.h>
0039 
0040 /*----------------------------------------------------------------------------+
0041 | CODE section
0042 +----------------------------------------------------------------------------*/
0043 EXTERN (rtems_i8259_masks)
0044 
0045 BEGIN_CODE
0046 
0047         EXTERN (_establish_stack)
0048     EXTERN (Timer_exit)
0049     EXTERN (clockOff)
0050 
0051 /*----------------------------------------------------------------------------+
0052 | pc386_delay
0053 +------------------------------------------------------------------------------
0054 | Delay is needed after doing I/O.
0055 |
0056 | The outb version is OK on most machines BUT the loop version ...
0057 |
0058 | will delay for 1us on 1Gz machine, it will take a little bit
0059 | longer on slower machines, however, it does not matter because we
0060 | are going to call this function only a few times
0061 
0062 +----------------------------------------------------------------------------*/
0063 #define DELAY_USE_OUTB
0064 
0065     .p2align 4
0066     .globl _pc386_delay
0067     .globl pc386_delay
0068 pc386_delay:
0069 _pc386_delay:
0070 #ifdef DELAY_USE_OUTB
0071     outb    al, $0x80   # about 1uS delay on most machines
0072 #else
0073     movl    $0x200, eax
0074 pc386_delay1:
0075     dec eax
0076     jnz pc386_delay1
0077 #endif
0078     ret
0079 
0080 /*-------------------------------------------------------------------------+
0081 |         Function: _load_segments
0082 |      Description: Current environment is standard PC booted by grub.
0083 |                   So, there is no value in saving current GDT and IDT
0084 |                   settings we have to set it up ourseves. (Naturally
0085 |               it will be not so in case we are booted by some
0086 |                   boot monitor, however, then it will be different
0087 |                   BSP). After that we have to load board segment registers
0088 |                   with apropriate values +  reprogram PIC.
0089 | Global Variables: None.
0090 |        Arguments: None.
0091 |          Returns: Nothing.
0092 +--------------------------------------------------------------------------*/
0093     .p2align 4
0094 
0095         PUBLIC (_load_segments)
0096 SYM (_load_segments):
0097 
0098     lgdt SYM(gdtdesc)
0099     lidt SYM(IDT_Descriptor)
0100 
0101     /* Load CS, flush prefetched queue */
0102     ljmp $0x8, $next_step
0103 
0104 next_step:
0105         /* Load segment registers */
0106     movw $0x10, ax
0107     movw ax, ss
0108     movw ax, ds
0109     movw ax, es
0110     movw ax, fs
0111     movw ax, gs
0112 
0113 /*---------------------------------------------------------------------+
0114 | Now we have to reprogram the interrupts :-(. We put them right after
0115 | the intel-reserved hardware interrupts, at int 0x20-0x2F. There they
0116 | won't mess up anything. Sadly IBM really messed this up with the
0117 | original PC, and they haven't been able to rectify it afterwards. Thus
0118 | the bios puts interrupts at 0x08-0x0f, which is used for the internal
0119 | hardware interrupts as well. We just have to reprogram the 8259's, and
0120 | it isn't fun.
0121 +---------------------------------------------------------------------*/
0122 
0123     movb    $0x11, al       /* initialization sequence          */
0124     outb    al, $0x20       /* send it to 8259A-1               */
0125     call    SYM(pc386_delay)
0126     outb    al, $0xA0       /* and to 8259A-2                   */
0127     call    SYM(pc386_delay)
0128 
0129     movb    $0x20, al       /* start of hardware int's (0x20)   */
0130     outb    al, $0x21
0131     call    SYM(pc386_delay)
0132     movb    $0x28, al       /* start of hardware int's 2 (0x28) */
0133     outb    al, $0xA1
0134     call    SYM(pc386_delay)
0135 
0136     movb    $0x04, al       /* 8259-1 is master                 */
0137     outb    al, $0x21
0138     call    SYM(pc386_delay)
0139     movb    $0x02, al       /* 8259-2 is slave                  */
0140     outb    al, $0xA1
0141     call    SYM(pc386_delay)
0142 
0143     movb    $0x01, al       /* 8086 mode for both               */
0144     outb    al, $0x21
0145     call    SYM(pc386_delay)
0146     outb    al, $0xA1
0147     call    SYM(pc386_delay)
0148 
0149     /*
0150      * The IMR values must correspond to the initial value of i8259s_cache.
0151      */
0152     movb    $0xFF, al       /* mask off all interrupts for now  */
0153     outb    al, $0xA1
0154     call    SYM(pc386_delay)
0155     movb    $0xFB, al       /* mask all irq's but irq2 which    */
0156     outb    al, $0x21       /* is cascaded                      */
0157     call    SYM(pc386_delay)
0158     jmp SYM (_establish_stack)  # return to the bsp entry code
0159 
0160 /*-------------------------------------------------------------------------+
0161 |         Function: _default_int_handler
0162 |      Description: default interrupt handler
0163 | Global Variables: None.
0164 |        Arguments: None.
0165 |          Returns: Nothing.
0166 +--------------------------------------------------------------------------*/
0167     .p2align 4
0168 
0169 /*---------------------------------------------------------------------------+
0170 | GDT itself
0171 +--------------------------------------------------------------------------*/
0172 #if GDT_SIZE < NUM_SYSTEM_GDT_DESCRIPTORS
0173 #error "GDT_SIZE must be at least NUM_SYSTEM_GDT_DESCRIPTORS"
0174 #endif
0175 
0176 BEGIN_DATA
0177     .p2align 4
0178 
0179     PUBLIC (_Global_descriptor_table)
0180 SYM (_Global_descriptor_table):
0181 
0182     /* NULL segment */
0183     .word 0, 0
0184     .byte 0, 0, 0, 0
0185 
0186     /* code segment */
0187     .word 0xffff, 0
0188     .byte 0, 0x9e, 0xcf, 0
0189 
0190     /* data segment */
0191     .word 0xffff, 0
0192     .byte 0, 0x92, 0xcf, 0
0193 
0194     /* gs segment(s) */
0195     .rept (NUM_SYSTEM_GDT_DESCRIPTORS - 3)
0196     .word 0xffff, 0
0197     .byte 0, 0x92, 0xcf, 0
0198     .endr
0199 
0200         /* allocated space for user segments */
0201         .rept (GDT_SIZE - NUM_SYSTEM_GDT_DESCRIPTORS)
0202         .word 0,0,0,0
0203         .endr
0204 
0205 /*---------------------------------------------------------------------------+
0206 | Descriptor of GDT
0207 +--------------------------------------------------------------------------*/
0208         PUBLIC(gdtdesc)
0209 SYM(gdtdesc):
0210     .word (GDT_SIZE*8 - 1)
0211     .long SYM (_Global_descriptor_table)
0212 
0213 /*---------------------------------------------------------------------------+
0214 | IDT itself
0215 +---------------------------------------------------------------------------*/
0216     .p2align 4
0217 
0218     PUBLIC(Interrupt_descriptor_table)
0219 SYM(Interrupt_descriptor_table):
0220     .rept IDT_SIZE
0221     .word 0,0,0,0
0222     .endr
0223 
0224 /*---------------------------------------------------------------------------+
0225 | Descriptor of IDT
0226 +--------------------------------------------------------------------------*/
0227 
0228     .p2align 4
0229     PUBLIC(IDT_Descriptor)
0230 SYM(IDT_Descriptor):
0231     .word  (IDT_SIZE*8 - 1)
0232     .long  SYM (Interrupt_descriptor_table)
0233 
0234 END_DATA
0235 
0236     .section .m_hdr
0237     .long 0x1BADB002
0238     .long 0
0239     .long 0xE4524FFE
0240 END