home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / multtsk / cpmult / source / v24.pas < prev   
Pascal/Delphi Source File  |  1990-04-07  |  12KB  |  259 lines

  1. (*////////////////////////////////////////////////////////////////////////////
  2. ///                                                                        ///
  3. ///         T U R B O  -  P A S C A L  V24-Interrupt-Handler V2.00         ///
  4. ///                (c) Copyright Juni 1988 by C.Philipps                   ///
  5. ///                                                                        ///
  6. ///               (Turbo Pascal V4.0  or higher required)                  ///
  7. ///                                                                        ///
  8. //////////////////////////////////////////////////////////////////////////////
  9. ///                                                                        ///
  10. ///            Low-Level Interrupt-Routinen für die Behandlung der         ///
  11. ///            seriellen Schnittstellen Com1 und Com2 mit Geschwindig-     ///
  12. ///            keiten von bis zu 115200 bps.                               ///
  13. ///            Teile der Grundidee sind dem Modul ASYNC von Mike Halli-    ///
  14. ///            day entnommen, das im Shuttle unter dem Namen ASYNC.ARC     ///
  15. ///            verfügbar ist.                                              ///
  16. ///                                                                        ///
  17. ///       Dieses Modul stelle ich hiermit allen interessierten Turbo-      ///
  18. ///       Pascal-Anwendern zur freien Verfügung.                           ///
  19. ///       Es darf ohne Bedenken an andere Benutzer weitergegeben           ///
  20. ///       werden, vorausgesetzt, dies geschieht unentgeldlich und in sei-  ///
  21. ///       ner ursprünglichen, unveränderten Form.                          ///
  22. ///       Es steht Ihnen frei, die Routinen in Ihre eigenen Programme zu   ///
  23. ///       integrieren oder sie zu erweitern/verändern. Ich wäre Ihnen je-  ///
  24. ///       doch dankbar, wenn Sie die daraus entstehende neue Version wie-  ///
  25. ///       derum der Allgemeinheit zur Verfügung stellten.                  ///
  26. ///                                                                        ///
  27. ///       Christian Philipps                                               ///
  28. ///       Düsseldorfer Str. 316                                            ///
  29. ///       4130 Moers 1                                                     ///
  30. ///                                                                        ///
  31. ///       Stand: 07/89                                                     ///
  32. ///                                                                        ///
  33. ////////////////////////////////////////////////////////////////////////////*)
  34.  
  35. {$R-,S-,I-,D-,F-,V-,B-,N-,L- }
  36.  
  37. UNIT V24;
  38.  
  39. INTERFACE
  40.  
  41. USES DOS;
  42.  
  43. TYPE   ComType      = (Com1,Com2,Com3,Com4,Com5,Com6);
  44.        BaudType     = (b110,b150,b300,b600,b1200,b2400,b4800,b9600,b19200,
  45.                        b38400,b57600,b115200);
  46.        ParityType   = (Space,Odd,Mark,Even,None);
  47.        DataBitsType = (d5,d6,d7,d8);
  48.        StopBitsType = (s1,s2);
  49.  
  50. CONST  V24Timeout   : BOOLEAN = FALSE;  {SendByte-Timeout}
  51.        IntMasks     : ARRAY[Com1..Com6] OF WORD    = ($EF,$F7,$EF,$F7,$EF,$F7);
  52.        IntVect      : ARRAY[Com1..Com6] OF BYTE    = ($0C,$0B,$0C,$0B,$0C,$0B);
  53.  
  54. VAR    V24TP        : WORD;         {Buffer Tail-Pointer
  55.                                      Im Interface-Teil, da zur Ereignis-
  56.                                      steuerung im Multi-Tasking benötigt.}
  57.        ComBaseAdr   : ARRAY[Com1..Com6] OF WORD;
  58.  
  59. FUNCTION  V24DataAvail:BOOLEAN;
  60. FUNCTION  V24GetByte:BYTE;
  61. PROCEDURE InitCom(ComPort:ComType;Baudrate:BaudType;Parity:ParityType;
  62.                   Bits:DataBitsType;Stop:StopBitsType);
  63. PROCEDURE DisableCom;
  64. PROCEDURE SendByte(Data:BYTE);
  65.  
  66. {=============================================================================}
  67.  
  68. IMPLEMENTATION
  69.  
  70. CONST  Regs       : Registers =
  71.        (AX:0;BX:0;CX:0;DX:0;BP:0;SI:0;DI:0;DS:0;ES:0;FLAGS:0);
  72.        RBR        = $00;          {xF8 Receive Buffer Register            }
  73.        THR        = $00;          {xF8 Transmitter Holding Register       }
  74.        IER        = $01;          {xF9 Interrupt Enable Register          }
  75.        IIR        = $02;          {xFA Interrupt Identification Register  }
  76.        LCR        = $03;          {xFB Line Control Register              }
  77.        MCR        = $04;          {xFC Modem Control Register             }
  78.        LSR        = $05;          {xFD Line Status Register               }
  79.        MSR        = $06;          {xFE Modem Status Register              }
  80.                                   {--- if LCR Bit 7 = 1  ---              }
  81.        DLL        = $00;          {xF8 Divisor Latch Low Byte             }
  82.        DLH        = $01;          {xF9 Divisor Latch Hi  Byte             }
  83.        CMD8259    = $20;          {Interrupt Controller Command Register  }
  84.        IMR8259    = $21;          {Interrupt Controller Mask Register     }
  85.                                   {Should be evaluated by any higher-level
  86.                                    send-routine}
  87.        LoopLimit  = 1000;         {When does a timeout-error occur        }
  88.        V24BuffSize= 2048;         { Ringpuffer 2 KB }
  89.  
  90. VAR    BiosComBaseAdr : ARRAY[Com1..Com2] OF WORD ABSOLUTE $0040:$0000;
  91.        ActivePort : ComType;
  92.        { The Com-Port base adresses are taken from the BIOS data area }
  93.        ComBase    : WORD;         {Hardware Com-Port Base Adress          }
  94.        OldV24     : Pointer;
  95.        V24HP      : WORD;         {Buffer Head-Pointer                    }
  96.        V24BuffEnd : WORD;         {Buffer End-Adress                      }
  97.        V24Buff    : ARRAY[0..V24BuffSize] OF BYTE;
  98.        OExitHandler : Pointer;    {Save-Area für Zeiger auf Org.-Exit-Proc}
  99.  
  100. {============================ lokale Routinen ================================}
  101.  
  102. PROCEDURE V24Int; external;
  103. {$L v24.obj}
  104.  
  105. {-----------------------------------------------------------------------------}
  106.  
  107. PROCEDURE ClearPendingInterrupts;
  108.  
  109. VAR  N : BYTE;
  110.  
  111. BEGIN {ClearPendingInterrupts}
  112.   WHILE (PORT[ComBase+IIR] AND 1) = 0 DO  {While Interrupts are pending}
  113.   BEGIN
  114.     N := PORT[ComBase+LSR];               {Read Line Status}
  115.     N := PORT[ComBase+MSR];               {Read Modem Status}
  116.     N := PORT[ComBase+RBR];               {Read Receive Buffer Register}
  117.     PORT[CMD8259] := $20;                 {End of Interrupt}
  118.   END;
  119. END;  {ClearPendingInterrupts}
  120.  
  121. {======================== extern verfügbare Routinen =========================}
  122.  
  123. FUNCTION V24DataAvail:BOOLEAN;
  124.  
  125. { Diese Funktion überprüft, ob Daten im Ringpuffer vorliegen }
  126.  
  127. BEGIN {V24DataAvail}
  128.   V24DataAvail := (V24HP <> V24TP);
  129. END;  {V24DataAvail}
  130.  
  131. {-----------------------------------------------------------------------------}
  132.  
  133. FUNCTION V24GetByte:BYTE;
  134.  
  135. { Diese Funktion holt ein Byte aus dem Ringpuffer. Es wird vorausgesetzt,
  136.   das über V24DataAvail zuvor sichergestellt wurde, daß auch ein Zeichen
  137.   zum Auslesen bereitsteht!!!!!
  138.   Da die Interruptroutine auf den Head-Pointer nur lesend zugreift,
  139.   brauchen beim Update des Pointers die Interrupts nicht gesperrt zu
  140.   werden! }
  141.  
  142. BEGIN {V24GetByte}
  143.   V24GetByte := Mem[DSeg:V24HP];
  144.   Inc(V24HP);
  145.   IF V24HP > V24BuffEnd
  146.      THEN V24HP := Ofs(V24Buff);
  147. END;  {V24GetByte}
  148.  
  149. {-----------------------------------------------------------------------------}
  150.  
  151. PROCEDURE SendByte(Data:BYTE);
  152.  
  153. VAR   Count:BYTE;
  154.  
  155. BEGIN {SendByte}
  156.   Count := 0;
  157.   V24Timeout := FALSE;
  158.   IF ComBase > 0
  159.      THEN BEGIN
  160.             REPEAT
  161.               Count := SUCC(Count);
  162.             UNTIL ((PORT[ComBase+LSR] AND $20) <> 0) OR (Count > LoopLimit);
  163.             IF Count > LoopLimit
  164.                THEN V24Timeout := TRUE
  165.                ELSE PORT[ComBase+THR] := Data;
  166.           END;
  167. END;  {SendByte}
  168.  
  169. {-----------------------------------------------------------------------------}
  170.  
  171. PROCEDURE InitCom(ComPort:ComType;Baudrate:BaudType;Parity:ParityType;
  172.                   Bits:DataBitsType;Stop:StopBitsType);
  173.  
  174. CONST BaudConst   : ARRAY[b110..b115200] OF WORD =
  175.                     ($417,$300,$180,$C0,$60,$30,$18,$0C,$06,$03,$02,$01);
  176.       ParityConst : ARRAY[Space..None] OF BYTE =
  177.                     ($38,$08,$28,$18,$00);
  178.       BitsConst   : ARRAY[d5..d8] OF BYTE =
  179.                     ($00,$01,$02,$03);
  180.       StopConst   : ARRAY[s1..s2] OF BYTE =
  181.                     ($00,$04);
  182.  
  183. BEGIN {InitCom}
  184.   V24HP       := Ofs(V24Buff);
  185.   V24TP       := V24HP;
  186.   V24BuffEnd  := V24HP+V24BuffSize;
  187.   FillChar(V24Buff,Succ(V24BuffSize),#0);
  188.   V24Timeout := FALSE;                             {Reset Timeout-Marker}
  189.   ComBase := ComBaseAdr[ComPort];                  {Get Com-Port base adress}
  190.   ActivePort := ComPort;                           {Keep Active-Port for EOI}
  191.   ClearPendingInterrupts;
  192.   GetIntVec(IntVect[ComPort],OldV24);
  193.   SetIntVec(IntVect[ComPort],@V24Int);
  194.                                                    {Install interrupt routine}
  195.   INLINE($FA);                                     {CLI}
  196.   PORT[ComBase+LCR] := $80;                        {Adress Divisor Latch}
  197.   PORT[ComBase+DLH] := Hi(BaudConst[Baudrate]);    {Set Baud rate}
  198.   PORT[COMBase+DLL] := Lo(BaudConst[Baudrate]);
  199.   PORT[ComBase+LCR] := ($00 OR ParityConst[Parity] {Setup Parity}
  200.                             OR BitsConst[Bits]     {Setup number of databits}
  201.                             OR StopConst[Stop]);   {Setup number of stopbits}
  202.   PORT[ComBase+MCR] := $0B;                        {Set RTS,DTR,OUT2}
  203. (*
  204.   PORT[ComBase+MCR] := $1B;                        {Set RTS,DTR,OUT2,Loop}
  205. *)
  206.   PORT[ComBase+IER] := $01;                        {Enable Data-Available Interrupts}
  207.   PORT[IMR8259] := PORT[IMR8259] AND IntMasks[ComPort]; {Enable V24-Interrups}
  208.   INLINE($FB);                                     {STI}
  209. END;  {InitCom}
  210.  
  211. {-----------------------------------------------------------------------------}
  212.  
  213. PROCEDURE DisableCom;
  214.  
  215. BEGIN {DisableCom}
  216.   IF ComBase = 0
  217.      THEN Exit;
  218.   INLINE($FA);                                     {CLI}
  219.   PORT[ComBase+MCR] := 00;                         {Disable Interrupts, Reset MCR}
  220.   PORT[IMR8259] := PORT[IMR8259] OR $18;           {Disable Interrupt Level 3 and 4}
  221.   PORT[ComBase+IER] := 0;                          {Disable 8250-Interrupts}
  222.   ClearPendingInterrupts;                          {Clean up}
  223.   ComBase := 0;                                    {Reset Combase}
  224.   SetIntVec(IntVect[ActivePort],OldV24);           {Reset old IV}
  225.   INLINE($FB);                                     {STI}
  226. END;  {DisableCom}
  227.  
  228. {-----------------------------------------------------------------------------}
  229.  
  230. {$F+}
  231. PROCEDURE V24ExitProc;
  232.  
  233. BEGIN {V24ExitProc}
  234.   DisableCom;
  235.   ExitProc := OExitHandler;                 { alten Exit-Handler reaktivieren }
  236. END;  {V24ExitProc}
  237. {$F-}
  238.  
  239. {-----------------------------------------------------------------------------}
  240.  
  241. BEGIN {Initialisierung}
  242.   {Grund-Init, damit irrtümliche Aufrufe von V24DataAvail nicht zu
  243.    endlosen Ausgaben von Speicherschrott führen!}
  244.   Move(BiosComBaseAdr,ComBaseAdr[Com1],SizeOf(BiosComBaseAdr));
  245.   Move(BiosComBaseAdr,ComBaseAdr[Com3],SizeOf(BiosComBaseAdr));
  246.   Move(BiosComBaseAdr,ComBaseAdr[Com5],SizeOf(BiosComBaseAdr));
  247.   ComBase     := 0;
  248.   V24HP       := Ofs(V24Buff);
  249.   V24TP       := V24HP;
  250.   V24BuffEnd  := V24HP+V24BuffSize;
  251.  
  252.   OExitHandler := ExitProc;                   {eigene Exit-Prozedur aktivieren}
  253.   ExitProc     := @V24ExitProc;
  254. END.  {Initialisierung}
  255.  
  256. (*////////////////////////////////////////////////////////////////////////////
  257. ///                       E N D   O F   M O D U L E                        ///
  258. ////////////////////////////////////////////////////////////////////////////*)
  259.