home *** CD-ROM | disk | FTP | other *** search
- ; XCOMMS.ASM - The XCOMMS kernal
- ;
- ; If assembled to be bundled in - MASM XCOMMS,,/DBUNDLD /Dmemory_model;
- ; otherwise, - MASM XCOMMS /Dmemory_model;
- ;
- ; Copyright (C) 1991, South Mountain Software Inc.
- ; All Rights Reserved
- ;
- ;
- ; ===============================================================
- ; Definitions
- ; ===============================================================
- ;
-
- INTERCEPTED EQU 01h ; Timer_State value
- NATIVE EQU 00h ; Timer_State value
-
- KEYBK EQU 1Bh ; Keyboard break
- TIMER EQU 1Ch ; Timer interrupt
- BDOS EQU 21h ; BDOS interrupt
- RS232 EQU 14h ; Int 14h service vector
-
- LIST_END EQU 0
- XCOMMS_ID EQU 0A66AH
- REV_MAJOR EQU 4
- REV_MINOR EQU 0
-
- IONOP MACRO ; Chip overrun safety factor
- JMP $+2
- JMP $+2
- JMP $+2
- ENDM
-
- Enter_critical MACRO ; Disable interrupts
- PUSHF
- CLI
- ENDM ; (The stack is changed!)
-
- Exit_critical MACRO ; Enable interrupts
- POPF
- ENDM ; (The stack is changed!)
- ;
- ; ===============================================================
- ; References
- ; ===============================================================
- ;
-
- PUBLIC XCOMMS
-
- INCLUDE ECLMACRO.INC
-
- ;
- ; ===============================================================
- ; Local data
- ; ===============================================================
- ;
- IFDEF BUNDLD
- _data segment word public 'DATA'
- _data ends
- DGROUP GROUP _DATA
-
- modstart XCOMMS
- ELSE
- CSEG SEGMENT BYTE PUBLIC 'CODE'
- ASSUME CS:CSEG, DS:CSEG, SS:CSEG, ES:CSEG
- ENDIF
-
- Service LABEL WORD
- DW 1400h ; COMMS_Status
- DW 1401h ; COMMS_Link
- DW 1402h ; COMMS_UnLink
- DW 1403h ; COMMS_DTRon
- DW 1404h ; COMMS_DTRoff
- DW 1405h ; COMMS_RTSon
- DW 1406h ; COMMS_RTSoff
- DW 1407h ; COMMS_BREAKon
- DW 1408h ; COMMS_BREAKoff
- DW 1409h ; COMMS_fc_on
- DW 140Ah ; COMMS_fc_off
- DW 140Bh ; COMMS_DTRget
- DW 140Ch ; COMMS_RTSget
- DW 140Dh ; COMMS_Gaddr
- DW 140Eh ; COMMS_Flush
- DW 140Fh ; COMMS_BREAKget REV 1.2
- DW 1410h ; COMMS_19200 REV 1.2
- DW 1411h ; COMMS_GPORT REV 2.0
- DW 1412h ; COMMS_Uxmit REV 2.0
- DW 1413h ; COMMS_UTEST REV 2.0
- DW 1414h ; COMMS_UKILL REV 2.0
- DW 1415h ; COMMS_FASTR REV 2.0
- DW 1416h ; COMMS_XCTIMOU REV 2.0
- DW 1417h ; COMMS_FCKILL REV 2.0
- DW 1418h ; COMMS_38400 REV 2.0
- DW 1419h ; COMMS_OUT2 REV 3.0a
- DW 1420h ; COMMS_STATUS_PORT REV 3.0
- DW 1421h ; COMMS_SHARED_VECTOR REV 3.0
- DW 1422h ; COMMS_ICMASK REV 3.0
- DW 1423h ; COMMS_BOARD_TYPE 3.0
- DW 1424h ; COMMS_57K REV 3.0
- DW 1425h ; COMMS_115K REV 3.0
- DW 1426h ; COMMS_STARTPORT REV 3.0
- DW 1427h ; COMMS_MAXPORT REV 3.0
- DW 1428h ; COMMS_SET_FC_CHAR REV 3.0
- DW 1429h ; COMMS_Test_16550 REV 4.0
- DW 142Ah ; COMMS_Set_16550 REV 4.0
- DW 142Bh ; COMMS_Get_Buffer_Memory REV 4.0
- DW 142Ch ; COMMS_Free_Buffer_Memory REV 4.0
- DW 142Dh ; COMMS_Put_Buffer_Memory REV 4.0
- DW 142Eh ; COMMS_Set_Int_Exit REV 4.0
-
- DW 0000h ; XCOMMS_Status
- DW 0001h ; XCOMMS_Exit
- DW 0002h ; XCOMMS_Entry
-
- DW 0010h ; BUFFR_Init
- DW 0011h ; BUFFR_Status
- DW 0012h ; BUFFR_Gmem
- DW 0013h ; BUFFR_Pmem
-
- DW 1C00h ; TIMER_Status
- DW 1C01h ; TIMER_Link
- DW 1C02h ; TIMER_UnLink
- DW 1C03h ; TIMER_Set
- DW 1C04h ; TIMER_Clear
- DW 1C05h ; TIMER_Test
- DW 1C06h ; TIMER_Wait
- DW 1C10h ; TIMERP_Status
- DW 1C11h ; TIMERP_Link
- DW 1C12h ; TIMERP_UnLink
- DW 1C13h ; TIMERP_Set
- DW 1C14h ; TIMERP_Clear
- DW 1C15h ; TIMERP_Test
- DW 1C16h ; TIMERP_Wait
-
- DW 1B00h ; KEYBK_Status
- DW 1B01h ; KEYBK_Link
- DW 1B02h ; KEYBK_UnLink
- DW 1B03h ; KEYBK_Test
-
- EndServ LABEL WORD
- No_Serv EQU (EndServ - Service) / 2 ; Number of services
-
-
- Routine LABEL WORD
- DW OFFSET COMMS_Status
- DW OFFSET COMMS_Link
- DW OFFSET COMMS_UnLink
- DW OFFSET COMMS_DTRon
- DW OFFSET COMMS_DTRoff
- DW OFFSET COMMS_RTSon
- DW OFFSET COMMS_RTSoff
- DW OFFSET COMMS_BREAKon
- DW OFFSET COMMS_BREAKoff
- DW OFFSET COMMS_fc_on
- DW OFFSET COMMS_fc_off
- DW OFFSET COMMS_DTRget
- DW OFFSET COMMS_RTSget
- DW OFFSET COMMS_Gaddr
- DW OFFSET COMMS_Flush
- DW OFFSET COMMS_BREAKget ; Rev 1.2
- DW OFFSET COMMS_19200 ; Rev 1.2
- DW OFFSET COMMS_GPORT ; REV 2.0
- DW OFFSET COMMS_Uxmit ; REV 2.0
- DW OFFSET COMMS_UTEST ; REV 2.0
- DW OFFSET COMMS_UKILL ; REV 2.0
- DW OFFSET COMMS_FASTR ; REV 2.0
- DW OFFSET COMMS_XCTIMOU ; REV 2.0
- DW OFFSET COMMS_FCKILL ; REV 2.0
- DW OFFSET COMMS_38400 ; REV 2.0
- DW OFFSET COMMS_OUT2 ; 2.0a
- DW OFFSET COMMS_STATUS_PORT ; 3.0
- DW OFFSET COMMS_SHARED_VECTOR ; 3.0
- DW OFFSET COMMS_SHARED_ICMASK ; 3.0
- DW OFFSET COMMS_BOARD_TYPE ; 3.0
- DW OFFSET COMMS_57K ; 3.0
- DW OFFSET COMMS_115K ; 3.0
- DW OFFSET COMMS_STARTPORT ; 3.0
- DW OFFSET COMMS_MAXPORT ; 3.0
- DW OFFSET COMMS_SET_FC_CHAR ; 3.0
- DW OFFSET COMMS_Test_16550 ; REV 4.0
- DW OFFSET COMMS_Set_16550 ; REV 4.0
- DW OFFSET COMMS_Get_Buffer_Memory ; REV 4.0
- DW OFFSET COMMS_Free_Buffer_Memory ; REV 4.0
- DW OFFSET COMMS_Put_Buffer_Memory ; REV 4.0
- DW OFFSET COMMS_Set_Int_Exit ; REV 4.0
-
- DW OFFSET XCOMMS_Status
- DW OFFSET XCOMMS_Exit
- DW OFFSET XCOMMS_Entry
-
- DW OFFSET BUFFR_Init
- DW OFFSET BUFFR_Status
- DW OFFSET BUFFR_Gmem
- DW OFFSET BUFFR_Pmem
-
- DW OFFSET TIMER_Status
- DW OFFSET TIMER_Link
- DW OFFSET TIMER_UnLink
- DW OFFSET TIMER_Set
- DW OFFSET TIMER_Clear
- DW OFFSET TIMER_Test
- DW OFFSET TIMER_Wait
- DW OFFSET TIMERP_Status ; REV 2.0
- DW OFFSET TIMERP_Link ; REV 2.0
- DW OFFSET TIMERP_UnLink ; REV 2.0
- DW OFFSET TIMERP_Set ; REV 2.0
- DW OFFSET TIMERP_Clear ; REV 2.0
- DW OFFSET TIMERP_Test ; REV 2.0
- DW OFFSET TIMERP_Wait ; REV 2.0
-
- DW OFFSET KEYBK_Status
- DW OFFSET KEYBK_Link
- DW OFFSET KEYBK_UnLink
- DW OFFSET KEYBK_Test
-
-
-
- XCOMMS_State DW NATIVE ; Not used
- XCOMMS_Buffer_Offset DW ?
- XCOMMS_Buffer_Segment DW ?
- XCOMMS_Buffer_Count DW ?
-
- copyright_data label word
- DB "Copyright (C) 1991, South Mountain Software Inc", 13,10
-
-
- Entries LABEL WORD
- DW OFFSET BUFFR_Entry
- DW OFFSET TIMER_Entry
- DW OFFSET KEYBK_Entry
- DW OFFSET COMMS_Entry
- DW LIST_END
-
- Exeunts LABEL WORD
- DW OFFSET TIMER_Exit
- DW OFFSET KEYBK_Exit
- DW OFFSET COMMS_Exit
- ;;;;; DW OFFSET BUFFR_Init
- DW LIST_END
-
- ;
- ; ===============================================================
- ; Kernal drivers
- ; ===============================================================
- ;
-
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
- ; INCLUDE COMMS.ASM ; Communications handler (COMM_INT.ASM)
- ;*******************************************************************
- ;
- ; COMMS.ASM XCOMMS kernal Communications handler
- ;
- ; (C) Copyright 1986, 1987, 1988 Essential Software, Inc.
- ; (C) Copyright 1989, South Mountain Software, Inc.
- ; All Rights Reserved
- ;
- ; *************************************************************
- ; *********************** MODIFICATIONS ***********************
- ; *************************************************************
- ;
- ; 10-25-89 - changes marked with "- **XMIT*XON*FIX**"
- ; 1) Added lockout of interrupts when doing the setup and transmission
- ; of the first character in unpended transmits. (see COMMS_Uxmit).
- ; Also added check for flow control and XONs.
- ;
- ; When XCOMMS is entered, the INT 14h vector is automatically
- ; intercepted. Each INT 14h request is checked for the appropriate
- ; LINKed unit - since either COM1 and/or COM2 may be linked.
- ;
- ; If intercepted, receiver interrupts are generated - none of the
- ; modem and line control signals are forced or verified unless
- ; explicitly desired by the caller at COMMS_Link request.
- ;
- ; An overrun error will NOT occur if the received character runs out of
- ; buffer space. Simply, characters that cannot be stored are ignored.
- ;
- ; DEPENDS ON SYSTEM ROM BAUD RATE TABLE AT F000:E729(HEX)
- ;
- ; CPR Rev fixed Description
- ; ------- ---------- ----------------------------------------
- ; ECL0002 1.2 xc_link loops forever on a non-existent COMx
- ; 1.2 New feature - COMMS_BREAKget returns status
- ; 1.2 New feature - COMMS_19200 fast speed
- ; 2.0 COMMS_FASTR
- ; 2.0 New feature - COMMS_38400 fast speed
- ; 2.0a Modified not to clear DTR in COMMS_Link
-
- PUBLIC INT14SEND, INT14READ, INT14STATUS
-
- TIMEOUT EQU 0FFFFh ; INT14READ,SEND loop timeout
-
- ; Flow control bit masks (.Comm_Xflags)
- FC_ENABLED EQU 01h ; Flow control is enabled
- FC_XOFF_SENT EQU 02h ; Xoff has been transmitted
- FC_XOFF_RCVD EQU 04h ; Xoff has been received
- FC_SEND_XOFF EQU 08h ; Xoff needs to be transmitted
- FC_SEND_XON EQU 10h ; Xon needs to be transmitted
- FC_REC_ON EQU 20h ; REC Flow control enabled
- FC_TX_ON EQU 40h ; TX Flow control enabled
-
- IONOP MACRO ; Chip overrun safety factor
- JMP $+2
- JMP $+2
- JMP $+2
- ENDM
- ;
- ; 8259A Interrupt Controller port assignments:
-
- ICA EQU 021h ; Interrupt controller addr
- EOI EQU 020h ; End of interrupt addr
-
- UART_DEF STRUC
- TX_RD_BUFF_DLLO DB ? ; TRANSMIT WO, READ RO
- ; DIVISOR LATCH LOW IF DLAB=1
- IER_DLHI DB ? ; INTERRUPT ENABLE REGISTER
- ; DIVISOR LATCH HIGH IF DLAB=1
- IIR DB ? ; INTERRUPT ID REGISTER
- LCR DB ? ; LINE CONTROL REGISTER RW
- MCR DB ? ; MODEM CONTROL REGISTER RW
- LSR DB ? ; LINE STATUS REGISTER RW
- MSR DB ? ; MODEM STATUS REGISTER RW
-
- UART_DEF ENDS
-
-
- ;
- ; ================================================================
- ; *** Communications port data base structure ***
- ;
- ; Each port is defined in terms of the following structure
- ; including:
- ; Port address and vector information
- ; Status flags (intercepted, DTR enabled, and break detected)
- ; Receive Buffer pointers, counters, and flags
- ; Transmit (rev 2.0) buffers and counters
- ; ================================================================
- ;
-
- Comms_str STRUC
- Comm_PortAddr DW ? ; Base port address FIXED
- Comm_Vector DB ? ; Interrupt vector FIXED
- Comm_IC_Mask DB ? ; Int Controller mask FIXED
- Comm_New_offset DW ?
- Comm_New_segment DW ?
- Comm_State DW ? ; = 01h if intercepted
- Comm_DTR_RTS DB ? ; Intercepted INT14INIT flag
- Comm_Break DB ? ; Break detected (recv int)
-
- Comm_Old_IntOffset DW ? ; IREQ3, 4 old offset
- Comm_Old_IntSegment DW ? ; IREQ3, 4 old segment
-
- Comm_Receive_Count DD ? ; Bytes received (DD!)
- Comm_Buffer_Count DW ? ; Number of blocks current
-
- Comm_CR_BUFFR_Offset DW ? ; Interrupt buffer pointer
- Comm_CR_BUFFR_Segment DW ?
- Comm_CR_BUFFR_Index DW ? ; Next index in buffer
-
- Comm_RD_BUFFR_Offset DW ? ; Int 14h read buffer pointer
- Comm_RD_BUFFR_Segment DW ?
- Comm_RD_BUFFR_Index DW ? ; Next index in buffer
- Comm_Error DW ? ; Overrun error flag
-
- Comm_Xflags DW ? ; Bit 0 X-On, X-Off
- ; Bit 1 X-Off sent
- ; Bit 2 X-Off received
- Comm_high DW ? ; High water mark
- Comm_low DW ? ; Low water mark
- Comm_xcount DW ? ; Rev 2.0 Transmit buffer counter
- Comm_xptr_Offset DW ? ; Rev 2.0 Transmit buffer addr
- Comm_xptr_Segment DW ? ; Rev 2.0 Transmit buffer addr
- Comm_unit DW ? ; COM1 = 0, COM2 = 2, ...
- Comm_UART_Mode DW 0 ; 16450: 0; 16550: (nonzero) contains trigger and mode information;
- Comm_IXmit_Base DW ? ;
- Comm_IXmit_Top DW ? ;
- Comm_IRec_Base DW ? ;
- Comm_IRec_Top DW ? ;
- Comm_rxbusy DW ? ;
- Comms_str ENDS
-
-
-
- TIMERS_X16 LABEL WORD ; 16-bit baud divisors
- DW 1047, 768, 384, 192, 96,48,24,12
- INT14_Old_Offset DW ?
- INT14_Old_Segment DW ?
- timeout_variable DW ?
- out2_variable DW 08h ; default to force out2 high for
- ; COM1 & COM2
- port_hold DW ? ; hold unit (port) number briefly
- board_type DW 0 ; multiport board type
- starting_port DW 99 ; starting port number for multiports
- ; multiplied by 2 for offset
- multi_init DW 0 ; flag for multiport linking
- multi_unlinked DW 0 ; flag for multiport unlinking
- maxshare DW 0 ; max num ports on this irq
-
- ; variables below are for second multiport
- board2_type DW 0 ; multiport board type
- starting2_port DW 99; starting port number for multiports
- ; multiplied by 2 for offset
- multi2_init DW 0 ; flag for multiport linking
- multi2_unlinked DW 0 ; flag for multiport unlinking
- maxshare2 DW 0 ; max num ports on this irq
- XON DB 11h ; Character XON
- XOFF DB 13h ; Character XOFF
-
-
- ; EQUATES FOR MASK TESTS
- MREC EQU 1
- MSEND EQU 2
- MMSR EQU 4
- MERR EQU 8
-
- IFDEF INT_EXITS
- com1_mask DW 0
- com1_func DD 0
- com2_mask DW 0
- com2_func DD 0
- share1_mask DW 0
- share1_func DD 0
- share2_mask DW 0
- share2_func DD 0
- ENDIF
-
-
-
-
- TEST_EXIT_REC MACRO handler, call_to, jmp_to, port
- local nothing_yet, change_char, no_jump, local_port, local_jump
- jmp local_jump
- local_port dw 0
- local_jump:
- test word ptr cs:handler, MREC
- jz nothing_yet
- mov cs:local_port, port
- push ax
- push bx
- push cx
- push dx
- push ds
- mov bx, DGROUP
- mov ds, bx
- xor ah, ah
- push ax
- mov ax, MREC
- push ax
- push cs:local_port
- call dword ptr call_to
- add sp, 6
- pop ds
- pop dx
- pop cx
- pop bx
-
- cmp ax, 0
- jne change_char
- pop ax
- jmp short nothing_yet
- change_char:
- add sp, 2 ; old ax still on stack
- cmp ax, 0ffffh ; should we not save the char ( ax == -1)
- ; je jmp_to rel jump out of range
- jne no_jump
- jmp jmp_to
- no_jump:
- ; anything else means store a new character
- xor ah, ah ; leave new char in AL
- nothing_yet:
- ENDM
-
- TEST_EXIT_SEND MACRO handler, call_to, port
- local nothing_yet, local_port, local_jump
- jmp local_jump
- local_port dw 0
- local_jump:
- test word ptr cs:handler, MSEND
- jz nothing_yet
- mov cs:local_port, port
- push ax
- push bx
- push cx
- push dx
- push ds
- mov bx, DGROUP
- mov ds, bx
- mov ax, MSEND
- push ax
- push cs:local_port
- call dword ptr call_to
- add sp, 4
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
-
- nothing_yet:
- ENDM
-
- TEST_EXIT_MSR MACRO handler, call_to, port
- local nothing_yet, local_port, local_jump
- jmp local_jump
- local_port dw 0
- local_jump:
- test word ptr cs:handler, MMSR
- jz nothing_yet
- mov cs:local_port, port
- push ax
- push bx
- push cx
- push dx
- push ds
- mov bx, DGROUP
- mov ds, bx
- xor ah, ah
- push ax
- mov ax, MMSR
- push ax
- push cs:local_port
- call dword ptr call_to
- add sp, 6
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
-
- nothing_yet:
- ENDM
-
- TEST_EXIT_ERR MACRO handler, call_to, port
- local nothing_yet, local_port, local_jump
- jmp local_jump
- local_port dw 0
- local_jump:
- test word ptr cs:handler, MERR
- jz nothing_yet
- mov cs:local_port, port
- push ax
- push bx
- push cx
- push dx
- push ds
- mov bx, DGROUP
- mov ds, bx
- xor ah, ah
- push ax
- mov ax, MERR
- push ax
- push cs:local_port
- call dword ptr call_to
- add sp, 6
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
-
- nothing_yet:
- ENDM
-
-
- public board_type, starting_port, multi_init, maxshare
- public board2_type, starting2_port, multi2_init, maxshare2
-
- ; variables below are for first and second PC/Xx intelligent multiport board
- PC_Xx_structure STRUC
- pcxx_io_port DB ? ;
- pcxx_irq DB ? ;
- pcxx_window_base DW ? ;
- pcxx_memory_seg DW ? ;
- pcxx_memory_size DD ? ;
- pcxx_nports DB ? ;
- pcxx_board_type DW ? ;
- PC_Xx_structure ENDS
-
-
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
- ; INCLUDE COMM_INT.ASM ; Communications handler (COMM_INT.ASM)
- ;*******************************************************************
- ;
- ; COMSALL.asm IBM PC COM1 and COM2 & MULTI-PORT Communications
- ; Comm_int.asm - Communications interrupt handlers
- ; (include file from COMMS.ASM)
- ;
- ; (C) Copyright 19896 SOuth Mountain Software Inc.
- ;
- ; *************************************************************
- ; *********************** MODIFICATIONS ***********************
- ; *************************************************************
- ;
- ; 10-23-89 - changes marked with "- WQ "
- ; - assemble with /DWQ for this one
- ; 1) Changed by WQ to add setting of flag bit when 1st XON received.
- ; Used so that the transmitter can wait for the first XON to
- ; be received before starting the transmission of data. This
- ; flag bit is in the structure entry "COMx.Comm_Xflags" (bit value
- ; "FC_FIRST_XON - 80H") which can be read via the "xc_gaddr()"
- ; function. This flag setting is NOT used within the driver - if
- ; needed by the application it must be read in the high level file
- ; transfer portion of the C code. Note that this bit value is
- ; currently unused but reserved by the ESI Comm. Library.
- ;
- ; 10-25-89 - changes marked with "- **XMIT*XON*FIX**"
- ; 1) Fixed bug in the 8250 "bug fix" code that caused a permanent loop
- ; to be caused when flow control was enabled, the THRE was empty, and
- ; the last character received was an XOFF.
- ; 12-27-89 - added DIGIBOARD Multichannel support
- ; 10-11-90 JHL - Corrected code to support Digiboard PC/X boards using
- ; even IRQs. Corrected code to support Digiboard MC/X boards.
- ; 12-05-90 JHL - Corrected code to support AST 4 PORT DOS and
- ; DFI MU440 boards in "Compatible" mode.
- ;
- ; service routines description
- ;
- ; IREQ4 COM1 standard interrupt operation
- ; IREQ3 COM2 standard interrupt operation
- ; IREQSHARE COM3+ multi-port interrupt operation
- ; IREQSHARE2 COM3n multi-port interrupt operation
- ;
- ; CPR Rev fixed Description
- ; ------- --------- ------------------------------------
- ; ECL0006 1.2 Interrupts "lost" CX during buffer read
- ; 2.0 Redistributed support for COM1 and COM2
- ; 2.0a Changed to IIR only checking.
- ; 2.0a Also combined flow control code
- ; and enabled XON/XOFF in both TX & RX.
- ; 2.0a Enabled hardwire handshaking for unpended TX
- ; 3.0 ALL of the multiport stuff + hardware bugfix
-
- IFDEF WQ
- FC_FIRST_XON EQU 80h ;1st XON received for WQ
- ENDIF
-
- PUBLIC C1
- PUBLIC IREQ4,IREQ3,IREQSHARE,IREQSHARE2
-
- C1 EQU 03F8h ; 8250 UART port offset COM1
- C2 EQU 02F8h ; 8250 UART port offset COM2
- C3 EQU 0 ; 3-n default to none available
- C4 EQU 0
- C5 EQU 0
- C6 EQU 0
- C7 EQU 0
- C8 EQU 0
- C9 EQU 0
- C10 EQU 0
- C11 EQU 0
- C12 EQU 0
- C13 EQU 0
- C14 EQU 0
- C15 EQU 0
- C16 EQU 0
- C17 EQU 0
- C18 EQU 0
- C19 EQU 0
- C20 EQU 0
- C21 EQU 0
- C22 EQU 0
- C23 EQU 0
- C24 EQU 0
- C25 EQU 0
- C26 EQU 0
- C27 EQU 0
- C28 EQU 0
- C29 EQU 0
- C30 EQU 0
- C31 EQU 0
- C32 EQU 0
- C33 EQU 0
- C34 EQU 0
-
-
- COM1 Comms_str <C1, 0Ch, 0EFh, OFFSET IREQ4, SEG IREQ4>
- COM2 Comms_str <C2, 0Bh, 0F7h, OFFSET IREQ3, SEG IREQ3>
- COM3 Comms_str <C3, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM4 Comms_str <C4, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM5 Comms_str <C5, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM6 Comms_str <C6, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM7 Comms_str <C7, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM8 Comms_str <C8, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM9 Comms_str <C9, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM10 Comms_str <C10, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM11 Comms_str <C11, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM12 Comms_str <C12, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM13 Comms_str <C13, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM14 Comms_str <C14, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM15 Comms_str <C15, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM16 Comms_str <C16, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM17 Comms_str <C17, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM18 Comms_str <C18, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM19 Comms_str <C19, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM20 Comms_str <C20, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM21 Comms_str <C21, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM22 Comms_str <C22, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM23 Comms_str <C23, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM24 Comms_str <C24, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM25 Comms_str <C25, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM26 Comms_str <C26, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM27 Comms_str <C27, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM28 Comms_str <C28, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM29 Comms_str <C29, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM30 Comms_str <C30, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM31 Comms_str <C31, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM32 Comms_str <C32, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM33 Comms_str <C33, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
- COM34 Comms_str <C34, 0Dh, 0DFh, OFFSET IREQSHARE, SEG IREQSHARE>
-
- Shared_vector DB 0Dh
- Shared_IC_mask DB 0DFh
- Shared_Old_IntOffset DW ? ; Shared interrupt previous vector
- Shared_Old_IntSegment DW ?
- Shared_New_IntOffset DW OFFSET IREQSHARE
- Shared_New_IntSegment DW SEG IREQSHARE
- Status_port DW 0h ; no default
-
- Shared2_vector DB 0Dh
- Shared2_IC_mask DB 0DFh
- Shared2_Old_IntOffset DW ? ; Shared interrupt previous vector
- Shared2_Old_IntSegment DW ?
- Shared2_New_IntOffset DW OFFSET IREQSHARE2
- Shared2_New_IntSegment DW SEG IREQSHARE2
- Status2_port DW 0h ; no default
-
- public Shared_vector, Shared_IC_mask, Status_port
- public Shared2_vector, Shared2_IC_mask, Status2_port
-
-
-
- MAXPORTS EQU 34 ; COM1 and COM2 & 32 others
-
- Port_Table DW OFFSET COM1 ; Pointer to Comms_str structures
- DW OFFSET COM2
- DW OFFSET COM3
- DW OFFSET COM4
- DW OFFSET COM5
- DW OFFSET COM6
- DW OFFSET COM7
- DW OFFSET COM8
- DW OFFSET COM9
- DW OFFSET COM10
- DW OFFSET COM11
- DW OFFSET COM12
- DW OFFSET COM13
- DW OFFSET COM14
- DW OFFSET COM15
- DW OFFSET COM16
- DW OFFSET COM17
- DW OFFSET COM18
- DW OFFSET COM19
- DW OFFSET COM20
- DW OFFSET COM21
- DW OFFSET COM22
- DW OFFSET COM23
- DW OFFSET COM24
- DW OFFSET COM25
- DW OFFSET COM26
- DW OFFSET COM27
- DW OFFSET COM28
- DW OFFSET COM29
- DW OFFSET COM30
- DW OFFSET COM31
- DW OFFSET COM32
- DW OFFSET COM33
- DW OFFSET COM34
-
- STATUS_POLLED EQU 0 ; Status default polled
- STATUS_INTERRUP EQU 1 ; Status interrupt driven
- STATUS_FLOWC EQU 2 ; Status interrupt and flow control on
-
- Port_Status DW MAXPORTS DUP (?);
-
-
-
- ; =======================================================================
-
- ;**** first Load_SI is from original COM1COM2
- ;Load_SI MACRO ; Required MACRO to load SI with Comms_str addr
- ; LOCAL skip
- ; LEA SI, COM1 ; Assume COM1
- ; CMP DL, 00
- ; JE skip
- ; LEA SI, COM2
- ;skip:
- ; ENDM
-
- Load_SI MACRO ; Required MACRO to load SI with Comms_str addr
- PUSH BX
- MOV BL, DL ; (No checking performed)
- MOV BH, 0
- ADD BX, BX
- MOV SI, Port_Table[BX]
- POP BX
- ENDM
-
-
-
- SI_continue MACRO ; Given SI, continue xmission
- LOCAL skip
- CMP [SI].Comm_xcount, 0
- JZ skip
- DEC [SI].Comm_xcount
- CMP [SI].Comm_xcount, 0
- JZ skip
-
- PUSH ES
- MOV BX, [SI].Comm_xptr_Offset
- MOV ES, [SI].Comm_xptr_Segment
- MOV AL, ES:[BX]
- INC [SI].Comm_xptr_Offset
- SI_putAL
- POP ES
- skip:
- ENDM
-
- ; This macro is used to xmit up to 16 bytes when FIFOs are enabled.
- ; Upon entry into this macro, both software flow control and hardware
- ; flow control has been checked so that we can xmit at least 1 charater
- ; without additional checking.
- SI_FIFO_continue MACRO ; Given SI, continue xmission
- LOCAL exit_1
- LOCAL pop_exit_2
- LOCAL send_char_to_FIFO
- LOCAL stuff_FIFO
- LOCAL no_fc
-
- cmp [si].Comm_xcount, 0
- jz exit_1 ; No more characters to xmit - then exit
- push es
- push cx
- mov cx, 010h ; set loop counter to 16 characters
- mov es, [si].Comm_xptr_Segment ; load segment of xmit buffer
- ; Send first character to the FIFO
- jmp send_char_to_FIFO
-
- ; Send the next character to the FIFO
- stuff_FIFO:
-
- ; Check if software Flow Control is enabled (XON - XOFF)
- test [si].Comm_Xflags, FC_TX_ON ;Is flow control enabled
- je no_fc
- test [si].Comm_Xflags, FC_XOFF_RCVD ;Was XOFF received
- jne pop_exit_2 ;If so we cannot xmit
-
- ; Check if Hardware Flow Control is disabled (Hardware Handshaking)
- no_fc:
- cmp [si].Comm_DTR_RTS, 0 ; see if handshaking disabled
- je send_char_to_FIFO ; Stuff next character in FIFO
- mov dx, [si].Comm_PortAddr ; Yes- read in modem status register to clear interrupt
- add dx, MSR
- in al, dx
- ; look for Hardware Handshaking flag
- and al, [si].Comm_DTR_RTS ; look for CTS and/or DSR
- cmp al, [si].Comm_DTR_RTS ; Unable to Xmit if Hardware Handshaking and CTS/DST not set
- jne pop_exit_2 ; try again if no CTS/DSR
- ; and al, 00110000B ; look for CTS and DSR
- ; cmp al, 00110000B ; Unable to Xmit if Hardware Handshaking and CTS/DST not set
- ; jne pop_exit_2 ; try again if no CTS/DSR
-
- send_char_to_FIFO:
- dec [si].Comm_xcount
- cmp [si].Comm_xcount, 0
- jz pop_exit_2
-
- mov bx, [si].Comm_xptr_Offset
- mov al, es:[bx]
- inc [si].Comm_xptr_Offset
- SI_putAL ; Send character to FIFO
-
- loop stuff_FIFO
-
- pop_exit_2:
- pop cx
- pop es
- exit_1:
- ENDM
-
-
-
- SI_putAL MACRO ; Given SI, send the character in AL
- ; !!! .Comm_xcount not modified !!!
- MOV DX, [SI].Comm_PortAddr
- ;*** ADD DX, TX_RD_BUFF_DLLO ;2.0a not necessary
- OUT DX, AL
- IONOP
- ENDM
-
-
- SI_FCon MACRO
- MOV BX, [SI].Comm_unit
- MOV WORD PTR Port_Status[BX], STATUS_FLOWC
- ENDM
-
- ; =======================================================================
-
- SI_FCoff MACRO
- MOV BX, [SI].Comm_unit
- MOV WORD PTR Port_Status[BX], STATUS_INTERRUP
- ENDM
-
- ; =======================================================================
- ;
- ; This macro gets the value of an 8250 register into AL. It assumes
- ; SI points to the port offset address already.
- ;
- SI_REG MACRO xxx
- MOV DX, [SI].Comm_PortAddr
- ADD DX, xxx
- IN AL, DX ; Get cause of interrupt
- ENDM
-
-
- IREQ4 PROC FAR ; COM1 standard interrupt operation
- PUSH DS ; Save segments
- PUSH ES ; Removed the LINE BREAK code!
- PUSH CS
- POP DS
- PUSH DI
- PUSH SI
- PUSH DX
- PUSH CX
- PUSH BX
- PUSH AX
-
- _ireq4_tryall: ;***** REV 2.0a changes here
- MOV SI, OFFSET COM1
- MOV DX, C1+IIR ; Find out what caused interrupt
- IN AL, DX ; Get cause of interrupt
- and al, 0Fh ; Isolate bits 0-3 of IIR
- CMP AL, 01H ; Any more interrupts pending?
-
- JNE _ireq4_ckrec ; jump if IIR says we have interrupt **XMIT*XON*FIX**
- ; **XMIT*XON*FIX**
- ; This area handles the "known" 8250-18450 UART bug that occurs when a **XMIT*XON*FIX**
- ; received data interrupt occurs at the same time that a THRE interrupt **XMIT*XON*FIX**
- ; occurred. When this circumstance occurs, no further TX interrupts are **XMIT*XON*FIX**
- ; generated, halting data xmission. **XMIT*XON*FIX**
- ; **XMIT*XON*FIX**
- MOV DX, C1+LSR ; look at THRE to get around 8250 bug
- IN AL, DX
- test AL, 20H
- jnz _ireq4_txbug ; have to check TX
- jmp _ireq4_exit
- ; AND AL, 20H ; isolate THRE
- ; CMP AL, 20H
- ; JE _ireq4_txbug ; have to check TX
- ; JMP _ireq4_exit
-
- _ireq4_txbug:
- CMP [SI].Comm_xcount, 0 ; anything to be xmitted? **XMIT*XON*FIX**
- JNE _ireq4_txbug_xmt_enter ; yes- see if conditions are ok **XMIT*XON*FIX**
- JMP _ireq4_exit ; no - nothing to do, get out **XMIT*XON*FIX**
-
- ; **XMIT*XON*FIX**
- ; THRE is empty - if flow control is enabled check for proper XON state. **XMIT*XON*FIX**
- ; (Note: 8250 bug will be overcome on the next receive interrupt by an **XMIT*XON*FIX**
- ; XON). **XMIT*XON*FIX**
- ; **XMIT*XON*FIX**
- _ireq4_txbug_xmt_enter: ;**XMIT*XON*FIX**
-
-
- TEST COM1.Comm_Xflags,FC_TX_ON ; Is flow control enabled? **XMIT*XON*FIX**
- JE txbug_no_fc4 ; no - check handshaking **XMIT*XON*FIX**
- TEST COM1.Comm_Xflags,FC_XOFF_RCVD ; Was XOFF received? **XMIT*XON*FIX**
- JE txbug_no_fc4 ; no - check handshaking **XMIT*XON*FIX**
- JMP _ireq4_exit ; wait for XON to xmit **XMIT*XON*FIX**
-
- ; **XMIT*XON*FIX**
- ; THRE is empty - if h/w handshake is enabled check modem signals. **XMIT*XON*FIX**
- ; (Note: 8250 bug will be overcome when the modem signals change and cause **XMIT*XON*FIX**
- ; an interrupt). **XMIT*XON*FIX**
- ; **XMIT*XON*FIX**
- txbug_no_fc4: ;**XMIT*XON*FIX**
- CMP [SI].Comm_DTR_RTS, 0 ; see if handshaking disabled **XMIT*XON*FIX**
- ; JE _ireq4_ckxmt3 ; handshaking is off, go xmit data! **XMIT*XON*FIX**
- jne tempab ; rel jump out of range
- jmp _ireq4_ckxmt3
- tempab:
- MOV DX, C1+MSR ; read in modem status register to **XMIT*XON*FIX**
- IN AL, DX ; clear interrupt **XMIT*XON*FIX**
- ; look for Hardware Handshaking flag
- and al, [si].Comm_DTR_RTS ; look for CTS and/or DSR
- cmp al, [si].Comm_DTR_RTS ; Unable to Xmit if Hardware Handshaking and CTS/DST not set
- ; AND AL, 00110000B ; look for CTS and DSR **XMIT*XON*FIX**
- ; CMP AL, 00110000B ; **XMIT*XON*FIX**
- JE _ireq4_ckxmt3 ; CTS/DSR ok, go xmit data **XMIT*XON*FIX**
- JMP _ireq4_exit ; can't xmit now so exit **XMIT*XON*FIX**
-
- ; AL contains bits 0-3 of IIR. Check if IIR bit 2 (04h)is set (Receive
- ; Data Available) or if both IIR bits 2 and 3 (0Ch) are set
- ; (Character Timeout Indication - Receive Data Available).
- _ireq4_ckrec:
- ; test al, 0CH ; Got a character to read?
- cmp al, 04H ; Got a character to read?
- jnz _ireq4_charto ; No
- jmp _ireq4_dataready ; Yes - go process it
- _ireq4_charto:
- cmp al, 0CH ; Got a character to read?
- jnz _ireq4_ckxmt ; No
- jmp _ireq4_dataready ; Yes - go process it
-
- _ireq4_ckxmt: ; AL contains bits 0-3 of IIR.
- CMP AL, 02H ; Ready to xmit a character? (Check Xmit Holding Reg Empty)
- ; JNE _ireq4_ckmsr ; No ; Rel Jump Out of range
- je _ireq4_xmt_enter
- jmp _ireq4_ckmsr ; No
-
- ; Transmit interrupt generated!!!!!!!!
- _ireq4_xmt_enter: ; Xmit chars if there are any to Xmit
-
- IFDEF INT_EXITS
- TEST_EXIT_SEND cs:com1_mask, cs:com1_func, 0
- ENDIF
-
- TEST COM1.Comm_Xflags,FC_TX_ON ;Is flow control enabled
- JE no_fc4
- TEST COM1.Comm_Xflags,FC_XOFF_RCVD ;Was XOFF received
- ;rel jmp out of range JNE _ireq4_tryall ; if so we cannot xmit
- je x2
- jmp _ireq4_tryall
- x2:
- no_fc4:
- CMP [SI].Comm_DTR_RTS, 0 ;2.0a see if handshaking disabled
- JE _ireq4_ckxmt3
- MOV DX, C1+MSR ; Yes- read in modem status register to
- IN AL, DX ; clear interrupt
-
- ; look for Hardware Handshaking flag
- and al, [si].Comm_DTR_RTS ; look for CTS and/or DSR
- cmp al, [si].Comm_DTR_RTS ; Unable to Xmit if Hardware Handshaking and CTS/DST not set
- ; AND AL, 00110000B ; look for CTS and DSR
- ; CMP AL, 00110000B ;
- ;rel jmp out of range JNE _ireq4_tryall ; try again if no CTS/DSR
- je x1
- jmp _ireq4_tryall
- x1:
-
- ; Xmit Interrupt Received, all clear to stuff Xmit buffer.
- ; When the Xmit FIFO is enabled (FCR0=1), Xmit interrupts will occur
- ; as follows: The transmitter holding register interrupt (02) occurs
- ; when the Xmit FIFO is empty. It is cleared as soon as the transmitter
- ; holding register is written to (1 to 16 characters may be written to
- ; the Xmit FIFO while servicing this interrupt) or the IIR is read.
- _ireq4_ckxmt3:
- ; Check if our UART mode indicates FIFOs are enabled
- ; Allowable values for "COMM_UART_Mode" are:
- ; 0 = 16440 (16550 Character) mode
- ; 1 = 16550 FIFOs enabled, DMA mode 0
- ; 9 = 16550 FIFOs enabled, DMA mode 1 (This mode is not used)
-
- test [si].COMM_UART_Mode, 09h
- jz _ireq4_x1char ; FIFOs not present or not enabled
-
- SI_FIFO_continue ; Stuff up to 16 chars in Xmit FIFO
- jmp _ireq4_tryall ; Now go see if anything else is pending
-
- _ireq4_x1char: ; Xmit 1 character
- SI_continue ; Xmit next char in Xmit buffer
- jmp _ireq4_tryall ; Now go see if anything else is pending
-
- ; No chars received, no chars to Xmit
- _ireq4_ckmsr: ;
- CMP AL, 00H ; Change in modem status? (AL contains bits 0-3 of IIR)
- JNE _ireq4_ckerr ; No - check for error or break
- _ireq4_ckmsr2: ;
- MOV DX, C1+MSR ; Yes- read in modem status register to
- IN AL, DX ; clear interrupt
-
- IFDEF INT_EXITS
- TEST_EXIT_MSR cs:com1_mask, cs:com1_func, 0
- ENDIF
-
- CMP [SI].Comm_DTR_RTS, 0 ; See if handshaking enabled
- ; JE _ireq4_tryall ; Now go see if anything else is pending
- JNE _ireq4_ckmsr3 ; JE above relative JMP out of range
- JMP _ireq4_tryall
- _ireq4_ckmsr3:
- MOV DX, C1+LSR
- IN AL, DX
- ; Check Xmit Holding Reg (LSR bit 6) and Xmit Empty (LSR bit 7) bits
- AND AL, 60h ; See if ready to transmit
- CMP AL, 60h
- ; JE _ireq4_ckxmt2 ; Relative Jump Out Of Range
- jne _ireq4_1rjor
- jmp _ireq4_xmt_enter ; go to start of Xmit char processing
- _ireq4_1rjor:
- jmp _ireq4_tryall ; Now go see if anything else is pending
-
-
- _ireq4_ckerr: ;
- CMP AL, 06H ; Got a rec'd char w/error or break?
- ;** JNE _ireq4_tryall ; No
- JE _ireq4_ckerr2 ; Relative jmp out of range
- JMP _ireq4_tryall
- _ireq4_ckerr2:
- MOV DX, C1+LSR ; Yes- read in line status register to
- IN AL, DX ; clear interrupt
-
- IFDEF INT_EXITS
- TEST_EXIT_ERR cs:com1_mask, cs:com1_func, 0
- ENDIF
-
- mov BYTE PTR [si].Comm_Break, al
- JMP _ireq4_tryall ; Now go see if anything else is pending
-
-
- _ireq4_exit:
- MOV AL, 20h ; Acknowledge interrupt
- OUT EOI, AL
- POP AX ; Restore registers
- POP BX
- POP CX
- POP DX
- POP SI
- POP DI
- POP ES
- POP DS
- IRET
-
- ; Read and Store character
- ; Data has been received (IIR is 04h or 0Ch); AL contains bits 0-3 of IIR
- _ireq4_dataready:
- ; Check if 16550 is present and if FIFOs are enabled
-
- test [si].COMM_UART_Mode, 09h
- jz _ireq4_noFIFO_dataready ; FIFOs not present or not enabled
- jmp _ireq4_FIFO_dataready ; FIFOs are present and enabled
-
- _ireq4_noFIFO_dataready:
- ; Read received character
- MOV DX, C1+TX_RD_BUFF_DLLO
- IN AL, DX
-
- IFDEF INT_EXITS
- TEST_EXIT_REC cs:com1_mask, cs:com1_func, _ireq4_tryall, 0
- ENDIF
-
-
- ; Check if Xmit Flow Control has been enabled
- TEST COM1.Comm_Xflags,FC_TX_ON ;Is flow control enabled
- JE no_fc4r
- CMP AL, XOFF ; Compare incomming char to XOFF
- JNE _ireq4fc_rskip1
- OR COM1.Comm_Xflags, FC_XOFF_RCVD ; Incoming XOFF, pause xmission
- JMP _ireq4_tryall
- _ireq4fc_rskip1:
- CMP AL, XON
- JNE _ireq4fc_rskip2
- AND COM1.Comm_Xflags, NOT FC_XOFF_RCVD ; Incoming XON, continue xmission
- IFDEF WQ
- OR COM1.Comm_Xflags, FC_FIRST_XON ; Got 1st XON for WQ
- ENDIF
- SI_continue ; Xmit next char in Xmit buffer if there is a char to Xmit
- JMP _ireq4_tryall
- _ireq4fc_rskip2:
-
- no_fc4r: ; No Flow Control Enabled
- MOV DX, COM1.Comm_CR_BUFFR_Segment
- MOV ES, DX
- MOV DI, COM1.Comm_CR_BUFFR_Offset
- MOV DX, COM1.Comm_CR_BUFFR_Index
- ADD DI, DX
- STOSB ; Store Char in receive buffer
- ; Increment Index into receive buffer
- ADD WORD PTR COM1.Comm_Receive_Count, 1
- ADC WORD PTR COM1.Comm_Receive_Count + 2, 0
- INC DX
- CMP DX, BUFFER_SIZE
- JNZ _ireq4_cont
-
- ; Optionally, add another buffer
-
- PUSH CX ; REV 1.2 ECL0006
- CALL BUFFR_Gmem ; Get next available buffer
- POP CX ; REV 1.2 ECL0006
- JC _ireq4_nobuff ; None available
- ; Increment next buffer information
- INC COM1.Comm_Buffer_Count
- MOV DI, COM1.Comm_CR_BUFFR_Offset
- MOV ES:[DI], BX ; Save pointer in previous last block
- MOV ES:[DI+2], DX
- MOV COM1.Comm_CR_BUFFR_Offset, BX
- MOV COM1.Comm_CR_BUFFR_Segment, DX
- MOV DX, 4 ; New index
-
- _ireq4_cont:
- ; Store Updated Receive Buffer Index in COMMS structure
- MOV COM1.Comm_CR_BUFFR_Index, DX
-
- TEST COM1.Comm_Xflags,FC_REC_ON ;Is flow control enabled
- JNE ck4_hi
- JMP _ireq4_tryall
- ck4_hi: ; check high flow control mark
- TEST COM1.Comm_Xflags, FC_XOFF_SENT ; Outgoing XOFF already sent
- JE ck4_hi_2
- JMP _ireq4_tryall
- ck4_hi_2:
- ;**** don't check high word, XON/XOFF only supported < 64K
- ;**** CMP WORD PTR COM1.Comm_Receive_Count+2, 0
- ;**** JNE over4_high
- MOV AX, COM1.Comm_high
- CMP WORD PTR COM1.Comm_Receive_Count, AX
- JGE over4_high
- JMP _ireq4_tryall
- over4_high:
- ; have to send XOFF
- MOV DX, C1+LSR ; get line status
- IN AL, DX
- ; Any error is revealed via LSR bits 1-4 when it's associated
- ; character is at the top of the FIFO
- TEST AL, 01h ; has a char come in
- JE over4_cont
- jmp _ireq4_noFIFO_dataready ; if so, go get it
- over4_cont:
- TEST AL, 40h ; look at TX ready bits
- JE over4_high ; wait for TX OK
- SUB DX, LSR
- MOV AL, XOFF
- OUT DX, AL ; Xmit XOFF
- OR COM1.Comm_Xflags, FC_XOFF_SENT
-
- JMP _ireq4_tryall
-
-
- ; No more Receive Buffer space available; Next Character received will
- ; overwrite the last character received.
- _ireq4_nobuff: ; None available
- SUB WORD PTR COM1.Comm_Receive_Count, 1
- SBB WORD PTR COM1.Comm_Receive_Count + 2, 0
- JMP _ireq4_tryall
-
- ;*************************************************************************
- ; The following code is executed if the Uart has it's FIFOS enabled.
- ;*************************************************************************
- ; If the Receive FIFOs are enabled, then the code will loop until
- ; the Receive FIFO is empty. Bit 0 of the Line Status Register is
- ; set to one whenever at least 1 character is in the Recieve Buffer
- ; Register. This bit (LSR bit0) is set to zero by reading all data
- ; in the receive buffer or FIFO.
-
- _ireq4_FIFO_dataready:
- ; Read received character
- MOV DX, C1+TX_RD_BUFF_DLLO
- IN AL, DX ; Read character received
-
- IFDEF INT_EXITS
- TEST_EXIT_REC cs:com1_mask, cs:com1_func, _ireq4_tryall, 0
- ENDIF
-
- ; Check if Xmit Flow Control has been enabled
- TEST COM1.Comm_Xflags,FC_TX_ON ;Is flow control enabled
- JE no_fc4rFIFO
- CMP AL, XOFF ; Compare incomming char to XOFF
- JNE _ireq4fc_FIFOrskip1
- OR COM1.Comm_Xflags, FC_XOFF_RCVD ; Incoming XOFF, pause xmission
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _ireq4_check_data_ready
-
- _ireq4fc_FIFOrskip1:
- CMP AL, XON
- JNE _ireq4fc_FIFOrskip2
- AND COM1.Comm_Xflags, NOT FC_XOFF_RCVD ; Incoming XON, continue xmission
- IFDEF WQ
- OR COM1.Comm_Xflags, FC_FIRST_XON ; Got 1st XON - WQ
- ENDIF
- SI_continue ; Xmit next char in Xmit buffer if there is a char to Xmit
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _ireq4_check_data_ready
-
- _ireq4fc_FIFOrskip2:
-
- no_fc4rFIFO: ; No Flow Control Enabled
- ; Get ECL Receive buffer location
- MOV DX, COM1.Comm_CR_BUFFR_Segment
- MOV ES, DX
- MOV DI, COM1.Comm_CR_BUFFR_Offset
- MOV DX, COM1.Comm_CR_BUFFR_Index
- ADD DI, DX
- STOSB ; Store Char in receive buffer
- ; Increment Index into receive buffer
- ADD WORD PTR COM1.Comm_Receive_Count, 1
- ADC WORD PTR COM1.Comm_Receive_Count + 2, 0
- INC DX
- CMP DX, BUFFER_SIZE
- JNZ _ireq4_contFIFO
-
- ; Optionally, add another buffer
-
- PUSH CX ; REV 1.2 ECL0006
- CALL BUFFR_Gmem ; Get next available buffer
- POP CX ; REV 1.2 ECL0006
- JC _ireq4_FIFOrjor6 ; No Buffers available
- jmp _ireq4_FIFOrjor7 ; Buffers available
- _ireq4_FIFOrjor6:
- jmp _ireq4_FIFOnobuff ; No Buffers available
- _ireq4_FIFOrjor7:
- ; Increment next buffer information
- INC COM1.Comm_Buffer_Count
- MOV DI, COM1.Comm_CR_BUFFR_Offset
- MOV ES:[DI], BX ; Save pointer in previous last block
- MOV ES:[DI+2], DX
- MOV COM1.Comm_CR_BUFFR_Offset, BX
- MOV COM1.Comm_CR_BUFFR_Segment, DX
- MOV DX, 4 ; New index
-
- _ireq4_contFIFO:
- ; Store Updated Receive Buffer Index in COMMS structure
- MOV COM1.Comm_CR_BUFFR_Index, DX
-
- TEST COM1.Comm_Xflags,FC_REC_ON ;Is Receive flow control enabled
- JNE ck4_hi_FIFO
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _ireq4_check_data_ready
-
- ck4_hi_FIFO: ; check high flow control mark
- TEST COM1.Comm_Xflags, FC_XOFF_SENT ; Outgoing XOFF already sent
- JE ck4_hi_2_FIFO
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _ireq4_check_data_ready
-
- ck4_hi_2_FIFO:
- ;**** don't check high word, XON/XOFF only supported < 64K
- ;**** CMP WORD PTR COM1.Comm_Receive_Count+2, 0
- ;**** JNE over4_high
- MOV AX, COM1.Comm_high
- CMP WORD PTR COM1.Comm_Receive_Count, AX
- JGE over4_high_FIFO
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _ireq4_check_data_ready
-
- over4_high_FIFO:
- ; have to send XOFF
- MOV DX, C1+LSR ; get line status
- IN AL, DX
- ; Any error is revealed via LSR bits 1-4 when it's associated
- ; character is at the top of the FIFO
- TEST AL, 01h ; has a char come in
- JE over4_cont_FIFO
- JMP _ireq4_FIFO_dataready ; if so, go get it
-
- over4_cont_FIFO:
- TEST AL, 40h ; look at TX ready bits
- JE over4_high_FIFO ; wait for TX OK
- SUB DX, LSR
- MOV AL, XOFF
- OUT DX, AL ; Xmit XOFF
- OR COM1.Comm_Xflags, FC_XOFF_SENT
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _ireq4_check_data_ready
-
- ; No more Receive Buffer space available; Next Character received will
- ; overwrite the last character received.
- _ireq4_FIFOnobuff: ; None available
- SUB WORD PTR COM1.Comm_Receive_Count, 1
- SBB WORD PTR COM1.Comm_Receive_Count + 2, 0
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- _ireq4_check_data_ready:
- mov dx, C1+LSR ; Load Line Status reg address
- in al, dx ; Get LSR
- test al, 01h ; Test for Receive FIFO empty
- jnz _ireq4_FIFO_rjor1 ; Get next character in Receive FIFO
- JMP _ireq4_tryall
- _ireq4_FIFO_rjor1: ; Relative Jump Out Of Range
- jmp _ireq4_FIFO_dataready ; Get next character in Receive FIFO
-
- IREQ4 ENDP
-
- ;*********************************************************************
-
- IREQ3 PROC FAR ; COM1 standard interrupt operation
- PUSH DS ; Save segments
- PUSH ES ; Removed the LINE BREAK code!
- PUSH CS
- POP DS
- PUSH DI
- PUSH SI
- PUSH DX
- PUSH CX
- PUSH BX
- PUSH AX
-
- _ireq3_tryall: ;***** REV 2.0a changes here
- MOV SI, OFFSET COM2
- MOV DX, C2+IIR ; Find out what caused interrupt
- IN AL, DX ; Get cause of interrupt
- and al, 0Fh ; Isolate bits 0-3 of IIR
- CMP AL, 01H ; Any more interrupts pending?
-
- JNE _ireq3_ckrec ; jump if IIR says we have interrupt **XMIT*XON*FIX**
- ; **XMIT*XON*FIX**
- ; This area handles the "known" 8250-18450 UART bug that occurs when a **XMIT*XON*FIX**
- ; received data interrupt occurs at the same time that a THRE interrupt **XMIT*XON*FIX**
- ; occurred. When this circumstance occurs, no further TX interrupts are **XMIT*XON*FIX**
- ; generated, halting data xmission. **XMIT*XON*FIX**
- ; **XMIT*XON*FIX**
- MOV DX, C2+LSR ; look at THRE to get around 8250 bug
- IN AL, DX
- ; AND AL, 20H ; isolate THRE
- ; CMP AL, 20H
- ; JE _ireq3_txbug ; have to check TX
- ; JMP _ireq3_exit
- test al, 020H
- jnz _ireq3_txbug ; have to check TX
- jmp _ireq3_exit
-
- _ireq3_txbug:
- CMP [SI].Comm_xcount, 0 ; anything to be xmitted? **XMIT*XON*FIX**
- JNE _ireq3_txbug_xmt_enter ; yes- see if conditions are ok **XMIT*XON*FIX**
- JMP _ireq3_exit ; no - nothing to do, get out **XMIT*XON*FIX**
-
- ; **XMIT*XON*FIX**
- ; THRE is empty - if flow control is enabled check for proper XON state. **XMIT*XON*FIX**
- ; (Note: 8250 bug will be overcome on the next receive interrupt by an **XMIT*XON*FIX**
- ; XON). **XMIT*XON*FIX**
- ; **XMIT*XON*FIX**
- _ireq3_txbug_xmt_enter: ;**XMIT*XON*FIX**
- TEST COM2.Comm_Xflags,FC_TX_ON ; Is flow control enabled? **XMIT*XON*FIX**
- JE txbug_no_fc3 ; no - check handshaking **XMIT*XON*FIX**
- TEST COM2.Comm_Xflags,FC_XOFF_RCVD ; Was XOFF received? **XMIT*XON*FIX**
- JE txbug_no_fc3 ; no - check handshaking **XMIT*XON*FIX**
- JMP _ireq3_exit ; wait for XON to xmit **XMIT*XON*FIX**
-
- ; **XMIT*XON*FIX**
- ; THRE is empty - if h/w handshake is enabled check modem signals. **XMIT*XON*FIX**
- ; (Note: 8250 bug will be overcome when the modem signals change and cause **XMIT*XON*FIX**
- ; an interrupt). **XMIT*XON*FIX**
- ; **XMIT*XON*FIX**
- txbug_no_fc3: ;**XMIT*XON*FIX**
- CMP [SI].Comm_DTR_RTS, 0 ; see if handshaking disabled **XMIT*XON*FIX**
- ; JE _ireq3_ckxmt3 ; handshaking is off, go xmit data! **XMIT*XON*FIX**
- jne tempaa ; rel jump out of range
- jmp _ireq3_ckxmt3
- tempaa:
- MOV DX, C2+MSR ; read in modem status register to **XMIT*XON*FIX**
- IN AL, DX ; clear interrupt **XMIT*XON*FIX**
- ; look for Hardware Handshaking flag
- and al, [si].Comm_DTR_RTS ; look for CTS and/or DSR
- cmp al, [si].Comm_DTR_RTS ; Unable to Xmit if Hardware Handshaking and CTS/DST not set
- ; AND AL, 00110000B ; look for CTS and DSR **XMIT*XON*FIX**
- ; CMP AL, 00110000B ; **XMIT*XON*FIX**
- JE _ireq3_ckxmt3 ; CTS/DSR ok, go xmit data **XMIT*XON*FIX**
- JMP _ireq3_exit ; can't xmit now so exit **XMIT*XON*FIX**
-
- ; AL contains bits 0-3 of IIR. Check if IIR bit 2 (04h)is set (Receive
- ; Data Available) or if both IIR bits 2 and 3 (0Ch) are set
- ; (Character Timeout Indication - Receive Data Available).
- _ireq3_ckrec:
- ; test al, 0CH ; Got a character to read?
- cmp al, 04H ; Got a character to read?
- jnz _ireq3_charto ; No
- jmp _ireq3_dataready ; Yes - go process it
- _ireq3_charto:
- cmp al, 0CH ; Got a character to read?
- jnz _ireq3_ckxmt ; No
- jmp _ireq3_dataready ; Yes - go process it
-
- _ireq3_ckxmt: ; AL contains bits 0-3 of IIR.
- CMP AL, 02H ; Ready to xmit a character? (Check Xmit Holding Reg Empty)
- ; JNE _ireq3_ckmsr ; No ; Rel Jump Out of range
- je _ireq3_xmt_enter
- jmp _ireq3_ckmsr ; No
-
- ; Transmit interrupt generated!!!!!!!!
- _ireq3_xmt_enter: ; Xmit chars if there are any to Xmit
-
- IFDEF INT_EXITS
- TEST_EXIT_SEND cs:com2_mask, cs:com2_func, 1
- ENDIF
-
- TEST COM2.Comm_Xflags,FC_TX_ON ;Is flow control enabled
- JE no_fc3
- TEST COM2.Comm_Xflags,FC_XOFF_RCVD ;Was XOFF received
- ;rel jmp OOR JNE _ireq3_tryall ;If so we cannot xmit
- JE no_fc3
- JMP _ireq3_tryall
- no_fc3:
- CMP [SI].Comm_DTR_RTS, 0 ;2.0a see if handshaking disabled
- JE _ireq3_ckxmt3
- MOV DX, C2+MSR ; Yes- read in modem status register to
- IN AL, DX ; clear interrupt
-
- ; look for Hardware Handshaking flag
- and al, [si].Comm_DTR_RTS ; look for CTS and/or DSR
- cmp al, [si].Comm_DTR_RTS ; Unable to Xmit if Hardware Handshaking and CTS/DST not set
- ; AND AL, 00110000B ; look for CTS and DSR
- ; CMP AL, 00110000B ; Unable to Xmit if Hardware Handshaking and CTS/DST not set
- ; rel jmp OOR JNE _ireq3_tryall ; try again if no CTS/DSR
- JE xx1
- JMP _ireq3_tryall
- xx1:
-
- ; Xmit Interrupt Received, all clear to stuff Xmit buffer.
- ; When the Xmit FIFO is enabled (FCR0=1), Xmit interrupts will occur
- ; as follows: The transmitter holding register interrupt (02) occurs
- ; when the Xmit FIFO is empty. It is cleared as soon as the transmitter
- ; holding register is written to (1 to 16 characters may be written to
- ; the Xmit FIFO while servicing this interrupt) or the IIR is read.
- _ireq3_ckxmt3:
- ; Check if our UART mode indicates FIFOs are enabled
- ; Allowable values for "COMM_UART_Mode" are:
- ; 0 = 16440 (16550 Character) mode
- ; 1 = 16550 FIFOs enabled, DMA mode 0
- ; 9 = 16550 FIFOs enabled, DMA mode 1 (This mode is not used)
-
- test [si].COMM_UART_Mode, 09h
- jz _ireq3_x1char ; FIFOs not present or not enabled
-
- SI_FIFO_continue ; Stuff up to 16 chars in Xmit FIFO
- jmp _ireq3_tryall ; Now go see if anything else is pending
-
- _ireq3_x1char: ; Xmit 1 character
- SI_continue ; Xmit next char in Xmit buffer
- jmp _ireq3_tryall ; Now go see if anything else is pending
-
- ; No chars received, no chars to Xmit
- _ireq3_ckmsr:
- CMP AL, 00H ; Change in modem status? (AL contains bits 0-3 of IIR)
- JNE _ireq3_ckerr ; No - check for error or break
- _ireq3_ckmsr2: ;
- MOV DX, C2+MSR ; Yes- read in modem status register to
- IN AL, DX ; clear interrupt
-
- IFDEF INT_EXITS
- TEST_EXIT_MSR cs:com2_mask, cs:com2_func, 1
- ENDIF
-
- CMP [SI].Comm_DTR_RTS, 0 ; See if handshaking enabled
- ; JE _ireq3_tryall ; Now go see if anything else is pending
- JNE _ireq3_ckmsr3 ; JE above relative JMP out of range
- JMP _ireq3_tryall
- _ireq3_ckmsr3:
- MOV DX, C2+LSR
- IN AL, DX
- ; Check Xmit Holding Reg (LSR bit 6) and Xmit Empty (LSR bit 7) bits
- AND AL, 60h ; See if ready to transmit
- CMP AL, 60h
- ; JE _ireq3_ckxmt2 ; Relative Jump Out Of Range
- jne _ireq3_1rjor
- jmp _ireq3_xmt_enter ; go to start of Xmit char processing
- _ireq3_1rjor:
- jmp _ireq3_tryall ; Now go see if anything else is pending
-
-
- _ireq3_ckerr: ;
- CMP AL, 06H ; Got a rec'd char w/error or break?
- ;** JNE _ireq3_tryall ; No
- JE _ireq3_ckerr2 ; Relative jmp out of range
- JMP _ireq3_tryall
- _ireq3_ckerr2:
- MOV DX, C2+LSR ; Yes- read in line status register to
- IN AL, DX ; clear interrupt
-
- IFDEF INT_EXITS
- TEST_EXIT_ERR cs:com2_mask, cs:com2_func, 1
- ENDIF
-
- mov BYTE PTR [si].Comm_Break, al
- JMP _ireq3_tryall ; Now go see if anything else is pending
-
-
- _ireq3_exit:
- MOV AL, 20h ; Acknowledge interrupt
- OUT EOI, AL
- POP AX ; Restore registers
- POP BX
- POP CX
- POP DX
- POP SI
- POP DI
- POP ES
- POP DS
- IRET
-
- ; Read and Store character
- ; Data has been received (IIR is 04h or 0Ch); AL contains bits 0-3 of IIR
- _ireq3_dataready:
- ; Check if 16550 is present and if FIFOs are enabled
-
- test [si].COMM_UART_Mode, 09h
- jz _ireq3_noFIFO_dataready ; FIFOs not present or not enabled
- jmp _ireq3_FIFO_dataready ; FIFOs are present and enabled
-
- _ireq3_noFIFO_dataready:
- ; Read received character
- MOV DX, C2+TX_RD_BUFF_DLLO
- IN AL, DX ; Read character received
-
- IFDEF INT_EXITS
- TEST_EXIT_REC cs:com2_mask, cs:com2_func, _ireq3_tryall, 1
- ENDIF
-
- ; Check if Xmit Flow Control has been enabled
- TEST COM2.Comm_Xflags,FC_TX_ON ;Is flow control enabled
- JE no_fc3r
- CMP AL, XOFF ; Compare incomming char to XOFF
- JNE _ireq3fc_rskip1
- OR COM2.Comm_Xflags, FC_XOFF_RCVD ; Incoming XOFF, pause xmission
- JMP _ireq3_tryall
- _ireq3fc_rskip1:
- CMP AL, XON
- JNE _ireq3fc_rskip2
- AND COM2.Comm_Xflags, NOT FC_XOFF_RCVD ; Incoming XON, continue xmission
- IFDEF WQ
- OR COM2.Comm_Xflags, FC_FIRST_XON ; Got 1st XON - WQ
- ENDIF
- SI_continue ; Xmit next char in Xmit buffer if there is a char to Xmit
- JMP _ireq3_tryall
- _ireq3fc_rskip2:
-
- no_fc3r: ; No Flow Control Enabled
- MOV DX, COM2.Comm_CR_BUFFR_Segment
- MOV ES, DX
- MOV DI, COM2.Comm_CR_BUFFR_Offset
- MOV DX, COM2.Comm_CR_BUFFR_Index
- ADD DI, DX
- STOSB ; Store Char in receive buffer
- ; Increment Index into receive buffer
- ADD WORD PTR COM2.Comm_Receive_Count, 1
- ADC WORD PTR COM2.Comm_Receive_Count + 2, 0
- INC DX
- CMP DX, BUFFER_SIZE
- JNZ _ireq3_cont
-
- ; Optionally, add another buffer
-
- PUSH CX ; REV 1.2 ECL0006
- CALL BUFFR_Gmem ; Get next available buffer
- POP CX ; REV 1.2 ECL0006
- JC _ireq3_nobuff ; None available
- ; Increment next buffer information
- INC COM2.Comm_Buffer_Count
- MOV DI, COM2.Comm_CR_BUFFR_Offset
- MOV ES:[DI], BX ; Save pointer in previous last block
- MOV ES:[DI+2], DX
- MOV COM2.Comm_CR_BUFFR_Offset, BX
- MOV COM2.Comm_CR_BUFFR_Segment, DX
- MOV DX, 4 ; New index
-
- _ireq3_cont:
- ; Store Updated Receive Buffer Index in COMMS structure
- MOV COM2.Comm_CR_BUFFR_Index, DX
-
- TEST COM2.Comm_Xflags,FC_REC_ON ;Is flow control enabled
- JNE ck3_hi
- JMP _ireq3_tryall
- ck3_hi: ; check high flow control mark
- TEST COM2.Comm_Xflags, FC_XOFF_SENT ; Outgoing XOFF already sent
- JE ck3_hi_2
- JMP _ireq3_tryall
- ck3_hi_2:
- ;**** don't check high word, XON/XOFF only supported < 64K
- ;**** CMP WORD PTR COM2.Comm_Receive_Count+2, 0
- ;**** JNE over3_high
- MOV AX, COM2.Comm_high
- CMP WORD PTR COM2.Comm_Receive_Count, AX
- JGE over3_high
- JMP _ireq3_tryall
- over3_high:
- ; have to send XOFF
- MOV DX, C2+LSR ; get line status
- IN AL, DX
- ; Any error is revealed via LSR bits 1-4 when it's
- ; associated character is at the top of the FIFO
- TEST AL, 01h ; has a char come in
- JE over3_cont
- JMP _ireq3_noFIFO_dataready ; if so, go get it
- over3_cont:
- TEST AL, 40h ; look at TX ready bits
- JE over3_high ; wait for TX OK
- SUB DX, LSR
- MOV AL, XOFF
- OUT DX, AL ; Xmit XOFF
- OR COM2.Comm_Xflags, FC_XOFF_SENT
-
- JMP _ireq3_tryall
-
-
- ; No more Receive Buffer space available; Next Character received will
- ; overwrite the last character received.
- _ireq3_nobuff: ; None available
- SUB WORD PTR COM2.Comm_Receive_Count, 1
- SBB WORD PTR COM2.Comm_Receive_Count + 2, 0
- JMP _ireq3_tryall
-
- ;*************************************************************************
- ; The following code is executed if the Uart has it's FIFOS enabled.
- ;*************************************************************************
- ; If the Receive FIFOs are enabled, then the code will loop until
- ; the Receive FIFO is empty. Bit 0 of the Line Status Register is
- ; set to one whenever at least 1 character is in the Recieve Buffer
- ; Register. This bit (LSR bit0) is set to zero by reading all data
- ; in the receive buffer or FIFO.
-
- _ireq3_FIFO_dataready:
- ; Read received character
- MOV DX, C2+TX_RD_BUFF_DLLO
- IN AL, DX ; Read character received
-
- IFDEF INT_EXITS
- TEST_EXIT_REC cs:com2_mask, cs:com2_func, _ireq3_tryall, 1
- ENDIF
-
- ; Check if Xmit Flow Control has been enabled
- TEST COM2.Comm_Xflags,FC_TX_ON ;Is flow control enabled
- JE no_fc3rFIFO
- CMP AL, XOFF ; Compare incomming char to XOFF
- JNE _ireq3fc_FIFOrskip1
- OR COM2.Comm_Xflags, FC_XOFF_RCVD ; Incoming XOFF, pause xmission
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _ireq3_check_data_ready
-
- _ireq3fc_FIFOrskip1:
- CMP AL, XON
- JNE _ireq3fc_FIFOrskip2
- AND COM2.Comm_Xflags, NOT FC_XOFF_RCVD ; Incoming XON, continue xmission
- IFDEF WQ
- OR COM2.Comm_Xflags, FC_FIRST_XON ; Got 1st XON - WQ
- ENDIF
- SI_continue ; Xmit next char in Xmit buffer if there is a char to Xmit
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _ireq3_check_data_ready
-
- _ireq3fc_FIFOrskip2:
-
- no_fc3rFIFO: ; No Flow Control Enabled
- ; Get ECL Receive buffer location
- MOV DX, COM2.Comm_CR_BUFFR_Segment
- MOV ES, DX
- MOV DI, COM2.Comm_CR_BUFFR_Offset
- MOV DX, COM2.Comm_CR_BUFFR_Index
- ADD DI, DX
- STOSB ; Store Char in receive buffer
- ; Increment Index into receive buffer
- ADD WORD PTR COM2.Comm_Receive_Count, 1
- ADC WORD PTR COM2.Comm_Receive_Count + 2, 0
- INC DX
- CMP DX, BUFFER_SIZE
- JNZ _ireq3_contFIFO
-
- ; Optionally, add another buffer
-
- PUSH CX ; REV 1.2 ECL0006
- CALL BUFFR_Gmem ; Get next available buffer
- POP CX ; REV 1.2 ECL0006
- JC _ireq3_FIFOrjor6 ; No Buffers available
- jmp _ireq3_FIFOrjor7 ; Buffers available
- _ireq3_FIFOrjor6:
- jmp _ireq3_FIFOnobuff ; No Buffers available
- _ireq3_FIFOrjor7:
- ; Increment next buffer information
- INC COM2.Comm_Buffer_Count
- MOV DI, COM2.Comm_CR_BUFFR_Offset
- MOV ES:[DI], BX ; Save pointer in previous last block
- MOV ES:[DI+2], DX
- MOV COM2.Comm_CR_BUFFR_Offset, BX
- MOV COM2.Comm_CR_BUFFR_Segment, DX
- MOV DX, 4 ; New index
-
- _ireq3_contFIFO:
- ; Store Updated Receive Buffer Index in COMMS structure
- MOV COM2.Comm_CR_BUFFR_Index, DX
-
- TEST COM2.Comm_Xflags,FC_REC_ON ;Is Receive flow control enabled
- JNE ck3_hi_FIFO
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _ireq3_check_data_ready
-
- ck3_hi_FIFO: ; check high flow control mark
- TEST COM2.Comm_Xflags, FC_XOFF_SENT ; Outgoing XOFF already sent
- JE ck3_hi_2_FIFO
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _ireq3_check_data_ready
-
- ck3_hi_2_FIFO:
- ;**** don't check high word, XON/XOFF only supported < 64K
- ;**** CMP WORD PTR COM2.Comm_Receive_Count+2, 0
- ;**** JNE over3_high
- MOV AX, COM2.Comm_high
- CMP WORD PTR COM2.Comm_Receive_Count, AX
- JGE over3_high_FIFO
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _ireq3_check_data_ready
-
- over3_high_FIFO:
- ; have to send XOFF
- MOV DX, C2+LSR ; get line status
- IN AL, DX
- ; Any error is revealed via LSR bits 1-4 when it's associated
- ; character is at the top of the FIFO
- TEST AL, 01h ; has a char come in
- JE over3_cont_FIFO
- JMP _ireq3_FIFO_dataready ; if so, go get it
-
- over3_cont_FIFO:
- TEST AL, 40h ; look at TX ready bits
- JE over3_high_FIFO ; wait for TX OK
- SUB DX, LSR
- MOV AL, XOFF
- OUT DX, AL ; Xmit XOFF
- OR COM2.Comm_Xflags, FC_XOFF_SENT
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _ireq3_check_data_ready
-
- ; No more Receive Buffer space available; Next Character received will
- ; overwrite the last character received.
- _ireq3_FIFOnobuff: ; None available
- SUB WORD PTR COM2.Comm_Receive_Count, 1
- SBB WORD PTR COM2.Comm_Receive_Count + 2, 0
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- _ireq3_check_data_ready:
- mov dx, C2+LSR ; Load Line Status reg address
- in al, dx ; Get LSR
- test al, 01h ; Test for Receive FIFO empty
- jnz _ireq3_FIFO_rjor1 ; Get next character in Receive FIFO
- JMP _ireq3_tryall
- _ireq3_FIFO_rjor1: ; Relative Jump Out Of Range
- jmp _ireq3_FIFO_dataready ; Get next character in Receive FIFO
- ;*********************************************************************
-
- IREQ3 ENDP
-
- ;*********************************************************************
- ;
- ; Shared Interrupt Service Routine
- ;
- ; IREQSHARE 1 First determine which UART interrupted:
- ; COM1, COM2, COM3, ... COM8
- ; 2 Then branch off if FLOW CONTROL enabled for that interrupt
- ;
-
- IREQSHARE PROC FAR ; Shared code IREQ for COM2, COM3, and COM4
- PUSH DS ; Save segments
- PUSH ES ; Removed the LINE BREAK code!
- PUSH CS
- POP DS
- PUSH DI
- PUSH SI
- PUSH DX
- PUSH CX
- PUSH BX
- PUSH AX
- ; ---------------------------------------------------------------
- ; ---------------------------------------------------------------
- ; Determine what port interrupted
-
- share_startover:
- CMP board_type, DIGI8
- JE digicom8_ports ; jmp to DigiBoard PC/4 and PC/8 code
- CMP board_type, DIGIPC16
- JE digipc16_ports ; jmp to DigiBoard PC/16 code
- CMP board_type, DIGIMC
- JE digicomMC_ports
- CMP board_type, STAR8
- ; JE star8_ports ; rel jmp out of range
- JNE s1
- JMP star8_ports
- s1:
- CMP board_type, PS2
- ; JE ps2_ports ; rel jmp out of range
- JNE comm_int3
- JMP ps2_ports
- comm_int3:
- CMP board_type, AST
- ; JE ast_ports ; rel jmp out of range
- JNE s2
- JMP ast_ports
- s2:
- CMP board_type, ASTCMP
- ; JE astcmp_ports ; rel jmp out of range
- JNE comm_int1
- JMP astcmp_ports
- comm_int1: ; should never reach here
-
-
- digicomMC_ports:
- ;*** following code works for DIGIBORD Microchannel MC/X Boards ***
- MOV DX, Status_port
- IN AX, DX ; Read 16 bit status port
- CMP AX, 0 ; Check if any ports are active
- JNZ digimc_cont
- JMP _share_exit ; Nope - false alarm (rel jump out of range)
- digimc_cont:
- MOV BX, starting_port
- MOV DX, 1
-
- share_which_portmc: ; loop until we find an active port
- test AX, DX
- ; JNZ share_int_here ; rel jmp out of range
- JZ s3
- JMP share_int_here ; found active port w/ BX point to comm unit
- s3:
- SHL DX, 1
- ADD BX, 2 ; Make BX point to comm unit * 2
- JMP share_which_portmc
-
- digipc16_ports:
- ;*** following code works for DIGIBORD PC/16
- MOV DX, Status_port ;
- IN AL, DX ; Read status port first set of 8 ports
- CMP AL, -1 ; FFh in status port = no interrupt pending
- JNZ digi_cont ; board # indicates either ports 1-8 or 9-16
- INC DX ; status port address for next set of 8 ports
- IN AL, DX ; Read status port for next set of 8 ports
- CMP AL, -1 ; FFh in status port = no interrupt pending
- JNZ digi_cont ; board # indicates either ports 1-8 or 9-16
- JMP _share_exit ; Nope - false alarm (rel jump out of range)
-
- digicom8_ports:
- ;*** following code works for DIGIBORD PC/4 & PC/8
- MOV DX, Status_port ; get status port address
- ; Determine if the digiboard is generating an even or odd IRQ
- MOV AL, SHARED_VECTOR
- AND AX,1 ; check if bit zero is set (for odd IRQ)
- ; if even IRQ, add 1 to status port address
- JNZ digi_odd_irq ; odd IRQ, don't increment status port adress
- INC DX ; even IRQ, increment status port adress
- digi_odd_irq:
- IN AL, DX ; Read status port
- CMP AL, -1 ; FFh in status port = no interrupt pending
- JNZ digi_cont
- JMP _share_exit ; Nope - false alarm (rel jump out of range)
- digi_cont:
- PUSH AX ; save which board bits
- AND AX, 07h ; *** will only work for 8 ports so far ***
- SHL AX, 01
- MOV BX, AX ; Make BX point to comm unit * 2
- ADD BX, starting_port ; have to consider starting at COM3
- POP AX
- AND AX, 18H ; mask board number bits
- ; JZ share_int_here ; board zero - rel jmp out of range
- JNZ comm_int7
- JMP share_int_here
- comm_int7:
- SHR AX, 1 ; isolate board bits
- SHR AX, 1
- SHR AX, 1
- CMP AX, 1
- JE board2 ; if second board
- CMP AX, 2
- JE board3 ; if third board
- ADD BX, 48 ; must be fourth board
- JMP share_int_here
- board3:
- ADD BX, 32
- JMP share_int_here
- board2:
- ADD BX, 16
- JMP share_int_here
-
-
- ps2_ports:
- ; Determine what port interrupted
- MOV CX, maxshare
- MOV BX, starting_port ; Start at COM2
- id_loop1:
- MOV SI, Port_Table[BX] ; Point to Comms_Str entry
-
- SI_REG IIR
- and al, 0Fh ; Isolate bits 0-3 of IIR
- CMP AL, 01H ; Any more interrupts pending?
- JE _share_advance
- JMP _share_ckrec ; Jump if we have int here
-
- ; Advance to next communications port
-
- _share_advance:
- ADD BX, 2 ; Point to next entry
- LOOP id_loop1 ; Go back for to try the next COMx
- JMP _share_exit
- ; ---------------------------------------------------------------
-
-
- star8_ports:
- ;**** following code works for STARGATE PLUS8
- MOV DX, Status_port
- IN AL, DX ; Read status port
- ;*** AND AL, 0FFh
- CMP AL, 0h ; Zero if no ints pending
- JNE _share_cont8 ; Relative jump out of range
- JMP _share_exit ; Nope - false alarm
- _share_cont8:
- MOV BX, starting_port
- MOV AH, 1
- share_which_port8:
- test AL, AH
- JNZ share_int_here
- SHL AH, 1
- ADD BX, 2 ; Make BX point to comm unit * 2
- JMP share_which_port8
-
- ast_ports:
- ;**** following code works for AST 4port DOS and DFI MU440 in "Expanded Mode"
- MOV DX, Status_port
- IN AL, DX ; Read status port
- AND AL, 0Fh
- CMP AL, 0Fh
- JNE _share_cont4 ; Relative jump out of range
- JMP _share_exit ; Nope - false alarm
- _share_cont4:
- AND AX, 0Fh
- MOV BX, starting_port
- MOV AH, 1
- share_which_port:
- test AL, AH
- JZ share_int_here
- SHL AH, 1
- ADD BX, 2 ; Make BX point to comm unit * 2
- JMP share_which_port
-
- astcmp_ports:
- ;**** following code works for AST 4port DOS and DFI MU440 in "Compatible Mode"
- MOV DX, Status_port
- IN AL, DX ; Read status port
- ; look at bits 2 (1st shared port) and 3 (2ond shared port) of status register.
- ; If one of these bit is zero, then that is the port generating the interrupt.
- AND AL, 0Ch
- CMP AL, 0Ch ; when bits set to 1 - no interrupt.
- JNE _share_astcmp4 ; Relative jump out of range
- JMP _share_exit ; Nope - false alarm
- _share_astcmp4:
- AND AX, 0Ch
- MOV BX, starting_port
- MOV AH, 4 ; start with bit 3 of status register
- share_astcmp_port:
- test AL, AH
- JZ share_int_here
- SHL AH, 1
- ADD BX, 2 ; Make BX point to comm unit * 2
- JMP share_astcmp_port
-
-
- share_int_here:
- ; ---------------------------------------------------------------
- ; Check for receive interrupt
-
- MOV SI, Port_Table[BX] ; Point to Comms_Str entry
-
- SI_REG IIR
- and al, 0Fh ; Isolate bits 0-3 of IIR
- CMP AL, 01H ; Any more interrupts pending?
- JNE _share_ckrec ; JE out of range
- JMP share_startover ; No - false alarm somehow
-
- ; AL contains bits 0-3 of IIR. Check if IIR bit 2 (04h)is set (Receive
- ; Data Available) or if both IIR bits 2 and 3 (0Ch) are set
- ; (Character Timeout Indication - Receive Data Available).
- _share_ckrec:
- ; test al, 0CH ; Got a character to read?
- cmp al, 04H ; Got a character to read?
- jnz _share_charto ; No
- jmp _share_dataready ; Yes - go process it
- _share_charto:
- cmp al, 0CH ; Got a character to read?
- jnz _share_ckxmt ; No
- jmp _share_dataready ; Yes - go process it
-
- _share_ckxmt: ; AL contains bits 0-3 of IIR.
- CMP AL, 02H ; Ready to xmit a character?
- ; JNE _share_ckmsr ; No ; Rel Jump Out of range
- je _share_xmt_enter
- jmp _share_ckmsr ; No
-
-
- ; Transmit interrupt generated!!!!!!!!
- _share_xmt_enter: ; Xmit chars if there are any to Xmit
-
- IFDEF INT_EXITS
- push bx
- shr bx, 1
- TEST_EXIT_SEND cs:share1_mask, cs:share1_func, bx
- pop bx
- ENDIF
-
- TEST [SI].Comm_Xflags,FC_TX_ON ;Is flow control enabled
- JE share_no_fc3
- TEST [SI].Comm_Xflags,FC_XOFF_RCVD ;Was XOFF received
- JE share_no_fc3 ; Relative jump out of range
- JMP share_startover ;If so we cannot xmit
- share_no_fc3:
- CMP [SI].Comm_DTR_RTS, 0 ;2.0a see if handshaking disabled
- JE _share_ckxmt3
- SI_REG MSR ; Yes - read MSR to clear interrupt.
-
- ; look for Hardware Handshaking flag
- and al, [si].Comm_DTR_RTS ; look for CTS and/or DSR
- cmp al, [si].Comm_DTR_RTS ; Unable to Xmit if Hardware Handshaking and CTS/DST not set
- ; AND AL, 00110000B ; look for CTS and DSR
- ; CMP AL, 00110000B ;
- JE _share_ckxmt3 ; rel jump out of range
- JMP share_startover ; try again if no CTS/DSR
-
- ; Xmit Interrupt Received, all clear to stuff Xmit buffer.
- ; When the Xmit FIFO is enabled (FCR0=1), Xmit interrupts will occur
- ; as follows: The transmitter holding register interrupt (02) occurs
- ; when the Xmit FIFO is empty. It is cleared as soon as the transmitter
- ; holding register is written to (1 to 16 characters may be written to
- ; the Xmit FIFO while servicing this interrupt) or the IIR is read.
- _share_ckxmt3:
- ; Check if our UART mode indicates FIFOs are enabled
- ; Allowable values for "COMM_UART_Mode" are:
- ; 0 = 16440 (16550 Character) mode
- ; 1 = 16550 FIFOs enabled, DMA mode 0
- ; 9 = 16550 FIFOs enabled, DMA mode 1 (This mode is not used)
-
- test [si].COMM_UART_Mode, 09h
- jz _share_x1char ; FIFOs not present or not enabled
-
- SI_FIFO_continue ; Stuff up to 16 chars in Xmit FIFO
- jmp share_startover ; Now go see if anything else is pending
-
- _share_x1char: ; Xmit 1 character
- SI_continue ; Xmit next char in Xmit buffer
- jmp share_startover ; Now go see if anything else is pending
-
- ; No chars received, no chars to Xmit
- _share_ckmsr:
- CMP AL, 00H ; Change in modem status?
- JNE _share_ckerr ; No - check for error or break
- _share_ckmsr2: ;
- SI_REG MSR ; Yes- read in MSR to clear interrupt
-
- IFDEF INT_EXITS
- push bx
- shr bx, 1
- TEST_EXIT_MSR cs:share1_mask, cs:share1_func, bx
- pop bx
- ENDIF
- CMP [SI].Comm_DTR_RTS, 0 ; See if handshaking enabled
- JNE _share_cont1 ; relative jump was out of range
- JMP share_startover ; Now go see if anything else is pending
- _share_cont1:
- SI_REG LSR
- ; Check Xmit Holding Reg (LSR bit 6) and Xmit Empty (LSR bit 7) bits
- AND AL, 60h ; See if ready to transmit
- CMP AL, 60h
- ; JE _share_xmt_enter; go to start of Xmit char processing
- ; JMP share_startover ; Now go see if anything else is pending
- jne _share_1rjor
- jmp _share_xmt_enter ; go to start of Xmit char processing
- _share_1rjor:
- jmp share_startover ; Now go see if anything else is pending
-
- _share_ckerr: ;
- CMP AL, 06H ; Got a rec'd char w/error or break?
- JE _share_cont2 ; Relative jump out of range
- JMP share_startover ; No
- _share_cont2:
- SI_REG LSR ; Yes- read in LSR to clear interrupt
-
- IFDEF INT_EXITS
- push bx
- shr bx, 1
- TEST_EXIT_ERR cs:share1_mask, cs:share1_func, bx
- pop bx
- ENDIF
- mov BYTE PTR [si].Comm_Break, al
- JMP share_startover ; Now go see if anything else is pending
-
-
- _share_exit:
- MOV AL, 20h ; Acknowledge interrupt
- OUT EOI, AL
- POP AX ; Restore registers
- POP BX
- POP CX
- POP DX
- POP SI
- POP DI
- POP ES
- POP DS
- IRET
-
- ; Read and Store character
- ; Data has been received (IIR is 04h or 0Ch); AL contains bits 0-3 of IIR
- _share_dataready:
- ; Check if 16550 is present and if FIFOs are enabled
- test [si].COMM_UART_Mode, 09h
- jz _share_noFIFO_dataready ; FIFOs not present or not enabled
- jmp _share_FIFO_dataready ; FIFOs are present and enabled
-
- _share_noFIFO_dataready:
- ; Read received character
- SI_REG TX_RD_BUFF_DLLO ; Read character received
-
- IFDEF INT_EXITS
- push bx
- shr bx, 1
- TEST_EXIT_REC cs:share1_mask, cs:share1_func,clrbx1 ,bx
- pop bx
- jmp short ok10
- clrbx1:
- pop bx
- jmp share_startover
- ok10:
- ENDIF
-
-
- ; Check if Xmit Flow Control has been enabled
- TEST [SI].Comm_Xflags,FC_TX_ON ;Is flow control enabled
- JE share_no_fc3r
- CMP AL, XOFF
- JNE _sharefc_rskip1
- OR [SI].Comm_Xflags, FC_XOFF_RCVD ; Incoming XOFF, pause xmission
- JMP share_txbug
- _sharefc_rskip1:
- CMP AL, XON
- JNE _sharefc_rskip2
- AND [SI].Comm_Xflags, NOT FC_XOFF_RCVD ; Incoming XON, continue xmission
- SI_continue ; Xmit next char in Xmit buffer if there is a char to Xmit
- JMP share_txbug
- _sharefc_rskip2:
-
- share_no_fc3r: ; No Flow Control Enabled
- ; Get ECL Receive buffer location
- MOV DX, [SI].Comm_CR_BUFFR_Segment
- MOV ES, DX
- MOV DI, [SI].Comm_CR_BUFFR_Offset
- MOV DX, [SI].Comm_CR_BUFFR_Index
- ADD DI, DX
- STOSB ; Store Char in receive buffer
- ; Increment Index into receive buffer
- ADD WORD PTR [SI].Comm_Receive_Count, 1
- ADC WORD PTR [SI].Comm_Receive_Count + 2, 0
- INC DX
- CMP DX, BUFFER_SIZE
- JNZ _share_cont
-
- ; Optionally, add another buffer
-
- PUSH CX ; REV 1.2 ECL0006
- CALL BUFFR_Gmem ; Get next available buffer
- POP CX ; REV 1.2 ECL0006
- JC _share_nobuff ; None available
- ; Increment next buffer information
- INC [SI].Comm_Buffer_Count
- MOV DI, [SI].Comm_CR_BUFFR_Offset
- MOV ES:[DI], BX ; Save pointer in previous last block
- MOV ES:[DI+2], DX
- MOV [SI].Comm_CR_BUFFR_Offset, BX
- MOV [SI].Comm_CR_BUFFR_Segment, DX
- MOV DX, 4 ; New index
-
- _share_cont:
- ; Store Updated Receive Buffer Index in COMMS structure
- MOV [SI].Comm_CR_BUFFR_Index, DX
-
- TEST [SI].Comm_Xflags,FC_REC_ON ;Is flow control enabled
- JNE share_ck3_hi
- JMP share_txbug
- share_ck3_hi: ; check high flow control mark
- TEST [SI].Comm_Xflags, FC_XOFF_SENT ; Outgoing XOFF already sent
- JE share_ck3_hi_2
- JMP share_txbug
- share_ck3_hi_2:
- ;**** don't check high word, XON/XOFF only supported < 64K
- ;**** CMP WORD PTR [SI].Comm_Receive_Count+2, 0
- ;**** JNE over3_high
- MOV AX, [SI].Comm_high
- CMP WORD PTR [SI].Comm_Receive_Count, AX
- JGE share_over3_high
- JMP share_txbug
- share_over3_high:
- ; have to send XOFF
- SI_REG LSR ; get line status
- ; Any error is revealed via LSR bits 1-4 when it's associated
- ; character is at the top of the FIFO
- TEST AL, 01h ; has a char come in
- JE share_over3_cont
- jmp _share_noFIFO_dataready ; if so, go get it
- share_over3_cont:
- TEST AL, 40h ; look at TX ready bits
- JE share_over3_high ; wait for TX OK
- SUB DX, LSR
- MOV AL, XOFF
- OUT DX, AL ; Xmit XOFF
- OR [SI].Comm_Xflags, FC_XOFF_SENT
-
- JMP share_txbug
-
-
- ; No more Receive Buffer space available; Next Character received will
- ; overwrite the last character received.
- _share_nobuff: ; None available
- SUB WORD PTR [SI].Comm_Receive_Count, 1
- SBB WORD PTR [SI].Comm_Receive_Count + 2, 0
- JMP share_txbug
-
-
-
- ;*************************************************************************
- ; The following code is executed if the Uart has it's FIFOS enabled.
- ;*************************************************************************
- ; If the Receive FIFOs are enabled, then the code will loop until
- ; the Receive FIFO is empty. Bit 0 of the Line Status Register is
- ; set to one whenever at least 1 character is in the Recieve Buffer
- ; Register. This bit (LSR bit0) is set to zero by reading all data
- ; in the receive buffer or FIFO.
-
- _share_FIFO_dataready:
- ; Read received character
- SI_REG TX_RD_BUFF_DLLO ; Read character received
-
- IFDEF INT_EXITS
- push bx
- shr bx, 1
- TEST_EXIT_REC cs:share1_mask, cs:share1_func,clrbx2,bx
- pop bx
- jmp short ok11
- clrbx2:
- pop bx
- jmp _share_check_data_ready
- ok11:
- ENDIF
-
-
- ; Check if Xmit Flow Control has been enabled
- TEST [si].Comm_Xflags,FC_TX_ON ;Is flow control enabled
- JE share_no_fc3rFIFO
- CMP AL, XOFF ; Compare incomming char to XOFF
- JNE _sharefc_FIFOrskip1
- OR [si].Comm_Xflags, FC_XOFF_RCVD ; Incoming XOFF, pause xmission
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _share_check_data_ready
-
- _sharefc_FIFOrskip1:
- CMP AL, XON
- JNE _sharefc_FIFOrskip2
- AND [si].Comm_Xflags, NOT FC_XOFF_RCVD ; Incoming XON, continue xmission
- IFDEF WQ
- OR [si].Comm_Xflags, FC_FIRST_XON ; Got 1st XON - WQ
- ENDIF
- SI_continue ; Xmit next char in Xmit buffer if there is a char to Xmit
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _share_check_data_ready
-
- _sharefc_FIFOrskip2:
-
- share_no_fc3rFIFO: ; No Flow Control Enabled
- ; Get ECL Receive buffer location
- MOV DX, [si].Comm_CR_BUFFR_Segment
- MOV ES, DX
- MOV DI, [si].Comm_CR_BUFFR_Offset
- MOV DX, [si].Comm_CR_BUFFR_Index
- ADD DI, DX
- STOSB ; Store Char in receive buffer
- ; Increment Index into receive buffer
- ADD WORD PTR [si].Comm_Receive_Count, 1
- ADC WORD PTR [si].Comm_Receive_Count + 2, 0
- INC DX
- CMP DX, BUFFER_SIZE
- JNZ _share_contFIFO
-
- ; Optionally, add another buffer
-
- PUSH CX ; REV 1.2 ECL0006
- CALL BUFFR_Gmem ; Get next available buffer
- POP CX ; REV 1.2 ECL0006
- JC _share_FIFOrjor6 ; No Buffers available
- jmp _share_FIFOrjor7 ; Buffers available
- _share_FIFOrjor6:
- jmp _share_FIFOnobuff ; No Buffers available
- _share_FIFOrjor7:
- ; Increment next buffer information
- INC [si].Comm_Buffer_Count
- MOV DI, [si].Comm_CR_BUFFR_Offset
- MOV ES:[DI], BX ; Save pointer in previous last block
- MOV ES:[DI+2], DX
- MOV [si].Comm_CR_BUFFR_Offset, BX
- MOV [si].Comm_CR_BUFFR_Segment, DX
- MOV DX, 4 ; New index
-
- _share_contFIFO:
- ; Store Updated Receive Buffer Index in COMMS structure
- MOV [si].Comm_CR_BUFFR_Index, DX
-
- TEST [si].Comm_Xflags,FC_REC_ON ;Is Receive flow control enabled
- JNE share_ck3_hi_FIFO
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _share_check_data_ready
-
- share_ck3_hi_FIFO: ; check high flow control mark
- TEST [si].Comm_Xflags, FC_XOFF_SENT ; Outgoing XOFF already sent
- JE share_ck3_hi_2_FIFO
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _share_check_data_ready
-
- share_ck3_hi_2_FIFO:
- ;**** don't check high word, XON/XOFF only supported < 64K
- ;**** CMP WORD PTR COM2.Comm_Receive_Count+2, 0
- ;**** JNE over3_high
- MOV AX, [si].Comm_high
- CMP WORD PTR [si].Comm_Receive_Count, AX
- JGE share_over3_high_FIFO
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _share_check_data_ready
-
- share_over3_high_FIFO:
- ; have to send XOFF
- SI_REG LSR ; get line status
- ; Any error is revealed via LSR bits 1-4 when it's associated
- ; character is at the top of the FIFO
- TEST AL, 01h ; has a char come in
- JE share_over3_cont_FIFO
- JMP _share_FIFO_dataready ; if so, go get it
-
- share_over3_cont_FIFO:
- TEST AL, 40h ; look at TX ready bits
- JE share_over3_high_FIFO ; wait for TX OK
- SUB DX, LSR
- MOV AL, XOFF
- OUT DX, AL ; Xmit XOFF
- OR [si].Comm_Xflags, FC_XOFF_SENT
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _share_check_data_ready
-
- ; No more Receive Buffer space available; Next Character received will
- ; overwrite the last character received.
- _share_FIFOnobuff: ; None available
- SUB WORD PTR [si].Comm_Receive_Count, 1
- SBB WORD PTR [si].Comm_Receive_Count + 2, 0
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- _share_check_data_ready:
- SI_REG LSR ; get line status register
- test al, 01h ; Test for Receive FIFO empty
- jnz _share_FIFO_rjor1 ; Get next character in Receive FIFO
- JMP share_txbug
- _share_FIFO_rjor1: ; Relative Jump Out Of Range
- jmp _share_FIFO_dataready ; Get next character in Receive FIFO
-
- ;*********************************************************************
-
-
- share_txbug: ; code for 8250 TX bug goes here for multiports
- SI_REG LSR ; look for THRE to get around 8250 bug
- test al, 020H
- jnz _share_txbug ; have to check TX
- jmp share_startover
- ; AND AL, 20H ; isolate THRE
- ; CMP AL, 20H
- ; JE _share_txbug ; have to check TX
- ; JMP share_startover
- _share_txbug:
- CMP [SI].Comm_xcount, 0
- JE _share_txbug_exit
- JMP _share_xmt_enter
- _share_txbug_exit:
- JMP share_startover
-
- IREQSHARE ENDP
-
- ;
- ; Shared Interrupt Service Routine
- ;
- ; IREQSHARE2 1 First determine which UART interrupted:
- ; COM1, COM2, COM3, ... COM8
- ; 2 Then branch off if FLOW CONTROL enabled for that interrupt
- ;
-
- IREQSHARE2 PROC FAR ; Shared code IREQ for COM2, COM3, and COM4
- PUSH DS ; Save segments
- PUSH ES ; Removed the LINE BREAK code!
- PUSH CS
- POP DS
- PUSH DI
- PUSH SI
- PUSH DX
- PUSH CX
- PUSH BX
- PUSH AX
- ; ---------------------------------------------------------------
- ; ---------------------------------------------------------------
- ; Determine what port interrupted
-
- share2_startover:
- CMP board2_type, DIGI8
- JE digicom82_ports
- CMP board2_type, DIGIPC16
- JE digipc162_ports
- CMP board2_type, DIGIMC
- JE digicomMC2_ports
- CMP board2_type, STAR8
- ; JE star82_ports ; rel jmp out of range
- JNE s4
- JMP star82_ports
- s4:
- CMP board2_type, PS2
- ; JE ps22_ports ; rel jmp out of range
- JNE comm_int6
- JMP ps22_ports
- comm_int6:
- JMP ast2_ports
- CMP board2_type, AST
- ; JE ast2_ports ; rel jmp out of range
- JNE s5
- JMP ast2_ports
- s5:
- CMP board2_type, ASTCMP
- ; JE ast2cmp_ports ; rel jmp out of range
- JNE comm_int2
- JMP ast2cmp_ports
- comm_int2: ; should never get here
-
-
-
- digicomMC2_ports:
- ;*** following code works for DIGIBORD Microchannel COM/4 & COM/8
- MOV DX, Status2_port
- IN AX, DX ; Read status port
- CMP AX, 0
- JNZ digimc2_cont
- JMP _share2_exit ; Nope - false alarm (rel jump out of range)
- digimc2_cont:
- MOV BX, starting2_port
- MOV DX, 1
-
- share_which_portmc2:
- test AX, DX
- ; JNZ share2_int_here ; rel jmp out of range
- JZ s6
- JMP share2_int_here
- s6:
- SHL DX, 1
- ADD BX, 2 ; Make BX point to comm unit * 2
- JMP share_which_portmc2
-
-
- digipc162_ports: ; Second PC/16 , board number 1
- ;*** following code works for DIGIBORD PC/16
- MOV DX,Status2_port ;
- IN AL, DX ; Read status port first set of 8 ports
- CMP AL, -1 ; FFh in status port = no interrupt pending
- JNZ digi2_cont ; board # indicates either ports 1-8 or 9-16
- INC DX ; status port address for next set of 8 ports
- IN AL, DX ; Read status port for next set of 8 ports
- CMP AL, -1 ; FFh in status port = no interrupt pending
- JNZ digi2_cont ; board # indicates either ports 1-8 or 9-16
- JMP _share2_exit ; Nope - false alarm (rel jump out of range)
-
- digicom82_ports: ; Second PC/4 or PC/8 , board number 1
- ;*** following code works for DIGIBORD PC/4 & PC/8
- MOV DX, Status2_port ; get status port address
- ; Determine if the digiboard is generating an even or odd IRQ
- MOV AL, SHARED2_VECTOR
- AND AX,1 ; check if bit zero is set (for odd IRQ)
- ; if even IRQ, add 1 to status port address
- JNZ digi2_odd_irq ; odd IRQ, don't increment status port adress
- INC DX ; even IRQ, increment status port adress
- digi2_odd_irq:
- IN AL, DX ; Read status port
- CMP AL, -1 ; FFh in status port = no interrupt pending
- JNZ digi2_cont
- JMP _share2_exit ; Nope - false alarm (rel jump out of range)
- digi2_cont:
- PUSH AX ; save which board bits
- AND AX, 07h ; *** will only work for 8 ports so far ***
- SHL AX, 01
- MOV BX, AX ; Make BX point to comm unit * 2
- ADD BX, starting2_port ; have to consider starting at COM3
- POP AX
- AND AX, 18H ; mask board number bits
- ; JZ share2_int_here ; board zero rel jump out of range
- JNZ comm_int4
- JMP share2_int_here ; board zero
- comm_int4:
- SHR AX, 1 ; isolate board bits
- SHR AX, 1
- SHR AX, 1
- CMP AX, 1
- JE board2_2 ; if second board
- CMP AX, 2
- JE board2_3 ; if third board
- ADD BX, 48 ; must be fourth board
- JMP share2_int_here
- board2_3:
- ADD BX, 32
- JMP share2_int_here
- board2_2:
- ADD BX, 16
- JMP share2_int_here
-
-
- ps22_ports:
- ; Determine what port interrupted
- MOV CX, maxshare2
- MOV BX, starting2_port ; Start at COM2
- id2_loop1:
- MOV SI, Port_Table[BX] ; Point to Comms_Str entry
-
- SI_REG IIR
- and al, 0Fh ; Isolate bits 0-3 of IIR
- CMP AL, 01H ; Any more interrupts pending?
- JE _share2_advance
- JMP _share2_ckrec ; Jump if we have int here
-
- ; Advance to next communications port
-
- _share2_advance:
- ADD BX, 2 ; Point to next entry
- LOOP id2_loop1 ; Go back for to try the next COMx
- JMP _share2_exit
- ; ---------------------------------------------------------------
-
-
-
- star82_ports:
- ;**** following code works for STARGATE PLUS8
- MOV DX, Status2_port
- IN AL, DX ; Read status port
- ;*** AND AL, 0FFh
- CMP AL, 0h ; Zero if no ints pending
- JNE _share2_cont8 ; Relative jump out of range
- JMP _share2_exit ; Nope - false alarm
- _share2_cont8:
- MOV BX, starting2_port
- MOV AH, 1
- share2_which_port8:
- test AL, AH
- JNZ share2_int_here
- SHL AH, 1
- ADD BX, 2 ; Make BX point to comm unit * 2
- JMP share2_which_port8
-
- ast2_ports:
- ;**** following code works for AST 4port DOS and DFI MU440 in "Expanded Mode"
- MOV DX, Status2_port
- IN AL, DX ; Read status port
- AND AL, 0Fh
- CMP AL, 0Fh
- JNE _share2_cont4 ; Relative jump out of range
- JMP _share2_exit ; Nope - false alarm
- _share2_cont4:
- AND AX, 0Fh
- MOV BX, starting2_port
- MOV AH, 1
- share2_which_port:
- test AL, AH
- JZ share2_int_here
- SHL AH, 1
- ADD BX, 2 ; Make BX point to comm unit * 2
- JMP share2_which_port
-
- ast2cmp_ports:
- ;**** following code works for AST 4port DOS and DFI MU440 in "Compatible Mode"
- MOV DX, Status2_port
- IN AL, DX ; Read status port
- ; look at bits 2 (1st shared port) and 3 (2ond shared port) of status register.
- ; If one of these bit is zero, then that is the port generating the interrupt.
- AND AL, 0Ch
- CMP AL, 0Ch ; when bits set to 1 - no interrupt.
- JNE _share2_astcmp4 ; Relative jump out of range
- JMP _share2_exit ; Nope - false alarm
- _share2_astcmp4:
- AND AX, 0Ch
- MOV BX, starting2_port
- MOV AH, 4 ; start looking at bit 3 of status register
- share2_astcmp_port:
- test AL, AH
- JZ share2_int_here
- SHL AH, 1
- ADD BX, 2 ; Make BX point to comm unit * 2
- JMP share2_astcmp_port
-
-
-
- share2_int_here:
- ; ---------------------------------------------------------------
- ; Check for receive interrupt
-
- MOV SI, Port_Table[BX] ; Point to Comms_Str entry
-
- SI_REG IIR
- and al, 0Fh ; Isolate bits 0-3 of IIR
- CMP AL, 01H ; Any more interrupts pending?
- JNE _share2_ckrec ; JE out of range
- JMP share2_startover ; No - false alarm somehow
-
- ; AL contains bits 0-3 of IIR. Check if IIR bit 2 (04h)is set (Receive
- ; Data Available) or if both IIR bits 2 and 3 (0Ch) are set
- ; (Character Timeout Indication - Receive Data Available).
- _share2_ckrec:
- ; test al, 0CH ; Got a character to read?
- cmp al, 04H ; Got a character to read?
- jnz _share2_charto ; No
- jmp _share2_dataready ; Yes - go process it
- _share2_charto:
- cmp al, 0CH ; Got a character to read?
- jnz _share2_ckxmt ; No
- jmp _share2_dataready ; Yes - go process it
-
- _share2_ckxmt: ;
- CMP AL, 02H ; Ready to xmit a character?
- ; JNE _share2_ckmsr ; No ; Rel Jump Out of range
- je _share2_xmt_enter
- jmp _share2_ckmsr ; No
-
-
- ; Transmit interrupt generated!!!!!!!!
- _share2_xmt_enter: ; Xmit chars if there are any to Xmit
- ; Transmit interrupt generated!!!!!!!!
-
- IFDEF INT_EXITS
- push bx
- shr bx, 1
- TEST_EXIT_SEND cs:share2_mask, cs:share2_func, bx
- pop bx
- ENDIF
-
- TEST [SI].Comm_Xflags,FC_TX_ON ;Is flow control enabled
- JE share2_no_fc3
- TEST [SI].Comm_Xflags,FC_XOFF_RCVD ;Was XOFF received
- JE share2_no_fc3 ; Relative jump out of range
- JMP share2_startover ;If so we cannot xmit
- share2_no_fc3:
- CMP [SI].Comm_DTR_RTS, 0 ;2.0a see if handshaking disabled
- JE _share2_ckxmt3
- SI_REG MSR ; Yes - read MSR to clear interrupt.
-
- ; look for Hardware Handshaking flag
- and al, [si].Comm_DTR_RTS ; look for CTS and/or DSR
- cmp al, [si].Comm_DTR_RTS ; Unable to Xmit if Hardware Handshaking and CTS/DST not set
- ; AND AL, 00110000B ; look for CTS and DSR
- ; CMP AL, 00110000B ;
- JE _share2_ckxmt3 ; rel jump out of range
- JMP share2_startover ; try again if no CTS/DSR
-
- ; Xmit Interrupt Received, all clear to stuff Xmit buffer.
- ; When the Xmit FIFO is enabled (FCR0=1), Xmit interrupts will occur
- ; as follows: The transmitter holding register interrupt (02) occurs
- ; when the Xmit FIFO is empty. It is cleared as soon as the transmitter
- ; holding register is written to (1 to 16 characters may be written to
- ; the Xmit FIFO while servicing this interrupt) or the IIR is read.
- _share2_ckxmt3:
- ; Check if our UART mode indicates FIFOs are enabled
- ; Allowable values for "COMM_UART_Mode" are:
- ; 0 = 16440 (16550 Character) mode
- ; 1 = 16550 FIFOs enabled, DMA mode 0
- ; 9 = 16550 FIFOs enabled, DMA mode 1 (This mode is not used)
-
- test [si].COMM_UART_Mode, 09h
- jz _share2_x1char ; FIFOs not present or not enabled
-
- SI_FIFO_continue ; Stuff up to 16 chars in Xmit FIFO
- jmp share2_startover; Now go see if anything else is pending
-
- _share2_x1char: ; Xmit 1 character
- SI_continue ; Xmit next char in Xmit buffer
- jmp share2_startover; Now go see if anything else is pending
-
- ; No chars received, no chars to Xmit
- _share2_ckmsr:
- CMP AL, 00H ; Change in modem status?
- JNE _share2_ckerr ; No - check for error or break
- _share2_ckmsr2: ;
- SI_REG MSR ; Yes- read in MSR to clear interrupt
-
- IFDEF INT_EXITS
- push bx
- shr bx, 1
- TEST_EXIT_MSR cs:share2_mask, cs:share2_func, bx
- pop bx
- ENDIF
- CMP [SI].Comm_DTR_RTS, 0 ; See if handshaking enabled
- JNE _share2_cont1 ; relative jump was out of range
- JMP share2_startover; Now go see if anything else is pending
- _share2_cont1:
- SI_REG LSR
- ; Check Xmit Holding Reg (LSR bit 6) and Xmit Empty (LSR bit 7) bits
- AND AL, 60h ; See if ready to transmit
- CMP AL, 60h
- ; JE _share2_xmt_enter; go to start of Xmit char processing
- ; JMP share2_startover; Now go see if anything else is pending
- jne _share2_1rjor
- jmp _share2_xmt_enter ; go to start of Xmit char processing
- _share2_1rjor:
- jmp share2_startover ; Now go see if anything else is pending
-
- _share2_ckerr: ;
- CMP AL, 06H ; Got a rec'd char w/error or break?
- JE _share2_cont2 ; Relative jump out of range
- JMP share2_startover; No
- _share2_cont2:
- SI_REG LSR ; Yes- read in LSR to clear interrupt
-
- IFDEF INT_EXITS
- push bx
- shr bx, 1
- TEST_EXIT_ERR cs:share2_mask, cs:share2_func, bx
- pop bx
- ENDIF
- mov BYTE PTR [si].Comm_Break, al
- JMP share2_startover; Now go see if anything else is pending
-
-
- _share2_exit:
- MOV AL, 20h ; Acknowledge interrupt
- OUT EOI, AL
- POP AX ; Restore registers
- POP BX
- POP CX
- POP DX
- POP SI
- POP DI
- POP ES
- POP DS
- IRET
-
- ; Read and Store character
- ; Data has been received (IIR is 04h or 0Ch); AL contains bits 0-3 of IIR
- _share2_dataready:
- ; Check if 16550 is present and if FIFOs are enabled
- test [si].COMM_UART_Mode, 09h
- jz _share2_noFIFO_dataready; FIFOs not present or not enabled
- jmp _share2_FIFO_dataready ; FIFOs are present and enabled
-
- _share2_noFIFO_dataready:
- ; Read received character
- SI_REG TX_RD_BUFF_DLLO ; Read character received
-
- IFDEF INT_EXITS
- push bx
- shr bx, 1
- TEST_EXIT_REC cs:share2_mask, cs:share2_func, clrbx3,bx
- pop bx
- jmp short ok12
- clrbx3:
- pop bx
- jmp share2_startover
- ok12:
- ENDIF
-
- ; Check if Xmit Flow Control has been enabled
- TEST [SI].Comm_Xflags,FC_TX_ON ;Is flow control enabled
- JE share2_no_fc3r
- CMP AL, XOFF
- JNE _share2fc_rskip1
- OR [SI].Comm_Xflags, FC_XOFF_RCVD ; Incoming XOFF, pause xmission
- JMP share2_txbug
- _share2fc_rskip1:
- CMP AL, XON
- JNE _share2fc_rskip2
- AND [SI].Comm_Xflags, NOT FC_XOFF_RCVD ; Incoming XON, continue xmission
- SI_continue
- JMP share2_txbug
- _share2fc_rskip2:
-
- share2_no_fc3r: ; No Flow Control Enabled
- ; Get ECL Receive buffer location
- MOV DX, [SI].Comm_CR_BUFFR_Segment
- MOV ES, DX
- MOV DI, [SI].Comm_CR_BUFFR_Offset
- MOV DX, [SI].Comm_CR_BUFFR_Index
- ADD DI, DX
- STOSB ; Store Char in receive buffer
- ; Increment Index into receive buffer
- ADD WORD PTR [SI].Comm_Receive_Count, 1
- ADC WORD PTR [SI].Comm_Receive_Count + 2, 0
- INC DX
- CMP DX, BUFFER_SIZE
- JNZ _share2_cont
-
- ; Optionally, add another buffer
-
- PUSH CX ; REV 1.2 ECL0006
- CALL BUFFR_Gmem ; Get next available buffer
- POP CX ; REV 1.2 ECL0006
- JC _share2_nobuff ; None available
- ; Increment next buffer information
- INC [SI].Comm_Buffer_Count
- MOV DI, [SI].Comm_CR_BUFFR_Offset
- MOV ES:[DI], BX ; Save pointer in previous last block
- MOV ES:[DI+2], DX
- MOV [SI].Comm_CR_BUFFR_Offset, BX
- MOV [SI].Comm_CR_BUFFR_Segment, DX
- MOV DX, 4 ; New index
-
- _share2_cont:
- ; Store Updated Receive Buffer Index in COMMS structure
- MOV [SI].Comm_CR_BUFFR_Index, DX
-
- TEST [SI].Comm_Xflags,FC_REC_ON ;Is flow control enabled
- JNE share2_ck3_hi
- JMP share2_txbug
- share2_ck3_hi: ; check high flow control mark
- TEST [SI].Comm_Xflags, FC_XOFF_SENT ; Outgoing XOFF already sent
- JE share2_ck3_hi_2
- JMP share2_txbug
- share2_ck3_hi_2:
- ;**** don't check high word, XON/XOFF only supported < 64K
- ;**** CMP WORD PTR [SI].Comm_Receive_Count+2, 0
- ;**** JNE over3_high
- MOV AX, [SI].Comm_high
- CMP WORD PTR [SI].Comm_Receive_Count, AX
- JGE share2_over3_high
- JMP share2_txbug
- share2_over3_high:
- ; have to send XOFF
- SI_REG LSR ; get line status
- ; Any error is revealed via LSR bits 1-4 when it's associated
- ; character is at the top of the FIFO
- TEST AL, 01h ; has a char come in
- JE share2_over3_cont
- jmp _share2_noFIFO_dataready ; if so, go get it
- share2_over3_cont:
- TEST AL, 40h ; look at TX ready bits
- JE share2_over3_high ; wait for TX OK
- SUB DX, LSR
- MOV AL, XOFF
- OUT DX, AL ; Xmit XOFF
- OR [SI].Comm_Xflags, FC_XOFF_SENT
-
- JMP share2_txbug
-
-
- ; No more Receive Buffer space available; Next Character received will
- ; overwrite the last character received.
- _share2_nobuff: ; None available
- SUB WORD PTR [SI].Comm_Receive_Count, 1
- SBB WORD PTR [SI].Comm_Receive_Count + 2, 0
- JMP share2_txbug
-
-
-
- ;*************************************************************************
- ; The following code is executed if the Uart has it's FIFOS enabled.
- ;*************************************************************************
- ; If the Receive FIFOs are enabled, then the code will loop until
- ; the Receive FIFO is empty. Bit 0 of the Line Status Register is
- ; set to one whenever at least 1 character is in the Recieve Buffer
- ; Register. This bit (LSR bit0) is set to zero by reading all data
- ; in the receive buffer or FIFO.
-
- _share2_FIFO_dataready:
- ; Read received character
- SI_REG TX_RD_BUFF_DLLO ; Read character received
-
-
- IFDEF INT_EXITS
- push bx
- shr bx, 1
- TEST_EXIT_REC cs:share2_mask, cs:share2_func,clrbx4 ,bx
- pop bx
- jmp short ok14
- clrbx4:
- pop bx
- jmp _share2_check_data_ready
- ok14:
- ENDIF
-
- ; Check if Xmit Flow Control has been enabled
- TEST [si].Comm_Xflags,FC_TX_ON ;Is flow control enabled
- JE share2_no_fc3rFIFO
- CMP AL, XOFF ; Compare incomming char to XOFF
- JNE _share2fc_FIFOrskip1
- OR [si].Comm_Xflags, FC_XOFF_RCVD ; Incoming XOFF, pause xmission
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _share2_check_data_ready
-
- _share2fc_FIFOrskip1:
- CMP AL, XON
- JNE _share2fc_FIFOrskip2
- AND [si].Comm_Xflags, NOT FC_XOFF_RCVD ; Incoming XON, continue xmission
- IFDEF WQ
- OR [si].Comm_Xflags, FC_FIRST_XON ; Got 1st XON - WQ
- ENDIF
- SI_continue ; Xmit next char in Xmit buffer if there is a char to Xmit
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _share2_check_data_ready
-
- _share2fc_FIFOrskip2:
-
- share2_no_fc3rFIFO: ; No Flow Control Enabled
- ; Get ECL Receive buffer location
- MOV DX, [si].Comm_CR_BUFFR_Segment
- MOV ES, DX
- MOV DI, [si].Comm_CR_BUFFR_Offset
- MOV DX, [si].Comm_CR_BUFFR_Index
- ADD DI, DX
- STOSB ; Store Char in receive buffer
- ; Increment Index into receive buffer
- ADD WORD PTR [si].Comm_Receive_Count, 1
- ADC WORD PTR [si].Comm_Receive_Count + 2, 0
- INC DX
- CMP DX, BUFFER_SIZE
- JNZ _share2_contFIFO
-
- ; Optionally, add another buffer
-
- PUSH CX ; REV 1.2 ECL0006
- CALL BUFFR_Gmem ; Get next available buffer
- POP CX ; REV 1.2 ECL0006
- JC _share2_FIFOrjor6 ; No Buffers available
- jmp _share2_FIFOrjor7 ; Buffers available
- _share2_FIFOrjor6:
- jmp _share2_FIFOnobuff ; No Buffers available
- _share2_FIFOrjor7:
- ; Increment next buffer information
- INC [si].Comm_Buffer_Count
- MOV DI, [si].Comm_CR_BUFFR_Offset
- MOV ES:[DI], BX ; Save pointer in previous last block
- MOV ES:[DI+2], DX
- MOV [si].Comm_CR_BUFFR_Offset, BX
- MOV [si].Comm_CR_BUFFR_Segment, DX
- MOV DX, 4 ; New index
-
- _share2_contFIFO:
- ; Store Updated Receive Buffer Index in COMMS structure
- MOV [si].Comm_CR_BUFFR_Index, DX
-
- TEST [si].Comm_Xflags,FC_REC_ON ;Is Receive flow control enabled
- JNE share2_ck3_hi_FIFO
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _share2_check_data_ready
-
- share2_ck3_hi_FIFO: ; check high flow control mark
- TEST [si].Comm_Xflags, FC_XOFF_SENT ; Outgoing XOFF already sent
- JE share2_ck3_hi_2_FIFO
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _share2_check_data_ready
-
- share2_ck3_hi_2_FIFO:
- ;**** don't check high word, XON/XOFF only supported < 64K
- ;**** CMP WORD PTR COM2.Comm_Receive_Count+2, 0
- ;**** JNE over3_high
- MOV AX, [si].Comm_high
- CMP WORD PTR [si].Comm_Receive_Count, AX
- JGE share2_over3_high_FIFO
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _share2_check_data_ready
-
- share2_over3_high_FIFO:
- ; have to send XOFF
- SI_REG LSR ; get line status
- ; Any error is revealed via LSR bits 1-4 when it's associated
- ; character is at the top of the FIFO
- TEST AL, 01h ; has a char come in
- JE share2_over3_cont_FIFO
- JMP _share2_FIFO_dataready ; if so, go get it
-
- share2_over3_cont_FIFO:
- TEST AL, 40h ; look at TX ready bits
- JE share2_over3_high_FIFO ; wait for TX OK
- SUB DX, LSR
- MOV AL, XOFF
- OUT DX, AL ; Xmit XOFF
- OR [si].Comm_Xflags, FC_XOFF_SENT
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- jmp _share2_check_data_ready
-
- ; No more Receive Buffer space available; Next Character received will
- ; overwrite the last character received.
- _share2_FIFOnobuff: ; None available
- SUB WORD PTR [si].Comm_Receive_Count, 1
- SBB WORD PTR [si].Comm_Receive_Count + 2, 0
-
- ; Check if receive FIFO is empty by checking bit0 of LSR
- _share2_check_data_ready:
- SI_REG LSR ; get line status register
- test al, 01h ; Test for Receive FIFO empty
- jnz _share2_FIFO_rjor1 ; Get next character in Receive FIFO
- JMP share2_txbug
- _share2_FIFO_rjor1: ; Relative Jump Out Of Range
- jmp _share2_FIFO_dataready ; Get next character in Receive FIFO
-
- ;*********************************************************************
-
-
- share2_txbug: ; code for 8250 TX bug goes here for multiports
- SI_REG LSR ; look for THRE to get around 8250 bug
- test al, 020H
- jnz _share2_txbug ; have to check TX
- jmp share2_startover
- ; AND AL, 20H ; isolate THRE
- ; CMP AL, 20H
- ; JE _share2_txbug ; have to check TX
- ; JMP share2_startover
- _share2_txbug:
- CMP [SI].Comm_xcount, 0
- JE _share2_txbug_exit
- JMP _share2_xmt_enter
- _share2_txbug_exit:
- JMP share2_startover
-
- IREQSHARE2 ENDP
-
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
-
-
- ;
- ; ===============================================================
- ; Local procedures
- ; ===============================================================
- ;
-
- Old_INT14 PROC NEAR ; Go to original Int 14h
- PUSHF
- CALL DWORD PTR CS:[INT14_Old_Offset]
- RET
- Old_INT14 ENDP
-
-
- ;
- ; ===============================================================
- ; INT 14h entry (regardless of intercept - they all come here)
- ; ===============================================================
- ;
-
-
- RS232_Int PROC FAR ; Interrupt 14 BIOS service
- STI ; Allow interrupts
- PUSH DS ; Data segment too!
- PUSH CS
- POP DS
- PUSH SI ; Used point to COMM data base
- ; *** SI, DS preset ***
- Load_SI ; Load SI with Comms_Str
-
- CMP CS:[SI].Comm_State, INTERCEPTED
- JE _RS232go ; Intercepted?
- CALL Old_INT14 ; Native - go back
- JMP SHORT _RS232exit
-
- _RS232go: ; SI is preset to COM1 or COM2 database
-
- CMP AH, 02h
- JNE $+7
- CALL INT14READ
- JMP SHORT _RS232exit
- CMP AH, 03h
- JNE $+7
- CALL INT14STATUS
- JMP SHORT _RS232exit
- CMP AH, 00h
- JNE $+7
- CALL INT14INIT
- JMP SHORT _RS232exit
- CMP AH, 01h
- JNE $+7
- CALL INT14SEND
- JMP SHORT _RS232exit
- _RS232exit:
- POP SI
- POP DS
- IRET
- RS232_Int ENDP
-
-
- ;
- ; ===============================================================
- ; INT14INIT Initialize communications interface (intercepted)
- ; ===============================================================
- ; same as BIOS
- ;
- ; Revision 1.2 Special 19,200 entry
- ; ; CX is the configuration
- ; ; DX is the unit number
- COMMS_19200 PROC NEAR ; requires baud bits to be 0!
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- MOV AX, CX ; Baud rate is preset to a 0 (110 baud)
- MOV WORD PTR TIMERS_X16, 6 ; 19,200 divisor
- CALL INT14INIT
- MOV WORD PTR TIMERS_X16, 1047 ; original 110 divisor
- POP SI
- RET
- COMMS_19200 ENDP
-
- COMMS_38400 PROC NEAR ; requires baud bits to be 0!
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- MOV AX, CX ; Baud rate is preset to a 0 (110 baud)
- MOV WORD PTR TIMERS_X16, 3 ; 38,400 divisor
- CALL INT14INIT
- MOV WORD PTR TIMERS_X16, 1047 ; original 110 divisor
- POP SI
- RET
- COMMS_38400 ENDP
-
-
-
- INT14INIT PROC NEAR ; AH = 0
- PUSH BX
- PUSH CX
- PUSH DX
-
- MOV AH, AL ; Save original parameter
-
- ; ===============================================================
- ; Set Baud rate
- ; ===============================================================
-
- MOV DX, [SI].Comm_PortAddr ; Set DLAB
- ADD DX, LCR
- IN AL, DX
- IONOP
- OR AL, 80h
- OUT DX, AL
- IONOP
-
- MOV BX, AX ; Access baud table
- AND BX, 0E000h ; Isolate baud rate triplet
- MOV CL, 12
- SHR BX, CL
- MOV CX, TIMERS_X16[BX]
- ; Low byte divisor first
- MOV AL, CL
- MOV DX, [SI].Comm_PortAddr
- ADD DX, TX_RD_BUFF_DLLO
- OUT DX, AL
- IONOP
- ; High byte divisor last
- MOV AL, CH
- MOV DX, [SI].Comm_PortAddr
- ADD DX, IER_DLHI
- OUT DX, AL
- IONOP
-
- ; ===============================================================
- ; Set parity stop data bit configuration
- ; ===============================================================
-
- MOV DX, [SI].Comm_PortAddr ; RESet DLAB, parity etc...
- ADD DX, LCR
- MOV AL, AH ; Restore original parameter
- AND AL, 01Fh
- OUT DX, AL
- IONOP
- CALL INT14STATUS
-
- POP DX
- POP CX
- POP BX
- RET
-
- INT14INIT ENDP
-
- ;
- ; ===============================================================
- ; INT14SEND Send character (intercept mode only)
- ; Rev 2.0 - all with interrupts!
- ; ===============================================================
- ; same as BIOS
- INT14SEND PROC NEAR ; AH = 1
- PUSH DX
- PUSH CX
- PUSH BX
-
- MOV BL, AL ; Save character
- MOV DX, [SI].Comm_PortAddr
- ADD DX, MCR
- IN AL, DX
- IONOP
- MOV AH, AL
- CMP [SI].Comm_DTR_RTS, 0
- JE _SEND_goahead ; Ignore DSR, CTS
-
- ; ===============================================================
- ; Optionally, set DTR, RTS and wait for CTS and/or DSR
- ; MCR still in register AL, character in BL
- ; ===============================================================
-
- OR AL, 03h
- OUT DX, AL
- IONOP
-
- MOV DX, [SI].Comm_PortAddr ; Wait for DSR and CTS
- ADD DX, MSR
- MOV CX, timeout_variable ; Timed loop for modem
- _Sd_loop:
- IN AL, DX
- IONOP
- MOV AH, AL ; Set AH register to status
- ; look for Hardware Handshaking flag
- and al, [si].Comm_DTR_RTS ; look for CTS and/or DSR
- cmp al, [si].Comm_DTR_RTS ; Unable to Xmit if Hardware Handshaking and CTS/DST not set
- ; AND AL, 30h
- ; CMP AL, 30h
- JE _SEND_goahead
- LOOP _Sd_loop ; Go back for more punishment
-
- OR AH, 080h ; OOOOOOOOPPPPPPSSSSSSS!
- JMP _SEND_exit ; Can't wait for modem signals
-
- ; ===============================================================
- ; Optionally, if been XOFF'ed wait around
- ; ===============================================================
-
- _SEND_goahead:
- MOV CX, timeout_variable ; Timed loop for modem
- _St_loop:
- TEST [SI].Comm_Xflags, FC_XOFF_RCVD ; Have we been X-OFFed?
- JZ _SEND_really_goahead
- IONOP
- IONOP
- IONOP
- JMP _St_loop ; Go back for more punishment
-
- OR AH, 080h ; OOOOOOOOPPPPPPSSSSSSS!
- JMP _SEND_exit ; Timeout - can't wait!
- ; ===============================================================
- ; If output pending, then wait till complete
- ; ===============================================================
-
- _SEND_really_goahead:
- _SEND_notready:
- CMP [SI].Comm_xcount, 0 ; Wait till ISR completes
- JNE _SEND_notready
-
- ; ===============================================================
- ; Transmit character and wait till completed
- ; ===============================================================
-
- MOV [SI].Comm_xcount, 1 ; Rev 2.0 set counter
- MOV AL, BL ; Retrieve the character
- SI_PutAL ; Send the character
-
- _SEND_waitloop:
- CMP [SI].Comm_xcount, 0 ; wait till ISR completes
- JNE _SEND_waitloop
-
- ; ===============================================================
- ; To be compatible with ROM BIOS, return the LSR in AH
- ; ===============================================================
-
- MOV DX, [SI].Comm_PortAddr
- ADD DX, LSR
- IN AL, DX
- MOV AH, AL ; Move LSR to AH status
- IONOP
- _SEND_exit:
- POP BX
- POP CX
- POP DX
- RET
- INT14SEND ENDP
-
- ;
- ; ===============================================================
- ; INT14READ Read next data byte (intercept mode only)
- ; ===============================================================
- ; same as BIOS
-
- INT14READ PROC NEAR ; AH = 2
- PUSH ES
- PUSH BX
- PUSH CX
- PUSH DX
-
- ; ===============================================================
- ; If IBM BIOS compatible (wait for DSR), drop RTS
- ; ===============================================================
-
- ;; CMP [SI].Comm_DTR_RTS, 0
- ;; JE _READ_WAIT
- ;;
- ;; MOV DX, [SI].Comm_PortAddr ; Set DSR, drop RTS
- ;; ADD DX, MCR
- ;; IN AL, DX
- ;; IONOP
- ;; OR AL, 1 ; Keep bit 0 (DTR) high
- ;; AND AL, 0FDh ; Force bit 1 (RTS) low
- ;; OUT DX, AL
- ;; IONOP
-
- ; ===============================================================
- ; Wait for character
- ; ===============================================================
-
- _READ_WAIT:
- MOV CX, timeout_variable ; Timeout
-
- _Rd_loop:
- CALL INT14STATUS ; Get the status
- ; JHL 3-5-91 Commented out code so that we do not need CTS or DSR to be
- ; enabled (when Hardware Handshaking is enabled) when we read data from
- ; xcomms receive buffer
- ; CMP [SI].Comm_DTR_RTS, 0
- ; JE _READ_SKIP_Chek ; Ignore IBM BIOS DSR check
-
- ; TEST AL, 20h ; Is DSR (modem) asserted?
- ; JZ _READ_TRY_AGAIN ; Not yet!
- _READ_SKIP_Chek:
- TEST AH, 01h ; Data ready?
- JNE _Rd_gotchar ; Yes!
- CMP [SI].Comm_Error, 0 ; Overflow?
- MOV [SI].Comm_Error, 0 ; Reset errors-no matter what
- JNE _Read_Error
- _READ_TRY_AGAIN:
- LOOP _Rd_loop ; Continue
- _Read_Error:
- OR AH, 80h ; No character yet????
- JMP _READ_Exit ; TIMEOUT - NO DSR or
- ; TIMEOUT - No character or
- ; BUFFR Overflow error
- _Rd_gotchar:
- CALL _Rd_getchar
- _READ_Exit:
- POP DX
- POP CX
- POP BX
- POP ES
- RET
- INT14READ ENDP
-
- ; ===============================================================
- ; _Rd_gotchar
- ; Character found - get character then update buffer pointer
- ; ===============================================================
- ; Given:
- ; AH Status of the line (is preserved and not modified)
- ; DS, CS XCOMMS segment
- ; SI COMx data base
- ; Return:
- ; AH Same
- ; AL Character
- ; SI COMx data base
- ; ES, BX, CX modified
- ; ===============================================================
-
- _Rd_getchar PROC
- CLI ;;; Disable interrupts
-
- SUB WORD PTR [SI].Comm_Receive_Count, 1
- SBB WORD PTR [SI].Comm_Receive_Count+2, 0
-
- MOV BX, [SI].Comm_RD_BUFFR_Segment
- MOV ES, BX
- MOV BX, [SI].Comm_RD_BUFFR_Offset
- ADD BX, [SI].Comm_RD_BUFFR_Index
- MOV AL, ES:[BX] ;;; Read the character byte
-
- INC [SI].Comm_RD_BUFFR_Index
- CMP [SI].Comm_RD_BUFFR_Index, BUFFER_SIZE
- JNE _READ_pointer
-
- ; ===============================================================
- ; Go to next block
- ; ===============================================================
-
- MOV [SI].Comm_RD_BUFFR_Index, 4
- MOV BX, [SI].Comm_RD_BUFFR_Offset
- MOV CX, ES:[BX]
- MOV [SI].Comm_RD_BUFFR_Offset, CX
- MOV CX, ES:[BX+2]
- MOV [SI].Comm_RD_BUFFR_Segment, CX
- MOV DX, ES
-
- PUSH AX
- CALL BUFFR_Pmem
- DEC [SI].Comm_Buffer_Count
- POP AX
-
- ; ===============================================================
- ; If the buffer is empty, then reset all pointers
- ; ===============================================================
-
- _READ_pointer:
- MOV BX, WORD PTR [SI].Comm_Receive_Count
- OR BX, WORD PTR [SI].Comm_Receive_Count+2
- JNE _Rd_gcexit
- MOV [SI].Comm_RD_BUFFR_Index, 4
- MOV [SI].Comm_CR_BUFFR_Index, 4
- _Rd_gcexit:
- STI ; Enable interrupts
- TEST [SI].Comm_Xflags, FC_ENABLED ; test for flow control
- JE no_fc_here
- TEST [SI].Comm_Xflags, FC_XOFF_SENT ; if we sent XOFF
- JE no_fc_here
- ; look for <= low water mark
- ;***** XON/XOFF only supported for high/lows < 64K
- ;***** CMP WORD PTR [SI].Comm_Receive_Count+2, 0 ;count > 64K?
- ;***** JNE no_fc_here ; if > 64K, can't be low water mark
- MOV DX, [SI].Comm_low
- CMP WORD PTR [SI].Comm_Receive_Count, DX ; <= low
- JG no_fc_here
- ; have to send XON
- MOV DX, [SI].Comm_PortAddr
- ADD DX, LSR ; get line status
- MOV AH, AL ; save character read
-
- XOR BX, BX ; must clear transmit count, temporarily
- ; not to interfere with xon logic here
- XCHG [SI].Comm_xcount, BX ; save count and clear it
- loop_xon:
- IN AL, DX
- AND AL, 60h ; look at TX ready bits
- CMP AL, 60h
- JNE loop_xon ; wait for TX OK
-
- SUB DX, LSR ; point to TX Port
- MOV AL, XON
- CLI ; turn ints off around here to
- ; guarantee we don't hang tx in the
- ; middle of a uput
- MOV [SI].Comm_xcount, BX ; restore tx count
- OUT DX, AL ; send xon
-
- STI
-
- AND [SI].Comm_Xflags, NOT FC_XOFF_SENT
- MOV AL, AH ; restore char read
-
- no_fc_here:
- ;**** the STI instruction was moved above not to leave ints off too long
- ;**** STI ; Enable interrupts
- RET
- _Rd_getchar ENDP
-
- ; ===============================================================
- ; ===============================================================
-
-
- ;
- ; ===============================================================
- ; INT14STATUS Read status (intercept mode only)
- ; ===============================================================
- ; same as BIOS call
- INT14STATUS PROC NEAR ; AH = 3
- PUSH BX
- PUSH DX
-
- MOV DX, [SI].Comm_PortAddr
- ADD DX, LSR
- IN AL, DX
- IONOP
- or al, BYTE PTR [SI].Comm_Break
- AND AL, 0FEh ; Get rid of Data Ready
- MOV BX, WORD PTR [SI].Comm_Receive_Count
- OR BX, WORD PTR [SI].Comm_Receive_Count+2
- CMP BX, 0
- JE _Status_skip1
- OR AL, 1h ; Set Data Ready bit
- _Status_skip1:
- MOV AH, AL
- MOV DX, [SI].Comm_PortAddr
- ADD DX, MSR
- IN AL, DX
- IONOP
-
- POP DX
- POP BX
- RET
- INT14STATUS ENDP
-
-
-
-
- ;
- ; ===============================================================
- ; COMMS_Entry Enter the COMMS library
- ; COMMS_Exit Exit the COMMS library
- ; ===============================================================
- ;
- ; Since either COM1 or COM2 can be linked at anytime, the default
- ; condition at COMMS_Entry is to take all INT14 BIOS calls - all
- ; requests for native (UnLinked) COM unit will go to the previous
- ; BIOS service routine.
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS, CS XBIOS CSEG[ment]
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; None affected
- ; ===============================================================
- ;
-
- COMMS_Entry PROC NEAR
- PUSH SI ; Rev 2.0 (new)
- PUSH DI ; Rev 2.0 (new)
-
-
- JMP PASTSHARE
-
- ;formerly macro Ports_Entr ; Rev 2.0 (new)
-
- ;Ports_Entr MACRO
-
- PUSH BX
- PUSH CX
-
- ; -------- SHARED INTERRUPT --------------------------
- ; 1. Take over the shared interrupt IREQ completely
- ; 2. Enable the interrupt controller 8259
- ; 3. Initialize status for each port assuming polling
- ; 4. Setup COM3, COM4 in ROM BIOS data base region
- ; ----------------------------------------------------
-
-
- ; 1 Point to shared interrupt
- MOV AL, Shared_vector
- MOV BX, OFFSET IREQSHARE
- MOV DX, SEG IREQSHARE
- swapvec
- MOV Shared_Old_IntOffset, BX
- MOV Shared_Old_IntSegment, DX
- IN AL, ICA ; 2 Enable 8259 channel
- AND AL, Shared_IC_mask
- IONOP
- OUT ICA, AL
- IONOP
-
-
-
-
- MOV CX, MAXPORTS ; 3 Polled mode
- MOV BX, 0
- Port_Status_Loop:
- MOV WORD PTR Port_Status[BX], STATUS_POLLED
- MOV SI, Port_Table[BX]
- MOV [SI].Comm_unit, BX
- ADD BX, 2
- LOOP Port_Status_Loop
-
- PUSH ES ; 4 Setup ROM BIOS data base
- MOV AX, 40h
- MOV ES, AX
- MOV WORD PTR ES:00h, C1
- MOV WORD PTR ES:02h, C2
- MOV WORD PTR ES:04h, C3
- MOV WORD PTR ES:06h, C4
- POP ES
- POP CX
- POP BX
- ; ENDM
-
- PASTSHARE:
-
- MOV CX, MAXPORTS ; Rev 2.0 (upgraded)
- MOV DL, 0 ; Rev 2.0
- _Entry_loop: ; Rev 2.0 init all ports
- PUSH DX ; Rev 2.0
- CALL COMMS_Gaddr ; Rev 2.0 (assume same segment)
- MOV [BX].Comm_State, NATIVE ; Rev 2.0
- MOV [BX].Comm_Xflags, 0 ; Rev 2.0
- POP DX ; Rev 2.0
- INC DL ; Rev 2.0
- LOOP _Entry_loop ; Rev 2.0
-
- MOV timeout_variable, TIMEOUT ; Default
-
- ; ===============================================================
- ; Set interrupt vector int 14h
- ; ===============================================================
-
- MOV AL, RS232
- MOV DX, SEG RS232_Int
- MOV BX, OFFSET RS232_Int
- swapvec
- MOV WORD PTR INT14_Old_Offset, BX
- MOV WORD PTR INT14_Old_Segment, DX
-
- ; ===============================================================
- ; Copy the baud rate table from system ROM
- ; ===============================================================
-
- PUSH DS
- MOV SI, 0E729h ; Source ROM table
- MOV AX, 0F000h
- MOV DS, AX
-
- MOV DI, OFFSET TIMERS_X16 ; Destination XBIOS table
- PUSH DS
- POP ES
-
- MOV CX, 8 ; Move 8 baud rate divisors
- REP MOVSW
- POP DS
-
- POP DI ; Rev 2.0 (new)
- POP SI ; Rev 2.0 (new)
- RET
- COMMS_Entry ENDP
-
-
- COMMS_Exit PROC NEAR
- PUSH SI ; Rev 2.0 (new)
- PUSH DI ; Rev 2.0 (new)
-
- ;formerly macro Ports_Exit ; Rev 2.0 (new)
-
- ;Ports_Exit MACRO
-
- ; -------- SHARED INTERRUPT --------------------------
- ; 1. Restore interrupt vector to previous contents
- ; 2. Disable the interrupt controller 8259 channel
- ; 3. Clear COM3 and COM4 entries in ROM BIOS data base
- ; ----------------------------------------------------
-
- ;***** MOV AL, Shared_vector ;***** 1 Restore shared vector
- ;***** MOV BX, Shared_Old_IntOffset
- ;***** MOV DX, Shared_Old_IntSegment
- ;***** setvec
- ;***** 2 Disable shared 8259 channel
- ;***** AND CL, Shared_IC_mask
- ;***** NOT CL
- ;***** IN AL, ICA
- ;***** IONOP
- ;***** OUT ICA, AL
- ;***** IONOP
-
- ; PUSH ES ; 3 Reset ROM BIOS data base
- ; MOV AX, 40h
- ; MOV ES, AX
- ; MOV WORD PTR ES:00h, 03F8h
- ; MOV WORD PTR ES:02h, 02F8h
- ; MOV WORD PTR ES:04h, 0
- ; MOV WORD PTR ES:06h, 0
- ; POP ES
- ; ENDM
-
-
-
- MOV CX, MAXPORTS ; Rev 2.0 (upgraded)
- MOV DX, 0 ; Rev 2.0
- _exit_loop:
- CALL COMMS_UnLink
- INC DL
- LOOP _exit_loop
-
- MOV AL, RS232
- MOV BX, WORD PTR INT14_Old_Offset
- MOV DX, WORD PTR INT14_Old_Segment
- setvec
- POP DI ; Rev 2.0 (new)
- POP SI ; Rev 2.0 (new)
- RET
- COMMS_Exit ENDP
-
-
-
- ;
- ; ===============================================================
- ; COMMS_Link Connect the communications circuit
- ; COMMS_UnLink Disconnect the communications circuit
- ; ===============================================================
- ;
- ; In the case of Link, connect into interrupt
- ; service routine structure. In the case of UnLink,
- ; restore the old interrupt service routine`s address and
- ; return all buffers to the buffer manager!
- ;
- ; XOFF/XON mode automatically disabled
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS, CS XBIOS CSEG[ment]
- ; DX Unit number (COM1 = 00h, COM2 = 01h)
- ; CL = 0 leave DTR, RTS alone
- ; = 1 assert DTR, RTS and watch for modem signals
- ; (like on IBM PC)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AL = 00h, Successful operation
- ; CY = NC
- ;
- ; CY = C
- ; AL = FFh Unsuccessful operation - already linked
- ; AL = FEh No buffers available
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; None affected
- ; ===============================================================
- ;
-
- public COMMS_Link
- COMMS_Link PROC NEAR
- PUSH SI
- PUSH BX
- PUSH CX
- PUSH DX
-
- MOV port_hold, DX ; save unit number
- Load_SI ; Load SI with Comms_Str
- CMP [SI].Comm_State, INTERCEPTED
- JNE _Lk_1
- JMP _Lk_error
- _Lk_1:
- MOV [SI].Comm_xcount, 0 ; Rev 2.0
-
- ; ===============================================================
- ; Clear the UART of any extraneous characters
- ; ===============================================================
-
- MOV [SI].Comm_DTR_RTS, CL
- _Lk_notready:
- MOV DX, [SI].Comm_PortAddr
- ADD DX, LSR
- IN AL, DX
- IONOP
- TEST AL, 01
- JZ check_iir
- MOV DX, [SI].Comm_PortAddr
- ADD DX, TX_RD_BUFF_DLLO
- IN AL, DX
- IONOP
- JMP _Lk_notready
- check_iir:
- MOV DX, [SI].Comm_PortAddr
- ADD DX, IIR
- IN AL, DX
- IONOP
- AND AL,0Fh ; recover bits 0-3 of IIR
- CMP AL, 1 ; no ints pending
- JE _Lk_ready
- IONOP
- MOV DX, [SI].Comm_PortAddr
- ADD DX, MSR
- IN AL, DX
- IONOP
- IONOP
- JMP _Lk_notready
- NOP ; REV 1.2 ECL0002
- NOP ; REV 1.2 ECL0002
- _Lk_ready:
-
-
- ; ===============================================================
- ; Setup the first initial buffer and point to first byte
- ; ===============================================================
-
- MOV [SI].Comm_Buffer_Count, 0
- CALL BUFFR_Gmem
- JNC _Lk_ok2
- JMP _Lk_error2
- _Lk_ok2:
- CALL COMMS_Bufclr ; Given DX:BX and SI
-
- ; Disable X-On and X-Off flow control processing
-
- MOV [SI].Comm_Xflags, 0
-
-
- ; ===============================================================
- ; Enable interrupts
- ; ===============================================================
-
- ; ===============================================================
- ; Install the new IREQ interrupt handler
- ; ===============================================================
-
-
- ;*** formerly macro SI_Link ; Rev 2.0
-
- ;SI_Link MACRO ; Given SI, store Interrupt link addr in vector
- ; and return in DX:BX the previous contents
-
-
- ; I/O is repeated twice to make up for
- ; some wierdness with 8259's.
- ; We needed it on 12Mhz, 0 wait 286.
- ; In any event, it does no harm.
-
- IN AL, ICA ; Enable 8259 channel
- IONOP
- IONOP
- IN AL, ICA ; Enable 8259 channel
- IONOP
- IONOP
- PUSH AX
- MOV AX, port_hold
- SHL AX, 1 ; mul port by 2 for cmp
-
- CMP AX, starting_port ; if multiport, use shared logic
- POP AX
- JGE shared_logic
- JMP no_shared
- shared_logic:
- PUSH AX
- MOV AX, port_hold
- SHL AX, 1 ; mul port by 2 for cmp
-
- CMP AX, starting2_port ; if multiport number 2
- POP AX
- JL j1 ;jump out of range
- JMP shared2_logic
- j1:
-
- CMP multi_init, 0
- JE shared_10
-
- MOV BX, [SI].Comm_unit
- MOV WORD PTR Port_Status[BX], STATUS_INTERRUP
-
- JMP Link_10
- shared_10:
- MOV multi_init, 1 ; set flag
- MOV multi_unlinked, 0 ; force reset of unlink flag
- AND AL, Shared_IC_mask
- OUT ICA, AL
- IONOP
- IONOP
- OUT ICA, AL
- IONOP
- IONOP
-
-
- MOV AL, Shared_vector ; Move over vector
- ;******* MOV BX, [SI].Comm_New_offset
- ;******* MOV DX, [SI].Comm_New_segment
- MOV BX, Shared_New_IntOffset
- MOV DX, Shared_New_IntSegment
- swapvec
- ;****** silink below was from original AST.AST where status port
- ;****** had to be initialized to turn on interrupts
- silink:
-
- ;******** MOV [SI].Comm_Old_IntOffset, BX
- ;******** MOV [SI].Comm_Old_IntSegment, DX
- MOV Shared_Old_IntOffset, BX
- MOV Shared_Old_IntSegment, DX
-
- MOV BX, [SI].Comm_unit
- MOV WORD PTR Port_Status[BX], STATUS_INTERRUP
-
- CMP board_type, AST ; is this AST in "expanded mode"
- JE j2 ; jump out of range
- CMP board_type, ASTCMP ; is this AST in "compatible mode"
- JE j2 ; jump out of range
- JMP Link_10 ; skip if not
- j2: PUSH DX ; otherwise init status port
- PUSH AX
- MOV DX, Status_port
- MOV AL, 8fh
- OUT DX, AL
- POP AX
- POP DX
-
- ;
- ; ENDM
- ;
- JMP Link_10
-
- shared2_logic:
- CMP multi2_init, 0
- JE shared2_10
- MOV BX, [SI].Comm_unit
- MOV WORD PTR Port_Status[BX], STATUS_INTERRUP
-
- JMP Link_10
- shared2_10:
- MOV multi2_init, 1 ; set flag
- MOV multi2_unlinked, 0 ; force reset of unlink flag
- AND AL, Shared2_IC_mask
- OUT ICA, AL
- IONOP
- IONOP
- OUT ICA, AL
- IONOP
- IONOP
-
-
- MOV AL, Shared2_vector ; Move over vector
- ;******* MOV BX, [SI].Comm_New_offset
- ;******* MOV DX, [SI].Comm_New_segment
- MOV BX, Shared2_New_IntOffset
- MOV DX, Shared2_New_IntSegment
- swapvec
- ;****** silink below was from original AST.AST where status port
- ;****** had to be initialized to turn on interrupts
- silink2:
- MOV BX, [SI].Comm_unit
- MOV WORD PTR Port_Status[BX], STATUS_INTERRUP
-
- ;******** MOV [SI].Comm_Old_IntOffset, BX
- ;******** MOV [SI].Comm_Old_IntSegment, DX
- MOV Shared2_Old_IntOffset, BX
- MOV Shared2_Old_IntSegment, DX
-
- CMP board2_type, AST ; is this AST 4 port DOS
- JE comms_j1 ; jump out of range
- CMP board2_type, ASTCMP ; is this AST 4 port DOS
- JE comms_j1 ; jump out of range
- JNE Link_10 ; skip if not
- comms_j1:
- PUSH DX ; otherwise init status port
- PUSH AX
- MOV DX, Status2_port
- MOV AL, 8fh
- OUT DX, AL
- POP AX
- POP DX
-
- ;
- ; ENDM
- ;
- JMP SHORT Link_10
- no_shared:
- AND AL, [SI].Comm_IC_Mask
- OUT ICA, AL
- IONOP
- IONOP
- OUT ICA, AL
- IONOP
- IONOP
-
-
- MOV AL, [SI].Comm_vector ; Move over vector
- MOV BX, [SI].Comm_New_offset
- MOV DX, [SI].Comm_New_segment
- swapvec
- ; ENDM
-
-
- MOV [SI].Comm_Old_IntOffset, BX
- MOV [SI].Comm_Old_IntSegment, DX
-
- Link_10:
-
-
- MOV DX, [SI].Comm_PortAddr
- CMP DX, 0
- JE _Lk_exit ; get out if no uart here
- ADD DX, MCR
- PUSH AX
- MOV AX, port_hold
- SHL AX, 1 ; mul port by 2 for cmp
-
- CMP AX, starting_port ; if multiport, use shared logic
- POP AX
- MOV CX, 08 ;default to turn on out2 of MCR
- ;for standard com ports
- JL Link_25
- MOV CX, out2_variable ; out2 on/off code for multiports
- Link_25:
- ; MOV CH, 0bh ;2.0a Enable TX/RX/MODEM ints
- mov ch, 0Fh ;4.0 Enable TX/RX/MODEM/linestatus ints
-
- CMP [SI].Comm_DTR_RTS, 0
- JE _Lk_skip1
- OR CL, 03h ; Raise DTR, and RTS
- _Lk_skip1:
- IN AL, DX
- IONOP
- OR AL, CL ;****** 2.0a (Maybe Raise OUT2 DTR,RTS)
- OUT DX, AL
-
- MOV DX, [SI].Comm_PortAddr
- ADD DX, IER_DLHI
- MOV AL, CH ; Rev 2.0a Enable interrupts
-
- OUT DX, AL
-
- MOV [SI].Comm_State, INTERCEPTED
- MOV AL, 00h
- CLC
- JMP SHORT _Lk_exit
- _Lk_error:
- MOV AL, 0FFh
- JMP _Lk_errrr
- _Lk_error2:
- MOV AL, 0FEh
- _Lk_errrr:
- STC
- _Lk_exit:
- POP DX
- POP CX
- POP BX
- POP SI
-
- RET
- COMMS_Link ENDP
-
- COMMS_UnLink PROC NEAR
- PUSH SI
- PUSH BX
- PUSH CX
- PUSH DX
- MOV port_hold, DX
-
- Load_SI ; Load SI with Comms_Str
- CMP [SI].Comm_State, INTERCEPTED
- JE _Ul_ok
- JMP _Ul_error
- _Ul_ok:
- MOV [SI].Comm_State, NATIVE
-
- ; ===============================================================
- ; Disable communications interface
- ; ===============================================================
-
- MOV DX, [SI].Comm_PortAddr ; Disable ALL interrupts
- CMP DX, 0
- ;*** JE _no_uart ; out of range
- JNE _Ul_10
- JMP _no_uart
- _Ul_10:
- ADD DX, IER_DLHI
- XOR AL, AL
- OUT DX, AL
- IONOP
-
- MOV DX, [SI].Comm_PortAddr ; Deassert DSR, DTR
- ADD DX, MCR
- IN AL, DX
- IONOP
- AND AL, 03h ; Clear out OUT1, OUT2
- OUT DX, AL
- IONOP
-
- ; ===============================================================
- ; Reset IREQx Interrupt vector
- ; ===============================================================
-
-
- ; formerly macro SI_UnLink ; Rev 2.0 disable 8259, vector
-
-
- ;SI_UnLink MACRO ; Given SI, store previous interrupt vector
- ; DX:BX are returned unmodified
-
- ; Disable 8259 first (COM1 and COM2 are unique)
- MOV AX, port_hold
- SHL AX, 1 ; mul. by 2 for cmp
- CMP AX, starting_port
- JGE shared_logic2
- MOV CL, [SI].Comm_IC_Mask
- NOT CL
- IN AL, ICA
- IONOP
- OR AL, CL
- OUT ICA, AL
- IONOP
-
-
- MOV AL, [SI].Comm_vector
- MOV BX, [SI].Comm_Old_IntOffset
- MOV DX, [SI].Comm_Old_IntSegment
- setvec
- JMP _no_uart
-
- ; ENDM
-
- shared_logic2:
- CMP multi_unlinked, 0
- JE shared_logic2_10
- MOV AX, port_hold
- SHL AX, 1 ; mul. by 2 for cmp
- CMP AX, starting2_port
- JGE shared2_logic2
-
- JMP _no_uart
-
- shared_logic2_10:
- MOV multi_unlinked, 1
- MOV multi_init, 0 ; clear for linking again
- MOV CL, Shared_IC_mask
- NOT CL
- IN AL, ICA
- IONOP
- OR AL, CL
- OUT ICA, AL
- IONOP
-
-
- MOV AL, Shared_vector
- ;****** MOV BX, [SI].Comm_Old_IntOffset
- ;****** MOV DX, [SI].Comm_Old_IntSegment
- MOV BX, Shared_Old_IntOffset
- MOV DX, Shared_Old_IntSegment
- setvec
- ;****** JMP SHORT _no_uart
-
-
- ;******* si_unlink below from original multiport asm files
- ;*******
- siunlink:
- ;SI_UnLink MACRO ; Given SI, store previous interrupt vector
- ; DX:BX are returned unmodified
- PUSH AX
- PUSH BX
- PUSH DX
- MOV BX, [SI].Comm_unit
- MOV WORD PTR Port_Status[BX], STATUS_POLLED
- MOV DX, Status_port
- CMP board_type, AST ; is this AST 4 port DOS
- JNE Unlink_10 ; skip if not
- ;***** MOV AL,0Fh
- ;***** OUT DX,AL
- Unlink_10:
- POP DX
- POP BX
- POP AX
- JMP _no_uart
- ; ENDM
-
- shared2_logic2:
- CMP multi2_unlinked, 0
- JE shared2_logic2_10
- JMP _no_uart
-
- shared2_logic2_10:
- MOV multi2_unlinked, 1
- MOV multi2_init, 0 ; clear for linking again
- MOV CL, Shared2_IC_mask
- NOT CL
- IN AL, ICA
- IONOP
- OR AL, CL
- OUT ICA, AL
- IONOP
-
-
- MOV AL, Shared2_vector
- ;****** MOV BX, [SI].Comm_Old_IntOffset
- ;****** MOV DX, [SI].Comm_Old_IntSegment
- MOV BX, Shared2_Old_IntOffset
- MOV DX, Shared2_Old_IntSegment
- setvec
- ;****** JMP SHORT _no_uart
-
-
- ;******* si_unlink below from original multiport asm files
- ;*******
- ;SI_UnLink MACRO ; Given SI, store previous interrupt vector
- ; DX:BX are returned unmodified
- PUSH AX
- PUSH BX
- PUSH DX
- MOV BX, [SI].Comm_unit
- MOV WORD PTR Port_Status[BX], STATUS_POLLED
- MOV DX, Status_port
- CMP board2_type, AST ; is this AST 4 port DOS
- JNE Unlink2_10 ; skip if not
- ;***** MOV AL,0Fh
- ;***** OUT DX,AL
- Unlink2_10:
- POP DX
- POP BX
- POP AX
- ; ENDM
-
-
- _no_uart:
-
- STI ; Enable the interrupts
-
- ; ===============================================================
- ; Disable X-On and X-Off flow control processing
- ; Return all used buffers back into the pool
- ; [Data receive interrupts are disabled, so links will remain]
- ; ===============================================================
-
-
- MOV [SI].Comm_Xflags, 0 ; CLEAR ALL XON/XOFF STATUS
- CALL COMMS_Buffree
- MOV AX, 00
- CLC
- JMP SHORT _Ul_exit
- _Ul_error:
- MOV AL, 0FFh
- STC
- _Ul_exit:
- POP DX
- POP CX
- POP BX
- POP SI
- RET
- COMMS_UnLink ENDP
-
- ;
- ; ===============================================================
- ; COMMS_Bufclr Clear the receive buffer data base (used by COMMS_Flush)
- ; ===============================================================
- ;
- ; Given the buffer address in DX:BX, initialize the data base
- ; so that it appears that there is no data received.
- ; The XON/XOFF and other status is not changed!
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS, CS XBIOS CSEG[ment]
- ; SI Pointer to communications database
- ; DX:BX Pointer to the first buffer block
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; Not applicable
- ; ===============================================================
- ;
-
- COMMS_Bufclr PROC NEAR
- MOV [SI].Comm_Buffer_Count, 1
- MOV [SI].Comm_CR_BUFFR_Offset, BX
- MOV [SI].Comm_RD_BUFFR_Offset, BX
- MOV [SI].Comm_CR_BUFFR_Segment, DX
- MOV [SI].Comm_RD_BUFFR_Segment, DX
- MOV [SI].Comm_CR_BUFFR_Index, 4
- MOV [SI].Comm_RD_BUFFR_Index, 4
-
- MOV WORD PTR [SI].Comm_Receive_Count, 0
- MOV WORD PTR [SI].Comm_Receive_Count+2, 0
- MOV WORD PTR [SI].Comm_Error, 0
- MOV BYTE PTR [SI].Comm_Break, 0
- RET
- COMMS_Bufclr ENDP
-
- ;
- ; ===============================================================
- ; COMMS_Buffree Return the buffer pool (used by COMMS_Flush)
- ; ===============================================================
- ;
- ; Given the buffer address in DX:BX, initialize the data base
- ; so that it appears that there is no data received.
- ; The XON/XOFF and other status is not changed!
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS, CS XBIOS CSEG[ment]
- ; SI Pointer to communications database
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; Not applicable
- ; ===============================================================
- ;
-
- COMMS_Buffree PROC NEAR
- MOV CX, [SI].Comm_Buffer_Count
- MOV BX, [SI].Comm_RD_BUFFR_Offset
- MOV DX, [SI].Comm_RD_BUFFR_Segment
- PUSH ES
- _put_em_back: ; DX:BX buffer, scratch ES,AX
- MOV ES, DX
- MOV AX, ES:[BX] ; Get next buffer link offset
- PUSH AX
- MOV AX, ES:[BX+2] ; Get next buffer link segment
- PUSH AX
- CALL BUFFR_Pmem
- POP DX
- POP BX
- DEC [SI].Comm_Buffer_Count
- LOOP _put_em_back ; Return the next buffer
- POP ES
- XOR AX, AX
- MOV WORD PTR [SI].Comm_Receive_Count, AX
- MOV WORD PTR [SI].Comm_Receive_Count + 2, AX
- CLC
- RET
- COMMS_Buffree ENDP
-
- ;
- ; ===============================================================
- ; COMMS_Flush Clear the receive buffers (leave modes intact!)
- ; ===============================================================
- ;
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS, CS XBIOS CSEG[ment]
- ; SI Pointer to communications database
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; Not applicable
- ; ===============================================================
- ;
- COMMS_Flush PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- CMP [SI].Comm_State, INTERCEPTED
- JE _init_buffers ; NATIVE POLLED MODE
- MOV DX, [SI].Comm_PortAddr
- IN AL, DX
- IONOP
- MOV DX, [SI].Comm_PortAddr
- IN AL, DX
- IONOP
- JMP SHORT _flush_exit
-
- _init_buffers: ; INTERRUPT MODE
- CLI ; Clear interrupts
-
- ; Check if our UART mode indicates FIFOs are enabled
- ; Allowable values for bits 0 to 3 of "COMM_UART_Mode" are:
- ; 0 = 16440 (16550 Character) mode
- ; 1 = 16550 FIFOs enabled, DMA mode 0
- ; 9 = 16550 FIFOs enabled, DMA mode 1 (This mode is not used)
-
- test [si].COMM_UART_Mode, 09h
- jz _flush_continue ; FIFOs not present or not enabled
-
- ; Clear Receive FIFO by writing a 1 to bit 1 of the UART's FCR
- mov dx, [si].Comm_PortAddr
- add dx, 2 ; DX points to FCR or IIR
- mov ax, [si].COMM_UART_Mode
- or ax, 02h ; Enable bit 1 of UART's FCR
- out dx, al ; clear Receive FIFO
- IONOP
-
- _flush_continue:
- CALL COMMS_Buffree ; Return all buffers
- CALL BUFFR_Gmem ; Return the first buffer
- CALL COMMS_Bufclr ; And initialize the database
- _flush_exit:
- MOV AX, 0 ; Assume all works!
- CLC
- STI ; Enable interrupts
- POP SI
- RET
- COMMS_Flush ENDP
-
-
- ;
- ; ===============================================================
- ; COMMS_Status Return the link status
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS, CS XBIOS CSEG[ment]
- ; DX Unit number (COM1 = 00h, COM2 = 01h)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX = 00h, Native
- ; AX = 01h, Intercepted
- ; CX Number of bytes received (low part)
- ; DX " (high part)
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX, CX, DX
- ; ===============================================================
- ;
- COMMS_Status PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- MOV AX, [SI].Comm_State
- CMP AL, INTERCEPTED
- JNE _ST_intercept
- MOV CX, WORD PTR [SI].Comm_Receive_Count
- MOV DX, WORD PTR [SI].Comm_Receive_Count+2
- JMP SHORT _ST_exit
- _ST_intercept:
- PUSH AX
- MOV DX, [SI].Comm_PortAddr
- ADD DX, LSR
- IN AL, DX
- MOV CX, 0
- MOV DX, CX
- TEST AL, 01h
- JZ _ST_intercept1
- INC CX
- _ST_intercept1:
- POP AX
- _ST_exit:
- POP SI
- RET
- COMMS_Status ENDP
-
- ;
- ; ===============================================================
- ; COMMS_DTRon Enable Data Terminal Ready
- ; COMMS_DTRoff Disable Data Terminal Ready
- ; COMMS_DTRget Return status of Data Terminal Ready
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS, CS XBIOS CSEG[ment]
- ; DX Unit number (COM1 = 00h, COM2 = 01h)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX modified
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AL Port value
- ; DX Port address
- ; SI COMMS structure base address
- ; ===============================================================
- ;
-
-
- COMMS_DTRon PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- ; Read in current setting
- PUSH DX
- MOV DX, [SI].Comm_PortAddr
- ADD DX, MCR
- IN AL, DX
- IONOP
- OR AL, 001h ; Set the DTR bit
- OUT DX, AL
- IONOP
- POP DX
- POP SI
- RET
- COMMS_DTRon ENDP
-
- COMMS_DTRoff PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- PUSH DX
- MOV DX, [SI].Comm_PortAddr
- ADD DX, MCR
- IN AL, DX
- IONOP
- AND AL, 0FEh ; Clear the DTR bit
- OUT DX, AL
- IONOP
- POP DX
- POP SI
- RET
- COMMS_DTRoff ENDP
-
- COMMS_DTRget PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- ; Read in current setting
- PUSH DX
- MOV DX, [SI].Comm_PortAddr
- ADD DX, MCR
- IN AL, DX
- IONOP
- AND AL, 001h ; Set the DTR bit
- MOV AH, 00h
- POP DX
- POP SI
- RET
- COMMS_DTRget ENDP
-
-
- ;
- ; ===============================================================
- ; COMMS_RTSon Enable Request to Send
- ; COMMS_RTSoff Disable Request to Send
- ; COMMS_RTSget Return status of RTS
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS, CS XBIOS CSEG[ment]
- ; DX Unit number (COM1 = 00h, COM2 = 01h)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX modified
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AL Port value
- ; DX Port address
- ; SI COMMS structure base address
- ; ===============================================================
- ;
-
- COMMS_RTSon PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- PUSH DX
- MOV DX, [SI].Comm_PortAddr
- ADD DX, MCR
- IN AL, DX
- IONOP
- OR AL, 002h ; Set the RTS bit
- OUT DX, AL
- IONOP
- POP DX
- POP SI
- RET
- COMMS_RTSon ENDP
-
- COMMS_RTSoff PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- PUSH DX
- MOV DX, [SI].Comm_PortAddr
- ADD DX, MCR
- IN AL, DX
- IONOP
- AND AL, 0FDh ; Clear the RTS bit
- OUT DX, AL
- IONOP
- POP DX
- POP SI
- RET
- COMMS_RTSoff ENDP
-
-
- COMMS_RTSget PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- PUSH DX
- MOV DX, [SI].Comm_PortAddr
- ADD DX, MCR
- IN AL, DX
- IONOP
- AND AL, 002h ; Set the RTS bit
- SHR AL, 1
- MOV AH, 0
- POP DX
- POP SI
- RET
- COMMS_RTSget ENDP
-
- ; ===============================================================
- ; COMMS_BREAKon Enable Line Break
- ; COMMS_BREAKoff Disable Line Break
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS, CS XBIOS CSEG[ment]
- ; DX Unit number (COM1 = 00h, COM2 = 01h)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX modified
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AL Port value
- ; DX Port address
- ; SI COMMS structure base address
- ; ===============================================================
- ;
- COMMS_BREAKon PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- PUSH DX
- MOV DX, [SI].Comm_PortAddr
- ADD DX, LCR
- IN AL, DX
- IONOP
- OR AL, 040h ; Set the Break bit
- OUT DX, AL
- IONOP
- POP DX
- POP SI
- RET
- COMMS_BREAKon ENDP
-
- COMMS_BREAKoff PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- PUSH DX
- MOV DX, [SI].Comm_PortAddr
- ADD DX, LCR
- IN AL, DX
- IONOP
- AND AL, 0BFh ; Clear the break bit
- OUT DX, AL
- IONOP
- POP DX
- POP SI
- RET
- COMMS_BREAKoff ENDP
-
- COMMS_BREAKget PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- PUSH DX
- MOV DX, [SI].Comm_PortAddr
- ADD DX, LCR
- IN AL, DX
- IONOP
- AND AL, 040h ; Clear the break bit
- MOV AH, 00h
- MOV CL, 6
- SHR AL, CL
- POP DX
- POP SI
- RET
- COMMS_BREAKget ENDP
-
-
- ;
- ; ===============================================================
- ; COMMS_fc_on Enable XON flow control (only in interrupt mode)
- ; COMMS_fc_off Disable XON flow control (only in interrupt mode)
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS, CS XBIOS CSEG[ment]
- ; DL Unit number (COM1 = 00h, COM2 = 01h)
- ; DH 3 for rec & tx, 1 for rec only, 2 for tx only
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AL modified
- ; == 00h, CY=NC Successful disabling of flow control
- ; AL== FFh, CY=C Interrupts not enabled
- ; AL== FEh, CY=C Flow control was already enabled
- ; AL== FDh, CY=C Low is >= high water mark
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; DX Port address
- ; SI COMMS structure base address
- ; ===============================================================
- ;
- public COMMS_fc_on
- COMMS_fc_on PROC NEAR
- PUSH SI
- PUSH DX
- XOR DH, DH ; DL has port number
- Load_SI ; Load SI with Comms_Str
- MOV AL, 0FFh ; Assume interrupt error
- CMP [SI].Comm_State, INTERCEPTED
- JNE _fcon_error
- ;*** MOV AL, 0FEh ; Assume flow control
- ;*** CMP [SI].Comm_Xflags, 0
- ;*** JNE _fcon_error
- MOV AL, 0FDh ; Assume water marks error
- CMP CX, BX
- JB _fcon_error ; (unsigned compare)
- ; All is OK
- MOV [SI].Comm_Xflags, 01h
- MOV [SI].Comm_low, BX
- MOV [SI].Comm_high, CX
-
- POP BX ; bh has rec/tx indicator
- XOR BL, BL
- MOV BL, BH
- MOV AX, BX
- AND AX, 1 ; rec on ?
- JZ test_tx
- OR [SI].COMM_Xflags, FC_REC_ON
- test_tx:
- MOV AX, BX
- AND AX, 2 ; rec on ?
- JZ test_tx2
- OR [SI].COMM_Xflags, FC_TX_ON
- test_tx2:
-
-
- ;
- ; Enable XON/XOFF routines
- ;
- SI_FCon
-
- MOV AL, 00h
- CLC
- JMP SHORT _fcon_exit
- _fcon_error:
- STC
- POP BX
- _fcon_exit:
- POP SI
- RET
- COMMS_fc_on ENDP
-
-
- ;
- ; ===============================================================
- ; COMMS_fc_off Disable XON flow control (only in interrupt mode)
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS, CS XBIOS CSEG[ment]
- ; DL Unit number (COM1 = 00h, COM2 = 01h)
- ; DH 3 for rec & tx, 1 for rec only, 2 for tx only
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AL modified
- ; == 00h, CY=NC Successful disabling of flow control
- ; AL== FFh, CY=C Interrupts not enabled
- ; AL== FEh, CY=C Flow control wasn't even enabled
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; DX Port address
- ; SI COMMS structure base address
- ; ===============================================================
- ;
-
- COMMS_fc_off PROC NEAR
- PUSH SI
- PUSH DX
- XOR DH, DH ; dl has port number
- Load_SI ; Load SI with Comms_Str
- MOV AL, 0FFh ; Assume interrupt error
- CMP [SI].Comm_State, INTERCEPTED
- JNE _fcoff_error
- ;*** MOV AL, 0FEh ; Assume no flow control
- ;*** TEST [SI].Comm_Xflags, 1
- ;*** JZ _fcoff_error
- ; All is OK
- MOV [SI].Comm_low, 0
- MOV [SI].Comm_high, 0
- ;****** MOV [SI].Comm_Xflags, 00h
-
- POP BX ; bh has rec/tx indicator
- XOR BL, BL
- MOV BL, BH
- MOV AX, BX
- AND AX, 1 ; rec off ?
- JZ test_txoff
- AND [SI].COMM_Xflags, NOT FC_REC_ON
- test_txoff:
- MOV AX, BX
- AND AX, 2 ; rec on ?
- JZ test_txoff2
- AND [SI].COMM_Xflags, NOT FC_TX_ON
- test_txoff2:
- MOV AX, [SI].COMM_Xflags
- TEST AX, FC_TX_ON or FC_REC_ON
- JNZ fc_not_off
- MOV [SI].COMM_Xflags, 0
-
- SI_FCoff
-
- fc_not_off:
- CLC
- MOV AL, 00h
- JMP SHORT _fcoff_exit
- _fcoff_error:
- STC
- POP BX
- _fcoff_exit:
- POP SI
- RET
- COMMS_fc_off ENDP
-
-
- ;
- ; ===============================================================
- ; COMMS_Gaddr Return the address to the COMMS structure
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL Comm unit number
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; DX:BX Address of Comm's structure
- ;
-
- COMMS_Gaddr PROC NEAR
- PUSH SI
-
- Load_SI ; Load SI with Comms_Str
- MOV BX, SI
- PUSH CS
- POP DX
-
- POP SI
- RET
- COMMS_Gaddr ENDP
-
- ;
- ; ===============================================================
- ; COMMS_GPORT Return the status of the communications port
- ; ===============================================================
- ; Available for external use (XC_TSR.ASM)
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DX Desired port number
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX = 0 OK, port exists
- ; 1 OK, however, actual I/O port doesn't seem to exist
- ; -1 Port is not supported
-
- PUBLIC COMMS_GPORT
- COMMS_GPORT PROC NEAR
- PUSH SI
- Load_SI
- MOV AX, -1 ; Assume illegal port
-
- CMP DX, MAXPORTS ; Return max ports
- JGE _gport_skip
-
- MOV DX, [SI].Comm_PortAddr ; Test the port presence
- ADD DX, LCR ; Read the LCR
- IN AL, DX
- IONOP
- MOV BH, AL ; Save the contents
-
- INC AL ; Modify the LCR
- MOV BL, AL
- OUT DX, AL
- IONOP
- MOV AL, 0AAh ; In case data doesn't latch
- IN AL, DX ; Read in the LCR again
-
- CMP AL, BL
- JE _gport_reset
- MOV AX, 1 ; Not the same, exit
- JMP SHORT _gport_skip
- _gport_reset:
- MOV AL, BH ; Restore original LCR
- OUT DX, AL
- MOV AX, 0
- IONOP
- _gport_skip:
- POP SI
- RET
- COMMS_GPORT ENDP
-
- ;
- ; ===============================================================
- ; COMMS_Uxmit Unpended block transmit
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; CX Count
- ; SI:BX Address of transmit buffer
- ; DL Communications unit
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX 0 (successful)
-
- public COMMS_Uxmit
- COMMS_Uxmit PROC NEAR
- PUSH ES
- PUSH SI
- PUSH SI
- POP ES
- Load_SI ; Load SI with Comms_Str
- _uxmit_loop:
- CMP [SI].Comm_xcount, 0 ; Transmission in progress?
- JNE _uxmit_loop ; Yes - wait ...
-
- MOV DX, [SI].Comm_PortAddr ; read in THRE register **XMIT*XON*FIX**
- ADD DX,LSR ; **XMIT*XON*FIX**
- _uxmit_loop2: ; **XMIT*XON*FIX**
- IN AL, DX ; **XMIT*XON*FIX**
- AND AL, 20H ; isolate THRE **XMIT*XON*FIX**
- CMP AL, 20H ; last char xmitted? **XMIT*XON*FIX**
- JNE _uxmit_loop2 ; no - wait ... **XMIT*XON*FIX**
-
- CLI ; disable interrupts **XMIT*XON*FIX**
-
- ; The following 4 lines were moved after "no_handshake:"
- ; INC CX ; Always starts one greater
- ; MOV [SI].Comm_xcount, CX
- ; MOV [SI].Comm_xptr_Segment, ES
- ; MOV [SI].Comm_xptr_Offset, BX
-
- TEST [SI].Comm_Xflags,FC_TX_ON ; Is flow control enabled? **XMIT*XON*FIX**
- JE uxmit_no_fc ; no - check handshaking **XMIT*XON*FIX**
- TEST [SI].Comm_Xflags,FC_XOFF_RCVD ; Was XOFF received? **XMIT*XON*FIX**
- JE uxmit_no_fc ; no - check handshaking **XMIT*XON*FIX**
- MOV AX, -1 ; **XMIT*XON*FIX**
- JMP err_return ; **XMIT*XON*FIX**
-
- ;********** 2.0a added handshaking logic
- uxmit_no_fc: ;**XMIT*XON*FIX**
- CMP [SI].Comm_DTR_RTS, 0 ; Are we using handshaking
- JE no_handshake
- MOV DX, [SI].Comm_PortAddr ; Yes- read in modem status register to
- ADD DX,MSR
- IN AL, DX ; clear interrupt
- ; look for Hardware Handshaking flag
- and al, [si].Comm_DTR_RTS ; look for CTS and/or DSR
- cmp al, [si].Comm_DTR_RTS ; Unable to Xmit if Hardware Handshaking and CTS/DST not set
- ; AND AL, 00110000B ; look for CTS and DSR
- ; CMP AL, 00110000B ;
- JE no_handshake ; OK to proceed
- MOV AX, -1
- JMP err_return
-
- no_handshake:
- INC CX ; Always starts one greater
- MOV [SI].Comm_xcount, CX
- MOV [SI].Comm_xptr_Segment, ES
- MOV [SI].Comm_xptr_Offset, BX
-
- SI_continue
- MOV AX, 0
- err_return:
- STI ;re-enable interrupts **XMIT*XON*FIX**
- POP SI
- POP ES
- RET
- COMMS_Uxmit ENDP
-
-
- ;
- ; ===============================================================
- ; COMMS_FASTR Fast read of the input buffer
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; CX Count
- ; SI:BX Address of user's buffer
- ; DL Communications unit
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; DX 0 (successful)
-
- COMMS_FASTR PROC NEAR
- PUSH ES
- PUSH DI
- PUSH SI
- PUSH SI
- POP ES ; ES:BX points to user's buffer
- Load_SI ; Load SI with Comms_Str
- MOV DI, BX
- XOR DX, DX ; DX actual, CX expected count
- _Fastr_loop:
- MOV AX, WORD PTR [SI].Comm_Receive_Count
- OR AX, WORD PTR [SI].Comm_Receive_Count+2
- JZ _Fastr_exit
-
- PUSH CX
- PUSH DX
- PUSH ES
- CALL _Rd_getchar
- POP ES
- POP DX
- POP CX
- STOSB ; Save the character
- INC DX ; Increment actual count read
- LOOP _Fastr_loop
- _Fastr_exit:
- MOV AX, DX ; Return the count
- POP SI
- POP DI
- POP ES
- RET
- COMMS_FASTR ENDP
-
-
- ; ===============================================================
- ; COMMS_UTEST Unpended block transmit
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL Communications unit
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX 0 (all done)
- ; != 0 (output still in progress)
-
- COMMS_UTEST PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
-
- MOV AX, [SI].Comm_xcount
-
- POP SI
- RET
- COMMS_UTEST ENDP
-
- ; ===============================================================
- ; COMMS_UKILL Unpended block transmit terminator
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL Communications unit
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
-
- COMMS_UKILL PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
-
- ; Check if our UART mode indicates FIFOs are enabled
- ; Allowable values for bits 0 to 3 of "COMM_UART_Mode" are:
- ; 0 = 16440 (16550 Character) mode
- ; 1 = 16550 FIFOs enabled, DMA mode 0
- ; 9 = 16550 FIFOs enabled, DMA mode 1 (This mode is not used)
- test [si].COMM_UART_Mode, 09h
- jz _ukill_continue ; FIFOs not present or not enabled
-
- ; Clear TX FIFO by writing a 1 to bit 2 of the UART's FCR
- mov dx, [si].Comm_PortAddr
- add dx, 2 ; DX points to FCR or IIR
- mov ax, [si].COMM_UART_Mode
- or ax, 04h ; Enable bit 2 of UART's FCR
- mov [si].Comm_xcount, 00 ; Clear XCOMMS TX buffer
- out dx, al ; clear TX FIFO
- IONOP
-
- _ukill_continue:
- mov [si].Comm_xcount, 00 ; Clear XCOMMS TX buffer
-
- POP SI
- RET
- COMMS_UKILL ENDP
-
-
- ; ===============================================================
- ; COMMS_FCKILL KILL ALL OF THE FLOW CONTROL DATA BASE
- ; ===============================================================
- ;
- ; Clear the state bits except for the FC_ENABLED bit.
- ; If there was any transmission pended (waiting on XON)
- ; then "kick start" it and continue sending where it left
- ; off.
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL Communications unit
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
-
- COMMS_FCKILL PROC NEAR
- PUSH SI
- Load_SI ; Load SI with Comms_Str
-
- AND [SI].Comm_Xflags, FC_ENABLED
- SI_continue ; Continue transmission
- POP SI
- RET
- COMMS_FCKILL ENDP
-
-
- ; ===============================================================
- ; COMMS_XCTIMOU Set the send/transmit timeout value
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL Communications unit
- ; CX New timeout value (unsigned)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
-
- COMMS_XCTIMOU PROC NEAR
- MOV timeout_variable, CX
- RET
- COMMS_XCTIMOU ENDP
-
-
- ; ===============================================================
- ; COMMS_OUT2 Set the out2 initialization value
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL Communications unit
- ; CX New value (unsigned)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
-
- COMMS_OUT2 PROC NEAR
- MOV out2_variable, CX
- RET
- COMMS_OUT2 ENDP
-
- ; ===============================================================
- ; COMMS_STATUS_PORT Set the status port value
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL Communications unit
- ; CX New value (unsigned)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
-
- COMMS_STATUS_PORT PROC NEAR
- CMP DL, 0
- JE firstboard4
- MOV Status2_port, CX
- RET
- firstboard4:
- MOV Status_port, CX
- RET
- COMMS_STATUS_PORT ENDP
-
- ; ===============================================================
- ; COMMS_SHARED_VECTOR Set the shared VECTOR value
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL Communications unit
- ; CX New value (unsigned)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
-
- COMMS_SHARED_VECTOR PROC NEAR
- CMP DL, 0
- JE firstboard5
- MOV Shared2_vector, CL
- RET
- firstboard5:
- MOV Shared_vector, CL
- RET
- COMMS_SHARED_VECTOR ENDP
-
- ; ===============================================================
- ; COMMS_SHARED_ICMASK Set the shared ICMASK value
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL Communications unit
- ; CX New value (unsigned)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
-
- COMMS_SHARED_ICMASK PROC NEAR
- CMP DL, 0
- JE firstboard6
- MOV Shared2_IC_mask, CL
- RET
- firstboard6:
- MOV Shared_IC_mask, CL
- RET
- COMMS_SHARED_ICMASK ENDP
-
- ; ===============================================================
- ; COMMS_BOARD_TYPE Set the multiport board type
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL Communications unit
- ; CX New value (unsigned)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
-
- COMMS_BOARD_TYPE PROC NEAR
- CMP DL, 0
- JE firstboard7
- MOV board2_type, CX
- RET
- firstboard7:
- MOV board_type, CX
- RET
- COMMS_BOARD_TYPE ENDP
-
-
- ; ===============================================================
- ; COMMS_STARTPORT Set the multiport starting port number
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL Communications unit
- ; CX New value (unsigned)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
-
- COMMS_STARTPORT PROC NEAR
- CMP DL, 0
- JE firstboard8
- MOV starting2_port, CX
- RET
- firstboard8:
- MOV starting_port, CX
- RET
- COMMS_STARTPORT ENDP
-
- ; ===============================================================
- ; COMMS_MAXPORT Set the multiport maximum port number
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL Multiport board number
- ; CX New value (unsigned)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
-
- COMMS_MAXPORT PROC NEAR
- CMP DL, 0
- JE firstboard9
- MOV maxshare2, CX
- RET
- firstboard9:
- MOV maxshare, CX
- RET
- COMMS_MAXPORT ENDP
-
-
- COMMS_57K PROC NEAR ; requires baud bits to be 0!
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- MOV AX, CX ; Baud rate is preset to a 0 (110 baud)
- MOV WORD PTR TIMERS_X16, 2 ; 57K divisor
- CALL INT14INIT
- MOV WORD PTR TIMERS_X16, 1047 ; original 110 divisor
- POP SI
- RET
- COMMS_57K ENDP
-
- COMMS_115K PROC NEAR ; requires baud bits to be 0!
- PUSH SI
- Load_SI ; Load SI with Comms_Str
- MOV AX, CX ; Baud rate is preset to a 0 (110 baud)
- MOV WORD PTR TIMERS_X16, 1 ; 115K divisor
- CALL INT14INIT
- MOV WORD PTR TIMERS_X16, 1047 ; original 110 divisor
- POP SI
- RET
- COMMS_115K ENDP
-
-
- public COMMS_SET_FC_CHAR
- ; ===============================================================
- ; COMMS_SET_FC_CHAR Set the XON/XOFF characters
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DL 0 = XON, 1 = XOFF
- ; CL New value (unsigned char)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
-
- COMMS_SET_FC_CHAR PROC NEAR
- CMP DL, 0
- JNE set_xoff
- MOV XON, CL
- RET
- set_xoff:
- MOV XOFF, CL
- RET
- COMMS_SET_FC_CHAR ENDP
-
- ;
- ; ===============================================================
- ; COMMS_Test_16550 : Test for existence of NS16550A UART
- ; ===============================================================
- ;
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; SI Pointer to communications database
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX 0 = NS 16550A UART is not present
- ; 1 = NS 16550A UART is present
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; Not applicable
- ; ===============================================================
- ;
- COMMS_Test_16550 PROC NEAR
- push si
- Load_SI ; Load SI with Comms_Str
- mov dx, [SI].Comm_PortAddr ; load port base adress
- add dx, 2 ; DX points to FCR or IIR
- mov al, 01h ; FIFO enable bit0 of FCR
- out dx, al ; Try to enable FIFOs
- IONOP
- in al, dx ; Read IIR or FCR
- IONOP
- test al, 0C0h ; See if IIR FIFO Enable Bits are set
- mov al, 00h ; FIFO disable bit0 of FCR
- out dx, al ; Disable FIFOs
- IONOP
- mov [SI].COMM_UART_Mode, 00h;Initialize UART Mode field
- jz _TST16550_not_present ; NS 16550A not present
- ; NS 16550A IS Present
- mov ax, 01h ; Return 1 : 16550A present
- jmp _exit_Test_16550
-
- _TST16550_not_present:
- mov ax, 00h ; Return 0 : 16550A not present
-
- _exit_Test_16550:
- pop si
- ret
- COMMS_Test_16550 ENDP
-
- ;
- ; ===============================================================
- ; COMMS_Set_16550 : Enable / Disable FIFOs on NS16550A UART
- ; ===============================================================
- ;
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; SI Pointer to communications database
- ; CH Always 0x00
- ;
- ; CL NS16550A Trigger value: (bits 6 and 7)
- ; 0x0* = 1 byte
- ; 0x1* = 4 bytes
- ; 0x2* = 8 bytes
- ; 0x3* = 14 bytes
- ;
- ; NS16550A Mode Value: (bits 0 to 3)
- ; 0x*0 = disable FIFOs (16450 mode)
- ; 0x*1 = Enable FIFOs, DMA mode 0
- ; 0x*9 = Enable FIFOs, DMA mode 1 (not used)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX 0 = NS 16550A UART is not present
- ; 1 = NS 16550A UART is present and initialzed
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; Not applicable
- ; ===============================================================
- ;
-
- COMMS_Set_16550 PROC NEAR
- push si
-
- Load_SI ; Load SI with Comms_Str
- mov dx, [si].Comm_PortAddr ; load port base adress
- add dx, 2 ; DX points to FCR or IIR
- test cl, 09h ; Mode: 0=disable, 1=FIFO enable:DMA mode0, 9=FIFO enable:DMA mode1 (not used)
- jnz _SET16550_enabled ; enable FIFO operation
- jmp _SET16550_not_enabled ; Disable FIFO operation
-
- ; ATTEMPT TO ENABLE NS16550A
- _SET16550_enabled:
- mov al, cl ; recover trigger value and mode
- out dx, al ; Try to enable FIFOs w/ trigger
- IONOP
- in al, dx ; Read IIR or FCR: Check for FIFOs enabled
- IONOP
- test al, 0C0h ; IIR, FIFO Enable mask
- jz _SET16550_not_enabled ; NS 16550A not present
-
- ; UART now intialized with FIFOs enabled with DMA mode 0 or mode 1
- mov [si].COMM_UART_Mode, cx ; Store UART's FCR containing Mode and Trigger info.
- mov ax, 01h ; Return 1 : 16550A present and initialized
- jmp _exit_Set_16550
-
- _SET16550_not_enabled: ; Disable FIFO operation
- mov ax, 00h ; FIFO disable bit0 of FCR
- ; Return 0 : 16550A not present
- out dx, al ; Disable FIFOs
- IONOP
- mov [si].COMM_UART_Mode, 00h;Initialize UART Mode field
-
- _exit_Set_16550:
- pop si
- ret
- COMMS_Set_16550 ENDP
-
-
-
- ;
- ; ===============================================================
- ; COMMS_Get_Buffer_Memory
- ; ===============================================================
- ;
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DH 1=get first buffer; 0=get subsequent buffers
- ; DL Comm Port number (starting from 0)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX 1 = Buffer Allocated
- ; 0 = Buffer not allocated
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; SI Pointer to communications database
- ; ===============================================================
- ;
-
- COMMS_Get_Buffer_Memory PROC NEAR
- push si
- push di
- push es
-
- ; cli ; Disable Interrupts
-
- Load_SI ; Load SI with Comms_Str
-
- test dh, 01h
- jnz xcgmem_first_buffer
-
- ; Get ECL Receive buffer location (segment)
- mov dx, [si].Comm_CR_BUFFR_Segment
- mov es, dx
-
- ; add another buffer
- call BUFFR_Gmem ; Get next available buffer
- jc xcgmem_nobuff ; None available
- ; Increment next buffer information
- inc [si].Comm_Buffer_Count
- mov di, [si].Comm_CR_BUFFR_Offset
- mov es:[di], bx ; Save pointer in previous last block
- mov es:[di+2], dx
- mov [si].Comm_CR_BUFFR_Offset, bx
- mov [si].Comm_CR_BUFFR_Segment, dx
- mov [si].Comm_CR_BUFFR_Index, 4 ; New index
- mov ax, 01h
- jmp xcgmem_exit
-
- xcgmem_first_buffer:
- mov WORD PTR [si].Comm_Receive_Count, 0
- mov WORD PTR [si].Comm_Receive_Count + 2, 0
- mov [si].Comm_Buffer_Count, 0
- call BUFFR_Gmem ; Get next available buffer
- jc xcgmem_nobuff ; None available
- call COMMS_Bufclr
- mov ax, 01h
- jmp xcgmem_exit
-
-
- xcgmem_nobuff:
- mov ax, 00h
-
- xcgmem_exit:
- ; sti ; Enable Interrupts
- pop es
- pop di
- pop si
- ret
- COMMS_Get_Buffer_Memory ENDP
-
-
- ;
- ; ===============================================================
- ; COMMS_Free_Buffer_Memory
- ; ===============================================================
- ;
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DH Always 0x00
- ; DL Comm Port number (starting from 0)
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not Applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; SI Pointer to communications database
- ; ===============================================================
- ;
-
- COMMS_Free_Buffer_Memory PROC NEAR
- push si
-
- cli ; Disable Interrupts
-
- Load_SI ; Load SI with Comms_Str
-
- ; Free all buffers for this port
- call COMMS_Buffree ; Free all buffers for this port
-
- sti ; Enable Interrupts
-
- pop si
- ret
- COMMS_Free_Buffer_Memory ENDP
-
- ;
- ; ===============================================================
- ; COMMS_Put_Buffer_Memory
- ; ===============================================================
- ;
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; BX Offset of the buffer base
- ; DX Segment of the buffer base
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not Applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; SI Pointer to communications database
- ; ===============================================================
- ;
- COMMS_Put_Buffer_Memory PROC NEAR
- cli ; disable ints
- ; Place one of the released memory buffers back in the pool
- call BUFFR_Pmem
- sti ; enable ints
- ret
- COMMS_Put_Buffer_Memory ENDP
-
-
- ;
- ; ===============================================================
- ; COMMS_Set_Int_Exit
- ; ===============================================================
- ;
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; CH Interrupt Handler Number COM1, COM2, SHARE1, SHARE2
- ; CL MASK for Interrupt Events to trap
- ; BX Offset of exit Function to call
- ; DX Segment of the function
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not Applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; SI Pointer to variable data area
- ; ===============================================================
- ;
- PUBLIC COMMS_Set_Int_Exit
- COMMS_Set_Int_Exit PROC NEAR
- IFDEF INT_EXITS
- push ds
- push cs
- pop ds
- mov si, offset cs:com1_mask ; use ds:si to reference data
- xor ah, ah ; 6 bytes per handler
- mov al, ch
- xor ch, ch
- mov ah, 6
- mul ah
- add si, ax ; si now points to mask area
- mov word ptr [si], cx ; mask
- mov word ptr [si+2], bx ; offset address
- mov word ptr [si+4], dx ; segment address
-
- cli ; disable ints
- mov word ptr si, cx ; mask value
- sti ; enable ints
- pop ds
- ENDIF
- ret
- COMMS_Set_Int_Exit ENDP
-
-
-
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
- ; INCLUDE BUFFR.ASM ; Include buffer management services
- ;*******************************************************************
- ;
- ; BUFFR.ASM - XCOMMS kernal memory allocation services
- ;
- ; (C) Copyright 1989, South Mountain Software Inc.
- ; All Rights Reserved
- ;
- ;
- ; Note that all of the procedures do not expect the segment
- ; registers to be preset to anything (except the CS, of course).
- ; Each buffer is suitable filled with the buffer number byte
- ; (first buffer filled with 0, second with 1, etc.).
- ;
- ; The first 2 words of each buffer contains the pointer to the
- ; next buffer in the chain.
- ;
- ; Note - the BUFFR module has no concept where the contiguous
- ; memory buffer came from!
- ;
- ; Revision 2.0 No changes required
-
- ;
- ; ===============================================================
- ; Definitions
- ; ===============================================================
- ;
-
- BUFFER_SIZE EQU 1024
- PARA EQU 16
- SEG_1K EQU 1024 / PARA
-
-
- ;
- ; ===============================================================
- ; Local data
- ; ===============================================================
- ;
-
- BUFFR_DATA LABEL BYTE ; BUFFR module data base
- Available DW ? ; Number of buffers left
- No_of_Buffers DW ? ; Number of buffers total
- BUFFR_Pool DD ?
- Base_Buffer DD ? ; Base of the buffer
- BUFFR_Total DW 8
- BUFFR_Used DW 0
-
- ;
- ; ===============================================================
- ; Local procedures
- ; ===============================================================
- ;
- ; BUFFR_Entry Enter in the buffer module and allocate
- ; BUFFR_Status Return the number of buffer used
- ; BUFFR_Init Initialize the buffer pool
- ; BUFFR_Gmem Get the next buffer from the buffer pool
- ; BUFFR_Pmem Put the memory block back into the pool
- ;
-
-
-
- ;
- ; ===============================================================
- ; BUFFR_Entry Enter in the buffer module and allocate
- ; ===============================================================
- ;
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; BX Offset of the buffer base
- ; DX Segment of the buffer base
- ; CX Number of 1K buffers to allocate
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX, BX, CX, DX Modified (not important to maintain)
- ; ===============================================================
- ;
-
-
- BUFFR_Entry PROC NEAR
-
- ; Setup the buffer parameters
-
- PUSH DS
- PUSH CS
- POP DS
-
- MOV Available, 0
- MOV No_of_Buffers, CX
-
- ; Adjust the base address so that the entire buffer fits in
- ; a segment
-
- TEST BX, 0000Fh ; First, get to paragraph
- JZ _entry_ok
- AND BX, 0FFF0h
- INC DX
- _entry_ok:
- MOV AX, BX ; Next, give it plenty of room
- AND BX, 0F000h
- MOV CL, 4
- SHR AX, CL
- AND AX, 00FFh
- ADD DX, AX
- MOV WORD PTR [Base_Buffer], BX
- MOV WORD PTR [Base_Buffer+2], DX
-
- ; Initialize the buffer pool list
-
- CALL BUFFR_Init
- POP DS
- RET
- BUFFR_Entry ENDP
-
-
- ;
- ; ===============================================================
- ; BUFFR_Status Return the number of buffer used
- ; ===============================================================
- ;
- ; Return the number of buffers reserved and the number
- ; of buffers available (in the buffer pool). The number
- ; actually in current use is equal to the difference.
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; BX Number of buffers reserved
- ; CX Number of buffers available for use
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; BX, CX Modified
- ; ===============================================================
- ;
-
- BUFFR_Status PROC NEAR
- PUSH DS
- PUSH CS
- POP DS
- MOV BX, No_of_Buffers
- MOV CX, Available
- POP DS
- RET
- BUFFR_Status ENDP
-
-
- ;
- ; ===============================================================
- ; BUFFR_Init Initialize the buffer pool
- ; ===============================================================
- ;
- ; Make all buffer entries available for use.
- ; This assumes that the No_of_Buffers and the Base_Buffer
- ; variables are preset.
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; None modified
- ; ===============================================================
- ;
-
- BUFFR_Init PROC NEAR
- PUSH ES
- PUSH DS
- PUSH CS
- POP DS
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
-
- MOV Available, 0 ; All buffers are available
- MOV BX, WORD PTR Base_Buffer; Assume base is adjusted
- MOV DX, WORD PTR Base_Buffer+2
- MOV CX, No_of_Buffers
- MOV AL, 0
- _BI_loop:
- MOV ES, DX
- MOV DI, BX
- PUSH CX
- MOV CX, BUFFER_SIZE
- REP STOSB
- POP CX
- INC AL
- PUSH AX
- CALL BUFFR_Pmem ; Add all buffers to pool
- ADD DX, SEG_1K
- POP AX
- LOOP _BI_loop
-
- POP DX
- POP CX
- POP BX
- POP AX
- POP DS
- POP ES
- RET
- BUFFR_Init ENDP
-
- ;
- ; ===============================================================
- ; BUFFR_Gmem Get the next buffer from the buffer pool
- ; ===============================================================
- ;
- ; The user asks for the next memory buffer and if one is
- ; available, becomes the owner. The number of buffers available
- ; will be decreased by one - in fact, the number of buffers left
- ; available is returned in this call.
- ;
- ; Before:
- ; +----------+
- ; BUFFR_Pool | o----|----------+
- ; +----------+ |
- ; b v
- ; +--------------+
- ; | o-------|---> c
- ; +--------------+
- ;
- ; After:
- ; +----------+
- ; BUFFR_Pool | o----|----------+
- ; +----------+ |
- ; c v
- ; +--------------+
- ; | o-------|---> d
- ; +--------------+
- ;
- ; If a buffer is not available (all are being owned), the appropriate
- ; status is returned and the pool is unchanged.
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; if buffer is returned (released to the user):
- ; CY = NC Signal (flag)
- ; AL = 00h Signal byte
- ; BX Offset of the buffer
- ; DX Segment of the buffer
- ; CX Number of 1K buffers still available (after release)
- ; if buffer is not available:
- ; CY = C Signal (flag)
- ; AL = FFh Signal byte
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX, BX, CX, DX Modified
- ; ===============================================================
- ;
-
- BUFFR_Gmem PROC NEAR
- PUSH DS
- PUSH CS
- POP DS
- CMP Available, 0 ; Any buffers available?
- JE _BG_error ; No
-
- PUSHF ; FORCE Disable interrupts
- CLI
- PUSH AX
- PUSH ES
- ; Unlink the first entry
- MOV AX, WORD PTR BUFFR_Pool+2
- MOV ES, AX
- MOV BX, WORD PTR BUFFR_Pool
- MOV AX, ES:[BX]
- MOV WORD PTR BUFFR_Pool, AX
- MOV AX, ES:[BX+2]
- MOV WORD PTR BUFFR_Pool+2, AX
- MOV DX, ES
-
- POP ES
- POP AX
-
- DEC Available
- POPF
- MOV CX, Available ; Return buffers still left
- CLC
- MOV AL, 00h
- JMP SHORT _BG_exit
- _BG_error:
- STC
- MOV AL, 0FFh
- _BG_exit:
- POP DS
- RET
- BUFFR_Gmem ENDP
-
- ;
- ; ===============================================================
- ; BUFFR_Pmem Put the memory block back into the pool
- ; ===============================================================
- ;
- ; Place one of the released memory buffers back into the pool -
- ; note that the offset must be at least 1K bytes from the
- ; segmentation limit (it is not checked).
- ;
- ; Using the address (segment:offset) received by the BUFFR_Pmem
- ; call will guarantee that. All registers are returned unmodified.
- ;
- ; MEMORY BUFFERS MUST HAVE BEEN INITIALIZED WITH BUFFR_ENTRY BEFORE
- ; THEY CAN BE PUT BACK INTO THE POOL.
- ;
- ; Before:
- ; +----------+
- ; BUFFR_Pool | o----|----------+
- ; +----------+ |
- ; b v
- ; +--------------+
- ; | o-------|---> c
- ; +--------------+
- ;
- ; After (insert 'x'):
- ;
- ; +----------+
- ; BUFFR_Pool | o----|----------+
- ; +----------+ |
- ; x v
- ; +--------------+
- ; | o-------|---> b
- ; +--------------+
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; BX Offset of the buffer base
- ; DX Segment of the buffer base
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; BX Offset of the buffer base
- ; DX Segment of the buffer base
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; Not applicable (None modified)
- ; ===============================================================
- ;
-
- BUFFR_Pmem PROC NEAR
- PUSH DS
- PUSH CS
- POP DS
- PUSH ES
- PUSH AX
-
- ; Add the front of the queue address to this buffer
-
- PUSHF
- CLI
- MOV ES, DX ; Add the link
- MOV AX, WORD PTR BUFFR_Pool
- MOV ES:[BX], AX
- MOV AX, WORD PTR BUFFR_Pool+2
- MOV ES:[BX+2], AX
-
- ; Put the buffer into the front of the queue
-
- MOV WORD PTR BUFFR_Pool, BX
- MOV WORD PTR BUFFR_Pool+2, DX
-
- ; Decrement the number used
-
- INC Available
- POPF
-
- POP AX
- POP ES
- POP DS
- RET
- BUFFR_Pmem ENDP
-
-
-
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
- ; INCLUDE TIMER.ASM ; The timer services
- ;*******************************************************************
- ;
- ; TIMER.ASM - XCOMMS kernal timer services
- ;
- ; (C) Copyright 19896 SOuth Mountain Software Inc.
- ; All Rights Reserved
- ;
- ; The TIMER component allows the 1Ch interrupt to be taken over
- ; for machine-independent timer requests. Note that the 1Ch
- ; interrupt handlers must be chained (previous handlers expect to
- ; still be called every 55 milliseconds).
- ;
- ; Revision 2.0 Changes required for timer "ports"
- ; NOTE - no verification of timer channel number!
- ;
- ; ===============================================================
- ; Definitions
- ; ===============================================================
- ;
-
- ;
- ; ===============================================================
- ; Local data
- ; ===============================================================
- ;
-
- Timer_State DW ? ; = 01h if intercepted
- Timer_Old_Offset DD ? ; Old 1Ch interrupt address
- Timer_Counter DW ? ; Timer decrementing counter
- Timer_Ports_Counter DW MAXPORTS DUP (?) ; Multiple timer channels
- Timer_Ports_State DW MAXPORTS DUP (?) ; Multiple timer channels
-
- ;
- ; ===============================================================
- ; Local procedures
- ; ===============================================================
- ;
- ; TIMER_Int The 1Ch interrupt handler (chained)
- ; TIMER_Entry Enter the timer module
- ; TIMER_Exit Exit the timer module
- ; TIMER_Status Return timer status
- ; TIMER_Link Link into Interrupt 1Ch chain (if not already)
- ; TIMER_UnLink Remove Link into the 1Ch timer interrupt chain
- ; TIMER_Set Set the Time counter increment (and go!)
- ; TIMER_Clear Abort the current timer count request
- ; TIMER_Test Test - return the current counter value
- ; TIMER_Wait Wait for the counter request to complete
- ;
-
-
- ;
- ; ===============================================================
- ; TIMER_Int Chain the 1Ch interrupt handler
- ; ===============================================================
- ;
- ; Take the 1Ch interrupt (once every 55 milliseconds) and
- ; if a timer counter is current, decrement. In any event,
- ; perform an indirect FAR jump to the previous 1Ch handler
- ; in the chain.
- ;
- ; Performance - routine should not take longer than 20 microseconds.
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; None affected
- ; ===============================================================
- ;
-
- Timer_Int PROC FAR ; New interrupt handler
- PUSH BX
- PUSH CX
-
- ; =======================
- ; Decrement generic timer
- ; =======================
-
- CMP CS:Timer_Counter, 0
- JE _TI_exit
- DEC CS:Timer_Counter ; Decrement the counter
- _TI_exit:
-
- ; =======================
- ; Decrement timer channels
- ; =======================
-
- MOV BX, 0 ; Timer channel index
- MOV CX, MAXPORTS
- _TI_loop:
- CMP CS:Timer_Ports_Counter[BX], 0
- JE _TI_skip
- DEC CS:Timer_Ports_Counter[BX]
- _TI_skip:
- ADD BX, 2
- LOOP _TI_loop
-
- POP CX
- POP BX
-
- ; =======================
- ; Chain to previous timer
- ; =======================
-
- JMP DWORD PTR CS:[Timer_Old_Offset]
- Timer_Int ENDP
-
-
-
- ;
- ; ===============================================================
- ; TIMER_Entry Enter the timer module
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; None affected
- ; ===============================================================
-
- TIMER_Entry PROC NEAR
- PUSH BX
- PUSH CX
-
- MOV Timer_Counter, 0 ; Init generic timer
- MOV Timer_State, NATIVE ; Assume not intercepted
-
- MOV BX, 0 ; Init timer channels
- MOV CX, MAXPORTS
- TIMER_Entry_loop:
- MOV Timer_Ports_State[BX], NATIVE
- MOV Timer_Ports_Counter[BX], 0
- ADD BX, 2
- LOOP TIMER_Entry_loop
-
- POP CX
- POP BX
- RET
- TIMER_Entry ENDP
-
- ;
- ; ===============================================================
- ; TIMER_Exit Exit the timer module
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; None affected
- ; ===============================================================
-
- TIMER_Exit PROC NEAR
- PUSH DX
- PUSH CX
-
- MOV DX, 0 ; Restore timer channels
- MOV CX, MAXPORTS
- _TIMER_Exit_loop:
- CALL TIMERP_UnLink
- INC DX
- LOOP _TIMER_Exit_loop
- POP CX
- POP DX
-
- CALL TIMER_UnLink ; Restore generic timer 1C interrupt
- CLC
- RET
- TIMER_Exit ENDP
-
- ;
- ; ===============================================================
- ; TIMER_Status Return timer status
- ; [TIMERP_Status Return timer channel status]
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; AH = 1Ch TIMER interrupt number
- ; AL = 00h Status request
- ; [DX Communications channel number]
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX = 00h Not intercepted
- ; AX = 01h Intercepted
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX Return value only
- ; ===============================================================
- ;
-
- TIMER_Status PROC NEAR
- MOV AX, Timer_State ; Return the status
- RET
- TIMER_Status ENDP
-
- ; ===============================================================
-
- TIMERP_Status PROC NEAR
- PUSH BX
-
- MOV BX, DX
- ADD BX, BX
- MOV AX, Timer_Ports_State[BX]
-
- POP BX
- RET
- TIMERP_Status ENDP
-
-
- ;
- ; ===============================================================
- ; TIMER_Link Link into Interrupt 1Ch chain (if not already)
- ; [TIMERP_Link Link into Interrupt 1Ch chain (if not already)]
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; AH = 1Ch TIMER interrupt number
- ; AL = 01h Link request
- ; [DX Communications channel number]
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AL = 00h Successful - chained in
- ; CY = NC Successful - chained in
- ; - or -
- ; AL = FFh Error
- ; CY = C Error - already chained, request ignored
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX Return value only
- ; DS Vector handler new segment address
- ; DX Vector handler new offset address
- ; ES Vector handler old segment address
- ; BX Vector handler old offset address
- ; ===============================================================
- ;
-
- TIMER_Link PROC NEAR
- CMP Timer_State, INTERCEPTED
- JE _TL_Error
-
- ; Save the current timer 1Ch vector handler address
-
- MOV Timer_Counter, 0 ; Timer counter is dead
-
- MOV AL, TIMER
- MOV DX, SEG Timer_Int
- MOV BX, OFFSET Timer_Int
- swapvec
- MOV WORD PTR Timer_Old_Offset, BX
- MOV WORD PTR Timer_Old_Offset+2, DX
- MOV Timer_State, INTERCEPTED
- MOV AL, 00h
- CLC
- JMP SHORT _TL_Exit
- _TL_Error:
- MOV AL, 0FFh
- STC
- _TL_Exit:
- RET
- TIMER_Link ENDP
-
- ; ===============================================================
-
- TIMERP_Link PROC NEAR ; Assumes TIMER_Link already called!!!!!!!!!
- PUSH BX
-
- MOV BX, DX
- ADD BX, BX
- CMP Timer_Ports_State[BX], INTERCEPTED
- JE _TLP_Error
- MOV Timer_Ports_State[BX], INTERCEPTED
- MOV AL, 00h
- CLC
- JMP SHORT _TLP_Exit
- _TLP_Error:
- MOV AL, 0FFh
- STC
- _TLP_Exit:
- POP BX
- RET
- TIMERP_Link ENDP
-
- ;
- ; ===============================================================
- ; TIMER_UnLink Remove Link into the 1Ch timer interrupt chain
- ; [TIMERP_UnLink Remove Link into the 1Ch timer interrupt chain]
- ; ===============================================================
- ;
- ; Link into the 1Ch timer interrupt chain ONLY IF the Timer_Int
- ; routine isn't already linked in. Return the appropriate status.
- ;
- ; TIMERP_UnLink does not modify interrupt 1C - assumes TIMER_UnLink controls
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; AH = 1Ch TIMER interrupt number
- ; AL = 02h UnLink request
- ; [DX Communications channel number]
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; CY = NC Successful - unchained out of 1Ch
- ; CY = C Error - not chained, request ignored
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX Set vector interface, scratch
- ; DS Vector handler new segment address
- ; DX Vector handler new offset address
- ; ===============================================================
- ;
-
- TIMER_UnLink PROC NEAR
- CMP Timer_State, INTERCEPTED
- JNE _TU_Error
-
- MOV BX, WORD PTR Timer_Old_Offset
- MOV DX, WORD PTR Timer_Old_Offset+2
- MOV AL, TIMER
- setvec
- MOV Timer_State, NATIVE
- MOV Timer_Counter, 0 ; Timer counter is dead
- MOV AL, 00h
- CLC
-
- JMP SHORT _TU_Exit
- _TU_Error:
- MOV AL, 0FFh
- STC
- _TU_Exit:
-
- RET
- TIMER_UnLink ENDP
-
- ; ===============================================================
-
- TIMERP_UnLink PROC NEAR
- PUSH BX
-
- MOV BX, DX
- ADD BX, BX
- CMP Timer_Ports_State[BX], INTERCEPTED
- JNE _TUP_Error
- MOV Timer_Ports_State[BX], NATIVE
- MOV Timer_Ports_Counter[BX], 0
- MOV AL, 00h
- CLC
- JMP SHORT _TUP_Exit
- _TUP_Error:
- MOV AL, 0FFh
- STC
- _TUP_Exit:
- POP BX
- RET
- TIMERP_UnLink ENDP
-
- ; ===============================================================
- ;
- ; Remaining timer services will NOT work if timer is not
- ; enabled - this routine is used by those routines
- ;
- ; ===============================================================
-
- _timer_status PROC NEAR
- MOV AX, Timer_State
- CMP AX, NATIVE
- JNE _intercept
- MOV AL, 0FFh
- STC
- JMP SHORT _exit
- _intercept:
- MOV AL, 00h
- CLC
- _exit:
- RET
- _timer_status ENDP
-
- ; ===============================================================
-
- _timerp_status PROC NEAR ; Expected DX for communications port number
-
- MOV BX, DX
- ADD BX, BX
- MOV AX, Timer_Ports_State[BX]
- CMP AX, NATIVE
- JNE p_intercept
- MOV AL, 0FFh
- STC
- JMP SHORT p_exit
- p_intercept:
- MOV AL, 00h
- CLC
- p_exit: ; Return BX as an index (word offset)
- RET
- _timerp_status ENDP
-
- ;
- ; ===============================================================
- ; TIMER_Set Set the Time counter increment (and go!)
- ; [TIMERP_Set Set the time channel counter and start]
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; CX Number of timer ticks (one occurs every 55 millis)
- ; [DX Timer channel number]
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AL = FFh,CY=C Not intercepted
- ; AX = 00h,CY=NC Intercepted
- ; CX same as above
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; Not applicable
- ; ===============================================================
- ;
-
- TIMER_Set PROC
- CALL _timer_status ; Set AL status return
- MOV Timer_Counter, CX
- RET
- TIMER_Set ENDP
-
- ; ===============================================================
-
- TIMERP_Set PROC
- PUSH BX
- CALL _timerp_status ; Set AL status return
- MOV Timer_Ports_Counter[BX],CX
- POP BX
- RET
- TIMERP_Set ENDP
-
- ;
- ; ===============================================================
- ; TIMER_Clear Abort the current timer count request
- ; [TIMERP_Clear Abort the current timer channel count request]
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS Pointer to CS segment
- ; [DX Timer channel number]
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AL = FFh,CY=C Not intercepted
- ; AX = 00h,CY=NC Intercepted
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX Return value only
- ; ===============================================================
- ;
-
- TIMER_Clear PROC
- CALL _timer_status ; Set AL status return
- MOV Timer_Counter, 0 ; Timer counter is dead
- RET
- TIMER_Clear ENDP
-
- ; ===============================================================
-
- TIMERP_Clear PROC
- PUSH BX
- CALL _timerp_status ; Set AL status return
- MOV Timer_Ports_Counter[BX],0; Timer counter is dead
- POP BX
- RET
- TIMERP_Clear ENDP
-
- ;
- ; ===============================================================
- ; TIMER_Test Test - return the current counter value
- ; [TIMERP_Test Test - return the current counter value]
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS Pointer to CS segment
- ; [DX Timer channel number]
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AL = FFh,CY=C Not intercepted
- ; or
- ; AX = 00h,CY=NC Intercepted
- ; CX = 00h Counter complete (or not even counted down)
- ; CX > 00h Counter timer still in progress
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX Return value only
- ; ===============================================================
- ;
-
- TIMER_Test PROC
- CALL _timer_status ; Set AL status return
- MOV CX, Timer_Counter ; Timer counter is dead
- RET
- TIMER_Test ENDP
-
- ; ===============================================================
-
- TIMERP_Test PROC
- PUSH BX
- CALL _timerp_status ; Set AL status return
- MOV CX, Timer_Ports_Counter[BX]
- POP BX
- RET
- TIMERP_Test ENDP
- ; ===============================================================
-
- ;
- ; ===============================================================
- ; TIMER_Wait Wait for the counter request to complete
- ; [TIMERP_Wait Wait for the counter request to complete]
- ; ===============================================================
- ;
- ; If no request is given (or the timer not even linked in),
- ; the request returns immediately.
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS Pointer to CS segment
- ; [DX Timer channel number]
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AL = FFh,CY=C Not intercepted
- ; AX = 00h,CY=NC Intercepted
- ; AX = 00h Not intercepted
- ; AX = 01h Intercepted
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX Return value only
- ; ===============================================================
- ;
-
- TIMER_Wait PROC
- STI ; ENABLE interrupts
- CALL _timer_status ; Set AL status return
- JC _wait_exit ; Not intercepted
- _Wait:
- CMP Timer_Counter, 0
- NOP
- JNE _Wait
- CLC ; Restored flag
- _wait_exit:
- RET
- TIMER_Wait ENDP
-
- ; ===============================================================
-
- TIMERP_Wait PROC
- STI ; ENABLE interrupts
- CALL _timerp_status ; Set AL status return
- JC _waitp_exit ; Not intercepted
- _Waitp:
- CMP Timer_Ports_Counter[BX], 0
- NOP
- JNE _Waitp
- CLC ; Restored flag
- _waitp_exit:
- RET
- TIMERP_Wait ENDP
- ; ===============================================================
-
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
- ; INCLUDE KEYBK.ASM ; The Ctrl-Break services
- ;*******************************************************************
- ;
- ; KEYBK.ASM XCOMMS kernal Ctrl-Break handler
- ;
- ; (C) Copyright 19896 SOuth Mountain Software Inc.
- ; All Rights Reserved
- ;
- ; All of the procedures are extended, miscellaneous services that
- ; have no equivalent defined in PC BIOS.
- ;
- ; KEYBK
- ;
- ; The KEYBK component chains into the 1Bh Ctrl-Break request.
- ; If a check for Ctrl-Break occurs, any keystrokes queued or
- ; automatically thrown away.
- ;
- ; Revision 2.0 No changes required
-
- ;
- ; ===============================================================
- ; Local data
- ; ===============================================================
- ;
-
- Keyboard_State DW ? ; = 01h if intercepted
- Keybk_Old_Offset DD ? ; Old 1Ch interrupt address
- Keyboard_Break DW ? ; Ctrl-Break Flag
-
- ;
- ; ===============================================================
- ; Local procedures
- ; ===============================================================
- ;
- ; Keybk_Int Chain the 1Bh interrupt handler
- ;
- ; KEYBK_Entry Enter the keyboard break module
- ; KEYBK_Exit Exit the keyboard break module
- ; KEYBK_Status Return keyboard Break intercept status
- ; KEYBK_Link Link into Interrupt 1Bh chain (if not already)
- ; KEYBK_UnLink Remove Link into the 1Bh Ctrl-Break chain
- ; KEYBK_Test Test - return the current Ctrl-Break status
- ;
-
- ;
- ; ===============================================================
- ; Keybk_Int Chain the 1Bh interrupt handler
- ; ===============================================================
- ;
- ; Take the Ctrl-Break Interrupt (1Bh) and set a flag. Note that
- ; we must NOT chain to the previous handler - this would cause
- ; MS-DOS to abort.
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; None affected
- ; ===============================================================
- ;
-
- Keybk_Int PROC FAR ; New interrupt handler
- MOV CS:Keyboard_Break, 1
- IRET
- ; ***** JMP DWORD PTR CS:[Keybk_Old_Offset]
- Keybk_Int ENDP
-
- ;
- ; ===============================================================
- ; KEYBK_Entry Enter the keyboard break module
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; None affected
- ; ===============================================================
-
- KEYBK_Entry PROC NEAR
- MOV Keyboard_Break, 0 ; No break pressed
- MOV Keyboard_State, NATIVE ; Assume not intercepted
- RET
- KEYBK_Entry ENDP
-
-
- ;
- ; ===============================================================
- ; KEYBK_Exit Exit the keyboard break module
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; None affected
- ; ===============================================================
-
- KEYBK_Exit PROC NEAR
- CALL KEYBK_UnLink ; Restore if intercepted
- CLC
- RET
- KEYBK_Exit ENDP
-
- ;
- ; ===============================================================
- ; KEYBK_Status Return keyboard Break intercept status
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; AH = 1Bh Break interrupt number
- ; AL = 00h Status request
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX = 00h Not intercepted
- ; AX = 01h Intercepted
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX Return value only
- ; ===============================================================
-
- KEYBK_Status PROC
- MOV AX, Keyboard_State
- RET
- KEYBK_Status ENDP
-
- ;
- ; ===============================================================
- ; KEYBK_Link Link into Interrupt 1Bh chain (if not already)
- ; ===============================================================
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; AH = 1Bh KEYBK interrupt number
- ; AL = 01h Link request
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AL = 00h Successful - chained in
- ; CY = NC Successful - chained in
- ; - or -
- ; AL = FFh Error
- ; CY = C Error - already chained, request ignored
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX Return value only
- ; DX Vector handler offset address
- ; BX Vector handler offset address
- ; ===============================================================
- ;
-
- KEYBK_Link PROC NEAR
- CMP Keyboard_State, INTERCEPTED
- JE _KL_Error
-
- ; Save the current timer 1Ch vector handler address
-
- MOV Keyboard_Break, 0 ; NO Ctrl-Break pressed yet
- MOV AL, KEYBK
- MOV DX, SEG Keybk_Int
- MOV BX, OFFSET Keybk_Int
- swapvec
- MOV WORD PTR Keybk_Old_Offset, BX
- MOV WORD PTR Keybk_Old_Offset+2, DX
- MOV Keyboard_State, INTERCEPTED
- MOV AL, 00h
- CLC
- JMP SHORT _KL_Exit
- _KL_Error:
- MOV AL, 0FFh
- STC
- _KL_Exit:
- RET
- KEYBK_Link ENDP
-
-
- ;
- ; ===============================================================
- ; KEYBK_UnLink Remove Link into the 1Bh Ctrl-Break chain
- ; ===============================================================
- ;
- ; Link into the 1Bh keyboard interrupt chain ONLY IF the Keybk_Int
- ; routine isn't already linked in. Return the appropriate status.
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; AH = 1Bh Keyboard Break interrupt number
- ; AL = 02h UnLink request
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; CY = NC Successful - unchained out of 1Ch
- ; CY = C Error - not chained, request ignored
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX Set vector interface, scratch
- ; DS Vector handler new segment address
- ; DX Vector handler new offset address
- ; ===============================================================
- ;
-
- KEYBK_UnLink PROC NEAR
- CMP Keyboard_State, INTERCEPTED
- JNE _KU_Error
- MOV BX, WORD PTR Keybk_Old_Offset
- MOV DX, WORD PTR Keybk_Old_Offset+2
- MOV AL, KEYBK
- setvec
- MOV Keyboard_State, NATIVE
- MOV Keyboard_Break, 0
- MOV AL, 00h
- CLC
- JMP SHORT _KU_Exit
- _KU_Error:
- MOV AL, 0FFh
- STC
- _KU_Exit:
-
- RET
- KEYBK_UnLink ENDP
-
-
- ;
- ; ===============================================================
- ; KEYBK_Test Test - return the current Ctrl-Break status
- ; ===============================================================
- ;
- ; If keyboard interrupt is NOT taken over, then a 0 is always
- ; returned.
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DS Pointer to CS segment
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AX = 00h No
- ; AX = 01h Ctrl-Break pressed
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; AX Return value only
- ; ===============================================================
- ;
-
- KEYBK_Test PROC
- CLI
- MOV AX, Keyboard_Break
- MOV Keyboard_Break, 0
- STI
- CMP AX, 0
- RET
- KEYBK_Test ENDP
-
-
-
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
- ;*******************************************************************
-
-
-
- ;
- ; ===============================================================
- ; XCOMMS local kernal drivers
- ; ===============================================================
- ;
- ; XCOMMS_Entry Enter and initialize all XCOMMS Services
- ; XCOMMS_Exit Enter and initialize all XCOMMS Services
- ; XCOMMS_Status Return revision level of XCOMMS
-
- ;
- ; ===============================================================
- ; XCOMMS_Entry Enter and initialize all XCOMMS Services
- ; ===============================================================
- ;
- ; Using the <Entries> table of intra-segment offsets, call
- ; each of these procedures. The first routine called must be
- ; the BUFFR entry to reserve the buffer pool.
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; DX:BX Address of buffer pool
- ; CX Number of 1K buffers
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; SI Word index into <Entries> table
- ; ===============================================================
- ;
-
- XCOMMS_Entry PROC NEAR
- MOV XCOMMS_Buffer_Offset, BX
- MOV XCOMMS_Buffer_Segment, DX
- MOV XCOMMS_Buffer_Count, CX
- MOV SI, 0 ; Call everyone
- _XENTR_loop:
- CMP Entries[SI], LIST_END
- JE _XENTR_exit
- PUSH SI
- CALL Entries[SI] ; Call indirect
- POP SI
- ADD SI, 2
- JMP _XENTR_loop
- _XENTR_exit:
- MOV AX, 0
- CLC
- RET
-
- XCOMMS_Entry ENDP
-
- ;
- ; ===============================================================
- ; XCOMMS_Exit Enter and initialize all XCOMMS Services
- ; ===============================================================
- ;
- ; Using the <Exeunts> table of intra-segment offsets, call
- ; each of these procedures. This is assumed to be invoked only
- ; when XCOMMS is to end. It is possible for XCOMMS to continue
- ; - so the XCOMMS_Entry will be called automatically.
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; AX = 0001h Entered via the XCOMMS vector
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; Not applicable
- ;
- ; Registers used Description
- ; -------------- ---------------------------
- ; BX Word index into <Exeunt> table
- ; ===============================================================
- ;
-
- XCOMMS_Exit PROC NEAR
- MOV BX, 0 ; Call everyone
- _XEXIT_loop:
- CMP Exeunts[BX], LIST_END
- JE _XEXIT_exit
- PUSH BX
- CALL Exeunts[BX] ; Call indirect
- POP BX
- ADD BX, 2
- JMP _XEXIT_loop
- _XEXIT_exit:
- ;; MOV BX, XCOMMS_Buffer_Offset
- ;; MOV DX, XCOMMS_Buffer_Segment
- ;; MOV CX, XCOMMS_Buffer_Count
- ;; CALL XCOMMS_Entry
- MOV AX, 0
- CLC
- RET
-
- XCOMMS_Exit ENDP
-
-
- ;
- ; ===============================================================
- ; XCOMMS_Status Return revision level of XCOMMS
- ; ===============================================================
- ;
- ;
- ; Input Description
- ; -------------- ---------------------------
- ; AX = 0000h
- ;
- ; Output Description
- ; -------------- ---------------------------
- ; AH Revision major level (binary)
- ; AL Revision minor level (binary)
- ; BX Number of buffers allocated
- ; CX Number of buffers available for use (in pool)
- ;
- ; ===============================================================
- ;
- XCOMMS_Status PROC NEAR
- MOV AH, REV_MAJOR
- MOV AL, REV_MINOR
- CALL BUFFR_Status
- RET
- XCOMMS_Status ENDP
-
- ;
- ; ===============================================================
- ; XCOMMS kernal dispatch interrupt handler
- ; ===============================================================
- ;
-
- ;
- ; ===============================================================
- ; XCOMMS Take the XCOMMS kernal interrupt
- ; ===============================================================
- ;
- ; Using the AH,AL 16-bit XCOMMS request code, dispatch to the
- ; requested service routine. Since all general purpose registers
- ; (AX, BX, CX, DX, SI, DI, BP) must be maintained in the
- ; interface, an indirect call is performed by placing the addres
- ; of the XCOMMS service routine on the stack. An XCOMMS routine
- ; will simply perform a NEAR RET to return back to XCOMMS_Int.
- ;
- ; Note - "XCOMMS Service" refers to the routine defined
- ; in XCOMMS for a given intercepted action.
- ;
- ; XCOMMS Service Description
- ; -------------- ---------------------------
- ; AX,BX,CX,DX User defined
- ; SI,DI,BP User defined
- ; CS,DS,ES XCOMMS resident code segment
- ; SP,SS User defined
- ;
-
- XCOMMS PROC NEAR ; *** Should be FAR ***
- JMP SHORT _XI_skip
- DW XCOMMS_ID
- _XI_skip:
- STI ; ENABLE INTERRUPTS
- PUSH DS ; Save often used seg regs
- PUSH ES
- PUSH CS
- PUSH CS
- POP ES
- POP DS
- PUSH BP
- MOV BP, SP
-
- PUSH CX ; Look for the AH,AL code
- PUSH DI
- MOV DI, OFFSET Service
- MOV CX, No_Serv
- PUSH CX
- REPNZ SCASW
- POP DI
- JNZ _XI_error
- SUB DI, CX
- DEC DI
- SHL DI, 1
- MOV DI, Routine[DI]
-
- ; |----------|
- ; | user DS |
- ; |----------|
- ; | user ES |
- ; |----------|
- ; | user BP |<-- BP
- ; |----------|----------|
- ; | user CX |_XI_return| [BP-2]
- ; |----------|----------|
- ; | user DI | service | [BP-4] <-- SP
- ; |----------|----------|
-
- MOV CX, OFFSET _XI_return
- XCHG CX, [BP-2]
- XCHG DI, [BP-4]
- RET ; *** NEAR *** Call
- _XI_return:
- JMP SHORT _XI_exit
- _XI_error:
- POP DI
- POP CX
- _XI_exit:
- POP BP
- POP ES
- POP DS
- IRET ; Not chained!
- XCOMMS ENDP
-
- IFDEF BUNDLD
- modend XCOMMS
- ELSE
- CSEG ENDS
- ENDIF
- END
-