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

📄 intrface.c

📁 agp windows驱动WDM,WINDDK开发
💻 C
📖 第 1 页 / 共 3 页
字号:
   NewMdl = AgpCombineMdlList(MdlList);

   if (!NewMdl && MdlList) {
      AGPLOG(AGP_WARNING, ("AGPLIB: Could not combine MDL List!\n"));

      // This is bad. The mdl list could not be combined probably 
      // because a large enough mdl could not be allocated for 
      // the combination.

      // This is not the end of the world however, since the mdl list
      // is not modified until its combination has succeeded so we 
      // still have a valid list. But we need it in one Mdl, so 
      // we just fall back to the simplest allocation strategy
      // we have available:

      // 1. Destroy the list and all of its allocations.
      
      while(MdlList)
      {
         MmFreePagesFromMdl(MdlList);
         NewMdl = MdlList->Next;
         ExFreePool(MdlList);
         MdlList = NewMdl;
      }

      // 2. Allocate a single Mdl with our pages without regard
      // for favored memory ranges. 

      NewMdl = MmAllocatePagesForMdl(ZeroAddress, 
                                     MaxAddress,
                                     ZeroAddress,
                                     TotalBytes);

   }

   return NewMdl;

   
}

PMDL
AgpCombineMdlList(IN PMDL MdlList)
/*++

Routine Description:

    Combines a list of MDLs that describe some set of physical memory
    pages into a single MDL that describes the same set of pages.
    
    The MDLs in the list should be of the type produced by
    MmAllocatePagesForMdl (i.e. MDLs that are useful for nothing more
    than as an array of PFNs)

    This function is used by AgpLibAllocatePhysicalMemory in order
    to combine its multiple range-based allocations into 1 MDL.
    
Arguments:

    MdlList - A list of MDLs to be combines

Return Value:

    A single MDL that describes the same set of physical pages as
    the MDLs in MdlList or NULL if this function is unsuccessful.
    
    NOTE: This function will deallocate the Mdls in MdlList if it
    is successful. If it is unsuccessful, however, it will leave
    the MdlList intact.

--*/
{
   PMDL NewMdl = NULL, Mdl, MdlTemp;
   ULONG Pages = 0;
   PPFN_NUMBER NewPageArray, PageArray;

   ULONG i; // for debugging only

   PAGED_CODE();

   if ((MdlList == NULL) || (MdlList->Next == NULL)) {

      // List of 0 or 1 elements, no need for this 
      // function to do anything.

      return MdlList;
   }

   // Calculate the number of pages spanned by this MdlList.

   for(Mdl = MdlList; Mdl; Mdl = Mdl->Next)
      Pages += BYTES_TO_PAGES(Mdl->ByteCount);

   // Allocate a new Mdl of the proper size.

   NewMdl = MmCreateMdl(NULL, NULL, Pages << PAGE_SHIFT);

   if (!NewMdl) {

      // Chances are that the system will bugcheck before
      // this actually happens ... but whatever.

      return NULL;
   }

   // Run through the mdl list, combining the mdls found
   // into a new mdl.

   //
   // First, get a pointer to the PFN array of the new Mdl
   //

   NewPageArray = MmGetMdlPfnArray(NewMdl);

   for(Mdl = MdlList; Mdl; Mdl = Mdl->Next)
   {
      // Get a pointer to the physical page number array in this Mdl.

      PageArray = MmGetMdlPfnArray(Mdl);
      Pages = Mdl->ByteCount >> PAGE_SHIFT;

      // Copy this array into a proper slot in the array area of the new Mdl.

      RtlCopyMemory((PVOID)NewPageArray, 
                    (PVOID)PageArray,
                    sizeof(PFN_NUMBER) * Pages);

      // Adjust new array slot pointer appropriately for the next copy

      NewPageArray += Pages;
         
   }

   // The list has been combined, now we need to destroy the Mdls
   // in the list.

   Mdl = MdlList;
   while(Mdl)
   {
      MdlTemp = Mdl->Next;
      ExFreePool(Mdl);
      Mdl = MdlTemp;
   }

   // All done. Return the new combined Mdl.

   return NewMdl;
}


PVOID
AgpLibAllocateMappedPhysicalMemory(IN PVOID AgpContext, IN ULONG TotalBytes)
/*++

Routine Description:

    Same as AgpLibAllocatePhysicalMemory, except this function will
    also map the allocated memory to a virtual address.

Arguments:

    Same as AgpLibAllocatePhysicalMemory.

Return Value:

    A virtual address of the allocated memory or NULL if unsuccessful.

--*/
{
   PMDL Mdl;
   PVOID Ret;

   PAGED_CODE();
   
   AGPLOG(AGP_NOISE, 
          ("AGPLIB: Attempting to allocate mapped memory = %u.\n", TotalBytes));

   //
   // Call the real memory allocator.
   //
   
   Mdl = AgpLibAllocatePhysicalMemory(AgpContext, TotalBytes);

   // Two possible failures 

   // 1. MDL is NULL. No memory could be allocated.

   if (Mdl == NULL) {

      AGPLOG(AGP_WARNING, ("AGPMAP: Could not allocate anything.\n"));

      return NULL;
   }

   // 2. MDL has some pages allocated but not enough.

   if (Mdl->ByteCount < TotalBytes) {

      AGPLOG(AGP_WARNING, ("AGPMAP: Could not allocate enough.\n"));

      MmFreePagesFromMdl(Mdl);
      ExFreePool(Mdl);
      return NULL;
   }

   // Ok. Our allocation succeeded. Map it to a virtual address.
   
   // Step 1: Map the locked Pages. (will return NULL if failed)

   Mdl->MdlFlags |= MDL_PAGES_LOCKED;
   Ret = MmMapLockedPagesSpecifyCache (Mdl,
                                         KernelMode,
                                         MmNonCached,
                                         NULL,
                                         FALSE,
                                         HighPagePriority);

   // Don't need the Mdl anymore, whether we succeeded or failed. 

   ExFreePool(Mdl);

   if (Ret == NULL) {
      AGPLOG(AGP_WARNING, ("AGPMAP: Could not map.\n"));
   } 

   return Ret;
}

#if defined (_X86_)
#define FLUSH_DCACHE(Mdl) __asm{ wbinvd }
#else
#define FLUSH_DCACHE(Mdl)   \
            AGPLOG(AGP_CRITICAL,    \
                   ("AgpLibFlushDcacheMdl - NEED TO IMPLEMENT DCACHE FLUSH FOR THIS ARCHITECTURE!!\n"))
#endif


VOID
AgpLibFlushDcacheMdl(
    PMDL Mdl
    )
/*++

Routine Description:

    Flushes the specified MDL from the D-caches of all processors
    in the system.

    Current algorithm is to set the current thread's affinity to each 
    processor in turn and flush the dcache. This could be made a lot
    more efficient if this turns out to be a hot codepath
    
Arguments:

    Mdl - Supplies the MDL to be flushed.

Return Value:

    None.

--*/

{
    NTSTATUS Status;
    KAFFINITY Processors;
    UCHAR Number;
    KEVENT Event;
    KDPC Dpc;

    PAGED_CODE();
    Processors = KeQueryActiveProcessors();
    //
    // Quick out for the UP case.
    //
    if (Processors == 1) {
        FLUSH_DCACHE(Mdl);
        return;
    }

    //
    // We will invoke a DPC on each processor. That DPC will flush the cache,
    // set the event and return. 
    //
    KeInitializeEvent(&Event, NotificationEvent, FALSE);

    Number = 0;
    while (Processors) {
        if (Processors & 1) {
            //
            // Initialize the DPC and set it to run on the specified
            // processor.
            //
            KeInitializeDpc(&Dpc,ApFlushDcache, &Event);
            KeSetTargetProcessorDpc(&Dpc, Number);

            //
            // Queue the DPC and wait for it to finish its work.
            //
            KeClearEvent(&Event);
            KeInsertQueueDpc(&Dpc, Mdl, NULL);
            KeWaitForSingleObject(&Event, 
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
        }
        Processors = Processors >> 1;
        ++Number;
    }
}



VOID
ApFlushDcache(
    IN PKDPC Dpc,
    IN PKEVENT Event,
    IN PMDL Mdl,
    IN PVOID SystemArgument2
    )
/*++

Routine Description:

    DPC which executes on each processor in turn to flush the
    specified MDL out of the dcache on each.

Arguments:

    Dpc - supplies the DPC object

    Event - Supplies the event to signal when the DPC is complete

    Mdl - Supplies the MDL to be flushed from the dcache

Return Value:

    None

--*/

{
    FLUSH_DCACHE(Mdl);
    KeSetEvent(Event, 0, FALSE);
}


NTSTATUS
AgpInterfaceSetRate(
    IN PMASTER_EXTENSION Extension,
    IN ULONG AgpRate
    )
/*++

Routine Description:

    This routine sets the AGP rate

Arguments:

    Extension - Supplies the device extension

    AgpRate - Rate to set

Return Value:

    STATUS_SUCCESS, or error status

--*/
{
    ULONGLONG DeviceFlags = 0;

    PAGED_CODE();

    switch (AgpRate) {
        case PCI_AGP_RATE_1X:
            DeviceFlags = AGP_FLAG_SET_RATE_1X;
            break;
        case PCI_AGP_RATE_2X:
            DeviceFlags = AGP_FLAG_SET_RATE_2X;
            break;
        case PCI_AGP_RATE_4X:
            DeviceFlags = AGP_FLAG_SET_RATE_4X;
            break;
        case 8:
            DeviceFlags = AGP_FLAG_SET_RATE_8X;
            break;
    }

    if (DeviceFlags != 0) {
        return AgpSpecialTarget(GET_AGP_CONTEXT_FROM_MASTER(Extension),
                                DeviceFlags);
    }

    return STATUS_INVALID_PARAMETER;
}

⌨️ 快捷键说明

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