
	.width 130
 #-----------------------------------------------------#
 # LX32 POWER ON DIAGNOSTICS                           #
 # BY: Jason Chan, Jacob Chik, Francise Ng, Kenny Ng.  #
 # Start   : July 20, 1989		               #
 # Last updated:	Aug. 30, 1989		       #
 #-----------------------------------------------------#
	.title "LX32 Power On Diagnostics"
	#.file "pwron.s"

#	include "def.s"
	.globl	diagnos,uart_init,get_dram_size
	
	.text

diagnos:
	movd	$led_0,r0		
 	movb	$0x80+led_8,led_port	# LED test , disable shadow ROM
  	movd	$SEC,r0
 del:	acbd	$-1,r0,del		# delay for 1 sec.
 	movb	$led_8,led_port

	movqd	$0, r6			# initialize r6
	call	uart_init

 #--- START The Power On Diagnostic Test --#
test_start:
	addr	start_msg, r5
	call	out_msg
 #------------- TEST CPU
 #test1:
 	movb	$led_0,led_port
	br	check_cpu		
test1_ret :
	movd	$CPU_pass,r6		# indicate cpu test pass
	lprd	sp,$stack_top		# init stack pointer
 #------------- TEST SERIAL I/O   
test2:
 	movb	$led_1,led_port
	br	check_serial_io 	
test2_ret:
	sbitb	$SERIAL_pass,r6		# C_flag=1 --> serial i/o test pass
	bcs	test3
	cbitb	$SERIAL_pass,r6		# C_flag=0 --> serial i/o test fail
 #------------- TEST DRAM JUMPER CONFIGURATION
test3:
 	movb	$led_2,led_port
	br	check_dram_jumper	#-- check DRAM jumpers config. -----#
 #------------- TEST DRAM 
test3a_ret:
	br	check_dram		#-- test DRAM ----------------------#
test3_ret:
	sbitb	$DRAM_pass,r6		# C_flag=1 --> dram test pass
	bcs	test4
	cbitb	$DRAM_pass,r6		# C_flag=0 --> dram test fail
 #------------- TEST EPROM
test4:
 	movb	$led_3,led_port
	br	check_eprom		#-- test EPROM ----------------------#
test4_ret:
	sbitb	$EPROM_pass,r6		# C_flag=1 --> EPROM test pass 
	bcs	test5
	cbitb	$EPROM_pass,r6		# C_flag=0 --> EPROM test fail
 #------------- TEST CENTRONICS PORT
test5:
 	movb	$led_4,led_port
	br	check_cent		#-- test CENTRONICS port ------------#
test5_ret:
	sbitb	$CENTRON_pass,r6	# C_flag=1 --> centronics test pass
	bcs	test6
	cbitb	$CENTRON_pass,r6	# C_flag=0 --> centronics test fail
 #------------- TEST SCSI INTERFACE
test6:
 	movb	$led_5,led_port
	br	check_scsi		#-- test ICU -----------------------#
test6_ret:
	sbitb	$SCSI_pass,r6		# C_flag=1 --> scsi test pass
	bcs	test7
	cbitb	$SCSI_pass,r6		# C_flag=0 --> scsi test fail
 #------------- TEST KEYBOARD INTERFACE 
test7:
 	movb	$led_6,led_port
	br	check_keybd		#-- test DMA -----------------------#
test7_ret:
	sbitb	$KEYB_pass,r6		# C_flag=1 --> keyboard I/F test pass
	bcs	test8
	cbitb	$KEYB_pass,r6		# C_flag=0 --> keyboard I/F test fail
 #------------- TEST TCP
test8:
 	movb	$led_7,led_port
	br	check_tcp		#-- test TCP -----------------------#
test8_ret:
	sbitb	$TCP_pass,r6		# C_flag=1 --> TCP test pass
	bcs	test9
	cbitb	$TCP_pass,r6		# C_flag=0 --> TCP test fail
 #------------- TEST ICU
test9:
 	movb	$led_8,led_port
	br	check_icu		#-- test ICU -----------------------#
test9_ret:
	sbitb	$ICU_pass,r6		# C_flag=1 --> ICU test pass
	bcs	test10
	cbitb	$ICU_pass,r6		# C_flag=0 --> ICU test fail
 #------------- TEST PRINTER ENGINE INTERFACE
test10:
 	movb	$led_9,led_port
	br	check_engine		#-- test Engine I/F ----------------#
test10_ret:
	sbitb	$ENG_pass,r6		# C_flag=1 --> engine I/F test pass
	bcs	test11
	cbitb	$ENG_pass,r6		# C_flag=0 --> engine I/F test fail
 #------------- TEST FPU
test11:
 	movb	$led_A,led_port
	br	check_fpu		#-- test FPU -----------------------#
test11_ret:
	sbitb	$FPU_pass,r6		# C_flag=1 --> FPU test pass
	bcs	test12
	cbitb	$FPU_pass,r6		# C_flag=0 --> FPU test fail
 #------------- TEST EPROM BURST/CACHEABLE MODES
test12:
 	movb	$led_b,led_port
	br	check_epmode		#-- test EPROM mode ---------------#
test12_ret:
	sbitb	$EPMODE_pass,r6		# C_flag=1 --> EPROM mode test pass
	bcs	test13  
	cbitb	$EPMODE_pass,r6		# C_flag=0 --> EPROM mode test fail
 #------------- TEST DRAM BURST, PAGE COMPARATOR & WINDOW ACCESS 
test13:
 	movb	$led_C,led_port		
	sprb	psr,tos			# save user psr
 	bsr	_chk_window		#-- test window access -------------#
	lprb	psr,tos			# restore user psr
	sbitb	$WINDOW_pass,r6		# r0 = 0 --> window access test pass
	cmpd	$0, r0
	beq	test13a
	bicpsrb	$C_flag			# clear C_flag, indicate test fail
	cbitb	$WINDOW_pass,r6		# r0 = 1 --> window access test fail
test13a:
 	movb	$led_d,led_port		
	sprb	psr,tos			# save user psr
	bsr	_chk_burst		#-- test burst on/off --------------#
	lprb	psr,tos			# restore user psr
	sbitb	$BURST_pass,r6		# r0 = 0 --> burst on/off test pass
	cmpd	$0, r0
	beq	test13b
	bicpsrb	$C_flag			# clear C_flag, indicate test fail
	cbitb	$BURST_pass,r6		# r0 = 1 --> burst on/off test fail
test13b:
# ifdef NEVER
 	movb	$led_E,led_port		
	sprb	psr,tos			# save user psr
 	bsr	_chk_page		#-- test page comparator -----------#
	lprb	psr,tos			# restore user psr
	sbitb	$PAGE_pass,r6		# r0 = 0 --> page comparator test pass
	cmpd	$0, r0
	beq	test_end
	bicpsrb	$C_flag			# clear C_flag, indicate test fail
	cbitb	$PAGE_pass,r6		# r0 = 1 --> page comparator test fail
# endif

 #--- end of power on diagnostic test -----#
test_end:
	movb	$led_P,led_port
	bcs	diag_exit
	movb	$led_F,led_port
diag_exit:
	addr	end_msg, r5
	call	out_msg
	call	get_dram_size
	lprw	psr, $0			# clear psr after diagnostic

	br	diag_ret

 #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 #=== check cpu (test1) =======================================================#
 # CPU test include the following tests:				      #
 # (1) internal data path test, use walk 1's & walk 0's method		      #
 # (2) verify shift operation & branch operation			      #
 # (3) verify register set integrity					      #	
 #	check 1) r0 -- r7						      #	
 #	      2) PC,SB,FP,SP1,SP0,INTBASE (FP,SP0 only)			      #
 #	      3) MOD and CFG (not checked)				      #
 # (4) verify ALU by testing multiply/addition/subtration instruction	      #
 # (5) check flag operation in PSR register 				      #
 #     for PSR, check C,L,N,Z flags only 			              #
 #		 b0: C - carry flag (indicate carry in ADD or borrow in SUD)  #
 #		 b1: T - Trace flag (if 1, generate trace trap per inst.)     #
 #		 b2: L - Low flag (integer compare: 1>2 give 1, other give 0  #
 #				   ,always clear by floating comparsion)      #
 #		 b3: 							      #
 #		 b4:							      #	
 #		 b5: F - general flag (signal exception condition)	      #
 #		 b6: Z - Zero flag (integer/float comparsion)		      #	
 #		 b7: N - Negative flag (signed integer comparsion)	      #
 #		 b8: U - User flag (when 1, in user mode. clear on int/trap)  #
 #		 b9: S - stack flag (indicate SP0 or SP1. clear on int/trap)  #
 #		 b10:P - trap pending flag (0 means no trace pending,         #
 #					    clear on int/trap)		      #
 #		 b11:I - Interrupt enable flag (1 enable all int, o NMI only, #
 #			 clear on int/Abort trap only, this not disable trap) #
 #									      #
 # output: all registers are destroyed					      #
 #	  if cpu error, whole system will be halted, LED's decimal point      #
 #   	  will not be flashed. Otherwise, C_flag is set & program continue    #
 # exit point : (1) cpu_error (the cpu will be halt)			      # 
 #	        (2) cpu_ret						      #
 #============================================================================#
check_cpu:
 #-- check cpu branch operation
	br	check_cpu_data
cpu_error:
	wait
 #-- check internal data path, walk 1's & walk 0's, shifter test also
check_cpu_data:
	movd	$0x1,r0			# walk 1's test
	rotd	$31,r0			# use rotate inst. to preserve
	cmpd	$0x80000000,r0		# all bit content
	bne	cpu_error
	movd	$0x7fffffff,r0		# walk 0's test
	rotd	$-31,r0			# use rotate inst. to preserve
	cmpd	$0xfffffffe,r0		# all bit content
	bne	cpu_error
 #-- check r0-r7
	movd	$0xaa55ff00,r0	# move test pattern to r0..7
	movd	r0,r1
	movd	r1,r2
	movd	r2,r3
	movd	r3,r4
	movd	r4,r5
	movd	r5,r6
	movd	r6,r7
	movd	r7,r0
	cmpd	$0xaa55ff00,r0	#
	bne	cpu_error	# internal data path error
	movd	$0x55aa00ff,r0	#
	movd	r0,r1
	movd	r1,r2
	movd	r2,r3
	movd	r3,r4
	movd	r4,r5
	movd	r5,r6
	movd	r6,r7
	movd	r7,r0
	cmpd	$0x55aa00ff,r0	#
	bne	cpu_error	#
 #-- check other registers
	lprd	fp,$0x55ff00	# load fp with 0x55ff00
	sprd	fp,r0		# read fp & place in r0
	lprd	sp,r0		# load sp with r0
	sprd	sp,r0		# read sp & place in r0
	cmpd	r0,$0x55ff00
	bne	cpu_error	# cpu error if comparsion fail

	lprd	fp,$0xaa00ff	# load fp with 0xaa00ff
	sprd	fp,r0		# read fp & place in r0
	lprd	sp,r0		# load sp with r0
	sprd	sp,r0		# read sp & place in r0
	cmpd	r0,$0xaa00ff
	bne	cpu_error	# cpu error if comparsion fail
 #-- check ALU
	movd	$0x7654,r0	# test multiply
	muld	$0xfedc,r0
	cmpd	r0,$0x75cd0830
	bne	cpu_error
	movd	$0x7654,r0	# test add
	movd	$0x1234,r1
	addd	r1,r0
	cmpd	r0,$0x8888
	bne	cpu_error
	subd	$0x1234,r0	# test sub
	cmpd	r0,$0x7654
	bne	cpu_error
 #-- check flags
	movb	$0xbb,r0
	cmpb	r0,$0xbb
	bne	cpu_error	# test Z flag, error if not equal
	cmpb	r0,$0xaa
	ble	cpu_error	# test N flag, error if bb < aa (-45 < -56)
	bls	cpu_error	# test L flag, error if bb < aa

	beq	cpu_error	# test Z flag, error if equal
	cmpb	r0,$0xcc
	bgt	cpu_error	# test N flag, error if bb > cc (-45 > -34)
	bhi	cpu_error	# test L flag, error if bb > cc

	addb	$0xbb,r0
	bcc	cpu_error	# test C flag, error if carry clear
	addb	$0x1,r0
	bcs	cpu_error	# test C flag, error if carry set
cpu_ret:
	bispsrb	$C_flag		# set carry flag ,indicate cpu test pass
  	br	test1_ret	


 #=== check serial io (test2) ===========================================#
 # DUART (NS16552) run at 18.432 MHz					#
 #	with uart1 console & uart0 tty					#
 # 2 kinds of test will be carried out:					#
 # (1) data path test by write/read/verify the uart scratch register	#
 # (2) local loopback test at max/9600/min. baud rate supported by this	#
 #     uart. (where max=128000, and min=50)				#
 #									#
 # output: 1) r0,r1,r2,r3,r4 are destroyed 				#
 #	     r6  temp1_flag, temp2_flag destroyed			#
 #	  2) r6 u1_flag=1 --> (uart1) console error			#
 #	        u2_flag=1 --> (uart0) tty error				#
 #	  3) C_flag clear indicate overall error			#
 #	     C_flag set   indicate overall pass				#
 #	  4) report cpu & serial i/o test result to console if uart1	#
 #	     (console) test OK, otherwise, no report in console		#
 # exit point : ss4 							#
 #=======================================================================#
check_serial_io:
 #-- check data path of serial I/O
	cbitb	$u1_flag,r6		# init uart0, uart1 OK flag
	cbitb	$u2_flag,r6
	cbitb	$temp1_flag,r6
	cbitb	$temp2_flag,r6
	movb	$0xaa:b,uart1+u_scratch	# write uart1 reg 0xaa
 	movb	$0x55,uart0+u_scratch	# write uart0 reg 0x55
	cmpb	uart1+u_scratch,$0xaa:b
	bne	serial_error10		# report data path error
 	cmpb	uart0+u_scratch,$0x55
 	bne	serial_error20		# report data path error

	movb	$0x55,uart1+u_scratch	# write uart1 reg 0x55
 	movb	$0xaa,uart0+u_scratch	# write uart0 reg 0xaa
	cmpb	$0x55,uart1+u_scratch
	bne	serial_error10		# report data path error
 	cmpb	$0xaa,uart0+u_scratch
 	bne	serial_error20		# report data path error

 #-- check with 9600 baud loopback
	movb	$0,uart1+u_ier		# disable all rx/tx/status cause int
	movb	$0,uart0+u_ier		# disable all rx/tx/status cause int
	movb	$B'10000011,uart1+u_lcr	# DLAB=1, N,8,1
	movb	$B'10000011,uart0+u_lcr	# DLAB=1, N,8,1
	movb	$1,uart1+u_afr		# set dual operation (uart1/2)
serial_1:
 	movb	$LSP_9600,uart1+u_ldlr	# select 9600 baud
 	movb	$MSP_9600,uart1+u_mdlr
	movb	$B'00000011,uart1+u_lcr	# DLAB=0, N, 8, 1
	movd	$DELAY_9600,r1		# set delay count to wait for data
	call	loopback_test
 #-- check 128000 baud loopback 
serial_2:
	movb	$B'10000011,uart1+u_lcr		# DLAB=1, N,8,1
	movb	$LSP_128000,uart1+u_ldlr	# select 128000 baud (highest)
	movb	$MSP_128000,uart1+u_mdlr
	movb	$B'00000011,uart1+u_lcr	# DLAB=0, N, 8, 1
	movd	$DELAY_128000,r1	# set delay count to wait for data
	call	loopback_test
 #-- check 50 baud loopback
serial_3:
	movb	$B'10000011,uart1+u_lcr	# DLAB=1, N,8,1
	movb	$LSP_50,uart1+u_ldlr	# select 50 baud (lowest)
	movb	$MSP_50,uart1+u_mdlr
	movb	$B'00000011,uart1+u_lcr	# DLAB=0, N, 8, 1
	movd	$DELAY_50,r1		# set delay count to wait for data
	call	loopback_test
 #-- check 38400 baud loopback 
serial_5:
	movb	$B'10000011,uart1+u_lcr		# DLAB=1, N,8,1
	movb	$LSP_38400,uart1+u_ldlr	# select 38400 baud
	movb	$MSP_38400,uart1+u_mdlr
	movb	$B'00000011,uart1+u_lcr	# DLAB=0, N, 8, 1
	movd	$DELAY_38400,r1		# set delay count to wait for data
	call	loopback_test
serial_4:
	tbitb	$u2_flag,r6	# test if uart0 error, if error, no set in
	bfs	uart0_error	# C_flag & indicate overall failure
	cbitb	$temp2_flag,r6	# clear indicating overall pass
	br	serial_ret

serial_error10:			# data path error
serial_error20:			# set temp1_flag to indicate this kind of error
	sbitb	$temp1_flag,r6	
serial_error11:			# uart1 (console) time out/line status reg error
serial_error12:			# uart1 (console) rx. data error
	sbitb	$u1_flag,r6	# indicate uart1 (console) or serious error
uart0_error:
	sbitb	$temp2_flag,r6	# set to indicate overall failure
serial_ret:
	movb	$0x03,uart1+u_mcr	# disable loopback mode 

	movb	$B'10000011,uart1+u_lcr	# DLAB=1, N,8,1
	movb	$0,uart1+u_afr		# clear dual operation (uart1/2)
	movb	$B'00000011,uart1+u_lcr	# DLAB=0, N,8,1
	movb	$B'00000011,uart0+u_lcr	# DLAB=0, N,8,1
 # report test result
ss1:	tbitb	$temp1_flag,r6	# is data path error, no any report
	bfs	ss3		#
	tbitb	$u1_flag,r6	# if uart1 error, no any report
	bfs	ss3		#

	call	uart_init	# init uart1 & uart0
	sbitb	$SERIAL_pass,r6	# temp set SERIAL_pass to indicate uart1 Ok

	addr	cpu_msg1,r5	# report "CPU test ... OK" 
	call	out_msg		#        "Serial channel 1 ... test Ok"
	addr	serial_msg1, r5
	call	out_msg
	addr	uart0_msg1,r5	# report uart0 test result
	call	out_msg
	addr	msg_lb_error,r5
	tbitb	$u2_flag,r6
	bfs	ss2
	addr	pass_msg,r5
ss2:	call	out_msg

ss3:	bicpsrb	$C_flag
	tbitb	$temp2_flag,r6
	bfs	ss4
	bispsrb	$C_flag
ss4:    br	test2_ret 

 #-- local loopback test -------------------------------------
 #	input: r1 -- delay count for the specified baud rate
 #	output: r0,r1,r2,r3,r4 will be destroyed
 #------------------------------------------------------------
loopback_test:
	movd	r1,r2
se_loop0:
	acbd	$-1,r2,se_loop0		# pure delay

	movb	$0x13,uart1+u_mcr	# enable local loopback test

 #-- check 0x55 loopback
loop_1:	movb	uart1+u_rx_data,r0	# read to clear DR of uart1 (console)
	movb	uart0+u_rx_data,r0	# read to clear DR of uart0 (tty)
	movd	r1,r2
se_loop:
	acbd	$-1,r2,se_loop
	movb	$0x55,uart1+u_tx_data	# tx. test pattern 0x55 to uart1/2
	movb	$0x55,r3
	movd	r1,r2			# reserve r1, use r2 as delay count
	movd	r7,r4			# reserve r7 (return address)
	call	check_rx_data
 #-- check 0xaa loopback
loop_2:	movb	uart1+u_rx_data,r0	# read to clear DR of uart1 (console)
	movb	uart0+u_rx_data,r0	# read to clear DR of uart0 (tty)
	movb	$0xaa,uart1+u_tx_data	# tx. test pattern 0xaa to uart1/2
	movb	$0xaa,r3
	movd	r1,r2			# move r1 to r2, use r2 as delay count
	call	check_rx_data
loopback_ret:
	movb	$0x03,uart1+u_mcr	# disable loopback test mode
	movd	r4,r7			# get the reserved return address
	return

 #-- check if data ready within time allowance, check if data correct? 
check_rx_data:
	acbd	$-1,r2,check_rx_data	# just pure delay to wait rx. data
 # check uart1 (console)
	tbitb	$0,uart1+u_lsr	# test line status register bit0 to see
 					# if data ready ?
	bfc	serial_error11		# time out or line status register error
					# if data not ready
	cmpb	r3,uart1+u_rx_data	# check rx. data = 0x55 ?
	bne	serial_error12		# rx. data error
 # check uart0 (tty)
 	tbitb	$0,uart0+u_lsr		# test line status register bit0 to see
  					# if data ready ?
 	bfc	serial_error21		# time out or line status register error
 					# if data not ready
	cmpb	r3,uart0+u_rx_data	# check rx. data = 0x55 ?
 	bne	serial_error22		# rx. data error
	return
serial_error21:			# uart0 (tty) timeout/line status reg error
serial_error22:			# uart0 (tty) rx. data error
	sbitb	$temp2_flag,r6		# indicate overall error
	sbitb	$u2_flag,r6		# set to indicate uart0 (tty)
	return				# is in defect

 #=== Check DRAM-jumper (Test 3a) ============================# 
 #
 #  bit0 of r6 indicates general memory access error
 #  bit1 of r6 indicates JP302 may be wrong
 #  bit2 of r6 indicates JP301 may be wrong
 #  bit3 of r6 indicates JP300 may be wrong
 #===========================================================#

#ifdef	NOTDEF

check_dram_jumper:
 	sprd	cfg, r5			# store the cfg reg into r5
	movd	r5, r4
	andd	$0x0ffffe1ff, r4	# turn off the d & i cache
	lprd	cfg, r4

jp_test1:
 #
 # assume 1 Mbit x 1 DRAM is installed (total 8 Mbyte)
 #
 #	bit3	bit2	bit1
 #	JP300	JP301	JP302
 #	 1-2	 1-2	 err
 # bit1 of r6 will be set
 #
	xord	r0, r0
	movd	r0, 0(r0)
	cmpd	r0, 0(r0)
	beq	L1
	orb	$bit0, r6		# memory access error (bit0 set)
L1:	movd	$0x400000, r1		# 5th Mbyte addr
	movd	r1, 0(r1)
	cmpd	r0, 0(r0)		# data in addr 0 becomes
	beq	jp_test2		# data just load in addr 5th M
	cmpd	r1, 0(r1)
	bne	jp_test2
	orb	$bit1, r6

jp_test2:
 #
 #	JP300	JP301	JP302
 #	 1-2	 err	 1-2
 # bit2 of r6 will be set
 #
	xord	r0, r0
	movd	r0, 0(r0)
  	movd	$0x1000, r1		# 5th kbyte addr
	movd	r1, 0(r1)
	cmpd	r0, 0(r0)
	beq	jp_test4
	cmpd	r1, 0(r1)
	bne	jp_test4
	orb	$bit2, r6		# addr 0 is overwritten

jp_test4:
 #
 #	JP300	JP301	JP302
 #	 err	 1-2	 1-2
 # bit3 of r6 will be set
 # note: JP301 may also be wrong installed (bit2 set)
 #
	tbitb	$2, r6
	bfc	jp_TT1
	orb	$bit3, r6

jp_TT1:
 #
 # assume 4 Mbit x 1 DRAM is installed (total 32 Mbyte)
 #
 #	bit3	bit2	bit1
 #	JP300	JP301	JP302
 #	 2-3	 2-3	 err
 # bit1 of r6 will be set
 #
	xord	r0, r0
	movd	r0, 0(r0)
	movd	$0x1000000, r1		# 17th Mbyte addr
	movd	r1, 0(r1)
	cmpd	r0, 0(r0)
	beq	jp_TT2
	cmpd	r1, 0(r1)
	bne	jp_TT2
	orb	$bit1, r6

jp_TT2:
 #
 #	JP300	JP301	JP302
 #	 1-2	 err	 1-2
 # bit2 of r6 will be set
 #
	movd	$0x1000000, r0		# 17th Mbyte addr
	movd	r0, 0(r0)
	movd	$0x1400000, r1		# 21th Mbyte addr
	movd	r1, 0(r1)
	cmpd	r0, 0(r0)
	beq	jp_TT3
	cmpd	r1, 0(r1)
	bne	jp_TT3
	orb	$bit2, r6

jp_TT3:
 	lprd	cfg, r5

 # Test if bit0, bit1, bit2 or bit3 of r6 is set.
 #  If any one of these bits is set, then return.

	andb	$0x0F, r6		# set bit4-7 to 0
	cmpb	$0, r6			# check if bit0-4 are clear
	beq	jp_done			# if yes, test passed.
	addr	dram_jp_msg, r5		# if not, display error message.
	call	out_msg
jp_done:
	br	test3a_ret
# else
check_dram_jumper:
	addr	dram_jp_msg, r5		
	call	out_msg
 	sprd	cfg, r5			# store the cfg reg into r5
	movd	r5, r4
	andd	$0x0ffffe1ff, r4	# turn off the d & i cache
	lprd	cfg, r4

jp_test1:
 #
 # assume 1 Mbit x 1 DRAM is installed (total 8 Mbyte)
 #
 #	Test    JP6  (300)
 #	may cause fault reading of addresses
 #	in two succesive pages

	movd	$0x5555,@50		# Write to succesive pages
	movd	$0xaaaa,@0x1010		
	movd	@50,r0			#... and read it back
	movd	@0x1010,r1
	cmpd	$0x5555,r0		# if fault read
	bne	jp6_err
	cmpd	$0xaaaa,r1
	bne	jp6_err


 #	Test	JP12  (301)	
 #	may  cause address overlap of 4KB

	movd	$0x5555,@50		# Write to 4KB diffrence address
	movd	$0xaaaa,@0x1050		
	movd	@50,r0			#... and read it back
	movd	@0x1050,r1
	cmpd	r0,r1			# if equal
	beq  	jp12_err


 #	Test	JP5 (302)	
 #	may  cause address overlap of 4MB

	movd	$0x5555,@0		# Write to 4MB diffrence address
	movd	$0xaaaa,@0x400000		
	movd	@0,r0			#... and read it back
	movd	@0x400000,r1
	cmpd	r0,r1			# if equal
	beq  	jp5_err



jp_done:
	addr	pass_msg,r5
	call	out_msg
	br	test3a_ret
jp6_err:
	sbitb	$3,r6
	addr	jp6_msg,r5
	call	out_msg
	br	test3a_ret
jp12_err:
	sbitb	$2,r6
	addr	jp12_msg,r5
	call	out_msg
	br	test3a_ret
jp5_err:
	sbitb	$1,r6
	addr	jp5_msg,r5
	call	out_msg
	br	test3a_ret

# endif
	
 #=== CHECK DRAM (Test 3) ========================================
 # The test consists of 5 parts :				  
 # 1. Data bus ---- Checks the integrity of data bus of both banks 
 #		    by walking 1 and 0.				  
 # 2. RAM sizing -- Check size by wrap around method.		 
 # 3. Address bus - Checks the integrity of address bus by walking 
 #		    1 and 0.					  
 # 4. 5N RAM test - Test all locations using 5N access method with
 #		    some magic nos.  The test ensures that all bits
 #		    can toggle from 0 to 1 and vice versa.
 #		    The test repeats for small block size in order
 #		    to exclude the possibility of bad refreshing.
 # 5. refresh ----- Check all locations written by 5N test. The
 #		    period of 5N test is much longer than 8ms.
 #
 # Lower word of r6 is used as follows :
 # b15 is the fail bit for the entire sub-test.  If error found in any
 #   section, this bit is set.
 # b7 is used to indicate error in the section.  If error found, this 
 #   bit is set & error message heading has been printed.
 # b6~0 is used to indicate individual errors
 #================================================================== 

 #--- Define macro to set error bits ------------------------#
 # set bit 15 of r6 to indicate error in entire sub-test     #
 # set bit 7 of r6 to indicate error in test section &       #
 #   no subsequent error message heading should be printed.  #
 # at exit, f flag = original value of bit 7 of r6 	     #
 #-----------------------------------------------------------#
	.macro	seterr
	sbitb	$15,r6
	sbitb	$7,r6
	.endm

check_dram:
	lprd	sb,r7		# save return address
	addr	dram_msg0,r5	# main test msg
	call	out_msg

check_ram1:
	sprd	cfg,r0
	sbitb	$11,r0		# enable ic for faster operation
	lprd	cfg,r0

	addr	dram_msg1,r5	# subtest msg
	call	out_msg

	addr	dram_msg2,r5	# Data path error heading
	movqw	$0,r6		# r6 used for storing error bit(s)
				# b7=0 -> no error detected yet
				# b1~0=1 -> error in walk 1 & 0
	addr	dram_start1,r0	# r0 = starting add. of DRAM
	movb	$31,r1		# r1 = loop count & bit-in-test
	movd	$0x80000000,r2	# r2 = test pattern (walk 1)

data2:  comd	r2,r3		# r3 = test pattern (walk 0)
	movd	r2,0(r0)	# walk 1 in loc 0
	movd	r3,4(r0)	# walk 0 in loc 4

	tbitb	r1,0(r0)
	bfc	dramerr_w1
data3:	tbitb	r1,4(r0)
	bfs	dramerr_w0

data6:	cmpb	r6,$0		# skip printing error if no error at
	beq	dcont		#   all
	cmpb	r6,$0x80	# skip if no error in this bit
	beq	dcont

	movqb	$1,r3		# count
disperr:			# display error loop
	movw	$space+6*256,r5	# o/p 6 spaces
	call	out_mbyte	#
	movb	$100,r5		# print '--' if no error
	cbitb	r3,r6
	bfc	dprintbit
	movb	r1,r5		# print error bits
dprintbit:
	call	out_decimal	# o/p 2 decimal digits
	movw	$space+(5+7)*256,r5	# o/p 23 spaces
	call	out_mbyte
	addqb	$-1,r3
	cmpb	r3,$0
	bge	disperr		# repeat

dcont:	rotd	$-1,r2		# shift the test bit
	addqb	$-1,r1		# dec count	
	cmpb	r1,$0
	bge	data2		# repeat if >= 0

	cmpqb	$0,r6		# if no error, print 'passed'
	bne	data_fail
	addr	pass_msg,r5
	call	out_msg
	br 	cram_size

data_fail:
	addr	dfail_msg,r5
	call	out_msg
cram_size:
	call get_dram_size
 #
 # Address path test
 #
	addr	dram_msg3,r5
	call	out_msg

 #   check if any address line stuck to 0
 #   by rippling a 1 thru the address bus

	movb	$0xff,dram_start1 # write a pattern in dram start
	movb	dram_start1,r2	 # r2=actual data read from dram start
				 # independent of data path errors
	movqb	$0,r6		# r6 = 0 indicates no error exists
	movqb	$0,r1		# r1 =loop count and bit-in-test

adr1:	addr	dram_start1,r3	# r3 = pointer
	movb	$0xff,0(r3)	# rewrite pattern in dram start
	sbitb	r1,r3		# set one bit in address bus
	cmpd	r3,r4		# does it exceed limit of dram?
	bhi	adr2	
	bfs	adr_cont1	# if bit is originally set, i.e.
				#  at dram start, skip test.
	movqb	$0,0(r3)	# write at that loc. If dram start
	cmpb	r2,dram_start1	# is changed, that addr. line is stuck
	beq	adr_cont1
				# display heading & error bits
	seterr			# indicate error
	bfs	aerr1		# skip heading if error already exists
	addr	dram_msg4,r5
	call	out_msg
aerr1:	movw	$space,r5
	call	out_byte
	movb	r1,r5		# display error addr. bit
	call	out_decimal
	
adr_cont1:
	addqb	$1,r1		# inc bit-in-test
	br	adr1

 #   check if any address line stuck to 1
 #   by rippling a 0 thru the address bus
adr2:
	lshb	$-1,r6		# shift error in walk 1 to bit 6
	movb	$0xff,0(r4)	# write a pattern in last loc.
	movb	0(r4),r2	 # r2=actual data read from that loc.
				 # independent of data path errors
	movqb	$0,r1		# r1 =loop count and bit-in-test

adr3:	movb	$0xff,0(r4)	# rewrite pattern in dram start
	movd	r4,r3		# r3 = pointer
	cbitb	r1,r3		# clear one bit in address bus
	bfc	adr_done	# if bit is originally cleared, i.e.
				#  at last loc., stop. 
	movqb	$0,0(r3)	# write at that loc. If last loc.
	cmpb	r2,0(r4)	# is changed, that addr. line is stuck
	beq	adr_cont0
				# display heading & error bits
	seterr			# indicate error
	bfs	aerr0		# skip heading if error already exists
	addr	dram_msg5,r5
	call	out_msg
aerr0:	movw	$space,r5
	call	out_byte
	movb	r1,r5		# display error addr. bit
	call	out_decimal
	
adr_cont0:
	addqb	$1,r1		# inc bit-in-test
	br	adr3

adr_done:			# display error in addr. path, if any.
	tbitb	$7,r6		# check for error in 2 sections
	bfs	chk_all_bytes
	tbitb	$6,r6
	bfs	chk_all_bytes
	addr	pass_msg,r5
	call	out_msg

 #
 #  check all locations using 5N access method
 #
chk_all_bytes:
	addr	dram_msg6,r5
	call	out_msg

	lprd	fp,r4		# save r4
	subd	$dram_start1-1,r4  # cal no. of 1K blocks > r4	
	lshd	$-10,r4

	addr	dram_start1,r1 	# r1 = pointer
	movd	$0xa9b2d5,r0	# r0 = some magic no.
	movqd	$0,r5		# r5=256 double words a time to prevent
				# intervention of refresh circuit.
 #-------
dchkab2:
	movqd	$0,r2		# r2 = initial pattern
 #-------
dchkab3:
	movd	r2,0(r1)	# write pattern
	comd	r2,0(r1)	# write /pattern
	addd	r0,r2		# change pattern for next loc.
	addqd	$4,r1		# update pointer
	acbb	$-1,r5,dchkab3
 #-------
	subd	$0x400,r1	# reset pointer to start of block
	movqd	$0,r2		# reset pattern

dchkab5:
	comd	0(r1),r3	# compare /pattern
	cmpd	r2,r3
	bne	dchkaberr
	addd	r0,r2
	addqd	$4,r1
	acbb	$-1,r5,dchkab5

	subd	$0x400,r1
	movqd	$0,r2

dchkab6:
	movd	r2,0(r1)	# write pattern
	addd	r0,r2		# change pattern for next loc.
	addqd	$4,r1		# update pointer
	acbb	$-1,r5,dchkab6

	subd	$0x400,r1
	movqd	$0,r2

dchkab7:
	cmpd	r2,0(r1)	# compare pattern
	bne	dchkaberr
	addd	r0,r2
	addqd	$4,r1
	acbb	$-1,r5,dchkab7

	rotd	$1,r0		# change magic no. for next block
	addqd	$1,r0
	acbd	$-1,r4,dchkab2	# repeat for all blocks

	addr	pass_msg,r5	# passed 5N access test !
	call	out_msg

 #
 #  Test refresh circuit by comparing the entire memory previously
 #   written.
 #
	addr	dram_msg7,r5
	call	out_msg

	sprd	fp,r4		# store r4
	subd	$dram_start1-1,r4  # cal no. of 1K blocks > r4
	lshd	$-10,r4

	addr	dram_start1,r1 	# r1 = pointer
	movd	$0xa9b2d5,r0	# r0 = some magic no.
	movqd	$0,r5		# r5=256 double words a time to prevent
				# intervention of refresh circuit.
 #-------
drefrsh1:
	movqd	$0,r2
 #-------
drefrsh2:
	cmpd	r2,0(r1)	# compare pattern
	bne	dchkaberr
	addd	r0,r2
	addqd	$4,r1
	acbb	$-1,r5,drefrsh2
 #-------
	rotd	$1,r0		# change magic no. for next block
	addqd	$1,r0
	acbd	$-1,r4,drefrsh1	# repeat for all blocks
 #-------
	sprd	fp,r4		# r4 = last loc.
	addr	pass_msg,r5	# passed refresh test !
	call	out_msg
	addr	dram_msg8,r5	# o/p memory size
	call	out_msg
	movd	r4,r5
	subd	$dram_start1-1,r5
	sprd	sb,r0
	call	out_hex
	lprd	sb,r0
	br	dram_exit	# CHANGE EXIT POINT

dchkaberr:
	sbitb	$15,r6
	addr	fail_msg,r5	# display error in address :
	call	out_msg
	movd	r1,r5
	sprd	sb,r0
	call	out_hex
	lprd	sb,r0

 #
 # Check cacheable RAM
 # This test will stop on first error encountered
 #
 # !!!PAY ATTENTION ON SYSTEM VARIABLE AND STACK IN RAM !!!!
chk_cache:
	addr	dram_msg8,r5
	call	out_msg
	movd	$0x55555555,r1	# initialize patterns
	movd	$0xAAAAAAAA,r2	# 

 # verify window 1 and window 3
 # W1 - window 1, 00000000~01FFFFFF  burst on, cacheable
 # W3 - window 3, 04000000~05FFFFFF  burst on, non-cacheable

	movd 	$0,r3		# initialize DRAM address pointer
cache1:	movd	r1,dram_start1(r3) # write pattern to W1, cacheable
	cmpd	r1,dram_start1(r3) # check pattern in cpu cache
	bne	cache_err	# if not written, error
	movd	r2,dram_start3(r3) # write pattern to W3, non-cacheable
	cmpd	r2,dram_start3(r3) # check pattern in DRAM
	bne	cache_err	# if not written, error
	cmpd	r2,dram_start1(r3) # check pattern in cpu cache
	beq	cache_err	# if written, error since non-cacheable
	addqd	$4,r3		# increment address pointer
	cmpd	r3,r4 
	blt	cache1		# repeat till the end of dram

 # verify window 2 and window 4
 # W2 - window 2, 02000000~03FFFFFF  burst off, cacheable
 # W4 - window 4, 06000000~07FFFFFF  burst off, non-cacheable

	movd 	$0,r3		# initialize DRAM address pointer
cache2:	movd	r1,dram_start2(r3) # write pattern to W1, cacheable
	cmpd	r1,dram_start2(r3) # check pattern in cpu cache
	bne	cache_err	# if not written, error
	movd	r2,dram_start4(r3) # write pattern to W3, non-cacheable
	cmpd	r2,dram_start4(r3) # check pattern in DRAM
	bne	cache_err	# if not written, error
	cmpd	r2,dram_start2(r3) # check pattern in cpu cache
	beq	cache_err	# if written, error since non-cacheable
	addqd	$4,r3		# increment address pointer
	cmpd	r3,r4 
	blt	cache2		# repeat till the end of dram
	br	dram_exit	# branch to exit

cache_err:
	sbitb	$15,r6
	addr	fail_msg,r5	# display error in address :
	call	out_msg
	movd	r3,r5
	sprd	sb,r0
	call	out_hex
	lprd	sb,r0

dram_exit:			# exit point for dram test
	bispsrb	$C_flag		# set carry to indicate pass
	tbitb	$15,r6
	bfc	dexit
	bicpsrb	$C_flag		# clear carry to indicate error

dexit:	sprd	sb,r7
 	br	test3_ret	# return to main program

 #---------------------------------------------------------------
 # error handling routine for data path test
dramerr_w1:	# error handling for walk 1

	seterr			# indicate a fail in RAM test has
	bfs	rw1		#  occured & skip heading printing
	call	out_msg		# print error heading
rw1:	sbitb	$1,r6		# set bit to indicate error type
	br	data3		# cont

 #----
dramerr_w0:	# error handling for walk 0

	seterr
	bfs	rw0
	call	out_msg
rw0:	sbitb	$0,r6
	br	data6


 #=== check eprom (Test 4) =================================#
 #
 #   This routine is used to verify the checksum of the
 #   ship-out/testing eproms with 8/32 bits data bus width
 #   for LX32 EB. The checksum is placed at the end of the
 #   whole program. And a known pattern "01ff02fe" is put
 #   doubleword-aligned before the checksum for indication.
 #   THe whole modification job is done in "makefile". (ie.  
 #   program code + 01ff02fe + cksm_lower_byte + cksm_upper_
 #   byte )
 #
 #===========================================================#
check_eprom:
#ifndef BURN
	addr	eprom_msg, r5
	call	out_msg
	movd	$prom_start,r0		# set starting address
	movd	$PROG_END,r1		# program-end indicator in r1
	movd	$0,r2			# clear checksum accumulator
prom0:	movb	$4,r4			#
prom1:	movzbw	0(r0),r3		# add one byte to
	addw	r3,r2			# accumulator
	addqd	$1,r0			# increment address pointer
	acbb	$-1,r4,prom1		#
	cmpd	r1,0(r0)		# is prog.-end indicator ?
	bne	prom0			# if not, loop until find it
	bispsrb	$C_flag			# set carry bit
	sbitb	$EPROM_pass, r6		# set pass bit in r6
	cmpw	r2,4(r0)		# cal. cksm = prestored cksm ?
	beq	prom2			# if yes, return
	bicpsrb	$C_flag			# if no, clear carry bit (error)
	cbitb	$EPROM_pass, r6		# clear pass bit in r6
	addr	dfail_msg, r5
	call 	out_msg
	br	test4_ret
prom2:  addr	pass_msg, r5 
	call 	out_msg
#endif
	br	test4_ret

 #=== check CENTRONICS port (Test 5) ==========#
 #  Check the CENTRONICS port by writing and 
 #  reading data at the status 
 #    register (CNS).
 #=============================================#
check_cent:
	addr	cent_msg1, r5
	call	out_msg
	movb	$0xaa,cent_status	# Write a byte to status register
	movb	cent_status,r0		# Read the status register
	cmpb	r0,$0xaa		# Verify if the data is correct
	bne	cent_error		# if not, report error
	movb	cent_data,r1		# Read the data register
	sbitb	$CENTRON_pass,r6
	addr	pass_msg, r5
	call 	out_msg
	br	test5_ret
cent_error:
	bicpsrb	$C_flag			# clear C flag to indicate failure
	addr	cent_msg2, r5
	call	out_msg
	br	test5_ret


 #=== check scsi (Test 6) ==================#
check_scsi:
#ifndef BURN

scsi_start:: 
	addr	scsi_msg1, r5
	call	out_msg
       	bispsrb $b'01000000	# clear zero flag
        movb $mode_e, @scsi_icr	# .set controller to e mode
	movb $loop_back, @scsi_emr	# .set loop back mode
	movb $init_ctl, @scsi_icr	# drive init controls
	movb $targ_ctl, @scsi_tcr	# drive target controls
        cmpb $cur_stat, @scsi_csb	# initiator controls ok?
	beq  test_tar_ctl	# if ok, goto test_tar_ctl
	addr scsi_msg1,r5            # otherwise, dsp err msg
	call out_msg            # by calling out_msg
	cbitb $21,r6		# .set scsi error flag
	br   data_test		# skip to data test

test_tar_ctl:
	bispsrb $b'01000000	# clear zero flag
	cmpb $bus_stat,@scbsr	# target controls ok?
	beq  data_test		# if ok, goto data_test
	addr scsi_msg1,r5		# otherwise, dsp err msg
	call out_msg		# by calling out_msg
	cbitb $21,r6		# .set scsi error flag

data_test:
	bispsrb $b'01000000      # clear zero flag
	movb $ass_data,@scsi_icr	# assert data bus
        movb $par_chki,@scsi_mr2	# enable parity & int
	movb $0xaa,@scsi_odr	# output data reg = aa
	cmpb $0xaa,@scsi_csd		# current scsi data = aa?
	beq  par_int1		# if yes, check parity int
	addr scsi_msg2,r5		# otherwise, dsp err msg
	call out_msg            # by calling out_msg 
	cbitb $21,r6		# .set scsi error flag
	br   dma_test		# skip to dma test

par_int1:
	tbitb $7,@scsi_isr  	        # test bit 7 of isr
	bfc  nex_data 		# if clear, continue
	addr scsi_msg2,r5		# otherwise, dsp err msg
	call out_msg		# by calling out_msg
	cbitb $21,r6		# .set scsi error flag
	andb $b'11111001,@scsi_emr	# clear interrupt
	orb  $b'00000010,@scsi_emr	
	andb $b'11111001,@scsi_emr
	br   dma_test		# skip nex_data test

nex_data: 
	bispsrb $b'01100000	# clear zero and flag bit
	movb $0x55,@scsi_odr	# .set output data reg = 55
	cmpb $0x55,@scsi_csd		# current scsi data reg = 55?
	beq  par_int2		# if yes, check parity int
	addr scsi_msg2,r5		# otherwise, dsp err msg
	call out_msg		# by calling out_msg
	cbitb $21,r6		# .set scsi error flag
	br   dma_test		# skip to dma_test

par_int2:
	tbitb $7,@scsi_isr	        # test bit 7 of isr
	bfc dma_test		# if clear, continue
        addr scsi_msg2,r5		# otherwise, dsp err msg
	call out_msg		# by calling out_msg
	cbitb $21,r6		# .set scsi error flag
	andb $b'11111001,@scsi_emr	# clear interrupt
	orb  $b'00000010,@scsi_emr
	andb $b'11111001,@scsi_emr

dma_test:
	bispsrb $b'01000000	# clear zero flag
	movb $bsy_data,@scsi_icr	# bsy & data bus on
	movb $dma_eop,@scsi_mr2	# enable dma & eop int
	movb $0xaa,@scsi_odr	# write aa to output reg
	movb $ass_req,@scsi_tcr	# assert req
	movb $star_dma,@scsds	# start dma send
        movb $des_req,@scsi_tcr	# deassert req
	cmpb $0xaa,@scsi_idr		# current scsi data reg = aa?
	beq  eop_int_ok		# if yes, check eop int
	addr scsi_msg3,r5		# otherwise, dsp err msg
	call out_msg		# by calling out_msg
  	cbitb $21,r6		# .set scsi error flag
#endif
	br	test6_ret 

eop_int_ok:
	bispsrb $b'01000000	# clear zero flag
	cmpb $eop_int,@scbsr	# eop int asserted?
	beq  res_int1 		# if yes, continue
	addr scsi_msg3,r5		# otherwise, dsp err msg
	call out_msg		# by calling out_msg
	cbitb $21,r6		# .set scsi error flag
	br	test6_ret	

res_int1:
	andb $b'11111001,@scsi_emr	# clear interrupt
 	orb  $b'00000010,@scsi_emr
	andb $b'11111001,@scsi_emr

	bispsrb $b'01000000	# clear zero flag
	movb $0x55,@scsi_odr	# write 55 to output reg
	movb $ass_req,@scsi_tcr	# assert req
 #.set mode_e, 0x040 	# enhanced mode
	movb $star_dma,@scsds	# start dma send
	movb $des_req,@scsi_tcr	# deassert req
	cmpb $0x55,@scsi_idr		# current scsi data = 55?
	beq  eop_int_ok2	# if yes, check eop int
	addr scsi_msg3,r5		# otherwise, dsp err msg
	call out_msg		# by calling out_msg
	cbitb $21,r6		# .set scsi error flag
 	br	test6_ret	

eop_int_ok2:
	bispsrb $b'01000000	# clear zero flag
	cmpb $eop_int,@scbsr	# eop int asserted?
	beq  res_int2		# if yes, continue
	addr scsi_msg3,r5		# otherwise, dsp err msg
	call out_msg		# by calling out_msg
	cbitb $21,r6		# .set scsi error flag
res_int2:
	andb $b'11111001,@scsi_emr	# clear interrupt
	orb  $b'00000010,@scsi_emr
	andb $b'11111001,@scsi_emr

	br	test6_ret


 #=== check KEYBOARD INTERFACE (Test 7 ) =============================#
 #  Check the keyboard interface by writing to the Miscellaneous I/O  #
 #  Output register (MIO) and reading back from the Miscellaneous I/O #
 #  In register (MII).						      #
 #====================================================================#
check_keybd:
#ifndef BURN
	movb 	$led_6, led_port	# Display test routine # to LED
	addr    keyb_msg1, r5		# Display testing message 
	call	out_msg
	movb	$0x55,mio_out    	# Write a byte x55 to MIO register
	movb	mio_in,r0		# Read the data back from the MII reg.
	cmpb	r0,$0x55		# Verify if the data is correct
	bne	mio_error		# if not, report error
	movb	$0xaa,mio_out    	# Write a byte xAA to MIO register
	movb	mio_in,r0		# Read the data back from the MII reg.
	cmpb	r0,$0xaa		# Verify if the data is correct
	bne	mio_error		# if not, report error
	sbitb	$KEYB_pass,r6
	addr	pass_msg, r5		# display PASS message
	call 	out_msg
	br	test7_ret
mio_error:
	bicpsrb	$C_flag			# clear C flag to indicate failure
	addr	dfail_msg, r5		# display FAIL message
	call	out_msg
#endif
	br	test7_ret


 #--------- Test TCP -----------------------------------------#
 #
 #	This is a test for TCP(timer clock peripheral) of
 #	LX32 EB in power on diagnoistics. The test consists
 #	of seven main parts:
 #	1. oscillator -->	check whether the crystal 
 #				function properly
 #	2. internal RAM -->	write, read & verify data 
 #				in RAM
 #	3. clock -->	load the date 23:59:59.99  12/31/99
 #			and wait for 10mS and check the result
 #	4. alarm -->	load the date 23:59:59.99 12/31/99 &
 #			set alarm to 0:0:0.xx 1/1/00, then 
 #			delay > 10mS & wait for interrupt
 #	5. periodic interrupt -->
 #			setup 1 sec. periodic int., delay &
 #			check int. really occur or not
 #	6. timer -->	set up timer & start the count
 #			store the instant counter value 
 #			continuously until count to zero &
 #			interrupt --> check if all OK
 #	7. hardware reset -->
 #			copy a reset service routine to 
 #			address zero, trigger the HW reset &
 #			see reset really process or not
 #
 ##########################################################

	.udata
	.align	4

tmp16b:	.blkd	4
store:	.blkd	1

	.text
	.align	4

setime:	.byte	0x99,0x59,0x59,0x23	# set time to 23:59:59.99 
	.byte	0x31,0x12,0x99,0x99	# 12/31/99 julian = 399
	.byte	0x03,0x07		# saturday
cktime:	.byte	0x00,0x00,0x00,0x00	# after 10mS, time should
	.byte	0x01,0x01,0x00,0x00	# 0:0:0.xx 1/1/00 jul.= 1
	.byte	0x00,0x01		# sunday
tcp_dt:	.double	tcp_int_rou,tcp_int_rou	# tcp dispatch table


	.macro	mvsting	len, from, to	# move string
	movd	{len},r0
	addr	{from},r1
	addr	{to},r2
	movsb
	.endm

	.macro	cpsting len, s1, s2	# compare string
	movd	{len},r0
	addr	{s1},r1
	addr	{s2},r2
	cmpsb
	.endm

tcp_int_rou:
	mvsting	$14,@tcp_msc,@tmp16b	# clk & timers (14b) save
	bispsrb	$0x80			# set N flag indicate int.
	movd	$1,r0			# escape delay loop imm.
	movb	$0x55,r2		# flag int
	reti				# go back

check_tcp:
tcp_main:
	addr    tcp_msg1, r5		# Display testing message 
	call	out_msg
	# initialize TCP #

	movb	$0x7f,@tcp_msr		# ps=0,rs=1,clear all int.
	movb	$0x40,@tcp_rtmr		# 24hr mode, clock stop, 4.19MHz
	movb	$0x2a,@tcp_omr		# output push-pull active low
	movb	$0,@tcp_icr0		# disable all interrupts
	movb	$0,@tcp_icr1		# 
	cbitb	$6,@tcp_msr		# rs=0 
	movb	$0,@tcp_irr		# all route to INT 
	cbitb	$6,@tcp_pfr		# standby (normal) mode
	bfs	tcp_osc_err		# if f=1--> OSC. failure
	sbitb	$6,@tcp_msr		# rs=1

	# testing internal ram #

	sbitb	$7,@tcp_msr		# ps=1 --> select ram
	mvsting	$31,@dataad,@tcp_addr+1	# move random # to ram
	cpsting	$31,@dataad,@tcp_addr+1	# read back & compare
	bne	tcp_ram_err		# if diff. --> ram error
	cbitb	$7,@tcp_msr		# ps=0 --> select page 0

	# testing the clock #

	mvsting	$10,setime,@tcp_msc	# set clock time
	sbitb	$3,@tcp_rtmr		# start the clock
	movw	$0xffff,r0		# 1 S > delay > 10mS   
tcp_delay:
	acbw	$-1,r0,tcp_delay	#
	cbitb	$3,@tcp_rtmr		# stop the clock
	cpsting	$9,cktime+1,@tcp_scc	# compare if expect time ?
	bne	tcp_clk_err		# if not equal--> error

	# establish temporary dispatch table #

	sprd	intbase,r4		# store the old table
	addr	tcp_dt,r0
	lprd	intbase,r0		# load the temp. one
	lprd	cfg,$0x01f0		# direct exception mode 
					# nonvectored int
	bicpsrw	$0x800			# disable cpu interrupts
	
	# testing the alarm & periodic interrupt #

	mvsting	$10,setime,@tcp_msc	# set the clock time
	mvsting	$5,cktime+1,@tcp_tcr	# set alarm =clk time +10mS
	movb	cktime+9,@tcp_tcr+5	# 
	movqb	0,r2			# r2 signal int 
	movb	$0x41 ,@tcp_icr1	# Seconds int   alarm int enable
	sbitb	$3,@tcp_rtmr		# start the clock
	movw	$0xffff,r0		# 1 S > delay > 10 mS
tcp_delay1:	
	acbw	$-1,r0,tcp_delay1	# (if int.->escape imm.)
	cmpb	$0x55,r2
	bne	tcp_alarm_err
	movqb	0,@tcp_icr1		# alarm interrupt disable
	movb	$0x7f,@tcp_msr		# clear tcp int. status
	movqb	0,r2
	sbitb	$2,@tcp_icr0		# periodic seconds int.
	movd	$0x00800000,r0		# 10 S > delay > 1 S
tcp_delay2:	
	acbd	$-1,r0,tcp_delay2	# (if int.-> escape imm.)
	cmpb	$0x55,r2
	bne	tcp_alarm_err		# no int.--> periodic err.
	movb	$0xc0,@tcp_icr0		# disable periodic int.
					# enable timer0,1 int.
	
	# testing timer interrupt #

	movb	$0x3f,@tcp_msr		# rs=0, clear tcp int. status
	movb	$0x20,@tcp_t0cr		# set T0,T1:clk=1kHz(1mS)
	movb    $0x20,@0xff200002
	movb	$0x20,@tcp_t1cr		#           single pulse
	movb	$10,@tcp_t0l		#           count=10(10mS)
	movb	$0,@tcp_t0m		#           stop count
	movb	$10,@tcp_t1l		#
	movb	$0,@tcp_t1m		#
	movqb	0,r2
	#sbitb	$0,@tcp_t0cr		# start T0 count
	movb	$0x21,@tcp_t0cr
	movw	$0xffff,r0		# delay > 10ms
tcp_delay3:	
	acbw	$-1,r0,tcp_delay3	# (if int.-> escape imm.)
	cmpb	$0x55,r2
	bne	tcp_timer_err		# no int. --> timer error
	cbitb	$0,@tcp_t0cr		# stop timer 0
	movb	$0x3f,@tcp_msr		# clear tcp int. status
	movqb	0,r2
	#sbitb	$0,@tcp_t1cr		# start T1 count
	#movb	$0x21,@tcp_t1cr
	movb	$0x21,@0xff200002
	movw	$0xffff,r0		# delay > 10 ms
tcp_delay4:	
	acbw	$-1,r0,tcp_delay4	# (if int.--> escape imm.)
	cmpb	$0x55,r2
	bne	tcp_timer_err		# no int.--> timer error
	#cbitb	$0,@tcp_t1cr		# stop timer 1
	cbitb	$0,@0xff200002		# stop timer 1
	movb	$0x3f,@tcp_msr		# clear tcp int. status

	# testing hardware reset function (MFO pin) #
#ifdef	NOTDEF
	addr	wdt_msg1, r5
	call	out_msg
	mvsting	$end-start,start,@0	# copy HW reset routine to address 0
	br	skip			# skip that reset routine
start:	nop				# align the return address
	nop				# to @4
	movd	$0,r0			# place return addr. to r0
	cbitb	$1,@tcp_irr		# periodic int. route to INT
	jump	r0			# go back
end:	.

trig:	movd	tos,@4			# place return address 
	save	[r4,r5,r6,r7]		# save reg.
	sprd	mod,tos			# save MOD
	sprd	intbase,tos		# save INTBASE
	sprd	psr,tos			# save PSR
	sprd	fp,tos			# save FP
	sprd	sp,@store		# save stack pointer

	sbitb	$6,@tcp_msr		# rs=1
	sbitb	$5,@tcp_icr0		# 1ms periodic int. enable
	sbitb	$3,@tcp_rtmr		# start the clock
	movw	$0xffff,r0		# init. delay loop
	cbitb	$6,@tcp_msr		# rs=0
	sbitb	$1,@tcp_irr		# periodic int. route to MFO
tcp_delay5:	
	acbw	$-1,r0,tcp_delay5	# delay > 1ms wait for int.
	cbitb	$1,@tcp_irr		# per. int. route to INT
	br	tcp_wd_err		# no reset --> error

skip:	bsr	trig
	cbitb	$1,@tcp_irr		# per. int. route to INT
	sbitb	$6,@tcp_msr		# rs=1
	cbitb	$5,@tcp_icr0		# 1ms per. int. disable
	cbitb	$3,@tcp_rtmr		# stop the clock

	lprd	sp,@store		# restore SP
	lprd	fp,tos			# restore FP
	lprd	psr,tos			# restore PSR
	lprd	intbase,tos		# restore INTBASE
	lprd	mod,tos			# restore MOD
	restore	[r4,r5,r6,r7]		# restore reg.

	# end of test #
#endif

	bispsrw	$C_flag			# set carry bit to indicate pass
	lprd	intbase,r4		# restore dispatch table
	addr	pass_msg,r5
	call	out_msg
	br	test8_ret		# back home

	# error handling #

tcp_osc_err:
	movb	$0x7f,@tcp_msr		# ps=0,rs=1,clear all int.
	sbitb	$0x3,@tcp_rtmr 		# restart clock to clear failure

	addr	tcp_msg2, r5
	br	tcp_msg_out
tcp_ram_err:
	addr	tcp_msg3, r5
	br	tcp_msg_out
tcp_clk_err:
	addr	tcp_msg4, r5
	br	tcp_msg_out
tcp_alarm_err:
	addr	tcp_msg5, r5
	br	tcp_msg_out
tcp_timer_err:	
	addr	tcp_msg6, r5
tcp_msg_out:
	call	out_msg
	bicpsrw	$C_flag    		# clear carry bit to indicate fail 
	lprd	intbase,r4		# restore dispatch table
	br	test8_ret		# finished

tcp_wd_err:
	cbitb	$6,@tcp_msr		# rs=0
	cbitb	$1,@tcp_irr		# per. int. route to INT
	addr	tcp_msg7, r5
	br	tcp_msg2_out
tcp_per_err:
	addr	tcp_msg8, r5
tcp_msg2_out:
	call	out_msg
	bicpsrw	$C_flag 		# clear carry bit to indicate fail 
	lprd	intbase,r4		# restore dispatch table
	br	test8_ret		# finished


 #=== check icu (Test 9) ===================#
 #
 #	This is a testing routine for ICU & keyboard of 
 #	lx32 EB. A dispatch table is generated in this 
 #	routine for 16 various hardware interrupt lines & 
 #	also software interrupt by the internal counter
 #	The test will be divided into 5 parts :
 #	1. initialize icu
 #	2. generate temporary dispatch table
 #	3. icu data bus checking
 #	4. icu internal counters checking
 #	5. simulate 16 interrupt requests
 #	6. keyboard checking
 #
 #===========================================================#

	.udata
	.align	4
inside_ram:
int_id:		.blkw	1
phy_path_l:	.blkb	1
phy_path_h:	.blkb	1

	.text

	.align	4

at_int_id:
	.double	0x00010001			# sirq3 int_id
	.double	0x00040004			# sirq4 int_id
	.double	0x00800080			# sirq5 int_id
	.double	0x01000100			# sirq6 int_id
	.double	0x80008000			# sirq7 int_id
dma_int_id:
	.double	0x00020002			# dma int_id
ctr_int_id:
	.double	0x00100010			# counter int_id
scwd_int_id:
	.double	0x00200020			# scsi watchdog id
sint_int_id:
	.double	0x00400040			# scsi int. id
kbd_int_id:
	.double	0x20002000			# keyboard id
exp_int_id:
	.double	0x00080008			# xint1 int_id
	.double	0x40004000			# xint2 int_id
uart_int_id:
	.double	0x04000400			# siir2 int_id
	.double	0x02000200			# siir1 int_id

int_dis_tb:						# dispatch table
	.double	int_nvi,int_nmi,int_abt,int_slave 	# direct-exception
	.double	int_ill,int_svc,int_dvz,int_flg   	# mode enabled
	.double	int_bpt,int_trc,int_und,int_res   
	.double	int_res,int_res,int_res,int_res
	.double	int_at3,int_dma,int_at4,int_exp1
	.double	int_ctr,int_scwd,int_sint,int_at5
	.double	int_at6,int_uart1,int_uart0,int_centb
	.double	int_centp,int_kbd,int_exp2,int_at7

 #
 #	16 interrupt routines
 #

