diff options
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.S | 501 |
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 |