//------------------------------------------------------------------
//	uartecho.s                       
//
//	This program is for testing a "null-modem" cable-connection
//	between a pair of adjacent PCs in our classroom.  First you
//	start this program running on one PC, and then you launch a
//	modified version of our 'testuart.s' application on a PC at
//	the other end of the cable.  The modification just consists 
//	of putting a zero-value into the MODEM_CONTROL register, to
//	disable the UART's 'loopback' mode.  You can terminate this
//	program by typing <CONTROL>-C.   
//
//		to assemble:  $ as uartecho.s -o uartecho.o
//		and to link:  $ ld uartecho.o -o uartecho
//
//	(NOTE: Remember to execute the 'iopl3' command beforehand!)
//
//	programmer: ALLAN CRUSE 
//	written on: 04 APR 2007 
//------------------------------------------------------------------

	# manifest constants 
	.equ	sys_WRITE, 4
	.equ	STDOUT, 1
	.equ	UART, 0x03F8
	.equ	LINE_CONTROL, UART+3
	.equ	DIVISOR_LATCH, UART+0
	.equ	MODEM_CONTROL, UART+4
	.equ	LINE_STATUS, UART+5
	.equ	TX_DATA, UART+0
	.equ	RX_DATA, UART+0


	.section	.data 
msg:	.ascii	"\nHit <CONTROL>-C to termine this program\n\n"
len:	.int	. - msg
inch:	.byte	0


	.section	.text 
_start:	# configure the UART's operational parameters
	mov	$LINE_CONTROL, %dx
	mov	$0x80, %al		# access Divisor-Latch 
	out	%al, %dx

	mov	$DIVISOR_LATCH, %dx
	mov	$0x0001, %ax		# set baudrate: 115200
	out	%ax, %dx

	mov	$LINE_CONTROL, %dx
	mov	$0x03, %al		# set data-format: 8-N-1
	out	%al, %dx

	mov	$MODEM_CONTROL, %dx	
	mov	$0x00, %al		# disable 'loopback' mode
	out	%al, %dx

	# tell the user how to terminate this application
	mov	$sys_WRITE, %eax
	mov	$STDOUT, %ebx
	lea	msg, %ecx
	mov	len, %edx
	int	$0x80

	# an infinite loop that sends back every byte it receives
again:
	# wait until the UART's has received a new byte of data
	mov	$LINE_STATUS, %dx
spin2:	in	%dx, %al
	test	$0x01, %al
	jz	spin2	

	# read the new character from the UART's RX_DATA register
	mov	$RX_DATA, %dx
	in	%dx, %al
	mov	%al, inch

	# show the received character on the screen
	mov	$sys_WRITE, %eax
	mov	$STDOUT, %ebx
	lea	inch, %ecx
	mov	$1, %edx
	int	$0x80

	# wait until the UART's Transmit Holding Register is empty
	mov	$LINE_STATUS, %dx
spin1:	in	%dx, %al
	test	$0x20, %al
	jz	spin1	

	# transmit the received character back to the sender 
	mov	inch, %al
	mov	$TX_DATA, %dx
	out	%al, %dx
	jmp	again

	.global	_start 
	.end