clr_ipnd:					#<--clear interrupt--> 
	sbitb	$3,@mctl			# frozen ipnd register
	movb	$0xff,@imsk_l			# mask all interrupts
	movb	$0xff,@imsk_h			# 
	movb	$0xff,@eltg_l			# level interrupts --> 
	movb	$0xff,@eltg_h			# --> clear input latch
	movb	$0,@tpl_l			# low level trigger
	movb	$0,@tpl_h			# 
	movb	$0x40,@ipnd_l			# clear pending interrupts
	movb	$0x40,@ipnd_h 			# 
	movb	$0,@eltg_l 			# edge interrupts
	movb	$0,@eltg_h 			# 
	movb	$0,@tpl_l			# low level trigger
	movb	$6,@tpl_h			# 
	movb	$0x82,@mctl 			# out of test mode
	movw	$0x1000,r0			# delay a while
delay:	acbw	$-1,r0,delay			# for icu settles ...     
	ret	$0

	.macro	intr vec			#<--interrupt routine--> 
	movw	{vec},@int_id			# store interrupt routine #
	movb	@isrv_l,@phy_path_l		# store physical pin # which
	movb	@isrv_h,@phy_path_h		# requested interrupt
	jsr	clr_ipnd:w			# clear pending interrupts
	movd	$2,r0				# force looping to end
	movb	$0,r3				# clear indicator:int. success
	reti
	.endm

int_nvi:	
	intr	$0xfff0
int_nmi:	
	intr	$0xfff1
int_abt:	
	intr	$0xfff2
int_slave:	
	intr	$0xfff3
int_ill:	
	intr	$0xfff4
int_svc:	
	intr	$0xfff5
int_dvz:	
	intr	$0xfff6
int_flg:	
	intr	$0xfff7
int_bpt:	
	intr	$0xfff8
int_trc:	
	intr	$0xfff9
int_und:	
	intr	$0xfffa
int_res:	
	intr	$0xfffb
int_at3:	
	intr	$0x0001
int_dma:	
	intr	$0x0002
int_at4:	
	intr	$0x0004
int_exp1:	
	intr	$0x0008
int_ctr:	
	intr	$0x0010
int_scwd:	
	intr	$0x0020
int_sint:	
	intr	$0x0040
int_at5:	
	intr	$0x0080
int_at6:	
	intr	$0x0100
int_uart1:	
	intr	$0x0200
int_uart0:	
	intr	$0x0400
int_centb:	
	intr	$0x0800
int_centp:	
	intr	$0x1000
int_kbd:	
	intr	$0x2000
int_exp2:	
	intr	$0x4000
int_at7:	
	intr	$0x8000

 #
 #	subroutine to initialize icu
 #

icu_init:
	movb	$0x82,@mctl 		# 8 bit data, fixed mode, frozen counter
	movb	$0x80,@cctl 		# set counter concatenated & halted
	# initialize counters start & current  values
	movqb	0x1,lcsv_l
	movqb	0x1,lcsv_h
	movqb	0x1,hcsv_l
	movqb	0x0,hcsv_h
	movqb	0x1,lccv_l
	movqb	0x1,lccv_h
	movqb	0x1,hccv_l
	movqb	0x0,hccv_h
	movb	$0xff,@ips 		# set ir0-ir14 for interrupts
	movb	$0xff,@pdir 		# set port input direction
	movb	$0x00,@ocasn 		# don't assign clk to any lines
	movb	$0x00,@isrv_l 		# clear in-service interrupt
	movb	$0x00,@isrv_h 		# 
	movb	$0x00,@csrc_l	 	# no cascade icu
	movb	$0x00,@csrc_h 		# 
	movb	$0x10,@svct 		# bias = 16, 1st entry in dispatch TB
	movb	$0x00,@eltg_l 		# set edge trigger mode
	movb	$0x00,@eltg_h 		# 
	movb	$0x00,@tpl_l 		# set all falling edge trigger
	movb	$0x6,@tpl_h 		# polarity of uart rising edge trigger
	movb	$0x00,@fprt_l 		# set ir0 to have first priority
	movb	$0xff,@imsk_l 		# mask all interrupts
	movb	$0xff,@imsk_h 		#
	ret	$0

check_icu:
icu_main:
	addr    icu_msg1, r5		# Display testing message 
	call	out_msg
	movw	$0,@int_id		# clear interrupt ID
	jsr	icu_init:w		# initialize icu

	# icu data bus checking --- walk one/zero #

	movb	$1,r0			# walk one/zero : initialized data
	movb	$8,r1			# walk 8 bits
walk:	movb	r0,@lcsv_l		# walk one	
	comb	r0,r2			#
	comb	r0,@lcsv_h		# walk zero
	cmpb	@lcsv_l,r0		# 
	bne	bus_err			# walk one fail --> data bus error
	cmpb	@lcsv_h,r2		#
	bne	bus_err			# walk zero fail --> data bus error
	rotb	$1,r0			# shift 1 bit
	acbb	$-1,r1,walk		# loop 8 times

	# counters interrupt checking #
	sprd	intbase,r4		# store the previous dispatch table
	addr    int_dis_tb, r0
	#lprd	intbase,int_dis_tb	# load table for icu test only
	lprd	intbase,r0
	lprd	cfg,$0x1f7		# set to direct exception mode
	jsr	icu_init:w		# initialize icu
	movb	$0x10,@cctl		# 16bit ctr halt, zero-detect of L
	movb	$0x03,@cictl		# enable L-counter interrupt
	movb	$0x44,@ciptr		# counter point to interrupt 4
#ifdef	NOTDEF
		# init counters in icu_init routine
	movb	$0xff,@lcsv_l		# ctr-L initial value =1ff
	movb	$1,@lcsv_h		# 
	movb	$0xff,@hcsv_l		# ctr-H initial value =1ff
	movb	$1,@hcsv_h		#
#endif
	movb	$0xff,r3		# indicator:if int. success `0'->r3
	movb	$0xef,@imsk_l		# unmask interrupt 4
	bispsrw	$0x800			# enable cpu interrupt
	sbitb	$2,@cctl		# L-counter start running
	movw	$0xffff,r0		# delay --> wait for interrupt
delay1:	acbw	$-1,r0,delay1		#
	movb	$0xb0,@cctl		# 32bit ctr halt, zero-detect of H-L
	cmpqb	$0,r3			# they are equal if int. success
	bne	ctr_int_err		# no interrupt -> counter int. error
	cmpd	ctr_int_id,@int_id	# interrupt ID & phy. path OK ?
	bne	ctr_int_err		# wrong ID or phy. path -> error

	movb	$0x31,@cictl		# enable HL-counter interrupt
	jsr	clr_ipnd:w		# clear icu latch
	movb	$0x31,@cictl		# enable HL-counter interrupt
	movb	$0x44,@ciptr		# counter point to interrupt 4
	movd	$0,@int_id		# clear int_id, phy_path_l/h
	movb	$0xff,r3		# indicator:if int. success `0'->r3
	movb	$0xef,@imsk_l		# unmask interrupt 4
	sbitb	$3,@cctl		# HL-counter start running
	movd	$3 * SEC,r0		# delay --> wait for interrupt
delay2:	acbw	$-1,r0,delay2		#
	cmpqb	$0,r3			# they are equal if int. success
	bne	ctr_int_err		# no interrupt -> counter int. error
	cbitb	$3,@cctl		# stop the HL counter
	cmpd	ctr_int_id,@int_id	# OK?
	bne	ctr_int_err		# wrong --> error
	jsr	clr_ipnd:w		# clear icu latch

	# duart interrupts checking #

	movd	$2,r1			# check 2 channals
uart_test:
	movb	$0x13,@uart1+u_mcr-8[r1:q]	# set loopback mode, DTR=RTS=1
	movb	$0xf9,@imsk_h		# unmask icu level 9 & 10
	movd	$0,@int_id		# clear int. ID
	movb	$0xff,r3		# indicator:if int. success `0'->r3
	cbitb	$7,@uart1+u_lcr-8[r1:q]		# set DLAB = 0
	cmpqb	$0,@uart1+u_msr-8[r1:q]	# clear modem status bits
	sbitb	$3,@uart1+u_ier-8[r1:q]	# enable uart modem status interrupt
	movw	$0xffff,r0
delay6a:	
	acbw	$-1,r0,delay6a	
	movw	$0xffff,r0		# delay --> wait for interrupt
	cbitb	$1,@uart1+u_mcr-8[r1:q]	# RTS=0 --> generate interrupt	
delay6:	acbw	$-1,r0,delay6		# 
	cbitb	$3,@uart1+u_ier-8[r1:q]	# clear enabled interrupt
	cmpqb	$0,r3			# they are equal if int. success
	bne	uart_int_err		# no int. --> error
	cmpd	uart_int_id-4[r1:d],@int_id # int ID match ?
	bne	uart_int_err		# not match --> error
	jsr	clr_ipnd:w		# clear icu latch
	acbb	$-1,r1,uart_test:w	# loop 2 times for 2 channals
	call 	uart_init

#ifndef BURN
	# SCSI interrupt checking #

	movb	$0x40,@scsi_icr		# set mode e
	movb	$0x8,@scsi_emr		# set loop back
	movb	$0x49,@scsi_icr		# bsy & data bus on
	movb	$0xa,@scsi_mr2		# enable dma & eop int
	movb	$0xaa,@scsi_odr		# write aa to output reg.
	movb	$0x8,@scsi_tcr		# assert req.
	movb	$0xbf,@imsk_l		# unmask level 6
	movb	$0xff,r3		# indicator:if int. success `0'->r3
	movw	$0xffff,r0		# delay --> wait for interrupt
	movd	$0,@int_id		# clear interrupt ID
	movb	$0,@scsds		# start dma send
	movb	$0,@scsi_tcr		# deassert req.
delay7:	acbw	$-1,r0,delay7		#
	cmpqb	$0,r3			# they are equal if int. success
	bne	sint_int_err		# no int. --> error
	cmpd	sint_int_id,@int_id	# int. ID match ?
	bne	sint_int_err		# not match --> error
	jsr	clr_ipnd:w		# clear icu latch

	# scsi watchdog interrupt checking #

	movb	$0x7f,@tcp_msr		# initialize TCP : rs=1
	movb	$0x2a,@tcp_omr		# o/p push-pull active L
	movb	$0,@tcp_icr0		# disable INTR pin
	movb	$0,@tcp_icr1		# 
	cbitb	$6,@tcp_msr		# rs=0
	movb	$0x20,@0xff200002		# set T1 clk=1kHz,single pulse
	#movb	$0x20,@tcp_t1cr		# set T1 clk=1kHz,single pulse
	movb	$10,@tcp_t1l		# set T1 count=10 (ms)
	movb	$0,@tcp_t1m		# end of TCP initialization
	movb	$0xdf,@imsk_l		# unmask level 5
	movb	$0xff,r3		# indicator:if int. success `0'->r3
	movd	$0,@int_id		# clear interrupt ID
	#sbitb	$0,@tcp_t1cr		# start T1 count
	sbitb	$0,@0xff200002		# start T1 count
	movw	$0xffff,r0		# delay --> wait for interrupt
delay8:	acbw	$-1,r0,delay8		#
	#cbitb	$0,@tcp_t1cr		# stop T1 count
	cbitb	$0,@0xff200002		# stop T1 count
	movb	$0x7f,@tcp_msr		# clear TCP reg.
	cmpqb	$0,r3			# intrrupt success ?
	bne	scwd_int_err		# if fail --> error
	cmpd	scwd_int_id,@int_id	# int. ID match ?
	bne	scwd_int_err		# not match --> error
	jsr	clr_ipnd:w		# clear icu latch

	# keyboard clock interrupt checking #

	sbitb	$1,@bd_mio		# set kbd clock for test
	movb	$0xdf,@imsk_h		# unmask level 13
	movb	$0xff,r3		# indicator:if int. success `0'->r3
	movd	$0,@int_id		# clear interrupt ID
	cbitb	$1,@bd_mio		# clear kbd clock
	sbitb	$1,@bd_mio		# set kbd clock for trigger
	movd	r0,r0			# dummy
	cmpqb	$0,r3			# interrupt executed ?
	bne	kbd_int_err		# if no --> error
	cmpd	$kbd_int_id,@int_id	# int. ID OK ?
	bne	kbd_int_err		# if not --> error
	jsr	clr_ipnd:w		# clear icu latch

#endif
	# end of test #

	lprd	intbase,r4		# restore old dispatch table
	bispsrb	$C_flag			# set carry bit to indicate pass
	addr	pass_msg, r5
	call	out_msg
	br 	test9_ret		# icu test finish 

	# error handling #

bus_err:
	addr	icu_msg2, r5
	br	icu_fail
ctr_int_err:
	addr	icu_msg3, r5
	br	icu_fail
at_int_err:
	addr	icu_msg4, r5
	br	icu_fail
