📄 scif.c
字号:
*/
WRITE_REGISTER_USHORT(pHWHead->pSSR, READ_REGISTER_USHORT(pHWHead->pSSR) &
~(SCIF_SCSSR_RDF | SCIF_SCSSR_DR));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-GetBytes - len %d.\r\n"),
*pBufflen));
return RetVal;
}
/*****************************************************************************
* FUNCTION : SCIF_PutBytes
* DESCRIPTION : This routine inserts a stream of bytes onto the serial
* device (comport)
* INPUTS : The HW device info, the src string, number of bytes
* OUTPUTS : number of bytes actually sent
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
ULONG SCIF_PutBytes(
PVOID pHead, /* PVOID returned by SCIF_Init. */
PUCHAR pSrc, /* Pointer to bytes to be sent. */
ULONG NumberOfBytes, /* Number of bytes to be sent. */
PULONG pBytesSent) /* Pointer to actual number of bytes put. */
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
BYTE byteCount;
USHORT SSR;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+PutBytes - Len %d.\r\n"),
NumberOfBytes));
/* clear and txmit buffer full errors */
pHWHead->CommErrors &= ~CE_TXFULL;
// CTS flow control
if(pHWHead->dcb.fOutxCtsFlow) {
// check CTS just before transmission
ReadModemStatus(pHWHead);
if(!(pHWHead->ModemStatus & MS_CTS_ON)) {
DEBUGMSG(ZONE_WRITE|ZONE_FLOW, (TEXT("PutBytes: Flowed OFF via CTS\r\n")));
// start to check CTS periodically
pHWHead->CTSFlowOff = TRUE;
SetEvent(pHWHead->hModemLinePollingEvent);
// never let MDD callback here (which uses Sleep API), because it may cause dropping
// Tx interrupts which come in simultaneously.
return 0;
}
}
DEBUGMSG (ZONE_WRITE, (TEXT("PutBytes wait for CritSec %x.\r\n"),
&(pHWHead->TransmitCritSec)));
EnterCriticalSection(&(pHWHead->TransmitCritSec));
DEBUGMSG (ZONE_WRITE, (TEXT("PutBytes got CritSec %x.\r\n"),
&(pHWHead->TransmitCritSec)));
SSR = ReadStatus( pHWHead );
while (NumberOfBytes && (byteCount = (FIFO_SIZE - GET_SCFDR_TX_BYTES(*pHWHead->pFDR))))
{
DEBUGMSG (ZONE_WRITE | ZONE_THREAD,
(TEXT("Put Bytes - Writing (0x%x), NumberofBytes = %d, byteCount = %d\r\n"),
*pSrc, NumberOfBytes, byteCount));
WRITE_REGISTER_UCHAR(pHWHead->pFTDR, *pSrc);
++pSrc;
(*pBytesSent)++;
NumberOfBytes--;
}
/*
* Enable xmit intr. We need to do this no matter what,
* since the MDD relies on one final interrupt before
* returning to the application.
*/
WRITE_REGISTER_USHORT(pHWHead->pSCR, READ_REGISTER_USHORT(pHWHead->pSCR) |
SCIF_SCSCR_TIE);
LeaveCriticalSection(&(pHWHead->TransmitCritSec));
DEBUGMSG (ZONE_WRITE, (TEXT("PutBytes released CritSec %x.\r\n"),
&(pHWHead->TransmitCritSec)));
DEBUGMSG (ZONE_WRITE, (TEXT("-PutBytes - sent %d.\r\n"),
*pBytesSent));
return 0;
}
/*****************************************************************************
* FUNCTION : SCIF_TxIntr
* DESCRIPTION : This routine is called from the MDD whenever INTR_TX is
* returned by SCIF_GetInterruptType.
* INPUTS : pHead
* OUTPUTS : none
* DESIGN NOTES : This function is referred to as HWTxIntrHandler() by the MDD
* A transmit interrupt only occurs when someone is waiting to
* finish a transmit. So it is effectively a flush. So
* all we really do here is set the Flush event
* CAUTIONS :
*****************************************************************************/
VOID SCIF_TxIntr(
PVOID pHead) /* Hardware Head */
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
DEBUGMSG (ZONE_EVENTS,(TEXT("+SCIF_TxIntr 0x%X\r\n"), pHead));
/* Clear and disable the interrupt */
WRITE_REGISTER_USHORT(pHWHead->pSCR, READ_REGISTER_USHORT(pHWHead->pSCR)
& ~SCIF_SCSCR_TIE);
WRITE_REGISTER_USHORT(pHWHead->pSSR, READ_REGISTER_USHORT(pHWHead->pSSR)
& ~SCIF_SCSSR_TDFE);
pHWHead->CommCharInQueue = FALSE;
DEBUGMSG (ZONE_EVENTS,(TEXT("SCIF_TxIntr : Interrupt Cleared\r\n")));
/* Let the putbytes routine know he can continue */
PulseEvent(pHWHead->FlushDone);
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SCIF_TxIntr 0x%X\r\n"), pHead));
}
/*****************************************************************************
* FUNCTION : SCIF_LineIntr
* DESCRIPTION : This routine is called from the MDD whenever INTR_LINE is
* returned by SCIF_GetInterruptType.
* INPUTS : pHead
* OUTPUTS : none
* DESIGN NOTES : This function is referred to as HWClearLineIntr by the MDD.
* Since we are here because of an interrupt we need to modify
* to clear it.
* CAUTIONS :
*****************************************************************************/
VOID SCIF_LineIntr(
PVOID pHead) /* Hardware Head */
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SCIF_LineIntr 0x%X\r\n"), pHead));
ReadStatus( pHWHead );
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SCIF_LineIntr 0x%X\r\n"), pHead));
}
/*****************************************************************************
* FUNCTION : SCIF_OtherIntr
* DESCRIPTION : This routine is called from the MDD whenever INTR_MODEM
* is returned by SCIF_GetInterruptType.
* INPUTS : pHead
* OUTPUTS : none
* DESIGN NOTES : This function is referred to as HWClearOtherIntr by the MDD.
* all we do is see what has changed on the line. Since we
* are here because of an interrupt we need to modify
* the interrupt so that we will be able to detect the
* change in level of the DCD and CTS
* CAUTIONS :
*****************************************************************************/
VOID SCIF_OtherIntr(PVOID pHead)
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SCIF_OtherIntr 0x%X\r\n"), pHead));
ReadModemStatus( pHWHead );
/*
* If we are currently flowed off via CTS or DSR, then
* we better signal the TX thread when one of them changes
* so that TX can resume sending.
*/
// if ( pHWHead->DSRFlowOff && (!(pHWHead->SCPDR & SCPDR_DSR)))
// {
// DEBUGMSG (ZONE_WRITE|ZONE_FLOW,
// (TEXT("PutBytes, flowed on via DSR\n") ) );
// pHWHead->DSRFlowOff = FALSE;
/* DSR is set, so go ahead and resume sending */
/* Then simulate a TX intr to get things moving */
// pHWHead->AddTXIntr = TRUE;
// }
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SCIF_OtherIntr 0x%X\r\n"), pHead));
}
/*****************************************************************************
* FUNCTION : SCIF_GetStatus
* DESCRIPTION : This structure is called by the MDD to retrieve the
* contents of a COMSTAT structure.
* INPUTS : pHead
* OUTPUTS : none
* DESIGN NOTES : The return is a ULONG, representing success (0) or
* failure (-1).
* CAUTIONS : PDD sets fCtsHold, fDsrHold, fRLSDHold, and fTXim
*****************************************************************************/
ULONG SCIF_GetStatus(
PVOID pHead, /* PVOID returned by SCIF_Init. */
LPCOMSTAT lpStat) /* Pointer to LPCOMMSTAT to hold status. */
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
ULONG RetVal = pHWHead->CommErrors;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SCIF_GetStatus 0x%X\r\n"), pHead));
pHWHead->CommErrors = 0; /* Clear old errors each time */
if ( lpStat )
{
if (pHWHead->ModemStatus & MS_CTS_MASK)
pHWHead->Status.fCtsHold = 1;
else
pHWHead->Status.fCtsHold = 0;
if (pHWHead->ModemStatus & MS_RLSD_MASK)
pHWHead->Status.fRlsdHold = 1;
else
pHWHead->Status.fRlsdHold = 0;
if (pHWHead->DSRFlowOff)
pHWHead->Status.fDsrHold = 1;
else
pHWHead->Status.fDsrHold = 0;
if (pHWHead->CommCharInQueue)
pHWHead->Status.fTxim = TRUE;
else
pHWHead->Status.fTxim = FALSE;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SCIF_GetStatus : fCtsHold = %d\r\n"), pHWHead->Status.fCtsHold));
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SCIF_GetStatus : fDsrHold = %d\r\n"), pHWHead->Status.fDsrHold));
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SCIF_GetStatus : fTxim = %d\r\n"), pHWHead->Status.fTxim));
memcpy(lpStat, &(pHWHead->Status), sizeof(COMSTAT));
}
else
RetVal = (ULONG)-1;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SCIF_GetStatus 0x%X\r\n"), pHead));
return RetVal;
}
/*****************************************************************************
* FUNCTION : SCIF_Reset
* DESCRIPTION : Perform any operations associated with a device reset
* INPUTS : pHead
* OUTPUTS : none
* DESIGN NOTES : The only goal of this function is to reset the COMSTAT
* structure in our internal structure. This function is
* NEVER called by the MDD.
* CAUTIONS :
*****************************************************************************/
VOID SCIF_Reset(PVOID pHead)
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SCIF_Reset 0x%X\r\n"), pHead));
memset(&pHWHead->Status, 0, sizeof(COMSTAT));
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SCIF_Reset 0x%X\r\n"), pHead));
}
/*****************************************************************************
* FUNCTION : SCIF_GetStatus
* DESCRIPTION : Retrieves modem status.
* INPUTS : pHead
* OUTPUTS : none
* DESIGN NOTES : The easiest way to do this, but not necessaily the cleanest
* is to read the Interrupt register. If it is Rising Edge, then
* we know that the signal is at 0, if it is Falling Edge, then
* we know that the signal is at 1 (this is for CTS and DTR).
* Note that 0 is ON and 1 is OFF.
* CAUTIONS : But,because of the specification of INTC in SH4, we can't
* check the edges or status of IRQ signal.
* Now on investigation.
*****************************************************************************/
VOID SCIF_GetModemStatus(
PVOID pHead, /* PVOID returned by SCIF_Init. */
PULONG pModemStatus) /* PULONG passed in by user.*/
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SCIF_GetModemStatus 0x%X\r\n"), pHead));
ReadModemStatus( pHWHead );
*pModemStatus = pHWHead->ModemStatus;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("SCIF_GetModemStatus : ModemStatus = 0x%X\r\n"), *pModemStatus));
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SCIF_GetModemStatus 0x%X\r\n"), pHead));
return;
}
/*****************************************************************************
* FUNCTION : SCIF_PurgeComm
* DESCRIPTION : Purge Rx and/or Tx. Empty FIFO.
* INPUTS : The pointer to the hardware struct and action to take
* OUTPUTS : N/A
* DESIGN NOTES :
* CAUTIONS :
*****************************************************************************/
VOID SCIF_PurgeComm(
PVOID pHead, /* PVOID returned by SCIF_Init. */
DWORD fdwAction) /* @parm Action to take. */
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
WORD FCR; /* Old FCR info */
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SCIF_PurgeComm 0x%X\r\n"), pHead));
/*
* Notes from MS ---
* 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. for
* now, if it is ABORT we will dump all of the data by resetting the FIFO
* no difference between ABORT and CLEAR. There is not going to be an
* easy way to do an abort. we cannot clear the regs beyond resetting the
* fifo. So reseting the FIFO is the closest we can come to aborting
* a transmission, and unless they de-init, we will keep getting data
*/
FCR = READ_REGISTER_USHORT(pHWHead->pFCR);
if ( (fdwAction & PURGE_TXCLEAR) || (fdwAction & PURGE_TXABORT) )
{
WRITE_REGISTER_USHORT(pHWHead->pFCR, READ_REGISTER_USHORT(pHWHead->pFCR)
| SCIF_SCFCR_TFRST);
WRITE_REGISTER_USHORT(pHWHead->pFCR, FCR);
}
if ( (fdwAction & PURGE_RXCLEAR) && (fdwAction & PURGE_RXABORT))
{
WRITE_REGISTER_USHORT(pHWHead->pFCR, READ_REGISTER_USHORT(pHWHead->pFCR)
| SCIF_SCFCR_RFRST);
WRITE_REGISTER_USHORT(pHWHead->pFCR, FCR);
}
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SCIF_PurgeComm 0x%X\r\n"), pHead));
return;
}
/*****************************************************************************
* FUNCTION : SCIF_XmitComChar
* DESCRIPTION : Transmit a char immediately
* INPUTS : The pointer to the hardware struct and the char to send
* OUTPUTS : N/A
* DESIGN NOTES : This code waits for the char to transmitted
* CAUTIONS :
*****************************************************************************/
BOOL SCIF_XmitComChar(
PVOID pHead, /* PVOID returned by SCIF_Init.*/
UCHAR ComChar) /* Character to transmit. */
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SCIF_XmitComChar 0x%X\r\n"), pHead));
/* We know Tx FIFO will eventually empty */
while( TRUE ){
/* Get critical section, then transmit when buffer empties */
DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar wait for CritSec %x.\r\n"),
&(pHWHead->TransmitCritSec)));
DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar got CritSec %x.\r\n"),
&(pHWHead->TransmitCritSec)));
EnterCriticalSection(&(pHWHead->TransmitCritSec));
// FIFO Full ? 2002.11.28
if( GET_SCFDR_TX_BYTES(*pHWHead->pFDR)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -