📄 serio.c
字号:
PPERP_IO_SER_INFO pHWHead = (PPERP_IO_SER_INFO)pHead;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWXmitComChar\r\n")));
while( TRUE ){ // We know THR will eventually empty
// Enable xmit intr.
ENABLE_BITS8(ASICSiuRegs.siuie, SERIAL_IER_RDA | SERIAL_IER_RLS
| SERIAL_IER_MS | SERIAL_IER_THR);
// Wait until the txintr has signalled.
// WaitForSingleObject(pHWHead->FlushDone, (ULONG)-1);
WaitForSingleObject(pHWHead->FlushDone, 1000);
// Write the character if we can
HWReadLSR( pHWHead );
if( pHWHead->LSR & SERIAL_LSR_THRE ){
REG8(ASICSiuRegs.siurb_th) = ComChar;
break;
}
}
return TRUE;
}
//***********************************************************************
// @doc OEM
// @func ULONG | HWGetStatus | Hardware status api.
// *
// @rdesc The return is a ULONG, representing success (0) or failure (-1).
// * See Win32 documentation for ClearCommError for description of lpStat.
//***********************************************************************
ULONG
HWGetStatus(
PVOID pHead, /* @parm PVOID returned by HWInit. */
LPCOMSTAT lpStat /* @parm Pointer to LPCOMMSTAT to hold status.*/
)
{
PPERP_IO_SER_INFO pHWHead = (PPERP_IO_SER_INFO)pHead;
ULONG RetVal = pHWHead->CommErrors;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWGetStatus\r\n")));
pHWHead->CommErrors = 0; // Clear old errors each time
if ( lpStat ){
if (pHWHead->CTSFlowOff){
pHWHead->Status.fCtsHold = 1;
}
else{
pHWHead->Status.fCtsHold = 0;
}
if (pHWHead->DSRFlowOff){
pHWHead->Status.fDsrHold = 1;
}
else{
pHWHead->Status.fDsrHold = 0;
}
pHWHead->Status.cbInQue = 0;
pHWHead->Status.cbOutQue = 0;
memcpy(lpStat, &(pHWHead->Status), sizeof(COMSTAT));
}
else{
RetVal = (ULONG)-1;
}
return RetVal;
}
// ******************************************************************
// @doc OEM
// @func ULONG | HWReset | Hardware reset api.
// *
// @rdesc This routine resets the COMSTAT status used by HWGetStatus.
// ******************************************************************
VOID
HWReset(
PVOID pHead /* @parm PVOID returned by HWInit. */
)
{
PPERP_IO_SER_INFO pHWHead = (PPERP_IO_SER_INFO)pHead;
USHORT divisor = 120;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWReset\r\n")));
// No longer called by MDD, just waiting to be removed from vtbl
if(pHWHead->PortOpen){
DEBUGMSG(ZONE_FUNCTION, (TEXT("Not Reset PortOpen Error!!\r\n")));
return;
}
ENABLE_BITS8(ASICSiuRegs.siulc, SERIAL_LCR_DLAB);
REG8(ASICSiuRegs.siurb_th) = (divisor & 0xff);
REG8(ASICSiuRegs.siuie) = ((divisor >> 8) & 0xff);
ENABLE_BITS8(ASICSiuRegs.siureset, SRESET);
Sleep(20);
DISABLE_BITS8(ASICSiuRegs.siureset, SRESET);
DISABLE_BITS8(ASICSiuRegs.siulc, SERIAL_LCR_DLAB);
}
// ********************************************************
// @doc OEM
// @func VOID | HWGetModemStatus | Retrieves modem status.
// *
// @rdesc See Win32 document for GetCommModemStatus.
// ********************************************************
VOID
HWGetModemStatus(
PVOID pHead, /* @parm PVOID returned by HWInit. */
PULONG pModemStatus /* @parm PULONG passed in by user. */
)
{
PPERP_IO_SER_INFO pHWHead = (PPERP_IO_SER_INFO)pHead;
UCHAR ubModemStatus;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWGetModemStatus\r\n")));
pHWHead->MSR = *((volatile UCHAR *)ASICSiuRegs.siums);
ubModemStatus = pHWHead->MSR;
if ( ubModemStatus & SERIAL_MSR_CTS ){
*pModemStatus |= MS_CTS_ON;
}
if ( ubModemStatus & SERIAL_MSR_DSR ){
*pModemStatus |= MS_DSR_ON;
}
if ( ubModemStatus & SERIAL_MSR_RI ){
*pModemStatus |= MS_RING_ON;
}
if (!(REG16(VRGiuRegs.giupiod) & DCDINTR)) {
*pModemStatus |= MS_RLSD_ON;
}
return;
}
// ***************************************************************
// @doc OEM
// @func VOID | HWGetCommProperties | Retrieves Comm Properties.
// *
// @rdesc None.
// ***************************************************************
VOID
HWGetCommProperties(
PVOID pHead, /* @parm PVOID returned by HWInit. */
LPCOMMPROP pCommProp /* @parm Pointer to receive COMMPROP structure. */
)
{
PPERP_IO_SER_INFO pHWHead = (PPERP_IO_SER_INFO)pHead;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWGetCommProperties\r\n")));
memcpy(pCommProp, &(pHWHead->CommProp), sizeof(COMMPROP));
return;
}
// ***********************************************************************
// @doc OEM
// @func VOID | HWPurgeComm | Purges comm device according to Win32 spec for
// * PURGE_TXABORT, PURGE_RXABORT, PURGE_TXCLEAR, PURGE_RXCLEAR (see
// * PurgeComm in the Win32 spec).
// *
// @rdesc None.
// ***********************************************************************
VOID
HWPurgeComm(
PVOID pHead, /* @parm PVOID returned by HWInit. */
DWORD fdwAction /* @parm Action to take. */
)
{
PPERP_IO_SER_INFO pHWHead = (PPERP_IO_SER_INFO)pHead;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWPurgeComm\r\n")));
if (fdwAction & PURGE_TXABORT){
DISABLE_BITS8(ASICSiuRegs.siuie, SERIAL_IER_THR);
}
// REVIEW THIS - I don't see how this could have terminated a pending read,
// nor how RX interrupts would ever get turned back on. I suspect that
// RXABORT and TXABORT would both be better implemented inthe MDD.
// if ( fdwAction & PURGE_RXABORT ) {
// DISABLE_BITS8(ASICSiuRegs.siuie, SERIAL_IER_RDA );
// }
if ( fdwAction & PURGE_TXCLEAR ){
ENABLE_BITS8(ASICSiuRegs.siuiid_fc, SERIAL_FCR_TXMT_RESET);
REG8(ASICSiuRegs.siuiid_fc) = pHWHead->FCR;
}
if ( fdwAction & PURGE_RXCLEAR ){
ENABLE_BITS8(ASICSiuRegs.siuiid_fc, SERIAL_FCR_RCVR_RESET);
REG8(ASICSiuRegs.siuiid_fc) = pHWHead->FCR;
}
return;
}
// ****************************************************************
//
// @doc OEM
//
// @func BOOL | HWSetDCB | Set the Device Control Block
//
// @parm PVOID | pHead | PDD Device Context
// @parm LPDCB | pDCB | The device control block to set
//
// @rdesc Returns TRUE for success, FALSE for failure. If an error
// occurs the caller can return the error using GetLastError()
//
// @remark This function is called by the MDD after the user has called
// the Win32 API SetCommState().
// *******************************************************************
BOOL
HWSetDCB(
PVOID pHead,
LPDCB pDCB
)
{
PPERP_IO_SER_INFO pHWHead = (PPERP_IO_SER_INFO)pHead;
BOOL RetVal = TRUE;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWSetDCB\r\n")));
EnterCriticalSection( &(pHWHead->CS));
// If the device is open, scan for changes and do whatever
// is needed for the changed fields. if the device isn't
// open yet, just save the DCB for later use by the open.
if( pHWHead->PortOpen ){
// Note, fparity just says whether we should check
// receive parity. And the 16550 won't let us NOT
// check parity if we generate it. So this field
// has no effect on the hardware.
if( pDCB->BaudRate != pHWHead->dcb.BaudRate ){
HWSetBaudRate( pHWHead, pDCB->BaudRate );
}
if( pDCB->ByteSize != pHWHead->dcb.ByteSize ){
HWSetByteSize( pHWHead, pDCB->ByteSize );
}
if( pDCB->Parity != pHWHead->dcb.Parity ){
HWSetParity( pHWHead, pDCB->Parity );
}
if( pDCB->StopBits != pHWHead->dcb.StopBits ){
HWSetStopBits( pHWHead, pDCB->StopBits );
}
}
// Now that we have done the right thing, store this DCB
pHWHead->dcb = *pDCB;
LeaveCriticalSection(&(pHWHead->CS));
return RetVal;
}
// ****************************************************************
//
// @doc OEM
//
// @func BOOL | HWSetCommTimeouts | Set the communications timeouts
//
// @parm PVOID | pHead | PDD device context (returned from HWInit())
// @parm LPCOMMTIMEOUTS | lpCommTO | The CommTimeouts structure
//
// @rdesc Return TRUE if successful, FALSE if any error occurs.
//
// @remark If the PDD needs to keep track of the CommTimeouts that
// the user has specified then this should be stashed away
// for later use. In general it is recommended that PDD's
// allow the MDD layer to manage the timeouts.
// *****************************************************************
BOOL
HWSetCommTimeouts(
PVOID pHead,
LPCOMMTIMEOUTS lpCommTO
)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWSetCommTimeouts\r\n")));
return TRUE;
}
// **********************************************************************
// @doc OEM
// @func BOOL | HWIoctl | Device IO control routine.
// @parm DWORD | dwOpenData | value returned from COM_Open call
// @parm DWORD | dwCode | io control code to be performed
// @parm PBYTE | pBufIn | input data to the device
// @parm DWORD | dwLenIn | number of bytes being passed in
// @parm PBYTE | pBufOut | output data from the device
// @parm DWORD | dwLenOut |maximum number of bytes to receive from device
// @parm PDWORD | pdwActualOut | actual number of bytes received from device
//
// @rdesc Returns TRUE for success, FALSE for failure
//
// @remark The MDD will pass any unrecognized IOCTLs through to this function.
//************************************************************************
BOOL
HWIoctl(PVOID pHead,DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn,
PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut)
{
BOOL RetVal = TRUE;
DEBUGMSG(ZONE_FUNCTION, (TEXT("Serial PDD: Enter HWIoctl\r\n")));
switch (dwCode) {
// Currently, no defined IOCTLs
default:
RetVal = FALSE;
break;
}
return RetVal;
}
const
HW_VTBL PerpIoVTbl = {
HWInit,
HWDeinit,
HWOpen,
HWClose,
HWGetBytes,
HWGetRxStart,
HWGetIntrType,
HWClearOtherIntr,
HWClearLineIntr,
HWGetRxBufferSize,
HWTxIntrHandler,
HWPutBytes,
HWPowerOff,
HWPowerOn,
HWClearDTR,
HWSetDTR,
HWClearRTS,
HWSetRTS,
HWEnableIR,
HWDisableIR,
HWClearBreak,
HWSetBreak,
HWXmitComChar,
HWGetStatus,
HWReset,
HWGetModemStatus,
HWGetCommProperties,
HWPurgeComm,
HWSetDCB,
HWSetCommTimeouts,
HWIoctl
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -