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

📄 legacy.c

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

Copyright (c) 1991, 1992, 1993 Microsoft Corporation

Module Name:

    Legacy.c

Abstract:

    This module contains the code that does the legacy configuration and
    initialization of the comm ports.  As the driver gets more PnP
    functionality and the PnP manager appears, most of this module should
    go away.

Environment:

    Kernel mode

--*/

#include "precomp.h"

#if !defined(NO_LEGACY_DRIVERS)

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,SerialEnumerateLegacy)
#pragma alloc_text(INIT,SerialMigrateLegacyRegistry)
#pragma alloc_text(INIT,SerialBuildResourceList)
#pragma alloc_text(INIT,SerialTranslateResourceList)
#pragma alloc_text(INIT,SerialBuildRequirementsList)
#pragma alloc_text(INIT,SerialIsUserDataValid)
#endif // ALLOC_PRAGMA

static const PHYSICAL_ADDRESS SerialPhysicalZero = {0};



NTSTATUS
SerialTranslateResourceList(IN PDRIVER_OBJECT DriverObject,
                            IN PKEY_BASIC_INFORMATION UserSubKey,
                            OUT PCM_RESOURCE_LIST PTrResourceList,
                            IN PCM_RESOURCE_LIST PResourceList,
                            IN ULONG PartialCount,
                            IN PSERIAL_USER_DATA PUserData)
/*++

Routine Description:

    This routine will create a resource list of translated resources
    based on PResourceList.


    This is pageable INIT because it is only called from SerialEnumerateLegacy
    which is also pageable INIT.


Arguments:
    DriverObject - Only used for logging.

    UserSubKey - Only used for logging.

    PPResourceList - Pointer to a PCM_RESOURCE_LIST that we are creating.

    PResourceList - PCM_RESOURCE_LIST that we are translating.

    ParitalCount - Number of Partial Resource lists in PResourceList.

    PUserData - Data retrieved as defaults or from the registry.


Return Value:

    STATUS_SUCCESS on success, apropriate error value otherwise.

--*/
{
   KIRQL outIrql;
   KAFFINITY outAffinity = (KAFFINITY)-1;
   ULONG outAddrSpace;
   PHYSICAL_ADDRESS outPhysAddr;
   NTSTATUS status = STATUS_SUCCESS;

   PAGED_CODE();

   SerialDbgPrintEx(SERTRACECALLS, "Enter SerialTranslateResourceList\n");

   outIrql = (KIRQL)(PUserData->UserLevel ? PUserData->UserLevel
      : PUserData->UserVector);

   //
   // Copy the list over to the translated buffer and fixup and translate
   // what we need.
   //
   RtlCopyMemory(PTrResourceList, PResourceList, sizeof(CM_RESOURCE_LIST)
                 + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 2);

   outAddrSpace = PTrResourceList->List[0].PartialResourceList
                  .PartialDescriptors[0].Flags;
   outPhysAddr = PTrResourceList->List[0].PartialResourceList
                 .PartialDescriptors[0].u.Port.Start;


   if (HalTranslateBusAddress(PUserData->UserInterfaceType,
                              PUserData->UserBusNumber, PUserData->UserPort,
                              &outAddrSpace, &outPhysAddr)
       == 0) {
      SerialLogError(DriverObject, NULL, PUserData->UserPort,
                     SerialPhysicalZero, 0, 0, 0, 60, STATUS_SUCCESS,
                     SERIAL_NO_TRANSLATE_PORT, UserSubKey->NameLength
                     + sizeof(WCHAR), &UserSubKey->Name[0], 0, NULL);

      SerialDbgPrintEx(SERERRORS, "Port map failed attempt was \n"
                             "------- Interface:  %x\n"
                             "------- Bus Number: %x\n"
                             "------- userPort:  %x\n"
                             "------- AddrSpace:  %x\n"
                             "------- PhysAddr:   %x\n",
                             PUserData->UserInterfaceType,
                             PUserData->UserBusNumber,
                             PUserData->UserPort,
                             PTrResourceList->List[0].
                             PartialResourceList.PartialDescriptors[0]
                             .Flags,
                             PTrResourceList->List[0].
                             PartialResourceList.PartialDescriptors[0]
                             .u.Port.Start.QuadPart);

      status = STATUS_NONE_MAPPED;
      goto SerialTranslateError;
   }

   PTrResourceList->List[0].PartialResourceList.PartialDescriptors[0].Flags
      = (USHORT)outAddrSpace;
   PTrResourceList->List[0].PartialResourceList.PartialDescriptors[0]
      .u.Port.Start = outPhysAddr;

   if ((PTrResourceList->List[0].PartialResourceList
        .PartialDescriptors[1].u.Interrupt.Vector
        = HalGetInterruptVector(PUserData->UserInterfaceType,
                                PUserData->UserBusNumber, PUserData->UserLevel
                                ? PUserData->UserLevel
                                : PUserData->UserVector,
                                PUserData->UserVector, &outIrql,
                                &outAffinity)) == 0) {

      SerialLogError(DriverObject, NULL, PUserData->UserPort,
                     SerialPhysicalZero, 0, 0, 0, 61, STATUS_SUCCESS,
                     SERIAL_NO_GET_INTERRUPT, UserSubKey->NameLength
                     + sizeof(WCHAR), &UserSubKey->Name[0], 0, NULL);

      status = STATUS_NONE_MAPPED;
      goto SerialTranslateError;
   }

   PTrResourceList->List[0].PartialResourceList
      .PartialDescriptors[1].u.Interrupt.Level = outIrql;

   PTrResourceList->List[0].PartialResourceList
      .PartialDescriptors[1].u.Interrupt.Affinity = outAffinity;

   outAddrSpace = PTrResourceList->List[0].PartialResourceList
                  .PartialDescriptors[2].Flags;
   outPhysAddr = PTrResourceList->List[0].PartialResourceList
                 .PartialDescriptors[2].u.Port.Start;


   if (PartialCount == 3) {
      if (HalTranslateBusAddress(PUserData->UserInterfaceType,
                                 PUserData->UserBusNumber,
                                 PUserData->UserInterruptStatus,
                                 &outAddrSpace, &outPhysAddr) == 0) {

         SerialLogError(DriverObject, NULL, PUserData->UserPort,
                        SerialPhysicalZero, 0, 0, 0, 62, STATUS_SUCCESS,
                        SERIAL_NO_TRANSLATE_ISR, UserSubKey->NameLength
                        + sizeof(WCHAR), &UserSubKey->Name[0], 0, NULL);


         SerialDbgPrintEx(SERERRORS, "ISR map failed attempt was \n"
                                "------- Interface:  %x\n"
                                "------- Bus Number: %x\n"
                                "------- IntStatus:  %x\n"
                                "------- AddrSpace:  %x\n"
                                "------- PhysAddr:   %x\n",
                                PUserData->UserInterfaceType,
                                PUserData->UserBusNumber,
                                PUserData->UserInterruptStatus,
                                PTrResourceList->List[0].
                                PartialResourceList.PartialDescriptors[2]
                                .Flags,
                                PTrResourceList->List[0].
                                PartialResourceList.PartialDescriptors[2]
                                .u.Port.Start.QuadPart);

        status = STATUS_NONE_MAPPED;
        goto SerialTranslateError;
      }

      SerialDbgPrintEx(SERDIAG1, "ISR map was %x\n", outPhysAddr.QuadPart);

      PTrResourceList->List[0].PartialResourceList.
         PartialDescriptors[2].Flags = (USHORT)outAddrSpace;
      PTrResourceList->List[0].PartialResourceList.PartialDescriptors[2]
         .u.Port.Start = outPhysAddr;
   }

   SerialTranslateError:;

   SerialDbgPrintEx(SERTRACECALLS, "Enter SerialTranslateResourceList\n");

   return status;
}


NTSTATUS
SerialBuildRequirementsList(OUT PIO_RESOURCE_REQUIREMENTS_LIST PRequiredList,
                            IN ULONG PartialCount,
                            IN PSERIAL_USER_DATA PUserData)
/*++

Routine Description:

    This routine will build an IO_RESOURCE_REQUIREMENTS_LIST based on
    the defaults and user-supplied registry info.


    This is pageable INIT because it is only called from SerialEnumerateLegacy
    which is also pageable INIT.


Arguments:

    DriverObject - Used only for logging.

    PRequiredList - PIO_RESOURCE_REQUIREMENTS_LIST we are building.

    PartialCount - Number of partial descriptors needed in PPRequiredList.

    PUserData - Default and user-supplied values from the registry.


Return Value:

    STATUS_SUCCESS on success, apropriate error value otherwise.

--*/
{
   PIO_RESOURCE_LIST reqResList;
   PIO_RESOURCE_DESCRIPTOR reqResDesc;
   NTSTATUS status = STATUS_SUCCESS;

   PAGED_CODE();

   SerialDbgPrintEx(SERTRACECALLS, "Enter SerialBuildRequirementsList\n");


   // Build requirements list
   //

   RtlZeroMemory(PRequiredList, sizeof(IO_RESOURCE_REQUIREMENTS_LIST)
                 + sizeof(IO_RESOURCE_DESCRIPTOR) * 2);

   PRequiredList->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST)
      + sizeof(IO_RESOURCE_DESCRIPTOR) * (PartialCount - 1);
   PRequiredList->InterfaceType = PUserData->UserInterfaceType;
   PRequiredList->BusNumber = PUserData->UserBusNumber;
   PRequiredList->SlotNumber = 0;
   PRequiredList->AlternativeLists = 1;

   reqResList = &PRequiredList->List[0];

   reqResList->Version = 1;
   reqResList->Revision = 1;
   reqResList->Count = PartialCount;

   reqResDesc = &reqResList->Descriptors[0];


   //
   // Port Information
   //

   reqResDesc->Flags = (USHORT)PUserData->UserAddressSpace;
   reqResDesc->Type = CmResourceTypePort;
   reqResDesc->ShareDisposition = CmResourceShareDriverExclusive;
   reqResDesc->u.Port.Length = SERIAL_REGISTER_SPAN;
   reqResDesc->u.Port.Alignment= 1;
   reqResDesc->u.Port.MinimumAddress = PUserData->UserPort;
   reqResDesc->u.Port.MaximumAddress.QuadPart
      = PUserData->UserPort.QuadPart + SERIAL_REGISTER_SPAN - 1;


   reqResDesc++;


   //
   // Interrupt information
   //

   if (PUserData->UserInterruptMode == Latched) {
      reqResDesc->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
   } else {
      reqResDesc->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
   }

   //
   // We have to globally share resources even though this is a **BAD**
   // thing.  We must do it for multiport cards.  DO NOT replicate
   // this in other drivers.
   //

   reqResDesc->ShareDisposition = CmResourceShareDriverExclusive;

   reqResDesc->Type = CmResourceTypeInterrupt;
   reqResDesc->u.Interrupt.MinimumVector = PUserData->UserVector;
   reqResDesc->u.Interrupt.MaximumVector = PUserData->UserVector;

   //
   // ISR register information (if needed)
   //
   if (PartialCount == 3) {

      reqResDesc++;

      reqResDesc->Type = CmResourceTypePort;

      //
      // We have to globally share resources even though this is a **BAD**
      // thing.  We must do it for multiport cards.  DO NOT replicate
      // this in other drivers.
      //

      reqResDesc->ShareDisposition = CmResourceShareDriverExclusive;

      reqResDesc->Flags = (USHORT)PUserData->UserAddressSpace;
      reqResDesc->u.Port.Length = 1;
      reqResDesc->u.Port.Alignment= 1;
      reqResDesc->u.Port.MinimumAddress = PUserData->UserInterruptStatus;
      reqResDesc->u.Port.MaximumAddress = PUserData->UserInterruptStatus;
   }

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

   return status;
}



