home *** CD-ROM | disk | FTP | other *** search
- unit COM_MGR;
- (* Manager of the COMx ports, rewritten from the illcoded ScenicSoft
- DEVICEIO units and, more usefully, from IBMCOM, a freeware program by
- Wayne E. Conrad (CompuServe 71631,210 or at (602) 484-9356 @ 2400 baud).
-
- The main differences from Conrad's approach are
-
- (1) Instead of separate calls to set the speed, parity, and so
- on, setup parameters here are all pre-loaded into a record, then
- set into the UART during initialization.
-
- (2) This routine will comply with various uses of the DSR and
- XOFF/XON protocols. In particular,
-
- If NEED_DSR is true, then this routine will hang until
- the attached device raises the DSR line.
- If USING_DTR is true, then this routine will lower DTR
- whenever its own buffers are getting full.
- If USING_XOFF is true, then this routine will refrain from
- transmissions between receiving an XOFF and receiving an XON,
- and it will send XOFF & XON as its own buffers become full and
- empty, respectively. The implementation allows for a degree of
- paranoia; if XOFF/XON characters are getting lost, with consequent
- buffer overflow or deadlock, then simple changes can allow each
- XOFF and/or XON to be sent more than once. Also, one may cause
- long XOFF waits to be announced on the screen, and then evaded
- with the entry of a carriage return.
-
- (3) The COM_WRITE_STRING here makes use of a fixed external buffer
- that is provided by the much larger application package in which this
- unit is utilized.
-
- (4) Various monitoring records (count of characters dropped, count
- of high water mark in input buffer, etc.) are retained for optional
- display at termination.
-
- (5) Because port addresses and interrupt assignments are not well
- established beyond COM2, only COM1 and COM2 are implemented here;
- the implementation allows obvious extension for additional ports.
- *)
-
- interface
- const
- COM_VERSION = 1017;
-
- (* eject *)
- type
- parity_option = (EVEN_PARITY, MARK_PARITY, NO_PARITY, ODD_PARITY,
- SPACE_PARITY);
- port_option = (COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8);
- stop_bits = (ONE_STOP_BIT, MORE_STOP_BITS);
-
- com_config_record = record
- FILED_VERSION (* version control for possible file *): integer;
- NEED_DSR (* if false, charge on regardless *),
- USING_DTR (* hardware handshake *),
- USING_XOFF (* software handshake *): boolean;
- THESE_DATA_BITS (* parity & data bits interdependent *): byte;
- THIS_BAUD (* 2 <= THIS_BAUD <= 115200 *): longint;
- THIS_PARITY (* parity & data-bits interdependent *): parity_option;
- THIS_PORT (* most of these not implemented *): port_option;
- THESE_STOP_BITS (* interpretation baud-dependent *): stop_bits
- end (* com_config_record *);
-
- var
- COM_CONFIGURATION (* from HW_COLD_START *): com_config_record;
- COM_INPUT_WAITING (** # of char in input buffer *),
- COM_OUTPUT_WAITING (** # of char in output buffer *): integer;
-
- function COM_CARRIER_PRESENT: boolean;
- procedure COM_LOWER_DTR;
- procedure COM_RAISE_DTR;
- function COM_READ: char;
- function COM_TX_READY: boolean;
- procedure COM_WRITE_CH(CH: char);
- procedure COM_WRITE_STRING;
- procedure INIT_COM_MGR;
- procedure TERM_COM_MGR;
-
- implementation
- uses
- DOS (* GetIntVec, Intr, registers, SetIntVec *),
- CRT (* ClrEol, GotoXY, KeyPressed, WhereY *),
- SCRN_MGR (* DEBUG, ERROR_EXIT, LOUD_WRITE, PAUSE *),
- IOERROR (* CHARS_WAITING, INIT_IOERROR, WAITING_CHAR *);
-
- (* eject *)
- const
- CR = #13;
- X_OFF = #19;
- X_ON = #17;
-
- DB_TRIGGER = 67;
-
- BAUD_RATE_DIVIDEND = 115200;
-
- RCV_BUFFER_SIZE = 1024;
- LAST_RCV_CHAR = 1023 (* derivative *);
- GETTING_FULL = 800 (* loosely derivative *);
- GETTING_EMPTY = 200 (* loosely derivative *);
- TX_BUFFER_SIZE = 256;
- LAST_TX_CHAR = 255 (* derivative *);
-
- CLI = $FA;
- STI = $FB;
-
- IRQ_BASE = 8;
-
- (* Interrupt enable register:
- bits 7-4 0000
- bit 3 1 = enable change-in-modem-status interrupt
- bit 2 1 = enable line-status interrupt
- bit 1 1 = enable transmit-register-empty interrupt
- bit 0 1 = enable data-available interrupt *)
- IER_ENB_TX_EMPTY = 2;
- IER_ENB_RCV_CHAR = 1;
-
- (* Line control register
- bit 7: 0 normal
- 1 address baud rate divisor registers
- bit 6: 0 break disabled
- 1 break enabled
- bits 5-3: 000 no parity
- 001 odd parity
- 010 no parity
- 011 even parity
- 100 no parity
- 101 parity always 1
- 110 no parity
- 111 parity always 0
- bit 2: 0 1 stop bit
- 1 1.5 stop bits if 5 bits/character or
- 2 stop bits if 6-8 bits/character
- bits 1-0: 00 5 bits/character
- 01 6 bits/character
- 10 7 bits/character
- 11 8 bits/character *)
- LCR_SET_BAUD = $80;
- LCR_PARITY_BITS: array[EVEN_PARITY .. SPACE_PARITY] of byte =
- ($18, $28, 0, 8, $38);
- LCR_STOP_BITS: array[ONE_STOP_BIT .. MORE_STOP_BITS] of byte = (0, 4);
- LCR_DATA_BITS: array[5 .. 8] of byte = (0, 1, 2, 3);
- (* eject *)
- (* Modem control register
- bits 7-5: 000
- bit 4: 0 normal
- 1 loop back test
- bit 3: 1 interrupts to system bus, user-designated output: OUT2
- bit 2: user-designated output, OUT1
- bit 1: 1 activate rts
- bit 0: 1 activate dtr *)
- MCR_DTR = 1;
- MCR_OUT2 = 8;
- MCR_RTS = 2;
-
- (* Modem status register
- bit 7: 1 receive line signal detect
- bit 6: 1 ring indicator (all PCs except PCjr)
- bit 5: 1 dsr
- bit 4: 1 cts
- bit 3: 1 receive line signal detect has changed state
- bit 2: 1 ring indicator has changed state (all PCs except PCjr)
- bit 1: 1 dsr has changed state
- bit 0: 1 cts has changed state *)
- MSR_CARRIER = $80;
- MSR_DSR = $20;
-
- PIC_EOI_PORT = $20;
- PIC_IE_PORT = $21;
-
- type
- rcv_record = record
- NEXT_IN (** next slot for an incoming character *),
- NEXT_OUT (* next source for COM_READ *): integer;
- BUFFER: array[0 .. LAST_RCV_CHAR] of byte
- end (* rcv_record *);
-
- tx_record = record
- NEXT_IN (* next sink for COM_WRITE_CH *),
- NEXT_OUT (** next source for port *): integer;
- BUFFER: array[0 .. LAST_TX_CHAR] of byte
- end (* tx_record *);
-
- (* eject *)
- var (** variables changed by interrupt *)
- EVER_ACTIVE (* if false, omit buff-use report *),
- INITIALIZED (* worth running termination code *),
- XOFF_RECEIVED (** XOFF rec'd from modem/printer *),
- XOFF_SENT (** XOFF sent to modem/printer *): boolean;
- IRQ_USED (* int used by THIS_PORT *),
- I8259_BIT (* 8259 int mask of THIS_PORT *),
- OLD_IER (* int enb reg before init *),
- OLD_I8259_MASK (* 8259 mask before initializing *),
- OLD_MCR (* modem ctl reg before init *),
- STACKED_XOFFS (** next chars to be sent *),
- STACKED_XONS (** next chars to be sent *): byte;
- DROPPED (** dropped input chars *),
- INPUT_ZENITH (** max ever in input buffer *): integer;
- WAITING_FOR_DSR (* cycles waiting to write *),
- WAITING_FOR_XON (* cycles waiting for receiver *): longint;
- OLD_IRQ_INT_PROC (* previous int handler for port *),
- SAVE_EXIT (* for exit chain *): pointer;
- RECEIVE_BUFFER (* complex once on heap *): rcv_record;
- TRANSMIT_BUFFER (* complex once on heap *): tx_record;
- DATA_REGISTER (* subscript of PORT array *),
- INT_ENABLE_REGISTER (* subscript of PORT array *),
- INT_ID_REGISTER (* subscript of PORT array *),
- LINE_CTL_REGISTER (* subscript of PORT array *),
- MODEM_CTL_REGISTER (* subscript of PORT array *),
- MODEM_STATUS_REGISTER (* subscript of PORT array *),
- LINE_STATUS_REGISTER (* subscript of PORT array *): word;
-
- procedure DISABLE_INTERRUPTS; inline(CLI);
- procedure ENABLE_INTERRUPTS; inline(STI);
-
- function COM_CARRIER_PRESENT: boolean;
- (* Return true iff carrier is present. *)
-
- begin (* COM_CARRIER *)
- COM_CARRIER_PRESENT :=
- ((port[MODEM_STATUS_REGISTER] and MSR_CARRIER) > 0)
- end (* COM_CARRIER *);
-
- procedure COM_INT_HANDLER; interrupt;
- (* Field interrupts from THIS_PORT. Operation of this ISR is
- crucially dependent upon contents received from INT_ID_REGISTER.
- In the case of a transmit-register-empty interrupt, we do a
- test of the line-status register to see if the transmit
- holding register is truly empty. Some UARTS seem to cause transmit
- interrupts when the holding register isn't empty, causing transmitted
- characters to be lost.
- If our transmit buffer is empty, then disable the transmitter to
- prevent any more transmit interrupts. This entails resetting the
- appropriate bit of the INT_ENABLE_REGISTER, as described above.
-
- If the modem is not ready for another character (not DSR), then
- hang; this is dependent upon the format of the MODEM_STATUS_REGISTER.
- Otherwise, send the character.
- *)
- (* eject *)
- const
- (* Line status register
- bit 7 0
- bit 6 1 ($40) = transmit shift register is empty
- bit 5 1 ($20) = transmit hold register is empty
- bit 4 1 ($10) = break received
- bit 3 1 ($08) = framing error received
- bit 2 1 ($04) = parity error received
- bit 1 1 ($02) = overrun error received
- bit 0 1 ($01) = data received *)
- LSR_TX_EMPTY = $20;
-
- (* Interrupt ID register
- bits 7-3 00000
- bits 2-1 00 = change-in-modem-status (lowest priority)
- bits 2-1 01 = transmit-register-empty (low priority)
- bits 2-1 10 = data available (high priority)
- bits 2-1 11 = line status (highest priority)
- bit 0 1 = no interrupt pending
- bit 0 0 = interrupt pending *)
- IID_CH_RECD = 4;
- IID_LINE_CHANGED = 6;
- IID_MODEM_CHANGED = 0;
- IID_TX_EMPTY = 2;
-
- PIC_EOI_PORT = $20;
- PIC_EOI_ARMED = $20;
-
- var
- PORT_QUIET (* bit 0 of INT_ID_REGISTER is 1 *): boolean;
- SCRATCH (* trash *): byte;
-
- (* eject *)
- procedure CHAR_RECEIVED;
- (* Kludge to reduce the size of COM_INT_HANDLER *)
-
- var
- RECEIVED_CHAR (* could be X_ON or X_OFF *): char;
-
- begin (* CHAR_RECEIVED *)
- with COM_CONFIGURATION, RECEIVE_BUFFER do
- begin (* received character *)
- RECEIVED_CHAR := chr(port[DATA_REGISTER]);
-
- if (RECEIVED_CHAR = X_OFF) and USING_XOFF then
- XOFF_RECEIVED := true
- else if (RECEIVED_CHAR = X_ON) and USING_XOFF then
- begin (* restart output *)
- XOFF_RECEIVED := false;
- if COM_OUTPUT_WAITING > 0 then
- port[INT_ENABLE_REGISTER] := port[INT_ENABLE_REGISTER] or
- IER_ENB_TX_EMPTY
- end (* restart output *)
- else if COM_INPUT_WAITING >= RCV_BUFFER_SIZE then
- inc(DROPPED)
- else
- begin (* found room *)
- BUFFER[NEXT_IN] := ord(RECEIVED_CHAR);
- inc(NEXT_IN);
- if NEXT_IN >= RCV_BUFFER_SIZE then
- NEXT_IN := 0;
- inc(COM_INPUT_WAITING);
- if COM_INPUT_WAITING > INPUT_ZENITH then
- INPUT_ZENITH := COM_INPUT_WAITING;
- if COM_INPUT_WAITING >= GETTING_FULL then
- if USING_XOFF then
- begin (* stack X_OFF *)
- STACKED_XOFFS := 1;
- STACKED_XONS := 0;
- port[INT_ENABLE_REGISTER] :=
- port[INT_ENABLE_REGISTER] or IER_ENB_TX_EMPTY;
- XOFF_SENT := true
- end (* stack X_OFF *)
- else if USING_DTR then
- port[MODEM_CTL_REGISTER] := port[MODEM_CTL_REGISTER] and
- not MCR_DTR
- end (* found room *)
- end (* received character *);
- end (* CHAR_RECEIVED *);
-
- (* eject *)
- procedure TX_EMPTY;
- (* Kludge to reduce the size of COM_INT_HANDLER *)
-
- begin (* TX_EMPTY *)
- if port[LINE_STATUS_REGISTER] and LSR_TX_EMPTY = 0 then
- (* ignore bogus interrupt *)
- else
- with TRANSMIT_BUFFER do
- begin (* probably will transmit something *)
- if COM_CONFIGURATION.NEED_DSR then
- repeat (* need data-set-ready *)
- inc(WAITING_FOR_DSR)
- until (* need data-set-ready *)
- (port[MODEM_STATUS_REGISTER] and MSR_DSR) <> 0;
-
- if STACKED_XOFFS > 0 then
- begin (* send X_OFF *)
- port[DATA_REGISTER] := ord(X_OFF);
- dec(STACKED_XOFFS)
- end (* send X_OFF *)
-
- else if STACKED_XONS > 0 then
- begin (* send X_ON *)
- port[DATA_REGISTER] := ord(X_ON);
- dec(STACKED_XONS)
- end (* send X_ON *)
-
- else if XOFF_RECEIVED or (COM_OUTPUT_WAITING = 0) then
- port[INT_ENABLE_REGISTER] := port[INT_ENABLE_REGISTER] and
- not IER_ENB_TX_EMPTY
- else
- with TRANSMIT_BUFFER do
- begin (* send character from buffer *)
- port[DATA_REGISTER] := BUFFER[NEXT_OUT];
- inc(NEXT_OUT);
- if NEXT_OUT >= TX_BUFFER_SIZE then
- NEXT_OUT := 0;
- dec(COM_OUTPUT_WAITING)
- end (* send character from buffer *)
- end (* probably will transmit something *)
- end (* TX_EMPTY *);
-
- (* eject *)
- begin (* COM_INT_HANDLER *)
- PORT_QUIET := false;
-
- repeat (* check interrupt bit *)
- case port[INT_ID_REGISTER] of
- IID_CH_RECD: CHAR_RECEIVED;
-
- IID_MODEM_CHANGED: SCRATCH := port[MODEM_STATUS_REGISTER];
-
- IID_TX_EMPTY: TX_EMPTY;
-
- IID_LINE_CHANGED: SCRATCH := port[LINE_STATUS_REGISTER]
-
- else PORT_QUIET := true
- end (* case on INT_ID_REGISTER *)
- until (* check interrupt bit *) PORT_QUIET;
-
- port[PIC_EOI_PORT] := PIC_EOI_ARMED
- end (* COM_INT_HANDLER *);
-
- procedure COM_LOWER_DTR;
- (* Lower (deactivate) the DTR line. Causes most modems to hang up. *)
-
- begin (* COM_LOWER_DTR *)
- DISABLE_INTERRUPTS;
- port[MODEM_CTL_REGISTER] := port[MODEM_CTL_REGISTER] and not MCR_DTR;
- ENABLE_INTERRUPTS
- end (* COM_LOWER_DTR *);
-
- procedure COM_RAISE_DTR;
- (* Raise (activate) the DTR line. *)
-
- begin (* COM_RAISE_DTR *)
- DISABLE_INTERRUPTS;
- port[MODEM_CTL_REGISTER] := port[MODEM_CTL_REGISTER] or MCR_DTR;
- ENABLE_INTERRUPTS
- end (* COM_RAISE_DTR *);
-
- (* eject *)
- function COM_READ: char;
- (* Wait for a character of input, then return it *)
-
- begin (* COM_READ *)
- while COM_INPUT_WAITING = 0 do
- (* spin *);
-
- with RECEIVE_BUFFER do
- begin (* use RECEIVE complex *)
- COM_READ := chr(BUFFER[NEXT_OUT]);
- inc(NEXT_OUT);
- if NEXT_OUT >= RCV_BUFFER_SIZE then
- NEXT_OUT := 0
- end (* use RECEIVE complex *);
-
- DISABLE_INTERRUPTS;
- dec(COM_INPUT_WAITING);
- ENABLE_INTERRUPTS;
-
- if COM_INPUT_WAITING <= GETTING_EMPTY then
- begin (* try to awaken sender *)
- DISABLE_INTERRUPTS;
- if XOFF_SENT then
- begin (* software handshake *)
- STACKED_XOFFS := 0;
- STACKED_XONS := 1;
- port[INT_ENABLE_REGISTER] := port[INT_ENABLE_REGISTER] or
- IER_ENB_TX_EMPTY;
- XOFF_SENT := false
- end (* software handshake *)
- else if COM_CONFIGURATION.USING_DTR then
- port[MODEM_CTL_REGISTER] := port[MODEM_CTL_REGISTER] or
- MCR_DTR;
- ENABLE_INTERRUPTS
- end (* try to awaken sender *)
- end (* COM_READ *);
-
- function COM_TX_READY: boolean;
- (* installed and DSR line raised by modem *)
-
- begin (* COM_TX_READY *)
- COM_TX_READY := INITIALIZED and
- ((not COM_CONFIGURATION.NEED_DSR) or
- ((port[MODEM_STATUS_REGISTER] and MSR_DSR) <> 0))
- end (* COM_TX_READY *);
-
- (* eject *)
- procedure COM_WRITE_CH(CH: char);
- (* Move CH to buffer for output *)
-
- var
- THIS_CALL_XOFF: longint;
-
- begin (* COM_WRITE_CH *)
- THIS_CALL_XOFF := 0;
- while XOFF_RECEIVED do
- begin (* avoid deadlock *)
- inc(WAITING_FOR_XON);
- inc(THIS_CALL_XOFF);
- if THIS_CALL_XOFF >= 100000 then
- begin (* may need intervention *)
- if DEBUG mod DB_TRIGGER = 1 then
- if THIS_CALL_XOFF = 100000 then
- LOUD_WRITE('X_OFF');
- if KeyPressed then
- if ReadKey = CR then
- XOFF_RECEIVED := false
- end (* may need intervention *)
- end (* avoid deadlock *);
-
- while COM_OUTPUT_WAITING = TX_BUFFER_SIZE do
- inc(WAITING_FOR_DSR);
-
- with TRANSMIT_BUFFER do
- begin (* with *)
- BUFFER[NEXT_IN] := ord(CH);
- inc(NEXT_IN);
- if NEXT_IN >= TX_BUFFER_SIZE then
- NEXT_IN := 0;
-
- DISABLE_INTERRUPTS;
- inc(COM_OUTPUT_WAITING);
- port[INT_ENABLE_REGISTER] := port[INT_ENABLE_REGISTER] or
- IER_ENB_TX_EMPTY;
- ENABLE_INTERRUPTS
- end (* with *)
- end (* COM_WRITE_CH *);
-
- procedure COM_WRITE_STRING;
- (* Run WAITING_CHAR[0 .. CHARS_WAITING-1] through COM_WRITE_CH *)
-
- var
- I: integer;
-
- begin (* COM_WRITE_STRING *)
- for I := 0 to CHARS_WAITING-1 do
- COM_WRITE_CH(WAITING_CHAR[I]);
- CHARS_WAITING := 0
- end (* COM_WRITE_STRING *);
-
- (* eject *)
- {$F+}
- procedure EPILOGUE;
- {$F-}
- (* Part of the great exit chain *)
-
- begin (* EPILOGUE *)
- COM_OUTPUT_WAITING := 0;
- TERM_COM_MGR;
- if DEBUG mod DB_TRIGGER = 1 then
- if EVER_ACTIVE then
- begin (* report experience *)
- writeln;
- write(INPUT_ZENITH:10, ' character');
- if INPUT_ZENITH <> 1 then
- write('s');
- writeln(' in COMx input buffer at peak.');
- write(DROPPED:10, ' COMx input character');
- if DROPPED <> 1 then
- write('s');
- writeln(' dropped.');
- writeln(WAITING_FOR_DSR:10, ' cycles waiting for DSR.');
- writeln(WAITING_FOR_XON:10, ' cycles waiting for XON.');
- PAUSE
- end (* report experience *);
- ExitProc := SAVE_EXIT
- end (* EPILOGUE *);
-
- procedure INIT_COM_MGR;
- (* Called from PSTSCRPT, only after COM_CONFIGURATION set by
- HW_COLD_START and use of real printer has been determined as
- part of HW_BEGIN_DOCUMENT *)
-
- procedure SET_SPEED_AND_PARITY;
- (* Kludge to shorten INIT_COM_MGR *)
-
- begin (* SET_SPEED_AND_PARITY *)
- with COM_CONFIGURATION do
- begin (* with *)
- if THIS_BAUD < 2 then
- THIS_BAUD := 2;
-
- DISABLE_INTERRUPTS;
- port[LINE_CTL_REGISTER] := LCR_SET_BAUD;
- portw[DATA_REGISTER] := 115200 div THIS_BAUD;
- port[LINE_CTL_REGISTER] := LCR_PARITY_BITS[THIS_PARITY] or
- LCR_STOP_BITS[THESE_STOP_BITS] or
- LCR_DATA_BITS[THESE_DATA_BITS];
- ENABLE_INTERRUPTS
- end (* with *)
- end (* SET_SPEED_AND_PARITY *);
-
- (* eject *)
- procedure SET_VARIABLES;
- (* Kludge to shorten INIT_COM_MGR *)
-
- begin (* SET_VARIABLES *)
- if COM_CONFIGURATION.FILED_VERSION <> COM_VERSION then
- ERROR_EXIT('COM_MGR configuration data in obsolete format.');
- COM_INPUT_WAITING := 0;
- COM_OUTPUT_WAITING := 0;
- EVER_ACTIVE := true;
- RECEIVE_BUFFER.NEXT_IN := 0;
- RECEIVE_BUFFER.NEXT_OUT := 0;
- STACKED_XOFFS := 0;
- STACKED_XONS := 0;
- TRANSMIT_BUFFER.NEXT_IN := 0;
- TRANSMIT_BUFFER.NEXT_OUT := 0;
- XOFF_RECEIVED := false;
- XOFF_SENT := false
- end (* SET_VARIABLES *);
-
- (* eject *)
- begin (* INIT_COM_MGR *)
- if not INITIALIZED then
- begin (* nondegenerate case *)
- INIT_IOERROR;
- SET_VARIABLES;
-
- case COM_CONFIGURATION.THIS_PORT of
- COM1: begin (* COM1 *)
- DATA_REGISTER := $3F8;
- IRQ_USED := 4
- end (* COM1 *);
- COM2: begin (* COM2 *)
- DATA_REGISTER := $2F8;
- IRQ_USED := 3
- end (* COM2 *)
- else ERROR_EXIT('Ports beyond COM2 not implemented.')
- end (* case on THIS_PORT *);
-
- INT_ENABLE_REGISTER := succ(DATA_REGISTER);
- INT_ID_REGISTER := succ(INT_ENABLE_REGISTER);
- LINE_CTL_REGISTER := succ(INT_ID_REGISTER);
- MODEM_CTL_REGISTER := succ(LINE_CTL_REGISTER);
- LINE_STATUS_REGISTER := succ(MODEM_CTL_REGISTER);
- MODEM_STATUS_REGISTER := succ(LINE_STATUS_REGISTER);
-
- I8259_BIT := 1 shl IRQ_USED;
-
- OLD_IER := port[INT_ENABLE_REGISTER];
- port[INT_ENABLE_REGISTER] := 0;
- if port[INT_ENABLE_REGISTER] <> 0 then
- ERROR_EXIT('Port hardware not responding.');
-
- DISABLE_INTERRUPTS;
- OLD_I8259_MASK := port[PIC_IE_PORT];
- port[PIC_IE_PORT] := OLD_I8259_MASK or I8259_BIT;
- ENABLE_INTERRUPTS;
-
- GetIntVec(IRQ_BASE+IRQ_USED, OLD_IRQ_INT_PROC);
- SetIntVec(IRQ_BASE+IRQ_USED, @COM_INT_HANDLER);
- INITIALIZED := true;
- port[LINE_CTL_REGISTER] := LCR_PARITY_BITS[NO_PARITY];
-
- DISABLE_INTERRUPTS;
- OLD_MCR := port[MODEM_CTL_REGISTER];
- port[MODEM_CTL_REGISTER] := MCR_OUT2 or MCR_RTS;
- ENABLE_INTERRUPTS;
-
- port[INT_ENABLE_REGISTER] := IER_ENB_RCV_CHAR;
-
- DISABLE_INTERRUPTS;
- port[PIC_IE_PORT] := port[PIC_IE_PORT] and not I8259_BIT;
- ENABLE_INTERRUPTS;
-
- SET_SPEED_AND_PARITY
- end (* nondegenerate case *)
- end (* INIT_COM_MGR *);
- (* eject *)
- procedure TERM_COM_MGR;
- (* Necessary if only to flush buffers before they go away *)
-
- begin (* TERM_COM_MGR *)
- if INITIALIZED then
- begin (* nondegenerate case *)
- while COM_OUTPUT_WAITING > 0 do
- begin (* drain *)
- if XOFF_RECEIVED then
- inc(WAITING_FOR_XON)
- else
- inc(WAITING_FOR_DSR);
- write('Draining buffer [', COM_OUTPUT_WAITING, '] ');
- GotoXY(1, WhereY);
- end (* drain *);
- ClrEol;
- port[MODEM_CTL_REGISTER] := OLD_MCR;
- port[INT_ENABLE_REGISTER] := OLD_IER;
-
- DISABLE_INTERRUPTS;
- port[PIC_IE_PORT] := port[PIC_IE_PORT] and not I8259_BIT or
- OLD_I8259_MASK and I8259_BIT;
- ENABLE_INTERRUPTS;
-
- SetIntVec(IRQ_BASE+IRQ_USED, OLD_IRQ_INT_PROC);
- INITIALIZED := false
- end (* nondegenerate case *)
- end (* TERM_COM_MGR *);
-
- begin (* COM_MGR *)
- DROPPED := 0;
- EVER_ACTIVE := false;
- INITIALIZED := false;
- INPUT_ZENITH := 0;
- SAVE_EXIT := ExitProc;
- WAITING_FOR_DSR := 0;
- WAITING_FOR_XON := 0;
-
- ExitProc := @EPILOGUE
- end (* COM_MGR *).
-
- END
- T-------T-------T-------T-------T-------T-------T-------T-------T-------T-------T
- $cursor=27342,20;$tag=23770,16;$last=24293,24;a=7948,17;z=26098,12;
- FTL0R79P5.F0B7
-
-