home *** CD-ROM | disk | FTP | other *** search
/ Software Collection (I) / TOOLS.iso / b04 / 22.img / COMBUFF / COMBUFF.AS_ / COMBUFF.AS
Encoding:
Text File  |  1992-01-04  |  33.7 KB  |  1,516 lines

  1. PAGE 58,132
  2. ;******************************************************************************
  3. TITLE combuff.asm -
  4. ;******************************************************************************
  5. ;
  6. ;   (C) Copyright MICROSOFT Corp.  All Rights Reserved, 1989, 1990
  7. ;
  8. ;   Title:    combuff.asm -
  9. ;
  10. ;   Version:    1.00
  11. ;
  12. ;   Date:    30-Jan-1990
  13. ;
  14. ;   Author:    RAL
  15. ;
  16. ;------------------------------------------------------------------------------
  17. ;
  18. ;   Change log:
  19. ;
  20. ;      DATE    REV            DESCRIPTION
  21. ;   ----------- --- -----------------------------------------------------------
  22. ;   30-Jan-1990 RAL Original
  23. ;   31-Jan-1990 RAL Added support for XON/XOFF protocol
  24. ;   13-Feb-1990 RAP Check for version 3.00 of VCD in Sys_Critical_Init
  25. ;
  26. ;==============================================================================
  27. ;
  28. ;   DESCRIPTION:
  29. ;    This device is responsible for buffering COM I/O.  It is closely
  30. ;    tied to the Virtual COM Device.  See the VCD documentation for
  31. ;    details.
  32. ;
  33. ;******************************************************************************
  34.  
  35.     .386p
  36.  
  37.  
  38. ;******************************************************************************
  39. ;                  I N C L U D E S
  40. ;******************************************************************************
  41.  
  42.     .XLIST
  43.     INCLUDE VMM.Inc
  44.     INCLUDE Debug.Inc
  45.     INCLUDE VPICD.inc
  46.     INCLUDE VCD.Inc
  47.     .LIST
  48.  
  49.  
  50. ;******************************************************************************
  51. ;         V I R T U A L     D E V I C E   D E C L A R A T I O N
  52. ;******************************************************************************
  53.  
  54. Declare_Virtual_Device COMBUFF, 1, 0, COMBuff_Control
  55.  
  56.  
  57. ;******************************************************************************
  58. ;                 E Q U A T E S
  59. ;******************************************************************************
  60.  
  61. CB_No_Proto    EQU    0
  62. CB_XOFF_Proto    EQU    1
  63.  
  64. XOFF_Char    EQU    13h
  65.  
  66. Default_Buf_Size EQU    128
  67.  
  68.  
  69. ;******************************************************************************
  70. ;                 S T R U C T U R E S
  71. ;******************************************************************************
  72.  
  73. COMBuff_Extended_COM_Struc STRUC
  74. Filler        db    SIZE VCD_COM_Struc dup (?)
  75.  
  76. VCD_Vier    db    ?    ; Virtual Interrupt Enable register
  77. VCD_Vlcr    db    ?    ; Virtual Line Control register
  78. VCD_Vmcr    db    ?    ; Virtual Modem Control register
  79. VCD_Viir    db    ?    ; Virtual Interrupt Identity register
  80. VCD_Vlsr    db    ?    ; Virtual Line status register
  81. VCD_Vrxb    db    ?    ; Virtual Rx Buffer
  82. VCD_Vmsr    db    0    ; Virtual Modem status register
  83. VCD_Virr    db    0    ; Virtual Interrupt Request register
  84.  
  85. VCD_XOFF_Flag    db    0
  86. VCD_Protocol    db    ?
  87.  
  88. IFDEF DEBUG
  89. VCD_Max_Queued    dw    ?    ; max # of chars ever queued
  90. ENDIF
  91.  
  92. VCD_RxQin    dw    0    ; First In...
  93. VCD_RxQout    dw    0    ; ...First Out
  94. VCD_RxQcount    dw    0    ; How many in queue
  95. VCD_RxQlen    dw    ?    ; Total size of queue in
  96. VCD_RxQ     dw    ?    ; QUEUE STARTS HERE -- Continues past here
  97. COMBuff_Extended_COM_Struc ENDS
  98.  
  99. .errnz SIZE COMBuff_Extended_COM_Struc - VCD_RxQ - 2
  100.  
  101.  
  102. ;
  103. ;   Compute extra size of data area EXCLUDING the word used for the first
  104. ;   queue entry (total queue size will be added on later).
  105. ;
  106. COMBuff_Extra_Data_Area = SIZE COMBuff_Extended_COM_Struc-SIZE VCD_COM_Struc-2
  107.  
  108.  
  109. ;******************************************************************************
  110. ;               F L A G   E Q U A T E S
  111. ;******************************************************************************
  112.  
  113.  
  114. ;******************************************************************************
  115. ;           I N I T I A L I Z A T I O N     D A T A
  116. ;******************************************************************************
  117.  
  118. VxD_IDATA_SEG
  119.  
  120. EXTRN COMBuff_Size_Ini_String:BYTE
  121. EXTRN COMBuff_Size_Ini_Number:BYTE
  122. EXTRN COMBuff_Prot_Ini_String:BYTE
  123. EXTRN COMBuff_Prot_Ini_Number:BYTE
  124. EXTRN COMBuff_XOFF_String:BYTE
  125.  
  126. VxD_IDATA_ENDS
  127.  
  128.  
  129. ;******************************************************************************
  130. ;                L O C A L    D A T A
  131. ;******************************************************************************
  132.  
  133. VxD_DATA_SEG
  134.  
  135. COMBuff_ProcList LABEL DWORD
  136.     dd    OFFSET32 COMBuff_VCD_Control
  137.     dd    OFFSET32 COMBuff_Int
  138.     dd    0
  139.     dd    OFFSET32 COMBuff_EOI
  140.     dd    OFFSET32 COMBuff_Mask
  141.     dd    OFFSET32 COMBuff_Test_Int_Req
  142.     dd    OFFSET32 COMBuff_In_RxTxB
  143.     dd    OFFSET32 COMBuff_Out_RxTxB
  144.     dd    OFFSET32 COMBuff_In_IER
  145.     dd    OFFSET32 COMBuff_Out_IER
  146.     dd    OFFSET32 COMBuff_In_IIR
  147.     dd    OFFSET32 COMBuff_Out_IIR
  148.     dd    OFFSET32 COMBuff_In_LCR
  149.     dd    OFFSET32 COMBuff_Out_LCR
  150.     dd    OFFSET32 COMBuff_In_MCR
  151.     dd    OFFSET32 COMBuff_Out_MCR
  152.     dd    OFFSET32 COMBuff_In_LSR
  153.     dd    OFFSET32 COMBuff_Out_LSR
  154.     dd    OFFSET32 COMBuff_In_MSR
  155.     dd    OFFSET32 COMBuff_Out_MSR
  156.  
  157. .ERRNZ $-COMBuff_ProcList-SIZE VCD_ProcList_Struc
  158.  
  159.  
  160. IFDEF DEBUG
  161. COM1_Handle    dd  0
  162. COM2_Handle    dd  0
  163. COM3_Handle    dd  0
  164. COM4_Handle    dd  0
  165. ENDIF
  166.  
  167. VxD_DATA_ENDS
  168.  
  169.  
  170. ;******************************************************************************
  171. ;           D E V I C E   C O N T R O L   P R O C E D U R E
  172. ;******************************************************************************
  173.  
  174. VxD_CODE_SEG
  175.  
  176. ;******************************************************************************
  177. ;
  178. ;   COMBuff_Control
  179. ;
  180. ;   DESCRIPTION:
  181. ;    This is the device control procedure for the COM Buffer device.
  182. ;
  183. ;   ENTRY:
  184. ;    EAX = Control call ID
  185. ;
  186. ;   EXIT:
  187. ;    If carry clear then
  188. ;        Successful
  189. ;    else
  190. ;        Control call failed
  191. ;
  192. ;   USES:
  193. ;    EAX, EBX, ECX, EDX, ESI, EDI, Flags
  194. ;
  195. ;==============================================================================
  196.  
  197. BeginProc COMBuff_Control
  198.  
  199.     Control_Dispatch Sys_Critical_Init, COMBuff_Sys_Crit_Init
  200.  
  201. IFDEF DEBUG
  202.     Control_Dispatch Debug_Query, COMBuff_Debug_Query
  203. ENDIF
  204.  
  205.     clc                    ; Ignore other control calls
  206.     ret
  207.  
  208. EndProc COMBuff_Control
  209.  
  210. VxD_CODE_ENDS
  211.  
  212.  
  213. ;******************************************************************************
  214. ;            I N I T I A L I Z A T I O N   C O D E
  215. ;******************************************************************************
  216.  
  217. VxD_ICODE_SEG
  218.  
  219. ;******************************************************************************
  220. ;
  221. ;   COMBuff_Sys_Crit_Init
  222. ;
  223. ;   DESCRIPTION:
  224. ;
  225. ;   ENTRY:
  226. ;
  227. ;   EXIT:
  228. ;
  229. ;   USES:
  230. ;
  231. ;==============================================================================
  232.  
  233. BeginProc COMBuff_Sys_Crit_Init
  234.  
  235.     VxDCall VCD_Get_Version
  236.     cmp    eax, 300h
  237.     jb    fail_init
  238.     xor    ecx, ecx
  239.  
  240. CB_SCI_Loop:
  241.     inc    ecx
  242.     push    ecx
  243.  
  244.     lea    eax, [ecx+"0"]
  245.     mov    [COMBuff_Size_Ini_Number], al
  246.     mov    [COMBuff_Prot_Ini_Number], al
  247.     mov    eax, Default_Buf_Size
  248.     xor    esi, esi            ; Null default program name
  249.     mov    edi, OFFSET32 COMBuff_Size_Ini_String
  250.     VMMcall Get_Profile_Decimal_Int
  251.     test    eax, eax
  252.     jz    DEBFAR CB_SCI_No_Buffer
  253.  
  254.     cmp    eax, 10000
  255.     jb    SHORT CB_SCI_Reasonable_Size
  256.     Debug_Out "Silly size of #EAX for COM buffer ignored -- Using a 10K buffer"
  257.     mov    eax, 10000
  258. CB_SCI_Reasonable_Size:
  259.  
  260.     push    eax
  261.     push    ecx
  262.     xchg    eax, ecx            ; EAX = Port #, ECX=Queue len
  263.     mov    ebx, COM_IRQ_Sharable
  264.     add    ecx, ecx            ; 2 bytes per queue entry
  265.     add    ecx, COMBuff_Extra_Data_Area    ; Add in size of data struc
  266.     xor    edx, edx
  267.     mov    esi, OFFSET32 COMBuff_ProcList
  268.     VxDcall VCD_Virtualize_Port
  269.     mov    ebx, eax
  270.     pop    ecx
  271.     pop    eax
  272.     jc    SHORT CB_SCI_No_Buffer
  273.  
  274. IFDEF DEBUG
  275.     ; save COM handle
  276.     push    esi
  277.     mov    esi, ecx
  278.     dec    esi
  279.     mov    [esi*4][COM1_Handle], ebx
  280.     pop    esi
  281. ENDIF
  282.     mov    [ebx.VCD_RxQlen], ax        ; Remember queue size
  283.  
  284.     xor    edx, edx
  285.     xor    esi, esi            ; Null default program name
  286.     mov    edi, OFFSET32 COMBuff_Prot_Ini_String
  287.     VMMcall Get_Profile_String
  288.  
  289.     mov    [ebx.VCD_Protocol], CB_No_Proto
  290.  
  291.     test    edx, edx
  292.     jz    SHORT CB_SCI_Next_Port
  293.  
  294.     mov    esi, OFFSET32 COMBuff_XOFF_String
  295.     mov    edi, edx
  296.     call    Compare_Strings
  297.     jc    SHORT CB_SCI_Next_Port
  298.  
  299.     mov    [ebx.VCD_Protocol], CB_XOFF_Proto
  300.  
  301.  
  302. CB_SCI_Next_Port:
  303. CB_SCI_No_Buffer:
  304.     pop    ecx
  305.     cmp    ecx, 4
  306.     jb    CB_SCI_Loop
  307.  
  308.     clc
  309. fail_init:
  310.     ret
  311.  
  312. EndProc COMBuff_Sys_Crit_Init
  313.  
  314.  
  315.  
  316. ;******************************************************************************
  317. ;
  318. ;   Compare_Strings
  319. ;
  320. ;   DESCRIPTION:
  321. ;    This procedure compares two strings.  If all of the characters up
  322. ;    to the NULL terminator of the first string match the characters
  323. ;    of the second string the procedure returns with carry clear,
  324. ;    otherwise carry is set.  On exit ECX contains the OFFSET of the
  325. ;    character that did not match.  Othewise it contains the length of
  326. ;    the first string (NOT including the NULL terminator).
  327. ;
  328. ;   ENTRY:
  329. ;    ESI = pointer to ASCIIZ string
  330. ;    EDI = pointer to String (does not have to be null terminated)
  331. ;
  332. ;   EXIT:
  333. ;    Carry clear if strings matched.
  334. ;
  335. ;   USES:
  336. ;    Flags
  337. ;
  338. ;==============================================================================
  339.  
  340. BeginProc Compare_Strings
  341.  
  342.     pushad
  343.  
  344.     xor    ecx, ecx
  345.     cld
  346. CS_Loop:
  347.     lodsb
  348.     test    al, al
  349.     jz    SHORT CS_Match
  350.     call    Force_Upper_Case
  351.     mov    bl, al
  352.     mov    al, BYTE PTR [edi]
  353.     inc    edi
  354.     call    Force_Upper_Case
  355.     cmp    al, bl
  356.     jne    SHORT CS_Failed
  357.     inc    ecx
  358.     jmp    CS_Loop
  359.  
  360. CS_Failed:
  361.     stc
  362.     jmp    SHORT CS_Exit
  363. CS_Match:
  364.     clc
  365. CS_Exit:
  366.     popad
  367.     ret
  368.  
  369. EndProc Compare_Strings
  370.  
  371.  
  372. ;******************************************************************************
  373. ;
  374. ;   Force_Upper_Case
  375. ;
  376. ;   DESCRIPTION:
  377. ;    This routine takes an ASCII character in AL and, if it is a lower
  378. ;    case letter, converts it to upper case.
  379. ;
  380. ;   ENTRY:
  381. ;    AL = ASCII character
  382. ;
  383. ;   EXIT:
  384. ;    AL = upper case letter or other ASCII character(unchanged)
  385. ;
  386. ;   USES:
  387. ;
  388. ;==============================================================================
  389.  
  390. BeginProc Force_Upper_Case
  391.  
  392.     cmp    al, "a"
  393.     jb    SHORT FUC_Done
  394.     cmp    al, "z"
  395.     ja    SHORT FUC_Done
  396.     sub    al, "a"-"A"
  397. FUC_Done:
  398.     ret
  399.  
  400. EndProc Force_Upper_Case
  401.  
  402.  
  403. VxD_ICODE_ENDS
  404.  
  405.  
  406. ;------------------------------------------------------------------------------
  407.  
  408. VxD_CODE_SEG
  409.  
  410. ;******************************************************************************
  411. ;      P R O C     F O R     C O N T R O L     C A L L S   F R O M   V C D
  412. ;******************************************************************************
  413.  
  414. ;******************************************************************************
  415. ;
  416. ;   COMBuff_VCD_Control
  417. ;
  418. ;   DESCRIPTION:
  419. ;
  420. ;   ENTRY:
  421. ;    EAX = message
  422. ;    EBX = new VM, or 0
  423. ;    EDX = old VM, or 0
  424. ;    ESI -> COM Struc
  425. ;
  426. ;   EXIT:
  427. ;
  428. ;   USES:
  429. ;
  430. ;==============================================================================
  431.  
  432. BeginProc COMBuff_VCD_Control
  433.  
  434.     cmp    eax, VCD_Control_Set_Owner
  435.     jne    SHORT COMBuff_VC_Ignore
  436.  
  437.     xchg    ebx, edx
  438.     or    ebx, ebx            ;Q: non-zero old VM handle
  439.     jz    SHORT CB_no_int_req        ;   N:
  440.     mov    eax, [esi.VCD_IRQ_Handle]    ;   Y: check about clearing
  441.                         ;      any outstanding int request
  442.     or    eax, eax
  443.     jz    short CB_no_int_req
  444.     VxDCall VPICD_Get_Complete_Status
  445.     test    ecx, VPICD_Stat_Virt_Dev_Req    ;Q: we requested int?
  446.     jz    SHORT CB_no_int_req        ;   N:
  447.     VxDCall VPICD_Clear_Int_Request     ;   Y: clear int request
  448.  
  449. CB_no_int_req:
  450.     mov    ebx, edx
  451.  
  452.     test    ebx, ebx            ;Q: assigning a new VM
  453.     jz    SHORT COMBuff_VC_Ignore     ;   N:
  454.  
  455.     call    COMBuff_Clear_Queue
  456.  
  457.     mov    eax, [esi.VCD_IRQ_Handle]
  458.     or    eax, eax
  459.     jz    short @F
  460.     VxDCall VPICD_Get_Complete_Status
  461.     test    ecx, VPICD_Stat_Virt_Mask    ;Q: VM has IRQ masked?
  462.     jz    short VC_not_masked        ;   N:
  463. @@:
  464.     call    COMBuff_Disable_Trapping    ;   Y: disable port trapping
  465. VC_not_masked:
  466.  
  467.     lea    edi, [esi.VCD_Vier]
  468.     mov    esi, [esi.VCD_CB_Offset]
  469.     lea    esi, [esi][ebx.VCD_IER]
  470.     cld
  471.     movsw                    ; Copy IER and LCR
  472.     movsb                    ; Copy MCR
  473.  
  474. COMBuff_VC_Ignore:
  475.     clc
  476.     ret
  477.  
  478. EndProc COMBuff_VCD_Control
  479.  
  480.  
  481. ;******************************************************************************
  482. ;            I / O   T R A P   P R O C E D U R E S
  483. ;******************************************************************************
  484.  
  485.  
  486. ;******************************************************************************
  487. ;
  488. ;   COMBuff_In_RxTxB
  489. ;
  490. ;   DESCRIPTION:
  491. ;
  492. ;   ENTRY:
  493. ;
  494. ;   EXIT:
  495. ;
  496. ;   USES:
  497. ;
  498. ;==============================================================================
  499.  
  500. BeginProc COMBuff_In_RxTxB, High_Freq
  501.  
  502.     cli
  503.     test    [esi.VCD_Vlcr], LCR_DLAB    ; Q: Access is to Divisor latch?
  504.     jnz    SHORT CB_In_Divisor_Latch    ;    Y: Yes, go do it
  505. ;
  506. ;   Input from data buffer
  507. ;
  508.     mov    al, [esi.VCD_Vrxb]        ; Get current character
  509.     and    [esi.VCD_Vlsr], NOT LSR_DR    ; Preserve error bits, reset DR
  510.     and    [esi.VCD_Virr], NOT IER_DR    ; Clear DR virtual interrupt
  511.     call    COMBuff_Extract_Queue        ; Suck out new status/char
  512.  
  513. IFDEF DEBUG_XOFF
  514.     push    eax
  515.     and    al, 7Fh
  516.     cmp    al, XOFF_char
  517.     jne    short D01_not_xoff
  518.     mov    al, [esi.VCD_Number]
  519.     Trace_Out 'XOFF read on COM#al'
  520. D01_not_xoff:
  521.     pop    eax
  522. ENDIF
  523.  
  524.     sti
  525.     ret
  526.  
  527. ;
  528. ;   Input from divisor latch LSB -- No virtualization
  529. ;
  530. CB_In_Divisor_Latch:
  531.     in    al, dx
  532.     sti
  533.     ret
  534.  
  535. EndProc COMBuff_In_RxTxB
  536.  
  537.  
  538.  
  539. ;******************************************************************************
  540. ;
  541. ;   COMBuff_Out_RxTxB
  542. ;
  543. ;   DESCRIPTION:
  544. ;
  545. ;   ENTRY:
  546. ;
  547. ;   EXIT:
  548. ;
  549. ;   USES:
  550. ;
  551. ;==============================================================================
  552.  
  553. BeginProc COMBuff_Out_RxTxB, High_Freq
  554.  
  555.     cli
  556.     test    [esi.VCD_Vlcr], LCR_DLAB    ; Q: Access is to Divisor latch?
  557.     jnz    SHORT CB_Out_Divisor_Latch    ;    Y: Yes, go do it
  558.  
  559.     and    [esi.VCD_Virr], NOT IER_THRE    ; Write to THR clears interrupt
  560.     cmp    al, XOFF_Char            ; Q: Is this a Ctrl-S
  561.     je    SHORT CB_THR_Sent_XOFF        ;    Y: Force delay
  562.     cmp    [esi.VCD_XOFF_Flag], True    ;    N: Q: Delaying now?
  563.     je    SHORT CB_THR_Restart        ;       Y: Stop delay now
  564.                         ;       N: Just send char
  565. CB_Out_Divisor_Latch:
  566.     out    dx, al                ; Do ouput
  567.     sti
  568.     ret
  569.  
  570. ;
  571. ;   Some other character was
  572. ;
  573. CB_THR_Restart:
  574.     mov    [esi.VCD_XOFF_Flag], False
  575.     push    eax
  576.     push    edx
  577.     call    COMBuff_Extract_Queue
  578.     call    COMBuff_Test_Int_Req
  579.     pop    edx
  580.     pop    eax
  581.     out    dx, al
  582.     sti
  583.     ret
  584.  
  585.  
  586. CB_THR_Sent_XOFF:
  587.     cmp    [esi.VCD_Protocol], CB_XOFF_Proto
  588.     jne    SHORT CB_THR_Output_Byte
  589.     mov    [esi.VCD_XOFF_Flag], True
  590. CB_THR_Output_Byte:
  591.     out    dx, al
  592.     sti
  593.     ret
  594.  
  595. EndProc COMBuff_Out_RxTxB
  596.  
  597.  
  598.  
  599. ;******************************************************************************
  600. ;
  601. ;   COMBuff_In_IER
  602. ;
  603. ;   DESCRIPTION:
  604. ;
  605. ;   ENTRY:
  606. ;
  607. ;   EXIT:
  608. ;
  609. ;   USES:
  610. ;
  611. ;==============================================================================
  612.  
  613. BeginProc COMBuff_In_IER, High_Freq
  614.  
  615.     cli
  616.     test    [esi.VCD_Vlcr], LCR_DLAB    ; Q: Access is to divisor latch
  617.     jnz    CB_In_Divisor_Latch        ;    Y: Do input from port
  618.  
  619.     mov    al, [esi.VCD_Vier]        ; return virtual reg
  620.     sti
  621.     ret
  622.  
  623. EndProc COMBuff_In_IER
  624.  
  625. ;******************************************************************************
  626. ;
  627. ;   COMBuff_Out_IER
  628. ;
  629. ;   DESCRIPTION:
  630. ;
  631. ;   ENTRY:
  632. ;
  633. ;   EXIT:
  634. ;
  635. ;   USES:
  636. ;
  637. ;==============================================================================
  638.  
  639. BeginProc COMBuff_Out_IER
  640.  
  641.     cli
  642.     test    [esi.VCD_Vlcr], LCR_DLAB    ; Q: Access is to divisor latch
  643.     jnz    CB_Out_Divisor_Latch        ;    Y: Do output to port
  644.  
  645.     xchg    al, [esi.VCD_Vier]        ; What the VM thought it was
  646.     out    dx, al                ; Make sure HW sees change
  647.     IO_Delay                ; Give hardware lots of time
  648.     mov    al, [esi.VCD_Vier]        ; Recover what the VM wants
  649.     or    al, IER_DR            ; Make sure we get Rx ints!
  650.     out    dx, al                ; Set it...
  651.     sti
  652.     ret
  653.  
  654. EndProc COMBuff_Out_IER
  655.  
  656.  
  657. ;******************************************************************************
  658. ;
  659. ;   COMBuff_In_IIR
  660. ;
  661. ;   DESCRIPTION:
  662. ;
  663. ;   ENTRY:
  664. ;
  665. ;   EXIT:
  666. ;
  667. ;   USES:
  668. ;
  669. ;==============================================================================
  670.  
  671. VxD_DATA_SEG
  672. ;
  673. ; Table to translate enabled active interrupts to IIR value
  674. ;    ( see VCD_Trap_IIR )
  675. ;
  676. COMBuff_IIR_Table LABEL BYTE
  677.         db    IIR_NONE    ;    0        0       0        0
  678.         db    IIR_DR        ;    0      0      0        1
  679.         db    IIR_THRE    ;    0      0      1        0
  680.         db    IIR_DR        ;    0      0      1        1
  681.         db    IIR_LS        ;    0      1      0        0
  682.         db    IIR_LS        ;    0      1      0        1
  683.         db    IIR_LS        ;    0      1      1        0
  684.         db    IIR_LS        ;    0      1      1        1
  685.         db    IIR_MS        ;    1      0      0        0
  686.         db    IIR_DR        ;    1      0      0        1
  687.         db    IIR_THRE    ;    1      0      1        0
  688.         db    IIR_DR        ;    1      0      1        1
  689.         db    IIR_LS        ;    1      1      0        0
  690.         db    IIR_LS        ;    1      1      0        1
  691.         db    IIR_LS        ;    1      1      1        0
  692.         db    IIR_LS        ;    1        1       1        1
  693.  
  694. VxD_DATA_ENDS
  695.  
  696.  
  697. BeginProc COMBuff_In_IIR
  698.  
  699.     cli
  700.     movzx    eax, [esi.VCD_Virr]        ; Interrupts requested
  701.     and    al, [esi.VCD_Vier]        ; Interrupts enabled
  702.     and    al, 1111b            ; Make sure only low nibble
  703.     mov    al, COMBuff_IIR_Table[eax]    ; Pick up value from table
  704.     cmp    al, IIR_THRE            ; Q: Strange one?
  705.     je    SHORT CB_In_IIR_Reset_THRE    ;    Y: Must reset THRE
  706.     sti
  707.     ret
  708.  
  709. CB_In_IIR_Reset_THRE:
  710.     and    [esi.VCD_Virr], NOT IER_THRE    ; not pending any more
  711.     sti
  712.     ret
  713.  
  714. EndProc COMBuff_In_IIR
  715.  
  716.  
  717. ;******************************************************************************
  718. ;
  719. ;   COMBuff_Out_IIR
  720. ;
  721. ;   DESCRIPTION:
  722. ;    This procedure should normally not be called!
  723. ;
  724. ;   ENTRY:
  725. ;
  726. ;   EXIT:
  727. ;
  728. ;   USES:
  729. ;
  730. ;==============================================================================
  731.  
  732. BeginProc COMBuff_Out_IIR
  733.  
  734.     mov    [esi.VCD_Viir], al
  735.     ret
  736.  
  737. EndProc COMBuff_Out_IIR
  738.  
  739.  
  740.  
  741. ;******************************************************************************
  742. ;
  743. ;   COMBuff_In_LCR
  744. ;
  745. ;   DESCRIPTION:
  746. ;
  747. ;   ENTRY:
  748. ;
  749. ;   EXIT:
  750. ;
  751. ;   USES:
  752. ;
  753. ;==============================================================================
  754.  
  755. BeginProc COMBuff_In_LCR
  756.  
  757.     cli
  758.     mov    al, [esi.VCD_Vlcr]        ; no point worrying device
  759.     sti
  760.     ret
  761.  
  762. EndProc COMBuff_In_LCR
  763.  
  764.  
  765. ;******************************************************************************
  766. ;
  767. ;   COMBuff_Out_LCR
  768. ;
  769. ;   DESCRIPTION:
  770. ;
  771. ;   ENTRY:
  772. ;
  773. ;   EXIT:
  774. ;
  775. ;   USES:
  776. ;
  777. ;==============================================================================
  778.  
  779. BeginProc COMBuff_Out_LCR
  780.  
  781.     cli
  782.     mov    [esi.VCD_Vlcr], al        ; Output: save it for DLAB
  783.     sti
  784.     out    dx, al                ;      and do it.
  785.     ret
  786.  
  787. EndProc COMBuff_Out_LCR
  788.  
  789.  
  790. ;******************************************************************************
  791. ;
  792. ;   COMBuff_In_MCR
  793. ;
  794. ;   DESCRIPTION:
  795. ;
  796. ;   ENTRY:
  797. ;
  798. ;   EXIT:
  799. ;
  800. ;   USES:
  801. ;
  802. ;==============================================================================
  803.  
  804. BeginProc COMBuff_In_MCR
  805.  
  806.     cli
  807.     mov    al, [esi.VCD_Vmcr]        ; no point worrying device
  808.     sti
  809.     ret
  810.  
  811. EndProc COMBuff_In_MCR
  812.  
  813.  
  814. ;******************************************************************************
  815. ;
  816. ;   COMBuff_Out_MCR
  817. ;
  818. ;   DESCRIPTION:
  819. ;
  820. ;   ENTRY:
  821. ;
  822. ;   EXIT:
  823. ;
  824. ;   USES:
  825. ;
  826. ;==============================================================================
  827.  
  828. BeginProc COMBuff_Out_MCR
  829.  
  830.     cli
  831.     xchg    al, [esi.VCD_Vmcr]        ; Get what the VM thought it was
  832.     out    dx, al                ; This may disable interrupt!
  833.     IO_Delay                ; Give hardware lots of time
  834.     mov    al, [esi.VCD_Vmcr]        ; Get what the VM wants
  835.     or    al, MCR_INTEN            ; Assume we want to enable ints
  836.     out    dx, al                ;      and do it.
  837.     test    al, MCR_DTR            ; Q: Is DTR is on?
  838.     jz    COMBuff_Clear_Queue        ;    N: Clear queue & return
  839.     sti
  840.     ret                    ;    Y: Done!
  841.  
  842. EndProc COMBuff_Out_MCR
  843.  
  844.  
  845. ;******************************************************************************
  846. ;
  847. ;   COMBuff_In_LSR
  848. ;
  849. ;   DESCRIPTION:
  850. ;
  851. ;   ENTRY:
  852. ;
  853. ;   EXIT:
  854. ;
  855. ;   USES:
  856. ;
  857. ;==============================================================================
  858.  
  859. BeginProc COMBuff_In_LSR, High_Freq
  860.  
  861.     cli
  862.     in    al, dx                ; Get real status
  863.     test    al, (LSR_DR + LSR_ERRBITS)    ; any Rx status?
  864.     jz    short VCD_Trap_LSR_Got_Status    ;     no, nothing to do
  865.     push    eax
  866.     and    al, (LSR_DR + LSR_ERRBITS)    ; junk transmit status
  867.     call    COMBuff_Poll_Status        ; Deal with Rx status
  868.     pop    eax                ; (ax got splattered!)
  869.     and    al, LSR_TXBITS            ; Real Tx status
  870. VCD_Trap_LSR_Got_Status:
  871.     mov    bl, [esi.VCD_Vlsr]        ; get virtual Rx status
  872.     or    al, bl                ; plus real Tx status
  873.     and    bl, LSR_DR            ; preserve DR bit, clear error
  874.     mov    [esi.VCD_Vlsr], bl        ; bits when reading LSR
  875.     and    [esi.VCD_Virr], NOT IER_LS    ; clear interrupt request
  876.     sti
  877.     ret
  878.  
  879. EndProc COMBuff_In_LSR
  880.  
  881.  
  882. ;******************************************************************************
  883. ;
  884. ;   COMBuff_Out_LSR
  885. ;
  886. ;   DESCRIPTION:
  887. ;
  888. ;   ENTRY:
  889. ;
  890. ;   EXIT:
  891. ;
  892. ;   USES:
  893. ;
  894. ;==============================================================================
  895.  
  896. BeginProc COMBuff_Out_LSR
  897.  
  898.     cli
  899.     and    al, (LSR_DR + LSR_ERRBITS)    ; what the chip does!
  900.     mov    [esi.VCD_Vlsr], al        ; weird!
  901.                         ; Emulate the H/W....
  902.     and    [esi.VCD_Virr], NOT (IER_LS + IER_DR)
  903.     test    al, LSR_DR
  904.     jz    SHORT CB_LSR_NoDR
  905.     or    [esi.VCD_Virr], IER_DR
  906. CB_LSR_NoDr:
  907.     test    al, LSR_ERRBITS
  908.     jz    SHORT CB_LSR_Exit
  909.     or    [esi.VCD_Virr], IER_LS
  910. CB_LSR_Exit:
  911.     sti
  912.     ret
  913.  
  914. EndProc COMBuff_Out_LSR
  915.  
  916.  
  917. ;******************************************************************************
  918. ;
  919. ;   COMBuff_In_MSR
  920. ;
  921. ;   DESCRIPTION:
  922. ;
  923. ;   ENTRY:
  924. ;
  925. ;   EXIT:
  926. ;
  927. ;   USES:
  928. ;
  929. ;==============================================================================
  930.  
  931. BeginProc COMBuff_In_MSR
  932.  
  933.     cli
  934.     in    al, dx                ; get real status
  935.     or    al, [esi.VCD_Vmsr]        ; and any saved delta bits
  936.     mov    [esi.VCD_Vmsr], 0
  937.     and    [esi.VCD_Virr], NOT IER_MS    ; clear modem interrupt request
  938.     sti
  939.     ret
  940.  
  941. EndProc COMBuff_In_MSR
  942.  
  943. ;******************************************************************************
  944. ;
  945. ;   COMBuff_Out_MSR
  946. ;
  947. ;   DESCRIPTION:
  948. ;
  949. ;   ENTRY:
  950. ;
  951. ;   EXIT:
  952. ;
  953. ;   USES:
  954. ;
  955. ;==============================================================================
  956.  
  957. BeginProc COMBuff_Out_MSR
  958.  
  959.     cli
  960.     out    dx, al                ; do it!
  961.     mov    [esi.VCD_Vmsr], 0        ; No saved delta bits now!
  962.     sti
  963.     ret
  964.  
  965. EndProc COMBuff_Out_MSR
  966.  
  967.  
  968. ;******************************************************************************
  969. ;      H A R D W A R E   I N T E R R U P T    P R O C E D U R E S
  970. ;******************************************************************************
  971.  
  972.  
  973. ;******************************************************************************
  974. ;
  975. ;   COMBuff_Int
  976. ;
  977. ;   DESCRIPTION:
  978. ;
  979. ;   ENTRY:
  980. ;
  981. ;   EXIT:
  982. ;
  983. ;   USES:
  984. ;
  985. ;==============================================================================
  986.  
  987.  
  988. VxD_DATA_SEG
  989.  
  990. CB_Int_Jmp_Table LABEL DWORD
  991.     dd    OFFSET32 CB_Modem_Int
  992.     dd    OFFSET32 CB_THRE_Int
  993.     dd    OFFSET32 CB_Rx_Int
  994.     dd    OFFSET32 CB_Rx_Int
  995.  
  996. VxD_DATA_ENDS
  997.  
  998.  
  999. BeginProc COMBuff_Int, High_Freq
  1000.  
  1001.     mov    edx, [esi.VCD_IObase]        ; Get start of ports
  1002.     add    dx, UART_IIR
  1003.     in    al, dx                ; get interrupt identity
  1004.     test    al, IIR_NONE            ; Came from this device?
  1005.     jz    SHORT CB_Int_Jump        ;     Yep, jump to handler
  1006.                         ;     Nope - Reflect it
  1007.     stc                    ;     to next guy in chain
  1008.     ret
  1009.  
  1010.  
  1011. CB_Int_Loop:
  1012.     mov    edx, [esi.VCD_IObase]        ; Get start of ports
  1013.     add    dx, UART_IIR
  1014.     in    al, dx                ; Get interrupt identity
  1015.     test    al, IIR_NONE            ; Came from this device?
  1016.     jnz    SHORT CB_Int_Done        ;    nope, just return!
  1017.  
  1018. CB_Int_Jump:
  1019.  
  1020. IFDEF DEBUG
  1021.     test    al, NOT 07h
  1022.     jz    short CB_IIR_Okay
  1023.     Debug_Out "COMBUF: IIR (#DX) has too many bits set: #AL"
  1024. CB_IIR_Okay:
  1025. ENDIF
  1026.     and    al, 07h
  1027.     movzx    eax, al
  1028.     jmp    CB_Int_Jmp_Table[eax*2]     ; Go deal with it
  1029.  
  1030. CB_Modem_Int:
  1031.     add    dx, (UART_MSR - UART_IIR)    ; pick up current modem status
  1032.     in    al, dx
  1033.     and    al, MSR_DELTA            ; only want Delta bits
  1034.     mov    [esi.VCD_Vmsr], al        ; save in virtual MSR
  1035.     or    [esi.VCD_Virr], IER_MS        ; set modem interrupt request
  1036.     jmp    CB_Int_Loop
  1037.  
  1038. CB_THRE_Int:
  1039.     or    [esi.VCD_Virr], IER_THRE    ; set THRE interrupt request
  1040.     jmp    CB_Int_Loop
  1041.  
  1042. CB_Rx_Int:
  1043.     add    dx, (UART_LSR - UART_IIR)    ; yes, get character/status
  1044.     in    al, dx
  1045.     and    al, (LSR_DR + LSR_ERRBITS)    ; junk transmit status
  1046.     jz    CB_Int_Loop            ; Hmmm!
  1047.     call    COMBuff_Poll_Status
  1048.     jmp    CB_Int_Loop
  1049.  
  1050. CB_Int_Done:
  1051.     mov    eax, [esi.VCD_IRQ_Handle]
  1052.     VxDcall VPICD_Phys_EOI
  1053.     call    COMBuff_Extract_Queue
  1054.     call    COMBuff_Test_Int_Req        ; Will "return" for us
  1055.     clc
  1056.     ret
  1057.  
  1058. EndProc COMBuff_Int
  1059.  
  1060.  
  1061. ;******************************************************************************
  1062. ;
  1063. ;   COMBuff_EOI
  1064. ;
  1065. ;   DESCRIPTION:
  1066. ;    Here we mindlessly clear the interrupt request for the COM port
  1067. ;    since it dosen't matter if the buffer was serviced yet or not.
  1068. ;    If it was not, then the IRET procedure will set the int request
  1069. ;    again and everyon will still be happy.
  1070. ;
  1071. ;   ENTRY:
  1072. ;    EAX = IRQ handle
  1073. ;    EBX = Current VM handle
  1074. ;    ESI -> COM structure
  1075. ;
  1076. ;   EXIT:
  1077. ;
  1078. ;   USES:
  1079. ;
  1080. ;==============================================================================
  1081.  
  1082.  
  1083. BeginProc COMBuff_EOI, High_Freq
  1084.  
  1085.     VxDjmp    VPICD_Clear_Int_Request
  1086.  
  1087. EndProc COMBuff_EOI
  1088.  
  1089.  
  1090. ;******************************************************************************
  1091. ;
  1092. ;   COMBuff_Mask
  1093. ;
  1094. ;   DESCRIPTION:    Routine called when VM is changing a COM port's IRQ mask
  1095. ;
  1096. ;   ENTRY:        EAX = IRQ handle
  1097. ;            EBX = VM handle
  1098. ;            ESI -> COM data structure
  1099. ;            ECX = 0, if unmasking
  1100. ;
  1101. ;   EXIT:        none
  1102. ;
  1103. ;   USES:        flags
  1104. ;
  1105. ;==============================================================================
  1106. BeginProc COMBuff_Mask
  1107.  
  1108.     jecxz    short COMBuff_Enable_Trapping
  1109.     VxDCall VPICD_Get_Complete_Status
  1110.     test    ecx, VPICD_Stat_In_Service    ;Q: IRQ in service?
  1111.     jz    short COMBuff_Disable_Trapping    ;   N: disable port trapping
  1112.     ret                    ;   Y: don't disable trapping
  1113.  
  1114. EndProc COMBuff_Mask
  1115.  
  1116.  
  1117. ;******************************************************************************
  1118. ;
  1119. ;   COMBuff_Disable_Trapping
  1120. ;
  1121. ;   DESCRIPTION:    Disable local trapping of a COM port's I/O ports
  1122. ;
  1123. ;   ENTRY:        ESI -> COM data structure
  1124. ;
  1125. ;   EXIT:        none
  1126. ;
  1127. ;   USES:        flags
  1128. ;
  1129. ;==============================================================================
  1130. BeginProc COMBuff_Disable_Trapping
  1131.  
  1132.     pushad
  1133. IFDEF DEBUG_verbose
  1134.     mov    al, [esi.VCD_Number]
  1135.     Trace_Out 'COMBUFF - disabling trapping for COM#al'
  1136. ENDIF
  1137.     mov    edx, [esi.VCD_IObase]
  1138.     mov    ecx, UART_PORTS
  1139. @@:
  1140.     VMMcall Disable_Local_Trapping
  1141.     inc    edx
  1142.     loopd    @B
  1143.     popad
  1144.     ret
  1145.  
  1146. EndProc COMBuff_Disable_Trapping
  1147.  
  1148.  
  1149. ;******************************************************************************
  1150. ;
  1151. ;   COMBuff_Enable_Trapping
  1152. ;
  1153. ;   DESCRIPTION:    Enable local trapping of a COM port's I/O ports
  1154. ;
  1155. ;   ENTRY:        ESI -> COM data structure
  1156. ;
  1157. ;   EXIT:        none
  1158. ;
  1159. ;   USES:        flags
  1160. ;
  1161. ;==============================================================================
  1162. BeginProc COMBuff_Enable_Trapping
  1163.  
  1164.     pushad
  1165. IFDEF DEBUG_verbose
  1166.     mov    al, [esi.VCD_Number]
  1167.     Trace_Out 'COMBUFF - enabling trapping for COM#al'
  1168. ENDIF
  1169. ;
  1170. ; First read current state of IER, LCR & MCR
  1171. ;
  1172.     mov    edx, [esi.VCD_IObase]
  1173.     inc    edx
  1174. .errnz UART_IER-1
  1175.     in    al, dx
  1176.     mov    [esi.VCD_Vier], al
  1177.     add    dl, UART_LCR-UART_IER
  1178.     IO_Delay
  1179.     in    al, dx
  1180.     mov    [esi.VCD_Vlcr], al
  1181.     inc    edx
  1182. .errnz UART_MCR-UART_LCR-1
  1183.     IO_Delay
  1184.     in    al, dx
  1185.     mov    [esi.VCD_Vmcr], al
  1186.     sub    dl, UART_MCR
  1187.  
  1188.     mov    ecx, UART_PORTS
  1189. @@:
  1190.     VMMcall Enable_Local_Trapping
  1191.     inc    edx
  1192.     loopd    @B
  1193.     popad
  1194.     ret
  1195.  
  1196. EndProc COMBuff_Enable_Trapping
  1197.  
  1198.  
  1199. ;******************************************************************************
  1200. ;
  1201. ;   COMBuff_Test_Int_Req
  1202. ;
  1203. ;   DESCRIPTION:
  1204. ;
  1205. ;   ENTRY:
  1206. ;    ESI -> COM structure
  1207. ;
  1208. ;   EXIT:
  1209. ;
  1210. ;   USES:
  1211. ;    Flags
  1212. ;
  1213. ;==============================================================================
  1214.  
  1215. BeginProc COMBuff_Test_Int_Req
  1216.  
  1217.     push    eax
  1218.     push    ebx
  1219.     push    ecx
  1220.     mov    ebx, [esi.VCD_Owner]        ; EBX = Handle of port owner
  1221.     Assert_VM_Handle ebx            ; Paranoia...
  1222.     mov    cl, [esi.VCD_Virr]        ; Interrupts pending
  1223.     and    cl, [esi.VCD_Vier]        ; and enabled?
  1224.     jz    SHORT CB_IR_Exit        ;    N: Clear int request
  1225.     test    [esi.VCD_Vlcr], LCR_DLAB    ; Q: Access is to divisor latch
  1226.     jnz    short CB_IR_Exit        ;    yes, can't send it!
  1227.     test    [esi.VCD_Vmcr], MCR_INTEN    ; and enabled?
  1228.     jz    short CB_IR_Exit        ;    no, can't send it!
  1229.     mov    eax, [esi.VCD_IRQ_Handle]    ; EAX = IRQ handle for VPICD
  1230.     or    eax, eax
  1231.     jz    short CB_IR_Exit
  1232.     VxDcall VPICD_Get_Status
  1233.     test    ecx, VPICD_Stat_IRET_Pending    ; Q: Waiting for IRET?
  1234.     jnz    SHORT CB_IR_Exit        ;    Y: Wait a little longer
  1235.     VxDcall VPICD_Set_Int_Request
  1236. CB_IR_Exit:
  1237.     pop    ecx
  1238.     pop    ebx
  1239.     pop    eax
  1240.     ret
  1241.  
  1242. EndProc COMBuff_Test_Int_Req
  1243.  
  1244.  
  1245.  
  1246. ;******************************************************************************
  1247. ;
  1248. ;   COMBuff_Poll_Status
  1249. ;
  1250. ;   DESCRIPTION:
  1251. ;      Read the Line Status Register.  Put Transmit status in
  1252. ;      vitual register, receive status in queue or virtual
  1253. ;      register as appropriate.
  1254. ;
  1255. ;   ENTRY:
  1256. ;      AL  = LSR Rx bits
  1257. ;      DX  = LSR I/O port
  1258. ;      ESI = pointer to VCD_COM structure
  1259. ;
  1260. ;   EXIT:
  1261. ;
  1262. ;   USES:
  1263. ;    EAX, EBX, EDX
  1264. ;
  1265. ;==============================================================================
  1266.  
  1267. BeginProc COMBuff_Poll_Status
  1268.  
  1269.     mov    ah, al                ; Save status in ah
  1270.     test    ah, LSR_DR            ; data ready?
  1271.     jz    SHORT CB_NoRxChar        ;    no, don't bother reading
  1272.     add    edx, (UART_RBR - UART_LSR)    ; DX => Receive buffer
  1273.     in    al, dx                ; get character in al
  1274. ;;;;;;;;;;;;;; DEBUGGING CODE WILL INSERT @ IF HARDWARE OVERFLOW ;;;;;;;;;;
  1275. IFDEF DEBUG
  1276.     test    ah, LSR_OE
  1277.     jz    SHORT OkieDokie
  1278.     mov    al, '@'
  1279.     and    ah, NOT LSR_OE
  1280. OkieDokie:
  1281. ENDIF
  1282. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1283.  
  1284. IFDEF DEBUG_XOFF
  1285.     push    eax
  1286.     and    al, 7Fh
  1287.     cmp    al, XOFF_Char
  1288.     jne    short D00_not_xoff
  1289.     mov    al, [esi.VCD_Number]
  1290.     Trace_Out 'Received XOFF on COM#al'
  1291. D00_not_xoff:
  1292.     pop    eax
  1293. ENDIF
  1294.  
  1295. CB_NoRxChar:
  1296.     mov    bl, [esi.VCD_Vlsr]        ; Set virtual regs
  1297.     test    bl, LSR_DR            ; Should we queue it?
  1298.     jnz    SHORT COMBuff_Insert_Queue    ;    yes, put in queue
  1299.     cmp    [esi.VCD_XOFF_Flag], True    ; XOFF sent?
  1300.     je    SHORT COMBuff_Insert_Queue    ;    yes, put in queue
  1301.  
  1302.     or    bl, ah
  1303.     mov    [esi.VCD_Vlsr], bl
  1304.     test    ah, LSR_DR            ; Data to put there?
  1305.     jz    SHORT CB_Poll_Status_Ret    ;    no, don't bother
  1306.     mov    [esi.VCD_Vrxb], al        ; (should usually have DR on)
  1307.     or    [esi.VCD_Virr], IER_DR        ; Set DR interrupt request
  1308.     test    bl, LSR_ERRBITS            ; Error bits on?
  1309.     jnz    SHORT CB_Poll_Set_Int_Status    ;    yes, go set interrupt
  1310. CB_Poll_Status_Ret:
  1311.     ret
  1312.  
  1313. CB_Poll_Set_Int_Status:
  1314.     or    [esi.VCD_Virr], IER_LS        ; Set LS interrupt request
  1315.     ret
  1316.  
  1317. EndProc COMBuff_Poll_Status
  1318.  
  1319.  
  1320. ;******************************************************************************
  1321. ;               Q U E U E    P R O C E D U R E S
  1322. ;******************************************************************************
  1323.  
  1324.  
  1325. ;******************************************************************************
  1326. ;
  1327. ;   COMBuff_Insert_Queue
  1328. ;
  1329. ;   DESCRIPTION:
  1330. ;
  1331. ;   ENTRY:
  1332. ;    AH = Status byte, AL = Data byte
  1333. ;
  1334. ;   EXIT:
  1335. ;
  1336. ;   USES:
  1337. ;    EBX, EAX
  1338. ;
  1339. ;==============================================================================
  1340.  
  1341. BeginProc COMBuff_Insert_Queue
  1342.  
  1343.     mov    bx, [esi.VCD_RxQlen]
  1344.     cmp    [esi.VCD_RxQcount], bx        ; queue full?
  1345.     je    SHORT CB_IQ_Full
  1346.     movzx    ebx, [esi.VCD_RxQin]
  1347.     mov    [esi.VCD_RxQ+ebx*2], ax        ; into the queue
  1348.     inc    [esi.VCD_RxQcount]
  1349.     inc    ebx
  1350.     cmp    bx, [esi.VCD_RxQlen]
  1351.     jb    SHORT CB_IQ_Set_New_Len
  1352.     xor    ebx, ebx
  1353. CB_IQ_Set_New_Len:
  1354.     mov    [esi.VCD_RxQin], bx        ; put index back
  1355. IFDEF DEBUG
  1356.     mov    bx, [esi.VCD_RxQcount]
  1357.     cmp    bx, [esi.VCD_Max_Queued]
  1358.     jbe    short CB_not_max
  1359.     mov    [esi.VCD_Max_Queued], bx
  1360. CB_not_max:
  1361. ENDIF
  1362.     ret
  1363.  
  1364. CB_IQ_Full:
  1365.     movzx    ebx, [esi.VCD_RxQin]
  1366.     or    ah, LSR_OE            ; simulate overrun error
  1367.     mov    [esi.VCD_RxQ+ebx*2], ax        ; into the queue
  1368.     ret
  1369.  
  1370. EndProc COMBuff_Insert_Queue
  1371.  
  1372.  
  1373.  
  1374. ;******************************************************************************
  1375. ;
  1376. ;   COMBuff_Extract_Queue
  1377. ;
  1378. ;   DESCRIPTION:
  1379. ;
  1380. ;   ENTRY:
  1381. ;    ESI -> COM data structure
  1382. ;
  1383. ;   EXIT:
  1384. ;
  1385. ;   USES:   EBX, EDX
  1386. ;
  1387. ;==============================================================================
  1388.  
  1389.  
  1390. BeginProc COMBuff_Extract_Queue, High_Freq
  1391.  
  1392.     cmp    [esi.VCD_RxQcount], 0        ; Anything in queue?
  1393.     je    SHORT CB_EQ_Exit        ;    no, nothing to extract
  1394.     cmp    [esi.VCD_XOFF_Flag], True    ; Q: XOFF?
  1395.     je    SHORT CB_EQ_Exit        ;    Y: Don't fill buffer
  1396. CB_EQ_Loop:
  1397.     test    [esi.VCD_Vlsr], LSR_DR
  1398.     jnz    SHORT CB_EQ_Exit
  1399.     dec    [esi.VCD_RxQcount]
  1400.     movzx    ebx, [esi.VCD_RxQout]
  1401.     mov    dx, [esi.VCD_RxQ+ebx*2]        ; get character from the queue
  1402.     inc    ebx
  1403.     cmp    bx, [esi.VCD_RxQlen]
  1404.     jb    SHORT CB_EQ_Set_Out_Ptr
  1405.     xor    ebx, ebx
  1406. CB_EQ_Set_Out_Ptr:
  1407.     mov    [esi.VCD_RxQout], bx        ; put index back
  1408.     or    dh, [esi.VCD_Vlsr]         ; add in old status
  1409.     mov    [esi.VCD_Vlsr], dh        ; and set virtual LSR
  1410.     test    dh, LSR_DR            ; Was there data too?
  1411.     jz    short CB_EQ_NoData
  1412.     mov    [esi.VCD_Vrxb], dl        ;    yes, put in virtual reg
  1413.     or    [esi.VCD_Virr], IER_DR        ; and set interrupt request
  1414.     test    dh, LSR_ERRBITS            ; Line status interrupt?
  1415.     jz    SHORT CB_EQ_Exit           ;       no, just return
  1416.     or    [esi.VCD_Virr], IER_LS        ;    yes, set interrupt request
  1417.     jmp    SHORT CB_EQ_Exit
  1418. CB_EQ_NoData:
  1419.     cmp    [esi.VCD_RxQcount], 0        ; queue empty?
  1420.     jne    short CB_EQ_Loop           ;       no, continue until queue
  1421.                         ;    empty, or LSR_DR is set
  1422.     test    dh, LSR_ERRBITS            ; Line status interrupt?
  1423.     jz    SHORT CB_EQ_Exit             ;         no, just return
  1424.     or    [esi.VCD_Virr], IER_LS        ;    yes, set interrupt request
  1425. CB_EQ_Exit:
  1426.     ret
  1427.  
  1428.  
  1429. EndProc COMBuff_Extract_Queue
  1430.  
  1431.  
  1432. ;******************************************************************************
  1433. ;
  1434. ;   COMBuff_Clear_Queue
  1435. ;
  1436. ;   DESCRIPTION:
  1437. ;
  1438. ;   ENTRY:
  1439. ;
  1440. ;   EXIT:
  1441. ;
  1442. ;   USES:
  1443. ;
  1444. ;==============================================================================
  1445.  
  1446. BeginProc COMBuff_Clear_Queue
  1447.  
  1448.     mov    [esi.VCD_RxQcount], 0        ; Clear receive Q
  1449.     mov    [esi.VCD_RxQin], 0
  1450.     mov    [esi.VCD_RxQout], 0
  1451.     and    [esi.VCD_Vlsr], NOT LSR_DR    ; preserve error bits, reset DR
  1452.     and    [esi.VCD_Virr], NOT IER_DR    ; clear DR virtual interrupt
  1453.     mov    [esi.VCD_XOFF_Flag], False
  1454.     ret
  1455.  
  1456. EndProc COMBuff_Clear_Queue
  1457.  
  1458.  
  1459.  
  1460.  
  1461. ;******************************************************************************
  1462. ;              D E B U G G I N G   C O D E
  1463. ;******************************************************************************
  1464.  
  1465. IFDEF DEBUG
  1466.  
  1467. ;******************************************************************************
  1468. ;
  1469. ;   COMBuff_Debug_Query
  1470. ;
  1471. ;   DESCRIPTION:
  1472. ;
  1473. ;   ENTRY:
  1474. ;
  1475. ;   EXIT:
  1476. ;
  1477. ;   USES:
  1478. ;
  1479. ;==============================================================================
  1480.  
  1481. BeginProc COMBuff_Debug_Query
  1482.  
  1483.     pushad
  1484.     mov    ecx, 4
  1485.     mov    al, 1
  1486.     mov    esi, OFFSET32 COM1_Handle
  1487. dump_port_data:
  1488.     mov    ebx, [esi]
  1489.     or    ebx, ebx
  1490.     jz    short debug_no_com_port
  1491.  
  1492.     movzx    edx, [ebx.VCD_Max_Queued]
  1493.     movzx    edi, [ebx.VCD_RxQlen]
  1494.     Trace_Out "COM#al: buffer size=#di, max queued=#dx"
  1495.     jmp    short debug_next_port
  1496.  
  1497. debug_no_com_port:
  1498.     Trace_Out "COM#al: no buffer assigned"
  1499.  
  1500. debug_next_port:
  1501.     inc    al
  1502.     add    esi, 4
  1503.     loop    dump_port_data
  1504.  
  1505.     popad
  1506.     ret
  1507.  
  1508. EndProc COMBuff_Debug_Query
  1509.  
  1510.  
  1511. ENDIF
  1512.  
  1513. VxD_CODE_ENDS
  1514.  
  1515.     END
  1516.