dma_int_err:
	addr	icu_msg5, r5
	br	icu_fail
exp_int_err:
	addr	icu_msg6, r5
	br	icu_fail
uart_int_err:
	call 	uart_init
	addr	icu_msg7, r5
	br	icu_fail
sint_int_err:
	addr	icu_msg8, r5
	br	icu_fail
scwd_int_err:
	addr	icu_msg9, r5
	br	icu_fail
kbd_int_err:
	addr	icu_msg10, r5
	br	icu_fail
icu_fail:
	call	out_msg
	jsr	clr_ipnd:w		# clear icu latch
	lprd	intbase,r4		# restore old dispatch table
	bicpsrb	$C_flag			# clear carry bit to indicate fail
	br	test9_ret		# icu test finish



 #=== check engine interface (Test 10) =====#
check_engine:
# ifndef BURN
	addr    eng_msg1, r5
	call 	out_msg
	movb	$0x55,r0
	movb	r0,r2
	movb	r0,@eng_isr		# load test pattern
	comb	@eng_isr,@eng_isr	# complement itself
	xorb	@eng_isr,r0		# normally r0 = 0xff
	orb	$0xf0,r0		# eng_isr bit4-7 undef.
	movb	r0,r1			# store the result
	movb	r2,r0
	movb	r0,@eng_lsr		# load test pattern
	comb	@eng_lsr,@eng_lsr	# complement itself
	xorb	@eng_lsr,r0		# normally r0 = 0xff
	orb	$0xe0,r0		# eng_lsr bit5-7 undef.
	andb	r0,r1			# and the result
	movb	r2,r0	
	movb	r0,@eng_sdr		# load test pattern
	comb	@eng_sdr,@eng_sdr	# complement itself
	xorb	@eng_sdr,r0		# normally r0 = 0xff
	orb	$0xf8,r0		# eng_sdr bit3-7 undef.
	andb	r0,r1			# and the result
	cmpb	$0xff,r1		# is any one test fail?
	bne	eng_err			# if yes, error

	# end of test #

	sbitb	$ENG_pass,r6		# set pass bit in r6
	bispsrb	$C_flag			# set carry bit to indicate pass
# endif
	br	test10_ret	  	# back home

	# error handling #

eng_err:
	cbitb	$ENG_pass,r6		# clear eng. I/F pass bit in r6
	bicpsrb	$C_flag			# clear carry bit to indicate error 
	br	test10_ret		# finish job

 ####### Test EPROM modes (Test 12 ) ###############################
 #
 #	This routine test the differences between
 #	four eprom regions (40000000,42000000,
 #	44000000 & 46000000) which have their unique
 #	properties (casheable or not/burst on or off)
 #	but actually mapped to a same physical 
 #	location.
 #	the property of cashe can be detected by
 #	1. read byte from a eprom location
 #	2. write its complement back to that location
 #	3. read back again and verify if the data alter
 #	4. if data can be altered, then it's casheable
 #	the property of burst on can be detected by
 #	1. setup the TCP as a timer
 #	2. move a block of data in burst off region
 #	   to itself and count the time used
 #	3. move a block of data in burst on region
 #	   back to itself. also count the time
 #	4. compare if the time used in 2. is longer
 #	   than in 3. then burst mode is really on.
 #
 ##################################################

check_epmode:	
	addr	epm_msg1, r5		# display test message
	call 	out_msg
	lprw	cfg,$0x3f0		# enable data cashe
	movd	$PROM0,r0		# (casheable)
	movb	0(r0),r1		# read data
	comb	r1,0(r0)		# write the complement back
	cmpb	r1,0(r0)		# write action success ?
	beq	rom_csh_err		# if no --> error
	movd	$PROM1,r0		# (casheable)
	movb	0(r0),r1		# read data
	comb	r1,0(r0)		# write the complement back
	cmpb	r1,0(r0)		# write action success ?
	beq	rom_csh_err		# if no --> error
	movd	$PROM2,r0		# (non-casheable)
	movb	0(r0),r1		# read data
	comb	r1,0(r0)		# write the complement back
	cmpb	r1,0(r0)		# write action success ?
	bne	rom_csh_err		# if yes --> error
	movd	$PROM3,r0		# (non-casheable)
	movb	0(r0),r1		# read data
	comb	r1,0(r0)		# write the complement back
	cmpb	r1,0(r0)		# write action success ?
	bne	rom_csh_err		# if yes --> error


	addr	pass_msg, r5
	call 	out_msg

	#MON Window check
	addr	drm_msg1, r5		# display test message
	call 	out_msg

	movb	@dram_start1+0x10000 ,r0	#read to init cache line
	movb	$0x55, @dram_start1 + 0x10000	#casheable window
	movb	$0xaa, @dram_start2 + 0x10000	
	cmpb	$0x55,@dram_start1+ 0x10000
	bne	rom_csh_err
	movb	$0xaa, @dram_start3 + 0x10000	
	cmpb	$0x55,@dram_start1+ 0x10000
	bne	rom_csh_err
	movb	$0xaa, @dram_start4 + 0x10000	
	cmpb	$0x55,@dram_start1+ 0x10000
	bne	rom_csh_err

	movb	@dram_start2+0x10000 ,r0	#read to init cache line
	movb	$0x55, @dram_start2 + 0x10000	#casheable window
	movb	$0xaa, @dram_start1 + 0x10000	
	cmpb	$0x55,@dram_start2+ 0x10000
	bne	rom_csh_err
	movb	$0xaa, @dram_start3 + 0x10000	
	cmpb	$0x55,@dram_start2+ 0x10000
	bne	rom_csh_err
	movb	$0xaa, @dram_start4 + 0x10000	
	cmpb	$0x55,@dram_start2+ 0x10000
	bne	rom_csh_err

	movb	@dram_start3+0x10000 ,r0	#read to init cache line
	movb	$0x55, @dram_start3 + 0x10000	#non casheable window
	movb	$0xaa, @dram_start2 + 0x10000	
	cmpb	$0x55,@dram_start3+ 0x10000
	beq	rom_csh_err
	movb	$0xaa, @dram_start1 + 0x10000	
	cmpb	$0x55,@dram_start3+ 0x10000
	beq	rom_csh_err
	movb	$0xaa, @dram_start4 + 0x10000	
	cmpb	$0x55,@dram_start3+ 0x10000
	beq	rom_csh_err

	movb	@dram_start4+0x10000 ,r0	#read to init cache line
	movb	$0x55, @dram_start4 + 0x10000	# non casheable window
	movb	$0xaa, @dram_start2 + 0x10000	
	cmpb	$0x55,@dram_start4+ 0x10000
	beq	rom_csh_err
	movb	$0xaa, @dram_start3 + 0x10000	
	cmpb	$0x55,@dram_start4+ 0x10000
	beq	rom_csh_err
	movb	$0xaa, @dram_start1 + 0x10000	
	cmpb	$0x55,@dram_start4+ 0x10000
	beq	rom_csh_err

	# burst on/off mode testing #
#ifdef	NOTDEF
	lprd	cfg,$0x3f0			# disable data cashe
	movd	$PROM0,r1		# load base address 
	movb	$4,r3			# for looping
	movb	$0x3f,@tcp_msr		# setup TCP timer
	movb	$0x10,@tcp_t0cr		# stop the timer
burst:	movb	$0xff,@tcp_t0l		# preset T0 value
	movb	$0xff,@tcp_t0m		# to 0xffff
	movb	$0x11,@tcp_t0cr		# start the timer
	movd	$0x100,r0		# move 256 bytes
	movd	r1,r2			# move back to itself
	movsb				# action (move)
	movb	$0xd0,@tcp_t0cr		# stop timer & hold reading
	movb	@tcp_t0m,tos		# push timer value to stack
	movb	@tcp_t0l,tos		# 
	addd	$0x1ffff00,r1		# test next region
	acbb	$-1,r3,burst		# loop thro' 4 regions
	movw	tos,r3			# region 4 (burst off)
	subw	tos,r3			# minus region 3 (burst on)
	bcc	rom_bst_err		# if burst on not faster, error
	movw	tos,r3			# region 2 (burst off)
	subw	tos,r3			# minus region 1 (burst on)
	bcc	rom_bst_err		# if burst off not slower, error
# endif
	# end of the test #

	addr	pass_msg, r5
	call 	out_msg
	bispsrw	$C_flag			# set carry bit (test passed)
	br	test12_ret

	# error handling #

rom_csh_err:
rom_bst_err:
	addr	dfail_msg, r5
	call 	out_msg
	bicpsrw	$C_flag			# clear carry bit (error)
	br	test12_ret


 #=== check FPU (Test 11) ===============================================#
 # NS32381 FPU								#
 # Floating Point Unit test.						#
 # 1) verify the data path integrity of fpu & cpu by a test similar to	#
 #    walk 1's & 0's test						#
 #    Note: a)This test suit for NS32081 FPU or NS32381 FPU.		#
 #	   b)data path between cpu & fpu are tested but not the data	#
 #	     integrity of the fpu only					#
 #	   c)assume in supervisor mode, so that cfg f bit will be set	#
 # 2) fpu registers test						#
 # 3) carry out some mathematical operation test, both signed & unsigned#
 #  output: 1) r0,r1,r2,r3,r4,r5,r7 destroyed				#
 #	      r6 temp2_flag destroyed					#
 #	   2) C_flag=1 indicate test pass, otherwise, fail		#
 #=======================================================================# 
check_fpu:
	addr	fpu_msg1,r5		# display "checking fpu" message
	call	out_msg
	cbitb	$temp2_flag,r6		# clear r6 temp2_flag(flag init)
 #-- fpu exist, continue the test
fpu_exist:
 	setcfg	[f]			# enable fpu in cfg
 #-- check cpu to fpu data path by walk 1's & walk 0's test
dfpu_3:
	movd	$0x01, r0		# the highest bit after rotate
	movd	$32, r1			# loop counter
dfpu_4:
	rotd	$-1, r0			# ripple a bit through pattern
	comd	r0, r2			# complement pattern in r2
	movdf	r0, f0			# transfer patterns to 1 reg
	movdl	r2, f2			# recharge bus with complement 
	roundfd	f0, r4			# move patterns back to gp regs
	roundld	f2, r3			# 
	cmpd	r0, r4			# compare the returned pattern
	beq	dfpu_5
 #-- error found
	sbitb	$temp2_flag,r6		# set r6 temp2_flag to indicate failure
	addqd	$-1, r1			# decrement r1 to real value
	movd	r1,r5		# bit stuck at 0
	call	out_decimal	# display error (stuck at 0)
	movd	$space,r5
	call	out_byte
	addqd	$1,r1			# recover the r1 count value
dfpu_5:	cmpd	r2, r3			# compare complement pattern
	beq	dfpu_6
 #-- error found
	sbitb	$temp2_flag,r6		# set r6 temp2_flag to indicate failure
	addqd	$-1, r1			# decrement r1 to real value
	movd	r1,r5		# bit stuck at 1
	call	out_decimal	# display error (stuck at 1)
	movd	$space,r5
	call	out_byte
	addqd	$1,r1			# recover the r1 count value
dfpu_6:	acbd	$-1, r1, dfpu_4		# loop for all 32 positions

 #-- check fpu registers f0-f7 (NS32081) or l0-l3 (NS32381)
	movf	$0y55555555,f0
	movf	f0,f1
	movf	f1,f2
	movf	f2,f3
	movf	f3,f4
	movf	f4,f5
	movf	f5,f6
	movf	f6,f7
	movf	f7,f0
	cmpf	$0y55555555,f0
	bne	fpu_reg_error

	movf	$0yaaaaaaaa,f0
	movf	f0,f1
	movf	f1,f2
	movf	f2,f3
	movf	f3,f4
	movf	f4,f5
	movf	f5,f6
	movf	f6,f7
	movf	f7,f0
	cmpf	$0yaaaaaaaa,f0
	beq	fpu_mul
fpu_reg_error:
	sbitb	$temp2_flag,r6	# set r6 temp2_flag to indicate failure
	addr	fpu_msg2,r5
	call	out_msg		# report error "register error"
	br	fpu_ok		# branch out if error in registers
fpu_mul:
 #-- check float multiply instruction
	movf	$0y4a9e5b65, f0		# multiply two floating pt. #s
 	movf	$0y39a69e65, f1
 	mulf	f0, f1
 	cmpf	$0y44ce227d, f1		# compare the results
	bne	fpu_mul_error
 #-- sign double precision multiply test
	movf	$0f-1.2345e21,f0
	movf	$0f9.876e-13,f1
	mulf	f0,f1
	roundfd	f1,r0
	cmpd	$0xb7549a80,r0
	beq	fpu_ok
 #-- fpu multiply test fail
