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

📄 pnp.c

📁 串口Windows驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
      return 1200U;
   }

   if (Bauds & SERIAL_BAUD_600) {
      return 600U;
   }

   if (Bauds & SERIAL_BAUD_300) {
      return 300U;
   }

   if (Bauds & SERIAL_BAUD_150) {
      return 150U;
   }

   if (Bauds & SERIAL_BAUD_134_5) {
      return 135U; // Close enough
   }

   if (Bauds & SERIAL_BAUD_110) {
      return 110U;
   }

   if (Bauds & SERIAL_BAUD_075) {
      return 75U;
   }

   //
   // We're in bad shape
   //

   return 0;
}

VOID
SerialAddToAllDevs(PLIST_ENTRY PListEntry)
{
   KIRQL oldIrql;

   KeAcquireSpinLock(&SerialGlobals.GlobalsSpinLock, &oldIrql);

   InsertTailList(&SerialGlobals.AllDevObjs, PListEntry);

   KeReleaseSpinLock(&SerialGlobals.GlobalsSpinLock, oldIrql);
}



NTSTATUS
SerialFinishStartDevice(IN PDEVICE_OBJECT PDevObj,
                        IN PCM_RESOURCE_LIST PResList,
                        IN PCM_RESOURCE_LIST PTrResList,
                        PSERIAL_USER_DATA PUserData)
/*++

Routine Description:

    This routine does serial-specific procedures to start a device.  It
    does this either for a legacy device detected by its registry entries,
    or for a PnP device after the start IRP has been sent down the stack.


Arguments:

   PDevObj    -  Pointer to the devobj that is starting

   PResList   -  Pointer to the untranslated resources needed by this device

   PTrResList -  Pointer to the translated resources needed by this device

   PUserData  -  Pointer to the user-specified resources/attributes


  Return Value:

    STATUS_SUCCESS on success, something else appropriate on failure


--*/

{
   PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
   NTSTATUS status;
   PCONFIG_DATA pConfig;
   HANDLE pnpKey;
   ULONG one = 1;
   BOOLEAN allocedUserData = FALSE;
   KIRQL oldIrql;

   PAGED_CODE();

   //
   // See if this is a restart, and if so don't reallocate the world
   //

   if ((pDevExt->Flags & SERIAL_FLAGS_STOPPED)
       && (pDevExt->Flags & SERIAL_FLAGS_STARTED)) {
      SerialClearFlags(pDevExt, SERIAL_FLAGS_STOPPED);

      pDevExt->PNPState = SERIAL_PNP_RESTARTING;

      //
      // Re-init resource-related things in the extension
      //

      pDevExt->TopLevelOurIsr = NULL;
      pDevExt->TopLevelOurIsrContext = NULL;

      pDevExt->OriginalController = SerialPhysicalZero;
      pDevExt->OriginalInterruptStatus = SerialPhysicalZero;

      pDevExt->OurIsr = NULL;
      pDevExt->OurIsrContext = NULL;

      pDevExt->Controller = NULL;
      pDevExt->InterruptStatus = NULL;
      pDevExt->Interrupt = NULL;

      pDevExt->SpanOfController = 0;
      pDevExt->SpanOfInterruptStatus = 0;

      pDevExt->Vector = 0;
      pDevExt->Irql = 0;
      pDevExt->OriginalVector = 0;
      pDevExt->OriginalIrql = 0;
      pDevExt->AddressSpace = 0;
      pDevExt->BusNumber = 0;
      pDevExt->InterfaceType = 0;

      pDevExt->CIsrSw = NULL;

      ASSERT(PUserData == NULL);


      PUserData = ExAllocatePool(PagedPool, sizeof(SERIAL_USER_DATA));

      if (PUserData == NULL) {
         return STATUS_INSUFFICIENT_RESOURCES;
      }

      allocedUserData = TRUE;

      RtlZeroMemory(PUserData, sizeof(SERIAL_USER_DATA));

      PUserData->DisablePort = FALSE;
      PUserData->UserClockRate = pDevExt->ClockRate;
      PUserData->TxFIFO = pDevExt->TxFifoAmount;
      PUserData->PermitShareDefault = pDevExt->PermitShare;


      //
      // Map betweeen trigger and amount
      //

      switch (pDevExt->RxFifoTrigger) {
      case SERIAL_1_BYTE_HIGH_WATER:
         PUserData->RxFIFO = 1;
         break;

      case SERIAL_4_BYTE_HIGH_WATER:
         PUserData->RxFIFO = 4;
         break;

      case SERIAL_8_BYTE_HIGH_WATER:
         PUserData->RxFIFO = 8;
         break;

      case SERIAL_14_BYTE_HIGH_WATER:
         PUserData->RxFIFO = 14;
         break;

      default:
         PUserData->RxFIFO = 1;
      }
   } else {
      //
      // Mark as serenumerable -- toss status because we can
      // still start without this key.
      //

      status = IoOpenDeviceRegistryKey(pDevExt->Pdo,
                                       PLUGPLAY_REGKEY_DEVICE,
                                       STANDARD_RIGHTS_WRITE, &pnpKey);

      if (NT_SUCCESS(status)) {
         ULONG powerPolicy = 0;
         ULONG powerOnClose = 0;

         //
         // Find out if we own power policy
         //

         SerialGetRegistryKeyValue(pnpKey, L"SerialRelinquishPowerPolicy",
                                   sizeof(L"SerialRelinquishPowerPolicy"),
                                   &powerPolicy, sizeof(ULONG));

         pDevExt->OwnsPowerPolicy = powerPolicy ? FALSE : TRUE;

         SerialGetRegistryKeyValue(pnpKey, L"EnablePowerManagement",
                                   sizeof(L"EnablePowerManagement"),
                                   &powerOnClose, sizeof(ULONG));

         pDevExt->RetainPowerOnClose = powerOnClose ? TRUE : FALSE;

         ZwClose(pnpKey);
      }
   }

   //
   // Allocate the config record.
   //

   pConfig = ExAllocatePool (PagedPool, sizeof(CONFIG_DATA));

   if (pConfig == NULL) {

      SerialLogError(pDevExt->DriverObject, NULL, SerialPhysicalZero,
                     SerialPhysicalZero, 0, 0, 0, 37, STATUS_SUCCESS,
                     SERIAL_INSUFFICIENT_RESOURCES, 0, NULL, 0, NULL);

      SerialDbgPrintEx(SERERRORS, "Couldn't allocate memory for the\n"
                             "------  user configuration record\n");

      status = STATUS_INSUFFICIENT_RESOURCES;
      goto SerialFinishStartDeviceError;
   }

   RtlZeroMemory(pConfig, sizeof(CONFIG_DATA));


   //
   // Get the configuration info for the device.
   //

   status = SerialGetPortInfo(PDevObj, PResList, PTrResList, pConfig,
                              PUserData);

   if (!NT_SUCCESS(status)) {
      goto SerialFinishStartDeviceError;
   }


   //
   // See if we are in the proper power state.
   //



   if (pDevExt->PowerState != PowerDeviceD0) {

      status = SerialGotoPowerState(pDevExt->Pdo, pDevExt, PowerDeviceD0);

      if (!NT_SUCCESS(status)) {
         goto SerialFinishStartDeviceError;
      }
   }

   //
   // Find and initialize the controller
   //

   status = SerialFindInitController(PDevObj, pConfig);

   if (!NT_SUCCESS(status)) {
      goto SerialFinishStartDeviceError;
   }


   //
   // The hardware that is set up to NOT interrupt, connect an interrupt.
   //

   //
   // If a device doesn't already have an interrupt and it has an isr then
   // we attempt to connect to the interrupt if it is not shareing with other
   // serial devices.  If we fail to connect to an  interrupt we will delete
   // this device.
   //

   if (pDevExt != NULL) {
      SerialDbgPrintEx(SERDIAG5, "pDevExt: Interrupt %x\n"
                       "-------               OurIsr %x\n", pDevExt->Interrupt,
                       pDevExt->OurIsr);
   } else {
      SerialDbgPrintEx(SERERRORS, "SerialFinishStartDevice got NULL "
                       "pDevExt\n");
   }

   if ((!pDevExt->Interrupt) && (pDevExt->OurIsr)) {

      SerialDbgPrintEx(SERDIAG5,
                       "About to connect to interrupt for port %wZ\n"
                       "------- address of extension is %x\n",
                       &pDevExt->DeviceName, pDevExt);

      SerialDbgPrintEx(SERDIAG5, "IoConnectInterrupt Args:\n"
                                "Interrupt           %x\n"
                                "OurIsr              %x\n"
                                "OurIsrContext       %x\n"
                                "NULL\n"
                                "Vector              %x\n"
                                "Irql                %x\n"
                                "InterruptMode       %x\n"
                                "InterruptShareable  %x\n"
                                "ProcessorAffinity   %x\n"
                                "FALSE\n",
                                &pDevExt->Interrupt,
                                SerialCIsrSw,
                                pDevExt->CIsrSw,
                                pDevExt->Vector,
                                pDevExt->Irql,
                                pConfig->InterruptMode,
                                pDevExt->InterruptShareable,
                                pConfig->Affinity
                               );

      //
      // Do a just in time construction of the ISR switch.
      //

      pDevExt->CIsrSw->IsrFunc = pDevExt->OurIsr;
      pDevExt->CIsrSw->Context = pDevExt->OurIsrContext;

      status = IoConnectInterrupt(&pDevExt->Interrupt, SerialCIsrSw,
                                  pDevExt->CIsrSw, NULL,
                                  pDevExt->Vector, pDevExt->Irql,
                                  pDevExt->Irql,
                                  pConfig->InterruptMode,
                                  pDevExt->InterruptShareable,
                                  pConfig->Affinity, FALSE);

      if (!NT_SUCCESS(status)) {

         //
         // Hmmm, how'd that happen?  Somebody either
         // didn't report their resources, or they
         // sneaked in since the last time I looked.
         //
         // Oh well,  delete this device.
         //

         SerialDbgPrintEx(SERERRORS, "Couldn't connect to interrupt for %wZ\n",
                          &pDevExt->DeviceName);

         SerialDbgPrintEx(SERERRORS, "IoConnectInterrupt Args:\n"
                                "Interrupt           %x\n"
                                "OurIsr              %x\n"
                                "OurIsrContext       %x\n"
                                "NULL\n"
                                "Vector              %x\n"
                                "Irql                %x\n"
                                "InterruptMode       %x\n"
                                "InterruptShareable  %x\n"
                                "ProcessorAffinity   %x\n"
                                "FALSE\n",
                                &pDevExt->Interrupt,
                                SerialCIsrSw,
                                pDevExt->CIsrSw,
                                pDevExt->Vector,
                                pDevExt->Irql,
                                pConfig->InterruptMode,
                                pDevExt->InterruptShareable,
                                pConfig->Affinity);



         SerialLogError(PDevObj->DriverObject, PDevObj,
                        pDevExt->OriginalController,
                        SerialPhysicalZero, 0, 0, 0, 1, status,
                        SERIAL_UNREPORTED_IRQL_CONFLICT,
                        pDevExt->DeviceName.Length + sizeof(WCHAR),
                        pDevExt->DeviceName.Buffer, 0, NULL);

         status = SERIAL_UNREPORTED_IRQL_CONFLICT;
         goto SerialFinishStartDeviceError;

      }
   }

   SerialDbgPrintEx(SERDIAG5, "Connected interrupt %08X\n", pDevExt->Interrupt);


   //
   // Add the PDevObj to the master list
   //

   SerialAddToAllDevs(&pDevExt->AllDevObjs);


   //
   // Reset the device.
   //


   //
   // While the device isn't open, disable all interrupts.
   //

   DISABLE_ALL_INTERRUPTS (pDevExt->Controller);


   WRITE_MODEM_CONTROL(pDevExt->Controller, (UCHAR)0);

   //
   // This should set up everything as it should be when
   // a device is to be opened.  We do need to lower the
   // modem lines, and disable the recalcitrant fifo
   // so that it will show up if the user boots to dos.
   //

   KeSynchronizeExecution(
                         pDevExt->Interrupt,
                         SerialReset,
                         pDevExt
                         );

   KeSynchronizeExecution( //Disables the fifo.
                           pDevExt->Interrupt,
                           SerialMarkClose,
                           pDevExt
                         );

   KeSynchronizeExecution(
                         pDevExt->Interrupt,
                         SerialClrRTS,
                         pDevExt
                         );

   KeSynchronizeExecution(
                         pDevExt->Interrupt,
                         SerialClrDTR,
                         pDevExt
                         );

   if (pDevExt->PNPState == SERIAL_PNP_ADDED ) {
      //
      // Do the external naming now that the device is accessible.
      //

      status = SerialDoExternalNaming(pDevExt, pDevExt->DeviceObject->
                                      DriverObject);


      if (!NT_SUCCESS(status)) {
         SerialDbgPrintEx(SERERRORS, "External Naming Failed - Status %x\n",
                          status);

         //
         // Allow the device to start anyhow
         //

         status = STATUS_SUCCESS;
      }
   } else {
      SerialDbgPrintEx(SERPNPPOWER, "Not doing external naming -- state is %x"
                       "\n", pDevExt->PNPState);

⌨️ 快捷键说明

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