summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/i386/ts_386ex/start/start.S
blob: 63248b961fcea12b56eba597d8dbd642ae56934c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
/*
 *  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	

#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