home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 07 / struc_pr.asc < prev    next >
Text File  |  1991-06-11  |  5KB  |  107 lines

  1. _STRUCTURED PROGRAMMING COLUMN_
  2. by Jeff Duntemann
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. PROGRAM LoopTest;    { From "Structured Programming" DDJ 7/91 }
  8. CONST
  9.   UART : ARRAY[0..4] OF STRING =
  10.          (' faulty','n 8250',' 16450',' 16550',' 16550A');
  11. VAR
  12.   PortNum : Byte;
  13. {-----------------------------------------------------------------}
  14. { FUNCTION DetectComPort  by Jeff Duntemann                       }
  15. { This function returns a Boolean value indicating whether or not }
  16. { a National Semiconductor UART (one of 8250B, 16450, 16550, or   }
  17. { 16550A) is present at the COM port passed in the PortNumber     }
  18. { parameter.  Don't run this function on serial ports that may be }
  19. { operating in some sort of background mode; it will probably     }
  20. { disrupt any communication stream currently in progress.         }
  21. {-----------------------------------------------------------------}
  22. FUNCTION DetectComPort(PortNumber : Integer) : Boolean;
  23. CONST
  24.   LOOPBIT = $10;
  25.   PortBases : ARRAY[1..4] OF Integer = ($03F8,$02F8,$03E8,$02E8);
  26.                                        { COM1  COM2  COM3  COM4 }
  27. VAR
  28.   Holder,HoldMCR,HoldMSR : Byte;
  29.   MCRPort,MSRPort,THRPort,RBRPort : Integer;
  30. BEGIN
  31.   { Calculate port numbers for the port being looked for: }
  32.   RBRPort := PortBases[PortNumber];  { RBR is at the base address }
  33.   THRPort := RBRPort;            { RBR and THR have same I/O address }
  34.   MCRPort := RBRPort + 4;        { MCR is at offset 4 }
  35.   MSRPort := RBRPort + 6;        { MSR is at offset 6 }
  36.   { Put the UART into loopback test mode: }
  37.   HoldMCR := Port[MCRPort];             { Save existing value of MCR }
  38.   Port[MCRPort] := HoldMCR OR LOOPBIT;  { Turn on loopback test mode }
  39.   HoldMSR := Port[MSRPort];
  40.   Port[MCRPort] := $0A OR LOOPBIT; { Put pattern to low 4 bits of MCR   }
  41.                                    {   without disabling loopback mode  }
  42.   Holder := Port[MSRPort] AND $F0; { Read pattern from hi 4 bits of MSR }
  43.   IF Holder = $90 THEN    { The $A pattern is changed to $9 inside UART }
  44.     DetectComPort := True
  45.   ELSE
  46.     DetectComPort := False;
  47.   { Restore previous contents of MSR: }
  48.   Port[MSRPort] := HoldMSR;
  49.   { Take the UART out of loopback mode & restore old state of MCR: }
  50.   Port[MCRPort] := HoldMCR AND (NOT LOOPBIT);
  51. END;
  52. {-----------------------------------------------------------------}
  53. { FUNCTION DetectUARTType  by Jeff Duntemann                      }
  54. { This function returns a numeric code indicating which UART chip }
  55. { is present at the selected PortNumber (1-4.)  The UART codes    }
  56. { returned are as follows:                                        }
  57. {   0 : Error; bad UART or no UART at COMn, where n=PortNumber    }
  58. {   1 : 8250; generally (but not always!) present in PC or XT     }
  59. {   2 : 16450; generally present in AT-class machines             }
  60. {   3 : 16550; in PS/2 mod 50/60/early 80.  FIFOs don't work!     }
  61. {   4 : 16550A; in later PS/2's.  FIFOs fully operative.          }
  62. { NOTE: This routine assumes a UART is "out there" at the port #  }
  63. { specified.  Run DetectComPort first to make sure port is there! }
  64. {-----------------------------------------------------------------}
  65. FUNCTION DetectUARTType(PortNumber : Integer) : Integer;
  66. CONST
  67.   PortBases : ARRAY[1..4] OF Integer = ($03F8,$02F8,$03E8,$02E8);
  68.                                        { COM1  COM2  COM3  COM4 }
  69. VAR
  70.   ScratchPort,IIRPort,FCRPort : Integer;
  71.   Holder : Byte;
  72. BEGIN
  73.   { The scratch register is at offset 7 from the comm port base: }
  74.   ScratchPort := PortBases[PortNumber] + 7;
  75.   FCRPort     := PortBases[PortNumber] + 2;
  76.   IIRPort     := FCRPort;       { IIR and FCR are at same offset }
  77.   Port[ScratchPort] := $AA;      { Write pattern to the scratch register }
  78.   IF Port[ScratchPort] <> $AA THEN          { Attempt to read it back... }
  79.     DetectUARTType := 1   { A UART without a scratch register is an 8250 }
  80.   ELSE
  81.     BEGIN      { Now we have to test among the 16450, 16550, and 16550A  }
  82.       Port[FCRPort] := $01;  { Setting FCR bit 0 on 16550 enables FIFOs  }
  83.       Holder := Port[IIRPort] AND $C0;  { Read back to FIFO status bits  }
  84.       CASE Holder OF
  85.         $C0 : DetectUARTType := 4; { Bits 6 & 7 both set = 16550A        }
  86.         $80 : DetectUARTType := 3; { Bit 7 set & bit 6 cleared = 16550   }
  87.         $00 : DetectUARTType := 2; { Neither bit set = 16450             }
  88.         ELSE DetectUARTType := 0;  { Error condition                     }
  89.       END; {CASE}
  90.       Port[FCRPort] := $00;        { Don't leave the FIFOs enabled! }
  91.     END;
  92. END;
  93.  
  94. BEGIN
  95.   FOR PortNum := 1 TO 4 DO
  96.     BEGIN
  97.       IF DetectComPort(PortNum) THEN
  98.         BEGIN
  99.           Write  ('Port COM',PortNum,' is present,');
  100.           Writeln(' using a',UART[DetectUARTType(PortNum)],' UART.');
  101.         END
  102.       ELSE
  103.         Writeln('Port COM',Portnum,' is not present.');
  104.     END;
  105. END.
  106.  
  107.