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

📄 pnp.c

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

Copyright (c) 1991, 1992, 1993 - 1997 Microsoft Corporation

Module Name:

    pnp.c

Abstract:

    This module contains the code that handles the plug and play
    IRPs for the serial driver.

Environment:

    Kernel mode

Revision History :


--*/

#include "precomp.h"

#define ALLF    0xffffffff

static const PHYSICAL_ADDRESS SerialPhysicalZero = {0};



#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGESRP0, SerialCreateDevObj)
#pragma alloc_text(PAGESRP0, SerialAddDevice)
#pragma alloc_text(PAGESRP0, SerialPnpDispatch)
#pragma alloc_text(PAGESRP0, SerialStartDevice)
#pragma alloc_text(PAGESRP0, SerialFinishStartDevice)
#pragma alloc_text(PAGESRP0, SerialGetPortInfo)
#pragma alloc_text(PAGESRP0, SerialDoExternalNaming)
#pragma alloc_text(PAGESRP0, SerialReportMaxBaudRate)
#pragma alloc_text(PAGESRP0, SerialControllerCallBack)
#pragma alloc_text(PAGESRP0, SerialItemCallBack)
#pragma alloc_text(PAGESRP0, SerialUndoExternalNaming)
#endif // ALLOC_PRAGMA

//
// Instantiate the GUID
//

#if !defined(FAR)
#define FAR
#endif // !defined(FAR)

#include <initguid.h>

DEFINE_GUID(GUID_CLASS_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08,
            0x00, 0x3e, 0x30, 0x1f, 0x73);


#if DBG

UCHAR *SerSystemCapString[] = {
   "PowerSystemUnspecified",
   "PowerSystemWorking",
   "PowerSystemSleeping1",
   "PowerSystemSleeping2",
   "PowerSystemSleeping3",
   "PowerSystemHibernate",
   "PowerSystemShutdown",
   "PowerSystemMaximum"
};

UCHAR *SerDeviceCapString[] = {
   "PowerDeviceUnspecified",
   "PowerDeviceD0",
   "PowerDeviceD1",
   "PowerDeviceD2",
   "PowerDeviceD3",
   "PowerDeviceMaximum"
};

#endif // DBG


NTSTATUS
SerialSyncCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
                     IN PKEVENT SerialSyncEvent)
{
   KeSetEvent(SerialSyncEvent, IO_NO_INCREMENT, FALSE);
   return STATUS_MORE_PROCESSING_REQUIRED;
}


NTSTATUS
SerialCreateDevObj(IN PDRIVER_OBJECT DriverObject,
                   OUT PDEVICE_OBJECT *NewDeviceObject)

/*++

Routine Description:

    This routine will create and initialize a functional device object to
    be attached to a Serial controller PDO.

Arguments:

    DriverObject - a pointer to the driver object this is created under
    NewDeviceObject - a location to store the pointer to the new device object

Return Value:

    STATUS_SUCCESS if everything was successful
    reason for failure otherwise

--*/

{
   UNICODE_STRING deviceObjName;
   PDEVICE_OBJECT deviceObject = NULL;
   PSERIAL_DEVICE_EXTENSION pDevExt;
   NTSTATUS status = STATUS_SUCCESS;
   static ULONG currentInstance = 0;
   UNICODE_STRING instanceStr;
   WCHAR instanceNumberBuffer[20];


   PAGED_CODE();

   SerialDbgPrintEx(SERTRACECALLS, "EnterSerialCreateDevObj\n");

   //
   // Zero out allocated memory pointers so we know if they must be freed
   //

   RtlZeroMemory(&deviceObjName, sizeof(UNICODE_STRING));

   deviceObjName.MaximumLength = DEVICE_OBJECT_NAME_LENGTH * sizeof(WCHAR);
   deviceObjName.Buffer = ExAllocatePool(PagedPool, deviceObjName.MaximumLength
                                     + sizeof(WCHAR));


   if (deviceObjName.Buffer == NULL) {
      SerialLogError(DriverObject, NULL, SerialPhysicalZero, SerialPhysicalZero,
                     0, 0, 0, 19, STATUS_SUCCESS, SERIAL_INSUFFICIENT_RESOURCES,
                     0, NULL, 0, NULL);
      SerialDbgPrintEx(SERERRORS,
                       "Couldn't allocate memory for device name\n");

      return STATUS_INSUFFICIENT_RESOURCES;

   }

   RtlZeroMemory(deviceObjName.Buffer, deviceObjName.MaximumLength
                 + sizeof(WCHAR));


   RtlAppendUnicodeToString(&deviceObjName, L"\\Device\\Serial");

   RtlInitUnicodeString(&instanceStr, NULL);

   instanceStr.MaximumLength = sizeof(instanceNumberBuffer);
   instanceStr.Buffer = instanceNumberBuffer;

   RtlIntegerToUnicodeString(currentInstance++, 10, &instanceStr);

   RtlAppendUnicodeStringToString(&deviceObjName, &instanceStr);


   //
   // Create the device object
   //

   status = IoCreateDevice(DriverObject, sizeof(SERIAL_DEVICE_EXTENSION),
                           &deviceObjName, FILE_DEVICE_SERIAL_PORT,
                           FILE_DEVICE_SECURE_OPEN, TRUE, &deviceObject);


   if (!NT_SUCCESS(status)) {
      SerialDbgPrintEx(SERERRORS, "SerialAddDevice: Create device failed - %x "
                       "\n", status);
      goto SerialCreateDevObjError;
   }

   ASSERT(deviceObject != NULL);


   //
   // The device object has a pointer to an area of non-paged
   // pool allocated for this device.  This will be the device
   // extension. Zero it out.
   //

   pDevExt = deviceObject->DeviceExtension;
   RtlZeroMemory(pDevExt, sizeof(SERIAL_DEVICE_EXTENSION));

   //
   // Initialize the count of IRP's pending
   //

   pDevExt->PendingIRPCnt = 1;


   //
   // Initialize the count of DPC's pending
   //

   pDevExt->DpcCount = 1;

   //
   // Allocate Pool and save the nt device name in the device extension.
   //

   pDevExt->DeviceName.Buffer =
      ExAllocatePool(PagedPool, deviceObjName.Length + sizeof(WCHAR));

   if (!pDevExt->DeviceName.Buffer) {

      SerialLogError(
                    DriverObject,
                    NULL,
                    SerialPhysicalZero,
                    SerialPhysicalZero,
                    0,
                    0,
                    0,
                    19,
                    STATUS_SUCCESS,
                    SERIAL_INSUFFICIENT_RESOURCES,
                    0,
                    NULL,
                    0,
                    NULL
                    );
      SerialDbgPrintEx(SERERRORS, "Couldn't allocate memory for DeviceName\n");

      status = STATUS_INSUFFICIENT_RESOURCES;
      goto SerialCreateDevObjError;
   }

   pDevExt->DeviceName.MaximumLength = deviceObjName.Length
      + sizeof(WCHAR);

   //
   // Zero fill it.
   //

   RtlZeroMemory(pDevExt->DeviceName.Buffer,
                 pDevExt->DeviceName.MaximumLength);

   RtlAppendUnicodeStringToString(&pDevExt->DeviceName, &deviceObjName);

   pDevExt->NtNameForPort.Buffer = ExAllocatePool(PagedPool,
                                                  deviceObjName.MaximumLength);

   if (pDevExt->NtNameForPort.Buffer == NULL) {
      SerialDbgPrintEx(SERERRORS, "SerialAddDevice: Cannot allocate memory for "
                       "NtName\n");
      status = STATUS_INSUFFICIENT_RESOURCES;
      goto SerialCreateDevObjError;
   }

   pDevExt->NtNameForPort.MaximumLength = deviceObjName.MaximumLength;
   RtlAppendUnicodeStringToString(&pDevExt->NtNameForPort,
                                  &deviceObjName);



   //
   // Set up the device extension.
   //

   pDevExt->DeviceIsOpened = FALSE;
   pDevExt->DeviceObject   = deviceObject;
   pDevExt->DriverObject   = DriverObject;
   pDevExt->DeviceObject   = deviceObject;
   pDevExt->PowerState     = PowerDeviceD0;

   pDevExt->TxFifoAmount           = driverDefaults.TxFIFODefault;
   pDevExt->CreatedSymbolicLink    = TRUE;
   pDevExt->OwnsPowerPolicy = TRUE;

   InitializeListHead(&pDevExt->CommonInterruptObject);
   InitializeListHead(&pDevExt->TopLevelSharers);
   InitializeListHead(&pDevExt->MultiportSiblings);
   InitializeListHead(&pDevExt->AllDevObjs);
   InitializeListHead(&pDevExt->ReadQueue);
   InitializeListHead(&pDevExt->WriteQueue);
   InitializeListHead(&pDevExt->MaskQueue);
   InitializeListHead(&pDevExt->PurgeQueue);
   InitializeListHead(&pDevExt->StalledIrpQueue);

   ExInitializeFastMutex(&pDevExt->OpenMutex);
   ExInitializeFastMutex(&pDevExt->CloseMutex);

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

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


   KeInitializeEvent(&pDevExt->PendingIRPEvent, SynchronizationEvent, FALSE);
   KeInitializeEvent(&pDevExt->PendingDpcEvent, SynchronizationEvent, FALSE);
   KeInitializeEvent(&pDevExt->PowerD0Event, SynchronizationEvent, FALSE);


   deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

   *NewDeviceObject = deviceObject;

   ExFreePool(deviceObjName.Buffer);

   SerialDbgPrintEx(SERTRACECALLS, "Leave SerialCreateDevObj\n");
   return STATUS_SUCCESS;


   SerialCreateDevObjError:

   SerialDbgPrintEx(SERERRORS, "SerialCreateDevObj Error, Cleaning up\n");

   //
   // Free the allocated strings for the NT and symbolic names if they exist.
   //

   if (deviceObjName.Buffer != NULL) {
      ExFreePool(deviceObjName.Buffer);
   }

   if (deviceObject) {

      if (pDevExt->NtNameForPort.Buffer != NULL) {
         ExFreePool(pDevExt->NtNameForPort.Buffer);
      }

      if (pDevExt->DeviceName.Buffer != NULL) {
         ExFreePool(pDevExt->DeviceName.Buffer);
      }

      IoDeleteDevice(deviceObject);
   }

   *NewDeviceObject = NULL;

   SerialDbgPrintEx(SERTRACECALLS, "Leave SerialCreateDevObj\n");
   return status;
}