fpu_mul_error:
	sbitb	$temp2_flag,r6		# set r6 temp2_flag to indicate failure
	addr	fpu_msg3,r5		# report "multiply yield bad result"
	call	out_msg
	br	test11_ret

fpu_ok:	bicpsrb	$C_flag
	tbitb	$temp2_flag,r6
	bfs	fpu_ret
	addr	pass_msg,r5
	call	out_msg			# report 'PASS' message
	bispsrb	$C_flag			# indicate fpu test pass
fpu_ret:
	br	test11_ret



 #--- subroutine --------------------------#

 #------------------get_dram_size------------------------------#
 # r4 holds size of dram.
 #-------------------------------------------------------------#

get_dram_size:
	addr	dram_start1,r4	# addr. pointer


clear_lp:
        movb    $0x0, 0(r4)             # clear the location
        addd    $0x10000, r4            # increment
        cmpd    r4, $0x4000000          # test for end (64Mb)
        blt     clear_lp
        addr    dram_start1, r4         # init pointer again
        movb    $0x55, 0(r4)            # init first location
size_lp:
        addd    $0x10000, r4            # increment pointer
        cmpd    $0x4000000, r4          # test for end (8Mb)
        beq     max_ram                 # if 64Mb, we're done
        cmpb    $0x55, 0(r4)            # look for wrap around
        bne     test_write              # if not x'55, no wrap yet
max_ram:
        movb    $0, dram_start1         # clear ram start
        addqd   $-1, r4                 # if it is, wrap-around occured
        #jump    0(r7)                  # return to calling routine
	return
test_write:
        cmpb    $0x0,  0(r4)             # look for clear (write) success
        bne     max_ram
        movb    $0xa5,  0(r4)            # write to location
        cmpb    $0xa5,   0(r4)           # If write fails we're done
        bne     max_ram
        cmpb    $0xff, 0(r4)            # test for no ram (later boards?)
        beq     max_ram                 # no ram, must be done
        br      size_lp                 # continue
 



 #--- display message to console ---------------#
 # display the string if r6 SERIAL_pass is set	#
 # (r6 SERIAL_pass indicate if uart OK or not)	#
 #	i/p: r5 <-- message address		#
 #	o/p: r5 destroyed			#
 #----------------------------------------------#
out_msg:
# ifdef	NOTDEF
	tbitb	$SERIAL_pass,r6		# don't display if uart error
	bfc	out_ret
# endif
out_m0:	cmpb	0(r5),$0x0	# check if terminator ?
	beq	out_end
wait_empty:
	tbitb	$5,uart0+u_lsr	# test bit5 of line status reg to see
					# if tx. reg empty
	bfc	wait_empty		# if not empty, wait again
	movb	0(r5),uart0+u_tx_data	# move data to uart0 (console)
out_m1:	addqd	$1,r5
	br	out_m0
out_end:
	return

 #--- out 1 byte data to console ---------------#
 # (out  a byte if r6 SERIAL_pass is set)	#
 #	i/p: character in r5 (in byte)		#
 #	o/p: out to console			#
 #	     (no timeout check)			#
 #----------------------------------------------#
out_byte:
	tbitb	$SERIAL_pass,r6		# don't display if uart error
	bfc	out_ret
	tbitb	$5,uart0+u_lsr		# test bit5 of line status reg to see
					# if tx. reg empty
	bfc	out_byte		# if not empty, wait again
	movb	r5,uart0+u_tx_data	# move data to uart0 (console)
out_ret:
	return


 #--- out m byte data to console ----------------#
 # (out m byte if r6 SERIAL_pass is set) 	 #
 #	i/p: character in r5 (in byte)		 #
 #	   : count in high byte of the low word	 #
 #	o/p: out to console			 #
 #	     (no timeout check)			 #
 #-----------------------------------------------#
out_mbyte:
	tbitb	$SERIAL_pass,r6		# don't display if uart error
	bfc	out_mret
	tbitb	$5,uart0+u_lsr		# test bit5 of line status reg to see
			     		# if tx. reg empty
	bfc	out_mbyte		# if not empty, wait again
	movb	r5,uart0+u_tx_data	# move data to uart0 (console)
	rotw	$8,r5
	subb	$1,r5			# decrement count
	cmpb	r5,$0
	rotw	$8,r5			# get the code to low byte
	bgt	out_mbyte		# if count != 0, display it again
out_mret:
	return

 #------ out a decimal number to console -------#
 # (out the decimal if r6 SERIAL_pass is set)	#
 # if r5 <100, then display the digit		#
 # if r5 >100, then display "--"		#
 #	I/P: decimal number in r5       	#
 #	O/P: r5 is destroyed		 	#
 #	     (no time out)		 	#
 #----------------------------------------------#
out_decimal:
	tbitb	$SERIAL_pass,r6	# don't display if uart error
	bfc	out_ret
	cmpb	r5,$99
	bhi	out_dash

	movzbw	r5,r5		# ensure r5 high byte cleared
	mulw	$(256+1),r5	# duplicate low byte to high byte
	quob	$10,r5		# get ten's digit
	addb	$0x30,r5	# convert to ASCII value
out_1:	tbitb	$5,uart0+u_lsr
	bfc	out_1
	movb	r5,uart0+u_tx_data	# out the MSB to console

	lshw	$-8,r5		# move high byte to low byte
	remb	$10,r5		# get unit's digit
	addb	$0x30,r5	# convert to ASCII value
out_2:	tbitb	$5,uart0+u_lsr
	bfc	out_2
	movb	r5,uart0+u_tx_data	# out the LSB to console
	br	out_d_ret
out_dash:
	addr	dashmsg,r5	# branch to display "--" by
	br	out_msg		# out_msg subroutine
out_d_ret:	
	return


 #--- display a 32-bit hexadecimal no. -#
 # i/p: double word in r5		#
 # o/p: out to console			#
 # lower byte of r6 is destroyed	#
 #--------------------------------------#
out_hex:
	lprd	sb,r7		# save r7
	movb	$8,r6		# counter : 8 digits
out_hex1:
	rotd	$4,r5		# rotate highest nibble to lowest one
	extsd	r5,r7,0,4	# extract nibble to r7
	andb	$0x0f,r7
	movb	hextab[r7:b],uart0+u_tx_data  # o/p byte
out_x:	tbitb	$5,uart0+u_lsr
	bfc	out_x
	acbb	$-1,r6,out_hex1
	sprd	sb,r7		# restore r7
	return

hextab:	.byte	"0123456789ABCDEF"

	
 #--- display LED -----------------------#
 # display the number in r0 to LED,	#
 #   i/p: r0 (number to be displayed)	#
 #   o/p: light LED stage code		#
 # e.g r0=0 give LED 0			#
 # but r0=d to f give LED blank		#
 #  (no boundary check is done)		#
 #---------------------------------------#
disp_led:
 	movb	led_table[r0:b],led_port		#no action now !
	return

	
 #--- status report message ---------------#
led_table:	.byte	led_0,led_1,led_2,led_3,led_4,led_5,led_6,led_7
		.byte	led_8,led_9,led_A,led_b,led_C,led_d,[2]led_space

start_msg:
	.byte	cr,lf,lf,lf,"LX32 Power-On Diagnostics",0
pass_msg:
	.byte 	"Passed",0
dfail_msg:
        .byte 	"Failed",0
cpu_msg1:
	.byte	cr,lf,"1...Basic CPU Tests - Passed",0
serial_msg1:
	.byte	cr,lf,"2...Testing Serial I/O -- "
	.byte	cr,lf,"  Serial channel 1 (console) --- Passed",0
uart0_msg1:
	.byte	cr,lf,"  Serial channel 2 (tty) --- ",0
msg_lb_error:
	.byte	cr,lf,"  loopback test error",0
dram_jp_msg:
	.byte	cr,lf,"3...DRAM jumpers configuration test ",0
jp6_msg:
	.byte	cr,lf,"  JP6 may be placed incorecctly",0
jp12_msg:
	.byte	cr,lf,"  JP12 may be placed incorecctly",0
jp5_msg:
	.byte	cr,lf,"  JP5 may be placed incorecctly",0
fail_msg:
	.byte	" failed at address ",0 
dashmsg:
	.byte	"--",0
dram_msg0:
	.byte	cr,lf,"3.a...DYNAMIC MEMORY TEST: ",0
dram_msg1:
	.byte	cr,lf,"  Data path test - ",0
dram_msg2:
	.byte	cr,lf
	.byte	"bank0 data bits=0   "
	.byte	"bank0 data bits=1   "
	.byte	"bank1 data bits=0   "
	.byte	"bank1 data bits=1   ",0
dram_msg3:
	.byte	cr,lf,"  Address path test - ",0
dram_msg4:
	.byte	cr,lf,"  following address lines stuck to '0' : ",0
dram_msg5:
	.byte	cr,lf,"  following address lines stuck to '1' : ",0
dram_msg6:
	.byte	cr,lf,"  Memory R/W test - ",0
dram_msg7:
	.byte	cr,lf,"  Refresh circuitry test - ",0
dram_msg8:
	.byte	cr,lf,"  Memory size is hex ",0
dram_msg9:
	.byte	cr,lf,"  Testing cacheable/non-cacheable access",0
eprom_msg: 
	.byte   cr,lf,"4...Testing EPROM - ",0
cent_msg1:
	.byte 	cr,lf,"5...Testing Centronics port - ",0
cent_msg2:
	.byte	cr,lf,"  Failed - Status register test",0
scsi_msg:
	.byte	cr,lf,"6...Testing SCSI - ",0
scsi_msg1:
	.byte	cr,lf," SCSI SIGNAL TEST FAILED",0
scsi_msg2:
	.byte	cr,lf," SCSI DATA TEST FAILED",0
scsi_msg3:
	.byte	cr,lf," SCSI DMA TEST FAILED",0
keyb_msg1:
	.byte	cr,lf,"7...Testing Keyboard Interface - ",0
 #--- TCP test messages --------------------#
tcp_msg1:
	.byte	cr,lf,"8...Testing TCP - ",0
wdt_msg1:
	.byte	cr,lf,"8.a...Testing watch-dog timer - ",0
tcp_msg2:
	.byte	cr,lf,"   - oscillator failure.",0 
tcp_msg3:
	.byte	cr,lf,"   - internal RAM error.",0 
tcp_msg4:
	.byte	cr,lf,"   - real time clock error.",0 
tcp_msg5:
	.byte	cr,lf,"   - alarm interrupt failed.",0 
tcp_msg6:
	.byte	cr,lf,"   - timer failed.",0 
tcp_msg7:
	.byte	cr,lf,"   - watch-dog timer error.",0 
tcp_msg8:
	.byte	cr,lf,"   - periodic interrupt failed.",0 


 #-------- ICU messages --------#
icu_msg1:
	.byte	cr,lf,"9...Testing ICU - ",0
icu_msg2:
	.byte	cr,lf,"   - data bus error.",0 
icu_msg3:
	.byte	cr,lf,"   - counters interrupt error.",0
icu_msg4:
	.byte	cr,lf,"   - AT interface interrupt error.",0 
icu_msg5:
	.byte	cr,lf,"   - DMA end-of-transfer interrupt error.",0
icu_msg6:
	.byte	cr,lf,"   - expansion bus interrupt error.",0
icu_msg7:
	.byte	cr,lf,"   - DUART interrupt error.",0 
icu_msg8:
	.byte	cr,lf,"   - SCSI interrupt error.",0
icu_msg9:
	.byte	cr,lf,"   - SCSI watch-dog interrupt error.",0
icu_msg10:
	.byte	cr,lf,"   - keyboard clock interrupt error.",0

eng_msg1:
	.byte	cr,lf,"10...Testing Engine Interface ...",0
fpu_msg1:
	.byte	cr,lf,"11...Testing FPU - ",0
fpu_msg2:
	.byte	cr,lf,"  Register test error",0
fpu_msg3:
	.byte	cr,lf,"  Multiply yield bad data error",0
epm_msg1:
	.byte	cr,lf,"12...Testing EPROM cache mode -",0
drm_msg1:
	.byte   cr,lf,"12.a...Testing DRAM cache mode -",0
end_msg:
	.byte	cr,lf," *** LX32 POWER ON DIAGNOSTICS TEST COMPLETED ***",cr,lf,cr,lf,0
	.double	PROG_END
