summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386/i386ex/start/start.s
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/i386/i386ex/start/start.s')
-rw-r--r--c/src/lib/libbsp/i386/i386ex/start/start.s572
1 files changed, 572 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/i386/i386ex/start/start.s b/c/src/lib/libbsp/i386/i386ex/start/start.s
new file mode 100644
index 0000000000..51bbea97d4
--- /dev/null
+++ b/c/src/lib/libbsp/i386/i386ex/start/start.s
@@ -0,0 +1,572 @@
+/*
+ * This file is the main boot and configuration file for the i386ex. It is
+ * solely responsible for initializing the internal register set to reflect
+ * the proper board configuration. This version is the "generic" i386ex
+ * startup:
+ *
+ * 1) 512K flask ROM @3f80000
+ * 2) 1 Mb RAM @ 0x0
+ * 3) Timer0 used as RTEMS clock ticker, 1 msec tick rate.
+ * 4) READY# is generated by CPU
+ *
+ * The file is a multi-section file, with sections as follows:
+ * 1) interrupt gates, in section "ints"
+ * 2) interrupt descriptor table, in section "idt"
+ * 3) global descriptor table, in section "gdt"
+ * 4) reset in section "reset"
+ * 5) and initial boot code in section " initial"
+ *
+ * Submitted by:
+ *
+ * Erik Ivanenko
+ * University of Toronto
+ * erik.ivanenko@utoronto.ca
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * $Id$
+ */
+
+#include "asm.h"
+#include "macros.inc"
+#include "80386ex.inc"
+
+
+ EXTERN (main) /* exits to bspstart */
+ EXTERN (stack_start) /* defined in startup/linkcmds */
+
+ .section .idt
+
+BEGIN_DATA
+ PUBLIC (Interrupt_descriptor_table)
+ PUBLIC(SYM(IDTR) )
+SYM(IDTR): DESC3( SYM(IDT), 0x188 );
+SYM (Interrupt_descriptor_table):
+SYM(IDT):
+SYM(GATE_DIVIDE_ERROR): INTERRUPT_GATE( DIVIDE_ERROR );
+SYM(GATE_DEBUG_EXCEPTION): INTERRUPT_GATE( DEBUG_EXCEPTION );
+SYM(GATE_NMI_INTERRUPT): INTERRUPT_GATE( NMI_INTERRUPT );
+SYM(GATE_BREAKPOINT): INTERRUPT_GATE( BREAKPOINT );
+SYM(GATE_INTO_OVERFLOW ): INTERRUPT_GATE( INTO_OVERFLOW );
+SYM(GATE_BOUND_EXCEEDED ): INTERRUPT_GATE( BOUND_EXCEEDED );
+SYM(GATE_INVALID_OPCODE ): INTERRUPT_GATE( INVALID_OPCODE );
+SYM(GATE_COPRO_NA ): INTERRUPT_GATE( COPRO_NA );
+SYM(GATE_DOUBLE_FAULT ): INTERRUPT_GATE( DOUBLE_FAULT );
+SYM(GATE_COPRO_SEG_OVERRUN ): INTERRUPT_GATE( COPRO_SEG_OVERRUN );
+SYM(GATE_INVALID_TSS ): INTERRUPT_GATE( INVALID_TSS );
+SYM(GATE_SEGMENT_NOT_PRESENT ): INTERRUPT_GATE( SEGMENT_NOT_PRESENT );
+SYM(GATE_STACK_FAULT ): INTERRUPT_GATE( STACK_FAULT );
+SYM(GATE_GPF ): INTERRUPT_GATE( GPF );
+SYM(GATE_PAGE_FAULT ): INTERRUPT_GATE( PAGE_FAULT );
+SYM(GATE_RESERVED_1 ): INTERRUPT_GATE( RESERVED );
+SYM(GATE_COPRO_ERROR ): INTERRUPT_GATE( COPRO_ERROR );
+SYM(GATE_RESERVED_17): INTERRUPT_GATE( RESERVED_17 );
+SYM(GATE_RESERVED_18): INTERRUPT_GATE( RESERVED_18 );
+SYM(GATE_RESERVED_19): INTERRUPT_GATE( RESERVED_19 );
+SYM(GATE_RESERVED_20): INTERRUPT_GATE( RESERVED_20 );
+SYM(GATE_RESERVED_21): INTERRUPT_GATE( RESERVED_21 );
+SYM(GATE_RESERVED_22): INTERRUPT_GATE( RESERVED_22 );
+SYM(GATE_RESERVED_23): INTERRUPT_GATE( RESERVED_23 );
+SYM(GATE_RESERVED_24): INTERRUPT_GATE( RESERVED_24 );
+SYM(GATE_RESERVED_25): INTERRUPT_GATE( RESERVED_25 );
+SYM(GATE_RESERVED_26): INTERRUPT_GATE( RESERVED_26 );
+SYM(GATE_RESERVED_27): INTERRUPT_GATE( RESERVED_27 );
+SYM(GATE_RESERVED_28): INTERRUPT_GATE( RESERVED_28 );
+SYM(GATE_RESERVED_29): INTERRUPT_GATE( RESERVED_29 );
+SYM(GATE_RESERVED_30): INTERRUPT_GATE( RESERVED_30 );
+SYM(GATE_RESERVED_31): INTERRUPT_GATE( RESERVED_31 );
+
+SYM ( GATE_TIMINT0): INTERRUPT_GATE( TIMINT0 );
+SYM ( GATE_MASTER_IR2 ): INTERRUPT_GATE( MASTER_IR2 );
+SYM ( GATE_SIOINT1 ): INTERRUPT_GATE( SIOINT1 );
+SYM ( GATE_SIOINT2 ): INTERRUPT_GATE( SIOINT2 );
+SYM ( GATE_DMAINT ): INTERRUPT_GATE( DMAINT );
+SYM ( GATE_UNUSED_IR5 ): INTERRUPT_GATE( UNUSED_IR5);
+SYM ( GATE_UNUSED_IR6 ): INTERRUPT_GATE( UNUSED_IR6);
+SYM ( GATE_UNUSED_IR7 ): INTERRUPT_GATE( UNUSED_IR7);
+SYM ( GATE_SLAVE_IR0 ): INTERRUPT_GATE( SLAVE_IR0 );
+SYM ( GATE_SLAVE_IR1 ): INTERRUPT_GATE( SLAVE_IR1 );
+SYM ( GATE_SLAVE_IR2 ): INTERRUPT_GATE( SLAVE_IR2 );
+SYM ( GATE_SLAVE_IR3 ): INTERRUPT_GATE( SLAVE_IR3 );
+SYM ( GATE_SLAVE_IR4 ): INTERRUPT_GATE( SLAVE_IR4 );
+SYM ( GATE_SLAVE_IR5 ): INTERRUPT_GATE( SLAVE_IR5 );
+SYM ( GATE_SLAVE_IR6 ): INTERRUPT_GATE( SLAVE_IR6 );
+SYM ( GATE_SLAVE_IR7 ): INTERRUPT_GATE( SLAVE_IR7 );
+END_DATA
+
+ .section .gdt
+BEGIN_DATA
+ PUBLIC (_Global_descriptor_table)
+
+SYM(GDTR): DESC3( GDT_TABLE, 0x1f ); # one less than the size
+SYM (_Global_descriptor_table):
+SYM(GDT):
+SYM(GDT_TABLE): DESC2(0,0,0,0,0,0);
+SYM(GDT_ALIAS): DESC2(32,0x1000,0x0,0x93,0,0x0);
+SYM(GDT_CODE): DESC2(0xffff,0,0x0,0x9B,0xDF,0x00);
+SYM(GDT_DATA): DESC2(0xffff,0,0x0,0x92,0xDF,0x00); # was CF
+SYM(GDT_END):
+
+END_DATA
+
+
+/* This section is the section that is used by the interrupt
+ descriptor table. It is used to provide the IDT with the
+ correct vector offsets. It is for symbol definition only.
+*/
+
+ .section .ints
+
+SYM(INTERRUPT_HANDLERS):
+SYM(DIVIDE_ERROR): jmp SYM(DIVIDE_ERROR)
+SYM(DEBUG_EXCEPTION): jmp SYM(DEBUG_EXCEPTION)
+SYM(NMI_INTERRUPT): jmp SYM(NMI_INTERRUPT)
+SYM(BREAKPOINT): jmp SYM(BREAKPOINT)
+SYM(INTO_OVERFLOW): jmp SYM(INTO_OVERFLOW)
+SYM(BOUND_EXCEEDED): jmp SYM(BOUND_EXCEEDED)
+SYM(INVALID_OPCODE): jmp SYM(INVALID_OPCODE)
+SYM(COPRO_NA): jmp SYM(COPRO_NA)
+SYM(DOUBLE_FAULT): jmp SYM(DOUBLE_FAULT)
+SYM(COPRO_SEG_OVERRUN): jmp SYM(COPRO_SEG_OVERRUN)
+SYM(INVALID_TSS): jmp SYM(INVALID_TSS)
+SYM(RESERVED): JMP SYM(RESERVED)
+SYM(COPRO_ERROR): JMP SYM(COPRO_ERROR)
+SYM(PAGE_FAULT): JMP SYM(PAGE_FAULT)
+SYM(GPF): JMP SYM(GPF)
+SYM(STACK_FAULT): JMP SYM(STACK_FAULT)
+SYM(SEGMENT_NOT_PRESENT): jmp SYM(SEGMENT_NOT_PRESENT)
+SYM(RESERVED_17): jmp SYM(RESERVED_17)
+SYM(RESERVED_18): jmp SYM(RESERVED_18)
+SYM(RESERVED_19): jmp SYM(RESERVED_19)
+SYM(RESERVED_20): jmp SYM(RESERVED_20)
+SYM(RESERVED_21): jmp SYM(RESERVED_21)
+SYM(RESERVED_22): jmp SYM(RESERVED_22)
+SYM(RESERVED_23): jmp SYM(RESERVED_23)
+SYM(RESERVED_24): jmp SYM(RESERVED_24)
+SYM(RESERVED_25): jmp SYM(RESERVED_25)
+SYM(RESERVED_26): jmp SYM(RESERVED_26)
+SYM(RESERVED_27): jmp SYM(RESERVED_27)
+SYM(RESERVED_28): jmp SYM(RESERVED_28)
+SYM(RESERVED_29): jmp SYM(RESERVED_29)
+SYM(RESERVED_30): jmp SYM(RESERVED_30)
+SYM(RESERVED_31): jmp SYM(RESERVED_31)
+SYM(TIMINT0): nop; iret
+SYM(MASTER_IR2): jmp SYM(MASTER_IR2)
+SYM(SIOINT1): jmp SYM(SIOINT1)
+SYM(SIOINT2): jmp SYM(SIOINT2)
+SYM(DMAINT): jmp SYM(DMAINT)
+SYM(UNUSED_IR5): jmp SYM(UNUSED_IR5)
+SYM(UNUSED_IR6): JMP SYM(UNUSED_IR6)
+SYM(UNUSED_IR7): JMP SYM(UNUSED_IR7)
+SYM(SLAVE_IR0): JMP SYM(SLAVE_IR0)
+SYM(SLAVE_IR1): JMP SYM(SLAVE_IR1)
+SYM(SLAVE_IR2): nop; iret
+SYM(SLAVE_IR3): JMP SYM(SLAVE_IR3)
+SYM(SLAVE_IR4): JMP SYM(SLAVE_IR4)
+SYM(SLAVE_IR5): JMP SYM(SLAVE_IR5)
+SYM(SLAVE_IR6): JMP SYM(SLAVE_IR6)
+SYM(SLAVE_IR7): JMP SYM(SLAVE_IR7)
+
+ PUBLIC( SYM(_initInternalRegisters) )
+
+
+ .section .reset
+
+ PUBLIC ( SYM(reset) )
+SYM(reset):
+ .code16
+ nop
+ cli
+ jmp SYM(_initInternalRegisters) /* different section in this file */
+ .code32 /* in case this section moves */
+ nop /* required by CHIP LAB to pad out size */
+ nop
+ nop
+ nop
+ nop
+
+ .section .initial
+
+/*
+ * Enable access to peripheral register at expanded I/O addresses
+ */
+ .code16
+SYM(_initInternalRegisters):
+ movw $0x8000 , ax
+ outb al , $REMAPCFGH
+ xchg al , ah
+ outb al,$REMAPCFGL
+ outw ax, $REMAPCFG ;
+
+
+/*
+ * Configure operation of the A20 Address Line
+ */
+SYM(A20):
+ movw $PORT92 , dx
+
+ inb dx , al # clear A20 port reset
+ andb $0xfe , al # b0 Fast Reset(0)=disabled,(1)=reset triggered
+ orb $0x02 , al # Bit 1 Fast A20 = 0 (always 0) else enabled.
+ outb al , dx
+
+SYM(Watchdog):
+ SetExRegByte( WDTSTATUS, 0x01 ) # disable watchdog timer
+
+/*
+ * Initialize Refresh Control Unit for:
+ * Refresh Address = 0x0000
+
+ * Refresh gate between rows is 15.6 uSec
+ * Using a CLK2 frequency of 50Mhz ( 25Mhz CPU )
+ * The refresh unit is enabled
+ * The refresh pin is not used.
+ */
+
+SYM(InitRCU):
+ SetExRegWord( RFSCIR , 390) # refresh interval was 390, tried 312
+ SetExRegWord( RFSBAD , 0x0) # base address
+ SetExRegWord( RFSADD , 0x0) # address register
+ SetExRegWord( RFSCON , 0x8000) # enable bit
+
+/*
+ * Initialize clock and power mgmt unit for:
+ * Clock Frequency = 50 Mhz
+ * Prescaled clock output = 1.19318 Mhz
+ * ( matches standard PC )
+ * Normal halt instructions
+ */
+
+SYM(InitClk):
+ SetExRegByte( PWRCON, 0x0 )
+ SetExRegWord( CLKPRS, 0x13)
+
+/**************************************************************
+ * Initialize the Pin Configurations
+ *************************************************************/
+
+/*
+ * Initialize I/O port 1 for:
+ * PIN 0 = 1, DCD0# to package pin
+ * PIN 1 = 1, RTS0# to package pin
+ * PIN 2 = 1, DTR0# to package pin
+ * PIN 3 = 1, DSR0# to package pin
+ * PIN 4 = 1, RI0# to package pin
+ * PIN 5 = 0, Outport (FLASH Vpp Enable, 0=Enable 1=Disable)
+ * PIN 6 = 0, Outport (P16_HOLD to 386ex option header JP7 pin 5)
+ * PIN 7 = 0, Outport (P17_HOLD to 386ex option header JP7 pin 3)
+ */
+
+SYM(InitPort1):
+ SetExRegByte( P1LTC , 0xff )
+ SetExRegByte( P1DIR , 0x0 )
+ SetExRegByte( P1CFG , 0x1f)
+
+/*
+ * Initialize I/O port 2 for:
+ * PIN 0 = 0, Outport (P20_CS0# to 386ex option header JP7 pin 11)
+ * PIN 1 = 0, Outport (P21_CS1# to 386ex option header JP7 pin 9)
+ * PIN 2 = 1, CS2# (SMRAM) If not using CS2 can be configured as.?
+ * PIN 3 = 0, Outport ( no connect )
+ * PIN 4 = 1, CS#4 (DRAM)
+ * PIN 5 = 1, RXD0 input. See not for I/0 port 1 pins 1-4
+ * PIN 6 = 1, TXD0 output.
+ * PIN 7 = 1, CTS0# input.
+ */
+
+SYM(InitPort2):
+ SetExRegByte( P2LTC , 0xff )
+ SetExRegByte( P2DIR , 0x0 )
+ SetExRegByte( P2CFG , 0xfe)
+
+/*
+ * Initialize I/O port 3 P3CFG
+ * PIN 0 = 1, TMROUT0 to package pin
+ * PIN 1 = 0, (TMROUT1 to 386ex option header JP7 pin 23)
+ * PIN 2 = 0, INT0 (IR1) disabled, (P3.2 out to JP7 pin 21)
+ * PIN 3 = 0, INT1 (IR5) disbled (P3.3 to option header JP7 pin 19)
+ * PIN 4 = 0, INT2 (IR6) disbled (P3.4 to option header JP7 pin 17)
+ * PIN 5 = 0, INT2 (IR7) disabled (P3.5 to 386ex header JP7 pin 15)
+ * PIN 6 = 0, Inport (Debugger Break P3.6/PWRD to package pin )
+ * P3.6 selected
+ * PIN 7 = 0, COMCLK output disabled, 1.8432 Mhz OSC1 oscillator.
+ * ( Debbugger uses COMCLK as the clocking source )
+ * P3.7 connected to package pin.
+ */
+
+SYM(InitPort3):
+ SetExRegByte( P3LTC , 0xff )
+ SetExRegByte( P3DIR , 0x41 )
+ SetExRegByte( P3CFG , 0x09 ) # can check TMROUT0
+/*
+ * Initialize Peripheral Pin Configurations:
+ * PIN 0 = 1, RTS1# to package pin
+ * PIN 1 = 1, DTR1# to package pin
+ * PIN 2 = 1, TXD1 out to package pin
+ * PIN 3 = 0, EOP#/TC
+ * PIN 4 = 0, DACK0#
+ * PIN 5 = 1, Timer2
+ * PIN 6 = 0, 0 => CS6# connected to package pin
+ * PIN 7 = 0, Don't care
+ */
+
+SYM(InitPeriph):
+ SetExRegByte( PINCFG , 0x24)
+
+/*
+ * Initialize the Asynchronous Serial Ports:
+ * BIT 7 = 1, Internal SIO1 modem signals
+ * BIT 6 = 1, Internal SIO0 modem signals
+ * BIT 2 = 0, PSCLK for SSIO clock
+ * BIT 1 = 1, SERCLK for SIO1 clock
+ * BIT 0 = 1, SERCLK for SIO0 clock
+ */
+
+SYM(InitSIO):
+ SetExRegByte( SIOCFG, 0xC3 ) # SIOn clocked internally
+
+ SetExRegByte( LCR0, 0x80 ) # latch DLL0, DLH0
+ SetExRegByte( DLL0, 0x51 ) # 0x51 sets to 9600 baud 0x7 -> 115,200
+ SetExRegByte( DLH0, 0x00 ) # 0x145 is 2400 baud
+ SetExRegByte( LCR0, 0x03 ) # enable r/w buffers, IER0 accessible
+ # mode 8-n-1
+ SetExRegByte( IER0, 0x00 ) # was 0x0f All interrupts detected
+
+ SetExRegByte( LCR1, 0x80 ) # latch DLL0, DLH0
+ SetExRegByte( DLL1, 0x51 ) # 0x51 set to 9600 baud, 0x7 = 115200
+ SetExRegByte( DLH1, 0x00 ) # 0x145 is 2400 baud
+ SetExRegByte( LCR1, 0x03 ) # enable r/w buffers, IER1 accessible
+ # reg 8-n-1
+ SetExRegByte( IER1, 0x00 ) # was 0x0f - All interrupts detected
+
+SYM(InitMCR):
+/*
+ * Initialize Timer for:
+ * BIT 7 = 1, Timer clocks disabled
+ * BIT 6 = 0, Reserved
+ * BIT 5 = 1, TMRCLK2 instead of Vcc to Gate2
+ * BIT 4 = 0, PSCLK to CLK2
+ * BIT 3 = 1, TMRCLK1 instead of Vcc to Gate1
+ * BIT 2 = 0, PSCLK to Gate1
+ * BIT 1 = 0, Vcc to Gate0
+ * BIT 0 = 0, PSCLK to Gate0
+ */
+
+SYM(InitTimer):
+ SetExRegByte(TMRCFG , 0x80 ) # All counters disabled, Gates 0,1
+ # and 2 are set to Vcc
+
+ SetExRegByte(TMRCON , 0x34 ) # prepare to write counter 0 LSB,MSB
+ SetExRegByte(TMR0 , 0xA8 ) # LSB = 0B count, followed by MSB
+ SetExRegByte(TMR0 , 0x04 ) # for INT every 50 msec. MSB = 0xE900
+ # for INT every 5 msec. 0x174c
+ # for INT every 1 msec. 0x04A8
+ # was 0xe900
+
+ SetExRegByte(TMRCON , 0x70 ) # mode 0 disables on Gate= Vcc
+ SetExRegByte(TMR1 , 0x00 ) # sfa
+ SetExRegByte(TMR1 , 0x00 ) # sfa
+
+ SetExRegByte(TMRCON , 0xB0 ) # mode 0 disables on gate =Vcc
+ SetExRegByte(TMR2 , 0x00 ) #
+ SetExRegByte(TMR2 , 0x00 ) #
+ SetExRegByte(TMRCFG , 0x80 ) # Enable timers = 0x00
+
+
+/*
+ * Initialize the DMACFG register for:
+ * BIT 7 = 1 , Disable DACK#1
+ * BITs 6:4 = 100, TMROUT2 connected to DRQ1
+ * BIT 3 = 1 , Disable DACK0#
+ * BIT 2:0 = 000, Pin is connected to DRQ0
+ */
+
+ SetExRegByte(DMACFG , 0xC0 )
+ SetExRegByte(DMACMD1, 0x00 ) # disable both DMA channels
+ SetExRegByte(DMAMOD1, 0x40 )
+/*
+ * Initialize the INTCFG register for:
+ * BIT 7 = 0, 8259 cascade disabled
+ * BIT 3 = 0, SLAVE IR6 connected to Vss
+ * BIT 2 = 0, SLAVE IR5 connected to Vss
+ * BIT 1 = 0, SLAVE IR1 connected to SSIOINT
+ * BIT 0 = 0, SLAVE IR0 connected to Vss
+ */
+
+SYM(InitInt):
+
+ cli # !
+
+ SetExRegByte(ICW1S , 0x11 ) # EDGE TRIGGERED
+ SetExRegByte(ICW2S , 0x28 ) # Slave base vector after Master
+ SetExRegByte(ICW3S , 0x04 ) # ( was 0x02! )slave cascaded to IR2 on master
+ SetExRegByte(ICW4S , 0x01 ) # must be 0x01
+
+ SetExRegByte(ICW1M , 0x11 ) # edge triggered
+ SetExRegByte(ICW2M , 0x20 ) # base vector starts at byte 32
+ SetExRegByte(ICW3M , 0x04 ) # IR2 is cascaded internally
+ SetExRegByte(ICW4M , 0X03 ) # AEOI MODE FIRST!
+
+ SetExRegByte(OCW1M , 0xde ) # IR0 only = 0xfe. for IR5 and IR0 active use 0xde
+ SetExRegByte(INTCFG , 0x00 )
+
+SYM(SetCS4):
+ SetExRegWord(CS4ADL , 0x702) #Configure chip select 4
+ SetExRegWord(CS4ADH , 0x00)
+ SetExRegWord(CS4MSKH, 0x03F)
+ SetExRegWord(CS4MSKL, 0xFC01)
+
+SYM(SetUCS1):
+ SetExRegWord(UCSADL , 0x0304) # 512K block starting at 0x80000 until 0x3f80000
+ SetExRegWord(UCSADH , 0x03F8)
+ SetExRegWord(UCSMSKH, 0x03F7)
+ SetExRegWord(UCSMSKL, 0xFC01) # configure upper chip select
+
+SYM(xfer_idt):
+ movw $ _ram_idt_offset , di
+ movw $ _ram_idt_segment , cx
+ mov cx, es
+
+ movw $ _rom_idt_offset , si
+ movw $ _rom_idt_segment , ax
+ mov ax , ds
+
+ movw $ _idt_size , cx
+
+ repne
+ movsb
+
+SYM(xfer_ints):
+
+ movw $ _ram_ints_offset , di
+ movw $ _ram_ints_segment , ax
+ mov ax , es
+
+ movw $ _rom_ints_offset , si
+ movw $ _rom_ints_segment, ax
+ mov ax , ds
+
+ movw $ _ints_size , cx
+
+ repne
+ movsb
+
+SYM(lidt):
+ movw $ _ram_idt_offset , di
+ movw $ 0x0 , si
+
+ movw $ _ram_idt_segment , ax
+
+ mov ax , ds
+ lidt _ram_idt_offset
+SYM(xfer_gdt):
+ movw $ _ram_gdt_offset , di
+ movw $ _ram_gdt_segment , cx
+ mov cx , es
+
+ movw $ _gdt_size , cx
+ movw $ _rom_gdt_segment , ax
+ movw $ _rom_gdt_offset , si
+ mov ax , ds
+
+ repne
+ movsb
+
+/*****************************
+ * Load the Global Descriptor
+ * Table Register
+ ****************************/
+
+ movw $ _ram_gdt_segment, ax
+ mov ax , ds
+
+ lgdt _ram_gdt_offset # location of GDT
+
+
+SYM(SetUCS):
+ SetExRegWord(UCSADL, 0x0704) # now 512K starting at 0x3f80000.
+ SetExRegWord(UCSADH, 0x03f8)
+ SetExRegWord(UCSMSKH, 0x0007)
+ SetExRegWord(UCSMSKL, 0xFC01) # configure upper chip select
+
+/***************************
+ * Switch to Protected Mode
+ ***************************/
+ mov %cr0, eax
+ orw $0x1, ax
+ mov eax, %cr0
+
+/**************************
+ * Flush prefetch queue,
+ * and load CS selector
+ *********************/
+
+ ljmp $ GDT_CODE_PTR , $ SYM(_copy_data) # sets the code selector
+/*
+ * Copy the data section down to RAM
+ */
+SYM(_copy_data):
+ .code32
+ pLOAD_SEGMENT( GDT_DATA_PTR, fs)
+ pLOAD_SEGMENT( GDT_DATA_PTR, gs)
+ pLOAD_SEGMENT( GDT_DATA_PTR, ss)
+ pLOAD_SEGMENT( GDT_DATA_PTR, ds)
+ pLOAD_SEGMENT( GDT_DATA_PTR, es)
+
+ movl $ SYM(_data_start) , edi # ram destination
+ movl $ SYM(_rom_data_start) , esi # rom data source
+ movl $ SYM(_edata) , ecx # end of data section
+ subl $ SYM(_data_start) , ecx # length of data section
+ # es, ds preloaded
+ repne # while ecx != 0
+ movsb # move a byte
+
+/*
+ * Set up the stack
+ */
+
+SYM (_establish_stack):
+ movl $end, eax # stack starts right after bss
+/* movl eax, stack_start # save for brk() routine */
+ movl $stack_origin, esp # this is the high starting address
+ movl $stack_origin, ebp
+/*
+ * Zero out the BSS segment
+ */
+SYM (zero_bss):
+ cld # make direction flag count up
+ movl $ SYM (end),ecx # find end of .bss
+ movl $ SYM (_bss_start),edi # edi = beginning of .bss
+ subl edi,ecx # ecx = size of .bss in bytes
+ shrl ecx # size of .bss in longs
+ shrl ecx
+ xorl eax,eax # value to clear out memory
+ repne # while ecx != 0
+ stosl # clear a long in the bss
+
+/*
+ * Transfer control to User's Board Support Package
+ */
+ pushl $0 # environp
+ pushl $0 # argv
+ pushl $0 # argc
+ call SYM (main) # does not return
+ addl $12,esp
+
+BEGIN_DATA_DCL
+
+/* .align 2
+ PUBLIC (start_frame)
+SYM (start_frame):
+ .long 0
+*/
+/* PUBLIC (stack_start)
+SYM (stack_start):
+ .long 0
+*/
+
+END_DATA_DCL
+
+END