RS232.MOD 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  1. (* Release 3.10 *)
  2. (*-------------------------------------------------------------------------*
  3. * *
  4. * RS232.MOD - COMMS Toolkit serial i/o *
  5. * *
  6. * COPYRIGHT (C) 1988..1992 Clarion Software Corporation. *
  7. * All Rights Reserved *
  8. * *
  9. *--------------------------------------------------------------------------*)
  10. IMPLEMENTATION MODULE RS232;
  11. (*%F _OS2*)
  12. (* DOS Version *)
  13. (*# check(index=>off)*)
  14. IMPORT Lib,SYSTEM;
  15. CONST
  16. BuffSize = 1024;
  17. LowWater = BuffSize DIV 4; (* Buffer Level when Rx is enabled *)
  18. HighWater = LowWater * 3; (* Buffer Level when Rx is disabled *)
  19. ICOCW2 = 20H; (* int. controller op. control word 2 *)
  20. ICOCW1 = 21H; (* int. controller op. control word 1 (mask) *)
  21. (* Intel 8250 register address offsets *)
  22. RBR = 0; (* receive buffer register *)
  23. THR = 0; (* transmitter holding register *)
  24. DLL = 0; (* divisor latch low (least significant) *)
  25. DLM = 1; (* divisor latch high (most significant) *)
  26. IER = 1; (* interrupt enable register *)
  27. IIR = 2; (* interrupt identification register *)
  28. LCR = 3; (* line control register *)
  29. MCR = 4; (* modem control register *)
  30. LSR = 5; (* line status register *)
  31. MSR = 6; (* modem status register *)
  32. TYPE
  33. StopStart = (Stop,Start);
  34. RingBuffer = RECORD
  35. rptr,wptr : CARDINAL;
  36. Buff : ARRAY[0..BuffSize-1] OF CHAR;
  37. END;
  38. VAR
  39. (*# save, data(volatile=>on)*) (* Modified asyncronously - so dont keep in registers! *)
  40. TxIdle,NoTx : BOOLEAN;
  41. RxBuff,TxBuff : RingBuffer;
  42. RxCount : CARDINAL; (* a count of the chars currently in the Rx buffer *)
  43. (*# restore *)
  44. FlowCtrlType : FlowControls;
  45. Installed,
  46. DCD,CTS,Dummy : BOOLEAN;
  47. OldVector : FarADDRESS;
  48. Continue : PROC;
  49. (*.............................................*)
  50. PROCEDURE Pause():BOOLEAN;
  51. BEGIN
  52. (* This procedure just wastes a little time so that chips have a *)
  53. (* little time to recover between IO calls. *)
  54. RETURN TRUE; (* do something so that the compiler doesnt optimise *)
  55. END Pause; (* this procedure out! *)
  56. (*.............................................*)
  57. PROCEDURE GetVector(Int:WORD):FarADDRESS;
  58. VAR
  59. r : SYSTEM.Registers;
  60. BEGIN
  61. r.AH := 35H;
  62. r.AL := BYTE(Int);
  63. Lib.Intr(r,21H); (* DOS Interrupt *)
  64. RETURN [r.ES:r.BX];
  65. END GetVector;
  66. PROCEDURE SetVector(Int:WORD;Addr:FarADDRESS);
  67. VAR
  68. r : SYSTEM.Registers;
  69. BEGIN
  70. r.AH := 25H;
  71. r.AL := BYTE(Int);
  72. r.DS := SYSTEM.Seg(Addr^);
  73. r.DX := SYSTEM.Ofs(Addr^);
  74. Lib.Intr(r,21H); (* DOS Interrupt *)
  75. END SetVector;
  76. PROCEDURE SelectPort(Port:PortNos);
  77. BEGIN
  78. IF Installed THEN
  79. UnInstall;
  80. END; (*IF*)
  81. CASE Port OF
  82. 1 : Base:=3F8H;
  83. IntLevel:=4; |
  84. 2 : Base:=2F8H;
  85. IntLevel:=3; |
  86. 3 : Base:=3E8H;
  87. IntLevel:=4; |
  88. 4 : Base:=2E8H;
  89. IntLevel:=3; |
  90. END;
  91. END SelectPort;
  92. (*.............................................*)
  93. PROCEDURE InitPort(Baud:CARDINAL;DataBits:Bits;StopBits:Stops;Parity:ParityCodes);
  94. VAR
  95. Divisor : CARDINAL;
  96. LCRValue : SHORTCARD;
  97. BEGIN
  98. SYSTEM.Out(Base+LCR,80H); (* turn on DLAB to access the divisor *)
  99. Divisor := CARDINAL(115200 DIV LONGCARD(Baud)); (* set the divisor *)
  100. SYSTEM.Out(Base+DLL,SHORTCARD(Divisor MOD 256));
  101. SYSTEM.Out(Base+DLM,SHORTCARD(Divisor DIV 256));
  102. (* turn off the DLAB and set the new comm. parameters *)
  103. LCRValue := SHORTCARD(ORD(Parity)*8+(StopBits-1)*4+(DataBits-5));
  104. SYSTEM.Out(Base+LCR,LCRValue);
  105. DCD := 7 IN BITSET(CARDINAL(SYSTEM.In(Base+MSR)));
  106. Dummy := Pause();
  107. CTS := 4 IN BITSET(CARDINAL(SYSTEM.In(Base+MSR)));
  108. END InitPort;
  109. (*.............................................*)
  110. PROCEDURE TxInt;
  111. VAR
  112. tmp : CARDINAL;
  113. BEGIN
  114. WITH TxBuff DO
  115. IF (rptr=wptr) OR (NoTx) THEN
  116. TxIdle := TRUE
  117. ELSE
  118. TxIdle := FALSE;
  119. tmp := rptr;
  120. rptr := (rptr+1) MOD BuffSize;
  121. SYSTEM.Out(Base+THR,SHORTCARD(Buff[tmp]));
  122. END;
  123. END;
  124. END TxInt;
  125. (*.............................................*)
  126. PROCEDURE SetFlowControl(Which:FlowControls);
  127. BEGIN
  128. FlowCtrlType := Which;
  129. IF Which=RtsCts THEN
  130. NoTx := NOT CTS;
  131. ELSE
  132. NoTx := FALSE;
  133. END;
  134. IF TxIdle THEN
  135. TxInt
  136. END;
  137. END SetFlowControl;
  138. (*.............................................*)
  139. PROCEDURE ControlFlow(Which:StopStart);
  140. VAR
  141. Ch : CHAR;
  142. BEGIN
  143. IF FlowCtrlType=XonXoff THEN
  144. IF Which=Stop THEN
  145. Ch:=XOFF
  146. ELSE
  147. Ch:=XON
  148. END;
  149. SerialWrite(Ch,1);
  150. ELSIF FlowCtrlType=RtsCts THEN
  151. IF Which=Stop THEN
  152. Ch:=CHR(09H)
  153. ELSE
  154. Ch:=CHR(0BH)
  155. END;
  156. SYSTEM.Out(Base+MCR,SHORTCARD(Ch));
  157. END;
  158. END ControlFlow;
  159. (*.............................................*)
  160. (*# save, call(interrupt=>on, reg_saved=>(ax,bx,cx,dx,si,di,ds,es,st1,st2),reg_param=>(),same_ds=>off)*)
  161. (* NB, The interrupt pragma sets up the registers as parameters to the *)
  162. (* procedure in the order defined below. This allows easy access to *)
  163. (* the entry registers. *)
  164. PROCEDURE SerialInt;
  165. VAR
  166. c : CHAR;
  167. IIRReg : SHORTCARD;
  168. i : CARDINAL;
  169. b,pic : BITSET;
  170. BEGIN
  171. (* Disable serial ints at the interrupt controller *)
  172. pic := BITSET(SYSTEM.In(ICOCW1));
  173. INCL(pic,IntLevel);
  174. SYSTEM.Out(ICOCW1,SHORTCARD(pic));
  175. SYSTEM.EI; (* now that serial ints are disabled we can allow other int types *)
  176. LOOP
  177. IIRReg := SYSTEM.In(Base+IIR);
  178. IF ODD(IIRReg) THEN
  179. EXIT;
  180. END;
  181. CASE IIRReg DIV 2 OF
  182. 0 : (* Modem Status - get CTS *)
  183. b := BITSET(SYSTEM.In(Base+MSR));
  184. IF 0 IN b THEN (* CTS has changed state *)
  185. CTS := (4 IN b);
  186. IF FlowCtrlType=RtsCts THEN
  187. NoTx := (NOT CTS);
  188. IF TxIdle THEN
  189. TxInt;
  190. END;
  191. END;
  192. END;
  193. IF 3 IN b THEN (* DCD has changed state *)
  194. DCD := (7 IN b);
  195. END; |
  196. 1 : (* TxReady *)
  197. TxInt; |
  198. 2 : (* RxReady *)
  199. c := CHAR(SYSTEM.In(Base));
  200. IF ((c=XOFF) OR (c=XON)) AND (FlowCtrlType=XonXoff) THEN
  201. NoTx := (c=XOFF);
  202. IF TxIdle THEN
  203. TxInt;
  204. END;
  205. ELSE
  206. WITH RxBuff DO
  207. Buff[wptr] := CHAR(SYSTEM.In(Base));
  208. wptr := (wptr+1) MOD BuffSize;
  209. END;
  210. SYSTEM.DI;
  211. INC(RxCount);
  212. SYSTEM.EI;
  213. IF RxCount=HighWater THEN
  214. ControlFlow(Stop);
  215. END;
  216. END; |
  217. 3 : (* Rx Line Status - check for error and clear *)
  218. b := BITSET(SYSTEM.In(Base+LSR));
  219. b := BITSET(SYSTEM.In(Base));
  220. (* clear rcv reg also *) |
  221. END;
  222. END;
  223. EXCL(pic,IntLevel); (* reenable serial ints at the int controller *)
  224. SYSTEM.Out(ICOCW1,SHORTCARD(pic));
  225. SYSTEM.Out(ICOCW2,SHORTCARD(60H+IntLevel)); (* send specific EOI to 8259 *)
  226. END SerialInt;
  227. (*# restore *)
  228. (*.............................................*)
  229. PROCEDURE Install;
  230. VAR
  231. x,IIRReg : SHORTCARD;
  232. b : BITSET;
  233. BEGIN
  234. UnInstall;
  235. SYSTEM.DI;
  236. SYSTEM.Out(Base+IER,0); (* disable serial ints while we set things up. *)
  237. SYSTEM.EI;
  238. SetVector(IntLevel+8,FarADR(SerialInt));
  239. RxBuff.rptr := 0; (* initialise ring buffer pointers & other vars *)
  240. RxBuff.wptr := 0;
  241. TxBuff.rptr := 0;
  242. TxBuff.wptr := 0;
  243. RxCount := 0;
  244. TxIdle := TRUE;
  245. NoTx := FALSE;
  246. SYSTEM.Out(Base+MCR,10H); (* put 8250 UART into loopback mode *)
  247. REPEAT
  248. b := BITSET(SYSTEM.In(Base+LSR)); (* wait for tx path to empty *)
  249. UNTIL (6 IN b);
  250. WHILE ODD(SYSTEM.In(Base+LSR)) DO (* clear out rx path *)
  251. x := SYSTEM.In(Base);
  252. END;
  253. Dummy := Pause();
  254. SYSTEM.Out(Base+IER,0FH); (* enable all four types of serial interrupt *)
  255. Dummy := Pause();
  256. SYSTEM.Out(Base+MCR,0BH); (* Raise DTR,RTS and OUT2 *)
  257. Dummy := Pause();
  258. LOOP
  259. Dummy := Pause();
  260. (* force reads from int. identification reg until it clears *)
  261. IIRReg := SYSTEM.In(Base+IIR);
  262. IF ODD(IIRReg) THEN
  263. EXIT;
  264. END;
  265. CASE IIRReg DIV 2 OF
  266. 0 : x:=SYSTEM.In(Base+MSR); |
  267. 1 : (* TxIdle -- ignore *) |
  268. 2 : x:=SYSTEM.In(Base); |
  269. 3 : (* Rx Line Status *)
  270. x:=SYSTEM.In(Base+LSR);
  271. x:=SYSTEM.In(Base); |
  272. END;
  273. END;
  274. DCD := 7 IN BITSET(CARDINAL(SYSTEM.In(Base+MSR)));
  275. Dummy := Pause();
  276. CTS := 4 IN BITSET(CARDINAL(SYSTEM.In(Base+MSR)));
  277. NoTx := (NOT CTS) AND (FlowCtrlType=RtsCts);
  278. (* Enable level 4 or level 3 interrupt in interrupt controller *)
  279. b := BITSET(SYSTEM.In(ICOCW1));
  280. EXCL(b,IntLevel);
  281. Dummy := Pause();
  282. SYSTEM.Out(ICOCW1,SHORTCARD(b));
  283. Dummy := Pause();
  284. SYSTEM.Out(ICOCW2,SHORTCARD(IntLevel)+60H); (* EOI to int controller to clr it *)
  285. Installed := TRUE;
  286. END Install;
  287. (*.............................................*)
  288. PROCEDURE CarrierDetect():BOOLEAN;
  289. BEGIN
  290. RETURN DCD;
  291. END CarrierDetect;
  292. (*.............................................*)
  293. PROCEDURE UnInstall;
  294. VAR
  295. b : BITSET;
  296. BEGIN
  297. (* Disable level 4 or level 3 interrupt in interrupt controller *)
  298. b := BITSET(SYSTEM.In(ICOCW1));
  299. INCL(b,IntLevel);
  300. Dummy := Pause();
  301. SYSTEM.Out(ICOCW1,SHORTCARD(b));
  302. Dummy := Pause();
  303. SYSTEM.Out(Base+IER,0); (* Disable interrupt from 8250 *)
  304. Dummy := Pause();
  305. SYSTEM.Out(Base+MCR,0); (* drop DTR and RTS *)
  306. SetVector(IntLevel+8,OldVector);
  307. Installed := FALSE;
  308. END UnInstall;
  309. (*.............................................*)
  310. (*# save,call(o_a_copy=>off)*)
  311. PROCEDURE SerialWrite(b:ARRAY OF CHAR; Lnth:CARDINAL);
  312. VAR
  313. c : CHAR;
  314. i,neww : CARDINAL;
  315. BEGIN
  316. IF Hooked THEN
  317. TxHook(b,Lnth);
  318. END; (*IF*)
  319. i:=0;
  320. WHILE i<Lnth DO
  321. c := b[i];
  322. WITH TxBuff DO
  323. neww := (wptr+1) MOD BuffSize;
  324. WHILE (neww=rptr) DO
  325. (* wait if buffer is about to overflow *)
  326. END;
  327. Buff[wptr] := c;
  328. wptr := neww;
  329. END;
  330. IF TxIdle THEN
  331. TxInt;
  332. END;
  333. INC(i);
  334. END;
  335. END SerialWrite;
  336. (*# restore *)
  337. (*.............................................*)
  338. PROCEDURE SerialRead(VAR c:CHAR; t:CARDINAL):BOOLEAN;
  339. VAR
  340. t2 : CARDINAL;
  341. BEGIN
  342. WITH RxBuff DO
  343. IF (t>0) AND (rptr=wptr) THEN
  344. (* if t>0 then wait "t" tenth/secs for char to arrive *)
  345. WHILE (rptr=wptr) AND (t>0) DO
  346. t2:=50;
  347. WHILE (rptr=wptr) AND (t2>0) DO
  348. Lib.Delay(2);
  349. DEC(t2);
  350. END;
  351. DEC(t);
  352. END;
  353. END;
  354. IF Hooked THEN
  355. RxHook(c);
  356. END; (*IF*)
  357. IF rptr=wptr THEN
  358. RETURN FALSE;
  359. ELSE
  360. c := Buff[rptr];
  361. rptr := (rptr+1) MOD BuffSize;
  362. SYSTEM.DI;
  363. DEC(RxCount);
  364. SYSTEM.EI;
  365. IF RxCount=LowWater THEN
  366. ControlFlow(Start);
  367. END;
  368. RETURN TRUE
  369. END;
  370. END;
  371. END SerialRead;
  372. (*.............................................*)
  373. PROCEDURE FlushInBuf;
  374. BEGIN
  375. SYSTEM.DI;
  376. RxBuff.rptr := 0;
  377. RxBuff.wptr := 0;
  378. SYSTEM.EI;
  379. END FlushInBuf;
  380. (*.............................................*)
  381. PROCEDURE SetBreak(Tenths:CARDINAL);
  382. VAR
  383. b : BITSET;
  384. BEGIN
  385. b := BITSET(SYSTEM.In(Base+LCR));
  386. Dummy := Pause();
  387. SYSTEM.Out(Base+LCR,SHORTCARD(b+{6}));
  388. Lib.Delay(Tenths*100);
  389. SYSTEM.Out(Base+LCR,SHORTCARD(b));
  390. END SetBreak;
  391. (*.............................................*)
  392. PROCEDURE AddTxHook(Hook:TxHookProc;VAR OldHook:TxHookProc);
  393. BEGIN
  394. OldHook := TxHook;
  395. TxHook := Hook;
  396. END AddTxHook;
  397. PROCEDURE AddRxHook(Hook:RxHookProc;VAR OldHook:RxHookProc);
  398. BEGIN
  399. OldHook := RxHook;
  400. RxHook := Hook;
  401. END AddRxHook;
  402. PROCEDURE TermProc;
  403. BEGIN
  404. UnInstall();
  405. Continue();
  406. END TermProc;
  407. (*................................................*)
  408. BEGIN (*RS232*)
  409. Base := 3F8H;
  410. IntLevel := 4;
  411. FlowCtrlType := RtsCts;
  412. OldVector := GetVector(IntLevel+8);
  413. Lib.Terminate(TermProc,Continue);
  414. Hooked := FALSE;
  415. RxHook := NULLPROC;
  416. TxHook := NULLPROC;
  417. Installed := FALSE;
  418. END RS232.
  419. (*%E*)
  420. (*%T _OS2*)
  421. (* OS/2 version *)
  422. IMPORT Dos;
  423. TYPE
  424. Byte = SHORTCARD[0..7];
  425. ByteSet = SET OF BYTE;
  426. DCBType = RECORD
  427. write,read : CARDINAL;
  428. flag1,flag2,
  429. flag3 : ByteSet;
  430. error,break,
  431. xon,xoff : CHAR;
  432. END;
  433. VAR
  434. PortNum : CARDINAL;
  435. Handle : CARDINAL;
  436. CurrBaud : CARDINAL;
  437. CurrData : Bits;
  438. CurrStop : Stops;
  439. CurrParity : ParityCodes;
  440. CurrFlow : FlowControls;
  441. CurrTime : CARDINAL;
  442. Locked,Installed : BOOLEAN;
  443. Null : FarADDRESS;
  444. PROCEDURE SelectPort(Port:PortNos);
  445. BEGIN
  446. IF NOT Locked THEN
  447. IF Installed THEN
  448. UnInstall;
  449. END; (*IF*)
  450. PortNum := Port;
  451. END;
  452. END SelectPort;
  453. PROCEDURE InitPort2;
  454. TYPE
  455. ParsType = ARRAY ParityCodes OF SHORTCARD;
  456. CONST
  457. Pars = ParsType(0,1,0,2,0,3,0,4);
  458. VAR
  459. char : RECORD
  460. data,
  461. parity,
  462. stop : SHORTCARD;
  463. END;
  464. BEGIN
  465. Dos.DevIOCtl(Null,FarADR(CurrBaud),41H,1,Handle);
  466. WITH char DO
  467. data := SHORTCARD(CurrData);
  468. parity := Pars[CurrParity];
  469. IF CurrStop = 2 THEN
  470. stop := 2;
  471. ELSE
  472. stop := 0;
  473. END;
  474. END;
  475. Dos.DevIOCtl(Null,FarADR(char),42H,1,Handle);
  476. END InitPort2;
  477. PROCEDURE InitPort(Baud:CARDINAL;DataBits:Bits;StopBits:Stops;Parity:ParityCodes);
  478. BEGIN
  479. IF NOT Locked THEN
  480. CurrBaud := Baud;
  481. CurrData := DataBits;
  482. CurrStop := StopBits;
  483. CurrParity := Parity;
  484. IF Handle # MAX(CARDINAL) THEN
  485. InitPort2;
  486. END;
  487. END;
  488. END InitPort;
  489. PROCEDURE SetFlowControl(Which:FlowControls);
  490. VAR
  491. dcb : DCBType;
  492. BEGIN
  493. IF NOT Locked THEN
  494. CurrFlow := Which;
  495. IF Handle # MAX(CARDINAL) THEN
  496. Dos.DevIOCtl(FarADR(dcb),Null,73H,1,Handle);
  497. WITH dcb DO
  498. EXCL(flag2,7);
  499. INCL(flag2,6);
  500. EXCL(flag2,1);
  501. EXCL(flag2,0);
  502. CASE Which OF
  503. NoFlowControl : ; (* already set *) |
  504. RtsCts : INCL(flag2,7);
  505. EXCL(flag2,6); |
  506. XonXoff : INCL(flag2,1);
  507. INCL(flag2,0); |
  508. END;
  509. END;
  510. Dos.DevIOCtl(Null,FarADR(dcb),53H,1,Handle);
  511. END;
  512. END;
  513. END SetFlowControl;
  514. PROCEDURE SetRdTime(time:CARDINAL);
  515. VAR
  516. dcb : DCBType;
  517. BEGIN
  518. Dos.DevIOCtl(FarADR(dcb),Null,73H,1,Handle);
  519. WITH dcb DO
  520. INCL(flag3,1);
  521. IF time = 0 THEN
  522. INCL(flag3,2);
  523. read := 0;
  524. ELSE
  525. IF time = MAX(CARDINAL) THEN
  526. read := 0;
  527. ELSE
  528. read := time*10-1;
  529. END;
  530. EXCL(flag3,2);
  531. END;
  532. END;
  533. Dos.DevIOCtl(Null,FarADR(dcb),53H,1,Handle);
  534. CurrTime := time;
  535. END SetRdTime;
  536. PROCEDURE SetWrTime(time:CARDINAL);
  537. VAR
  538. dcb : DCBType;
  539. BEGIN
  540. Dos.DevIOCtl(FarADR(dcb),Null,73H,1,Handle);
  541. WITH dcb DO
  542. IF time = 0 THEN
  543. INCL(flag3,0);
  544. ELSE
  545. IF time = MAX(CARDINAL) THEN
  546. write := 0;
  547. ELSE
  548. write := time*10-1;
  549. END;
  550. EXCL(flag3,0);
  551. END;
  552. END;
  553. Dos.DevIOCtl(Null,FarADR(dcb),53H,1,Handle);
  554. END SetWrTime;
  555. PROCEDURE UnInstall2;
  556. VAR
  557. tmp : CARDINAL;
  558. BEGIN
  559. IF Handle # MAX(CARDINAL) THEN
  560. tmp := Handle;
  561. Handle := MAX(CARDINAL);
  562. SetRdTime(MAX(CARDINAL));
  563. SetWrTime(MAX(CARDINAL));
  564. Dos.Close(tmp);
  565. END;
  566. END UnInstall2;
  567. PROCEDURE Install;
  568. TYPE
  569. NamesType = ARRAY PortNos OF ARRAY[0..4] OF CHAR;
  570. CONST
  571. Names = NamesType('COM1'+0C,'COM2'+0C,'COM3'+0C,'NUL'+0C);
  572. VAR
  573. r : CARDINAL;
  574. a : CARDINAL;
  575. BEGIN
  576. Dos.EnterCritSec();
  577. IF NOT Locked THEN
  578. Locked := TRUE;
  579. Dos.ExitCritSec();
  580. UnInstall2;
  581. r := Dos.Open(Names[PortNum],Handle,a,0,0,1,CARDINAL({13,7,4,1}),0);
  582. IF r = 0 THEN
  583. InitPort2;
  584. SetFlowControl(CurrFlow);
  585. SetRdTime(MAX(CARDINAL));
  586. SetWrTime(600);
  587. Installed := TRUE;
  588. ELSE
  589. Handle := MAX(CARDINAL);
  590. END;
  591. Locked := FALSE;
  592. ELSE
  593. Dos.ExitCritSec();
  594. END;
  595. END Install;
  596. PROCEDURE CarrierDetect():BOOLEAN;
  597. VAR
  598. r : CARDINAL;
  599. mcis : ByteSet;
  600. BEGIN
  601. IF NOT Locked AND (Handle # MAX(CARDINAL)) THEN
  602. r := Dos.DevIOCtl(FarADR(mcis),Null,67H,1,Handle);
  603. RETURN (r = 0) AND (7 IN mcis);
  604. ELSE
  605. RETURN FALSE;
  606. END;
  607. END CarrierDetect;
  608. PROCEDURE UnInstall;
  609. VAR
  610. tmp : CARDINAL;
  611. BEGIN
  612. Dos.EnterCritSec();
  613. IF NOT Locked THEN
  614. Locked := TRUE;
  615. Dos.ExitCritSec();
  616. UnInstall2;
  617. Locked := FALSE;
  618. Installed := FALSE;
  619. ELSE
  620. Dos.ExitCritSec();
  621. END;
  622. END UnInstall;
  623. (*# save, call(o_a_copy => off), check(index=>off) *)
  624. PROCEDURE SerialWrite(b:ARRAY OF CHAR; Lnth:CARDINAL);
  625. VAR
  626. cnt,pos : CARDINAL;
  627. BEGIN
  628. IF NOT Locked AND (Handle # MAX(CARDINAL)) THEN
  629. IF Hooked THEN
  630. TxHook(b,Lnth);
  631. END; (*IF*)
  632. pos := 0;
  633. WHILE Lnth-pos # 0 DO
  634. Dos.Write(Handle,FarADR(b[pos]),Lnth-pos,cnt);
  635. INC(pos,cnt);
  636. END;
  637. END;
  638. END SerialWrite;
  639. (*# restore *)
  640. PROCEDURE SerialRead(VAR c:CHAR; t:CARDINAL):BOOLEAN;
  641. VAR
  642. r : CARDINAL;
  643. len : CARDINAL;
  644. BEGIN
  645. IF NOT Locked AND (Handle # MAX(CARDINAL)) THEN
  646. IF t # CurrTime THEN
  647. SetRdTime(t);
  648. END;
  649. r := Dos.Read(Handle,FarADR(c),1,len);
  650. IF Hooked THEN
  651. RxHook(c);
  652. END; (*IF*)
  653. RETURN (r = 0) AND (len # 0);
  654. ELSE
  655. RETURN FALSE;
  656. END;
  657. END SerialRead;
  658. PROCEDURE FlushInBuf;
  659. VAR
  660. Return : RECORD
  661. Chars,
  662. QSize : CARDINAL;
  663. END; (*RECORD*)
  664. i : CARDINAL;
  665. void : ARRAY[0..128] OF BYTE;
  666. BEGIN
  667. Dos.DevIOCtl(FarADR(Return),Null,68H,1,Handle);
  668. WHILE Return.Chars > 0 DO
  669. IF Return.Chars > SIZE(void) THEN
  670. i := SIZE(void);
  671. ELSE
  672. i := Return.Chars;
  673. END; (*IF*)
  674. Dos.Read(Handle,FarADR(void),i,i);
  675. DEC(Return.Chars,i);
  676. END; (*WHILE*)
  677. END FlushInBuf;
  678. PROCEDURE SetBreak(Tenths:CARDINAL);
  679. VAR
  680. err : CARDINAL;
  681. BEGIN
  682. IF NOT Locked AND (Handle # MAX(CARDINAL)) THEN
  683. Dos.DevIOCtl(FarADR(err),Null,4BH,1,Handle);
  684. Dos.Sleep(VAL(LONGCARD,Tenths)*100);
  685. Dos.DevIOCtl(FarADR(err),Null,45H,1,Handle);
  686. END;
  687. END SetBreak;
  688. PROCEDURE AddTxHook(Hook:TxHookProc;VAR OldHook:TxHookProc);
  689. BEGIN
  690. OldHook := TxHook;
  691. TxHook := Hook;
  692. END AddTxHook;
  693. PROCEDURE AddRxHook(Hook:RxHookProc;VAR OldHook:RxHookProc);
  694. BEGIN
  695. OldHook := RxHook;
  696. RxHook := Hook;
  697. END AddRxHook;
  698. BEGIN (*RS232*)
  699. Handle := MAX(CARDINAL);
  700. CurrBaud := 1200;
  701. CurrData := 8;
  702. CurrStop := 1;
  703. CurrParity := None;
  704. CurrFlow := RtsCts;
  705. Locked := FALSE;
  706. Null := FarNIL;
  707. SelectPort(1);
  708. Hooked := FALSE;
  709. RxHook := NULLPROC;
  710. TxHook := NULLPROC;
  711. Installed := FALSE;
  712. END RS232.
  713. (*%E*)
  714.