📄 scif0.c
字号:
//
// @rdesc This routine returns a bitmask indicating which interrupts
// are currently pending.
//
INTERRUPT_TYPE
SCIF0GetInterruptType(
PVOID pHead // Pointer to hardware head
)
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
PDMA_INFO pTxDma = pHWHead -> pTxDma;
PDMA_INFO pRxDma = pHWHead -> pRxDma;
INTERRUPT_TYPE interrupts;
USHORT FSR;
USHORT LSR;
DEBUGMSG (ZONE_THREAD,
(TEXT("+SerGetInterruptType 0x%X\r\n"), pHead));
try
{
FSR = READ_REGISTER_USHORT(pHWHead -> pFSR);
LSR = READ_REGISTER_USHORT(pHWHead -> pLSR);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
FSR = 0;
LSR = 0;
}
// Clear InterruptType
interrupts = INTR_NONE;
// Check ErrorFlag
if ( LSR & SCIF_LSR_ORER ||
// FSR & (SCIF_SSR_BRK|SCIF_SSR_FER|SCIF_SSR_PER) ){
FSR & (SCIF_SSR_ER|SCIF_SSR_BRK|SCIF_SSR_FER|SCIF_SSR_PER) ){
DEBUGMSG(ZONE_THREAD,(TEXT("ERROR - FSR : 0x%x LSR : 0x%x\r\n"),FSR,LSR));
interrupts = INTR_LINE;
}else if ( LSR & SCIF_LSR_TO ){
interrupts = INTR_RX;
// DEBUGMSG(ZONE_THREAD,(TEXT("SCIF Receive timeout FSR[%04x] LSR[%04x]\r\n"),FSR,LSR));
// WRITE_REGISTER_USHORT(pHWHead -> pLSR,
// READ_REGISTER_USHORT(pHWHead -> pLSR) & ~(SCIF_LSR_TO));
// DMA Transfer complate (Receive)
}else if (*(pRxDma -> pvDINTSR) & (0x00000001 << (pRxDma -> Ch))){
interrupts = INTR_RX;
WRITE_REGISTER_ULONG(pRxDma -> pvDINTCR, 0x00000001 << (pRxDma -> Ch));
// DMA Transfer complate (Transmit)
}else if (*(pTxDma -> pvDINTSR) & (0x00000001 << (pTxDma -> Ch))){
interrupts = INTR_TX;
WRITE_REGISTER_ULONG(pTxDma -> pvDINTCR, 0x00000001 << (pTxDma -> Ch));
SetEvent(pHWHead->FlushDone);
}
if (pHWHead->AddTXIntr) {
interrupts |= INTR_TX;
pHWHead->AddTXIntr = FALSE;
}
DEBUGMSG (ZONE_THREAD,
(TEXT("-SerGetInterruptType 0x%X, 0x%X\r\n"),
pHead, interrupts));
return interrupts;
}
#pragma optimize("", off)
//
// @doc OEM
// @func ULONG | SerTXIntr | This routine is called from the new MDD
// whenever INTR_TX is returned by SerGetInterruptType. It is responsible
// for loading up the TX FIFO with next block of data.
//
// @rdesc None
//
VOID
SCIF0TxIntr(
PVOID pHead, // Hardware Head
PUCHAR pTxBuffer, // @parm Pointer to receive buffer
ULONG *pBuffLen // @parm In = max bytes to transmit, out = bytes transmitted
)
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
DWORD byteCount, transCount;
DWORD dcr_value;
USHORT SPTR;
UCHAR dmy;
DEBUGMSG (ZONE_WRITE, (TEXT("+PutBytes - sent %d.\r\n"),
*pBuffLen));
if( *pBuffLen == 0 ){
return;
}
// If CTS flow control is desired, check cts. If clear, don't send,
// but loop. When CTS comes back on, the OtherInt routine will
// detect this and re-enable TX interrupts (causing Flushdone).
// For finest granularity, we would check this in the loop below,
// but for speed, I check it here (up to 8 xmit characters before
// we actually flow off.
if ( pHWHead->dcb.fOutxCtsFlow )
{
SPTR = ReadModemStatus( pHWHead );
// We don't need to explicitly read the MSR, since we always enable
// IER_MS, which ensures that we will get an interrupt and read
// the MSR whenever CTS, DSR, TERI, or DCD change.
if(! (pHWHead->SPTR & SCIF_SPTR_CTS) )
{
DEBUGMSG (ZONE_WRITE|ZONE_FLOW,
(TEXT("PutBytes, flowed off via CTS\n") ) );
pHWHead->CTSFlowOff = TRUE; // Record flowed off state
WRITE_REGISTER_USHORT(pHWHead -> pSCR, READ_REGISTER_USHORT(pHWHead -> pSCR) & ~SCIF_SCR_TIE);
// disable TX interrupts shile flowed off
// We could return a positive value here, which would
// cause the MDD to periodically check the flow control
// status. However, we don't need to since we know that
// the DCTS interrupt will cause the MDD to call us, and we
// will subsequently fake a TX interrupt to the MDD, causing
// him to call back into PutBytes.
*pBuffLen = 0;
return;
}
}
EnterCriticalSection(&(pHWHead->TransmitCritSec));
if ( SCIF0_TXBUFFER_SIZE < *pBuffLen ){
byteCount = SCIF0_TXBUFFER_SIZE;
}else{
byteCount = *pBuffLen;
}
DEBUGMSG (ZONE_WRITE | ZONE_THREAD,
(TEXT("Put Bytes - Write max of %d bytes\r\n"),
byteCount));
*pBuffLen = 0;
for( transCount = 0; byteCount; byteCount-- ){
*(pHWHead -> pTxBuff + (transCount++)) = *(pTxBuffer++);
(*pBuffLen)++;
}
dmy = *(pHWHead -> pTxBuff + transCount - 1); // Coherency measures
// WRITE_REGISTER_USHORT(pHWHead -> pSCR, READ_REGISTER_USHORT(pHWHead -> pSCR) & ~SCIF_SCR_TE);
dcr_value = DCR_DPDS_8BIT |
DCR_DDRMD_MODULE |
DCR_DPDAM_FIX |
DCR_DMDL_PERIPHERAL |
DCR_SPDS_8BIT |
DCR_SDRMD_MODULE |
DCR_SPDAM_FIX |
DCR_SMDL_MEMORY |
DCR_DIP_1PAGE |
DCR_ACMD_DISABLE |
DCR_CT_DISABLE |
DCR_PKMD_DISABLE |
DCR_BTMD_ENABLE |
DCR_DTAU_BYTE |
DCR_DTAC_DISABLE ;
try {
dma_SetPage(pHWHead -> pTxDma, 0, SCIF0_TX_BUFFER_BASE, SCIF0_REGBASE + SCIF_SCFTDR_OFFSET, (ULONG)transCount);
dma_SetPort(pHWHead -> pTxDma, DPTR_DDPT_SCIF0);
dma_SetControl(pHWHead -> pTxDma, dcr_value);
dma_SetCommand(pHWHead -> pTxDma, DCMDR_DMEN);
dma_InterruptEnable(pHWHead -> pTxDma);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
}
LeaveCriticalSection(&(pHWHead->TransmitCritSec));
DEBUGMSG (ZONE_WRITE, (TEXT("-PutBytes - sent %d.\r\n"),
*pBuffLen));
return;
}
#pragma optimize("", on)
//
// @doc OEM
// @func ULONG | SCIF0_OtherIntr | This routine is called from the MDD
// whenever INTR_MODEM is returned by SCIF_GetInterruptType.
//
// @rdesc None
//
VOID
SCIF0OtherIntr(
PVOID pHead // Hardware Head
)
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
USHORT MSR;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SCIF0OtherIntr 0x%X\r\n"), pHead));
MSR = (USHORT)ReadModemStatus( pHWHead );
try
{
if ( pHWHead -> CTSFlowOff && (MSR & SCIF_SPTR_CTS) ){
pHWHead -> CTSFlowOff = FALSE;
WRITE_REGISTER_USHORT(pHWHead -> pSCR, READ_REGISTER_USHORT(pHWHead -> pSCR) | SCIF_SCR_TIE);
pHWHead -> AddTXIntr = TRUE;
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
DEBUGMSG (0,
(TEXT("-SCIF0OtherIntr 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func ULONG | SL_OtherIntr | This routine is called from the MDD
// whenever INTR_MODEM is returned by SL_GetInterruptType.
//
// @rdesc None
//
VOID
SCIF0ModemIntr(
PVOID pHead // Hardware Head
)
{
SCIF0OtherIntr(pHead);
}
//
// @doc OEM
// @func ULONG | SerGetStatus | This structure is called by the MDD
// to retrieve the contents of a COMSTAT structure.
//
// @rdesc The return is a ULONG, representing success (0) or failure (-1).
//
ULONG
SCIF0GetStatus(
PVOID pHead, // @parm PVOID returned by HWInit.
LPCOMSTAT lpStat // Pointer to LPCOMMSTAT to hold status.
)
{
PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
ULONG RetVal = pHWHead->CommErrors;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SCIF0GetStatus 0x%X\r\n"), pHead));
pHWHead->CommErrors = 0; // Clear old errors each time
if ( lpStat )
{
if ( pHWHead -> CTSFlowOff )
pHWHead -> Status.fCtsHold = 1;
else
pHWHead -> Status.fCtsHold = 0;
if ( pHWHead -> CommCharInQueue )
pHWHead -> Status.fTxim = TRUE;
else
pHWHead -> Status.fTxim = FALSE;
memcpy(lpStat, &(pHWHead->Status), sizeof(COMSTAT));
}
else
RetVal = (ULONG)-1;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SCIF0GetStatus 0x%X\r\n"), pHead));
return RetVal;
}
/*
@doc OEM
@func BOOL | SCIF_EnableIR | This routine enables ir.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
BOOL
SCIF0EnableIR(
PVOID pHead, // @parm PVOID returned by HWinit.
ULONG BaudRate // @parm ULONG baudrate.
)
{
return FALSE;
}
/*
@doc OEM
@func BOOL | SCIF_DisableIR | This routine disable the ir.
* Not exported to users, only to driver.
*
@rdesc Returns TRUE if successful, FALSEotherwise.
*/
BOOL
SCIF0DisableIR(
PVOID pHead /*@parm PVOID returned by HWinit. */
)
{
return FALSE;
}
const
HW_VTBL SCIF0IoVTbl = {
SCIF0Init,
SCIF_PostInit,
SCIF_Deinit,
SCIF0Open,
SCIF_Close,
SCIF0GetInterruptType,
SCIF_RxIntr,
SCIF0TxIntr,
SCIF0ModemIntr,
SCIF_LineIntr,
SCIF_GetRxBufferSize,
SCIF_PowerOff,
SCIF_PowerOn,
SCIF_ClearDTR,
SCIF_SetDTR,
SCIF0ClearRTS,
SCIF0SetRTS,
SCIF0EnableIR,
SCIF0DisableIR,
SCIF_ClearBreak,
SCIF_SetBreak,
SCIF_XmitComChar,
SCIF0GetStatus,
SCIF_Reset,
SCIF_GetModemStatus,
SCIF_GetCommProperties,
SCIF_PurgeComm,
SCIF_SetDCB,
SCIF_SetCommTimeouts,
SCIF_Ioctl};
PHWOBJ
GetSerialObject(
DWORD DeviceArrayIndex
)
{
PHWOBJ pSerObj;
// We do not have a statically allocated array of HWObjs. Instead, we
// allocate a new HWObj for each instance of the driver. The MDD will
// always call GetSerialObj/HWInit/HWDeinit in that order, so we can do
// the alloc here and do any subsequent free in HWDeInit.
// Allocate space for the HWOBJ.
pSerObj = (PHWOBJ)LocalAlloc( LPTR, sizeof(HWOBJ) );
if ( !pSerObj )
return (NULL);
// Fill in the HWObj structure that we just allocated.
if( DeviceArrayIndex == 0 ){
pSerObj->BindFlags = THREAD_AT_INIT; // Have MDD create thread when device is first opened.
// pSerObj->BindFlags = THREAD_IN_PDD; // We take care of our own IST
pSerObj->dwIntID = SYSINTR_SCIF0; // SysIntr is filled in at init time
pSerObj->pFuncTbl = (HW_VTBL *) &SCIF0IoVTbl; // Return pointer to appropriate functions
}
else{
pSerObj->BindFlags = THREAD_AT_INIT; // Have MDD create thread when device is first opened.
// pSerObj->BindFlags = THREAD_IN_PDD; // We take care of our own IST
pSerObj->dwIntID = SYSINTR_IR; // SysIntr is filled in at init time
pSerObj->pFuncTbl = (HW_VTBL *) &SCIF3IoVTbl; // Return pointer to appropriate functions
}
// Now return this structure to the MDD.
return (pSerObj);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -