📄 initunlo.c
字号:
//
// If necessary, unmap the device registers.
//
if (PDevExt->UnMapRegisters) {
MmUnmapIoSpace(PDevExt->Controller, PDevExt->SpanOfController);
}
if (PDevExt->UnMapStatus) {
MmUnmapIoSpace(PDevExt->InterruptStatus,
PDevExt->SpanOfInterruptStatus);
}
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, "<SerialReleaseResources\n");
}
NTSTATUS
SerialPrepareRemove(IN PDEVICE_OBJECT PDevObj)
/*++
Routine Description:
Removes a serial device object from the system.
Arguments:
PDevObj - A pointer to the Device Object we want removed.
Return Value:
Always TRUE
--*/
{
PSERIAL_DEVICE_EXTENSION pDevExt
= (PSERIAL_DEVICE_EXTENSION)PDevObj->DeviceExtension;
POWER_STATE state;
ULONG pendingIRPs;
PAGED_CODE();
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, ">SerialPrepareRemove(%X)\n", PDevObj);
//
// Mark as not accepting requests
//
SerialSetAccept(pDevExt, SERIAL_PNPACCEPT_REMOVING);
//
// Complete all pending requests
//
SerialKillPendingIrps(PDevObj);
//
// Wait for any pending requests we raced on.
//
pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
if (pendingIRPs) {
KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive, KernelMode,
FALSE, NULL);
}
state.DeviceState = PowerDeviceD3;
PoSetPowerState(PDevObj, DevicePowerState, state);
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, "<SerialPrepareRemove TRUE\n");
return TRUE;
}
VOID
SerialDisableInterfacesResources(IN PDEVICE_OBJECT PDevObj,
BOOLEAN DisableUART)
{
PSERIAL_DEVICE_EXTENSION pDevExt
= (PSERIAL_DEVICE_EXTENSION)PDevObj->DeviceExtension;
PAGED_CODE();
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, ">SerialDisableInterfaces(%X, %s)\n",
PDevObj, DisableUART ? "TRUE" : "FALSE");
//
// Only do these many things if the device has started and still
// has resources allocated
//
if (pDevExt->Flags & SERIAL_FLAGS_STARTED) {
PULONG countSoFar = &IoGetConfigurationInformation()->SerialCount;
(*countSoFar)--;
if (!(pDevExt->Flags & SERIAL_FLAGS_STOPPED)) {
if (DisableUART) {
//
// Mask off interrupts
//
DISABLE_ALL_INTERRUPTS(pDevExt->Controller);
}
SerialReleaseResources(pDevExt);
}
//
// Remove us from WMI consideration
//
IoWMIRegistrationControl(PDevObj, WMIREG_ACTION_DEREGISTER);
}
//
// Undo external names
//
SerialUndoExternalNaming(pDevExt);
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, "<SerialDisableInterfaces\n");
}
NTSTATUS
SerialRemoveDevObj(IN PDEVICE_OBJECT PDevObj)
/*++
Routine Description:
Removes a serial device object from the system.
Arguments:
PDevObj - A pointer to the Device Object we want removed.
Return Value:
Always TRUE
--*/
{
PSERIAL_DEVICE_EXTENSION pDevExt
= (PSERIAL_DEVICE_EXTENSION)PDevObj->DeviceExtension;
PAGED_CODE();
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, ">SerialRemoveDevObj(%X)\n", PDevObj);
if (!(pDevExt->DevicePNPAccept & SERIAL_PNPACCEPT_SURPRISE_REMOVING)) {
//
// Disable all external interfaces and release resources
//
SerialDisableInterfacesResources(PDevObj, TRUE);
}
IoDetachDevice(pDevExt->LowerDeviceObject);
//
// Free memory allocated in the extension
//
if (pDevExt->NtNameForPort.Buffer != NULL) {
ExFreePool(pDevExt->NtNameForPort.Buffer);
}
if (pDevExt->DeviceName.Buffer != NULL) {
ExFreePool(pDevExt->DeviceName.Buffer);
}
if (pDevExt->SymbolicLinkName.Buffer != NULL) {
ExFreePool(pDevExt->SymbolicLinkName.Buffer);
}
if (pDevExt->DosName.Buffer != NULL) {
ExFreePool(pDevExt->DosName.Buffer);
}
if (pDevExt->ObjectDirectory.Buffer) {
ExFreePool(pDevExt->ObjectDirectory.Buffer);
}
//
// Delete the devobj
//
IoDeleteDevice(PDevObj);
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, "<SerialRemoveDevObj %X\n",
STATUS_SUCCESS);
return STATUS_SUCCESS;
}
VOID
SerialKillPendingIrps(PDEVICE_OBJECT PDevObj)
/*++
Routine Description:
This routine kills any irps pending for the passed device object.
Arguments:
PDevObj - Pointer to the device object whose irps must die.
Return Value:
VOID
--*/
{
PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
KIRQL oldIrql;
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, ">SerialKillPendingIrps(%X)\n",
PDevObj);
//
// First kill all the reads and writes.
//
SerialKillAllReadsOrWrites(PDevObj, &pDevExt->WriteQueue,
&pDevExt->CurrentWriteIrp);
SerialKillAllReadsOrWrites(PDevObj, &pDevExt->ReadQueue,
&pDevExt->CurrentReadIrp);
//
// Next get rid of purges.
//
SerialKillAllReadsOrWrites(PDevObj, &pDevExt->PurgeQueue,
&pDevExt->CurrentPurgeIrp);
//
// Get rid of any mask operations.
//
SerialKillAllReadsOrWrites(PDevObj, &pDevExt->MaskQueue,
&pDevExt->CurrentMaskIrp);
//
// Now get rid a pending wait mask irp.
//
IoAcquireCancelSpinLock(&oldIrql);
if (pDevExt->CurrentWaitIrp) {
PDRIVER_CANCEL cancelRoutine;
cancelRoutine = pDevExt->CurrentWaitIrp->CancelRoutine;
pDevExt->CurrentWaitIrp->Cancel = TRUE;
if (cancelRoutine) {
pDevExt->CurrentWaitIrp->CancelIrql = oldIrql;
pDevExt->CurrentWaitIrp->CancelRoutine = NULL;
cancelRoutine(PDevObj, pDevExt->CurrentWaitIrp);
}
} else {
IoReleaseCancelSpinLock(oldIrql);
}
//
// Cancel any pending wait-wake irps
//
if (pDevExt->PendingWakeIrp != NULL) {
IoCancelIrp(pDevExt->PendingWakeIrp);
pDevExt->PendingWakeIrp = NULL;
}
//
// Finally, dump any stalled IRPS
//
SerialKillAllStalled(PDevObj);
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, "<SerialKillPendingIrps\n");
}
BOOLEAN
SerialSingleToMulti(PVOID Context)
/*++
Routine Description:
This routine converts a root device set up to be a single port
device to a multiport device while that device is running.
Arguments:
Context - Actually a pointer to the device extension of the root
device we are turning into a multiport device.
Return Value:
Always TRUE
--*/
{
PSERIAL_DEVICE_EXTENSION pDevExt = (PSERIAL_DEVICE_EXTENSION)Context;
PSERIAL_MULTIPORT_DISPATCH pOurIsrContext;
PSERIAL_MULTIPORT_DISPATCH pNewIsrContext
= (PSERIAL_MULTIPORT_DISPATCH)pDevExt->NewExtension;
PVOID isrFunc;
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, ">SerialSingleToMulti(%X)\n", pDevExt);
//
// Stomp OurIsrContext since we are going from one to many
// thus our previous context was just pDevExt and doesn't
// need to be released (i.e., no call to ExFreePool() is needed).
//
pOurIsrContext = pDevExt->OurIsrContext = pDevExt->TopLevelOurIsrContext
= pNewIsrContext;
//
// We are now multiport
//
pDevExt->PortOnAMultiportCard = TRUE;
//
// Update our personal extensions slot
//
pOurIsrContext->Extensions[pDevExt->PortIndex - 1] = pDevExt;
pOurIsrContext->InterruptStatus = pDevExt->InterruptStatus;
//
// We have to pick a new ISR and a new context.
// As soon as this is done, the ISR will change, so we have to
// be ready to handle things there.
//
if (pDevExt->Indexed == FALSE) {
pOurIsrContext->UsablePortMask = 1 << (pDevExt->PortIndex - 1);
pOurIsrContext->MaskInverted = pDevExt->MaskInverted;
isrFunc = SerialBitMappedMultiportIsr;
} else {
isrFunc = SerialIndexedMultiportIsr;
}
pDevExt->OurIsr = isrFunc;
pDevExt->TopLevelOurIsr = isrFunc;
if (pDevExt->CIsrSw->IsrFunc != SerialSharerIsr) {
pDevExt->CIsrSw->IsrFunc = isrFunc;
pDevExt->CIsrSw->Context = pOurIsrContext;
}
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, "<SerialSingleToMulti TRUE\n");
return TRUE;
}
BOOLEAN
SerialAddToMulti(PVOID Context)
/*++
Routine Description:
This routine adds a new port to a multiport device while that device is
running.
Arguments:
Context - Actually a pointer to the device extension of the root
device we are adding a port to.
Return Value:
Always TRUE
--*/
{
PSERIAL_DEVICE_EXTENSION pDevExt = (PSERIAL_DEVICE_EXTENSION)Context;
PSERIAL_MULTIPORT_DISPATCH pOurIsrContext
= (PSERIAL_MULTIPORT_DISPATCH)pDevExt->OurIsrContext;
PSERIAL_DEVICE_EXTENSION pNewExt
= (PSERIAL_DEVICE_EXTENSION)pDevExt->NewExtension;
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, ">SerialAddToMulti(%X)\n", pDevExt);
if (pDevExt->Indexed == FALSE) {
pOurIsrContext->UsablePortMask |= 1 << (pDevExt->NewPortIndex - 1);
pOurIsrContext->MaskInverted |= pDevExt->NewMaskInverted;
}
//
// Add us to the linked list of common interrupt objects if we are not
// already in it. We may be if there is another device besides our
// multiport card.
//
if (IsListEmpty(&pNewExt->CommonInterruptObject)) {
InsertTailList(&pDevExt->CommonInterruptObject,
&pNewExt->CommonInterruptObject);
}
//
// Give us the list of contexts also
//
pNewExt->OurIsrContext = pOurIsrContext;
//
// Add us to the list of our siblings
//
InsertTailList(&pDevExt->MultiportSiblings, &pNewExt->MultiportSiblings);
SerialDbgPrintEx(SERDIAG1, "Adding to multi...\n");
SerialDbgPrintEx(SERDIAG1, "old ext %X\n", pDevExt);
//
// Map us in so the ISR can find us.
//
pOurIsrContext->Extensions[pDevExt->NewPortIndex - 1]
= pDevExt->NewExtension;
pNewExt->TopLevelOurIsr = pDevExt->TopLevelOurIsr;
pNewExt->TopLevelOurIsrContext = pDevExt->TopLevelOurIsrContext;
SerialDbgPrintEx(DPFLTR_TRACE_LEVEL, "<SerialAddToMulti TRUE\n");
return TRUE;
}
NTSTATUS
SerialInitMultiPort(IN PSERIAL_DEVICE_EXTENSION PDevExt,
IN PCONFIG_DATA PConfigData, IN PDEVICE_OBJECT PDevObj)
/*++
Routine Description:
This routine initializes a multiport device by adding a port to an existing
one.
Arguments:
PDevExt - pointer to the device extension of the root of the multiport
device.
PConfigData - pointer to the config data for the new port
PDevObj - pointer to the devobj for the new port
Return Value:
STATUS_SUCCESS on success, appropriate error on failure.
--*/
{
PSERIAL_DEVICE_EXTENSION pOurIsrContext
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -