home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
ddkx86v5.zip
/
DDKX86
/
SRC
/
DEV
/
ATCOM
/
ATIOCTL.ASM
< prev
next >
Wrap
Assembly Source File
|
1995-04-14
|
43KB
|
1,222 lines
;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT Copyright (C) 1995 IBM Corporation
;
; The following IBM OS/2 WARP source code is provided to you solely for
; the purpose of assisting you in your development of OS/2 WARP device
; drivers. You may use this code in accordance with the IBM License
; Agreement provided in the IBM Device Driver Source Kit for OS/2. This
; Copyright statement may not be removed.;
;*****************************************************************************/
; SCCSID = @(#)atioctl.asm 6.6 91/11/11
; ***************************************************************************
; *
; *
; *
; ***************************************************************************
PAGE 80,132
.286p
TITLE com01.sys - Asynchronous Communication Device Driver
NAME com01
; Bryan Diehl
; David Gilman
;*** atioctl.asm - IOCTL Routines
;
; Support routines for generic IOCTLs.
;
; LoadGIODataPack - Put a byte or word into the IOCTL data packet
; GetGIOParaPack - Get a byte or word from the IOCTL parameter packet
; VerifyAddr - Verify an IOCTL packet pointers
; VerifyNull - Verify a NULL IOCTL packet pointer
; ComIoctl - IOCTL dispatcher
;
; Modification History
;
; BD 01/18/87 Re-written to conform to MS standard for
; style, clarity and efficiency.
; New queue structure.
; JGT 05/10/88 Add enhanced baud rate support
; YN 05/25/89 MVDM Support - @VDM
; YN 10/06/89 PTR 707056 - @@1
; ACW 04/16/91 @PVW Added perfview counters/timers
; YN 08/13/91 CP20D1390 - Bulletin Board Support
; WDM 04/21/94 82548 - pvwxport.inc now included in atcom.inc
; PMS 07/27/94 89343 - Only call CheckAPO when FIFO flags change
;
.xlist
include devhlp.inc
include devsym.inc
include basemaca.inc
include realmac.inc
include ioctl.inc
include seldesc.inc
include atcom.inc ; local include
include atesp.inc
.list
extrn DevHlp:dword
extrn ComInit:near
extrn CheckTX:near
extrn CmxDone:near
extrn CmxGenFail:near
extrn CmxInvalidParameter:near
extrn CmxInUse:near
extrn CmxMonitor:near
extrn CmxUnknown:near
extrn DisableRemoteTX:near
extrn EnableRemoteTXXO:near
extrn Get_OCI_Sem:near
extrn CheckLCR:near
extrn ComputeAPO:near
extrn ComputeHHS:near
extrn ComputeRTO:near
extrn ComputeWTO:near
extrn EnableRemoteTX:near
extrn MxInt:near
extrn SetLineC:near
extrn SetBaud:near
DSEG SEGMENT
;* IoctlTab - dispatch table for IOCTLs
;
EVEN
PUBLIC IoctlTab
IoctlTab LABEL WORD
DW OFFSET ioc_bad ; 40
DW OFFSET ioc_sbaud ; 41 set baud rate
DW OFFSET ioc_slinec ; 42 set line control
DW OFFSET ioc_sbaudenh ; 43 set extended bit baud
DW OFFSET ioc_tximmed ; 44 trans immed
DW OFFSET ioc_break0 ; 45 break off
DW OFFSET ioc_smodemc ; 46 set modem control
DW OFFSET ioc_rxoff ; 47 as if XOFF received
DW OFFSET ioc_rxon ; 48 as if XON received
DW OFFSET ioc_bad ; 49
DW OFFSET ioc_bad ; 4A
DW OFFSET ioc_break1 ; 4B break on
DW OFFSET ioc_bad ; 4C
DW OFFSET ioc_bad ; 4D
DW OFFSET ioc_bad ; 4E
DW OFFSET ioc_bad ; 4F
DW OFFSET ioc_bad ; 50
DW OFFSET ioc_bad ; 51
DW OFFSET ioc_bad ; 52
DW OFFSET ioc_sdcb ; 53 set device control block
DW OFFSET ioc_senh ; 54 set enhanced parms
DW OFFSET ioc_bad ; 55
DW OFFSET ioc_bad ; 56
DW OFFSET ioc_bad ; 57
DW OFFSET ioc_bad ; 58
DW OFFSET ioc_bad ; 59
DW OFFSET ioc_bad ; 5A
DW OFFSET ioc_bad ; 5B
DW OFFSET ioc_bad ; 5C
DW OFFSET ioc_bad ; 5D
DW OFFSET ioc_bad ; 5E
DW OFFSET ioc_bad ; 5F
DW OFFSET ioc_bad ; 60
DW OFFSET ioc_gbaud ; 61 get baud rate
DW OFFSET ioc_glinec ; 62 get line control
DW OFFSET ioc_gbaudenh ; 63 get baud enhanced
DW OFFSET ioc_gcomstat ; 64 get com status
DW OFFSET ioc_gtxstat ; 65 get tx status
DW OFFSET ioc_gmodemc ; 66 get modem control output signals
DW OFFSET ioc_gmodems ; 67 get modem control input signals
DW OFFSET ioc_gistat ; 68 input queue status
DW OFFSET ioc_gostat ; 69 output queue status
DW OFFSET ioc_bad ; 6A
DW OFFSET ioc_bad ; 6B
DW OFFSET ioc_bad ; 6C
DW OFFSET ioc_gcomerr ; 6D get com error word
DW OFFSET ioc_bad ; 6E
DW OFFSET ioc_bad ; 6F
DW OFFSET ioc_bad ; 70
DW OFFSET ioc_bad ; 71
DW OFFSET ioc_gevent ; 72 get comm event word
DW OFFSET ioc_gdcb ; 73 get device control block
DW OFFSET ioc_genh ; 74 get enhanced parms
MAXIOCTL = (($ - IoctlTab)/2) - 1
DSEG ENDS
CSEG SEGMENT
ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
;** LoadGIODataPackB - load a byte into the data packet
;** LoadGIODataPackW - load a word into the data packet
;
; ENTRY (es:di) -> request packet
; al = byte to put in GIODataPack
; ax = word to put in GIODataPack
;
; EXIT
;
; USES cx es di
;
; WARNING will not return if IOCTL data packet pointer is bad.
; See VerifyAddrD
;
; NOTE IOCTL packet pointers are virtual addresses.
Procedure LoadGIODataPackB,NEAR
ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
ChkRPPtr
mov cx,1 ; byte
call VerifyAddrD ; verify data address
SaveReg <es,di>
les di,es:[di].GIODataPack ; (ds:si) -> IOCTL data packet
stosb ; Put al into the data packet
RestoreReg <di,es>
ASSUME es:NOTHING
ret
Entry LoadGIODataPackW
ChkRPPtr
mov cx,2 ; word
call VerifyAddrD ; verify data address
SaveReg <es,di>
les di,es:[di].GIODataPack ; (ds:si) -> IOCTL data packet
stosw ; Put ax into the data packet
RestoreReg <di,es>
ASSUME es:NOTHING
ret
EndProc LoadGIODataPackB
;** GetGIOParaPackB - get a byte from the parameter packet
;** GetGIOParaPackW - get a word from the parameter packet
;
; ENTRY (es:di) -> request packet
;
; EXIT al = byte from GIOParaPack
; ax = word from GIOParaPack
;
; USES cx es di
;
; WARNING will not return if IOCTL parameter packet pointer is bad.
; See VerifyAddrP
;
; NOTE IOCTL packet pointers are virtual addresses.
Procedure GetGIOParaPackB,NEAR
ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
mov cx,1
jmp short GetGIOx
Entry GetGIOParaPackW
mov cx,2
GetGIOx:
ChkRPPtr
call VerifyAddrP ; verify parameter address, cx = size
SaveReg <es,di>
les di,es:[di].GIOParaPack ; (ds:si) -> IOCTL paramaters
cmp cx,1
je GetPack10 ; load a byte
mov ax,es:[di] ; load a word
jmp short GetPack99
GetPack10:
mov al,es:[di] ; load a byte
GetPack99:
RestoreReg <di,es>
ret
EndProc GetGIOParaPackB
;** VerifyAddrP - Verify IOCTL Parameter pointer
;** VerifyAddrD - Verify IOCTL Data pointer
;
; ENTRY (es:di) -> request packet
; cx length to verify
;
; EXIT will not return if invalid address
;
; USES none
;
; WARNING cx == 0 => 65536
; WARNING will not return if IOCTL parameter/data packet pointer is bad
; jumps indirectly to CmxGenFail (general failure)
; process will terminate when it returns from the kernel
Procedure VerifyAddrD,NEAR
ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
push ax
push dx
push di
mov ax,es:[di].GIODataPack._hi
mov di,es:[di].GIODataPack._lo
mov dx,(0100h OR DevHlp_VerifyAccess) ; read/write
jmp short VerifyAddr10
Entry VerifyAddrP
push ax
push dx
push di
mov ax,es:[di].GIOParaPack._hi
mov di,es:[di].GIOParaPack._lo
mov dx,(0000h OR DevHlp_VerifyAccess) ; read only
VerifyAddr10:
test [si].ci_vdm_flag,VDM_Flag_InUse ; @VDM if in use by VDM
jnz ver99 ; @VDM no check for pointer
devhelp
jc ioc_99 ; address
ver99: pop di
pop dx
pop ax
ret
EndProc VerifyAddrD
;** VerifyNullP - verify IOCTL parameter packet pointer is null
;** VerifyNullD - verify IOCTL data packet pointer is null
;
; ENTRY (es:di) -> request packet
;
; EXIT none
;
; USES none
;
; WARNING will NOT return if IOCTL parameter/data packet pointer
; is not null.
; jumps indirectly to CmxGenFail (general failure)
Procedure VerifyNullD,NEAR
ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
push bx
mov bx,GIODataPack ; offset of data packet
jmp short vn10
Entry VerifyNullP
push bx
mov bx,GIOParaPack ; offset of parameter packet
vn10: ChkRPPtr
test es:[di+bx]._hi,SELECTOR_MASK
jnz ioc_99 ; not a null selector
cmp es:[di+bx]._lo,0
jnz ioc_99 ; not a null offset
pop bx
ret
EndProc VerifyNullD
;** ComIoctl - Generic IOCTL Function Dispatcher
;
; ENTRY (ds:si) -> ComInfo
; (es:di) -> Request packet
;
; EXIT none
;
; USES ax bx
;
; Each IOCTL subroutine is called with:
; (ds:si) -> ComInfo
; (es:di) -> Request packet
; ah = major code (category)
; al = minor code (subfunction)
; df = direction flag cleared for auto increment
;
; IOCTL subroutines can use any register except bp.
Procedure ComIoctl,NEAR
ASSUME cs:CSEG,ds:DSEG,es:NOTHING,ss:NOTHING
ChkComInfoPtr
ChkRPPtr
; We need to insure mutual exclusion between opens, closes and ioctls.
call Get_OCI_Sem ; will not return if error
mov ah,es:[di].GIOCategory ; ah = category
mov al,es:[di].GIOFunction ; al = function
; We must handle monitor IOCTLs separately since they have
; a specific error code.
cmp ah,IOC_MO
je ioc_monitor ; monitor category not supported
; Sort out which IOCTL function we have.
cmp ah,IOC_SE
jne ioc_unknown ; not serial device category
mov bl,al ; function in bx for table index
and bx,IOMIN_SUBFUNC OR IOMIN_READ ; subfunction and read bits only
cmp bx,MAXIOCTL
ja ioc_bad ; function out of range
shl bx,1 ; word offset for dispatch table
cld ; clear direction flag (auto increment)
; If an IOCTL completes successfully, it does a RET or a jump to CmxDone.
; If it errs (like "invalid baud rate"), it can jump to ioc_99 or
; Cmx* instead no matter what stack depth it is at, as long
; as it hasn't modified bp (bp is used to restore the stack).
call IoctlTab[bx]
jmp CmxDone ; done and no error.
ioc_99: jmp CmxGenFail ; "general failure"
;** ioc_bad - unknown ioctl category and/or function
; don't return error if they don't want to see it
;
; ENTRY (es:di) -> request packet
;
; EXIT jumps to CmxDone or CmxUnknown
;
; USES none
ioc_bad:
test es:[di].GIOFunction,IOMIN_IGNERR
jz ioc_unknown ; don't ignore error
jmp CmxDone ; ignore error
ioc_unknown:
jmp CmxUnknown ; return 'unknown command'
ioc_monitor:
jmp CmxMonitor ; return 'monitors not supported'
;** IOCTL #41 - set baud rate
;
ioc_sbaud:
call VerifyNullD ; verify null data pointer
call GetGIOParaPackW ; (ax) = baud requested
call SetBaud ; set baud rate if legal
jnc ioc_sbx ; ok
jmp CmxInvalidParameter ; baud
ioc_sbx:
ret ; return normally.
;** IOCTL #42 - set line control (byte size, parity, stop bits)
;
; Parmlist contains three bytes: al = ByteSize, ah = Parity, ch = StopBits
;
ioc_slinec:
call VerifyNullD ; verify null data pointer
mov cx,3 ; number of bytes in the LCR structure
call VerifyAddrP ; verify address
les di,es:[di].GIOParaPack ; es:di -> Data Buffer.
mov ax,es:[di] ; get byte size and parity
mov ch,es:[di]+2 ; get stopbits
SaveReg <ax,cx> ; save LCR bytes
call CheckLCR ; verify input values
jnc ioc_linec10 ; "General Failure" err w/LCR input
jmp CmxGenFail ; line control, general failure
ioc_linec10:
RestoreReg <cx,dx> ; restore byte size and parity
mov [si].ci_bytesize,dl ; No error: put input into ComInfo.
mov [si].ci_parity,dh ;
mov [si].ci_stopbits,ch ;
call SetLineC ; Set [si].ci_linec, .ci_cmask
ret
;** IOCTL #46 - set modem control output signals (DTR and RTS only)
;
; uses masks of signals to turn off and on:
;
; WORD where high byte = mask of bits to turn OFF.
; low byte = mask of bits to turn ON.
;
; Examples: input high low result
; Set RTS: WORD = (NOT 0 shl 8 + 2) = 11111111 00000010 ; bit 2 ON
; Clear RTS: WORD = (NOT 2 shl 8 + 0) = 11111101 00000000 ; bit 2 OFF
; Set DTR: WORD = (NOT 0 shl 8 + 1) = 11111111 00000001 ; bit 1 ON
; Clear DTR: WORD = (NOT 1 shl 8 + 0) = 11111110 00000000 ; bit 1 OFF
; Set both: WORD = (NOT 0 shl 8 + 3) = 11111111 00000011 ; bits 1+2 ON
; Clear both: WORD = (NOT 3 shl 8 + 0) = 11111100 00000000 ; bits 1+2 OFF
;
; return general failure if the app tries to modify a signal that is being
; controled automatically by the drvice driver.
;
; return ComErr
;
ioc_smodemc:
; load up return value now in case of pointer
mov ax,[si].ci_comerr
call LoadGIODataPackW ; return ComErr word
call GetGIOParaPackW ; ax = control masks
mov bx,ax ; save in bx
; verify not trying to modify a signal being used for handshaking
not ah ; bits being turned off
or al,ah ; bits being modified
test al,NOT (MC_DTR OR MC_RTS OR MC_LOOP) ; trying to set
; reserved fields?
jnz ioc_99 ; yes, error
test al,MC_DTR
jz ioc_smodemc10 ; not modifying DTR
; don't have to mask because only DTR_FLOW has bit 10b on
.errnz F1_DTR_FLOW - 00000010b
.errnz F1_DTR_INVALID - 00000011b
test [si].ci_dcb_flags1,F1_DTR_FLOW
jnz ioc_99 ; DTR handshake - error
ioc_smodemc10:
test al,MC_RTS
jz ioc_smodemc15 ; not modifying RTS
; don't have to mask because both auto modes have bit 10000000b on
.errnz F2_RTS_FLOW - 10000000b
.errnz F2_RTS_TOGGLE - 11000000b
test [si].ci_dcb_flags2,F2_RTS_FLOW
jnz ioc_99 ; RTS handshake or toggle - error
ioc_smodemc15:
; Set MCR for standard port. (bx) = control masks
mov dx,[si].ci_port ; need port address for in/out
add dx,R_MODMC ; MCR port
min al,dx ; Get old MCR value.
and al,bh ; Turn OFF desired bits.
or al,bl ; Turn ON desired bits.
mout dx,al ; Output new MCR value.
ioc_smodemcx:
ret
;** IOCTL #61 - get baud rate
ioc_gbaud:
call VerifyNullP ; verify null parameter pointer
mov ax,[si].ci_baud
call LoadGIODataPackW ; load baud rate
ret
;** IOCTL #62 - get line control (byte size, parity, stop bits)
ioc_glinec:
call VerifyNullP ; verify null parameter pointer
mov cx,4 ; verify a write of four bytes
call VerifyAddrD ; verify a data address
les di,es:[di].GIODataPack ; es:di -> Data Buffer.
mov al,[si].ci_bytesize ; Data buffer: byte 0 = bytesize
mov ah,[si].ci_parity ; byte 1 = parity
stosw
mov al,[si].ci_stopbits ; byte 2 = stopbits
mov ah,[si].ci_linec ; byte 3 = Tx break
rol ah,2 ; roll break bit to bit 0
and ah,1 ; break bit only
stosw
ret
;** IOCTL #65 - return tx status
;
; Bit Description
; 0 queued write requests
; 1 data in DD tx queue
; 2 data in holding/shift register
; 3 character to tx immed
; 4 xon pending
; 5 xoff pending
; 6 reserved
; 7 reserved
;
ioc_gtxstat:
call VerifyNullP ; verify null parameter pointer
xor ah,ah ; clear ah
; Queued write requests?
cmp [si].ci_w_rp._hi,0
je short ioc_gtx10 ; no
or ah,1 shl 0 ; yes
ioc_gtx10:
; Data in driver transmit queue?
cmp [si].ci_qout.ioq_count,0
je short ioc_gtx20 ; no
or ah,1 shl 1 ; yes
ioc_gtx20:
; If standard port, look at LSR to see if data in tx hardware.
cli
ReadLSR ; (al) = LSR
sti
and al,LS_THRE OR LS_TSRE
cmp al,LS_THRE OR LS_TSRE ; data in tx hardware?
je ioc_gtx30 ; no
or ah,1 shl 2 ; yes
ioc_gtx30:
test [si].ci_hsflag,HS_TX_IMMED ; character waiting to tx immed?
jz short ioc_gtx40 ; no
or ah,1 shl 3 ; yes
ioc_gtx40:
test [si].ci_hsflag,HS_XON_PENDING ; XON pending?
jz short ioc_gtx50 ; no
or ah,1 shl 4 ; yes
ioc_gtx50:
test [si].ci_hsflag,HS_XOFF_PENDING ; XOFF pending?
jz short ioc_gtx60 ; no
or ah,1 shl 5 ; yes
ioc_gtx60:
xchg ah,al
call LoadGIODataPackB ; load tx status
ret
;** IOCTL #66 - get modem control output signals (DTR and RTS only)
ioc_gmodemc:
call VerifyNullP ; verify null parameter pointer
ioc_gmc20:
; If standard port, just read MCR.
mov dx,[si].ci_port ; need port address for in/out
add dx,R_MODMC ; Get Modem Control Reg value.
min al,dx
ioc_gmcx:
; (al) = MCR.
and al,MC_DTR OR MC_RTS ; mask reserved bits
call LoadGIODataPackB ; Put AL in the Req Packet data buffer.
ret
;** IOCTL #67 - get control input signals (from shadow)
ioc_gmodems: ; PTR B708056 @@1
call VerifyNullP ; verify null parameter pointer
gms50:
; If standard port, just read MSR.
mov dx,[si].ci_port ; @@1
add dx,R_MODMS ; (dx) -> modem status reg @@1
cli ; @@1
min al,dx ; (al) = modem status @@1
test al,MS_DCTS OR MS_DDSR OR MS_TERI OR MS_DDCD ; @@1
jz gms90 ; no MSR changes (interrupt) @@1
jmp SHORT gms80
gms80: call MxInt ; process modem status interrupt @@1
mov al,[si].ci_msrshadow
gms90: sti
call LoadGIODataPackB ; Put AL in the Req Packet data buffer.
ret
;** IOCTL #44 - transmit immediate
ioc_tximmed:
test [si].ci_vdm_flag,VDM_Flag_InUse ;CP20D1390 If the port is opened
jz tximm_normal_req ; with special vdm access,
cmp [si].ci_nvdmopens,0 ; Transmit Imm is not allowed.
ljg CmxInUse ;+yn error General Failure
tximm_normal_req:
call VerifyNullD ; verify null data pointer
call GetGIOParaPackB ; get byte to Tx
cli
test [si].ci_hsflag,HS_TX_IMMED ; already one pending?
jz txim10 ; no, were cool
sti
jmp CmxGenFail ; yes, general failure
txim10: mov [si].ci_tximm,al ; save char
or [si].ci_hsflag,HS_TX_IMMED ; flag TxImm char pending
txim20:
;NOTE interrupts are still off for CheckTX
call CheckTX ; kick transmitter into action.
tximmx: sti
ret
;** IOCTL #47 - as if XOFF received
ioc_rxoff:
call VerifyNullP ; verify null parameter pointer
call VerifyNullD ; verify null data pointer
off20:
cli
or [si].ci_HSFlag,HS_XOFF_RECEIVED
call CheckTX
sti
offx: ret
;** IOCTL #48 - as if XON received
ioc_rxon:
call VerifyNullP ; verify null parameter pointer
call VerifyNullD ; verify null data pointer
on20:
cli
and [si].ci_HSFlag,NOT HS_XOFF_RECEIVED ; Show XOff NOT received
call CheckTX
sti
onx: ret
;** IOCTL #4B - tx break on (stop transmitting)
ioc_break1:
call VerifyNullP ; verify null parameter pointer
call LoadGIODataPackW ; verify valid data parameter
cli ; See ioctl 45
or [si].ci_HSFlag,LC_BREAK ; set the break bit
.errnz HS_BREAK_SET-LC_BREAK
brk110:
mov al,[si].ci_linec ; get line control
or al,LC_BREAK ; set break bit
call SetLineC
call CheckTX
brk1x: sti
mov ax,[si].ci_comerr
call LoadGIODataPackW ; Return ComErr word, w/o clearing it.
ret
;** IOCTL #45 - tx break off (resume tranmitting)
ioc_break0:
call VerifyNullP ; verify null parameter pointer
call LoadGIODataPackW ; verify valid data parameter
cli
and [si].ci_HSFlag,not LC_BREAK ; clear the break bit
.errnz HS_BREAK_SET-LC_BREAK
brk010:
mov al,[si].ci_linec ; get line control
and al,not LC_BREAK ; clear break bit
call SetLineC
call CheckTX ; restart transmission
brkx: sti
mov ax,[si].ci_comerr
call LoadGIODataPackW ; Return ComErr word, w/o clearing it.
ret
;** IOCTL #68 - return # of characters in and size of receive queue
;
; NOTE Usable size of queue is one less than declared (QI_SIZE - 1).
ioc_gistat:
lea bx,[si].ci_qin ; get pointer to input queue
mov dx,QI_SIZE - 1
jmp SHORT ioc_giostat
;** IOCTL #69 - return # of characters in and size of transmit queue
;
; NOTE Usable size of queue is one less than declared (QO_SIZE - 1).
ioc_gostat:
lea bx,[si].ci_qout ; get pointer to queue
mov dx,QO_SIZE - 1
ioc_giostat:
call VerifyNullP ; verify null parameter pointer
mov cx,4 ; verify a write of four bytes
call VerifyAddrD ; verify a data address
les di,es:[di].GIODataPack ; es:di -> Data Buffer.
mov ax,[bx].ioq_count ; # of chars in Queue
stosw
mov ax,dx ; size
stosw
ret
;** IOCTL #72 - get (and clear) com event word
ioc_gevent:
call VerifyNullP ; verify null parameter pointer
xor ax,ax ; ax = 0
xchg ax,[si].ci_event ; Get the current event word
call LoadGIODataPackW ; Return the event
ret
;** IOCTL #64 - return com status
;
; the ComStatus byte is defined as follows:
;
; CST_CTS_HOLD = 01h Tx waiting for CTS
; CST_DSR_HOLD = 02h Tx waiting for DSR
; CST_DCD_HOLD = 04h Tx waiting for DCD
; CST_XOFF_HOLD = 08h Tx waiting because XOFF received
; CST_XOFF_SENT = 10h Tx waiting because XOFF transmitted
; CST_BREAK_HOLD = 20h Tx waiting because break being xmitted
; CST_TX_IMMED = 40h Character waiting to transmitt immediate
; CST_RX_DSR_HOLD = 80h Receive waiting for DSR
;
; Need to get the status for a com port. Since not all the status is
; contained within ci_status, it has to be assembled.
; Note: MSR has active low values (0 = on, 1 = off)
ioc_gcomstat:
call VerifyNullP ; verify null parameter pointer
xor ah,ah
; get DSR CTS DCD
mov al,[si].ci_msrshadow ; (al) = msrshadow
; (al) = MSR
gcs03: not al ; (al) = NOT msrshadow - which are down
mov bl,al ; (bl) = NOT msrshadow - which are down
and al,[si].ci_outhhslines ; only bits being used for handshaking
shl ax,1 ; shift DCD into ah
shl al,1 ; shift DSR and CTS next to DCD
shr ax,6 ; shift into position
.errnz MS_CTS-00010000b
.errnz MS_DSR-00100000b
.errnz MS_DCD-10000000b
.errnz CST_CTS_HOLD-00000001b
.errnz CST_DSR_HOLD-00000010b
.errnz CST_DCD_HOLD-00000100b
; Standard port:
cli
mov ah,[si].ci_HSFlag ; handshake flag
and ah,HS_XOFF_RECEIVED OR HS_XOFF_SENT ; xoff rx/txed flags
or al,ah ;Fix
sti
test [si].ci_dcb_flags2,F2_FULL_DUP
jz gcs09 ; full dup NOT on
and ah,NOT HS_XOFF_SENT ; full dup ON, tx doesn't wait
gcs05: or al,ah
.errnz HS_XOFF_RECEIVED-00001000b
.errnz CST_XOFF_HOLD-00001000b
.errnz HS_XOFF_SENT-00010000b
.errnz CST_XOFF_SENT-00010000b
gcs09:
; Get BreakHold
test [si].ci_hsflag,HS_BREAK_SET ; handshake flag
jz gcs10
or al,CST_BREAK_HOLD
gcs10:
; Get TxImmed
test [si].ci_hsflag,HS_TX_IMMED
jz gcs20
or al,CST_TX_IMMED ; show TX_IMMED pending
gcs20:
; Get F1_IN_DSR_SENSE
test [si].ci_dcb_flags1,F1_IN_DSR_SENSE ; input sensitivity to DSR?
jz ioc_comstatx ; no, can't be waiting for it
and bl,MS_DSR ; mask off DSR from MSR above
shl bl,2 ; shift into position
or al,bl
.errnz MS_DSR-00100000b
.errnz CST_RX_DSR_HOLD-10000000b
ioc_comstatx:
call LoadGIODataPackB ; load status
ret
;** IOCTL #6D - return (and clear) com error word
ioc_gcomerr:
call VerifyNullP ; verify null parameter pointer
xor ax,ax
xchg ax,[si].ci_comerr
call LoadGIODataPackW
ret
;** IOCTL #53 - set device control block (DCB)
;
; see spec and include files for definitions of the DCB structure
;
ioc_sdcb:
call VerifyNullD ; verify null data pointer
mov cx,DCB_SIZE ; # bytes in the DCB structure
.errnz DCB_SIZE - 11
call VerifyAddrP ; verify address
xchg si,di ; (ds:di) -> ComInfo
; (es:si) -> request packet
SaveReg <ds>
lds si,es:[si].GIOParaPack ; (ds:si) -> new DCB parameters
RestoreReg <es> ; (es:di) -> ComInfo struc
; check for invalid values in the DCB request
mov al,[si].ci_dcb_flags1 ; al = new flags1
mov bl,[si].ci_dcb_flags3 ; bl = new flags3
test al,F1_RESERVED
ljnz ioc_genfail ; reserved bits on
.errnz F3_READ_TO_MASK - 00000110b
.errnz F3_READ_TO_BAD - 00000000b
test bl,F3_READ_TO_MASK
jz ioc_genfail ; read timeout
; if (new flags3 fifo mode is zero)
; use old flags3 fifo bits and new flags3 other bits
; else if (new flags3 is non-zero)
; if (fifo not available)
; general failure
; set flags3 after copying to dd memory (can't change user memory)
mov bh,es:[di].ci_dcb_flags3 ; bh = old f3
test bl,F3_FIFO_MASK
jnz sdcb2 ; setting fifo mode, go verify
; the FIFO mode is zero, ignore all the fifo flags (use old values)
and bh,F3_FIFO_ALL ; bh = old f3 with fifo only
and bl,NOT F3_FIFO_ALL ; bl = new f3 with no fifo
or bl,bh ; bl = new f3 with old fifo
jmp SHORT sdcb4
; user is attempting to set the FIFO mode. Fail if no FIFO available.
sdcb2: test bh,F3_FIFO_MASK
jz ioc_genfail ; fifo not available
; RTS mode cannot be invalid
; check DTR modes
.errnz F1_DTR_ENABLE - 00000001b
.errnz F1_DTR_FLOW - 00000010b
sdcb4: and al,F1_DTR_MASK ; only the DTR bits
cmp al,F1_DTR_INVALID
je ioc_genfail ; invalid DRT mode
; all values are valid - put values into ComInfo
; save old flags1 and flags2 for ComputeHHS
mov al,es:[di].ci_dcb_flags1 ; al = old flags1
mov ah,es:[di].ci_dcb_flags2 ; ah = old flags2
SaveReg <ax> ; save old flags 1 and 2
; all values are valid - put values into ComInfo
SaveReg <di> ; save ComInfo pointer
.errnz ci_dcb_writeto
mov cx,DCB_SIZE
.errnz DCB_SIZE - 11
cli ; no interrupts while we set up the new modes
rep movsb ; copy DCB structure
RestoreReg <si> ; ComInfo pointer
push es
pop ds ; (ds:si) -> ComInfo struc
ChkComInfoPtr
mov [si].ci_dcb_flags3,bl ; save valid flags3
; ComputeAPO MUST be called before ComputeXTO because the timeouts
; are based on the number of characters per interrupt.
;@89343 Because some applications may wish to modify the Read T/O or
; the Write T/O and these values are part of the Function #53,
; we do not want to be changing the FIFO unless the FIFO flags
; have been changed. This is especially important because of
; the SMC patches applied in ComputeAPO. Also remember that
; ComputeAPO will be called at ComOpen if a FIFO exists so the
; initial values will be set at least one time. This fix is to
; handle the function 53 calls made while actively reading /
; writing to the port.
;
; @89343 start
cmp bh,bl ; bh = old, bl = new
je sdcb10 ; No change, then skip FIFO
SaveReg <bx> ; Save register
and bh,F3_FIFO_ALL ; mask bits 0 - 2
and bl,F3_FIFO_ALL ; mask bits 0 - 2
cmp bh,bl ; bh,bl masked off
RestoreReg <bx> ; Restore Register Back
je sdcb10 ; No Status Change in Flags.
; @89343 end
call ComputeAPO ; compute FIFO modes
sdcb10:
; always recalc read/write timeouts as timeout, RX trig or TX count
; may have changed. Easier to always recalc than to check.
call ComputeRTO ; calculate new read timeout values
call ComputeWTO ; calculate new write timeout values
RestoreReg <bx> ; bl = old flags1, bh = old flags2
; set DTR/RTS according to old/new DTR/RTS modes
call ComputeHHS ; calculate new hs masks
;Port is standard:
;if buffer full
; call DisableRemoteTX
;else
; call EnableRemoteTX. (This call is necessary to get DTR and RTS
; raised when we are transitioning from DTR and RTS off to input HS.
;endif
cmp [si].ci_qin.ioq_count,RX_HIGH_HS ;cj test to see if it's
;cj above HW mark
jle sdcb12 ;cj jump if RXQ is below high water mark
call DisableRemoteTX ;cj go drop input HS lines or
;cj send XOFF as appropriate
jmp SHORT sdcb14 ;cj
sdcb12:
call EnableRemoteTX ;cj go raise HS lines or
;cj send XON as appropriate
;Port is standard:
;if ATF disabled
; reset XOFF_RECEIVED flag
;endif
sdcb14:
test [si].ci_dcb_flags2,F2_OUT_XO ;cj test if ATF enabled
jnz sdcb16 ;cj jump if yes
and [si].ci_hsflag,NOT HS_XOFF_RECEIVED
;cj else turn off XOFF_Received
;cj flag
;Port is standard:
;if ARF disabled
; call EnableRemoteTXXO. We may have to send an XON, and we would
; have to do this regardless of the status of the receive buffer.
; We can't call EnableRemoteTX because EnableRemoteTX only works
; when ARF is enabled.
;endif
sdcb16:
test [si].ci_dcb_flags2,F2_IN_XO ;cj test if ARF is enabled
jnz sdcb18 ;cj jump if yes
call EnableRemoteTXXO ;cj else go send XON
;if input HS was disabled, then the HS lines would have been set
;appropriately when ComputeHHS was called above.
;
sdcb18:
call CheckTX ;cj
sdcb20:
; call MxInt to set FX_IN_DSR_OK in case F1_IN_DSR_SENSE mode changed
mov al,[si].ci_msrshadow ; (al) = modem status register shadow
call MxInt ; calls CheckTX
sdcbx: sti ; all modes set, ok for interrupts again
ret
ioc_genfail: ; intermediate jump point
jmp CmxGenFail ; general failure
;** IOCTL #73 - get device control block
ioc_gdcb:
call VerifyNullP ; verify null parameter pointer
mov cx,DCB_SIZE ; # bytes in the DCB structure
call VerifyAddrD ; verify data address
.errnz DCB_SIZE - 11
lea si,[si].ci_dcb_writeto ; (ds:si) -> DCB in ComInfo
les di,es:[di].GIODataPack ; (es:di) -> Data Buffer.
rep movsb ; copy DCB structure
ret
;************************************************************************
;* IOCTL #74 ioc_gENH
;*
;* Return Com Enhanced parameters Information (74h)
;*
;* FUNCTION: Retrieves the Enhanced Mode information from ComInfo.
;
; Bit Description
;
; 0 Enhanced mode supported by haardware
; 1 Enhanced mode enabled
; 2,3 DMA Recieve Operation Request
; 00 DMA Receive Disabled
; 01 DMA Receive Auto
; 10 DMA Receive Dedicated
; 11 Reserved
; 4,5 DMA Transmit Operation Request
; 00 DMA Transmit Disabled
; 01 DMA Transmit Auto
; 10 DMA Transmit Dedicated
; 11 Reserved
; 6 Last receive used DMA
; 7 Last transmit used DMA
ioc_genh:
call VerifyNullP ; make sure param pkt pointer is NULL
mov cx,1
call VerifyAddrD ; make sure data buffer addr is valid
; (AL) = enhanced flags
; set bits 0,1,6,7
mov al,[si].ci_eflags
and al,11000011b
; set bits 2,3
mov ah,[si].ci_tx_request
shl ah,2
or al,ah
; set bits 4,5
mov ah,[si].ci_rx_request
shl ah,4
or al,ah
call LoadGIODataPackB
ret ; return through ComIoctl
;************************************************************************
;* IOCTL #54 ioc_sENH
;*
;* Set Enhanced Mode Parameters (54h)
;*
;* FUNCTION: Verifies that all Flags passed in are valid.
;* Updates the Enhanced flags in ComInfo.
;*
ioc_sENH:
jmp CmxGenFail ; hardware doesn't support enhanced
;************************************************************************
;* IOCTL #63 ioc_gbaudENH
;*
;* Get Extended Baud Rate (63h)
;*
;* Returns port Data Transfer Rate (in ComInfo) to user.
;*
ioc_gbaudenh:
call VerifyNullP ; make sure null parm pkt pointer
mov cx,15 ; length of packet
call VerifyAddrD ; verify data address
; put baud rate into RP Data Area
SaveReg <si>
.386p
les di,es:[di].GIODataPack ; (es:di) -> IOCTL data packet
movzx eax,[si].ci_baud ; ax = baud data
; high part of eax = 0
stosd ; Baud
xor al,al
stosb ; Baud Frac
mov ax,MINBAUD
stosd ; Baud Min
xor al,al
stosb ; Min Frac
mov ax,MAX_EBAUD
stosd ; Baud Max
xor al,al
stosb ; Max Frac
.286p
RestoreReg <si>
ret
;************************************************************************
;* IOCtl #43 ioc_sbaudENH
;*
;* Set Extended (bit) Baud Rate (43h)
;*
;* Calls SetBaud to validate and set the Baud Rate.
;* Calls ComputeTPC to compute the new tick per char
;* value.
;*
ioc_sbaudenh:
call VerifyNullD ; verify null data pointer
mov cx,5 ; parameter packet is 5 bytes long
call VerifyAddrP ; verify parameter address, cx = size
push bx
SaveReg <es,di>
les di,es:[di].GIOParaPack ; (ds:si) -> IOCTL paramaters
.386p
mov eax,es:[di] ; load double word baud rate
.286p
xor bx,bx
mov bl,es:[di]+4 ; fraction
RestoreReg <di,es>
call SetBaud ; set baud rate if legal
; (only uses ax so no problem)
pop bx
jnc ioc_sbex
jmp CmxInvalidParameter ; baud
ioc_sbex:
ret ; return normally.
;##MAF end
EndProc ComIoctl
CSEG ENDS
END