📄 write.c
字号:
// The rts line may already be up from previous writes,
// however, it won't take much additional time to turn
// on the RTS line if we are doing transmit toggling.
//
if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE) {
SerialSetRTS(Extension);
}
return FALSE;
}
VOID
SerialCancelCurrentWrite(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
/*++
Routine Description:
This routine is used to cancel the current write.
Arguments:
DeviceObject - Pointer to the device object for this device
Irp - Pointer to the IRP to be canceled.
Return Value:
None.
--*/
{
PDEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
//SERIAL_LOCKED_PAGED_CODE();
SerialTryToCompleteCurrent(
Extension,
SerialGrabWriteFromIsr,
Irp->CancelIrql,
STATUS_CANCELLED,
&Extension->CurrentWriteIrp,
&Extension->WriteQueue,
NULL,
&Extension->WriteRequestTotalTimer,
SerialStartWrite,
SerialGetNextWrite,
SERIAL_REF_CANCEL
);
}
VOID
SerialWriteTimeout(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemContext1,
IN PVOID SystemContext2
)
/*++
Routine Description:
This routine will try to timeout the current write.
Arguments:
Dpc - Not Used.
DeferredContext - Really points to the device extension.
SystemContext1 - Not Used.
SystemContext2 - Not Used.
Return Value:
None.
--*/
{
PDEVICE_EXTENSION Extension = DeferredContext;
KIRQL OldIrql;
UNREFERENCED_PARAMETER(SystemContext1);
UNREFERENCED_PARAMETER(SystemContext2);
SerialDump(SERTRACECALLS, ("SERIAL: SerialWriteTimeout\n"));
IoAcquireCancelSpinLock(&OldIrql);
SerialTryToCompleteCurrent(
Extension,
SerialGrabWriteFromIsr,
OldIrql,
STATUS_TIMEOUT,
&Extension->CurrentWriteIrp,
&Extension->WriteQueue,
NULL,
&Extension->WriteRequestTotalTimer,
SerialStartWrite,
SerialGetNextWrite,
SERIAL_REF_TOTAL_TIMER
);
SerialDpcEpilogue(Extension, Dpc);
}
BOOLEAN
SerialGrabWriteFromIsr(
IN PVOID Context
)
/*++
Routine Description:
This routine is used to grab the current irp, which could be timing
out or canceling, from the ISR
NOTE: This routine is being called from KeSynchronizeExecution.
NOTE: This routine assumes that the cancel spin lock is held
when this routine is called.
Arguments:
Context - Really a pointer to the device extension.
Return Value:
Always false.
--*/
{
PDEVICE_EXTENSION Extension = Context;
//SERIAL_LOCKED_PAGED_CODE();
//
// Check if the write length is non-zero. If it is non-zero
// then the ISR still owns the irp. We calculate the the number
// of characters written and update the information field of the
// irp with the characters written. We then clear the write length
// the isr sees.
//
if (Extension->WriteLength) {
//
// We could have an xoff counter masquerading as a
// write irp. If so, don't update the write length.
//
if (IoGetCurrentIrpStackLocation(Extension->CurrentWriteIrp)
->MajorFunction == IRP_MJ_WRITE) {
Extension->CurrentWriteIrp->IoStatus.Information =
IoGetCurrentIrpStackLocation(
Extension->CurrentWriteIrp
)->Parameters.Write.Length -
Extension->WriteLength;
} else {
Extension->CurrentWriteIrp->IoStatus.Information = 0;
}
//
// Since the isr no longer references this irp, we can
// decrement it's reference count.
//
SERIAL_CLEAR_REFERENCE(
Extension->CurrentWriteIrp,
SERIAL_REF_ISR
);
Extension->WriteLength = 0;
}
return FALSE;
}
BOOLEAN
SerialGrabXoffFromIsr(
IN PVOID Context
)
/*++
Routine Description:
This routine is used to grab an xoff counter irp from the
isr when it is no longer masquerading as a write irp. This
routine is called by the cancel and timeout code for the
xoff counter ioctl.
NOTE: This routine is being called from KeSynchronizeExecution.
NOTE: This routine assumes that the cancel spin lock is held
when this routine is called.
Arguments:
Context - Really a pointer to the device extension.
Return Value:
Always false.
--*/
{
PDEVICE_EXTENSION Extension = Context;
//SERIAL_LOCKED_PAGED_CODE();
if (Extension->CountSinceXoff) {
//
// This is only non-zero when there actually is a Xoff ioctl
// counting down.
//
Extension->CountSinceXoff = 0;
//
// We decrement the count since the isr no longer owns
// the irp.
//
SERIAL_CLEAR_REFERENCE(
Extension->CurrentXoffIrp,
SERIAL_REF_ISR
);
}
return FALSE;
}
VOID
SerialCompleteXoff(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemContext1,
IN PVOID SystemContext2
)
/*++
Routine Description:
This routine is merely used to truely complete an xoff counter irp. It
assumes that the status and the information fields of the irp are
already correctly filled in.
Arguments:
Dpc - Not Used.
DeferredContext - Really points to the device extension.
SystemContext1 - Not Used.
SystemContext2 - Not Used.
Return Value:
None.
--*/
{
PDEVICE_EXTENSION Extension = DeferredContext;
KIRQL OldIrql;
UNREFERENCED_PARAMETER(SystemContext1);
UNREFERENCED_PARAMETER(SystemContext2);
SerialDump(SERTRACECALLS, ("SERIAL: SerialCompleteXoff\n"));
IoAcquireCancelSpinLock(&OldIrql);
SerialTryToCompleteCurrent(
Extension,
NULL,
OldIrql,
STATUS_SUCCESS,
&Extension->CurrentXoffIrp,
NULL,
NULL,
&Extension->XoffCountTimer,
NULL,
NULL,
SERIAL_REF_ISR
);
SerialDpcEpilogue(Extension, Dpc);
}
VOID
SerialTimeoutXoff(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemContext1,
IN PVOID SystemContext2
)
/*++
Routine Description:
This routine is merely used to truely complete an xoff counter irp,
if its timer has run out.
Arguments:
Dpc - Not Used.
DeferredContext - Really points to the device extension.
SystemContext1 - Not Used.
SystemContext2 - Not Used.
Return Value:
None.
--*/
{
PDEVICE_EXTENSION Extension = DeferredContext;
KIRQL OldIrql;
UNREFERENCED_PARAMETER(SystemContext1);
UNREFERENCED_PARAMETER(SystemContext2);
SerialDump(SERTRACECALLS, ("SERIAL: SerialTimeoutXoff\n"));
IoAcquireCancelSpinLock(&OldIrql);
SerialTryToCompleteCurrent(
Extension,
SerialGrabXoffFromIsr,
OldIrql,
STATUS_SERIAL_COUNTER_TIMEOUT,
&Extension->CurrentXoffIrp,
NULL,
NULL,
NULL,
NULL,
NULL,
SERIAL_REF_TOTAL_TIMER
);
SerialDpcEpilogue(Extension, Dpc);
}
VOID
SerialCancelCurrentXoff(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
/*++
Routine Description:
This routine is used to cancel the current write.
Arguments:
DeviceObject - Pointer to the device object for this device
Irp - Pointer to the IRP to be canceled.
Return Value:
None.
--*/
{
PDEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
//SERIAL_LOCKED_PAGED_CODE();
SerialTryToCompleteCurrent(
Extension,
SerialGrabXoffFromIsr,
Irp->CancelIrql,
STATUS_CANCELLED,
&Extension->CurrentXoffIrp,
NULL,
NULL,
&Extension->XoffCountTimer,
NULL,
NULL,
SERIAL_REF_CANCEL
);
}
BOOLEAN
SerialGiveXoffToIsr(
IN PVOID Context
)
/*++
Routine Description:
This routine starts off the xoff counter. It merely
has to set the xoff count and increment the reference
count to denote that the isr has a reference to the irp.
NOTE: This routine is called by KeSynchronizeExecution.
NOTE: This routine assumes that it is called with the
cancel spin lock held.
Arguments:
Context - Really a pointer to the device extension.
Return Value:
This routine always returns FALSE.
--*/
{
PDEVICE_EXTENSION Extension = Context;
//
// The current stack location. This contains all of the
// information we need to process this particular request.
//
PSERIAL_XOFF_COUNTER Xc =
Extension->CurrentXoffIrp->AssociatedIrp.SystemBuffer;
//SERIAL_LOCKED_PAGED_CODE();
ASSERT(Extension->CurrentXoffIrp);
Extension->CountSinceXoff = Xc->Counter;
//
// The isr now has a reference to the irp.
//
SERIAL_SET_REFERENCE(
Extension->CurrentXoffIrp,
SERIAL_REF_ISR
);
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -