Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1539 lines
36 KiB

  1. page,132
  2. ;---------------------------Module-Header-------------------------------
  3. ; Module Name: IBMINT.ASM
  4. ;
  5. ; Created: Fri 06-Feb-1987 10:45:12
  6. ; Author: Walt Moore [waltm]
  7. ;
  8. ; Copyright (c) Microsoft Corporation 1985-1990. All Rights Reserved
  9. ;
  10. ; General Description:
  11. ; This file contains the interrupt time routines for the
  12. ; IBM Windows communications driver.
  13. ;
  14. ; The interrupt code is preloaded and fixed.
  15. ;
  16. ; History:
  17. ;
  18. ; **********************************************************************
  19. ; Tue Dec 19 1989 09:35:15 -by- Amit Chatterjee [amitc]
  20. ; ----------------------------------------------------------------------
  21. ; Added a far entry point 'FakeCOMIntFar' so that the routine 'FakeCOMInt'
  22. ; could be called from the 'InitAPort' routine in IBMCOM.ASM
  23. ;
  24. ; 26.Nov.90 richp
  25. ;
  26. ; Changed interrupt routines to use new VPICD services for bi-modal/multi-
  27. ; modal interrupt handling. They now work in straight real mode for real
  28. ; mode Windows, but can also handle interrupts in real mode or protected
  29. ; mode for standard mode Windows, and handle interrupts in RING 0 protected
  30. ; mode for enhanced mode Windows, even when the Windows VM is not currently
  31. ; executing.
  32. ;
  33. ; sudeepb 10-Jan-1993 changed the costly cli/sti with non-trapping
  34. ; FCLI/FSTI macros
  35. ;-----------------------------------------------------------------------;
  36. subttl Communications Hardware Interrupt Service Routines
  37. .xlist
  38. include cmacros.inc
  39. include comdev.inc
  40. include ibmcom.inc
  41. include ins8250.inc
  42. include BIMODINT.INC
  43. include vint.inc
  44. .list
  45. externFP GetSystemMsecCount
  46. externW COMptrs
  47. externW activeCOMs
  48. externD lpPostMessage
  49. ifdef NEC_98
  50. externFP Comm4 ;Ins 940923 KBNES
  51. endif ; NEC_98
  52. sBegin Data
  53. PUBLIC IRQhooks
  54. IRQhooks label byte
  55. DefineIRQhook MACRO num
  56. IFDEF No_DOSX_Bimodal_Services
  57. IRQhook&num IRQ_Hook_Struc <,,,,IntCodeOFFSET DEF_COM_INT_&num,,,, \
  58. IntCodeOFFSET DEF_RM_COM_INT_&num>
  59. ELSE
  60. IRQhook&num IRQ_Hook_Struc <,,,,IntCodeOFFSET DEF_COM_INT_&num>
  61. ENDIF
  62. ENDM
  63. ??portnum = 1
  64. REPT MAXCOM+1
  65. DefineIRQhook %??portnum
  66. ??portnum = ??portnum+1
  67. ENDM
  68. PURGE DefineIRQhook
  69. EXTRN VCD_int_callback:fword
  70. sEnd data
  71. createSeg _INTERRUPT,IntCode,word,public,CODE
  72. sBegin IntCode
  73. assumes cs,IntCode
  74. page
  75. IFDEF No_DOSX_Bimodal_Services
  76. public RM_IntDataSeg
  77. RM_IntDataSeg dw 0
  78. ; this variable is written into by a routine in inicom
  79. ; if the 286 DOS extender is present. This variable
  80. ; contains the SEGMENT value of the data selector "_DATA"
  81. ; so that the real mode interrupt handler may use the
  82. ; data segment, and not it's selector !
  83. PUBLIC RM_CallBack
  84. RM_CallBack dd 0
  85. ENDIF
  86. Control proc far
  87. ret
  88. Control endp
  89. IFDEF No_DOSX_Bimodal_Services
  90. DEF_RM_Handler proc far
  91. push es
  92. push di
  93. push ax
  94. mov es, cs:[RM_IntDataSeg]
  95. mov di, es:[di.First_DEB] ; ES:DI -> ComDEB
  96. add di, SIZE ComDEB ; ES:DI -> BIS
  97. mov es:[di.BIS_Mode], 4
  98. push cs
  99. call NEAR PTR COMHandler
  100. mov es:[di.BIS_Mode], 0
  101. pop ax
  102. pop di ; ES:DI -> IRQ_Hook_Struc
  103. ifndef NEC_98
  104. jc short DEF_RM_chain
  105. endif ; NEC_98
  106. pop es
  107. pop di
  108. add sp, 4
  109. iret
  110. DEF_RM_chain:
  111. call DOCLI
  112. push bp
  113. mov bp, sp ;stack frame:
  114. ; bp+8 -> OldInt CS
  115. ; bp+6 -> OldInt IP
  116. ; bp+4 -> di
  117. ; bp+2 -> es
  118. ; bp+0 -> bp
  119. les di, es:[di.RM_OldIntVec]
  120. mov [bp+6], di
  121. mov [bp+8], es
  122. pop bp
  123. pop es
  124. pop di
  125. ret ; far ret to OldInt handler
  126. DEF_RM_Handler endp
  127. ENDIF ;No_DOSX_Bimodal_Services
  128. Define_DEF_COM_INT MACRO num
  129. IFDEF No_DOSX_Bimodal_Services
  130. PUBLIC DEF_RM_COM_INT_&num
  131. DEF_RM_COM_INT_&num proc far
  132. sub sp, 4
  133. push di
  134. mov di, DataOFFSET IRQhook&num
  135. jmp DEF_RM_Handler
  136. DEF_RM_COM_INT_&num endp
  137. ENDIF
  138. PUBLIC DEF_COM_INT_&num
  139. DEF_COM_INT_&num proc far
  140. sub sp, 4
  141. push di
  142. mov di, DataOFFSET IRQhook&num
  143. jmp DEF_Handler
  144. DEF_COM_INT_&num endp
  145. ENDM
  146. ??portnum = 2
  147. REPT MAXCOM
  148. Define_DEF_COM_INT %??portnum
  149. ??portnum = ??portnum+1
  150. ENDM
  151. PURGE Define_DEF_COM_INT
  152. IFDEF No_DOSX_Bimodal_Services
  153. PUBLIC DEF_RM_COM_INT_1
  154. DEF_RM_COM_INT_1 proc far
  155. sub sp, 4
  156. push di
  157. mov di, DataOFFSET IRQhook1
  158. jmp DEF_RM_Handler
  159. DEF_RM_COM_INT_1 endp
  160. ENDIF
  161. PUBLIC DEF_COM_INT_1
  162. DEF_COM_INT_1 proc far
  163. sub sp, 4
  164. push di
  165. mov di, DataOFFSET IRQhook1
  166. IF2
  167. .errnz $ - OFFSET DEF_Handler
  168. ENDIF
  169. DEF_COM_INT_1 endp
  170. DEF_Handler proc far
  171. push es
  172. push di
  173. push ax
  174. mov ax, _DATA
  175. mov es, ax
  176. mov di, es:[di.First_DEB] ; ES:DI -> ComDEB
  177. add di, SIZE ComDEB ; ES:DI -> BIS
  178. push cs
  179. call NEAR PTR COMHandler
  180. pop ax
  181. pop di ; ES:DI -> IRQ_Hook_Struc
  182. ifndef NEC_98
  183. jc short DEF_chain
  184. endif ; NEC_98
  185. pop es
  186. pop di
  187. add sp, 4
  188. iret
  189. DEF_chain:
  190. call DOCLI
  191. push bp
  192. mov bp, sp ;stack frame:
  193. ; bp+8 -> OldInt CS
  194. ; bp+6 -> OldInt IP
  195. ; bp+4 -> di
  196. ; bp+2 -> es
  197. ; bp+0 -> bp
  198. les di, es:[di.OldIntVec]
  199. mov [bp+6], di
  200. mov [bp+8], es
  201. pop bp
  202. pop es
  203. pop di
  204. ret ; far ret to OldInt handler
  205. DEF_Handler endp
  206. ;------------------------------------------------------------------------------
  207. ;
  208. ; ENTER: ES:DI -> BIS
  209. ;
  210. ; EXIT: Carry set, if IRQ not handled by any com ports
  211. ;
  212. COMHandler proc far
  213. push ds
  214. push si
  215. push ax
  216. push bx
  217. mov si, es
  218. mov ds, si
  219. mov bh, -1
  220. ch_chk_all:
  221. lea si, [di-SIZE ComDEB] ;ds:si -> ComDEB
  222. mov si, [si.IRQhook]
  223. mov si, [si.First_DEB]
  224. mov bl, -1
  225. ch_next_com:
  226. inc bl ; first time bl = 0
  227. xor ax, ax
  228. xchg ax, [di.BIS_Mode]
  229. lea di, [si+SIZE ComDEB]
  230. mov [di.BIS_Mode], ax
  231. call CommInt
  232. and al, 80h
  233. or bl, al
  234. mov si, [si.NextDEB]
  235. or si, si
  236. jnz ch_next_com
  237. test bl, 7Fh ;Q: more than 1 com port?
  238. jnz short ch_shared ; Y: check if handled
  239. or bl, bl ;Q: int handled by port?
  240. stc
  241. jns ch_exit ; N:
  242. ch_eoi:
  243. xor ax, ax
  244. .errnz BIH_API_EOI
  245. xor bx, bx
  246. xchg bx, es:[di.BIS_Mode]
  247. call es:[bx][di.BIS_User_Mode_API]
  248. lea si, [di-SIZE ComDEB] ; ds:si -> ComDEB
  249. mov si, [si.IRQhook]
  250. mov al, [si.OldMask]
  251. shr al, 1 ; shift bit 0 into Carry (0, if unmasked
  252. cmc ; -1, if originally masked)
  253. ch_exit:
  254. pop bx
  255. pop ax
  256. pop si
  257. pop ds
  258. ret
  259. ch_shared:
  260. inc bh ; count loop
  261. or bl, bl ;Q: int handled by any port?
  262. js ch_chk_all ; Y: check all ports again
  263. or bh, bh ;Q: first time thru loop?
  264. stc
  265. jz ch_exit ; Y: int wasn't for a COM port, so
  266. ; chain to next IRQ handler
  267. jmp ch_eoi
  268. COMHandler endp
  269. IFDEF No_DOSX_Bimodal_Services
  270. PUBLIC Entry_From_RM
  271. Entry_From_RM proc far
  272. ;
  273. ; Simulate the far ret
  274. ;
  275. cld
  276. lodsw
  277. mov es:[di.RealMode_IP], ax
  278. lodsw
  279. mov es:[di.RealMode_CS], ax
  280. add es:[di.RealMode_SP], 4
  281. push es
  282. push di
  283. .286
  284. ;
  285. ; Push far addr of Ret_To_IRET to cleanup stack and return to DPMI host
  286. ;
  287. push cs
  288. push IntCodeOFFSET Ret_To_IRET
  289. ;
  290. ; Push far addr of proc to call, so we can do a far ret to it
  291. ;
  292. push es:[di.RealMode_CX] ; segment of callback
  293. push es:[di.RealMode_DX] ; offset of callback
  294. mov di, es:[di.RealMode_DI]
  295. ret ; far ret to cx:dx
  296. ; called proc will do a far ret
  297. Ret_To_IRET: ; <- to here
  298. pop di
  299. pop es
  300. iret
  301. .8086
  302. Entry_From_RM endp
  303. PUBLIC RM_APIHandler
  304. RM_APIHandler proc far
  305. cmp ax, BIH_API_Call_Back
  306. jne APIHandler
  307. call cs:[RM_CallBack]
  308. ret
  309. RM_APIHandler endp
  310. ENDIF
  311. ;------------------------------------------------------------------------------
  312. ;
  313. ; ENTER: ES:DI -> BIS
  314. ;
  315. APIHandler proc far
  316. or ax, ax
  317. jnz short api_not_EOI
  318. .errnz BIH_API_EOI
  319. mov ax, es:[di.BIS_IRQ_Number]
  320. cmp al,8 ;Q: slave IRQ?
  321. mov al,EOI
  322. jb short api_master ; N:
  323. ifdef NEC_98
  324. out 08h,al ; Y: EOI slave
  325. else ; NEC_98
  326. out 0A0h,al ; Y: EOI slave
  327. endif ; NEC_98
  328. api_master:
  329. ifdef NEC_98
  330. out 00h,al ; EOI master
  331. else ; NEC_98
  332. out INTA0,al ; EOI master
  333. endif ; NEC_98
  334. ret
  335. api_not_EOI:
  336. cmp ax, BIH_API_Call_Back
  337. jae short api_callme
  338. push dx
  339. push cx
  340. ifdef NEC_98
  341. mov dx, 02h
  342. else ; NEC_98
  343. mov dx, INTA1
  344. endif ; NEC_98
  345. mov cx, es:[di.BIS_IRQ_Number]
  346. cmp cl, 8 ;Q: 2nd PIC?
  347. jb @f ; N:
  348. ifdef NEC_98
  349. mov dx, 0Ah ; Y: dx = mask port
  350. else ; NEC_98
  351. mov dx, 0A1h ; Y: dx = mask port
  352. endif ; NEC_98
  353. sub cl, 8
  354. @@:
  355. cmp al, BIH_API_Get_Mask ;Q: get IRQ mask?
  356. jae api_get_mask ; Y:
  357. mov ah, al
  358. mov ch, 1
  359. shl ch, cl ; ch = mask byte
  360. pushf
  361. call DOCLI
  362. in al, dx ; get current PIC mask state
  363. cmp ah, BIH_API_Mask ;Q: mask IRQ?
  364. jne @f ; N:
  365. or al, ch ; Y: set IRQ's bit
  366. jmp short api_mask_exit
  367. @@:
  368. not ch ; N: clear IRQ's bit to unmask
  369. and al, ch
  370. api_mask_exit:
  371. out dx, al
  372. pop ax
  373. test ah, 2 ;Q: ints were enabled?
  374. jz @f ; N:
  375. call DOSTI
  376. @@:
  377. pop cx
  378. pop dx
  379. ret
  380. api_get_mask:
  381. in al, dx ; get current PIC mask state
  382. ifdef NEC_98
  383. iodelay ;1994.08.01 KBNES
  384. endif ; NEC_98
  385. inc cl
  386. shr al, cl ; move IRQ's bit into carry
  387. ; Carry set, if IRQ masked
  388. pop cx
  389. pop dx
  390. ret
  391. api_callme:
  392. push cx
  393. push dx
  394. ret ; far ret to call back, which will
  395. ; do a far ret to our caller
  396. APIHandler endp
  397. ;--------------------------Fake a Hardware Interrupt----------------------;
  398. ; FakeCOMInt
  399. ;
  400. ; This routine fakes a hardware interrupt to IRQ3 or IRQ4
  401. ; to clear out characters pending in the buffer
  402. ;
  403. ; Entry:
  404. ; DS:SI --> DEB
  405. ; INTERRUPTS DISABLED!
  406. ; Returns:
  407. ; None
  408. ; Error Returns:
  409. ; None
  410. ; Registers Preserved:
  411. ;
  412. ; Registers Destroyed:
  413. ; AX,DX,FLAGS
  414. ; History: glenn steffler 5/17/89
  415. ;-----------------------------------------------------------------------;
  416. FakeCOMInt proc near
  417. ; call DOCLI ;Done by caller
  418. ;
  419. ; WARNING: jumping into the middle of CommInt, so the stack must be set
  420. ; properly.
  421. ;
  422. push dx
  423. push bx
  424. push cx
  425. push di
  426. push es
  427. push EvtWord[si]
  428. mov dx,Port[si] ;Get device I/O address
  429. add dl, ACE_IIDR
  430. push dx
  431. jmp FakeXmitEmpty ;Process the fake interrupt, DS:SI is
  432. ; already pointing to proper DEB
  433. ;
  434. ; FakeXmitEmpty falls in XmitEmpty which jumps back into CommInt. When CommInt
  435. ; determines that no interrupt is pending, then it will near return back to
  436. ; FakeCOMIntFar which can far ret back to its caller.
  437. ;
  438. FakeCOMInt endp
  439. public FakeCOMIntFar
  440. FakeCOMIntFar proc far
  441. call FakeCOMInt
  442. ret
  443. FakeCOMIntFar endp
  444. ;--------------------------Interrupt Handler----------------------------
  445. ;
  446. ; CommInt - Interrupt handler for com ports
  447. ;
  448. ; Interrupt handlers for PC com ports. This is the communications
  449. ; interrupt service routine for RS232 communications. When an RS232
  450. ; event occurs the interrupt vectors here. This routine determines
  451. ; who the caller was and services the appropriate interrupt. The
  452. ; interrupts are prioritized in the following order:
  453. ;
  454. ; 1. line status interrupt
  455. ; 2. read data available interrupt
  456. ; 3. transmit buffer empty interrupt
  457. ; 4. modem service interrupt
  458. ;
  459. ; This routine continues to service until all interrupts have been
  460. ; satisfied.
  461. ;
  462. ; Entry:
  463. ; DS:SI --> DEB
  464. ; INTERRUPTS DISABLED!
  465. ; Returns:
  466. ; AL = 0, if not handled, -1, if handled
  467. ;
  468. ;-----------------------------------------------------------------------
  469. assumes ds,Data
  470. assumes es,nothing
  471. ; Dispatch table for interrupt types
  472. SrvTab label word
  473. dw OFFSET ModemStatus ;[0] Modem Status Interrupt
  474. dw OFFSET XmitEmpty ;[2] Tx Holding Reg. Interrupt
  475. dw OFFSET DataAvail ;[4] Rx Data Available Interrupt
  476. ; or [C] if 16550 & 16550A
  477. dw OFFSET LineStat ;[6] Reciever Line Status Interrupt
  478. public CommInt
  479. CommInt proc near
  480. xor al, al
  481. cmp word ptr [VCD_int_callback+4], 0
  482. je short @F ; jump if no callback (not 3.1 VCD)
  483. test [si.VCDflags], fCOM_ignore_ints ;Q: we still own port?
  484. jnz IntLoop40 ; N: ignore the int
  485. .386
  486. push esi
  487. mov esi, [si.VCD_data]
  488. call [VCD_int_callback]
  489. pop esi
  490. .8086
  491. @@:
  492. push dx
  493. mov dx,Port[si] ;Get comm I/O port
  494. add dl,ACE_IIDR ;--> Interrupt ID Register
  495. in al, dx
  496. ifdef NEC_98
  497. iodelay ;1994.08.01 KBNES
  498. endif ; NEC_98
  499. test al, 1 ;Q: interrupt pending?
  500. jnz short IntLoop30 ; N:
  501. push bx
  502. push cx
  503. push di
  504. push es
  505. mov cx, EvtWord[si]
  506. push cx
  507. jmp short IntLoop10
  508. InterruptLoop_ChkTx:
  509. cmp QOutCount[si],0 ;Output queue empty?
  510. je short InterruptLoop ; Y: don't chk tx
  511. pop dx
  512. push dx
  513. dec dx ; to IER
  514. .errnz ACE_IIDR - ACE_IER - 1
  515. in al, dx
  516. and al,NOT ACE_ETBEI ; disable it
  517. iodelay
  518. out dx, al
  519. or al, ACE_ETBEI ; enable it again
  520. iodelay
  521. out dx, al
  522. iodelay
  523. out dx, al
  524. ifdef NEC_98
  525. iodelay ;1994.08.01 KBNES
  526. endif ; NEC_98
  527. InterruptLoop:
  528. pop dx ;Get ID reg I/O address
  529. in al,dx ;Get Interrupt Id
  530. ifdef NEC_98
  531. iodelay ;1994.08.01 KBNES
  532. endif ; NEC_98
  533. test al,1 ;Interrupt need servicing?
  534. jnz IntLoop20 ;No, all done
  535. IntLoop10:
  536. and ax, 07h
  537. mov di,ax
  538. push dx ;Save Id register
  539. jmp SrvTab[di] ;Service the Interrupt
  540. IntLoop20:
  541. mov ax,EvtMask[si] ;Mask the event word to only the
  542. and ax, EvtWord[si] ; user specified bits
  543. mov EvtWord[si], ax
  544. pop bx
  545. test [si.NotifyFlagsHI], CN_Notify
  546. jz short ci_exit
  547. not bx
  548. and ax, bx ; bits set in ax are new events
  549. jnz short ci_new_events
  550. ci_exit:
  551. pop es
  552. assumes es,nothing
  553. pop di
  554. pop cx
  555. pop bx
  556. xor al, al
  557. IntLoop30:
  558. pop dx
  559. and al, 1
  560. dec al ; 0->-1, 1->0
  561. IntLoop40:
  562. ret
  563. ci_new_events:
  564. mov ax, CN_EVENT
  565. call notify_owner
  566. jmp ci_exit
  567. CommInt endp
  568. page
  569. ;----------------------------Private-Routine----------------------------;
  570. ;
  571. ; LineStat - Line Status Interrupt Handler
  572. ;
  573. ; Break detection is handled and set in the event word if
  574. ; enabled. Other errors (overrun, parity, framing) are
  575. ; saved for the data available interrupt.
  576. ;
  577. ; This routine used to fall into DataAvail for the bulk of its processing.
  578. ; This is no longer the case... A very popular internal modem seems to
  579. ; operate differently than a real 8250 when parity errors occur. Falling
  580. ; into the DataAvail handler on a parity error caused the same character
  581. ; to be received twice. Having this routine save the LSR status, and
  582. ; return to InterruptLoop fixes the problem, and still works on real COMM
  583. ; ports. The extra overhead isn't a big deal since this routine is only
  584. ; entered when there is an exception like a parity error.
  585. ;
  586. ; This routine is jumped to, and will perform a jump back into
  587. ; the dispatch loop.
  588. ;
  589. ; Entry:
  590. ; DS:SI --> DEB
  591. ; DX = Port.IIDR
  592. ; Returns:
  593. ; None
  594. ; Error Returns:
  595. ; None
  596. ; Registers Destroyed:
  597. ; AX,FLAGS
  598. ; History:
  599. ;-----------------------------------------------------------------------;
  600. ; assumes ds,Data
  601. assumes es,nothing
  602. public LineStat ;Public for debugging
  603. LineStat proc near
  604. or by EvtWord[si],EV_Err ;Show line status error
  605. add dl,ACE_LSR-ACE_IIDR ;--> Line Status Register
  606. in al,dx
  607. ifdef NEC_98
  608. iodelay ;1994.08.01 KBNES
  609. endif ; NEC_98
  610. test al,ACE_PE+ACE_FE+ACE_OR ;Parity, Framing, Overrun error?
  611. jz @f
  612. mov LSRShadow[si],al ;yes, save status for DataAvail
  613. @@:
  614. test al,ACE_BI ;Break detect?
  615. jz InterruptLoop_ChkTx ;Not break detect interrupt
  616. or by EvtWord[si],EV_Break ;Show break
  617. jmp short InterruptLoop_ChkTx
  618. LineStat endp
  619. page
  620. ;----------------------------Private-Routine----------------------------;
  621. ;
  622. ; DataAvail - Data Available Interrupt Handler
  623. ;
  624. ; The available character is read and stored in the input queue.
  625. ; If the queue has reached the point that a handshake is needed,
  626. ; one is issued (if enabled). EOF detection, Line Status errors,
  627. ; and lots of other stuff is checked.
  628. ;
  629. ; This routine is jumped to, and will perform a jump back into
  630. ; the dispatch loop.
  631. ;
  632. ; Entry:
  633. ; DS:SI --> DEB
  634. ; DX = Port.IIDR
  635. ; Returns:
  636. ; None
  637. ; Error Returns:
  638. ; None
  639. ; Registers Destroyed:
  640. ; AX,BX,CX,DI,ES,FLAGS
  641. ; History:
  642. ;-----------------------------------------------------------------------;
  643. ; assumes ds,Data
  644. assumes es,nothing
  645. public DataAvail ;public for debugging
  646. DataAvail proc near
  647. sub dl,ACE_IIDR-ACE_RBR ;--> receiver buffer register
  648. in al,dx ;Read received character
  649. ifdef NEC_98
  650. iodelay ;1994.08.01 KBNES
  651. endif ; NEC_98
  652. and [si.NotifyFlagsHI], NOT CN_Idle ; flag as not idle
  653. mov ah,LSRShadow[si] ;what did the last Line Status intrpt
  654. mov bh,ah ; have to say?
  655. or ah,ah
  656. jz @f
  657. and ah,ErrorMask[si] ;there was an error, record it
  658. or by ComErr[si],ah
  659. IFNDEF KKBUGFIX ; 1/05/93:TakuA:Fix #1666
  660. mov LSRShadow[si],0
  661. ENDIF
  662. .errnz ACE_OR-CE_OVERRUN ;Must be the same bits
  663. .errnz ACE_PE-CE_RXPARITY
  664. .errnz ACE_FE-CE_FRAME
  665. .errnz ACE_BI-CE_BREAK
  666. @@:
  667. ; Regardless of the character received, flag the event in case
  668. ; the user wants to see it.
  669. or by EvtWord[si],EV_RxChar ;Show a character received
  670. .errnz HIGH EV_RxChar
  671. ; Check the input queue, and see if there is room for another
  672. ; character. If not, or if the end of file character has already
  673. ; been received, then go declare overflow.
  674. DataAvail00:
  675. IFDEF KKBUGFIX ; 1/05/93:TakuA:Fix #1666
  676. mov bh,LSRShadow[si]
  677. mov LSRShadow[si],0
  678. ENDIF
  679. mov cx,QInCount[si] ;Get queue count (used later too)
  680. cmp cx,QInSize[si] ;Is queue full?
  681. jge DataAvail20 ; Yes, comm overrun
  682. test EFlags[si],fEOF ;Has end of file been received?
  683. jnz DataAvail20 ; Yes - treat as overflow
  684. ; Test to see if there was a parity error, and replace
  685. ; the character with the parity character if so
  686. test bh,ACE_PE ;Parity error
  687. jz DataAvail25 ; No
  688. test [si.DCB_Flags2],fPErrChar ;Parity error replacement character?
  689. jz DataAvail25 ; No
  690. mov al,[si.DCB_PEChar] ; Yes, get parity replacement char
  691. ; Skip all other processing except event checking and the queing
  692. ; of the parity error replacement character
  693. jmp short DataAvail80 ;Skip all but event check, queing
  694. DataAvail20:
  695. or by ComErr[si],CE_RXOVER ;Show queue overrun
  696. jmp short DataAvail50
  697. ; See if we need to strip null characters, and skip
  698. ; queueing if this is one. Also remove any parity bits.
  699. DataAvail25:
  700. and al,RxMask[si] ;Remove any parity bits
  701. jnz DataAvail30 ;Not a Null character
  702. test [si.DCB_Flags2],fNullStrip ;Are we stripping received nulls?
  703. jnz DataAvail50 ; Yes, put char in the bit bucket
  704. ; Check to see if we need to check for EOF characters, and if so
  705. ; see if this character is it.
  706. DataAvail30:
  707. test [si.DCB_Flags],fBinary ;Is this binary stuff?
  708. jnz DataAvail60 ; Yes, skip EOF check
  709. cmp al,[si.DCB_EOFChar] ;Is this the EOF character?
  710. jnz DataAvail60 ; No, see about queing the charcter
  711. or EFlags[si],fEOF ;Set end of file flag
  712. DataAvail50:
  713. jmp DataAvail140 ;Skip the queing process
  714. ; If output XOn/XOff is enabled, see if the character just received
  715. ; is either an XOn or XOff character. If it is, then set or
  716. ; clear the XOffReceived flag as appropriate.
  717. DataAvail60:
  718. test [si.DCB_Flags2],fOutX ;Output handshaking?
  719. jz DataAvail80 ; No
  720. cmp al,[si.DCB_XoffChar] ;Is this an X-Off character?
  721. jnz DataAvail70 ; No, see about XOn or Ack
  722. or HSFlag[si],XOffReceived ;Show XOff received, ENQ or ETX [rkh]
  723. test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack?
  724. jz DataAvail50 ; No
  725. cmp cx,[si.DCB_XonLim] ;See if at XOn limit
  726. ja DataAvail50 ; No
  727. and HSFlag[si],NOT XOffReceived ;Show ENQ or ETX not received
  728. and HSFlag[si], NOT XOnPending+XOffSent
  729. mov al, [si.DCB_XonChar]
  730. call OutHandshakingChar
  731. jmp DataAvail50 ;Done
  732. DataAvail70:
  733. cmp al,[si.DCB_XonChar] ;Is this an XOn character?
  734. jnz DataAvail80 ; No, just a normal character
  735. and HSFlag[si],NOT XOffReceived
  736. test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack?
  737. jz DataAvail75 ; No - jump to FakeXmitEmpty to get
  738. ; transmitting going again
  739. and HSFlag[si],NOT EnqSent
  740. DataAvail75:
  741. jmp FakeXmitEmpty ;Restart transmit
  742. ; Now see if this is a character for which we need to set an event as
  743. ; having occured. If it is, then set the appropriate event flag
  744. DataAvail80:
  745. cmp al,[si.DCB_EVTChar] ;Is it the event generating character?
  746. jne DataAvail90 ; No
  747. or by EvtWord[si],EV_RxFlag ;Show received specific character
  748. ; Finally, a valid character that we want to keep, and we have
  749. ; room in the queue. Place the character in the queue.
  750. ; If the discard flag is set, then discard the character
  751. DataAvail90:
  752. test MiscFlags[si], Discard ;Discarding characters ?
  753. jnz DataAvail50 ; Yes
  754. lea bx, [si+SIZE ComDEB] ; DS:BX -> BIS
  755. mov bx, [bx.BIS_Mode] ; mode will be either 0 or 4
  756. les di,QInAddr[si][bx] ;Get queue base pointer from either
  757. assumes es,nothing ; QInAddr or AltQInAddr
  758. mov bx,QInPut[si] ;Get index into queue
  759. mov es:[bx][di],al ;Store the character
  760. inc bx ;Update queue index
  761. cmp bx,QInSize[si] ;See if time for wrap-around
  762. jc DataAvail100 ;Not time to wrap
  763. xor bx,bx ;Wrap-around is a new zero pointer
  764. DataAvail100:
  765. mov QInPut[si],bx ;Store updated pointer
  766. inc cx ;And update queue population
  767. mov QInCount[si],cx
  768. ; If flow control has been enabled, see if we are within the
  769. ; limit that requires us to halt the host's transmissions
  770. cmp cx,XOffPoint[si] ;Time to see about XOff?
  771. jc DataAvail120 ; Not yet
  772. test HSFlag[si],HSSent ;Handshake already sent?
  773. jnz DataAvail120 ; Yes, don't send it again
  774. mov ah,HHSLines[si] ;Should hardware lines be dropped?
  775. or ah,ah ; (i.e. do we have HW HS enabled?)
  776. jz DataAvail110 ; No
  777. add dl,ACE_MCR ; Yes
  778. in al,dx ;Clear the necessary bits
  779. ifdef NEC_98
  780. iodelay ;1994.08.01 KBNES
  781. endif ; NEC_98
  782. not ah
  783. and al,ah
  784. or HSFlag[si],HHSDropped ;Show lines have been dropped
  785. out dx,al ; and drop the lines
  786. ifdef NEC_98
  787. iodelay ;1994.08.01 KBNES
  788. endif ; NEC_98
  789. sub dl,ACE_MCR
  790. DataAvail110:
  791. test [si.DCB_Flags2],fInX ;Input Xon/XOff handshaking
  792. jz DataAvail120 ; No
  793. or HSFlag[si], XOffSent
  794. mov al, [si.DCB_XoffChar]
  795. call OutHandshakingChar
  796. DataAvail120:
  797. cmp cx, [si.RecvTrigger] ;Q: time to call owner's callback?
  798. jb short DataAvail130 ; N:
  799. test [si.NotifyFlagsHI], CN_RECEIVE
  800. jnz short DataAvail140 ; jump if notify already sent and
  801. ; data in buffer hasn't dropped
  802. ; below threshold
  803. mov ax, IntCodeOFFSET DataAvail140
  804. push ax
  805. mov ax, CN_RECEIVE
  806. %OUT probably should just set a flag and notify after EOI
  807. jmp notify_owner
  808. DataAvail130:
  809. and [si.NotifyFlagsHI], NOT CN_RECEIVE
  810. DataAvail140:
  811. pop dx
  812. push dx
  813. add dl, ACE_LSR-ACE_IIDR
  814. in al, dx
  815. ifdef NEC_98
  816. iodelay ;1994.08.01 KBNES
  817. endif ; NEC_98
  818. test al, ACE_DR ;Q: more data available?
  819. jz @F ; N:
  820. sub dl, ACE_LSR ; Y: go read it
  821. in al, dx ;Read available character
  822. ifdef NEC_98
  823. iodelay ;1994.08.01 KBNES
  824. endif ; NEC_98
  825. jmp DataAvail00
  826. @@:
  827. jmp InterruptLoop_ChkTx
  828. DataAvail endp
  829. OutHandshakingChar proc near
  830. add dl, ACE_LSR
  831. mov ah, al
  832. @@:
  833. in al, dx
  834. ifdef NEC_98
  835. iodelay ;1994.08.01 KBNES
  836. endif ; NEC_98
  837. test al, ACE_THRE
  838. jz @B
  839. sub dl, ACE_LSR
  840. mov al, ah
  841. out dx, al
  842. ifdef NEC_98
  843. iodelay ;1994.08.01 KBNES
  844. endif ; NEC_98
  845. ret
  846. OutHandshakingChar endp
  847. page
  848. ;----------------------------Private-Routine----------------------------;
  849. ;
  850. ; XmitEmpty - Transmitter Register Empty
  851. ;
  852. ; Entry:
  853. ; DS:SI --> DEB
  854. ; DX = Port.IIDR
  855. ; Returns:
  856. ; None
  857. ; Error Returns:
  858. ; None
  859. ; Registers Destroyed:
  860. ; AX,BX,CX,DI,ES,FLAGS
  861. ; History:
  862. ;-----------------------------------------------------------------------;
  863. ; assumes ds,Data
  864. assumes es,nothing
  865. public FakeXmitEmpty
  866. FakeXmitEmpty:
  867. pop dx
  868. push dx
  869. ; "Kick" the transmitter interrupt routine into operation.
  870. dec dl
  871. .errnz ACE_IIDR - ACE_IER-1
  872. in al,dx ;Get current IER state
  873. ifdef NEC_98
  874. iodelay ;1994.08.01 KBNES
  875. endif ; NEC_98
  876. test al,ACE_ETBEI ;Interrupt already enabled?
  877. jnz @F ; Yes, don't reenable it
  878. or al,ACE_ETBEI ; No, enable it
  879. out dx,al
  880. iodelay ;8250, 8250-B bug requires
  881. out dx,al ; writting register twice
  882. @@:
  883. add dl,ACE_LSR-ACE_IER ;--> Line Status Register
  884. iodelay
  885. in al,dx ;Is xmit really empty?
  886. ifdef NEC_98
  887. iodelay ;1994.08.01 KBNES
  888. endif ; NEC_98
  889. sub dl,ACE_LSR-ACE_THR ;--> Transmitter Holding Register
  890. test al,ACE_THRE
  891. jnz short XmitEmpty5 ; Y: send next char
  892. jmp InterruptLoop ; N: return to processing loop
  893. public XmitEmpty
  894. XmitEmpty proc near
  895. add dl,ACE_LSR-ACE_IIDR ;--> Line Status Register
  896. in al,dx ;Is xmit really empty?
  897. ifdef NEC_98
  898. iodelay ;1994.08.01 KBNES
  899. endif ; NEC_98
  900. sub dl,ACE_LSR-ACE_THR ;--> Transmitter Holding Register
  901. test al,ACE_THRE
  902. jz Xmit_jumpto90 ;Transmitter not empty, cannot send
  903. ; If the hardware handshake lines are down, then XOff/XOn cannot
  904. ; be sent. If they are up and XOff/XOn has been received, still
  905. ; allow us to transmit an XOff/XOn character. It will make
  906. ; a dead lock situation less possible (even though there are
  907. ; some which could happen that cannot be handled).
  908. XmitEmpty5:
  909. mov ah,HSFlag[si] ;Get handshaking flag
  910. test ah,HHSDown+BreakSet ;Hardware lines down or break set?
  911. jnz Xmit_jumpto100 ; Yes, cannot transmit
  912. ; Give priority to any handshake character waiting to be
  913. ; sent. If there are none, then check to see if there is
  914. ; an "immediate" character to be sent. If not, try the queue.
  915. XmitEmpty10:
  916. test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack?
  917. jnz XmitEmpty40 ; Yes
  918. XmitEmpty15:
  919. test ah,HSPending ;XOff or XOn pending
  920. jz XmitEmpty40 ; No
  921. XmitEmpty20:
  922. and ah,NOT XOnPending+XOffSent
  923. mov al,[si.DCB_XonChar] ;Get XOn character
  924. XmitEmpty30:
  925. mov HSFlag[si],ah ;Save updated handshake flag
  926. jmp XmitEmpty110 ;Go output the character
  927. Xmit_jumpto90:
  928. jmp XmitEmpty90
  929. ; If any of the lines which were specified for a timeout are low, then
  930. ; don't send any characters. Note that by putting the check here,
  931. ; XOff and Xon can still be sent even though the lines might be low.
  932. ; Also test to see if a software handshake was received. If so,
  933. ; then transmission cannot continue. By delaying the software check
  934. ; to here, XOn/XOff can still be issued even though the host told
  935. ; us to stop transmission.
  936. XmitEmpty40:
  937. test ah,CannotXmit ;Anything preventing transmission?
  938. jz XmitEmpty45 ; No
  939. Xmit_jumpto100:
  940. jmp XmitEmpty100 ; Yes, disarm and exit
  941. ; If a character has been placed in the single character "transmit
  942. ; immediately" buffer, clear that flag and pick up that character
  943. ; without affecting the transmitt queue.
  944. XmitEmpty45:
  945. test EFlags[si],fTxImmed ;Character to xmit immediately?
  946. jz XmitEmpty515 ; No, try the queue
  947. and EFlags[si],NOT fTxImmed ;Clear xmit immediate flag
  948. mov al,ImmedChar[si] ;Get char to xmit
  949. jmp XmitEmpty110 ;Transmit the character
  950. XmitEmpty515:
  951. mov cx,QOutCount[si] ;Output queue empty?
  952. jcxz Xmit_jumpto90 ; Yes, go set an event
  953. test [si.DCB_Flags],fEtxAck ;Etx Ack?
  954. jz XmitEmpty55 ; No
  955. mov cx,QOutMod[si] ;Get number bytes sent since last ETX
  956. cmp cx,[si.DCB_XonLim] ;At Etx limit yet?
  957. jne XmitEmpty51 ; No, inc counter
  958. mov QOutMod[si],0 ; Yes, zero counter
  959. or HSFlag[si],EtxSent ;Show ETX sent
  960. jmp short XE_sendXOFF
  961. XmitEmpty51:
  962. inc cx ; Update counter
  963. mov QOutMod[si],cx ; Save counter
  964. jmp short XmitEmpty59 ; Send queue character
  965. XmitEmpty55:
  966. test [si.DCB_Flags],fEnqAck ;Enq Ack?
  967. jz XmitEmpty59 ; No, send queue character
  968. mov cx,QOutMod[si] ;Get number bytes sent since last ENQ
  969. or cx,cx ;At the front again?
  970. jnz XmitEmpty56 ; No, inc counter
  971. mov QOutMod[si],1 ; Yes, send ENQ
  972. or HSFlag[si],EnqSent ;Show ENQ sent
  973. XE_sendXOFF:
  974. mov al,[si.DCB_XoffChar]
  975. jmp short XmitEmpty110 ;Go output the character
  976. XmitEmpty56:
  977. inc cx ;Update counter
  978. cmp cx,[si.DCB_XonLim] ;At end of our out buffer len?
  979. jne XmitEmpty58 ; No
  980. xor cx,cx ;Show at front again.
  981. XmitEmpty58:
  982. mov QOutMod[si],cx ;Save counter
  983. XmitEmpty59:
  984. lea bx, [si+SIZE ComDEB] ; DS:BX -> BIS
  985. mov bx, [bx.BIS_Mode] ; mode will be either 0 or 4
  986. les di,QOutAddr[si][bx] ;Get queue base pointer from either
  987. assumes es,nothing ; QOutAddr or AltQOutAddr
  988. mov bx,QOutGet[si] ;Get pointer into queue
  989. mov al,es:[bx][di] ;Get the character
  990. inc bx ;Update queue pointer
  991. cmp bx,QOutSize[si] ;See if time for wrap-around
  992. jc XmitEmpty60 ;Not time for wrap
  993. xor bx,bx ;Wrap by zeroing the index
  994. XmitEmpty60:
  995. mov QOutGet[si],bx ;Save queue index
  996. mov cx,QOutCount[si] ;Output queue empty?
  997. dec cx ;Dec # of bytes in queue
  998. mov QOutCount[si],cx ; and save new population
  999. out dx,al ;Send char
  1000. ifdef NEC_98
  1001. iodelay ;1994.08.01 KBNES
  1002. endif ; NEC_98
  1003. cmp cx, [si.SendTrigger] ;Q: time to call owner's callback?
  1004. jae short XmitEmpty70 ; N:
  1005. test [si.NotifyFlagsHI], CN_TRANSMIT
  1006. jnz short XmitEmpty80 ; jump if notify already sent and
  1007. ; data in buffer hasn't raised
  1008. ; above threshold
  1009. mov ax, IntCodeOFFSET XmitEmpty80
  1010. push ax
  1011. mov ax, CN_TRANSMIT
  1012. jmp short notify_owner
  1013. XmitEmpty70:
  1014. and [si.NotifyFlagsHI], NOT CN_TRANSMIT
  1015. XmitEmpty80:
  1016. %OUT check fNoFIFO in EFlags[si] to determine if we can queue more output
  1017. jmp InterruptLoop
  1018. ; No more characters to transmit. Flag this as an event.
  1019. XmitEmpty90:
  1020. or by EvtWord[si],EV_TxEmpty
  1021. ; Cannot continue transmitting (for any of a number of reasons).
  1022. ; Disable the transmit interrupt. When it's time resume, the
  1023. ; transmit interrupt will be reenabled, which will generate an
  1024. ; interrupt.
  1025. XmitEmpty100:
  1026. inc dx ;--> Interrupt Enable Register
  1027. .errnz ACE_IER-ACE_THR-1
  1028. in al,dx ;I don't know why it has to be read
  1029. ifdef NEC_98
  1030. iodelay ;1994.08.01 KBNES
  1031. endif ; NEC_98
  1032. and al,NOT ACE_ETBEI ; first, but it works this way
  1033. XmitEmpty110:
  1034. out dx,al
  1035. jmp InterruptLoop
  1036. XmitEmpty endp
  1037. page
  1038. ;----------------------------Private-Routine----------------------------;
  1039. ;
  1040. ; ModemStatus - Modem Status Interrupt Handler
  1041. ;
  1042. ; Entry:
  1043. ; DS:SI --> DEB
  1044. ; DX = Port.IIDR
  1045. ; Returns:
  1046. ; None
  1047. ; Error Returns:
  1048. ; None
  1049. ; Registers Destroyed:
  1050. ; AX,BX,CX,DI,ES,FLAGS
  1051. ; History:
  1052. ;-----------------------------------------------------------------------;
  1053. ; assumes ds,Data
  1054. assumes es,nothing
  1055. public ModemStatus ;Public for debugging
  1056. ModemStatus proc near
  1057. ; Get the modem status value and shadow it for MSRWait.
  1058. add dl,ACE_MSR-ACE_IIDR ;--> Modem Status Register
  1059. in al,dx
  1060. ifdef NEC_98
  1061. iodelay ;1994.08.01 KBNES
  1062. endif ; NEC_98
  1063. mov MSRShadow[si],al ;Save MSR data for others
  1064. mov ch,al ;Save a local copy
  1065. ; Create the event mask for the delta signals
  1066. mov ah,al ;Just a lot of shifting
  1067. shr ax,1
  1068. shr ax,1
  1069. shr ah,1
  1070. mov cl,3
  1071. shr ax,cl
  1072. and ax,EV_CTS+EV_DSR+EV_RLSD+EV_Ring
  1073. or EvtWord[si],ax
  1074. mov ah,ch ;[rkh]...
  1075. shr ah,1
  1076. shr ah,1
  1077. and ax,EV_CTSS+EV_DSRS
  1078. or EvtWord[si],ax
  1079. mov ah,ch
  1080. mov cl,3
  1081. shr ah,cl
  1082. and ax,EV_RLSD
  1083. or EvtWord[si],ax
  1084. mov ah,ch
  1085. mov cl,3
  1086. shl ah,cl
  1087. and ax,EV_RingTe
  1088. or EvtWord[si],ax
  1089. .errnz EV_CTS-0000000000001000b
  1090. .errnz EV_DSR-0000000000010000b
  1091. .errnz EV_RLSD-0000000000100000b
  1092. .errnz EV_Ring-0000000100000000b
  1093. .errnz EV_CTSS-0000010000000000b ;[rkh]
  1094. .errnz EV_DSRS-0000100000000000b
  1095. .errnz EV_RLSDS-0001000000000000b
  1096. .errnz EV_RingTe-0010000000000000b
  1097. .errnz ACE_DCTS-00000001b
  1098. .errnz ACE_DDSR-00000010b
  1099. .errnz ACE_DRLSD-00001000b
  1100. .errnz ACE_RI-01000000b
  1101. .errnz ACE_TERI-00000100b ;[rkh]
  1102. .errnz ACE_CTS-00010000b
  1103. .errnz ACE_DSR-00100000b
  1104. .errnz ACE_RLSD-10000000b
  1105. ModemStatus10:
  1106. mov al,OutHHSLines[si] ;Get output hardware handshake lines
  1107. or al,al ;Any lines that must be set?
  1108. jz ModemStatus40 ;No hardware handshake on output
  1109. and ch,al ;Mask bits of interest
  1110. cmp ch,al ;Lines set for Xmit?
  1111. je ModemStatus20 ; Yes
  1112. or HSFlag[si],HHSDown ;Show hardware lines have dropped
  1113. ModemStatus30:
  1114. jmp InterruptLoop
  1115. ModemStatus40:
  1116. jmp InterruptLoop_ChkTx
  1117. ; Lines are set for xmit. Kick an xmit interrupt if needed
  1118. ModemStatus20:
  1119. and HSFlag[si],NOT (HHSDown OR HHSAlwaysDown)
  1120. ;Show hardware lines back up
  1121. mov cx,QOutCount[si] ;Output queue empty?
  1122. jcxz ModemStatus30 ; Yes, return to InterruptLoop
  1123. jmp FakeXmitEmpty ;Restart transmit
  1124. ModemStatus endp
  1125. page
  1126. ;------------------------------------------------------------------------------
  1127. ;
  1128. ; ENTER: AX = message #
  1129. ; DS:SI -> DEB
  1130. notify_owner proc near
  1131. or [si.NotifyFlags], ax
  1132. lea di, [si+SIZE ComDEB]
  1133. mov ax, ds
  1134. mov es, ax
  1135. mov ax, BIH_API_Call_Back ; call immediate, or in protected mode
  1136. mov bx, 1 ; force SYS VM, if enhanced mode
  1137. mov cx, _INTERRUPT
  1138. mov dx, IntCodeOFFSET callback_event
  1139. %OUT use equate
  1140. push ds
  1141. push si
  1142. mov si, 1 ; low priority boost
  1143. push bp
  1144. mov bp, es:[di.BIS_Mode]
  1145. call es:[bp][di.BIS_User_Mode_API]
  1146. pop bp
  1147. pop si
  1148. pop ds
  1149. ret
  1150. notify_owner endp
  1151. ;------------------------------------------------------------------------------
  1152. ;
  1153. ; ENTER: ES:DI -> BIS
  1154. ;
  1155. callback_event proc far
  1156. lea si, [di-SIZE ComDEB]
  1157. mov ax, es
  1158. mov ds, ax
  1159. mov ax, [si.NotifyHandle]
  1160. push ax ; push hWnd
  1161. mov ax, WM_COMMNOTIFY
  1162. push ax ; push wMsg
  1163. xor ax, ax
  1164. mov al, [si.DCB_Id]
  1165. push ax ; push wParam = ComID
  1166. xor al, al
  1167. push ax ; push high word of lParam
  1168. xchg al, [si.NotifyFlagsLO]
  1169. or [si.NotifyFlagsHI], al
  1170. push ax ; push low word of lParam = event flags
  1171. call [lpPostMessage]
  1172. ret
  1173. callback_event endp
  1174. PUBLIC TimerProc
  1175. TimerProc proc far
  1176. push ds
  1177. mov ax, _DATA
  1178. mov ds, ax
  1179. assumes ds,data
  1180. mov ax, [activeCOMs]
  1181. or ax, ax
  1182. jz short tp_nonactive
  1183. push si
  1184. mov si, DataOFFSET COMptrs
  1185. mov cx, MAXCOM+1
  1186. tp_lp:
  1187. push si
  1188. mov si, [si] ; si -> ComDEB
  1189. shr ax, 1
  1190. jnc tp_lpend
  1191. cmp [si.RecvTrigger], -1 ;Q: owner wants notification?
  1192. je short tp_lpend ; N: skip notify
  1193. cmp [si.QInCount], 0 ;Q: anything in input queue?
  1194. je short tp_lpend ; N: skip notify
  1195. test [si.NotifyFlagsHI], CN_RECEIVE ;Q: timeout notify already given?
  1196. jnz short tp_lpend ; N: skip notify
  1197. xor [si.NotifyFlagsHI], CN_Idle ;Q: first timer call?
  1198. js short tp_lpend ; Y: skip notify
  1199. push ax
  1200. push cx
  1201. mov ax, CN_RECEIVE ; N: notify owner
  1202. call notify_owner
  1203. pop cx
  1204. pop ax
  1205. tp_lpend:
  1206. pop si
  1207. inc si ; inc to ptr to next ComDEB
  1208. inc si
  1209. or ax, ax
  1210. loopnz tp_lp
  1211. pop si
  1212. tp_nonactive:
  1213. pop ds
  1214. assumes ds,nothing
  1215. ret
  1216. TimerProc endp
  1217. page
  1218. ifdef NEC_98
  1219. ;===========================================================================
  1220. ; System Timer Interrupt Routine
  1221. ;
  1222. ; if ( QOutCount[si] != 0x0000 )
  1223. ; {
  1224. ; KickTx ();
  1225. ; }
  1226. ;===========================================================================
  1227. public TickEntry4 ;Ins 940923 KBNES
  1228. TickEntry4 proc far ;for COM4
  1229. push si ;
  1230. push ds ;
  1231. push ax ;
  1232. mov si,dataOFFSET Comm4 ;
  1233. mov ax, _DATA ;
  1234. mov ds, ax
  1235. ;
  1236. public TickWork ;
  1237. TickWork: ;
  1238. cmp QOutCount[si],wo 00h ;Does queue empty ?
  1239. jz TickNoWork ; Yes : Goto Return
  1240. push dx ;
  1241. call KickTxINT ;
  1242. pop dx ;
  1243. TickNoWork: ;
  1244. pop ax ;
  1245. pop ds ;
  1246. pop si ;
  1247. ret ;
  1248. TickEntry4 endp
  1249. ;----------------------------Private-Routine----------------------------;
  1250. ;
  1251. ; KickTxInt - Kick Transmitter
  1252. ;
  1253. ; "Kick" the transmitter interrupt routine into operation.
  1254. ; If the Transmitter Holding Register isn't empty, then
  1255. ; nothing needs to be done. If it is empty, then the xmit
  1256. ; interrupt needs to enabled in the IER.
  1257. ;
  1258. ; Entry:
  1259. ; DS:SI --> DEB
  1260. ; INTERRUPTS DISABLED!
  1261. ; Returns:
  1262. ; None
  1263. ; Error Returns:
  1264. ; None
  1265. ; Registers Preserved:
  1266. ; BX,CX,SI,DI,DS,ES
  1267. ; Registers Destroyed:
  1268. ; AX,DX,FLAGS
  1269. ; History:
  1270. ;-----------------------------------------------------------------------;
  1271. ;------------------------------Pseudo-Code------------------------------;
  1272. ; {
  1273. ; }
  1274. ;-----------------------------------------------------------------------;
  1275. assumes ds,Data
  1276. assumes es,nothing
  1277. public KickTxInt ;Ins 940923 KBNES
  1278. KickTxInt proc near
  1279. mov dx,Port[si] ;Get device I/O address
  1280. add dl,ACE_IER ;--> Interrupt enable register
  1281. in al,dx ;Get current IER state
  1282. iodelay ;
  1283. test al,ACE_ETBEI ;Interrupt already enabled?
  1284. jnz @F ; Yes, don't reenable it
  1285. or al,ACE_ETBEI ; No, enable it
  1286. out dx,al
  1287. iodelay ;8250, 8250-B bug requires
  1288. out dx,al ; writting register twice
  1289. iodelay ;
  1290. @@:
  1291. ret
  1292. KickTxInt endp
  1293. endif ; NEC_98
  1294. ifdef DEBUG
  1295. public Control, DEF_Handler, COMHandler, APIHandler
  1296. public InterruptLoop, IntLoop10, IntLoop20
  1297. public DataAvail25, DataAvail30, DataAvail50
  1298. public DataAvail60, DataAvail70, DataAvail80, DataAvail90
  1299. public DataAvail100, DataAvail110, DataAvail120
  1300. public DataAvail130, DataAvail140, OutHandshakingChar
  1301. public XmitEmpty10, XmitEmpty20, XmitEmpty30, XmitEmpty40
  1302. public XmitEmpty59, XmitEmpty60
  1303. public XmitEmpty90, XmitEmpty100, XmitEmpty110
  1304. public ModemStatus10, ModemStatus20, ModemStatus30
  1305. public notify_owner, callback_event
  1306. endif
  1307. DOSTI proc near
  1308. FSTI
  1309. ret
  1310. DOSTI endp
  1311. DOCLI proc near
  1312. FCLI
  1313. ret
  1314. DOCLI endp
  1315. sEnd IntCode
  1316. end