home *** CD-ROM | disk | FTP | other *** search
- /* FFFFFFF A CCCCCC TTTTTTTTTTT CCCCCC
- * F A A C T C
- * FFFFF A A C T C
- * F A AAA A C T C
- * F A A C T .. C
- * F A A CCCCCC T .. CCCCCC
- *
- * FACT.C -- FIFO Asynchronous Communication Test Program for
- * NS16550 and NS16552 UARTs
- *
- * Greg DeJager Ver 1.0 1/31/89
- *
- * Adapted from LBT.C -- LoopBack Test Rev 1.1
- * Developed By: Brian A. Berg
- * Berg Software Design
- * October 1988
- *
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <conio.h>
- #include <dos.h>
- #include "stdhdr.h"
- #include "serio.h"
-
- /* define some macros for use herein */
- /* program test name for user prompt and help screen */
- #define TESTNAME "NS16550/NS16552 FIFO Asynchronous Communications Test (FACT)"
- /* clear the RBR, LSR and IIR registers (used at start and before exit) */
- #define CLEAR_REGS() ((void)rdRBR(), (void)rdRBR(), \
- (void)rdLSR(), (void)rdIIR(), (void)wrMCR(0), \
- (void)wrFCR(CLR_FIFO))
-
- /* GET ctrl-break/ctrl-c checking flag status via "INT 21H" */
- #define GETBRK() (regs.h.ah = 0x33, regs.h.al = 0, \
- intdos(®s, ®s), regs.h.dl)
- /* SET ctrl-break/ctrl-c checking flag to argument via "INT 21H" */
- #define SETBRK(brk) (regs.h.ah = 0x33, regs.h.al = 1, \
- regs.h.dl = (brk), intdos(®s, ®s))
-
- /* COMx-dependent parameters */
- UINT comvnum[COM_CNT] = {0x0C, 0x0B, 0x0B}; /* int. vector nos. for COMx */
- UINT uartbadd[COM_CNT] = {0x3F8, 0x2F8, 0x3220}; /* UART base adds. for COMx */
- UINT picmsk[COM_CNT] = {0xEF, 0xF7, 0xF7}; /* PIC masks for COMx: IRQ4,3 */
-
- /* declare parameters and default values; override via invocation line args. */
- /* argument 1: COM number */
- int com = COM_DEF;
- UINT ivnum; /* int. vector number (set as comvnum[com-1]) */
- UINT ubase; /* UART base address (set as uartbadd[com-1]) */
- /* argument 2: baud rate divisor */
- int baudiv = BAUDIV_DEF;
-
- UCHAR bytwr = 0; /* write byte counter (goes from 0 to 255) */
- UCHAR bytrd = 0; /* read byte counter (goes from 0 to 255) */
-
- UCHAR iir, lsr; /* storage for IIR and LSR */
- UCHAR bytin; /* input byte storage */
-
- UINT errflag = FALSE; /* error indication and ID */
-
- /* storage for original environment parameters */
- void far *savect; /* interrupt vector */
- UCHAR savbrk; /* ctrl-break flag */
- UINT savmsk; /* PIC mask */
- UCHAR savier; /* IER register */
- UCHAR savlcr; /* LCR register */
- UCHAR savmcr; /* MCR register */
- UCHAR savdll; /* DLL register */
- UCHAR savdlm; /* DLM register */
-
- CNVTR cnvtr; /* handy union for data type conversions */
- union REGS regs; /* 16- and 8-bit registers for intdos() */
- int finit = FALSE; /* boolean for program termination */
-
- /* globals which control the tick mark on the screen */
- int tick = FALSE; /* boolean for display of "tick" on CRT */
- int tick_ff = 0; /* tick flip-flop (either 0 or 1) */
- int bytick = 0; /* helps determine when to set tick boolean */
- UCHAR *tickstr[] = {"\b*", "\b$"}; /* "tick" mark strings */
-
- /* Routines contained herein: */
- 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 to console */
- void usage(void); /* display usage info and exit */
-
- /*
- * main(): main program
- */
-
- void main(argc, argv)
- int argc;
- char **argv;
- {
- /* process invocation args., and set up int vector no. and UART base add */
- procarg(argc, argv); /* get com# and baudrate from argument string */
- CLEAR_REGS(); /* clear RBR, LSR, IIR, MCR, and FIFOs */
- savepar(); /* save our environment parameters */
-
- /* set baud rate */
- wrLCR(0x80); /* set DLAB */
- cnvtr.intval[0] = baudiv;
- outp(DLL, cnvtr.chrval[0]);
- outp(DLM, cnvtr.chrval[1]);
- wrLCR(0x0B); /* 8 data, 1 stop, odd parity */
-
- printf("\n\n %s\n\n",TESTNAME); /*startup message*/
-
- /* wait loop to insure other machine has cleared its registers */
- printf("\nHit a key when other program has been started.\n\n");
- while( !(kbhit() && getch()) );
-
- /* set up registers for our environment */
- wrFCR(CLR_FIFO); /* clear transmitter and receiver FIFOs */
- wrFCR(FIFO_EN); /* enable FIFOs, set Rx trigger at 14 bytes */
- if ( (rdIIR() & 0xc0) != 0xc0) /* ensure FIFOs present */
- {
- printf("\nFatal Error. FIFOs not present\n");
- errflag = ENDPROG;
- }
- wrMCR(OUT2); /* enable PIC interrupt (OUT2) */
- wrIER(IER_VAL1); /* Enable LSI and RDAI */
- wrMCR(0x0a); /* Assert RTS (and OUT2) */
-
- printf("Waiting for first 'Request To Send' from other machine...\n\n");
- while (!(rdMSR() & CTS)); /* wait for other machine to assert RTS */
-
- printf("\n\nHit non-control key to stop: ");
-
- /* Enable Tx interupts; loop until int. handler finished or any key struck */
- wrIER(IER_VAL2);
- while (!errflag)
- {
- if (kbhit() && getch())
- errflag = ENDPROG;
- if (tick) /* display tick mark */
- {
- /* display the tick mark */
- printf("%s",tickstr[tick_ff]);
- tick_ff = 1 - tick_ff; /* update tick flip-flop */
- tick = FALSE;
- }
- }
- wrIER(0); /* disable UART interrupts */
- while ( !(rdLSR() & TEMT) ); /* wait for Tx FIFO to clear */
- CLEAR_REGS(); /* clear RBR, LSR, MCR and IIR registers before we exit */
-
- /* Output error message represented by 'errflag' variable */
- switch (errflag)
- {
- case ENDPROG: /* keyboard hit or fatal error */
- break;
-
- case FALSEINT: /* IIR shows no interrupt active */
- printf("\nFalse interrupt. No UART interrupt active.\n");
- break;
-
- case STATUSERR: /* Line Status interrupt generated */
- printf("\nLine Status interrupt. LSR = %x\n",lsr);
- printf("Byte causing LSI = %x\n",bytin);
- break;
-
- case MISMATCH: /* Data received did not match data expected */
- printf("\nData mismatch\n");
- printf("Byte expected = %x\n",--bytrd);
- printf("Byte received = %x\n",bytin);
- break;
-
- case RX_ERROR: /* RDAI generated but DR was not set */
- printf("\nError: RDAI but no DR indication\n");
- break;
-
- case TX_ERROR: /* THREI generated but THRE was not set */
- printf("\nError: THREI but no THRE indication\n");
- break;
-
- case IIR_ERROR: /* Invalid IIR */
- printf("\nIIR invalid\n");
- break;
-
- case TIMEOUT: /* Character Timeout Interrupt */
- printf("\nCharacter Timeout.\n");
- break;
-
- case TIMEOUT_ERR: /* False Character Timeout Interrupt */
- printf("\nError: False Character Timeout Interrupt.\n");
- break;
-
- default:
- break;
- } /* end of switch */
-
- rstrpar(); /* restore our environment parameters */
-
- printf("\n\n\nEnd of program; Environment parameters restored.\n");
-
- } /* end of main() */
-
- /*
- * serint(): serial port interrupt handler
- */
-
- void interrupt far serint()
- {
- int bytecnt=0;
-
- /* if errflag has been set, ignore the interrupt */
- if (errflag)
- {
- wrIER(0);
- outp(PICTRL, EOI); /* send EOI to 8259A PIC */
- return;
- }
-
- /* here's the code to handle each of the various interrupt types */
- switch (iir = rdIIR())
- {
- case F_NOIP: /* NO Interrupt Pending */
- errflag = FALSEINT;
- break;
-
- case F_RLST: /* Receiver Line STatus interrupt */
- lsr = rdLSR();
- bytin = rdRBR(); /* read byte with error */
- errflag = STATUSERR;
- break;
-
- case F_RDAV: /* Received Data AVailable */
- wrMCR(OUT2); /* clear RTS */
- lsr = rdLSR();
- /* read bytes from FIFO and compare them with expected values */
- while (rdLSR() & DR)
- {
- bytin = rdRBR();
- if (bytin != bytrd++)
- {
- errflag = MISMATCH;
- break; /* error, stop reading FIFO */
- }
- else
- /* display "tick" after reading 2560 bytes */
- if (!bytrd && ++bytick == 10)
- {
- bytick = 0;
- tick = TRUE; /* turn on "tick" boolean */
- }
- }
- if (!errflag)
- wrMCR(0x0a); /* reassert RTS */
- break;
-
- case F_IIR_THRE: /* Transmitter Holding Register Empty */
- lsr = rdLSR();
- bytecnt = 0;
- if (lsr & LSR_THRE)
- {
- while (rdMSR() & CTS) /* while CTS, fill FIFO */
- if (bytecnt++ <= 15)
- wrTHR(bytwr++);
- else
- break;
- }
- else
- errflag = TX_ERROR; /* THREI without THRE set */
- break;
-
- case F_CHR_TIMEOUT: /* no characters received for 4 character times */
- errflag = TIMEOUT;
- if (rdLSR() & DR)
- while (rdLSR() & DR) /* clear all of FIFO */
- {
- bytin = rdRBR();
- if (bytin != bytrd++)
- {
- errflag = MISMATCH;
- break; /* error, stop reading FIFO */
- }
- }
- else
- errflag = TIMEOUT_ERR; /* false timeout interrupt */
- break;
-
- default: /* IIR default case: FATAL ERROR */
- errflag = IIR_ERROR;
- break;
- }
-
- /* Toggle INTR line of UART to create edge if multiple ints pending */
- wrIER(0);
- if (!errflag)
- wrIER(IER_VAL2);
-
- outp(PICTRL, EOI); /* send EOI to 8259A PIC */
-
- } /* end of serint() */
-
-
- /*
- * procarg(): process invocation arguments
- */
-
- void procarg(argc, argv)
- int argc;
- char **argv;
- {
- int badarg = TRUE; /* boolean: improper invocation arg. */
-
- switch (argc)
- {
- case 3: /* baud rate divisor */
- baudiv = atoi(argv[2]);
- if (!MN_MX(baudiv, BAUDIV_MIN, BAUDIV_MAX))
- break;
- case 2: /* COM number */
- com = atoi(argv[1]);
- if (!MN_MX(com, COM_MIN, COM_MAX))
- break;
- case 1: /* no arguments => go with defaults */
- badarg = FALSE;
- break;
- default: /* illegal argument count */
- break;
- }
-
- if (badarg)
- usage(); /* never returns */
-
- /* set up interrupt vector number and UART base address */
- ivnum = comvnum[com-1];
- ubase = uartbadd[com-1];
-
- /* verify existence of COM port */
- savlcr = (UCHAR)inp(LCR); /* save original LCR */
- wrLCR(0x33); /* write test value to LCR */
- if (inp(LCR) != 0x33)
- {
- printf("FATAL ERROR: COM%d not present\n", com);
- exit(1);
- }
-
- } /* end of procarg() */
-
- /*
- * savepar(): save our environment parameters
- */
-
- void savepar()
- {
- /* handle interrupt vector: save original and plug in our own address */
- savect = _dos_getvect(ivnum); /* save original int. vector */
- _dos_setvect(ivnum, serint);
-
- /* handle ctrl-break/ctrl-c status: save original flag and disable it */
- savbrk = GETBRK();
- SETBRK(0);
-
- /* handle PIC mask: save original mask and allow COMx to interrupt */
- savmsk = inp(PICMSK);
- outp(PICMSK, inp(PICMSK) & picmsk[com-1]);
-
- /* save registers */
- /* NOTE: LCR already saved in procarg() */
- wrLCR(0x80); /* set DLAB */
- savdll = (UCHAR)inp(DLL); /* save baud */
- savdlm = (UCHAR)inp(DLM); /* rate */
- savier = (UCHAR)inp(IER); /* save original IER */
-
- } /* end of savepar() */
-
- /*****************************************************************************/
-
- /*
- * rstrpar(): restore our environment parameters
- */
-
- void rstrpar()
- {
- /* restore registers */
- outp(LCR, 0x80); /* set DLAB */
- outp(DLL, savdll); /* restore baud */
- outp(DLM, savdlm); /* rate */
- outp(LCR, 0); /* clear DLAB */
- outp(IER, savier);
- outp(LCR, savlcr);
-
- /* restore original address to interrupt vector */
- _dos_setvect(ivnum, savect);
-
- /* restore original ctrl-break/ctrl-c checking flag */
- SETBRK(savbrk);
-
- /* restore original PIC mask */
- outp(PICMSK, savmsk);
-
- } /* end of rstrpar() */
-
-
- /*****************************************************************************/
-
- /*
- * usage(): display program usage information and terminate (never return)
- */
-
- void usage()
- {
- printf("\n** HELP Screen for %s **\n\n", TESTNAME);
- printf("USAGE: fact [<COM-number> [<baudrate-divisor>]]\n");
- printf(" arg1 arg2 \n");
- printf(" ('fact' may be followed by no args, arg1, or arg1+2)\n\n");
- printf(" ARGUMENT MINIMUM VALUE MAXIMUM VALUE DEFAULT VALUE \n");
- printf("============ =============== =============== ==============\n");
- printf(" COM-number %d (for COM%d) %d (for COM%d) %d \n",
- COM_MIN, COM_MIN, COM_MAX, COM_MAX, COM_DEF);
- printf(" (serial line %d) (serial line %d) (COM%d)\n\n",
- COM_MIN-1, COM_MAX-1, COM_DEF);
- printf(" baudrate- %d (56000 baud) %d (%ld baud) %4d \n",
- BAUDIV_MIN, BAUDIV_MAX, BAUDRATE(BAUDIV_MAX), BAUDIV_DEF);
- printf(" divisor (based on 1.8432 MHz crystal) (%ld baud) \n",
- BAUDRATE(BAUDIV_DEF));
- printf(" * Sample baudrate divisors: for baud= 1200, use 96 * \n");
- printf(" * 2400 48 * \n");
- printf(" * 4800 24 * \n");
- printf(" * 9600 12 * \n");
- printf(" * 19200 6 * \n");
- exit(1);
-
- } /* end of usage() */
-
- /* end of act.c */