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

📄 initunlo.c

📁 怎样在win2000下构造驱动程序znsoft_Serial2000_demo.ZIP
💻 C
📖 第 1 页 / 共 5 页
字号:
Routine Description:

    Releases resources (not pool) stored in the device extension.

Arguments:

    PDevExt - Pointer to the device extension to release resources from.

Return Value:

    VOID

--*/
{
   PAGED_CODE();

   SerialDump(SERTRACECALLS,("SERIAL: Enter SerialReleaseResources\n"));

   //
   // Remove us from any lists we may be on
   //

   if (PDevExt->Interrupt != NULL) {
      KeSynchronizeExecution(PDevExt->Interrupt, SerialCleanLists, PDevExt);
   }

   //
   // SerialCleanLists can remove our interrupt from us...
   //

   if (PDevExt->Interrupt != NULL) {
      //
      // Stop servicing interrupts if we are the owner
      //

      SerialDump(SERPNPPOWER,
                 ("SERIAL: Release - disconnecting interrupt %08X\n",
                  PDevExt->Interrupt));

      IoDisconnectInterrupt(PDevExt->Interrupt);
      PDevExt->Interrupt = NULL;

      if (PDevExt->CIsrSw != NULL) {
         ExFreePool(PDevExt->CIsrSw);
         PDevExt->CIsrSw = NULL;
      }
   }

   if (PDevExt->PortOnAMultiportCard) {
       ULONG i;

       //
       // If we are the last device, free this memory
       //

       for (i = 0; i < SERIAL_MAX_PORTS_INDEXED; i++) {
          if (((PSERIAL_MULTIPORT_DISPATCH)PDevExt->OurIsrContext)
              ->Extensions[i] != NULL) {
             break;
          }
       }

       if (i == SERIAL_MAX_PORTS_INDEXED) {
          SerialDump(SERPNPPOWER,("SERIAL: Release - freeing multi context\n"));
          ExFreePool(PDevExt->OurIsrContext);
       }
    }


   //
   // Stop handling timers
   //

   SerialCancelTimer(&PDevExt->ReadRequestTotalTimer, PDevExt);
   SerialCancelTimer(&PDevExt->ReadRequestIntervalTimer, PDevExt);
   SerialCancelTimer(&PDevExt->WriteRequestTotalTimer, PDevExt);
   SerialCancelTimer(&PDevExt->ImmediateTotalTimer, PDevExt);
   SerialCancelTimer(&PDevExt->XoffCountTimer, PDevExt);
   SerialCancelTimer(&PDevExt->LowerRTSTimer, PDevExt);

   //
   // Stop servicing DPC's
   //

   SerialRemoveQueueDpc(&PDevExt->CompleteWriteDpc, PDevExt);
   SerialRemoveQueueDpc(&PDevExt->CompleteReadDpc, PDevExt);
   SerialRemoveQueueDpc(&PDevExt->TotalReadTimeoutDpc, PDevExt);
   SerialRemoveQueueDpc(&PDevExt->IntervalReadTimeoutDpc, PDevExt);
   SerialRemoveQueueDpc(&PDevExt->TotalWriteTimeoutDpc, PDevExt);
   SerialRemoveQueueDpc(&PDevExt->CommErrorDpc, PDevExt);
   SerialRemoveQueueDpc(&PDevExt->CompleteImmediateDpc, PDevExt);
   SerialRemoveQueueDpc(&PDevExt->TotalImmediateTimeoutDpc, PDevExt);
   SerialRemoveQueueDpc(&PDevExt->CommWaitDpc, PDevExt);
   SerialRemoveQueueDpc(&PDevExt->XoffCountTimeoutDpc, PDevExt);
   SerialRemoveQueueDpc(&PDevExt->XoffCountCompleteDpc, PDevExt);
   SerialRemoveQueueDpc(&PDevExt->StartTimerLowerRTSDpc, PDevExt);
   SerialRemoveQueueDpc(&PDevExt->PerhapsLowerRTSDpc, PDevExt);



   //
   // If necessary, unmap the device registers.
   //

   if (PDevExt->UnMapRegisters) {
      MmUnmapIoSpace(PDevExt->Controller, PDevExt->SpanOfController);
   }

   if (PDevExt->UnMapStatus) {
      MmUnmapIoSpace(PDevExt->InterruptStatus,
                     PDevExt->SpanOfInterruptStatus);
   }

   SerialDump(SERTRACECALLS,("SERIAL: Leave 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();

   SerialDump(SERTRACECALLS,("SERIAL: Enter SerialPrepareRemove\n"));

   //
   // 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);

   return TRUE;
}


VOID
SerialDisableInterfacesResources(IN PDEVICE_OBJECT PDevObj,
                                 BOOLEAN DisableUART)
{
   PSERIAL_DEVICE_EXTENSION pDevExt
      = (PSERIAL_DEVICE_EXTENSION)PDevObj->DeviceExtension;

   PAGED_CODE();

   SerialDump(SERTRACECALLS,("SERIAL: Enter SerialDisableInterfaces\n"));

   //
   // Only do these many things if the device has started and still
   // has resources allocated
   //

   if (pDevExt->Flags & SERIAL_FLAGS_STARTED) {
       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);

   SerialDump(SERTRACECALLS,("SERIAL: Exit 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();

   SerialDump(SERTRACECALLS,("SERIAL: Enter SerialRemoveDevObj\n"));

   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);


   SerialDump(SERTRACECALLS,("SERIAL: Leave SerialRemoveDevObj\n"));

   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;

   SerialDump (SERTRACECALLS,("SERIAL: Enter SerialKillPendingIrps\n"));

   //
   // 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);


    SerialDump (SERTRACECALLS,("SERIAL: Leave 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;

   SerialDump (SERTRACECALLS,("SERIAL: Enter SerialSingleToMulti\n"));

   //
   // 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;
   }

   SerialDump (SERTRACECALLS,("SERIAL: Leave SerialSingleToMulti\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:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -