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

📄 pnp.c

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

   if (Bauds & SERIAL_BAUD_4800) {
      return 4800U;
   }

   if (Bauds & SERIAL_BAUD_2400) {
      return 2400U;
   }

   if (Bauds & SERIAL_BAUD_1800) {
      return 1800U;
   }

   if (Bauds & SERIAL_BAUD_1200) {
      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;
}



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;

   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;

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

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

         pDevExt->OwnsPowerPolicy = powerPolicy ? FALSE : TRUE;


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

      SerialDump(SERERRORS, ("SERIAL: 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) {
      SerialDump(SERDIAG5, ("SERIAL: pDevExt: Interrupt %x\n"
                            "-------               OurIsr %x\n",
                            pDevExt->Interrupt, pDevExt->OurIsr));
   } else {
      SerialDump(SERERRORS, ("SERIAL: SerialFinishStartDevice got NULL "
                           "pDevExt\n"));
   }

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

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

      SerialDump(SERDIAG5, ("SERIAL: 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.
         //

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

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

      }
   }

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


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

   InsertTailList(&SerialGlobals.AllDevObjs, &pDevExt->AllDevObjs);


   //
   // Reset the device.
   //


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

   DISABLE_ALL_INTERRUPTS (pDevExt->Controller);


   if (pDevExt->Jensen) {

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

   } else {

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

⌨️ 快捷键说明

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