home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / ATCOM / ATCOM.ASM next >
Assembly Source File  |  1995-04-14  |  97KB  |  2,670 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 = @(#)atcom.asm  6.14 92/03/18
  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. ;***    atcom.asm
  29. ;
  30. ;       This file contains the strategy routine for the com01.sys
  31. ;       device driver. This is the asynch device driver for the AT.
  32. ;       The device driver handles up to four com ports.
  33.  
  34. ;       The asynch device driver is an installable driver. It is
  35. ;       installed via the 'device=' command in config.sys. It has no
  36. ;       command line arguments, therefore installation amounts to
  37. ;       the command:
  38. ;
  39. ;               device=com01.sys
  40. ;
  41. ;       being present in config.sys.
  42.  
  43. ;       Com01.sys must use low memory for its I/O buffers. Therefore
  44. ;       it is advisable not to install the driver unless it is needed.
  45.  
  46. ;       Modification History
  47. ;
  48. ;       DJG     01/06/87  Re-written to conform to MS standard for
  49. ;                         style, clarity and efficiency.
  50. ;       JGT     05/10/88  Add enhanced baud rate support (p587-cpd12)
  51. ;       JGT     07/25/88  Disable to read MsCount in ComClose - p1355
  52. ;       YN      05/25/89  MVDM Support   @VDM
  53. ;       ACW     04/16/91  @PVW Added perfview counters/timers
  54. ;       YN      08/13/91  CP20D1390 - Bulletin Board Support
  55. ;       YN      10/30/91  CP20PB729004 - Shutdown Support (Reset FIFO)
  56. ;       MF      02/21/92  PB732220 - Procomm Plus host mode fix (@0001)
  57. ;       JAG     07/29/93  72032 Fix detection of FIFO buffer for PCMCIA
  58. ;       JAG     09/14/93  73679 change IDC_handler to behave correctly
  59. ;                                (Cy set on error; more parm checking)
  60. ;       RAC     12/7/93   Add define statements to conditionally
  61. ;                         assemble PERFVIEW and TRACE code
  62. ;       RDW     03/17/94  77701 same as defect 76009 (add getlid to ABIOS)
  63. ;       RDW     03/30/94  81245  SMC SIO chip cause hang enabling FIFO UART
  64. ;       JAG     07/11/94  85558  Update 40:X for PCMCIA card inst/deinst.
  65. ;       JAG     08/26/94  95202  Check ABIOS rc for NOT_VALID; ThinkPad 720
  66. ;       JAG     09/26/94  99428  Resource manager fixes
  67. ;       JAG     09/29/94  100764 High speed pcmcia modems busted.
  68. ;       PMS     11/16/94  103070 -1 ComClose does not CLI before ProcBlockNI
  69. ;                         Found ComWFlushSub / ComRFlushSub were trashing
  70. ;                         ES:DI registers (ReqPacket).
  71. ;       PMS     11/16/94  103070 -2 PERFVIEW addition removed JMPs from
  72. ;                         ComRead and ComWrite code
  73.  
  74.  
  75. COM_ATTRIB      EQU     DEV_CHAR_DEV OR DEV_30 OR DEVLEV_3 OR DEV_GIOCTL OR DEV_SHARE OR DEV_IDC
  76.  
  77.  
  78. .xlist
  79. include devhlp.inc
  80. include devsym.inc
  81. include realmac.inc
  82. include basemaca.inc
  83. include error.inc
  84. include filemode.inc
  85. include infoseg.inc
  86. include aberror.inc
  87. .list
  88. include atcom.inc
  89. include gas.inc
  90. include ateisa.inc
  91.         EXTRN   Com1:WORD
  92.         EXTRN   Com2:WORD
  93.         EXTRN   Com3:WORD
  94.         EXTRN   Com4:WORD
  95.         EXTRN   Com1P:WORD
  96.         EXTRN   Com2P:WORD
  97.         EXTRN   Com3P:WORD
  98.         EXTRN   Com4P:WORD
  99.         EXTRN   Kernel_Type:WORD
  100.         EXTRN   ComInit:FAR
  101.         EXTRN   ComIoctl:NEAR
  102.         EXTRN   DevHlp:DWORD
  103.         EXTRN   Ticker:NEAR
  104.         extrn   CheckLCR:near
  105.  
  106.         extrn   CheckTX:near
  107.         extrn   Get_OCI_Sem:near
  108.         extrn   LinkRP:near
  109.         extrn   ProcBlock:near
  110.         extrn   ProcBlockNI:near
  111.         extrn   ProcRun:near
  112.         extrn   ReadQueue:near
  113.         extrn   StartNextRRP:near
  114.         extrn   StartNextWRP:near
  115.         extrn   UnLinkHeadRP:near
  116.         extrn   UnLinkRP:near
  117.         extrn   WriteQueue:near
  118.         extrn   EnqComInfo:near
  119.         extrn   DeqComInfo:near
  120.  
  121.         extrn   SetUpGDT:near
  122.  
  123.         extrn   endswapcode:byte
  124.         extrn   ENDSWAPDATA:word
  125.         extrn   MxInt:near
  126.         extrn   EnableRemoteTX:near
  127.         extrn   ComputeAPO:near
  128.         extrn   ComputeHHS:near
  129.         extrn   ComputeRTO:near
  130.         extrn   ComputeWTO:near
  131.         extrn   SetLineC:near
  132.         extrn   SetBaud:near
  133.         extrn   CheckLCR:near
  134.         EXTRN   ComInit:FAR
  135.         EXTRN   ComInt1:FAR
  136.         EXTRN   ComInt2:FAR
  137.         EXTRN   ComInt3:FAR
  138.         EXTRN   ComInt4:FAR
  139.         EXTRN   SComInt1:FAR
  140.         EXTRN   SComInt2:FAR
  141.         EXTRN   SComInt3:FAR
  142.         EXTRN   SComInt4:FAR
  143.         EXTRN   ShrdIRQ1:BYTE
  144.         EXTRN   _RMHELP_CreateLDev:FAR
  145.         EXTRN   _RMHELP_DestroyLDev:FAR
  146.         EXTRN   _RMHELP_FindPCMCIANode:FAR
  147.  
  148.  
  149.  
  150. HSEG SEGMENT
  151.  
  152. ;       Com1Dev and Com2Dev are the headers for the asynch
  153. ;       device drivers.
  154.  
  155. ;       WARNING : If Com1Dev is the first header in the device
  156. ;       driver chain, the DOS expects to find it at the beginning
  157. ;       of the device driver's data segment.
  158.  
  159. SDev macro baselabel, devnext, devattr, devstrat, devintr, devname, devpCS, devpDS, devrCS, devrDS, devcap
  160.     ?SDev       macro   field, size, value
  161.         .errnz ($ - baselabel - offset field)
  162.         size value
  163.     endm
  164.     baselabel label byte
  165.     ?SDev  SDevNext     dd      <devnext>
  166.     ?SDev  SDevAtt      dw      <devattr>
  167.     ?SDev  SDevStrat    dw      <devstrat>
  168.     ?SDev  SDevInt      dw      <devintr>
  169.     ?SDev  SDevName     db      <devname>
  170.     ?SDev  SDevProtCS   dw      <devpCS>
  171.     ?SDev  SDevProtDS   dw      <devpDS>
  172.     ?SDev  SDevRealCS   dw      <devrCS>
  173.     ?SDev  SDevRealDS   dw      <devrDS>
  174.     ?SDev  SDevCaps     dd      <devcap OR 0000000000000001b>
  175.     .errnz ($ - baselabel - size SysDev3)
  176. endm
  177.  
  178. ;IFDEF    COMDEBUG
  179. ;SDev Com1Dev -1, COM_ATTRIB, Com1Strat, 0, 'COM1    '
  180. ;ELSE
  181. SDev Com1Dev <offset Com2Dev>,COM_ATTRIB,Com1Strat,COM1_IDC_Entry,'COM1    ',0,0,0,0,DEV_16MB
  182. SDev Com2Dev <offset Com3Dev>,COM_ATTRIB,Com2Strat,COM2_IDC_Entry,'COM2    ',0,0,0,0,DEV_16MB
  183. SDev Com3Dev <offset Com4Dev>,COM_ATTRIB,Com3Strat,COM3_IDC_Entry,'COM3    ',0,0,0,0,DEV_16MB
  184. SDev Com4Dev -1,              COM_ATTRIB,Com4Strat,COM4_IDC_Entry,'COM4    ',0,0,0,0,DEV_16MB
  185. ;ENDIF
  186.  
  187. .ERRNZ  OFFSET HSEG:Com1Dev             ; enforce the above warning
  188.  
  189. HSEG    ENDS
  190.  
  191. DSEG SEGMENT
  192.  
  193. public startswapdata
  194. startswapdata   label byte
  195.  
  196. ;       There are 13 (out of a possible 21) commands that can be
  197. ;       made of a character device driver. Communication with a
  198. ;       device driver is performed through packets. Within this
  199. ;       packet is the command code. We use this value to drive the
  200. ;       strategy routine of com01.sys. This is accomplished via the
  201. ;       following jump table.
  202.  
  203.         EVEN                            ; force word alignment
  204. ComStratTab     LABEL   WORD
  205.         DW      0                       ;0: Init (not used in this table)
  206.         DW      OFFSET CSEG:CmxUnknown  ;1: Media Check (Block Devices Only)
  207.         DW      OFFSET CSEG:CmxUnknown  ;2: Build BPB (Block Devices Only)
  208.         DW      OFFSET CSEG:CmxUnknown  ;3: Reserved (used to be Ioctl Input)
  209.         DW      OFFSET CSEG:ComRead     ;4: Input (Read)
  210.         DW      OFFSET CSEG:ComNDRead   ;5: Non-Destructive Input, no wait.
  211.         DW      OFFSET CSEG:ComRStat    ;6: Input Status
  212.         DW      OFFSET CSEG:ComRFlush   ;7: Input Flush
  213.         DW      OFFSET CSEG:ComWrite    ;8: Output (Write)
  214.         DW      OFFSET CSEG:ComWrite    ;9: Output (Write) with verify
  215.         DW      OFFSET CSEG:ComWStat    ;10: Output Status
  216.         DW      OFFSET CSEG:ComWFlush   ;11: Output Flush
  217.         DW      OFFSET CSEG:CmxUnknown  ;12: Reserved (used to be Ioctl Output)
  218.         DW      OFFSET CSEG:ComOpen     ;13: Device Open
  219.         DW      OFFSET CSEG:ComClose    ;14: Device Close
  220.         DW      OFFSET CSEG:CmxUnknown  ;15: Removable Media
  221.         DW      OFFSET CSEG:ComIoctl    ;16: Generic Ioctl
  222.         DW      OFFSET CSEG:CmxUnknown  ;17: Reset Media
  223.         DW      OFFSET CSEG:CmxUnknown  ;18: Get Logical Drive Map
  224.         DW      OFFSET CSEG:CmxUnknown  ;19: Set Logical Drive Map
  225.         DW      OFFSET CSEG:CmxUnknown  ;20: DeInstall
  226. MAXCMD = (($ - ComStratTab)/2) - 1
  227.  
  228. TimerHook       DB      0       ; timer hook count
  229. ; actually a count of the number of ports that are open.
  230. ; incremented on a first open, decremented on a last close for any port.
  231.  
  232.         PUBLIC  VCOMAddress                             ; @VDM
  233. VCOMAddress     df      0                               ; @VDM
  234. ; VCOM interrupt handler entry point                      @VDM
  235.  
  236.         PUBLIC  ClkIntrvl
  237. ClkIntrvl       DW      0       ; System clock interval in 10000s of a second
  238.  
  239. SysInfoSeg      DW      0       ; for getting running MsCount for close timeout
  240.  
  241.         PUBLIC  Flags
  242. Flags   DB      0               ; flags for driver shut down
  243.  
  244. PUBLIC  ComLHead, ComGAS
  245.  
  246. ComLHead  LOGHEAD  <,GasSize-$-2,SNAGENALERT,,,,,,,>        ; SNA ALERT log entry header
  247.           PSIDS    <>                                       ; product set ID SV
  248. ComGAS    GAS      <,,,GAS_PERM_LOSS,GAS_ADC_DEVCOMERROR,0> ; alert Sub Vector
  249. ComPCS    GAS_PCS  <,,GAS_PCD_COMSTARTSTOP>                 ; prob cause SV
  250. ComFCS    GAS_FCS  <,,,,GAS_FCC_DEVOUT,,,GAS_RAC_READY_DEVICE> ; fail cause SV
  251. GasSize LABEL WORD
  252.  
  253. codelockhandle  db      lhlen   dup(0)
  254. datalockhandle  db      lhlen   dup(0)
  255.  
  256. public IntRoutines
  257. IntRoutines     DW      OFFSET RSEG:ComInt1     ; Int. routine for COM1
  258.                 DW      OFFSET RSEG:ComInt2     ; Int. routine for COM2
  259.                 DW      OFFSET RSEG:ComInt3     ; Int. routine for COM3
  260.                 DW      OFFSET RSEG:ComInt4     ; Int. routine for COM4
  261.  
  262.  
  263. DSEG    ENDS
  264.  
  265.  
  266. CSEG    SEGMENT
  267.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  268.  
  269. public startswapcode
  270. startswapcode   label   byte
  271.  
  272. ;**     ComStrat - strategy entry point for COM
  273. ;
  274. ;       Com1Strat and Com2Strat are the entry points for the strategy
  275. ;       routine for the asynch device driver. The strategy routine is
  276. ;       called by the DOS in order to handle device requests.  This is
  277. ;       the combined portion of the strategy code.  This portion is
  278. ;       swappable until the first open completes.
  279. ;
  280. ;       ENTRY   (es:bx) -> request packet
  281. ;               (ds) DSEG segment for com01.sys
  282. ;
  283. ;       EXIT    result of operation set in request
  284. ;               packet status field (PktStatus)
  285. ;
  286. ;       USES    di
  287. Procedure ComStrat,FAR
  288.  
  289.         mov     di,bx                   ; (es:di) -> request packet
  290.  
  291. IFDEF RPSTRICT
  292.         or      es:[di].PktStatus,SIGNATURE
  293. ENDIF
  294.  
  295.         SaveReg         <es,di>         ; save pointer to request packet
  296.         SaveReg         <ds,si>         ; save pointer to ComInfo structure
  297.         mov     bp,sp                   ; allocate NULL stack frame
  298.  
  299. ;        cmp     es:[di].PktCmd,01BH
  300.         cmp     es:[di].PktCmd,CMDInit
  301.         jne     cst10                   ; init command, call directly
  302.  
  303.         call    ComInit                 ; do init
  304.         jmp     bx                      ; do end processing
  305.  
  306. cst10:
  307.         cmp     es:[di].PktCmd,CMDShutdown
  308.         jne     cst20                   ; init command, call directly
  309.  
  310.         call    ComShutdown
  311.         jmp     CmxDone
  312.  
  313. cst20:
  314.         or      si,si
  315.         jz      CmxNotReady             ; device not installed
  316.  
  317.         xor     bx,bx
  318.         mov     bl,es:[di].PktCmd
  319.  
  320.         cmp     bl,MAXCMD
  321.         ja      CmxUnknown              ; command is invalid
  322.  
  323. IFDEF   COMDEBUG
  324. ;       int     3
  325. ENDIF
  326.  
  327.         shl     bx,1                    ; (bx) = word index to ComStratTab
  328.  
  329. ; On entry to each of the command handlers:
  330. ;
  331. ;       (ds:si)         -> device info structure for COM1 or COM2.
  332. ;       (es:di)         -> request packet
  333. ;       ax              = device minor number
  334.  
  335.         jmp     ComStratTab[bx]         ; go execute command
  336.  
  337. ; Following are the six exit points for the driver. Request
  338. ; handlers all jump to one of these labels to have their exit
  339. ; condition set. The stack is permitted to be in an inconsistent
  340. ; state here because we are going to deallocate the stack frame.
  341.  
  342. Entry CmxDone,,,nocheck                 ; no error
  343.  
  344.         mov     ax,STDON
  345.         jmp     SHORT cmx
  346.  
  347. Entry CmxUnknown,,,nocheck              ; error - unknown command
  348.  
  349.         mov     ax,STDON OR STERR OR ERROR_I24_BAD_COMMAND
  350.         jmp     SHORT cmx
  351.  
  352. Entry CmxNotReady,,,nocheck             ; error - device not ready
  353.  
  354.         mov     ax,STDON OR STERR OR ERROR_I24_NOT_READY
  355.         jmp     SHORT cmx
  356.  
  357. Entry CmxBusy,,,nocheck                 ; no error, device busy
  358.  
  359.         mov     ax,STDON OR STBUI
  360.         jmp     SHORT cmx
  361.  
  362. Entry CmxMonitor,,,nocheck              ; error - monitors not supported
  363.  
  364.         mov     ax,STDON OR STERR OR ERROR_I24_NO_MONITOR_SUPPORT
  365.         jmp     SHORT cmx
  366.  
  367. Entry CmxInterrupted,,,nocheck          ; error - interrupted ProcBlock
  368.  
  369.         mov     ax,STDON OR STERR OR ERROR_I24_CHAR_CALL_INTERRUPTED
  370.         jmp     SHORT cmx
  371.  
  372. Entry CmxInvalidParameter,,,nocheck     ; error - invalid parameter
  373.  
  374.         mov     ax,STDON OR STERR OR ERROR_I24_INVALID_PARAMETER
  375.         jmp     SHORT cmx
  376.  
  377. Entry CmxBadLock,,,nocheck              ; error, Lock failed
  378. Entry CmxGenFail,,,nocheck              ; error, general failure
  379.  
  380.         mov     ax,STDON OR STERR OR ERROR_I24_GEN_FAILURE
  381.         jmp     SHORT cmx
  382.  
  383. Entry CmxInUse,,,nocheck                ; error, device in use
  384.         mov     ax,STDON OR STERR OR ERROR_I24_DEVICE_IN_USE
  385.  
  386. ; Common exit point.
  387.  
  388. cmx:    sti                             ; just in case someone left them off
  389.         mov     sp,bp                   ; deallocate NULL stack frame
  390.         RestoreReg      <si,ds>         ; (ds:si) -> ComInfo structure
  391.         RestoreReg      <di,es>         ; (es:di) -> request packet
  392.         ASSUME  ds:DSEG,es:NOTHING
  393.         ;BUGBUG internal error if es:di not a req packet
  394.         ;can't call ChkRPPtr because already poped stack frame.
  395.  
  396.         mov     es:[di].PktStatus,ax    ; update status field
  397.  
  398.         or      si,si
  399.         jz      cmret                   ; port is not installed or ShtuDown
  400.  
  401.         test    Flags,F_SHUT_DOWN
  402.         jnz     cmret                   ; driver is shut down
  403.  
  404. ;**  Logging Facility support:
  405. ;
  406. ;   if ci_flagGA != 0                   ; is there an alert condition active?
  407. ;     if  SIS_SysLog != 0               ; yes, is the system logging active?
  408. ;       ax = 8                          ; yes, so set cx = max flag bit value
  409. ;       GASLoop: if ci_flagGA[cx] != 0  ; is the bit on?
  410. ;               es:bx --> ci_GAS        ; yes, set up pointer to alert struc
  411. ;               CALL DevHlp_LogEntry    ;   send the alert struc to sys log
  412. ;       end_GASLoop;                    ; no....
  413. ;             if ci_flagGA == 0         ; any other bits on?
  414. ;                or ax == 0
  415. ;               jump to postGAS         ; no, so quit
  416. ;             ax = ax - 1               ; test next bit in ci_flagGA
  417. ;             ci_flagGA = ci_flagGA/2   ; shift right, lose low order bit
  418. ;             jump to GASLoop           ; and iterate
  419. ;     postGAS:  ci_flagGA = 0
  420. ;
  421.         mov     cx,[si].ci_flagGA       ; do we have an alert condition?
  422.         or      cx,cx
  423.         jz      cmx_oci                 ; no, so skip to check OCI Sem
  424.  
  425.         mov     ax,SysInfoSeg           ; get SysInfoSeg pointer
  426.         push    ds
  427.         mov     ds,ax
  428.         mov     ax,ds:SIS_SysLog        ; get SysLog word from SysInfoSeg
  429.         test    ax,LF_LOGENABLE         ; is system logging enabled?
  430.         pop     ds
  431.         jz      postGAS                 ; no, reset GAS flag & continue on
  432.  
  433. ; from here, check and service each bit in ci_flagGA that is set
  434.  
  435.         mov     ax,GAS_FLAG_MAX         ; start with highest valid GAS bit
  436.  
  437. GASloop:
  438.         test    cx,ax                   ; is this bit on?
  439.         jz      end_GASLoop             ; no, so check next bit
  440.  
  441. ; now we know we have a specific alert condition (index = ax)
  442.  
  443.         SaveReg <es,cx>                 ; preserve RP address
  444.         mov     cx,LOGERROR             ; function is LOGERROR
  445.         mov     WORD PTR DS:ComGAS.GAS_ALERTID,ax  ; IBMHACK use this for now
  446.         mov     WORD PTR DS:ComGAS.GAS_ALERTID+2,0 ; IBMHACK
  447.         push    ds                      ; es needs to point to COM data seg
  448.         pop     es
  449.         lea     bx,ComLHead             ; (es:bx) --> ComLHead struc
  450.  
  451.         mov     dl,DevHlp_LogEntry      ; log this generic alert
  452.         DevHelp                         ; via the DevHlp
  453.  
  454.         RestoreReg <cx,es>              ; restore RP pointer
  455.  
  456. end_GASLoop:
  457.  
  458.         shr     ax,1                    ; bump test bit over one
  459.         jnz     GASloop                 ; else try next bit
  460.  
  461. postGAS:
  462.         mov     [si].ci_flagGA,0        ; reset all flags for next request
  463.  
  464. ;** If this request is the owner of the oci_sem semaphore, clear it.
  465. ; We do this here, rather than in the respective ComXXX routines,
  466. ; because of the many places in which these routines can 'exit'.
  467.  
  468.         ;BUGBUG internal error if ds:si not a ComInfo
  469.         ;can't call ChkComInfoPtr because already poped stack frame.
  470. cmx_oci:
  471.         mov     ax,es                           ; (ax) = es
  472.         cmp     ax,[si].ci_oci_sem_own._hi
  473.         jne     cmret                           ; not oci_sem owner
  474.  
  475.         cmp     di,[si].ci_oci_sem_own._lo
  476.         jne     cmret                           ; not oci_sem owner
  477.  
  478.         ; this request owns the semaphore so clear it
  479.         mov     ax,ds
  480.         lea     bx,[si].ci_oci_sem              ; (ax:bx) -> semaphore
  481.         mov     dl,DevHlp_SemClear
  482.         DevHelp
  483.  
  484.         mov     [si].ci_oci_sem_own._hi,0       ; zap owner high (segment)
  485.  
  486. cmret:  ret
  487.  
  488. EndProc ComStrat
  489.  
  490.  
  491. ;**     IDC_Handler - IDC strategy entry point for COM
  492. ;
  493. ;       IDC_Handler is the entry point for the IDC strategy
  494. ;       routine for the asynch device driver. The strategy routine is
  495. ;       called by the PCMCIA drivers.
  496. ;
  497. ;       ENTRY   (es:bx) -> request packet
  498. ;               (ds) DSEG segment for com01.sys
  499. ;
  500. ;       EXIT    result of operation set in request
  501. ;               packet status field (Return_Code)
  502. ;
  503. ;       USES    di
  504. Procedure IDC_Handler,FAR
  505.  
  506.         push    es
  507.         push    ds
  508.         pusha
  509.         setDS   DSEG
  510.         mov     di,bx                   ; (es:di) -> request packet
  511.         mov     dx,es:[di].Command_Flag        ;Check Command Flag
  512.         cmp     dx,INSTALL_CMD                 ; Is it for Install COM port?
  513.         je      idc10                          ; Yes
  514.         cmp     dx,DEINSTALL_CMD               ; Is it for Deinstall COM port?
  515.         lje     idc_deinstall                  ; Yes
  516.         mov     cx,ERROR_INVALID_FUNCTION      ; Otherwise, invalid Command
  517.         jmp     idc88                          ; Set Return Code and end
  518. ; Process Install COM port command
  519. idc10:                                         ; 
  520.         mov     ax,es:[di].Com_Port_Num        ; Check for Port Number conflict
  521.         cmp     ax,MAXCOMPORTS                 ; Com port > 4?
  522.         ljg     port_num_conflict              ; yes
  523.         dec     ax                             ; 
  524.         shl     ax,1                           ; 
  525.         push    bx
  526.         lea     bx,Com1                        ; Check 40:X for conflict
  527.         add     bx,ax                          ; 
  528.         mov     bx,DS:[bx]                     ; 
  529.         cmp     bx,0                           ; 
  530.         pop     bx
  531.         ljne    port_num_conflict              ; 
  532.  
  533.         ; COM port address verification        ;
  534. no_40x_conflict:
  535.         mov     dx,es:[bx].Com_Port_Addr
  536.         cmp     dx,0                           ; 
  537.         lje     port_addr_conflict
  538.         mov     si,Com1                        ; 
  539.         cmp     si,0                           ; 
  540.         je      addr_check2                    ; 
  541.         mov     dx,ds:[si].ci_port             ; 
  542.         cmp     es:[bx].Com_Port_Addr,dx       ; 
  543.         jne     addr_check2                    ; 
  544.         jmp     port_addr_conflict             ; 
  545. addr_check2:                                   ; 
  546.         mov     si,Com2                        ; 
  547.         cmp     si,0                           ; 
  548.         je      addr_check3                    ; 
  549.         mov     dx,ds:[si].ci_port             ; 
  550.         cmp     es:[bx].Com_Port_Addr,dx       ; 
  551.         jne     addr_check3                    ; 
  552.         jmp     port_addr_conflict             ; 
  553. addr_check3:                                   ; 
  554.         mov     si,Com3                        ; 
  555.         cmp     si,0                           ; 
  556.         je      addr_check4                    ; 
  557.         mov     dx,ds:[si].ci_port             ; 
  558.         cmp     es:[bx].Com_Port_Addr,dx       ; 
  559.         jne     addr_check4                    ; 
  560.         jmp     port_addr_conflict             ; 
  561. addr_check4:                                   ; 
  562.         mov     si,Com4                        ; 
  563.         cmp     si,0                           ; 
  564.         je      irq_check                      ; 
  565.         mov     dx,ds:[si].ci_port             ; 
  566.         cmp     es:[bx].Com_Port_Addr,dx       ; 
  567.         jne     irq_check                      ; 
  568.         jmp     port_addr_conflict             ; 
  569.         ;  IRQ verification
  570. public irq_check
  571. irq_check:                                     ; 
  572.         mov     dx,es:[di].Com_Port_IRQ        ; Copy port IRQ from IDC packet
  573.         cmp     dx,0
  574.         lje     port_irq_conflict
  575.  
  576.         mov     ax,es:[di].Com_Port_Num        ; 
  577.         dec     ax                             ; 
  578.         shl     ax,1                           ; 
  579.         lea     bx,Com1P                       ;  Copy ComNP to ComN
  580.         add     bx,ax                          ;  to install COM port
  581.         mov     dx,DS:[bx]                     ; 
  582.         mov     si,dx                          ; 
  583.  
  584.         mov     dx,es:[di].Com_Port_IRQ        ; Copy port IRQ from IDC packet
  585.  
  586.  
  587.         lea     bx,Com1                        ; 
  588.         add     bx,ax                          ; 
  589.         mov     DS:[bx],si                     ; 
  590.  
  591.         shr     ax,1
  592.  
  593. no_irq_conflict:                               ; 
  594.         ; SetUp ComInfo Structure!
  595.         mov     ds:[si].ci_port_number,al      ; 
  596.         mov     ds:[si].ci_irq,dl              ; to ComInfo structure
  597.         mov     dx,es:[di].Com_Port_Addr       ; Copy port addr from IDC packet
  598.         mov     ds:[si].ci_port,dx             ; to ComInfo structure
  599.         mov     [si].ci_flagx,0                ; chip type = ?  @72032
  600.         mov     [si].ci_dcb_writeto, WRITE_TO_INIT    ; write timeout
  601.         mov     [si].ci_dcb_readto, READ_TO_INIT      ; read  timeout
  602.         mov     [si].ci_dcb_flags1, F1_INIT           ; first  flags byte
  603.         mov     [si].ci_dcb_flags2, F2_INIT           ; second flags byte
  604.         mov     [si].ci_dcb_flags3, F3_INIT           ; third  flags byte
  605.         mov     [si].ci_dcb_XonChar, xonequ           ; XON  character
  606.         mov     [si].ci_dcb_XoffChar, xoffequ         ; XOFF character
  607.         mov     [si].ci_signature, SIGNATURE          ; signature ID word
  608.         mov     [si].ci_baud, DEFAULT_BAUD            ; baud rate
  609.         mov     [si].ci_bytesize, DEFAULT_BYTESIZE    ; TX/RX byte size
  610.         mov     [si].ci_parity, DEFAULT_PARITY        ; parity
  611.         mov     [si].ci_stopbits, DEFAULT_STOPBITS    ; stop bits
  612.         mov     [si].ci_cmask, DEFAULT_CHAR_MASK      ; received character mask
  613.         mov     [si].ci_depth, D_NONE                 ; interrupt depth
  614.         mov     [si].ci_r_rpl.rpl_signature, SIGNATURE
  615.         mov     [si].ci_w_rpl.rpl_signature, SIGNATURE
  616.         mov     [si].ci_int_sharing, 0                ; int. sharing
  617.         mov     [si].ci_mult_COMs_IRQ, 0              ; no other COM ports
  618.                                                       ; on this IRQ line
  619.         or      [si].ci_dcb_flags2,F2_BRK_CHAR        ;break replace active
  620.  
  621.         or      [si].ci_vdm_flag,VDM_Flag_notify_the_VCOM_TX   ;@VDM
  622.         or      [si].ci_vdm_flag,VDM_Flag_notify_the_VCOM_RX   ;@VDM
  623.         or      [si].ci_vdm_flag,VDM_Flag_InOut_Handshake_Init
  624.         mov     [si].ci_vdm_Rx_State,1                ;@VDM set to Rx state 1
  625.         mov     [si].ci_vdm_Tx_State,1                ;@VDM set to Tx state 1
  626.         mov     [si].ci_vdm_Rx_Count,0                ;@VDM
  627.         mov     [si].ci_vdm_Tx_Count,0                ;@VDM
  628.         mov     [si].ci_vdm_LastMSR,0                 ;@VDM
  629.         or      [si].ci_flagx1, FX1_PCMCIA_MODEM      ; Leave pcmcia bit
  630.  
  631.         push    es
  632.         push    ax
  633.         push    dx
  634.  
  635.         push    DSEG
  636.         push    si
  637.         call    _RMHELP_FindPCMCIANode
  638.         add     sp,4
  639.  
  640.         push    DSEG
  641.         push    si
  642.         call    _RMHELP_CreateLDev
  643.         add     sp,4
  644.         pop     dx
  645.         pop     ax
  646.         pop     es
  647.  
  648.  
  649. public idc_40_0
  650. idc_40_0:
  651.                                         ; update 40:0 area ; 85558
  652.         mov     bx,ax                   ; port num
  653.         shl     bx,1                    ; com minor
  654.         mov     ax,COM_SEG              ; 40: tiled selector to ROM data
  655.         push    es                      ; save es
  656.         mov     es,ax                   ; (es:bx) -> 40:X
  657.         mov     es:[bx],dx              ; (dx) -> port addr
  658.         pop     es                      ; restore es
  659.  
  660. public idc_uart
  661. idc_uart:
  662.         ; check for 16550A (FIFO)
  663.         add     dx,R_FIFOC                     ; (dx) -> FIFO control register
  664.         mov     al,FF_CLEAR_RX OR FF_CLEAR_TX
  665.         mout    dx,al                          ; try to turn off the 16550A FIFOs
  666.  
  667.         mov     al,FF_ENABLE
  668.         mout    dx,al                          ; try to turn on the 16550A FIFOs
  669.         min     al,dx                          ; (al) = interrupt id
  670.         and     al,II_16550A
  671.         test    [si].ci_flagx,FX_16550A        ; chip type = 16550A?
  672.         jnz     idc20
  673.         cmp     al,II_16550A
  674.         jne     idc21                          ; NO 16550A FIFO; go check for 16450
  675.  
  676. idc20:
  677.         or      [si].ci_flagx,FX_16550A        ; chip type = 16550A
  678.         or      [si].ci_dcb_flags3,F3_FIFO_APO ; FIFO auto priority override
  679.  
  680.         xor     al,al
  681.         mout    dx,al                          ; disable the 16550 FIFOs
  682.  
  683.         jmp     short idc23
  684.  
  685. idc21:  ; check for 16450 (or 16550) by looking for the scratch register
  686.         ; that is only on the 16450, 16550 and 16550A (not on 8250x).
  687.         MAGIC   EQU     10101100b
  688.  
  689.         xor     al,al
  690.         mout    dx,al                   ; disable the 16550 FIFOs
  691.  
  692.         add     dx,R_SCRATCH-R_FIFOC    ; (dx) -> scratch register
  693.         mov     al,MAGIC
  694.         mout    dx,al                   ; (scratch) = MAGIC
  695.         min     al,dx                   ; (al) = (scratch)
  696.         cmp     al,MAGIC
  697.         jne     idc23                   ; NO scratch register; must be 8250
  698.  
  699.         or      [si].ci_flagx,FX_16450  ; set type flag to 16450
  700.  
  701. idc23:
  702.         cmp     Kernel_Type, ABIOS_COM         ; 
  703.         jne     idc30                          ; 
  704.         cli
  705.         call    InitSharedIRQ
  706.         sti
  707.         mov     [si].ci_int_sharing, INT_SHARING ; sharing com irq
  708.         mov     [si].ci_mult_COMs_IRQ, INT_SHARING ; 
  709.         cli
  710.         call    OptimizeSharedIRQs
  711.         sti
  712. idc30:
  713.         mov     dx,[si].ci_port         ; get port address
  714.         add     dx,R_MODMC              ; (dx) -> modem control reg.
  715.         xor     al,al                   ; (al) = 0
  716.         mout    dx,al                   ; lower all modem control lines
  717.  
  718.         add     dx,R_LINEC-R_MODMC      ; (dx) -> line control reg.
  719.         min     al,dx                   ; (al) = line control register
  720.         and     al,NOT LC_BREAK         ; turn off break
  721.         mout    dx,al                   ; send to port
  722.  
  723. ; save interrupt handler offset
  724.  
  725. ; To make multiple COM ports easier to handle, this code is now
  726. ; table driven.
  727. idc40:
  728.         mov     bx,es:[di].Com_Port_Num
  729.         dec     bx                      ; (bx) = minor number
  730.         shl     bx,1                    ; (es:bx) -> 40:X
  731.         mov     dx, IntRoutines[bx]     ; bx = com_minor*2
  732.         add     bx, OFFSET DSEG:Com1    ; adjust to com. data struc.
  733.  
  734. idc45:
  735.         setDS   DSEG
  736.         mov     [si].ci_isr,dx          ; save in cominfo
  737.         mov     [bx],si                 ; init ComInfo ptr.
  738.  
  739.         call    InitQueues              ; initialize input and output queues
  740.  
  741.         xor     cx,cx                        ; NO_ERROR return code
  742.         jmp     SHORT idc89                  ; CY cleared by XOR
  743.  
  744. ; Process Deinstall COM port command
  745. public idc_deinstall
  746. idc_deinstall:
  747.         mov     ax,es:[di].Com_Port_Num
  748.         dec     ax
  749.         shl     ax,1
  750.         lea     bx,Com1
  751.         add     bx,ax
  752.         mov     ax,ds:[bx]
  753.         mov     si,ax
  754.         cmp     ax,0
  755.         je      port_not_exist
  756.         xor     ax,ax
  757.         mov     ds:[bx],ax
  758.                                         ; 85558
  759.         mov     bx,es:[di].Com_Port_Num ; Update 40:X BIOS data area
  760.         dec     bx                      ; Zero based
  761.         shl     bx,1                    ; Offset into 40:0
  762.         mov     ax,COM_SEG              ; 40: tiled selector to ROM data
  763.         push    es                      ; save es
  764.         mov     es,ax                   ; (es:bx) -> 40:X
  765.         xor     ax,ax                   ; clear ax
  766.         mov     es:[bx],ax              ; (dx) -> port addr
  767.  
  768.  
  769.         push    DSEG
  770.         push    si
  771.         call    _RMHELP_DestroyLDev
  772.         add     sp,4
  773.  
  774.         pop     es                      ; restore es
  775.  
  776.         cli
  777.         call    OptimizeSharedIRQs             ; Clean up SharedIRQ structure
  778.         sti
  779.         xor     cx,cx                          ; NO_ERROR return code
  780.         jmp     SHORT idc89                    ; CY cleared by XOR
  781. port_not_exist:                                ; 
  782.         mov     cx,ERROR_DEV_NOT_EXIST         ; 
  783.         jmp     SHORT idc88                    ; 
  784. port_irq_conflict:                             ; 
  785.         mov     cx,ERROR_INTERRUPT             ; 
  786.         jmp     SHORT idc88                    ; 
  787. port_addr_conflict:                            ; 
  788.         mov     cx,487                         ; ERROR_INVALID_ADDRESS
  789.         jmp     SHORT idc88                    ; 
  790. port_num_conflict:                             ; 
  791.         mov     cx,ERROR_DEVICE_IN_USE         ; 
  792. idc88:  stc                                    ; CY set for ERROR
  793. idc89:                                         ; 
  794.         mov     es:[di].Return_Code,cx         ; 
  795. idc90:                                         ; 
  796.         popa
  797.         pop  ds
  798.         pop  es
  799.         ret                                    ; 
  800.  
  801. EndProc IDC_Handler
  802.  
  803. ;**     ComOpen - open request handler
  804. ;
  805. ;       Most of the work performed by ComOpen occurs if the device
  806. ;       is being opened for the first time. If it isn't all we have
  807. ;       to do is increment the count of the number of opens (this is
  808. ;       needed for close processing). If it is the first open then we
  809. ;       have to initialize the device and the driver. Specifically, we
  810. ;       have to;
  811. ;               - hook the appropriate IRQ
  812. ;               - hook the timer ticks
  813. ;               - initialize the clock interval value (done once per boot)
  814. ;               - flush the I/O queues
  815. ;               - initialize the DCB structure, line control register,
  816. ;                 hardware registers and hardware handshake status
  817. ;               - enable the modem control signals which in turn enables
  818. ;                 the remote transmitter
  819. ;
  820. ;       ENTRY   (ds:si) -> ComInfo
  821. ;               (es:di) -> request packet
  822. ;
  823. ;       EXIT    hardware and driver initialized, open count incremented
  824. ;
  825. ;       USES    ax bx cx dx di
  826.  
  827. Procedure ComOpen,NEAR
  828.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  829.  
  830.         ChkComInfoPtr
  831.         ChkRPPtr
  832.  
  833.         mov     [si].ci_vdm_OpenError ,1        ;@VDM set up for general failure
  834.  
  835.         test    es:[di].PktStatus,open_monitor
  836.         jz      cop01
  837.  
  838.         test    [si].ci_vdm_flag,VDM_Flag_InUse  ; FIX ---------------
  839.         ljz     CmxMonitor                       ; no monitor support
  840.         jmp     CmxGenFail                       ; if vdm, it is a failure
  841.  
  842. ; We need to insure mutual exclusion between opens, closes and ioctls.
  843. cop01:
  844.         call    Get_OCI_Sem                     ; will not return if error
  845.  
  846.         ChkComInfoPtr
  847.  
  848.         cmp     [si].ci_nopens,0
  849.         je      cop05                           ; not first open
  850.  
  851. ;@VDM Begin
  852. ; check for VDM-Protectmode conflict
  853. ;    IF (OpenCount != 0) AND (ComInfo.vdm_flag.InUse = TRUE)
  854.         test    [si].ci_vdm_flag,VDM_Flag_InUse  ;CP20D1390 ---------------
  855.         jz      vdm_sup001                       ;  |
  856.         push    es                               ;  |
  857.         push    ax
  858.         mov     al,LocINFOseg             ;Set VAR index for Local InfoSeg.
  859.         mov     dl,DevHlp_GetDOSVar       ;Set DevHlp function.
  860.         xor     dh,dh
  861.         call    [DevHlp]                  ;Go get variable address.
  862.         mov     es,ax                     ;Make ES:BX point to InfoSeg address variable.
  863.         mov     ax,es:[bx]+2
  864.         mov     bx,es:[bx]
  865.         mov     es,ax                     ;Make ES:BX point to InfoSeg address variable.
  866.         mov     ax,es:[bx].LIS_CurScrnGrp ;Get Screen Group ID = Session ID
  867.         cmp     [si].ci_sid,ax                   ; 
  868.         pop     ax                               ;  |
  869.         pop     es                               ;  |
  870.         je      UsedOpen                         ;CP20D1390
  871.  
  872. ;    THEN
  873.         jmp     CmxInUse
  874.  
  875. UsedOpen:                               ; CP20D1390
  876.         inc     [si].ci_nvdmopens       ; Increment the counter for special VDM open
  877.  
  878. vdm_sup001:                             ; not in use by VDM
  879. ;    ENDIF
  880. ;@VDM End
  881.  
  882.         jmp     cop80
  883.  
  884. ; When the device is opened for the first time there are a number of
  885. ; initializations that need to be performed.
  886.  
  887. cop05:
  888.         test    [si].ci_vdm_flag,VDM_Flag_No_IRQ_Open
  889.         ljnz     cop90
  890.  
  891.         test    [si].ci_vdm_flag,VDM_Flag_InOut_Handshake_Init
  892.         jz      cop0505
  893.         and     [si].ci_vdm_flag,NOT VDM_Flag_InOut_Handshake_Init
  894.         push    ax
  895.         push    es                               ;  |
  896.         mov     al,LocINFOseg             ;Set VAR index for Local InfoSeg.
  897.         mov     dl,DevHlp_GetDOSVar       ;Set DevHlp function.
  898.         xor     dh,dh
  899.         call    [DevHlp]                  ;Go get variable address.
  900.         mov     es,ax                     ;Make ES:BX point to InfoSeg address variable.
  901.         mov     ax,es:[bx]+2
  902.         mov     bx,es:[bx]
  903.         mov     es,ax                     ;Make ES:BX point to InfoSeg address variable.
  904.         cmp     es:[bx].LIS_ProcType,LIS_PT_REALMODE  ;If VDM session
  905.         jne     cop0504
  906.  
  907.         mov     al,[si].ci_dcb_flags1
  908.         and     al,NOT F1_IN_DSR_SENSE  ; IDSR=OFF
  909.         and     al,NOT F1_OUT_DSR_FLOW  ; ODSR=OFF
  910.         and     al,NOT F1_OUT_CTS_FLOW  ; OCTS=OFF
  911.         mov     [si].ci_dcb_flags1,al
  912.  
  913. ;       mov     al,[si].ci_dcb_flags3
  914. ;       test    al,F3_FIFO_ON           ; Is FIFO enabled?
  915. ;       jz      cop0504                 ; no
  916. ;                                       ; yes
  917. ;       and     al,NOT F3_FIFO_ON       ; then,
  918. ;       or      al,F3_FIFO_OFF          ; disable FIFO
  919. ;
  920. ;       and     al,NOT F3_RX_MASK       ; set Receive Triger Level to 1 char
  921. ;       and     al,NOT F3_TX_16         ; set Transmit Triger Level to 1 char
  922. ;       mov     [si].ci_dcb_flags3,al
  923.  
  924. cop0504:
  925.         pop     es                               ;  |
  926.         pop     ax                               ;  |
  927.  
  928.  
  929. ; Rules for locking code and data segments:
  930. ;   if (port is only one open)
  931. ;       lock non-resident code and data segments;
  932. cop0505:
  933. .386p
  934.         cmp     TimerHook,0             ; has any port been opened?
  935.         ljne    codelocked              ; at least one opened so already locked
  936.  
  937.         push    si
  938.         ; lock driver's non-resident code segment
  939.         ; do a virttolin DevHelp (linear address)
  940.         mov     ax,CSEG
  941.         lea     esi,startswapcode
  942.         mov     dl,DevHlp_VirtToLin
  943.         DevHelp
  944.         mov     edi,eax
  945.         ; do a virttolin DevHelp (lockhandle)
  946.         mov     ax,DSEG
  947.         mov     esi,OFFSET codelockhandle
  948.         mov     dl,DevHlp_VirtToLin
  949.         DevHelp
  950.         ; do a VMLock DevHelp
  951.         mov     esi,eax         ; get offset to lock handle
  952.         mov     eax,16          ; long term lock
  953.         mov     ebx,edi         ; get offset to area to lock
  954.         mov     edi,-1          ; set to no page list
  955.         lea     ecx,endswapcode ; size to lock
  956.         sub     ecx,OFFSET startswapcode ; size to lock
  957.         mov     dl,DevHlp_VMLock
  958.         DevHelp
  959.         ljc     CmxBadLock
  960.  
  961.         ; Lock driver's non-resident data segment.
  962.  
  963.         ; If ANY enhanced ports were initialized, then this segment must
  964.         ; be both physically contiguous and writable. This segment contains
  965.         ; all ComInfos, and ComInfos contain the port's in/out queues.
  966.         ; An enhanced port may do DMA operations to/from these queues, so
  967.         ; the segment must be contiguous and writable. Since this lock is
  968.         ; done when the FIRST port is opened, the lock must be "DMA aware"
  969.         ; (subsequent enhanced port opens may need this).
  970.  
  971.         mov     ax,DSEG
  972.         lea     esi,startswapdata
  973.         mov     dl,DevHlp_VirtToLin
  974.         DevHelp
  975.         mov     edi,eax
  976.         ; do a virttolin DevHelp (lockhandle)
  977.         mov     ax,DSEG
  978.         mov     esi,OFFSET datalockhandle
  979.         mov     dl,DevHlp_VirtToLin
  980.         DevHelp
  981.         ; do a VMLock DevHelp
  982.         mov     esi,eax         ; get offset to lock handle
  983.         mov     ebx,edi         ; get offset to area to lock
  984.         mov     edi,-1          ; set to no page list
  985.         movzx   ecx,endswapdata ; size to lock
  986.         sub     ecx,OFFSET startswapdata ; size to lock
  987. LOCK_CONTIGUOUS EQU 0000010b
  988. LOCK_WRITE      EQU 0001000b
  989. LOCK_LONG_TERM  EQU 0010000b
  990.         mov     eax,LOCK_LONG_TERM
  991.         test    Flags,F_LOCK_CONTIGUOUS
  992.         jz      no_dma
  993.         or      eax,LOCK_CONTIGUOUS OR LOCK_WRITE
  994. no_dma: mov     dl,DevHlp_VMLock
  995.         DevHelp
  996.  
  997.         pop     si
  998.         jnc     codelocked
  999.  
  1000.         ; unlock code
  1001.         push    si
  1002.         ; do a virttolin DevHelp (lockhandle)
  1003.         mov     ax,DSEG
  1004.         mov     esi,OFFSET codelockhandle
  1005.         mov     dl,DevHlp_VirtToLin
  1006.         DevHelp
  1007.         ; do a VMUnlock DevHelp using previously saved lock handle
  1008.         mov     esi,eax         ; get offset to lock handle
  1009.         mov     dl,DevHlp_VMUnlock
  1010.         DevHelp
  1011.         pop     si
  1012.  
  1013.         jmp     CmxBadLock
  1014.  
  1015.  
  1016. codelocked:
  1017. .286p
  1018.         SetDS   DSEG
  1019. ;;==================== Enable LID again  RAY Change Team 11\30\93 =====
  1020. ; defect 77701 rdw  BUGBUG The following code was removed because of problems
  1021. ;                   wtih Resource Manager on Thinkpad with PCMCIA. There could
  1022. ;                   still be a problem if resource manger is not fixed.
  1023. ;
  1024.       cmp     Kernel_Type, ABIOS_COM
  1025.       jne     cop06c
  1026.  
  1027.       mov     al,DEVICE_ID                    ; set device ID value
  1028.       mov     bl, [si].ci_port_number         ; get port number
  1029.       inc     bl
  1030.       mov     dl,DevHlp_GetLIDEntry
  1031.       xor     dh, dh
  1032.       call    [DevHlp]                     ; go for it!
  1033.       jnc     cop06d
  1034.       mov     [si].ci_LID,0                ;clear       @95202
  1035.       cmp     ax, ERROR_LID_DOES_NOT_EXIST ;PCMCIA?     @95202
  1036.       je      cop06c                       ;no LID      @95202
  1037.       jmp     CmxInUse                     ; 
  1038.  
  1039. cop06d:
  1040.       mov     [si].ci_LID, ax              ; remember it for Close LID!
  1041. ;;==========================================================================
  1042.  
  1043. cop06c:
  1044.         test    [si].ci_mult_COMs_IRQ, INT_SHARING ; sharing the IRQ with
  1045.         jnz     cop069                          ; other COM ports?
  1046.  
  1047. cop06z:
  1048.         mov     ax,[si].ci_isr                  ; (ds:ax) -> handler
  1049.         mov     bl,[si].ci_irq                  ; (bx) = interrupt to be set
  1050.  
  1051. cop07:
  1052.         xor     bh,bh
  1053.         mov     dh,[si].ci_int_sharing          ; 0 on ISA, var. on EISA
  1054.         mov     dl,DevHlp_SetIRQ                ; devhlp request code
  1055.  
  1056.         ; Grab the interrupt vector.
  1057.         ; The interrupt handler will ignore interrupts (disable 16450 chip interrupts
  1058.         ; and EOI) if ci_nopens is zero, so interrupts can remain enabled until
  1059.         ; the interrupt enable register is to be set.
  1060.  
  1061.         push    es
  1062.         push    ds
  1063.         pop     es
  1064.  
  1065.         setDS   HSEG                     ; DS = driver's res. data seg
  1066.         call    es:[DevHlp]
  1067.         pop     es
  1068.         setDS   DSEG
  1069.  
  1070.         jnc     cop06                    ; error, couldn't get IRQ
  1071.  
  1072. copFreeLID:
  1073.         mov     ax,[si].ci_LID                  ; set device ID value
  1074.         mov     bl, [si].ci_port_number         ; get port number
  1075.         inc     bl
  1076.         mov     dl,DevHlp_FreeLIDEntry          ; Free LID
  1077.         xor     dh,dh
  1078.         call    [DevHlp]
  1079.         jmp     CmxGenFail
  1080.  
  1081. cop069:
  1082.         pushf                                   ; Y: save interrupt flag
  1083.         cli                                     ; while updating linked list
  1084.         call    EnqComInfo                      ; add to queue
  1085.         jnc     cop053                          ; no errors, so continue
  1086.         call    DeqComInfo                      ; add to queue
  1087.         popf                                    ; restore interrupt flag
  1088.         jmp     CmxGenFail                      ; error, couldn't get IRQ
  1089.  
  1090. cop053:
  1091.         popf                                    ; restore interrupt flag
  1092.  
  1093. ; We hook the timer once for the driver, not for each port.
  1094.  
  1095. cop06:
  1096.         cmp     TimerHook,0
  1097.         ljne    cop40                   ; timer already hooked
  1098.  
  1099. ; The system clock interval is retrieved once, the very first time we
  1100. ; get a first open.
  1101.  
  1102.         cmp     ClkIntrvl,0
  1103.         jne     cop30                   ; ClkIntrvl already known
  1104.  
  1105.         mov     al,1
  1106.         mov     dl,DevHlp_GetDOSVar
  1107.         DevHelp                         ; (ax:bx) -> SysInfoSeg
  1108.         jnc     cop10
  1109.  
  1110.         ComErr  <ComOpen : DOSvars unavailable>
  1111.  
  1112. cop10:  mov     es,ax
  1113.         mov     es,es:[bx]              ; (es:0) -> InfoSeg
  1114.         mov     SysInfoSeg,es           ; save SysInfoSeg pointer for close
  1115.         mov     ax,es:SIS_ClkIntrvl     ; (ax) = clock interval in 0.0001 secs.
  1116.  
  1117. ; BUGBUG 11-29-88 bryand - min clock interval = 100/10000 sec
  1118. ; The test below insures that we can divide the caller's timeout values
  1119. ; by the system clock interval and still store the results in a word.
  1120.  
  1121.         cmp     ax,100
  1122.         jae     cop20                   ; safe timeout value
  1123.  
  1124.         ComErr  <ComOpen : system timeout value too small>
  1125.  
  1126. cop20:  mov     ClkIntrvl,ax            ; save the value
  1127.  
  1128. ; Hook the timer
  1129.  
  1130. cop30:  mov     dl,DevHlp_SetTimer
  1131.         mov     ax,OFFSET Ticker
  1132.  
  1133.         setES   DSEG                            ; ES = seg where DevHlp is
  1134.         setDS   HSEG                            ; DS = driver's res. data seg
  1135.         call    es:[DevHlp]
  1136.         setDS   DSEG
  1137.  
  1138.         jnc     cop40                   ; sucessfully got timer
  1139.  
  1140.         ; could not hook timer - unset IRQ and fail the open
  1141.         test    [si].ci_mult_COMs_IRQ, INT_SHARING ; sharing the IRQ with
  1142.                                                 ;  other COM ports?
  1143.         jz      cop35                           ; N: unset normally
  1144.         pushf                                   ; Y: save interrupt flag
  1145.         cli                                     ; while updating linked list
  1146.         call    DeqComInfo                      ; remove from queue
  1147.         popf                                    ; restore interrupt flag
  1148.         jmp     CmxGenFail                      ;  then continue
  1149.  
  1150. cop35:
  1151.         xor     bh,bh
  1152.         mov     bl,[si].ci_irq
  1153.         mov     dl,DevHlp_UnSetIRQ
  1154.         setES   DSEG                            ; ES = seg where DevHlp is
  1155.         setDS   HSEG                            ; DS = driver's res. data seg
  1156.         call    es:[DevHlp]
  1157.         setDS   DSEG
  1158.         jmp     CmxGenFail
  1159.  
  1160.  
  1161. cop40:  inc     TimerHook               ; got timer - inc count
  1162.         FlushQueue      ci_qin          ; Flush the I/O queues.
  1163.         FlushQueue      ci_qout
  1164.  
  1165. ; Initialize dcb values and internal flags needed on a first open.
  1166.  
  1167.         mov     [si].ci_dcb_XonChar,xonequ
  1168.         mov     [si].ci_dcb_XoffChar,xoffequ
  1169.  
  1170.         mov     [si].ci_dcb_writeto,WRITE_TO_INIT
  1171.         mov     [si].ci_dcb_readto,READ_TO_INIT
  1172.  
  1173.         xor     ax,ax                   ; (AX) = 0
  1174.         mov     [si].ci_dcb_ErrChar,al
  1175.         mov     [si].ci_dcb_BrkChar,al
  1176.  
  1177.         and     [si].ci_dcb_flags2,NOT (F2_ERR_CHAR OR F2_NULL_STRIP OR F2_BRK_CHAR)
  1178.         and     [si].ci_dcb_flags3,NOT F3_READ_TO_MASK
  1179.         or      [si].ci_dcb_flags3,F3_READ_TO_NORM
  1180.  
  1181.         mov     [si].ci_event,ax
  1182.         mov     [si].ci_comerr,ax
  1183.         mov     [si].ci_hsflag,al
  1184.  
  1185.         mov     al,[si].ci_bytesize
  1186.         mov     ah,[si].ci_parity
  1187.         mov     ch,[si].ci_stopbits
  1188.         ; 
  1189.         ; reset VDM stuff for this port
  1190.         ; 
  1191. ;    IF (ComInfo.vdm_flag.InUse = TRUE)
  1192.         test    [si].ci_vdm_flag,VDM_Flag_InUse ;@VDM
  1193.         jz      vdm_sup010                      ;@VDM
  1194. ;    THEN
  1195.         or      [si].ci_dcb_flags2,F2_BRK_CHAR  ;break replace active
  1196.  
  1197.         or      [si].ci_vdm_flag,VDM_Flag_notify_the_VCOM_TX   ;@VDM
  1198.         or      [si].ci_vdm_flag,VDM_Flag_notify_the_VCOM_RX   ;@VDM
  1199.         mov     [si].ci_vdm_Rx_State,1          ;@VDM set to Rx state 1
  1200.         mov     [si].ci_vdm_Tx_State,1          ;@VDM set to Tx state 1
  1201.         mov     [si].ci_vdm_Rx_Count,0                         ;@VDM
  1202.         mov     [si].ci_vdm_Tx_Count,0                         ;@VDM
  1203.         mov     [si].ci_vdm_LastMSR,0                          ;@VDM
  1204.  
  1205. vdm_sup010:                             ; not in use by VDM
  1206.  
  1207.         call    CheckLCR                        ; set up line control reg.
  1208.         jnc     cop50
  1209.  
  1210.         ComErr  <ComOpen : invalid line control>
  1211.  
  1212. cop50:
  1213.  
  1214.  
  1215.         call    SetLineC          ; set LCR
  1216.  
  1217. ;
  1218. ;       vdm NO FIFO
  1219. ;
  1220. ;       test    [si].ci_vdm_flag,VDM_Flag_InUse
  1221. ;       jnz     cop55
  1222.  
  1223. ; ComputeAPO MUST be called before SetBaud so SetBaud can set
  1224. ; the timeouts based on the baud rate.
  1225.  
  1226.         call    ComputeAPO                  ; compute FIFO modes
  1227.  
  1228. cop55:
  1229.         mov     ax,[si].ci_baud
  1230.         call    SetBaud                         ; set baud rate and timeouts
  1231.         jnc     short cop70
  1232.  
  1233.         ComErr  <SetBaud : invalid baud rate>
  1234.  
  1235.  
  1236. ; Standard port: initialize UART registers.
  1237. cop70:  mov     dx,[si].ci_port
  1238.  
  1239. ; WARNING: From here to the end of ComOpen (dx) is used to address a number
  1240. ; of different ports. These port addresses are computed relative to the
  1241. ; address currently in (dx). Any changes to this code should be sensitive
  1242. ; to the order in which things occur.
  1243.  
  1244. ; rdw 81245 -  The following code has been added to handle     on SMC UART's
  1245. ;              per the recommendation from from SMC Engineering.
  1246. ; jag 102436 - Make sure interrupts are turned off at chip before prodding.
  1247.  
  1248. ; check for 16550A (FIFO)
  1249. public smcuart1
  1250. smcuart1:
  1251.         test    [si].ci_flagx1, FX1_PCMCIA_MODEM
  1252.         jnz     rlines
  1253.  
  1254.         xor     ax,ax                   ; clear ax - disable all ints
  1255.         add     dx,R_INTEN              ; (dx) -> interrupt enable reg
  1256.         mout    dx,al                   ; turn off ints
  1257.  
  1258.         add     dx, R_FIFOC-R_INTEN             ; 81245 (dx) -> FIFO Control Register
  1259.         mov     al, FF_CLEAR_RX OR FF_CLEAR_TX  ; 81245
  1260.         mout    dx, al                  ; 81245 try to turn of the 16550a FIFOs
  1261.  
  1262.         add     dx, R_MODMC-R_FIFOC     ; 81245 (dx) -> MCR
  1263.         min     al, dx                  ; 81245 Get current value of MCR
  1264.         or      al, MC_LOOP             ; 81245 Set loopback ON to clear THR
  1265.  
  1266.         mout    dx, al                  ; 81245
  1267.         add     dx, R_DATA-R_MODMC      ; 81245 (dx) -> RBR
  1268.         min     al, dx                  ; 81245 Clear the 1 byte RBR
  1269.  
  1270. ; 81245 At this point, we don't have to worry about clearing the loop back
  1271. ;       in the MCR as we will do this later when we clear MCR.
  1272. rlines:
  1273.         add     dx,R_LINES              ; (dx) -> line status reg
  1274.         min     al,dx                   ; (al) = line status (clear it)
  1275.         mov     [si].ci_lsrshadow,al    ; shadow the contents of the LSR
  1276.  
  1277.         add     dx,R_DATA-R_LINES       ; (dx) -> data reg
  1278.         min     al,dx                   ; clear RX buffer
  1279.  
  1280.         add     dx,R_FIFOC-R_DATA       ; (dx) -> fifo control reg
  1281.         test    [si].ci_dcb_flags3,F3_FIFO_HW_ON
  1282.         jz      cop75                   ; FIFO HW off
  1283.         mov     al,[si].ci_dcb_flags3   ; (al) = flags3
  1284.         and     al,F3_RX_MASK           ; (al) = RX trigger level
  1285.         shl     al,1                    ; (al) = RX trigger level bits for FIFO
  1286.         or      al,FF_ENABLE OR FF_CLEAR_RX OR FF_CLEAR_TX
  1287.         mout    dx,al                   ; clear RX and TX FIFOs
  1288.  
  1289. cop75:  .errnz  R_INTID-R_FIFOC
  1290. ;        add     dx,R_INTID-R_FIFOC      ; (dx) -> int id reg.
  1291.         min     al,dx                   ; clear int id
  1292.  
  1293.         mov     [si].ci_msrshadow,0     ; zero previous msrshadow
  1294.         add     dx,R_MODMS-R_INTID      ; (dx) -> modem status reg.
  1295.         min     al,dx                   ; clear modem status
  1296.         call    MxInt                   ; update msrshadow
  1297.  
  1298.         xor     bx,bx                   ; show 0 for previous flags1 and flags2
  1299.         call    ComputeHHS              ; set up handshake state and
  1300.                                         ; initialize the MCR
  1301.  
  1302.         call    EnableRemoteTX          ; we're all set up, tell the remote TXer
  1303.  
  1304.         cli                     ; disable processor interrupts before
  1305.                                 ; enabling 16450 chip interrupts
  1306.  
  1307. ; Enable Receive Data and nModem Status interrupts.
  1308. ; TX Holding Register interrupt will be enabled by CheckTx.
  1309.         mov     dx,[si].ci_port         ; (dx) -> port
  1310.  
  1311.  
  1312. public smcuart2
  1313. smcuart2:
  1314.         mov     al,IE_RX OR IE_MX       ; (al) = interrupts to enable
  1315.         add     dx,R_INTEN              ; (dx) -> interrupt enable reg
  1316.         mout    dx,al
  1317.  
  1318. cop80:
  1319.  
  1320.  
  1321.         inc     [si].ci_nopens          ; count the open calls
  1322.  
  1323. cop90:
  1324.         push    es                        ;CP20D1390 Store the Session ID
  1325.         push    ax
  1326.         mov     al,LocINFOseg             ;Set VAR index for Local InfoSeg.
  1327.         mov     dl,DevHlp_GetDOSVar       ;Set DevHlp function.
  1328.         xor     dh,dh
  1329.         call    [DevHlp]                  ;Go get variable address.
  1330.         mov     es,ax                     ;Make ES:BX point to InfoSeg address variable.
  1331.         mov     ax,es:[bx]+2
  1332.         mov     bx,es:[bx]
  1333.         mov     es,ax                     ;Make ES:BX point to InfoSeg address variable.
  1334.         mov     ax,es:[bx].LIS_CurScrnGrp ;Get Screen Group ID = Session ID
  1335.         mov     [si].ci_sid,ax            ;Save the Session ID
  1336.         pop     ax
  1337.         pop     es
  1338.  
  1339. cop100:
  1340.         sti                     ; enable processor interrupts now that
  1341.                                 ; UART/ESP interrupts are enabled and the
  1342.                                 ; open count has been incremented.
  1343.  
  1344.         jmp     CmxDone                 ; done, no error
  1345.  
  1346. EndProc ComOpen
  1347.  
  1348.  
  1349. ;**     ComClose - close request handler
  1350. ;
  1351. ;       ComClose performs most of its functions if it the close request
  1352. ;       leaves no pending opens on the device. If there are pending opens
  1353. ;       then ComClose does nothing. In the case where the close request
  1354. ;       will close the device, the following major functions are performed:
  1355. ;
  1356. ;               - I/O queues are flushed
  1357. ;               - XON is sent if a previous XOFF was sent
  1358. ;               - async interrupts are disabled
  1359. ;               - the TX hardware is flushed
  1360. ;               - the timer hook and IRQ are released
  1361. ;
  1362. ;       ENTRY   (ds:si) -> ComInfo
  1363. ;
  1364. ;       EXIT    open count decremented, device may be closed
  1365. ;
  1366. ;       USES    ax bx cx dx di
  1367.  
  1368. Procedure ComClose,NEAR
  1369.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1370.  
  1371.         ChkComInfoPtr
  1372.  
  1373. ; Need to insure mutual exclusion between opens, closes and ioctls.
  1374.  
  1375.         call    Get_OCI_Sem                     ; will not return if error
  1376.  
  1377.         ChkComInfoPtr
  1378.         ChkRPPtr
  1379.         ChkRPType       CMDClose
  1380.  
  1381.         cmp     [si].ci_nopens,0
  1382.         jne     ccl1                    ; device is open
  1383.         jmp     CmxDone                 ; done, no opens
  1384.  
  1385. ccl1:   cmp     [si].ci_nopens,1
  1386.         ljne    ccl99           ; not the last close, port is still open
  1387.  
  1388. ; Set the last close flag so that the RX interrupt service routine
  1389. ; will not enqueue any more data.
  1390.         test    [si].ci_vdm_flag,VDM_Flag_No_IRQ_Open
  1391.         ljnz     ccl99
  1392.  
  1393.         or      [si].ci_flagx,FX_LAST_CLOSE     ; flag last close in progress
  1394.  
  1395.         mov     [si].ci_sid,0           ; Clear the Session ID (@0001)
  1396.  
  1397.         SaveReg <es,di>                 ; 103070-1 Keep our Req. Packet PTR
  1398.         call    ComWFlushSub            ; flush all outstanding write requests
  1399.         call    ComRFlushSub            ; flush all outstanding read  requests
  1400.         RestoreReg <di,es>              ; 103070-1 Restore our Req. Packet PTR
  1401.  
  1402.         mov     al,[si].ci_linec        ; (al) = line control value
  1403.         and     al,NOT LC_BREAK         ; turn off break
  1404.         and     [si].ci_hsflag, NOT HS_BREAK_SET
  1405.                                         ; break no longer set
  1406.         call    SetLineC
  1407.  
  1408.         ; Standard port:
  1409. ccl13:  call    EnableRemoteTX          ; send an XON if XOFF previously sent
  1410.  
  1411.         mov     dx,[si].ci_port
  1412.         add     dx,R_INTEN              ; (dx) -> interruprt enable reg
  1413.         xor     al,al
  1414.         mout    dx,al                   ; disable all com interrupts
  1415.  
  1416.         test    [si].ci_mult_COMs_IRQ, INT_SHARING ; sharing the IRQ with
  1417.                                         ; other COM ports?
  1418.         jz      ccl12                   ; N: unset normally
  1419.         pushf                           ; Y: save interrupt flag
  1420.         cli                             ; while updating linked list
  1421.         call    DeqComInfo              ; remove from queue
  1422.         popf                            ; restore interrupt flag
  1423.         jmp     short ccl15             ;  then continue
  1424.  
  1425. ccl12:
  1426.  
  1427. ccl14:
  1428.         xor     bh,bh
  1429.         mov     bl,[si].ci_irq
  1430.         mov     dl,DevHlp_UnSetIRQ
  1431.         push    es
  1432.         push    ds
  1433.         pop     es
  1434.         setDS   HSEG
  1435.         call    es:[DevHlp]             ; release the IRQ
  1436.         pop     es
  1437.         setDS   DSEG
  1438.         jnc     ccl15
  1439.  
  1440.         ComErr  <ComClose : could not release the IRQ>
  1441.  
  1442.         ; BUGBUG Should we compute wait time based on byte size too?
  1443.         ; if either DTR or RTS is ON, we need to wait:
  1444.         ;   for data to get out of TX hardware (THRE & TSRE)
  1445.         ;     up to 2 character times (.5 char time at a time up to 1 second)
  1446.         ;   for data to be received by remote
  1447.         ;     10 character times up to a 1 second maximum
  1448.         ; before turning OFF DTR and RTS.
  1449.  
  1450. ccl15:  mov     dx,[si].ci_port
  1451.         add     dx,R_MODMC              ; (dx) -> modem control reg
  1452.         min     al,dx                   ; al = modem output signals
  1453.         test    al,MC_DTR OR MC_RTS
  1454.         ljz     ccl60                   ; lines are already down, don't wait
  1455.  
  1456.         ; wait for data to get out of TX hardware (THRE & TSRE)
  1457.         ; 6000 (bits*ms/sec) = 12 bits * .5 chars * 1000 (ms/sec)
  1458.         ; ms = 6000 (bits*ms/sec) / baud (bits/sec)
  1459.         xor     dx,dx
  1460.         mov     ax,6000d              ; dx:ax = 6000d
  1461.  
  1462.         ; trap 0 problem: ci_baud MUST be > 0 for the div to work
  1463.         ;                 the result MUST fit into ax for the div to work
  1464.         ;                 (dx = 0 so the above is true)
  1465.         cmp     [si].ci_baud,0
  1466.         je      ccl151
  1467.         div     [si].ci_baud            ; ax = ms for 6 bits
  1468.         jmp     short   ccl152
  1469. ccl151:
  1470.         mov     ax,998d                 ; set AX value for ci_baud = 0
  1471. ccl152:
  1472.  
  1473.         inc     ax                      ; round up
  1474.         mov     cx,ax                   ; (0:cx)  = timeout
  1475.         cmp     cx,1000d
  1476.         jb      ccl20                   ; cx < 1 second timeout
  1477.  
  1478.         mov     cx,1000d                ; cx = 1 second timeout
  1479.  
  1480. ccl20:  ; don't have to use ReadLSR because IRQ is already disabled
  1481.         mov     dx,[si].ci_port
  1482.         add     dx,R_LINES              ; (dx) -> LSR
  1483.         min     al,dx                   ; (al) =  LSR
  1484.         and     al,LS_THRE OR LS_TSRE
  1485.         cmp     al,LS_THRE OR LS_TSRE
  1486.         je      ccl30                   ; transmit hardware already empty
  1487.         xor     dx,dx                   ; (dx:cx) = timeout value
  1488.         cli                             ; 103070-1 must cli before block
  1489.         call    ProcBlockNI             ; wait for data to get out of hardware
  1490.         jmp     SHORT ccl20             ; go check if done
  1491.  
  1492.         ; wait 10 char times for data to be received by remote (1 sec max)
  1493.         ; 120000 (bits*ms/sec) = 12 bits * 10 chars * 1000 (ms/sec)
  1494.         ; ms = 120000 (bits*ms/sec) / baud (bits/sec)
  1495.         ; NOTE: baud must be >= 2 or div will overflow
  1496.         ; 
  1497.         ; timeout = (120000/baud)+1
  1498.         ; if (timeout > 1000)
  1499.         ;     timeout = 1000
  1500.         ; endtime = MsCount + timeout
  1501.         ; do {
  1502.         ;     block(timeout)
  1503.         ;     timeout = endtime - MsCount
  1504.         ; } while (timeout > 0);
  1505.  
  1506. ccl30:  mov     dx,1
  1507.         mov     ax,0d4c0h               ; (dx:ax) = 120000
  1508.  
  1509.         cmp     [si].ci_baud,2          ; remove trap 0
  1510.         jb      ccl301
  1511.         div     [si].ci_baud            ; ax = ms for 12 bits
  1512.         jmp     short   ccl302
  1513. ccl301:
  1514.         mov     ax,998d
  1515. ccl302:
  1516.  
  1517.         inc     ax                      ; round up
  1518.         mov     cx,ax
  1519.         xor     dx,dx                   ; (dx:cx) = timeout value
  1520.         cmp     cx,1000d
  1521.         jb      ccl40                   ; cx < 1 second timeout
  1522.  
  1523.         mov     cx,1000d                ; cx = 1 second timeout
  1524.  
  1525. ccl40:  ; get current time (running MS count from sysinfoseg)
  1526.         SaveReg         <ds>
  1527.         mov     ax,SysInfoSeg           ; get SysInfoSeg pointer for close
  1528.         mov     ds,ax
  1529.         cli                             ;JGT  disable to read MsCount
  1530.         mov     ax,ds:SIS_MsCount._hi
  1531.         mov     bx,ds:SIS_MsCount._lo   ; (ax:bx) = running MS count
  1532.         sti                             ;JGT  and reenable
  1533.         RestoreReg      <ds>
  1534.         add     bx,cx
  1535.         adc     ax,0                    ; (ax:bx) = completion MS count
  1536.  
  1537. ccl50:  SaveReg         <ax,bx>         ; save completion MS count
  1538.  
  1539.         cli                             ; 103070-1 must cli before block
  1540.         call    ProcBlockNI             ; wait for remote to get data
  1541.         ; blocks NON-INTERRUPTABLY for up to 1 second
  1542.         ; if the block times out, then the full time was waited;
  1543.         ; else spurious ProcRun, we have to make sure enough time elapsed
  1544.  
  1545.         RestoreReg      <bx,ax>         ; (ax:bx) = completion MS count
  1546.         jc      ccl60                   ; block timed out, were done
  1547.  
  1548.         SaveReg         <ds>
  1549.         mov     cx,SysInfoSeg
  1550.         mov     ds,cx                   ; (ds:0) -> SysInfoSeg
  1551.         mov     cx,bx
  1552.         mov     dx,ax                   ; (dx:cx) = completion MS count
  1553.         cli                             ;JGT  disable to read MsCount
  1554.         sub     cx,ds:SIS_MsCount._lo
  1555.         sbb     dx,ds:SIS_MsCount._hi   ; (dx:cx) = MS remaining
  1556.         sti                             ;JGT  and reenable
  1557.         RestoreReg      <ds>
  1558.  
  1559.         js      ccl60                   ; remaining is neg, done
  1560.         jnz     ccl50                   ; remaining is NZ, not done
  1561.         or      cx,cx
  1562.         jnz     ccl50                   ; remaining is NZ, not done
  1563.  
  1564. ccl60:  mov     dx,[si].ci_port
  1565.         add     dx,R_MODMC              ; (dx) -> modem control reg
  1566.         xor     al,al
  1567.         mout    dx,al                   ; turn off all MCR signals
  1568.  
  1569.  
  1570. ccl70:
  1571. .386p
  1572.         ; Unhook timer if all devices closed
  1573.         dec     TimerHook
  1574.         jnz     ccl90                   ; one of the ports still has
  1575.                                         ; outstanding opens
  1576.  
  1577.         mov     dl,DevHlp_ResetTimer
  1578.         mov     ax,OFFSET Ticker
  1579.  
  1580.         setES   DSEG
  1581.         setDS   HSEG
  1582.         call    es:[DevHlp]
  1583.         setDS   DSEG
  1584.  
  1585.         ; unlock code
  1586.         push    si
  1587.         ; do a virttolin DevHelp (lockhandle)
  1588.         mov     ax,ds
  1589.         mov     esi,OFFSET codelockhandle
  1590.         mov     dl,DevHlp_VirtToLin
  1591.         DevHelp
  1592.         ; do a VMUnlock DevHelp using previously saved lock handle
  1593.         mov     esi,eax         ; get offset to lock handle
  1594.         mov     dl,DevHlp_VMUnlock
  1595.         DevHelp
  1596.         pop     si
  1597.  
  1598.         ; unlock common data
  1599.         push    si
  1600.         ; do a virttolin DevHelp (lockhandle)
  1601.         mov     ax,ds
  1602.         mov     esi,OFFSET datalockhandle
  1603.         mov     dl,DevHlp_VirtToLin
  1604.         DevHelp
  1605.         ; do a VMUnlock DevHelp using previously saved lock handle
  1606.         mov     esi,eax         ; get offset to lock handle
  1607.         mov     dl,DevHlp_VMUnlock
  1608.         DevHelp
  1609.         pop     si
  1610.  
  1611. .286p
  1612.  
  1613.         jnc     ccl90
  1614.  
  1615.         ComErr  <ComClose : could not reset timer>
  1616.  
  1617. ccl90:  and     [si].ci_flagx,NOT FX_LAST_CLOSE  ; clear last close flag
  1618.  
  1619.         cmp     Kernel_Type, ABIOS_COM
  1620.         jne     ccl99
  1621.  
  1622.         mov     ax, [si].ci_LID            ; retrieve the LID for him
  1623.         mov     dl, DevHlp_FreeLIDEntry
  1624.         call    [DevHlp]
  1625.  
  1626.  
  1627. ccl99:  dec     [si].ci_nopens          ; one less open
  1628.  
  1629.         cmp     [si].ci_nvdmopens,0     ; CP20D1390 If special VDM open was done
  1630.         jle     ccl100                  ; then
  1631.         dec     [si].ci_nvdmopens       ; decrement the counter
  1632. ccl100:
  1633.         jmp     CmxDone
  1634.  
  1635. EndProc ComClose
  1636.  
  1637.  
  1638. ;**     ComDeInstall - deinstall request handler
  1639. ;
  1640. ;       Deinstallation is not supported.
  1641. ;
  1642. ;       ENTRY
  1643. ;
  1644. ;       EXIT
  1645. ;
  1646. ;       USES
  1647.  
  1648. ;Procedure ComDeInstall,NEAR
  1649.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1650.  
  1651. ; Since we are not supporting deinstallation, we optimize the handling
  1652. ; of this request by making its table entry CmxUnknown.
  1653.  
  1654. ;EndProc ComDeInstall
  1655.  
  1656.  
  1657. ;**     ComRead - read request handler
  1658. ;
  1659. ;       ComRead handles read requests for the driver. If there are no
  1660. ;       outstanding requests, we will attempt to satisfy the current
  1661. ;       one immediately. If we can't then we will block the thread
  1662. ;       until we can satisfy it or we time out. Once the thread wakes
  1663. ;       up from the block it will attempt to satisfy its request.
  1664. ;
  1665. ;       ENTRY   (ds:si) -> ComInfo
  1666. ;               (es:di) -> request packet
  1667. ;
  1668. ;       EXIT
  1669. ;
  1670. ;       USES    al cx dx si
  1671.  
  1672. Procedure ComRead,NEAR
  1673.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1674.  
  1675.         ChkComInfoPtr
  1676.         ChkRPPtr
  1677.         ChkRPType  CMDINPUT
  1678.  
  1679. ifdef PERFVIEW
  1680.         pvw_Read START                  ;@PVW start timer
  1681. endif
  1682.  
  1683.         cli
  1684.  
  1685.         cmp     [si].ci_r_rp._hi,0
  1686.         jne     crr30           ; current request active, queue this one
  1687.  
  1688. ;       test    [si].ci_vdm_flag,VDM_Flag_InUse  ;CP20D1390 -- Fix CP20PB726384
  1689. ;       jz      crr_normal_req                   ; If the port is opened by special
  1690. ;       cmp     [si].ci_nvdmopens,0              ; VDM access, Read is not allowed.
  1691. ;       ljg     CmxInUse                         ;+yn Device in Use
  1692.  
  1693. crr_normal_req:
  1694. ; If there are no outstanding read requests we attempt to satisfy the
  1695. ; one we just got.
  1696.  
  1697.         sti
  1698.  
  1699.         mov     cx,es:[di].IOcount      ; (cx) = requested bytes
  1700.         or      cx,cx
  1701. ifdef PERFVIEW
  1702.         ljz     crrx                    ; request is for 0 bytes, done;@PVW
  1703. else
  1704.         ljz     CmxDone
  1705. endif
  1706.  
  1707.         mov     [si].ci_r_to_move,cx    ; initialize number of bytes to move
  1708.  
  1709.         ; set up GDT selector which we allocated at init time
  1710.         ;; PhysToGDTSel (ComInfo[si].GDTSelRead, physical @, length)
  1711.         ;; move ComInfo[si].GDTSelRead to Physical @. _hi
  1712.         ;; move 0 to Physical @. _lo
  1713.         push    si
  1714.         mov     si,[si].ci_GDTSelRead
  1715.         ; es:di -> request packet
  1716.         call    SetUpGDT
  1717.         pop     si
  1718.  
  1719.         cmp     [si].ci_qin.ioq_count,0
  1720.         je      crr00                   ; no data in queue
  1721.  
  1722.         call    ReadQueue               ; returns (cx) = bytes not dequeued
  1723.                                         ; updates ci_r_to_move
  1724.  
  1725. ; The current request may be satisfied if any of the following are true
  1726. ;       - all the data requested was moved (ci_r_to_move == cx == 0)
  1727. ;       - read mode is no wait
  1728. ;       - read mode is wait for something and something was moved
  1729. ;               (ci_r_to_move != IOcount)
  1730.  
  1731. ; If the request cannot be completed now, it is either normal timeout
  1732. ; mode or 'wait for something' mode and nothing received yet.
  1733. ; If it is normal timeout mode, the request will be run when there is
  1734. ; enough data in the RXQ to satisfy the request (RxInt) or when the
  1735. ; request times out (ReadTick).
  1736. ; If it is 'wait for something' mode, the request will be run when there
  1737. ; is ANY data in the RXQ (RxInt) or when the request times out (ReadTick).
  1738.  
  1739.         jcxz    crr10                   ; all the data was moved (done)
  1740.  
  1741. crr00:  mov     al,[si].ci_dcb_flags3
  1742.         and     al,F3_READ_TO_MASK      ; al = read timeout mode
  1743.         cmp     al,F3_READ_TO_NW
  1744.         je      crr10                   ; read mode is no wait (done)
  1745.  
  1746.         cmp     al,F3_READ_TO_NORM
  1747.         je      crr20                   ; read mode normal (block)
  1748.  
  1749.         cmp     cx,es:[di].IOcount
  1750.         je      crr20                   ; nothing moved and wait for something
  1751.  
  1752. crr10:  sub     es:[di].IOcount,cx      ; update number of bytes read
  1753. ifdef PERFVIEW
  1754.         jmp     crrx                    ; request is done   ;@PVW
  1755. else
  1756.         jmp     CmxDone
  1757. endif
  1758.  
  1759. ; If we get here we couldn't satisfy the request. This means
  1760. ; that we couldn't completely satisfy a normal request or there
  1761. ; was nothing to move for a wait for something request.
  1762.  
  1763. crr20:  cli
  1764.  
  1765.         mov     [si].ci_r_rp._hi,es     ; save request packet pointer
  1766.         mov     [si].ci_r_rp._lo,di
  1767.  
  1768.         mov     cx,[si].ci_r_to_start   ; initialize request time out value
  1769.         mov     [si].ci_r_to,cx
  1770.  
  1771.         jmp       SHORT crr40             ; go block
  1772.  
  1773.  
  1774. crr30:
  1775. ; We get here when there is already a current request, so this request
  1776. ; must be added to the read request packet list and processed later.
  1777.  
  1778.         SaveReg         <si>
  1779.         lea     si,[si].ci_r_rpl        ; (ds:si) -> read request packet list
  1780.         call    LinkRP                  ; add RP to list of reads
  1781.                                         ; outstanding requests
  1782.         RestoreReg      <si>            ; (ds:si) -> ComInfo
  1783.  
  1784.  
  1785. crr40:
  1786. ; Block until the request:
  1787. ;    completes  - normal wait mode - ProcRun'ed - carry clear
  1788. ;                 enough data in qin to finish request
  1789. ;
  1790. ;    completes  - no wait mode - ProcRun'ed - carry clear
  1791. ;                 may be some data in qin (could be 0)
  1792. ;                 may be enough data in qin to finish request (could be 0)
  1793. ;
  1794. ;    completes  - wait for something - ProcRun'ed - carry clear
  1795. ;                 some data in qin (could be 1)
  1796. ;                 may be enough data in qin to finish request (could be 1)
  1797. ;
  1798. ;    times out  - ProcRun'ed - carry clear
  1799. ;                 may not be enough data in qin to finish request
  1800. ;
  1801. ;    is flushed - ProcRun'ed - carry clear
  1802. ;                 request packet shows zero bytes requested
  1803. ;
  1804. ;    block is interrupted (usually for a signal to the thread).
  1805. ;                 may be enough data in qin to finish request (could be 0)
  1806.  
  1807. ifdef PERFVIEW
  1808.         pvw_Read STOP                   ;@PVW Stop perfview timer
  1809. endif
  1810.  
  1811.         mov     cx,-1                   ; (dx:cx) = infinite time out
  1812.         mov     dx,cx
  1813.         call    ProcBlock
  1814.  
  1815.         ChkRPType       CMDINPUT
  1816.  
  1817. ifdef PERFVIEW
  1818.         pushf                           ;@PVW save flags
  1819.         pvw_Read START                  ;@PVW start timer again
  1820.         popf                            ;@PVW restore flags
  1821. endif
  1822.         cli
  1823.  
  1824.         jc      crr50                   ; interrupted ProcBlock
  1825.  
  1826.         test    es:[di].PktStatus,STDON
  1827.         jz      crr40                   ; spurious ProcRun go ProcBlock again
  1828.  
  1829. ; We were run, lets finish the request.
  1830.  
  1831.         jmp     SHORT crr60
  1832.  
  1833. ; Interrupted ProcBlock.
  1834.  
  1835. crr50:  cmp     di,[si].ci_r_rp._lo
  1836.         jne     crr80                   ; not the current request
  1837.         mov     ax,es
  1838.         cmp     ax,[si].ci_r_rp._hi
  1839.         jne     crr80                   ; not the current request
  1840.  
  1841. ; As the current request we were either run or interrupted.
  1842. ; Either way, we will finish the request know.
  1843.  
  1844. crr60:  mov     cx,es:[di].IOcount
  1845.         jcxz    crr70                   ; request is satisfied (zero length)
  1846.                                         ; could have been forced to zero
  1847.                                         ; because it was flushed
  1848.  
  1849.         mov     cx,[si].ci_r_to_move    ; (cx) = number of bytes to transfer
  1850.         jcxz    crr70                   ; already done
  1851.  
  1852.         cmp     [si].ci_qin.ioq_count,0
  1853.         je      crr70                   ; there is nothing to transfer
  1854.  
  1855.         sti
  1856.         call    ReadQueue               ; returns (cx) = bytes not dequeued
  1857.                                         ; updates ci_r_to_move
  1858.         cli
  1859.  
  1860. crr70:  sub     es:[di].IOcount,cx      ; update number of bytes transfered
  1861.         mov     [si].ci_r_rp._hi,0      ; no longer current
  1862.         call    StartNextRRP            ; start the next read request
  1863. ifdef PERFVIEW
  1864.         jmp     SHORT crrx              ; this request is done
  1865. else
  1866.         jmp     CmxDone
  1867. endif
  1868.  
  1869. ; The ProcBlock was interrupted but we are not the current request.
  1870. ; So we have to pull ourselves out of the read request list.
  1871.  
  1872. crr80:  cmp     [si].ci_r_rpl._hi,0     ; 103070-1 See if RPL exists
  1873.         je      crr81                   ; 103070-1 No, must be ci_r_rp._hi=0
  1874.         lea     si,[si].ci_r_rpl        ; (ds:si) -> read request packet list
  1875.         call    UnLinkRP                ; unlink the specific interrupted RP
  1876.  
  1877. crr81:                                  ; 103070-1 Clear IO count and return
  1878.         mov     es:[di].IOcount,0       ; interrupted, therefore 0 bytes moved
  1879.  
  1880. ifdef PERFVIEW
  1881. crrx:
  1882.         pvw_Read STOP,DOCOUNTERS        ;@PVW stop timer, inc num_reads,
  1883.                                         ;@PVW update bytes read
  1884.         jmp     CmxDone
  1885. else
  1886.         jmp     CmxDone                 ; 103070-2 no Perfview enabled
  1887. endif
  1888.  
  1889. EndProc ComRead
  1890.  
  1891.  
  1892. ;**     ComWrite - write request handler
  1893. ;
  1894. ;       ComWrite handles write requests for the driver. When we get a write
  1895. ;       request we check to see if there are any others active. If there
  1896. ;       aren't we transfer as much data into the queue as we can. Either
  1897. ;       way we then block the process until we send the data out the hardware.
  1898. ;       When we wake up from the block we adjust the number of bytes moved
  1899. ;       and return. If we are interrupted and are not the current request
  1900. ;       we pull ourselves out of the queue and set the number of bytes
  1901. ;       transferred to zero.
  1902. ;
  1903. ;       ENTRY   (ds:si) -> ComInfo
  1904. ;               (es:di) -> request packet
  1905. ;
  1906. ;       EXIT
  1907. ;
  1908. ;
  1909. ;       USES    ax bx cx
  1910.  
  1911. Procedure ComWrite,NEAR
  1912.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  1913.  
  1914.         ChkComInfoPtr
  1915.         ChkRPPtr
  1916.  
  1917. IFDEF RPTSTRICT
  1918.         mov     es:[di].PktCmd,CMDOUTPUT        ; write with verity => write
  1919. ENDIF
  1920.  
  1921. ifdef PERFVIEW
  1922.         pvw_Write START                  ;@PVW start timer
  1923. endif
  1924.  
  1925.         cli
  1926.  
  1927. ;       test    [si].ci_vdm_flag,VDM_Flag_InUse ;CP20D1390  -- Fix CP20PB726384
  1928. ;       jz      cwr_normal_req                  ; If the port is opened with special
  1929. ;       cmp     [si].ci_nvdmopens,0             ; vdm access, Write is not allowed
  1930. ;       ljg     CmxInUse                        ;+yn error General Failure
  1931.  
  1932. cwr_normal_req:
  1933.         cmp     [si].ci_w_rp._hi,0
  1934.         jne     cwr1                    ; no current request
  1935.  
  1936. ; If there are no outstanding write requests we move as much data
  1937. ; as we can into the output queue.
  1938.  
  1939.         sti
  1940.  
  1941.         mov     cx,es:[di].IOcount
  1942.         or      cx,cx
  1943. ifdef PERFVIEW
  1944.         ljz     cwrx                    ; request is for 0 bytes, done;@PVW
  1945. else
  1946.         ljz     CmxDone
  1947. endif
  1948.  
  1949.         ; set up GDT selector which we allocated at init time
  1950.         ;; PhysToGDTSel (ComInfo[si].GDTSelWrite, physical @, length)
  1951.         ;; move ComInfo[si].GDTSelWrite to Physical @. _hi
  1952.         ;; move 0 to Physical @. _lo
  1953.         push    si
  1954.         mov     si,[si].ci_GDTSelWrite
  1955.         ; es:di -> request packet
  1956.         call    SetUpGDT
  1957.         pop     si
  1958.  
  1959.         call    WriteQueue              ; returns (cx) = bytes not enqueued
  1960.                                         ; updates ci_w_to_move
  1961.  
  1962.         cli
  1963.  
  1964.         mov     [si].ci_w_rp._hi,es     ; save request packet pointer
  1965.         mov     [si].ci_w_rp._lo,di
  1966.  
  1967.         mov     cx,[si].ci_w_to_start   ; initialize request time out value
  1968.         mov     [si].ci_w_to,cx
  1969.  
  1970.         SaveReg         <di>            ; save request pkt ptr
  1971.         call    CheckTX                 ; adjust TX empty interrupt
  1972.         RestoreReg      <di>            ; restore request pkt ptr
  1973.         jmp     SHORT cwr2
  1974.  
  1975. ; Whether or not we are the current request we have to block until
  1976. ; the data moves out of the hardware.
  1977.  
  1978. cwr1:   SaveReg         <si>
  1979.         lea     si,[si].ci_w_rpl        ; (ds:si) -> write request packet list
  1980.         call    LinkRP                  ; add RP to list of writes
  1981.         RestoreReg      <si>            ; (ds:si) -> ComInfo
  1982.  
  1983. ; Now that we have linked the request we want to block it
  1984. ; until we are able to satisfy it.
  1985.  
  1986. cwr2:
  1987. ifdef PERFVIEW
  1988.         pvw_Write STOP                  ;@PVW stop timer
  1989. endif
  1990.  
  1991.         mov     cx,-1                   ; (dx:cx) = no ProcBlock time out
  1992.         mov     dx,cx
  1993.         call    ProcBlock
  1994.  
  1995.         ChkRPType       CMDOUTPUT
  1996.  
  1997. ifdef PERFVIEW
  1998.         pushf                           ;@PVW save flags
  1999.         pvw_Write START                 ;@PVW start timer again
  2000.         popf                            ;@PVW restore flags
  2001. endif
  2002.  
  2003.         cli
  2004.  
  2005.         jc      cwr3                    ; interrupted ProcBlock
  2006.  
  2007.         test    es:[di].PktStatus,STDON
  2008.         jz      cwr2                    ; spurious ProcRun go ProcBlock again
  2009. ;;MF    jmp     cwrx                    ; valid ProcRun, request done  ;@PVW
  2010.         jmp     cwr3_5          ;;MF    ; valid ProcRun, run next request
  2011.  
  2012.  
  2013. ; Interrupted ProcBlock.
  2014.  
  2015. cwr3:   test    es:[di].PktStatus,STDON
  2016. ;;MF    jnz     cwrx                    ; request already complete
  2017.         jnz     cwr3_5                  ; request complete, run next request
  2018.  
  2019.         cmp     di,[si].ci_w_rp._lo
  2020.         jne     cwr4                    ; not the current request
  2021.         mov     ax,es
  2022.         cmp     ax,[si].ci_w_rp._hi
  2023.         jne     cwr4                    ; not the current request
  2024.  
  2025. ; Current request was interrupted.
  2026.  
  2027.         mov     [si].ci_w_rp._hi,0      ; no longer a current request
  2028.         mov     ax,[si].ci_w_to_move
  2029.         add     ax,[si].ci_qout.ioq_count
  2030.         sub     es:[di].IOcount,ax      ; number of bytes sent to HW
  2031.  
  2032.         FlushQueue      ci_qout
  2033.  
  2034.         sti
  2035.  
  2036. cwr3_5:                 ;;MF
  2037.         call    StartNextWRP            ; start the next write request
  2038.  
  2039. ifdef PERFVIEW
  2040.         jmp     SHORT cwrx              ; this request is done
  2041. else
  2042.         jmp     CmxDone
  2043. endif
  2044.  
  2045.  
  2046. ; The ProcBlock was interrupted but we were not the current request.
  2047.  
  2048. cwr4:   cmp     [si].ci_w_rpl._hi,0     ; 103070-1 Check to see that RPL exists
  2049.         je      cwr4_5                  ; 103070-1 No, must be ci_w_rp._hi=0
  2050.         lea     si,[si].ci_w_rpl        ; (ds:si) -> write request packet list
  2051.         call    UnLinkRP                ; unlink the specific interrupted RP
  2052. cwr4_5:                                 ; 103070-1 Clear IO Count and return
  2053.         mov     es:[di].IOcount,0       ; interrupted therefore 0 bytes written
  2054.  
  2055. ifdef PERFVIEW
  2056. cwrx:
  2057.         pvw_Write STOP,DOCOUNTERS       ;@PVW stop timer, inc num_writes,
  2058.                                         ;@PVW update bytes written
  2059.         jmp     CmxDone
  2060. else
  2061.         jmp     CmxDone                 ; 103070-2 no PERVIEW enabled
  2062. endif
  2063.  
  2064. EndProc ComWrite
  2065.  
  2066.  
  2067. ;**     ComNDRead - Non-destructive read request handler
  2068. ;
  2069. ;       ComNDRead will return the first character in the input queue
  2070. ;       if there is one. Otherwise it returns an error. The read is
  2071. ;       non-destructive in that the character is not removed from the
  2072. ;       queue.
  2073. ;
  2074. ;       ENTRY   (ds:si) -> ComInfo
  2075. ;               (es:di) -> request packet
  2076. ;
  2077. ;       EXIT
  2078. ;
  2079. ;       USES    bx
  2080.  
  2081. Procedure ComNDRead,NEAR
  2082.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  2083.  
  2084.         ChkComInfoPtr
  2085.         ChkRPPtr
  2086.  
  2087. ;       test    [si].ci_vdm_flag,VDM_Flag_InUse  ;CP20D1390  -- Fix CP20PB726384
  2088. ;       jz      cndr_normal_req                  ; If the port is opened with special
  2089. ;       cmp     [si].ci_nvdmopens,0              ; vdm access, none distructive Read is not allowed.
  2090. ;       ljg     CmxInUse                         ;+yn error General Failure
  2091.  
  2092. cndr_normal_req:
  2093.         cmp     [si].ci_qin.ioq_count,0
  2094.         lje     CmxBusy                 ; no data in queue, device busy
  2095.  
  2096.         mov     bx,[si].ci_qin.ioq_out  ; Get the first char
  2097.         mov     bl,[bx]
  2098.         mov     es:[di].NDRbyte,bl
  2099.         jmp     CmxDone                 ; Return w/ "Done, no error."
  2100.  
  2101. EndProc ComNDRead
  2102.  
  2103.  
  2104. ;**     ComRStat - input status request handler
  2105. ;
  2106. ;       We return busy if the input queue is empty or
  2107. ;       if there is an outstanding read request.
  2108. ;       Otherwise we return done.
  2109. ;
  2110. ;       ENTRY   (ds:si) -> ComInfo
  2111. ;
  2112. ;       EXIT
  2113. ;
  2114. ;       USES    NONE
  2115.  
  2116. Procedure ComRStat,NEAR
  2117.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  2118.  
  2119.         cmp     [si].ci_qin.ioq_count,0
  2120.         lje     CmxBusy                 ; queue is empty
  2121.  
  2122.         cmp     [si].ci_r_rp._hi,0
  2123.         ljne    CmxBusy                 ; request outstanding
  2124.  
  2125.         jmp     CmxDone                 ; we're not busy
  2126.  
  2127. EndProc ComRStat
  2128.  
  2129.  
  2130. ;**     ComWStat - output status request handler
  2131. ;
  2132. ;       We return busy if there is an outstanding write request
  2133. ;       or we are unable to transmit.
  2134. ;       Otherwise we return done.
  2135. ;
  2136. ;       ENTRY   (ds:si) -> ComInfo
  2137. ;
  2138. ;       EXIT
  2139. ;
  2140. ;       USES    al
  2141.  
  2142. Procedure ComWStat,NEAR
  2143.  
  2144.         ChkComInfoPtr
  2145.  
  2146.         cmp     [si].ci_w_rp._hi,0
  2147.         ljne    CmxBusy                 ; request outstanding
  2148.  
  2149.  
  2150. ; If a BREAK is set or an XOFF was sent or recieved, we can not transmit.
  2151.  
  2152.         test    [si].ci_hsflag,HS_BREAK_SET OR HS_XOFF_RECEIVED OR HS_XOFF_SENT
  2153.         ljnz    CmxBusy
  2154.  
  2155.         mov     al,[si].ci_msrshadow    ; (al) = msr_shadow
  2156.         and     al,[si].ci_outhhslines  ; mask bits of interest
  2157.         cmp     al,[si].ci_outhhslines
  2158.         ljne    CmxBusy                 ; modem lines down
  2159.  
  2160.         jmp     CmxDone                 ; we're not busy
  2161.  
  2162.  
  2163. EndProc ComWStat
  2164.  
  2165.  
  2166.  
  2167.  
  2168. ;**     ComRFlush - read flush request handler
  2169. ;**     ComWFlush - write flush request handler
  2170. ;
  2171. ;       ENTRY   (ds:si) -> ComInfo
  2172. ;
  2173. ;       EXIT
  2174. ;
  2175. ;       USES
  2176.  
  2177. Procedure ComRFlush,NEAR
  2178. ;                                                 -- Fix CP20PB726384
  2179. ;       test    [si].ci_vdm_flag,VDM_Flag_InUse ;CP20D1390 If the port is opened
  2180. ;       jz      crf_normal_req                  ; with special vdm access,
  2181. ;       cmp     [si].ci_nvdmopens,0             ; Read Buffer Flush is not allowed.
  2182. ;       ljg     CmxInUse                        ;+yn error General Failure
  2183.  
  2184. crf_normal_req:
  2185.         call    ComRFlushSub
  2186.  
  2187. cr10:   call    EnableRemoteTX          ; send an XON if XOFF previously sent
  2188.         jmp     CmxDone
  2189.  
  2190.  
  2191.  
  2192. Entry ComWFlush,,,nocheck
  2193.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  2194.  
  2195.         call    ComWFlushSub
  2196.         jmp     CmxDone
  2197.  
  2198. EndProc ComRFlush
  2199.  
  2200. Procedure ComRFlushSub,NEAR
  2201.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  2202.  
  2203.         ChkComInfoPtr
  2204. ;                                                 -- Fix CP20PB726384
  2205. ;       test    [si].ci_vdm_flag,VDM_Flag_InUse ;CP20D1390 If the port is opened
  2206. ;       jz      cwf_normal_req                  ; with special vdm access,
  2207. ;       cmp     [si].ci_nvdmopens,0             ; Write Buffer Flush is not allowed.
  2208. ;       ljg     CmxInUse                        ;+yn error General Failure
  2209.  
  2210. cwf_normal_req:
  2211.  
  2212.         cli
  2213.  
  2214.         or      [si].ci_Flagx1,FX1_FLUSH_RX_IP ;;MF
  2215.  
  2216.         FlushQueue      ci_qin
  2217.  
  2218.         cmp     [si].ci_r_rp._hi,0
  2219.         je      crf1                    ; no current request
  2220.  
  2221.         les     di,[si].ci_r_rp         ; (es:di) -> current read request
  2222.         ChkRPPtr
  2223.         ChkRPType       CMDINPUT
  2224.         mov     es:[di].IOcount,0       ; update number of bytes transfered
  2225.  
  2226.         mov     es:[di].PktStatus,STDON ;mw mark request done
  2227.         mov     [si].ci_r_rp._hi,0      ; no more read requests
  2228.  
  2229.         sti
  2230.  
  2231.         call    ProcRun
  2232.  
  2233. crf1:   push    si
  2234.         lea     si,[si].ci_r_rpl        ; (ds:si) -> read request packet list
  2235.         jmp     SHORT cmf1
  2236.  
  2237.  
  2238. Entry ComWFlushSub,,,nocheck
  2239.  
  2240.         cli
  2241.  
  2242.         or      [si].ci_Flagx1,FX1_FLUSH_TX_IP ;;MF
  2243.  
  2244.         mov     dx,[si].ci_port
  2245.         add     dx,R_INTEN              ; (dx) -> interrupt enable reg
  2246.         in      al,dx
  2247.         and     al,NOT IE_TX            ; disable TX interrupts first
  2248.         out     dx,al
  2249.  
  2250.         ChkComInfoPtr
  2251.  
  2252.         mov     cx,[si].ci_qout.ioq_count
  2253.  
  2254.         FlushQueue      ci_qout
  2255.  
  2256.         cmp     [si].ci_w_rp._hi,0
  2257.         je      cwf1                    ; no current requests
  2258.  
  2259.         les     di,[si].ci_w_rp         ; (es:di) -> current write request
  2260.         ChkRPPtr
  2261.         ChkRPType       CMDOUTPUT
  2262.         add     cx,[si].ci_w_to_move
  2263.         sub     es:[di].IOcount,cx      ; update number of bytes transfered
  2264.  
  2265.         mov     es:[di].PktStatus,STDON ;mw mark request done
  2266.  
  2267.         mov     [si].ci_w_rp._hi,0      ; no more write requests
  2268.         mov     [si].ci_w_to_move,0   ;;MF reset the # of bytes left to move
  2269.  
  2270.         sti
  2271.  
  2272.         call    ProcRun
  2273.  
  2274. cwf1:   push    si
  2275.         lea     si,[si].ci_w_rpl        ; (ds:si) -> write request packet list
  2276.  
  2277. ; We enter here, after the current requests are flushed, in
  2278. ; order to flush all outstanding requests.
  2279.  
  2280. cmf1:   sti
  2281.  
  2282. ;BUGBUG must remove all requests from the list BEFORE enabling interrupts.
  2283. ;unless ci_r_rp is always checked before trying to use ci_r_rpl
  2284.  
  2285.         ChkRPLPtr
  2286.         call     UnLinkHeadRP            ; (es:di) -> runnable request packet
  2287.         jc      cmfx                    ; no more to run
  2288.  
  2289.         ChkRPPtr
  2290.         mov     es:[di].IOcount,0       ; update number of bytes transfered
  2291.         call    ProcRun
  2292.         jmp     SHORT cmf1              ; try to run another
  2293.  
  2294. cmfx:   pop     si
  2295.  
  2296.         and     [si].ci_Flagx1, not (FX1_FLUSH_TX_IP+FX1_FLUSH_RX_IP) ;;MF
  2297.  
  2298.         ret
  2299.  
  2300. EndProc ComRFlushSub
  2301.  
  2302.  
  2303. ;**     ComShutdown - Shutdown Handler
  2304. ;
  2305. ;       ComShutdown turns off the FIFO enabling bit of the given COM port.
  2306. ;       ComShutdown also turns off the loop back bit of MCR.
  2307. ;
  2308. ;
  2309. ;       ENTRY   (ds:si) -> ComInfo
  2310. ;               (es:di) -> request packet
  2311. ;
  2312. ;       EXIT
  2313. ;
  2314. ;       USES    bx
  2315.  
  2316. Procedure ComShutdown,NEAR
  2317.         ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  2318.  
  2319.         ChkComInfoPtr
  2320.         ChkRPPtr
  2321.         cmp     si,0
  2322.         je      End_Shutdown
  2323.  
  2324.         test    [si].ci_dcb_flags3,F3_FIFO_ON
  2325.         jz      End_Shutdown
  2326.  
  2327.         mov     dx,[si].ci_port
  2328.         add     dx,R_FIFOC
  2329. ; 81245        mov     al,FF_ENABLE
  2330. ; 81245        mout    dx,al
  2331.         min     al,dx
  2332.         and     al,NOT FF_RX_MASK
  2333.         mout    dx,al
  2334.         mov     al,NOT FF_ENABLE
  2335.         mout    dx,al
  2336.  
  2337.         and     [si].ci_dcb_flags3,NOT F3_FIFO_ON
  2338.  
  2339.         mov     dx,[si].ci_port
  2340.         add     dx,R_MODMC
  2341.         min     al,dx
  2342.         and     al,NOT MC_LOOP
  2343.         mout    dx,al
  2344.  
  2345. End_Shutdown:
  2346.         ret
  2347. EndProc ComShutdown
  2348.  
  2349.  
  2350. ;------- !WARNING! Keep InitQueues at the bottom or risk assmembly errors!
  2351. ;**     InitQueues - initialize the qin and qout IO_Queues
  2352. ;
  2353. ;       InitQueues merely sets up the input and output queues
  2354. ;       to there initial state. That is,
  2355. ;
  2356. ;               base = in = out = start of queue
  2357. ;               end = start of queue + size of queue
  2358. ;               count = 0
  2359. ;
  2360. ;       ENTRY   (ds:si) -> ComInfo structure
  2361. ;
  2362. ;       EXIT    ioq structures initialized
  2363. ;
  2364. ;       USES    ax
  2365. Procedure InitQueues,HYBRID
  2366.  
  2367.         ASSUME  cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  2368.  
  2369.         ChkComInfoPtr
  2370.  
  2371.         lea     ax,WORD PTR [si].ci_qin_q       ; (ax) -> input queue
  2372.  
  2373. ; Initialize input queue.
  2374.  
  2375.         mov     [si].ci_qin.ioq_base,ax
  2376.         mov     [si].ci_qin.ioq_in,ax
  2377.         mov     [si].ci_qin.ioq_out,ax
  2378.         add     ax,QI_SIZE
  2379.         mov     [si].ci_qin.ioq_end,ax
  2380.         mov     [si].ci_qin.ioq_count,0
  2381.  
  2382.         lea     ax,WORD PTR [si].ci_qout_q      ; (ax) -> output queue
  2383.  
  2384. ; Initialize output queue.
  2385.  
  2386.         mov     [si].ci_qout.ioq_base,ax
  2387.         mov     [si].ci_qout.ioq_in,ax
  2388.         mov     [si].ci_qout.ioq_out,ax
  2389.         add     ax,QO_SIZE
  2390.         mov     [si].ci_qout.ioq_end,ax
  2391.         mov     [si].ci_qout.ioq_count,0
  2392.  
  2393.         ret
  2394.  
  2395. EndProc InitQueues
  2396.  
  2397. ;**     InitSharedIRQ - initialize the ShrdIRQData structure
  2398. ;
  2399. ;       InitSharedIRQ - sets up the ShrdIRQData structure for
  2400. ;       a shared interrupt line.  This data structure is used
  2401. ;       as the "head" pointer for the linked list of ComInfo structures
  2402. ;       that share an IRQ line.  There is a two-way link used
  2403. ;       to connect the data structures (NOTE: this picture is of the
  2404. ;       FIRST ComInfo structure in the chain - the variable si_firstCOM
  2405. ;       is the "head" pointer to the start of the chain.)
  2406. ;
  2407. ;               ShrdIRQData             ComInfo
  2408. ;                structure              structure
  2409. ;
  2410. ;                                       +----------------+
  2411. ;                                    +->| ci_dcb_writeto |
  2412. ;                                    |  +----------------+
  2413. ;               +-------------+      |         .
  2414. ;               | si_irq      | <--+ |         .
  2415. ;               +-------------+    | |  +----------------+
  2416. ;               | si_opens    |    +----| ci_int_data    |
  2417. ;               +-------------+      |  +----------------+
  2418. ;               | si_firstCOM |------+  | ci_nextCOM     |--->next ComInfo
  2419. ;               +-------------+         +----------------+    in the chain
  2420. ;
  2421. ;       This way, when the COM port is opened, the ci_int_data field in
  2422. ;       ComInfo can be used to determine
  2423. ;       which of the ShrdIRQData structures the COM port is associated with.
  2424.  
  2425. ;       The chain can then be walked to determine where the COM port
  2426. ;       should be placed (based on highest baud rate first).
  2427. ;
  2428. ;
  2429. ;      The responsiblity of this routine is to initialize ci_int_data
  2430. ;      and, if necessary, si_irq.
  2431. ;
  2432. ;      ENTRY   (ds:si) -> ComInfo structure
  2433. ;
  2434. ;      EXIT    ComInfo and ShrdIRQData structures initialized
  2435. ;
  2436. ;      USES    flags
  2437.  
  2438. Procedure InitSharedIRQ,HYBRID
  2439.       ASSUME  cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
  2440.  
  2441.       pusha
  2442.       push    ds
  2443.       push    es
  2444.  
  2445.         setDS   DSEG                    ; DSEG selector
  2446.  
  2447.         xor     bx,bx                   ; init. index
  2448.         mov     al, [si].ci_irq         ; IRQ number to search for
  2449.         mov     cx, MAXCOMPORTS         ; max. COM ports = max. IRQ lines
  2450.  
  2451. sinit5:
  2452.         cmp     ShrdIRQ1[bx].si_irq, al ; IRQ line matches?
  2453.         je      sinit40                 ; Y: update data structures
  2454.         add     bx, size SharedIntData  ; N: increment index to next IRQ struc.
  2455.         loop    sinit5                  ; and try again
  2456.  
  2457.         ; No ShrdIRQ structure has been setup yet for this IRQ line,
  2458.         ; so find the first empty ShrdIRQ structure and use it.
  2459.         xor     bx, bx                  ; re-init.
  2460.         mov     cx, MAXCOMPORTS         ; re-init.
  2461.  
  2462. sinit10:
  2463.         cmp     ShrdIRQ1[bx].si_irq, 0  ; this entry is empty?
  2464.         je      sinit20                 ; Y: initialize this entry
  2465.         add     bx, size SharedIntData  ; N: increment index to next IRQ struc.
  2466.         loop    sinit10                 ; and try again
  2467.  
  2468.         mov     byte ptr [si].int_sharing, 0 ; don't support int. sharing
  2469.         jmp     short sinit50
  2470.  
  2471. sinit20:
  2472.         mov     ShrdIRQ1[bx].si_irq, al ; store the IRQ line
  2473.         mov     ShrdIRQ1[bx].si_count, 0 ; initialize the total count value
  2474.  
  2475. sinit40:
  2476.        inc     ShrdIRQ1[bx].si_count   ; total number of COMs on this IRQ line
  2477.        mov     [si].ci_int_data, bx    ; save offset for use at open time
  2478.  
  2479. sinit50:
  2480.        pop     es
  2481.        pop     ds
  2482.        popa
  2483.        ret
  2484.  
  2485. EndProc InitSharedIRQ
  2486.  
  2487.  
  2488. ;**     OptimizeSharedIRQs - check the ShrdIRQData structures for
  2489. ;                            unnecessary entries.
  2490. ;       OptimizeSharedIRQs - examines the ShrdIRQData structures that are in
  2491. ;       use.  If the total COM port count for an IRQ line is equal to 1,
  2492. ;       then there is no reason to use the "shared" entry point in to
  2493. ;       the interrupt service routine.  The "shared" entry points have
  2494. ;       a small amount of extra overhead for handling multiple COM ports
  2495. ;       on the same IRQ line.  If, however, a COM port is not sharing
  2496. ;       its IRQ line with one or more other COM ports (instead, it is
  2497. ;       being shared with some other peripheral in the system), then
  2498. ;       there is no reason to use the "shared" entry point.  The regular
  2499. ;       entry point for the COM port can be called directly, which
  2500. ;       saves on that small amount of overhead.  When this routine finds a
  2501. ;       ShrdIRQData structure that has a value of 1, it sets the
  2502. ;       ci_mult_COMs_IRQ flag for that COM port to zero, so that at
  2503. ;       DosOpen time the regular interrupt entry point will be registered
  2504. ;       via DevHlp_SetIRQ.
  2505. ;
  2506. ;       ENTRY   none
  2507. ;
  2508. ;       EXIT    ComInfo structures updated if needed
  2509. ;
  2510. ;       USES    flags
  2511.  
  2512. Procedure OptimizeSharedIRQs,HYBRID
  2513.         ASSUME  cs:CSEG,ds:NOTHING,es:NOTHING,ss:NOTHING
  2514.  
  2515.         pusha
  2516.         push    ds
  2517.  
  2518.         setDS   DSEG                    ; DSEG selector
  2519.  
  2520.         xor     bx,bx                   ; init. index
  2521.         mov     cx, MAXCOMPORTS         ; examine all COM ports
  2522.  
  2523. optz5:
  2524.         cmp     word ptr Com1[bx], 0    ; Valid COM port?
  2525.         je      optz40                  ; N: try the next one
  2526.         mov     si, word ptr Com1[bx]   ; Y: load the offset
  2527.         cmp     [si].ci_mult_COMs_IRQ, INT_SHARING ; possibly sharing with
  2528.                                                    ;  another COM port?
  2529.         jne     optz40                  ; N: go to next COM port
  2530.         mov     di, [si].ci_int_data    ; Y: get offset of shared IRQ data
  2531.         cmp     ShrdIRQ1[di].si_count, 1 ; Only 1 COM port on this IRQ line?
  2532.  
  2533.         jne     optz40                  ; N: No changes needed, go to next COM
  2534.         mov     [si].ci_mult_COMs_IRQ, 0 ; Y: indicate only 1 COM on this IRQ
  2535.  
  2536. optz40:
  2537.         inc     bx
  2538.         inc     bx                      ; next ComInfo offset in the array
  2539.         loop    optz5                   ; and try again
  2540.  
  2541. optz50:
  2542.         pop     ds
  2543.         popa
  2544.         ret
  2545.  
  2546. EndProc OptimizeSharedIRQs
  2547.  
  2548.  
  2549. CSEG    ENDS
  2550.  
  2551.  
  2552. RSEG    SEGMENT
  2553.         ASSUME cs:RSEG
  2554.  
  2555. ;**     Com1Strat - strategy entry point for COM1
  2556. ;**     Com2Strat - strategy entry point for COM2
  2557. ;
  2558. ;       Com1Strat and Com2Strat are the entry points for the strategy
  2559. ;       routine for the asynch device driver. The strategy routine is
  2560. ;       called by the OS to handle device requests.
  2561. ;
  2562. ;       ENTRY   (es:bx) -> request packet
  2563. ;               (ds) HSEG segment for com01.sys
  2564. ;
  2565. ;       EXIT    none (doesn't come through here on exit)
  2566. ;
  2567. ;       USES    ax si
  2568.  
  2569. Procedure Com1Strat,FAR
  2570.         ASSUME cs:RSEG,ds:HSEG,es:NOTHING,ss:NOTHING
  2571.  
  2572. IFDEF COMDEBUG
  2573.         int 3
  2574. ENDIF
  2575.         setDS   DSEG
  2576.         mov     si,Com1                 ; (ds:si) -> COM1 info
  2577.         mov     ax,Com1Minor
  2578.         jmp     ComStrat
  2579.  
  2580. Entry Com2Strat,,,nocheck
  2581.         ASSUME cs:RSEG,ds:HSEG,es:NOTHING,ss:NOTHING
  2582.  
  2583. IFDEF COMDEBUG
  2584.         int 3
  2585. ENDIF
  2586.  
  2587.         setDS   DSEG
  2588.         mov     si,Com2                 ; (ds:si) -> COM2 info
  2589.         mov     ax,Com2Minor
  2590.         jmp     ComStrat
  2591.  
  2592. Entry Com3Strat,,,nocheck
  2593.  
  2594. IFDEF COMDEBUG
  2595.         int 3
  2596. ENDIF
  2597.  
  2598.         setDS   DSEG
  2599.         mov     si,Com3                 ; (ds:si) -> COM3 info
  2600.         mov     ax,Com3Minor
  2601.         jmp     ComStrat
  2602.  
  2603. Entry Com4Strat,,,nocheck
  2604.  
  2605. IFDEF COMDEBUG
  2606.         int 3
  2607. ENDIF
  2608.  
  2609.         setDS   DSEG
  2610.         mov     si,Com4                 ; (ds:si) -> COM4 info
  2611.         mov     ax,Com4Minor
  2612.         jmp     ComStrat
  2613.  
  2614. EndProc Com1Strat
  2615.  
  2616. ;********************************************************************
  2617. ;*
  2618. ;*  FUNCTION NAME :  HIDC_Entry
  2619. ;*
  2620. ;*  DESCRIPTION   :  Hardware DD IDC entry point.
  2621. ;*
  2622. ;*                   Route all IDC function requests.
  2623. ;*
  2624. ;*  ENTRY POINT   :  COM1_IDC_Entry        LINKAGE:  CALL FAR
  2625. ;*
  2626. ;*  INPUT         :  ES:BX = Segemrnt:Offset of IDC packet
  2627. ;*
  2628. ;*  RETURN-NORMAL :  Function performed, carry clear
  2629. ;*
  2630. ;*  RETURN-ERROR  :  Function rejected, carry set.
  2631. ;*
  2632. ;*  EFFECTS       :  Stack is clean on return.  AX, CX, DX, SI, and DI
  2633. ;*                   registers are changed.
  2634. ;*
  2635. ;*  INTERNAL REFERENCES:
  2636. ;*     ROUTINES:  Query_Config, Read_Enable, Read_Disable,
  2637. ;*                Enable_Device, Disable_Device
  2638. ;*
  2639. ;*  EXTERNAL REFERENCES:
  2640. ;*     ROUTINES:  NONE.
  2641. ;*     DevHlps:  None.
  2642. ;*
  2643. ;********************************************************************
  2644.  
  2645.  
  2646. Procedure COM1_IDC_Entry,FAR
  2647.         ASSUME cs:RSEG,ds:HSEG,es:NOTHING,ss:NOTHING
  2648.  
  2649.        jmp  IDC_Handler
  2650.  
  2651. Entry COM2_IDC_Entry,,,nocheck
  2652.  
  2653.        jmp  IDC_Handler
  2654.  
  2655. Entry COM3_IDC_Entry,,,nocheck
  2656.  
  2657.        jmp  IDC_Handler
  2658.  
  2659. Entry COM4_IDC_Entry,,,nocheck
  2660.  
  2661.        jmp  IDC_Handler
  2662.  
  2663. EndProc COM1_IDC_Entry
  2664.  
  2665. RSEG    ENDS
  2666.  
  2667.  
  2668.  
  2669.         END
  2670.