summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386/ts_386ex/start/start.S
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/i386/ts_386ex/start/start.S')
-rw-r--r--c/src/lib/libbsp/i386/ts_386ex/start/start.S501
1 files changed, 501 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/i386/ts_386ex/start/start.S b/c/src/lib/libbsp/i386/ts_386ex/start/start.S
new file mode 100644
index 0000000000..7a3c8509c1
--- /dev/null
+++ b/c/src/lib/libbsp/i386/ts_386ex/start/start.S
@@ -0,0 +1,501 @@
+/*
+ * This file is the main boot and configuration file for the TS-1325. It is
+ * solely responsible for initializing the internal register set to reflect
+ * the proper board configuration. This version is modified from the i386ex
+ * BSP startup:
+ *
+ * 1) 1 MB RAM @ 0x0100000
+ * 2) 1 MB RAM @ 0x0 but with standard DOS memory usage.
+ * 3) Timer0 used as RTEMS clock ticker, 1 msec tick rate.
+ * 4) READY# is generated by CPU
+ *
+ * The file describes the ".initial" section, which contains:
+ * 1) device configuration code
+ * 2) interrupt descriptor table
+ * 3) global descriptor table
+ * 4) and initial boot code
+ *
+ * Modified by:
+ *
+ * Tony Ambardar
+ * University of British Columbia
+ * tonya@ece.ubc.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"
+
+#include "ts_1325.inc" /* controls for LED and button */
+
+/*
+ * NEW_GAS Needed for binutils 2.9.1.0.7 and higher
+ */
+
+ EXTERN (boot_card) /* exits to bspstart */
+ EXTERN (_DOS_seg_base) /* defined in startup/linkcmds */
+ EXTERN (Clock_exit)
+
+ PUBLIC (Interrupt_descriptor_table)
+ PUBLIC ( SYM(IDTR) )
+ PUBLIC (_Global_descriptor_table)
+ PUBLIC ( SYM(GDTR) )
+
+ PUBLIC( SYM(_init_i386ex) )
+
+
+ .section .initial
+
+/*
+ * Enable access to peripheral register at expanded I/O addresses
+ */
+SYM(_init_i386ex):
+ .code16
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+# cli Move this up for now for debug.
+ movw $0x8000 , ax
+ outb al , $REMAPCFGH
+ xchg al , ah
+ outb al , $REMAPCFGL
+ outw ax , $REMAPCFG ;
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+/*
+ * 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
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+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
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+/*
+ * Initialize Refresh Control Unit for:
+ * Refresh Address = 0x0000
+
+ * Refresh gate between rows is 20.0 (???) uSec
+ * Using a CLK2 frequency of 50Mhz ( 25Mhz CPU )
+ * The refresh unit is enabled
+ * The refresh pin is not used.
+ *
+ * Different TS units might have different refresh intervals, so
+ * comment out. Will be set up anyway after booting to DOS.
+ */
+
+/*
+SYM(InitRCU):
+ SetExRegWord( RFSCIR , 0x1F4) # refresh interval 500
+ SetExRegWord( RFSBAD , 0x0) # base address
+ SetExRegWord( RFSADD , 0x0) # address register
+ SetExRegWord( RFSCON , 0x8000) # enable bit
+*/
+
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+/*
+ * Initialize clock and power mgmt unit for:
+ * Clock Frequency = 50 Mhz
+ * Prescaled clock output = 1 Mhz
+ * Normal halt instructions
+ *
+ * NOTE: Hope this doesn't change the COMCLK frequency
+ */
+
+SYM(InitClk):
+ SetExRegByte( PWRCON, 0x0 )
+ SetExRegWord( CLKPRS, 0x17) # 0x13 for 1.19318 MHz. 0x17 for 1MHz.
+
+/**************************************************************
+ * Initialize the Pin Configurations
+ *************************************************************/
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+/*
+ * Initialize I/O port 1 for:
+ * PIN 0 = 0, Inport for external push-button switch
+ * PIN 1 = 1, RTS0# to package pin
+ * PIN 2 = 1, DTR0# to package pin
+ * PIN 3 = 1, DSR0# to package pin
+ * PIN 4 = 0, Inport ???
+ * PIN 5 = 0, Outport (Green LED, 1 = ON)
+ * PIN 6 = 0, Outport (Red LED, 1 = OFF)
+ * PIN 7 = 0, Inport ???
+ */
+
+SYM(InitPort1):
+ SetExRegByte( P1LTC , 0xd1 )
+ SetExRegByte( P1DIR , 0x91)
+ SetExRegByte( P1CFG , 0x0e)
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+/*
+ * Initialize I/O port 2 for:
+ * PIN 0 = 0, Outport ???
+ * PIN 1 = 0, Outport ???
+ * PIN 2 = 0, Outport ???
+ * PIN 3 = 0, Outport ???
+ * PIN 4 = 0, Outport ???
+ * PIN 5 = 1, Int. periph, RXD0
+ * PIN 6 = 1, Int. periph, TXD0
+ * PIN 7 = 0, Outport ???
+ */
+
+SYM(InitPort2):
+ SetExRegByte( P2LTC , 0x1f )
+ SetExRegByte( P2DIR , 0x00 )
+ SetExRegByte( P2CFG , 0x60)
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+/*
+ * Initialize I/O port 3 P3CFG
+ * PIN 0 = 1, Int. periph, TMROUT0
+ * PIN 1 = 1, Int. periph, TMROUT1
+ * PIN 2 = 1, Int. periph, INT0 (IR1)
+ * PIN 3 = 1, Int. periph, INT1 (IR5)
+ * PIN 4 = 1, Int. periph, INT2 (IR6)
+ * PIN 5 = 1, Int. periph, INT2 (IR7)
+ * PIN 6 = 0, Outport ???
+ * PIN 7 = 1, Int. periph, COMCLK used for serial I/O
+ */
+
+SYM(InitPort3):
+ SetExRegByte( P3LTC , 0x00 )
+ SetExRegByte( P3DIR , 0xbf )
+ SetExRegByte( P3CFG , 0xbf ) # can check TMROUT0
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+/*
+ * Initialize Peripheral Pin Configurations:
+ * PIN 0 = 1, Select RTS1#
+ * PIN 1 = 1, Select DTR1#
+ * PIN 2 = 1, Select TXD1#
+ * PIN 3 = 1, Select CTS1#
+ * PIN 4 = 1, CS5
+ * PIN 5 = 1, Timer2 pins enabled
+ * PIN 6 = 0, Select CS6#
+ * PIN 7 = 0, Don't care
+ */
+
+SYM(InitPeriph):
+ SetExRegByte( PINCFG , 0x3f)
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+/*
+ * 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, 0x00 ) # COMCLK -> baud-rate generator
+ # modem signals -> package pins
+ SetExRegByte( LCR0, 0x80 ) # latch DLL0, DLH0
+ SetExRegByte( DLL0, 0x01 ) # 0x0C sets to 9600 baud 0x6 = 19.2K
+ SetExRegByte( DLH0, 0x00 ) # 0x4 is 28.8K baud, 0x1 is 115K baud
+ SetExRegByte( LCR0, 0x03 ) # enable r/w buffers, IER0 accessible
+ # mode 8-n-1
+ SetExRegByte( IER0, 0x00 ) # no generated interrupts
+
+ SetExRegByte( LCR1, 0x80 ) # latch DLL0, DLH0
+ SetExRegByte( DLL1, 0x01 ) # 0x0C set to 9600 baud, 0x6 = 19.2K
+ SetExRegByte( DLH1, 0x00 ) # 0x4 is 28.8K baud
+ SetExRegByte( LCR1, 0x03 ) # enable r/w buffers, IER1 accessible
+ # reg 8-n-1
+ SetExRegByte( IER1, 0x00 ) # no generated intrrupts
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+SYM(InitMCR):
+ SetExRegByte( MCR0, 0x03 ) # standard mode, RTS,DTR activated
+ SetExRegByte( MCR1, 0x03 ) # standard mode, RTS,DTR activated
+
+/*
+ * 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
+ */
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+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 ) #
+
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+/*
+ * 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
+ *
+ * NOTE: not 100% sure of this...
+ */
+
+ SetExRegByte(DMACFG , 0xC0 )
+ SetExRegByte(DMACMD1, 0x00 ) # disable both DMA channels
+ SetExRegByte(DMAMOD1, 0x40 ) # DMA0 single transer mode
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+/*
+ * 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
+ *
+ * NOTE: not 100% sure of this either... Why IR5 active?
+ */
+
+SYM(InitInt):
+
+ cli # !
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+ 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 ) # fully nested mode, no EOI
+
+ SetExRegByte(ICW1M , 0x11 ) # edge triggered
+ SetExRegByte(ICW2M , 0x20 ) # base vector starts at byte 32
+ SetExRegByte(ICW3M , 0x04) # internal slave cascaded from master IR2
+ SetExRegByte(ICW4M , 0x01 ) # idem
+
+ SetExRegByte(OCW1M , 0xfb ) # mask master IRQs, but not IR2 (cascade)
+ SetExRegByte(OCW1S , 0xff ) # mask all slave IRQs
+ SetExRegByte(INTCFG , 0x00 ) # slave IRs -> Vss or SSIOINT
+
+/* The i8259s_cache (IRQ mask) location is in BSS, which is zeroed later!
+ * So to initialize the cache we should do the following command after
+ * the BSS is zeroed, and in 32-bit protected mode.
+ *
+ * movw $0xFFFB, SYM(i8259s_cache)
+ *
+ */
+
+/*
+ NOTE: not sure about this so comment out...
+
+SYM(SetCS4):
+ SetExRegWord(CS4ADL , 0x702) #Configure chip select 4
+ SetExRegWord(CS4ADH , 0x00)
+ SetExRegWord(CS4MSKH, 0x03F)
+ SetExRegWord(CS4MSKL, 0xFC01)
+*/
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+/*****************************
+ * Load the Global Descriptor
+ * Table Register
+ ****************************/
+
+ movl $SYM(GDTR), eax
+ andl $0xFFFF, eax
+
+#ifdef NEW_GAS
+ addr32
+ data32
+#endif
+
+ lgdt (eax) # location of GDT in segment
+
+/*
+ NOTE: not sure about this either so comment out for now...
+SYM(SetUCS):
+ SetExRegWord(UCSADL, 0xC503) # values taken from TS-1325 memory
+ SetExRegWord(UCSADH, 0x000D)
+ SetExRegWord(UCSMSKH, 0x0000)
+ SetExRegWord(UCSMSKL, 0x3C01) # configure upper chip select
+*/
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+/***************************
+ * Switch to Protected Mode
+ ***************************/
+ mov cr0, eax
+ orw $0x1, ax
+ mov eax, cr0
+
+/**************************
+ * Flush prefetch queue,
+ * and load CS selector
+ *********************/
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+ ljmpl $ GDT_CODE_PTR , $ SYM(_load_segment_registers) # sets the code selector
+
+/*
+ * Load the segment registers
+ */
+SYM(_load_segment_registers):
+ .code32
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+ 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
+ */
+/*
+ LED_OFF
+ WAIT_BUTTON
+*/
+SYM(lidtr):
+ lidt SYM(IDTR)
+/*
+ LED_YELLOW
+ WAIT_BUTTON
+*/
+SYM (_establish_stack):
+ movl $_ebss, eax # stack starts right after bss
+ movl $stack_origin, esp # this is the high starting address
+ movl $stack_origin, ebp
+/*
+ LED_GREEN
+ WAIT_BUTTON
+*/
+/*
+ * Zero out the BSS segment
+ */
+SYM (zero_bss):
+ cld # make direction flag count up
+ movl $ SYM (_ebss),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
+/*
+ * Now we can initialize the IRQ mask in i8259s_cache
+ */
+ movw $0xFFFB, SYM(i8259s_cache)
+/*
+ LED_YELLOW # Indicate ready to run
+ WAIT_BUTTON
+*/
+ LED_GREEN # Indicate RTEMS running!
+
+/*
+ * Transfer control to User's Board Support Package
+ */
+ pushl $0 # environp
+ pushl $0 # argv
+ pushl $0 # argc
+ call SYM(boot_card)
+ addl $12,esp
+
+ LED_RED # Indicate RTEMS exited
+/*
+ WAIT_BUTTON
+*/
+ cli # stops interrupts after hlt!
+ hlt # shutdown
+
+
+ .balign 4 # align tables to 4 byte boundary
+
+SYM(IDTR): DESC3( SYM(Interrupt_descriptor_table), 0x07ff );
+
+SYM(Interrupt_descriptor_table): /* Now in data section */
+ .rept 256
+ .word 0,0,0,0
+ .endr
+
+
+/*
+ * Use the first (null) entry in the the GDT as a self-pointer for the GDTR.
+ * (looks like a common trick)
+ */
+
+SYM (_Global_descriptor_table):
+SYM(GDTR): DESC3( GDTR, 0x17 ); # one less than the size
+ .word 0 # padding to DESC2 size
+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