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.S437
1 files changed, 437 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..543a300744
--- /dev/null
+++ b/c/src/lib/libbsp/i386/i386ex/start/start.S
@@ -0,0 +1,437 @@
+/*
+ * 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$
+
+
+changes:
+ SetExRegByte(ICW3S , 0x02 ) # MUST be 0x02 according to intel
+ SetExRegByte(ICW3M , 0x04 ) # IR2 is cascaded internally: was 0x02 => IR1 is cascaded
+
+ */
+
+#include "asm.h"
+#include "macros.inc"
+#include "80386ex.inc"
+
+/*
+ * NEW_GAS Needed for binutils 2.9.1.0.7 and higher
+ */
+
+ EXTERN (boot_card) /* exits to bspstart */
+ EXTERN (stack_start) /* defined in startup/linkcmds */
+ EXTERN (Clock_exit)
+
+ PUBLIC (Interrupt_descriptor_table)
+ PUBLIC ( SYM(IDTR) )
+ PUBLIC( SYM(_initInternalRegisters) )
+
+BEGIN_DATA
+SYM(IDTR): DESC3( SYM(Interrupt_descriptor_table), 0x07ff );
+
+SYM(Interrupt_descriptor_table): /* Now in data section */
+ .rept 256
+ .word 0,0,0,0
+ .endr
+
+END_DATA
+
+BEGIN_DATA
+ PUBLIC (_Global_descriptor_table)
+
+SYM(GDTR): DESC3( GDT_TABLE, 0x1f ); # one less than the size
+SYM (_Global_descriptor_table):
+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 .reset
+
+ PUBLIC ( SYM(reset) )
+SYM(reset):
+ 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
+ */
+SYM(_initInternalRegisters):
+ .code16
+ 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):
+ movw $WDTSTATUS , dx # address the WDT status port
+ inb dx , al # get the WDT status
+ orb $0x01 , al # set the CLKDIS bit
+ outb al , dx # disable the clock to the WDT
+
+/*
+ * 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 Mhz
+ * Normal halt instructions
+ */
+
+SYM(InitClk):
+ SetExRegByte( PWRCON, 0x0 )
+ SetExRegWord( CLKPRS, 0x17) # 0x13 for 1.19318 MHz. 0x17 for 1MHz.
+
+/**************************************************************
+ * 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 , 0x00 ) # sfa
+ SetExRegByte(TMR0 , 0x00 ) # sfa
+
+
+ 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 = 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 , 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 , 0x01 ) # idem
+
+ SetExRegByte(OCW1M , 0xde ) # IR0 only = 0xfe. for IR5 and IR0 active use 0xde
+ SetExRegByte(INTCFG , 0x00 )
+
+ movw $0xFFFB, SYM(i8259s_cache) /* set up same values in cache */
+
+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
+
+/******************************************************
+* The GDT must be in RAM since it must be writeable,
+* So, move the whole data section down.
+********************************************************/
+
+ movw $ _ram_data_offset , di
+ movw $ _ram_data_segment, cx
+ mov cx , es
+
+ movw $ _data_size , cx
+ movw $ _rom_data_segment, ax
+ movw $ _rom_data_offset , si
+ mov ax , ds
+
+ repne
+ movsb
+
+/*****************************
+ * Load the Global Descriptor
+ * Table Register
+ ****************************/
+
+#ifdef NEW_GAS
+ data32
+ addr32
+#endif
+ lgdt SYM(GDTR) # location of GDT
+
+
+SYM(SetUCS):
+ SetExRegWord(UCSADL, 0x0702) # 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
+ *********************/
+
+ ljmpl $ GDT_CODE_PTR , $ SYM(_load_segment_registers) # sets the code selector
+
+/*
+ * Load the segment registers
+ */
+SYM(_load_segment_registers):
+ .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)
+
+/*
+ * Set up the stack
+ */
+
+SYM(lidtr):
+ lidt SYM(IDTR)
+
+SYM (_establish_stack):
+ movl $end, eax # stack starts right after bss
+ 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(boot_card)
+ addl $12,esp
+
+ cli # stops interrupts from being processed after hlt!
+ hlt # shutdown
+
+END
+