[Back to COMM SWAG index] [Back to Main SWAG index] [Original]
{-------------------------------------------------------------------------
! !
! UARD.PAS : Uart Detection Program Ver 1.0 !
! !
! Created : 09-23-93 Changed: 09-23-93 !
! !
! Converted To Turbo Pascal 6.0 By: David D. Cruger !
! !
! Original Program By: National Semiconductor Corporation !
! NS1655.ZIP Microcomputer Systems Division !
! Microcontroller Applications Group !
! Written By: Louis Shay / 01/11/89 !
! Originaly Written in some form of 'C'. !
! This program only does the 'detection'. !
! The original program ran some tests on !
! the Uarts. !
! !
! SAVE/RESTORE Uart Registers Routines from Form Message #195739 !
! by Michael Day (TeamB) !
! !
! *NOTE* This program is just an example of how to detect Uarts and !
! is not intended to be a stand alone program. I here by !
! release this program to the public domain. Use at your own !
! risk. !
! !
! 0: No Uart at Port Address !
! 1: INS8250, INS8250-B !
! 2: INS8250A, INS82C50A, NS16450, NS16C450 !
! 3: NS16550A !
! 4: NS16C552 !
! !
!------------------------------------------------------------------------}
Program UartD;
{
A = Align Data
B = Boolean Short
D = Debug On
E = Emulate 80287
F = Far Calls
G = Generate 286 Code
L = Local Symbol Information
N = Numeric Processing Switch
O = Overlay
R = Range Checking On
S = Stack-Overflow
V = Var-String Checking
}
{$a+,b-,d-,e-,f-,g-,l-,n-,o-,r-,s-,v-} {}
{$M 2500,0,0}
Uses Dos;
Type Uart_Registers=Array[0..9] OF Byte; { Uart Registers }
Var URegs: Uart_Registers; { Uart Register Array }
PA : Word; { Port Address Com1=$3F8 Com2=$2F8.. }
RBR,THR,IER,IIR,FCR,LCR,MCR,LSR,MSR,SCR,DLL,DLM,AFR: Word;
{-------- Save Uart Registers --------}
Procedure Save_Uart_Registers(BaseAdd: Word; Var URegs: Uart_Registers);
Var I: Byte;
Begin
ASM CLI; END;
For I:=1 to 6 Do URegs[I]:=Port[BaseAdd+I];
Port[BaseAdd+3]:=Port[BaseAdd+3] or $80;
URegs[7]:=Port[BaseAdd+0];
URegs[8]:=Port[BaseAdd+1];
Port[BaseAdd+3]:=Port[BaseAdd+3] and $7F;
ASM STI; END;
End; { End Procedure }
{------ Restore Uart Registers --------}
Procedure Restore_Uart_Registers(BaseAdd: Word; URegs: Uart_Registers);
Var I: Byte;
Begin
ASM CLI; END;
Port[BaseAdd+3]:=Port[BaseAdd+3] or $80;
Port[BaseAdd+0]:=URegs[7];
Port[BaseAdd+1]:=URegs[8];
Port[BaseAdd+3]:=Port[BaseAdd+3] and $7F;
For I:=1 to 6 Do Port[BaseAdd+I]:=URegs[I];
ASM STI; END;
End; { End Procedure }
Procedure Return_Code(C: Byte);
Begin
Case C of
0:Writeln('No Uart at Port Address');
1:Writeln('INS8250, INS8250-B');
2:Writeln('INS8250A, INS82C50A, NS16450, NS16C450');
3:Writeln('NS16550A');
4:Writeln('NS16C552');
End;
Restore_Uart_Registers(PA,URegs);
Halt(C); { Halt with Errorlevel of Uart }
End; { End Procedure }
Procedure Set_Uart_Register_Values(PA: Word);
Begin
RBR:=PA+0; { Receive Buffer Registers (R ) (DLAB=0) }
THR:=PA+0; { Transmitter Holding Register ( W) (DLAB=0) }
IER:=PA+1; { Interrupt Enable Register (R/W) (DLAB=0) }
IIR:=PA+2; { Interrupt Ident. Register (R ) }
FCR:=PA+2; { FIFO Control Register ( W) }
LCR:=PA+3; { Line Control Register (R/W) }
MCR:=PA+4; { MODEM Control Register (R/W) }
LSR:=PA+5; { Line Status Register (R ) }
MSR:=PA+6; { MODEM Status Register (R/W) }
SCR:=PA+7; { Scratch Register (R/W) }
DLL:=PA+0; { Divisor Latch (LSB) (R/W) (DLAB=1) }
DLM:=PA+1; { Divisor Latch (MSB) (R/W) (DLAB=1) }
AFR:=PA+2; { Alternate Function Register (R/W) }
End; { End Procedure }
Begin { Main Section of Program }
PA:=$3F8; { Com1/ This can be changed to any port address you want }
Write('Com1: $3F8 : Uart:=');
Save_Uart_Registers(PA,URegs); { Saves State of Current Uart Registers }
Set_Uart_Register_Values(PA); { Return_Code() Restores Uart Registers }
Port[LCR]:=$AA; { Test LCR Registers }
If $AA<>Port[LCR] Then Return_Code(0);
Port[DLM]:=$55; { Test DLM Present 8-bits }
If $55<>Port[DLM] Then Return_Code(0);
Port[LCR]:=$55; { LCR/ DLAB=0 }
If $55<>Port[LCR] Then Return_Code(0);
Port[IER]:=$55; { Test IER Present 4-bits }
If $05<>Port[IER] Then Return_Code(0);
Port[FCR]:=$0; { FIFO's Off, If Present }
Port[IER]:=$0; { Interrupts Off, IIR Should be 01 }
If $1<>Port[IIR] Then Return_Code(0);
{----- Test Modem Control Register Address. Should be 5-bits Wide -----}
Port[MCR]:=$F5; { 8-bit Write }
If $15<>Port[MCR] Then Return_Code(0);
{------ Test MCR/MSR Loopback Functions ------}
Port[MCR]:=$10; { Set Loop Mode }
Port[MSR]:=$0; { Clear out Delta Bits }
If ($F0 and Port[MSR])<>0 Then Return_Code(0); { Check State Bits }
Port[MCR]:=$1F; { Toggle Modem Control Lines }
If ($F0 and Port[MSR])<>$F0 Then Return_Code(0); { Check State Bits }
Port[MCR]:=$03; { Exit Loop Mode, DTR, RTS Active }
{---- Port Id Successful at this point. determine port type ----}
Port[SCR]:=$55; { Is There a Scratch Register? }
If $55<>Port[SCR] Then Return_Code(1); { No SCR, Type = INS8250 }
Port[FCR]:=$CF; { Enable FIFO's, If Present }
If ($C0 and Port[IIR])<>$C0 Then Return_Code(2); { Check FIFO ID bits }
Port[FCR]:=$0; { Turn Off FIFO's }
Port[LCR]:=$80; { Set DLAB }
Port[AFR]:=$07; { Write to AFR }
If $07<>Port[AFR] Then { Read AFR }
Begin
Port[LCR]:=$0; { Reset DLAB }
Return_Code(3); { If Not Type=NS16550A }
End;
Port[AFR]:=$0; { Clear AFR }
Port[LCR]:=$0; { Reset DLAB }
Return_Code(4);
End.
[Back to COMM SWAG index] [Back to Main SWAG index] [Original]