{------------------------------------------------------------------------- ! ! ! 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.