📄 isr.c
字号:
DeviceData->ConsecutiveFFs++;
} else {
//
// Reset!
//
DeviceData->ConsecutiveFFs = 0;
}
bytesDequeued++;
}
}
lsr.AsUChar = READ_HARDWARE_UCHAR(DeviceData,
CIRCC2_LINE_STATUS_R);
//
// End of IR data or have we trashed the FIFO? If we
// trashed the FIFO then the safest thing to do is
// just abort the keypress and start over, which we'll
// do...
//
if ((DeviceData->ConsecutiveFFs >= DeviceData->NumFFsForDataEnd) ||
lsr.OverRun) {
//
// Indeed. Let's start this over...
//
DeviceData->ConsecutiveFFs = 0;
//
// Enqueue one more byte, this time indicate that
// we are indeed at the end fo the line with TRUE
// for DataEnd...
//
SmscIrEnqueueFifoByte(DeviceData,
0xFF,
TRUE);
//
// Once the receiver starts to collect IR
// data, it collects the samples from the actual
// IR stream and then continues to fill the FIFO
// with FFs to indicate silence until we shut it
// up. How do we shut it up, you ask? By disabling
// the IR receiver and then enabling it again, of
// course...
//
// We'll reenable the receiver before we get out of here...
//
lcb.AsUChar = 0;
WRITE_HARDWARE_UCHAR(DeviceData,
CIRCC2_LINE_CONTROL_B,
lcb.AsUChar);
//
// Dump any potential leftovers from the FIFO.
//
lca.AsUChar = 0;
lca.FifoReset = TRUE;
WRITE_HARDWARE_UCHAR(DeviceData,
CIRCC2_LINE_CONTROL_A,
lca.AsUChar);
//
// If we're in priority mode we'll need to read
// the carrier measure register
//
if (DeviceData->InPriorityMode) {
mbc.AsUChar = 0;
mbc.RegisterBlockSelect = 5;
WRITE_HARDWARE_UCHAR(DeviceData,
CIRCC2_MASTER_BLOCK_CONTROL,
mbc.AsUChar);
carrierMeasure
= READ_HARDWARE_UCHAR(DeviceData,
CIRCC2_CARRIER_CAPTURE_MEASURE);
if (carrierMeasure != 0) {
DeviceData->CarrierMeasure = carrierMeasure;
}
//
// Reset the carrier capture control
//
captureControl.AsUChar = 0;
captureControl.CaptureReset = TRUE;
WRITE_HARDWARE_UCHAR(DeviceData,
CIRCC2_CARRIER_CAPTURE_CONTROL,
captureControl.AsUChar);
}
mbc.AsUChar = 0;
mbc.ErrorReset = TRUE;
WRITE_HARDWARE_UCHAR(DeviceData,
CIRCC2_MASTER_BLOCK_CONTROL,
mbc.AsUChar);
mbc.AsUChar = 0;
mbc.MasterInterruptEnable = TRUE;
WRITE_HARDWARE_UCHAR(DeviceData,
CIRCC2_MASTER_BLOCK_CONTROL,
mbc.AsUChar);
}
//
// Re-enable the FIFO interrupt
//
intEnable.AsUChar = 0;
intEnable.Fifo = TRUE;
WRITE_HARDWARE_UCHAR(DeviceData,
CIRCC2_INTERRUPT_ENABLE,
intEnable.AsUChar);
//
// Set the device to receive.
//
lcb.AsUChar = 0;
lcb.SCEModeBits = SCE_MODE_RECEIVE;
WRITE_HARDWARE_UCHAR(DeviceData,
CIRCC2_LINE_CONTROL_B,
lcb.AsUChar);
//
// DPC required.
//
return TRUE;
}
BOOLEAN
__forceinline
SmscIrProcessTxInterrupt(
PSMSCIR_DATA DeviceData,
PBIRCC2_INTERRUPT_ID_OR_ENABLE TxIntId
) {
BIRCC2_LINE_CONTROL txLc;
BIRCC2_INTERRUPT_ID_OR_ENABLE txIntEnable;
//
// Store away the interrupt mask
//
DeviceData->TxIntId.AsUChar |= TxIntId->AsUChar;
if (TxIntId->Fifo) {
//
// Shut off the FIFO interrupt.
//
txIntEnable.AsUChar = 0;
WRITE_TRANSMIT_UCHAR(DeviceData,
BIRCC2_INTERRUPT_ENABLE_ADDR,
txIntEnable.AsUChar);
//
// Need a DPC
//
return TRUE;
}
//
// No FIFO interrupt...Check for an underrun
//
if (TxIntId->TxComplete) {
txLc.AsUChar = READ_TRANSMIT_UCHAR(DeviceData,
BIRCC2_LINE_CONTROL_ADDR);
if (txLc.FifoNotEmpty &&
!txLc.TxEnable) {
//
// Underrun...Provoke the DPC into continuing the
// processing...
//
DeviceData->TxIntId.Fifo = TRUE;
//
// And reset the FIFO
//
txLc.FifoReset = TRUE;
WRITE_TRANSMIT_UCHAR(DeviceData,
BIRCC2_LINE_CONTROL_ADDR,
txLc.AsUChar);
}
return TRUE;
}
return FALSE;
}
__forceinline
VOID
SmscIrEnqueueFifoByte(
IN PSMSCIR_DATA FdoData,
UCHAR Byte,
IN BOOLEAN DataEnd
) {
/*++
Routine Description:
Called from the ISR to move the byte taken from
the FIFO into the circular buffer
Arguments:
FdoData - The device extension
Byte - The byte to store
DataEnd - Is this a data end?
--*/
FdoData->CurrentFifoBufferSize++;
FdoData->FifoBuffer[FdoData->NextFifoIndex++] = Byte;
if (FdoData->NextFifoIndex == SMSCIR_FIFO_BUFFER_SIZE) {
FdoData->NextFifoIndex = 0;
}
if (FdoData->CurrentFifoBufferSize > SMSCIR_FIFO_BUFFER_SIZE) {
FdoData->CurrentFifoBufferSize = SMSCIR_FIFO_BUFFER_SIZE;
FdoData->CurrentFifoIndex = (FdoData->NextFifoIndex != 0)
? FdoData->NextFifoIndex-1
: SMSCIR_FIFO_BUFFER_SIZE-1;
}
//
// If this is a data end, then we'll set the watermark
// for the data end event. When the dequeue code comes
// in it will use this to know how to mark the
// DataEnd member of the RECEIVE IOCTL.
//
if (DataEnd) {
if (FdoData->BytesToDataEnd) {
SmscIrTracePrint(
TRACE_LEVEL_INFORMATION,
SMSCDBG_RECEIVE_INFO,
("SmscIrEnqueueFifoByte: DataEnd was already present. "\
"Previous KeyUp missed\n"));
}
FdoData->BytesToDataEnd = FdoData->CurrentFifoBufferSize;
}
}
ULONG
SmscIrFifoBytesRemaining(
IN PSMSCIR_DATA DeviceData
) {
/*++
Routine Description:
Returns the number of bytes remaining in the FIFO buffer
*Interrupt Lock* held by caller on entry
Arguments:
DeviceData - The device extension
--*/
if (DeviceData->BytesToDataEnd) {
return DeviceData->BytesToDataEnd;
} else {
return DeviceData->CurrentFifoBufferSize;
}
}
ULONG
SmscIrDequeueFifoData(
IN PSMSCIR_DATA DeviceData,
__out_bcount(MaxLen) PUCHAR Buffer,
ULONG MaxLen,
__out PBOOLEAN DataEnd
) {
/*++
Routine Description:
Called from the DPC to remove multiple bytes from
the FIFO circular buffer
*Interrupt Lock* held by caller on entry
Arguments:
DeviceData - The device extension
Buffer - Buffer to copy the data into
MaxLen - Size of the Buffer parameter, in bytes
DataEnd - Is this a data end?
Return Value:
Actual number of bytes copied
--*/
ULONG bufferSize;
ULONG amountToCopy;
ULONG nextIndex;
#if DBG
ULONG prevValue;
#endif
*DataEnd = FALSE;
if (0 == DeviceData->CurrentFifoBufferSize){
return 0;
} else {
if (DeviceData->BytesToDataEnd) {
bufferSize = DeviceData->BytesToDataEnd;
} else {
bufferSize = DeviceData->CurrentFifoBufferSize;
}
amountToCopy = bufferSize < MaxLen ? bufferSize : MaxLen;
if ((DeviceData->CurrentFifoIndex + amountToCopy)
> SMSCIR_FIFO_BUFFER_SIZE) {
ULONG amountToCopyFirst
= SMSCIR_FIFO_BUFFER_SIZE - DeviceData->CurrentFifoIndex;
RtlCopyMemory(
Buffer,
DeviceData->FifoBuffer + DeviceData->CurrentFifoIndex,
amountToCopyFirst);
//
// Prefast will complain about this calculation, but it is
// correct.
//
#pragma prefast (suppress:411, "Calculation is correct and as designed")
RtlCopyMemory(Buffer + amountToCopyFirst,
DeviceData->FifoBuffer,
amountToCopy - amountToCopyFirst);
DeviceData->CurrentFifoIndex = amountToCopy - amountToCopyFirst;
} else {
RtlCopyMemory(
Buffer,
DeviceData->FifoBuffer + DeviceData->CurrentFifoIndex,
amountToCopy);
nextIndex = DeviceData->CurrentFifoIndex + amountToCopy;
if (nextIndex == SMSCIR_FIFO_BUFFER_SIZE) {
DeviceData->CurrentFifoIndex = 0;
} else {
DeviceData->CurrentFifoIndex = nextIndex;
}
}
if (DeviceData->BytesToDataEnd) {
#if DBG
prevValue = DeviceData->BytesToDataEnd;
#endif
DeviceData->BytesToDataEnd -= amountToCopy;
#if DBG
//
// Make sure we didn't wrap under...
//
ASSERT(DeviceData->BytesToDataEnd < prevValue);
#endif
*DataEnd = (BOOLEAN)(DeviceData->BytesToDataEnd == 0);
}
#if DBG
prevValue = DeviceData->CurrentFifoBufferSize;
#endif
DeviceData->CurrentFifoBufferSize -= amountToCopy;
#if DBG
//
// Make sure we didn't wrap under...
//
ASSERT(DeviceData->CurrentFifoBufferSize < prevValue);
#endif
return amountToCopy;
}
}
NTSTATUS
SmscIrEvtInterruptDisable(
IN WDFINTERRUPT Interrupt,
IN WDFDEVICE Device
) {
/*++
Routine Description.
Called here to disable interrupts on the device.
Arguments:
Interrupt - Our interrupt object
Device - The device to enable interrupts on
--*/
MASTER_BLOCK_CONTROL mbc;
PSMSCIR_DATA deviceData;
UNREFERENCED_PARAMETER(Interrupt);
SmscIrTracePrint(TRACE_LEVEL_VERBOSE,
SMSCDBG_INIT_INFO,
("SmscIrEvtInterruptDisable: Entered"));
deviceData = (PSMSCIR_DATA)GetIrData(Device);
//
// Just disabling master interrupts is enough
// to quiesce the device and allow our driver
// to go away safely.
//
mbc.AsUChar = 0;
WRITE_HARDWARE_UCHAR(deviceData,
CIRCC2_MASTER_BLOCK_CONTROL,
mbc.AsUChar);
SmscIrTracePrint(TRACE_LEVEL_VERBOSE,
SMSCDBG_INIT_INFO,
("SmscIrEvtInterruptDisable: Exited"));
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -