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

📄 comeml.c

📁 The Lite Evaluation/Demonstration Kit is intended to illustrate use of the AN3042. The AN3042 is c
💻 C
📖 第 1 页 / 共 4 页
字号:
   if (completeTheIrp)
   {
      IoCompleteRequest(Irp,
                      IO_NO_INCREMENT);
   }

   return ntStatus;
}

//////////////////////////////////////////////////////////////////////////
// 
// Routine Description:
//
//    Allocates non-paged pool memory for use by the comem device.  Actual Input
//    and Output comes from the IRP system buffer, and are AllocMemoryIn and 
//    AllocMemoryOut structures (see comemdrv.h).
//    This routine keeps track of memory allocations by storing allocation 
//    information in the device extension.  If memory has alrady been allocated
//    for the comem device, this routine will return an error.
//    If the entire allocation request can not be satisfied, then no allocation is
//    performed (actually, the part of the allocaion that succeeds is undone).
//    Callers to this funcion should also call CoMemUpdatePagetable().
// 
// 
// Arguments:
// 
//     DeviceObject - pointer to a device object
// 
//     Irp          - pointer to an I/O Request Packet
// 
// Return Value:
// 
//    returns status in two places: the return value, and in the output structure's
//    status field.  The return value is just an NTSTATUS value that most closey resembles
//    the status.  The output structure's status field is a comem status value as defined in
//    comemdrv.h.
// 
//////////////////////////////////////////////////////////////////////////
NTSTATUS
CoMemAllocContigMemory(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
   AllocContigMemIn allocRequest;
   AllocContigMemOut *allocMemoryOut = (AllocContigMemOut *) Irp->AssociatedIrp.SystemBuffer;
   int i;
   ULONG errors = FALSE;
   PVOID ptr = NULL;
   PDEVICE_EXTENSION   deviceExtension = NULL;
   NTSTATUS ntStatus = STATUS_SUCCESS;
   PHYSICAL_ADDRESS     maxAddress;
   PHYSICAL_ADDRESS     physicalAddress;
   deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
     
   //
   // make a copy of the input structure.  The input and output
   // structures share the same memory and we don't want to 
   // trash the input params before we're done with them
   //
   RtlCopyBytes(&allocRequest,
              (AllocContigMemIn *) Irp->AssociatedIrp.SystemBuffer,
              sizeof(AllocContigMemIn));


   allocMemoryOut->status = NO_ERROR;

   //
   // Check the device extension to see if memory has already
   // been allocated for this Comem device.  If so, return an
   // error
   //
   if (deviceExtension->systemAddr)
   {
      allocMemoryOut->status = ERROR_ALLOC_EXISTS;
      return STATUS_UNSUCCESSFUL;
   }

   //
   // allocate a block of RAM
   //
   maxAddress.LowPart=0xFFFFFFFF;
   maxAddress.HighPart=0x0;

   deviceExtension->bufferSize = allocRequest.size * PAGE_SIZE;
   deviceExtension->systemAddr = MmAllocateContiguousMemory(deviceExtension->bufferSize,
                                     maxAddress);

   if (!deviceExtension->systemAddr)
   {
      CoMemKdPrint (("COMEM.SYS: ExAllocatePool failed\n"));
      deviceExtension->bufferSize = 0;
      allocMemoryOut->status = ERROR_MEMORY_ALLOC;
      ntStatus = STATUS_NO_MEMORY;
      errors = TRUE;
      goto CLEANUP;
   }

   //
   // now get a physical address and a user mode pointer for the buffer
   //

   physicalAddress = MmGetPhysicalAddress(deviceExtension->systemAddr);
   allocMemoryOut->physAddr =
   deviceExtension->physAddr = physicalAddress.LowPart;

   deviceExtension->linearAddr = CoMemGetLinearPointer(deviceExtension->systemAddr,
                                                       allocRequest.size * PAGE_SIZE);
   allocMemoryOut->linearAddr = (DWORD) deviceExtension->linearAddr;
 
CLEANUP:
   if (errors)
   {
      CoMemDeAllocContigMemory(DeviceObject);
   }

   return ntStatus;
}    

//////////////////////////////////////////////////////////////////////////
// 
// Routine Description:
// 
//    Deallocates all memory that has been allocated for the comem device.
//    Note: It is possible that one or more user mode apps have pointers to
//    the comem memory.  It is also posible that the comem device is still
//    running and may be using the allocated memory regions.  This routine
//    does not safeguard against these conditions.  Callers shoud also call
//    CoMemUpdatePagetable() after deallocating memory so the comem pagetable
//    reflects the true memory situation.
//    This routine may be called redundantly (ie. even if no memory is allocate).
// 
// Arguments:
// 
//     DeviceObject - pointer to a device object
// 
// Return Value:
// 
// 
//////////////////////////////////////////////////////////////////////////
void
CoMemDeAllocContigMemory(
    IN PDEVICE_OBJECT DeviceObject
    )
{
   PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
   PMDL pMdl = NULL;

   //
   // unmap the buffer from user mode
   //
   if (deviceExtension->linearAddr)
   {
      pMdl = IoAllocateMdl(deviceExtension->systemAddr,
                           deviceExtension->bufferSize,
                           FALSE,
                           FALSE,
                           NULL);

      MmBuildMdlForNonPagedPool(pMdl);

      MmUnmapLockedPages(deviceExtension->linearAddr, pMdl);

      deviceExtension->linearAddr = NULL;

      IoFreeMdl(pMdl);
   }
  

   //
   // free the buffer
   //
   if (deviceExtension->systemAddr)
   {
      MmFreeContiguousMemory(deviceExtension->systemAddr);

      deviceExtension->systemAddr = NULL;
      deviceExtension->physAddr = 0,0;
      deviceExtension->bufferSize = 0;
   }

}    