NTSTATUS
SerialBuildResourceList(OUT PCM_RESOURCE_LIST PResourceList,
                        OUT PULONG PPartialCount,
                        IN PSERIAL_USER_DATA PUserData)
/*++

Routine Description:

    This routine will build a resource list based on the information
    supplied by the registry.


    This is pageable INIT because it is only called from SerialEnumerateLegacy
    which is also pageable INIT.


Arguments:

    PResourceList - Pointer to PCM_RESOURCE_LIST we are building.

    PPartialCount - Number of Partial Resource Lists we required.

    PUserData - Pointer to user-supplied and default info from registry.


Return Value:

    STATUS_SUCCESS on success, apropriate error value otherwise.

--*/
{
   ULONG countOfPartials;
   PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartial;
   NTSTATUS status = STATUS_SUCCESS;

   PAGED_CODE();

   SerialDbgPrintEx(SERTRACECALLS, "Enter SerialBuildResourceList\n");
   SerialDbgPrintEx(SERDIAG1, "Building cmreslist in %x\n", PResourceList);

   *PPartialCount = 0;

   //
   // If we have a separate ISR register requirement, we then have 3
   // partials instead of 2.
   //
   countOfPartials = (PUserData->UserInterruptStatus.LowPart != 0) ? 3 : 2;


   RtlZeroMemory(PResourceList, sizeof(CM_RESOURCE_LIST)
                 + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 2);

   PResourceList->Count = 1;

   PResourceList->List[0].InterfaceType = PUserData->UserInterfaceType;
   PResourceList->List[0].BusNumber = PUserData->UserBusNumber;
   PResourceList->List[0].PartialResourceList.Count = countOfPartials;

   pPartial
      = &PResourceList->List[0].PartialResourceList.PartialDescriptors[0];


   //
   // Port information
   //

   pPartial->Type = CmResourceTypePort;
   pPartial->ShareDisposition = CmResourceShareDeviceExclusive;
   pPartial->Flags = (USHORT)PUserData->UserAddressSpace;
   pPartial->u.Port.Start = PUserData->UserPort;
   pPartial->u.Port.Length = SERIAL_REGISTER_SPAN;


⌨️ 快捷键说明

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