home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1991
/
07
/
struc_pr.asc
< prev
next >
Wrap
Text File
|
1991-06-11
|
5KB
|
107 lines
_STRUCTURED PROGRAMMING COLUMN_
by Jeff Duntemann
[LISTING ONE]
PROGRAM LoopTest; { From "Structured Programming" DDJ 7/91 }
CONST
UART : ARRAY[0..4] OF STRING =
(' faulty','n 8250',' 16450',' 16550',' 16550A');
VAR
PortNum : Byte;
{-----------------------------------------------------------------}
{ FUNCTION DetectComPort by Jeff Duntemann }
{ This function returns a Boolean value indicating whether or not }
{ a National Semiconductor UART (one of 8250B, 16450, 16550, or }
{ 16550A) is present at the COM port passed in the PortNumber }
{ parameter. Don't run this function on serial ports that may be }
{ operating in some sort of background mode; it will probably }
{ disrupt any communication stream currently in progress. }
{-----------------------------------------------------------------}
FUNCTION DetectComPort(PortNumber : Integer) : Boolean;
CONST
LOOPBIT = $10;
PortBases : ARRAY[1..4] OF Integer = ($03F8,$02F8,$03E8,$02E8);
{ COM1 COM2 COM3 COM4 }
VAR
Holder,HoldMCR,HoldMSR : Byte;
MCRPort,MSRPort,THRPort,RBRPort : Integer;
BEGIN
{ Calculate port numbers for the port being looked for: }
RBRPort := PortBases[PortNumber]; { RBR is at the base address }
THRPort := RBRPort; { RBR and THR have same I/O address }
MCRPort := RBRPort + 4; { MCR is at offset 4 }
MSRPort := RBRPort + 6; { MSR is at offset 6 }
{ Put the UART into loopback test mode: }
HoldMCR := Port[MCRPort]; { Save existing value of MCR }
Port[MCRPort] := HoldMCR OR LOOPBIT; { Turn on loopback test mode }
HoldMSR := Port[MSRPort];
Port[MCRPort] := $0A OR LOOPBIT; { Put pattern to low 4 bits of MCR }
{ without disabling loopback mode }
Holder := Port[MSRPort] AND $F0; { Read pattern from hi 4 bits of MSR }
IF Holder = $90 THEN { The $A pattern is changed to $9 inside UART }
DetectComPort := True
ELSE
DetectComPort := False;
{ Restore previous contents of MSR: }
Port[MSRPort] := HoldMSR;
{ Take the UART out of loopback mode & restore old state of MCR: }
Port[MCRPort] := HoldMCR AND (NOT LOOPBIT);
END;
{-----------------------------------------------------------------}
{ FUNCTION DetectUARTType by Jeff Duntemann }
{ This function returns a numeric code indicating which UART chip }
{ is present at the selected PortNumber (1-4.) The UART codes }
{ returned are as follows: }
{ 0 : Error; bad UART or no UART at COMn, where n=PortNumber }
{ 1 : 8250; generally (but not always!) present in PC or XT }
{ 2 : 16450; generally present in AT-class machines }
{ 3 : 16550; in PS/2 mod 50/60/early 80. FIFOs don't work! }
{ 4 : 16550A; in later PS/2's. FIFOs fully operative. }
{ NOTE: This routine assumes a UART is "out there" at the port # }
{ specified. Run DetectComPort first to make sure port is there! }
{-----------------------------------------------------------------}
FUNCTION DetectUARTType(PortNumber : Integer) : Integer;
CONST
PortBases : ARRAY[1..4] OF Integer = ($03F8,$02F8,$03E8,$02E8);
{ COM1 COM2 COM3 COM4 }
VAR
ScratchPort,IIRPort,FCRPort : Integer;
Holder : Byte;
BEGIN
{ The scratch register is at offset 7 from the comm port base: }
ScratchPort := PortBases[PortNumber] + 7;
FCRPort := PortBases[PortNumber] + 2;
IIRPort := FCRPort; { IIR and FCR are at same offset }
Port[ScratchPort] := $AA; { Write pattern to the scratch register }
IF Port[ScratchPort] <> $AA THEN { Attempt to read it back... }
DetectUARTType := 1 { A UART without a scratch register is an 8250 }
ELSE
BEGIN { Now we have to test among the 16450, 16550, and 16550A }
Port[FCRPort] := $01; { Setting FCR bit 0 on 16550 enables FIFOs }
Holder := Port[IIRPort] AND $C0; { Read back to FIFO status bits }
CASE Holder OF
$C0 : DetectUARTType := 4; { Bits 6 & 7 both set = 16550A }
$80 : DetectUARTType := 3; { Bit 7 set & bit 6 cleared = 16550 }
$00 : DetectUARTType := 2; { Neither bit set = 16450 }
ELSE DetectUARTType := 0; { Error condition }
END; {CASE}
Port[FCRPort] := $00; { Don't leave the FIFOs enabled! }
END;
END;
BEGIN
FOR PortNum := 1 TO 4 DO
BEGIN
IF DetectComPort(PortNum) THEN
BEGIN
Write ('Port COM',PortNum,' is present,');
Writeln(' using a',UART[DetectUARTType(PortNum)],' UART.');
END
ELSE
Writeln('Port COM',Portnum,' is not present.');
END;
END.