home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / ATCOM / ATSUB.ASM < prev    next >
Assembly Source File  |  1995-04-14  |  78KB  |  2,327 lines

  1. ;*DDK*************************************************************************/
  2. ;
  3. ; COPYRIGHT (C) Microsoft Corporation, 1989
  4. ; COPYRIGHT    Copyright (C) 1995 IBM Corporation
  5. ;
  6. ;    The following IBM OS/2 WARP source code is provided to you solely for
  7. ;    the purpose of assisting you in your development of OS/2 WARP device
  8. ;    drivers. You may use this code in accordance with the IBM License
  9. ;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
  10. ;    Copyright statement may not be removed.;
  11. ;*****************************************************************************/
  12. ;       SCCSID = @(#)atsub.asm  6.5 91/11/14
  13. ; ***************************************************************************
  14. ; *
  15. ; *
  16. ; *
  17. ; ***************************************************************************
  18.  
  19.         PAGE    80,132
  20.         .286p
  21.  
  22.         TITLE   com01.sys - Asynchronous Communication Device Driver
  23.         NAME com01
  24.  
  25. ;       Bryan Diehl
  26. ;       David Gilman
  27.  
  28. ;***    atsub.asm
  29. ;
  30. ;       This file contains the support procedures for the AT com
  31. ;       driver.
  32.  
  33. ;       Modification History
  34. ;
  35. ;       DJG     01/06/87        Re-written to conform to MS standard for
  36. ;                               style, clarity and efficiency.
  37. ;       JGT     05/10/88        Add enhanced baud rate support (p587-cpd12)
  38. ;       JGT     06/20/88        Fix     jump     in ComputeHHS (p1037-cpd12)
  39. ;       JGT     06/24/88        Fix inc     in ComputeWTO (p1160 - cpd12)
  40. ;       YN      05/25/89        MVDM Support - @VDM
  41. ;       ACW     04/16/91        @PVW Added perfview counters/timers
  42. ;       JAG     07/29/93        @71491 Fix ComputeHHS for RTS=TOG
  43. ;       RAC     12/7/93         Make Perfview conditional code
  44. ;       RDW     03/30/94        81245 SMC SIO chip cause hang enabling FIFO UART
  45. ;       JAG     01/06/94        @76898 Fix RTS=TOG; need to mask before cmp
  46. ;
  47.  
  48.  
  49.  
  50. include devhlp.inc
  51. include devsym.inc
  52. include basemaca.inc
  53. ;include osmaca.inc
  54. include realmac.inc
  55. include error.inc
  56. include filemode.inc
  57. include atcom.inc
  58. include ateisa.inc
  59. include iodelay.inc
  60. .list
  61.         EXTRN   ClkIntrvl:WORD          ; system clock interval
  62.         EXTRN   Com1:WORD               ; data for Com1
  63.         EXTRN   Com2:WORD               ; data for Com2
  64.         EXTRN   Com3:WORD               ; data for Com3
  65.         EXTRN   Com4:WORD               ; data for Com4
  66.         EXTRN   DevHlp:DWORD            ; device help entry point
  67.         EXTRN   Flags:BYTE
  68.         EXTRN   ShrdIRQ1:BYTE
  69.         EXTRN   Ticker:NEAR
  70.         extrn   CmxGenFail:near
  71.         extrn   CmxInterrupted:near
  72.         extrn   ComRFlushSub:near
  73.         extrn   ComWFlushSub:near
  74.         extrn   cinterr:near
  75.  
  76.  
  77. DSEG    SEGMENT
  78.  
  79. ; DataSegSig is a      so that we can identify our DATA segment.
  80.  
  81. DataSegSig      DW      SIGNATURE
  82.  
  83. ; Ready is a list of request packets which are ready to be run.
  84.  
  85.         PUBLIC  Ready
  86. Ready           RP_List <>
  87.  
  88. ; MaskTab contains masks for the four character sizes that are supported.
  89.  
  90. MaskTab         DB      CHAR_5_MASK
  91.                 DB      CHAR_6_MASK
  92.                 DB      CHAR_7_MASK
  93.                 DB      CHAR_8_MASK
  94.  
  95. ; 16550A HW FIFO RX trigger level encodings
  96. RxTrigTbl       DB      1,4,8,14
  97.  
  98. DSEG    ENDS
  99.  
  100. CSEG    SEGMENT
  101.         ASSUME  cs:CSEG
  102.  
  103. ALIGN 4
  104.  
  105.  
  106. ;**     CheckTX - enable/disable the TX interrupt as appropriate
  107. ;
  108. ;       CheckTX determines if the transmitter should be enabled
  109. ;       or disabled. This determination is based upon the
  110. ;       current state of the driver and the modem control signals.
  111. ;
  112. ;       The transmitter will be enabled if:
  113. ;
  114. ;               - BREAK is NOT set AND
  115. ;                 our output HW handshake lines are high AND
  116. ;                 XON, XOFF or TxImmed is pending
  117. ;
  118. ;               - BREAK is NOT set AND
  119. ;                 our output HW handshake lines are high AND
  120. ;                 XOFF has not been received AND
  121. ;                 (full duplex set OR XOFF has not been sent) AND
  122. ;                 user data is ready to be sent
  123. ;
  124. ;       Otherwise, the transmitter will be disabled
  125. ;
  126. ;       ENTRY   (ds:si) -> ComInfo
  127. ;               Interrupts disabled
  128. ;
  129. ;       EXIT    if 'C' set
  130. ;                       TX interrupt disabled
  131. ;               else
  132. ;                       TX interrupt enabled
  133. ;               Interrupts disabled
  134. ;
  135. ;       USES    ax dx
  136.  
  137. Procedure CheckTX,NEAR
  138.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  139.  
  140.         ChkComInfoPtr
  141.         push    ax
  142.         mov     dx,[si].ci_port
  143.         add     dx,R_INTEN              ; (dx) -> interrupt enable reg
  144.  
  145.                                         ;@VDM start new
  146.                                         ;@VDM if in use by a VDM
  147.         test    [si].ci_vdm_flag,VDM_Flag_InUse
  148.         jz      stx009                  ;@VDM
  149.                                         ;@VDM
  150.         mov     al,[si].ci_msrshadow    ; (al) = msrshadow
  151.         and     al,[si].ci_outhhslines  ; mask bits of interest
  152.         cmp     al,[si].ci_outhhslines
  153.         jne     stx003                  ; modem lines down
  154.  
  155.         cmp     [si].ci_vdm_rx_state,1  ;@VDM are we in state 1?
  156.         jne     stx003                  ;@VDM no, go enable
  157.                                         ;@VDM
  158.         cmp     [si].ci_qout.ioq_count,0;@VDM yes, check if data is in queue
  159.         jne     stx_on                  ;@VDM yes, go enable
  160.                                         ;@VDM
  161. stx003:                                 ;@VDM DISABLE
  162.         jmp     stx_off                 ;@VDM go do disable
  163.                                         ;@VDM
  164. stx009:                                 ;@VDM end new
  165.         call    CheckRTSToggle
  166.  
  167.         mov     dx,[si].ci_port
  168.         add     dx,R_INTEN              ; (dx) -> interrupt enable reg
  169.         mov     ah,[si].ci_hsflag       ; (ah) =  ci_hsflag
  170.  
  171.         test    ah,HS_BREAK_SET
  172.         jnz     stx_off                 ; break being sent
  173.  
  174.         mov     al,[si].ci_msrshadow    ; (al) = msrshadow
  175.         and     al,[si].ci_outhhslines  ; mask bits of interest
  176.         cmp     al,[si].ci_outhhslines
  177.         jne     stx_off                 ; modem lines down
  178.  
  179.         test    ah,HS_XON_PENDING OR HS_XOFF_PENDING OR HS_TX_IMMED
  180.         jnz     stx_on                  ; XON, XOFF or TX_IMMED pending
  181.  
  182.         cmp     [si].ci_w_rp._hi,0
  183.         jz      stx_off                 ; no data enqueued
  184.  
  185. stx10:  test    ah,HS_XOFF_RECEIVED
  186.         jnz     stx_off                 ; XOFF received, can't tx
  187.  
  188.         test    [si].ci_dcb_flags2,F2_FULL_DUP
  189.         jnz     stx_on                  ; full dup, can tx even if XOFF sent
  190.  
  191.         test    ah,HS_XOFF_SENT
  192.         jnz     stx_off                 ; XOFF sent and NOT full dup, can't tx
  193.  
  194. stx_on: ; enable transmit interrupts
  195.  
  196.         min     al,dx                   ; (al) = IER
  197.  
  198.         test    al,IE_TX
  199.         jnz     stxx                    ; TX interrupt already on
  200.  
  201.         or      al,IE_TX                ; enable TX interrupts (clears carry)
  202.         out     dx,al                   ; could cause interrupt to be pending!
  203.         push ax
  204.         DevIODelay ax
  205.         pop  ax
  206.         out     dx,al                   ; write twice for 8250 bug
  207.         jmp     SHORT stxx
  208.  
  209. stx_off:        ; disable transmit interrupts
  210.         min     al,dx                   ; (al) = IER
  211.         and     al,NOT IE_TX            ; disable TX interrupts
  212.         mout    dx,al
  213.         stc
  214.  
  215. stxx:   pop     ax
  216.         ret
  217.  
  218. EndProc CheckTX
  219.  
  220. ;**     CheckRTSToggle - raise/lower RTS for RTS toggling
  221. ;
  222. ;       CheckRTSToggle determines if RTS should be raised of lowered.
  223. ;       This determination is based upon the current state of the
  224. ;       driver and the modem control signals.
  225. ;
  226. ;       RTS will be controlled if RTS toggling is enabled as follows:
  227. ;
  228. ;           RTS will be raised if:
  229. ;               - BREAK is set OR
  230. ;               - XON, XOFF or TxImmed is pending OR
  231. ;               - user data is ready to be sent AND XOFF not sent or received
  232. ;
  233. ;           Otherwise, RTS drop pending will be marked (processed in ticker)
  234. ;
  235. ;       ENTRY   (ds:si) -> ComInfo
  236. ;
  237. ;       EXIT
  238. ;
  239. ;       USES    al dx
  240.  
  241. Procedure CheckRTSToggle,NEAR
  242.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  243.  
  244.         ChkComInfoPtr
  245.  
  246.         ; check for RTS toggling
  247.         mov     al,[si].ci_dcb_flags2
  248.         and     al,F2_RTS_MASK
  249.         cmp     al,F2_RTS_TOGGLE
  250.         jne     crtx                    ; RTS toggling not enabled
  251.  
  252.         mov     dh,[si].ci_hsflag       ; (dh) =  ci_hsflag
  253.  
  254.         test    dh,HS_BREAK_SET
  255.         jnz     crt_on                  ; break being sent
  256.  
  257.         test    dh,HS_XON_PENDING OR HS_XOFF_PENDING OR HS_TX_IMMED
  258.         jnz     crt_on                  ; XON, XOFF or TX_IMMED pending
  259.  
  260.         cmp     [si].ci_w_rp._hi,0
  261.         je      crt_off                 ; no current write request
  262.  
  263.         test    dh,HS_XOFF_RECEIVED
  264.         jnz     crt_off                 ; XOFF received, can't tx
  265.  
  266.         test    [si].ci_dcb_flags2,F2_FULL_DUP
  267.         jnz     crt_on                  ; full dup, can tx even if XOFF sent
  268.  
  269.         test    dh,HS_XOFF_SENT
  270.         jnz      crt_off                 ; XOFF sent and NOT full dup, can't tx
  271.  
  272. crt_on: ; raise RTS
  273.         and     [si].ci_flagx,NOT FX_RTS_DROP_PENDING   ; clear flag
  274.  
  275.         mov     dx,[si].ci_port
  276.         add     dx,R_MODMC              ; (dx) -> modem control reg
  277.         min     al,dx                   ; (al) = MCR
  278.         or      al,MC_RTS               ; turn RTS on
  279.         mout    dx,al
  280.         jmp     SHORT crtx
  281.  
  282. crt_off: ; drop RTS
  283.         mov     dx,[si].ci_port
  284.         add     dx,R_MODMC              ; (dx) -> modem control reg
  285.         min     al,dx                   ; (al) = MCR
  286.         test    al,MC_RTS
  287.         jz      crtx                    ; RTS already down
  288.  
  289.         or      [si].ci_flagx,FX_RTS_DROP_PENDING
  290.                 ; drop RTS at timer tick (ticker) time when
  291.                 ; THR and TSR are empty
  292. crtx:   ret
  293.  
  294. EndProc CheckRTSToggle
  295.  
  296.  
  297. ;**     ComputeAPO - compute automatic priority override
  298. ;
  299. ;       Check cominfo flags and compute the FIFO HW mode (on or off),
  300. ;       the Recieve Trigger Level and the Transmit Buffer Load Count.
  301. ;
  302. ;       ENTRY   (ds:si) -> ComInfo
  303. ;
  304. ;       EXIT    cominfo fields and hardware set
  305. ;
  306. ;       USES    ax dx
  307. ;
  308. ;
  309. ;       if (FIFO == off) {
  310. ;           RX_trig = 1;
  311. ;           TX_cnt  = 1;
  312. ;       }
  313. ;
  314. ;       if (FIFO == on) {
  315. ;           RX_trig = user_RX_trig;
  316. ;           TX_cnt  = user_TX_cnt;
  317. ;       }
  318. ;
  319. ;       if (FIFO == apo) {
  320. ;           if (out_XO || inDSR)
  321. ;               RXtrig = 1
  322. ;           else
  323. ;               RXtrig = 8
  324. ;
  325. ;           if (outCTS || outDSR || outDCD || out_XO)
  326. ;               TXcnt = 1
  327. ;           else
  328. ;               TXcnt = 16
  329. ;       }
  330.  
  331. ; Declare as hybrid so that ESP-specific can call as FAR,
  332. ; and non-ESP code can call as NEAR.
  333. Procedure ComputeAPO,HYBRID
  334.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  335.  
  336.         ChkComInfoPtr
  337.  
  338.         mov     dx,[si].ci_port
  339.         add     dx,R_FIFOC              ; dx -> FIFO control register
  340.  
  341.         .errnz  F3_FIFO_MASK - 00011000b
  342.         .errnz  F3_FIFO_NA   - 00000000b
  343.         .errnz  F3_FIFO_OFF  - 00001000b
  344.         .errnz  F3_FIFO_ON   - 00010000b
  345.         .errnz  F3_FIFO_APO  - 00011000b
  346.  
  347.         mov     al,[si].ci_dcb_flags3   ; al = flags3
  348.         mov     ah,al                   ; ah = flags3
  349.  
  350.         and     ah,F3_FIFO_MASK         ; ah = flags3 fifo mode flags only
  351.         jz      capox                   ; FIFO not available, done
  352.  
  353.         cmp     ah,F3_FIFO_OFF
  354.         je      fifo_off                ; FIFO = OFF, turn fifo HW off
  355.  
  356.         cmp     ah,F3_FIFO_ON
  357.         je      fifo_on                 ; FIFO = ON,  use user values
  358.  
  359.         ; FIFO = APO
  360.         ; compute RX trigger level
  361.         .errnz  F3_RX_MASK - 01100000b
  362.         .errnz  F3_RX_1    - 00000000b
  363.         and     al,NOT (F3_RX_MASK OR F3_TX_16)         ; RX trig = 1
  364.                                                         ; TX cnt  = 1
  365.         test    [si].ci_dcb_flags1,F1_IN_DSR_SENSE
  366.         jnz     capo10                                  ; IN_DSR, RX trig = 1
  367.         test    [si].ci_dcb_flags2,F2_OUT_XO
  368.         jnz     capo10                                  ; OUT_XO, RX trig = 1
  369.  
  370.         or      al,F3_RX_8                              ; RX trig = 8
  371.  
  372. capo10: ; compute TX count
  373.         test    [si].ci_dcb_flags1,F1_OUT_FLOW          ; out CTS, DSR or DCD
  374.         jnz     capo20                                  ; OUT_FLOW, TX cnt = 1
  375.         test    [si].ci_dcb_flags2,F2_OUT_XO
  376.         jnz     capo20                                  ; OUT_XO, TX cnt = 1
  377.  
  378.         or      al,F3_TX_16                             ; TX cnt = 16
  379.  
  380. capo20: mov     [si].ci_dcb_flags3,al                   ; save flags3 value
  381.         ; FALL THROUGH!
  382.  
  383. fifo_on:        ; turn FIFO HW on, set rx trig
  384.         .errnz  FF_RX_MASK - 11000000b
  385.         .errnz  F3_RX_MASK - 01100000b
  386.  
  387. ; 81245 The following code has been added (or modified) to handle defect SMC
  388. ;       UARTs. This code was added per recommendation of SMC Engineering.
  389.  
  390. ; 81245 Check for 16550A (FIFO)
  391.         mov     al, FF_CLEAR_RX OR FF_CLEAR_TX  ; 81245
  392.         mout    dx, al                  ; 81245 try to turn off 16550A FIFOs
  393.  
  394.         add     dx, R_MODMC-R_FIFOC     ; 81245 (dx) -> MCR
  395.         min     al, dx                  ; 81245 Get current value of MCR
  396.         or      al, MC_LOOP             ; 81245 Set loopback ON to clear THR
  397.  
  398.         mout    dx, al                  ; 81245
  399.         add     dx, R_DATA-R_MODMC      ; 81245 (dx) -> RBR
  400.         min     al, dx                  ; 81245 Clear the 1 byte RBR
  401.  
  402. ; 81245 At this point, we don't have to worrt about clearing the loop back
  403. ;       in the MCR as we will do this later when we clear the MCR.
  404.  
  405.         add     dx, R_FIFOC             ; 81245 (dx) -> FCR
  406.         mov     al, FF_CLEAR_RX OR FF_CLEAR_TX ; 81245 restore (al)
  407.  
  408.         and     al,F3_RX_MASK           ; al = RX trigger level from flags3
  409.         shl     al,1                    ; al = RX trigger level bits for FIFO
  410.         or      al,FF_ENABLE
  411.         mout    dx,al                   ; send data to FIFO control reg
  412.  
  413.         add     dx, R_MODMC-R_FIFOC     ; 81245 (dx) -> MCR
  414.         min     al, dx                  ; 81245 Get current MCR
  415.         and     al, NOT MC_LOOP         ; 81245 Clear the LOOP back bit
  416.         mout    dx, al                  ; 81245
  417.         jmp     short capox
  418.  
  419. fifo_off:       ; turn FIFO HW off
  420.         and     [si].ci_dcb_flags3,NOT (F3_RX_MASK OR F3_TX_16)
  421.         xor     al,al                   ; al = 0 (disable FIFO)
  422.         mout    dx,al                   ; send data to FIFO control reg
  423.  
  424. capox:  ret
  425.  
  426. EndProc ComputeAPO
  427.  
  428.  
  429. ;**     ProcBlockNI - block the current thread non-interruptably
  430. ;**     ProcBlock   - block the current thread interruptably
  431. ;
  432. ;       ProcBlock blocks the calling thread using the
  433. ;       virtual address of its request packet as the key.
  434. ;       Callers specify the appropriate timeout.
  435. ;
  436. ;       ENTRY   (es:di) -> tiled request packet
  437. ;               dx:cx = time out value in milliseconds
  438. ;               Interrupts disabled (usually)
  439. ;
  440. ;       EXIT    'C' clear ProcRun caused wakeup
  441. ;               'C' set
  442. ;                       'Z' flag clear if interrupted
  443. ;                       'Z' set if timed out
  444. ;               Interrupts enabled
  445. ;
  446. ;       USES    ax bx
  447.  
  448. Procedure ProcBlockNI,NEAR
  449.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  450.  
  451.         mov     bx,(0100h OR DevHlp_ProcBlock)  ; bx = ProcBlock non-interrupt
  452.         jmp     SHORT pb10
  453.  
  454. Entry   ProcBlock,,,nocheck
  455.  
  456.         mov     bx,(0000h OR DevHlp_ProcBlock)  ; bx = ProcBlock interrupt
  457.  
  458. pb10:   ChkRPPtr
  459.  
  460.         mov     ax,es
  461.         xchg    bx,di                   ; ax:bx => request packet
  462.                                         ; di = ProcBlock + flag
  463.  
  464.         xchg    di,dx                   ; di:cx = time out
  465.                                         ; dx = ProcBlock + flag
  466.         DevHelp                         ; block (enables interrupts)
  467.  
  468.         xchg    di,dx                   ; dx:cx = time out
  469.         xchg    bx,di                   ; (es:di) -> RP
  470.  
  471.         ChkRPPtr
  472.  
  473.         pushf                   ; save DevHlp_ProcBlock return codes
  474.         test    Flags,F_SHUT_DOWN
  475.         jz      pbx             ; driver not shut down, OK
  476.  
  477.         jmp     CmxGenFail      ; driver is shut down, fail all requests
  478.  
  479. pbx:    popf                    ; restore DevHlp_ProcBlock return codes
  480.         ret
  481.  
  482. EndProc ProcBlockNI
  483.  
  484.  
  485. ;**     ProcRun - run the current thread
  486. ;
  487. ;       ProcRun runs the thread that owns the request packet pointed
  488. ;       to by the virtual address in (es:di).
  489. ;       ProcRun also sets the STDON bit in the request packet status field.
  490. ;
  491. ;       ENTRY   (es:di) -> tiled request packet
  492. ;
  493. ;       EXIT    NONE
  494. ;
  495. ;       USES    ax bx dx
  496.  
  497. ; Declare as hybrid so that ESP-specific can call as FAR,
  498. ; and non-ESP code can call as NEAR.
  499. Procedure ProcRun,HYBRID
  500.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  501.  
  502.         ChkRPPtr
  503.  
  504.         or      es:[di].PktStatus,STDON         ; set STDON bit
  505.  
  506.         mov     ax,es
  507.         mov     bx,di                   ; ax:bx => request packet
  508.  
  509.         mov     dl,DevHlp_ProcRun
  510.         DevHelp                         ; run (enables interrupts)
  511.  
  512.         ret
  513.  
  514. EndProc ProcRun
  515.  
  516.  
  517. ;**     DisableRemoteTX - disable the remote transmissions
  518.  
  519. ;       DisableRemoteTX disables the remote transmitter using whatever
  520. ;       handshaking mode(s) are currently active. That is, it will disable
  521. ;       the hardware handshake lines and/or send an XOFF character.
  522. ;
  523. ;       ENTRY   (ds:si) -> ComInfo
  524. ;
  525. ;       EXIT    interrupts enabled
  526. ;
  527. ;       USES    ax dx
  528.  
  529. Procedure DisableRemoteTX,NEAR
  530.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  531.  
  532.         ChkComInfoPtr
  533.  
  534.         mov     ah,[si].ci_hhslines     ; (ah) = hardware handshake lines
  535.  
  536.         cli
  537.  
  538.         or      ah,ah                   ; check for any input HS lines up
  539.         jz      drt4                    ; no handshake lines to disable
  540.  
  541.         call    DisableRemoteTXHS       ;cj go lower HS lines
  542.  
  543. drt4:   test    [si].ci_dcb_flags2,F2_IN_XO     ; input flow enabled?
  544.         jz      drtx                            ; input XON/XOFF disabled
  545.  
  546.         call    DisableRemoteTXXO       ;cj go send XOFF
  547.  
  548.         call    CheckTX                 ; attempt to enable TXer
  549.  
  550. drtx:   sti
  551.  
  552.         ret
  553.  
  554. EndProc DisableRemoteTX
  555.  
  556. ;********************** START OF SPECIFICATIONS *********************
  557. ;*
  558. ;*  SUBROUTINE NAME:    DisableRemoteTXHS
  559. ;*
  560. ;*  DESCRIPTIVE NAME:   Lower input handshaking lines
  561. ;*
  562. ;*  FUNCTION:   Set Modem Control to disable input HS lines.
  563. ;*
  564. ;*  ENTRY POINT:  DisableRemoteTXHS
  565. ;*
  566. ;*  LINKAGE:    Near
  567. ;*
  568. ;*  USES:       AX
  569. ;*
  570. ;*  INPUT:      DS:SI -> ComInfo data area
  571. ;*
  572. ;*  OUTPUT:     none
  573. ;*
  574. ;*  EXIT-NORMAL: none
  575. ;*
  576. ;*  EXIT_ERROR:  none
  577. ;*
  578. ;*  EFFECTS:   ComInfo data area
  579. ;*
  580. ;*  INTERNAL REFERENCES:
  581. ;*      None
  582. ;*
  583. ;*  EXTERNAL REFERENCES: none
  584. ;*
  585. ;*********************** END OF SPECIFICATIONS **********************
  586.  
  587. Procedure DisableRemoteTXHS,HYBRID
  588.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  589.  
  590.         mov     ah,[si].ci_hhslines     ;cj (ah) = hardware handshake lines
  591.         mov     dx,[si].ci_port         ;cj
  592.         add     dx,R_MODMC              ;cj (dx) -> modem control reg.
  593.         min     al,dx                   ;cj (al) = current MCR values
  594.         not     ah                      ;cj (ah) = hardware lines to disable
  595.         and     al,ah                   ;cj turn off hardware handshake lines
  596.         mout    dx,al                   ;cj
  597.  
  598.         ret                             ;cj
  599.  
  600. EndProc DisableRemoteTXHS
  601.  
  602. ;********************** START OF SPECIFICATIONS *********************
  603. ;*
  604. ;*  SUBROUTINE NAME:    DisableRemoteTXXO
  605. ;*
  606. ;*  DESCRIPTIVE NAME:   Send XOFF
  607. ;*
  608. ;*  FUNCTION:   Sends XOFF if not previously sent
  609. ;*
  610. ;*  ENTRY POINT:  DisableRemoteTXXO
  611. ;*
  612. ;*  LINKAGE:    Near
  613. ;*
  614. ;*  USES:       AX
  615. ;*
  616. ;*  INPUT:      DS:SI -> ComInfo data area
  617. ;*
  618. ;*  OUTPUT:     none
  619. ;*
  620. ;*  EXIT-NORMAL: none
  621. ;*
  622. ;*  EXIT_ERROR:  none
  623. ;*
  624. ;*  EFFECTS:   ComInfo data area
  625. ;*
  626. ;*  INTERNAL REFERENCES:
  627. ;*      None
  628. ;*
  629. ;*  EXTERNAL REFERENCES: none
  630. ;*
  631. ;*********************** END OF SPECIFICATIONS **********************
  632.  
  633. Procedure DisableRemoteTXXO,HYBRID
  634.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  635.  
  636.         mov     al,[si].ci_hsflag               ;cj (al) = handshake flag
  637.         test    al,HS_XON_PENDING               ;cj is XON pending?
  638.         jz      drtxo5                          ;cj XON not pending
  639.  
  640.         and     [si].ci_hsflag,NOT HS_XON_PENDING     ;cj don't send the XON
  641.         jmp     SHORT drtxxo                          ;cj in effect send XOFF
  642.  
  643. drtxo5: test    al,HS_XOFF_SENT                 ;cj was XOFF sent?
  644.         jnz     drtxxo                          ;cj XOFF already sent
  645.  
  646.         or      [si].ci_hsflag,HS_XOFF_PENDING  ;cj show XOFF must be sent
  647. drtxxo:
  648.         ret                                     ;cj
  649.  
  650. EndProc DisableRemoteTXXO
  651.  
  652.  
  653. ;**     EnableRemoteTX - enable the remote transmissions
  654. ;
  655. ;       EnableRemoteTX enables the remote transmitter using whatever
  656. ;       handshaking mode(s) are currently active. That is, it will enable
  657. ;       the hardware handshake lines and/or send an XON character.
  658. ;
  659. ;       ENTRY   (ds:si) -> ComInfo
  660. ;
  661. ;       EXIT    interrupts enabled
  662. ;
  663. ;       USES    ax dx
  664.  
  665. ; Declare as hybrid so that ESP-specific can call as FAR,
  666. ; and non-ESP code can call as NEAR.
  667. Procedure EnableRemoteTX,HYBRID
  668.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  669.  
  670.         ChkComInfoPtr
  671.  
  672.         mov     ah,[si].ci_hhslines     ; (ah) = hardware handshake lines
  673.         cli
  674.         or      ah,ah                   ; check for HS lines to enable
  675.         jz      ert4                    ; no handshake lines to enable
  676.  
  677.         call    EnableRemoteTXHS        ;cj go raise HS lines
  678.  
  679. ert4:   test    [si].ci_dcb_flags2,F2_IN_XO   ; is input flow control enabled?
  680.         jz      ertx                          ; jump if not
  681.  
  682.         call    EnableRemoteTXXO        ;cj go send XON
  683.  
  684.         call    CheckTX                 ; enable TX
  685.  
  686. ertx:   sti
  687.  
  688.         ret
  689.  
  690. EndProc EnableRemoteTX
  691.  
  692. ;********************** START OF SPECIFICATIONS *********************
  693. ;*
  694. ;*  SUBROUTINE NAME:    EnableRemoteTXHS
  695. ;*
  696. ;*  DESCRIPTIVE NAME:   Raise input handshaking lines
  697. ;*
  698. ;*  FUNCTION:   Set Modem Control to enable input HS lines.
  699. ;*
  700. ;*  ENTRY POINT:  EnableRemoteTXHS
  701. ;*
  702. ;*  LINKAGE:    Near
  703. ;*
  704. ;*  USES:       AX
  705. ;*
  706. ;*  INPUT:      DS:SI -> ComInfo data area
  707. ;*
  708. ;*  OUTPUT:     none
  709. ;*
  710. ;*  EXIT-NORMAL: none
  711. ;*
  712. ;*  EXIT_ERROR:  none
  713. ;*
  714. ;*  EFFECTS:   ComInfo data area
  715. ;*
  716. ;*  INTERNAL REFERENCES:
  717. ;*      None
  718. ;*
  719. ;*  EXTERNAL REFERENCES: none
  720. ;*
  721. ;*********************** END OF SPECIFICATIONS **********************
  722.  
  723. Procedure EnableRemoteTXHS,HYBRID
  724.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  725.  
  726.         mov     ah,[si].ci_hhslines     ;cj (ah) = hardware handshake lines
  727.         mov     dx,[si].ci_port         ;cj
  728.         add     dx,R_MODMC              ;cj (dx) -> modem control reg.
  729.         min     al,dx                   ;cj (al) = current MCR values
  730.         or      al,ah                   ;cj turn on hardware handshake lines
  731.         mout    dx,al                   ;cj
  732.  
  733.         ret                             ;cj
  734.  
  735. EndProc EnableRemoteTXHS
  736.  
  737. ;********************** START OF SPECIFICATIONS *********************
  738. ;*
  739. ;*  SUBROUTINE NAME:    EnableRemoteTXXO
  740. ;*
  741. ;*  DESCRIPTIVE NAME:   Enable the remote transmissions
  742. ;*
  743. ;*  FUNCTION:   If XOFF was previously sent, send XON.
  744. ;*
  745. ;*  ENTRY POINT:  EnableRemoteTXXO
  746. ;*
  747. ;*  LINKAGE:    Near
  748. ;*
  749. ;*  USES:       AX
  750. ;*
  751. ;*  INPUT:      DS:SI -> ComInfo data area
  752. ;*
  753. ;*  OUTPUT:     none
  754. ;*
  755. ;*  EXIT-NORMAL: none
  756. ;*
  757. ;*  EXIT_ERROR:  none
  758. ;*
  759. ;*  EFFECTS:   ComInfo data area
  760. ;*
  761. ;*  INTERNAL REFERENCES:
  762. ;*
  763. ;*  EXTERNAL REFERENCES: none
  764. ;*
  765. ;*********************** END OF SPECIFICATIONS **********************
  766.  
  767. Procedure EnableRemoteTXXO,HYBRID
  768.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  769.  
  770.         and     [si].ci_hsflag,NOT HS_XOFF_PENDING ;cj turn off any XOFF pending
  771.         test    [si].ci_hsflag,HS_XOFF_SENT        ;cj was XOFF sent?
  772.         jz      ertxxo                             ;cj no jump
  773.         or      [si].ci_hsflag,HS_XON_PENDING      ;cj XON must be sent
  774.  
  775. ertxxo:
  776.         ret                                        ;cj
  777.  
  778. EndProc EnableRemoteTXXO
  779.  
  780.  
  781. ;**     ComputeHHS - compute hardware handshake signals
  782. ;
  783. ;       ComputeHHS performs a number of functions pertaining to
  784. ;       the setting of the hardware handshake lines.
  785. ;
  786. ;       May raise or lower DTR or RTS depending on flags1 and flags2
  787. ;       and the previous values of flags1 and flgas2.
  788. ;
  789. ;       Set hhslines and outhhslines depending on flags1 and flags2.
  790. ;
  791. ;       ENTRY   (ds:si) -> ComInfo
  792. ;               (bl) = previous flags1
  793. ;               (bh) = previous flags2
  794. ;
  795. ;       EXIT
  796. ;
  797. ;       USES    ax bx dx
  798.  
  799. ; Declare as hybrid so that ESP-specific can call as FAR,
  800. ; and non-ESP code can call as NEAR.
  801. Procedure ComputeHHS,HYBRID
  802.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  803.  
  804.         ChkComInfoPtr
  805.  
  806.  
  807.         ; Standard port: raise/lower RTS/DTR.
  808. chh10:
  809.         and     bl,F1_DTR_MASK                  ; old DTR bits from flags1
  810.         and     bh,F2_RTS_MASK                  ; old RTS bits from flags2
  811.  
  812.         mov     dx,[si].ci_port
  813.         add     dx,R_MODMC              ; (dx) -> modem control reg
  814.         min     al,dx                   ; al = current modem control lines
  815.         and     al,MC_DTR OR MC_RTS     ; mask bits of interest
  816.         or      al,MC_OUT2              ; must be set to get interrupts on AT
  817.  
  818.  
  819.         ; DTR processing
  820.         .errnz  F1_DTR_DISABLE - 00000000b
  821.         .errnz  F1_DTR_ENABLE  - 00000001b
  822.         .errnz  F1_DTR_FLOW    - 00000010b
  823.         .errnz  F1_DTR_INVALID - 00000011b
  824.         .errnz  MC_DTR         - 00000001b
  825.  
  826.         mov     ah,[si].ci_dcb_flags1           ; ah = flags1
  827.         and     ah,F1_DTR_MASK                  ; new DTR bits
  828.         xchg    ah,bl                           ; bl = flags1
  829.         cmp     ah,bl
  830.         je      chh20                           ; no change to DTR
  831.  
  832.         test    bl,F1_DTR_FLOW
  833.         jnz     chh20                           ; handshake line
  834.  
  835.         and     al,NOT MC_DTR                   ; clear DTR line
  836.         or      al,bl                           ; raise DTR if enable
  837.  
  838.  
  839. chh20:  ; RTS processing
  840.         .errnz  F2_RTS_DISABLE - 00000000b
  841.         .errnz  F2_RTS_ENABLE  - 01000000b
  842.         .errnz  F2_RTS_FLOW    - 10000000b
  843.         .errnz  F2_RTS_TOGGLE  - 11000000b
  844.         .errnz  MC_RTS         - 00000010b
  845.  
  846.         mov     ah,[si].ci_dcb_flags2           ; ah = flags2
  847.         and     ah,F2_RTS_MASK                  ; new RTS bits
  848.         xchg    ah,bh                           ; bh = flags2
  849.         cmp     ah,bh
  850.         je      chh40                           ; no change to RTS
  851.  
  852.         cmp    bh,F2_RTS_FLOW                   ;                @71491
  853.         jz     chh40                            ; handshake line @71491
  854.  
  855.         and     al,NOT MC_RTS                   ; clear RTS line
  856.         rol     bh,3                            ; shift RTS enable into MC_RTS
  857.         or      al,bh                           ; raise RTS if enable
  858.         ror     bh,3                            ; shift RTS enable back
  859.  
  860.  
  861. chh40:  mout    dx,al                           ; set modem control reg
  862.  
  863.  
  864. chh50:
  865. ; Both standard and enhanced set handshake flags -- though only standard
  866. ; uses them for handshaking.
  867. ; Set input handshaking based on the values of DTR and RTS in ci_dcb_flags2.
  868.         .errnz  F1_DTR_FLOW - 00000010b
  869.         .errnz  F2_RTS_FLOW - 10000000b
  870.         .errnz       MC_DTR - 00000001b
  871.         .errnz       MC_RTS - 00000010b
  872.  
  873.         xor     al,al
  874.         test    [si].ci_dcb_flags1,F1_DTR_FLOW   ;CP20PB727400
  875.         jz      chh60                            ;CP20PB727400
  876.  
  877.         or      al,MC_DTR
  878.  
  879. chh60:
  880.         mov     ah,[si].ci_dcb_flags2           ; ah = flags2  @76898
  881.         and     ah,F2_RTS_MASK                  ; new RTS bits @76898
  882.         cmp     ah,F2_RTS_FLOW                  ;CP20PB727400  @71491
  883.         jnz     chh80                           ;CP20PB727400  @71491
  884.  
  885.         or      al,MC_RTS
  886.  
  887. chh80:  mov     [si].ci_hhslines,al
  888.  
  889.  
  890. ; Set output handshaking for DSR, CTS and DCD from ci_dcb_flags1.
  891.  
  892.         .errnz  F1_OUT_CTS_FLOW - 00001000b
  893.         .errnz  F1_OUT_DSR_FLOW - 00010000b
  894.         .errnz  F1_OUT_DCD_FLOW - 00100000b
  895.         .errnz           MS_CTS - 00010000b
  896.         .errnz           MS_DSR - 00100000b
  897.         .errnz           MS_DCD - 10000000b
  898.  
  899.         mov     al,[si].ci_dcb_flags1
  900.         shl     ax,3                            ; d8 = DCD, d7 = DSR, d6 = CTS
  901.         shr     al,1                            ; d8 = DCD, d6 = DSR, d5 = CTS
  902.         shr     ax,1                            ; d7 = DCD, d5 = DSR, d4 = CTS
  903.         and     al,MS_DCD OR MS_DSR OR MS_CTS    ; mask bits of interest
  904.         mov     [si].ci_outhhslines,al
  905.  
  906.         ret
  907.  
  908. EndProc ComputeHHS
  909.  
  910. ;********************** START OF SPECIFICATIONS *********************
  911. ;*
  912. ;* SUBROUTINE NAME:  SetAlert
  913. ;*
  914. ;* DESCRIPTIVE NAME:  Set the SNA Generic Alert Flags
  915. ;*
  916. ;* FUNCTION:  Sets the SNA Generic Alert Flags (in ci_flagGA).  Checks
  917. ;*            the Hardware Handshake mode and the MSR bits (in the
  918. ;*            ComInfo MSR Shadow.
  919. ;*
  920. ;* NOTES:     ABIOS MUST BE PRESENT
  921. ;*            Called by WriteTick on Write TimeOut - ** INTs Disabled **
  922. ;*
  923. ;* ENTRY POINTS:  SetAlert
  924. ;*    LINKAGE:    Near CALL
  925. ;*
  926. ;* INPUT:     DS:SI --> ComInfo data area for this port
  927. ;*            ES:DI --> RequestPkt address
  928. ;*
  929. ;* EXIT-NORMAL: none
  930. ;*
  931. ;* EXIT_ERROR:  none
  932. ;*
  933. ;* EFFECTS:   Registers:  AX, BX, CX
  934. ;*            ComInfo data area  (ci_flagGA)
  935. ;*
  936. ;*            ci_flagGA  BIT DEFINITIONS:
  937. ;*              FGA_WRITE_TO_CTS        EQU     0000000000000001
  938. ;*              FGA_WRITE_TO_DSR        EQU     0000000000000010
  939. ;*              FGA_WRITE_TO_DCD        EQU     0000000000000100
  940. ;*              FGA_WRITE_TO_XOFF       EQU     0000000000001000
  941. ;*
  942. ;* INTERNAL REFERENCES: none
  943. ;*
  944. ;* EXTERNAL REFERENCES: none
  945. ;*
  946. ;*********************** END OF SPECIFICATIONS **********************
  947.  
  948.  
  949. Procedure SetAlert,NEAR
  950.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  951.  
  952. ;**  We know there is a Write Timeout on entry - now find out why.
  953. ;    We also know INTs are DISABLED, so that no modem INTs can occur here.
  954.         push    cx
  955.         xor     cx,cx                           ; prepare temp flagGA word
  956.  
  957.         mov     al,[si].ci_dcb_flags1           ; load 1st DCB flag word
  958.         mov     dl,[si].ci_msrshadow            ; load MSR shadow from CIDA
  959.         test    al,F1_OUT_CTS_FLOW              ; CTS output handshaking on?
  960.         jz      trydsr                          ; no, go check DSR
  961.  
  962.         test    dl,MS_CTS                       ; is CTS down now?
  963.         jnz     trydsr                          ; no, go check DSR
  964.  
  965.         or      cx,FGA_WRITE_TO_CTS             ; Yes, so set CTS Alert bit
  966.  
  967. trydsr:
  968.         test    al,F1_OUT_DSR_FLOW              ; DSR output handshaking on?
  969.         jz      trydcd                          ; no, go check DCD
  970.  
  971.         test    dl,MS_DSR                       ; is DSR down now?
  972.         jnz     trydcd                          ; no, go check DCD
  973.  
  974.         or      cx,FGA_WRITE_TO_DSR             ; Yes, so set DSR Alert bit
  975.  
  976. trydcd:
  977.         test    al,F1_OUT_DCD_FLOW              ; DCD output handshaking on?
  978.         jz      tryxoff                         ; no, go check XOFF
  979.  
  980.         test    dl,MS_DCD                       ; is DCD down now?
  981.         jnz     tryxoff                         ; no, go check XOFF
  982.  
  983.         or      cx,FGA_WRITE_TO_DCD             ; Yes, so set DCD Alert bit
  984.  
  985. tryxoff:
  986.         mov     al,[si].ci_dcb_flags2           ; load 2nd DCB flag word
  987.         test    al,F2_OUT_XO                    ; XON/XOFF flow control on?
  988.         jz      sax                             ; no, go to exit
  989.  
  990.         test    [si].ci_hsflag,HS_XOFF_RECEIVED ; Was XOFF received?
  991.         jz      sax                             ; no, go to exit
  992.  
  993.         or      cx,FGA_WRITE_TO_XOFF            ; Yes, so set XOFF Alert bit
  994.  
  995. sax:    mov     [si].ci_flagGA,cx               ; save the alert flags
  996.         pop     cx
  997.         ret                                     ; and return
  998.  
  999. EndProc SetAlert
  1000.  
  1001. ;**     SetLineC - set the line control values
  1002. ;
  1003. ;       SetLineC sets the byte size, parity and number of stop bits
  1004. ;       according to the value in (al).
  1005. ;
  1006. ;       ENTRY   (ds:si) -> ComInfo
  1007. ;               (al) = new LCR value
  1008. ;
  1009. ;       EXIT
  1010. ;
  1011. ;       USES    al bx dx
  1012.  
  1013. ; Declare as hybrid so that ESP-specific can call as FAR,
  1014. ; and non-ESP code can call as NEAR.
  1015. Procedure SetLineC,HYBRID
  1016.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1017.  
  1018.         ChkComInfoPtr
  1019.  
  1020.         and     al,LC_MASK              ; clear divisor latch bit in new LCR
  1021.  
  1022.         mov     dx,[si].ci_port
  1023.         add     dx,R_LINEC              ; (dx) = line control reg.
  1024.         mout    dx,al                   ; set LCR
  1025.  
  1026.         ; Now update ComInfo block
  1027. sl20:   mov     [si].ci_linec,al        ; save new LCR value
  1028.         mov     bx,ax
  1029.         and     bx,LC_BMASK             ; (bx) = byte size - 5
  1030.         mov     al,MaskTab[bx]          ; (al) = byte mask
  1031.         mov     [si].ci_cmask,al        ; save new byte mask
  1032.  
  1033.         ret
  1034.  
  1035. EndProc SetLineC
  1036.  
  1037.  
  1038. ;**     CheckLCR - check the line control configuration
  1039. ;
  1040. ;       CheckLCR verifies the validity of the three line control
  1041. ;       parameters, character size, number of stop bits and parity.
  1042. ;       If the values are valid the new LCR is returned in (al).
  1043. ;
  1044. ;       ENTRY   (al) = byte size
  1045. ;               (ah) = parity
  1046. ;               (ch) = stop bits
  1047. ;               ds:si -> ComInfo
  1048. ;
  1049. ;       EXIT    if 'C' clear
  1050. ;                       (al) = value for line control reg
  1051. ;               else 'C' set
  1052. ;                       invalid line control
  1053. ;
  1054. ;       USES    ax cx
  1055.  
  1056. ; Declare as hybrid so that ESP-specific can call as FAR,
  1057. ; and non-ESP code can call as NEAR.
  1058. Procedure CheckLCR,HYBRID
  1059.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1060.  
  1061. ; Set up byte size.
  1062.  
  1063.         cmp     al,8
  1064.         ja      clcrx                   ; byte size out of range
  1065.  
  1066.         sub     al,5                    ; shift byte size to bits 0 and 1
  1067.         .errnz  LC_BMASK-00000011b      ; byte size must be these bits
  1068.         jc      clcrx                   ; byte size out of range
  1069.  
  1070. ; al == 0, 5 data bits
  1071. ; al == 1, 6 data bits
  1072. ; al == 2, 7 data bits
  1073. ; al == 3, 8 data bits
  1074.  
  1075. ; Set up number of stop bits.
  1076. ; ch == 0, 1 stop bits
  1077. ; ch == 1, 1.5 stop bits if byte size is 5
  1078. ; ch == 2, 2 stop bits if byte size is not 5
  1079.  
  1080.         or      ch,ch
  1081.         jz      clcr2                   ; 1 stop bit
  1082.  
  1083.         dec     ch
  1084.         jz      clcr0                   ; 1.5 stop bits
  1085.  
  1086.         dec     ch
  1087.         jnz     clcrx                   ; invalid number of stop bits
  1088.  
  1089.         or      al,al
  1090.         jz      clcrx                   ; 5 bit byte, 2 stop bits are invalid
  1091.         jmp     SHORT clcr1             ; not 5 bit byte, 2 stop bits is valid
  1092.  
  1093. clcr0:  or      al,al
  1094.         jnz     clcrx                   ; 1.5 stop with 6, 7 or 8 bit invalid
  1095.  
  1096. clcr1:  or      al,LC_STOP2             ; 1.5 or 2 stop bits
  1097.  
  1098.         .errnz  ONE_STOP_BIT-0
  1099.         .errnz  ONE_5_STOP_BITS-1
  1100.         .errnz  TWO_STOP_BITS-2
  1101.         .errnz  LC_BITS5
  1102.  
  1103. ; Set up parity.
  1104.  
  1105. clcr2:  cmp     ah,SPACE_PARITY
  1106.         ja      clcrx                   ; parity out of range
  1107.  
  1108.         add     ah,ah                   ; map parity to 16450 ACE bits
  1109.         jz      clcr3                   ; 0=>0, 1=>1, 2=>3, 3=>5, 4=>7
  1110.         dec     ah
  1111.  
  1112. clcr3:  shl     ah,3                    ; Align with 16450 parity bits
  1113.         or      al,ah                   ; or into byte size
  1114.  
  1115.         .errnz  NO_PARITY-0
  1116.         .errnz       ODD_PARITY-1
  1117.         .errnz  EVEN_PARITY-2
  1118.         .errnz  MARK_PARITY-3
  1119.         .errnz  SPACE_PARITY-4
  1120.  
  1121.         ret
  1122.  
  1123. clcrx:  stc                             ; invalid LCR value
  1124.         ret
  1125.  
  1126. EndProc CheckLCR
  1127.  
  1128.  
  1129. ;**     SetBaud - set the baud rete
  1130. ;
  1131. ;       SetBaud verifies that the baud rate is within the valid
  1132. ;       baud range and can be supported within +-.01% (except 110
  1133. ;       baud @ +.026% error, and 2000 baud @ -.69% error)
  1134. ;       Converts the baud rate into the format necesary
  1135. ;       by the hardware and sets the rate.
  1136. ;       Also calls ComputeRTO and ComputeWTO to recalculate the timeouts.
  1137. ;
  1138. ;       ENTRY   (ds:si) -> ComInfo
  1139. ;               (ax) = baud rate
  1140. ;
  1141. ;       EXIT    if 'C' clear
  1142. ;                       ci_baud = baud rate
  1143. ;                       divisor latch set in hardware
  1144. ;               else
  1145. ;                       invalid baud rate
  1146. ;
  1147. ;       USES    ax bx cx dx flags
  1148.  
  1149. ; Declare as hybrid so that ESP-specific can call as FAR,
  1150. ; and non-ESP code can call as NEAR.
  1151. Procedure SetBaud,HYBRID
  1152.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1153.  
  1154.         ChkComInfoPtr
  1155.  
  1156. ; verify within range of valid bauds
  1157.         cmp     ax,MINBAUD
  1158.         ljb     sberr                   ; invalid baud rate
  1159.         mov     bx,MAX_SBAUD            ; assume max baud for standard port
  1160.  
  1161. sb10:   cmp     ax,bx
  1162.         lja     sberr                   ; invalid baud rate
  1163.  
  1164.         ; convert baud rate to divisor and remainder
  1165.         mov     bx,ax                   ; (bx) = baud rate
  1166.         mov     dx,CLOCK_RATEHI         ; 
  1167.         mov     ax,CLOCK_RATELO         ; (dx:ax) = clock rate
  1168.         div     bx                      ; (ax) = divisor = clock / baud
  1169.                                         ; (dx) = remainder
  1170.         mov     cx,ax                   ; (cx) = divisor
  1171.  
  1172. ; special case to allow 110 baud without checking remainder
  1173.         cmp     bx,110
  1174.         je      sb50                    ; 110 baud, ok
  1175.  
  1176. ; verify that the baud rate can be supported within .01% by
  1177. ; checking that the remainder is within the threshold
  1178.         cmp     dx,MAXREM
  1179.         jbe     sb50                    ; remainder within threshold, ok
  1180.  
  1181. ; remainder too large on + side.  try on minus side
  1182.         inc     cx                      ; (cx) = divisor + 1
  1183.         mov     ax,cx                   ; (ax) = divisor + 1
  1184.         mul     bx                      ; (dx:ax) = (divisor+1) * baud
  1185.  
  1186. ; special case to allow 2000 baud without checking remainder
  1187. ; (must be done here cuz 2000 is closer on the minus side!)
  1188.         cmp     bx,2000
  1189.         je      sb50                    ; 2000 baud, ok
  1190.  
  1191.         sub     ax,CLOCK_RATELO         ; 
  1192.         sbb     dx,CLOCK_RATEHI         ; (dx:ax) = (divisor+1) * baud - clock
  1193.                                         ;         = remainder
  1194.         ljnz    sberr                   ; remainder high not zero, invalid baud
  1195.         cmp     ax,MAXREM
  1196.         lja     sberr                   ; remainder too large, invalid baud
  1197.  
  1198. sb50:   ; the baud is ok.  (cx) = divisor
  1199.  
  1200.  
  1201. ; If standard port, set divisor-latch access bit (DLAB) in line control reg.
  1202.         pushf                           ; save flags
  1203.         cli                             ; disable interrupts while setting baud
  1204.  
  1205.         mov     dx,[si].ci_port
  1206.         add     dx,R_LINEC              ; (dx) -> LCR
  1207.         min     al,dx                   ; (al) = current value of LCR
  1208.         mov     ah,al                   ; save original state of LCR
  1209.         or      al,LC_DLAB              ; turn on DLAB
  1210.         mout    dx,al
  1211.  
  1212. ; Set divisor-latch value.
  1213. ; (dx) -> R_LINEC
  1214.  
  1215.         add     dx,R_BAUDH-R_LINEC      ; (dx) -> MSB of baud latch
  1216.         mov     al,ch                   ; (al) = divisor latch MSB
  1217.         mout    dx,al
  1218.         dec     dx                      ; (dx) -> LSB of baud latch
  1219.         mov     al,cl                   ; (al) = divisor latch LSB
  1220.         mout    dx,al                   ; set LSB of baud latch
  1221.  
  1222. ; Restore original state of LCR (turn off DLAB)
  1223. ; (dx) -> R_BAUDL
  1224.  
  1225.         add     dx,R_LINEC-R_BAUDL      ; (dx) -> LCR
  1226.         mov     al,ah                   ; (al) = original state of LCR
  1227.         mout    dx,al
  1228.  
  1229.         mov     ax,bx                   ; (ax) = baud
  1230.         mov     [si].ci_baud,ax         ; ci_baud = baud
  1231.  
  1232.         test    [si].ci_mult_COMs_IRQ, INT_SHARING ; sharing this IRQ line?
  1233.                                         ;  with another COM port?
  1234.         jz      sb60                    ; N: continue
  1235.         or      [si].ci_Flagx1,FX1_SET_BAUD_IP  ; Y: set "in progress" flag
  1236.         call    DeqComInfo              ; Y: remove COM port from linked list
  1237.         call    EnqComInfo              ; then put it back in baud rate order
  1238.         and     [si].ci_Flagx1,NOT FX1_SET_BAUD_IP ; clear "in progress" flag
  1239.  
  1240. sb60:
  1241.         call    ComputeWTO              ; re-compute write timeout value
  1242.         call    ComputeRTO              ; re-compute read  timeout value
  1243.  
  1244.         popff                           ; restore flags (interrupts)
  1245.         clc                             ; valid baud rate
  1246.         jmp     sbx
  1247.  
  1248.  
  1249. sberr:  stc                             ; invalid baud rate
  1250. sbx:    ret
  1251.  
  1252. EndProc SetBaud
  1253.  
  1254.  
  1255. ;**     StartNextWRP - start the next write request packet
  1256. ;
  1257. ;       StartNextWRP pulls the next request off of the write request
  1258. ;       list and makes it the current request.  In order to satisfy
  1259. ;       this request we then attempt to enable the TX interrupt.
  1260. ;
  1261. ;       ENTRY   (ds:si) -> ComInfo
  1262. ;
  1263. ;       EXIT    if 'C' clear
  1264. ;                       next request is now current AND ready to TX
  1265. ;               else
  1266. ;                       no requests outstanding OR not ready to TX
  1267. ;
  1268. ;       USES    ax bx
  1269.  
  1270. Procedure StartNextWRP,NEAR
  1271.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1272.  
  1273.         ChkComInfoPtr
  1274.  
  1275.         cmp     [si].ci_w_rp._hi,0
  1276.         je      snw1                    ; current request
  1277.  
  1278.         ComErr  <StartNextWRP : already a current request>
  1279.  
  1280.  
  1281. snw1:   SaveReg         <si>
  1282.         lea     si,[si].ci_w_rpl        ; (ds:si) -> write request packet list
  1283.         call    UnLinkHeadRP            ; (es:di) -> request packet
  1284.         RestoreReg      <si>            ; (ds:si) -> ComInfo structure
  1285.         jc      snwx                    ; there is no request to start
  1286.  
  1287.         ChkRPPtr
  1288.         ChkRPType       CMDOUTPUT
  1289.  
  1290.         mov     bx,es:[di].IOcount      ; initialize number of bytes to move
  1291.         mov     [si].ci_w_to_move,bx
  1292.  
  1293.         mov     bx,[si].ci_w_to_start   ; initialize time out value
  1294.         mov     [si].ci_w_to,bx
  1295.  
  1296.         ; set up GDT selector which we allocated at init time
  1297.         ;; PhysToGDTSel (ComInfo[si].GDTSelWrite, physical @, length)
  1298.         ;; move ComInfo[si].GDTSelWrite to Physical @. _hi
  1299.         ;; move 0 to Physical @. _lo
  1300.  
  1301.         push    si
  1302.         mov     si,[si].ci_GDTSelWrite
  1303.         ; es:di -> request packet
  1304.         call    SetUpGDT
  1305.         pop     si
  1306.  
  1307.         mov     [si].ci_w_rp._hi,es     ; save request packet
  1308.         mov     [si].ci_w_rp._lo,di
  1309.  
  1310. snwx:   call    CheckTX                 ; adjust the state of the TXer
  1311.         ret
  1312.  
  1313. EndProc StartNextWRP
  1314.  
  1315.  
  1316. ;**     StartNextRRP - start the next read request packet
  1317. ;
  1318. ;       StartNextRRP pulls the next request off of the read request
  1319. ;       list and makes it the current request. If there is enough data
  1320. ;       in the input queue to satisfy this new current request we
  1321. ;       immediately run it.
  1322. ;
  1323. ;       ENTRY   (ds:si) -> ComInfo
  1324. ;
  1325. ;       EXIT    interrupts enabled
  1326. ;
  1327. ;       USES    ax bx dx
  1328.  
  1329. Procedure StartNextRRP,NEAR
  1330.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1331.  
  1332.         ChkComInfoPtr
  1333.  
  1334.         cli
  1335.  
  1336.         cmp     [si].ci_r_rp._hi,0
  1337.         je      snr10                   ; there is no current request
  1338.  
  1339.         ComErr  <StartNextRRP : already a current request>
  1340.  
  1341. snr10:  SaveReg         <si>
  1342.         lea     si,[si].ci_r_rpl        ; (ds:si) -> read request packet list
  1343.         call    UnLinkHeadRP            ; (es:di) -> request packet
  1344.         RestoreReg      <si>            ; (ds:si) -> ComInfo structure
  1345.         jc      snrx                    ; there is no current request to start
  1346.  
  1347.         ChkRPPtr
  1348.         ChkRPType       CMDINPUT
  1349.  
  1350. ; We have a request.
  1351.  
  1352.         mov     bx,es:[di].IOcount      ; initialize number of bytes to move
  1353.         mov     [si].ci_r_to_move,bx
  1354.  
  1355.         mov     bx,[si].ci_r_to_start   ; initialize time out value
  1356.         mov     [si].ci_r_to,bx
  1357.  
  1358.         ; set up GDT selector which we allocated at init time
  1359.         ;; PhysToGDTSel (ComInfo[si].GDTSelRead, physical @, length)
  1360.         ;; move ComInfo[si].GDTSelRead to Physical @. _hi
  1361.         ;; move 0 to Physical @. _lo
  1362.         push    si
  1363.         mov     si,[si].ci_GDTSelRead
  1364.         ; es:di -> request packet
  1365.         call    SetUpGDT
  1366.         pop     si
  1367.  
  1368.         mov     [si].ci_r_rp._hi,es     ; save request packet
  1369.         mov     [si].ci_r_rp._lo,di
  1370.  
  1371.         mov     bx,es:[di].IOcount      ; (bx) = number requested
  1372.         cmp     [si].ci_qin.ioq_count,bx
  1373.         jae     snr30                   ; enough to satisfy the request
  1374.  
  1375.         mov     al,[si].ci_dcb_flags3
  1376.         and     al,F3_READ_TO_MASK      ; (al) = read timeout mode
  1377.  
  1378.         cmp     al,F3_READ_TO_NW
  1379.         jne     snrx                    ; NOT no wait mode
  1380.  
  1381. snr30:  sti
  1382.         call    ProcRun                 ; run the guy
  1383.  
  1384. snrx:   sti
  1385.         ret
  1386.  
  1387. EndProc StartNextRRP
  1388.  
  1389.  
  1390. ;**     LinkRP - link a request packet onto the end of a list
  1391. ;
  1392. ;       LinkRP takes a pointer to an RP_List and a pointer
  1393. ;       to a request packet and adds the packet to the end
  1394. ;       of the RP_List.
  1395. ;
  1396. ;       ENTRY   (ds:si) -> RP_List
  1397. ;               (es:di) -> request packet
  1398. ;
  1399. ;       EXIT
  1400. ;
  1401. ;       USES    NONE
  1402.  
  1403. ; Declare as hybrid so that ESP-specific can call as FAR,
  1404. ; and non-ESP code can call as NEAR.
  1405. Procedure LinkRP,HYBRID
  1406.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1407.  
  1408.         ChkRPLPtr
  1409.         ChkRPPtr
  1410.  
  1411.         mov     es:[di].PktDevLink._hi,0        ; NULLify the RP link
  1412.  
  1413.         pushf
  1414.         cli
  1415.  
  1416.         cmp     [si].rpl_head._hi,0
  1417.         jne     lrp1                    ; list is not empty
  1418.  
  1419.         mov     [si].rpl_head._hi,es    ; initialize head pointer
  1420.         mov     [si].rpl_head._lo,di
  1421.         mov     [si].rpl_tail._hi,es    ; initialize tail pointer
  1422.         mov     [si].rpl_tail._lo,di
  1423.         jmp     SHORT lrpx
  1424.  
  1425. lrp1:   SaveReg         <ds,si>
  1426.  
  1427.         lds     si,[si].rpl_tail        ; (ds:di) -> last RP in list
  1428.  
  1429.         mov     [si].PktDevLink._hi,es  ; add the RP to the list
  1430.         mov     [si].PktDevLink._lo,di
  1431.  
  1432.         RestoreReg      <si,ds>         ; (ds:si) -> RP_List
  1433.         ASSUME  ds:NOTHING
  1434.  
  1435.         mov     [si].rpl_tail._hi,es    ; update the tail pointer
  1436.         mov     [si].rpl_tail._lo,di
  1437.  
  1438. lrpx:   POPFF
  1439.  
  1440.         ret
  1441.  
  1442. EndProc LinkRP
  1443.  
  1444.  
  1445. ;**     UnLinkHeadRP - unlink a request packet from the head of a list
  1446. ;
  1447. ;       UnLinkHeadRP removes the first request packet
  1448. ;       from an RP_List if it the list not empty.
  1449. ;
  1450. ;       ENTRY   (ds:si) -> RP_List
  1451. ;
  1452. ;       EXIT    if 'C' clear
  1453. ;                       (es:di) -> request packet
  1454. ;               else
  1455. ;                       list is empty
  1456. ;
  1457. ;       USES    ax es di carry
  1458.  
  1459. ; Declare as hybrid so that ESP-specific can call as FAR,
  1460. ; and non-ESP code can call as NEAR.
  1461. Procedure UnLinkHeadRP,HYBRID
  1462.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1463.  
  1464.         ChkRPLPtr
  1465.  
  1466.         stc                                     ; assume the list is empty
  1467.         pushf                                   ; save flags
  1468.         cli
  1469.  
  1470.         cmp     [si].rpl_head._hi,0
  1471.         jz      ulhx                            ; list is empty
  1472.  
  1473.         les     di,[si].rpl_head                ; (es:di) -> RP
  1474.  
  1475.         mov     ax,es:[di].PktDevLink._hi       ; update head pointer
  1476.         mov     [si].rpl_head._hi,ax
  1477.         mov     ax,es:[di].PktDevLink._lo
  1478.         mov     [si].rpl_head._lo,ax
  1479.  
  1480.         popff                                   ; restore flags
  1481.         clc                                     ; no carry
  1482.         ret
  1483.  
  1484. ulhx:   popff                                   ; restore flags
  1485.         ret
  1486.  
  1487. EndProc UnLinkHeadRP
  1488.  
  1489.  
  1490. ;**     UnLinkRP - unlink a specific request packet from a list
  1491. ;
  1492. ;       UnLinkRP removes a specific request packet from anywhere in
  1493. ;       an RP_List. It is considered an inconsistent state if
  1494. ;       the specified request is not on the list.
  1495. ;
  1496. ;       ENTRY   (ds:si) -> RP_List
  1497. ;               (es:di) -> request packet
  1498. ;
  1499. ;       EXIT
  1500. ;
  1501. ;       USES    ax bx
  1502.  
  1503. ; Declare as hybrid so that ESP-specific can call as FAR,
  1504. ; and non-ESP code can call as NEAR.
  1505. Procedure UnLinkRP,HYBRID
  1506.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1507.  
  1508.         ChkRPLPtr
  1509.         ChkRPPtr
  1510.  
  1511.         pushf                                   ; save flags
  1512.         cli
  1513.  
  1514. IFDEF RPLSTRICT
  1515.         cmp     [si].rpl_head._hi,0
  1516.         jnz     ulr0_1                  ; not end of list
  1517.  
  1518.         ComErr  <UnLinkRP : NULL list>
  1519. ulr0_1:
  1520. ENDIF
  1521.         mov     ax,es
  1522.         cmp     [si].rpl_head._hi,ax
  1523.         jne     ulr0                            ; not removing the head
  1524.  
  1525.         cmp     [si].rpl_head._lo,di
  1526.         jne     ulr0                            ; not removing the head
  1527.  
  1528.         mov     ax,es:[di].PktDevLink._hi       ; remove head
  1529.         mov     [si].rpl_head._hi,ax
  1530.         mov     ax,es:[di].PktDevLink._lo
  1531.         mov     [si].rpl_head._lo,ax
  1532.         jmp     SHORT ulrx
  1533.  
  1534. ulr0:   SaveReg         <ds,si>
  1535.  
  1536.         lds     si,[si].rpl_head                ; (ds:si) -> first RP
  1537.  
  1538. ulr1:
  1539.  
  1540. ; If we get to the end of the list without finding the
  1541. ; specified packet, we are in an inconsistent state.
  1542.  
  1543.         cmp     [si].PktDevLink._hi,0
  1544.         jne     ulr1_1                          ; not end of list
  1545.  
  1546.         ComErr  <UnLinkRP : end of list>
  1547.  
  1548. ulr1_1: mov     ax,es
  1549.         cmp     [si].PktDevLink._hi,ax
  1550.         jne     ulr2                            ; not the specified RP
  1551.  
  1552.         cmp     [si].PktDevLink._lo,di
  1553.         je      ulr3                            ; found the specified RP
  1554.  
  1555. ulr2:   lds     si,[si].PktDevLink              ; (ds:si) -> next RP
  1556.         jmp     SHORT ulr1
  1557.  
  1558. ulr3:   mov     ax,es:[di].PktDevLink._lo       ; remove specified RP
  1559.         mov     [si].PktDevLink._lo,ax
  1560.         mov     ax,es:[di].PktDevLink._hi
  1561.         mov     [si].PktDevLink._hi,ax
  1562.  
  1563.         or      ax,ax
  1564.         mov     ax,ds
  1565.         mov     bx,si                           ; (ax:bx) -> potential tail
  1566.  
  1567.         RestoreReg      <si,ds>                 ; (ds:si) -> RP_List
  1568.         ASSUME  ds:NOTHING
  1569.  
  1570.         jnz     ulrx                            ; did not remove tail
  1571.                                                 ; cc set by above or instr.
  1572.  
  1573.         mov     [si].rpl_tail._hi,ax            ; update tail pointer
  1574.         mov     [si].rpl_tail._lo,bx
  1575.  
  1576. ulrx:   popff
  1577.         ret
  1578.  
  1579. EndProc UnLinkRP
  1580.  
  1581.  
  1582. ;**     ComputeRTO - compute the read timeout in timer ticks
  1583. ;
  1584. ;       ComputeRTO coverts the user specified read time out value from
  1585. ;       hundredths of a second to system timer ticks. It also saves
  1586. ;       this converted value in the ComInfo structure and initializes
  1587. ;       the timeout countdown value.
  1588. ;
  1589. ;       ENTRY   (ds:si) -> ComInfo
  1590. ;
  1591. ;       EXIT
  1592. ;
  1593. ;       USES    ax dx
  1594. ;
  1595. ;       NOTE    Must be called with interrupts off so an interrupt doesn't
  1596. ;               come in while we are updating the timeout values.
  1597.  
  1598. ; Declare as hybrid so that ESP-specific can call as FAR,
  1599. ; and non-ESP code can call as NEAR.
  1600. Procedure ComputeRTO,HYBRID
  1601.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1602.  
  1603.         ChkComInfoPtr
  1604.  
  1605.         mov     ax,[si].ci_dcb_readto       ; (ax) = 0.01 sec/timeout
  1606.         mov     dx,100                  ;        * 100
  1607.         mul     dx                      ; (dx:ax) = .0001 sec/timeout
  1608.         div     ClkIntrvl               ;         / .0001 sec/tick
  1609.                                         ; (ax) = ticks/timeout
  1610.         inc     ax                      ; round up
  1611.         cmp     ax,1                    ; is it only one tick?
  1612.         jne     crto10                  ;  no, ok
  1613.         inc     ax                      ;  yes, make it 2 ticks instead
  1614.  
  1615. crto10: mov     [si].ci_r_to_start,ax   ; save read timeout value
  1616.         mov     [si].ci_r_to,ax         ; initialize read countdown
  1617.  
  1618.  
  1619.         ; Compute ticks per RX interrupt and use if larger than user
  1620.         ; specified timeout.  This is required even if the FIFO is
  1621.         ; off if the system clock is fast and the baud rate is low.
  1622.  
  1623.         SaveReg <bx>
  1624.         mov     bl,[si].ci_dcb_flags3   ; (bl) = flags3
  1625.         .errnz  F3_RX_MASK - 01100000b
  1626.         and     bx,F3_RX_MASK           ; (bx) = rx trig level
  1627.         rol     bl,3                    ; (bx) = rx trig level index
  1628.         mov     bl,RxTrigTbl[bx]        ; (bx) = rx trig level value (char/int)
  1629.  
  1630.         call    ComputeTPI              ; (ax) = ticks/interrupt
  1631.         RestoreReg <bx>
  1632.  
  1633.         cmp     ax,[si].ci_r_to_start   ; if ax > read timeout
  1634.         jbe     crtox
  1635.  
  1636.         mov     [si].ci_r_to_start,ax   ; save read timeout value
  1637.         mov     [si].ci_r_to,ax         ; initialize read countdown
  1638.  
  1639. crtox:  ret
  1640.  
  1641. EndProc ComputeRTO
  1642.  
  1643.  
  1644. ;**     ComputeWTO - compute the write timeout in timer ticks
  1645. ;
  1646. ;       ComputeWTO coverts the user specified write time out value from
  1647. ;       hundredths of a second to system timer ticks. It also saves
  1648. ;       this converted value in the ComInfo structure and initializes
  1649. ;       the timeout countdown value.
  1650. ;
  1651. ;       ENTRY   (ds:si) -> ComInfo
  1652. ;
  1653. ;       EXIT
  1654. ;
  1655. ;       USES    ax dx
  1656. ;
  1657. ;       NOTE    Must be called with interrupts off so an interrupt doesn't
  1658. ;               come in while we are updating the timeout values.
  1659.  
  1660. ; Declare as hybrid so that ESP-specific can call as FAR,
  1661. ; and non-ESP code can call as NEAR.
  1662. Procedure ComputeWTO,HYBRID
  1663.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1664.  
  1665.         ChkComInfoPtr
  1666.  
  1667.         mov     ax,[si].ci_dcb_writeto  ; (ax) = 0.01 sec/timeout
  1668.         mov     dx,100                  ;        * 100
  1669.         mul     dx                      ; (dx:ax) = .0001 sec/timeout
  1670.         div     ClkIntrvl               ;         / .0001 sec/tick
  1671.                                         ; (ax) = ticks/timeout
  1672.         inc     ax                      ; round up
  1673.         cmp     ax,1                    ; is it only one tick?
  1674.         jne     cwto10                  ;  no, ok
  1675.         inc     ax                      ;  yes, make it 2 ticks instead
  1676.  
  1677. cwto10: mov     [si].ci_w_to_start,ax   ; save write timeout value
  1678.         mov     [si].ci_w_to,ax         ; initialize write countdown
  1679.  
  1680.  
  1681.         ; Compute ticks per TX interrupt and use if larger than user
  1682.         ; specified timeout.  This is required even if the FIFO is
  1683.         ; off if the system clock is fast and the baud rate is low.
  1684.  
  1685.         SaveReg <bx>
  1686.         mov     bx,1                            ; (bl) = 1  (char/int)
  1687.         test    [si].ci_dcb_flags3,F3_TX_16     ; 16 char/int TX?
  1688.         jz      cwto20                          ;  no, use 1
  1689.         mov     bx,16                           ; (bl) = 16 (char/int)
  1690.  
  1691. cwto20: call    ComputeTPI                      ; (ax) = ticks/interrupt
  1692.         RestoreReg <bx>
  1693.  
  1694.         cmp     ax,[si].ci_w_to_start           ; if ax > write timeout
  1695.         jbe     cwtox
  1696.  
  1697.         mov     [si].ci_w_to_start,ax           ; save write timeout value
  1698.         mov     [si].ci_w_to,ax                 ; initialize write countdown
  1699.  
  1700. cwtox:  ret
  1701.  
  1702. EndProc ComputeWTO
  1703.  
  1704.  
  1705. ;**     ComputeTPI - compute ticks per interrupt
  1706. ;
  1707. ;       ComputeTPI computes the number of system timer ticks it takes
  1708. ;       to transmit BX characters at the current baud rate.
  1709. ;
  1710. ;       ENTRY   (ds:si) -> ComInfo
  1711. ;               (bx)     = chars/int (1, 4, 8 or 14 for RX; 1 or 16 for TX)
  1712. ;
  1713. ;       EXIT    (ax)     = ticks/interrupt
  1714. ;
  1715. ;       USES    ax bx dx
  1716.  
  1717. Procedure ComputeTPI,NEAR
  1718.  
  1719.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1720.  
  1721.         ChkComInfoPtr    9
  1722.  
  1723. ; Compute ticks per RX or TX interrupt and use if less than user
  1724. ; specified timeout.  This is required even if the FIFO is off
  1725. ; if the system clock is fast and the baud rate is low.
  1726. ;
  1727. ; in:   bits /sec       (baud) (2-19200)
  1728. ;       sec  /tick      (system clock interval in .0001 sec units)
  1729. ;                        (100-10000)
  1730. ;       chars/int       (bx) (1-16)
  1731. ;
  1732. ; out:  ticks/int
  1733. ;
  1734. ;       char/int * 12 bits/char * 10000   bits/int
  1735. ;       ------------------------------- = --------- = ticks/int
  1736. ;       bits/sec * sec/tick               bits/tick
  1737. ;
  1738. ; BUGBUG 11-29-88 bryand - 12 bits per char - could calc exact
  1739. ;
  1740. ; BUGBUG 11-29-88 bryand - min clock interval = 30/10000 sec
  1741. ;       the max numerator   = 16 * 12 * 10000 = 1920000
  1742. ;       the min denominator = (1920000/65535) + 1 = 30
  1743. ;       to make the quotient fit in 16 bits without a 32/32 divide.
  1744.  
  1745.         shl     bx,1                    ; (bx) = char/int * 2 (120000 = 2*60000)
  1746.         mov     ax,60000                ;           * 10000 * 6 bits/char
  1747.         mul     bx                      ; (dx:ax) = bits/int
  1748.                                         ;           / sec/tick
  1749.         div     ClkIntrvl               ; (ax) = bits/int * tick/sec
  1750.         xor     dx,dx                   ;        / bits/sec
  1751.         div     [si].ci_baud            ; (ax) = ticks/int
  1752.         inc     ax                      ; (ax) = ticks/int (rounded up)
  1753.  
  1754.         ret
  1755.  
  1756. EndProc ComputeTPI
  1757.  
  1758.  
  1759. ;**     Get_OCI_Sem - get the open/close/ioctl semaphore
  1760. ;
  1761. ;       Get the open/close/ioctl semaphore.
  1762. ;       If cannot get semaphore jump to CmxGenFail.
  1763. ;       If we got the sem, but the device has shut down, free the sem
  1764. ;       (so all blockers will wake up) and jump to CmxGenFail.
  1765. ;
  1766. ;       ENTRY   (ds:si) -> cominfo
  1767. ;
  1768. ;       EXIT    No Carry - got semaphore
  1769. ;
  1770. ;               Carry    - couldn't get semaphore or driver shut down,
  1771. ;                          jmp CmxGenFail
  1772. ;
  1773. ;       USES    ax bx cx dx
  1774.  
  1775. Procedure Get_OCI_Sem,NEAR
  1776.         ASSUME cs:CSEG,ds:NOTHING,es:NOTHING,ss:NOTHING
  1777.  
  1778.         ChkComInfoPtr
  1779.  
  1780.         SaveReg         <di>
  1781.         mov     ax,ds
  1782.         lea     bx,[si].ci_oci_sem              ; (ax:bx) -> semaphore
  1783.         mov     cx,-1
  1784.         mov     di,cx                           ; (cx:di) = time out
  1785.         mov     dl,DevHlp_SemRequest
  1786.         DevHelp
  1787.         RestoreReg      <di>
  1788.         jc      gosf                            ; error, couldn't get semaphore
  1789.  
  1790.         ChkComInfoPtr
  1791.  
  1792.         ; got the semaphore
  1793.         test    Flags,F_SHUT_DOWN
  1794.         jz      gosx                            ; driver is not shut down
  1795.  
  1796.         ; got the semaphore, but driver is shut down so clear the sem and fail
  1797.         mov     ax,ds
  1798.         lea     bx,[si].ci_oci_sem              ; (ax:bx) -> semaphore
  1799.         mov     dl,DevHlp_SemClear
  1800.         DevHelp
  1801.  
  1802. gosgenfail:
  1803.         jmp     CmxGenFail                      ; error, couldn't get semaphore
  1804.  
  1805. gosx:   mov     [si].ci_oci_sem_own._hi,es      ; save oci_sem owner
  1806.         mov     [si].ci_oci_sem_own._lo,di
  1807.         ret
  1808.  
  1809. gosf:   cmp     ax,ERROR_INTERRUPT
  1810.         jne     gosgenfail                      ; not interrupted, genfail
  1811.         jmp     CmxInterrupted                  ; SemRequest Interrupted
  1812.  
  1813. EndProc Get_OCI_Sem
  1814.  
  1815.  
  1816. ;**     ComError - com driver internal error
  1817. ;
  1818. ;       ComError is used to shut down the device driver in cases
  1819. ;       of absolute failure. It should be invoked by the ComErr macro.
  1820. ;
  1821. ;       Actions taken:
  1822. ;               set F_SHUT_DOWN flag to show driver is sutting down
  1823. ;               UnsetTimer
  1824. ;               UnsetIRQ for open ports
  1825. ;               ProcRun all threads blocked in the driver
  1826. ;               zap ComInfo offsets to fail subsequent requests
  1827. ;
  1828. ;       ENTRY   pointer to string       (WORD) <- TOS
  1829. ;
  1830. ;       EXIT    (ds) -> DD Data seg
  1831. ;               if unrecoverable error  - int 3
  1832. ;               if task time            - jmp CmxGenFail
  1833. ;               if interrupt time       - jmp cinterr
  1834. ;
  1835. ;       USES    ax bx cx dx es di
  1836. ;
  1837. ;       WARNING It is assumed that either ds or es contains the device
  1838. ;               drivers DATA segment.
  1839.  
  1840. ; Declare as hybrid so that ESP-specific can call as FAR,
  1841. ; and non-ESP code can call as NEAR.
  1842. Procedure ComError,HYBRID
  1843.         ASSUME cs:CSEG,ds:NOTHING,es:NOTHING,ss:NOTHING
  1844.  
  1845. ; Get addressabilty to our DATA segment
  1846.  
  1847.         ; verify ds before using to prevent trap if DATA is in es
  1848.         ; don't bother verifying es as we trap if DATA is not in es anyway
  1849.  
  1850.         mov     ax,ds                   ; (ax) = ds
  1851.         verifywrite     ax
  1852.         jnz     cer5                    ; ds not writable data segment, try es
  1853.  
  1854.         loadsl  ax,ax                   ; (ax) = ds segment limit
  1855.         cmp     ax,OFFSET DataSegSig+1  ; +1 for 2nd byte of signature
  1856.         jb      cer5                    ; ds segment limit too small, try es
  1857.  
  1858.         cmp     ds:DataSegSig,SIGNATURE
  1859.         je      cer10                   ; (ds) = DATA
  1860.  
  1861. cer5:   cmp     es:DataSegSig,SIGNATURE
  1862.         ljne    cerxx                   ; DATA unavailable
  1863.         push    es
  1864.         pop     ds                      ; (ds) = DATA
  1865.         ASSUME  ds:DSEG
  1866.  
  1867. cer10:  cli                             ; no interrupts while checking flags
  1868.         test    Flags,F_SHUT_DOWN
  1869.         ljnz    cerxx                   ; nested internal error, trap
  1870.  
  1871.         or      Flags,F_SHUT_DOWN       ; flag shut down in progress
  1872.  
  1873.         push    si                      ; save current ComInfo
  1874.         push    Com4                    ; save Com2 cominfo
  1875.         push    Com3                    ; save Com2 cominfo
  1876.         push    Com2                    ; save Com2 cominfo
  1877.         mov     si,Com1                 ; (ds:si) -> Com1 cominfo
  1878.  
  1879.         ; zeroing the Comn pointer values will make subsequent requests
  1880.         ; because the strategy routine will think the port is not installed.
  1881.         ; subsequent interrupts (before we finish calling ShutDownPort below)
  1882.         ; will fail in the same way.
  1883.  
  1884.         mov     Com1,0          ; zap Com1 Info
  1885.         mov     Com2,0          ; zap Com2 Info
  1886.         mov     Com3,0          ; zap Com2 Info
  1887.         mov     Com4,0          ; zap Com2 Info
  1888.  
  1889.         sti
  1890.  
  1891.         cmp     si,0
  1892.         je      sd_com2
  1893.         call    ShutDownPort            ; shut down Com1
  1894.  
  1895. sd_com2:
  1896.         pop     si                      ; (ds:si) -> Com2 ComInfo
  1897.         cmp     si,0
  1898.         je      sd_com3
  1899.         call    ShutDownPort            ; shut down Com2
  1900.  
  1901. sd_com3:
  1902.         pop     si                      ; (ds:si) -> Com3 ComInfo
  1903.         cmp     si,0
  1904.         je      sd_com4
  1905.         call    ShutDownPort            ; shut down Com3
  1906.  
  1907. sd_com4:
  1908.         pop     si                      ; (ds:si) -> Com4 ComInfo
  1909.         cmp     si,0
  1910.         je      sd_comx
  1911.         call    ShutDownPort            ; shut down Com4
  1912.  
  1913. sd_comx:
  1914.         mov     ax,OFFSET Ticker
  1915.         mov     dl,DevHlp_ResetTimer
  1916.         DevHelp
  1917.  
  1918.         ; ProcRun requests on the ready list
  1919.         mov     si,OFFSET Ready ; (ds:si) -> Ready list
  1920.  
  1921. cer70:  call    UnLinkHeadRP    ; (es:di) -> runnable request packet
  1922.         jc      cer80           ; no more to run
  1923.         call    ProcRun
  1924.         jmp     SHORT cer70     ; try to run another
  1925.  
  1926. cer80:
  1927.         pop     si                      ; (ds:si) -> current Cominfo
  1928.         ChkComInfoPtr
  1929.  
  1930.         cmp     [si].ci_depth,D_NONE
  1931.         jne     cerxx           ; interrupt time
  1932.  
  1933.         jmp     CmxGenFail      ; task time => GenFail
  1934.  
  1935.  
  1936. cerxx:
  1937.         ret
  1938.  
  1939. EndProc ComError
  1940.  
  1941.  
  1942. ;** ShutDownPort - shut down a com port if it was open
  1943. ;
  1944. ;       if the port is open
  1945. ;         UnsetIRQ
  1946. ;         ProcRun requests on the ready list
  1947. ;         flush write requests
  1948. ;         flush read requests
  1949. ;         SemClear open/close/ioctl semaphore
  1950. ;
  1951. ;       ENTRY   (ds:si) -> ComInfo of port to shut down
  1952. ;
  1953. ;       EXIT    NONE
  1954. ;
  1955. ;       USES    ax bx cx dx es di
  1956.  
  1957. Procedure ShutDownPort,NEAR
  1958.         ASSUME cs:CSEG,ds:NOTHING,es:NOTHING,ss:NOTHING
  1959.  
  1960.         or      si,si
  1961.         lje     sdpx                    ; device not installed
  1962.  
  1963.         ChkComInfoPtr
  1964.  
  1965.         cmp     [si].ci_nopens,0
  1966.         lje     sdpx                    ; device not open
  1967.  
  1968.  
  1969. sdpx10:
  1970.         ; Standard port: disable interrupts from UART, drop modem lines and
  1971.         ; clear break
  1972.         mov     dx,[si].ci_port
  1973.         add     dx,R_INTEN              ; (dx) -> interruprt enable reg
  1974.         xor     al,al                   ; (al) =  0
  1975.         mout    dx,al                   ; disable all com interrupts
  1976.  
  1977.         add     dx,R_MODMC-R_INTEN      ; (dx) -> modem control reg
  1978.         mout    dx,al                   ; turn off all MCR signals
  1979.  
  1980.         mov     al,[si].ci_linec        ; (al) = line control value
  1981.         and     al,NOT LC_BREAK     ; turn off break
  1982.         and     [si].ci_hsflag, NOT HS_BREAK_SET
  1983.                                         ; break no longer set
  1984.         call    SetLineC
  1985.  
  1986.         test    [si].ci_mult_COMs_IRQ, INT_SHARING  ; sharing the IRQ?
  1987.                                                 ; with other COM ports?
  1988.         jz      sdpx15                          ; N: unset normally
  1989.         call    DeqComInfo                      ; Y: remove from queue
  1990.         jmp     short sdpx30                    ; then continue
  1991.  
  1992. sdpx15: mov     bl, [si].ci_irq
  1993.         jmp     SHORT @f
  1994.  
  1995. sdpx20:  mov     bl,[bx].pi_irq
  1996.  
  1997. @@:     xor     bh,bh
  1998.         mov     dl,DevHlp_UnSetIRQ
  1999.         DevHelp                       ; release the IRQ
  2000.  
  2001. sdpx30:  call    ComWFlushSub            ; flush all outstanding write requests
  2002.         call    ComRFlushSub            ; flush all outstanding read  requests
  2003.  
  2004.         mov     ax,ds
  2005.         lea     bx,[si].ci_oci_sem      ; (ax:bx) -> semaphore
  2006.         mov     dl,DevHlp_SemClear
  2007.         DevHelp                         ; clear sem to run threads waiting on it
  2008.  
  2009. sdpx:   ret
  2010.  
  2011. EndProc ShutDownPort
  2012.  
  2013.  
  2014. ;**
  2015. ;       The following procedures are conditionally assembled based
  2016. ;       on the definition of a number of assembler defines.
  2017. ;       They are used as a debugging aid.
  2018.  
  2019. IFDEF   CISTRICT
  2020.  
  2021. ;**     CheckComInfoPtr - check the validity of the ComInfo pointer
  2022. ;
  2023. ;       CheckComInfoPtr is a debugging routine which will attempt
  2024. ;       to verify that (ds:si) points to a valid ComInfo structure.
  2025. ;       It does this verification by checking for a SIGNATURE
  2026. ;       in ci_signature.
  2027. ;
  2028. ;       To invoke this procedure, use the ChkComInfoPtr macro which
  2029. ;       is also conditionally assembled.
  2030. ;
  2031. ;       ENTRY   (ds:si) -> ComInfo
  2032. ;
  2033. ;       EXIT    If (ds:si) is invalid
  2034. ;                       ComError
  2035. ;               else
  2036. ;                       return
  2037. ;
  2038. ;       USES    NONE
  2039.  
  2040. Procedure CheckComInfoPtr,NEAR
  2041.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  2042.  
  2043.         pushf
  2044.         cmp     [si].ci_signature,SIGNATURE
  2045.         jne     cip1                            ; invalid pointer
  2046.  
  2047.         POPFF
  2048.         ret
  2049.  
  2050. cip1:   ComErr  <ChkComInfoPtr : invalid signature.>
  2051.  
  2052. EndProc CheckComInfoPtr
  2053.  
  2054. ENDIF   ; CISTRICT
  2055.  
  2056.  
  2057. IFDEF   RPSTRICT
  2058.  
  2059. ;**     CheckRPPtr - check the validity of the request packet pointer
  2060. ;
  2061. ;       CheckRPPtr is a debugging routine which will attempt
  2062. ;       to verify that (es:di) points to a valid request packet.
  2063. ;       It does this verification by checking for a SIGNATURE
  2064. ;       in PktStatus.
  2065. ;
  2066. ;       To invoke this procedure, use the ChkRPPtr macro which
  2067. ;       is also conditionally assembled.
  2068. ;
  2069. ;       ENTRY   (es:di) -> request packet
  2070. ;
  2071. ;       EXIT    If (es:di) is invalid
  2072. ;                       ComErr
  2073. ;               else
  2074. ;                       return
  2075. ;
  2076. ;       USES    NONE
  2077.  
  2078. Procedure CheckRPPtr,NEAR
  2079.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  2080.  
  2081. ;       the SIGNATURE can't use the STDON or open_monitor bits
  2082.         .errnz  SIGNATURE AND STDON
  2083.         .errnz  SIGNATURE AND open_monitor
  2084.  
  2085.         pushf
  2086.         SaveReg         <ax>
  2087.         mov     ax,es:[di].PktStatus
  2088.         and     ax,NOT (STDON OR open_monitor)          ; ignore STDON bit
  2089.         cmp     ax,SIGNATURE
  2090.         RestoreReg      <ax>
  2091.         jne     crp1                                    ; invalid pointer
  2092.  
  2093.         POPFF
  2094.         ret
  2095.  
  2096. crp1:   ComErr  <ChkRPPtr : invalid signature.>
  2097.  
  2098. EndProc CheckRPPtr
  2099.  
  2100. ENDIF   ; RPSTRICT
  2101.  
  2102.  
  2103. IFDEF   RPLSTRICT
  2104.  
  2105. ;**     CheckRPLPtr - check the validity of the RP_List pointer
  2106. ;
  2107. ;       CheckRPLPtr is a debugging routine which will attempt
  2108. ;       to verify that (ds:si) points to a valid RP_List.
  2109. ;       It does this verification by checking for a SIGNATURE
  2110. ;       in rpl_head.
  2111. ;
  2112. ;       To invoke this procedure, use the ChkRPLPtr macro which
  2113. ;       is also conditionally assembled.
  2114. ;
  2115. ;       ENTRY   (ds:si) -> RPL_List
  2116. ;
  2117. ;       EXIT    If (ds:si) is invalid
  2118. ;                       ComErr
  2119. ;               else
  2120. ;                       return
  2121. ;
  2122. ;       USES    NONE
  2123.  
  2124. Procedure CheckRPLPtr,NEAR
  2125.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  2126.  
  2127.         pushf
  2128.         cmp     [si].rpl_signature,SIGNATURE
  2129.         jne     crpl1                   ; invalid pointer
  2130.  
  2131.         POPFF
  2132.         ret
  2133.  
  2134. crpl1:  ComErr  <ChkRPLPtr : invalid signature.>
  2135.  
  2136. EndProc CheckRPLPtr
  2137.  
  2138. ENDIF   ; RPLSTRICT
  2139.  
  2140. ;**     EnqComInfo - Enqueue a ComInfo structure
  2141. ;
  2142. ;       EnqComInfo updates the data structures used to
  2143. ;       support IRQ sharing.  For each shared IRQ line, a
  2144. ;       linked list of ComInfo structures is maintained in baud
  2145. ;       rate order.  On an Open of a COM port that shares its
  2146. ;       IRQ line, this routine is called to insert the ComInfo
  2147. ;       structure into the linked list.  This is a standard
  2148. ;       "walk the chain" algorithm that searches a uni-directional
  2149. ;       linked list for the spot to insert the new entry.
  2150. ;
  2151. ;       ENTRY   (ds:si) -> ComInfo structure
  2152. ;
  2153. ;       EXIT    Linked list updated
  2154. ;               CY = 0, no error
  2155. ;               CY = 1, error
  2156. ;
  2157. ;       USES    Flags
  2158.  
  2159. Procedure EnqComInfo,NEAR
  2160.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  2161.  
  2162.         pusha
  2163.  
  2164.         mov     bx, [si].ci_int_data    ; IRQ line data for this COM port
  2165.         cmp     ShrdIRQ1[bx].si_firstCOM, 0     ; chain currently empty?
  2166.         jne     enq10                   ; N: we'll have to walk the chain
  2167.         mov     ShrdIRQ1[bx].si_firstCOM, si    ; Y: set the "head" pointer
  2168.         mov     [si].ci_next_COM, 0     ; indicate we are last in chain
  2169.         jmp     short enq50             ; then exit
  2170.  
  2171. enq10:
  2172.         mov     di, ShrdIRQ1[bx].si_firstCOM    ; first ComInfo in chain
  2173.         xor     cx, cx                  ; "back pointer" to insert location
  2174.  
  2175. enq20:
  2176.         mov     ax, [si].ci_baud        ; get candidate baud rate
  2177.         cmp     ax, [di].ci_baud        ; is it > than the chain entry's baud?
  2178.         jle     enq30                   ; N: keep walking the chain
  2179.         cmp     cx, 0                   ; Y: are we inserting at the top?
  2180.         jne     enq25                   ; N: just update the chain
  2181.         mov     ax, ShrdIRQ1[bx].si_firstCOM    ; Y: we'll have to update the "head" ptr
  2182.         mov     ShrdIRQ1[bx].si_firstCOM, si    ; update the "head" pointer
  2183.         mov     [si].ci_next_COM, ax    ; former first entry in chain
  2184.         jmp     short enq50             ; then exit
  2185.  
  2186. enq25:
  2187.         mov     [si].ci_next_COM, di    ; point to current chain entry
  2188.         mov     di, cx                  ; get "back pointer"
  2189.         mov     [di].ci_next_COM, si    ; get in front of current entry
  2190.         jmp     short enq50             ; then exit
  2191.  
  2192. enq30:
  2193.         cmp     [di].ci_next_COM, 0     ; are we at the end of the chain?
  2194.         jne     enq35                   ; N: keep searching
  2195.         mov     [di].ci_next_COM, si    ; Y: hook in at the end of the chain
  2196.         mov     [si].ci_next_COM, 0     ; and indicate "end of chain"
  2197.         jmp     short enq50             ; then exit
  2198.  
  2199. enq35:
  2200.         mov     cx, di                  ; update the "back pointer"
  2201.         mov     di, [di].ci_next_COM    ; next entry in the chain
  2202.         jmp     enq20                   ; and then try again
  2203.  
  2204. enq50:
  2205.         test    [si].ci_Flagx1, FX1_SET_BAUD_IP ; just changing the baud?
  2206.         jnz     enq60                   ; Y: skip the IRQ stuff and exit (CY cl)
  2207.         inc     ShrdIRQ1[bx].si_opens   ; N: increment the number of opens
  2208.         cmp     ShrdIRQ1[bx].si_opens, 1  ; first COM port on this IRQ?
  2209.         clc                             ;   assume no
  2210.         jne     enq60                   ; N: already have IRQ, just exit
  2211.  
  2212.         mov     ax, ShrdIRQ1[bx].si_entry ; offset of IRQ handler
  2213.         xor     bh,bh
  2214.         mov     bl, ShrdIRQ1[bx].si_irq ; IRQ line
  2215.         mov     dh, 1                   ; share the IRQ line
  2216.         mov     dl, DevHlp_SetIRQ
  2217.         push    es
  2218.         push    ds
  2219.         pop     es                      ; point to DSEG
  2220.         setDS   HSEG                    ; point to resident data
  2221.         call    es:[DevHlp]             ; register for the IRQ line, CY set on
  2222.                                         ;  error
  2223.         pop     es
  2224.         setDS   DSEG                    ; restore DS
  2225.  
  2226. enq60:
  2227.         popa
  2228.         ret                             ; with CY indicating success/failure
  2229.  
  2230. EndProc EnqComInfo
  2231.  
  2232. ;**     DeqComInfo - Dequeue a ComInfo structure
  2233. ;
  2234. ;       DeqComInfo updates the data structures used to
  2235. ;       support IRQ sharing.  For each shared IRQ line, a
  2236. ;       linked list of ComInfo structures is maintained in baud
  2237. ;       rate order.  On a Close of a COM port that shares its
  2238. ;       IRQ line, this routine is called to remove the ComInfo
  2239. ;       structure from the linked list.  This is a standard
  2240. ;       "walk the chain" algorithm that searches a uni-directional
  2241. ;       linked list for the entry to remove.
  2242. ;
  2243. ;       ENTRY   (ds:si) -> ComInfo structure
  2244. ;
  2245. ;       EXIT    Linked list updated
  2246. ;
  2247. ;       USES    Flags
  2248.  
  2249. Procedure DeqComInfo,NEAR
  2250.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  2251.  
  2252.         pusha
  2253.  
  2254.         mov     bx, [si].ci_int_data    ; IRQ line data for this COM port
  2255.         cmp     ShrdIRQ1[bx].si_firstCOM, si    ; Are we first in the chain?
  2256.         jne     deq10                   ; N: we'll have to walk the chain
  2257.         mov     ax, [si].ci_next_COM    ; Y: get addr. of entry following us
  2258.         mov     ShrdIRQ1[bx].si_firstCOM, ax    ; and update the "head" ptr.
  2259.         jmp     short deq50             ; then exit
  2260.  
  2261. deq10:
  2262.         mov     di, ShrdIRQ1[bx].si_firstCOM    ; first ComInfo in chain
  2263.  
  2264. deq20:
  2265.         cmp     si, [di].ci_next_COM    ; does this chain entry point to us?
  2266.         jne     deq30                   ; N: keep walking the chain
  2267.         mov     ax, [si].ci_next_COM    ; Y: get the ComInfo we point to
  2268.         mov     [di].ci_next_COM, ax    ; and remove us from the chain
  2269.         jmp     short deq50             ; then exit
  2270.  
  2271. deq30:
  2272.         mov     di, [di].ci_next_COM    ; get next entry in chain
  2273.         jmp     deq20                   ; and try again
  2274.  
  2275. deq50:
  2276.         test    [si].ci_Flagx1, FX1_SET_BAUD_IP ; just changing the baud?
  2277.         jnz     deq60                   ; Y: skip the IRQ stuff and exit
  2278.         dec     ShrdIRQ1[bx].si_opens   ; N: decrement the number of opens
  2279.         cmp     ShrdIRQ1[bx].si_opens, 0 ;  COM ports left?
  2280.         jne     deq60                   ; Y: just exit
  2281.         xor     bh,bh
  2282.         mov     bl, ShrdIRQ1[bx].si_irq ; get IRQ line
  2283.         mov     dl, DevHlp_UnSetIRQ
  2284.         push    es
  2285.         push    ds
  2286.         pop     es                      ; point to DSEG
  2287.         setDS   HSEG                    ; point to resident data
  2288.         call    es:[DevHlp]             ; release the IRQ line
  2289.         pop     es
  2290.         setDS   DSEG                    ; restore DS
  2291.  
  2292. deq60:
  2293.         popa
  2294.         ret
  2295.  
  2296. EndProc DeqComInfo
  2297.  
  2298. Procedure SetUpGDT, near
  2299. ; si = selector to set up
  2300. ; es:di -> request packet
  2301.  
  2302.         push    ax
  2303.         push    bx
  2304.         push    cx
  2305.         push    dx
  2306.  
  2307.         mov     ax,es:[di].IoPData._hi
  2308.         mov     bx,es:[di].IoPData._lo          ; (ax:bx)= physical xfer address
  2309.         mov     cx,es:[di].IOcount              ; (cx) = requested bytes
  2310.         mov     dx,DevHlp_PhysToGDTSelector
  2311.         call    [DevHlp]
  2312.  
  2313.         mov     es:[di].IoPData._hi,si
  2314.         mov     es:[di].IoPData._lo,0           ; physical xfer address = Sel:0
  2315.  
  2316.         pop     dx
  2317.         pop     cx
  2318.         pop     bx
  2319.         pop     ax
  2320.  
  2321.         ret
  2322. EndProc SetUpGDT
  2323.  
  2324. CSEG    ENDS
  2325.  
  2326. END
  2327.