📄 gwcom.asm
字号:
TITLE GWCOM - OEM-indepedent Communications Routines
PAGE 56,132
;***
; GWCOM.ASM - OEM-indepedent Communications Routines
;
; Copyright <C> 1986 - 1988, Microsoft Corporation
;
; Purpose:
; To provide the GW I/O dispatch routines for the serial
; communications ports through calls to the OEM routines.
;
;******************************************************************************
INCLUDE switch.inc
INCLUDE rmacros.inc
useSeg _BSS
useSeg _DATA
useSeg CONST
useSeg DV_TEXT
INCLUDE seg.inc
INCLUDE baslibma.inc
INCLUDE files.inc
INCLUDE devdef.inc
INCLUDE ascii.inc ;must follow devdef.inc
INCLUDE addr.inc ;usercode header structure
INCLUDE comdcb.inc ;DCB structure for comm device
INCLUDE rtps.inc ; constants shared with QBI
INCLUDE idmac.inc
; The following macros generate the dispatch target labels used
; by the the I/O system one-time initialization(I) and dispatch
; dispatch table entry(D).
ComDspLabels MACRO Ctype
Cindex = 0 ;;value to pass to item generation macro
REPT NUM_RS232 ;;one item for each comm device defined
Cindex = Cindex + 1 ;;update the counter
ComItem Ctype,%Cindex ;;define item with type (I,C,D) and counter
ENDM
ENDM ;;ComDspLabels
ComItem MACRO Ctype,Cindex
PUBLIC B$&Ctype&_COM&Cindex ;;define PUBLIC (e.g., PUBLIC B$I_COM2)
B$&Ctype&_COM&Cindex: ;;define label (e.g., B$I_COM2:)
ENDM ;;ComItem
sBegin CONST
CMERRT DW OFFSET B$ERR_IOE ;Other IO Error
DW OFFSET B$ERR_CBO ;buffer overflow error
DW OFFSET B$ERR_IOE ;parity error
DW OFFSET B$ERR_DTO ;device timeout
DW OFFSET B$ERR_DTO ;device timeout
DW OFFSET B$ERR_DTO ;device timeout
sEnd CONST
sBegin _BSS
externB B$CM1DCB ; defined in GWDATA.ASM
externB b$FILMOD ; defined in GWINI.ASM
externB b$PATHNAM ; defined in GWINI.ASM
externW b$ComPort ;LLPARAM - save area for COMx I/O ports
externB b$COM_DCB ;DCB for COM1 device
externD b$RECPTR ; pointer to random record
externW b$cbComBuffer ;combuffer size specified on QB command line
staticW COMSAV,,2 ;save area for b$ComPort across SHELL
globalB b$COFlag,0,1 ; Flag to indicate COM OPEN in progress
sEnd _BSS
sBegin DV_TEXT
assumes CS,DV_TEXT
externNP B$FHHighAlloc
externNP B$FHHighDealloc
; Device Independent Interface
DSPMAC MACRO func
DW COM_&func ;;Define Dispatch Table for Specific Device
ENDM
; Communications Dispatch Table - must not be at offset 0.
ComDspLabels D ;define dispatch table labels
DSPNAM ;define dispatch table
SUBTTL Communications Generalized I/O Routines
externNP B$DEVOPN
externNP B$LHDALC_CPCT
externNP B$INICOM
externNP B$RECCOM
externNP B$SNDCOM
externNP B$STACOM
externNP B$TRMCOM
externNP B$BREAK_CHK
externNP B$ERR_BFN ;Error routines - Bad File Name
externNP B$ERR_DNA ;device unavailable error
externNP B$ERR_FAO ; File Already Open
externNP B$ERR_CBO ; Com Buffer Overflow
externNP B$ERR_DTO ; Device Time Out
externNP B$ERR_IOE ; Device Input Output Error
externNP B$ERR_FC ; Bad Function Call
externNP B$ERR_OM_FH ; out of memory error
; $I_COMx - called during BASIC initialization
; Entry - DI = -2*device id
ComDspLabels I ;define initialization labels
PUSH AX ;save registers...
PUSH DI
CALL GetComDCB ;DI points to device control block
MOV [DI].CD_CMWID,0FFH ;initial width is infinite
MOV [DI].CD_CMPOS,0 ;initial position is zero
MOV [DI].CD_CMFDB,0 ;mark this device as available for open
POP DI ;restore registers...
POP AX
RET ;return to caller
;***
; COM_OPEN - open an asynchronous communications device
;
; Entry:
; AL = device id (negative number from DN_COM1 to DN_COMn)
; BX = file number (0..n)
; CX = random record size if [b$FILMOD] = random
; (if [CX] = 0, use default record size)
; DI = device offset (2=COMD, 4=SCRN, etc.)
; b$FILMOD = file mode
; MD_SQI = 1 - sequential input
; MD_SQO = 2 - sequential output
; MD_RND = 4 - random
; MD_APP = 8 - append
; b$PATHNAM = null-terminated com options string (including "COMn:")
; Exit:
; SI = pointer to FDB allocated
;*****************************************************************************
; Syntax: OPEN "COMn:[SPEED][,[PARITY][,[DATA][,[STOP][,nonpos]]]]"
; Positional parameters:
;
; SPEED baud rate in bits per second
; PARITY N(none), E(even), O(odd), M(mark), S(space)
; DATA 5, 6, 7, or 8 bits per character
; STOP 1, 1.5, or 2 stop bits
; Default for slower than 110 baud and 6, 7, or 8 data bits is 2.
; Default for slower than 110 baud 5 data bits is 1.5.
; Default for 110 baud or faster is 1.
;
; Nonpositional parameters:
;
; RS Suppress RTS (Request To Send).
; OP[n] Open timeout in milliseconds.
; CS[n] Clear-to-send (CTS) timeout in milliseconds.
; DS[n] Data-set-ready (DSR) timeout in milliseconds.
; CD[n] Carrier-detect (CD) timeout in milliseconds.
; RB[n] Size of receive buffer in bytes.
; TB[n] Size of transmit buffer in bytes.
; LF Transmit a line-feed following a carriage-return.
; ASC Open COM file in ASCII mode | none => open in
; BIN Open COM file in binary mode | IBM mode
DbPub <COM_OPEN>
COM_OPEN:
MOV AH,BL ;[AH]=file number
PUSH AX ;save file number, device id
PUSH CX ;save variable record len (if random)
CALL GetComDCB ;AX = 0, 1, ... for COM1, COM2, ...
;DI points to Device Control Block
CMP [DI].CD_CMFDB,0 ;see if device is opened to another file
JE NERFNO ;No ERror, File Not Open
JMP B$ERR_FAO ;File Already Opened
NERFNO:
MOV [DI].CD_DEVID,AL ;set unit field of Device Control Block
MOV SI,OFFSET DGROUP:b$PATHNAM+5 ; point to options
CALL ParseOpt ;parse options (fill in DCB fields)
CALL B$ComAlloc ;[2]allocate the comm buffer and fill in DCB
MOV [DI].CD_CMPOS,0 ;reset column to 0
MOV BX,DI ;BX points to DCB
DbAssertRelB <[b$COFlag]>,E,0,DV_TEXT,<b$COFlag non-zero in COM_OPEN> ;
INC [b$COFlag] ; non-zero indicates COM OPEN in progress
CALL B$INICOM ;call machine dependent OPEN routine
;destroys FLAGS, AX..DX
DbAssertRelB <[b$COFlag]>,B,2,DV_TEXT,<bad b$COFlag value in COM_OPEN> ;
MOV [b$COFlag],0 ; be sure this is CLEARed on exit
OR AH,AH ;check for error during OPEN
JZ COMOPEN_NOERR ;if no error, then jump
CALL B$ComDealloc ;[2]deallocate the comm buffers
INC AH ;see if B$INICOM didn't like options
JZ ERCIFN ;bad file name error if illegal mode
INC AH ;test if device unavailable
JZ ERCDNA ;if so, then process error
SUB AH,2 ;get back error code other than -1 or -2
CALL CKCMER ;check for device error code (will not return)
COMOPEN_NOERR:
POP CX ;[CX]=record length
CMP b$FILMOD,MD_RND ; random open?
JNE NOTRND ; brif not
INC CX ; LEN parameter specified?
LOOP OPENIT ; brif so -- use that value for length
MOV CX,REC_LENGTH ; use default record length
SKIP 2 ; JMP OPENIT
NOTRND:
XOR CX,CX ; don't need any buffer space for seq files
OPENIT:
POP AX ; [AL]=device id, AH = file number
MOV DL,[DI].CD_CMWID ; [DL]=width from Device Control Block
MOV BL,AH
XOR BH,BH ; [BX]=file number
MOV AH,MD_RNDCH+MD_RND+MD_APP+MD_SQO+MD_SQI ; allow all file
; modes except BINARY
CALL B$DEVOPN ;Initialize FDB, SI has addr of FDB
JCXZ NO_BUFFER ; brif no buffer allocated
MOV [SI].FD_VRECL,CX ; save buffer size in FDB
NO_BUFFER:
OR [SI].FD_FLAGS,FL_NEOF ;not at eof
MOV [DI].CD_CMFDB,SI ;save FDB pointer in DCB
MOV [DI].CD_CMEVT,0 ;init event signal counter
TEST [DI].CD_CMFLG,CF_CMBIN
JZ CMOPNX ;branch if user wants ASCII mode
OR [SI].FD_FLAGS,FL_BIN ; indicate BINARY mode
CMOPNX:
RET
ERCIFN:
JMP B$ERR_BFN ;Bad File Name
ERCDNA:
JMP B$ERR_DNA ;device unavailable
;***
; ParseOpt - parse communications option string
;
; Purpose:
; [Rewritten as part of revision 6].
; To parse the communication option string and set the
; appropriate values in the device control block (DCB) for
; the specified device.
; Inputs:
; SI = pointer to start of option string.
; DI = pointer to device control block (DCB).
; Outputs:
; None.
; Modifies:
; AX, BX, CX, DX.
; Exceptions:
; B$ERR_BFN - bad file name error if option string syntax error.
;******************************************************************************
ParseOpt:
; Parse the first field as a numeric field for the baud rate.
MOV [DI].CD_BAUDR,300 ;set the default baud rate
CALL GetOptVal ;get the numeric value in DX
JC ParseBaudDone ;if null field, then use default
MOV [DI].CD_BAUDR,DX ;set the baud rate to the value read
ParseBaudDone:
; Parse the second field as one letter for the parity type.
; None(N)=0, Odd(O)=1, Even(E)=2, Mark(M)=3, and Space(S)=4.
MOV [DI].CD_PARIT,2 ;set the default parity as even
CALL GetOptChar ;read the next character in AL
JC ParseParDone ;if null field, then use default
MOV CX,5 ;five parity type to test
XOR BX,BX ;initialize the table index
ParseParLoop:
CMP AL,CS:ParityTable[BX] ;test field against parity types
JE ParseParFound ;if found, then jump to set it
INC BX ;increment index to next table entry
LOOP ParseParLoop ;loop until last type is tested
ParseError:
JMP B$ERR_BFN ;jump to report error in option string
ParityTable DB "NOEMS" ;available parity types in order
ParseParFound:
MOV [DI].CD_PARIT,BL ;put index as the parity type
CALL GetOptChar ;read next character looking for terminator
JNC ParseError ;if not terminator, then error
ParseParDone:
; Parse the third field as a numeric value for the data
; length (valid range is 5 to 8).
MOV [DI].CD_BYTSZ,7 ;default data length is 7 bits
CALL GetOptVal ;get the numeric value in DX
JC ParseSizeDone ;if null, then jump to use default
CMP DX,5 ;test lower bound of legal range
JB ParseError ;if less, then error
CMP DX,8 ;test upper bound of legal range
JA ParseError ;if more, then error
MOV [DI].CD_BYTSZ,DL ;set the size field with the value read
ParseSizeDone:
; Parse the fourth field as the number of stop bits. Legal
; values are 1, 1.5, and 2. Values are read as characters,
; not as a numeric value (no leading zeroes). If no value
; is given, the default value is:
; 1 stop bit - 0 - if over 110 baud
; 1.5 stop bits - 1 - if 110 or less baud and 5 bit data length
; 2 stop bits - 2 - if 110 or less baud and 6-8 bit data length
XOR DX,DX ;assume 1 stop bit
CMP [DI].CD_BAUDR,110 ;test computed baud rate
JA ParseStopDef ;if over 110 baud, jump to set default
INC DX ;now assume 1.5 stop bits
CMP [DI].CD_BYTSZ,5 ;test if 5 bit data length
JE ParseStopDef ;if 5 bit data, set default to 1.5 stop bits
INC DX ;6-8 bit data, set default to 2 stop bits
ParseStopDef:
CALL GetOptChar ;get the first character in field
JC ParseStopSet ;if null, jump to use default value in DL
MOV DL,AL ;move the character read
SUB DL,"1" ;map "1" to 0 and "2" to 1
CMP DL,1 ;test for valid range (0 to 1)
JA ParseError ;if not in range, then error
SHL DL,1 ;shift so values are 0(1 bit) and 2(2 bits)
JNZ ParseStopTerm ;if 2 bits, then jump to test for termination
CALL GetOptChar ;get the next char - either "." or terminator
JC ParseStopSet ;if terminator, then done - jump
MOV AH,AL ;move character for double test
CALL GetOptChar ;get next character - should be "5"
CMP AX,"5." ;*WRONG* test if last two characters of "1.5"
JNE ParseError ;if not, then syntax error
INC DL ;make value 1 for 1.5 stop bits
ParseStopTerm:
CALL GetOptChar ;get the terminator character
JNC ParseError ;if not, then syntax error
ParseStopSet:
MOV [DI].CD_STOPB,DL ;set the stop bit value
; The fifth and successive fields contain the order-independent
; parameters, which are identified by their leading characters.
; These parameters are:
; RS - turn off request-to-send
; OPn - set open timeout to n milliseconds
; DSn - set data-set-ready timeout to n milliseconds
; CSn - set clear-to-send timeout to n milliseconds
; CDn - set carrier-detect timeout to n milliseconds
; RBn - set size of receive buffer in bytes
; TBn - set size of transmit buffer in bytes
; LF - send line-feed after carriage-return at line end
; BIN - send data without conversion
; ASC - send data with conversion
; PE - enable reporting of parity errors on received data
XOR AX,AX ;clear register for setting values
MOV [DI].CD_CMFLG,CF_CMBIN ;clear all flags except for BIN
MOV [DI].CD_RLSTO,AX ;set carrier-detect timeout to zero
MOV [DI].CD_CTSTO,1000 ;set clear-to-send timeout to 1 second
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -