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

📄 initunlo.c

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

    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;


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

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

   SerialDump(SERDIAG1, ("SERIAL: Adding to multi...\n"));
   SerialDump(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;

   SerialDump (SERTRACECALLS,("SERIAL: Leave SerialAddToMulti\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
      = (PSERIAL_DEVICE_EXTENSION)PDevExt->OurIsrContext;
   PSERIAL_DEVICE_EXTENSION pNewExt
      = (PSERIAL_DEVICE_EXTENSION)PDevObj->DeviceExtension;
   NTSTATUS status;
   PSERIAL_MULTIPORT_DISPATCH pDispatch;

   PAGED_CODE();


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

   //
   // Allow him to share our CISRsw and interrupt object
   //

   pNewExt->CIsrSw = PDevExt->CIsrSw;
   pNewExt->Interrupt = PDevExt->Interrupt;

   //
   // First, see if we can initialize the one we have found
   //

   status = SerialInitOneController(PDevObj, PConfigData);

   if (!NT_SUCCESS(status)) {
      SerialDump (SERTRACECALLS,("SERIAL: Leave SerialInitMultiPort\n"));
      return status;
   }

   //
   // OK.  He's good to go.  Find the root controller.  He may
   // currently be a single, so we have to change him to multi.
   //

   if (PDevExt->PortOnAMultiportCard != TRUE) {

      pDispatch = PDevExt->NewExtension
         = ExAllocatePool(NonPagedPool, sizeof(SERIAL_MULTIPORT_DISPATCH));

      if (pDispatch == NULL) {
         // FAIL and CLEANUP
         SerialDump (SERTRACECALLS,("SERIAL: Leave SerialInitMultiPort\n"));
         return STATUS_INSUFFICIENT_RESOURCES;
      }

      RtlZeroMemory(pDispatch, sizeof(*pDispatch));
      KeSynchronizeExecution(PDevExt->Interrupt, SerialSingleToMulti, PDevExt);
   }

   //
   // Update some important fields
   //

   ((PSERIAL_DEVICE_EXTENSION)PDevObj->DeviceExtension)->PortOnAMultiportCard
      = TRUE;
   ((PSERIAL_DEVICE_EXTENSION)PDevObj->DeviceExtension)->OurIsr = NULL;


   PDevExt->NewPortIndex = PConfigData->PortIndex;
   PDevExt->NewMaskInverted = PConfigData->MaskInverted;
   PDevExt->NewExtension = PDevObj->DeviceExtension;

   //
   // Now, we can add the new guy.  He will be hooked in
   // immediately, so we need to be able to handle interrupts.
   //

   KeSynchronizeExecution(PDevExt->Interrupt, SerialAddToMulti, PDevExt);

   SerialDump (SERTRACECALLS,("SERIAL: Leave SerialInitMultiPort\n"));
   return STATUS_SUCCESS;
}



NTSTATUS
SerialInitController(IN PDEVICE_OBJECT PDevObj, IN PCONFIG_DATA PConfigData)

/*++

Routine Description:

    Really too many things to mention here.  In general initializes
    kernel synchronization structures, allocates the typeahead buffer,
    sets up defaults, etc.

Arguments:

    PDevObj       - Device object for the device to be started

    PConfigData   - Pointer to a record for a single port.

Return Value:

    STATUS_SUCCCESS if everything went ok.  A !NT_SUCCESS status
    otherwise.

--*/

{

   PSERIAL_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;

   //
   // This will hold the string that we need to use to describe
   // the name of the device to the IO system.
   //

   UNICODE_STRING uniNameString;

   //
   // Holds the NT Status that is returned from each call to the
   // kernel and executive.
   //

   NTSTATUS status = STATUS_SUCCESS;

   //
   // Indicates that a conflict was detected for resources
   // used by this device.
   //

   BOOLEAN conflictDetected = FALSE;

   //
   // Indicates if we allocated an ISR switch
   //

   BOOLEAN allocedISRSw = FALSE;

   PAGED_CODE();


   SerialDump(
             SERDIAG1,
             ("SERIAL: Initializing for configuration record of %wZ\n",
              &pDevExt->DeviceName)
             );

   //
   // This compare is done using **untranslated** values since that is what
   // the kernel shoves in regardless of the architecture.
   //

   if ((*KdComPortInUse) == ((PUCHAR)(PConfigData->Controller.LowPart))) {
      SerialDump(SERERRORS, ("SERIAL: Kernel debugger is using port at address "
                             "%x\n"
                             "------  Serial driver will not load port\n",
                             *KdComPortInUse));

      SerialLogError(
                    PDevObj->DriverObject,
                    NULL,
                    PConfigData->TrController,
                    SerialPhysicalZero,
                    0,
                    0,
                    0,
                    3,
                    STATUS_SUCCESS,
                    SERIAL_KERNEL_DEBUGGER_ACTIVE,
                    pDevExt->DeviceName.Length+sizeof(WCHAR),
                    pDevExt->DeviceName.Buffer,
                    0,
                    NULL
                    );

      return STATUS_INSUFFICIENT_RESOURCES;
   }


   if (pDevExt->CIsrSw == NULL) {
      if ((pDevExt->CIsrSw
           = ExAllocatePool(NonPagedPool, sizeof(SERIAL_CISR_SW))) == NULL) {
         return STATUS_INSUFFICIENT_RESOURCES;
      }

      InitializeListHead(&pDevExt->CIsrSw->SharerList);

      allocedISRSw = TRUE;
   }

   //
   // Propagate that it is a jensen.
   //

   pDevExt->Jensen = PConfigData->Jensen;


   //
   // Initialize the spinlock associated with fields read (& set)
   // by IO Control functions and the flags spinlock.
   //

   KeInitializeSpinLock(&pDevExt->ControlLock);
   KeInitializeSpinLock(&pDevExt->FlagsLock);


   //
   // Initialize the timers used to timeout operations.
   //

   KeInitializeTimer(&pDevExt->ReadRequestTotalTimer);
   KeInitializeTimer(&pDevExt->ReadRequestIntervalTimer);
   KeInitializeTimer(&pDevExt->WriteRequestTotalTimer);
   KeInitializeTimer(&pDevExt->ImmediateTotalTimer);
   KeInitializeTimer(&pDevExt->XoffCountTimer);
   KeInitializeTimer(&pDevExt->LowerRTSTimer);


   //
   // Intialialize the dpcs that will be used to complete
   // or timeout various IO operations.
   //

   KeInitializeDpc(&pDevExt->CompleteWriteDpc, SerialCompleteWrite, pDevExt);
   KeInitializeDpc(&pDevExt->CompleteReadDpc, SerialCompleteRead, pDevExt);
   KeInitializeDpc(&pDevExt->TotalReadTimeoutDpc, SerialReadTimeout, pDevExt);
   KeInitializeDpc(&pDevExt->IntervalReadTimeoutDpc, SerialIntervalReadTimeout,
                   pDevExt);
   KeInitializeDpc(&pDevExt->TotalWriteTimeoutDpc, SerialWriteTimeout, pDevExt);
   KeInitializeDpc(&pDevExt->CommErrorDpc, SerialCommError, pDevExt);
   KeInitializeDpc(&pDevExt->CompleteImmediateDpc, SerialCompleteImmediate,
                   pDevExt);
   KeInitializeDpc(&pDevExt->TotalImmediateTimeoutDpc, SerialTimeoutImmediate,
                   pDevExt);
   KeInitializeDpc(&pDevExt->CommWaitDpc, SerialCompleteWait, pDevExt);
   KeInitializeDpc(&pDevExt->XoffCountTimeoutDpc, SerialTimeoutXoff, pDevExt);
   KeInitializeDpc(&pDevExt->XoffCountCompleteDpc, SerialCompleteXoff, pDevExt);
   KeInitializeDpc(&pDevExt->StartTimerLowerRTSDpc, SerialStartTimerLowerRTS,
                   pDevExt);
   KeInitializeDpc(&pDevExt->PerhapsLowerRTSDpc, SerialInvokePerhapsLowerRTS,
                   pDevExt);
   KeInitializeDpc(&pDevExt->IsrUnlockPagesDpc, SerialUnlockPages, pDevExt);

#if 0 // DBG
   //
   // Init debug stuff
   //

   pDevExt->DpcQueued[0].Dpc = &pDevExt->CompleteWriteDpc;
   pDevExt->DpcQueued[1].Dpc = &pDevExt->CompleteReadDpc;
   pDevExt->DpcQueued[2].Dpc = &pDevExt->TotalReadTimeoutDpc;
   pDevExt->DpcQueued[3].Dpc = &pDevExt->IntervalReadTimeoutDpc;
   pDevExt->DpcQueued[4].Dpc = &pDevExt->TotalWriteTimeoutDpc;
   pDevExt->DpcQueued[5].Dpc = &pDevExt->CommErrorDpc;
   pDevExt->DpcQueued[6].Dpc = &pDevExt->CompleteImmediateDpc;
   pDevExt->DpcQueued[7].Dpc = &pDevExt->TotalImmediateTimeoutDpc;
   pDevExt->DpcQueued[8].Dpc = &pDevExt->CommWaitDpc;
   pDevExt->DpcQueued[9].Dpc = &pDevExt->XoffCountTimeoutDpc;
   pDevExt->DpcQueued[10].Dpc = &pDevExt->XoffCountCompleteDpc;
   pDevExt->DpcQueued[11].Dpc = &pDevExt->StartTimerLowerRTSDpc;
   pDevExt->DpcQueued[12].Dpc = &pDevExt->PerhapsLowerRTSDpc;
   pDevExt->DpcQueued[13].Dpc = &pDevExt->IsrUnlockPagesDpc;

#endif

   if (!((PConfigData->ClockRate == 1843200) ||
         (PConfigData->ClockRate == 3072000) ||
         (PConfigData->ClockRate == 4233600) ||
         (PConfigData->ClockRate == 8000000))) {

      SerialLogError(
                    PDevObj->DriverObject,
                    PDevObj,
                    PConfigData->TrController,
                    SerialPhysicalZero,
                    0,
                    0,
                    0,
                    6,
                    STATUS_SUCCESS,
                    SERIAL_UNSUPPORTED_CLOCK_RATE,
                    pDevExt->DeviceName.Length+sizeof(WCHAR),
                    pDevExt->DeviceName.Buffer,
                    0,
                    NULL
                    );

      SerialDump(
                SERERRORS,
                ("SERIAL: Invalid clock rate specified for %wZ\n",
                 &pDevExt->DeviceName)
                );

      status = STATUS_SERIAL_NO_DEVICE_INITED;
      goto ExtensionCleanup;

   }


   //
   // Save the value of clock input to the part.  We use this to calculate
   // the divisor latch value.  The value is in Hertz.
   //

   pDevExt->ClockRate = PConfigData->ClockRate;





   //
   // Map the memory for the control registers for the serial device
   // into virtual memory.
   //
   pDevExt->Controller =
      SerialGetMappedAddress(PConfigData->InterfaceType,
                             PConfigData->BusNumber,
                             PConfigData->TrController,
                             PConfigData->SpanOfController,
                             (BOOLEAN)PConfigData->AddressSpace,
                             &pDevExt->UnMapRegisters);

   if (!pDevExt->Controller) {

      SerialLogError(
                    PDevObj->DriverObject,
                    pDevExt->DeviceObject,
                    PConfigData->TrController,
                    SerialPhysicalZero,
                    0,
                    0,
                    0,
                    7,
                    STATUS_SUCCESS,
                    SERIAL_REGISTERS_NOT_MAPPED,
                    pDevExt->DeviceName.Length+sizeof(WCHAR),
                    pDevExt->DeviceName.Buffer,
                    0,
                    NULL
                    );

      SerialDump(
                SERERRORS,
                ("SERIAL: Could not map memory for device registers for %wZ\n",
                 &pDevExt->DeviceName)
                );

      pDevExt->UnMapRegisters = FALSE;
      status = STATUS_NONE_MAPPED;
      goto ExtensionCleanup;

   }

   pDevExt->AddressSpace          = PConfigData->AddressSpace;
   pDevExt->OriginalController    = PConfigData->Controller;
   pDevExt->SpanOfController      = PConfigData->SpanOfController;


   //
   // if we have an interrupt status then map it.
   //

   pDevExt->InterruptStatus =
      (PUCHAR)PConfigData->TrInterruptStatus.QuadPart;

   if (pDevExt->InterruptStatus) {

      pDevExt->InterruptStatus
         = SerialGetMappedAddress(PConfigData->InterfaceType,
                                  PConfigData->BusNumber,
                                  PConfigData->TrInterruptStatus,
                                  PConfigData->SpanOfInterruptStatus,
                                  (BOOLEAN)PConfigData->AddressSpace,
                                  &pDevExt->UnMapStatus);


      if (!pDevExt->InterruptStatus) {

         SerialLogError(
                       PDevObj->DriverObject,
                       PDevObj,
                       PConfigData->TrController,
                       SerialPhysicalZero,
                       0,
                       0,
                       0,
                       8,
                       STATUS_SUCCESS,
                       SERIAL_REGISTERS_NOT_MAPPED,
                       pDevExt->DeviceName.Length+sizeof(WCHAR),
                       pDevExt->DeviceName.Buffer,
                       0,
                       NULL
                       );

⌨️ 快捷键说明

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