home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 050 / pibasync.arc / ASYINT.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-10-31  |  13.0 KB  |  313 lines

  1.          STI                                ;Allow interrupts
  2. ;
  3.          PUSH    AX                         ;Save registers
  4.          PUSH    BX
  5.          PUSH    CX
  6.          PUSH    DX
  7.          PUSH    DS
  8.          PUSH    SI
  9.          PUSH    ES
  10.          PUSH    DI
  11. ;
  12. ;  Get data segment for addressing global variables
  13. ;
  14.     CS:  MOV     DS,[>Async_DSeg_Save]
  15. ;
  16. ;  Begin major polling loop over pending interrupts.
  17. ;
  18. ;  The polling loop is needed because the 8259 cannot handle another 8250
  19. ;  interrupt while we service this interrupt.  We keep polling here as long
  20. ;  as an interrupt is received.
  21. ;
  22. Poll:    MOV     DX,[>Async_Uart_IIR]       ;Get Interrupt ident register
  23.          IN      AL,DX                      ;Pick up interrupt type
  24. ;
  25.          TEST    AL,1                       ;See if any interrupt signalled.
  26.          JZ      Polla                      ;Yes --- continue
  27.          JMP     NEAR Back                  ;No  ---  return to invoker
  28. ;
  29. ;  Determine type of interrupt.
  30. ;  Possibilities:
  31. ;
  32. ;     0 = Modem status changed
  33. ;     2 = Transmit hold register empty (write char)
  34. ;     4 = Character received from port
  35. ;     6 = Line status changed
  36. ;
  37. Polla:   AND     AL,6                       ;Strip unwanted bits from interrupt type
  38.          CMP     AL,4                       ;Check if interrupt >= 4
  39.          JE      Pollb                      ;
  40.          JMP     NEAR Int2
  41. ;
  42. ;  Write interrupts must be turned on if a higher-priority interrupt
  43. ;  has been received, else the characters may not be sent (and a lockup
  44. ;  may occur).
  45. ;
  46. Pollb:   PUSH    AX                         ;Save interrupt type
  47.          CALL    EnabWI                     ;Enable write interrupts
  48.          POP     AX                         ;Restore interrupt type
  49. ;
  50. ;  --- Received a character ----
  51. ;
  52. Int4:    CMP     AL,4                       ;Check for received char interrupt
  53.          JE      Int4a                      ;Yes -- process it.
  54.          JMP     NEAR Int2                  ;No -- skip.
  55. ;
  56. ;  Read the character from the serial port.
  57. ;
  58. Int4a:   MOV     DX,[>Async_Base]           ;Read character from port
  59.          IN      AL,DX
  60. ;
  61. ;  Check if XON/XOFF honored.  If so, check if incoming character is
  62. ;  an XON or an XOFF.
  63. ;
  64.          TEST    BYTE [<Async_Do_XonXoff],1 ;See if we honor XON/XOFF
  65.          JZ      Int4d                      ;No -- skip XON/XOFF checks
  66. ;
  67.          CMP     AL,<XON                    ;See if XON found
  68.          JE      Int4b                      ;Skip if XON found
  69.          CMP     AL,<XOFF                   ;See if XOFF found
  70.          JNE     Int4d                      ;Skip if XOFF not found
  71. ;
  72. ;  XOFF received -- set flag indicating sending of chars isn't possible
  73. ;
  74.          MOV     BYTE [<Async_XOFF_Received],1    ;Turn on received XOFF flag
  75.          MOV     BYTE [<Async_XOFF_Rec_Display],1 ;Turn on display flag
  76.          JMP     NEAR Poll
  77. ;
  78. ;  XON received -- allow more characters to be sent.
  79. ;
  80. Int4b:   MOV     BYTE [<Async_XOFF_Received],0   ;Turn off received XOFF flag
  81.          MOV     BYTE [<Async_XON_Rec_Display],1 ;Turn on display flag
  82. ;
  83.          CALL    EnabWI                     ;Enable write interrupts
  84.          JMP     NEAR Int4z
  85. ;
  86. ;  Not XON/XOFF -- handle other character.
  87. ;
  88. Int4d:   TEST    BYTE [>Async_Line_Status],2 ;Check for buffer overrun
  89.          JNZ     Int4z                      ;Yes --- don't store anything
  90. ;
  91.          MOV     BX,[>Async_Buffer_Head]    ;Current position in input buffer
  92.          LES     DI,[>Async_Buffer_Ptr]     ;Pick up buffer address
  93.          ADD     DI,BX                      ;Update position
  94.      ES: MOV     [DI],AL                    ;Store received character in buffer
  95.          INC     WORD [>Async_Buffer_Used]  ;Increment count of chars in buffer
  96. ;
  97.          MOV     AX,[>Async_Buffer_Used]    ;Pick up buffer usage count
  98.          CMP     AX,[>Async_MaxBufferUsed]  ;See if greater usage than ever before
  99.          JLE     Int4f                      ;Skip if not
  100.          MOV     [>Async_MaxBufferUsed],AX  ;This is greatest use thus far
  101. ;
  102. Int4f:   INC     BX                         ;Increment buffer pointer
  103.          CMP     BX,[>Async_Buffer_Size]    ;Check if past end of buffer
  104.          JLE     Int4h
  105.          XOR     BX,BX                      ;If so, wrap around to front
  106. ;
  107. Int4h:   CMP     WORD [>Async_Buffer_Tail],BX ;Check for overflow
  108.          JE      Int4s                      ;Jump if head ran into tail
  109. ;
  110.          MOV     [>Async_Buffer_Head],BX    ;Update head pointer
  111. ;
  112. ;  If XON/XOFF available, and buffer getting full, set up to send
  113. ;  XOFF to remote system.
  114. ;
  115. ;  This happens in two possible stages:
  116. ;
  117. ;     (1)  An XOFF is sent right when the buffer becomes 'Async_Buffer_High'
  118. ;          characters full.
  119. ;
  120. ;     (2)  A second XOFF is sent right when the buffer becomes
  121. ;          'Async_Buffer_High_2' characters full;  this case is likely the
  122. ;          result of the remote not having seen our XOFF because it was
  123. ;          lost in transmission.
  124. ;
  125.          TEST    BYTE [<Async_Do_XonXoff],1 ;See if we honor XON/XOFF
  126.          JZ      Int4z                      ;No -- skip XON/XOFF checks
  127. ;
  128. ;  Check against first high-water mark.
  129. ;
  130.          CMP     AX,[>Async_Buffer_High]    ;AX still has Async_Buffer_Used
  131.          JL      Int4z                      ;Not very full, so keep going.
  132. ;
  133. ;  Check if we've already sent XOFF.
  134. ;
  135.          TEST    BYTE [<Async_XOFF_Sent],1  ;Remember if we sent XOFF or not
  136.          JZ      Int4j                      ;No -- go send it now.
  137. ;
  138. ;  Check against second high-water mark.
  139. ;  If we are right at it, send an XOFF regardless of whether we've
  140. ;  already sent one or not.  (Perhaps the first got lost.)
  141. ;
  142.          CMP     AX,[>Async_Buffer_High_2]
  143.          JNE     Int4z                      ;Not at 2nd mark -- skip
  144. ;
  145. Int4j:   MOV     BYTE [<Async_Send_XOFF],1  ;Indicate we need to send XOFF
  146.          CALL    EnabWI                     ;Ensure write interrupts enabled
  147.          JMP     NEAR Poll                  ;
  148. ;
  149. ;  If we come here, then the input buffer has overflowed.
  150. ;  Characters will be thrown away until the buffer empties at least one slot.
  151. ;
  152. Int4s:   OR      BYTE PTR [>Async_Line_Status],2 ;Flag overrun
  153. ;
  154. Int4z:   JMP     NEAR Poll
  155. ;
  156. ;  --- Write a character ---
  157. ;
  158. Int2:    CMP     AL,2                       ;Check for THRE interrupt
  159.          JE      Int2a                      ;Yes -- process it.
  160.          JMP     NEAR Int6                  ;No -- skip.
  161. ;
  162. ;  Check first if we need to send an XOFF to remote system.
  163. ;
  164. Int2a:   TEST    BYTE [<Async_Send_Xoff],1  ;See if we are sending XOFF
  165.          JZ      Int2d                      ;No -- skip it
  166. ;
  167. ;  Yes, we are to send XOFF to remote.
  168. ;
  169. ;  First, check DSR and CTS as requested.
  170. ;  If those status lines aren't ready, turn off write interrupts and
  171. ;  try later, after a line status change.
  172. ;
  173.          TEST    BYTE [<Async_Do_DSR],1     ;See if DSR checking required
  174.          JZ      Int2b                      ;No -- skip it
  175. ;
  176.          MOV     DX,[>Async_Uart_MSR]       ;Get modem status register
  177.          IN      AL,DX
  178.          TEST    AL,<Async_DSR              ;Check for Data Set Ready
  179.          JZ      Int2e                      ;If not DSR, turn off write interrupts
  180. ;
  181. Int2b:   TEST    BYTE [<Async_Do_CTS],1     ;See if CTS checking required
  182.          JZ      Int2c                      ;No -- skip it
  183. ;
  184.          MOV     DX,[>Async_Uart_MSR]       ;Get modem status register
  185.          IN      AL,DX
  186.          TEST    AL,<Async_CTS              ;Check for Clear To Send
  187.          JZ      Int2e                      ;If not CTS, turn off write ints
  188. ;
  189. ;  All status lines look OK.
  190. ;  Send the XOFF.
  191. ;
  192. Int2c:   MOV     AL,<XOFF                   ;Get XOFF Character
  193.          MOV     DX,[>Async_Base]           ;Get transmit hold register address
  194.          OUT     DX,AL                      ;Output the XOFF
  195.          MOV     BYTE [<Async_Send_XOFF],0  ;Turn off send XOFF flag
  196.          MOV     BYTE [<Async_XOFF_Sent],1  ;Turn on sent XOFF flag
  197.          JMP     NEAR Poll                  ;Return
  198. ;
  199. ;  Not sending XOFF -- see if any character in buffer to be sent.
  200. ;
  201. Int2d:   MOV     BX,[>Async_OBuffer_Tail]   ;Pick up output buffer pointers
  202.          CMP     BX,[>Async_OBuffer_Head]
  203.          JNE     Int2m                      ;Skip if not equal --> something to send
  204. ;
  205. ;  If nothing to send, turn off write interrupts to avoid unnecessary
  206. ;  time spent handling useless THRE interrupts.
  207. ;
  208. Int2e:   MOV     DX,[>Async_Uart_IER]       ;If nothing -- or can't -- send ...
  209.          IN      AL,DX                      ;
  210.          AND     AL,$FD                     ;
  211.          OUT     DX,AL                      ;... disable write interrupts
  212.          JMP     NEAR Poll                  ;
  213. ;
  214. ;  If something to send, ensure that remote system didn't send us XOFF.
  215. ;  If it did, we can't send anything, so turn off write interrupts and
  216. ;  wait for later (after an XON has been received).
  217. ;
  218. Int2m:   TEST    BYTE [<Async_XOFF_Received],1 ;See if we received XOFF
  219.          JNZ     Int2e                      ;Yes -- can't send anything now
  220. ;
  221. ;  If we can send character, check DSR and CTS as requested.
  222. ;  If those status lines aren't ready, turn off write interrupts and
  223. ;  try later, after a line status change.
  224. ;
  225.          MOV     DX,[>Async_Uart_MSR]       ;Otherwise get modem status
  226.          IN      AL,DX
  227.          MOV     [>Async_Modem_Status],AL   ;and save modem status for later
  228. ;
  229.          TEST    BYTE [<Async_Do_DSR],1     ;See if DSR checking required
  230.          JZ      Int2n                      ;No -- skip it
  231. ;
  232.          TEST    AL,<Async_DSR              ;Check for Data Set Ready
  233.          JZ      Int2e                      ;If not DSR, turn off write ints
  234. ;
  235. Int2n:   TEST    BYTE [<Async_Do_CTS],1     ;See if CTS checking required
  236.          JZ      Int2o                      ;No -- skip it
  237. ;
  238.          TEST    AL,<Async_CTS              ;Check for Clear To Send
  239.          JZ      Int2e                      ;If not CTS, turn off write ints
  240. ;
  241. ;  Everything looks OK for sending, so send the character.
  242. ;
  243. Int2o:   LES     DI,[>Async_OBuffer_Ptr]    ;Get output buffer pointer
  244.          ADD     DI,BX                      ;Position to character to output
  245.      ES: MOV     AL,[DI]                    ;Get character to output
  246.          MOV     DX,[>Async_Base]           ;Get transmit hold register address
  247.          OUT     DX,AL                      ;Output the character
  248. ;
  249.          DEC     WORD [>Async_OBuffer_Used] ;Decrement count of chars in buffer
  250.          INC     BX                         ;Increment tail pointer
  251.          CMP     BX,[>Async_OBuffer_Size]   ;See if past end of buffer
  252.          JLE     Int2z
  253.          XOR     BX,BX                      ;If so, wrap to front
  254. ;
  255. Int2z:   MOV     [>Async_OBuffer_Tail],BX   ;Store updated buffer tail
  256.          JMP     NEAR Poll
  257. ;
  258. ;  --- Line status change ---
  259. ;
  260. Int6:    CMP     AL,6                       ;Check for line status interrupt
  261.          JNE     Int0                       ;No -- skip.
  262. ;
  263.          MOV     DX,[>Async_Uart_LSR]       ;Yes -- pick up line status register
  264.          IN      AL,DX                      ;and its contents
  265.          AND     AL,$1E                     ;Strip unwanted bits
  266.          MOV     [>Async_Line_Status],AL    ;Store for future reference
  267.          OR      [>Async_Line_Error_Flags],AL ;Add to any past transgressions
  268.          JMP     NEAR Poll
  269. ;
  270. ;  --- Modem status change ---
  271. ;
  272. Int0:    CMP     AL,0                       ;Check for modem status change
  273.          JE      Int0a                      ;Yes -- handle it
  274.          JMP     NEAR Poll                  ;Else get next interrupt
  275. ;
  276. Int0a:   MOV     DX,[>Async_Uart_MSR]       ;Pick up modem status reg. address
  277.          IN      AL,DX                      ;and its contents
  278.          MOV     [>Async_Modem_Status],AL   ;Store for future reference
  279.          CALL    EnabWI                     ;Turn on write interrupts, in case
  280. ;                                           ;status change resulted from CTS/DSR
  281. ;                                           ;changing state.
  282.          JMP     NEAR Poll
  283. ;
  284. ;  Internal subroutine to enable write interrupts.
  285. ;
  286. EnabWI: ;PROC    NEAR
  287.          MOV     DX,[>Async_Uart_IER]       ;Get interrupt enable register
  288.          IN      AL,DX                      ;Check contents of IER
  289.          TEST    AL,2                       ;See if write interrupt enabled
  290.          JNZ     EnabRet                    ;Skip if so
  291.          OR      AL,2                       ;Else enable write interrupts ...
  292.          OUT     DX,AL                      ;... by rewriting IER contents
  293. EnabRet: RET                                ;Return to caller
  294. ;
  295. ;  Send non-specific EOI to 8259 controller.
  296. ;
  297. Back:    MOV     AL,$20                     ;EOI = $20
  298.          OUT     $20,AL
  299. ;
  300. ;  Restore registers
  301. ;
  302.          POP     DI
  303.          POP     ES
  304.          POP     SI
  305.          POP     DS
  306.          POP     DX
  307.          POP     CX
  308.          POP     BX
  309.          POP     AX
  310.          MOV     SP,BP
  311.          POP     BP
  312.          IRET
  313.