📄 serialio.c
字号:
InterruptRTag->RTLink = RS232RTag->RTLink;
RS232RTag->RTLink = RS232RTag->RTModule->LDResourceList;
RS232RTag->RTModule->LDResourceList = RS232RTag;
Disable();
rc = SetHardwareInterrupt( p->IrqNumber,
irqRoutine[p->ComPort],
InterruptRTag, 0, 0, &eoi);
// rc=1 for invalid parms rc = 2 for interrupt not available
// and rc = 3 for out of memory
Enable();
if (rc != 0)
{
Free(p);
return rc;
}
else
{
p-> InputBuffer = (char *)Alloc( RCV_FIFO_LENGTH, NLMAllocRTag );
p-> OutputBuffer = (char *)Alloc( XMT_FIFO_LENGTH, NLMAllocRTag );
if ( p-> InputBuffer == NULL || p-> OutputBuffer == NULL )
{
Free(p);
return ERR_OUT_MEMORY;
}
p->ComPortLink = ComPortListHead;
ComPortListHead = p;
p-> EnableMask = 0;
p-> RS232IORTag = RS232RTag;
p-> ComStructID = ComStructSignature;
p-> MemAllocRTag = NLMAllocRTag;
/* initialize FIFO pointers */
p-> RcvErrors[0] = 0;
p-> RcvErrors[1] = 0;
p-> RcvErrors[2] = 0;
p-> RcvErrors[3] = 0;
p-> XmitBufferSize = XMT_FIFO_LENGTH;
p-> ComOutputPtr = p-> OutputBuffer;
p-> PCOutputPtr = p-> OutputBuffer;
p-> RcvBufferSize = RCV_FIFO_LENGTH;
p-> ComInputPtr = p-> InputBuffer;
p-> PCInputPtr = p-> InputBuffer;
p-> RcvByteCount = 0;
p-> RTS_OFFthreshold = HW_XOFF_THRESHOLD;
p-> FlowControl = TRUE;
p->RS232IORTag->RTResourceCount++;
p->InterruptRTag = InterruptRTag;
*ComPortHandle = (int)p;
return 0;
}
}
/****************************************************************************/
WORD InitSerialPort( T_ComPortStruct *ComPortHandle, BYTE UserBitRate,
BYTE UserDataBits, BYTE UserStopBits, BYTE UserParity,
BYTE UserFlowControl)
{
WORD rc;
WORD rate, id;
BYTE controlValue;
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
/* save settings in the Port Control Block */
ComPortHandle-> BitRate = UserBitRate;
ComPortHandle-> DataBits = UserDataBits;
ComPortHandle-> StopBits = UserStopBits;
ComPortHandle-> Parity = UserParity;
if ((rc = ValidateParameters( ComPortHandle )) == 0)
{
/* if BitRate is -1 don't change callers selected rate, data bits, etc */
if (ComPortHandle-> BitRate != -1)
{
ComPortHandle-> FlowControl = UserFlowControl;
/* translate Bit Rate */
rate = BitRateTable[ComPortHandle-> BitRate];
/* translate Data Bits */
controlValue = CharacterLengthTable[ComPortHandle-> DataBits];
/* translate Parity Bits */
controlValue |= ParityTable[ComPortHandle-> Parity];
/* translate Stop Bits */
controlValue |= StopBitTable[ComPortHandle-> StopBits];
/* output bit rate to the hardware */
outportb(ComPortHandle->IOAddress + SER_LINE_CTL, 0x80);
outportb(ComPortHandle->IOAddress + SER_BAUD_LSB, rate % 256);
outportb(ComPortHandle->IOAddress + SER_BAUD_MSB, rate / 256);
/* output parity, stop bits, character length to hardware */
outportb(ComPortHandle->IOAddress + SER_LINE_CTL, controlValue);
}
/* Setting Receive Data interrupts */
ComPortHandle-> EnableMask |= SER_DATA_ENABLE;
outportb(ComPortHandle->IOAddress + SER_INT_ENABLE,
ComPortHandle-> EnableMask);
outportb(ComPortHandle->IOAddress + SER_MODEM_CTL, OUT2 | RTS | DTR);
ComPortHandle->RTS_ON=TRUE;
/* Tell the interrupt controller to allow IRQ for serial port */
outportb(INT_MASK_PORT,
inportb(INT_MASK_PORT) & ~(1 << ComPortHandle->IrqNumber));
// Make sure no outstanding pending interrupts
id = inportb ( ComPortHandle-> IOAddress+SER_ID ) & NO_PENDING_INTR;
if ( !id ) // there is a pending interrupt
{
inportb ( ComPortHandle-> IOAddress+SER_MODEM_STATUS );
inportb ( ComPortHandle-> IOAddress+SER_LINE_STATUS );
inportb ( ComPortHandle-> IOAddress + SER_RECEIVE);
}
}
return (rc);
}
/****************************************************************************/
static WORD ValidateParameters( T_ComPortStruct *p)
{
WORD rc;
rc = 0;
if ((p-> BitRate >= MaxBitRateIndex) && (p-> BitRate != -1))
rc = ERR_INVALID_PARAMETER;
if (p-> DataBits >= MaxDataBitsIndex)
rc = ERR_INVALID_PARAMETER;
if (p-> StopBits >= MaxStopBitsIndex)
rc = ERR_INVALID_PARAMETER;
if (p-> Parity >= MaxParityIndex)
rc = ERR_INVALID_PARAMETER;
return rc;
}
/****************************************************************************/
WORD ReleasePort(T_ComPortStruct *ComPortHandle)
{
T_ComPortStruct *p1;
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
/* Disable Interrupts from serial chip */
Disable();
ComPortHandle-> EnableMask = 0;
outportb(ComPortHandle->IOAddress + SER_INT_ENABLE, ComPortHandle-> EnableMask);
outportb(ComPortHandle->IOAddress + SER_MODEM_CTL, 0x00);
/* Disable interrupt controller for this device */
outportb(INT_MASK_PORT,
inportb(INT_MASK_PORT) | (1 << ComPortHandle->IrqNumber));
/* Restore Interrupt Vector */
Disable();
ClearHardwareInterrupt(ComPortHandle->IrqNumber,
irqRoutine[ComPortHandle->ComPort] );
Enable();
ComPortHandle->RS232IORTag->RTResourceCount--;
// delink the current acquired port from list
if ( ComPortHandle == ComPortListHead )
ComPortListHead = ComPortHandle->ComPortLink;
else
{
p1 = ComPortListHead;
while (p1 != NULL)
{
if (p1->ComPortLink == ComPortHandle)
{
p1->ComPortLink = ComPortHandle->ComPortLink;
break;
}
else
p1 = p1->ComPortLink;
}
}
Free(ComPortHandle->InputBuffer);
Free(ComPortHandle->OutputBuffer);
Free(ComPortHandle);
return 0;
}
/***************************************************************************
SetReceiveBufferSize(T_ComPortStruct *ComPortHandle, WORD BufferSize)
Allocate a buffer of size BufferSize and copy the buffer pointer
into the structure PORT for COM port given by PortNumber. This
function will return an error code if it is called before
AcquireSerialPort(). The function will return the size of buffer
that has actually been allocated which may be different from
BufferSize.
***************************************************************************/
WORD SetReceiveBufferSize(T_ComPortStruct *ComPortHandle, WORD BufferSize)
{
char *tmp;
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
if ( BufferSize < BUFFER_MIN ) BufferSize = BUFFER_MIN;
if ( BufferSize > BUFFER_MAX ) BufferSize = BUFFER_MAX;
tmp = (char *)Alloc( BufferSize, ComPortHandle->MemAllocRTag );
if ( tmp != NULL ) // allocate ok, use new buffer
{
Free(ComPortHandle->InputBuffer);
ComPortHandle->InputBuffer = tmp;
}
else // cannot allocate, use old buffer
{
if ( BufferSize > ComPortHandle->RcvBufferSize )
BufferSize = ComPortHandle->RcvBufferSize;
// use old buffersize
}
ComPortHandle-> RcvBufferSize = BufferSize;
ComPortHandle-> ComInputPtr = ComPortHandle-> InputBuffer;
ComPortHandle-> PCInputPtr = ComPortHandle-> InputBuffer;
ComPortHandle-> RcvByteCount = 0;
return BufferSize;
}
WORD SetTransmitBufferSize(T_ComPortStruct *ComPortHandle, WORD BufferSize)
{
char *tmp;
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
if ( BufferSize < BUFFER_MIN ) BufferSize = BUFFER_MIN;
if ( BufferSize > BUFFER_MAX ) BufferSize = BUFFER_MAX;
tmp = (char *)Alloc( BufferSize, ComPortHandle->MemAllocRTag );
if ( tmp != NULL ) // allocate ok, use new buffer
{
Free(ComPortHandle->OutputBuffer);
ComPortHandle->OutputBuffer = tmp;
}
else // cannot allocate, use old buffer
{
if ( BufferSize > ComPortHandle->XmitBufferSize )
BufferSize = ComPortHandle->XmitBufferSize;
// use old buffersize
}
ComPortHandle-> XmitBufferSize = BufferSize;
ComPortHandle-> ComOutputPtr = ComPortHandle-> OutputBuffer;
ComPortHandle-> PCOutputPtr = ComPortHandle-> OutputBuffer;
return BufferSize;
}
/****************************************************************************/
/* returns Number of characters written */
/****************************************************************************/
WORD WriteData(T_ComPortStruct *ComPortHandle, char *Buffer, WORD Length)
{
char *NewPCOutput;
WORD i;
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
i = 0;
for ( ; i < Length; i++)
{
NewPCOutput = ComPortHandle-> PCOutputPtr + 1;
/* Make pointer circular */
if ( NewPCOutput == (ComPortHandle-> OutputBuffer) +
ComPortHandle->XmitBufferSize )
NewPCOutput = ComPortHandle-> OutputBuffer;
if (NewPCOutput == ComPortHandle-> ComOutputPtr)
break;
else
{
ComPortHandle-> PCOutputPtr[0] = Buffer[i];
ComPortHandle-> PCOutputPtr = NewPCOutput;
}
}
StartTransmit(ComPortHandle);
return i;
}
/*********)******************************************************************/
/* returns Number of read */
/****************************************************************************/
WORD ReadData(T_ComPortStruct *ComPortHandle, char *Buffer, WORD Length)
{
char *NewPCInput;
WORD i;
if ( ComPortListHead == NULL ||
ComPortHandle->ComStructID != ComStructSignature )
return ERR_BAD_HANDLE;
i = 0;
Disable();
if ( ComPortHandle->RcvByteCount == 0 ) return i;
Enable();
while( ComPortHandle-> PCInputPtr != ComPortHandle->ComInputPtr &&
i < Length && ComPortHandle->RcvByteCount > 0)
{
Buffer[i] = ComPortHandle-> PCInputPtr[0];
i++;
ComPortHandle->RcvByteCount--;
/* Update circular buffer Pointer */
NewPCInput = ComPortHandle-> PCInputPtr + 1;
if ( NewPCInput == (ComPortHandle-> InputBuffer) +
ComPortHandle->RcvBufferSize )
NewPCInput = ComPortHandle-> InputBuffer;
ComPortHandle-> PCInputPtr = NewPCInput;
if (ComPortHandle->FlowControl && ComPortHandle->RTS_ON == FALSE)
// Handware Handshake and RTS was off
{
if ( ComPortHandle->RcvBufferSize - ComPortHandle->RcvByteCount >
ComPortHandle->RTS_OFFthreshold ) // there is more room
{
WriteModemControlRegister ( ComPortHandle,
inportb(ComPortHandle->IOAddress+SER_MODEM_CTL) | RTS );
// Turn RTS on
ComPortHandle->RTS_ON=TRUE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -