diff options
Diffstat (limited to 'private/mvdm/wow16/drivers')
41 files changed, 11528 insertions, 0 deletions
diff --git a/private/mvdm/wow16/drivers/comm/bimodint.inc b/private/mvdm/wow16/drivers/comm/bimodint.inc new file mode 100644 index 000000000..e579440bb --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/bimodint.inc @@ -0,0 +1,95 @@ +;****************************************************************************** +; +; (C) Copyright MICROSOFT Corp., 1990 +; +; Title: BIMODINT.INC - Bimodal Interrupt Handler Equates and Structures +; +; Version: 1.00 +; +; Date: 14-Nov-1990 +; +; Author: RAL +; +;------------------------------------------------------------------------------ +; +; Change log: +; +; DATE REV DESCRIPTION +; ----------- --- ----------------------------------------------------------- +; 14-Nov-1990 RAL Original +; +;============================================================================== + +Bimodal_Int_Struc STRUC +BIS_IRQ_Number dw ? +BIS_VM_ID dw 0 +BIS_Next dd ? +BIS_Reserved1 dd ? +BIS_Reserved2 dd ? +BIS_Reserved3 dd ? +BIS_Reserved4 dd ? +BIS_Flags dd 0 +BIS_Mode dw 0 +BIS_Entry dw ? +BIS_Control_Proc dw ? + dw ? +BIS_User_Mode_API dd ? +BIS_Super_Mode_API dd ? +BIS_User_Mode_CS dw ? +BIS_User_Mode_DS dw ? +BIS_Super_Mode_CS dw ? +BIS_Super_Mode_DS dw ? +BIS_Descriptor_Count dw ? +Bimodal_Int_Struc ENDS + +BIS_Sel_Table equ word ptr (SIZE Bimodal_Int_Struc) + + +EBIS_Sel_Struc STRUC +EBIS_User_Mode_Sel dw ? + dw ? +EBIS_Super_Mode_Sel dw ? +EBIS_Sel_Struc ENDS + + +.errnz BIS_Super_Mode_API-BIS_User_Mode_API-4 +.errnz BIS_Super_Mode_CS-BIS_User_Mode_CS-4 +.errnz BIS_Super_Mode_DS-BIS_User_Mode_DS-4 +.errnz EBIS_Super_Mode_Sel-EBIS_User_Mode_Sel-4 + + +VPICD_API_Get_Ver EQU 0000h +VPICD_Install_Handler EQU 0001h +VPICD_Remove_Handler EQU 0002h +VPICD_Call_At_Ring0 EQU 0003h + + +BIH_API_EOI EQU 0000h +BIH_API_Mask EQU 0001h +BIH_API_Unmask EQU 0002h +BIH_API_Get_Mask EQU 0003h +BIH_API_Get_IRR EQU 0004h +BIH_API_Get_ISR EQU 0005h +BIH_API_Call_Back EQU 0006h + + +Declare_PM_BIS MACRO IRQn,CtrlP,ISRoff,APIoff,ISRcs,ISRds +LOCAL strt +strt label byte + dw IRQn ; BIS_IRQ_Number + dw 0 ; BIS_VM_ID + dd 6 DUP(0) ; BIS_Next/BIS_Reserved1-BIS_Reserved4/BIS_Flags + dw 0 ; BIS_Mode + dw ISRoff ; BIS_Entry + dw CtrlP ; BIS_Control_Proc + dw 0 ; filler + dw APIoff ; BIS_User_Mode_API + dw ISRcs + dd 0 ; BIS_Super_Mode_API + dw ISRcs ; BIS_User_Mode_CS + dw ISRds ; BIS_User_Mode_DS + dw 0 ; BIS_Super_Mode_CS + dw 0 ; BIS_Super_Mode_DS + dw 0 ; BIS_Descriptor_Count +.errnz $-strt - (SIZE Bimodal_Int_Struc) +ENDM diff --git a/private/mvdm/wow16/drivers/comm/ccom.asm b/private/mvdm/wow16/drivers/comm/ccom.asm new file mode 100644 index 000000000..31dbc94fd --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/ccom.asm @@ -0,0 +1,616 @@ +page,132 + +;---------------------------Module-Header-------------------------------; +; Module Name: CCOM.ASM +; +; Copyright (c) Microsoft Corporation 1985-1990. All Rights Reserved. +; +; History +; +; 041786 Fixed RECCOM to return be able to return nulls + +.xlist +include cmacros.inc +include comdev.inc +include ibmcom.inc +.list + +sBegin Code +assumes cs,Code +assumes ds,Data + +;========================================================================= +; +; Communications Device Driver - C language interface module. +; This module provides an interface layer between programs written +; in C, and the low-level OEM specific communications drivers. +; +;========================================================================= + + externNP $CLRBRK + externNP $DCBPTR + externNP $EVT + externNP $EVTGET + externNP $EXTCOM + externNP $FLUSH + externNP $INICOM + externNP $RECCOM + externNP $RECSTR + externNP $SETBRK + externNP $SETCOM + externNP $SETQUE + externNP $SNDCOM + externNP $SNDIMM + externNP $STACOM + externNP $TRMCOM + externNP $SNDCOMSTR + externNP $ENANOTIFY + + externNP GetDEB + +;========================================================================= +; +; ushort inicom(pdcb) +; dcb far *pdcb; +; +; returns - 0 if no errors occured +; - Error Code (which is reset) +; +; Inicom is a one-time called routine to initialize. This is meant +; to be called when a process starts, or determines that it will use +; communications. Operating parameters are also passed on to setcom(), +; below. +; +; Fields within the dcb (including device id) should be set up prior to +; calling inicom. +; +; As a true device driver, this routine is to be called when the device +; driver is loaded at system start-up time. The dcb reflects the +; default operating parameters. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc inicom,<PUBLIC,FAR> + parmD pdcb + +cBegin + les bx,pdcb + assumes es,nothing + + call $INICOM +cEnd + +page + +;========================================================================= +; +; ushort setcom(pdcb) +; dcb far *pdcb; +; +; returns - 0 if no errors occured +; - Error Code (reset) +; +; Set/alter communications operating parameters. This is a non-destructive +; alteration of operating mode. Queues and interrupts are not affected. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc setcom,<PUBLIC,FAR> + parmD pdcb + +cBegin + les bx,pdcb ;get pointer to dcb + assumes es,nothing + + call $SETCOM +cEnd + +page + +;========================================================================= +; +; void setque(cid,pqdb) +; char cid; +; qdb far *pqdb; +; +; Init the locations of the receive and transmit queues that are to be +; used to buffer incomming and outgoing characters. +; +; This may be called at any time by a process to use a different set +; of queues. Characters (transmit and/or receive) may be lost if the +; queues are changed when not empty. This allows dynamic allocation +; of variable sized queues. Under DOS 4.0, the queues must be locked in +; memory. +; +; As a true device driver, the queues would be allocated at boot time, +; and must also be locked under DOS 4.0. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc setque,<PUBLIC,FAR> + parmB cid + parmD pqdb + +cBegin + mov ah,cid + les bx,pqdb ;pointer to qdb + assumes es,nothing + + call $SETQUE +cEnd + +page + +;========================================================================= +; +; short reccom(cid) +; char cid; +; +; Returns - character. +; - -1 if error +; - -2 if no character available +; +; Read a byte. Extracts a byte from the receive data queue. Returns +; immediately. +;========================================================================= + + +assumes ds,Data +assumes es,nothing + +cProc reccom,<PUBLIC,FAR> + parmB cid + +cBegin + mov ah,cid ;Id Into AH + + call $RECCOM ;Get char, error, or no data + mov cx,ax ;Save data + mov ah,0 ;Assume valid data + jnz reccom5 ;Data is valid + mov ax,-2 ;Assume no data available + jcxz reccom5 ;No data available + inc ax ;Show error (-1) + +reccom5: +cEnd + +page + +;========================================================================= +; +; short ReadCommString(cid, buf, cnt) +; char cid; +; LPSTR buf; +; int cnt; +; +; Returns - ax = # of bytes read +; - 0 if no character available or error +; +; Read string. Extracts bytes from the receive data queue. Returns +; immediately. +;========================================================================= + + +assumes ds,Data +assumes es,nothing + +cProc ReadCommString,<PUBLIC,FAR> + parmB cid + parmD buf + parmW cnt + +cBegin + mov ah,cid ;Id Into AH + les di, buf + mov cx, cnt + + call $RECSTR ;Get char, error, or no data + jnz short recstr5 ; jmp if no error + xor ax, ax +recstr5: +cEnd + +page + +;========================================================================= +; +; ushort sndcom(cid,ch) +; char cid; +; char ch; +; +; Returns - 0 if no errors +; - Error Code (Not removed, i.e. stacom will return this error +; unless another occurs before the next call to stacom.) +; +; Transmit a byte. Places a byte into the transmit queue. Negative return +; indicates error. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc sndcom,<PUBLIC,FAR> + parmB cid + parmB chr + +cBegin + mov ah,cid + mov al,chr + + call $SNDCOM +cEnd + +page + +;========================================================================= +; +; ushort ctx(cid,ch) +; char cid; +; char ch; +; +; Returns - 0 if no errors +; - -1 if character could not be sent. +; +; Transmit a byte "immediately". Places a byte into the transmit queue. +; or other buffer such that it is the next character picked up for +; transmission. Negative return indicates error. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc ctx,<PUBLIC,FAR> + parmB cid + parmB chr + +cBegin + mov ah,cid + mov al,chr + + call $SNDIMM +cEnd + +page + +;========================================================================= +; +; void trmcom(cid) +; char cid; +; +; Terminate communications on a particular channel. Flushes the +; buffers (waits for completion), and shuts down the comm device. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc trmcom,<PUBLIC,FAR> + parmB cid + +cBegin + mov ah,cid + + call $TRMCOM ;and go for it +cEnd +page + +;========================================================================= +; +; ushort stacom(cid,pstat) +; char cid; +; stat far *pstat; +; +; Returns - 0 if no errors +; - Error Code +; - status structure updated. +; +; Get device status. Returns device status and input queue status. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc stacom,<PUBLIC,FAR>,<si,di> + parmB cid + parmD pstat + +cBegin + mov ah,cid + les bx,pstat + assumes es,nothing + + call $STACOM +cEnd + +page + +;========================================================================= +; +; dword cextfcn(cid,fcn) +; char cid; +; short fcn; +; +; Perform extended functions. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc cextfcn,<PUBLIC,FAR> + parmB cid + parmW fcn + +cBegin + mov ah,cid + mov bx,fcn + + call $EXTCOM +cEnd + +page + +;========================================================================= +; +; ushort cflush(cid,q) +; ushort cid; +; ushort q; +; +; Queue flush. empties the specified queue. q=0 means transmit queue, +; 1 indicates receive queue. +; +; Returns - 0 or -1. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc cflush,<PUBLIC,FAR>,<si,di> + parmB cid + parmB q + +cBegin + mov ah,cid + mov bh,q + + call $FLUSH +cEnd + +page + +;========================================================================= +; +; ushort far *cevt(cid,evtmask) +; ushort cid; +; ushort evtmask; +; +; Returns the location of a word which in which certain bits will be set +; when particular events occur. The event mask passed defines which bits +; are to be enabled. The event byte is used primarily for speed in +; determining if certain events have occurred. Returns 0 on success, -1 +; for an illegal handle. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc cevt,<PUBLIC,FAR> + parmB cid + parmW evt_mask + +cBegin + mov ah,cid + mov bx,evt_mask + + call $EVT ;Set the event +cEnd + +page + +;========================================================================= +; +; short cevtGet(cid, evtmask) +; ushort cid; +; ushort evtmask; +; +; The event byte set up by cevt, above, is returned. This routine must be +; used to read the event byte in order to prevent loss of an event +; occurance. Those bits set in the event mask passed are then cleared in +; the event byte. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc cevtGet,<PUBLIC,FAR> + parmB cid + parmW evt_mask + +cBegin + mov ah,cid + mov bx,evt_mask + + call $EVTGET +cEnd + +page + +;========================================================================= +; +; short csetbrk(cid) +; ushort cid; +; +; Suspends character transmission, and places the transmission line in +; a break state until cclrbrk is called. Returns 0 on success, -1 if +; illegal handle. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc csetbrk,<PUBLIC,FAR>,<si,di> + parmB cid + +cBegin + mov ah,cid + + call $SETBRK +cEnd + +page + +;========================================================================= +; +; short cclrbrk(cid) +; ushort cid; +; +; Restores the line to a non-breaking state, and restarts character +; transmission. Returns 0 on success, -1 if illegal handle. +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc cclrbrk,<PUBLIC,FAR>,<si,di> + parmB cid + +cBegin + mov ah,cid + + call $CLRBRK +cEnd + +page + +;========================================================================= +; +; dcb far *getdcb(cid) +; ushort cid; +; +; Returns a pointer to the dcb associated with the given id. +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc getdcb,<PUBLIC,FAR>,<si,di> + parmB cid + +cBegin + mov ah,cid + + call $DCBPTR +cEnd + +;========================================================================= +; +; int CommWriteString(cid, lpstring, count) +; ushort cid; +; LPSTR lpstring; +; int count; +; +; Returns # of bytes sent +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc CommWriteString, <FAR, PUBLIC>, <si, di> + + parmB cid + parmD lpstring + parmW count + +cBegin + + xor ax, ax + mov cx, count + jcxz short cws_exit + mov ah, cid + les di, lpstring + call $SNDCOMSTR +cws_exit: +cEnd +page + +;========================================================================= +; +; bool EnableNotification(cid, hWnd, recv_trigger, send_trigger) +; ushort cid; +; WORD hWnd; /* 0, to disable notification */ +; int recv_trigger; +; int send_trigger; +; +; Returns # of bytes sent +; +;========================================================================= + +assumes ds,Data +assumes es,nothing + +cProc EnableNotification, <FAR, PUBLIC>, <si, di> + + parmB cid + parmW _hWnd + parmW recvT + parmW sendT + +cBegin + + mov ah, [cid] + mov bx, [_hWnd] + mov cx, [recvT] + mov dx, [sendT] + call $ENANOTIFY +cEnd +page + +;-----------------------------------------------------------------------; +; WEP +; +; +; Entry: +; +; Returns: +; +; Registers Destroyed: +; +; History: +; Sat 13-Jan-1990 18:33:48 -by- David N. Weise [davidw] +; Wrote it! +;-----------------------------------------------------------------------; + + assumes ds,nothing + assumes es,nothing + +cProc WEP,<PUBLIC,FAR> +cBegin nogen + nop ; You don't want to know why. + mov ax,1 + ret 2 +cEnd nogen + +sEnd Code + +end + diff --git a/private/mvdm/wow16/drivers/comm/comdev.h b/private/mvdm/wow16/drivers/comm/comdev.h new file mode 100644 index 000000000..a913cffa3 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/comdev.h @@ -0,0 +1,243 @@ +/************************************************************************* +** +** Miscelaneous definitions. +*/ +typedef unsigned short ushort; +typedef unsigned char uchar; + +#define NULL 0 +#define FALSE 0 +#define TRUE 1 + +#define LPTx 0x80 /* Mask to indicate cid is for LPT device */ /*081985*/ +#define LPTxMask 0x7F /* Mask to get cid for LPT device */ /*081985*/ + +#define PIOMAX 3 /* Max number of LPTx devices in high level */ /*081985*/ +#define CDEVMAX 10 /* Max number of COMx devices in high level */ +#define DEVMAX 13 /* Max number of devices in high level */ /*081985*/ + +/************************************************************************* +** +** device control block. +** This block of information defines the functional parameters of the +** communications software and hardware. +** +** Fields in the DCB are defined as follows: +** +** Id - Comm device ID, set by the device driver. +** BaudRate - Baud rate at which operating. +** ByteSize - Number of bits per transmitted/received byte. (4-8) +** Received data is also masked off to this size. +** Parity - Transmitt/Receive Parity. (0,1,2,3,4) = (None, Odd, +** Even, Mark, Space) +** StopBits - Number of stop bits. (0,1,2) = (1, 1.5, 2) +** RlsTimeout - Amount of time, in milleseconds, to wait for RLSD to +** become high. RLSD, Receive Line Signal Detect is also +** known as CD, Carrier Detect. RLSD flow control can be +** achieved by specifying infinite timeout. +** CtsTimeout - Amount of time, in milleseconds, to wait for CTS, +** Clear To Send, to become high. CTS flow control can +** be achieved by specifying infinite timeout. +** DsrTimeout - Amount of time, in milleseconds, to wait for DSR, +** Data Set Ready, to become high. DSR flow control can +** be acheived by specifying infinite timeout. +** fBinary - Binary Mode flag. In non-binary mode, EofChar is +** recognized and remembered as end of data. +** fRtsDisable - Disable RTS flag. If set, Request To Send is NOT +** used, and remains low. Normally, RTS is asserted when +** the device is openned, and dropped when closed. +** fParity - Enable Parity Checking. Parity errors are not +** reported when 0. +** fOutxCtsFlow - enable output xon/xoff(hardware) using cts +** fOutxDsrFlow - enable output xon/xoff(hardware) using dsr +** fOutX - Indicates that X-ON/X-OFF flow control is to be used +** during transmission. The transmitter will halt if +** an X-OFF character is received, and will start again +** when an X-ON character is received. +** fInX - Indicates that X-ON/X-OFF flow control is to be used +** during reception. An X-OFF character will be +** transmitted when the receive queue comes within 10 +** characters of being full, after which an X-ON will be +** transmitted when the queue comes with 10 characters +** of being empty. +** fPeChar - Indicates that characters received with parity errors +** are to be replaced with the character specified in +** PeChar, below. +** fNull - Indicates that received NULL characters are to be +** discarded. +** fChEvt - Indicates that the reception of EvtChar is to be +** flagged as an event by cevt. +** fDtrFlow - Indicates that the DTR signal is to be used for +** receive flow control. (cextfcn can be used to set and +** clear DTR, overriding this definition). +** fRtsFlow - Indicates that the RTS signal is to be used for +** receive flow control. (cextfcn can be used to set and +** clear RTS, overriding this definition). +** XonChar - X-ON character for both transmit and receive +** XoffChar - X-OFF character for both transmit and receive +** XonLim - When the number of characters in the receive queue +** drops below this value, then an X-ON character is +** sent, if enabled, and DTR is set, if enabled. +** XoffLim - When the number of characters in the receive queue +** exceeds this value, then an X-OFF character is sent, +** if enabled, and DTR is dropped, if enabled. +** PeChar - Parity Error replacement character. +** EvtChar - Character which triggers an event flag. +** EofChar - Character which specifies end of input. +** TxDelay - Specifies the minimum amount of time that must pass +** between transmission of characters. +** +** Timeouts are in milleseconds. 0 means ignore the signal. 0xffff means +** infinite timeout. +** +*************************************************************************/ +typedef struct { + char Id; /* Internal Device ID */ + ushort BaudRate; /* Baudrate at which runing */ + char ByteSize; /* Number of bits/byte, 4-8 */ + char Parity; /* 0,1,2,3,4 = None,Odd,Even,Mark,Sp*/ + char StopBits; /* 0,1,2 = 1, 1.5, 2 */ + ushort RlsTimeout; /* Timeout for RLSD to be set */ + ushort CtsTimeout; /* Timeout for CTS to be set */ + ushort DsrTimeout; /* Timeout for DSR to be set */ + + uchar fBinary: 1; /* CTRL-Z as EOF flag */ + uchar fRtsDisable:1; /* Suppress RTS */ + uchar fParity: 1; /* Enable parity check */ + uchar fOutxCtsFlow: 1; /* Enable output xon/xoff with cts */ + uchar fOutxDsrFlow: 1; /* Enable output xon/xoff with dsr */ + uchar fDummy: 3; + + uchar fOutX: 1; /* Enable output X-ON/X-OFF */ + uchar fInX: 1; /* Enable input X-ON/X-OFF */ + uchar fPeChar: 1; /* Enable Parity Err Replacement */ + uchar fNull: 1; /* Enable Null stripping */ + uchar fChEvt: 1; /* Enable Rx character event. */ + uchar fDtrflow: 1; /* Enable DTR flow control */ + uchar fRtsflow: 1; /* Enable RTS flow control */ + uchar fDummy2: 1; + + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + ushort XonLim; /* Transmit X-ON threshold */ + ushort XoffLim; /* Transmit X-OFF threshold */ + char PeChar; /* Parity error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Recieved Event character */ + ushort TxDelay; /* Amount of time between chars */ + } DCB; + +/************************************************************************* +** +** COMSTAT +** Status record returned by GetCommError +** +*************************************************************************/ +typedef struct { + uchar fCtsHold: 1; /* Transmit is on CTS hold */ + uchar fDsrHold: 1; /* Transmit is on DSR hold */ + uchar fRlsdHold: 1; /* Transmit is on RLSD hold */ + uchar fXoffHold: 1; /* Transmit is on X-Off hold */ + uchar fXoffSent: 1; /* Recieve in X-Off or DTR hold */ + uchar fEof: 1; /* End of file character found */ + uchar fTxim: 1; /* Character being transmitted */ + uchar fPerr:1; /* Printer error */ /*081985*/ + ushort cbInQue; /* count of characters in Rx Que*/ + ushort cbOutQue; /* count of characters in Tx Que*/ + } COMSTAT; + +/************************************************************************* +** +** DCB field definitions. +** +*************************************************************************/ +#define NOPARITY 0 +#define ODDPARITY 1 +#define EVENPARITY 2 +#define MARKPARITY 3 +#define SPACEPARITY 4 + +#define ONESTOPBIT 0 +#define ONE5STOPBITS 1 +#define TWOSTOPBITS 2 + +#define IGNORE 0 /* Ignore signal */ +#define INFINITE 0xffff /* Infinite timeout */ + +/************************************************************************* +** +** Comm Device Driver Error Bits. +** +*************************************************************************/ +#define CE_RXOVER 0x0001 /* Receive Queue overflow */ +#define CE_OVERRUN 0x0002 /* Receive Overrun Error */ +#define CE_RXPARITY 0x0004 /* Receive Parity Error */ +#define CE_FRAME 0x0008 /* Receive Framing error */ +#define CE_CTSTO 0x0020 /* CTS Timeout */ +#define CE_DSRTO 0x0040 /* DSR Timeout */ +#define CE_RLSDTO 0x0080 /* RLSD Timeout */ +#define CE_PTO 0x0100 /* LPTx Timeout */ /*081985*/ +#define CE_IOE 0x0200 /* LPTx I/O Error */ /*081985*/ +#define CE_DNS 0x0400 /* LPTx Device not selected */ /*081985*/ +#define CE_OOP 0x0800 /* LPTx Out-Of-Paper */ /*081985*/ +#define CE_MODE 0x8000 /* Requested mode unsupported */ + +/************************************************************************* +** +** Initialization Error Codes +** +*************************************************************************/ +#define IE_BADID -1 /* Invalid or unsupported id */ +#define IE_OPEN -2 /* Device Already Open */ +#define IE_NOPEN -3 /* Device Not Open */ +#define IE_MEMORY -4 /* Unable to allocate queues */ +#define IE_DEFAULT -5 /* Error in default parameters */ +#define IE_HARDWARE -10 /* Hardware Not Present */ +#define IE_BYTESIZE -11 /* Illegal Byte Size */ +#define IE_BAUDRATE -12 /* Unsupported BaudRate */ +/************************************************************************* +** +** Event mask definitions. Used by SetCommEventMask and GetCommEventMask +** +** RXCHAR - Set when any character is received and placed in the input +** queue. +** RXFLAG - Set when a particular character, as defined in the dcb, is +** received and placed in the input queue. +** TXEMPTY - Set when the last character in the transmit queue is +** transmitted. +** CTS - Set when the CTS signal changes state. +** DSR - Set when the DSR signal changes state. +** RLSD - Set when the RLSD signal changes state. +** BREAK - Set when a break is detected on input. +** ERR - Set when a line status error occurs. +** +*************************************************************************/ +#define EV_RXCHAR 0x0001 /* Any Character received */ +#define EV_RXFLAG 0x0002 /* Received certain character */ +#define EV_TXEMPTY 0x0004 /* Transmitt Queue Empty */ +#define EV_CTS 0x0008 /* CTS changed state */ +#define EV_DSR 0x0010 /* DSR changed state */ +#define EV_RLSD 0x0020 /* RLSD changed state */ +#define EV_BREAK 0x0040 /* BREAK received */ +#define EV_ERR 0x0080 /* Line Status Error Occurred */ +#define EV_RING 0x0100 /* Ring signal detected */ +#define EV_PERR 0x0200 /* LPTx error occured */ /*081985*/ + +/************************************************************************* +** +** Extended Functions +** +** SETXOFF - Causes transmit to behave as if an X-OFF character had +** been received. Valid only if transmit X-ON/X-OFF specified +** in the dcb. +** SETXON - Causes transmit to behave as if an X-ON character had +** been received. Valid only if transmit X-ON/X-OFF specified +** in the dcb. +*************************************************************************/ +#define SETXOFF 1 /* Set X-Off for output control */ +#define SETXON 2 /* Set X-ON for output control */ +#define SETRTS 3 /* Set RTS high */ +#define CLRRTS 4 /* Set RTS low */ +#define SETDTR 5 /* Set DTR high */ +#define CLRDTR 6 /* Set DTR low */ +#define RESETDEV 7 /* Reset device if possible */ /*081985*/ diff --git a/private/mvdm/wow16/drivers/comm/comdev.inc b/private/mvdm/wow16/drivers/comm/comdev.inc new file mode 100644 index 000000000..1238c6b62 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/comdev.inc @@ -0,0 +1,103 @@ +;========================================================================= +; Communications Device Driver Definitions - September, 1985 +;========================================================================= + +.xcref + +WIN31 = 1 +; remove unneeded things in Windows.inc +NOGDICAPMASKS = 1 +NOVK = 1 +NOWH = 1 +NOMST = 1 +NORASTOPS = 1 +NOMETAFILE = 1 +NOMDI = 1 +NOWINMESSAGES = 1 +NOSYSMETRICS = 1 +NOCOLOR = 1 +include windows.inc + +DCBSize equ SIZE DCB +DCB_Flags equ byte ptr DCB_BitMask1 +DCB_Flags2 equ byte ptr DCB_BitMask2 + +LPTx equ 10000000b ;Flags an ID as being an LPT port + + +; DCB_BitMask1 (DCB_Flags) equates + +fBinary equ 00000001b ;Binary mode +fRTSDisable equ 00000010b ;Disable RTS +fParity equ 00000100b ;Perform Parity Checking +fOutXCTSFlow equ 00001000b ;Output handshaking using CTS +fOutXDSRFlow equ 00010000b ;Output handshaking using DSR +fEnqAck equ 00100000b ;ENQ/ACK software handshaking [rkh] ... +fEtxAck equ 01000000b ;ETX/ACK software handshaking +fDTRDisable equ 10000000b ;Disable DTR + + +; DCB_BitMask2 (DCB_Flags2) equates + +fOutX equ 00000001b ;Output X-ON/X-OFF +fInX equ 00000010b ;Input X-ON/X-OFF +fPErrChar equ 00000100b ;Parity Error Replacement char active +fNullStrip equ 00001000b ;Null Stripping +fCharEvent equ 00010000b ;Character event +fDTRFlow equ 00100000b ;Input handshaking using DTR +fRTSFlow equ 01000000b ;Input handshaking using RTS +; equ 10000000b + + +; Values for RLSTimeout, CTSTimeout, DSRTimeout + +Ignore equ 0 +Infinite equ 0FFFFh + + +; COMS_BitMask1 equates + +fCTSHold equ 00000001b ;Tx is on CTS hold +fDSRHold equ 00000010b ;Tx is on DSR hold +fRLSDHold equ 00000100b ;Tx is on RLSD hold +fXOFFHold equ 00001000b ;Received an X-OFF +fXOFFSent equ 00010000b ;Sent an X-OFF +fEOF equ 00100000b ;Received defined EOF character +fTxImmed equ 01000000b ;There's a char to transmit immediate +; equ 10000000b + + + +; Event mask definitions. Used by SetCommEventMask and GetCommEventMask +; +; RXCHAR - Set when any character is received and placed in the input +; queue. +; RXFLAG - Set when a particular character, as defined in the DCB, +; is received and placed in the input queue. +; TXEMPTY - Set when the last character in the transmit queue is +; transmitted. +; CTS - Set when the CTS signal changes state. +; DSR - Set when the DSR signal changes state. +; RLSD - Set when the RLSD signal changes state. +; BREAK - Set when a break is detected on input. +; RING - Set when Ring Indicator is detected +; ERR - Set when a line status error occurs. + + +;========================================================================= +; +; qdb +; Queue definition block. Passed to setqueue, defines the location and +; size of the transmit and receive circular queue's used for interrupt +; transmit and recieve processing. +; +;========================================================================= + +QDB struc + QueueRxAddr dd ? ;Pointer to RX Queue, Offset + QueueRxSize dw ? ;Size of RX Queue in bytes + QueueTxAddr dd ? ;Pointer to TX Queue, Offset + QueueTxSize dw ? ;Size of TX Queue in bytes +QDB ends + +.cref diff --git a/private/mvdm/wow16/drivers/comm/comdevi.h b/private/mvdm/wow16/drivers/comm/comdevi.h new file mode 100644 index 000000000..f640125c2 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/comdevi.h @@ -0,0 +1,28 @@ +/************************************************************************* +** +** qdb +** que definition block. +** +*************************************************************************/ +typedef struct { + char far *pqRx; /* pointer to rx queue */ + short cbqRx; /* size of RX Queue in bytes */ + char far *pqTx; /* Pointer to TX Queue */ + short cbqTx; /* Size of TX Queue in bytes */ + } qdb; + +ushort far pascal inicom(DCB far *); +ushort far pascal setcom(DCB far *); +void far pascal setque(); +int far pascal reccom(); +ushort far pascal sndcom(); +ushort far pascal ctx(); +short far pascal trmcom(); +ushort far pascal stacom(); +ushort far pascal cextfcn(); +ushort far pascal cflush(); +ushort far *far pascal cevt(); +ushort far pascal cevtGet(); +int far pascal csetbrk(); +int far pascal cclrbrk(); +DCB far *far pascal getdcb(); diff --git a/private/mvdm/wow16/drivers/comm/comm.def b/private/mvdm/wow16/drivers/comm/comm.def new file mode 100644 index 000000000..99b887da8 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/comm.def @@ -0,0 +1,42 @@ +LIBRARY COMM + +DESCRIPTION 'Windows Communications Driver' + +EXETYPE WINDOWS +STUB '..\..\bin\WINSTUB.EXE' + +DATA PRELOAD FIXED SINGLE + +SEGMENTS + _INIT PRELOAD MOVEABLE DISCARDABLE SHARED + _TEXT MOVEABLE DISCARDABLE SHARED + _INTERRUPT PRELOAD FIXED SHARED + + +EXPORTS + inicom @1 + setcom @2 + setque @3 + reccom @4 + sndcom @5 + ctx @6 + trmcom @7 + stacom @8 + cextfcn @9 + cflush @10 + cevt @11 + cevtGet @12 + csetbrk @13 + cclrbrk @14 + getdcb @15 +; mapdevname @16 ;Reserved for mapping dev to cid + SuspendOpenCommPorts @17 ;for 286 winoldaps only + ReactivateOpenCommPorts @18 ;for 286 winoldaps only + CommWriteString @19 ; for fast lpt output + ReadCommString @20 ; for fast input + EnableNotification @100 + WEP + +IMPORTS + CreateSystemTimer = SYSTEM.2 + GetSystemMsecCount = SYSTEM.6 diff --git a/private/mvdm/wow16/drivers/comm/comm.rc b/private/mvdm/wow16/drivers/comm/comm.rc new file mode 100644 index 000000000..fabcbab37 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/comm.rc @@ -0,0 +1,4 @@ +/********************************************************************/ +/* COMM.RC */ +/********************************************************************/ +#include "comm.rcv" diff --git a/private/mvdm/wow16/drivers/comm/comm.rcv b/private/mvdm/wow16/drivers/comm/comm.rcv new file mode 100644 index 000000000..ea8edd8c4 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/comm.rcv @@ -0,0 +1,12 @@ +/********************************************************************/ +/* COMM.RCV */ +/********************************************************************/ +#include <version.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_COMM +#define VER_FILEDESCRIPTION_STR "Windows COMM Driver" +#define VER_INTERNALNAME_STR "COMM" +#define VER_ORIGINALFILENAME_STR "COMM.DRV" + +#include <common.ver> diff --git a/private/mvdm/wow16/drivers/comm/commmsg.asm b/private/mvdm/wow16/drivers/comm/commmsg.asm new file mode 100644 index 000000000..8980166dc --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/commmsg.asm @@ -0,0 +1,51 @@ +.xlist +include cmacros.inc +.list + + +sBegin Data + +PUBLIC szMessage, pLPTByte +PUBLIC szCOMMessage, pCOMByte +PUBLIC _szTitle + +szMessage db 'The LPT' +pLPTByte db '?' + db ' port is currently assigned to a DOS application. Do you ' + db 'want to reassign the port to Windows?',0 +szCOMMessage db 'The COM' +pCOMByte db '?' + db ' port is currently assigned to a DOS application. Do you ' + db 'want to reassign the port to Windows?',0 +_szTitle db 'Device Conflict',0 + +PUBLIC lpCommBase, CommBaseX +lpCommBase db 'COM' +CommBaseX db ? + db 'BASE', 0 + +PUBLIC lpCommIrq, CommIrqX +lpCommIrq db 'COM' +CommIrqX db ? + db 'IRQ', 0 + +PUBLIC lpCommFifo, CommFifoX +lpCommFifo db 'COM' +CommFifoX db ? + db 'FIFO', 0 + +PUBLIC lpCommDSR, CommDSRx +lpCommDSR db 'COM' +CommDSRx db ? + db 'FORCEDSR', 0 + +PUBLIC lpCommSection, lpSYSTEMINI + +lpCommSection db '386ENH', 0 +lpSYSTEMINI db 'SYSTEM.INI', 0 + + ALIGN 2 + +sEnd Data + +End diff --git a/private/mvdm/wow16/drivers/comm/ddkmake b/private/mvdm/wow16/drivers/comm/ddkmake new file mode 100644 index 000000000..f148215e4 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/ddkmake @@ -0,0 +1,47 @@ +# International mods +# NOTE: LANG is a external macros set by international +!IFNDEF LANG +RES_DIR=.\messages\usa +!ELSE +RES_DIR=.\messages\$(LANG) +!ENDIF + +# +# Standard command line definitions +# +OPT= /W2 #NOP the options feature +as=masm +MASMOBJ=$(as) $(OPT) +# +# DOS 3.x inference rules +# +.asm.obj: + $(MASMOBJ) $*.asm; + +.asm.lst: + $(as) $(OPT) /l $*.asm; + +comm: comm.drv + +ccom.obj ccom.lst: ccom.asm ibmcom.inc comdev.inc + +ibmsetup.obj ibmsetup.lst: ibmsetup.asm ibmcom.inc comdev.inc ins8250.inc + +ibmcom.obj: ibmcom.asm ibmcom.inc comdev.inc ins8250.inc + +ibmint.obj: ibmint.asm ibmcom.inc comdev.inc ins8250.inc + +ibmlpt.obj: ibmlpt.asm ibmcom.inc comdev.inc + +commmsg.obj: $(RES_DIR)\commmsg.asm + $(MASMOBJ) $(RES_DIR)\commmsg.asm, commmsg.obj; + +comm.drv: iclean ccom.obj ibmsetup.obj ibmcom.obj ibmint.obj ibmlpt.obj commmsg.obj \ + comm.def comm.rc comm.rcv + link ccom+ibmsetup+ibmcom+ibmint+ibmlpt+commmsg,comm.drv,comm.map/map,libw /NOD /AL:16,comm.def + rc comm.rc comm.drv + mapsym comm + +iclean: + del comm.drv + del commmsg.obj diff --git a/private/mvdm/wow16/drivers/comm/ibmcom.asm b/private/mvdm/wow16/drivers/comm/ibmcom.asm new file mode 100644 index 000000000..653726cf1 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/ibmcom.asm @@ -0,0 +1,1947 @@ +page,132 +;---------------------------Module-Header-------------------------------; +; Module Name: IBMCOM.ASM +; +; !!! +; +; Created: Fri 06-Feb-1987 10:45:12 +; Author: Walt Moore [waltm] +; +; Copyright (c) Microsoft Corporation 1985-1990. All Rights Reserved. +; +; General Description: +; +; History: +; +; *************************************************************** +; Tue Dec 19 1989 09:32:15 -by- Amit Chatterjee [amitc] +; --------------------------------------------------------------- +; Modified the 'InitAPort' routine called from 'ReactivateOpenCommPort'. +; If the out queue for a port has characters to send out then we must +; restart the trasmission process by faking a comm interrupt on that +; port. +; *************************************************************** +; Tue Nov 21 1989 09:46:50 -by- Amit Chatterjee [amitc] +; --------------------------------------------------------------- +; The base port addresses in the COMM1,COMM2,COMM3,COMM4 structures +; are being zeroed out when the corresponding comm port is closed. +; This is because the 'ReactivateOpenCommPort' function looks at it +; and if the port address is not zero decides that comm ports are +; open. +; *************************************************************** +; Tue Nov 14 1989 18:42:00 ADDED TWO EXPORTED FUNCTIONS +; --------------------------------------------------------------- +; Added two exported functions 'SuspendOpenCommPorts' and +; 'ReactivateOpenCommPorts' for 286 winoldap support. The first one simply +; releases the comm int vects and installs the originall one, the second one +; hooks back the comm driver comm vectors and then reads the receive buffer, +; the status and the IIR registers of all the available comm ports to +; remove pending interrupts. It also reprograms the PIC to enable interrupts +; on all open comm channels. +; --------------------------------------------------------------- +; -by- Amit Chatterjee [amitc] +; *************************************************************** +; Tue Aug 30 198? 12:52:00 MAJOR FIX TO HANDLE 8250B +; --------------------------------------------------------------- +; +; 8250B has the following peculiar charactersistic +; . The very first time (after reset) the Tx Holding Empty +; interrupt is enabled, an immediate interrupt is generated +; +; . After the first time, switching the Tx Holding Empty +; interrupt enable bit from disabled to enabled will NOT +; generate an immediate interrupt (unlike in 8250) +; Because of this the KICKTX routine fails to set the transmit cycle +; on if the machine has a 8250B +; +; This has been taken care as follows: +; . For the very first byte that is being transmitted, KICKTX +; is used to generate the first Tx Holding Empty interrupt +; . Subsequently, whenever we find that the transmit buffer +; is empty, we use a SOFTWARE INT (either INT 0Bh, or INT 0Ch) +; to force the first character out, once this is done the +; Tx Holding Empty interrupt will be generated once the buffer +; really is empty +; . Now we no longer disable the Tx Holding Empty interrupt +; in the Xmit ISR to ensure that even m/cs with 8250, use +; the software int to kick the tx interrupt on after the +; first time. +; . The software interrupt is also forced whenever an X-ON +; character is received. +; +; The code that implements the above logic is marked out with a line +; asterixes. +; ------------------------------------------------------------------ +; -by- Amit Chatterjee [amitc] +; ****************************************************************** +; +; 062587 HSFlag and Evtmask in DoLPT. These fields do not exist +; for LPT type devices. The code which manipulated them +; was removed +; +; KickTx from $SndCom - interrupts were not disabled when +; calling KickTx. +; +; $SetCom - added CLD at the start +; +; $SetQue - movsw ==> stosw +; +; 111285 Changed the Timeout from 7 to 30 seconds. +; +; 110885 Forgot to set EV_RxChar event when a character +; was received. +; +; 102985 INS8250, INS8250B bug with enabling interrupts. +; Setting ACE_ETBEI in the Interrupt Enable Register +; will cause an immediate interrupt regardless of +; whether the transmitter register is empty or not. +; The first interrupt MAY also be missed. +; +; The first case is not a problem since we only enable +; interrupts if the transmitter register is empty. The +; second problem was showing up on Microsoft System Cards +; in PC-XTs. The first interrupt was missed after a cold +; boot. National claims the fix is to write the register +; twice, which SEEMS to work... +; +; Added timeout code to $TRMCOM. If the number of +; characters in the output queue doesn't decrease +; in "Timeout" seconds, then the port will be closed +; anyway. Also flushed the input queue and added a +; discard-input flag for the data available interrupt +; code to discard any input received while terminating +; a port. $TRMCOM will return an error code if it +; discarded any output data. +; +; Removed infinite timeout test in MSRWait routine. +; Still bad, but it will timeout around 65 seconds +; instead of never. +; +; 102785 LPT initialization code was jumping to InitCom90, +; which was setting EFlags[si] to null. Well, LPTs +; don't have an EFlags field, so the null was getting +; stuffed over the LSB of BIOSPortLoc of the next LPT +; device. +; +; 101185 Save interrupt vector when opening a comm port +; and restore it when closing. Would you believe +; there are actually programs that assume the +; vector points to a non-specific 8259 ACK and +; an IRET! +; +; 100985 Added MS-NET support to gain exclusive control +; of an LPT port if DOS 3.x and not running in as +; a server, receiver, or messenger. Required to +; keep another application, such as command.com +; from closing the stream or mixing their output +; with ours. +; sudeepb 10-Jan-1993 changed the costly cli/sti with non-trapping +; FCLI/FSTI macros +;-----------------------------------------------------------------------; + +title IBMCom - IBM PC, PC-XT, PC-AT, PS/2 Communications Interface + +.xlist +include cmacros.inc +include comdev.inc +include ins8250.inc +include ibmcom.inc +include vint.inc +.list + +externNP GetDEB +externNP DoLPT +externNP StringToLPT +externNP FindCOMPort +externNP StealPort + + +sBegin Data + +externB $MachineID + +sEnd Data + +sBegin Code +assumes cs,Code +assumes ds,Data + +page + +;----------------------------Public Routine-----------------------------; +; +; $RECCOM - Receive Characters From Device +; +; Read Byte From RS232 Input Queue If Data Is Ready +; +; LPT ports will return with an indication that no characters are +; available. +; +; Entry: +; AH = Device ID +; Returns: +; 'Z' clear if data available +; AL = byte +; Error Returns: +; 'Z' Set if error or no data +; AX = error code +; AX = 0 if no data +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $RECCOM +$RECCOM proc near + + push si ;Once again, save some registers + push di + call GetDEB ;Get DEB pointer in SI + jc RecCom10 ;Invalid Port [rkh] ... + jns RecCom20 ;COM port + jmp RecCom95 ;LPT port, return no characters + +RecCom10: + jmp RecCom100 ; Invalid Port + +; Before removing any charcters from the input queue, check to see +; if XON needs to be issued. If it needs to be issued, set the +; flag that will force it and arm transmit interrupts. + +RecCom20: + test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack? + jz RecCom32 ; No + test HSFlag[si],EnqReceived+HHSDropped ;Enq recvd or lines dropped? + jnz RecCom21 ; No Enq recvd & no lines dropped + jmp RecCom60 ; No Enq recvd & no lines dropped +RecCom21: + jmp short RecCom34 + +RecCom32: + test HSFlag[si],HSSent ;Handshake sent? + jnz RecCom33 ; No XOFF sent & no lines dropped + jmp RecCom60 ; No XOFF sent & no lines dropped +RecCom33: + +RecCom34: + mov ax,QInCount[si] ;Get current count of input chars + cmp ax,[si.DCB_XonLim] ;See if at XOn limit + ja RecCom60 ;Not at XOn limit yet + +; If any hardware lines are down, then raise them. Then see +; about sending XON. + + mov dx,Port[si] ;Get the port + mov ah,HHSLines[si] ;Get hardware lines mask + call DOCLI ;Handle this as a critical section + mov cl,HSFlag[si] ;Get handshaking flags + or ah,ah ;Any hardware lines to play with? + jz RecCom40 ; No + add dl,ACE_MCR ;--> Modem control register + in al,dx + or al,ah ;Turn on the hardware bits + iodelay + out dx,al + and cl,NOT HHSDropped ;Show hardware lines back up + +RecCom40: + test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack? + jz RecCom47 ; No + test cl,EnqReceived ;Did we receive Enq? + jz RecCom55 ; No + and cl,NOT EnqReceived + jmp short RecCom50 + +RecCom47: + test cl,XOffSent ;Did we send XOFF? + jz RecCom55 ; No + and cl,NOT XOffSent ;Remove XOFF sent flag + +RecCom50: + or cl,XOnPending ;Show XON or ACK must be sent + call KickTx ;Kick xmit if needed + +RecCom55: + mov HSFlag[si],cl ;Store handshake flag + call DOSTI ;Can allow interrupts now + +; Now we can get down to the business at hand, and remove a character +; from the receive queue. If a communications error exists, we return +; that, and nothing else. + +RecCom60: + xor ax,ax + or ax,ComErr[si] ;Any Errors? + jnz RecCom100 ; Yes, return the error code + or ax,QInCount[si] ;Get current input char count + jz RecCom90 ;No characters in the queue + les di,QInAddr[si] ;Get queue pointer + assumes es,nothing + + mov bx,QInGet[si] ;Also get the index to head + mov al,es:[bx][di] ;Finally, get byte from queue + inc bx ;Update queue index + cmp bx,QInSize[si] ;See if time for wrap-around + jc RecCom70 ;Jump if no wrap + xor bx,bx ;wrap by zeroing the index + +RecCom70: + mov QInGet[si],bx ;Save new head pointer + dec QInCount[si] ;Dec # of bytes in queue + + mov cx, [si.QinCount] + cmp cx, [si.RecvTrigger] ;Q: have we read below trigger? + jae RecCom80 ; N: + and [si.NotifyFlagsHI], NOT CN_RECEIVE ; allow timeout notify again +RecCom80: + or sp,sp ;Reset PSW.Z + pop di + pop si + ret + +; No characters in the input queue. Check to see if EOF +; was received, and return it if it was. Otherwise show +; no characters. + +RecCom90: + test [si.DCB_Flags],fBinary ;Are we doing binary stuff? + jnz RecCom95 ; Yes, show no characters + mov al,[si.DCB_EofChar] ;Assume EOF + test EFlags[si],fEOF ;Has end of file char been received? + jnz RecCom80 ; Yes, show end of file + +RecCom95: + xor ax,ax ;Show no more characters + +; Return with 'Z' to show error or no characters + +RecCom100: + xor cx,cx ;Set PSW.Z + pop di + pop si + ret + +$RECCOM endp +page + +;----------------------------Public Routine-----------------------------; +; +; $RECSTR - Receive Characters From Device +; +; Read Byte From RS232 Input Queue If Data Is Ready +; +; LPT ports will return with an indication that no characters are +; available. +; +; Entry: +; AH = Device ID +; ES:DI -> receive buffer +; CX max bytes to read +; Returns: +; 'Z' clear if data available +; AX = # of bytes read +; Error Returns: +; 'Z' Set if error or no data +; AX = error code +; AX = 0 if no data +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $RECSTR +$RECSTR proc near + + push si ;Once again, save some registers + push di + call GetDEB ;Get DEB pointer in SI + jc RecStr10 ;Invalid Port [rkh] ... + jns RecStr20 ;COM port + jmp RecStr95 ;LPT port, return no characters + +RecStr10: + jmp RecStr100 ; Invalid Port +RecStr15: + jmp RecStr90 + +RecStr20: + xor ax,ax + or ax,ComErr[si] ;Any Errors? + jnz RecStr10 ; Yes, return the error code + or ax,QInCount[si] ;Get current input char count + jz RecStr15 ;No characters in the queue + + cmp cx, ax ;Q: more chars available than can read? + jbe short RecStr30 ; N: + mov cx, ax ; Y: adjust # of chars to read +RecStr30: + push cx + mov dx, QInSize[si] + mov ax, QInGet[si] + sub dx, ax ; dx = # of bytes before end of buf + cmp dx, cx ;Q: more avail than can read? + jbe short RecStr40 ; N: + mov dx, cx ; Y: adjust avail count +RecStr40: + xchg cx, dx ; cx = # of bytes for 1st copy + sub dx, cx ; dx = # of bytes for 2nd copy + + push ds + push si + lds bx, QInAddr[si] + mov si, bx + add si, ax ; ds:si -> first char in buffer + cld + rep movsb ; do first copy + mov cx, dx + jcxz short RecStr50 ; jump if no 2nd copy needed + mov si, bx ; ds:si -> start of buffer + rep movsb ; do 2nd copy +RecStr50: + sub si, bx ; si = new QInGet + mov bx, si + pop si + pop ds + pop cx + call DOCLI + mov QInGet[si], bx ; update QInGet + sub QInCount[si], cx ; update count + mov ax, QInCount[si] + call DOSTI + + cmp ax, [si.RecvTrigger] ;Q: have we read below trigger? + jae @F ; N: + and [si.NotifyFlagsHI], NOT CN_RECEIVE ; allow timeout notify again +@@: + +; Check to see if XON needs to be issued. If it needs to be issued, set the +; flag that will force it and arm transmit interrupts. + + test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack? + jz @F ; No + test HSFlag[si],EnqReceived+HHSDropped ;Enq recvd or lines dropped? + jnz RecStr58 ; No Enq recvd & no lines dropped + jmp RecStr80 ; No Enq recvd & no lines dropped +RecStr58: + jmp short RecStr60 + +@@: + test HSFlag[si],HSSent ;Handshake sent? + jnz RecStr59 ; No XOFF sent & no lines dropped + jmp RecStr80 ; No XOFF sent & no lines dropped +RecStr59: + +RecStr60: + ;ax = current count of input chars + cmp ax,[si.DCB_XonLim] ;See if at XOn limit + ja RecStr80 ;Not at XOn limit yet + +;; int 1 +; If any hardware lines are down, then raise them. Then see +; about sending XON. + + mov dx,Port[si] ;Get the port + mov ah,HHSLines[si] ;Get hardware lines mask + push cx + call DOCLI ;Handle this as a critical section + mov cl,HSFlag[si] ;Get handshaking flags + or ah,ah ;Any hardware lines to play with? + jz @F ; No + add dl,ACE_MCR ;--> Modem control register + in al,dx + or al,ah ;Turn on the hardware bits + iodelay + out dx,al + and cl,NOT HHSDropped ;Show hardware lines back up + +@@: + test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack? + jz @F ; No + test cl,EnqReceived ;Did we receive Enq? + jz RecStr70 ; No + and cl,NOT EnqReceived + jmp short RecStr65 + +@@: + test cl,XOffSent ;Did we send XOFF? + jz RecStr70 ; No + and cl,NOT XOffSent ;Remove XOFF sent flag + +RecStr65: + or cl,XOnPending ;Show XON or ACK must be sent + call KickTx ;Kick xmit if needed + +RecStr70: + mov HSFlag[si],cl ;Store handshake flag + call DOSTI ;Can allow interrupts now + pop cx + +RecStr80: + mov ax, cx + or sp,sp ;Reset PSW.Z + pop di + pop si + ret + +; No characters in the input queue. Check to see if EOF +; was received, and return it if it was. Otherwise show +; no characters. + +RecStr90: + test [si.DCB_Flags],fBinary ;Are we doing binary stuff? + jnz RecStr95 ; Yes, show no characters + mov al,[si.DCB_EofChar] ;Assume EOF + test EFlags[si],fEOF ;Has end of file char been received? + jnz RecStr80 ; Yes, show end of file + +RecStr95: + xor ax,ax ;Show no more characters + +; Return with 'Z' to show error or no characters + +RecStr100: + xor cx,cx ;Set PSW.Z + pop di + pop si + ret + +$RECSTR endp +page + +;----------------------------Public Routine-----------------------------; +; +; $SNDIMM - Send A Character Immediately +; +; This routine either sends a character to the port immediately, +; or places the character in a special location which is used by +; the next transmit interrupt to transmit the character prior to +; those in the normal transmit queue. +; +; For LPT ports, the character is always sent immediately. +; +; Entry: +; AH = Device ID +; AL = Character +; Returns: +; AX = 0 +; Error Returns: +; AX = 8000H if Bad ID +; AX = 4000H if couldn't send because another character +; transmitted "immediately" is waiting to be sent +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + + + assumes ds,Data + assumes es,nothing + + public $SNDIMM +$SNDIMM proc near + + push si + call GetDEB ;Get pointer to the DEB + jc SendImm20 ;Bad ID, return an error + jns SendImm10 ;Its a COM port + + +; For LPT ports, call DoLPT to do the dirty work. If DoLPT +; returns an error code, map it to 4000h. + + xor ch,ch ;Show xmit character + call DoLPT ;Do the work here + or ax,ax ;Error occur? + jz SendImm20 ; No, show all is OK + mov ax,4000h ; Yes, return 4000h + jmp short SendImm20 + +SendImm10: + mov dl, al + mov ax,4000h ;In case we cannot send + test EFlags[si],fTxImmed ;Another char waiting "immediately"? + jnz SendImm20 ; Yes, return error + mov ah,dl ;Set char for TXI + call DOCLI ;TXI is critical section code + call TXI ;Set character to tx immediately + call DOSTI + xor ax,ax ;Show all is OK + +SendImm20: + pop si + ret + +$SNDIMM endp +page + +;----------------------------Public Routine-----------------------------; +; +; $SNDCOM - Send Byte To Port +; +; The given byte is sent to the passed port if possible. +; If the output queue is full, an error will be returned. +; +; Entry: +; AH = Device ID +; AL = Character +; Returns: +; AX = 0 +; Error Returns: +; AX = error code +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $SNDCOM +$SNDCOM proc near + + push si + push di + call GetDEB ;--> DEB + jc SendCom40 ;Invalid ID + jns SendCom20 ;Its a COM port + +; Handle the transmission of a LPT character. The ROM BIOS int 17 +; call will be made to do the transmission. The port address will +; be restored during the call, then zeroed out upon return. + +SendCom10: + xor ch,ch ;Show xmit character + call DoLPT ;Do the work here + jmp short SendCom40 ;Return the status to caller + +; Send a character to a COM port. Return an error if control +; line timeout occurs or there is no room in the output queue. + +SendCom20: + push ax ;Save character + + call MSRWait ;See if lines are correct for output + pop ax ;Restore char + jnz SendCom60 ;Timeout occured, return error + mov cx,QOutSize[si] ;See if queue is full + cmp cx,QOutCount[si] + jle SendCom50 ;There is no room in the queue + les di,QOutAddr[si] ;--> output queue + assumes es,nothing + + mov bx,QOutPut[si] ;Get index into queue + mov es:[bx][di],al ;Store the byte + inc bx ;Update index + cmp bx,cx ;Wrap time? + jc SendCom30 ; No + xor bx,bx ;Wrap-around is a new zero pointer + +SendCom30: + + call DOCLI + mov QOutPut[si],bx ;Store updated pointer + mov ax,QOutCount[si] ; get the count + inc ax ; have the updated value in AX for test later + mov QOutCount[si],ax ;Update queue population + call KickTx ;Make sure xmit interrupt is armed + call DOSTI + + xor ax,ax ;Show no error (that we know of) + +;**************************************************************************** + +SendCom40: + pop di + pop si + ret + +SendCom50: + or by ComErr+1[si],HIGH CE_TXFULL + .errnz LOW CE_TXFULL + +SendCom60: + mov ax,ComErr[si] ;Return error code to caller + jmp short SendCom40 + +$SNDCOM endp +page + +;----------------------------Public Routine-----------------------------; +; +; $SNDCOMSTR - Send buffer To Port +; +; The given buffer is sent to the passed port if possible. +; Once the output queue is detected as being full, a CE_TXFULL error +; will be indicated and AX will be returned as the # of chars actually +; queued. +; +; Entry: +; DS:SI --> DEB +; ES:DI --> buffer +; Returns: +; AX = # of bytes queued +; Registers Destroyed: +; AX,BX,CX,DX,DI,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $SNDCOMSTR +$SNDCOMSTR proc near + + push cx ; save count + call GetDEB + jc cws_error ; jump if id invalid + jns cws_comm ; jump if COM port + + call StringToLPT + pop cx ; discard saved count, ax = # transfered + jmp short cws_exit + +cws_error: + pop ax + sub ax, cx ; ax = # transfered +cws_exit: + ret + +cws_comm: + call MSRWait ;See if lines are correct for output + pop cx + push cx + jnz cws_error ;Timeout occured, return error + + mov dx, QOutSize[si] ;See if queue is full + sub dx, QOutCount[si] ; dx = # of chars free in queue + jg scs_loop + jmp scs_full ;There is no room in the queue + +scs_loop: + push cx ; save count left to send + cmp cx, dx ;Q: room for buffer in queue? + jbe @f ; Y: + mov cx, dx ; N: adjust size to send +@@: + push cx ; save # of chars which will be copied + push si + push ds + push di + push es + les bx,QOutAddr[si] ;--> output queue + assumes es,nothing + + mov dx, QOutSize[si] + mov di, QOutPut[si] ;Get index into queue + sub dx, di ; dx = # of free chars before end of queue + cmp dx, cx + jbe @f + mov dx, cx +@@: + xchg cx, dx ; cx = # of chars for 1st copy + sub dx, cx ; dx = # of chars for 2nd copy + pop ds + pop si ; ds:si -> src buffer + assumes ds,nothing + add di, bx ; es:di -> current pos in queue + cld + rep movsb ; copy first section + mov cx, dx + jcxz @F + mov di, bx ; circle back to start of queue + rep movsb ; copy 2nd section +@@: + sub di, bx ; di last index into queue + mov dx, di + mov di, si ; last location in src buffer + mov si, ds + mov es, si ; es:di -> last loc in src buf + pop ds + pop si ; ds:si -> ComDEB + assumes ds,data + pop bx ; # of chars copied + call DOCLI + mov QOutPut[si], dx ;new index into queue + add QOutCount[si], bx + call KickTx + call DOSTI + pop cx + sub cx, bx ; # of chars left to send + jnz scs_full_2 ; jump if none +scs_exit: + pop ax + sub ax, cx ; ax = # transfered + ret + +scs_full: + call DOCLI + call KickTx + call DOSTI +scs_full_2: + or by ComErr+1[si],HIGH CE_TXFULL + .errnz LOW CE_TXFULL + jmp scs_exit + +$SNDCOMSTR endp +page + +;----------------------------Public Routine-----------------------------; +; +; $FLUSH - Flush The Input and Output Queues +; +; This is a hard initialization of the transmit and receive queue's, +; which immediately empties the given queue. +; +; LPT ports will just return the device error word +; +; Entry: +; AH = Device ID +; BH = Queue # to clear (0=Tx, 1=Rx) +; Returns: +; AX = Device Error Word. (Not reset) +; Error Returns: +; AX = error code +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public $FLUSH +$FLUSH proc near + + push si + push di + call GetDEB ;si --> DEB + jc Flush40 ;Invalid ID + js Flush30 ;LPT port, return any error + + mov cx,QOutCount-QInCount ;# of bytes to zero + lea di,QInCount[si] ;--> receive queue data + or bh,bh ;Transmit queue? + jnz Flush10 ; No, input queue + add di,cx ; Yes, --> xmit queue data + +Flush10: + cld + push ds + pop es + assumes es,nothing + + xor al,al + call DOCLI ;Time to worry about critical sections + rep stosb + call DOSTI + .errnz QInGet-QInCount-2 + .errnz QInPut-QInGet-2 + .errnz QOutCount-QInPut-2 + .errnz QOutGet-QOutCount-2 + .errnz QOutPut-QOutGet-2 + + or bh,bh ;Rx queue? + jz Flush30 ; No, xmit queue + + +; If the queue to be cleared is the receive queue, any +; hardware handshake must be cleared to prevent a possible +; deadlock situation. Since we just zeroed the queue count, +; a quick call to $RecCom should do wonders to clear any +; receive handshake (i.e. send XON if needed). + +Flush20: + call $RECCOM ;Take care of handshakes here + +Flush30: + mov ax,ComErr[si] ;And return the error word. + +Flush40: + pop di + pop si + ret + +$FLUSH endp +page + +;----------------------------Private-Routine----------------------------; +; +; TXI - Transmit A Character Immediately +; +; Set up a character to be transmitted "immediately". +; by placing the character in a location that guarantees +; it to be the next character transmitted. +; +; The check to see if the immediate character can be placed has +; already been made prior to entry. +; +; Interrupts must be disabled before entering this code +; +; Entry: +; AH = Character +; DS:SI --> DEB +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; BX,CX,SI,DI,DS,ES +; Registers Destroyed: +; L,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public TXI ;Public for debugging +TXI proc near + +; call DOCLI ;Must be done by caller! + or EFlags[si],fTxImmed ;Show char to xmit + mov ImmedChar[si],ah ;Set character to transmit next +; jmp short KickTx ;Kick Xmit just in case + errn$ KickTx + +TXI endp +page + +;----------------------------Private-Routine----------------------------; +; +; KickTx - Kick Transmitter +; +; "Kick" the transmitter interrupt routine into operation. +; If the Transmitter Holding Register isn't empty, then +; nothing needs to be done. If it is empty, then the xmit +; interrupt needs to enabled in the IER. +; +; Entry: +; DS:SI --> DEB +; INTERRUPTS DISABLED! +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; BX,CX,SI,DI,DS,ES +; Registers Destroyed: +; AX,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public KickTx ;Public for debugging +KickTx proc near + +; call DOCLI ;Done by caller + test [si.VCDflags], 1 ;Q: we still own port? + jnz can_we_steal ; N: + +enable_int: + mov dx,Port[si] ;Get device I/O address + add dl,ACE_IER ;--> Interrupt enable register + in al,dx ;Get current IER state + test al,ACE_ETBEI ;Interrupt already enabled? + jnz KickTx10 ; Yes, don't reenable it + or al,ACE_ETBEI ; No, enable it + out dx,al + iodelay ;8250, 8250-B bug requires + out dx,al ; writting register twice + +KickTx10: +; call DOSTI ;Done by caller + ret + +can_we_steal: + call StealPort ; call VCD to see if we can steal + ; the port back + jnc short enable_int ; jump, if we got it +; +; flush out queue +; + xor ax, ax + mov [si.QOutCount], ax + mov [si.QOutMod], ax + mov ax, [si.QOutGet] + mov [si.QOutPut], ax + jmp short KickTx10 ; N: + +KickTx endp +page + +;----------------------------Private-Routine----------------------------; +; +; MSRWait - Modem Status Register Wait +; +; This routine checks the modem status register for CTS, DSR, +; and/or RLSD signals. If a timeout occurs while checking, +; the appropriate error code will be returned. +; +; This routine will not check for any signal with a corresponding +; time out value of 0 (ignore line). +; +; Entry: +; SI --> DEB +; Returns: +; AL = error code +; ComErr[si] updated +; 'Z' set if no timeout +; Error Returns: +; None +; Registers Destroyed: +; AX,CX,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public MSRWait ;Public for debugging + +MSRWait proc near + + push di + +MSRRestart: + xor di,di ;Init Timer + +MSRWait10: + mov cx,11 ;Init Delay counter (used on non-ATs) + +MSRWait20: + xor dh,dh ;Init error accumulator + mov al,MSRShadow[si] ;Get Modem Status + and al,MSRMask[si] ;Only leave bits of interest + xor al,MSRMask[si] ;0 = line high + jz MSRWait90 ;All lines of interest are high + mov ah,al ;ah has 1 bits for down lines + + shl ah,1 ;Line Signal Detect low? + jnc MSRWait30 ; No, it's high + .errnz ACE_RLSD-10000000b + cmp di,[si.DCB_RlsTimeout] ;RLSD timeout yet? + jb MSRWait30 ; No + or dh,CE_RLSDTO ;Show modem status timeout + +MSRWait30: + shl ah,1 ;Data Set Ready low? + shl ah,1 + .errnz ACE_DSR-00100000b + jnc MSRWait40 ; No, it's high + cmp di,[si.DCB_DsrTimeout] ;DSR timeout yet? + jb MSRWait40 ; No + or dh,CE_DSRTO ;Show data set ready timeout + +MSRWait40: + shl ah,1 ;CTS low? + jnc MSRWait50 ; No, it's high + .errnz ACE_CTS-00010000b + cmp di,[si.DCB_CtsTimeout] ;CTS timeout yet? + jb MSRWait50 ; No + or dh,CE_CTSTO ;Show clear to send timeout + +MSRWait50: + or dh,dh ;Any timeout occur? + jnz MSRWait80 ; Yes + + cmp [$MachineID],0FCh ;Is this a PC-AT? [rkh debug for PS/2] + je MSRWait60 ; Yes, use ROM function + loop MSRWait20 ; No, continue until timeout + jmp short MSRWait70 ;Should have taken about a millisecond + +MSRWait60: + push bx ;Special SALMON ROM routine to delay + push di + xor cx,cx ;Number of Microseconds to delay + mov dx,1000 ; in CX:DX + mov ah,86h + int 15h ;Wait 1 millisecond + pop di + pop bx + +MSRWait70: + inc di ;Timer +1 + jmp short MSRWait10 ;Until Timeout or Good status + +MSRWait80: + xor ah,ah + mov al,dh + or by ComErr[si],al ;Return updated status + .errnz HIGH CE_CTSTO + .errnz HIGH CE_DSRTO + .errnz HIGH CE_RLSDTO + +MSRWait90: + or al,al ;Set 'Z' if no timeout + pop di + ret + +MSRWait endp +page + +;----------------------------Public Routine-----------------------------; +; +; $EVT - Set Event Mask +; +; Set up event word and mask. Returns a pointer to a word in which +; certain bits, as enabled by the mask, will be set when certain +; events occur. +; +; Entry: +; AH = Device ID +; BX = Event enable mask +; Returns: +; DX:AX --> event word. +; Error Returns: +; AX = 0 if error +; Registers Preserved: +; BX,CX,SI,DI,DS,ES +; Registers Destroyed: +; AX,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public $EVT +$EVT proc near + + push si + xor dx,dx ;In case of error + call GetDEB ;Get pointer to DEB + mov ax,dx ;Finish setting error return value + jc Evt10 ;Illegal id, return error + js Evt10 ;LPTx, return error + mov EvtMask[si],bx ;Save the new event mask + lea ax,EvtWord[si] ;Get address of event word + mov dx,ds ; into dx:ax + +Evt10: + pop si + ret + +$EVT endp +page + +;----------------------------Public Routine-----------------------------; +; +; $EVTGET - Get Event Word +; +; Return and clear fields in the event word. This routine MUST be used +; by applications to read the event word, as it is the ONLY way they +; can be assured that an event is not lost between reading the flags +; and resetting some. +; +; Entry: +; AH = Device ID +; BX = Event clear mask +; Returns: +; AX = event word +; Error Returns: +; None +; Registers Preserved: +; AX,CX,SI,DI,DS,ES +; Registers Destroyed: +; BX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public $EVTGET +$EVTGET proc near + + push si + call GetDEB + mov ah,0 ;In case of error (AL already 0) + jc EvtGet10 ;Illegal ID + js EvtGet10 ;Illegal ID + call DOCLI ;No interrupts allowed + mov ax,EvtWord[si] ;Get the current event word + not bx ;Convert mask for our purposes + and bx,ax ;Clear events that user wants us to + mov EvtWord[si],bx ;And save those results + call DOSTI ;Magic over + +EvtGet10: + pop si + ret + +$EVTGET endp +page + +;----------------------------Public Routine-----------------------------; +; +; $STACOM - Return Status Information +; +; Returns the number of bytes in both queues. +; +; LPT ports will show both queues empty. +; and resetting some. +; +; Entry: +; AH = Device ID +; ES:BX = Pointer to status structure to be updated. +; = Null if not to update +; Returns: +; AX = comm error word +; Status Structure Updated. +; Error Returns: +; AX = error code +; Registers Preserved: +; SI,DI,DS,ES +; Registers Destroyed: +; AX,BX,CX,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $STACOM +$STACOM proc near + + push si + call GetDEB ;Get DEB pointer in SI + jc StaCom30 ;Invalid ID + mov cx,es ;Is the pointer NULL? + or cx,bx + jz StaCom25 ; Yes, just return error code + xor cx,cx + xor dx,dx + or ah,ah ;Set 'S' if LPT port + mov ax,cx ;For LPTs, everything is zero + js StaCom20 ;LPT port + +; Need to get the status for a com port. Since not all the +; status is contained within EFlags, it has to be assembled. +; Also note that currently there is no way to specify RLSD +; as a handshaking line, so fRLSDHold is always returned false. + + mov al,MSRShadow[si] ;Get state of hardware lines + and al,OutHHSLines[si] ;Mask off required bits + xor al,OutHHSLines[si] ;1 = line low + mov cl,4 ;Align bits + shr al,cl ;al = fCTSHold + fDSRHold + .errnz ACE_CTS-00010000b + .errnz ACE_DSR-00100000b + .errnz fCTSHold-00000001b + .errnz fDSRHold-00000010b + + mov ah,HSFlag[si] ;Get fXOffHold+fXOffSent + and ah,XOffReceived+XOffSent + or al,ah + + .errnz XOffReceived-fXOFFHold + .errnz XOffSent-fXOFFSent + + mov ah,EFlags[si] ;Get fEOF+fTxImmed + and ah,fEOF+fTxImmed + or al,ah + + mov cx,QInCount[si] ;Get input queue count + mov dx,QOutCount[si] ;Get tx queue count + +StaCom20: + mov es:[bx.COMS_BitMask1],al + mov es:[bx.COMS_cbInQue],cx + mov es:[bx.COMS_cbOutQue],dx + +StaCom25: + xor ax,ax ;Return old com error + xchg ax,ComErr[si] ; and clear it out + +StaCom30: + pop si + ret + +$STACOM endp +page + +;----------------------------Public Routine-----------------------------; +; +; $SetBrk - Set Break +; +; Clamp the Tx data line low. Does not wait for the +; transmitter holding register and shift registers to empty. +; +; LPT ports will just return the comm error word +; +; Entry: +; AH = Device ID +; Returns: +; AX = comm error word +; Error Returns: +; AX = error code +; Registers Preserved: +; SI,DI,DS,ES +; Registers Destroyed: +; AX,BX,CX,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public $SETBRK +$SETBRK proc near + + mov cx,0FF00h+ACE_SB ;Will be setting break + jmp short ClrBrk10 + .errnz BreakSet-ACE_SB ;Must be same bits + +$SETBRK endp +page + +;----------------------------Public Routine-----------------------------; +; +; $CLRBRK - Clear Break +; +; Release any BREAK clamp on the Tx data line. +; +; LPT ports will just return the comm error word +; +; Entry: +; AH = Device ID +; Returns: +; AX = comm error word +; Error Returns: +; AX = error code +; Registers Preserved: +; SI,DI,DS,ES +; Registers Destroyed: +; AX,BX,CX,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $CLRBRK +$CLRBRK proc near + + mov cx,(NOT ACE_SB) SHL 8 + .errnz BreakSet-ACE_SB ;Must be same bits + +ClrBrk10: + push si + call GetDEB ;Get DEB address + jc ClrBrk30 ;Invalid ID + js ClrBrk20 ;Ignored for LPT ports + call DOCLI + and HSFlag[si],ch ;Set or clear the BreakSet bit + or HSFlag[si],cl + +; ch = mask to remove bits in the Line Control Register +; cl = mask to turn bits on in the Line Control Register + + mov dx,Port[si] ;Get comm device base I/O port + add dl,ACE_LCR ;Point at the Line Control Regieter + in al,dx ;Get old line control value + and al,ch ;Turn off desired bits + or al,cl ;Turn on desired bits + iodelay + out dx,al ;Output New LCR. + call DOSTI + +ClrBrk20: + mov ax,ComErr[si] ;Return Status Word + +ClrBrk30: + pop si + ret + +$CLRBRK endp + +page + +;----------------------------Public Routine-----------------------------; +; +; $EXTCOM - Extended Comm Functions +; +; A number of extended functions are routed through this entry point. +; +; Functions currently implemented: +; +; 0: Ignored +; 1: SETXOFF - Exactly as if X-OFF character has been received. +; 2: SETXON - Exactly as if X-ON character has been received. +; 3: SETRTS - Set the RTS signal +; 4: CLRRTS - Clear the RTS signal +; 5: SETDTR - Set the DTR signal +; 6: CLRDTR - Clear the DTR signal +; 7: RESET - Yank on reset line if available (LPT devices) +; +; Entry: +; AH = Device ID +; BL = Function Code +; (0-127 are MS-defined, 128-255 are OEM defined) +; Returns: +; AX = comm error word +; Error Returns: +; AX = error code +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + +; Dispatch table for the extended functions + +ExtTab dw ExtComDummy ;Function 0: Never Mind + dw ExtCom_FN1 ;1: Set X-Off + dw ExtCom_FN2 ;2: Clear X-Off + dw ExtCom_FN3 ;3: Set RTS + dw ExtCom_FN4 ;4: Clear RTS + dw ExtCom_FN5 ;5: Set DSR + dw ExtCom_FN6 ;6: Clear DSR + dw ExtCom_FN7 ;7: Reset printer + dw ExtCom_FN8 ;8: Get Max LPT Port + dw ExtCom_FN9 ;9: Get Max COM Port + dw ExtCom_FN10 ;10: Get COM Port Base & IRQ + dw ExtCom_FN10 ;11: Get COM Port Base & IRQ +%OUT fix this for bld 32 -- GetBaseIRQ is now 10 + + assumes ds,Data + assumes es,nothing + + public $EXTCOM +$EXTCOM proc near + + push si + push di + call GetDEB ;Get DEB pointer + jc ExtCom40 ;Invalid ID, return error + mov dx,Port[si] ; get port address + jns ExtCom10 ;Its a COM port + cmp bl,7 ;RESET extended function? + jne ExtCom30 ; No, return error word + jmp short ExtCom20 ; Yes, invoke the function + +ExtCom10: + cmp bl,11 ;Last fcn supported + ja ExtCom30 ;Not an implemented function. + +ExtCom20: + xor bh,bh + add bx,bx ;Shift for the call + call DOCLI ;Consider as critical sections + call ExtTab[bx] ; and perform the function + call DOSTI + jc ExtCom40 ; jump if sub returns data in DX:AX + +ExtCom30: + mov ax,ComErr[si] ;Return standard error word + xor dx, dx + +ExtCom40: + pop di + pop si + + ret + +$EXTCOM endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN1 - Extended Function Set X-Off +; +; Analagous to receiving an X-OFF character. Bufferred transmision of +; characters is halted until an X-ON character is received, or until +; we fake that with a Clear X-Off call. +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public ExtCom_FN1 +ExtCom_FN1 proc near + + or HSFlag[si],XOffReceived +ExtComDummy: + clc + ret + +ExtCom_FN1 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN2 - Extended Function Clear X-Off +; +; Analagous to receiving an X-ON character. Buffered +; transmission of characters is restarted. +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public ExtCom_FN2 +ExtCom_FN2 proc near + + and HSFlag[si],NOT XOffReceived + call KickTx ;Kick transmitter interrupts on + clc + ret + +ExtCom_FN2 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN3 - Extended Function Set RTS +; +; Set the RTS signal active. +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public ExtCom_FN3 +ExtCom_FN3 proc near + + add dl,ACE_MCR ;Point at Modem Control Register + in al,dx ;Get current settings + or al,ACE_RTS ;Set RTS + iodelay + out dx,al ;And update + clc + ret + +ExtCom_FN3 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN4 - Extended Function Clear RTS +; +; Set the RTS signal inactive. +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public ExtCom_FN4 +ExtCom_FN4 proc near + + add dl,ACE_MCR ;Point at Modem Control Register + in al,dx ;Get current settings + and al,NOT ACE_RTS ;Clear RTS + iodelay + out dx,al ;And update + clc + ret + +ExtCom_FN4 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN5 - Extended Function Set DTR +; +; Set the DTR signal active. +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public ExtCom_FN5 +ExtCom_FN5 proc near + + add dl,ACE_MCR ;Point at Modem Control Register + in al,dx ;Get current settings + or al,ACE_DTR ;Set DTR + iodelay + out dx,al ;And update + clc + ret + +ExtCom_FN5 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN6 - Extended Function Clear DTR +; +; Set the DTR signal inactive. +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public ExtCom_FN6 +ExtCom_FN6 proc near + + add dl,ACE_MCR ;Point at Modem Control Register + in al,dx ;Get current settings + and al,NOT ACE_DTR ;Clear DTR + iodelay + out dx,al ;And update + clc + ret + +ExtCom_FN6 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN7 - Extended Function Reset Printer +; +; Assert the RESET line on an LPT port +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public ExtCom_FN7 +ExtCom_FN7 proc near + + call DOSTI ;Not called at interrupt time + mov ch,1 ;ROM BIOS Reset Port + call DoLPT ;Perform the function + clc + ret + +ExtCom_FN7 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN8 - Get Num Ports +; +; Entry: +; Returns: +; AX = Max LPT port id +; DX = 0 +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public ExtCom_FN8 +ExtCom_FN8 proc near + + mov ax, MAXLPT + LPTx + xor dx, dx + stc + ret + +ExtCom_FN8 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN9 - Get Max COM Port +; +; Entry: +; Returns: +; AX = Max COM port id +; DX = 0 +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public ExtCom_FN9 +ExtCom_FN9 proc near + + mov ax, MAXCOM + xor dx, dx + stc + ret + +ExtCom_FN9 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN10 - Get COM Port Bas & IRQ +; +; Entry: +; AH = com id +; DS:SI -> DEB +; Returns: +; AX = base +; DX = irq +; Error Returns: +; None +; Registers Preserved: +; DS +; Registers Destroyed: +; AX,BX,CX,DX,DI,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public ExtCom_FN10 +ExtCom_FN10 proc near + + call FindCOMPort + stc + ret + +ExtCom_FN10 endp +page + + +ifdef DEBUG + public RecCom40, RecCom50, RecCom60, RecCom70, RecCom80 + public RecCom90, RecCom95, RecCom100 + public SendImm10, SendImm20, + public SendCom10, SendCom20, SendCom30, SendCom40, SendCom50, SendCom60 + public Flush10, Flush20, Flush30, Flush40 + public KickTx10 + public Evt10 + public EvtGet10 + public StaCom20, StaCom25, StaCom30 + public ClrBrk10, ClrBrk20, ClrBrk30 + public ExtCom10, ExtCom20, ExtCom30, ExtCom40, ExtComDummy + public MSRRestart, MSRWait10, MSRWait20, MSRWait30, MSRWait40 + public MSRWait50, MSRWait60, MSRWait70, MSRWait80, MSRWait90 +endif + + +DOSTI proc near + FSTI + ret +DOSTI endp + +DOCLI proc near + FCLI + ret +DOCLI endp + + +sEnd code +End diff --git a/private/mvdm/wow16/drivers/comm/ibmcom.inc b/private/mvdm/wow16/drivers/comm/ibmcom.inc new file mode 100644 index 000000000..cdf4608c1 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/ibmcom.inc @@ -0,0 +1,265 @@ +DEBUG equ 1 + +No_DOSX_Bimodal_Services = 1 +IFDEF No_DOSX_Bimodal_Services +%OUT generating code to handle ints without Bimodal Interrupt Services for DOSX +ENDIF + +wo equ word ptr +by equ byte ptr + +MAXLPT equ 2 ;3 LPTs supported (LPT1,2,3) +MAXCOM equ 3 ;4 COMs supported (COM1,2,3,4) + +RS232B equ 0h ;RS232 Card(s) I/O addr 40:Save area. +LPTB equ 8h ;LPT Card(s) I/O addr 40:Save area. + +IRQ3 equ 0bh ; Int vector for Com card @ 2xxh +IRQ4 equ 0ch ; Int vector for Com card @ 3xxh + +INTA0 equ 20h ;X'20' 8259 Interrupt Control Port +INTA1 equ 21h ;X'21' 8259 Interrupt Mask Port +EOI equ 20h ;X'20' 8259 End-of-Interrupt ack + +Open equ 0201h ;Int 2F open request +Close equ 0202h ;Int 2F close request +Lock2F equ 0203h ;Int 2F lock request +Unlock2F equ 0204h ;Int 2F unlock request + + +; COMDEB - Communications Device Equipment Block. +; +; This is essentially a superset of the DCB used outside of this +; module. The DCB is contained within the DEB as the first fields. +; The fields which follow are data and status fields which +; are unique to this implementation. +; +; AltQInAddr and AltQOutAddr are alternate queue pointers which are used when +; in "supervisor" mode. Supervisor mode is a processor mode other than the +; one which Windows normally runs in. In standard mode Windows, supervisor +; mode is REAL mode. In enhanced mode Windows, supervisor mode is RING 0 +; protected mode. For more details see comments in IBMINT.ASM. + +ComDEB struc ;RS232 Data Equip Block + + ComDCB db ((DCBSize+1) and 0FFFEh) DUP (0) + + ComErr dw 0 ;Non-zero if I/O error + Port dw 0 ;Base I/O Address + NotifyHandle dw 0 + NotifyFlags dw 0 + RecvTrigger dw -1 ; char count threshold for calling + SendTrigger dw 0 ; char count threshold for calling + +; The following fields are specific to com ports only + + IRQhook dw 0 ; ptr to IRQ_Hook_Struc + NextDEB dw 0 ; ptr to next DEB that is sharing IRQ + XOffPoint dw 0 ;Q count where XOff is sent + EvtMask dw 0 ;Mask of events to check for + EvtWord dw 0 ;Event flags + QInAddr dd 0 ;Address of the queue + AltQInAddr dd 0 ; Addr of queue in "supervisor" mode + QInSize dw 0 ;Length of queue in bytes + QOutAddr dd 0 ;Address of the queue + AltQOutAddr dd 0 ; Addr of queue in "supervisor" mode + QOutSize dw 0 ;Length of queue in bytes + QInCount dw 0 ;Number of bytes currently in queue + QInGet dw 0 ;Offset into queue to get bytes from + QInPut dw 0 ;Offset into queue to put bytes in + QOutCount dw 0 ;Number of bytes currently in queue + QOutGet dw 0 ;Offset into queue to get bytes from + QOutPut dw 0 ;Offset into queue to put bytes in + EFlags db 0 ;Extended flags + MSRShadow db 0 ;Modem Status Register Shadow + ErrorMask db 0 ;Default error-checking mask + RxMask db 0 ;Character mask + ImmedChar db 0 ;Char to be transmitted immediately + HSFlag db 0 ;Handshake flag + HHSLines db 0 ;8250 DTR/RTS bits for handshaking + OutHHSLines db 0 ;Lines that must be high to output + MSRMask db 0 ;Mask of Modem Lines to check + MSRInfinite db 0 ;Mask of MSR lines that must be high + IntVecNum db 0 ;Interrupt vector number + LSRShadow db 0 ;Line Status Register shadow + QOutMod dw 0 ;characters sent mod xOnLim ENQ/ETX [rkh] + VCD_data dd 0 + VCDflags db 0 + MiscFlags db 0 ;still more flags +ComDEB ends + +.errnz (SIZE ComDEB) and 1 + +.errnz MSRShadow - EvtWord - 35 +; In 3.0 MSRShadow had this relationship to EvtWord and major COM apps all +; use this offset of 35 to get to MSRShadow so that they can determine the +; current status of the Modem Status bits. We need to maintain this offset +; so that these apps will continue to run. + + +; The LptDEB is identical to the ComDEB structure, except +; all the COM port specific stuff has been removed (which +; convientiently was stored at the end so offsets would +; be correct). This allows the code to act indifferently +; when accessing the strucutres for things like the port. + +LptDEB struc + xComDCB db ((DCBSize+1) AND 0FFFEh) dup (0) + xComErr dw 0 ;Non-zero if I/O error + xPort dw 0 ;Base I/O Address + xNotifyHandle dw 0 + xNotifyFlags dw 0 + xRecvTrigger dw -1 ; char count threshold for calling + xSendTrigger dw 0 ; char count threshold for calling + + BIOSPortLoc dw 0 ;Offset to port location (i.e. 40:0) +LptDEB ends + + .errnz xComDCB-ComDCB + .errnz xComErr-ComErr + .errnz xPort-Port + + .errnz xNotifyHandle-NotifyHandle + .errnz xNotifyFlags-NotifyFlags + .errnz xRecvTrigger-RecvTrigger + .errnz xSendTrigger-SendTrigger + + +; flag equates in EFlags +fUseDSR equ 00000001b ; set, if DSR is significant +fNoFIFO equ 00000010b ; set, if no FIFO on port +fFIFOchkd equ 00000100b ; set, if FIFO has been checked +fFIFOpre equ 00001000b ; FIFO enabled when port opened +;fEOF equ 00100000b ; defined in comdev.inc +;fTxImmed equ 01000000b ; defined in comdev.inc + +fEFlagsMask equ fUseDSR OR fFIFOpre OR fFIFOchkd OR fNoFIFO ; flags which shouldn't be cleared + +.errnz fEFlagsMask AND (fEOF OR fTxImmed) ;can't overlap with either of the bits + ; that are folded into COMS_BitMask1 + + +; Values for NotifyFlags +; +CN_RecvSent equ CN_RECEIVE SHL 8 +CN_TransSent equ CN_TRANSMIT SHL 8 + +CN_Idle equ 10000000b +CN_Notify equ 01000000b + +NotifyFlagsLO equ byte ptr NotifyFlags +NotifyFlagsHI equ byte ptr NotifyFlags+1 + +; Values for the handshake flag +; +; BreakSet - True if break was set - stops transmission +; XOffSent - True if we have sent the XOff character +; XOffPending - True if XOff character needs to be sent +; XOnPending - True if XOn character needs to be sent +; HHSDown - True if host dropped required hardware lines +; HHSDropped - True if we dropped our hardware handshake lines +; XOffReceived - True if XOff received from host +; HSPending - Mask to return non-zero if XOn or Xoff must be sent +; HSReceived - Mask to return non-zero if handshake has been +; received from host stopping transmission +; CannotXmit - Mask to return non-zero if any condition +; exists which prevents us from tranmitting. +; HSSent - Mask to return non-zero if we sent a handshake + + +XOffPending equ 00000001b ;XOff needs to be sent +EnqPending equ 00000001b ;Enq needs to be sent [rkh] +EtxPending equ 00000001b ;Etx needs to be sent + +HHSDropped equ 00000010b ;Our hardware handshake lines are down + +XOnPending equ 00000100b ;XOn needs to be sent +AckPending equ 00000100b ;Ack needs to be sent (ENQ/ACK & ETX/ACK) + +XOffReceived equ 00001000b ;XOff character received +EnqSent equ 00001000b ;Enq has been sent +EtxSent equ 00001000b ;Etx has been sent + +XOffSent equ 00010000b ;XOff has been sent +EnqReceived equ 00010000b ;Enq character received (ENQ/ACK) +EtxReceived equ 00010000b ;Etx character received (ETX/ACK) + +HHSDown equ 00100000b ;Host hardware handshake lines are down + +BreakSet equ 01000000b ;Break has been set + +HHSAlwaysDown equ 10000000b ;set if host handshake lines were never + ; detected high + +HSPending equ XOffPending+XOnPending +HSReceived equ XOffReceived+HHSDown +HSSent equ XOffSent+HHSDropped +CannotXmit equ HSPending+HSReceived+BreakSet + +; values for MiscFlags + +Discard equ 00000001b ;Discard recevied data + + +iodelay macro ;;macro to insure that an instruction + jmp $+2 ;; fetch occurs between IN and/or OUT + jmp $+2 ;; instructions on the PC-AT machine +endm + + +TimeoutError equ -2 ;Timeout error code for $TRMCOM +Timeout equ 30 ;30 second timeout + +DELAY_TIME equ 200 ;Delay at least 200 milliseconds + + +; Status bits returned from the BIOS for LPT ports + +PS_NotBusy equ 10000000b ;Printer not busy +PS_Ack equ 01000000b ;Data acknowledged +PS_PaperOut equ 00100000b ;Out of paper +PS_Select equ 00010000b ;Device is selected +PS_IOError equ 00001000b ;IO error +PS_Timeout equ 00000001b ;Timeout occured + + +; status bit defines for LPT + +L_BITS equ 0F8h ; the status bits we want +L_BITS_INVERT equ 048h ; must invert to match BIOS +L_DEVBUSY equ 080h ; device busy bit +L_TIMEOUT equ 001h ; timeout bit + +; control bit defines for LPT + +L_NORMAL equ 00Ch ; normal state: selected, no reset +L_RESET equ 008h ; reset state +L_STROBE equ 00Dh ; tell printer we have char + + +IRQ_Hook_Struc struc +IRQn db 0 +HookCnt db 0 +OldMask db 0 +VecN db 0FFh +HandlerOff dw 0 +First_DEB dw 0 +OldIntVec dd 0 +IFDEF No_DOSX_Bimodal_Services +RM_OldIntVec dd 0 +RM_HandlerOff dw 0 +ENDIF +IRQ_Hook_Struc ends + + +IFDEF No_DOSX_Bimodal_Services +include int31.inc + +Get_RM_IntVector equ (Int31_Int_Serv SHL 8) + Int_Get_Real_Vec +Set_RM_IntVector equ (Int31_Int_Serv SHL 8) + Int_Set_Real_Vec +ENDIF + +; +; flag bits for VCDflags +; +fCOM_ignore_ints equ 00000001b diff --git a/private/mvdm/wow16/drivers/comm/ibmcom1.asm b/private/mvdm/wow16/drivers/comm/ibmcom1.asm new file mode 100644 index 000000000..0998e258c --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/ibmcom1.asm @@ -0,0 +1,1556 @@ +page + +;---------------------------Module-Header-------------------------------; +; Module Name: IBMCOM1.ASM +; +; Copyright (c) Microsoft Corporation 1985-1990. All Rights Reserved. +; +;----------------------------Private-Routine----------------------------; +; +; DoLPT - Do Function To LPT port +; +; The given function (output or reset) is performed to the +; passed LPT port. +; +; Before a character is sent, a check is made to see if the device +; will be able to accept the character. If it can, then the character +; will be sent. If not, then an error will be returned. If the +; printer is selected and busy and no error, then the code returned +; will be CE_TXFULL and the handshake bits will be set in HSFlag +; to simulate that a handshake was received. +; +; If the BIOS ROM code is examined, you will note that they wait for +; the busy character from the last charcater to be cleared before +; they strobe in the current character. This can take a long time +; on the standard EPSON class printer (1 mSec to greater than +; 300 mSec if the last character actually caused printing). +; +; Because of this, several status read retrys will be made before +; declaring that the device is actually busy. If only one status +; read is performed, the spooler will yeild, take a while to get +; back here, and things will be really slow. What difference does +; it really make if we or the BIOS does the delay, at least we can +; break out of it at some point when it seems hopeless. +; +; The OKIHACK: Okidata reports a 50 ns. 2.2 volt pulse on the paper +; out signal on the trailing edge of the Busy signal. If we see this +; glitch then we report paper out. So we try to get the status twice... +; if it changes between the two tries we keep getting the status. +; Silly hardware people. +; +; Entry: +; AH = cid +; AL = character to output +; CH = Function request. 0 = Output, 1 = Initialize, 2 = Status +; DS:SI -> DEB for the port +; Returns: +; AX = 0 if no errors occured +; Error Returns: +; AX = error code +; Registers Preserved: +; SI,DI +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +; sudeepb 10-Jan-1993 changed the costly cli/sti with non-trapping +; FCLI/FSTI macros +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + + assumes ds,Data + assumes es,nothing + +include vint.inc + +externFP OutputDebugString + +dbmsg macro msg +.286 +push cs +push offset $ + 3 + 5 + 2 ; push + far call + short jump +call OutputDebugString +jmp short @F + db msg,13,10,0 +@@: +endm + +iodelay macro + jmp $+2 + jmp $+2 +endm + + public DoLPT ;Publics for debugging + public LPT_Reset + public LPT_Outchar + public LPT_Strobe + public LPT_GetStatus + public DoLPT40 + +; status bit defines + +L_BITS equ 0F8h ; the status bits we want +L_BITS_INVERT equ 048h ; must invert to match BIOS +L_DEVBUSY equ 080h ; device busy bit +L_TIMEOUT equ 001h ; timeout bit + +; control bit defines + +L_NORMAL equ 00Ch ; normal state: selected, no reset +L_RESET equ 008h ; reset state +L_STROBE equ 00Dh ; tell printer we have char + +DoLPT proc near + + mov dx,Port[si] ;Get port address + +; DX = port address +; CH = operation: 0 = write, 1 = init, 2 = status +; AL = character + + or ch, ch + jz LPT_OutChar + cmp ch, 1 + jz LPT_Reset + jmp LPT_GetStatus + ret + +LPT_Reset: + + inc dx + inc dx + mov al, L_RESET + iodelay + out dx, al + + push dx + + cCall GetSystemMsecCount + mov bx, ax + +LPT_ResetDelay: + push bx + cCall GetSystemMsecCount + pop bx + sub ax, bx + cmp ax, 300 ; 1/3 sec as good as any + jbe LPT_ResetDelay + + pop dx + + mov al, L_NORMAL + iodelay + iodelay + out dx, al + dec dx + dec dx + jmp LPT_GetStatus + +LPT_OutChar: + push ax ; save character to be written + + ; first check to see if printer is ready for us + push di + + push dx + call GetSystemMSecCount + mov di, ax + pop dx + +LPT_WaitReady: + + inc dx ; point to status port + iodelay + in al, dx ; get status bits + and al, L_BITS ; mask unused ones + xor al, L_BITS_INVERT ; flip a couple + xchg al, ah + +ifndef NOOKIHACK + iodelay + in al, dx + + dec dx + + and al, L_BITS + xor al, L_BITS_INVERT + cmp al, ah ; did any bits change? + jnz LPT_WaitReady +else + dec dx +endif + + + test ah, PS_PaperOut or PS_IOError + jnz LPT_PrinterNotReady + test ah, PS_Select + jz LPT_PrinterNotReady + test ah, PS_NotBusy + jnz LPT_PrinterReady + + push ax + push dx + call GetSystemMSecCount + pop dx + pop bx + sub ax, di + cmp ax, 300 ; 1/3 sec timeout + + jbe LPT_WaitReady + +; The device seems to be selected and powered up, but is just +; busy (some printers seem to show selected but busy when they +; are taken offline). Show that the transmit queue is full and +; that the hold handshakes are set. This is so the windows +; spooler will retry (and do yields so that other apps may run). + + + or ComErr[si],CE_TXFULL ;Show queue full + mov ah,bh + or ah, L_TIMEOUT + +LPT_PrinterNotReady: + + pop di + pop cx ; throw away character + jmp LPT_ReturnStatus + +LPT_PrinterReady: + pop di ; get di back + pop ax ; get character back + + iodelay + out dx, al ; write character to port + + inc dx ; access status port + +LPT_Strobe: + inc dx ; control port + mov al, L_STROBE ; set strobe high + iodelay + iodelay + iodelay + iodelay + out dx, al ; ... + + mov al, L_NORMAL ; + iodelay + iodelay + iodelay + iodelay + out dx, al ; set strobe low + + sub dx, 2 ; point back to port base + + ; FALL THRU + +LPT_GetStatus: + inc dx ; point to status port +LPT_GS1: + iodelay + iodelay + in al, dx ; get status bits + and al, L_BITS ; mask unused ones + xor al, L_BITS_INVERT ; flip a couple + mov ah, al + +ifndef NOOKIHACK + in al, dx + and al, L_BITS + xor al, L_BITS_INVERT + cmp al, ah + jnz LPT_GS1 ; if they changed try again... +endif + +LPT_ReturnStatus: + + assumes ds,Data + and ax,(PS_PaperOut+PS_Select+PS_IOError+PS_Timeout)*256 + shr ah,1 + adc ah,al ;Get back Timeout bit + xor ah,HIGH CE_DNS ;Invert selected bit + .errnz LOW CE_DNS + or by ComErr+1[si],ah ;Save comm error + ret + + .errnz CE_PTO-0200h + .errnz CE_IOE-0400h + .errnz CE_DNS-0800h + .errnz CE_OOP-1000h + +DoLPT40: + assumes ds,Data + or ComErr[si],CE_TXFULL ;Show queue full + ret + +DoLPT endp +page + +;----------------------------Private-Routine----------------------------; +; +; TXI - Transmit A Character Immediately +; +; Set up a character to be transmitted "immediately". +; by placing the character in a location that guarantees +; it to be the next character transmitted. +; +; The check to see if the immediate character can be placed has +; already been made prior to entry. +; +; Interrupts must be disabled before entering this code +; +; Entry: +; AH = Character +; DS:SI --> DEB +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; BX,CX,SI,DI,DS,ES +; Registers Destroyed: +; AL,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public TXI ;Public for debugging +TXI proc near + +; FCLI ;Must be done by caller! + or EFlags[si],fTxImmed ;Show char to xmit + mov ImmedChar[si],ah ;Set character to transmit next +; jmp short KickTx ;Kick Xmit just in case + errn$ KickTx + +TXI endp +page + +;----------------------------Private-Routine----------------------------; +; +; KickTx - Kick Transmitter +; +; "Kick" the transmitter interrupt routine into operation. +; If the Transmitter Holding Register isn't empty, then +; nothing needs to be done. If it is empty, then the xmit +; interrupt needs to enabled in the IER. +; +; Entry: +; DS:SI --> DEB +; INTERRUPTS DISABLED! +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; BX,CX,SI,DI,DS,ES +; Registers Destroyed: +; AX,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public KickTx ;Public for debugging +KickTx proc near + +; FCLI ;Done by caller + mov dx,Port[si] ;Get device I/O address + add dl,ACE_LSR ;Point at the line status reg + pin al,dx ;And get it + and al,ACE_THRE ;Check transmitter holding reg status + jz KickTx10 ;Busy, interrupt will hit soon enough + + sub dl,ACE_LSR-ACE_IER ;--> Interrupt enable register + pin al,dx ;Get current IER state + test al,ACE_THREI ;Interrupt already enabled? + jnz KickTx10 ; Yes, don't reenable it + or al,ACE_THREI ; No, enable it + pout dx,al + pause ;8250, 8250-B bug requires + pout dx,al ; writting register twice + +KickTx10: +; FSTI ;Done by caller + ret + +KickTx endp +page + +;----------------------------Private-Routine----------------------------; +; +; GetDEB - Get Pointer To Device's DEB +; +; Returns a pointer to appropriate DEB, based on device number. +; +; Entry: +; AH = cid +; Returns: +; 'C' clear +; 'S' set if LPT device +; DS:SI --> DEB is valid cid +; AH = cid +; Error Returns: +; 'C' set if error (cid is invalid) +; AX = 8000h +; Registers Preserved: +; BX,CX,DX,DI,DS,ES +; Registers Destroyed: +; AX,SI,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public GetDEB ;Public for debugging +GetDEB proc near + + cmp ah,LPTx+MAXLPT ;Within range? + ja GetDEB30 ;No, return invalid ID + mov si,DataOFFSET LPT3 ;Assume LPT3 + je GetDEB10 ;It's LPT3 + cmp ah,MAXCOM ;Is cid within range for a com port? + ja GetDEB20 ; No, check for a LPT port 1 and 2 + mov si,DataOFFSET Comm4 ;Assume COM4 [rkh] ... + je GetDEB10 ;It was COM4 + mov si,DataOFFSET Comm3 ;Assume COM3 + cmp ah,MAXCOM-1 ;Is cid within range for a com port? + je GetDEB10 ;It was COM3 + mov si,DataOFFSET Comm2 ;Assume COM2 + cmp ah,MAXCOM-2 ;Is cid within range for a com port? + je GetDEB10 ;It was COM2 + mov si,DataOFFSET Comm1 ;It was COM1 + +GetDEB10: + or ah,ah ;Set 'S' if LPT, clear 'C' + ret + .errnz LPTx-10000000b + +GetDEB20: + mov si,DataOFFSET LPT1 ;Assume LPT1 + cmp ah,LPTx + je GetDEB10 ;Its LPT1 + mov si,DataOFFSET LPT2 ;Assume LPT2 + ja GetDEB10 ;Its LPT2 + +GetDEB30: + mov ax,8000h ;Set error code + stc ;Set 'C' to show error + ret + +GetDEB endp + +page + +;----------------------------Public Routine-----------------------------; +; +; $SETQUE - Set up Queue Pointers +; +; Sets pointers to Receive and Transmit Queues, as provided by the +; caller, and initializes those queues to be empty. +; +; Queues must be set before $INICOM is called! +; +; Entry: +; AH = Device ID +; ES:BX --> Queue Definition Block +; Returns: +; AX = 0 if no errors occured +; Error Returns: +; AX = error code +; Registers Preserved: +; BX,DX,SI,DI,DS +; Registers Destroyed: +; AX,CX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $SETQUE +$SETQUE proc near + + push si ;These will be used + push di + call GetDEB ;Get DEB + jc SetQue10 ;Invalid, ignore the call + js SetQue10 ;Ignore call for LPT ports + push ds ;Set ds:si --> QDB + push es ;Set es:di --> to ComDCB.QInAddr + pop ds + assumes ds,nothing + pop es + assumes es,Data + lea di,QInAddr[si] + mov si,bx + mov cx,(SIZE QDB)/2 + .errnz (SIZE QDB) AND 1 + xor ax,ax ;Will do some zero filling + cld + FCLI ;No one else can play with queues + rep movsw + mov cl,(EFlags-QInCount)/2 + .errnz (EFlags-QInCount) AND 0FE01h + rep stosw + FSTI + push es ;Restore the data segment + pop ds + assumes ds,Data + assumes es,nothing + +SetQue10: + pop di ;Restore saved registers + pop si + ret + +; The above code made a few assumptions about how memory +; was allocated within the structures: + + .errnz (QueueRxSize-QueueRxAddr)-(QInSize-QInAddr) + .errnz (QueueTxAddr-QueueRxSize)-(QOutAddr-QInSize) + .errnz (QueueTxSize-QueueTxAddr)-(QOutSize-QOutAddr) + + .errnz QueueRxSize-QueueRxAddr-4 + .errnz QueueTxAddr-QueueRxSize-2 + .errnz QueueTxSize-QueueTxAddr-4 + + .errnz QInSize-QInAddr-4 + .errnz QOutAddr-QInSize-2 + .errnz QOutSize-QOutAddr-4 + + .errnz QInCount-QOutSize-2 + .errnz QInGet-QInCount-2 + .errnz QInPut-QInGet-2 + .errnz QOutCount-QInPut-2 + .errnz QOutGet-QOutCount-2 + .errnz QOutPut-QOutGet-2 + .errnz EFlags-QOutPut-2 ;First non-queue item + +$SETQUE endp + +page + +;----------------------------Public Routine-----------------------------; +; +; $EVT - Set Event Mask +; +; Set up event word and mask. Returns a pointer to a word in which +; certain bits, as enabled by the mask, will be set when certain +; events occur. +; +; Entry: +; AH = Device ID +; BX = Event enable mask +; Returns: +; DX:AX --> event word. +; Error Returns: +; AX = 0 if error +; Registers Preserved: +; BX,CX,SI,DI,DS,ES +; Registers Destroyed: +; AX,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public $EVT +$EVT proc near + + push si + xor dx,dx ;In case of error + call GetDEB ;Get pointer to DEB + mov ax,dx ;Finish setting error return value + jc Evt10 ;Illegal id, return error + js Evt10 ;LPTx, return error + mov EvtMask[si],bx ;Save the new event mask + lea ax,EvtWord[si] ;Get address of event word + mov dx,ds ; into dx:ax + +Evt10: + pop si + ret + +$EVT endp +page + +;----------------------------Public Routine-----------------------------; +; +; $EVTGET - Get Event Word +; +; Return and clear fields in the event word. This routine MUST be used +; by applications to read the event word, as it is the ONLY way they +; can be assured that an event is not lost between reading the flags +; and resetting some. +; +; Entry: +; AH = Device ID +; BX = Event clear mask +; Returns: +; AX = event word +; Error Returns: +; None +; Registers Preserved: +; AX,CX,SI,DI,DS,ES +; Registers Destroyed: +; BX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public $EVTGET +$EVTGET proc near + + push si + call GetDEB + mov ah,0 ;In case of error (AL already 0) + jc EvtGet10 ;Illegal ID + js EvtGet10 ;Illegal ID + FCLI ;No interrupts allowed + mov ax,EvtWord[si] ;Get the current event word + not bx ;Convert mask for our purposes + and bx,ax ;Clear events that user wants us to + mov EvtWord[si],bx ;And save those results + FSTI ;Magic over + +EvtGet10: + pop si + ret + +$EVTGET endp +page + +;----------------------------Public Routine-----------------------------; +; +; $STACOM - Return Status Information +; +; Returns the number of bytes in both queues. +; +; LPT ports will show both queues empty. +; and resetting some. +; +; Entry: +; AH = Device ID +; ES:BX = Pointer to status structure to be updated. +; = Null if not to update +; Returns: +; AX = comm error word +; Status Structure Updated. +; Error Returns: +; AX = error code +; Registers Preserved: +; SI,DI,DS,ES +; Registers Destroyed: +; AX,BX,CX,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $STACOM +$STACOM proc near + + push si + call GetDEB ;Get DEB pointer in SI + jc StaCom30 ;Invalid ID + mov cx,es ;Is the pointer NULL? + or cx,bx + jz StaCom25 ; Yes, just return error code + xor cx,cx + xor dx,dx + or ah,ah ;Set 'S' if LPT port + mov ax,cx ;For LPTs, everything is zero + js StaCom20 ;LPT port + +; Need to get the status for a com port. Since not all the +; status is contained within EFlags, it has to be assembled. +; Also note that currently there is no way to specify RLSD +; as a handshaking line, so fRLSDHold is always returned false. + + mov al,MSRShadow[si] ;Get state of hardware lines + and al,OutHHSLines[si] ;Mask off required bits + xor al,OutHHSLines[si] ;1 = line low + mov cl,4 ;Align bits + shr al,cl ;al = fCTSHold + fDSRHold + .errnz ACE_CTS-00010000b + .errnz ACE_DSR-00100000b + .errnz fCTSHold-00000001b + .errnz fDSRHold-00000010b + + mov ah,HSFlag[si] ;Get fXOffHold+fXOffSent + and ah,XOffReceived+XOffSent + or al,ah + + .errnz XOffReceived-fXOFFHold + .errnz XOffSent-fXOFFSent + + mov ah,EFlags[si] ;Get fEOF+fTxImmed + and ah,fEOF+fTxImmed + or al,ah + + mov cx,QInCount[si] ;Get input queue count + mov dx,QOutCount[si] ;Get tx queue count + +StaCom20: + mov es:StatFlags[bx],al + mov es:StatRxCount[bx],cx + mov es:StatTxCount[bx],dx + +StaCom25: + xor ax,ax ;Return old com error + xchg ax,ComErr[si] ; and clear it out + +StaCom30: + pop si + ret + +$STACOM endp +page + +;----------------------------Public Routine-----------------------------; +; +; $SetBrk - Set Break +; +; Clamp the Tx data line low. Does not wait for the +; transmitter holding register and shift registers to empty. +; +; LPT ports will just return the comm error word +; +; Entry: +; AH = Device ID +; Returns: +; AX = comm error word +; Error Returns: +; AX = error code +; Registers Preserved: +; SI,DI,DS,ES +; Registers Destroyed: +; AX,BX,CX,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public $SETBRK +$SETBRK proc near + + mov cx,0FF00h+ACE_SB ;Will be setting break + jmp short ClrBrk10 + .errnz BreakSet-ACE_SB ;Must be same bits + +$SETBRK endp +page + +;----------------------------Public Routine-----------------------------; +; +; $CLRBRK - Clear Break +; +; Release any BREAK clamp on the Tx data line. +; +; LPT ports will just return the comm error word +; +; Entry: +; AH = Device ID +; Returns: +; AX = comm error word +; Error Returns: +; AX = error code +; Registers Preserved: +; SI,DI,DS,ES +; Registers Destroyed: +; AX,BX,CX,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $CLRBRK +$CLRBRK proc near + + mov cx,(NOT ACE_SB) SHL 8 + .errnz BreakSet-ACE_SB ;Must be same bits + +ClrBrk10: + push si + call GetDEB ;Get DEB address + jc ClrBrk30 ;Invalid ID + js ClrBrk20 ;Ignored for LPT ports + FCLI + and HSFlag[si],ch ;Set or clear the BreakSet bit + or HSFlag[si],cl + +; ch = mask to remove bits in the Line Control Register +; cl = mask to turn bits on in the Line Control Register + + mov dx,Port[si] ;Get comm device base I/O port + add dl,ACE_LCR ;Point at the Line Control Regieter + pin al,dx ;Get old line control value + and al,ch ;Turn off desired bits + or al,cl ;Turn on desired bits + pause + pout dx,al ;Output New LCR. + FSTI + +ClrBrk20: + mov ax,ComErr[si] ;Return Status Word + +ClrBrk30: + pop si + ret + +$CLRBRK endp + +page + +;----------------------------Public Routine-----------------------------; +; +; $EXTCOM - Extended Comm Functions +; +; A number of extended functions are routed through this entry point. +; +; Functions currently implemented: +; +; 0: Ignored +; 1: SETXOFF - Exactly as if X-OFF character has been received. +; 2: SETXON - Exactly as if X-ON character has been received. +; 3: SETRTS - Set the RTS signal +; 4: CLRRTS - Clear the RTS signal +; 5: SETDTR - Set the DTR signal +; 6: CLRDTR - Clear the DTR signal +; 7: RESET - Yank on reset line if available (LPT devices) +; +; Entry: +; AH = Device ID +; BL = Function Code +; (0-127 are MS-defined, 128-255 are OEM defined) +; Returns: +; AX = comm error word +; Error Returns: +; AX = error code +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + +; Dispatch table for the extended functions + +ExtTab dw ExtComDummy ;Function 0: Never Mind + dw ExtCom_FN1 ;1: Set X-Off + dw ExtCom_FN2 ;2: Clear X-Off + dw ExtCom_FN3 ;3: Set RTS + dw ExtCom_FN4 ;4: Clear RTS + dw ExtCom_FN5 ;5: Set DSR + dw ExtCom_FN6 ;6: Clear DSR + dw ExtCom_FN7 ;7: Reset printer + + assumes ds,Data + assumes es,nothing + + public $EXTCOM +$EXTCOM proc near + + push si + call GetDEB ;Get DEB pointer + jc ExtCom40 ;Invalid ID, return error + mov dx,Port[si] ; get port address + jns ExtCom10 ;Its a COM port + cmp bl,7 ;RESET extended function? + jne ExtCom30 ; No, return error word + jmp short ExtCom20 ; Yes, invoke the function + +ExtCom10: + cmp bl,7 ;Last fcn supported +1 + jnc ExtCom30 ;Not an implemented function. + +ExtCom20: + xor bh,bh + add bx,bx ;Shift for the call + FCLI ;Consider as critical sections + call ExtTab[bx] ; and perform the function + FSTI + +ExtCom30: + mov ax,ComErr[si] ;Return standard error word + +ExtCom40: + pop si + +ExtComDummy: + ret + +$EXTCOM endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN1 - Extended Function Set X-Off +; +; Analagous to receiving an X-OFF character. Bufferred transmision of +; characters is halted until an X-ON character is received, or until +; we fake that with a Clear X-Off call. +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public ExtCom_FN1 +ExtCom_FN1 proc near + + or HSFlag[si],XOffReceived + ret + +ExtCom_FN1 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN2 - Extended Function Clear X-Off +; +; Analagous to receiving an X-ON character. Buffered +; transmission of characters is restarted. +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public ExtCom_FN2 +ExtCom_FN2 proc near + + and HSFlag[si],NOT XOffReceived + jmp KickTx ;Kick transmitter interrupts on + +ExtCom_FN2 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN3 - Extended Function Set RTS +; +; Set the RTS signal active. +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public ExtCom_FN3 +ExtCom_FN3 proc near + + add dl,ACE_MCR ;Point at Modem Control Register + pin al,dx ;Get current settings + or al,ACE_RTS ;Set RTS + pause + pout dx,al ;And update + ret + +ExtCom_FN3 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN4 - Extended Function Clear RTS +; +; Set the RTS signal inactive. +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public ExtCom_FN4 +ExtCom_FN4 proc near + + add dl,ACE_MCR ;Point at Modem Control Register + pin al,dx ;Get current settings + and al,NOT ACE_RTS ;Clear RTS + pause + pout dx,al ;And update + ret + +ExtCom_FN4 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN5 - Extended Function Set DTR +; +; Set the DTR signal active. +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public ExtCom_FN5 +ExtCom_FN5 proc near + + add dl,ACE_MCR ;Point at Modem Control Register + pin al,dx ;Get current settings + or al,ACE_DTR ;Set DTR + pause + pout dx,al ;And update + ret + +ExtCom_FN5 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN6 - Extended Function Clear DTR +; +; Set the DTR signal inactive. +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public ExtCom_FN6 +ExtCom_FN6 proc near + + add dl,ACE_MCR ;Point at Modem Control Register + pin al,dx ;Get current settings + and al,NOT ACE_DTR ;Clear DTR + pause + pout dx,al ;And update + ret + +ExtCom_FN6 endp +page + +;----------------------------Private-Routine----------------------------; +; +; ExtCom_FN7 - Extended Function Reset Printer +; +; Assert the RESET line on an LPT port +; +; Entry: +; interrupts disabled +; dx = port base address +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public ExtCom_FN7 +ExtCom_FN7 proc near + + FSTI ;Not called at interrupt time + mov ch,1 ;ROM BIOS Reset Port + call DoLPT ;Perform the function + ret + +ExtCom_FN7 endp +page + +;----------------------------Public Routine-----------------------------; +; +; $DCBPtr - Return Pointer To DCB +; +; Returns a long pointer to the DCB for the requested device. +; +; Entry: +; AH = Device ID +; Returns: +; DX:AX = pointer to DCB. +; Error Returns: +; DX:AX = 0 +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; BX,CX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public $DCBPTR +$DCBPTR proc near + + push si + xor dx,dx + call GetDEB ;Get pointer to DEB + mov ax,dx + jc DCBPtr10 ;Jump if invalid device + mov ax,si ;else return value here + mov dx,ds + +DCBPtr10: + pop si + ret + +$DCBPTR endp +page + +;----------------------------Public Routine-----------------------------; +; +; $RECCOM - Receive Characters From Device +; +; Read Byte From RS232 Input Queue If Data Is Ready +; +; LPT ports will return with an indication that no characters are +; available. +; +; Entry: +; AH = Device ID +; Returns: +; 'Z' clear if data available +; AL = byte +; Error Returns: +; 'Z' Set if error or no data +; AX = error code +; AX = 0 if no data +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $RECCOM +$RECCOM proc near + + push si ;Once again, save some registers + push di + call GetDEB ;Get DEB pointer in SI + jc RecCom10 ;Invalid Port [rkh] ... + js RecCom20 ;LPT port, return no characters + jmp short RecCom30 + +RecCom10: + jmp RecCom100 ; Invalid Port + +RecCom20: + jmp RecCom95 ;LPT port, return no characters + +; Before removing any charcters from the input queue, check to see +; if XON needs to be issued. If it needs to be issued, set the +; flag that will force it and arm transmit interrupts. + +RecCom30: + test Flags[si],fEnqAck+fEtxAck ;Enq or Etx Ack? + jz RecCom32 ; No + test HSFlag[si],EnqReceived+HHSDropped ;Enq recvd or lines dropped? + jz RecCom60 ; No Enq recvd & no lines dropped + jmp short RecCom34 + +RecCom32: + test HSFlag[si],HSSent ;Handshake sent? + jz RecCom60 ; No XOFF sent & no lines dropped + +RecCom34: + mov ax,QInCount[si] ;Get current count of input chars + cmp ax,XONLim[si] ;See if at XOn limit + ja RecCom60 ;Not at XOn limit yet + +; If any hardware lines are down, then raise them. Then see +; about sending XON. + + mov dx,Port[si] ;Get the port + mov ah,HHSLines[si] ;Get hardware lines mask + FCLI ;Handle this as a critical section + mov cl,HSFlag[si] ;Get handshaking flags + or ah,ah ;Any hardware lines to play with? + jz RecCom40 ; No + add dl,ACE_MCR ;--> Modem control register + pin al,dx + or al,ah ;Turn on the hardware bits + pause + pout dx,al + and cl,NOT HHSDropped ;Show hardware lines back up + +RecCom40: + test Flags[si],fEnqAck+fEtxAck ;Enq or Etx Ack? + jz RecCom47 ; No + test cl,EnqReceived ;Did we receive Enq? + jz RecCom55 ; No + and cl,NOT EnqReceived + jmp short RecCom50 + +RecCom47: + test cl,XOffSent ;Did we send XOFF? + jz RecCom55 ; No + and cl,NOT XOffSent ;Remove XOFF sent flag + +RecCom50: + or cl,XOnPending ;Show XON or ACK must be sent + call KickTx ;Kick xmit if needed + +RecCom55: + mov HSFlag[si],cl ;Store handshake flag + FSTI ;Can allow interrupts now + +; Now we can get down to the business at hand, and remove a character +; from the receive queue. If a communications error exists, we return +; that, and nothing else. + +RecCom60: + xor ax,ax + or ax,ComErr[si] ;Any Errors? + jnz RecCom100 ; Yes, return the error code + or ax,QInCount[si] ;Get current input char count + jz RecCom90 ;No characters in the queue + les di,QInAddr[si] ;Get queue pointer + assumes es,nothing + + mov bx,QInGet[si] ;Also get the index to head + mov al,es:[bx][di] ;Finally, get byte from queue + inc bx ;Update queue index + cmp bx,QInSize[si] ;See if time for wrap-around + jc RecCom70 ;Jump if no wrap + xor bx,bx ;wrap by zeroing the index + +RecCom70: + mov QInGet[si],bx ;Save new head pointer + dec QInCount[si] ;Dec # of bytes in queue + +RecCom80: + or sp,sp ;Reset PSW.Z + pop di + pop si + ret + +; No characters in the input queue. Check to see if EOF +; was received, and return it if it was. Otherwise show +; no characters. + +RecCom90: + test Flags[si],fBinary ;Are we doing binary stuff? + jnz RecCom95 ; Yes, show no characters + mov al,EOFChar[si] ;Assume EOF + test EFlags[si],fEOF ;Has end of file char been received? + jnz RecCom80 ; Yes, show end of file + +RecCom95: + xor ax,ax ;Show no more characters + +; Return with 'Z' to show error or no characters + +RecCom100: + xor cx,cx ;Set PSW.Z + pop di + pop si + ret + +$RECCOM endp +page + +;----------------------------Public Routine-----------------------------; +; +; $FLUSH - Flush The Input and Output Queues +; +; This is a hard initialization of the transmit and receive queue's, +; which immediately empties the given queue. +; +; LPT ports will just return the device error word +; +; Entry: +; AH = Device ID +; BH = Queue # to clear (0=Tx, 1=Rx) +; Returns: +; AX = Device Error Word. (Not reset) +; Error Returns: +; AX = error code +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public $FLUSH +$FLUSH proc near + + push si + push di + call GetDEB ;si --> DEB + jc Flush40 ;Invalid ID + js Flush30 ;LPT port, return any error + + mov cx,QOutCount-QInCount ;# of bytes to zero + lea di,QInCount[si] ;--> receive queue data + or bh,bh ;Transmit queue? + jnz Flush10 ; No, input queue + add di,cx ; Yes, --> xmit queue data + +Flush10: + cld + push ds + pop es + assumes es,nothing + + xor al,al + FCLI ;Time to worry about critical sections + rep stosb + FSTI + .errnz QInGet-QInCount-2 + .errnz QInPut-QInGet-2 + .errnz QOutCount-QInPut-2 + .errnz QOutGet-QOutCount-2 + .errnz QOutPut-QOutGet-2 + + or bh,bh ;Rx queue? + jz Flush30 ; No, xmit queue + + +; If the queue to be cleared is the receive queue, any +; hardware handshake must be cleared to prevent a possible +; deadlock situation. Since we just zeroed the queue count, +; a quick call to $RecCom should do wonders to clear any +; receive handshake (i.e. send XON if needed). + +Flush20: + call $RECCOM ;Take care of handshakes here + +Flush30: + mov ax,ComErr[si] ;And return the error word. + +Flush40: + pop di + pop si + ret + +$FLUSH endp + +ifdef DEBUG + public KickTx10 + public GetDEB10 + public GetDEB20 + public GetDEB30 + public SetQue10 + public Evt10 + public EvtGet10 + public StaCom20 + public StaCom25 + public StaCom30 + public ClrBrk10 + public ClrBrk20 + public ClrBrk30 + public ExtCom10 + public ExtCom20 + public ExtCom30 + public ExtCom40 + public ExtComDummy + public DCBPtr10 + public RecCom30 + public RecCom40 + public RecCom50 + public RecCom60 + public RecCom70 + public RecCom80 + public RecCom90 + public RecCom95 + public RecCom100 + public Flush10 + public Flush20 + public Flush30 + public Flush40 +endif diff --git a/private/mvdm/wow16/drivers/comm/ibmint.asm b/private/mvdm/wow16/drivers/comm/ibmint.asm new file mode 100644 index 000000000..d902841f2 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/ibmint.asm @@ -0,0 +1,1374 @@ +page,132 +;---------------------------Module-Header------------------------------- +; Module Name: IBMINT.ASM +; +; Created: Fri 06-Feb-1987 10:45:12 +; Author: Walt Moore [waltm] +; +; Copyright (c) Microsoft Corporation 1985-1990. All Rights Reserved +; +; General Description: +; This file contains the interrupt time routines for the +; IBM Windows communications driver. +; +; The interrupt code is preloaded and fixed. +; +; History: +; +; ********************************************************************** +; Tue Dec 19 1989 09:35:15 -by- Amit Chatterjee [amitc] +; ---------------------------------------------------------------------- +; Added a far entry point 'FakeCOMIntFar' so that the routine 'FakeCOMInt' +; could be called from the 'InitAPort' routine in IBMCOM.ASM +; +; 26.Nov.90 richp +; +; Changed interrupt routines to use new VPICD services for bi-modal/multi- +; modal interrupt handling. They now work in straight real mode for real +; mode Windows, but can also handle interrupts in real mode or protected +; mode for standard mode Windows, and handle interrupts in RING 0 protected +; mode for enhanced mode Windows, even when the Windows VM is not currently +; executing. +; +; sudeepb 10-Jan-1993 changed the costly cli/sti with non-trapping +; FCLI/FSTI macros +;-----------------------------------------------------------------------; + +subttl Communications Hardware Interrupt Service Routines + +.xlist +include cmacros.inc +include comdev.inc +include ibmcom.inc +include ins8250.inc +include BIMODINT.INC +include vint.inc +.list + +externFP GetSystemMsecCount + +externW COMptrs +externW activeCOMs + +externD lpPostMessage + +sBegin Data + +PUBLIC IRQhooks +IRQhooks label byte +DefineIRQhook MACRO num +IFDEF No_DOSX_Bimodal_Services +IRQhook&num IRQ_Hook_Struc <,,,,IntCodeOFFSET DEF_COM_INT_&num,,,, \ + IntCodeOFFSET DEF_RM_COM_INT_&num> +ELSE +IRQhook&num IRQ_Hook_Struc <,,,,IntCodeOFFSET DEF_COM_INT_&num> +ENDIF +ENDM +??portnum = 1 +REPT MAXCOM+1 + DefineIRQhook %??portnum +??portnum = ??portnum+1 +ENDM + +PURGE DefineIRQhook + +EXTRN VCD_int_callback:fword + +sEnd data + +createSeg _INTERRUPT,IntCode,word,public,CODE +sBegin IntCode +assumes cs,IntCode + +page + +IFDEF No_DOSX_Bimodal_Services +public RM_IntDataSeg +RM_IntDataSeg dw 0 + ; this variable is written into by a routine in inicom + ; if the 286 DOS extender is present. This variable + ; contains the SEGMENT value of the data selector "_DATA" + ; so that the real mode interrupt handler may use the + ; data segment, and not it's selector ! + +PUBLIC RM_CallBack +RM_CallBack dd 0 +ENDIF + + +Control proc far + ret +Control endp + + +IFDEF No_DOSX_Bimodal_Services +DEF_RM_Handler proc far + push es + push di + push ax + mov es, cs:[RM_IntDataSeg] + mov di, es:[di.First_DEB] ; ES:DI -> ComDEB + add di, SIZE ComDEB ; ES:DI -> BIS + mov es:[di.BIS_Mode], 4 + push cs + call NEAR PTR COMHandler + mov es:[di.BIS_Mode], 0 + pop ax + pop di ; ES:DI -> IRQ_Hook_Struc + jc short DEF_RM_chain + pop es + pop di + add sp, 4 + iret + +DEF_RM_chain: + call DOCLI + push bp + mov bp, sp ;stack frame: + ; bp+8 -> OldInt CS + ; bp+6 -> OldInt IP + ; bp+4 -> di + ; bp+2 -> es + ; bp+0 -> bp + les di, es:[di.RM_OldIntVec] + mov [bp+6], di + mov [bp+8], es + pop bp + pop es + pop di + ret ; far ret to OldInt handler +DEF_RM_Handler endp +ENDIF ;No_DOSX_Bimodal_Services + + +Define_DEF_COM_INT MACRO num +IFDEF No_DOSX_Bimodal_Services +PUBLIC DEF_RM_COM_INT_&num +DEF_RM_COM_INT_&num proc far + sub sp, 4 + push di + mov di, DataOFFSET IRQhook&num + jmp DEF_RM_Handler +DEF_RM_COM_INT_&num endp +ENDIF +PUBLIC DEF_COM_INT_&num +DEF_COM_INT_&num proc far + sub sp, 4 + push di + mov di, DataOFFSET IRQhook&num + jmp DEF_Handler +DEF_COM_INT_&num endp +ENDM + +??portnum = 2 +REPT MAXCOM + Define_DEF_COM_INT %??portnum +??portnum = ??portnum+1 +ENDM + +PURGE Define_DEF_COM_INT + +IFDEF No_DOSX_Bimodal_Services +PUBLIC DEF_RM_COM_INT_1 +DEF_RM_COM_INT_1 proc far + sub sp, 4 + push di + mov di, DataOFFSET IRQhook1 + jmp DEF_RM_Handler +DEF_RM_COM_INT_1 endp +ENDIF + +PUBLIC DEF_COM_INT_1 +DEF_COM_INT_1 proc far + sub sp, 4 + push di + mov di, DataOFFSET IRQhook1 +IF2 +.errnz $ - OFFSET DEF_Handler +ENDIF +DEF_COM_INT_1 endp + +DEF_Handler proc far + push es + push di + push ax + mov ax, _DATA + mov es, ax + mov di, es:[di.First_DEB] ; ES:DI -> ComDEB + add di, SIZE ComDEB ; ES:DI -> BIS + push cs + call NEAR PTR COMHandler + pop ax + pop di ; ES:DI -> IRQ_Hook_Struc + jc short DEF_chain + pop es + pop di + add sp, 4 + iret + +DEF_chain: + call DOCLI + push bp + mov bp, sp ;stack frame: + ; bp+8 -> OldInt CS + ; bp+6 -> OldInt IP + ; bp+4 -> di + ; bp+2 -> es + ; bp+0 -> bp + les di, es:[di.OldIntVec] + mov [bp+6], di + mov [bp+8], es + pop bp + pop es + pop di + ret ; far ret to OldInt handler +DEF_Handler endp + +;------------------------------------------------------------------------------ +; +; ENTER: ES:DI -> BIS +; +; EXIT: Carry set, if IRQ not handled by any com ports +; +COMHandler proc far + push ds + push si + push ax + push bx + mov si, es + mov ds, si + mov bh, -1 +ch_chk_all: + lea si, [di-SIZE ComDEB] ;ds:si -> ComDEB + mov si, [si.IRQhook] + mov si, [si.First_DEB] + mov bl, -1 +ch_next_com: + inc bl ; first time bl = 0 + xor ax, ax + xchg ax, [di.BIS_Mode] + lea di, [si+SIZE ComDEB] + mov [di.BIS_Mode], ax + call CommInt + and al, 80h + or bl, al + + mov si, [si.NextDEB] + or si, si + jnz ch_next_com + + test bl, 7Fh ;Q: more than 1 com port? + jnz short ch_shared ; Y: check if handled + or bl, bl ;Q: int handled by port? + stc + jns ch_exit ; N: + +ch_eoi: + xor ax, ax +.errnz BIH_API_EOI + xor bx, bx + xchg bx, es:[di.BIS_Mode] + call es:[bx][di.BIS_User_Mode_API] + lea si, [di-SIZE ComDEB] ; ds:si -> ComDEB + mov si, [si.IRQhook] + mov al, [si.OldMask] + shr al, 1 ; shift bit 0 into Carry (0, if unmasked + cmc ; -1, if originally masked) + +ch_exit: + pop bx + pop ax + pop si + pop ds + ret + +ch_shared: + inc bh ; count loop + or bl, bl ;Q: int handled by any port? + js ch_chk_all ; Y: check all ports again + or bh, bh ;Q: first time thru loop? + stc + jz ch_exit ; Y: int wasn't for a COM port, so + ; chain to next IRQ handler + jmp ch_eoi + +COMHandler endp + + +IFDEF No_DOSX_Bimodal_Services + +PUBLIC Entry_From_RM +Entry_From_RM proc far + +; +; Simulate the far ret +; + cld + lodsw + mov es:[di.RealMode_IP], ax + lodsw + mov es:[di.RealMode_CS], ax + add es:[di.RealMode_SP], 4 + + push es + push di +.286 +; +; Push far addr of Ret_To_IRET to cleanup stack and return to DPMI host +; + push cs + push IntCodeOFFSET Ret_To_IRET +; +; Push far addr of proc to call, so we can do a far ret to it +; + push es:[di.RealMode_CX] ; segment of callback + push es:[di.RealMode_DX] ; offset of callback + mov di, es:[di.RealMode_DI] + ret ; far ret to cx:dx + ; called proc will do a far ret +Ret_To_IRET: ; <- to here + pop di + pop es + iret +.8086 + +Entry_From_RM endp + +PUBLIC RM_APIHandler +RM_APIHandler proc far + cmp ax, BIH_API_Call_Back + jne APIHandler + call cs:[RM_CallBack] + ret +RM_APIHandler endp + +ENDIF + +;------------------------------------------------------------------------------ +; +; ENTER: ES:DI -> BIS +; +APIHandler proc far + + or ax, ax + jnz short api_not_EOI +.errnz BIH_API_EOI + mov ax, es:[di.BIS_IRQ_Number] + cmp al,8 ;Q: slave IRQ? + mov al,EOI + jb short api_master ; N: + out 0A0h,al ; Y: EOI slave +api_master: + out INTA0,al ; EOI master + ret + +api_not_EOI: + cmp ax, BIH_API_Call_Back + jae short api_callme + push dx + push cx + mov dx, INTA1 + mov cx, es:[di.BIS_IRQ_Number] + cmp cl, 8 ;Q: 2nd PIC? + jb @f ; N: + mov dx, 0A1h ; Y: dx = mask port + sub cl, 8 +@@: + cmp al, BIH_API_Get_Mask ;Q: get IRQ mask? + jae api_get_mask ; Y: + mov ah, al + mov ch, 1 + shl ch, cl ; ch = mask byte + pushf + call DOCLI + in al, dx ; get current PIC mask state + cmp ah, BIH_API_Mask ;Q: mask IRQ? + jne @f ; N: + or al, ch ; Y: set IRQ's bit + jmp short api_mask_exit +@@: + not ch ; N: clear IRQ's bit to unmask + and al, ch +api_mask_exit: + out dx, al + pop ax + test ah, 2 ;Q: ints were enabled? + jz @f ; N: + call DOSTI +@@: + pop cx + pop dx + ret + +api_get_mask: + in al, dx ; get current PIC mask state + inc cl + shr al, cl ; move IRQ's bit into carry + ; Carry set, if IRQ masked + pop cx + pop dx + ret + +api_callme: + push cx + push dx + ret ; far ret to call back, which will + ; do a far ret to our caller +APIHandler endp + + +;--------------------------Fake a Hardware Interrupt----------------------; +; FakeCOMInt +; +; This routine fakes a hardware interrupt to IRQ3 or IRQ4 +; to clear out characters pending in the buffer +; +; Entry: +; DS:SI --> DEB +; INTERRUPTS DISABLED! +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; +; Registers Destroyed: +; AX,DX,FLAGS +; History: glenn steffler 5/17/89 +;-----------------------------------------------------------------------; + +FakeCOMInt proc near + + ; call DOCLI ;Done by caller +; +; WARNING: jumping into the middle of CommInt, so the stack must be set +; properly. +; + push dx + push bx + push cx + push di + push es + push EvtWord[si] + mov dx,Port[si] ;Get device I/O address + add dl, ACE_IIDR + push dx + jmp FakeXmitEmpty ;Process the fake interrupt, DS:SI is + ; already pointing to proper DEB +; +; FakeXmitEmpty falls in XmitEmpty which jumps back into CommInt. When CommInt +; determines that no interrupt is pending, then it will near return back to +; FakeCOMIntFar which can far ret back to its caller. +; +FakeCOMInt endp + +public FakeCOMIntFar +FakeCOMIntFar proc far + + call FakeCOMInt + ret + +FakeCOMIntFar endp + +;--------------------------Interrupt Handler---------------------------- +; +; CommInt - Interrupt handler for com ports +; +; Interrupt handlers for PC com ports. This is the communications +; interrupt service routine for RS232 communications. When an RS232 +; event occurs the interrupt vectors here. This routine determines +; who the caller was and services the appropriate interrupt. The +; interrupts are prioritized in the following order: +; +; 1. line status interrupt +; 2. read data available interrupt +; 3. transmit buffer empty interrupt +; 4. modem service interrupt +; +; This routine continues to service until all interrupts have been +; satisfied. +; +; Entry: +; DS:SI --> DEB +; INTERRUPTS DISABLED! +; Returns: +; AL = 0, if not handled, -1, if handled +; +;----------------------------------------------------------------------- + +assumes ds,Data +assumes es,nothing + +; Dispatch table for interrupt types + +SrvTab label word + dw OFFSET ModemStatus ;[0] Modem Status Interrupt + dw OFFSET XmitEmpty ;[2] Tx Holding Reg. Interrupt + dw OFFSET DataAvail ;[4] Rx Data Available Interrupt + ; or [C] if 16550 & 16550A + dw OFFSET LineStat ;[6] Reciever Line Status Interrupt + + + public CommInt + +CommInt proc near + + xor al, al + cmp word ptr [VCD_int_callback+4], 0 + je short @F ; jump if no callback (not 3.1 VCD) + test [si.VCDflags], fCOM_ignore_ints ;Q: we still own port? + jnz IntLoop40 ; N: ignore the int +.386 + push esi + mov esi, [si.VCD_data] + call [VCD_int_callback] + pop esi +.8086 +@@: + + push dx + mov dx,Port[si] ;Get comm I/O port + add dl,ACE_IIDR ;--> Interrupt ID Register + in al, dx + test al, 1 ;Q: interrupt pending? + jnz short IntLoop30 ; N: + + push bx + push cx + push di + push es + mov cx, EvtWord[si] + push cx + jmp short IntLoop10 + +InterruptLoop_ChkTx: + cmp QOutCount[si],0 ;Output queue empty? + je short InterruptLoop ; Y: don't chk tx + pop dx + push dx + dec dx ; to IER +.errnz ACE_IIDR - ACE_IER - 1 + in al, dx + and al,NOT ACE_ETBEI ; disable it + iodelay + out dx, al + or al, ACE_ETBEI ; enable it again + iodelay + out dx, al + iodelay + out dx, al + +InterruptLoop: + pop dx ;Get ID reg I/O address + + in al,dx ;Get Interrupt Id + test al,1 ;Interrupt need servicing? + jnz IntLoop20 ;No, all done + +IntLoop10: + and ax, 07h + mov di,ax + push dx ;Save Id register + jmp SrvTab[di] ;Service the Interrupt + +IntLoop20: + mov ax,EvtMask[si] ;Mask the event word to only the + and ax, EvtWord[si] ; user specified bits + mov EvtWord[si], ax + pop bx + test [si.NotifyFlagsHI], CN_Notify + jz short ci_exit + not bx + and ax, bx ; bits set in ax are new events + jnz short ci_new_events + +ci_exit: + pop es + assumes es,nothing + + pop di + pop cx + pop bx + xor al, al + +IntLoop30: + pop dx + and al, 1 + dec al ; 0->-1, 1->0 +IntLoop40: + ret + +ci_new_events: + mov ax, CN_EVENT + call notify_owner + jmp ci_exit + +CommInt endp + +page + +;----------------------------Private-Routine----------------------------; +; +; LineStat - Line Status Interrupt Handler +; +; Break detection is handled and set in the event word if +; enabled. Other errors (overrun, parity, framing) are +; saved for the data available interrupt. +; +; This routine used to fall into DataAvail for the bulk of its processing. +; This is no longer the case... A very popular internal modem seems to +; operate differently than a real 8250 when parity errors occur. Falling +; into the DataAvail handler on a parity error caused the same character +; to be received twice. Having this routine save the LSR status, and +; return to InterruptLoop fixes the problem, and still works on real COMM +; ports. The extra overhead isn't a big deal since this routine is only +; entered when there is an exception like a parity error. +; +; This routine is jumped to, and will perform a jump back into +; the dispatch loop. +; +; Entry: +; DS:SI --> DEB +; DX = Port.IIDR +; Returns: +; None +; Error Returns: +; None +; Registers Destroyed: +; AX,FLAGS +; History: +;-----------------------------------------------------------------------; + + +; assumes ds,Data +assumes es,nothing + +public LineStat ;Public for debugging +LineStat proc near + + or by EvtWord[si],EV_Err ;Show line status error + + add dl,ACE_LSR-ACE_IIDR ;--> Line Status Register + in al,dx + test al,ACE_PE+ACE_FE+ACE_OR ;Parity, Framing, Overrun error? + jz @f + + mov LSRShadow[si],al ;yes, save status for DataAvail +@@: + test al,ACE_BI ;Break detect? + jz InterruptLoop_ChkTx ;Not break detect interrupt + + or by EvtWord[si],EV_Break ;Show break + + jmp short InterruptLoop_ChkTx + +LineStat endp + +page + +;----------------------------Private-Routine----------------------------; +; +; DataAvail - Data Available Interrupt Handler +; +; The available character is read and stored in the input queue. +; If the queue has reached the point that a handshake is needed, +; one is issued (if enabled). EOF detection, Line Status errors, +; and lots of other stuff is checked. +; +; This routine is jumped to, and will perform a jump back into +; the dispatch loop. +; +; Entry: +; DS:SI --> DEB +; DX = Port.IIDR +; Returns: +; None +; Error Returns: +; None +; Registers Destroyed: +; AX,BX,CX,DI,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +; assumes ds,Data +assumes es,nothing + +public DataAvail ;public for debugging +DataAvail proc near + + sub dl,ACE_IIDR-ACE_RBR ;--> receiver buffer register + in al,dx ;Read received character + + and [si.NotifyFlagsHI], NOT CN_Idle ; flag as not idle + + mov ah,LSRShadow[si] ;what did the last Line Status intrpt + mov bh,ah ; have to say? + or ah,ah + jz @f + + and ah,ErrorMask[si] ;there was an error, record it + or by ComErr[si],ah + mov LSRShadow[si],0 + .errnz ACE_OR-CE_OVERRUN ;Must be the same bits + .errnz ACE_PE-CE_RXPARITY + .errnz ACE_FE-CE_FRAME + .errnz ACE_BI-CE_BREAK +@@: + +; Regardless of the character received, flag the event in case +; the user wants to see it. + + or by EvtWord[si],EV_RxChar ;Show a character received + .errnz HIGH EV_RxChar + +; Check the input queue, and see if there is room for another +; character. If not, or if the end of file character has already +; been received, then go declare overflow. + +DataAvail00: + + mov cx,QInCount[si] ;Get queue count (used later too) + cmp cx,QInSize[si] ;Is queue full? + jge DataAvail20 ; Yes, comm overrun + test EFlags[si],fEOF ;Has end of file been received? + jnz DataAvail20 ; Yes - treat as overflow + +; Test to see if there was a parity error, and replace +; the character with the parity character if so + + test bh,ACE_PE ;Parity error + jz DataAvail25 ; No + test [si.DCB_Flags2],fPErrChar ;Parity error replacement character? + jz DataAvail25 ; No + mov al,[si.DCB_PEChar] ; Yes, get parity replacement char + +; Skip all other processing except event checking and the queing +; of the parity error replacement character + + jmp short DataAvail80 ;Skip all but event check, queing + +DataAvail20: + or by ComErr[si],CE_RXOVER ;Show queue overrun + jmp short DataAvail50 + +; See if we need to strip null characters, and skip +; queueing if this is one. Also remove any parity bits. + +DataAvail25: + and al,RxMask[si] ;Remove any parity bits + jnz DataAvail30 ;Not a Null character + test [si.DCB_Flags2],fNullStrip ;Are we stripping received nulls? + jnz DataAvail50 ; Yes, put char in the bit bucket + +; Check to see if we need to check for EOF characters, and if so +; see if this character is it. + +DataAvail30: + test [si.DCB_Flags],fBinary ;Is this binary stuff? + jnz DataAvail60 ; Yes, skip EOF check + cmp al,[si.DCB_EOFChar] ;Is this the EOF character? + jnz DataAvail60 ; No, see about queing the charcter + or EFlags[si],fEOF ;Set end of file flag +DataAvail50: + jmp DataAvail140 ;Skip the queing process + +; If output XOn/XOff is enabled, see if the character just received +; is either an XOn or XOff character. If it is, then set or +; clear the XOffReceived flag as appropriate. + +DataAvail60: + test [si.DCB_Flags2],fOutX ;Output handshaking? + jz DataAvail80 ; No + cmp al,[si.DCB_XoffChar] ;Is this an X-Off character? + jnz DataAvail70 ; No, see about XOn or Ack + or HSFlag[si],XOffReceived ;Show XOff received, ENQ or ETX [rkh] + test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack? + jz DataAvail50 ; No + cmp cx,[si.DCB_XonLim] ;See if at XOn limit + ja DataAvail50 ; No + and HSFlag[si],NOT XOffReceived ;Show ENQ or ETX not received + and HSFlag[si], NOT XOnPending+XOffSent + mov al, [si.DCB_XonChar] + call OutHandshakingChar + jmp DataAvail50 ;Done + +DataAvail70: + cmp al,[si.DCB_XonChar] ;Is this an XOn character? + jnz DataAvail80 ; No, just a normal character + and HSFlag[si],NOT XOffReceived + test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack? + jz DataAvail75 ; No - jump to FakeXmitEmpty to get + ; transmitting going again + and HSFlag[si],NOT EnqSent + +DataAvail75: + jmp FakeXmitEmpty ;Restart transmit + +; Now see if this is a character for which we need to set an event as +; having occured. If it is, then set the appropriate event flag + + +DataAvail80: + cmp al,[si.DCB_EVTChar] ;Is it the event generating character? + jne DataAvail90 ; No + or by EvtWord[si],EV_RxFlag ;Show received specific character + +; Finally, a valid character that we want to keep, and we have +; room in the queue. Place the character in the queue. +; If the discard flag is set, then discard the character + +DataAvail90: + test MiscFlags[si], Discard ;Discarding characters ? + jnz DataAvail50 ; Yes + + lea bx, [si+SIZE ComDEB] ; DS:BX -> BIS + mov bx, [bx.BIS_Mode] ; mode will be either 0 or 4 + les di,QInAddr[si][bx] ;Get queue base pointer from either + assumes es,nothing ; QInAddr or AltQInAddr + + mov bx,QInPut[si] ;Get index into queue + mov es:[bx][di],al ;Store the character + inc bx ;Update queue index + cmp bx,QInSize[si] ;See if time for wrap-around + jc DataAvail100 ;Not time to wrap + xor bx,bx ;Wrap-around is a new zero pointer + +DataAvail100: + mov QInPut[si],bx ;Store updated pointer + inc cx ;And update queue population + mov QInCount[si],cx + +; If flow control has been enabled, see if we are within the +; limit that requires us to halt the host's transmissions + + cmp cx,XOffPoint[si] ;Time to see about XOff? + jc DataAvail120 ; Not yet + test HSFlag[si],HSSent ;Handshake already sent? + jnz DataAvail120 ; Yes, don't send it again + + mov ah,HHSLines[si] ;Should hardware lines be dropped? + or ah,ah ; (i.e. do we have HW HS enabled?) + jz DataAvail110 ; No + add dl,ACE_MCR ; Yes + in al,dx ;Clear the necessary bits + not ah + and al,ah + or HSFlag[si],HHSDropped ;Show lines have been dropped + out dx,al ; and drop the lines + sub dl,ACE_MCR + +DataAvail110: + test [si.DCB_Flags2],fInX ;Input Xon/XOff handshaking + jz DataAvail120 ; No + or HSFlag[si], XOffSent + mov al, [si.DCB_XoffChar] + call OutHandshakingChar + +DataAvail120: + cmp cx, [si.RecvTrigger] ;Q: time to call owner's callback? + jb short DataAvail130 ; N: + + test [si.NotifyFlagsHI], CN_RECEIVE + jnz short DataAvail140 ; jump if notify already sent and + ; data in buffer hasn't dropped + ; below threshold + mov ax, IntCodeOFFSET DataAvail140 + push ax + mov ax, CN_RECEIVE +%OUT probably should just set a flag and notify after EOI + jmp notify_owner + +DataAvail130: + and [si.NotifyFlagsHI], NOT CN_RECEIVE + +DataAvail140: + pop dx + push dx + add dl, ACE_LSR-ACE_IIDR + in al, dx + test al, ACE_DR ;Q: more data available? + jz @F ; N: + sub dl, ACE_LSR ; Y: go read it + in al, dx ;Read available character + jmp DataAvail00 +@@: + jmp InterruptLoop_ChkTx + +DataAvail endp + + +OutHandshakingChar proc near + + add dl, ACE_LSR + mov ah, al +@@: + in al, dx + test al, ACE_THRE + jz @B + sub dl, ACE_LSR + mov al, ah + out dx, al + ret + +OutHandshakingChar endp + + +page + +;----------------------------Private-Routine----------------------------; +; +; XmitEmpty - Transmitter Register Empty +; +; Entry: +; DS:SI --> DEB +; DX = Port.IIDR +; Returns: +; None +; Error Returns: +; None +; Registers Destroyed: +; AX,BX,CX,DI,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +; assumes ds,Data +assumes es,nothing + +public FakeXmitEmpty +FakeXmitEmpty: + pop dx + push dx + +; "Kick" the transmitter interrupt routine into operation. + + dec dl +.errnz ACE_IIDR - ACE_IER-1 + in al,dx ;Get current IER state + test al,ACE_ETBEI ;Interrupt already enabled? + jnz @F ; Yes, don't reenable it + or al,ACE_ETBEI ; No, enable it + out dx,al + iodelay ;8250, 8250-B bug requires + out dx,al ; writting register twice +@@: + add dl,ACE_LSR-ACE_IER ;--> Line Status Register + iodelay + in al,dx ;Is xmit really empty? + sub dl,ACE_LSR-ACE_THR ;--> Transmitter Holding Register + test al,ACE_THRE + jnz short XmitEmpty5 ; Y: send next char + jmp InterruptLoop ; N: return to processing loop + +public XmitEmpty +XmitEmpty proc near + + add dl,ACE_LSR-ACE_IIDR ;--> Line Status Register + in al,dx ;Is xmit really empty? + sub dl,ACE_LSR-ACE_THR ;--> Transmitter Holding Register + test al,ACE_THRE + jz Xmit_jumpto90 ;Transmitter not empty, cannot send + +; If the hardware handshake lines are down, then XOff/XOn cannot +; be sent. If they are up and XOff/XOn has been received, still +; allow us to transmit an XOff/XOn character. It will make +; a dead lock situation less possible (even though there are +; some which could happen that cannot be handled). + +XmitEmpty5: + mov ah,HSFlag[si] ;Get handshaking flag + test ah,HHSDown+BreakSet ;Hardware lines down or break set? + jnz Xmit_jumpto100 ; Yes, cannot transmit + +; Give priority to any handshake character waiting to be +; sent. If there are none, then check to see if there is +; an "immediate" character to be sent. If not, try the queue. + +XmitEmpty10: + test [si.DCB_Flags],fEnqAck+fEtxAck ;Enq or Etx Ack? + jnz XmitEmpty40 ; Yes + +XmitEmpty15: + test ah,HSPending ;XOff or XOn pending + jz XmitEmpty40 ; No + +XmitEmpty20: + and ah,NOT XOnPending+XOffSent + mov al,[si.DCB_XonChar] ;Get XOn character + +XmitEmpty30: + mov HSFlag[si],ah ;Save updated handshake flag + jmp XmitEmpty110 ;Go output the character + +Xmit_jumpto90: + jmp XmitEmpty90 + +; If any of the lines which were specified for a timeout are low, then +; don't send any characters. Note that by putting the check here, +; XOff and Xon can still be sent even though the lines might be low. + +; Also test to see if a software handshake was received. If so, +; then transmission cannot continue. By delaying the software check +; to here, XOn/XOff can still be issued even though the host told +; us to stop transmission. + +XmitEmpty40: + test ah,CannotXmit ;Anything preventing transmission? + jz XmitEmpty45 ; No +Xmit_jumpto100: + jmp XmitEmpty100 ; Yes, disarm and exit + +; If a character has been placed in the single character "transmit +; immediately" buffer, clear that flag and pick up that character +; without affecting the transmitt queue. + +XmitEmpty45: + test EFlags[si],fTxImmed ;Character to xmit immediately? + jz XmitEmpty515 ; No, try the queue + and EFlags[si],NOT fTxImmed ;Clear xmit immediate flag + mov al,ImmedChar[si] ;Get char to xmit + jmp XmitEmpty110 ;Transmit the character + +XmitEmpty515: + mov cx,QOutCount[si] ;Output queue empty? + jcxz Xmit_jumpto90 ; Yes, go set an event + + test [si.DCB_Flags],fEtxAck ;Etx Ack? + jz XmitEmpty55 ; No + mov cx,QOutMod[si] ;Get number bytes sent since last ETX + cmp cx,[si.DCB_XonLim] ;At Etx limit yet? + jne XmitEmpty51 ; No, inc counter + mov QOutMod[si],0 ; Yes, zero counter + or HSFlag[si],EtxSent ;Show ETX sent + jmp short XE_sendXOFF + +XmitEmpty51: + inc cx ; Update counter + mov QOutMod[si],cx ; Save counter + jmp short XmitEmpty59 ; Send queue character + +XmitEmpty55: + test [si.DCB_Flags],fEnqAck ;Enq Ack? + jz XmitEmpty59 ; No, send queue character + mov cx,QOutMod[si] ;Get number bytes sent since last ENQ + or cx,cx ;At the front again? + jnz XmitEmpty56 ; No, inc counter + mov QOutMod[si],1 ; Yes, send ENQ + or HSFlag[si],EnqSent ;Show ENQ sent +XE_sendXOFF: + mov al,[si.DCB_XoffChar] + jmp short XmitEmpty110 ;Go output the character + +XmitEmpty56: + inc cx ;Update counter + cmp cx,[si.DCB_XonLim] ;At end of our out buffer len? + jne XmitEmpty58 ; No + xor cx,cx ;Show at front again. + +XmitEmpty58: + mov QOutMod[si],cx ;Save counter + +XmitEmpty59: + lea bx, [si+SIZE ComDEB] ; DS:BX -> BIS + mov bx, [bx.BIS_Mode] ; mode will be either 0 or 4 + les di,QOutAddr[si][bx] ;Get queue base pointer from either + assumes es,nothing ; QOutAddr or AltQOutAddr + + mov bx,QOutGet[si] ;Get pointer into queue + mov al,es:[bx][di] ;Get the character + + inc bx ;Update queue pointer + cmp bx,QOutSize[si] ;See if time for wrap-around + jc XmitEmpty60 ;Not time for wrap + xor bx,bx ;Wrap by zeroing the index + +XmitEmpty60: + mov QOutGet[si],bx ;Save queue index + mov cx,QOutCount[si] ;Output queue empty? + dec cx ;Dec # of bytes in queue + mov QOutCount[si],cx ; and save new population + + out dx,al ;Send char + + cmp cx, [si.SendTrigger] ;Q: time to call owner's callback? + jae short XmitEmpty70 ; N: + + test [si.NotifyFlagsHI], CN_TRANSMIT + jnz short XmitEmpty80 ; jump if notify already sent and + ; data in buffer hasn't raised + ; above threshold + mov ax, IntCodeOFFSET XmitEmpty80 + push ax + mov ax, CN_TRANSMIT + jmp short notify_owner + +XmitEmpty70: + and [si.NotifyFlagsHI], NOT CN_TRANSMIT + +XmitEmpty80: +%OUT check fNoFIFO in EFlags[si] to determine if we can queue more output + jmp InterruptLoop + + +; No more characters to transmit. Flag this as an event. + +XmitEmpty90: + or by EvtWord[si],EV_TxEmpty + +; Cannot continue transmitting (for any of a number of reasons). +; Disable the transmit interrupt. When it's time resume, the +; transmit interrupt will be reenabled, which will generate an +; interrupt. + +XmitEmpty100: + inc dx ;--> Interrupt Enable Register + .errnz ACE_IER-ACE_THR-1 + in al,dx ;I don't know why it has to be read + and al,NOT ACE_ETBEI ; first, but it works this way +XmitEmpty110: + out dx,al + jmp InterruptLoop + +XmitEmpty endp + +page + +;----------------------------Private-Routine----------------------------; +; +; ModemStatus - Modem Status Interrupt Handler +; +; Entry: +; DS:SI --> DEB +; DX = Port.IIDR +; Returns: +; None +; Error Returns: +; None +; Registers Destroyed: +; AX,BX,CX,DI,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + + +; assumes ds,Data +assumes es,nothing + +public ModemStatus ;Public for debugging +ModemStatus proc near + +; Get the modem status value and shadow it for MSRWait. + + add dl,ACE_MSR-ACE_IIDR ;--> Modem Status Register + in al,dx + mov MSRShadow[si],al ;Save MSR data for others + mov ch,al ;Save a local copy + +; Create the event mask for the delta signals + + mov ah,al ;Just a lot of shifting + shr ax,1 + shr ax,1 + shr ah,1 + mov cl,3 + shr ax,cl + and ax,EV_CTS+EV_DSR+EV_RLSD+EV_Ring + or EvtWord[si],ax + + mov ah,ch ;[rkh]... + shr ah,1 + shr ah,1 + and ax,EV_CTSS+EV_DSRS + or EvtWord[si],ax + + mov ah,ch + mov cl,3 + shr ah,cl + and ax,EV_RLSD + or EvtWord[si],ax + + mov ah,ch + mov cl,3 + shl ah,cl + and ax,EV_RingTe + or EvtWord[si],ax + + .errnz EV_CTS-0000000000001000b + .errnz EV_DSR-0000000000010000b + .errnz EV_RLSD-0000000000100000b + .errnz EV_Ring-0000000100000000b + + .errnz EV_CTSS-0000010000000000b ;[rkh] + .errnz EV_DSRS-0000100000000000b + .errnz EV_RLSDS-0001000000000000b + .errnz EV_RingTe-0010000000000000b + + .errnz ACE_DCTS-00000001b + .errnz ACE_DDSR-00000010b + .errnz ACE_DRLSD-00001000b + .errnz ACE_RI-01000000b + + .errnz ACE_TERI-00000100b ;[rkh] + .errnz ACE_CTS-00010000b + .errnz ACE_DSR-00100000b + .errnz ACE_RLSD-10000000b + +ModemStatus10: + mov al,OutHHSLines[si] ;Get output hardware handshake lines + or al,al ;Any lines that must be set? + jz ModemStatus40 ;No hardware handshake on output + and ch,al ;Mask bits of interest + cmp ch,al ;Lines set for Xmit? + je ModemStatus20 ; Yes + or HSFlag[si],HHSDown ;Show hardware lines have dropped +ModemStatus30: + jmp InterruptLoop + +ModemStatus40: + jmp InterruptLoop_ChkTx + +; Lines are set for xmit. Kick an xmit interrupt if needed + +ModemStatus20: + and HSFlag[si],NOT (HHSDown OR HHSAlwaysDown) + ;Show hardware lines back up + mov cx,QOutCount[si] ;Output queue empty? + jcxz ModemStatus30 ; Yes, return to InterruptLoop + jmp FakeXmitEmpty ;Restart transmit + +ModemStatus endp + +page + +;------------------------------------------------------------------------------ +; +; ENTER: AX = message # +; DS:SI -> DEB +notify_owner proc near + + or [si.NotifyFlags], ax + lea di, [si+SIZE ComDEB] + mov ax, ds + mov es, ax + mov ax, BIH_API_Call_Back ; call immediate, or in protected mode + mov bx, 1 ; force SYS VM, if enhanced mode + mov cx, _INTERRUPT + mov dx, IntCodeOFFSET callback_event +%OUT use equate + push ds + push si + mov si, 1 ; low priority boost + push bp + mov bp, es:[di.BIS_Mode] + call es:[bp][di.BIS_User_Mode_API] + pop bp + pop si + pop ds + ret + +notify_owner endp + +;------------------------------------------------------------------------------ +; +; ENTER: ES:DI -> BIS +; +callback_event proc far + lea si, [di-SIZE ComDEB] + mov ax, es + mov ds, ax + mov ax, [si.NotifyHandle] + push ax ; push hWnd + mov ax, WM_COMMNOTIFY + push ax ; push wMsg + xor ax, ax + mov al, [si.DCB_Id] + push ax ; push wParam = ComID + xor al, al + push ax ; push high word of lParam + xchg al, [si.NotifyFlagsLO] + or [si.NotifyFlagsHI], al + push ax ; push low word of lParam = event flags + call [lpPostMessage] + ret +callback_event endp + + +PUBLIC TimerProc +TimerProc proc far + + push ds + mov ax, _DATA + mov ds, ax + assumes ds,data + + mov ax, [activeCOMs] + or ax, ax + jz short tp_nonactive + push si + mov si, DataOFFSET COMptrs + mov cx, MAXCOM+1 +tp_lp: + push si + mov si, [si] ; si -> ComDEB + shr ax, 1 + jnc tp_lpend + + cmp [si.RecvTrigger], -1 ;Q: owner wants notification? + je short tp_lpend ; N: skip notify + cmp [si.QInCount], 0 ;Q: anything in input queue? + je short tp_lpend ; N: skip notify + test [si.NotifyFlagsHI], CN_RECEIVE ;Q: timeout notify already given? + jnz short tp_lpend ; N: skip notify + + xor [si.NotifyFlagsHI], CN_Idle ;Q: first timer call? + js short tp_lpend ; Y: skip notify + + push ax + push cx + mov ax, CN_RECEIVE ; N: notify owner + call notify_owner + pop cx + pop ax + +tp_lpend: + pop si + inc si ; inc to ptr to next ComDEB + inc si + or ax, ax + loopnz tp_lp + pop si + +tp_nonactive: + pop ds + assumes ds,nothing + ret + +TimerProc endp +page + +ifdef DEBUG + public Control, DEF_Handler, COMHandler, APIHandler + public InterruptLoop, IntLoop10, IntLoop20 + public DataAvail25, DataAvail30, DataAvail50 + public DataAvail60, DataAvail70, DataAvail80, DataAvail90 + public DataAvail100, DataAvail110, DataAvail120 + public DataAvail130, DataAvail140, OutHandshakingChar + public XmitEmpty10, XmitEmpty20, XmitEmpty30, XmitEmpty40 + public XmitEmpty59, XmitEmpty60 + public XmitEmpty90, XmitEmpty100, XmitEmpty110 + public ModemStatus10, ModemStatus20, ModemStatus30 + public notify_owner, callback_event +endif + +DOSTI proc near + FSTI + ret +DOSTI endp + +DOCLI proc near + FCLI + ret +DOCLI endp + + + +sEnd IntCode +end diff --git a/private/mvdm/wow16/drivers/comm/ibmlpt.asm b/private/mvdm/wow16/drivers/comm/ibmlpt.asm new file mode 100644 index 000000000..c47e101cc --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/ibmlpt.asm @@ -0,0 +1,412 @@ +page,132 +;---------------------------Module-Header-------------------------------; +; Module Name: IBMLPT.ASM +; +; Copyright (c) Microsoft Corporation 1985-1990. All Rights Reserved. +; +; General Description: +; +; History: +; +;-----------------------------------------------------------------------; + +title IBMLpt - IBM PC, PC-XT, PC-AT, PS/2 Parallel Communications Interface + +.xlist +include cmacros.inc +include comdev.inc +include ins8250.inc +include ibmcom.inc +.list + +sBegin Code +assumes cs,Code +assumes ds,Data + +externFP GetSystemMsecCount + +externA __0040H + +;----------------------------Private-Routine----------------------------; +; +; DoLPT - Do Function To LPT port +; +; The given function (output or reset) is performed to the +; passed LPT port. +; +; Before a character is sent, a check is made to see if the device +; will be able to accept the character. If it can, then the character +; will be sent. If not, then an error will be returned. If the +; printer is selected and busy and no error, then the code returned +; will be CE_TXFULL and the handshake bits will be set in HSFlag +; to simulate that a handshake was received. +; +; If the BIOS ROM code is examined, you will note that they wait for +; the busy character from the last charcater to be cleared before +; they strobe in the current character. This can take a long time +; on the standard EPSON class printer (1 mSec to greater than +; 300 mSec if the last character actually caused printing). +; +; Because of this, several status read retrys will be made before +; declaring that the device is actually busy. If only one status +; read is performed, the spooler will yeild, take a while to get +; back here, and things will be really slow. What difference does +; it really make if we or the BIOS does the delay, at least we can +; break out of it at some point when it seems hopeless. +; +; The OKIHACK: Okidata reports a 50 ns. 2.2 volt pulse on the paper +; out signal on the trailing edge of the Busy signal. If we see this +; glitch then we report paper out. So we try to get the status twice... +; if it changes between the two tries we keep getting the status. +; Silly hardware people. +; +; Entry: +; AH = cid +; AL = character to output +; CH = Function request. 0 = Output, 1 = Initialize, 2 = Status +; DS:SI -> DEB for the port +; Returns: +; AX = 0 if no errors occured +; Error Returns: +; AX = error code +; Registers Preserved: +; SI,DI +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public DoLPT +DoLPT proc near + + mov dx,Port[si] ;Get port address + +; DX = port address +; CH = operation: 0 = write, 1 = init, 2 = status +; AL = character + + or ch, ch + jz LPT_OutChar + cmp ch, 1 + jz LPT_Reset + jmp LPT_GetStatus + ret + +LPT_Reset: + + inc dx + inc dx + mov al, L_RESET + iodelay + out dx, al + + push dx + + cCall GetSystemMsecCount + mov bx, ax + +LPT_ResetDelay: + push bx + cCall GetSystemMsecCount + pop bx + sub ax, bx + cmp ax, 300 ; 1/3 sec as good as any + jbe LPT_ResetDelay + + pop dx + + mov al, L_NORMAL + iodelay + iodelay + out dx, al + dec dx + dec dx + jmp LPT_GetStatus + +LPT_OutChar: + push ax ; save character to be written + + ; first check to see if printer is ready for us + push di + + push dx + call GetSystemMSecCount + mov di, ax + pop dx + +LPT_WaitReady: + + inc dx ; point to status port + iodelay + in al, dx ; get status bits + and al, L_BITS ; mask unused ones + xor al, L_BITS_INVERT ; flip a couple + xchg al, ah + +ifndef NOOKIHACK + iodelay + in al, dx + + dec dx + + and al, L_BITS + xor al, L_BITS_INVERT + cmp al, ah ; did any bits change? + jnz LPT_WaitReady +else + dec dx +endif + + + test ah, PS_PaperOut or PS_IOError + jnz LPT_PrinterNotReady + test ah, PS_Select + jz LPT_PrinterNotReady + test ah, PS_NotBusy + jnz LPT_PrinterReady + + push ax + push dx + call GetSystemMSecCount + pop dx + pop bx + sub ax, di + cmp ax, 300 ; 1/3 sec timeout + + jbe LPT_WaitReady + +; The device seems to be selected and powered up, but is just +; busy (some printers seem to show selected but busy when they +; are taken offline). Show that the transmit queue is full and +; that the hold handshakes are set. This is so the windows +; spooler will retry (and do yields so that other apps may run). + + + or ComErr[si],CE_TXFULL ;Show queue full + mov ah,bh + or ah, L_TIMEOUT + +LPT_PrinterNotReady: + + pop di + pop cx ; throw away character + jmp short LPT_ReturnStatus + +LPT_PrinterReady: + pop di ; get di back + pop ax ; get character back + + iodelay + out dx, al ; write character to port + + inc dx ; access status port + +LPT_Strobe: + inc dx ; control port + mov al, L_STROBE ; set strobe high + iodelay + iodelay + iodelay + iodelay + out dx, al ; ... + + mov al, L_NORMAL ; + iodelay + iodelay + iodelay + iodelay + out dx, al ; set strobe low + + sub dx, 2 ; point back to port base + + ; FALL THRU + +LPT_GetStatus: + inc dx ; point to status port +LPT_GS1: + iodelay + iodelay + in al, dx ; get status bits + and al, L_BITS ; mask unused ones + xor al, L_BITS_INVERT ; flip a couple + mov ah, al + +ifndef NOOKIHACK + in al, dx + and al, L_BITS + xor al, L_BITS_INVERT + cmp al, ah + jnz LPT_GS1 ; if they changed try again... +endif + +LPT_ReturnStatus: + + assumes ds,Data + and ax,(PS_PaperOut+PS_Select+PS_IOError+PS_Timeout)*256 + shr ah,1 + adc ah,al ;Get back Timeout bit + xor ah,HIGH CE_DNS ;Invert selected bit + .errnz LOW CE_DNS + or by ComErr+1[si],ah ;Save comm error + ret + + .errnz CE_PTO-0200h + .errnz CE_IOE-0400h + .errnz CE_DNS-0800h + .errnz CE_OOP-1000h + +DoLPT40: + assumes ds,Data + or ComErr[si],CE_TXFULL ;Show queue full + ret + +DoLPT endp +page + + +CheckStatus proc near + in al, dx ; get status bits + mov ah, al + and al, L_BITS ; mask unused ones + xor al, L_BITS_INVERT ; flip a couple + xchg al, ah + +ifndef NOOKIHACK + iodelay + in al, dx + + and al, L_BITS + xor al, L_BITS_INVERT + cmp al, ah ; did any bits change? + jnz CheckStatus +endif + test ah, PS_PaperOut or PS_IOError + jz @F + stc + ret +@@: + test ah, PS_Select + jnz @F + stc + ret +@@: + and ah, PS_NotBusy + clc + ret + +CheckStatus endp + + +;----------------------------Public Routine-----------------------------; +; +; StringToLPT - Send string To LPT Port +; +; Entry: +; DS:SI -> DEB +; ES:DI -> string to send +; CX = # of bytes to send +; Returns: +; AX = # of bytes actually sent +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +PUBLIC StringToLPT +StringToLPT proc near + + mov dx, Port[si] ; get port address + inc dx ; access status port + + push cx ; save count for later + push ds + mov bx, __0040H + mov ds, bx + + cld + + call CheckStatus ; quick status check before slowness + jc PrinterError + jz PrinterBusy ; if printer not ready for first char + ; then just return with CE_TXFULL + +CharacterToLPT: +;; mov bh, 10 ; will wait 10 clock tics (~ 1/2 sec) + mov bh, 3 ; will wait 3 clock tics (~ 1/6 sec) +l1: + mov bl, ds:[006Ch] ; low byte of tic counter +l2: + call CheckStatus ; quick status check before slowness + jc PrinterError + jnz LPT_PrinterRdy + + cmp bl, ds:[006Ch] + jz l2 ; tic count hasn't changed + + dec bh + jz PrinterBusy ; out of tics, timeout + jmp short l1 + +LPT_PrinterRdy: + mov al, es:[di] + inc di + + dec dx ; point to data port + + out dx, al ; write character to port + + add dx, 2 ; access control port + mov al, L_STROBE ; set strobe high + out dx, al ; ... + + mov al, L_NORMAL ; + iodelay + iodelay + out dx, al ; set strobe low + + dec dx ; point to status port for check + + loop CharacterToLPT + pop ds + jmp short LPT_Exit + +PrinterError: + pop ds + jmp short ReturnStatus + +PrinterBusy: + pop ds + or ComErr[si],CE_TXFULL ; set buffer full bit + or al, L_TIMEOUT ; show timeout bit + +ReturnStatus: + and ax,(PS_PaperOut+PS_Select+PS_IOError+PS_Timeout) + xchg al, ah + shr ah,1 + adc ah,al ;Get back Timeout bit + xor ah,HIGH CE_DNS ;Invert selected bit + .errnz LOW CE_DNS + or by ComErr+1[si],ah ;Save comm error + +LPT_Exit: + pop ax ; get total count + sub ax, cx ; subtract remaining unsent charts + + ret + +StringToLPT endp + + +IFDEF DEBUG ;Publics for debugging + public LPT_Reset + public LPT_Outchar + public LPT_Strobe + public LPT_GetStatus + public DoLPT40 +ENDIF + +sEnd code +End diff --git a/private/mvdm/wow16/drivers/comm/ibmsetup.asm b/private/mvdm/wow16/drivers/comm/ibmsetup.asm new file mode 100644 index 000000000..be430f747 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/ibmsetup.asm @@ -0,0 +1,2878 @@ +page,132 +;---------------------------Module-Header-------------------------------; +; Module Name: IBMSETUP.ASM +; +; Copyright (c) Microsoft Corporation 1985-1990. All Rights Reserved. +; +; General Description: +; +; History: +; sudeepb 10-Jan-1993 changed the costly cli/sti with non-trapping +; FCLI/FSTI macros +; +;-----------------------------------------------------------------------; + +title IBMSetup - IBM PC, PC-XT, PC-AT, PS/2 Communications Interface + +.xlist +include cmacros.inc +include comdev.inc +include ins8250.inc +include ibmcom.inc +include BIMODINT.INC +include vint.inc +.list + + +EBIS_Sel1 equ SIZE Bimodal_Int_Struc +EBIS_Sel2 equ EBIS_Sel1 + (SIZE EBIS_Sel_Struc) + +externA __WinFlags + +externFP GetSystemMsecCount +externFP CreateSystemTimer +externFP AllocCStoDSAlias +externFP LockSegment +externFP UnlockSegment +externFP FreeSelector +externFP GetSelectorBase +externFP GetModuleHandle +externFP GetProcAddress +externFP GetPrivateProfileInt +externFP GetPrivateProfileString +externFP GetAppCompatFlags +externFP WowCloseComPort + +externNP $RECCOM + +externA __0040H +externA __F000h + +externB IRQhooks + +IF 0 +externD OldIntVecIntB +externD OldIntVecIntC +externD OurIntVecIntB +externD OurIntVecIntC +ENDIF + +externB szMessage +externB pLPTByte +externB szCOMMessage +externB pCOMByte +externB _szTitle + + +MULTIPLEX equ 2Fh ; multiplex interrupt number +GET386API equ 1684h ; Get API entry point from VxD +VPD equ 000Fh ; device ID of VPD device +VPD_GETPORT equ 0004h ; function: assign port to current VM +VPD_RELPORT equ 0005h ; function: release port +VCD equ 000Eh ; device ID of VCD device +VCD_GETVER equ 0000h ; get version API +VCD_GETPORT equ 0004h ; function: assign port to current VM +VCD_RELPORT equ 0005h ; function: release port +VCD_STEALPORT equ 0006h +VPICD equ 0003h ; device ID of VPICD device + +POSTMESSAGE equ 110 ; export ordinal of PostMessage() +MESSAGEBOX equ 1 ; export ordinal of MessageBox() +MB_TASKMODAL equ 2000h +MB_YESNO equ 0004h ; messagebox flags +MB_ICONEXCLAMATION equ 0030h +IDYES equ 6 + + +createSeg _INTERRUPT,IntCode,word,public,CODE +sBegin IntCode +assumes cs,IntCode + + externFP FakeCOMIntFar + externFP TimerProc + externFP Control + externFP COMHandler + externFP APIHandler +IFDEF No_DOSX_Bimodal_Services + externW RM_IntDataSeg + externFP RM_APIHandler + externFP Entry_From_RM + externD RM_CallBack +ENDIF + +sEnd IntCode + +page +sBegin Data + +externB lpCommBase +externB CommBaseX +externB lpCommIrq +externB CommIrqX +externB lpCommFifo +externB CommFifoX +externB lpCommDSR +externB CommDSRx + +externB lpCommSection +externB lpSYSTEMINI + + +;------------------------------------------------------------------------------ +; +; Reserve data space for COM ports +; +DefineCommX MACRO num + public Comm&num +Comm&num label byte + db num-1 +.errnz DCB_Id + db ((DCBSize+1) AND 0FFFEh)-1 DUP (0) ; ComDCB + dw 0 ; ComErr + dw 0 ; Port + dw 0 ; NotifyHandle + dw 0 ; NotifyFlags + dw -1 ; RecvTrigger + dw 0 ; SendTrigger +.errnz IRQhook - SendTrigger - 2 + db (SIZE ComDEB) - IRQhook DUP(0) +.errnz $ - Comm&num - (SIZE ComDEB) + Declare_PM_BIS 0,Control,COMHandler,APIHandler,_INTERRUPT,_DATA + db (SIZE EBIS_Sel_Struc) * 2 DUP(0) ; res space for 2 selectors +ENDM +DW_OFFSET_CommX MACRO num + dw DataOFFSET Comm&num +ENDM + + +??portnum = 1 +REPT MAXCOM+1 + DefineCommX %??portnum +??portnum = ??portnum+1 +ENDM + +PUBLIC COMptrs ; table of offsets to CommX's declared above +COMptrs label word +??portnum = 1 +REPT MAXCOM+1 + DW_OFFSET_CommX %??portnum +??portnum = ??portnum+1 +ENDM + +PURGE DefineCommX +PURGE DW_OFFSET_CommX + +;------------------------------------------------------------------------------ +; +; Reserve data space for LPT ports +; +DefineLPTx MACRO num + public LPT&num +LPT&num label byte + db num-1+LPTx +.errnz DCB_Id + db ((DCBSize+1) AND 0FFFEh)-1 DUP (0) ; xComDCB + dw 0 ; xComErr + dw 0 ; xPort + dw 0 ; xNotifyHandle + dw 0 ; xNotifyFlags + dw -1 ; xRecvTrigger + dw 0 ; xSendTrigger +IF num LE 3 + dw LPTB + (num-1)*2 +ELSE + dw 0 ; BIOSPortLoc +ENDIF + .errnz $-LPT&num - SIZE LptDEB +ENDM + +??portnum = 1 +REPT MAXLPT+1 + DefineLPTx %??portnum +??portnum = ??portnum+1 +ENDM + +PURGE DefineLPTx + +page + +PUBLIC $MachineID, Using_DPMI +$MachineID db 0 ;IBM Machine ID +Using_DPMI db 0 ; 0FFh, if TRUE + + ALIGN 2 + +PUBLIC activeCOMs +activeCOMs dw 0 + +PUBLIC lpPostMessage, lpfnMessageBox, lpfnVPD, fVPD + +lpPostMessage dd 0 +lpfnMessageBox dd 0 + +lpfnVPD dd 0 ; far pointer to win 386 VPD entry point +lpfnVCD dd 0 ; far pointer to win 386 VCD entry point +lpfnVPICD dd 0 ; far pointer to win 386 VPICD entry point +PUBLIC VCD_int_callback +VCD_int_callback df 0 ; VCD returns the address for this callback + ; on every call to acquire a COM port, but + ; it is always the same address, so we will + ; just maintain it globally. +fVPD db 0 ; 0-not checked, 1 vpd present, -1 no vpd +fVCD db 0 ; 0-not checked, 1 vcd present, -1 no vcd +fVPICD db 0 ; 0-not checked, 1 vpicd present, -1 no vpicd + +szUser db 'USER',0 + + +default_table db 4, 3, 4, 3, 0 ; Default IRQ's (COM3 default is changed to + ; 3 for PS/2's during LoadLib) + + +IFDEF No_DOSX_Bimodal_Services +RM_Call_Struc Real_Mode_Call_Struc <> +ENDIF + +IFDEF DEBUG_TimeOut +%OUT including code to display MsgBox, if closing comm with data in buffer +szSendTO db 'TimedOut CloseComm with data in buffer. Retry?', 0 +ENDIF + + +sEnd Data + +ROMBios segment at 0F000h + org 0FFFEh + +MachineID label byte +RomBios Ends + + +sBegin Code +assumes cs,Code +assumes ds,Data + +page + +IFDEF No_DOSX_Bimodal_Services +;----------------------------Private-Routine----------------------------; +; SegmentFromSelector +; +; Converts a selector to a segment...note that this routine assumes +; the memory pointed to by the selector is below the 1Meg line! +; +; Params: +; AX = selector to convert to segment +; +; Returns: +; AX = segment of selector given +; +; Error Returns: +; None +; +; Registers Destroyed: +; CX +; +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public SegmentFromSelector +SegmentFromSelector proc far + +.286 + push dx + cCall GetSelectorBase,<ax> ;DX:AX = segment of selector + shr ax, 4 + shl dl, 4 + or ah, dl ;AX now points to interrupt *segment* + pop dx + ret +.8086 + +SegmentFromSelector endp +ENDIF +page + +;------------------------------------------------------------------------------ +; +; Get_API_Entry +; +; entry - BX = device id +; DS:DI -> DWORD for proc address +; exit - Z flag set, if failed +; +Get_API_Entry proc near + + push di + xor di, di + mov es, di + mov ax, GET386API + int MULTIPLEX + mov ax, di + pop di + mov [di], ax + mov [di+2], es + or ax, [di+2] + ret + +Get_API_Entry endp + +;----------------------------Private-Routine----------------------------; +; +; Contention_Dlg +; +; If running under Win386, this routine can be called to ask the user to +; resolve contention for a COM or LPT port. +; +; entry - CX is offset of message string for dialog box +; +; exit - Z flag set, if user specified that Windows should steal the port + +Contention_Dlg proc near +PUBLIC Contention_Dlg + + xor ax,ax + push ax ; hwndOwner + push ds + push cx ; message ptr + + cmp wo lpfnMessageBox[2], 0 ;Q: ptr to MessageBox proc valid? + jne short gmbp_done ; Y: we can call it + push ds ; N: get module handle of USER + lea ax, szUser + push ax + cCall GetModuleHandle + + push ax ; module handle + mov ax, MESSAGEBOX + cwd + push dx + push ax + cCall GetProcAddress + mov wo lpfnMessageBox[0], ax ; save received proc address + mov wo lpfnMessageBox[2], dx +gmbp_done: + + push ds + lea ax, _szTitle + push ax + mov ax, MB_ICONEXCLAMATION or MB_YESNO or MB_TASKMODAL + push ax + cCall lpfnMessageBox + cmp ax, IDYES ; user allows us to take the port? + ret +Contention_Dlg endp + + +;----------------------------Private-Routine----------------------------; +; +; GetPort386 +; +; If running under Win386, tell the VPD to assign an LPT port to us. +; The comm driver will handle contention. +; +; entry - DI contains offset in ROM area of port... +; 8 - LPT1, A - LPT2, etc +; +; exit - registers saved, carry = clear if OK to proceed, set if +; user won't allow assignment of port or Win386 error +; + +GetPort386 proc near +public GetPort386 + + cmp fVPD, 0 + jl getport_VPDNotInstalled + jnz short getport_CallVPD + + push di + mov bx, VPD + mov di, DataOFFSET lpfnVPD + call Get_API_Entry + pop di + jnz short getport_CallVPD + mov fVPD, -1 + +getport_VPDNotInstalled: + clc + jmp short getport_exit + +getport_CallVPD: + mov fVPD, 1 + push di + sub di, LPTB + shr di, 1 ; turn DI into port number + + xor ax, ax + mov dx, VPD_GETPORT + mov cx, di + call [lpfnVPD] + jnc getport_gotit + +; port owned by another VM... ask the user for it + + add cl, '1' ; fix up the port name... + mov pLPTByte, cl ; HACK HACK HACK + lea cx, szMessage + call Contention_Dlg + jnz getport_userwontallow + + mov ax, 1 ; tell win386 we really do want it + mov cx, di ; + mov dx, VPD_GETPORT ; + call [lpfnVPD] ; return with C set or clear... + jmp short getport_gotit + +getport_userwontallow: + stc + +getport_gotit: + pop di + +getport_exit: + ret + +GetPort386 endp + +;----------------------------Private-Routine----------------------------; +; +; ReleasePort386 +; +; If running under Win386, tell the VPD to deassign an LPT port. +; +; entry - DS:SI -> COMDEB +; + +ReleasePort386 proc near + + cmp fVPD, 1 + jne release_noVPD + + xor cx, cx + mov cl, [si.DCB_id] + and cl, NOT LPTx ; clear high bit + mov dx, VPD_RELPORT + call [lpfnVPD] + +release_noVPD: + ret + +ReleasePort386 endp + + +;----------------------------Private-Routine----------------------------; +; +; GetCOMport386 +; +; If running under Win386, tell the VCD to assign a COM port to us. +; The comm driver will handle contention. +; +; entry - DS:SI -> COMDEB +; +; exit - registers saved, carry = clear if OK to proceed, set if +; user won't allow assignment of port or Win386 error +; +.386 +GetCOMport386 proc near +public GetCOMport386 + + push es + pushad + cmp fVCD, 0 + jl short getcomport_VCDNotInstalled + jnz short getcomport_CallVCD + + mov bx, VCD + mov di, DataOFFSET lpfnVCD + call Get_API_Entry + jz short getcomport_checknoVCD + + mov dx, VCD_GETVER + call [lpfnVCD] + cmp ax, 30Ah ;Q: 3.1 or greater? + jae short getcomport_CallVCD ; Y: + +getcomport_checknoVCD: + mov fVCD, -1 + +getcomport_VCDNotInstalled: + clc + jmp short getcomport_exit + +getcomport_CallVCD: + mov fVCD, 1 + + mov ax, 10b ; flag ring0 int handler + call VCD_GetPort_API + jnc short getcomport_success ; jump if acquire worked + jnz short getcomport_noport ; jump if port doesn't exist + +; port owned by another VM... ask the user for it + + mov cl, [si.DCB_id] + add cl, '1' ; fix up the port name... + mov pCOMByte, cl + lea cx, szCOMMessage + call Contention_Dlg + stc + jnz short getcomport_exit + + mov ax, 11b ; tell win386 we really do want it + call VCD_GetPort_API + jc short getcomport_exit + +getcomport_success: + mov dword ptr [VCD_int_callback], edi + mov word ptr [VCD_int_callback+4], cx + mov [si.VCD_data], ebx + xchg ax, [si.Port] + or ax, ax ;Q: already had port base? + jnz short getcomport_exit ; Y: don't update vector #, or FIFO + mov [si.IntVecNum], dl + call GetPortFlags + clc + +getcomport_exit: + popad + pop es + ret + +getcomport_noport: + mov [si.Port], -1 + jmp getcomport_exit + +GetCOMport386 endp + +VCD_GetPort_API proc near + mov dx, VCD_GETPORT + xor cx, cx + mov cl, [si.DCB_Id] ; cx = port # + mov di, VCDflags ; offset from start of DEB + call [lpfnVCD] + ret +VCD_GetPort_API endp +.8086 + +;----------------------------Private-Routine----------------------------; +; +; ReleaseCOMport386 +; +; If running under Win386, tell the VCD to deassign a COM port. +; +; entry - DS:SI -> COMDEB +; + +ReleaseCOMport386 proc near + +ifndef WOW + cmp fVCD, 1 + jne release_noVCD + + xor cx, cx + mov cl, [si.DCB_id] + mov dx, VCD_RELPORT + call [lpfnVCD] +else + xor cx, cx + mov cl, [si.DCB_id] + push cx + call WowCloseComPort +endif + +release_noVCD: + ret + +ReleaseCOMport386 endp + +PUBLIC StealPort +StealPort proc near + + cmp fVCD, 1 + jne sp_yes + mov dx, VCD_STEALPORT + xor cx, cx + mov cl, [si.DCB_id] + call [lpfnVCD] + or al, al + jnz sp_yes + +sp_no: + stc + ret + +sp_yes: + clc + mov [si.VCDflags], 0 + ret + +StealPort endp + +page + +;------------------------------------------------------------------------------ +; +; ENTER: DS:SI -> ComDEB +; EXIT: AL = 0, if IRQ was unmasked, else -1, if IRQ was already masked +; +MaskIRQ proc near + push es + push di + mov di, ds + mov es, di + lea di, [si+SIZE ComDEB] + mov ax, BIH_API_Get_Mask + call APIHandler ; returns Carry Set, if masked + jc short already_masked + pushf + mov ax, BIH_API_Mask + call APIHandler ; mask IRQ + xor ax, ax + popf + jnc short mask_exit +already_masked: + or al, -1 +mask_exit: + pop di + pop es + ret +MaskIRQ endp + +;------------------------------------------------------------------------------ +; +; ENTER: DS:SI -> ComDEB +; +UnmaskIRQ proc near + push es + push di + mov di, ds + mov es, di + lea di, [si+SIZE ComDEB] + mov ax, BIH_API_Unmask + call APIHandler + pop di + pop es + ret +UnmaskIRQ endp +page + +;----------------------------Public Routine-----------------------------; +; +; $INICOM - Initialize A Port +; +; Initalizes the requested port if present, and sets +; up the port with the given attributes when they are valid. +; This routine also initializes communications buffer control +; variables. This routine is passed the address of a device +; control block. +; +; The RLSD, CTS, and DSR signals should be ignored by all COM +; routines if the corresponding timeout values are 0. +; +; For the LPT ports, a check is performed to see if the hardware +; is present (via the LPT port addresses based at 40:8h. If the +; port is unavailable, an error is returned. If the port is +; available, then the DEB is set up for the port. $SETCOM will +; be called to set up the DEB so that there will be something +; valid to pass back to the caller when he inquires the DEB. +; +; No hardware initialization will be performed to prevent the +; RESET line from being asserted and resetting the printer every +; time this routine is called. +; +; Entry: +; EX:BX --> Device Control Block with all fields set. +; Returns: +; AX = 0 if no errors occured +; Error Returns: +; AX = initialization error code otherwise +; Registers Preserved: +; None +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $INICOM +$INICOM proc near + push si ;As usual, save register variables + push di + mov ah,es:[bx.DCB_Id] ;Get device i.d. + call GetDEB ;--> DEB for this device + mov ax, IE_BADID ; call it a bad id (spooler uses DOS) + jc InitCom15 ;Invalid device + jns InitCom20 ; jmp if COM port + + push ds + + mov di, [si.BIOSPortLoc] + cmp di, LPTB + jb short InitLPT_Installed + + mov cx,__0040H ;[rkh] ... + mov ds,cx ;Point DS: at ROM Save Area. + assumes ds,nothing + + mov ax, IE_HARDWARE + mov cx, wo [di] + jcxz InitCom10 ; if zero, no hardware + + mov ax,IE_BadID ;Show bad device + cmp ch, 0 ; zero hibyte -> not valid (redir) + jz InitCom10 ; call it a bad id (spooler uses DOS) + + cmp di, LPTB ; LPT1? + jz InitLPT_Installed ; yes, must be installed + + cmp cx, wo [di-2] ;Q: duplicate of previous port + je InitCom10 ; Y: (redirected port) + +InitLPT_Installed: + pop ds + mov [si.Port], cx + call $SETCOM + call GetPort386 ; tell win386 we're using the port + mov ax, IE_OPEN ; port already open (by another VM) + jc InitCom15 ; error + jmp InitCom90 ;That's all + +InitCom10: + pop ds ; get DS back +InitCom15: + jmp InitCom100 + + + assumes ds,Data +InitCom17: + mov ax, IE_OPEN + cmp [si.Port], -1 ;Q: determined that port didn't exist? + jne InitCom15 ; N: return IE_OPEN + jmp short InitCom27 ; Y: return IE_HARDWARE + +; *** Set up serial port *** +; +InitCom20: + cmp [si.Port], -1 ;Q: port exists? + je InitCom27 ; N: report not found + + mov ax, __WinFlags + test ax, WF_ENHANCED + jz short @F + call GetCOMport386 + jc InitCom17 + +@@: + cmp [si.Port], 0 ;Q: already got info? + jnz @F + call FindCOMPort + jc InitCom27 ; report not found, if error + mov [si.Port], ax + mov [si.IntVecNum], dl +@@: + + push es ;Save these registers + push di + push cx ;needed later for $SETCOM etc + push bx + + mov al, [si.IntVecNum] + xor ah, ah + lea di, [si+SIZE ComDEB] + mov [di.BIS_IRQ_Number], ax + + mov di, DataOFFSET IRQhooks + mov cx, MAXCOM+1 +InitCom25: + cmp al, [di.IRQn] ;Q: hooked IRQ matches ours? + je short InitCom30 ; Y: + cmp [di.IRQn], 0 ;Q: end of hooked IRQ list? + je short InitCom35 ; Y: + add di, SIZE IRQ_Hook_Struc ; N: check next hook + loop InitCom25 + int 3 ; data structures corrupt if we + ; get here, because no hook table + ; entries exist and there is suppose + ; to be at least 1 for each DEB +InitCom26: + call ReleaseCOMport386 ; give port back to 386... + pop bx + pop cx + pop di + pop es + +InitCom27: + mov ax, IE_HARDWARE ; jump if port not available + jmp InitCom100 + +InitCom30: + cmp [di.HookCnt], 0 ;Q: IRQ still hooked? + je short InitCom35 ; N: rehook + inc [di.HookCnt] ; Y: inc hook count + mov [si.IRQhook], di ; & link DEB into list + mov ax, [di.First_DEB] + mov [si.NextDEB], ax + mov [di.First_DEB], si + jmp short InitCom40 + +InitCom35: + mov [di.IRQn], al ; hook IRQ for first time, or rehook + mov [si.IRQhook], di + mov [di.First_DEB], si + mov [di.HookCnt], 1 + call MaskIRQ + mov [di.OldMask], al + +InitCom40: ; di -> IRQ_Hook_Struc + + cmp [fVPICD], 0 ;Q: VPICD bimodel services available? + jl short InitCom415 ; N: + mov ax, ds ; Y: use them + mov es, ax + lea di, [si+SIZE ComDEB] + + mov [di.BIS_Descriptor_Count], 2 + mov ax, word ptr [si.QInAddr+2] ; get selector of in queue + mov [di.EBIS_Sel1.EBIS_User_Mode_Sel], ax + mov ax, word ptr [si.QOutAddr+2] ; get selector of out queue + mov [di.EBIS_Sel2.EBIS_User_Mode_Sel], ax + + mov ax, VPICD_Install_Handler + call [lpfnVPICD] + jnc InitCom42 + cmp [di.OldMask], 0 + jne InitCom26 + call UnmaskIRQ + jmp InitCom26 + +InitCom42: +; +; save newly allocated selectors/segments into "Alt" queue pointers +; + mov ax, [di.EBIS_Sel1.EBIS_Super_Mode_Sel] + mov word ptr [si.AltQInAddr+2], ax + mov ax, [di.EBIS_Sel2.EBIS_Super_Mode_Sel] + mov word ptr [si.AltQOutAddr+2], ax + +InitCom414: + jmp InitCom59 + +InitCom415: + cmp [di.VecN], 0FFh ;Q: int already hooked? +IFDEF No_DOSX_Bimodal_Services + jnz short InitCom52 ; Y: init RMode ptrs in BIS +ELSE + jnz InitCom414 ; Y: +ENDIF + mov al, [si.IntVecNum] + add al, 8 ; 1st PIC starts at vector 8h + cmp al, 16 ;Q: 2nd PIC? + jb short InitCom418 ; N: + add al, 70h-16 ; Y: 2nd PIC starts at vector 70h +InitCom418: + mov [di.VecN], al + +; *** Set interrupt vectors *** +; + mov ah,35h ;Get the DOS vector + int 21h ;DOS Get Vector Function + mov wo [di.OldIntVec][0], bx + mov wo [di.OldIntVec][2], es + +InitCom50: + push ds ;Save original DS + mov dx, [di.HandlerOff] + mov bx, _INTERRUPT + mov ds, bx ;Interrupt handler address in ds:dx + assumes ds,nothing + mov ah, 25h ;DOS Set Vector Function + int 21h ;Set the DOS vector + pop ds ;Original DS + assumes ds,Data + +IFDEF No_DOSX_Bimodal_Services +InitCom52: + cmp [Using_DPMI], 0 + jz short InitCom57 + + mov ax, Int31_Get_Version SHL 8 + int 31h + mov bl, [si.IntVecNum] + mov bh, bl + add bl, dh ; assume master PIC + sub bh, 8 ;Q: IRQ in master? + jb @f ; Y: add master's base vec + add bh, dl ; N: add slave's base vec + mov bl, bh +@@: + mov ax, Get_RM_IntVector + int 31h + mov wo [di.RM_OldIntVec][0], dx + mov wo [di.RM_OldIntVec][2], cx + + mov dx, [di.RM_HandlerOff] + mov ax, _INTERRUPT + call SegmentFromSelector + mov cx, ax + push cx + mov ax, Set_RM_IntVector + int 31h + + lea di, [si+SIZE ComDEB] + mov wo [di.BIS_Super_Mode_API], IntCodeOFFSET RM_APIHandler + pop cx + mov wo [di.BIS_Super_Mode_API+2], cx + +; +; Get segment addresses for the Q's and set AltQInAddr and AltQOutAddr +; + mov ax, wo [si.AltQInAddr+2] + call SegmentFromSelector + mov wo [si.AltQInAddr+2], ax + mov ax, wo [si.AltQOutAddr+2] + call SegmentFromSelector + mov wo [si.AltQOutAddr+2], ax +InitCom57: +ENDIF + mov ax, __WinFlags ;In Standard mode, the PIC IRQ + test al, WF_STANDARD ; priorities get rotated to favor + jz InitCom59 ; the comm ports. + + call Rotate_PIC + +; *** Interrupt handler set : jump here if handler is already installed *** +; +InitCom59: + pop bx + pop cx + pop di + pop es + +InitCom60: + mov dx,[si.Port] ;Set comm card address + xor ax,ax ;Need a zero + inc dx ;--> Interrupt Enable Register + .errnz ACE_IER-ACE_RBR-1 + out dx,al ;Turn off interrupts + call FlagNotActive + add dl,ACE_MCR-ACE_IER ;--> Modem Control Register + in al,dx + and al,ACE_DTR+ACE_RTS ;Leave DTR, RTS high if already so + iodelay ; but tri-state IRQ line + out dx,al + +InitCom70: + push es ;Zero queue counts and indexes + + push ds + pop es + assumes es,Data + + lea di,QInCount[si] + mov cx,(EFlags-QInCount)/2 + .errnz (EFlags-QInCount) AND 1 + xor ax,ax + cld + rep stosw + + .errnz QInGet-QInCount-2 + .errnz QInPut-QInGet-2 + .errnz QOutCount-QInPut-2 + .errnz QOutGet-QOutCount-2 + .errnz QOutPut-QOutGet-2 + .errnz EFlags-QOutPut-2 ;First non-queue item + + pop es + assumes es,nothing + + mov HSFlag[si],al ;Show no handshakes yet + mov MiscFlags[si],al ;Show not discarding + mov EvtWord[si],ax ;Show no events + mov [si.VCDflags], al + + mov [si.SendTrigger], ax + dec ax + mov [si.RecvTrigger], ax + +;Call $SETCOM to perform further hardware initialization. + +InitCom80: + sub dl,ACE_MCR-ACE_FCR ; dx -> FCR + in al, dx + iodelay + test al, ACE_FIFO_E2 ;Q: FIFO already on? + jz short @F ; N: + or EFlags[si], fFIFOpre ; Y: flag it +@@: + + ; needs si, di, and es to be saved from the beginning of inicom + call $SETCOM ;Set up Comm Device + jnz short InitCom110 ;jump if failed + + call UnmaskIRQ + and EFlags[si], fEFlagsMask ;Clear internal state + +InitCom90: + xor ax,ax ;Return AX = 0 to show success + mov ComErr[si],ax ;Get rid of any bogus init error + +InitCom100: + pop di + pop si + ret + +; +; jump to here, if call to $SETCOM failed +; +; DANGER! *** Call into middle of Terminate to clean things up *** DANGER! +; +InitCom110: + push ax ;Failure, save error code + call Terminate45 ;Restore port address, int vec + pop ax ;Restore error code and exit + jmp InitCom100 + +$INICOM endp +page + +;----------------------------Public Routine-----------------------------; +; +; $TRMCOM - Terminate Communications Channel +; +; Wait for any outbound data to be transmitted, drop the hardware +; handshaking lines, and disable interrupts. If the output queue +; contained data when it was closed, an error will be returned +; +; LPT devices have it easy. They just need to restore the I/O port +; address. +; +; Entry: +; AH = Device ID +; Returns: +; AX = 0 +; Error Returns: +; AX = 8000h if invalid device ID +; AX = -2 if output queue timeout occured +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $TRMCOM +$TRMCOM proc near + + push si + push di + xor cx,cx ;Show no error if LPT port + call GetDEB + jc TermCom60 ;ID is invalid, return error + js TermCom30 ;Port is a LPT port + + push ax ;Save port id + or MiscFlags[si],Discard ;Show discarding serial data + mov ComErr[si],cx ;Clear error flags + mov QInCount[si],cx ;Show no chars in input queue + call $RECCOM ;Send XON if needed + +;-----------------------------------------------------------------------; +; We have to wait for the output queue to empty. To do this, +; a timer will be created. If no character has been transmitted +; when the timeout occurs, then an error will be indicated and +; the port closed anyway. If the timer cannot be created, then +; just loop until the queue empties, which will be better than +; discarding charatcers if there are any +;-----------------------------------------------------------------------; + + test [si.HSFlag], HHSAlwaysDown ; Q: handshaking ever up? + jnz TermCom17 ; N: skip wait loop + +TermCom10: + mov cx,QOutCount[si] ;Get current queue count + jcxz TermCom20 ;No characters in queue + + cCall GetSystemMsecCount + mov di, ax + +TermCom15: + cmp QOutCount[si],cx ;Queue count change? + jne TermCom10 ; Yes, restart timeout + + cCall GetSystemMsecCount + sub ax, di + cmp ax, Timeout * 1000 ;Q: Timeout reached? + jb TermCom15 ; No, keep waiting + +IFDEF DEBUG_TimeOut +.286 + pusha + lea cx, szSendTO + call Contention_Dlg + popa + jz TermCom10 +.8086 +ENDIF + +TermCom17: + mov cx, TimeoutError ; Yes, show timeout error + +TermCom20: + pop ax ;Restore cid + +TermCom30: + mov dx,Port[si] ;Get port base address + call Terminate ;The real work is done here + mov ax,cx ;Set return code + +TermCom60: + pop di + pop si + ret + +$TRMCOM endp +page + +;----------------------------Private-Routine----------------------------; +; +; Terminate - Terminate Device +; +; Restore the port I/O address and make sure that interrupts are off +; +; Entry: +; AH = Device Id. +; DX = Device I/O port address. +; SI --> DEB +; Returns: +; AX = 0 +; Error Returns: +; AX = -1 +; Registers Destroyed: +; AX,BX,DX,FLAGS +; History: +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public Terminate ;Public for debugging +Terminate proc near + + or ah,ah ;LPT port? + jns Terminate10 ; No, process COM port + .errnz LPTx-10000000b + +Terminate5: + call ReleasePort386 ; give port back to 386... + jmp Terminate50 ;That's all + + +;-----------------------------------------------------------------------; +; It is a com port! +; +; We delay for a bit while the last character finishes transmitting +; Then we drop DTR and RTS, and disable the interrupt generation at +; the 8250. Even if fRTSDisable or fDTRDisable is set, those lines +; will be dropped when the port is closed. +;-----------------------------------------------------------------------; +; +; When the OUT2 bit is reset to 0 to disable interrupts, many ports +; generate an interrupt which can not be identified, because the the +; interrupt ID register will not be set. To work around this hardware +; problem we first mask the IRQ, then set the port into loopback mode +; and output a NULL to generate a receive interrupt request. Then we +; reset OUT2 and unmask the IRQ. This will cause the interrupt to occur +; and the interrupt handler will be able to correctly identify the +; interrupt as coming from the com port. + +Terminate10: + inc dx ;Disable chip interrupts + .errnz ACE_IER-ACE_RBR-1 + mov al, ACE_ERBFI ; except receive + out dx,al + call FlagNotActive ; don't need to check for postmessage + ; on timer ticks + add dl,ACE_LSR-ACE_IER ;--> line status register + iodelay + +Terminate20: + in al,dx ;Wait until xmit is empty + and al,ACE_THRE+ACE_TSRE + cmp al,ACE_THRE+ACE_TSRE + jne Terminate20 ;Not empty yet + +Terminate30: + xor al, al + test EFlags[si], fFIFOpre ;Q: leave FIFO enabled? + jz short @F ; N: + mov al, ACE_TRIG14 OR ACE_EFIFO OR ACE_CRFIFO OR ACE_CTFIFO +@@: + sub dl, ACE_LSR-ACE_FCR + out dx, al + iodelay + call MaskIRQ + add dl, ACE_MCR-ACE_FCR ;--> Modem Control Register + in al,dx + iodelay + mov ah, al + or al,ACE_LOOP ; turn on loopback + out dx, al + iodelay + sub dl, ACE_MCR-ACE_THR + xor al, al + out dx, al ; output a NULL to generate an int + iodelay + add dl, ACE_LSR-ACE_THR +Terminate35: + in al,dx ;Wait until xmit is empty + and al,ACE_THRE+ACE_TSRE + cmp al,ACE_THRE+ACE_TSRE + jne Terminate35 ;Not empty yet + mov al, ah + dec dl ; now clear OUT2 and loopback + .errnz ACE_LSR-ACE_MCR-1 + and al,ACE_DTR+ACE_RTS ;Leave DTR, RTS high if already so + out dx,al ; but tri-state IRQ line + + call UnmaskIRQ ; this will cause the receive int + ; to occur and be processed + sub dl, ACE_MCR-ACE_IER ; clear the receive int enable + xor al, al + out dx, al + dec dx + .errnz ACE_IER-ACE_RBR-1 + call MaskIRQ + +;******* DANGER! ***** NOTICE! ***** DANGER! ***** WARNING! ***** NOTICE! +; +; Terminate45 is a secondary entrypoint into this routine--it's called +; by the initialization code when that code is unable to properly init +; a com port and needs to clean-up the mess it's made. +; +;******* DANGER! ***** NOTICE! ***** DANGER! ***** WARNING! ***** NOTICE! + +Terminate45: + push cx ;Save original cx + push bx ;Save original bx + + cmp [fVPICD], 0 ;Q: VPICD bimodel services available? + jl short @F ; N: + mov ax, ds ; Y: use them + mov es, ax + lea di, [si+SIZE ComDEB] + mov ax, VPICD_Remove_Handler + call [lpfnVPICD] +@@: + + mov di, [si.IRQhook] + dec [di.HookCnt] ;Q: last port using IRQ? + jne short Terminate495 ; N: unmask IRQ again + mov al, 0FFh + xchg al, [di.VecN] ;Interrupt vector number + cmp al, 0FFh ;Q: IRQ vector hooked? + je short Terminate49 ; no... + +IFDEF No_DOSX_Bimodal_Services + cmp [Using_DPMI], 0 + jz short term_no_dpmi + +; +; unhook RM vector thru DPMI for standard mode +; + push ax + mov ax, Int31_Get_Version SHL 8 + int 31h + mov bl, [si.IntVecNum] + mov bh, bl + add bl, dh ; assume master PIC + sub bh, 8 ;Q: IRQ in master? + jb @f ; Y: add master's base vec + add bh, dl ; N: add slave's base vec + mov bl, bh +@@: + mov dx, wo [di.RM_OldIntVec][0] + mov cx, wo [di.RM_OldIntVec][2] + mov ax, Set_RM_IntVector + int 31h + pop ax +term_no_dpmi: +ENDIF + mov dx, __WinFlags ;In Standard mode the PIC interrupt + test dl, WF_STANDARD ; priorities are changed to favor + jz Terminate48 ; the comm ports. + + call Rotate_PIC ;This port no longer needs priority + +Terminate48: + ; *** reset int vector to it's previous state + assumes ds,nothing + push ds ;Save original DS [rkh] ... + lds dx, [di.OldIntVec] + mov ah, 25h ;DOS Set Vector Function + int 21h ;Set the DOS vector + pop ds ;Original DS + assumes ds,data + +; *** interrupt vectors have been reset if needed at this point *** +; +Terminate49: + mov cl, [di.OldMask] + +; Set the 8259 interrupt mask bit for this IRQ. Leave interrupts enabled +; if they were already enabled when the comm port was initialized by us. + + or cl, cl + jnz @f +Terminate495: + call UnmaskIRQ +@@: + + xor ax, ax + xchg ax, [si.NextDEB] + cmp [di.First_DEB], si ;Q: DEB first for IRQ hook? + je short Terminate46 ; Y: + mov bx, [di.First_DEB] ; N: get first +Terminate453: + cmp [bx.NextDEB], si ;Q: does this DEB point to one terminating? + je Terminate455 ; Y: + mov bx, [bx.NextDEB] ; N: get next DEB + jmp Terminate453 +Terminate455: + mov [bx.NextDEB], ax ; link previous DEB to NextDEB + jmp short Terminate47 +Terminate46: + mov [di.First_DEB], ax ; point IRQ hook at NextDEB +Terminate47: + pop bx ;Original BX + + call ReleaseCOMport386 ; give port back to 386... + + pop cx ;Original CX + +Terminate50: ;Also called from $INICOM ! + xor ax,ax ;Indicate no error + ret ;Port is closed and deallocated + +Terminate endp +page + +;----------------------------Public Routine-----------------------------; +; +; $ENANOTIFY - Enable Event Notification +; +; Entry: +; AH = Device ID +; BX = Window handle for PostMessage +; CX = Receive threshold +; DX = Transmit threshold +; Returns: +; AX = 1, if no errors occured +; Error Returns: +; AX = 0 +; Registers Preserved: +; BX,SI,DI,DS +; Registers Destroyed: +; AX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $ENANOTIFY +$ENANOTIFY proc near + push si + call GetDEB + mov ax, 0 + jc scb_exit + + mov ax, cx + inc ax + jz short scb_recv_ok + cmp cx, [si.QInSize] ;Q: receive threshold reasonable? + jb short scb_recv_ok ; Y: +%OUT should we return an error, if thresholds invalid? + mov cx, [si.QInSize] ; N: + sub cx, 10 +scb_recv_ok: + inc dx + jz short scb_send_ok + dec dx + cmp dx, [si.QOutSize] ;Q: receive threshold reasonable? + jb short scb_send_ok ; Y: + mov dx, [si.QOutSize] ; N: + sub dx, 10 +scb_send_ok: + mov [si.NotifyHandle], bx + mov [si.NotifyFlagsHI], CN_Notify + or bx, bx ;Q: null callback? + jnz scb_save_thresholds ; N: save thresholds + or cx, -1 ; Y: zero thresholds + xor dx, dx + mov [si.NotifyFlagsHI], 0 +scb_save_thresholds: + mov [si.RecvTrigger], cx + mov [si.SendTrigger], dx + or [si.NotifyFlagsHI], CN_TRANSMIT ; we don't want to send + ; a transmit trigger notification until + ; the transmit buffer has been filled + ; above the trigger level and then + ; emptied below it again! + + cmp wo lpPostMessage[2], 0 ;Q: gotten addr of PostMessage yet? + jne short scb_good ; Y: + push ds ; N: get module handle of USER + lea ax, szUser + push ax + cCall GetModuleHandle + + push ax ; module handle + mov ax, POSTMESSAGE + cwd + push dx + push ax + cCall GetProcAddress + mov wo lpPostMessage[0], ax ; save received proc address + mov wo lpPostMessage[2], dx + +scb_good: + mov ax, 1 + +scb_exit: + pop si + ret +$ENANOTIFY endp +page + +;----------------------------Public Routine-----------------------------; +; +; $SETQUE - Set up Queue Pointers +; +; Sets pointers to Receive and Transmit Queues, as provided by the +; caller, and initializes those queues to be empty. +; +; Queues must be set before $INICOM is called! +; +; Entry: +; AH = Device ID +; ES:BX --> Queue Definition Block +; Returns: +; AX = 0 if no errors occured +; Error Returns: +; AX = error code +; Registers Preserved: +; BX,DX,SI,DI,DS +; Registers Destroyed: +; AX,CX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $SETQUE +$SETQUE proc near + + push si ;These will be used + push di + call GetDEB ;Get DEB + jc SetQue10 ;Invalid, ignore the call + js SetQue10 ;Ignore call for LPT ports + push ds ;Set ds:si --> QDB + push es ;Set es:di --> to ComDCB.QInAddr + pop ds + assumes ds,nothing + pop es + assumes es,Data + lea di,QInAddr[si] + mov si,bx + cld + FCLI ;No one else can play with queues + movsw ; QInAddr = QueueRxAddr + movsw + .errnz QueueRxAddr + sub si, 4 ; AltQInAddr = QueueRxAddr + mov cx, 5 ; QInSize = QueueRxSize + rep movsw ; QOutAddr = QueueTxAddr + sub si, 4 + mov cx, 3 ; AltQOutAddr = QueueTxAddr + rep movsw ; QOutSize = QueueTxSize + + xor ax,ax ;Will do some zero filling + mov cl,(EFlags-QInCount)/2 + .errnz (EFlags-QInCount) AND 0FE01h + rep stosw + FSTI + push es ;Restore the data segment + pop ds + assumes ds,Data + assumes es,nothing + +SetQue10: + pop di ;Restore saved registers + pop si + ret + +; The above code made a few assumptions about how memory +; was allocated within the structures: + + .errnz AltQInAddr-QInAddr-4 + .errnz (QueueRxSize-QueueRxAddr)-(QInSize-AltQInAddr) + .errnz (QueueTxAddr-QueueRxSize)-(QOutAddr-QInSize) + .errnz AltQOutAddr-QOutAddr-4 + .errnz (QueueTxSize-QueueTxAddr)-(QOutSize-AltQOutAddr) + + .errnz QueueRxSize-QueueRxAddr-4 + .errnz QueueTxAddr-QueueRxSize-2 + .errnz QueueTxSize-QueueTxAddr-4 + + .errnz QInSize-AltQInAddr-4 + .errnz QOutAddr-QInSize-2 + .errnz QOutSize-AltQOutAddr-4 + + .errnz QInCount-QOutSize-2 + .errnz QInGet-QInCount-2 + .errnz QInPut-QInGet-2 + .errnz QOutCount-QInPut-2 + .errnz QOutGet-QOutCount-2 + .errnz QOutPut-QOutGet-2 + .errnz EFlags-QOutPut-2 ;First non-queue item + +$SETQUE endp +page + +;----------------------------Public Routine-----------------------------; +; +; $SETCOM - Set Communications parameters +; +; Re-initalizes the requested port if present, and sets up the +; port with the given attributes when they are valid. +; +; For LPT ports, just copies whatever is given since it's ignored +; anyway. +; +; Entry: +; ES:BX --> DCB with all fields set. +; Returns: +; 'Z' Set if no errors occured +; AX = 0 +; Error Returns: +; 'Z' clear if errors occured +; AX = initialization error code. +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public $SETCOM +$SETCOM proc near + + cld + push si + push di + mov ah,es:[bx.DCB_Id] ;Get device i.d. + call GetDEB ;Get DEB pointer in SI + mov ax,IE_BadID ;Assume unknown device + jc SetCom10 ;Invalid device, return error + jns SetCom20 ;COM port + call SetCom100 ;Copy the DCB + +SetCom5: + xor ax,ax ;Show no error + +SetCom10: + or ax,ax ;Set/clear 'Z' + pop di ; and exit + pop si + ret + +;-----------------------------------------------------------------------; +; Have a comm device, check all the serial parameters to make +; sure they are correct before moving the new DCB into our space +; and changing the ACE parameters. +;-----------------------------------------------------------------------; + +SetCom20: + call SetCom300 ;Baud rate valid? + jcxz SetCom10 ; No, return error + call SetCom400 ;Byte size/parity/stop bits correct? + jc SetCom10 ; No, return error + +; The parameters seem correct. Copy the DCB into our space and +; initialize the ACE with the new parameters + + mov dx,Port[si] ;Disable interrupts from the 8250 + inc dx + .errnz ACE_IER-1 + xor ax,ax + out dx,al + call FlagNotActive + + call SetCom100 ;Copy the DCB + mov bx,si ;Set ES:BX --> DCB + call SetCom200 ;Get timeout masks + xchg al,ah ;Want them in the correct registers + mov wo MSRMask[si],ax + .errnz MSRInfinite-MSRMask-1 + + call SetCom400 ;Get line control byte + push ax ; and save LCR value + inc dx ;--> LCR + inc dx + .errnz ACE_LCR-ACE_IER-2 + or al,ACE_DLAB ;Want access to divisor latch + out dx,al + mov RxMask[si],ah ;Save Receive character mask + mov ax,di ;Get flags mask, error mask + and [si.DCB_Flags],ah ;Disable parity checking if no parity + mov ErrorMask[si],al ;Save line status error mask + + call SetCom300 ;Get baud rate + sub dl,ACE_LCR-ACE_DLL ;--> LSB of divisor latch + mov al,cl + out dx,al + mov al,ch + inc dx ;--> MSB of divisor latch + .errnz ACE_DLM-ACE_DLL-1 + iodelay + out dx,al + inc dx ;--> LCR and clear divisor access bit + inc dx + .errnz ACE_LCR-ACE_DLM-2 + pop ax + out dx,al + + inc dx ;--> Modem Control Register + .errnz ACE_MCR-ACE_LCR-1 + +;-----------------------------------------------------------------------; +; Compute initial state of DTR and RTS. If they have been disabled, +; then do not raise them, and disallow being used as a handshaking +; line. Also compute the bits to use as hardware handshake bits +; (DTR and/or RTS as indicated, qualified with the disabled flags). +;-----------------------------------------------------------------------; + + mov al,[si.DCB_Flags] ;Align DTR/RTS disable flags for 8250 + and al,fRTSDisable+fDTRDisable + rol al,1 ;d0 = DTR, d2 = RTS (1 = disabled) + shr al,1 ;'C'= DTR, d1 = RTS + adc al,0 ;d0 = DTR, d1 = RTS + .errnz fRTSDisable-00000010b + .errnz fDTRDisable-10000000b + .errnz ACE_DTR-00000001b + .errnz ACE_RTS-00000010b + + mov ah,al ;Save disable mask + xor al,ACE_DTR+ACE_RTS+ACE_OUT2 + out dx,al ;Set Modem Control Register + + mov al,[si.DCB_Flags2] ;Get hardware handshake flags + rol al,1 ;Align flags as needed + rol al,1 + rol al,1 + and al,ACE_DTR+ACE_RTS ;Mask bits of interest + not ah ;Want inverse of disable mask + and al,ah ;al = bits to handshake with + mov HHSLines[si],al ;Save for interrupt code + + .errnz fDTRFlow-00100000b + .errnz fRTSFlow-01000000b + .errnz ACE_DTR-00000001b + .errnz ACE_RTS-00000010b + + mov al,[si.DCB_Flags] ;Compute the mask for the output + shl al,1 ; hardware handshake lines + and al,ACE_DSR+ACE_CTS + mov OutHHSLines[si],al + + .errnz fOutXCTSFlow-00001000b + .errnz fOutXDSRFlow-00010000b + .errnz ACE_CTS-00010000b + .errnz ACE_DSR-00100000b + +; Compute the queue count where XOff should be issued (or hardware +; lines dropped). This will prevent having to do it at interrupt +; time. + + mov ax,QInSize[si] ;Get where they want it + sub ax,[si.DCB_XoffLim] ; and compute queue count + mov XOffPoint[si],ax + +; Enable FIFO if possible when baudrate >= 4800 +; + sub dl,ACE_MCR - ACE_FCR ; dx = FCR + test EFlags[si], fNoFIFO ;Q: FIFO can be enabled? + jnz sc_nofifo ; N: + mov ax, [si.DCB_BaudRate] + cmp ax, 4800 + jb sc_nofifo + cmp ah, -1 ;Q: baudrate index? + jne sc_fifo ; N: baudrate >= 4800, enable FIFO + cmp ax, CBR_4800 + jb sc_nofifo +%OUT this isn't correct, if lower baudrates are assigned indices above CBR_4800 + +sc_fifo: + mov al, ACE_TRIG14 OR ACE_EFIFO OR ACE_CRFIFO OR ACE_CTFIFO + out dx, al ; attempt to enable FIFO + test EFlags[si], fFIFOchkd ;Q: FIFO detect been done? + jnz sc_fifodone ; Y: enabled FIFO + iodelay + .errnz ACE_IIDR-ACE_FCR + in al, dx + or EFlags[si], fFIFOchkd + test al, ACE_FIFO_E2 ;Q: FIFO enabled? + jz short @F + test al, ACE_FIFO_E1 ;Q: 16550A detected? + jnz sc_fifodone ; Y: enabled FIFO +@@: + iodelay + or EFlags[si], fNoFIFO + +sc_nofifo: + xor al, al + out dx, al +sc_fifodone: + + sub dl,ACE_FCR-ACE_RBR ; dx -> RBR +; +; Delay for things to settle +; + push dx + cCall GetSystemMsecCount + pop dx + mov cx, ax +delay_loop: + in al, dx ;Read it once + push dx + cCall GetSystemMsecCount + pop dx + sub ax, cx + cmp ax, DELAY_TIME ;Q: Timeout reached? +ifndef WOW + jb delay_loop ; N: +endif + + add dl,ACE_MSR ;--> Modem Status reg + in al,dx ;Throw away 1st status read + iodelay + in al,dx ;Save 2nd for MSRWait (Clear MSR int) + mov MSRShadow[si],al + +; Win 3.0 didn't check hardware handshaking until the line status changed. +; Allow some apps to keep that behavior. + + push dx + xor ax, ax + cCall GetAppCompatFlags,<ax> + pop dx + test ax, GACF_DELAYHWHNDSHAKECHK + jnz short sc_HHSup + +; +; HACK FOR SOME MODEMS: apparently some modems set CTS, but don't set DSR +; which means that COMM.DRV won't send if the app specifies that hardware +; handshaking is based on CTS & DSR being set. +; + mov ah,OutHHSLines[si] + mov al, MSRShadow[si] + and al,ah ;Only leave bits of interest + cmp al, ah ;Q: handshaking lines ok? + je short sc_HHSup ; Y: + cmp ah, ACE_CTS OR ACE_DSR ;Q: app looking for both high? + jne short sc_HHSdown ; N: skip hack + test [si.EFlags], fUseDSR ;Q: DSR is always significant? + jnz short sc_HHSdown ; Y: skip hack + cmp al, ACE_CTS ;Q: DSR low & CTS high + jne short sc_HHSdown ; N: skip hack + and ah, NOT ACE_DSR ; Y: ignore DSR line + mov OutHHSLines[si], ah + jmp short sc_HHSup + +sc_HHSdown: + or [si.HSFlag], HHSDown OR HHSAlwaysDown ; flag handshaking down +sc_HHSup: + +;-----------------------------------------------------------------------; +; Now, at last, interrupts can be enabled. Don't enable the +; transmitter empty interrupt. It will be enabled by the first +; call to KickTx. +;-----------------------------------------------------------------------; + + sub dl,ACE_MSR-ACE_IER ;--> Interrupt Enable Register + +; flag port as being active + push cx + mov cl, [si.DCB_Id] + mov ax, 1 + shl ax, cl + or [activeCOMs], ax + pop cx + + mov al,ACE_ERBFI+ACE_ELSI+ACE_EDSSI + FCLI + out dx,al ;Enable interrupts. + add dl,ACE_LSR-ACE_IER ;--> Line Status Register + iodelay + in al,dx ;Clear any Line Status interrupt + sub dl,ACE_LSR ;--> Receiver Buffer Register + iodelay + in al,dx ;Clear any Received Data interrupt + FSTI + jmp SetCom5 ;All done + +$SETCOM endp +page + +FlagNotActive proc near + push cx + mov cl, [si.DCB_Id] + mov ax, NOT 1 + rol ax, cl + and [activeCOMs], ax + pop cx + ret +FlagNotActive endp + +;----------------------------Private-Routine----------------------------; +; +; SetCom100 +; +; Copy the given DCB into the appropriate DEB. The check has +; already been made to determine that the ID was valid, so +; that check can be skipped. +; +; Entry: +; ES:BX --> DCB +; DS:SI --> DEB +; Returns: +; DS:SI --> DEB +; ES = Data +; Error Returns: +; None +; Registers Destroyed: +; AX,CX,ES,DI,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +SetCom100 proc near + push si ;Save DEB pointer + mov di,si + mov si,bx + push es + mov ax,ds + pop ds + assumes ds,nothing + + mov es,ax + assumes es,Data + + mov cx,DCBSize + cld + rep movsb + mov ds,ax + assumes ds,Data + + pop si ;Restore DEB pointer + ret + +SetCom100 endp +page + +;----------------------------Private-Routine----------------------------; +; +; SetCom200 +; +; Based on whether or not a timeout has been specified for each +; signal, set up a mask byte which is used to mask off lines for +; which we wish to detect timeouts. 0 indicates that the line is +; to be ignored. +; +; Also set up a mask to indicate those lines which are set for +; infinite timeout. 1 indicates that the line has infinite +; timeout. +; +; Entry: +; ES:BX --> DCB +; Returns: +; ES:BX --> DCB +; AH = lines to check +; AL = lines with infinite timeout +; Error Returns: +; None +; Registers Destroyed: +; AX,CX,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +SetCom200 proc near + + xor ax,ax + xor cx,cx ;Get mask of lines with timeout = 0 + call SetCom210 + not al ;Invert result to get lines to check + and al,ACE_CTS+ACE_DSR+ACE_RLSD + xchg ah,al + dec cx ;Get mask of infinite timeouts + +SetCom210: + cmp es:[bx.DCB_RlsTimeout],cx ;Timeout set to passed value? + jne SetCom220 ; No + or al,ACE_RLSD ; Yes, show checking line + +SetCom220: + cmp es:[bx.DCB_CtsTimeout],cx ;Timeout set to passed value? + jne SetCom230 ; No + or al,ACE_CTS ; Yes, show checking line + +SetCom230: + cmp es:[bx.DCB_DsrTimeout],cx ;Timeout set to passed value? + jne SetCom240 ; No + or al,ACE_DSR ; Yes, show checking line + +SetCom240: + ret + +SetCom200 endp +page + +;----------------------------Private-Routine----------------------------; +; +; SetCom300 +; +; Calculate the correct baudrate divisor for the comm chip. +; +; Note that the baudrate is allowed to be any integer in the +; range 2-19200. The divisor is computed as 115,200/baudrate. +; +; Entry: +; ES:BX --> DCB +; Returns: +; ES:BX --> DCB +; CX = baudrate +; Error Returns: +; CX = 0 if error +; AX = error code if invalid baud rate +; Registers Destroyed: +; AX,CX,FLAGS +; History: +;-----------------------------------------------------------------------; + +BaudRateByIndexTable label word + dw 1047 ; CBR_110 + dw 384 ; CBR_300 + dw 192 ; CBR_600 + dw 96 ; CBR_1200 + dw 48 ; CBR_2400 + dw 24 ; CBR_4800 + dw 12 ; CBR_9600 + dw 9 ; CBR_14400 + dw 6 ; CBR_19200 + dw 0 ; 0FF19h (reserved) + dw 0 ; 0FF1Ah (reserved) + dw 3 ; CBR_38400 + dw 0 ; 0FF1Ch (reserved) + dw 0 ; 0FF1Dh (reserved) + dw 0 ; 0FF1Eh (reserved) + dw 2 ; CBR_56000 + +assumes ds,Data +assumes es,nothing + +SetCom300 proc near + + push dx + mov cx,es:[bx.DCB_BaudRate] ;Get requested baud rate + xor ax,ax ;Assume error + cmp cx, CBR_110 ;Q: baudrate specified as an index? + jae by_index + cmp cx,2 ;Within valid range? + jnae SetCom310 ; No, return error + + mov dx,1 ;(dx:ax) = 115,200 + mov ax,0C200h + div cx ;(ax) = 115,200/baud + +SetCom310: + mov cx,ax ;(cx) = baud rate, or error code (0) + mov ax,IE_Baudrate ;Set error code incase bad baud + pop dx + ret + +by_index: + cmp cx, CBR_56000 ;Q: above supported? + ja SetCom310 ; Y: return error + push bx + mov bx, cx + sub bx, CBR_110 + shl bx, 1 + mov ax, cs:[bx+BaudRateByIndexTable] ; get divisor + pop bx + jmp SetCom310 ; Y: return error + + +SetCom300 endp +page + +;----------------------------Private-Routine----------------------------; +; +; SetCom400 +; +; Check the line configuration (Parity, Stop bits, Byte size) +; +; Entry: +; ES:BX --> DCB +; Returns: +; ES:BX --> DCB +; 'C' clear if OK +; AL = Line Control Register +; AH = RxMask +; DI[15:8] = Flags mask (to remove parity checking) +; DI[7:0] = Error mask (to remove parity error) +; Error Returns: +; 'C' set if error +; AX = error code +; Registers Destroyed: +; AX,CX,DI,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +SetCom400 proc near + + mov ax,wo es:[bx.DCB_ByteSize] ;al = byte size, ah = parity + cmp ah,SpaceParity ;Parity out of range? + ja SetCom470 ; Yes, return error + mov di,0FF00h+ACE_OR+ACE_PE+ACE_FE+ACE_BI + or ah,ah ;Is parity "NONE"? + jnz SetCom410 ; No, something is there for parity + xor di,(fParity*256)+ACE_PE ;Disable parity checking + +SetCom410: + cmp al,8 ;Byte size out of range? + ja SetCom460 ; Yes, error + +SetCom420: + sub al,5 ;Shift byte size to bits 0&1 + .errnz ACE_WLS-00000011b ;Word length must be these bits + jc SetCom460 ;Byte size is illegal, return error + add ah,ah ;Map parity to ACE bits + jz SetCom430 ;0=>0, 1=>1, 2=>3, 3=>5, 4=>7 + dec ah + +SetCom430: + shl ah,1 ;Align with 8250 parity bits + shl ah,1 + shl ah,1 + or al,ah ;Add to byte size + + .errnz NoParity-0 + .errnz OddParity-1 + .errnz EvenParity-2 + .errnz MarkParity-3 + .errnz SpaceParity-4 + .errnz ACE_PEN-00001000b + .errnz ACE_PSB-00110000b + .errnz ACE_EPS-00010000b + .errnz ACE_SP-00100000b + + or al,ACE_2SB ;Assume 2 stop bits + mov ah,es:[bx.DCB_StopBits] ;Get # of stop bits 0=1,1/2= .GT. 1 + or ah,ah ;Out of range? + js SetCom470 ; Yes, return error + jz SetCom440 ;One stop bit + sub ah,2 + jz SetCom450 ;Two stop bits + jns SetCom470 ;Not 1.5, return error + test al,ACE_WLS ;1.5 stop bits, 5 bit words? + jnz SetCom470 ; No, illegal + .errnz OneStopBit-0 + .errnz One5StopBits-1 + .errnz TwoStopBits-2 + .errnz ACE_5BW + +SetCom440: + and al,NOT ACE_2SB ;Show 1 (or 1.5) stop bit(s) + + +; From the byte size, get a mask to be used for stripping +; off unused bits as the characters are received. + +SetCom450: + push dx + mov cl,es:[bx.DCB_ByteSize] ;Get data byte size + mov dx,00FFh ;Turn into mask by shifting bits + shl dx,cl + mov ah,dh ;Return mask in ah + pop dx + clc ;Show all is fine + ret + +SetCom460: + mov ax,IE_ByteSize ;Show byte size is wrong + stc ;Show error + ret + +SetCom470: + mov ax,IE_Default ;Show something is wrong + stc ;Show error + ret + +SetCom400 endp +page + +;---------------------------------------------------------------------------- +; SuspendOpenCommPorts: +; +; This routine is called from 286 Winoldaps to simply deinstall the comm port +; hooks. +;---------------------------------------------------------------------------- + +cProc SuspendOpenCommPorts,<FAR,PUBLIC,PASCAL> + +cBegin nogen + + assumes cs,Code + assumes ds,Data + +%OUT not masking IRQ's + + ; Nothing to do under 3.1! + + ret + +cEnd nogen + +;----------------------------------------------------------------------------; +; ReactivateOpenCommPorts: ; +; ; +; This routine reinstalls the comm hooks in real mode and reads the 8250 ; +; data and status registers to clear pending interrupts. ; +;----------------------------------------------------------------------------; + +cProc ReactivateOpenCommPorts,<FAR,PASCAL,PUBLIC>,<si,di> + +cBegin + call Rotate_PIC ;make comm ports highest priority + + mov cx, MAXCOM+1 + mov di,dataOffset COMptrs +rcp_loop: + mov si, [di] + mov dx, Port[si] + or dx, dx + jz @f + call InitAPort ;read comm port regs to clr pending ints +@@: + add di, 2 + loop rcp_loop + +cEnd + +;----------------------------------------------------------------------------; +; InitAPort: ; +; ; +; reads the data,status & IIR registers of a port (has to be 8250!) ; +; ; +; If the port has an out queue pending, then this woutine will also start ; +; the transmit process by faking a comm interrupt. ; +;----------------------------------------------------------------------------; + +public InitAPort +InitAPort proc near + + add dl,ACE_RBR ;dx=receive buffer register + in al,dx ;read the data port + jmp short $+2 ;i/o delay + add dl,ACE_LSR - ACE_RBR ;get to the status port + in al,dx ;read it too. + jmp short $+2 ;i/o delay + add dl,ACE_IIDR - ACE_LSR ;get to the line status register + in al,dx ;read it once more + jmp short $+2 ;i/o delay + add dl,ACE_MSR - ACE_IIDR ;get to the modem status register + in al,dx ;read it once more + jmp short $+2 ;i/o delay + add dl,ACE_RBR - ACE_MSR ;get to the receive buffer register + in al,dx ;read it once more + jmp short $+2 ;i/o delay + call UnmaskIRQ + +; now if the port has characters pending to be sent out then we must fake a +; comm interrupt. + + cmp [si].QOutCount,0 ;characters pending to be sent ? + jz @f ;no. + FCLI ;disable interrupts + call FakeCOMIntFar ;fake an interrupt + FSTI ;renable interrupts +@@: + ret + +InitAPort endp + +page + +;----------------------------Public Routine-----------------------------; +; +; $DCBPtr - Return Pointer To DCB +; +; Returns a long pointer to the DCB for the requested device. +; +; Entry: +; AH = Device ID +; Returns: +; DX:AX = pointer to DCB. +; Error Returns: +; DX:AX = 0 +; Registers Preserved: +; SI,DI,DS +; Registers Destroyed: +; BX,CX,ES,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public $DCBPTR +$DCBPTR proc near + + push si + xor dx,dx + call GetDEB ;Get pointer to DEB + mov ax,dx + jc DCBPtr10 ;Jump if invalid device + mov ax,si ;else return value here + mov dx,ds + +DCBPtr10: + pop si + ret + +$DCBPTR endp +page + +;----------------------------Private-Routine----------------------------; +; +; GetDEB - Get Pointer To Device's DEB +; +; Returns a pointer to appropriate DEB, based on device number. +; +; Entry: +; AH = cid +; Returns: +; 'C' clear +; 'S' set if LPT device +; DS:SI --> DEB is valid cid +; AH = cid +; Error Returns: +; 'C' set if error (cid is invalid) +; AX = 8000h +; Registers Preserved: +; BX,CX,DX,DI,DS,ES +; Registers Destroyed: +; AX,SI,FLAGS +; History: +;-----------------------------------------------------------------------; + +;------------------------------Pseudo-Code------------------------------; +; { +; } +;-----------------------------------------------------------------------; + +assumes ds,Data +assumes es,nothing + +public GetDEB ;Public for debugging +GetDEB proc near + + push cx + mov cl, ah + and cx, (NOT LPTx AND 0FFh) + test ah, ah ;Q: LPT id? + js short GetDEB10 ; Y: +.errnz LPTx - 80h + cmp ah, MAXCOM ;Q: Within range? + ja GetDEB30 ; N: return invalid ID + shl cx, 1 + mov si, cx + mov si, [si+COMptrs] + jmp short GetDEB20 + +GetDEB10: + cmp ah, LPTx+MAXLPT ;Q: Within range? + ja GetDEB30 ; N: return invalid ID + mov si, DataOFFSET LPT1 + jcxz GetDEB20 +GetDEB15: + add si, SIZE LptDEB + loop GetDEB15 +GetDEB20: + pop cx + or ah, ah ; clear Carry & set S, if LPT port + ret + +GetDEB30: + pop cx + mov ax,8000h ;Set error code + stc ;Set 'C' to show error + ret + +GetDEB endp +page + + +CvtHex proc near +; assume DS=SS + push si + mov cl, 4 + mov si, di + xor dx, dx + cld +ch_lp: + lodsb + sub al, '0' ;Q: char < '0' + jb ch_exit ; Y: return + cmp al, 9 ;Q: char <= '9' + jbe ch_got_digit ; Y: move digit into result + sub al, 'A' - '0' ;Q: char < 'A' + jb ch_exit ; Y: return + add al, 10 + cmp al, 15 ;Q: char <= 'F' + jbe ch_got_digit ; Y: move hex char into result + sub al, 10 + 'a' - 'A' ;Q: char < 'a' + jb ch_exit ; Y: return + add al, 10 + cmp al, 15 ;Q: char > 'f' + ja ch_exit ; Y: return +ch_got_digit: + shl dx, cl + or dl, al + jmp ch_lp +ch_exit: + mov ax, dx + pop si + ret +CvtHex endp + +.286 +; attempt to read base from SYSTEM.INI +GetComBase proc near + push ds ; save our DS + sub sp, 6 + mov di, sp + mov byte ptr ss:[di], 0 + push ds + push DataOFFSET lpCommSection + push ds + push DataOFFSET lpCommBase + push ss ; temp buffer + push di + push ss ; default = temp buffer + push di + push 5 + push ds + push DataOFFSET lpSYSTEMINI + mov cx, ss ; temporarily assign DS=SS + mov ds, cx ; to allow KERNEL to thunk + assumes ds,nothing + call GetPrivateProfileString ; our segment in real mode + or ax, ax + jz short gcb_exit + call CvtHex ; DS still equal to SS +gcb_exit: + add sp, 6 + pop ds ; restore our DS + assumes ds,Data + ret +GetComBase endp + +GetPortIRQ proc near + push ds ; save our DS + push ds + push DataOFFSET lpCommSection + push ds + push DataOFFSET lpCommIrq + push bx + mov bl, [si.DCB_Id] + cmp bl, 4 + jb @f + mov bl, 4 +@@: + xor bh, bh + mov bl, [bx+default_table] + mov cx, bx + pop bx + push cx ; default + push ds + push DataOFFSET lpSYSTEMINI + mov cx, ss ; temporarily assign DS=SS + mov ds, cx ; to allow KERNEL to thunk + assumes ds,nothing + call GetPrivateProfileInt ; our segment in real mode + pop ds ; restore our DS + assumes ds,Data + ret +GetPortIRQ endp + + +GetPortFlags proc near + mov al, [si.DCB_Id] +.erre MAXCOM LT 9 ;only single digit port numbers supported + add al, '1' + mov [CommFIFOX], al + mov [CommDSRx], al + call GetPortFIFO + call GetPortDSR + ret +GetPortFlags endp + +GetPortFIFO proc near + push ds ; save our DS + push ds + push DataOFFSET lpCommSection + push ds + push DataOFFSET lpCommFifo + push 2 + push ds + push DataOFFSET lpSYSTEMINI + mov cx, ss ; temporarily assign DS=SS + mov ds, cx ; to allow KERNEL to thunk + assumes ds,nothing + call GetPrivateProfileInt ; our segment in real mode + pop ds ; restore our DS + assumes ds,Data + cmp ax, 1 + ja short gpf_exit ; just check at open + jb short gpf_no_fifo ; force OFF, if = 0 + or EFlags[si], fFIFOchkd ; flag as checked, to force ON + jmp short gpf_exit + +gpf_no_fifo: + or EFlags[si], fNoFIFO OR fFIFOchkd ; force OFF + +gpf_exit: + ret +GetPortFIFO endp + +GetPortDSR proc near + push ds ; save our DS + push ds + push DataOFFSET lpCommSection + push ds + push DataOFFSET lpCommDSR + push 0 + push ds + push DataOFFSET lpSYSTEMINI + mov cx, ss ; temporarily assign DS=SS + mov ds, cx ; to allow KERNEL to thunk + assumes ds,nothing + call GetPrivateProfileInt ; our segment in real mode + pop ds ; restore our DS + assumes ds,Data + or ax, ax + jz short gpd_exit + or EFlags[si], fUseDSR + +gpd_exit: + ret +GetPortDSR endp + + +; FindCOMPort +; +; DS:SI -> DEB +; + PUBLIC FindCOMPort +FindCOMPort proc near +; +; Examine BIOS data area to get base I/O addresses for COM and LPT ports +; + push bx + push cx + push es + mov ax, __0040H + mov es, ax + assumes es,nothing + + mov al, [si.DCB_Id] + mov ah, al +.erre MAXCOM LT 9 ;only single digit port numbers supported + add ah, '1' + mov [CommBaseX], ah + mov [CommIRQX], ah + mov [CommFIFOX], ah + mov [CommDSRx], ah + + cmp al, 4 + jae fcp_not_phys_com + xor ah, ah + shl ax, 1 + mov bx, ax + mov ax, es:[bx+RS232B] + or ax, ax + jnz fcp_got_com_base +fcp_not_phys_com: + call GetComBase + or ax, ax + jnz fcp_got_com_base + mov bl, [si.DCB_Id] + cmp bl, 2 + jne fcp_invalid ; jump, if base = 0 & com port <> com3 + mov ax, 3E8h ; default COM3 to 3E8h +fcp_got_com_base: + push ax + call GetPortIRQ + mov dx, ax + pop ax + or dl, dl ;Q: non-zero IRQ? + jz fcp_invalid ; N: + cmp dl, 15 ;Q: IRQ in range? + ja fcp_invalid ; N: + xor dh, dh + push ax + push dx + call GetPortFIFO + call GetPortDSR + pop dx + pop ax + clc +fcp_exit: + pop es + pop cx + pop bx + ret + +fcp_invalid: + or ax, -1 + mov dx, ax + stc + jmp fcp_exit + +FindCOMPort endp +.8086 + +page +;--------------------------Private Routine-----------------------------; +; +; Rotate the PIC interrupt priorities so the communication ports are +; highest priority. +; +; NOTE: Only rotates priorities on master PIC. +; +;-----------------------------------------------------------------------; + + assumes ds,Data + assumes es,nothing + + public Rotate_PIC + +Rotate_PIC proc near + + push ax + push cx + push di + + mov al, 8 ; 0 - 7 rotated + mov cx, MAXCOM+1 + mov di, DataOFFSET IRQhooks +rp_loop: + mov ah, [di.IRQn] + cmp ah, 0 ;End of hooked IRQ list? + je rp_set + cmp [di.VecN], 0FFh ;Hooked? + je rp_next + cmp ah, 8 ;If on slave PIC, treat as IRQ2 + jb @f + mov ah, 2 +@@: + cmp ah, al + jae rp_next + mov al, ah ;AL = lowest hooked comm IRQ +rp_next: + add di, SIZE IRQ_Hook_Struc + loop rp_loop + +rp_set: + dec al ;Setting IRQ(n-1) as the lowest + and al, 07h ; priority makes IRQn the highest + or al, 0C0h + out INTA0, al + + pop di + pop cx + pop ax + ret + +Rotate_PIC endp + + +ifdef DEBUG + public InitCom10, InitCom20, InitCom40, InitCom50, InitCom59 + public InitCom60, InitCom70, InitCom80, InitCom90, InitCom100 + public TermCom10, TermCom15, TermCom20, TermCom30 + public TermCom60, Terminate5, Terminate10, Terminate20, Terminate30 + public Terminate45, Terminate49, Terminate50 + public SetQue10 + public SetCom5, SetCom10, SetCom20, SetCom210, SetCom220, SetCom230 + public SetCom240, SetCom310, SetCom410, SetCom420, SetCom430 + public SetCom440, SetCom450, SetCom460, SetCom470 + public GetDEB10, GetDEB20, GetDEB30 + public DCBPtr10 +endif + +sEnd code + +page + +createSeg _INIT,init,word,public,CODE +sBegin init +assumes cs,init + + + +;------------------------------------------------------------------------------ +;------------------------------------------------------------------------------ +IBMmodel proc near + push ax + push bx + push es + + mov ah, 0c0h + int 15h + jc IBMmodel_exit + + assumes es,nothing + + cmp by es:[bx+2], 0f8h ; PS/2 80 + je IBMmodel_exit ; return carry clear + + cmp by es:[bx+2], 0fch ; AT or PS/2 50 or 60 + jne OldBios ; assume OldBios + + cmp by es:[bx+3], 04h ; PS/2 50 + je IBMmodel_exit ; return carry clear + cmp by es:[bx+3], 05h ; PS/2 60 + je IBMmodel_exit ; return carry clear + +OldBios: + stc + +IBMmodel_exit: + pop es + pop bx + pop ax + ret + +IBMmodel endp + +cProc LoadLib, <FAR,PUBLIC,NODATA>,<si,di> +cBegin + + push ds + mov ax, __F000H + mov ds, ax + assumes ds, ROMBios + mov al, [MachineID] + pop ds + assumes ds,Data + mov [$MachineID], al + + call IBMmodel ;Q: PS/2? + jc @F ; N: + mov [default_table+2], 3 ; Y: change COM3 default IRQ to 3 +@@: + + push ds + mov ax, __0040H + mov ds, ax + assumes ds,nothing + cmp word ptr ds:[RS232B], 2F8h ;Q: COM2 base in COM1 slot? + pop ds + assumes ds,Data + jne @F ; N: leave IRQ default as 4 + mov [default_table], 3 ; Y: change IRQ default to 3 +@@: + + mov [fVPICD], -1 ; assume no + + xor di, di + mov es, di + mov ax, GET386API + mov bx, VPICD + int MULTIPLEX + mov wo [lpfnVPICD], di + mov wo [lpfnVPICD+2], es + mov ax, es + or ax, di + jz short no_VPICD ; jump if no bimodel services available +; +; version check VPICD +; + mov ax, VPICD_API_Get_Ver + call [lpfnVPICD] +%OUT version check VPICD + + mov [fVPICD], 1 ; flag services are available + +IFDEF No_DOSX_Bimodal_Services + jmp short skip_dosx_stuff + +no_VPICD: + mov ax, __WinFlags + and al, WF_PMODE or WF_WIN286 + cmp al, WF_PMODE or WF_WIN286 + jne skip_dosx_stuff + +.286 + mov ax, Int31_Get_Version SHL 8 + int 31h + test bl, 10b ;Q: processor goes to real mode + ; for int reflection? + jz skip_dosx_stuff ; N: + mov [Using_DPMI], 0FFh ; Y: flag use of DPMI + + mov ax, ds + cCall GetSelectorBase,<ax> ;DX:AX = segment of selector + shr ax, 4 + shl dl, 4 + or ah, dl ;AX now points to interrupt *segment* + push ax ;save on stack + mov ax, _INTERRUPT ;write data SEGMENT into _INTERRUPT + cCall AllocCStoDSAlias,<ax> ; code segment -- requires a data alias + mov es, ax + pop ax + mov es:[RM_IntDataSeg],ax + push ds + push es + mov ax, ds + mov es, ax + mov ax, _INTERRUPT + mov ds, ax + mov ax, (Int31_Trans_Serv SHL 8) + Trans_Call_Back + mov si, IntCodeOFFSET Entry_From_RM + mov di, DataOFFSET RM_Call_Struc + int 31h + pop es + pop ds + mov ax, 0 + jnc @f + jmp short LoadExit +@@: + mov wo es:[RM_CallBack], dx + mov wo es:[RM_CallBack+2], cx + cCall FreeSelector,<es> ;don't need CS alias any longer +.8086 +skip_dosx_stuff: +ELSE +no_VPICD: +ENDIF + +; +; find base values for LPT ports +; + mov cx, __0040h + mov es, cx + mov cx, MAXLPT+1 + mov si, DataOFFSET LPT1 +ll_initl_lp: + mov bx, [si.BIOSPortLoc] + or bx, bx + jz ll_not_phys_lpt + mov ax, es:[bx] + or ah, ah ;Q: lpt redirected, or 0? + jz ll_not_phys_lpt ; Y: + cmp bx, LPTB ;Q: first LPT? + je ll_got_lpt_base ; Y: + cmp ax, es:[bx-2] ;Q: base same as previous (redirected)? + jne ll_got_lpt_base ; N: must be real +ll_not_phys_lpt: +%OUT attempt to read base from SYSTEM.INI + +ll_got_lpt_base: + mov [si.Port], ax + loop ll_initl_lp + +; +; create system timer for signalling chars in receive buffer +; + +ifndef WOW + mov ax, 100 ; create 100msec timer + push ax + mov ax, _INTERRUPT + push ax + mov ax, IntCodeOFFSET TimerProc + push ax + call CreateSystemTimer ; ax = 0, if failed +%OUT should I display an error message here? + +endif + assumes es,nothing +LoadExit: +cEnd + +sEnd init + +End LoadLib diff --git a/private/mvdm/wow16/drivers/comm/ins8250.inc b/private/mvdm/wow16/drivers/comm/ins8250.inc new file mode 100644 index 000000000..6d61a0227 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/ins8250.inc @@ -0,0 +1,78 @@ +; INS8250 ACE Register Offsets And Bit Definitions + + +ACE_RBR equ 0 ;Receiver Buffer +ACE_THR equ 0 ;Transmit Holding Register + +ACE_IER equ 1 ;Interrupt Enable + ACE_ERBFI equ 00000001b ; Received Data Available + ACE_ETBEI equ 00000010b ; Transmitter Holding Register Empty + ACE_ELSI equ 00000100b ; Receiver Line Status + ACE_EDSSI equ 00001000b ; Modem Status + +ACE_FCR equ 2 ;FIFO control register + ACE_EFIFO equ 00000001b ; Enable FIFO + ACE_CRFIFO equ 00000010b ; Clear receive FIFO queue + ACE_CTFIFO equ 00000100b ; Clear transmit FIFO queue + ACE_TRIG01 equ 00000000b ; Trigger receive int on every char + ACE_TRIG04 equ 01000000b ; Trigger receive int on every 4th char + ACE_TRIG08 equ 10000000b ; Trigger receive int on every 8th char + ACE_TRIG14 equ 11000000b ; Trigger receive int on every 14th char + +ACE_IIDR equ 2 ;Interrupt Identification + ACE_IIP equ 00000001b ; Inverted Interrupt Pending (0=int) + ACE_IID equ 00000110b ; Interrupt ID + ACE_MSI equ 00000000b ; Modem Status + ACE_THREI equ 00000010b ; Transmitter Holding Register Empty + ACE_RDAI equ 00000100b ; Received Data Available + ACE_RLSI equ 00000110b ; Receiver Line Status + ACE_FIFO_E1 equ 01000000b ;set, if FIFO enabled on 16550A + ACE_FIFO_E2 equ 10000000b ;set, if FIFO enabled on 16550 or 16550A + +ACE_LCR equ 3 ;Line Control + ACE_WLS equ 00000011b ; Word Length Select Bits + ACE_WLS0 equ 00000001b ; Word Length Select Bit 0 + ACE_WLS1 equ 00000010b ; Word Length Select Bit 1 + ACE_5BW equ 00000000b ; 5 Bit Words + ACE_6BW equ 00000001b ; 6 Bit Words + ACE_7BW equ 00000010b ; 7 Bit Words + ACE_8BW equ 00000011b ; 8 Bit Words + ACE_STB equ 00000100b ; Stop Bits + ACE_1SB equ 00000000b ; 1 Stop Bits (1.5 for 5 bit words) + ACE_2SB equ 00000100b ; 2 Stop Bits + ACE_PEN equ 00001000b ; Parity Enable + ACE_PSB equ 00110000b ; Parity select bits + ACE_EPS equ 00010000b ; Even Parity Select + ACE_SP equ 00100000b ; Stick Parity + ACE_SB equ 01000000b ; Set Break + ACE_DLAB equ 10000000b ; Divisor Latch Access Bit + +ACE_MCR equ 4 ;Modem Control + ACE_DTR equ 00000001b ; Data Terminal ready + ACE_RTS equ 00000010b ; Request To Send + ACE_OUT1 equ 00000100b ; Output Line 1 + ACE_OUT2 equ 00001000b ; Output Line 2 + ACE_LOOP equ 00010000b ; Loopback + +ACE_LSR equ 5 ;Line Status + ACE_DR equ 00000001b ; Data Ready + ACE_OR equ 00000010b ; Overrun Error + ACE_PE equ 00000100b ; Parity Error + ACE_FE equ 00001000b ; Framing Error + ACE_BI equ 00010000b ; Break Interrupt + ACE_THRE equ 00100000b ; Transmitter Holding Register Empty + ACE_TSRE equ 01000000b ; Transmitter Shift Register Empty + +ACE_MSR equ 6 ;Modem Status + ACE_DCTS equ 00000001b ; Delta Clear to Send + ACE_DDSR equ 00000010b ; Delta Data Set Ready + ACE_TERI equ 00000100b ; Trailing Edge Ring Indicator + ACE_DRLSD equ 00001000b ; Delta Receive Line Signal Detect + ACE_CTS equ 00010000b ; Clear To Send + ACE_DSR equ 00100000b ; Data Set ready + ACE_RI equ 01000000b ; Ring Indicator + ACE_RLSD equ 10000000b ; Receive Line Signal Detect + +ACE_DLL equ 0 ;LSB Baud Rate Divisor + +ACE_DLM equ 1 ;MSB Baud Rate Divisor diff --git a/private/mvdm/wow16/drivers/comm/makefile b/private/mvdm/wow16/drivers/comm/makefile new file mode 100644 index 000000000..2b5303d44 --- /dev/null +++ b/private/mvdm/wow16/drivers/comm/makefile @@ -0,0 +1,127 @@ +# comm16 makefile +# +# Copyright (c) 1992, Microsoft Corporation +# +# History: +# 27-Mar-1992 Nandurir +# Created. +# 6-Feb-1994 LeeHart +# Modified for version resources & CV Symbols +# + +!IFDEF USEBUILD + +# If using BUILD.EXE, edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2. + +!INCLUDE $(NTMAKEENV)\makefile.def + +!ELSE + +.SUFFIXES: +.SUFFIXES: .c .asm .h .inc .obj .lst .sys .exe .com .map .sym .def .lib .rc .res + + +!ifdef INCLUDE +INCS = +!else +INCS = -I..\..\inc -I..\..\..\inc +!endif + +########## Path definition so we find 16 bit tools ########## +# Also works around stupid bug in RC 3.1 that doesn't allow rcpp.err to be +# in a directory that is greater than 128 chars down the path, even if +# rc 3.1 is running as an OS/2 app. + +PATH = $(_NTBINDIR)\private\mvdm\tools16;$(PATH) + +# DEFINES = -DWOW -DDEBUG $(MVDMFLAGS) +DEFINES = -DWOW $(MVDMFLAGS) + +AOBJ = -t $(DEFINES) $(INCS) + +CW16 = -AS -G2sw -Os -W3 -Zp $(DEFINES) $(INCS) +CW16B = $(CW16) -B1 c1l.exe -B2 c2l.exe -B3 c3l.exe + +LINK = /map /align:16 + +!if "$(NTDEBUG)"!="" && "$(NTDEBUG)"!="retail" && "$(NTDEBUG)" != "ntsdnodbg" +AOBJ = $(AOBJ) -Zd +CW16 = $(CW16) /Od /Oi /Zd +LINK = $(LINK) /LI +!endif + +W16LIBS = ..\..\lib\snocrtd.lib + + +.asm.obj: + masm $(AOBJ) $*; + +.asm.lst: + masm $(AOBJ) -l $*,nul,$*.lst; + + +.c.obj: + cl16 -c -nologo $(CW16) $*.c + +.c.lst: + cl16 -c -nologo $(CW16) -Fonul -Fc$*.lst $*.c + + +.def.lib: + implib $*.lib $*.def + +.map.sym: + mapsym $* + +.rc.res: + rc16 -r $(INCS) -fo $@ $*.rc + + +all: comm.drv comm.map comm.sym comm.lrf + binplace comm.drv comm.map comm.sym + +clean: cleanup all + +cleanup: + if exist *.lrf del *.lrf + if exist *.obj del *.obj + if exist *.exe del *.exe + if exist *.map del *.map + if exist *.sym del *.sym + if exist *.drv del *.drv + if exist *.res del *.res + + +ccom.obj ccom.lst: ccom.asm ibmcom.inc comdev.inc + +ibmsetup.obj ibmsetup.lst: ibmsetup.asm ibmcom.inc comdev.inc ins8250.inc + +ibmcom.obj: $*.asm $*.inc comdev.inc ins8250.inc + +ibmint.obj: $*.asm ibmcom.inc comdev.inc ins8250.inc + +ibmlpt.obj: $*.asm ibmcom.inc comdev.inc + +commmsg.obj: $*.asm + +comm.res: $*.rc $*.rcv ..\..\inc\common.ver + +comm.lrf: makefile + echo ccom+ibmsetup+ibmcom+ibmint+ibmlpt+commmsg >$@ + echo $*.exe/align:16>>$@ + echo $* $(LINK)>>$@ + echo ..\..\lib\libw.lib ..\..\lib\snocrtd.lib /map /nod>>$@ + echo $*;>>$@ + +comm.drv: ccom.obj ibmsetup.obj ibmcom.obj ibmint.obj ibmlpt.obj commmsg.obj \ + $*.def $*.res $*.lrf + link16 @$*.lrf; + rc16 -t $*.res $*.exe + if exist *.drv del *.drv + ren $*.exe $@ + +comm.sym: $*.map + mapsym $* +!ENDIF diff --git a/private/mvdm/wow16/drivers/display/config.asm b/private/mvdm/wow16/drivers/display/config.asm new file mode 100644 index 000000000..d8b7c3a2a --- /dev/null +++ b/private/mvdm/wow16/drivers/display/config.asm @@ -0,0 +1,64 @@ +;*************************************************************************** +; * +; Copyright (C) 1985-1989 by Microsoft Inc. * +; * +;*************************************************************************** + + title Hardware Dependent Parameters + %out config + page ,132 + + +RGB macro R, G, B + db R,G,B,0 + endm + + + +OEM segment public + +; Machine dependent parameters + + dw 14 ;Height of vertical thumb + dw 18 ;Width of horizontal thumb + dw 2 ;Icon horiz compression factor + dw 2 ;Icon vert compression factor + dw 1 ;Cursor horz compression factor + dw 1 ;Cursor vert compression factor + dw 0 ;Kanji window height + dw 1 ;cxBorder (thickness of vertical lines) + dw 1 ;cyBorder (thickness of horizontal lines) + +; Default system color values + + RGB 129,129,129 ;clrScrollbar + RGB 192,192,192 ;clrDesktop + RGB 000,000,128 ;clrActiveCaption + RGB 255,255,255 ;clrInactiveCaption + RGB 255,255,255 ;clrMenu + RGB 255,255,255 ;clrWindow + RGB 000,000,000 ;clrWindowFrame + RGB 000,000,000 ;clrMenuText + RGB 000,000,000 ;clrWindowText + RGB 255,255,255 ;clrCaptionText + RGB 128,128,128 ;clrActiveBorder + RGB 255,255,255 ;clrInactiveBorder + RGB 255,255,255 ;clrAppWorkspace + RGB 000,000,128 ;clrHiliteBk + RGB 255,255,255 ;clrHiliteText + RGB 255,255,255 ;clrBtnFace + RGB 128,128,128 ;clrBtnShadow + RGB 128,128,128 ;clrGrayText + RGB 000,000,000 ;clrBtnText + +; dw 0 ;Unused words +; dw 0 +; dw 0 +; dw 0 +; dw 0 +; dw 0 + dw 0 + dw 0 + +OEM ends +end diff --git a/private/mvdm/wow16/drivers/display/display.asm b/private/mvdm/wow16/drivers/display/display.asm new file mode 100644 index 000000000..5573f7eac --- /dev/null +++ b/private/mvdm/wow16/drivers/display/display.asm @@ -0,0 +1,88 @@ + TITLE DISPLAY.ASM + PAGE ,132 +; +; WOW v1.0 +; +; Copyright (c) 1991, Microsoft Corporation +; +; DISPLAY.ASM +; Thunks in 16-bit space to route Windows API calls to WOW32 +; +; History: +; 13-MAY-1992 Matt Felton (mattfe) +; Created. +; +; WinProj 3.0 does the following API:- +; GetModuleFileName(GetModuleHandle("DISPLAY"), buffer, sizeof(buffer)); +; In WOW we do not require a display driver becuase we always call GDI32 to +; perform screen IO. + + + + .286p + + .xlist + include cmacros.inc + .list + + __acrtused = 0 + public __acrtused ;satisfy external C ref. + + +createSeg _TEXT,CODE,WORD,PUBLIC,CODE +createSeg _DATA,DATA,WORD,PUBLIC,DATA,DGROUP +defgrp DGROUP,DATA + +sBegin DATA +Reserved db 16 dup (0) ;reserved for Windows //!!!!! what is this + +DISPLAY_Identifier db 'DISPLAY' + +sEnd DATA + + +sBegin CODE +assumes CS,CODE +assumes DS,DATA +assumes ES,NOTHING + +cProc DISPLAY,<PUBLIC,FAR,PASCAL,NODATA,ATOMIC> + cBegin <nogen> + mov ax,1 ;always indicate success + ret + cEnd <nogen> + +assumes DS,NOTHING + +cProc WEP,<PUBLIC,FAR,PASCAL,NODATA,NOWIN,ATOMIC> + parmW iExit ;DLL exit code + + cBegin + mov ax,1 ;always indicate success + cEnd + +cProc Disable,<FAR,PUBLIC,WIN,PASCAL>,<si,di> + parmD lp_device + +cBegin + mov ax,-1 +cEnd + +cProc Enable,<FAR,PUBLIC,WIN,PASCAL>,<si,di> + parmD lp_device ;Physical device or GDIinfo destination + parmW style ;Style, Enable Device, or Inquire Info + parmD lp_device_type ;Device type (i.e FX80, HP7470, ...) + parmD lp_output_file ;DOS output file name (if applicable) + parmD lp_stuff ;Device specific information + +cBegin + mov ax,0 +cEnd + +assumes DS,DATA + +assumes DS,NOTHING + +sEnd CODE + +end DISPLAY diff --git a/private/mvdm/wow16/drivers/display/display.def b/private/mvdm/wow16/drivers/display/display.def new file mode 100644 index 000000000..175fbfa33 --- /dev/null +++ b/private/mvdm/wow16/drivers/display/display.def @@ -0,0 +1,17 @@ +LIBRARY DISPLAY + +DESCRIPTION 'Windows Display Driver' + +EXETYPE WINDOWS +STUB '..\..\BIN\WINSTUB.EXE' + +CODE PRELOAD MOVEABLE + +DATA PRELOAD MOVEABLE SINGLE + +HEAPSIZE 0 + +EXPORTS + WEP + Disable @4 + Enable @5 diff --git a/private/mvdm/wow16/drivers/display/display.rc b/private/mvdm/wow16/drivers/display/display.rc new file mode 100644 index 000000000..585d45cce --- /dev/null +++ b/private/mvdm/wow16/drivers/display/display.rc @@ -0,0 +1,8 @@ +/* Resource file for EGA (4-plane) display driver */ + +#define OEMRESOURCE +#define WIN31 +#include "windows.h" +#include "display.rcv" + +1 oembin PRELOAD config.bin diff --git a/private/mvdm/wow16/drivers/display/display.rcv b/private/mvdm/wow16/drivers/display/display.rcv new file mode 100644 index 000000000..596a32d4d --- /dev/null +++ b/private/mvdm/wow16/drivers/display/display.rcv @@ -0,0 +1,12 @@ +/********************************************************************/ +/* DISPLAY.RCV */ +/********************************************************************/ +#include <version.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_DISPLAY +#define VER_FILEDESCRIPTION_STR "WOW Display Driver Module" +#define VER_INTERNALNAME_STR "VGA" +#define VER_ORIGINALFILENAME_STR "VGA.DRV" + +#include <common.ver> diff --git a/private/mvdm/wow16/drivers/display/makefile b/private/mvdm/wow16/drivers/display/makefile new file mode 100644 index 000000000..673e1a1ad --- /dev/null +++ b/private/mvdm/wow16/drivers/display/makefile @@ -0,0 +1,121 @@ +# display16 makefile +# +# Copyright (c) 1991, Microsoft Corporation +# +# History: +# 13-May-1992 Matt Felton (MattFe) +# +# Created. +# + +!IFDEF USEBUILD + +# If using BUILD.EXE, edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2. + +!INCLUDE $(NTMAKEENV)\makefile.def + +!ELSE + +.SUFFIXES: +.SUFFIXES: .c .asm .h .inc .obj .lst .sys .exe .com .map .sym .def .lib .res .rc + + +!ifdef INCLUDE +INCS = +!else +INCS = -I..\..\inc -I..\..\..\inc +!endif + +########## Path definition so we find 16 bit tools ########## +# Also works around stupid bug in RC 3.1 that doesn't allow rcpp.err to be +# in a directory that is greater than 128 chars down the path, even if +# rc 3.1 is running as an OS/2 app. + +PATH = $(_NTBINDIR)\private\mvdm\tools16;$(PATH) + +DEFINES = -DWOW -DDEBUG $(MVDMFLAGS) + +AOBJ = -Ml -t $(DEFINES) $(INCS) + +CW16 = -AS -G2sw -Os -W3 -Zp $(DEFINES) $(INCS) +CW16B = $(CW16) -B1 c1l.exe -B2 c2l.exe -B3 c3l.exe + +LINK = /map /align:16 + +!if "$(NTDEBUG)"!="" && "$(NTDEBUG)"!="retail" && "$(NTDEBUG)" != "ntsdnodbg" +AOBJ = $(AOBJ) -Zd +CW16 = $(CW16) /Od /Oi /Zd +LINK = $(LINK) /LI +!endif + +W16LIBS = ..\..\lib\snocrtd.lib + + +.asm.obj: + masm $(AOBJ) $*; + +.asm.lst: + masm $(AOBJ) -l $*,nul,$*.lst; + +.c.obj: + cl16 -c -nologo $(CW16) $*.c + +.c.lst: + cl16 -c -nologo $(CW16) -Fonul -Fc$*.lst $*.c + + +.def.lib: + implib $*.lib $*.def + +.map.sym: + mapsym $* + +.rc.res: + rc16 -r -fo $@ $(INCS) $*.rc + +all: display.exe display.map display.sym + copy display.exe vga.drv + copy display.sym vga.sym + copy display.map vga.map + binplace vga.drv vga.map vga.sym + +clean: cleanup all + +cleanup: + if exist *.lrf del *.lrf + if exist *.obj del *.obj + if exist *.exe del *.exe + if exist *.map del *.map + if exist *.sym del *.sym + if exist *.res del *.res + +display.obj: $*.asm ..\..\..\inc\wow.inc + masm -l $(AOBJ) $*; + +config.obj: $*.asm + masm -l $(AOBJ) $*; + +config.exe: $*.obj + link16 $*; + +config.bin: $*.exe + exe2bin $*.exe + +display.res: $*.rc config.bin $*.rcv ..\..\inc\common.ver + +display.lrf: makefile + echo $*.obj >$@ + echo $*.exe>>$@ + echo $* $(LINK)>>$@ + echo ..\..\lib\libw.lib ..\..\lib\snocrt.lib /nod>>$@ + echo $*;>>$@ + +display.exe display.map: display.obj display.lrf display.def display.res + link16 @display.lrf; + rc16 -t display.res display.exe + +display.sym: $*.map + +!ENDIF diff --git a/private/mvdm/wow16/drivers/keyboard/kbd.def b/private/mvdm/wow16/drivers/keyboard/kbd.def new file mode 100644 index 000000000..c5961214d --- /dev/null +++ b/private/mvdm/wow16/drivers/keyboard/kbd.def @@ -0,0 +1,118 @@ +LIBRARY KEYBOARD + +; ============================================================ +; ANY CHANGES TO KBD.DEF SHOULD ALSO BE MADE IN THE FOLLOWING: +; KBDNOKIA.DEF KBDHP.DEF KBDOLI.DEF +; (except for SetSpeed) +; ============================================================ + +; Copyright (C) 1989 by Microsoft Corporation + +DESCRIPTION 'KEYBOARD (Enhanced keyboard):' + +EXETYPE WINDOWS + +; (use LINK4 default stub, not WINSTUB) + +CODE PRELOAD FIXED +DATA PRELOAD FIXED SINGLE + +; ============================================================ +; ANY CHANGES TO KBD.DEF SHOULD ALSO BE MADE IN THE FOLLOWING: +; KBDNOKIA.DEF KBDHP.DEF KBDOLI.DEF +; ============================================================ + +SEGMENTS +; Initialization once-only code + _INIT PRELOAD FIXED DISCARDABLE + +; Translation tables + _TABS LOADONCALL FIXED DISCARDABLE + +; NewTable()'s and GetCSAlias()'s segment + _NEWTAB PRELOAD FIXED DISCARDABLE + +; OemKeyScan's segment + _OEMSC LOADONCALL DISCARDABLE + +; VkKeyScan's segment + _VKKSC LOADONCALL DISCARDABLE + +; SetSpeed's segment + _SETSP PRELOAD FIXED DISCARDABLE + +; GetKeyboardType's segment + _GETTYPE LOADONCALL DISCARDABLE + +; MapVirtualKey's segment + _MAPVK LOADONCALL DISCARDABLE + +; GetKeyNameText's segment + _GETNAME LOADONCALL DISCARDABLE + +; ============================================================ +; ANY CHANGES TO KBD.DEF SHOULD ALSO BE MADE IN THE FOLLOWING: +; KBDNOKIA.DEF KBDHP.DEF KBDOLI.DEF +; (except for SetSpeed) +; ============================================================ + +EXPORTS + Inquire @1 ;Internal + Enable @2 ;Internal + Disable @3 ;Internal + ToAscii @4 + AnsiToOem @5 + OemToAnsi @6 + +; Special call for setting keyboard repeat speed on AT-type keyboards +; (omit in Olivetti M24 and NOKIA drivers, since they're not for AT keyboards) + SetSpeed @7 ;Internal + +; Special call for OS/2 Compatibility box +; (omit in Olivetti M24 drivers) + ScreenSwitchEnable @100 ;Internal + +; Routines for initializing keyboard tables + + GetTableSeg @126 ;Internal + NewTable @127 ;Internal + +; Special call for WIN386 WINOLDAP +; (omit in Olivetti M24 drivers, since they're 8086 only) + OEMKeyScan @128 + +; Special ASCII to virtual keycode routine + VkKeyScan @129 + +; Return keyboard type number, etc. + GetKeyboardType @130 + +; Return translations VK-> scancode, scancode-> VK, VK-> ASCII. + MapVirtualKey @131 + +; Return code page of current Oem/Ansi translation tables. + GetKBCodePage @132 + +; Get name string for key + GetKeyNameText @133 + +; Translate routines + AnsiToOemBuff @134 + OemToAnsiBuff @135 + +; Enable SysReq trap + EnableKBSysReq @136 ;Internal + +; codeview support + GetBIOSKeyProc @137 + + WEP ;Internal + +; ============================================================ +; ANY CHANGES TO KBD.DEF SHOULD ALSO BE MADE IN THE FOLLOWING: +; KBDNOKIA.DEF KBDHP.DEF KBDOLI.DEF +; ============================================================ + + +IMPORTS + CVWBREAK = KERNEL.205 diff --git a/private/mvdm/wow16/drivers/keyboard/kbdlocal.asm b/private/mvdm/wow16/drivers/keyboard/kbdlocal.asm new file mode 100644 index 000000000..e736ccfa6 --- /dev/null +++ b/private/mvdm/wow16/drivers/keyboard/kbdlocal.asm @@ -0,0 +1,301 @@ +;++ +; +; WOW v1.0 +; +; Copyright (c) 1991, Microsoft Corporation +; +; KBDLOCAL.ASM +; +; Win16 KEYBOARD APIS that are 'internal' +; We make these apis a 'nop'. Relevant code has been copied from WIN31. +; The intention here is to maintain the stack. Any arguments to the apis +; are popped and that is it. +; +; History: +; +; Created 06-Jan-1992 by NanduriR +;-- + + TITLE KBDLOCAL.ASM + PAGE ,132 + + .286p + + .xlist + include wow.inc + include wowkbd.inc + include cmacros.inc + include windefs.inc + .list + + __acrtused = 0 + public __acrtused ;satisfy external C ref. + + +createSeg _TEXT,CODE,WORD,PUBLIC,CODE +createSeg _DATA,DATA,WORD,PUBLIC,DATA,DGROUP +defgrp DGROUP,DATA + +; Double byte range values for the Far East. +; The values defined here are for the Rest Of the World. +; These values are for the inquireData (KBINFO) structure defined below. +; ('KeyInfo' in the Kernel, pState in USER) +; +BeginRange1 equ 255 +EndRange1 equ 254 +BeginRange2 equ 255 +EndRange2 equ 254 + +sBegin DATA + +globalD bios_proc, 0 +globalD nmi_vector, 0 +;externD nmi_vector + + +public fSysReq +fSysReq db 0 ; Enables CTRL-ALT-SysReq if NZ + +; Keyboard information block (copied to 'KeyInfo' in the kernel) +; this is a KBINFO data structure.. defined in KERNEL.INC, USER.INC, USER.H +; and WINDEFS.INC. +; +; As of 3.0, build 1.30, KBINFO includes the number of function keys +; As of 3.0, build 1.59, the number of bytes in the state block is +; fixed at 4 MAX, for compatibility with Excel 2.1c!!! +; + PUBLIC inquireData + PUBLIC iqdNumFunc +inquireData LABEL BYTE + DB BeginRange1 + DB EndRange1 + DB BeginRange2 + DB EndRange2 + DW 4 ; #bytes of state info for ToAscii() +iqdNumFunc label word + dw 10 ; number of function keys + +sEnd DATA + + +sBegin CODE +assumes CS,CODE +assumes DS,NOTHING +assumes ES,NOTHING + +assumes DS,DATA + +;*************************************************************************** +; +; Inquire( pKBINFO ) - copies information about the keyboard hardware into +; the area pointer to by the long pointer argument. Returns a count of the +; number of bytes copied. +; +; The Windows kernel calls this to copy information to its 'KeyInfo' data +; structure. +; +;*************************************************************************** +cProc Inquire,<PUBLIC,FAR>,<si,di> + parmD pKBINFO + +cBegin Inquire + ; .. now pass data to Windows .. + les di,pKBINFO ; Get far pointer of destination area + mov si, OFFSET inquireData ; Get source + mov ax,size KBINFO ; Get number of bytes to move + mov cx,ax ; (Return byte count in AX) + rep movsb ; Move the bytes + +cEnd Inquire + +;--------------------------------------------------------------------- +; +;---- ScreenSwitchEnable( fEnable ) ---------------------------------- +; +; This function is called by the display driver to inform the keyboard +; driver that the display driver is in a critical section and to ignore +; all OS/2 screen switches until the display driver leaves its +; critical section. The fEnable parameter is set to 0 to disable +; screen switches, and a NONZERO value to re-enable them. At startup, +; screen switches are enabled. +;--------------------------------------------------------------------- +; + +cProc ScreenSwitchEnable,<PUBLIC,FAR> +parmW fEnable + +cBegin ScreenSwitchEnable + + mov ax,fEnable ; get WORD parameter + or al,ah ; stuff any NZ bits into AL +;;; mov fSwitchEnable,al ; save BYTE. + +cEnd ScreenSwitchEnable + +;--------------------------------------------------------------------- +; +;---- EnableKBSysReq( fSys ) ---------------------------------- +; +; This function enables and shuttles off NMI interrupt simulation +; (trap to debugger) when CTRL-ALT-SysReq is pressed. +; CVWBreak overides int 2. +; fSysParm = 01 enable int 2 +; = 02 disable int 2 +; = 04 enable CVWBreak +; = 08 disable CVWBreak +; +;--------------------------------------------------------------------- +; +cProc EnableKBSysReq,<PUBLIC,FAR> +parmW fSysParm + +cBegin EnableKBSysReq + + mov ax, fSysParm ; get WORD parameter + + test al,01 ; turn on int 2? + jz @F + or fSysReq,01 ; yes, turn it on! +@@: test al,02 ; turn off int 2? + jz @F + and fSysReq,NOT 01 ; yes, turn it off! + +@@: test al,04 ; turn on CVWBreak? + jz @F + or fSysReq,02 ; yes, turn it on! +@@: test al,08 ; turn off CVWBreak? + jz @F + and fSysReq,NOT 02 ; yes, turn it off! +@@: + xor ah,ah + mov al,fSysReq + +ifdef NEWNMI + push ax ; save return value + call short GetNmi ; save NMI + pop ax ; restore .. +endif + +cEnd EnableKBSysReq + + +; save NMI vector. Called above in EnableKBSysReq() and in Enable(). + +ifdef NEWNMI +GetNmi proc near + mov ax,3502h + int 21h + mov word ptr ds:[nmi_vector][0],bx + mov word ptr ds:[nmi_vector][2],es + ret +GetNmi endp +endif + +;*************************************************************************** +; +; Enable( eventProc ) - enable hardware keyboard interrupts, with the passed +; procedure address being the target of all keyboard events. +; +; lpKeyState is a long pointer to the Windows 256 byte keystate table +; +;*************************************************************************** +cProc Enable,<PUBLIC,FAR>,<si,di> + parmD eventProc + parmD lpKeyState +cBegin Enable + sub ax, ax +cEnd Enable + +;*************************************************************************** +; Disable( eventProc ) - disable hardware keyboard interrupts, restoring +; the previous IBM BIOS keyboard interrupt handler. +; +;*************************************************************************** +cProc Disable,<PUBLIC,FAR>,<si,di> + +cBegin Disable + + sub ax,ax + +cEnd Disable + +; ** GetTableSeg() *************************************** +; +; This finds the paragraph of the TABS segment and stores +; it in TableSeg. +; +; Calling this will force the segment to be loaded. +; +; This segment isn't written to. +; +; REMEMBER that AX is TRASHED !! + + +cProc GetTableSeg,<PUBLIC,FAR>,<si,di> +cBegin GetTableSeg + +;;; mov ax,cs +;;; mov TableSeg,ax + +cEnd GetTableSeg + +;*************************************************************************** +; +; NewTable() +; +; Change keyboard tables, if a keyboard table DLL is defined in +; SYSTEM.INI and the function GetKbdTable() exists and returns +; successfully. +; +; This function is passed no parameters by the caller -- it obtains +; the following from SYSTEM.INI: +; +; [keyboard] +; TYPE = 4 ; 1..6. 4 is enhanced kbd. +; SUBTYPE = 0 ; 0 for all but Olivetti +; ; 8086 systems & AT&T 6300+ +; KEYBOARD.DLL = kbdus.dll ; name of DLL file +; OEMANSI.BIN = XLATNO.BIN ; oem/ansi tables file +; +; The module name of the DLL is expected to be the root of the DLL's +; file name. In any event, the module name must be different for +; each keyboard-table DLL! +; +;*************************************************************************** + +cProc NewTable,<PUBLIC,FAR>,<si,di> + ; LOCAL variables on stack: + +cBegin NewTable + sub ax,ax +cEnd NewTable + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; SetSpeed.asm +; +; +; Sets 'typematic' speed of AT-type keyboards (type code 3 or 4 in this +; driver). +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +cProc SetSpeed,<FAR,PASCAL,PUBLIC> + parmW rate_of_speed +cBegin + +SS_error_return: + mov ax,-1 ; error return + +SS_end: +cEnd + + +cProc GetBIOSKeyProc, <FAR, PUBLIC> +cBegin + mov ax, word ptr [bios_proc][0] + mov dx, word ptr [bios_proc][2] +cEnd + +sEnd CODE + + +end diff --git a/private/mvdm/wow16/drivers/keyboard/keyboard.asm b/private/mvdm/wow16/drivers/keyboard/keyboard.asm new file mode 100644 index 000000000..e234209b9 --- /dev/null +++ b/private/mvdm/wow16/drivers/keyboard/keyboard.asm @@ -0,0 +1,155 @@ +;++ +; +; WOW v1.0 +; +; Copyright (c) 1991, Microsoft Corporation +; +; KBD.ASM +; Win16 KEYBOARD thunks +; +; History: +; +; Created 06-Jan-1992 by NanduriR +;-- + + TITLE KEYBOARD.ASM + PAGE ,132 + + .286p + + .xlist + include wow.inc + include wowkbd.inc + include cmacros.inc + include windefs.inc + include vdmtib.inc + .list + + __acrtused = 0 + public __acrtused ;satisfy external C ref. + + +createSeg _TEXT,CODE,WORD,PUBLIC,CODE +createSeg _DATA,DATA,WORD,PUBLIC,DATA,DGROUP +defgrp DGROUP,DATA + +sBegin DATA +Reserved db 16 dup (0) ;reserved for Windows +KEYBOARD_Identifier db 'KEYBOARD16 Data Segment' +externD bios_proc + +sEnd DATA + + +sBegin CODE +assumes CS,CODE +assumes DS,DATA +assumes ES,NOTHING + +; Hung App Support +; If USER32 is unable to terminate an app via End Task then it calls +; WOW32 to kill the app. We do this by generating a keyboard h/w +; interrupt 9. Since in WOW all keyboard input comes via USER32 the +; keyboard h/w interrupt is unused for anything else so we can reuse +; this interrupt. + + +cProc KEYBOARD16,<PUBLIC,FAR> +cBegin + mov ax,3500h or 09h + int 21h ; vector is in ES:BX + mov word ptr [bios_proc][0], bx + mov word ptr [bios_proc][2], es + +; Setup keyboard interrupt vector to point to our interrupt routine + mov ax,2500h or 09h + mov dx,OFFSET keybd_int + push ds ; save DS + push cs + pop ds ; set DS = CS + int 21h ; set the vector + pop ds ; restore DS + mov ax,1 +cEnd + + +INTA0 equ 20h ;X'20' 8259 Interrupt Control Port +EOI equ 20h ;X'20' 8259 End-of-Interrupt ack + +public keybd_int +keybd_int PROC FAR + push ax + push bx + push es + + mov al,EOI ; Send Non-Specific EOI + out INTA0,al + +; +; Now we test the bit in low memory that is set by wow32 to see if this +; is really a keyboard int forced in by the hung app support. +; + mov ax, 40h ;use bios data selector + mov es, ax + mov bx, FIXED_NTVDMSTATE_LINEAR - 400h + + .386 ;make it assemble +.errnz VDM_WOWHUNGAPP AND 0ff00ffffh ;make sure it's the third byte + test byte ptr es:[bx+2], VDM_WOWHUNGAPP SHR 16 + + jnz short hungapp_exit ;jump if this is really a hung app + + pop es + pop bx + pop ax + iret + +hungapp_exit: + and byte ptr es:[bx+2], 255 - (VDM_WOWHUNGAPP SHR 16) ; turn it off + pop es + pop bx + pop ax + .286p + + mov ax,4CFFH ; They said OK to Nuke app. + int 21h +keybd_int ENDP + + + +cProc WEP,<PUBLIC,FAR,PASCAL,NODATA,NOWIN,ATOMIC> + parmW iExit ;DLL exit code + + cBegin + mov ax,1 ;always indicate success + cEnd + + +assumes DS,NOTHING + +;;; KbdThunk INQUIRE ;Internal LOCALAPI +;;; KbdThunk ENABLE ;Internal +;;; KbdThunk DISABLE ;Internal + KbdThunk TOASCII + KbdThunk ANSITOOEM + KbdThunk OEMTOANSI +;;; KbdThunk SETSPEED ;Internal +;;; KbdThunk SCREENSWITCHENABLE ;Internal +;;; KbdThunk GETTABLESEG ;Internal +;;; KbdThunk NEWTABLE ;Internal + KbdThunk OEMKEYSCAN + KbdThunk VKKEYSCAN + KbdThunk GETKEYBOARDTYPE + KbdThunk MAPVIRTUALKEY + KbdThunk GETKBCODEPAGE + KbdThunk GETKEYNAMETEXT + KbdThunk ANSITOOEMBUFF + KbdThunk OEMTOANSIBUFF +;;; KbdThunk ENABLEKBSYSREQ ;Internal LOCALAPI +;;; KbdThunk GETBIOSKEYPROC ; in kbdlocal.asm + + + +sEnd CODE + +end KEYBOARD16 diff --git a/private/mvdm/wow16/drivers/keyboard/keyboard.def b/private/mvdm/wow16/drivers/keyboard/keyboard.def new file mode 100644 index 000000000..4bbe239c7 --- /dev/null +++ b/private/mvdm/wow16/drivers/keyboard/keyboard.def @@ -0,0 +1,30 @@ +LIBRARY KEYBOARD + +DESCRIPTION 'WOW REPLACEMENT KEYBOARD (Enhanced keyboard)' +EXETYPE WINDOWS +CODE PRELOAD FIXED +DATA PRELOAD FIXED SINGLE +HEAPSIZE 0 + +EXPORTS + WEP + INQUIRE @1 ;Internal + ENABLE @2 ;Internal + DISABLE @3 ;Internal + TOASCII @4 + ANSITOOEM @5 + OEMTOANSI @6 + SETSPEED @7 ;Internal + SCREENSWITCHENABLE @100 ;Internal + GETTABLESEG @126 ;Internal + NEWTABLE @127 ;Internal + OEMKEYSCAN @128 + VKKEYSCAN @129 + GETKEYBOARDTYPE @130 + MAPVIRTUALKEY @131 + GETKBCODEPAGE @132 + GETKEYNAMETEXT @133 + ANSITOOEMBUFF @134 + OEMTOANSIBUFF @135 + ENABLEKBSYSREQ @136 ;Internal + GETBIOSKEYPROC @137 diff --git a/private/mvdm/wow16/drivers/keyboard/keyboard.rc b/private/mvdm/wow16/drivers/keyboard/keyboard.rc new file mode 100644 index 000000000..abd869a70 --- /dev/null +++ b/private/mvdm/wow16/drivers/keyboard/keyboard.rc @@ -0,0 +1,4 @@ +/********************************************************************/ +/* KEYBOARD.RC */ +/********************************************************************/ +#include "keyboard.rcv" diff --git a/private/mvdm/wow16/drivers/keyboard/keyboard.rcv b/private/mvdm/wow16/drivers/keyboard/keyboard.rcv new file mode 100644 index 000000000..58989318c --- /dev/null +++ b/private/mvdm/wow16/drivers/keyboard/keyboard.rcv @@ -0,0 +1,12 @@ +/********************************************************************/ +/* KEYBOARD.RCV */ +/********************************************************************/ +#include <version.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_KEYBOARD +#define VER_FILEDESCRIPTION_STR "WOW Keyboard Driver Module" +#define VER_INTERNALNAME_STR "KEYBOARD" +#define VER_ORIGINALFILENAME_STR "KEYBOARD.DRV" + +#include <common.ver> diff --git a/private/mvdm/wow16/drivers/keyboard/makefile b/private/mvdm/wow16/drivers/keyboard/makefile new file mode 100644 index 000000000..11ecfe472 --- /dev/null +++ b/private/mvdm/wow16/drivers/keyboard/makefile @@ -0,0 +1,114 @@ +# keyboard16 makefile +# +# Copyright (c) 1991, Microsoft Corporation +# +# History: +# 26-Jan-1991 Jeff Parsons (jeffpar) +# Created. +# + +!IFDEF USEBUILD + +# If using BUILD.EXE, edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2. + +!INCLUDE $(NTMAKEENV)\makefile.def + +!ELSE + +.SUFFIXES: +.SUFFIXES: .c .asm .h .inc .obj .lst .sys .exe .com .map .sym .def .lib .rc .res + + +!ifdef INCLUDE +INCS = +!else +INCS = -I..\..\inc -I..\..\..\inc +!endif + +########## Path definition so we find 16 bit tools ########## +# Also works around stupid bug in RC 3.1 that doesn't allow rcpp.err to be +# in a directory that is greater than 128 chars down the path, even if +# rc 3.1 is running as an OS/2 app. + +PATH = $(_NTBINDIR)\private\mvdm\tools16;$(PATH) + +# DEFINES = -DWOW -DDEBUG $(MVDMFLAGS) +DEFINES = -DWOW $(MVDMFLAGS) + +AOBJ = -Ml -t $(DEFINES) $(INCS) + +CW16 = -AS -G2sw -Os -W3 -Zp $(DEFINES) $(INCS) +CW16B = $(CW16) -B1 c1l.exe -B2 c2l.exe -B3 c3l.exe + +LINK = /map /align:16 + +!if "$(NTDEBUG)"!="" && "$(NTDEBUG)"!="retail" && "$(NTDEBUG)" != "ntsdnodbg" +AOBJ = $(AOBJ) -Zd +CW16 = $(CW16) /Od /Oi /Zd +LINK = $(LINK) /LI +!endif + +W16LIBS = ..\..\lib\libw.lib ..\..\lib\snocrtd.lib + + +.asm.obj: + masm $(AOBJ) $*; + +.asm.lst: + masm $(AOBJ) -l $*,nul,$*.lst; + + +.c.obj: + cl16 -c -nologo $(CW16) $*.c + +.c.lst: + cl16 -c -nologo $(CW16) -Fonul -Fc$*.lst $*.c + + +.def.lib: + implib $*.lib $*.def + +.map.sym: + mapsym $* + +.rc.res: + rc16 -r $(INCS) $*.rc -fo $@ + +all: keyboard.drv keyboard.map keyboard.sym + binplace keyboard.drv keyboard.map keyboard.sym + +clean: cleanup all + +cleanup: + if exist *.lrf del *.lrf + if exist *.obj del *.obj + if exist *.exe del *.exe + if exist *.map del *.map + if exist *.sym del *.sym + if exist *.drv del *.drv + if exist *.res del *.res + +keyboard.obj: $*.asm ..\..\..\inc\wow.inc ..\..\..\inc\wowkbd.inc + +kbdlocal.obj: $*.asm ..\..\..\inc\wow.inc ..\..\..\inc\wowkbd.inc + +keyboard.res: $*.rc $*.rcv ..\..\inc\common.ver + +keyboard.lrf: makefile + echo $*.obj kbdlocal.obj >$@ + echo $*.exe/align:16>>$@ + echo $* $(LINK)>>$@ + echo ..\..\lib\libw.lib ..\..\lib\snocrtd.lib /map /nod>>$@ + echo $*;>>$@ + +keyboard.drv: $*.obj kbdlocal.obj $*.def $*.res $*.lrf + link16 @$*.lrf; + rc16 -t $*.res $*.exe + if exist *.drv del *.drv + ren $*.exe $@ + +keyboard.sym: $*.map + +!ENDIF diff --git a/private/mvdm/wow16/drivers/mouse/makefile b/private/mvdm/wow16/drivers/mouse/makefile new file mode 100644 index 000000000..20e1807c5 --- /dev/null +++ b/private/mvdm/wow16/drivers/mouse/makefile @@ -0,0 +1,110 @@ +# mouse16 makefile +# +# Copyright (c) 1991, Microsoft Corporation +# +# History: +# 30-Sept-1992 Chandan Chauhan (ChandanC) +# +# Created. +# + +!IFDEF USEBUILD + +# If using BUILD.EXE, edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2. + +!INCLUDE $(NTMAKEENV)\makefile.def + +!ELSE + +.SUFFIXES: +.SUFFIXES: .c .asm .h .inc .obj .lst .sys .exe .com .map .sym .def .lib .rc .res + + +!ifdef INCLUDE +INCS = +!else +INCS = -I..\..\inc -I..\..\..\inc +!endif + +########## Path definition so we find 16 bit tools ########## +# Also works around stupid bug in RC 3.1 that doesn't allow rcpp.err to be +# in a directory that is greater than 128 chars down the path, even if +# rc 3.1 is running as an OS/2 app. + +PATH = $(_NTBINDIR)\private\mvdm\tools16;$(PATH) + +DEFINES = -DWOW -DDEBUG $(MVDMFLAGS) + +AOBJ = -Ml -t $(DEFINES) $(INCS) + +CW16 = -AS -G2sw -Os -W3 -Zp $(DEFINES) $(INCS) +CW16B = $(CW16) -B1 c1l.exe -B2 c2l.exe -B3 c3l.exe + +LINK = /map /align:16 + +!if "$(NTDEBUG)"!="" && "$(NTDEBUG)"!="retail" && "$(NTDEBUG)" != "ntsdnodbg" +AOBJ = $(AOBJ) -Zd +CW16 = $(CW16) /Od /Oi /Zd +LINK = $(LINK) /LI +!endif + +W16LIBS = ..\..\lib\libw.lib ..\..\lib\snocrtd.lib + + +.asm.obj: + masm $(AOBJ) $*; + +.asm.lst: + masm $(AOBJ) -l $*,nul,$*.lst; + + +.c.obj: + cl16 -c -nologo $(CW16) $*.c + +.c.lst: + cl16 -c -nologo $(CW16) -Fonul -Fc$*.lst $*.c + +.def.lib: + implib $*.lib $*.def + +.map.sym: + mapsym $* + +.rc.res: + rc16 -r $(INCS) $*.rc -fo $@ + +all: mouse.exe mouse.map mouse.sym + copy mouse.exe mouse.drv + binplace mouse.drv mouse.map mouse.sym + +clean: cleanup all + +cleanup: + if exist *.lrf del *.lrf + if exist *.obj del *.obj + if exist *.exe del *.exe + if exist *.drv del *.drv + if exist *.lst del *.lst + if exist *.map del *.map + if exist *.sym del *.sym + if exist *.res del *.res + +mouse.obj: $*.asm ..\..\..\inc\wow.inc + masm -l $(AOBJ) $*; + +mouse.lrf: makefile + echo $*.obj >$@ + echo $*.exe>>$@ + echo $* $(LINK)>>$@ + echo ..\..\lib\libw.lib ..\..\lib\snocrtd.lib /nod>>$@ + echo $*;>>$@ + +mouse.res: mouse.rc mouse.rcv ..\..\inc\common.ver + +mouse.exe mouse.map: mouse.obj mouse.lrf mouse.def mouse.res + link16 @mouse.lrf; + rc16 -t mouse.res mouse.exe + +!ENDIF diff --git a/private/mvdm/wow16/drivers/mouse/mouse.asm b/private/mvdm/wow16/drivers/mouse/mouse.asm new file mode 100644 index 000000000..82d26ffd0 --- /dev/null +++ b/private/mvdm/wow16/drivers/mouse/mouse.asm @@ -0,0 +1,224 @@ + TITLE MOUSE.ASM + PAGE ,132 +; +; WOW v1.0 +; +; Copyright (c) 1991, Microsoft Corporation +; +; MOUSE.ASM +; Thunks in 16-bit space to route Windows API calls to WOW32 +; +; History: +; 30-Sept-1992 Chandan Chauhan (ChandanC) +; Created. +; +; Freehand and ??? need mouse driver. +; + + + .286p + + .xlist + include cmacros.inc + .list + + __acrtused = 0 + public __acrtused ;satisfy external C ref. + + +createSeg _TEXT,CODE,WORD,PUBLIC,CODE +createSeg _DATA,DATA,WORD,PUBLIC,DATA,DGROUP +defgrp DGROUP,DATA + +sBegin DATA +Reserved db 16 dup (0) ;reserved for Windows //!!!!! what is this + +mouse_Identifier db 'mouse' + +sEnd DATA + + +sBegin CODE +assumes CS,CODE +assumes DS,DATA +assumes ES,NOTHING + + + +cProc MOUSE,<PUBLIC,FAR,PASCAL,NODATA,ATOMIC> + cBegin <nogen> + mov ax,1 ;always indicate success + ret + cEnd <nogen> + + + +;--------------------------Exported-Routine-----------------------------; +; int Inquire(lp_mouse_info); +; +; Information regarding the mouse is returned to the caller. +; +; Entry: +; None +; Returns: +; AX = # bytes returned in lp_mouse_info +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS,BP +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +;-----------------------------------------------------------------------; + + assumes cs,Code + assumes ds,Data + +cProc Inquire,<FAR,PUBLIC,WIN,PASCAL>,<di> + + parmD lp_mouse_info + +cBegin + xor ax, ax + +cEnd + + + + +;--------------------------Exported-Routine-----------------------------; +; void Enable(lp_event_proc); +; +; Enable hardware mouse interrupts, with the passed procedure address +; being the target of all mouse events. +; +; This routine may be called while already enabled. In this case the +; passed event procedure should be saved, and all other initialization +; skipped. +; +; Entry: +; None +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS,BP +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +;-----------------------------------------------------------------------; + + assumes cs,Code + assumes ds,Data + +cProc Enable,<FAR,PUBLIC,WIN,PASCAL>,<si,di> + + parmD new_event_proc + +cBegin + +; The new event procedure is always saved regardless of the +; mouse already being enabled. This allows the event proc +; to be changed as needed. + + xor ax, ax + +cEnd + +;--------------------------Exported-Routine-----------------------------; +; void Disable(); +; +; Disable hardware mouse interrupts, restoring the previous mouse +; interrupt handler and 8259 interrupt enable mask. +; +; This routine may be called while already disabled. In this case the +; disabling should be ignored. +; +; Entry: +; None +; Returns: +; None +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS,BP +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +;-----------------------------------------------------------------------; + + + assumes cs,Code + assumes ds,Data + +cProc Disable,<FAR,PUBLIC,WIN,PASCAL>,<si,di> + +cBegin + xor ax, ax + +cEnd + +;--------------------------Exported-Routine-----------------------------; +; WORD WEP(); +; +; Generic WEP. +; +; Entry: +; None +; Returns: +; AX = 1 +; Error Returns: +; None +; Registers Preserved: +; all +; Registers Destroyed: +; none +;-----------------------------------------------------------------------; + + + assumes cs,Code + assumes ds,Data + +cProc WEP,<FAR,PUBLIC,WIN,PASCAL> +; parmW stuff +cBegin nogen + mov ax,1 + ret 2 +cEnd nogen + +;--------------------------Exported-Routine-----------------------------; +; int MouseGetIntVect(); +; +; The interrupt vector used by the mouse is returned to the caller. +; If no mouse is found, then -1 is returned. +; +; Entry: +; None +; Returns: +; AX = interrupt vector +; AX = -1 if no mouse was found +; Error Returns: +; None +; Registers Preserved: +; SI,DI,DS,BP +; Registers Destroyed: +; AX,BX,CX,DX,ES,FLAGS +;-----------------------------------------------------------------------; + + + assumes cs,Code + assumes ds,Data + +cProc MouseGetIntVect,<FAR,PUBLIC,WIN,PASCAL> + +cBegin + mov al, -1 +cEnd + + + +assumes DS,DATA + +assumes DS,NOTHING + +sEnd CODE + +end MOUSE diff --git a/private/mvdm/wow16/drivers/mouse/mouse.def b/private/mvdm/wow16/drivers/mouse/mouse.def new file mode 100644 index 000000000..05dd6a179 --- /dev/null +++ b/private/mvdm/wow16/drivers/mouse/mouse.def @@ -0,0 +1,16 @@ +LIBRARY MOUSE + +DESCRIPTION 'Microsoft Mouse' + +EXETYPE WINDOWS +STUB '..\..\bin\WINSTUB.EXE' + +CODE PRELOAD DISCARDABLE +DATA PRELOAD FIXED SINGLE + +EXPORTS + Inquire @1 + Enable @2 + Disable @3 + MouseGetIntVect @4 + WEP diff --git a/private/mvdm/wow16/drivers/mouse/mouse.rc b/private/mvdm/wow16/drivers/mouse/mouse.rc new file mode 100644 index 000000000..63c7913b7 --- /dev/null +++ b/private/mvdm/wow16/drivers/mouse/mouse.rc @@ -0,0 +1,4 @@ +/********************************************************************/ +/* MOUSE.RC */ +/********************************************************************/ +#include "mouse.rcv" diff --git a/private/mvdm/wow16/drivers/mouse/mouse.rcv b/private/mvdm/wow16/drivers/mouse/mouse.rcv new file mode 100644 index 000000000..c18f8290a --- /dev/null +++ b/private/mvdm/wow16/drivers/mouse/mouse.rcv @@ -0,0 +1,12 @@ +/********************************************************************/ +/* MOUSE.RCV */ +/********************************************************************/ +#include <version.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_MOUSE +#define VER_FILEDESCRIPTION_STR "WOW MOUSE Driver Module" +#define VER_INTERNALNAME_STR "MOUSE" +#define VER_ORIGINALFILENAME_STR "MOUSE.DRV" + +#include <common.ver> diff --git a/private/mvdm/wow16/drivers/sound/makefile b/private/mvdm/wow16/drivers/sound/makefile new file mode 100644 index 000000000..71554cdc9 --- /dev/null +++ b/private/mvdm/wow16/drivers/sound/makefile @@ -0,0 +1,109 @@ +# Sound16 makefile +# +# Copyright (c) 1992, Microsoft Corporation +# +# History: +# 27-Mar-1992 Nandurir +# Created. +# + +!IFDEF USEBUILD + +# If using BUILD.EXE, edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2. + +!INCLUDE $(NTMAKEENV)\makefile.def + +!ELSE + +.SUFFIXES: +.SUFFIXES: .c .asm .h .inc .obj .lst .sys .exe .com .map .sym .def .lib .rc .res + + +!ifdef INCLUDE +INCS = +!else +INCS = -I..\..\inc -I..\..\..\inc +!endif + +########## Path definition so we find 16 bit tools ########## +# Also works around stupid bug in RC 3.1 that doesn't allow rcpp.err to be +# in a directory that is greater than 128 chars down the path, even if +# rc 3.1 is running as an OS/2 app. + +PATH = $(_NTBINDIR)\private\mvdm\tools16;$(PATH) + +# DEFINES = -DWOW -DDEBUG $(MVDMFLAGS) +DEFINES = -DWOW $(MVDMFLAGS) + +AOBJ = -Ml -t $(DEFINES) $(INCS) + +CW16 = -AS -G2sw -Os -W3 -Zp $(DEFINES) $(INCS) +CW16B = $(CW16) -B1 c1l.exe -B2 c2l.exe -B3 c3l.exe + +LINK = /map /align:16 + +!if "$(NTDEBUG)"!="" && "$(NTDEBUG)"!="retail" && "$(NTDEBUG)" != "ntsdnodbg" +AOBJ = $(AOBJ) -Zd +CW16 = $(CW16) /Od /Oi /Zd +LINK = $(LINK) /LI +!endif + +W16LIBS = ..\..\lib\snocrtd.lib + +.asm.obj: + masm -L $(AOBJ) $*; + +.asm.lst: + masm $(AOBJ) -l $*,nul,$*.lst; + +.c.obj: + cl16 -c -nologo $(CW16) $*.c + +.c.lst: + cl16 -c -nologo $(CW16) -Fonul -Fc$*.lst $*.c + + +.def.lib: + implib $*.lib $*.def + +.map.sym: + mapsym $* + +.rc.res: + rc16 -r $(INCS) -fo $@ $*.rc + +all: sound.drv sound.map sound.sym + binplace sound.drv sound.map sound.sym + +clean: cleanup all + +cleanup: + if exist *.lrf del *.lrf + if exist *.obj del *.obj + if exist *.exe del *.exe + if exist *.map del *.map + if exist *.sym del *.sym + if exist *.drv del *.drv + if exist *.res del *.res + +sound.res: $*.rc $*.rcv ..\..\inc\common.ver + +sound.obj: $*.asm ..\..\..\inc\wow.inc ..\..\..\inc\wowsnd.inc + masm $(AOBJ) $*; + +sound.lrf: makefile + echo $*.obj >$@ + echo $*.exe/align:16>>$@ + echo $* $(LINK)>>$@ + echo ..\..\lib\libw.lib ..\..\lib\snocrtd.lib /map /nod>>$@ + echo $*;>>$@ + +sound.drv: $*.obj $*.lrf $*.def $*.res + link16 @$*.lrf; + rc16 -t $*.res $*.exe + if exist $*.drv del $*.drv + ren $*.exe $@ + +!ENDIF diff --git a/private/mvdm/wow16/drivers/sound/sound.asm b/private/mvdm/wow16/drivers/sound/sound.asm new file mode 100644 index 000000000..4ff4f7de6 --- /dev/null +++ b/private/mvdm/wow16/drivers/sound/sound.asm @@ -0,0 +1,88 @@ +;++ +; +; WOW v1.0 +; +; Copyright (c) 1991, Microsoft Corporation +; +; SOUND.ASM +; Win16 SOUND thunks +; +; History: +; +; Created 06-Jan-1992 by NanduriR +;-- + + TITLE SOUND.ASM + PAGE ,132 + + .286p + + .xlist + include wow.inc + include wowsnd.inc + include cmacros.inc + include windefs.inc + .list + + __acrtused = 0 + public __acrtused ;satisfy external C ref. + + +createSeg _TEXT,CODE,WORD,PUBLIC,CODE +createSeg _DATA,DATA,WORD,PUBLIC,DATA,DGROUP +defgrp DGROUP,DATA + +sBegin DATA +Reserved db 16 dup (0) ;reserved for Windows +SOUND_Identifier db 'SOUND16 Data Segment' + + +sEnd DATA + + +sBegin CODE +assumes CS,CODE +assumes DS,NOTHING +assumes ES,NOTHING + +cProc SOUND16,<PUBLIC,FAR,PASCAL,NODATA,ATOMIC> + + cBegin <nogen> + mov ax,1 + ret + cEnd <nogen> + + +cProc WEP,<PUBLIC,FAR,PASCAL,NODATA,NOWIN,ATOMIC> + parmW iExit ;DLL exit code + + cBegin + mov ax,1 ;always indicate success + cEnd + + +assumes DS,NOTHING + + SoundThunk OPENSOUND + SoundThunk CLOSESOUND + SoundThunk SETVOICEQUEUESIZE + SoundThunk SETVOICENOTE + SoundThunk SETVOICEACCENT + SoundThunk SETVOICEENVELOPE + SoundThunk SETSOUNDNOISE + SoundThunk SETVOICESOUND + SoundThunk STARTSOUND + SoundThunk STOPSOUND + SoundThunk WAITSOUNDSTATE + SoundThunk SYNCALLVOICES + SoundThunk COUNTVOICENOTES + SoundThunk GETTHRESHOLDEVENT + SoundThunk GETTHRESHOLDSTATUS + SoundThunk SETVOICETHRESHOLD + SoundThunk DOBEEP + SoundThunk MYOPENSOUND + + +sEnd CODE + +end SOUND16 diff --git a/private/mvdm/wow16/drivers/sound/sound.def b/private/mvdm/wow16/drivers/sound/sound.def new file mode 100644 index 000000000..fdb91863d --- /dev/null +++ b/private/mvdm/wow16/drivers/sound/sound.def @@ -0,0 +1,27 @@ +LIBRARY SOUND + +DESCRIPTION 'WOW REPLACEMENT SOUND DRIVER' +EXETYPE WINDOWS +CODE PRELOAD FIXED +DATA FIXED SINGLE PRELOAD + +EXPORTS + OPENSOUND @1 + CLOSESOUND @2 + SETVOICEQUEUESIZE @3 + SETVOICENOTE @4 + SETVOICEACCENT @5 + SETVOICEENVELOPE @6 NODATA + SETSOUNDNOISE @7 NODATA + SETVOICESOUND @8 + STARTSOUND @9 + STOPSOUND @10 + WAITSOUNDSTATE @11 + SYNCALLVOICES @12 NODATA + COUNTVOICENOTES @13 + GETTHRESHOLDEVENT @14 + GETTHRESHOLDSTATUS @15 + SETVOICETHRESHOLD @16 + DOBEEP @17 NODATA ;Internal + MYOPENSOUND @18 ;Internal + WEP NODATA ;Internal diff --git a/private/mvdm/wow16/drivers/sound/sound.rc b/private/mvdm/wow16/drivers/sound/sound.rc new file mode 100644 index 000000000..1d5afb03d --- /dev/null +++ b/private/mvdm/wow16/drivers/sound/sound.rc @@ -0,0 +1,4 @@ +/********************************************************************/ +/* SOUND.RC */ +/********************************************************************/ +#include "sound.rcv" diff --git a/private/mvdm/wow16/drivers/sound/sound.rcv b/private/mvdm/wow16/drivers/sound/sound.rcv new file mode 100644 index 000000000..2a8856150 --- /dev/null +++ b/private/mvdm/wow16/drivers/sound/sound.rcv @@ -0,0 +1,12 @@ +/********************************************************************/ +/* SOUND.RCV */ +/********************************************************************/ +#include <version.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SOUND +#define VER_FILEDESCRIPTION_STR "WOW SOUND Driver Module" +#define VER_INTERNALNAME_STR "SOUND" +#define VER_ORIGINALFILENAME_STR "SOUND.DRV" + +#include <common.ver> |