home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
progm
/
pibasy.zip
/
ASYINT.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-11-11
|
13KB
|
286 lines
STI ;Allow interrupts
;
; Begin major polling loop over pending interrupts.
;
; The polling loop is needed because the 8259 cannot handle another 8250
; interrupt while we service this interrupt. We keep polling here as long
; as an interrupt is received.
;
Poll: MOV DX,[>Async_Uart_IIR] ;Get Interrupt ident register
IN AL,DX ;Pick up interrupt type
;
TEST AL,1 ;See if any interrupt signalled.
JZ Polla ;Yes --- continue
JMP NEAR Back ;No --- return to invoker
;
; Determine type of interrupt.
; Possibilities:
;
; 0 = Modem status changed
; 2 = Transmit hold register empty (write char)
; 4 = Character received from port
; 6 = Line status changed
;
Polla: AND AL,6 ;Strip unwanted bits from interrupt type
CMP AL,4 ;Check if interrupt >= 4
JE Pollb ;
JMP NEAR Int2
;
; Write interrupts must be turned on if a higher-priority interrupt
; has been received, else the characters may not be sent (and a lockup
; may occur).
;
Pollb: PUSH AX ;Save interrupt type
CALL EnabWI ;Enable write interrupts
POP AX ;Restore interrupt type
;
; --- Received a character ----
;
Int4: CMP AL,4 ;Check for received char interrupt
JE Int4a ;Yes -- process it.
JMP NEAR Int2 ;No -- skip.
;
; Read the character from the serial port.
;
Int4a: MOV DX,[>Async_Base] ;Read character from port
IN AL,DX
;
; Check if XON/XOFF honored. If so, check if incoming character is
; an XON or an XOFF.
;
TEST BYTE [<Async_Do_XonXoff],1 ;See if we honor XON/XOFF
JZ Int4d ;No -- skip XON/XOFF checks
;
CMP AL,<XON ;See if XON found
JE Int4b ;Skip if XON found
CMP AL,<XOFF ;See if XOFF found
JNE Int4d ;Skip if XOFF not found
;
; XOFF received -- set flag indicating sending of chars isn't possible
;
MOV BYTE [<Async_XOFF_Received],1 ;Turn on received XOFF flag
MOV BYTE [<Async_XOFF_Rec_Display],1 ;Turn on display flag
JMP NEAR Poll
;
; XON received -- allow more characters to be sent.
;
Int4b: MOV BYTE [<Async_XOFF_Received],0 ;Turn off received XOFF flag
MOV BYTE [<Async_XON_Rec_Display],1 ;Turn on display flag
;
CALL EnabWI ;Enable write interrupts
JMP NEAR Int4z
;
; Not XON/XOFF -- handle other character.
;
Int4d: TEST BYTE [>Async_Line_Status],2 ;Check for buffer overrun
JNZ Int4z ;Yes --- don't store anything
;
MOV BX,[>Async_Buffer_Head] ;Current position in input buffer
LES DI,[>Async_Buffer_Ptr] ;Pick up buffer address
ADD DI,BX ;Update position
ES: MOV [DI],AL ;Store received character in buffer
INC WORD [>Async_Buffer_Used] ;Increment count of chars in buffer
;
MOV AX,[>Async_Buffer_Used] ;Pick up buffer usage count
CMP AX,[>Async_MaxBufferUsed] ;See if greater usage than ever before
JLE Int4f ;Skip if not
MOV [>Async_MaxBufferUsed],AX ;This is greatest use thus far
;
Int4f: INC BX ;Increment buffer pointer
CMP BX,[>Async_Buffer_Size] ;Check if past end of buffer
JLE Int4h
XOR BX,BX ;If so, wrap around to front
;
Int4h: CMP WORD [>Async_Buffer_Tail],BX ;Check for overflow
JE Int4s ;Jump if head ran into tail
;
MOV [>Async_Buffer_Head],BX ;Update head pointer
;
; If XON/XOFF available, and buffer getting full, set up to send
; XOFF to remote system.
;
; This happens in two possible stages:
;
; (1) An XOFF is sent right when the buffer becomes 'Async_Buffer_High'
; characters full.
;
; (2) A second XOFF is sent right when the buffer becomes
; 'Async_Buffer_High_2' characters full; this case is likely the
; result of the remote not having seen our XOFF because it was
; lost in transmission.
;
TEST BYTE [<Async_Do_XonXoff],1 ;See if we honor XON/XOFF
JZ Int4z ;No -- skip XON/XOFF checks
;
; Check against first high-water mark.
;
CMP AX,[>Async_Buffer_High] ;AX still has Async_Buffer_Used
JL Int4z ;Not very full, so keep going.
;
; Check if we've already sent XOFF.
;
TEST BYTE [<Async_XOFF_Sent],1 ;Remember if we sent XOFF or not
JZ Int4j ;No -- go send it now.
;
; Check against second high-water mark.
; If we are right at it, send an XOFF regardless of whether we've
; already sent one or not. (Perhaps the first got lost.)
;
CMP AX,[>Async_Buffer_High_2]
JNE Int4z ;Not at 2nd mark -- skip
;
Int4j: MOV BYTE [<Async_Send_XOFF],1 ;Indicate we need to send XOFF
CALL EnabWI ;Ensure write interrupts enabled
JMP NEAR Poll ;
;
; If we come here, then the input buffer has overflowed.
; Characters will be thrown away until the buffer empties at least one slot.
;
Int4s: OR BYTE PTR [>Async_Line_Status],2 ;Flag overrun
;
Int4z: JMP NEAR Poll
;
; --- Write a character ---
;
Int2: CMP AL,2 ;Check for THRE interrupt
JE Int2a ;Yes -- process it.
JMP NEAR Int6 ;No -- skip.
;
; Check first if we need to send an XOFF to remote system.
;
Int2a: TEST BYTE [<Async_Send_Xoff],1 ;See if we are sending XOFF
JZ Int2d ;No -- skip it
;
; Yes, we are to send XOFF to remote.
;
; First, check DSR and CTS as requested.
; If those status lines aren't ready, turn off write interrupts and
; try later, after a line status change.
;
TEST BYTE [<Async_Do_DSR],1 ;See if DSR checking required
JZ Int2b ;No -- skip it
;
MOV DX,[>Async_Uart_MSR] ;Get modem status register
IN AL,DX
TEST AL,<Async_DSR ;Check for Data Set Ready
JZ Int2e ;If not DSR, turn off write interrupts
;
Int2b: TEST BYTE [<Async_Do_CTS],1 ;See if CTS checking required
JZ Int2c ;No -- skip it
;
MOV DX,[>Async_Uart_MSR] ;Get modem status register
IN AL,DX
TEST AL,<Async_CTS ;Check for Clear To Send
JZ Int2e ;If not CTS, turn off write ints
;
; All status lines look OK.
; Send the XOFF.
;
Int2c: MOV AL,<XOFF ;Get XOFF Character
MOV DX,[>Async_Base] ;Get transmit hold register address
OUT DX,AL ;Output the XOFF
MOV BYTE [<Async_Send_XOFF],0 ;Turn off send XOFF flag
MOV BYTE [<Async_XOFF_Sent],1 ;Turn on sent XOFF flag
JMP NEAR Poll ;Return
;
; Not sending XOFF -- see if any character in buffer to be sent.
;
Int2d: MOV BX,[>Async_OBuffer_Tail] ;Pick up output buffer pointers
CMP BX,[>Async_OBuffer_Head]
JNE Int2m ;Skip if not equal --> something to send
;
; If nothing to send, turn off write interrupts to avoid unnecessary
; time spent handling useless THRE interrupts.
;
Int2e: MOV DX,[>Async_Uart_IER] ;If nothing -- or can't -- send ...
IN AL,DX ;
AND AL,$FD ;
OUT DX,AL ;... disable write interrupts
JMP NEAR Poll ;
;
; If something to send, ensure that remote system didn't send us XOFF.
; If it did, we can't send anything, so turn off write interrupts and
; wait for later (after an XON has been received).
;
Int2m: TEST BYTE [<Async_XOFF_Received],1 ;See if we received XOFF
JNZ Int2e ;Yes -- can't send anything now
;
; If we can send character, check DSR and CTS as requested.
; If those status lines aren't ready, turn off write interrupts and
; try later, after a line status change.
;
MOV DX,[>Async_Uart_MSR] ;Otherwise get modem status
IN AL,DX
MOV [>Async_Modem_Status],AL ;and save modem status for later
;
TEST BYTE [<Async_Do_DSR],1 ;See if DSR checking required
JZ Int2n ;No -- skip it
;
TEST AL,<Async_DSR ;Check for Data Set Ready
JZ Int2e ;If not DSR, turn off write ints
;
Int2n: TEST BYTE [<Async_Do_CTS],1 ;See if CTS checking required
JZ Int2o ;No -- skip it
;
TEST AL,<Async_CTS ;Check for Clear To Send
JZ Int2e ;If not CTS, turn off write ints
;
; Everything looks OK for sending, so send the character.
;
Int2o: LES DI,[>Async_OBuffer_Ptr] ;Get output buffer pointer
ADD DI,BX ;Position to character to output
ES: MOV AL,[DI] ;Get character to output
MOV DX,[>Async_Base] ;Get transmit hold register address
OUT DX,AL ;Output the character
;
DEC WORD [>Async_OBuffer_Used] ;Decrement count of chars in buffer
INC BX ;Increment tail pointer
CMP BX,[>Async_OBuffer_Size] ;See if past end of buffer
JLE Int2z
XOR BX,BX ;If so, wrap to front
;
Int2z: MOV [>Async_OBuffer_Tail],BX ;Store updated buffer tail
JMP NEAR Poll
;
; --- Line status change ---
;
Int6: CMP AL,6 ;Check for line status interrupt
JNE Int0 ;No -- skip.
;
MOV DX,[>Async_Uart_LSR] ;Yes -- pick up line status register
IN AL,DX ;and its contents
AND AL,$1E ;Strip unwanted bits
MOV [>Async_Line_Status],AL ;Store for future reference
OR [>Async_Line_Error_Flags],AL ;Add to any past transgressions
JMP NEAR Poll
;
; --- Modem status change ---
;
Int0: CMP AL,0 ;Check for modem status change
JE Int0a ;Yes -- handle it
JMP NEAR Poll ;Else get next interrupt
;
Int0a: MOV DX,[>Async_Uart_MSR] ;Pick up modem status reg. address
IN AL,DX ;and its contents
MOV [>Async_Modem_Status],AL ;Store for future reference
CALL EnabWI ;Turn on write interrupts, in case
; ;status change resulted from CTS/DSR
; ;changing state.
JMP NEAR Poll
;
; Internal subroutine to enable write interrupts.
;
EnabWI: ;PROC NEAR
MOV DX,[>Async_Uart_IER] ;Get interrupt enable register
IN AL,DX ;Check contents of IER
TEST AL,2 ;See if write interrupt enabled
JNZ EnabRet ;Skip if so
OR AL,2 ;Else enable write interrupts ...
OUT DX,AL ;... by rewriting IER contents
EnabRet: RET ;Return to caller
;
; Send non-specific EOI to 8259 controller.
;
Back: MOV AL,$20 ;EOI = $20
OUT $20,AL