NTSTATUS
SerialAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PPdo)

/*++

Routine Description:

    This routine creates a functional device object for com ports in the
    system and attaches them to the physical device objects for the ports


Arguments:

    DriverObject - a pointer to the object for this driver

    PPdo - a pointer to the PDO in the stack we need to attach to

Return Value:

    status from device creation and initialization

--*/

{
   PDEVICE_OBJECT pNewDevObj = NULL;
   PDEVICE_OBJECT pLowerDevObj = NULL;
   NTSTATUS status;
   PSERIAL_DEVICE_EXTENSION pDevExt;

   PAGED_CODE();

   SerialDbgPrintEx(SERTRACECALLS, "Enter SerialAddDevice with PPdo 0x%x\n",
                    PPdo);

   if (PPdo == NULL) {
      //
      // Return no more devices
      //

      SerialDbgPrintEx(SERERRORS, "SerialAddDevice: Enumeration request, "
                       "returning NO_MORE_ENTRIES\n");

      return (STATUS_NO_MORE_ENTRIES);
   }



   //
   // create and initialize the new device object
   //

   status = SerialCreateDevObj(DriverObject, &pNewDevObj);

   if (!NT_SUCCESS(status)) {

      SerialDbgPrintEx(SERERRORS,
                       "SerialAddDevice - error creating new devobj [%#08lx]\n",
                       status);
      return status;
   }


   //
   // Layer our DO on top of the lower device object
   // The return value is a pointer to the device object to which the
   // DO is actually attached.
   //

   pLowerDevObj = IoAttachDeviceToDeviceStack(pNewDevObj, PPdo);


   //
   // No status. Do the best we can.
   //
   ASSERT(pLowerDevObj != NULL);


   pDevExt = pNewDevObj->DeviceExtension;
   pDevExt->LowerDeviceObject = pLowerDevObj;
   pDevExt->Pdo = PPdo;



   //
   // Specify that this driver only supports buffered IO.  This basically
   // means that the IO system copies the users data to and from
   // system supplied buffers.
   //
   // Also specify that we are power pagable.
   //

   pNewDevObj->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;

   SerialDbgPrintEx(SERTRACECALLS, "Leave SerialAddDevice\n");

   return status;
}


NTSTATUS
SerialPnpDispatch(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)

/*++

Routine Description:

    This is a dispatch routine for the IRPs that come to the driver with the

⌨️ 快捷键说明

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