home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / ATCOM / ATESP.ASM < prev    next >
Assembly Source File  |  1995-04-14  |  61KB  |  1,702 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 = @(#)atesp.asm    6.3 91/04/22
  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. ;       Modification History
  26. ;
  27. ;       ACW     04/16/91        @PVW Added perfview counters/timers
  28. ;       WDM     04/21/94        82548 - pvwxport.inc now included in atcom.inc
  29. ;
  30.  
  31.         .286p
  32.  
  33. .xlist
  34. ;  82548   include pvwxport.inc            ;@PVW
  35. include ateisa.inc
  36. include devhlp.inc
  37. include atcom.inc
  38. include realmac.inc
  39. include basemaca.inc
  40. include osmaca.inc
  41. include atesp.inc
  42. include atespmac.inc
  43.  
  44. .list
  45.  
  46.         EXTRNFAR        ComError
  47.         EXTRNFAR        SetBaud
  48.         EXTRNFAR        CheckLCR
  49.         EXTRNFAR        SetLineC
  50.         EXTRNFAR        ComputeHHS
  51.         EXTRNFAR        ComputeAPO
  52.         EXTRNFAR        ComputeWTO
  53.         EXTRNFAR        ComputeRTO
  54.         EXTRNFAR        EnableRemoteTX
  55.         EXTRNFAR        MxInt
  56.         extrn           endESPcode:byte
  57.  
  58. HSEG SEGMENT
  59.  
  60. ; All ABIOS request blocks must reside in driver's RESIDENT data segment
  61. ; (HSEG) because DevHlp_ABIOSCommonEntry requires that DS points to driver's
  62. ; RESIDENT data segment.
  63.         public  alloc_rb,dealloc_rb,disable_rb,tcount_rb,read_write_rb
  64.         public  alloc_ptr,dealloc_ptr,disable_ptr,tcount_ptr,read_write_ptr
  65.  
  66. alloc_rb        ArbLevelRB      <>
  67. alloc_ptr       dw              alloc_rb
  68. dealloc_rb      ArbLevelRB      <>
  69. dealloc_ptr     dw              dealloc_rb
  70. disable_rb      ArbLevelRB      <>
  71. disable_ptr     dw              disable_rb
  72. tcount_rb       TransCountRB    <>
  73. tcount_ptr      dw              tcount_rb
  74. read_write_rb   ReadWriteRB     <>
  75. read_write_ptr  dw              read_write_rb
  76.  
  77.         public  get_parms_ptr,read_pos_ptr
  78. get_parms_rb    GetParmsRB      <>
  79. get_parms_ptr   dw              get_parms_rb
  80. read_pos_rb     ReadPOSRB       <>
  81. read_pos_ptr    dw              read_pos_rb
  82. HSEG ENDS
  83.  
  84. DSEG SEGMENT
  85.         EXTRN   DevHlp:DWORD
  86.         EXTRN   Flags:BYTE
  87.         EXTRN   Kernel_Type:WORD
  88.  
  89. ports_using_DMA_lid             db      0       ;free DMA LID when this goes to zero
  90. DMA_lid                         dw      0       ;need this to talk to ABIOS
  91.         public FirstESP,SecondESP
  92. ; MASM/Link     fix start
  93. ;FirstESP        ESPInfo       <>
  94. ;SecondESP       ESPInfo       <>
  95. FirstESP        db size ESPInfo dup(-1)         ;port1 and port2 should be -1
  96. SecondESP       db size ESPInfo dup(-1)         ;port1 and port2 should be -1
  97. ; MASM/Link     fix end
  98.  
  99.         public  ESP1,ESP2
  100. ESP1    dw      FirstESP
  101. ESP2    dw      SecondESP
  102.  
  103. ESPcodelockh    db      lhlen   dup(0)
  104. ESPdatalockh    db      lhlen   dup(0)
  105.  
  106. DSEG ENDS
  107.  
  108. E_CSEG SEGMENT                  ; code specific to enhanced ports
  109.  
  110.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  111.  
  112.         public startESPcode
  113. startESPcode    label   byte            ; before any code in E_CSEG
  114.  
  115. ;**     E_LockSegments
  116. ;
  117. ;       Locks segment containg ESP-specific code
  118. ;
  119. ;       ENTRY   (ds:si) -> ComInfo
  120. ;
  121. ;       EXIT    'C' clear if lock successful
  122. ;               'C' set if lock failed
  123. ;
  124. Procedure E_LockSegments,FAR
  125.         ASSUME cs:E_CSEG,ds:DSEG,es:DSEG,ss:NOTHING
  126. .386p
  127.         SaveReg         <es,si>
  128.         setES   DSEG                    ; DevHlp is in DSEG
  129.  
  130.         ; lock ESP-specific code
  131.         ; do a virttolin DevHelp (linear address)
  132.         mov     ax,E_CSEG                       ; ESP-specific code segment
  133.         lea     esi,startESPcode
  134.         mov     dl,DevHlp_VirtToLin
  135.         call    es:[DevHlp]
  136.         mov     edi,eax
  137.         ; do a virttolin DevHelp (lockhandle)
  138.         mov     ax,DSEG                         ; lock handle is in DSEG
  139.         mov     esi,OFFSET ESPcodelockh
  140.         mov     dl,DevHlp_VirtToLin
  141.         call    es:[DevHlp]
  142.         ; do a VMLock DevHelp
  143.         mov     esi,eax         ; get offset to lock handle
  144.         mov     ebx,edi         ; get offset to area to lock
  145.         mov     edi,-1          ; set to no page list
  146.         lea     ecx,endESPcode ; size to lock
  147.         sub     ecx,OFFSET startESPcode ; size to lock
  148.         mov     eax,16          ; long term lock
  149.         mov     dl,DevHlp_VMLock
  150.         call    es:[DevHlp]
  151.         jnc     lockok
  152.  
  153. lockerr:stc
  154.         jmp     SHORT lockx
  155.  
  156.  lockok: SET    Flags,F_ESP_CODE_LOCKED
  157.         clc
  158. lockx:  RestoreReg      <si,es>
  159.         ret
  160. .286p
  161. EndProc E_LockSegments
  162.  
  163. ;**     E_UnLockSegments
  164. ;
  165. ;       Unlocks segment containg ESP-specific code
  166. ;
  167. ;       ENTRY   (ds:si) -> ComInfo
  168. ;
  169. Procedure E_UnLockSegments,FAR
  170.         ASSUME cs:E_CSEG,ds:DSEG,es:DSEG,ss:NOTHING
  171. .386p
  172.         ; unlock code
  173.         push    si
  174.         ; do a virttolin DevHelp (lockhandle)
  175.         mov     ax,DSEG
  176.         mov     esi,OFFSET ESPcodelockh
  177.         mov     dl,DevHlp_VirtToLin
  178.         DevHelp
  179.         ; do a VMUnlock DevHelp using previously saved lock handle
  180.         mov     esi,eax         ; get offset to lock handle
  181.         mov     dl,DevHlp_VMUnlock
  182.         DevHelp
  183.         pop     si
  184.         CLR     Flags,F_ESP_CODE_LOCKED
  185.         ret
  186.  
  187. .286p
  188. EndProc E_UnLockSegments
  189.  
  190. ;**     JustEnhancedMode
  191. ;
  192. ;       Sends ESP command to switch hw into enhanced mode. Either DMA or
  193. ;       PIO mode is chosen independently for tx and rx, based on ComInfo.
  194. ;
  195. ;       ENTRY   (ds:si) -> ComInfo
  196. ;
  197. Procedure JustEnhancedMode,FAR
  198.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  199.         xor     ah,ah
  200.         cmp     [si].ci_rx_request,DMA_REQ_DISABLE
  201.         je      em10
  202.  
  203.         SET     ah,ESP_MODE_RX_DMA
  204.         jmp     SHORT em20
  205.  
  206. em10:   CLR     ah,ESP_MODE_RX_DMA
  207. em20:   cmp     [si].ci_tx_request,DMA_REQ_DISABLE
  208.         je      em30
  209.  
  210.         SET     ah,ESP_MODE_TX_DMA
  211.         jmp     SHORT em40
  212.  
  213. em30:   CLR     ah,ESP_MODE_TX_DMA
  214. em40:   or      ah,ESP_MODE_ENHANCED
  215.  
  216.         SetMode ah
  217.  
  218.         ret
  219.  
  220. EndProc JustEnhancedMode
  221.  
  222. ;**     JustStandardMode
  223. ;
  224. ;       Sends ESP command to switch hw into standard mode.
  225. ;
  226. ;       ENTRY   (ds:si) -> ComInfo
  227. Procedure JustStandardMode,FAR
  228.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  229.  
  230.         SetMode ESP_MODE_S
  231.  
  232.         ret
  233.  
  234. EndProc JustStandardMode
  235.  
  236. ;**     SwtichToEnhanced
  237. ;
  238. ;       Does all that is necessary to switch port from standard to enhanced:
  239. ;          - sets up UART registers
  240. ;          - sends ESP setup commands
  241. ;          - deinstall interrupt handler for UART
  242. ;          - installs interrupt handler for ESP if necessary
  243. ;          - send ESP command to put this port in enhanced mode
  244. ;          - sets up ESP's interrupt mask
  245. ;       WARNING! The order of the above steps is very important!
  246. ;
  247. ;       ENTRY   (ds:si) -> ComInfo
  248. ;
  249. ;       EXIT    'C' clear if no problems
  250.  
  251. Procedure SwitchToEnhanced,FAR
  252.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  253.  
  254.         push    di                              ; ???????
  255.  
  256.         SET     [si].ci_eflags,EF_MODE_ENHANCED
  257.  
  258.         ; Go through ESP to set up UART's baud rate, LCR, and MCR.
  259.         mov     ax,[si].ci_baud
  260.         CALLFAR SetBaud                 ; does SetTriggerLevel, SetRxTimeout
  261.         mov     al,[si].ci_bytesize
  262.         mov     ah,[si].ci_parity
  263.         mov     ch,[si].ci_stopbits
  264.         CALLFAR CheckLCR                ; calculates LCR, puts it into (al)
  265.         CALLFAR SetLineC
  266.         mov     bx,0
  267.         CALLFAR ComputeHHS              ; does SetErrorMask, SetFCType
  268.  
  269.         ; Just to be safe, better send ALL port setup commands to ESP.
  270.         ; Must use "gate" mechanism, because other ESP port may be in
  271.         ; enhanced mode already.
  272.         SetFCLevel              HIGH(ESP_DEF_FC_LEVEL_OFF), \
  273.                                 LOW(ESP_DEF_FC_LEVEL_OFF), \
  274.                                 HIGH(ESP_DEF_FC_LEVEL_ON), \
  275.                                 LOW(ESP_DEF_FC_LEVEL_ON)
  276.         SetFlowOffTimeout       ESP_DEF_FLOW_OFF
  277.         FlushRxFIFO
  278.         FlushTxFIFO
  279.  
  280.         ; Always dump UART interrupt handler for this port's (standard) irq.
  281.         xor     bh,bh
  282.         mov     bl,[si].ci_irq                          ; standard irq
  283.         mov     dl,DevHlp_UnSetIRQ
  284.         ; Do fancy segment swapping so DevHlp is called with DS set to
  285.         ; driver's resident data segment.
  286.         setES   DSEG                            ; ES = segment for DevHlp ptr
  287.         setDS   HSEG                            ; DS = driver's resident data seg
  288.         call    es:[DevHlp]
  289.         setDS   DSEG                            ; restore DS
  290.  
  291.         ; Use info in ESPInfo to install ESP interrupt handler only if
  292.         ; other ESP port hasn't already.
  293.         ; Proper handler MUST be installed before switching to enhanced mode!
  294.         test    [di].pi_flagx,PIF_ONE_HAS_IRQ
  295.         jnz     swen30
  296.  
  297.         SET     [di].pi_flagx,PIF_ONE_HAS_IRQ
  298.         mov     ax,[di].pi_isr                  ; enhanced port isr
  299.         mov     bl,[di].pi_irq          ; enhanced port irq
  300.         xor     bh,bh
  301.         mov     dh,[si].ci_int_sharing          ; 0 on ISA, var. on EISA
  302.         mov     dl,DevHlp_SetIRQ                ; devhlp request code
  303.  
  304.         ; Do fancy segment swapping so DevHlp is called with DS set to
  305.         ; driver's resident data segment.
  306.         setES   DSEG                            ; ES = segment for DevHlp ptr
  307.         setDS   HSEG                            ; DS = driver's resident data seg
  308.         call    es:[DevHlp]
  309.         setDS   DSEG                            ; restore DS
  310.         ljc     swenx                           ; error, couldn't get IRQ
  311.  
  312. swen30:
  313.         ; ESP interrupt handler is registered -- now we can switch port to
  314.         ; enhanced mode.
  315.         call    JustEnhancedMode
  316.  
  317.         ; Set this port's bits in ESP's service mask
  318.         mov     ah,[di].pi_svcmask              ; (al) = current svc mask
  319.         cmp     [si].ci_cmd_offset,0
  320.         jne     swen40                          ; port2
  321.         SET     ah,ESP_SID_PORT1                ; turn on port1 bits in mask
  322.         CLR     ah,ESP_SID_TX1                  ; Tx enabled (later) by CheckTx
  323.         jmp     SHORT swen50
  324.  
  325. swen40: or      ah,ESP_SID_PORT2                ; turn on port2 bits in mask
  326.         CLR     ah,ESP_SID_TX2                  ; Tx enabled (later) by CheckTx
  327.  
  328. swen50: SET     ah,ESP_SID_DMAFIN               ; turn on DMA fin bit in mask
  329.         SET     ah,ESP_SID_DMATO                ; turn on DMA fin bit in mask
  330.         mov     [di].pi_svcmask,ah           ; save new svc mask
  331.  
  332.         ; Disable ALL ints while re-enabling ESP interrupts
  333.         cli
  334.         ISSUE   ESP_CMD_SETSVCMASK,ah
  335.         ISSUE   ESP_CMD_GDIPS
  336.         PREAD   ESP_R_STATUS1
  337.         sti
  338.         clc                                     ; show caller no problems
  339.  
  340. swenx:  pop     di                      ; ????????????
  341.         ret
  342.  
  343. EndProc SwitchToEnhanced
  344.  
  345.  
  346. ;**     SwtichToStandard
  347. ;
  348. ;       Does all that is necessary to switch port from enhanced to standard:
  349. ;          - disable ESP interrupts for this port
  350. ;          - deinstall interrupt handler for ESP if last open enhanced port
  351. ;          - install interrupt handler for UART on this port's standard IRQ
  352. ;          - send ESP commmand to put this port in standard mode
  353. ;          - set up UART registers
  354. ;       WARNING! The order of the above steps is very important!
  355. ;
  356. ;       ENTRY   (ds:si) -> ComInfo
  357. ;
  358. ;       EXIT    'C' clear if no problems
  359.  Procedure SwitchToStandard,FAR
  360.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  361.  
  362.         push    di                              ; ??????????????
  363.         mov     di,[si].ci_pinfo
  364.  
  365.         CLR     [si].ci_eflags,EF_MODE_ENHANCED
  366.  
  367.         ; Send ESP a new service mask to disable enhanced interrupts --
  368.         ; for this port ONLY.
  369.         mov     al,[di].pi_svcmask
  370.         cmp     [si].ci_cmd_offset,0
  371.         jne     sws5
  372.         CLR     al,ESP_SID_PORT1
  373.         jmp     SHORT sws10
  374.  
  375. sws5:   CLR     al,ESP_SID_PORT2
  376. sws10:  mov     [di].pi_svcmask,al              ; save new svc mask
  377.         SetSvcMask      al
  378.  
  379.         ; Dump ESP interrupt handler only if other ESP port is NOT using the
  380.         ; (enhanced) interrupt.
  381.         push    si
  382.         cmp     [si].ci_cmd_offset,0
  383.         jne     sws20
  384.  
  385.         ; We're ESP port1, so examine port2 ComInfo
  386.         mov     si,[di].pi_port2
  387.         jmp     SHORT sws30
  388.  
  389.         ; We're ESP port2, so examine port1 ComInfo
  390. sws20:  mov     si,[di].pi_port1
  391.  
  392. sws30:
  393.         ; (si) -> ComInfo pointer for "other" port on ESP board.
  394.         test    [si].ci_eflags,EF_MODE_ENHANCED ; other port enhanced?
  395.         jz      sws35                           ; no, release irq
  396.         cmp     [si].ci_nopens,0                ; other port open?
  397.         je      sws35                           ; no, release irq
  398.         jmp     SHORT sws40                     ; don't release irq
  399.  
  400. sws35:  xor     bh,bh
  401.         mov     bl,[di].pi_irq                  ; enhanced irq
  402.         mov     dl,DevHlp_UnSetIRQ
  403.         ; Do fancy segment swapping so DevHlp is called with DS set to
  404.         ; driver's resident data segment.
  405.         setES   DSEG                            ; ES = segment for DevHlp ptr
  406.         setDS   HSEG                            ; DS = driver's resident data seg
  407.         call    es:[DevHlp]
  408.         setDS   DSEG                            ; restore DS
  409.  
  410.         CLR     [di].pi_flagx,PIF_ONE_HAS_IRQ
  411.  
  412. sws40:  pop     si                              ; (ds:si) -> original ComInfo
  413.  
  414.         ; Use info in ComInfo to install regular UART interrupt handler
  415.         ; for this port's irq.
  416.         ; Proper handler MUST be installed before switching to standard mode!
  417.         mov     ax,[si].ci_isr                  ; standard port isr
  418.         mov     bl,[si].ci_irq                  ; standard port irq
  419.         xor     bh,bh
  420.         mov     dh,[si].ci_int_sharing          ; 0 on ISA, var. on EISA
  421.         mov     dl,DevHlp_SetIRQ                ; devhlp request code
  422.  
  423.         ; Do fancy segment swapping so DevHlp is called with DS set to
  424.         ; driver's resident data segment.
  425.         setES   DSEG                            ; ES = segment for DevHlp ptr
  426.         setDS   HSEG                            ; DS = driver's resident data seg
  427.         call    es:[DevHlp]
  428.         setDS   DSEG                            ; restore DS
  429.  
  430.         ljc     swsx                            ; error, couldn't get IRQ
  431.  
  432.         ; UART interrupt handler is registered -- now we can switch port to
  433.         ; standard mode. Once we do this, the UART can begin generating
  434.         ; interrupts. But wait, the UART registers (baud,LCR,etc.) aren't
  435.         ; set up properly yet! So make the ISR ignore interrupts temporarily
  436.         ; by settings ci_nopens to zero.
  437.         push    [si].ci_nopens
  438.         mov     [si].ci_nopens,0
  439.         SetMode         ESP_MODE_S
  440.  
  441.         ; Set up UART's baud rate, LCR, and MCR.
  442.         mov     ax,[si].ci_baud
  443.         CALLFAR SetBaud
  444.         mov     al,[si].ci_bytesize
  445.         mov     ah,[si].ci_parity
  446.         mov     ch,[si].ci_stopbits
  447.         CALLFAR CheckLCR                ; calculates LCR, puts it into (al)
  448.         CALLFAR SetLineC
  449.  
  450.         ; Set up rest of UART stuff.
  451.         mov     dx,[si].ci_port         ; (dx) -> port base address
  452.         add     dx,R_LINES              ; (dx) -> LSR
  453.         min     al,dx                   ; (al) = LSR (clear it)
  454.         mov     [si].ci_lsrshadow,al    ; shadow the contents of LSR
  455.         add     dx,R_DATA-R_LINES       ; (dx) -> data reg
  456.         min     al,dx                   ; clear RX buffer
  457.         add     dx,R_FIFOC-R_DATA       ; (dx) -> fifo control reg
  458.         test    [si].ci_dcb_flags3,F3_FIFO_HW_ON
  459.         jz      sws50                   ; FIFO HW off
  460.         mov     al,[si].ci_dcb_flags3   ; (al) = flags3
  461.         and     al,F3_RX_MASK           ; (al) = RX trigger level
  462.         shl     al,1                    ; (al) = RX trigger level bits for FIFO
  463.         or      al,FF_ENABLE OR FF_CLEAR_RX OR FF_CLEAR_TX
  464.         mout    dx,al                   ; clear RX and TX FIFOs
  465.  
  466. sws50:
  467.         .errnz  R_INTID-R_FIFOC
  468.         add     dx,R_INTID-R_FIFOC      ; (dx) -> int id reg.
  469.         min     al,dx                   ; clear int id
  470.  
  471.         mov     [si].ci_msrshadow,0     ; zero previous msrshadow
  472.         add     dx,R_MODMS-R_INTID      ; (dx) -> modem status reg.
  473.         min     al,dx                   ; clear modem status
  474.         CALLFAR MxInt                   ; update msrshadow
  475.  
  476.         xor     bx,bx                   ; show 0 for previous flags1 and flags2
  477.         CALLFAR ComputeHHS              ; set up handshake state and
  478.                                         ; initialize the MCR
  479.         CALLFAR EnableRemoteTX          ; we're all set up, tell the remote TXer
  480.  
  481.         cli                     ; disable processor interrupts before
  482.                                 ; enabling 16450 chip interrupts
  483.  
  484.         ; Enable Receive Data and nModem Status interrupts.
  485.         ; TX Holding Register interrupt will be enabled by CheckTx.
  486.         mov     dx,[si].ci_port         ; (dx) -> port
  487.         add     dx,R_INTEN              ; (dx) -> interrupt enable reg
  488.         mov     al,IE_RX OR IE_MX       ; (al) = interrupts to enable
  489.         mout    dx,al
  490.  
  491.         ; Finished with UART set up, so restore ci_nopens and interrupt
  492.         ; handler will process interrupts once again.
  493.         pop     [si].ci_nopens          ; count the open calls
  494.         sti
  495.         clc                             ; show caller no problem
  496.  
  497. swsx:   pop     di
  498.         ret
  499.  
  500. EndProc SwitchToStandard
  501.  
  502.  
  503. ;**     E_CheckTX
  504. ;
  505. ;       Enables/disables TxFIFO interrupt for a port
  506. ;
  507. ;       ENTRY   (ds:si) -> ComInfo
  508. ;
  509. ;       EXIT    'C' clear if TX disabled
  510. ;               'C' set if TX enabled
  511. Procedure E_CheckTX,FAR
  512.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  513.  
  514.         ChkComInfoPtr
  515.  
  516.         mov     di,[si].ci_pinfo
  517.  
  518.         cmp     [si].ci_w_rp._hi,0
  519.         jz      ctxoff                  ; no data enqueued, disable TxFIFO
  520.  
  521.         test    [si].ci_hsflag,HS_BREAK_SET
  522.         jnz     ctxoff
  523.  
  524.         test    [si].ci_hsflag,HS_XOFF_RECEIVED
  525.         jnz     ctxoff                  ; act like XOFF received, disable TxFIFO
  526.  
  527.         ; Enable transmit interrupts
  528.         mov     al,[di].pi_svcmask
  529.         cmp     [si].ci_cmd_offset,0
  530.         jne     ctx25
  531.         ; Enable TxFIFO for port1
  532.         SET     al,ESP_SVC_MASK_TX1
  533.         jmp     SHORT ctx26
  534.  
  535. ctx25:  ; Enable TxFIFO for port2
  536.         SET     al,ESP_SVC_MASK_TX2
  537. ctx26:  clc                                     ; 'C' clear - TX disabled
  538.         jmp     ctx40
  539.  
  540.         ; Disable transmit interrupts
  541. ctxoff: mov     al,[di].pi_svcmask
  542.         cmp     [si].ci_cmd_offset,0
  543.         jne     ctx35
  544.         ; Disable TxFIFO for por1
  545.         CLR     al,ESP_SVC_MASK_TX1
  546.         jmp     ctx37
  547.  
  548. ctx35:  ; Disable TxFIFO for port2
  549.         CLR     al,ESP_SVC_MASK_TX2
  550. ctx37:  stc
  551.  
  552. ctx40:  pushf                           ; save C flag for caller
  553.         mov     [di].pi_svcmask,al
  554.         mov     dx,[di].pi_address
  555.         ; Disable ALL ints while re-enabling ESP interrupts
  556.         CLI
  557. ctx50:  in      al,dx
  558.         test    al,ESP_RDY_CMD1
  559.         jz      ctx50
  560.         add     dx,ESP_R_CMD1-ESP_R_RDY
  561.         mov     al,ESP_CMD_SETSVCMASK
  562.         out     dx,al
  563.         add     dx,ESP_R_RDY-ESP_R_CMD1
  564. ctx60:  in      al,dx
  565.         test    al,ESP_RDY_CMD2
  566.         jz      ctx60
  567.         add     dx,ESP_R_CMD2-ESP_R_RDY
  568.         mov     al,[di].pi_svcmask
  569.         out     dx,al
  570.         ; Issue GetDips to be *SURE* that ESP has processed SetSvcMask before
  571.         ; we re-enable interrupts
  572.         mov     dx,[di].pi_address
  573. ctx70:  in      al,dx
  574.         test    al,ESP_RDY_CMD1
  575.         jz      ctx70
  576.         add     dx,ESP_R_CMD1-ESP_R_RDY
  577.         mov     al,ESP_CMD_GDIPS
  578.         out     dx,al
  579.         add     dx,ESP_R_RDY-ESP_R_CMD1
  580. ctx80:  in      al,dx
  581.         test    al,ESP_RDY_STATUS1
  582.         jz      ctx80
  583.         add     dx,ESP_R_STATUS1-ESP_R_RDY
  584.         in      al,dx
  585.  
  586.         STI
  587.         ASSUME  ds:NOTHING
  588.         POPFF                           ; restore C flag for caller
  589.  
  590.         ret
  591.  
  592. EndProc E_CheckTX
  593.  
  594.  
  595. Procedure E_Init_For_ABIOS_DMA,FAR
  596.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  597.  
  598.         SaveReg         <si,ds,es>
  599.  
  600.         ; Fill in ABIOS structures now so DMA can be used later.
  601.         ; First step is to ask for logical ID for DMA device.
  602.         inc     ports_using_DMA_lid
  603.         cmp     ports_using_DMA_lid,1   ; Only port using DMA LID?
  604.         ljne    edma_x                   ; Yes, don't get LID -- strucs already filled in
  605.         mov     al,DEVICE_ID_DMA
  606.         mov     bl,0                    ; first avail LID
  607.         mov     dh,1                    ; must be 1 to get DMA device
  608.         mov     dl,DevHlp_GetLIDEntry
  609.         DevHelp                         ; (ax) = LID
  610.         jnc     edma_lid
  611.         jmp     edma_x                  ; 'C' set tells caller error occurred
  612. edma_lid:
  613.         mov     DMA_lid,ax
  614.  
  615.         ; Got that LID, ask ABIOS for length of DMA request block.
  616.         mov     cx,ax                   ; (cx) DMA LID from DevHlp
  617.         setDS   HSEG                    ; get_parms_rb is in HSEG
  618.         lea     si,get_parms_rb
  619.         mov     [si].lid,ax
  620.         mov     [si].func,ABIOS_FUNC_RETURNPARMS
  621.         mov     [si].len,20h            ; ABIOS doc says this is fixed at 20h
  622.         mov     [si].retval,0FFFFh
  623.         sub     ax,ax
  624.         mov     WORD PTR [si].res,ax
  625.         mov     WORD PTR [si].res+2,ax
  626.  
  627.         mov     dh,0                            ; use Start entry point
  628.         mov     dl,DevHlp_ABIOSCommonEntry
  629.         ; Do fancy segment swapping so DevHlp is called with DS set to
  630.         ; driver's resident data segment.
  631.         setES   DSEG                            ; ES = segment for DevHlp ptr
  632.         call    es:[DevHlp]                     ; DS = RESIDENT data segment
  633.         jnc     eop_arbstruc
  634.         cmp     [si].retval,0
  635.         je      eop_arbstruc
  636.         ; Can't use DMA because of problem with ABIOS. Free LID entry and
  637.         ; return with 'C' set to notify caller of error.
  638.         dec     es:ports_using_DMA_lid
  639.         jnz     lid_in_use
  640.         mov     ax,DMA_lid
  641.         mov     dl,DevHlp_FreeLIDEntry
  642.         call    es:[DevHlp]
  643. lid_in_use:
  644.         stc                                     ; 'C' set tells caller error occurred
  645.         jmp     SHORT edma_x
  646.  
  647. eop_arbstruc:
  648.         mov     ax,[si].rblen           ; (ax) = DMA rb length
  649.         ; Now that we know the DMA Request Block length, fill in specific
  650.         ; Request Block strucs for use at interrupt time.
  651.         lea     si,alloc_rb
  652.         mov     [si].arblid,cx          ; (cx) = LID from DevHlp
  653.         mov     [si].arblen,ax          ; (ax) = DMA rb length from above
  654.         mov     [si].arbunit,0          ; first unit within LID
  655.         mov     [si].arbtime,0
  656.         lea     si,dealloc_rb
  657.         mov     [si].arblid,cx          ; (cx) = LID from DevHlp
  658.         mov     [si].arblen,ax          ; (ax) = DMA rb length from above
  659.         mov     [si].arbunit,0          ; first unit within LID
  660.         mov     [si].arbtime,0
  661.         lea     si,disable_rb
  662.         mov     [si].arblid,cx          ; (cx) = LID from DevHlp
  663.         mov     [si].arblen,ax          ; (ax) = DMA rb length from above
  664.         mov     [si].arbunit,0          ; first unit within LID
  665.         mov     [si].arbtime,0
  666.         lea     si,tcount_rb
  667.         mov     [si].tclid,cx           ; (cx) = LID from DevHlp
  668.         mov     [si].tclen,ax           ; (ax) = DMA rb length from above
  669.         mov     [si].tcunit,0           ; first unit within LID
  670.         lea     si,read_write_rb
  671.         mov     [si].rwlid,cx           ; (cx) = LID from DevHlp
  672.         mov     [si].rwlen,ax           ; (ax) = DMA rb length from above
  673.         mov     [si].rwunit,0           ; first unit within LID
  674.         clc
  675.  
  676. edma_x:
  677.         RestoreReg      <es,ds,si>
  678.         ret
  679.  
  680. EndProc E_Init_For_ABIOS_DMA
  681.  
  682. ;**     E_Open
  683. ;
  684. ;       Must take extra steps to open an enhanced port:
  685. ;          - initialize ComInfo.eflags
  686. ;          - send ESP set up commands
  687. ;          - store physical address of in/out ques for use at interrupt time
  688. ;          - send ESP SetIRQ command to set up IRQ and DMA channel
  689. ;          - enable ESP interrupts for this port
  690. ;          - send command to put this port into enhanced mode
  691. ;
  692. ;       ENTRY   (ds:si) -> ComInfo
  693. ;
  694. ;       EXIT    'C' clear if TX disabled
  695. ;               'C' set if TX enabled
  696. Procedure E_Open,FAR
  697.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  698.  
  699.         mov     [si].ci_rx_request,DMA_REQ_AUTO
  700.         mov     [si].ci_tx_request,DMA_REQ_AUTO
  701.         SET     [si].ci_eflags,EF_RX_REQUEST_DEF_DMA
  702.         CLR     [si].ci_eflags,EF_RX_REQUEST_NOT_PIO
  703.         SET     [si].ci_eflags,EF_TX_REQUEST_DEF_DMA
  704.         CLR     [si].ci_eflags,EF_TX_REQUEST_NOT_PIO
  705.         SET     [si].ci_eflags,EF_LAST_RX_WAS_DMA
  706.         SET     [si].ci_eflags,EF_LAST_TX_WAS_DMA
  707.  
  708.         ; Read LSR and MSR
  709.         GetUARTStatus                   ; (al) = LSR, (ah) = MSR
  710.         mov     [si].ci_lsrshadow,al
  711.         mov     [si].ci_msrshadow,ah
  712.         xor     bx,bx                           ; show 0 for previous flags1
  713.                                                 ; and flags2
  714.         CALLFAR ComputeHHS                      ; set up handshake state and
  715.                                                 ; issue SetFCType and SetErrMask
  716.  
  717.         LocalXon                                ; spec says "first-level open
  718.                                                 ; will cause driver to believe
  719.                                                 ; it has NOT received an XOFF"
  720.         SetFCLevel              HIGH(ESP_FC_LEVEL_OFF),LOW(ESP_FC_LEVEL_OFF),HIGH(ESP_FC_LEVEL_ON),LOW(ESP_FC_LEVEL_ON)
  721.         SetFlowOffTimeout       ESP_DEF_FLOW_OFF
  722.         FlushRxFIFO
  723.         FlushTxFIFO
  724.  
  725.         ; Get phys address of in and out queues -- used at int time for DMA
  726. eop10:  lea     bx,[si].ci_qin_q
  727.         SaveReg         <si>
  728.         mov     si,bx                   ; (ds:si) = virtual address to convert
  729.         mov     dl,DevHlp_VirtToPhys
  730.         call    [DevHlp]
  731.         RestoreReg      <si>
  732.         jnc     eop20
  733.  
  734.         ComErr  <VirtToPhys failed>,CALLFAR
  735.  
  736. eop20:  mov     WORD PTR [si].ci_qin.ioq_phys._hi,ax
  737.         mov     WORD PTR [si].ci_qin.ioq_phys._lo,bx
  738.  
  739.         lea     bx,[si].ci_qout_q
  740.         SaveReg         <si>
  741.         mov     si,bx                   ; (ds:si) = virtual address to convert
  742.         mov     dl,DevHlp_VirtToPhys
  743.         call    [DevHlp]
  744.         RestoreReg      <si>
  745.         jnc     eop30
  746.  
  747.         ComErr  <VirtToPhys failed>,CALLFAR
  748.  
  749. eop30:  mov     WORD PTR [si].ci_qout.ioq_phys._hi,ax
  750.         mov     WORD PTR [si].ci_qout.ioq_phys._lo,bx
  751.  
  752.         ; FIX THIS: Should ask VDMA if DMA channel available for receive,
  753.         ; if not don't use DMA. If user didn't specify, do we use 1 or 3?
  754.         mov     di,[si].ci_pinfo        ; Look at ESPInfo
  755.         cmp     [di].pi_DMA_chan,-1     ; did parameter specify DMA channel?
  756.         jne     dma_done                ; yes
  757.         mov     [di].pi_DMA_chan,1      ; assume adapter is first ESP, use 1
  758.         cmp     di,es:ESP1
  759.         je      dma_done
  760.         mov     [di].pi_DMA_chan,3      ; adapter is second ESP, use 3
  761.  
  762. dma_done:
  763.         mov     al,[di].pi_irq
  764.         cmp     al,3                    ; build irq/dma mask
  765.         jne     eop40
  766.         mov     al,2
  767.         jmp     SHORT eop60
  768.  
  769. eop40:  cmp     al,5
  770.         jne     eop50
  771.         mov     al,6
  772.         jmp     SHORT eop60
  773.  
  774. eop50:  cmp     al,9
  775.         jne     eop60
  776.         mov     al,0
  777.  
  778.         ; last case is irq_level=4, but mask for that value is also 4
  779. eop60:  SET     al,ESP_INT_ENABLE
  780.         mov     ah,[di].pi_DMA_chan
  781.         shl     ah,4
  782.         or      ah,al
  783.         SetIRQ  ah
  784.  
  785.         ; Send ESP a new service mask, with non-zero bits for OUR PORT ONLY.
  786. eop65:  cli                             ; disable processor interrupts before
  787.                                         ; enabling ESP interrupts
  788.  
  789.         mov     al,[di].pi_svcmask           ; (al) = current svc mask
  790.         cmp     [si].ci_cmd_offset,0
  791.         jne     eop70                           ; port2
  792.         SET     al,ESP_SID_PORT1                ; turn on port1 bits in mask
  793.         CLR     al,ESP_SID_TX1                  ; Tx enabled (later) by CheckTx
  794.         jmp     SHORT eop80
  795.  
  796. eop70:  or      al,ESP_SID_PORT2                ; turn on port2 bits in mask
  797.         CLR     al,ESP_SID_TX2                  ; Tx enabled (later) by CheckTx
  798.  
  799. eop80:  SET     al,ESP_SID_DMAFIN               ; turn on DMA fin bit in mask
  800.         SET     al,ESP_SID_DMATO                ; turn on DMA fin bit in mask
  801.         mov     [di].pi_svcmask,al           ; save new svc mask
  802.         SetSvcMask      al
  803.  
  804.         ;issue mode command
  805.         xor     ah,ah
  806.         cmp     [si].ci_rx_request,DMA_REQ_DISABLE
  807.         je      eop90
  808.  
  809.         SET     ah,ESP_MODE_RX_DMA
  810.         jmp     SHORT eop95
  811.  
  812. eop90:  CLR     ah,ESP_MODE_RX_DMA
  813. eop95:  cmp     [si].ci_tx_request,DMA_REQ_DISABLE
  814.         je      eop100
  815.  
  816.         SET     ah,ESP_MODE_TX_DMA
  817.         jmp     SHORT eop105
  818.  
  819. eop100: CLR     ah,ESP_MODE_TX_DMA
  820. eop105: or      ah,ESP_MODE_ENHANCED
  821.  
  822.         SetMode ah
  823.  
  824.         ret
  825.  
  826. EndProc E_Open
  827.  
  828. ;**     E_Close
  829. ;
  830. ;       Must take extra steps to close an enhanced port:
  831. ;          - disable ESP interrupts for this port
  832. ;          - deinstall ESP interrupt handler
  833. ;
  834. ;       ENTRY   (ds:si) -> ComInfo
  835. ;
  836. ;       EXIT    'C' clear if TX disabled
  837. ;               'C' set if TX enabled
  838. Procedure E_Close,FAR
  839.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  840.  
  841.         SaveReg         <ds,es>
  842.  
  843.         ; Flush ESP's RxFIFO -- he'll flow remote transmitter on if necessary.
  844.         FlushRxFIFO
  845.         xor     ax,ax
  846.         SetFCType       ah,al           ; lower RTS and DTR
  847.  
  848.         ; Send ESP a new service mask to ignore interrupts from our port.
  849.         mov     di,[si].ci_pinfo
  850.         mov     al,[di].pi_svcmask
  851.         cmp     [si].ci_cmd_offset,0
  852.         jne     ec10
  853.         CLR     al,ESP_SID_PORT1
  854.         jmp     SHORT ec20
  855.  
  856. ec10:   CLR     al,ESP_SID_PORT2
  857. ec20:   mov     [di].pi_svcmask,al              ; save new svc mask
  858.         SetSvcMask      al
  859.  
  860.         ; Don't release IRQ if:
  861.         ;    - interrupt sharing
  862.         ;    - other ESP port is both enhanced and open
  863.         test    [si].ci_int_sharing, INT_SHARING ; sharing the IRQ?
  864.         ljnz    ec70                            ; yes, don't release irq
  865.         SaveReg         <si>
  866.         mov     di,[si].ci_pinfo
  867.         cmp     [si].ci_cmd_offset,0
  868.         jne     ec30
  869.  
  870.         ; We're ESP port1, so examine port2 ComInfo
  871.         cmp     [di].pi_port2,0                 ; does other port exist?
  872.         je      ec50                            ; no, pop di, pop si and release irq
  873.         mov     si,[di].pi_port2
  874.         jmp     SHORT ec40
  875.  
  876.         ; We're ESP port2, so examine port1 ComInfo
  877. ec30:   cmp     [di].pi_port1,0                 ; does other port exist?
  878.         je      ec50                            ; no, pop di, pop si and release irq
  879.         mov     si,[di].pi_port1
  880.  
  881.         ; (si) -> ComInfo pointer for "other" port on ESP board.
  882. ec40:   test    [si].ci_eflags,EF_MODE_ENHANCED ; other port enhanced?
  883.         jz      ec50                            ; no, pop di, pop si and release irq
  884.         cmp     [si].ci_nopens,0                ; other port open?
  885.         je      ec50                            ; no, pop di, pop si and release irq
  886.  
  887.         ; OK, now we know the other ESP port on this board is still using
  888.         ; the irq, so don't release the irq.
  889.         pop     si
  890.         jmp     ec60
  891.  
  892.         ; OK, now we know the other ESP port on this board is NOT using
  893.         ; the irq, so we will release the irq.
  894. ec50:   xor     bh,bh
  895.         mov     bl,[di].pi_irq
  896.         mov     dl,DevHlp_UnSetIRQ
  897.  
  898.         ; Do fancy segment swapping so DevHlp is called with DS set to
  899.         ; driver's resident data segment.
  900.         setES   DSEG                            ; ES = segment for DevHlp ptr
  901.         setDS   HSEG                            ; DS = driver's resident data seg
  902.         call    es:[DevHlp]
  903.         setDS   DSEG                            ; restore DS
  904.         RestoreReg      <si>
  905.         CLR     [di].pi_flagx,PIF_ONE_HAS_IRQ
  906.         jnc     ec60
  907.  
  908.         ComErr  <ComClose : could not release the IRQ>,CALLFAR
  909.  
  910.         ; Now that the IRQ is released, the ISR won't run again, so we can
  911.         ; clear PIF_PECAN_BUSY.
  912. ec60:   mov     di,[si].ci_pinfo
  913.         CLR     [di].pi_flagx,PIF_PECAN_BUSY
  914.  
  915.         ; If we're the only enhanced port left open, we can free the DMA LID
  916.         ; entry we've been using to talk to ABIOS.
  917.         cmp     kernel_type,ABIOS_COM
  918.         jne     ec70
  919.         dec     ports_using_DMA_lid
  920.         jnz     ec70
  921.         mov     ax,DMA_lid
  922.         mov     dl,DevHlp_FreeLIDEntry
  923.         ; Do fancy segment swapping so DevHlp is called with DS set to
  924.         ; driver's resident data segment.
  925.         setES   DSEG                            ; ES = segment for DevHlp ptr
  926.         setDS   HSEG                            ; DS = driver's resident data seg
  927.         call    es:[DevHlp]
  928.  
  929. ec70:
  930.         RestoreReg      <es,ds>
  931.         ret
  932.  
  933. EndProc E_Close
  934.  
  935. ;**     E_WStat
  936. ;
  937. ;       Answers the question: can the enhanced port transmit?
  938. ;
  939. ;       ENTRY   (ds:si) -> ComInfo
  940. ;
  941. ;       EXIT    'C' clear if CAN transmit
  942. ;               'C' set if CAN'T transmit
  943. Procedure E_WStat,FAR
  944.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  945.  
  946. .386
  947.         GetErrorStatus                  ; (al) = error1; (ah) = error2
  948.         bt      ah,ESP_ERR2_ONLOCAL             ; (ah) = error2
  949.         ; carry set if busy, carry clear if able to transmit
  950.         ret
  951.  
  952. EndProc E_WStat
  953.  
  954. ;**     E_RFlush
  955. ;
  956. ;       Sends ESP command to clear receive FIFOs
  957. ;
  958. ;       ENTRY   (ds:si) -> ComInfo
  959. ;
  960. Procedure E_RFlush,FAR
  961.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  962.  
  963.         ; Flush ESP's buffers, and he'll enable remote transmitter.
  964.         FlushRxFIFO
  965.  
  966.         ret
  967.  
  968. EndProc E_RFlush
  969.  
  970. ;**     E_HHS - compute hardware handshake signals for enhanced port
  971. ;
  972. ;       E_HHS sets up ESP for appropriate flow control type for this port
  973. ;
  974. ;       May raise or lower DTR or RTS depending on flags1 and flags2
  975. ;       and the previous values of flags1 and flgas2.
  976. ;
  977. ;       Set hhslines and outhhslines depending on flags1 and flags2.
  978. ;
  979. ;       ENTRY   (ds:si) -> ComInfo
  980. ;               (bl) = previous flags1
  981. ;               (bh) = previous flags2
  982. ;
  983. ;       EXIT
  984. ;
  985. ;       USES    ax bx dx
  986. Procedure E_HHS,FAR
  987.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  988.  
  989.         SaveReg        <bx>
  990.  
  991.         ; process DTR
  992.         and     bl,F1_DTR_MASK                  ; (bl) = old DTR bits
  993.         mov     ah,[si].ci_dcb_flags1           ; (ah) = flags1
  994.         and     ah,F1_DTR_MASK                  ; (ah) = new DTR bits
  995.         cmp     ah,bl
  996.         je      ehh20                           ; no change to DTR, do RTS
  997.  
  998.         test    ah,F1_DTR_FLOW
  999.         jnz     ehh10                           ; DTR is handshake line
  1000.  
  1001.         ; enable/disable DTR
  1002.         CLR     [si].ci_esp_flow1,ESP_FC1_RX_DTR        ; ESP does NOT use DTR
  1003.         test    ah,F1_DTR_ENABLE
  1004.         jz      ehh5
  1005.  
  1006.         SET     [si].ci_esp_flow1,ESP_FC1_ON_DTR        ; enable DTR
  1007.         jmp     SHORT ehh20                     ; finished with DTR, do RTS
  1008.  
  1009. ehh5:   CLR     [si].ci_esp_flow1,ESP_FC1_ON_DTR        ; disable DTR
  1010.         jmp     SHORT ehh20                     ; finished with DTR, do RTS
  1011.  
  1012.         ; DTR is handshake line
  1013. ehh10:  SET     [si].ci_esp_flow1,ESP_FC1_RX_DTR        ; ESP uses DTR
  1014.         CLR     [si].ci_esp_flow1,ESP_FC1_ON_DTR        ; ESP does NOT use DTR
  1015.  
  1016.         ; process RTS
  1017. ehh20:  and     bh,F2_RTS_MASK                  ; (bh) = old RTS bits
  1018.         mov     ah,[si].ci_dcb_flags2           ; (ah) = flags2
  1019.         and     ah,F2_RTS_MASK                  ; (ah) = new RTS bits
  1020.         cmp     ah,bh
  1021.         je      ehh40                           ; no change to RTS, do XOFF
  1022.  
  1023.         cmp     ah,F2_RTS_FLOW
  1024.         je      ehh30                           ; RTS is handshake line
  1025.  
  1026.         ; enable/disable RTS
  1027.         CLR     [si].ci_esp_flow1,ESP_FC1_RX_RTS        ; ESP does NOT use RTS
  1028.  
  1029.         ; if RTS toggling, turn off RTS for now
  1030.         cmp     ah,F2_RTS_TOGGLE
  1031.         je      ehh25
  1032.         test    ah,F2_RTS_ENABLE
  1033.         jz      ehh25
  1034.  
  1035.         SET     [si].ci_esp_flow1,ESP_FC1_ON_RTS        ; enable RTS
  1036.         jmp     SHORT ehh40                     ; finished with RTS, do XOFF
  1037.  
  1038. ehh25:  CLR     [si].ci_esp_flow1,ESP_FC1_ON_RTS        ; disable RTS
  1039.         jmp     SHORT ehh40                     ; finished with RTS, do XOFF
  1040.  
  1041.         ; RTS is handshake line
  1042. ehh30:  SET     [si].ci_esp_flow1,ESP_FC1_RX_RTS; ESP uses RTS
  1043.         CLR     [si].ci_esp_flow1,ESP_FC1_ON_RTS
  1044.  
  1045.         ; process input XON/XOFF
  1046. ehh40:  RestoreReg     <bx>                     ; (bl) = previous flags1,
  1047.                                                 ; (bh) = previous flags2
  1048.         SaveReg        <bx>
  1049.         mov     bl,bh                           ; (bl) = (bh) = previous flags2
  1050.         mov     ah,[si].ci_dcb_flags2           ; (ah) = flags2
  1051.         and     ah,F2_IN_XO                     ; (ah) = new input XON bit
  1052.         and     bh,F2_IN_XO                     ; (bh) = old input XON bit
  1053.         cmp     ah,bh
  1054.         je      ehh50                           ; no change to input XON,
  1055.                                                 ; do output XON
  1056.  
  1057.         test    ah,F2_IN_XO
  1058.         jz      ehh45
  1059.         SET     [si].ci_esp_flow1,ESP_FC1_RX_XO ; ESP uses input XON/XOFF
  1060.         jmp     SHORT ehh50
  1061.  
  1062. ehh45:  CLR     [si].ci_esp_flow1,ESP_FC1_RX_XO ; ESP does NOT use input XON/XOFF
  1063.  
  1064.         ; process output XON/XOFF
  1065. ehh50:  mov     ah,[si].ci_dcb_flags2           ; (ah) = flags2
  1066.         and     ah,F2_OUT_XO                    ; (ah) = new output XON bit
  1067.         and     bl,F2_OUT_XO                    ; (bl) = old output XON bit
  1068.         cmp     ah,bl
  1069.         je      ehh60                           ; no change to output XON, do CTS
  1070.  
  1071.         test    ah,F2_OUT_XO
  1072.         jz      ehh55
  1073.         SET     [si].ci_esp_flow1,ESP_FC1_TX_XO ; ESP uses output XON/XOFF
  1074.         jmp     SHORT ehh60
  1075.  
  1076. ehh55:  CLR     [si].ci_esp_flow1,ESP_FC1_TX_XO ; ESP does NOT use output XON/XOFF
  1077.  
  1078.         ; process CTS
  1079. ehh60:  RestoreReg     <bx>                     ; (bl) = previous flags1,
  1080.                                                 ; (bh) = previous flags2
  1081.         SaveReg        <bx>
  1082.         mov     bh,bl                           ; (bh) = (bl) = previous flags1
  1083.         mov     ah,[si].ci_dcb_flags1           ; (ah) = flags1
  1084.         and     ah,F1_OUT_CTS_FLOW              ; (ah) = new CTS bits
  1085.         and     bl,F1_OUT_CTS_FLOW              ; (bl) = old CTS bits
  1086.         cmp     ah,bl
  1087.         je      ehh70                           ; no change to CTS, do DSR
  1088.  
  1089.         test    ah,F1_OUT_CTS_FLOW
  1090.         jz      ehh65
  1091.         SET     [si].ci_esp_flow2,ESP_FC2_TX_CTS; ESP uses CTS
  1092.         jmp     SHORT ehh70
  1093.  
  1094. ehh65:  CLR     [si].ci_esp_flow2,ESP_FC2_TX_CTS; ESP does not use CTS
  1095.  
  1096.         ; process DSR
  1097. ehh70:  mov     ah,[si].ci_dcb_flags1           ; (ah) = flags1
  1098.         and     ah,F1_OUT_DSR_FLOW              ; (ah) = new DSR bits
  1099.         and     bh,F1_OUT_DSR_FLOW              ; (bl) = old DSR bits
  1100.         cmp     ah,bh
  1101.         je      ehh80                           ; no change DSR
  1102.  
  1103.         test    ah,F1_OUT_DSR_FLOW
  1104.         jz      ehh75
  1105.         SET     [si].ci_esp_flow2,ESP_FC2_TX_DSR; ESP uses DSR
  1106.         jmp     SHORT ehh80
  1107.  
  1108. ehh75:  CLR     [si].ci_esp_flow2,ESP_FC2_TX_DSR; ESP does not use DSR
  1109.  
  1110.         ; Finally ready to tell ESP the proper flow control type
  1111. ehh80:
  1112.         mov     ah,[si].ci_esp_flow1
  1113.         mov     al,[si].ci_esp_flow2
  1114.  
  1115.         SetFCType       ah,al
  1116.  
  1117.         ; If XON/XOFF chosen, must tell ESP flow control characters to use
  1118.         test    [si].ci_dcb_flags2,F2_OUT_XO
  1119.         jnz     ehh83                           ; using XON/XOFF
  1120.         test    [si].ci_dcb_flags2,F2_IN_XO
  1121.         jnz     ehh83                           ; using XON/XOFF
  1122.         jmp     SHORT ehh85                     ; not using XON/XOFF
  1123.  
  1124.         ; Set ESP flow control characters. Last 3 ESP parameters are only used
  1125.         ; if xparent flow control is selected, but must send them anyway.
  1126. ehh83:  mov     ah,[si].ci_dcb_XonChar
  1127.         mov     al,[si].ci_dcb_XoffChar
  1128.         SetFCChar       ah,al,DLE,XMASK,PMASK
  1129.  
  1130. ehh85:  RestoreReg      <bx>                    ; (bl) = previous flags1
  1131.                                                 ; (bh) = previous flags2
  1132.         SaveReg         <bx>
  1133.         mov     bl,bh                           ; (bl) = (bh) = previous flags1
  1134.  
  1135.         ; process DSR sensitivity and DCD handshaking
  1136.         xor     cx,cx
  1137.         mov     al,[si].ci_dcb_flags1
  1138.         and     al,F1_OUT_DCD_FLOW
  1139.         and     bl,F1_OUT_DCD_FLOW
  1140.         cmp     bl,al
  1141.         jne     ehh100
  1142.  
  1143.         mov     ah,[si].ci_dcb_flags1
  1144.         and     ah,F1_IN_DSR_SENSE
  1145.         and     bh,F1_IN_DSR_SENSE
  1146.         cmp     bh,ah
  1147.         je      ehh130
  1148.  
  1149. ehh100: test    [si].ci_dcb_flags1,F1_OUT_DCD_FLOW
  1150.         jz      ehh105
  1151.  
  1152.         mov     cl,ESP_ERR1_MSR
  1153.         jmp     SHORT ehh110
  1154.  
  1155. ehh105:   xor     cl,cl
  1156.  
  1157. ehh110: SET     [si].ci_flagx,FX_IN_DSR_OK      ; assume no DSR sensitivity
  1158.         test    [si].ci_dcb_flags1,F1_IN_DSR_SENSE
  1159.         jz      ehh120
  1160.  
  1161.         SaveReg         <cx>
  1162.         GetUARTStatus                   ; (al) = LSR; (ah) = MSR
  1163.         RestoreReg      <cx>
  1164.         SET     [si].ci_flagx,FX_IN_DSR_OK
  1165.         test    ah,MS_DSR
  1166.         jnz     ehh115
  1167.  
  1168.         CLR     [si].ci_flagx,FX_IN_DSR_OK
  1169.  
  1170. ehh115: mov     ch,ESP_ERR1_MSR
  1171.         jmp     SHORT ehh125
  1172.  
  1173. ehh120: xor     ch,ch
  1174.  
  1175. ehh125: or      cl,ch
  1176.  
  1177. ehh130: or      cl,ESP_DEF_ERR1
  1178.         SetErrorMask    cl,ESP_DEF_ERR2
  1179.  
  1180.         RestoreReg     <bx>             ; (bl) = previous flags1
  1181.                                         ; (bh) = previous flags2
  1182.         ret
  1183.  
  1184. EndProc E_HHS
  1185.  
  1186. ;**     E_SetLineC - set line control values for an enhanced port
  1187. ;
  1188. ;       E_SetLineC sets the byte size, parity and number of stop bits
  1189. ;       according to the value in (al).
  1190. ;
  1191. ;       ENTRY   (ds:si) -> ComInfo
  1192. ;
  1193. ;       EXIT
  1194. ;
  1195. Procedure E_SetLineC,FAR
  1196.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1197.  
  1198.         SaveReg         <ax>
  1199.         WriteToUART     R_LINEC,al
  1200.         RestoreReg      <ax>
  1201.         ret
  1202.  
  1203. EndProc E_SetLineC
  1204.  
  1205. ;**     E_SetBaud - set the baud rate for an enhanced port
  1206. ;
  1207. ;       SetBaud verifies that the baud rate is within the valid
  1208. ;       baud range and can be supported within +-.01% (except 110
  1209. ;       baud @ +.026% error, and 2000 baud @ -.69% error)
  1210. ;       Converts the baud rate into the format necesary
  1211. ;       by the hardware and sets the rate.
  1212. ;       Also sends ESP commands to set trigger level and receive timeout value
  1213. ;
  1214. ;       ENTRY   (ds:si) -> ComInfo
  1215. ;               (ax) = baud rate
  1216. ;
  1217. ;       EXIT    if 'C' clear
  1218. ;                       ci_baud = baud rate
  1219. ;                       divisor latch set in hardware
  1220. ;               else
  1221. ;                       invalid baud rate
  1222. ;
  1223. ;       USES    ax bx cx dx flags
  1224. Procedure E_SetBaud,FAR
  1225.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1226.  
  1227.         ; Enhanced port: Tell ESP to set baud, trigger level and receive
  1228.         ; timeout.
  1229.         SaveReg         <bx>
  1230.         ChangeBaud      ch,cl  ; give ESP divisor, he sets baud
  1231.         RestoreReg      <bx>
  1232.         mov     ax,bx
  1233.         mov     [si].ci_baud,ax
  1234.  
  1235.         ; Also change trigger level when we change baud rates, so that
  1236.         ; RxFIFO trigger happens at least every 0.1 second. If baud rate
  1237.         ; is above 19200, more than 256 characters will come in during 0.1
  1238.         ; second, and ESP suggests a trigger <= 256.
  1239.         cmp     ax,19200
  1240.         jbe     esb55
  1241.         mov     ax,255
  1242.         jmp     SHORT esb70
  1243.  
  1244. esb55:   mov     cl,100                  ; 10 bits in a char
  1245.         ; (ax) = baud = dividend; (cl) = 100 = divisor
  1246.         div     cl
  1247.         ; now (al) = quotient = new trigger level
  1248.         xor     ah,ah           ; Because we know trigger level is < 256
  1249.  
  1250. esb70:   mov     [si].ci_rx_trigger,ax   ; save new trigger level
  1251.         SetTriggers     ah, al, HIGH(ESP_DEF_TRIGGER_TX), LOW(ESP_DEF_TRIGGER_TX)
  1252.  
  1253.         ; Change Receive Char Timeout to about 4 character times. However,
  1254.         ; ESP only allows timeout between 2 msec and 239 msec, so for
  1255.         ; baud < 300 use max timeout and for baud >= 19200 use min timeout.
  1256.  
  1257.         cmp     [si].ci_baud,300
  1258.         jae     esb74
  1259.         mov     al,239
  1260.         jmp     SHORT esb80
  1261.  
  1262. esb74:   cmp     [si].ci_baud,19200
  1263.         jb      esb78
  1264.         mov     al,4
  1265.         jmp     SHORT esb80
  1266.  
  1267. esb78:   mov     ax,40000                    ; dividend
  1268.         xor     dx,dx
  1269.         div     [si].ci_baud            ; quotient goes into ax
  1270.  
  1271. esb80:   SetRxTimeout    al
  1272.  
  1273.         CALLFAR ComputeWTO              ; re-compute write timeout value
  1274.         CALLFAR ComputeRTO              ; re-compute read  timeout value
  1275.  
  1276.         clc                             ; valid baud rate
  1277.         ret
  1278.  
  1279. EndProc E_SetBaud
  1280.  
  1281. ;** E_ShutDownPort - shut down an enhanced com port if it was open
  1282. ;
  1283. ;       if the port is open
  1284. ;         turn off ESP interrupts from this port
  1285. ;         UnsetIRQ
  1286. ;
  1287. ;       ENTRY   (ds:si) -> ComInfo of port to shut down
  1288. ;
  1289. ;       EXIT    NONE
  1290. ;
  1291. Procedure E_ShutDownPort,FAR
  1292.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1293.  
  1294.         ; Enhanced port: tell ESP to ignore interrupts from our port,
  1295.         mov     bx,[si].ci_pinfo
  1296.         mov     al,[bx].pi_svcmask
  1297.         cmp     [si].ci_cmd_offset,0
  1298.         jne     esd12
  1299.         CLR     al,ESP_SID_PORT1
  1300.         jmp     SHORT esd13
  1301.  
  1302. esd12:  CLR     al,ESP_SID_PORT2
  1303.  
  1304. esd13:  mov     [bx].pi_svcmask,al              ; save new svc mask
  1305.         SetSvcMask      al
  1306.  
  1307.         ; Can't release IRQ unless we determine that other ESP port
  1308.         ; is closed.
  1309.         mov     bx,[si].ci_pinfo
  1310.         mov     al,[si].ci_cmd_offset   ; are we ESP port1 or port2?
  1311.         or      al,al
  1312.         jnz     esd15
  1313.  
  1314.         ; we're ESP port1, examine port2 ComInfo
  1315.         cmp     [bx].pi_port2,0         ; does other port even exist?
  1316.         je      esstc                   ; no, release IRQ
  1317.         SaveReg         <si>            ; save original ComInfo ptr
  1318.         mov     si,[bx].pi_port2        ; (si) -> ComInfo for port2
  1319.         cmp     [si].ci_nopens,0        ; other ESP port still open?
  1320.         RestoreReg      <si>            ; restore original ComInfo ptr
  1321.         jne     esclc                   ; don't release IRQ
  1322.         jmp     esstc                   ; release IRQ
  1323.  
  1324.         ; we're ESP port2, examine port1 ComInfo
  1325. esd15:   cmp     [bx].pi_port1,0         ; does other port even exist?
  1326.         je      esstc                   ; no, release IRQ
  1327.         SaveReg         <si>            ; save original ComInfo ptr
  1328.         mov     si,[bx].pi_port1        ; (si) -> ComInfo for port2
  1329.         cmp     [si].ci_nopens,0        ; other ESP port still open?
  1330.         RestoreReg      <si>            ; restore original ComInfo ptr
  1331.         jne     esclc                   ; don't release IRQ
  1332.  
  1333. esstc:  stc                             ; tell caller to release IRQ
  1334.         ret
  1335.  
  1336. esclc:  clc                             ; tell caller NOT to release IRQ
  1337.         ret
  1338.  
  1339. EndProc E_ShutDownPort
  1340.  
  1341. ;** E_SetModemC - set Modem Control register for enhanced port
  1342. ;
  1343. ;       ENTRY   (ds:si) -> ComInfo
  1344. ;               bh = bits to turn off
  1345. ;               bl = bits to turn on
  1346. ;
  1347. ;       EXIT    NONE
  1348. Procedure E_SetModemC,FAR
  1349.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1350.  
  1351.         ; (bh) = bits to turn off, (bl) = bits to turn on
  1352.         mov     cl,4
  1353.         rol     bh,cl                   ; adjust MCR bit position to same as
  1354.                                         ; ESP flow control bit position
  1355.         or      [si].ci_esp_flow1,bl    ; turn ON desired bits.
  1356.         rol     bl,cl                   ; adjust MCR bit position to same as
  1357.                                         ; ESP flow control bit position.
  1358.         and     [si].ci_esp_flow1,bh    ; turn OFF desired bits.
  1359.         mov     ah,[si].ci_esp_flow1
  1360.         mov     al,[si].ci_esp_flow2
  1361.  
  1362.         SetFCType       ah,al   ; Use SetFCType ESP commmand to set MCR
  1363.  
  1364.         ret
  1365.  
  1366. EndProc E_SetModemC
  1367.  
  1368. ;** E_TxBytes - get bytes available in ESP's transmit FIFO
  1369. ;
  1370. ;       ENTRY   (ds:si) -> ComInfo
  1371. ;
  1372. ;       EXIT    (ax) = bytes available in ESP transmit FIFO
  1373. Procedure E_TxBytes,FAR
  1374.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1375.  
  1376.         GetTxBytes
  1377.         xchg    ah,al                   ; (ax) = bytes avail in ESP's TxFIFO
  1378.         ret
  1379.  
  1380. EndProc E_TxBytes
  1381.  
  1382. ;** E_GetMCR - get Modem Control register for enhanced port
  1383. ;
  1384. ;       ENTRY   (ds:si) -> ComInfo
  1385. ;
  1386. ;       EXIT    (al) = MCR
  1387. Procedure E_GetMCR,FAR
  1388.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1389.  
  1390.         ReadFromUART    R_MODMC
  1391.         ret                                     ; (al) = MCR
  1392.  
  1393. EndProc E_GetMCR
  1394.  
  1395. ;** E_GetMSR - get Modem Status register for enhanced port
  1396. ;
  1397. ;       ENTRY   (ds:si) -> ComInfo
  1398. ;
  1399. ;       EXIT    (al) = MSR
  1400. Procedure E_GetMSR,FAR
  1401.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1402.  
  1403.         GetUARTStatus           ; (al) = LSR, (ah) = MSR
  1404.         xchg    ah,al                   ; (al) = MSR
  1405.         ret
  1406.  
  1407. EndProc E_GetMSR
  1408.  
  1409. ;** E_GetLSR - get Line Status register for enhanced port
  1410. ;
  1411. ;       ENTRY   (ds:si) -> ComInfo
  1412. ;
  1413. ;       EXIT    (al) = LSR
  1414. Procedure E_GetLSR,FAR
  1415.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1416.  
  1417.         GetUARTStatus           ; (al) = LSR, (ah) = MSR
  1418.         ret
  1419.  
  1420. EndProc E_GetLSR
  1421.  
  1422. ;** E_GetLSR - transmit byte immediately from enhanced port
  1423. ;
  1424. ;       ENTRY   (ds:si) -> ComInfo
  1425. ;               (al) = data byte
  1426. Procedure E_TxImm,FAR
  1427.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1428.  
  1429.         ; (al) = data byte to transmit immediately
  1430.         WriteToUART     R_DATA,al
  1431.         ret
  1432.  
  1433. EndProc E_TxImm
  1434.  
  1435. ;** E_Xoff - behave as if XOFF received for enhanced port
  1436. ;
  1437. ;       ENTRY   (ds:si) -> ComInfo
  1438. Procedure E_Xoff,FAR
  1439.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1440.  
  1441.         ; Tell ESP to stop transmitting
  1442.         SaveReg         <es,di>
  1443.         LocalXoff
  1444.         RestoreReg      <di,es>
  1445.         SET     [si].ci_HSFlag,HS_FLOW_OFF_LOCAL
  1446.         test    [si].ci_dcb_flags2,F2_OUT_XO OR F2_IN_XO
  1447.         jz      eoffx
  1448.         SET     [si].ci_HSFlag,HS_XOFF_RECEIVED
  1449.  
  1450. eoffx:  ret
  1451.  
  1452. EndProc E_Xoff
  1453.  
  1454. ;** E_Xon - behave as if XON received for enhanced port
  1455. ;
  1456. ;       ENTRY   (ds:si) -> ComInfo
  1457. Procedure E_Xon,FAR
  1458.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1459.  
  1460.         ; Tell ESP to start transmitting
  1461.         SaveReg         <es,di>
  1462.         LocalXon
  1463.         RestoreReg      <di,es>
  1464.         CLR     [si].ci_HSFlag,HS_FLOW_OFF_LOCAL
  1465.         test    [si].ci_dcb_flags2,F2_OUT_XO OR F2_IN_XO
  1466.         jz      eonx
  1467.         CLR     [si].ci_HSFlag,HS_XOFF_RECEIVED
  1468. eonx:   ret
  1469.  
  1470. EndProc E_Xon
  1471.  
  1472. ;** E_BreakOn - start transmitting break for enhanced port
  1473. ;
  1474. ;       ENTRY   (ds:si) -> ComInfo
  1475. Procedure E_BreakOn,FAR
  1476.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1477.  
  1478.         SendBreak       0       ; hold line until Break Off cmd
  1479.         ret
  1480.  
  1481. EndProc E_BreakOn
  1482.  
  1483. ;** E_BreakOff - stop transmitting break for enhanced port
  1484. ;
  1485. ;       ENTRY   (ds:si) -> ComInfo
  1486. Procedure E_BreakOff,FAR
  1487.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1488.  
  1489.         SendBreak       1       ; 10ms break, then ESP will stop
  1490.         ret
  1491.  
  1492. EndProc E_BreakOff
  1493.  
  1494. ;** E_EnableRxFIFO - enable RxFIFO interrupts for enhanced port
  1495. ;
  1496. ;       ENTRY   (ds:si) -> ComInfo
  1497. Procedure E_EnableRxFIFO,FAR
  1498.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1499.  
  1500.         mov     di,[si].ci_pinfo
  1501.         cmp     [si].ci_cmd_offset,0
  1502.         jne     rdq60
  1503.         SET     [di].pi_svcmask,ESP_SID_RX1
  1504.         jmp     SHORT rdq70
  1505.  
  1506. rdq60:  SET     [di].pi_svcmask,ESP_SID_RX2
  1507. rdq70:
  1508.         mov     [si].ci_rx_state,RX_STATE_OK
  1509.         mov     dx,[di].pi_address
  1510.         ; Disable ALL ints while re-enabling ESP interrupts
  1511.         CLI
  1512. rdq72:  in      al,dx
  1513.         test    al,ESP_RDY_CMD1
  1514.         jz      rdq72
  1515.         add     dx,ESP_R_CMD1-ESP_R_RDY
  1516.         mov     al,ESP_CMD_SETSVCMASK
  1517.         add     al,[si].ci_cmd_offset
  1518.         out     dx,al
  1519.         add     dx,ESP_R_RDY-ESP_R_CMD1
  1520. rdq73:  in      al,dx
  1521.         test    al,ESP_RDY_CMD2
  1522.         jz      rdq73
  1523.         add     dx,ESP_R_CMD2-ESP_R_RDY
  1524.         mov     al,[di].pi_svcmask
  1525.         out     dx,al
  1526.  
  1527.         ; Issue GetDips to be *SURE* that ESP has processed SetSvcMask before
  1528.         ; we re-enable interrupts
  1529.         mov     dx,[di].pi_address
  1530. rdq74:  in      al,dx
  1531.         test    al,ESP_RDY_CMD1
  1532.         jz      rdq74
  1533.         add     dx,ESP_R_CMD1-ESP_R_RDY
  1534.         mov     al,ESP_CMD_GDIPS
  1535.         out     dx,al
  1536.         add     dx,ESP_R_RDY-ESP_R_CMD1
  1537. rdq76:  in      al,dx
  1538.         test    al,ESP_RDY_STATUS1
  1539.         jz      rdq76
  1540.         add     dx,ESP_R_STATUS1-ESP_R_RDY
  1541.         in      al,dx
  1542.         ; Re-enable ALL interrupts.
  1543.         STI
  1544.  
  1545.         ret
  1546.  
  1547. EndProc E_EnableRxFIFO
  1548.  
  1549. ;** TriggerTX - turn on/off TxFIFO interrupt for enhanced port
  1550. ;
  1551. ;       ENTRY   (ds:si) -> ComInfo
  1552. ;
  1553. ; ESP interrupt handler needs NEAR call, but WriteTick (in CSEG) needs FAR call
  1554. Procedure TriggerTX,HYBRID
  1555.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1556.  
  1557.         mov     di,[si].ci_pinfo
  1558.         mov     al,[di].pi_svcmask
  1559.  
  1560.         ; Must keep transmit int enabled if waiting on tx empty -- if not,
  1561.         ; how will we know when tx goes empty?
  1562.         test    [si].ci_flagx,FX_WAITING_TX_EMPTY
  1563.         jnz     ictx5
  1564.  
  1565.         cmp     [si].ci_w_rp._hi,0              ; no request packet
  1566.         je      ictx20
  1567.  
  1568.         ; enable transmit interrupts
  1569. ictx5:  cmp     [si].ci_cmd_offset,0
  1570.         jne     ictx10
  1571.         ; enable TxFIFO for port1
  1572.         SET     al,ESP_SVC_MASK_TX1
  1573.         jmp     SHORT ictx15
  1574.  
  1575.         ; enable TxFIFO for port2
  1576. ictx10: SET     al,ESP_SVC_MASK_TX2
  1577. ictx15: clc                                     ; 'C' clear - TX enabled
  1578.         jmp     SHORT ictx40
  1579.  
  1580. ictx20: ; disable transmit interrupts
  1581.         cmp     [si].ci_cmd_offset,0
  1582.         jne     ictx30
  1583.         ; disable TxFIFO for port1
  1584.         CLR     al,ESP_SVC_MASK_TX1
  1585.         ; if TxFIFO int was pending in SID, issuing new service mask will
  1586.         ; clear it, so update sid
  1587. ;        CLR     [di].pi_sid,ESP_SID_TX1
  1588.         jmp     SHORT ictx35
  1589.  
  1590.         ; disable TxFIFO for port2
  1591. ictx30: CLR     al,ESP_SVC_MASK_TX2
  1592.         ; if TxFIFO int was pending in SID, issuing new service mask will
  1593.         ; clear it, so update sid
  1594. ;        CLR     [di].pi_sid,ESP_SID_TX2
  1595. ictx35: stc                                     ; 'C' set - TX disabled
  1596.  
  1597.         ; Don't issue ESP SetSvcMask command unless "new" one in AL
  1598.         ; differs from "current" one in [di].pi_svcmask
  1599. ictx40: cmp     al,[di].pi_svcmask
  1600.         je      ttx                             ; don't issue command
  1601.         mov     [di].pi_svcmask,al              ; save new svcmask
  1602.         pushf                                   ; save carry flag
  1603.         mov     dx,[si].ci_esp_address          ; (dx) -> ready reg
  1604. ictx50: in      al,dx
  1605.         test    al,ESP_RDY_CMD1
  1606.         jz      ictx50
  1607.         add     dx,ESP_R_CMD1-ESP_R_RDY         ; (dx) -> cmd1 reg
  1608.         mov     al,ESP_CMD_SETSVCMASK
  1609.         add     al,[si].ci_cmd_offset
  1610.         out     dx,al
  1611.         add     dx,ESP_R_RDY-ESP_R_CMD1        ; (dx) -> ready reg
  1612. ictx60: in      al,dx
  1613.         test    al,ESP_RDY_CMD2
  1614.         jz      ictx60
  1615.         add     dx,ESP_R_CMD2-ESP_R_RDY         ; (dx) -> cmd2 reg
  1616.         mov     al,[di].pi_svcmask              ; (al) = new svc mask
  1617.         out     dx,al
  1618.  
  1619.         popf                                    ; restore carry flag for caller
  1620. ttx:    ret
  1621. EndProc TriggerTX
  1622.  
  1623. ; **    IssueESPCmd
  1624. ;
  1625. ;       ENTRY   (ds:si) -> ComInfo
  1626. ;               [si].ci_parm_area.cmd_code = command
  1627. ;               [si].ci_parm_area.num_writes = how many parameters to
  1628. ;                                               write to ESP
  1629. ;               [si].ci_parm_area.writes = array of parameters to write
  1630. ;               [si].ci_parm_area.num_reads = how many status bytes to
  1631. ;                                               read from ESP
  1632. ;
  1633. ;       EXIT    [si].ci_parm_area.reads = array of status bytes read from ESP
  1634. ;
  1635. ;       USES    ax,bx,cx,dx,si,di
  1636. ;
  1637. ; WARNING - IssueESPCmd declared NEAR, so don't call except from E_CSEG!
  1638. Procedure IssueESPCmd,NEAR
  1639.         ASSUME cs:E_CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1640.  
  1641.         CLI
  1642.  
  1643.         mov     dx,[si].ci_esp_address          ; (dx) -> ready reg
  1644. foo1:   in      al,dx                            ; wait for cmd1 ready
  1645.         test    al,ESP_RDY_CMD1
  1646.         jz      foo1
  1647.  
  1648.         mov     al,[si].ci_parm_area.cmd_code
  1649.         add     dx,ESP_R_CMD1-ESP_R_RDY         ; (dx) -> cmd1 reg
  1650.         out     dx,al                           ; out cmd1
  1651.  
  1652.         mov     cl,[si].ci_parm_area.num_writes
  1653.         or      cl,cl                           ; jump around if no data
  1654.         jz      foo3                            ; bytes to send out
  1655.  
  1656.         xor     ch,ch                           ; set up for loop
  1657.         xor     bx,bx
  1658.  
  1659.         add     dx,ESP_R_RDY-ESP_R_CMD1         ; (dx) -> ready reg
  1660. foo2:   in      al,dx
  1661.         test    al,ESP_RDY_CMD2                ; wait for cmd2 ready
  1662.         jz      foo2
  1663.         add     dx,ESP_R_CMD2-ESP_R_RDY         ; (dx) -> cmd2 reg
  1664.         mov     al,[si].ci_parm_area.writes+[bx]
  1665.         out     dx,al                           ; out next data byte
  1666.         inc     bx
  1667.         add     dx,ESP_R_RDY-ESP_R_CMD2         ; (dx) -> ready reg
  1668.         loop    foo2
  1669.  
  1670. foo3:   mov     cl,[si].ci_parm_area.num_reads
  1671.         or      cl,cl                           ; jump around if not data
  1672.         jz      foo6                            ; bytes to get
  1673.  
  1674.         mov     dx,[si].ci_esp_address
  1675.         add     dx,ESP_R_RDY                    ; (dx) -> ready reg
  1676. foo4:   in      al,dx
  1677.         test    al,ESP_RDY_STATUS1              ; wait for status1 ready
  1678.         jz      foo4
  1679.         add     dx,ESP_R_STATUS1-ESP_R_RDY      ; (dx) -> status1 reg
  1680.         in      al,dx
  1681.         mov     [si].ci_parm_area.reads,al      ; store data byte
  1682.  
  1683.         cmp     cl,2                            ; get another?
  1684.         jne     foo6
  1685.         add     dx,ESP_R_RDY-ESP_R_STATUS1      ; (dx) -> ready reg
  1686. foo5:   in      al,dx
  1687.         test    al,ESP_RDY_STATUS2              ; wait for status2 ready
  1688.         jz      foo5
  1689.         add     dx,ESP_R_STATUS2-ESP_R_RDY      ; (dx) -> status2 reg
  1690.         in      al,dx
  1691.         mov     [si].ci_parm_area.reads+1,al          ; store data byte
  1692.  
  1693. foo6:
  1694.         STI
  1695.         ret
  1696.  
  1697. EndProc IssueESPCmd
  1698.  
  1699. E_CSEG  ENDS
  1700.  
  1701. END
  1702.