⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 initunlo.c

📁 串口Windows驱动
💻 C
📖 第 1 页 / 共 5 页
字号:

   //
   // 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 + -