home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / alt / sources / 3098 < prev    next >
Encoding:
Internet Message Format  |  1993-01-25  |  51.4 KB

  1. Path: sparky!uunet!cs.utexas.edu!usc!howland.reston.ans.net!bogus.sura.net!darwin.sura.net!newsserver.jvnc.net!yale.edu!ira.uka.de!smurf.sub.org!pfm!rebell!root
  2. From: root@rebell.rmt.sub.org (Gottfried Hamm)
  3. Newsgroups: alt.sources
  4. Subject: v24.pas - Turbo Pascal Unit for the serial V.24 interface (MS-DOS)
  5. Message-ID: <root00241930025231405@rebell.rmt.sub.org>
  6. Date: Mon, 25 Jan 93 23:14:05 MESZ
  7. Distribution: world               
  8. Organization: rebell * +49 6249 8842 * D-6524 Guntersblum
  9. Lines: 1136
  10. X-Newsreader: NWREADER [version 3.01]
  11.  
  12. The following ist the source to build a Turbo Pascal Unit (tpu) to
  13. communicate with the serial interface of a PC. I use it in all my programs,
  14. using this interface.
  15.  
  16. I hope it will be helpful to you.
  17.  
  18. Gottfried
  19.  
  20. -----cut here-----cut here-----cut here-----cut here-----cut here-----
  21. unit v24;
  22.  
  23. INTERFACE
  24.  
  25. uses dos, crt;
  26.  
  27. (*----------------------------------------------------------------------*)
  28. (*              V24.PAS   --- Asynchronous I/O for Turbo Pascal         *)
  29. (*----------------------------------------------------------------------*)
  30. (*                                                                      *)
  31. (*  Author:  Philip R. Burns                                            *)
  32. (*  Date:    January, 1985                                              *)
  33. (*  Version: 1.0                                                        *)
  34. (*  Systems: For MS-DOS on IBM PCs and close compatibles only.          *)
  35. (*           Note:  I have checked these on Zenith 151s under           *)
  36. (*                  MSDOS 2.1 and IBM PCs under PCDOS 2.0.              *)
  37. (*                                                                      *)
  38. (*  History: Some of these routines are based upon ones written by:     *)
  39. (*                                                                      *)
  40. (*              Alan Bishop                                             *)
  41. (*              C. J. Dunford                                           *)
  42. (*              Michael Quinlan                                         *)
  43. (*                                                                      *)
  44. (*           I have cleaned up these other authors' code, fixed some    *)
  45. (*           bugs, and added many new features.                         *)
  46. (*                                                                      *)
  47. (*           Suggestions for improvements or corrections are welcome.   *)
  48. (*           Please leave messages on Gene Plantz's BBS (312) 882 4145  *)
  49. (*           or Ron Fox's BBS (312) 940 6496.                           *)
  50. (*                                                                      *)
  51. (*           If you use this code in your own programs, please be nice  *)
  52. (*           and give all of us credit.                                 *)
  53. (*                                                                      *)
  54. (*  Realization as Turbo-Pascal-Unit by Gottfried Hamm, June 1990       *)
  55. (*                                                                      *)
  56. (*----------------------------------------------------------------------*)
  57. (*                                                                      *)
  58. (*  Routines:                                                           *)
  59. (*                                                                      *)
  60. (*     Async_Init             ---    Performs initialization.           *)
  61. (*     Async_Open             ---    Sets up COM port                   *)
  62. (*     Async_Close            ---    Closes down COM port               *)
  63. (*     Async_Carrier_Detect   ---    Checks for modem carrier detect    *)
  64. (*     Async_Carrier_Drop     ---    Checks for modem carrier drop      *)
  65. (*     Async_Buffer_Check     ---    Checks if character in COM buffer  *)
  66. (*     Async_Term_Ready       ---    Toggles terminal ready status      *)
  67. (*     Async_Receive          ---    Reads character from COM buffer    *)
  68. (*     Async_Receive_With_Timeout                                       *)
  69. (*                            ---    Receives char. with timeout check  *)
  70. (*     Async_Send             ---    Transmits char over COM port       *)
  71. (*     Async_Send_String      ---    Sends string over COM port         *)
  72. (*     Async_Send_String_With_Delays                                    *)
  73. (*                            ---    Sends string with timed delays     *)
  74. (*     Async_Send_Break       ---    Sends break (attention) signal     *)
  75. (*     Async_Percentage_Used  ---    Returns percentage com buffer used *)
  76. (*     Async_Purge_Buffer     ---    Purges receive buffer              *)
  77. (*                                                                      *)
  78. (*----------------------------------------------------------------------*)
  79. (*                                                                      *)
  80. (*----------------------------------------------------------------------*)
  81.  
  82. (*----------------------------------------------------------------------*)
  83. (*                                                                      *)
  84. (*                  COMMUNICATIONS HARDWARE ADDRESSES                   *)
  85. (*                                                                      *)
  86. (*        These are specific to IBM PCs and close compatibles.          *)
  87. (*                                                                      *)
  88. (*----------------------------------------------------------------------*)
  89.  
  90. Const
  91.  
  92.    UART_THR = $00;       (* offset from base of UART Registers for IBM PC *)
  93.    UART_RBR = $00;
  94.    UART_IER = $01;
  95.    UART_IIR = $02;
  96.    UART_LCR = $03;
  97.    UART_MCR = $04;
  98.    UART_LSR = $05;
  99.    UART_MSR = $06;
  100.  
  101.    I8088_IMR = $21;      (* port address of the Interrupt Mask Register *)
  102.  
  103.    COM1_Base = $03F8;    (* port addresses for the UART *)
  104.    COM2_Base = $02F8;
  105.  
  106.    COM1_Irq = 4;         (* Interrupt line for the UART *)
  107.    COM2_Irq = 3;
  108.  
  109.    Async_DSeg_Save : Integer = 0;  (* Save DS reg in Code Segment for *)
  110.                                    (* interrupt routine               *)
  111.  
  112. (*----------------------------------------------------------------------*)
  113. (*                                                                      *)
  114. (*                   COMMUNICATIONS BUFFER VARIABLES                    *)
  115. (*                                                                      *)
  116. (*     The Communications Buffer is implemented as a circular (ring)    *)
  117. (*     buffer, or double-ended queue.  The asynchronous I/O routines    *)
  118. (*     enter characters in the buffer as they are received.  Higher-    *)
  119. (*     level routines may extract characters from the buffer.           *)
  120. (*                                                                      *)
  121. (*     Note that this buffer is used for input only;  output is done    *)
  122. (*     on a character-by-character basis.                               *)
  123. (*                                                                      *)
  124. (*----------------------------------------------------------------------*)
  125.  
  126.    Async_Buffer_Max    = 8191;       (* Size of Communications Buffer   *)
  127. (* Async_Loops_Per_Sec = 6500;          Loops per second -- 4.77 clock  *)
  128. (* Als Variable definiert - siehe unten!                                *)
  129.    TimeOut             = 256;        (* TimeOut value                   *)
  130.  
  131. Type anystr = string[80];
  132.  
  133. Var
  134.                                      (* Communications Buffer Itself *)
  135.  
  136.    Async_Buffer          : Array[0..Async_Buffer_Max] of Char;
  137.  
  138.    Async_Loops_Per_Sec   : Integer;  (* Loops per second - siehe oben     *)
  139.    Async_Open_Flag       : Boolean;  (* true if Open but no Close         *)
  140.    Async_Port            : Integer;  (* current Open port number (1 or 2) *)
  141.    Async_Base            : Integer;  (* base for current open port        *)
  142.    Async_Irq             : Integer;  (* irq for current open port         *)
  143.  
  144.    Async_Buffer_Overflow : Boolean;  (* True if buffer overflow has happened *)
  145.    Async_Buffer_Used     : Integer;
  146.    Async_MaxBufferUsed   : Integer;
  147.  
  148.                                      (* Async_Buffer empty if Head = Tail    *)
  149.    Async_Buffer_Head    : Integer;   (* Loc in Async_Buffer to put next char *)
  150.    Async_Buffer_Tail    : Integer;   (* Loc in Async_Buffer to get next char *)
  151.    Async_Buffer_NewTail : Integer;
  152.  
  153. (*----------------------------------------------------------------------*)
  154. (*                BIOS_RS232_Init --- Initialize UART                   *)
  155. (*                                                                      *)
  156. Procedure BIOS_RS232_Init( ComPort, ComParm : Integer );
  157. (*                                                                      *)
  158. (*     Procedure:  BIOS_RS232_Init                                      *)
  159. (*                                                                      *)
  160. (*     Purpose:    Issues interrupt $14 to initialize the UART          *)
  161. (*                                                                      *)
  162. (*     Calling Sequence:                                                *)
  163. (*                                                                      *)
  164. (*        BIOS_RS232_Init( ComPort, ComParm : Integer );                *)
  165. (*                                                                      *)
  166. (*           ComPort  --- Communications Port Number (1 or 2)           *)
  167. (*           ComParm  --- Communications Parameter Word                 *)
  168. (*                                                                      *)
  169. (*      Calls:   INTR   (to perform BIOS interrupt $14)                 *)
  170. (*----------------------------------------------------------------------*)
  171.  
  172. (*----------------------------------------------------------------------*)
  173. (*             DOS_Set_Intrpt --- Call DOS to set interrupt vector      *)
  174. (*                                                                      *)
  175. Procedure DOS_Set_Intrpt( v, s, o : Integer );
  176. (*                                                                      *)
  177. (*     Procedure:  DOS_Set_Intrpt                                       *)
  178. (*                                                                      *)
  179. (*     Purpose:    Calls DOS to set interrupt vector                    *)
  180. (*                                                                      *)
  181. (*     Calling Sequence:                                                *)
  182. (*                                                                      *)
  183. (*        DOS_Set_Intrpt( v, s, o : Integer );                          *)
  184. (*                                                                      *)
  185. (*           v --- interrupt vector number to set                       *)
  186. (*           s --- segment address of interrupt routine                 *)
  187. (*           o --- offset address of interrupt routine                  *)
  188. (*                                                                      *)
  189. (*      Calls:   MSDOS   (to set interrupt)                             *)
  190. (*----------------------------------------------------------------------*)
  191.  
  192. (*----------------------------------------------------------------------*)
  193. (*               Async_Isr --- Interrupt Service Routine                *)
  194. (*                                                                      *)
  195. Procedure Async_Isr;
  196. (*                                                                      *)
  197. (*     Procedure:  Async_Isr                                            *)
  198. (*                                                                      *)
  199. (*     Purpose:    Invoked when UART has received character from        *)
  200. (*                 communications line  (asynchronous)                  *)
  201. (*                                                                      *)
  202. (*     Calling Sequence:                                                *)
  203. (*                                                                      *)
  204. (*        Async_Isr;                                                    *)
  205. (*                                                                      *)
  206. (*           --- Called asyncronously only!!!!!!                        *)
  207. (*                                                                      *)
  208. (*     Remarks:                                                         *)
  209. (*                                                                      *)
  210. (*        This is Michael Quinlan's version of the interrupt handler.   *)
  211. (*----------------------------------------------------------------------*)
  212.  
  213. (*----------------------------------------------------------------------*)
  214. (*               Async_Init --- Initialize Asynchronous Variables       *)
  215. (*                                                                      *)
  216. Procedure Async_Init;
  217. (*                                                                      *)
  218. (*     Procedure:  Async_Init                                           *)
  219. (*                                                                      *)
  220. (*     Purpose:    Initializes variables                                *)
  221. (*                                                                      *)
  222. (*     Calling Sequence:                                                *)
  223. (*                                                                      *)
  224. (*        Async_Init;                                                   *)
  225. (*                                                                      *)
  226. (*     Calls:  None                                                     *)
  227. (*----------------------------------------------------------------------*)
  228.  
  229. (*----------------------------------------------------------------------*)
  230. (*               Async_Close --- Close down communications interrupts   *)
  231. (*                                                                      *)
  232. Procedure Async_Close;
  233. (*                                                                      *)
  234. (*     Procedure:  Async_Close                                          *)
  235. (*                                                                      *)
  236. (*     Purpose:    Resets interrupt system when UART interrupts         *)
  237. (*                 are no longer needed.                                *)
  238. (*                                                                      *)
  239. (*     Calling Sequence:                                                *)
  240. (*                                                                      *)
  241. (*        Async_Close;                                                  *)
  242. (*                                                                      *)
  243. (*     Calls:  None                                                     *)
  244. (*----------------------------------------------------------------------*)
  245.  
  246. (*----------------------------------------------------------------------*)
  247. (*               Async_Open --- Open communications port                *)
  248. (*                                                                      *)
  249. Function Async_Open( ComPort       : Integer;
  250.                      BaudRate      : Integer;
  251.                      Parity        : Char;
  252.                      WordSize      : Integer;
  253.                      StopBits      : Integer  ) : Boolean;
  254. (*                                                                      *)
  255. (*     Function:   Async_Open                                           *)
  256. (*                                                                      *)
  257. (*     Purpose:    Opens communications port                            *)
  258. (*                                                                      *)
  259. (*     Calling Sequence:                                                *)
  260. (*                                                                      *)
  261. (*        Flag := Async_Open( ComPort       : Integer;                  *)
  262. (*                            BaudRate      : Integer;                  *)
  263. (*                            Parity        : Char;                     *)
  264. (*                            WordSize      : Integer;                  *)
  265. (*                            StopBits      : Integer) : Boolean;       *)
  266. (*                                                                      *)
  267. (*           ComPort  --- which port (1 or 2)                           *)
  268. (*           BaudRate --- Baud rate (110 to 9600)                       *)
  269. (*           Parity   --- "E" for even, "O" for odd, "N" for none       *)
  270. (*           WordSize --- Bits per character  (5 through 8)             *)
  271. (*           StopBits --- How many stop bits  (1 or 2)                  *)
  272. (*                                                                      *)
  273. (*           Flag returned TRUE if port initialized successfully;       *)
  274. (*           Flag returned FALSE if any errors.                         *)
  275. (*                                                                      *)
  276. (*     Calls:                                                           *)
  277. (*                                                                      *)
  278. (*        BIOS_RS232_Init --- initialize RS232 port                     *)
  279. (*        DOS_Set_Intrpt  --- set address of RS232 interrupt routine    *)
  280. (*----------------------------------------------------------------------*)
  281.  
  282. (*----------------------------------------------------------------------*)
  283. (*      Async_Carrier_Detect --- Check for modem carrier detect         *)
  284. (*                                                                      *)
  285. Function Async_Carrier_Detect : Boolean;
  286. (*                                                                      *)
  287. (*     Function:   Async_Carrier_Detect                                 *)
  288. (*                                                                      *)
  289. (*     Purpose:    Looks for modem carrier detect                       *)
  290. (*                                                                      *)
  291. (*     Calling Sequence:                                                *)
  292. (*                                                                      *)
  293. (*        Flag := Async_Carrier_Detect : Boolean;                       *)
  294. (*                                                                      *)
  295. (*           Flag is set TRUE if carrier detected, else FALSE.          *)
  296. (*                                                                      *)
  297. (*     Calls:  None                                                     *)
  298. (*----------------------------------------------------------------------*)
  299.  
  300. (*----------------------------------------------------------------------*)
  301. (*      Async_Carrier_Drop --- Check for modem carrier drop/timeout     *)
  302. (*                                                                      *)
  303. Function Async_Carrier_Drop : Boolean;
  304. (*                                                                      *)
  305. (*     Function:   Async_Carrier_Drop                                   *)
  306. (*                                                                      *)
  307. (*     Purpose:    Looks for modem carrier drop/timeout                 *)
  308. (*                                                                      *)
  309. (*     Calling Sequence:                                                *)
  310. (*                                                                      *)
  311. (*        Flag := Async_Carrier_Drop : Boolean;                         *)
  312. (*                                                                      *)
  313. (*           Flag is set TRUE if carrier dropped, else FALSE.           *)
  314. (*                                                                      *)
  315. (*     Calls:  None                                                     *)
  316. (*----------------------------------------------------------------------*)
  317.  
  318. (*----------------------------------------------------------------------*)
  319. (*      Async_Term_Ready --- Set terminal ready status                  *)
  320. (*                                                                      *)
  321. Procedure Async_Term_Ready( Ready_Status : Boolean );
  322. (*                                                                      *)
  323. (*     Procedure:  Async_Term_Ready                                     *)
  324. (*                                                                      *)
  325. (*     Purpose:    Sets terminal ready status                           *)
  326. (*                                                                      *)
  327. (*     Calling Sequence:                                                *)
  328. (*                                                                      *)
  329. (*        Async_Term_Ready( Ready_Status : Boolean );                   *)
  330. (*                                                                      *)
  331. (*           Ready_Status --- Set TRUE to set terminal ready on,        *)
  332. (*                            Set FALSE to set terminal ready off.      *)
  333. (*                                                                      *)
  334. (*     Calls:  None                                                     *)
  335. (*----------------------------------------------------------------------*)
  336.  
  337. (*----------------------------------------------------------------------*)
  338. (*          Async_Buffer_Check --- Check if character in buffer         *)
  339. (*                                                                      *)
  340. Function Async_Buffer_Check : Boolean;
  341. (*                                                                      *)
  342. (*     Function:   Async_Buffer_Check                                   *)
  343. (*                                                                      *)
  344. (*     Purpose:    Check if character in buffer                         *)
  345. (*                                                                      *)
  346. (*     Calling Sequence:                                                *)
  347. (*                                                                      *)
  348. (*        Flag := Async_Buffer_Check : Boolean;                         *)
  349. (*                                                                      *)
  350. (*           Flag returned TRUE if character received in buffer,        *)
  351. (*           Flag returned FALSE if no character received.              *)
  352. (*                                                                      *)
  353. (*     Calls:  None                                                     *)
  354. (*                                                                      *)
  355. (*     Remarks:                                                         *)
  356. (*                                                                      *)
  357. (*       This routine only checks if a character has been received      *)
  358. (*       and thus can be read; it does NOT return the character.        *)
  359. (*       Use Async_Receive to read the character.                       *)
  360. (*----------------------------------------------------------------------*)
  361.  
  362. (*----------------------------------------------------------------------*)
  363. (*          Async_Receive --- Return character from buffer              *)
  364. (*                                                                      *)
  365. Function Async_Receive( Var C : Char ) : Boolean;
  366. (*                                                                      *)
  367. (*     Function:   Async_Receive                                        *)
  368. (*                                                                      *)
  369. (*     Purpose:    Retrieve character (if any) from buffer              *)
  370. (*                                                                      *)
  371. (*     Calling Sequence:                                                *)
  372. (*                                                                      *)
  373. (*        Flag := Async_Receive( Var C: Char ) : Boolean;               *)
  374. (*                                                                      *)
  375. (*           C --- character (if any) retrieved from buffer;            *)
  376. (*                 set to CHR(0) if no character available.             *)
  377. (*                                                                      *)
  378. (*           Flag returned TRUE if character retrieved from buffer,     *)
  379. (*           Flag returned FALSE if no character retrieved.             *)
  380. (*                                                                      *)
  381. (*     Calls:  None                                                     *)
  382. (*----------------------------------------------------------------------*)
  383.  
  384. (*----------------------------------------------------------------------*)
  385. (*   Async_Receive_With_TimeOut --- Return char. from buffer with delay *)
  386. (*                                                                      *)
  387. Procedure Async_Receive_With_Timeout( Secs : Integer; Var C : Integer );
  388. (*                                                                      *)
  389. (*     Procedure:  Async_Receive_With_Delay                            *)
  390. (*                                                                      *)
  391. (*     Purpose:    Retrieve character as integer from buffer,           *)
  392. (*                 or return TimeOut if specified delay period          *)
  393. (*                 expires.                                             *)
  394. (*                                                                      *)
  395. (*     Calling Sequence:                                                *)
  396. (*                                                                      *)
  397. (*        Async_Receive_With_Timeout( Secs: Integer; Var C: Integer );  *)
  398. (*                                                                      *)
  399. (*           Secs ---  Timeout period in seconds                        *)
  400. (*           C     --- ORD(character) (if any) retrieved from buffer;   *)
  401. (*                     set to TimeOut if no character found before      *)
  402. (*                     delay period expires.                            *)
  403. (*                                                                      *)
  404. (*     Calls:  Async_Receive                                            *)
  405. (*                                                                      *)
  406. (*     WATCH OUT!  THIS ROUTINE RETURNS AN INTEGER, NOT A CHARACTER!!!  *)
  407. (*                                                                      *)
  408. (*     Note:  This routine uses a CPU loop to do timing.  The value of  *)
  409. (*            the constant used is suitable for 4.77 MHz CPUs.  If your *)
  410. (*            CPU is faster or slower, you will need to adjust the      *)
  411. (*            value of ASYNC_LOOPS_PER_SEC.                             *)
  412. (*----------------------------------------------------------------------*)
  413.  
  414. (*----------------------------------------------------------------------*)
  415. (*          Async_Send --- Send character over communications port      *)
  416. (*                                                                      *)
  417. Procedure Async_Send( C : Char );
  418. (*                                                                      *)
  419. (*     Procedure:  Async_Send                                           *)
  420. (*                                                                      *)
  421. (*     Purpose:    Sends character out over communications port         *)
  422. (*                                                                      *)
  423. (*     Calling Sequence:                                                *)
  424. (*                                                                      *)
  425. (*        Async_Send( C : Char );                                       *)
  426. (*                                                                      *)
  427. (*           C --- Character to send                                    *)
  428. (*                                                                      *)
  429. (*     Calls:  None                                                     *)
  430. (*----------------------------------------------------------------------*)
  431.  
  432. (*----------------------------------------------------------------------*)
  433. (*          Async_Send_Break --- Send break (attention) signal          *)
  434. (*                                                                      *)
  435. Procedure Async_Send_Break;
  436. (*                                                                      *)
  437. (*     Procedure:  Async_Send_Break                                     *)
  438. (*                                                                      *)
  439. (*     Purpose:    Sends break signal over communications port          *)
  440. (*                                                                      *)
  441. (*     Calling Sequence:                                                *)
  442. (*                                                                      *)
  443. (*        Async_Send_Break;                                             *)
  444. (*                                                                      *)
  445. (*     Calls:  None                                                     *)
  446. (*----------------------------------------------------------------------*)
  447.  
  448. (*----------------------------------------------------------------------*)
  449. (*     Async_Send_String --- Send string over communications port       *)
  450. (*                                                                      *)
  451. Procedure Async_Send_String( S : AnyStr );
  452. (*                                                                      *)
  453. (*     Procedure:  Async_Send_String                                    *)
  454. (*                                                                      *)
  455. (*     Purpose:    Sends string out over communications port            *)
  456. (*                                                                      *)
  457. (*     Calling Sequence:                                                *)
  458. (*                                                                      *)
  459. (*        Async_Send_String( S : AnyStr );                              *)
  460. (*                                                                      *)
  461. (*           S --- String to send                                       *)
  462. (*                                                                      *)
  463. (*     Calls:  Async_Send                                               *)
  464. (*----------------------------------------------------------------------*)
  465.  
  466. (*----------------------------------------------------------------------*)
  467. (*     Async_Send_String_With_Delays --- Send string with timed delays  *)
  468. (*                                                                      *)
  469. Procedure Async_Send_String_With_Delays( S          : AnyStr;
  470.                                          Char_Delay : Integer;
  471.                                          EOS_Delay  : Integer  );
  472. (*                                                                      *)
  473. (*     Procedure:  Async_Send_String_With_Delays                        *)
  474. (*                                                                      *)
  475. (*     Purpose:    Sends string out over communications port with       *)
  476. (*                 specified delays for each character and at the       *)
  477. (*                 end of the string.                                   *)
  478. (*                                                                      *)
  479. (*     Calling Sequence:                                                *)
  480. (*                                                                      *)
  481. (*        Async_Send_String_With_Delays( S          : AnyStr ;          *)
  482. (*                                       Char_Delay : Integer;          *)
  483. (*                                       EOS_Delay  : Integer );        *)
  484. (*                                                                      *)
  485. (*           S          --- String to send                              *)
  486. (*           Char_Delay --- Number of milliseconds to delay after       *)
  487. (*                          sending each character                      *)
  488. (*           EOS_Delay  --- Number of milleseconds to delay after       *)
  489. (*                          sending last character in string            *)
  490. (*                                                                      *)
  491. (*     Calls:  Async_Send                                               *)
  492. (*             Async_Send_String                                        *)
  493. (*             Length                                                   *)
  494. (*             Delay                                                    *)
  495. (*                                                                      *)
  496. (*     Remarks:                                                         *)
  497. (*                                                                      *)
  498. (*        This routine is useful when writing routines to perform       *)
  499. (*        non-protocol uploads.  Many computer systems require delays   *)
  500. (*        between receipt of characters for correct processing.  The    *)
  501. (*        delay for end-of-string usually applies when the string       *)
  502. (*        represents an entire line of a file.                          *)
  503. (*                                                                      *)
  504. (*        If delays are not required, Async_Send_String is faster.      *)
  505. (*        This routine will call Async_Send_String if no character      *)
  506. (*        delay is to be done.                                          *)
  507. (*----------------------------------------------------------------------*)
  508.  
  509. (*----------------------------------------------------------------------*)
  510. (*      Async_Percentage_Used --- Report Percentage Buffer Filled       *)
  511. (*                                                                      *)
  512. Function Async_Percentage_Used : Real;
  513. (*                                                                      *)
  514. (*     Function:   Async_Percent_Used                                   *)
  515. (*                                                                      *)
  516. (*     Purpose:    Reports percentage of com buffer currently filled    *)
  517. (*                                                                      *)
  518. (*     Calling Sequence:                                                *)
  519. (*                                                                      *)
  520. (*        Percentage := Async_Percentage_Used : Real;                   *)
  521. (*                                                                      *)
  522. (*           Percentage gets how much of buffer is filled;              *)
  523. (*           value goes from 0.0 (empty) to 1.0 (totally full).         *)
  524. (*                                                                      *)
  525. (*     Calls:  None                                                     *)
  526. (*                                                                      *)
  527. (*     Remarks:                                                         *)
  528. (*                                                                      *)
  529. (*       This routine is helpful when incorporating handshaking into    *)
  530. (*       a communications program.  For example, assume that the host   *)
  531. (*       computer uses the XON/XOFF (DC1/DC3) protocol.  Then the       *)
  532. (*       PC program should issue an XOFF  to the host when the value    *)
  533. (*       returned by Async_Percentage_Used > .75 or so.  When the       *)
  534. (*       utilization percentage drops below .25 or so, the PC program   *)
  535. (*       should transmit an XON.                                        *)
  536. (*----------------------------------------------------------------------*)
  537.  
  538. (*----------------------------------------------------------------------*)
  539. (*     Async_Purge_Buffer --- Purge communications input buffer         *)
  540. (*                                                                      *)
  541. Procedure Async_Purge_Buffer;
  542. (*                                                                      *)
  543. (*     Procedure:  Async_Purge_Buffer                                   *)
  544. (*                                                                      *)
  545. (*     Purpose:    Purges communications input buffer                   *)
  546. (*                                                                      *)
  547. (*     Calling Sequence:                                                *)
  548. (*                                                                      *)
  549. (*        Async_Purge_Buffer;                                           *)
  550. (*                                                                      *)
  551. (*     Calls:  Async_Receive                                            *)
  552. (*----------------------------------------------------------------------*)
  553.  
  554.  
  555. IMPLEMENTATION
  556.  
  557. (*----------------------------------------------------------------------*)
  558.  
  559. Procedure BIOS_RS232_Init;
  560.  
  561. Var
  562.    Regs: Registers;
  563.  
  564. Begin   (* BIOS_RS232_Init *)
  565.  
  566.    With Regs Do
  567.       Begin
  568.          Ax := ComParm AND $00FF;  (* AH=0; AL=ComParm   *)
  569.          Dx := ComPort;            (* Port number to use *)
  570.          INTR($14, Regs);
  571.       End;
  572.  
  573. End    (* BIOS_RS232_Init *);
  574.  
  575. (*----------------------------------------------------------------------*)
  576.  
  577. Procedure DOS_Set_Intrpt;
  578.  
  579. Var
  580.    Regs : Registers;
  581.  
  582. Begin   (* DOS_Set_Intrpt *)
  583.  
  584.    With Regs Do
  585.       Begin
  586.          Ax := $2500 + ( v AND $00FF );
  587.          Ds := s;
  588.          Dx := o;
  589.          MsDos( Regs );
  590.       End;
  591.  
  592. End    (* DOS_Set_Intrpt *);
  593.  
  594. (*----------------------------------------------------------------------*)
  595.  
  596. Procedure Async_Isr;
  597.  
  598. Begin   (* Async_Isr *)
  599.  
  600.   (*  NOTE: on entry, Turbo Pascal has already PUSHed BP and SP  *)
  601.  
  602.   Inline(
  603.       (* save all registers used *)
  604.     $50/                           (* PUSH AX *)
  605.     $53/                           (* PUSH BX *)
  606.     $52/                           (* PUSH DX *)
  607.     $1E/                           (* PUSH DS *)
  608.     $FB/                           (* STI *)
  609.       (* set up the DS register to point to Turbo Pascal's data segment *)
  610.     $2E/$FF/$36/Async_Dseg_Save/   (* PUSH CS:Async_Dseg_Save *)
  611.     $1F/                           (* POP DS *)
  612.       (* get the incomming character *)
  613.       (* Async_Buffer[Async_Buffer_Head] := Chr(Port[UART_RBR + Async_Base]); *)
  614.     $8B/$16/Async_Base/            (* MOV DX,Async_Base *)
  615.     $EC/                           (* IN AL,DX *)
  616.     $8B/$1E/Async_Buffer_Head/     (* MOV BX,Async_Buffer_Head *)
  617.     $88/$87/Async_Buffer/          (* MOV Async_Buffer[BX],AL *)
  618.       (* Async_Buffer_NewHead := Async_Buffer_Head + 1; *)
  619.     $43/                           (* INC BX *)
  620.       (* if Async_Buffer_NewHead > Async_Buffer_Max then
  621.           Async_Buffer_NewHead := 0; *)
  622.     $81/$FB/Async_Buffer_Max/      (* CMP BX,Async_Buffer_Max *)
  623.     $7E/$02/                       (* JLE L001 *)
  624.     $33/$DB/                       (* XOR BX,BX *)
  625.       (* if Async_Buffer_NewHead = Async_Buffer_Tail then
  626.           Async_Buffer_Overflow := TRUE
  627.         else *)
  628. (*L001:*)
  629.     $3B/$1E/Async_Buffer_Tail/     (* CMP BX,Async_Buffer_Tail *)
  630.     $75/$08/                       (* JNE L002 *)
  631.     $C6/$06/Async_Buffer_Overflow/$01/ (* MOV Async_Buffer_Overflow,1 *)
  632.     $90/                           (* NOP generated by assembler for some reason *)
  633.     $EB/$16/                       (* JMP SHORT L003 *)
  634.       (* begin
  635.           Async_Buffer_Head := Async_Buffer_NewHead;
  636.           Async_Buffer_Used := Async_Buffer_Used + 1;
  637.           if Async_Buffer_Used > Async_MaxBufferUsed then
  638.             Async_MaxBufferUsed := Async_Buffer_Used
  639.         end; *)
  640. (*L002:*)
  641.     $89/$1E/Async_Buffer_Head/     (* MOV Async_Buffer_Head,BX *)
  642.     $FF/$06/Async_Buffer_Used/     (* INC Async_Buffer_Used *)
  643.     $8B/$1E/Async_Buffer_Used/     (* MOV BX,Async_Buffer_Used *)
  644.     $3B/$1E/Async_MaxBufferUsed/   (* CMP BX,Async_MaxBufferUsed *)
  645.     $7E/$04/                       (* JLE L003 *)
  646.     $89/$1E/Async_MaxBufferUsed/   (* MOV Async_MaxBufferUsed,BX *)
  647. (*L003:*)
  648.       (* disable interrupts *)
  649.     $FA/                           (* CLI *)
  650.       (* Port[$20] := $20; *)  (* use non-specific EOI *)
  651.     $B0/$20/                       (* MOV AL,20h *)
  652.     $E6/$20/                       (* OUT 20h,AL *)
  653.       (* restore the registers then use IRET to return *)
  654.       (* the last two POPs are required because Turbo Pascal PUSHes these regs
  655.         before we get control.  The manual doesn't say so, but that is what
  656.         really happens *)
  657.     $1F/                           (* POP DS *)
  658.     $5A/                           (* POP DX *)
  659.     $5B/                           (* POP BX *)
  660.     $58/                           (* POP AX *)
  661.     $5C/                           (* POP SP *)
  662.     $5D/                           (* POP BP *)
  663.     $CF)                           (* IRET *)
  664.  
  665. End    (* Async_Isr *);
  666.  
  667. (*----------------------------------------------------------------------*)
  668.  
  669. Procedure Async_Init;
  670.  
  671. Begin   (* Async_Init *)
  672.  
  673.   Async_DSeg_Save       := DSeg;
  674.   Async_Open_Flag       := FALSE;
  675.   Async_Buffer_Overflow := FALSE;
  676.   Async_Buffer_Used     := 0;
  677.   Async_MaxBufferUsed   := 0;
  678.  
  679. End     (* Async_Init *);
  680.  
  681. (*----------------------------------------------------------------------*)
  682.  
  683. Procedure Async_Close;
  684.  
  685. Var
  686.    i : Integer;
  687.    m : Integer;
  688.  
  689. Begin  (* Async_Close *)
  690.  
  691.    If Async_Open_Flag Then
  692.       Begin
  693.  
  694.                      (* disable the IRQ on the 8259 *)
  695.  
  696.          Inline($FA);                 (* disable interrupts *)
  697.  
  698.          i := Port[I8088_IMR];        (* get the interrupt mask register *)
  699.          m := 1 shl Async_Irq;        (* set mask to turn off interrupt  *)
  700.          Port[I8088_IMR] := i or m;
  701.  
  702.                      (* disable the 8250 data ready interrupt *)
  703.  
  704.          Port[UART_IER + Async_Base] := 0;
  705.  
  706.                      (* disable OUT2 on the 8250 *)
  707.  
  708.          Port[UART_MCR + Async_Base] := 0;
  709.  
  710.          Inline($FB);                 (* enable interrupts *)
  711.  
  712.                      (* re-initialize our data areas so we know *)
  713.                      (* the port is closed                      *)
  714.  
  715.          Async_Open_Flag := FALSE;
  716.  
  717.       End;
  718.  
  719. End    (* Async_Close *);
  720.  
  721. (*----------------------------------------------------------------------*)
  722.  
  723. Function Async_Open;
  724.  
  725. Const   (* Baud Rate Constants *)
  726.  
  727.    Async_Num_Bauds = 8;
  728.  
  729.    Async_Baud_Table : Array [1..Async_Num_Bauds] Of Record
  730.                                                        Baud, Bits : Integer;
  731.                                                     End
  732.  
  733.                     = ( ( Baud: 110;  Bits: $00 ),
  734.                         ( Baud: 150;  Bits: $20 ),
  735.                         ( Baud: 300;  Bits: $40 ),
  736.                         ( Baud: 600;  Bits: $60 ),
  737.                         ( Baud: 1200; Bits: $80 ),
  738.                         ( Baud: 2400; Bits: $A0 ),
  739.                         ( Baud: 4800; Bits: $C0 ),
  740.                         ( Baud: 9600; Bits: $E0 ) );
  741.  
  742. Var
  743.    ComParm : Integer;
  744.    i       : Integer;
  745.    m       : Integer;
  746.  
  747. Begin  (* Async_Open *)
  748.  
  749.                              (* If port open, close it down first. *)
  750.  
  751.    If Async_Open_Flag Then Async_Close;
  752.  
  753.                              (* Choose communications port *)
  754.    If ComPort = 2 Then
  755.       Begin
  756.          Async_Port := 2;
  757.          Async_Base := COM2_Base;
  758.          Async_Irq  := COM2_Irq;
  759.       End
  760.    Else
  761.       Begin
  762.          Async_Port := 1;  (* default to COM1 *)
  763.          Async_Base := COM1_Base;
  764.          Async_Irq  := COM1_Irq;
  765.       End;
  766.  
  767.    If (Port[UART_IIR + Async_Base] and $00F8) <> 0 Then
  768.       Async_Open := FALSE    (* Serial port not installed *)
  769.    Else
  770.       Begin   (* Open the port *)
  771.  
  772.                    (* Set buffer pointers *)
  773.  
  774.          Async_Buffer_Head     := 0;
  775.          Async_Buffer_Tail     := 0;
  776.          Async_Buffer_Overflow := FALSE;
  777.  
  778.             (*---------------------------------------------------*)
  779.             (*    Build the ComParm for RS232_Init               *)
  780.             (*    See Technical Reference Manual for description *)
  781.             (*---------------------------------------------------*)
  782.  
  783.                    (* Set up the bits for the baud rate *)
  784.  
  785.          If BaudRate > 9600 Then
  786.             BaudRate := 9600
  787.          Else If BaudRate <= 0 Then
  788.             BaudRate := 300;
  789.  
  790.          i := 0;
  791.  
  792.          Repeat
  793.             i := i + 1
  794.          Until ( ( i >= Async_Num_Bauds ) OR
  795.                  ( BaudRate = Async_Baud_Table[i].Baud ) );
  796.  
  797.          ComParm := Async_Baud_Table[i].Bits;
  798.  
  799.                    (* Choose Parity *)
  800.  
  801.          If Parity In ['E', 'e'] Then
  802.             ComParm := ComParm or $0018
  803.          Else If Parity In ['O', 'o'] Then
  804.             ComParm := ComParm or $0008;
  805.  
  806.                    (* Choose number of data bits *)
  807.  
  808.          WordSize := WordSize - 5;
  809.  
  810.          If ( WordSize < 0 ) OR ( WordSize > 3 ) Then
  811.             WordSize := 3;
  812.  
  813.          ComParm := ComParm OR WordSize;
  814.  
  815.                    (* Choose stop bits *)
  816.  
  817.          If StopBits = 2 Then
  818.             ComParm := ComParm OR $0004;  (* default is 1 stop bit *)
  819.  
  820.                    (* use the BIOS COM port initialization routine *)
  821.  
  822.          BIOS_RS232_Init( Async_Port - 1 , ComParm );
  823.  
  824.          DOS_Set_Intrpt( Async_Irq + 8 , CSeg , Ofs( Async_Isr ) );
  825.  
  826.                    (* Read the RBR and reset any pending error conditions. *)
  827.                    (* First turn off the Divisor Access Latch Bit to allow *)
  828.                    (* access to RBR, etc.                                  *)
  829.  
  830.          Inline($FA);  (* disable interrupts *)
  831.  
  832.          Port[UART_LCR + Async_Base] := Port[UART_LCR + Async_Base] and $7F;
  833.  
  834.                    (* Read the Line Status Register to reset any errors *)
  835.                    (* it indicates                                      *)
  836.  
  837.          i := Port[UART_LSR + Async_Base];
  838.  
  839.                    (* Read the Receiver Buffer Register in case it *)
  840.                    (* contains a character                         *)
  841.  
  842.          i := Port[UART_RBR + Async_Base];
  843.  
  844.                    (* enable the irq on the 8259 controller *)
  845.  
  846.          i := Port[I8088_IMR];  (* get the interrupt mask register *)
  847.          m := (1 shl Async_Irq) xor $00FF;
  848.  
  849.          Port[I8088_IMR] := i and m;
  850.  
  851.                    (* enable the data ready interrupt on the 8250 *)
  852.  
  853.          Port[UART_IER + Async_Base] := $01;
  854.  
  855.                    (* enable OUT2 on 8250 *)
  856.  
  857.          i := Port[UART_MCR + Async_Base];
  858.          Port[UART_MCR + Async_Base] := i or $08;
  859.  
  860.  
  861.          Inline($FB); (* enable interrupts *)
  862.  
  863.          Async_Open := TRUE
  864.  
  865.     End;
  866.  
  867. End   (* Async_Open *);
  868.  
  869. (*----------------------------------------------------------------------*)
  870.  
  871. Function Async_Carrier_Detect;
  872.  
  873. Begin (* Async_Carrier_Detect *)
  874.  
  875.    Async_Carrier_Detect := ODD( Port[ UART_MSR + Async_Base ] SHR 7 );
  876.  
  877. End   (* Async_Carrier_Detect *);
  878.  
  879. (*----------------------------------------------------------------------*)
  880.  
  881. Function Async_Carrier_Drop;
  882.  
  883. Begin (* Async_Carrier_Drop *)
  884.  
  885.    Async_Carrier_Drop := NOT ODD( Port[ UART_MSR + Async_Base ] SHR 7 );
  886.  
  887. End   (* Async_Carrier_Drop *);
  888.  
  889. (*----------------------------------------------------------------------*)
  890.  
  891. Procedure Async_Term_Ready;
  892.  
  893. Var
  894.    Mcr_Value: Byte;
  895.  
  896. Begin (* Async_Term_Ready *)
  897.  
  898.    Mcr_Value := Port[ UART_MCR + Async_Base ];
  899.  
  900.    If ODD( Mcr_Value ) Then Mcr_Value := Mcr_Value - 1;
  901.  
  902.    If Ready_Status Then Mcr_Value := Mcr_Value + 1;
  903.  
  904.    Port[ UART_MCR + Async_Base ] := Mcr_Value;
  905.  
  906. End   (* Async_Term_Ready *);
  907.  
  908. (*----------------------------------------------------------------------*)
  909.  
  910. Function Async_Buffer_Check;
  911.  
  912. Begin   (* Async_Buffer_Check *)
  913.  
  914.    Async_Buffer_Check := ( Async_Buffer_Head <> Async_Buffer_Tail );
  915.  
  916. End     (* Async_Buffer_Check *);
  917.  
  918. (*----------------------------------------------------------------------*)
  919.  
  920. Function Async_Receive;
  921.  
  922. Begin   (* Async_Receive *)
  923.  
  924.    If Async_Buffer_Head = Async_Buffer_Tail Then
  925.       Begin (* No character to retrieve *)
  926.  
  927.          Async_Receive := FALSE;
  928.          C             := CHR( 0 );
  929.  
  930.       End   (* No character available   *)
  931.  
  932.    Else
  933.       Begin (* Character available *)
  934.  
  935.                    (* Turn off interrupts *)
  936.  
  937.          INLINE( $FA );       (* CLI --- Turn off interrupts *)
  938.  
  939.                    (* Get character from buffer *)
  940.  
  941.          C := Async_Buffer[ Async_Buffer_Tail ];
  942.  
  943.                    (* Increment buffer pointer.   If past *)
  944.                    (* end of buffer, reset to beginning.  *)
  945.  
  946.          Async_Buffer_Tail := Async_Buffer_Tail + 1;
  947.  
  948.          If Async_Buffer_Tail > Async_Buffer_Max Then
  949.             Async_Buffer_Tail := 0;
  950.  
  951.                    (* Decrement buffer use count *)
  952.  
  953.          Async_Buffer_Used  := Async_Buffer_Used - 1;
  954.  
  955.                    (* Turn on interrupts *)
  956.  
  957.          INLINE( $FB );       (* STI --- Turn on interrupts *)
  958.  
  959.                    (* Indicate character successfully retrieved *)
  960.  
  961.          Async_Receive := TRUE;
  962.  
  963.       End   (* Character available *);
  964.  
  965. End   (* Async_Receive *);
  966.  
  967. (*----------------------------------------------------------------------*)
  968.  
  969. Procedure Async_Receive_With_Timeout;
  970.  
  971. Var
  972.    Isecs        : Integer;
  973.    Jsecs        : Integer;
  974.    I            : Integer;
  975.    J            : Integer;
  976.    Char_Waiting : Boolean;
  977.    Ch           : Char;
  978.  
  979. Begin (* Async_Receive_With_Timeout *)
  980.  
  981.    I     := Maxint DIV Async_Loops_Per_Sec;
  982.    Isecs := ( Secs + I - 1 ) DIV I;
  983.    Jsecs := ( Secs - Isecs * ( I - 1 ) ) * Async_Loops_Per_Sec;
  984.    Isecs := Isecs + 1;
  985.  
  986.    Repeat
  987.       J := Jsecs;
  988.       Repeat
  989.          J            := J - 1;
  990.          Char_Waiting := ( Async_Buffer_Head <> Async_Buffer_Tail );
  991.       Until( ( J = 0 ) OR ( Char_Waiting ) );
  992.       Isecs  := Isecs - 1;
  993.    Until( ( Isecs = 0 ) OR ( Char_Waiting ) );
  994.  
  995.    If ( NOT Char_Waiting) Then
  996.       C := TimeOut
  997.    Else
  998.       Begin
  999.          Char_Waiting := Async_Receive( Ch );
  1000.          C := ORD( Ch );
  1001.       End;
  1002.  
  1003. End   (* Async_Receive_With_Timeout *);
  1004.  
  1005. (*----------------------------------------------------------------------*)
  1006.  
  1007. Procedure Async_Send;
  1008.  
  1009. Var
  1010.    i       : Integer;
  1011.    m       : Integer;
  1012.    Counter : Integer;
  1013.  
  1014. Begin   (* Async_Send *)
  1015.  
  1016.                    (* Turn on OUT2, DTR, and RTS *)
  1017.  
  1018.    Port[UART_MCR + Async_Base] := $0B;
  1019.  
  1020.                    (* Wait for CTS using Busy Wait *)
  1021.  
  1022.    Counter := MaxInt;
  1023.  
  1024.    While ( Counter <> 0 ) AND
  1025.          ( ( Port[UART_MSR + Async_Base] AND $10 ) = 0 ) Do
  1026.       Counter := Counter - 1;
  1027.  
  1028.                    (* Wait for Transmit Hold Register Empty (THRE) *)
  1029.  
  1030.    If Counter <> 0 Then Counter := MaxInt;
  1031.  
  1032.    While ( Counter <> 0 ) AND
  1033.          ( ( Port[UART_LSR + Async_Base] AND $20 ) = 0 ) Do
  1034.       Counter := Counter - 1;
  1035.  
  1036.                    (* Send the character if port clear *)
  1037.  
  1038.   If Counter <> 0 Then
  1039.      Begin  (* Send the Character *)
  1040.  
  1041.         Inline($FA); (* CLI --- disable interrupts *)
  1042.  
  1043.         Port[UART_THR + Async_Base] := Ord(C);
  1044.  
  1045.         Inline($FB); (* STI --- enable interrupts *)
  1046.  
  1047.      End    (* Send the Character *)
  1048.  
  1049.   Else  (* Timed Out *)
  1050.      Writeln('<<<TIMEOUT>>>');
  1051.  
  1052. End    (* Async_Send *);
  1053.  
  1054. (*----------------------------------------------------------------------*)
  1055.  
  1056. Procedure Async_Send_Break;
  1057.  
  1058. Var
  1059.    Old_Lcr   : Byte;
  1060.    Break_Lcr : Byte;
  1061.  
  1062. Begin (* Async_Send_Break *)
  1063.  
  1064.    Old_Lcr   := Port[ UART_LCR + Async_Base ];
  1065.    Break_Lcr := Old_Lcr;
  1066.  
  1067.    If Break_Lcr >  127 Then Break_Lcr := Break_Lcr - 128;
  1068.    If Break_Lcr <=  63 Then Break_Lcr := Break_Lcr +  64;
  1069.  
  1070.    Port[ UART_LCR + Async_Base ] := Break_Lcr;
  1071.  
  1072.    Delay( 400 );
  1073.  
  1074.    Port[ UART_LCR + Async_Base ] := Old_Lcr;
  1075.  
  1076. End   (* Async_Send_Break *);
  1077.  
  1078. (*----------------------------------------------------------------------*)
  1079.  
  1080. Procedure Async_Send_String;
  1081.  
  1082. Var
  1083.    i : Integer;
  1084.  
  1085. Begin  (* Async_Send_String *)
  1086.  
  1087.   For i := 1 To LENGTH( S ) Do
  1088.      Async_Send( S[i] )
  1089.  
  1090. End    (* Async_Send_String *);
  1091.  
  1092. (*----------------------------------------------------------------------*)
  1093.  
  1094. Procedure Async_Send_String_With_Delays;
  1095.  
  1096. Var
  1097.    I : Integer;
  1098.  
  1099. Begin  (* Async_Send_String_With_Delays *)
  1100.  
  1101.    If Char_Delay <= 0 Then
  1102.       Async_Send_String( S )
  1103.    Else
  1104.       For I := 1 To LENGTH( S ) Do
  1105.          Begin
  1106.             Async_Send( S[I] );
  1107.             Delay( Char_Delay );
  1108.          End;
  1109.  
  1110.    If EOS_Delay > 0 Then Delay( EOS_Delay );
  1111.  
  1112. End    (* Async_Send_String_With_Delays *);
  1113.  
  1114. (*----------------------------------------------------------------------*)
  1115.  
  1116. Function Async_Percentage_Used;
  1117.  
  1118. Begin (* Async_Percentage_Used *)
  1119.  
  1120.    Async_Percentage_Used := Async_Buffer_Used / ( Async_Buffer_Max + 1 );
  1121.  
  1122. End   (* Async_Percentage_Used *);
  1123.  
  1124. (*----------------------------------------------------------------------*)
  1125.  
  1126. Procedure Async_Purge_Buffer;
  1127.  
  1128. Var
  1129.    C: Char;
  1130.  
  1131. Begin  (* Async_Purge_Buffer *)
  1132.  
  1133.    Repeat
  1134.       Delay( 35 );
  1135.    Until ( NOT Async_Receive( C ) );
  1136.  
  1137. End    (* Async_Purge_Buffer *);
  1138.  
  1139. (*----------------------------------------------------------------------*)
  1140.  
  1141. End    (* V24.PAS *).
  1142. -----cut here-----cut here-----cut here-----cut here-----cut here-----
  1143.  
  1144.  
  1145. | Gottfried Hamm      |  Email: root@rebell.rmt.sub.org  |     I'm      |
  1146. | Wormser Str. 36     |  Phone: +49 6249 8997            |   awaiting   |
  1147. | D-6524 Guntersblum  |  Fax  : +49 6249 8842            | your mail... |
  1148.