URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [i386/] [ts_386ex/] [start/] [start.S] - Rev 173
Compare with Previous | Blame | View Log
/*
* 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: start.S,v 1.2 2001-09-27 11:59:50 chris Exp $
*/
#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