//////////////////////////////////////////////////////////////////////////
// 
// Routine Description:
//
//    Returns a user mode pointer to the specified System buffer
// 
//    Warning:  All system to user mode mappings must be undone before
//    the application that initiated the mapping goes away.  Otherwise,
//    the system will bugcheck

// Arguments:
//    IN PVOID SystemAddress - kernel mode address of the memory buffer to be
//                             mapped to user mode
//    IN ULONG Length        - length of the buffer pointed to by SystemAddress
// 
// 
// Return Value:
//    user mode pointer (in the address context of the calling app) to the
//    specified system buffer
// 
//////////////////////////////////////////////////////////////////////////
PVOID
CoMemGetLinearPointer(
   IN PVOID SystemAddress,
   IN ULONG Length
   )
{
   PMDL pMdl = NULL;
   PVOID LinearAddress = NULL;

   pMdl = IoAllocateMdl(SystemAddress,
                        Length,
                        FALSE,
                        FALSE,
                        NULL);
   
   if (!pMdl)
   {
      return NULL;
   }

   MmBuildMdlForNonPagedPool(pMdl);

   //
   // Using the MDL, generate a User mode virtual address for
   // the allocated buffer.
   //
   LinearAddress = MmMapLockedPages(pMdl, UserMode);

   IoFreeMdl(pMdl);

   return LinearAddress;
   
}   



//////////////////////////////////////////////////////////////////////////
// 
// Routine Description:
// 
// Arguments:
// 
//     DeviceObject - pointer to a device object
//
//     Irp          - pointer to an I/O Request Packet
// 
// Return Value:
// 
// 
//////////////////////////////////////////////////////////////////////////
NTSTATUS
CoMemMapBars(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{

   int i;
   NTSTATUS ntStatus = STATUS_SUCCESS;
   PDEVICE_EXTENSION deviceExtension;
   CreateBarPtrOut * Output;
   ULONG barLength[] = {32768,1024,32768,8};

   deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

   Output = (CreateBarPtrOut *) Irp->AssociatedIrp.SystemBuffer;
   Output->status = NO_ERROR;

   //
   // Check if the caller has already gotten a pointer to the BAR.  If it has
   // fail this call
   //
   if (deviceExtension->linearBaseAddr[0])
      return STATUS_UNSUCCESSFUL;

   //
   // initialize the bar map info and the output structure
   //
   for (i = 0; i < COMEM_MAX_BARS; i++)
   {
      deviceExtension->linearBaseAddr[i] = 0;
      Output->linBAR[i] = 0;
   }

   // MDMBUG - skip the last BAR, it's in IO space
   for (i = 0; i < COMEM_MAX_BARS - 1; i++)
   {
      GetLinearBarPointer(deviceExtension->baseAddresses[i],
                       barLength[i],
                       &(deviceExtension->linearBaseAddr[i]));
      
      Output->linBAR[i] = (ULONG) deviceExtension->linearBaseAddr[i];
   }

   return ntStatus;
}    

//////////////////////////////////////////////////////////////////////////
// 
// Routine Description:
// 
// 
// Arguments:
// 
// Return Value:
// 
// 
//////////////////////////////////////////////////////////////////////////
void
CoMemUnmapBars(
    IN PDEVICE_OBJECT DeviceObject
    )
{
   int i;
   PDEVICE_EXTENSION deviceExtension = NULL;

   deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

   //
   // Unmap each BAR pointer 
   //

   for (i = 0; i < COMEM_MAX_BARS; i++)
   {
      if (deviceExtension->linearBaseAddr[i])
      {
         ZwUnmapViewOfSection ((HANDLE) -1,
                               deviceExtension->linearBaseAddr[i]);

         deviceExtension->linearBaseAddr[i] = NULL;
         
      }
   }



}    

//////////////////////////////////////////////////////////////////////////
// 
// Routine Description:
//
//    This is a direct cut and past from the NT DDK example program called
//    mapmem.  See ddk\src\general\mapmem\sys for more details.
// 
// Arguments:
// 
// Return Value:
// 
// 
//////////////////////////////////////////////////////////////////////////
NTSTATUS
GetLinearBarPointer(
   IN ULONG PhysicalBarAddress,
   IN ULONG Length,
   IN OUT PVOID *LinearBarAddress
   )
{

   INTERFACE_TYPE     interfaceType;
   ULONG              busNumber;
   PHYSICAL_ADDRESS   physicalAddress;
   ULONG              length;
   UNICODE_STRING     physicalMemoryUnicodeString;
   OBJECT_ATTRIBUTES  objectAttributes;
   HANDLE             physicalMemoryHandle  = NULL;
   PVOID              PhysicalMemorySection = NULL;
   ULONG              inIoSpace, inIoSpace2;
   NTSTATUS           ntStatus;
   PHYSICAL_ADDRESS   physicalAddressBase;
   PHYSICAL_ADDRESS   physicalAddressEnd;
   PHYSICAL_ADDRESS   viewBase;
   PHYSICAL_ADDRESS   mappedLength;
   BOOLEAN            translateBaseAddress;
   BOOLEAN            translateEndAddress;
   PVOID              virtualAddress;

   interfaceType          = PCIBus;
   busNumber              = 0;    // MDMBUG - hardcoded for now.  This is the
                                  // bus number where comem shows up on my 
                                  // Sony.  Don't know about other systems.

   physicalAddress.HighPart = 0;
   physicalAddress.LowPart  = PhysicalBarAddress & 0xFFFFFFFE;
   inIoSpace = inIoSpace2 = PhysicalBarAddress & 1;
   length                 = Length;

   //

⌨️ 快捷键说明

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