summaryrefslogblamecommitdiffstats
path: root/c/src/lib/libbsp/i386/ts_386ex/start/start.S
blob: 3f167fe9e3f46829c8822f58c76b04a2b09b23b3 (plain) (tree)



















































                                                                             
                               





























































































































































































































































































































                                                                               
     
                                                                       

                                         
































































































































                                                                                       
/*
 *  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, "ax"

/*
 * 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	

#if 0
        lgdt	 (eax)                    #  location of GDT in segment
#endif
        lgdt SYM(GDTR) #  location of GDT

/*
	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