/* * 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.rtems.com/license/LICENSE. * * $Id$ */ #include #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