📄 sir.cpp
字号:
// Parameters:
// thisDev
// [in] pFirDevice_t.
//
// Returns:
// This function returns the actually baudrate set.
//
//-----------------------------------------------------------------------------
baudRates SirSetSpeed(pFirDevice_t thisDev)
{
baudRates rate = BAUDRATE_INVALID;
ULONG bRefFreq = UART_REF_FREQ;
ULONG speed = thisDev->newSpeed;
ULONG baudrate = speed;
if (speed <= MAX_SIR_SPEED)
{
for (int i=0; i<NUM_BAUDRATES; i++)
{
if (speed == supportedBaudRateTable[i].bitsPerSec)
{
rate = supportedBaudRateTable[i].tableIndex;
break;
}
}
// Check whether IR special case is needed.
if (speed < IRSC_BAUDRATE)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("Sir: SIR special case!")));
CSP_BITFINS(g_pVSIRReg->UCR4, UART_UCR4_IRSC, UART_UCR4_IRSC_SAMPCLK);
CSP_BITFINS(g_pVSIRReg->UCR2, UART_UCR2_SRST, UART_UCR2_SRST_RESET);
CSP_BITFINS(g_pVSIRReg->UCR4, UART_UCR4_IRSC, UART_UCR4_IRSC_REFCLK);
}
else
{
CSP_BITFINS(g_pVSIRReg->UCR4, UART_UCR4_IRSC, UART_UCR4_IRSC_SAMPCLK);
CSP_BITFINS(g_pVSIRReg->UCR2, UART_UCR2_SRST, UART_UCR2_SRST_RESET);
for (UINT i=0; i<4; i++);
CSP_BITFINS(g_pVSIRReg->UCR4, UART_UCR4_IRSC, UART_UCR4_IRSC_SAMPCLK);
}
CSP_BITFINS(g_pVSIRReg->UFCR, UART_UFCR_RFDIV, RFDIV_VALUE(BSPUartCalRFDIV(&bRefFreq)));
g_pVSIRReg->UBIR = UART_UBIR_INCREMENT(speed, UART_UBMR_MOD_DEFAULT, bRefFreq)-1;
g_pVSIRReg->UBMR = UART_UBMR_MOD_DEFAULT -1;
NdisStallExecution(5000); // delay
}
else
DEBUGMSG(ZONE_FUNCTION, (TEXT("Sir: SirSetSpeed, unsupported bitsPerSec: %d, NOT SIR\r\n"), speed));
DEBUGMSG(ZONE_FUNCTION, (TEXT("Sir: -SirSetSpeed\r\n")));
return rate;
}
//-----------------------------------------------------------------------------
//
// Function: SirClearInterruptStatus
//
// This function is to clear the interrupts status on UART22.
//
// Parameters:
// None.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
VOID SirClearInterruptStatus(VOID)
{
// We don't use error interrupt, therefore all status bits
// will be automatically cleared.
return;
}
//-----------------------------------------------------------------------------
//
// Function: SirEnableInterrupt
//
// This function is to enable the interrupts from UART2 module.
//
// Parameters:
// thisDev
// [in] .
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
VOID SirEnableInterrupt(pFirDevice_t thisDev)
{
if (thisDev->writePending)
{
CSP_BITFINS(g_pVSIRReg->UCR1, UART_UCR1_TXMPTYEN, UART_UCR1_TXMPTYEN_ENABLE); // Transmitter FIFO empty interrupt
}
else
{
CSP_BITFINS(g_pVSIRReg->UCR4, UART_UCR4_DREN, UART_UCR4_DREN_ENABLE); // Receive data Ready Interrupt
}
}
//-----------------------------------------------------------------------------
//
// Function: SirDisableInterrupt
//
// This function is to disable the interrupts from UART2 module.
//
// Parameters:
// thisDev
// [in] .
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
VOID SirDisableInterrupt(pFirDevice_t thisDev)
{
CSP_BITFINS(g_pVSIRReg->UCR1, UART_UCR1_TXMPTYEN, UART_UCR1_TXMPTYEN_DISABLE);
CSP_BITFINS(g_pVSIRReg->UCR4, UART_UCR4_DREN, UART_UCR4_DREN_DISABLE);
}
//-----------------------------------------------------------------------------
//
// Function: SirInitialize
//
// This function initializes the Sir device.
//
// Parameters:
// thisDev
// [in] pFirDevice_t.
//
// Returns:
// This function returns initialization status.
//
//-----------------------------------------------------------------------------
BOOLEAN SirInitialize(pFirDevice_t thisDev)
{
PHYSICAL_ADDRESS Addr = {thisDev->SirPhyAddr, 0};
DEVICE_LOCATION devLoc;
DEBUGMSG(ZONE_INIT, (TEXT("Sir: +SirInitialize\r\n")));
// read from registry?
// Map peripheral physical address to virtual address
if(g_pVSIRReg == NULL)
{
g_pVSIRReg = (PCSP_UART_REG) MmMapIoSpace(Addr, sizeof(CSP_UART_REG), FALSE);
// Check if virtual mapping failed
if (g_pVSIRReg == NULL)
{
DEBUGMSG(0, (TEXT("Sir: MmMapIoSpace failed!\r\n")));
return FALSE;
}
}
#if 0
if (!BSPUartGetIrq((ULONG)thisDev->SirPhyAddr, &thisDev->sysIntrSir))
{
DEBUGMSG(ZONE_ERROR, (TEXT("Resource: ERROR: Failed to obtain uart info.\r\n")));
return FALSE;
}
#endif
// Use kernel IOCTL to translate the UART base address into an IRQ since
// the IRQ value differs based on the SoC. Note that DEVICE_LOCATION
// fields except IfcType and LogicalLoc are ignored for internal SoC
// components.
devLoc.IfcType = Internal;
devLoc.LogicalLoc = (ULONG)thisDev->SirPhyAddr;
if (!KernelIoControl(IOCTL_HAL_REQUEST_IRQ, &devLoc, sizeof(devLoc),
&thisDev->sysIntrSir, sizeof(thisDev->sysIntrSir), NULL))
{
ERRORMSG(1, (_T("Cannot obtain UART IRQ!\r\n")));
DEBUGMSG(ZONE_ERROR, (TEXT("Sir - Initialization failed!!\r\n")));
return FALSE;
}
DEBUGMSG(ZONE_INIT, (TEXT("Sir: -SirInitialize\r\n")));
return TRUE;
}
//-----------------------------------------------------------------------------
//
// Function: SirDeInitialize
//
// This function deinitializes the Sir device.
//
// Parameters:
// thisDev
// [in] pFirDevice_t.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
VOID SirDeInitialize(pFirDevice_t thisDev)
{
DEBUGMSG(ZONE_DEINIT, (TEXT("Sir: +SirDeInitialize\r\n")));
// Free UART register
if(g_pVSIRReg)
{
MmUnmapIoSpace(g_pVSIRReg, sizeof(CSP_UART_REG));
g_pVSIRReg = NULL;
}
// Release SYSINTR
KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR, &thisDev->sysIntrSir, sizeof(DWORD), NULL, 0, NULL);
thisDev->sysIntrSir = SYSINTR_UNDEFINED;
DEBUGMSG(ZONE_DEINIT, (TEXT("Sir: -SirDeInitialize\r\n")));
}
//-----------------------------------------------------------------------------
//
// Function: SirClose
//
// This function closes the Sir device.
//
// Parameters:
// thisDev
// [in] pFirDevice_t.
//
// Returns:
// None.
//
//-----------------------------------------------------------------------------
VOID SirClose(pFirDevice_t thisDev)
{
DEBUGMSG(ZONE_CLOSE, (TEXT("Sir: +SirClose\r\n")));
if (thisDev->portInfo.readBuf)
{
InsertTailList(&thisDev->rcvBufBuf, RCV_BUF_TO_LIST_ENTRY(thisDev->portInfo.readBuf));
thisDev->portInfo.readBuf = NULL;
}
thisDev->writeBuf = NULL;
CSP_BITFCLR(g_pVSIRReg->UCR2, UART_UCR2_TXEN);
CSP_BITFCLR(g_pVSIRReg->UCR2, UART_UCR2_RXEN);
// Reset UART2
g_pVSIRReg->UCR2 = CSP_BITFVAL(UART_UCR2_SRST, UART_UCR2_SRST_RESET);
// Disable extern IrDa pin
BSPIrdaEnable(FALSE);
BSPUartEnableClock(thisDev->SirPhyAddr, FALSE);
DEBUGMSG(ZONE_CLOSE, (TEXT("Sir: -SirClose\r\n")));
}
//-----------------------------------------------------------------------------
//
// Function: SirOpen
//
// This function opens the Sir device.
//
// Parameters:
// thisDev
// [in] pFirDevice_t.
//
// Returns:
// This function returns status of open device.
//
//-----------------------------------------------------------------------------
BOOLEAN SirOpen(pFirDevice_t thisDev)
{
PLIST_ENTRY pListEntry;
BOOLEAN result = TRUE;
UINT i;
ULONG bRefFreq = UART_REF_FREQ;
DEBUGMSG(ZONE_OPEN, (TEXT("Sir: +SirOpen")));
BSPIrdaEnable(TRUE);
BSPSirSetIOMUX();
BSPIrdaSetMode(SIR_MODE);
if (!BSPUartEnableClock(thisDev->SirPhyAddr, TRUE))
{
DEBUGMSG(ZONE_ERROR, (TEXT("Fir: BSPUartEnableClock failed!\r\n")));
return FALSE;
}
if (!thisDev->writeBuf)
thisDev->writeBuf = (PUCHAR)MyMemAlloc(MAX_IRDA_DATA_SIZE);
pListEntry = MyRemoveHeadList(&thisDev->rcvBufBuf);
if (pListEntry)
{
thisDev->portInfo.readBuf = (PUCHAR) LIST_ENTRY_TO_RCV_BUF(pListEntry);
}
else
{
result = FALSE;
goto done;
}
thisDev->portInfo.rcvState = STATE_INIT;
thisDev->writePending = FALSE;
// Configure UART2 registers
g_pVSIRReg->UCR1 = CSP_BITFVAL(UART_UCR1_UARTEN, UART_UCR1_UARTEN_DISABLE); // Disable UART
g_pVSIRReg->UCR2 = CSP_BITFVAL(UART_UCR2_SRST, UART_UCR2_SRST_RESET); // Reset UART
// wait for a while
for (i = 0; i <= 4; i++);
CSP_BITFINS(g_pVSIRReg->UFCR, UART_UFCR_RFDIV, RFDIV_VALUE(BSPUartCalRFDIV(&bRefFreq)));
g_pVSIRReg->UBIR = UART_UBIR_INCREMENT(DEFAULT_BAUD_RATE, UART_UBMR_MOD_DEFAULT, bRefFreq)-1;
g_pVSIRReg->UBMR = UART_UBMR_MOD_DEFAULT -1;
g_pVSIRReg->ONEMS = (UART_REF_FREQ / 1000);
g_pVSIRReg->UCR2 |=
CSP_BITFVAL(UART_UCR2_SRST, UART_UCR2_SRST_NORESET) | // no reset
CSP_BITFVAL(UART_UCR2_RXEN, UART_UCR2_RXEN_ENABLE) | // enable receiver
CSP_BITFVAL(UART_UCR2_TXEN, UART_UCR2_TXEN_ENABLE) | // enable transmitter
CSP_BITFVAL(UART_UCR2_WS, UART_UCR2_WS_8BIT) | // 8 Bits
CSP_BITFVAL(UART_UCR2_IRTS, UART_UCR2_IRTS_IGNORERTS); // ignore RTS pin, for "none flow control"
g_pVSIRReg->UCR3 =
CSP_BITFVAL(UART_UCR3_INVT, UART_UCR3_INVT_ACTIVELOW) | // transmitter not inverted
CSP_BITFVAL(UART_UCR3_RXDMUXSEL, UART_UCR3_RXDMUXSEL_MUX); // new add in mx21
g_pVSIRReg->UCR4 =
CSP_BITFVAL(UART_UCR4_INVR, UART_UCR4_INVR_ACTIVELOW) | // receiver not inverted
CSP_BITFVAL(UART_UCR4_CTSTL, 32);
g_pVSIRReg->UCR1 =
CSP_BITFVAL(UART_UCR1_UARTEN, UART_UCR1_UARTEN_ENABLE) | // Enable UART
CSP_BITFVAL(UART_UCR1_IREN, UART_UCR1_IREN_ENABLE); // Enable IR
// We should call SetSpeed() only at initialization.
// If this function is called from other functions,
// we only need setup UART speed but not all speed info.
if (!thisDev->linkSpeedInfo)
SetSpeed(thisDev);
else
SirSetSpeed(thisDev);
done:
DEBUGMSG(ZONE_OPEN, (TEXT("Sir: -SirOpen %s"), (CHAR *)(result ? "succeeded" : "failed")));
if (result)
{
return TRUE;
}
else
{
SirClose(thisDev);
return FALSE;
}
}
//-----------------------------------------------------------------------------
//
// Function: SirSendPacketQ
//
// This function sends the packet from the send queue.
//
// Parameters:
// thisDev
// [in] pFirDevice_t.
// firstBufIsPending
// [out] BOOLEAN.
//
// Returns:
// NDIS_STATUS.
//
//-----------------------------------------------------------------------------
NDIS_STATUS SirSendPacketQ(pFirDevice_t thisDev, BOOLEAN firstBufIsPending)
{
NDIS_STATUS Result = NDIS_STATUS_FAILURE;
BOOLEAN sendSucceeded;
PLIST_ENTRY ListEntry;
DEBUGMSG(ZONE_SEND, (TEXT("Sir: SirSendPacketQ(dev=0x%x, %hs)\r\n"),
(UINT)thisDev, (CHAR *)(firstBufIsPending ? "pend" : "not pend")));
// Get packet from the head of SendQueue
ListEntry = MyRemoveHeadList(&thisDev->SendQueue);
if (ListEntry)
{
PNDIS_PACKET packetToSend = CONTAINING_RECORD(ListEntry,
NDIS_PACKET, MiniportReserved);
PNDIS_IRDA_PACKET_INFO packetInfo;
packetInfo = GetPacketInfo(packetToSend);
//
// NOTE: Don't use NdisStallExecution for turnaround delay since
// you shouldn't stall for more than 60 us. Calling
// NdisStallExecution for large times will degrade system
// performance.
//
DEBUGMSG(ZONE_SEND, (TEXT("Sir: TurnaroundTimer (%d).\r\n"), packetInfo->MinTurnAroundTime));
if (packetInfo->MinTurnAroundTime)
{
UINT usecToWait = packetInfo->MinTurnAroundTime;
UINT msecToWait;
// Reset the time, so that the packet gets sent out after timeout
packetInfo->MinTurnAroundTime = 0;
// Add it back to the head of the SendQueue
InsertHeadList(&thisDev->SendQueue, (PLIST_ENTRY)packetToSend->MiniportReserved);
// Ndis timer has a 1ms granularity (in theory). Let's round off.
msecToWait = (usecToWait < 1000) ? 1 : (usecToWait + 500) / 1000;
DEBUGMSG(ZONE_SEND, (TEXT("Sir: TurnaroundTimer (%d).\r\n"), msecToWait));
NdisMSetTimer(&thisDev->TurnaroundTimer, msecToWait);
return NDIS_STATUS_PENDING; // Say we're successful. We'll come back here.
}
// See if this was the last packet before we need to change speed.
if (packetToSend == thisDev->lastPacketAtOldSpeed)
{
thisDev->lastPacketAtOldSpeed = NULL;
thisDev->setSpeedAfterCurrentSendPacket = TRUE;
}
// Send one packet to the COM port.
DEBUGMSG(ZONE_SEND, (TEXT("Sir: Sending packet (0x%x).\r\n"), (UINT)packetToSend));
sendSucceeded = SirDoSend(thisDev, packetToSend);
// If the buffer we just sent was pending
// (i.e. we returned NDIS_STATUS_PENDING for it in SirSend),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -