Category : Tutorials + Patches
Archive   : NAT_UART.ZIP
Filename : ACTB.DOC
=========================================================================
National Semiconductor Corporation
Greg DeJager February 8, 1989
Adapted from LBT.C -- Loopback Test Rev 1.1
Developed by: Brian A. Berg
BERG SOFTWARE DESIGN
Summary of Files
--------------------------
ACTB.C C source code: main program, subroutines and interrupt handler
SERIO.H header file containing UART definitions for C code use
STDHDR.H header file containing "standard" definitions for C code use
ACTB.EXE executable file
Intro, Hardware Setup and Program Operation
===========================================
This test was developed to run on all IBM PC or PC compatible architectures.
System requirements include two separate machines at least one being a PC
with an INS8250 or INS8250N-B located at COM1, 2 or 3. The other machine may
be an AT or PS/2 with an NS16450/16550 driving its COM port. The COM ports on
the machines must be connected by the following RS-232 DTE to DTE interface:
Tx----------------------------Rx
Rx----------------------------Tx
RTS--------------------------CTS
CTS--------------------------RTS
GND--------------------------GND
The executable software to be run on the PC is titled ACTB.EXE. If the other
machine is not a PC and contains a 16450/550, it must run the program ACT.EXE
(ACT.EXE is a similar communication program which tests 16450 UARTs on AT machines).
To test the 8250/N-B, the above hardware must be set up and after entering the
proper directories, the user must type ACTB
or ACT on the other machine. The programs will prompt the user to start both
machines and then hit a key to begin the test. This procedure is necessary to
ensure that all modem control outputs are deasserted before program start-up
so that a machine won't begin transmitting before the other is ready to receive.
Full duplex transmission begins after a key is hit on both machines and each
machine has exchanged initial RTS signals. Proper test operation is indicated
by a '|' and '_' character being printed to the screen every 2560 characters
received.
All operations are interrupt driven. UART line status, receiver and transmitter
interrupts are enabled. When not servicing interrupts, the CPU sits in a
loop checking for a keyboard hit (means for user to stop test) and for errors
produced within the interrupt service routines. A transmitter interrupt is
generated whenever the transmit holding register empties. The CPU services
the interrupt by writing the next character to the holding register ONLY if CTS
is asserted. If CTS is not asserted a timer variable is incremented and compared
to a large number (50). If 50 transmit interrupts occur in succession
without CTS being asserted, the program assumes that the other machine has
stopped and the program is ended.
A receiver interrupt is generated when the receiver buffer gets a new character.
The CPU immediately deasserts RTS to stop any further transmission from the
other machine. It then reads the byte out of the receiver buffer comparing
it to an expected value. Data transmitted and received sequences between 00
and FFH. If a mismatch occurs, the expected and received data are displayed
and the program stops. A line status interrupt results from an Overrun, Framing
or Parity error or Break condition. Upon receiving the status interrupt, the
program prints the corrupted data and the line status register value and exits
the program. Inconsistencies between the Interrupt ID and Line Status Registers
also cause error messages to be printed and the program to stop.
There is a restriction associated with program operation. The maximum baudrate
that can be selected is 56k; however, this baudrate is limited by the processor
speed and the host system. The COMPAQ PC compatible tested operated at a
maximum baud rate of 1800. At higher baud rates operation is system dependent
due to the overhead involved with processing the interrupts.
The default com port is COM1 and default baudrate is 1200. However, the user
can control these options by specifying arguments on the command line. Arguments
must be separated by spaces. The first argument is a selection of COM1, COM2
or COM3 (eg. ACTB 2 selects COM2). The second argument is a decimal
divisor from 2 through 2304 which specifies a baudrate from 56k to 50 (the
default is 96, 1200 baud). The baudrate arguement must be proceeded on the
command line by the COM port designation. Again, specifying no arguments
causes a default of COM1, 1200 baud to be used. An example command line which
causes the program to use COM1 and 300 baud is: ACTB 1 384. A help screen is
printed if any improper argument is used or if ACTB H is entered.
Programmer's Guide for ACTB.C -- Rev 1.0
========================================
Help Screen for ACTB
-------------------
NOTE: The following is displayed if any incorrect arguments are supplied
to the ACTB (this includes entering "actb help")
HELP Screen for INS8250/INS8250N-B Asynchronous Communications Test (ACTB)
USAGE: actb [
arg1 arg2
('actb' may be followed by no args, arg1 or arg1+2)
ARGUMENT MINIMUM VALUE MAXIMUM VALUE DEFAULT VALUE
============ =============== =============== ==============
COM-number 1 (for COM1) 3 (for COM3) 1
(serial line 0) (serial line 2) (COM1)
baudrate- 2 (56000 baud) 2304 (50 baud) 96
divisor (based on 1.8432 MHz crystal) (1200 baud)
* Sample baudrate divisors: for baud= 300, use 384 *
* 600 192 *
* 1200 96 *
* 2400 48 *
* 4800 24 *
Page 2 of 4
Programmer's Guide for ACTB
===========================
Summary of ACTB.C Subroutines
-----------------------------
NOTE: As the code itself is heavily commented, it should be inspected if
further clarification is necessary.
The following subroutines are contained in this file:
void main(int, char **); /* main program */
void interrupt far serint(void); /* serial interrupt handler */
void procarg(int, char **); /* process invocation arguments */
void savepar(void); /* save our environment parameters */
void rstrpar(void); /* restore our environment parameters */
void dspstr(UCHAR *); /* display a string on the console */
void usage(void); /* display usage info and exit */
1. main(): main program
The main program initializes the system as follows:
processes invocation arguments by calling procarg(),
uses the CLEAR_REGS() macro to clear the RBR, LSR, IIR and MCR registers,
saves environment parameters by calling savepar(),
sets the requested (or default) baud rate and LCR register,
prints name of test to screen
prints "Hit a key when other program has been started" and waits for keyboard hit,
enables IRQ by setting OUT2,
enables UART receiver and line status interrupts,
asserts RTS and after receiving CTS (RTS from other machine),
it prompts the operator to "Hit any non-control key to stop" the program.
It then starts full duplex communication by enabling transmitter interrupts
and then loops until either the global variable "errflag" changes from
FALSE (0) to TRUE (a specific error code), or for the operator strikes any
non-control keyboard key. The errflag variable is set by the interrupt
handler as described for serint().
While this loop is active, the global variable "tick" is inspected. If it is
non-zero, either "|" or "_" is displayed at one place on the screen in order
to inform the operator that the program is active. This is facilitated by
use of a flip-flop variable to index one of two ASCII strings. The character
is changed every 2560 bytes received.
After exiting this loop, the program waits for the TEMT bit in the LSR to be
set to indicate an empty transmitter. The CLEAR_REGS() macro is again
invoked. An 'End of program' message is printed and, if the interrupt
handler found an error, an error message corresponding to the code in the
variable errflag is output.
Page 3 of 4
Programmer's Guide for the ACTB
===============================
Summary of ACTB.C Subroutines (continued)
----------------------------------------
2. serint(): serial port interrupt handler
The interrupt handler first checks if the global "errflag" is TRUE. If so,
the interrupt is ignored by disabling UART interrupts and by sending the
PIC an EOI and exiting.
Then the IIR is read and each interrupt type is handled:
NO Interrupt Pending:
errflag <- False Interrupt error message code
Receiver Line STatus interrupt:
read and store LSR
read and store RBR
errflag <- Status error message code
Received Data AVailable (RDAV):
clear RTS
if Data Ready bit is set
read byte and compare to expected value else errflag <-
Receiver Error code
if mismatch is found, errflag <- Mismatch Error code
else increment byte counter variable and set 'tick if
2560 characters were received
if no errors were found RTS is reasserted
Transmitter Holding Register Empty:
the LSR is read
verify THRE bit set, errflag <- Tx Error message code if not
if CTS is asserted
write next byte to transmitter and clear timeout counter
else
increment timeout counter and if it is > 50 (arbitrary
large number), errflag <- End of Program code (this means
that other machine has stopped requesting more data
(ie. CTS = 0) )
Any other value for the IIR:
errflag <- IIR Error code
if THRE is asserted (ie transmit interrupt pending)
transmitter interrupt is disabled and immediately reenabled (This fixes
full-duplex bug involving missing a transmitter interrupt)
An EOI is sent to the PIC.
(NOTE: an IRET instruction is automatically generated to exit this int. handler)
Page 4 of 4
Programmer's Guide for ACTB
===========================
Summary of ACTB.C Subroutines (concluded)
----------------------------------------
3. procarg(): process invocation arguments
The invocation arguments as defined in the help screen are validated
by this routine. The help screen itself is displayed by calling
usage() if any illegal arguments are found.
Based on the COM argument (or its default), the interrupt vector number
and UART base address are set up for global use. The existence of
the requested COM port is verified; its non-existence causes program
termination.
4. savepar(): save our environment parameters
This routine saves the original interrupt vector, ctrl-break/ctrl-c
status and PIC mask, and then sets these up as required for FACT use.
It also saves some of the UART register values.
5. rstrpar(): restore our environment parameters
This routine is the complement for savepar(): it restores the saved
registers, interrupt vector, ctrl-break/ctrl-c status and PIC mask.
6. dspstr(): display a string of characters on the console
This routine uses the INT 10H software interrupt to display a string a
character at a time.
7. usage(): display program usage information and terminate (never return)
This routine displays the help screen and terminates the program.
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/