📄 serialio.c
字号:
}
return i;
}
/****************************************************************************/
WORD ExternalStatus(T_ComPortStruct *ComPortHandle)
{
WORD Status;
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
Status = inportb(ComPortHandle->IOAddress+SER_MODEM_STATUS);
return Status & 0x7fff;
}
/****************************************************************************/
WORD WriteModemControlRegister(T_ComPortStruct *ComPortHandle, WORD Status)
{
// Only writes to DTR and RTS lines
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
Status = ( Status & (RTS | DTR) ) |
( inportb(ComPortHandle->IOAddress+SER_MODEM_CTL) & ~(DTR | RTS) ) ;
outportb(ComPortHandle->IOAddress + SER_MODEM_CTL, Status );
return Status; // return the actual modem control word output
}
/****************************************************************************/
WORD FlushReadBuffer(T_ComPortStruct *ComPortHandle)
{
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
Disable();
/* reset FIFO pointers */
ComPortHandle-> ComInputPtr = ComPortHandle-> InputBuffer;
ComPortHandle-> PCInputPtr = ComPortHandle-> InputBuffer;
/* clear out the COM port */
inportb(ComPortHandle-> IOAddress + SER_RECEIVE);
Enable();
return 0;
}
/****************************************************************************/
WORD FlushWriteBuffer(T_ComPortStruct *ComPortHandle)
{
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
Disable();
/* reset FIFO pointers */
ComPortHandle-> ComOutputPtr = ComPortHandle-> OutputBuffer;
ComPortHandle-> PCOutputPtr = ComPortHandle-> OutputBuffer;
Enable();
return 0;
}
/****************************************************************************/
WORD ReadStatus(T_ComPortStruct *ComPortHandle)
{
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
return ComPortHandle->RcvByteCount;
}
/****************************************************************************/
LONG ReadErrors(T_ComPortStruct *ComPortHandle, LONG *Count)
// return a pointer to a LONG array with 3 elements :
// *ptr = # of OverRun errors accumulated
// *ptr+1 = # of Parity errors accumulated
// *ptr+2 = # of Framing errors accumulated
// *ptr+3 = # of bytes for missed characters
// all the error counts will be reset to zeroes after the read
{
LONG total=0;
WORD i;
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
CMovD( (LONG *)&(ComPortHandle->RcvErrors[0]),
(LONG *)&(ComPortHandle->RcvErrorsSent[0]),
4 );
/* ComPortHandle-> RcvErrorsSent[0] = ComPortHandle-> RcvErrors[0];
ComPortHandle-> RcvErrorsSent[1] = ComPortHandle-> RcvErrors[1];
ComPortHandle-> RcvErrorsSent[2] = ComPortHandle-> RcvErrors[2];
ComPortHandle-> RcvErrorsSent[3] = ComPortHandle-> RcvErrors[3];
*/
for (i=0; i<4; i++)
total += ComPortHandle->RcvErrors[i];
ComPortHandle-> RcvErrors[0] = 0;
ComPortHandle-> RcvErrors[1] = 0;
ComPortHandle-> RcvErrors[2] = 0;
ComPortHandle-> RcvErrors[3] = 0;
Count = (LONG *)&(ComPortHandle->RcvErrorsSent[0]);
return total;
}
/****************************************************************************/
WORD WriteStatus(T_ComPortStruct *ComPortHandle)
{
WORD WriteComplete;
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
WriteComplete = FALSE;
if (ComPortHandle-> PCOutputPtr == ComPortHandle-> ComOutputPtr)
WriteComplete = TRUE;
return(WriteComplete);
}
/****************************************************************************/
WORD SendBreak(T_ComPortStruct *ComPortHandle)
{
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
/* Dont try to send data during Break */
FlushWriteBuffer(ComPortHandle);
Disable();
outportb(ComPortHandle->IOAddress + SER_LINE_CTL,
(inportb(ComPortHandle->IOAddress + SER_LINE_CTL) | SEND_BREAK));
Enable();
return 0;
}
/****************************************************************************/
WORD ClearBreak(T_ComPortStruct *ComPortHandle)
{
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
/* Dont try to send data during Break */
Disable();
outportb( ComPortHandle->IOAddress + SER_LINE_CTL,
(inportb(ComPortHandle->IOAddress + SER_LINE_CTL) & ~SEND_BREAK));
Enable();
return 0;
}
/****************************************************************************/
WORD TestBreak(T_ComPortStruct *ComPortHandle)
{
WORD BreakState;
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
BreakState = 0;
/* Dont try to send data during Break */
Disable();
if (inportb(ComPortHandle->IOAddress + SER_LINE_STATUS) & BREAK_DETECT)
BreakState++;
Enable();
return BreakState;
}
/****************************************************************************/
//void interrupt _IntServiceSer1(void)
void _IntServiceSer1(void) // interrupt for COM1 port
{
T_ComPortStruct *ComPortHandle;
if ( ComPortListHead != NULL )
{
ComPortHandle = ComPortListHead;
for (; ComPortHandle != NULL; ComPortHandle = ComPortHandle->ComPortLink )
if ( ComPortHandle->ComPort == COM1PORT ) break;
if ( ComPortHandle != NULL )
SerialIntProcess(ComPortHandle);
}
outportb(INT_CTRL_PORT, END_OF_INT);
}
/****************************************************************************/
//void interrupt _IntServiceSer2(void)
void _IntServiceSer2(void) // interrupt for COM2 port
{
T_ComPortStruct *ComPortHandle;
if ( ComPortListHead != NULL )
{
ComPortHandle = ComPortListHead;
for (; ComPortHandle != NULL; ComPortHandle = ComPortHandle->ComPortLink )
if ( ComPortHandle->ComPort == COM2PORT ) break;
if ( ComPortHandle != NULL )
SerialIntProcess(ComPortHandle);
}
outportb(INT_CTRL_PORT, END_OF_INT);
}
/****************************************************************************/
void SerialIntProcess(T_ComPortStruct *ComPortHandle)
{
BYTE inByte, bytenotread;
char *NewInputPtr;
WORD error_mask;
error_mask = inportb(ComPortHandle-> IOAddress + SER_LINE_STATUS);
if ( error_mask & OVERRUN_ERROR )
ComPortHandle-> RcvErrors[0]++;
if ( error_mask & PARITY_ERROR )
ComPortHandle-> RcvErrors[1]++;
if ( error_mask & FRAMING_ERROR )
ComPortHandle-> RcvErrors[2]++;
// if ((inportb(ComPortHandle-> IOAddress + SER_LINE_STATUS)) & RECEIVE_READY)
if ( error_mask & RECEIVE_READY)
{
inByte = inportb(ComPortHandle-> IOAddress + SER_RECEIVE);
inByte &= CharacterMaskTable[ComPortHandle-> DataBits];
bytenotread = 1;
/* check if room in the FIFO */
if ( ComPortHandle->FlowControl &&
( ComPortHandle->RcvBufferSize - ComPortHandle->RcvByteCount <=
ComPortHandle->RTS_OFFthreshold ) ) // there is no room with HW
// handshaking
{
if ( ComPortHandle->RTS_ON == TRUE ) // should send xoff and RTS is on
{
WriteModemControlRegister ( ComPortHandle,
inportb(ComPortHandle->IOAddress+SER_MODEM_CTL) & ~RTS );
// Turn RTS off
ComPortHandle->RTS_ON = FALSE;
}
// RTS already off
}
// No flowcontrol or there is room
/* update FIFO pointer */
NewInputPtr = ComPortHandle-> ComInputPtr + 1;
if (NewInputPtr == ComPortHandle-> InputBuffer + ComPortHandle->RcvBufferSize )
NewInputPtr = ComPortHandle-> InputBuffer;
if (NewInputPtr != ComPortHandle->PCInputPtr)
{
ComPortHandle-> ComInputPtr[0] = inByte;
ComPortHandle-> ComInputPtr = NewInputPtr;
bytenotread = 0;
ComPortHandle-> RcvByteCount++;
}
ComPortHandle->RcvErrors[3] += bytenotread;
}
/* try to transmit character if its ready */
TransmitChar(ComPortHandle);
return;
}
/****************************************************************************/
void StartTransmit(T_ComPortStruct *ComPortHandle)
{
Disable();
/* if transmitter is not running start it */
if ((ComPortHandle-> EnableMask & (SER_TBRE_ENABLE | SER_MSR_ENABLE)) == 0)
// if ((ComPortHandle-> EnableMask & SER_TBRE_ENABLE ) == 0)
{
/* enable transmit buffer empty interrupts */
ComPortHandle-> EnableMask |= SER_TBRE_ENABLE;
outportb(ComPortHandle->IOAddress + SER_INT_ENABLE,
ComPortHandle-> EnableMask);
}
Enable();
return;
}
/****************************************************************************/
extern struct ScreenStruct *sID;
void TransmitChar(T_ComPortStruct *ComPortHandle)
{
char *NewOutput;
BYTE CurrentMask;
WORD msr;
CurrentMask = ComPortHandle-> EnableMask;
msr = inportb ( ComPortHandle-> IOAddress+SER_MODEM_STATUS ) & (CTS|DSR);
if ( ( ComPortHandle-> FlowControl == 0 ) || msr == (CTS|DSR) )
{
/* If data is buffered lets try to send it */
if (ComPortHandle-> ComOutputPtr != ComPortHandle-> PCOutputPtr)
{
/* make sure hardware can take character */
if (inportb(ComPortHandle->IOAddress + SER_LINE_STATUS) &
TRANSMIT_READY)
{
outportb(ComPortHandle-> IOAddress + SER_TRANSMIT,
ComPortHandle-> ComOutputPtr[0]);
NewOutput = ComPortHandle-> ComOutputPtr + 1;
if (NewOutput == ComPortHandle-> OutputBuffer +
ComPortHandle->XmitBufferSize )
NewOutput = ComPortHandle-> OutputBuffer;
ComPortHandle-> ComOutputPtr = NewOutput;
}
/* Send next character when Transmit buffer is empty */
ComPortHandle-> EnableMask &= ~SER_MSR_ENABLE;
ComPortHandle-> EnableMask |= SER_TBRE_ENABLE;
}
else
{
/* no more characters in FIFO, so turn off all interrupts */
ComPortHandle-> EnableMask &= ~(SER_TBRE_ENABLE | SER_MSR_ENABLE);
ComPortHandle-> EnableMask &= ~SER_TBRE_ENABLE;
}
}
else
{
/* cannot send due to hardware flow control so wait for status change*/
ComPortHandle-> EnableMask |= SER_MSR_ENABLE;
ComPortHandle-> EnableMask &= ~SER_TBRE_ENABLE;
}
/* if mask changed output mask to hardware */
if (CurrentMask != ComPortHandle-> EnableMask)
outportb(ComPortHandle->IOAddress + SER_INT_ENABLE,
ComPortHandle-> EnableMask);
return;
}
/****************************************************************************/
WORD Peek(pointer)
WORD *pointer;
{
return(((WORD *)MapAbsoluteAddressToDataOffset((LONG) pointer))[0]);
}
/****************************************************************************/
#pragma aux inportb = \
0xEC /* in al, dx */ \
parm [dx] \
value [al];
/****************************************************************************/
#pragma aux outportb = \
0xEE /* out dx, al */ \
parm [dx] [al];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -